custom message type for VM_INFO
[minix3.git] / commands / ifdef / ifdef.c
blob23abc930d8e669d9e23ad8d187faf92b7f0f8cd9
1 /* ifdef - remove #ifdefs Author: Warren Toomey */
3 /* Copyright 1989 by Warren Toomey wkt@cs.adfa.oz.au[@uunet.uu.net]
5 * You may freely copy or distribute this code as long as this notice
6 * remains intact.
8 * You may modify this code, as long as this notice remains intact, and
9 * you add another notice indicating that the code has been modified.
11 * You may NOT sell this code or in any way profit from this code without
12 * prior agreement from the author.
15 #include <sys/types.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
21 /* Definition of structures and constants used in ifdef.c */
23 /* Types of symbols */
24 #define DEF 1 /* Symbol is defined */
25 #define UNDEF 2 /* Symbol isn't defined */
26 #define IGN 3 /* Ignore this symbol unless defined */
28 /* Redef mode values */
29 #define MUTABLE 1 /* Symbol can change defined <-> undefined */
30 #define IMMUTABLE 2 /* Symbol can't change as above */
32 /* Processing modes */
33 #define NO 0 /* Don't process */
34 #define YES 1 /* Process */
36 /* Ignore (IGN), ignore but process */
37 struct DEFINE {
38 char *symbol; /* SLL of defined symbols. The redef */
39 char type; /* field indicates if this symbol can */
40 char redef; /* change from defined <-> undefined. */
41 struct DEFINE *next; /* Type is DEF or UNDEF. */
44 /* Global variables & structures */
45 FILE *zin; /* Input file for processing */
46 struct DEFINE *defptr; /* Defined symbols SLL */
47 struct DEFINE *defend; /* Ptr to last node in defptr */
48 struct DEFINE *deftemp; /* Ptr to last found node */
49 int line = 1; /* Current line number */
50 int table = 0; /* Don't normally want a table */
52 extern int optind;
53 extern char *optarg;
55 /* Prototypes. */
56 int main(int argc, char **argv);
57 char fgetarg(FILE *stream, char *cbuf);
58 int find(char *symd);
59 void defit(char *sym, int redef, int typed);
60 void stop(void);
61 void gotoeoln(void);
62 void prteoln(void);
63 void printtable(void);
64 char getendif(void);
65 void gettable(void);
66 void parse(void);
67 void usage(void);
69 #ifdef __STDC__
70 char fgetarg ( FILE *stream , char *cbuf )
71 #else
72 char fgetarg(stream, cbuf) /* Get next arg from file into cbuf, */
73 FILE *stream; /* returning the character that */
74 char *cbuf; /* terminated it. Cbuf returns 0 */
75 #endif
76 { /* if no arg. EOF is returned if no */
77 int ch; /* args left in file. */
78 int i;
80 i = 0;
81 cbuf[i] = 0;
83 while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n'))
84 if (ch == '\n') return(ch); /* Bypass leading */
85 /* Whitespace */
86 if (feof(stream)) return(EOF);
88 cbuf[i++] = ch;
90 while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n'))
91 cbuf[i++] = ch; /* Get the argument */
93 cbuf[i] = 0;
94 return(ch);
98 #ifdef __STDC__
99 int find ( char *sym )
100 #else
101 int find(sym)
102 char *sym;
103 #endif
104 { /* Return DEF if defined else UNDEF */
106 deftemp = defptr;
107 while (deftemp) { /* Search for the symbol */
108 if (!strcmp(deftemp->symbol, sym))
109 return(deftemp->type); /* Setting up the type */
110 deftemp = deftemp->next;
112 return(0);
117 #define Define(x,y) defit(x,y,DEF)
118 #define Undefine(x,y) defit(x,y,UNDEF)
119 #define Ignore(x,y) defit(x,y,IGN)
121 #ifdef __STDC__
122 void defit ( char *sym , int redef , int type )
123 #else
124 void defit(sym, redef, type) /* Add symbol to the define list */
125 char *sym;
126 char redef; /* Mode: MUTABLE etc */
127 char type; /* Type: DEF, UNDEF, IGN */
128 #endif
130 struct DEFINE *temp;
131 char c;
133 c = find(sym); /* First try finding the symbol */
134 if (type == c) return; /* Return if already declared */
135 if (c) { /* We have to move if from DEF <-> UNDEF */
136 if (deftemp->redef == IMMUTABLE)
137 return;
138 else {
139 deftemp->type = type;
140 deftemp->redef = redef;
142 } else { /* We must create a struct & add it */
143 /* Malloc room for the struct */
144 if ((temp = (struct DEFINE *)malloc(sizeof(struct DEFINE))) == NULL) {
145 (void)fprintf(stderr, "ifdef: could not malloc\n");
146 exit(1);
149 /* Malloc room for symbol */
150 if ((temp->symbol = (char *)malloc(strlen(sym) + 1)) == NULL) {
151 (void)fprintf(stderr, "ifdef: could not malloc\n");
152 exit(1);
154 (void)strcpy(temp->symbol, sym); /* Copy symbol into struct */
155 temp->redef = redef; /* and set its redef mode too */
156 temp->type = type; /* as well as making it defined */
159 /* Now add to the SLL */
160 if (defptr == NULL) /* If first node set */
161 defptr = temp; /* the pointers to it */
162 else
163 defend->next = temp; /* else add it to the */
164 defend = temp; /* end of the list. */
170 #ifdef __STDC__
171 void stop ( void )
172 #else
173 void stop()
174 #endif
175 { /* Stop: Tidy up at EOF */
176 if (table) printtable();
177 (void)fclose(zin);
178 exit(0);
181 #define Goto { line++; if (ch!='\n') gotoeoln(); }
182 #define Print { line++; if (ch!='\n') prteoln(); }
184 #ifdef __STDC__
185 void gotoeoln ( void )
186 #else
187 void gotoeoln() /* Go to the end of the line */
188 #endif
190 int ch;
191 while ((ch = fgetc(zin)) != '\n')
192 if (ch == EOF) stop();
196 #ifdef __STDC__
197 void prteoln ( void )
198 #else
199 void prteoln() /* Print to the end of the line */
200 #endif
202 int ch;
203 while ((ch = fgetc(zin)) != '\n')
204 if (ch == EOF)
205 stop();
206 else
207 (void)putchar(ch);
208 (void)putchar('\n');
212 #ifdef __STDC__
213 void printtable ( void )
214 #else
215 void printtable() /* Print the defines in the SLL */
216 #endif
218 struct DEFINE *temp;
220 (void)printf("Defined\n\n");
222 temp = defptr;
223 while (temp) {
224 if (temp->type == DEF) (void)printf("%s\n", temp->symbol);
225 temp = temp->next;
228 (void)printf("\n\nUndefined\n\n");
230 temp = defptr;
231 while (temp) {
232 if (temp->type == UNDEF) (void)printf("%s\n", temp->symbol);
233 temp = temp->next;
237 #ifdef __STDC__
238 char getendif ( void )
239 #else
240 char getendif()
241 #endif
242 { /* Find matching endif when ignoring */
243 char word[80]; /* Buffer for symbols */
244 int ch;
245 int skip; /* Number of skipped #ifdefs */
247 skip = 1;
249 while (1) {
250 /* Scan through the file looking for starting lines */
251 if ((ch = fgetc(zin)) == EOF)
252 stop(); /* Get first char on the line */
253 if (ch != '#') { /* If not a # ignore line */
254 (void)putchar(ch);
255 Print;
256 continue;
258 ch = fgetarg(zin, word); /* Get the word after the # */
260 if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) skip++;
261 /* Keep track of ifdefs & */
262 if (!strcmp(word, "endif")) skip--; /* endifs */
264 (void)printf("#%s%c", word, ch); /* Print the line out */
265 Print;
266 if (!skip) return('\n'); /* If matching endif, return */
271 #ifdef __STDC__
272 void gettable ( void )
273 #else
274 void gettable() /* Get & print a table of defines etc. */
275 #endif
278 char word[80]; /* Buffer for symbols */
279 int ch;
281 while (1) {
282 /* Scan through the file looking for starting lines */
283 if ((ch = fgetc(zin)) == EOF)
284 stop(); /* Get first char on the line */
285 if (ch != '#') { /* If not a # ignore line */
286 Goto;
287 continue;
289 ch = fgetarg(zin, word); /* Get the word after the # */
291 if (!strcmp(word, "define")) { /* Define: Define the */
292 ch = fgetarg(zin, word); /* symbol, and goto */
293 Define(word, MUTABLE); /* the end of line */
294 Goto;
295 continue;
297 if (!strcmp(word, "undef")) { /* Undef: Undefine the */
298 ch = fgetarg(zin, word); /* symbol, and goto */
299 Undefine(word, MUTABLE); /* the end of line */
300 Goto;
301 continue;
302 } /* Ifdef: */
303 if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) {
304 ch = fgetarg(zin, word); /* Get the symbol */
305 if (find(word) != DEF)
306 Undefine(word, MUTABLE); /* undefine it */
307 Goto;
308 continue;
310 Goto; /* else ignore the line */
316 #ifdef __STDC__
317 void parse ( void )
318 #else
319 void parse()
320 #endif
321 { /* Parse & remove ifdefs from C source */
322 char word[80]; /* Buffer for symbols */
323 int ch;
324 int proc; /* Should we be processing this bit? */
325 int skip; /* Number of skipped #ifdefs */
327 proc = 1;
328 skip = 0;
330 while (1) {
331 /* Scan through the file looking for starting lines */
332 if ((ch = fgetc(zin)) == EOF)
333 stop(); /* Get first char on the line */
334 if (ch != '#')
335 if (proc) { /* If not # and we're processing */
336 (void)putchar(ch); /* then print the line */
337 Print;
338 continue;
339 } else {
340 Goto; /* else just skip the line */
341 continue;
344 ch = fgetarg(zin, word); /* Get the word after the # */
346 if (!strcmp(word, "define") && proc) { /* Define: Define the */
347 ch = fgetarg(zin, word); /* symbol, and goto */
348 Define(word, MUTABLE); /* the end of line */
349 (void)printf("#define %s%c", word, ch);
350 Print;
351 continue;
353 if (!strcmp(word, "undef") && proc) { /* Undef: Undefine the */
354 ch = fgetarg(zin, word); /* symbol, and goto */
355 Undefine(word, MUTABLE); /* the end of line */
356 (void)printf("#undef %s%c", word, ch);
357 Print;
358 continue;
360 if (!strcmp(word, "if")) { /* If: we cannot handle these */
361 if (!proc) /* at the moment, so just */
362 skip++; /* treat them as an ignored */
363 else { /* definition */
364 (void)printf("#%s%c",word,ch);
365 Print;
366 ch = getendif(); /* Get matching endif */
367 continue;
370 if (!strcmp(word, "ifdef")) { /* Ifdef: */
371 if (!proc) /* If not processing */
372 skip++; /* skip it */
373 else {
374 ch = fgetarg(zin, word); /* Get the symbol */
375 switch (find(word)) {
376 case DEF:
377 break;
378 case IGN:
379 (void)printf("#ifdef %s%c", word, ch);
380 Print;
381 ch = getendif(); /* Get matching endif */
382 break;
383 /* If symbol undefined */
384 default:
385 Undefine(word, MUTABLE); /* undefine it */
386 proc = 0; /* & stop processing */
389 Goto;
390 continue;
392 if (!strcmp(word, "ifndef")) {
393 /* Ifndef: */
394 if (!proc) /* If not processing */
395 skip++; /* skip the line */
396 else {
397 ch = fgetarg(zin, word); /* Get the symbol */
398 switch (find(word)) { /* If defined, stop */
399 case DEF:
400 proc = 0; /* processing */
401 break;
402 case IGN:
403 (void)printf("#ifdef %s%c", word, ch);
404 Print;
405 ch = getendif(); /* Get matching endif */
406 break;
409 Goto;
410 continue;
412 if (!strcmp(word, "else") && !skip) { /* Else: Flip processing */
413 proc = !proc;
414 Goto;
415 continue;
417 if (!strcmp(word, "endif")) { /* Endif: If no skipped */
418 /* ifdefs turn processing */
419 if (!skip) /* on, else decrement the */
420 proc = 1; /* number of skips */
421 else
422 skip--;
423 Goto;
424 continue;
426 /* The word fails all of the above tests, so if we're */
427 /* processing, print the line. */
428 if (proc) {
429 (void)printf("#%s%c", word, ch);
430 Print;
431 } else
432 Goto;
437 #ifdef __STDC__
438 void usage ( void )
439 #else
440 void usage()
441 #endif
443 (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n");
444 exit(0);
448 #ifdef __STDC__
449 int main(int argc , char *argv [])
450 #else
451 int main(argc, argv)
452 int argc;
453 char *argv[];
454 #endif
456 char sym[80]; /* Temp symbol storage */
457 int c;
459 if (argc == 1) usage(); /* Catch the curious user */
460 while ((c = getopt(argc, argv, "tD:d:U:I:")) != EOF) {
461 switch (c) {
462 case 't':
463 table = 1; /* Get the various options */
464 break;
466 case 'd':
467 (void)strcpy(sym, optarg);
468 Define(sym, MUTABLE);
469 break;
471 case 'D':
472 (void)strcpy(sym, optarg);
473 Define(sym, IMMUTABLE);
474 break;
476 case 'U':
477 (void)strcpy(sym, optarg);
478 Undefine(sym, IMMUTABLE);
479 break;
481 case 'I':
482 (void)strcpy(sym, optarg);
483 Ignore(sym, IMMUTABLE);
484 break;
486 default: usage();
490 zin = stdin; /* If a C file is named */
491 /* Open stdin with it */
492 if (*argv[argc - 1] != '-') {
493 (void)fclose(zin);
494 if ((zin = fopen(argv[argc - 1], "r")) == NULL) {
495 perror("ifdef");
496 exit(1);
499 if (table)
500 gettable(); /* Either generate a table or */
501 else
502 parse(); /* parse & replace with the file */
503 return(0);