1 2 snprintf.c 3 - a portable implementation of snprintf, 4 including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf 5 6 snprintf is a routine to convert numeric and string arguments to 7 formatted strings. It is similar to sprintf(3) provided in a system's 8 C library, yet it requires an additional argument - the buffer size - 9 and it guarantees never to store anything beyond the given buffer, 10 regardless of the format or arguments to be formatted. Some newer 11 operating systems do provide snprintf in their C library, but many do 12 not or do provide an inadequate (slow or idiosyncratic) version, which 13 calls for a portable implementation of this routine. 14 15Author 16 17 Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000 18 Copyright � 1999, Mark Martinec 19 20Terms and conditions ... 21 22 This program is free software; you can redistribute it and/or modify 23 it under the terms of the Frontier Artistic License which comes with 24 this Kit. 25 26Features 27 28 * careful adherence to specs regarding flags, field width and 29 precision; 30 * good performance for large string handling (large format, large 31 argument or large paddings). Performance is similar to system's 32 sprintf and in several cases significantly better (make sure you 33 compile with optimizations turned on, tell the compiler the code 34 is strict ANSI if necessary to give it more freedom for 35 optimizations); 36 * return value semantics per ISO/IEC 9899:1999 ("ISO C99"); 37 * written in standard ISO/ANSI C - requires an ANSI C compiler. 38 39Supported conversion specifiers and data types 40 41 This snprintf only supports the following conversion specifiers: s, c, 42 d, o, u, x, X, p (and synonyms: i, D, U, O - see below) with flags: 43 '-', '+', ' ', '0' and '#'. An asterisk is supported for field width 44 as well as precision. 45 46 Length modifiers 'h' (short int), 'l' (long int), and 'll' (long long 47 int) are supported. 48 49 NOTE: 50 51 If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the 52 length modifier 'll' is recognized but treated the same as 'l', 53 which may cause argument value truncation! Defining 54 SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also 55 handles length modifier 'll'. long long int is a language extension 56 which may not be portable. 57 58 Conversion of numeric data (conversion specifiers d, o, u, x, X, p) 59 with length modifiers (none or h, l, ll) is left to the system routine 60 sprintf, but all handling of flags, field width and precision as well 61 as c and s conversions is done very carefully by this portable 62 routine. If a string precision (truncation) is specified (e.g. %.8s) 63 it is guaranteed the string beyond the specified precision will not be 64 referenced. 65 66 Length modifiers h, l and ll are ignored for c and s conversions (data 67 types wint_t and wchar_t are not supported). 68 69 The following common synonyms for conversion characters are supported: 70 * i is a synonym for d 71 * D is a synonym for ld, explicit length modifiers are ignored 72 * U is a synonym for lu, explicit length modifiers are ignored 73 * O is a synonym for lo, explicit length modifiers are ignored 74 75 The D, O and U conversion characters are nonstandard, they are 76 supported for backward compatibility only, and should not be used for 77 new code. 78 79 The following is specifically not supported: 80 * flag ' (thousands' grouping character) is recognized but ignored 81 * numeric conversion specifiers: f, e, E, g, G and synonym F, as 82 well as the new a and A conversion specifiers 83 * length modifier 'L' (long double) and 'q' (quad - use 'll' 84 instead) 85 * wide character/string conversions: lc, ls, and nonstandard 86 synonyms C and S 87 * writeback of converted string length: conversion character n 88 * the n$ specification for direct reference to n-th argument 89 * locales 90 91 It is permitted for str_m to be zero, and it is permitted to specify 92 NULL pointer for resulting string argument if str_m is zero (as per 93 ISO C99). 94 95 The return value is the number of characters which would be generated 96 for the given input, excluding the trailing null. If this value is 97 greater or equal to str_m, not all characters from the result have 98 been stored in str, output bytes beyond the (str_m-1) -th character 99 are discarded. If str_m is greater than zero it is guaranteed the 100 resulting string will be null-terminated. 101 102 NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, 103 but is different from some older and vendor implementations, and is 104 also different from XPG, XSH5, SUSv2 specifications. For historical 105 discussion on changes in the semantics and standards of snprintf see 106 printf(3) man page in the Linux programmers manual. 107 108 Routines asprintf and vasprintf return a pointer (in the ptr argument) 109 to a buffer sufficiently large to hold the resulting string. This 110 pointer should be passed to free(3) to release the allocated storage 111 when it is no longer needed. If sufficient space cannot be allocated, 112 these functions will return -1 and set ptr to be a NULL pointer. These 113 two routines are a GNU C library extensions (glibc). 114 115 Routines asnprintf and vasnprintf are similar to asprintf and 116 vasprintf, yet, like snprintf and vsnprintf counterparts, will write 117 at most str_m-1 characters into the allocated output string, the last 118 character in the allocated buffer then gets the terminating null. If 119 the formatted string length (the return value) is greater than or 120 equal to the str_m argument, the resulting string was truncated and 121 some of the formatted characters were discarded. These routines 122 present a handy way to limit the amount of allocated memory to some 123 sane value. 124 125Availability 126 127 http://www.ijs.si/software/snprintf/ 128 * snprintf_1.3.tar.gz (1999-06-30), md5 sum: snprintf_1.3.tar.gz.md5 129 * snprintf_2.1.tar.gz (2000-07-14), md5 sum: snprintf_2.1.tar.gz.md5 130 * snprintf_2.2.tar.gz (2000-10-18), md5 sum: snprintf_2.2.tar.gz.md5 131 132Mailing list 133 134 There is a very low-traffic mailing list snprintf-announce@ijs.si 135 where announcements about new versions will be posted as well as 136 warnings about threatening bugs if discovered. The posting is 137 restricted to snprintf developer(s). 138 139 To subscribe to (or unsubscribe from) the mailing list please visit 140 the list server's web page 141 http://mailman.ijs.si/listinfo/snprintf-announce 142 143 You can also subscribe to the list by mailing the command SUBSCRIBE 144 either in the subject or in the message body to the address 145 snprintf-announce-request@ijs.si . You will be asked for confirmation 146 before subscription will be effective. 147 148 The list of members is only accessible to the list administrator, so 149 there is no need for concern about automatic e-mail address gatherers. 150 151 Questions about the mailing list and concerns for the attention of a 152 person should be sent to snprintf-announce-admin@ijs.si 153 154 There is no general discussion list about portable snprintf at the 155 moment. Please send comments and suggestion to the author. 156 157Revision history 158 159 Version 1.3 fixes a runaway loop problem from 1.2. Please upgrade. 160 161 1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si> 162 163 + fixed runaway loop (eventually crashing when str_l wraps 164 beyond 2^31) while copying format string without conversion 165 specifiers to a buffer that is too short (thanks to Edwin 166 Young <edwiny@autonomy.com> for spotting the problem); 167 + added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) to 168 snprintf.h 169 170 2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si> 171 172 + relaxed license terms: The Artistic License now applies. You 173 may still apply the GNU GENERAL PUBLIC LICENSE as was 174 distributed with previous versions, if you prefer; 175 + changed REVISION HISTORY dates to use ISO 8601 date format; 176 + added vsnprintf (patch also independently proposed by Caol�n 177 McNamara 2000-05-04, and Keith M Willenson 2000-06-01) 178 179 2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si> 180 181 + removed POSIX check for str_m < 1; value 0 for str_m is 182 allowed by ISO C99 (and GNU C library 2.1) (pointed out on 183 2000-05-04 by Caol�n McNamara, caolan@ csn dot ul dot ie). 184 Besides relaxed license this change in standards adherence is 185 the main reason to bump up the major version number; 186 + added nonstandard routines asnprintf, vasnprintf, asprintf, 187 vasprintf that dynamically allocate storage for the resulting 188 string; these routines are not compiled by default, see 189 comments where NEED_V?ASN?PRINTF macros are defined; 190 + autoconf contributed by Caol�n McNamara 191 192 2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si> 193 194 + BUG FIX: the %c conversion used a temporary variable that was 195 no longer in scope when referenced, possibly causing 196 incorrect resulting character; 197 + BUG FIX: make precision and minimal field width unsigned to 198 handle huge values (2^31 <= n < 2^32) correctly; also be more 199 careful in the use of signed/unsigned/size_t internal 200 variables -- probably more careful than many vendor 201 implementations, but there may still be a case where huge 202 values of str_m, precision or minimal field could cause 203 incorrect behaviour; 204 + use separate variables for signed/unsigned arguments, and for 205 short/int, long, and long long argument lengths to avoid 206 possible incompatibilities on certain computer architectures. 207 Also use separate variable arg_sign to hold sign of a numeric 208 argument, to make code more transparent; 209 + some fiddling with zero padding and "0x" to make it Linux 210 compatible; 211 + systematically use macros fast_memcpy and fast_memset instead 212 of case-by-case hand optimization; determine some breakeven 213 string lengths for different architectures; 214 + terminology change: format -> conversion specifier, C9x -> 215 ISO/IEC 9899:1999 ("ISO C99"), alternative form -> alternate 216 form, data type modifier -> length modifier; 217 + several comments rephrased and new ones added; 218 + make compiler not complain about 'credits' defined but not 219 used; 220 221Other implementations of snprintf 222 223 I am aware of some other (more or less) portable implementations of 224 snprintf. I do not claim they are free software - please refer to 225 their respective copyright and licensing terms. If you know of other 226 versions please let me know. 227 * a very thorough implementation (src/util_snprintf.c) by the Apache 228 Group distributed with the Apache web server - 229 http://www.apache.org/ . Does its own floating point conversions 230 using routines ecvt(3), fcvt(3) and gcvt(3) from the standard C 231 library or from the GNU libc. 232 This is from the code: 233 234 This software [...] was originally based on public domain software 235 written at the National Center for Supercomputing Applications, 236 University of Illinois, Urbana-Champaign. 237 [...] This code is based on, and used with the permission of, the 238 SIO stdio-replacement strx_* functions by Panos Tsirigotis 239 <panos@alumni.cs.colorado.edu> for xinetd. 240 * QCI Utilities use a modified version of snprintf from the Apache 241 group. 242 * implementations as distributed with OpenBSD, FreeBSD, and NetBSD 243 are all wrappers to vfprintf.c, which is derived from software 244 contributed to Berkeley by Chris Torek. 245 * implementation from Prof. Patrick Powell <papowell@sdsu.edu>, 246 Dept. Electrical and Computer Engineering, San Diego State 247 University, San Diego, CA 92182-1309, published in Bugtraq 248 archives for 3rd quarter (Jul-Aug) 1995. No floating point 249 conversions. 250 * Brandon Long's <blong@fiction.net> modified version of Prof. 251 Patrick Powell's snprintf with contributions from others. With 252 minimal floating point support. 253 * implementation (src/snprintf.c) as distributed with sendmail - 254 http://www.sendmail.org/ is a cleaned up Prof. Patrick Powell's 255 version to compile properly and to support .precision and %lx. 256 * implementation from Caol�n McNamara available at 257 http://www.csn.ul.ie/~caolan/publink/snprintf-1.1.tar.gz, handles 258 floating point. 259 * implementation used by newlog (a replacement for syslog(3)) made 260 available by the SOS Corporation. Enabling floating point support 261 is a compile-time option. 262 * implementation by Michael Richardson <mcr@metis.milkyway.com> is 263 available at http://sandelman.ottawa.on.ca/SSW/snp/snp.html. It is 264 based on BSD44-lite's vfprintf() call, modified to function on 265 SunOS. Needs internal routines from the 4.4 strtod (included), 266 requires GCC to compile the long long (aka quad_t) portions. 267 * implementation from Tomi Salo <ttsalo@ssh.fi> distributed with SSH 268 2.0 Unix Server. Not in public domain. Floating point conversions 269 done by system's sprintf. 270 * and for completeness: my portable version described in this very 271 document available at http://www.ijs.si/software/snprintf/ . 272 273 In retrospect, it appears that a lot of effort was wasted by many 274 people for not being aware of what others are doing. Sigh. 275 276 Also of interest: The Approved Base Working Group Resolution for XSH5, 277 Ref: bwg98-006, Topic: snprintf. 278 _________________________________________________________________ 279 280 mm 281 Last updated: 2000-10-18 282 283 Valid HTML 4.0! 284