diff --git a/sys/man/1/test b/sys/man/1/test index 8feabf19a..3ea005b9d 100644 --- a/sys/man/1/test +++ b/sys/man/1/test @@ -100,11 +100,6 @@ or .BR -le may be used in place of .BR -eq . -The (nonstandard) construct -.BI -l " string\f1, -meaning the length of -.IR string , -may be used in place of an integer. .TP .IB a " -nt " b True if file @@ -209,10 +204,3 @@ is in the current directory. .B /sys/src/cmd/test.c .SH "SEE ALSO" .IR rc (1) -.SH BUGS -Won't complain about extraneous arguments -since there may be arguments left unprocessed by -short-circuit evaluation of -.B -a -or -.BR -o . diff --git a/sys/src/cmd/test.c b/sys/src/cmd/test.c index 5c7c17663..be080a259 100644 --- a/sys/src/cmd/test.c +++ b/sys/src/cmd/test.c @@ -30,7 +30,7 @@ int isolderthan(char *, char *); int isnewerthan(char *, char *); int hasmode(char *, ulong); int tio(char *, int); -int e(void), e1(void), e2(void), e3(void); +int e(int), e1(int), e2(int), e3(int); char *nxtarg(int); void @@ -47,12 +47,8 @@ main(int argc, char *argv[]) argv[ac] = 0; if (ac<=1) exits("usage"); - r = e(); - /* - * nice idea but short-circuit -o and -a operators may have - * not consumed their right-hand sides. - */ - if(0 && (c = nxtarg(1)) != nil) + r = e(1); + if((c = nxtarg(1)) != nil) synbad("unexpected operator/operand: ", c); exits(r?0:"false"); } @@ -81,78 +77,128 @@ nxtintarg(int *pans) } int -e(void) +e(int eval) { + char *op; int p1; - p1 = e1(); - if (EQ(nxtarg(1), "-o")) - return(p1 || e()); - ap--; - return(p1); + p1 = e1(eval); + for(;;){ + op = nxtarg(1); + if(op == nil) + break; + if(!EQ(op, "-o")){ + ap--; + return p1; + } + if(!p1 && eval) + p1 |= e1(1); + else + e1(0); + } + return p1; } int -e1(void) +e1(int eval) { + char *op; int p1; - p1 = e2(); - if (EQ(nxtarg(1), "-a")) - return (p1 && e1()); - ap--; - return(p1); + p1 = e2(eval); + for(;;){ + op = nxtarg(1); + if(op == nil) + break; + if(!EQ(op, "-a")){ + ap--; + return p1; + } + if(p1 && eval) + p1 &= e2(1); + else + e2(0); + } + return p1; } int -e2(void) +e2(int eval) { - if (EQ(nxtarg(0), "!")) - return(!e2()); + char *op; + int p1; + + p1 = 0; + for(;;){ + op = nxtarg(1); + if(op == nil) + return p1 ^ 1; + if(!EQ(op, "!")) + break; + p1 ^= 1; + } ap--; - return(e3()); + return(p1^e3(eval)); } int -e3(void) +e3(int eval) { int p1, int1, int2; - char *a, *p2; + char *a, *b, *p2; a = nxtarg(0); if(EQ(a, "(")) { - p1 = e(); + p1 = e(eval); if(!EQ(nxtarg(0), ")")) synbad(") expected",""); return(p1); } - if(EQ(a, "-A")) - return(hasmode(nxtarg(0), DMAPPEND)); + if(EQ(a, "-A")){ + b = nxtarg(0); + return(eval && hasmode(b, DMAPPEND)); + } - if(EQ(a, "-L")) - return(hasmode(nxtarg(0), DMEXCL)); + if(EQ(a, "-L")){ + b = nxtarg(0); + return(eval && hasmode(b, DMEXCL)); + } - if(EQ(a, "-T")) - return(hasmode(nxtarg(0), DMTMP)); + if(EQ(a, "-T")){ + b = nxtarg(0); + return(eval && hasmode(b, DMTMP)); + } - if(EQ(a, "-f")) - return(isreg(nxtarg(0))); + if(EQ(a, "-f")){ + b = nxtarg(0); + return(eval && isreg(b)); + } - if(EQ(a, "-d")) - return(isdir(nxtarg(0))); + if(EQ(a, "-d")){ + b = nxtarg(0); + return(eval && isdir(b)); + } - if(EQ(a, "-r")) - return(tio(nxtarg(0), AREAD)); + if(EQ(a, "-r")){ + b = nxtarg(0); + return(eval && tio(b, AREAD)); + } - if(EQ(a, "-w")) - return(tio(nxtarg(0), AWRITE)); + if(EQ(a, "-w")){ + b = nxtarg(0); + return(eval && tio(b, AWRITE)); + } - if(EQ(a, "-x")) - return(tio(nxtarg(0), AEXEC)); + if(EQ(a, "-x")){ + b = nxtarg(0); + return(eval && tio(b, AEXEC)); + } - if(EQ(a, "-e")) - return(tio(nxtarg(0), AEXIST)); + if(EQ(a, "-e")){ + b = nxtarg(0); + return(eval && tio(b, AEXIST)); + } if(EQ(a, "-c")) return(0); @@ -166,14 +212,16 @@ e3(void) if(EQ(a, "-g")) return(0); - if(EQ(a, "-s")) - return(fsizep(nxtarg(0))); + if(EQ(a, "-s")){ + b = nxtarg(0); + return(eval && fsizep(b)); + } if(EQ(a, "-t")) if(ap>=ac) - return(isatty(1)); + return(eval && isatty(1)); else if(nxtintarg(&int1)) - return(isatty(int1)); + return(eval && isatty(int1)); else synbad("not a valid file descriptor number ", ""); @@ -191,35 +239,40 @@ e3(void) if(EQ(p2, "!=")) return(!EQ(nxtarg(0), a)); - if(EQ(p2, "-older")) - return(isolder(nxtarg(0), a)); - - if(EQ(p2, "-ot")) - return(isolderthan(nxtarg(0), a)); - - if(EQ(p2, "-nt")) - return(isnewerthan(nxtarg(0), a)); - - if(!isint(a, &int1)) - synbad("unexpected operator/operand: ", p2); - - if(nxtintarg(&int2)){ - if(EQ(p2, "-eq")) - return(int1==int2); - if(EQ(p2, "-ne")) - return(int1!=int2); - if(EQ(p2, "-gt")) - return(int1>int2); - if(EQ(p2, "-lt")) - return(int1=int2); - if(EQ(p2, "-le")) - return(int1<=int2); + if(EQ(p2, "-older")){ + b = nxtarg(0); + return(eval && isolder(b, a)); } - synbad("unknown operator ",p2); - return 0; /* to shut ken up */ + if(EQ(p2, "-ot")){ + b = nxtarg(0); + return(eval && isolderthan(b, a)); + } + + if(EQ(p2, "-nt")){ + b = nxtarg(0); + return(eval && isnewerthan(b, a)); + } + + if(isint(a, &int1)){ + if(nxtintarg(&int2)){ + if(EQ(p2, "-eq")) + return(int1==int2); + if(EQ(p2, "-ne")) + return(int1!=int2); + if(EQ(p2, "-gt")) + return(int1>int2); + if(EQ(p2, "-lt")) + return(int1=int2); + if(EQ(p2, "-le")) + return(int1<=int2); + ap--; + } + } + ap--; + return !EQ(a, ""); } int