From 53cf1b1c1c3f0c2b5067afccc2976b99a574a089 Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 14 May 1997 15:30:41 +0000 Subject: Initial revision --- walk.c | 358 ----------------------------------------------------------------- 1 file changed, 358 deletions(-) delete mode 100644 walk.c (limited to 'walk.c') diff --git a/walk.c b/walk.c deleted file mode 100644 index ed9f965..0000000 --- a/walk.c +++ /dev/null @@ -1,358 +0,0 @@ -/* walk.c: walks the parse tree. */ - -#include -#include -#include "rc.h" -#include "jbwrap.h" - -/* - global which indicates whether rc is executing a test; - used by rc -e so that if (false) does not exit. -*/ -bool cond = FALSE; - -static bool haspreredir(Node *); -static bool isallpre(Node *); -static bool dofork(bool); -static void dopipe(Node *); - -/* Tail-recursive version of walk() */ - -#define WALK(x, y) { n = x; parent = y; goto top; } - -/* walk the parse-tree. "obvious". */ - -extern bool walk(Node *n, bool parent) { -top: sigchk(); - if (n == NULL) { - if (!parent) - exit(0); - set(TRUE); - return TRUE; - } - switch (n->type) { - case nArgs: case nBackq: case nConcat: case nCount: - case nFlat: case nLappend: case nRedir: case nVar: - case nVarsub: case nWord: case nQword: - exec(glob(glom(n)), parent); /* simple command */ - break; - case nBody: - walk(n->u[0].p, TRUE); - WALK(n->u[1].p, parent); - /* WALK doesn't fall through */ - case nNowait: { - int pid; - if ((pid = rc_fork()) == 0) { -#if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP) - setsigdefaults(FALSE); - rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ - rc_signal(SIGTTIN, SIG_IGN); - rc_signal(SIGTSTP, SIG_IGN); - setpgid(0, getpid()); -#else - setsigdefaults(TRUE); /* ignore SIGINT, SIGQUIT, SIGTERM */ -#endif - mvfd(rc_open("/dev/null", rFrom), 0); - walk(n->u[0].p, FALSE); - exit(getstatus()); - } - if (interactive) - fprint(2, "%d\n", pid); - varassign("apid", word(nprint("%d", pid), NULL), FALSE); - redirq = NULL; /* kill pre-redir queue */ - break; - } - case nAndalso: { - bool oldcond = cond; - cond = TRUE; - if (walk(n->u[0].p, TRUE)) { - cond = oldcond; - WALK(n->u[1].p, parent); - } else - cond = oldcond; - break; - } - case nOrelse: { - bool oldcond = cond; - cond = TRUE; - if (!walk(n->u[0].p, TRUE)) { - cond = oldcond; - WALK(n->u[1].p, parent); - } else - cond = oldcond; - break; - } - case nBang: - set(!walk(n->u[0].p, TRUE)); - break; - case nIf: { - bool oldcond = cond; - Node *true_cmd = n->u[1].p, *false_cmd = NULL; - if (true_cmd != NULL && true_cmd->type == nElse) { - false_cmd = true_cmd->u[1].p; - true_cmd = true_cmd->u[0].p; - } - cond = TRUE; - if (!walk(n->u[0].p, TRUE)) - true_cmd = false_cmd; /* run the else clause */ - cond = oldcond; - WALK(true_cmd, parent); - } - case nWhile: { - Jbwrap j; - Edata jbreak; - Estack e1, e2; - bool testtrue, oldcond = cond; - cond = TRUE; - if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */ - cond = oldcond; - break; - } - if (setjmp(j.j)) - break; - jbreak.jb = &j; - except(eBreak, jbreak, &e1); - do { - Edata block; - block.b = newblock(); - cond = oldcond; - except(eArena, block, &e2); - walk(n->u[1].p, TRUE); - testtrue = walk(n->u[0].p, TRUE); - unexcept(); /* eArena */ - cond = TRUE; - } while (testtrue); - cond = oldcond; - unexcept(); /* eBreak */ - break; - } - case nForin: { - List *l, *var = glom(n->u[0].p); - Jbwrap j; - Estack e1, e2; - Edata jbreak; - if (setjmp(j.j)) - break; - jbreak.jb = &j; - except(eBreak, jbreak, &e1); - for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { - Edata block; - assign(var, word(l->w, NULL), FALSE); - block.b = newblock(); - except(eArena, block, &e2); - walk(n->u[2].p, TRUE); - unexcept(); /* eArena */ - } - unexcept(); /* eBreak */ - break; - } - case nSubshell: - if (dofork(TRUE)) { - walk(n->u[0].p, FALSE); - rc_exit(getstatus()); - } - break; - case nAssign: - if (n->u[0].p == NULL) - rc_error("null variable name"); - assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE); - set(TRUE); - break; - case nPipe: - dopipe(n); - break; - case nNewfn: { - List *l = glom(n->u[0].p); - if (l == NULL) - rc_error("null function name"); - while (l != NULL) { - if (dashex) - prettyprint_fn(2, l->w, n->u[1].p); - fnassign(l->w, n->u[1].p); - l = l->n; - } - set(TRUE); - break; - } - case nRmfn: { - List *l = glom(n->u[0].p); - while (l != NULL) { - if (dashex) - fprint(2, "fn %S\n", l->w); - fnrm(l->w); - l = l->n; - } - set(TRUE); - break; - } - case nDup: - redirq = NULL; - break; /* Null command */ - case nMatch: { - List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); - if (dashex) - fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " "); - set(lmatch(a, b)); - break; - } - case nSwitch: { - List *v = glom(n->u[0].p); - while (1) { - do { - n = n->u[1].p; - if (n == NULL) - return istrue(); - } while (n->u[0].p == NULL || n->u[0].p->type != nCase); - if (lmatch(v, glom(n->u[0].p->u[0].p))) { - for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) - walk(n->u[0].p, TRUE); - break; - } - } - break; - } - case nPre: { - List *v; - if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { - if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ - break; - qredir(n->u[0].p); - if (!haspreredir(n->u[1].p)) - doredirs(); /* no more preredirs, empty queue */ - walk(n->u[1].p, FALSE); - rc_exit(getstatus()); - /* NOTREACHED */ - } else if (n->u[0].p->type == nAssign) { - if (isallpre(n->u[1].p)) { - walk(n->u[0].p, TRUE); - WALK(n->u[1].p, parent); - } else { - Estack e; - Edata var; - v = glom(n->u[0].p->u[0].p); - assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE); - var.name = v->w; - except(eVarstack, var, &e); - walk(n->u[1].p, parent); - varrm(v->w, TRUE); - unexcept(); /* eVarstack */ - } - } else - panic("unexpected node in preredir section of walk"); - break; - } - case nBrace: - if (n->u[1].p == NULL) { - WALK(n->u[0].p, parent); - } else if (dofork(parent)) { - walk(n->u[1].p, TRUE); /* Do redirections */ - redirq = NULL; /* Reset redirection queue */ - walk(n->u[0].p, FALSE); /* Do commands */ - rc_exit(getstatus()); - /* NOTREACHED */ - } - break; - case nEpilog: - qredir(n->u[0].p); - if (n->u[1].p != NULL) { - WALK(n->u[1].p, parent); /* Do more redirections. */ - } else { - doredirs(); /* Okay, we hit the bottom. */ - } - break; - case nNmpipe: - rc_error("named pipes cannot be executed as commands"); - /* NOTREACHED */ - default: - panic("unknown node in walk"); - /* NOTREACHED */ - } - return istrue(); -} - -/* checks to see whether there are any pre-redirections left in the tree */ - -static bool haspreredir(Node *n) { - while (n != NULL && n->type == nPre) { - if (n->u[0].p->type == nDup || n->u[0].p->type == nRedir) - return TRUE; - n = n->u[1].p; - } - return FALSE; -} - -/* checks to see whether a subtree is all pre-command directives, i.e., assignments and redirs only */ - -static bool isallpre(Node *n) { - while (n != NULL && n->type == nPre) - n = n->u[1].p; - return n == NULL || n->type == nRedir || n->type == nAssign || n->type == nDup; -} - -/* - A code-saver. Forks, child returns (for further processing in walk()), and the parent - waits for the child to finish, setting $status appropriately. -*/ - -static bool dofork(bool parent) { - int pid, sp; - - if (!parent || (pid = rc_fork()) == 0) - return TRUE; - redirq = NULL; /* clear out the pre-redirection queue in the parent */ - rc_wait4(pid, &sp, TRUE); - setstatus(-1, sp); - sigchk(); - return FALSE; -} - -static void dopipe(Node *n) { - int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2]; - bool intr; - Node *r; - - fd_prev = fd_out = 1; - for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) { - if (i > 500) /* the only hard-wired limit in rc? */ - rc_error("pipe too long"); - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if ((pid = rc_fork()) == 0) { - redirq = NULL; /* clear preredir queue */ - mvfd(p[0], r->u[1].i); - if (fd_prev != 1) - mvfd(fd_prev, fd_out); - close(p[1]); - walk(r->u[3].p, FALSE); - exit(getstatus()); - } - if (fd_prev != 1) - close(fd_prev); /* parent must close all pipe fd's */ - pids[i] = pid; - fd_prev = p[1]; - fd_out = r->u[0].i; - close(p[0]); - } - if ((pid = rc_fork()) == 0) { - mvfd(fd_prev, fd_out); - walk(r, FALSE); - exit(getstatus()); - /* NOTREACHED */ - } - redirq = NULL; /* clear preredir queue */ - close(fd_prev); - pids[i++] = pid; - - /* collect statuses */ - - intr = FALSE; - for (j = 0; j < i; j++) { - rc_wait4(pids[j], &sp, TRUE); - stats[j] = sp; - intr |= (sp == SIGINT); - } - setpipestatus(stats, i); - sigchk(); -} -- cgit v1.2.3