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_posix/sys/src/cmd/unix/drawterm/libc/fmt.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 <u.h>
2
#include <libc.h>
3
#include "fmtdef.h"
4
 
5
enum
6
{
7
	Maxfmt = 64
8
};
9
 
10
typedef struct Convfmt Convfmt;
11
struct Convfmt
12
{
13
	int	c;
14
	volatile	Fmts	fmt;	/* for spin lock in fmtfmt; avoids race due to write order */
15
};
16
 
17
struct
18
{
19
	/* lock by calling __fmtlock, __fmtunlock */
20
	int	nfmt;
21
	Convfmt	fmt[Maxfmt];
22
} fmtalloc;
23
 
24
static Convfmt knownfmt[] = {
25
	' ',	__flagfmt,
26
	'#',	__flagfmt,
27
	'%',	__percentfmt,
28
	'+',	__flagfmt,
29
	',',	__flagfmt,
30
	'-',	__flagfmt,
31
	'C',	__runefmt,	/* Plan 9 addition */
32
	'E',	__efgfmt,
33
#ifndef PLAN9PORT
34
	'F',	__efgfmt,	/* ANSI only */
35
#endif
36
	'G',	__efgfmt,
37
#ifndef PLAN9PORT
38
	'L',	__flagfmt,	/* ANSI only */
39
#endif
40
	'S',	__runesfmt,	/* Plan 9 addition */
41
	'X',	__ifmt,
42
	'b',	__ifmt,		/* Plan 9 addition */
43
	'c',	__charfmt,
44
	'd',	__ifmt,
45
	'e',	__efgfmt,
46
	'f',	__efgfmt,
47
	'g',	__efgfmt,
48
	'h',	__flagfmt,
49
#ifndef PLAN9PORT
50
	'i',	__ifmt,		/* ANSI only */
51
#endif
52
	'l',	__flagfmt,
53
	'n',	__countfmt,
54
	'o',	__ifmt,
55
	'p',	__ifmt,
56
	'r',	__errfmt,
57
	's',	__strfmt,
58
#ifdef PLAN9PORT
59
	'u',	__flagfmt,
60
#else
61
	'u',	__ifmt,
62
#endif
63
	'x',	__ifmt,
64
	0,	0,
65
};
66
 
67
 
68
int	(*fmtdoquote)(int);
69
 
70
/*
71
 * __fmtlock() must be set
72
 */
73
static int
74
__fmtinstall(int c, Fmts f)
75
{
76
	Convfmt *p, *ep;
77
 
78
	if(c<=0 || c>=65536)
79
		return -1;
80
	if(!f)
81
		f = __badfmt;
82
 
83
	ep = &fmtalloc.fmt[fmtalloc.nfmt];
84
	for(p=fmtalloc.fmt; p<ep; p++)
85
		if(p->c == c)
86
			break;
87
 
88
	if(p == &fmtalloc.fmt[Maxfmt])
89
		return -1;
90
 
91
	p->fmt = f;
92
	if(p == ep){	/* installing a new format character */
93
		fmtalloc.nfmt++;
94
		p->c = c;
95
	}
96
 
97
	return 0;
98
}
99
 
100
int
101
fmtinstall(int c, int (*f)(Fmt*))
102
{
103
	int ret;
104
 
105
	__fmtlock();
106
	ret = __fmtinstall(c, f);
107
	__fmtunlock();
108
	return ret;
109
}
110
 
111
static Fmts
112
fmtfmt(int c)
113
{
114
	Convfmt *p, *ep;
115
 
116
	ep = &fmtalloc.fmt[fmtalloc.nfmt];
117
	for(p=fmtalloc.fmt; p<ep; p++)
118
		if(p->c == c){
119
			while(p->fmt == 0)	/* loop until value is updated */
120
				;
121
			return p->fmt;
122
		}
123
 
124
	/* is this a predefined format char? */
125
	__fmtlock();
126
	for(p=knownfmt; p->c; p++)
127
		if(p->c == c){
128
			__fmtinstall(p->c, p->fmt);
129
			__fmtunlock();
130
			return p->fmt;
131
		}
132
	__fmtunlock();
133
 
134
	return __badfmt;
135
}
136
 
137
void*
138
__fmtdispatch(Fmt *f, void *fmt, int isrunes)
139
{
140
	Rune rune, r;
141
	int i, n;
142
 
143
	f->flags = 0;
144
	f->width = f->prec = 0;
145
 
146
	for(;;){
147
		if(isrunes){
148
			r = *(Rune*)fmt;
149
			fmt = (Rune*)fmt + 1;
150
		}else{
151
			fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
152
			r = rune;
153
		}
154
		f->r = r;
155
		switch(r){
156
		case '\0':
157
			return nil;
158
		case '.':
159
			f->flags |= FmtWidth|FmtPrec;
160
			continue;
161
		case '0':
162
			if(!(f->flags & FmtWidth)){
163
				f->flags |= FmtZero;
164
				continue;
165
			}
166
			/* fall through */
167
		case '1': case '2': case '3': case '4':
168
		case '5': case '6': case '7': case '8': case '9':
169
			i = 0;
170
			while(r >= '0' && r <= '9'){
171
				i = i * 10 + r - '0';
172
				if(isrunes){
173
					r = *(Rune*)fmt;
174
					fmt = (Rune*)fmt + 1;
175
				}else{
176
					r = *(char*)fmt;
177
					fmt = (char*)fmt + 1;
178
				}
179
			}
180
			if(isrunes)
181
				fmt = (Rune*)fmt - 1;
182
			else
183
				fmt = (char*)fmt - 1;
184
		numflag:
185
			if(f->flags & FmtWidth){
186
				f->flags |= FmtPrec;
187
				f->prec = i;
188
			}else{
189
				f->flags |= FmtWidth;
190
				f->width = i;
191
			}
192
			continue;
193
		case '*':
194
			i = va_arg(f->args, int);
195
			if(i < 0){
196
				/*
197
				 * negative precision =>
198
				 * ignore the precision.
199
				 */
200
				if(f->flags & FmtPrec){
201
					f->flags &= ~FmtPrec;
202
					f->prec = 0;
203
					continue;
204
				}
205
				i = -i;
206
				f->flags |= FmtLeft;
207
			}
208
			goto numflag;
209
		}
210
		n = (*fmtfmt(r))(f);
211
		if(n < 0)
212
			return nil;
213
		if(n == 0)
214
			return fmt;
215
	}
216
}