~ubuntu-branches/ubuntu/precise/judy/precise

« back to all changes in this revision

Viewing changes to tool/unifdef.c

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Y. Ts'o
  • Date: 2004-01-17 00:04:53 UTC
  • Revision ID: james.westby@ubuntu.com-20040117000453-d5sj6uoon2v1g4gf
Tags: upstream-0.0.4
ImportĀ upstreamĀ versionĀ 0.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Comments by AJS, 020301:
 
3
 *
 
4
 * This code appears to recognize but not handle "#if" directives.
 
5
 *
 
6
 * The LICENSE file is already in the C code below.
 
7
 *
 
8
 * The README file follows:
 
9
 *
 
10
 *      This is the standard "unifdef" from BSD 4.4lite, hacked to allow for
 
11
 *      C++ comments.    -- ajw@cs.cmu.edu
 
12
 *
 
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
 
16
 */
 
17
 
 
18
/*
 
19
 * Copyright (c) 1985, 1993
 
20
 *      The Regents of the University of California.  All rights reserved.
 
21
 *
 
22
 * This code is derived from software contributed to Berkeley by
 
23
 * Dave Yost.
 
24
 *
 
25
 * Redistribution and use in source and binary forms, with or without
 
26
 * modification, are permitted provided that the following conditions
 
27
 * are met:
 
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.
 
40
 *
 
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
 
51
 * SUCH DAMAGE.
 
52
 */
 
53
 
 
54
#ifndef lint
 
55
static char copyright[] =
 
56
"@(#) Copyright (c) 1985, 1993\n\
 
57
        The Regents of the University of California.  All rights reserved.\n";
 
58
#endif /* not lint */
 
59
 
 
60
#ifndef lint
 
61
static char sccsid[] = "@(#)unifdef.c   8.1 (Berkeley) 6/6/93\n@(#) $Revision: 4.2 $ $Source: /judy/tool/unifdef.c $";
 
62
#endif /* not lint */
 
63
 
 
64
/*
 
65
 * unifdef - remove ifdef'ed lines
 
66
 *
 
67
 *  Warning: will not work correctly if input contains null characters.
 
68
 *
 
69
 *  Wishlist:
 
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
 
75
 */
 
76
 
 
77
#include <stdio.h>
 
78
#include <stdlib.h>
 
79
#include <string.h>
 
80
#include <ctype.h>
 
81
 
 
82
#define BSS
 
83
FILE *input;
 
84
#ifndef YES
 
85
#define YES 1
 
86
#define NO  0
 
87
#endif/*YES */
 
88
typedef int Bool;
 
89
 
 
90
char *progname BSS;
 
91
char *filename BSS;
 
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 */
 
95
 
 
96
#define MAXSYMS 100
 
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  */
 
104
 
 
105
char nsyms BSS;
 
106
char incomment BSS;         /* inside C comment */
 
107
char inCPPcomment BSS;      /* inside C++ comment */
 
108
 
 
109
#define QUOTE_NONE   0
 
110
#define QUOTE_SINGLE 1
 
111
#define QUOTE_DOUBLE 2
 
112
char inquote BSS;           /* inside single or double quotes */
 
113
 
 
114
int exitstat BSS;
 
115
 
 
116
typedef int Reject_level;
 
117
typedef int Linetype;
 
118
 
 
119
#define FUNCTION                /* null, to find functions */
 
120
 
 
121
int      main(int argc, char ** argv);
 
122
void     pfile(void);
 
123
int      doif(register int thissym, int inif, Reject_level prevreject,
 
124
              int depth);
 
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);
 
131
void     prname(void);
 
132
int      error(int err, int line, int depth);
 
133
 
 
134
FUNCTION int main(int argc, char ** argv)
 
135
{
 
136
    char **curarg;
 
137
    register char *cp;
 
138
    register char *cp1;
 
139
    char ignorethis;
 
140
 
 
141
/* Make compiler happy: */
 
142
 
 
143
    cp = copyright;
 
144
    cp = sccsid;
 
145
 
 
146
    progname = argv[0][0] ? argv[0] : "unifdef";
 
147
 
 
148
    for (curarg = &argv[1]; --argc > 0; curarg++) {
 
149
        if (*(cp1 = cp = *curarg) != '-')
 
150
            break;
 
151
        if (*++cp1 == 'i') {
 
152
            ignorethis = YES;
 
153
            cp1++;
 
154
        } else
 
155
            ignorethis = NO;
 
156
        if (   (   *cp1 == 'D'
 
157
                || *cp1 == 'U'
 
158
               )
 
159
            && cp1[1] != '\0'
 
160
           ) {
 
161
            register int symind;
 
162
 
 
163
            if ((symind = findsym (&cp1[1])) < 0) {
 
164
                if (nsyms >= MAXSYMS) {
 
165
                    prname ();
 
166
                    fprintf (stderr, "too many symbols.\n");
 
167
                    exit (2);
 
168
                }
 
169
                symind = nsyms++;
 
170
                symname[symind] = &cp1[1];
 
171
                insym[symind] = SYM_INACTIVE;
 
172
            }
 
173
            ignore[symind] = ignorethis;
 
174
            true[symind] = *cp1 == 'D' ? YES : NO;
 
175
        } else if (ignorethis)
 
176
            goto unrec;
 
177
        else if (strcmp (&cp[1], "t") == 0)
 
178
            text = YES;
 
179
        else if (strcmp (&cp[1], "l") == 0)
 
180
            lnblank = YES;
 
181
        else if (strcmp (&cp[1], "c") == 0)
 
182
            complement = YES;
 
183
        else {
 
184
 unrec:
 
185
            prname ();
 
186
            fprintf (stderr, "unrecognized option: %s\n", cp);
 
187
            goto usage;
 
188
        }
 
189
    }
 
190
    if (nsyms == 0) {
 
191
 usage:
 
192
        fprintf (stderr, "\
 
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);
 
195
        exit (2);
 
196
    }
 
197
 
 
198
    if (argc > 1) {
 
199
        prname ();
 
200
        fprintf (stderr, "can only do one file.\n");
 
201
    } else if (argc == 1) {
 
202
        filename = *curarg;
 
203
        if ((input = fopen (filename, "r")) != NULL) {
 
204
            pfile();
 
205
            (void) fclose (input);
 
206
        } else {
 
207
            prname ();
 
208
            fprintf (stderr, "can't open ");
 
209
            perror(*curarg);
 
210
        }
 
211
    } else {
 
212
        filename = "[stdin]";
 
213
        input = stdin;
 
214
        pfile();
 
215
    }
 
216
 
 
217
    (void) fflush (stdout);
 
218
    exit (exitstat);
 
219
}
 
220
 
 
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 */
 
230
 
 
231
Reject_level reject BSS;    /* 0 or 1: pass thru; 1 or 2: ignore comments */
 
232
#define REJ_NO          0
 
233
#define REJ_IGNORE      1
 
234
#define REJ_YES         2
 
235
 
 
236
int linenum BSS;    /* current line number */
 
237
int stqcline BSS;   /* start of current coment or quote */
 
238
char *errs[] = {
 
239
#define NO_ERR      0
 
240
                        "",
 
241
#define END_ERR     1
 
242
                        "",
 
243
#define ELSE_ERR    2
 
244
                        "Inappropriate else",
 
245
#define ENDIF_ERR   3
 
246
                        "Inappropriate endif",
 
247
#define IEOF_ERR    4
 
248
                        "Premature EOF in ifdef",
 
249
#define CEOF_ERR    5
 
250
                        "Premature EOF in comment",
 
251
#define Q1EOF_ERR   6
 
252
                        "Premature EOF in quoted character",
 
253
#define Q2EOF_ERR   7
 
254
                        "Premature EOF in quoted string"
 
255
};
 
256
 
 
257
/* States for inif arg to doif */
 
258
#define IN_NONE 0
 
259
#define IN_IF   1
 
260
#define IN_ELSE 2
 
261
 
 
262
FUNCTION void pfile(void)
 
263
{
 
264
    reject = REJ_NO;
 
265
    (void) doif (-1, IN_NONE, reject, 0);
 
266
    return;
 
267
}
 
268
 
 
269
FUNCTION int doif(
 
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 */
 
274
{
 
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 */
 
280
 
 
281
    stline = linenum;
 
282
    for (;;) {
 
283
        switch (lineval = checkline (&cursym)) {
 
284
        case LT_PLAIN:
 
285
            flushline (YES);
 
286
            break;
 
287
 
 
288
        case LT_TRUE:
 
289
        case LT_FALSE:
 
290
            thisreject = reject;
 
291
            if (lineval == LT_TRUE)
 
292
                insym[cursym] = SYM_TRUE;
 
293
            else {
 
294
                if (reject != REJ_YES)
 
295
                    reject = ignore[cursym] ? REJ_IGNORE : REJ_YES;
 
296
                insym[cursym] = SYM_FALSE;
 
297
            }
 
298
            if (ignore[cursym])
 
299
                flushline (YES);
 
300
            else {
 
301
                exitstat = 0;           /* was 1, but bothers make(1) -- ajs */
 
302
                flushline (NO);
 
303
            }
 
304
            if ((doret = doif (cursym, IN_IF, thisreject, depth + 1)) != NO_ERR)
 
305
                return error (doret, stline, depth);
 
306
            break;
 
307
 
 
308
        case LT_IF:
 
309
        case LT_OTHER:
 
310
            flushline (YES);
 
311
            if ((doret = doif (-1, IN_IF, reject, depth + 1)) != NO_ERR)
 
312
                return error (doret, stline, depth);
 
313
            break;
 
314
 
 
315
        case LT_ELSE:
 
316
            if (inif != IN_IF)
 
317
                return error (ELSE_ERR, linenum, depth);
 
318
            inif = IN_ELSE;
 
319
            if (thissym >= 0) {
 
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) */
 
324
                    reject = prevreject;
 
325
                    insym[thissym] = SYM_TRUE;
 
326
                }
 
327
                if (!ignore[thissym]) {
 
328
                    flushline (NO);
 
329
                    break;
 
330
                }
 
331
            }
 
332
            flushline (YES);
 
333
            break;
 
334
 
 
335
        case LT_ENDIF:
 
336
            if (inif == IN_NONE)
 
337
                return error (ENDIF_ERR, linenum, depth);
 
338
            if (thissym >= 0) {
 
339
                insym[thissym] = SYM_INACTIVE;
 
340
                reject = prevreject;
 
341
                if (!ignore[thissym]) {
 
342
                    flushline (NO);
 
343
                    return NO_ERR;
 
344
                }
 
345
            }
 
346
            flushline (YES);
 
347
            return NO_ERR;
 
348
 
 
349
        case LT_LEOF: {
 
350
            int err;
 
351
            err =   incomment
 
352
                  ? CEOF_ERR
 
353
                  : inquote == QUOTE_SINGLE
 
354
                  ? Q1EOF_ERR
 
355
                  : inquote == QUOTE_DOUBLE
 
356
                  ? Q2EOF_ERR
 
357
                  : NO_ERR;
 
358
            if (inif != IN_NONE) {
 
359
                if (err != NO_ERR)
 
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);
 
364
            else
 
365
                return NO_ERR;
 
366
            }
 
367
        }
 
368
    }
 
369
}
 
370
 
 
371
#define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_')
 
372
 
 
373
#define MAXLINE 256
 
374
char tline[MAXLINE] BSS;
 
375
 
 
376
FUNCTION Linetype checkline(
 
377
    int *cursym)    /* if LT_TRUE or LT_FALSE returned, set this to sym index */
 
378
{
 
379
    register char *cp;
 
380
    register char *symp;
 
381
    char *scp;
 
382
    Linetype retval;
 
383
#   define KWSIZE 8
 
384
    char keyword[KWSIZE];
 
385
 
 
386
    linenum++;
 
387
    if (getlin (tline, sizeof tline, input, NO) == EOF)
 
388
        return LT_LEOF;
 
389
 
 
390
    retval = LT_PLAIN;
 
391
    if (   *(cp = tline) != '#'
 
392
        || incomment
 
393
        || inquote == QUOTE_SINGLE
 
394
        || inquote == QUOTE_DOUBLE
 
395
       )
 
396
        goto eol;
 
397
 
 
398
    cp = skipcomment (++cp);
 
399
    symp = keyword;
 
400
    while (!endsym (*cp)) {
 
401
        *symp = *cp++;
 
402
        if (++symp >= &keyword[KWSIZE])
 
403
            goto eol;
 
404
    }
 
405
    *symp = '\0';
 
406
 
 
407
    if (strcmp (keyword, "ifdef") == 0) {
 
408
        retval = YES;
 
409
        goto ifdef;
 
410
    } else if (strcmp (keyword, "ifndef") == 0) {
 
411
        retval = NO;
 
412
 ifdef:
 
413
        scp = cp = skipcomment (++cp);
 
414
        if (incomment) {
 
415
            retval = LT_PLAIN;
 
416
            goto eol;
 
417
        }
 
418
        {
 
419
            int symind;
 
420
 
 
421
            if ((symind = findsym (scp)) >= 0)
 
422
                retval = (retval ^ true[*cursym = symind])
 
423
                         ? LT_FALSE : LT_TRUE;
 
424
            else
 
425
                retval = LT_OTHER;
 
426
        }
 
427
    } else if (strcmp (keyword, "if") == 0)
 
428
        retval = LT_IF;
 
429
    else if (strcmp (keyword, "else") == 0)
 
430
        retval = LT_ELSE;
 
431
    else if (strcmp (keyword, "endif") == 0)
 
432
        retval = LT_ENDIF;
 
433
 
 
434
 eol:
 
435
    if (!text && reject != REJ_IGNORE)
 
436
        for (; *cp; ) {
 
437
            if (incomment)
 
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);
 
447
            else if (*cp == '"')
 
448
                cp = skipquote (cp, QUOTE_DOUBLE);
 
449
            else
 
450
                cp++;
 
451
        }
 
452
    return retval;
 
453
}
 
454
 
 
455
/*
 
456
 *  Skip over comments and stop at the next charaacter
 
457
 *  position that is not whitespace.
 
458
 */
 
459
FUNCTION char * skipcomment(
 
460
    register char *cp)
 
461
{
 
462
    if (incomment)
 
463
        goto inside;
 
464
    for (;; cp++) {
 
465
        while (*cp == ' ' || *cp == '\t')
 
466
            cp++;
 
467
        if (text)
 
468
            return cp;
 
469
        if (   cp[0] != '/'
 
470
            || (cp[1] != '*' && cp[1] != '/')
 
471
           )
 
472
            return cp;
 
473
        if (!incomment) {
 
474
            incomment = YES;
 
475
            inCPPcomment = (cp[1] == '/');
 
476
            stqcline = linenum;
 
477
        }
 
478
        cp += 2;
 
479
 inside:
 
480
        for (;;) {
 
481
            for (; *cp != '*'; cp++)
 
482
                if (*cp == '\0')
 
483
                {
 
484
                    if (inCPPcomment)
 
485
                        incomment = NO;
 
486
                    return cp;
 
487
                }
 
488
            if (*++cp == '/') {
 
489
                incomment = NO;
 
490
                break;
 
491
            }
 
492
        }
 
493
    }
 
494
}
 
495
 
 
496
/*
 
497
 *  Skip over a quoted string or character and stop at the next charaacter
 
498
 *  position that is not whitespace.
 
499
 */
 
500
FUNCTION char * skipquote(
 
501
    register char *cp,
 
502
    register int type)
 
503
{
 
504
    register char qchar;
 
505
 
 
506
    qchar = ((type == QUOTE_SINGLE) ? '\'' : '"');
 
507
 
 
508
    if (inquote == type)
 
509
        goto inside;
 
510
    for (;; cp++) {
 
511
        if (*cp != qchar)
 
512
            return cp;
 
513
        cp++;
 
514
        inquote = type;
 
515
        stqcline = linenum;
 
516
 inside:
 
517
        for (; ; cp++) {
 
518
            if (*cp == qchar)
 
519
                break;
 
520
            if (   *cp == '\0'
 
521
                || (*cp == '\\' && *++cp == '\0')
 
522
               )
 
523
                return cp;
 
524
        }
 
525
        inquote = QUOTE_NONE;
 
526
    }
 
527
}
 
528
 
 
529
/*
 
530
 *  findsym - look for the symbol in the symbol table.
 
531
 *            if found, return symbol table index,
 
532
 *            else return -1.
 
533
 */
 
534
FUNCTION int findsym(char *str)
 
535
{
 
536
    register char *cp;
 
537
    register char *symp;
 
538
    register int symind;
 
539
    register char chr;
 
540
 
 
541
    for (symind = 0; symind < nsyms; ++symind) {
 
542
        if (insym[symind] == SYM_INACTIVE) {
 
543
            for ( symp = symname[symind], cp = str
 
544
                ; *symp && *cp == *symp
 
545
                ; cp++, symp++
 
546
                )
 
547
                continue;
 
548
            chr = *cp;
 
549
            if (*symp == '\0' && endsym (chr))
 
550
                return symind;
 
551
        }
 
552
    }
 
553
    return -1;
 
554
}
 
555
 
 
556
/*
 
557
 *   getlin - expands tabs if asked for
 
558
 *            and (if compiled in) treats form-feed as an end-of-line
 
559
 */
 
560
FUNCTION int getlin(register char * line, int maxline, FILE * inp, int expandtabs)
 
561
{
 
562
    int tmp;
 
563
    register int num;
 
564
    register int chr;
 
565
#ifdef  FFSPECIAL
 
566
    static char havechar = NO;  /* have leftover char from last time */
 
567
    static char svchar BSS;
 
568
#endif/*FFSPECIAL */
 
569
 
 
570
    num = 0;
 
571
#ifdef  FFSPECIAL
 
572
    if (havechar) {
 
573
        havechar = NO;
 
574
        chr = svchar;
 
575
        goto ent;
 
576
    }
 
577
#endif/*FFSPECIAL */
 
578
    while (num + 8 < maxline) {   /* leave room for tab */
 
579
        chr = getc (inp);
 
580
        switch(chr)
 
581
        {
 
582
        case EOF: 
 
583
            return EOF;
 
584
        case '\t':
 
585
            if (expandtabs) {
 
586
                num += tmp = 8 - (num & 7);
 
587
                do
 
588
                    *line++ = ' ';
 
589
                while (--tmp);
 
590
                break;
 
591
            }
 
592
        default:
 
593
#ifdef  FFSPECIAL
 
594
 ent:
 
595
#endif/*FFSPECIAL */
 
596
            *line++ = chr;
 
597
            num++;
 
598
            break;
 
599
        case '\n':
 
600
            *line = '\n';
 
601
            num++;
 
602
            goto end;
 
603
#ifdef  FFSPECIAL
 
604
            case '\f':
 
605
                if (++num == 1)
 
606
                    *line = '\f';
 
607
                else {
 
608
                    *line = '\n';
 
609
                    havechar = YES;
 
610
                    svchar = chr;
 
611
                }
 
612
                goto end;
 
613
#endif/*FFSPECIAL */
 
614
        }
 
615
    }
 
616
 end:
 
617
    *++line = '\0';
 
618
    return num;
 
619
}
 
620
 
 
621
FUNCTION void flushline(Bool keep)
 
622
{
 
623
    if ((keep && reject != REJ_YES) ^ complement) {
 
624
        register char *line = tline;
 
625
        register FILE *out = stdout;
 
626
        register char chr;
 
627
 
 
628
        while ((chr = *line++))
 
629
            putc (chr, out);
 
630
    } else if (lnblank)
 
631
        putc ('\n', stdout);
 
632
    return;
 
633
}
 
634
 
 
635
FUNCTION void prname(void)
 
636
{
 
637
    fprintf (stderr, "%s: ", progname);
 
638
    return;
 
639
}
 
640
 
 
641
FUNCTION int error(
 
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 */
 
645
{
 
646
    if (err == END_ERR)
 
647
        return err;
 
648
 
 
649
    prname ();
 
650
 
 
651
#ifndef TESTING
 
652
    fprintf (stderr, "Error in %s line %d: %s.\n", filename, line, errs[err]);
 
653
#else/* TESTING */
 
654
    fprintf (stderr, "Error in %s line %d: %s. ", filename, line, errs[err]);
 
655
    fprintf (stderr, "ifdef depth: %d\n", depth);
 
656
#endif/*TESTING */
 
657
 
 
658
    exitstat = 2;
 
659
    return depth > 1 ? IEOF_ERR : END_ERR;
 
660
}