2 * The authors of this software are Rob Pike and Ken Thompson.
3 * Copyright (c) 2002 by Lucent Technologies.
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose without fee is hereby granted, provided that this entire notice
6 * is included in all copies of any software which is or includes a copy
7 * or modification of this software and in all copies of the supporting
8 * documentation for such software.
9 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
11 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
20 /* format the output into f->to and return the number of characters fmted */
22 dofmt(Fmt *f, char *fmt)
34 while((r = *(uchar*)fmt) && r != '%'){
38 fmt += chartorune(&rune, fmt);
41 FMTRCHAR(f, rt, rs, r);
44 f->nfmt += rt - (Rune *)f->to;
47 return f->nfmt - nfmt;
52 while((r = *(uchar*)fmt) && r != '%'){
57 n = chartorune(&rune, fmt);
59 t = (char*)__fmtflush(f, t, n);
70 f->nfmt += t - (char *)f->to;
73 return f->nfmt - nfmt;
77 fmt = (char*)__fmtdispatch(f, fmt, 0);
81 return 0; /* not reached */
85 __fmtflush(Fmt *f, void *t, int len)
88 f->nfmt += (Rune*)t - (Rune*)f->to;
90 f->nfmt += (char*)t - (char *)f->to;
92 if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
100 * put a formatted block of memory sz bytes long of n runes into the output buffer,
101 * left/right justified in a field of at least f->width charactes
104 __fmtpad(Fmt *f, int n)
111 for(i = 0; i < n; i++)
112 FMTCHAR(f, t, s, ' ');
113 f->nfmt += t - (char *)f->to;
119 __rfmtpad(Fmt *f, int n)
126 for(i = 0; i < n; i++)
127 FMTRCHAR(f, t, s, ' ');
128 f->nfmt += t - (Rune *)f->to;
134 __fmtcpy(Fmt *f, const void *vm, int n, int sz)
137 char *t, *s, *m, *me;
145 if((fl & FmtPrec) && n > f->prec)
148 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
152 for(nc = n; nc > 0; nc--){
156 else if((me - m) >= UTFmax || fullrune(m, me-m))
157 m += chartorune(&r, m);
160 FMTRCHAR(f, rt, rs, r);
162 f->nfmt += rt - (Rune *)f->to;
166 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
169 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
173 for(nc = n; nc > 0; nc--){
177 else if((me - m) >= UTFmax || fullrune(m, me-m))
178 m += chartorune(&r, m);
183 f->nfmt += t - (char *)f->to;
185 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
192 __fmtrcpy(Fmt *f, const void *vm, int n)
194 Rune r, *m, *me, *rt, *rs;
202 if((fl & FmtPrec) && n > f->prec)
205 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
209 for(me = m + n; m < me; m++)
210 FMTRCHAR(f, rt, rs, *m);
211 f->nfmt += rt - (Rune *)f->to;
213 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
216 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
220 for(me = m + n; m < me; m++){
224 f->nfmt += t - (char *)f->to;
226 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
232 /* fmt out one character */
238 x[0] = va_arg(f->args, int);
240 return __fmtcpy(f, (const char*)x, 1, 1);
243 /* fmt out one rune */
249 x[0] = va_arg(f->args, int);
250 return __fmtrcpy(f, (const void*)x, 1);
253 /* public helper routine: fmt out a null terminated string already in hand */
255 fmtstrcpy(Fmt *f, char *s)
259 return __fmtcpy(f, "<nil>", 5, 5);
260 /* if precision is specified, make sure we don't wander off the end */
261 if(f->flags & FmtPrec){
263 for(i = 0; i < p; i++)
266 return __fmtcpy(f, s, utfnlen(s, i), i); /* BUG?: won't print a partial rune at end */
269 return __fmtcpy(f, s, utflen(s), strlen(s));
272 /* fmt out a null terminated utf string */
278 s = va_arg(f->args, char *);
279 return fmtstrcpy(f, s);
282 /* public helper routine: fmt out a null terminated rune string already in hand */
284 fmtrunestrcpy(Fmt *f, Rune *s)
290 return __fmtcpy(f, "<nil>", 5, 5);
291 /* if precision is specified, make sure we don't wander off the end */
292 if(f->flags & FmtPrec){
294 for(n = 0; n < p; n++)
302 return __fmtrcpy(f, s, n);
305 /* fmt out a null terminated rune string */
311 s = va_arg(f->args, Rune *);
312 return fmtrunestrcpy(f, s);
323 return __fmtrcpy(f, (const void*)x, 1);
330 char buf[70], *p, *conv;
333 int neg, base, i, n, fl, w, isv;
352 u = (ulong)va_arg(f->args, void*);
355 }else if(fl & FmtVLong){
358 vu = va_arg(f->args, uvlong);
360 vu = va_arg(f->args, vlong);
361 }else if(fl & FmtLong){
363 u = va_arg(f->args, ulong);
365 u = va_arg(f->args, long);
366 }else if(fl & FmtByte){
368 u = (uchar)va_arg(f->args, int);
370 u = (char)va_arg(f->args, int);
371 }else if(fl & FmtShort){
373 u = (ushort)va_arg(f->args, int);
375 u = (short)va_arg(f->args, int);
378 u = va_arg(f->args, uint);
380 u = va_arg(f->args, int);
382 conv = "0123456789abcdef";
396 conv = "0123456789ABCDEF";
407 if(!(fl & FmtUnsigned)){
408 if(isv && (vlong)vu < 0){
411 }else if(!isv && (long)u < 0){
416 fl &= ~(FmtSign|FmtSpace); /* no + for unsigned conversions */
418 p = buf + sizeof buf - 1;
424 if((fl & FmtComma) && n % 4 == 3){
435 if((fl & FmtComma) && n % 4 == 3){
444 if(!(fl & FmtPrec) || f->prec != 0){
450 for(w = f->prec; n < w && p > buf+3; n++)
452 if(neg || (fl & (FmtSign|FmtSpace)))
464 if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
465 for(w = f->width; n < w && p > buf+3; n++)
472 if(base == 16 || base == 8)
477 else if(fl & FmtSign)
479 else if(fl & FmtSpace)
481 f->flags &= ~FmtPrec;
482 return __fmtcpy(f, p + 1, n, n);
492 p = va_arg(f->args, void*);
494 *(vlong*)p = f->nfmt;
495 }else if(fl & FmtLong){
497 }else if(fl & FmtByte){
499 }else if(fl & FmtShort){
500 *(short*)p = f->nfmt;
512 f->flags |= FmtComma;
521 f->flags |= FmtSharp;
524 f->flags |= FmtSpace;
527 f->flags |= FmtUnsigned;
530 if(f->flags & FmtShort)
532 f->flags |= FmtShort;
535 f->flags |= FmtLDouble;
538 if(f->flags & FmtLong)
539 f->flags |= FmtVLong;
546 /* default error format */
556 __fmtcpy(f, (const void*)x, 3, 3);