[master] c796ea52d Add abi, major and minor to VMOD JSON spec

Poul-Henning Kamp phk at FreeBSD.org
Thu Jun 23 10:37:05 UTC 2022


commit c796ea52d0f3369ec8e53aa8bebbef00fa65c391
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Jun 23 10:00:32 2022 +0000

    Add abi, major and minor to VMOD JSON spec

diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index a9f169d10..a90712f19 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -54,10 +54,14 @@ struct vmod_import {
 	const char		*err;
 	char			*path;
 
+	// From $VMOD
 	double			vmod_syntax;
 	char			*name;
 	char			*func_name;
 	char			*file_id;
+	char			*abi;
+	unsigned		major;
+	unsigned		minor;
 
 	struct symbol		*sym;
 	const struct token	*t_mod;
@@ -102,31 +106,52 @@ vcc_ParseJSON(const struct vcc *tl, const char *jsn, struct vmod_import *vim)
 		return ("Not array[0]");
 
 	vv2 = VTAILQ_FIRST(&vv->children);
+	AN(vv2);
 	if (!vjsn_is_array(vv2))
 		return ("Not array[1]");
 	vv3 = VTAILQ_FIRST(&vv2->children);
+	AN(vv3);
 	if (!vjsn_is_string(vv3))
 		return ("Not string[2]");
 	if (strcmp(vv3->value, "$VMOD"))
 		return ("Not $VMOD[3]");
 
 	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
 	assert(vjsn_is_string(vv3));
 	vim->vmod_syntax = strtod(vv3->value, NULL);
 	assert (vim->vmod_syntax == 1.0);
 
 	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
 	assert(vjsn_is_string(vv3));
 	vim->name = vv3->value;
 
 	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
 	assert(vjsn_is_string(vv3));
 	vim->func_name = vv3->value;
 
 	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
 	assert(vjsn_is_string(vv3));
 	vim->file_id = vv3->value;
 
+	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
+	assert(vjsn_is_string(vv3));
+	vim->abi = vv3->value;
+
+	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
+	assert(vjsn_is_number(vv3));
+	vim->major = atoi(vv3->value);
+
+	vv3 = VTAILQ_NEXT(vv3, list);
+	AN(vv3);
+	assert(vjsn_is_number(vv3));
+	vim->minor = atoi(vv3->value);
+
 	if (!vcc_IdIs(vim->t_mod, vim->name)) {
 		VSB_printf(tl->sb, "Wrong file for VMOD %.*s\n",
 		    PF(vim->t_mod));
@@ -135,6 +160,27 @@ vcc_ParseJSON(const struct vcc *tl, const char *jsn, struct vmod_import *vim)
 		return ("");
 	}
 
+	if (vim->major == 0 && vim->minor == 0 &&
+	    strcmp(vim->abi, VMOD_ABI_Version)) {
+		VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(vim->t_mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", vim->path);
+		VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
+			   VMOD_ABI_Version, vim->abi);
+		return ("");
+	}
+	if (vim->major != 0 &&
+	    (vim->major != VRT_MAJOR_VERSION ||
+	    vim->minor > VRT_MINOR_VERSION)) {
+		VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(vim->t_mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", vim->path);
+		VSB_printf(tl->sb, "\tVMOD wants ABI version %u.%u\n",
+		    vim->major, vim->minor);
+		VSB_printf(tl->sb, "\tvarnishd provides ABI version %u.%u\n",
+		    VRT_MAJOR_VERSION, VRT_MINOR_VERSION);
+		return ("");
+	}
+
+
 	VTAILQ_FOREACH(vv2, &vv->children, list) {
 		assert (vjsn_is_array(vv2));
 		vv3 = VTAILQ_FIRST(&vv2->children);
@@ -204,7 +250,9 @@ vcc_VmodLoad(const struct vcc *tl, struct vmod_import *vim, char *fnp)
 		return (-1);
 	}
 
-	err = vcc_ParseJSON(tl, vmd->json, vim);
+	assert(!memcmp(vmd->json, "VMOD_JSON_SPEC\x03", 15));
+
+	err = vcc_ParseJSON(tl, vmd->json + 15, vim);
 	AZ(dlclose(vim->hdl));
 	vim->hdl = NULL;
 	if (err != NULL && *err != '\0') {
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 1ea7f66be..50e5ab99b 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -639,6 +639,12 @@ class ABIStanza(Stanza):
         if self.vcc.strict_abi is None:
             err("Valid ABI types are 'strict' or 'vrt', got '%s'\n" %
                 self.toks[1])
+        if self.vcc.strict_abi:
+            self.vcc.vrt_major = "0"
+            self.vcc.vrt_minor = "0"
+        else:
+            self.vcc.vrt_major = "VRT_MAJOR_VERSION"
+            self.vcc.vrt_minor = "VRT_MINOR_VERSION"
         self.vcc.contents.append(self)
 
 
@@ -1097,16 +1103,27 @@ class vcc(object):
             yield i + " "
 
     def json(self, fo, fnx):
+        fo.write('#define STRINGIFY(arg) #arg\n')
         fo.write("\nstatic const char Vmod_Json[] = {\n")
+        fo.write('\t"VMOD_JSON_SPEC\\x03"\n')
 
-        for i in self.iter_json(fnx):
+        for n, i in enumerate(self.iter_json(fnx)):
             fo.write('\t"')
             for j in i:
                 if j in '"\\':
                     fo.write('\\')
                 fo.write(j)
-            fo.write('"\n')
+            if n == 6:
+                # Hand-munge the JSON to insert stuff only known by
+                # the C-compiler at compile-time.
+                fo.write(',"\n\t"    \\"" VMOD_ABI_Version "\\", "\n')
+                fo.write('\t    STRINGIFY(%s) ", "\n' % self.vrt_major)
+                fo.write('\t    STRINGIFY(%s)\n' % self.vrt_minor)
+            else:
+                fo.write('"\n')
         fo.write('\t\"\\n\"\n};\n')
+        fo.write('#undef STRINGIFY\n')
+
 
     def vmod_data(self, fo):
         vmd = "Vmod_%s_Data" % self.modname
@@ -1115,12 +1132,8 @@ class vcc(object):
             fo.write("/*lint -esym(%d, %s) */\n" % (i, vmd))
         fo.write("\nextern const struct vmod_data %s;\n" % vmd)
         fo.write("\nconst struct vmod_data %s = {\n" % vmd)
-        if self.strict_abi:
-            fo.write("\t.vrt_major =\t0,\n")
-            fo.write("\t.vrt_minor =\t0,\n")
-        else:
-            fo.write("\t.vrt_major =\tVRT_MAJOR_VERSION,\n")
-            fo.write("\t.vrt_minor =\tVRT_MINOR_VERSION,\n")
+        fo.write("\t.vrt_major =\t%s,\n" % self.vrt_major)
+        fo.write("\t.vrt_minor =\t%s,\n" % self.vrt_minor)
         fo.write('\t.name =\t\t"%s",\n' % self.modname)
         fo.write('\t.func =\t\t&%s,\n' % self.csn)
         fo.write('\t.func_len =\tsizeof(%s),\n' % self.csn)
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index a0a11f5b6..846b00d92 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -1087,13 +1087,15 @@ const struct vmod_data Vmod_wrong2_Data = {
 	.func =		foo_struct,
 	.func_len =	sizeof foo_struct,
 	.func_name =	"foo_struct",
-	.json =		"["
+	.json =		"VMOD_JSON_SPEC\x03["
 			    "["
 				"\"$VMOD\""
 				", \"1.0\""
 				", \"wrongN\""
 				", \"foo_struct\""
 				", \"file_id\""
+				", \"abi\""
+				", 0, 0"	// major, minor
 			    "]"
 			"]",
 };
@@ -1106,13 +1108,15 @@ const struct vmod_data Vmod_wrong3_Data = {
 	.func =		foo_struct,
 	.func_len =	sizeof foo_struct,
 	.func_name =	"foo_struct",
-	.json =		"["
+	.json =		"VMOD_JSON_SPEC\x03["
 			    "["
 				"\"$VMOD\""
 				", \"1.0\""
 				", \"wrongN\""
 				", \"foo_struct\""
 				", \"file_id\""
+				", \"abi\""
+				", 0, 0"	// major, minor
 			    "]"
 			    ", [\"$CPROTO\", \"\"]"
 			"]",


More information about the varnish-commit mailing list