[master] ceb88d2e0 vcc: New $Alias stanza for VMODs
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Tue Feb 22 15:12:06 UTC 2022
commit ceb88d2e0134907eb9bf160c67db1f4e422d241f
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date: Tue Feb 22 10:24:32 2022 +0100
vcc: New $Alias stanza for VMODs
It is now possible to rename a symbol from a VMOD without breaking
existing code until the VMOD author decides to remove the deprecated
alias.
The VCC file syntax is simply:
$Alias <alias> <function>
[Optional description]
$Alias <.alias> <obj.method>
[Optional description]
The alias can only apply to a $Function or $Method.
The generated RST looks like this for a method:
ALIAS x<object>.<name>()
------------------------
Deprecated alias for ``x<object>.<method>()``.
[Optional description]
It looks the same for a function without the $Object prefix. Aliases
don't have a reference label for sphinx docs, the goal is not to make
them prominent, but rather to have the ability to move them to a manual
section for deprecated symbols at the end of the document.
diff --git a/bin/varnishtest/tests/r01332.vtc b/bin/varnishtest/tests/r01332.vtc
index 1f6616737..eea01c990 100644
--- a/bin/varnishtest/tests/r01332.vtc
+++ b/bin/varnishtest/tests/r01332.vtc
@@ -15,6 +15,7 @@ varnish v1 -vcl+backend {
sub vcl_deliver {
objx.enum(martin);
set resp.http.foo = objx.foo("");
+ set resp.http.bar = objx.bar("");
}
} -start
@@ -23,4 +24,5 @@ client c1 {
rxresp
expect resp.status == 200
expect resp.http.foo == "BOO"
+ expect resp.http.bar == "BOO"
} -run
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index 2b5ec5959..9c5be1234 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -76,6 +76,38 @@ vcc_path_dlopen(void *priv, const char *fn)
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)
+{
+ 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)
@@ -83,10 +115,14 @@ func_sym(struct vcc *tl, vcc_kind_t kind, const struct symbol *psym,
struct symbol *sym;
struct vsb *buf;
+ if (kind == SYM_ALIAS) {
+ alias_sym(tl, psym, v);
+ return;
+ }
+
buf = VSB_new_auto();
AN(buf);
- VSB_clear(buf);
VCC_SymName(buf, psym);
VSB_printf(buf, ".%s", v->value);
AZ(VSB_finish(buf));
@@ -158,6 +194,7 @@ vcc_json_always(struct vcc *tl, const struct vjsn *vj, const char *vmod_name)
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 {
@@ -237,6 +274,7 @@ vcc_vmod_kind(const char *type)
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);
}
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 0eb77c527..5be4d4665 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -835,6 +835,53 @@ class MethodStanza(Stanza):
self.proto.jsonproto(jl[-1], self.proto.cname())
+class AliasStanza(Stanza):
+
+ ''' $Alias ALIAS SYMBOL '''
+
+ def find_symbol(self, tbl, name):
+ for sym in tbl:
+ if sym.proto is None:
+ continue;
+ if sym.proto.name == name:
+ return sym
+ err("Symbol '%s' not found\n" % name, warn=False)
+
+ def parse(self):
+ if len(self.toks) != 3:
+ err("Syntax error, expected: $Alias <alias> <symbol>\n", warn=False)
+ if not re.match('^\.?[a-zA-Z_][a-zA-Z0-9_]*$', self.toks[1]):
+ err("%s(): Illegal C-name\n" % self.toks[1], warn=False)
+ if self.toks[1][0] == '.':
+ if not re.match('^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$',
+ self.toks[2]):
+ err("Syntax error, expected: $Alias <.alias> <obj.method>\n",
+ warn=False)
+ obj_name = self.toks[2].split('.')[0]
+ obj = self.find_symbol(self.vcc.contents, obj_name)
+ self.find_symbol(obj.methods, self.toks[2])
+ self.sym_alias = "%s%s" % (obj_name, self.toks[1])
+ self.doc_alias = "x%s" % self.sym_alias
+ self.sym_name = self.toks[2]
+ self.doc_name = "x%s" % self.toks[2]
+ else:
+ self.find_symbol(self.vcc.contents, self.toks[2])
+ self.sym_alias = self.toks[1]
+ self.doc_alias = self.toks[1]
+ self.sym_name = self.toks[2]
+ self.doc_name = self.toks[2]
+ self.vcc.contents.append(self)
+
+ def rsthead(self, fo, unused_man):
+ write_rst_hdr(fo, "ALIAS %s()" % self.doc_alias, "-")
+ fo.write("\nDeprecated alias for ``%s()``." % self.doc_name)
+ if len(self.doc) > 0:
+ fo.write("\n\n")
+
+ def json(self, jl):
+ jl.append(["$ALIAS", self.sym_alias, self.sym_name])
+
+
#######################################################################
DISPATCH = {
@@ -846,6 +893,7 @@ DISPATCH = {
"Object": ObjectStanza,
"Method": MethodStanza,
"Synopsis": SynopsisStanza,
+ "Alias": AliasStanza,
}
diff --git a/vmod/vmod_debug.vcc b/vmod/vmod_debug.vcc
index b3ff9ac4d..2fb67e8ab 100644
--- a/vmod/vmod_debug.vcc
+++ b/vmod/vmod_debug.vcc
@@ -374,3 +374,10 @@ $Object caller(SUB)
$Method VOID .call()
$Method SUB .xsub()
+
+DEPRECATED
+==========
+
+$Alias .bar obj.foo
+
+Bar was wrong, it was definitely foo.
More information about the varnish-commit
mailing list