X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=include%2Fircd_snprintf.h;h=23fa826b45b71bf04b84996e4032967ccede1bd1;hb=refs%2Fheads%2Fupstream;hp=824c5940c4602cb96d444900112414821bbfae56;hpb=8cc498edc0e18db8d8a52f929d25e348852f45cf;p=ircu2.10.12-pk.git diff --git a/include/ircd_snprintf.h b/include/ircd_snprintf.h index 824c594..23fa826 100644 --- a/include/ircd_snprintf.h +++ b/include/ircd_snprintf.h @@ -17,12 +17,11 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ */ -#ifndef INCLUDED_config_h -#include "config.h" -#endif +/** @file + * @brief IRC-specific printf() clone interface. + * @version $Id$ + */ #ifndef INCLUDED_sys_types_h #include #define INCLUDED_sys_types_h @@ -34,17 +33,289 @@ struct Client; -/* structure passed as argument for %v conversion */ +/** structure passed as argument for %v conversion */ 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 */ + 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 */ }; +#ifndef HAVE_VA_COPY +#if HAVE___VA_COPY +#define va_copy(DEST, SRC) __va_copy(DEST, SRC) +#else +/** Fallback macro to copy to \a DEST from \a SRC. */ +#define va_copy(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof(DEST)) +#endif +#endif + extern int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len, const char *format, ...); extern int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len, const char *format, va_list args); +/** @fn int ircd_snprintf(struct Client *dest, char *buf, size_t + buf_len, const char *format, ...) +** +** 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, dependant 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 manpage 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: +** +** +** +** 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. +** +** @param[in] dest Client receiving of message. +** @param[out] buf Output buffer for formatted message. +** @param[in] buf_len Number of bytes that can be written to \a buf. +** @param[in] format Format string for message. +** @return Number of bytes that would be written to \a buf without truncation. +*/ + #endif /* INCLUDED_ircd_snprintf_h */