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