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

Defined functions

checkline defined in line 259; used 1 times
doif defined in line 155; used 3 times
error defined in line 531; used 7 times
flushline defined in line 500; used 8 times
getlin defined in line 428; used 1 times
main defined in line 35; never used
pfile defined in line 148; used 2 times
prname defined in line 524; used 5 times
putlin defined in line 513; used 2 times
skipcomment defined in line 355; used 5 times
skipquote defined in line 390; used 5 times

Defined variables

BSS defined in line 257; never used
complement defined in line 20; used 2 times
errs defined in line 129; used 2 times
exitstat defined in line 31; used 3 times
filename defined in line 17; used 5 times
ignore defined in line 23; used 6 times
incomment defined in line 27; used 8 times
inquote defined in line 30; used 10 times
insym defined in line 25; used 6 times
linenum defined in line 127; used 6 times
lnblank defined in line 19; used 2 times
nsyms defined in line 26; used 6 times
progname defined in line 16; used 3 times
reject defined in line 126; used 11 times
stqcline defined in line 128; used 4 times
sym defined in line 24; used 2 times
text defined in line 18; used 3 times
tline defined in line 257; used 4 times
true defined in line 22; used 2 times

Defined macros

BSS defined in line 9; used 1 times
CEOF_ERR defined in line 140; used 1 times
ELSE defined in line 122; used 1 times
ELSE_ERR defined in line 134; used 1 times
ENDIF defined in line 123; used 1 times
ENDIF_ERR defined in line 136; used 1 times
END_ERR defined in line 132; used 2 times
FALSE defined in line 120; used 1 times
IEOF_ERR defined in line 138; used 2 times
KWSIZE defined in line 268; used 2 times
LEOF defined in line 124; used 1 times
MAXLINE defined in line 256; used 1 times
MAXSYMS defined in line 21; used 5 times
NO defined in line 13; used 12 times
NO_ERR defined in line 130; used 8 times
OTHER defined in line 121; used 2 times
PLAIN defined in line 118; used 2 times
Q1EOF_ERR defined in line 142; used 1 times
Q2EOF_ERR defined in line 144; used 1 times
QUOTE1 defined in line 28; used 6 times
QUOTE2 defined in line 29; used 5 times
TRUE defined in line 119; used 2 times
YES defined in line 12; used 17 times
endsym defined in line 254; used 2 times
Last modified: 1982-11-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1628
Valid CSS Valid XHTML 1.0 Strict