[master] 419fbadef More rework of VCC-VMOD code.
Poul-Henning Kamp
phk at FreeBSD.org
Thu Jun 23 08:32:05 UTC 2022
commit 419fbadefa200830e0f5eba5a29c342ab3d22aad
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu Jun 23 08:30:25 2022 +0000
More rework of VCC-VMOD code.
diff --git a/include/vrt.h b/include/vrt.h
index 975149322..c4afdc6b6 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -58,7 +58,7 @@
* binary/load-time compatible, increment MAJOR version
*
* NEXT (2022-09-15)
- * C-prototypes moved into JSON
+ * VMOD C-prototypes moved into JSON
* VRT_AddVDP() deprecated
* VRT_AddVFP() deprecated
* VRT_RemoveVDP() deprecated
diff --git a/lib/libvcc/Makefile.am b/lib/libvcc/Makefile.am
index 8731890da..117f38a3c 100644
--- a/lib/libvcc/Makefile.am
+++ b/lib/libvcc/Makefile.am
@@ -30,6 +30,8 @@ libvcc_la_SOURCES = \
vcc_utils.c \
vcc_var.c \
vcc_vmod.c \
+ vcc_vmod.h \
+ vcc_vmod_sym.c \
vcc_xref.c
dist_noinst_SCRIPTS = \
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 1663ba92d..d697d3381 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -194,6 +194,9 @@ struct symbol {
const char *extra;
+ /* vcc_vmod.c */
+ const struct vmod_import *import;
+
/* SYM_VAR */
const char *rname;
unsigned r_methods;
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index db79a5aac..a9f169d10 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -26,6 +26,9 @@
* 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.
+ *
+ * Parse `import`, check metadata and versioning.
+ *
*/
#include "config.h"
@@ -42,22 +45,31 @@
#include "vmod_abi.h"
#include "vsb.h"
+#include "vcc_vmod.h"
+
struct vmod_import {
unsigned magic;
#define VMOD_IMPORT_MAGIC 0x31803a5d
void *hdl;
const char *err;
- const struct vmod_data *vmd;
-};
+ char *path;
-struct vmod_obj {
- unsigned magic;
-#define VMOD_OBJ_MAGIC 0x349885f8
+ double vmod_syntax;
char *name;
- struct type type[1];
- VTAILQ_ENTRY(vmod_obj) list;
+ char *func_name;
+ char *file_id;
+
+ struct symbol *sym;
+ const struct token *t_mod;
+ struct vjsn *vj;
+#define STANZA(UU, ll, ss) int n_##ll;
+ STANZA_TBL
+#undef STANZA
};
+typedef void vcc_do_stanza_f(struct vcc *tl, const struct vmod_import *vim,
+ const struct vjsn_val *vv);
+
static int
vcc_path_dlopen(void *priv, const char *fn)
{
@@ -74,178 +86,111 @@ vcc_path_dlopen(void *priv, const char *fn)
return (0);
}
-static void vcc_VmodObject(struct vcc *tl, struct symbol *sym);
-static void vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym);
-
-static void
-alias_sym(struct vcc *tl, const struct symbol *psym, const struct vjsn_val *v)
+static const char *
+vcc_ParseJSON(const struct vcc *tl, const char *jsn, struct vmod_import *vim)
{
- char *alias = NULL, *func = NULL;
- struct symbol *sym;
- struct vsb *buf;
-
- buf = VSB_new_auto();
- AN(buf);
-
- VCC_SymName(buf, psym);
- VSB_printf(buf, ".%s", v->value);
- AZ(VSB_finish(buf));
- REPLACE(alias, VSB_data(buf));
-
- v = VTAILQ_NEXT(v, list);
- assert(vjsn_is_string(v));
-
- VSB_clear(buf);
- VCC_SymName(buf, psym);
- VSB_printf(buf, ".%s", v->value);
- AZ(VSB_finish(buf));
- REPLACE(func, VSB_data(buf));
-
- sym = VCC_MkSymAlias(tl, alias, func);
- AN(sym);
- assert(sym->kind == SYM_FUNC || sym->kind == SYM_METHOD);
- VSB_destroy(&buf);
- free(alias);
- free(func);
-}
-
-static void
-func_sym(struct vcc *tl, vcc_kind_t kind, const struct symbol *psym,
- const struct vjsn_val *v)
-{
- struct symbol *sym;
- struct vsb *buf;
-
- if (kind == SYM_ALIAS) {
- alias_sym(tl, psym, v);
- return;
+ const struct vjsn_val *vv, *vv2, *vv3;
+ const char *err;
+
+ vim->vj = vjsn_parse(jsn, &err);
+ if (err != NULL)
+ return (err);
+ AN(vim->vj);
+
+ vv = vim->vj->value;
+ if (!vjsn_is_array(vv))
+ return ("Not array[0]");
+
+ vv2 = VTAILQ_FIRST(&vv->children);
+ if (!vjsn_is_array(vv2))
+ return ("Not array[1]");
+ vv3 = VTAILQ_FIRST(&vv2->children);
+ if (!vjsn_is_string(vv3))
+ return ("Not string[2]");
+ if (strcmp(vv3->value, "$VMOD"))
+ return ("Not $VMOD[3]");
+
+ vv3 = VTAILQ_NEXT(vv3, list);
+ assert(vjsn_is_string(vv3));
+ vim->vmod_syntax = strtod(vv3->value, NULL);
+ assert (vim->vmod_syntax == 1.0);
+
+ vv3 = VTAILQ_NEXT(vv3, list);
+ assert(vjsn_is_string(vv3));
+ vim->name = vv3->value;
+
+ vv3 = VTAILQ_NEXT(vv3, list);
+ assert(vjsn_is_string(vv3));
+ vim->func_name = vv3->value;
+
+ vv3 = VTAILQ_NEXT(vv3, list);
+ assert(vjsn_is_string(vv3));
+ vim->file_id = vv3->value;
+
+ if (!vcc_IdIs(vim->t_mod, vim->name)) {
+ VSB_printf(tl->sb, "Wrong file for VMOD %.*s\n",
+ PF(vim->t_mod));
+ VSB_printf(tl->sb, "\tFile name: %s\n", vim->path);
+ VSB_printf(tl->sb, "\tContains vmod \"%s\"\n", vim->name);
+ return ("");
}
- buf = VSB_new_auto();
- AN(buf);
-
- VCC_SymName(buf, psym);
- VSB_printf(buf, ".%s", v->value);
- AZ(VSB_finish(buf));
- sym = VCC_MkSym(tl, VSB_data(buf), SYM_MAIN, kind, VCL_LOW, VCL_HIGH);
- AN(sym);
- VSB_destroy(&buf);
-
- if (kind == SYM_OBJECT) {
- sym->eval_priv = v;
- sym->vmod_name = psym->vmod_name;
- sym->r_methods = VCL_MET_INIT;
- vcc_VmodObject(tl, sym);
- vcc_VmodSymbols(tl, sym);
- return;
+ VTAILQ_FOREACH(vv2, &vv->children, list) {
+ assert (vjsn_is_array(vv2));
+ vv3 = VTAILQ_FIRST(&vv2->children);
+ assert(vjsn_is_string(vv3));
+ assert(vv3->value[0] == '$');
+#define STANZA(UU, ll, ss) \
+ if (!strcmp(vv3->value, "$" #UU)) {vim->n_##ll++; continue;}
+ STANZA_TBL
+#undef STANZA
+ return ("Unknown entry");
}
-
- if (kind == SYM_METHOD)
- sym->extra = psym->rname;
-
- v = VTAILQ_NEXT(v, list);
-
- assert(vjsn_is_array(v));
- sym->action = vcc_Act_Call;
- sym->vmod_name = psym->vmod_name;
- sym->eval = vcc_Eval_SymFunc;
- sym->eval_priv = v;
- v = VTAILQ_FIRST(&v->children);
- assert(vjsn_is_array(v));
- v = VTAILQ_FIRST(&v->children);
- assert(vjsn_is_string(v));
- sym->type = VCC_Type(v->value);
- AN(sym->type);
- sym->r_methods = VCL_MET_TASK_ALL;
+ if (vim->n_cproto != 1)
+ return ("Bad cproto stanza(s)");
+ if (vim->n_vmod != 1)
+ return ("Bad vmod stanza(s)");
+ return (NULL);
}
-static void
-vcc_json_always(struct vcc *tl, const struct vjsn *vj, const char *vmod_name)
-{
- struct inifin *ifp;
- const struct vjsn_val *vv, *vv2;
- double vmod_syntax = 0.0;
- int cproto_seen = 0;
-
- AN(vj);
- AN(vmod_name);
- ifp = NULL;
-
- VTAILQ_FOREACH(vv, &vj->value->children, list) {
- assert(vjsn_is_array(vv));
- vv2 = VTAILQ_FIRST(&vv->children);
- assert(vjsn_is_string(vv2));
- 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_name);
- VSB_printf(ifp->fin,
- "\t\t(void)%s(ctx, &vmod_priv_%s,\n"
- "\t\t\t VCL_EVENT_DISCARD);",
- vv2->value, vmod_name);
- VSB_printf(ifp->event, "%s(ctx, &vmod_priv_%s, ev)",
- vv2->value, vmod_name);
- } else if (!strcmp(vv2->value, "$ALIAS")) {
- } else if (!strcmp(vv2->value, "$FUNC")) {
- } else if (!strcmp(vv2->value, "$OBJ")) {
- } else if (!strcmp(vv2->value, "$CPROTO")) {
- cproto_seen = 1;
- } 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");
- }
- }
- if (!cproto_seen)
- WRONG("Vmod JSON has no CPROTO");
-}
+/*
+ * Load and check the metadata from the objectfile containing the vmod
+ */
-static const struct vmod_data *
-vcc_VmodSanity(struct vcc *tl, void *hdl, const struct token *mod, char *fnp)
+static int
+vcc_VmodLoad(const struct vcc *tl, struct vmod_import *vim, char *fnp)
{
char buf[256];
+ static const char *err;
const struct vmod_data *vmd;
- bprintf(buf, "Vmod_%.*s_Data", PF(mod));
- vmd = dlsym(hdl, buf);
+ CHECK_OBJ_NOTNULL(vim, VMOD_IMPORT_MAGIC);
+ bprintf(buf, "Vmod_%.*s_Data", PF(vim->t_mod));
+ vmd = dlsym(vim->hdl, buf);
if (vmd == NULL) {
- VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(mod));
+ VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(vim->t_mod));
VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
VSB_cat(tl->sb, "\t(no Vmod_Data symbol)\n");
- vcc_ErrWhere(tl, mod);
- return (NULL);
+ return (-1);
}
if (vmd->vrt_major == 0 && vmd->vrt_minor == 0 &&
- (vmd->abi == NULL || strcmp(vmd->abi, VMOD_ABI_Version) != 0)) {
- VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod));
+ (vmd->abi == NULL || strcmp(vmd->abi, VMOD_ABI_Version))) {
+ VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(vim->t_mod));
VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
VMOD_ABI_Version, vmd->abi);
- vcc_ErrWhere(tl, mod);
- return (NULL);
+ return (-1);
}
- if (vmd->vrt_major != 0 && (vmd->vrt_major != VRT_MAJOR_VERSION ||
+ if (vmd->vrt_major != 0 &&
+ (vmd->vrt_major != VRT_MAJOR_VERSION ||
vmd->vrt_minor > VRT_MINOR_VERSION)) {
- VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod));
+ VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(vim->t_mod));
VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
VSB_printf(tl->sb, "\tVMOD wants ABI version %u.%u\n",
vmd->vrt_major, vmd->vrt_minor);
VSB_printf(tl->sb, "\tvarnishd provides ABI version %u.%u\n",
VRT_MAJOR_VERSION, VRT_MINOR_VERSION);
- vcc_ErrWhere(tl, mod);
- return (NULL);
+ return (-1);
}
if (vmd->name == NULL ||
vmd->func == NULL ||
@@ -253,131 +198,146 @@ vcc_VmodSanity(struct vcc *tl, void *hdl, const struct token *mod, char *fnp)
vmd->json == NULL ||
vmd->proto != NULL ||
vmd->abi == NULL) {
- VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(mod));
+ VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(vim->t_mod));
VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
VSB_cat(tl->sb, "\tInconsistent metadata\n");
- vcc_ErrWhere(tl, mod);
- return (NULL);
+ return (-1);
}
- if (!vcc_IdIs(mod, vmd->name)) {
- VSB_printf(tl->sb, "Wrong file for VMOD %.*s\n", PF(mod));
- VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
- VSB_printf(tl->sb, "\tContains vmod \"%s\"\n", vmd->name);
- vcc_ErrWhere(tl, mod);
- return (NULL);
+
+ err = vcc_ParseJSON(tl, vmd->json, vim);
+ AZ(dlclose(vim->hdl));
+ vim->hdl = NULL;
+ if (err != NULL && *err != '\0') {
+ VSB_printf(tl->sb,
+ "VMOD %.*s: bad metadata\n", PF(vim->t_mod));
+ VSB_printf(tl->sb, "\t(%s)\n", err);
+ VSB_printf(tl->sb, "\tFile name: %s\n", vim->path);
}
- return (vmd);
-}
-static vcc_kind_t
-vcc_vmod_kind(const char *type)
-{
+ if (err != NULL)
+ return (-1);
-#define VMOD_KIND(str, kind) \
- do { \
- if (!strcmp(str, type)) \
- return (kind); \
- } while (0)
- VMOD_KIND("$OBJ", SYM_OBJECT);
- VMOD_KIND("$METHOD", SYM_METHOD);
- VMOD_KIND("$FUNC", SYM_FUNC);
- VMOD_KIND("$ALIAS", SYM_ALIAS);
-#undef VMOD_KIND
- return (SYM_NONE);
+ return(0);
}
-static void
-vcc_VmodObject(struct vcc *tl, struct symbol *sym)
+static void v_matchproto_(vcc_do_stanza_f)
+vcc_do_event(struct vcc *tl, const struct vmod_import *vim,
+ const struct vjsn_val *vv)
{
- struct vmod_obj *obj;
- struct vsb *buf;
-
- buf = VSB_new_auto();
- AN(buf);
-
- VSB_printf(buf, "%s.%s", sym->vmod_name, sym->name);
- AZ(VSB_finish(buf));
-
- ALLOC_OBJ(obj, VMOD_OBJ_MAGIC);
- AN(obj);
- REPLACE(obj->name, VSB_data(buf));
+ struct inifin *ifp;
- INIT_OBJ(obj->type, TYPE_MAGIC);
- obj->type->name = obj->name;
- sym->type = obj->type;
- VTAILQ_INSERT_TAIL(&tl->vmod_objects, obj, list);
- VSB_destroy(&buf);
+ ifp = New_IniFin(tl);
+ VSB_printf(ifp->ini,
+ "\tif (%s(ctx, &vmod_priv_%s, VCL_EVENT_LOAD))\n"
+ "\t\treturn(1);",
+ vv->value, vim->sym->vmod_name);
+ VSB_printf(ifp->fin,
+ "\t\t(void)%s(ctx, &vmod_priv_%s,\n"
+ "\t\t\t VCL_EVENT_DISCARD);",
+ vv->value, vim->sym->vmod_name);
+ VSB_printf(ifp->event, "%s(ctx, &vmod_priv_%s, ev)",
+ vv->value, vim->sym->vmod_name);
}
-static void
-vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym)
+static void v_matchproto_(vcc_do_stanza_f)
+vcc_do_cproto(struct vcc *tl, const struct vmod_import *vim,
+ const struct vjsn_val *vv)
{
- const struct vjsn *vj;
- const struct vjsn_val *vv, *vv1, *vv2;
- vcc_kind_t kind;
-
- if (sym->kind == SYM_VMOD) {
- CAST_OBJ_NOTNULL(vj, sym->eval_priv, VJSN_MAGIC);
- vv = VTAILQ_FIRST(&vj->value->children);
- } else if (sym->kind == SYM_OBJECT) {
- CAST_OBJ_NOTNULL(vv, sym->eval_priv, VJSN_VAL_MAGIC);
- } else {
- WRONG("symbol kind");
- }
-
- for (; vv != NULL; vv = VTAILQ_NEXT(vv, list)) {
- if (!vjsn_is_array(vv))
- continue;
- vv1 = VTAILQ_FIRST(&vv->children);
- assert(vjsn_is_string(vv1));
- vv2 = VTAILQ_NEXT(vv1, list);
- if (!vjsn_is_string(vv2))
- continue;
-
- kind = vcc_vmod_kind(vv1->value);
- if (kind == SYM_NONE)
- continue;
-
- func_sym(tl, kind, sym, vv2);
- }
+ (void)vim;
+ do {
+ assert (vjsn_is_string(vv));
+ Fh(tl, 0, "%s\n", vv->value);
+ vv = VTAILQ_NEXT(vv, list);
+ } while(vv != NULL);
}
static void
-vcc_emit_c_prototypes(const struct vcc *tl, const struct vjsn *vj)
+vcc_vj_foreach(struct vcc *tl, const struct vmod_import *vim,
+ const char *stanza, vcc_do_stanza_f *func)
{
const struct vjsn_val *vv, *vv2, *vv3;
- Fh(tl, 0, "\n");
- vv = vj->value;
+ vv = vim->vj->value;
assert (vjsn_is_array(vv));
- vv3 = NULL;
VTAILQ_FOREACH(vv2, &vv->children, list) {
assert (vjsn_is_array(vv2));
vv3 = VTAILQ_FIRST(&vv2->children);
assert (vjsn_is_string(vv3));
- if (!strcmp(vv3->value, "$CPROTO"))
- break;
- }
- assert(vv3 != NULL);
- while (1) {
- vv3 = VTAILQ_NEXT(vv3, list);
- if (vv3 == NULL)
- break;
- assert (vjsn_is_string(vv3));
- Fh(tl, 0, "%s\n", vv3->value);
+ if (!strcmp(vv3->value, stanza))
+ func(tl, vim, VTAILQ_NEXT(vv3, list));
}
}
+static void
+vcc_emit_setup(struct vcc *tl, const struct vmod_import *vim)
+{
+ struct inifin *ifp;
+ const struct token *mod = vim->t_mod;
+
+ ifp = New_IniFin(tl);
+
+ VSB_cat(ifp->ini, "\tif (VPI_Vmod_Init(ctx,\n");
+ VSB_printf(ifp->ini, "\t &VGC_vmod_%.*s,\n", PF(mod));
+ VSB_printf(ifp->ini, "\t %u,\n", tl->vmod_count++);
+ VSB_printf(ifp->ini, "\t &%s,\n", vim->func_name);
+ VSB_printf(ifp->ini, "\t sizeof(%s),\n", vim->func_name);
+ VSB_printf(ifp->ini, "\t \"%.*s\",\n", PF(mod));
+ VSB_cat(ifp->ini, "\t ");
+ VSB_quote(ifp->ini, vim->path, -1, VSB_QUOTE_CSTR);
+ VSB_cat(ifp->ini, ",\n");
+ AN(vim->file_id);
+ VSB_printf(ifp->ini, "\t \"%s\",\n", vim->file_id);
+ VSB_printf(ifp->ini, "\t \"./vmod_cache/_vmod_%.*s.%s\"\n",
+ PF(mod), vim->file_id);
+ VSB_cat(ifp->ini, "\t ))\n");
+ VSB_cat(ifp->ini, "\t\treturn(1);");
+
+ VSB_cat(tl->symtab, ",\n {\n");
+ VSB_cat(tl->symtab, "\t\"dir\": \"import\",\n");
+ VSB_cat(tl->symtab, "\t\"type\": \"$VMOD\",\n");
+ VSB_printf(tl->symtab, "\t\"name\": \"%.*s\",\n", PF(mod));
+ VSB_printf(tl->symtab, "\t\"file\": \"%s\",\n", vim->path);
+ VSB_printf(tl->symtab, "\t\"dst\": \"./vmod_cache/_vmod_%.*s.%s\"\n",
+ PF(mod), vim->file_id);
+ VSB_cat(tl->symtab, " }");
+
+ /* XXX: zero the function pointer structure ?*/
+ VSB_printf(ifp->fin, "\t\tVRT_priv_fini(ctx, &vmod_priv_%.*s);",
+ PF(mod));
+ VSB_printf(ifp->final, "\t\tVPI_Vmod_Unload(ctx, &VGC_vmod_%.*s);",
+ PF(mod));
+
+ vcc_vj_foreach(tl, vim, "$EVENT", vcc_do_event);
+
+ Fh(tl, 0, "\n/* --- BEGIN VMOD %.*s --- */\n\n", PF(mod));
+ Fh(tl, 0, "static struct vmod *VGC_vmod_%.*s;\n", PF(mod));
+ Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
+
+ vcc_vj_foreach(tl, vim, "$CPROTO", vcc_do_cproto);
+
+ Fh(tl, 0, "\n/* --- END VMOD %.*s --- */\n\n", PF(mod));
+}
+
+static void
+vcc_vim_destroy(struct vmod_import **vimp)
+{
+ struct vmod_import *vim;
+
+ TAKE_OBJ_NOTNULL(vim, vimp, VMOD_IMPORT_MAGIC);
+ if (vim->path)
+ free(vim->path);
+ if (vim->vj)
+ vjsn_delete(&vim->vj);
+ FREE_OBJ(vim);
+}
+
void
vcc_ParseImport(struct vcc *tl)
{
- char fn[1024], *fnpx;
+ char fn[1024];
const char *p;
struct token *mod, *tmod, *t1;
- struct inifin *ifp;
struct symbol *msym, *vsym;
- const struct vmod_data *vmd;
- struct vjsn *vj;
struct vmod_import *vim;
const struct vmod_import *vimold;
@@ -428,8 +388,10 @@ vcc_ParseImport(struct vcc *tl)
ALLOC_OBJ(vim, VMOD_IMPORT_MAGIC);
AN(vim);
+ vim->t_mod = mod;
+ vim->sym = msym;
- if (VFIL_searchpath(tl->vmod_path, vcc_path_dlopen, vim, fn, &fnpx)) {
+ if (VFIL_searchpath(tl->vmod_path, vcc_path_dlopen, vim, fn, &vim->path)) {
if (vim->err == NULL) {
VSB_printf(tl->sb,
"Could not find VMOD %.*s\n", PF(mod));
@@ -437,26 +399,24 @@ vcc_ParseImport(struct vcc *tl)
VSB_printf(tl->sb,
"Could not open VMOD %.*s\n", PF(mod));
VSB_printf(tl->sb, "\tFile name: %s\n",
- fnpx != NULL ? fnpx : fn);
+ vim->path != NULL ? vim->path : fn);
VSB_printf(tl->sb, "\tdlerror: %s\n", vim->err);
}
vcc_ErrWhere(tl, mod);
- free(fnpx);
- FREE_OBJ(vim);
+ vcc_vim_destroy(&vim);
return;
}
- vmd = vcc_VmodSanity(tl, vim->hdl, mod, fnpx);
- if (vmd == NULL || tl->err) {
- AZ(dlclose(vim->hdl));
- free(fnpx);
- FREE_OBJ(vim);
+ if (vcc_VmodLoad(tl, vim, vim->path) < 0 || tl->err) {
+ vcc_ErrWhere(tl, vim->t_mod);
+ vcc_vim_destroy(&vim);
return;
}
- CAST_OBJ(vimold, (const void*)(msym->extra), VMOD_IMPORT_MAGIC);
+ vimold = msym->import;
if (vimold != NULL) {
- if (!strcmp(vimold->vmd->file_id, vmd->file_id)) {
+ CHECK_OBJ_NOTNULL(vimold, VMOD_IMPORT_MAGIC);
+ if (!strcmp(vimold->file_id, vim->file_id)) {
/* Identical import is OK */
} else {
VSB_printf(tl->sb,
@@ -464,9 +424,7 @@ vcc_ParseImport(struct vcc *tl)
PF(tmod));
vcc_ErrWhere2(tl, t1, tl->t);
}
- AZ(dlclose(vim->hdl));
- free(fnpx);
- FREE_OBJ(vim);
+ vcc_vim_destroy(&vim);
return;
}
msym->def_b = t1;
@@ -474,151 +432,26 @@ vcc_ParseImport(struct vcc *tl)
VTAILQ_FOREACH(vsym, &tl->sym_vmods, sideways) {
assert(vsym->kind == SYM_VMOD);
- CAST_OBJ_NOTNULL(vimold, (const void*)(vsym->extra),
- VMOD_IMPORT_MAGIC);
- if (!strcmp(vimold->vmd->file_id, vmd->file_id)) {
+ vimold = vsym->import;
+ CHECK_OBJ_NOTNULL(vimold, VMOD_IMPORT_MAGIC);
+ if (!strcmp(vimold->file_id, vim->file_id)) {
/* Already loaded under different name */
msym->eval_priv = vsym->eval_priv;
- msym->extra = vsym->extra;
+ msym->import = vsym->import;
msym->vmod_name = vsym->vmod_name;
vcc_VmodSymbols(tl, msym);
- AZ(dlclose(vim->hdl));
- free(fnpx);
- FREE_OBJ(vim);
+ // XXX: insert msym in sideways ?
+ vcc_vim_destroy(&vim);
return;
}
}
VTAILQ_INSERT_TAIL(&tl->sym_vmods, msym, sideways);
- ifp = New_IniFin(tl);
-
- VSB_cat(ifp->ini, "\tif (VPI_Vmod_Init(ctx,\n");
- VSB_printf(ifp->ini, "\t &VGC_vmod_%.*s,\n", PF(mod));
- VSB_printf(ifp->ini, "\t %u,\n", tl->vmod_count++);
- VSB_printf(ifp->ini, "\t &%s,\n", vmd->func_name);
- VSB_printf(ifp->ini, "\t sizeof(%s),\n", vmd->func_name);
- VSB_printf(ifp->ini, "\t \"%.*s\",\n", PF(mod));
- VSB_cat(ifp->ini, "\t ");
- VSB_quote(ifp->ini, fnpx, -1, VSB_QUOTE_CSTR);
- VSB_cat(ifp->ini, ",\n");
- AN(vmd);
- AN(vmd->file_id);
- VSB_printf(ifp->ini, "\t \"%s\",\n", vmd->file_id);
- VSB_printf(ifp->ini, "\t \"./vmod_cache/_vmod_%.*s.%s\"\n",
- PF(mod), vmd->file_id);
- VSB_cat(ifp->ini, "\t ))\n");
- VSB_cat(ifp->ini, "\t\treturn(1);");
-
- VSB_cat(tl->symtab, ",\n {\n");
- VSB_cat(tl->symtab, "\t\"dir\": \"import\",\n");
- VSB_cat(tl->symtab, "\t\"type\": \"$VMOD\",\n");
- VSB_printf(tl->symtab, "\t\"name\": \"%.*s\",\n", PF(mod));
- VSB_printf(tl->symtab, "\t\"file\": \"%s\",\n", fnpx);
- VSB_printf(tl->symtab, "\t\"dst\": \"./vmod_cache/_vmod_%.*s.%s\"\n",
- PF(mod), vmd->file_id);
- VSB_cat(tl->symtab, " }");
-
- /* XXX: zero the function pointer structure ?*/
- VSB_printf(ifp->fin, "\t\tVRT_priv_fini(ctx, &vmod_priv_%.*s);", PF(mod));
- VSB_printf(ifp->final, "\t\tVPI_Vmod_Unload(ctx, &VGC_vmod_%.*s);", PF(mod));
-
- vj = vjsn_parse(vmd->json, &p);
- XXXAZ(p);
- AN(vj);
- msym->eval_priv = vj;
- vim->vmd = vmd;
- msym->extra = (const char *)vim;
- msym->vmod_name = TlDup(tl, vmd->name);
+ msym->eval_priv = vim->vj;
+ msym->import = vim;
+ msym->vmod_name = TlDup(tl, vim->name);
vcc_VmodSymbols(tl, msym);
- vcc_json_always(tl, vj, msym->vmod_name);
-
- Fh(tl, 0, "\n/* --- BEGIN VMOD %.*s --- */\n\n", PF(mod));
- Fh(tl, 0, "static struct vmod *VGC_vmod_%.*s;\n", PF(mod));
- Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
- vcc_emit_c_prototypes(tl, vj);
- Fh(tl, 0, "\n/* --- END VMOD %.*s --- */\n\n", PF(mod));
- free(fnpx);
-}
-
-void v_matchproto_(sym_act_f)
-vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
-{
- struct symbol *isym, *osym;
- struct inifin *ifp;
- struct vsb *buf;
- const struct vjsn_val *vv, *vf;
- int null_ok = 0;
-
- (void)sym;
- (void)t;
-
- ExpectErr(tl, ID);
- vcc_ExpectVid(tl, "VCL object");
- ERRCHK(tl);
- isym = VCC_HandleSymbol(tl, INSTANCE);
- ERRCHK(tl);
- AN(isym);
- isym->noref = 1;
- isym->action = vcc_Act_Obj;
-
- SkipToken(tl, '=');
- ExpectErr(tl, ID);
- osym = VCC_SymbolGet(tl, SYM_MAIN, SYM_OBJECT, SYMTAB_EXISTING,
- XREF_NONE);
- ERRCHK(tl);
- AN(osym);
-
- /* Scratch the generic INSTANCE type */
- isym->type = osym->type;
-
- CAST_OBJ_NOTNULL(vv, osym->eval_priv, VJSN_VAL_MAGIC);
- // vv = object name
-
- isym->vmod_name = osym->vmod_name;
- isym->eval_priv = vv;
-
- vv = VTAILQ_NEXT(vv, list);
- // vv = flags
- assert(vjsn_is_object(vv));
- VTAILQ_FOREACH(vf, &vv->children, list)
- if (!strcmp(vf->name, "NULL_OK") && vjsn_is_true(vf))
- null_ok = 1;
- if (!null_ok)
- VTAILQ_INSERT_TAIL(&tl->sym_objects, isym, sideways);
-
- vv = VTAILQ_NEXT(vv, list);
- // vv = struct name
-
- Fh(tl, 0, "static %s *%s;\n\n", vv->value, isym->rname);
- vv = VTAILQ_NEXT(vv, list);
-
- vf = VTAILQ_FIRST(&vv->children);
- vv = VTAILQ_NEXT(vv, list);
- assert(vjsn_is_string(vf));
- assert(!strcmp(vf->value, "$INIT"));
-
- vf = VTAILQ_NEXT(vf, list);
-
- buf = VSB_new_auto();
- AN(buf);
- VSB_printf(buf, "&%s, \"%s\"", isym->rname, isym->name);
- AZ(VSB_finish(buf));
- vcc_Eval_Func(tl, vf, VSB_data(buf), osym);
- VSB_destroy(&buf);
- ERRCHK(tl);
- SkipToken(tl, ';');
- isym->def_e = tl->t;
-
- vf = VTAILQ_FIRST(&vv->children);
- assert(vjsn_is_string(vf));
- assert(!strcmp(vf->value, "$FINI"));
-
- vf = VTAILQ_NEXT(vf, list);
- vf = VTAILQ_FIRST(&vf->children);
- vf = VTAILQ_NEXT(vf, list);
- ifp = New_IniFin(tl);
- VSB_printf(ifp->fin, "\t\tif (%s)\n", isym->rname);
- VSB_printf(ifp->fin, "\t\t\t\t%s(&%s);", vf->value, isym->rname);
+ vcc_emit_setup(tl, vim);
}
diff --git a/lib/libvcc/vcc_vmod.h b/lib/libvcc/vcc_vmod.h
new file mode 100644
index 000000000..2f386cf5a
--- /dev/null
+++ b/lib/libvcc/vcc_vmod.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2010-2015 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * 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.
+ */
+
+#define STANZA_TBL \
+ STANZA(ALIAS, alias, SYM_ALIAS) \
+ STANZA(CPROTO, cproto, SYM_NONE) \
+ STANZA(EVENT, evant, SYM_NONE) \
+ STANZA(FUNC, func, SYM_FUNC) \
+ STANZA(METHOD, method, SYM_METHOD) \
+ STANZA(OBJ, obj, SYM_OBJECT) \
+ STANZA(VMOD, vmod, SYM_NONE)
+
+void vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym);
diff --git a/lib/libvcc/vcc_vmod_sym.c b/lib/libvcc/vcc_vmod_sym.c
new file mode 100644
index 000000000..65f7f4d6f
--- /dev/null
+++ b/lib/libvcc/vcc_vmod_sym.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 2010-2015 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * 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.
+ *
+ * Turn vmod JSON spec into symbols
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+#include "libvcc.h"
+#include "vjsn.h"
+#include "vsb.h"
+
+#include "vcc_vmod.h"
+
+struct vmod_obj {
+ unsigned magic;
+#define VMOD_OBJ_MAGIC 0x349885f8
+ char *name;
+ struct type type[1];
+ VTAILQ_ENTRY(vmod_obj) list;
+};
+
+static void
+vcc_VmodObject(struct vcc *tl, struct symbol *sym)
+{
+ struct vmod_obj *obj;
+ struct vsb *buf;
+
+ buf = VSB_new_auto();
+ AN(buf);
+
+ VSB_printf(buf, "%s.%s", sym->vmod_name, sym->name);
+ AZ(VSB_finish(buf));
+
+ ALLOC_OBJ(obj, VMOD_OBJ_MAGIC);
+ AN(obj);
+ REPLACE(obj->name, VSB_data(buf));
+
+ INIT_OBJ(obj->type, TYPE_MAGIC);
+ obj->type->name = obj->name;
+ sym->type = obj->type;
+ VTAILQ_INSERT_TAIL(&tl->vmod_objects, obj, list);
+ VSB_destroy(&buf);
+}
+
+static void
+alias_sym(struct vcc *tl, const struct symbol *psym, const struct vjsn_val *v)
+{
+ char *alias = NULL, *func = NULL;
+ struct symbol *sym;
+ struct vsb *buf;
+
+ buf = VSB_new_auto();
+ AN(buf);
+
+ VCC_SymName(buf, psym);
+ VSB_printf(buf, ".%s", v->value);
+ AZ(VSB_finish(buf));
+ REPLACE(alias, VSB_data(buf));
+
+ v = VTAILQ_NEXT(v, list);
+ assert(vjsn_is_string(v));
+
+ VSB_clear(buf);
+ VCC_SymName(buf, psym);
+ VSB_printf(buf, ".%s", v->value);
+ AZ(VSB_finish(buf));
+ REPLACE(func, VSB_data(buf));
+
+ sym = VCC_MkSymAlias(tl, alias, func);
+ AN(sym);
+ assert(sym->kind == SYM_FUNC || sym->kind == SYM_METHOD);
+ VSB_destroy(&buf);
+ free(alias);
+ free(func);
+}
+
+static void
+func_sym(struct vcc *tl, vcc_kind_t kind, const struct symbol *psym,
+ const struct vjsn_val *v)
+{
+ struct symbol *sym;
+ struct vsb *buf;
+
+ if (kind == SYM_ALIAS) {
+ alias_sym(tl, psym, v);
+ return;
+ }
+
+ buf = VSB_new_auto();
+ AN(buf);
+
+ VCC_SymName(buf, psym);
+ VSB_printf(buf, ".%s", v->value);
+ AZ(VSB_finish(buf));
+ sym = VCC_MkSym(tl, VSB_data(buf), SYM_MAIN, kind, VCL_LOW, VCL_HIGH);
+ AN(sym);
+ VSB_destroy(&buf);
+
+ if (kind == SYM_OBJECT) {
+ sym->eval_priv = v;
+ sym->vmod_name = psym->vmod_name;
+ sym->r_methods = VCL_MET_INIT;
+ vcc_VmodObject(tl, sym);
+ vcc_VmodSymbols(tl, sym);
+ return;
+ }
+
+ if (kind == SYM_METHOD)
+ sym->extra = psym->rname;
+
+ v = VTAILQ_NEXT(v, list);
+
+ assert(vjsn_is_array(v));
+ sym->action = vcc_Act_Call;
+ sym->vmod_name = psym->vmod_name;
+ sym->eval = vcc_Eval_SymFunc;
+ sym->eval_priv = v;
+ v = VTAILQ_FIRST(&v->children);
+ assert(vjsn_is_array(v));
+ v = VTAILQ_FIRST(&v->children);
+ assert(vjsn_is_string(v));
+ sym->type = VCC_Type(v->value);
+ AN(sym->type);
+ sym->r_methods = VCL_MET_TASK_ALL;
+}
+
+void
+vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym)
+{
+ const struct vjsn *vj;
+ const struct vjsn_val *vv, *vv1, *vv2;
+ vcc_kind_t kind;
+
+ if (sym->kind == SYM_VMOD) {
+ CAST_OBJ_NOTNULL(vj, sym->eval_priv, VJSN_MAGIC);
+ vv = VTAILQ_FIRST(&vj->value->children);
+ } else if (sym->kind == SYM_OBJECT) {
+ CAST_OBJ_NOTNULL(vv, sym->eval_priv, VJSN_VAL_MAGIC);
+ } else {
+ WRONG("symbol kind");
+ }
+
+ for (; vv != NULL; vv = VTAILQ_NEXT(vv, list)) {
+ if (!vjsn_is_array(vv))
+ continue;
+ vv1 = VTAILQ_FIRST(&vv->children);
+ assert(vjsn_is_string(vv1));
+ vv2 = VTAILQ_NEXT(vv1, list);
+ if (!vjsn_is_string(vv2))
+ continue;
+
+ kind = SYM_NONE;
+#define STANZA(UU, ll, ss) if (!strcmp(vv1->value, "$" #UU)) kind = ss;
+ STANZA_TBL
+#undef STANZA
+ if (kind != SYM_NONE)
+ func_sym(tl, kind, sym, vv2);
+ }
+}
+
+void v_matchproto_(sym_act_f)
+vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
+{
+ struct symbol *isym, *osym;
+ struct inifin *ifp;
+ struct vsb *buf;
+ const struct vjsn_val *vv, *vf;
+ int null_ok = 0;
+
+ (void)sym;
+ (void)t;
+
+ ExpectErr(tl, ID);
+ vcc_ExpectVid(tl, "VCL object");
+ ERRCHK(tl);
+ isym = VCC_HandleSymbol(tl, INSTANCE);
+ ERRCHK(tl);
+ AN(isym);
+ isym->noref = 1;
+ isym->action = vcc_Act_Obj;
+
+ SkipToken(tl, '=');
+ ExpectErr(tl, ID);
+ osym = VCC_SymbolGet(tl, SYM_MAIN, SYM_OBJECT, SYMTAB_EXISTING,
+ XREF_NONE);
+ ERRCHK(tl);
+ AN(osym);
+
+ /* Scratch the generic INSTANCE type */
+ isym->type = osym->type;
+
+ CAST_OBJ_NOTNULL(vv, osym->eval_priv, VJSN_VAL_MAGIC);
+ // vv = object name
+
+ isym->vmod_name = osym->vmod_name;
+ isym->eval_priv = vv;
+
+ vv = VTAILQ_NEXT(vv, list);
+ // vv = flags
+ assert(vjsn_is_object(vv));
+ VTAILQ_FOREACH(vf, &vv->children, list)
+ if (!strcmp(vf->name, "NULL_OK") && vjsn_is_true(vf))
+ null_ok = 1;
+ if (!null_ok)
+ VTAILQ_INSERT_TAIL(&tl->sym_objects, isym, sideways);
+
+ vv = VTAILQ_NEXT(vv, list);
+ // vv = struct name
+
+ Fh(tl, 0, "static %s *%s;\n\n", vv->value, isym->rname);
+ vv = VTAILQ_NEXT(vv, list);
+
+ vf = VTAILQ_FIRST(&vv->children);
+ vv = VTAILQ_NEXT(vv, list);
+ assert(vjsn_is_string(vf));
+ assert(!strcmp(vf->value, "$INIT"));
+
+ vf = VTAILQ_NEXT(vf, list);
+
+ buf = VSB_new_auto();
+ AN(buf);
+ VSB_printf(buf, "&%s, \"%s\"", isym->rname, isym->name);
+ AZ(VSB_finish(buf));
+ vcc_Eval_Func(tl, vf, VSB_data(buf), osym);
+ VSB_destroy(&buf);
+ ERRCHK(tl);
+ SkipToken(tl, ';');
+ isym->def_e = tl->t;
+
+ vf = VTAILQ_FIRST(&vv->children);
+ assert(vjsn_is_string(vf));
+ assert(!strcmp(vf->value, "$FINI"));
+
+ vf = VTAILQ_NEXT(vf, list);
+ vf = VTAILQ_FIRST(&vf->children);
+ vf = VTAILQ_NEXT(vf, list);
+ ifp = New_IniFin(tl);
+ VSB_printf(ifp->fin, "\t\tif (%s)\n", isym->rname);
+ VSB_printf(ifp->fin, "\t\t\t\t%s(&%s);", vf->value, isym->rname);
+}
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 823e12385..1ea7f66be 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -1086,7 +1086,7 @@ class vcc(object):
def iter_json(self, fnx):
- jl = [["$VMOD", "1.0"]]
+ jl = [["$VMOD", "1.0", self.modname, self.csn, self.file_id]]
jl.append(["$CPROTO"])
for i in open(fnx):
jl[-1].append(i.rstrip())
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index 53b0ebc14..a0a11f5b6 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -1087,7 +1087,15 @@ const struct vmod_data Vmod_wrong2_Data = {
.func = foo_struct,
.func_len = sizeof foo_struct,
.func_name = "foo_struct",
- .json = "blablabla",
+ .json = "["
+ "["
+ "\"$VMOD\""
+ ", \"1.0\""
+ ", \"wrongN\""
+ ", \"foo_struct\""
+ ", \"file_id\""
+ "]"
+ "]",
};
extern const struct vmod_data Vmod_wrong3_Data;
@@ -1098,7 +1106,16 @@ const struct vmod_data Vmod_wrong3_Data = {
.func = foo_struct,
.func_len = sizeof foo_struct,
.func_name = "foo_struct",
- .json = "blablabla",
+ .json = "["
+ "["
+ "\"$VMOD\""
+ ", \"1.0\""
+ ", \"wrongN\""
+ ", \"foo_struct\""
+ ", \"file_id\""
+ "]"
+ ", [\"$CPROTO\", \"\"]"
+ "]",
.abi = "abiblabla",
};
More information about the varnish-commit
mailing list