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