10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*291Smike_s * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate
300Sstevel@tonic-gate /* Copyright (c) 1982 Regents of the University of California */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * unifdef - remove ifdef'ed lines
360Sstevel@tonic-gate */
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <stdio.h>
390Sstevel@tonic-gate #include <ctype.h>
400Sstevel@tonic-gate #include <locale.h>
41*291Smike_s #include <string.h>
42*291Smike_s #include <stdlib.h>
43*291Smike_s #include <unistd.h>
44*291Smike_s
450Sstevel@tonic-gate FILE *input;
460Sstevel@tonic-gate #ifndef YES
47*291Smike_s #define YES 1
48*291Smike_s #define NO 0
490Sstevel@tonic-gate #endif
500Sstevel@tonic-gate
51*291Smike_s char *progname;
52*291Smike_s char *filename;
53*291Smike_s char text; /* -t option in effect: this is a text file */
54*291Smike_s char lnblank; /* -l option in effect: blank deleted lines */
55*291Smike_s char complement; /* -c option in effect: complement the operation */
56*291Smike_s #define MAXSYMS 100
57*291Smike_s char true[MAXSYMS];
58*291Smike_s char ignore[MAXSYMS];
59*291Smike_s char *sym[MAXSYMS];
60*291Smike_s signed char insym[MAXSYMS];
61*291Smike_s #define KWSIZE 8
62*291Smike_s char buf[KWSIZE];
63*291Smike_s char nsyms;
64*291Smike_s char incomment;
65*291Smike_s #define QUOTE1 0
66*291Smike_s #define QUOTE2 1
67*291Smike_s char inquote[2];
68*291Smike_s int exitstat;
69*291Smike_s
70*291Smike_s static char *skipcomment(char *cp);
71*291Smike_s static char *skipquote(char *cp, int type);
72*291Smike_s static char *nextsym(char *p);
73*291Smike_s static int doif(int thissym, int inif, int prevreject, int depth);
74*291Smike_s static void pfile(void);
75*291Smike_s static int getlin(char *line, int maxline, FILE *inp, int expandtabs);
76*291Smike_s static void prname(void);
77*291Smike_s static void flushline(int keep);
78*291Smike_s static int checkline(int *cursym);
79*291Smike_s static int error(int err, int line, int depth);
80*291Smike_s static void putlin(char *line, FILE *fio);
81*291Smike_s
82*291Smike_s static void
usage(void)83*291Smike_s usage(void)
84*291Smike_s {
85*291Smike_s (void) fprintf(stderr, gettext(
86*291Smike_s "Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-idsym] "
87*291Smike_s "[-iusym]]... [file]\n"
88*291Smike_s " At least one arg from [-D -U -id -iu] is required\n"),
89*291Smike_s progname);
90*291Smike_s exit(2);
91*291Smike_s }
920Sstevel@tonic-gate
93*291Smike_s int
main(int argc,char ** argv)94*291Smike_s main(int argc, char **argv)
95*291Smike_s {
96*291Smike_s char **curarg;
97*291Smike_s char *cp;
98*291Smike_s char *cp1;
99*291Smike_s char ignorethis;
100*291Smike_s
101*291Smike_s (void) setlocale(LC_ALL, "");
102*291Smike_s
103*291Smike_s #if !defined(TEXT_DOMAIN)
104*291Smike_s #define TEXT_DOMAIN "SYS_TEST"
105*291Smike_s #endif
106*291Smike_s (void) textdomain(TEXT_DOMAIN);
107*291Smike_s
108*291Smike_s progname = argv[0][0] ? argv[0] : "unifdef";
109*291Smike_s
110*291Smike_s for (curarg = &argv[1]; --argc > 0; curarg++) {
111*291Smike_s if (*(cp1 = cp = *curarg) != '-')
112*291Smike_s break;
113*291Smike_s if (*++cp1 == 'i') {
114*291Smike_s ignorethis = YES;
115*291Smike_s cp1++;
116*291Smike_s } else
117*291Smike_s ignorethis = NO;
118*291Smike_s if ((*cp1 == 'D' || *cp1 == 'U') &&
119*291Smike_s cp1[1] != '\0') {
120*291Smike_s if (nsyms >= MAXSYMS) {
121*291Smike_s prname();
122*291Smike_s (void) fprintf(stderr,
123*291Smike_s gettext("too many symbols.\n"));
124*291Smike_s exit(2);
125*291Smike_s }
126*291Smike_s ignore[nsyms] = ignorethis;
127*291Smike_s true[nsyms] = *cp1 == 'D' ? YES : NO;
128*291Smike_s sym[nsyms++] = &cp1[1];
129*291Smike_s } else if (ignorethis)
130*291Smike_s goto unrec;
131*291Smike_s else if (strcmp(&cp[1], "t") == 0)
132*291Smike_s text = YES;
133*291Smike_s else if (strcmp(&cp[1], "l") == 0)
134*291Smike_s lnblank = YES;
135*291Smike_s else if (strcmp(&cp[1], "c") == 0)
136*291Smike_s complement = YES;
137*291Smike_s else {
138*291Smike_s unrec:
139*291Smike_s prname();
140*291Smike_s (void) fprintf(stderr,
141*291Smike_s gettext("unrecognized option: %s\n"), cp);
142*291Smike_s usage();
143*291Smike_s }
1440Sstevel@tonic-gate }
145*291Smike_s if (nsyms == 0) {
146*291Smike_s usage();
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
149*291Smike_s if (argc > 1) {
150*291Smike_s prname();
151*291Smike_s (void) fprintf(stderr, gettext("can only do one file.\n"));
152*291Smike_s } else if (argc == 1) {
153*291Smike_s filename = *curarg;
154*291Smike_s if ((input = fopen(filename, "r")) != NULL) {
155*291Smike_s pfile();
156*291Smike_s (void) fclose(input);
157*291Smike_s } else {
158*291Smike_s prname();
159*291Smike_s perror(*curarg);
160*291Smike_s }
161*291Smike_s } else {
162*291Smike_s filename = "[stdin]";
163*291Smike_s input = stdin;
164*291Smike_s pfile();
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
167*291Smike_s (void) fflush(stdout);
168*291Smike_s return (exitstat);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /* types of input lines: */
172*291Smike_s #define PLAIN 0 /* ordinary line */
173*291Smike_s #define TRUE 1 /* a true #ifdef of a symbol known to us */
174*291Smike_s #define FALSE 2 /* a false #ifdef of a symbol known to us */
175*291Smike_s #define OTHER 3 /* an #ifdef of a symbol not known to us */
176*291Smike_s #define ELSE 4 /* #else */
177*291Smike_s #define ENDIF 5 /* #endif */
178*291Smike_s #define LEOF 6 /* end of file */
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /* should be int declaration, was char */
181*291Smike_s int reject; /* 0 or 1: pass thru; 1 or 2: ignore comments */
182*291Smike_s int linenum; /* current line number */
183*291Smike_s int stqcline; /* start of current comment or quote */
184*291Smike_s
1850Sstevel@tonic-gate char *errs[] = {
186*291Smike_s #define NO_ERR 0
1870Sstevel@tonic-gate "",
188*291Smike_s #define END_ERR 1
1890Sstevel@tonic-gate "",
190*291Smike_s #define ELSE_ERR 2
1910Sstevel@tonic-gate "Inappropriate else",
192*291Smike_s #define ENDIF_ERR 3
1930Sstevel@tonic-gate "Inappropriate endif",
194*291Smike_s #define IEOF_ERR 4
1950Sstevel@tonic-gate "Premature EOF in ifdef",
196*291Smike_s #define CEOF_ERR 5
1970Sstevel@tonic-gate "Premature EOF in comment",
198*291Smike_s #define Q1EOF_ERR 6
1990Sstevel@tonic-gate "Premature EOF in quoted character",
200*291Smike_s #define Q2EOF_ERR 7
2010Sstevel@tonic-gate "Premature EOF in quoted string"
2020Sstevel@tonic-gate };
2030Sstevel@tonic-gate
204*291Smike_s static void
pfile(void)205*291Smike_s pfile(void)
2060Sstevel@tonic-gate {
207*291Smike_s reject = 0;
208*291Smike_s (void) doif(-1, NO, reject, 0);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
211*291Smike_s static int
doif(int thissym,int inif,int prevreject,int depth)212*291Smike_s doif(
213*291Smike_s int thissym, /* index of the symbol who was last ifdef'ed */
214*291Smike_s int inif, /* YES or NO we are inside an ifdef */
215*291Smike_s int prevreject, /* previous value of reject */
216*291Smike_s int depth /* depth of ifdef's */
217*291Smike_s )
2180Sstevel@tonic-gate {
219*291Smike_s int lineval;
220*291Smike_s int thisreject;
221*291Smike_s int doret; /* tmp return value of doif */
222*291Smike_s int cursym; /* index of the symbol returned by checkline */
223*291Smike_s int stline; /* line number when called this time */
224*291Smike_s int err;
225*291Smike_s
226*291Smike_s stline = linenum;
227*291Smike_s for (;;) {
228*291Smike_s switch (lineval = checkline(&cursym)) {
229*291Smike_s case PLAIN:
230*291Smike_s flushline(YES);
231*291Smike_s break;
2320Sstevel@tonic-gate
233*291Smike_s case TRUE:
234*291Smike_s case FALSE:
235*291Smike_s thisreject = reject;
236*291Smike_s if (lineval == TRUE)
237*291Smike_s insym[cursym] = 1;
238*291Smike_s else {
239*291Smike_s if (reject < 2)
240*291Smike_s reject = ignore[cursym] ? 1 : 2;
241*291Smike_s insym[cursym] = -1;
242*291Smike_s }
243*291Smike_s if (ignore[cursym])
244*291Smike_s flushline(YES);
245*291Smike_s else {
246*291Smike_s exitstat = 0;
247*291Smike_s flushline(NO);
248*291Smike_s }
249*291Smike_s if ((doret = doif(cursym, YES,
250*291Smike_s thisreject, depth + 1)) != NO_ERR)
251*291Smike_s return (error(doret, stline, depth));
252*291Smike_s break;
253*291Smike_s
254*291Smike_s case OTHER:
255*291Smike_s flushline(YES);
256*291Smike_s if ((doret = doif(-1, YES,
257*291Smike_s reject, depth + 1)) != NO_ERR)
258*291Smike_s return (error(doret, stline, depth));
259*291Smike_s break;
260*291Smike_s
261*291Smike_s case ELSE:
262*291Smike_s if (inif != 1)
263*291Smike_s return (error(ELSE_ERR, linenum, depth));
264*291Smike_s inif = 2;
265*291Smike_s if (thissym >= 0) {
266*291Smike_s if ((insym[thissym] = -insym[thissym]) < 0)
267*291Smike_s reject = ignore[thissym] ? 1 : 2;
268*291Smike_s else
269*291Smike_s reject = prevreject;
270*291Smike_s if (!ignore[thissym]) {
271*291Smike_s flushline(NO);
272*291Smike_s break;
273*291Smike_s }
274*291Smike_s }
275*291Smike_s flushline(YES);
276*291Smike_s break;
2770Sstevel@tonic-gate
278*291Smike_s case ENDIF:
279*291Smike_s if (inif == 0)
280*291Smike_s return (error(ENDIF_ERR, linenum, depth));
281*291Smike_s if (thissym >= 0) {
282*291Smike_s insym[thissym] = 0;
283*291Smike_s reject = prevreject;
284*291Smike_s if (!ignore[thissym]) {
285*291Smike_s flushline(NO);
286*291Smike_s return (NO_ERR);
287*291Smike_s }
288*291Smike_s }
289*291Smike_s flushline(YES);
290*291Smike_s return (NO_ERR);
291*291Smike_s
292*291Smike_s case LEOF:
293*291Smike_s err = incomment
294*291Smike_s ? CEOF_ERR
295*291Smike_s : inquote[QUOTE1]
296*291Smike_s ? Q1EOF_ERR
297*291Smike_s : inquote[QUOTE2]
298*291Smike_s ? Q2EOF_ERR
299*291Smike_s : NO_ERR;
300*291Smike_s if (inif) {
301*291Smike_s if (err != NO_ERR)
302*291Smike_s (void) error(err, stqcline, depth);
303*291Smike_s return (error(IEOF_ERR, stline, depth));
304*291Smike_s } else if (err != NO_ERR)
305*291Smike_s return (error(err, stqcline, depth));
306*291Smike_s else
307*291Smike_s return (NO_ERR);
308*291Smike_s }
309*291Smike_s }
310*291Smike_s }
3110Sstevel@tonic-gate
312*291Smike_s #define endsym(c) (!isalpha(c) && !isdigit(c) && c != '_')
313*291Smike_s
314*291Smike_s #define MAXLINE 256
315*291Smike_s char tline[MAXLINE];
316*291Smike_s
317*291Smike_s static int
checkline(int * cursym)318*291Smike_s checkline(int *cursym)
319*291Smike_s {
320*291Smike_s char *cp;
321*291Smike_s char *symp;
322*291Smike_s char chr;
323*291Smike_s char *scp;
324*291Smike_s int retval;
325*291Smike_s int symind;
326*291Smike_s char keyword[KWSIZE];
3270Sstevel@tonic-gate
328*291Smike_s linenum++;
329*291Smike_s if (getlin(tline, sizeof (tline), input, NO) == EOF)
330*291Smike_s return (LEOF);
331*291Smike_s
332*291Smike_s retval = PLAIN;
333*291Smike_s if (*(cp = tline) != '#' || incomment ||
334*291Smike_s inquote[QUOTE1] || inquote[QUOTE2])
335*291Smike_s goto eol;
336*291Smike_s
3370Sstevel@tonic-gate cp = skipcomment(++cp);
338*291Smike_s symp = keyword;
339*291Smike_s while (!endsym (*cp)) {
340*291Smike_s *symp = *cp++;
341*291Smike_s if (++symp >= &keyword[KWSIZE])
342*291Smike_s goto eol;
343*291Smike_s }
344*291Smike_s *symp = '\0';
345*291Smike_s
346*291Smike_s if (strcmp(keyword, "ifdef") == 0) {
3470Sstevel@tonic-gate retval = YES;
3480Sstevel@tonic-gate goto ifdef;
349*291Smike_s } else if (strcmp(keyword, "if") == 0) {
350*291Smike_s cp = skipcomment(++cp);
351*291Smike_s if (strcmp(nextsym(cp), "defined") == 0) {
352*291Smike_s cp += strlen("defined") + 1;
353*291Smike_s /* skip to identifier */
354*291Smike_s while (endsym(*cp))
355*291Smike_s ++cp;
356*291Smike_s retval = YES;
357*291Smike_s goto ifdef;
358*291Smike_s } else {
359*291Smike_s retval = OTHER;
360*291Smike_s goto eol;
361*291Smike_s }
362*291Smike_s } else if (strcmp(keyword, "ifndef") == 0) {
363*291Smike_s retval = NO;
364*291Smike_s ifdef:
365*291Smike_s scp = cp = skipcomment(cp);
366*291Smike_s if (incomment) {
367*291Smike_s retval = PLAIN;
368*291Smike_s goto eol;
3690Sstevel@tonic-gate }
370*291Smike_s symind = 0;
371*291Smike_s for (;;) {
372*291Smike_s if (insym[symind] == 0) {
373*291Smike_s for (symp = sym[symind], cp = scp;
374*291Smike_s *symp && *cp == *symp; cp++, symp++) {
375*291Smike_s /* NULL */
376*291Smike_s }
377*291Smike_s chr = *cp;
378*291Smike_s if (*symp == '\0' && endsym(chr)) {
379*291Smike_s *cursym = symind;
380*291Smike_s retval = (retval ^ true[symind]) ?
381*291Smike_s FALSE : TRUE;
382*291Smike_s break;
383*291Smike_s }
384*291Smike_s }
385*291Smike_s if (++symind >= nsyms) {
386*291Smike_s retval = OTHER;
387*291Smike_s break;
388*291Smike_s }
389*291Smike_s }
390*291Smike_s } else if (strcmp(keyword, "else") == 0)
391*291Smike_s retval = ELSE;
392*291Smike_s else if (strcmp(keyword, "endif") == 0)
393*291Smike_s retval = ENDIF;
3940Sstevel@tonic-gate
395*291Smike_s eol:
396*291Smike_s if (!text && !reject)
397*291Smike_s while (*cp) {
398*291Smike_s if (incomment)
399*291Smike_s cp = skipcomment(cp);
400*291Smike_s else if (inquote[QUOTE1])
401*291Smike_s cp = skipquote(cp, QUOTE1);
402*291Smike_s else if (inquote[QUOTE2])
403*291Smike_s cp = skipquote(cp, QUOTE2);
404*291Smike_s else if (*cp == '/' && cp[1] == '*')
405*291Smike_s cp = skipcomment(cp);
406*291Smike_s else if (*cp == '\'')
407*291Smike_s cp = skipquote(cp, QUOTE1);
408*291Smike_s else if (*cp == '"')
409*291Smike_s cp = skipquote(cp, QUOTE2);
410*291Smike_s else
411*291Smike_s cp++;
412*291Smike_s }
413*291Smike_s return (retval);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate /*
417*291Smike_s * Skip over comments and stop at the next character
418*291Smike_s * position that is not whitespace.
419*291Smike_s */
420*291Smike_s static char *
skipcomment(char * cp)421*291Smike_s skipcomment(char *cp)
4220Sstevel@tonic-gate {
423*291Smike_s if (incomment)
424*291Smike_s goto inside;
425*291Smike_s for (;;) {
426*291Smike_s while (*cp == ' ' || *cp == '\t')
427*291Smike_s cp++;
428*291Smike_s if (text)
429*291Smike_s return (cp);
430*291Smike_s if (cp[0] != '/' || cp[1] != '*')
431*291Smike_s return (cp);
432*291Smike_s cp += 2;
433*291Smike_s if (!incomment) {
434*291Smike_s incomment = YES;
435*291Smike_s stqcline = linenum;
436*291Smike_s }
437*291Smike_s inside:
438*291Smike_s for (;;) {
439*291Smike_s for (; *cp != '*'; cp++)
440*291Smike_s if (*cp == '\0')
441*291Smike_s return (cp);
442*291Smike_s if (*++cp == '/')
443*291Smike_s break;
444*291Smike_s }
445*291Smike_s incomment = NO;
446*291Smike_s cp++;
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate
450*291Smike_s /*
451*291Smike_s * Skip over a quoted string or character and stop at the next charaacter
452*291Smike_s * position that is not whitespace.
453*291Smike_s */
454*291Smike_s static char *
skipquote(char * cp,int type)455*291Smike_s skipquote(char *cp, int type)
4560Sstevel@tonic-gate {
457*291Smike_s char qchar;
458*291Smike_s
459*291Smike_s qchar = type == QUOTE1 ? '\'' : '"';
460*291Smike_s
461*291Smike_s if (inquote[type])
462*291Smike_s goto inside;
463*291Smike_s for (;;) {
464*291Smike_s if (*cp != qchar)
465*291Smike_s return (cp);
466*291Smike_s cp++;
467*291Smike_s if (!inquote[type]) {
468*291Smike_s inquote[type] = YES;
469*291Smike_s stqcline = linenum;
470*291Smike_s }
471*291Smike_s inside:
472*291Smike_s for (; ; cp++) {
473*291Smike_s if (*cp == qchar)
474*291Smike_s break;
475*291Smike_s if (*cp == '\0' || *cp == '\\' && *++cp == '\0')
476*291Smike_s return (cp);
477*291Smike_s }
478*291Smike_s inquote[type] = NO;
479*291Smike_s cp++;
480*291Smike_s }
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /*
484*291Smike_s * special getlin - treats form-feed as an end-of-line
485*291Smike_s * and expands tabs if asked for
486*291Smike_s */
487*291Smike_s static int
getlin(char * line,int maxline,FILE * inp,int expandtabs)488*291Smike_s getlin(char *line, int maxline, FILE *inp, int expandtabs)
4890Sstevel@tonic-gate {
490*291Smike_s int tmp;
491*291Smike_s int num;
492*291Smike_s int chr;
493*291Smike_s #ifdef FFSPECIAL
494*291Smike_s static char havechar = NO; /* have leftover char from last time */
495*291Smike_s static char svchar;
496*291Smike_s #endif
497*291Smike_s
498*291Smike_s num = 0;
499*291Smike_s #ifdef FFSPECIAL
500*291Smike_s if (havechar) {
501*291Smike_s havechar = NO;
502*291Smike_s chr = svchar;
503*291Smike_s goto ent;
504*291Smike_s }
505*291Smike_s #endif
506*291Smike_s while (num + 8 < maxline) { /* leave room for tab */
507*291Smike_s chr = getc(inp);
508*291Smike_s if (isprint(chr)) {
509*291Smike_s #ifdef FFSPECIAL
510*291Smike_s ent:
511*291Smike_s #endif
512*291Smike_s *line++ = chr;
513*291Smike_s num++;
514*291Smike_s } else
515*291Smike_s switch (chr) {
516*291Smike_s case EOF:
517*291Smike_s return (EOF);
5180Sstevel@tonic-gate
519*291Smike_s case '\t':
520*291Smike_s if (expandtabs) {
521*291Smike_s num += tmp = 8 - (num & 7);
522*291Smike_s do
523*291Smike_s *line++ = ' ';
524*291Smike_s while (--tmp);
525*291Smike_s break;
526*291Smike_s }
527*291Smike_s default:
528*291Smike_s *line++ = chr;
529*291Smike_s num++;
530*291Smike_s break;
531*291Smike_s
532*291Smike_s case '\n':
533*291Smike_s *line = '\n';
534*291Smike_s num++;
535*291Smike_s goto end;
536*291Smike_s
537*291Smike_s #ifdef FFSPECIAL
538*291Smike_s case '\f':
539*291Smike_s if (++num == 1)
540*291Smike_s *line = '\f';
541*291Smike_s else {
542*291Smike_s *line = '\n';
543*291Smike_s havechar = YES;
544*291Smike_s svchar = chr;
545*291Smike_s }
546*291Smike_s goto end;
547*291Smike_s #endif
548*291Smike_s }
549*291Smike_s }
550*291Smike_s end:
551*291Smike_s *++line = '\0';
552*291Smike_s return (num);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate
555*291Smike_s static void
flushline(int keep)556*291Smike_s flushline(int keep)
5570Sstevel@tonic-gate {
558*291Smike_s if ((keep && reject < 2) ^ complement)
559*291Smike_s putlin(tline, stdout);
560*291Smike_s else if (lnblank)
561*291Smike_s putlin("\n", stdout);
562*291Smike_s }
563*291Smike_s
564*291Smike_s /*
565*291Smike_s * putlin - for tools
566*291Smike_s */
567*291Smike_s static void
putlin(char * line,FILE * fio)568*291Smike_s putlin(char *line, FILE *fio)
569*291Smike_s {
570*291Smike_s char chr;
571*291Smike_s
572*291Smike_s while (chr = *line++)
573*291Smike_s (void) putc(chr, fio);
574*291Smike_s }
575*291Smike_s
576*291Smike_s static void
prname(void)577*291Smike_s prname(void)
578*291Smike_s {
579*291Smike_s (void) fprintf(stderr, "%s: ", progname);
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate
583*291Smike_s static int
error(int err,int line,int depth)584*291Smike_s error(int err, int line, int depth)
5850Sstevel@tonic-gate {
586*291Smike_s if (err == END_ERR)
587*291Smike_s return (err);
5880Sstevel@tonic-gate
589*291Smike_s prname();
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate #ifndef TESTING
592*291Smike_s (void) fprintf(stderr, gettext("Error in %s line %d: %s.\n"),
593*291Smike_s filename, line, gettext(errs[err]));
5940Sstevel@tonic-gate #endif
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate #ifdef TESTING
597*291Smike_s (void) fprintf(stderr, gettext("Error in %s line %d: %s. "),
598*291Smike_s filename, line, errs[err]);
599*291Smike_s (void) fprintf(stderr, gettext("ifdef depth: %d\n"), depth);
6000Sstevel@tonic-gate #endif
6010Sstevel@tonic-gate
602*291Smike_s exitstat = 1;
603*291Smike_s return (depth > 1 ? IEOF_ERR : END_ERR);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate /* return the next token in the line buffer */
6070Sstevel@tonic-gate char *
nextsym(char * p)608*291Smike_s nextsym(char *p)
6090Sstevel@tonic-gate {
610*291Smike_s char *key;
611*291Smike_s int i = KWSIZE;
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate key = buf;
6140Sstevel@tonic-gate while (!endsym(*p) && --i)
6150Sstevel@tonic-gate *key++ = *p++;
6160Sstevel@tonic-gate *key = '\0';
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate return (buf);
6190Sstevel@tonic-gate }
620