/* listify -- turn an argc/argv vector into a list */ extern List *listify(int argc, char **argv) { Ref(List *, list, NULL); while (argc > 0) { Term *term = mkterm(argv[--argc], NULL); list = mklist(term, list); } RefReturn(list); }
extern List *endsplit(void) { List *result; if (buffer != NULL) { Term *term = mkterm(sealcountedbuffer(buffer), NULL); value = mklist(term, value); buffer = NULL; } result = reverse(value); value = NULL; return result; }
extern int esopt(const char *options) { int c; const char *arg, *opt; assert(usage != NULL); assert(termarg == NULL); if (nextchar == 0) { if (args == NULL) return EOF; assert(args->term != NULL); arg = getstr(args->term); if (*arg != '-') return EOF; if (arg[1] == '-' && arg[2] == '\0') { args = args->next; return EOF; } nextchar = 1; } else { assert(args != NULL && args->term != NULL); arg = getstr(args->term); } c = arg[nextchar++]; opt = strchr(options, c); if (opt == NULL) { const char *msg = usage; usage = NULL; args = NULL; nextchar = 0; fail(invoker, "illegal option: -%c -- usage: %s", c, msg); } if (arg[nextchar] == '\0') { nextchar = 0; args = args->next; } if (opt[1] == ':') { if (args == NULL) { const char *msg = usage; fail(invoker, "option -%c expects an argument -- usage: %s", c, msg); } termarg = (nextchar == 0) ? args->term : mkterm(gcdup(arg + nextchar), NULL); nextchar = 0; args = args->next; } return c; }
extern void splitstring(char *in, size_t len, Boolean endword) { Buffer *buf = buffer; unsigned char *s = (unsigned char *) in, *inend = s + len; if (splitchars) { assert(buf == NULL); while (s < inend) { Term *term = mkterm(gcndup((char *) s++, 1), NULL); value = mklist(term, value); } return; } if (!coalesce && buf == NULL) buf = openbuffer(0); while (s < inend) { int c = *s++; if (buf != NULL) if (isifs[c]) { Term *term = mkterm(sealcountedbuffer(buf), NULL); value = mklist(term, value); buf = coalesce ? NULL : openbuffer(0); } else buf = bufputc(buf, c); else if (!isifs[c]) buf = bufputc(openbuffer(0), c); } if (endword && buf != NULL) { Term *term = mkterm(sealcountedbuffer(buf), NULL); value = mklist(term, value); buf = NULL; } buffer = buf; }
/* 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); }
/* eval -- evaluate a list, producing a list */ extern List *eval(List *list0, Binding *binding0, int flags) { Closure *volatile cp; List *fn; if (++evaldepth >= maxevaldepth) fail("es:eval", "max-eval-depth exceeded"); Ref(List *, list, list0); Ref(Binding *, binding, binding0); Ref(char *, funcname, NULL); restart: if (list == NULL) { RefPop3(funcname, binding, list); --evaldepth; return true; } assert(list->term != NULL); if ((cp = getclosure(list->term)) != NULL) { switch (cp->tree->kind) { case nPrim: assert(cp->binding == NULL); list = prim(cp->tree->u[0].s, list->next, binding, flags); break; case nThunk: list = walk(cp->tree->u[0].p, cp->binding, flags); break; case nLambda: ExceptionHandler Push p; Ref(Tree *, tree, cp->tree); Ref(Binding *, context, bindargs(tree->u[0].p, list->next, cp->binding)); if (funcname != NULL) varpush(&p, "0", mklist(mkterm(funcname, NULL), NULL)); list = walk(tree->u[1].p, context, flags); if (funcname != NULL) varpop(&p); RefEnd2(context, tree); CatchException (e) if (termeq(e->term, "return")) { list = e->next; goto done; } throw(e); EndExceptionHandler break; case nList: { list = glom(cp->tree, cp->binding, TRUE); list = append(list, list->next); goto restart; } default: panic("eval: bad closure node kind %d", cp->tree->kind); } goto done; } /* the logic here is duplicated in $&whatis */ Ref(char *, name, getstr(list->term)); fn = varlookup2("fn-", name, binding); if (fn != NULL) { funcname = name; list = append(fn, list->next); RefPop(name); goto restart; } if (isabsolute(name)) { char *error = checkexecutable(name); if (error != NULL) fail("$&whatis", "%s: %s", name, error); list = forkexec(name, list, flags & eval_inchild); RefPop(name); goto done; } RefEnd(name); fn = pathsearch(list->term); if (fn != NULL && fn->next == NULL && (cp = getclosure(fn->term)) == NULL) { char *name = getstr(fn->term); list = forkexec(name, list, flags & eval_inchild); goto done; } list = append(fn, list->next); goto restart; done: --evaldepth; if ((flags & eval_exitonfalse) && !istrue(list)) exit(exitstatus(list)); RefEnd2(funcname, binding); RefReturn(list); }