diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-14 19:42:12 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-14 19:42:12 +0200 |
commit | 82a6fb3ea6b49bcf1ef21ab589179ee2d6ffdc09 (patch) | |
tree | eb8ffd6fcf3a111f5392ecb47a6ad45401ae6d82 | |
parent | 2441060bebec2d65c9d106335223f37ec6e8ea5b (diff) | |
download | busybox-w32-82a6fb3ea6b49bcf1ef21ab589179ee2d6ffdc09.tar.gz busybox-w32-82a6fb3ea6b49bcf1ef21ab589179ee2d6ffdc09.tar.bz2 busybox-w32-82a6fb3ea6b49bcf1ef21ab589179ee2d6ffdc09.zip |
ash: fix . builtin
Also, move [[ ]] comment to test.c and expand it
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | coreutils/test.c | 46 | ||||
-rw-r--r-- | shell/ash.c | 42 | ||||
-rw-r--r-- | shell/ash_test/ash-misc/source1.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-misc/source1.tests | 5 | ||||
-rwxr-xr-x | shell/ash_test/run-all | 2 | ||||
-rw-r--r-- | shell/hush.c | 15 |
6 files changed, 66 insertions, 46 deletions
diff --git a/coreutils/test.c b/coreutils/test.c index cfaf4ca5d..73048d311 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -19,7 +19,6 @@ | |||
19 | * Original copyright notice states: | 19 | * Original copyright notice states: |
20 | * "This program is in the Public Domain." | 20 | * "This program is in the Public Domain." |
21 | */ | 21 | */ |
22 | |||
23 | #include "libbb.h" | 22 | #include "libbb.h" |
24 | #include <setjmp.h> | 23 | #include <setjmp.h> |
25 | 24 | ||
@@ -29,7 +28,6 @@ | |||
29 | * This is true regardless of PREFER_APPLETS and STANDALONE_SHELL | 28 | * This is true regardless of PREFER_APPLETS and STANDALONE_SHELL |
30 | * state. */ | 29 | * state. */ |
31 | 30 | ||
32 | |||
33 | /* test(1) accepts the following grammar: | 31 | /* test(1) accepts the following grammar: |
34 | oexpr ::= aexpr | aexpr "-o" oexpr ; | 32 | oexpr ::= aexpr | aexpr "-o" oexpr ; |
35 | aexpr ::= nexpr | nexpr "-a" aexpr ; | 33 | aexpr ::= nexpr | nexpr "-a" aexpr ; |
@@ -47,6 +45,50 @@ | |||
47 | operand ::= <any legal UNIX file name> | 45 | operand ::= <any legal UNIX file name> |
48 | */ | 46 | */ |
49 | 47 | ||
48 | /* TODO: handle [[ expr ]] bashism bash-compatibly. | ||
49 | * [[ ]] is meant to be a "better [ ]", with less weird syntax | ||
50 | * and without the risk of variables and quoted strings misinterpreted | ||
51 | * as operators. | ||
52 | * This will require support from shells - we need to know quote status | ||
53 | * of each parameter (see below). | ||
54 | * | ||
55 | * Word splitting and pathname expansion should NOT be performed: | ||
56 | * # a="a b"; [[ $a = "a b" ]] && echo YES | ||
57 | * YES | ||
58 | * # [[ /bin/m* ]] && echo YES | ||
59 | * YES | ||
60 | * | ||
61 | * =~ should do regexp match | ||
62 | * = and == should do pattern match against right side: | ||
63 | * # [[ *a* == bab ]] && echo YES | ||
64 | * # [[ bab == *a* ]] && echo YES | ||
65 | * YES | ||
66 | * != does the negated == (i.e., also with pattern matching). | ||
67 | * Pattern matching is quotation-sensitive: | ||
68 | * # [[ bab == "b"a* ]] && echo YES | ||
69 | * YES | ||
70 | * # [[ bab == b"a*" ]] && echo YES | ||
71 | * | ||
72 | * Conditional operators such as -f must be unquoted literals to be recognized: | ||
73 | * # [[ -e /bin ]] && echo YES | ||
74 | * YES | ||
75 | * # [[ '-e' /bin ]] && echo YES | ||
76 | * bash: conditional binary operator expected... | ||
77 | * # A='-e'; [[ $A /bin ]] && echo YES | ||
78 | * bash: conditional binary operator expected... | ||
79 | * | ||
80 | * || and && should work as -o and -a work in [ ] | ||
81 | * -a and -o aren't recognized (&& and || are to be used instead) | ||
82 | * ( and ) do not need to be quoted unlike in [ ]: | ||
83 | * # [[ ( abc ) && '' ]] && echo YES | ||
84 | * # [[ ( abc ) || '' ]] && echo YES | ||
85 | * YES | ||
86 | * # [[ ( abc ) -o '' ]] && echo YES | ||
87 | * bash: syntax error in conditional expression... | ||
88 | * | ||
89 | * Apart from the above, [[ expr ]] should work as [ expr ] | ||
90 | */ | ||
91 | |||
50 | #define TEST_DEBUG 0 | 92 | #define TEST_DEBUG 0 |
51 | 93 | ||
52 | enum token { | 94 | enum token { |
diff --git a/shell/ash.c b/shell/ash.c index 3452351b0..9b40ca3c6 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -2224,17 +2224,17 @@ listvars(int on, int off, char ***end) | |||
2224 | /* ============ Path search helper | 2224 | /* ============ Path search helper |
2225 | * | 2225 | * |
2226 | * The variable path (passed by reference) should be set to the start | 2226 | * The variable path (passed by reference) should be set to the start |
2227 | * of the path before the first call; padvance will update | 2227 | * of the path before the first call; path_advance will update |
2228 | * this value as it proceeds. Successive calls to padvance will return | 2228 | * this value as it proceeds. Successive calls to path_advance will return |
2229 | * the possible path expansions in sequence. If an option (indicated by | 2229 | * the possible path expansions in sequence. If an option (indicated by |
2230 | * a percent sign) appears in the path entry then the global variable | 2230 | * a percent sign) appears in the path entry then the global variable |
2231 | * pathopt will be set to point to it; otherwise pathopt will be set to | 2231 | * pathopt will be set to point to it; otherwise pathopt will be set to |
2232 | * NULL. | 2232 | * NULL. |
2233 | */ | 2233 | */ |
2234 | static const char *pathopt; /* set by padvance */ | 2234 | static const char *pathopt; /* set by path_advance */ |
2235 | 2235 | ||
2236 | static char * | 2236 | static char * |
2237 | padvance(const char **path, const char *name) | 2237 | path_advance(const char **path, const char *name) |
2238 | { | 2238 | { |
2239 | const char *p; | 2239 | const char *p; |
2240 | char *q; | 2240 | char *q; |
@@ -2538,7 +2538,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
2538 | } | 2538 | } |
2539 | do { | 2539 | do { |
2540 | c = *path; | 2540 | c = *path; |
2541 | p = padvance(&path, dest); | 2541 | p = path_advance(&path, dest); |
2542 | if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { | 2542 | if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { |
2543 | if (c && c != ':') | 2543 | if (c && c != ':') |
2544 | flags |= CD_PRINT; | 2544 | flags |= CD_PRINT; |
@@ -7159,7 +7159,7 @@ shellexec(char **argv, const char *path, int idx) | |||
7159 | e = errno; | 7159 | e = errno; |
7160 | } else { | 7160 | } else { |
7161 | e = ENOENT; | 7161 | e = ENOENT; |
7162 | while ((cmdname = padvance(&path, argv[0])) != NULL) { | 7162 | while ((cmdname = path_advance(&path, argv[0])) != NULL) { |
7163 | if (--idx < 0 && pathopt == NULL) { | 7163 | if (--idx < 0 && pathopt == NULL) { |
7164 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); | 7164 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); |
7165 | if (errno != ENOENT && errno != ENOTDIR) | 7165 | if (errno != ENOENT && errno != ENOTDIR) |
@@ -7198,7 +7198,7 @@ printentry(struct tblentry *cmdp) | |||
7198 | idx = cmdp->param.index; | 7198 | idx = cmdp->param.index; |
7199 | path = pathval(); | 7199 | path = pathval(); |
7200 | do { | 7200 | do { |
7201 | name = padvance(&path, cmdp->cmdname); | 7201 | name = path_advance(&path, cmdp->cmdname); |
7202 | stunalloc(name); | 7202 | stunalloc(name); |
7203 | } while (--idx >= 0); | 7203 | } while (--idx >= 0); |
7204 | out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr)); | 7204 | out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr)); |
@@ -7570,7 +7570,7 @@ describe_command(char *command, int describe_command_verbose) | |||
7570 | p = command; | 7570 | p = command; |
7571 | } else { | 7571 | } else { |
7572 | do { | 7572 | do { |
7573 | p = padvance(&path, command); | 7573 | p = path_advance(&path, command); |
7574 | stunalloc(p); | 7574 | stunalloc(p); |
7575 | } while (--j >= 0); | 7575 | } while (--j >= 0); |
7576 | } | 7576 | } |
@@ -8727,23 +8727,6 @@ static int ulimitcmd(int, char **) FAST_FUNC; | |||
8727 | #define BUILTIN_REG_ASSG "6" | 8727 | #define BUILTIN_REG_ASSG "6" |
8728 | #define BUILTIN_SPEC_REG_ASSG "7" | 8728 | #define BUILTIN_SPEC_REG_ASSG "7" |
8729 | 8729 | ||
8730 | /* We do not handle [[ expr ]] bashism bash-compatibly, | ||
8731 | * we make it a synonym of [ expr ]. | ||
8732 | * Basically, word splitting and pathname expansion should NOT be performed | ||
8733 | * Examples: | ||
8734 | * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0" | ||
8735 | * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0" | ||
8736 | * Additional operators: | ||
8737 | * || and && should work as -o and -a | ||
8738 | * =~ regexp match | ||
8739 | * == should do _pattern match_ against right side. bash does this: | ||
8740 | * # [[ *a* == bab ]] && echo YES | ||
8741 | * # [[ bab == *a* ]] && echo YES | ||
8742 | * YES | ||
8743 | * != does the negated == (i.e., also with pattern matching) | ||
8744 | * Apart from the above, [[ expr ]] should work as [ expr ] | ||
8745 | */ | ||
8746 | |||
8747 | /* Stubs for calling non-FAST_FUNC's */ | 8730 | /* Stubs for calling non-FAST_FUNC's */ |
8748 | #if ENABLE_ASH_BUILTIN_ECHO | 8731 | #if ENABLE_ASH_BUILTIN_ECHO |
8749 | static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); } | 8732 | static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); } |
@@ -9718,7 +9701,7 @@ chkmail(void) | |||
9718 | setstackmark(&smark); | 9701 | setstackmark(&smark); |
9719 | mpath = mpathset() ? mpathval() : mailval(); | 9702 | mpath = mpathset() ? mpathval() : mailval(); |
9720 | for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) { | 9703 | for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) { |
9721 | p = padvance(&mpath, nullstr); | 9704 | p = path_advance(&mpath, nullstr); |
9722 | if (p == NULL) | 9705 | if (p == NULL) |
9723 | break; | 9706 | break; |
9724 | if (*p == '\0') | 9707 | if (*p == '\0') |
@@ -11912,7 +11895,7 @@ find_dot_file(char *name) | |||
11912 | goto try_cur_dir; | 11895 | goto try_cur_dir; |
11913 | } | 11896 | } |
11914 | 11897 | ||
11915 | while ((fullname = padvance(&path, name)) != NULL) { | 11898 | while ((fullname = path_advance(&path, name)) != NULL) { |
11916 | try_cur_dir: | 11899 | try_cur_dir: |
11917 | if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { | 11900 | if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { |
11918 | /* | 11901 | /* |
@@ -11921,7 +11904,8 @@ find_dot_file(char *name) | |||
11921 | */ | 11904 | */ |
11922 | return fullname; | 11905 | return fullname; |
11923 | } | 11906 | } |
11924 | stunalloc(fullname); | 11907 | if (fullname != name) |
11908 | stunalloc(fullname); | ||
11925 | } | 11909 | } |
11926 | 11910 | ||
11927 | /* not found in the PATH */ | 11911 | /* not found in the PATH */ |
@@ -12095,7 +12079,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
12095 | e = ENOENT; | 12079 | e = ENOENT; |
12096 | idx = -1; | 12080 | idx = -1; |
12097 | loop: | 12081 | loop: |
12098 | while ((fullname = padvance(&path, name)) != NULL) { | 12082 | while ((fullname = path_advance(&path, name)) != NULL) { |
12099 | stunalloc(fullname); | 12083 | stunalloc(fullname); |
12100 | /* NB: code below will still use fullname | 12084 | /* NB: code below will still use fullname |
12101 | * despite it being "unallocated" */ | 12085 | * despite it being "unallocated" */ |
diff --git a/shell/ash_test/ash-misc/source1.right b/shell/ash_test/ash-misc/source1.right new file mode 100644 index 000000000..0ab7c548c --- /dev/null +++ b/shell/ash_test/ash-misc/source1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | Sourced ok | ||
2 | Done | ||
diff --git a/shell/ash_test/ash-misc/source1.tests b/shell/ash_test/ash-misc/source1.tests new file mode 100755 index 000000000..e2e75b227 --- /dev/null +++ b/shell/ash_test/ash-misc/source1.tests | |||
@@ -0,0 +1,5 @@ | |||
1 | echo "echo Sourced ok" >../sourced.sh | ||
2 | PATH="..:$PATH" | ||
3 | . sourced.sh | ||
4 | rm ../sourced.sh | ||
5 | echo Done | ||
diff --git a/shell/ash_test/run-all b/shell/ash_test/run-all index 4d0f39a41..ad93e251d 100755 --- a/shell/ash_test/run-all +++ b/shell/ash_test/run-all | |||
@@ -19,7 +19,7 @@ export THIS_SH | |||
19 | do_test() | 19 | do_test() |
20 | { | 20 | { |
21 | test -d "$1" || return 0 | 21 | test -d "$1" || return 0 |
22 | echo do_test "$1" | 22 | # echo do_test "$1" |
23 | # $1 but with / replaced by # so that it can be used as filename part | 23 | # $1 but with / replaced by # so that it can be used as filename part |
24 | noslash=`echo "$1" | sed 's:/:#:g'` | 24 | noslash=`echo "$1" | sed 's:/:#:g'` |
25 | ( | 25 | ( |
diff --git a/shell/hush.c b/shell/hush.c index 245fb586d..fe05e4715 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -311,22 +311,9 @@ struct command { | |||
311 | #if ENABLE_HUSH_BASH_COMPAT | 311 | #if ENABLE_HUSH_BASH_COMPAT |
312 | # define CMD_SINGLEWORD_NOGLOB 2 | 312 | # define CMD_SINGLEWORD_NOGLOB 2 |
313 | #endif | 313 | #endif |
314 | // Basically, word splitting and pathname expansion should NOT be performed | ||
315 | // Examples: | ||
316 | // no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0" | ||
317 | // no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0" | ||
318 | // Additional operators: | ||
319 | // || and && should work as -o and -a | ||
320 | // =~ regexp match | ||
321 | // == should do _pattern match_ against right side. bash does this: | ||
322 | // # [[ *a* == bab ]] && echo YES | ||
323 | // # [[ bab == *a* ]] && echo YES | ||
324 | // YES | ||
325 | // != does the negated == (i.e., also with pattern matching) | ||
326 | // Apart from the above, [[ expr ]] should work as [ expr ] | ||
327 | 314 | ||
328 | /* used for "export noglob=* glob* a=`echo a b`" */ | 315 | /* used for "export noglob=* glob* a=`echo a b`" */ |
329 | /*#define CMD_SINGLEWORD_NOGLOB_COND 3 */ | 316 | //#define CMD_SINGLEWORD_NOGLOB_COND 3 |
330 | // It is hard to implement correctly, it adds significant amounts of tricky code, | 317 | // It is hard to implement correctly, it adds significant amounts of tricky code, |
331 | // and all this is only useful for really obscure export statements | 318 | // and all this is only useful for really obscure export statements |
332 | // almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND | 319 | // almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND |