Add function for printing command usage
[oweals/u-boot_mod.git] / u-boot / common / command.c
1 /*
2  * (C) Copyright 2000-2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier: GPL-2.0
6  */
7
8 /* Command Processor Table */
9 #include <common.h>
10 #include <command.h>
11
12 void print_cmd_help(cmd_tbl_t *cmdtp)
13 {
14 #ifdef CFG_LONGHELP
15         if (cmdtp->help != NULL) {
16                 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
17         } else {
18                 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
19         }
20 #else
21         printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
22 #endif
23 }
24
25 int do_version(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
26 {
27         extern char version_string[];
28
29         puts("Version and build date:\n");
30         printf("  %s\n  " __DATE__ ", " __TIME__ "\n\n", version_string);
31
32         puts("Modification by:\n");
33         puts("  Piotr Dymacz <piotr@dymacz.pl>\n");
34         puts("  https://github.com/pepe2k/u-boot_mod\n\n");
35
36         return 0;
37 }
38
39 U_BOOT_CMD(version, 1, 1, do_version, "print U-Boot version\n", NULL);
40
41 #if (CONFIG_COMMANDS & CFG_CMD_ECHO)
42 int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
43 {
44         int i, putnl = 1;
45
46         for (i = 1; i < argc; i++) {
47                 char *p = argv[i], c;
48
49                 if (i > 1)
50                         putc(' ');
51
52                 while ((c = *p++) != '\0') {
53                         if (c == '\\' && *p == 'c') {
54                                 putnl = 0;
55                                 p++;
56                         } else {
57                                 putc(c);
58                         }
59                 }
60         }
61
62         if (putnl)
63                 putc('\n');
64
65         return 0;
66 }
67
68 U_BOOT_CMD(echo, CFG_MAXARGS, 1, do_echo,
69         "echo args to console\n", "[args..]\n"
70         "\t- echo args to console; \\c suppresses newline\n");
71 #endif /* CFG_CMD_ECHO */
72
73 #ifdef CFG_HUSH_PARSER
74 int do_test(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
75 {
76         char **ap;
77         int adv, expr, last_expr, last_cmp, left, neg;
78
79         /* args? */
80         if (argc < 3)
81                 return 1;
82
83         last_expr = 0;
84         left = argc - 1;
85         ap = argv + 1;
86
87         if (left > 0 && strcmp(ap[0], "!") == 0) {
88                 neg = 1;
89                 ap++;
90                 left--;
91         } else {
92                 neg = 0;
93         }
94
95         expr = -1;
96         last_cmp = -1;
97         last_expr = -1;
98
99         while (left > 0) {
100                 if (strcmp(ap[0], "-o") == 0 ||
101                     strcmp(ap[0], "-a") == 0) {
102                         adv = 1;
103                 } else if (strcmp(ap[0], "-z") == 0 ||
104                            strcmp(ap[0], "-n") == 0) {
105                         adv = 2;
106                 } else {
107                         adv = 3;
108                 }
109
110                 if (left < adv) {
111                         expr = 1;
112                         break;
113                 }
114
115                 if (adv == 1) {
116                         if (strcmp(ap[0], "-o") == 0) {
117                                 last_expr = expr;
118                                 last_cmp = 0;
119                         } else if (strcmp(ap[0], "-a") == 0) {
120                                 last_expr = expr;
121                                 last_cmp = 1;
122                         } else {
123                                 expr = 1;
124                                 break;
125                         }
126                 }
127
128                 if (adv == 2) {
129                         if (strcmp(ap[0], "-z") == 0) {
130                                 expr = strlen(ap[1]) == 0 ? 1 : 0;
131                         } else if (strcmp(ap[0], "-n") == 0) {
132                                 expr = strlen(ap[1]) == 0 ? 0 : 1;
133                         } else {
134                                 expr = 1;
135                                 break;
136                         }
137
138                         if (last_cmp == 0) {
139                                 expr = last_expr || expr;
140                         } else if (last_cmp == 1) {
141                                 expr = last_expr && expr;
142                         }
143
144                         last_cmp = -1;
145                 }
146
147                 if (adv == 3) {
148                         if (strcmp(ap[1], "=") == 0) {
149                                 expr = strcmp(ap[0], ap[2]) == 0;
150                         } else if (strcmp(ap[1], "!=") == 0) {
151                                 expr = strcmp(ap[0], ap[2]) != 0;
152                         } else if (strcmp(ap[1], ">") == 0) {
153                                 expr = strcmp(ap[0], ap[2]) > 0;
154                         } else if (strcmp(ap[1], "<") == 0) {
155                                 expr = strcmp(ap[0], ap[2]) < 0;
156                         } else if (strcmp(ap[1], "-eq") == 0) {
157                                 expr = simple_strtol(ap[0], NULL, 10)
158                                        == simple_strtol(ap[2], NULL, 10);
159                         } else if (strcmp(ap[1], "-ne") == 0) {
160                                 expr = simple_strtol(ap[0], NULL, 10)
161                                        != simple_strtol(ap[2], NULL, 10);
162                         } else if (strcmp(ap[1], "-lt") == 0) {
163                                 expr = simple_strtol(ap[0], NULL, 10)
164                                        < simple_strtol(ap[2], NULL, 10);
165                         } else if (strcmp(ap[1], "-le") == 0) {
166                                 expr = simple_strtol(ap[0], NULL, 10)
167                                        <= simple_strtol(ap[2], NULL, 10);
168                         } else if (strcmp(ap[1], "-gt") == 0) {
169                                 expr = simple_strtol(ap[0], NULL, 10)
170                                        > simple_strtol(ap[2], NULL, 10);
171                         } else if (strcmp(ap[1], "-ge") == 0) {
172                                 expr = simple_strtol(ap[0], NULL, 10)
173                                        >= simple_strtol(ap[2], NULL, 10);
174                         } else {
175                                 expr = 1;
176                                 break;
177                         }
178
179                         if (last_cmp == 0) {
180                                 expr = last_expr || expr;
181                         } else if (last_cmp == 1) {
182                                 expr = last_expr && expr;
183                         }
184
185                         last_cmp = -1;
186                 }
187
188                 ap += adv; left -= adv;
189         }
190
191         if (neg)
192                 expr = !expr;
193
194         expr = !expr;
195
196         return expr;
197 }
198
199 U_BOOT_CMD(test, CFG_MAXARGS, 1, do_test,
200         "minimal test like /bin/sh\n", "[args..]\n"
201         "\t- test functionality\n");
202
203 int do_exit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
204 {
205         int r = 0;
206
207         if (argc > 1)
208                 r = simple_strtoul(argv[1], NULL, 10);
209
210         return (-r - 2);
211 }
212
213 U_BOOT_CMD(exit, 2, 1, do_exit,
214         "exit script\n", "\n\t- exit functionality\n");
215 #endif /* CFG_HUSH_PARSER */
216
217 /*
218  * Use puts() instead of printf() to avoid printf buffer overflow
219  * for long help messages
220  */
221 int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
222 {
223         int i;
224         int rcode = 0;
225
226         /* Show list of commands */
227         if (argc == 1) {
228                 /* Pointer arith! */
229                 int cmd_items = &__u_boot_cmd_end - &__u_boot_cmd_start;
230
231                 cmd_tbl_t *cmd_array[cmd_items];
232                 int i, j, swaps, max_len = 0;
233
234                 /* Make array of commands from .uboot_cmd section */
235                 cmdtp = &__u_boot_cmd_start;
236
237                 for (i = 0; i < cmd_items; i++) {
238                         cmd_array[i] = cmdtp++;
239                 }
240
241                 /* Sort command list (trivial bubble sort) */
242                 for (i = cmd_items - 1; i > 0; --i) {
243                         swaps = 0;
244                         for (j = 0; j < i; ++j) {
245                                 const char *name = cmd_array[j]->name;
246
247                                 if (strlen(name) >= max_len)
248                                         max_len = strlen(name);
249
250                                 if (strcmp(cmd_array[j]->name,
251                                            cmd_array[j + 1]->name) > 0) {
252                                         cmd_tbl_t *tmp;
253                                         tmp = cmd_array[j];
254                                         cmd_array[j] = cmd_array[j + 1];
255                                         cmd_array[j + 1] = tmp;
256                                         ++swaps;
257                                 }
258                         }
259
260                         if (!swaps)
261                                 break;
262                 }
263
264                 /* Print short help (usage) */
265                 for (i = 0; i < cmd_items; i++) {
266                         const char *usage = cmd_array[i]->usage;
267                         const char *name = cmd_array[i]->name;
268
269                         /* Allow user abort */
270                         if (ctrlc())
271                                 return 1;
272
273                         if (usage == NULL)
274                                 continue;
275
276                         /* Print aligned command name and usage */
277                         printf("%-*s - ", max_len, name);
278                         puts(usage);
279                 }
280
281                 puts("\n");
282                 return 0;
283         }
284
285         /* Command help (long version) */
286         for (i = 1; i < argc; ++i) {
287                 if ((cmdtp = find_cmd(argv[i])) != NULL) {
288 #ifdef  CFG_LONGHELP
289                         /* Found - print (long) help info */
290                         puts(cmdtp->name);
291                         putc(' ');
292
293                         if (cmdtp->help) {
294                                 puts(cmdtp->help);
295                         } else {
296                                 puts("- there is no help for this command\n");
297                                 rcode = 1;
298                         }
299
300                         putc('\n');
301 #else
302                         if (cmdtp->usage)
303                                 puts(cmdtp->usage);
304 #endif /* CFG_LONGHELP */
305                 } else {
306                         printf("Unknown command '%s' - try 'help' without arguments\n\n", argv[i]);
307                         rcode = 1;
308                 }
309         }
310
311         return rcode;
312 }
313
314 U_BOOT_CMD(help, CFG_MAXARGS, 1, do_help,
315         "print embedded help\n", "[command ...]\n"
316         "\t- show help information for 'command' or short usage of all commands\n");
317
318 /* This do not ust the U_BOOT_CMD macro as ? can't be used in symbol names */
319 #ifdef CFG_LONGHELP
320 cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {"?", CFG_MAXARGS, 1, do_help, "alias for 'help'\n", NULL};
321 #else
322 cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {"?", CFG_MAXARGS, 1, do_help, "alias for 'help'\n"};
323 #endif /* CFG_LONGHELP */
324
325 /*
326  * Find command table entry for a command
327  */
328 cmd_tbl_t *find_cmd(const char *cmd)
329 {
330         int len;
331         int n_found = 0;
332         const char *p;
333         cmd_tbl_t *cmdtp;
334         cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
335
336         /*
337          * Some commands allow length modifiers (like "cp.b");
338          * compare command name only until first dot.
339          */
340         len = ((p = strchr(cmd, '.')) == NULL) ? strlen(cmd) : (p - cmd);
341
342         for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) {
343                 if (strncmp(cmd, cmdtp->name, len) == 0) {
344                         /* Full match? */
345                         if (len == strlen(cmdtp->name))
346                                 return cmdtp;
347
348                         /* Abbreviated command ? */
349                         cmdtp_temp = cmdtp;
350                         n_found++;
351                 }
352         }
353
354         /* Exactly one match */
355         if (n_found == 1)
356                 return(cmdtp_temp);
357
358         /* Not found or ambiguous command */
359         return NULL;
360 }