STATIC union node * list(nlflag) { union node *n1, *n2, *n3; checkkwd(); if (nlflag == 0 && tokendlist[lasttoken]) return NULL; n1 = andor(); for (;;) { switch (readtoken()) { case TBACKGND: if (n1->type == NCMD || n1->type == NPIPE) { n1->ncmd.backgnd = 1; } else if (n1->type == NREDIR) { n1->type = NBACKGND; } else { n3 = (union node *)stalloc(sizeof (struct nredir)); n3->type = NBACKGND; n3->nredir.n = n1; n3->nredir.redirect = NULL; n1 = n3; } goto tsemi; case TNL: tokpushback++; /* fall through */ tsemi: case TSEMI: if (readtoken() == TNL) { parseheredoc(); if (nlflag) return n1; } else { tokpushback++; } checkkwd(); if (tokendlist[lasttoken]) return n1; n2 = andor(); n3 = (union node *)stalloc(sizeof (struct nbinary)); n3->type = NSEMI; n3->nbinary.ch1 = n1; n3->nbinary.ch2 = n2; n1 = n3; break; case TEOF: if (heredoclist) parseheredoc(); else pungetc(); /* push back EOF on input */ return n1; default: if (nlflag) synexpect(-1); tokpushback++; return n1; } } }
STATIC int readtoken(void) { int t; int savecheckkwd = checkkwd; struct alias *ap; #if DEBUG int alreadyseen = tokpushback; #endif top: t = xxreadtoken(); if (checkkwd) { /* * eat newlines */ if (checkkwd == 2) { checkkwd = 0; while (t == TNL) { parseheredoc(); t = xxreadtoken(); } } else checkkwd = 0; /* * check for keywords and aliases */ if (t == TWORD && !quoteflag) { const char * const *pp; for (pp = parsekwd; *pp; pp++) { if (**pp == *wordtext && equal(*pp, wordtext)) { lasttoken = t = pp - parsekwd + KWDOFFSET; TRACE(("keyword %s recognized\n", tokname[t])); goto out; } } if (noaliases == 0 && (ap = lookupalias(wordtext, 1)) != NULL) { pushstring(ap->val, strlen(ap->val), ap); checkkwd = savecheckkwd; goto top; } } out: checkkwd = (t == TNOT) ? savecheckkwd : 0; } #if DEBUG if (!alreadyseen) TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); else TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); #endif return (t); }
STATIC void checkkwd() { register char *const *pp; int t; while ((t = readtoken()) == TNL) parseheredoc(); if (t == TWORD && quoteflag == 0) { for (pp = parsekwd ; *pp ; pp++) { if (**pp == *wordtext && equal(*pp, wordtext)) { lasttoken = pp - parsekwd + KWDOFFSET; break; } } } tokpushback++; }
STATIC union node * list(int nlflag) { union node *n1, *n2, *n3; int tok; checkkwd = 2; if (nlflag == 0 && tokendlist[peektoken()]) return NULL; n1 = NULL; for (;;) { n2 = andor(); tok = readtoken(); if (tok == TBACKGND) { if (n2->type == NCMD || n2->type == NPIPE) { n2->ncmd.backgnd = 1; } else if (n2->type == NREDIR) { n2->type = NBACKGND; } else { n3 = (union node *)stalloc(sizeof (struct nredir)); n3->type = NBACKGND; n3->nredir.n = n2; n3->nredir.redirect = NULL; n2 = n3; } } if (n1 == NULL) { n1 = n2; } else { n3 = (union node *)stalloc(sizeof (struct nbinary)); n3->type = NSEMI; n3->nbinary.ch1 = n1; n3->nbinary.ch2 = n2; n1 = n3; } switch (tok) { case TBACKGND: case TSEMI: tok = readtoken(); /* FALLTHROUGH */ case TNL: if (tok == TNL) { parseheredoc(); if (nlflag) return n1; } else { tokpushback++; } checkkwd = 2; if (tokendlist[peektoken()]) return n1; break; case TEOF: if (heredoclist) parseheredoc(); else pungetc(); /* push back EOF on input */ return n1; default: if (nlflag) synexpect(-1); tokpushback++; return n1; } } }