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
11 * ANY 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);
84 __fmtflush(Fmt *f, void *t, int len)
87 f->nfmt += (Rune*)t - (Rune*)f->to;
89 f->nfmt += (char*)t - (char *)f->to;
91 if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
99 * put a formatted block of memory sz bytes long of n runes into the output buffer,
100 * left/right justified in a field of at least f->width charactes
103 __fmtpad(Fmt *f, int n)
110 for(i = 0; i < n; i++)
111 FMTCHAR(f, t, s, ' ');
112 f->nfmt += t - (char *)f->to;
118 __rfmtpad(Fmt *f, int n)
125 for(i = 0; i < n; i++)
126 FMTRCHAR(f, t, s, ' ');
127 f->nfmt += t - (Rune *)f->to;
133 __fmtcpy(Fmt *f, const void *vm, int n, int sz)
136 char *t, *s, *m, *me;
144 if((fl & FmtPrec) && n > f->prec)
147 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
151 for(nc = n; nc > 0; nc--){
155 else if((me - m) >= UTFmax || fullrune(m, me-m))
156 m += chartorune(&r, m);
159 FMTRCHAR(f, rt, rs, r);
161 f->nfmt += rt - (Rune *)f->to;
163 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
166 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
170 for(nc = n; nc > 0; nc--){
174 else if((me - m) >= UTFmax || fullrune(m, me-m))
175 m += chartorune(&r, m);
180 f->nfmt += t - (char *)f->to;
182 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
189 __fmtrcpy(Fmt *f, const void *vm, int n)
191 Rune r, *m, *me, *rt, *rs;
199 if((fl & FmtPrec) && n > f->prec)
202 if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
206 for(me = m + n; m < me; m++)
207 FMTRCHAR(f, rt, rs, *m);
208 f->nfmt += rt - (Rune *)f->to;
210 if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
213 if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
217 for(me = m + n; m < me; m++){
221 f->nfmt += t - (char *)f->to;
223 if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
229 /* fmt out one character */
235 x[0] = va_arg(f->args, int);
237 return __fmtcpy(f, (const char*)x, 1, 1);
240 /* fmt out one rune */
246 x[0] = va_arg(f->args, int);
247 return __fmtrcpy(f, (const void*)x, 1);
250 /* public helper routine: fmt out a null terminated string already in hand */
252 fmtstrcpy(Fmt *f, char *s)
258 return __fmtcpy(f, "<nil>", 5, 5);
259 /* if precision is specified, make sure we don't wander off the end */
260 if(f->flags & FmtPrec){
262 for(j=0; j<f->prec && s[i]; j++)
263 i += chartorune(&r, s+i);
264 return __fmtcpy(f, s, j, i);
266 return __fmtcpy(f, s, utflen(s), strlen(s));
269 /* fmt out a null terminated utf string */
275 s = va_arg(f->args, char *);
276 return fmtstrcpy(f, s);
279 /* public helper routine: fmt out a null terminated rune string already in hand */
281 fmtrunestrcpy(Fmt *f, Rune *s)
287 return __fmtcpy(f, "<nil>", 5, 5);
288 /* if precision is specified, make sure we don't wander off the end */
289 if(f->flags & FmtPrec){
291 for(n = 0; n < p; n++)
299 return __fmtrcpy(f, s, n);
302 /* fmt out a null terminated rune string */
308 s = va_arg(f->args, Rune *);
309 return fmtrunestrcpy(f, s);
320 return __fmtrcpy(f, (const void*)x, 1);
327 char buf[70], *p, *conv;
330 int neg, base, i, n, fl, w, isv;
339 * Unsigned verbs for ANSI C
348 fl &= ~(FmtSign|FmtSpace);
353 u = (ulong)va_arg(f->args, void*);
356 }else if(fl & FmtVLong){
359 vu = va_arg(f->args, uvlong);
361 vu = va_arg(f->args, vlong);
362 }else if(fl & FmtLong){
364 u = va_arg(f->args, ulong);
366 u = va_arg(f->args, long);
367 }else if(fl & FmtByte){
369 u = (uchar)va_arg(f->args, int);
371 u = (char)va_arg(f->args, int);
372 }else if(fl & FmtShort){
374 u = (ushort)va_arg(f->args, int);
376 u = (short)va_arg(f->args, int);
379 u = va_arg(f->args, uint);
381 u = va_arg(f->args, int);
383 conv = "0123456789abcdef";
395 conv = "0123456789ABCDEF";
406 if(!(fl & FmtUnsigned)){
407 if(isv && (vlong)vu < 0){
410 }else if(!isv && (long)u < 0){
415 p = buf + sizeof buf - 1;
421 if((fl & FmtComma) && n % 4 == 3){
432 if((fl & FmtComma) && n % 4 == 3){
444 for(w = f->prec; n < w && p > buf+3; n++)
446 if(neg || (fl & (FmtSign|FmtSpace)))
458 if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
459 for(w = f->width; n < w && p > buf+3; n++)
466 if(base == 16 || base == 8)
471 else if(fl & FmtSign)
473 else if(fl & FmtSpace)
475 f->flags &= ~FmtPrec;
476 return __fmtcpy(f, p + 1, n, n);
486 p = va_arg(f->args, void*);
488 *(vlong*)p = f->nfmt;
489 }else if(fl & FmtLong){
491 }else if(fl & FmtByte){
493 }else if(fl & FmtShort){
494 *(short*)p = f->nfmt;
506 f->flags |= FmtComma;
515 f->flags |= FmtSharp;
518 f->flags |= FmtSpace;
521 f->flags |= FmtUnsigned;
524 if(f->flags & FmtShort)
526 f->flags |= FmtShort;
529 f->flags |= FmtLDouble;
532 if(f->flags & FmtLong)
533 f->flags |= FmtVLong;
540 /* default error format */
550 __fmtcpy(f, (const void*)x, 3, 3);