extern Boolean listmatch(List *subject, List *pattern, StrList *quote) { if (subject == NULL) { if (pattern == NULL) return TRUE; Ref(List *, p, pattern); Ref(StrList *, q, quote); for (; p != NULL; p = p->next, q = q->next) { /* one or more stars match null */ char *pw = getstr(p->term), *qw = q->str; if (*pw != '\0' && qw != QUOTED) { int i; Boolean matched = TRUE; for (i = 0; pw[i] != '\0'; i++) if (pw[i] != '*' || (qw != UNQUOTED && qw[i] != 'r')) { matched = FALSE; break; } if (matched) { RefPop2(q, p); return TRUE; } } } RefEnd2(q, p); return FALSE; } Ref(List *, s, subject); Ref(List *, p, pattern); Ref(StrList *, q, quote); for (; p != NULL; p = p->next, q = q->next) { assert(q != NULL); assert(p->term != NULL); assert(q->str != NULL); Ref(char *, pw, getstr(p->term)); Ref(char *, qw, q->str); Ref(List *, t, s); for (; t != NULL; t = t->next) { char *tw = getstr(t->term); if (match(tw, pw, qw)) { RefPop3(t, qw, pw); RefPop3(q, p, s); return TRUE; } } RefEnd3(t, qw, pw); } RefEnd3(q, p, s); return FALSE; }
/* 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); }