diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-10-31 03:34:07 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-10-31 03:34:07 +0100 |
| commit | d2241f59022c38d4b171e56eea42e216ecccfdd9 (patch) | |
| tree | edb75c2530f493c9e3f193f346d8125fe79c107f /coreutils | |
| parent | 112453acf24520b4655f9f36da41d8ac591b1a60 (diff) | |
| download | busybox-w32-d2241f59022c38d4b171e56eea42e216ecccfdd9.tar.gz busybox-w32-d2241f59022c38d4b171e56eea42e216ecccfdd9.tar.bz2 busybox-w32-d2241f59022c38d4b171e56eea42e216ecccfdd9.zip | |
shell: better support of [[ ]] bashism
Still rather rudimentary for ash
function old new delta
binop 433 589 +156
check_operator 65 101 +36
done_word 736 769 +33
test_main 405 418 +13
parse_stream 2227 2238 +11
ops_texts 124 133 +9
ops_table 80 86 +6
run_pipe 1557 1562 +5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 8/0 up/down: 269/0) Total: 269 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/test.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/coreutils/test.c b/coreutils/test.c index a08986130..ac7b546a3 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
| @@ -76,6 +76,8 @@ | |||
| 76 | //usage: "1\n" | 76 | //usage: "1\n" |
| 77 | 77 | ||
| 78 | #include "libbb.h" | 78 | #include "libbb.h" |
| 79 | #include <regex.h> | ||
| 80 | #include <fnmatch.h> | ||
| 79 | 81 | ||
| 80 | /* This is a NOFORK applet. Be very careful! */ | 82 | /* This is a NOFORK applet. Be very careful! */ |
| 81 | 83 | ||
| @@ -146,6 +148,14 @@ | |||
| 146 | 148 | ||
| 147 | #define TEST_DEBUG 0 | 149 | #define TEST_DEBUG 0 |
| 148 | 150 | ||
| 151 | #if ENABLE_TEST2 \ | ||
| 152 | || (ENABLE_ASH_BASH_COMPAT && ENABLE_ASH_TEST) \ | ||
| 153 | || (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) | ||
| 154 | # define BASH_TEST2 1 | ||
| 155 | #else | ||
| 156 | # define BASH_TEST2 0 | ||
| 157 | #endif | ||
| 158 | |||
| 149 | enum token { | 159 | enum token { |
| 150 | EOI, | 160 | EOI, |
| 151 | 161 | ||
| @@ -184,6 +194,10 @@ enum token { | |||
| 184 | STRLT, | 194 | STRLT, |
| 185 | STRGT, | 195 | STRGT, |
| 186 | 196 | ||
| 197 | #if BASH_TEST2 | ||
| 198 | REGEX, | ||
| 199 | #endif | ||
| 200 | |||
| 187 | INTEQ, /* int ops */ | 201 | INTEQ, /* int ops */ |
| 188 | INTNE, | 202 | INTNE, |
| 189 | INTGE, | 203 | INTGE, |
| @@ -257,6 +271,9 @@ static const char *const TOKSTR[] = { | |||
| 257 | "STRNE", | 271 | "STRNE", |
| 258 | "STRLT", | 272 | "STRLT", |
| 259 | "STRGT", | 273 | "STRGT", |
| 274 | #if BASH_TEST2 | ||
| 275 | "REGEX", | ||
| 276 | #endif | ||
| 260 | "INTEQ", | 277 | "INTEQ", |
| 261 | "INTNE", | 278 | "INTNE", |
| 262 | "INTGE", | 279 | "INTGE", |
| @@ -320,6 +337,9 @@ static const struct operator_t ops_table[] = { | |||
| 320 | { /* "!=" */ STRNE , BINOP }, | 337 | { /* "!=" */ STRNE , BINOP }, |
| 321 | { /* "<" */ STRLT , BINOP }, | 338 | { /* "<" */ STRLT , BINOP }, |
| 322 | { /* ">" */ STRGT , BINOP }, | 339 | { /* ">" */ STRGT , BINOP }, |
| 340 | #if BASH_TEST2 | ||
| 341 | { /* "=~" */ REGEX , BINOP }, | ||
| 342 | #endif | ||
| 323 | { /* "-eq"*/ INTEQ , BINOP }, | 343 | { /* "-eq"*/ INTEQ , BINOP }, |
| 324 | { /* "-ne"*/ INTNE , BINOP }, | 344 | { /* "-ne"*/ INTNE , BINOP }, |
| 325 | { /* "-ge"*/ INTGE , BINOP }, | 345 | { /* "-ge"*/ INTGE , BINOP }, |
| @@ -332,6 +352,10 @@ static const struct operator_t ops_table[] = { | |||
| 332 | { /* "!" */ UNOT , BUNOP }, | 352 | { /* "!" */ UNOT , BUNOP }, |
| 333 | { /* "-a" */ BAND , BBINOP }, | 353 | { /* "-a" */ BAND , BBINOP }, |
| 334 | { /* "-o" */ BOR , BBINOP }, | 354 | { /* "-o" */ BOR , BBINOP }, |
| 355 | #if BASH_TEST2 | ||
| 356 | { /* "&&" */ BAND , BBINOP }, | ||
| 357 | { /* "||" */ BOR , BBINOP }, | ||
| 358 | #endif | ||
| 335 | { /* "(" */ LPAREN , PAREN }, | 359 | { /* "(" */ LPAREN , PAREN }, |
| 336 | { /* ")" */ RPAREN , PAREN }, | 360 | { /* ")" */ RPAREN , PAREN }, |
| 337 | }; | 361 | }; |
| @@ -365,6 +389,9 @@ static const char ops_texts[] ALIGN1 = | |||
| 365 | "!=" "\0" | 389 | "!=" "\0" |
| 366 | "<" "\0" | 390 | "<" "\0" |
| 367 | ">" "\0" | 391 | ">" "\0" |
| 392 | #if BASH_TEST2 | ||
| 393 | "=~" "\0" | ||
| 394 | #endif | ||
| 368 | "-eq" "\0" | 395 | "-eq" "\0" |
| 369 | "-ne" "\0" | 396 | "-ne" "\0" |
| 370 | "-ge" "\0" | 397 | "-ge" "\0" |
| @@ -377,6 +404,10 @@ static const char ops_texts[] ALIGN1 = | |||
| 377 | "!" "\0" | 404 | "!" "\0" |
| 378 | "-a" "\0" | 405 | "-a" "\0" |
| 379 | "-o" "\0" | 406 | "-o" "\0" |
| 407 | #if BASH_TEST2 | ||
| 408 | "&&" "\0" | ||
| 409 | "||" "\0" | ||
| 410 | #endif | ||
| 380 | "(" "\0" | 411 | "(" "\0" |
| 381 | ")" "\0" | 412 | ")" "\0" |
| 382 | ; | 413 | ; |
| @@ -397,6 +428,9 @@ struct test_statics { | |||
| 397 | const struct operator_t *last_operator; | 428 | const struct operator_t *last_operator; |
| 398 | gid_t *group_array; | 429 | gid_t *group_array; |
| 399 | int ngroups; | 430 | int ngroups; |
| 431 | #if BASH_TEST2 | ||
| 432 | bool bash_test2; | ||
| 433 | #endif | ||
| 400 | jmp_buf leaving; | 434 | jmp_buf leaving; |
| 401 | }; | 435 | }; |
| 402 | 436 | ||
| @@ -408,6 +442,7 @@ extern struct test_statics *const test_ptr_to_statics; | |||
| 408 | #define last_operator (S.last_operator) | 442 | #define last_operator (S.last_operator) |
| 409 | #define group_array (S.group_array ) | 443 | #define group_array (S.group_array ) |
| 410 | #define ngroups (S.ngroups ) | 444 | #define ngroups (S.ngroups ) |
| 445 | #define bash_test2 (S.bash_test2 ) | ||
| 411 | #define leaving (S.leaving ) | 446 | #define leaving (S.leaving ) |
| 412 | 447 | ||
| 413 | #define INIT_S() do { \ | 448 | #define INIT_S() do { \ |
| @@ -501,6 +536,20 @@ static enum token check_operator(const char *s) | |||
| 501 | n = index_in_strings(ops_texts, s); | 536 | n = index_in_strings(ops_texts, s); |
| 502 | if (n < 0) | 537 | if (n < 0) |
| 503 | return OPERAND; | 538 | return OPERAND; |
| 539 | |||
| 540 | #if BASH_TEST2 | ||
| 541 | if (ops_table[n].op_num == REGEX && !bash_test2) { | ||
| 542 | /* =~ is only for [[ ]] */ | ||
| 543 | return OPERAND; | ||
| 544 | } | ||
| 545 | if (ops_table[n].op_num == BAND || ops_table[n].op_num == BOR) { | ||
| 546 | /* [ ] accepts -a and -o but not && and || */ | ||
| 547 | /* [[ ]] accepts && and || but not -a and -o */ | ||
| 548 | if (bash_test2 == (s[0] == '-')) | ||
| 549 | return OPERAND; | ||
| 550 | } | ||
| 551 | #endif | ||
| 552 | |||
| 504 | last_operator = &ops_table[n]; | 553 | last_operator = &ops_table[n]; |
| 505 | return ops_table[n].op_num; | 554 | return ops_table[n].op_num; |
| 506 | } | 555 | } |
| @@ -536,6 +585,29 @@ static int binop(void) | |||
| 536 | /*if (op->op_num == INTLT)*/ | 585 | /*if (op->op_num == INTLT)*/ |
| 537 | return val1 < val2; | 586 | return val1 < val2; |
| 538 | } | 587 | } |
| 588 | #if BASH_TEST2 | ||
| 589 | if (bash_test2) { | ||
| 590 | if (op->op_num == STREQ) { | ||
| 591 | val1 = fnmatch(opnd2, opnd1, 0); | ||
| 592 | return val1 == 0; | ||
| 593 | } | ||
| 594 | if (op->op_num == STRNE) { | ||
| 595 | val1 = fnmatch(opnd2, opnd1, 0); | ||
| 596 | return val1 != 0; | ||
| 597 | } | ||
| 598 | if (op->op_num == REGEX) { | ||
| 599 | regex_t re_buffer; | ||
| 600 | memset(&re_buffer, 0, sizeof(re_buffer)); | ||
| 601 | if (regcomp(&re_buffer, opnd2, REG_EXTENDED)) { // REG_NEWLINE? | ||
| 602 | /* Bad regex */ | ||
| 603 | longjmp(leaving, 2); /* [[ a =~ * ]]; echo $? - prints 2 (silently, no error msg) */ | ||
| 604 | } | ||
| 605 | val1 = regexec(&re_buffer, opnd1, 0, NULL, 0); | ||
| 606 | regfree(&re_buffer); | ||
| 607 | return val1 == 0; | ||
| 608 | } | ||
| 609 | } | ||
| 610 | #endif | ||
| 539 | if (is_str_op(op->op_num)) { | 611 | if (is_str_op(op->op_num)) { |
| 540 | val1 = strcmp(opnd1, opnd2); | 612 | val1 = strcmp(opnd1, opnd2); |
| 541 | if (op->op_num == STREQ) | 613 | if (op->op_num == STREQ) |
| @@ -824,6 +896,9 @@ int test_main(int argc, char **argv) | |||
| 824 | { | 896 | { |
| 825 | int res; | 897 | int res; |
| 826 | const char *arg0; | 898 | const char *arg0; |
| 899 | #if BASH_TEST2 | ||
| 900 | bool bt2 = 0; | ||
| 901 | #endif | ||
| 827 | 902 | ||
| 828 | arg0 = bb_basename(argv[0]); | 903 | arg0 = bb_basename(argv[0]); |
| 829 | if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_TEST || ENABLE_HUSH_TEST) | 904 | if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_TEST || ENABLE_HUSH_TEST) |
| @@ -840,6 +915,9 @@ int test_main(int argc, char **argv) | |||
| 840 | bb_simple_error_msg("missing ]]"); | 915 | bb_simple_error_msg("missing ]]"); |
| 841 | return 2; | 916 | return 2; |
| 842 | } | 917 | } |
| 918 | #if BASH_TEST2 | ||
| 919 | bt2 = 1; | ||
| 920 | #endif | ||
| 843 | } | 921 | } |
| 844 | argv[argc] = NULL; | 922 | argv[argc] = NULL; |
| 845 | } | 923 | } |
| @@ -848,6 +926,10 @@ int test_main(int argc, char **argv) | |||
| 848 | /* We must do DEINIT_S() prior to returning */ | 926 | /* We must do DEINIT_S() prior to returning */ |
| 849 | INIT_S(); | 927 | INIT_S(); |
| 850 | 928 | ||
| 929 | #if BASH_TEST2 | ||
| 930 | bash_test2 = bt2; | ||
| 931 | #endif | ||
| 932 | |||
| 851 | res = setjmp(leaving); | 933 | res = setjmp(leaving); |
| 852 | if (res) | 934 | if (res) |
| 853 | goto ret; | 935 | goto ret; |
