1 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2 /* Copyright (c) 2004 Google Inc.; see LICENSE */
10 /* format the output into f->to and return the number of characters fmted */
12 dofmt(Fmt *f, char *fmt)
24 while((r = *(uchar*)fmt) && r != '%'){
28 fmt += chartorune(&rune, fmt);
31 FMTRCHAR(f, rt, rs, r);
34 f->nfmt += rt - (Rune *)f->to;
37 return f->nfmt - nfmt;
42 while((r = *(uchar*)fmt) && r != '%'){
47 n = chartorune(&rune, fmt);
49 t = (char*)__fmtflush(f, t, n);
60 f->nfmt += t - (char *)f->to;
63 return f->nfmt - nfmt;
67 fmt = (char*)__fmtdispatch(f, fmt, 0);
74 __fmtflush(Fmt *f, void *t, int len)
77 f->nfmt += (Rune*)t - (Rune*)f->to;
79 f->nfmt += (char*)t - (char *)f->to;
81 if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
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)
93 __fmtpad(Fmt *f, int n)
100 for(i = 0; i < n; i++)
101 FMTCHAR(f, t, s, ' ');
102 f->nfmt += t - (char *)f->to;
108 __rfmtpad(Fmt *f, int n)
115 for(i = 0; i < n; i++)
116 FMTRCHAR(f, t, s, ' ');
117 f->nfmt += t - (Rune *)f->to;
123 __fmtcpy(Fmt *f, const void *vm, int n, int sz)
126 char *t, *s, *m, *me;
136 if((fl & FmtPrec) && n > f->prec)
139 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
143 for(nc = n; nc > 0; nc--){
147 else if((me - m) >= UTFmax || fullrune(m, me-m))
148 m += chartorune(&r, m);
151 FMTRCHAR(f, rt, rs, r);
153 f->nfmt += rt - (Rune *)f->to;
155 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
158 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
162 for(nc = n; nc > 0; nc--){
166 else if((me - m) >= UTFmax || fullrune(m, me-m))
167 m += chartorune(&r, m);
172 f->nfmt += t - (char *)f->to;
174 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
181 __fmtrcpy(Fmt *f, const void *vm, int n)
183 Rune r, *m, *me, *rt, *rs;
193 if((fl & FmtPrec) && n > f->prec)
196 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
200 for(me = m + n; m < me; m++)
201 FMTRCHAR(f, rt, rs, *m);
202 f->nfmt += rt - (Rune *)f->to;
204 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
207 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
211 for(me = m + n; m < me; m++){
215 f->nfmt += t - (char *)f->to;
217 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
223 /* fmt out one character */
229 x[0] = va_arg(f->args, int);
231 return __fmtcpy(f, (const char*)x, 1, 1);
234 /* fmt out one rune */
240 x[0] = va_arg(f->args, int);
241 return __fmtrcpy(f, (const void*)x, 1);
244 /* public helper routine: fmt out a null terminated string already in hand */
246 fmtstrcpy(Fmt *f, char *s)
251 return __fmtcpy(f, "<nil>", 5, 5);
252 /* if precision is specified, make sure we don't wander off the end */
253 if(f->flags & FmtPrec){
257 for(j=0; j<f->prec && s[i]; j++)
258 i += chartorune(&r, s+i);
260 /* ANSI requires precision in bytes, not Runes */
261 for(i=0; i<f->prec; i++)
264 j = utfnlen(s, i); /* won't print partial at end */
266 return __fmtcpy(f, s, j, i);
268 return __fmtcpy(f, s, utflen(s), strlen(s));
271 /* fmt out a null terminated utf string */
277 s = va_arg(f->args, char *);
278 return fmtstrcpy(f, s);
281 /* public helper routine: fmt out a null terminated rune string already in hand */
283 fmtrunestrcpy(Fmt *f, Rune *s)
289 return __fmtcpy(f, "<nil>", 5, 5);
290 /* if precision is specified, make sure we don't wander off the end */
291 if(f->flags & FmtPrec){
293 for(n = 0; n < p; n++)
301 return __fmtrcpy(f, s, n);
304 /* fmt out a null terminated rune string */
310 s = va_arg(f->args, Rune *);
311 return fmtrunestrcpy(f, s);
322 return __fmtrcpy(f, (const void*)x, 1);
329 char buf[140], *p, *conv;
330 /* 140: for 64 bits of binary + 3-byte sep every 4 digits */
333 int neg, base, i, n, fl, w, isv;
334 int ndig, len, excess, bytelen;
345 * Unsigned verbs for ANSI C
354 fl &= ~(FmtSign|FmtSpace);
359 u = (ulong)va_arg(f->args, void*);
362 }else if(fl & FmtVLong){
365 vu = va_arg(f->args, uvlong);
367 vu = va_arg(f->args, vlong);
368 }else if(fl & FmtLong){
370 u = va_arg(f->args, ulong);
372 u = va_arg(f->args, long);
373 }else if(fl & FmtByte){
375 u = (uchar)va_arg(f->args, int);
377 u = (char)va_arg(f->args, int);
378 }else if(fl & FmtShort){
380 u = (ushort)va_arg(f->args, int);
382 u = (short)va_arg(f->args, int);
385 u = va_arg(f->args, uint);
387 u = va_arg(f->args, int);
389 conv = "0123456789abcdef";
390 grouping = "\4"; /* for hex, octal etc. (undefined by spec but nice) */
391 thousands = f->thousands;
397 grouping = f->grouping;
400 conv = "0123456789ABCDEF";
416 if(!(fl & FmtUnsigned)){
417 if(isv && (vlong)vu < 0){
420 }else if(!isv && (long)u < 0){
425 p = buf + sizeof buf - 1;
426 n = 0; /* in runes */
427 excess = 0; /* number of bytes > number runes */
429 len = utflen(thousands);
430 bytelen = strlen(thousands);
435 if((fl & FmtComma) && n % 4 == 3){
439 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
441 excess += bytelen - len;
443 memmove(p+1, thousands, bytelen);
452 if((fl & FmtComma) && n % 4 == 3){
456 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
458 excess += bytelen - len;
460 memmove(p+1, thousands, bytelen);
468 * "The result of converting a zero value with
469 * a precision of zero is no characters." - ANSI
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
475 if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){
479 __needsep(&ndig, &grouping);
483 * Zero values don't get 0x.
485 if(f->r == 'x' || f->r == 'X')
488 for(w = f->prec; n < w && p > buf+3; n++){
489 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
491 excess += bytelen - len;
493 memmove(p+1, thousands, bytelen);
497 if(neg || (fl & (FmtSign|FmtSpace)))
509 if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
513 for(; n < w && p > buf+3; n++){
514 if((fl & FmtApost) && __needsep(&ndig, &grouping)){
516 excess += bytelen - len;
518 memmove(p+1, thousands, bytelen);
522 f->flags &= ~FmtWidth;
527 if(base == 16 || base == 8)
532 else if(fl & FmtSign)
534 else if(fl & FmtSpace)
536 f->flags &= ~FmtPrec;
537 return __fmtcpy(f, p + 1, n, n + excess);
547 p = va_arg(f->args, void*);
549 *(vlong*)p = f->nfmt;
550 }else if(fl & FmtLong){
552 }else if(fl & FmtByte){
554 }else if(fl & FmtShort){
555 *(short*)p = f->nfmt;
567 f->flags |= FmtComma;
576 f->flags |= FmtSharp;
579 f->flags |= FmtApost;
582 f->flags |= FmtSpace;
585 f->flags |= FmtUnsigned;
588 if(f->flags & FmtShort)
590 f->flags |= FmtShort;
593 f->flags |= FmtLDouble;
596 if(f->flags & FmtLong)
597 f->flags |= FmtVLong;
604 /* default error format */
614 __fmtcpy(f, (const void*)x, 3, 3);