1: #ifndef lint
   2: static char sccsid[] = "@(#)unifdef.c	4.4 (Berkeley) 8/11/83";
   3: #endif
   4: 
   5: /*
   6:  * unifdef - remove ifdef'ed lines
   7:  */
   8: 
   9: #include <stdio.h>
  10: #include <ctype.h>
  11: #define BSS
  12: FILE *input;
  13: #ifndef YES
  14: #define YES 1
  15: #define NO  0
  16: #endif
  17: 
  18: char *progname BSS;
  19: char *filename BSS;
  20: char text BSS;          /* -t option in effect: this is a text file */
  21: char lnblank BSS;       /* -l option in effect: blank deleted lines */
  22: char complement BSS;    /* -c option in effect: complement the operation */
  23: #define MAXSYMS 100
  24: char true[MAXSYMS] BSS;
  25: char ignore[MAXSYMS] BSS;
  26: char *sym[MAXSYMS] BSS;
  27: char insym[MAXSYMS] BSS;
  28: char nsyms BSS;
  29: char incomment BSS;
  30: #define QUOTE1 0
  31: #define QUOTE2 1
  32: char inquote[2] BSS;
  33: int exitstat BSS;
  34: char *skipcomment ();
  35: char *skipquote ();
  36: 
  37: main (argc, argv)
  38: int argc;
  39: char **argv;
  40: {
  41:     char **curarg;
  42:     register char *cp;
  43:     register char *cp1;
  44:     char ignorethis;
  45: 
  46:     progname = argv[0][0] ? argv[0] : "unifdef";
  47: 
  48:     for (curarg = &argv[1]; --argc > 0; curarg++) {
  49:     if (*(cp1 = cp = *curarg) != '-')
  50:         break;
  51:     if (*++cp1 == 'i') {
  52:         ignorethis = YES;
  53:         cp1++;
  54:     }
  55:     else
  56:         ignorethis = NO;
  57:     if (   (   *cp1 == 'D'
  58:         || *cp1 == 'U'
  59:            )
  60:         && cp1[1] != '\0'
  61:        ) {
  62:         if (nsyms >= MAXSYMS) {
  63:         prname ();
  64:         fprintf (stderr, "too many symbols.\n");
  65:         exit (2);
  66:         }
  67:         ignore[nsyms] = ignorethis;
  68:         true[nsyms] = *cp1 == 'D' ? YES : NO;
  69:         sym[nsyms++] = &cp1[1];
  70:     }
  71:     else if (ignorethis)
  72:         goto unrec;
  73:     else if (strcmp (&cp[1], "t") == 0)
  74:         text = YES;
  75:     else if (strcmp (&cp[1], "l") == 0)
  76:         lnblank = YES;
  77:     else if (strcmp (&cp[1], "c") == 0)
  78:         complement = YES;
  79:     else {
  80:  unrec:
  81:         prname ();
  82:         fprintf (stderr, "unrecognized option: %s\n", cp);
  83:         goto usage;
  84:     }
  85:     }
  86:     if (nsyms == 0) {
  87:  usage:
  88:     fprintf (stderr, "\
  89: Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-idsym] [-iusym]]... [file]\n\
  90:     At least one arg from [-D -U -id -iu] is required\n", progname);
  91:     exit (2);
  92:     }
  93: 
  94:     if (argc > 1) {
  95:     prname ();
  96:     fprintf (stderr, "can only do one file.\n");
  97:     }
  98:     else if (argc == 1) {
  99:     filename = *curarg;
 100:     if ((input = fopen (filename, "r")) != NULL) {
 101:         pfile();
 102:         fclose (input);
 103:     }
 104:     else {
 105:         prname ();
 106:         perror(*curarg);
 107:     }
 108:     }
 109:     else {
 110:     filename = "[stdin]";
 111:     input = stdin;
 112:     pfile();
 113:     }
 114: 
 115:     fflush (stdout);
 116:     exit (exitstat);
 117: }
 118: 
 119: /* types of input lines: */
 120: #define PLAIN       0   /* ordinary line */
 121: #define TRUE        1   /* a true  #ifdef of a symbol known to us */
 122: #define FALSE       2   /* a false #ifdef of a symbol known to us */
 123: #define OTHER       3   /* an #ifdef of a symbol not known to us */
 124: #define ELSE        4   /* #else */
 125: #define ENDIF       5   /* #endif */
 126: #define LEOF        6   /* end of file */
 127: 
 128: char reject BSS;    /* 0 or 1: pass thru; 1 or 2: ignore comments */
 129: int linenum BSS;    /* current line number */
 130: int stqcline BSS;   /* start of current coment or quote */
 131: char *errs[] = {
 132: #define NO_ERR      0
 133:             "",
 134: #define END_ERR     1
 135:             "",
 136: #define ELSE_ERR    2
 137:             "Inappropriate else",
 138: #define ENDIF_ERR   3
 139:             "Inappropriate endif",
 140: #define IEOF_ERR    4
 141:             "Premature EOF in ifdef",
 142: #define CEOF_ERR    5
 143:             "Premature EOF in comment",
 144: #define Q1EOF_ERR   6
 145:             "Premature EOF in quoted character",
 146: #define Q2EOF_ERR   7
 147:             "Premature EOF in quoted string"
 148: };
 149: 
 150: pfile ()
 151: {
 152:     reject = 0;
 153:     doif (-1, NO, reject, 0);
 154:     return;
 155: }
 156: 
 157: doif (thissym, inif, prevreject, depth)
 158: register int thissym;   /* index of the symbol who was last ifdef'ed */
 159: int inif;               /* YES or NO we are inside an ifdef */
 160: int prevreject;         /* previous value of reject */
 161: int depth;              /* depth of ifdef's */
 162: {
 163:     register int lineval;
 164:     register int thisreject;
 165:     int doret;          /* tmp return valud]e of doif */
 166:     int cursym;         /* index of the symbol returned by checkline */
 167:     int stline;         /* line number when called this time */
 168: 
 169:     stline = linenum;
 170:     for (;;) {
 171:     switch (lineval = checkline (&cursym)) {
 172:     case PLAIN:
 173:         flushline (YES);
 174:         break;
 175: 
 176:     case TRUE:
 177:     case FALSE:
 178:         thisreject = reject;
 179:         if (lineval == TRUE)
 180:         insym[cursym] = 1;
 181:         else {
 182:         if (reject < 2)
 183:             reject = ignore[cursym] ? 1 : 2;
 184:         insym[cursym] = -1;
 185:         }
 186:         if (ignore[cursym])
 187:         flushline (YES);
 188:         else {
 189:         exitstat = 1;
 190:         flushline (NO);
 191:         }
 192:         if ((doret = doif (cursym, YES, thisreject, depth + 1)) != NO_ERR)
 193:         return error (doret, stline, depth);
 194:             break;
 195: 
 196:     case OTHER:
 197:         flushline (YES);
 198:         if ((doret = doif (-1, YES, reject, depth + 1)) != NO_ERR)
 199:         return error (doret, stline, depth);
 200:         break;
 201: 
 202:     case ELSE:
 203:         if (inif != 1)
 204:         return error (ELSE_ERR, linenum, depth);
 205:         inif = 2;
 206:         if (thissym >= 0) {
 207:         if ((insym[thissym] = -insym[thissym]) < 0)
 208:             reject = ignore[thissym] ? 1 : 2;
 209:         else
 210:             reject = prevreject;
 211:         if (!ignore[thissym]) {
 212:             flushline (NO);
 213:             break;
 214:         }
 215:         }
 216:         flushline (YES);
 217:         break;
 218: 
 219:     case ENDIF:
 220:         if (inif == 0)
 221:         return error (ENDIF_ERR, linenum, depth);
 222:         if (thissym >= 0) {
 223:         insym[thissym] = 0;
 224:         reject = prevreject;
 225:         if (!ignore[thissym]) {
 226:             flushline (NO);
 227:             return NO_ERR;
 228:         }
 229:         }
 230:         flushline (YES);
 231:         return NO_ERR;
 232: 
 233:     case LEOF: {
 234:         int err;
 235:         err =   incomment
 236:           ? CEOF_ERR
 237:           : inquote[QUOTE1]
 238:           ? Q1EOF_ERR
 239:           : inquote[QUOTE2]
 240:           ? Q2EOF_ERR
 241:           : NO_ERR;
 242:         if (inif) {
 243:         if (err != NO_ERR)
 244:             error (err, stqcline, depth);
 245:         return error (IEOF_ERR, stline, depth);
 246:         }
 247:         else if (err != NO_ERR)
 248:         return error (err, stqcline, depth);
 249:         else
 250:         return NO_ERR;
 251:         }
 252:     }
 253:     }
 254: }
 255: 
 256: #define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_')
 257: 
 258: #define MAXLINE 256
 259: char tline[MAXLINE] BSS;
 260: 
 261: checkline (cursym)
 262: int *cursym;
 263: {
 264:     register char *cp;
 265:     register char *symp;
 266:     register char chr;
 267:     char *scp;
 268:     int retval;
 269:     int symind;
 270: #   define KWSIZE 8
 271:     char keyword[KWSIZE];
 272: 
 273:     linenum++;
 274:     if (getlin (tline, sizeof tline, input, NO) == EOF)
 275:         return LEOF;
 276: 
 277:     retval = PLAIN;
 278:     if (   *(cp = tline) != '#'
 279:     || incomment
 280:     || inquote[QUOTE1]
 281:     || inquote[QUOTE2]
 282:        )
 283:     goto eol;
 284: 
 285:     cp = skipcomment (++cp);
 286:     symp = keyword;
 287:     while (!endsym (*cp)) {
 288:     *symp = *cp++;
 289:     if (++symp >= &keyword[KWSIZE])
 290:         goto eol;
 291:     }
 292:     *symp = '\0';
 293: 
 294:     if (strcmp (keyword, "ifdef") == 0) {
 295:     retval = YES;
 296:     goto ifdef;
 297:     }
 298:     else if (strcmp (keyword, "ifndef") == 0) {
 299:     retval = NO;
 300:  ifdef:
 301:     scp = cp = skipcomment (++cp);
 302:     if (incomment) {
 303:         retval = PLAIN;
 304:         goto eol;
 305:     }
 306:     for (symind = 0; ; ) {
 307:         if (insym[symind] == 0) {
 308:         for ( symp = sym[symind], cp = scp
 309:             ; *symp && *cp == *symp
 310:             ; cp++, symp++
 311:             )
 312:             {}
 313:         chr = *cp;
 314:         if (*symp == '\0' && endsym (chr)) {
 315:             *cursym = symind;
 316:             retval = (retval ^ true[symind]) ? FALSE : TRUE;
 317:             break;
 318:         }
 319:         }
 320:         if (++symind >= nsyms) {
 321:         retval = OTHER;
 322:         break;
 323:         }
 324:     }
 325:     }
 326:     else if (strcmp (keyword, "if") == 0)
 327:     retval = OTHER;
 328:     else if (strcmp (keyword, "else") == 0)
 329:     retval = ELSE;
 330:     else if (strcmp (keyword, "endif") == 0)
 331:     retval = ENDIF;
 332: 
 333:  eol:
 334:     if (!text && !reject)
 335:     for (; *cp; ) {
 336:         if (incomment)
 337:         cp = skipcomment (cp);
 338:         else if (inquote[QUOTE1])
 339:         cp = skipquote (cp, QUOTE1);
 340:         else if (inquote[QUOTE2])
 341:         cp = skipquote (cp, QUOTE2);
 342:         else if (*cp == '/' && cp[1] == '*')
 343:         cp = skipcomment (cp);
 344:         else if (*cp == '\'')
 345:         cp = skipquote (cp, QUOTE1);
 346:         else if (*cp == '"')
 347:         cp = skipquote (cp, QUOTE2);
 348:         else
 349:         cp++;
 350:     }
 351:     return retval;
 352: }
 353: 
 354: /*  Skip over comments and stop at the next charaacter
 355: /*  position that is not whitespace.
 356: /**/
 357: char *
 358: skipcomment (cp)
 359: register char *cp;
 360: {
 361:     if (incomment)
 362:     goto inside;
 363:     for (;; cp++) {
 364:         while (*cp == ' ' || *cp == '\t')
 365:             cp++;
 366:     if (text)
 367:             return cp;
 368:     if (   cp[0] != '/'
 369:         || cp[1] != '*'
 370:        )
 371:             return cp;
 372:     cp += 2;
 373:     if (!incomment) {
 374:         incomment = YES;
 375:         stqcline = linenum;
 376:     }
 377:  inside:
 378:     for (;;) {
 379:         for (; *cp != '*'; cp++)
 380:         if (*cp == '\0')
 381:             return cp;
 382:         if (*++cp == '/')
 383:         break;
 384:     }
 385:     incomment = NO;
 386:     }
 387: }
 388: 
 389: /*  Skip over a quoted string or character and stop at the next charaacter
 390: /*  position that is not whitespace.
 391: /**/
 392: char *
 393: skipquote (cp, type)
 394: register char *cp;
 395: register int type;
 396: {
 397:     register char qchar;
 398: 
 399:     qchar = type == QUOTE1 ? '\'' : '"';
 400: 
 401:     if (inquote[type])
 402:     goto inside;
 403:     for (;; cp++) {
 404:     if (*cp != qchar)
 405:         return cp;
 406:     cp++;
 407:     if (!inquote[type]) {
 408:         inquote[type] = YES;
 409:         stqcline = linenum;
 410:     }
 411:  inside:
 412:     for (; ; cp++) {
 413:         if (*cp == qchar)
 414:         break;
 415:         if (   *cp == '\0'
 416:         || *cp == '\\'
 417:         && *++cp == '\0'
 418:            )
 419:         return cp;
 420:     }
 421:     inquote[type] = NO;
 422:     }
 423: }
 424: 
 425: /*
 426: /*   special getlin - treats form-feed as an end-of-line
 427: /*                    and expands tabs if asked for
 428: /*
 429: /**/
 430: getlin (line, maxline, inp, expandtabs)
 431: register char *line;
 432: int maxline;
 433: FILE *inp;
 434: int expandtabs;
 435: {
 436:     int tmp;
 437:     register int num;
 438:     register int chr;
 439: #ifdef FFSPECIAL
 440:     static char havechar = NO;  /* have leftover char from last time */
 441:     static char svchar BSS;
 442: #endif
 443: 
 444:     num = 0;
 445: #ifdef FFSPECIAL
 446:     if (havechar) {
 447:     havechar = NO;
 448:     chr = svchar;
 449:     goto ent;
 450:     }
 451: #endif
 452:     while (num + 8 < maxline) {   /* leave room for tab */
 453:         chr = getc (inp);
 454:     if (isprint (chr)) {
 455: #ifdef FFSPECIAL
 456:  ent:
 457: #endif
 458:         *line++ = chr;
 459:         num++;
 460:     }
 461:     else
 462:         switch (chr) {
 463:         case EOF:
 464:         return EOF;
 465: 
 466:         case '\t':
 467:         if (expandtabs) {
 468:             num += tmp = 8 - (num & 7);
 469:             do
 470:             *line++ = ' ';
 471:             while (--tmp);
 472:             break;
 473:         }
 474:             default:
 475:                 *line++ = chr;
 476:                 num++;
 477:         break;
 478: 
 479:         case '\n':
 480:                 *line = '\n';
 481:                 num++;
 482:                 goto end;
 483: 
 484: #ifdef FFSPECIAL
 485:         case '\f':
 486:         if (++num == 1)
 487:             *line = '\f';
 488:         else {
 489:             *line = '\n';
 490:             havechar = YES;
 491:                     svchar = chr;
 492:                 }
 493:                 goto end;
 494: #endif
 495:         }
 496:     }
 497:  end:
 498:     *++line = '\0';
 499:     return num;
 500: }
 501: 
 502: flushline (keep)
 503: {
 504:     if ((keep && reject < 2) ^ complement)
 505:     putlin (tline, stdout);
 506:     else if (lnblank)
 507:     putlin ("\n", stdout);
 508:     return;
 509: }
 510: 
 511: /*
 512: /*  putlin - for tools
 513: /*
 514: /**/
 515: putlin (line, fio)
 516: register char *line;
 517: register FILE *fio;
 518: {
 519:     register char chr;
 520: 
 521:     while (chr = *line++)
 522:     putc (chr, fio);
 523:     return;
 524: }
 525: 
 526: prname ()
 527: {
 528:     fprintf (stderr, "%s: ", progname);
 529:     return;
 530: }
 531: 
 532: 
 533: error (err, line, depth)
 534: {
 535:     if (err == END_ERR)
 536:     return err;
 537: 
 538:     prname ();
 539: 
 540: #ifndef TESTING
 541:     fprintf (stderr, "Error in %s line %d: %s.\n",
 542:          filename, line, errs[err]);
 543: #endif
 544: 
 545: #ifdef TESTING
 546:     fprintf (stderr, "Error in %s line %d: %s. ",
 547:          filename, line, errs[err]);
 548:     fprintf (stderr, "ifdef depth: %d\n", depth);
 549: #endif
 550: 
 551:     exitstat = 2;
 552:     return depth > 1 ? IEOF_ERR : END_ERR;
 553: }

Defined functions

checkline defined in line 261; used 1 times
doif defined in line 157; used 3 times
error defined in line 533; used 8 times
flushline defined in line 502; used 8 times
getlin defined in line 430; used 1 times
main defined in line 37; never used
pfile defined in line 150; used 2 times
prname defined in line 526; used 5 times
putlin defined in line 515; used 2 times
skipcomment defined in line 357; used 5 times
skipquote defined in line 392; used 5 times

Defined variables

BSS defined in line 259; never used
complement defined in line 22; used 2 times
errs defined in line 131; used 2 times
exitstat defined in line 33; used 3 times
filename defined in line 19; used 5 times
ignore defined in line 25; used 6 times
incomment defined in line 29; used 8 times
inquote defined in line 32; used 10 times
insym defined in line 27; used 6 times
linenum defined in line 129; used 6 times
lnblank defined in line 21; used 2 times
nsyms defined in line 28; used 6 times
progname defined in line 18; used 3 times
reject defined in line 128; used 11 times
sccsid defined in line 2; never used
stqcline defined in line 130; used 4 times
sym defined in line 26; used 2 times
text defined in line 20; used 3 times
tline defined in line 259; used 4 times
true defined in line 24; used 2 times

Defined macros

BSS defined in line 11; used 1 times
CEOF_ERR defined in line 142; used 1 times
ELSE defined in line 124; used 1 times
ELSE_ERR defined in line 136; used 1 times
ENDIF defined in line 125; used 1 times
ENDIF_ERR defined in line 138; used 1 times
END_ERR defined in line 134; used 2 times
FALSE defined in line 122; used 1 times
IEOF_ERR defined in line 140; used 2 times
KWSIZE defined in line 270; used 2 times
LEOF defined in line 126; used 1 times
MAXLINE defined in line 258; used 1 times
MAXSYMS defined in line 23; used 5 times
NO defined in line 15; used 12 times
NO_ERR defined in line 132; used 8 times
OTHER defined in line 123; used 2 times
PLAIN defined in line 120; used 2 times
Q1EOF_ERR defined in line 144; used 1 times
Q2EOF_ERR defined in line 146; used 1 times
QUOTE1 defined in line 30; used 6 times
QUOTE2 defined in line 31; used 5 times
TRUE defined in line 121; used 2 times
YES defined in line 14; used 17 times
endsym defined in line 256; used 2 times
Last modified: 1987-02-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4122
Valid CSS Valid XHTML 1.0 Strict