Commit 51a9ab68 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Start massaging the conditional parsing to handle non-variable left sides.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5014 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent fa8942f6
......@@ -10,6 +10,7 @@ libvcl_la_SOURCES = \
vcc_priv.h \
vcc_compile.h \
vcc_token_defs.h \
vcc_types.h \
\
vcc_acl.c \
vcc_action.c \
......
......@@ -556,6 +556,8 @@ vcc_CompileSource(const struct vcc *tl0, struct vsb *sb, struct source *sp)
for (v = tl->vars; v->name != NULL; v++) {
sym = VCC_AddSymbol(tl, v->name);
sym->var = v;
sym->fmt = v->fmt;
sym->r_methods = v->r_methods;
if (v->fmt == HEADER)
sym->wildcard = 1;
}
......
......@@ -38,6 +38,12 @@
struct acl_e;
enum var_type {
#define VCC_TYPE(foo) foo,
#include "vcc_types.h"
#undef VCC_TYPE
};
struct membit {
VTAILQ_ENTRY(membit) list;
void *ptr;
......@@ -70,6 +76,8 @@ struct symbol {
unsigned nlen;
unsigned wildcard;
const struct var *var;
enum var_type fmt;
unsigned r_methods;
};
VTAILQ_HEAD(tokenhead, token);
......@@ -129,19 +137,6 @@ struct vcc {
unsigned nsockaddr;
};
enum var_type {
BACKEND,
BOOL,
INT,
// SIZE,
// FLOAT,
TIME,
DURATION,
STRING,
IP,
HEADER
};
enum ref_type {
R_SUB,
R_ACL,
......@@ -164,7 +159,7 @@ struct var {
const char *rname;
unsigned r_methods;
const char *lname;
unsigned l_methods;
unsigned w_methods;
const char *hdr;
};
......@@ -227,7 +222,7 @@ extern const struct var vcc_vars[];
void vcc_Parse(struct vcc *tl);
void vcc_RTimeVal(struct vcc *tl, double *);
void vcc_TimeVal(struct vcc *tl, double *);
void vcc_SizeVal(struct vcc *tl, double *);
// void vcc_SizeVal(struct vcc *tl, double *);
unsigned vcc_UintVal(struct vcc *tl);
double vcc_DoubleVal(struct vcc *tl);
......
......@@ -323,10 +323,92 @@ vcc_Cond_Backend(const struct var *vp, struct vcc *tl)
vcc_NextToken(tl);
}
const char *typenm[] = {
#define VCC_TYPE(foo) [foo] = #foo,
#include "vcc_types.h"
#undef VCC_TYPE
};
static int
vcc_Relation(struct vcc *tl, enum var_type fmt)
{
switch(tl->t->tok) {
case T_EQ:
case T_NEQ:
if (fmt != BOOL)
return (tl->t->tok);
break;
case '>':
case T_GEQ:
case '<':
case T_LEQ:
if (fmt == INT || fmt == TIME || fmt == DURATION)
return (tl->t->tok);
break;
case '~':
case T_NOMATCH:
if (fmt == IP || fmt == STRING || fmt == HEADER)
return (tl->t->tok);
break;
default:
if (fmt == STRING || fmt == HEADER || fmt == BOOL)
return (-1);
break;
}
vsb_printf(tl->sb, "Invalid comparison/match operator ");
vsb_printf(tl->sb, " for type %s.\n", typenm[fmt]);
vcc_ErrToken(tl, tl->t);
vcc_ErrWhere(tl, tl->t);
return (-1);
}
static void
vcc_Cond_2(struct vcc *tl)
vcc_Cond_3(struct vcc *tl)
{
const struct var *vp;
const struct symbol *sym;
sym = VCC_FindSymbol(tl, tl->t);
if (sym == NULL) {
vsb_printf(tl->sb,
"Syntax error in condition.\n"
"Expected '(', '!' or variable name.\n"
"Found ");
vcc_ErrToken(tl, tl->t);
vsb_printf(tl->sb, "\n");
vcc_ErrWhere(tl, tl->t);
return;
}
vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
AN(sym->var);
vp = vcc_FindVar(tl, tl->t, 0, "cannot be read");
ERRCHK(tl);
assert(vp != NULL);
vcc_NextToken(tl);
vcc_Relation(tl, sym->fmt);
switch (vp->fmt) {
case INT: L(tl, vcc_Cond_Int(vp, tl)); break;
// case SIZE: L(tl, vcc_Cond_Int(vp, tl)); break;
case BOOL: L(tl, vcc_Cond_Bool(vp, tl)); break;
case IP: L(tl, vcc_Cond_Ip(vp, tl)); break;
case STRING: L(tl, vcc_Cond_String(vp, tl)); break;
case TIME: L(tl, vcc_Cond_Int(vp, tl)); break;
case DURATION: L(tl, vcc_Cond_Int(vp, tl)); break;
case BACKEND: L(tl, vcc_Cond_Backend(vp, tl)); break;
default:
vsb_printf(tl->sb,
"Variable '%s'"
" has no conditions that can be checked\n",
vp->name);
vcc_ErrWhere(tl, tl->t);
return;
}
}
static void
vcc_Cond_2(struct vcc *tl)
{
C(tl, ",");
if (tl->t->tok == '!') {
......@@ -339,38 +421,22 @@ vcc_Cond_2(struct vcc *tl)
vcc_NextToken(tl);
vcc_Cond_0(tl);
SkipToken(tl, ')');
} else if (tl->t->tok == ID) {
vp = vcc_FindVar(tl, tl->t, 0, "cannot be read");
ERRCHK(tl);
assert(vp != NULL);
vcc_NextToken(tl);
switch (vp->fmt) {
case INT: L(tl, vcc_Cond_Int(vp, tl)); break;
// case SIZE: L(tl, vcc_Cond_Int(vp, tl)); break;
case BOOL: L(tl, vcc_Cond_Bool(vp, tl)); break;
case IP: L(tl, vcc_Cond_Ip(vp, tl)); break;
case STRING: L(tl, vcc_Cond_String(vp, tl)); break;
case TIME: L(tl, vcc_Cond_Int(vp, tl)); break;
case DURATION: L(tl, vcc_Cond_Int(vp, tl)); break;
case BACKEND: L(tl, vcc_Cond_Backend(vp, tl)); break;
default:
vsb_printf(tl->sb,
"Variable '%s'"
" has no conditions that can be checked\n",
vp->name);
vcc_ErrWhere(tl, tl->t);
return;
}
} else {
vsb_printf(tl->sb,
"Syntax error in condition, expected '(', '!' or"
" variable name, found ");
vcc_ErrToken(tl, tl->t);
vsb_printf(tl->sb, "\n");
vcc_ErrWhere(tl, tl->t);
Fb(tl, 1, ")\n");
return;
}
Fb(tl, 1, ")\n");
if (tl->t->tok == ID) {
vcc_Cond_3(tl);
Fb(tl, 1, ")\n");
return;
}
vsb_printf(tl->sb,
"Syntax error in condition.\n"
"Expected '(', '!' or variable name.\n"
"Found ");
vcc_ErrToken(tl, tl->t);
vsb_printf(tl->sb, "\n");
vcc_ErrWhere(tl, tl->t);
return;
}
static void
......
/*-
* Copyright (c) 2010 Linpro AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
VCC_TYPE(BACKEND)
VCC_TYPE(BOOL)
VCC_TYPE(INT)
VCC_TYPE(TIME)
VCC_TYPE(DURATION)
VCC_TYPE(STRING)
VCC_TYPE(IP)
VCC_TYPE(HEADER)
......@@ -62,7 +62,7 @@ HeaderVar(struct vcc *tl, const struct token *t, const struct var *vh)
p[i] = '\0';
v->name = p;
v->r_methods = vh->r_methods;
v->l_methods = vh->l_methods;
v->w_methods = vh->w_methods;
v->fmt = STRING;
v->hdr = vh->hdr;
l = strlen(v->name + vh->len) + 1;
......@@ -99,7 +99,7 @@ vcc_FindVar(struct vcc *tl, const struct token *t, int wr_access,
v = sym->var;
AN(v);
if (wr_access && v->l_methods == 0) {
if (wr_access && v->w_methods == 0) {
vsb_printf(tl->sb, "Variable ");
vcc_ErrToken(tl, t);
vsb_printf(tl->sb, " is read only.");
......@@ -107,7 +107,7 @@ vcc_FindVar(struct vcc *tl, const struct token *t, int wr_access,
vcc_ErrWhere(tl, t);
return (NULL);
} else if (wr_access) {
vcc_AddUses(tl, t, v->l_methods, use);
vcc_AddUses(tl, t, v->w_methods, use);
} else if (v->r_methods == 0) {
vsb_printf(tl->sb, "Variable ");
vcc_ErrToken(tl, t);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment