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