//config: bool "test (3.6 kb)"
//config: default y
//config: help
-//config: test is used to check file types and compare values,
-//config: returning an appropriate exit code. The bash shell
-//config: has test built in, ash can build it in optionally.
+//config: test is used to check file types and compare values,
+//config: returning an appropriate exit code. The bash shell
+//config: has test built in, ash can build it in optionally.
//config:
//config:config TEST1
//config: bool "test as ["
//config: default y
//config: help
-//config: Provide test command in the "[ EXPR ]" form
+//config: Provide test command in the "[ EXPR ]" form
//config:
//config:config TEST2
//config: bool "test as [["
//config: default y
//config: help
-//config: Provide test command in the "[[ EXPR ]]" form
+//config: Provide test command in the "[[ EXPR ]]" form
//config:
//config:config FEATURE_TEST_64
//config: bool "Extend test to 64 bit"
//config: default y
//config: depends on TEST || TEST1 || TEST2 || ASH_TEST || HUSH_TEST
//config: help
-//config: Enable 64-bit support in test.
+//config: Enable 64-bit support in test.
//applet:IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
//usage: "1\n"
#include "libbb.h"
-#include <setjmp.h>
/* This is a NOFORK applet. Be very careful! */
{ /* "-L" */ FILSYM , UNOP },
{ /* "-S" */ FILSOCK , UNOP },
{ /* "=" */ STREQ , BINOP },
+ /* "==" is bashism, http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
+ * lists only "=" as comparison operator.
+ */
{ /* "==" */ STREQ , BINOP },
{ /* "!=" */ STRNE , BINOP },
{ /* "<" */ STRLT , BINOP },
"-L" "\0"
"-S" "\0"
"=" "\0"
+ /* "==" is bashism */
"==" "\0"
"!=" "\0"
"<" "\0"
res = (argv[0][0] == '\0');
goto ret_special;
}
- if (argv[2] && !argv[3]) {
- check_operator(argv[1]);
- if (last_operator->op_type == BINOP) {
- /* "test [!] arg1 <binary_op> arg2" */
- args = argv;
- res = (binop() == 0);
+ if (argv[2]) {
+ if (!argv[3]) {
+ /*
+ * http://pubs.opengroup.org/onlinepubs/009695399/utilities/test.html
+ * """ 3 arguments:
+ * If $2 is a binary primary, perform the binary test of $1 and $3.
+ * """
+ */
+ check_operator(argv[1]);
+ if (last_operator->op_type == BINOP) {
+ /* "test [!] arg1 <binary_op> arg2" */
+ args = argv;
+ res = (binop() == 0);
ret_special:
- /* If there was leading "!" op... */
- res ^= negate;
- goto ret;
+ /* If there was leading "!" op... */
+ res ^= negate;
+ goto ret;
+ }
+ /* """If $1 is '(' and $3 is ')', perform the unary test of $2."""
+ * Looks like this works without additional coding.
+ */
+ goto check_negate;
+ }
+ /* argv[3] exists (at least 4 args), is it exactly 4 args? */
+ if (!argv[4]) {
+ /*
+ * """ 4 arguments:
+ * If $1 is '!', negate the three-argument test of $2, $3, and $4.
+ * If $1 is '(' and $4 is ')', perform the two-argument test of $2 and $3.
+ * """
+ * Example why code below is necessary: test '(' ! -e ')'
+ */
+ if (LONE_CHAR(argv[0], '(')
+ && LONE_CHAR(argv[3], ')')
+ ) {
+ /* "test [!] ( x y )" */
+ argv[3] = NULL;
+ argv++;
+ }
}
}
+ check_negate:
if (LONE_CHAR(argv[0], '!')) {
argv++;
negate ^= 1;