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