[master] 3f3ff59 Change the specification format in the compiled VMOD from our own home-rolled stuff to VJSN in anticipation of more complex specifications in the future.

Poul-Henning Kamp phk at FreeBSD.org
Wed Feb 21 17:01:09 UTC 2018


commit 3f3ff599eeaf1c421d90605d6f40ce9d22e49390
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Feb 21 16:58:49 2018 +0000

    Change the specification format in the compiled VMOD from our own
    home-rolled stuff to VJSN in anticipation of more complex
    specifications in the future.

diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c
index 658e3ba..4e11ce5 100644
--- a/bin/varnishd/cache/cache_vrt_vmod.c
+++ b/bin/varnishd/cache/cache_vrt_vmod.c
@@ -128,7 +128,7 @@ VRT_Vmod_Init(VRT_CTX, struct vmod **hdl, void *ptr, int len, const char *nm,
 		    d->func == NULL ||
 		    d->func_len <= 0 ||
 		    d->proto == NULL ||
-		    d->spec == NULL) {
+		    d->json == NULL) {
 			VSB_printf(ctx->msg,
 			    "Loading VMOD %s from %s:\n", nm, path);
 			VSB_printf(ctx->msg, "VMOD data is mangled.\n");
diff --git a/include/vrt.h b/include/vrt.h
index c2dab1e..4822b9f 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -209,7 +209,7 @@ struct vmod_data {
 	const void			*func;
 	int				func_len;
 	const char			*proto;
-	const char			* const *spec;
+	const char			*json;
 	const char			*abi;
 };
 
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 7ae776c..696aa6a 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -71,6 +71,7 @@ struct acl_e;
 struct proc;
 struct expr;
 struct vcc;
+struct vjsn_val;
 struct symbol;
 
 struct source {
@@ -308,8 +309,8 @@ void vcc_Expr_Init(struct vcc *tl);
 sym_expr_t vcc_Eval_Var;
 sym_expr_t vcc_Eval_Handle;
 sym_expr_t vcc_Eval_SymFunc;
-void vcc_Eval_Func(struct vcc *tl, const char *spec,
-    const char *extra, const struct symbol *sym);
+void vcc_Eval_Func(struct vcc *, const struct vjsn_val *,
+    const char *, const struct symbol *);
 void VCC_GlobalSymbol(struct symbol *, vcc_type_t fmt, const char *pfx);
 struct symbol *VCC_HandleSymbol(struct vcc *, vcc_type_t , const char *);
 
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index f8e5d90..2191d4b 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -36,6 +36,7 @@
 #include <string.h>
 
 #include "vcc_compile.h"
+#include "vjsn.h"
 
 struct expr {
 	unsigned	magic;
@@ -400,7 +401,7 @@ vcc_priv_arg(struct vcc *tl, const char *p, const char *name, const char *vmod)
 
 struct func_arg {
 	vcc_type_t		type;
-	const char		*enum_bits;
+	const struct vjsn_val	*enums;
 	const char		*cname;
 	const char		*name;
 	const char		*val;
@@ -423,25 +424,20 @@ vcc_do_enum(struct vcc *tl, struct func_arg *fa, int len, const char *ptr)
 static void
 vcc_do_arg(struct vcc *tl, struct func_arg *fa)
 {
-	const char *p, *r;
 	struct expr *e2;
+	struct vjsn_val *vv;
 
 	if (fa->type == ENUM) {
 		ExpectErr(tl, ID);
 		ERRCHK(tl);
-		r = p = fa->enum_bits;
-		do {
-			if (vcc_IdIs(tl->t, p))
+		VTAILQ_FOREACH(vv, &fa->enums->children, list)
+			if (vcc_IdIs(tl->t, vv->value))
 				break;
-			p += strlen(p) + 1;
-		} while (*p != '\1');
-		if (*p == '\1') {
+		if (vv == NULL) {
 			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' && *r != '\1');
+			VTAILQ_FOREACH(vv, &fa->enums->children, list)
+				VSB_printf(tl->sb, "\t%s\n", vv->value);
 			vcc_ErrWhere(tl, tl->t);
 			return;
 		}
@@ -456,60 +452,59 @@ vcc_do_arg(struct vcc *tl, struct func_arg *fa)
 }
 
 static void
-vcc_func(struct vcc *tl, struct expr **e, const char *spec,
+vcc_func(struct vcc *tl, struct expr **e, const void *priv,
     const char *extra, const struct symbol *sym)
 {
 	vcc_type_t rfmt;
-	const char *args;
 	const char *cfunc;
-	const char *p;
 	struct expr *e1;
 	struct func_arg *fa, *fa2;
 	VTAILQ_HEAD(,func_arg) head;
 	struct token *t1;
+	const struct vjsn_val *vv, *vvp;
 
-	rfmt = VCC_Type(spec);
-	spec += strlen(spec) + 1;
-	cfunc = spec;
-	spec += strlen(spec) + 1;
-	args = spec;
+	CAST_OBJ_NOTNULL(vv, priv, VJSN_VAL_MAGIC);
+	assert(vv->type == VJSN_ARRAY);
+	vv = VTAILQ_FIRST(&vv->children);
+	rfmt = VCC_Type(VTAILQ_FIRST(&vv->children)->value);
+	AN(rfmt);
+	vv = VTAILQ_NEXT(vv, list);
+	cfunc = vv->value;
+	vv = VTAILQ_NEXT(vv, list);
 	SkipToken(tl, '(');
-	p = args;
 	if (extra == NULL)
 		extra = "";
-	AN(rfmt);
 	VTAILQ_INIT(&head);
-	while (*p != '\0') {
+	for(;vv != NULL; vv = VTAILQ_NEXT(vv, list)) {
+		assert(vv->type == VJSN_ARRAY);
 		fa = calloc(1, sizeof *fa);
 		AN(fa);
 		fa->cname = cfunc;
 		VTAILQ_INSERT_TAIL(&head, fa, list);
-		if (!memcmp(p, "PRIV_", 5)) {
-			fa->result = vcc_priv_arg(tl, p, sym->name, sym->vmod);
+
+		vvp = VTAILQ_FIRST(&vv->children);
+		if (!memcmp(vvp->value, "PRIV_", 5)) {
+			fa->result = vcc_priv_arg(tl, vvp->value,
+			    sym->name, sym->vmod);
 			fa->name = "";
-			p += strlen(p) + 1;
 			continue;
 		}
-		fa->type = VCC_Type(p);
+		fa->type = VCC_Type(vvp->value);
 		AN(fa->type);
-		p += strlen(p) + 1;
-		if (*p == '\1') {
-			fa->enum_bits = ++p;
-			while (*p != '\1')
-				p += strlen(p) + 1;
-			p++;
-			assert(*p == '\0');
-			p++;
-		}
-		if (*p == '\2') {
-			fa->name = p + 1;
-			p += strlen(p) + 1;
-		}
-		if (*p == '\3') {
-			fa->val = p + 1;
-			p += strlen(p) + 1;
+		vvp = VTAILQ_NEXT(vvp, list);
+		if (vvp != NULL) {
+			fa->name = vvp->value;
+			vvp = VTAILQ_NEXT(vvp, list);
+			if (vvp != NULL) {
+				fa->val = vvp->value;
+				vvp = VTAILQ_NEXT(vvp, list);
+				if (vvp != NULL) {
+					fa->enums = vvp;
+					vvp = VTAILQ_NEXT(vvp, list);
+				}
+			}
 		}
-		assert(*p == 0 || *p > ' ');
+		AZ(vvp);
 	}
 
 	VTAILQ_FOREACH(fa, &head, list) {
@@ -576,11 +571,12 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec,
 	SkipToken(tl, ')');
 }
 
+
 /*--------------------------------------------------------------------
  */
 
 void
-vcc_Eval_Func(struct vcc *tl, const char *spec,
+vcc_Eval_Func(struct vcc *tl, const struct vjsn_val *spec,
     const char *extra, const struct symbol *sym)
 {
 	struct expr *e = NULL;
@@ -605,7 +601,6 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, struct token *t,
 	assert(sym->kind == SYM_FUNC);
 	AN(sym->eval_priv);
 
-	// assert(sym->fmt == VCC_Type(sym->eval_priv));
 	vcc_func(tl, e, sym->eval_priv, sym->extra, sym);
 	ERRCHK(tl);
 	if ((*e)->fmt == STRING) {
@@ -1261,7 +1256,7 @@ vcc_Act_Call(struct vcc *tl, struct token *t, struct symbol *sym)
 	struct expr *e;
 
 	e = NULL;
-	vcc_Eval_SymFunc(tl, &e, t, sym, VOID);
+	vcc_func(tl, &e, sym->eval_priv, sym->extra, sym);
 	if (!tl->err) {
 		vcc_expr_fmt(tl->fb, tl->indent, e);
 		SkipToken(tl, ';');
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index 6b6969d..fe9253d 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -36,6 +36,7 @@
 
 #include "libvcc.h"
 #include "vfil.h"
+#include "vjsn.h"
 #include "vmod_abi.h"
 
 static int
@@ -54,18 +55,97 @@ vcc_path_dlopen(void *priv, const char *fn)
 	return (0);
 }
 
+static void
+func_sym(struct symbol *sym, const char *vmod, const struct vjsn_val *v)
+{
+
+	assert(v->type == VJSN_ARRAY);
+	sym->action = vcc_Act_Call;
+	sym->vmod = vmod;
+	sym->eval = vcc_Eval_SymFunc;
+	sym->eval_priv = v;
+	v = VTAILQ_FIRST(&v->children);
+	assert(v->type == VJSN_ARRAY);
+	v = VTAILQ_FIRST(&v->children);
+	assert(v->type == VJSN_STRING);
+	sym->type = VCC_Type(v->value);
+	AN(sym->type);
+}
+
+static void
+parse_json(struct vcc * tl, const char *vmod, const char *json)
+{
+	struct inifin *ifp;
+	struct vjsn *vj;
+	struct vjsn_val *vv, *vv2;
+	double vmod_syntax = 0.0;
+	const char *p;
+	struct symbol *sym;
+
+	ifp = NULL;
+
+	vj = vjsn_parse(json, &p);
+	XXXAZ(p);
+	AN(vj);
+
+	VTAILQ_FOREACH(vv, &vj->value->children, list) {
+		assert(vv->type == VJSN_ARRAY);
+		vv2 = VTAILQ_FIRST(&vv->children);
+		assert(vv2->type == VJSN_STRING);
+		if (!strcmp(vv2->value, "$VMOD")) {
+			vmod_syntax =
+			    strtod(VTAILQ_NEXT(vv2, list)->value, NULL);
+			continue;
+		}
+		assert (vmod_syntax == 1.0);
+		if (!strcmp(vv2->value, "$EVENT")) {
+			/* XXX: What about the rest of the events ? */
+			if (ifp == NULL)
+				ifp = New_IniFin(tl);
+			vv2 = VTAILQ_NEXT(vv2, list);
+			VSB_printf(ifp->ini,
+			    "\tif (%s(ctx, &vmod_priv_%s, VCL_EVENT_LOAD))\n"
+			    "\t\treturn(1);",
+			    vv2->value, vmod);
+			VSB_printf(ifp->fin,
+			    "\t\t(void)%s(ctx, &vmod_priv_%s,\n"
+			    "\t\t\t    VCL_EVENT_DISCARD);\n",
+			    vv2->value, vmod);
+			VSB_printf(ifp->event, "%s(ctx, &vmod_priv_%s, ev)",
+			    vv2->value, vmod);
+		} else if (!strcmp(vv2->value, "$FUNC")) {
+			vv2 = VTAILQ_NEXT(vv2, list);
+			sym = VCC_MkSym(tl,
+			    vv2->value, SYM_FUNC, VCL_LOW, VCL_HIGH);
+			ERRCHK(tl);
+			AN(sym);
+			func_sym(sym, vmod, VTAILQ_NEXT(vv2, list));
+		} else if (!strcmp(vv2->value, "$OBJ")) {
+			vv2 = VTAILQ_NEXT(vv2, list);
+			sym = VCC_MkSym(tl, vv2->value,
+			    SYM_OBJECT, VCL_LOW, VCL_HIGH);
+			XXXAN(sym);
+			sym->eval_priv = vv2;
+			sym->vmod = vmod;
+		} else {
+			VTAILQ_FOREACH(vv2, &vv->children, list)
+				fprintf(stderr, "\tt %s n %s v %s\n",
+				    vv2->type, vv2->name, vv2->value);
+			WRONG("Vmod JSON syntax error");
+		}
+	}
+}
+
 void
 vcc_ParseImport(struct vcc *tl)
 {
 	void *hdl;
 	char fn[1024], *fnp, *fnpx;
 	char buf[256];
+	const char *p;
 	struct token *mod, *t1;
 	struct inifin *ifp;
-	const char * const *spec;
-	struct symbol *sym;
 	struct symbol *msym;
-	const char *p;
 	const struct vmod_data *vmd;
 
 	t1 = tl->t;
@@ -216,48 +296,7 @@ vcc_ParseImport(struct vcc *tl)
 	VSB_printf(ifp->fin, "\t\tVRT_priv_fini(&vmod_priv_%.*s);\n", PF(mod));
 	VSB_printf(ifp->fin, "\t\t\tVRT_Vmod_Fini(&VGC_vmod_%.*s);", PF(mod));
 
-	ifp = NULL;
-
-	spec = vmd->spec;
-	for (; *spec != NULL; spec++) {
-		p = *spec;
-		if (!strcmp(p, "$OBJ")) {
-			p += strlen(p) + 1;
-			sym = VCC_MkSym(tl, p, SYM_OBJECT, VCL_LOW, VCL_HIGH);
-			XXXAN(sym);
-			sym->extra = p;
-			sym->vmod = msym->name;
-		} else if (!strcmp(p, "$EVENT")) {
-			p += strlen(p) + 1;
-			if (ifp == NULL)
-				ifp = New_IniFin(tl);
-			VSB_printf(ifp->ini,
-			    "\tif (%s(ctx, &vmod_priv_%.*s, VCL_EVENT_LOAD))\n"
-			    "\t\treturn(1);",
-			    p, PF(mod));
-			VSB_printf(ifp->fin,
-			    "\t\t(void)%s(ctx, &vmod_priv_%.*s,\n"
-			    "\t\t\t    VCL_EVENT_DISCARD);\n", p, PF(mod));
-			VSB_printf(ifp->event, "%s(ctx, &vmod_priv_%.*s, ev)",
-			    p, PF(mod));
-		} else if (!strcmp(p, "$FUNC")) {
-			p += strlen(p) + 1;
-			sym = VCC_MkSym(tl, p, SYM_FUNC, VCL_LOW, VCL_HIGH);
-			ERRCHK(tl);
-			AN(sym);
-			sym->action = vcc_Act_Call;
-			sym->vmod = msym->name;
-			sym->eval = vcc_Eval_SymFunc;
-			p += strlen(p) + 1;
-			sym->eval_priv = p;
-			sym->type = VCC_Type(p);
-			AN(sym->type);
-		} else {
-			VSB_printf(tl->sb, "Internal spec error (%s)\n", p);
-			vcc_ErrWhere(tl, mod);
-			return;
-		}
-	}
+	parse_json(tl, msym->name, vmd->json);
 
 	Fh(tl, 0, "\n/* --- BEGIN VMOD %.*s --- */\n\n", PF(mod));
 	Fh(tl, 0, "static struct vmod *VGC_vmod_%.*s;\n", PF(mod));
@@ -271,9 +310,11 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
 {
 	struct symbol *sy1, *sy2, *sy3;
 	struct inifin *ifp;
-	const char *p, *s_obj;
+	const char *s_obj;
 	char buf1[128];
 	char buf2[128];
+	const struct vjsn_val *vv, *vf;
+	const char *p;
 
 	(void)sym;
 	ExpectErr(tl, ID);
@@ -292,7 +333,7 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
 	sy2 = VCC_SymbolGet(tl, SYM_OBJECT, "Symbol not found", XREF_NONE);
 	ERRCHK(tl);
 	AN(sy2);
-	if (sy2->extra == NULL) {
+	if (sy2->eval_priv == NULL) {
 		VSB_printf(tl->sb, "Constructor not found: ");
 		vcc_ErrToken(tl, t);
 		VSB_printf(tl->sb, " at ");
@@ -300,49 +341,53 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
 		return;
 	}
 
-	p = sy2->extra;
-	AN(p);
+	CAST_OBJ_NOTNULL(vv, sy2->eval_priv, VJSN_VAL_MAGIC);
+
+	s_obj = vv->value;
+	vv = VTAILQ_NEXT(vv, list);
+
+	Fh(tl, 0, "static %s *%s;\n\n", vv->value, sy1->rname);
+	vv = VTAILQ_NEXT(vv, list);
 
-	s_obj = p;
-	p += strlen(p) + 1;
+	vf = VTAILQ_FIRST(&vv->children);
+	vv = VTAILQ_NEXT(vv, list);
+	assert(vf->type == VJSN_STRING);
+	assert(!strcmp(vf->value, "$INIT"));
 
-	Fh(tl, 0, "static %s *%s;\n\n", p, sy1->rname);
-	p += strlen(p) + 1;
+	vf = VTAILQ_NEXT(vf, list);
 
 	bprintf(buf1, ", &%s, \"%s\"", sy1->rname, sy1->name);
-	vcc_Eval_Func(tl, p, buf1, sy2);
+	vcc_Eval_Func(tl, vf, buf1, sy2);
 	ERRCHK(tl);
 	SkipToken(tl, ';');
+	sy1->def_e = tl->t;
 
-	while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0')
-		p++;
-	p += 3;
+	vf = VTAILQ_FIRST(&vv->children);
+	vv = VTAILQ_NEXT(vv, list);
+	assert(vf->type == VJSN_STRING);
+	assert(!strcmp(vf->value, "$FINI"));
 
+	vf = VTAILQ_NEXT(vf, list);
+	vf = VTAILQ_FIRST(&vf->children);
+	vf = VTAILQ_NEXT(vf, list);
 	ifp = New_IniFin(tl);
-	p += strlen(p) + 1;
-	VSB_printf(ifp->fin, "\t\t%s(&%s);", p, sy1->rname);
-
-	while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0')
-		p++;
-	p += 3;
+	VSB_printf(ifp->fin, "\t\t%s(&%s);", vf->value, sy1->rname);
 
 	/* Instantiate symbols for the methods */
 	bprintf(buf1, ", %s", sy1->rname);
-	while (*p != '\0') {
-		p += strlen(s_obj);
-		bprintf(buf2, "%s%s", sy1->name, p);
+	p = TlDup(tl, buf1);
+	while (vv != NULL) {
+		vf = VTAILQ_FIRST(&vv->children);
+		assert(vf->type == VJSN_STRING);
+		assert(!strcmp(vf->value, "$METHOD"));
+		vf = VTAILQ_NEXT(vf, list);
+		assert(vf->type == VJSN_STRING);
+
+		bprintf(buf2, "%s%s", sy1->name, vf->value + strlen(s_obj));
 		sy3 = VCC_MkSym(tl, buf2, SYM_FUNC, VCL_LOW, VCL_HIGH);
 		AN(sy3);
-		sy3->action = vcc_Act_Call;
-		sy3->eval = vcc_Eval_SymFunc;
-		p += strlen(p) + 1;
-		sy3->eval_priv = p;
-		sy3->type = VCC_Type(p);
-		sy3->extra = TlDup(tl, buf1);
-		sy3->vmod = sy2->vmod;
-		while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0')
-			p++;
-		p += 3;
+		func_sym(sy3, sy2->vmod, VTAILQ_NEXT(vf, list));
+		sy3->extra = p;
+		vv = VTAILQ_NEXT(vv, list);
 	}
-	sy1->def_e = tl->t;
 }
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index dad08a8..b5ea510 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -43,6 +43,7 @@ import optparse
 import unittest
 import random
 import copy
+import json
 
 rstfmt = False
 strict_abi = True
@@ -227,24 +228,10 @@ class ctype(object):
             return self.vt
         return self.vt + " {" + ",".join(self.spec) + "}"
 
-    def specstr(self, fo, p):
-        fo.write(p + '"' + self.vt)
-        fo.write('\\0"\n')
-        p = indent(p, 4)
-        if self.spec is not None:
-            fo.write(p + '"\\1"\n')
-            p = indent(p, 4)
-            for i in self.spec:
-                fo.write(p + '"' + i + '\\0"\n')
-            p = indent(p, -4)
-            # This terminating \1 is necessary to ensure that
-            # a prototype always ends with three \0's
-            fo.write(p + '"\\1\\0"\n')
-        if self.nm is not None:
-            fo.write(p + '"\\2" "' + self.nm + '\\0"\n')
-        if self.defval is not None:
-            fo.write(p + '"\\3" "' + quote(self.defval) + '\\0"\n')
-
+    def json(self, jl):
+        jl.append([self.vt, self.nm, self.defval, self.spec])
+        while jl[-1][-1] is None:
+                jl[-1].pop(-1)
 
 def vtype(txt):
     j = len(txt)
@@ -404,17 +391,13 @@ class prototype(object):
         s += '%s %s(%s);' % (self.c_ret(), fn, self.c_args(args))
         return "\n".join(lwrap(s)) + "\n"
 
-    def specstr(self, fo, cfunc, p):
-        if self.retval is None:
-            fo.write(p + '"VOID\\0"\n')
-        else:
-            self.retval.specstr(fo, p)
-        fo.write(p + '"' + cfunc + '\\0"\n')
-        p = indent(p, 4)
-        if self.args is not None:
-            for i in self.args:
-                i.specstr(fo, p)
-        fo.write(p + '"\\0"\n')
+    def json(self, jl, cfunc):
+        ll = []
+        self.retval.json(ll)
+        ll.append(cfunc)
+        for i in self.args:
+                i.json(ll)
+        jl.append(ll)
 
 #######################################################################
 
@@ -469,7 +452,7 @@ class stanza(object):
     def cstruct_init(self, fo):
         return
 
-    def specstr(self, fo):
+    def json(self, jl):
         return
 
 #######################################################################
@@ -568,10 +551,11 @@ class s_event(stanza):
     def cstruct_init(self, fo):
         fo.write("\t%s,\n" % self.event_func)
 
-    def specstr(self, fo):
-        fo.write('\t"$EVENT\\0"\n\t    "Vmod_%s_Func._event",\n\n' %
-                 self.vcc.modname)
-
+    def json(self, jl):
+        jl.append([
+                "$EVENT",
+                "Vmod_%s_Func._event" % self.vcc.modname
+        ])
 
 class s_function(stanza):
     def parse(self):
@@ -591,12 +575,13 @@ class s_function(stanza):
     def cstruct_init(self, fo):
         fo.write("\t" + self.proto.cname(pfx=True) + ",\n")
 
-    def specstr(self, fo):
-        fo.write('\t"$FUNC\\0"\t"%s.%s\\0"\n\n' %
-                 (self.vcc.modname, self.proto.name))
-        self.proto.specstr(fo, 'Vmod_%s_Func.%s' %
-                           (self.vcc.modname, self.proto.cname()), "\t    ")
-        fo.write('\t    "\\0",\n\n')
+    def json(self,jl):
+        jl.append([
+                "$FUNC",
+                "%s.%s" % (self.vcc.modname, self.proto.name),
+        ])
+        self.proto.json(jl[-1], 'Vmod_%s_Func.%s' %
+                           (self.vcc.modname, self.proto.cname()))
 
 
 class s_object(stanza):
@@ -663,29 +648,29 @@ class s_object(stanza):
             i.cstruct_init(fo)
         fo.write("\n")
 
-    def specstr(self, fo):
+    def json(self, jl):
+        ll = [
+                "$OBJ",
+                self.vcc.modname + "." + self.proto.name,
+                "struct %s%s_%s" %
+                    (self.vcc.sympfx, self.vcc.modname, self.proto.name),
+        ]
 
-        fo.write('\t"$OBJ\\0"\t"%s.%s\\0"\n\n' %
-                 (self.vcc.modname, self.proto.name))
+        l2 = [ "$INIT" ]
+        ll.append(l2)
+        self.init.json(l2,
+            'Vmod_%s_Func.%s' % (self.vcc.modname, self.init.name))
 
-        fo.write('\t    "struct %s%s_%s\\0"\n' %
-                 (self.vcc.sympfx, self.vcc.modname, self.proto.name))
-        fo.write("\n")
-
-        self.proto.specstr(fo, 'Vmod_%s_Func.%s' %
-                           (self.vcc.modname, self.init.name), '\t    ')
-        fo.write('\t    "\\0"\n\n')
-
-        fo.write('\t    "VOID\\0"\n')
-        fo.write('\t    "Vmod_%s_Func.%s\\0"\n' %
-                 (self.vcc.modname, self.fini.name))
-        fo.write('\t\t"\\0"\n')
-        fo.write('\t    "\\0"\n\n')
+        l2 = [ "$FINI" ]
+        ll.append(l2)
+        self.fini.json(l2,
+            'Vmod_%s_Func.%s' % (self.vcc.modname, self.fini.name))
 
         for i in self.methods:
-            i.specstr(fo)
+                i.json(ll)
+
+        jl.append(ll)
 
-        fo.write('\t    "\\0",\n\n')
 
     def dump(self):
         super(s_object, self).dump()
@@ -707,12 +692,14 @@ class s_method(stanza):
     def cstruct_init(self, fo):
         fo.write('\t' + self.proto.cname(pfx=True) + ",\n")
 
-    def specstr(self, fo):
-        fo.write('\t    "%s.%s\\0"\n' %
-                 (self.vcc.modname, self.proto.name))
-        self.proto.specstr(fo, 'Vmod_%s_Func.%s' %
-                           (self.vcc.modname, self.proto.cname()), '\t\t')
-        fo.write('\t\t"\\0"\n\n')
+    def json(self, jl):
+        jl.append([
+                "$METHOD",
+                self.vcc.modname + "." + self.proto.name
+        ])
+        self.proto.json(jl[-1],
+            'Vmod_%s_Func.%s' % (self.vcc.modname, self.proto.cname()))
+
 
 #######################################################################
 
@@ -836,15 +823,29 @@ class vcc(object):
             fo.write("\t&%senum_%s,\n" % (self.sympfx, j))
         fo.write("};\n")
 
-    def specstr(self, fo):
-        fo.write("\n/*lint -save -e786 -e840 */\n")
-        fo.write("static const char * const Vmod_Spec[] = {\n")
-
+    def json(self, fo):
+        jl = [ ["$VMOD", "1.0" ] ]
         for j in self.contents:
-            j.specstr(fo)
-        fo.write("\t0\n")
-        fo.write("};\n")
-        fo.write("/*lint -restore */\n")
+                j.json(jl)
+
+        bz = bytearray(json.dumps(jl, separators=(",",":"))) + "\0"
+        fo.write("\nstatic const char Vmod_Json[%d] = {\n" % len(bz))
+        t = "\t"
+        for i in bz:
+                t += "%d," % i
+                if len(t) >= 69:
+                        fo.write(t + "\n")
+                        t = "\t"
+        if len(t) > 1:
+                fo.write(t[:-1])
+        fo.write("\n};\n\n")
+        for i in json.dumps(jl, indent=2, separators=(',', ': ')).split("\n"):
+                j = "// " + i
+                if len(j) > 72:
+                        fo.write(j[:72] + "[...]\n")
+                else:
+                        fo.write(j + "\n")
+        fo.write("\n")
 
     def api(self, fo):
         for i in (714, 759, 765):
@@ -863,7 +864,7 @@ class vcc(object):
         fo.write('\t.func =\t\t&Vmod_Func,\n')
         fo.write('\t.func_len =\tsizeof(Vmod_Func),\n')
         fo.write('\t.proto =\tVmod_Proto,\n')
-        fo.write('\t.spec =\t\tVmod_Spec,\n')
+        fo.write('\t.json =\t\tVmod_Json,\n')
         fo.write('\t.abi =\t\tVMOD_ABI_Version,\n')
         # NB: Sort of hackish:
         # Fill file_id with random stuff, so we can tell if
@@ -927,7 +928,7 @@ class vcc(object):
 
         os.remove(fn2)
 
-        self.specstr(fo)
+        self.json(fo)
 
         self.api(fo)
 


More information about the varnish-commit mailing list