[master] 8ae3d9782 Extend the syntax to 'import vmod [as name] [from "path"]; '
Poul-Henning Kamp
phk at FreeBSD.org
Mon May 20 10:22:10 UTC 2019
commit 8ae3d978224587ae6021a78d5821b9978ae65f24
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon May 20 10:20:43 2019 +0000
Extend the syntax to 'import vmod [as name] [from "path"];'
There are a surprising number of subtle corner cases here, and I
think I have handled them all correctly, but caveat emptor...
diff --git a/bin/varnishtest/tests/m00000.vtc b/bin/varnishtest/tests/m00000.vtc
index 1931db422..a62ff527b 100644
--- a/bin/varnishtest/tests/m00000.vtc
+++ b/bin/varnishtest/tests/m00000.vtc
@@ -11,10 +11,12 @@ varnish v1 -vcl+backend {
import debug;
import vtc;
import debug; // again
+ import debug as dbg;
+ import debug as dbg; // again
sub vcl_init {
- new objx = debug.obj();
- debug.vsc_new();
+ new objx = dbg.obj();
+ dbg.vsc_new();
}
sub vcl_synth {
diff --git a/bin/varnishtest/tests/m00008.vtc b/bin/varnishtest/tests/m00008.vtc
index a0bc5b2a3..7b5647487 100644
--- a/bin/varnishtest/tests/m00008.vtc
+++ b/bin/varnishtest/tests/m00008.vtc
@@ -12,6 +12,11 @@ varnish v1 -errvcl {Module debug conflicts with other symbol.} {
}
}
+varnish v1 -errvcl {Another module already imported as foo} {
+ import debug as foo;
+ import directors as foo;
+}
+
server s1 {
rxreq
txresp
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 58eb570c6..20213c0b9 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -144,7 +144,7 @@ struct symbol {
int hirev;
struct symbol *parent;
- const struct symbol *vmod;
+ const char *vmod_name;
sym_wildcard_t *wildcard;
vcc_kind_t kind;
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 9638b519f..c74cc4c4b 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -359,10 +359,10 @@ vcc_priv_arg(struct vcc *tl, const char *p, const struct symbol *sym)
struct procprivhead *marklist = NULL;
AN(sym);
- AN(sym->vmod);
+ AN(sym->vmod_name);
if (!strcmp(p, "PRIV_VCL"))
- return (vcc_mk_expr(VOID, "&vmod_priv_%s", sym->vmod->name));
+ return (vcc_mk_expr(VOID, "&vmod_priv_%s", sym->vmod_name));
if (!strcmp(p, "PRIV_CALL")) {
bprintf(buf, "vmod_priv_%u", tl->unique++);
@@ -383,9 +383,9 @@ vcc_priv_arg(struct vcc *tl, const char *p, const struct symbol *sym)
}
AN(f);
AN(marklist);
- bprintf(buf, "ARG_priv_%s_%s", f, sym->vmod->name);
+ bprintf(buf, "ARG_priv_%s_%s", f, sym->vmod_name);
- if (vcc_MarkPriv(tl, marklist, sym->vmod->name) == NULL)
+ if (vcc_MarkPriv(tl, marklist, sym->vmod_name) == NULL)
VSB_printf(tl->curproc->prologue,
" struct vmod_priv *%s = "
"VRT_priv_%s(ctx, &VGC_vmod_%s);\n"
@@ -394,7 +394,7 @@ vcc_priv_arg(struct vcc *tl, const char *p, const struct symbol *sym)
"for vmod %s\");\n"
" return;\n"
" }\n",
- buf, f, sym->vmod->name, buf, f, sym->vmod->name);
+ buf, f, sym->vmod_name, buf, f, sym->vmod_name);
return (vcc_mk_expr(VOID, "%s", buf));
}
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index ff4831198..38863ceb5 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -64,13 +64,12 @@ vcc_path_dlopen(void *priv, const char *fn)
}
static void
-func_sym(struct symbol *sym, const struct symbol *vmod,
- const struct vjsn_val *v)
+func_sym(struct symbol *sym, const char *vmod_name, const struct vjsn_val *v)
{
assert(v->type == VJSN_ARRAY);
sym->action = vcc_Act_Call;
- sym->vmod = vmod;
+ sym->vmod_name = vmod_name;
sym->eval = vcc_Eval_SymFunc;
sym->eval_priv = v;
v = VTAILQ_FIRST(&v->children);
@@ -82,17 +81,16 @@ func_sym(struct symbol *sym, const struct symbol *vmod,
}
static void
-vcc_json_always(struct vcc *tl, const struct symbol *msym)
+vcc_json_always(struct vcc *tl, const struct vjsn *vj, const char *vmod_name)
{
struct inifin *ifp;
- const struct vjsn *vj;
const struct vjsn_val *vv, *vv2;
double vmod_syntax = 0.0;
+ AN(vj);
+ AN(vmod_name);
ifp = NULL;
- CAST_OBJ_NOTNULL(vj, msym->eval_priv, VJSN_MAGIC);
-
VTAILQ_FOREACH(vv, &vj->value->children, list) {
assert(vv->type == VJSN_ARRAY);
vv2 = VTAILQ_FIRST(&vv->children);
@@ -111,13 +109,13 @@ vcc_json_always(struct vcc *tl, const struct symbol *msym)
VSB_printf(ifp->ini,
"\tif (%s(ctx, &vmod_priv_%s, VCL_EVENT_LOAD))\n"
"\t\treturn(1);",
- vv2->value, msym->name);
+ 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, msym->name);
+ vv2->value, vmod_name);
VSB_printf(ifp->event, "%s(ctx, &vmod_priv_%s, ev)",
- vv2->value, msym->name);
+ vv2->value, vmod_name);
} else if (!strcmp(vv2->value, "$FUNC")) {
} else if (!strcmp(vv2->value, "$OBJ")) {
} else {
@@ -147,66 +145,104 @@ vcc_json_wildcard(struct vcc *tl, struct symbol *msym, struct symbol *tsym)
!strcmp(vv2->value, tsym->name)) {
tsym->kind = SYM_FUNC;
tsym->noref = 1;
- func_sym(tsym, msym, VTAILQ_NEXT(vv2, list));
+ func_sym(tsym, msym->vmod_name, VTAILQ_NEXT(vv2, list));
return;
} else if (!strcmp(vv1->value, "$OBJ") &&
!strcmp(vv2->value, tsym->name)) {
tsym->kind = SYM_OBJECT;
tsym->eval_priv = vv2;
- tsym->vmod = msym;
+ tsym->vmod_name = msym->vmod_name;
return;
}
}
tl->err = 1;
}
+static const struct vmod_data *
+vcc_VmodSanity(struct vcc *tl, void *hdl, struct token *mod, char *fnp)
+{
+ char buf[256];
+ const struct vmod_data *vmd;
+
+ bprintf(buf, "Vmod_%.*s_Data", PF(mod));
+ vmd = dlsym(hdl, buf);
+ if (vmd == NULL) {
+ VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(mod));
+ VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
+ VSB_printf(tl->sb, "\t(no Vmod_Data symbol)\n");
+ vcc_ErrWhere(tl, mod);
+ return (NULL);
+ }
+ 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));
+ 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);
+ }
+ 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, "\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);
+ }
+ if (vmd->name == NULL ||
+ vmd->func == NULL ||
+ vmd->func_len <= 0 ||
+ vmd->proto == NULL ||
+ vmd->abi == NULL) {
+ VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(mod));
+ VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
+ VSB_printf(tl->sb, "\tInconsistent metadata\n");
+ vcc_ErrWhere(tl, mod);
+ return (NULL);
+ }
+ 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);
+ }
+ return (vmd);
+}
+
void
vcc_ParseImport(struct vcc *tl)
{
- char fn[1024], *fnp, *fnpx;
- char buf[256];
+ char fn[1024], *fnpx;
const char *p;
- struct token *mod, *t1;
+ struct token *mod, *tmod, *t1;
struct inifin *ifp;
- struct symbol *msym;
+ struct symbol *msym, *vsym;
const struct vmod_data *vmd;
struct vjsn *vj;
- int again = 0;
struct vmod_open vop[1];
INIT_OBJ(vop, VMOD_OPEN_MAGIC);
t1 = tl->t;
SkipToken(tl, ID); /* "import" */
-
- ExpectErr(tl, ID);
+ ExpectErr(tl, ID); /* "vmod_name" */
mod = tl->t;
vcc_NextToken(tl);
- msym = VCC_SymbolGetTok(tl, SYM_NONE, SYMTAB_NOERR, XREF_NONE, mod);
-
- if (msym != NULL && msym->kind != SYM_VMOD) {
- /*
- * We need to make sure the entire std.* namespace is empty
- */
- VSB_printf(tl->sb, "Module %.*s conflicts with other symbol.\n",
- PF(mod));
- vcc_ErrWhere2(tl, t1, tl->t);
- return;
- }
- if (msym != NULL) {
- again = 1;
- } else {
- msym = VCC_SymbolGetTok(tl, SYM_VMOD,
- SYMTAB_CREATE, XREF_NONE, mod);
- ERRCHK(tl);
- AN(msym);
- msym->def_b = t1;
- msym->def_e = tl->t;
+ if (tl->t->tok == ID && vcc_IdIs(tl->t, "as")) {
+ SkipToken(tl, ID); /* "as" */
+ ExpectErr(tl, ID); /* "vcl_name" */
+ tmod = tl->t;
+ vcc_NextToken(tl);
+ } else {
+ tmod = mod;
}
- VTAILQ_INSERT_TAIL(&tl->sym_vmods, msym, sideways);
-
if (tl->t->tok == ID) {
if (!vcc_IdIs(tl->t, "from")) {
VSB_printf(tl->sb, "Expected 'from path ...'\n");
@@ -234,9 +270,6 @@ vcc_ParseImport(struct vcc *tl)
SkipToken(tl, ';');
- if (!again)
- msym->def_e = tl->t;
-
if (VFIL_searchpath(tl->vmod_path, vcc_path_dlopen, vop, fn, &fnpx)) {
if (vop->err == NULL) {
VSB_printf(tl->sb,
@@ -253,72 +286,58 @@ vcc_ParseImport(struct vcc *tl)
return;
}
- AN(fnpx);
- fnp = TlDup(tl, fnpx);
- free(fnpx);
-
- bprintf(buf, "Vmod_%.*s_Data", PF(mod));
- vmd = dlsym(vop->hdl, buf);
- if (vmd == NULL) {
- VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(mod));
- VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
- VSB_printf(tl->sb, "\t(no Vmod_Data symbol)\n");
- vcc_ErrWhere(tl, mod);
- return;
- }
- 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));
- 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;
- }
- 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, "\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;
- }
- if (vmd->name == NULL ||
- vmd->func == NULL ||
- vmd->func_len <= 0 ||
- vmd->proto == NULL ||
- vmd->abi == NULL) {
- VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(mod));
- VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
- VSB_printf(tl->sb, "\tInconsistent metadata\n");
- vcc_ErrWhere(tl, mod);
+ vmd = vcc_VmodSanity(tl, vop->hdl, mod, fnpx);
+ if (vmd == NULL || tl->err) {
+ AZ(dlclose(vop->hdl));
+ free(fnpx);
return;
}
- 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;
- }
+ msym = VCC_SymbolGetTok(tl, SYM_NONE, SYMTAB_NOERR, XREF_NONE, tmod);
- if (again && strcmp(vmd->file_id, msym->extra)) {
+ if (msym != NULL && msym->kind == SYM_VMOD &&
+ !strcmp(msym->extra, vmd->file_id)) {
+ /* Identical import is OK */
+ AZ(dlclose(vop->hdl));
+ free(fnpx);
+ return;
+ } else if (msym != NULL && msym->kind == SYM_VMOD) {
VSB_printf(tl->sb,
- "Different version of module %.*s already imported.\n",
- PF(mod));
+ "Another module already imported as %.*s.\n", PF(tmod));
+ vcc_ErrWhere2(tl, t1, tl->t);
+ AZ(dlclose(vop->hdl));
+ free(fnpx);
+ return;
+ } else if (msym != NULL) {
+ VSB_printf(tl->sb,
+ "Module %.*s conflicts with other symbol.\n", PF(tmod));
vcc_ErrWhere2(tl, t1, tl->t);
- VSB_printf(tl->sb, "Previous import was here:\n");
- vcc_ErrWhere2(tl, msym->def_b, msym->def_e);
- }
- if (again) {
AZ(dlclose(vop->hdl));
+ free(fnpx);
return;
}
+ msym = VCC_SymbolGetTok(tl, SYM_VMOD, SYMTAB_CREATE, XREF_NONE, tmod);
+ ERRCHK(tl);
+ AN(msym);
+ msym->def_b = t1;
+ msym->def_e = tl->t;
+
+ VTAILQ_FOREACH(vsym, &tl->sym_vmods, sideways) {
+ assert(vsym->kind == SYM_VMOD);
+ if (!strcmp(vsym->extra, vmd->file_id)) {
+ /* Already loaded under different name */
+ msym->eval_priv = vsym->eval_priv;
+ msym->wildcard = vsym->wildcard;
+ msym->extra = vsym->extra;
+ msym->vmod_name = vsym->vmod_name;
+ AZ(dlclose(vop->hdl));
+ return;
+ }
+ }
+
+ VTAILQ_INSERT_TAIL(&tl->sym_vmods, msym, sideways);
+
ifp = New_IniFin(tl);
VSB_printf(ifp->ini, "\tif (VPI_Vmod_Init(ctx,\n");
@@ -328,7 +347,7 @@ vcc_ParseImport(struct vcc *tl)
VSB_printf(ifp->ini, "\t sizeof(%s),\n", vmd->func_name);
VSB_printf(ifp->ini, "\t \"%.*s\",\n", PF(mod));
VSB_printf(ifp->ini, "\t ");
- VSB_quote(ifp->ini, fnp, -1, VSB_QUOTE_CSTR);
+ VSB_quote(ifp->ini, fnpx, -1, VSB_QUOTE_CSTR);
VSB_printf(ifp->ini, ",\n");
AN(vmd);
AN(vmd->file_id);
@@ -339,7 +358,7 @@ vcc_ParseImport(struct vcc *tl)
VSB_printf(ifp->ini, "\t\treturn(1);");
VSB_printf(tl->fi, "%s VMOD %s ./vmod_cache/_vmod_%.*s.%s */\n",
- VCC_INFO_PREFIX, fnp, PF(mod), vmd->file_id);
+ VCC_INFO_PREFIX, fnpx, PF(mod), vmd->file_id);
/* XXX: zero the function pointer structure ?*/
VSB_printf(ifp->fin, "\t\tVRT_priv_fini(&vmod_priv_%.*s);", PF(mod));
@@ -352,14 +371,16 @@ vcc_ParseImport(struct vcc *tl)
msym->eval_priv = vj;
msym->wildcard = vcc_json_wildcard;
msym->extra = TlDup(tl, vmd->file_id);
+ msym->vmod_name = TlDup(tl, vmd->name);
- vcc_json_always(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));
Fh(tl, 0, "\n%s\n", vmd->proto);
Fh(tl, 0, "\n/* --- END VMOD %.*s --- */\n\n", PF(mod));
+ free(fnpx);
}
void v_matchproto_(sym_act_f)
@@ -462,7 +483,7 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
AZ(VSB_finish(buf));
sy3 = VCC_MkSym(tl, VSB_data(buf), SYM_FUNC, VCL_LOW, VCL_HIGH);
AN(sy3);
- func_sym(sy3, sy2->vmod, VTAILQ_NEXT(vf, list));
+ func_sym(sy3, sy2->vmod_name, VTAILQ_NEXT(vf, list));
sy3->extra = p;
vv = VTAILQ_NEXT(vv, list);
}
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 1b40b10b8..4d8734d4c 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -603,7 +603,7 @@ class ModuleStanza(Stanza):
write_rst_hdr(fo, "SYNOPSIS", "=")
fo.write("\n")
fo.write(".. parsed-literal::\n\n")
- fo.write(' import %s [from "path"]\n' % self.vcc.modname)
+ fo.write(' import %s [as name] [from "path"]\n' % self.vcc.modname)
fo.write(" \n")
for c in self.vcc.contents:
c.synopsis(fo, man)
More information about the varnish-commit
mailing list