[master] 035cfa4 Turn VCL types into C-objects inside the VCC compiler.
Poul-Henning Kamp
phk at FreeBSD.org
Wed Jun 8 20:59:06 CEST 2016
commit 035cfa4fe3b24fe01ae18eb894eca368d2dc6ba9
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Wed Jun 8 15:22:58 2016 +0000
Turn VCL types into C-objects inside the VCC compiler.
(Confused ? You won't be after next weeks episode of ...)
diff --git a/lib/libvcc/Makefile.am b/lib/libvcc/Makefile.am
index d0c8ece..70fad80 100644
--- a/lib/libvcc/Makefile.am
+++ b/lib/libvcc/Makefile.am
@@ -30,6 +30,7 @@ libvcc_la_SOURCES = \
vcc_storage.c \
vcc_symb.c \
vcc_token.c \
+ vcc_types.c \
vcc_utils.c \
vcc_var.c \
vcc_vmod.c \
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index ea626a8..99dfcfb 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -68,14 +68,6 @@ struct expr;
struct vcc;
struct symbol;
-enum var_type {
-#define VCC_TYPE(foo) foo,
-#include "tbl/vcc_types.h"
-#undef VCC_TYPE
-};
-
-typedef enum var_type vcc_type_t;
-
struct source {
VTAILQ_ENTRY(source) list;
char *name;
@@ -95,6 +87,22 @@ struct token {
char *dec;
};
+typedef const struct type *vcc_type_t;
+
+struct type {
+ unsigned magic;
+#define TYPE_MAGIC 0xfae932d9
+
+ const char *name;
+ const char *tostring;
+ vcc_type_t multype;
+};
+
+#define VCC_TYPE(foo) extern const struct type foo[1];
+#include "tbl/vcc_types.h"
+#undef VCC_TYPE
+
+
enum symkind {
#define VCC_SYMB(uu, ll) SYM_##uu,
#include "tbl/symbol_kind.h"
@@ -277,7 +285,6 @@ sym_expr_t vcc_Eval_Handle;
sym_expr_t vcc_Eval_SymFunc;
void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra,
const char *name, const char *args, const char *vmod);
-vcc_type_t VCC_arg_type(const char **p);
enum symkind VCC_HandleKind(vcc_type_t fmt);
struct symbol *VCC_HandleSymbol(struct vcc *, const struct token *,
vcc_type_t fmt, const char *str, ...);
@@ -325,6 +332,9 @@ void vcc__ErrInternal(struct vcc *tl, const char *func,
void vcc_AddToken(struct vcc *tl, unsigned tok, const char *b,
const char *e);
+/* vcc_types.c */
+vcc_type_t VCC_Type(const char *p);
+
/* vcc_var.c */
sym_wildcard_t vcc_Var_Wildcard;
const struct symbol *vcc_FindVar(struct vcc *tl, const struct token *t,
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 5e86895..1a73ce3 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -39,19 +39,6 @@
#include "vcc_compile.h"
-static const char *
-vcc_Type(vcc_type_t fmt)
-{
- switch(fmt) {
-#define VCC_TYPE(a) case a: return(#a);
-#include "tbl/vcc_types.h"
-#undef VCC_TYPE
- default:
- assert("Unknown Type");
- return(NULL);
- }
-}
-
/*--------------------------------------------------------------------
* Recognize and convert units of time, return seconds.
*/
@@ -381,19 +368,6 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
/*--------------------------------------------------------------------
*/
-vcc_type_t
-VCC_arg_type(const char **p)
-{
-
-#define VCC_TYPE(a) if (!strcmp(#a, *p)) { *p += strlen(#a) + 1; return (a);}
-#include "tbl/vcc_types.h"
-#undef VCC_TYPE
- return (VOID);
-}
-
-/*--------------------------------------------------------------------
- */
-
static void
vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
{
@@ -403,41 +377,25 @@ vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
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:
+ p = (*e)->fmt->tostring;
+ if (p == NULL && (*e)->fmt == 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;
+ } else if (p == NULL && (*e)->fmt == 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;
+ } else {
+ AN(p);
}
- if (p != NULL) {
+ if (*p != '\0') {
*e = vcc_expr_edit(fmt, p, *e, NULL);
(*e)->constant = constant;
}
@@ -606,9 +564,9 @@ vcc_do_arg(struct vcc *tl, struct func_arg *fa)
if (e2->fmt != fa->type) {
VSB_printf(tl->sb, "Wrong argument type.");
VSB_printf(tl->sb, " Expected %s.",
- vcc_Type(fa->type));
+ fa->type->name);
VSB_printf(tl->sb, " Got %s.\n",
- vcc_Type(e2->fmt));
+ e2->fmt->name);
vcc_ErrWhere2(tl, e2->t1, tl->t);
return;
}
@@ -640,19 +598,23 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
p = args;
if (extra == NULL)
extra = "";
- rfmt = VCC_arg_type(&p);
+ rfmt = VCC_Type(p);
+ AN(rfmt);
+ p += strlen(p) + 1;
VTAILQ_INIT(&head);
while (*p != '\0') {
fa = calloc(sizeof *fa, 1);
AN(fa);
VTAILQ_INSERT_TAIL(&head, fa, list);
- fa->type = VCC_arg_type(&p);
- if (fa->type == VOID && !memcmp(p, "PRIV_", 5)) {
+ if (!memcmp(p, "PRIV_", 5)) {
fa->result = vcc_priv_arg(tl, p, name, vmod);
fa->name = "";
p += strlen(p) + 1;
continue;
}
+ fa->type = VCC_Type(p);
+ AN(fa->type);
+ p += strlen(p) + 1;
if (*p == '\1') {
fa->enum_bits = ++p;
while (*p != '\1')
@@ -825,7 +787,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
VSB_printf(tl->sb, "Symbol not found: ");
vcc_ErrToken(tl, tl->t);
VSB_printf(tl->sb, " (expected type %s):\n",
- vcc_Type(fmt));
+ fmt->name);
vcc_ErrWhere(tl, tl->t);
return;
}
@@ -914,7 +876,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
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));
+ VSB_printf(tl->sb, " when looking for %s\n\n", fmt->name);
vcc_ErrWhere(tl, tl->t);
break;
}
@@ -937,18 +899,14 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
vcc_expr4(tl, e, fmt);
ERRCHK(tl);
AN(*e);
- f3 = f2 = (*e)->fmt;
+ f3 = (*e)->fmt;
- switch(f2) {
- case INT: f2 = INT; break;
- case DURATION: f2 = REAL; break;
- case BYTES: f2 = REAL; break;
- case REAL: f2 = REAL; break;
- default:
+ f2 = f3->multype;
+ if (f2 == NULL) {
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));
+ PF(tl->t), f3->name);
vcc_ErrWhere(tl, tl->t);
return;
}
@@ -1067,7 +1025,7 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
return;
} else {
VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
- vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt));
+ (*e)->fmt->name, PF(tk), e2->fmt->name);
vcc_ErrWhere2(tl, tk, tl->t);
return;
}
@@ -1166,9 +1124,9 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t 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));
+ VSB_printf(tl->sb, "%s ", (*e)->fmt->name);
vcc_ErrToken(tl, tk);
- VSB_printf(tl->sb, " %s\n", vcc_Type(e2->fmt));
+ VSB_printf(tl->sb, " %s\n", e2->fmt->name);
vcc_ErrWhere(tl, tk);
return;
}
@@ -1224,7 +1182,7 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt)
case '~':
case T_NOMATCH:
VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
- PF(tl->t), vcc_Type((*e)->fmt));
+ PF(tl->t), (*e)->fmt->name);
vcc_ErrWhere(tl, tl->t);
return;
default:
@@ -1263,7 +1221,7 @@ vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt)
return;
}
VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
- VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
+ VSB_printf(tl->sb, "%s.\n", e2->fmt->name);
vcc_ErrWhere2(tl, tk, tl->t);
}
@@ -1293,7 +1251,7 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if (e2->fmt != BOOL) {
VSB_printf(tl->sb,
"'&&' must be followed by BOOL, found ");
- VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
+ VSB_printf(tl->sb, "%s.\n", e2->fmt->name);
vcc_ErrWhere2(tl, tk, tl->t);
return;
}
@@ -1327,7 +1285,7 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if (e2->fmt != BOOL) {
VSB_printf(tl->sb,
"'||' must be followed by BOOL, found ");
- VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
+ VSB_printf(tl->sb, "%s.\n", e2->fmt->name);
vcc_ErrWhere2(tl, tk, tl->t);
return;
}
@@ -1362,7 +1320,7 @@ vcc_Expr(struct vcc *tl, vcc_type_t fmt)
e->t1 = t1;
if (!tl->err && fmt != e->fmt) {
VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
- vcc_Type(e->fmt), vcc_Type(fmt));
+ e->fmt->name, fmt->name);
tl->err = 1;
}
if (!tl->err) {
diff --git a/lib/libvcc/vcc_symb.c b/lib/libvcc/vcc_symb.c
index ad223a7..ee12862 100644
--- a/lib/libvcc/vcc_symb.c
+++ b/lib/libvcc/vcc_symb.c
@@ -41,14 +41,12 @@
enum symkind
VCC_HandleKind(vcc_type_t fmt)
{
- switch(fmt) {
- case ACL: return(SYM_ACL);
- case BACKEND: return(SYM_BACKEND);
- case PROBE: return(SYM_PROBE);
- case STEVEDORE: return(SYM_STEVEDORE);
- case INSTANCE: return(SYM_INSTANCE);
- default: return(SYM_NONE);
- }
+ if (fmt == ACL) return(SYM_ACL);
+ if (fmt == BACKEND) return(SYM_BACKEND);
+ if (fmt == PROBE) return(SYM_PROBE);
+ if (fmt == STEVEDORE) return(SYM_STEVEDORE);
+ if (fmt == INSTANCE) return(SYM_INSTANCE);
+ return(SYM_NONE);
}
const char *
diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c
new file mode 100644
index 0000000..822471d
--- /dev/null
+++ b/lib/libvcc/vcc_types.c
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at 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.
+ *
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+const struct type ACL[1] = {{
+ .magic = 0xfae932d9,
+ .name = "ACL",
+}};
+
+const struct type BACKEND[1] = {{
+ .magic = 0xfae932d9,
+ .name = "BACKEND",
+ .tostring = "VRT_BACKEND_string(\v1)",
+}};
+
+const struct type BLOB[1] = {{
+ .magic = 0xfae932d9,
+ .name = "BLOB",
+}};
+
+const struct type BOOL[1] = {{
+ .magic = 0xfae932d9,
+ .name = "BOOL",
+ .tostring = "VRT_BOOL_string(\v1)",
+}};
+
+const struct type BYTES[1] = {{
+ .magic = 0xfae932d9,
+ .name = "BYTES",
+ .tostring = "VRT_REAL_string(ctx, \v1)", // XXX: wrong
+ .multype = REAL, // XXX: wrong
+}};
+
+const struct type DURATION[1] = {{
+ .magic = 0xfae932d9,
+ .name = "DURATION",
+ .tostring = "VRT_REAL_string(ctx, \v1)", // XXX 's' suff?
+ .multype = REAL,
+}};
+
+const struct type ENUM[1] = {{
+ .magic = 0xfae932d9,
+ .name = "ENUM",
+ .tostring = "",
+}};
+
+const struct type HEADER[1] = {{
+ .magic = 0xfae932d9,
+ .name = "HEADER",
+ .tostring = "VRT_GetHdr(ctx, \v1)",
+}};
+
+const struct type HTTP[1] = {{
+ .magic = 0xfae932d9,
+ .name = "HTTP",
+}};
+
+const struct type INSTANCE[1] = {{
+ .magic = 0xfae932d9,
+ .name = "INSTANCE",
+}};
+
+const struct type INT[1] = {{
+ .magic = 0xfae932d9,
+ .name = "INT",
+ .multype = INT,
+}};
+
+const struct type IP[1] = {{
+ .magic = 0xfae932d9,
+ .name = "IP",
+ .tostring = "VRT_IP_string(ctx, \v1)",
+}};
+
+const struct type PROBE[1] = {{
+ .magic = 0xfae932d9,
+ .name = "PROBE",
+}};
+
+const struct type REAL[1] = {{
+ .magic = 0xfae932d9,
+ .name = "REAL",
+ .tostring = "VRT_REAL_string(ctx, \v1)",
+ .multype = REAL,
+}};
+
+const struct type STEVEDORE[1] = {{
+ .magic = 0xfae932d9,
+ .name = "STEVEDORE",
+}};
+
+const struct type STRING[1] = {{
+ .magic = 0xfae932d9,
+ .name = "STRING",
+ .tostring = "",
+}};
+
+const struct type STRING_LIST[1] = {{
+ .magic = 0xfae932d9,
+ .name = "STRING_LIST",
+ .tostring = "",
+}};
+
+const struct type TIME[1] = {{
+ .magic = 0xfae932d9,
+ .name = "TIME",
+ .tostring = "VRT_TIME_string(ctx, \v1)",
+}};
+
+const struct type VOID[1] = {{
+ .magic = 0xfae932d9,
+ .name = "VOID",
+}};
+
+vcc_type_t
+VCC_Type(const char *p)
+{
+
+#define VCC_TYPE(foo) if (!strcmp(p, #foo)) return (foo);
+#include "tbl/vcc_types.h"
+#undef VCC_TYPE
+ return (NULL);
+}
+
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index 9f6f59e..c151337 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -248,7 +248,9 @@ vcc_ParseImport(struct vcc *tl)
sym->cfunc = p;
p += strlen(p) + 1;
sym->args = p;
- sym->fmt = VCC_arg_type(&p);
+ sym->fmt = VCC_Type(p);
+ AN(sym->fmt);
+ p += strlen(p) + 1;
} else {
VSB_printf(tl->sb, "Internal spec error (%s)\n", p);
vcc_ErrWhere(tl, mod);
More information about the varnish-commit
mailing list