double fun_ri (double x, void *params) { struct fun_root_params *p = (struct fun_root_params *) params; double md = p->md; double mb = p->mb; double c = p->c; double d = p->d; double rb0 = p->rb0; double nsersic = p->nsersic; double qb_obs = p->qb_obs; double lim_mb = p->lim_mb; double rf = p->rf; double xc = x*c; gsl_function F; F.function = &M_b; struct dens3_params pm; pm.nsersic = nsersic; F.params = ± if(qb_obs < 0.99) {return rf*((md*M_d(rf/d) + mb*M_b(rf/rb0, (void*) &pm)/lim_mb)\ *Fh(c) / Fh(xc) + 1.0 - md - mb) - x;} else {return rf*((md*M_d(rf/d) + mb*M_bsph(rf/rb0, (void*) &pm)/lim_mb)\ *Fh(c) / Fh(xc) + 1.0 - md - mb) - x;} }
static void vcc_suckaddr(struct vcc *tl, const char *host, const struct suckaddr *vsa, const char **ip, const char **ip_ascii, const char **p_ascii) { char a[VTCP_ADDRBUFSIZE]; char p[VTCP_PORTBUFSIZE]; const int sz = sizeof(unsigned long long); const unsigned n = (vsa_suckaddr_len + sz - 1) / sz; unsigned long long b[n]; int len; char *q; VTCP_name(vsa, a, sizeof a, p, sizeof p); Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, a); if (ip_ascii != NULL) *ip_ascii = TlDup(tl, a); if (p_ascii != NULL && *p_ascii == NULL) *p_ascii = TlDup(tl, p); Fh(tl, 0, "static const unsigned long long"); Fh(tl, 0, " suckaddr_%u[%d] = {\n", tl->unique, n); memcpy(b, vsa, vsa_suckaddr_len); for (len = 0; len < n; len++) Fh(tl, 0, "%s 0x%0*llxULL", len ? ",\n" : "", sz * 2, b[len]); Fh(tl, 0, "\n};\n"); q = TlAlloc(tl, 40); AN(q); assert(snprintf(q, 40, "(const void*)suckaddr_%u", tl->unique) < 40); *ip = q; tl->unique++; }
const char * vcc_regexp(struct vcc *tl) { char buf[BUFSIZ], *p; vre_t *t; const char *error; int erroroffset; struct inifin *ifp; Expect(tl, CSTR); if (tl->err) return (NULL); t = VRE_compile(tl->t->dec, 0, &error, &erroroffset); if (t == NULL) { VSB_printf(tl->sb, "Regexp compilation error:\n\n%s\n\n", error); vcc_ErrWhere(tl, tl->t); return (NULL); } VRE_free(&t); bprintf(buf, "VGC_re_%u", tl->unique++); p = TlAlloc(tl, strlen(buf) + 1); strcpy(p, buf); Fh(tl, 0, "static void *%s;\n", buf); ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\tVRT_re_init(&%s, ",buf); EncToken(ifp->ini, tl->t); VSB_printf(ifp->ini, ");"); VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf); vcc_NextToken(tl); return (p); }
static int emit_sockaddr(struct vcc *tl, void *sa, unsigned sal) { unsigned len; uint8_t *u; AN(sa); AN(sal); assert(sal < 256); Fh(tl, 0, "\nstatic const unsigned char sockaddr_%u[%d] = {\n", tl->unique, sal + 1); Fh(tl, 0, " %3u, /* Length */\n", sal); u = sa; for (len = 0; len <sal; len++) { if ((len % 8) == 0) Fh(tl, 0, " "); Fh(tl, 0, " %3u", u[len]); if (len + 1 < sal) Fh(tl, 0, ","); if ((len % 8) == 7) Fh(tl, 0, "\n"); } Fh(tl, 0, "\n};\n"); return (tl->unique++); }
void vcc_Backend_Init(struct vcc *tl) { struct inifin *ifp; Fh(tl, 0, "\nstatic struct vsmw_cluster *vsc_cluster;\n"); ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\tvsc_cluster = VRT_VSM_Cluster_New(ctx,\n" "\t ndirector * VRT_backend_vsm_need(ctx));\n"); VSB_printf(ifp->ini, "\tif (vsc_cluster == 0)\n\t\treturn(1);"); VSB_printf(ifp->fin, "\t\tVRT_VSM_Cluster_Destroy(ctx, &vsc_cluster);"); }
static void vcc_Function(struct vcc *tl) { int m, i; vcc_NextToken(tl); ExpectErr(tl, ID); m = IsMethod(tl->t); if (m != -1) { assert(m < VCL_MET_MAX); tl->fb = tl->fm[m]; if (tl->mprocs[m] == NULL) { (void)vcc_AddDef(tl, tl->t, SYM_SUB); vcc_AddRef(tl, tl->t, SYM_SUB); tl->mprocs[m] = vcc_AddProc(tl, tl->t); } tl->curproc = tl->mprocs[m]; Fb(tl, 1, " /* ... from "); vcc_Coord(tl, tl->fb, NULL); Fb(tl, 0, " */\n"); } else { tl->fb = tl->fc; i = vcc_AddDef(tl, tl->t, SYM_SUB); if (i > 1) { VSB_printf(tl->sb, "Function %.*s redefined\n", PF(tl->t)); vcc_ErrWhere(tl, tl->t); return; } tl->curproc = vcc_AddProc(tl, tl->t); Fh(tl, 0, "static int VGC_function_%.*s (struct sess *sp);\n", PF(tl->t)); Fc(tl, 1, "\nstatic int\n"); Fc(tl, 1, "VGC_function_%.*s (struct sess *sp)\n", PF(tl->t)); } vcc_NextToken(tl); tl->indent += INDENT; Fb(tl, 1, "{\n"); L(tl, vcc_Compound(tl)); if (m == -1) { /* * non-method subroutines must have an explicit non-action * return in case they just fall through the bottom. */ Fb(tl, 1, " return(0);\n"); } Fb(tl, 1, "}\n"); tl->indent -= INDENT; tl->fb = NULL; tl->curproc = NULL; }
static void parse_return_vcl(struct vcc *tl) { struct symbol *sym; struct inifin *p; char buf[1024]; ExpectErr(tl, '('); vcc_NextToken(tl); ExpectErr(tl, ID); sym = VCC_SymbolTok(tl, NULL, tl->t, SYM_VCL, 0); ERRCHK(tl); if (sym == NULL) { VSB_printf(tl->sb, "Not a VCL label:\n"); vcc_ErrWhere(tl, tl->t); return; } if (sym->eval_priv == NULL) { VSB_printf(tl->fi, "%s VCL %.*s */\n", VCC_INFO_PREFIX, PF(tl->t)); bprintf(buf, "vgc_vcl_%u", tl->unique++); sym->eval_priv = strdup(buf); AN(sym->eval_priv); Fh(tl, 0, "static VCL_VCL %s;", buf); Fh(tl, 0, "\t/* VCL %.*s */\n", PF(tl->t)); p = New_IniFin(tl); AN(p); VSB_printf(p->ini, "\t%s = VRT_vcl_lookup(\"%.*s\");", buf, PF(tl->t)); } Fb(tl, 1, "VRT_vcl_select(ctx, %s);\t/* %.*s */\n", (const char*)sym->eval_priv, PF(tl->t)); vcc_NextToken(tl); ExpectErr(tl, ')'); vcc_NextToken(tl); }
void fun_ri_fdf (double x, void *params, double *y, double *dy) { struct fun_root_params *p = (struct fun_root_params *) params; double md = p->md; double mb = p->mb; double c = p->c; double d = p->d; double rb0 = p->rb0; double nsersic = p->nsersic; double qb_obs = p->qb_obs; double lim_mb = p->lim_mb; double rf = p->rf; double xc = x*c; gsl_function F; F.function = &M_b; struct dens3_params pm; pm.nsersic = nsersic; F.params = ± if(qb_obs < 0.99) {*y = rf*((md*M_d(rf/d) + mb*M_b(rf/rb0, (void*) &pm)/lim_mb)\ *Fh(c) / Fh(xc) + 1.0 - md) - x; *dy = - rf*(md*M_d(rf/d) + mb*M_b(rf/rb0, (void*) &pm)/lim_mb)\ *Fh(c)*c*Fhdf(xc) / Fh(xc) / Fh(xc) - 1.0;} else {*y = rf*((md*M_d(rf/d) + mb*M_bsph(rf/rb0, (void*) &pm)/lim_mb)\ *Fh(c) / Fh(xc) + 1.0 - md) - x; *dy = - rf*(md*M_d(rf/d) + mb*M_bsph(rf/rb0, (void*) &pm)/lim_mb)\ *Fh(c)*c*Fhdf(xc) / Fh(xc) / Fh(xc) - 1.0;} }
void vcc_ParseBackend(struct vcc *tl) { struct token *t_first, *t_be; struct symbol *sym; const char *dn; tl->ndirector++; t_first = tl->t; SkipToken(tl, ID); /* ID: backend */ vcc_ExpectVid(tl, "backend"); /* ID: name */ ERRCHK(tl); t_be = tl->t; if (vcc_IdIs(tl->t, "default")) { if (tl->first_director != NULL) { tl->first_director->noref = 0; tl->first_director = NULL; tl->default_director = NULL; } if (tl->default_director != NULL) { VSB_printf(tl->sb, "Only one default director possible.\n"); vcc_ErrWhere(tl, t_first); return; } vcc_NextToken(tl); dn = "vgc_backend_default"; tl->default_director = dn; } else { sym = VCC_HandleSymbol(tl, BACKEND, "vgc_backend"); ERRCHK(tl); dn = sym->rname; if (tl->default_director == NULL) { tl->first_director = sym; tl->default_director = dn; sym->noref = 1; } } Fh(tl, 0, "\nstatic VCL_BACKEND %s;\n", dn); vcc_ParseHostDef(tl, t_be, dn); if (tl->err) { VSB_printf(tl->sb, "\nIn %.*s specification starting at:\n", PF(t_first)); vcc_ErrWhere(tl, t_first); return; } }
void vcc_ParseBackend(struct vcc *tl) { struct token *t_first, *t_be; struct symbol *sym; char vgcname[MAX_BACKEND_NAME + 20]; t_first = tl->t; vcc_NextToken(tl); /* ID: backend */ vcc_ExpectCid(tl); /* ID: name */ ERRCHK(tl); if (tl->t->e - tl->t->b > MAX_BACKEND_NAME) { VSB_printf(tl->sb, "Name of %.*s too long (max %d, is %zu):\n", PF(t_first), MAX_BACKEND_NAME, (size_t)(tl->t->e - tl->t->b)); vcc_ErrWhere(tl, tl->t); return; } t_be = tl->t; vcc_NextToken(tl); sprintf(vgcname, "vgc_backend_%.*s", PF(t_be)); Fh(tl, 0, "\nstatic struct director *%s;\n", vgcname); sym = VCC_HandleSymbol(tl, t_be, BACKEND, "%s", vgcname); ERRCHK(tl); vcc_ParseHostDef(tl, t_be, vgcname); ERRCHK(tl); if (tl->err) { VSB_printf(tl->sb, "\nIn %.*s specification starting at:\n", PF(t_first)); vcc_ErrWhere(tl, t_first); return; } if (tl->default_director == NULL || vcc_IdIs(t_be, "default")) { tl->default_director = sym->rname; tl->t_default_director = t_be; } }
void vcc_ParseProbe(struct vcc *tl) { struct token *t_probe; int i; vcc_NextToken(tl); /* ID: probe */ vcc_ExpectCid(tl); /* ID: name */ ERRCHK(tl); t_probe = tl->t; vcc_NextToken(tl); i = vcc_AddDef(tl, t_probe, SYM_PROBE); if (i > 1) { VSB_printf(tl->sb, "Probe %.*s redefined\n", PF(t_probe)); vcc_ErrWhere(tl, t_probe); } Fh(tl, 0, "\n#define vgc_probe_%.*s\tvgc_probe__%d\n", PF(t_probe), tl->nprobe); vcc_ParseProbeSpec(tl); }
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_ParseFunction(struct vcc *tl) { int m, i; vcc_NextToken(tl); vcc_ExpectCid(tl, "function"); ERRCHK(tl); m = IsMethod(tl->t); if (m == -2) { VSB_printf(tl->sb, "VCL sub's named 'vcl*' are reserved names.\n"); vcc_ErrWhere(tl, tl->t); VSB_printf(tl->sb, "Valid vcl_* methods are:\n"); for (i = 1; method_tab[i].name != NULL; i++) VSB_printf(tl->sb, "\t%s\n", method_tab[i].name); return; } else if (m != -1) { assert(m < VCL_MET_MAX); tl->fb = tl->fm[m]; if (tl->mprocs[m] == NULL) { (void)vcc_AddDef(tl, tl->t, SYM_SUB); vcc_AddRef(tl, tl->t, SYM_SUB); tl->mprocs[m] = vcc_AddProc(tl, tl->t); } tl->curproc = tl->mprocs[m]; Fb(tl, 1, " /* ... from "); vcc_Coord(tl, tl->fb, NULL); Fb(tl, 0, " */\n"); } else { tl->fb = tl->fc; i = vcc_AddDef(tl, tl->t, SYM_SUB); if (i > 1) { VSB_printf(tl->sb, "Function '%.*s' redefined\n", PF(tl->t)); vcc_ErrWhere(tl, tl->t); return; } tl->curproc = vcc_AddProc(tl, tl->t); Fh(tl, 0, "int VGC_function_%.*s " "(VRT_CTX);\n", PF(tl->t)); Fc(tl, 1, "\nint __match_proto__(vcl_func_t)\n"); Fc(tl, 1, "VGC_function_%.*s(VRT_CTX)\n", PF(tl->t)); } vcc_NextToken(tl); tl->indent += INDENT; Fb(tl, 1, "{\n"); L(tl, vcc_Compound(tl)); if (m == -1) { /* * non-method subroutines must have an explicit non-action * return in case they just fall through the bottom. */ Fb(tl, 1, " return(0);\n"); } Fb(tl, 1, "}\n"); tl->indent -= INDENT; tl->fb = NULL; tl->curproc = NULL; }
void vcc_ParseImport(struct vcc *tl) { void *hdl; char fn[1024], *fnp, *fnpx; char buf[256]; struct token *mod, *t1; struct inifin *ifp; const char * const *spec; struct symbol *sym; struct symbol *msym; const struct symbol *osym; const char *p; // int *modlen; const struct vmod_data *vmd; t1 = tl->t; SkipToken(tl, ID); /* "import" */ ExpectErr(tl, ID); mod = tl->t; vcc_NextToken(tl); osym = VCC_SymbolTok(tl, NULL, mod, SYM_NONE, 0); if (osym != NULL && osym->kind != SYM_VMOD) { VSB_printf(tl->sb, "Module %.*s conflicts with other symbol.\n", PF(mod)); vcc_ErrWhere2(tl, t1, tl->t); return; } if (osym != NULL) { VSB_printf(tl->sb, "Module %.*s already imported.\n", PF(mod)); vcc_ErrWhere2(tl, t1, tl->t); VSB_printf(tl->sb, "Previous import was here:\n"); vcc_ErrWhere2(tl, osym->def_b, osym->def_e); return; } bprintf(fn, "%.*s", PF(mod)); msym = VCC_Symbol(tl, NULL, fn, NULL, SYM_VMOD, 1); ERRCHK(tl); AN(msym); msym->def_b = t1; msym->def_e = tl->t; if (tl->t->tok == ID) { if (!vcc_IdIs(tl->t, "from")) { VSB_printf(tl->sb, "Expected 'from path ...'\n"); vcc_ErrWhere(tl, tl->t); return; } vcc_NextToken(tl); if (!tl->unsafe_path && strchr(tl->t->dec, '/')) { VSB_printf(tl->sb, "'import ... from path ...' is unsafe.\nAt:"); vcc_ErrToken(tl, tl->t); vcc_ErrWhere(tl, tl->t); return; } ExpectErr(tl, CSTR); p = strrchr(tl->t->dec, '/'); if (p != NULL && p[1] == '\0') bprintf(fn, "%slibvmod_%.*s.so", tl->t->dec, PF(mod)); else bprintf(fn, "%s", tl->t->dec); vcc_NextToken(tl); } else { bprintf(fn, "libvmod_%.*s.so", PF(mod)); } SkipToken(tl, ';'); if (VFIL_searchpath(tl->vmod_path, vcc_path_dlopen, &hdl, fn, &fnpx)) { VSB_printf(tl->sb, "Could not load VMOD %.*s\n", PF(mod)); VSB_printf(tl->sb, "\tFile name: %s\n", fnpx != NULL ? fnpx : fn); VSB_printf(tl->sb, "\tdlerror: %s\n", dlerror()); vcc_ErrWhere(tl, mod); free(fnpx); return; } AN(fnpx); fnp = TlDup(tl, fnpx); free(fnpx); bprintf(buf, "Vmod_%.*s_Data", PF(mod)); vmd = dlsym(hdl, buf); if (vmd == NULL) { VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(mod)); VSB_printf(tl->sb, "\tFile name: %s\n", fnp); VSB_printf(tl->sb, "\t(no Vmod_Data symbol)\n"); vcc_ErrWhere(tl, mod); return; } if (strcmp(VCS_Branch, "master") == 0 && strcmp(vmd->abi, VMOD_ABI_Version) != 0) { VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod)); VSB_printf(tl->sb, "\tFile name: %s\n", fnp); VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n", VMOD_ABI_Version, vmd->abi); vcc_ErrWhere(tl, mod); return; } if (vmd->vrt_major != VRT_MAJOR_VERSION || vmd->vrt_minor > VRT_MINOR_VERSION) { VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod)); VSB_printf(tl->sb, "\tFile name: %s\n", fnp); VSB_printf(tl->sb, "\tVMOD version %u.%u\n", vmd->vrt_major, vmd->vrt_minor); VSB_printf(tl->sb, "\tvarnishd version %u.%u\n", VRT_MAJOR_VERSION, VRT_MINOR_VERSION); vcc_ErrWhere(tl, mod); return; } if (vmd->name == NULL || vmd->func == NULL || vmd->func_len <= 0 || vmd->proto == NULL || vmd->abi == NULL) { VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(mod)); VSB_printf(tl->sb, "\tFile name: %s\n", fnp); VSB_printf(tl->sb, "\tInconsistent metadata\n"); vcc_ErrWhere(tl, mod); return; } if (!vcc_IdIs(mod, vmd->name)) { VSB_printf(tl->sb, "Wrong VMOD file %.*s\n", PF(mod)); VSB_printf(tl->sb, "\tFile name: %s\n", fnp); VSB_printf(tl->sb, "\tContains vmod \"%s\"\n", vmd->name); vcc_ErrWhere(tl, mod); return; } ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod)); VSB_printf(ifp->ini, "\t &Vmod_%.*s_Func,\n", PF(mod)); VSB_printf(ifp->ini, "\t sizeof(Vmod_%.*s_Func),\n", PF(mod)); VSB_printf(ifp->ini, "\t \"%.*s\",\n", PF(mod)); VSB_printf(ifp->ini, "\t "); VSB_quote(ifp->ini, fnp, -1, VSB_QUOTE_CSTR); VSB_printf(ifp->ini, ",\n"); AN(vmd); AN(vmd->file_id); VSB_printf(ifp->ini, "\t \"%s\",\n", vmd->file_id); VSB_printf(ifp->ini, "\t ctx))\n"); VSB_printf(ifp->ini, "\t\treturn(1);"); /* XXX: zero the function pointer structure ?*/ VSB_printf(ifp->fin, "\t\tVRT_priv_fini(&vmod_priv_%.*s);", PF(mod)); VSB_printf(ifp->fin, "\n\t\tVRT_Vmod_Fini(&VGC_vmod_%.*s);", PF(mod)); ifp = NULL; spec = vmd->spec; for (; *spec != NULL; spec++) { p = *spec; if (!strcmp(p, "$OBJ")) { p += strlen(p) + 1; sym = VCC_Symbol(tl, NULL, p, NULL, SYM_OBJECT, 1); XXXAN(sym); sym->extra = p; sym->vmod = msym->name; } else if (!strcmp(p, "$EVENT")) { p += strlen(p) + 1; if (ifp == NULL) ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\tif (%s(ctx, &vmod_priv_%.*s, VCL_EVENT_LOAD))\n" "\t\treturn(1);", p, PF(mod)); VSB_printf(ifp->fin, "\t\t(void)%s(ctx, &vmod_priv_%.*s,\n" "\t\t VCL_EVENT_DISCARD);\n", p, PF(mod)); VSB_printf(ifp->event, "\t%s(ctx, &vmod_priv_%.*s, ev)", p, PF(mod)); } else if (!strcmp(p, "$FUNC")) { p += strlen(p) + 1; sym = VCC_Symbol(tl, NULL, p, NULL, SYM_FUNC, 1); ERRCHK(tl); AN(sym); sym->vmod = msym->name; sym->eval = vcc_Eval_SymFunc; p += strlen(p) + 1; sym->eval_priv = p; sym->fmt = VCC_Type(p); AN(sym->fmt); } else { VSB_printf(tl->sb, "Internal spec error (%s)\n", p); vcc_ErrWhere(tl, mod); return; } } Fh(tl, 0, "\n/* --- BEGIN VMOD %.*s --- */\n\n", PF(mod)); Fh(tl, 0, "static struct vmod *VGC_vmod_%.*s;\n", PF(mod)); Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod)); Fh(tl, 0, "\n%s\n", vmd->proto); Fh(tl, 0, "\n/* --- END VMOD %.*s --- */\n\n", PF(mod)); }
void vcc_ParseNew(struct vcc *tl) { struct symbol *sy1, *sy2, *sy3; struct inifin *ifp; const char *p, *s_obj; char buf1[128]; char buf2[128]; vcc_NextToken(tl); ExpectErr(tl, ID); vcc_ExpectCid(tl, "VCL object"); ERRCHK(tl); sy1 = VCC_HandleSymbol(tl, tl->t, INSTANCE, "XXX"); ERRCHK(tl); /* We allow implicit use of VMOD objects: Pretend it's ref'ed */ sy1->nref++; vcc_NextToken(tl); ExpectErr(tl, '='); vcc_NextToken(tl); ExpectErr(tl, ID); sy2 = VCC_SymbolTok(tl, NULL, tl->t, SYM_OBJECT, 0); if (sy2 == NULL) { VSB_printf(tl->sb, "Symbol not found: "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } vcc_NextToken(tl); p = sy2->extra; s_obj = p; p += strlen(p) + 1; Fh(tl, 0, "static %s *vo_%s;\n\n", p, sy1->name); p += strlen(p) + 1; bprintf(buf1, ", &vo_%s, \"%s\"", sy1->name, sy1->name); vcc_Eval_Func(tl, p, buf1, sy2); ExpectErr(tl, ';'); while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0') p++; p += 3; ifp = New_IniFin(tl); p += strlen(p) + 1; VSB_printf(ifp->fin, "\t\t%s(&vo_%s);", p, sy1->name); while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0') p++; p += 3; /* Instantiate symbols for the methods */ bprintf(buf1, ", vo_%s", sy1->name); while (*p != '\0') { p += strlen(s_obj); bprintf(buf2, "%s%s", sy1->name, p); sy3 = VCC_Symbol(tl, NULL, buf2, NULL, SYM_FUNC, 1); AN(sy3); sy3->eval = vcc_Eval_SymFunc; p += strlen(p) + 1; sy3->eval_priv = p; sy3->fmt = VCC_Type(p); sy3->extra = TlDup(tl, buf1); while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0') p++; p += 3; } sy1->def_e = tl->t; }
static void parse_new(struct vcc *tl) { struct symbol *sy1, *sy2, *sy3; const char *p, *s_obj, *s_init, *s_struct, *s_fini; char buf1[128]; char buf2[128]; vcc_NextToken(tl); ExpectErr(tl, ID); sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE); XXXAZ(sy1); sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE); // XXX: NONE ? XXXAN(sy1); vcc_NextToken(tl); ExpectErr(tl, '='); vcc_NextToken(tl); ExpectErr(tl, ID); sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT); XXXAN(sy2); /*lint -save -e448 */ /* Split the first three args */ p = sy2->args; s_obj = p; p += strlen(p) + 1; s_init = p; while (p[0] != '\0' || p[1] != '\0') p++; p += 2; s_struct = p; p += strlen(p) + 1; s_fini = p + strlen(p) + 1; while (p[0] != '\0' || p[1] != '\0') p++; p += 2; Fh(tl, 0, "static %s *%s;\n\n", s_struct, sy1->name); vcc_NextToken(tl); bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name); vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1); Fd(tl, 0, "\t%s(&%s);\n", s_fini, sy1->name); ExpectErr(tl, ';'); bprintf(buf1, ", %s", sy1->name); /* Split the methods from the args */ while (*p != '\0') { p += strlen(s_obj); bprintf(buf2, "%s%s", sy1->name, p); sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC); AN(sy3); sy3->eval = vcc_Eval_SymFunc; p += strlen(p) + 1; sy3->cfunc = p; p += strlen(p) + 1; /* Functions which return VOID are procedures */ if (!memcmp(p, "VOID\0", 5)) sy3->kind = SYM_PROC; sy3->args = p; sy3->extra = TlDup(tl, buf1); while (p[0] != '\0' || p[1] != '\0') p++; p += 2; } /*lint -restore */ }
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; }
static void parse_new(struct vcc *tl) { struct symbol *sy1, *sy2, *sy3; struct inifin *ifp; const char *p, *s_obj, *s_init, *s_struct, *s_fini; char buf1[128]; char buf2[128]; vcc_NextToken(tl); ExpectErr(tl, ID); if (!vcc_isCid(tl->t)) { VSB_printf(tl->sb, "Names of VCL objects cannot contain '-'\n"); vcc_ErrWhere(tl, tl->t); return; } sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE); if (sy1 != NULL) { VSB_printf(tl->sb, "Object name '%.*s' already used.\n", PF(tl->t)); VSB_printf(tl->sb, "First usage:\n"); AN(sy1->def_b); if (sy1->def_e != NULL) vcc_ErrWhere2(tl, sy1->def_b, sy1->def_e); else vcc_ErrWhere(tl, sy1->def_b); VSB_printf(tl->sb, "Redefinition:\n"); vcc_ErrWhere(tl, tl->t); return; } sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE); // XXX: NONE ? XXXAN(sy1); sy1->def_b = tl->t; vcc_NextToken(tl); ExpectErr(tl, '='); vcc_NextToken(tl); ExpectErr(tl, ID); sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT); if (sy2 == NULL) { VSB_printf(tl->sb, "Symbol not found: "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } XXXAN(sy2); /*lint -save -e448 */ /* Split the first three args */ p = sy2->args; s_obj = p; p += strlen(p) + 1; s_init = p; while (p[0] != '\0' || p[1] != '\0') p++; p += 2; s_struct = p; p += strlen(p) + 1; s_fini = p + strlen(p) + 1; while (p[0] != '\0' || p[1] != '\0') p++; p += 2; Fh(tl, 0, "static %s *vo_%s;\n\n", s_struct, sy1->name); vcc_NextToken(tl); bprintf(buf1, ", &vo_%s, \"%s\"", sy1->name, sy1->name); vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1); ifp = New_IniFin(tl); VSB_printf(ifp->fin, "\t%s(&vo_%s);", s_fini, sy1->name); ExpectErr(tl, ';'); bprintf(buf1, ", vo_%s", sy1->name); /* Split the methods from the args */ while (*p != '\0') { p += strlen(s_obj); bprintf(buf2, "%s%s", sy1->name, p); sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC); AN(sy3); sy3->eval = vcc_Eval_SymFunc; p += strlen(p) + 1; sy3->cfunc = p; p += strlen(p) + 1; /* Functions which return VOID are procedures */ if (!memcmp(p, "VOID\0", 5)) sy3->kind = SYM_PROC; sy3->args = p; sy3->extra = TlDup(tl, buf1); while (p[0] != '\0' || p[1] != '\0') { if (!memcmp(p, "ENUM\0", 5)) { /* XXX: Special case for ENUM that has it's own \0\0 end marker. Not exactly elegant, we should consider alternatives here. Maybe runlength encode the entire block? */ p += strlen(p) + 1; while (p[0] != '\0' || p[1] != '\0') p++; } p++; } p += 2; } sy1->def_e = tl->t; /*lint -restore */ }
void vcc_ParseImport(struct vcc *tl) { void *hdl; char fn[1024]; char buf[256]; struct token *mod, *t1; const char *modname; const char *proto; const char *abi; const char **spec; struct symbol *sym; const struct symbol *osym; const char *p; // int *modlen; t1 = tl->t; SkipToken(tl, ID); /* "import" */ ExpectErr(tl, ID); mod = tl->t; vcc_NextToken(tl); osym = VCC_FindSymbol(tl, mod, SYM_NONE); if (osym != NULL && osym->kind != SYM_VMOD) { VSB_printf(tl->sb, "Module %.*s conflics with other symbol.\n", PF(mod)); vcc_ErrWhere2(tl, t1, tl->t); return; } if (osym != NULL) { VSB_printf(tl->sb, "Module %.*s already imported.\n", PF(mod)); vcc_ErrWhere2(tl, t1, tl->t); VSB_printf(tl->sb, "Previous import was here:\n"); vcc_ErrWhere2(tl, osym->def_b, osym->def_e); return; } bprintf(fn, "%.*s", PF(mod)); sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD); ERRCHK(tl); AN(sym); sym->def_b = t1; sym->def_e = tl->t; if (tl->t->tok == ID) { if (!tl->unsafe_path) { VSB_printf(tl->sb, "'import ... from path...'" " not allowed.\nAt:"); vcc_ErrToken(tl, tl->t); vcc_ErrWhere(tl, tl->t); return; } if (!vcc_IdIs(tl->t, "from")) { VSB_printf(tl->sb, "Expected 'from path...'\n"); vcc_ErrWhere(tl, tl->t); return; } vcc_NextToken(tl); ExpectErr(tl, CSTR); bprintf(fn, "%s", tl->t->dec); vcc_NextToken(tl); } else { bprintf(fn, "%s/libvmod_%.*s.so", tl->vmod_dir, PF(mod)); } Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod)); Fi(tl, 0, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod)); Fi(tl, 0, "\t &Vmod_%.*s_Func,\n", PF(mod)); Fi(tl, 0, "\t sizeof(Vmod_%.*s_Func),\n", PF(mod)); Fi(tl, 0, "\t \"%.*s\",\n", PF(mod)); Fi(tl, 0, "\t "); EncString(tl->fi, fn, NULL, 0); Fi(tl, 0, ",\n\t "); Fi(tl, 0, "cli))\n"); Fi(tl, 0, "\t\treturn(1);\n"); SkipToken(tl, ';'); hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL); if (hdl == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, dlerror()); vcc_ErrWhere(tl, mod); return; } bprintf(buf, "Vmod_%.*s_Name", PF(mod)); modname = dlsym(hdl, buf); if (modname == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, "Symbol Vmod_Name not found"); vcc_ErrWhere(tl, mod); return; } if (!vcc_IdIs(mod, modname)) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", PF(mod), fn); VSB_printf(tl->sb, "\tModule has wrong name: <%s>\n", modname); vcc_ErrWhere(tl, mod); return; } bprintf(buf, "Vmod_%.*s_ABI", PF(mod)); abi = dlsym(hdl, buf); if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", PF(mod), fn); VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n", VMOD_ABI_Version, abi); vcc_ErrWhere(tl, mod); return; } bprintf(buf, "Vmod_%.*s_Proto", PF(mod)); proto = dlsym(hdl, buf); if (proto == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, "Symbol Vmod_Proto not found"); vcc_ErrWhere(tl, mod); return; } bprintf(buf, "Vmod_%.*s_Spec", PF(mod)); spec = dlsym(hdl, buf); if (spec == NULL) { VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", PF(mod), fn, "Symbol Vmod_Spec not found"); vcc_ErrWhere(tl, mod); return; } Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod)); for (; *spec != NULL; spec++) { p = *spec; if (!strcmp(p, "OBJ")) { p += strlen(p) + 1; sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT); XXXAN(sym); sym->args = p; } else if (!strcmp(p, "INIT")) { p += strlen(p) + 1; Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n", p, PF(mod)); } else { sym = VCC_AddSymbolStr(tl, p, SYM_FUNC); ERRCHK(tl); AN(sym); sym->eval = vcc_Eval_SymFunc; p += strlen(p) + 1; sym->cfunc = p; p += strlen(p) + 1; sym->args = p; /* Functions which return VOID are procedures */ if (!memcmp(p, "VOID\0", 5)) sym->kind = SYM_PROC; } } Fh(tl, 0, "\n%s\n", proto); /* XXX: zero the function pointer structure ?*/ Ff(tl, 0, "\tvmod_priv_fini(&vmod_priv_%.*s);\n", PF(mod)); Ff(tl, 0, "\tVRT_Vmod_Fini(&VGC_vmod_%.*s);\n", PF(mod)); }
static void vcc_ParseHostDef(struct vcc *tl, const struct token *t_be, const char *vgcname) { struct token *t_field; struct token *t_val; struct token *t_host = NULL; struct token *t_port = NULL; struct token *t_hosthdr = NULL; struct fld_spec *fs; struct inifin *ifp; struct vsb *vsb; char *p; unsigned u; double t; fs = vcc_FldSpec(tl, "!host", "?port", "?host_header", "?connect_timeout", "?first_byte_timeout", "?between_bytes_timeout", "?probe", "?max_connections", "?proxy_header", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); tl->fb = vsb; Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", vgcname); Fb(tl, 0, "\t.magic = VRT_BACKEND_MAGIC,\n"); Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be)); Fb(tl, 0, "\",\n"); /* Check for old syntax */ if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) { VSB_printf(tl->sb, "NB: Backend Syntax has changed:\n" "Remove \"set\" and \"backend\" in front" " of backend fields.\n" ); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "host")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_host = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "port")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_port = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "host_header")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_hosthdr = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "connect_timeout")) { Fb(tl, 0, "\t.connect_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "first_byte_timeout")) { Fb(tl, 0, "\t.first_byte_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { Fb(tl, 0, "\t.between_bytes_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); ERRCHK(tl); SkipToken(tl, ';'); Fb(tl, 0, "\t.max_connections = %u,\n", u); } else if (vcc_IdIs(t_field, "proxy_header")) { t_val = tl->t; u = vcc_UintVal(tl); ERRCHK(tl); if (u != 1 && u != 2) { VSB_printf(tl->sb, ".proxy_header must be 1 or 2\n"); vcc_ErrWhere(tl, t_val); return; } SkipToken(tl, ';'); Fb(tl, 0, "\t.proxy_header = %u,\n", u); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') { vcc_ParseProbeSpec(tl, NULL, &p); Fb(tl, 0, "\t.probe = &%s,\n", p); ERRCHK(tl); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) { if (VCC_FindSymbol(tl, tl->t, SYM_PROBE) == NULL) { VSB_printf(tl->sb, "Probe %.*s not found\n", PF(tl->t)); vcc_ErrWhere(tl, tl->t); return; } Fb(tl, 0, "\t.probe = &vgc_probe_%.*s,\n", PF(tl->t)); vcc_AddRef(tl, tl->t, SYM_PROBE); vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe")) { VSB_printf(tl->sb, "Expected '{' or name of probe, got "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); return; } else { ErrInternal(tl); return; } } vcc_FieldsOk(tl, fs); ERRCHK(tl); /* Check that the hostname makes sense */ assert(t_host != NULL); Emit_Sockaddr(tl, t_host, t_port); ERRCHK(tl); ExpectErr(tl, '}'); /* We have parsed it all, emit the ident string */ /* Emit the hosthdr field, fall back to .host if not specified */ Fb(tl, 0, "\t.hosthdr = "); if (t_hosthdr != NULL) EncToken(tl->fb, t_hosthdr); else EncToken(tl->fb, t_host); Fb(tl, 0, ",\n"); /* Close the struct */ Fb(tl, 0, "};\n"); vcc_NextToken(tl); tl->fb = NULL; AZ(VSB_finish(vsb)); Fh(tl, 0, "%s", VSB_data(vsb)); VSB_destroy(&vsb); ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\t%s =\n\t VRT_new_backend(ctx, &vgc_dir_priv_%s);", vgcname, vgcname); }
static void vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) { struct token *t_field; struct token *t_host = NULL; struct token *t_port = NULL; struct token *t_hosthdr = NULL; unsigned saint = UINT_MAX; struct fld_spec *fs; struct vsb *vsb; unsigned u; double t; Fh(tl, 1, "\n#define VGC_backend_%s %d\n", vgcname, tl->ndirector); fs = vcc_FldSpec(tl, "!host", "?port", "?host_header", "?connect_timeout", "?first_byte_timeout", "?between_bytes_timeout", "?probe", "?max_connections", "?saintmode_threshold", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); tl->fb = vsb; Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", vgcname); Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(tl->t_dir)); if (serial >= 0) Fb(tl, 0, "[%d]", serial); Fb(tl, 0, "\",\n"); /* Check for old syntax */ if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) { VSB_printf(tl->sb, "NB: Backend Syntax has changed:\n" "Remove \"set\" and \"backend\" in front" " of backend fields.\n" ); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "host")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_host = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "port")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_port = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "host_header")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_hosthdr = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "connect_timeout")) { Fb(tl, 0, "\t.connect_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "first_byte_timeout")) { Fb(tl, 0, "\t.first_byte_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { Fb(tl, 0, "\t.between_bytes_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); ERRCHK(tl); SkipToken(tl, ';'); Fb(tl, 0, "\t.max_connections = %u,\n", u); } else if (vcc_IdIs(t_field, "saintmode_threshold")) { u = vcc_UintVal(tl); /* UINT_MAX == magic number to mark as unset, so * not allowed here. */ if (u == UINT_MAX) { VSB_printf(tl->sb, "Value outside allowed range: "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); } ERRCHK(tl); saint = u; SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') { Fb(tl, 0, "\t.probe = &vgc_probe__%d,\n", tl->nprobe); vcc_ParseProbeSpec(tl); ERRCHK(tl); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) { Fb(tl, 0, "\t.probe = &vgc_probe_%.*s,\n", PF(tl->t)); vcc_AddRef(tl, tl->t, SYM_PROBE); vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe")) { VSB_printf(tl->sb, "Expected '{' or name of probe."); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); return; } else { ErrInternal(tl); return; } } vcc_FieldsOk(tl, fs); ERRCHK(tl); /* Check that the hostname makes sense */ assert(t_host != NULL); if (t_port != NULL) Emit_Sockaddr(tl, t_host, t_port->dec); else Emit_Sockaddr(tl, t_host, "80"); ERRCHK(tl); ExpectErr(tl, '}'); /* We have parsed it all, emit the ident string */ /* Emit the hosthdr field, fall back to .host if not specified */ Fb(tl, 0, "\t.hosthdr = "); if (t_hosthdr != NULL) EncToken(tl->fb, t_hosthdr); else EncToken(tl->fb, t_host); Fb(tl, 0, ",\n"); Fb(tl, 0, "\t.saintmode_threshold = %d,\n",saint); /* Close the struct */ Fb(tl, 0, "};\n"); vcc_NextToken(tl); tl->fb = NULL; AZ(VSB_finish(vsb)); Fh(tl, 0, "%s", VSB_data(vsb)); VSB_delete(vsb); Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director, \"simple\",\n" "\t VGC_backend_%s, &vgc_dir_priv_%s);\n", vgcname, vgcname); Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(%s));\n", vgcname); tl->ndirector++; }
static void vcc_ParseProbeSpec(struct vcc *tl, const struct symbol *sym, char **name) { struct fld_spec *fs; struct token *t_field; struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL; struct token *t_initial = NULL; struct vsb *vsb; char *retval; unsigned window, threshold, initial, status; double t; fs = vcc_FldSpec(tl, "?url", "?request", "?expected_response", "?timeout", "?interval", "?window", "?threshold", "?initial", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); if (sym != NULL) VSB_cat(vsb, sym->rname); else VSB_printf(vsb, "vgc_probe__%d", tl->nprobe++); AZ(VSB_finish(vsb)); retval = TlDup(tl, VSB_data(vsb)); AN(retval); VSB_destroy(&vsb); if (name != NULL) *name = retval; window = 0; threshold = 0; initial = 0; status = 0; Fh(tl, 0, "static const struct vrt_backend_probe %s[] = {{\n", retval); Fh(tl, 0, "\t.magic = VRT_BACKEND_PROBE_MAGIC,\n"); while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "url")) { vcc_Redef(tl, "Probe request", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); Fh(tl, 0, "\t.url = "); EncToken(tl->fh, tl->t); Fh(tl, 0, ",\n"); vcc_NextToken(tl); } else if (vcc_IdIs(t_field, "request")) { vcc_Redef(tl, "Probe request", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); Fh(tl, 0, "\t.request =\n"); while (tl->t->tok == CSTR) { Fh(tl, 0, "\t\t"); EncToken(tl->fh, tl->t); Fh(tl, 0, " \"\\r\\n\"\n"); vcc_NextToken(tl); } Fh(tl, 0, "\t\t\"\\r\\n\",\n"); } else if (vcc_IdIs(t_field, "timeout")) { Fh(tl, 0, "\t.timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fh(tl, 0, "%g,\n", t); } else if (vcc_IdIs(t_field, "interval")) { Fh(tl, 0, "\t.interval = "); vcc_Duration(tl, &t); ERRCHK(tl); Fh(tl, 0, "%g,\n", t); } else if (vcc_IdIs(t_field, "window")) { t_window = tl->t; window = vcc_UintVal(tl); ERRCHK(tl); } else if (vcc_IdIs(t_field, "initial")) { t_initial = tl->t; initial = vcc_UintVal(tl); ERRCHK(tl); } else if (vcc_IdIs(t_field, "expected_response")) { status = vcc_UintVal(tl); if (status < 100 || status > 999) { VSB_printf(tl->sb, "Must specify .expected_response with " "exactly three digits " "(100 <= x <= 999)\n"); vcc_ErrWhere(tl, tl->t); return; } ERRCHK(tl); } else if (vcc_IdIs(t_field, "threshold")) { t_threshold = tl->t; threshold = vcc_UintVal(tl); ERRCHK(tl); } else { vcc_ErrToken(tl, t_field); vcc_ErrWhere(tl, t_field); ErrInternal(tl); return; } SkipToken(tl, ';'); } if (t_threshold != NULL || t_window != NULL) { if (t_threshold == NULL && t_window != NULL) { VSB_printf(tl->sb, "Must specify .threshold with .window\n"); vcc_ErrWhere(tl, t_window); return; } else if (t_threshold != NULL && t_window == NULL) { if (threshold > 64) { VSB_printf(tl->sb, "Threshold must be 64 or less.\n"); vcc_ErrWhere(tl, t_threshold); return; } window = threshold + 1; } else if (window > 64) { AN(t_window); VSB_printf(tl->sb, "Window must be 64 or less.\n"); vcc_ErrWhere(tl, t_window); return; } if (threshold > window ) { VSB_printf(tl->sb, "Threshold can not be greater than window.\n"); AN(t_threshold); vcc_ErrWhere(tl, t_threshold); AN(t_window); vcc_ErrWhere(tl, t_window); } Fh(tl, 0, "\t.window = %u,\n", window); Fh(tl, 0, "\t.threshold = %u,\n", threshold); } if (t_initial != NULL) Fh(tl, 0, "\t.initial = %u,\n", initial); else Fh(tl, 0, "\t.initial = ~0U,\n"); if (status > 0) Fh(tl, 0, "\t.exp_status = %u,\n", status); Fh(tl, 0, "}};\n"); SkipToken(tl, '}'); }
static void vcc_ParseHostDef(struct vcc *tl, const struct token *t_be, const char *vgcname) { struct token *t_field; struct token *t_val; struct token *t_host = NULL; struct token *t_port = NULL; struct token *t_path = NULL; struct token *t_hosthdr = NULL; struct symbol *pb; struct token *t_did = NULL; struct fld_spec *fs; struct inifin *ifp; struct vsb *vsb; char *p; unsigned u; double t; fs = vcc_FldSpec(tl, "?host", "?port", "?path", "?host_header", "?connect_timeout", "?first_byte_timeout", "?between_bytes_timeout", "?probe", "?max_connections", "?proxy_header", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); tl->fb = vsb; Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", vgcname); Fb(tl, 0, "\t.magic = VRT_BACKEND_MAGIC,\n"); Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be)); Fb(tl, 0, "\",\n"); /* Check for old syntax */ if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) { VSB_printf(tl->sb, "NB: Backend Syntax has changed:\n" "Remove \"set\" and \"backend\" in front" " of backend fields.\n" ); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "host")) { vcc_Redef(tl, "Address", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_host = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "port")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_port = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "path")) { if (tl->syntax < VCL_41) { VSB_printf(tl->sb, "Unix socket backends only supported" " in VCL4.1 and higher.\n"); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } vcc_Redef(tl, "Address", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_path = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "host_header")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_hosthdr = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "connect_timeout")) { Fb(tl, 0, "\t.connect_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "first_byte_timeout")) { Fb(tl, 0, "\t.first_byte_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { Fb(tl, 0, "\t.between_bytes_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); ERRCHK(tl); SkipToken(tl, ';'); Fb(tl, 0, "\t.max_connections = %u,\n", u); } else if (vcc_IdIs(t_field, "proxy_header")) { t_val = tl->t; u = vcc_UintVal(tl); ERRCHK(tl); if (u != 1 && u != 2) { VSB_printf(tl->sb, ".proxy_header must be 1 or 2\n"); vcc_ErrWhere(tl, t_val); return; } SkipToken(tl, ';'); Fb(tl, 0, "\t.proxy_header = %u,\n", u); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') { vcc_ParseProbeSpec(tl, NULL, &p); Fb(tl, 0, "\t.probe = %s,\n", p); ERRCHK(tl); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) { if (vcc_IdIs(tl->t, "default")) { vcc_NextToken(tl); (void)vcc_default_probe(tl); } else { pb = VCC_SymbolGet(tl, SYM_PROBE, "Probe not found", XREF_REF); ERRCHK(tl); AN(pb); Fb(tl, 0, "\t.probe = %s,\n", pb->rname); } SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe")) { VSB_printf(tl->sb, "Expected '{' or name of probe, got "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); return; } else { ErrInternal(tl); return; } } vcc_FieldsOk(tl, fs); ERRCHK(tl); if (t_host == NULL && t_path == NULL) { VSB_printf(tl->sb, "Expected .host or .path.\n"); vcc_ErrWhere(tl, t_be); return; } assert(t_host != NULL || t_path != NULL); if (t_host != NULL) /* Check that the hostname makes sense */ Emit_Sockaddr(tl, t_host, t_port); else /* Check that the path can be a legal UDS */ Emit_UDS_Path(tl, t_path, "Backend path"); ERRCHK(tl); ExpectErr(tl, '}'); /* We have parsed it all, emit the ident string */ /* Emit the hosthdr field, fall back to .host if not specified */ /* If .path is specified, set "0.0.0.0". */ Fb(tl, 0, "\t.hosthdr = "); if (t_hosthdr != NULL) EncToken(tl->fb, t_hosthdr); else if (t_host != NULL) EncToken(tl->fb, t_host); else Fb(tl, 0, "\"0.0.0.0\""); Fb(tl, 0, ",\n"); /* Close the struct */ Fb(tl, 0, "};\n"); vcc_NextToken(tl); tl->fb = NULL; AZ(VSB_finish(vsb)); Fh(tl, 0, "%s", VSB_data(vsb)); VSB_destroy(&vsb); ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\t%s =\n\t VRT_new_backend_clustered(ctx, vsc_cluster,\n" "\t\t&vgc_dir_priv_%s);", vgcname, vgcname); VSB_printf(ifp->fin, "\t\tVRT_delete_backend(ctx, &%s);", vgcname); }