]> git.saurik.com Git - apple/libc.git/blob - stdio/xprintf.5
Libc-1272.250.1.tar.gz
[apple/libc.git] / stdio / xprintf.5
1 .Dd Aug 19, 2012
2 .Dt XPRINTF 5
3 .Os Darwin
4 .Sh NAME
5 .Nm xprintf
6 .Nd extensible printf
7 .Sh SYNOPSIS
8 .In printf.h
9 .Ft "typedef int"
10 .Fn printf_arginfo_function "const struct printf_info *info" "size_t n" "int *argtypes"
11 .Ft "typedef int"
12 .Fn printf_function "FILE *stream" "const struct printf_info *info" "const void *const *args"
13 .Sh DESCRIPTION
14 The standard
15 .Xr printf 3
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
19 start with the
20 .Sq Li %
21 character and end with a conversion specifier character (like
22 .Sq Li d
23 or
24 .Sq Li f ) ,
25 with conversion flag characters in-between.
26 .Pp
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:
32 .Pp
33 .Li http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html
34 .Pp
35 The main problem with the usual forms of extensible printf is that
36 changes to
37 .Xr printf 3
38 are program-wide.
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
42 former.
43 .Pp
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
50 .Xr xprintf 3
51 variant along with the format string and arguments to generate output.
52 The standard
53 .Xr printf 3
54 behavior is never affected.
55 .Pp
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.
60 .Pp
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.
66 Important fields in
67 .Vt struct printf_info
68 are:
69 .Bl -tag -width ".Va is_long_double"
70 .It Va alt
71 Boolean value whether the
72 .Sq Li #
73 flag was specified.
74 .It Va context
75 A
76 .Vt void *
77 pointer to arbitrary data specified in the original call to
78 .Xr register_printf_domain_function 3 .
79 .It Va group
80 Boolean value whether the
81 .Sq Li '
82 flag was specified.
83 .It Va is_char
84 Boolean value whether the
85 .Sq Li hh
86 flag was specified.
87 .It Va is_intmax
88 Boolean value whether the
89 .Sq Li j
90 flag was specified.
91 .It Va is_long
92 Boolean value whether the
93 .Sq Li l
94 flag was specified.
95 .It Va is_long_double
96 Boolean value whether the
97 .Sq Li L
98 or
99 .Sq Li ll
100 flags were specified.
101 .It Va is_ptrdiff
102 Boolean value whether the
103 .Sq Li t
104 flag was specified.
105 .It Va is_quad
106 Boolean value whether the
107 .Sq Li q
108 flag was specified.
109 .It Va is_short
110 Boolean value whether the
111 .Sq Li h
112 flag was specified.
113 .It Va is_size
114 Boolean value whether the
115 .Sq Li z
116 flag was specified.
117 .It Va is_vec
118 Boolean value whether the
119 .Sq Li v
120 flag was specified.
121 .It Va left
122 Boolean value whether the
123 .Sq Li -
124 flag was specified.
125 .It Va loc
126 The extended locale (see
127 .Xr xlocale 3 )
128 specified by the extensible printf caller (never
129 .Dv NULL ) .
130 .It Va pad
131 The padding character; either
132 .Sq Li 0
133 or space.
134 .It Va prec
135 The value of the optional precision.
136 -1 means the precision was unspecified.
137 .It Va showsign
138 Boolean value whether the
139 .Sq Li +
140 flag was specified.
141 .It Va signchar
142 The sign character, either
143 .Sq Li + ,
144 space or zero if none.
145 .It Va space
146 Boolean value whether the space flag was specified.
147 .It Va spec
148 The specifier character itself.
149 .It Va vsep
150 The separator character between vector items (using the
151 .Sq Li v
152 flag).
153 Can be any one of the four characters
154 .Dq Li ,:;_
155 or
156 .Sq Li X
157 if no separator character was specified (meaning that a space is used as the
158 separator, unless the specifier is
159 .Sq Li c ,
160 in which case no separator is used).
161 .It Va width
162 The value of the minimum field width (defaults to zero).
163 .El
164 .Pp
165 All other structure fields are either unused or private (and shouldn't be
166 used).
167 .Pp
168 This
169 .Vt struct printf_info
170 structure is then passed to the corresponding
171 .Nm printf_arginfo_function
172 callback 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
176 .Dv __PRINTFMAXARG ,
177 which is currently set to 2, but could be increased in the future if there is
178 need).
179 .Pp
180 The callback function is also passed an integer array and the length of that
181 array; the length will typically be
182 .Dv __PRINTFMAXARG .
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"
186 .It Dv PA_CHAR
187 The argument type is an
188 .Vt int
189 cast to a
190 .Vt char .
191 .It Dv PA_DOUBLE
192 The argument type is a
193 .Vt double .
194 OR-ing
195 .Dv PA_DOUBLE
196 with
197 .Dv PA_FLAG_LONG_DOUBLE
198 specifies a
199 .Vt "long double"
200 type.
201 .It Dv PA_FLOAT
202 (Defined but unused; best to avoid, since
203 .Vt float
204 is automatically promoted to
205 .Vt double
206 anyways.)
207 .It Dv PA_INT
208 The argument type is
209 .Vt int
210 (either signed or unsigned).
211 The size can be adjusted by OR-ing the following values to
212 .Dv PA_INT :
213 .Bl -tag -width ".Dv PA_FLAG_LONG_LONG"
214 .It Dv PA_FLAG_INTMAX
215 The integer is the size of a
216 .Vt intmax_t .
217 .It Dv PA_FLAG_LONG
218 The integer is the size of a
219 .Vt long .
220 .It Dv PA_FLAG_LONG_LONG
221 The integer is the size of a
222 .Vt "long long" .
223 .It Dv PA_FLAG_PTRDIFF
224 The integer is the size of a
225 .Vt ptrdiff_t .
226 .It Dv PA_FLAG_QUAD
227 The integer is the size of a
228 .Vt quad_t
229 (deprecated).
230 .It Dv PA_FLAG_SHORT
231 The integer is the size of a
232 .Vt short .
233 .It Dv PA_FLAG_SIZE
234 The integer is the size of a
235 .Vt size_t .
236 .El
237 .It Dv PA_POINTER
238 The argument type is a pointer type, cast to a
239 .Vt "void *" .
240 .It Dv PA_STRING
241 The argument type is a null-terminated character string
242 .Vt ( "char *" ) .
243 .It Dv PA_VECTOR
244 The argument type is an AltiVec or SSE vector (16 bytes).
245 .It Dv PA_WCHAR
246 The argument type is a
247 .Vt wchar_t .
248 .It Dv PA_WSTRING
249 The argument type is a null-terminated wide character string
250 .Vt ( "wchar_t *" ) .
251 .El
252 .Pp
253 After the
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.
258 .Pp
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.
269 .Sh EXAMPLE
270 Here is an example that demonstrates many of the features of extensible printf:
271 .Bd -literal
272 #include <stdio.h>
273 #include <stdlib.h>
274 #include <printf.h>
275 #include <locale.h>
276 #include <xlocale.h>
277 #include <err.h>
278
279 /* The Coordinate type */
280 typedef struct {
281 double x;
282 double y;
283 } Coordinate;
284
285 #define L (1 << 0)
286 #define P (1 << 1)
287
288 /* The renderer callback for Coordinate */
289 static int
290 print_coordinate (FILE *stream, const struct printf_info *info,
291 const void *const *args)
292 {
293 const Coordinate *c;
294 int width, ret, which = 0;
295 char fmt[32];
296 char *bp, *cp, *ep;
297 /* The optional coordinate labels */
298 const char **labels = (const char **)info->context;
299
300 /* Get the argument pointer to a Coordinate */
301 c = *((const Coordinate **) (args[0]));
302
303 /* Set up the format string */
304 cp = fmt;
305 if(info->alt) *cp++ = '(';
306 bp = cp;
307 if(labels) {
308 which |= L;
309 *cp++ = '%';
310 *cp++ = 's';
311 }
312 *cp++ = '%';
313 if(info->group) *cp++ = '\e'';
314 *cp++ = '*';
315 if(info->prec >= 0) {
316 which |= P;
317 *cp++ = '.';
318 *cp++ = '*';
319 }
320 *cp++ = 'l';
321 *cp++ = 'f';
322 ep = cp;
323 if(info->alt) *cp++ = ',';
324 *cp++ = ' ';
325 while(bp < ep) *cp++ = *bp++;
326 if(info->alt) *cp++ = ')';
327 *cp = 0;
328
329 width = info->left ? -info->width : info->width;
330
331 /* Output to the given stream */
332 switch(which) {
333 case 0:
334 ret = fprintf_l(stream, info->loc, fmt, width, c->x, width, c->y);
335 break;
336 case L:
337 ret = fprintf_l(stream, info->loc, fmt, labels[0], width, c->x,
338 labels[1], width, c->y);
339 break;
340 case P:
341 ret = fprintf_l(stream, info->loc, fmt, width, info->prec, c->x,
342 width, info->prec, c->y);
343 break;
344 case (L | P):
345 ret = fprintf_l(stream, info->loc, fmt, labels[0], width,
346 info->prec, c->x, labels[1], width, info->prec,
347 c->y);
348 break;
349 }
350
351 return ret;
352 }
353
354 /* The arginfo callback for Coordinate */
355 static int
356 coordinate_arginfo (const struct printf_info *info, size_t n,
357 int *argtypes)
358 {
359 /* We always take exactly one argument and this is a pointer to the
360 structure.. */
361 if (n > 0)
362 argtypes[0] = PA_POINTER;
363 return 1;
364 }
365
366 int
367 main (void)
368 {
369 Coordinate mycoordinate = {12345.6789, 3.141593};
370 printf_domain_t domain;
371 locale_t loc;
372 const char *labels[] = {"x=", "y="};
373
374 /* Set up a domain to add support for Coordinate conversion */
375 domain = new_printf_domain();
376 if(!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);
380 if(!loc)
381 err(1, "newlocale");
382
383 /* Register the callbacks for Coordinates in the domain */
384 register_printf_domain_function (domain, 'C', print_coordinate,
385 coordinate_arginfo, NULL);
386
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);
394
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");
402
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);
410
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);
420
421 return 0;
422 }
423 .Ed
424 .Pp
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
428 .Sq Li #
429 (alternate form) flag, as parenthesized numbers separated by a comma.
430 Note the use of
431 .Nm printf_l
432 to do the actual output; this is using regular printf from within an extensible
433 printf renderer callback.
434 The use of
435 .Nm printf_l
436 also insures correct handling of extended locales.
437 .Pp
438 The output of the programs looks like:
439 .Bd -literal
440 |12345.678900 3.141593|
441 | 12345.678900 3.141593|
442 |12345.68 3.14 |
443 |(12345.678900, 3.141593)|
444 |( 12345.678900, 3.141593)|
445 |(12345.68 , 3.14 )|
446 -------------
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 )|
453 -------------
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 )|
460 .Ed
461 .Pp
462 Notice:
463 .Bl -bullet
464 .It
465 Field width, precision and left adjustment are applied to each of the numbers.
466 .It
467 The alternate form, using parenthesized numbers separated by a comma.
468 .It
469 In the second group of six, the thousands separator corresponds to the
470 global locale setting
471 .Pq Li en_US.UTF-8 .
472 .It
473 The second and third group have a label for each number, provide through
474 the user-defined context argument.
475 .It
476 The third group has the decimal point and thousands separator of the extended
477 locale argument
478 .Pq Li uk_UA.UTF-8 .
479 .El
480 .Sh PERFORMANCE
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
484 .Xr printf 3 .
485 Recursive use of
486 .Xr printf 3
487 from within an extensible printf renderer callback
488 (as in the
489 .Sx EXAMPLE
490 above) adds additional overhead.
491 .Pp
492 To ameliorate some of this slowness, the concept of separate compilation
493 and execution phases has be added to extensible printf.
494 The functions in
495 .Xr xprintf_comp 3
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
499 .Xr xprintf_exec 3
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
502 any number of times.
503 .Pp
504 A simple example of use is:
505 .Bd -literal
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]);
509 }
510 free_printf_comp(pc);
511 .Ed
512 .Pp
513 Here,
514 .Va coords
515 is a array containing
516 .Vt Coordinate
517 structures that are to be printed and the
518 .Va domain
519 and
520 .Va loc
521 variables are as from
522 .Sx EXAMPLE
523 above.
524 (Error checking on the return value from
525 .Fn new_printf_comp
526 is not shown).
527 .Sh SEE ALSO
528 .Xr printf 3 ,
529 .Xr xlocale 3 ,
530 .Xr xprintf 3 ,
531 .Xr xprintf_comp 3 ,
532 .Xr xprintf_domain 3 ,
533 .Xr xprintf_exec 3