123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- /* (C) 1992,1996,1998-9 R de Bath */
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #ifdef __STDC__ /* == Not braindead compiler (hopefully!) */
- #include <stdlib.h>
- #define P(x) x
- #else
- #define P(x) ()
- #define void char
- #endif
- /*
- * Linked list of variables, the only source for these is the command line
- * and the (optional) manifest constants.
- */
- struct varrec
- {
- struct varrec * next;
- int state;
- char name[1];
- }
- *varlist = 0;
- int cuttype = 0; /* 0 = use blank lines */
- /* 1 = use #lines */
- /* 2 = use '# 'oldtext */
- /* 3 = delete unused lines */
- int striphash = 0;
- int stripcomment = 0;
- char linebuf[2048];
- char * filename;
- int lineno;
- int prline;
- FILE * fd;
- int iflevel = 0;
- int keeptext = 1;
- int unknown_stat = 0;
- char * commentstr = "#";
- char names[16][32];
- char state[16];
- int main P((int argc, char ** argv));
- void Usage P((char * prog));
- void save_name P((char * varname, int state));
- void do_file P((char * fname));
- void set_line P((int lineno));
- int do_hashcom P((void));
- int do_ifdef P((char * p, int which));
- void check_name P((char * nm));
- void fatal P((char * msg));
- void manifest_constant P((void));
- int
- main(argc, argv)
- int argc;
- char ** argv;
- {
- int ar;
- char * ptr;
- if( argc <= 1 ) Usage(argv[0]);
- for(ar=1; ar<argc; ar++) if( argv[ar][0] == '-' )
- {
- if( argv[ar][1] == 'D' || argv[ar][1] == 'U' )
- {
- if( argv[ar][2] )
- save_name(argv[ar]+2, argv[ar][1]);
- else
- unknown_stat = argv[ar][1];
- }
- else if( argv[ar][1] == 'C' )
- {
- cuttype = 2;
- if( argv[ar][2] ) commentstr = argv[ar]+2;
- }
- else for(ptr=argv[ar]+1; *ptr; ptr++) switch(*ptr)
- {
- case 'b': cuttype = 0; break;
- case 'l': cuttype = 1; break;
- case 'C':
- case 'c': cuttype = 2; break;
- case 'r': cuttype = 3; break;
- case 'h': striphash=1; break;
- case 'M': manifest_constant(); break;
- case 'D': unknown_stat = 'D'; break;
- case 'U': unknown_stat = 'U'; break;
- default: Usage(argv[0]);
- }
- }
- else
- {
- do_file(argv[ar]);
- }
- exit(0);
- }
- void Usage(prog)
- char * prog;
- {
- fprintf(stderr, "Usage: %s [-DFLAG] [-UFLAG] [-blcrhMDU] [-C##] files\n",
- prog);
- fprintf(stderr, "\t-DFLAG\tDefine flag.\n");
- fprintf(stderr, "\t-UFLAG\tUndefine flag.\n");
- fprintf(stderr, "\t-C##\tComment out liines with '##'\n");
- fprintf(stderr, "\t-b\tRemove contents of lines leaving empty lines\n");
- fprintf(stderr, "\t-l\tUse #line lines.\n");
- fprintf(stderr, "\t-c\tComment out with '# '\n");
- fprintf(stderr, "\t-r\tRemove undefined lines completely.\n");
- fprintf(stderr, "\t-h\tRemove any line beginning with a '#'\n");
- fprintf(stderr, "\t-M\tInclude manifest constants.\n");
- fprintf(stderr, "\t-D\tAssume any unknown names are defined.\n");
- fprintf(stderr, "\t-U\tAssume any unknown names are undefined.\n");
- exit(1);
- }
- void
- save_name(varname, state)
- char * varname;
- int state;
- {
- struct varrec * curr;
- struct varrec * prev = 0;
- for(curr=varlist;
- curr && strcmp(curr->name, varname) != 0;
- prev=curr, curr=curr->next)
- ;
- if( curr == 0 )
- {
- curr = (struct varrec*) malloc(sizeof(struct varrec)+strlen(varname));
- if( curr == 0 )
- fatal("Out of memory error");
- if( prev ) prev->next = curr;
- else varlist = curr;
- curr->next = 0;
- strcpy(curr->name, varname);
- }
- curr->state = state;
- }
- void
- do_file(fname)
- char * fname;
- {
- filename = fname;
- prline = lineno = 0;
- fd = fopen(fname, "r");
- if( fd == 0 )
- fatal("Cannot open file");
- if( cuttype == 1 )
- printf("#line 1 \"%s\"\n", filename);
- /* NB: limited line length */
- while( fgets(linebuf, sizeof(linebuf), fd) != 0 )
- {
- int f = 1;
- char * p = linebuf;
- lineno++;
- while(isspace(*p)) p++;
- if( *p == '#' )
- f = do_hashcom();
- if(f)
- {
- if( keeptext )
- {
- if( cuttype == 1 ) set_line(lineno);
- printf("%s", linebuf);
- }
- else
- {
- if( cuttype == 0 ) printf("\n");
- if( cuttype == 2 ) printf("%s %s", commentstr, linebuf);
- }
- }
- }
- fclose(fd);
- if( iflevel != 0 ) fatal("Not enough endif's");
- }
- void
- set_line(lineno)
- int lineno;
- {
- if( prline+2 == lineno )
- printf("\n");
- else if( prline+1 != lineno )
- printf("#line %d \"%s\"\n", lineno, filename);
- prline = lineno;
- }
- int
- do_hashcom()
- {
- char * p = linebuf;
- int flg = -1;
- while(isspace(*p)) p++;
- if( *p == '#' ) p++;
- while(isspace(*p)) p++;
- if(strncmp(p, "ifdef", 5) == 0)
- {
- do_ifdef(p+5, 'D');
- }
- else
- if(strncmp(p, "ifndef", 6) == 0)
- {
- do_ifdef(p+6, 'U');
- }
- else
- if(strncmp(p, "if", 2) == 0 && isspace(p[2]) )
- {
- state[iflevel++] = keeptext;
- keeptext |= 2;
- }
- else
- if(strncmp(p, "else", 4) == 0)
- {
- if( iflevel == 0 ) fatal("#else at top level");
- if( iflevel && state[iflevel-1]) keeptext ^= 1;
- }
- else
- if(strncmp(p, "endif", 5) == 0)
- {
- flg = (keeptext&2);
- if( iflevel == 0 ) fatal("Too many endif's");
- iflevel--;
- keeptext = state[iflevel];
- }
- else if( !striphash ) return 1;
- if( flg < 0 ) flg = (keeptext&2);
- if( flg ) return 1;
- if( cuttype == 0 ) printf("\n");
- if( cuttype == 2 ) printf("%s %s", commentstr, linebuf);
- return 0;
- }
- int
- do_ifdef(p, which)
- char * p;
- int which;
- {
- char * nm;
- char * s;
- struct varrec * curr;
- while( *p == ' ' || *p == '\t') p++;
- nm = p;
- for(curr=varlist; curr ; curr = curr->next)
- {
- s = curr->name;
- p = nm;
- while( *p == *s ) { p++; s++; }
- if( *s == '\0' && *p <= ' ' ) /* FIXME alphanum */
- break;
- }
- state[iflevel] = keeptext;
- iflevel++;
- p=nm;
- s=names[iflevel];
- while(*p > ' ') *s++ = *p++;
- *s = '\0';
- if( curr == 0 )
- {
- if( unknown_stat == 0 )
- {
- if( keeptext ) keeptext |= 2;
- return 0;
- }
- if( keeptext )
- keeptext = (unknown_stat == which);
- return 1;
- }
- if( keeptext )
- keeptext = (curr->state == which);
- return 1;
- }
- #if 0
- do_if(p)
- char * p;
- {
- /*
- * Look for:
- * defined Label
- * one sort of || &&
- * 0
- * 1
- *
- * Skip characters: WS, (, )
- *
- * Give up on unknown characters and labels without a defined or assumed
- * state. BUT note that if there is another label that forces the state
- * of the result irrespective of an unknown label the state should be set.
- *
- */
- static char wbuf[256];
- int combiner = 0;
- int true_defs = 0;
- int false_defs = 0;
- int unkn_defs = 0;
- int state = 0;
- char * d;
- for(;;)
- {
- d=wbuf;
- do
- {
- while( isspace(*p) || (d==wbuf && (*p == '(' || *p == ')' ))) p++;
- if( d!=wbuf && (*p == '(' || *p == ')' )) break;
- while( !(isspace(*p) || *p == '(' || *p == ')' ))
- if( d<wbuf+sizeof(wbuf)-2) *d++ = *p++;
- else p++;
- *d= 0;
- }
- while( strcmp(wbuf, "!") == 0 );
- if( state == 0 )
- {
- if( strcmp(wbuf, "defined" ) == 0 )
- {
- state = 1;
- continue;
- }
- if( strcmp(wbuf, "!defined" ) == 0 )
- {
- state = 2;
- continue;
- }
- if( strcmp(wbuf, "||" ) == 0 || strcmp(wbuf, "&&") == 0 )
- {
- if( combiner == 0 ) combiner = wbuf[0];
- if( combiner != wbuf[0] ) combiner = '@';
- continue;
- }
- /* Something we're not ready for ... */
- goto Dont_know;
- }
- }
- }
- #endif
- void
- check_name(nm)
- char * nm;
- {
- char * p;
- char * s;
- while(*nm == ' ' || *nm == '\t' ) nm++;
- s = nm;
- if( *s == '\n' || *s == '\r' || *s == '\0' ) return;
- p = names[iflevel];
- while(*p)
- {
- if( *p++ != *s++ )
- goto x_error;
- }
- if( *s <= ' ' ) return;
- x_error:
- fprintf(stderr, "Ifdef mis-nesting Line %d Expect '%s' Got '",
- lineno,
- names[iflevel]);
- while(*nm > ' ' )
- fputc(*nm++, stderr);
- fputc('\'', stderr);
- fputc('\n', stderr);
- }
- void
- fatal(msg)
- char * msg;
- {
- fprintf(stderr, "Fatal error:%s\n", msg);
- exit(1);
- }
- /* This places manifest constants defined by the C compiler into ifdef
- *
- * Unfortunatly I can find no way of discovering the variables automatically
- */
- void
- manifest_constant()
- {
- /* General */
- #ifdef __STDC__
- save_name("__STDC__", 'D');
- #endif
- #ifdef __GNUC__
- save_name("__GNUC__", 'D');
- #endif
- #ifdef GNUMAKE
- save_name("GNUMAKE", 'D');
- #endif
- if( sizeof(int) < 4 )
- save_name("__SMALL_INTS__", 'D');
- if( sizeof(char *) <= 2 )
- save_name("__SMALL_MEMORY__", 'D');
- if( sizeof(long) == 4 )
- save_name("__LONG_32_BIT__", 'D');
- if( sizeof(long) == 8 )
- save_name("__LONG_64_BIT__", 'D');
- /* MSDOS */
- #ifdef MSDOS
- save_name("MSDOS", 'D');
- #endif
- #ifdef __MSDOS__
- save_name("__MSDOS__", 'D');
- #endif
- /* Linux/unix */
- #ifdef __linux__
- save_name("__linux__", 'D');
- #ifdef __i386__
- save_name("__elksemu_works__", 'D');
- #endif
- /* Is this true ? */
- #ifdef __x86_64__
- save_name("__elksemu_works__", 'D');
- #endif
- #endif
- #ifdef __unix__
- save_name("__unix__", 'D');
- #endif
- #ifdef __GNUC__
- save_name("__GNUC__", 'D');
- #endif
- #ifdef __ELF__
- save_name("__ELF__", 'D');
- #endif
- #ifdef __i386__
- save_name("__i386__", 'D');
- #endif
- #ifdef __i486__
- save_name("__i486__", 'D');
- #endif
- #ifdef i386
- save_name("i386", 'D');
- #endif
- #ifdef linux
- save_name("linux", 'D');
- #endif
- #ifdef unix
- save_name("unix", 'D');
- #endif
- /* BCC */
- #ifdef __BCC__
- save_name("__BCC__", 'D');
- #endif
- #ifdef __AS386_16__
- save_name("__AS386_16__", 'D');
- #endif
- #ifdef __AS386_32__
- save_name("__AS386_32__", 'D');
- #endif
- /* AIX, RS6000 */
- #ifdef _IBMR2
- save_name("_IBMR2", 'D');
- #endif
- #ifdef _AIX
- save_name("_AIX", 'D');
- #endif
- #ifdef _AIX32
- save_name("_AIX32", 'D');
- #endif
- /* Ugh! Minix is actually _very_ nasty */
- #ifdef __minix
- save_name("__minix", 'D');
- #endif
- /* This isn't much nicer */
- #ifdef __CYGWIN__
- save_name("__CYGWIN__", 'D');
- #endif
- #ifdef __APPLE__
- save_name("__APPLE__", 'D');
- #endif
- }
|