diff -ruNb u-boot-original/README u-boot-work/README --- u-boot-original/README 2004-04-16 02:14:49.000000000 +0300 +++ u-boot-work/README 2004-04-16 19:28:29.278549688 +0300 @@ -1317,6 +1317,14 @@ of the backslashes before semicolons and special symbols. + Note 2: + CONFIG_HUSH_OLD_PARSER_COMPATIBLE + + Define this in order to allow compatibility between the + original parser; allows to enclose variables with '(' + and ')'. + Example $ipaddr = ${ipaddr} = $(ipaddr). + - Default Environment: CONFIG_EXTRA_ENV_SETTINGS diff -ruNb u-boot-original/common/command.c u-boot-work/common/command.c --- u-boot-original/common/command.c 2004-04-15 21:22:42.000000000 +0300 +++ u-boot-work/common/command.c 2004-04-16 18:38:02.507688800 +0300 @@ -74,6 +74,159 @@ " - echo args to console; \\c suppresses newline\n" ); +#ifdef CFG_HUSH_PARSER + +int +do_test (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char **ap; + int left, adv, expr, last_expr, neg, last_cmp; + + /* args? */ + if (argc < 3) + return 1; + +#if 0 + { + printf("test:"); + left = 1; + while (argv[left]) + printf(" %s", argv[left++]); + } +#endif + + last_expr = 0; + left = argc - 1; ap = argv + 1; + if (left > 0 && strcmp(ap[0], "!") == 0) { + neg = 1; + ap++; + left--; + } else + neg = 0; + + expr = -1; + last_cmp = -1; + last_expr = -1; + while (left > 0) { + + if (strcmp(ap[0], "-o") == 0 || strcmp(ap[0], "-a") == 0) + adv = 1; + else if (strcmp(ap[0], "-z") == 0 || strcmp(ap[0], "-n") == 0) + adv = 2; + else + adv = 3; + + if (left < adv) { + expr = 1; + break; + } + + if (adv == 1) { + if (strcmp(ap[0], "-o") == 0) { + last_expr = expr; + last_cmp = 0; + } else if (strcmp(ap[0], "-a") == 0) { + last_expr = expr; + last_cmp = 1; + } else { + expr = 1; + break; + } + } + + if (adv == 2) { + if (strcmp(ap[0], "-z") == 0) + expr = strlen(ap[1]) == 0 ? 0 : 1; + else if (strcmp(ap[0], "-n") == 0) + expr = strlen(ap[1]) == 0 ? 1 : 0; + else { + expr = 1; + break; + } + + if (last_cmp == 0) + expr = last_expr || expr; + else if (last_cmp == 1) + expr = last_expr && expr; + last_cmp = -1; + } + + if (adv == 3) { + if (strcmp(ap[1], "=") == 0) + expr = strcmp(ap[0], ap[2]) == 0; + else if (strcmp(ap[1], "!=") == 0) + expr = strcmp(ap[0], ap[2]) != 0; + else if (strcmp(ap[1], ">") == 0) + expr = strcmp(ap[0], ap[2]) > 0; + else if (strcmp(ap[1], "<") == 0) + expr = strcmp(ap[0], ap[2]) < 0; + else if (strcmp(ap[1], "-eq") == 0) + expr = simple_strtol(ap[0], NULL, 10) == simple_strtol(ap[2], NULL, 10); + else if (strcmp(ap[1], "-ne") == 0) + expr = simple_strtol(ap[0], NULL, 10) != simple_strtol(ap[2], NULL, 10); + else if (strcmp(ap[1], "-lt") == 0) + expr = simple_strtol(ap[0], NULL, 10) < simple_strtol(ap[2], NULL, 10); + else if (strcmp(ap[1], "-le") == 0) + expr = simple_strtol(ap[0], NULL, 10) <= simple_strtol(ap[2], NULL, 10); + else if (strcmp(ap[1], "-gt") == 0) + expr = simple_strtol(ap[0], NULL, 10) > simple_strtol(ap[2], NULL, 10); + else if (strcmp(ap[1], "-ge") == 0) + expr = simple_strtol(ap[0], NULL, 10) >= simple_strtol(ap[2], NULL, 10); + else { + expr = 1; + break; + } + + if (last_cmp == 0) + expr = last_expr || expr; + else if (last_cmp == 1) + expr = last_expr && expr; + last_cmp = -1; + } + + ap += adv; left -= adv; + } + + if (neg) + expr = !expr; + + expr = !expr; + +#if 0 + printf(": returns %d\n", expr); +#endif + + return expr; +} + +U_BOOT_CMD( + test, CFG_MAXARGS, 1, do_test, + "test - minimal test like /bin/sh\n", + "[args..]\n" + " - test functionality\n" +); + +int +do_exit (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int r; + + r = 0; + if (argc > 1) + r = simple_strtoul(argv[1], NULL, 10); + + return -r - 2; +} + +U_BOOT_CMD( + exit, 2, 1, do_exit, + "exit - exit script\n", + " - exit functionality\n" +); + + +#endif + /* * Use puts() instead of printf() to avoid printf buffer overflow * for long help messages diff -ruNb u-boot-original/common/hush.c u-boot-work/common/hush.c --- u-boot-original/common/hush.c 2004-04-12 17:31:44.000000000 +0300 +++ u-boot-work/common/hush.c 2004-04-16 19:02:10.753521968 +0300 @@ -290,6 +290,7 @@ unsigned int global_argc; #endif unsigned int last_return_code; +int nesting_level; #ifndef __U_BOOT__ extern char **environ; /* This is in , but protected with __USE_GNU */ #endif @@ -416,7 +417,9 @@ static int b_addchr(o_string *o, int ch); static void b_reset(o_string *o); static int b_addqchr(o_string *o, int ch, int quote); +#ifndef __U_BOOT__ static int b_adduint(o_string *o, unsigned int i); +#endif /* in_str manipulations: */ static int static_get(struct in_str *i); static int static_peek(struct in_str *i); @@ -936,6 +939,7 @@ return p + 1; } +#ifndef __U_BOOT__ static int b_adduint(o_string *o, unsigned int i) { int r; @@ -944,6 +948,7 @@ do r=b_addchr(o, *p++); while (r==0 && *p); return r; } +#endif static int static_get(struct in_str *i) { @@ -1921,6 +1926,10 @@ } last_return_code=rcode; #else + if (rcode < -1) { + last_return_code = -rcode - 2; + return -2; /* exit */ + } last_return_code=(rcode == 0) ? 0 : 1; #endif #ifndef __U_BOOT__ @@ -2145,6 +2154,10 @@ } #endif +#ifdef __U_BOOT__ +static char *get_dollar_var(char ch); +#endif + /* This is used to get/check local shell variables */ static char *get_local_var(const char *s) { @@ -2152,6 +2165,12 @@ if (!s) return NULL; + +#ifdef __U_BOOT__ + if (*s == '$') + return get_dollar_var(s[1]); +#endif + for (cur = top_vars; cur; cur=cur->next) if(strcmp(cur->name, s)==0) return cur->value; @@ -2168,12 +2187,19 @@ int result=0; struct variables *cur; +#ifdef __U_BOOT__ + /* might be possible! */ + if (!isalpha(*s)) + return -1; +#endif + name=strdup(s); #ifdef __U_BOOT__ if (getenv(name) != NULL) { printf ("ERROR: " "There is a global environment variable with the same name.\n"); + free(name); return -1; } #endif @@ -2278,7 +2304,10 @@ static int is_assignment(const char *s) { - if (s==NULL || !isalpha(*s)) return 0; + if (s == NULL) + return 0; + + if (!isalpha(*s)) return 0; ++s; while(isalnum(*s) || *s=='_') ++s; return *s=='='; @@ -2749,15 +2778,35 @@ * see the bash man page under "Parameter Expansion" */ static char *lookup_param(char *src) { - char *p=NULL; - if (src) { + char *p; + + if (!src) + return NULL; + p = getenv(src); if (!p) p = get_local_var(src); - } + return p; } +#ifdef __U_BOOT__ +static char *get_dollar_var(char ch) +{ + static char buf[40]; + + buf[0] = '\0'; + switch (ch) { + case '?': + sprintf(buf, "%u", (unsigned int)last_return_code); + break; + default: + return NULL; + } + return buf; +} +#endif + /* return code: 0 for OK, 1 for syntax error */ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input) { @@ -2769,6 +2818,7 @@ #ifndef __U_BOOT__ char sep[]=" "; #endif + char match; int ch = input->peek(input); /* first character after the $ */ debug_printf("handle_dollar: ch=%c\n",ch); if (isalpha(ch)) { @@ -2799,7 +2849,15 @@ break; #endif case '?': +#ifndef __U_BOOT__ b_adduint(dest,last_return_code); +#else + ctx->child->sp++; + b_addchr(dest, SPECIAL_VAR_SYMBOL); + b_addchr(dest, '$'); + b_addchr(dest, '?'); + b_addchr(dest, SPECIAL_VAR_SYMBOL); +#endif advance = 1; break; #ifndef __U_BOOT__ @@ -2809,14 +2867,18 @@ break; #endif case '{': +#if defined(__U_BOOT__) && defined(CONFIG_HUSH_OLD_PARSER_COMPATIBLE) + case '(': +#endif + match = ch == '{' ? '}' : ')'; b_addchr(dest, SPECIAL_VAR_SYMBOL); ctx->child->sp++; b_getch(input); /* XXX maybe someone will try to escape the '}' */ - while(ch=b_getch(input),ch!=EOF && ch!='}') { + while(ch=b_getch(input),ch!=EOF && ch!=match) { b_addchr(dest,ch); } - if (ch != '}') { + if (ch != match) { syntax(); return 1; } @@ -2885,8 +2947,10 @@ if (input->__promptme == 0) return 1; #endif next = (ch == '\n') ? 0 : b_peek(input); - debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d\n", - ch,ch,m,dest->quote); + + debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n", + ch >= ' ' ? ch : '.',ch,m,dest->quote,ctx->stack == NULL ? '*' : '.'); + if (m==0 || ((m==1 || m==2) && dest->quote)) { b_addqchr(dest, ch, dest->quote); } else { @@ -3107,7 +3171,18 @@ #ifndef __U_BOOT__ run_list(ctx.list_head); #else - if (((code = run_list(ctx.list_head)) == -1)) + code = run_list(ctx.list_head); + if (code == -2) { /* exit */ + b_free(&temp); + code = 0; + /* XXX hackish way to not allow exit from main loop */ + if (inp->peek == file_peek) { + printf("exit not allowed from main input shell.\n"); + continue; + } + break; + } + if (code == -1) flag_repeat = 0; #endif } else {