4 #include "jim-subcmd.h"
5 #include "jimautoconf.h"
8 * Implements the common 'commands' subcommand
10 static int subcmd_null(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
12 /* Nothing to do, since the result has already been created */
17 * Do-nothing command to support -commands and -usage
19 static const jim_subcmd_type dummy_subcmd
= {
20 "dummy", NULL
, subcmd_null
, 0, 0, JIM_MODFLAG_HIDDEN
23 static void add_commands(Jim_Interp
*interp
, const jim_subcmd_type
* ct
, const char *sep
)
27 for (; ct
->cmd
; ct
++) {
28 if (!(ct
->flags
& JIM_MODFLAG_HIDDEN
)) {
29 Jim_AppendStrings(interp
, Jim_GetResult(interp
), s
, ct
->cmd
, NULL
);
35 static void bad_subcmd(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
, const char *type
,
36 Jim_Obj
*cmd
, Jim_Obj
*subcmd
)
38 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
39 Jim_AppendStrings(interp
, Jim_GetResult(interp
), Jim_String(cmd
), ", ", type
,
40 " command \"", Jim_String(subcmd
), "\": should be ", NULL
);
41 add_commands(interp
, command_table
, ", ");
44 static void show_cmd_usage(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
, int argc
,
47 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
48 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "Usage: \"", Jim_String(argv
[0]),
49 " command ... \", where command is one of: ", NULL
);
50 add_commands(interp
, command_table
, ", ");
53 static void add_cmd_usage(Jim_Interp
*interp
, const jim_subcmd_type
* ct
, Jim_Obj
*cmd
)
56 Jim_AppendStrings(interp
, Jim_GetResult(interp
), Jim_String(cmd
), " ", NULL
);
58 Jim_AppendStrings(interp
, Jim_GetResult(interp
), ct
->cmd
, NULL
);
59 if (ct
->args
&& *ct
->args
) {
60 Jim_AppendStrings(interp
, Jim_GetResult(interp
), " ", ct
->args
, NULL
);
64 static void set_wrong_args(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
, Jim_Obj
*subcmd
)
66 Jim_SetResultString(interp
, "wrong # args: must be \"", -1);
67 add_cmd_usage(interp
, command_table
, subcmd
);
68 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "\"", NULL
);
71 const jim_subcmd_type
*Jim_ParseSubCmd(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
,
72 int argc
, Jim_Obj
*const *argv
)
74 const jim_subcmd_type
*ct
;
75 const jim_subcmd_type
*partial
= 0;
82 cmdname
= Jim_String(argv
[0]);
85 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
86 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "wrong # args: should be \"", cmdname
,
87 " command ...\"\n", NULL
);
88 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "Use \"", cmdname
, " -help ?command?\" for help", NULL
);
94 /* Check for the help command */
95 if (Jim_CompareStringImmediate(interp
, cmd
, "-help")) {
97 /* Usage for the command, not the subcommand */
98 show_cmd_usage(interp
, command_table
, argc
, argv
);
103 /* Skip the 'help' command */
107 /* Check for special builtin '-commands' command first */
108 if (Jim_CompareStringImmediate(interp
, cmd
, "-commands")) {
109 /* Build the result here */
110 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
111 add_commands(interp
, command_table
, " ");
112 return &dummy_subcmd
;
115 cmdstr
= Jim_GetString(cmd
, &cmdlen
);
117 for (ct
= command_table
; ct
->cmd
; ct
++) {
118 if (Jim_CompareStringImmediate(interp
, cmd
, ct
->cmd
)) {
119 /* Found an exact match */
122 if (strncmp(cmdstr
, ct
->cmd
, cmdlen
) == 0) {
126 /* Just show the top level help here */
127 show_cmd_usage(interp
, command_table
, argc
, argv
);
128 return &dummy_subcmd
;
130 bad_subcmd(interp
, command_table
, "ambiguous", argv
[0], argv
[1 + help
]);
138 /* If we had an unambiguous partial match */
139 if (partial
&& !ct
->cmd
) {
144 /* No matching command */
146 /* Just show the top level help here */
147 show_cmd_usage(interp
, command_table
, argc
, argv
);
148 return &dummy_subcmd
;
150 bad_subcmd(interp
, command_table
, "unknown", argv
[0], argv
[1 + help
]);
155 Jim_SetResultString(interp
, "Usage: ", -1);
157 add_cmd_usage(interp
, ct
, argv
[0]);
158 return &dummy_subcmd
;
161 /* Check the number of args */
162 if (argc
- 2 < ct
->minargs
|| (ct
->maxargs
>= 0 && argc
- 2 > ct
->maxargs
)) {
163 Jim_SetResultString(interp
, "wrong # args: must be \"", -1);
165 add_cmd_usage(interp
, ct
, argv
[0]);
166 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "\"", NULL
);
175 int Jim_CallSubCmd(Jim_Interp
*interp
, const jim_subcmd_type
* ct
, int argc
, Jim_Obj
*const *argv
)
180 if (ct
->flags
& JIM_MODFLAG_FULLARGV
) {
181 ret
= ct
->function(interp
, argc
, argv
);
184 ret
= ct
->function(interp
, argc
- 2, argv
+ 2);
187 set_wrong_args(interp
, ct
, argv
[0]);
194 int Jim_SubCmdProc(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
196 const jim_subcmd_type
*ct
=
197 Jim_ParseSubCmd(interp
, (const jim_subcmd_type
*)Jim_CmdPrivData(interp
), argc
, argv
);
199 return Jim_CallSubCmd(interp
, ct
, argc
, argv
);