|
|
1.1 root 1: #include "u.h"
2: #include "lib.h"
3:
4: #define PTR sizeof(char*)
5: #define SHORT sizeof(int)
6: #define INT sizeof(int)
7: #define LONG sizeof(long)
8: #define IDIGIT 30
9: #define MAXCON 30
10:
11: static int convcount = { 10 };
12:
13: #define FLONG (1<<0)
14: #define FSHORT (1<<1)
15: #define FUNSIGN (1<<2)
16:
17: typedef struct Op Op;
18: struct Op
19: {
20: char *p;
21: char *ep;
22: void *argp;
23: int f1;
24: int f2;
25: int f3;
26: };
27:
28: static int noconv(Op*);
29: static int cconv(Op*);
30: static int dconv(Op*);
31: static int hconv(Op*);
32: static int lconv(Op*);
33: static int oconv(Op*);
34: static int sconv(Op*);
35: static int uconv(Op*);
36: static int xconv(Op*);
37: static int percent(Op*);
38:
39: static
40: int (*fmtconv[MAXCON])(Op*) =
41: {
42: noconv,
43: cconv, dconv, hconv, lconv,
44: oconv, sconv, uconv, xconv,
45: percent,
46: };
47: static
48: char fmtindex[128] =
49: {
50: ['c'] 1,
51: ['d'] 2,
52: ['h'] 3,
53: ['l'] 4,
54: ['o'] 5,
55: ['s'] 6,
56: ['u'] 7,
57: ['x'] 8,
58: ['%'] 9,
59: };
60:
61: static void
62: PUT(Op *o, int c)
63: {
64: static int pos;
65: int opos;
66:
67: if(c == '\t'){
68: opos = pos;
69: pos = (opos+8) & ~7;
70: while(opos++ < pos && o->p < o->ep)
71: *o->p++ = ' ';
72: return;
73: }
74: if(o->p < o->ep){
75: *o->p++ = c;
76: pos++;
77: }
78: if(c == '\n')
79: pos = 0;
80: }
81:
82: int
83: fmtinstall(char c, int (*f)(Op*))
84: {
85:
86: c &= 0177;
87: if(fmtindex[c] == 0) {
88: if(convcount >= MAXCON)
89: return 1;
90: fmtindex[c] = convcount++;
91: }
92: fmtconv[fmtindex[c]] = f;
93: return 0;
94: }
95:
96: char*
97: donprint(char *p, char *ep, char *fmt, void *argp)
98: {
99: int sf1, c;
100: Op o;
101:
102: o.p = p;
103: o.ep = ep;
104: o.argp = argp;
105:
106: loop:
107: c = *fmt++;
108: if(c != '%') {
109: if(c == 0) {
110: if(o.p < o.ep)
111: *o.p = 0;
112: return o.p;
113: }
114: PUT(&o, c);
115: goto loop;
116: }
117: o.f1 = 0;
118: o.f2 = -1;
119: o.f3 = 0;
120: c = *fmt++;
121: sf1 = 0;
122: if(c == '-') {
123: sf1 = 1;
124: c = *fmt++;
125: }
126: while(c >= '0' && c <= '9') {
127: o.f1 = o.f1*10 + c-'0';
128: c = *fmt++;
129: }
130: if(sf1)
131: o.f1 = -o.f1;
132: if(c != '.')
133: goto l1;
134: c = *fmt++;
135: while(c >= '0' && c <= '9') {
136: if(o.f2 < 0)
137: o.f2 = 0;
138: o.f2 = o.f2*10 + c-'0';
139: c = *fmt++;
140: }
141: l1:
142: if(c == 0)
143: fmt--;
144: c = (*fmtconv[fmtindex[c&0177]])(&o);
145: if(c < 0) {
146: o.f3 |= -c;
147: c = *fmt++;
148: goto l1;
149: }
150: o.argp = (char*)o.argp + c;
151: goto loop;
152: }
153:
154: void
155: strconv(char *o, Op *op, int f1, int f2)
156: {
157: int n, c;
158: char *p;
159:
160: n = strlen(o);
161: if(f1 >= 0)
162: while(n < f1) {
163: PUT(op, ' ');
164: n++;
165: }
166: for(p=o; c = *p++;)
167: if(f2 != 0) {
168: PUT(op, c);
169: f2--;
170: }
171: if(f1 < 0) {
172: f1 = -f1;
173: while(n < f1) {
174: PUT(op, ' ');
175: n++;
176: }
177: }
178: }
179:
180: int
181: numbconv(Op *op, int base)
182: {
183: char b[IDIGIT];
184: int i, f, n, r;
185: long v;
186: short h;
187:
188: f = 0;
189: switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
190: case FLONG:
191: v = *(long*)op->argp;
192: r = LONG;
193: break;
194:
195: case FUNSIGN|FLONG:
196: v = *(ulong*)op->argp;
197: r = LONG;
198: break;
199:
200: case FSHORT:
201: h = *(int*)op->argp;
202: v = h;
203: r = SHORT;
204: break;
205:
206: case FUNSIGN|FSHORT:
207: h = *(int*)op->argp;
208: v = (ushort)h;
209: r = SHORT;
210: break;
211:
212: default:
213: v = *(int*)op->argp;
214: r = INT;
215: break;
216:
217: case FUNSIGN:
218: v = *(unsigned*)op->argp;
219: r = INT;
220: break;
221: }
222: if(!(op->f3 & FUNSIGN) && v < 0) {
223: v = -v;
224: f = 1;
225: }
226: b[IDIGIT-1] = 0;
227: for(i = IDIGIT-2;; i--) {
228: n = (ulong)v % base;
229: n += '0';
230: if(n > '9')
231: n += 'a' - ('9'+1);
232: b[i] = n;
233: if(i < 2)
234: break;
235: v = (ulong)v / base;
236: if(op->f2 >= 0 && i >= IDIGIT-op->f2)
237: continue;
238: if(v <= 0)
239: break;
240: }
241: sout:
242: if(f)
243: b[--i] = '-';
244: strconv(b+i, op, op->f1, -1);
245: return r;
246: }
247:
248: static int
249: noconv(Op *op)
250: {
251:
252: strconv("***", op, 0, -1);
253: return 0;
254: }
255:
256: static int
257: cconv(Op *op)
258: {
259: char b[2];
260:
261: b[0] = *(int*)op->argp;
262: b[1] = 0;
263: strconv(b, op, op->f1, -1);
264: return INT;
265: }
266:
267: static int
268: dconv(Op *op)
269: {
270: return numbconv(op, 10);
271: }
272:
273: static int
274: hconv(Op*)
275: {
276: return -FSHORT;
277: }
278:
279: static int
280: lconv(Op*)
281: {
282: return -FLONG;
283: }
284:
285: static int
286: oconv(Op *op)
287: {
288: return numbconv(op, 8);
289: }
290:
291: static int
292: sconv(Op *op)
293: {
294: strconv(*(char**)op->argp, op, op->f1, op->f2);
295: return PTR;
296: }
297:
298: static int
299: uconv(Op*)
300: {
301: return -FUNSIGN;
302: }
303:
304: static int
305: xconv(Op *op)
306: {
307: return numbconv(op, 16);
308: }
309:
310: static int
311: percent(Op *op)
312: {
313:
314: PUT(op, '%');
315: return 0;
316: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.