]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/command.c
fat cp: copy_dir (untested)
[z180-stamp.git] / avr / command.c
index b9c5e56f6985a27d98ce31011be11aab582f5e26..c8a73f0bea37facb1b640451e5dd30d55dedd324 100644 (file)
@@ -59,6 +59,8 @@ int cmpstring_PP(const void *p1, const void *p2)
                         (*(const FLASH cmd_tbl_t **) p2)->name);
 }
 
+/****************************************************************************/
+
 int cmd_tbl_item_count(cmd_tbl_t *p)
 {
        int count = 0;
@@ -69,51 +71,85 @@ int cmd_tbl_item_count(cmd_tbl_t *p)
        return count;
 }
 
-/***************************************************************************
- * find command table entry for a command
- */
-cmd_tbl_t *find_cmd (const char *cmd, cmd_tbl_t *table)
+
+cmd_tbl_t *get_cmd_tbl_base(cmd_tbl_t  *cmdtp)
 {
-       cmd_tbl_t *cmdtp;
-       cmd_tbl_t *cmdtp_temp = table;  /*Init value */
-       int table_len = cmd_tbl_item_count(table);
-       size_t len;
-       uint_fast8_t n_found = 0;
+       cmd_tbl_t *p = cmdtp;
 
-       char *optenv = getenv_str(PSTR("cmd"));
-       bool opt_debug = optenv && strstr_P(optenv, PSTR("debug")) != NULL;
+       while (p->name != NULL)
+               ++p;
 
-       if (!cmd)
-               return NULL;
+       return p->subcmd;
+}
 
-       len = strlen(cmd);
+/*
+ * find command table entry for a command
+ */
+typedef struct {
+               size_t len;
+               uint_fast8_t level;
+               bool opt_debug;
+       } find_cmd_para_t;
 
-       for (cmdtp = table;
-            cmdtp != table + table_len;
-            cmdtp++) {
-               if (strncmp_P(cmd, cmdtp->name, len) == 0 &&
-                                       (opt_debug || cmdtp->name[0] != '!')) {
-                       if (len == strlen_P(cmdtp->name))
+cmd_tbl_t *_find_cmd (const char *cmd, cmd_tbl_t *table, find_cmd_para_t *para)
+{
+       cmd_tbl_t *cmdtp_ret = NULL;
+       uint_fast8_t n_found = 0, sub_found = 0;
+
+       for (cmd_tbl_t *cmdtp = table; cmdtp->name != NULL; cmdtp++) {
+               if (strncmp_P(cmd, cmdtp->name, para->len) == 0 &&
+                                       (para->opt_debug || !(cmdtp->flags & CTBL_DBG))) {
+                       if (para->len == strlen_P(cmdtp->name))
                                return cmdtp;   /* full match */
 
-                       cmdtp_temp = cmdtp;     /* abbreviated command ? */
+                       cmdtp_ret = cmdtp;      /* abbreviated command ? */
                        n_found++;
+               } else if (cmdtp->subcmd && cmdtp->flags & CTBL_SUBCMDAUTO) {
+                       cmd_tbl_t *sub = _find_cmd(cmd, cmdtp->subcmd, para);
+                       if (sub) {
+                               cmdtp_ret = sub;
+                               ++n_found;
+                       }
                }
        }
-       if (n_found == 1)                       /* exactly one match */
-               return cmdtp_temp;
+       if (n_found == 1) {                     /* exactly one match */
+               if (sub_found)
+                       para->level++;
+               return cmdtp_ret;
+       }
 
        return NULL;    /* not found or ambiguous command */
 }
 
-cmd_tbl_t *get_cmd_tbl_start(cmd_tbl_t  *cmdtp)
+
+cmd_tbl_t *find_cmd (const char *cmd, cmd_tbl_t *table, uint_fast8_t *cmdlevel)
 {
-       cmd_tbl_t *p = cmdtp;
+       find_cmd_para_t para;
 
-       while (p->name != NULL)
-               ++p;
+       if (!cmd)
+               return NULL;
 
-       return p->subcmd;
+       char *optenv = getenv_str(PSTR("cmd"));
+       para.level = 0;
+       para.opt_debug = optenv && strstr_P(optenv, PSTR("debug")) != NULL;
+       para.len = strlen(cmd);
+
+       cmd_tbl_t *cmdtp = _find_cmd(cmd, table, &para);
+
+       if (cmdlevel)
+               *cmdlevel = para.level;
+       return cmdtp;
+}
+
+cmd_tbl_t *find_cmd_sub(const char *cmd, cmd_tbl_t *table)
+{
+       cmd_tbl_t *entry = NULL;
+
+       for (cmd_tbl_t *tp = get_cmd_tbl_base(table); tp->name && entry == NULL; tp++)
+               if (tp->subcmd && tp->flags & CTBL_SUBCMDAUTO)
+                       entry = find_cmd(cmd, tp->subcmd, NULL);
+
+       return entry;
 }
 
 /*
@@ -121,50 +157,50 @@ cmd_tbl_t *get_cmd_tbl_start(cmd_tbl_t  *cmdtp)
  * for long help messages
  */
 
-command_ret_t do_help(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
+command_ret_t do_help(cmd_tbl_t *cmdtp, uint_fast8_t flag UNUSED, int argc, char * const argv[])
 {
-       (void) flag;
-
-       cmd_tbl_t *tbl_start = get_cmd_tbl_start(cmdtp);
+       cmd_tbl_t *tbl_start = get_cmd_tbl_base(cmdtp);
 
        char *optenv = getenv_str(PSTR("cmd"));
        bool opt_debug = optenv && strstr_P(optenv, PSTR("debug")) != NULL;
 
        if (argc == 1) {        /*show list of commands */
                int cmd_items = cmd_tbl_item_count(tbl_start);
-               cmd_tbl_t *cmd_array[cmd_items];
-               cmd_tbl_t *tp = tbl_start;
-               uint_fast8_t max_len = 0;
+               cmd_tbl_t **cmd_list = (cmd_tbl_t **) malloc(cmd_items * sizeof(cmd_tbl_t *));
+               uint_fast8_t maxlen_cmd = 0;
 
-               /* Make array of commands from .uboot_cmd section */
+               /* Make array of commands */
+               cmd_tbl_t *tp = tbl_start;
                for (int i = 0; i < cmd_items; i++) {
-                       cmd_array[i] = tp++;
-                       uint_fast8_t l = strlen_P(cmd_array[i]->name);
-                       if (l > max_len)
-                               max_len = l;
+                       uint_fast8_t l = strlen_P(tp->name);
+                       if (l > maxlen_cmd)
+                               maxlen_cmd = l;
+                       cmd_list[i] = tp++;
                }
-
                /* Sort command list */
-               qsort(cmd_array, cmd_items, sizeof (cmd_tbl_t *), cmpstring_PP);
+               qsort(cmd_list, cmd_items, sizeof (cmd_tbl_t *), cmpstring_PP);
 
                /* print short help (usage) */
                for (int i = 0; i < cmd_items; i++) {
-                       if (opt_debug || cmd_array[i]->name[0] != '!') {
-                               const FLASH char *usage = cmd_array[i]->usage;
+                       if (opt_debug || !(cmd_list[i]->flags & CTBL_DBG)) {
+                               const FLASH char *usage = cmd_list[i]->usage;
 
                                /* allow user abort */
-                               if (ctrlc ())
+                               if (ctrlc ()) {
+                                       free(cmd_list);
                                        return CMD_RET_FAILURE;
+                               }
                                if (usage == NULL)
                                        continue;
 #if defined(GCC_BUG_61443) || 1
-                               print_usage_line(cmd_array[i]->name, max_len, usage);
+                               print_usage_line(cmd_list[i]->name, maxlen_cmd, usage);
 #else
                                printf_P(PSTR("%-" stringify(8) /*FIXME*/ "S - %S\n"),
-                                               cmd_array[i]->name, usage);
+                                               cmd_list[i]->name, usage);
 #endif
                        }
                }
+               free(cmd_list);
                return CMD_RET_SUCCESS;
        }
 
@@ -172,7 +208,7 @@ command_ret_t do_help(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * cons
         * command help (long version)
         */
        for (uint8_t i = 1; i < argc; ++i) {
-               if ((cmdtp = find_cmd(argv[i], tbl_start)) != NULL &&
+               if ((cmdtp = find_cmd(argv[i], tbl_start, NULL)) != NULL &&
                                        (opt_debug || cmdtp->name[0] != '!')) {
                        cmd_usage(cmdtp);
                } else {
@@ -504,28 +540,37 @@ command_ret_t cmd_process(uint_fast8_t flag, int argc, char * const argv[],
 {
        command_ret_t rc = CMD_RET_SUCCESS;
        cmd_tbl_t *cmdtp;
+       uint_fast8_t cmdlevel;
 
        /* Look up command in command table */
-       cmdtp = find_cmd(argv[0], cmd_tbl);
+       cmdtp = find_cmd(argv[0], cmd_tbl, &cmdlevel);
+       if (cmdtp != NULL) {
+               /* Check if this command has subcommands */
+               if (cmdtp->subcmd && argc > 1) {
+
+                       /* Look up subcommand in subcommand table */
+                       cmd_tbl_t *cmdtpsub = find_cmd(argv[1], cmdtp->subcmd, &cmdlevel);
+                       if (cmdtpsub == NULL) {
+                               printf_P(PSTR("Unknown '%s' subcommand '%s' - try '%s help'\n"), argv[0], argv[1], argv[0]);
+                               return CMD_RET_FAILURE;
+                       }
+                       cmdtp = cmdtpsub;
+                       --argc;
+                       ++argv;
+               }
+       }
+#if 0
+        else {
+               /* Search subcommands */
+               cmdtp = find_cmd_sub(argv[0], cmd_tbl, &cmdlevel);
+       }
+#endif
+
        if (cmdtp == NULL) {
                printf_P(PSTR("Unknown command '%s' - try 'help'\n"), argv[0]);
                return CMD_RET_FAILURE;
        }
 
-       /* Check for subcommand */
-       if (cmdtp->subcmd && argc > 1) {
-
-               /* Look up subcommand in subcommand table */
-               cmd_tbl_t *cmdtpsub = find_cmd(argv[1], cmdtp->subcmd);
-               if (cmdtpsub == NULL) {
-                       printf_P(PSTR("Unknown '%s' subcommand '%s' - try '%s help'\n"), argv[0], argv[1], argv[0]);
-                       return CMD_RET_FAILURE;
-               }
-               cmdtp = cmdtpsub;
-               --argc;
-               ++argv;
-       }
-
        /* found - check max args */
        if (argc > cmdtp->maxargs)
                rc = CMD_RET_USAGE;
@@ -548,7 +593,7 @@ command_ret_t cmd_process(uint_fast8_t flag, int argc, char * const argv[],
        /* If OK so far, then do the command */
        if (!rc) {
                rc = cmd_call(cmdtp, flag, argc, argv);
-               *repeatable &= (cmdtp->flags & CTBL_REPEAT) != 0;
+               *repeatable &= (cmdtp->flags & CTBL_RPT) != 0;
        }
        if (rc == CMD_RET_USAGE)
                rc = cmd_usage(cmdtp);