示例#1
0
文件: parser.c 项目: 7shi/minix-tools
STATIC union node *
command(void)
{
	union node *n1, *n2;
	union node *ap, **app;
	union node *cp, **cpp;
	union node *redir, **rpp;
	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;
		rpp = &n2->nfile.next;
		parsefname();
	}
	tokpushback++;

	while (readtoken() == TNOT) {
		TRACE(("command: TNOT recognized\n"));
		negate = !negate;
	}
	tokpushback++;

	switch (readtoken()) {
	case TIF:
		n1 = (union node *)stalloc(sizeof (struct nif));
		n1->type = NIF;
		if ((n1->nif.test = list(0)) == NULL)
			synexpect(-1);
		if (readtoken() != TTHEN)
			synexpect(TTHEN);
		n1->nif.ifpart = list(0);
		n2 = n1;
		while (readtoken() == TELIF) {
			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
			n2 = n2->nif.elsepart;
			n2->type = NIF;
			if ((n2->nif.test = list(0)) == NULL)
				synexpect(-1);
			if (readtoken() != TTHEN)
				synexpect(TTHEN);
			n2->nif.ifpart = list(0);
		}
		if (lasttoken == TELSE)
			n2->nif.elsepart = list(0);
		else {
			n2->nif.elsepart = NULL;
			tokpushback++;
		}
		if (readtoken() != TFI)
			synexpect(TFI);
		checkkwd = 1;
		break;
	case TWHILE:
	case TUNTIL: {
		int got;
		n1 = (union node *)stalloc(sizeof (struct nbinary));
		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
		if ((n1->nbinary.ch1 = list(0)) == NULL)
			synexpect(-1);
		if ((got=readtoken()) != TDO) {
TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
			synexpect(TDO);
		}
		n1->nbinary.ch2 = list(0);
		if (readtoken() != TDONE)
			synexpect(TDONE);
		checkkwd = 1;
		break;
	}
	case TFOR:
		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
			synerror("Bad for loop variable");
		n1 = (union node *)stalloc(sizeof (struct nfor));
		n1->type = NFOR;
		n1->nfor.var = wordtext;
		if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
			app = ≈
			while (readtoken() == TWORD) {
				n2 = (union node *)stalloc(sizeof (struct narg));
				n2->type = NARG;
				n2->narg.text = wordtext;
				n2->narg.backquote = backquotelist;
				*app = n2;
				app = &n2->narg.next;
			}
			*app = NULL;
			n1->nfor.args = ap;
			if (lasttoken != TNL && lasttoken != TSEMI)
				synexpect(-1);
		} else {
#ifndef GDB_HACK
			static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
								   '@', '=', '\0'};
#endif
			n2 = (union node *)stalloc(sizeof (struct narg));
			n2->type = NARG;
			n2->narg.text = (char *)argvars;
			n2->narg.backquote = NULL;
			n2->narg.next = NULL;
			n1->nfor.args = n2;
			/*
			 * Newline or semicolon here is optional (but note
			 * that the original Bourne shell only allowed NL).
			 */
			if (lasttoken != TNL && lasttoken != TSEMI)
				tokpushback++;
		}
		checkkwd = 2;
		if ((t = readtoken()) == TDO)
			t = TDONE;
		else if (t == TBEGIN)
			t = TEND;
		else
			synexpect(-1);
		n1->nfor.body = list(0);
		if (readtoken() != t)
			synexpect(t);
		checkkwd = 1;
		break;
	case TCASE:
		n1 = (union node *)stalloc(sizeof (struct ncase));
		n1->type = NCASE;
		if (readtoken() != TWORD)
			synexpect(TWORD);
		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
		n2->type = NARG;
		n2->narg.text = wordtext;
		n2->narg.backquote = backquotelist;
		n2->narg.next = NULL;
		while (readtoken() == TNL);
		if (lasttoken != TWORD || ! equal(wordtext, "in"))
			synerror("expecting \"in\"");
		cpp = &n1->ncase.cases;
		noaliases = 1;	/* turn off alias expansion */
		checkkwd = 2, readtoken();
		while (lasttoken != TESAC) {
			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
			cp->type = NCLIST;
			app = &cp->nclist.pattern;
			if (lasttoken == TLP)
				readtoken();
			for (;;) {
				*app = ap = (union node *)stalloc(sizeof (struct narg));
				ap->type = NARG;
				ap->narg.text = wordtext;
				ap->narg.backquote = backquotelist;
				if (checkkwd = 2, readtoken() != TPIPE)
					break;
				app = &ap->narg.next;
				readtoken();
			}
			ap->narg.next = NULL;
			if (lasttoken != TRP)
				noaliases = 0, synexpect(TRP);
			cp->nclist.body = list(0);

			checkkwd = 2;
			if ((t = readtoken()) != TESAC) {
				if (t != TENDCASE)
					noaliases = 0, synexpect(TENDCASE);
				else
					checkkwd = 2, readtoken();
			}
			cpp = &cp->nclist.next;
		}
		noaliases = 0;	/* reset alias expansion */
		*cpp = NULL;
		checkkwd = 1;
		break;
	case TLP:
		n1 = (union node *)stalloc(sizeof (struct nredir));
		n1->type = NSUBSHELL;
		n1->nredir.n = list(0);
		n1->nredir.redirect = NULL;
		if (readtoken() != TRP)
			synexpect(TRP);
		checkkwd = 1;
		break;
	case TBEGIN:
		n1 = list(0);
		if (readtoken() != TEND)
			synexpect(TEND);
		checkkwd = 1;
		break;
	/* Handle an empty command like other simple commands.  */
	case TSEMI:
	case TAND:
	case TOR:
		/*
		 * An empty command before a ; doesn't make much sense, and
		 * should certainly be disallowed in the case of `if ;'.
		 */
		if (!redir)
			synexpect(-1);
	case TNL:
	case TEOF:
	case TWORD:
	case TRP:
		tokpushback++;
		n1 = simplecmd(rpp, redir);
		goto checkneg;
	default:
		synexpect(-1);
	}

	/* Now check for redirection which may follow command */
	while (readtoken() == TREDIR) {
		*rpp = n2 = redirnode;
		rpp = &n2->nfile.next;
		parsefname();
	}
	tokpushback++;
	*rpp = NULL;
	if (redir) {
		if (n1->type != NSUBSHELL) {
			n2 = (union node *)stalloc(sizeof (struct nredir));
			n2->type = NREDIR;
			n2->nredir.n = n1;
			n1 = n2;
		}
		n1->nredir.redirect = redir;
	}

checkneg:
	if (negate) {
		n2 = (union node *)stalloc(sizeof (struct nnot));
		n2->type = NNOT;
		n2->nnot.com = n1;
		return n2;
	}
	else
		return n1;
}
示例#2
0
文件: parser.c 项目: hakan-akan/cor
STATIC union node *
command() {
      union node *n1, *n2;
      union node *ap, **app;
      union node *cp, **cpp;
      union node *redir, **rpp;
      int t;

      checkkwd();
      switch (readtoken()) {
      case TIF:
            n1 = (union node *)stalloc(sizeof (struct nif));
            n1->type = NIF;
            n1->nif.test = list(0);
            if (readtoken() != TTHEN)
                  synexpect(TTHEN);
            n1->nif.ifpart = list(0);
            n2 = n1;
            while (readtoken() == TELIF) {
                  n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
                  n2 = n2->nif.elsepart;
                  n2->type = NIF;
                  n2->nif.test = list(0);
                  if (readtoken() != TTHEN)
                        synexpect(TTHEN);
                  n2->nif.ifpart = list(0);
            }
            if (lasttoken == TELSE)
                  n2->nif.elsepart = list(0);
            else {
                  n2->nif.elsepart = NULL;
                  tokpushback++;
            }
            if (readtoken() != TFI)
                  synexpect(TFI);
            break;
      case TWHILE:
      case TUNTIL:
            n1 = (union node *)stalloc(sizeof (struct nbinary));
            n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
            n1->nbinary.ch1 = list(0);
            if (readtoken() != TDO)
                  synexpect(TDO);
            n1->nbinary.ch2 = list(0);
            if (readtoken() != TDONE)
                  synexpect(TDONE);
            break;
      case TFOR:
            if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
                  synerror("Bad for loop variable");
            n1 = (union node *)stalloc(sizeof (struct nfor));
            n1->type = NFOR;
            n1->nfor.var = wordtext;
            if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
                  app = ≈
                  while (readtoken() == TWORD) {
                        n2 = (union node *)stalloc(sizeof (struct narg));
                        n2->type = NARG;
                        n2->narg.text = wordtext;
                        n2->narg.backquote = backquotelist;
                        *app = n2;
                        app = &n2->narg.next;
                  }
                  *app = NULL;
                  n1->nfor.args = ap;
            } else {
#ifndef GDB_HACK
                  static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
                                                  '@', '=', '\0'};
#endif
                  n2 = (union node *)stalloc(sizeof (struct narg));
                  n2->type = NARG;
                  n2->narg.text = (char *)argvars;
                  n2->narg.backquote = NULL;
                  n2->narg.next = NULL;
                  n1->nfor.args = n2;
            }
            if (lasttoken != TNL && lasttoken != TSEMI)
                  synexpect(-1);
            checkkwd();
            if ((t = readtoken()) == TDO)
                  t = TDONE;
            else if (t == TBEGIN)
                  t = TEND;
            else
                  synexpect(-1);
            n1->nfor.body = list(0);
            if (readtoken() != t)
                  synexpect(t);
            break;
      case TCASE:
            n1 = (union node *)stalloc(sizeof (struct ncase));
            n1->type = NCASE;
            if (readtoken() != TWORD)
                  synexpect(TWORD);
            n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
            n2->type = NARG;
            n2->narg.text = wordtext;
            n2->narg.backquote = backquotelist;
            n2->narg.next = NULL;
            while (readtoken() == TNL);
            if (lasttoken != TWORD || ! equal(wordtext, "in"))
                  synerror("expecting \"in\"");
            cpp = &n1->ncase.cases;
            while (checkkwd(), readtoken() == TWORD) {
                  *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
                  cp->type = NCLIST;
                  app = &cp->nclist.pattern;
                  for (;;) {
                        *app = ap = (union node *)stalloc(sizeof (struct narg));
                        ap->type = NARG;
                        ap->narg.text = wordtext;
                        ap->narg.backquote = backquotelist;
                        if (readtoken() != TPIPE)
                              break;
                        app = &ap->narg.next;
                        if (readtoken() != TWORD)
                              synexpect(TWORD);
                  }
                  ap->narg.next = NULL;
                  if (lasttoken != TRP)
                        synexpect(TRP);
                  cp->nclist.body = list(0);
                  if ((t = readtoken()) == TESAC)
                        tokpushback++;
                  else if (t != TENDCASE)
                        synexpect(TENDCASE);
                  cpp = &cp->nclist.next;
            }
            *cpp = NULL;
            if (lasttoken != TESAC)
                  synexpect(TESAC);
            break;
      case TLP:
            n1 = (union node *)stalloc(sizeof (struct nredir));
            n1->type = NSUBSHELL;
            n1->nredir.n = list(0);
            n1->nredir.redirect = NULL;
            if (readtoken() != TRP)
                  synexpect(TRP);
            break;
      case TBEGIN:
            n1 = list(0);
            if (readtoken() != TEND)
                  synexpect(TEND);
            break;
      case TWORD:
      case TREDIR:
            tokpushback++;
            return simplecmd();
      default:
            synexpect(-1);
      }

      /* Now check for redirection which may follow command */
      rpp = &redir;
      while (readtoken() == TREDIR) {
            *rpp = n2 = redirnode;
            rpp = &n2->nfile.next;
            parsefname();
      }
      tokpushback++;
      *rpp = NULL;
      if (redir) {
            if (n1->type != NSUBSHELL) {
                  n2 = (union node *)stalloc(sizeof (struct nredir));
                  n2->type = NREDIR;
                  n2->nredir.n = n1;
                  n1 = n2;
            }
            n1->nredir.redirect = redir;
      }
      return n1;
}