Home | History | Annotate | Line # | Download | only in unifdef
unifdef.c revision 1.1.1.1
      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.1  cgd static char sccsid[] = "@(#)unifdef.c	4.7 (Berkeley) 6/1/90";
     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