X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=blobdiff_plain;f=include%2Fircd_snprintf.h;fp=include%2Fircd_snprintf.h;h=23fa826b45b71bf04b84996e4032967ccede1bd1;hp=0000000000000000000000000000000000000000;hb=0400a5a6479398d82526785c18c0df8bc8b92dce;hpb=d17e10da972ce5776c60b4c317267c6abe0e1ead diff --git a/include/ircd_snprintf.h b/include/ircd_snprintf.h new file mode 100644 index 0000000..23fa826 --- /dev/null +++ b/include/ircd_snprintf.h @@ -0,0 +1,321 @@ +#ifndef INCLUDED_ircd_snprintf_h +#define INCLUDED_ircd_snprintf_h +/* + * IRC - Internet Relay Chat, include/ircd_snprintf.h + * Copyright (C) 2000 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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. + */ +/** @file + * @brief IRC-specific printf() clone interface. + * @version $Id$ + */ +#ifndef INCLUDED_sys_types_h +#include +#define INCLUDED_sys_types_h +#endif +#ifndef INCLUDED_stdarg_h +#include +#define INCLUDED_stdarg_h +#endif + +struct Client; + +/** 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 */ +}; + +#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: +** +**
  • 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. +** +** @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 */