[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