diff --git a/Units/option-makeTagEntryReflection.d/args.ctags b/Units/option-makeTagEntryReflection.d/args.ctags new file mode 100644 index 0000000000..6eacc2a14e --- /dev/null +++ b/Units/option-makeTagEntryReflection.d/args.ctags @@ -0,0 +1,79 @@ +# See #3020 and #3027. + +--sort=no +--extras=+q + +--_extradef-Markdown=withfname,appending input filename +--extras-Markdown=+{withfname} + +--_prelude-Markdown={{ + % You can customize the string combining the original name + % and the basen name of input file. + /SEP (@) def + + % dict + /scope-remapping-table 31 dict def + + % (abc/input.d) dropext => (abc/input) + % (abc.d/input) dropext => (abc.d/input) + /dropext { + (/.) _strrpbrk { + % string offset + 2 copy get ?/ eq { + pop + } { + 0 exch 0 string _copyinterval + } ifelse + } if + } def + + % (abc/efg) basename => (efg) + /basename { + ?/ _strrchr { + 1 add dup 2 index length exch sub + 0 string _copyinterval + } if + } def +}} + +--_sequel-Markdown={{ + % Fill the scope field of withfname extra tags. + scope-remapping-table { + % Make the original tag invisible + exch dup _markplaceholder + :scope dup + % withfname-index:int original-scope:int original-scope:int + 0 eq { + pop pop + } { + % withfname-index:int original-scope:int + scope-remapping-table exch get + % withfname-index:int withfname-scope:int + scope: + } ifelse + } forall +}} + +--_makeTagEntryReflection-Markdown={{ + /Markdown.withfname _extraenabled { + . :extras { + /Markdown.withfname _amember not + } { + true + } ifelse + { + mark + . :name + SEP + . :input dropext basename + _buildstring + + . :kind + . _tagloc _tag dup /Markdown.withfname _markextra + _commit + % Record the pair of original-index:int and withfname-index:int. + scope-remapping-table . 3 -1 roll put + } if + + } if +}} diff --git a/Units/option-makeTagEntryReflection.d/expected.tags b/Units/option-makeTagEntryReflection.d/expected.tags new file mode 100644 index 0000000000..4fe40c6dcf --- /dev/null +++ b/Units/option-makeTagEntryReflection.d/expected.tags @@ -0,0 +1,7 @@ +ABC@input input.md /^# ABC$/;" c +DEF@input input.md /^## DEF$/;" s chapter:ABC@input +GHI@input input.md /^### GHI$/;" S section:ABC@input""DEF@input +HIJ@input input.md /^### HIJ$/;" S section:ABC@input""DEF@input +KLM@input input.md /^## KLM$/;" s chapter:ABC@input +OPQ@input input.md /^# OPQ$/;" c +RST@input input.md /^### RST$/;" S chapter:OPQ@input diff --git a/Units/option-makeTagEntryReflection.d/input.md b/Units/option-makeTagEntryReflection.d/input.md new file mode 100644 index 0000000000..9e796c61e6 --- /dev/null +++ b/Units/option-makeTagEntryReflection.d/input.md @@ -0,0 +1,13 @@ +# ABC + +## DEF + +### GHI + +### HIJ + +## KLM + +# OPQ + +### RST diff --git a/main/dependency.c b/main/dependency.c index ecb5a9e60c..5020090075 100644 --- a/main/dependency.c +++ b/main/dependency.c @@ -14,6 +14,7 @@ #include "debug.h" #include "dependency.h" +#include "entry.h" #include "options.h" #include "parse_p.h" #include "read.h" @@ -184,14 +185,18 @@ extern void notifyMakeTagEntry (const tagEntryInfo *tag, int corkIndex) { subparser *s; + /* running optscript code attaching to --makeTagEntryReflection- */ + langType lang = tag->langType; + notifyLanguageRegexMakeTagEntry (lang, corkIndex); + foreachSubparser(s, false) { + enterSubparser(s); if (s->makeTagEntryNotify) - { - enterSubparser(s); s->makeTagEntryNotify (s, tag, corkIndex); - leaveSubparser(); - } + /* propagate the event recursively */ + notifyMakeTagEntry (tag, corkIndex); + leaveSubparser(); } } diff --git a/main/dependency.h b/main/dependency.h index bdeb71ab92..a485fb152a 100644 --- a/main/dependency.h +++ b/main/dependency.h @@ -43,4 +43,9 @@ struct sSlaveParser { slaveParser *next; }; +/* These are for CPreProcessor. + * Don't use in the other parsers. */ +extern void notifyInputStart (void); +extern void notifyInputEnd (void); + #endif /* CTAGS_MAIN_DEPENDENCY_H */ diff --git a/main/lregex.c b/main/lregex.c index 2d6c84f509..015c9c681f 100644 --- a/main/lregex.c +++ b/main/lregex.c @@ -2249,6 +2249,17 @@ extern void notifyRegexInputEnd (struct lregexControlBlock *lcb) fillEndLineFieldOfUpperScopes (lcb, endline); } +extern void notifyRegexMakeTagEntry (struct lregexControlBlock *lcb, + int corkIndex) +{ + if (ptrArrayCount (lcb->hook[SCRIPT_HOOK_MAKE_TAG_ENTRY_REFLECTION]) > 0) + { + optscriptSetup (optvm, lcb->local_dict, corkIndex); + scriptEvalHook (optvm, lcb, SCRIPT_HOOK_MAKE_TAG_ENTRY_REFLECTION); + optscriptTeardown (optvm, lcb->local_dict); + } +} + extern void findRegexTagsMainloop (int (* driver)(void)) { /* merely read all lines of the file */ diff --git a/main/lregex_p.h b/main/lregex_p.h index 103944f2f1..d90f2191ca 100644 --- a/main/lregex_p.h +++ b/main/lregex_p.h @@ -107,6 +107,7 @@ extern bool matchMultitableRegex (struct lregexControlBlock *lcb, const vString* extern void notifyRegexInputStart (struct lregexControlBlock *lcb); extern void notifyRegexInputEnd (struct lregexControlBlock *lcb); +extern void notifyRegexMakeTagEntry (struct lregexControlBlock *lcb, int corkIndex); extern void addRegexTable (struct lregexControlBlock *lcb, const char *name); extern void extendRegexTable (struct lregexControlBlock *lcb, const char *src, const char *dist); diff --git a/main/options.c b/main/options.c index 7888250dd7..4173448b85 100644 --- a/main/options.c +++ b/main/options.c @@ -378,6 +378,8 @@ static optionDescription LongOptionDescription [] = { {1,1," Define new extra for . --extras-=+{name} enables it."}, {1,1," --_fielddef-=,"}, {1,1," Define new field for ."}, + {1,1," --_makeTagEntryReflection-={{ optscript-code }}"}, + {1,1," Specify code run when parser makes a tag."}, {1,1," --_mtable-extend-=disttable+srctable."}, {1,1," Copy patterns of a regex table to another regex table."}, {1,1," --_mtable-regex-=///[]"}, @@ -3363,6 +3365,8 @@ static void processLongOption ( ; else if (processSequelOption (option, parameter)) ; + else if (processMakeTagEntryReflectionOption (option, parameter)) + ; else if (processPretendOption (option, parameter)) ; else if (processRolesOption (option, parameter)) diff --git a/main/options_p.h b/main/options_p.h index b8ada160bc..46665063b6 100644 --- a/main/options_p.h +++ b/main/options_p.h @@ -177,6 +177,7 @@ extern bool processRoledefOption (const char *const option, const char *const pa extern bool processScopesepOption (const char *const option, const char *const parameter); extern bool processPreludeOption (const char *const option, const char *const parameter); extern bool processSequelOption (const char *const option, const char *const parameter); +extern bool processMakeTagEntryReflectionOption (const char *const option, const char *const parameter); extern bool processPretendOption (const char *const option, const char *const parameter); extern bool processRolesOption (const char *const option, const char *const parameter); diff --git a/main/parse.c b/main/parse.c index eb3becae64..c12b21cae9 100644 --- a/main/parse.c +++ b/main/parse.c @@ -4110,6 +4110,11 @@ extern void notifyLanguageRegexInputEnd (langType language) notifyRegexInputEnd(pobj->lregexControlBlock); } +extern void notifyLanguageRegexMakeTagEntry (langType language, int corkIndex) +{ + notifyRegexMakeTagEntry((LanguageTable + language)->lregexControlBlock, corkIndex); +} + static unsigned int parserCorkFlags (parserDefinition *parser) { subparser *tmp; @@ -5418,6 +5423,11 @@ extern bool processSequelOption (const char *const option, const char *const par return processHookOption (option, parameter, "_sequel-", SCRIPT_HOOK_SEQUEL); } +extern bool processMakeTagEntryReflectionOption (const char *const option, const char *const parameter) +{ + return processHookOption (option, parameter, "_makeTagEntryReflection-", SCRIPT_HOOK_MAKE_TAG_ENTRY_REFLECTION); +} + extern bool processPretendOption (const char *const option, const char *const parameter) { langType new_language, old_language; diff --git a/main/parse.h b/main/parse.h index 6f3051b619..ea8d12315c 100644 --- a/main/parse.h +++ b/main/parse.h @@ -74,6 +74,7 @@ typedef enum { enum scriptHook { SCRIPT_HOOK_PRELUDE, SCRIPT_HOOK_SEQUEL, + SCRIPT_HOOK_MAKE_TAG_ENTRY_REFLECTION, SCRIPT_HOOK_MAX, }; diff --git a/main/parse_p.h b/main/parse_p.h index b841cce41b..2b7e734d72 100644 --- a/main/parse_p.h +++ b/main/parse_p.h @@ -152,6 +152,7 @@ extern bool doesLanguageHaveForeignDependency (const langType language, const la extern bool processLanguageRegexOption (langType language, enum regexParserType regptype, const char *const parameter); extern void notifyLanguageRegexInputStart (langType language); extern void notifyLanguageRegexInputEnd (langType language); +extern void notifyLanguageRegexMakeTagEntry (langType language, int corkIndex); extern bool hasLanguagePostRunRegexPatterns (const langType language); extern void matchLanguageRegex (const langType language, const vString* const line, bool postrun); diff --git a/main/subparser_p.h b/main/subparser_p.h index 375c6de188..6d23e3f861 100644 --- a/main/subparser_p.h +++ b/main/subparser_p.h @@ -28,8 +28,6 @@ extern subparser *getFirstSubparser(struct slaveControlBlock *controlBlock); /* A base parser doesn't have to call the following three functions. The main part calls them internally. */ -extern void notifyInputStart (void); -extern void notifyInputEnd (void); extern void notifyMakeTagEntry (const tagEntryInfo *info, int corkIndex); extern void setupSubparsersInUse (struct slaveControlBlock *controlBlock); diff --git a/parsers/cpreprocessor.c b/parsers/cpreprocessor.c index b60c191e57..b3a653836b 100644 --- a/parsers/cpreprocessor.c +++ b/parsers/cpreprocessor.c @@ -16,6 +16,7 @@ #include #include "debug.h" +#include "dependency.h" /* notifyInputStart, notifyInputEnd */ #include "entry.h" #include "htable.h" #include "x-cpreprocessor.h" @@ -392,6 +393,14 @@ static void cppInitCommon(langType clientLang, : clientLang) & CORK_SYMTAB)) ? makeMacroTable () : NULL; + + if (Cpp.lang != Cpp.clientLang + && Cpp.clientLang != LANG_IGNORE) + { + pushLanguage (Cpp.lang); + notifyInputStart (); + popLanguage (); + } } extern void cppInit (const bool state, const bool hasAtLiteralStrings, @@ -427,6 +436,14 @@ static void cppClearMacroInUse (cppMacroInfo **pM) extern void cppTerminate (void) { + if (Cpp.lang != Cpp.clientLang + && Cpp.clientLang != LANG_IGNORE) + { + pushLanguage (Cpp.lang); + notifyInputEnd (); + popLanguage (); + } + if (Cpp.directive.name != NULL) { vStringDelete (Cpp.directive.name);