[master] 1ba4d05 Build arglist from spec and walk it as separate steps.

Poul-Henning Kamp phk at FreeBSD.org
Tue Nov 25 14:50:43 CET 2014


commit 1ba4d053d98956056eefa3cce29916f29bbf6823
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Nov 25 12:15:59 2014 +0000

    Build arglist from spec and walk it as separate steps.

diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 2eb9e73..54c113a 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -569,13 +569,24 @@ vcc_priv_arg(struct vcc *tl, const char *p, const char *name)
 	return (e2);
 }
 
+struct func_arg {
+	enum var_type		type;
+	const char		*enum_bits;
+	const char		*name;
+	const char		*val;
+	struct expr		*result;
+	VTAILQ_ENTRY(func_arg)	list;
+};
+
 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;
-	enum var_type fmt;
+	struct func_arg *fa, *fa2;
+	enum var_type rfmt;
+	VTAILQ_HEAD(,func_arg) head;
 
 	AN(cfunc);
 	AN(args);
@@ -584,21 +595,43 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
 	p = args;
 	if (extra == NULL)
 		extra = "";
-	e1 = vcc_mk_expr(vcc_arg_type(&p), "%s(ctx%s\v+", cfunc, extra);
+	rfmt = vcc_arg_type(&p);
+	VTAILQ_INIT(&head);
 	while (*p != '\0') {
-		e2 = NULL;
-		fmt = vcc_arg_type(&p);
-		if (!memcmp(p, "PRIV_", 5)) {
-			assert(fmt == VOID);
-			e2 = vcc_priv_arg(tl, p, name);
-			e1 = vcc_expr_edit(e1->fmt, "\v1,\n\v2", e1, e2);
+		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)) {
+			fa->result = vcc_priv_arg(tl, p, name);
+			fa->name = "";
 			p += strlen(p) + 1;
 			continue;
 		}
-		if (fmt == ENUM) {
+		if (fa->type == ENUM) {
+			fa->enum_bits = p;
+			while (*p != '\0')
+				p += strlen(p) + 1;
+			p += strlen(p) + 1;
+		}
+		if (*p == '\1') {
+			fa->name = p + 1;
+			p = strchr(p, '\0') + 1;
+			if (*p == '\2') {
+				fa->val = p + 1;
+				p = strchr(p, '\0') + 1;
+			}
+		}
+	}
+
+	VTAILQ_FOREACH(fa, &head, list) {
+		if (fa->result != NULL)
+			continue;
+		e2 = NULL;
+		if (fa->type == ENUM) {
 			ExpectErr(tl, ID);
 			ERRCHK(tl);
-			r = p;
+			r = p = fa->enum_bits;
 			do {
 				if (vcc_IdIs(tl->t, p))
 					break;
@@ -614,45 +647,39 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
 				vcc_ErrWhere(tl, tl->t);
 				return;
 			}
-			e2 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
-			while (*p != '\0')
-				p += strlen(p) + 1;
-			p++;
+			fa->result = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
 			SkipToken(tl, ID);
 		} else {
-			vcc_expr0(tl, &e2, fmt);
+			vcc_expr0(tl, &e2, fa->type);
 			ERRCHK(tl);
-			if (e2->fmt != fmt) {
+			if (e2->fmt != fa->type) {
 				VSB_printf(tl->sb, "Wrong argument type.");
 				VSB_printf(tl->sb, "  Expected %s.",
-					vcc_Type(fmt));
+					vcc_Type(fa->type));
 				VSB_printf(tl->sb, "  Got %s.\n",
 					vcc_Type(e2->fmt));
 				vcc_ErrWhere2(tl, e2->t1, tl->t);
 				return;
 			}
-			assert(e2->fmt == fmt);
+			assert(e2->fmt == fa->type);
 			if (e2->fmt == STRING_LIST) {
 				e2 = vcc_expr_edit(STRING_LIST,
 				    "\v+\n\v1,\nvrt_magic_string_end\v-",
 				    e2, NULL);
 			}
+			fa->result = e2;
 		}
-		e1 = vcc_expr_edit(e1->fmt, "\v1,\n\v2", e1, e2);
-
-		/* XXX: ignore argument name and default value for now */
-		if (*p == '\1') {
-			/* Argument name */
-			p = strchr(p, '\0') + 1;
-			if (*p == '\2') {
-				/* Argument default value */
-				p = strchr(p, '\0') + 1;
-			}
-		}
-		if (*p != '\0')		/*lint !e448 */
+		if (VTAILQ_NEXT(fa, list) != NULL)
 			SkipToken(tl, ',');
 	}
 	SkipToken(tl, ')');
+
+	e1 = vcc_mk_expr(rfmt, "%s(ctx%s\v+", cfunc, extra);
+	VTAILQ_FOREACH_SAFE(fa, &head, list, fa2) {
+		AN(fa->result);
+		e1 = vcc_expr_edit(e1->fmt, "\v1,\n\v2", e1, fa->result);
+		free(fa);
+	}
 	e1 = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL);
 	*e = e1;
 }



More information about the varnish-commit mailing list