1 85231fd8 2006-05-21 devnull /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2 e17e1a71 2006-05-22 devnull /* Copyright (c) 2004 Google Inc.; see LICENSE */
4 91c13e54 2004-02-29 devnull #include <stdarg.h>
5 91c13e54 2004-02-29 devnull #include <string.h>
6 e5aa96ac 2004-12-26 devnull #include "plan9.h"
7 91c13e54 2004-02-29 devnull #include "fmt.h"
8 91c13e54 2004-02-29 devnull #include "fmtdef.h"
10 91c13e54 2004-02-29 devnull /* format the output into f->to and return the number of characters fmted */
12 91c13e54 2004-02-29 devnull dofmt(Fmt *f, char *fmt)
14 91c13e54 2004-02-29 devnull Rune rune, *rt, *rs;
16 91c13e54 2004-02-29 devnull char *t, *s;
17 91c13e54 2004-02-29 devnull int n, nfmt;
19 91c13e54 2004-02-29 devnull nfmt = f->nfmt;
21 91c13e54 2004-02-29 devnull if(f->runes){
22 91c13e54 2004-02-29 devnull rt = (Rune*)f->to;
23 91c13e54 2004-02-29 devnull rs = (Rune*)f->stop;
24 91c13e54 2004-02-29 devnull while((r = *(uchar*)fmt) && r != '%'){
25 91c13e54 2004-02-29 devnull if(r < Runeself)
28 91c13e54 2004-02-29 devnull fmt += chartorune(&rune, fmt);
29 91c13e54 2004-02-29 devnull r = rune;
31 91c13e54 2004-02-29 devnull FMTRCHAR(f, rt, rs, r);
34 91c13e54 2004-02-29 devnull f->nfmt += rt - (Rune *)f->to;
35 91c13e54 2004-02-29 devnull f->to = rt;
37 91c13e54 2004-02-29 devnull return f->nfmt - nfmt;
38 91c13e54 2004-02-29 devnull f->stop = rs;
40 91c13e54 2004-02-29 devnull t = (char*)f->to;
41 91c13e54 2004-02-29 devnull s = (char*)f->stop;
42 91c13e54 2004-02-29 devnull while((r = *(uchar*)fmt) && r != '%'){
43 91c13e54 2004-02-29 devnull if(r < Runeself){
44 91c13e54 2004-02-29 devnull FMTCHAR(f, t, s, r);
47 91c13e54 2004-02-29 devnull n = chartorune(&rune, fmt);
48 91c13e54 2004-02-29 devnull if(t + n > s){
49 91c13e54 2004-02-29 devnull t = (char*)__fmtflush(f, t, n);
50 91c13e54 2004-02-29 devnull if(t != nil)
51 91c13e54 2004-02-29 devnull s = (char*)f->stop;
53 91c13e54 2004-02-29 devnull return -1;
55 91c13e54 2004-02-29 devnull while(n--)
56 91c13e54 2004-02-29 devnull *t++ = *fmt++;
60 91c13e54 2004-02-29 devnull f->nfmt += t - (char *)f->to;
61 91c13e54 2004-02-29 devnull f->to = t;
63 91c13e54 2004-02-29 devnull return f->nfmt - nfmt;
64 91c13e54 2004-02-29 devnull f->stop = s;
67 91c13e54 2004-02-29 devnull fmt = (char*)__fmtdispatch(f, fmt, 0);
68 91c13e54 2004-02-29 devnull if(fmt == nil)
69 91c13e54 2004-02-29 devnull return -1;
74 91c13e54 2004-02-29 devnull __fmtflush(Fmt *f, void *t, int len)
76 91c13e54 2004-02-29 devnull if(f->runes)
77 91c13e54 2004-02-29 devnull f->nfmt += (Rune*)t - (Rune*)f->to;
79 91c13e54 2004-02-29 devnull f->nfmt += (char*)t - (char *)f->to;
80 91c13e54 2004-02-29 devnull f->to = t;
81 91c13e54 2004-02-29 devnull if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
82 91c13e54 2004-02-29 devnull f->stop = f->to;
83 91c13e54 2004-02-29 devnull return nil;
85 91c13e54 2004-02-29 devnull return f->to;
89 91c13e54 2004-02-29 devnull * put a formatted block of memory sz bytes long of n runes into the output buffer,
90 85231fd8 2006-05-21 devnull * left/right justified in a field of at least f->width characters (if FmtWidth is set)
93 91c13e54 2004-02-29 devnull __fmtpad(Fmt *f, int n)
95 91c13e54 2004-02-29 devnull char *t, *s;
98 91c13e54 2004-02-29 devnull t = (char*)f->to;
99 91c13e54 2004-02-29 devnull s = (char*)f->stop;
100 91c13e54 2004-02-29 devnull for(i = 0; i < n; i++)
101 91c13e54 2004-02-29 devnull FMTCHAR(f, t, s, ' ');
102 91c13e54 2004-02-29 devnull f->nfmt += t - (char *)f->to;
103 91c13e54 2004-02-29 devnull f->to = t;
104 91c13e54 2004-02-29 devnull return 0;
108 91c13e54 2004-02-29 devnull __rfmtpad(Fmt *f, int n)
110 91c13e54 2004-02-29 devnull Rune *t, *s;
113 91c13e54 2004-02-29 devnull t = (Rune*)f->to;
114 91c13e54 2004-02-29 devnull s = (Rune*)f->stop;
115 91c13e54 2004-02-29 devnull for(i = 0; i < n; i++)
116 91c13e54 2004-02-29 devnull FMTRCHAR(f, t, s, ' ');
117 91c13e54 2004-02-29 devnull f->nfmt += t - (Rune *)f->to;
118 91c13e54 2004-02-29 devnull f->to = t;
119 91c13e54 2004-02-29 devnull return 0;
123 91c13e54 2004-02-29 devnull __fmtcpy(Fmt *f, const void *vm, int n, int sz)
125 91c13e54 2004-02-29 devnull Rune *rt, *rs, r;
126 91c13e54 2004-02-29 devnull char *t, *s, *m, *me;
127 91c13e54 2004-02-29 devnull ulong fl;
128 91c13e54 2004-02-29 devnull int nc, w;
130 91c13e54 2004-02-29 devnull m = (char*)vm;
131 91c13e54 2004-02-29 devnull me = m + sz;
132 91c13e54 2004-02-29 devnull fl = f->flags;
134 85231fd8 2006-05-21 devnull if(fl & FmtWidth)
135 85231fd8 2006-05-21 devnull w = f->width;
136 91c13e54 2004-02-29 devnull if((fl & FmtPrec) && n > f->prec)
137 91c13e54 2004-02-29 devnull n = f->prec;
138 91c13e54 2004-02-29 devnull if(f->runes){
139 91c13e54 2004-02-29 devnull if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
140 91c13e54 2004-02-29 devnull return -1;
141 91c13e54 2004-02-29 devnull rt = (Rune*)f->to;
142 91c13e54 2004-02-29 devnull rs = (Rune*)f->stop;
143 91c13e54 2004-02-29 devnull for(nc = n; nc > 0; nc--){
144 91c13e54 2004-02-29 devnull r = *(uchar*)m;
145 91c13e54 2004-02-29 devnull if(r < Runeself)
147 91c13e54 2004-02-29 devnull else if((me - m) >= UTFmax || fullrune(m, me-m))
148 91c13e54 2004-02-29 devnull m += chartorune(&r, m);
151 91c13e54 2004-02-29 devnull FMTRCHAR(f, rt, rs, r);
153 91c13e54 2004-02-29 devnull f->nfmt += rt - (Rune *)f->to;
154 91c13e54 2004-02-29 devnull f->to = rt;
155 91c13e54 2004-02-29 devnull if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
156 91c13e54 2004-02-29 devnull return -1;
158 91c13e54 2004-02-29 devnull if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
159 91c13e54 2004-02-29 devnull return -1;
160 91c13e54 2004-02-29 devnull t = (char*)f->to;
161 91c13e54 2004-02-29 devnull s = (char*)f->stop;
162 91c13e54 2004-02-29 devnull for(nc = n; nc > 0; nc--){
163 91c13e54 2004-02-29 devnull r = *(uchar*)m;
164 91c13e54 2004-02-29 devnull if(r < Runeself)
166 91c13e54 2004-02-29 devnull else if((me - m) >= UTFmax || fullrune(m, me-m))
167 91c13e54 2004-02-29 devnull m += chartorune(&r, m);
170 91c13e54 2004-02-29 devnull FMTRUNE(f, t, s, r);
172 91c13e54 2004-02-29 devnull f->nfmt += t - (char *)f->to;
173 91c13e54 2004-02-29 devnull f->to = t;
174 91c13e54 2004-02-29 devnull if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
175 91c13e54 2004-02-29 devnull return -1;
177 91c13e54 2004-02-29 devnull return 0;
181 91c13e54 2004-02-29 devnull __fmtrcpy(Fmt *f, const void *vm, int n)
183 91c13e54 2004-02-29 devnull Rune r, *m, *me, *rt, *rs;
184 91c13e54 2004-02-29 devnull char *t, *s;
185 91c13e54 2004-02-29 devnull ulong fl;
188 91c13e54 2004-02-29 devnull m = (Rune*)vm;
189 91c13e54 2004-02-29 devnull fl = f->flags;
191 85231fd8 2006-05-21 devnull if(fl & FmtWidth)
192 85231fd8 2006-05-21 devnull w = f->width;
193 91c13e54 2004-02-29 devnull if((fl & FmtPrec) && n > f->prec)
194 91c13e54 2004-02-29 devnull n = f->prec;
195 91c13e54 2004-02-29 devnull if(f->runes){
196 91c13e54 2004-02-29 devnull if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
197 91c13e54 2004-02-29 devnull return -1;
198 91c13e54 2004-02-29 devnull rt = (Rune*)f->to;
199 91c13e54 2004-02-29 devnull rs = (Rune*)f->stop;
200 91c13e54 2004-02-29 devnull for(me = m + n; m < me; m++)
201 91c13e54 2004-02-29 devnull FMTRCHAR(f, rt, rs, *m);
202 91c13e54 2004-02-29 devnull f->nfmt += rt - (Rune *)f->to;
203 91c13e54 2004-02-29 devnull f->to = rt;
204 91c13e54 2004-02-29 devnull if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
205 91c13e54 2004-02-29 devnull return -1;
207 91c13e54 2004-02-29 devnull if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
208 91c13e54 2004-02-29 devnull return -1;
209 91c13e54 2004-02-29 devnull t = (char*)f->to;
210 91c13e54 2004-02-29 devnull s = (char*)f->stop;
211 91c13e54 2004-02-29 devnull for(me = m + n; m < me; m++){
213 91c13e54 2004-02-29 devnull FMTRUNE(f, t, s, r);
215 91c13e54 2004-02-29 devnull f->nfmt += t - (char *)f->to;
216 91c13e54 2004-02-29 devnull f->to = t;
217 91c13e54 2004-02-29 devnull if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
218 91c13e54 2004-02-29 devnull return -1;
220 91c13e54 2004-02-29 devnull return 0;
223 91c13e54 2004-02-29 devnull /* fmt out one character */
225 91c13e54 2004-02-29 devnull __charfmt(Fmt *f)
227 91c13e54 2004-02-29 devnull char x[1];
229 91c13e54 2004-02-29 devnull x[0] = va_arg(f->args, int);
230 91c13e54 2004-02-29 devnull f->prec = 1;
231 91c13e54 2004-02-29 devnull return __fmtcpy(f, (const char*)x, 1, 1);
234 91c13e54 2004-02-29 devnull /* fmt out one rune */
236 91c13e54 2004-02-29 devnull __runefmt(Fmt *f)
238 91c13e54 2004-02-29 devnull Rune x[1];
240 91c13e54 2004-02-29 devnull x[0] = va_arg(f->args, int);
241 91c13e54 2004-02-29 devnull return __fmtrcpy(f, (const void*)x, 1);
244 91c13e54 2004-02-29 devnull /* public helper routine: fmt out a null terminated string already in hand */
246 91c13e54 2004-02-29 devnull fmtstrcpy(Fmt *f, char *s)
248 3f1a2197 2004-12-26 devnull int i, j;
251 91c13e54 2004-02-29 devnull return __fmtcpy(f, "<nil>", 5, 5);
252 91c13e54 2004-02-29 devnull /* if precision is specified, make sure we don't wander off the end */
253 91c13e54 2004-02-29 devnull if(f->flags & FmtPrec){
254 ab239cb5 2006-05-26 devnull #ifdef PLAN9PORT
257 3f1a2197 2004-12-26 devnull for(j=0; j<f->prec && s[i]; j++)
258 3f1a2197 2004-12-26 devnull i += chartorune(&r, s+i);
260 ab239cb5 2006-05-26 devnull /* ANSI requires precision in bytes, not Runes */
261 ab239cb5 2006-05-26 devnull for(i=0; i<f->prec; i++)
262 ab239cb5 2006-05-26 devnull if(s[i] == 0)
264 ab239cb5 2006-05-26 devnull j = utfnlen(s, i); /* won't print partial at end */
266 3f1a2197 2004-12-26 devnull return __fmtcpy(f, s, j, i);
268 91c13e54 2004-02-29 devnull return __fmtcpy(f, s, utflen(s), strlen(s));
271 91c13e54 2004-02-29 devnull /* fmt out a null terminated utf string */
273 91c13e54 2004-02-29 devnull __strfmt(Fmt *f)
275 91c13e54 2004-02-29 devnull char *s;
277 91c13e54 2004-02-29 devnull s = va_arg(f->args, char *);
278 91c13e54 2004-02-29 devnull return fmtstrcpy(f, s);
281 91c13e54 2004-02-29 devnull /* public helper routine: fmt out a null terminated rune string already in hand */
283 91c13e54 2004-02-29 devnull fmtrunestrcpy(Fmt *f, Rune *s)
285 91c13e54 2004-02-29 devnull Rune *e;
286 91c13e54 2004-02-29 devnull int n, p;
289 91c13e54 2004-02-29 devnull return __fmtcpy(f, "<nil>", 5, 5);
290 91c13e54 2004-02-29 devnull /* if precision is specified, make sure we don't wander off the end */
291 91c13e54 2004-02-29 devnull if(f->flags & FmtPrec){
292 91c13e54 2004-02-29 devnull p = f->prec;
293 91c13e54 2004-02-29 devnull for(n = 0; n < p; n++)
294 91c13e54 2004-02-29 devnull if(s[n] == 0)
297 91c13e54 2004-02-29 devnull for(e = s; *e; e++)
299 91c13e54 2004-02-29 devnull n = e - s;
301 91c13e54 2004-02-29 devnull return __fmtrcpy(f, s, n);
304 91c13e54 2004-02-29 devnull /* fmt out a null terminated rune string */
306 91c13e54 2004-02-29 devnull __runesfmt(Fmt *f)
308 91c13e54 2004-02-29 devnull Rune *s;
310 91c13e54 2004-02-29 devnull s = va_arg(f->args, Rune *);
311 91c13e54 2004-02-29 devnull return fmtrunestrcpy(f, s);
314 91c13e54 2004-02-29 devnull /* fmt a % */
316 91c13e54 2004-02-29 devnull __percentfmt(Fmt *f)
318 91c13e54 2004-02-29 devnull Rune x[1];
320 91c13e54 2004-02-29 devnull x[0] = f->r;
321 91c13e54 2004-02-29 devnull f->prec = 1;
322 91c13e54 2004-02-29 devnull return __fmtrcpy(f, (const void*)x, 1);
325 91c13e54 2004-02-29 devnull /* fmt an integer */
327 91c13e54 2004-02-29 devnull __ifmt(Fmt *f)
329 85231fd8 2006-05-21 devnull char buf[140], *p, *conv;
330 85231fd8 2006-05-21 devnull /* 140: for 64 bits of binary + 3-byte sep every 4 digits */
331 91c13e54 2004-02-29 devnull uvlong vu;
332 91c13e54 2004-02-29 devnull ulong u;
333 91c13e54 2004-02-29 devnull int neg, base, i, n, fl, w, isv;
334 85231fd8 2006-05-21 devnull int ndig, len, excess, bytelen;
335 85231fd8 2006-05-21 devnull char *grouping;
336 85231fd8 2006-05-21 devnull char *thousands;
338 91c13e54 2004-02-29 devnull neg = 0;
339 91c13e54 2004-02-29 devnull fl = f->flags;
340 91c13e54 2004-02-29 devnull isv = 0;
343 3f1a2197 2004-12-26 devnull #ifndef PLAN9PORT
345 3f1a2197 2004-12-26 devnull * Unsigned verbs for ANSI C
347 91c13e54 2004-02-29 devnull switch(f->r){
348 e5aa96ac 2004-12-26 devnull case 'o':
349 3f1a2197 2004-12-26 devnull case 'p':
350 85231fd8 2006-05-21 devnull case 'u':
351 85231fd8 2006-05-21 devnull case 'x':
352 85231fd8 2006-05-21 devnull case 'X':
353 91c13e54 2004-02-29 devnull fl |= FmtUnsigned;
354 3f1a2197 2004-12-26 devnull fl &= ~(FmtSign|FmtSpace);
358 91c13e54 2004-02-29 devnull if(f->r == 'p'){
359 91c13e54 2004-02-29 devnull u = (ulong)va_arg(f->args, void*);
360 91c13e54 2004-02-29 devnull f->r = 'x';
361 91c13e54 2004-02-29 devnull fl |= FmtUnsigned;
362 91c13e54 2004-02-29 devnull }else if(fl & FmtVLong){
363 91c13e54 2004-02-29 devnull isv = 1;
364 91c13e54 2004-02-29 devnull if(fl & FmtUnsigned)
365 91c13e54 2004-02-29 devnull vu = va_arg(f->args, uvlong);
367 91c13e54 2004-02-29 devnull vu = va_arg(f->args, vlong);
368 91c13e54 2004-02-29 devnull }else if(fl & FmtLong){
369 91c13e54 2004-02-29 devnull if(fl & FmtUnsigned)
370 91c13e54 2004-02-29 devnull u = va_arg(f->args, ulong);
372 91c13e54 2004-02-29 devnull u = va_arg(f->args, long);
373 91c13e54 2004-02-29 devnull }else if(fl & FmtByte){
374 91c13e54 2004-02-29 devnull if(fl & FmtUnsigned)
375 91c13e54 2004-02-29 devnull u = (uchar)va_arg(f->args, int);
377 91c13e54 2004-02-29 devnull u = (char)va_arg(f->args, int);
378 91c13e54 2004-02-29 devnull }else if(fl & FmtShort){
379 91c13e54 2004-02-29 devnull if(fl & FmtUnsigned)
380 91c13e54 2004-02-29 devnull u = (ushort)va_arg(f->args, int);
382 91c13e54 2004-02-29 devnull u = (short)va_arg(f->args, int);
384 91c13e54 2004-02-29 devnull if(fl & FmtUnsigned)
385 91c13e54 2004-02-29 devnull u = va_arg(f->args, uint);
387 91c13e54 2004-02-29 devnull u = va_arg(f->args, int);
389 91c13e54 2004-02-29 devnull conv = "0123456789abcdef";
390 85231fd8 2006-05-21 devnull grouping = "\4"; /* for hex, octal etc. (undefined by spec but nice) */
391 85231fd8 2006-05-21 devnull thousands = f->thousands;
392 91c13e54 2004-02-29 devnull switch(f->r){
393 91c13e54 2004-02-29 devnull case 'd':
394 91c13e54 2004-02-29 devnull case 'i':
395 91c13e54 2004-02-29 devnull case 'u':
396 91c13e54 2004-02-29 devnull base = 10;
397 85231fd8 2006-05-21 devnull grouping = f->grouping;
399 85231fd8 2006-05-21 devnull case 'X':
400 85231fd8 2006-05-21 devnull conv = "0123456789ABCDEF";
401 85231fd8 2006-05-21 devnull /* fall through */
402 91c13e54 2004-02-29 devnull case 'x':
403 91c13e54 2004-02-29 devnull base = 16;
404 85231fd8 2006-05-21 devnull thousands = ":";
406 91c13e54 2004-02-29 devnull case 'b':
407 91c13e54 2004-02-29 devnull base = 2;
408 85231fd8 2006-05-21 devnull thousands = ":";
410 91c13e54 2004-02-29 devnull case 'o':
411 91c13e54 2004-02-29 devnull base = 8;
413 91c13e54 2004-02-29 devnull default:
414 91c13e54 2004-02-29 devnull return -1;
416 3f1a2197 2004-12-26 devnull if(!(fl & FmtUnsigned)){
417 91c13e54 2004-02-29 devnull if(isv && (vlong)vu < 0){
418 91c13e54 2004-02-29 devnull vu = -(vlong)vu;
419 91c13e54 2004-02-29 devnull neg = 1;
420 91c13e54 2004-02-29 devnull }else if(!isv && (long)u < 0){
421 91c13e54 2004-02-29 devnull u = -(long)u;
422 91c13e54 2004-02-29 devnull neg = 1;
425 91c13e54 2004-02-29 devnull p = buf + sizeof buf - 1;
426 85231fd8 2006-05-21 devnull n = 0; /* in runes */
427 85231fd8 2006-05-21 devnull excess = 0; /* number of bytes > number runes */
428 85231fd8 2006-05-21 devnull ndig = 0;
429 85231fd8 2006-05-21 devnull len = utflen(thousands);
430 85231fd8 2006-05-21 devnull bytelen = strlen(thousands);
431 91c13e54 2004-02-29 devnull if(isv){
432 91c13e54 2004-02-29 devnull while(vu){
433 91c13e54 2004-02-29 devnull i = vu % base;
434 91c13e54 2004-02-29 devnull vu /= base;
435 91c13e54 2004-02-29 devnull if((fl & FmtComma) && n % 4 == 3){
436 91c13e54 2004-02-29 devnull *p-- = ',';
439 85231fd8 2006-05-21 devnull if((fl & FmtApost) && __needsep(&ndig, &grouping)){
440 85231fd8 2006-05-21 devnull n += len;
441 85231fd8 2006-05-21 devnull excess += bytelen - len;
442 85231fd8 2006-05-21 devnull p -= bytelen;
443 85231fd8 2006-05-21 devnull memmove(p+1, thousands, bytelen);
445 91c13e54 2004-02-29 devnull *p-- = conv[i];
449 91c13e54 2004-02-29 devnull while(u){
450 91c13e54 2004-02-29 devnull i = u % base;
451 91c13e54 2004-02-29 devnull u /= base;
452 91c13e54 2004-02-29 devnull if((fl & FmtComma) && n % 4 == 3){
453 91c13e54 2004-02-29 devnull *p-- = ',';
456 85231fd8 2006-05-21 devnull if((fl & FmtApost) && __needsep(&ndig, &grouping)){
457 85231fd8 2006-05-21 devnull n += len;
458 85231fd8 2006-05-21 devnull excess += bytelen - len;
459 85231fd8 2006-05-21 devnull p -= bytelen;
460 85231fd8 2006-05-21 devnull memmove(p+1, thousands, bytelen);
462 91c13e54 2004-02-29 devnull *p-- = conv[i];
466 91c13e54 2004-02-29 devnull if(n == 0){
468 e17e1a71 2006-05-22 devnull * "The result of converting a zero value with
469 e17e1a71 2006-05-22 devnull * a precision of zero is no characters." - ANSI
471 e17e1a71 2006-05-22 devnull * "For o conversion, # increases the precision, if and only if
472 e17e1a71 2006-05-22 devnull * necessary, to force the first digit of the result to be a zero
473 e17e1a71 2006-05-22 devnull * (if the value and precision are both 0, a single 0 is printed)." - ANSI
475 e17e1a71 2006-05-22 devnull if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){
476 e17e1a71 2006-05-22 devnull *p-- = '0';
478 e17e1a71 2006-05-22 devnull if(fl & FmtApost)
479 e17e1a71 2006-05-22 devnull __needsep(&ndig, &grouping);
483 e17e1a71 2006-05-22 devnull * Zero values don't get 0x.
485 e17e1a71 2006-05-22 devnull if(f->r == 'x' || f->r == 'X')
486 e17e1a71 2006-05-22 devnull fl &= ~FmtSharp;
488 85231fd8 2006-05-21 devnull for(w = f->prec; n < w && p > buf+3; n++){
489 85231fd8 2006-05-21 devnull if((fl & FmtApost) && __needsep(&ndig, &grouping)){
490 85231fd8 2006-05-21 devnull n += len;
491 85231fd8 2006-05-21 devnull excess += bytelen - len;
492 85231fd8 2006-05-21 devnull p -= bytelen;
493 85231fd8 2006-05-21 devnull memmove(p+1, thousands, bytelen);
495 91c13e54 2004-02-29 devnull *p-- = '0';
497 91c13e54 2004-02-29 devnull if(neg || (fl & (FmtSign|FmtSpace)))
499 91c13e54 2004-02-29 devnull if(fl & FmtSharp){
500 91c13e54 2004-02-29 devnull if(base == 16)
502 91c13e54 2004-02-29 devnull else if(base == 8){
503 91c13e54 2004-02-29 devnull if(p[1] == '0')
504 91c13e54 2004-02-29 devnull fl &= ~FmtSharp;
509 91c13e54 2004-02-29 devnull if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
511 85231fd8 2006-05-21 devnull if(fl & FmtWidth)
512 85231fd8 2006-05-21 devnull w = f->width;
513 85231fd8 2006-05-21 devnull for(; n < w && p > buf+3; n++){
514 85231fd8 2006-05-21 devnull if((fl & FmtApost) && __needsep(&ndig, &grouping)){
515 85231fd8 2006-05-21 devnull n += len;
516 85231fd8 2006-05-21 devnull excess += bytelen - len;
517 85231fd8 2006-05-21 devnull p -= bytelen;
518 85231fd8 2006-05-21 devnull memmove(p+1, thousands, bytelen);
520 91c13e54 2004-02-29 devnull *p-- = '0';
522 85231fd8 2006-05-21 devnull f->flags &= ~FmtWidth;
524 91c13e54 2004-02-29 devnull if(fl & FmtSharp){
525 91c13e54 2004-02-29 devnull if(base == 16)
526 91c13e54 2004-02-29 devnull *p-- = f->r;
527 91c13e54 2004-02-29 devnull if(base == 16 || base == 8)
528 91c13e54 2004-02-29 devnull *p-- = '0';
531 91c13e54 2004-02-29 devnull *p-- = '-';
532 91c13e54 2004-02-29 devnull else if(fl & FmtSign)
533 91c13e54 2004-02-29 devnull *p-- = '+';
534 91c13e54 2004-02-29 devnull else if(fl & FmtSpace)
535 91c13e54 2004-02-29 devnull *p-- = ' ';
536 91c13e54 2004-02-29 devnull f->flags &= ~FmtPrec;
537 85231fd8 2006-05-21 devnull return __fmtcpy(f, p + 1, n, n + excess);
541 91c13e54 2004-02-29 devnull __countfmt(Fmt *f)
543 91c13e54 2004-02-29 devnull void *p;
544 91c13e54 2004-02-29 devnull ulong fl;
546 91c13e54 2004-02-29 devnull fl = f->flags;
547 91c13e54 2004-02-29 devnull p = va_arg(f->args, void*);
548 91c13e54 2004-02-29 devnull if(fl & FmtVLong){
549 91c13e54 2004-02-29 devnull *(vlong*)p = f->nfmt;
550 91c13e54 2004-02-29 devnull }else if(fl & FmtLong){
551 91c13e54 2004-02-29 devnull *(long*)p = f->nfmt;
552 91c13e54 2004-02-29 devnull }else if(fl & FmtByte){
553 91c13e54 2004-02-29 devnull *(char*)p = f->nfmt;
554 91c13e54 2004-02-29 devnull }else if(fl & FmtShort){
555 91c13e54 2004-02-29 devnull *(short*)p = f->nfmt;
557 91c13e54 2004-02-29 devnull *(int*)p = f->nfmt;
559 91c13e54 2004-02-29 devnull return 0;
563 91c13e54 2004-02-29 devnull __flagfmt(Fmt *f)
565 91c13e54 2004-02-29 devnull switch(f->r){
566 91c13e54 2004-02-29 devnull case ',':
567 91c13e54 2004-02-29 devnull f->flags |= FmtComma;
569 91c13e54 2004-02-29 devnull case '-':
570 91c13e54 2004-02-29 devnull f->flags |= FmtLeft;
572 91c13e54 2004-02-29 devnull case '+':
573 91c13e54 2004-02-29 devnull f->flags |= FmtSign;
575 91c13e54 2004-02-29 devnull case '#':
576 91c13e54 2004-02-29 devnull f->flags |= FmtSharp;
578 85231fd8 2006-05-21 devnull case '\'':
579 85231fd8 2006-05-21 devnull f->flags |= FmtApost;
581 91c13e54 2004-02-29 devnull case ' ':
582 91c13e54 2004-02-29 devnull f->flags |= FmtSpace;
584 91c13e54 2004-02-29 devnull case 'u':
585 91c13e54 2004-02-29 devnull f->flags |= FmtUnsigned;
587 91c13e54 2004-02-29 devnull case 'h':
588 91c13e54 2004-02-29 devnull if(f->flags & FmtShort)
589 91c13e54 2004-02-29 devnull f->flags |= FmtByte;
590 91c13e54 2004-02-29 devnull f->flags |= FmtShort;
592 91c13e54 2004-02-29 devnull case 'L':
593 91c13e54 2004-02-29 devnull f->flags |= FmtLDouble;
595 91c13e54 2004-02-29 devnull case 'l':
596 91c13e54 2004-02-29 devnull if(f->flags & FmtLong)
597 91c13e54 2004-02-29 devnull f->flags |= FmtVLong;
598 91c13e54 2004-02-29 devnull f->flags |= FmtLong;
601 91c13e54 2004-02-29 devnull return 1;
604 91c13e54 2004-02-29 devnull /* default error format */
606 91c13e54 2004-02-29 devnull __badfmt(Fmt *f)
608 0cadb430 2009-09-11 russcox char x[2+UTFmax];
611 91c13e54 2004-02-29 devnull x[0] = '%';
612 0cadb430 2009-09-11 russcox n = 1 + runetochar(x+1, &f->r);
613 0cadb430 2009-09-11 russcox x[n++] = '%';
614 0cadb430 2009-09-11 russcox f->prec = n;
615 0cadb430 2009-09-11 russcox __fmtcpy(f, (const void*)x, n, n);
616 91c13e54 2004-02-29 devnull return 0;