aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-06-14 19:42:12 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-06-14 19:42:12 +0200
commit82a6fb3ea6b49bcf1ef21ab589179ee2d6ffdc09 (patch)
treeeb8ffd6fcf3a111f5392ecb47a6ad45401ae6d82
parent2441060bebec2d65c9d106335223f37ec6e8ea5b (diff)
downloadbusybox-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.c46
-rw-r--r--shell/ash.c42
-rw-r--r--shell/ash_test/ash-misc/source1.right2
-rwxr-xr-xshell/ash_test/ash-misc/source1.tests5
-rwxr-xr-xshell/ash_test/run-all2
-rw-r--r--shell/hush.c15
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
52enum token { 94enum 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 */
2234static const char *pathopt; /* set by padvance */ 2234static const char *pathopt; /* set by path_advance */
2235 2235
2236static char * 2236static char *
2237padvance(const char **path, const char *name) 2237path_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
8749static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); } 8732static 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 @@
1Sourced ok
2Done
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 @@
1echo "echo Sourced ok" >../sourced.sh
2PATH="..:$PATH"
3. sourced.sh
4rm ../sourced.sh
5echo 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
19do_test() 19do_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