
Путь: Toys/POSIX, команды версии: Ver.4 Ver.9 Комментарии в файле test.c : Команд: 2 test
test_glue _КЛЕЙ логический по умолчанию г зависит от ТЕСТ || Ш _GLUE bool default y depends on TEST || SH Исходный текст в файле test.c #include "toys.h"
// Consume 3, 2, or 1 argument test, returning result and *count used.
static int do_test(char **args, int *count)
{
char c, *s;
int i;
if (*count>=3) {
*count = 3;
char *s = args[1], *ss = "eqnegtgeltle";
// TODO shell integration case insensitivity
if (!strcmp(s, "=") || !strcmp(s, "==")) return !strcmp(args[0], args[2]);
if (!strcmp(s, "!=")) return strcmp(args[0], args[2]);
if (!strcmp(s, "=~")) {
regex_t reg;
// TODO: regex needs integrated quoting support with the shell.
// Ala [[ abc =~ "1"* ]] matches but [[ abc =~ 1"*" ]] does not
xregcomp(®, args[2], REG_NOSUB); // REG_EXTENDED? REG_ICASE?
i = regexec(®, args[0], 0, 0, 0);
regfree(®);
return !i;
}
if ((*s=='<' || *s=='>') && !s[1]) {
i = strcmp(args[0], args[2]);
return (*s=='<') ? i<0 : i>0;
}
if (*s=='-' && strlen(s)==3 && (s = strstr(ss, s+1)) && !((i = s-ss)&1)) {
long long a = atolx(args[0]), b = atolx(args[2]);
if (!i) return a == b;
if (i==2) return a != b;
if (i==4) return a > b;
if (i==6) return a >= b;
if (i==8) return a < b;
if (i==10) return a<= b;
}
}
s = *args;
if (*count>=2 && *s == '-' && s[1] && !s[2]) {
*count = 2;
c = s[1];
if (c=='a') c = 'e';
if (-1 != (i = stridx("hLbcdefgkpSusxwr", c))) {
struct stat st;
if (i>=13) return !access(args[1], 1<<(i-13));
// stat or lstat, check s
if (-1 == ((i<2) ? lstat : stat)(args[1], &st)) return 0;
if (c == 's') return !!st.st_size; // otherwise 1<<32 == 0
// handle file type checking and SUID/SGID
if ((i = ((char []){80,80,48,16,32,0,64,2,1,8,96,4}[i])<<9)>=4096)
return (st.st_mode&S_IFMT) == i;
else return (st.st_mode & i) == i;
} else if (c == 'z') return !*args[1];
else if (c == 'n') return *args[1];
else if (c == 't') return isatty(atolx(args[1]));
}
return *count = 0;
}
#define NOT 1 // Most recent test had an odd number of preceding !
#define AND 2 // test before -a failed since -o or ( so force false
#define OR 4 // test before -o succeeded since ( so force true
void test_main(void)
{
char *s = (void *)1;
int pos, paren, pstack, result = 0;
toys.exitval = 2;
if (CFG_TOYBOX && *toys.which->name=='[') {
if (toys.optc) for (s = toys.optargs[--toys.optc]; *s==']'; s++);
if (*s) error_exit("Missing ']'");
}
// loop through command line arguments
if (toys.optc) for (pos = paren = pstack = 0; ; pos++) {
int len = toys.optc-pos;
if (!len) perror_exit("need arg @%d", pos);
// Evaluate next test
result = do_test(toys.optargs+pos, &len);
pos += len;
// Single argument could be ! ( or nonempty
if (!len) {
if (toys.optargs[pos+1]) {
if (!strcmp("!", toys.optargs[pos])) {
pstack ^= NOT;
continue;
}
if (!strcmp("(", toys.optargs[pos])) {
if (++paren>9) perror_exit("bad (");
pstack <<= 3;
continue;
}
}
result = *toys.optargs[pos++];
}
s = toys.optargs[pos];
for (;;) {
// Handle pending ! -a -o (the else means -o beats -a)
if (pstack&NOT) result = !result;
pstack &= ~NOT;
if (pstack&OR) result = 1;
else if (pstack&AND) result = 0;
// Do it again for every )
if (!paren || pos==toys.optc || strcmp(")", s)) break;
paren--;
pstack >>= 3;
s = toys.optargs[++pos];
}
// Out of arguments?
if (pos==toys.optc) {
if (paren) perror_exit("need )");
break;
}
// are we followed by -a or -o?
if (!strcmp("-a", s)) {
if (!result) pstack |= AND;
} else if (!strcmp("-o", s)) {
// -o flushes -a even if previous test was false
pstack &=~AND;
if (result) pstack |= OR;
} else error_exit("too many arguments");
}
// Invert C logic to get shell logic
toys.exitval = !result;
} |
![]() |