4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 /* Copyright (c) 1982 Regents of the University of California */
33 * unifdef - remove ifdef'ed lines
51 char text
; /* -t option in effect: this is a text file */
52 char lnblank
; /* -l option in effect: blank deleted lines */
53 char complement
; /* -c option in effect: complement the operation */
58 signed char insym
[MAXSYMS
];
68 static char *skipcomment(char *cp
);
69 static char *skipquote(char *cp
, int type
);
70 static char *nextsym(char *p
);
71 static int doif(int thissym
, int inif
, int prevreject
, int depth
);
72 static void pfile(void);
73 static int getlin(char *line
, int maxline
, FILE *inp
, int expandtabs
);
74 static void prname(void);
75 static void flushline(int keep
);
76 static int checkline(int *cursym
);
77 static int error(int err
, int line
, int depth
);
78 static void putlin(char *line
, FILE *fio
);
83 (void) fprintf(stderr
, gettext(
84 "Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-idsym] "
85 "[-iusym]]... [file]\n"
86 " At least one arg from [-D -U -id -iu] is required\n"),
92 main(int argc
, char **argv
)
99 (void) setlocale(LC_ALL
, "");
101 #if !defined(TEXT_DOMAIN)
102 #define TEXT_DOMAIN "SYS_TEST"
104 (void) textdomain(TEXT_DOMAIN
);
106 progname
= argv
[0][0] ? argv
[0] : "unifdef";
108 for (curarg
= &argv
[1]; --argc
> 0; curarg
++) {
109 if (*(cp1
= cp
= *curarg
) != '-')
116 if ((*cp1
== 'D' || *cp1
== 'U') &&
118 if (nsyms
>= MAXSYMS
) {
120 (void) fprintf(stderr
,
121 gettext("too many symbols.\n"));
124 ignore
[nsyms
] = ignorethis
;
125 true[nsyms
] = *cp1
== 'D' ? YES
: NO
;
126 sym
[nsyms
++] = &cp1
[1];
127 } else if (ignorethis
)
129 else if (strcmp(&cp
[1], "t") == 0)
131 else if (strcmp(&cp
[1], "l") == 0)
133 else if (strcmp(&cp
[1], "c") == 0)
138 (void) fprintf(stderr
,
139 gettext("unrecognized option: %s\n"), cp
);
149 (void) fprintf(stderr
, gettext("can only do one file.\n"));
150 } else if (argc
== 1) {
152 if ((input
= fopen(filename
, "r")) != NULL
) {
154 (void) fclose(input
);
160 filename
= "[stdin]";
165 (void) fflush(stdout
);
169 /* types of input lines: */
170 #define PLAIN 0 /* ordinary line */
171 #define TRUE 1 /* a true #ifdef of a symbol known to us */
172 #define FALSE 2 /* a false #ifdef of a symbol known to us */
173 #define OTHER 3 /* an #ifdef of a symbol not known to us */
174 #define ELSE 4 /* #else */
175 #define ENDIF 5 /* #endif */
176 #define LEOF 6 /* end of file */
178 /* should be int declaration, was char */
179 int reject
; /* 0 or 1: pass thru; 1 or 2: ignore comments */
180 int linenum
; /* current line number */
181 int stqcline
; /* start of current comment or quote */
189 "Inappropriate else",
191 "Inappropriate endif",
193 "Premature EOF in ifdef",
195 "Premature EOF in comment",
197 "Premature EOF in quoted character",
199 "Premature EOF in quoted string"
206 (void) doif(-1, NO
, reject
, 0);
211 int thissym
, /* index of the symbol who was last ifdef'ed */
212 int inif
, /* YES or NO we are inside an ifdef */
213 int prevreject
, /* previous value of reject */
214 int depth
/* depth of ifdef's */
219 int doret
; /* tmp return value of doif */
220 int cursym
; /* index of the symbol returned by checkline */
221 int stline
; /* line number when called this time */
226 switch (lineval
= checkline(&cursym
)) {
238 reject
= ignore
[cursym
] ? 1 : 2;
247 if ((doret
= doif(cursym
, YES
,
248 thisreject
, depth
+ 1)) != NO_ERR
)
249 return (error(doret
, stline
, depth
));
254 if ((doret
= doif(-1, YES
,
255 reject
, depth
+ 1)) != NO_ERR
)
256 return (error(doret
, stline
, depth
));
261 return (error(ELSE_ERR
, linenum
, depth
));
264 if ((insym
[thissym
] = -insym
[thissym
]) < 0)
265 reject
= ignore
[thissym
] ? 1 : 2;
268 if (!ignore
[thissym
]) {
278 return (error(ENDIF_ERR
, linenum
, depth
));
282 if (!ignore
[thissym
]) {
300 (void) error(err
, stqcline
, depth
);
301 return (error(IEOF_ERR
, stline
, depth
));
302 } else if (err
!= NO_ERR
)
303 return (error(err
, stqcline
, depth
));
310 #define endsym(c) (!isalpha(c) && !isdigit(c) && c != '_')
316 checkline(int *cursym
)
324 char keyword
[KWSIZE
];
327 if (getlin(tline
, sizeof (tline
), input
, NO
) == EOF
)
331 if (*(cp
= tline
) != '#' || incomment
||
332 inquote
[QUOTE1
] || inquote
[QUOTE2
])
335 cp
= skipcomment(++cp
);
337 while (!endsym (*cp
)) {
339 if (++symp
>= &keyword
[KWSIZE
])
344 if (strcmp(keyword
, "ifdef") == 0) {
347 } else if (strcmp(keyword
, "if") == 0) {
348 cp
= skipcomment(++cp
);
349 if (strcmp(nextsym(cp
), "defined") == 0) {
350 cp
+= strlen("defined") + 1;
351 /* skip to identifier */
360 } else if (strcmp(keyword
, "ifndef") == 0) {
363 scp
= cp
= skipcomment(cp
);
370 if (insym
[symind
] == 0) {
371 for (symp
= sym
[symind
], cp
= scp
;
372 *symp
&& *cp
== *symp
; cp
++, symp
++) {
376 if (*symp
== '\0' && endsym(chr
)) {
378 retval
= (retval
^ true[symind
]) ?
383 if (++symind
>= nsyms
) {
388 } else if (strcmp(keyword
, "else") == 0)
390 else if (strcmp(keyword
, "endif") == 0)
394 if (!text
&& !reject
)
397 cp
= skipcomment(cp
);
398 else if (inquote
[QUOTE1
])
399 cp
= skipquote(cp
, QUOTE1
);
400 else if (inquote
[QUOTE2
])
401 cp
= skipquote(cp
, QUOTE2
);
402 else if (*cp
== '/' && cp
[1] == '*')
403 cp
= skipcomment(cp
);
404 else if (*cp
== '\'')
405 cp
= skipquote(cp
, QUOTE1
);
407 cp
= skipquote(cp
, QUOTE2
);
415 * Skip over comments and stop at the next character
416 * position that is not whitespace.
419 skipcomment(char *cp
)
424 while (*cp
== ' ' || *cp
== '\t')
428 if (cp
[0] != '/' || cp
[1] != '*')
437 for (; *cp
!= '*'; cp
++)
449 * Skip over a quoted string or character and stop at the next charaacter
450 * position that is not whitespace.
453 skipquote(char *cp
, int type
)
457 qchar
= type
== QUOTE1
? '\'' : '"';
465 if (!inquote
[type
]) {
473 if (*cp
== '\0' || *cp
== '\\' && *++cp
== '\0')
482 * special getlin - treats form-feed as an end-of-line
483 * and expands tabs if asked for
486 getlin(char *line
, int maxline
, FILE *inp
, int expandtabs
)
492 static char havechar
= NO
; /* have leftover char from last time */
504 while (num
+ 8 < maxline
) { /* leave room for tab */
519 num
+= tmp
= 8 - (num
& 7);
557 if ((keep
&& reject
< 2) ^ complement
)
558 putlin(tline
, stdout
);
560 putlin("\n", stdout
);
567 putlin(char *line
, FILE *fio
)
571 while (chr
= *line
++)
572 (void) putc(chr
, fio
);
578 (void) fprintf(stderr
, "%s: ", progname
);
583 error(int err
, int line
, int depth
)
591 (void) fprintf(stderr
, gettext("Error in %s line %d: %s.\n"),
592 filename
, line
, gettext(errs
[err
]));
596 (void) fprintf(stderr
, gettext("Error in %s line %d: %s. "),
597 filename
, line
, errs
[err
]);
598 (void) fprintf(stderr
, gettext("ifdef depth: %d\n"), depth
);
602 return (depth
> 1 ? IEOF_ERR
: END_ERR
);
605 /* return the next token in the line buffer */
613 while (!endsym(*p
) && --i
)