Example #1
0
static void
vcc_ParseVcl(struct vcc *tl)
{
	struct token *tok;

	assert(vcc_IdIs(tl->t, "vcl"));
	vcc_NextToken(tl);
	tok = tl->t;
	tok->src->syntax = vcc_DoubleVal(tl);
	ERRCHK(tl);
	if (tl->t->e - tok->b > 4) {
		VSB_printf(tl->sb,
		    "Don't play silly buggers with VCL version numbers\n");
		vcc_ErrWhere2(tl, tok, tl->t);
		ERRCHK(tl);
	}
	if (tl->syntax != 0.0 && tok->src->syntax > tl->syntax) {
		VSB_printf(tl->sb,
		    "VCL version %.1f higher than"
		    " the top level version %.1f\n",
		    tok->src->syntax, tl->syntax);
		vcc_ErrWhere2(tl, tok, tl->t);
		ERRCHK(tl);
	}
	ExpectErr(tl, ';');
	vcc_NextToken(tl);
}
Example #2
0
void
vcc_Expr(struct vcc *tl, enum var_type fmt)
{
	struct expr *e;
	struct token *t1;

	assert(fmt != VOID);

	t1 = tl->t;
	vcc_expr0(tl, &e, fmt);
	ERRCHK(tl);
	if (fmt == STRING || fmt == STRING_LIST)
		vcc_expr_tostring(&e, fmt);
	if (!tl->err && fmt != e->fmt)  {
		VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
		    vcc_Type(e->fmt), vcc_Type(fmt));
		tl->err = 1;
	}
	if (!tl->err) {
		if (e->fmt == STRING_LIST) {
			e = vcc_expr_edit(STRING_LIST,
			    "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL);
		}
		vcc_expr_fmt(tl->fb, tl->indent, e);
		VSB_putc(tl->fb, '\n');
	} else {
		if (t1 != tl->t)
			vcc_ErrWhere2(tl, t1, tl->t);
	}
	vcc_delete_expr(e);
}
Example #3
0
static void
vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr *e2;
	struct token *tk;

	*e = NULL;
	vcc_expr_cand(tl, e, fmt);
	ERRCHK(tl);
	if ((*e)->fmt != BOOL || tl->t->tok != T_COR)
		return;
	*e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
	while (tl->t->tok == T_COR) {
		vcc_NextToken(tl);
		tk = tl->t;
		vcc_expr_cand(tl, &e2, fmt);
		ERRCHK(tl);
		if (e2->fmt != BOOL) {
			VSB_printf(tl->sb,
			    "'||' must be followed by BOOL, found ");
			VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
			vcc_ErrWhere2(tl, tk, tl->t);
			return;
		}
		*e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2);
	}
	*e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
}
Example #4
0
static void
vcc_expr_tostring(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	const char *p;
	uint8_t	constant = EXPR_VAR;

	CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
	AN(fmt == STRING || fmt == STRING_LIST);

	p = NULL;
	switch((*e)->fmt) {
	case BACKEND:	p = "VRT_BACKEND_string(\v1)"; break;
	case BOOL:	p = "VRT_BOOL_string(\v1)"; break;
	case DURATION:	p = "VRT_REAL_string(ctx, \v1)"; break;
			 /* XXX: should DURATION insist on "s" suffix ? */
	case INT:
		if (vcc_isconst(*e)) {
			p = "\"\v1\"";
			constant = EXPR_CONST;
		} else {
			p = "VRT_INT_string(ctx, \v1)";
		}
		break;
	case IP:	p = "VRT_IP_string(ctx, \v1)"; break;
	case BYTES:	p = "VRT_REAL_string(ctx, \v1)"; break; /* XXX */
	case REAL:	p = "VRT_REAL_string(ctx, \v1)"; break;
	case TIME:	p = "VRT_TIME_string(ctx, \v1)"; break;
	case HEADER:	p = "VRT_GetHdr(ctx, \v1)"; break;
	case ENUM:
	case STRING:
	case STRING_LIST:
			break;
	case BLOB:
			VSB_printf(tl->sb,
			    "Wrong use of BLOB value.\n"
			    "BLOBs can only be used as arguments to VMOD"
			    " functions.\n");
			vcc_ErrWhere2(tl, (*e)->t1, tl->t);
			return;
	default:
			INCOMPL();
			break;
	}
	if (p != NULL) {
		*e = vcc_expr_edit(fmt, p, *e, NULL);
		(*e)->constant = constant;
	}
}
Example #5
0
void
vcc_Eval_Func(struct vcc *tl, const char *cfunc,
    const char *extra, const char *name, const char *args)
{
	struct expr *e = NULL;
	struct token *t1;

	t1 = tl->t;
	vcc_func(tl, &e, cfunc, extra, name, args);
	if (!tl->err) {
		vcc_expr_fmt(tl->fb, tl->indent, e);
		VSB_cat(tl->fb, ";\n");
	} else if (t1 != tl->t) {
		vcc_ErrWhere2(tl, t1, tl->t);
	}
	vcc_delete_expr(e);
}
Example #6
0
void
vcc_Expr_Call(struct vcc *tl, const struct symbol *sym)
{

	struct expr *e;
	struct token *t1;

	t1 = tl->t;
	e = NULL;
	vcc_Eval_Func(tl, &e, sym);
	if (!tl->err) {
		vcc_expr_fmt(tl->fb, tl->indent, e);
		VSB_cat(tl->fb, ";\n");
	} else if (t1 != tl->t) {
		vcc_ErrWhere2(tl, t1, tl->t);
	}
	vcc_delete_expr(e);
}
Example #7
0
static void
vcc_expr_not(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr *e2;
	struct token *tk;

	*e = NULL;
	if (fmt != BOOL || tl->t->tok != '!') {
		vcc_expr_cmp(tl, e, fmt);
		return;
	}

	vcc_NextToken(tl);
	tk = tl->t;
	vcc_expr_cmp(tl, &e2, fmt);
	ERRCHK(tl);
	if (e2->fmt == BOOL) {
		*e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL);
		return;
	}
	VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
	VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
	vcc_ErrWhere2(tl, tk, tl->t);
}
Example #8
0
static void
vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr  *e2;
	enum var_type f2;
	struct token *tk;

	*e = NULL;
	vcc_expr_mul(tl, e, fmt);
	ERRCHK(tl);
	f2 = (*e)->fmt;

	if ((f2 == STRING_LIST || f2 == STRING) && tl->t->tok == '+') {
		while (tl->t->tok == '+') {
			vcc_NextToken(tl);
			vcc_expr_mul(tl, &e2, STRING);
			ERRCHK(tl);
			if (e2->fmt != STRING && e2->fmt != STRING_LIST)
				vcc_expr_tostring(&e2, f2);
			ERRCHK(tl);
			assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
			if ((*e)->constant &&  e2->constant) {
				assert((*e)->fmt == STRING);
				assert(e2->fmt == STRING);
				*e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2);
			} else {
				*e = vcc_expr_edit(STRING_LIST,
				    "\v1,\n\v2", *e, e2);
			}
		}
	}
	if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST)
		*e = vcc_expr_edit(STRING,
		    "\v+VRT_WrkString(sp,\n\v1,\nvrt_magic_string_end)",
		    *e, NULL);
	if (fmt == STRING_LIST && (*e)->fmt == STRING)
		(*e)->fmt = STRING_LIST;

	switch(f2) {
	case INT:	break;
	case TIME:	break;
	case DURATION:	break;
	case BYTES:	break;
	default:
		if (tl->t->tok != '+' && tl->t->tok != '-')
			return;
		VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n",
		    PF(tl->t), vcc_Type(f2));
		vcc_ErrWhere(tl, tl->t);
		return;
	}

	while (tl->t->tok == '+' || tl->t->tok == '-') {
		if (f2 == TIME)
			f2 = DURATION;
		tk = tl->t;
		vcc_NextToken(tl);
		vcc_expr_mul(tl, &e2, f2);
		ERRCHK(tl);
		if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) {
			/* OK */
		} else if (tk->tok == '-' &&
		    (*e)->fmt == BYTES && e2->fmt == BYTES) {
			/* OK */
		} else if (e2->fmt != f2) {
			VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
			    vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt));
			vcc_ErrWhere2(tl, tk, tl->t);
			return;
		}
		if (tk->tok == '+')
			*e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2);
		else if (f2 == TIME && e2->fmt == TIME)
			*e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2);
		else
			*e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2);
	}
}
Example #9
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;
}
Example #10
0
void
vcc_Parse(struct vcc *tl)
{
	struct toplev *tp;
	struct token *tok;

	AZ(tl->indent);
	if (tl->t->tok != ID || !vcc_IdIs(tl->t, "vcl")) {
		VSB_printf(tl->sb,
		    "VCL version declaration missing\n"
		    "Update your VCL to Version 4 syntax, and add\n"
		    "\tvcl 4.0;\n"
		    "on the first line of the VCL files.\n"
		);
		vcc_ErrWhere(tl, tl->t);
		ERRCHK(tl);
	}
	tok = tl->t;
	vcc_ParseVcl(tl);
	if (tok->src->syntax != 4.0) {
		VSB_printf(tl->sb, "VCL version %.1f not supported.\n",
		    tok->src->syntax);
		vcc_ErrWhere2(tl, tok, tl->t);
		ERRCHK(tl);
	}
	tl->syntax = tl->t->src->syntax;
	ERRCHK(tl);
	while (tl->t->tok != EOI) {
		ERRCHK(tl);
		switch (tl->t->tok) {
		case CSRC:
			if (tl->allow_inline_c) {
				Fc(tl, 0, "%.*s\n",
				    (int) (tl->t->e - (tl->t->b + 4)),
				    tl->t->b + 2);
				vcc_NextToken(tl);
			} else {
				VSB_printf(tl->sb,
				    "Inline-C not allowed\n");
				vcc_ErrWhere(tl, tl->t);
			}
			break;
		case EOI:
			break;
		case ID:
			for (tp = toplev; tp->name != NULL; tp++) {
				if (!vcc_IdIs(tl->t, tp->name))
					continue;
				tp->func(tl);
				break;
			}
			if (tp->name != NULL)
				break;
			/* FALLTHROUGH */
		default:
			/* We deliberately do not mention inline-C */
			VSB_printf(tl->sb, "Expected one of\n\t");
			for (tp = toplev; tp->name != NULL; tp++) {
				if (tp[1].name == NULL)
					VSB_printf(tl->sb, " or ");
				VSB_printf(tl->sb, "'%s'", tp->name);
				if (tp[1].name != NULL)
					VSB_printf(tl->sb, ", ");
			}
			VSB_printf(tl->sb, "\nFound: ");
			vcc_ErrToken(tl, tl->t);
			VSB_printf(tl->sb, " at\n");
			vcc_ErrWhere(tl, tl->t);
			return;
		}
	}
	AZ(tl->indent);
}
Example #11
0
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));
}
Example #12
0
static void
vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr  *e2;
	enum var_type f2;
	struct token *tk;

	*e = NULL;
	vcc_expr_mul(tl, e, fmt);
	ERRCHK(tl);
	f2 = (*e)->fmt;

	/* Unless we specifically ask for a HEADER, fold them to string here */
	if (fmt != HEADER && f2 == HEADER) {
		vcc_expr_tostring(tl, e, STRING);
		ERRCHK(tl);
		f2 = (*e)->fmt;
		assert(f2 == STRING);
	}

	if (tl->t->tok != '+' && tl->t->tok != '-')
		return;

	switch(f2) {
	case STRING:
	case STRING_LIST:
		vcc_expr_string_add(tl, e);
		return;
	case INT:		break;
	case TIME:		break;
	case DURATION:		break;
	case BYTES:		break;
	default:
		VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n",
		    PF(tl->t), vcc_Type(f2));
		vcc_ErrWhere(tl, tl->t);
		return;
	}

	while (tl->t->tok == '+' || tl->t->tok == '-') {
		if (f2 == TIME)
			f2 = DURATION;
		tk = tl->t;
		vcc_NextToken(tl);
		vcc_expr_mul(tl, &e2, f2);
		ERRCHK(tl);
		if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) {
			/* OK */
		} else if ((*e)->fmt == TIME && e2->fmt == DURATION) {
			f2 = TIME;
			/* OK */
		} else if (tk->tok == '-' &&
		    (*e)->fmt == BYTES && e2->fmt == BYTES) {
			/* OK */
		} else if (e2->fmt != f2) {
			VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
			    vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt));
			vcc_ErrWhere2(tl, tk, tl->t);
			return;
		}
		if (tk->tok == '+')
			*e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2);
		else if (f2 == TIME && e2->fmt == TIME)
			*e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2);
		else
			*e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2);
	}
}
Example #13
0
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;
}
Example #14
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 */
}
Example #15
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));
}