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