Root/
Source at commit 1146 created 12 years 10 months ago. By azimutz, Sync with trunk (r1145). Add nVidia dev id's, 0DF4 for "GeForce GT 450M" (issue 99) and 1251 for "GeForce GTX 560M" (thanks to oSxFr33k for testing). | |
---|---|
1 | /*␊ |
2 | * vsnprintf.c␊ |
3 | *␊ |
4 | * vsnprintf(), from which the rest of the printf()␊ |
5 | * family is built␊ |
6 | */␊ |
7 | ␊ |
8 | #include "libsaio.h"␊ |
9 | #include "limits.h"␊ |
10 | enum flags {␊ |
11 | ␉FL_ZERO␉␉= 0x01,␉/* Zero modifier */␊ |
12 | ␉FL_MINUS␉= 0x02,␉/* Minus modifier */␊ |
13 | ␉FL_PLUS␉␉= 0x04,␉/* Plus modifier */␊ |
14 | ␉FL_TICK␉␉= 0x08,␉/* ' modifier */␊ |
15 | ␉FL_SPACE␉= 0x10,␉/* Space modifier */␊ |
16 | ␉FL_HASH␉␉= 0x20,␉/* # modifier */␊ |
17 | ␉FL_SIGNED␉= 0x40,␉/* Number is signed */␊ |
18 | ␉FL_UPPER␉= 0x80␉/* Upper case digits */␊ |
19 | };␊ |
20 | ␊ |
21 | /* These may have to be adjusted on certain implementations */␊ |
22 | enum ranks {␊ |
23 | ␉rank_char␉= -2,␊ |
24 | ␉rank_short␉= -1,␊ |
25 | ␉rank_int␉= 0,␊ |
26 | ␉rank_long␉= 1,␊ |
27 | ␉rank_longlong␉= 2␊ |
28 | };␊ |
29 | ␊ |
30 | #define MIN_RANK␉rank_char␊ |
31 | #define MAX_RANK␉rank_longlong␊ |
32 | ␊ |
33 | #define INTMAX_RANK␉rank_longlong␊ |
34 | #define SIZE_T_RANK␉rank_long␊ |
35 | #define PTRDIFF_T_RANK␉rank_long␊ |
36 | ␊ |
37 | #define EMIT(x) ({ if (o<n){*q++ = (x);} o++; })␊ |
38 | ␊ |
39 | static size_t␊ |
40 | format_int(char *q, size_t n, uintmax_t val, enum flags flags,␊ |
41 | ␉ int base, int width, int prec)␊ |
42 | {␊ |
43 | ␉char *qq;␊ |
44 | ␉size_t o = 0, oo;␊ |
45 | ␉static const char lcdigits[] = "0123456789abcdef";␊ |
46 | ␉static const char ucdigits[] = "0123456789ABCDEF";␊ |
47 | ␉const char *digits;␊ |
48 | ␉uintmax_t tmpval;␊ |
49 | ␉int minus = 0;␊ |
50 | ␉int ndigits = 0, nchars;␊ |
51 | ␉int tickskip, b4tick;␊ |
52 | ␊ |
53 | ␉/* Select type of digits */␊ |
54 | ␉digits = (flags & FL_UPPER) ? ucdigits : lcdigits;␊ |
55 | ␊ |
56 | ␉/* If signed, separate out the minus */␊ |
57 | ␉if (flags & FL_SIGNED && (intmax_t) val < 0) {␊ |
58 | ␉␉minus = 1;␊ |
59 | ␉␉val = (uintmax_t) (-(intmax_t) val);␊ |
60 | ␉}␊ |
61 | ␊ |
62 | ␉/* Count the number of digits needed. This returns zero for 0. */␊ |
63 | ␉tmpval = val;␊ |
64 | ␉while (tmpval) {␊ |
65 | ␉␉tmpval /= base;␊ |
66 | ␉␉ndigits++;␊ |
67 | ␉}␊ |
68 | ␊ |
69 | ␉/* Adjust ndigits for size of output */␊ |
70 | ␊ |
71 | ␉if (flags & FL_HASH && base == 8) {␊ |
72 | ␉␉if (prec < ndigits + 1)␊ |
73 | ␉␉␉prec = ndigits + 1;␊ |
74 | ␉}␊ |
75 | ␊ |
76 | ␉if (ndigits < prec) {␊ |
77 | ␉␉ndigits = prec;␉/* Mandatory number padding */␊ |
78 | ␉} else if (val == 0) {␊ |
79 | ␉␉ndigits = 1;␉/* Zero still requires space */␊ |
80 | ␉}␊ |
81 | ␊ |
82 | ␉/* For ', figure out what the skip should be */␊ |
83 | ␉if (flags & FL_TICK) {␊ |
84 | ␉␉tickskip = (base == 16) ? 4 : 3;␊ |
85 | ␉} else {␊ |
86 | ␉␉tickskip = ndigits;␉/* No tick marks */␊ |
87 | ␉}␊ |
88 | ␊ |
89 | ␉/* Tick marks aren't digits, but generated by the number converter */␊ |
90 | ␉ndigits += (ndigits - 1) / tickskip;␊ |
91 | ␊ |
92 | ␉/* Now compute the number of nondigits */␊ |
93 | ␉nchars = ndigits;␊ |
94 | ␊ |
95 | ␉if (minus || (flags & (FL_PLUS | FL_SPACE)))␊ |
96 | ␉␉nchars++;␉/* Need space for sign */␊ |
97 | ␉if ((flags & FL_HASH) && base == 16) {␊ |
98 | ␉␉nchars += 2;␉/* Add 0x for hex */␊ |
99 | ␉}␊ |
100 | ␊ |
101 | ␉/* Emit early space padding */␊ |
102 | ␉if (!(flags & (FL_MINUS | FL_ZERO)) && width > nchars) {␊ |
103 | ␉␉while (width > nchars) {␊ |
104 | ␉␉␉EMIT(' ');␊ |
105 | ␉␉␉width--;␊ |
106 | ␉␉}␊ |
107 | ␉}␊ |
108 | ␊ |
109 | ␉/* Emit nondigits */␊ |
110 | ␉if (minus)␊ |
111 | ␉␉EMIT('-');␊ |
112 | ␉else if (flags & FL_PLUS)␊ |
113 | ␉␉EMIT('+');␊ |
114 | ␉else if (flags & FL_SPACE)␊ |
115 | ␉␉EMIT(' ');␊ |
116 | ␊ |
117 | ␉if ((flags & FL_HASH) && base == 16) {␊ |
118 | ␉␉EMIT('0');␊ |
119 | ␉␉EMIT((flags & FL_UPPER) ? 'X' : 'x');␊ |
120 | ␉}␊ |
121 | ␊ |
122 | ␉/* Emit zero padding */␊ |
123 | ␉if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits) {␊ |
124 | ␉␉while (width > nchars) {␊ |
125 | ␉␉␉EMIT('0');␊ |
126 | ␉␉␉width--;␊ |
127 | ␉␉}␊ |
128 | ␉}␊ |
129 | ␊ |
130 | ␉/* Generate the number. This is done from right to left. */␊ |
131 | ␉q += ndigits;␉␉/* Advance the pointer to end of number */␊ |
132 | ␉o += ndigits;␊ |
133 | ␉qq = q;␊ |
134 | ␉oo = o;␉␉␉/* Temporary values */␊ |
135 | ␊ |
136 | ␉b4tick = tickskip;␊ |
137 | ␉while (ndigits > 0) {␊ |
138 | ␉␉if (!b4tick--) {␊ |
139 | ␉␉␉qq--;␊ |
140 | ␉␉␉oo--;␊ |
141 | ␉␉␉ndigits--;␊ |
142 | ␉␉␉if (oo < n)␊ |
143 | ␉␉␉␉*qq = '_';␊ |
144 | ␉␉␉b4tick = tickskip - 1;␊ |
145 | ␉␉}␊ |
146 | ␉␉qq--;␊ |
147 | ␉␉oo--;␊ |
148 | ␉␉ndigits--;␊ |
149 | ␉␉if (oo < n)␊ |
150 | ␉␉␉*qq = digits[val % base];␊ |
151 | ␉␉val /= base;␊ |
152 | ␉}␊ |
153 | ␊ |
154 | ␉/* Emit late space padding */␊ |
155 | ␉while ((flags & FL_MINUS) && width > nchars) {␊ |
156 | ␉␉EMIT(' ');␊ |
157 | ␉␉width--;␊ |
158 | ␉}␊ |
159 | ␊ |
160 | ␉return o;␊ |
161 | }␊ |
162 | ␊ |
163 | int vsnprintf(char *buffer, size_t n, const char *format, va_list ap)␊ |
164 | {␊ |
165 | ␉const char *p = format;␊ |
166 | ␉char ch;␊ |
167 | ␉char *q = buffer;␊ |
168 | ␉size_t o = 0;␉␉/* Number of characters output */␊ |
169 | ␉uintmax_t val = 0;␊ |
170 | ␉int rank = rank_int;␉/* Default rank */␊ |
171 | ␉int width = 0;␊ |
172 | ␉int prec = -1;␊ |
173 | ␉int base;␊ |
174 | ␉size_t sz;␊ |
175 | ␉enum flags flags = 0;␊ |
176 | ␉enum {␊ |
177 | ␉␉st_normal,␉/* Ground state */␊ |
178 | ␉␉st_flags,␉/* Special flags */␊ |
179 | ␉␉st_width,␉/* Field width */␊ |
180 | ␉␉st_prec,␉/* Field precision */␊ |
181 | ␉␉st_modifiers␉/* Length or conversion modifiers */␊ |
182 | ␉} state = st_normal;␊ |
183 | ␉const char *sarg;␉/* %s string argument */␊ |
184 | ␉char carg;␉␉/* %c char argument */␊ |
185 | ␉int slen;␉␉/* String length */␊ |
186 | ␊ |
187 | ␉while ((ch = *p++)) {␊ |
188 | ␉␉switch (state) {␊ |
189 | ␉␉case st_normal:␊ |
190 | ␉␉␉if (ch == '%') {␊ |
191 | ␉␉␉␉state = st_flags;␊ |
192 | ␉␉␉␉flags = 0;␊ |
193 | ␉␉␉␉rank = rank_int;␊ |
194 | ␉␉␉␉width = 0;␊ |
195 | ␉␉␉␉prec = -1;␊ |
196 | ␉␉␉} else {␊ |
197 | ␉␉␉␉EMIT(ch);␊ |
198 | ␉␉␉}␊ |
199 | ␉␉␉break;␊ |
200 | ␊ |
201 | ␉␉case st_flags:␊ |
202 | ␉␉␉switch (ch) {␊ |
203 | ␉␉␉case '-':␊ |
204 | ␉␉␉␉flags |= FL_MINUS;␊ |
205 | ␉␉␉␉break;␊ |
206 | ␉␉␉case '+':␊ |
207 | ␉␉␉␉flags |= FL_PLUS;␊ |
208 | ␉␉␉␉break;␊ |
209 | ␉␉␉case '\'':␊ |
210 | ␉␉␉␉flags |= FL_TICK;␊ |
211 | ␉␉␉␉break;␊ |
212 | ␉␉␉case ' ':␊ |
213 | ␉␉␉␉flags |= FL_SPACE;␊ |
214 | ␉␉␉␉break;␊ |
215 | ␉␉␉case '#':␊ |
216 | ␉␉␉␉flags |= FL_HASH;␊ |
217 | ␉␉␉␉break;␊ |
218 | ␉␉␉case '0':␊ |
219 | ␉␉␉␉flags |= FL_ZERO;␊ |
220 | ␉␉␉␉break;␊ |
221 | ␉␉␉default:␊ |
222 | ␉␉␉␉state = st_width;␊ |
223 | ␉␉␉␉p--;␉/* Process this character again */␊ |
224 | ␉␉␉␉break;␊ |
225 | ␉␉␉}␊ |
226 | ␉␉␉break;␊ |
227 | ␊ |
228 | ␉␉case st_width:␊ |
229 | ␉␉␉if (ch >= '0' && ch <= '9') {␊ |
230 | ␉␉␉␉width = width * 10 + (ch - '0');␊ |
231 | ␉␉␉} else if (ch == '*') {␊ |
232 | ␉␉␉␉width = va_arg(ap, int);␊ |
233 | ␉␉␉␉if (width < 0) {␊ |
234 | ␉␉␉␉␉width = -width;␊ |
235 | ␉␉␉␉␉flags |= FL_MINUS;␊ |
236 | ␉␉␉␉}␊ |
237 | ␉␉␉} else if (ch == '.') {␊ |
238 | ␉␉␉␉prec = 0;␉/* Precision given */␊ |
239 | ␉␉␉␉state = st_prec;␊ |
240 | ␉␉␉} else {␊ |
241 | ␉␉␉␉state = st_modifiers;␊ |
242 | ␉␉␉␉p--;␉/* Process this character again */␊ |
243 | ␉␉␉}␊ |
244 | ␉␉␉break;␊ |
245 | ␊ |
246 | ␉␉case st_prec:␊ |
247 | ␉␉␉if (ch >= '0' && ch <= '9') {␊ |
248 | ␉␉␉␉prec = prec * 10 + (ch - '0');␊ |
249 | ␉␉␉} else if (ch == '*') {␊ |
250 | ␉␉␉␉prec = va_arg(ap, int);␊ |
251 | ␉␉␉␉if (prec < 0)␊ |
252 | ␉␉␉␉␉prec = -1;␊ |
253 | ␉␉␉} else {␊ |
254 | ␉␉␉␉state = st_modifiers;␊ |
255 | ␉␉␉␉p--;␉/* Process this character again */␊ |
256 | ␉␉␉}␊ |
257 | ␉␉␉break;␊ |
258 | ␊ |
259 | ␉␉case st_modifiers:␊ |
260 | ␉␉␉switch (ch) {␊ |
261 | ␉␉␉␉/* Length modifiers - nonterminal sequences */␊ |
262 | ␉␉␉case 'h':␊ |
263 | ␉␉␉␉rank--;␉/* Shorter rank */␊ |
264 | ␉␉␉␉break;␊ |
265 | ␉␉␉case 'l':␊ |
266 | ␉␉␉␉rank++;␉/* Longer rank */␊ |
267 | ␉␉␉␉break;␊ |
268 | ␉␉␉case 'j':␊ |
269 | ␉␉␉␉rank = INTMAX_RANK;␊ |
270 | ␉␉␉␉break;␊ |
271 | ␉␉␉case 'z':␊ |
272 | ␉␉␉␉rank = SIZE_T_RANK;␊ |
273 | ␉␉␉␉break;␊ |
274 | ␉␉␉case 't':␊ |
275 | ␉␉␉␉rank = PTRDIFF_T_RANK;␊ |
276 | ␉␉␉␉break;␊ |
277 | ␉␉␉case 'L':␊ |
278 | ␉␉␉case 'q':␊ |
279 | ␉␉␉␉rank += 2;␊ |
280 | ␉␉␉␉break;␊ |
281 | ␉␉␉default:␊ |
282 | ␉␉␉␉/* Output modifiers - terminal sequences */␊ |
283 | ␊ |
284 | ␉␉␉␉/* Next state will be normal */␊ |
285 | ␉␉␉␉state = st_normal;␊ |
286 | ␊ |
287 | ␉␉␉␉/* Canonicalize rank */␊ |
288 | ␉␉␉␉if (rank < MIN_RANK)␊ |
289 | ␉␉␉␉␉rank = MIN_RANK;␊ |
290 | ␉␉␉␉else if (rank > MAX_RANK)␊ |
291 | ␉␉␉␉␉rank = MAX_RANK;␊ |
292 | ␊ |
293 | ␉␉␉␉switch (ch) {␊ |
294 | ␉␉␉␉case 'P':␉/* Upper case pointer */␊ |
295 | ␉␉␉␉␉flags |= FL_UPPER;␊ |
296 | ␉␉␉␉␉/* fall through */␊ |
297 | ␉␉␉␉case 'p':␉/* Pointer */␊ |
298 | ␉␉␉␉␉base = 16;␊ |
299 | ␉␉␉␉␉prec = (CHAR_BIT*sizeof(void *)+3)/4;␊ |
300 | ␉␉␉␉␉flags |= FL_HASH;␊ |
301 | ␉␉␉␉␉val = (uintmax_t)(uintptr_t)␊ |
302 | ␉␉␉␉␉␉va_arg(ap, void *);␊ |
303 | ␉␉␉␉␉goto is_integer;␊ |
304 | ␊ |
305 | ␉␉␉␉case 'd':␉/* Signed decimal output */␊ |
306 | ␉␉␉␉case 'i':␊ |
307 | ␉␉␉␉␉base = 10;␊ |
308 | ␉␉␉␉␉flags |= FL_SIGNED;␊ |
309 | ␉␉␉␉␉switch (rank) {␊ |
310 | ␉␉␉␉␉case rank_char:␊ |
311 | ␉␉␉␉␉␉/* Yes, all these casts are␊ |
312 | ␉␉␉␉␉␉ needed... */␊ |
313 | ␉␉␉␉␉␉val = (uintmax_t)(intmax_t)␊ |
314 | ␉␉␉␉␉␉␉(signed char)␊ |
315 | ␉␉␉␉␉␉␉va_arg(ap, signed int);␊ |
316 | ␉␉␉␉␉␉break;␊ |
317 | ␉␉␉␉␉case rank_short:␊ |
318 | ␉␉␉␉␉␉val = (uintmax_t)(intmax_t)␊ |
319 | ␉␉␉␉␉␉␉(signed short)␊ |
320 | ␉␉␉␉␉␉␉va_arg(ap, signed int);␊ |
321 | ␉␉␉␉␉␉break;␊ |
322 | ␉␉␉␉␉case rank_int:␊ |
323 | ␉␉␉␉␉␉val = (uintmax_t)(intmax_t)␊ |
324 | ␉␉␉␉␉␉ va_arg(ap, signed int);␊ |
325 | ␉␉␉␉␉␉break;␊ |
326 | ␉␉␉␉␉case rank_long:␊ |
327 | ␉␉␉␉␉␉val = (uintmax_t)(intmax_t)␊ |
328 | ␉␉␉␉␉␉ va_arg(ap, signed long);␊ |
329 | ␉␉␉␉␉␉break;␊ |
330 | ␉␉␉␉␉case rank_longlong:␊ |
331 | ␉␉␉␉␉␉val = (uintmax_t)(intmax_t)␊ |
332 | ␉␉␉␉␉␉ va_arg(ap,␊ |
333 | ␉␉␉␉␉␉␉ signed long long);␊ |
334 | ␉␉␉␉␉␉break;␊ |
335 | ␉␉␉␉␉}␊ |
336 | ␉␉␉␉␉goto is_integer;␊ |
337 | ␉␉␉␉case 'o':␉/* Octal */␊ |
338 | ␉␉␉␉␉base = 8;␊ |
339 | ␉␉␉␉␉goto is_unsigned;␊ |
340 | ␉␉␉␉case 'u':␉/* Unsigned decimal */␊ |
341 | ␉␉␉␉␉base = 10;␊ |
342 | ␉␉␉␉␉goto is_unsigned;␊ |
343 | ␉␉␉␉case 'X':␉/* Upper case hexadecimal */␊ |
344 | ␉␉␉␉␉flags |= FL_UPPER;␊ |
345 | ␉␉␉␉␉/* fall through */␊ |
346 | ␉␉␉␉case 'x':␉/* Hexadecimal */␊ |
347 | ␉␉␉␉␉base = 16;␊ |
348 | ␉␉␉␉␉goto is_unsigned;␊ |
349 | ␊ |
350 | ␉␉␉␉is_unsigned:␊ |
351 | ␉␉␉␉␉switch (rank) {␊ |
352 | ␉␉␉␉␉case rank_char:␊ |
353 | ␉␉␉␉␉␉val = (uintmax_t)␊ |
354 | ␉␉␉␉␉␉␉(unsigned char)␊ |
355 | ␉␉␉␉␉␉␉va_arg(ap, unsigned␊ |
356 | ␉␉␉␉␉␉␉ int);␊ |
357 | ␉␉␉␉␉␉break;␊ |
358 | ␉␉␉␉␉case rank_short:␊ |
359 | ␉␉␉␉␉␉val = (uintmax_t)␊ |
360 | ␉␉␉␉␉␉␉(unsigned short)␊ |
361 | ␉␉␉␉␉␉␉va_arg(ap, unsigned␊ |
362 | ␉␉␉␉␉␉␉ int);␊ |
363 | ␉␉␉␉␉␉break;␊ |
364 | ␉␉␉␉␉case rank_int:␊ |
365 | ␉␉␉␉␉␉val = (uintmax_t)␊ |
366 | ␉␉␉␉␉␉␉va_arg(ap, unsigned␊ |
367 | ␉␉␉␉␉␉␉ int);␊ |
368 | ␉␉␉␉␉␉break;␊ |
369 | ␉␉␉␉␉case rank_long:␊ |
370 | ␉␉␉␉␉␉val = (uintmax_t)␊ |
371 | ␉␉␉␉␉␉␉va_arg(ap, unsigned␊ |
372 | ␉␉␉␉␉␉␉ long);␊ |
373 | ␉␉␉␉␉␉break;␊ |
374 | ␉␉␉␉␉case rank_longlong:␊ |
375 | ␉␉␉␉␉␉val = (uintmax_t)␊ |
376 | ␉␉␉␉␉␉␉va_arg(ap, unsigned␊ |
377 | ␉␉␉␉␉␉␉ long long);␊ |
378 | ␉␉␉␉␉␉break;␊ |
379 | ␉␉␉␉␉}␊ |
380 | ␉␉␉␉␉/* fall through */␊ |
381 | ␊ |
382 | ␉␉␉␉is_integer:␊ |
383 | ␉␉␉␉␉sz = format_int(q, (o < n) ? n - o : 0,␊ |
384 | ␉␉␉␉␉␉␉val, flags, base,␊ |
385 | ␉␉␉␉␉␉␉width, prec);␊ |
386 | ␉␉␉␉␉q += sz;␊ |
387 | ␉␉␉␉␉o += sz;␊ |
388 | ␉␉␉␉␉break;␊ |
389 | ␊ |
390 | ␉␉␉␉case 'c':␉/* Character */␊ |
391 | ␉␉␉␉␉carg = (char)va_arg(ap, int);␊ |
392 | ␉␉␉␉␉sarg = &carg;␊ |
393 | ␉␉␉␉␉slen = 1;␊ |
394 | ␉␉␉␉␉goto is_string;␊ |
395 | ␉␉␉␉case 's':␉/* String */␊ |
396 | ␉␉␉␉␉sarg = va_arg(ap, const char *);␊ |
397 | ␉␉␉␉␉sarg = sarg ? sarg : "(null)";␊ |
398 | ␉␉␉␉␉slen = strlen(sarg);␊ |
399 | ␉␉␉␉␉goto is_string;␊ |
400 | ␊ |
401 | ␉␉␉␉is_string:␊ |
402 | ␉␉␉␉␉{␊ |
403 | ␉␉␉␉␉␉char sch;␊ |
404 | ␉␉␉␉␉␉int i;␊ |
405 | ␊ |
406 | ␉␉␉␉␉␉if (prec != -1 && slen > prec)␊ |
407 | ␉␉␉␉␉␉␉slen = prec;␊ |
408 | ␊ |
409 | ␉␉␉␉␉␉if (width > slen␊ |
410 | ␉␉␉␉␉␉ && !(flags & FL_MINUS)) {␊ |
411 | ␉␉␉␉␉␉␉char pad =␊ |
412 | ␉␉␉␉␉␉␉ (flags & FL_ZERO) ?␊ |
413 | ␉␉␉␉␉␉␉ '0' : ' ';␊ |
414 | ␉␉␉␉␉␉␉while (width > slen) {␊ |
415 | ␉␉␉␉␉␉␉␉EMIT(pad);␊ |
416 | ␉␉␉␉␉␉␉␉width--;␊ |
417 | ␉␉␉␉␉␉␉}␊ |
418 | ␉␉␉␉␉␉}␊ |
419 | ␉␉␉␉␉␉for (i = slen; i; i--) {␊ |
420 | ␉␉␉␉␉␉␉sch = *sarg++;␊ |
421 | ␉␉␉␉␉␉␉EMIT(sch);␊ |
422 | ␉␉␉␉␉␉}␊ |
423 | ␉␉␉␉␉␉if (width > slen␊ |
424 | ␉␉␉␉␉␉ && (flags & FL_MINUS)) {␊ |
425 | ␉␉␉␉␉␉␉while (width > slen) {␊ |
426 | ␉␉␉␉␉␉␉␉EMIT(' ');␊ |
427 | ␉␉␉␉␉␉␉␉width--;␊ |
428 | ␉␉␉␉␉␉␉}␊ |
429 | ␉␉␉␉␉␉}␊ |
430 | ␉␉␉␉␉}␊ |
431 | ␉␉␉␉␉break;␊ |
432 | ␊ |
433 | ␉␉␉␉case 'n':␊ |
434 | ␉␉␉␉␉{␊ |
435 | ␉␉␉␉␉␉/* Output the number of␊ |
436 | ␉␉␉␉␉␉ characters written */␊ |
437 | ␊ |
438 | ␉␉␉␉␉␉switch (rank) {␊ |
439 | ␉␉␉␉␉␉case rank_char:␊ |
440 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
441 | ␉␉␉␉␉␉␉␉signed char *)␊ |
442 | ␉␉␉␉␉␉␉␉= o;␊ |
443 | ␉␉␉␉␉␉␉break;␊ |
444 | ␉␉␉␉␉␉case rank_short:␊ |
445 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
446 | ␉␉␉␉␉␉␉␉signed short *)␊ |
447 | ␉␉␉␉␉␉␉␉= o;␊ |
448 | ␉␉␉␉␉␉␉break;␊ |
449 | ␉␉␉␉␉␉case rank_int:␊ |
450 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
451 | ␉␉␉␉␉␉␉␉signed int *)␊ |
452 | ␉␉␉␉␉␉␉␉= o;␊ |
453 | ␉␉␉␉␉␉␉break;␊ |
454 | ␉␉␉␉␉␉case rank_long:␊ |
455 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
456 | ␉␉␉␉␉␉␉␉signed long *)␊ |
457 | ␉␉␉␉␉␉␉␉= o;␊ |
458 | ␉␉␉␉␉␉␉break;␊ |
459 | ␉␉␉␉␉␉case rank_longlong:␊ |
460 | ␉␉␉␉␉␉␉*va_arg(ap,␊ |
461 | ␉␉␉␉␉␉␉␉signed long long *)␊ |
462 | ␉␉␉␉␉␉␉␉= o;␊ |
463 | ␉␉␉␉␉␉␉break;␊ |
464 | ␉␉␉␉␉␉}␊ |
465 | ␉␉␉␉␉}␊ |
466 | ␉␉␉␉␉break;␊ |
467 | ␊ |
468 | ␉␉␉␉default:␉/* Anything else, including % */␊ |
469 | ␉␉␉␉␉EMIT(ch);␊ |
470 | ␉␉␉␉␉break;␊ |
471 | ␉␉␉␉}␊ |
472 | ␉␉␉}␊ |
473 | ␉␉}␊ |
474 | ␉}␊ |
475 | ␊ |
476 | ␉/* Null-terminate the string */␊ |
477 | ␉if (o < n)␊ |
478 | ␉␉*q = '\0';␉/* No overflow */␊ |
479 | ␉else if (n > 0)␊ |
480 | ␉␉buffer[n - 1] = '\0';␉/* Overflow - terminate at end of buffer */␊ |
481 | ␊ |
482 | ␉return o;␊ |
483 | }␊ |
484 |