diff options
author | Steve Bennett <steveb@workware.net.au> | 2023-06-22 13:55:33 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2023-07-04 10:08:32 +1000 |
commit | b4401224612367bba465d15e1f940fcf00173142 (patch) | |
tree | 3e7733e130c06462c2c1fe46672a88f370d714a6 | |
parent | 8edfa0eee24e0477d20fa25f0ee2f2f50ffa15ab (diff) | |
download | jimtcl-b4401224612367bba465d15e1f940fcf00173142.zip jimtcl-b4401224612367bba465d15e1f940fcf00173142.tar.gz jimtcl-b4401224612367bba465d15e1f940fcf00173142.tar.bz2 |
subcmd: minor improvements
Add support for modulo maxarg count. If maxargs is (e.g.) -2, then a
multiple of 2 args is expected.
Also expose Jim_SubCmdArgError() to make it easy to add additional
arg validation but still have subcmd report the usage.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | jim-subcmd.c | 20 | ||||
-rw-r--r-- | jim-subcmd.h | 12 |
2 files changed, 28 insertions, 4 deletions
diff --git a/jim-subcmd.c b/jim-subcmd.c index 2063704..8a946ce 100644 --- a/jim-subcmd.c +++ b/jim-subcmd.c @@ -82,10 +82,10 @@ static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Ob } } -static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd) +void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *subcmd) { Jim_SetResultString(interp, "wrong # args: should be \"", -1); - add_cmd_usage(interp, command_table, subcmd); + add_cmd_usage(interp, ct, subcmd); Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); } @@ -110,6 +110,7 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type Jim_Obj *cmd; const char *cmdstr; int help = 0; + int argsok = 1; if (argc < 2) { Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n" @@ -200,7 +201,18 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type found: /* Check the number of args */ - if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { + + if (argc - 2 < ct->minargs) { + argsok = 0; + } + else if (ct->maxargs >= 0 && argc - 2 > ct->maxargs) { + argsok = 0; + } + else if (ct->maxargs < -1 && (argc - 2) % -ct->maxargs != 0) { + /* -2 means must have n * 2 args */ + argsok = 0; + } + if (!argsok) { Jim_SetResultString(interp, "wrong # args: should be \"", -1); /* subcmd */ add_cmd_usage(interp, ct, argv[0]); @@ -225,7 +237,7 @@ int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim ret = ct->function(interp, argc - 2, argv + 2); } if (ret < 0) { - set_wrong_args(interp, ct, argv[0]); + Jim_SubCmdArgError(interp, ct, argv[0]); ret = JIM_ERR; } } diff --git a/jim-subcmd.h b/jim-subcmd.h index ab30f37..2d05821 100644 --- a/jim-subcmd.h +++ b/jim-subcmd.h @@ -31,6 +31,11 @@ typedef struct { unsigned short flags; /* JIM_MODFLAG_... plus custom flags */ } jim_subcmd_type; +/* This makes it easy to define a jim_subcmd_type array with function=NULL + * see jim-namespace.c for an example + */ +#define JIM_DEF_SUBCMD(name, args, minargs, maxargs) { name, args, NULL, minargs, maxargs } + /** * Looks up the appropriate subcommand in the given command table and return * the command function which implements the subcommand. @@ -70,6 +75,13 @@ int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); */ int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv); +/** + * Sets an error result indicating the usage of the subcmd 'ct'. + * Typically this will be called with the result of Jim_ParseSubCmd() after + * additional checks if the args are wrong. + */ +void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type *ct, Jim_Obj *subcmd); + #ifdef __cplusplus } #endif |