269 lines
12 KiB
Plaintext
269 lines
12 KiB
Plaintext
These functions are intended to be a complete replacement for sprintf
|
|
and sprintf_irc. They are a (nearly) complete reimplementation, and
|
|
of course they're snprintf clones, making it more difficult for
|
|
accidental buffer overflows to crop up.
|
|
|
|
First off, what's missing? These functions support all ANSI C
|
|
conversion specifiers and selected ones from ISO 9x, with the
|
|
exception of all floating-point conversions. The floating-point
|
|
conversions are tricky, and will likely be dependent on the
|
|
representation of a floating-point number on a particular
|
|
architecture. While that representation is likely to conform to some
|
|
standard, it is not currently used in ircu, so seemed like a good
|
|
thing to omit, given the difficulty of implementing it.
|
|
|
|
There are two more things missing from this implementation that would
|
|
be required by ANSI; the first is support for multibyte character
|
|
strings, and the second is support for locales, neither of which have
|
|
any relevance for ircu, so again omission seemed to be a good policy.
|
|
Additionally, %#x always causes '0x' (or '0X') to be printed, even if
|
|
the number is zero.
|
|
|
|
These functions also have some extensions not seen in a
|
|
standards-compliant implementation; technically, the ISO 9x extensions
|
|
fall into this category, for instance. The ISO 9x extensions
|
|
supported are type extensions--%ju, %tu, and %zu, for instance; %qu
|
|
and %hhu are also supported. The extensions added for use in ircu are
|
|
%Tu, which takes a time_t, and the new %C conversion, which inserts
|
|
either a numeric or a nick, dependent on the <dest> parameter. The
|
|
GNU %m extension, which inserts the strerror() string corresponding to
|
|
the current value of errno, is also supported, as is a special %v
|
|
extension, which essentially does a recursive call to ircd_snprintf.
|
|
|
|
The following description is descended from the Linux man page for the
|
|
printf family of functions.
|
|
|
|
The format string is composed of zero or more directives: ordinary
|
|
characters (not %), which are copied unchanged to the output stream;
|
|
and conversion specifications, each of which results in fetching zero
|
|
or more subsequent arguments. Each conversion specification is
|
|
introduced by the character %. The arguments must correspond properly
|
|
(after type promotion) with the conversion specifier. After the %,
|
|
the following appear in sequence:
|
|
|
|
* Zero or more of the following flags:
|
|
|
|
# specifying that the value should be converted to an "alternate
|
|
form." For c, d, i, n, p, s, and u conversions, this option
|
|
has no effect. For o conversions, the precision of the number
|
|
is increased to force the first character of the output string
|
|
to a zero (except if a zero value is printed with an explicit
|
|
precision of zero). For x and X conversions, the string '0x'
|
|
(or '0X' for X conversions) is prepended to it. For e, E, f,
|
|
g, and G conversions, the result will always contain a decimal
|
|
point, even if no digits follow it (normally, a decimal point
|
|
appears in the results of those conversions only if a digit
|
|
follows). For g and G conversions, trailing zeros are not
|
|
removed from the result as they would otherwise be. For C
|
|
conversions, if the destination is local and the origin is a
|
|
user, the nick!user@host form is used.
|
|
|
|
0 specifying zero padding. For all conversions except n, the
|
|
converted value is padded on the left with zeros rather than
|
|
blanks. If a precision is given with a numeric conversion (d,
|
|
i, o, u, i, x, and X), the 0 flag is ignored.
|
|
|
|
- (a negative field width flag) indicates the converted value is
|
|
to be left adjusted on the field boundary. Except for n
|
|
conversions, the converted value is padded on the right with
|
|
blanks, rather than on the left with blanks or zeros. A -
|
|
overrides a 0 if both are given.
|
|
|
|
' ' (a space) specifying that a blank should be left before a
|
|
positive number produced by a signed conversion (d, e, E, f,
|
|
g, G, or i).
|
|
|
|
+ specifying that a sign always be placed before a number
|
|
produced by a signed conversion. A + overrides a space if
|
|
both are used.
|
|
|
|
: specifying that a struct Client name should be preceded by a
|
|
':' character if the destination is a user
|
|
|
|
* An optional decimal digit string specifying a minimum field width.
|
|
If the converted value has fewer characters than the field width, it
|
|
will be padded with spaces on the left (or right, if the
|
|
left-adjustment flag has been given) to fill out the field width.
|
|
|
|
* An optional precision, in the form of a period (`.') followed by an
|
|
optional digit string. If the digit string is omitted, the
|
|
precision is taken as zero. This gives the minimum number of digits
|
|
to appear for d, i, o, u, x, and X conversions, the number of digits
|
|
to appear after the decimal-point for e, E, and f conversions, the
|
|
maximum number of significant digits for g and G conversions, or the
|
|
maximum number of characters to be printed from a string for s
|
|
conversions.
|
|
|
|
* The optional character h, specifying that a following d, i, o, u, x,
|
|
or X conversion corresponds to a short int or unsigned short int
|
|
argument, or that a following n conversion corresponds to a pointer
|
|
to a short int argument. If the h character is given again, char is
|
|
used instead of short int.
|
|
|
|
* The optional character l (ell) specifying that a following d, i, o,
|
|
u, x, or X conversion applies to a pointer to a long int or unsigned
|
|
long int argument, or that a following n conversion corresponds to a
|
|
pointer to a long int argument.
|
|
|
|
* The character L specifying that a following e, E, f, g, or G
|
|
conversion corresponds to a long double argument, or a following d,
|
|
i, o, u, x, or X conversion corresponds to a long long argument.
|
|
Note that long long is not specified in ANSI C and therefore not
|
|
portable to all architectures.
|
|
|
|
* The optional character q. This is equivalent to L.
|
|
|
|
* A j character specifying that the following integer (d, i, o, u, x,
|
|
or X) conversion corresponds to an intmax_t argument.
|
|
|
|
* A t character specifying that the following integer (d, i, o, u, x,
|
|
or X) conversion corresponds to a ptrdiff_t argument.
|
|
|
|
* A z character specifying that the following integer (d, i, o, u, x,
|
|
or X) conversion corresponds to a size_t argument.
|
|
|
|
* A T character specifying that the following integer (d, i, o, u, x,
|
|
or X) conversion corresponds to a time_t argument.
|
|
|
|
* A character that specifies the type of conversion to be applied.
|
|
|
|
A field width or precision, or both, may be indicated by an asterisk
|
|
`*' instead of a digit string. In this case, an int argument supplies
|
|
the field width or precision. A negative field width is treated as a
|
|
left adjustment flag followed by a positive field width; a negative
|
|
precision is treated as though it were missing.
|
|
|
|
The conversion specifiers and their meanings are:
|
|
|
|
diouxX The int (or appropriate variant) argument is converted
|
|
to signed decimal (d and i), unsigned octal (o),
|
|
unsigned decimal (u), or unsigned hexadecimal (x and
|
|
X) notation. The letters abcdef are used for x
|
|
conversions; the letters ABCDEF are used for X
|
|
conversions. The precision, if any, gives the minimum
|
|
number of digits that must appear; if the converted
|
|
value requires fewer digits, it is padded on the left
|
|
with zeros.
|
|
|
|
eE [NOT IMPLEMENTED] The double argument is rounded and
|
|
converted in the style [-]d.dddedd where there is one
|
|
digit before the decimal-point character and the
|
|
number of digits after it is equal to the precision;
|
|
if the precision is missing, it is taken as 6; if the
|
|
precision is zero, no decimal-point character
|
|
appears. An E conversion uses the letter E (rather
|
|
than e) to introduce the exponent. The exponent
|
|
always contains at least two digits; if the value is
|
|
zero, the exponent is 00.
|
|
|
|
f [NOT IMPLEMENTED] The double argument is rounded and
|
|
converted to decimal notation in the style
|
|
[-]ddd.ddd, where the number of digits after the
|
|
decimal-point character is equal to the precision
|
|
specification. If the precision is missing, it is
|
|
taken as 6; if the precision is explicitly zero, no
|
|
decimal-point character appears. If a decimal point
|
|
appears, at least one digit appears before it.
|
|
|
|
g [NOT IMPLEMENTED] The double argument is converted in
|
|
style f or e (or E for G conversions). The precision
|
|
specifies the number of significant digits. If the
|
|
precision is missing, 6 digits are given; if the
|
|
precision is zero, it is treated as 1. Style e is
|
|
used if the exponent from its conversion is less than
|
|
-4 or greater than or equal to the precision.
|
|
Trailing zeros are removed from the fractional part of
|
|
the result; a decimal point appears only if it is
|
|
followed by at least one digit.
|
|
|
|
c The int argument is converted to an unsigned char, and
|
|
the resulting character is written.
|
|
|
|
s The "char *" argument is expected to be a pointer to
|
|
an array of character type (pointer to a string).
|
|
Characters from the array are written up to (but not
|
|
including) a terminating NUL character; if a precision
|
|
is specified, no more than the number specified are
|
|
written. If a precision is given, no null character
|
|
need be present; if the precision is not specified, or
|
|
is greater than the size of the array, the array must
|
|
contain a terminating NUL character.
|
|
|
|
p The "void *" pointer argument is printed in
|
|
hexadecimal (as if by %#x or %#lx).
|
|
|
|
n The number of characters written so far is stored into
|
|
the integer indicated by the ``int *'' (or variant)
|
|
pointer argument. No argument is converted.
|
|
|
|
m The error message associated with the current value of
|
|
errno is printed as if by %s.
|
|
|
|
C The client argument identifier is printed under the
|
|
control of the <dest> argument; if <dest> is NULL or
|
|
is a user, the client's name (nickname or server name)
|
|
is printed; otherwise, the client's network numeric is
|
|
printed.
|
|
|
|
H The channel argument identifier (channel name) is
|
|
printed.
|
|
|
|
v The argument given must be a pointer to a struct
|
|
VarData with vd_format and vd_args must be initialized
|
|
appropriately. On return, vd_chars will contain the
|
|
number of characters added to the buffer, and
|
|
vd_overflow will contain the number of characters that
|
|
could not be added due to buffer overflow or due to a
|
|
precision.
|
|
|
|
% A `%' is written. No argument is converted. The
|
|
complete conversion specification is `%%'.
|
|
|
|
In no case does a non-existent or small field width cause truncation
|
|
of a field; if the result of a conversion is wider than the field
|
|
width, the field is expanded to contain the conversion result.
|
|
|
|
<struct>
|
|
struct VarData {
|
|
size_t vd_chars; /* number of characters inserted */
|
|
size_t vd_overflow; /* number of characters that couldn't be */
|
|
const char *vd_format; /* format string */
|
|
va_list vd_args; /* arguments for %v */
|
|
};
|
|
|
|
This structure is used by the %v conversion specification. The
|
|
_vd_format_ element must contain a format string, and the _vd_args_
|
|
element must be a variable argument list. Upon return from
|
|
ircd_snprintf() or ircd_vsnprintf(), the _vd_chars_ element will
|
|
contain the number of characters that were able to be inserted, and
|
|
the _vd_overflow_ element will contain the number of characters that
|
|
could not be inserted.
|
|
</struct>
|
|
|
|
<function>
|
|
int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len,
|
|
const char *format, ...);
|
|
|
|
This formats the argument list, under control of the _format_, into
|
|
the buffer specified by _buf_, the size of which is specified by
|
|
_buf_len_. The _dest_ parameter is used to determine whether to use a
|
|
numeric or a nickname for %C conversions.
|
|
</function>
|
|
|
|
<function>
|
|
int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len,
|
|
const char *format, va_list args);
|
|
|
|
This function is identical to the ircd_snprintf() function except for
|
|
the variable argument list given by _args_.
|
|
</function>
|
|
|
|
<authors>
|
|
Kev <klmitch@mit.edu>
|
|
</authors>
|
|
|
|
<changelog>
|
|
[2001-6-15 Kev] Initial documentation of the ircd_snprintf family of
|
|
functions.
|
|
</changelog>
|