usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / usbmodeswitch / jim / jim-subcmd.c
blob2de560ac7516ace0b4ded35bcbc7e9f1af4bf62e
1 #include <stdio.h>
2 #include <string.h>
4 #include "jim-subcmd.h"
5 #include "jimautoconf.h"
7 /**
8 * Implements the common 'commands' subcommand
9 */
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 */
13 return JIM_OK;
16 /**
17 * Do-nothing command to support -commands and -usage
19 static const jim_subcmd_type dummy_subcmd = {
20 .cmd = "dummy",
21 .function = subcmd_null,
22 .flags = JIM_MODFLAG_HIDDEN,
25 static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep)
27 const char *s = "";
29 for (; ct->cmd; ct++) {
30 if (!(ct->flags & JIM_MODFLAG_HIDDEN)) {
31 Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL);
32 s = sep;
37 static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
38 Jim_Obj *cmd, Jim_Obj *subcmd)
40 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
41 Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type,
42 " command \"", Jim_String(subcmd), "\": should be ", NULL);
43 add_commands(interp, command_table, ", ");
46 static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
47 Jim_Obj *const *argv)
49 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
50 Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]),
51 " command ... \", where command is one of: ", NULL);
52 add_commands(interp, command_table, ", ");
55 static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd)
57 if (cmd) {
58 Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), " ", NULL);
60 Jim_AppendStrings(interp, Jim_GetResult(interp), ct->cmd, NULL);
61 if (ct->args && *ct->args) {
62 Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL);
66 static void show_full_usage(Jim_Interp *interp, const jim_subcmd_type * ct, int argc,
67 Jim_Obj *const *argv)
69 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
70 for (; ct->cmd; ct++) {
71 if (!(ct->flags & JIM_MODFLAG_HIDDEN)) {
72 /* subcmd */
73 add_cmd_usage(interp, ct, argv[0]);
74 if (ct->description) {
75 Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n ", ct->description, NULL);
77 Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", NULL);
82 static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd)
84 Jim_SetResultString(interp, "wrong # args: must be \"", -1);
85 add_cmd_usage(interp, command_table, subcmd);
86 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
89 const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table,
90 int argc, Jim_Obj *const *argv)
92 const jim_subcmd_type *ct;
93 const jim_subcmd_type *partial = 0;
94 int cmdlen;
95 Jim_Obj *cmd;
96 const char *cmdstr;
97 const char *cmdname;
98 int help = 0;
100 cmdname = Jim_String(argv[0]);
102 if (argc < 2) {
103 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
104 Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname,
105 " command ...\"\n", NULL);
106 Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help\" or \"",
107 cmdname, " -help command\" for help", NULL);
108 return 0;
111 cmd = argv[1];
113 if (argc == 2 && Jim_CompareStringImmediate(interp, cmd, "-usage")) {
114 /* Show full usage */
115 show_full_usage(interp, command_table, argc, argv);
116 return &dummy_subcmd;
119 /* Check for the help command */
120 if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
121 if (argc == 2) {
122 /* Usage for the command, not the subcommand */
123 show_cmd_usage(interp, command_table, argc, argv);
124 return &dummy_subcmd;
126 help = 1;
128 /* Skip the 'help' command */
129 cmd = argv[2];
132 /* Check for special builtin '-commands' command first */
133 if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
134 /* Build the result here */
135 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
136 add_commands(interp, command_table, " ");
137 return &dummy_subcmd;
140 cmdstr = Jim_GetString(cmd, &cmdlen);
142 for (ct = command_table; ct->cmd; ct++) {
143 if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
144 /* Found an exact match */
145 break;
147 if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
148 if (partial) {
149 /* Ambiguous */
150 if (help) {
151 /* Just show the top level help here */
152 show_cmd_usage(interp, command_table, argc, argv);
153 return &dummy_subcmd;
155 bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
156 return 0;
158 partial = ct;
160 continue;
163 /* If we had an unambiguous partial match */
164 if (partial && !ct->cmd) {
165 ct = partial;
168 if (!ct->cmd) {
169 /* No matching command */
170 if (help) {
171 /* Just show the top level help here */
172 show_cmd_usage(interp, command_table, argc, argv);
173 return &dummy_subcmd;
175 bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
176 return 0;
179 if (help) {
180 Jim_SetResultString(interp, "Usage: ", -1);
181 /* subcmd */
182 add_cmd_usage(interp, ct, argv[0]);
183 if (ct->description) {
184 Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", ct->description, NULL);
186 return &dummy_subcmd;
189 /* Check the number of args */
190 if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
191 Jim_SetResultString(interp, "wrong # args: must be \"", -1);
192 /* subcmd */
193 add_cmd_usage(interp, ct, argv[0]);
194 Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
196 return 0;
199 /* Good command */
200 return ct;
203 int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
205 int ret = JIM_ERR;
207 if (ct) {
208 if (ct->flags & JIM_MODFLAG_FULLARGV) {
209 ret = ct->function(interp, argc, argv);
211 else {
212 ret = ct->function(interp, argc - 2, argv + 2);
214 if (ret < 0) {
215 set_wrong_args(interp, ct, argv[0]);
216 ret = JIM_ERR;
219 return ret;
222 int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
224 const jim_subcmd_type *ct =
225 Jim_ParseSubCmd(interp, (const jim_subcmd_type *)Jim_CmdPrivData(interp), argc, argv);
227 return Jim_CallSubCmd(interp, ct, argc, argv);
230 /* The following two functions are for normal commands */
232 Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
233 Jim_Obj *const *argv)
235 /* -usage or -help */
236 if (argc == 2) {
237 if (Jim_CompareStringImmediate(interp, argv[1], "-usage")
238 || Jim_CompareStringImmediate(interp, argv[1], "-help")) {
239 Jim_SetResultString(interp, "Usage: ", -1);
240 add_cmd_usage(interp, command_table, NULL);
241 if (command_table->description) {
242 Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", command_table->description,
243 NULL);
245 return JIM_OK;
248 if (argc >= 2 && command_table->function) {
249 /* This is actually a sub command table */
251 Jim_Obj *nargv[4];
252 int nargc = 0;
253 const char *subcmd = NULL;
255 if (Jim_CompareStringImmediate(interp, argv[1], "-subcommands")) {
256 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
257 add_commands(interp, (jim_subcmd_type *) command_table->function, " ");
258 return JIM_OK;
261 if (Jim_CompareStringImmediate(interp, argv[1], "-subhelp")
262 || Jim_CompareStringImmediate(interp, argv[1], "-help")) {
263 subcmd = "-help";
265 else if (Jim_CompareStringImmediate(interp, argv[1], "-subusage")) {
266 subcmd = "-usage";
269 if (subcmd) {
270 nargv[nargc++] = Jim_NewStringObj(interp, "$handle", -1);
271 nargv[nargc++] = Jim_NewStringObj(interp, subcmd, -1);
272 if (argc >= 3) {
273 nargv[nargc++] = argv[2];
275 Jim_ParseSubCmd(interp, (jim_subcmd_type *) command_table->function, nargc, nargv);
276 Jim_FreeNewObj(interp, nargv[0]);
277 Jim_FreeNewObj(interp, nargv[1]);
278 return 0;
282 /* Check the number of args */
283 if (argc - 1 < command_table->minargs || (command_table->maxargs >= 0
284 && argc - 1 > command_table->maxargs)) {
285 set_wrong_args(interp, command_table, NULL);
286 Jim_AppendStrings(interp, Jim_GetResult(interp), "\nUse \"", Jim_String(argv[0]),
287 " -help\" for help", NULL);
288 return JIM_ERR;
291 /* Not usage, but passed arg checking */
292 return -1;