/* ifdef - remove #ifdefs Author: Warren Toomey */ /* Copyright 1989 by Warren Toomey wkt@cs.adfa.oz.au[@uunet.uu.net] * * You may freely copy or distribute this code as long as this notice * remains intact. * * You may modify this code, as long as this notice remains intact, and * you add another notice indicating that the code has been modified. * * You may NOT sell this code or in any way profit from this code without * prior agreement from the author. */ #include #include #include #include #include /* Definition of structures and constants used in ifdef.c */ /* Types of symbols */ #define DEF 1 /* Symbol is defined */ #define UNDEF 2 /* Symbol isn't defined */ #define IGN 3 /* Ignore this symbol unless defined */ /* Redef mode values */ #define MUTABLE 1 /* Symbol can change defined <-> undefined */ #define IMMUTABLE 2 /* Symbol can't change as above */ /* Processing modes */ #define NO 0 /* Don't process */ #define YES 1 /* Process */ /* Ignore (IGN), ignore but process */ struct DEFINE { char *symbol; /* SLL of defined symbols. The redef */ char type; /* field indicates if this symbol can */ char redef; /* change from defined <-> undefined. */ struct DEFINE *next; /* Type is DEF or UNDEF. */ }; /* Global variables & structures */ FILE *zin; /* Input file for processing */ struct DEFINE *defptr; /* Defined symbols SLL */ struct DEFINE *defend; /* Ptr to last node in defptr */ struct DEFINE *deftemp; /* Ptr to last found node */ int line = 1; /* Current line number */ int table = 0; /* Don't normally want a table */ extern int optind; extern char *optarg; /* Prototypes. */ _PROTOTYPE(int main, (int argc, char **argv)); _PROTOTYPE(char fgetarg, (FILE *stream, char *cbuf)); _PROTOTYPE(int find, (char *symd)); _PROTOTYPE(void defit, (char *sym, int redef, int typed)); _PROTOTYPE(void stop, (void)); _PROTOTYPE(void gotoeoln, (void)); _PROTOTYPE(void prteoln, (void)); _PROTOTYPE(void printtable, (void)); _PROTOTYPE(char getendif, (void)); _PROTOTYPE(void gettable, (void)); _PROTOTYPE(void parse, (void)); _PROTOTYPE(void usage, (void)); #ifdef __STDC__ char fgetarg ( FILE *stream , char *cbuf ) #else char fgetarg(stream, cbuf) /* Get next arg from file into cbuf, */ FILE *stream; /* returning the character that */ char *cbuf; /* terminated it. Cbuf returns 0 */ #endif { /* if no arg. EOF is returned if no */ int ch; /* args left in file. */ int i; i = 0; cbuf[i] = 0; while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n')) if (ch == '\n') return(ch); /* Bypass leading */ /* Whitespace */ if (feof(stream)) return(EOF); cbuf[i++] = ch; while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n')) cbuf[i++] = ch; /* Get the argument */ cbuf[i] = 0; return(ch); } #ifdef __STDC__ int find ( char *sym ) #else int find(sym) char *sym; #endif { /* Return DEF if defined else UNDEF */ deftemp = defptr; while (deftemp) { /* Search for the symbol */ if (!strcmp(deftemp->symbol, sym)) return(deftemp->type); /* Setting up the type */ deftemp = deftemp->next; } return(0); } #define Define(x,y) defit(x,y,DEF) #define Undefine(x,y) defit(x,y,UNDEF) #define Ignore(x,y) defit(x,y,IGN) #ifdef __STDC__ void defit ( char *sym , int redef , int type ) #else void defit(sym, redef, type) /* Add symbol to the define list */ char *sym; char redef; /* Mode: MUTABLE etc */ char type; /* Type: DEF, UNDEF, IGN */ #endif { struct DEFINE *temp; char c; c = find(sym); /* First try finding the symbol */ if (type == c) return; /* Return if already declared */ if (c) { /* We have to move if from DEF <-> UNDEF */ if (deftemp->redef == IMMUTABLE) return; else { deftemp->type = type; deftemp->redef = redef; } } else { /* We must create a struct & add it */ /* Malloc room for the struct */ if ((temp = (struct DEFINE *)malloc(sizeof(struct DEFINE))) == NULL) { (void)fprintf(stderr, "ifdef: could not malloc\n"); exit(1); } /* Malloc room for symbol */ if ((temp->symbol = (char *)malloc(strlen(sym) + 1)) == NULL) { (void)fprintf(stderr, "ifdef: could not malloc\n"); exit(1); } (void)strcpy(temp->symbol, sym); /* Copy symbol into struct */ temp->redef = redef; /* and set its redef mode too */ temp->type = type; /* as well as making it defined */ /* Now add to the SLL */ if (defptr == NULL) /* If first node set */ defptr = temp; /* the pointers to it */ else defend->next = temp; /* else add it to the */ defend = temp; /* end of the list. */ } } #ifdef __STDC__ void stop ( void ) #else void stop() #endif { /* Stop: Tidy up at EOF */ if (table) printtable(); (void)fclose(zin); exit(0); } #define Goto { line++; if (ch!='\n') gotoeoln(); } #define Print { line++; if (ch!='\n') prteoln(); } #ifdef __STDC__ void gotoeoln ( void ) #else void gotoeoln() /* Go to the end of the line */ #endif { int ch; while ((ch = fgetc(zin)) != '\n') if (ch == EOF) stop(); } #ifdef __STDC__ void prteoln ( void ) #else void prteoln() /* Print to the end of the line */ #endif { int ch; while ((ch = fgetc(zin)) != '\n') if (ch == EOF) stop(); else (void)putchar(ch); (void)putchar('\n'); } #ifdef __STDC__ void printtable ( void ) #else void printtable() /* Print the defines in the SLL */ #endif { struct DEFINE *temp; (void)printf("Defined\n\n"); temp = defptr; while (temp) { if (temp->type == DEF) (void)printf("%s\n", temp->symbol); temp = temp->next; } (void)printf("\n\nUndefined\n\n"); temp = defptr; while (temp) { if (temp->type == UNDEF) (void)printf("%s\n", temp->symbol); temp = temp->next; } } #ifdef __STDC__ char getendif ( void ) #else char getendif() #endif { /* Find matching endif when ignoring */ char word[80]; /* Buffer for symbols */ int ch; int skip; /* Number of skipped #ifdefs */ skip = 1; while (1) { /* Scan through the file looking for starting lines */ if ((ch = fgetc(zin)) == EOF) stop(); /* Get first char on the line */ if (ch != '#') { /* If not a # ignore line */ (void)putchar(ch); Print; continue; } ch = fgetarg(zin, word); /* Get the word after the # */ if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) skip++; /* Keep track of ifdefs & */ if (!strcmp(word, "endif")) skip--; /* endifs */ (void)printf("#%s%c", word, ch); /* Print the line out */ Print; if (!skip) return('\n'); /* If matching endif, return */ } } #ifdef __STDC__ void gettable ( void ) #else void gettable() /* Get & print a table of defines etc. */ #endif { char word[80]; /* Buffer for symbols */ int ch; while (1) { /* Scan through the file looking for starting lines */ if ((ch = fgetc(zin)) == EOF) stop(); /* Get first char on the line */ if (ch != '#') { /* If not a # ignore line */ Goto; continue; } ch = fgetarg(zin, word); /* Get the word after the # */ if (!strcmp(word, "define")) { /* Define: Define the */ ch = fgetarg(zin, word); /* symbol, and goto */ Define(word, MUTABLE); /* the end of line */ Goto; continue; } if (!strcmp(word, "undef")) { /* Undef: Undefine the */ ch = fgetarg(zin, word); /* symbol, and goto */ Undefine(word, MUTABLE); /* the end of line */ Goto; continue; } /* Ifdef: */ if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) { ch = fgetarg(zin, word); /* Get the symbol */ if (find(word) != DEF) Undefine(word, MUTABLE); /* undefine it */ Goto; continue; } Goto; /* else ignore the line */ } } #ifdef __STDC__ void parse ( void ) #else void parse() #endif { /* Parse & remove ifdefs from C source */ char word[80]; /* Buffer for symbols */ int ch; int proc; /* Should we be processing this bit? */ int skip; /* Number of skipped #ifdefs */ proc = 1; skip = 0; while (1) { /* Scan through the file looking for starting lines */ if ((ch = fgetc(zin)) == EOF) stop(); /* Get first char on the line */ if (ch != '#') if (proc) { /* If not # and we're processing */ (void)putchar(ch); /* then print the line */ Print; continue; } else { Goto; /* else just skip the line */ continue; } ch = fgetarg(zin, word); /* Get the word after the # */ if (!strcmp(word, "define") && proc) { /* Define: Define the */ ch = fgetarg(zin, word); /* symbol, and goto */ Define(word, MUTABLE); /* the end of line */ (void)printf("#define %s%c", word, ch); Print; continue; } if (!strcmp(word, "undef") && proc) { /* Undef: Undefine the */ ch = fgetarg(zin, word); /* symbol, and goto */ Undefine(word, MUTABLE); /* the end of line */ (void)printf("#undef %s%c", word, ch); Print; continue; } if (!strcmp(word, "if")) { /* If: we cannot handle these */ if (!proc) /* at the moment, so just */ skip++; /* treat them as an ignored */ else { /* definition */ (void)printf("#%s%c",word,ch); Print; ch = getendif(); /* Get matching endif */ continue; } } if (!strcmp(word, "ifdef")) { /* Ifdef: */ if (!proc) /* If not processing */ skip++; /* skip it */ else { ch = fgetarg(zin, word); /* Get the symbol */ switch (find(word)) { case DEF: break; case IGN: (void)printf("#ifdef %s%c", word, ch); Print; ch = getendif(); /* Get matching endif */ break; /* If symbol undefined */ default: Undefine(word, MUTABLE); /* undefine it */ proc = 0; /* & stop processing */ } } Goto; continue; } if (!strcmp(word, "ifndef")) { /* Ifndef: */ if (!proc) /* If not processing */ skip++; /* skip the line */ else { ch = fgetarg(zin, word); /* Get the symbol */ switch (find(word)) { /* If defined, stop */ case DEF: proc = 0; /* processing */ break; case IGN: (void)printf("#ifdef %s%c", word, ch); Print; ch = getendif(); /* Get matching endif */ break; } } Goto; continue; } if (!strcmp(word, "else") && !skip) { /* Else: Flip processing */ proc = !proc; Goto; continue; } if (!strcmp(word, "endif")) { /* Endif: If no skipped */ /* ifdefs turn processing */ if (!skip) /* on, else decrement the */ proc = 1; /* number of skips */ else skip--; Goto; continue; } /* The word fails all of the above tests, so if we're */ /* processing, print the line. */ if (proc) { (void)printf("#%s%c", word, ch); Print; } else Goto; } } #ifdef __STDC__ void usage ( void ) #else void usage() #endif { (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] \n"); exit(0); } #ifdef __STDC__ int main(int argc , char *argv []) #else int main(argc, argv) int argc; char *argv[]; #endif { char sym[80]; /* Temp symbol storage */ int c; if (argc == 1) usage(); /* Catch the curious user */ while ((c = getopt(argc, argv, "tD:d:U:I:")) != EOF) { switch (c) { case 't': table = 1; /* Get the various options */ break; case 'd': (void)strcpy(sym, optarg); Define(sym, MUTABLE); break; case 'D': (void)strcpy(sym, optarg); Define(sym, IMMUTABLE); break; case 'U': (void)strcpy(sym, optarg); Undefine(sym, IMMUTABLE); break; case 'I': (void)strcpy(sym, optarg); Ignore(sym, IMMUTABLE); break; default: usage(); } } zin = stdin; /* If a C file is named */ /* Open stdin with it */ if (*argv[argc - 1] != '-') { (void)fclose(zin); if ((zin = fopen(argv[argc - 1], "r")) == NULL) { perror("ifdef"); exit(1); } } if (table) gettable(); /* Either generate a table or */ else parse(); /* parse & replace with the file */ return(0); }