mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 17:53:37 +08:00
Add description of printf_size and printf_size_info.
This commit is contained in:
parent
307bcd7783
commit
29bb8719cf
@ -1968,6 +1968,7 @@ The facilities of this section are declared in the header file
|
||||
to @code{register_printf_function}.
|
||||
* Printf Extension Example:: How to define a @code{printf}
|
||||
handler function.
|
||||
* Predefined Printf Handlers:: Predefined @code{printf} handlers.
|
||||
@end menu
|
||||
|
||||
@strong{Portability Note:} The ability to extend the syntax of
|
||||
@ -2212,6 +2213,79 @@ The output produced by this program looks like:
|
||||
|<Widget 0xffeffb7c: mywidget> |
|
||||
@end smallexample
|
||||
|
||||
@node Predefined Printf Handlers
|
||||
@subsection Predefined @code{printf} Handlers
|
||||
|
||||
The GNU libc also contains a concrete and useful application of the
|
||||
@code{printf} handler extension. There are two functions available
|
||||
which implement a special way to print floating-point numbers.
|
||||
|
||||
@comment printf.h
|
||||
@comment GNU
|
||||
@deftypefun int printf_size (FILE *@var{fp}, const struct printf_info *@var{info}, const void *const *@var{args})
|
||||
Print a given floating point number as for the format @code{%f} except
|
||||
that there is a postfix character indicating the divisor for the
|
||||
number to make this less than 1000. There are two possible divisors:
|
||||
powers of 1024 or powers to 1000. Which one is used depends on the
|
||||
format character specified while registered this handler. If the
|
||||
character is of lower case, 1024 is used. For upper case characters,
|
||||
1000 is used.
|
||||
|
||||
The postfix tag corresponds to bytes, kilobytes, megabytes, gigabytes,
|
||||
etc. The full table is:
|
||||
|
||||
@multitable {' '} {2^10 (1024)} {zetta} {Upper} {10^24 (1000)}
|
||||
@item low @tab Multiplier @tab From @tab Upper @tab Multiplier
|
||||
@item ' ' @tab 1 @tab @tab ' ' @tab 1
|
||||
@item k @tab 2^10 (1024) @tab kilo @tab K @tab 10^3 (1000)
|
||||
@item m @tab 2^20 @tab mega @tab M @tab 10^6
|
||||
@item g @tab 2^30 @tab giga @tab G @tab 10^9
|
||||
@item t @tab 2^40 @tab tera @tab T @tab 10^12
|
||||
@item p @tab 2^50 @tab peta @tab P @tab 10^15
|
||||
@item e @tab 2^60 @tab exa @tab E @tab 10^18
|
||||
@item z @tab 2^70 @tab zetta @tab Z @tab 10^21
|
||||
@item y @tab 2^80 @tab yotta @tab Y @tab 10^24
|
||||
@end multitable
|
||||
|
||||
The default precision is 3, i.e., 1024 is printed with a lower-case
|
||||
format character as if it were @code{%.3fk} and will yield @code{1.000k}.
|
||||
@end deftypefun
|
||||
|
||||
Due to the requirements of @code{register_printf_function} we must also
|
||||
provide the function which return information about the arguments.
|
||||
|
||||
@comment printf.h
|
||||
@comment GNU
|
||||
@deftypefun int printf_size_info (const struct printf_info *@var{info}, size_t @var{n}, int *@var{argtypes})
|
||||
This function will return in @var{argtypes} the information about the
|
||||
used parameters in the way the @code{vfprintf} implementation expects
|
||||
it. The format always takes one argument.
|
||||
@end deftypefun
|
||||
|
||||
To use these functions both functions must be registered with a call like
|
||||
|
||||
@smallexample
|
||||
register_printf_function ('B', printf_size, printf_size_info);
|
||||
@end smallexample
|
||||
|
||||
Here we register the functions to print numbers as powers of 1000 since
|
||||
the format character @code{'B'} is an upper-case characeter. If we
|
||||
would additionally use @code{'b'} in a line like
|
||||
|
||||
@smallexample
|
||||
register_printf_function ('b', printf_size, printf_size_info);
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
we could also print using power of 1024. Please note that all what is
|
||||
different in these both lines in the format specifier. The
|
||||
@code{printf_size} function knows about the difference of low and upper
|
||||
case format specifiers.
|
||||
|
||||
The use of @code{'B'} and @code{'b'} is no coincidence. Rather it is
|
||||
the preferred way to use this functionality since it is available on
|
||||
some other systems also available using the format specifiers.
|
||||
|
||||
@node Formatted Input
|
||||
@section Formatted Input
|
||||
|
||||
|
@ -96,8 +96,8 @@ printf_size (FILE *fp, const struct printf_info *info, const void *const *args)
|
||||
/* Units for the both formats. */
|
||||
static const char units[2][8] =
|
||||
{
|
||||
" kmgtps", /* For binary format. */
|
||||
" KMGTPS" /* For decimal format. */
|
||||
" kmgtpezy", /* For binary format. */
|
||||
" KMGTPEZY" /* For decimal format. */
|
||||
};
|
||||
const char *tag = units[isupper (info->spec) != 0];
|
||||
int divisor = isupper (info->spec) ? 1000 : 1024;
|
||||
|
66
stdio-common/tst-printfsz.c
Normal file
66
stdio-common/tst-printfsz.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* Based on code by Larry McVoy <lm@neteng.engr.sgi.com>. */
|
||||
#include <printf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define V 12345678.12345678
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char buf[1024];
|
||||
int result = 0;
|
||||
|
||||
/* Register the printf handlers. */
|
||||
register_printf_function ('b', printf_size, printf_size_info);
|
||||
register_printf_function ('B', printf_size, printf_size_info);
|
||||
|
||||
|
||||
sprintf (buf, "%g %b %B %.0b %.0B %.1b %.1B %8.0b %08.0B",
|
||||
V, 1025., V, V, V, V, V, V, V, V);
|
||||
fputs (buf, stdout);
|
||||
if (strcmp (buf, "\
|
||||
1.23457e+07 1.001k 12.346M 12m 12M 11.8m 12.3M 12m 0000012M"))
|
||||
{
|
||||
result = 1;
|
||||
fputs (" -> WRONG\n", stdout);
|
||||
}
|
||||
else
|
||||
fputs (" -> OK\n", stdout);
|
||||
|
||||
sprintf (buf, "%b|%B|%-20.2b|%-10.0b|%-10.8b|%-10.2B|",
|
||||
V, V, V, V, V, V, V, V, V, V, V);
|
||||
fputs (buf, stdout);
|
||||
if (strcmp (buf, "\
|
||||
11.774m|12.346M|11.77m |12m |11.77375614m|12.35M |"))
|
||||
{
|
||||
result = 1;
|
||||
fputs (" -> WRONG\n", stdout);
|
||||
}
|
||||
else
|
||||
fputs (" -> OK\n", stdout);
|
||||
|
||||
sprintf (buf, "%#.0B %*.0b %10.*b %*.*B %10.2B",
|
||||
V, 2, V, 2, V, 10, 2, V, V);
|
||||
fputs (buf, stdout);
|
||||
if (strcmp (buf, "12.M 12m 11.77m 12.35M 12.35M"))
|
||||
{
|
||||
result = 1;
|
||||
fputs (" -> WRONG\n", stdout);
|
||||
}
|
||||
else
|
||||
fputs (" -> OK\n", stdout);
|
||||
|
||||
sprintf (buf, "%6B %6.1B %b %B %b %B",
|
||||
V, V, 1000.0, 1000.0, 1024.0, 1024.0);
|
||||
fputs (buf, stdout);
|
||||
if (strcmp (buf, "12.346M 12.3M 1000.000 1.000K 1.000k 1.024K"))
|
||||
{
|
||||
result = 1;
|
||||
fputs (" -> WRONG\n", stdout);
|
||||
}
|
||||
else
|
||||
fputs (" -> OK\n", stdout);
|
||||
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user