Annotation of 42BSD/ucb/unifdef.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.