]>
Commit | Line | Data |
---|---|---|
189935b1 | 1 | #ifndef INCLUDED_ircd_snprintf_h |
2 | #define INCLUDED_ircd_snprintf_h | |
3 | /* | |
4 | * IRC - Internet Relay Chat, include/ircd_snprintf.h | |
5 | * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2, or (at your option) | |
10 | * any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | */ | |
21 | /** @file | |
22 | * @brief IRC-specific printf() clone interface. | |
23 | * @version $Id: ircd_snprintf.h,v 1.8 2004/10/05 04:21:37 entrope Exp $ | |
24 | */ | |
25 | #ifndef INCLUDED_sys_types_h | |
26 | #include <sys/types.h> | |
27 | #define INCLUDED_sys_types_h | |
28 | #endif | |
29 | #ifndef INCLUDED_stdarg_h | |
30 | #include <stdarg.h> | |
31 | #define INCLUDED_stdarg_h | |
32 | #endif | |
33 | ||
34 | struct Client; | |
35 | ||
36 | /** structure passed as argument for %v conversion */ | |
37 | struct VarData { | |
38 | size_t vd_chars; /**< number of characters inserted */ | |
39 | size_t vd_overflow; /**< number of characters that couldn't be */ | |
40 | const char *vd_format; /**< format string */ | |
41 | va_list vd_args; /**< arguments for %v */ | |
42 | }; | |
43 | ||
44 | #ifndef HAVE_VA_COPY | |
45 | #if HAVE___VA_COPY | |
46 | #define va_copy(DEST, SRC) __va_copy(DEST, SRC) | |
47 | #else | |
48 | /** Fallback macro to copy to \a DEST from \a SRC. */ | |
49 | #define va_copy(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof(DEST)) | |
50 | #endif | |
51 | #endif | |
52 | ||
53 | extern int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len, | |
54 | const char *format, ...); | |
55 | extern int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len, | |
56 | const char *format, va_list args); | |
57 | ||
58 | /** @fn int ircd_snprintf(struct Client *dest, char *buf, size_t | |
59 | buf_len, const char *format, ...) | |
60 | ** | |
61 | ** These functions are intended to be a complete replacement for | |
62 | ** sprintf and sprintf_irc. They are a (nearly) complete | |
63 | ** reimplementation, and of course they're snprintf clones, making it | |
64 | ** more difficult for accidental buffer overflows to crop up. | |
65 | ** | |
66 | ** First off, what's missing? These functions support all ANSI C | |
67 | ** conversion specifiers and selected ones from ISO 9x, with the | |
68 | ** exception of all floating-point conversions. The floating-point | |
69 | ** conversions are tricky, and will likely be dependent on the | |
70 | ** representation of a floating-point number on a particular | |
71 | ** architecture. While that representation is likely to conform to | |
72 | ** some standard, it is not currently used in ircu, so seemed like a | |
73 | ** good thing to omit, given the difficulty of implementing it. | |
74 | ** | |
75 | ** There are two more things missing from this implementation that | |
76 | ** would be required by ANSI; the first is support for multibyte | |
77 | ** character strings, and the second is support for locales, neither | |
78 | ** of which have any relevance for ircu, so again omission seemed to | |
79 | ** be a good policy. Additionally, %#x always causes '0x' (or '0X') | |
80 | ** to be printed, even if the number is zero. | |
81 | ** | |
82 | ** These functions also have some extensions not seen in a | |
83 | ** standards-compliant implementation; technically, the ISO 9x | |
84 | ** extensions fall into this category, for instance. The ISO 9x | |
85 | ** extensions supported are type extensions--%ju, %tu, and %zu, for | |
86 | ** instance; %qu and %hhu are also supported. The extensions added | |
87 | ** for use in ircu are %Tu, which takes a time_t, and the new %C | |
88 | ** conversion, which inserts either a numeric or a nick, dependant on | |
89 | ** the <dest> parameter. The GNU %m extension, which inserts the | |
90 | ** strerror() string corresponding to the current value of errno, is | |
91 | ** also supported, as is a special %v extension, which essentially | |
92 | ** does a recursive call to ircd_snprintf. | |
93 | ** | |
94 | ** The following description is descended from the Linux manpage for | |
95 | ** the printf family of functions. | |
96 | ** | |
97 | ** The format string is composed of zero or more directives: | |
98 | ** ordinary characters (not %), which are copied unchanged to the | |
99 | ** output stream; and conversion specifications, each of which results | |
100 | ** in fetching zero or more subsequent arguments. Each conversion | |
101 | ** specification is introduced by the character %. The arguments must | |
102 | ** correspond properly (after type promotion) with the conversion | |
103 | ** specifier. After the %, the following appear in sequence: | |
104 | ** | |
105 | ** <ul><li>Zero or more of the following flags:<dl> | |
106 | ** | |
107 | ** <dt>#</dt> | |
108 | ** <dd>specifying that the value should be converted to an | |
109 | ** "alternate form." For c, d, i, n, p, s, and u conversions, | |
110 | ** this option has no effect. For o conversions, the precision | |
111 | ** of the number is increased to force the first character of the | |
112 | ** output string to a zero (except if a zero value is printed | |
113 | ** with an explicit precision of zero). For x and X conversions, | |
114 | ** the string '0x' (or '0X' for X conversions) is prepended to | |
115 | ** it. For e, E, f, g, and G conversions, the result will always | |
116 | ** contain a decimal point, even if no digits follow it | |
117 | ** (normally, a decimal point appears in the results of those | |
118 | ** conversions only if a digit follows). For g and G | |
119 | ** conversions, trailing zeros are not removed from the result as | |
120 | ** they would otherwise be. For C conversions, if the | |
121 | ** destination is local and the origin is a user, the | |
122 | ** nick!user\@host form is used.</dd> | |
123 | ** | |
124 | ** <dt>0</dt> | |
125 | ** <dd> specifying zero padding. For all conversions except n, the | |
126 | ** converted value is padded on the left with zeros rather than | |
127 | ** blanks. If a precision is given with a numeric conversion (d, | |
128 | ** i, o, u, i, x, and X), the 0 flag is ignored.</dd> | |
129 | ** | |
130 | ** <dt>-</dt> | |
131 | ** <dd>(a negative field width flag) indicates the converted value is | |
132 | ** to be left adjusted on the field boundary. Except for n | |
133 | ** conversions, the converted value is padded on the right with | |
134 | ** blanks, rather than on the left with blanks or zeros. A - | |
135 | ** overrides a 0 if both are given.</dd> | |
136 | ** | |
137 | ** <dt>' ' (a space)</dt> | |
138 | ** <dd>specifying that a blank should be left before a | |
139 | ** positive number produced by a signed conversion (d, e, E, f, | |
140 | ** g, G, or i).</dd> | |
141 | ** | |
142 | ** <dt>+</dt> | |
143 | ** <dd>specifying that a sign always be placed before a number | |
144 | ** produced by a signed conversion. A + overrides a space if | |
145 | ** both are used.</dd> | |
146 | ** | |
147 | ** <dt>:</dt> | |
148 | ** <dd>specifying that a struct Client name should be preceded by a | |
149 | ** ':' character if the destination is a user.</dd> | |
150 | ** </dl></li> | |
151 | ** | |
152 | ** <li>An optional decimal digit string specifying a minimum field | |
153 | ** width. If the converted value has fewer characters than the | |
154 | ** field width, it will be padded with spaces on the left (or right, | |
155 | ** if the left-adjustment flag has been given) to fill out the field | |
156 | ** width.</li> | |
157 | ** | |
158 | ** <li>An optional precision, in the form of a period (`.') followed by | |
159 | ** an optional digit string. If the digit string is omitted, the | |
160 | ** precision is taken as zero. This gives the minimum number of | |
161 | ** digits to appear for d, i, o, u, x, and X conversions, the number | |
162 | ** of digits to appear after the decimal-point for e, E, and f | |
163 | ** conversions, the maximum number of significant digits for g and G | |
164 | ** conversions, or the maximum number of characters to be printed | |
165 | ** from a string for s conversions.</li> | |
166 | ** | |
167 | ** <li>The optional character h, specifying that a following d, i, o, u, | |
168 | ** x, or X conversion corresponds to a short int or unsigned short | |
169 | ** int argument, or that a following n conversion corresponds to a | |
170 | ** pointer to a short int argument. If the h character is given | |
171 | ** again, char is used instead of short int.</li> | |
172 | ** | |
173 | ** <li>The optional character l (ell) specifying that a following d, i, | |
174 | ** o, u, x, or X conversion applies to a pointer to a long int or | |
175 | ** unsigned long int argument, or that a following n conversion | |
176 | ** corresponds to a pointer to a long int argument.</li> | |
177 | ** | |
178 | ** <li>The character L specifying that a following e, E, f, g, or G | |
179 | ** conversion corresponds to a long double argument, or a following | |
180 | ** d, i, o, u, x, or X conversion corresponds to a long long | |
181 | ** argument. Note that long long is not specified in ANSI C and | |
182 | ** therefore not portable to all architectures.</li> | |
183 | ** | |
184 | ** <li>The optional character q. This is equivalent to L.</li> | |
185 | ** | |
186 | ** <li>A j character specifying that the following integer (d, i, o, u, | |
187 | ** x, or X) conversion corresponds to an intmax_t argument.</li> | |
188 | ** | |
189 | ** <li>A t character specifying that the following integer (d, i, o, u, | |
190 | ** x, or X) conversion corresponds to a ptrdiff_t argument.</li> | |
191 | ** | |
192 | ** <li>A z character specifying that the following integer (d, i, o, u, | |
193 | ** x, or X) conversion corresponds to a size_t argument.</li> | |
194 | ** | |
195 | ** <li>A T character specifying that the following integer (d, i, o, u, | |
196 | ** x, or X) conversion corresponds to a time_t argument.</li> | |
197 | ** | |
198 | ** <li>A character that specifies the type of conversion to be applied.</li> | |
199 | ** </ul> | |
200 | ** | |
201 | ** A field width or precision, or both, may be indicated by an | |
202 | ** asterisk `*' instead of a digit string. In this case, an int | |
203 | ** argument supplies the field width or precision. A negative field | |
204 | ** width is treated as a left adjustment flag followed by a positive | |
205 | ** field width; a negative precision is treated as though it were | |
206 | ** missing. | |
207 | ** | |
208 | ** The conversion specifiers and their meanings are: | |
209 | ** | |
210 | ** <dl> | |
211 | ** <dt>diouxX</dt> | |
212 | ** <dd>The int (or appropriate variant) argument is converted | |
213 | ** to signed decimal (d and i), unsigned octal (o), | |
214 | ** unsigned decimal (u), or unsigned hexadecimal (x and | |
215 | ** X) notation. The letters abcdef are used for x | |
216 | ** conversions; the letters ABCDEF are used for X | |
217 | ** conversions. The precision, if any, gives the minimum | |
218 | ** number of digits that must appear; if the converted | |
219 | ** value requires fewer digits, it is padded on the left | |
220 | ** with zeros.</dd> | |
221 | ** | |
222 | ** <dt>eE [NOT IMPLEMENTED]</dt> | |
223 | ** <dd>The double argument is rounded and | |
224 | ** converted in the style [-]d.dddedd where there is one | |
225 | ** digit before the decimal-point character and the | |
226 | ** number of digits after it is equal to the precision; | |
227 | ** if the precision is missing, it is taken as 6; if the | |
228 | ** precision is zero, no decimal-point character appears. | |
229 | ** An E conversion uses the letter E (rather than e) to | |
230 | ** introduce the exponent. The exponent always contains | |
231 | ** at least two digits; if the value is zero, the | |
232 | ** exponent is 00.</dd> | |
233 | ** | |
234 | ** <dt>f [NOT IMPLEMENTED]</dt> | |
235 | ** <dd>The double argument is rounded and | |
236 | ** converted to decimal notation in the style | |
237 | ** [-]ddd.ddd, where the number of digits after the | |
238 | ** decimal-point character is equal to the precision | |
239 | ** specification. If the precision is missing, it is | |
240 | ** taken as 6; if the precision is explicitly zero, no | |
241 | ** decimal-point character appears. If a decimal point | |
242 | ** appears, at least one digit appears before it.</dd> | |
243 | ** | |
244 | ** <dt>g [NOT IMPLEMENTED]</dt> | |
245 | ** <dd>The double argument is converted in | |
246 | ** style f or e (or E for G conversions). The precision | |
247 | ** specifies the number of significant digits. If the | |
248 | ** precision is missing, 6 digits are given; if the | |
249 | ** precision is zero, it is treated as 1. Style e is | |
250 | ** used if the exponent from its conversion is less than | |
251 | ** -4 or greater than or equal to the precision. | |
252 | ** Trailing zeros are removed from the fractional part of | |
253 | ** the result; a decimal point appears only if it is | |
254 | ** followed by at least one digit.</dd> | |
255 | ** | |
256 | ** <dt>c</dt> | |
257 | ** <dd>The int argument is converted to an unsigned char, and | |
258 | ** the resulting character is written.</dd> | |
259 | ** | |
260 | ** <dt>s</dt> | |
261 | ** <dd>The "char *" argument is expected to be a pointer to | |
262 | ** an array of character type (pointer to a string). | |
263 | ** Characters from the array are written up to (but not | |
264 | ** including) a terminating NUL character; if a precision | |
265 | ** is specified, no more than the number specified are | |
266 | ** written. If a precision is given, no null character | |
267 | ** need be present; if the precision is not specified, or | |
268 | ** is greater than the size of the array, the array must | |
269 | ** contain a terminating NUL character.</dd> | |
270 | ** | |
271 | ** <dt>p</dt> | |
272 | ** <dd>The "void *" pointer argument is printed in | |
273 | ** hexadecimal (as if by %#x or %#lx).</dd> | |
274 | ** | |
275 | ** <dt>n</dt> | |
276 | ** <dd>The number of characters written so far is stored into | |
277 | ** the integer indicated by the ``int *'' (or variant) | |
278 | ** pointer argument. No argument is converted.</dd> | |
279 | ** | |
280 | ** <dt>m</dt> | |
281 | ** <dd>The error message associated with the current value of | |
282 | ** errno is printed as if by %s.</dd> | |
283 | ** | |
284 | ** <dt>C</dt> | |
285 | ** <dd>The client argument identifier is printed under the | |
286 | ** control of the <dest> argument; if <dest> is NULL or | |
287 | ** is a user, the client's name (nickname or server name) | |
288 | ** is printed; otherwise, the client's network numeric is | |
289 | ** printed.</dd> | |
290 | ** | |
291 | ** <dt>H</dt> | |
292 | ** <dd>The channel argument identifier (channel name) is | |
293 | ** printed.</dd> | |
294 | ** | |
295 | ** <dt>v</dt> | |
296 | ** <dd>The argument given must be a pointer to a struct | |
297 | ** VarData with vd_format and vd_args must be initialized | |
298 | ** appropriately. On return, vd_chars will contain the | |
299 | ** number of characters added to the buffer, and | |
300 | ** vd_overflow will contain the number of characters that | |
301 | ** could not be added due to buffer overflow or due to a | |
302 | ** precision.</dd> | |
303 | ** | |
304 | ** <dt>%<dt> | |
305 | ** <dd>A `%' is written. No argument is converted. The | |
306 | ** complete conversion specification is `%%'.</dd> | |
307 | ** </dl> | |
308 | ** | |
309 | ** In no case does a non-existent or small field width cause | |
310 | ** truncation of a field; if the result of a conversion is wider than | |
311 | ** the field width, the field is expanded to contain the conversion | |
312 | ** result. | |
313 | ** | |
314 | ** @param[in] dest Client receiving of message. | |
315 | ** @param[out] buf Output buffer for formatted message. | |
316 | ** @param[in] buf_len Number of bytes that can be written to \a buf. | |
317 | ** @param[in] format Format string for message. | |
318 | ** @return Number of bytes that would be written to \a buf without truncation. | |
319 | */ | |
320 | ||
321 | #endif /* INCLUDED_ircd_snprintf_h */ |