diff options
| author | Ron Yorston <rmy@pobox.com> | 2021-10-13 14:37:51 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2021-10-13 14:37:51 +0100 |
| commit | 0ecf1aea459571b48dc68ddc2b7b9265740fa960 (patch) | |
| tree | 491d6184a44b8b525a4ca35759d622aecd7f6344 /shell | |
| parent | 4859ddcb20616718efbea12c6bf8b27c469b68de (diff) | |
| parent | aaf3d5ba74c5da97ff80b61f30cb8dd225d39096 (diff) | |
| download | busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.gz busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.bz2 busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.zip | |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 68 | ||||
| -rw-r--r-- | shell/ash_test/ash-arith/arith-postinc.right | 3 | ||||
| -rwxr-xr-x | shell/ash_test/ash-arith/arith-postinc.tests | 4 | ||||
| -rw-r--r-- | shell/ash_test/ash-arith/arith.right | 78 | ||||
| -rwxr-xr-x | shell/ash_test/ash-arith/arith.tests | 55 | ||||
| -rwxr-xr-x | shell/ash_test/ash-arith/arith1.sub | 4 | ||||
| -rwxr-xr-x | shell/ash_test/ash-arith/arith2.sub | 22 | ||||
| -rw-r--r-- | shell/ash_test/ash-comm/comm.right | 6 | ||||
| -rwxr-xr-x | shell/ash_test/ash-comm/comm.tests | 20 | ||||
| -rw-r--r-- | shell/hush.c | 48 | ||||
| -rw-r--r-- | shell/hush_test/hush-arith/arith-postinc.right | 3 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith-postinc.tests | 4 | ||||
| -rw-r--r-- | shell/hush_test/hush-arith/arith.right | 37 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith.tests | 40 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith1.sub | 4 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith2.sub | 22 | ||||
| -rw-r--r-- | shell/hush_test/hush-comm/comm.right | 6 | ||||
| -rwxr-xr-x | shell/hush_test/hush-comm/comm.tests | 20 | ||||
| -rw-r--r-- | shell/math.c | 71 |
19 files changed, 331 insertions, 184 deletions
diff --git a/shell/ash.c b/shell/ash.c index 9214982c1..98da20f8a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -351,19 +351,6 @@ typedef long arith_t; | |||
| 351 | # error "Do not even bother, ash will not run on NOMMU machine" | 351 | # error "Do not even bother, ash will not run on NOMMU machine" |
| 352 | #endif | 352 | #endif |
| 353 | 353 | ||
| 354 | /* We use a trick to have more optimized code (fewer pointer reloads): | ||
| 355 | * ash.c: extern struct globals *const ash_ptr_to_globals; | ||
| 356 | * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; | ||
| 357 | * This way, compiler in ash.c knows the pointer can not change. | ||
| 358 | * | ||
| 359 | * However, this may break on weird arches or toolchains. In this case, | ||
| 360 | * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable | ||
| 361 | * this optimization. | ||
| 362 | */ | ||
| 363 | #ifndef BB_GLOBAL_CONST | ||
| 364 | # define BB_GLOBAL_CONST const | ||
| 365 | #endif | ||
| 366 | |||
| 367 | #if ENABLE_PLATFORM_MINGW32 | 354 | #if ENABLE_PLATFORM_MINGW32 |
| 368 | # define FORKSHELL_DEBUG 0 | 355 | # define FORKSHELL_DEBUG 0 |
| 369 | 356 | ||
| @@ -693,8 +680,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
| 693 | #endif | 680 | #endif |
| 694 | 681 | ||
| 695 | #define INIT_G_misc() do { \ | 682 | #define INIT_G_misc() do { \ |
| 696 | (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ | 683 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \ |
| 697 | barrier(); \ | ||
| 698 | savestatus = -1; \ | 684 | savestatus = -1; \ |
| 699 | curdir = nullstr; \ | 685 | curdir = nullstr; \ |
| 700 | physdir = nullstr; \ | 686 | physdir = nullstr; \ |
| @@ -1783,8 +1769,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; | |||
| 1783 | #define g_stacknleft (G_memstack.g_stacknleft) | 1769 | #define g_stacknleft (G_memstack.g_stacknleft) |
| 1784 | #define stackbase (G_memstack.stackbase ) | 1770 | #define stackbase (G_memstack.stackbase ) |
| 1785 | #define INIT_G_memstack() do { \ | 1771 | #define INIT_G_memstack() do { \ |
| 1786 | (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ | 1772 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \ |
| 1787 | barrier(); \ | ||
| 1788 | g_stackp = &stackbase; \ | 1773 | g_stackp = &stackbase; \ |
| 1789 | g_stacknxt = stackbase.space; \ | 1774 | g_stacknxt = stackbase.space; \ |
| 1790 | g_stacknleft = MINSIZE; \ | 1775 | g_stacknleft = MINSIZE; \ |
| @@ -2445,8 +2430,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; | |||
| 2445 | #endif | 2430 | #endif |
| 2446 | #define INIT_G_var() do { \ | 2431 | #define INIT_G_var() do { \ |
| 2447 | unsigned i; \ | 2432 | unsigned i; \ |
| 2448 | (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ | 2433 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \ |
| 2449 | barrier(); \ | ||
| 2450 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ | 2434 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ |
| 2451 | varinit[i].flags = varinit_data[i].flags; \ | 2435 | varinit[i].flags = varinit_data[i].flags; \ |
| 2452 | varinit[i].var_text = varinit_data[i].var_text; \ | 2436 | varinit[i].var_text = varinit_data[i].var_text; \ |
| @@ -7840,14 +7824,19 @@ subevalvar(char *start, char *str, int strloc, | |||
| 7840 | if ((unsigned)len > (orig_len - pos)) | 7824 | if ((unsigned)len > (orig_len - pos)) |
| 7841 | len = orig_len - pos; | 7825 | len = orig_len - pos; |
| 7842 | 7826 | ||
| 7843 | for (vstr = startp; pos; vstr++, pos--) { | 7827 | if (!quotes) { |
| 7844 | if (quotes && (unsigned char)*vstr == CTLESC) | 7828 | loc = mempcpy(startp, startp + pos, len); |
| 7829 | } else { | ||
| 7830 | for (vstr = startp; pos != 0; pos--) { | ||
| 7831 | if ((unsigned char)*vstr == CTLESC) | ||
| 7832 | vstr++; | ||
| 7845 | vstr++; | 7833 | vstr++; |
| 7846 | } | 7834 | } |
| 7847 | for (loc = startp; len; len--) { | 7835 | for (loc = startp; len != 0; len--) { |
| 7848 | if (quotes && (unsigned char)*vstr == CTLESC) | 7836 | if ((unsigned char)*vstr == CTLESC) |
| 7837 | *loc++ = *vstr++; | ||
| 7849 | *loc++ = *vstr++; | 7838 | *loc++ = *vstr++; |
| 7850 | *loc++ = *vstr++; | 7839 | } |
| 7851 | } | 7840 | } |
| 7852 | *loc = '\0'; | 7841 | *loc = '\0'; |
| 7853 | goto out; | 7842 | goto out; |
| @@ -7901,7 +7890,7 @@ subevalvar(char *start, char *str, int strloc, | |||
| 7901 | #if BASH_PATTERN_SUBST | 7890 | #if BASH_PATTERN_SUBST |
| 7902 | workloc = expdest - (char *)stackblock(); | 7891 | workloc = expdest - (char *)stackblock(); |
| 7903 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 7892 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
| 7904 | size_t no_meta_len; | 7893 | size_t no_meta_len, first_escaped; |
| 7905 | int len; | 7894 | int len; |
| 7906 | char *idx, *end; | 7895 | char *idx, *end; |
| 7907 | 7896 | ||
| @@ -7919,28 +7908,34 @@ subevalvar(char *start, char *str, int strloc, | |||
| 7919 | if (str[0] == '\0') | 7908 | if (str[0] == '\0') |
| 7920 | goto out1; | 7909 | goto out1; |
| 7921 | 7910 | ||
| 7922 | no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); | 7911 | first_escaped = (str[0] == '\\' && str[1]); |
| 7912 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" | ||
| 7913 | * as literal too (as it is semi-common, and easy to accomodate | ||
| 7914 | * by just using str + 1). | ||
| 7915 | */ | ||
| 7916 | no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str); | ||
| 7923 | len = 0; | 7917 | len = 0; |
| 7924 | idx = startp; | 7918 | idx = startp; |
| 7925 | end = str - 1; | 7919 | end = str - 1; |
| 7926 | while (idx <= end) { | 7920 | while (idx <= end) { |
| 7927 | try_to_match: | 7921 | try_to_match: |
| 7928 | if (no_meta_len == 0) { | 7922 | if (no_meta_len == 0) { |
| 7929 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ | 7923 | /* pattern has meta chars, have to glob */ |
| 7930 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); | 7924 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); |
| 7931 | } else { | 7925 | } else { |
| 7932 | /* Testcase for very slow replace (performs about 22k replaces): | 7926 | /* Testcase for very slow replace (performs about 22k replaces): |
| 7933 | * x=:::::::::::::::::::::: | 7927 | * x=:::::::::::::::::::::: |
| 7934 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 7928 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
| 7935 | * echo "${x//:/|}" | 7929 | * echo "${x//:/|}" |
| 7930 | * To test "first_escaped" logic, replace : with *. | ||
| 7936 | */ | 7931 | */ |
| 7937 | if (strncmp(rmesc, str, no_meta_len) != 0) | 7932 | if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0) |
| 7938 | goto no_match; | 7933 | goto no_match; |
| 7939 | loc = idx; | 7934 | loc = idx; |
| 7940 | if (!quotes) { | 7935 | if (!quotes) { |
| 7941 | loc += no_meta_len; | 7936 | loc += no_meta_len - first_escaped; |
| 7942 | } else { | 7937 | } else { |
| 7943 | size_t n = no_meta_len; | 7938 | size_t n = no_meta_len - first_escaped; |
| 7944 | do { | 7939 | do { |
| 7945 | if ((unsigned char)*loc == CTLESC) | 7940 | if ((unsigned char)*loc == CTLESC) |
| 7946 | loc++; | 7941 | loc++; |
| @@ -11811,14 +11806,14 @@ static void freestrings(struct strpush *sp) | |||
| 11811 | INT_OFF; | 11806 | INT_OFF; |
| 11812 | do { | 11807 | do { |
| 11813 | struct strpush *psp; | 11808 | struct strpush *psp; |
| 11814 | 11809 | #if ENABLE_ASH_ALIAS | |
| 11815 | if (sp->ap) { | 11810 | if (sp->ap) { |
| 11816 | sp->ap->flag &= ~ALIASINUSE; | 11811 | sp->ap->flag &= ~ALIASINUSE; |
| 11817 | if (sp->ap->flag & ALIASDEAD) { | 11812 | if (sp->ap->flag & ALIASDEAD) { |
| 11818 | unalias(sp->ap->name); | 11813 | unalias(sp->ap->name); |
| 11819 | } | 11814 | } |
| 11820 | } | 11815 | } |
| 11821 | 11816 | #endif | |
| 11822 | psp = sp; | 11817 | psp = sp; |
| 11823 | sp = sp->spfree; | 11818 | sp = sp->spfree; |
| 11824 | 11819 | ||
| @@ -15497,7 +15492,7 @@ init(void) | |||
| 15497 | 15492 | ||
| 15498 | 15493 | ||
| 15499 | //usage:#define ash_trivial_usage | 15494 | //usage:#define ash_trivial_usage |
| 15500 | //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" | 15495 | //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" |
| 15501 | //////// comes from ^^^^^^^^^^optletters | 15496 | //////// comes from ^^^^^^^^^^optletters |
| 15502 | //usage:#define ash_full_usage "\n\n" | 15497 | //usage:#define ash_full_usage "\n\n" |
| 15503 | //usage: "Unix shell interpreter" | 15498 | //usage: "Unix shell interpreter" |
| @@ -15764,13 +15759,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
| 15764 | } | 15759 | } |
| 15765 | state2: | 15760 | state2: |
| 15766 | state = 3; | 15761 | state = 3; |
| 15767 | if ( | 15762 | if (iflag |
| 15768 | #if ENABLE_PLATFORM_POSIX | 15763 | #if ENABLE_PLATFORM_POSIX |
| 15769 | #ifndef linux | 15764 | #ifndef linux |
| 15770 | getuid() == geteuid() && getgid() == getegid() && | 15765 | && getuid() == geteuid() && getgid() == getegid() |
| 15771 | #endif | 15766 | #endif |
| 15772 | #endif | 15767 | #endif |
| 15773 | iflag | ||
| 15774 | ) { | 15768 | ) { |
| 15775 | const char *shinit = lookupvar("ENV"); | 15769 | const char *shinit = lookupvar("ENV"); |
| 15776 | if (shinit != NULL && *shinit != '\0') | 15770 | if (shinit != NULL && *shinit != '\0') |
diff --git a/shell/ash_test/ash-arith/arith-postinc.right b/shell/ash_test/ash-arith/arith-postinc.right index c95ce02bf..5cd4ba6b4 100644 --- a/shell/ash_test/ash-arith/arith-postinc.right +++ b/shell/ash_test/ash-arith/arith-postinc.right | |||
| @@ -2,4 +2,7 @@ | |||
| 2 | 1 1 | 2 | 1 1 |
| 3 | 1 1 | 3 | 1 1 |
| 4 | 1 1 | 4 | 1 1 |
| 5 | 6 6 | ||
| 6 | 7 7 | ||
| 7 | 7 7 | ||
| 5 | Ok:0 | 8 | Ok:0 |
diff --git a/shell/ash_test/ash-arith/arith-postinc.tests b/shell/ash_test/ash-arith/arith-postinc.tests index 3fd9bfed5..f2ae778df 100755 --- a/shell/ash_test/ash-arith/arith-postinc.tests +++ b/shell/ash_test/ash-arith/arith-postinc.tests | |||
| @@ -2,4 +2,8 @@ echo 1 $((0++1)) | |||
| 2 | echo 1 $((0--1)) | 2 | echo 1 $((0--1)) |
| 3 | x=-1; echo 1 $((0-$x)) | 3 | x=-1; echo 1 $((0-$x)) |
| 4 | x=+1; echo 1 $((0+$x)) | 4 | x=+1; echo 1 $((0+$x)) |
| 5 | a=3 | ||
| 6 | echo 6 $((a+++3)) # a++ + 3 | ||
| 7 | echo 7 $(((a)+++3)) # a + + + 3 | ||
| 8 | echo 7 $(((a)+++3)) # a + + + 3 | ||
| 5 | echo Ok:$? | 9 | echo Ok:$? |
diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 6936f1269..61fcab55e 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right | |||
| @@ -43,40 +43,60 @@ Format: 'expected actual' | |||
| 43 | 4 4 | 43 | 4 4 |
| 44 | 29 29 | 44 | 29 29 |
| 45 | 5 5 | 45 | 5 5 |
| 46 | unary plus, minus | ||
| 46 | -4 -4 | 47 | -4 -4 |
| 47 | 4 4 | 48 | 4 4 |
| 49 | conditional expressions | ||
| 48 | 1 1 | 50 | 1 1 |
| 49 | 32 32 | 51 | 32 32 |
| 50 | 32 32 | 52 | 32 32 |
| 51 | 1 1 | 53 | 1 1 |
| 52 | 1 1 | 54 | 1 1 |
| 53 | 32 32 | 55 | 32 32 |
| 56 | check that the unevaluated part of the ternary operator does not do evaluation or assignment | ||
| 54 | 20 20 | 57 | 20 20 |
| 55 | 30 30 | 58 | 30 30 |
| 56 | 20 20 | 59 | 20 20 |
| 57 | 30 30 | 60 | 30 30 |
| 58 | ./arith.tests: line 117: arithmetic syntax error | 61 | check precedence of assignment vs. conditional operator |
| 62 | ./arith.tests: line 116: arithmetic syntax error | ||
| 63 | check precedence of assignment vs. conditional operator | ||
| 64 | associativity of assignment-operator operator | ||
| 59 | 6 6 | 65 | 6 6 |
| 60 | 6,5,3 6,5,3 | 66 | 6,5,3 6,5,3 |
| 67 | octal, hex | ||
| 61 | 263 263 | 68 | 263 263 |
| 62 | 255 255 | 69 | 255 255 |
| 63 | 40 40 | 70 | 40 40 |
| 64 | ./arith.tests: line 163: arithmetic syntax error | 71 | other bases |
| 65 | ./arith.tests: line 165: divide by zero | 72 | 10 10 |
| 66 | ./arith.tests: let: line 166: arithmetic syntax error | 73 | 10 10 |
| 67 | ./arith.tests: line 167: arithmetic syntax error | 74 | 10 10 |
| 68 | ./arith.tests: let: line 168: arithmetic syntax error | 75 | 10 10 |
| 76 | 10 10 | ||
| 77 | 10 10 | ||
| 78 | 36 36 | ||
| 79 | 36 36 | ||
| 80 | 62 62 | ||
| 81 | 63 63 | ||
| 82 | missing number after base | ||
| 83 | 0 0 | ||
| 84 | ./arith.tests: line 162: arithmetic syntax error | ||
| 85 | ./arith.tests: line 164: divide by zero | ||
| 86 | ./arith.tests: let: line 165: arithmetic syntax error | ||
| 87 | ./arith.tests: line 166: arithmetic syntax error | ||
| 88 | ./arith.tests: let: line 167: arithmetic syntax error | ||
| 69 | abc | 89 | abc |
| 70 | def | 90 | def |
| 71 | ghi | 91 | ghi |
| 72 | ./arith.tests: line 191: arithmetic syntax error | 92 | ./arith.tests: line 190: arithmetic syntax error |
| 73 | 16 16 | 93 | 16 16 |
| 74 | ./arith.tests: line 196: arithmetic syntax error | 94 | ./arith.tests: line 195: arithmetic syntax error |
| 75 | ./arith.tests: line 197: malformed ?: operator | 95 | ./arith.tests: line 196: malformed ?: operator |
| 76 | ./arith.tests: line 198: arithmetic syntax error | 96 | ./arith.tests: line 197: arithmetic syntax error |
| 77 | 9 9 | 97 | 9 9 |
| 78 | ./arith.tests: line 205: arithmetic syntax error | 98 | ./arith.tests: line 204: arithmetic syntax error |
| 79 | ./arith.tests: line 208: arithmetic syntax error | 99 | ./arith.tests: line 207: arithmetic syntax error |
| 80 | 9 9 | 100 | 9 9 |
| 81 | 9 9 | 101 | 9 9 |
| 82 | 9 9 | 102 | 9 9 |
| @@ -97,14 +117,17 @@ ghi | |||
| 97 | 3 3 | 117 | 3 3 |
| 98 | 4 4 | 118 | 4 4 |
| 99 | 4 4 | 119 | 4 4 |
| 100 | ./arith.tests: line 257: arithmetic syntax error | 120 | 7 7 |
| 121 | ./arith.tests: line 256: arithmetic syntax error | ||
| 122 | ./arith.tests: line 258: arithmetic syntax error | ||
| 101 | ./arith.tests: line 259: arithmetic syntax error | 123 | ./arith.tests: line 259: arithmetic syntax error |
| 102 | ./arith.tests: line 260: arithmetic syntax error | 124 | ./arith.tests: line 261: arithmetic syntax error |
| 103 | ./arith.tests: line 262: arithmetic syntax error | 125 | ./arith.tests: line 262: arithmetic syntax error |
| 104 | ./arith.tests: line 263: arithmetic syntax error | ||
| 105 | 4 4 | 126 | 4 4 |
| 106 | 7 7 | 127 | 7 7 |
| 107 | -7 -7 | 128 | -7 -7 |
| 129 | 7 | ||
| 130 | 7 | ||
| 108 | ./arith1.sub: line 2: arithmetic syntax error | 131 | ./arith1.sub: line 2: arithmetic syntax error |
| 109 | ./arith1.sub: line 3: arithmetic syntax error | 132 | ./arith1.sub: line 3: arithmetic syntax error |
| 110 | ./arith1.sub: line 4: arithmetic syntax error | 133 | ./arith1.sub: line 4: arithmetic syntax error |
| @@ -119,11 +142,12 @@ ghi | |||
| 119 | 2 2 | 142 | 2 2 |
| 120 | -2 -2 | 143 | -2 -2 |
| 121 | 1 1 | 144 | 1 1 |
| 122 | ./arith1.sub: line 37: arithmetic syntax error | 145 | 7 |
| 123 | ./arith2.sub: line 2: arithmetic syntax error | 146 | 7 |
| 124 | ./arith2.sub: line 3: arithmetic syntax error | 147 | 7 |
| 125 | ./arith2.sub: line 4: arithmetic syntax error | 148 | 7 |
| 126 | ./arith2.sub: line 5: arithmetic syntax error | 149 | 7 |
| 150 | 7 | ||
| 127 | 5 5 | 151 | 5 5 |
| 128 | 1 1 | 152 | 1 1 |
| 129 | 6 6 | 153 | 6 6 |
| @@ -132,11 +156,17 @@ ghi | |||
| 132 | 1 1 | 156 | 1 1 |
| 133 | 4 4 | 157 | 4 4 |
| 134 | 0 0 | 158 | 0 0 |
| 135 | ./arith2.sub: line 42: arithmetic syntax error | 159 | -7 |
| 136 | ./arith2.sub: line 47: arithmetic syntax error | 160 | -7 |
| 161 | 7 | ||
| 162 | 7 | ||
| 163 | -7 -7 | ||
| 164 | -7 -7 | ||
| 165 | 7 7 | ||
| 166 | 7 7 | ||
| 137 | 8 12 | 167 | 8 12 |
| 138 | ./arith.tests: line 290: arithmetic syntax error | 168 | ./arith.tests: line 289: arithmetic syntax error |
| 139 | 42 | 169 | 42 |
| 140 | 42 | 170 | 42 |
| 141 | 42 | 171 | 42 |
| 142 | ./arith.tests: line 302: a[b[c]d]=e: not found | 172 | ./arith.tests: line 301: a[b[c]d]=e: not found |
diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests index d65758e7d..b9cb8ba4c 100755 --- a/shell/ash_test/ash-arith/arith.tests +++ b/shell/ash_test/ash-arith/arith.tests | |||
| @@ -75,11 +75,11 @@ echo 4 $(( iv &= 4 )) | |||
| 75 | echo 29 $(( iv += (jv + 9))) | 75 | echo 29 $(( iv += (jv + 9))) |
| 76 | echo 5 $(( (iv + 4) % 7 )) | 76 | echo 5 $(( (iv + 4) % 7 )) |
| 77 | 77 | ||
| 78 | # unary plus, minus | 78 | echo unary plus, minus |
| 79 | echo -4 $(( +4 - 8 )) | 79 | echo -4 $(( +4 - 8 )) |
| 80 | echo 4 $(( -4 + 8 )) | 80 | echo 4 $(( -4 + 8 )) |
| 81 | 81 | ||
| 82 | # conditional expressions | 82 | echo conditional expressions |
| 83 | echo 1 $(( 4<5 ? 1 : 32)) | 83 | echo 1 $(( 4<5 ? 1 : 32)) |
| 84 | echo 32 $(( 4>5 ? 1 : 32)) | 84 | echo 32 $(( 4>5 ? 1 : 32)) |
| 85 | echo 32 $(( 4>(2+3) ? 1 : 32)) | 85 | echo 32 $(( 4>(2+3) ? 1 : 32)) |
| @@ -87,8 +87,7 @@ echo 1 $(( 4<(2+3) ? 1 : 32)) | |||
| 87 | echo 1 $(( (2+2)<(2+3) ? 1 : 32)) | 87 | echo 1 $(( (2+2)<(2+3) ? 1 : 32)) |
| 88 | echo 32 $(( (2+2)>(2+3) ? 1 : 32)) | 88 | echo 32 $(( (2+2)>(2+3) ? 1 : 32)) |
| 89 | 89 | ||
| 90 | # check that the unevaluated part of the ternary operator does not do | 90 | echo check that the unevaluated part of the ternary operator does not do evaluation or assignment |
| 91 | # evaluation or assignment | ||
| 92 | x=i+=2 | 91 | x=i+=2 |
| 93 | y=j+=2 | 92 | y=j+=2 |
| 94 | #ash# declare -i i=1 j=1 | 93 | #ash# declare -i i=1 j=1 |
| @@ -109,20 +108,20 @@ echo 20 $((1 ? 20 : (x+=2))) | |||
| 109 | echo 30 $((0 ? (y+=2) : 30)) | 108 | echo 30 $((0 ? (y+=2) : 30)) |
| 110 | #ash# echo $i,$y # ash mishandles this | 109 | #ash# echo $i,$y # ash mishandles this |
| 111 | 110 | ||
| 112 | # check precedence of assignment vs. conditional operator | 111 | echo check precedence of assignment vs. conditional operator |
| 113 | # should be an error | 112 | # should be an error |
| 114 | #ash# declare -i x=2 | 113 | #ash# declare -i x=2 |
| 115 | x=2 | 114 | x=2 |
| 116 | #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: | 115 | #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: |
| 117 | ( y=$((1 ? 20 : x+=2)) ) | 116 | ( y=$((1 ? 20 : x+=2)) ) |
| 118 | 117 | ||
| 119 | # check precedence of assignment vs. conditional operator | 118 | echo check precedence of assignment vs. conditional operator |
| 120 | #ash# declare -i x=2 | 119 | #ash# declare -i x=2 |
| 121 | x=2 | 120 | x=2 |
| 122 | # ash says "line NNN: syntax error: 0 ? x+=2 : 20" | 121 | # ash says "line NNN: syntax error: 0 ? x+=2 : 20" |
| 123 | #ash# echo 20 $((0 ? x+=2 : 20)) | 122 | #ash# echo 20 $((0 ? x+=2 : 20)) |
| 124 | 123 | ||
| 125 | # associativity of assignment-operator operator | 124 | echo associativity of assignment-operator operator |
| 126 | #ash# declare -i i=1 j=2 k=3 | 125 | #ash# declare -i i=1 j=2 k=3 |
| 127 | i=1 | 126 | i=1 |
| 128 | j=2 | 127 | j=2 |
| @@ -130,7 +129,7 @@ k=3 | |||
| 130 | echo 6 $((i += j += k)) | 129 | echo 6 $((i += j += k)) |
| 131 | echo 6,5,3 $i,$j,$k | 130 | echo 6,5,3 $i,$j,$k |
| 132 | 131 | ||
| 133 | # octal, hex | 132 | echo octal, hex |
| 134 | echo 263 $(( 0x100 | 007 )) | 133 | echo 263 $(( 0x100 | 007 )) |
| 135 | echo 255 $(( 0xff )) | 134 | echo 255 $(( 0xff )) |
| 136 | #ash# echo 255 $(( 16#ff )) | 135 | #ash# echo 255 $(( 16#ff )) |
| @@ -139,25 +138,25 @@ echo 255 $(( 0xff )) | |||
| 139 | 138 | ||
| 140 | echo 40 $(( 8 ^ 32 )) | 139 | echo 40 $(( 8 ^ 32 )) |
| 141 | 140 | ||
| 142 | #ash# # other bases | 141 | echo other bases |
| 143 | #ash# echo 10 $(( 16#a )) | 142 | echo 10 $(( 16#a )) |
| 144 | #ash# echo 10 $(( 32#a )) | 143 | echo 10 $(( 32#a )) |
| 145 | #ash# echo 10 $(( 56#a )) | 144 | echo 10 $(( 56#a )) |
| 146 | #ash# echo 10 $(( 64#a )) | 145 | echo 10 $(( 64#a )) |
| 147 | #ash# | 146 | |
| 148 | #ash# echo 10 $(( 16#A )) | 147 | echo 10 $(( 16#A )) |
| 149 | #ash# echo 10 $(( 32#A )) | 148 | echo 10 $(( 32#A )) |
| 150 | #ash# echo 36 $(( 56#A )) | 149 | echo 36 $(( 56#A )) |
| 151 | #ash# echo 36 $(( 64#A )) | 150 | echo 36 $(( 64#A )) |
| 152 | #ash# | 151 | |
| 153 | #ash# echo 62 $(( 64#@ )) | 152 | echo 62 $(( 64#@ )) |
| 154 | #ash# echo 63 $(( 64#_ )) | 153 | echo 63 $(( 64#_ )) |
| 155 | 154 | ||
| 156 | #ash# # weird bases (error) | 155 | #ash# # weird bases (error) |
| 157 | #ash# echo $(( 3425#56 )) | 156 | #ash# echo $(( 3425#56 )) |
| 158 | 157 | ||
| 159 | #ash# # missing number after base | 158 | echo missing number after base |
| 160 | #ash# echo 0 $(( 2# )) | 159 | echo 0 $(( 2# )) |
| 161 | 160 | ||
| 162 | # these should generate errors | 161 | # these should generate errors |
| 163 | ( echo $(( 7 = 43 )) ) | 162 | ( echo $(( 7 = 43 )) ) |
| @@ -252,8 +251,8 @@ echo 3 $x | |||
| 252 | echo 4 $(( ++x )) | 251 | echo 4 $(( ++x )) |
| 253 | echo 4 $x | 252 | echo 4 $x |
| 254 | 253 | ||
| 255 | # bash 3.2 apparently thinks that ++7 is 7 | 254 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 256 | #ash# echo 7 $(( ++7 )) | 255 | echo 7 $(( ++7 )) |
| 257 | ( echo $(( 7-- )) ) | 256 | ( echo $(( 7-- )) ) |
| 258 | 257 | ||
| 259 | ( echo $(( --x=7 )) ) | 258 | ( echo $(( --x=7 )) ) |
| @@ -267,9 +266,9 @@ echo 4 $x | |||
| 267 | echo 7 $(( +7 )) | 266 | echo 7 $(( +7 )) |
| 268 | echo -7 $(( -7 )) | 267 | echo -7 $(( -7 )) |
| 269 | 268 | ||
| 270 | # bash 3.2 apparently thinks that ++7 is 7 | 269 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 271 | #ash# echo $(( ++7 )) | 270 | echo $(( ++7 )) |
| 272 | #ash# echo $(( --7 )) | 271 | echo $(( --7 )) |
| 273 | 272 | ||
| 274 | ${THIS_SH} ./arith1.sub | 273 | ${THIS_SH} ./arith1.sub |
| 275 | ${THIS_SH} ./arith2.sub | 274 | ${THIS_SH} ./arith2.sub |
diff --git a/shell/ash_test/ash-arith/arith1.sub b/shell/ash_test/ash-arith/arith1.sub index 80aa99922..a36785c67 100755 --- a/shell/ash_test/ash-arith/arith1.sub +++ b/shell/ash_test/ash-arith/arith1.sub | |||
| @@ -35,6 +35,6 @@ echo 1 $a | |||
| 35 | 35 | ||
| 36 | #ash# (( ++ )) | 36 | #ash# (( ++ )) |
| 37 | ( echo $(( +++7 )) ) | 37 | ( echo $(( +++7 )) ) |
| 38 | # bash 3.2 apparently thinks that ++ +7 is 7 | 38 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 39 | #ash# echo $(( ++ + 7 )) | 39 | echo $(( ++ + 7 )) |
| 40 | #ash# (( -- )) | 40 | #ash# (( -- )) |
diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub index 9105059db..8d7918114 100755 --- a/shell/ash_test/ash-arith/arith2.sub +++ b/shell/ash_test/ash-arith/arith2.sub | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # bash 3.2 apparently thinks that ++7 is 7 etc | 1 | # ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences |
| 2 | ( echo $(( --7 )) ) | 2 | ( echo $(( --7 )) ) |
| 3 | ( echo $(( ++7 )) ) | 3 | ( echo $(( ++7 )) ) |
| 4 | ( echo $(( -- 7 )) ) | 4 | ( echo $(( -- 7 )) ) |
| @@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a )) | |||
| 37 | echo 0 $a | 37 | echo 0 $a |
| 38 | 38 | ||
| 39 | #ash# (( -- )) | 39 | #ash# (( -- )) |
| 40 | # bash 3.2 apparently thinks that ---7 is -7 | 40 | # -- is not a dec operator on non-variable, it is the - - sequence |
| 41 | #ash# echo $(( ---7 )) | 41 | echo $(( ---7 )) |
| 42 | ( echo $(( -- - 7 )) ) | 42 | ( echo $(( -- - 7 )) ) |
| 43 | 43 | ||
| 44 | #ash# (( ++ )) | 44 | #ash# (( ++ )) |
| 45 | # bash 3.2: 7 | 45 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 46 | #ash# echo 7 $(( ++7 )) | 46 | echo $(( ++7 )) |
| 47 | ( echo $(( ++ + 7 )) ) | 47 | ( echo $(( ++ + 7 )) ) |
| 48 | 48 | ||
| 49 | # bash 3.2: -7 | 49 | echo -7 $(( ++-7 )) |
| 50 | #ash# echo -7 $(( ++-7 )) | 50 | echo -7 $(( ++ - 7 )) |
| 51 | # bash 3.2: -7 | ||
| 52 | #ash# echo -7 $(( ++ - 7 )) | ||
| 53 | 51 | ||
| 54 | # bash 3.2: 7 | 52 | echo 7 $(( +--7 )) |
| 55 | #ash# echo 7 $(( +--7 )) | 53 | echo 7 $(( -- + 7 )) |
| 56 | # bash 3.2: 7 | ||
| 57 | #ash# echo 7 $(( -- + 7 )) | ||
diff --git a/shell/ash_test/ash-comm/comm.right b/shell/ash_test/ash-comm/comm.right new file mode 100644 index 000000000..1d836656f --- /dev/null +++ b/shell/ash_test/ash-comm/comm.right | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | ./SCRIPT.sh: | ||
| 2 | /proc/N/comm: SCRIPT.sh | ||
| 3 | exec ./SCRIPT.sh: | ||
| 4 | /proc/N/comm: SCRIPT.sh | ||
| 5 | sh ./SCRIPT.sh: | ||
| 6 | /proc/N/comm: ash | ||
diff --git a/shell/ash_test/ash-comm/comm.tests b/shell/ash_test/ash-comm/comm.tests new file mode 100755 index 000000000..671bfc176 --- /dev/null +++ b/shell/ash_test/ash-comm/comm.tests | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | { | ||
| 2 | echo "#!$THIS_SH" | ||
| 3 | echo 'procdir=/proc/$$' | ||
| 4 | #echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"' | ||
| 5 | echo 'echo " /proc/N/comm: $(cat $procdir/comm)"' | ||
| 6 | } >SCRIPT.sh | ||
| 7 | chmod 755 SCRIPT.sh | ||
| 8 | |||
| 9 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
| 10 | echo './SCRIPT.sh:' | ||
| 11 | ./SCRIPT.sh | ||
| 12 | |||
| 13 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
| 14 | echo 'exec ./SCRIPT.sh:' | ||
| 15 | (exec ./SCRIPT.sh) | ||
| 16 | |||
| 17 | echo 'sh ./SCRIPT.sh:' | ||
| 18 | $THIS_SH ./SCRIPT.sh | ||
| 19 | |||
| 20 | rm SCRIPT.sh | ||
diff --git a/shell/hush.c b/shell/hush.c index 6d472337f..6a27b1634 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -339,7 +339,7 @@ | |||
| 339 | * therefore we don't show them either. | 339 | * therefore we don't show them either. |
| 340 | */ | 340 | */ |
| 341 | //usage:#define hush_trivial_usage | 341 | //usage:#define hush_trivial_usage |
| 342 | //usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" | 342 | //usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" |
| 343 | //usage:#define hush_full_usage "\n\n" | 343 | //usage:#define hush_full_usage "\n\n" |
| 344 | //usage: "Unix shell interpreter" | 344 | //usage: "Unix shell interpreter" |
| 345 | 345 | ||
| @@ -373,7 +373,7 @@ | |||
| 373 | # define F_DUPFD_CLOEXEC F_DUPFD | 373 | # define F_DUPFD_CLOEXEC F_DUPFD |
| 374 | #endif | 374 | #endif |
| 375 | 375 | ||
| 376 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) | 376 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH |
| 377 | # include "embedded_scripts.h" | 377 | # include "embedded_scripts.h" |
| 378 | #else | 378 | #else |
| 379 | # define NUM_SCRIPTS 0 | 379 | # define NUM_SCRIPTS 0 |
| @@ -3360,7 +3360,7 @@ static int glob_brace(char *pattern, o_string *o, int n) | |||
| 3360 | * NEXT points past the terminator of the first element, and REST | 3360 | * NEXT points past the terminator of the first element, and REST |
| 3361 | * points past the final }. We will accumulate result names from | 3361 | * points past the final }. We will accumulate result names from |
| 3362 | * recursive runs for each brace alternative in the buffer using | 3362 | * recursive runs for each brace alternative in the buffer using |
| 3363 | * GLOB_APPEND. */ | 3363 | * GLOB_APPEND. */ |
| 3364 | 3364 | ||
| 3365 | p = begin + 1; | 3365 | p = begin + 1; |
| 3366 | while (1) { | 3366 | while (1) { |
| @@ -6311,7 +6311,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int | |||
| 6311 | 6311 | ||
| 6312 | /* Expanding ARG in ${var+ARG}, ${var-ARG} | 6312 | /* Expanding ARG in ${var+ARG}, ${var-ARG} |
| 6313 | */ | 6313 | */ |
| 6314 | static int encode_then_append_var_plusminus(o_string *output, int n, | 6314 | static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n, |
| 6315 | char *str, int dquoted) | 6315 | char *str, int dquoted) |
| 6316 | { | 6316 | { |
| 6317 | struct in_str input; | 6317 | struct in_str input; |
| @@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | |||
| 6472 | /* ${var/[/]pattern[/repl]} helpers */ | 6472 | /* ${var/[/]pattern[/repl]} helpers */ |
| 6473 | static char *strstr_pattern(char *val, const char *pattern, int *size) | 6473 | static char *strstr_pattern(char *val, const char *pattern, int *size) |
| 6474 | { | 6474 | { |
| 6475 | int sz = strcspn(pattern, "*?[\\"); | 6475 | int first_escaped = (pattern[0] == '\\' && pattern[1]); |
| 6476 | if (pattern[sz] == '\0') { | 6476 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" |
| 6477 | * as literal too (as it is semi-common, and easy to accomodate | ||
| 6478 | * by just using str + 1). | ||
| 6479 | */ | ||
| 6480 | int sz = strcspn(pattern + first_escaped * 2, "*?[\\"); | ||
| 6481 | if ((pattern + first_escaped * 2)[sz] == '\0') { | ||
| 6477 | /* Optimization for trivial patterns. | 6482 | /* Optimization for trivial patterns. |
| 6478 | * Testcase for very slow replace (performs about 22k replaces): | 6483 | * Testcase for very slow replace (performs about 22k replaces): |
| 6479 | * x=:::::::::::::::::::::: | 6484 | * x=:::::::::::::::::::::: |
| 6480 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 6485 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
| 6481 | * echo "${x//:/|}" | 6486 | * echo "${x//:/|}" |
| 6482 | */ | 6487 | */ |
| 6483 | *size = sz; | 6488 | *size = sz + first_escaped; |
| 6484 | return strstr(val, pattern); | 6489 | return strstr(val, pattern + first_escaped); |
| 6485 | } | 6490 | } |
| 6486 | 6491 | ||
| 6487 | while (1) { | 6492 | while (1) { |
| @@ -10220,7 +10225,7 @@ int hush_main(int argc, char **argv) | |||
| 10220 | 10225 | ||
| 10221 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ | 10226 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ |
| 10222 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ | 10227 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ |
| 10223 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ | 10228 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ |
| 10224 | 10229 | ||
| 10225 | /* Deal with HUSH_VERSION */ | 10230 | /* Deal with HUSH_VERSION */ |
| 10226 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 10231 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
| @@ -10351,6 +10356,29 @@ int hush_main(int argc, char **argv) | |||
| 10351 | /* Well, we cannot just declare interactiveness, | 10356 | /* Well, we cannot just declare interactiveness, |
| 10352 | * we have to have some stuff (ctty, etc) */ | 10357 | * we have to have some stuff (ctty, etc) */ |
| 10353 | /* G_interactive_fd++; */ | 10358 | /* G_interactive_fd++; */ |
| 10359 | //There are a few cases where bash -i -c 'SCRIPT' | ||
| 10360 | //has visible effect (differs from bash -c 'SCRIPT'): | ||
| 10361 | //it ignores TERM: | ||
| 10362 | // bash -i -c 'kill $$; echo ALIVE' | ||
| 10363 | // ALIVE | ||
| 10364 | //it resets SIG_INGed HUP to SIG_DFL: | ||
| 10365 | // trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' | ||
| 10366 | // Hangup [the message is not printed by bash, it's the shell which started it] | ||
| 10367 | //is talkative about jobs and exiting: | ||
| 10368 | // bash -i -c 'sleep 1 & exit' | ||
| 10369 | // [1] 16170 | ||
| 10370 | // exit | ||
| 10371 | //includes $ENV file (only if run as "sh"): | ||
| 10372 | // echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE' | ||
| 10373 | // last: cannot open /var/log/wtmp: No such file or directory | ||
| 10374 | // HERE | ||
| 10375 | //(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i). | ||
| 10376 | // | ||
| 10377 | //ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting | ||
| 10378 | //(this may be a bug, bash does not do this). | ||
| 10379 | //(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed) | ||
| 10380 | // | ||
| 10381 | //None of the above feel like useful features people would rely on. | ||
| 10354 | break; | 10382 | break; |
| 10355 | case 's': | 10383 | case 's': |
| 10356 | G.opt_s = 1; | 10384 | G.opt_s = 1; |
| @@ -11727,7 +11755,7 @@ static int FAST_FUNC builtin_fg_bg(char **argv) | |||
| 11727 | /* TODO: bash prints a string representation | 11755 | /* TODO: bash prints a string representation |
| 11728 | * of job being foregrounded (like "sleep 1 | cat") */ | 11756 | * of job being foregrounded (like "sleep 1 | cat") */ |
| 11729 | if (argv[0][0] == 'f' && G_saved_tty_pgrp) { | 11757 | if (argv[0][0] == 'f' && G_saved_tty_pgrp) { |
| 11730 | /* Put the job into the foreground. */ | 11758 | /* Put the job into the foreground. */ |
| 11731 | tcsetpgrp(G_interactive_fd, pi->pgrp); | 11759 | tcsetpgrp(G_interactive_fd, pi->pgrp); |
| 11732 | } | 11760 | } |
| 11733 | 11761 | ||
diff --git a/shell/hush_test/hush-arith/arith-postinc.right b/shell/hush_test/hush-arith/arith-postinc.right index c95ce02bf..5cd4ba6b4 100644 --- a/shell/hush_test/hush-arith/arith-postinc.right +++ b/shell/hush_test/hush-arith/arith-postinc.right | |||
| @@ -2,4 +2,7 @@ | |||
| 2 | 1 1 | 2 | 1 1 |
| 3 | 1 1 | 3 | 1 1 |
| 4 | 1 1 | 4 | 1 1 |
| 5 | 6 6 | ||
| 6 | 7 7 | ||
| 7 | 7 7 | ||
| 5 | Ok:0 | 8 | Ok:0 |
diff --git a/shell/hush_test/hush-arith/arith-postinc.tests b/shell/hush_test/hush-arith/arith-postinc.tests index 3fd9bfed5..f2ae778df 100755 --- a/shell/hush_test/hush-arith/arith-postinc.tests +++ b/shell/hush_test/hush-arith/arith-postinc.tests | |||
| @@ -2,4 +2,8 @@ echo 1 $((0++1)) | |||
| 2 | echo 1 $((0--1)) | 2 | echo 1 $((0--1)) |
| 3 | x=-1; echo 1 $((0-$x)) | 3 | x=-1; echo 1 $((0-$x)) |
| 4 | x=+1; echo 1 $((0+$x)) | 4 | x=+1; echo 1 $((0+$x)) |
| 5 | a=3 | ||
| 6 | echo 6 $((a+++3)) # a++ + 3 | ||
| 7 | echo 7 $(((a)+++3)) # a + + + 3 | ||
| 8 | echo 7 $(((a)+++3)) # a + + + 3 | ||
| 5 | echo Ok:$? | 9 | echo Ok:$? |
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index c48e468a5..a8612295e 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right | |||
| @@ -70,6 +70,19 @@ octal, hex | |||
| 70 | 263 263 | 70 | 263 263 |
| 71 | 255 255 | 71 | 255 255 |
| 72 | 40 40 | 72 | 40 40 |
| 73 | other bases | ||
| 74 | 10 10 | ||
| 75 | 10 10 | ||
| 76 | 10 10 | ||
| 77 | 10 10 | ||
| 78 | 10 10 | ||
| 79 | 10 10 | ||
| 80 | 36 36 | ||
| 81 | 36 36 | ||
| 82 | 62 62 | ||
| 83 | 63 63 | ||
| 84 | missing number after base | ||
| 85 | 0 0 | ||
| 73 | hush: arithmetic syntax error | 86 | hush: arithmetic syntax error |
| 74 | hush: divide by zero | 87 | hush: divide by zero |
| 75 | hush: can't execute 'let': No such file or directory | 88 | hush: can't execute 'let': No such file or directory |
| @@ -106,6 +119,7 @@ hush: arithmetic syntax error | |||
| 106 | 3 3 | 119 | 3 3 |
| 107 | 4 4 | 120 | 4 4 |
| 108 | 4 4 | 121 | 4 4 |
| 122 | 7 7 | ||
| 109 | hush: arithmetic syntax error | 123 | hush: arithmetic syntax error |
| 110 | hush: arithmetic syntax error | 124 | hush: arithmetic syntax error |
| 111 | hush: arithmetic syntax error | 125 | hush: arithmetic syntax error |
| @@ -114,6 +128,8 @@ hush: arithmetic syntax error | |||
| 114 | 4 4 | 128 | 4 4 |
| 115 | 7 7 | 129 | 7 7 |
| 116 | -7 -7 | 130 | -7 -7 |
| 131 | 7 | ||
| 132 | 7 | ||
| 117 | hush: arithmetic syntax error | 133 | hush: arithmetic syntax error |
| 118 | hush: arithmetic syntax error | 134 | hush: arithmetic syntax error |
| 119 | hush: arithmetic syntax error | 135 | hush: arithmetic syntax error |
| @@ -128,11 +144,12 @@ hush: arithmetic syntax error | |||
| 128 | 2 2 | 144 | 2 2 |
| 129 | -2 -2 | 145 | -2 -2 |
| 130 | 1 1 | 146 | 1 1 |
| 131 | hush: arithmetic syntax error | 147 | 7 |
| 132 | hush: arithmetic syntax error | 148 | 7 |
| 133 | hush: arithmetic syntax error | 149 | 7 |
| 134 | hush: arithmetic syntax error | 150 | 7 |
| 135 | hush: arithmetic syntax error | 151 | 7 |
| 152 | 7 | ||
| 136 | 5 5 | 153 | 5 5 |
| 137 | 1 1 | 154 | 1 1 |
| 138 | 6 6 | 155 | 6 6 |
| @@ -141,8 +158,14 @@ hush: arithmetic syntax error | |||
| 141 | 1 1 | 158 | 1 1 |
| 142 | 4 4 | 159 | 4 4 |
| 143 | 0 0 | 160 | 0 0 |
| 144 | hush: arithmetic syntax error | 161 | -7 |
| 145 | hush: arithmetic syntax error | 162 | -7 |
| 163 | 7 | ||
| 164 | 7 | ||
| 165 | -7 -7 | ||
| 166 | -7 -7 | ||
| 167 | 7 7 | ||
| 168 | 7 7 | ||
| 146 | 8 12 | 169 | 8 12 |
| 147 | hush: arithmetic syntax error | 170 | hush: arithmetic syntax error |
| 148 | 42 | 171 | 42 |
diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests index bc6b341d1..6b707486c 100755 --- a/shell/hush_test/hush-arith/arith.tests +++ b/shell/hush_test/hush-arith/arith.tests | |||
| @@ -142,25 +142,25 @@ echo 255 $(( 0xff )) | |||
| 142 | 142 | ||
| 143 | echo 40 $(( 8 ^ 32 )) | 143 | echo 40 $(( 8 ^ 32 )) |
| 144 | 144 | ||
| 145 | #ash# # other bases | 145 | echo other bases |
| 146 | #ash# echo 10 $(( 16#a )) | 146 | echo 10 $(( 16#a )) |
| 147 | #ash# echo 10 $(( 32#a )) | 147 | echo 10 $(( 32#a )) |
| 148 | #ash# echo 10 $(( 56#a )) | 148 | echo 10 $(( 56#a )) |
| 149 | #ash# echo 10 $(( 64#a )) | 149 | echo 10 $(( 64#a )) |
| 150 | #ash# | 150 | |
| 151 | #ash# echo 10 $(( 16#A )) | 151 | echo 10 $(( 16#A )) |
| 152 | #ash# echo 10 $(( 32#A )) | 152 | echo 10 $(( 32#A )) |
| 153 | #ash# echo 36 $(( 56#A )) | 153 | echo 36 $(( 56#A )) |
| 154 | #ash# echo 36 $(( 64#A )) | 154 | echo 36 $(( 64#A )) |
| 155 | #ash# | 155 | |
| 156 | #ash# echo 62 $(( 64#@ )) | 156 | echo 62 $(( 64#@ )) |
| 157 | #ash# echo 63 $(( 64#_ )) | 157 | echo 63 $(( 64#_ )) |
| 158 | 158 | ||
| 159 | #ash# # weird bases (error) | 159 | #ash# # weird bases (error) |
| 160 | #ash# echo $(( 3425#56 )) | 160 | #ash# echo $(( 3425#56 )) |
| 161 | 161 | ||
| 162 | #ash# # missing number after base | 162 | echo missing number after base |
| 163 | #ash# echo 0 $(( 2# )) | 163 | echo 0 $(( 2# )) |
| 164 | 164 | ||
| 165 | # these should generate errors | 165 | # these should generate errors |
| 166 | ( echo $(( 7 = 43 )) ) | 166 | ( echo $(( 7 = 43 )) ) |
| @@ -255,8 +255,8 @@ echo 3 $x | |||
| 255 | echo 4 $(( ++x )) | 255 | echo 4 $(( ++x )) |
| 256 | echo 4 $x | 256 | echo 4 $x |
| 257 | 257 | ||
| 258 | # bash 3.2 apparently thinks that ++7 is 7 | 258 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 259 | #ash# echo 7 $(( ++7 )) | 259 | echo 7 $(( ++7 )) |
| 260 | ( echo $(( 7-- )) ) | 260 | ( echo $(( 7-- )) ) |
| 261 | 261 | ||
| 262 | ( echo $(( --x=7 )) ) | 262 | ( echo $(( --x=7 )) ) |
| @@ -270,9 +270,9 @@ echo 4 $x | |||
| 270 | echo 7 $(( +7 )) | 270 | echo 7 $(( +7 )) |
| 271 | echo -7 $(( -7 )) | 271 | echo -7 $(( -7 )) |
| 272 | 272 | ||
| 273 | # bash 3.2 apparently thinks that ++7 is 7 | 273 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 274 | #ash# echo $(( ++7 )) | 274 | echo $(( ++7 )) |
| 275 | #ash# echo $(( --7 )) | 275 | echo $(( --7 )) |
| 276 | 276 | ||
| 277 | ${THIS_SH} ./arith1.sub | 277 | ${THIS_SH} ./arith1.sub |
| 278 | ${THIS_SH} ./arith2.sub | 278 | ${THIS_SH} ./arith2.sub |
diff --git a/shell/hush_test/hush-arith/arith1.sub b/shell/hush_test/hush-arith/arith1.sub index 80aa99922..a36785c67 100755 --- a/shell/hush_test/hush-arith/arith1.sub +++ b/shell/hush_test/hush-arith/arith1.sub | |||
| @@ -35,6 +35,6 @@ echo 1 $a | |||
| 35 | 35 | ||
| 36 | #ash# (( ++ )) | 36 | #ash# (( ++ )) |
| 37 | ( echo $(( +++7 )) ) | 37 | ( echo $(( +++7 )) ) |
| 38 | # bash 3.2 apparently thinks that ++ +7 is 7 | 38 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 39 | #ash# echo $(( ++ + 7 )) | 39 | echo $(( ++ + 7 )) |
| 40 | #ash# (( -- )) | 40 | #ash# (( -- )) |
diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub index 9105059db..8d7918114 100755 --- a/shell/hush_test/hush-arith/arith2.sub +++ b/shell/hush_test/hush-arith/arith2.sub | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # bash 3.2 apparently thinks that ++7 is 7 etc | 1 | # ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences |
| 2 | ( echo $(( --7 )) ) | 2 | ( echo $(( --7 )) ) |
| 3 | ( echo $(( ++7 )) ) | 3 | ( echo $(( ++7 )) ) |
| 4 | ( echo $(( -- 7 )) ) | 4 | ( echo $(( -- 7 )) ) |
| @@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a )) | |||
| 37 | echo 0 $a | 37 | echo 0 $a |
| 38 | 38 | ||
| 39 | #ash# (( -- )) | 39 | #ash# (( -- )) |
| 40 | # bash 3.2 apparently thinks that ---7 is -7 | 40 | # -- is not a dec operator on non-variable, it is the - - sequence |
| 41 | #ash# echo $(( ---7 )) | 41 | echo $(( ---7 )) |
| 42 | ( echo $(( -- - 7 )) ) | 42 | ( echo $(( -- - 7 )) ) |
| 43 | 43 | ||
| 44 | #ash# (( ++ )) | 44 | #ash# (( ++ )) |
| 45 | # bash 3.2: 7 | 45 | # ++ is not a inc operator on non-variable, it is the + + sequence |
| 46 | #ash# echo 7 $(( ++7 )) | 46 | echo $(( ++7 )) |
| 47 | ( echo $(( ++ + 7 )) ) | 47 | ( echo $(( ++ + 7 )) ) |
| 48 | 48 | ||
| 49 | # bash 3.2: -7 | 49 | echo -7 $(( ++-7 )) |
| 50 | #ash# echo -7 $(( ++-7 )) | 50 | echo -7 $(( ++ - 7 )) |
| 51 | # bash 3.2: -7 | ||
| 52 | #ash# echo -7 $(( ++ - 7 )) | ||
| 53 | 51 | ||
| 54 | # bash 3.2: 7 | 52 | echo 7 $(( +--7 )) |
| 55 | #ash# echo 7 $(( +--7 )) | 53 | echo 7 $(( -- + 7 )) |
| 56 | # bash 3.2: 7 | ||
| 57 | #ash# echo 7 $(( -- + 7 )) | ||
diff --git a/shell/hush_test/hush-comm/comm.right b/shell/hush_test/hush-comm/comm.right new file mode 100644 index 000000000..1b62b617e --- /dev/null +++ b/shell/hush_test/hush-comm/comm.right | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | ./SCRIPT.sh: | ||
| 2 | /proc/N/comm: SCRIPT.sh | ||
| 3 | exec ./SCRIPT.sh: | ||
| 4 | /proc/N/comm: SCRIPT.sh | ||
| 5 | sh ./SCRIPT.sh: | ||
| 6 | /proc/N/comm: hush | ||
diff --git a/shell/hush_test/hush-comm/comm.tests b/shell/hush_test/hush-comm/comm.tests new file mode 100755 index 000000000..671bfc176 --- /dev/null +++ b/shell/hush_test/hush-comm/comm.tests | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | { | ||
| 2 | echo "#!$THIS_SH" | ||
| 3 | echo 'procdir=/proc/$$' | ||
| 4 | #echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"' | ||
| 5 | echo 'echo " /proc/N/comm: $(cat $procdir/comm)"' | ||
| 6 | } >SCRIPT.sh | ||
| 7 | chmod 755 SCRIPT.sh | ||
| 8 | |||
| 9 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
| 10 | echo './SCRIPT.sh:' | ||
| 11 | ./SCRIPT.sh | ||
| 12 | |||
| 13 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
| 14 | echo 'exec ./SCRIPT.sh:' | ||
| 15 | (exec ./SCRIPT.sh) | ||
| 16 | |||
| 17 | echo 'sh ./SCRIPT.sh:' | ||
| 18 | $THIS_SH ./SCRIPT.sh | ||
| 19 | |||
| 20 | rm SCRIPT.sh | ||
diff --git a/shell/math.c b/shell/math.c index 2942cdd26..76d22c9bd 100644 --- a/shell/math.c +++ b/shell/math.c | |||
| @@ -116,10 +116,6 @@ | |||
| 116 | #include "libbb.h" | 116 | #include "libbb.h" |
| 117 | #include "math.h" | 117 | #include "math.h" |
| 118 | 118 | ||
| 119 | #define lookupvar (math_state->lookupvar) | ||
| 120 | #define setvar (math_state->setvar ) | ||
| 121 | //#define endofname (math_state->endofname) | ||
| 122 | |||
| 123 | typedef unsigned char operator; | 119 | typedef unsigned char operator; |
| 124 | 120 | ||
| 125 | /* An operator's token id is a bit of a bitfield. The lower 5 bits are the | 121 | /* An operator's token id is a bit of a bitfield. The lower 5 bits are the |
| @@ -258,7 +254,7 @@ static const char* | |||
| 258 | arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) | 254 | arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) |
| 259 | { | 255 | { |
| 260 | if (t->var) { | 256 | if (t->var) { |
| 261 | const char *p = lookupvar(t->var); | 257 | const char *p = math_state->lookupvar(t->var); |
| 262 | if (p) { | 258 | if (p) { |
| 263 | remembered_name *cur; | 259 | remembered_name *cur; |
| 264 | remembered_name cur_save; | 260 | remembered_name cur_save; |
| @@ -445,16 +441,15 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
| 445 | 441 | ||
| 446 | if (top_of_stack->var == NULL) { | 442 | if (top_of_stack->var == NULL) { |
| 447 | /* Hmm, 1=2 ? */ | 443 | /* Hmm, 1=2 ? */ |
| 448 | //TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8 | ||
| 449 | goto err; | 444 | goto err; |
| 450 | } | 445 | } |
| 451 | /* Save to shell variable */ | 446 | /* Save to shell variable */ |
| 452 | sprintf(buf, ARITH_FMT, rez); | 447 | sprintf(buf, ARITH_FMT, rez); |
| 453 | setvar(top_of_stack->var, buf); | 448 | math_state->setvar(top_of_stack->var, buf); |
| 454 | /* After saving, make previous value for v++ or v-- */ | 449 | /* After saving, make previous value for v++ or v-- */ |
| 455 | if (op == TOK_POST_INC) | 450 | if (op == TOK_POST_INC) |
| 456 | rez--; | 451 | rez--; |
| 457 | else if (op == TOK_POST_DEC) | 452 | if (op == TOK_POST_DEC) |
| 458 | rez++; | 453 | rez++; |
| 459 | } | 454 | } |
| 460 | 455 | ||
| @@ -607,11 +602,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 607 | const char *p; | 602 | const char *p; |
| 608 | operator op; | 603 | operator op; |
| 609 | operator prec; | 604 | operator prec; |
| 610 | char arithval; | ||
| 611 | 605 | ||
| 612 | expr = skip_whitespace(expr); | 606 | expr = skip_whitespace(expr); |
| 613 | arithval = *expr; | 607 | if (*expr == '\0') { |
| 614 | if (arithval == '\0') { | ||
| 615 | if (expr == start_expr) { | 608 | if (expr == start_expr) { |
| 616 | /* Null expression */ | 609 | /* Null expression */ |
| 617 | numstack->val = 0; | 610 | numstack->val = 0; |
| @@ -628,6 +621,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 628 | * append a closing right paren | 621 | * append a closing right paren |
| 629 | * and let the loop process it */ | 622 | * and let the loop process it */ |
| 630 | expr = ptr_to_rparen; | 623 | expr = ptr_to_rparen; |
| 624 | //bb_error_msg("expr=')'"); | ||
| 631 | continue; | 625 | continue; |
| 632 | } | 626 | } |
| 633 | /* At this point, we're done with the expression */ | 627 | /* At this point, we're done with the expression */ |
| @@ -635,19 +629,16 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 635 | /* ...but if there isn't, it's bad */ | 629 | /* ...but if there isn't, it's bad */ |
| 636 | goto err; | 630 | goto err; |
| 637 | } | 631 | } |
| 638 | if (numstack->var) { | ||
| 639 | /* expression is $((var)) only, lookup now */ | ||
| 640 | errmsg = arith_lookup_val(math_state, numstack); | ||
| 641 | } | ||
| 642 | goto ret; | 632 | goto ret; |
| 643 | } | 633 | } |
| 644 | 634 | ||
| 645 | p = endofname(expr); | 635 | p = endofname(expr); |
| 646 | if (p != expr) { | 636 | if (p != expr) { |
| 647 | /* Name */ | 637 | /* Name */ |
| 648 | size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ | 638 | size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ |
| 649 | numstackptr->var = alloca(var_name_size); | 639 | numstackptr->var = alloca(var_name_size); |
| 650 | safe_strncpy(numstackptr->var, expr, var_name_size); | 640 | safe_strncpy(numstackptr->var, expr, var_name_size); |
| 641 | //bb_error_msg("var:'%s'", numstackptr->var); | ||
| 651 | expr = p; | 642 | expr = p; |
| 652 | num: | 643 | num: |
| 653 | numstackptr->second_val_present = 0; | 644 | numstackptr->second_val_present = 0; |
| @@ -656,11 +647,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 656 | continue; | 647 | continue; |
| 657 | } | 648 | } |
| 658 | 649 | ||
| 659 | if (isdigit(arithval)) { | 650 | if (isdigit(*expr)) { |
| 660 | /* Number */ | 651 | /* Number */ |
| 661 | numstackptr->var = NULL; | 652 | numstackptr->var = NULL; |
| 662 | errno = 0; | 653 | errno = 0; |
| 663 | numstackptr->val = strto_arith_t(expr, (char**) &expr); | 654 | numstackptr->val = strto_arith_t(expr, (char**) &expr); |
| 655 | //bb_error_msg("val:%lld", numstackptr->val); | ||
| 664 | if (errno) | 656 | if (errno) |
| 665 | numstackptr->val = 0; /* bash compat */ | 657 | numstackptr->val = 0; /* bash compat */ |
| 666 | goto num; | 658 | goto num; |
| @@ -668,19 +660,26 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 668 | 660 | ||
| 669 | /* Should be an operator */ | 661 | /* Should be an operator */ |
| 670 | 662 | ||
| 671 | /* Special case: NUM-- and NUM++ are not recognized if NUM | 663 | /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized |
| 672 | * is a literal number, not a variable. IOW: | 664 | * only if XYZ is a variable name, not a number or EXPR. IOW: |
| 673 | * "a+++v" is a++ + v. | 665 | * "a+++v" is a++ + v. |
| 666 | * "(a)+++7" is ( a ) + + + 7. | ||
| 674 | * "7+++v" is 7 + ++v, not 7++ + v. | 667 | * "7+++v" is 7 + ++v, not 7++ + v. |
| 668 | * "--7" is - - 7, not --7. | ||
| 669 | * "++++a" is + + ++a, not ++ ++a. | ||
| 675 | */ | 670 | */ |
| 676 | if (lasttok == TOK_NUM && !numstackptr[-1].var /* number literal */ | 671 | if ((expr[0] == '+' || expr[0] == '-') |
| 677 | && (expr[0] == '+' || expr[0] == '-') | ||
| 678 | && (expr[1] == expr[0]) | 672 | && (expr[1] == expr[0]) |
| 679 | ) { | 673 | ) { |
| 680 | //bb_error_msg("special %c%c", expr[0], expr[0]); | 674 | if (numstackptr == numstack || !numstackptr[-1].var) { /* not a VAR++ */ |
| 681 | op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); | 675 | char next = skip_whitespace(expr + 2)[0]; |
| 682 | expr += 1; | 676 | if (!(isalpha(next) || next == '_')) { /* not a ++VAR */ |
| 683 | goto tok_found1; | 677 | //bb_error_msg("special %c%c", expr[0], expr[0]); |
| 678 | op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); | ||
| 679 | expr++; | ||
| 680 | goto tok_found1; | ||
| 681 | } | ||
| 682 | } | ||
| 684 | } | 683 | } |
| 685 | 684 | ||
| 686 | p = op_tokens; | 685 | p = op_tokens; |
| @@ -749,26 +748,40 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 749 | * "applied" in this way. | 748 | * "applied" in this way. |
| 750 | */ | 749 | */ |
| 751 | prec = PREC(op); | 750 | prec = PREC(op); |
| 751 | //bb_error_msg("prec:%02x", prec); | ||
| 752 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { | 752 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { |
| 753 | /* not left paren or unary */ | 753 | /* not left paren or unary */ |
| 754 | if (lasttok != TOK_NUM) { | 754 | if (lasttok != TOK_NUM) { |
| 755 | /* binary op must be preceded by a num */ | 755 | /* binary op must be preceded by a num */ |
| 756 | goto err; | 756 | goto err; |
| 757 | } | 757 | } |
| 758 | /* The algorithm employed here is simple: while we don't | ||
| 759 | * hit an open paren nor the bottom of the stack, pop | ||
| 760 | * tokens and apply them */ | ||
| 758 | while (stackptr != stack) { | 761 | while (stackptr != stack) { |
| 759 | operator prev_op = *--stackptr; | 762 | operator prev_op = *--stackptr; |
| 760 | if (op == TOK_RPAREN) { | 763 | if (op == TOK_RPAREN) { |
| 761 | /* The algorithm employed here is simple: while we don't | 764 | //bb_error_msg("op == TOK_RPAREN"); |
| 762 | * hit an open paren nor the bottom of the stack, pop | ||
| 763 | * tokens and apply them */ | ||
| 764 | if (prev_op == TOK_LPAREN) { | 765 | if (prev_op == TOK_LPAREN) { |
| 766 | //bb_error_msg("prev_op == TOK_LPAREN"); | ||
| 767 | //bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var); | ||
| 768 | if (numstackptr[-1].var) { | ||
| 769 | /* Expression is (var), lookup now */ | ||
| 770 | errmsg = arith_lookup_val(math_state, &numstackptr[-1]); | ||
| 771 | if (errmsg) | ||
| 772 | goto err_with_custom_msg; | ||
| 773 | /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ | ||
| 774 | numstackptr[-1].var = NULL; | ||
| 775 | } | ||
| 765 | /* Any operator directly after a | 776 | /* Any operator directly after a |
| 766 | * close paren should consider itself binary */ | 777 | * close paren should consider itself binary */ |
| 767 | lasttok = TOK_NUM; | 778 | lasttok = TOK_NUM; |
| 768 | goto next; | 779 | goto next; |
| 769 | } | 780 | } |
| 781 | //bb_error_msg("prev_op != TOK_LPAREN"); | ||
| 770 | } else { | 782 | } else { |
| 771 | operator prev_prec = PREC(prev_op); | 783 | operator prev_prec = PREC(prev_op); |
| 784 | //bb_error_msg("op != TOK_RPAREN"); | ||
| 772 | fix_assignment_prec(prec); | 785 | fix_assignment_prec(prec); |
| 773 | fix_assignment_prec(prev_prec); | 786 | fix_assignment_prec(prev_prec); |
| 774 | if (prev_prec < prec | 787 | if (prev_prec < prec |
| @@ -778,6 +791,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 778 | break; | 791 | break; |
| 779 | } | 792 | } |
| 780 | } | 793 | } |
| 794 | //bb_error_msg("arith_apply(prev_op:%02x)", prev_op); | ||
| 781 | errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); | 795 | errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); |
| 782 | if (errmsg) | 796 | if (errmsg) |
| 783 | goto err_with_custom_msg; | 797 | goto err_with_custom_msg; |
| @@ -787,6 +801,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
| 787 | } | 801 | } |
| 788 | 802 | ||
| 789 | /* Push this operator to the stack and remember it */ | 803 | /* Push this operator to the stack and remember it */ |
| 804 | //bb_error_msg("push op:%02x", op); | ||
| 790 | *stackptr++ = lasttok = op; | 805 | *stackptr++ = lasttok = op; |
| 791 | next: ; | 806 | next: ; |
| 792 | } /* while (1) */ | 807 | } /* while (1) */ |
