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

1.6     ! deraadt     1: /*     $OpenBSD: unifdef.c,v 1.5 2002/05/10 19:13:07 jason 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.6     ! deraadt    50: static char rcsid[] = "$OpenBSD: unifdef.c,v 1.5 2002/05/10 19:13:07 jason 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:
1.3       deraadt    69: FILE   *input;
1.1       deraadt    70: #ifndef YES
                     71: #define YES 1
                     72: #define NO  0
1.3       deraadt    73: #endif                         /* YES */
                     74: #define C_COMMENT   1
                     75: #define CXX_COMMENT 2
1.1       deraadt    76: typedef int Bool;
                     77:
1.6     ! deraadt    78: char   *progname;
        !            79: char   *filename;
        !            80: char text;                     /* -t option in effect: this is a text file */
        !            81: char lnblank;                  /* -l option in effect: blank deleted lines */
        !            82: char complement;               /* -c option in effect: complement the
1.3       deraadt    83:                                 * operation */
1.1       deraadt    84:
                     85: #define MAXSYMS 100
1.6     ! deraadt    86: char   *symname[MAXSYMS];      /* symbol name */
        !            87: char    true[MAXSYMS];         /* -Dsym */
        !            88: char    ignore[MAXSYMS];       /* -iDsym or -iUsym */
        !            89: char    insym[MAXSYMS];                /* state: false, inactive, true */
1.3       deraadt    90: #define SYM_INACTIVE 0         /* symbol is currently inactive */
                     91: #define SYM_FALSE    1         /* symbol is currently false */
                     92: #define SYM_TRUE     2         /* symbol is currently true  */
1.1       deraadt    93:
1.6     ! deraadt    94: char nsyms;
        !            95: char incomment;                        /* inside C comment */
1.1       deraadt    96:
                     97: #define QUOTE_NONE   0
                     98: #define QUOTE_SINGLE 1
                     99: #define QUOTE_DOUBLE 2
1.6     ! deraadt   100: char inquote;                  /* inside single or double quotes */
        !           101: int exitstat;
1.1       deraadt   102:
1.4       millert   103: int error(int, int, int);
                    104: int findsym(char *);
                    105: void flushline(Bool);
                    106: int getlin(char *, int, FILE *, int);
                    107: void pfile(void);
                    108: void prname(void);
                    109: char   *skipcomment(char *);
                    110: char   *skipquote(char *, int);
1.1       deraadt   111:
                    112: int
1.3       deraadt   113: main(argc, argv)
                    114:        int     argc;
                    115:        char  **argv;
                    116: {
                    117:        char  **curarg;
                    118:        char *cp;
                    119:        char *cp1;
                    120:        char    ignorethis;
                    121:
                    122:        progname = argv[0][0] ? argv[0] : "unifdef";
                    123:
                    124:        for (curarg = &argv[1]; --argc > 0; curarg++) {
                    125:                if (*(cp1 = cp = *curarg) != '-')
                    126:                        break;
                    127:                if (*++cp1 == 'i') {
                    128:                        ignorethis = YES;
                    129:                        cp1++;
                    130:                } else
                    131:                        ignorethis = NO;
                    132:                if ((*cp1 == 'D'
                    133:                        || *cp1 == 'U'
                    134:                    )
                    135:                    && cp1[1] != '\0'
                    136:                    ) {
                    137:                        int symind;
                    138:
                    139:                        if ((symind = findsym(&cp1[1])) < 0) {
                    140:                                if (nsyms >= MAXSYMS) {
                    141:                                        prname();
                    142:                                        fprintf(stderr, "too many symbols.\n");
                    143:                                        exit(2);
                    144:                                }
                    145:                                symind = nsyms++;
                    146:                                symname[symind] = &cp1[1];
                    147:                                insym[symind] = SYM_INACTIVE;
                    148:                        }
                    149:                        ignore[symind] = ignorethis;
                    150:                        true[symind] = *cp1 == 'D' ? YES : NO;
                    151:                } else
                    152:                        if (ignorethis)
                    153:                                goto unrec;
                    154:                        else
                    155:                                if (strcmp(&cp[1], "t") == 0)
                    156:                                        text = YES;
                    157:                                else
                    158:                                        if (strcmp(&cp[1], "l") == 0)
                    159:                                                lnblank = YES;
                    160:                                        else
                    161:                                                if (strcmp(&cp[1], "c") == 0)
                    162:                                                        complement = YES;
                    163:                                                else {
                    164:                                        unrec:
                    165:                                                        prname();
                    166:                                                        fprintf(stderr, "unrecognized option: %s\n", cp);
                    167:                                                        goto usage;
                    168:                                                }
1.1       deraadt   169:        }
1.3       deraadt   170:        if (nsyms == 0) {
                    171: usage:
                    172:                fprintf(stderr, "\
1.1       deraadt   173: Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-iDsym] [-iUsym]]... [file]\n\
                    174:     At least one arg from [-D -U -iD -iU] is required\n", progname);
1.3       deraadt   175:                exit(2);
1.1       deraadt   176:        }
1.3       deraadt   177:        if (argc > 1) {
                    178:                prname();
                    179:                fprintf(stderr, "can only do one file.\n");
                    180:        } else
                    181:                if (argc == 1) {
                    182:                        filename = *curarg;
                    183:                        if ((input = fopen(filename, "r")) != NULL) {
                    184:                                pfile();
                    185:                                (void) fclose(input);
                    186:                        } else {
                    187:                                prname();
                    188:                                fprintf(stderr, "can't open ");
                    189:                                perror(*curarg);
                    190:                        }
                    191:                } else {
                    192:                        filename = "[stdin]";
                    193:                        input = stdin;
                    194:                        pfile();
                    195:                }
1.1       deraadt   196:
1.3       deraadt   197:        (void) fflush(stdout);
                    198:        exit(exitstat);
1.1       deraadt   199: }
                    200: /* types of input lines: */
                    201: typedef int Linetype;
1.3       deraadt   202: #define LT_PLAIN       0       /* ordinary line */
                    203: #define LT_TRUE        1       /* a true  #ifdef of a symbol known to us */
                    204: #define LT_FALSE       2       /* a false #ifdef of a symbol known to us */
                    205: #define LT_OTHER       3       /* an #ifdef of a symbol not known to us */
                    206: #define LT_IF          4       /* an #ifdef of a symbol not known to us */
                    207: #define LT_ELSE        5       /* #else */
                    208: #define LT_ENDIF       6       /* #endif */
                    209: #define LT_LEOF        7       /* end of file */
1.4       millert   210: Linetype checkline(int *);
1.1       deraadt   211:
                    212: typedef int Reject_level;
1.6     ! deraadt   213: Reject_level reject;           /* 0 or 1: pass thru; 1 or 2: ignore comments */
1.1       deraadt   214: #define REJ_NO          0
                    215: #define REJ_IGNORE      1
                    216: #define REJ_YES         2
1.4       millert   217: int doif(int, int, Reject_level, int);
1.1       deraadt   218:
1.6     ! deraadt   219: int linenum;                   /* current line number */
        !           220: int stqcline;                  /* start of current coment or quote */
1.3       deraadt   221: char   *errs[] = {
1.1       deraadt   222: #define NO_ERR      0
1.3       deraadt   223:        "",
1.1       deraadt   224: #define END_ERR     1
1.3       deraadt   225:        "",
1.1       deraadt   226: #define ELSE_ERR    2
1.3       deraadt   227:        "Inappropriate else",
1.1       deraadt   228: #define ENDIF_ERR   3
1.3       deraadt   229:        "Inappropriate endif",
1.1       deraadt   230: #define IEOF_ERR    4
1.3       deraadt   231:        "Premature EOF in ifdef",
1.1       deraadt   232: #define CEOF_ERR    5
1.3       deraadt   233:        "Premature EOF in comment",
1.1       deraadt   234: #define Q1EOF_ERR   6
1.3       deraadt   235:        "Premature EOF in quoted character",
1.1       deraadt   236: #define Q2EOF_ERR   7
1.3       deraadt   237:        "Premature EOF in quoted string"
1.1       deraadt   238: };
                    239: /* States for inif arg to doif */
                    240: #define IN_NONE 0
                    241: #define IN_IF   1
                    242: #define IN_ELSE 2
                    243:
                    244: void
1.3       deraadt   245: pfile()
1.1       deraadt   246: {
1.3       deraadt   247:        reject = REJ_NO;
                    248:        (void) doif(-1, IN_NONE, reject, 0);
                    249:        return;
1.1       deraadt   250: }
                    251:
                    252: int
1.3       deraadt   253: doif(thissym, inif, prevreject, depth)
                    254:        int thissym;    /* index of the symbol who was last ifdef'ed */
                    255:        int     inif;           /* YES or NO we are inside an ifdef */
                    256:        Reject_level prevreject;/* previous value of reject */
                    257:        int     depth;          /* depth of ifdef's */
                    258: {
                    259:        Linetype lineval;
                    260:        Reject_level thisreject;
                    261:        int     doret;          /* tmp return value of doif */
                    262:        int     cursym;         /* index of the symbol returned by checkline */
                    263:        int     stline;         /* line number when called this time */
                    264:
                    265:        stline = linenum;
                    266:        for (;;) {
                    267:                switch (lineval = checkline(&cursym)) {
                    268:                case LT_PLAIN:
                    269:                        flushline(YES);
                    270:                        break;
                    271:
                    272:                case LT_TRUE:
                    273:                case LT_FALSE:
                    274:                        thisreject = reject;
                    275:                        if (lineval == LT_TRUE)
                    276:                                insym[cursym] = SYM_TRUE;
                    277:                        else {
                    278:                                if (reject != REJ_YES)
                    279:                                        reject = ignore[cursym] ? REJ_IGNORE : REJ_YES;
                    280:                                insym[cursym] = SYM_FALSE;
                    281:                        }
                    282:                        if (ignore[cursym])
                    283:                                flushline(YES);
                    284:                        else {
                    285:                                exitstat = 1;
                    286:                                flushline(NO);
                    287:                        }
                    288:                        if ((doret = doif(cursym, IN_IF, thisreject, depth + 1)) != NO_ERR)
                    289:                                return error(doret, stline, depth);
                    290:                        break;
                    291:
                    292:                case LT_IF:
                    293:                case LT_OTHER:
                    294:                        flushline(YES);
                    295:                        if ((doret = doif(-1, IN_IF, reject, depth + 1)) != NO_ERR)
                    296:                                return error(doret, stline, depth);
                    297:                        break;
                    298:
                    299:                case LT_ELSE:
                    300:                        if (inif != IN_IF)
                    301:                                return error(ELSE_ERR, linenum, depth);
                    302:                        inif = IN_ELSE;
                    303:                        if (thissym >= 0) {
                    304:                                if (insym[thissym] == SYM_TRUE) {
                    305:                                        reject = ignore[thissym] ? REJ_IGNORE : REJ_YES;
                    306:                                        insym[thissym] = SYM_FALSE;
                    307:                                } else {        /* (insym[thissym] ==
                    308:                                                 * SYM_FALSE) */
                    309:                                        reject = prevreject;
                    310:                                        insym[thissym] = SYM_TRUE;
                    311:                                }
                    312:                                if (!ignore[thissym]) {
                    313:                                        flushline(NO);
                    314:                                        break;
                    315:                                }
                    316:                        }
                    317:                        flushline(YES);
                    318:                        break;
                    319:
                    320:                case LT_ENDIF:
                    321:                        if (inif == IN_NONE)
                    322:                                return error(ENDIF_ERR, linenum, depth);
                    323:                        if (thissym >= 0) {
                    324:                                insym[thissym] = SYM_INACTIVE;
                    325:                                reject = prevreject;
                    326:                                if (!ignore[thissym]) {
                    327:                                        flushline(NO);
                    328:                                        return NO_ERR;
                    329:                                }
                    330:                        }
                    331:                        flushline(YES);
                    332:                        return NO_ERR;
                    333:
                    334:                case LT_LEOF:{
                    335:                                int     err;
                    336:                                err = incomment
                    337:                                    ? CEOF_ERR
                    338:                                    : inquote == QUOTE_SINGLE
                    339:                                    ? Q1EOF_ERR
                    340:                                    : inquote == QUOTE_DOUBLE
                    341:                                    ? Q2EOF_ERR
                    342:                                    : NO_ERR;
                    343:                                if (inif != IN_NONE) {
                    344:                                        if (err != NO_ERR)
                    345:                                                (void) error(err, stqcline, depth);
                    346:                                        return error(IEOF_ERR, stline, depth);
                    347:                                } else
                    348:                                        if (err != NO_ERR)
                    349:                                                return error(err, stqcline, depth);
                    350:                                        else
                    351:                                                return NO_ERR;
                    352:                        }
1.1       deraadt   353:                }
                    354:        }
                    355: }
                    356: #define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_')
                    357:
                    358: #define MAXLINE 256
1.6     ! deraadt   359: char    tline[MAXLINE];
1.1       deraadt   360:
                    361: Linetype
1.3       deraadt   362: checkline(cursym)
                    363:        int    *cursym;         /* if LT_TRUE or LT_FALSE returned, set this
                    364:                                 * to sym index */
                    365: {
                    366:        char *cp;
                    367:        char *symp;
                    368:        char   *scp;
                    369:        Linetype retval;
                    370: #define KWSIZE 8
                    371:        char    keyword[KWSIZE];
                    372:
                    373:        linenum++;
                    374:        if (getlin(tline, sizeof tline, input, NO) == EOF)
                    375:                return LT_LEOF;
                    376:
                    377:        retval = LT_PLAIN;
                    378:        if (*(cp = tline) != '#'
                    379:            || incomment
                    380:            || inquote == QUOTE_SINGLE
                    381:            || inquote == QUOTE_DOUBLE
                    382:            )
                    383:                goto eol;
                    384:
                    385:        cp = skipcomment(++cp);
                    386:        symp = keyword;
                    387:        while (!endsym(*cp)) {
                    388:                *symp = *cp++;
                    389:                if (++symp >= &keyword[KWSIZE])
                    390:                        goto eol;
1.1       deraadt   391:        }
1.3       deraadt   392:        *symp = '\0';
1.1       deraadt   393:
1.3       deraadt   394:        if (strcmp(keyword, "ifdef") == 0) {
                    395:                retval = YES;
                    396:                goto ifdef;
                    397:        } else
                    398:                if (strcmp(keyword, "ifndef") == 0) {
                    399:                        retval = NO;
                    400:        ifdef:
                    401:                        scp = cp = skipcomment(++cp);
                    402:                        if (incomment) {
                    403:                                retval = LT_PLAIN;
                    404:                                goto eol;
                    405:                        } {
                    406:                                int     symind;
                    407:
                    408:                                if ((symind = findsym(scp)) >= 0)
                    409:                                        retval = (retval ^ true[*cursym = symind])
                    410:                                            ? LT_FALSE : LT_TRUE;
                    411:                                else
                    412:                                        retval = LT_OTHER;
                    413:                        }
                    414:                } else
                    415:                        if (strcmp(keyword, "if") == 0)
                    416:                                retval = LT_IF;
                    417:                        else
                    418:                                if (strcmp(keyword, "else") == 0)
                    419:                                        retval = LT_ELSE;
                    420:                                else
                    421:                                        if (strcmp(keyword, "endif") == 0)
                    422:                                                retval = LT_ENDIF;
                    423:
                    424: eol:
                    425:        if (!text && reject != REJ_IGNORE)
                    426:                for (; *cp;) {
                    427:                        if (incomment)
                    428:                                cp = skipcomment(cp);
                    429:                        else
                    430:                                if (inquote == QUOTE_SINGLE)
                    431:                                        cp = skipquote(cp, QUOTE_SINGLE);
                    432:                                else
                    433:                                        if (inquote == QUOTE_DOUBLE)
                    434:                                                cp = skipquote(cp, QUOTE_DOUBLE);
                    435:                                        else
                    436:                                                if (*cp == '/' && (cp[1] == '*' || cp[1] == '/'))
                    437:                                                        cp = skipcomment(cp);
                    438:                                                else
                    439:                                                        if (*cp == '\'')
                    440:                                                                cp = skipquote(cp, QUOTE_SINGLE);
                    441:                                                        else
                    442:                                                                if (*cp == '"')
                    443:                                                                        cp = skipquote(cp, QUOTE_DOUBLE);
                    444:                                                                else
                    445:                                                                        cp++;
                    446:                }
                    447:        return retval;
1.1       deraadt   448: }
                    449: /*
                    450:  *  Skip over comments and stop at the next charaacter
                    451:  *  position that is not whitespace.
                    452:  */
1.3       deraadt   453: char   *
                    454: skipcomment(cp)
                    455:        char *cp;
                    456: {
                    457:        if (incomment)
                    458:                goto inside;
                    459:        for (;; cp++) {
                    460:                while (*cp == ' ' || *cp == '\t')
                    461:                        cp++;
                    462:                if (text)
                    463:                        return cp;
                    464:                if (cp[0] != '/')
                    465:                        return cp;
                    466:
                    467:                if (cp[1] == '*') {
                    468:                        if (!incomment) {
                    469:                                incomment = C_COMMENT;
                    470:                                stqcline = linenum;
                    471:                        }
                    472:                } else if (cp[1] == '/') {
                    473:                        if (!incomment) {
                    474:                                incomment = CXX_COMMENT;
                    475:                                stqcline = linenum;
                    476:                        }
                    477:                } else
                    478:                        return cp;
                    479:
                    480:                cp += 2;
                    481: inside:
                    482:                if (incomment == C_COMMENT) {
                    483:                        for (;;) {
                    484:                                for (; *cp != '*'; cp++)
                    485:                                        if (*cp == '\0')
                    486:                                                return cp;
                    487:                                if (*++cp == '/') {
                    488:                                        incomment = NO;
                    489:                                        break;
                    490:                                }
                    491:                        }
                    492:                }
                    493:                else if (incomment == CXX_COMMENT) {
                    494:                        for (; *cp != '\n'; cp++)
                    495:                                if (*cp == '\0')
                    496:                                        return cp;
                    497:                        incomment = NO;
                    498:                }
1.1       deraadt   499:        }
                    500: }
                    501: /*
                    502:  *  Skip over a quoted string or character and stop at the next charaacter
                    503:  *  position that is not whitespace.
                    504:  */
1.3       deraadt   505: char   *
                    506: skipquote(cp, type)
                    507:        char *cp;
                    508:        int type;
                    509: {
                    510:        char qchar;
                    511:
                    512:        qchar = type == QUOTE_SINGLE ? '\'' : '"';
                    513:
                    514:        if (inquote == type)
                    515:                goto inside;
                    516:        for (;; cp++) {
                    517:                if (*cp != qchar)
                    518:                        return cp;
                    519:                cp++;
                    520:                inquote = type;
                    521:                stqcline = linenum;
                    522: inside:
                    523:                for (;; cp++) {
                    524:                        if (*cp == qchar)
                    525:                                break;
                    526:                        if (*cp == '\0' || (*cp == '\\' && *++cp == '\0'))
                    527:                                return cp;
                    528:                }
                    529:                inquote = QUOTE_NONE;
1.1       deraadt   530:        }
                    531: }
                    532: /*
                    533:  *  findsym - look for the symbol in the symbol table.
                    534:  *            if found, return symbol table index,
                    535:  *            else return -1.
                    536:  */
                    537: int
1.3       deraadt   538: findsym(str)
                    539:        char   *str;
1.1       deraadt   540: {
1.3       deraadt   541:        char *cp;
                    542:        char *symp;
                    543:        int symind;
                    544:        char chr;
                    545:
                    546:        for (symind = 0; symind < nsyms; ++symind) {
                    547:                if (insym[symind] == SYM_INACTIVE) {
                    548:                        for (symp = symname[symind], cp = str
                    549:                            ; *symp && *cp == *symp
                    550:                            ; cp++, symp++
                    551:                            )
                    552:                                continue;
                    553:                        chr = *cp;
                    554:                        if (*symp == '\0' && endsym(chr))
                    555:                                return symind;
                    556:                }
1.1       deraadt   557:        }
1.3       deraadt   558:        return -1;
1.1       deraadt   559: }
                    560: /*
                    561:  *   getlin - expands tabs if asked for
                    562:  *            and (if compiled in) treats form-feed as an end-of-line
                    563:  */
                    564: int
1.3       deraadt   565: getlin(line, maxline, inp, expandtabs)
                    566:        char *line;
                    567:        int     maxline;
                    568:        FILE   *inp;
                    569:        int     expandtabs;
                    570: {
                    571:        int     tmp;
                    572:        int num;
                    573:        int chr;
1.1       deraadt   574: #ifdef  FFSPECIAL
1.3       deraadt   575:        static char havechar = NO;      /* have leftover char from last time */
1.6     ! deraadt   576:        static char svchar;
1.3       deraadt   577: #endif                         /* FFSPECIAL */
1.1       deraadt   578:
1.3       deraadt   579:        num = 0;
1.1       deraadt   580: #ifdef  FFSPECIAL
1.3       deraadt   581:        if (havechar) {
                    582:                havechar = NO;
                    583:                chr = svchar;
                    584:                goto ent;
                    585:        }
                    586: #endif                         /* FFSPECIAL */
                    587:        while (num + 8 < maxline) {     /* leave room for tab */
                    588:                chr = getc(inp);
1.5       jason     589:                if (chr == EOF)
                    590:                        return EOF;
1.3       deraadt   591:                if (isprint(chr)) {
1.1       deraadt   592: #ifdef  FFSPECIAL
1.3       deraadt   593:        ent:
                    594: #endif                         /* FFSPECIAL */
                    595:                        *line++ = chr;
                    596:                        num++;
                    597:                } else
                    598:                        switch (chr) {
                    599:                        case '\t':
                    600:                                if (expandtabs) {
                    601:                                        num += tmp = 8 - (num & 7);
                    602:                                        do
                    603:                                                *line++ = ' ';
                    604:                                        while (--tmp);
                    605:                                        break;
                    606:                                }
                    607:                        default:
                    608:                                *line++ = chr;
                    609:                                num++;
                    610:                                break;
                    611:
                    612:                        case '\n':
                    613:                                *line = '\n';
                    614:                                num++;
                    615:                                goto end;
1.1       deraadt   616:
                    617: #ifdef  FFSPECIAL
1.3       deraadt   618:                        case '\f':
                    619:                                if (++num == 1)
                    620:                                        *line = '\f';
                    621:                                else {
                    622:                                        *line = '\n';
                    623:                                        havechar = YES;
                    624:                                        svchar = chr;
                    625:                                }
                    626:                                goto end;
                    627: #endif                         /* FFSPECIAL */
                    628:                        }
                    629:        }
                    630: end:
                    631:        *++line = '\0';
                    632:        return num;
1.1       deraadt   633: }
                    634:
                    635: void
1.3       deraadt   636: flushline(keep)
                    637:        Bool    keep;
1.1       deraadt   638: {
1.3       deraadt   639:        if ((keep && reject != REJ_YES) ^ complement) {
                    640:                char *line = tline;
                    641:                FILE *out = stdout;
                    642:                char chr;
                    643:
                    644:                while ((chr = *line++))
                    645:                        putc(chr, out);
                    646:        } else
                    647:                if (lnblank)
                    648:                        putc('\n', stdout);
                    649:        return;
1.1       deraadt   650: }
                    651:
                    652: void
1.3       deraadt   653: prname()
1.1       deraadt   654: {
1.3       deraadt   655:        fprintf(stderr, "%s: ", progname);
                    656:        return;
1.1       deraadt   657: }
                    658:
                    659: int
1.3       deraadt   660: error(err, line, depth)
                    661:        int     err;            /* type of error & index into error string
                    662:                                 * array */
                    663:        int     line;           /* line number */
                    664:        int     depth;          /* how many ifdefs we are inside */
1.1       deraadt   665: {
1.3       deraadt   666:        if (err == END_ERR)
                    667:                return err;
1.1       deraadt   668:
1.3       deraadt   669:        prname();
1.1       deraadt   670:
                    671: #ifndef TESTING
1.3       deraadt   672:        fprintf(stderr, "Error in %s line %d: %s.\n", filename, line, errs[err]);
                    673: #else                          /* TESTING */
                    674:        fprintf(stderr, "Error in %s line %d: %s. ", filename, line, errs[err]);
                    675:        fprintf(stderr, "ifdef depth: %d\n", depth);
                    676: #endif                         /* TESTING */
1.1       deraadt   677:
1.3       deraadt   678:        exitstat = 2;
                    679:        return depth > 1 ? IEOF_ERR : END_ERR;
1.1       deraadt   680: }