Merge branch 'u2_10_12_branch' of git://git.code.sf.net/p/undernet-ircu/ircu2
[ircu2.10.12-pk.git] / doc / api / ircd_snprintf.txt
diff --git a/doc/api/ircd_snprintf.txt b/doc/api/ircd_snprintf.txt
new file mode 100644 (file)
index 0000000..ee9b7f2
--- /dev/null
@@ -0,0 +1,268 @@
+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>