diff --git a/ctags/main/entry.h b/ctags/main/entry.h index 32f44374..051e2885 100644 --- a/ctags/main/entry.h +++ b/ctags/main/entry.h @@ -26,6 +26,7 @@ #define WHOLE_FILE -1L #define NO_PARSER_FIELD -1 +#define CORK_NIL 0 /* * DATA DECLARATIONS diff --git a/ctags/main/lcpp.c b/ctags/main/lcpp.c index ca17b3b9..3c16f591 100644 --- a/ctags/main/lcpp.c +++ b/ctags/main/lcpp.c @@ -22,7 +22,7 @@ #include "options.h" #include "read.h" #include "vstring.h" -#include "routines.h" +#include "parse.h" #include "xtag.h" /* @@ -135,10 +135,7 @@ extern void cppInit (const bool state, const bool hasAtLiteralStrings, Cpp.directive.ifdef [0].branchChosen = false; Cpp.directive.ifdef [0].ignoring = false; - if (Cpp.directive.name == NULL) - Cpp.directive.name = vStringNew (); - else - vStringClear (Cpp.directive.name); + Cpp.directive.name = vStringNewOrClear (Cpp.directive.name); } extern void cppTerminate (void) @@ -305,35 +302,40 @@ static bool popConditional (void) return isIgnore (); } -static void makeDefineTag (const char *const name, bool parameterized) +static int makeDefineTag (const char *const name, bool parameterized, bool undef) { const bool isFileScope = (bool) (! isInputHeaderFile ()); - if (includingDefineTags () && - (! isFileScope || isXtagEnabled(XTAG_FILE_SCOPE))) + if (!Cpp.defineMacroKind) + return CORK_NIL; + if (isFileScope && !isXtagEnabled(XTAG_FILE_SCOPE)) + return CORK_NIL; + + if ( /* condition for definition tag */ + ((!undef) && Cpp.defineMacroKind->enabled) + || /* condition for reference tag */ + (undef && isXtagEnabled(XTAG_REFERENCE_TAGS))) { tagEntryInfo e; initTagEntry (&e, name, Cpp.defineMacroKind); - - e.lineNumberEntry = (bool) (Option.locate != EX_PATTERN); + e.lineNumberEntry = (bool) (Option.locate == EX_LINENUM); e.isFileScope = isFileScope; e.truncateLine = true; if (parameterized) - { - e.extensionFields.signature = cppGetArglistFromFilePos(getInputFilePosition() - , e.name); - } + e.extensionFields.signature = cppGetArglistFromFilePos(getInputFilePosition(), e.name); makeTagEntry (&e); if (parameterized) eFree((char *) e.extensionFields.signature); } + return CORK_NIL; } -static void directiveDefine (const int c) +static int directiveDefine (const int c, bool undef) { bool parameterized; int nc; + int r = CORK_NIL; if (cppIsident1 (c)) { @@ -342,9 +344,22 @@ static void directiveDefine (const int c) ungetcToInputFile (nc); parameterized = (bool) (nc == '('); if (! isIgnore ()) - makeDefineTag (vStringValue (Cpp.directive.name), parameterized); + makeDefineTag (vStringValue (Cpp.directive.name), parameterized, undef); } Cpp.directive.state = DRCTV_NONE; + return r; +} + +static void directiveUndef (const int c) +{ + if (isXtagEnabled (XTAG_REFERENCE_TAGS)) + { + directiveDefine (c, true); + } + else + { + Cpp.directive.state = DRCTV_NONE; + } } static void directivePragma (int c) @@ -362,7 +377,7 @@ static void directivePragma (int c) if (cppIsident1 (c)) { readIdentifier (c, Cpp.directive.name); - makeDefineTag (vStringValue (Cpp.directive.name), false); + makeDefineTag (vStringValue (Cpp.directive.name), NULL, false); } } } @@ -417,18 +432,20 @@ static bool directiveHash (const int c) /* Handles a pre-processor directive whose first character is given by "c". */ -static bool handleDirective (const int c) +static bool handleDirective (const int c, int *macroCorkIndex) { bool ignore = isIgnore (); switch (Cpp.directive.state) { case DRCTV_NONE: ignore = isIgnore (); break; - case DRCTV_DEFINE: directiveDefine (c); break; + case DRCTV_DEFINE: + *macroCorkIndex = directiveDefine (c, false); + break; case DRCTV_HASH: ignore = directiveHash (c); break; case DRCTV_IF: ignore = directiveIf (c); break; case DRCTV_PRAGMA: directivePragma (c); break; - case DRCTV_UNDEF: directiveDefine (c); break; + case DRCTV_UNDEF: directiveUndef (c); break; } return ignore; } @@ -612,13 +629,6 @@ static int skipToEndOfChar (void) ungetcToInputFile (c); break; } - else if (count == 1 && strchr ("DHOB", toupper (c)) != NULL) - veraBase = c; - else if (veraBase != '\0' && ! isalnum (c)) - { - ungetcToInputFile (c); - break; - } } return CHAR_SYMBOL; /* symbolic representation of character */ } @@ -633,6 +643,7 @@ extern int cppGetc (void) bool directive = false; bool ignore = false; int c; + int macroCorkIndex = CORK_NIL; if (Cpp.ungetch != '\0') { @@ -643,6 +654,7 @@ extern int cppGetc (void) } else do { +start_loop: c = getcFromInputFile (); process: switch (c) @@ -650,6 +662,7 @@ process: case EOF: ignore = false; directive = false; + macroCorkIndex = CORK_NIL; break; case TAB: @@ -658,7 +671,10 @@ process: case NEWLINE: if (directive && ! ignore) + { + macroCorkIndex = CORK_NIL; directive = false; + } Cpp.directive.accept = true; break; @@ -705,7 +721,7 @@ process: int next = getcFromInputFile (); if (next == NEWLINE) - continue; + goto start_loop; else ungetcToInputFile (next); break; @@ -828,7 +844,7 @@ process: enter: Cpp.directive.accept = false; if (directive) - ignore = handleDirective (c); + ignore = handleDirective (c, ¯oCorkIndex); break; } } while (directive || ignore); diff --git a/ctags/main/lcpp.h b/ctags/main/lcpp.h index 62d17144..371e8666 100644 --- a/ctags/main/lcpp.h +++ b/ctags/main/lcpp.h @@ -28,7 +28,32 @@ * VMS allows '$' in identifiers. * Vala allows '@' in identifiers. */ -#define cppIsident1(c) (isalpha(c) || (c) == '_' || (c) == '~' || (c) == '$' || (c) == '@') +#define cppIsident1(c) ( ((c >= 0) && (c < 0x80) && isalpha(c)) \ + || (c) == '_' || (c) == '~' || (c) == '$' || (c) == '@') +/* NOTE about isident1 profitability + + Doing the same as isascii before passing value to isalpha + ---------------------------------------------------------- + cppGetc() can return the value out of range of char. + cppGetc calls skipToEndOfString and skipToEndOfString can + return STRING_SYMBOL(== 338). + + Depending on the platform, isalpha(338) returns different value . + As far as Fedora22, it returns 0. On Windows 2010, it returns 1. + + man page on Fedora 22 says: + + These functions check whether c, which must have the value of an + unsigned char or EOF, falls into a certain character class + according to the specified locale. + + isascii is for suitable to verify the range of input. However, it + is not portable enough. */ + +#define RoleTemplateUndef { true, "undef", "undefined" } + +#define RoleTemplateSystem { true, "system", "system header" } +#define RoleTemplateLocal { true, "local", "local header" } /* * FUNCTION PROTOTYPES @@ -36,9 +61,10 @@ extern bool cppIsBraceFormat (void); extern unsigned int cppGetDirectiveNestLevel (void); -extern void cppInit (const bool state, const bool hasAtLiteralStrings, - const bool hasCxxRawLiteralStrings, - const kindOption *defineMacroKind); +extern void cppInit (const bool state, + const bool hasAtLiteralStrings, + const bool hasCxxRawLiteralStrings, + const kindOption *defineMacroKind); extern void cppTerminate (void); extern void cppBeginStatement (void); extern void cppEndStatement (void); diff --git a/ctags/parsers/c.c b/ctags/parsers/c.c index c574f07c..ea004fe8 100644 --- a/ctags/parsers/c.c +++ b/ctags/parsers/c.c @@ -3138,11 +3138,16 @@ static bool findCTags (const unsigned int passCount) { exception_t exception; bool retry; + kindOption *kind_for_define = NULL; contextual_fake_count = 0; Assert (passCount < 3); - cppInit ((bool) (passCount > 1), isInputLanguage (Lang_csharp), isInputLanguage (Lang_cpp), &(CKinds [CK_DEFINE])); + + kind_for_define = CKinds+CK_DEFINE; + + cppInit ((bool) (passCount > 1), isInputLanguage (Lang_csharp), isInputLanguage(Lang_cpp), + kind_for_define); exception = (exception_t) setjmp (Exception); retry = false;