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
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>
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 */
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 */
56 int main(int argc
, char **argv
);
57 char fgetarg(FILE *stream
, char *cbuf
);
59 void defit(char *sym
, int redef
, int typed
);
63 void printtable(void);
70 char fgetarg ( FILE *stream
, char *cbuf
)
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 */
76 { /* if no arg. EOF is returned if no */
77 int ch
; /* args left in file. */
83 while (((ch
= fgetc(stream
)) == ' ') || (ch
== '\t') || (ch
== '\n'))
84 if (ch
== '\n') return(ch
); /* Bypass leading */
86 if (feof(stream
)) return(EOF
);
90 while (((ch
= fgetc(stream
)) != ' ') && (ch
!= '\t') && (ch
!= '\n'))
91 cbuf
[i
++] = ch
; /* Get the argument */
99 int find ( char *sym
)
104 { /* Return DEF if defined else UNDEF */
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
;
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)
122 void defit ( char *sym
, int redef
, int type
)
124 void defit(sym
, redef
, type
) /* Add symbol to the define list */
126 char redef
; /* Mode: MUTABLE etc */
127 char type
; /* Type: DEF, UNDEF, IGN */
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
)
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");
149 /* Malloc room for symbol */
150 if ((temp
->symbol
= (char *)malloc(strlen(sym
) + 1)) == NULL
) {
151 (void)fprintf(stderr
, "ifdef: could not malloc\n");
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 */
163 defend
->next
= temp
; /* else add it to the */
164 defend
= temp
; /* end of the list. */
175 { /* Stop: Tidy up at EOF */
176 if (table
) printtable();
181 #define Goto { line++; if (ch!='\n') gotoeoln(); }
182 #define Print { line++; if (ch!='\n') prteoln(); }
185 void gotoeoln ( void )
187 void gotoeoln() /* Go to the end of the line */
191 while ((ch
= fgetc(zin
)) != '\n')
192 if (ch
== EOF
) stop();
197 void prteoln ( void )
199 void prteoln() /* Print to the end of the line */
203 while ((ch
= fgetc(zin
)) != '\n')
213 void printtable ( void )
215 void printtable() /* Print the defines in the SLL */
220 (void)printf("Defined\n\n");
224 if (temp
->type
== DEF
) (void)printf("%s\n", temp
->symbol
);
228 (void)printf("\n\nUndefined\n\n");
232 if (temp
->type
== UNDEF
) (void)printf("%s\n", temp
->symbol
);
238 char getendif ( void )
242 { /* Find matching endif when ignoring */
243 char word
[80]; /* Buffer for symbols */
245 int skip
; /* Number of skipped #ifdefs */
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 */
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 */
266 if (!skip
) return('\n'); /* If matching endif, return */
272 void gettable ( void )
274 void gettable() /* Get & print a table of defines etc. */
278 char word
[80]; /* Buffer for symbols */
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 */
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 */
297 if (!strcmp(word
, "undef")) { /* Undef: Undefine the */
298 ch
= fgetarg(zin
, word
); /* symbol, and goto */
299 Undefine(word
, MUTABLE
); /* the end of line */
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 */
310 Goto
; /* else ignore the line */
321 { /* Parse & remove ifdefs from C source */
322 char word
[80]; /* Buffer for symbols */
324 int proc
; /* Should we be processing this bit? */
325 int skip
; /* Number of skipped #ifdefs */
331 /* Scan through the file looking for starting lines */
332 if ((ch
= fgetc(zin
)) == EOF
)
333 stop(); /* Get first char on the line */
335 if (proc
) { /* If not # and we're processing */
336 (void)putchar(ch
); /* then print the line */
340 Goto
; /* else just skip the line */
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
);
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
);
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
);
366 ch
= getendif(); /* Get matching endif */
370 if (!strcmp(word
, "ifdef")) { /* Ifdef: */
371 if (!proc
) /* If not processing */
372 skip
++; /* skip it */
374 ch
= fgetarg(zin
, word
); /* Get the symbol */
375 switch (find(word
)) {
379 (void)printf("#ifdef %s%c", word
, ch
);
381 ch
= getendif(); /* Get matching endif */
383 /* If symbol undefined */
385 Undefine(word
, MUTABLE
); /* undefine it */
386 proc
= 0; /* & stop processing */
392 if (!strcmp(word
, "ifndef")) {
394 if (!proc
) /* If not processing */
395 skip
++; /* skip the line */
397 ch
= fgetarg(zin
, word
); /* Get the symbol */
398 switch (find(word
)) { /* If defined, stop */
400 proc
= 0; /* processing */
403 (void)printf("#ifdef %s%c", word
, ch
);
405 ch
= getendif(); /* Get matching endif */
412 if (!strcmp(word
, "else") && !skip
) { /* Else: Flip processing */
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 */
426 /* The word fails all of the above tests, so if we're */
427 /* processing, print the line. */
429 (void)printf("#%s%c", word
, ch
);
443 (void)fprintf(stderr
, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n");
449 int main(int argc
, char *argv
[])
456 char sym
[80]; /* Temp symbol storage */
459 if (argc
== 1) usage(); /* Catch the curious user */
460 while ((c
= getopt(argc
, argv
, "tD:d:U:I:")) != EOF
) {
463 table
= 1; /* Get the various options */
467 (void)strcpy(sym
, optarg
);
468 Define(sym
, MUTABLE
);
472 (void)strcpy(sym
, optarg
);
473 Define(sym
, IMMUTABLE
);
477 (void)strcpy(sym
, optarg
);
478 Undefine(sym
, IMMUTABLE
);
482 (void)strcpy(sym
, optarg
);
483 Ignore(sym
, IMMUTABLE
);
490 zin
= stdin
; /* If a C file is named */
491 /* Open stdin with it */
492 if (*argv
[argc
- 1] != '-') {
494 if ((zin
= fopen(argv
[argc
- 1], "r")) == NULL
) {
500 gettable(); /* Either generate a table or */
502 parse(); /* parse & replace with the file */