Pristine Ack-5.5
[Ack-5.5.git] / util / cmisc / cclash.c
1 /* $Id: cclash.c,v 0.7 1994/06/24 10:16:36 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /*
7         cclash: find clashing names within C programs
8
9         Flags:
10         -c              : produce oldname=newname line for each clashing id
11                           (useful input for cid)
12         -l<num>         : check identifiers of <num> or more characters
13                           (default <num> = 8)
14         -m              : output a #define for each clashing id
15
16         Author: Erik Baalbergen
17         Date: Nov 8, 1985
18
19         Revised: Dec 10, 1985
20                 C keywords are not listed
21         Revised: Aug 27, 1986
22                 Skip C numeric constants
23         Revised: Wed Jul 23 13:27:16 MDT 1986
24                 by Ceriel Jacobs,
25                 replaced "stoi" by "atoi"
26         Revised: Tue Nov 11 13:32:31 MET 1986
27                 by Ceriel Jacobs,
28                 to produce lists for "cid" or preprocessor in
29                 alphabetical order.
30 */
31
32 #include <stdio.h>
33
34 #define DEF_LENGTH      8
35
36 struct idf {
37         struct idf *id_next;
38         char *id_name;
39         struct idf *id_same;
40         char id_key;
41 };
42
43 #define ACT_LISTONLY    0
44 #define ACT_MAPFILE     1
45 #define ACT_CID         2
46
47 int maxlen = DEF_LENGTH;
48 int action = ACT_LISTONLY;
49
50 extern char *ProgName;
51
52 char * keywords[] = {
53         "asm",
54         "auto",
55         "break",
56         "case",
57         "char",
58         "continue",
59         "default",
60         "do",
61         "double",
62         "else",
63         "entry",
64         "extern",
65         "float",
66         "for",
67         "fortran",
68         "goto",
69         "if",
70         "int",
71         "long",
72         "register",
73         "return",
74         "short",
75         "sizeof",
76         "static",
77         "struct",
78         "switch",
79         "typedef",
80         "union",
81         "unsigned",
82         "while",
83         0
84 };
85
86 struct idf *maplist = 0;
87
88 DefineKeys()
89 {
90         register char **pkey = &keywords[0];
91         register char *id;
92
93         while (id = *pkey++)
94                 if (strlen(id) >= maxlen)
95                         InsertId(id, 1);
96 }
97
98 DoOption(str)
99         char *str;
100 {
101         switch (str[1]) {
102
103         case 'c':
104                 action = ACT_CID;
105                 break;
106
107         case 'l':
108                 if ((maxlen = atoi(&str[2])) <= 0) {
109                         fprintf(stderr, "%s: option \"-l%s\" ignored\n",
110                                 ProgName, &str[2]);
111                         maxlen = DEF_LENGTH;
112                 }
113                 break;
114         
115         case 'm':
116                 action = ACT_MAPFILE;
117                 break;
118
119         default:
120                 fprintf(stderr, "%s: bad option \"%s\"\n", ProgName, str);
121                 break;
122         }
123 }
124
125 #define HASHSIZE 257
126
127 struct idf *hash_tab[HASHSIZE];
128
129 char *Malloc(), *Salloc();
130
131 InsertId(id, key)
132         char *id;
133 {
134         int hash_val = EnHash(id);
135         register struct idf *idp = hash_tab[hash_val];
136         register struct idf *p = 0;
137
138         while (idp && strncmp(idp->id_name, id, maxlen)) {
139                 p = idp;
140                 idp = idp->id_next;
141         }
142
143         if (idp == 0) {
144                 idp = (struct idf *) Malloc(sizeof(struct idf));
145                 idp->id_next = 0;
146                 if (!p) hash_tab[hash_val] = idp;
147                 else p->id_next = idp;
148                 idp->id_name = Salloc(id);
149                 idp->id_same = 0;
150         }
151
152         p = idp;
153
154         while (p && strcmp(p->id_name, id)) {
155                 idp = p;
156                 p = p->id_same;
157         }
158
159         if (p == 0) {
160                 p = (struct idf *) Malloc(sizeof(struct idf));
161                 p->id_next = 0;
162                 p->id_same = 0;
163                 p->id_name = Salloc(id);
164                 idp->id_same = p;
165         }
166
167         p->id_key = key;
168 }
169
170 char *
171 Malloc(n)
172         unsigned n;
173 {
174         char *mem, *malloc();
175
176         if ((mem = malloc(n)) == 0) {
177                 fprintf(stderr, "%s: out of memory\n", ProgName);
178                 exit(1);
179         }
180         return mem;
181 }
182
183 char *
184 Salloc(str)
185         char *str;
186 {
187         char *strcpy();
188
189         if (str == 0)
190                 str = "";
191
192         return strcpy(Malloc((unsigned)strlen(str) + 1), str);
193 }
194
195 EnHash(id)
196         char *id;
197 {
198         register unsigned hash_val = 0;
199         register n = maxlen;
200
201         while (n-- && *id)
202                 hash_val = 31 * hash_val + *id++;
203
204         return hash_val % (unsigned) HASHSIZE;
205 }
206
207 BeginOfProgram() { DefineKeys(); }
208
209 EndOfProgram()
210 {
211         register int i;
212         register struct idf *idp, *p;
213
214         for (i = 0; i < HASHSIZE; i++) {
215                 for (idp = hash_tab[i]; idp; idp = idp->id_next) {
216                         if (idp->id_same == 0)
217                                 continue;
218
219                         switch (action) {
220                                 register n;
221
222                         case ACT_LISTONLY:
223                                 n = 0;
224                                 if (idp->id_key == 0) {
225                                         printf(idp->id_name);
226                                         n++;
227                                 }
228                                 for (p = idp->id_same; p; p = p->id_same)
229                                         if (p->id_key == 0) {
230                                                 printf("%s%s",
231                                                         n ? " " : "",
232                                                         p->id_name
233                                                 );
234                                                 n++;
235                                         }
236                                 if (n)
237                                         printf("\n");
238                                 break;
239                         
240                         case ACT_CID:
241                         case ACT_MAPFILE:
242                                 for (p = idp->id_same; p;) {
243                                         register struct idf *q = p->id_same;
244
245                                         if (p->id_key == 0)
246                                                 saveline(p);
247                                         p = q;
248                                 }
249                                 if (idp->id_key == 0)
250                                         saveline(idp);
251                                 break;
252                         }
253                 }
254         }
255         switch(action) {
256         case ACT_CID:
257         case ACT_MAPFILE:
258                 for (idp = maplist; idp; idp = idp->id_same) {
259                         mapline(idp->id_name);
260                 }
261         }
262 }
263
264 saveline(p)
265         register struct idf *p;
266 {
267         register struct idf *idp = maplist, *idp1 = 0;
268
269         while (idp && strcmp(idp->id_name, p->id_name) < 0) {
270                 idp1 = idp;
271                 idp = idp->id_same;
272         }
273         p->id_same = idp;
274         if (idp1 == 0) {
275                 maplist = p;
276         }
277         else {
278                 idp1->id_same = p;
279         }
280 }
281
282 mapline(nm)
283         char *nm;
284 {
285         static map_count = 0;
286
287         switch (action) {
288
289         case ACT_MAPFILE:
290                 printf("#define %s _%d_%s\n", nm, ++map_count, nm);
291                 break;
292         
293         case ACT_CID:
294                 printf("%s=_%d_%s\n", nm, ++map_count, nm);
295                 break;
296         }
297 }
298
299 CheckId(id, s)
300         char *id;
301 {
302         if (s >= maxlen)
303                 InsertId(id, 0);
304 }