0bf295996de00f1250505c47645ffe66c63aee5f
[43bsd.git] / xify / xifyfilt.c
1 #include <ctype.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 struct str {
8         int str_len;
9         char *str_data;
10 };
11
12 struct str keywords[1024] = {
13         {2, "X_"},
14         {5, "break"},
15         {4, "case"},
16         {4, "char"},
17         {8, "continue"},
18         {7, "default"},
19         {7, "defined"},
20         {2, "do"},
21         {6, "double"},
22         {4, "else"},
23         {4, "enum"},
24         {6, "extern"},
25         {5, "float"},
26         {2, "if"},
27         {3, "for"},
28         {4, "goto"},
29         {6, "return"},
30         {8, "register"},
31         {6, "sizeof"},
32         {6, "static"},
33         {6, "struct"},
34         {6, "switch"},
35         {7, "typedef"},
36         {5, "union"},
37         {4, "void"},
38         {5, "while"},
39         {8, "__FILE__"},
40         {8, "__GNUC__"},
41         {8, "__LINE__"},
42         {3, "__P"},
43         {8, "__STDC__"},
44         {13, "__attribute__"},
45         {12, "__noreturn__"}
46 };
47 int n_keywords = 33;
48
49 struct str typedefs[1024] = {
50         {4, "char"},
51         {6, "double"},
52         {4, "enum"},
53         {5, "float"},
54         {3, "int"},
55         {4, "long"},
56         {5, "short"},
57         {6, "struct"},
58         {5, "union"},
59         {8, "unsigned"},
60         {4, "void"}
61 };
62 int n_typedefs = 11;
63
64 char buf[1024];
65
66 int main(argc, argv) int argc; char **argv; {
67   char *p, *q, *r;
68   int l, m, n;
69   int e, i;
70
71   while (fgets(buf, sizeof(buf), stdin)) {
72     p = buf;
73     l = 0;
74     if (p[l] == '#') {
75       ++l;
76       while (isblank(p[l]))
77         ++l;
78       q = p + l;
79       m = 0;
80       if (isalpha(q[m]) || q[m] == '_') {
81         ++m;
82         while (isalnum(q[m]) || q[m] == '_')
83           ++m;
84         if (m == 7 && memcmp(q, "include", 7) == 0) {
85           l += m;
86           while (isblank(p[l]))
87             ++l;
88           if (p[l] == '<') {
89             e = '>';
90             goto include;
91           }
92           else if (p[l] == '"') {
93             e = '"';
94           include:
95             fwrite(p, ++l, 1, stdout);
96             p += l;
97             for (m = 0; p[m] && p[m] != e; ++m)
98               ;
99             for (l = m; l > 0 && p[l - 1] != '/'; --l)
100               ;
101             q = p + l;
102             m -= l;
103             if (m >= 4 && memcmp(q, "nox_", 4) == 0) {
104               fwrite(p, l, 1, stdout);
105               p = q + 4;
106               l = m - 4;
107             }
108             else if (
109               (l != 0 || m != 8 || memcmp(p, "setjmp.h", 8) != 0) &&
110               (l != 0 || m != 8 || memcmp(p, "stdarg.h", 8) != 0) &&
111               (l != 0 || m != 8 || memcmp(p, "stdint.h", 8) != 0) &&
112               (l != 0 || m != 9 || memcmp(p, "varargs.h", 9) != 0)
113             ) {
114 #if 1
115               fwrite(p, l, 1, stdout);
116 #else
117               fwrite(p - 1, l + m + 2, 1, stderr); /* include <> or "" */
118               fputc('\n', stderr);
119               if (l) {
120                 fwrite("../", 3, 1, stdout);
121                 fwrite(p, l, 1, stdout);
122                 fwrite(".xify/", 6, 1, stdout);
123               }
124 #endif
125               fwrite("x_", 2, 1, stdout);
126               p = q;
127               l = m;
128             }
129             else
130               l += m;
131             ++l;
132           }
133         }
134         else if (m == 6 && memcmp(q, "pragma", 6) == 0) {
135           while (isblank(q[m]))
136             ++m;
137           r = q + m;
138           n = 0;
139           if (isalpha(r[n]) || r[n] == '_') {
140             ++n;
141             while (isalnum(r[n]) || r[n] == '_')
142               ++n;
143             if (n == 7 && memcmp(r, "keyword", 7) == 0) {
144               while (isblank(r[n]))
145                 ++n;
146               p = r + n;
147               l = 0;
148               while (isalpha(p[l]) || p[l] == '_') {
149                 while (isalnum(p[l]) || p[l] == '_')
150                   ++l;
151 #if 0
152  fwrite("keyword: ", 9, 1, stderr);
153  fwrite(p, l, 1, stderr);
154  putc('\n', stderr);
155 #endif
156                 if ((q = malloc(l)) == 0)
157                   abort();
158                 memcpy(q, p, l);
159                 if (n_keywords >= sizeof(keywords) / sizeof(struct str))
160                   abort();
161                 keywords[n_keywords].str_len = l;
162                 keywords[n_keywords].str_data = q;
163                 ++n_keywords;
164                 while (isblank(p[l]))
165                   ++l;
166                 p += l;
167                 l = 0;
168               }
169               if (p[l] != '\n') {
170                 fprintf(stderr, "%s: warning: garbage after #pragma keyword: ", argv[0]);
171                 while (p[l] && p[l] != '\n')
172                   putc(p[l++], stderr);
173                 putc('\n', stderr);
174               }
175               continue;
176             }
177             else if (n == 7 && memcmp(r, "typedef", 7) == 0) {
178               while (isblank(r[n]))
179                 ++n;
180               p = r + n;
181               l = 0;
182               while (isalpha(p[l]) || p[l] == '_') {
183                 while (isalnum(p[l]) || p[l] == '_')
184                   ++l;
185 #if 0
186  fwrite("typedef: ", 9, 1, stderr);
187  fwrite(p, l, 1, stderr);
188  putc('\n', stderr);
189 #endif
190                 if ((q = malloc(l)) == 0)
191                   abort();
192                 memcpy(q, p, l);
193  /* typedefs notified through #pragma are also keywords */
194  /* this isn't the case for typedefs we notice ourselves */
195  if (n_keywords >= sizeof(keywords) / sizeof(struct str))
196   abort();
197  keywords[n_keywords].str_len = l;
198  keywords[n_keywords].str_data = q;
199  ++n_keywords;
200                 if (n_typedefs >= sizeof(typedefs) / sizeof(struct str))
201                   abort();
202                 typedefs[n_typedefs].str_len = l;
203                 typedefs[n_typedefs].str_data = q;
204                 ++n_typedefs;
205                 while (isblank(p[l]))
206                   ++l;
207                 p += l;
208                 l = 0;
209               }
210               if (p[l] != '\n') {
211                 fprintf(stderr, "%s: warning: garbage after #pragma typedef: ", argv[0]);
212                 while (p[l] && p[l] != '\n')
213                   putc(p[l++], stderr);
214                 putc('\n', stderr);
215               }
216               continue;
217             }
218           }
219           fwrite(p, l, 1, stdout);
220           fputs(p + l + m, stdout);
221           continue;
222         }
223         else
224           l += m;
225         fwrite(p, l, 1, stdout);
226         p += l;
227         l = 0;
228       }
229     }
230     while (p[l]) {
231       if (isalpha(p[l]) || p[l] == '_') {
232         ++l;
233         while (isalnum(p[l]) || p[l] == '_')
234           ++l;
235         if (
236           (l == 6 && memcmp(p, "extern", 6) == 0) ||
237           (l == 8 && memcmp(p, "register", 8) == 0) ||
238           (l == 6 && memcmp(p, "static", 6) == 0)
239         ) {
240           fwrite(p, l, 1, stdout);
241           p += l;
242           l = 0;
243           while (isblank(p[l]))
244             ++l;
245           q = p + l;
246           m = 0;
247           if (isalpha(q[m]) || q[m] == '_') {
248             ++m;
249             while (isalnum(q[m]) || q[m] == '_')
250               ++m;
251             for (i = 0; i < n_typedefs; ++i)
252               if (
253                 m == typedefs[i].str_len &&
254                 memcmp(q, typedefs[i].str_data, m) == 0
255               )
256                 goto found_typedef;
257             q += m;
258             m = 0;
259             while (isblank(q[m]))
260               ++m;
261             if (q[m] != '*') /* avoid something like: register FILE *fp; */
262               fwrite(" x_int", 6, 1, stdout);
263           found_typedef:
264             ;
265           }
266         else /* maybe something like: register *p; */
267           fwrite(" x_int", 6, 1, stdout);
268         }
269         else if (l == 3 && memcmp(p, "int", 3) == 0) {
270           fwrite("x_int", 5, 1, stdout);
271           p += l;
272           l = 0;
273         }
274         else if (
275           (l == 5 && memcmp(p, "short", 5) == 0) ||
276           (l == 4 && memcmp(p, "long", 4) == 0) 
277         ) {
278           fwrite("x_", 2, 1, stdout);
279           fwrite(p, l, 1, stdout);
280           p += l;
281           l = 0;
282           while (isblank(p[l]))
283             ++l;
284           q = p + l;
285           m = 0;
286           if (isalpha(q[m]) || q[m] == '_') {
287             ++m;
288             while (isalnum(q[m]) || q[m] == '_')
289               ++m;
290             if (m == 3 && memcmp(q, "int", 3) == 0) {
291               p += l + m;
292               l = 0;
293             }
294           }
295         }
296         else if (l == 8 && memcmp(p, "unsigned", 8) == 0) {
297           while (isblank(p[l]))
298             ++l;
299           q = p + l;
300           m = 0;
301           if (isalpha(q[m]) || q[m] == '_') {
302             ++m;
303             while (isalnum(q[m]) || q[m] == '_')
304               ++m;
305             if (m == 3 && memcmp(q, "int", 3) == 0) {
306               fwrite("x_unsigned_int", 14, 1, stdout);
307               p += l + m;
308               l = 0;
309             }
310             else if (
311               (m == 5 && memcmp(q, "short", 5) == 0) ||
312               (m == 4 && memcmp(q, "long", 4) == 0) 
313             ) {
314               fwrite("x_unsigned_", 11, 1, stdout);
315               fwrite(q, m, 1, stdout);
316               p += l + m;
317               l = 0;
318               while (isblank(p[l]))
319                 ++l;
320               q = p + l;
321               m = 0;
322               if (isalpha(q[m]) || q[m] == '_') {
323                 ++m;
324                 while (isalnum(q[m]) || q[m] == '_')
325                   ++m;
326                 if (m == 3 && memcmp(q, "int", 3) == 0) {
327                   p += l + m;
328                   l = 0;
329                 }
330               }
331             }
332             else if (m != 4 || memcmp(q, "char", 4) != 0) {
333               fwrite("x_unsigned_int", 14, 1, stdout);
334               p += 8;
335               l -= 8;
336             }
337           }
338         }
339         else if (l >= 4 && memcmp(p, "nox_", 4) == 0) {
340           p += 4;
341           l -= 4;
342         }
343         else {
344           for (i = 0; i < n_keywords; ++i)
345             if (
346               l == keywords[i].str_len &&
347               memcmp(p, keywords[i].str_data, l) == 0
348             )
349               goto found_keyword;
350           fwrite("x_", 2, 1, stdout);
351         found_keyword:
352           ;
353         }
354       }
355       else if (p[l] == '.' && isdigit(p[l + 1])) {
356         l += 2;
357         goto decimal;
358       }
359       else if (p[l] == '0' && (p[l + 1] == 'x' || p[l + 1] == 'X')) {
360         l += 2;
361         while (isxdigit(p[l]))
362           ++l;
363         goto integer;
364       }
365       else if (isdigit(p[l])) {
366         ++l;
367         while (isdigit(p[l]))
368           ++l;
369         if (p[l] == '.') {
370           ++l;
371         decimal:
372           while (isdigit(p[l]))
373             ++l;
374           if (p[l] == 'E' || p[l] == 'e' || p[l] == 'D' || p[l] == 'd')
375             goto exponent;
376         }
377         else if (p[l] == 'E' || p[l] == 'e' || p[l] == 'D' || p[l] == 'd') {
378         exponent:
379           ++l;
380           if (p[l] == '+' || p[l] == '-')
381             ++l;
382           while (isdigit(p[l]))
383             ++l;
384         }
385         else {
386         integer:
387           if (p[l] == 'U' || p[l] == 'u')
388             ++l;
389           if (p[l] == 'L' || p[l] == 'l')
390             ++l;
391         }
392       }
393       else if (p[l] == '\'' || p[l] == '"') {
394         e = p[l++];
395         while (p[l] != e) {
396           if (p[l] == '\\')
397             ++l;
398           if (p[l] == 0) {
399             fwrite(p, l, 1, stdout);
400             if (fgets(buf, sizeof(buf), stdin) == 0)
401               return 0;
402             p = buf;
403             l = 0;
404           }
405           else
406             ++l;
407         }
408         ++l;
409       }
410       else if (p[l] == '/' && p[l + 1] == '*') {
411         l += 2;
412         while (p[l] != '*' || p[l + 1] != '/')
413           if (p[l] == 0) {
414             fwrite(p, l, 1, stdout);
415             if (fgets(buf, sizeof(buf), stdin) == 0)
416               return 0;
417             p = buf;
418             l = 0;
419           }
420           else
421             ++l;
422         l += 2;
423       }
424       else
425         ++l;
426       fwrite(p, l, 1, stdout);
427       p += l;
428       l = 0;
429     }
430   }
431   return 0;
432 }