/src/plan9port/src/lib9/fmt/dofmt.c
Line | Count | Source |
1 | | /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ |
2 | | /* Copyright (c) 2004 Google Inc.; see LICENSE */ |
3 | | |
4 | | #include <stdarg.h> |
5 | | #include <string.h> |
6 | | #include "plan9.h" |
7 | | #include "fmt.h" |
8 | | #include "fmtdef.h" |
9 | | |
10 | | /* format the output into f->to and return the number of characters fmted */ |
11 | | int |
12 | | dofmt(Fmt *f, char *fmt) |
13 | 39.2k | { |
14 | 39.2k | Rune rune, *rt, *rs; |
15 | 39.2k | int r; |
16 | 39.2k | char *t, *s; |
17 | 39.2k | int n, nfmt; |
18 | | |
19 | 39.2k | nfmt = f->nfmt; |
20 | 63.4k | for(;;){ |
21 | 63.4k | if(f->runes){ |
22 | 0 | rt = (Rune*)f->to; |
23 | 0 | rs = (Rune*)f->stop; |
24 | 0 | while((r = *(uchar*)fmt) && r != '%'){ |
25 | 0 | if(r < Runeself) |
26 | 0 | fmt++; |
27 | 0 | else{ |
28 | 0 | fmt += chartorune(&rune, fmt); |
29 | 0 | r = rune; |
30 | 0 | } |
31 | 0 | FMTRCHAR(f, rt, rs, r); |
32 | 0 | } |
33 | 0 | fmt++; |
34 | 0 | f->nfmt += rt - (Rune *)f->to; |
35 | 0 | f->to = rt; |
36 | 0 | if(!r) |
37 | 0 | return f->nfmt - nfmt; |
38 | 0 | f->stop = rs; |
39 | 63.4k | }else{ |
40 | 63.4k | t = (char*)f->to; |
41 | 63.4k | s = (char*)f->stop; |
42 | 194k | while((r = *(uchar*)fmt) && r != '%'){ |
43 | 131k | if(r < Runeself){ |
44 | 131k | FMTCHAR(f, t, s, r); |
45 | 131k | fmt++; |
46 | 131k | }else{ |
47 | 0 | n = chartorune(&rune, fmt); |
48 | 0 | if(t + n > s){ |
49 | 0 | t = (char*)__fmtflush(f, t, n); |
50 | 0 | if(t != nil) |
51 | 0 | s = (char*)f->stop; |
52 | 0 | else |
53 | 0 | return -1; |
54 | 0 | } |
55 | 0 | while(n--) |
56 | 0 | *t++ = *fmt++; |
57 | 0 | } |
58 | 131k | } |
59 | 63.4k | fmt++; |
60 | 63.4k | f->nfmt += t - (char *)f->to; |
61 | 63.4k | f->to = t; |
62 | 63.4k | if(!r) |
63 | 39.2k | return f->nfmt - nfmt; |
64 | 24.1k | f->stop = s; |
65 | 24.1k | } |
66 | | |
67 | 24.1k | fmt = (char*)__fmtdispatch(f, fmt, 0); |
68 | 24.1k | if(fmt == nil) |
69 | 0 | return -1; |
70 | 24.1k | } |
71 | 39.2k | } |
72 | | |
73 | | void * |
74 | | __fmtflush(Fmt *f, void *t, int len) |
75 | 5.82k | { |
76 | 5.82k | if(f->runes) |
77 | 0 | f->nfmt += (Rune*)t - (Rune*)f->to; |
78 | 5.82k | else |
79 | 5.82k | f->nfmt += (char*)t - (char *)f->to; |
80 | 5.82k | f->to = t; |
81 | 5.82k | if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){ |
82 | 0 | f->stop = f->to; |
83 | 0 | return nil; |
84 | 0 | } |
85 | 5.82k | return f->to; |
86 | 5.82k | } |
87 | | |
88 | | /* |
89 | | * put a formatted block of memory sz bytes long of n runes into the output buffer, |
90 | | * left/right justified in a field of at least f->width characters (if FmtWidth is set) |
91 | | */ |
92 | | int |
93 | | __fmtpad(Fmt *f, int n) |
94 | 24.1k | { |
95 | 24.1k | char *t, *s; |
96 | 24.1k | int i; |
97 | | |
98 | 24.1k | t = (char*)f->to; |
99 | 24.1k | s = (char*)f->stop; |
100 | 24.1k | for(i = 0; i < n; i++) |
101 | 0 | FMTCHAR(f, t, s, ' '); |
102 | 24.1k | f->nfmt += t - (char *)f->to; |
103 | 24.1k | f->to = t; |
104 | 24.1k | return 0; |
105 | 24.1k | } |
106 | | |
107 | | int |
108 | | __rfmtpad(Fmt *f, int n) |
109 | 0 | { |
110 | 0 | Rune *t, *s; |
111 | 0 | int i; |
112 | |
|
113 | 0 | t = (Rune*)f->to; |
114 | 0 | s = (Rune*)f->stop; |
115 | 0 | for(i = 0; i < n; i++) |
116 | 0 | FMTRCHAR(f, t, s, ' '); |
117 | 0 | f->nfmt += t - (Rune *)f->to; |
118 | 0 | f->to = t; |
119 | 0 | return 0; |
120 | 0 | } |
121 | | |
122 | | int |
123 | | __fmtcpy(Fmt *f, const void *vm, int n, int sz) |
124 | 24.1k | { |
125 | 24.1k | Rune *rt, *rs, r; |
126 | 24.1k | char *t, *s, *m, *me; |
127 | 24.1k | ulong fl; |
128 | 24.1k | int nc, w; |
129 | | |
130 | 24.1k | m = (char*)vm; |
131 | 24.1k | me = m + sz; |
132 | 24.1k | fl = f->flags; |
133 | 24.1k | w = 0; |
134 | 24.1k | if(fl & FmtWidth) |
135 | 2.41k | w = f->width; |
136 | 24.1k | if((fl & FmtPrec) && n > f->prec) |
137 | 0 | n = f->prec; |
138 | 24.1k | if(f->runes){ |
139 | 0 | if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) |
140 | 0 | return -1; |
141 | 0 | rt = (Rune*)f->to; |
142 | 0 | rs = (Rune*)f->stop; |
143 | 0 | for(nc = n; nc > 0; nc--){ |
144 | 0 | r = *(uchar*)m; |
145 | 0 | if(r < Runeself) |
146 | 0 | m++; |
147 | 0 | else if((me - m) >= UTFmax || fullrune(m, me-m)) |
148 | 0 | m += chartorune(&r, m); |
149 | 0 | else |
150 | 0 | break; |
151 | 0 | FMTRCHAR(f, rt, rs, r); |
152 | 0 | } |
153 | 0 | f->nfmt += rt - (Rune *)f->to; |
154 | 0 | f->to = rt; |
155 | 0 | if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) |
156 | 0 | return -1; |
157 | 24.1k | }else{ |
158 | 24.1k | if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) |
159 | 0 | return -1; |
160 | 24.1k | t = (char*)f->to; |
161 | 24.1k | s = (char*)f->stop; |
162 | 843k | for(nc = n; nc > 0; nc--){ |
163 | 819k | r = *(uchar*)m; |
164 | 819k | if(r < Runeself) |
165 | 410k | m++; |
166 | 409k | else if((me - m) >= UTFmax || fullrune(m, me-m)) |
167 | 409k | m += chartorune(&r, m); |
168 | 317 | else |
169 | 317 | break; |
170 | 819k | FMTRUNE(f, t, s, r); |
171 | 819k | } |
172 | 24.1k | f->nfmt += t - (char *)f->to; |
173 | 24.1k | f->to = t; |
174 | 24.1k | if(fl & FmtLeft && __fmtpad(f, w - n) < 0) |
175 | 0 | return -1; |
176 | 24.1k | } |
177 | 24.1k | return 0; |
178 | 24.1k | } |
179 | | |
180 | | int |
181 | | __fmtrcpy(Fmt *f, const void *vm, int n) |
182 | 0 | { |
183 | 0 | Rune r, *m, *me, *rt, *rs; |
184 | 0 | char *t, *s; |
185 | 0 | ulong fl; |
186 | 0 | int w; |
187 | |
|
188 | 0 | m = (Rune*)vm; |
189 | 0 | fl = f->flags; |
190 | 0 | w = 0; |
191 | 0 | if(fl & FmtWidth) |
192 | 0 | w = f->width; |
193 | 0 | if((fl & FmtPrec) && n > f->prec) |
194 | 0 | n = f->prec; |
195 | 0 | if(f->runes){ |
196 | 0 | if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) |
197 | 0 | return -1; |
198 | 0 | rt = (Rune*)f->to; |
199 | 0 | rs = (Rune*)f->stop; |
200 | 0 | for(me = m + n; m < me; m++) |
201 | 0 | FMTRCHAR(f, rt, rs, *m); |
202 | 0 | f->nfmt += rt - (Rune *)f->to; |
203 | 0 | f->to = rt; |
204 | 0 | if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) |
205 | 0 | return -1; |
206 | 0 | }else{ |
207 | 0 | if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) |
208 | 0 | return -1; |
209 | 0 | t = (char*)f->to; |
210 | 0 | s = (char*)f->stop; |
211 | 0 | for(me = m + n; m < me; m++){ |
212 | 0 | r = *m; |
213 | 0 | FMTRUNE(f, t, s, r); |
214 | 0 | } |
215 | 0 | f->nfmt += t - (char *)f->to; |
216 | 0 | f->to = t; |
217 | 0 | if(fl & FmtLeft && __fmtpad(f, w - n) < 0) |
218 | 0 | return -1; |
219 | 0 | } |
220 | 0 | return 0; |
221 | 0 | } |
222 | | |
223 | | /* fmt out one character */ |
224 | | int |
225 | | __charfmt(Fmt *f) |
226 | 0 | { |
227 | 0 | char x[1]; |
228 | |
|
229 | 0 | x[0] = va_arg(f->args, int); |
230 | 0 | f->prec = 1; |
231 | 0 | return __fmtcpy(f, (const char*)x, 1, 1); |
232 | 0 | } |
233 | | |
234 | | /* fmt out one rune */ |
235 | | int |
236 | | __runefmt(Fmt *f) |
237 | 0 | { |
238 | 0 | Rune x[1]; |
239 | |
|
240 | 0 | x[0] = va_arg(f->args, int); |
241 | 0 | return __fmtrcpy(f, (const void*)x, 1); |
242 | 0 | } |
243 | | |
244 | | /* public helper routine: fmt out a null terminated string already in hand */ |
245 | | int |
246 | | fmtstrcpy(Fmt *f, char *s) |
247 | 12.1k | { |
248 | 12.1k | int i, j; |
249 | | |
250 | 12.1k | if(!s) |
251 | 0 | return __fmtcpy(f, "<nil>", 5, 5); |
252 | | /* if precision is specified, make sure we don't wander off the end */ |
253 | 12.1k | if(f->flags & FmtPrec){ |
254 | 0 | #ifdef PLAN9PORT |
255 | 0 | Rune r; |
256 | 0 | i = 0; |
257 | 0 | for(j=0; j<f->prec && s[i]; j++) |
258 | 0 | i += chartorune(&r, s+i); |
259 | | #else |
260 | | /* ANSI requires precision in bytes, not Runes */ |
261 | | for(i=0; i<f->prec; i++) |
262 | | if(s[i] == 0) |
263 | | break; |
264 | | j = utfnlen(s, i); /* won't print partial at end */ |
265 | | #endif |
266 | 0 | return __fmtcpy(f, s, j, i); |
267 | 0 | } |
268 | 12.1k | return __fmtcpy(f, s, utflen(s), strlen(s)); |
269 | 12.1k | } |
270 | | |
271 | | /* fmt out a null terminated utf string */ |
272 | | int |
273 | | __strfmt(Fmt *f) |
274 | 12.1k | { |
275 | 12.1k | char *s; |
276 | | |
277 | 12.1k | s = va_arg(f->args, char *); |
278 | 12.1k | return fmtstrcpy(f, s); |
279 | 12.1k | } |
280 | | |
281 | | /* public helper routine: fmt out a null terminated rune string already in hand */ |
282 | | int |
283 | | fmtrunestrcpy(Fmt *f, Rune *s) |
284 | 0 | { |
285 | 0 | Rune *e; |
286 | 0 | int n, p; |
287 | |
|
288 | 0 | if(!s) |
289 | 0 | return __fmtcpy(f, "<nil>", 5, 5); |
290 | | /* if precision is specified, make sure we don't wander off the end */ |
291 | 0 | if(f->flags & FmtPrec){ |
292 | 0 | p = f->prec; |
293 | 0 | for(n = 0; n < p; n++) |
294 | 0 | if(s[n] == 0) |
295 | 0 | break; |
296 | 0 | }else{ |
297 | 0 | for(e = s; *e; e++) |
298 | 0 | ; |
299 | 0 | n = e - s; |
300 | 0 | } |
301 | 0 | return __fmtrcpy(f, s, n); |
302 | 0 | } |
303 | | |
304 | | /* fmt out a null terminated rune string */ |
305 | | int |
306 | | __runesfmt(Fmt *f) |
307 | 0 | { |
308 | 0 | Rune *s; |
309 | |
|
310 | 0 | s = va_arg(f->args, Rune *); |
311 | 0 | return fmtrunestrcpy(f, s); |
312 | 0 | } |
313 | | |
314 | | /* fmt a % */ |
315 | | int |
316 | | __percentfmt(Fmt *f) |
317 | 0 | { |
318 | 0 | Rune x[1]; |
319 | |
|
320 | 0 | x[0] = f->r; |
321 | 0 | f->prec = 1; |
322 | 0 | return __fmtrcpy(f, (const void*)x, 1); |
323 | 0 | } |
324 | | |
325 | | /* fmt an integer */ |
326 | | int |
327 | | __ifmt(Fmt *f) |
328 | 11.9k | { |
329 | 11.9k | char buf[140], *p, *conv; |
330 | | /* 140: for 64 bits of binary + 3-byte sep every 4 digits */ |
331 | 11.9k | uvlong vu; |
332 | 11.9k | ulong u; |
333 | 11.9k | int neg, base, i, n, fl, w, isv; |
334 | 11.9k | int ndig, len, excess, bytelen; |
335 | 11.9k | char *grouping; |
336 | 11.9k | char *thousands; |
337 | | |
338 | 11.9k | neg = 0; |
339 | 11.9k | fl = f->flags; |
340 | 11.9k | isv = 0; |
341 | 11.9k | vu = 0; |
342 | 11.9k | u = 0; |
343 | | #ifndef PLAN9PORT |
344 | | /* |
345 | | * Unsigned verbs for ANSI C |
346 | | */ |
347 | | switch(f->r){ |
348 | | case 'o': |
349 | | case 'p': |
350 | | case 'u': |
351 | | case 'x': |
352 | | case 'X': |
353 | | fl |= FmtUnsigned; |
354 | | fl &= ~(FmtSign|FmtSpace); |
355 | | break; |
356 | | } |
357 | | #endif |
358 | 11.9k | if(f->r == 'p'){ |
359 | 0 | u = (ulong)va_arg(f->args, void*); |
360 | 0 | f->r = 'x'; |
361 | 0 | fl |= FmtUnsigned; |
362 | 11.9k | }else if(fl & FmtVLong){ |
363 | 0 | isv = 1; |
364 | 0 | if(fl & FmtUnsigned) |
365 | 0 | vu = va_arg(f->args, uvlong); |
366 | 0 | else |
367 | 0 | vu = va_arg(f->args, vlong); |
368 | 11.9k | }else if(fl & FmtLong){ |
369 | 0 | if(fl & FmtUnsigned) |
370 | 0 | u = va_arg(f->args, ulong); |
371 | 0 | else |
372 | 0 | u = va_arg(f->args, long); |
373 | 11.9k | }else if(fl & FmtByte){ |
374 | 0 | if(fl & FmtUnsigned) |
375 | 0 | u = (uchar)va_arg(f->args, int); |
376 | 0 | else |
377 | 0 | u = (char)va_arg(f->args, int); |
378 | 11.9k | }else if(fl & FmtShort){ |
379 | 0 | if(fl & FmtUnsigned) |
380 | 0 | u = (ushort)va_arg(f->args, int); |
381 | 0 | else |
382 | 0 | u = (short)va_arg(f->args, int); |
383 | 11.9k | }else{ |
384 | 11.9k | if(fl & FmtUnsigned) |
385 | 0 | u = va_arg(f->args, uint); |
386 | 11.9k | else |
387 | 11.9k | u = va_arg(f->args, int); |
388 | 11.9k | } |
389 | 11.9k | conv = "0123456789abcdef"; |
390 | 11.9k | grouping = "\4"; /* for hex, octal etc. (undefined by spec but nice) */ |
391 | 11.9k | thousands = f->thousands; |
392 | 11.9k | switch(f->r){ |
393 | 9.57k | case 'd': |
394 | 9.57k | case 'i': |
395 | 9.57k | case 'u': |
396 | 9.57k | base = 10; |
397 | 9.57k | grouping = f->grouping; |
398 | 9.57k | break; |
399 | 0 | case 'X': |
400 | 0 | conv = "0123456789ABCDEF"; |
401 | | /* fall through */ |
402 | 2.41k | case 'x': |
403 | 2.41k | base = 16; |
404 | 2.41k | thousands = ":"; |
405 | 2.41k | break; |
406 | 0 | case 'b': |
407 | 0 | base = 2; |
408 | 0 | thousands = ":"; |
409 | 0 | break; |
410 | 0 | case 'o': |
411 | 0 | base = 8; |
412 | 0 | break; |
413 | 0 | default: |
414 | 0 | return -1; |
415 | 11.9k | } |
416 | 11.9k | if(!(fl & FmtUnsigned)){ |
417 | 11.9k | if(isv && (vlong)vu < 0){ |
418 | 0 | vu = -(vlong)vu; |
419 | 0 | neg = 1; |
420 | 11.9k | }else if(!isv && (long)u < 0){ |
421 | 145 | u = -(long)u; |
422 | 145 | neg = 1; |
423 | 145 | } |
424 | 11.9k | } |
425 | 11.9k | p = buf + sizeof buf - 1; |
426 | 11.9k | n = 0; /* in runes */ |
427 | 11.9k | excess = 0; /* number of bytes > number runes */ |
428 | 11.9k | ndig = 0; |
429 | 11.9k | len = utflen(thousands); |
430 | 11.9k | bytelen = strlen(thousands); |
431 | 11.9k | if(isv){ |
432 | 0 | while(vu){ |
433 | 0 | i = vu % base; |
434 | 0 | vu /= base; |
435 | 0 | if((fl & FmtComma) && n % 4 == 3){ |
436 | 0 | *p-- = ','; |
437 | 0 | n++; |
438 | 0 | } |
439 | 0 | if((fl & FmtApost) && __needsep(&ndig, &grouping)){ |
440 | 0 | n += len; |
441 | 0 | excess += bytelen - len; |
442 | 0 | p -= bytelen; |
443 | 0 | memmove(p+1, thousands, bytelen); |
444 | 0 | } |
445 | 0 | *p-- = conv[i]; |
446 | 0 | n++; |
447 | 0 | } |
448 | 11.9k | }else{ |
449 | 31.3k | while(u){ |
450 | 19.3k | i = u % base; |
451 | 19.3k | u /= base; |
452 | 19.3k | if((fl & FmtComma) && n % 4 == 3){ |
453 | 0 | *p-- = ','; |
454 | 0 | n++; |
455 | 0 | } |
456 | 19.3k | if((fl & FmtApost) && __needsep(&ndig, &grouping)){ |
457 | 0 | n += len; |
458 | 0 | excess += bytelen - len; |
459 | 0 | p -= bytelen; |
460 | 0 | memmove(p+1, thousands, bytelen); |
461 | 0 | } |
462 | 19.3k | *p-- = conv[i]; |
463 | 19.3k | n++; |
464 | 19.3k | } |
465 | 11.9k | } |
466 | 11.9k | if(n == 0){ |
467 | | /* |
468 | | * "The result of converting a zero value with |
469 | | * a precision of zero is no characters." - ANSI |
470 | | * |
471 | | * "For o conversion, # increases the precision, if and only if |
472 | | * necessary, to force the first digit of the result to be a zero |
473 | | * (if the value and precision are both 0, a single 0 is printed)." - ANSI |
474 | | */ |
475 | 1.13k | if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){ |
476 | 1.13k | *p-- = '0'; |
477 | 1.13k | n = 1; |
478 | 1.13k | if(fl & FmtApost) |
479 | 0 | __needsep(&ndig, &grouping); |
480 | 1.13k | } |
481 | | |
482 | | /* |
483 | | * Zero values don't get 0x. |
484 | | */ |
485 | 1.13k | if(f->r == 'x' || f->r == 'X') |
486 | 118 | fl &= ~FmtSharp; |
487 | 1.13k | } |
488 | 12.7k | for(w = f->prec; n < w && p > buf+3; n++){ |
489 | 793 | if((fl & FmtApost) && __needsep(&ndig, &grouping)){ |
490 | 0 | n += len; |
491 | 0 | excess += bytelen - len; |
492 | 0 | p -= bytelen; |
493 | 0 | memmove(p+1, thousands, bytelen); |
494 | 0 | } |
495 | 793 | *p-- = '0'; |
496 | 793 | } |
497 | 11.9k | if(neg || (fl & (FmtSign|FmtSpace))) |
498 | 145 | n++; |
499 | 11.9k | if(fl & FmtSharp){ |
500 | 0 | if(base == 16) |
501 | 0 | n += 2; |
502 | 0 | else if(base == 8){ |
503 | 0 | if(p[1] == '0') |
504 | 0 | fl &= ~FmtSharp; |
505 | 0 | else |
506 | 0 | n++; |
507 | 0 | } |
508 | 0 | } |
509 | 11.9k | if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){ |
510 | 0 | w = 0; |
511 | 0 | if(fl & FmtWidth) |
512 | 0 | w = f->width; |
513 | 0 | for(; n < w && p > buf+3; n++){ |
514 | 0 | if((fl & FmtApost) && __needsep(&ndig, &grouping)){ |
515 | 0 | n += len; |
516 | 0 | excess += bytelen - len; |
517 | 0 | p -= bytelen; |
518 | 0 | memmove(p+1, thousands, bytelen); |
519 | 0 | } |
520 | 0 | *p-- = '0'; |
521 | 0 | } |
522 | 0 | f->flags &= ~FmtWidth; |
523 | 0 | } |
524 | 11.9k | if(fl & FmtSharp){ |
525 | 0 | if(base == 16) |
526 | 0 | *p-- = f->r; |
527 | 0 | if(base == 16 || base == 8) |
528 | 0 | *p-- = '0'; |
529 | 0 | } |
530 | 11.9k | if(neg) |
531 | 145 | *p-- = '-'; |
532 | 11.8k | else if(fl & FmtSign) |
533 | 0 | *p-- = '+'; |
534 | 11.8k | else if(fl & FmtSpace) |
535 | 0 | *p-- = ' '; |
536 | 11.9k | f->flags &= ~FmtPrec; |
537 | 11.9k | return __fmtcpy(f, p + 1, n, n + excess); |
538 | 11.9k | } |
539 | | |
540 | | int |
541 | | __countfmt(Fmt *f) |
542 | 0 | { |
543 | 0 | void *p; |
544 | 0 | ulong fl; |
545 | |
|
546 | 0 | fl = f->flags; |
547 | 0 | p = va_arg(f->args, void*); |
548 | 0 | if(fl & FmtVLong){ |
549 | 0 | *(vlong*)p = f->nfmt; |
550 | 0 | }else if(fl & FmtLong){ |
551 | 0 | *(long*)p = f->nfmt; |
552 | 0 | }else if(fl & FmtByte){ |
553 | 0 | *(char*)p = f->nfmt; |
554 | 0 | }else if(fl & FmtShort){ |
555 | 0 | *(short*)p = f->nfmt; |
556 | 0 | }else{ |
557 | 0 | *(int*)p = f->nfmt; |
558 | 0 | } |
559 | 0 | return 0; |
560 | 0 | } |
561 | | |
562 | | int |
563 | | __flagfmt(Fmt *f) |
564 | 0 | { |
565 | 0 | switch(f->r){ |
566 | 0 | case ',': |
567 | 0 | f->flags |= FmtComma; |
568 | 0 | break; |
569 | 0 | case '-': |
570 | 0 | f->flags |= FmtLeft; |
571 | 0 | break; |
572 | 0 | case '+': |
573 | 0 | f->flags |= FmtSign; |
574 | 0 | break; |
575 | 0 | case '#': |
576 | 0 | f->flags |= FmtSharp; |
577 | 0 | break; |
578 | 0 | case '\'': |
579 | 0 | f->flags |= FmtApost; |
580 | 0 | break; |
581 | 0 | case ' ': |
582 | 0 | f->flags |= FmtSpace; |
583 | 0 | break; |
584 | 0 | case 'u': |
585 | 0 | f->flags |= FmtUnsigned; |
586 | 0 | break; |
587 | 0 | case 'h': |
588 | 0 | if(f->flags & FmtShort) |
589 | 0 | f->flags |= FmtByte; |
590 | 0 | f->flags |= FmtShort; |
591 | 0 | break; |
592 | 0 | case 'L': |
593 | 0 | f->flags |= FmtLDouble; |
594 | 0 | break; |
595 | 0 | case 'l': |
596 | 0 | if(f->flags & FmtLong) |
597 | 0 | f->flags |= FmtVLong; |
598 | 0 | f->flags |= FmtLong; |
599 | 0 | break; |
600 | 0 | } |
601 | 0 | return 1; |
602 | 0 | } |
603 | | |
604 | | /* default error format */ |
605 | | int |
606 | | __badfmt(Fmt *f) |
607 | 0 | { |
608 | 0 | char x[2+UTFmax]; |
609 | 0 | int n; |
610 | |
|
611 | 0 | x[0] = '%'; |
612 | 0 | n = 1 + runetochar(x+1, &f->r); |
613 | 0 | x[n++] = '%'; |
614 | 0 | f->prec = n; |
615 | 0 | __fmtcpy(f, (const void*)x, n, n); |
616 | 0 | return 0; |
617 | 0 | } |