]> git.lizzy.rs Git - plan9front.git/commitdiff
test: fix expression parser
authorAlex Musolino <alex@musolino.id.au>
Sat, 6 Feb 2021 05:21:09 +0000 (15:51 +1030)
committerAlex Musolino <alex@musolino.id.au>
Sat, 6 Feb 2021 05:21:09 +0000 (15:51 +1030)
The old parser code was rubbish and only worked for trivial
expressions.  The new code properly handles complex expressions,
including short circuit evaluation.

As such, the BUGS section has been removed from the test(1) man page.
The description of an unimplemented feature has also been removed.

sys/man/1/test
sys/src/cmd/test.c

index 8feabf19af08f3b1117ac0234b3e3a0f93a2fa07..3ea005b9df6b5c2bab3fe88227d0703d6b45bc93 100644 (file)
@@ -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 .
index 5c7c17663678ec1d8b65fd4b87d0b998668f907a..be080a259da2cd340414a9842463764ac1bbd55f 100644 (file)
@@ -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, "-ge"))
-                       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, "-ge"))
+                               return(int1>=int2);
+                       if(EQ(p2, "-le"))
+                               return(int1<=int2);
+                       ap--;
+               }
+       }
+       ap--;
+       return !EQ(a, "");
 }
 
 int