Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include "fmtdef.h"
4
 
5
/* format the output into f->to and return the number of characters fmted  */
6
int
7
dofmt(Fmt *f, char *fmt)
8
{
9
	Rune rune, *rt, *rs;
10
	int r;
11
	char *t, *s;
12
	int n, nfmt;
13
 
14
	nfmt = f->nfmt;
15
	for(;;){
16
		if(f->runes){
17
			rt = (Rune*)f->to;
18
			rs = (Rune*)f->stop;
19
			while((r = *(uchar*)fmt) && r != '%'){
20
				if(r < Runeself)
21
					fmt++;
22
				else{
23
					fmt += chartorune(&rune, fmt);
24
					r = rune;
25
				}
26
				FMTRCHAR(f, rt, rs, r);
27
			}
28
			fmt++;
29
			f->nfmt += rt - (Rune *)f->to;
30
			f->to = rt;
31
			if(!r)
32
				return f->nfmt - nfmt;
33
			f->stop = rs;
34
		}else{
35
			t = (char*)f->to;
36
			s = (char*)f->stop;
37
			while((r = *(uchar*)fmt) && r != '%'){
38
				if(r < Runeself){
39
					FMTCHAR(f, t, s, r);
40
					fmt++;
41
				}else{
42
					n = chartorune(&rune, fmt);
43
					if(t + n > s){
44
						t = (char*)__fmtflush(f, t, n);
45
						if(t != nil)
46
							s = (char*)f->stop;
47
						else
48
							return -1;
49
					}
50
					while(n--)
51
						*t++ = *fmt++;
52
				}
53
			}
54
			fmt++;
55
			f->nfmt += t - (char *)f->to;
56
			f->to = t;
57
			if(!r)
58
				return f->nfmt - nfmt;
59
			f->stop = s;
60
		}
61
 
62
		fmt = (char*)__fmtdispatch(f, fmt, 0);
63
		if(fmt == nil)
64
			return -1;
65
	}
66
}
67
 
68
void *
69
__fmtflush(Fmt *f, void *t, int len)
70
{
71
	if(f->runes)
72
		f->nfmt += (Rune*)t - (Rune*)f->to;
73
	else
74
		f->nfmt += (char*)t - (char *)f->to;
75
	f->to = t;
76
	if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
77
		f->stop = f->to;
78
		return nil;
79
	}
80
	return f->to;
81
}
82
 
83
/*
84
 * put a formatted block of memory sz bytes long of n runes into the output buffer,
85
 * left/right justified in a field of at least f->width charactes
86
 */
87
int
88
__fmtpad(Fmt *f, int n)
89
{
90
	char *t, *s;
91
	int i;
92
 
93
	t = (char*)f->to;
94
	s = (char*)f->stop;
95
	for(i = 0; i < n; i++)
96
		FMTCHAR(f, t, s, ' ');
97
	f->nfmt += t - (char *)f->to;
98
	f->to = t;
99
	return 0;
100
}
101
 
102
int
103
__rfmtpad(Fmt *f, int n)
104
{
105
	Rune *t, *s;
106
	int i;
107
 
108
	t = (Rune*)f->to;
109
	s = (Rune*)f->stop;
110
	for(i = 0; i < n; i++)
111
		FMTRCHAR(f, t, s, ' ');
112
	f->nfmt += t - (Rune *)f->to;
113
	f->to = t;
114
	return 0;
115
}
116
 
117
int
118
__fmtcpy(Fmt *f, const void *vm, int n, int sz)
119
{
120
	Rune *rt, *rs, r;
121
	char *t, *s, *m, *me;
122
	ulong fl;
123
	int nc, w;
124
 
125
	m = (char*)vm;
126
	me = m + sz;
127
	w = f->width;
128
	fl = f->flags;
129
	if((fl & FmtPrec) && n > f->prec)
130
		n = f->prec;
131
	if(f->runes){
132
		if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
133
			return -1;
134
		rt = (Rune*)f->to;
135
		rs = (Rune*)f->stop;
136
		for(nc = n; nc > 0; nc--){
137
			r = *(uchar*)m;
138
			if(r < Runeself)
139
				m++;
140
			else if((me - m) >= UTFmax || fullrune(m, me-m))
141
				m += chartorune(&r, m);
142
			else
143
				break;
144
			FMTRCHAR(f, rt, rs, r);
145
		}
146
		f->nfmt += rt - (Rune *)f->to;
147
		f->to = rt;
148
		if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
149
			return -1;
150
	}else{
151
		if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
152
			return -1;
153
		t = (char*)f->to;
154
		s = (char*)f->stop;
155
		for(nc = n; nc > 0; nc--){
156
			r = *(uchar*)m;
157
			if(r < Runeself)
158
				m++;
159
			else if((me - m) >= UTFmax || fullrune(m, me-m))
160
				m += chartorune(&r, m);
161
			else
162
				break;
163
			FMTRUNE(f, t, s, r);
164
		}
165
		f->nfmt += t - (char *)f->to;
166
		f->to = t;
167
		if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
168
			return -1;
169
	}
170
	return 0;
171
}
172
 
173
int
174
__fmtrcpy(Fmt *f, const void *vm, int n)
175
{
176
	Rune r, *m, *me, *rt, *rs;
177
	char *t, *s;
178
	ulong fl;
179
	int w;
180
 
181
	m = (Rune*)vm;
182
	w = f->width;
183
	fl = f->flags;
184
	if((fl & FmtPrec) && n > f->prec)
185
		n = f->prec;
186
	if(f->runes){
187
		if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
188
			return -1;
189
		rt = (Rune*)f->to;
190
		rs = (Rune*)f->stop;
191
		for(me = m + n; m < me; m++)
192
			FMTRCHAR(f, rt, rs, *m);
193
		f->nfmt += rt - (Rune *)f->to;
194
		f->to = rt;
195
		if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
196
			return -1;
197
	}else{
198
		if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
199
			return -1;
200
		t = (char*)f->to;
201
		s = (char*)f->stop;
202
		for(me = m + n; m < me; m++){
203
			r = *m;
204
			FMTRUNE(f, t, s, r);
205
		}
206
		f->nfmt += t - (char *)f->to;
207
		f->to = t;
208
		if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
209
			return -1;
210
	}
211
	return 0;
212
}
213
 
214
/* fmt out one character */
215
int
216
__charfmt(Fmt *f)
217
{
218
	char x[1];
219
 
220
	x[0] = va_arg(f->args, int);
221
	f->prec = 1;
222
	return __fmtcpy(f, (const char*)x, 1, 1);
223
}
224
 
225
/* fmt out one rune */
226
int
227
__runefmt(Fmt *f)
228
{
229
	Rune x[1];
230
 
231
	x[0] = va_arg(f->args, int);
232
	return __fmtrcpy(f, (const void*)x, 1);
233
}
234
 
235
/* public helper routine: fmt out a null terminated string already in hand */
236
int
237
fmtstrcpy(Fmt *f, char *s)
238
{
239
	int i, j;
240
	Rune r;
241
 
242
	if(!s)
243
		return __fmtcpy(f, "<nil>", 5, 5);
244
	/* if precision is specified, make sure we don't wander off the end */
245
	if(f->flags & FmtPrec){
246
		i = 0;
247
		for(j=0; j<f->prec && s[i]; j++)
248
			i += chartorune(&r, s+i);
249
		return __fmtcpy(f, s, j, i);
250
	}
251
	return __fmtcpy(f, s, utflen(s), strlen(s));
252
}
253
 
254
/* fmt out a null terminated utf string */
255
int
256
__strfmt(Fmt *f)
257
{
258
	char *s;
259
 
260
	s = va_arg(f->args, char *);
261
	return fmtstrcpy(f, s);
262
}
263
 
264
/* public helper routine: fmt out a null terminated rune string already in hand */
265
int
266
fmtrunestrcpy(Fmt *f, Rune *s)
267
{
268
	Rune *e;
269
	int n, p;
270
 
271
	if(!s)
272
		return __fmtcpy(f, "<nil>", 5, 5);
273
	/* if precision is specified, make sure we don't wander off the end */
274
	if(f->flags & FmtPrec){
275
		p = f->prec;
276
		for(n = 0; n < p; n++)
277
			if(s[n] == 0)
278
				break;
279
	}else{
280
		for(e = s; *e; e++)
281
			;
282
		n = e - s;
283
	}
284
	return __fmtrcpy(f, s, n);
285
}
286
 
287
/* fmt out a null terminated rune string */
288
int
289
__runesfmt(Fmt *f)
290
{
291
	Rune *s;
292
 
293
	s = va_arg(f->args, Rune *);
294
	return fmtrunestrcpy(f, s);
295
}
296
 
297
/* fmt a % */
298
int
299
__percentfmt(Fmt *f)
300
{
301
	Rune x[1];
302
 
303
	x[0] = f->r;
304
	f->prec = 1;
305
	return __fmtrcpy(f, (const void*)x, 1);
306
}
307
 
308
/* fmt an integer */
309
int
310
__ifmt(Fmt *f)
311
{
312
	char buf[70], *p, *conv;
313
	uvlong vu;
314
	ulong u;
315
	int neg, base, i, n, fl, w, isv;
316
 
317
	neg = 0;
318
	fl = f->flags;
319
	isv = 0;
320
	vu = 0;
321
	u = 0;
322
	/*
323
	 * Unsigned verbs for ANSI C
324
	 */
325
	switch(f->r){
326
	case 'x':
327
	case 'X':
328
	case 'o':
329
	case 'u':
330
	case 'p':
331
		fl |= FmtUnsigned;
332
		fl &= ~(FmtSign|FmtSpace);
333
		break;
334
	}
335
	if(f->r == 'p'){
336
		if(sizeof(void*) == sizeof(uvlong)){
337
			isv = 1;
338
			vu = (uvlong)va_arg(f->args, uvlong);
339
		}else
340
			u = (ulong)va_arg(f->args, ulong);
341
		f->r = 'x';
342
		fl |= FmtUnsigned;
343
	}else if(fl & FmtVLong){
344
		isv = 1;
345
		if(fl & FmtUnsigned)
346
			vu = va_arg(f->args, uvlong);
347
		else
348
			vu = va_arg(f->args, vlong);
349
	}else if(fl & FmtLong){
350
		if(fl & FmtUnsigned)
351
			u = va_arg(f->args, ulong);
352
		else
353
			u = va_arg(f->args, long);
354
	}else if(fl & FmtByte){
355
		if(fl & FmtUnsigned)
356
			u = (uchar)va_arg(f->args, int);
357
		else
358
			u = (char)va_arg(f->args, int);
359
	}else if(fl & FmtShort){
360
		if(fl & FmtUnsigned)
361
			u = (ushort)va_arg(f->args, int);
362
		else
363
			u = (short)va_arg(f->args, int);
364
	}else{
365
		if(fl & FmtUnsigned)
366
			u = va_arg(f->args, uint);
367
		else
368
			u = va_arg(f->args, int);
369
	}
370
	conv = "0123456789abcdef";
371
	switch(f->r){
372
	case 'd':
373
	case 'i':
374
	case 'u':
375
		base = 10;
376
		break;
377
	case 'x':
378
		base = 16;
379
		break;
380
	case 'X':
381
		base = 16;
382
		conv = "0123456789ABCDEF";
383
		break;
384
	case 'b':
385
		base = 2;
386
		break;
387
	case 'o':
388
		base = 8;
389
		break;
390
	default:
391
		return -1;
392
	}
393
	if(!(fl & FmtUnsigned)){
394
		if(isv && (vlong)vu < 0){
395
			vu = -(vlong)vu;
396
			neg = 1;
397
		}else if(!isv && (long)u < 0){
398
			u = -(long)u;
399
			neg = 1;
400
		}
401
	}
402
	p = buf + sizeof buf - 1;
403
	n = 0;
404
	if(isv){
405
		while(vu){
406
			i = vu % base;
407
			vu /= base;
408
			if((fl & FmtComma) && n % 4 == 3){
409
				*p-- = ',';
410
				n++;
411
			}
412
			*p-- = conv[i];
413
			n++;
414
		}
415
	}else{
416
		while(u){
417
			i = u % base;
418
			u /= base;
419
			if((fl & FmtComma) && n % 4 == 3){
420
				*p-- = ',';
421
				n++;
422
			}
423
			*p-- = conv[i];
424
			n++;
425
		}
426
	}
427
	if(n == 0){
428
		*p-- = '0';
429
		n = 1;
430
	}
431
	for(w = f->prec; n < w && p > buf+3; n++)
432
		*p-- = '0';
433
	if(neg || (fl & (FmtSign|FmtSpace)))
434
		n++;
435
	if(fl & FmtSharp){
436
		if(base == 16)
437
			n += 2;
438
		else if(base == 8){
439
			if(p[1] == '0')
440
				fl &= ~FmtSharp;
441
			else
442
				n++;
443
		}
444
	}
445
	if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
446
		for(w = f->width; n < w && p > buf+3; n++)
447
			*p-- = '0';
448
		f->width = 0;
449
	}
450
	if(fl & FmtSharp){
451
		if(base == 16)
452
			*p-- = f->r;
453
		if(base == 16 || base == 8)
454
			*p-- = '0';
455
	}
456
	if(neg)
457
		*p-- = '-';
458
	else if(fl & FmtSign)
459
		*p-- = '+';
460
	else if(fl & FmtSpace)
461
		*p-- = ' ';
462
	f->flags &= ~FmtPrec;
463
	return __fmtcpy(f, p + 1, n, n);
464
}
465
 
466
int
467
__countfmt(Fmt *f)
468
{
469
	void *p;
470
	ulong fl;
471
 
472
	fl = f->flags;
473
	p = va_arg(f->args, void*);
474
	if(fl & FmtVLong){
475
		*(vlong*)p = f->nfmt;
476
	}else if(fl & FmtLong){
477
		*(long*)p = f->nfmt;
478
	}else if(fl & FmtByte){
479
		*(char*)p = f->nfmt;
480
	}else if(fl & FmtShort){
481
		*(short*)p = f->nfmt;
482
	}else{
483
		*(int*)p = f->nfmt;
484
	}
485
	return 0;
486
}
487
 
488
int
489
__flagfmt(Fmt *f)
490
{
491
	switch(f->r){
492
	case ',':
493
		f->flags |= FmtComma;
494
		break;
495
	case '-':
496
		f->flags |= FmtLeft;
497
		break;
498
	case '+':
499
		f->flags |= FmtSign;
500
		break;
501
	case '#':
502
		f->flags |= FmtSharp;
503
		break;
504
	case ' ':
505
		f->flags |= FmtSpace;
506
		break;
507
	case 'u':
508
		f->flags |= FmtUnsigned;
509
		break;
510
	case 'h':
511
		if(f->flags & FmtShort)
512
			f->flags |= FmtByte;
513
		f->flags |= FmtShort;
514
		break;
515
	case 'L':
516
		f->flags |= FmtLDouble;
517
		break;
518
	case 'l':
519
		if(f->flags & FmtLong)
520
			f->flags |= FmtVLong;
521
		f->flags |= FmtLong;
522
		break;
523
	}
524
	return 1;
525
}
526
 
527
/* default error format */
528
int
529
__badfmt(Fmt *f)
530
{
531
	char x[3];
532
 
533
	x[0] = '%';
534
	x[1] = f->r;
535
	x[2] = '%';
536
	f->prec = 3;
537
	__fmtcpy(f, (const void*)x, 3, 3);
538
	return 0;
539
}