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; }
/* extractpattern -- Like matchpattern, but returns matches */ static List *extractpattern(Tree *subjectform0, Tree *patternform0, Binding *binding) { List *pattern; StrList *quote = NULL; Ref(List *, result, NULL); Ref(Binding *, bp, binding); Ref(Tree *, patternform, patternform0); Ref(List *, subject, glom(subjectform0, bp, TRUE)); pattern = glom2(patternform, bp, "e); result = (List *) extractmatches(subject, pattern, quote); RefEnd3(subject, patternform, bp); RefReturn(result); }
/* matchpattern -- does the text match a pattern? */ static List *matchpattern(Tree *subjectform0, Tree *patternform0, Binding *binding) { Boolean result; List *pattern; StrList *quote = NULL; Ref(Binding *, bp, binding); Ref(Tree *, patternform, patternform0); Ref(List *, subject, glom(subjectform0, bp, TRUE)); pattern = glom2(patternform, bp, "e); result = listmatch(subject, pattern, quote); RefEnd3(subject, patternform, bp); return result ? true : false; }
/* local -- build, recursively, one layer of local assignment */ static List *local(Tree *defn, Tree *body0, Binding *bindings0, int evalflags) { Ref(List *, result, NULL); Ref(Tree *, body, body0); Ref(Binding *, bindings, bindings0); Ref(Binding *, dynamic, reversebindings(letbindings(defn, NULL, bindings, evalflags))); result = localbind(dynamic, bindings, body, evalflags); RefEnd3(dynamic, bindings, body); RefReturn(result); }
/* localbind -- recursively convert a Bindings list into dynamic binding */ static List *localbind(Binding *dynamic0, Binding *lexical0, Tree *body0, int evalflags) { if (dynamic0 == NULL) return walk(body0, lexical0, evalflags); else { Push p; Ref(List *, result, NULL); Ref(Tree *, body, body0); Ref(Binding *, dynamic, dynamic0); Ref(Binding *, lexical, lexical0); varpush(&p, dynamic->name, dynamic->defn); result = localbind(dynamic->next, lexical, body, evalflags); varpop(&p); RefEnd3(lexical, dynamic, body); RefReturn(result); } }
/* letbindings -- create a new Binding containing let-bound variables */ static Binding *letbindings(Tree *defn0, Binding *outer0, Binding *context0, int evalflags) { Ref(Binding *, binding, outer0); Ref(Binding *, context, context0); 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, context, FALSE)); Ref(List *, values, glom(assign->u[1].p, context, TRUE)); if (vars == NULL) fail("es:let", "null variable name"); for (; vars != NULL; vars = vars->next) { List *value; Ref(char *, name, getstr(vars->term)); if (values == NULL) value = NULL; else if (vars->next == NULL || values->next == NULL) { value = values; values = NULL; } else { value = mklist(values->term, NULL); values = values->next; } binding = mkbinding(name, value, binding); RefEnd(name); } RefEnd3(values, vars, assign); } RefEnd2(defn, context); RefReturn(binding); }
/* 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); }