示例#1
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);
}
示例#2
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);
}
示例#3
0
static void
vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr *e2;
	enum var_type f2, f3;
	struct token *tk;

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

	switch(f2) {
	case INT:	f2 = INT; break;
	case DURATION:	f2 = REAL; break;
	case BYTES:	f2 = REAL; 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 == '/') {
		tk = tl->t;
		vcc_NextToken(tl);
		vcc_expr4(tl, &e2, f2);
		ERRCHK(tl);
		assert(e2->fmt == f2);
		if (tk->tok == '*')
			*e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2);
		else
			*e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2);
	}
}
示例#4
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);
}
示例#5
0
static void
vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt)
{
	struct expr *e2;
	const struct cmps *cp;
	char buf[256];
	char *re;
	const char *not;
	struct token *tk;

	*e = NULL;

	vcc_expr_add(tl, e, fmt);
	ERRCHK(tl);

	if ((*e)->fmt == BOOL)
		return;

	tk = tl->t;
	for (cp = vcc_cmps; cp->fmt != VOID; cp++)
		if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token)
			break;
	if (cp->fmt != VOID) {
		vcc_NextToken(tl);
		vcc_expr_add(tl, &e2, (*e)->fmt);
		ERRCHK(tl);
		if (e2->fmt != (*e)->fmt) { /* XXX */
			VSB_printf(tl->sb, "Comparison of different types: ");
			VSB_printf(tl->sb, "%s ", vcc_Type((*e)->fmt));
			vcc_ErrToken(tl, tk);
			VSB_printf(tl->sb, " %s\n", vcc_Type(e2->fmt));
			vcc_ErrWhere(tl, tk);
			return;
		}
		*e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
		return;
	}
	if ((*e)->fmt == STRING &&
	    (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) {
	        not = tl->t->tok == '~' ? "" : "!";
		vcc_NextToken(tl);
		ExpectErr(tl, CSTR);
		re = vcc_regexp(tl);
		ERRCHK(tl);
		vcc_NextToken(tl);
		bprintf(buf, "%sVRT_re_match(\v1, %s)", not, re);
		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
		return;
	}
	if ((*e)->fmt == IP &&
	    (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) {
	        not = tl->t->tok == '~' ? "" : "!";
		vcc_NextToken(tl);
		ExpectErr(tl, ID);
		vcc_AddRef(tl, tl->t, SYM_ACL);
		bprintf(buf, "%smatch_acl_named_%.*s(sp, \v1)", not, PF(tl->t));
		vcc_NextToken(tl);
		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
		return;
	}
	if ((*e)->fmt == IP && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) {
		vcc_Acl_Hack(tl, buf);
		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
		return;
	}
	if ((*e)->fmt == BACKEND &&
	    (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) {
		vcc_NextToken(tl);
		ExpectErr(tl, ID);
		vcc_AddRef(tl, tl->t, SYM_BACKEND);
		bprintf(buf, "(\v1 %.*s VGCDIR(_%.*s))", PF(tk), PF(tl->t));
		vcc_NextToken(tl);
		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
		return;
	}
	switch (tl->t->tok) {
	case T_EQ:
	case T_NEQ:
	case '<':
	case T_LEQ:
	case '>':
	case T_GEQ:
	case '~':
	case T_NOMATCH:
		VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
		    PF(tl->t), vcc_Type((*e)->fmt));
		vcc_ErrWhere(tl, tl->t);
		return;
	default:
		break;
	}
	if (fmt == BOOL && (*e)->fmt == STRING) {
		*e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL);
		return;
	}
}
示例#6
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);
	}
}
示例#7
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;
	}
}
示例#8
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;
}
示例#9
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);
	}
}
示例#10
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;
}