/* glob1 -- glob pattern path against the file system */ static List *glob1(const char *pattern, const char *quote) { const char *s, *q; char *d, *p, *qd, *qp; size_t psize; List *matched; static char *dir = NULL, *pat = NULL, *qdir = NULL, *qpat = NULL, *raw = NULL; static size_t dsize = 0; assert(quote != QUOTED); if ((psize = strlen(pattern) + 1) > dsize || pat == NULL) { pat = erealloc(pat, psize); raw = erealloc(raw, psize); dir = erealloc(dir, psize); qpat = erealloc(qpat, psize); qdir = erealloc(qdir, psize); dsize = psize; memset(raw, 'r', psize); } d = dir; qd = qdir; q = (quote == UNQUOTED) ? raw : quote; s = pattern; if (*s == '/') while (*s == '/') *d++ = *s++, *qd++ = *q++; else while (*s != '/' && *s != '\0') *d++ = *s++, *qd++ = *q++; /* get first directory component */ *d = '\0'; /* * Special case: no slashes in the pattern, i.e., open the current directory. * Remember that w cannot consist of slashes alone (the other way *s could be * zero) since doglob gets called iff there's a metacharacter to be matched */ if (*s == '\0') return dirmatch("", ".", dir, qdir); matched = (*pattern == '/') ? mklist(mkstr(dir), NULL) : dirmatch("", ".", dir, qdir); do { size_t slashcount; SIGCHK(); for (slashcount = 0; *s == '/'; s++, q++) slashcount++; /* skip slashes */ for (p = pat, qp = qpat; *s != '/' && *s != '\0';) *p++ = *s++, *qp++ = *q++; /* get pat */ *p = '\0'; matched = listglob(matched, pat, qpat, slashcount); } while (*s != '\0' && matched != NULL); return matched; }
/* forkexec -- fork (if necessary) and exec */ extern List *forkexec(char *file, List *list, Boolean inchild) { int pid, status; Vector *env; gcdisable(); env = mkenv(); pid = efork(!inchild, FALSE); if (pid == 0) { execve(file, vectorize(list)->vector, env->vector); failexec(file, list); } gcenable(); status = ewaitfor(pid); if ((status & 0xff) == 0) { sigint_newline = FALSE; SIGCHK(); sigint_newline = TRUE; } else SIGCHK(); printstatus(0, status); return mklist(mkterm(mkstatus(status), NULL), NULL); }
/* walk -- walk through a tree, evaluating nodes */ extern List *walk(Tree *tree0, Binding *binding0, int flags) { Tree *volatile tree = tree0; Binding *volatile binding = binding0; SIGCHK(); top: if (tree == NULL) return true; switch (tree->kind) { case nConcat: case nList: case nQword: case nVar: case nVarsub: case nWord: case nThunk: case nLambda: case nCall: case nPrim: { List *list; Ref(Binding *, bp, binding); list = glom(tree, binding, TRUE); binding = bp; RefEnd(bp); return eval(list, binding, flags); } case nAssign: return assign(tree->u[0].p, tree->u[1].p, binding); case nLet: case nClosure: Ref(Tree *, body, tree->u[1].p); binding = letbindings(tree->u[0].p, binding, binding, flags); tree = body; RefEnd(body); goto top; case nLocal: return local(tree->u[0].p, tree->u[1].p, binding, flags); case nFor: return forloop(tree->u[0].p, tree->u[1].p, binding, flags); case nMatch: return matchpattern(tree->u[0].p, tree->u[1].p, binding); case nExtract: return extractpattern(tree->u[0].p, tree->u[1].p, binding); default: panic("walk: bad node kind %d", tree->kind); } NOTREACHED; }
extern void ewrite(int fd, const char *buf, size_t n) { volatile long i, remain; const char *volatile bufp = buf; for (i = 0, remain = n; remain > 0; bufp += i, remain -= i) { interrupted = FALSE; if (!setjmp(slowlabel)) { slow = TRUE; if (interrupted) break; else if ((i = write(fd, bufp, remain)) <= 0) break; /* abort silently on errors in write() */ } else break; slow = FALSE; } slow = FALSE; SIGCHK(); }
extern long eread(int fd, char *buf, size_t n) { long r; interrupted = FALSE; if (!setjmp(slowlabel)) { slow = TRUE; if (!interrupted) r = read(fd, buf, n); else r = -2; } else r = -2; slow = FALSE; if (r == -2) { errno = EINTR; r = -1; } SIGCHK(); return r; }
/* forloop -- evaluate a for loop */ static List *forloop(Tree *defn0, Tree *body0, Binding *binding, int evalflags) { static List MULTIPLE = { NULL, NULL }; Ref(List *, result, true); Ref(Binding *, outer, binding); Ref(Binding *, looping, NULL); Ref(Tree *, body, body0); Ref(Tree *, defn, defn0); for (; defn != NULL; defn = defn->u[1].p) { assert(defn->kind == nList); if (defn->u[0].p == NULL) continue; Ref(Tree *, assign, defn->u[0].p); assert(assign->kind == nAssign); Ref(List *, vars, glom(assign->u[0].p, outer, FALSE)); Ref(List *, list, glom(assign->u[1].p, outer, TRUE)); if (vars == NULL) fail("es:for", "null variable name"); for (; vars != NULL; vars = vars->next) { char *var = getstr(vars->term); looping = mkbinding(var, list, looping); list = &MULTIPLE; } RefEnd3(list, vars, assign); SIGCHK(); } looping = reversebindings(looping); RefEnd(defn); ExceptionHandler for (;;) { Boolean allnull = TRUE; Ref(Binding *, bp, outer); Ref(Binding *, lp, looping); Ref(Binding *, sequence, NULL); for (; lp != NULL; lp = lp->next) { Ref(List *, value, NULL); if (lp->defn != &MULTIPLE) sequence = lp; assert(sequence != NULL); if (sequence->defn != NULL) { value = mklist(sequence->defn->term, NULL); sequence->defn = sequence->defn->next; allnull = FALSE; } bp = mkbinding(lp->name, value, bp); RefEnd(value); } RefEnd2(sequence, lp); if (allnull) { RefPop(bp); break; } result = walk(body, bp, evalflags & eval_exitonfalse); RefEnd(bp); SIGCHK(); } CatchException (e) if (!termeq(e->term, "break")) throw(e); result = e->next; EndExceptionHandler RefEnd3(body, looping, outer); RefReturn(result); }