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 */
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
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);
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? */
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;
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;
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;
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;
}