void vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym) { const char *p, *r; struct expr *e1, *e2; enum var_type fmt; char buf[32]; assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC); AN(sym->cfunc); AN(sym->args); SkipToken(tl, ID); SkipToken(tl, '('); p = sym->args; e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(sp\v+", sym->cfunc); while (*p != '\0') { e1 = NULL; fmt = vcc_arg_type(&p); if (fmt == VOID && !strcmp(p, "PRIV_VCL")) { r = strchr(sym->name, '.'); AN(r); e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s", r - sym->name, sym->name); p += strlen(p) + 1; } else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) { bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++); Fh(tl, 0, "struct vmod_priv %s;\n", buf); e1 = vcc_mk_expr(VOID, "&%s", buf); p += strlen(p) + 1; } else if (fmt == ENUM) { ExpectErr(tl, ID); ERRCHK(tl); r = p; do { if (vcc_IdIs(tl->t, p)) break; p += strlen(p) + 1; } while (*p != '\0'); if (*p == '\0') { VSB_printf(tl->sb, "Wrong enum value."); VSB_printf(tl->sb, " Expected one of:\n"); do { VSB_printf(tl->sb, "\t%s\n", r); r += strlen(r) + 1; } while (*r != '\0'); vcc_ErrWhere(tl, tl->t); return; } e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t)); while (*p != '\0') p += strlen(p) + 1; p++; SkipToken(tl, ID); if (*p != '\0') SkipToken(tl, ','); } else if (fmt == HEADER) { const struct var *v; sym = VCC_FindSymbol(tl, tl->t, SYM_NONE); ERRCHK(tl); SkipToken(tl, ID); if (sym == NULL) { VSB_printf(tl->sb, "Symbol not found.\n"); vcc_ErrWhere(tl, tl->t); return; } vcc_AddUses(tl, tl->t, sym->r_methods, "Not available"); if (sym->kind != SYM_VAR) { VSB_printf(tl->sb, "Wrong kind of symbol.\n"); vcc_ErrWhere(tl, tl->t); return; } AN(sym->var); v = sym->var; if (v->http == NULL) { VSB_printf(tl->sb, "Variable not an HTTP header.\n"); vcc_ErrWhere(tl, tl->t); return; } e1 = vcc_mk_expr(VOID, "%s, \"%s\"", v->http, v->hdr); if (*p != '\0') SkipToken(tl, ','); } else { vcc_expr0(tl, &e1, fmt); ERRCHK(tl); if (e1->fmt != fmt) { VSB_printf(tl->sb, "Wrong argument type."); VSB_printf(tl->sb, " Expected %s.", vcc_Type(fmt)); VSB_printf(tl->sb, " Got %s.\n", vcc_Type(e1->fmt)); vcc_ErrWhere2(tl, e1->t1, tl->t); return; } assert(e1->fmt == fmt); if (e1->fmt == STRING_LIST) { e1 = vcc_expr_edit(STRING_LIST, "\v+\n\v1,\nvrt_magic_string_end\v-", e1, NULL); } if (*p != '\0') SkipToken(tl, ','); } e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1); } SkipToken(tl, ')'); e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL); *e = e2; }
static void vcc_func(struct vcc *tl, struct expr **e, const char *cfunc, const char *extra, const char *name, const char *args) { const char *p, *r; struct expr *e1, *e2; struct inifin *ifp; enum var_type fmt; char buf[32]; AN(cfunc); AN(args); AN(name); SkipToken(tl, '('); p = args; if (extra == NULL) extra = ""; e1 = vcc_mk_expr(vcc_arg_type(&p), "%s(ctx%s\v+", cfunc, extra); while (*p != '\0') { e2 = NULL; fmt = vcc_arg_type(&p); if (fmt == VOID && !strcmp(p, "PRIV_VCL")) { r = strchr(name, '.'); AN(r); e2 = vcc_mk_expr(VOID, "&vmod_priv_%.*s", (int) (r - name), name); p += strlen(p) + 1; } else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) { bprintf(buf, "vmod_priv_%u", tl->unique++); ifp = New_IniFin(tl); Fh(tl, 0, "static struct vmod_priv %s;\n", buf); VSB_printf(ifp->fin, "\tvmod_priv_fini(&%s);", buf); e2 = vcc_mk_expr(VOID, "&%s", buf); p += strlen(p) + 1; } else if (fmt == ENUM) { ExpectErr(tl, ID); ERRCHK(tl); r = p; do { if (vcc_IdIs(tl->t, p)) break; p += strlen(p) + 1; } while (*p != '\0'); if (*p == '\0') { VSB_printf(tl->sb, "Wrong enum value."); VSB_printf(tl->sb, " Expected one of:\n"); do { VSB_printf(tl->sb, "\t%s\n", r); r += strlen(r) + 1; } while (*r != '\0'); vcc_ErrWhere(tl, tl->t); return; } e2 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t)); while (*p != '\0') p += strlen(p) + 1; p++; SkipToken(tl, ID); if (*p != '\0') /*lint !e448 */ SkipToken(tl, ','); } else { vcc_expr0(tl, &e2, fmt); ERRCHK(tl); if (e2->fmt != fmt) { VSB_printf(tl->sb, "Wrong argument type."); VSB_printf(tl->sb, " Expected %s.", vcc_Type(fmt)); VSB_printf(tl->sb, " Got %s.\n", vcc_Type(e2->fmt)); vcc_ErrWhere2(tl, e2->t1, tl->t); return; } assert(e2->fmt == fmt); if (e2->fmt == STRING_LIST) { e2 = vcc_expr_edit(STRING_LIST, "\v+\n\v1,\nvrt_magic_string_end\v-", e2, NULL); } if (*p != '\0') SkipToken(tl, ','); } e1 = vcc_expr_edit(e1->fmt, "\v1,\n\v2", e1, e2); } SkipToken(tl, ')'); e1 = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL); *e = e1; }