summaryrefslogtreecommitdiffstats
path: root/lib/printf/glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/printf/glue.c')
-rw-r--r--lib/printf/glue.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/lib/printf/glue.c b/lib/printf/glue.c
index 29ca26ad5..114790123 100644
--- a/lib/printf/glue.c
+++ b/lib/printf/glue.c
@@ -210,15 +210,16 @@ void printfrr_ext_reg(const struct printfrr_ext *ext)
exts[i] = ext;
}
-ssize_t printfrr_extp(char *buf, size_t sz, const char *fmt, int prec,
+ssize_t printfrr_extp(struct fbuf *buf, struct printfrr_eargs *ea,
const void *ptr)
{
+ const char *fmt = ea->fmt;
const struct printfrr_ext *ext;
size_t i;
for (i = ext_offsets[fmt[0] - 'A']; i < MAXEXT; i++) {
if (!entries[i].fmt[0] || entries[i].fmt[0] > fmt[0])
- return 0;
+ return -1;
if (entries[i].fmt[1] && entries[i].fmt[1] != fmt[1])
continue;
ext = exts[i];
@@ -226,20 +227,22 @@ ssize_t printfrr_extp(char *buf, size_t sz, const char *fmt, int prec,
continue;
if (strncmp(ext->match, fmt, strlen(ext->match)))
continue;
- return ext->print_ptr(buf, sz, fmt, prec, ptr);
+ ea->fmt += strlen(ext->match);
+ return ext->print_ptr(buf, ea, ptr);
}
- return 0;
+ return -1;
}
-ssize_t printfrr_exti(char *buf, size_t sz, const char *fmt, int prec,
+ssize_t printfrr_exti(struct fbuf *buf, struct printfrr_eargs *ea,
uintmax_t num)
{
+ const char *fmt = ea->fmt;
const struct printfrr_ext *ext;
size_t i;
for (i = ext_offsets[fmt[0] - 'A']; i < MAXEXT; i++) {
if (!entries[i].fmt[0] || entries[i].fmt[0] > fmt[0])
- return 0;
+ return -1;
if (entries[i].fmt[1] && entries[i].fmt[1] != fmt[1])
continue;
ext = exts[i];
@@ -247,7 +250,48 @@ ssize_t printfrr_exti(char *buf, size_t sz, const char *fmt, int prec,
continue;
if (strncmp(ext->match, fmt, strlen(ext->match)))
continue;
- return ext->print_int(buf, sz, fmt, prec, num);
+ ea->fmt += strlen(ext->match);
+ return ext->print_int(buf, ea, num);
}
- return 0;
+ return -1;
+}
+
+printfrr_ext_autoreg_p("FB", printfrr_fb)
+static ssize_t printfrr_fb(struct fbuf *out, struct printfrr_eargs *ea,
+ const void *ptr)
+{
+ const struct fbuf *in = ptr;
+ ptrdiff_t copy_len;
+
+ if (!in)
+ return bputs(out, "NULL");
+
+ if (out) {
+ copy_len = MIN(in->pos - in->buf,
+ out->buf + out->len - out->pos);
+ if (copy_len > 0) {
+ memcpy(out->pos, in->buf, copy_len);
+ out->pos += copy_len;
+ }
+ }
+
+ return in->pos - in->buf;
+}
+
+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);
}