From bd7610b4578d115ca6cbcc26244b10d017a14a26 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Tue, 23 Feb 2016 17:04:48 +0900 Subject: [PATCH 01/12] main: automatic fq generation --- main/entry.c | 22 +++++++++++++++++++--- main/parse.c | 9 ++++++++- main/parse.h | 2 ++ main/read.h | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/main/entry.c b/main/entry.c index 1af00c52de..fa530c2f90 100644 --- a/main/entry.c +++ b/main/entry.c @@ -970,8 +970,15 @@ static int addExtensionFields (const tagEntryInfo *const tag) scopeKey, scope->kind->name, full_qualified_scope_name); - /* TODO: Make the value pointed by full_qualified_scope_name reusable. */ - eFree (full_qualified_scope_name); + if (doesInputLanguageRequestAutomaticFQTag () + && isXtagEnabled (XTAG_QUALIFIED_TAGS)) + { + /* Make the information reusable to generate full qualified entry. */ + ((tagEntryInfo *const)tag)->extensionFields.scopeKind = scope->kind; + ((tagEntryInfo *const)tag)->extensionFields.scopeName = full_qualified_scope_name; + } + else + eFree (full_qualified_scope_name); } } @@ -1372,7 +1379,16 @@ extern void uncorkTagFile(void) return ; for (i = 1; i < TagFile.corkQueue.count; i++) - writeTagEntry (TagFile.corkQueue.queue + i); + { + tagEntryInfo *tag = TagFile.corkQueue.queue + i; + writeTagEntry (tag); + if (doesInputLanguageRequestAutomaticFQTag () + && isXtagEnabled (XTAG_QUALIFIED_TAGS) + && tag->extensionFields.scopeKind + && tag->extensionFields.scopeName + && tag->extensionFields.scopeIndex) + makeQualifiedTagEntry (tag); + } for (i = 1; i < TagFile.corkQueue.count; i++) clearTagEntryInQueue (TagFile.corkQueue.queue + i); diff --git a/main/parse.c b/main/parse.c index 217c100c11..98f5258ff9 100644 --- a/main/parse.c +++ b/main/parse.c @@ -177,6 +177,12 @@ extern boolean doesLanguageAllowNullTag (const langType language) return LanguageTable [language]->allowNullTag; } +extern boolean doesLanguageRequestAutomaticFQTag (const langType language) +{ + Assert (0 <= language && language < (int) LanguageCount); + return LanguageTable [language]->requestAutomaticFQTag; +} + extern const char *getLanguageName (const langType language) { const char* result; @@ -1391,7 +1397,8 @@ extern void initializeParser (langType lang) installTagXpathTable (lang); installFieldSpec (lang); - if (hasScopeActionInRegex (lang)) + if (hasScopeActionInRegex (lang) + || parser->requestAutomaticFQTag) parser->useCork = TRUE; if ((parser->initialize != NULL) && (parser->initialized == FALSE)) diff --git a/main/parse.h b/main/parse.h index 61e3861ca8..d722010960 100644 --- a/main/parse.h +++ b/main/parse.h @@ -138,6 +138,7 @@ typedef struct { unsigned int method; /* See PARSE__... definitions above */ boolean useCork; boolean allowNullTag; + boolean requestAutomaticFQTag; const tagRegexTable *tagRegexTable; unsigned int tagRegexCount; const keywordTable *keywordTable; @@ -199,6 +200,7 @@ extern int makeSimpleRefTag (const vString* const name, kindOption* const kinds, extern parserDefinition* parserNew (const char* name); extern parserDefinition* parserNewFull (const char* name, char fileKind); extern boolean doesLanguageAllowNullTag (const langType language); +extern boolean doesLanguageRequestAutomaticFQTag (const langType language); extern const char *getLanguageName (const langType language); extern kindOption* getLanguageFileKind (const langType language); extern langType getNamedLanguage (const char *const name, size_t len); diff --git a/main/read.h b/main/read.h index 5f1e38ef5f..67997940fc 100644 --- a/main/read.h +++ b/main/read.h @@ -47,6 +47,7 @@ #define doesInputLanguageAllowNullTag() doesLanguageAllowNullTag (File.input.language) #define getInputLanguageFileKind() getLanguageFileKind (File.input.language) +#define doesInputLanguageRequestAutomaticFQTag() doesLanguageRequestAutomaticFQTag (File.input.language) #define getSourceFileTagPath() vStringValue (File.source.tagPath) #define getSourceLanguageName() getLanguageName (File.source.language) #define getSourceLineNumber() File.source.lineNumber From f6dafc0609db8a478c9791eb39a65494ec0ac921 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Fri, 18 Mar 2016 02:35:31 +0900 Subject: [PATCH 02/12] dtc: utilize cork based automatic FQ tag generator Signed-off-by: Masatake YAMATO --- Units/dts-simple.d/args.ctags | 2 +- Units/dts-simple.d/expected.tags | 2 ++ parsers/dts.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Units/dts-simple.d/args.ctags b/Units/dts-simple.d/args.ctags index f92a4351d9..795a162d94 100644 --- a/Units/dts-simple.d/args.ctags +++ b/Units/dts-simple.d/args.ctags @@ -1,2 +1,2 @@ --fields=+Zr ---extra=+r +--extra=+rq diff --git a/Units/dts-simple.d/expected.tags b/Units/dts-simple.d/expected.tags index 7a60c19248..acd6f5cb36 100644 --- a/Units/dts-simple.d/expected.tags +++ b/Units/dts-simple.d/expected.tags @@ -3,4 +3,6 @@ bar input.dts /^#define bar /;" d file: bar input.dts /^#undef bar$/;" d file: role:undef foo.dtsi input.dts /^#include "foo.dtsi"/;" h role:local label input.dts /^label: test {$/;" l +label.0x00 input.dts /^ phandle = <0x00>;$/;" p scope:label:label +label.label2 input.dts /^ label2: chosen { } ;$/;" l scope:label:label label2 input.dts /^ label2: chosen { } ;$/;" l scope:label:label diff --git a/parsers/dts.c b/parsers/dts.c index 6980c96e80..872ef28ba5 100644 --- a/parsers/dts.c +++ b/parsers/dts.c @@ -89,6 +89,7 @@ extern parserDefinition* DTSParser (void) def->tagRegexTable = dtsTagRegexTable; def->tagRegexCount = ARRAY_SIZE (dtsTagRegexTable); def->method = METHOD_REGEX; + def->requestAutomaticFQTag = TRUE; return def; } From 221de4ddd7ffc0d9fc70d861d2e03312f2efc5de Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Fri, 18 Mar 2016 12:20:50 +0900 Subject: [PATCH 03/12] main: allow automagic FQ tags generator to emit FQ tags even when --fields=-s is given Signed-off-by: Masatake YAMATO --- Units/dts-fq-without-scope-field.d/README | 6 ++ Units/dts-fq-without-scope-field.d/args.ctags | 2 + .../expected.tags | 8 +++ Units/dts-fq-without-scope-field.d/input.dts | 12 ++++ main/entry.c | 60 +++++++++++-------- 5 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 Units/dts-fq-without-scope-field.d/README create mode 100644 Units/dts-fq-without-scope-field.d/args.ctags create mode 100644 Units/dts-fq-without-scope-field.d/expected.tags create mode 100644 Units/dts-fq-without-scope-field.d/input.dts diff --git a/Units/dts-fq-without-scope-field.d/README b/Units/dts-fq-without-scope-field.d/README new file mode 100644 index 0000000000..935936ea3e --- /dev/null +++ b/Units/dts-fq-without-scope-field.d/README @@ -0,0 +1,6 @@ +This test case verifies a corner use case of Cork based automatic full +qualified tag generator(FQgen). + +FQgen caches scope informations built just before emitting it as value +for scope fields. Therefore when --field=-s(disabling scope field) is +given, FQ tags were not generated. diff --git a/Units/dts-fq-without-scope-field.d/args.ctags b/Units/dts-fq-without-scope-field.d/args.ctags new file mode 100644 index 0000000000..5f9b7cf2ed --- /dev/null +++ b/Units/dts-fq-without-scope-field.d/args.ctags @@ -0,0 +1,2 @@ +--fields=+Zr-s +--extra=+rq diff --git a/Units/dts-fq-without-scope-field.d/expected.tags b/Units/dts-fq-without-scope-field.d/expected.tags new file mode 100644 index 0000000000..05faf04d81 --- /dev/null +++ b/Units/dts-fq-without-scope-field.d/expected.tags @@ -0,0 +1,8 @@ +0x00 input.dts /^ phandle = <0x00>;$/;" p +bar input.dts /^#define bar /;" d file: +bar input.dts /^#undef bar$/;" d file: role:undef +foo.dtsi input.dts /^#include "foo.dtsi"/;" h role:local +label input.dts /^label: test {$/;" l +label.0x00 input.dts /^ phandle = <0x00>;$/;" p +label.label2 input.dts /^ label2: chosen { } ;$/;" l +label2 input.dts /^ label2: chosen { } ;$/;" l diff --git a/Units/dts-fq-without-scope-field.d/input.dts b/Units/dts-fq-without-scope-field.d/input.dts new file mode 100644 index 0000000000..ab29875fe7 --- /dev/null +++ b/Units/dts-fq-without-scope-field.d/input.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +#include "foo.dtsi" +#define bar 98 + +label: test { + dummy { + label2: chosen { } ; + phandle = <0x00>; + }; +}; +#undef bar diff --git a/main/entry.c b/main/entry.c index fa530c2f90..89668178b2 100644 --- a/main/entry.c +++ b/main/entry.c @@ -926,6 +926,10 @@ static int addExtensionFields (const tagEntryInfo *const tag) const char* separator = ";\""; const char* const empty = ""; int length = 0; + + boolean making_fq_tag = (doesInputLanguageRequestAutomaticFQTag () + && isXtagEnabled (XTAG_QUALIFIED_TAGS)); + /* "sep" returns a value only the first time it is evaluated */ #define sep (first ? (first = FALSE, separator) : empty) @@ -949,46 +953,50 @@ static int addExtensionFields (const tagEntryInfo *const tag) getFieldName (FIELD_LANGUAGE), escapeName (tag, FIELD_LANGUAGE)); - if (isFieldEnabled (FIELD_SCOPE)) + if (isFieldEnabled (FIELD_SCOPE) || making_fq_tag) { + const tagEntryInfo * scope = NULL; + char *full_qualified_scope_name = NULL; + + const char* k = NULL, *v = NULL; + if (tag->extensionFields.scopeKind != NULL && tag->extensionFields.scopeName != NULL) - length += mio_printf (TagFile.fp, scopeFmt, sep, - scopeKey, - tag->extensionFields.scopeKind->name, - escapeName (tag, FIELD_SCOPE)); - else if (tag->extensionFields.scopeIndex != CORK_NIL + { + k = tag->extensionFields.scopeKind->name; + v = escapeName (tag, FIELD_SCOPE); + } + else if (tag->extensionFields.scopeIndex != SCOPE_NIL && TagFile.corkQueue.count > 0) { - const tagEntryInfo * scope; - char *full_qualified_scope_name; - scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex); full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope); Assert (full_qualified_scope_name); - length += mio_printf (TagFile.fp, scopeFmt, sep, - scopeKey, - scope->kind->name, full_qualified_scope_name); - if (doesInputLanguageRequestAutomaticFQTag () - && isXtagEnabled (XTAG_QUALIFIED_TAGS)) - { - /* Make the information reusable to generate full qualified entry. */ - ((tagEntryInfo *const)tag)->extensionFields.scopeKind = scope->kind; - ((tagEntryInfo *const)tag)->extensionFields.scopeName = full_qualified_scope_name; - } - else - eFree (full_qualified_scope_name); + k = scope->kind->name; + v = full_qualified_scope_name; } + + if (isFieldEnabled (FIELD_SCOPE) && k && v) + length += mio_printf (TagFile.fp, scopeFmt, sep, scopeKey, k, v); + + if (scope && full_qualified_scope_name) + { + /* Make the information reusable to generate full qualified entry, and xformat output*/ + ((tagEntryInfo *const)tag)->extensionFields.scopeKind = scope->kind; + ((tagEntryInfo *const)tag)->extensionFields.scopeName = full_qualified_scope_name; + } + else + eFree (full_qualified_scope_name); } if (isFieldEnabled (FIELD_TYPE_REF) && - tag->extensionFields.typeRef [0] != NULL && - tag->extensionFields.typeRef [1] != NULL) + tag->extensionFields.typeRef [0] != NULL && + tag->extensionFields.typeRef [1] != NULL) length += mio_printf (TagFile.fp, "%s\t%s:%s:%s", sep, - getFieldName (FIELD_TYPE_REF), - tag->extensionFields.typeRef [0], - escapeName (tag, FIELD_TYPE_REF)); + getFieldName (FIELD_TYPE_REF), + tag->extensionFields.typeRef [0], + escapeName (tag, FIELD_TYPE_REF)); if (isFieldEnabled (FIELD_FILE_SCOPE) && tag->isFileScope) length += mio_printf (TagFile.fp, "%s\t%s:", sep, From 23b0cc44452b6cc3d7dfd020c2a89f021f11b6b3 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sat, 19 Mar 2016 06:28:49 +0900 Subject: [PATCH 04/12] docs: write about automatic FQ generation Signed-off-by: Masatake YAMATO --- docs/internal.rst | 29 +++++++++++++++++++++++++++-- docs/optlib.rst | 3 +++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/internal.rst b/docs/internal.rst index 01fa92067e..d2e86b312f 100644 --- a/docs/internal.rst +++ b/docs/internal.rst @@ -95,7 +95,7 @@ parser does not set `useCork` field. `writeTagEntry` calls one of three functions, `writeTagsEntry`, `writeXrefEntry` or `writeCtagsEntry`. One of them is chosen depending on the arguments passed to ctags. -If `useCork` is set, the tag informations goes to a queue on memory. +If `useCork` is set, the tag information goes to a queue on memory. The queue is flushed when `useCork` in unset. See `cork API` for more details. @@ -121,7 +121,7 @@ Following code is taken from clojure.c(with modifications). makeTagEntry (¤t); `parent`, values stored to `scope [0]` and `scope [1]` are all -something string. +kind of strings. cork API provides more solid way to hold scope information. cork API expects `parent`, which represents scope of a tag(`current`) @@ -199,3 +199,28 @@ When using `scopeIndex` of `current`, `NULL` must be assigned to both `current.extensionFields.scope[1]`. `initTagEntry` function does this initialization internally, so you generally you don't have to write the initialization explicitly. + +Automatic full qualified tag generation +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, + +If a parser uses the cork for recording and emitting scope +information, ctags can reuse it for generating full qualified(FQ) +tags. Set `requestAutomaticFQTag` field of `parserDefinition` to +`TRUE` then the main part of ctags emits FQ tags on behalf of the parser +if `--extra=+q` is given. + +An example can be found in DTS parser: + +.. code-block:: c + + extern parserDefinition* DTSParser (void) + { + static const char *const extensions [] = { "dts", "dtsi", NULL }; + parserDefinition* const def = parserNew ("DTS"); + ... + def->requestAutomaticFQTag = TRUE; + return def; + } + +Setting `requestAutomaticFQTag` to `TRUE` implies setting +`useCork` to `TRUE`. diff --git a/docs/optlib.rst b/docs/optlib.rst index 3e8a610035..db6d180748 100644 --- a/docs/optlib.rst +++ b/docs/optlib.rst @@ -435,6 +435,9 @@ Example 2:: foo /tmp/input.pp /^class foo {$/;" c +NOTE: Giving a scope long flag implies setting `useCork` of the parser +to `TRUE`. See `cork API`. + Override the letter for file kind ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (See also #317.) From fdbcfbd5e70afcc8455813fba4d0d2fd1e5d8903 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 11 May 2016 13:15:13 +0900 Subject: [PATCH 05/12] main: move printf function at the end of block when printing scope information To reuse the code making scope information, I'm working on separating the code making scope information and the code printing them. This is the initial step. A buffer pointed by full_qualified_scope_name was freed the original code. However, it is always freed when flusing the cork queue. So this commit deletes the code freeing the buffer. Signed-off-by: Masatake YAMATO --- main/entry.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/main/entry.c b/main/entry.c index 89668178b2..1ed9b9e22e 100644 --- a/main/entry.c +++ b/main/entry.c @@ -884,6 +884,9 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_ v = vStringNewInit (sep); stringListAdd (queue, v); } + /* TODO: scope field of SCOPE can be used for optimization. + In that case, whether scope field is escaped or not + must be cared. */ v = vStringNewInit (escapeName (scope, FIELD_NAME)); stringListAdd (queue, v); kind = scope->kind; @@ -955,39 +958,38 @@ static int addExtensionFields (const tagEntryInfo *const tag) if (isFieldEnabled (FIELD_SCOPE) || making_fq_tag) { - const tagEntryInfo * scope = NULL; - char *full_qualified_scope_name = NULL; - const char* k = NULL, *v = NULL; + boolean hasAlreadyEscaped; - if (tag->extensionFields.scopeKind != NULL && - tag->extensionFields.scopeName != NULL) - { - k = tag->extensionFields.scopeKind->name; - v = escapeName (tag, FIELD_SCOPE); - } - else if (tag->extensionFields.scopeIndex != SCOPE_NIL - && TagFile.corkQueue.count > 0) + if (tag->extensionFields.scopeKind == NULL + && tag->extensionFields.scopeName == NULL + && tag->extensionFields.scopeIndex != SCOPE_NIL + && TagFile.corkQueue.count > 0) { + const tagEntryInfo * scope = NULL; + char *full_qualified_scope_name = NULL; + scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex); full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope); Assert (full_qualified_scope_name); - k = scope->kind->name; - v = full_qualified_scope_name; - } - - if (isFieldEnabled (FIELD_SCOPE) && k && v) - length += mio_printf (TagFile.fp, scopeFmt, sep, scopeKey, k, v); - - if (scope && full_qualified_scope_name) - { /* Make the information reusable to generate full qualified entry, and xformat output*/ ((tagEntryInfo *const)tag)->extensionFields.scopeKind = scope->kind; ((tagEntryInfo *const)tag)->extensionFields.scopeName = full_qualified_scope_name; } - else - eFree (full_qualified_scope_name); + + hasAlreadyEscaped = tag->extensionFields.scopeIndex != SCOPE_NIL; + if (tag->extensionFields.scopeKind != NULL && + tag->extensionFields.scopeName != NULL) + { + k = tag->extensionFields.scopeKind->name; + v = hasAlreadyEscaped + ? tag->extensionFields.scopeName + : escapeName (tag, FIELD_SCOPE); + } + + if (isFieldEnabled (FIELD_SCOPE) && k && v) + length += mio_printf (TagFile.fp, scopeFmt, sep, scopeKey, k, v); } if (isFieldEnabled (FIELD_TYPE_REF) && From 3d043a6a8eef88ca8b2961d869ffc83bd5f2f1da Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 11 May 2016 14:22:53 +0900 Subject: [PATCH 06/12] main: keep auto-generated scope information as is (unescaped) till printing To reuse auto-generated scope information (and full qualified name) wider area in ctags, the process escaping the scope name (and fq name) should be delayed. If the process done in too early stage, double escaping can be occurs somewhere. Signed-off-by: Masatake YAMATO --- main/entry.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/main/entry.c b/main/entry.c index 1ed9b9e22e..041b0e4f73 100644 --- a/main/entry.c +++ b/main/entry.c @@ -884,10 +884,8 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_ v = vStringNewInit (sep); stringListAdd (queue, v); } - /* TODO: scope field of SCOPE can be used for optimization. - In that case, whether scope field is escaped or not - must be cared. */ - v = vStringNewInit (escapeName (scope, FIELD_NAME)); + /* TODO: scope field of SCOPE can be used for optimization. */ + v = vStringNewInit (scope->name); stringListAdd (queue, v); kind = scope->kind; } @@ -959,7 +957,6 @@ static int addExtensionFields (const tagEntryInfo *const tag) if (isFieldEnabled (FIELD_SCOPE) || making_fq_tag) { const char* k = NULL, *v = NULL; - boolean hasAlreadyEscaped; if (tag->extensionFields.scopeKind == NULL && tag->extensionFields.scopeName == NULL @@ -978,14 +975,11 @@ static int addExtensionFields (const tagEntryInfo *const tag) ((tagEntryInfo *const)tag)->extensionFields.scopeName = full_qualified_scope_name; } - hasAlreadyEscaped = tag->extensionFields.scopeIndex != SCOPE_NIL; if (tag->extensionFields.scopeKind != NULL && tag->extensionFields.scopeName != NULL) { k = tag->extensionFields.scopeKind->name; - v = hasAlreadyEscaped - ? tag->extensionFields.scopeName - : escapeName (tag, FIELD_SCOPE); + v = escapeName (tag, FIELD_SCOPE); } if (isFieldEnabled (FIELD_SCOPE) && k && v) From 94141ad20f966edab996700ade93ba15986d84eb Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 11 May 2016 14:44:19 +0900 Subject: [PATCH 07/12] refactor: introduce a helper function for making scope information string Signed-off-by: Masatake YAMATO --- main/entry.c | 60 +++++++++++++++++++++++++++++++--------------------- main/entry.h | 2 ++ 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/main/entry.c b/main/entry.c index 041b0e4f73..f5275fec5d 100644 --- a/main/entry.c +++ b/main/entry.c @@ -905,6 +905,41 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_ return vStringDeleteUnwrap (n); } +extern void getTagScopeInformation (tagEntryInfo *const tag, + const char **kind, const char **name) +{ + if (kind) + *kind = NULL; + if (name) + *name = NULL; + + if (tag->extensionFields.scopeKind == NULL + && tag->extensionFields.scopeName == NULL + && tag->extensionFields.scopeIndex != CORK_NIL + && TagFile.corkQueue.count > 0) + { + const tagEntryInfo * scope = NULL; + char *full_qualified_scope_name = NULL; + + scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex); + full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope); + Assert (full_qualified_scope_name); + + /* Make the information reusable to generate full qualified entry, and xformat output*/ + tag->extensionFields.scopeKind = scope->kind; + tag->extensionFields.scopeName = full_qualified_scope_name; + } + + if (tag->extensionFields.scopeKind != NULL && + tag->extensionFields.scopeName != NULL) + { + if (kind) + *kind = tag->extensionFields.scopeKind->name; + if (name) + *name = escapeName (tag, FIELD_SCOPE); + } +} + static int addExtensionFields (const tagEntryInfo *const tag) { boolean isKindKeyEnabled = isFieldEnabled (FIELD_KIND_KEY); @@ -958,30 +993,7 @@ static int addExtensionFields (const tagEntryInfo *const tag) { const char* k = NULL, *v = NULL; - if (tag->extensionFields.scopeKind == NULL - && tag->extensionFields.scopeName == NULL - && tag->extensionFields.scopeIndex != SCOPE_NIL - && TagFile.corkQueue.count > 0) - { - const tagEntryInfo * scope = NULL; - char *full_qualified_scope_name = NULL; - - scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex); - full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope); - Assert (full_qualified_scope_name); - - /* Make the information reusable to generate full qualified entry, and xformat output*/ - ((tagEntryInfo *const)tag)->extensionFields.scopeKind = scope->kind; - ((tagEntryInfo *const)tag)->extensionFields.scopeName = full_qualified_scope_name; - } - - if (tag->extensionFields.scopeKind != NULL && - tag->extensionFields.scopeName != NULL) - { - k = tag->extensionFields.scopeKind->name; - v = escapeName (tag, FIELD_SCOPE); - } - + getTagScopeInformation (((tagEntryInfo *const)tag), &k, &v); if (isFieldEnabled (FIELD_SCOPE) && k && v) length += mio_printf (TagFile.fp, scopeFmt, sep, scopeKey, k, v); } diff --git a/main/entry.h b/main/entry.h index f9618b1ec1..f5b68e0c79 100644 --- a/main/entry.h +++ b/main/entry.h @@ -135,6 +135,8 @@ extern void invalidatePatternCache(void); extern void tagFilePosition (MIOPos *p); extern void setTagFilePosition (MIOPos *p); extern const char* getTagFileDirectory (void); +extern void getTagScopeInformation (tagEntryInfo *const tag, + const char **kind, const char **name); /* Getting line associated with tag */ extern char *readLineFromBypassAnyway (vString *const vLine, const tagEntryInfo *const tag, From 64a937a11ec727fb88d9c81cd3752c7ce0593fc7 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 11 May 2016 15:05:34 +0900 Subject: [PATCH 08/12] main: implement a field for printing the kind of scope Signed-off-by: Masatake YAMATO --- Tmain/list-fields-with-prefix.d/stdout-expected.txt | 1 + Tmain/list-fields.d/stdout-expected.txt | 1 + main/field.c | 12 ++++++++++++ main/field.h | 3 ++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Tmain/list-fields-with-prefix.d/stdout-expected.txt b/Tmain/list-fields-with-prefix.d/stdout-expected.txt index 220b82351c..a610b01a9d 100644 --- a/Tmain/list-fields-with-prefix.d/stdout-expected.txt +++ b/Tmain/list-fields-with-prefix.d/stdout-expected.txt @@ -2,6 +2,7 @@ r UCTAGSrole off NONE TRUE Role Z UCTAGSscope off NONE FALSE Include the "scope:" key in scope field (use s) E UCTAGSextra off NONE TRUE Extra tag type information x UCTAGSxpath off NONE TRUE xpath for the tag +p UCTAGSscopeKind on NONE TRUE Kind of scope as full name - UCTAGSend off C TRUE end lines of various constructs - UCTAGSproperties off C TRUE properties (static, inline, mutable,...) - UCTAGSend off C++ TRUE end lines of various constructs diff --git a/Tmain/list-fields.d/stdout-expected.txt b/Tmain/list-fields.d/stdout-expected.txt index 736e2e776f..ea27bc739e 100644 --- a/Tmain/list-fields.d/stdout-expected.txt +++ b/Tmain/list-fields.d/stdout-expected.txt @@ -20,6 +20,7 @@ R NONE off NONE TRUE Marker (R or D) representing whether tag is definition or r Z scope off NONE FALSE Include the "scope:" key in scope field (use s) E extra off NONE TRUE Extra tag type information x xpath off NONE TRUE xpath for the tag +p scopeKind on NONE TRUE Kind of scope as full name - end off C TRUE end lines of various constructs - properties off C TRUE properties (static, inline, mutable,...) - end off C++ TRUE end lines of various constructs diff --git a/main/field.c b/main/field.c index a14875d29f..aa2c58bcff 100644 --- a/main/field.c +++ b/main/field.c @@ -54,6 +54,7 @@ static const char *renderFieldRole (const tagEntryInfo *const tag, const char *v static const char *renderFieldRefMarker (const tagEntryInfo *const tag, const char *value, vString* b); static const char *renderFieldExtra (const tagEntryInfo *const tag, const char *value, vString* b); static const char *renderFieldXpath (const tagEntryInfo *const tag, const char *value, vString* b); +static const char *renderFieldScopeKindName(const tagEntryInfo *const tag, const char *value, vString* b); #define DEFINE_FIELD_SPEC(L, N, V, H, F) \ { \ @@ -139,6 +140,9 @@ static fieldSpec fieldSpecsUniversal [] = { DEFINE_FIELD_SPEC ('x', "xpath", FALSE, "xpath for the tag", renderFieldXpath), + DEFINE_FIELD_SPEC ('p', "scopeKind", TRUE, + "Kind of scope as full name", + renderFieldScopeKindName), }; @@ -677,6 +681,14 @@ static const char *renderFieldXpath (const tagEntryInfo *const tag, return NULL; } +static const char *renderFieldScopeKindName(const tagEntryInfo *const tag, + const char *value, + vString* b) +{ + const kindOption *kind = tag->extensionFields.scopeKind; + + return renderAsIs (b, kind? kind->name: "-"); +} extern boolean isFieldEnabled (fieldType type) { diff --git a/main/field.h b/main/field.h index 950e4b9d95..3941c258b3 100644 --- a/main/field.h +++ b/main/field.h @@ -44,7 +44,8 @@ typedef enum eFieldType { /* extension field content control */ FIELD_SCOPE_KEY, FIELD_EXTRA, FIELD_XPATH, - FIELD_BUILTIN_LAST = FIELD_XPATH, + FIELD_SCOPE_KIND_LONG, + FIELD_BUILTIN_LAST = FIELD_SCOPE_KIND_LONG, } fieldType ; struct sFieldDesc; From 4d5ee6f7c6f6e9eeabecfb0073a1cc82233732ad Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 11 May 2016 15:42:41 +0900 Subject: [PATCH 09/12] main: allow render function returning NULL in --_xformat processing Signed-off-by: Masatake YAMATO --- main/fmt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/fmt.c b/main/fmt.c index e012d4f6a1..1db086a2e6 100644 --- a/main/fmt.c +++ b/main/fmt.c @@ -66,6 +66,9 @@ static int printTagField (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag) else str = renderFieldEscaped (ftype, tag, NO_PARSER_FIELD); + if (str == NULL) + str = ""; + if (width < 0) i = mio_printf (fp, "%-*s", -1 * width, str); else if (width > 0) From 261570995141f8beea29996c965d02124dab6f12 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 11 May 2016 15:52:42 +0900 Subject: [PATCH 10/12] main: call getTagScopeInformation in scope related renderers In the original code, scope related renderers access scope related fields of a given tag directly. Therefore they cannot reder scope information building on demand. In ths last commit I introduced a function for building the information in entry.c. The scope related renderers use it. Signed-off-by: Masatake YAMATO --- Tmain/list-fields.d/stdout-expected.txt | 2 +- main/entry.c | 6 ++++-- main/field.c | 12 ++++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Tmain/list-fields.d/stdout-expected.txt b/Tmain/list-fields.d/stdout-expected.txt index ea27bc739e..ed98ff3e6a 100644 --- a/Tmain/list-fields.d/stdout-expected.txt +++ b/Tmain/list-fields.d/stdout-expected.txt @@ -12,7 +12,7 @@ l language off NONE TRUE Language of input file containing tag m implementation off NONE TRUE Implementation information n line off NONE TRUE Line number of tag definition S signature off NONE TRUE Signature of routine (e.g. prototype or parameter list) -s NONE on NONE TRUE Scope of tag definition (WARNING: this doesn't work well as a format letter) +s NONE on NONE TRUE Scope of tag definition (`p' can be used for printing its kind) t typeref on NONE TRUE Type and name of a variable or typedef z kind off NONE FALSE Include the "kind:" key in kind field (use k or K) r role off NONE TRUE Role diff --git a/main/entry.c b/main/entry.c index f5275fec5d..022d7eb86a 100644 --- a/main/entry.c +++ b/main/entry.c @@ -936,7 +936,7 @@ extern void getTagScopeInformation (tagEntryInfo *const tag, if (kind) *kind = tag->extensionFields.scopeKind->name; if (name) - *name = escapeName (tag, FIELD_SCOPE); + *name = tag->extensionFields.scopeName; } } @@ -993,7 +993,9 @@ static int addExtensionFields (const tagEntryInfo *const tag) { const char* k = NULL, *v = NULL; - getTagScopeInformation (((tagEntryInfo *const)tag), &k, &v); + k = escapeName (tag, FIELD_SCOPE_KIND_LONG); + v = escapeName (tag, FIELD_SCOPE); + if (isFieldEnabled (FIELD_SCOPE) && k && v) length += mio_printf (TagFile.fp, scopeFmt, sep, scopeKey, k, v); } diff --git a/main/field.c b/main/field.c index aa2c58bcff..ceada8758e 100644 --- a/main/field.c +++ b/main/field.c @@ -114,7 +114,7 @@ static fieldSpec fieldSpecsExuberant [] = { "Signature of routine (e.g. prototype or parameter list)", renderFieldSignature), DEFINE_FIELD_SPEC ('s', NULL, TRUE, - "Scope of tag definition (WARNING: this doesn't work well as a format letter)", + "Scope of tag definition (`p' can be used for printing its kind)", renderFieldScope), DEFINE_FIELD_SPEC ('t', "typeref", TRUE, "Type and name of a variable or typedef", @@ -442,7 +442,10 @@ static const char *renderFieldSignature (const tagEntryInfo *const tag, const ch static const char *renderFieldScope (const tagEntryInfo *const tag, const char *value __unused__, vString* b) { - return renderEscapedName (WITH_DEFUALT_VALUE(tag->extensionFields.scopeName), tag, b); + const char* scope; + + getTagScopeInformation ((tagEntryInfo *const)tag, NULL, &scope); + return scope? renderEscapedName (scope, tag, b): NULL; } static const char *renderFieldInherits (const tagEntryInfo *const tag, const char *value __unused__, vString* b) @@ -685,9 +688,10 @@ static const char *renderFieldScopeKindName(const tagEntryInfo *const tag, const char *value, vString* b) { - const kindOption *kind = tag->extensionFields.scopeKind; + const char* kind; - return renderAsIs (b, kind? kind->name: "-"); + getTagScopeInformation ((tagEntryInfo *const)tag, &kind, NULL); + return kind? renderAsIs (b, kind): NULL; } extern boolean isFieldEnabled (fieldType type) From 1b4642e2ae77424e3c3cb5450cdbda332e0ba33e Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 12 May 2016 00:35:52 +0900 Subject: [PATCH 11/12] main: allow to use %{scope} in --_xformat Signed-off-by: Masatake YAMATO --- Tmain/list-fields-with-prefix.d/stdout-expected.txt | 2 +- Tmain/list-fields.d/stdout-expected.txt | 2 +- main/field.c | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Tmain/list-fields-with-prefix.d/stdout-expected.txt b/Tmain/list-fields-with-prefix.d/stdout-expected.txt index a610b01a9d..2a8c2d36e7 100644 --- a/Tmain/list-fields-with-prefix.d/stdout-expected.txt +++ b/Tmain/list-fields-with-prefix.d/stdout-expected.txt @@ -1,5 +1,5 @@ r UCTAGSrole off NONE TRUE Role -Z UCTAGSscope off NONE FALSE Include the "scope:" key in scope field (use s) +Z UCTAGSscope off NONE TRUE Include the "scope:" key in scope field (use s) in tags output, scope name in xref output E UCTAGSextra off NONE TRUE Extra tag type information x UCTAGSxpath off NONE TRUE xpath for the tag p UCTAGSscopeKind on NONE TRUE Kind of scope as full name diff --git a/Tmain/list-fields.d/stdout-expected.txt b/Tmain/list-fields.d/stdout-expected.txt index ed98ff3e6a..470e4e5c94 100644 --- a/Tmain/list-fields.d/stdout-expected.txt +++ b/Tmain/list-fields.d/stdout-expected.txt @@ -17,7 +17,7 @@ t typeref on NONE TRUE Type and name of a variable or typedef z kind off NONE FALSE Include the "kind:" key in kind field (use k or K) r role off NONE TRUE Role R NONE off NONE TRUE Marker (R or D) representing whether tag is definition or reference -Z scope off NONE FALSE Include the "scope:" key in scope field (use s) +Z scope off NONE TRUE Include the "scope:" key in scope field (use s) in tags output, scope name in xref output E extra off NONE TRUE Extra tag type information x xpath off NONE TRUE xpath for the tag p scopeKind on NONE TRUE Kind of scope as full name diff --git a/main/field.c b/main/field.c index ceada8758e..5c978760a5 100644 --- a/main/field.c +++ b/main/field.c @@ -132,8 +132,10 @@ static fieldSpec fieldSpecsUniversal [] = { "Marker (R or D) representing whether tag is definition or reference", renderFieldRefMarker), DEFINE_FIELD_SPEC ('Z', "scope", FALSE, - "Include the \"scope:\" key in scope field (use s)", - NULL), + "Include the \"scope:\" key in scope field (use s) in tags output, scope name in xref output", + /* Following renderer is for handling --_xformat=%{scope}; + and is not for tags output. */ + renderFieldScope), DEFINE_FIELD_SPEC ('E', "extra", FALSE, "Extra tag type information", renderFieldExtra), From 70a63d165d07012842f0fa42855c797cafd55fa9 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 12 May 2016 00:28:29 +0900 Subject: [PATCH 12/12] Units: add a case for testing automatic FQ generation Signed-off-by: Masatake YAMATO --- Units/{ => parser-dts.r}/dts-core-dump.d/input.dts | 0 Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/README | 0 Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/args.ctags | 0 .../{ => parser-dts.r}/dts-fq-without-scope-field.d/expected.tags | 0 Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/input.dts | 0 Units/{ => parser-dts.r}/dts-simple.d/args.ctags | 0 Units/{ => parser-dts.r}/dts-simple.d/expected.tags | 0 Units/{ => parser-dts.r}/dts-simple.d/input.dts | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename Units/{ => parser-dts.r}/dts-core-dump.d/input.dts (100%) rename Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/README (100%) rename Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/args.ctags (100%) rename Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/expected.tags (100%) rename Units/{ => parser-dts.r}/dts-fq-without-scope-field.d/input.dts (100%) rename Units/{ => parser-dts.r}/dts-simple.d/args.ctags (100%) rename Units/{ => parser-dts.r}/dts-simple.d/expected.tags (100%) rename Units/{ => parser-dts.r}/dts-simple.d/input.dts (100%) diff --git a/Units/dts-core-dump.d/input.dts b/Units/parser-dts.r/dts-core-dump.d/input.dts similarity index 100% rename from Units/dts-core-dump.d/input.dts rename to Units/parser-dts.r/dts-core-dump.d/input.dts diff --git a/Units/dts-fq-without-scope-field.d/README b/Units/parser-dts.r/dts-fq-without-scope-field.d/README similarity index 100% rename from Units/dts-fq-without-scope-field.d/README rename to Units/parser-dts.r/dts-fq-without-scope-field.d/README diff --git a/Units/dts-fq-without-scope-field.d/args.ctags b/Units/parser-dts.r/dts-fq-without-scope-field.d/args.ctags similarity index 100% rename from Units/dts-fq-without-scope-field.d/args.ctags rename to Units/parser-dts.r/dts-fq-without-scope-field.d/args.ctags diff --git a/Units/dts-fq-without-scope-field.d/expected.tags b/Units/parser-dts.r/dts-fq-without-scope-field.d/expected.tags similarity index 100% rename from Units/dts-fq-without-scope-field.d/expected.tags rename to Units/parser-dts.r/dts-fq-without-scope-field.d/expected.tags diff --git a/Units/dts-fq-without-scope-field.d/input.dts b/Units/parser-dts.r/dts-fq-without-scope-field.d/input.dts similarity index 100% rename from Units/dts-fq-without-scope-field.d/input.dts rename to Units/parser-dts.r/dts-fq-without-scope-field.d/input.dts diff --git a/Units/dts-simple.d/args.ctags b/Units/parser-dts.r/dts-simple.d/args.ctags similarity index 100% rename from Units/dts-simple.d/args.ctags rename to Units/parser-dts.r/dts-simple.d/args.ctags diff --git a/Units/dts-simple.d/expected.tags b/Units/parser-dts.r/dts-simple.d/expected.tags similarity index 100% rename from Units/dts-simple.d/expected.tags rename to Units/parser-dts.r/dts-simple.d/expected.tags diff --git a/Units/dts-simple.d/input.dts b/Units/parser-dts.r/dts-simple.d/input.dts similarity index 100% rename from Units/dts-simple.d/input.dts rename to Units/parser-dts.r/dts-simple.d/input.dts