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