Blame


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 */
3 e17e1a71 2006-05-22 devnull
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"
9 91c13e54 2004-02-29 devnull
10 91c13e54 2004-02-29 devnull /* format the output into f->to and return the number of characters fmted */
11 91c13e54 2004-02-29 devnull int
12 91c13e54 2004-02-29 devnull dofmt(Fmt *f, char *fmt)
13 91c13e54 2004-02-29 devnull {
14 91c13e54 2004-02-29 devnull Rune rune, *rt, *rs;
15 91c13e54 2004-02-29 devnull int r;
16 91c13e54 2004-02-29 devnull char *t, *s;
17 91c13e54 2004-02-29 devnull int n, nfmt;
18 91c13e54 2004-02-29 devnull
19 91c13e54 2004-02-29 devnull nfmt = f->nfmt;
20 91c13e54 2004-02-29 devnull for(;;){
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)
26 91c13e54 2004-02-29 devnull fmt++;
27 91c13e54 2004-02-29 devnull else{
28 91c13e54 2004-02-29 devnull fmt += chartorune(&rune, fmt);
29 91c13e54 2004-02-29 devnull r = rune;
30 91c13e54 2004-02-29 devnull }
31 91c13e54 2004-02-29 devnull FMTRCHAR(f, rt, rs, r);
32 91c13e54 2004-02-29 devnull }
33 91c13e54 2004-02-29 devnull fmt++;
34 91c13e54 2004-02-29 devnull f->nfmt += rt - (Rune *)f->to;
35 91c13e54 2004-02-29 devnull f->to = rt;
36 91c13e54 2004-02-29 devnull if(!r)
37 91c13e54 2004-02-29 devnull return f->nfmt - nfmt;
38 91c13e54 2004-02-29 devnull f->stop = rs;
39 91c13e54 2004-02-29 devnull }else{
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);
45 91c13e54 2004-02-29 devnull fmt++;
46 91c13e54 2004-02-29 devnull }else{
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;
52 91c13e54 2004-02-29 devnull else
53 91c13e54 2004-02-29 devnull return -1;
54 91c13e54 2004-02-29 devnull }
55 91c13e54 2004-02-29 devnull while(n--)
56 91c13e54 2004-02-29 devnull *t++ = *fmt++;
57 91c13e54 2004-02-29 devnull }
58 91c13e54 2004-02-29 devnull }
59 91c13e54 2004-02-29 devnull fmt++;
60 91c13e54 2004-02-29 devnull f->nfmt += t - (char *)f->to;
61 91c13e54 2004-02-29 devnull f->to = t;
62 91c13e54 2004-02-29 devnull if(!r)
63 91c13e54 2004-02-29 devnull return f->nfmt - nfmt;
64 91c13e54 2004-02-29 devnull f->stop = s;
65 91c13e54 2004-02-29 devnull }
66 91c13e54 2004-02-29 devnull
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;
70 91c13e54 2004-02-29 devnull }
71 91c13e54 2004-02-29 devnull }
72 91c13e54 2004-02-29 devnull
73 91c13e54 2004-02-29 devnull void *
74 91c13e54 2004-02-29 devnull __fmtflush(Fmt *f, void *t, int len)
75 91c13e54 2004-02-29 devnull {
76 91c13e54 2004-02-29 devnull if(f->runes)
77 91c13e54 2004-02-29 devnull f->nfmt += (Rune*)t - (Rune*)f->to;
78 91c13e54 2004-02-29 devnull else
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;
84 91c13e54 2004-02-29 devnull }
85 91c13e54 2004-02-29 devnull return f->to;
86 91c13e54 2004-02-29 devnull }
87 91c13e54 2004-02-29 devnull
88 91c13e54 2004-02-29 devnull /*
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)
91 91c13e54 2004-02-29 devnull */
92 91c13e54 2004-02-29 devnull int
93 91c13e54 2004-02-29 devnull __fmtpad(Fmt *f, int n)
94 91c13e54 2004-02-29 devnull {
95 91c13e54 2004-02-29 devnull char *t, *s;
96 91c13e54 2004-02-29 devnull int i;
97 91c13e54 2004-02-29 devnull
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;
105 91c13e54 2004-02-29 devnull }
106 91c13e54 2004-02-29 devnull
107 91c13e54 2004-02-29 devnull int
108 91c13e54 2004-02-29 devnull __rfmtpad(Fmt *f, int n)
109 91c13e54 2004-02-29 devnull {
110 91c13e54 2004-02-29 devnull Rune *t, *s;
111 91c13e54 2004-02-29 devnull int i;
112 91c13e54 2004-02-29 devnull
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;
120 91c13e54 2004-02-29 devnull }
121 91c13e54 2004-02-29 devnull
122 91c13e54 2004-02-29 devnull int
123 91c13e54 2004-02-29 devnull __fmtcpy(Fmt *f, const void *vm, int n, int sz)
124 91c13e54 2004-02-29 devnull {
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;
129 91c13e54 2004-02-29 devnull
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;
133 85231fd8 2006-05-21 devnull w = 0;
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)
146 91c13e54 2004-02-29 devnull m++;
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);
149 91c13e54 2004-02-29 devnull else
150 91c13e54 2004-02-29 devnull break;
151 91c13e54 2004-02-29 devnull FMTRCHAR(f, rt, rs, r);
152 91c13e54 2004-02-29 devnull }
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;
157 91c13e54 2004-02-29 devnull }else{
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)
165 91c13e54 2004-02-29 devnull m++;
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);
168 91c13e54 2004-02-29 devnull else
169 91c13e54 2004-02-29 devnull break;
170 91c13e54 2004-02-29 devnull FMTRUNE(f, t, s, r);
171 91c13e54 2004-02-29 devnull }
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;
176 91c13e54 2004-02-29 devnull }
177 91c13e54 2004-02-29 devnull return 0;
178 91c13e54 2004-02-29 devnull }
179 91c13e54 2004-02-29 devnull
180 91c13e54 2004-02-29 devnull int
181 91c13e54 2004-02-29 devnull __fmtrcpy(Fmt *f, const void *vm, int n)
182 91c13e54 2004-02-29 devnull {
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;
186 91c13e54 2004-02-29 devnull int w;
187 91c13e54 2004-02-29 devnull
188 91c13e54 2004-02-29 devnull m = (Rune*)vm;
189 91c13e54 2004-02-29 devnull fl = f->flags;
190 85231fd8 2006-05-21 devnull w = 0;
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;
206 91c13e54 2004-02-29 devnull }else{
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++){
212 91c13e54 2004-02-29 devnull r = *m;
213 91c13e54 2004-02-29 devnull FMTRUNE(f, t, s, r);
214 91c13e54 2004-02-29 devnull }
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;
219 91c13e54 2004-02-29 devnull }
220 91c13e54 2004-02-29 devnull return 0;
221 91c13e54 2004-02-29 devnull }
222 91c13e54 2004-02-29 devnull
223 91c13e54 2004-02-29 devnull /* fmt out one character */
224 91c13e54 2004-02-29 devnull int
225 91c13e54 2004-02-29 devnull __charfmt(Fmt *f)
226 91c13e54 2004-02-29 devnull {
227 91c13e54 2004-02-29 devnull char x[1];
228 91c13e54 2004-02-29 devnull
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);
232 91c13e54 2004-02-29 devnull }
233 91c13e54 2004-02-29 devnull
234 91c13e54 2004-02-29 devnull /* fmt out one rune */
235 91c13e54 2004-02-29 devnull int
236 91c13e54 2004-02-29 devnull __runefmt(Fmt *f)
237 91c13e54 2004-02-29 devnull {
238 91c13e54 2004-02-29 devnull Rune x[1];
239 91c13e54 2004-02-29 devnull
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);
242 91c13e54 2004-02-29 devnull }
243 91c13e54 2004-02-29 devnull
244 91c13e54 2004-02-29 devnull /* public helper routine: fmt out a null terminated string already in hand */
245 91c13e54 2004-02-29 devnull int
246 91c13e54 2004-02-29 devnull fmtstrcpy(Fmt *f, char *s)
247 91c13e54 2004-02-29 devnull {
248 3f1a2197 2004-12-26 devnull int i, j;
249 3f1a2197 2004-12-26 devnull
250 91c13e54 2004-02-29 devnull if(!s)
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
255 7bd73c7f 2006-06-25 devnull Rune r;
256 3f1a2197 2004-12-26 devnull i = 0;
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);
259 ab239cb5 2006-05-26 devnull #else
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)
263 ab239cb5 2006-05-26 devnull break;
264 ab239cb5 2006-05-26 devnull j = utfnlen(s, i); /* won't print partial at end */
265 ab239cb5 2006-05-26 devnull #endif
266 3f1a2197 2004-12-26 devnull return __fmtcpy(f, s, j, i);
267 91c13e54 2004-02-29 devnull }
268 91c13e54 2004-02-29 devnull return __fmtcpy(f, s, utflen(s), strlen(s));
269 91c13e54 2004-02-29 devnull }
270 91c13e54 2004-02-29 devnull
271 91c13e54 2004-02-29 devnull /* fmt out a null terminated utf string */
272 91c13e54 2004-02-29 devnull int
273 91c13e54 2004-02-29 devnull __strfmt(Fmt *f)
274 91c13e54 2004-02-29 devnull {
275 91c13e54 2004-02-29 devnull char *s;
276 91c13e54 2004-02-29 devnull
277 91c13e54 2004-02-29 devnull s = va_arg(f->args, char *);
278 91c13e54 2004-02-29 devnull return fmtstrcpy(f, s);
279 91c13e54 2004-02-29 devnull }
280 91c13e54 2004-02-29 devnull
281 91c13e54 2004-02-29 devnull /* public helper routine: fmt out a null terminated rune string already in hand */
282 91c13e54 2004-02-29 devnull int
283 91c13e54 2004-02-29 devnull fmtrunestrcpy(Fmt *f, Rune *s)
284 91c13e54 2004-02-29 devnull {
285 91c13e54 2004-02-29 devnull Rune *e;
286 91c13e54 2004-02-29 devnull int n, p;
287 91c13e54 2004-02-29 devnull
288 91c13e54 2004-02-29 devnull if(!s)
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)
295 91c13e54 2004-02-29 devnull break;
296 91c13e54 2004-02-29 devnull }else{
297 91c13e54 2004-02-29 devnull for(e = s; *e; e++)
298 91c13e54 2004-02-29 devnull ;
299 91c13e54 2004-02-29 devnull n = e - s;
300 91c13e54 2004-02-29 devnull }
301 91c13e54 2004-02-29 devnull return __fmtrcpy(f, s, n);
302 91c13e54 2004-02-29 devnull }
303 91c13e54 2004-02-29 devnull
304 91c13e54 2004-02-29 devnull /* fmt out a null terminated rune string */
305 91c13e54 2004-02-29 devnull int
306 91c13e54 2004-02-29 devnull __runesfmt(Fmt *f)
307 91c13e54 2004-02-29 devnull {
308 91c13e54 2004-02-29 devnull Rune *s;
309 91c13e54 2004-02-29 devnull
310 91c13e54 2004-02-29 devnull s = va_arg(f->args, Rune *);
311 91c13e54 2004-02-29 devnull return fmtrunestrcpy(f, s);
312 91c13e54 2004-02-29 devnull }
313 91c13e54 2004-02-29 devnull
314 91c13e54 2004-02-29 devnull /* fmt a % */
315 91c13e54 2004-02-29 devnull int
316 91c13e54 2004-02-29 devnull __percentfmt(Fmt *f)
317 91c13e54 2004-02-29 devnull {
318 91c13e54 2004-02-29 devnull Rune x[1];
319 91c13e54 2004-02-29 devnull
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);
323 91c13e54 2004-02-29 devnull }
324 91c13e54 2004-02-29 devnull
325 91c13e54 2004-02-29 devnull /* fmt an integer */
326 91c13e54 2004-02-29 devnull int
327 91c13e54 2004-02-29 devnull __ifmt(Fmt *f)
328 91c13e54 2004-02-29 devnull {
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;
337 91c13e54 2004-02-29 devnull
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;
341 91c13e54 2004-02-29 devnull vu = 0;
342 91c13e54 2004-02-29 devnull u = 0;
343 3f1a2197 2004-12-26 devnull #ifndef PLAN9PORT
344 91c13e54 2004-02-29 devnull /*
345 3f1a2197 2004-12-26 devnull * Unsigned verbs for ANSI C
346 91c13e54 2004-02-29 devnull */
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);
355 91c13e54 2004-02-29 devnull break;
356 91c13e54 2004-02-29 devnull }
357 3f1a2197 2004-12-26 devnull #endif
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);
366 91c13e54 2004-02-29 devnull else
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);
371 91c13e54 2004-02-29 devnull else
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);
376 91c13e54 2004-02-29 devnull else
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);
381 91c13e54 2004-02-29 devnull else
382 91c13e54 2004-02-29 devnull u = (short)va_arg(f->args, int);
383 91c13e54 2004-02-29 devnull }else{
384 91c13e54 2004-02-29 devnull if(fl & FmtUnsigned)
385 91c13e54 2004-02-29 devnull u = va_arg(f->args, uint);
386 91c13e54 2004-02-29 devnull else
387 91c13e54 2004-02-29 devnull u = va_arg(f->args, int);
388 91c13e54 2004-02-29 devnull }
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;
398 91c13e54 2004-02-29 devnull break;
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 = ":";
405 91c13e54 2004-02-29 devnull break;
406 91c13e54 2004-02-29 devnull case 'b':
407 91c13e54 2004-02-29 devnull base = 2;
408 85231fd8 2006-05-21 devnull thousands = ":";
409 91c13e54 2004-02-29 devnull break;
410 91c13e54 2004-02-29 devnull case 'o':
411 91c13e54 2004-02-29 devnull base = 8;
412 91c13e54 2004-02-29 devnull break;
413 91c13e54 2004-02-29 devnull default:
414 91c13e54 2004-02-29 devnull return -1;
415 91c13e54 2004-02-29 devnull }
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;
423 91c13e54 2004-02-29 devnull }
424 91c13e54 2004-02-29 devnull }
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-- = ',';
437 91c13e54 2004-02-29 devnull n++;
438 91c13e54 2004-02-29 devnull }
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);
444 85231fd8 2006-05-21 devnull }
445 91c13e54 2004-02-29 devnull *p-- = conv[i];
446 91c13e54 2004-02-29 devnull n++;
447 91c13e54 2004-02-29 devnull }
448 91c13e54 2004-02-29 devnull }else{
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-- = ',';
454 91c13e54 2004-02-29 devnull n++;
455 91c13e54 2004-02-29 devnull }
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);
461 85231fd8 2006-05-21 devnull }
462 91c13e54 2004-02-29 devnull *p-- = conv[i];
463 91c13e54 2004-02-29 devnull n++;
464 91c13e54 2004-02-29 devnull }
465 91c13e54 2004-02-29 devnull }
466 91c13e54 2004-02-29 devnull if(n == 0){
467 e17e1a71 2006-05-22 devnull /*
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
470 e17e1a71 2006-05-22 devnull *
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
474 e17e1a71 2006-05-22 devnull */
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';
477 e17e1a71 2006-05-22 devnull n = 1;
478 e17e1a71 2006-05-22 devnull if(fl & FmtApost)
479 e17e1a71 2006-05-22 devnull __needsep(&ndig, &grouping);
480 e17e1a71 2006-05-22 devnull }
481 fa325e9b 2020-01-10 cross
482 e17e1a71 2006-05-22 devnull /*
483 e17e1a71 2006-05-22 devnull * Zero values don't get 0x.
484 e17e1a71 2006-05-22 devnull */
485 e17e1a71 2006-05-22 devnull if(f->r == 'x' || f->r == 'X')
486 e17e1a71 2006-05-22 devnull fl &= ~FmtSharp;
487 91c13e54 2004-02-29 devnull }
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);
494 85231fd8 2006-05-21 devnull }
495 91c13e54 2004-02-29 devnull *p-- = '0';
496 85231fd8 2006-05-21 devnull }
497 91c13e54 2004-02-29 devnull if(neg || (fl & (FmtSign|FmtSpace)))
498 91c13e54 2004-02-29 devnull n++;
499 91c13e54 2004-02-29 devnull if(fl & FmtSharp){
500 91c13e54 2004-02-29 devnull if(base == 16)
501 91c13e54 2004-02-29 devnull n += 2;
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;
505 91c13e54 2004-02-29 devnull else
506 91c13e54 2004-02-29 devnull n++;
507 91c13e54 2004-02-29 devnull }
508 91c13e54 2004-02-29 devnull }
509 91c13e54 2004-02-29 devnull if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
510 85231fd8 2006-05-21 devnull w = 0;
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);
519 85231fd8 2006-05-21 devnull }
520 91c13e54 2004-02-29 devnull *p-- = '0';
521 85231fd8 2006-05-21 devnull }
522 85231fd8 2006-05-21 devnull f->flags &= ~FmtWidth;
523 91c13e54 2004-02-29 devnull }
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';
529 91c13e54 2004-02-29 devnull }
530 91c13e54 2004-02-29 devnull if(neg)
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);
538 91c13e54 2004-02-29 devnull }
539 91c13e54 2004-02-29 devnull
540 91c13e54 2004-02-29 devnull int
541 91c13e54 2004-02-29 devnull __countfmt(Fmt *f)
542 91c13e54 2004-02-29 devnull {
543 91c13e54 2004-02-29 devnull void *p;
544 91c13e54 2004-02-29 devnull ulong fl;
545 91c13e54 2004-02-29 devnull
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;
556 91c13e54 2004-02-29 devnull }else{
557 91c13e54 2004-02-29 devnull *(int*)p = f->nfmt;
558 91c13e54 2004-02-29 devnull }
559 91c13e54 2004-02-29 devnull return 0;
560 91c13e54 2004-02-29 devnull }
561 91c13e54 2004-02-29 devnull
562 91c13e54 2004-02-29 devnull int
563 91c13e54 2004-02-29 devnull __flagfmt(Fmt *f)
564 91c13e54 2004-02-29 devnull {
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;
568 91c13e54 2004-02-29 devnull break;
569 91c13e54 2004-02-29 devnull case '-':
570 91c13e54 2004-02-29 devnull f->flags |= FmtLeft;
571 91c13e54 2004-02-29 devnull break;
572 91c13e54 2004-02-29 devnull case '+':
573 91c13e54 2004-02-29 devnull f->flags |= FmtSign;
574 91c13e54 2004-02-29 devnull break;
575 91c13e54 2004-02-29 devnull case '#':
576 91c13e54 2004-02-29 devnull f->flags |= FmtSharp;
577 91c13e54 2004-02-29 devnull break;
578 85231fd8 2006-05-21 devnull case '\'':
579 85231fd8 2006-05-21 devnull f->flags |= FmtApost;
580 85231fd8 2006-05-21 devnull break;
581 91c13e54 2004-02-29 devnull case ' ':
582 91c13e54 2004-02-29 devnull f->flags |= FmtSpace;
583 91c13e54 2004-02-29 devnull break;
584 91c13e54 2004-02-29 devnull case 'u':
585 91c13e54 2004-02-29 devnull f->flags |= FmtUnsigned;
586 91c13e54 2004-02-29 devnull break;
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;
591 91c13e54 2004-02-29 devnull break;
592 91c13e54 2004-02-29 devnull case 'L':
593 91c13e54 2004-02-29 devnull f->flags |= FmtLDouble;
594 91c13e54 2004-02-29 devnull break;
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;
599 91c13e54 2004-02-29 devnull break;
600 91c13e54 2004-02-29 devnull }
601 91c13e54 2004-02-29 devnull return 1;
602 91c13e54 2004-02-29 devnull }
603 91c13e54 2004-02-29 devnull
604 91c13e54 2004-02-29 devnull /* default error format */
605 91c13e54 2004-02-29 devnull int
606 91c13e54 2004-02-29 devnull __badfmt(Fmt *f)
607 91c13e54 2004-02-29 devnull {
608 0cadb430 2009-09-11 russcox char x[2+UTFmax];
609 0cadb430 2009-09-11 russcox int n;
610 91c13e54 2004-02-29 devnull
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;
617 91c13e54 2004-02-29 devnull }