Commit | Line | Data |
---|---|---|
dc533d04 KB |
1 | /* |
2 | * Copyright (c) 1985 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Dave Yost. | |
7 | * | |
6ecf3d85 | 8 | * %sccs.include.redist.c% |
dc533d04 KB |
9 | */ |
10 | ||
476fcd16 | 11 | #ifndef lint |
dc533d04 KB |
12 | char copyright[] = |
13 | "@(#) Copyright (c) 1985 The Regents of the University of California.\n\ | |
14 | All rights reserved.\n"; | |
15 | #endif /* not lint */ | |
16 | ||
17 | #ifndef lint | |
6ecf3d85 | 18 | static char sccsid[] = "@(#)unifdef.c 4.7 (Berkeley) %G%"; |
dc533d04 | 19 | #endif /* not lint */ |
ba2c33c2 | 20 | |
476fcd16 SL |
21 | /* |
22 | * unifdef - remove ifdef'ed lines | |
f42d2b57 KB |
23 | * |
24 | * Warning: will not work correctly if input contains null characters. | |
25 | * | |
26 | * Wishlist: | |
27 | * provide an option which will append the name of the | |
28 | * appropriate symbol after #else's and #endif's | |
29 | * provide an option which will check symbols after | |
30 | * #else's and #endif's to see that they match their | |
31 | * corresponding #ifdef or #ifndef | |
476fcd16 SL |
32 | */ |
33 | ||
ba2c33c2 KM |
34 | #include <stdio.h> |
35 | #include <ctype.h> | |
dc533d04 | 36 | |
ba2c33c2 KM |
37 | #define BSS |
38 | FILE *input; | |
39 | #ifndef YES | |
40 | #define YES 1 | |
41 | #define NO 0 | |
f42d2b57 KB |
42 | #endif/*YES */ |
43 | typedef int Bool; | |
ba2c33c2 KM |
44 | |
45 | char *progname BSS; | |
46 | char *filename BSS; | |
47 | char text BSS; /* -t option in effect: this is a text file */ | |
48 | char lnblank BSS; /* -l option in effect: blank deleted lines */ | |
49 | char complement BSS; /* -c option in effect: complement the operation */ | |
f42d2b57 | 50 | |
ba2c33c2 | 51 | #define MAXSYMS 100 |
f42d2b57 KB |
52 | char *symname[MAXSYMS] BSS; /* symbol name */ |
53 | char true[MAXSYMS] BSS; /* -Dsym */ | |
54 | char ignore[MAXSYMS] BSS; /* -iDsym or -iUsym */ | |
55 | char insym[MAXSYMS] BSS; /* state: false, inactive, true */ | |
56 | #define SYM_INACTIVE 0 /* symbol is currently inactive */ | |
57 | #define SYM_FALSE 1 /* symbol is currently false */ | |
58 | #define SYM_TRUE 2 /* symbol is currently true */ | |
59 | ||
ba2c33c2 | 60 | char nsyms BSS; |
f42d2b57 KB |
61 | char incomment BSS; /* inside C comment */ |
62 | ||
63 | #define QUOTE_NONE 0 | |
64 | #define QUOTE_SINGLE 1 | |
65 | #define QUOTE_DOUBLE 2 | |
66 | char inquote BSS; /* inside single or double quotes */ | |
67 | ||
ba2c33c2 KM |
68 | int exitstat BSS; |
69 | char *skipcomment (); | |
70 | char *skipquote (); | |
71 | ||
72 | main (argc, argv) | |
73 | int argc; | |
74 | char **argv; | |
75 | { | |
76 | char **curarg; | |
77 | register char *cp; | |
78 | register char *cp1; | |
79 | char ignorethis; | |
80 | ||
81 | progname = argv[0][0] ? argv[0] : "unifdef"; | |
82 | ||
83 | for (curarg = &argv[1]; --argc > 0; curarg++) { | |
84 | if (*(cp1 = cp = *curarg) != '-') | |
85 | break; | |
86 | if (*++cp1 == 'i') { | |
87 | ignorethis = YES; | |
88 | cp1++; | |
f42d2b57 | 89 | } else |
ba2c33c2 | 90 | ignorethis = NO; |
535a99db SL |
91 | if ( ( *cp1 == 'D' |
92 | || *cp1 == 'U' | |
ba2c33c2 KM |
93 | ) |
94 | && cp1[1] != '\0' | |
95 | ) { | |
f42d2b57 KB |
96 | register int symind; |
97 | ||
98 | if ((symind = findsym (&cp1[1])) < 0) { | |
99 | if (nsyms >= MAXSYMS) { | |
100 | prname (); | |
101 | fprintf (stderr, "too many symbols.\n"); | |
102 | exit (2); | |
103 | } | |
104 | symind = nsyms++; | |
105 | symname[symind] = &cp1[1]; | |
106 | insym[symind] = SYM_INACTIVE; | |
ba2c33c2 | 107 | } |
f42d2b57 KB |
108 | ignore[symind] = ignorethis; |
109 | true[symind] = *cp1 == 'D' ? YES : NO; | |
110 | } else if (ignorethis) | |
ba2c33c2 KM |
111 | goto unrec; |
112 | else if (strcmp (&cp[1], "t") == 0) | |
113 | text = YES; | |
114 | else if (strcmp (&cp[1], "l") == 0) | |
115 | lnblank = YES; | |
116 | else if (strcmp (&cp[1], "c") == 0) | |
117 | complement = YES; | |
118 | else { | |
119 | unrec: | |
120 | prname (); | |
121 | fprintf (stderr, "unrecognized option: %s\n", cp); | |
122 | goto usage; | |
123 | } | |
124 | } | |
125 | if (nsyms == 0) { | |
126 | usage: | |
127 | fprintf (stderr, "\ | |
f42d2b57 KB |
128 | Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-iDsym] [-iUsym]]... [file]\n\ |
129 | At least one arg from [-D -U -iD -iU] is required\n", progname); | |
ba2c33c2 KM |
130 | exit (2); |
131 | } | |
132 | ||
133 | if (argc > 1) { | |
134 | prname (); | |
135 | fprintf (stderr, "can only do one file.\n"); | |
f42d2b57 | 136 | } else if (argc == 1) { |
ba2c33c2 KM |
137 | filename = *curarg; |
138 | if ((input = fopen (filename, "r")) != NULL) { | |
139 | pfile(); | |
f42d2b57 KB |
140 | (void) fclose (input); |
141 | } else { | |
ba2c33c2 | 142 | prname (); |
f42d2b57 | 143 | fprintf (stderr, "can't open "); |
6404bb88 | 144 | perror(*curarg); |
ba2c33c2 | 145 | } |
f42d2b57 | 146 | } else { |
ba2c33c2 KM |
147 | filename = "[stdin]"; |
148 | input = stdin; | |
149 | pfile(); | |
150 | } | |
151 | ||
f42d2b57 | 152 | (void) fflush (stdout); |
ba2c33c2 KM |
153 | exit (exitstat); |
154 | } | |
155 | ||
156 | /* types of input lines: */ | |
f42d2b57 KB |
157 | typedef int Linetype; |
158 | #define LT_PLAIN 0 /* ordinary line */ | |
159 | #define LT_TRUE 1 /* a true #ifdef of a symbol known to us */ | |
160 | #define LT_FALSE 2 /* a false #ifdef of a symbol known to us */ | |
161 | #define LT_OTHER 3 /* an #ifdef of a symbol not known to us */ | |
162 | #define LT_IF 4 /* an #ifdef of a symbol not known to us */ | |
163 | #define LT_ELSE 5 /* #else */ | |
164 | #define LT_ENDIF 6 /* #endif */ | |
165 | #define LT_LEOF 7 /* end of file */ | |
166 | extern Linetype checkline (); | |
167 | ||
168 | typedef int Reject_level; | |
169 | Reject_level reject BSS; /* 0 or 1: pass thru; 1 or 2: ignore comments */ | |
170 | #define REJ_NO 0 | |
171 | #define REJ_IGNORE 1 | |
172 | #define REJ_YES 2 | |
173 | ||
ba2c33c2 KM |
174 | int linenum BSS; /* current line number */ |
175 | int stqcline BSS; /* start of current coment or quote */ | |
176 | char *errs[] = { | |
177 | #define NO_ERR 0 | |
178 | "", | |
179 | #define END_ERR 1 | |
180 | "", | |
181 | #define ELSE_ERR 2 | |
182 | "Inappropriate else", | |
183 | #define ENDIF_ERR 3 | |
184 | "Inappropriate endif", | |
185 | #define IEOF_ERR 4 | |
186 | "Premature EOF in ifdef", | |
187 | #define CEOF_ERR 5 | |
188 | "Premature EOF in comment", | |
189 | #define Q1EOF_ERR 6 | |
190 | "Premature EOF in quoted character", | |
191 | #define Q2EOF_ERR 7 | |
192 | "Premature EOF in quoted string" | |
193 | }; | |
194 | ||
f42d2b57 KB |
195 | /* States for inif arg to doif */ |
196 | #define IN_NONE 0 | |
197 | #define IN_IF 1 | |
198 | #define IN_ELSE 2 | |
199 | ||
ba2c33c2 KM |
200 | pfile () |
201 | { | |
f42d2b57 KB |
202 | reject = REJ_NO; |
203 | (void) doif (-1, IN_NONE, reject, 0); | |
ba2c33c2 KM |
204 | return; |
205 | } | |
206 | ||
f42d2b57 | 207 | int |
ba2c33c2 KM |
208 | doif (thissym, inif, prevreject, depth) |
209 | register int thissym; /* index of the symbol who was last ifdef'ed */ | |
210 | int inif; /* YES or NO we are inside an ifdef */ | |
f42d2b57 | 211 | Reject_level prevreject;/* previous value of reject */ |
ba2c33c2 KM |
212 | int depth; /* depth of ifdef's */ |
213 | { | |
f42d2b57 KB |
214 | register Linetype lineval; |
215 | register Reject_level thisreject; | |
216 | int doret; /* tmp return value of doif */ | |
ba2c33c2 KM |
217 | int cursym; /* index of the symbol returned by checkline */ |
218 | int stline; /* line number when called this time */ | |
219 | ||
220 | stline = linenum; | |
221 | for (;;) { | |
222 | switch (lineval = checkline (&cursym)) { | |
f42d2b57 | 223 | case LT_PLAIN: |
ba2c33c2 KM |
224 | flushline (YES); |
225 | break; | |
226 | ||
f42d2b57 KB |
227 | case LT_TRUE: |
228 | case LT_FALSE: | |
ba2c33c2 | 229 | thisreject = reject; |
f42d2b57 KB |
230 | if (lineval == LT_TRUE) |
231 | insym[cursym] = SYM_TRUE; | |
ba2c33c2 | 232 | else { |
f42d2b57 KB |
233 | if (reject != REJ_YES) |
234 | reject = ignore[cursym] ? REJ_IGNORE : REJ_YES; | |
235 | insym[cursym] = SYM_FALSE; | |
ba2c33c2 KM |
236 | } |
237 | if (ignore[cursym]) | |
238 | flushline (YES); | |
239 | else { | |
240 | exitstat = 1; | |
241 | flushline (NO); | |
242 | } | |
f42d2b57 | 243 | if ((doret = doif (cursym, IN_IF, thisreject, depth + 1)) != NO_ERR) |
ba2c33c2 | 244 | return error (doret, stline, depth); |
f42d2b57 | 245 | break; |
ba2c33c2 | 246 | |
f42d2b57 KB |
247 | case LT_IF: |
248 | case LT_OTHER: | |
ba2c33c2 | 249 | flushline (YES); |
f42d2b57 | 250 | if ((doret = doif (-1, IN_IF, reject, depth + 1)) != NO_ERR) |
ba2c33c2 KM |
251 | return error (doret, stline, depth); |
252 | break; | |
253 | ||
f42d2b57 KB |
254 | case LT_ELSE: |
255 | if (inif != IN_IF) | |
ba2c33c2 | 256 | return error (ELSE_ERR, linenum, depth); |
f42d2b57 | 257 | inif = IN_ELSE; |
ba2c33c2 | 258 | if (thissym >= 0) { |
f42d2b57 KB |
259 | if (insym[thissym] == SYM_TRUE) { |
260 | reject = ignore[thissym] ? REJ_IGNORE : REJ_YES; | |
261 | insym[thissym] = SYM_FALSE; | |
262 | } else { /* (insym[thissym] == SYM_FALSE) */ | |
ba2c33c2 | 263 | reject = prevreject; |
f42d2b57 KB |
264 | insym[thissym] = SYM_TRUE; |
265 | } | |
ba2c33c2 KM |
266 | if (!ignore[thissym]) { |
267 | flushline (NO); | |
268 | break; | |
269 | } | |
270 | } | |
271 | flushline (YES); | |
272 | break; | |
273 | ||
f42d2b57 KB |
274 | case LT_ENDIF: |
275 | if (inif == IN_NONE) | |
ba2c33c2 KM |
276 | return error (ENDIF_ERR, linenum, depth); |
277 | if (thissym >= 0) { | |
f42d2b57 | 278 | insym[thissym] = SYM_INACTIVE; |
ba2c33c2 KM |
279 | reject = prevreject; |
280 | if (!ignore[thissym]) { | |
281 | flushline (NO); | |
282 | return NO_ERR; | |
283 | } | |
284 | } | |
285 | flushline (YES); | |
286 | return NO_ERR; | |
287 | ||
f42d2b57 | 288 | case LT_LEOF: { |
ba2c33c2 KM |
289 | int err; |
290 | err = incomment | |
291 | ? CEOF_ERR | |
f42d2b57 | 292 | : inquote == QUOTE_SINGLE |
ba2c33c2 | 293 | ? Q1EOF_ERR |
f42d2b57 | 294 | : inquote == QUOTE_DOUBLE |
ba2c33c2 KM |
295 | ? Q2EOF_ERR |
296 | : NO_ERR; | |
f42d2b57 | 297 | if (inif != IN_NONE) { |
ba2c33c2 | 298 | if (err != NO_ERR) |
f42d2b57 | 299 | (void) error (err, stqcline, depth); |
ba2c33c2 | 300 | return error (IEOF_ERR, stline, depth); |
f42d2b57 | 301 | } else if (err != NO_ERR) |
ba2c33c2 KM |
302 | return error (err, stqcline, depth); |
303 | else | |
304 | return NO_ERR; | |
305 | } | |
306 | } | |
307 | } | |
308 | } | |
309 | ||
310 | #define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_') | |
311 | ||
312 | #define MAXLINE 256 | |
313 | char tline[MAXLINE] BSS; | |
314 | ||
f42d2b57 | 315 | Linetype |
ba2c33c2 | 316 | checkline (cursym) |
f42d2b57 | 317 | int *cursym; /* if LT_TRUE or LT_FALSE returned, set this to sym index */ |
ba2c33c2 KM |
318 | { |
319 | register char *cp; | |
320 | register char *symp; | |
ba2c33c2 | 321 | char *scp; |
f42d2b57 | 322 | Linetype retval; |
ba2c33c2 KM |
323 | # define KWSIZE 8 |
324 | char keyword[KWSIZE]; | |
325 | ||
326 | linenum++; | |
327 | if (getlin (tline, sizeof tline, input, NO) == EOF) | |
f42d2b57 | 328 | return LT_LEOF; |
ba2c33c2 | 329 | |
f42d2b57 | 330 | retval = LT_PLAIN; |
ba2c33c2 KM |
331 | if ( *(cp = tline) != '#' |
332 | || incomment | |
f42d2b57 KB |
333 | || inquote == QUOTE_SINGLE |
334 | || inquote == QUOTE_DOUBLE | |
ba2c33c2 KM |
335 | ) |
336 | goto eol; | |
337 | ||
338 | cp = skipcomment (++cp); | |
339 | symp = keyword; | |
340 | while (!endsym (*cp)) { | |
341 | *symp = *cp++; | |
342 | if (++symp >= &keyword[KWSIZE]) | |
343 | goto eol; | |
344 | } | |
345 | *symp = '\0'; | |
346 | ||
347 | if (strcmp (keyword, "ifdef") == 0) { | |
348 | retval = YES; | |
349 | goto ifdef; | |
f42d2b57 | 350 | } else if (strcmp (keyword, "ifndef") == 0) { |
ba2c33c2 KM |
351 | retval = NO; |
352 | ifdef: | |
353 | scp = cp = skipcomment (++cp); | |
354 | if (incomment) { | |
f42d2b57 | 355 | retval = LT_PLAIN; |
ba2c33c2 KM |
356 | goto eol; |
357 | } | |
f42d2b57 KB |
358 | { |
359 | int symind; | |
360 | ||
361 | if ((symind = findsym (scp)) >= 0) | |
362 | retval = (retval ^ true[*cursym = symind]) | |
363 | ? LT_FALSE : LT_TRUE; | |
364 | else | |
365 | retval = LT_OTHER; | |
ba2c33c2 | 366 | } |
f42d2b57 KB |
367 | } else if (strcmp (keyword, "if") == 0) |
368 | retval = LT_IF; | |
ba2c33c2 | 369 | else if (strcmp (keyword, "else") == 0) |
f42d2b57 | 370 | retval = LT_ELSE; |
ba2c33c2 | 371 | else if (strcmp (keyword, "endif") == 0) |
f42d2b57 | 372 | retval = LT_ENDIF; |
ba2c33c2 KM |
373 | |
374 | eol: | |
f42d2b57 | 375 | if (!text && reject != REJ_IGNORE) |
ba2c33c2 KM |
376 | for (; *cp; ) { |
377 | if (incomment) | |
378 | cp = skipcomment (cp); | |
f42d2b57 KB |
379 | else if (inquote == QUOTE_SINGLE) |
380 | cp = skipquote (cp, QUOTE_SINGLE); | |
381 | else if (inquote == QUOTE_DOUBLE) | |
382 | cp = skipquote (cp, QUOTE_DOUBLE); | |
ba2c33c2 KM |
383 | else if (*cp == '/' && cp[1] == '*') |
384 | cp = skipcomment (cp); | |
385 | else if (*cp == '\'') | |
f42d2b57 | 386 | cp = skipquote (cp, QUOTE_SINGLE); |
ba2c33c2 | 387 | else if (*cp == '"') |
f42d2b57 | 388 | cp = skipquote (cp, QUOTE_DOUBLE); |
ba2c33c2 KM |
389 | else |
390 | cp++; | |
391 | } | |
392 | return retval; | |
393 | } | |
394 | ||
f42d2b57 KB |
395 | /* |
396 | * Skip over comments and stop at the next charaacter | |
397 | * position that is not whitespace. | |
398 | */ | |
ba2c33c2 KM |
399 | char * |
400 | skipcomment (cp) | |
401 | register char *cp; | |
402 | { | |
403 | if (incomment) | |
404 | goto inside; | |
405 | for (;; cp++) { | |
f42d2b57 KB |
406 | while (*cp == ' ' || *cp == '\t') |
407 | cp++; | |
ba2c33c2 | 408 | if (text) |
f42d2b57 | 409 | return cp; |
ba2c33c2 KM |
410 | if ( cp[0] != '/' |
411 | || cp[1] != '*' | |
412 | ) | |
f42d2b57 | 413 | return cp; |
ba2c33c2 KM |
414 | cp += 2; |
415 | if (!incomment) { | |
416 | incomment = YES; | |
417 | stqcline = linenum; | |
418 | } | |
419 | inside: | |
420 | for (;;) { | |
421 | for (; *cp != '*'; cp++) | |
422 | if (*cp == '\0') | |
423 | return cp; | |
f42d2b57 KB |
424 | if (*++cp == '/') { |
425 | incomment = NO; | |
ba2c33c2 | 426 | break; |
f42d2b57 | 427 | } |
ba2c33c2 | 428 | } |
ba2c33c2 KM |
429 | } |
430 | } | |
431 | ||
f42d2b57 KB |
432 | /* |
433 | * Skip over a quoted string or character and stop at the next charaacter | |
434 | * position that is not whitespace. | |
435 | */ | |
ba2c33c2 KM |
436 | char * |
437 | skipquote (cp, type) | |
438 | register char *cp; | |
439 | register int type; | |
440 | { | |
441 | register char qchar; | |
442 | ||
f42d2b57 | 443 | qchar = type == QUOTE_SINGLE ? '\'' : '"'; |
ba2c33c2 | 444 | |
f42d2b57 | 445 | if (inquote == type) |
ba2c33c2 KM |
446 | goto inside; |
447 | for (;; cp++) { | |
448 | if (*cp != qchar) | |
449 | return cp; | |
450 | cp++; | |
f42d2b57 KB |
451 | inquote = type; |
452 | stqcline = linenum; | |
ba2c33c2 KM |
453 | inside: |
454 | for (; ; cp++) { | |
455 | if (*cp == qchar) | |
456 | break; | |
457 | if ( *cp == '\0' | |
f42d2b57 | 458 | || *cp == '\\' && *++cp == '\0' |
ba2c33c2 KM |
459 | ) |
460 | return cp; | |
461 | } | |
f42d2b57 | 462 | inquote = QUOTE_NONE; |
ba2c33c2 KM |
463 | } |
464 | } | |
465 | ||
466 | /* | |
f42d2b57 KB |
467 | * findsym - look for the symbol in the symbol table. |
468 | * if found, return symbol table index, | |
469 | * else return -1. | |
470 | */ | |
471 | int | |
472 | findsym (str) | |
473 | char *str; | |
474 | { | |
475 | register char *cp; | |
476 | register char *symp; | |
477 | register int symind; | |
478 | register char chr; | |
479 | ||
480 | for (symind = 0; symind < nsyms; ++symind) { | |
481 | if (insym[symind] == SYM_INACTIVE) { | |
482 | for ( symp = symname[symind], cp = str | |
483 | ; *symp && *cp == *symp | |
484 | ; cp++, symp++ | |
485 | ) | |
486 | continue; | |
487 | chr = *cp; | |
488 | if (*symp == '\0' && endsym (chr)) | |
489 | return symind; | |
490 | } | |
491 | } | |
492 | return -1; | |
493 | } | |
494 | ||
ba2c33c2 | 495 | /* |
f42d2b57 KB |
496 | * getlin - expands tabs if asked for |
497 | * and (if compiled in) treats form-feed as an end-of-line | |
498 | */ | |
499 | int | |
ba2c33c2 KM |
500 | getlin (line, maxline, inp, expandtabs) |
501 | register char *line; | |
502 | int maxline; | |
503 | FILE *inp; | |
504 | int expandtabs; | |
505 | { | |
506 | int tmp; | |
507 | register int num; | |
508 | register int chr; | |
f42d2b57 | 509 | #ifdef FFSPECIAL |
ba2c33c2 KM |
510 | static char havechar = NO; /* have leftover char from last time */ |
511 | static char svchar BSS; | |
f42d2b57 | 512 | #endif/*FFSPECIAL */ |
ba2c33c2 KM |
513 | |
514 | num = 0; | |
f42d2b57 | 515 | #ifdef FFSPECIAL |
ba2c33c2 KM |
516 | if (havechar) { |
517 | havechar = NO; | |
518 | chr = svchar; | |
519 | goto ent; | |
520 | } | |
f42d2b57 | 521 | #endif/*FFSPECIAL */ |
ba2c33c2 | 522 | while (num + 8 < maxline) { /* leave room for tab */ |
f42d2b57 | 523 | chr = getc (inp); |
ba2c33c2 | 524 | if (isprint (chr)) { |
f42d2b57 | 525 | #ifdef FFSPECIAL |
ba2c33c2 | 526 | ent: |
f42d2b57 | 527 | #endif/*FFSPECIAL */ |
ba2c33c2 KM |
528 | *line++ = chr; |
529 | num++; | |
f42d2b57 | 530 | } else |
ba2c33c2 KM |
531 | switch (chr) { |
532 | case EOF: | |
533 | return EOF; | |
534 | ||
535 | case '\t': | |
536 | if (expandtabs) { | |
537 | num += tmp = 8 - (num & 7); | |
538 | do | |
539 | *line++ = ' '; | |
540 | while (--tmp); | |
541 | break; | |
f42d2b57 KB |
542 | } |
543 | default: | |
544 | *line++ = chr; | |
545 | num++; | |
ba2c33c2 KM |
546 | break; |
547 | ||
548 | case '\n': | |
f42d2b57 KB |
549 | *line = '\n'; |
550 | num++; | |
551 | goto end; | |
552 | ||
553 | #ifdef FFSPECIAL | |
ba2c33c2 KM |
554 | case '\f': |
555 | if (++num == 1) | |
556 | *line = '\f'; | |
557 | else { | |
558 | *line = '\n'; | |
559 | havechar = YES; | |
f42d2b57 KB |
560 | svchar = chr; |
561 | } | |
562 | goto end; | |
563 | #endif/*FFSPECIAL */ | |
ba2c33c2 KM |
564 | } |
565 | } | |
566 | end: | |
567 | *++line = '\0'; | |
568 | return num; | |
569 | } | |
570 | ||
571 | flushline (keep) | |
f42d2b57 | 572 | Bool keep; |
ba2c33c2 | 573 | { |
f42d2b57 KB |
574 | if ((keep && reject != REJ_YES) ^ complement) { |
575 | register char *line = tline; | |
576 | register FILE *out = stdout; | |
577 | register char chr; | |
578 | ||
579 | while (chr = *line++) | |
580 | putc (chr, out); | |
581 | } else if (lnblank) | |
582 | putc ('\n', stdout); | |
ba2c33c2 KM |
583 | return; |
584 | } | |
585 | ||
586 | prname () | |
587 | { | |
588 | fprintf (stderr, "%s: ", progname); | |
589 | return; | |
590 | } | |
591 | ||
f42d2b57 | 592 | int |
ba2c33c2 | 593 | error (err, line, depth) |
f42d2b57 KB |
594 | int err; /* type of error & index into error string array */ |
595 | int line; /* line number */ | |
596 | int depth; /* how many ifdefs we are inside */ | |
ba2c33c2 KM |
597 | { |
598 | if (err == END_ERR) | |
599 | return err; | |
600 | ||
601 | prname (); | |
602 | ||
603 | #ifndef TESTING | |
f42d2b57 KB |
604 | fprintf (stderr, "Error in %s line %d: %s.\n", filename, line, errs[err]); |
605 | #else/* TESTING */ | |
606 | fprintf (stderr, "Error in %s line %d: %s. ", filename, line, errs[err]); | |
ba2c33c2 | 607 | fprintf (stderr, "ifdef depth: %d\n", depth); |
f42d2b57 | 608 | #endif/*TESTING */ |
ba2c33c2 KM |
609 | |
610 | exitstat = 2; | |
611 | return depth > 1 ? IEOF_ERR : END_ERR; | |
612 | } |