* Non-MT-safe version
*/
ssize_t
-vbprintfrr(struct fbuf *cb, const char *fmt0, va_list ap)
+vbprintfrr(struct fbuf *cb_in, const char *fmt0, va_list ap)
{
const char *fmt; /* format string */
int ch; /* character from fmt */
va_list orgap; /* original argument pointer */
char *convbuf; /* wide to multibyte conversion result */
char *extstart = NULL; /* where printfrr_ext* started printing */
+ struct fbuf cb_copy, *cb;
+ struct fmt_outpos *opos;
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
+
+ if (cb_in) {
+ /* prevent printfrr exts from polluting cb->outpos */
+ cb_copy = *cb_in;
+ cb_copy.outpos = NULL;
+ cb_copy.outpos_n = cb_copy.outpos_i = 0;
+ cb = &cb_copy;
+ } else
+ cb = NULL;
+
io_init(&io, cb);
ret = 0;
sign = '\0';
ox[1] = '\0';
+ if (cb_in && cb_in->outpos_i < cb_in->outpos_n)
+ opos = &cb_in->outpos[cb_in->outpos_i];
+ else
+ opos = NULL;
+
rflag: ch = *fmt++;
reswitch: switch (ch) {
case ' ':
size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
sign = '\0';
break;
-#ifdef DANGEROUS_PERCENT_N
- /* FRR does not use %n in printf formats. This is just left
- * here in case someone tries to use %n and starts debugging
- * why the f* it doesn't work
- */
- case 'n':
- /*
- * Assignment-like behavior is specified if the
- * value overflows or is otherwise unrepresentable.
- * C99 says to use `signed char' for %hhn conversions.
- */
- if (flags & LLONGINT)
- *GETARG(long long *) = ret;
- else if (flags & SIZET)
- *GETARG(ssize_t *) = (ssize_t)ret;
- else if (flags & PTRDIFFT)
- *GETARG(ptrdiff_t *) = ret;
- else if (flags & INTMAXT)
- *GETARG(intmax_t *) = ret;
- else if (flags & LONGINT)
- *GETARG(long *) = ret;
- else if (flags & SHORTINT)
- *GETARG(short *) = ret;
- else if (flags & CHARINT)
- *GETARG(signed char *) = ret;
- else
- *GETARG(int *) = ret;
- continue; /* no output */
-#endif
case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
cp = buf;
size = 1;
sign = '\0';
+ opos = NULL;
break;
}
if ((flags & (LADJUST|ZEROPAD)) == 0)
PAD(width - realsz, blanks);
+ if (opos)
+ opos->off_start = cb->pos - cb->buf;
+
/* prefix */
if (sign)
PRINT(&sign, 1);
/* leading zeroes from decimal precision */
PAD(dprec - size, zeroes);
PRINT(cp, size);
+
+ if (opos) {
+ opos->off_end = cb->pos - cb->buf;
+ cb_in->outpos_i++;
+ }
+
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
PAD(width - realsz, blanks);
cb->pos = extstart;
PAD(npad, blanks);
cb->pos += nmove;
+ extstart += npad;
}
io.avail = cb ? cb->len - (cb->pos - cb->buf) : 0;
+ if (opos && extstart <= cb->pos) {
+ opos->off_start = extstart - cb->buf;
+ opos->off_end = cb->pos - cb->buf;
+ cb_in->outpos_i++;
+ }
+
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
PAD(width - realsz, blanks);
free(convbuf);
if ((argtable != NULL) && (argtable != statargtable))
free (argtable);
+ if (cb_in)
+ cb_in->pos = cb->pos;
return (ret);
/* NOTREACHED */
}
errors++;
}
+ struct fmt_outpos outpos[16];
+ struct fbuf fb = {
+ .buf = bufrr,
+ .pos = bufrr,
+ .len = sizeof(bufrr) - 1,
+ .outpos = outpos,
+ .outpos_n = array_size(outpos),
+ };
+
va_start(ap, fmt);
- vsnprintfrr(bufrr, sizeof(bufrr), fmt, ap);
+ vbprintfrr(&fb, fmt, ap);
+ fb.pos[0] = '\0';
va_end(ap);
- printf("fmt: \"%s\"\nref: \"%s\"\nfrr: \"%s\"\n%s\n\n",
+ printf("fmt: \"%s\"\nref: \"%s\"\nfrr: \"%s\"\n%s\n",
fmt, ref, bufrr, strcmp(ref, bufrr) ? "ERROR" : "ok");
if (strcmp(ref, bufrr))
errors++;
printf("return value <> length mismatch\n");
errors++;
}
+
+ for (size_t i = 0; i < fb.outpos_i; i++)
+ printf("\t[%zu: %u..%u] = \"%.*s\"\n", i,
+ outpos[i].off_start,
+ outpos[i].off_end,
+ (int)(outpos[i].off_end - outpos[i].off_start),
+ bufrr + outpos[i].off_start);
+ printf("\n");
}
int main(int argc, char **argv)