Clean up test.c
* A number of logic and style fixes * No longer changes toys.optargs and toys.optc * Now supports ( ) ! -a -o * Supports POSIX special cases for low argument count
This commit is contained in:
parent
8993496e49
commit
ef3044114a
@ -39,76 +39,179 @@ config TEST
|
||||
|
||||
#include "toys.h"
|
||||
|
||||
int get_stat(struct stat *st, int *link, char* s)
|
||||
{
|
||||
if (lstat(s, st) == -1) return 0;
|
||||
*link = S_ISLNK(st->st_mode);
|
||||
if (*link && (stat(s, st) == -1)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// basic expression without !, -o, -a, (
|
||||
int test_basic(int optb, int opte)
|
||||
{
|
||||
int id, val;
|
||||
char *s, *err_fmt = "Bad flag '%s'", *err_int = "Bad integer '%s'";
|
||||
|
||||
if (optb == opte) val = 0;
|
||||
else if (optb + 1 == opte) val = !!*toys.optargs[optb];
|
||||
else if (optb + 2 == opte && toys.optargs[optb][0] == '-') {
|
||||
char c = toys.optargs[optb][1];
|
||||
struct stat st;
|
||||
int link;
|
||||
|
||||
if (!c || toys.optargs[optb][2]) error_exit(err_fmt, toys.optargs[optb]);
|
||||
s = toys.optargs[optb + 1];
|
||||
if (c == 'b') val = get_stat(&st, &link, s) && S_ISBLK(st.st_mode);
|
||||
else if (c == 'c') val = get_stat(&st, &link, s) && S_ISCHR(st.st_mode);
|
||||
else if (c == 'd') val = get_stat(&st, &link, s) && S_ISDIR(st.st_mode);
|
||||
else if (c == 'e') val = get_stat(&st, &link, s);
|
||||
else if (c == 'f') val = get_stat(&st, &link, s) && S_ISREG(st.st_mode);
|
||||
else if (c == 'g') val = get_stat(&st, &link, s) && (st.st_mode & S_ISGID);
|
||||
else if (c == 'h' || c == 'L') val = get_stat(&st, &link, s) && link;
|
||||
else if (c == 'p') val = get_stat(&st, &link, s) && S_ISFIFO(st.st_mode);
|
||||
else if (c == 'S') val = get_stat(&st, &link, s) && S_ISSOCK(st.st_mode);
|
||||
else if (c == 's') val = get_stat(&st, &link, s) && st.st_size != 0;
|
||||
else if (c == 'u') val = get_stat(&st, &link, s) && (st.st_mode & S_ISUID);
|
||||
else if (c == 'r') val = access(s, R_OK) != -1;
|
||||
else if (c == 'w') val = access(s, W_OK) != -1;
|
||||
else if (c == 'x') val = access(s, X_OK) != -1;
|
||||
else if (c == 'z') val = !*s;
|
||||
else if (c == 'n') val = !!*s;
|
||||
else if (c == 't') {
|
||||
struct termios termios;
|
||||
val = tcgetattr(atoi(s), &termios) != -1;
|
||||
}
|
||||
else error_exit(err_fmt, toys.optargs[optb]);
|
||||
}
|
||||
else if (optb + 3 == opte) {
|
||||
if (*toys.optargs[optb + 1] == '-') {
|
||||
char *end_a, *end_b;
|
||||
long a, b;
|
||||
int errno_a, errno_b;
|
||||
|
||||
errno = 0;
|
||||
a = strtol(toys.optargs[optb], &end_a, 10);
|
||||
errno_a = errno;
|
||||
b = strtol(toys.optargs[optb + 2], &end_b, 10);
|
||||
errno_b = errno;
|
||||
s = toys.optargs[optb + 1] + 1;
|
||||
if (!strcmp("eq", s)) val = a == b;
|
||||
else if (!strcmp("ne", s)) val = a != b;
|
||||
else if (!strcmp("gt", s)) val = a > b;
|
||||
else if (!strcmp("ge", s)) val = a >= b;
|
||||
else if (!strcmp("lt", s)) val = a < b;
|
||||
else if (!strcmp("le", s)) val = a <= b;
|
||||
else error_exit(err_fmt, toys.optargs[optb + 1]);
|
||||
if (!*toys.optargs[optb] || *end_a || errno_a)
|
||||
error_exit(err_int, toys.optargs[optb]);
|
||||
if (!*toys.optargs[optb + 2] || *end_b || errno_b)
|
||||
error_exit(err_int, toys.optargs[optb + 2]);
|
||||
}
|
||||
else {
|
||||
int result = strcmp(toys.optargs[optb], toys.optargs[optb + 2]);
|
||||
|
||||
s = toys.optargs[optb + 1];
|
||||
if (!strcmp("=", s)) val = !result;
|
||||
else if (!strcmp("!=", s)) val = !!result;
|
||||
else error_exit(err_fmt, toys.optargs[optb + 1]);
|
||||
}
|
||||
}
|
||||
else error_exit("Syntax error");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int test_sub(int optb, int opte)
|
||||
{
|
||||
int not, and = 1, or = 0, i, expr;
|
||||
char *err_syntax = "Syntax error";
|
||||
|
||||
for (;;) {
|
||||
not = 0;
|
||||
while (optb < opte && !strcmp("!", toys.optargs[optb])) {
|
||||
not = !not;
|
||||
optb++;
|
||||
}
|
||||
if (optb < opte && !strcmp("(", toys.optargs[optb])) {
|
||||
int par = 1;
|
||||
|
||||
for (i = optb + 1; par && i < opte; i++) {
|
||||
if (!strcmp(")", toys.optargs[i])) par--;
|
||||
else if (!strcmp("(", toys.optargs[i])) par++;
|
||||
}
|
||||
if (par) error_exit("Missing ')'");
|
||||
expr = not ^ test_sub(optb + 1, i - 1);
|
||||
optb = i;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (optb + i == opte || !strcmp("-a", toys.optargs[optb + i])
|
||||
|| !strcmp("-o", toys.optargs[optb + i])) break;
|
||||
}
|
||||
if (i == 4) error_exit(err_syntax);
|
||||
expr = not ^ test_basic(optb, optb + i);
|
||||
optb += i;
|
||||
}
|
||||
|
||||
if (optb == opte) {
|
||||
return or || (and && expr);
|
||||
}
|
||||
else if (!strcmp("-o", toys.optargs[optb])) {
|
||||
or = or || (and && expr);
|
||||
and = 1;
|
||||
optb++;
|
||||
}
|
||||
else if (!strcmp("-a", toys.optargs[optb])) {
|
||||
and = and && expr;
|
||||
optb++;
|
||||
}
|
||||
else error_exit(err_syntax);
|
||||
}
|
||||
}
|
||||
|
||||
int test_few_args(int optb, int opte)
|
||||
{
|
||||
if (optb == opte) return 0;
|
||||
else if (optb + 1 == opte) return !!*toys.optargs[optb];
|
||||
else if (optb + 2 == opte) {
|
||||
if (!strcmp("!", toys.optargs[optb])) return !*toys.optargs[optb + 1];
|
||||
else if (toys.optargs[optb][0] == '-' &&
|
||||
stridx("bcdefghLpSsurwxznt", toys.optargs[optb][1]) != -1 &&
|
||||
!toys.optargs[optb][2]) return test_basic(optb, opte);
|
||||
}
|
||||
else if (optb + 3 == opte) {
|
||||
if (!strcmp("-eq", toys.optargs[optb + 1]) ||
|
||||
!strcmp("-ne", toys.optargs[optb + 1]) ||
|
||||
!strcmp("-gt", toys.optargs[optb + 1]) ||
|
||||
!strcmp("-ge", toys.optargs[optb + 1]) ||
|
||||
!strcmp("-lt", toys.optargs[optb + 1]) ||
|
||||
!strcmp("-le", toys.optargs[optb + 1]) ||
|
||||
!strcmp("=", toys.optargs[optb + 1]) ||
|
||||
!strcmp("!=", toys.optargs[optb + 1])) return test_basic(optb, opte);
|
||||
else if (!strcmp("!", toys.optargs[optb]))
|
||||
return !test_few_args(optb + 1, opte);
|
||||
else if (!strcmp("(", toys.optargs[optb]) &&
|
||||
!strcmp(")", toys.optargs[optb + 2]))
|
||||
return !!*toys.optargs[optb + 1];
|
||||
}
|
||||
else {
|
||||
if (!strcmp("!", toys.optargs[optb])) return !test_few_args(optb + 1, opte);
|
||||
else if (!strcmp("(", toys.optargs[optb]) &&
|
||||
!strcmp(")", toys.optargs[optb + 3]))
|
||||
return test_few_args(optb + 1, opte - 1);
|
||||
}
|
||||
return test_sub(optb, opte);
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
int id, not;
|
||||
char *s, *err_fmt = "Bad flag '%s'";
|
||||
int optc = toys.optc;
|
||||
|
||||
toys.exitval = 2;
|
||||
if (!strcmp("[", toys.which->name))
|
||||
if (!strcmp("]", toys.optargs[--toys.optc])) error_exit("Missing ']'");
|
||||
if (!strcmp("!", toys.optargs[0])) {
|
||||
not = 1;
|
||||
toys.optargs++;
|
||||
toys.optc--;
|
||||
}
|
||||
if (!toys.optc) toys.exitval = 0;
|
||||
else if (toys.optargs[0][0] == '-') {
|
||||
id = stridx("bcdefghLpSsurwxznt", toys.optargs[0][1]);
|
||||
if (id == -1 || toys.optargs[0][2]) error_exit(err_fmt, toys.optargs[0]);
|
||||
if (id < 12) {
|
||||
struct stat st;
|
||||
int nolink;
|
||||
|
||||
toys.exitval = 1;
|
||||
if (lstat(toys.optargs[1], &st) == -1) return;
|
||||
nolink = !S_ISLNK(st.st_mode);
|
||||
if (!nolink && (stat(toys.optargs[1], &st) == -1)) return;
|
||||
|
||||
if (id == 0) toys.exitval = !S_ISBLK(st.st_mode); // b
|
||||
else if (id == 1) toys.exitval = !S_ISCHR(st.st_mode); // c
|
||||
else if (id == 2) toys.exitval = !S_ISDIR(st.st_mode); // d
|
||||
else if (id == 3) toys.exitval = 0; // e
|
||||
else if (id == 4) toys.exitval = !S_ISREG(st.st_mode); // f
|
||||
else if (id == 5) toys.exitval = !(st.st_mode & S_ISGID); // g
|
||||
else if ((id == 6) || (id == 7)) toys.exitval = nolink; // hL
|
||||
else if (id == 8) toys.exitval = !S_ISFIFO(st.st_mode); // p
|
||||
else if (id == 9) toys.exitval = !S_ISSOCK(st.st_mode); // S
|
||||
else if (id == 10) toys.exitval = st.st_size == 0; // s
|
||||
else toys.exitval = !(st.st_mode & S_ISUID); // u
|
||||
}
|
||||
else if (id < 15) // rwx
|
||||
toys.exitval = access(toys.optargs[1], 1 << (id - 12)) == -1;
|
||||
else if (id < 17) // zn
|
||||
toys.exitval = toys.optargs[1] && !*toys.optargs[1] ^ (id - 15);
|
||||
else { // t
|
||||
struct termios termios;
|
||||
toys.exitval = tcgetattr(atoi(toys.optargs[1]), &termios) == -1;
|
||||
}
|
||||
}
|
||||
else if (toys.optc == 1) toys.exitval = *toys.optargs[0] == 0;
|
||||
else if (toys.optc == 3) {
|
||||
if (*toys.optargs[1] == '-') {
|
||||
long a = atol(toys.optargs[0]), b = atol(toys.optargs[2]);
|
||||
|
||||
s = toys.optargs[1] + 1;
|
||||
if (!strcmp("eq", s)) toys.exitval = a != b;
|
||||
else if (!strcmp("ne", s)) toys.exitval = a == b;
|
||||
else if (!strcmp("gt", s)) toys.exitval = a < b;
|
||||
else if (!strcmp("ge", s)) toys.exitval = a <= b;
|
||||
else if (!strcmp("lt", s)) toys.exitval = a > b;
|
||||
else if (!strcmp("le", s)) toys.exitval = a >= b;
|
||||
else error_exit(err_fmt, toys.optargs[1]);
|
||||
}
|
||||
else {
|
||||
int result = strcmp(toys.optargs[0], toys.optargs[2]);
|
||||
|
||||
s = toys.optargs[1];
|
||||
if (!strcmp("=", s)) toys.exitval = !!result;
|
||||
else if (!strcmp("!=", s)) toys.exitval = !result;
|
||||
else error_exit(err_fmt, toys.optargs[1]);
|
||||
}
|
||||
}
|
||||
toys.exitval ^= not;
|
||||
if (!optc || strcmp("]", toys.optargs[--optc])) error_exit("Missing ']'");
|
||||
if (optc <= 4) toys.exitval = !test_few_args(0, optc);
|
||||
else toys.exitval = !test_sub(0, optc);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user