]>
Commit | Line | Data |
---|---|---|
189935b1 | 1 | These functions are intended to be a complete replacement for sprintf |
2 | and sprintf_irc. They are a (nearly) complete reimplementation, and | |
3 | of course they're snprintf clones, making it more difficult for | |
4 | accidental buffer overflows to crop up. | |
5 | ||
6 | First off, what's missing? These functions support all ANSI C | |
7 | conversion specifiers and selected ones from ISO 9x, with the | |
8 | exception of all floating-point conversions. The floating-point | |
9 | conversions are tricky, and will likely be dependent on the | |
10 | representation of a floating-point number on a particular | |
11 | architecture. While that representation is likely to conform to some | |
12 | standard, it is not currently used in ircu, so seemed like a good | |
13 | thing to omit, given the difficulty of implementing it. | |
14 | ||
15 | There are two more things missing from this implementation that would | |
16 | be required by ANSI; the first is support for multibyte character | |
17 | strings, and the second is support for locales, neither of which have | |
18 | any relevance for ircu, so again omission seemed to be a good policy. | |
19 | Additionally, %#x always causes '0x' (or '0X') to be printed, even if | |
20 | the number is zero. | |
21 | ||
22 | These functions also have some extensions not seen in a | |
23 | standards-compliant implementation; technically, the ISO 9x extensions | |
24 | fall into this category, for instance. The ISO 9x extensions | |
25 | supported are type extensions--%ju, %tu, and %zu, for instance; %qu | |
26 | and %hhu are also supported. The extensions added for use in ircu are | |
27 | %Tu, which takes a time_t, and the new %C conversion, which inserts | |
28 | either a numeric or a nick, dependent on the <dest> parameter. The | |
29 | GNU %m extension, which inserts the strerror() string corresponding to | |
30 | the current value of errno, is also supported, as is a special %v | |
31 | extension, which essentially does a recursive call to ircd_snprintf. | |
32 | ||
33 | The following description is descended from the Linux man page for the | |
34 | printf family of functions. | |
35 | ||
36 | The format string is composed of zero or more directives: ordinary | |
37 | characters (not %), which are copied unchanged to the output stream; | |
38 | and conversion specifications, each of which results in fetching zero | |
39 | or more subsequent arguments. Each conversion specification is | |
40 | introduced by the character %. The arguments must correspond properly | |
41 | (after type promotion) with the conversion specifier. After the %, | |
42 | the following appear in sequence: | |
43 | ||
44 | * Zero or more of the following flags: | |
45 | ||
46 | # specifying that the value should be converted to an "alternate | |
47 | form." For c, d, i, n, p, s, and u conversions, this option | |
48 | has no effect. For o conversions, the precision of the number | |
49 | is increased to force the first character of the output string | |
50 | to a zero (except if a zero value is printed with an explicit | |
51 | precision of zero). For x and X conversions, the string '0x' | |
52 | (or '0X' for X conversions) is prepended to it. For e, E, f, | |
53 | g, and G conversions, the result will always contain a decimal | |
54 | point, even if no digits follow it (normally, a decimal point | |
55 | appears in the results of those conversions only if a digit | |
56 | follows). For g and G conversions, trailing zeros are not | |
57 | removed from the result as they would otherwise be. For C | |
58 | conversions, if the destination is local and the origin is a | |
59 | user, the nick!user@host form is used. | |
60 | ||
61 | 0 specifying zero padding. For all conversions except n, the | |
62 | converted value is padded on the left with zeros rather than | |
63 | blanks. If a precision is given with a numeric conversion (d, | |
64 | i, o, u, i, x, and X), the 0 flag is ignored. | |
65 | ||
66 | - (a negative field width flag) indicates the converted value is | |
67 | to be left adjusted on the field boundary. Except for n | |
68 | conversions, the converted value is padded on the right with | |
69 | blanks, rather than on the left with blanks or zeros. A - | |
70 | overrides a 0 if both are given. | |
71 | ||
72 | ' ' (a space) specifying that a blank should be left before a | |
73 | positive number produced by a signed conversion (d, e, E, f, | |
74 | g, G, or i). | |
75 | ||
76 | + specifying that a sign always be placed before a number | |
77 | produced by a signed conversion. A + overrides a space if | |
78 | both are used. | |
79 | ||
80 | : specifying that a struct Client name should be preceded by a | |
81 | ':' character if the destination is a user | |
82 | ||
83 | * An optional decimal digit string specifying a minimum field width. | |
84 | If the converted value has fewer characters than the field width, it | |
85 | will be padded with spaces on the left (or right, if the | |
86 | left-adjustment flag has been given) to fill out the field width. | |
87 | ||
88 | * An optional precision, in the form of a period (`.') followed by an | |
89 | optional digit string. If the digit string is omitted, the | |
90 | precision is taken as zero. This gives the minimum number of digits | |
91 | to appear for d, i, o, u, x, and X conversions, the number of digits | |
92 | to appear after the decimal-point for e, E, and f conversions, the | |
93 | maximum number of significant digits for g and G conversions, or the | |
94 | maximum number of characters to be printed from a string for s | |
95 | conversions. | |
96 | ||
97 | * The optional character h, specifying that a following d, i, o, u, x, | |
98 | or X conversion corresponds to a short int or unsigned short int | |
99 | argument, or that a following n conversion corresponds to a pointer | |
100 | to a short int argument. If the h character is given again, char is | |
101 | used instead of short int. | |
102 | ||
103 | * The optional character l (ell) specifying that a following d, i, o, | |
104 | u, x, or X conversion applies to a pointer to a long int or unsigned | |
105 | long int argument, or that a following n conversion corresponds to a | |
106 | pointer to a long int argument. | |
107 | ||
108 | * The character L specifying that a following e, E, f, g, or G | |
109 | conversion corresponds to a long double argument, or a following d, | |
110 | i, o, u, x, or X conversion corresponds to a long long argument. | |
111 | Note that long long is not specified in ANSI C and therefore not | |
112 | portable to all architectures. | |
113 | ||
114 | * The optional character q. This is equivalent to L. | |
115 | ||
116 | * A j character specifying that the following integer (d, i, o, u, x, | |
117 | or X) conversion corresponds to an intmax_t argument. | |
118 | ||
119 | * A t character specifying that the following integer (d, i, o, u, x, | |
120 | or X) conversion corresponds to a ptrdiff_t argument. | |
121 | ||
122 | * A z character specifying that the following integer (d, i, o, u, x, | |
123 | or X) conversion corresponds to a size_t argument. | |
124 | ||
125 | * A T character specifying that the following integer (d, i, o, u, x, | |
126 | or X) conversion corresponds to a time_t argument. | |
127 | ||
128 | * A character that specifies the type of conversion to be applied. | |
129 | ||
130 | A field width or precision, or both, may be indicated by an asterisk | |
131 | `*' instead of a digit string. In this case, an int argument supplies | |
132 | the field width or precision. A negative field width is treated as a | |
133 | left adjustment flag followed by a positive field width; a negative | |
134 | precision is treated as though it were missing. | |
135 | ||
136 | The conversion specifiers and their meanings are: | |
137 | ||
138 | diouxX The int (or appropriate variant) argument is converted | |
139 | to signed decimal (d and i), unsigned octal (o), | |
140 | unsigned decimal (u), or unsigned hexadecimal (x and | |
141 | X) notation. The letters abcdef are used for x | |
142 | conversions; the letters ABCDEF are used for X | |
143 | conversions. The precision, if any, gives the minimum | |
144 | number of digits that must appear; if the converted | |
145 | value requires fewer digits, it is padded on the left | |
146 | with zeros. | |
147 | ||
148 | eE [NOT IMPLEMENTED] The double argument is rounded and | |
149 | converted in the style [-]d.dddedd where there is one | |
150 | digit before the decimal-point character and the | |
151 | number of digits after it is equal to the precision; | |
152 | if the precision is missing, it is taken as 6; if the | |
153 | precision is zero, no decimal-point character | |
154 | appears. An E conversion uses the letter E (rather | |
155 | than e) to introduce the exponent. The exponent | |
156 | always contains at least two digits; if the value is | |
157 | zero, the exponent is 00. | |
158 | ||
159 | f [NOT IMPLEMENTED] The double argument is rounded and | |
160 | converted to decimal notation in the style | |
161 | [-]ddd.ddd, where the number of digits after the | |
162 | decimal-point character is equal to the precision | |
163 | specification. If the precision is missing, it is | |
164 | taken as 6; if the precision is explicitly zero, no | |
165 | decimal-point character appears. If a decimal point | |
166 | appears, at least one digit appears before it. | |
167 | ||
168 | g [NOT IMPLEMENTED] The double argument is converted in | |
169 | style f or e (or E for G conversions). The precision | |
170 | specifies the number of significant digits. If the | |
171 | precision is missing, 6 digits are given; if the | |
172 | precision is zero, it is treated as 1. Style e is | |
173 | used if the exponent from its conversion is less than | |
174 | -4 or greater than or equal to the precision. | |
175 | Trailing zeros are removed from the fractional part of | |
176 | the result; a decimal point appears only if it is | |
177 | followed by at least one digit. | |
178 | ||
179 | c The int argument is converted to an unsigned char, and | |
180 | the resulting character is written. | |
181 | ||
182 | s The "char *" argument is expected to be a pointer to | |
183 | an array of character type (pointer to a string). | |
184 | Characters from the array are written up to (but not | |
185 | including) a terminating NUL character; if a precision | |
186 | is specified, no more than the number specified are | |
187 | written. If a precision is given, no null character | |
188 | need be present; if the precision is not specified, or | |
189 | is greater than the size of the array, the array must | |
190 | contain a terminating NUL character. | |
191 | ||
192 | p The "void *" pointer argument is printed in | |
193 | hexadecimal (as if by %#x or %#lx). | |
194 | ||
195 | n The number of characters written so far is stored into | |
196 | the integer indicated by the ``int *'' (or variant) | |
197 | pointer argument. No argument is converted. | |
198 | ||
199 | m The error message associated with the current value of | |
200 | errno is printed as if by %s. | |
201 | ||
202 | C The client argument identifier is printed under the | |
203 | control of the <dest> argument; if <dest> is NULL or | |
204 | is a user, the client's name (nickname or server name) | |
205 | is printed; otherwise, the client's network numeric is | |
206 | printed. | |
207 | ||
208 | H The channel argument identifier (channel name) is | |
209 | printed. | |
210 | ||
211 | v The argument given must be a pointer to a struct | |
212 | VarData with vd_format and vd_args must be initialized | |
213 | appropriately. On return, vd_chars will contain the | |
214 | number of characters added to the buffer, and | |
215 | vd_overflow will contain the number of characters that | |
216 | could not be added due to buffer overflow or due to a | |
217 | precision. | |
218 | ||
219 | % A `%' is written. No argument is converted. The | |
220 | complete conversion specification is `%%'. | |
221 | ||
222 | In no case does a non-existent or small field width cause truncation | |
223 | of a field; if the result of a conversion is wider than the field | |
224 | width, the field is expanded to contain the conversion result. | |
225 | ||
226 | <struct> | |
227 | struct VarData { | |
228 | size_t vd_chars; /* number of characters inserted */ | |
229 | size_t vd_overflow; /* number of characters that couldn't be */ | |
230 | const char *vd_format; /* format string */ | |
231 | va_list vd_args; /* arguments for %v */ | |
232 | }; | |
233 | ||
234 | This structure is used by the %v conversion specification. The | |
235 | _vd_format_ element must contain a format string, and the _vd_args_ | |
236 | element must be a variable argument list. Upon return from | |
237 | ircd_snprintf() or ircd_vsnprintf(), the _vd_chars_ element will | |
238 | contain the number of characters that were able to be inserted, and | |
239 | the _vd_overflow_ element will contain the number of characters that | |
240 | could not be inserted. | |
241 | </struct> | |
242 | ||
243 | <function> | |
244 | int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len, | |
245 | const char *format, ...); | |
246 | ||
247 | This formats the argument list, under control of the _format_, into | |
248 | the buffer specified by _buf_, the size of which is specified by | |
249 | _buf_len_. The _dest_ parameter is used to determine whether to use a | |
250 | numeric or a nickname for %C conversions. | |
251 | </function> | |
252 | ||
253 | <function> | |
254 | int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len, | |
255 | const char *format, va_list args); | |
256 | ||
257 | This function is identical to the ircd_snprintf() function except for | |
258 | the variable argument list given by _args_. | |
259 | </function> | |
260 | ||
261 | <authors> | |
262 | Kev <klmitch@mit.edu> | |
263 | </authors> | |
264 | ||
265 | <changelog> | |
266 | [2001-6-15 Kev] Initial documentation of the ircd_snprintf family of | |
267 | functions. | |
268 | </changelog> |