snprintf.c
+ - a portable implementation of snprintf,
+ including
+vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
+
+
+
snprintf is a routine to convert numeric and string arguments
+to formatted strings. It is similar to sprintf(3) provided in a
+system's C library, yet it requires an additional argument - the buffer
+size - and it guarantees never to store anything beyond the given buffer,
+regardless of the format or arguments to be formatted. Some newer
+operating systems do provide snprintf in their C library,
+but many do not or do provide an inadequate (slow or idiosyncratic)
+version, which calls for a portable implementation of this routine.
+
+
This program is free software; you can redistribute it
+and/or modify it under the terms of the
+Frontier Artistic License
+which comes with this Kit.
+
+
Features
+
+
+
careful adherence to specs regarding flags, field width and precision;
+
good performance for large string handling (large format, large argument
+or large paddings). Performance is similar to system's sprintf
+and in several cases significantly better (make sure you compile with
+optimizations turned on, tell the compiler the code is strict ANSI
+if necessary to give it more freedom for optimizations);
+
return value semantics per ISO/IEC 9899:1999 ("ISO C99");
+
written in standard ISO/ANSI C - requires an ANSI C compiler.
+
+
+
Supported conversion specifiers and data types
+
+
This snprintf only supports the following conversion specifiers:
+s, c, d, o, u, x, X, p (and synonyms: i, D, U, O - see below)
+with flags: '-', '+', ' ', '0' and '#'.
+An asterisk is supported for field width as well as precision.
+
+
Length modifiers 'h' (short int), 'l' (long int),
+and 'll' (long long int) are supported.
+
+
NOTE:
+
+If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default)
+the length modifier 'll' is recognized but treated the same as 'l',
+which may cause argument value truncation!
+Defining SNPRINTF_LONGLONG_SUPPORT requires that your system's
+sprintf also handles length modifier 'll'.
+long long int is a language extension which may not be portable.
+
+
+
Conversion of numeric data (conversion specifiers d, o, u, x, X, p)
+with length modifiers (none or h, l, ll) is left to the system
+routine sprintf, but all handling of flags, field width and precision
+as well as c and s conversions is done very carefully by this portable routine.
+If a string precision (truncation) is specified (e.g. %.8s) it is
+guaranteed the string beyond the specified precision will not be referenced.
+
+
Length modifiers h, l and ll are ignored for c and s conversions
+(data types wint_t and wchar_t are not supported).
+
+
The following common synonyms for conversion characters are supported:
+
+
i is a synonym for d
+
D is a synonym for ld, explicit length modifiers are ignored
+
U is a synonym for lu, explicit length modifiers are ignored
+
O is a synonym for lo, explicit length modifiers are ignored
+
+The D, O and U conversion characters are nonstandard, they are supported
+for backward compatibility only, and should not be used for new code.
+
+
The following is specifically not supported:
+
+
flag ' (thousands' grouping character) is recognized but ignored
+
numeric conversion specifiers: f, e, E, g, G and synonym F,
+as well as the new a and A conversion specifiers
+
wide character/string conversions: lc, ls, and nonstandard
+synonyms C and S
+
writeback of converted string length: conversion character n
+
the n$ specification for direct reference to n-th argument
+
locales
+
+
+
It is permitted for str_m to be zero, and it is permitted to specify NULL
+pointer for resulting string argument if str_m is zero (as per ISO C99).
+
+
The return value is the number of characters which would be generated
+for the given input, excluding the trailing null. If this value
+is greater or equal to str_m, not all characters from the result
+have been stored in str, output bytes beyond the (str_m-1) -th character
+are discarded. If str_m is greater than zero it is guaranteed
+the resulting string will be null-terminated.
+
+
NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1,
+but is different from some older and vendor implementations,
+and is also different from XPG, XSH5, SUSv2 specifications.
+For historical discussion on changes in the semantics and standards
+of snprintf see printf(3) man page in the Linux programmers manual.
+
+
Routines asprintf and vasprintf return a pointer (in the ptr argument)
+to a buffer sufficiently large to hold the resulting string. This pointer
+should be passed to free(3) to release the allocated storage when it is
+no longer needed. If sufficient space cannot be allocated, these functions
+will return -1 and set ptr to be a NULL pointer. These two routines are a
+GNU C library extensions (glibc).
+
+
Routines asnprintf and vasnprintf are similar to asprintf and vasprintf,
+yet, like snprintf and vsnprintf counterparts, will write at most str_m-1
+characters into the allocated output string, the last character in the
+allocated buffer then gets the terminating null. If the formatted string
+length (the return value) is greater than or equal to the str_m argument,
+the resulting string was truncated and some of the formatted characters
+were discarded. These routines present a handy way to limit the amount
+of allocated memory to some sane value.
+
+
There is a very low-traffic mailing list snprintf-announce@ijs.si
+where announcements about new versions will be posted
+as well as warnings about threatening bugs if discovered.
+The posting is restricted to snprintf developer(s).
+
+
You can also subscribe to the list by mailing
+the command SUBSCRIBE either in the subject or in the message body
+to the address snprintf-announce-request@ijs.si . You will be asked for
+confirmation before subscription will be effective.
+
+
The list of members is only accessible to the list administrator,
+so there is no need for concern about automatic e-mail address gatherers.
+
+
Questions about the mailing list and concerns for the attention
+of a person should be sent to snprintf-announce-admin@ijs.si
+
+
There is no general discussion list about portable snprintf
+at the moment. Please send comments and suggestion to the author.
+
+
+
Revision history
+
+
Version 1.3 fixes a runaway loop problem from 1.2. Please upgrade.
+
+
+
1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
+
+
fixed runaway loop (eventually crashing when str_l wraps
+ beyond 2^31) while copying format string without
+ conversion specifiers to a buffer that is too short
+ (thanks to Edwin Young <edwiny@autonomy.com> for spotting the problem);
+
added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) to snprintf.h
+
+
+
2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
+
+
relaxed license terms:
+ The Artistic License now applies.
+ You may still apply the GNU GENERAL PUBLIC LICENSE
+ as was distributed with previous versions, if you prefer;
+
added vsnprintf (patch also independently proposed by
+ Caolán McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
+
+
+
2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
+
+
removed POSIX check for str_m < 1; value 0 for str_m is
+ allowed by ISO C99 (and GNU C library 2.1) (pointed out
+ on 2000-05-04 by Caolán McNamara, caolan@ csn dot ul dot ie).
+ Besides relaxed license this change in standards adherence
+ is the main reason to bump up the major version number;
+
added nonstandard routines asnprintf, vasnprintf, asprintf,
+ vasprintf that dynamically allocate storage for the
+ resulting string; these routines are not compiled by default,
+ see comments where NEED_V?ASN?PRINTF macros are defined;
+
autoconf contributed by Caolán McNamara
+
+
+
2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si>
+
+
BUG FIX: the %c conversion used a temporary variable
+ that was no longer in scope when referenced,
+ possibly causing incorrect resulting character;
+
BUG FIX: make precision and minimal field width unsigned
+ to handle huge values (2^31 <= n < 2^32) correctly;
+ also be more careful in the use of signed/unsigned/size_t
+ internal variables -- probably more careful than many
+ vendor implementations, but there may still be a case
+ where huge values of str_m, precision or minimal field
+ could cause incorrect behaviour;
+
use separate variables for signed/unsigned arguments,
+ and for short/int, long, and long long argument lengths
+ to avoid possible incompatibilities on certain
+ computer architectures. Also use separate variable
+ arg_sign to hold sign of a numeric argument,
+ to make code more transparent;
+
some fiddling with zero padding and "0x" to make it
+ Linux compatible;
+
systematically use macros fast_memcpy and fast_memset
+ instead of case-by-case hand optimization; determine some
+ breakeven string lengths for different architectures;
+
terminology change: format -> conversion specifier,
+ C9x -> ISO/IEC 9899:1999 ("ISO C99"),
+ alternative form -> alternate form,
+ data type modifier -> length modifier;
+
several comments rephrased and new ones added;
+
make compiler not complain about 'credits' defined but
+ not used;
+
+
+
+
Other implementations of snprintf
+
+
I am aware of some other (more or less) portable implementations
+of snprintf. I do not claim they are free software - please refer
+to their respective copyright and licensing terms.
+If you know of other versions please let
+me know.
+
+
+
a very thorough implementation (src/util_snprintf.c)
+by the Apache Group distributed with the
+Apache web server
+- http://www.apache.org/ .
+Does its own floating point conversions using routines
+ecvt(3), fcvt(3) and gcvt(3) from the standard C library
+or from the GNU libc.
+
+ This is from the code:
+
+This software [...] was originally based
+on public domain software written at the
+National Center
+for Supercomputing Applications, University of Illinois,
+Urbana-Champaign.
+[...] This code is based on, and used with the permission of,
+the SIO stdio-replacement strx_* functions by Panos Tsirigotis
+<panos@alumni.cs.colorado.edu> for xinetd.
+
+
+
QCI
+Utilities use a modified version of snprintf from the Apache group.
+
+
implementations as distributed with
+OpenBSD,
+FreeBSD, and
+NetBSD
+are all wrappers to vfprintf.c, which is derived from software
+contributed to Berkeley by Chris Torek.
+
+
implementation from Prof. Patrick Powell
+<papowell@sdsu.edu>,
+Dept. Electrical and Computer Engineering, San Diego State University,
+San Diego, CA 92182-1309, published in
+Bugtraq
+archives for 3rd quarter (Jul-Aug) 1995.
+No floating point conversions.
+
+
Brandon Long's
+<blong@fiction.net>
+modified version
+of Prof. Patrick Powell's snprintf with contributions from others.
+With minimal floating point support.
+
+
implementation (src/snprintf.c) as distributed with
+sendmail - http://www.sendmail.org/
+is a cleaned up Prof. Patrick Powell's version
+to compile properly and to support .precision and %lx.
+
+
implementation used by
+newlog
+(a replacement for syslog(3)) made available by
+the SOS Corporation.
+Enabling floating point support is a compile-time option.
+
+
implementation by Michael Richardson
+<mcr@metis.milkyway.com>
+is available at
+http://sandelman.ottawa.on.ca/SSW/snp/snp.html.
+It is based on BSD44-lite's vfprintf() call, modified to function
+on SunOS. Needs internal routines from the 4.4 strtod (included),
+requires GCC to compile the long long (aka quad_t) portions.
+
+
implementation from Tomi Salo
+<ttsalo@ssh.fi>
+distributed with
+SSH 2.0
+Unix Server. Not in public domain.
+Floating point conversions done by system's sprintf.
+
+