ifdef.c

Go to the documentation of this file.
00001 /* ifdef - remove #ifdefs               Author: Warren Toomey */
00002 
00003 /* Copyright 1989 by Warren Toomey      wkt@cs.adfa.oz.au[@uunet.uu.net]
00004  *
00005  * You may freely copy or distribute this code as long as this notice
00006  * remains intact.
00007  *
00008  * You may modify this code, as long as this notice remains intact, and
00009  * you add another notice indicating that the code has been modified.
00010  *
00011  * You may NOT sell this code or in any way profit from this code without
00012  * prior agreement from the author.
00013  */
00014 
00015 #include <sys/types.h>
00016 #include <string.h>
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <unistd.h>
00020 
00021 /* Definition of structures and constants used in ifdef.c  */
00022 
00023 /* Types of symbols */
00024 #define DEF       1             /* Symbol is defined    */
00025 #define UNDEF     2             /* Symbol isn't defined */
00026 #define IGN       3             /* Ignore this symbol unless defined */
00027 
00028 /* Redef mode values */
00029 #define MUTABLE   1             /* Symbol can change defined <-> undefined */
00030 #define IMMUTABLE 2             /* Symbol can't change as above            */
00031 
00032 /* Processing modes */
00033 #define NO      0               /* Don't process */
00034 #define YES     1               /* Process */
00035 
00036 /* Ignore (IGN), ignore but process */
00037 struct DEFINE {
00038   char *symbol;                 /* SLL of defined symbols. The redef  */
00039   char type;                    /* field indicates if this symbol can */
00040   char redef;                   /* change from defined <-> undefined. */
00041   struct DEFINE *next;          /* Type is DEF or UNDEF.              */
00042 };
00043 
00044 /* Global variables & structures */
00045 FILE *zin;                      /* Input file for processing  */
00046 struct DEFINE *defptr;          /* Defined symbols SLL        */
00047 struct DEFINE *defend;          /* Ptr to last node in defptr */
00048 struct DEFINE *deftemp;         /* Ptr to last found node     */
00049 int line = 1;                   /* Current line number        */
00050 int table = 0;                  /* Don't normally want a table */
00051 
00052 extern int optind;
00053 extern char *optarg;
00054 
00055 /* Prototypes. */
00056 _PROTOTYPE(int main, (int argc, char **argv));
00057 _PROTOTYPE(char fgetarg, (FILE *stream, char *cbuf));
00058 _PROTOTYPE(int find, (char *symd));
00059 _PROTOTYPE(void defit, (char *sym, int redef, int typed));
00060 _PROTOTYPE(void stop, (void));
00061 _PROTOTYPE(void gotoeoln, (void));
00062 _PROTOTYPE(void prteoln, (void));
00063 _PROTOTYPE(void printtable, (void));
00064 _PROTOTYPE(char getendif, (void));
00065 _PROTOTYPE(void gettable, (void));
00066 _PROTOTYPE(void parse, (void));
00067 _PROTOTYPE(void usage, (void));
00068 
00069 #ifdef __STDC__
00070 char fgetarg ( FILE *stream , char *cbuf )
00071 #else
00072 char fgetarg(stream, cbuf)      /* Get next arg from file into cbuf, */
00073 FILE *stream;                   /* returning the character that      */
00074 char *cbuf;                     /* terminated it. Cbuf returns 0     */
00075 #endif
00076 {                               /* if no arg. EOF is returned if no  */
00077   int ch;                       /* args left in file.                */
00078   int i;
00079 
00080   i = 0;
00081   cbuf[i] = 0;
00082 
00083   while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n'))
00084         if (ch == '\n') return(ch);     /* Bypass leading */
00085                                         /* Whitespace     */
00086   if (feof(stream)) return(EOF);
00087 
00088   cbuf[i++] = ch;
00089 
00090   while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n'))
00091         cbuf[i++] = ch;                 /* Get the argument */
00092 
00093   cbuf[i] = 0;
00094   return(ch);
00095 }
00096 
00097 
00098 #ifdef __STDC__
00099 int find ( char *sym )
00100 #else
00101 int find(sym)
00102 char *sym;
00103 #endif
00104 {                               /* Return DEF if defined else UNDEF */
00105 
00106   deftemp = defptr;
00107   while (deftemp) {                     /* Search for the symbol */
00108         if (!strcmp(deftemp->symbol, sym))
00109                 return(deftemp->type);  /* Setting up the type */
00110         deftemp = deftemp->next;
00111   }
00112   return(0);
00113 }
00114 
00115 
00116 
00117 #define Define(x,y)     defit(x,y,DEF)
00118 #define Undefine(x,y)   defit(x,y,UNDEF)
00119 #define Ignore(x,y)     defit(x,y,IGN)
00120 
00121 #ifdef __STDC__
00122 void defit ( char *sym , int redef , int type )
00123 #else
00124 void defit(sym, redef, type)    /* Add symbol to the define list */
00125 char *sym;
00126 char redef;                     /* Mode: MUTABLE etc      */
00127 char type;                      /* Type: DEF, UNDEF, IGN  */
00128 #endif
00129 {
00130   struct DEFINE *temp;
00131   char c;
00132 
00133   c = find(sym);                /* First try finding the symbol */
00134   if (type == c) return;        /* Return if already declared */
00135   if (c) {                      /* We have to move if from DEF <-> UNDEF */
00136         if (deftemp->redef == IMMUTABLE)
00137                 return;
00138         else {
00139                 deftemp->type = type;
00140                 deftemp->redef = redef;
00141         }
00142   } else {                      /* We must create a struct & add it */
00143                                 /* Malloc room for the struct */
00144         if ((temp = (struct DEFINE *)malloc(sizeof(struct DEFINE))) == NULL) {
00145                 (void)fprintf(stderr, "ifdef: could not malloc\n");
00146                 exit(1);
00147         }
00148 
00149                                         /* Malloc room for symbol */
00150         if ((temp->symbol = (char *)malloc(strlen(sym) + 1)) == NULL) {
00151                 (void)fprintf(stderr, "ifdef: could not malloc\n");
00152                 exit(1);
00153         }
00154         (void)strcpy(temp->symbol, sym); /* Copy symbol into struct      */
00155         temp->redef = redef;            /* and set its redef mode too   */
00156         temp->type = type;              /* as well as making it defined */
00157 
00158 
00159                                         /* Now add to the SLL */
00160         if (defptr == NULL)             /* If first node set  */
00161                 defptr = temp;          /* the pointers to it */
00162         else
00163                 defend->next = temp;    /* else add it to the */
00164         defend = temp;                  /* end of the list.   */
00165   }
00166 }
00167 
00168 
00169 
00170 #ifdef __STDC__
00171 void stop ( void )
00172 #else
00173 void stop()
00174 #endif
00175 {                               /* Stop: Tidy up at EOF */
00176   if (table) printtable();
00177   (void)fclose(zin);
00178   exit(0);
00179 }
00180 
00181 #define Goto    { line++; if (ch!='\n') gotoeoln(); }
00182 #define Print   { line++; if (ch!='\n') prteoln();  }
00183 
00184 #ifdef __STDC__
00185 void gotoeoln ( void )
00186 #else
00187 void gotoeoln()                 /* Go to the end of the line */
00188 #endif
00189 {
00190   int ch;
00191   while ((ch = fgetc(zin)) != '\n')
00192         if (ch == EOF) stop();
00193 }
00194 
00195 
00196 #ifdef __STDC__
00197 void prteoln ( void )
00198 #else
00199 void prteoln()                  /* Print to the end of the line */
00200 #endif
00201 {
00202   int ch;
00203   while ((ch = fgetc(zin)) != '\n')
00204         if (ch == EOF)
00205                 stop();
00206         else
00207                 (void)putchar(ch);
00208   (void)putchar('\n');
00209 }
00210 
00211 
00212 #ifdef __STDC__
00213 void printtable ( void )
00214 #else
00215 void printtable()               /* Print the defines in the SLL */
00216 #endif
00217 {
00218   struct DEFINE *temp;
00219 
00220   (void)printf("Defined\n\n");
00221 
00222   temp = defptr;
00223   while (temp) {
00224         if (temp->type == DEF) (void)printf("%s\n", temp->symbol);
00225         temp = temp->next;
00226   }
00227 
00228   (void)printf("\n\nUndefined\n\n");
00229 
00230   temp = defptr;
00231   while (temp) {
00232         if (temp->type == UNDEF) (void)printf("%s\n", temp->symbol);
00233         temp = temp->next;
00234   }
00235 }
00236 
00237 #ifdef __STDC__
00238 char getendif ( void )
00239 #else
00240 char getendif()
00241 #endif
00242 {                               /* Find matching endif when ignoring */
00243   char word[80];                /* Buffer for symbols */
00244   int ch;
00245   int skip;                     /* Number of skipped #ifdefs */
00246 
00247   skip = 1;
00248 
00249   while (1) {
00250                         /* Scan through the file looking for starting lines */
00251         if ((ch = fgetc(zin)) == EOF)
00252                 stop();         /* Get first char on the line */
00253         if (ch != '#') {        /* If not a # ignore line     */
00254                 (void)putchar(ch);
00255                 Print;
00256                 continue;
00257         }
00258         ch = fgetarg(zin, word);        /* Get the word after the # */
00259 
00260         if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) skip++;
00261                                                 /* Keep track of ifdefs & */
00262         if (!strcmp(word, "endif")) skip--;     /* endifs                 */
00263 
00264         (void)printf("#%s%c", word, ch);        /* Print the line out     */
00265         Print;
00266         if (!skip) return('\n');        /* If matching endif, return */
00267   }
00268 }
00269 
00270 
00271 #ifdef __STDC__
00272 void gettable ( void )
00273 #else
00274 void gettable()                 /* Get & print a table of defines etc.  */
00275 #endif
00276 {
00277 
00278   char word[80];                /* Buffer for symbols */
00279   int ch;
00280 
00281   while (1) {
00282                         /* Scan through the file looking for starting lines */
00283         if ((ch = fgetc(zin)) == EOF)
00284                 stop();         /* Get first char on the line */
00285         if (ch != '#') {        /* If not a # ignore line     */
00286                 Goto;
00287                 continue;
00288         }
00289         ch = fgetarg(zin, word);        /* Get the word after the # */
00290 
00291         if (!strcmp(word, "define")) {          /* Define: Define the */
00292                 ch = fgetarg(zin, word);        /* symbol, and goto   */
00293                 Define(word, MUTABLE);          /* the end of line    */
00294                 Goto;
00295                 continue;
00296         }
00297         if (!strcmp(word, "undef")) {           /* Undef: Undefine the */
00298                 ch = fgetarg(zin, word);        /* symbol, and goto    */
00299                 Undefine(word, MUTABLE);        /* the end of line     */
00300                 Goto;
00301                 continue;
00302         }                                       /* Ifdef:            */
00303         if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) {
00304                 ch = fgetarg(zin, word);        /* Get the symbol */
00305                 if (find(word) != DEF)
00306                         Undefine(word, MUTABLE);        /* undefine it */
00307                 Goto;
00308                 continue;
00309         }
00310         Goto;                           /* else ignore the line */
00311   }
00312 }
00313 
00314 
00315 
00316 #ifdef __STDC__
00317 void parse ( void )
00318 #else
00319 void parse()
00320 #endif
00321 {                               /* Parse & remove ifdefs from C source */
00322   char word[80];                /* Buffer for symbols */
00323   int ch;
00324   int proc;                     /* Should we be processing this bit?    */
00325   int skip;                     /* Number of skipped #ifdefs             */
00326 
00327   proc = 1;
00328   skip = 0;
00329 
00330   while (1) {
00331                         /* Scan through the file looking for starting lines */
00332         if ((ch = fgetc(zin)) == EOF)
00333                 stop();         /* Get first char on the line */
00334         if (ch != '#')
00335                 if (proc) {     /* If not # and  we're processing */
00336                         (void)putchar(ch); /* then print the line */
00337                         Print;
00338                         continue;
00339                 } else {
00340                         Goto;   /* else just skip the line  */
00341                         continue;
00342                 }
00343 
00344         ch = fgetarg(zin, word);        /* Get the word after the # */
00345 
00346         if (!strcmp(word, "define") && proc) {  /* Define: Define the */
00347                 ch = fgetarg(zin, word);        /* symbol, and goto   */
00348                 Define(word, MUTABLE);          /* the end of line    */
00349                 (void)printf("#define %s%c", word, ch);
00350                 Print;
00351                 continue;
00352         }
00353         if (!strcmp(word, "undef") && proc) {   /* Undef: Undefine the */
00354                 ch = fgetarg(zin, word);        /* symbol, and goto    */
00355                 Undefine(word, MUTABLE);        /* the end of line     */
00356                 (void)printf("#undef %s%c", word, ch);
00357                 Print;
00358                 continue;
00359         }
00360         if (!strcmp(word, "if")) {      /* If: we cannot handle these */
00361                 if (!proc)              /* at the moment, so just */
00362                         skip++;         /* treat them as an ignored */
00363                 else {                  /* definition */
00364                         (void)printf("#%s%c",word,ch);
00365                         Print;
00366                         ch = getendif();        /* Get matching endif */
00367                         continue;
00368                         }
00369         }
00370         if (!strcmp(word, "ifdef")) {   /* Ifdef:            */
00371                 if (!proc)              /* If not processing */
00372                         skip++;         /* skip it           */
00373                 else {
00374                         ch = fgetarg(zin, word); /* Get the symbol */
00375                         switch (find(word)) {
00376                             case DEF:
00377                                 break;
00378                             case IGN:
00379                                 (void)printf("#ifdef %s%c", word, ch);
00380                                 Print;
00381                                 ch = getendif(); /* Get matching endif */
00382                                 break;
00383                                                 /* If symbol undefined */
00384                             default:
00385                                 Undefine(word, MUTABLE); /* undefine it */
00386                                 proc = 0;       /* & stop processing */
00387                         }
00388                 }
00389                 Goto;
00390                 continue;
00391         }
00392         if (!strcmp(word, "ifndef")) {
00393                 /* Ifndef: */
00394                 if (!proc)      /* If not processing */
00395                         skip++; /* skip the line     */
00396                 else {
00397                         ch = fgetarg(zin, word); /* Get the symbol */
00398                         switch (find(word)) {   /* If defined, stop */
00399                             case DEF:
00400                                 proc = 0;       /* processing       */
00401                                 break;
00402                             case IGN:
00403                                 (void)printf("#ifdef %s%c", word, ch);
00404                                 Print;
00405                                 ch = getendif(); /* Get matching endif */
00406                                 break;
00407                         }
00408                 }
00409                 Goto;
00410                 continue;
00411         }
00412         if (!strcmp(word, "else") && !skip) {   /* Else: Flip processing */
00413                 proc = !proc;
00414                 Goto;
00415                 continue;
00416         }
00417         if (!strcmp(word, "endif")) {   /* Endif: If no skipped   */
00418                                         /* ifdefs turn processing */
00419                 if (!skip)              /* on, else decrement the */
00420                         proc = 1;       /* number of skips        */
00421                 else
00422                         skip--;
00423                 Goto;
00424                 continue;
00425         }
00426                 /* The word fails all of the above tests, so if we're */
00427                 /* processing, print the line. */
00428         if (proc) {
00429                 (void)printf("#%s%c", word, ch);
00430                 Print;
00431         } else
00432                 Goto;
00433   }
00434 }
00435 
00436 
00437 #ifdef __STDC__
00438 void usage ( void )
00439 #else
00440 void usage()
00441 #endif
00442 {
00443   (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n");
00444   exit(0);
00445 }
00446 
00447 
00448 #ifdef __STDC__
00449 int main(int argc , char *argv [])
00450 #else
00451 int main(argc, argv)
00452 int argc;
00453 char *argv[];
00454 #endif
00455 {
00456   char sym[80];                 /* Temp symbol storage */
00457   int c;
00458 
00459   if (argc == 1) usage();       /* Catch the curious user        */
00460   while ((c = getopt(argc, argv, "tD:d:U:I:")) != EOF) {
00461         switch (c) {
00462             case 't':
00463                 table = 1;      /* Get the various options */
00464                 break;
00465 
00466             case 'd':
00467                 (void)strcpy(sym, optarg);
00468                 Define(sym, MUTABLE);
00469                 break;
00470 
00471             case 'D':
00472                 (void)strcpy(sym, optarg);
00473                 Define(sym, IMMUTABLE);
00474                 break;
00475 
00476             case 'U':
00477                 (void)strcpy(sym, optarg);
00478                 Undefine(sym, IMMUTABLE);
00479                 break;
00480 
00481             case 'I':
00482                 (void)strcpy(sym, optarg);
00483                 Ignore(sym, IMMUTABLE);
00484                 break;
00485 
00486             default:    usage();
00487         }
00488   }
00489 
00490   zin = stdin;          /* If a C file is named */
00491                         /* Open stdin with it */
00492   if (*argv[argc - 1] != '-') {
00493         (void)fclose(zin);
00494         if ((zin = fopen(argv[argc - 1], "r")) == NULL) {
00495                 perror("ifdef");
00496                 exit(1);
00497         }
00498   }
00499   if (table)
00500         gettable();             /* Either generate a table or    */
00501   else
00502         parse();                /* parse & replace with the file */
00503   return(0);
00504 }

Generated on Fri Apr 14 22:57:07 2006 for minix by  doxygen 1.4.6