Ejemplo n.º 1
0
int
vcc_ParseAction(struct vcc *tl)
{
	struct token *at;
	struct action_table *atp;
	const struct symbol *sym;

	at = tl->t;
	assert(at->tok == ID);
	for(atp = action_table; atp->name != NULL; atp++) {
		if (vcc_IdIs(at, atp->name)) {
			if (atp->bitmask != 0)
				vcc_AddUses(tl, at, atp->bitmask,
				    "not a valid action");
			atp->func(tl);
			return (1);
		}
	}
	sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
	if (sym != NULL && sym->kind == SYM_PROC) {
		vcc_Expr_Call(tl, sym);
		return (1);
	}
	return (0);
}
Ejemplo n.º 2
0
const struct var *
vcc_FindVar(struct vcc *tl, const struct token *t, int wr_access,
    const char *use)
{
	const struct var *v;
	const struct symbol *sym;

	AN(tl->vars);
	sym = VCC_FindSymbol(tl, t, SYM_VAR);
	if (sym != NULL) {
		v = sym->var;
		AN(v);

		if (wr_access && v->w_methods == 0) {
			VSB_printf(tl->sb, "Variable ");
			vcc_ErrToken(tl, t);
			VSB_printf(tl->sb, " is read only.");
			VSB_cat(tl->sb, "\nAt: ");
			vcc_ErrWhere(tl, t);
			return (NULL);
		} else if (wr_access) {
			vcc_AddUses(tl, t, v->w_methods, use);
		} else if (v->r_methods == 0) {
			VSB_printf(tl->sb, "Variable ");
			vcc_ErrToken(tl, t);
			VSB_printf(tl->sb, " is write only.");
			VSB_cat(tl->sb, "\nAt: ");
			vcc_ErrWhere(tl, t);
			return (NULL);
		} else {
			vcc_AddUses(tl, t, v->r_methods, use);
		}
		assert(v->fmt != HEADER);
		return (v);
	}
	VSB_printf(tl->sb, "Unknown variable ");
	vcc_ErrToken(tl, t);
	VSB_cat(tl->sb, "\nAt: ");
	vcc_ErrWhere(tl, t);
	return (NULL);
}
Ejemplo n.º 3
0
static void
vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr *e1, *e2;
	const struct symbol *sym;
	double d;

	*e = NULL;
	if (tl->t->tok == '(') {
		SkipToken(tl, '(');
		vcc_expr0(tl, &e2, fmt);
		ERRCHK(tl);
		SkipToken(tl, ')');
		*e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL);
		return;
	}
	switch(tl->t->tok) {
	case ID:
		/*
		 * XXX: what if var and func/proc had same name ?
		 * XXX: look for SYM_VAR first for consistency ?
		 */
		sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
		if (sym == NULL || sym->eval == NULL) {
			VSB_printf(tl->sb, "Symbol not found: ");
			vcc_ErrToken(tl, tl->t);
			VSB_printf(tl->sb, " (expected type %s):\n",
			    vcc_Type(fmt));
			vcc_ErrWhere(tl, tl->t);
			return;
		}
		AN(sym);
		switch(sym->kind) {
		case SYM_VAR:
		case SYM_FUNC:
		case SYM_BACKEND:
			AN(sym->eval);
			AZ(*e);
			sym->eval(tl, e, sym);
			return;
		default:
			break;
		}
		VSB_printf(tl->sb,
		    "Symbol type (%s) can not be used in expression.\n",
		    VCC_SymKind(tl, sym));
		vcc_ErrWhere(tl, tl->t);
		return;
	case CSTR:
		assert(fmt != VOID);
		e1 = vcc_new_expr();
		EncToken(e1->vsb, tl->t);
		e1->fmt = STRING;
		e1->t1 = tl->t;
		e1->constant = 1;
		vcc_NextToken(tl);
		AZ(VSB_finish(e1->vsb));
		*e = e1;
		break;
	case CNUM:
		/*
		 * XXX: %g may not have enough decimals by default
		 * XXX: but %a is ugly, isn't it ?
		 */
		assert(fmt != VOID);
		if (fmt == DURATION) {
			vcc_RTimeVal(tl, &d);
			ERRCHK(tl);
			e1 = vcc_mk_expr(DURATION, "%g", d);
		} else if (fmt == BYTES) {
			vcc_ByteVal(tl, &d);
			ERRCHK(tl);
			e1 = vcc_mk_expr(BYTES, "%.1f", d);
			ERRCHK(tl);
		} else if (fmt == REAL) {
			e1 = vcc_mk_expr(REAL, "%g", vcc_DoubleVal(tl));
			ERRCHK(tl);
		} else {
			e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t));
			vcc_NextToken(tl);
		}
		e1->constant = 1;
		*e = e1;
		break;
	default:
		VSB_printf(tl->sb, "Unknown token ");
		vcc_ErrToken(tl, tl->t);
		VSB_printf(tl->sb, " when looking for %s\n\n", vcc_Type(fmt));
		vcc_ErrWhere(tl, tl->t);
		break;
	}
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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 */
}
Ejemplo n.º 6
0
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));
}
Ejemplo n.º 7
0
void
vcc_ParseImport(struct vcc *tl)
{
	void *hdl;
	char fn[1024], *fnp;
	char buf[256];
	struct token *mod, *t1;
	struct inifin *ifp;
	const char * const *spec;
	struct symbol *sym;
	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_FindSymbol(tl, mod, SYM_NONE);
	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));
	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 (!vcc_IdIs(tl->t, "from")) {
			VSB_printf(tl->sb, "Expected 'from path ...'\n");
			vcc_ErrWhere(tl, tl->t);
			return;
		}
		vcc_NextToken(tl);
		if (!tl->param->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->param->vmod_path,
	    vcc_path_dlopen, &hdl, fn, &fnp)) {
		VSB_printf(tl->sb, "Could not load VMOD %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n", fnp != NULL ? fnp : fn);
		VSB_printf(tl->sb, "\tdlerror: %s\n", dlerror());
		vcc_ErrWhere(tl, mod);
		return;
	}

	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    ");
	EncString(ifp->ini, fnp, NULL, 0);
	free(fnp);
	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_AddSymbolStr(tl, p, SYM_OBJECT);
			XXXAN(sym);
			sym->args = p;
		} 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(void)%s(ctx, &vmod_priv_%.*s, ev);\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/* --- 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));
}
Ejemplo n.º 8
0
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 */
}
Ejemplo n.º 9
0
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);
}