[BACK]Return to unifdef.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / unifdef

Annotation of src/usr.bin/unifdef/unifdef.c, Revision 1.3

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