aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2023-06-22 13:55:33 +1000
committerSteve Bennett <steveb@workware.net.au>2023-07-04 10:08:32 +1000
commitb4401224612367bba465d15e1f940fcf00173142 (patch)
tree3e7733e130c06462c2c1fe46672a88f370d714a6
parent8edfa0eee24e0477d20fa25f0ee2f2f50ffa15ab (diff)
downloadjimtcl-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.c20
-rw-r--r--jim-subcmd.h12
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