summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/printf/glue.c18
-rw-r--r--lib/printfrr.h11
2 files changed, 29 insertions, 0 deletions
diff --git a/lib/printf/glue.c b/lib/printf/glue.c
index 389f503c33..2c97dd639e 100644
--- a/lib/printf/glue.c
+++ b/lib/printf/glue.c
@@ -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);
+}
diff --git a/lib/printfrr.h b/lib/printfrr.h
index 8245a664b3..6ca4d963c4 100644
--- a/lib/printfrr.h
+++ b/lib/printfrr.h
@@ -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