Source-Changes-D archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: CVS commit: src/distrib



On Sep 21, 10:01pm, david%l8s.co.uk@localhost (David Laight) wrote:
-- Subject: Re: CVS commit: src/distrib

| On Sun, Sep 20, 2009 at 05:32:17PM -0400, Christos Zoulas wrote:
| > 
| > | Although posix defines strict rules for expressions with small
| > | numbers of arguments, netbsd'd parser doesn't obey them!
| > 
| > Really? Can you give me an example.
| 
| See PR/34646
| 
| $ test ! = foo

This should prolly fix it... From FreeBSD.

christos

Index: test.c
===================================================================
RCS file: /cvsroot/src/bin/test/test.c,v
retrieving revision 1.37
diff -u -u -r1.37 test.c
--- test.c      10 Sep 2008 19:00:51 -0000      1.37
+++ test.c      21 Sep 2009 22:37:06 -0000
@@ -153,8 +153,10 @@
        {"z",   STREZ,  UNOP},
 };
 
+static int nargc;
 static char **t_wp;
 static struct t_op const *t_wp_op;
+static int parenlevel;
 
 static void syntax(const char *, const char *);
 static int oexpr(enum token);
@@ -165,8 +167,10 @@
 static int test_access(struct stat *, mode_t);
 static int filstat(char *, enum token);
 static enum token t_lex(char *);
-static int isoperand(void);
 static long long getn(const char *);
+static int isunopoperand(void);
+static int islparenoperand(void);
+static int isrparenoperand(void);
 static int newerf(const char *, const char *);
 static int olderf(const char *, const char *);
 static int equalf(const char *, const char *);
@@ -200,6 +204,8 @@
 }
 #endif
 
+#define GETARG (nargc > 0 ? (--nargc, *++t_wp) : NULL)
+
 #ifdef SHELL
 int testcmd(int, char **);
 
@@ -228,13 +234,21 @@
                argv[argc] = NULL;
        }
 
-       if (argc < 2)
+       if (--argc <= 0)
                return 1;
 
+       nargc = argc - 1;
        t_wp = &argv[1];
-       res = !oexpr(t_lex(*t_wp));
+       parenlevel = 0;
+       if (nargc == 4 && strcmp(*t_wp, "!") == 0) {
+               /* Things like ! "" -o x do not fit in the normal grammar. */
+               --nargc;
+               ++t_wp;
+               res = oexpr(t_lex(*t_wp));
+       } else 
+               res = !oexpr(t_lex(*t_wp));
 
-       if (*t_wp != NULL && *++t_wp != NULL)
+       if (--nargc > 0)
                syntax(*t_wp, "unexpected operator");
 
        return res;
@@ -258,9 +272,10 @@
        res = aexpr(n);
        if (*t_wp == NULL)
                return res;
-       if (t_lex(*++t_wp) == BOR)
-               return oexpr(t_lex(*++t_wp)) || res;
+       if (t_lex(GETARG) == BOR)
+               return oexpr(t_lex(GETARG)) || res;
        t_wp--;
+       nargc++;
        return res;
 }
 
@@ -272,9 +287,10 @@
        res = nexpr(n);
        if (*t_wp == NULL)
                return res;
-       if (t_lex(*++t_wp) == BAND)
-               return aexpr(t_lex(*++t_wp)) && res;
+       if (t_lex(GETARG) == BAND)
+               return aexpr(t_lex(GETARG)) && res;
        t_wp--;
+       nargc++;
        return res;
 }
 
@@ -283,7 +299,7 @@
 {
 
        if (n == UNOT)
-               return !nexpr(t_lex(*++t_wp));
+               return !nexpr(t_lex(GETARG));
        return primary(n);
 }
 
@@ -296,30 +312,35 @@
        if (n == EOI)
                return 0;               /* missing expression */
        if (n == LPAREN) {
-               if ((nn = t_lex(*++t_wp)) == RPAREN)
+               parenlevel++;
+               if ((nn = t_lex(GETARG)) == RPAREN) {
+                       parenlevel--;
                        return 0;       /* missing expression */
+               }
                res = oexpr(nn);
-               if (t_lex(*++t_wp) != RPAREN)
+               if (t_lex(GETARG) != RPAREN)
                        syntax(NULL, "closing paren expected");
+               parenlevel--;
                return res;
        }
        if (t_wp_op && t_wp_op->op_type == UNOP) {
                /* unary expression */
-               if (*++t_wp == NULL)
+               if (--nargc == 0)
                        syntax(t_wp_op->op_text, "argument expected");
                switch (n) {
                case STREZ:
-                       return strlen(*t_wp) == 0;
+                       return strlen(*++t_wp) == 0;
                case STRNZ:
-                       return strlen(*t_wp) != 0;
+                       return strlen(*++t_wp) != 0;
                case FILTT:
-                       return isatty((int)getn(*t_wp));
+                       return isatty((int)getn(*++t_wp));
                default:
-                       return filstat(*t_wp, n);
+                       return filstat(*++t_wp, n);
                }
        }
 
-       if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
+       if (t_lex(nargc > 0 ? t_wp[1] : NULL), t_wp_op && t_wp_op->op_type ==
+           BINOP) {
                return binop();
        }         
 
@@ -333,10 +354,10 @@
        struct t_op const *op;
 
        opnd1 = *t_wp;
-       (void) t_lex(*++t_wp);
+       (void) t_lex(GETARG);
        op = t_wp_op;
 
-       if ((opnd2 = *++t_wp) == NULL)
+       if ((opnd2 = GETARG) == NULL)
                syntax(op->op_text, "argument expected");
                
        switch (op->op_num) {
@@ -639,28 +660,67 @@
        }
 
        if ((op = findop(s)) != NULL) {
-               if (!((op->op_type == UNOP && isoperand()) ||
-                   (op->op_num == LPAREN && *(t_wp+1) == 0))) {
-                       t_wp_op = op;
-                       return op->op_num;
-               }
+               if (((op->op_type == UNOP || op->op_type == BUNOP)
+                                       && isunopoperand()) ||
+                   (op->op_num == LPAREN && islparenoperand()) ||
+                   (op->op_num == RPAREN && isrparenoperand()))
+                       goto out;
+               t_wp_op = op;
+               return op->op_num;
        }
+out:
        t_wp_op = NULL;
        return OPERAND;
 }
 
 static int
-isoperand(void)
+isunopoperand(void)
+{
+       struct t_op const *op;
+       char *s;
+       char *t;
+
+       if (nargc == 1)
+               return 1;
+       s = *(t_wp + 1);
+       if (nargc == 2)
+               return parenlevel == 1 && strcmp(s, ")") == 0;
+       t = *(t_wp + 2);
+       if ((op = findop(s)) != NULL) {
+               return op->op_type == BINOP &&
+                   (parenlevel == 0 || t[0] != ')' || t[1] != '\0');
+       }
+       return 0;
+}
+
+static int
+islparenoperand(void)
 {
        struct t_op const *op;
-       char *s, *t;
+       char *s;
 
-       if ((s  = *(t_wp+1)) == 0)
+       if (nargc == 1)
                return 1;
-       if ((t = *(t_wp+2)) == 0)
+       s = *(t_wp + 1);
+       if (nargc == 2)
+               return parenlevel == 1 && strcmp(s, ")") == 0;
+       if (nargc != 3)
                return 0;
        if ((op = findop(s)) != NULL)
-               return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); 
+               return op->op_type == BINOP;
+       return 0;
+}
+
+static int
+isrparenoperand(void)
+{
+       char *s;
+
+       if (nargc == 1)
+               return 0;
+       s = *(t_wp + 1);
+       if (nargc == 2)
+               return parenlevel == 1 && strcmp(s, ")") == 0;
        return 0;
 }
 


Home | Main Index | Thread Index | Old Index