ash: fix . builtin
Also, move [[ ]] comment to test.c and expand it Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
2441060beb
commit
82a6fb3ea6
@ -19,7 +19,6 @@
|
|||||||
* Original copyright notice states:
|
* Original copyright notice states:
|
||||||
* "This program is in the Public Domain."
|
* "This program is in the Public Domain."
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
@ -29,7 +28,6 @@
|
|||||||
* This is true regardless of PREFER_APPLETS and STANDALONE_SHELL
|
* This is true regardless of PREFER_APPLETS and STANDALONE_SHELL
|
||||||
* state. */
|
* state. */
|
||||||
|
|
||||||
|
|
||||||
/* test(1) accepts the following grammar:
|
/* test(1) accepts the following grammar:
|
||||||
oexpr ::= aexpr | aexpr "-o" oexpr ;
|
oexpr ::= aexpr | aexpr "-o" oexpr ;
|
||||||
aexpr ::= nexpr | nexpr "-a" aexpr ;
|
aexpr ::= nexpr | nexpr "-a" aexpr ;
|
||||||
@ -47,6 +45,50 @@
|
|||||||
operand ::= <any legal UNIX file name>
|
operand ::= <any legal UNIX file name>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* TODO: handle [[ expr ]] bashism bash-compatibly.
|
||||||
|
* [[ ]] is meant to be a "better [ ]", with less weird syntax
|
||||||
|
* and without the risk of variables and quoted strings misinterpreted
|
||||||
|
* as operators.
|
||||||
|
* This will require support from shells - we need to know quote status
|
||||||
|
* of each parameter (see below).
|
||||||
|
*
|
||||||
|
* Word splitting and pathname expansion should NOT be performed:
|
||||||
|
* # a="a b"; [[ $a = "a b" ]] && echo YES
|
||||||
|
* YES
|
||||||
|
* # [[ /bin/m* ]] && echo YES
|
||||||
|
* YES
|
||||||
|
*
|
||||||
|
* =~ should do regexp match
|
||||||
|
* = and == should do pattern match against right side:
|
||||||
|
* # [[ *a* == bab ]] && echo YES
|
||||||
|
* # [[ bab == *a* ]] && echo YES
|
||||||
|
* YES
|
||||||
|
* != does the negated == (i.e., also with pattern matching).
|
||||||
|
* Pattern matching is quotation-sensitive:
|
||||||
|
* # [[ bab == "b"a* ]] && echo YES
|
||||||
|
* YES
|
||||||
|
* # [[ bab == b"a*" ]] && echo YES
|
||||||
|
*
|
||||||
|
* Conditional operators such as -f must be unquoted literals to be recognized:
|
||||||
|
* # [[ -e /bin ]] && echo YES
|
||||||
|
* YES
|
||||||
|
* # [[ '-e' /bin ]] && echo YES
|
||||||
|
* bash: conditional binary operator expected...
|
||||||
|
* # A='-e'; [[ $A /bin ]] && echo YES
|
||||||
|
* bash: conditional binary operator expected...
|
||||||
|
*
|
||||||
|
* || and && should work as -o and -a work in [ ]
|
||||||
|
* -a and -o aren't recognized (&& and || are to be used instead)
|
||||||
|
* ( and ) do not need to be quoted unlike in [ ]:
|
||||||
|
* # [[ ( abc ) && '' ]] && echo YES
|
||||||
|
* # [[ ( abc ) || '' ]] && echo YES
|
||||||
|
* YES
|
||||||
|
* # [[ ( abc ) -o '' ]] && echo YES
|
||||||
|
* bash: syntax error in conditional expression...
|
||||||
|
*
|
||||||
|
* Apart from the above, [[ expr ]] should work as [ expr ]
|
||||||
|
*/
|
||||||
|
|
||||||
#define TEST_DEBUG 0
|
#define TEST_DEBUG 0
|
||||||
|
|
||||||
enum token {
|
enum token {
|
||||||
|
40
shell/ash.c
40
shell/ash.c
@ -2224,17 +2224,17 @@ listvars(int on, int off, char ***end)
|
|||||||
/* ============ Path search helper
|
/* ============ Path search helper
|
||||||
*
|
*
|
||||||
* The variable path (passed by reference) should be set to the start
|
* The variable path (passed by reference) should be set to the start
|
||||||
* of the path before the first call; padvance will update
|
* of the path before the first call; path_advance will update
|
||||||
* this value as it proceeds. Successive calls to padvance will return
|
* this value as it proceeds. Successive calls to path_advance will return
|
||||||
* the possible path expansions in sequence. If an option (indicated by
|
* the possible path expansions in sequence. If an option (indicated by
|
||||||
* a percent sign) appears in the path entry then the global variable
|
* a percent sign) appears in the path entry then the global variable
|
||||||
* pathopt will be set to point to it; otherwise pathopt will be set to
|
* pathopt will be set to point to it; otherwise pathopt will be set to
|
||||||
* NULL.
|
* NULL.
|
||||||
*/
|
*/
|
||||||
static const char *pathopt; /* set by padvance */
|
static const char *pathopt; /* set by path_advance */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
padvance(const char **path, const char *name)
|
path_advance(const char **path, const char *name)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
char *q;
|
char *q;
|
||||||
@ -2538,7 +2538,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
c = *path;
|
c = *path;
|
||||||
p = padvance(&path, dest);
|
p = path_advance(&path, dest);
|
||||||
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
||||||
if (c && c != ':')
|
if (c && c != ':')
|
||||||
flags |= CD_PRINT;
|
flags |= CD_PRINT;
|
||||||
@ -7159,7 +7159,7 @@ shellexec(char **argv, const char *path, int idx)
|
|||||||
e = errno;
|
e = errno;
|
||||||
} else {
|
} else {
|
||||||
e = ENOENT;
|
e = ENOENT;
|
||||||
while ((cmdname = padvance(&path, argv[0])) != NULL) {
|
while ((cmdname = path_advance(&path, argv[0])) != NULL) {
|
||||||
if (--idx < 0 && pathopt == NULL) {
|
if (--idx < 0 && pathopt == NULL) {
|
||||||
tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
|
tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
|
||||||
if (errno != ENOENT && errno != ENOTDIR)
|
if (errno != ENOENT && errno != ENOTDIR)
|
||||||
@ -7198,7 +7198,7 @@ printentry(struct tblentry *cmdp)
|
|||||||
idx = cmdp->param.index;
|
idx = cmdp->param.index;
|
||||||
path = pathval();
|
path = pathval();
|
||||||
do {
|
do {
|
||||||
name = padvance(&path, cmdp->cmdname);
|
name = path_advance(&path, cmdp->cmdname);
|
||||||
stunalloc(name);
|
stunalloc(name);
|
||||||
} while (--idx >= 0);
|
} while (--idx >= 0);
|
||||||
out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
|
out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
|
||||||
@ -7570,7 +7570,7 @@ describe_command(char *command, int describe_command_verbose)
|
|||||||
p = command;
|
p = command;
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
p = padvance(&path, command);
|
p = path_advance(&path, command);
|
||||||
stunalloc(p);
|
stunalloc(p);
|
||||||
} while (--j >= 0);
|
} while (--j >= 0);
|
||||||
}
|
}
|
||||||
@ -8727,23 +8727,6 @@ static int ulimitcmd(int, char **) FAST_FUNC;
|
|||||||
#define BUILTIN_REG_ASSG "6"
|
#define BUILTIN_REG_ASSG "6"
|
||||||
#define BUILTIN_SPEC_REG_ASSG "7"
|
#define BUILTIN_SPEC_REG_ASSG "7"
|
||||||
|
|
||||||
/* We do not handle [[ expr ]] bashism bash-compatibly,
|
|
||||||
* we make it a synonym of [ expr ].
|
|
||||||
* Basically, word splitting and pathname expansion should NOT be performed
|
|
||||||
* Examples:
|
|
||||||
* no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
|
|
||||||
* no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
|
|
||||||
* Additional operators:
|
|
||||||
* || and && should work as -o and -a
|
|
||||||
* =~ regexp match
|
|
||||||
* == should do _pattern match_ against right side. bash does this:
|
|
||||||
* # [[ *a* == bab ]] && echo YES
|
|
||||||
* # [[ bab == *a* ]] && echo YES
|
|
||||||
* YES
|
|
||||||
* != does the negated == (i.e., also with pattern matching)
|
|
||||||
* Apart from the above, [[ expr ]] should work as [ expr ]
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Stubs for calling non-FAST_FUNC's */
|
/* Stubs for calling non-FAST_FUNC's */
|
||||||
#if ENABLE_ASH_BUILTIN_ECHO
|
#if ENABLE_ASH_BUILTIN_ECHO
|
||||||
static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); }
|
static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); }
|
||||||
@ -9718,7 +9701,7 @@ chkmail(void)
|
|||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
mpath = mpathset() ? mpathval() : mailval();
|
mpath = mpathset() ? mpathval() : mailval();
|
||||||
for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
|
for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
|
||||||
p = padvance(&mpath, nullstr);
|
p = path_advance(&mpath, nullstr);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
break;
|
break;
|
||||||
if (*p == '\0')
|
if (*p == '\0')
|
||||||
@ -11912,7 +11895,7 @@ find_dot_file(char *name)
|
|||||||
goto try_cur_dir;
|
goto try_cur_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((fullname = padvance(&path, name)) != NULL) {
|
while ((fullname = path_advance(&path, name)) != NULL) {
|
||||||
try_cur_dir:
|
try_cur_dir:
|
||||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
|
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
|
||||||
/*
|
/*
|
||||||
@ -11921,6 +11904,7 @@ find_dot_file(char *name)
|
|||||||
*/
|
*/
|
||||||
return fullname;
|
return fullname;
|
||||||
}
|
}
|
||||||
|
if (fullname != name)
|
||||||
stunalloc(fullname);
|
stunalloc(fullname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12095,7 +12079,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
|
|||||||
e = ENOENT;
|
e = ENOENT;
|
||||||
idx = -1;
|
idx = -1;
|
||||||
loop:
|
loop:
|
||||||
while ((fullname = padvance(&path, name)) != NULL) {
|
while ((fullname = path_advance(&path, name)) != NULL) {
|
||||||
stunalloc(fullname);
|
stunalloc(fullname);
|
||||||
/* NB: code below will still use fullname
|
/* NB: code below will still use fullname
|
||||||
* despite it being "unallocated" */
|
* despite it being "unallocated" */
|
||||||
|
2
shell/ash_test/ash-misc/source1.right
Normal file
2
shell/ash_test/ash-misc/source1.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Sourced ok
|
||||||
|
Done
|
5
shell/ash_test/ash-misc/source1.tests
Executable file
5
shell/ash_test/ash-misc/source1.tests
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
echo "echo Sourced ok" >../sourced.sh
|
||||||
|
PATH="..:$PATH"
|
||||||
|
. sourced.sh
|
||||||
|
rm ../sourced.sh
|
||||||
|
echo Done
|
@ -19,7 +19,7 @@ export THIS_SH
|
|||||||
do_test()
|
do_test()
|
||||||
{
|
{
|
||||||
test -d "$1" || return 0
|
test -d "$1" || return 0
|
||||||
echo do_test "$1"
|
# echo do_test "$1"
|
||||||
# $1 but with / replaced by # so that it can be used as filename part
|
# $1 but with / replaced by # so that it can be used as filename part
|
||||||
noslash=`echo "$1" | sed 's:/:#:g'`
|
noslash=`echo "$1" | sed 's:/:#:g'`
|
||||||
(
|
(
|
||||||
|
15
shell/hush.c
15
shell/hush.c
@ -311,22 +311,9 @@ struct command {
|
|||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if ENABLE_HUSH_BASH_COMPAT
|
||||||
# define CMD_SINGLEWORD_NOGLOB 2
|
# define CMD_SINGLEWORD_NOGLOB 2
|
||||||
#endif
|
#endif
|
||||||
// Basically, word splitting and pathname expansion should NOT be performed
|
|
||||||
// Examples:
|
|
||||||
// no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
|
|
||||||
// no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
|
|
||||||
// Additional operators:
|
|
||||||
// || and && should work as -o and -a
|
|
||||||
// =~ regexp match
|
|
||||||
// == should do _pattern match_ against right side. bash does this:
|
|
||||||
// # [[ *a* == bab ]] && echo YES
|
|
||||||
// # [[ bab == *a* ]] && echo YES
|
|
||||||
// YES
|
|
||||||
// != does the negated == (i.e., also with pattern matching)
|
|
||||||
// Apart from the above, [[ expr ]] should work as [ expr ]
|
|
||||||
|
|
||||||
/* used for "export noglob=* glob* a=`echo a b`" */
|
/* used for "export noglob=* glob* a=`echo a b`" */
|
||||||
/*#define CMD_SINGLEWORD_NOGLOB_COND 3 */
|
//#define CMD_SINGLEWORD_NOGLOB_COND 3
|
||||||
// It is hard to implement correctly, it adds significant amounts of tricky code,
|
// It is hard to implement correctly, it adds significant amounts of tricky code,
|
||||||
// and all this is only useful for really obscure export statements
|
// and all this is only useful for really obscure export statements
|
||||||
// almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND
|
// almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND
|
||||||
|
Loading…
Reference in New Issue
Block a user