10 .Fn printf_arginfo_function "const struct printf_info *info" "size_t n" "int *argtypes"
12 .Fn printf_function "FILE *stream" "const struct printf_info *info" "const void *const *args"
16 family of routines provides a convenient way to convert one or more arguments
17 to various forms for output, under the control of a format string.
18 The format string may contain any number of conversion specifications, which
21 character and end with a conversion specifier character (like
25 with conversion flag characters in-between.
27 Extensible printf is an enhancement that allows adding new (user-defined)
28 conversion specifiers, or modifying/removing existing ones.
29 The implementation of extensible printf in Mac OS X is derived from the
30 FreeBSD version, which is based on the one in GNU libc (GLIBC).
31 Documentation for the GLIBC version is available at:
33 .Li http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html
35 The main problem with the usual forms of extensible printf is that
39 But this is unsafe, since frameworks,
40 libraries or some other thread could change printf behavior in ways
41 unexpected by the main program, or the latter could unexpectedly affect the
44 So instead, the implementation used in Mac OS X makes
45 changes to conversion specifiers within printf domains,
46 which are independent structures containing the specifier definitions.
47 These domains are created as described in
48 .Xr xprintf_domain 3 ,
49 and once set up, it can be passed to a
51 variant along with the format string and arguments to generate output.
54 behavior is never affected.
56 To define a new conversion specifier, two function typedefs are defined, and
57 the user must provide two functions based on these typedefs.
58 These functions will get called from extensible printf while processing
59 the corresponding conversion specification.
61 During the first of three phases of extensible printf processing, the format
62 string is parsed, and for each conversion specification, a
63 .Vt struct printf_info
64 is created, containing the option flags specified in the
65 conversion specification as well as other settings.
67 .Vt struct printf_info
69 .Bl -tag -width ".Va is_long_double"
71 Boolean value whether the
77 pointer to arbitrary data specified in the original call to
78 .Xr register_printf_domain_function 3 .
80 Boolean value whether the
84 Boolean value whether the
88 Boolean value whether the
92 Boolean value whether the
96 Boolean value whether the
100 flags were specified.
102 Boolean value whether the
106 Boolean value whether the
110 Boolean value whether the
114 Boolean value whether the
118 Boolean value whether the
122 Boolean value whether the
126 The extended locale (see
128 specified by the extensible printf caller (never
131 The padding character; either
135 The value of the optional precision.
136 -1 means the precision was unspecified.
138 Boolean value whether the
142 The sign character, either
144 space or zero if none.
146 Boolean value whether the space flag was specified.
148 The specifier character itself.
150 The separator character between vector items (using the
153 Can be any one of the four characters
157 if no separator character was specified (meaning that a space is used as the
158 separator, unless the specifier is
160 in which case no separator is used).
162 The value of the minimum field width (defaults to zero).
165 All other structure fields are either unused or private (and shouldn't be
169 .Vt struct printf_info
170 structure is then passed to the corresponding
171 .Nm printf_arginfo_function
173 The callback function should return the number of consecutive arguments the
174 specifier handles, including zero (the maximum number of consecutive arguments
175 a single specifier can handle is
177 which is currently set to 2, but could be increased in the future if there is
180 The callback function is also passed an integer array and the length of that
181 array; the length will typically be
183 The function should fill out the array up to the number of arguments it expects,
184 using the following values:
185 .Bl -tag -width ".Dv PA_POINTER"
187 The argument type is an
192 The argument type is a
197 .Dv PA_FLAG_LONG_DOUBLE
202 (Defined but unused; best to avoid, since
204 is automatically promoted to
210 (either signed or unsigned).
211 The size can be adjusted by OR-ing the following values to
213 .Bl -tag -width ".Dv PA_FLAG_LONG_LONG"
214 .It Dv PA_FLAG_INTMAX
215 The integer is the size of a
218 The integer is the size of a
220 .It Dv PA_FLAG_LONG_LONG
221 The integer is the size of a
223 .It Dv PA_FLAG_PTRDIFF
224 The integer is the size of a
227 The integer is the size of a
231 The integer is the size of a
234 The integer is the size of a
238 The argument type is a pointer type, cast to a
241 The argument type is a null-terminated character string
244 The argument type is an AltiVec or SSE vector (16 bytes).
246 The argument type is a
249 The argument type is a null-terminated wide character string
250 .Vt ( "wchar_t *" ) .
254 .Nm printf_arginfo_function
255 returns, phase 2 of extensible printf processing involves converting the
256 argument according to the types specified by the returned type array.
257 Note that positional arguments are dealt with here as well.
259 Then in phase 3, output is generated, either from the text in-between the
260 conversion specifications, or by calling the so-called rendering functions
261 associated with each conversion specifier (with typedef
262 .Nm printf_function ) .
263 The rendering function is passed the same
264 .Vt struct printf_info
265 structure, as well as an array of pointers to each of the arguments converted
266 in phase 2 that it is responsible for.
267 The callback should write its output to the provided output
268 stdio stream, and then return the number of characters written.
270 Here is an example that demonstrates many of the features of extensible printf:
279 /* The Coordinate type */
288 /* The renderer callback for Coordinate */
290 print_coordinate (FILE *stream, const struct printf_info *info,
291 const void *const *args)
294 int width, ret, which = 0;
297 /* The optional coordinate labels */
298 const char **labels = (const char **)info->context;
300 /* Get the argument pointer to a Coordinate */
301 c = *((const Coordinate **) (args[0]));
303 /* Set up the format string */
305 if(info->alt) *cp++ = '(';
313 if(info->group) *cp++ = '\e'';
315 if(info->prec >= 0) {
323 if(info->alt) *cp++ = ',';
325 while(bp < ep) *cp++ = *bp++;
326 if(info->alt) *cp++ = ')';
329 width = info->left ? -info->width : info->width;
331 /* Output to the given stream */
334 ret = fprintf_l(stream, info->loc, fmt, width, c->x, width, c->y);
337 ret = fprintf_l(stream, info->loc, fmt, labels[0], width, c->x,
338 labels[1], width, c->y);
341 ret = fprintf_l(stream, info->loc, fmt, width, info->prec, c->x,
342 width, info->prec, c->y);
345 ret = fprintf_l(stream, info->loc, fmt, labels[0], width,
346 info->prec, c->x, labels[1], width, info->prec,
354 /* The arginfo callback for Coordinate */
356 coordinate_arginfo (const struct printf_info *info, size_t n,
359 /* We always take exactly one argument and this is a pointer to the
362 argtypes[0] = PA_POINTER;
369 Coordinate mycoordinate = {12345.6789, 3.141593};
370 printf_domain_t domain;
372 const char *labels[] = {"x=", "y="};
374 /* Set up a domain to add support for Coordinate conversion */
375 domain = new_printf_domain();
377 err(1, "new_printf_domain");
378 /* Set up an extended locale to test locale support */
379 loc = newlocale(LC_ALL_MASK, "uk_UA.UTF-8", NULL);
383 /* Register the callbacks for Coordinates in the domain */
384 register_printf_domain_function (domain, 'C', print_coordinate,
385 coordinate_arginfo, NULL);
387 /* Print the coordinate using the current locale (C). */
388 xprintf(domain, NULL, "|%'C|\en", &mycoordinate);
389 xprintf(domain, NULL, "|%'14C|\en", &mycoordinate);
390 xprintf(domain, NULL, "|%'-14.2C|\en", &mycoordinate);
391 xprintf(domain, NULL, "|%'#C|\en", &mycoordinate);
392 xprintf(domain, NULL, "|%'#14C|\en", &mycoordinate);
393 xprintf(domain, NULL, "|%'#-14.2C|\en", &mycoordinate);
395 printf("-------------\en");
396 /* Reregister the callbacks, specifying coordinate labels
397 * and setting the global locale (notice thousands separator) */
398 register_printf_domain_function (domain, 'C', print_coordinate,
399 coordinate_arginfo, labels);
400 if(setlocale(LC_ALL, "en_US.UTF-8") == NULL)
401 errx(1, "setlocale");
403 /* Reprint with labels */
404 xprintf(domain, NULL, "|%'C|\en", &mycoordinate);
405 xprintf(domain, NULL, "|%'14C|\en", &mycoordinate);
406 xprintf(domain, NULL, "|%'-14.2C|\en", &mycoordinate);
407 xprintf(domain, NULL, "|%'#C|\en", &mycoordinate);
408 xprintf(domain, NULL, "|%'#14C|\en", &mycoordinate);
409 xprintf(domain, NULL, "|%'#-14.2C|\en", &mycoordinate);
411 printf("-------------\en");
412 /* Now print with the test locale (notice decimal point and
413 * thousands separator) */
414 xprintf(domain, loc, "|%'C|\en", &mycoordinate);
415 xprintf(domain, loc, "|%'14C|\en", &mycoordinate);
416 xprintf(domain, loc, "|%'-14.2C|\en", &mycoordinate);
417 xprintf(domain, loc, "|%'#C|\en", &mycoordinate);
418 xprintf(domain, loc, "|%'#14C|\en", &mycoordinate);
419 xprintf(domain, loc, "|%'#-14.2C|\en", &mycoordinate);
425 This example defines a Coordinate type, that consists of a pair of doubles.
426 We create a conversion specifier that displays a Coordinate type, either just
427 as two floating point numbers, or with the
429 (alternate form) flag, as parenthesized numbers separated by a comma.
432 to do the actual output; this is using regular printf from within an extensible
433 printf renderer callback.
436 also insures correct handling of extended locales.
438 The output of the programs looks like:
440 |12345.678900 3.141593|
441 | 12345.678900 3.141593|
443 |(12345.678900, 3.141593)|
444 |( 12345.678900, 3.141593)|
447 |x=12,345.678900 y=3.141593|
448 |x= 12,345.678900 y= 3.141593|
449 |x=12,345.68 y=3.14 |
450 |(x=12,345.678900, y=3.141593)|
451 |(x= 12,345.678900, y= 3.141593)|
452 |(x=12,345.68 , y=3.14 )|
454 |x=12 345,678900 y=3,141593|
455 |x= 12 345,678900 y= 3,141593|
456 |x=12 345,68 y=3,14 |
457 |(x=12 345,678900, y=3,141593)|
458 |(x= 12 345,678900, y= 3,141593)|
459 |(x=12 345,68 , y=3,14 )|
465 Field width, precision and left adjustment are applied to each of the numbers.
467 The alternate form, using parenthesized numbers separated by a comma.
469 In the second group of six, the thousands separator corresponds to the
470 global locale setting
473 The second and third group have a label for each number, provide through
474 the user-defined context argument.
476 The third group has the decimal point and thousands separator of the extended
481 Because of the three phase processing of extensible printf, as well as the
482 use of two callbacks for each conversion specifier, performance is
483 considerably slower than the one pass, highly optimized regular
487 from within an extensible printf renderer callback
490 above) adds additional overhead.
492 To ameliorate some of this slowness, the concept of separate compilation
493 and execution phases has be added to extensible printf.
496 allow the creation of pre-compiled extensible printf structures (performing
497 phase one of extensible printf processing).
498 These pre-compiled structures can then be passed to the printf variants in
500 to produce the actual output (performing phases 2 and 3).
501 The compilation phase need only be done once, while execution can be performed
504 A simple example of use is:
506 printf_comp_t pc = new_printf_comp(domain, loc, "%d: %C\en");
507 for(i = 0; i = sizeof(coords) / sizeof(*coords); i++) {
508 xprintf_exec(pc, i, &coords[i]);
510 free_printf_comp(pc);
515 is a array containing
517 structures that are to be printed and the
521 variables are as from
524 (Error checking on the return value from
532 .Xr xprintf_domain 3 ,