diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-11 14:00:38 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-11 14:00:38 +0100 |
commit | 7d4aec0c3ecb0c10de60070616d9d8fb9b074497 (patch) | |
tree | c4edb5852c5d64a3310d521a7b12e03d3e5fc1d1 /shell | |
parent | a8a075acfee7b31c4da00cf3500b67354339e3b9 (diff) | |
download | busybox-w32-7d4aec0c3ecb0c10de60070616d9d8fb9b074497.tar.gz busybox-w32-7d4aec0c3ecb0c10de60070616d9d8fb9b074497.tar.bz2 busybox-w32-7d4aec0c3ecb0c10de60070616d9d8fb9b074497.zip |
ash: split bash compatible extensions into separate defines. No code changes
Splitting these options makes it self-documenting about what
bash-compatible features we have.
Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 175 |
1 files changed, 101 insertions, 74 deletions
diff --git a/shell/ash.c b/shell/ash.c index 866c7de05..02545f565 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -145,15 +145,10 @@ | |||
145 | //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o | 145 | //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o |
146 | 146 | ||
147 | /* | 147 | /* |
148 | * The following should be set to reflect the type of system you have: | 148 | * DEBUG=1 to compile in debugging ('set -o debug' turns on) |
149 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. | 149 | * DEBUG=2 to compile in and turn on debugging. |
150 | * define SYSV if you are running under System V. | 150 | * When debugging is on ("set -o debug" was executed, or DEBUG=2), |
151 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) | 151 | * debugging info is written to ./trace, quit signal generates core dump. |
152 | * define DEBUG=2 to compile in and turn on debugging. | ||
153 | * | ||
154 | * When debugging is on (DEBUG is 1 and "set -o debug" was executed), | ||
155 | * debugging info will be written to ./trace and a quit signal | ||
156 | * will generate a core dump. | ||
157 | */ | 152 | */ |
158 | #define DEBUG 0 | 153 | #define DEBUG 0 |
159 | /* Tweak debug output verbosity here */ | 154 | /* Tweak debug output verbosity here */ |
@@ -170,9 +165,30 @@ | |||
170 | #include <fnmatch.h> | 165 | #include <fnmatch.h> |
171 | #include <sys/times.h> | 166 | #include <sys/times.h> |
172 | #include <sys/utsname.h> /* for setting $HOSTNAME */ | 167 | #include <sys/utsname.h> /* for setting $HOSTNAME */ |
173 | |||
174 | #include "busybox.h" /* for applet_names */ | 168 | #include "busybox.h" /* for applet_names */ |
175 | 169 | ||
170 | /* So far, all bash compat is controlled by one config option */ | ||
171 | /* Separate defines document which part of code implements what */ | ||
172 | /* function keyword */ | ||
173 | #define BASH_FUNCTION ENABLE_ASH_BASH_COMPAT | ||
174 | #define IF_BASH_FUNCTION IF_ASH_BASH_COMPAT | ||
175 | /* &>file */ | ||
176 | #define BASH_REDIR_OUTPUT ENABLE_ASH_BASH_COMPAT | ||
177 | #define IF_BASH_REDIR_OUTPUT IF_ASH_BASH_COMPAT | ||
178 | /* $'...' */ | ||
179 | #define BASH_DOLLAR_SQUOTE ENABLE_ASH_BASH_COMPAT | ||
180 | #define IF_BASH_DOLLAR_SQUOTE IF_ASH_BASH_COMPAT | ||
181 | #define BASH_PATTERN_SUBST ENABLE_ASH_BASH_COMPAT | ||
182 | #define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT | ||
183 | #define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT | ||
184 | #define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT | ||
185 | /* [[ EXPR ]] */ | ||
186 | #define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST) | ||
187 | #define BASH_SOURCE ENABLE_ASH_BASH_COMPAT | ||
188 | #define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT | ||
189 | #define BASH_HOSTNAME_VAR ENABLE_ASH_BASH_COMPAT | ||
190 | #define BASH_SHLVL_VAR ENABLE_ASH_BASH_COMPAT | ||
191 | |||
176 | #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 | 192 | #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 |
177 | /* Bionic at least up to version 24 has no glob() */ | 193 | /* Bionic at least up to version 24 has no glob() */ |
178 | # undef ENABLE_ASH_INTERNAL_GLOB | 194 | # undef ENABLE_ASH_INTERNAL_GLOB |
@@ -250,7 +266,7 @@ static const char *const optletters_optnames[] = { | |||
250 | "b" "notify", | 266 | "b" "notify", |
251 | "u" "nounset", | 267 | "u" "nounset", |
252 | "\0" "vi" | 268 | "\0" "vi" |
253 | #if ENABLE_ASH_BASH_COMPAT | 269 | #if BASH_PIPEFAIL |
254 | ,"\0" "pipefail" | 270 | ,"\0" "pipefail" |
255 | #endif | 271 | #endif |
256 | #if DEBUG | 272 | #if DEBUG |
@@ -327,14 +343,14 @@ struct globals_misc { | |||
327 | #define bflag optlist[11] | 343 | #define bflag optlist[11] |
328 | #define uflag optlist[12] | 344 | #define uflag optlist[12] |
329 | #define viflag optlist[13] | 345 | #define viflag optlist[13] |
330 | #if ENABLE_ASH_BASH_COMPAT | 346 | #if BASH_PIPEFAIL |
331 | # define pipefail optlist[14] | 347 | # define pipefail optlist[14] |
332 | #else | 348 | #else |
333 | # define pipefail 0 | 349 | # define pipefail 0 |
334 | #endif | 350 | #endif |
335 | #if DEBUG | 351 | #if DEBUG |
336 | # define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT] | 352 | # define nolog optlist[14 + BASH_PIPEFAIL] |
337 | # define debug optlist[15 + ENABLE_ASH_BASH_COMPAT] | 353 | # define debug optlist[15 + BASH_PIPEFAIL] |
338 | #endif | 354 | #endif |
339 | 355 | ||
340 | /* trap handler commands */ | 356 | /* trap handler commands */ |
@@ -655,8 +671,10 @@ out2str(const char *p) | |||
655 | #define VSTRIMLEFT 0x8 /* ${var#pattern} */ | 671 | #define VSTRIMLEFT 0x8 /* ${var#pattern} */ |
656 | #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ | 672 | #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ |
657 | #define VSLENGTH 0xa /* ${#var} */ | 673 | #define VSLENGTH 0xa /* ${#var} */ |
658 | #if ENABLE_ASH_BASH_COMPAT | 674 | #if BASH_SUBSTR |
659 | #define VSSUBSTR 0xc /* ${var:position:length} */ | 675 | #define VSSUBSTR 0xc /* ${var:position:length} */ |
676 | #endif | ||
677 | #if BASH_PATTERN_SUBST | ||
660 | #define VSREPLACE 0xd /* ${var/pattern/replacement} */ | 678 | #define VSREPLACE 0xd /* ${var/pattern/replacement} */ |
661 | #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */ | 679 | #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */ |
662 | #endif | 680 | #endif |
@@ -683,7 +701,7 @@ static const char dolatstr[] ALIGN1 = { | |||
683 | #define NDEFUN 14 | 701 | #define NDEFUN 14 |
684 | #define NARG 15 | 702 | #define NARG 15 |
685 | #define NTO 16 | 703 | #define NTO 16 |
686 | #if ENABLE_ASH_BASH_COMPAT | 704 | #if BASH_REDIR_OUTPUT |
687 | #define NTO2 17 | 705 | #define NTO2 17 |
688 | #endif | 706 | #endif |
689 | #define NCLOBBER 18 | 707 | #define NCLOBBER 18 |
@@ -1093,7 +1111,7 @@ shcmd(union node *cmd, FILE *fp) | |||
1093 | case NTO: s = ">>"+1; dftfd = 1; break; | 1111 | case NTO: s = ">>"+1; dftfd = 1; break; |
1094 | case NCLOBBER: s = ">|"; dftfd = 1; break; | 1112 | case NCLOBBER: s = ">|"; dftfd = 1; break; |
1095 | case NAPPEND: s = ">>"; dftfd = 1; break; | 1113 | case NAPPEND: s = ">>"; dftfd = 1; break; |
1096 | #if ENABLE_ASH_BASH_COMPAT | 1114 | #if BASH_REDIR_OUTPUT |
1097 | case NTO2: | 1115 | case NTO2: |
1098 | #endif | 1116 | #endif |
1099 | case NTOFD: s = ">&"; dftfd = 1; break; | 1117 | case NTOFD: s = ">&"; dftfd = 1; break; |
@@ -4455,7 +4473,8 @@ cmdputs(const char *s) | |||
4455 | static const char vstype[VSTYPE + 1][3] = { | 4473 | static const char vstype[VSTYPE + 1][3] = { |
4456 | "", "}", "-", "+", "?", "=", | 4474 | "", "}", "-", "+", "?", "=", |
4457 | "%", "%%", "#", "##" | 4475 | "%", "%%", "#", "##" |
4458 | IF_ASH_BASH_COMPAT(, ":", "/", "//") | 4476 | IF_BASH_SUBSTR(, ":") |
4477 | IF_BASH_PATTERN_SUBST(, "/", "//") | ||
4459 | }; | 4478 | }; |
4460 | 4479 | ||
4461 | const char *p, *str; | 4480 | const char *p, *str; |
@@ -4682,7 +4701,7 @@ cmdtxt(union node *n) | |||
4682 | case NAPPEND: | 4701 | case NAPPEND: |
4683 | p = ">>"; | 4702 | p = ">>"; |
4684 | goto redir; | 4703 | goto redir; |
4685 | #if ENABLE_ASH_BASH_COMPAT | 4704 | #if BASH_REDIR_OUTPUT |
4686 | case NTO2: | 4705 | case NTO2: |
4687 | #endif | 4706 | #endif |
4688 | case NTOFD: | 4707 | case NTOFD: |
@@ -5209,7 +5228,7 @@ openredirect(union node *redir) | |||
5209 | goto ecreate; | 5228 | goto ecreate; |
5210 | break; | 5229 | break; |
5211 | case NTO: | 5230 | case NTO: |
5212 | #if ENABLE_ASH_BASH_COMPAT | 5231 | #if BASH_REDIR_OUTPUT |
5213 | case NTO2: | 5232 | case NTO2: |
5214 | #endif | 5233 | #endif |
5215 | /* Take care of noclobber mode. */ | 5234 | /* Take care of noclobber mode. */ |
@@ -5370,7 +5389,7 @@ redirect(union node *redir, int flags) | |||
5370 | union node *tmp = redir; | 5389 | union node *tmp = redir; |
5371 | do { | 5390 | do { |
5372 | sv_pos++; | 5391 | sv_pos++; |
5373 | #if ENABLE_ASH_BASH_COMPAT | 5392 | #if BASH_REDIR_OUTPUT |
5374 | if (tmp->nfile.type == NTO2) | 5393 | if (tmp->nfile.type == NTO2) |
5375 | sv_pos++; | 5394 | sv_pos++; |
5376 | #endif | 5395 | #endif |
@@ -5412,7 +5431,7 @@ redirect(union node *redir, int flags) | |||
5412 | continue; | 5431 | continue; |
5413 | } | 5432 | } |
5414 | } | 5433 | } |
5415 | #if ENABLE_ASH_BASH_COMPAT | 5434 | #if BASH_REDIR_OUTPUT |
5416 | redirect_more: | 5435 | redirect_more: |
5417 | #endif | 5436 | #endif |
5418 | if (need_to_remember(sv, fd)) { | 5437 | if (need_to_remember(sv, fd)) { |
@@ -5465,12 +5484,12 @@ redirect(union node *redir, int flags) | |||
5465 | } | 5484 | } |
5466 | } else if (fd != newfd) { /* move newfd to fd */ | 5485 | } else if (fd != newfd) { /* move newfd to fd */ |
5467 | dup2_or_raise(newfd, fd); | 5486 | dup2_or_raise(newfd, fd); |
5468 | #if ENABLE_ASH_BASH_COMPAT | 5487 | #if BASH_REDIR_OUTPUT |
5469 | if (!(redir->nfile.type == NTO2 && fd == 2)) | 5488 | if (!(redir->nfile.type == NTO2 && fd == 2)) |
5470 | #endif | 5489 | #endif |
5471 | close(newfd); | 5490 | close(newfd); |
5472 | } | 5491 | } |
5473 | #if ENABLE_ASH_BASH_COMPAT | 5492 | #if BASH_REDIR_OUTPUT |
5474 | if (redir->nfile.type == NTO2 && fd == 1) { | 5493 | if (redir->nfile.type == NTO2 && fd == 1) { |
5475 | /* We already redirected it to fd 1, now copy it to 2 */ | 5494 | /* We already redirected it to fd 1, now copy it to 2 */ |
5476 | newfd = 1; | 5495 | newfd = 1; |
@@ -5787,15 +5806,15 @@ static char * | |||
5787 | rmescapes(char *str, int flag) | 5806 | rmescapes(char *str, int flag) |
5788 | { | 5807 | { |
5789 | static const char qchars[] ALIGN1 = { | 5808 | static const char qchars[] ALIGN1 = { |
5790 | IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' }; | 5809 | IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' }; |
5791 | 5810 | ||
5792 | char *p, *q, *r; | 5811 | char *p, *q, *r; |
5793 | unsigned inquotes; | 5812 | unsigned inquotes; |
5794 | unsigned protect_against_glob; | 5813 | unsigned protect_against_glob; |
5795 | unsigned globbing; | 5814 | unsigned globbing; |
5796 | IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;) | 5815 | IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;) |
5797 | 5816 | ||
5798 | p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash)); | 5817 | p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash)); |
5799 | if (!p) | 5818 | if (!p) |
5800 | return str; | 5819 | return str; |
5801 | 5820 | ||
@@ -5847,7 +5866,7 @@ rmescapes(char *str, int flag) | |||
5847 | protect_against_glob = 0; | 5866 | protect_against_glob = 0; |
5848 | goto copy; | 5867 | goto copy; |
5849 | } | 5868 | } |
5850 | #if ENABLE_ASH_BASH_COMPAT | 5869 | #if BASH_PATTERN_SUBST |
5851 | else if (*p == '/' && slash) { | 5870 | else if (*p == '/' && slash) { |
5852 | /* stop handling globbing and mark location of slash */ | 5871 | /* stop handling globbing and mark location of slash */ |
5853 | globbing = slash = 0; | 5872 | globbing = slash = 0; |
@@ -6494,10 +6513,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6494 | char *loc; | 6513 | char *loc; |
6495 | char *rmesc, *rmescend; | 6514 | char *rmesc, *rmescend; |
6496 | char *str; | 6515 | char *str; |
6497 | IF_ASH_BASH_COMPAT(char *repl = NULL;) | 6516 | IF_BASH_SUBSTR(int pos, len, orig_len;) |
6498 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) | ||
6499 | int amount, resetloc; | 6517 | int amount, resetloc; |
6500 | IF_ASH_BASH_COMPAT(int workloc;) | 6518 | IF_BASH_PATTERN_SUBST(int workloc;) |
6519 | IF_BASH_PATTERN_SUBST(char *repl = NULL;) | ||
6501 | int zero; | 6520 | int zero; |
6502 | char *(*scan)(char*, char*, char*, char*, int, int); | 6521 | char *(*scan)(char*, char*, char*, char*, int, int); |
6503 | 6522 | ||
@@ -6522,7 +6541,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6522 | varunset(p, varname, startp, varflags); | 6541 | varunset(p, varname, startp, varflags); |
6523 | /* NOTREACHED */ | 6542 | /* NOTREACHED */ |
6524 | 6543 | ||
6525 | #if ENABLE_ASH_BASH_COMPAT | 6544 | #if BASH_SUBSTR |
6526 | case VSSUBSTR: | 6545 | case VSSUBSTR: |
6527 | //TODO: support more general format ${v:EXPR:EXPR}, | 6546 | //TODO: support more general format ${v:EXPR:EXPR}, |
6528 | // where EXPR follows $(()) rules | 6547 | // where EXPR follows $(()) rules |
@@ -6591,17 +6610,19 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6591 | amount = loc - expdest; | 6610 | amount = loc - expdest; |
6592 | STADJUST(amount, expdest); | 6611 | STADJUST(amount, expdest); |
6593 | return loc; | 6612 | return loc; |
6594 | #endif | 6613 | #endif /* BASH_SUBSTR */ |
6595 | } | 6614 | } |
6596 | 6615 | ||
6597 | resetloc = expdest - (char *)stackblock(); | 6616 | resetloc = expdest - (char *)stackblock(); |
6598 | 6617 | ||
6618 | #if BASH_PATTERN_SUBST | ||
6599 | /* We'll comeback here if we grow the stack while handling | 6619 | /* We'll comeback here if we grow the stack while handling |
6600 | * a VSREPLACE or VSREPLACEALL, since our pointers into the | 6620 | * a VSREPLACE or VSREPLACEALL, since our pointers into the |
6601 | * stack will need rebasing, and we'll need to remove our work | 6621 | * stack will need rebasing, and we'll need to remove our work |
6602 | * areas each time | 6622 | * areas each time |
6603 | */ | 6623 | */ |
6604 | IF_ASH_BASH_COMPAT(restart:) | 6624 | restart: |
6625 | #endif | ||
6605 | 6626 | ||
6606 | amount = expdest - ((char *)stackblock() + resetloc); | 6627 | amount = expdest - ((char *)stackblock() + resetloc); |
6607 | STADJUST(-amount, expdest); | 6628 | STADJUST(-amount, expdest); |
@@ -6626,11 +6647,11 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6626 | * RMESCAPE_SLASH causes preglob to work differently on the pattern | 6647 | * RMESCAPE_SLASH causes preglob to work differently on the pattern |
6627 | * and string. It's only used on the first call. | 6648 | * and string. It's only used on the first call. |
6628 | */ | 6649 | */ |
6629 | preglob(str, IF_ASH_BASH_COMPAT( | 6650 | preglob(str, IF_BASH_PATTERN_SUBST( |
6630 | (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? | 6651 | (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? |
6631 | RMESCAPE_SLASH :) 0); | 6652 | RMESCAPE_SLASH : ) 0); |
6632 | 6653 | ||
6633 | #if ENABLE_ASH_BASH_COMPAT | 6654 | #if BASH_PATTERN_SUBST |
6634 | workloc = expdest - (char *)stackblock(); | 6655 | workloc = expdest - (char *)stackblock(); |
6635 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 6656 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
6636 | char *idx, *end; | 6657 | char *idx, *end; |
@@ -6731,7 +6752,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6731 | STADJUST(-amount, expdest); | 6752 | STADJUST(-amount, expdest); |
6732 | return startp; | 6753 | return startp; |
6733 | } | 6754 | } |
6734 | #endif /* ENABLE_ASH_BASH_COMPAT */ | 6755 | #endif /* BASH_PATTERN_SUBST */ |
6735 | 6756 | ||
6736 | subtype -= VSTRIMRIGHT; | 6757 | subtype -= VSTRIMRIGHT; |
6737 | #if DEBUG | 6758 | #if DEBUG |
@@ -6999,8 +7020,10 @@ evalvar(char *p, int flag, struct strlist *var_str_list) | |||
6999 | case VSTRIMLEFTMAX: | 7020 | case VSTRIMLEFTMAX: |
7000 | case VSTRIMRIGHT: | 7021 | case VSTRIMRIGHT: |
7001 | case VSTRIMRIGHTMAX: | 7022 | case VSTRIMRIGHTMAX: |
7002 | #if ENABLE_ASH_BASH_COMPAT | 7023 | #if BASH_SUBSTR |
7003 | case VSSUBSTR: | 7024 | case VSSUBSTR: |
7025 | #endif | ||
7026 | #if BASH_PATTERN_SUBST | ||
7004 | case VSREPLACE: | 7027 | case VSREPLACE: |
7005 | case VSREPLACEALL: | 7028 | case VSREPLACEALL: |
7006 | #endif | 7029 | #endif |
@@ -7924,7 +7947,7 @@ enum { | |||
7924 | TESAC, | 7947 | TESAC, |
7925 | TFI, | 7948 | TFI, |
7926 | TFOR, | 7949 | TFOR, |
7927 | #if ENABLE_ASH_BASH_COMPAT | 7950 | #if BASH_FUNCTION |
7928 | TFUNCTION, | 7951 | TFUNCTION, |
7929 | #endif | 7952 | #endif |
7930 | TIF, | 7953 | TIF, |
@@ -7962,7 +7985,7 @@ enum { | |||
7962 | /* 19 */ | (1u << TESAC) | 7985 | /* 19 */ | (1u << TESAC) |
7963 | /* 20 */ | (1u << TFI) | 7986 | /* 20 */ | (1u << TFI) |
7964 | /* 21 */ | (0u << TFOR) | 7987 | /* 21 */ | (0u << TFOR) |
7965 | #if ENABLE_ASH_BASH_COMPAT | 7988 | #if BASH_FUNCTION |
7966 | /* 22 */ | (0u << TFUNCTION) | 7989 | /* 22 */ | (0u << TFUNCTION) |
7967 | #endif | 7990 | #endif |
7968 | /* 23 */ | (0u << TIF) | 7991 | /* 23 */ | (0u << TIF) |
@@ -8000,7 +8023,7 @@ static const char *const tokname_array[] = { | |||
8000 | "esac", | 8023 | "esac", |
8001 | "fi", | 8024 | "fi", |
8002 | "for", | 8025 | "for", |
8003 | #if ENABLE_ASH_BASH_COMPAT | 8026 | #if BASH_FUNCTION |
8004 | "function", | 8027 | "function", |
8005 | #endif | 8028 | #endif |
8006 | "if", | 8029 | "if", |
@@ -8244,7 +8267,7 @@ static const uint8_t nodesize[N_NUMBER] ALIGN1 = { | |||
8244 | [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)), | 8267 | [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)), |
8245 | [NARG ] = SHELL_ALIGN(sizeof(struct narg)), | 8268 | [NARG ] = SHELL_ALIGN(sizeof(struct narg)), |
8246 | [NTO ] = SHELL_ALIGN(sizeof(struct nfile)), | 8269 | [NTO ] = SHELL_ALIGN(sizeof(struct nfile)), |
8247 | #if ENABLE_ASH_BASH_COMPAT | 8270 | #if BASH_REDIR_OUTPUT |
8248 | [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)), | 8271 | [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)), |
8249 | #endif | 8272 | #endif |
8250 | [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)), | 8273 | [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)), |
@@ -8326,7 +8349,7 @@ calcsize(int funcblocksize, union node *n) | |||
8326 | funcblocksize = calcsize(funcblocksize, n->narg.next); | 8349 | funcblocksize = calcsize(funcblocksize, n->narg.next); |
8327 | break; | 8350 | break; |
8328 | case NTO: | 8351 | case NTO: |
8329 | #if ENABLE_ASH_BASH_COMPAT | 8352 | #if BASH_REDIR_OUTPUT |
8330 | case NTO2: | 8353 | case NTO2: |
8331 | #endif | 8354 | #endif |
8332 | case NCLOBBER: | 8355 | case NCLOBBER: |
@@ -8440,7 +8463,7 @@ copynode(union node *n) | |||
8440 | new->narg.next = copynode(n->narg.next); | 8463 | new->narg.next = copynode(n->narg.next); |
8441 | break; | 8464 | break; |
8442 | case NTO: | 8465 | case NTO: |
8443 | #if ENABLE_ASH_BASH_COMPAT | 8466 | #if BASH_REDIR_OUTPUT |
8444 | case NTO2: | 8467 | case NTO2: |
8445 | #endif | 8468 | #endif |
8446 | case NCLOBBER: | 8469 | case NCLOBBER: |
@@ -8873,14 +8896,14 @@ expredir(union node *n) | |||
8873 | case NFROMTO: | 8896 | case NFROMTO: |
8874 | case NFROM: | 8897 | case NFROM: |
8875 | case NTO: | 8898 | case NTO: |
8876 | #if ENABLE_ASH_BASH_COMPAT | 8899 | #if BASH_REDIR_OUTPUT |
8877 | case NTO2: | 8900 | case NTO2: |
8878 | #endif | 8901 | #endif |
8879 | case NCLOBBER: | 8902 | case NCLOBBER: |
8880 | case NAPPEND: | 8903 | case NAPPEND: |
8881 | expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); | 8904 | expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); |
8882 | TRACE(("expredir expanded to '%s'\n", fn.list->text)); | 8905 | TRACE(("expredir expanded to '%s'\n", fn.list->text)); |
8883 | #if ENABLE_ASH_BASH_COMPAT | 8906 | #if BASH_REDIR_OUTPUT |
8884 | store_expfname: | 8907 | store_expfname: |
8885 | #endif | 8908 | #endif |
8886 | #if 0 | 8909 | #if 0 |
@@ -8902,7 +8925,7 @@ expredir(union node *n) | |||
8902 | expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); | 8925 | expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); |
8903 | if (fn.list == NULL) | 8926 | if (fn.list == NULL) |
8904 | ash_msg_and_raise_error("redir error"); | 8927 | ash_msg_and_raise_error("redir error"); |
8905 | #if ENABLE_ASH_BASH_COMPAT | 8928 | #if BASH_REDIR_OUTPUT |
8906 | //FIXME: we used expandarg with different args! | 8929 | //FIXME: we used expandarg with different args! |
8907 | if (!isdigit_str9(fn.list->text)) { | 8930 | if (!isdigit_str9(fn.list->text)) { |
8908 | /* >&file, not >&fd */ | 8931 | /* >&file, not >&fd */ |
@@ -9298,7 +9321,7 @@ static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, a | |||
9298 | #if ENABLE_ASH_PRINTF | 9321 | #if ENABLE_ASH_PRINTF |
9299 | static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } | 9322 | static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } |
9300 | #endif | 9323 | #endif |
9301 | #if ENABLE_ASH_TEST | 9324 | #if ENABLE_ASH_TEST || BASH_TEST2 |
9302 | static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } | 9325 | static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } |
9303 | #endif | 9326 | #endif |
9304 | 9327 | ||
@@ -9308,9 +9331,9 @@ static const struct builtincmd builtintab[] = { | |||
9308 | { BUILTIN_SPEC_REG ":" , truecmd }, | 9331 | { BUILTIN_SPEC_REG ":" , truecmd }, |
9309 | #if ENABLE_ASH_TEST | 9332 | #if ENABLE_ASH_TEST |
9310 | { BUILTIN_REGULAR "[" , testcmd }, | 9333 | { BUILTIN_REGULAR "[" , testcmd }, |
9311 | # if ENABLE_ASH_BASH_COMPAT | 9334 | #endif |
9335 | #if BASH_TEST2 | ||
9312 | { BUILTIN_REGULAR "[[" , testcmd }, | 9336 | { BUILTIN_REGULAR "[[" , testcmd }, |
9313 | # endif | ||
9314 | #endif | 9337 | #endif |
9315 | #if ENABLE_ASH_ALIAS | 9338 | #if ENABLE_ASH_ALIAS |
9316 | { BUILTIN_REG_ASSG "alias" , aliascmd }, | 9339 | { BUILTIN_REG_ASSG "alias" , aliascmd }, |
@@ -9363,7 +9386,7 @@ static const struct builtincmd builtintab[] = { | |||
9363 | { BUILTIN_SPEC_REG "return" , returncmd }, | 9386 | { BUILTIN_SPEC_REG "return" , returncmd }, |
9364 | { BUILTIN_SPEC_REG "set" , setcmd }, | 9387 | { BUILTIN_SPEC_REG "set" , setcmd }, |
9365 | { BUILTIN_SPEC_REG "shift" , shiftcmd }, | 9388 | { BUILTIN_SPEC_REG "shift" , shiftcmd }, |
9366 | #if ENABLE_ASH_BASH_COMPAT | 9389 | #if BASH_SOURCE |
9367 | { BUILTIN_SPEC_REG "source" , dotcmd }, | 9390 | { BUILTIN_SPEC_REG "source" , dotcmd }, |
9368 | #endif | 9391 | #endif |
9369 | #if ENABLE_ASH_TEST | 9392 | #if ENABLE_ASH_TEST |
@@ -9386,7 +9409,7 @@ static const struct builtincmd builtintab[] = { | |||
9386 | #define COMMANDCMD (builtintab + \ | 9409 | #define COMMANDCMD (builtintab + \ |
9387 | /* . : */ 2 + \ | 9410 | /* . : */ 2 + \ |
9388 | /* [ */ 1 * ENABLE_ASH_TEST + \ | 9411 | /* [ */ 1 * ENABLE_ASH_TEST + \ |
9389 | /* [[ */ 1 * ENABLE_ASH_TEST * ENABLE_ASH_BASH_COMPAT + \ | 9412 | /* [[ */ 1 * BASH_TEST2 + \ |
9390 | /* alias */ 1 * ENABLE_ASH_ALIAS + \ | 9413 | /* alias */ 1 * ENABLE_ASH_ALIAS + \ |
9391 | /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \ | 9414 | /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \ |
9392 | /* break cd cddir */ 3) | 9415 | /* break cd cddir */ 3) |
@@ -11008,10 +11031,10 @@ simplecmd(void) | |||
11008 | union node *vars, **vpp; | 11031 | union node *vars, **vpp; |
11009 | union node **rpp, *redir; | 11032 | union node **rpp, *redir; |
11010 | int savecheckkwd; | 11033 | int savecheckkwd; |
11011 | #if ENABLE_ASH_BASH_COMPAT | 11034 | #if BASH_TEST2 |
11012 | smallint double_brackets_flag = 0; | 11035 | smallint double_brackets_flag = 0; |
11013 | smallint function_flag = 0; | ||
11014 | #endif | 11036 | #endif |
11037 | IF_BASH_FUNCTION(smallint function_flag = 0;) | ||
11015 | 11038 | ||
11016 | args = NULL; | 11039 | args = NULL; |
11017 | app = &args; | 11040 | app = &args; |
@@ -11026,12 +11049,14 @@ simplecmd(void) | |||
11026 | checkkwd = savecheckkwd; | 11049 | checkkwd = savecheckkwd; |
11027 | t = readtoken(); | 11050 | t = readtoken(); |
11028 | switch (t) { | 11051 | switch (t) { |
11029 | #if ENABLE_ASH_BASH_COMPAT | 11052 | #if BASH_FUNCTION |
11030 | case TFUNCTION: | 11053 | case TFUNCTION: |
11031 | if (peektoken() != TWORD) | 11054 | if (peektoken() != TWORD) |
11032 | raise_error_unexpected_syntax(TWORD); | 11055 | raise_error_unexpected_syntax(TWORD); |
11033 | function_flag = 1; | 11056 | function_flag = 1; |
11034 | break; | 11057 | break; |
11058 | #endif | ||
11059 | #if BASH_TEST2 | ||
11035 | case TAND: /* "&&" */ | 11060 | case TAND: /* "&&" */ |
11036 | case TOR: /* "||" */ | 11061 | case TOR: /* "||" */ |
11037 | if (!double_brackets_flag) { | 11062 | if (!double_brackets_flag) { |
@@ -11045,7 +11070,7 @@ simplecmd(void) | |||
11045 | n->type = NARG; | 11070 | n->type = NARG; |
11046 | /*n->narg.next = NULL; - stzalloc did it */ | 11071 | /*n->narg.next = NULL; - stzalloc did it */ |
11047 | n->narg.text = wordtext; | 11072 | n->narg.text = wordtext; |
11048 | #if ENABLE_ASH_BASH_COMPAT | 11073 | #if BASH_TEST2 |
11049 | if (strcmp("[[", wordtext) == 0) | 11074 | if (strcmp("[[", wordtext) == 0) |
11050 | double_brackets_flag = 1; | 11075 | double_brackets_flag = 1; |
11051 | else if (strcmp("]]", wordtext) == 0) | 11076 | else if (strcmp("]]", wordtext) == 0) |
@@ -11060,7 +11085,7 @@ simplecmd(void) | |||
11060 | app = &n->narg.next; | 11085 | app = &n->narg.next; |
11061 | savecheckkwd = 0; | 11086 | savecheckkwd = 0; |
11062 | } | 11087 | } |
11063 | #if ENABLE_ASH_BASH_COMPAT | 11088 | #if BASH_FUNCTION |
11064 | if (function_flag) { | 11089 | if (function_flag) { |
11065 | checkkwd = CHKNL | CHKKWD; | 11090 | checkkwd = CHKNL | CHKKWD; |
11066 | switch (peektoken()) { | 11091 | switch (peektoken()) { |
@@ -11090,7 +11115,7 @@ simplecmd(void) | |||
11090 | parsefname(); /* read name of redirection file */ | 11115 | parsefname(); /* read name of redirection file */ |
11091 | break; | 11116 | break; |
11092 | case TLP: | 11117 | case TLP: |
11093 | IF_ASH_BASH_COMPAT(do_func:) | 11118 | IF_BASH_FUNCTION(do_func:) |
11094 | if (args && app == &args->narg.next | 11119 | if (args && app == &args->narg.next |
11095 | && !vars && !redir | 11120 | && !vars && !redir |
11096 | ) { | 11121 | ) { |
@@ -11098,7 +11123,7 @@ simplecmd(void) | |||
11098 | const char *name; | 11123 | const char *name; |
11099 | 11124 | ||
11100 | /* We have a function */ | 11125 | /* We have a function */ |
11101 | if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP) | 11126 | if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP) |
11102 | raise_error_unexpected_syntax(TRP); | 11127 | raise_error_unexpected_syntax(TRP); |
11103 | name = n->narg.text; | 11128 | name = n->narg.text; |
11104 | if (!goodname(name) | 11129 | if (!goodname(name) |
@@ -11111,7 +11136,7 @@ simplecmd(void) | |||
11111 | n->narg.next = parse_command(); | 11136 | n->narg.next = parse_command(); |
11112 | return n; | 11137 | return n; |
11113 | } | 11138 | } |
11114 | IF_ASH_BASH_COMPAT(function_flag = 0;) | 11139 | IF_BASH_FUNCTION(function_flag = 0;) |
11115 | /* fall through */ | 11140 | /* fall through */ |
11116 | default: | 11141 | default: |
11117 | tokpushback = 1; | 11142 | tokpushback = 1; |
@@ -11292,7 +11317,7 @@ parse_command(void) | |||
11292 | n1 = list(0); | 11317 | n1 = list(0); |
11293 | t = TEND; | 11318 | t = TEND; |
11294 | break; | 11319 | break; |
11295 | IF_ASH_BASH_COMPAT(case TFUNCTION:) | 11320 | IF_BASH_FUNCTION(case TFUNCTION:) |
11296 | case TWORD: | 11321 | case TWORD: |
11297 | case TREDIR: | 11322 | case TREDIR: |
11298 | tokpushback = 1; | 11323 | tokpushback = 1; |
@@ -11325,7 +11350,7 @@ parse_command(void) | |||
11325 | return n1; | 11350 | return n1; |
11326 | } | 11351 | } |
11327 | 11352 | ||
11328 | #if ENABLE_ASH_BASH_COMPAT | 11353 | #if BASH_DOLLAR_SQUOTE |
11329 | static int | 11354 | static int |
11330 | decode_dollar_squote(void) | 11355 | decode_dollar_squote(void) |
11331 | { | 11356 | { |
@@ -11410,7 +11435,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11410 | IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ | 11435 | IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ |
11411 | int dqvarnest; /* levels of variables expansion within double quotes */ | 11436 | int dqvarnest; /* levels of variables expansion within double quotes */ |
11412 | 11437 | ||
11413 | IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) | 11438 | IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;) |
11414 | 11439 | ||
11415 | startlinno = g_parsefile->linno; | 11440 | startlinno = g_parsefile->linno; |
11416 | bqlist = NULL; | 11441 | bqlist = NULL; |
@@ -11445,7 +11470,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11445 | USTPUTC(c, out); | 11470 | USTPUTC(c, out); |
11446 | break; | 11471 | break; |
11447 | case CCTL: | 11472 | case CCTL: |
11448 | #if ENABLE_ASH_BASH_COMPAT | 11473 | #if BASH_DOLLAR_SQUOTE |
11449 | if (c == '\\' && bash_dollar_squote) { | 11474 | if (c == '\\' && bash_dollar_squote) { |
11450 | c = decode_dollar_squote(); | 11475 | c = decode_dollar_squote(); |
11451 | if (c == '\0') { | 11476 | if (c == '\0') { |
@@ -11506,7 +11531,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11506 | dblquote = 1; | 11531 | dblquote = 1; |
11507 | goto quotemark; | 11532 | goto quotemark; |
11508 | case CENDQUOTE: | 11533 | case CENDQUOTE: |
11509 | IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;) | 11534 | IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;) |
11510 | if (eofmark != NULL && varnest == 0) { | 11535 | if (eofmark != NULL && varnest == 0) { |
11511 | USTPUTC(c, out); | 11536 | USTPUTC(c, out); |
11512 | } else { | 11537 | } else { |
@@ -11565,7 +11590,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11565 | break; | 11590 | break; |
11566 | default: | 11591 | default: |
11567 | if (varnest == 0) { | 11592 | if (varnest == 0) { |
11568 | #if ENABLE_ASH_BASH_COMPAT | 11593 | #if BASH_REDIR_OUTPUT |
11569 | if (c == '&') { | 11594 | if (c == '&') { |
11570 | //Can't call pgetc_eatbnl() here, this requires three-deep pungetc() | 11595 | //Can't call pgetc_eatbnl() here, this requires three-deep pungetc() |
11571 | if (pgetc() == '>') | 11596 | if (pgetc() == '>') |
@@ -11597,7 +11622,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11597 | len = out - (char *)stackblock(); | 11622 | len = out - (char *)stackblock(); |
11598 | out = stackblock(); | 11623 | out = stackblock(); |
11599 | if (eofmark == NULL) { | 11624 | if (eofmark == NULL) { |
11600 | if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>')) | 11625 | if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>')) |
11601 | && quotef == 0 | 11626 | && quotef == 0 |
11602 | ) { | 11627 | ) { |
11603 | if (isdigit_str9(out)) { | 11628 | if (isdigit_str9(out)) { |
@@ -11685,7 +11710,7 @@ parseredir: { | |||
11685 | pungetc(); | 11710 | pungetc(); |
11686 | } | 11711 | } |
11687 | } | 11712 | } |
11688 | #if ENABLE_ASH_BASH_COMPAT | 11713 | #if BASH_REDIR_OUTPUT |
11689 | else if (c == 0x100 + '>') { /* this flags &> redirection */ | 11714 | else if (c == 0x100 + '>') { /* this flags &> redirection */ |
11690 | np->nfile.fd = 1; | 11715 | np->nfile.fd = 1; |
11691 | pgetc(); /* this is '>', no need to check */ | 11716 | pgetc(); /* this is '>', no need to check */ |
@@ -11751,7 +11776,7 @@ parsesub: { | |||
11751 | if (c > 255 /* PEOA or PEOF */ | 11776 | if (c > 255 /* PEOA or PEOF */ |
11752 | || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) | 11777 | || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) |
11753 | ) { | 11778 | ) { |
11754 | #if ENABLE_ASH_BASH_COMPAT | 11779 | #if BASH_DOLLAR_SQUOTE |
11755 | if (syntax != DQSYNTAX && c == '\'') | 11780 | if (syntax != DQSYNTAX && c == '\'') |
11756 | bash_dollar_squote = 1; | 11781 | bash_dollar_squote = 1; |
11757 | else | 11782 | else |
@@ -11827,7 +11852,7 @@ parsesub: { | |||
11827 | switch (c) { | 11852 | switch (c) { |
11828 | case ':': | 11853 | case ':': |
11829 | c = pgetc_eatbnl(); | 11854 | c = pgetc_eatbnl(); |
11830 | #if ENABLE_ASH_BASH_COMPAT | 11855 | #if BASH_SUBSTR |
11831 | /* This check is only needed to not misinterpret | 11856 | /* This check is only needed to not misinterpret |
11832 | * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD} | 11857 | * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD} |
11833 | * constructs. | 11858 | * constructs. |
@@ -11857,7 +11882,7 @@ parsesub: { | |||
11857 | subtype++; | 11882 | subtype++; |
11858 | break; | 11883 | break; |
11859 | } | 11884 | } |
11860 | #if ENABLE_ASH_BASH_COMPAT | 11885 | #if BASH_PATTERN_SUBST |
11861 | case '/': | 11886 | case '/': |
11862 | /* ${v/[/]pattern/repl} */ | 11887 | /* ${v/[/]pattern/repl} */ |
11863 | //TODO: encode pattern and repl separately. | 11888 | //TODO: encode pattern and repl separately. |
@@ -12112,7 +12137,7 @@ xxreadtoken(void) | |||
12112 | p += xxreadtoken_doubles + 1; | 12137 | p += xxreadtoken_doubles + 1; |
12113 | } else { | 12138 | } else { |
12114 | pungetc(); | 12139 | pungetc(); |
12115 | #if ENABLE_ASH_BASH_COMPAT | 12140 | #if BASH_REDIR_OUTPUT |
12116 | if (c == '&' && cc == '>') /* &> */ | 12141 | if (c == '&' && cc == '>') /* &> */ |
12117 | break; /* return readtoken1(...) */ | 12142 | break; /* return readtoken1(...) */ |
12118 | #endif | 12143 | #endif |
@@ -13274,9 +13299,11 @@ init(void) | |||
13274 | setvareq((char*)defoptindvar, VTEXTFIXED); | 13299 | setvareq((char*)defoptindvar, VTEXTFIXED); |
13275 | 13300 | ||
13276 | setvar0("PPID", utoa(getppid())); | 13301 | setvar0("PPID", utoa(getppid())); |
13277 | #if ENABLE_ASH_BASH_COMPAT | 13302 | #if BASH_SHLVL_VAR |
13278 | p = lookupvar("SHLVL"); | 13303 | p = lookupvar("SHLVL"); |
13279 | setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); | 13304 | setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); |
13305 | #endif | ||
13306 | #if BASH_HOSTNAME_VAR | ||
13280 | if (!lookupvar("HOSTNAME")) { | 13307 | if (!lookupvar("HOSTNAME")) { |
13281 | struct utsname uts; | 13308 | struct utsname uts; |
13282 | uname(&uts); | 13309 | uname(&uts); |