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