Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/unix/u9fs/doprint.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	<plan9.h>
2
 
3
#define lock(x)
4
#define unlock(x)
5
 
6
enum
7
{
8
	IDIGIT	= 40,
9
	MAXCONV	= 40,
10
	FDIGIT	= 30,
11
	FDEFLT	= 6,
12
	NONE	= -1000,
13
	MAXFMT	= 512,
14
 
15
	FPLUS	= 1<<0,
16
	FMINUS	= 1<<1,
17
	FSHARP	= 1<<2,
18
	FLONG	= 1<<3,
19
	FUNSIGN	= 1<<5,
20
	FVLONG	= 1<<6,
21
	FPOINTER= 1<<7
22
};
23
 
24
int	printcol;
25
 
26
static struct
27
{
28
/*	Lock;	*/
29
	int	convcount;
30
	char	index[MAXFMT];
31
	int	(*conv[MAXCONV])(va_list*, Fconv*);
32
} fmtalloc;
33
 
34
static	int	noconv(va_list*, Fconv*);
35
static	int	flags(va_list*, Fconv*);
36
 
37
static	int	cconv(va_list*, Fconv*);
38
static	int	sconv(va_list*, Fconv*);
39
static	int	percent(va_list*, Fconv*);
40
static	int	column(va_list*, Fconv*);
41
 
42
extern	int	numbconv(va_list*, Fconv*);
43
 
44
 
45
static	void
46
initfmt(void)
47
{
48
	int cc;
49
 
50
	lock(&fmtalloc);
51
	if(fmtalloc.convcount <= 0) {
52
		cc = 0;
53
		fmtalloc.conv[cc] = noconv;
54
		cc++;
55
 
56
		fmtalloc.conv[cc] = flags;
57
		fmtalloc.index['+'] = cc;
58
		fmtalloc.index['-'] = cc;
59
		fmtalloc.index['#'] = cc;
60
		fmtalloc.index['l'] = cc;
61
		fmtalloc.index['u'] = cc;
62
		cc++;
63
 
64
		fmtalloc.conv[cc] = numbconv;
65
		fmtalloc.index['d'] = cc;
66
		fmtalloc.index['o'] = cc;
67
		fmtalloc.index['x'] = cc;
68
		fmtalloc.index['X'] = cc;
69
		fmtalloc.index['p'] = cc;
70
		cc++;
71
 
72
 
73
		fmtalloc.conv[cc] = cconv;
74
		fmtalloc.index['c'] = cc;
75
		fmtalloc.index['C'] = cc;
76
		cc++;
77
 
78
		fmtalloc.conv[cc] = sconv;
79
		fmtalloc.index['s'] = cc;
80
		fmtalloc.index['S'] = cc;
81
		cc++;
82
 
83
		fmtalloc.conv[cc] = percent;
84
		fmtalloc.index['%'] = cc;
85
		cc++;
86
 
87
		fmtalloc.conv[cc] = column;
88
		fmtalloc.index['|'] = cc;
89
		cc++;
90
 
91
		fmtalloc.convcount = cc;
92
	}
93
	unlock(&fmtalloc);
94
}
95
 
96
int
97
fmtinstall(int c, int (*f)(va_list*, Fconv*))
98
{
99
 
100
	if(fmtalloc.convcount <= 0)
101
		initfmt();
102
 
103
	lock(&fmtalloc);
104
	if(c < 0 || c >= MAXFMT) {
105
		unlock(&fmtalloc);
106
		return -1;
107
	}
108
	if(fmtalloc.convcount >= MAXCONV) {
109
		unlock(&fmtalloc);
110
		return -1;
111
	}
112
	fmtalloc.conv[fmtalloc.convcount] = f;
113
	fmtalloc.index[c] = fmtalloc.convcount;
114
	fmtalloc.convcount++;
115
 
116
	unlock(&fmtalloc);
117
	return 0;
118
}
119
 
120
static	void
121
pchar(Rune c, Fconv *fp)
122
{
123
	int n;
124
 
125
	n = fp->eout - fp->out;
126
	if(n > 0) {
127
		if(c < Runeself) {
128
			*fp->out++ = c;
129
			return;
130
		}
131
		if(n >= UTFmax || n >= runelen(c)) {
132
			n = runetochar(fp->out, &c);
133
			fp->out += n;
134
			return;
135
		}
136
		fp->eout = fp->out;
137
	}
138
}
139
 
140
char*
141
doprint(char *s, char *es, char *fmt, va_list *argp)
142
{
143
	int n, c;
144
	Rune rune;
145
	Fconv local;
146
 
147
	if(fmtalloc.convcount <= 0)
148
		initfmt();
149
 
150
	if(s >= es)
151
		return s;
152
	local.out = s;
153
	local.eout = es-1;
154
 
155
loop:
156
	c = *fmt & 0xff;
157
	if(c >= Runeself) {
158
		n = chartorune(&rune, fmt);
159
		fmt += n;
160
		c = rune;
161
	} else
162
		fmt++;
163
	switch(c) {
164
	case 0:
165
		*local.out = 0;
166
		return local.out;
167
 
168
	default:
169
		printcol++;
170
		goto common;
171
 
172
	case '\n':
173
		printcol = 0;
174
		goto common;
175
 
176
	case '\t':
177
		printcol = (printcol+8) & ~7;
178
		goto common;
179
 
180
	common:
181
		pchar(c, &local);
182
		goto loop;
183
 
184
	case '%':
185
		break;
186
	}
187
	local.f1 = NONE;
188
	local.f2 = NONE;
189
	local.f3 = 0;
190
 
191
	/*
192
	 * read one of the following
193
	 *	1. number, => f1, f2 in order.
194
	 *	2. '*' same as number (from args)
195
	 *	3. '.' ignored (separates numbers)
196
	 *	4. flag => f3
197
	 *	5. verb and terminate
198
	 */
199
l0:
200
	c = *fmt & 0xff;
201
	if(c >= Runeself) {
202
		n = chartorune(&rune, fmt);
203
		fmt += n;
204
		c = rune;
205
	} else
206
		fmt++;
207
 
208
l1:
209
	if(c == 0) {
210
		fmt--;
211
		goto loop;
212
	}
213
	if(c == '.') {
214
		if(local.f1 == NONE)
215
			local.f1 = 0;
216
		local.f2 = 0;
217
		goto l0;
218
	}
219
	if((c >= '1' && c <= '9') ||
220
	   (c == '0' && local.f1 != NONE)) {	/* '0' is a digit for f2 */
221
		n = 0;
222
		while(c >= '0' && c <= '9') {
223
			n = n*10 + c-'0';
224
			c = *fmt++;
225
		}
226
		if(local.f1 == NONE)
227
			local.f1 = n;
228
		else
229
			local.f2 = n;
230
		goto l1;
231
	}
232
	if(c == '*') {
233
		n = va_arg(*argp, int);
234
		if(local.f1 == NONE)
235
			local.f1 = n;
236
		else
237
			local.f2 = n;
238
		goto l0;
239
	}
240
	n = 0;
241
	if(c >= 0 && c < MAXFMT)
242
		n = fmtalloc.index[c];
243
	local.chr = c;
244
	n = (*fmtalloc.conv[n])(argp, &local);
245
	if(n < 0) {
246
		local.f3 |= -n;
247
		goto l0;
248
	}
249
	goto loop;
250
}
251
 
252
int
253
numbconv(va_list *arg, Fconv *fp)
254
{
255
	char s[IDIGIT];
256
	int i, f, n, b, ucase;
257
	long v;
258
	vlong vl;
259
 
260
	SET(v);
261
	SET(vl);
262
 
263
	ucase = 0;
264
	b = fp->chr;
265
	switch(fp->chr) {
266
	case 'u':
267
		fp->f3 |= FUNSIGN;
268
	case 'd':
269
		b = 10;
270
		break;
271
 
272
	case 'b':
273
		b = 2;
274
		break;
275
 
276
	case 'o':
277
		b = 8;
278
		break;
279
 
280
	case 'X':
281
		ucase = 1;
282
	case 'x':
283
		b = 16;
284
		break;
285
	case 'p':
286
		fp->f3 |= FPOINTER|FUNSIGN;
287
		b = 16;
288
		break;
289
	}
290
 
291
	f = 0;
292
	switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) {
293
	case FVLONG|FLONG:
294
		vl = va_arg(*arg, vlong);
295
		break;
296
 
297
	case FUNSIGN|FVLONG|FLONG:
298
		vl = va_arg(*arg, uvlong);
299
		break;
300
 
301
	case FUNSIGN|FPOINTER:
302
		v = (ulong)va_arg(*arg, void*);
303
		break;
304
 
305
	case FLONG:
306
		v = va_arg(*arg, long);
307
		break;
308
 
309
	case FUNSIGN|FLONG:
310
		v = va_arg(*arg, ulong);
311
		break;
312
 
313
	default:
314
		v = va_arg(*arg, int);
315
		break;
316
 
317
	case FUNSIGN:
318
		v = va_arg(*arg, unsigned);
319
		break;
320
	}
321
	if(fp->f3 & FVLONG) {
322
		if(!(fp->f3 & FUNSIGN) && vl < 0) {
323
			vl = -vl;
324
			f = 1;
325
		}
326
	} else {
327
		if(!(fp->f3 & FUNSIGN) && v < 0) {
328
			v = -v;
329
			f = 1;
330
		}
331
	}
332
	s[IDIGIT-1] = 0;
333
	for(i = IDIGIT-2;; i--) {
334
		if(fp->f3 & FVLONG)
335
			n = (uvlong)vl % b;
336
		else
337
			n = (ulong)v % b;
338
		n += '0';
339
		if(n > '9') {
340
			n += 'a' - ('9'+1);
341
			if(ucase)
342
				n += 'A'-'a';
343
		}
344
		s[i] = n;
345
		if(i < 2)
346
			break;
347
		if(fp->f3 & FVLONG)
348
			vl = (uvlong)vl / b;
349
		else
350
			v = (ulong)v / b;
351
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
352
			continue;
353
		if(fp->f3 & FVLONG) {
354
			if(vl <= 0)
355
				break;
356
			continue;
357
		}
358
		if(v <= 0)
359
			break;
360
	}
361
 
362
	if(fp->f3 & FSHARP) {
363
		if(b == 8 && s[i] != '0')
364
			s[--i] = '0';
365
		if(b == 16) {
366
			if(ucase)
367
				s[--i] = 'X';
368
			else
369
				s[--i] = 'x';
370
			s[--i] = '0';
371
		}
372
	}
373
	if(f)
374
		s[--i] = '-';
375
	else if(fp->f3 & FPLUS)
376
		s[--i] = '+';
377
 
378
	fp->f2 = NONE;
379
	strconv(s+i, fp);
380
	return 0;
381
}
382
 
383
void
384
Strconv(Rune *s, Fconv *fp)
385
{
386
	int n, c;
387
 
388
	if(fp->f3 & FMINUS)
389
		fp->f1 = -fp->f1;
390
	n = 0;
391
	if(fp->f1 != NONE && fp->f1 >= 0) {
392
		for(; s[n]; n++)
393
			;
394
		while(n < fp->f1) {
395
			pchar(' ', fp);
396
			printcol++;
397
			n++;
398
		}
399
	}
400
	for(;;) {
401
		c = *s++;
402
		if(c == 0)
403
			break;
404
		n++;
405
		if(fp->f2 == NONE || fp->f2 > 0) {
406
			pchar(c, fp);
407
			if(fp->f2 != NONE)
408
				fp->f2--;
409
			switch(c) {
410
			default:
411
				printcol++;
412
				break;
413
			case '\n':
414
				printcol = 0;
415
				break;
416
			case '\t':
417
				printcol = (printcol+8) & ~7;
418
				break;
419
			}
420
		}
421
	}
422
	if(fp->f1 != NONE && fp->f1 < 0) {
423
		fp->f1 = -fp->f1;
424
		while(n < fp->f1) {
425
			pchar(' ', fp);
426
			printcol++;
427
			n++;
428
		}
429
	}
430
}
431
 
432
void
433
strconv(char *s, Fconv *fp)
434
{
435
	int n, c, i;
436
	Rune rune;
437
 
438
	if(fp->f3 & FMINUS)
439
		fp->f1 = -fp->f1;
440
	n = 0;
441
	if(fp->f1 != NONE && fp->f1 >= 0) {
442
		n = utflen(s);
443
		while(n < fp->f1) {
444
			pchar(' ', fp);
445
			printcol++;
446
			n++;
447
		}
448
	}
449
	for(;;) {
450
		c = *s & 0xff;
451
		if(c >= Runeself) {
452
			i = chartorune(&rune, s);
453
			s += i;
454
			c = rune;
455
		} else
456
			s++;
457
		if(c == 0)
458
			break;
459
		n++;
460
		if(fp->f2 == NONE || fp->f2 > 0) {
461
			pchar(c, fp);
462
			if(fp->f2 != NONE)
463
				fp->f2--;
464
			switch(c) {
465
			default:
466
				printcol++;
467
				break;
468
			case '\n':
469
				printcol = 0;
470
				break;
471
			case '\t':
472
				printcol = (printcol+8) & ~7;
473
				break;
474
			}
475
		}
476
	}
477
	if(fp->f1 != NONE && fp->f1 < 0) {
478
		fp->f1 = -fp->f1;
479
		while(n < fp->f1) {
480
			pchar(' ', fp);
481
			printcol++;
482
			n++;
483
		}
484
	}
485
}
486
 
487
static int
488
noconv(va_list *va, Fconv *fp)
489
{
490
	char s[10];
491
 
492
	USED(va);
493
	s[0] = '*';
494
	s[1] = fp->chr;
495
	s[2] = '*';
496
	s[3] = 0;
497
	fp->f1 = 0;
498
	fp->f2 = NONE;
499
	fp->f3 = 0;
500
	strconv(s, fp);
501
	return 0;
502
}
503
 
504
static int
505
cconv(va_list *arg, Fconv *fp)
506
{
507
	char s[10];
508
	Rune rune;
509
 
510
	rune = va_arg(*arg, int);
511
	if(fp->chr == 'c')
512
		rune &= 0xff;
513
	s[runetochar(s, &rune)] = 0;
514
 
515
	fp->f2 = NONE;
516
	strconv(s, fp);
517
	return 0;
518
}
519
 
520
static Rune null[] = { L'<', L'n', L'u', L'l', L'l', L'>', L'\0' };
521
 
522
static	int
523
sconv(va_list *arg, Fconv *fp)
524
{
525
	char *s;
526
	Rune *r;
527
 
528
	if(fp->chr == 's') {
529
		s = va_arg(*arg, char*);
530
		if(s == 0)
531
			s = "<null>";
532
		strconv(s, fp);
533
	} else {
534
		r = va_arg(*arg, Rune*);
535
		if(r == 0)
536
			r = null;
537
		Strconv(r, fp);
538
	}
539
	return 0;
540
}
541
 
542
static	int
543
percent(va_list *va, Fconv *fp)
544
{
545
	USED(va);
546
 
547
	pchar('%', fp);
548
	printcol++;
549
	return 0;
550
}
551
 
552
static	int
553
column(va_list *arg, Fconv *fp)
554
{
555
	int col, pc;
556
 
557
	col = va_arg(*arg, int);
558
	while(printcol < col) {
559
		pc = (printcol+8) & ~7;
560
		if(pc <= col) {
561
			pchar('\t', fp);
562
			printcol = pc;
563
		} else {
564
			pchar(' ', fp);
565
			printcol++;
566
		}
567
	}
568
	return 0;
569
}
570
 
571
static int
572
flags(va_list *va, Fconv *fp)
573
{
574
	int f;
575
 
576
	USED(va);
577
	f = 0;
578
	switch(fp->chr) {
579
	case '+':
580
		f = FPLUS;
581
		break;
582
 
583
	case '-':
584
		f = FMINUS;
585
		break;
586
 
587
	case '#':
588
		f = FSHARP;
589
		break;
590
 
591
	case 'l':
592
		f = FLONG;
593
		if(fp->f3 & FLONG)
594
			f = FVLONG;
595
		break;
596
 
597
	case 'u':
598
		f = FUNSIGN;
599
		break;
600
	}
601
	return -f;
602
}
603
 
604
/*
605
 * This code is superseded by the more accurate (but more complex)
606
 * algorithm in fltconv.c and dtoa.c.  Uncomment this routine to avoid
607
 * using the more complex code.
608
 *
609
 */
610