About extensible prinf(3), a slightly long X-mas card
Matthew N. Dodd
mdodd at FreeBSD.ORG
Sat Dec 17 09:57:44 PST 2005
On Fri, 16 Dec 2005, Poul-Henning Kamp wrote:
> If this proves useful, it'll stay in the tree and be part of 7.0 (no MFCs!)
> it people break out in bikesheds about it, it will not.
I'd rather leave the single letter specifiers and modifiers to the
standards compliant printf and use something like %{foo} as the specifier
for extensions.
I've re-arranged some of the internals to make this easier to implement,
and stubbed out the parsing of the %{} formats. I'm a little unsure what
sort of errors to throw on extension lookup failure.
...
What are your feelings on implementing things in such a way that the
compiler could use this same sort of extension plugin to perform type
checking?
-------------- next part --------------
Index: include/printf.h
===================================================================
RCS file: /home/cvs/src/include/printf.h,v
retrieving revision 1.1
diff -u -u -r1.1 printf.h
--- include/printf.h 16 Dec 2005 18:56:38 -0000 1.1
+++ include/printf.h 17 Dec 2005 17:13:27 -0000
@@ -74,6 +74,7 @@
const char *begin;
const char *end;
void *arg[__PRINTFMAXARG];
+ struct arg_function *arg_fcn;
};
enum {
@@ -105,6 +106,12 @@
struct __printf_io;
typedef int printf_render(struct __printf_io *, const struct printf_info *, const void *const *);
+struct arg_function {
+ printf_arginfo_function *arginfo;
+ printf_function *gnurender;
+ printf_render *render;
+};
+
/* vprintf.c */
extern const char __lowercase_hex[17];
extern const char __uppercase_hex[17];
Index: lib/libc/stdio/xprintf.c
===================================================================
RCS file: /home/cvs/src/lib/libc/stdio/xprintf.c,v
retrieving revision 1.1
diff -u -u -r1.1 xprintf.c
--- lib/libc/stdio/xprintf.c 16 Dec 2005 18:56:38 -0000 1.1
+++ lib/libc/stdio/xprintf.c 17 Dec 2005 17:48:37 -0000
@@ -230,11 +230,7 @@
/* table -------------------------------------------------------------*/
/*lint -esym(785, printf_tbl) */
-static struct {
- printf_arginfo_function *arginfo;
- printf_function *gnurender;
- printf_render *render;
-} printf_tbl[256] = {
+struct arg_function printf_tbl[256] = {
['%'] = { __printf_arginfo_pct, NULL, __printf_render_pct },
['A'] = { __printf_arginfo_float, NULL, __printf_render_float },
['C'] = { __printf_arginfo_chr, NULL, __printf_render_chr },
@@ -429,13 +425,31 @@
pi->is_size = 1;
fmt++;
continue;
+ case '{':
+ /* Skip { */
+ pi->spec++;
+
+ /* Look for end brace. */
+ while (*fmt++ != '}')
+ ;
+
+ /* No closing brace! */
+ if (*fmt == '\0')
+ abort();
+
+ /* len = pi->spec - fmt - 1 */
+ break;
default:
fmt++;
break;
}
- if (printf_tbl[pi->spec].arginfo == NULL)
+
+ if (pi->arg_fcn == NULL)
+ pi->arg_fcn = &printf_tbl[pi->spec];
+
+ if (pi->arg_fcn->arginfo == NULL)
errx(1, "arginfo[%c] = NULL", pi->spec);
- ch = printf_tbl[pi->spec].arginfo(
+ ch = pi->arg_fcn->arginfo(
pi, __PRINTFMAXARG, &argt[nextarg]);
if (ch > 0)
pi->arg[0] = &args[nextarg];
@@ -540,14 +554,14 @@
if (pi->get_prec)
pi->prec = args[pi->get_prec].intarg;
ret += __printf_puts(&io, pi->begin, pi->end - pi->begin);
- if (printf_tbl[pi->spec].gnurender != NULL) {
+ if (pi->arg_fcn->gnurender != NULL) {
__printf_flush(&io);
pi->sofar = ret;
- ret += printf_tbl[pi->spec].gnurender(
+ ret += pi->arg_fcn->gnurender(
fp, pi, (const void *)pi->arg);
- } else if (printf_tbl[pi->spec].render != NULL) {
+ } else if (pi->arg_fcn->render != NULL) {
pi->sofar = ret;
- n = printf_tbl[pi->spec].render(
+ n = pi->arg_fcn->render(
&io, pi, (const void *)pi->arg);
if (n < 0)
io.fp->_flags |= __SERR;
More information about the freebsd-current
mailing list