Handle template expressions that may use the << or >> operators
[arduino-ctags.git] / get.c
blobd74ed95bb8ae1d7b99a8be1b084850418103acc2
1 /*
2 * $Id: get.c 559 2007-06-17 03:30:09Z elliotth $
4 * Copyright (c) 1996-2002, Darren Hiebert
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains the high level source read functions (preprocessor
10 * directives are handled within this level).
14 * INCLUDE FILES
16 #include "general.h" /* must always come first */
18 #include <string.h>
20 #include "debug.h"
21 #include "entry.h"
22 #include "get.h"
23 #include "options.h"
24 #include "read.h"
25 #include "vstring.h"
28 * MACROS
30 #define stringMatch(s1,s2) (strcmp (s1,s2) == 0)
31 #define isspacetab(c) ((c) == SPACE || (c) == TAB)
34 * DATA DECLARATIONS
36 typedef enum { COMMENT_NONE, COMMENT_C, COMMENT_CPLUS } Comment;
38 enum eCppLimits {
39 MaxCppNestingLevel = 20,
40 MaxDirectiveName = 10
43 /* Defines the one nesting level of a preprocessor conditional.
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 */
50 } conditionalInfo;
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 */
61 /* Defines the current state of the pre-processor.
63 typedef struct sCppState {
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;
74 } cppState;
77 * DATA DEFINITIONS
80 /* Use brace formatting to detect end of block.
82 static boolean BraceFormat = FALSE;
84 static cppState Cpp = {
85 '\0', '\0', /* ungetch characters */
86 FALSE, /* resolveRequired */
87 FALSE, /* hasAtLiteralStrings */
89 DRCTV_NONE, /* state */
90 FALSE, /* accept */
91 NULL, /* tag name */
92 0, /* nestLevel */
93 { {FALSE,FALSE,FALSE,FALSE} } /* ifdef array */
94 } /* directive */
98 * FUNCTION DEFINITIONS
101 extern boolean isBraceFormat (void)
103 return BraceFormat;
106 extern unsigned int getDirectiveNestLevel (void)
108 return Cpp.directive.nestLevel;
111 extern void cppInit (const boolean state, const boolean hasAtLiteralStrings)
113 BraceFormat = state;
115 Cpp.ungetch = '\0';
116 Cpp.ungetch2 = '\0';
117 Cpp.resolveRequired = FALSE;
118 Cpp.hasAtLiteralStrings = hasAtLiteralStrings;
120 Cpp.directive.state = DRCTV_NONE;
121 Cpp.directive.accept = TRUE;
122 Cpp.directive.nestLevel = 0;
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;
129 if (Cpp.directive.name == NULL)
130 Cpp.directive.name = vStringNew ();
131 else
132 vStringClear (Cpp.directive.name);
135 extern void cppTerminate (void)
137 if (Cpp.directive.name != NULL)
139 vStringDelete (Cpp.directive.name);
140 Cpp.directive.name = NULL;
144 extern void cppBeginStatement (void)
146 Cpp.resolveRequired = TRUE;
149 extern void cppEndStatement (void)
151 Cpp.resolveRequired = FALSE;
155 * Scanning functions
157 * This section handles preprocessor directives. It strips out all
158 * directives and may emit a tag for #define directives.
161 /* This puts a character back into the input queue for the source File.
162 * Up to two characters may be ungotten.
164 extern void cppUngetc (const int c)
166 Assert (Cpp.ungetch2 == '\0');
167 Cpp.ungetch2 = Cpp.ungetch;
168 Cpp.ungetch = c;
171 /* Reads a directive, whose first character is given by "c", into "name".
173 static boolean readDirective (int c, char *const name, unsigned int maxLength)
175 unsigned int i;
177 for (i = 0 ; i < maxLength - 1 ; ++i)
179 if (i > 0)
181 c = fileGetc ();
182 if (c == EOF || ! isalpha (c))
184 fileUngetc (c);
185 break;
188 name [i] = c;
190 name [i] = '\0'; /* null terminate */
192 return (boolean) isspacetab (c);
195 /* Reads an identifier, whose first character is given by "c", into "tag",
196 * together with the file location and corresponding line number.
198 static void readIdentifier (int c, vString *const name)
200 vStringClear (name);
203 vStringPut (name, c);
204 } while (c = fileGetc (), (c != EOF && isident (c)));
205 fileUngetc (c);
206 vStringTerminate (name);
209 static conditionalInfo *currentConditional (void)
211 return &Cpp.directive.ifdef [Cpp.directive.nestLevel];
214 static boolean isIgnore (void)
216 return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring;
219 static boolean setIgnore (const boolean ignore)
221 return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring = ignore;
224 static boolean isIgnoreBranch (void)
226 conditionalInfo *const ifdef = currentConditional ();
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.
232 if (Cpp.resolveRequired && ! BraceFormat)
233 ifdef->singleBranch = TRUE;
235 /* We will ignore this branch in the following cases:
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
243 return (boolean) (ifdef->ignoreAllBranches ||
244 (ifdef->branchChosen && ifdef->singleBranch));
247 static void chooseBranch (void)
249 if (! BraceFormat)
251 conditionalInfo *const ifdef = currentConditional ();
253 ifdef->branchChosen = (boolean) (ifdef->singleBranch ||
254 Cpp.resolveRequired);
258 /* Pushes one nesting level for an #if directive, indicating whether or not
259 * the branch should be ignored and whether a branch has already been chosen.
261 static boolean pushConditional (const boolean firstBranchChosen)
263 const boolean ignoreAllBranches = isIgnore (); /* current ignore */
264 boolean ignoreBranch = FALSE;
266 if (Cpp.directive.nestLevel < (unsigned int) MaxCppNestingLevel - 1)
268 conditionalInfo *ifdef;
270 ++Cpp.directive.nestLevel;
271 ifdef = currentConditional ();
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.
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;
286 return ignoreBranch;
289 /* Pops one nesting level for an #endif directive.
291 static boolean popConditional (void)
293 if (Cpp.directive.nestLevel > 0)
294 --Cpp.directive.nestLevel;
296 return isIgnore ();
299 static void makeDefineTag (const char *const name)
301 const boolean isFileScope = (boolean) (! isHeaderFile ());
303 if (includingDefineTags () &&
304 (! isFileScope || Option.include.fileScope))
306 tagEntryInfo e;
307 initTagEntry (&e, name);
308 e.lineNumberEntry = (boolean) (Option.locate != EX_PATTERN);
309 e.isFileScope = isFileScope;
310 e.truncateLine = TRUE;
311 e.kindName = "macro";
312 e.kind = 'd';
313 makeTagEntry (&e);
317 static void directiveDefine (const int c)
319 if (isident1 (c))
321 readIdentifier (c, Cpp.directive.name);
322 if (! isIgnore ())
323 makeDefineTag (vStringValue (Cpp.directive.name));
325 Cpp.directive.state = DRCTV_NONE;
328 static void directivePragma (int c)
330 if (isident1 (c))
332 readIdentifier (c, Cpp.directive.name);
333 if (stringMatch (vStringValue (Cpp.directive.name), "weak"))
335 /* generate macro tag for weak name */
338 c = fileGetc ();
339 } while (c == SPACE);
340 if (isident1 (c))
342 readIdentifier (c, Cpp.directive.name);
343 makeDefineTag (vStringValue (Cpp.directive.name));
347 Cpp.directive.state = DRCTV_NONE;
350 static boolean directiveIf (const int c)
352 DebugStatement ( const boolean ignore0 = isIgnore (); )
353 const boolean ignore = pushConditional ((boolean) (c != '0'));
355 Cpp.directive.state = DRCTV_NONE;
356 DebugStatement ( debugCppNest (TRUE, Cpp.directive.nestLevel);
357 if (ignore != ignore0) debugCppIgnore (ignore); )
359 return ignore;
362 static boolean directiveHash (const int c)
364 boolean ignore = FALSE;
365 char directive [MaxDirectiveName];
366 DebugStatement ( const boolean ignore0 = isIgnore (); )
368 readDirective (c, directive, MaxDirectiveName);
369 if (stringMatch (directive, "define"))
370 Cpp.directive.state = DRCTV_DEFINE;
371 else if (stringMatch (directive, "undef"))
372 Cpp.directive.state = DRCTV_UNDEF;
373 else if (strncmp (directive, "if", (size_t) 2) == 0)
374 Cpp.directive.state = DRCTV_IF;
375 else if (stringMatch (directive, "elif") ||
376 stringMatch (directive, "else"))
378 ignore = setIgnore (isIgnoreBranch ());
379 if (! ignore && stringMatch (directive, "else"))
380 chooseBranch ();
381 Cpp.directive.state = DRCTV_NONE;
382 DebugStatement ( if (ignore != ignore0) debugCppIgnore (ignore); )
384 else if (stringMatch (directive, "endif"))
386 DebugStatement ( debugCppNest (FALSE, Cpp.directive.nestLevel); )
387 ignore = popConditional ();
388 Cpp.directive.state = DRCTV_NONE;
389 DebugStatement ( if (ignore != ignore0) debugCppIgnore (ignore); )
391 else if (stringMatch (directive, "pragma"))
392 Cpp.directive.state = DRCTV_PRAGMA;
393 else
394 Cpp.directive.state = DRCTV_NONE;
396 return ignore;
399 /* Handles a pre-processor directive whose first character is given by "c".
401 static boolean handleDirective (const int c)
403 boolean ignore = isIgnore ();
405 switch (Cpp.directive.state)
407 case DRCTV_NONE: ignore = isIgnore (); break;
408 case DRCTV_DEFINE: directiveDefine (c); break;
409 case DRCTV_HASH: ignore = directiveHash (c); break;
410 case DRCTV_IF: ignore = directiveIf (c); break;
411 case DRCTV_PRAGMA: directivePragma (c); break;
412 case DRCTV_UNDEF: directiveDefine (c); break;
414 return ignore;
417 /* Called upon reading of a slash ('/') characters, determines whether a
418 * comment is encountered, and its type.
420 static Comment isComment (void)
422 Comment comment;
423 const int next = fileGetc ();
425 if (next == '*')
426 comment = COMMENT_C;
427 else if (next == '/')
428 comment = COMMENT_CPLUS;
429 else
431 fileUngetc (next);
432 comment = COMMENT_NONE;
434 return comment;
437 /* Skips over a C style comment. According to ANSI specification a comment
438 * is treated as white space, so we perform this substitution.
440 int skipOverCComment (void)
442 int c = fileGetc ();
444 while (c != EOF)
446 if (c != '*')
447 c = fileGetc ();
448 else
450 const int next = fileGetc ();
452 if (next != '/')
453 c = next;
454 else
456 c = SPACE; /* replace comment with space */
457 break;
461 return c;
464 /* Skips over a C++ style comment.
466 static int skipOverCplusComment (void)
468 int c;
470 while ((c = fileGetc ()) != EOF)
472 if (c == BACKSLASH)
473 fileGetc (); /* throw away next character, too */
474 else if (c == NEWLINE)
475 break;
477 return c;
480 /* Skips to the end of a string, returning a special character to
481 * symbolically represent a generic string.
483 static int skipToEndOfString (boolean ignoreBackslash)
485 int c;
487 while ((c = fileGetc ()) != EOF)
489 if (c == BACKSLASH && ! ignoreBackslash)
490 fileGetc (); /* throw away next character, too */
491 else if (c == DOUBLE_QUOTE)
492 break;
494 return STRING_SYMBOL; /* symbolic representation of string */
497 /* Skips to the end of the three (possibly four) 'c' sequence, returning a
498 * special character to symbolically represent a generic character.
499 * Also detects Vera numbers that include a base specifier (ie. 'b1010).
501 static int skipToEndOfChar (void)
503 int c;
504 int count = 0, veraBase = '\0';
506 while ((c = fileGetc ()) != EOF)
508 ++count;
509 if (c == BACKSLASH)
510 fileGetc (); /* throw away next character, too */
511 else if (c == SINGLE_QUOTE)
512 break;
513 else if (c == NEWLINE)
515 fileUngetc (c);
516 break;
518 else if (count == 1 && strchr ("DHOB", toupper (c)) != NULL)
519 veraBase = c;
520 else if (veraBase != '\0' && ! isalnum (c))
522 fileUngetc (c);
523 break;
526 return CHAR_SYMBOL; /* symbolic representation of character */
529 /* This function returns the next character, stripping out comments,
530 * C pre-processor directives, and the contents of single and double
531 * quoted strings. In short, strip anything which places a burden upon
532 * the tokenizer.
534 extern int cppGetc (void)
536 boolean directive = FALSE;
537 boolean ignore = FALSE;
538 int c;
540 if (Cpp.ungetch != '\0')
542 c = Cpp.ungetch;
543 Cpp.ungetch = Cpp.ungetch2;
544 Cpp.ungetch2 = '\0';
545 return c; /* return here to avoid re-calling debugPutc () */
547 else do
549 c = fileGetc ();
550 process:
551 switch (c)
553 case EOF:
554 ignore = FALSE;
555 directive = FALSE;
556 break;
558 case TAB:
559 case SPACE:
560 break; /* ignore most white space */
562 case NEWLINE:
563 if (directive && ! ignore)
564 directive = FALSE;
565 Cpp.directive.accept = TRUE;
566 break;
568 case DOUBLE_QUOTE:
569 Cpp.directive.accept = FALSE;
570 c = skipToEndOfString (FALSE);
571 break;
573 case '#':
574 if (Cpp.directive.accept)
576 directive = TRUE;
577 Cpp.directive.state = DRCTV_HASH;
578 Cpp.directive.accept = FALSE;
580 break;
582 case SINGLE_QUOTE:
583 Cpp.directive.accept = FALSE;
584 c = skipToEndOfChar ();
585 break;
587 case '/':
589 const Comment comment = isComment ();
591 if (comment == COMMENT_C)
592 c = skipOverCComment ();
593 else if (comment == COMMENT_CPLUS)
595 c = skipOverCplusComment ();
596 if (c == NEWLINE)
597 fileUngetc (c);
599 else
600 Cpp.directive.accept = FALSE;
601 break;
604 case BACKSLASH:
606 int next = fileGetc ();
608 if (next == NEWLINE)
609 continue;
610 else if (next == '?')
611 cppUngetc (next);
612 else
613 fileUngetc (next);
614 break;
617 case '?':
619 int next = fileGetc ();
620 if (next != '?')
621 fileUngetc (next);
622 else
624 next = fileGetc ();
625 switch (next)
627 case '(': c = '['; break;
628 case ')': c = ']'; break;
629 case '<': c = '{'; break;
630 case '>': c = '}'; break;
631 case '/': c = BACKSLASH; goto process;
632 case '!': c = '|'; break;
633 case SINGLE_QUOTE: c = '^'; break;
634 case '-': c = '~'; break;
635 case '=': c = '#'; goto process;
636 default:
637 fileUngetc (next);
638 cppUngetc ('?');
639 break;
642 } break;
644 default:
645 if (c == '@' && Cpp.hasAtLiteralStrings)
647 int next = fileGetc ();
648 if (next == DOUBLE_QUOTE)
650 Cpp.directive.accept = FALSE;
651 c = skipToEndOfString (TRUE);
652 break;
655 Cpp.directive.accept = FALSE;
656 if (directive)
657 ignore = handleDirective (c);
658 break;
660 } while (directive || ignore);
662 DebugStatement ( debugPutc (DEBUG_CPP, c); )
663 DebugStatement ( if (c == NEWLINE)
664 debugPrintf (DEBUG_CPP, "%6ld: ", getInputLineNumber () + 1); )
666 return c;
669 /* vi:set tabstop=4 shiftwidth=4: */