From 3bd62a18871ecebb89b66e2c947cc3a2616f1be6 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 23 Nov 2022 03:40:10 +0900 Subject: [PATCH 1/3] Sh: update the kind description for "heredoc" Signed-off-by: Masatake YAMATO --- Tmain/ptag-in-optlib-parser.d/stdout-expected.txt | 2 +- parsers/sh.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt b/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt index 41719bce88..915d9ed69a 100644 --- a/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt +++ b/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt @@ -8,7 +8,7 @@ !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ !_TAG_KIND_DESCRIPTION!Sh a,alias /aliases/ !_TAG_KIND_DESCRIPTION!Sh f,function /functions/ -!_TAG_KIND_DESCRIPTION!Sh h,heredoc /label for here document/ +!_TAG_KIND_DESCRIPTION!Sh h,heredoc /labels for here document/ !_TAG_KIND_DESCRIPTION!Sh s,script /script files/ !_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ !_TAG_OUTPUT_FILESEP slash /slash or backslash/ diff --git a/parsers/sh.c b/parsers/sh.c index df25ad9673..abec1b3df2 100644 --- a/parsers/sh.c +++ b/parsers/sh.c @@ -86,7 +86,7 @@ static roleDefinition ZshFunctionRoles [] = { .referenceOnly = false, FUNCTION_ROLES_SPEC }, \ { true, 's', "script", "script files", \ .referenceOnly = true, ATTACH_ROLES (SCRIPT_ROLES) }, \ - { true, 'h', "heredoc", "label for here document", \ + { true, 'h', "heredoc", "labels for here document", \ .referenceOnly = false, ATTACH_ROLES (HEREDOC_ROLES) } static kindDefinition ShKinds [] = { From ff7e88ee99b9e7d5d8562ff9e0778fa98ab3a494 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 23 Nov 2022 03:46:06 +0900 Subject: [PATCH 2/3] [EXPERIMENTAL] Sh: extract variables in variable assignments Signed-off-by: Masatake YAMATO --- Units/parser-sh.r/sh-comments.d/expected.tags | 4 ++ Units/parser-sh.r/sh-quotes.d/expected.tags | 5 +++ parsers/sh.c | 39 +++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/Units/parser-sh.r/sh-comments.d/expected.tags b/Units/parser-sh.r/sh-comments.d/expected.tags index 0cb132b138..48532f69de 100644 --- a/Units/parser-sh.r/sh-comments.d/expected.tags +++ b/Units/parser-sh.r/sh-comments.d/expected.tags @@ -2,3 +2,7 @@ afterpound1 input.sh /^foo="#"; afterpound1() {}$/;" f afterpound2 input.sh /^foo="#\\""; afterpound2() {}$/;" f afterpound3 input.sh /^foo='#'; afterpound3() {}$/;" f afterpound4 input.sh /^foo='#'''; afterpound4() {}$/;" f +foo input.sh /^foo="#"; afterpound1() {}$/;" v +foo input.sh /^foo="#\\""; afterpound2() {}$/;" v +foo input.sh /^foo='#'''; afterpound4() {}$/;" v +foo input.sh /^foo='#'; afterpound3() {}$/;" v diff --git a/Units/parser-sh.r/sh-quotes.d/expected.tags b/Units/parser-sh.r/sh-quotes.d/expected.tags index 0cb132b138..1c71b53595 100644 --- a/Units/parser-sh.r/sh-quotes.d/expected.tags +++ b/Units/parser-sh.r/sh-quotes.d/expected.tags @@ -2,3 +2,8 @@ afterpound1 input.sh /^foo="#"; afterpound1() {}$/;" f afterpound2 input.sh /^foo="#\\""; afterpound2() {}$/;" f afterpound3 input.sh /^foo='#'; afterpound3() {}$/;" f afterpound4 input.sh /^foo='#'''; afterpound4() {}$/;" f +foo input.sh /^foo="#"; afterpound1() {}$/;" v +foo input.sh /^foo="#\\""; afterpound2() {}$/;" v +foo input.sh /^foo="nofunction()"$/;" v +foo input.sh /^foo='#'''; afterpound4() {}$/;" v +foo input.sh /^foo='#'; afterpound3() {}$/;" v diff --git a/parsers/sh.c b/parsers/sh.c index abec1b3df2..792f4d1f31 100644 --- a/parsers/sh.c +++ b/parsers/sh.c @@ -38,6 +38,7 @@ typedef enum { K_FUNCTION, K_SCRIPT, K_HEREDOCLABEL, + K_VARIABLE, } shKind; typedef enum { @@ -87,7 +88,9 @@ static roleDefinition ZshFunctionRoles [] = { { true, 's', "script", "script files", \ .referenceOnly = true, ATTACH_ROLES (SCRIPT_ROLES) }, \ { true, 'h', "heredoc", "labels for here document", \ - .referenceOnly = false, ATTACH_ROLES (HEREDOC_ROLES) } + .referenceOnly = false, ATTACH_ROLES (HEREDOC_ROLES) }, \ + { true, 'v', "variable", "variables assigment (experimental)" } + static kindDefinition ShKinds [] = { SH_KINDS_COMMON(ShScriptRoles, ShHeredocRoles,), @@ -456,6 +459,32 @@ static size_t handleZshKeyword (int keyword, return vStringLength(token); } +static bool handleVariableAssignment (vString *input) +{ + const char *base = vStringValue (input); + const char *cp = base; + + while (*cp != '\0') + { + if (*cp == '=') + { + size_t len = cp - base; + if (len > 0) + { + vStringTruncate (input, len); + return true; + } + break; + } + else if ( ((cp == base)? + isIdentChar0: isIdentChar) ((unsigned char)*cp) ) + cp++; + else + break; + } + return false; +} + typedef bool (* checkCharFunc) (int); static void findShTagsCommon (size_t (* keyword_handler) (int, vString *, @@ -653,8 +682,9 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, while (isspace ((int) *cp)) ++cp; - if ((found_kind != K_SCRIPT) - && *cp == '(') + if (found_kind == K_SCRIPT) + ; /* Do NOTHING */ + else if (*cp == '(') { ++cp; while (isspace ((int) *cp)) @@ -680,6 +710,9 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, ++cp; } } + else if (found_kind == K_NOTHING + && handleVariableAssignment (name)) + found_kind = K_VARIABLE; if (found_kind != K_NOTHING) { From 5fede00bc140234fbbbc38c78b026feed0a59158 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 23 Nov 2022 04:47:20 +0900 Subject: [PATCH 3/3] Sh: make the way to extract variables more robust Signed-off-by: Masatake YAMATO --- .../stdout-expected.txt | 1 + parsers/sh.c | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt b/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt index 915d9ed69a..932f3c16b3 100644 --- a/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt +++ b/Tmain/ptag-in-optlib-parser.d/stdout-expected.txt @@ -10,6 +10,7 @@ !_TAG_KIND_DESCRIPTION!Sh f,function /functions/ !_TAG_KIND_DESCRIPTION!Sh h,heredoc /labels for here document/ !_TAG_KIND_DESCRIPTION!Sh s,script /script files/ +!_TAG_KIND_DESCRIPTION!Sh v,variable /variables assigment (experimental)/ !_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ !_TAG_OUTPUT_FILESEP slash /slash or backslash/ !_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ diff --git a/parsers/sh.c b/parsers/sh.c index 792f4d1f31..d8c4634ebf 100644 --- a/parsers/sh.c +++ b/parsers/sh.c @@ -459,6 +459,27 @@ static size_t handleZshKeyword (int keyword, return vStringLength(token); } +static bool doesLineCotinue(const unsigned char *start, const unsigned char *cp) +{ + cp--; + if (start >= cp) + return false; + + if (*cp != '\\') + return false; + + while (start < cp) + { + if (*cp == ';' || *cp == '|' || *cp == '&') + return false; + else if (isspace(*cp)) + cp--; + else + return true; + } + return false; +} + static bool handleVariableAssignment (vString *input) { const char *base = vStringValue (input); @@ -503,6 +524,7 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, struct hereDocParsingState hstate; hdocStateInit (&hstate); + bool cont_line = false; while ((line = readLineFromInputFile ()) != NULL) { const unsigned char* cp = line; @@ -528,10 +550,12 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, vStringDelete (hereDocDelimiter); hereDocDelimiter = NULL; } + cont_line = false; continue; } hdocStateClear (&hstate); + bool beginning_of_line = !cont_line; while (*cp != '\0') { subparser *sub = NULL; @@ -669,6 +693,7 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, cp += d; else if (*cp != '\0') ++cp; + beginning_of_line = false; continue; } @@ -710,7 +735,8 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, ++cp; } } - else if (found_kind == K_NOTHING + else if (beginning_of_line + && found_kind == K_NOTHING && handleVariableAssignment (name)) found_kind = K_VARIABLE; @@ -729,7 +755,11 @@ static void findShTagsCommon (size_t (* keyword_handler) (int, else if (!hereDocDelimiter) hdocStateUpdateArgs (&hstate, name); vStringClear (name); + beginning_of_line = false; } + if (*cp == '#') + cont_line = false; + cont_line = doesLineCotinue (line, cp); } hdocStateFini (&hstate); vStringDelete (name);