]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add `%pVA` recursive printfrr
authorDavid Lamparter <equinox@diac24.net>
Tue, 2 Mar 2021 19:45:57 +0000 (20:45 +0100)
committerDavid Lamparter <equinox@diac24.net>
Tue, 30 Mar 2021 20:32:59 +0000 (22:32 +0200)
Analogous to Linux kernel `%pV` (but our mechanism expects 2 specifier
chars and `%pVA` is clearer anyway.)

Signed-off-by: David Lamparter <equinox@diac24.net>
doc/developer/logging.rst
lib/printf/glue.c
lib/printfrr.h
tests/lib/test_printfrr.c

index a35e60619c25002b7dd76527e0795a3eca0c1752..5e8cb79cc25af65cc44956cbb908128f73c36632 100644 (file)
@@ -65,6 +65,8 @@ Extensions
 +-----------+--------------------------+----------------------------------------------+
 | ``%Ld``   | ``int64_t``              | ``-12345``                                   |
 +-----------+--------------------------+----------------------------------------------+
+| ``%pVA``  | ``struct va_format *``   | (recursive printfrr)                         |
++-----------+--------------------------+----------------------------------------------+
 | ``%pI4``  | ``struct in_addr *``     | ``1.2.3.4``                                  |
 |           |                          |                                              |
 |           | ``in_addr_t *``          |                                              |
index 389f503c334facfbec43d3b470a391f1dd62b9fc..2c97dd639e66390ab0a210a5d4861320afae37ae 100644 (file)
@@ -255,3 +255,21 @@ ssize_t printfrr_exti(struct fbuf *buf, struct printfrr_eargs *ea,
        }
        return -1;
 }
+
+printfrr_ext_autoreg_p("VA", printfrr_va)
+static ssize_t printfrr_va(struct fbuf *buf, struct printfrr_eargs *ea,
+                          const void *ptr)
+{
+       const struct va_format *vaf = ptr;
+       va_list ap;
+
+       if (!vaf || !vaf->fmt || !vaf->va)
+               return bputs(buf, "NULL");
+
+       /* make sure we don't alter the data passed in - especially since
+        * bprintfrr (and thus this) might be called on the same format twice,
+        * when allocating a larger buffer in asnprintfrr()
+        */
+       va_copy(ap, *vaf->va);
+       return vbprintfrr(buf, vaf->fmt, ap);
+}
index 8245a664b3187df8c90abe32a87de61c75972de8..6ca4d963c4499d813c36ac89ffcd70073bcb04e3 100644 (file)
@@ -251,6 +251,17 @@ static inline ssize_t bputch(struct fbuf *buf, char ch)
        return 1;
 }
 
+/* %pVA extension, equivalent to Linux kernel %pV */
+
+struct va_format {
+       const char *fmt;
+       va_list *va;
+};
+
+#ifdef _FRR_ATTRIBUTE_PRINTFRR
+#pragma FRR printfrr_ext "%pVA" (struct va_format *)
+#endif
+
 /* when using non-ISO-C compatible extension specifiers... */
 
 #ifdef _FRR_ATTRIBUTE_PRINTFRR
index 5a8d10e9b78ffe0b74a6a6f60af6aeda64ce1963..8fa8bfcc2361af43f07fa5f1488f93a1419dd9e4 100644 (file)
@@ -128,6 +128,21 @@ static int printchk(const char *ref, const char *fmt, ...)
        return 0;
 }
 
+static void test_va(const char *ref, const char *fmt, ...) PRINTFRR(2, 3);
+static void test_va(const char *ref, const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list ap;
+
+       va_start(ap, fmt);
+       vaf.fmt = fmt;
+       vaf.va = &ap;
+
+       printchk(ref, "VA [%pVA] %s", &vaf, "--");
+
+       va_end(ap);
+}
+
 int main(int argc, char **argv)
 {
        size_t i;
@@ -168,6 +183,8 @@ int main(int argc, char **argv)
 
        printcmp("%p", &ip);
 
+       test_va("VA [192.168.1.2 1234] --", "%pI4 %u", &ip, 1234);
+
        snprintfrr(buf, sizeof(buf), "test%s", "#1");
        csnprintfrr(buf, sizeof(buf), "test%s", "#2");
        assert(strcmp(buf, "test#1test#2") == 0);