4 #include <jim-subcmd.h>
7 * Implements the common 'commands' subcommand
9 static int subcmd_null(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
11 /* Nothing to do, since the result has already been created */
16 * Do-nothing command to support -commands and -usage
18 static const jim_subcmd_type dummy_subcmd
= {
19 "dummy", NULL
, subcmd_null
, 0, 0, JIM_MODFLAG_HIDDEN
22 static void add_commands(Jim_Interp
*interp
, const jim_subcmd_type
* ct
, const char *sep
)
26 for (; ct
->cmd
; ct
++) {
27 if (!(ct
->flags
& JIM_MODFLAG_HIDDEN
)) {
28 Jim_AppendStrings(interp
, Jim_GetResult(interp
), s
, ct
->cmd
, NULL
);
34 static void bad_subcmd(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
, const char *type
,
35 Jim_Obj
*cmd
, Jim_Obj
*subcmd
)
37 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
38 Jim_AppendStrings(interp
, Jim_GetResult(interp
), Jim_String(cmd
), ", ", type
,
39 " command \"", Jim_String(subcmd
), "\": should be ", NULL
);
40 add_commands(interp
, command_table
, ", ");
43 static void show_cmd_usage(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
, int argc
,
46 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
47 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "Usage: \"", Jim_String(argv
[0]),
48 " command ... \", where command is one of: ", NULL
);
49 add_commands(interp
, command_table
, ", ");
52 static void add_cmd_usage(Jim_Interp
*interp
, const jim_subcmd_type
* ct
, Jim_Obj
*cmd
)
55 Jim_AppendStrings(interp
, Jim_GetResult(interp
), Jim_String(cmd
), " ", NULL
);
57 Jim_AppendStrings(interp
, Jim_GetResult(interp
), ct
->cmd
, NULL
);
58 if (ct
->args
&& *ct
->args
) {
59 Jim_AppendStrings(interp
, Jim_GetResult(interp
), " ", ct
->args
, NULL
);
63 static void set_wrong_args(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
, Jim_Obj
*subcmd
)
65 Jim_SetResultString(interp
, "wrong # args: should be \"", -1);
66 add_cmd_usage(interp
, command_table
, subcmd
);
67 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "\"", NULL
);
70 const jim_subcmd_type
*Jim_ParseSubCmd(Jim_Interp
*interp
, const jim_subcmd_type
* command_table
,
71 int argc
, Jim_Obj
*const *argv
)
73 const jim_subcmd_type
*ct
;
74 const jim_subcmd_type
*partial
= 0;
81 cmdname
= Jim_String(argv
[0]);
84 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
85 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "wrong # args: should be \"", cmdname
,
86 " command ...\"\n", NULL
);
87 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "Use \"", cmdname
, " -help ?command?\" for help", NULL
);
93 /* Check for the help command */
94 if (Jim_CompareStringImmediate(interp
, cmd
, "-help")) {
96 /* Usage for the command, not the subcommand */
97 show_cmd_usage(interp
, command_table
, argc
, argv
);
102 /* Skip the 'help' command */
106 /* Check for special builtin '-commands' command first */
107 if (Jim_CompareStringImmediate(interp
, cmd
, "-commands")) {
108 /* Build the result here */
109 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
110 add_commands(interp
, command_table
, " ");
111 return &dummy_subcmd
;
114 cmdstr
= Jim_GetString(cmd
, &cmdlen
);
116 for (ct
= command_table
; ct
->cmd
; ct
++) {
117 if (Jim_CompareStringImmediate(interp
, cmd
, ct
->cmd
)) {
118 /* Found an exact match */
121 if (strncmp(cmdstr
, ct
->cmd
, cmdlen
) == 0) {
125 /* Just show the top level help here */
126 show_cmd_usage(interp
, command_table
, argc
, argv
);
127 return &dummy_subcmd
;
129 bad_subcmd(interp
, command_table
, "ambiguous", argv
[0], argv
[1 + help
]);
137 /* If we had an unambiguous partial match */
138 if (partial
&& !ct
->cmd
) {
143 /* No matching command */
145 /* Just show the top level help here */
146 show_cmd_usage(interp
, command_table
, argc
, argv
);
147 return &dummy_subcmd
;
149 bad_subcmd(interp
, command_table
, "unknown", argv
[0], argv
[1 + help
]);
154 Jim_SetResultString(interp
, "Usage: ", -1);
156 add_cmd_usage(interp
, ct
, argv
[0]);
157 return &dummy_subcmd
;
160 /* Check the number of args */
161 if (argc
- 2 < ct
->minargs
|| (ct
->maxargs
>= 0 && argc
- 2 > ct
->maxargs
)) {
162 Jim_SetResultString(interp
, "wrong # args: should be \"", -1);
164 add_cmd_usage(interp
, ct
, argv
[0]);
165 Jim_AppendStrings(interp
, Jim_GetResult(interp
), "\"", NULL
);
174 int Jim_CallSubCmd(Jim_Interp
*interp
, const jim_subcmd_type
* ct
, int argc
, Jim_Obj
*const *argv
)
179 if (ct
->flags
& JIM_MODFLAG_FULLARGV
) {
180 ret
= ct
->function(interp
, argc
, argv
);
183 ret
= ct
->function(interp
, argc
- 2, argv
+ 2);
186 set_wrong_args(interp
, ct
, argv
[0]);
193 int Jim_SubCmdProc(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
195 const jim_subcmd_type
*ct
=
196 Jim_ParseSubCmd(interp
, (const jim_subcmd_type
*)Jim_CmdPrivData(interp
), argc
, argv
);
198 return Jim_CallSubCmd(interp
, ct
, argc
, argv
);