2
* Comments by AJS, 020301:
4
* This code appears to recognize but not handle "#if" directives.
6
* The LICENSE file is already in the C code below.
8
* The README file follows:
10
* This is the standard "unifdef" from BSD 4.4lite, hacked to allow for
11
* C++ comments. -- ajw@cs.cmu.edu
13
* Obtained 020301 via http://freshmeat.net/projects/unifdef/. -- ajs
14
* Made repairs to avoid compile warnings on Linux (gcc). -- ajs
15
* Modified to return 0, not 1, even when text modified. -- ajs
19
* Copyright (c) 1985, 1993
20
* The Regents of the University of California. All rights reserved.
22
* This code is derived from software contributed to Berkeley by
25
* Redistribution and use in source and binary forms, with or without
26
* modification, are permitted provided that the following conditions
28
* 1. Redistributions of source code must retain the above copyright
29
* notice, this list of conditions and the following disclaimer.
30
* 2. Redistributions in binary form must reproduce the above copyright
31
* notice, this list of conditions and the following disclaimer in the
32
* documentation and/or other materials provided with the distribution.
33
* 3. All advertising materials mentioning features or use of this software
34
* must display the following acknowledgement:
35
* This product includes software developed by the University of
36
* California, Berkeley and its contributors.
37
* 4. Neither the name of the University nor the names of its contributors
38
* may be used to endorse or promote products derived from this software
39
* without specific prior written permission.
41
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55
static char copyright[] =
56
"@(#) Copyright (c) 1985, 1993\n\
57
The Regents of the University of California. All rights reserved.\n";
61
static char sccsid[] = "@(#)unifdef.c 8.1 (Berkeley) 6/6/93\n@(#) $Revision: 4.2 $ $Source: /judy/tool/unifdef.c $";
65
* unifdef - remove ifdef'ed lines
67
* Warning: will not work correctly if input contains null characters.
70
* provide an option which will append the name of the
71
* appropriate symbol after #else's and #endif's
72
* provide an option which will check symbols after
73
* #else's and #endif's to see that they match their
74
* corresponding #ifdef or #ifndef
92
char text BSS; /* -t option in effect: this is a text file */
93
char lnblank BSS; /* -l option in effect: blank deleted lines */
94
char complement BSS; /* -c option in effect: complement the operation */
97
char *symname[MAXSYMS] BSS; /* symbol name */
98
char true[MAXSYMS] BSS; /* -Dsym */
99
char ignore[MAXSYMS] BSS; /* -iDsym or -iUsym */
100
char insym[MAXSYMS] BSS; /* state: false, inactive, true */
101
#define SYM_INACTIVE 0 /* symbol is currently inactive */
102
#define SYM_FALSE 1 /* symbol is currently false */
103
#define SYM_TRUE 2 /* symbol is currently true */
106
char incomment BSS; /* inside C comment */
107
char inCPPcomment BSS; /* inside C++ comment */
110
#define QUOTE_SINGLE 1
111
#define QUOTE_DOUBLE 2
112
char inquote BSS; /* inside single or double quotes */
116
typedef int Reject_level;
117
typedef int Linetype;
119
#define FUNCTION /* null, to find functions */
121
int main(int argc, char ** argv);
123
int doif(register int thissym, int inif, Reject_level prevreject,
125
Linetype checkline(int *cursym);
126
char * skipcomment(register char *cp);
127
char * skipquote(register char *cp, register int type);
128
int findsym(char *str);
129
int getlin(register char * line, int maxline, FILE * inp, int expandtabs);
130
void flushline(Bool keep);
132
int error(int err, int line, int depth);
134
FUNCTION int main(int argc, char ** argv)
141
/* Make compiler happy: */
146
progname = argv[0][0] ? argv[0] : "unifdef";
148
for (curarg = &argv[1]; --argc > 0; curarg++) {
149
if (*(cp1 = cp = *curarg) != '-')
163
if ((symind = findsym (&cp1[1])) < 0) {
164
if (nsyms >= MAXSYMS) {
166
fprintf (stderr, "too many symbols.\n");
170
symname[symind] = &cp1[1];
171
insym[symind] = SYM_INACTIVE;
173
ignore[symind] = ignorethis;
174
true[symind] = *cp1 == 'D' ? YES : NO;
175
} else if (ignorethis)
177
else if (strcmp (&cp[1], "t") == 0)
179
else if (strcmp (&cp[1], "l") == 0)
181
else if (strcmp (&cp[1], "c") == 0)
186
fprintf (stderr, "unrecognized option: %s\n", cp);
193
Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-iDsym] [-iUsym]]... [file]\n\
194
At least one arg from [-D -U -iD -iU] is required\n", progname);
200
fprintf (stderr, "can only do one file.\n");
201
} else if (argc == 1) {
203
if ((input = fopen (filename, "r")) != NULL) {
205
(void) fclose (input);
208
fprintf (stderr, "can't open ");
212
filename = "[stdin]";
217
(void) fflush (stdout);
221
/* types of input lines: */
222
#define LT_PLAIN 0 /* ordinary line */
223
#define LT_TRUE 1 /* a true #ifdef of a symbol known to us */
224
#define LT_FALSE 2 /* a false #ifdef of a symbol known to us */
225
#define LT_OTHER 3 /* an #ifdef of a symbol not known to us */
226
#define LT_IF 4 /* an #ifdef of a symbol not known to us */
227
#define LT_ELSE 5 /* #else */
228
#define LT_ENDIF 6 /* #endif */
229
#define LT_LEOF 7 /* end of file */
231
Reject_level reject BSS; /* 0 or 1: pass thru; 1 or 2: ignore comments */
236
int linenum BSS; /* current line number */
237
int stqcline BSS; /* start of current coment or quote */
244
"Inappropriate else",
246
"Inappropriate endif",
248
"Premature EOF in ifdef",
250
"Premature EOF in comment",
252
"Premature EOF in quoted character",
254
"Premature EOF in quoted string"
257
/* States for inif arg to doif */
262
FUNCTION void pfile(void)
265
(void) doif (-1, IN_NONE, reject, 0);
270
register int thissym, /* index of the symbol who was last ifdef'ed */
271
int inif, /* YES or NO we are inside an ifdef */
272
Reject_level prevreject, /* previous value of reject */
273
int depth) /* depth of ifdef's */
275
register Linetype lineval;
276
register Reject_level thisreject;
277
int doret; /* tmp return value of doif */
278
int cursym; /* index of the symbol returned by checkline */
279
int stline; /* line number when called this time */
283
switch (lineval = checkline (&cursym)) {
291
if (lineval == LT_TRUE)
292
insym[cursym] = SYM_TRUE;
294
if (reject != REJ_YES)
295
reject = ignore[cursym] ? REJ_IGNORE : REJ_YES;
296
insym[cursym] = SYM_FALSE;
301
exitstat = 0; /* was 1, but bothers make(1) -- ajs */
304
if ((doret = doif (cursym, IN_IF, thisreject, depth + 1)) != NO_ERR)
305
return error (doret, stline, depth);
311
if ((doret = doif (-1, IN_IF, reject, depth + 1)) != NO_ERR)
312
return error (doret, stline, depth);
317
return error (ELSE_ERR, linenum, depth);
320
if (insym[thissym] == SYM_TRUE) {
321
reject = ignore[thissym] ? REJ_IGNORE : REJ_YES;
322
insym[thissym] = SYM_FALSE;
323
} else { /* (insym[thissym] == SYM_FALSE) */
325
insym[thissym] = SYM_TRUE;
327
if (!ignore[thissym]) {
337
return error (ENDIF_ERR, linenum, depth);
339
insym[thissym] = SYM_INACTIVE;
341
if (!ignore[thissym]) {
353
: inquote == QUOTE_SINGLE
355
: inquote == QUOTE_DOUBLE
358
if (inif != IN_NONE) {
360
(void) error (err, stqcline, depth);
361
return error (IEOF_ERR, stline, depth);
362
} else if (err != NO_ERR)
363
return error (err, stqcline, depth);
371
#define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_')
374
char tline[MAXLINE] BSS;
376
FUNCTION Linetype checkline(
377
int *cursym) /* if LT_TRUE or LT_FALSE returned, set this to sym index */
384
char keyword[KWSIZE];
387
if (getlin (tline, sizeof tline, input, NO) == EOF)
391
if ( *(cp = tline) != '#'
393
|| inquote == QUOTE_SINGLE
394
|| inquote == QUOTE_DOUBLE
398
cp = skipcomment (++cp);
400
while (!endsym (*cp)) {
402
if (++symp >= &keyword[KWSIZE])
407
if (strcmp (keyword, "ifdef") == 0) {
410
} else if (strcmp (keyword, "ifndef") == 0) {
413
scp = cp = skipcomment (++cp);
421
if ((symind = findsym (scp)) >= 0)
422
retval = (retval ^ true[*cursym = symind])
423
? LT_FALSE : LT_TRUE;
427
} else if (strcmp (keyword, "if") == 0)
429
else if (strcmp (keyword, "else") == 0)
431
else if (strcmp (keyword, "endif") == 0)
435
if (!text && reject != REJ_IGNORE)
438
cp = skipcomment (cp);
439
else if (inquote == QUOTE_SINGLE)
440
cp = skipquote (cp, QUOTE_SINGLE);
441
else if (inquote == QUOTE_DOUBLE)
442
cp = skipquote (cp, QUOTE_DOUBLE);
443
else if (*cp == '/' && (cp[1] == '*' || cp[1] == '/'))
444
cp = skipcomment (cp);
445
else if (*cp == '\'')
446
cp = skipquote (cp, QUOTE_SINGLE);
448
cp = skipquote (cp, QUOTE_DOUBLE);
456
* Skip over comments and stop at the next charaacter
457
* position that is not whitespace.
459
FUNCTION char * skipcomment(
465
while (*cp == ' ' || *cp == '\t')
470
|| (cp[1] != '*' && cp[1] != '/')
475
inCPPcomment = (cp[1] == '/');
481
for (; *cp != '*'; cp++)
497
* Skip over a quoted string or character and stop at the next charaacter
498
* position that is not whitespace.
500
FUNCTION char * skipquote(
506
qchar = ((type == QUOTE_SINGLE) ? '\'' : '"');
521
|| (*cp == '\\' && *++cp == '\0')
525
inquote = QUOTE_NONE;
530
* findsym - look for the symbol in the symbol table.
531
* if found, return symbol table index,
534
FUNCTION int findsym(char *str)
541
for (symind = 0; symind < nsyms; ++symind) {
542
if (insym[symind] == SYM_INACTIVE) {
543
for ( symp = symname[symind], cp = str
544
; *symp && *cp == *symp
549
if (*symp == '\0' && endsym (chr))
557
* getlin - expands tabs if asked for
558
* and (if compiled in) treats form-feed as an end-of-line
560
FUNCTION int getlin(register char * line, int maxline, FILE * inp, int expandtabs)
566
static char havechar = NO; /* have leftover char from last time */
567
static char svchar BSS;
578
while (num + 8 < maxline) { /* leave room for tab */
586
num += tmp = 8 - (num & 7);
621
FUNCTION void flushline(Bool keep)
623
if ((keep && reject != REJ_YES) ^ complement) {
624
register char *line = tline;
625
register FILE *out = stdout;
628
while ((chr = *line++))
635
FUNCTION void prname(void)
637
fprintf (stderr, "%s: ", progname);
642
int err, /* type of error & index into error string array */
643
int line, /* line number */
644
int depth) /* how many ifdefs we are inside */
652
fprintf (stderr, "Error in %s line %d: %s.\n", filename, line, errs[err]);
654
fprintf (stderr, "Error in %s line %d: %s. ", filename, line, errs[err]);
655
fprintf (stderr, "ifdef depth: %d\n", depth);
659
return depth > 1 ? IEOF_ERR : END_ERR;