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> |