]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cli.c
Integrate fatfs. Add some sd card test commands.
[z180-stamp.git] / avr / cli.c
index 44cf5b8260b6aaca8283ae30d0f7d7fb8988d09d..b310f793d97eb54d85db24129eecc4bb6996687b 100644 (file)
--- a/avr/cli.c
+++ b/avr/cli.c
@@ -43,137 +43,138 @@ static int cli_parse_line(char *line, char *argv[])
        return nargs;
 }
 
-static void process_macros(const char *input, char *output)
+static
+void append_char(uint_fast8_t pass, char **p, char c)
 {
-       char c, prev;
-       const char *varname_start = NULL;
-#if 0 && (CONFIG_SYS_CBSIZE < __UINT_FAST8_MAX__)
-       uint_fast8_t inputcnt = strlen(input);
-       uint_fast8_t outputcnt = CONFIG_SYS_CBSIZE;
-#else
-       int inputcnt = strlen(input);
-       int outputcnt = CONFIG_SYS_CBSIZE;
-#endif
-       uint_fast8_t state = 0;         /* 0 = waiting for '$'  */
-
-       /* 1 = waiting for '(' or '{' */
-       /* 2 = waiting for ')' or '}' */
-       /* 3 = waiting for '''  */
-       char *output_start = output;
-
-       debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input),
-                    input);
-
-       prev = '\0';            /* previous character   */
-
-       while (inputcnt && outputcnt) {
-               c = *input++;
-               inputcnt--;
-
-               if (state != 3) {
-                       /* remove one level of escape characters */
-                       if ((c == '\\') && (prev != '\\')) {
-                               if (inputcnt-- == 0)
-                                       break;
-                               prev = c;
-                               c = *input++;
-                       }
+
+       if (pass) {
+               **p = c;
+       }
+       ++(*p);
+}
+
+static
+char *process_macros(char *input, char *output)
+{
+       char c, prev, *inp, *outp;
+       const char *varname = NULL;
+
+       for(uint_fast8_t pass = 0; pass < 2; pass++)
+       {
+               uint_fast8_t state = 0;         /* 0 = waiting for '$'  */
+               /* 1 = waiting for '{' */
+               /* 2 = waiting for '}' */
+               /* 3 = waiting for ''' */
+
+               if (pass == 0) {
+                       outp = output;
+               } else {
+                       int outputlen = outp - output;
+                       outp = xrealloc(output, outputlen);
+                       output = outp;
                }
 
-               switch (state) {
-               case 0: /* Waiting for (unescaped) $    */
-                       if ((c == '\'') && (prev != '\\')) {
-                               state = 3;
-                               break;
-                       }
-                       if ((c == '$') && (prev != '\\')) {
-                               state++;
-                       } else {
-                               *(output++) = c;
-                               outputcnt--;
-                       }
-                       break;
-               case 1: /* Waiting for (        */
-                       if (c == '(' || c == '{') {
-                               state++;
-                               varname_start = input;
-                       } else {
-                               state = 0;
-                               *(output++) = '$';
-                               outputcnt--;
-
-                               if (outputcnt) {
-                                       *(output++) = c;
-                                       outputcnt--;
+               inp = input;
+               prev = '\0';            /* previous character   */
+
+               debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(inp),
+                            inp);
+
+               while ((c = *inp++) != '\0') {
+
+                       if (state != 3) {
+                               /* remove one level of escape characters */
+                               if ((c == '\\') && (prev != '\\')) {
+                                       if (*inp == '\0')
+                                               break;
+                                       prev = c;
+                                       c = *inp++;
                                }
                        }
-                       break;
-               case 2: /* Waiting for )        */
-                       if (c == ')' || c == '}') {
-                               char envname[CONFIG_SYS_ENV_NAMELEN+1], *envval;
-                               /* Varname # of chars */
-                               uint_fast8_t envcnt = input - varname_start - 1;
-                               if (envcnt > CONFIG_SYS_ENV_NAMELEN)
-                                       envcnt = CONFIG_SYS_ENV_NAMELEN;
-
-                               memcpy(envname, varname_start, envcnt);
-                               envname[envcnt] = '\0';
-
-                               /* Get its value */
-                               envval = getenv(envname);
-
-                               /* Copy into the line if it exists */
-                               if (envval != NULL)
-                                       while ((*envval) && outputcnt) {
-                                               *(output++) = *(envval++);
-                                               outputcnt--;
-                                       }
-                               /* Look for another '$' */
-                               state = 0;
-                       }
-                       break;
-               case 3: /* Waiting for '        */
-                       if ((c == '\'') && (prev != '\\')) {
-                               state = 0;
-                       } else {
-                               *(output++) = c;
-                               outputcnt--;
+
+                       switch (state) {
+                       case 0: /* Waiting for (unescaped) $    */
+                               if ((c == '\'') && (prev != '\\')) {
+                                       state = 3;
+                                       break;
+                               }
+                               if ((c == '$') && (prev != '\\'))
+                                       state++;
+                               else
+                                       append_char(pass, &outp, c);
+                               break;
+                       case 1: /* Waiting for {        */
+                               if (c == '{') {
+                                       state++;
+                                       varname = inp;
+                               } else {
+                                       state = 0;
+                                       append_char(pass, &outp, '$');
+                                       append_char(pass, &outp, c);
+                               }
+                               break;
+                       case 2: /* Waiting for }        */
+                               if (c == '}') {
+                                       /* Terminate variable name */
+                                       *(inp-1) = '\0';
+                                       const char *envval = getenv(varname);
+                                       *(inp-1) = '}';
+                                       /* Copy into the line if it exists */
+                                       if (envval != NULL)
+                                               while (*envval)
+                                                       append_char(pass, &outp, *(envval++));
+                                       /* Look for another '$' */
+                                       state = 0;
+                               }
+                               break;
+                       case 3: /* Waiting for '        */
+                               if ((c == '\'') && (prev != '\\'))
+                                       state = 0;
+                               else
+                                       append_char(pass, &outp, c);
+                               break;
                        }
-                       break;
+                       prev = c;
                }
-               prev = c;
-       }
 
-       if (outputcnt)
-               *output = 0;
-       else
-               *(output - 1) = 0;
+               append_char(pass, &outp, 0);
+       }
 
        debug_parser("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
-                    strlen(output_start), output_start);
+                    strlen(output), output);
+
+       return output;
 }
 
- /*
+/**
+ *
+ *
  * WARNING:
  *
  * We must create a temporary copy of the command since the command we get
  * may be the result from getenv(), which returns a pointer directly to
  * the environment data, which may change magicly when the command we run
  * creates or modifies environment variables (like "bootp" does).
+ *
+ *
+ * @param cmd
+ * @param flag
+ * @returns
+ *
  */
 static int cli_run_command(const char *cmd, int flag)
 {
        char *cmdbuf;                   /* working copy of cmd          */
        char *token;                    /* start of token in cmdbuf     */
        char *sep;                      /* end of token (separator) in cmdbuf */
-       char *finaltoken;
+       char *finaltoken = NULL;        /* token after macro expansion  */
        char *str;
        char *argv[CONFIG_SYS_MAXARGS + 1];     /* NULL terminated      */
        int argc;
        uint_fast8_t inquotes, repeatable = 1;
        int rc = 0;
 
-       debug_parser("[RUN_COMMAND] cmd[%p]=\"%s\"\n", 
+       debug_parser("[RUN_COMMAND] cmd[%p]=\"%s\"\n",
                        cmd, cmd ? cmd : "NULL");
 
        clear_ctrlc();          /* forget any previous Control C */
@@ -181,11 +182,10 @@ static int cli_run_command(const char *cmd, int flag)
        if (!cmd || !*cmd)
                return -1;      /* empty command */
 
+       cmdbuf = strdup(cmd);
+       if (!cmdbuf)
+               return -1;      /* not enough memory */
 
-       cmdbuf = xmalloc(strlen(cmd) + 1);
-       finaltoken = xmalloc(CONFIG_SYS_CBSIZE);
-
-       strcpy(cmdbuf, cmd);
        str = cmdbuf;
 
        /* Process separators and check for invalid
@@ -223,7 +223,7 @@ static int cli_run_command(const char *cmd, int flag)
                debug_parser("token: \"%s\"\n", token);
 
                /* find macros in this token and replace them */
-               process_macros(token, finaltoken);
+               finaltoken = process_macros(token, finaltoken);
 
                /* Extract arguments */
                argc = cli_parse_line(finaltoken, argv);
@@ -232,7 +232,7 @@ static int cli_run_command(const char *cmd, int flag)
                        continue;
                }
 
-               if (cmd_process(flag, argc, argv, &repeatable))
+               if (cmd_process(flag, argc, argv, &repeatable) != CMD_RET_SUCCESS)
                        rc = -1;
 
                /* Did the user stop this? */
@@ -290,21 +290,16 @@ static int run_command_repeatable(const char *cmd, int flag)
 int run_command_list(const char *cmd, int len)
 {
        (void) len;
-       
+
        return cli_run_command_list(cmd);
 }
 
 /****************************************************************************/
 
-#define DYN_BUFFER 1
 
 void cli_loop(void)
 {
-#if DYN_BUFFER
        char *lastcommand = NULL;
-#else
-       static char lastcommand[CONFIG_SYS_CBSIZE];
-#endif
        int len;
        int flag;
        int rc = 1;
@@ -314,15 +309,8 @@ void cli_loop(void)
 
                flag = 0;       /* assume no special flags for now */
                if (len > 0) {
-#if DYN_BUFFER
-                       lastcommand = (char *) xrealloc(lastcommand, len+1);
-                       if (lastcommand != NULL) {
-                               strncpy(lastcommand, console_buffer, len+1);
-                               lastcommand[len] = '\0';
-                       }
-#else
-                       strcpy(lastcommand, console_buffer);
-#endif
+                       free (lastcommand);
+                       lastcommand = strdup(console_buffer);
                } else if (len == 0)
                        flag |= CMD_FLAG_REPEAT;
 
@@ -333,18 +321,14 @@ void cli_loop(void)
 
                if (rc <= 0) {
                        /* invalid command or not repeatable, forget it */
-#if DYN_BUFFER
                        free(lastcommand);
                        lastcommand = NULL;
-#else
-                       lastcommand[0] = 0;
-#endif
                }
        }
 }
 
 
-int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        int i;
        (void) cmdtp;
@@ -358,12 +342,12 @@ int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                arg = getenv(argv[i]);
                if (arg == NULL) {
                        printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[i]);
-                       return 1;
+                       return CMD_RET_FAILURE;
                }
 
                if (run_command(arg, flag) != 0)
-                       return 1;
+                       return CMD_RET_FAILURE;
        }
-       return 0;
+       return CMD_RET_SUCCESS;
 }