From a6c24e9c1a78da2ae9a5d5e6a110f26da40ac143 Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Thu, 7 May 2020 09:21:23 +1000 Subject: lsearch, switch: fix -regexp case with option-like pattern If the pattern begins with -, the internal invocation of regexp will treat the pattern as an option. Fix this by adding -- to the internal invocation of regexp. Fixes #154 Reported-by: Barry Arthur Signed-off-by: Steve Bennett --- jim.c | 35 +++++++++++++++++++++++------------ jim.h | 1 + tests/jim.test | 9 +++++++++ tests/lsearch.test | 8 ++++++++ 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/jim.c b/jim.c index bbdb6fe..08c448b 100644 --- a/jim.c +++ b/jim.c @@ -12028,19 +12028,24 @@ static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } -/* Returns 1 if match, 0 if no match or - on error (e.g. -JIM_ERR, -JIM_BREAK)*/ +/* Returns 1 if match, 0 if no match or - on error (e.g. -JIM_ERR, -JIM_BREAK) + * flags may contain JIM_NOCASE and/or JIM_OPT_END + */ int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj, - Jim_Obj *stringObj, int nocase) + Jim_Obj *stringObj, int flags) { - Jim_Obj *parms[4]; + Jim_Obj *parms[5]; int argc = 0; long eq; int rc; parms[argc++] = commandObj; - if (nocase) { + if (flags & JIM_NOCASE) { parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1); } + if (flags & JIM_OPT_END) { + parms[argc++] = Jim_NewStringObj(interp, "--", -1); + } parms[argc++] = patternObj; parms[argc++] = stringObj; @@ -12058,6 +12063,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a { enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; + int match_flags = 0; Jim_Obj *command = NULL, *scriptObj = NULL, *strObj; Jim_Obj **caseList; @@ -12080,8 +12086,10 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a matchOpt = SWITCH_EXACT; else if (strncmp(option, "-glob", 2) == 0) matchOpt = SWITCH_GLOB; - else if (strncmp(option, "-regexp", 2) == 0) + else if (strncmp(option, "-regexp", 2) == 0) { matchOpt = SWITCH_RE; + match_flags |= JIM_OPT_END; + } else if (strncmp(option, "-command", 2) == 0) { matchOpt = SWITCH_CMD; if ((argc - opt) < 2) @@ -12124,7 +12132,7 @@ static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a command = Jim_NewStringObj(interp, "regexp", -1); /* Fall thru intentionally */ case SWITCH_CMD:{ - int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); + int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, match_flags); /* After the execution of a command we need to * make sure to reconvert the object into a list @@ -12227,7 +12235,6 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const * int i; int opt_bool = 0; int opt_not = 0; - int opt_nocase = 0; int opt_all = 0; int opt_inline = 0; int opt_match = OPT_EXACT; @@ -12235,6 +12242,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const * int rc = JIM_OK; Jim_Obj *listObjPtr = NULL; Jim_Obj *commandObj = NULL; + int match_flags = 0; if (argc < 3) { wrongargs: @@ -12258,7 +12266,7 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const * opt_not = 1; break; case OPT_NOCASE: - opt_nocase = 1; + match_flags |= JIM_NOCASE; break; case OPT_INLINE: opt_inline = 1; @@ -12267,6 +12275,10 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const * case OPT_ALL: opt_all = 1; break; + case OPT_REGEXP: + opt_match = option; + match_flags |= JIM_OPT_END; + break; case OPT_COMMAND: if (i >= argc - 2) { goto wrongargs; @@ -12275,7 +12287,6 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const * /* fallthru */ case OPT_EXACT: case OPT_GLOB: - case OPT_REGEXP: opt_match = option; break; } @@ -12300,16 +12311,16 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const * switch (opt_match) { case OPT_EXACT: - eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; + eq = Jim_StringCompareObj(interp, argv[1], objPtr, match_flags) == 0; break; case OPT_GLOB: - eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase); + eq = Jim_StringMatchObj(interp, argv[1], objPtr, match_flags); break; case OPT_REGEXP: case OPT_COMMAND: - eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase); + eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, match_flags); if (eq < 0) { if (listObjPtr) { Jim_FreeNewObj(interp, listObjPtr); diff --git a/jim.h b/jim.h index f156980..807ad9b 100644 --- a/jim.h +++ b/jim.h @@ -161,6 +161,7 @@ extern "C" { /* Flags used by API calls getting a 'nocase' argument. */ #define JIM_CASESENS 0 /* case sensitive */ #define JIM_NOCASE 1 /* no case */ +#define JIM_OPT_END 2 /* if implemented by a command (e.g. regexp), add -- to the argument list */ /* Filesystem related */ #define JIM_PATH_LEN 1024 diff --git a/tests/jim.test b/tests/jim.test index 121e909..eaef8aa 100644 --- a/tests/jim.test +++ b/tests/jim.test @@ -2500,6 +2500,15 @@ test switch-3.7 {-exact vs. -glob vs. -regexp} { list [catch {switch -foo a b c} msg] $msg } {1 {bad option "-foo": must be -exact, -glob, -regexp, -command procname or --}} +test switch-3.8 {switch -regexp with option-like pattern} regexp { + switch -regexp -- -def { + -abc {concat first} + -def {concat second} + -ghi {concat third} + default {concat none} + } +} second + test switch-4.1 {error in executed command} { list [catch {switch a a {error "Just a test"} default {expr 1}} msg] \ $msg diff --git a/tests/lsearch.test b/tests/lsearch.test index 1eb6607..ff1342a 100644 --- a/tests/lsearch.test +++ b/tests/lsearch.test @@ -72,6 +72,14 @@ test lsearch-2.9 {search modes, -nocase} { lsearch -nocase -glob {b.x ^bc xy bcx} B* } 0 +test lsearch-2.10 {regexp with option-looking pattern} regexp { + lsearch -regexp {-abc -def -ghi} -def +} 1 + +test lsearch-2.11 {regexp with option-looking pattern, -nocase} regexp { + lsearch -nocase -regexp {-abc -def -ghi} -DEF +} 1 + test lsearch-3.1 {lsearch errors} { list [catch lsearch msg] } {1} -- cgit v1.1