17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
239fb11590Smike_s  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /* Copyright (c) 1982 Regents of the University of California */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  *    unifdef - remove ifdef'ed lines
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate #include <locale.h>
399fb11590Smike_s #include <string.h>
409fb11590Smike_s #include <stdlib.h>
419fb11590Smike_s #include <unistd.h>
429fb11590Smike_s 
437c478bd9Sstevel@tonic-gate FILE *input;
447c478bd9Sstevel@tonic-gate #ifndef YES
459fb11590Smike_s #define	YES 1
469fb11590Smike_s #define	NO  0
477c478bd9Sstevel@tonic-gate #endif
487c478bd9Sstevel@tonic-gate 
499fb11590Smike_s char *progname;
509fb11590Smike_s char *filename;
519fb11590Smike_s char text;		/* -t option in effect: this is a text file */
529fb11590Smike_s char lnblank;		/* -l option in effect: blank deleted lines */
539fb11590Smike_s char complement;	/* -c option in effect: complement the operation */
549fb11590Smike_s #define	MAXSYMS 100
559fb11590Smike_s char true[MAXSYMS];
569fb11590Smike_s char ignore[MAXSYMS];
579fb11590Smike_s char *sym[MAXSYMS];
589fb11590Smike_s signed char insym[MAXSYMS];
599fb11590Smike_s #define	KWSIZE 8
607c478bd9Sstevel@tonic-gate char buf[KWSIZE];
619fb11590Smike_s char nsyms;
629fb11590Smike_s char incomment;
639fb11590Smike_s #define	QUOTE1 0
649fb11590Smike_s #define	QUOTE2 1
659fb11590Smike_s char inquote[2];
669fb11590Smike_s int exitstat;
679fb11590Smike_s 
689fb11590Smike_s static char *skipcomment(char *cp);
699fb11590Smike_s static char *skipquote(char *cp, int type);
709fb11590Smike_s static char *nextsym(char *p);
719fb11590Smike_s static int doif(int thissym, int inif, int prevreject, int depth);
729fb11590Smike_s static void pfile(void);
739fb11590Smike_s static int getlin(char *line, int maxline, FILE *inp, int expandtabs);
749fb11590Smike_s static void prname(void);
759fb11590Smike_s static void flushline(int keep);
769fb11590Smike_s static int checkline(int *cursym);
779fb11590Smike_s static int error(int err, int line, int depth);
789fb11590Smike_s static void putlin(char *line, FILE *fio);
799fb11590Smike_s 
809fb11590Smike_s static void
usage(void)819fb11590Smike_s usage(void)
827c478bd9Sstevel@tonic-gate {
839fb11590Smike_s 	(void) fprintf(stderr, gettext(
849fb11590Smike_s 	    "Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-idsym] "
859fb11590Smike_s 	    "[-iusym]]... [file]\n"
869fb11590Smike_s 	    "    At least one arg from [-D -U -id -iu] is required\n"),
879fb11590Smike_s 	    progname);
889fb11590Smike_s 	exit(2);
899fb11590Smike_s }
907c478bd9Sstevel@tonic-gate 
919fb11590Smike_s int
main(int argc,char ** argv)929fb11590Smike_s main(int argc, char **argv)
939fb11590Smike_s {
949fb11590Smike_s 	char **curarg;
959fb11590Smike_s 	char *cp;
969fb11590Smike_s 	char *cp1;
979fb11590Smike_s 	char ignorethis;
987c478bd9Sstevel@tonic-gate 
999fb11590Smike_s 	(void) setlocale(LC_ALL, "");
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1029fb11590Smike_s #define	TEXT_DOMAIN "SYS_TEST"
1037c478bd9Sstevel@tonic-gate #endif
1049fb11590Smike_s 	(void) textdomain(TEXT_DOMAIN);
1059fb11590Smike_s 
1069fb11590Smike_s 	progname = argv[0][0] ? argv[0] : "unifdef";
1079fb11590Smike_s 
1089fb11590Smike_s 	for (curarg = &argv[1]; --argc > 0; curarg++) {
1099fb11590Smike_s 		if (*(cp1 = cp = *curarg) != '-')
1109fb11590Smike_s 			break;
1119fb11590Smike_s 		if (*++cp1 == 'i') {
1129fb11590Smike_s 			ignorethis = YES;
1139fb11590Smike_s 			cp1++;
1149fb11590Smike_s 		} else
1159fb11590Smike_s 			ignorethis = NO;
1169fb11590Smike_s 		if ((*cp1 == 'D' || *cp1 == 'U') &&
1179fb11590Smike_s 		    cp1[1] != '\0') {
1189fb11590Smike_s 			if (nsyms >= MAXSYMS) {
1199fb11590Smike_s 				prname();
1209fb11590Smike_s 				(void) fprintf(stderr,
1219fb11590Smike_s 				    gettext("too many symbols.\n"));
1229fb11590Smike_s 				exit(2);
1239fb11590Smike_s 			}
1249fb11590Smike_s 			ignore[nsyms] = ignorethis;
1259fb11590Smike_s 			true[nsyms] = *cp1 == 'D' ? YES : NO;
1269fb11590Smike_s 			sym[nsyms++] = &cp1[1];
1279fb11590Smike_s 		} else if (ignorethis)
1289fb11590Smike_s 			goto unrec;
1299fb11590Smike_s 		else if (strcmp(&cp[1], "t") == 0)
1309fb11590Smike_s 			text = YES;
1319fb11590Smike_s 		else if (strcmp(&cp[1], "l") == 0)
1329fb11590Smike_s 			lnblank = YES;
1339fb11590Smike_s 		else if (strcmp(&cp[1], "c") == 0)
1349fb11590Smike_s 			complement = YES;
1359fb11590Smike_s 		else {
1369fb11590Smike_s unrec:
1379fb11590Smike_s 			prname();
1389fb11590Smike_s 			(void) fprintf(stderr,
1399fb11590Smike_s 			    gettext("unrecognized option: %s\n"), cp);
1409fb11590Smike_s 			usage();
1419fb11590Smike_s 		}
1427c478bd9Sstevel@tonic-gate 	}
1439fb11590Smike_s 	if (nsyms == 0) {
1449fb11590Smike_s 		usage();
1457c478bd9Sstevel@tonic-gate 	}
1469fb11590Smike_s 
1479fb11590Smike_s 	if (argc > 1) {
1489fb11590Smike_s 		prname();
1499fb11590Smike_s 		(void) fprintf(stderr, gettext("can only do one file.\n"));
1509fb11590Smike_s 	} else if (argc == 1) {
1519fb11590Smike_s 		filename = *curarg;
1529fb11590Smike_s 		if ((input = fopen(filename, "r")) != NULL) {
1539fb11590Smike_s 			pfile();
1549fb11590Smike_s 			(void) fclose(input);
1559fb11590Smike_s 		} else {
1569fb11590Smike_s 			prname();
1579fb11590Smike_s 			perror(*curarg);
1589fb11590Smike_s 		}
1599fb11590Smike_s 	} else {
1609fb11590Smike_s 		filename = "[stdin]";
1619fb11590Smike_s 		input = stdin;
1629fb11590Smike_s 		pfile();
1637c478bd9Sstevel@tonic-gate 	}
1649fb11590Smike_s 
1659fb11590Smike_s 	(void) fflush(stdout);
1669fb11590Smike_s 	return (exitstat);
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate /* types of input lines: */
1709fb11590Smike_s #define	PLAIN	0   /* ordinary line */
1719fb11590Smike_s #define	TRUE	1   /* a true  #ifdef of a symbol known to us */
1729fb11590Smike_s #define	FALSE	2   /* a false #ifdef of a symbol known to us */
1739fb11590Smike_s #define	OTHER	3   /* an #ifdef of a symbol not known to us */
1749fb11590Smike_s #define	ELSE	4   /* #else */
1759fb11590Smike_s #define	ENDIF	5   /* #endif */
1769fb11590Smike_s #define	LEOF	6   /* end of file */
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate /* should be int declaration, was char */
1799fb11590Smike_s int reject;    /* 0 or 1: pass thru; 1 or 2: ignore comments */
1809fb11590Smike_s int linenum;    /* current line number */
1819fb11590Smike_s int stqcline;   /* start of current comment or quote */
1829fb11590Smike_s 
1837c478bd9Sstevel@tonic-gate char *errs[] = {
1849fb11590Smike_s #define	NO_ERR		0
1857c478bd9Sstevel@tonic-gate 			"",
1869fb11590Smike_s #define	END_ERR		1
1877c478bd9Sstevel@tonic-gate 			"",
1889fb11590Smike_s #define	ELSE_ERR	2
1897c478bd9Sstevel@tonic-gate 			"Inappropriate else",
1909fb11590Smike_s #define	ENDIF_ERR	3
1917c478bd9Sstevel@tonic-gate 			"Inappropriate endif",
1929fb11590Smike_s #define	IEOF_ERR	4
1937c478bd9Sstevel@tonic-gate 			"Premature EOF in ifdef",
1949fb11590Smike_s #define	CEOF_ERR	5
1957c478bd9Sstevel@tonic-gate 			"Premature EOF in comment",
1969fb11590Smike_s #define	Q1EOF_ERR	6
1977c478bd9Sstevel@tonic-gate 			"Premature EOF in quoted character",
1989fb11590Smike_s #define	Q2EOF_ERR	7
1997c478bd9Sstevel@tonic-gate 			"Premature EOF in quoted string"
2007c478bd9Sstevel@tonic-gate };
2017c478bd9Sstevel@tonic-gate 
2029fb11590Smike_s static void
pfile(void)2039fb11590Smike_s pfile(void)
2047c478bd9Sstevel@tonic-gate {
2059fb11590Smike_s 	reject = 0;
2069fb11590Smike_s 	(void) doif(-1, NO, reject, 0);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2099fb11590Smike_s static int
doif(int thissym,int inif,int prevreject,int depth)2109fb11590Smike_s doif(
2119fb11590Smike_s     int thissym,	/* index of the symbol who was last ifdef'ed */
2129fb11590Smike_s     int inif,		/* YES or NO we are inside an ifdef */
2139fb11590Smike_s     int prevreject,	/* previous value of reject */
2149fb11590Smike_s     int depth		/* depth of ifdef's */
2159fb11590Smike_s )
2167c478bd9Sstevel@tonic-gate {
2179fb11590Smike_s 	int lineval;
2189fb11590Smike_s 	int thisreject;
2199fb11590Smike_s 	int doret;	/* tmp return value of doif */
2209fb11590Smike_s 	int cursym;	/* index of the symbol returned by checkline */
2219fb11590Smike_s 	int stline;	/* line number when called this time */
2229fb11590Smike_s 	int err;
2239fb11590Smike_s 
2249fb11590Smike_s 	stline = linenum;
2259fb11590Smike_s 	for (;;) {
2269fb11590Smike_s 		switch (lineval = checkline(&cursym)) {
2279fb11590Smike_s 		case PLAIN:
2289fb11590Smike_s 			flushline(YES);
2299fb11590Smike_s 			break;
2309fb11590Smike_s 
2319fb11590Smike_s 		case TRUE:
2329fb11590Smike_s 		case FALSE:
2339fb11590Smike_s 			thisreject = reject;
2349fb11590Smike_s 			if (lineval == TRUE)
2359fb11590Smike_s 				insym[cursym] = 1;
2369fb11590Smike_s 			else {
2379fb11590Smike_s 				if (reject < 2)
2389fb11590Smike_s 					reject = ignore[cursym] ? 1 : 2;
2399fb11590Smike_s 				insym[cursym] = -1;
2409fb11590Smike_s 			}
2419fb11590Smike_s 			if (ignore[cursym])
2429fb11590Smike_s 				flushline(YES);
2439fb11590Smike_s 			else {
2449fb11590Smike_s 				exitstat = 0;
2459fb11590Smike_s 				flushline(NO);
2469fb11590Smike_s 			}
2479fb11590Smike_s 			if ((doret = doif(cursym, YES,
2489fb11590Smike_s 			    thisreject, depth + 1)) != NO_ERR)
2499fb11590Smike_s 				return (error(doret, stline, depth));
2509fb11590Smike_s 			break;
2519fb11590Smike_s 
2529fb11590Smike_s 		case OTHER:
2539fb11590Smike_s 			flushline(YES);
2549fb11590Smike_s 			if ((doret = doif(-1, YES,
2559fb11590Smike_s 			    reject, depth + 1)) != NO_ERR)
2569fb11590Smike_s 				return (error(doret, stline, depth));
2579fb11590Smike_s 			break;
2589fb11590Smike_s 
2599fb11590Smike_s 		case ELSE:
2609fb11590Smike_s 			if (inif != 1)
2619fb11590Smike_s 				return (error(ELSE_ERR, linenum, depth));
2629fb11590Smike_s 			inif = 2;
2639fb11590Smike_s 			if (thissym >= 0) {
2649fb11590Smike_s 				if ((insym[thissym] = -insym[thissym]) < 0)
2659fb11590Smike_s 					reject = ignore[thissym] ? 1 : 2;
2669fb11590Smike_s 				else
2679fb11590Smike_s 					reject = prevreject;
2689fb11590Smike_s 				if (!ignore[thissym]) {
2699fb11590Smike_s 					flushline(NO);
2709fb11590Smike_s 					break;
2719fb11590Smike_s 				}
2729fb11590Smike_s 			}
2739fb11590Smike_s 			flushline(YES);
2749fb11590Smike_s 			break;
2759fb11590Smike_s 
2769fb11590Smike_s 		case ENDIF:
2779fb11590Smike_s 			if (inif == 0)
2789fb11590Smike_s 				return (error(ENDIF_ERR, linenum, depth));
2799fb11590Smike_s 			if (thissym >= 0) {
2809fb11590Smike_s 				insym[thissym] = 0;
2819fb11590Smike_s 				reject = prevreject;
2829fb11590Smike_s 				if (!ignore[thissym]) {
2839fb11590Smike_s 					flushline(NO);
2849fb11590Smike_s 					return (NO_ERR);
2859fb11590Smike_s 				}
2869fb11590Smike_s 			}
2879fb11590Smike_s 			flushline(YES);
2889fb11590Smike_s 			return (NO_ERR);
2899fb11590Smike_s 
2909fb11590Smike_s 		case LEOF:
2919fb11590Smike_s 			err = incomment
2929fb11590Smike_s 			    ? CEOF_ERR
2939fb11590Smike_s 			    : inquote[QUOTE1]
2949fb11590Smike_s 			    ? Q1EOF_ERR
2959fb11590Smike_s 			    : inquote[QUOTE2]
2969fb11590Smike_s 			    ? Q2EOF_ERR
2979fb11590Smike_s 			    : NO_ERR;
2989fb11590Smike_s 			if (inif) {
2999fb11590Smike_s 				if (err != NO_ERR)
3009fb11590Smike_s 					(void) error(err, stqcline, depth);
3019fb11590Smike_s 				return (error(IEOF_ERR, stline, depth));
3029fb11590Smike_s 			} else if (err != NO_ERR)
3039fb11590Smike_s 				return (error(err, stqcline, depth));
3049fb11590Smike_s 			else
3059fb11590Smike_s 				return (NO_ERR);
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate 
3109fb11590Smike_s #define	endsym(c) (!isalpha(c) && !isdigit(c) && c != '_')
3117c478bd9Sstevel@tonic-gate 
3129fb11590Smike_s #define	MAXLINE 256
3139fb11590Smike_s char tline[MAXLINE];
3147c478bd9Sstevel@tonic-gate 
3159fb11590Smike_s static int
checkline(int * cursym)3169fb11590Smike_s checkline(int *cursym)
3177c478bd9Sstevel@tonic-gate {
3189fb11590Smike_s 	char *cp;
3199fb11590Smike_s 	char *symp;
3209fb11590Smike_s 	char chr;
3219fb11590Smike_s 	char *scp;
3229fb11590Smike_s 	int retval;
3239fb11590Smike_s 	int symind;
3249fb11590Smike_s 	char keyword[KWSIZE];
3259fb11590Smike_s 
3269fb11590Smike_s 	linenum++;
3279fb11590Smike_s 	if (getlin(tline, sizeof (tline), input, NO) == EOF)
3289fb11590Smike_s 		return (LEOF);
3299fb11590Smike_s 
3309fb11590Smike_s 	retval = PLAIN;
3319fb11590Smike_s 	if (*(cp = tline) != '#' || incomment ||
3329fb11590Smike_s 	    inquote[QUOTE1] || inquote[QUOTE2])
3339fb11590Smike_s 		goto eol;
3349fb11590Smike_s 
3357c478bd9Sstevel@tonic-gate 	cp = skipcomment(++cp);
3369fb11590Smike_s 	symp = keyword;
3379fb11590Smike_s 	while (!endsym (*cp)) {
3389fb11590Smike_s 		*symp = *cp++;
3399fb11590Smike_s 		if (++symp >= &keyword[KWSIZE])
3409fb11590Smike_s 			goto eol;
3419fb11590Smike_s 	}
3429fb11590Smike_s 	*symp = '\0';
3439fb11590Smike_s 
3449fb11590Smike_s 	if (strcmp(keyword, "ifdef") == 0) {
3457c478bd9Sstevel@tonic-gate 		retval = YES;
3467c478bd9Sstevel@tonic-gate 		goto ifdef;
3479fb11590Smike_s 	} else if (strcmp(keyword, "if") == 0) {
3489fb11590Smike_s 		cp = skipcomment(++cp);
3499fb11590Smike_s 		if (strcmp(nextsym(cp), "defined") == 0) {
3509fb11590Smike_s 			cp += strlen("defined") + 1;
3519fb11590Smike_s 			/* skip to identifier */
3529fb11590Smike_s 			while (endsym(*cp))
3539fb11590Smike_s 				++cp;
3549fb11590Smike_s 			retval = YES;
3559fb11590Smike_s 			goto ifdef;
3569fb11590Smike_s 		} else {
3579fb11590Smike_s 			retval = OTHER;
3589fb11590Smike_s 			goto eol;
3597c478bd9Sstevel@tonic-gate 		}
3609fb11590Smike_s 	} else if (strcmp(keyword, "ifndef") == 0) {
3619fb11590Smike_s 		retval = NO;
3629fb11590Smike_s ifdef:
3639fb11590Smike_s 		scp = cp = skipcomment(cp);
3649fb11590Smike_s 		if (incomment) {
3659fb11590Smike_s 			retval = PLAIN;
3669fb11590Smike_s 			goto eol;
3679fb11590Smike_s 		}
3689fb11590Smike_s 		symind = 0;
3699fb11590Smike_s 		for (;;) {
3709fb11590Smike_s 			if (insym[symind] == 0) {
3719fb11590Smike_s 				for (symp = sym[symind], cp = scp;
3729fb11590Smike_s 				*symp && *cp == *symp; cp++, symp++) {
3739fb11590Smike_s 					/* NULL */
3749fb11590Smike_s 				}
3759fb11590Smike_s 				chr = *cp;
3769fb11590Smike_s 				if (*symp == '\0' && endsym(chr)) {
3779fb11590Smike_s 					*cursym = symind;
3789fb11590Smike_s 					retval = (retval ^ true[symind]) ?
3799fb11590Smike_s 					    FALSE : TRUE;
3809fb11590Smike_s 					break;
3819fb11590Smike_s 				}
3829fb11590Smike_s 			}
3839fb11590Smike_s 			if (++symind >= nsyms) {
3849fb11590Smike_s 				retval = OTHER;
3859fb11590Smike_s 				break;
3869fb11590Smike_s 			}
3879fb11590Smike_s 		}
3889fb11590Smike_s 	} else if (strcmp(keyword, "else") == 0)
3899fb11590Smike_s 		retval = ELSE;
3909fb11590Smike_s 	else if (strcmp(keyword, "endif") == 0)
3919fb11590Smike_s 		retval = ENDIF;
3929fb11590Smike_s 
3939fb11590Smike_s eol:
3949fb11590Smike_s 	if (!text && !reject)
3959fb11590Smike_s 		while (*cp) {
3969fb11590Smike_s 			if (incomment)
3979fb11590Smike_s 				cp = skipcomment(cp);
3989fb11590Smike_s 			else if (inquote[QUOTE1])
3999fb11590Smike_s 				cp = skipquote(cp, QUOTE1);
4009fb11590Smike_s 			else if (inquote[QUOTE2])
4019fb11590Smike_s 				cp = skipquote(cp, QUOTE2);
4029fb11590Smike_s 			else if (*cp == '/' && cp[1] == '*')
4039fb11590Smike_s 				cp = skipcomment(cp);
4049fb11590Smike_s 			else if (*cp == '\'')
4059fb11590Smike_s 				cp = skipquote(cp, QUOTE1);
4069fb11590Smike_s 			else if (*cp == '"')
4079fb11590Smike_s 				cp = skipquote(cp, QUOTE2);
4089fb11590Smike_s 			else
4099fb11590Smike_s 				cp++;
4109fb11590Smike_s 		}
4119fb11590Smike_s 	return (retval);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4149fb11590Smike_s /*
4159fb11590Smike_s  * Skip over comments and stop at the next character
4169fb11590Smike_s  *  position that is not whitespace.
4179fb11590Smike_s  */
4189fb11590Smike_s static char *
skipcomment(char * cp)4199fb11590Smike_s skipcomment(char *cp)
4207c478bd9Sstevel@tonic-gate {
4219fb11590Smike_s 	if (incomment)
4229fb11590Smike_s 		goto inside;
4237c478bd9Sstevel@tonic-gate 	for (;;) {
4249fb11590Smike_s 		while (*cp == ' ' || *cp == '\t')
4259fb11590Smike_s 			cp++;
4269fb11590Smike_s 		if (text)
4279fb11590Smike_s 			return (cp);
4289fb11590Smike_s 		if (cp[0] != '/' || cp[1] != '*')
4299fb11590Smike_s 			return (cp);
4309fb11590Smike_s 		cp += 2;
4319fb11590Smike_s 		if (!incomment) {
4329fb11590Smike_s 			incomment = YES;
4339fb11590Smike_s 			stqcline = linenum;
4349fb11590Smike_s 		}
4359fb11590Smike_s inside:
4369fb11590Smike_s 		for (;;) {
4379fb11590Smike_s 			for (; *cp != '*'; cp++)
4389fb11590Smike_s 				if (*cp == '\0')
4399fb11590Smike_s 					return (cp);
4409fb11590Smike_s 			if (*++cp == '/')
4419fb11590Smike_s 				break;
4429fb11590Smike_s 		}
4439fb11590Smike_s 		incomment = NO;
4449fb11590Smike_s 		cp++;
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4489fb11590Smike_s /*
4499fb11590Smike_s  * Skip over a quoted string or character and stop at the next charaacter
4509fb11590Smike_s  *  position that is not whitespace.
4519fb11590Smike_s  */
4529fb11590Smike_s static char *
skipquote(char * cp,int type)4539fb11590Smike_s skipquote(char *cp, int type)
4547c478bd9Sstevel@tonic-gate {
4559fb11590Smike_s 	char qchar;
4569fb11590Smike_s 
4579fb11590Smike_s 	qchar = type == QUOTE1 ? '\'' : '"';
4589fb11590Smike_s 
4599fb11590Smike_s 	if (inquote[type])
4609fb11590Smike_s 		goto inside;
4619fb11590Smike_s 	for (;;) {
4629fb11590Smike_s 		if (*cp != qchar)
4639fb11590Smike_s 			return (cp);
4649fb11590Smike_s 		cp++;
4659fb11590Smike_s 		if (!inquote[type]) {
4669fb11590Smike_s 			inquote[type] = YES;
4679fb11590Smike_s 			stqcline = linenum;
4689fb11590Smike_s 		}
4699fb11590Smike_s inside:
4709fb11590Smike_s 		for (; ; cp++) {
4719fb11590Smike_s 			if (*cp == qchar)
4729fb11590Smike_s 				break;
4739fb11590Smike_s 			if (*cp == '\0' || *cp == '\\' && *++cp == '\0')
4749fb11590Smike_s 				return (cp);
4759fb11590Smike_s 		}
4769fb11590Smike_s 		inquote[type] = NO;
4779fb11590Smike_s 		cp++;
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate /*
4829fb11590Smike_s  *   special getlin - treats form-feed as an end-of-line
4839fb11590Smike_s  *                    and expands tabs if asked for
4849fb11590Smike_s  */
4859fb11590Smike_s static int
getlin(char * line,int maxline,FILE * inp,int expandtabs)4869fb11590Smike_s getlin(char *line, int maxline, FILE *inp, int expandtabs)
4877c478bd9Sstevel@tonic-gate {
4889fb11590Smike_s 	int tmp;
4899fb11590Smike_s 	int num;
4909fb11590Smike_s 	int chr;
4917c478bd9Sstevel@tonic-gate #ifdef FFSPECIAL
4929fb11590Smike_s 	static char havechar = NO;  /* have leftover char from last time */
4939fb11590Smike_s 	static char svchar;
4947c478bd9Sstevel@tonic-gate #endif
4957c478bd9Sstevel@tonic-gate 
4969fb11590Smike_s 	num = 0;
4977c478bd9Sstevel@tonic-gate #ifdef FFSPECIAL
4989fb11590Smike_s 	if (havechar) {
4999fb11590Smike_s 		havechar = NO;
5009fb11590Smike_s 		chr = svchar;
5019fb11590Smike_s 		goto ent;
5029fb11590Smike_s 	}
5037c478bd9Sstevel@tonic-gate #endif
5049fb11590Smike_s 	while (num + 8 < maxline) {   /* leave room for tab */
5059fb11590Smike_s 		chr = getc(inp);
5069fb11590Smike_s 		if (isprint(chr)) {
5077c478bd9Sstevel@tonic-gate #ifdef FFSPECIAL
5089fb11590Smike_s ent:
5097c478bd9Sstevel@tonic-gate #endif
5109fb11590Smike_s 			*line++ = chr;
5119fb11590Smike_s 			num++;
5129fb11590Smike_s 		} else
5139fb11590Smike_s 			switch (chr) {
5149fb11590Smike_s 			case EOF:
5159fb11590Smike_s 				return (EOF);
5169fb11590Smike_s 
5179fb11590Smike_s 			case '\t':
5189fb11590Smike_s 				if (expandtabs) {
5199fb11590Smike_s 					num += tmp = 8 - (num & 7);
5209fb11590Smike_s 					do
5219fb11590Smike_s 						*line++ = ' ';
5229fb11590Smike_s 					while (--tmp);
5239fb11590Smike_s 					break;
5249fb11590Smike_s 				}
525*1e819975SToomas Soome 				/* FALLTHROUGH */
5269fb11590Smike_s 			default:
5279fb11590Smike_s 				*line++ = chr;
5289fb11590Smike_s 				num++;
5299fb11590Smike_s 				break;
5309fb11590Smike_s 
5319fb11590Smike_s 			case '\n':
5329fb11590Smike_s 				*line = '\n';
5339fb11590Smike_s 				num++;
5349fb11590Smike_s 				goto end;
5359fb11590Smike_s 
5367c478bd9Sstevel@tonic-gate #ifdef FFSPECIAL
5379fb11590Smike_s 			case '\f':
5389fb11590Smike_s 				if (++num == 1)
5399fb11590Smike_s 					*line = '\f';
5409fb11590Smike_s 				else {
5419fb11590Smike_s 					*line = '\n';
5429fb11590Smike_s 					havechar = YES;
5439fb11590Smike_s 					svchar = chr;
5449fb11590Smike_s 				}
5459fb11590Smike_s 				goto end;
5467c478bd9Sstevel@tonic-gate #endif
5479fb11590Smike_s 			}
5489fb11590Smike_s 	}
5499fb11590Smike_s end:
5509fb11590Smike_s 	*++line = '\0';
5519fb11590Smike_s 	return (num);
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate 
5549fb11590Smike_s static void
flushline(int keep)5559fb11590Smike_s flushline(int keep)
5567c478bd9Sstevel@tonic-gate {
5579fb11590Smike_s 	if ((keep && reject < 2) ^ complement)
5589fb11590Smike_s 		putlin(tline, stdout);
5599fb11590Smike_s 	else if (lnblank)
5609fb11590Smike_s 		putlin("\n", stdout);
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate /*
5649fb11590Smike_s  *  putlin - for tools
5659fb11590Smike_s  */
5669fb11590Smike_s static void
putlin(char * line,FILE * fio)5679fb11590Smike_s putlin(char *line, FILE *fio)
5687c478bd9Sstevel@tonic-gate {
5699fb11590Smike_s 	char chr;
5707c478bd9Sstevel@tonic-gate 
5719fb11590Smike_s 	while (chr = *line++)
5729fb11590Smike_s 		(void) putc(chr, fio);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate 
5759fb11590Smike_s static void
prname(void)5769fb11590Smike_s prname(void)
5777c478bd9Sstevel@tonic-gate {
5789fb11590Smike_s 	(void) fprintf(stderr, "%s: ", progname);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 
5829fb11590Smike_s static int
error(int err,int line,int depth)5839fb11590Smike_s error(int err, int line, int depth)
5847c478bd9Sstevel@tonic-gate {
5859fb11590Smike_s 	if (err == END_ERR)
5869fb11590Smike_s 		return (err);
5877c478bd9Sstevel@tonic-gate 
5889fb11590Smike_s 	prname();
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate #ifndef TESTING
5919fb11590Smike_s 	(void) fprintf(stderr, gettext("Error in %s line %d: %s.\n"),
5929fb11590Smike_s 	    filename, line, gettext(errs[err]));
5937c478bd9Sstevel@tonic-gate #endif
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate #ifdef TESTING
5969fb11590Smike_s 	(void) fprintf(stderr, gettext("Error in %s line %d: %s. "),
5979fb11590Smike_s 	    filename, line, errs[err]);
5989fb11590Smike_s 	(void) fprintf(stderr, gettext("ifdef depth: %d\n"), depth);
5997c478bd9Sstevel@tonic-gate #endif
6007c478bd9Sstevel@tonic-gate 
6019fb11590Smike_s 	exitstat = 1;
6029fb11590Smike_s 	return (depth > 1 ? IEOF_ERR : END_ERR);
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate /* return the next token in the line buffer */
6067c478bd9Sstevel@tonic-gate char *
nextsym(char * p)6079fb11590Smike_s nextsym(char *p)
6087c478bd9Sstevel@tonic-gate {
6099fb11590Smike_s 	char *key;
6109fb11590Smike_s 	int i = KWSIZE;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	key = buf;
6137c478bd9Sstevel@tonic-gate 	while (!endsym(*p) && --i)
6147c478bd9Sstevel@tonic-gate 		*key++ = *p++;
6157c478bd9Sstevel@tonic-gate 	*key = '\0';
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	return (buf);
6187c478bd9Sstevel@tonic-gate }
619