summaryrefslogtreecommitdiff
path: root/include/command.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/command.h')
-rw-r--r--include/command.h133
1 files changed, 129 insertions, 4 deletions
diff --git a/include/command.h b/include/command.h
index 200c7a5e9f..461b17447c 100644
--- a/include/command.h
+++ b/include/command.h
@@ -29,7 +29,16 @@
struct cmd_tbl_s {
char *name; /* Command Name */
int maxargs; /* maximum number of arguments */
- int repeatable; /* autorepeat allowed? */
+ /*
+ * Same as ->cmd() except the command
+ * tells us if it can be repeated.
+ * Replaces the old ->repeatable field
+ * which was not able to make
+ * repeatable property different for
+ * the main command and sub-commands.
+ */
+ int (*cmd_rep)(struct cmd_tbl_s *cmd, int flags, int argc,
+ char * const argv[], int *repeatable);
/* Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char * const []);
char *usage; /* Usage message (short) */
@@ -54,9 +63,25 @@ int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int
flag, int argc, char * const argv[]);
cmd_tbl_t *find_cmd(const char *cmd);
cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
+int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc,
+ char * const argv[], char last_char, int maxv,
+ char *cmdv[]);
extern int cmd_usage(const cmd_tbl_t *cmdtp);
+/* Dummy ->cmd and ->cmd_rep wrappers. */
+int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[], int *repeatable);
+int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[], int *repeatable);
+int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[]);
+
+static inline bool cmd_is_repeatable(cmd_tbl_t *cmdtp)
+{
+ return cmdtp->cmd_rep == cmd_always_repeatable;
+}
+
#ifdef CONFIG_AUTO_COMPLETE
extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp);
@@ -184,17 +209,93 @@ int board_run_command(const char *cmdline);
# define _CMD_HELP(x)
#endif
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+#define U_BOOT_SUBCMDS_RELOC(_cmdname) \
+ static void _cmdname##_subcmds_reloc(void) \
+ { \
+ static int relocated; \
+ \
+ if (relocated) \
+ return; \
+ \
+ fixup_cmdtable(_cmdname##_subcmds, \
+ ARRAY_SIZE(_cmdname##_subcmds)); \
+ relocated = 1; \
+ }
+#else
+#define U_BOOT_SUBCMDS_RELOC(_cmdname) \
+ static void _cmdname##_subcmds_reloc(void) { }
+#endif
+
+#define U_BOOT_SUBCMDS_DO_CMD(_cmdname) \
+ static int do_##_cmdname(cmd_tbl_t *cmdtp, int flag, int argc, \
+ char * const argv[], int *repeatable) \
+ { \
+ cmd_tbl_t *subcmd; \
+ \
+ _cmdname##_subcmds_reloc(); \
+ \
+ /* We need at least the cmd and subcmd names. */ \
+ if (argc < 2 || argc > CONFIG_SYS_MAXARGS) \
+ return CMD_RET_USAGE; \
+ \
+ subcmd = find_cmd_tbl(argv[1], _cmdname##_subcmds, \
+ ARRAY_SIZE(_cmdname##_subcmds)); \
+ if (!subcmd || argc - 1 > subcmd->maxargs) \
+ return CMD_RET_USAGE; \
+ \
+ if (flag == CMD_FLAG_REPEAT && \
+ !cmd_is_repeatable(subcmd)) \
+ return CMD_RET_SUCCESS; \
+ \
+ return subcmd->cmd_rep(subcmd, flag, argc - 1, \
+ argv + 1, repeatable); \
+ }
+
+#ifdef CONFIG_AUTO_COMPLETE
+#define U_BOOT_SUBCMDS_COMPLETE(_cmdname) \
+ static int complete_##_cmdname(int argc, char * const argv[], \
+ char last_char, int maxv, \
+ char *cmdv[]) \
+ { \
+ return complete_subcmdv(_cmdname##_subcmds, \
+ ARRAY_SIZE(_cmdname##_subcmds), \
+ argc - 1, argv + 1, last_char, \
+ maxv, cmdv); \
+ }
+#else
+#define U_BOOT_SUBCMDS_COMPLETE(_cmdname)
+#endif
+
+#define U_BOOT_SUBCMDS(_cmdname, ...) \
+ static cmd_tbl_t _cmdname##_subcmds[] = { __VA_ARGS__ }; \
+ U_BOOT_SUBCMDS_RELOC(_cmdname) \
+ U_BOOT_SUBCMDS_DO_CMD(_cmdname) \
+ U_BOOT_SUBCMDS_COMPLETE(_cmdname)
+
#ifdef CONFIG_CMDLINE
+#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
+ _usage, _help, _comp) \
+ { #_name, _maxargs, _cmd_rep, cmd_discard_repeatable, \
+ _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+
#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \
_usage, _help, _comp) \
- { #_name, _maxargs, _rep, _cmd, _usage, \
- _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+ { #_name, _maxargs, \
+ _rep ? cmd_always_repeatable : cmd_never_repeatable, \
+ _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
ll_entry_declare(cmd_tbl_t, _name, cmd) = \
U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \
_usage, _help, _comp);
+#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \
+ _help, _comp) \
+ ll_entry_declare(cmd_tbl_t, _name, cmd) = \
+ U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
+ _usage, _help, _comp)
+
#else
#define U_BOOT_SUBCMD_START(name) static cmd_tbl_t name[] = {};
#define U_BOOT_SUBCMD_END
@@ -206,15 +307,25 @@ int board_run_command(const char *cmdline);
_cmd(NULL, 0, 0, NULL); \
return 0; \
}
+
+#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
+ _usage, _help, _comp) \
+ { #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage, \
+ _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+
#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, \
_help, _comp) \
- { #_name, _maxargs, _rep, 0 ? _cmd : NULL, _usage, \
+ { #_name, _maxargs, NULL, 0 ? _cmd : NULL, _usage, \
_CMD_HELP(_help) _CMD_COMPLETE(_comp) }
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \
_comp) \
_CMD_REMOVE(sub_ ## _name, _cmd)
+#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \
+ _help, _comp) \
+ _CMD_REMOVE(sub_ ## _name, _cmd_rep)
+
#endif /* CONFIG_CMDLINE */
#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \
@@ -224,4 +335,18 @@ int board_run_command(const char *cmdline);
U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \
_usage, _help, NULL)
+#define U_BOOT_SUBCMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd, \
+ _comp) \
+ U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd, \
+ "", "", _comp)
+
+#define U_BOOT_SUBCMD_MKENT(_name, _maxargs, _rep, _do_cmd) \
+ U_BOOT_SUBCMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd, \
+ NULL)
+
+#define U_BOOT_CMD_WITH_SUBCMDS(_name, _usage, _help, ...) \
+ U_BOOT_SUBCMDS(_name, __VA_ARGS__) \
+ U_BOOT_CMDREP_COMPLETE(_name, CONFIG_SYS_MAXARGS, do_##_name, \
+ _usage, _help, complete_##_name)
+
#endif /* __COMMAND_H */