Wed, 20 Jun 2007 22:24:09 +0200
CF_NO_GETTEXT
| 35 | 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 | ||
| 15 | Author | |
| 16 | ||
| 17 | Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000 | |
| 18 | Copyright © 1999, Mark Martinec | |
| 19 | ||
| 20 | Terms 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 | ||
| 26 | Features | |
| 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 | ||
| 39 | Supported 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 | ||
| 125 | Availability | |
| 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 | ||
| 132 | Mailing 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 | ||
| 157 | Revision 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 | ||
| 221 | Other 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! |