]> git.ipfire.org Git - thirdparty/man-pages.git/blame - man3head/printf.h.3head
man*/: srcfix (Use .P instead of .PP or .LP)
[thirdparty/man-pages.git] / man3head / printf.h.3head
CommitLineData
0ba27b03
AC
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
7printf.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
31Standard C library
32.RI ( libc ", " \-lc )
33.SH SYNOPSIS
34.nf
35.B #include <printf.h>
c6d039a3 36.P
0ba27b03
AC
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
84These functions serve to extend and/or modify the behavior of the
85.BR printf (3)
86family of functions.
87.SS register_printf_specifier()
88This function registers a custom conversion specifier for the
89.BR printf (3)
90family of functions.
91.TP
92.I spec
93The character which will be used as a conversion specifier in the format string.
94.TP
95.I func
96Callback function that will be executed by the
97.BR printf (3)
98family of functions
99to format the input arguments into the output
100.IR stream .
101.RS
102.TP
103.I stream
104Output stream where the formatted output should be printed.
105This stream transparently represents the output,
106even in the case of functions that write to a string.
107.TP
108.I info
109Structure that holds context information,
110including the modifiers specified in the format string.
111This holds the same contents as in
112.IR arginfo .
113.TP
114.I args
115Array of pointers to the arguments to the
116.BR printf (3)\c
117-like function.
118.RE
119.TP
120.I arginfo
121Callback function that will be executed by the
122.BR printf (3)
123family of functions
124to know how many arguments should be parsed for the custom specifier
125and also their types.
126.RS
127.TP
128.I info
129Structure that holds context information,
130including the modifiers specified in the format string.
131This holds the same contents as in
132.IR func .
133.TP
134.I n
135Number of arguments remaining to be parsed.
136.TP
137.I argtypes
138This array should be set to
139define the type of each of the arguments that will be parsed.
140Each element in the array represents one of the arguments to be parsed,
141in the same order that they are passed to the
142.BR printf (3)\c
143-like function.
144Each element should be set to a base type
145.RB ( PA_ *)
146from the enum above,
147or a custom one,
148and optionally ORed with an appropriate length modifier
149.RB ( PA_FLAG_ *).
150.RS
c6d039a3 151.P
0ba27b03
AC
152The 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 ,
159cast to
160.IR char .
161.TP
7c6483b5
AC
162.B PA_WCHAR
163.IR wchar_t .
0ba27b03
AC
164.TP
165.B PA_STRING
7c6483b5 166.IR "const char\~*" ,
0ba27b03
AC
167a \(aq\e0\(aq-terminated string.
168.TP
169.B PA_WSTRING
7c6483b5 170.IR "const wchar_t\~*" ,
0ba27b03
AC
171a 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
183TODO.
184.RE
185.TP
186.I size
187For user-defined types,
188the size of the type (in bytes) should also be specified through this array.
189Otherwise, leave it unused.
190.RE
c6d039a3 191.P
0ba27b03
AC
192.I arginfo
193is called before
194.IR func ,
195and prepares some information needed to call
196.IR func .
197.SS register_printf_modifier()
198TODO
199.SS register_printf_type()
200TODO
201.SH RETURN VALUE
202.BR \%register_printf_specifier (),
203.BR \%register_printf_modifier (),
204and
205.BR \%register_printf_type ()
206return zero on success, or \-1 on error.
207.SS Callbacks
208The callback of type
209.I printf_function
210should return the number of characters written,
211or \-1 on error.
c6d039a3 212.P
0ba27b03
AC
213The callback of type
214.I \%printf_arginfo_size_function
215should return the number of arguments to be parsed by this specifier.
216It also passes information about the type of those arguments
217to the caller through
218.IR argtypes .
219On error, it should return \-1.
220.SH ERRORS
221.TP
222.B EINVAL
223The specifier was not a valid character.
4131356c
AC
224.SH STANDARDS
225GNU.
226.SH HISTORY
0ba27b03
AC
227.BR \%register_printf_function (3)
228is an older function similar to
629aeb16 229.BR \%register_printf_specifier (),
0ba27b03
AC
230and is now deprecated.
231That function can't handle user-defined types.
c6d039a3 232.P
0ba27b03
AC
233.BR \%register_printf_specifier ()
234superseeds
235.BR \%register_printf_function (3).
0ba27b03
AC
236.SH EXAMPLES
237The following example program registers the 'b' and 'B' specifiers
238to print integers in binary format,
239mirroring rules for other unsigned conversion specifiers like 'x' and 'u'.
240This can be used to print in binary prior to C23.
c6d039a3 241.P
0ba27b03
AC
242.\" SRC BEGIN (register_printf_specifier.c)
243.EX
244/* This code is in the public domain */
fe5dba13 245\&
0ba27b03
AC
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>
fe5dba13 254\&
0ba27b03 255#include <printf.h>
fe5dba13 256\&
0ba27b03 257#define GROUP_SEP \[aq]\e\[aq]\[aq]
fe5dba13 258\&
0ba27b03
AC
259struct Printf_Pad {
260 char ch;
261 size_t len;
262};
fe5dba13 263\&
0ba27b03
AC
264static int b_printf(FILE *stream, const struct printf_info *info,
265 const void *const args[]);
266static int b_arginf_sz(const struct printf_info *info,
267 size_t n, int argtypes[n], int size[n]);
fe5dba13 268\&
0ba27b03
AC
269static uintmax_t b_value(const struct printf_info *info,
270 const void *arg);
271static size_t b_bin_repr(char bin[UINTMAX_WIDTH],
272 const struct printf_info *info, const void *arg);
273static size_t b_bin_len(const struct printf_info *info,
274 ptrdiff_t min_len);
275static size_t b_pad_len(const struct printf_info *info,
276 ptrdiff_t bin_len);
277static ssize_t b_print_prefix(FILE *stream,
278 const struct printf_info *info);
279static ssize_t b_pad_zeros(FILE *stream, const struct printf_info *info,
280 ptrdiff_t min_len);
281static 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);
285static char pad_ch(const struct printf_info *info);
286static ssize_t pad_spaces(FILE *stream, size_t pad_len);
fe5dba13 287\&
0ba27b03
AC
288int
289main(void)
290{
88163675 291 if (register_printf_specifier(\[aq]b\[aq], b_printf, b_arginf_sz) == \-1)
0ba27b03 292 err(EXIT_FAILURE, "register_printf_specifier(\[aq]b\[aq], ...)");
88163675 293 if (register_printf_specifier(\[aq]B\[aq], b_printf, b_arginf_sz) == \-1)
0ba27b03 294 err(EXIT_FAILURE, "register_printf_specifier(\[aq]B\[aq], ...)");
fe5dba13 295\&
0ba27b03
AC
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");
fe5dba13 345\&
0ba27b03
AC
346 return 0;
347}
fe5dba13 348\&
0ba27b03
AC
349static int
350b_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};
fe5dba13 357\&
0ba27b03 358 len = 0;
fe5dba13 359\&
0ba27b03
AC
360 min_len = b_bin_repr(bin, info, args[0]);
361 bin_len = b_bin_len(info, min_len);
fe5dba13 362\&
0ba27b03
AC
363 pad.ch = pad_ch(info);
364 if (pad.ch == \[aq] \[aq])
365 pad.len = b_pad_len(info, bin_len);
fe5dba13 366\&
0ba27b03
AC
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 }
fe5dba13 374\&
0ba27b03
AC
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 }
fe5dba13 382\&
0ba27b03
AC
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 }
fe5dba13 390\&
0ba27b03
AC
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;
fe5dba13 396\&
0ba27b03
AC
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 }
fe5dba13 404\&
0ba27b03
AC
405 return len;
406}
fe5dba13 407\&
0ba27b03
AC
408static int
409b_arginf_sz(const struct printf_info *info, size_t n, int argtypes[n],
410 [[maybe_unused]] int size[n])
411{
412 if (n < 1)
88163675 413 return \-1;
fe5dba13 414\&
0ba27b03
AC
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;
fe5dba13 421\&
0ba27b03
AC
422 return 1;
423}
fe5dba13 424\&
0ba27b03
AC
425static uintmax_t
426b_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;
fe5dba13 432\&
0ba27b03
AC
433 /* short and char are both promoted to int */
434 return *(const unsigned int *)arg;
435}
fe5dba13 436\&
0ba27b03
AC
437static size_t
438b_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;
fe5dba13 443\&
0ba27b03 444 val = b_value(info, arg);
fe5dba13 445\&
0ba27b03
AC
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 }
fe5dba13 451\&
0ba27b03
AC
452 return MAX(min_len, 1);
453}
fe5dba13 454\&
0ba27b03
AC
455static size_t
456b_bin_len(const struct printf_info *info, ptrdiff_t min_len)
457{
458 return MAX(info\->prec, min_len);
459}
fe5dba13 460\&
0ba27b03
AC
461static size_t
462b_pad_len(const struct printf_info *info, ptrdiff_t bin_len)
463{
464 ptrdiff_t pad_len;
fe5dba13 465\&
0ba27b03
AC
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;
fe5dba13 471\&
0ba27b03
AC
472 return MAX(pad_len, 0);
473}
fe5dba13 474\&
0ba27b03
AC
475static ssize_t
476b_print_prefix(FILE *stream, const struct printf_info *info)
477{
478 ssize_t len;
fe5dba13 479\&
0ba27b03
AC
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++;
fe5dba13 487\&
0ba27b03
AC
488 return len;
489}
fe5dba13 490\&
0ba27b03
AC
491static ssize_t
492b_pad_zeros(FILE *stream, const struct printf_info *info,
493 ptrdiff_t min_len)
494{
495 ssize_t len;
496 ptrdiff_t tmp;
fe5dba13 497\&
0ba27b03
AC
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++;
fe5dba13 506\&
0ba27b03
AC
507 if (!info\->group || (i % 4))
508 continue;
509 if (fputc(GROUP_SEP, stream) == EOF)
510 return EOF;
511 len++;
512 }
fe5dba13 513\&
0ba27b03
AC
514 return len;
515}
fe5dba13 516\&
0ba27b03
AC
517static ssize_t
518b_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;
fe5dba13 523\&
0ba27b03 524 len = 0;
fe5dba13 525\&
0ba27b03
AC
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++;
fe5dba13 531\&
0ba27b03
AC
532 if (!info\->group || (i % 4))
533 continue;
534 if (fputc(GROUP_SEP, stream) == EOF)
535 return EOF;
536 len++;
537 }
fe5dba13 538\&
0ba27b03
AC
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++;
fe5dba13 544\&
0ba27b03
AC
545 if (!info\->group || (i % 4) || !i)
546 continue;
547 if (fputc(GROUP_SEP, stream) == EOF)
548 return EOF;
549 len++;
550 }
fe5dba13 551\&
0ba27b03
AC
552 return len;
553}
fe5dba13 554\&
0ba27b03
AC
555static char
556pad_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}
fe5dba13 562\&
0ba27b03
AC
563static ssize_t
564pad_spaces(FILE *stream, size_t pad_len)
565{
566 ssize_t len;
fe5dba13 567\&
0ba27b03
AC
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 }
fe5dba13 574\&
0ba27b03
AC
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)