diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1996-12-01 05:09:52 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1996-12-01 05:09:52 +0000 |
commit | 41c60e568d8d84276cc5023fc9f1429f8efdefa8 (patch) | |
tree | 0bd8cc11a4e1ca9407a3fc3d441f69a9750e2b61 /bin/sh | |
parent | bf0832b344afcdaa95f3e74104d79808a74b9617 (diff) |
Parser fix from NetBSD (christos)
- ! was only recognized in the beginning of pipelines. Now we
are recognizing it everywhere like ksh, so the following works.
! if [ a = b ]; then ! echo c && ! true; else ! echo d; fi
Diffstat (limited to 'bin/sh')
-rw-r--r-- | bin/sh/parser.c | 99 |
1 files changed, 60 insertions, 39 deletions
diff --git a/bin/sh/parser.c b/bin/sh/parser.c index e30da0c5457..5205429be43 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -1,5 +1,5 @@ -/* $OpenBSD: parser.c,v 1.5 1996/10/20 00:55:02 millert Exp $ */ -/* $NetBSD: parser.c,v 1.29 1996/05/09 19:40:08 christos Exp $ */ +/* $OpenBSD: parser.c,v 1.6 1996/12/01 05:09:51 millert Exp $ */ +/* $NetBSD: parser.c,v 1.31 1996/11/25 20:22:00 christos Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; #else -static char rcsid[] = "$NetBSD: parser.c,v 1.29 1996/05/09 19:40:08 christos Exp $"; +static char rcsid[] = "$OpenBSD: parser.c,v 1.6 1996/12/01 05:09:51 millert Exp $"; #endif #endif /* not lint */ @@ -123,7 +123,7 @@ STATIC int readtoken1 __P((int, char const *, char *, int)); STATIC int noexpand __P((char *)); STATIC void synexpect __P((int)); STATIC void synerror __P((char *)); -STATIC void setprompt __P((int)); +STATIC void setprompt __P((int)); /* @@ -132,7 +132,7 @@ STATIC void setprompt __P((int)); */ union node * -parsecmd(interact) +parsecmd(interact) int interact; { int t; @@ -154,7 +154,7 @@ parsecmd(interact) STATIC union node * -list(nlflag) +list(nlflag) int nlflag; { union node *n1, *n2, *n3; @@ -252,16 +252,10 @@ andor() { STATIC union node * pipeline() { - union node *n1, *pipenode, *notnode; + union node *n1, *pipenode; struct nodelist *lp, *prev; - int negate = 0; TRACE(("pipeline: entered\n")); - while (readtoken() == TNOT) { - TRACE(("pipeline: TNOT recognized\n")); - negate = !negate; - } - tokpushback++; n1 = command(); if (readtoken() == TPIPE) { pipenode = (union node *)stalloc(sizeof (struct npipe)); @@ -280,12 +274,6 @@ pipeline() { n1 = pipenode; } tokpushback++; - if (negate) { - notnode = (union node *)stalloc(sizeof (struct nnot)); - notnode->type = NNOT; - notnode->nnot.com = n1; - n1 = notnode; - } return n1; } @@ -297,12 +285,13 @@ command() { union node *ap, **app; union node *cp, **cpp; union node *redir, **rpp; - int t; + int t, negate = 0; checkkwd = 2; redir = NULL; n1 = NULL; rpp = &redir; + /* Check for redirection which may precede command */ while (readtoken() == TREDIR) { *rpp = n2 = redirnode; @@ -311,6 +300,12 @@ command() { } tokpushback++; + while (readtoken() == TNOT) { + TRACE(("command: TNOT recognized\n")); + negate = !negate; + } + tokpushback++; + switch (readtoken()) { case TIF: n1 = (union node *)stalloc(sizeof (struct nif)); @@ -481,7 +476,8 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); case TWORD: case TRP: tokpushback++; - return simplecmd(rpp, redir); + n1 = simplecmd(rpp, redir); + goto checkneg; default: synexpect(-1); } @@ -503,17 +499,27 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); } n1->nredir.redirect = redir; } - return n1; + +checkneg: + if (negate) { + n2 = (union node *)stalloc(sizeof (struct nnot)); + n2->type = NNOT; + n2->nnot.com = n1; + return n2; + } + else + return n1; } STATIC union node * -simplecmd(rpp, redir) +simplecmd(rpp, redir) union node **rpp, *redir; { union node *args, **app; union node **orig_rpp = rpp; - union node *n = NULL; + union node *n = NULL, *n2; + int negate = 0; /* If we don't have any redirections already, then we must reset */ /* rpp to be the address of the local redir variable. */ @@ -522,13 +528,19 @@ simplecmd(rpp, redir) args = NULL; app = &args; - /* + /* * We save the incoming value, because we need this for shell * functions. There can not be a redirect or an argument between - * the function name and the open parenthesis. + * the function name and the open parenthesis. */ orig_rpp = rpp; + while (readtoken() == TNOT) { + TRACE(("command: TNOT recognized\n")); + negate = !negate; + } + tokpushback++; + for (;;) { if (readtoken() == TWORD) { n = (union node *)stalloc(sizeof (struct narg)); @@ -552,7 +564,7 @@ simplecmd(rpp, redir) #endif n->type = NDEFUN; n->narg.next = command(); - return n; + goto checkneg; } else { tokpushback++; break; @@ -565,7 +577,16 @@ simplecmd(rpp, redir) n->ncmd.backgnd = 0; n->ncmd.args = args; n->ncmd.redirect = redir; - return n; + +checkneg: + if (negate) { + n2 = (union node *)stalloc(sizeof (struct nnot)); + n2->type = NNOT; + n2->nnot.com = n; + return n2; + } + else + return n; } STATIC union node * @@ -594,7 +615,7 @@ void fixredir(n, text, err) else if (text[0] == '-' && text[1] == '\0') n->ndup.dupfd = -1; else { - + if (err) synerror("Bad fd number"); else @@ -686,7 +707,7 @@ readtoken() { #ifdef DEBUG int alreadyseen = tokpushback; #endif - + top: t = xxreadtoken(); @@ -705,12 +726,12 @@ readtoken() { /* * check for keywords and aliases */ - if (t == TWORD && !quoteflag) + if (t == TWORD && !quoteflag) { register char * const *pp; for (pp = (char **)parsekwd; *pp; pp++) { - if (**pp == *wordtext && equal(*pp, wordtext)) + if (**pp == *wordtext && equal(*pp, wordtext)) { lasttoken = t = pp - parsekwd + KWDOFFSET; TRACE(("keyword %s recognized\n", tokname[t])); @@ -724,7 +745,7 @@ readtoken() { } } out: - checkkwd = 0; + checkkwd = (t == TNOT) ? savecheckkwd : 0; } #ifdef DEBUG if (!alreadyseen) @@ -989,7 +1010,7 @@ readtoken1(firstc, syntax, eofmark, striptabs) } else USTPUTC(')', out); } else { - /* + /* * unbalanced parens * (don't 2nd guess - no error) */ @@ -1195,7 +1216,7 @@ badsub: synerror("Bad substitution"); subtype = p - types + VSNORMAL; break; case '%': - case '#': + case '#': { int cc = c; subtype = c == '#' ? VSTRIMLEFT : @@ -1265,7 +1286,7 @@ parsebackq: { int savelen; char *str; - + STARTSTACKSTR(out); for (;;) { if (needprompt) { @@ -1302,9 +1323,9 @@ parsebackq: { break; case PEOF: - startlinno = plinno; + startlinno = plinno; synerror("EOF in backquote substitution"); - break; + break; default: break; @@ -1455,7 +1476,7 @@ goodname(name) */ STATIC void -synexpect(token) +synexpect(token) int token; { char msg[64]; |