cdrtools/libschily/format.3

533 lines
11 KiB
Groff
Raw Normal View History

2025-06-15 04:19:58 +08:00
'\" t
. \" Manual Seite fuer format
. \" @(#)format.3 1.4 17/12/08 Copyright 1985-2017 J. Schilling
. \"
.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-.75n'U
.if t .ds s \(*b
.if t .ds S SS
.if n .ds a ae
.if n .ds o oe
.if n .ds u ue
.if n .ds s sz
.TH FORMAT 3 "2017/12/08" "J\*org Schilling" "Schily\'s LIBRARY FUNCTIONS"
.SH NAME
format() \- generates formatted output as in printf
.SH SYNOPSIS
.nf
.B
int format(cfun, farg, formatstr, formatargs)
.B int (*cfun)();
.B void *farg;
.B char *formatstr;
.B va_list formatargs;
.fi
.SH DESCRIPTION
format() generates ASCII data, based on a specified input
string. format() knows how to create ASCII representations of
all C data types.
.PP
This subroutine takes four arguments:
.TP
.B cfun
is the address of a function declared in C as
.RS
.PP
.nf
.B int cfun(ch, farg)
.B char ch;
.B void *farg;
.fi
.PP
cfun is called with each character generated by format().
farg is an arbitrary value passed as the second argument to
cfun.
.RE
.TP
.B formatstr
is a format string that controls the output, as
described below.
.TP
.B formatargs
points to a list of arguments that are to be
formatted.
.PP
.B Formatting Options
.PP
The formatting, although complicated, has a great deal of
flexibility. The format string contains a string to be
processed and places where other strings can be inserted. These
places are denoted by a % followed by characters which specify
how the next argument from formatargs is to be placed in the
string. For example, %c inserts a character. The format string
"I am printing the letter %c." with the character 'f' results in
the string, "I am printing the letter f."
.PP
The simplest formatting options are as follows:
.TP
.B %c
outputs byte as a character
.TP
.B %d
outputs integer as a decimal number
.TP
.B %i
outputs integer as a decimal number
.TP
.B %D
outputs long as a decimal number
.TP
.B %o
outputs integer as an octal number
.TP
.B %O
outputs long as an octal number
.TP
.B %u
outputs unsigned integer as a decimal number
.TP
.B %x
outputs integer as a hexadecimal number
.TP
.B %X
outputs long as a hexadecimal number
.TP
.B %l
outputs long decimal
.TP
.B %ld
outputs long decimal
.TP
.B %li
outputs long decimal
.TP
.B %lo
outputs long octal
.TP
.B %lu
outputs unsigned long as a decimal number
.TP
.B %lx
outputs long hexadecimal
.PP
For more specialized formatting, use the portable set. The
syntax for the portable set is:
.PP
.I %<unsigned><intype><outtype>
.PP
.I <unsigned>, <intype>,
and
.I <outtype>
are one character options,
as follows:
.PP
.TS
center;
cb cb lb
ci c l.
Option Character Means
.sp .5
<unsigned> U unsigned
none signed
.sp .5
<intype> C char
I int
S short
L long
.sp .5
<outtype> O octal
X hexadecimal
D decimal
.TE
.PP
.I <intype>
indicates the type of argument, while
.I <outtype>
indicates the type of format you want
.I <intype>
printed in.
.PP
For example, use %CO to output a character in octal or %US to
output an unsigned short in decimal.
.PP
Note that in
.I The C Programming Language,
Kernighan and Ritchie
document %x and %d; in the portable set, %IX performs the same
function as %x, while %ID performs the same function as %d.
.PP
Using U for the
.I <unsigned>
option is only useful when D is used as the
.I <outtype>
option because octal and hexadecimal numbers are never signed.
.PP
.B Specifying Field Width
.PP
Any type of formatting option can also have a number which
further specifies the formatting. The number appears after the
percent sign and before any characters. The number is of the
form
.I y.z
and can be negative.
.PP
.I y
specifies the minimum number of characters that the formatted
argument will fill. If the number is positive, the result will
be right justified. If it is negative, the result will be left
justified. This only specifies a minimum, so if there are more
characters than can fit into
.I y
characters, the rest will be
printed. Thus, "%6c" with the character 'f' results in the
following:
.PP
.TS
center;
l l.
.B
"%6c" "\ \ \ \ \ f"
.B
"%-6c" "f\ \ \ \ \ "
.TE
.PP
A leading 0 in the
.I y
specification causes zero filling for the
right justification, so 3 printed in %06d yields "000003". The
zero does not mean octal.
.PP
.I z
specifies a maximum number of characters or significant digits
and is not used for the above types because they are all fixed
length. The
.I z
is, however, used in %s, %b, %e, %f, and %g formats.
.LP
A field width or the significant digits or both may be
indicated by an asterisk
.RB ( \(** )
instead of a digit string.
In this case, an integer
.I arg
supplies
the field width or the significant digits. The
.I arg
that is actually converted is not fetched until
the conversion letter is seen, so the
.IR arg s
specifying field width or the significant digits must appear
.I before
the
.I arg
(if any) to be converted.
A negative field width argument is taken as a
.RB ` \- '
flag followed by a positive field width.
If the significant digits argument is negative,
it will be changed to zero.
.TP
.B %s
Inserts a string.
.RS
.PP
Useful for printing strings that have no null terminator.
The minimum width of the string is
.I y
and the maximum width
of the string is
.I z.
.PP
NOTE: When string formatting reaches a null, the
formatting stops. If the
.I y
field has specified more
characters, the result is padded with blanks. Thus,
formatting "test" results in the following:
.PP
.TS
center;
l l.
.B
"%6s" "\ \ test"
.B
"%-6s" "test\ \ "
.B
"%.2" "te"
.B
"%6.2" "\ \ \ \ te"
.TE
.RE
.TP
.B %b
Inserts a string bounded by a length.
.RS
.PP
This actually uses TWO arguments: the first is a string,
and the second is a number. For instance:
.PP
.B
"%b", x, 3
is the same as
.B
"%.3s", x
.PP
The number argument is used as the maximum number of
characters in the string. %b is used when the number of
characters used might change with different calls.
.RE
.TP
.B %e
Inserts a floating number in 'e format'.
.br
This is of the form "~.####e*&&":
.RS
.TP
.B ~
either a minus sign or nothing
.TP
.B #'s
the digits of the mantissa
.TP
.B *
either plus or minus
.TP
.B &'s
the digits of the exponent
.PP
Thus, 43.5 is formatted as .435e+02 and \-.00435 is
formatted as \-.435e-02. There are always two digits of
exponent. The
.I y
field gives a minimum width for the entire number, and the
.I z
field gives the maximum number of digits in the mantissa.
.I z
defaults to 6. Thus, formatting 43.5 results in the following:
.PP
.TS
center;
l l.
.B
"%10e" "\ \ .435e+02"
.B
"%-10e" ".435e+02\ \ "
.B
"%5e" ".435e+02"
.B
"%10.1e" "\ \ \ \ .4e+02"
.TE
.RE
.TP
.B %E
Inserts a floating number in 'E format'.
.br
This is of the form "~.####E*&&", and identical
to the
.B %e
format except that
.B E
is used instead of
.B e
in the exponent.
.TP
.B %f
Inserts a floating number in 'f format'.
.br
This is of the form "~####.&&":
.RS
.TP
.B ~
either a minus sign or nothing
.TP
.B #'s
the digits before the decimal point
.TP
.B &'s
the digits after the decimal point
.PP
The number of #'s is always the number needed. Again, the
.I y
field gives a minimum on the size of the entire number,
while the
.I z
field is the number of significant digits to
keep after the decimal point.
.I z
defaults to 6. Thus,
formatting 1.23456 results in the following:
.PP
.TS
center;
l l.
.B
"%10f" "\ \ 1.234560"
.B
"%-10f" "1.234560\ \ "
.B
"%.2f" "1.23"
.B
"%5.2f" "\ 1.23"
.TE
.RE
.TP
.B %F
Inserts a floating number in 'F format'.
.br
This is mainly the same as the
.B %f
format.
.TP
.B %g
Inserts a floating number in optional format.
.RS
.PP
Prints in either %e or %f format, whichever is shorter,
with the minimum number of digits needed to the right of
the decimal. Whole numbers will have no digits to the
right of the decimal because trailing zeroes are
suppressed.
.I z
gives the maximum number of significant
digits including digits before the decimal point.
.I z
defaults to 6. For example, the format string "%10.4g"
results in the following:
.PP
.TS
center;
l l.
.B
435.0 "\ \ \ \ \ \ 435."
.B
4.35 "\ \ \ \ \ \ 4.35"
.B
\&.0435 "\ \ .435e-01"
.B
\&.000435 "\ \ .435e-03"
.TE
.RE
.TP
.B %G
Inserts a floating number in 'G format'.
.br
This outputs the form "~.####E*&&" in case that the exponent
variant is used.
.TP
.B %r
Recursive or remote format.
.RS
.PP
This takes two arguments: the first is a format string,
and the second is a pointer to the argument list. The new
format string is formatted and put out in place of the %r.
.PP
The field width and significant digit specification is ignored
within the %r format. The recursive format makes it possible to write
variable arg printing routines without using format(3) directly.
.RE
.TP
.B %%
Inserts %.
.RS
.PP
A double percent sign in the format string becomes a
single percent sign in the output. This does not use an
argument.
.RE
.TP
.B %<SP>
Inserts spaces.
.RS
.PP
A space character as a format control causes a field of
.I y
spaces to be output. This does not use an argument.
Note that an actual space should appear where <SP> appears
above.
.SH RETURNS
the number of characters transmitted exluding the trailing null byte.
.SH EXAMPLES
.TP
.B 1.
.B fprintf()
(formatted print to a file) could be implemented this way:
.RS
.PP
.nf
#include <stdio.h>
#include <varargs.h>
/* VARARGS2 */
fprintf(f, fmt, va_alist)
FILE *f;
char *fmt;
va_dcl
{
va_list args;
extern int fputc();
va_start(args);
format(&fputc, (long)f, fmt, args);
va_end(args);
}
.RE
.fi
.TP
.B 2.
.B comerr()
could be implemented this way:
.RS
.PP
.nf
#include <stdio.h>
#include <varargs.h>
/* VARARGS1 */
comerr(fmt, va_alist)
char *fmt;
va_dcl
{
va_list args;
int err;
char errbuf[20];
char *errnam;
extern int errno;
extern int sys_nerr;
extern char *sys_errlist[];
err = errno;
va_start(args);
if (err < 0) {
fprintf(stderr, "Progname: %r", fmt, args);
} else {
if (err >= sys_nerr) {
sprintf(errbuf, "Error %d", err);
errnam = errbuf;
} else {
errnam = sys_errlist[err];
}
fprintf(stderr, "Progname: %s. %r",
errnam, fmt, args);
}
va_end(args);
exit(err);
}
.RE
.fi
.SH "SEE ALSO"
comerr(3), error(3), fprintf(3), printf(3), sprintf(3)
.SH NOTES
If there are no floating point operations anywhere in the
program, the floating point package is not loaded and therefore
floating point printing commands will possibly not work correctly.
.PP
To just print a string without any formatting, use the %s format
to ensure that the string is correctly interpreted. This is
especially important if the string itself contains % characters,
because format() will attempt to interpret them, which causes
unwanted additions in the output string. The number of
characters inserted for either %s or %b should be less than 512.