~ubuntu-branches/ubuntu/raring/geany/raring-proposed

« back to all changes in this revision

Viewing changes to tagmanager/get.c

  • Committer: Bazaar Package Importer
  • Author(s): Damián Viano
  • Date: 2008-05-02 11:37:45 UTC
  • mfrom: (1.2.1 upstream) (9 hardy)
  • mto: (3.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20080502113745-xzp4g6dmovrpoj17
Tags: 0.14-1
New upstream release (Closes: #478126)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
 
2
*   $Id: get.c 1810 2007-08-17 14:50:55Z ntrel $
2
3
*
3
 
*   Copyright (c) 1996-2001, Darren Hiebert
 
4
*   Copyright (c) 1996-2002, Darren Hiebert
4
5
*
5
6
*   This source code is released for free distribution under the terms of the
6
7
*   GNU General Public License.
12
13
/*
13
14
*   INCLUDE FILES
14
15
*/
15
 
#include "general.h"    /* must always come first */
 
16
#include "general.h"  /* must always come first */
 
17
 
 
18
#include <string.h>
16
19
#include <glib.h>
17
20
 
18
 
#include <string.h>
19
 
 
20
21
#include "entry.h"
21
22
#include "get.h"
22
 
#include "main.h"
23
23
#include "options.h"
24
24
#include "read.h"
25
25
#include "vstring.h"
27
27
/*
28
28
*   MACROS
29
29
*/
30
 
#define stringMatch(s1,s2)      (strcmp (s1,s2) == 0)
31
 
#define isspacetab(c)           ((c) == ' ' || (c) == '\t')
 
30
#define stringMatch(s1,s2)              (strcmp (s1,s2) == 0)
 
31
#define isspacetab(c)                   ((c) == SPACE || (c) == TAB)
32
32
 
33
33
/*
34
34
*   DATA DECLARATIONS
36
36
typedef enum { COMMENT_NONE, COMMENT_C, COMMENT_CPLUS } Comment;
37
37
 
38
38
enum eCppLimits {
39
 
    MaxCppNestingLevel = 20,
40
 
    MaxDirectiveName = 10
 
39
        MaxCppNestingLevel = 20,
 
40
        MaxDirectiveName = 10
41
41
};
42
42
 
43
43
/*  Defines the one nesting level of a preprocessor conditional.
44
44
 */
45
45
typedef struct sConditionalInfo {
46
 
    boolean ignoreAllBranches;  /* ignoring parent conditional branch */
47
 
    boolean singleBranch;       /* choose only one branch */
48
 
    boolean branchChosen;       /* branch already selected */
49
 
    boolean ignoring;           /* current ignore state */
 
46
        boolean ignoreAllBranches;  /* ignoring parent conditional branch */
 
47
        boolean singleBranch;       /* choose only one branch */
 
48
        boolean branchChosen;       /* branch already selected */
 
49
        boolean ignoring;           /* current ignore state */
50
50
} conditionalInfo;
51
51
 
 
52
enum eState {
 
53
        DRCTV_NONE,    /* no known directive - ignore to end of line */
 
54
        DRCTV_DEFINE,  /* "#define" encountered */
 
55
        DRCTV_HASH,    /* initial '#' read; determine directive */
 
56
        DRCTV_IF,      /* "#if" or "#ifdef" encountered */
 
57
        DRCTV_PRAGMA,  /* #pragma encountered */
 
58
        DRCTV_UNDEF    /* "#undef" encountered */
 
59
};
 
60
 
52
61
/*  Defines the current state of the pre-processor.
53
62
 */
54
63
typedef struct sCppState {
55
 
    int     ungetch, ungetch2;  /* ungotten characters, if any */
56
 
    boolean resolveRequired;    /* must resolve if/else/elif/endif branch */
57
 
    struct sDirective {
58
 
        enum eState {
59
 
            DRCTV_NONE,         /* no known directive - ignore to end of line */
60
 
            DRCTV_DEFINE,       /* "#define" encountered */
61
 
            DRCTV_HASH,         /* initial '#' read; determine directive */
62
 
            DRCTV_IF,           /* "#if" or "#ifdef" encountered */
63
 
            DRCTV_UNDEF         /* "#undef" encountered */
64
 
        } state;
65
 
        boolean accept;         /* is a directive syntatically permitted? */
66
 
        vString * name;         /* macro name */
67
 
        unsigned int nestLevel; /* level 0 is not used */
68
 
        conditionalInfo ifdef [MaxCppNestingLevel];
69
 
    } directive;
 
64
        int             ungetch, ungetch2;   /* ungotten characters, if any */
 
65
        boolean resolveRequired;     /* must resolve if/else/elif/endif branch */
 
66
        boolean hasAtLiteralStrings; /* supports @"c:\" strings */
 
67
        struct sDirective {
 
68
                enum eState state;       /* current directive being processed */
 
69
                boolean accept;          /* is a directive syntactically permitted? */
 
70
                vString * name;          /* macro name */
 
71
                unsigned int nestLevel;  /* level 0 is not used */
 
72
                conditionalInfo ifdef [MaxCppNestingLevel];
 
73
        } directive;
70
74
} cppState;
71
75
 
72
76
/*
78
82
static boolean BraceFormat = FALSE;
79
83
 
80
84
static cppState Cpp = {
81
 
    '\0', '\0',                 /* ungetch characters */
82
 
    FALSE,                      /* resolveRequired */
83
 
    {
84
 
        DRCTV_NONE,             /* state */
85
 
        FALSE,                  /* accept */
86
 
        NULL,                   /* tag name */
87
 
        0,                      /* nestLevel */
88
 
        { {FALSE,FALSE,FALSE,FALSE} }   /* ifdef array */
89
 
    }                           /* directive */
 
85
        '\0', '\0',  /* ungetch characters */
 
86
        FALSE,       /* resolveRequired */
 
87
        FALSE,       /* hasAtLiteralStrings */
 
88
        {
 
89
                DRCTV_NONE,  /* state */
 
90
                FALSE,       /* accept */
 
91
                NULL,        /* tag name */
 
92
                0,           /* nestLevel */
 
93
                { {FALSE,FALSE,FALSE,FALSE} }  /* ifdef array */
 
94
        }  /* directive */
90
95
};
91
96
 
92
97
/*
95
100
 
96
101
extern boolean isBraceFormat (void)
97
102
{
98
 
    return BraceFormat;
 
103
        return BraceFormat;
99
104
}
100
105
 
101
106
extern unsigned int getDirectiveNestLevel (void)
102
107
{
103
 
    return Cpp.directive.nestLevel;
 
108
        return Cpp.directive.nestLevel;
104
109
}
105
110
 
106
 
extern void cppInit (const boolean state)
 
111
extern void cppInit (const boolean state, const boolean hasAtLiteralStrings)
107
112
{
108
 
    BraceFormat = state;
109
 
 
110
 
    Cpp.ungetch         = '\0';
111
 
    Cpp.ungetch2        = '\0';
112
 
    Cpp.resolveRequired = FALSE;
113
 
 
114
 
    Cpp.directive.state     = DRCTV_NONE;
115
 
    Cpp.directive.accept    = TRUE;
116
 
    Cpp.directive.nestLevel = 0;
117
 
 
118
 
    if (Cpp.directive.name == NULL)
119
 
        Cpp.directive.name = vStringNew ();
120
 
    else
121
 
        vStringClear (Cpp.directive.name);
 
113
        BraceFormat = state;
 
114
 
 
115
        Cpp.ungetch         = '\0';
 
116
        Cpp.ungetch2        = '\0';
 
117
        Cpp.resolveRequired = FALSE;
 
118
        Cpp.hasAtLiteralStrings = hasAtLiteralStrings;
 
119
 
 
120
        Cpp.directive.state     = DRCTV_NONE;
 
121
        Cpp.directive.accept    = TRUE;
 
122
        Cpp.directive.nestLevel = 0;
 
123
 
 
124
        Cpp.directive.ifdef [0].ignoreAllBranches = FALSE;
 
125
        Cpp.directive.ifdef [0].singleBranch = FALSE;
 
126
        Cpp.directive.ifdef [0].branchChosen = FALSE;
 
127
        Cpp.directive.ifdef [0].ignoring     = FALSE;
 
128
 
 
129
        if (Cpp.directive.name == NULL)
 
130
                Cpp.directive.name = vStringNew ();
 
131
        else
 
132
                vStringClear (Cpp.directive.name);
122
133
}
123
134
 
124
135
extern void cppTerminate (void)
125
136
{
126
 
    if (Cpp.directive.name != NULL)
127
 
    {
128
 
        vStringDelete (Cpp.directive.name);
129
 
        Cpp.directive.name = NULL;
130
 
    }
 
137
        if (Cpp.directive.name != NULL)
 
138
        {
 
139
                vStringDelete (Cpp.directive.name);
 
140
                Cpp.directive.name = NULL;
 
141
        }
131
142
}
132
143
 
133
144
extern void cppBeginStatement (void)
134
145
{
135
 
    Cpp.resolveRequired = TRUE;
 
146
        Cpp.resolveRequired = TRUE;
136
147
}
137
148
 
138
149
extern void cppEndStatement (void)
139
150
{
140
 
    Cpp.resolveRequired = FALSE;
 
151
        Cpp.resolveRequired = FALSE;
141
152
}
142
153
 
143
154
/*
152
163
 */
153
164
extern void cppUngetc (const int c)
154
165
{
155
 
    Assert (Cpp.ungetch2 == '\0');
156
 
    Cpp.ungetch2 = Cpp.ungetch;
157
 
    Cpp.ungetch = c;
 
166
        Assert (Cpp.ungetch2 == '\0');
 
167
        Cpp.ungetch2 = Cpp.ungetch;
 
168
        Cpp.ungetch = c;
158
169
}
159
170
 
160
171
/*  Reads a directive, whose first character is given by "c", into "name".
161
172
 */
162
173
static boolean readDirective (int c, char *const name, unsigned int maxLength)
163
174
{
164
 
    unsigned int i;
 
175
        unsigned int i;
165
176
 
166
 
    for (i = 0  ;  i < maxLength - 1  ;  ++i)
167
 
    {
168
 
        if (i > 0)
 
177
        for (i = 0  ;  i < maxLength - 1  ;  ++i)
169
178
        {
170
 
            c = fileGetc ();
171
 
            if (c == EOF  ||  ! isalpha (c))
172
 
            {
173
 
                fileUngetc (c);
174
 
                break;
175
 
            }
 
179
                if (i > 0)
 
180
                {
 
181
                        c = fileGetc ();
 
182
                        if (c == EOF  ||  ! isalpha (c))
 
183
                        {
 
184
                                fileUngetc (c);
 
185
                                break;
 
186
                        }
 
187
                }
 
188
                name [i] = c;
176
189
        }
177
 
        name [i] = c;
178
 
    }
179
 
    name [i] = '\0';                                    /* null terminate */
 
190
        name [i] = '\0';  /* null terminate */
180
191
 
181
 
    return (boolean) isspacetab (c);
 
192
        return (boolean) isspacetab (c);
182
193
}
183
194
 
184
195
/*  Reads an identifier, whose first character is given by "c", into "tag",
185
196
 *  together with the file location and corresponding line number.
186
197
 */
187
 
static boolean readDefineTag (int c, vString *const name,
188
 
                              boolean *const parameterized)
 
198
static void readIdentifier (int c, vString *const name)
189
199
{
190
 
    vStringClear (name);
191
 
    do
192
 
    {
193
 
        vStringPut (name, c);
194
 
    } while (c = fileGetc (), (c != EOF  &&  isident (c)));
195
 
    fileUngetc (c);
196
 
    vStringPut (name, '\0');
197
 
 
198
 
    *parameterized = (boolean) (c == '(');
199
 
    return (boolean) (isspace (c)  ||  c == '(');
 
200
        vStringClear (name);
 
201
        do
 
202
        {
 
203
                vStringPut (name, c);
 
204
        } while (c = fileGetc (), (c != EOF  &&  isident (c)));
 
205
        fileUngetc (c);
 
206
        vStringTerminate (name);
200
207
}
201
208
 
202
209
static conditionalInfo *currentConditional (void)
203
210
{
204
 
    return &Cpp.directive.ifdef [Cpp.directive.nestLevel];
 
211
        return &Cpp.directive.ifdef [Cpp.directive.nestLevel];
205
212
}
206
213
 
207
214
static boolean isIgnore (void)
208
215
{
209
 
    return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring;
 
216
        return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring;
210
217
}
211
218
 
212
219
static boolean setIgnore (const boolean ignore)
213
220
{
214
 
    return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring = ignore;
 
221
        return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring = ignore;
215
222
}
216
223
 
217
224
static boolean isIgnoreBranch (void)
218
225
{
219
 
    conditionalInfo *const ifdef = currentConditional ();
220
 
 
221
 
    /*  Force a single branch if an incomplete statement is discovered
222
 
     *  en route. This may have allowed earlier branches containing complete
223
 
     *  statements to be followed, but we must follow no further branches.
224
 
     */
225
 
    if (Cpp.resolveRequired  &&  ! BraceFormat)
226
 
        ifdef->singleBranch = TRUE;
227
 
 
228
 
    /*  We will ignore this branch in the following cases:
229
 
     *
230
 
     *  1.  We are ignoring all branches (conditional was within an ignored
231
 
     *        branch of the parent conditional)
232
 
     *  2.  A branch has already been chosen and either of:
233
 
     *      a.  A statement was incomplete upon entering the conditional
234
 
     *      b.  A statement is incomplete upon encountering a branch
235
 
     */
236
 
    return (boolean) (ifdef->ignoreAllBranches ||
237
 
                     (ifdef->branchChosen  &&  ifdef->singleBranch));
 
226
        conditionalInfo *const ifdef = currentConditional ();
 
227
 
 
228
        /*  Force a single branch if an incomplete statement is discovered
 
229
         *  en route. This may have allowed earlier branches containing complete
 
230
         *  statements to be followed, but we must follow no further branches.
 
231
         */
 
232
        if (Cpp.resolveRequired  &&  ! BraceFormat)
 
233
                ifdef->singleBranch = TRUE;
 
234
 
 
235
        /*  We will ignore this branch in the following cases:
 
236
         *
 
237
         *  1.  We are ignoring all branches (conditional was within an ignored
 
238
         *        branch of the parent conditional)
 
239
         *  2.  A branch has already been chosen and either of:
 
240
         *      a.  A statement was incomplete upon entering the conditional
 
241
         *      b.  A statement is incomplete upon encountering a branch
 
242
         */
 
243
        return (boolean) (ifdef->ignoreAllBranches ||
 
244
                                         (ifdef->branchChosen  &&  ifdef->singleBranch));
238
245
}
239
246
 
240
247
static void chooseBranch (void)
241
248
{
242
 
    if (! BraceFormat)
243
 
    {
244
 
        conditionalInfo *const ifdef = currentConditional ();
 
249
        if (! BraceFormat)
 
250
        {
 
251
                conditionalInfo *const ifdef = currentConditional ();
245
252
 
246
 
        ifdef->branchChosen = (boolean) (ifdef->singleBranch ||
247
 
                                        Cpp.resolveRequired);
248
 
    }
 
253
                ifdef->branchChosen = (boolean) (ifdef->singleBranch ||
 
254
                                                                                Cpp.resolveRequired);
 
255
        }
249
256
}
250
257
 
251
258
/*  Pushes one nesting level for an #if directive, indicating whether or not
253
260
 */
254
261
static boolean pushConditional (const boolean firstBranchChosen)
255
262
{
256
 
    const boolean ignoreAllBranches = isIgnore ();      /* current ignore */
257
 
    boolean ignoreBranch = FALSE;
258
 
 
259
 
    if (Cpp.directive.nestLevel < (unsigned int) MaxCppNestingLevel - 1)
260
 
    {
261
 
        conditionalInfo *ifdef;
262
 
 
263
 
        ++Cpp.directive.nestLevel;
264
 
        ifdef = currentConditional ();
265
 
 
266
 
        /*  We take a snapshot of whether there is an incomplete statement in
267
 
         *  progress upon encountering the preprocessor conditional. If so,
268
 
         *  then we will flag that only a single branch of the conditional
269
 
         *  should be followed.
270
 
         */
271
 
        ifdef->ignoreAllBranches= ignoreAllBranches;
272
 
        ifdef->singleBranch     = Cpp.resolveRequired;
273
 
        ifdef->branchChosen     = firstBranchChosen;
274
 
        ifdef->ignoring         = (boolean) (ignoreAllBranches || (
275
 
                                    ! firstBranchChosen  &&  ! BraceFormat  &&
276
 
                                    (ifdef->singleBranch || !Option.if0)));
277
 
        ignoreBranch = ifdef->ignoring;
278
 
    }
279
 
    return ignoreBranch;
 
263
        const boolean ignoreAllBranches = isIgnore ();  /* current ignore */
 
264
        boolean ignoreBranch = FALSE;
 
265
 
 
266
        if (Cpp.directive.nestLevel < (unsigned int) MaxCppNestingLevel - 1)
 
267
        {
 
268
                conditionalInfo *ifdef;
 
269
 
 
270
                ++Cpp.directive.nestLevel;
 
271
                ifdef = currentConditional ();
 
272
 
 
273
                /*  We take a snapshot of whether there is an incomplete statement in
 
274
                 *  progress upon encountering the preprocessor conditional. If so,
 
275
                 *  then we will flag that only a single branch of the conditional
 
276
                 *  should be followed.
 
277
                 */
 
278
                ifdef->ignoreAllBranches = ignoreAllBranches;
 
279
                ifdef->singleBranch      = Cpp.resolveRequired;
 
280
                ifdef->branchChosen      = firstBranchChosen;
 
281
                ifdef->ignoring = (boolean) (ignoreAllBranches || (
 
282
                                ! firstBranchChosen  &&  ! BraceFormat  &&
 
283
                                (ifdef->singleBranch || !Option.if0)));
 
284
                ignoreBranch = ifdef->ignoring;
 
285
        }
 
286
        return ignoreBranch;
280
287
}
281
288
 
282
289
/*  Pops one nesting level for an #endif directive.
283
290
 */
284
291
static boolean popConditional (void)
285
292
{
286
 
    if (Cpp.directive.nestLevel > 0)
287
 
        --Cpp.directive.nestLevel;
 
293
        if (Cpp.directive.nestLevel > 0)
 
294
                --Cpp.directive.nestLevel;
288
295
 
289
 
    return isIgnore ();
 
296
        return isIgnore ();
290
297
}
291
298
 
292
299
static void makeDefineTag (const char *const name, boolean parameterized)
293
300
{
294
 
    const boolean isFileScope = (boolean) (! isHeaderFile ());
295
 
 
296
 
    if (includingDefineTags () &&
297
 
        (! isFileScope  ||  Option.include.fileScope))
298
 
    {
299
 
        tagEntryInfo e;
300
 
 
301
 
        initTagEntry (&e, name);
302
 
 
303
 
        e.lineNumberEntry = (boolean) (Option.locate != EX_PATTERN);
304
 
        e.isFileScope   = isFileScope;
305
 
        e.truncateLine  = TRUE;
306
 
        e.kindName      = "macro";
307
 
        e.kind          = 'd';
308
 
        if (parameterized)
309
 
                e.extensionFields.arglist = getArglistFromPos(getInputFilePosition()
310
 
                  , e.name);
311
 
        makeTagEntry (&e);
312
 
        if (parameterized)
313
 
                free((char *) e.extensionFields.arglist);
314
 
    }
 
301
        const boolean isFileScope = (boolean) (! isHeaderFile ());
 
302
 
 
303
        if (includingDefineTags () &&
 
304
                (! isFileScope  ||  Option.include.fileScope))
 
305
        {
 
306
                tagEntryInfo e;
 
307
 
 
308
                initTagEntry (&e, name);
 
309
 
 
310
                e.lineNumberEntry = (boolean) (Option.locate != EX_PATTERN);
 
311
                e.isFileScope  = isFileScope;
 
312
                e.truncateLine = TRUE;
 
313
                e.kindName     = "macro";
 
314
                e.kind         = 'd';
 
315
                if (parameterized)
 
316
                        e.extensionFields.arglist = getArglistFromPos(getInputFilePosition()
 
317
                                , e.name);
 
318
                makeTagEntry (&e);
 
319
                if (parameterized)
 
320
                        free((char *) e.extensionFields.arglist);
 
321
        }
315
322
}
316
323
 
317
324
static void directiveDefine (const int c)
318
325
{
319
 
    boolean parameterized;
320
 
 
321
 
    if (isident1 (c))
322
 
    {
323
 
        readDefineTag (c, Cpp.directive.name, &parameterized);
324
 
        if (! isIgnore ())
325
 
            /// TODO
326
 
            // the second argument need to be tested, not sure if TRUE is correct
327
 
            makeDefineTag (vStringValue (Cpp.directive.name), TRUE);
328
 
    }
329
 
    Cpp.directive.state = DRCTV_NONE;
 
326
        boolean parameterized;
 
327
        int nc;
 
328
 
 
329
        if (isident1 (c))
 
330
        {
 
331
                readIdentifier (c, Cpp.directive.name);
 
332
                nc = fileGetc ();
 
333
                fileUngetc (nc);
 
334
                parameterized = (boolean) (nc == '(');
 
335
                if (! isIgnore ())
 
336
                        makeDefineTag (vStringValue (Cpp.directive.name), parameterized);
 
337
        }
 
338
        Cpp.directive.state = DRCTV_NONE;
 
339
}
 
340
 
 
341
static void directivePragma (int c)
 
342
{
 
343
        if (isident1 (c))
 
344
        {
 
345
                readIdentifier (c, Cpp.directive.name);
 
346
                if (stringMatch (vStringValue (Cpp.directive.name), "weak"))
 
347
                {
 
348
                        /* generate macro tag for weak name */
 
349
                        do
 
350
                        {
 
351
                                c = fileGetc ();
 
352
                        } while (c == SPACE);
 
353
                        if (isident1 (c))
 
354
                        {
 
355
                                readIdentifier (c, Cpp.directive.name);
 
356
                                makeDefineTag (vStringValue (Cpp.directive.name), FALSE);
 
357
                        }
 
358
                }
 
359
        }
 
360
        Cpp.directive.state = DRCTV_NONE;
330
361
}
331
362
 
332
363
static boolean directiveIf (const int c)
333
364
{
334
 
    const boolean ignore = pushConditional ((boolean) (c != '0'));
335
 
 
336
 
    Cpp.directive.state = DRCTV_NONE;
337
 
 
338
 
    return ignore;
 
365
        const boolean ignore = pushConditional ((boolean) (c != '0'));
 
366
 
 
367
        Cpp.directive.state = DRCTV_NONE;
 
368
 
 
369
        return ignore;
339
370
}
340
371
 
341
372
static boolean directiveHash (const int c)
342
373
{
343
 
    boolean ignore = FALSE;
344
 
    char directive [MaxDirectiveName];
345
 
    DebugStatement ( const boolean ignore0 = isIgnore (); )
346
 
 
347
 
    readDirective (c, directive, MaxDirectiveName);
348
 
    if (stringMatch (directive, "define"))
349
 
        Cpp.directive.state = DRCTV_DEFINE;
350
 
    else if (stringMatch (directive, "undef"))
351
 
        Cpp.directive.state = DRCTV_UNDEF;
352
 
    else if (strncmp (directive, "if", (size_t) 2) == 0)
353
 
        Cpp.directive.state = DRCTV_IF;
354
 
    else if (stringMatch (directive, "elif")  ||
355
 
            stringMatch (directive, "else"))
356
 
    {
357
 
        ignore = setIgnore (isIgnoreBranch ());
358
 
        if (! ignore  &&  stringMatch (directive, "else"))
359
 
            chooseBranch ();
360
 
        Cpp.directive.state = DRCTV_NONE;
361
 
        DebugStatement ( if (ignore != ignore0) debugCppIgnore (ignore); )
362
 
    }
363
 
    else if (stringMatch (directive, "endif"))
364
 
    {
365
 
        DebugStatement ( debugCppNest (FALSE, Cpp.directive.nestLevel); )
366
 
        ignore = popConditional ();
367
 
        Cpp.directive.state = DRCTV_NONE;
368
 
        DebugStatement ( if (ignore != ignore0) debugCppIgnore (ignore); )
369
 
    }
370
 
    else        /* "pragma", etc. */
371
 
        Cpp.directive.state = DRCTV_NONE;
372
 
 
373
 
    return ignore;
 
374
        boolean ignore = FALSE;
 
375
        char directive [MaxDirectiveName];
 
376
        DebugStatement ( const boolean ignore0 = isIgnore (); )
 
377
 
 
378
        readDirective (c, directive, MaxDirectiveName);
 
379
        if (stringMatch (directive, "define"))
 
380
                Cpp.directive.state = DRCTV_DEFINE;
 
381
        else if (stringMatch (directive, "undef"))
 
382
                Cpp.directive.state = DRCTV_UNDEF;
 
383
        else if (strncmp (directive, "if", (size_t) 2) == 0)
 
384
                Cpp.directive.state = DRCTV_IF;
 
385
        else if (stringMatch (directive, "elif")  ||
 
386
                        stringMatch (directive, "else"))
 
387
        {
 
388
                ignore = setIgnore (isIgnoreBranch ());
 
389
                if (! ignore  &&  stringMatch (directive, "else"))
 
390
                        chooseBranch ();
 
391
                Cpp.directive.state = DRCTV_NONE;
 
392
                DebugStatement ( if (ignore != ignore0) debugCppIgnore (ignore); )
 
393
        }
 
394
        else if (stringMatch (directive, "endif"))
 
395
        {
 
396
                DebugStatement ( debugCppNest (FALSE, Cpp.directive.nestLevel); )
 
397
                ignore = popConditional ();
 
398
                Cpp.directive.state = DRCTV_NONE;
 
399
                DebugStatement ( if (ignore != ignore0) debugCppIgnore (ignore); )
 
400
        }
 
401
        else if (stringMatch (directive, "pragma"))
 
402
                Cpp.directive.state = DRCTV_PRAGMA;
 
403
        else
 
404
                Cpp.directive.state = DRCTV_NONE;
 
405
 
 
406
        return ignore;
374
407
}
375
408
 
376
409
/*  Handles a pre-processor directive whose first character is given by "c".
377
410
 */
378
411
static boolean handleDirective (const int c)
379
412
{
380
 
    boolean ignore = isIgnore ();
 
413
        boolean ignore = isIgnore ();
381
414
 
382
 
    switch (Cpp.directive.state)
383
 
    {
384
 
        case DRCTV_NONE:        ignore = isIgnore ();           break;
385
 
        case DRCTV_DEFINE:      directiveDefine (c);            break;
386
 
        case DRCTV_HASH:        ignore = directiveHash (c);     break;
387
 
        case DRCTV_IF:          ignore = directiveIf (c);       break;
388
 
        case DRCTV_UNDEF:       directiveDefine (c);            break;
389
 
    }
390
 
    return ignore;
 
415
        switch (Cpp.directive.state)
 
416
        {
 
417
                case DRCTV_NONE:    ignore = isIgnore ();        break;
 
418
                case DRCTV_DEFINE:  directiveDefine (c);         break;
 
419
                case DRCTV_HASH:    ignore = directiveHash (c);  break;
 
420
                case DRCTV_IF:      ignore = directiveIf (c);    break;
 
421
                case DRCTV_PRAGMA:  directivePragma (c);         break;
 
422
                case DRCTV_UNDEF:   directiveDefine (c);         break;
 
423
        }
 
424
        return ignore;
391
425
}
392
426
 
393
427
/*  Called upon reading of a slash ('/') characters, determines whether a
395
429
 */
396
430
static Comment isComment (void)
397
431
{
398
 
    Comment comment;
399
 
    const int next = fileGetc ();
 
432
        Comment comment;
 
433
        const int next = fileGetc ();
400
434
 
401
 
    if (next == '*')
402
 
        comment = COMMENT_C;
403
 
    else if (next == '/')
404
 
        comment = COMMENT_CPLUS;
405
 
    else
406
 
    {
407
 
        fileUngetc (next);
408
 
        comment = COMMENT_NONE;
409
 
    }
410
 
    return comment;
 
435
        if (next == '*')
 
436
                comment = COMMENT_C;
 
437
        else if (next == '/')
 
438
                comment = COMMENT_CPLUS;
 
439
        else
 
440
        {
 
441
                fileUngetc (next);
 
442
                comment = COMMENT_NONE;
 
443
        }
 
444
        return comment;
411
445
}
412
446
 
413
447
/*  Skips over a C style comment. According to ANSI specification a comment
414
 
 *  is treated as white space, so we perform this subsitution.
 
448
 *  is treated as white space, so we perform this substitution.
415
449
 */
416
 
static int skipOverCComment (void)
 
450
int skipOverCComment (void)
417
451
{
418
 
    int c = fileGetc ();
 
452
        int c = fileGetc ();
419
453
 
420
 
    while (c != EOF)
421
 
    {
422
 
        if (c != '*')
423
 
            c = fileGetc ();
424
 
        else
 
454
        while (c != EOF)
425
455
        {
426
 
            const int next = fileGetc ();
 
456
                if (c != '*')
 
457
                        c = fileGetc ();
 
458
                else
 
459
                {
 
460
                        const int next = fileGetc ();
427
461
 
428
 
            if (next != '/')
429
 
                c = next;
430
 
            else
431
 
            {
432
 
                c = ' ';                        /* replace comment with space */
433
 
                break;
434
 
            }
 
462
                        if (next != '/')
 
463
                                c = next;
 
464
                        else
 
465
                        {
 
466
                                c = SPACE;  /* replace comment with space */
 
467
                                break;
 
468
                        }
 
469
                }
435
470
        }
436
 
    }
437
 
    return c;
 
471
        return c;
438
472
}
439
473
 
440
474
/*  Skips over a C++ style comment.
441
475
 */
442
476
static int skipOverCplusComment (void)
443
477
{
444
 
    int c;
 
478
        int c;
445
479
 
446
 
    while ((c = fileGetc ()) != EOF)
447
 
    {
448
 
        if (c == BACKSLASH)
449
 
            fileGetc ();                        /* throw away next character, too */
450
 
        else if (c == NEWLINE)
451
 
            break;
452
 
    }
453
 
    return c;
 
480
        while ((c = fileGetc ()) != EOF)
 
481
        {
 
482
                if (c == BACKSLASH)
 
483
                        fileGetc ();  /* throw away next character, too */
 
484
                else if (c == NEWLINE)
 
485
                        break;
 
486
        }
 
487
        return c;
454
488
}
455
489
 
456
490
/*  Skips to the end of a string, returning a special character to
457
491
 *  symbolically represent a generic string.
458
492
 */
459
 
static int skipToEndOfString (void)
 
493
static int skipToEndOfString (boolean ignoreBackslash)
460
494
{
461
 
    int c;
 
495
        int c;
462
496
 
463
 
    while ((c = fileGetc ()) != EOF)
464
 
    {
465
 
        if (c == BACKSLASH)
466
 
            fileGetc ();                        /* throw away next character, too */
467
 
        else if (c == DOUBLE_QUOTE)
468
 
            break;
469
 
    }
470
 
    return STRING_SYMBOL;               /* symbolic representation of string */
 
497
        while ((c = fileGetc ()) != EOF)
 
498
        {
 
499
                if (c == BACKSLASH && ! ignoreBackslash)
 
500
                        fileGetc ();  /* throw away next character, too */
 
501
                else if (c == DOUBLE_QUOTE)
 
502
                        break;
 
503
        }
 
504
        return STRING_SYMBOL;  /* symbolic representation of string */
471
505
}
472
506
 
473
507
/*  Skips to the end of the three (possibly four) 'c' sequence, returning a
474
508
 *  special character to symbolically represent a generic character.
 
509
 *  Also detects Vera numbers that include a base specifier (ie. 'b1010).
475
510
 */
476
511
static int skipToEndOfChar (void)
477
512
{
478
 
    int c;
 
513
        int c;
 
514
        int count = 0, veraBase = '\0';
479
515
 
480
 
    while ((c = fileGetc ()) != EOF)
481
 
    {
482
 
        if (c == BACKSLASH)
483
 
            fileGetc ();                        /* throw away next character, too */
484
 
        else if (c == SINGLE_QUOTE)
485
 
            break;
486
 
        else if (c == NEWLINE)
 
516
        while ((c = fileGetc ()) != EOF)
487
517
        {
488
 
            fileUngetc (c);
489
 
            break;
 
518
            ++count;
 
519
                if (c == BACKSLASH)
 
520
                        fileGetc ();  /* throw away next character, too */
 
521
                else if (c == SINGLE_QUOTE)
 
522
                        break;
 
523
                else if (c == NEWLINE)
 
524
                {
 
525
                        fileUngetc (c);
 
526
                        break;
 
527
                }
 
528
                else if (count == 1  &&  strchr ("DHOB", toupper (c)) != NULL)
 
529
                        veraBase = c;
 
530
                else if (veraBase != '\0'  &&  ! isalnum (c))
 
531
                {
 
532
                        fileUngetc (c);
 
533
                        break;
 
534
                }
490
535
        }
491
 
    }
492
 
    return CHAR_SYMBOL;             /* symbolic representation of character */
 
536
        return CHAR_SYMBOL;  /* symbolic representation of character */
493
537
}
494
538
 
495
539
/*  This function returns the next character, stripping out comments,
499
543
 */
500
544
extern int cppGetc (void)
501
545
{
502
 
    boolean directive = FALSE;
503
 
    boolean ignore = FALSE;
504
 
    int c;
 
546
        boolean directive = FALSE;
 
547
        boolean ignore = FALSE;
 
548
        int c;
505
549
 
506
 
    if (Cpp.ungetch != '\0')
507
 
    {
508
 
        c = Cpp.ungetch;
509
 
        Cpp.ungetch = Cpp.ungetch2;
510
 
        Cpp.ungetch2 = '\0';
511
 
        return c;           /* return here to avoid re-calling debugPutc () */
512
 
    }
513
 
    else do
514
 
    {
515
 
        c = fileGetc ();
 
550
        if (Cpp.ungetch != '\0')
 
551
        {
 
552
                c = Cpp.ungetch;
 
553
                Cpp.ungetch = Cpp.ungetch2;
 
554
                Cpp.ungetch2 = '\0';
 
555
                return c;  /* return here to avoid re-calling debugPutc () */
 
556
        }
 
557
        else do
 
558
        {
 
559
                c = fileGetc ();
516
560
process:
517
 
        switch (c)
518
 
        {
519
 
            case EOF:
520
 
                ignore    = FALSE;
521
 
                directive = FALSE;
522
 
                break;
523
 
 
524
 
            case TAB:
525
 
            case SPACE:
526
 
                break;                          /* ignore most white space */
527
 
 
528
 
            case NEWLINE:
529
 
                if (directive  &&  ! ignore)
530
 
                    directive = FALSE;
531
 
                Cpp.directive.accept = TRUE;
532
 
                break;
533
 
 
534
 
            case DOUBLE_QUOTE:
535
 
                Cpp.directive.accept = FALSE;
536
 
                c = skipToEndOfString ();
537
 
                break;
538
 
 
539
 
            case '#':
540
 
                if (Cpp.directive.accept)
541
 
                {
542
 
                    directive = TRUE;
543
 
                    Cpp.directive.state  = DRCTV_HASH;
544
 
                    Cpp.directive.accept = FALSE;
545
 
                }
546
 
                break;
547
 
 
548
 
            case SINGLE_QUOTE:
549
 
                Cpp.directive.accept = FALSE;
550
 
                c = skipToEndOfChar ();
551
 
                break;
552
 
 
553
 
            case '/':
554
 
            {
555
 
                const Comment comment = isComment ();
556
 
 
557
 
                if (comment == COMMENT_C)
558
 
                    c = skipOverCComment ();
559
 
                else if (comment == COMMENT_CPLUS)
560
 
                {
561
 
                    c = skipOverCplusComment ();
562
 
                    if (c == NEWLINE)
563
 
                        fileUngetc (c);
564
 
                }
565
 
                else
566
 
                    Cpp.directive.accept = FALSE;
567
 
                break;
568
 
            }
569
 
 
570
 
            case BACKSLASH:
571
 
            {
572
 
                int next = fileGetc ();
573
 
 
574
 
                if (next == NEWLINE)
575
 
                    continue;
576
 
                else if (next == '?')
577
 
                    cppUngetc (next);
578
 
                else
579
 
                    fileUngetc (next);
580
 
                break;
581
 
            }
582
 
 
583
 
            case '?':
584
 
            {
585
 
                int next = fileGetc ();
586
 
                if (next != '?')
587
 
                    fileUngetc (next);
588
 
                else
589
 
                {
590
 
                    next = fileGetc ();
591
 
                    switch (next)
592
 
                    {
593
 
                        case '(':          c = '[';       break;
594
 
                        case ')':          c = ']';       break;
595
 
                        case '<':          c = '{';       break;
596
 
                        case '>':          c = '}';       break;
597
 
                        case '/':          c = BACKSLASH; goto process;
598
 
                        case '!':          c = '|';       break;
599
 
                        case SINGLE_QUOTE: c = '^';       break;
600
 
                        case '-':          c = '~';       break;
601
 
                        case '=':          c = '#';       goto process;
 
561
                switch (c)
 
562
                {
 
563
                        case EOF:
 
564
                                ignore    = FALSE;
 
565
                                directive = FALSE;
 
566
                                break;
 
567
 
 
568
                        case TAB:
 
569
                        case SPACE:
 
570
                                break;  /* ignore most white space */
 
571
 
 
572
                        case NEWLINE:
 
573
                                if (directive  &&  ! ignore)
 
574
                                        directive = FALSE;
 
575
                                Cpp.directive.accept = TRUE;
 
576
                                break;
 
577
 
 
578
                        case DOUBLE_QUOTE:
 
579
                                Cpp.directive.accept = FALSE;
 
580
                                c = skipToEndOfString (FALSE);
 
581
                                break;
 
582
 
 
583
                        case '#':
 
584
                                if (Cpp.directive.accept)
 
585
                                {
 
586
                                        directive = TRUE;
 
587
                                        Cpp.directive.state  = DRCTV_HASH;
 
588
                                        Cpp.directive.accept = FALSE;
 
589
                                }
 
590
                                break;
 
591
 
 
592
                        case SINGLE_QUOTE:
 
593
                                Cpp.directive.accept = FALSE;
 
594
                                c = skipToEndOfChar ();
 
595
                                break;
 
596
 
 
597
                        case '/':
 
598
                        {
 
599
                                const Comment comment = isComment ();
 
600
 
 
601
                                if (comment == COMMENT_C)
 
602
                                        c = skipOverCComment ();
 
603
                                else if (comment == COMMENT_CPLUS)
 
604
                                {
 
605
                                        c = skipOverCplusComment ();
 
606
                                        if (c == NEWLINE)
 
607
                                                fileUngetc (c);
 
608
                                }
 
609
                                else
 
610
                                        Cpp.directive.accept = FALSE;
 
611
                                break;
 
612
                        }
 
613
 
 
614
                        case BACKSLASH:
 
615
                        {
 
616
                                int next = fileGetc ();
 
617
 
 
618
                                if (next == NEWLINE)
 
619
                                        continue;
 
620
                                else if (next == '?')
 
621
                                        cppUngetc (next);
 
622
                                else
 
623
                                        fileUngetc (next);
 
624
                                break;
 
625
                        }
 
626
 
 
627
                        case '?':
 
628
                        {
 
629
                                int next = fileGetc ();
 
630
                                if (next != '?')
 
631
                                        fileUngetc (next);
 
632
                                else
 
633
                                {
 
634
                                        next = fileGetc ();
 
635
                                        switch (next)
 
636
                                        {
 
637
                                                case '(':          c = '[';       break;
 
638
                                                case ')':          c = ']';       break;
 
639
                                                case '<':          c = '{';       break;
 
640
                                                case '>':          c = '}';       break;
 
641
                                                case '/':          c = BACKSLASH; goto process;
 
642
                                                case '!':          c = '|';       break;
 
643
                                                case SINGLE_QUOTE: c = '^';       break;
 
644
                                                case '-':          c = '~';       break;
 
645
                                                case '=':          c = '#';       goto process;
 
646
                                                default:
 
647
                                                        fileUngetc (next);
 
648
                                                        cppUngetc ('?');
 
649
                                                        break;
 
650
                                        }
 
651
                                }
 
652
                        } break;
 
653
 
602
654
                        default:
603
 
                            fileUngetc (next);
604
 
                            cppUngetc ('?');
605
 
                            break;
606
 
                    }
 
655
                                if (c == '@' && Cpp.hasAtLiteralStrings)
 
656
                                {
 
657
                                        int next = fileGetc ();
 
658
                                        if (next == DOUBLE_QUOTE)
 
659
                                        {
 
660
                                                Cpp.directive.accept = FALSE;
 
661
                                                c = skipToEndOfString (TRUE);
 
662
                                                break;
 
663
                                        }
 
664
                                }
 
665
                                Cpp.directive.accept = FALSE;
 
666
                                if (directive)
 
667
                                        ignore = handleDirective (c);
 
668
                                break;
607
669
                }
608
 
            } break;
609
 
 
610
 
            default:
611
 
                Cpp.directive.accept = FALSE;
612
 
                if (directive)
613
 
                    ignore = handleDirective (c);
614
 
                break;
615
 
        }
616
 
    } while (directive || ignore);
617
 
 
618
 
    DebugStatement ( debugPutc (DEBUG_CPP, c); )
619
 
    DebugStatement ( if (c == NEWLINE)
620
 
                debugPrintf (DEBUG_CPP, "%6ld: ", getInputLineNumber () + 1); )
621
 
 
622
 
    return c;
 
670
        } while (directive || ignore);
 
671
 
 
672
        DebugStatement ( debugPutc (DEBUG_CPP, c); )
 
673
        DebugStatement ( if (c == NEWLINE)
 
674
                                debugPrintf (DEBUG_CPP, "%6ld: ", getInputLineNumber () + 1); )
 
675
 
 
676
        return c;
623
677
}
624
678
 
625
 
 
626
679
extern char *getArglistFromPos(fpos_t startPosition, const char *tokenName)
627
680
{
628
681
        fpos_t originalPosition;
760
813
        return strdup(start);
761
814
}
762
815
 
763
 
/* vi:set tabstop=8 shiftwidth=4: */
 
816
/* vi:set tabstop=4 shiftwidth=4: */