505 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			505 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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 <sys/types.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| /* 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. */
 | |
| int main(int argc, char **argv);
 | |
| char fgetarg(FILE *stream, char *cbuf);
 | |
| int find(char *symd);
 | |
| void defit(char *sym, int redef, int typed);
 | |
| void stop(void);
 | |
| void gotoeoln(void);
 | |
| void prteoln(void);
 | |
| void printtable(void);
 | |
| char getendif(void);
 | |
| void gettable(void);
 | |
| void parse(void);
 | |
| 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] <file>\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);
 | |
| }
 | 
