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