|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Dave Yost. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that: (1) source distributions retain this entire copyright ! 10: * notice and comment, and (2) distributions including binaries display ! 11: * the following acknowledgement: ``This product includes software ! 12: * developed by the University of California, Berkeley and its contributors'' ! 13: * in the documentation or other materials provided with the distribution ! 14: * and in all advertising materials mentioning features or use of this ! 15: * software. Neither the name of the University nor the names of its ! 16: * contributors may be used to endorse or promote products derived ! 17: * from this software without specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1985 The Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)unifdef.c 4.7 (Berkeley) 6/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: /* ! 34: * unifdef - remove ifdef'ed lines ! 35: * ! 36: * Warning: will not work correctly if input contains null characters. ! 37: * ! 38: * Wishlist: ! 39: * provide an option which will append the name of the ! 40: * appropriate symbol after #else's and #endif's ! 41: * provide an option which will check symbols after ! 42: * #else's and #endif's to see that they match their ! 43: * corresponding #ifdef or #ifndef ! 44: */ ! 45: ! 46: #include <stdio.h> ! 47: #include <ctype.h> ! 48: ! 49: #define BSS ! 50: FILE *input; ! 51: #ifndef YES ! 52: #define YES 1 ! 53: #define NO 0 ! 54: #endif/*YES */ ! 55: typedef int Bool; ! 56: ! 57: char *progname BSS; ! 58: char *filename BSS; ! 59: char text BSS; /* -t option in effect: this is a text file */ ! 60: char lnblank BSS; /* -l option in effect: blank deleted lines */ ! 61: char complement BSS; /* -c option in effect: complement the operation */ ! 62: ! 63: #define MAXSYMS 100 ! 64: char *symname[MAXSYMS] BSS; /* symbol name */ ! 65: char true[MAXSYMS] BSS; /* -Dsym */ ! 66: char ignore[MAXSYMS] BSS; /* -iDsym or -iUsym */ ! 67: char insym[MAXSYMS] BSS; /* state: false, inactive, true */ ! 68: #define SYM_INACTIVE 0 /* symbol is currently inactive */ ! 69: #define SYM_FALSE 1 /* symbol is currently false */ ! 70: #define SYM_TRUE 2 /* symbol is currently true */ ! 71: ! 72: char nsyms BSS; ! 73: char incomment BSS; /* inside C comment */ ! 74: ! 75: #define QUOTE_NONE 0 ! 76: #define QUOTE_SINGLE 1 ! 77: #define QUOTE_DOUBLE 2 ! 78: char inquote BSS; /* inside single or double quotes */ ! 79: ! 80: int exitstat BSS; ! 81: char *skipcomment (); ! 82: char *skipquote (); ! 83: ! 84: main (argc, argv) ! 85: int argc; ! 86: char **argv; ! 87: { ! 88: char **curarg; ! 89: register char *cp; ! 90: register char *cp1; ! 91: char ignorethis; ! 92: ! 93: progname = argv[0][0] ? argv[0] : "unifdef"; ! 94: ! 95: for (curarg = &argv[1]; --argc > 0; curarg++) { ! 96: if (*(cp1 = cp = *curarg) != '-') ! 97: break; ! 98: if (*++cp1 == 'i') { ! 99: ignorethis = YES; ! 100: cp1++; ! 101: } else ! 102: ignorethis = NO; ! 103: if ( ( *cp1 == 'D' ! 104: || *cp1 == 'U' ! 105: ) ! 106: && cp1[1] != '\0' ! 107: ) { ! 108: register int symind; ! 109: ! 110: if ((symind = findsym (&cp1[1])) < 0) { ! 111: if (nsyms >= MAXSYMS) { ! 112: prname (); ! 113: fprintf (stderr, "too many symbols.\n"); ! 114: exit (2); ! 115: } ! 116: symind = nsyms++; ! 117: symname[symind] = &cp1[1]; ! 118: insym[symind] = SYM_INACTIVE; ! 119: } ! 120: ignore[symind] = ignorethis; ! 121: true[symind] = *cp1 == 'D' ? YES : NO; ! 122: } else if (ignorethis) ! 123: goto unrec; ! 124: else if (strcmp (&cp[1], "t") == 0) ! 125: text = YES; ! 126: else if (strcmp (&cp[1], "l") == 0) ! 127: lnblank = YES; ! 128: else if (strcmp (&cp[1], "c") == 0) ! 129: complement = YES; ! 130: else { ! 131: unrec: ! 132: prname (); ! 133: fprintf (stderr, "unrecognized option: %s\n", cp); ! 134: goto usage; ! 135: } ! 136: } ! 137: if (nsyms == 0) { ! 138: usage: ! 139: fprintf (stderr, "\ ! 140: Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-iDsym] [-iUsym]]... [file]\n\ ! 141: At least one arg from [-D -U -iD -iU] is required\n", progname); ! 142: exit (2); ! 143: } ! 144: ! 145: if (argc > 1) { ! 146: prname (); ! 147: fprintf (stderr, "can only do one file.\n"); ! 148: } else if (argc == 1) { ! 149: filename = *curarg; ! 150: if ((input = fopen (filename, "r")) != NULL) { ! 151: pfile(); ! 152: (void) fclose (input); ! 153: } else { ! 154: prname (); ! 155: fprintf (stderr, "can't open "); ! 156: perror(*curarg); ! 157: } ! 158: } else { ! 159: filename = "[stdin]"; ! 160: input = stdin; ! 161: pfile(); ! 162: } ! 163: ! 164: (void) fflush (stdout); ! 165: exit (exitstat); ! 166: } ! 167: ! 168: /* types of input lines: */ ! 169: typedef int Linetype; ! 170: #define LT_PLAIN 0 /* ordinary line */ ! 171: #define LT_TRUE 1 /* a true #ifdef of a symbol known to us */ ! 172: #define LT_FALSE 2 /* a false #ifdef of a symbol known to us */ ! 173: #define LT_OTHER 3 /* an #ifdef of a symbol not known to us */ ! 174: #define LT_IF 4 /* an #ifdef of a symbol not known to us */ ! 175: #define LT_ELSE 5 /* #else */ ! 176: #define LT_ENDIF 6 /* #endif */ ! 177: #define LT_LEOF 7 /* end of file */ ! 178: extern Linetype checkline (); ! 179: ! 180: typedef int Reject_level; ! 181: Reject_level reject BSS; /* 0 or 1: pass thru; 1 or 2: ignore comments */ ! 182: #define REJ_NO 0 ! 183: #define REJ_IGNORE 1 ! 184: #define REJ_YES 2 ! 185: ! 186: int linenum BSS; /* current line number */ ! 187: int stqcline BSS; /* start of current coment or quote */ ! 188: char *errs[] = { ! 189: #define NO_ERR 0 ! 190: "", ! 191: #define END_ERR 1 ! 192: "", ! 193: #define ELSE_ERR 2 ! 194: "Inappropriate else", ! 195: #define ENDIF_ERR 3 ! 196: "Inappropriate endif", ! 197: #define IEOF_ERR 4 ! 198: "Premature EOF in ifdef", ! 199: #define CEOF_ERR 5 ! 200: "Premature EOF in comment", ! 201: #define Q1EOF_ERR 6 ! 202: "Premature EOF in quoted character", ! 203: #define Q2EOF_ERR 7 ! 204: "Premature EOF in quoted string" ! 205: }; ! 206: ! 207: /* States for inif arg to doif */ ! 208: #define IN_NONE 0 ! 209: #define IN_IF 1 ! 210: #define IN_ELSE 2 ! 211: ! 212: pfile () ! 213: { ! 214: reject = REJ_NO; ! 215: (void) doif (-1, IN_NONE, reject, 0); ! 216: return; ! 217: } ! 218: ! 219: int ! 220: doif (thissym, inif, prevreject, depth) ! 221: register int thissym; /* index of the symbol who was last ifdef'ed */ ! 222: int inif; /* YES or NO we are inside an ifdef */ ! 223: Reject_level prevreject;/* previous value of reject */ ! 224: int depth; /* depth of ifdef's */ ! 225: { ! 226: register Linetype lineval; ! 227: register Reject_level thisreject; ! 228: int doret; /* tmp return value of doif */ ! 229: int cursym; /* index of the symbol returned by checkline */ ! 230: int stline; /* line number when called this time */ ! 231: ! 232: stline = linenum; ! 233: for (;;) { ! 234: switch (lineval = checkline (&cursym)) { ! 235: case LT_PLAIN: ! 236: flushline (YES); ! 237: break; ! 238: ! 239: case LT_TRUE: ! 240: case LT_FALSE: ! 241: thisreject = reject; ! 242: if (lineval == LT_TRUE) ! 243: insym[cursym] = SYM_TRUE; ! 244: else { ! 245: if (reject != REJ_YES) ! 246: reject = ignore[cursym] ? REJ_IGNORE : REJ_YES; ! 247: insym[cursym] = SYM_FALSE; ! 248: } ! 249: if (ignore[cursym]) ! 250: flushline (YES); ! 251: else { ! 252: exitstat = 1; ! 253: flushline (NO); ! 254: } ! 255: if ((doret = doif (cursym, IN_IF, thisreject, depth + 1)) != NO_ERR) ! 256: return error (doret, stline, depth); ! 257: break; ! 258: ! 259: case LT_IF: ! 260: case LT_OTHER: ! 261: flushline (YES); ! 262: if ((doret = doif (-1, IN_IF, reject, depth + 1)) != NO_ERR) ! 263: return error (doret, stline, depth); ! 264: break; ! 265: ! 266: case LT_ELSE: ! 267: if (inif != IN_IF) ! 268: return error (ELSE_ERR, linenum, depth); ! 269: inif = IN_ELSE; ! 270: if (thissym >= 0) { ! 271: if (insym[thissym] == SYM_TRUE) { ! 272: reject = ignore[thissym] ? REJ_IGNORE : REJ_YES; ! 273: insym[thissym] = SYM_FALSE; ! 274: } else { /* (insym[thissym] == SYM_FALSE) */ ! 275: reject = prevreject; ! 276: insym[thissym] = SYM_TRUE; ! 277: } ! 278: if (!ignore[thissym]) { ! 279: flushline (NO); ! 280: break; ! 281: } ! 282: } ! 283: flushline (YES); ! 284: break; ! 285: ! 286: case LT_ENDIF: ! 287: if (inif == IN_NONE) ! 288: return error (ENDIF_ERR, linenum, depth); ! 289: if (thissym >= 0) { ! 290: insym[thissym] = SYM_INACTIVE; ! 291: reject = prevreject; ! 292: if (!ignore[thissym]) { ! 293: flushline (NO); ! 294: return NO_ERR; ! 295: } ! 296: } ! 297: flushline (YES); ! 298: return NO_ERR; ! 299: ! 300: case LT_LEOF: { ! 301: int err; ! 302: err = incomment ! 303: ? CEOF_ERR ! 304: : inquote == QUOTE_SINGLE ! 305: ? Q1EOF_ERR ! 306: : inquote == QUOTE_DOUBLE ! 307: ? Q2EOF_ERR ! 308: : NO_ERR; ! 309: if (inif != IN_NONE) { ! 310: if (err != NO_ERR) ! 311: (void) error (err, stqcline, depth); ! 312: return error (IEOF_ERR, stline, depth); ! 313: } else if (err != NO_ERR) ! 314: return error (err, stqcline, depth); ! 315: else ! 316: return NO_ERR; ! 317: } ! 318: } ! 319: } ! 320: } ! 321: ! 322: #define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_') ! 323: ! 324: #define MAXLINE 256 ! 325: char tline[MAXLINE] BSS; ! 326: ! 327: Linetype ! 328: checkline (cursym) ! 329: int *cursym; /* if LT_TRUE or LT_FALSE returned, set this to sym index */ ! 330: { ! 331: register char *cp; ! 332: register char *symp; ! 333: char *scp; ! 334: Linetype retval; ! 335: # define KWSIZE 8 ! 336: char keyword[KWSIZE]; ! 337: ! 338: linenum++; ! 339: if (getlin (tline, sizeof tline, input, NO) == EOF) ! 340: return LT_LEOF; ! 341: ! 342: retval = LT_PLAIN; ! 343: if ( *(cp = tline) != '#' ! 344: || incomment ! 345: || inquote == QUOTE_SINGLE ! 346: || inquote == QUOTE_DOUBLE ! 347: ) ! 348: goto eol; ! 349: ! 350: cp = skipcomment (++cp); ! 351: symp = keyword; ! 352: while (!endsym (*cp)) { ! 353: *symp = *cp++; ! 354: if (++symp >= &keyword[KWSIZE]) ! 355: goto eol; ! 356: } ! 357: *symp = '\0'; ! 358: ! 359: if (strcmp (keyword, "ifdef") == 0) { ! 360: retval = YES; ! 361: goto ifdef; ! 362: } else if (strcmp (keyword, "ifndef") == 0) { ! 363: retval = NO; ! 364: ifdef: ! 365: scp = cp = skipcomment (++cp); ! 366: if (incomment) { ! 367: retval = LT_PLAIN; ! 368: goto eol; ! 369: } ! 370: { ! 371: int symind; ! 372: ! 373: if ((symind = findsym (scp)) >= 0) ! 374: retval = (retval ^ true[*cursym = symind]) ! 375: ? LT_FALSE : LT_TRUE; ! 376: else ! 377: retval = LT_OTHER; ! 378: } ! 379: } else if (strcmp (keyword, "if") == 0) ! 380: retval = LT_IF; ! 381: else if (strcmp (keyword, "else") == 0) ! 382: retval = LT_ELSE; ! 383: else if (strcmp (keyword, "endif") == 0) ! 384: retval = LT_ENDIF; ! 385: ! 386: eol: ! 387: if (!text && reject != REJ_IGNORE) ! 388: for (; *cp; ) { ! 389: if (incomment) ! 390: cp = skipcomment (cp); ! 391: else if (inquote == QUOTE_SINGLE) ! 392: cp = skipquote (cp, QUOTE_SINGLE); ! 393: else if (inquote == QUOTE_DOUBLE) ! 394: cp = skipquote (cp, QUOTE_DOUBLE); ! 395: else if (*cp == '/' && cp[1] == '*') ! 396: cp = skipcomment (cp); ! 397: else if (*cp == '\'') ! 398: cp = skipquote (cp, QUOTE_SINGLE); ! 399: else if (*cp == '"') ! 400: cp = skipquote (cp, QUOTE_DOUBLE); ! 401: else ! 402: cp++; ! 403: } ! 404: return retval; ! 405: } ! 406: ! 407: /* ! 408: * Skip over comments and stop at the next charaacter ! 409: * position that is not whitespace. ! 410: */ ! 411: char * ! 412: skipcomment (cp) ! 413: register char *cp; ! 414: { ! 415: if (incomment) ! 416: goto inside; ! 417: for (;; cp++) { ! 418: while (*cp == ' ' || *cp == '\t') ! 419: cp++; ! 420: if (text) ! 421: return cp; ! 422: if ( cp[0] != '/' ! 423: || cp[1] != '*' ! 424: ) ! 425: return cp; ! 426: cp += 2; ! 427: if (!incomment) { ! 428: incomment = YES; ! 429: stqcline = linenum; ! 430: } ! 431: inside: ! 432: for (;;) { ! 433: for (; *cp != '*'; cp++) ! 434: if (*cp == '\0') ! 435: return cp; ! 436: if (*++cp == '/') { ! 437: incomment = NO; ! 438: break; ! 439: } ! 440: } ! 441: } ! 442: } ! 443: ! 444: /* ! 445: * Skip over a quoted string or character and stop at the next charaacter ! 446: * position that is not whitespace. ! 447: */ ! 448: char * ! 449: skipquote (cp, type) ! 450: register char *cp; ! 451: register int type; ! 452: { ! 453: register char qchar; ! 454: ! 455: qchar = type == QUOTE_SINGLE ? '\'' : '"'; ! 456: ! 457: if (inquote == type) ! 458: goto inside; ! 459: for (;; cp++) { ! 460: if (*cp != qchar) ! 461: return cp; ! 462: cp++; ! 463: inquote = type; ! 464: stqcline = linenum; ! 465: inside: ! 466: for (; ; cp++) { ! 467: if (*cp == qchar) ! 468: break; ! 469: if ( *cp == '\0' ! 470: || *cp == '\\' && *++cp == '\0' ! 471: ) ! 472: return cp; ! 473: } ! 474: inquote = QUOTE_NONE; ! 475: } ! 476: } ! 477: ! 478: /* ! 479: * findsym - look for the symbol in the symbol table. ! 480: * if found, return symbol table index, ! 481: * else return -1. ! 482: */ ! 483: int ! 484: findsym (str) ! 485: char *str; ! 486: { ! 487: register char *cp; ! 488: register char *symp; ! 489: register int symind; ! 490: register char chr; ! 491: ! 492: for (symind = 0; symind < nsyms; ++symind) { ! 493: if (insym[symind] == SYM_INACTIVE) { ! 494: for ( symp = symname[symind], cp = str ! 495: ; *symp && *cp == *symp ! 496: ; cp++, symp++ ! 497: ) ! 498: continue; ! 499: chr = *cp; ! 500: if (*symp == '\0' && endsym (chr)) ! 501: return symind; ! 502: } ! 503: } ! 504: return -1; ! 505: } ! 506: ! 507: /* ! 508: * getlin - expands tabs if asked for ! 509: * and (if compiled in) treats form-feed as an end-of-line ! 510: */ ! 511: int ! 512: getlin (line, maxline, inp, expandtabs) ! 513: register char *line; ! 514: int maxline; ! 515: FILE *inp; ! 516: int expandtabs; ! 517: { ! 518: int tmp; ! 519: register int num; ! 520: register int chr; ! 521: #ifdef FFSPECIAL ! 522: static char havechar = NO; /* have leftover char from last time */ ! 523: static char svchar BSS; ! 524: #endif/*FFSPECIAL */ ! 525: ! 526: num = 0; ! 527: #ifdef FFSPECIAL ! 528: if (havechar) { ! 529: havechar = NO; ! 530: chr = svchar; ! 531: goto ent; ! 532: } ! 533: #endif/*FFSPECIAL */ ! 534: while (num + 8 < maxline) { /* leave room for tab */ ! 535: chr = getc (inp); ! 536: if (isprint (chr)) { ! 537: #ifdef FFSPECIAL ! 538: ent: ! 539: #endif/*FFSPECIAL */ ! 540: *line++ = chr; ! 541: num++; ! 542: } else ! 543: switch (chr) { ! 544: case EOF: ! 545: return EOF; ! 546: ! 547: case '\t': ! 548: if (expandtabs) { ! 549: num += tmp = 8 - (num & 7); ! 550: do ! 551: *line++ = ' '; ! 552: while (--tmp); ! 553: break; ! 554: } ! 555: default: ! 556: *line++ = chr; ! 557: num++; ! 558: break; ! 559: ! 560: case '\n': ! 561: *line = '\n'; ! 562: num++; ! 563: goto end; ! 564: ! 565: #ifdef FFSPECIAL ! 566: case '\f': ! 567: if (++num == 1) ! 568: *line = '\f'; ! 569: else { ! 570: *line = '\n'; ! 571: havechar = YES; ! 572: svchar = chr; ! 573: } ! 574: goto end; ! 575: #endif/*FFSPECIAL */ ! 576: } ! 577: } ! 578: end: ! 579: *++line = '\0'; ! 580: return num; ! 581: } ! 582: ! 583: flushline (keep) ! 584: Bool keep; ! 585: { ! 586: if ((keep && reject != REJ_YES) ^ complement) { ! 587: register char *line = tline; ! 588: register FILE *out = stdout; ! 589: register char chr; ! 590: ! 591: while (chr = *line++) ! 592: putc (chr, out); ! 593: } else if (lnblank) ! 594: putc ('\n', stdout); ! 595: return; ! 596: } ! 597: ! 598: prname () ! 599: { ! 600: fprintf (stderr, "%s: ", progname); ! 601: return; ! 602: } ! 603: ! 604: int ! 605: error (err, line, depth) ! 606: int err; /* type of error & index into error string array */ ! 607: int line; /* line number */ ! 608: int depth; /* how many ifdefs we are inside */ ! 609: { ! 610: if (err == END_ERR) ! 611: return err; ! 612: ! 613: prname (); ! 614: ! 615: #ifndef TESTING ! 616: fprintf (stderr, "Error in %s line %d: %s.\n", filename, line, errs[err]); ! 617: #else/* TESTING */ ! 618: fprintf (stderr, "Error in %s line %d: %s. ", filename, line, errs[err]); ! 619: fprintf (stderr, "ifdef depth: %d\n", depth); ! 620: #endif/*TESTING */ ! 621: ! 622: exitstat = 2; ! 623: return depth > 1 ? IEOF_ERR : END_ERR; ! 624: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.