[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.4

1.4     ! millert     1: /*     $OpenBSD: unifdef.c,v 1.3 1998/11/16 21:58:29 deraadt Exp $     */
1.3       deraadt     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.4     ! millert    50: static char rcsid[] = "$OpenBSD: unifdef.c,v 1.3 1998/11/16 21:58:29 deraadt Exp $";
1.3       deraadt    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.4     ! millert   104: int error(int, int, int);
        !           105: int findsym(char *);
        !           106: void flushline(Bool);
        !           107: int getlin(char *, int, FILE *, int);
        !           108: void pfile(void);
        !           109: void prname(void);
        !           110: char   *skipcomment(char *);
        !           111: char   *skipquote(char *, int);
1.1       deraadt   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.4     ! millert   211: Linetype checkline(int *);
1.1       deraadt   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
1.4     ! millert   218: int doif(int, int, Reject_level, int);
1.1       deraadt   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: }