diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-02 20:17:49 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-02 20:17:49 +0000 |
| commit | b7aaae9052025426b669a0edeec1da5997fea8be (patch) | |
| tree | 062eff7de09b9307a57260c47571888ed3f598b7 /shell | |
| parent | 7a79afa3cab4d35f6c042a1038554948ebe9b2e1 (diff) | |
| download | busybox-w32-b7aaae9052025426b669a0edeec1da5997fea8be.tar.gz busybox-w32-b7aaae9052025426b669a0edeec1da5997fea8be.tar.bz2 busybox-w32-b7aaae9052025426b669a0edeec1da5997fea8be.zip | |
hush: rename ->o_quote to ->o_escape
hush_test/hush-arith/*: new tests for arithmetic evaluation
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 56 | ||||
| -rw-r--r-- | shell/hush_test/hush-arith/arith.right | 138 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith.tests | 302 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith1.sub | 40 | ||||
| -rwxr-xr-x | shell/hush_test/hush-arith/arith2.sub | 57 |
5 files changed, 565 insertions, 28 deletions
diff --git a/shell/hush.c b/shell/hush.c index b46a1fd76..f0d372625 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -392,9 +392,9 @@ typedef struct o_string { | |||
| 392 | char *data; | 392 | char *data; |
| 393 | int length; /* position where data is appended */ | 393 | int length; /* position where data is appended */ |
| 394 | int maxlen; | 394 | int maxlen; |
| 395 | /* Misnomer! it's not "quoting", it's "protection against globbing"! | 395 | /* Protect newly added chars against globbing |
| 396 | * (by prepending \ to *, ?, [ and to \ too) */ | 396 | * (by prepending \ to *, ?, [, \) */ |
| 397 | smallint o_quote; | 397 | smallint o_escape; |
| 398 | smallint o_glob; | 398 | smallint o_glob; |
| 399 | smallint nonnull; | 399 | smallint nonnull; |
| 400 | smallint has_empty_slot; | 400 | smallint has_empty_slot; |
| @@ -1440,7 +1440,7 @@ static void o_addqchr(o_string *o, int ch) | |||
| 1440 | static void o_addQchr(o_string *o, int ch) | 1440 | static void o_addQchr(o_string *o, int ch) |
| 1441 | { | 1441 | { |
| 1442 | int sz = 1; | 1442 | int sz = 1; |
| 1443 | if (o->o_quote && strchr("*?[\\", ch)) { | 1443 | if (o->o_escape && strchr("*?[\\", ch)) { |
| 1444 | sz++; | 1444 | sz++; |
| 1445 | o->data[o->length] = '\\'; | 1445 | o->data[o->length] = '\\'; |
| 1446 | o->length++; | 1446 | o->length++; |
| @@ -1453,7 +1453,7 @@ static void o_addQchr(o_string *o, int ch) | |||
| 1453 | 1453 | ||
| 1454 | static void o_addQstr(o_string *o, const char *str, int len) | 1454 | static void o_addQstr(o_string *o, const char *str, int len) |
| 1455 | { | 1455 | { |
| 1456 | if (!o->o_quote) { | 1456 | if (!o->o_escape) { |
| 1457 | o_addstr(o, str, len); | 1457 | o_addstr(o, str, len); |
| 1458 | return; | 1458 | return; |
| 1459 | } | 1459 | } |
| @@ -1668,7 +1668,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
| 1668 | while (1) { | 1668 | while (1) { |
| 1669 | int word_len = strcspn(str, G.ifs); | 1669 | int word_len = strcspn(str, G.ifs); |
| 1670 | if (word_len) { | 1670 | if (word_len) { |
| 1671 | if (output->o_quote || !output->o_glob) | 1671 | if (output->o_escape || !output->o_glob) |
| 1672 | o_addQstr(output, str, word_len); | 1672 | o_addQstr(output, str, word_len); |
| 1673 | else /* protect backslashes against globbing up :) */ | 1673 | else /* protect backslashes against globbing up :) */ |
| 1674 | o_addstr_duplicate_backslash(output, str, word_len); | 1674 | o_addstr_duplicate_backslash(output, str, word_len); |
| @@ -1751,9 +1751,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
| 1751 | break; | 1751 | break; |
| 1752 | ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ | 1752 | ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ |
| 1753 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ | 1753 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ |
| 1754 | smallint sv = output->o_quote; | 1754 | smallint sv = output->o_escape; |
| 1755 | /* unquoted var's contents should be globbed, so don't quote */ | 1755 | /* unquoted var's contents should be globbed, so don't escape */ |
| 1756 | output->o_quote = 0; | 1756 | output->o_escape = 0; |
| 1757 | while (G.global_argv[i]) { | 1757 | while (G.global_argv[i]) { |
| 1758 | n = expand_on_ifs(output, n, G.global_argv[i]); | 1758 | n = expand_on_ifs(output, n, G.global_argv[i]); |
| 1759 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); | 1759 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); |
| @@ -1766,7 +1766,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
| 1766 | debug_print_list("expand_vars_to_list[3]", output, n); | 1766 | debug_print_list("expand_vars_to_list[3]", output, n); |
| 1767 | } | 1767 | } |
| 1768 | } | 1768 | } |
| 1769 | output->o_quote = sv; | 1769 | output->o_escape = sv; |
| 1770 | } else | 1770 | } else |
| 1771 | /* If or_mask is nonzero, we handle assignment 'a=....$@.....' | 1771 | /* If or_mask is nonzero, we handle assignment 'a=....$@.....' |
| 1772 | * and in this case should treat it like '$*' - see 'else...' below */ | 1772 | * and in this case should treat it like '$*' - see 'else...' below */ |
| @@ -1945,17 +1945,17 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
| 1945 | store_val: | 1945 | store_val: |
| 1946 | #endif | 1946 | #endif |
| 1947 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ | 1947 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ |
| 1948 | debug_printf_expand("unquoted '%s', output->o_quote:%d\n", val, output->o_quote); | 1948 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, output->o_escape); |
| 1949 | if (val) { | 1949 | if (val) { |
| 1950 | /* unquoted var's contents should be globbed, so don't quote */ | 1950 | /* unquoted var's contents should be globbed, so don't escape */ |
| 1951 | smallint sv = output->o_quote; | 1951 | smallint sv = output->o_escape; |
| 1952 | output->o_quote = 0; | 1952 | output->o_escape = 0; |
| 1953 | n = expand_on_ifs(output, n, val); | 1953 | n = expand_on_ifs(output, n, val); |
| 1954 | val = NULL; | 1954 | val = NULL; |
| 1955 | output->o_quote = sv; | 1955 | output->o_escape = sv; |
| 1956 | } | 1956 | } |
| 1957 | } else { /* quoted $VAR, val will be appended below */ | 1957 | } else { /* quoted $VAR, val will be appended below */ |
| 1958 | debug_printf_expand("quoted '%s', output->o_quote:%d\n", val, output->o_quote); | 1958 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, output->o_escape); |
| 1959 | } | 1959 | } |
| 1960 | } /* default: */ | 1960 | } /* default: */ |
| 1961 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ | 1961 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ |
| @@ -1999,7 +1999,7 @@ static char **expand_variables(char **argv, int or_mask) | |||
| 1999 | o_string output = NULL_O_STRING; | 1999 | o_string output = NULL_O_STRING; |
| 2000 | 2000 | ||
| 2001 | if (or_mask & 0x100) { | 2001 | if (or_mask & 0x100) { |
| 2002 | output.o_quote = 1; /* protect against globbing for "$var" */ | 2002 | output.o_escape = 1; /* protect against globbing for "$var" */ |
| 2003 | /* (unquoted $var will temporarily switch it off) */ | 2003 | /* (unquoted $var will temporarily switch it off) */ |
| 2004 | output.o_glob = 1; | 2004 | output.o_glob = 1; |
| 2005 | } | 2005 | } |
| @@ -3979,7 +3979,7 @@ static int handle_dollar(o_string *dest, struct in_str *input) | |||
| 3979 | { | 3979 | { |
| 3980 | int expansion; | 3980 | int expansion; |
| 3981 | int ch = i_peek(input); /* first character after the $ */ | 3981 | int ch = i_peek(input); /* first character after the $ */ |
| 3982 | unsigned char quote_mask = dest->o_quote ? 0x80 : 0; | 3982 | unsigned char quote_mask = dest->o_escape ? 0x80 : 0; |
| 3983 | 3983 | ||
| 3984 | debug_printf_parse("handle_dollar entered: ch='%c'\n", ch); | 3984 | debug_printf_parse("handle_dollar entered: ch='%c'\n", ch); |
| 3985 | if (isalpha(ch)) { | 3985 | if (isalpha(ch)) { |
| @@ -4143,7 +4143,7 @@ static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote | |||
| 4143 | if (ch == dquote_end) { /* may be only '"' or EOF */ | 4143 | if (ch == dquote_end) { /* may be only '"' or EOF */ |
| 4144 | dest->nonnull = 1; | 4144 | dest->nonnull = 1; |
| 4145 | if (dest->o_assignment == NOT_ASSIGNMENT) | 4145 | if (dest->o_assignment == NOT_ASSIGNMENT) |
| 4146 | dest->o_quote ^= 1; | 4146 | dest->o_escape ^= 1; |
| 4147 | debug_printf_parse("parse_stream_dquoted return 0\n"); | 4147 | debug_printf_parse("parse_stream_dquoted return 0\n"); |
| 4148 | return 0; | 4148 | return 0; |
| 4149 | } | 4149 | } |
| @@ -4157,8 +4157,8 @@ static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote | |||
| 4157 | if (ch != '\n') { | 4157 | if (ch != '\n') { |
| 4158 | next = i_peek(input); | 4158 | next = i_peek(input); |
| 4159 | } | 4159 | } |
| 4160 | debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n", | 4160 | debug_printf_parse(": ch=%c (%d) m=%d escape=%d\n", |
| 4161 | ch, ch, m, dest->o_quote); | 4161 | ch, ch, m, dest->o_escape); |
| 4162 | /* Basically, checking every CHAR_SPECIAL char except '"' */ | 4162 | /* Basically, checking every CHAR_SPECIAL char except '"' */ |
| 4163 | if (ch == '\\') { | 4163 | if (ch == '\\') { |
| 4164 | if (next == EOF) { | 4164 | if (next == EOF) { |
| @@ -4225,13 +4225,13 @@ static int parse_stream(o_string *dest, struct parse_context *ctx, | |||
| 4225 | int is_in_dquote; | 4225 | int is_in_dquote; |
| 4226 | int next; | 4226 | int next; |
| 4227 | 4227 | ||
| 4228 | /* Only double-quote state is handled in the state variable dest->o_quote. | 4228 | /* Double-quote state is handled in the state variable is_in_dquote. |
| 4229 | * A single-quote triggers a bypass of the main loop until its mate is | 4229 | * A single-quote triggers a bypass of the main loop until its mate is |
| 4230 | * found. When recursing, quote state is passed in via dest->o_quote. */ | 4230 | * found. When recursing, quote state is passed in via dest->o_escape. */ |
| 4231 | 4231 | ||
| 4232 | debug_printf_parse("parse_stream entered, end_trigger='%s' dest->o_assignment:%d\n", end_trigger, dest->o_assignment); | 4232 | debug_printf_parse("parse_stream entered, end_trigger='%s' dest->o_assignment:%d\n", end_trigger, dest->o_assignment); |
| 4233 | 4233 | ||
| 4234 | is_in_dquote = dest->o_quote; | 4234 | is_in_dquote = dest->o_escape; |
| 4235 | while (1) { | 4235 | while (1) { |
| 4236 | if (is_in_dquote) { | 4236 | if (is_in_dquote) { |
| 4237 | if (parse_stream_dquoted(dest, input, '"')) | 4237 | if (parse_stream_dquoted(dest, input, '"')) |
| @@ -4248,8 +4248,8 @@ static int parse_stream(o_string *dest, struct parse_context *ctx, | |||
| 4248 | next = i_peek(input); | 4248 | next = i_peek(input); |
| 4249 | } | 4249 | } |
| 4250 | } | 4250 | } |
| 4251 | debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n", | 4251 | debug_printf_parse(": ch=%c (%d) m=%d escape=%d\n", |
| 4252 | ch, ch, m, dest->o_quote); | 4252 | ch, ch, m, dest->o_escape); |
| 4253 | if (m == CHAR_ORDINARY) { | 4253 | if (m == CHAR_ORDINARY) { |
| 4254 | o_addQchr(dest, ch); | 4254 | o_addQchr(dest, ch); |
| 4255 | if ((dest->o_assignment == MAYBE_ASSIGNMENT | 4255 | if ((dest->o_assignment == MAYBE_ASSIGNMENT |
| @@ -4365,7 +4365,7 @@ static int parse_stream(o_string *dest, struct parse_context *ctx, | |||
| 4365 | dest->nonnull = 1; | 4365 | dest->nonnull = 1; |
| 4366 | is_in_dquote ^= 1; /* invert */ | 4366 | is_in_dquote ^= 1; /* invert */ |
| 4367 | if (dest->o_assignment == NOT_ASSIGNMENT) | 4367 | if (dest->o_assignment == NOT_ASSIGNMENT) |
| 4368 | dest->o_quote ^= 1; | 4368 | dest->o_escape ^= 1; |
| 4369 | break; | 4369 | break; |
| 4370 | #if ENABLE_HUSH_TICK | 4370 | #if ENABLE_HUSH_TICK |
| 4371 | case '`': { | 4371 | case '`': { |
| @@ -4594,7 +4594,7 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
| 4594 | } | 4594 | } |
| 4595 | #endif | 4595 | #endif |
| 4596 | /*temp.nonnull = 0; - o_free does it below */ | 4596 | /*temp.nonnull = 0; - o_free does it below */ |
| 4597 | /*temp.o_quote = 0; - o_free does it below */ | 4597 | /*temp.o_escape = 0; - o_free does it below */ |
| 4598 | free_pipe_list(ctx.list_head, /* indent: */ 0); | 4598 | free_pipe_list(ctx.list_head, /* indent: */ 0); |
| 4599 | /* Discard all unprocessed line input, force prompt on */ | 4599 | /* Discard all unprocessed line input, force prompt on */ |
| 4600 | inp->p = NULL; | 4600 | inp->p = NULL; |
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right new file mode 100644 index 000000000..a35fe893f --- /dev/null +++ b/shell/hush_test/hush-arith/arith.right | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | Format: 'expected actual' | ||
| 2 | 163 163 | ||
| 3 | 4 4 | ||
| 4 | 16 16 | ||
| 5 | 8 8 | ||
| 6 | 2 2 | ||
| 7 | 4 4 | ||
| 8 | 2 2 | ||
| 9 | 2 2 | ||
| 10 | 1 1 | ||
| 11 | 0 0 | ||
| 12 | 0 0 | ||
| 13 | 0 0 | ||
| 14 | 1 1 | ||
| 15 | 1 1 | ||
| 16 | 2 2 | ||
| 17 | -3 -3 | ||
| 18 | -2 -2 | ||
| 19 | 1 1 | ||
| 20 | 0 0 | ||
| 21 | 2 2 | ||
| 22 | 131072 131072 | ||
| 23 | 29 29 | ||
| 24 | 33 33 | ||
| 25 | 49 49 | ||
| 26 | 1 1 | ||
| 27 | 1 1 | ||
| 28 | 0 0 | ||
| 29 | 0 0 | ||
| 30 | 1 1 | ||
| 31 | 1 1 | ||
| 32 | 1 1 | ||
| 33 | 2 2 | ||
| 34 | 3 3 | ||
| 35 | 1 1 | ||
| 36 | 58 58 | ||
| 37 | 2 2 | ||
| 38 | 60 60 | ||
| 39 | 1 1 | ||
| 40 | 256 256 | ||
| 41 | 16 16 | ||
| 42 | 62 62 | ||
| 43 | 4 4 | ||
| 44 | 29 29 | ||
| 45 | 5 5 | ||
| 46 | -4 -4 | ||
| 47 | 4 4 | ||
| 48 | 1 1 | ||
| 49 | 32 32 | ||
| 50 | 32 32 | ||
| 51 | 1 1 | ||
| 52 | 1 1 | ||
| 53 | 32 32 | ||
| 54 | 20 20 | ||
| 55 | 30 30 | ||
| 56 | 20 20 | ||
| 57 | 30 30 | ||
| 58 | hush: arith: syntax error | ||
| 59 | 6 6 | ||
| 60 | 6,5,3 6,5,3 | ||
| 61 | 263 263 | ||
| 62 | 255 255 | ||
| 63 | 40 40 | ||
| 64 | hush: arith: syntax error | ||
| 65 | hush: arith: divide by zero | ||
| 66 | hush: can't exec 'let': No such file or directory | ||
| 67 | hush: arith: syntax error | ||
| 68 | hush: can't exec 'let': No such file or directory | ||
| 69 | abc | ||
| 70 | def | ||
| 71 | ghi | ||
| 72 | hush: arith: syntax error | ||
| 73 | 16 16 | ||
| 74 | hush: arith: syntax error | ||
| 75 | hush: arith: syntax error | ||
| 76 | hush: arith: syntax error | ||
| 77 | 9 9 | ||
| 78 | hush: arith: syntax error | ||
| 79 | hush: arith: syntax error | ||
| 80 | 9 9 | ||
| 81 | 9 9 | ||
| 82 | 9 9 | ||
| 83 | 7 7 | ||
| 84 | 7 | ||
| 85 | 4 4 | ||
| 86 | 32767 32767 | ||
| 87 | 32768 32768 | ||
| 88 | 131072 131072 | ||
| 89 | 2147483647 2147483647 | ||
| 90 | 1 1 | ||
| 91 | 4 4 | ||
| 92 | 4 4 | ||
| 93 | 5 5 | ||
| 94 | 5 5 | ||
| 95 | 4 4 | ||
| 96 | 3 3 | ||
| 97 | 3 3 | ||
| 98 | 4 4 | ||
| 99 | 4 4 | ||
| 100 | hush: arith: syntax error | ||
| 101 | hush: arith: syntax error | ||
| 102 | hush: arith: syntax error | ||
| 103 | hush: arith: syntax error | ||
| 104 | hush: arith: syntax error | ||
| 105 | 4 4 | ||
| 106 | 7 7 | ||
| 107 | -7 -7 | ||
| 108 | hush: arith: syntax error | ||
| 109 | hush: arith: syntax error | ||
| 110 | hush: arith: syntax error | ||
| 111 | hush: arith: syntax error | ||
| 112 | 6 6 | ||
| 113 | 3 3 | ||
| 114 | 7 7 | ||
| 115 | 4 4 | ||
| 116 | 0 0 | ||
| 117 | 3 3 | ||
| 118 | 7 7 | ||
| 119 | 2 2 | ||
| 120 | -2 -2 | ||
| 121 | 1 1 | ||
| 122 | hush: arith: syntax error | ||
| 123 | hush: arith: syntax error | ||
| 124 | hush: arith: syntax error | ||
| 125 | hush: arith: syntax error | ||
| 126 | hush: arith: syntax error | ||
| 127 | 5 5 | ||
| 128 | 1 1 | ||
| 129 | 4 4 | ||
| 130 | 0 0 | ||
| 131 | hush: arith: syntax error | ||
| 132 | hush: arith: syntax error | ||
| 133 | 8 12 | ||
| 134 | hush: arith: syntax error | ||
| 135 | 42 | ||
| 136 | 42 | ||
| 137 | 42 | ||
| 138 | hush: can't exec 'a[b[c]d]=e': No such file or directory | ||
diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests new file mode 100755 index 000000000..57e66e888 --- /dev/null +++ b/shell/hush_test/hush-arith/arith.tests | |||
| @@ -0,0 +1,302 @@ | |||
| 1 | #ash# set +o posix | ||
| 2 | #ash# declare -i iv jv | ||
| 3 | |||
| 4 | echo "Format: 'expected actual'" | ||
| 5 | |||
| 6 | iv=$(( 3 + 5 * 32 )) | ||
| 7 | echo 163 $iv | ||
| 8 | #ash# iv=iv+3 | ||
| 9 | #ash# echo 166 $iv | ||
| 10 | iv=2 | ||
| 11 | jv=iv | ||
| 12 | |||
| 13 | : $((jv *= 2)) ##hush## let "jv *= 2" | ||
| 14 | echo 4 $jv | ||
| 15 | jv=$(( $jv << 2 )) | ||
| 16 | echo 16 $jv | ||
| 17 | |||
| 18 | : $((jv=$jv / 2)) ##hush## let jv="$jv / 2" | ||
| 19 | echo 8 $jv | ||
| 20 | #ash# jv="jv >> 2" | ||
| 21 | : $((jv=jv >> 2)) ##hush## let jv="jv >> 2" | ||
| 22 | echo 2 $jv | ||
| 23 | |||
| 24 | iv=$((iv+ $jv)) | ||
| 25 | echo 4 $iv | ||
| 26 | echo 2 $((iv -= jv)) | ||
| 27 | echo 2 $iv | ||
| 28 | echo 1 $(( iv == jv )) | ||
| 29 | echo 0 $(( iv != $jv )) | ||
| 30 | echo 0 $(( iv < jv )) | ||
| 31 | echo 0 $(( $iv > $jv )) | ||
| 32 | echo 1 $(( iv <= $jv )) | ||
| 33 | echo 1 $(( $iv >= jv )) | ||
| 34 | |||
| 35 | echo 2 $jv | ||
| 36 | echo -3 $(( ~$jv )) | ||
| 37 | echo -2 $(( ~1 )) | ||
| 38 | echo 1 $(( ! 0 )) | ||
| 39 | |||
| 40 | echo 0 $(( jv % 2 )) | ||
| 41 | echo 2 $(( $iv % 4 )) | ||
| 42 | |||
| 43 | echo 131072 $(( iv <<= 16 )) | ||
| 44 | echo 29 $(( iv %= 33 )) | ||
| 45 | |||
| 46 | echo 33 $(( 33 & 55 )) | ||
| 47 | echo 49 $(( 33 | 17 )) | ||
| 48 | |||
| 49 | echo 1 $(( iv && $jv )) | ||
| 50 | echo 1 $(( $iv || jv )) | ||
| 51 | |||
| 52 | echo 0 $(( iv && 0 )) | ||
| 53 | echo 0 $(( iv & 0 )) | ||
| 54 | echo 1 $(( iv && 1 )) | ||
| 55 | echo 1 $(( iv & 1 )) | ||
| 56 | |||
| 57 | echo 1 $(( $jv || 0 )) | ||
| 58 | echo 2 $(( jv | 0 )) | ||
| 59 | echo 3 $(( jv | 1 )) | ||
| 60 | echo 1 $(( $jv || 1 )) | ||
| 61 | |||
| 62 | : $((iv *= jv)) ##hush## let 'iv *= jv' | ||
| 63 | echo 58 $iv | ||
| 64 | echo 2 $jv | ||
| 65 | : $((jv += $iv)) ##hush## let "jv += $iv" | ||
| 66 | echo 60 $jv | ||
| 67 | |||
| 68 | echo 1 $(( jv /= iv )) | ||
| 69 | echo 256 $(( jv <<= 8 )) | ||
| 70 | echo 16 $(( jv >>= 4 )) | ||
| 71 | |||
| 72 | echo 62 $(( iv |= 4 )) | ||
| 73 | echo 4 $(( iv &= 4 )) | ||
| 74 | |||
| 75 | echo 29 $(( iv += (jv + 9))) | ||
| 76 | echo 5 $(( (iv + 4) % 7 )) | ||
| 77 | |||
| 78 | # unary plus, minus | ||
| 79 | echo -4 $(( +4 - 8 )) | ||
| 80 | echo 4 $(( -4 + 8 )) | ||
| 81 | |||
| 82 | # conditional expressions | ||
| 83 | echo 1 $(( 4<5 ? 1 : 32)) | ||
| 84 | echo 32 $(( 4>5 ? 1 : 32)) | ||
| 85 | echo 32 $(( 4>(2+3) ? 1 : 32)) | ||
| 86 | echo 1 $(( 4<(2+3) ? 1 : 32)) | ||
| 87 | echo 1 $(( (2+2)<(2+3) ? 1 : 32)) | ||
| 88 | echo 32 $(( (2+2)>(2+3) ? 1 : 32)) | ||
| 89 | |||
| 90 | # check that the unevaluated part of the ternary operator does not do | ||
| 91 | # evaluation or assignment | ||
| 92 | x=i+=2 | ||
| 93 | y=j+=2 | ||
| 94 | #ash# declare -i i=1 j=1 | ||
| 95 | i=1 | ||
| 96 | j=1 | ||
| 97 | echo 20 $((1 ? 20 : (x+=2))) | ||
| 98 | #ash# echo $i,$x # ash mishandles this | ||
| 99 | echo 30 $((0 ? (y+=2) : 30)) | ||
| 100 | #ash# echo $j,$y # ash mishandles this | ||
| 101 | |||
| 102 | x=i+=2 | ||
| 103 | y=j+=2 | ||
| 104 | #ash# declare -i i=1 j=1 | ||
| 105 | i=1 | ||
| 106 | j=1 | ||
| 107 | echo 20 $((1 ? 20 : (x+=2))) | ||
| 108 | #ash# echo $i,$x # ash mishandles this | ||
| 109 | echo 30 $((0 ? (y+=2) : 30)) | ||
| 110 | #ash# echo $i,$y # ash mishandles this | ||
| 111 | |||
| 112 | # check precedence of assignment vs. conditional operator | ||
| 113 | # should be an error | ||
| 114 | #ash# declare -i x=2 | ||
| 115 | x=2 | ||
| 116 | #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: | ||
| 117 | ( y=$((1 ? 20 : x+=2)) ) | ||
| 118 | |||
| 119 | # check precedence of assignment vs. conditional operator | ||
| 120 | #ash# declare -i x=2 | ||
| 121 | x=2 | ||
| 122 | # ash says "line NNN: syntax error: 0 ? x+=2 : 20" | ||
| 123 | #ash# echo 20 $((0 ? x+=2 : 20)) | ||
| 124 | |||
| 125 | # associativity of assignment-operator operator | ||
| 126 | #ash# declare -i i=1 j=2 k=3 | ||
| 127 | i=1 | ||
| 128 | j=2 | ||
| 129 | k=3 | ||
| 130 | echo 6 $((i += j += k)) | ||
| 131 | echo 6,5,3 $i,$j,$k | ||
| 132 | |||
| 133 | # octal, hex | ||
| 134 | echo 263 $(( 0x100 | 007 )) | ||
| 135 | echo 255 $(( 0xff )) | ||
| 136 | #ash# echo 255 $(( 16#ff )) | ||
| 137 | #ash# echo 127 $(( 16#FF/2 )) | ||
| 138 | #ash# echo 36 $(( 8#44 )) | ||
| 139 | |||
| 140 | echo 40 $(( 8 ^ 32 )) | ||
| 141 | |||
| 142 | #ash# # other bases | ||
| 143 | #ash# echo 10 $(( 16#a )) | ||
| 144 | #ash# echo 10 $(( 32#a )) | ||
| 145 | #ash# echo 10 $(( 56#a )) | ||
| 146 | #ash# echo 10 $(( 64#a )) | ||
| 147 | #ash# | ||
| 148 | #ash# echo 10 $(( 16#A )) | ||
| 149 | #ash# echo 10 $(( 32#A )) | ||
| 150 | #ash# echo 36 $(( 56#A )) | ||
| 151 | #ash# echo 36 $(( 64#A )) | ||
| 152 | #ash# | ||
| 153 | #ash# echo 62 $(( 64#@ )) | ||
| 154 | #ash# echo 63 $(( 64#_ )) | ||
| 155 | |||
| 156 | #ash# # weird bases (error) | ||
| 157 | #ash# echo $(( 3425#56 )) | ||
| 158 | |||
| 159 | #ash# # missing number after base | ||
| 160 | #ash# echo 0 $(( 2# )) | ||
| 161 | |||
| 162 | # these should generate errors | ||
| 163 | ( echo $(( 7 = 43 )) ) | ||
| 164 | #ash# echo $(( 2#44 )) | ||
| 165 | ( echo $(( 44 / 0 )) ) | ||
| 166 | ( let 'jv += $iv' ) | ||
| 167 | ( echo $(( jv += \$iv )) ) | ||
| 168 | ( let 'rv = 7 + (43 * 6' ) | ||
| 169 | |||
| 170 | #ash# # more errors | ||
| 171 | #ash# declare -i i | ||
| 172 | #ash# i=0#4 | ||
| 173 | #ash# i=2#110#11 | ||
| 174 | |||
| 175 | ((echo abc; echo def;); echo ghi) | ||
| 176 | |||
| 177 | #ash# if (((4+4) + (4 + 7))); then | ||
| 178 | #ash# echo ok | ||
| 179 | #ash# fi | ||
| 180 | |||
| 181 | #ash# (()) # make sure the null expression works OK | ||
| 182 | |||
| 183 | #ash# a=(0 2 4 6) | ||
| 184 | #ash# echo 6 $(( a[1] + a[2] )) | ||
| 185 | #ash# echo 1 $(( (a[1] + a[2]) == a[3] )) | ||
| 186 | #ash# (( (a[1] + a[2]) == a[3] )) ; echo 0 $? | ||
| 187 | |||
| 188 | # test pushing and popping the expression stack | ||
| 189 | unset A | ||
| 190 | A="4 + " | ||
| 191 | ( echo A $(( ( 4 + A ) + 4 )) ) | ||
| 192 | A="3 + 5" | ||
| 193 | echo 16 $(( ( 4 + A ) + 4 )) | ||
| 194 | |||
| 195 | # badly-formed conditional expressions | ||
| 196 | ( echo $(( 4 ? : $A )) ) | ||
| 197 | ( echo $(( 1 ? 20 )) ) | ||
| 198 | ( echo $(( 4 ? 20 : )) ) | ||
| 199 | |||
| 200 | # precedence and short-circuit evaluation | ||
| 201 | B=9 | ||
| 202 | echo 9 $B | ||
| 203 | |||
| 204 | # error | ||
| 205 | ( echo $(( 0 && B=42 )); echo 9 $B ) | ||
| 206 | |||
| 207 | # error | ||
| 208 | ( echo $(( 1 || B=88 )); echo 9 $B ) | ||
| 209 | |||
| 210 | # ash mistakenly evaluates B=... below | ||
| 211 | #ash# echo 0 $(( 0 && (B=42) )) | ||
| 212 | echo 9 $B | ||
| 213 | #ash# echo 0 $(( (${$} - $$) && (B=42) )) | ||
| 214 | echo 9 $B | ||
| 215 | #ash# echo 1 $(( 1 || (B=88) )) | ||
| 216 | echo 9 $B | ||
| 217 | |||
| 218 | |||
| 219 | # until command with (( )) command | ||
| 220 | x=7 | ||
| 221 | |||
| 222 | echo 7 $x | ||
| 223 | #ash# until (( x == 4 )) | ||
| 224 | until test "$x" = 4 | ||
| 225 | do | ||
| 226 | echo $x | ||
| 227 | x=4 | ||
| 228 | done | ||
| 229 | |||
| 230 | echo 4 $x | ||
| 231 | |||
| 232 | # exponentiation | ||
| 233 | echo 32767 $(( 2**15 - 1)) | ||
| 234 | echo 32768 $(( 2**(16-1))) | ||
| 235 | echo 131072 $(( 2**16*2 )) | ||
| 236 | echo 2147483647 $(( 2**31-1)) | ||
| 237 | echo 1 $(( 2**0 )) | ||
| 238 | |||
| 239 | # {pre,post}-{inc,dec}rement and associated errors | ||
| 240 | |||
| 241 | x=4 | ||
| 242 | |||
| 243 | echo 4 $x | ||
| 244 | echo 4 $(( x++ )) | ||
| 245 | echo 5 $x | ||
| 246 | echo 5 $(( x-- )) | ||
| 247 | echo 4 $x | ||
| 248 | |||
| 249 | echo 3 $(( --x )) | ||
| 250 | echo 3 $x | ||
| 251 | |||
| 252 | echo 4 $(( ++x )) | ||
| 253 | echo 4 $x | ||
| 254 | |||
| 255 | # bash 3.2 apparently thinks that ++7 is 7 | ||
| 256 | #ash# echo 7 $(( ++7 )) | ||
| 257 | ( echo $(( 7-- )) ) | ||
| 258 | |||
| 259 | ( echo $(( --x=7 )) ) | ||
| 260 | ( echo $(( ++x=7 )) ) | ||
| 261 | |||
| 262 | ( echo $(( x++=7 )) ) | ||
| 263 | ( echo $(( x--=7 )) ) | ||
| 264 | |||
| 265 | echo 4 $x | ||
| 266 | |||
| 267 | echo 7 $(( +7 )) | ||
| 268 | echo -7 $(( -7 )) | ||
| 269 | |||
| 270 | # bash 3.2 apparently thinks that ++7 is 7 | ||
| 271 | #ash# echo $(( ++7 )) | ||
| 272 | #ash# echo $(( --7 )) | ||
| 273 | |||
| 274 | ${THIS_SH} ./arith1.sub | ||
| 275 | ${THIS_SH} ./arith2.sub | ||
| 276 | |||
| 277 | x=4 | ||
| 278 | y=7 | ||
| 279 | |||
| 280 | #ash# (( x=8 , y=12 )) | ||
| 281 | x=8 | ||
| 282 | y=12 | ||
| 283 | echo $x $y | ||
| 284 | |||
| 285 | #ash# # should be an error | ||
| 286 | #ash# (( x=9 y=41 )) | ||
| 287 | |||
| 288 | # These are errors | ||
| 289 | unset b | ||
| 290 | ( echo $((a b)) ) | ||
| 291 | #ash# ((a b)) | ||
| 292 | |||
| 293 | n=42 | ||
| 294 | printf "%d\n" $n | ||
| 295 | printf "%i\n" $n | ||
| 296 | #ash# echo $(( 8#$(printf "%o\n" $n) )) | ||
| 297 | printf "%u\n" $n | ||
| 298 | #ash# echo $(( 16#$(printf "%x\n" $n) )) | ||
| 299 | #ash# echo $(( 16#$(printf "%X\n" $n) )) | ||
| 300 | |||
| 301 | # causes longjmp botches through bash-2.05b | ||
| 302 | a[b[c]d]=e | ||
diff --git a/shell/hush_test/hush-arith/arith1.sub b/shell/hush_test/hush-arith/arith1.sub new file mode 100755 index 000000000..80aa99922 --- /dev/null +++ b/shell/hush_test/hush-arith/arith1.sub | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | # test of redone post-increment and post-decrement code | ||
| 2 | ( echo $(( 4-- )) ) | ||
| 3 | ( echo $(( 4++ )) ) | ||
| 4 | ( echo $(( 4 -- )) ) | ||
| 5 | ( echo $(( 4 ++ )) ) | ||
| 6 | |||
| 7 | #ash# (( array[0]++ )) | ||
| 8 | #ash# echo ${array} | ||
| 9 | |||
| 10 | #ash# (( array[0] ++ )) | ||
| 11 | #ash# echo ${array} | ||
| 12 | |||
| 13 | #ash# (( a++ )) | ||
| 14 | #ash# echo $a | ||
| 15 | #ash# (( a ++ )) | ||
| 16 | #ash# echo $a | ||
| 17 | a=2 | ||
| 18 | |||
| 19 | echo 6 $(( a ++ + 4 )) | ||
| 20 | echo 3 $a | ||
| 21 | |||
| 22 | echo 7 $(( a+++4 )) | ||
| 23 | echo 4 $a | ||
| 24 | |||
| 25 | echo 0 $(( a---4 )) | ||
| 26 | echo 3 $a | ||
| 27 | |||
| 28 | echo 7 $(( a -- + 4 )) | ||
| 29 | echo 2 $a | ||
| 30 | |||
| 31 | echo -2 $(( a -- - 4 )) | ||
| 32 | echo 1 $a | ||
| 33 | |||
| 34 | #ash# (( ++ + 7 )) | ||
| 35 | |||
| 36 | #ash# (( ++ )) | ||
| 37 | ( echo $(( +++7 )) ) | ||
| 38 | # bash 3.2 apparently thinks that ++ +7 is 7 | ||
| 39 | #ash# echo $(( ++ + 7 )) | ||
| 40 | #ash# (( -- )) | ||
diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub new file mode 100755 index 000000000..f7e3c9235 --- /dev/null +++ b/shell/hush_test/hush-arith/arith2.sub | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | # bash 3.2 apparently thinks that ++7 is 7 etc | ||
| 2 | ( echo $(( --7 )) ) | ||
| 3 | ( echo $(( ++7 )) ) | ||
| 4 | ( echo $(( -- 7 )) ) | ||
| 5 | ( echo $(( ++ 7 )) ) | ||
| 6 | |||
| 7 | #ash# ((++array[0] )) | ||
| 8 | #ash# echo 1 $array | ||
| 9 | #ash# (( ++ array[0] )) | ||
| 10 | #ash# echo 2 $array | ||
| 11 | |||
| 12 | #ash# (( ++a )) | ||
| 13 | #ash# echo 1 $a | ||
| 14 | #ash# (( ++ a )) | ||
| 15 | #ash# echo 2 $a | ||
| 16 | |||
| 17 | #ash# (( --a )) | ||
| 18 | #ash# echo 1 $a | ||
| 19 | #ash# (( -- a )) | ||
| 20 | #ash# echo 0 $a | ||
| 21 | a=0 | ||
| 22 | |||
| 23 | echo 5 $(( 4 + ++a )) | ||
| 24 | echo 1 $a | ||
| 25 | |||
| 26 | # ash doesn't handle it right... | ||
| 27 | #ash# echo 6 $(( 4+++a )) | ||
| 28 | #ash# echo 2 $a | ||
| 29 | a=2 | ||
| 30 | |||
| 31 | # ash doesn't handle it right... | ||
| 32 | #ash# echo 3 $(( 4---a )) | ||
| 33 | #ash# echo 1 $a | ||
| 34 | a=1 | ||
| 35 | |||
| 36 | echo 4 $(( 4 - -- a )) | ||
| 37 | echo 0 $a | ||
| 38 | |||
| 39 | #ash# (( -- )) | ||
| 40 | # bash 3.2 apparently thinks that ---7 is -7 | ||
| 41 | #ash# echo $(( ---7 )) | ||
| 42 | ( echo $(( -- - 7 )) ) | ||
| 43 | |||
| 44 | #ash# (( ++ )) | ||
| 45 | # bash 3.2: 7 | ||
| 46 | #ash# echo 7 $(( ++7 )) | ||
| 47 | ( echo $(( ++ + 7 )) ) | ||
| 48 | |||
| 49 | # bash 3.2: -7 | ||
| 50 | #ash# echo -7 $(( ++-7 )) | ||
| 51 | # bash 3.2: -7 | ||
| 52 | #ash# echo -7 $(( ++ - 7 )) | ||
| 53 | |||
| 54 | # bash 3.2: 7 | ||
| 55 | #ash# echo 7 $(( +--7 )) | ||
| 56 | # bash 3.2: 7 | ||
| 57 | #ash# echo 7 $(( -- + 7 )) | ||
