]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man3head/printf.h.3head
man*/: srcfix (Use .P instead of .PP or .LP)
[thirdparty/man-pages.git] / man3head / printf.h.3head
1 .\" Copyright (C) 2022 Alejandro Colomar <alx.manpages@gmail.com>
2 .\"
3 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
4 .\"
5 .TH printf.h 3head 2022-09-18 "Linux man-pages (unreleased)"
6 .SH NAME
7 printf.h,
8 \%register_printf_specifier,
9 \%register_printf_modifier,
10 \%register_printf_type,
11 \%printf_function,
12 \%printf_arginfo_size_function,
13 \%printf_va_arg_function,
14 \%printf_info,
15 \%PA_INT,
16 \%PA_CHAR,
17 \%PA_WCHAR,
18 \%PA_STRING,
19 \%PA_WSTRING,
20 \%PA_POINTER,
21 \%PA_FLOAT,
22 \%PA_DOUBLE,
23 \%PA_LAST,
24 \%PA_FLAG_LONG_LONG,
25 \%PA_FLAG_LONG_DOUBLE,
26 \%PA_FLAG_LONG,
27 \%PA_FLAG_SHORT,
28 \%PA_FLAG_PTR
29 \- define custom behavior for printf-like functions
30 .SH LIBRARY
31 Standard C library
32 .RI ( libc ", " \-lc )
33 .SH SYNOPSIS
34 .nf
35 .B #include <printf.h>
36 .P
37 .BI "int register_printf_specifier(int " spec ", printf_function " func ,
38 .BI " printf_arginfo_size_function " arginfo );
39 .BI "int register_printf_modifier(const wchar_t *" str );
40 .BI "int register_printf_type(printf_va_arg_function " fct );
41 .fi
42 .SS Callbacks
43 .nf
44 .BI "typedef int printf_function(FILE *" stream ", const struct printf_info *" info ,
45 .BI " const void *const " args []);
46 .BI "typedef int printf_arginfo_size_function(const struct printf_info *" info ,
47 .BI " size_t " n ", int " argtypes [ n "], int " size [ n ]);
48 .BI "typedef void printf_va_arg_function(void *" mem ", va_list *" ap );
49 .fi
50 .SS Types
51 .EX
52 .B struct printf_info {
53 .BR " int prec; " "// Precision"
54 .BR " int width; " "// Width"
55 .BR " wchar_t spec; " "// Format letter"
56 .BR " unsigned int is_long_double:1;" "// " L " or " ll " flag"
57 .BR " unsigned int is_short:1; " "// " h " flag"
58 .BR " unsigned int is_long:1; " "// " l " flag"
59 .BR " unsigned int alt:1; " "// " # " flag"
60 .BR " unsigned int space:1; " "// Space flag"
61 .BR " unsigned int left:1; " "// " - " flag"
62 .BR " unsigned int showsign:1; " "// " + " flag"
63 .BR " unsigned int group:1; " "// " \[aq] " flag"
64 .BR " unsigned int extra:1; " "// For special use"
65 .BR " unsigned int is_char:1; " "// " hh " flag"
66 .BR " unsigned int wide:1; " "// True for wide character streams"
67 .BR " unsigned int i18n:1; " "// " I " flag"
68 .BR " unsigned int is_binary128:1; " "/* Floating-point argument is"
69 .BR " " " ABI-compatible with"
70 .BR " " " IEC 60559 binary128 */"
71 .BR " unsigned short user; " "// Bits for user-installed modifiers"
72 .BR " wchar_t pad; " "// Padding character"
73 .B };
74 .EE
75 .SS Constants
76 .EX
77 .BR "#define PA_FLAG_LONG_LONG " "/* ... */"
78 .BR "#define PA_FLAG_LONG_DOUBLE " "/* ... */"
79 .BR "#define PA_FLAG_LONG " "/* ... */"
80 .BR "#define PA_FLAG_SHORT " "/* ... */"
81 .BR "#define PA_FLAG_PTR " "/* ... */"
82 .EE
83 .SH DESCRIPTION
84 These functions serve to extend and/or modify the behavior of the
85 .BR printf (3)
86 family of functions.
87 .SS register_printf_specifier()
88 This function registers a custom conversion specifier for the
89 .BR printf (3)
90 family of functions.
91 .TP
92 .I spec
93 The character which will be used as a conversion specifier in the format string.
94 .TP
95 .I func
96 Callback function that will be executed by the
97 .BR printf (3)
98 family of functions
99 to format the input arguments into the output
100 .IR stream .
101 .RS
102 .TP
103 .I stream
104 Output stream where the formatted output should be printed.
105 This stream transparently represents the output,
106 even in the case of functions that write to a string.
107 .TP
108 .I info
109 Structure that holds context information,
110 including the modifiers specified in the format string.
111 This holds the same contents as in
112 .IR arginfo .
113 .TP
114 .I args
115 Array of pointers to the arguments to the
116 .BR printf (3)\c
117 -like function.
118 .RE
119 .TP
120 .I arginfo
121 Callback function that will be executed by the
122 .BR printf (3)
123 family of functions
124 to know how many arguments should be parsed for the custom specifier
125 and also their types.
126 .RS
127 .TP
128 .I info
129 Structure that holds context information,
130 including the modifiers specified in the format string.
131 This holds the same contents as in
132 .IR func .
133 .TP
134 .I n
135 Number of arguments remaining to be parsed.
136 .TP
137 .I argtypes
138 This array should be set to
139 define the type of each of the arguments that will be parsed.
140 Each element in the array represents one of the arguments to be parsed,
141 in the same order that they are passed to the
142 .BR printf (3)\c
143 -like function.
144 Each element should be set to a base type
145 .RB ( PA_ *)
146 from the enum above,
147 or a custom one,
148 and optionally ORed with an appropriate length modifier
149 .RB ( PA_FLAG_ *).
150 .RS
151 .P
152 The type is determined by using one of the following constants:
153 .TP
154 .B PA_INT
155 .IR int .
156 .TP
157 .B PA_CHAR
158 .IR int ,
159 cast to
160 .IR char .
161 .TP
162 .B PA_WCHAR
163 .IR wchar_t .
164 .TP
165 .B PA_STRING
166 .IR "const char\~*" ,
167 a \(aq\e0\(aq-terminated string.
168 .TP
169 .B PA_WSTRING
170 .IR "const wchar_t\~*" ,
171 a wide character L\(aq\e0\(aq-terminated string.
172 .TP
173 .B PA_POINTER
174 .IR void\~* .
175 .TP
176 .B PA_FLOAT
177 .IR float .
178 .TP
179 .B PA_DOUBLE
180 .IR double .
181 .TP
182 .B PA_LAST
183 TODO.
184 .RE
185 .TP
186 .I size
187 For user-defined types,
188 the size of the type (in bytes) should also be specified through this array.
189 Otherwise, leave it unused.
190 .RE
191 .P
192 .I arginfo
193 is called before
194 .IR func ,
195 and prepares some information needed to call
196 .IR func .
197 .SS register_printf_modifier()
198 TODO
199 .SS register_printf_type()
200 TODO
201 .SH RETURN VALUE
202 .BR \%register_printf_specifier (),
203 .BR \%register_printf_modifier (),
204 and
205 .BR \%register_printf_type ()
206 return zero on success, or \-1 on error.
207 .SS Callbacks
208 The callback of type
209 .I printf_function
210 should return the number of characters written,
211 or \-1 on error.
212 .P
213 The callback of type
214 .I \%printf_arginfo_size_function
215 should return the number of arguments to be parsed by this specifier.
216 It also passes information about the type of those arguments
217 to the caller through
218 .IR argtypes .
219 On error, it should return \-1.
220 .SH ERRORS
221 .TP
222 .B EINVAL
223 The specifier was not a valid character.
224 .SH STANDARDS
225 GNU.
226 .SH HISTORY
227 .BR \%register_printf_function (3)
228 is an older function similar to
229 .BR \%register_printf_specifier (),
230 and is now deprecated.
231 That function can't handle user-defined types.
232 .P
233 .BR \%register_printf_specifier ()
234 superseeds
235 .BR \%register_printf_function (3).
236 .SH EXAMPLES
237 The following example program registers the 'b' and 'B' specifiers
238 to print integers in binary format,
239 mirroring rules for other unsigned conversion specifiers like 'x' and 'u'.
240 This can be used to print in binary prior to C23.
241 .P
242 .\" SRC BEGIN (register_printf_specifier.c)
243 .EX
244 /* This code is in the public domain */
245 \&
246 #include <err.h>
247 #include <limits.h>
248 #include <stddef.h>
249 #include <stdint.h>
250 #include <stdio.h>
251 #include <stdlib.h>
252 #include <string.h>
253 #include <sys/param.h>
254 \&
255 #include <printf.h>
256 \&
257 #define GROUP_SEP \[aq]\e\[aq]\[aq]
258 \&
259 struct Printf_Pad {
260 char ch;
261 size_t len;
262 };
263 \&
264 static int b_printf(FILE *stream, const struct printf_info *info,
265 const void *const args[]);
266 static int b_arginf_sz(const struct printf_info *info,
267 size_t n, int argtypes[n], int size[n]);
268 \&
269 static uintmax_t b_value(const struct printf_info *info,
270 const void *arg);
271 static size_t b_bin_repr(char bin[UINTMAX_WIDTH],
272 const struct printf_info *info, const void *arg);
273 static size_t b_bin_len(const struct printf_info *info,
274 ptrdiff_t min_len);
275 static size_t b_pad_len(const struct printf_info *info,
276 ptrdiff_t bin_len);
277 static ssize_t b_print_prefix(FILE *stream,
278 const struct printf_info *info);
279 static ssize_t b_pad_zeros(FILE *stream, const struct printf_info *info,
280 ptrdiff_t min_len);
281 static ssize_t b_print_number(FILE *stream,
282 const struct printf_info *info,
283 const char bin[UINTMAX_WIDTH],
284 size_t min_len, size_t bin_len);
285 static char pad_ch(const struct printf_info *info);
286 static ssize_t pad_spaces(FILE *stream, size_t pad_len);
287 \&
288 int
289 main(void)
290 {
291 if (register_printf_specifier(\[aq]b\[aq], b_printf, b_arginf_sz) == \-1)
292 err(EXIT_FAILURE, "register_printf_specifier(\[aq]b\[aq], ...)");
293 if (register_printf_specifier(\[aq]B\[aq], b_printf, b_arginf_sz) == \-1)
294 err(EXIT_FAILURE, "register_printf_specifier(\[aq]B\[aq], ...)");
295 \&
296 printf("....----....----....----....----\en");
297 printf("%llb;\en", 0x5Ellu);
298 printf("%lB;\en", 0x5Elu);
299 printf("%b;\en", 0x5Eu);
300 printf("%hB;\en", 0x5Eu);
301 printf("%hhb;\en", 0x5Eu);
302 printf("%jb;\en", (uintmax_t)0x5E);
303 printf("%zb;\en", (size_t)0x5E);
304 printf("....----....----....----....----\en");
305 printf("%#b;\en", 0x5Eu);
306 printf("%#B;\en", 0x5Eu);
307 printf("....----....----....----....----\en");
308 printf("%10b;\en", 0x5Eu);
309 printf("%010b;\en", 0x5Eu);
310 printf("%.10b;\en", 0x5Eu);
311 printf("....----....----....----....----\en");
312 printf("%\-10B;\en", 0x5Eu);
313 printf("....----....----....----....----\en");
314 printf("%\[aq]B;\en", 0x5Eu);
315 printf("....----....----....----....----\en");
316 printf("....----....----....----....----\en");
317 printf("%#16.12b;\en", 0xAB);
318 printf("%\-#\[aq]20.12b;\en", 0xAB);
319 printf("%#\[aq]020B;\en", 0xAB);
320 printf("....----....----....----....----\en");
321 printf("%#020B;\en", 0xAB);
322 printf("%\[aq]020B;\en", 0xAB);
323 printf("%020B;\en", 0xAB);
324 printf("....----....----....----....----\en");
325 printf("%#021B;\en", 0xAB);
326 printf("%\[aq]021B;\en", 0xAB);
327 printf("%021B;\en", 0xAB);
328 printf("....----....----....----....----\en");
329 printf("%#022B;\en", 0xAB);
330 printf("%\[aq]022B;\en", 0xAB);
331 printf("%022B;\en", 0xAB);
332 printf("....----....----....----....----\en");
333 printf("%#023B;\en", 0xAB);
334 printf("%\[aq]023B;\en", 0xAB);
335 printf("%023B;\en", 0xAB);
336 printf("....----....----....----....----\en");
337 printf("%\-#\[aq]19.11b;\en", 0xAB);
338 printf("%#\[aq]019B;\en", 0xAB);
339 printf("%#019B;\en", 0xAB);
340 printf("....----....----....----....----\en");
341 printf("%\[aq]019B;\en", 0xAB);
342 printf("%019B;\en", 0xAB);
343 printf("%#016b;\en", 0xAB);
344 printf("....----....----....----....----\en");
345 \&
346 return 0;
347 }
348 \&
349 static int
350 b_printf(FILE *stream, const struct printf_info *info,
351 const void *const args[])
352 {
353 char bin[UINTMAX_WIDTH];
354 size_t min_len, bin_len;
355 ssize_t len, tmp;
356 struct Printf_Pad pad = {0};
357 \&
358 len = 0;
359 \&
360 min_len = b_bin_repr(bin, info, args[0]);
361 bin_len = b_bin_len(info, min_len);
362 \&
363 pad.ch = pad_ch(info);
364 if (pad.ch == \[aq] \[aq])
365 pad.len = b_pad_len(info, bin_len);
366 \&
367 /* Padding with \[aq] \[aq] (right aligned) */
368 if ((pad.ch == \[aq] \[aq]) && !info->left) {
369 tmp = pad_spaces(stream, pad.len);
370 if (tmp == EOF)
371 return EOF;
372 len += tmp;
373 }
374 \&
375 /* "0b"/"0B" prefix */
376 if (info->alt) {
377 tmp = b_print_prefix(stream, info);
378 if (tmp == EOF)
379 return EOF;
380 len += tmp;
381 }
382 \&
383 /* Padding with \[aq]0\[aq] */
384 if (pad.ch == \[aq]0\[aq]) {
385 tmp = b_pad_zeros(stream, info, min_len);
386 if (tmp == EOF)
387 return EOF;
388 len += tmp;
389 }
390 \&
391 /* Print number (including leading 0s to fill precision) */
392 tmp = b_print_number(stream, info, bin, min_len, bin_len);
393 if (tmp == EOF)
394 return EOF;
395 len += tmp;
396 \&
397 /* Padding with \[aq] \[aq] (left aligned) */
398 if (info\->left) {
399 tmp = pad_spaces(stream, pad.len);
400 if (tmp == EOF)
401 return EOF;
402 len += tmp;
403 }
404 \&
405 return len;
406 }
407 \&
408 static int
409 b_arginf_sz(const struct printf_info *info, size_t n, int argtypes[n],
410 [[maybe_unused]] int size[n])
411 {
412 if (n < 1)
413 return \-1;
414 \&
415 if (info\->is_long_double)
416 argtypes[0] = PA_INT | PA_FLAG_LONG_LONG;
417 else if (info\->is_long)
418 argtypes[0] = PA_INT | PA_FLAG_LONG;
419 else
420 argtypes[0] = PA_INT;
421 \&
422 return 1;
423 }
424 \&
425 static uintmax_t
426 b_value(const struct printf_info *info, const void *arg)
427 {
428 if (info\->is_long_double)
429 return *(const unsigned long long *)arg;
430 if (info\->is_long)
431 return *(const unsigned long *)arg;
432 \&
433 /* short and char are both promoted to int */
434 return *(const unsigned int *)arg;
435 }
436 \&
437 static size_t
438 b_bin_repr(char bin[UINTMAX_WIDTH],
439 const struct printf_info *info, const void *arg)
440 {
441 size_t min_len;
442 uintmax_t val;
443 \&
444 val = b_value(info, arg);
445 \&
446 bin[0] = \[aq]0\[aq];
447 for (min_len = 0; val; min_len++) {
448 bin[min_len] = \[aq]0\[aq] + (val % 2);
449 val >>= 1;
450 }
451 \&
452 return MAX(min_len, 1);
453 }
454 \&
455 static size_t
456 b_bin_len(const struct printf_info *info, ptrdiff_t min_len)
457 {
458 return MAX(info\->prec, min_len);
459 }
460 \&
461 static size_t
462 b_pad_len(const struct printf_info *info, ptrdiff_t bin_len)
463 {
464 ptrdiff_t pad_len;
465 \&
466 pad_len = info\->width \- bin_len;
467 if (info\->alt)
468 pad_len \-= 2;
469 if (info\->group)
470 pad_len \-= (bin_len \- 1) / 4;
471 \&
472 return MAX(pad_len, 0);
473 }
474 \&
475 static ssize_t
476 b_print_prefix(FILE *stream, const struct printf_info *info)
477 {
478 ssize_t len;
479 \&
480 len = 0;
481 if (fputc(\[aq]0\[aq], stream) == EOF)
482 return EOF;
483 len++;
484 if (fputc(info\->spec, stream) == EOF)
485 return EOF;
486 len++;
487 \&
488 return len;
489 }
490 \&
491 static ssize_t
492 b_pad_zeros(FILE *stream, const struct printf_info *info,
493 ptrdiff_t min_len)
494 {
495 ssize_t len;
496 ptrdiff_t tmp;
497 \&
498 len = 0;
499 tmp = info\->width \- (info\->alt * 2);
500 if (info\->group)
501 tmp \-= tmp / 5 \- !(tmp % 5);
502 for (ptrdiff_t i = tmp \- 1; i > min_len \- 1; i\-\-) {
503 if (fputc(\[aq]0\[aq], stream) == EOF)
504 return EOF;
505 len++;
506 \&
507 if (!info\->group || (i % 4))
508 continue;
509 if (fputc(GROUP_SEP, stream) == EOF)
510 return EOF;
511 len++;
512 }
513 \&
514 return len;
515 }
516 \&
517 static ssize_t
518 b_print_number(FILE *stream, const struct printf_info *info,
519 const char bin[UINTMAX_WIDTH],
520 size_t min_len, size_t bin_len)
521 {
522 ssize_t len;
523 \&
524 len = 0;
525 \&
526 /* Print leading zeros to fill precision */
527 for (size_t i = bin_len \- 1; i > min_len \- 1; i\-\-) {
528 if (fputc(\[aq]0\[aq], stream) == EOF)
529 return EOF;
530 len++;
531 \&
532 if (!info\->group || (i % 4))
533 continue;
534 if (fputc(GROUP_SEP, stream) == EOF)
535 return EOF;
536 len++;
537 }
538 \&
539 /* Print number */
540 for (size_t i = min_len \- 1; i < min_len; i\-\-) {
541 if (fputc(bin[i], stream) == EOF)
542 return EOF;
543 len++;
544 \&
545 if (!info\->group || (i % 4) || !i)
546 continue;
547 if (fputc(GROUP_SEP, stream) == EOF)
548 return EOF;
549 len++;
550 }
551 \&
552 return len;
553 }
554 \&
555 static char
556 pad_ch(const struct printf_info *info)
557 {
558 if ((info\->prec != \-1) || (info\->pad == \[aq] \[aq]) || info\->left)
559 return \[aq] \[aq];
560 return \[aq]0\[aq];
561 }
562 \&
563 static ssize_t
564 pad_spaces(FILE *stream, size_t pad_len)
565 {
566 ssize_t len;
567 \&
568 len = 0;
569 for (size_t i = pad_len - 1; i < pad_len; i\-\-) {
570 if (fputc(\[aq] \[aq], stream) == EOF)
571 return EOF;
572 len++;
573 }
574 \&
575 return len;
576 }
577 .EE
578 .\" SRC END
579 .SH SEE ALSO
580 .BR asprintf (3),
581 .BR printf (3),
582 .BR wprintf (3)