[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