1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
30: #include <stdarg.h>
31: #include <basic.h>
32:
33:
34: #define OUTBUF_SZ 0
35:
36: typedef unsigned char uchar;
37:
38: extern int tm_putchar(int c);
39: extern int tm_putstring(uchar *s);
40:
41:
42: typedef struct {
43: short len;
44: short cnt;
45: uchar *bufp;
46: } OutPar;
47: typedef void (*OutFn)(uchar *str, int len, OutPar *par);
48:
49: 50: 51:
52: static uchar *outint(uchar *ep, unsigned long val, uchar base)
53: {
54: static const uchar digits[] = "0123456789abcdef0123456789ABCDEF";
55: uchar caps;
56:
57: caps = (base & 0x40) >> 2;
58: for (base &= 0x3F; val >= base; val /= base) {
59: *--ep = digits[(val % base) + caps];
60: }
61: *--ep = digits[val + caps];
62: return ep;
63: }
64:
65: 66: 67:
68: static void _vsprintf(OutFn ostr, OutPar *par,
69: const uchar *fmt, va_list ap)
70: {
71: #define MAX_DIGITS 14
72: unsigned long v;
73: short wid, prec, n;
74: uchar *fms, *cbs, *cbe, cbuf[MAX_DIGITS];
75: uchar c, base, flg, sign, qual;
76:
77:
78: #define F_LEFT 0x01
79: #define F_PLUS 0x02
80: #define F_SPACE 0x04
81: #define F_PREFIX 0x08
82: #define F_ZERO 0x10
83:
84: for (fms = NULL; (c = *fmt++) != '\0'; ) {
85:
86: if (c != '%') {
87: if (fms == NULL) fms = (uchar*)fmt - 1;
88: continue;
89: }
90:
91:
92: if (fms != NULL) {
93: (*ostr)(fms, fmt - fms - 1, par);
94: fms = NULL;
95: }
96:
97:
98: for (flg = 0; ; ) {
99: switch (c = *fmt++) {
100: case '-': flg |= F_LEFT; continue;
101: case '+': flg |= F_PLUS; continue;
102: case ' ': flg |= F_SPACE; continue;
103: case '#': flg |= F_PREFIX; continue;
104: case '0': flg |= F_ZERO; continue;
105: }
106: break;
107: }
108:
109:
110: if (c == '*') {
111: wid = va_arg(ap, int);
112: if (wid < 0) {
113: wid = -wid;
114: flg |= F_LEFT;
115: }
116: c = *fmt++;
117: } else {
118: for (wid = 0; c >= '0' && c <= '9'; c = *fmt++)
119: wid = wid * 10 + c - '0';
120: }
121:
122:
123: prec = -1;
124: if (c == '.') {
125: c = *fmt++;
126: if (c == '*') {
127: prec = va_arg(ap, int);
128: if (prec < 0) prec = 0;
129: c = *fmt++;
130: } else {
131: for (prec = 0;c >= '0' && c <= '9';c = *fmt++)
132: prec = prec * 10 + c - '0';
133: }
134: flg &= ~F_ZERO;
135: }
136:
137:
138: qual = 0;
139: if (c == 'h' || c == 'l') {
140: qual = c;
141: c = *fmt++;
142: }
143:
144:
145: base = 10;
146: sign = 0;
147: cbe = &cbuf[MAX_DIGITS];
148:
149: switch (c) {
150: case 'i':
151: case 'd':
152: case 'u':
153: case 'X':
154: case 'x':
155: case 'o':
156: if (qual == 'l') {
157: v = va_arg(ap, unsigned long);
158: } else {
159: v = va_arg(ap, unsigned int);
160: if (qual == 'h') {
161: v = (c == 'i' || c == 'd') ?
162: (short)v :(unsigned short)v;
163: }
164: }
165: switch (c) {
166: case 'i':
167: case 'd':
168: if ((long)v < 0) {
169: v = - (long)v;
170: sign = '-';
171: } else if ((flg & F_PLUS) != 0) {
172: sign = '+';
173: } else if ((flg & F_SPACE) != 0) {
174: sign = ' ';
175: } else {
176: break;
177: }
178: wid--;
179: case 'u':
180: break;
181: case 'X':
182: base += 0x40;
183: case 'x':
184: base += 8;
185: case 'o':
186: base -= 2;
187: if ((flg & F_PREFIX) != 0 && v != 0) {
188: wid -= (base == 8) ? 1 : 2;
189: base |= 0x80;
190: }
191: break;
192: }
193:
194: cbs = (v == 0 && prec == 0) ?
195: cbe : outint(cbe, v, base);
196: break;
197: case 'p':
198: v = (unsigned long)va_arg(ap, void *);
199: if (v != 0) {
200: base = 16 | 0x80;
201: wid -= 2;
202: }
203: cbs = outint(cbe, v, base);
204: break;
205: case 's':
206: cbe = cbs = va_arg(ap, uchar *);
207: if (prec < 0) {
208: while (*cbe != '\0') cbe++;
209: } else {
210: while (--prec >= 0 && *cbe != '\0') cbe++;
211: }
212: break;
213: case 'c':
214: cbs = cbe;
215: *--cbs = (uchar)va_arg(ap, int);
216: prec = 0;
217: break;
218: case '\0':
219: fmt--;
220: continue;
221: default:
222:
223: fms = (uchar*)fmt - 1;
224: continue;
225: }
226:
227: n = cbe - cbs;
228: if ((prec -= n) > 0) n += prec;
229: wid -= n;
230:
231:
232: if ((flg & (F_LEFT | F_ZERO)) == 0 ) {
233: while (--wid >= 0) (*ostr)((uchar*)" ", 1, par);
234: }
235:
236:
237: if (sign != 0) {
238: (*ostr)(&sign, 1, par);
239: }
240:
241:
242: if ((base & 0x80) != 0) {
243: (*ostr)((uchar*)"0", 1, par);
244: if ((base & 0x10) != 0) {
245: (*ostr)((base & 0x40) ?
246: (uchar*)"X" : (uchar*)"x", 1, par);
247: }
248: }
249:
250:
251: if ((n = prec) <= 0) {
252: if ((flg & (F_LEFT | F_ZERO)) == F_ZERO ) {
253: n = wid;
254: wid = 0;
255: }
256: }
257: while (--n >= 0) (*ostr)((uchar*)"0", 1, par);
258:
259:
260: (*ostr)(cbs, cbe - cbs, par);
261:
262:
263: while (--wid >= 0) (*ostr)((uchar*)" ", 1, par);
264: }
265:
266:
267: if (fms != NULL) {
268: (*ostr)(fms, fmt - fms - 1, par);
269: }
270: #if OUTBUF_SZ > 0
271:
272: (*ostr)(NULL, 0, par);
273: #endif
274: }
275:
276: 277: 278:
279: static void out_cons(uchar *str, int len, OutPar *par)
280: {
281: #if OUTBUF_SZ == 0
282:
283: par->len += len;
284: while (--len >= 0) tm_putchar(*str++);
285: #else
286:
287: if (str == NULL) {
288: if (par->cnt > 0) {
289: par->bufp[par->cnt] = '\0';
290: tm_putstring(par->bufp);
291: par->cnt = 0;
292: }
293: } else {
294: par->len += len;
295: while (--len >= 0) {
296: if (par->cnt >= OUTBUF_SZ - 1) {
297: par->bufp[par->cnt] = '\0';
298: tm_putstring(par->bufp);
299: par->cnt = 0;
300: }
301: par->bufp[par->cnt++] = *str++;
302: }
303: }
304: #endif
305: }
306:
307: int tm_vprintf(const char *format, va_list ap)
308: {
309: #if OUTBUF_SZ == 0
310: short len = 0;
311: _vsprintf(out_cons, (OutPar*)&len, (const uchar *)format, ap);
312: return len;
313: #else
314: char obuf[OUTBUF_SZ];
315: OutPar par;
316:
317: par.len = par.cnt = 0;
318: par.bufp = obuf;
319: _vsprintf(out_cons, (OutPar*)&par, (const uchar *)format, ap);
320: va_end(ap);
321: return par.len;
322: #endif
323: }
324:
325: int tm_printf(const char *format, ...)
326: {
327: va_list ap;
328: int len;
329:
330: va_start(ap, format);
331: len = tm_vprintf(format, ap);
332: va_end(ap);
333:
334: return len;
335: }
336:
337: 338: 339:
340: static void out_buf(uchar *str, int len, OutPar *par)
341: {
342: par->len += len;
343: while (--len >= 0) *(par->bufp)++ = *str++;
344: }
345:
346: int tm_vsprintf(char *str, const char *format, va_list ap)
347: {
348: OutPar par;
349:
350: par.len = 0;
351: par.bufp = (uchar*)str;
352: _vsprintf(out_buf, &par, (const uchar *)format, ap);
353: str[par.len] = '\0';
354: return par.len;
355: }
356:
357: int tm_sprintf(char *str, const char *format, ...)
358: {
359: va_list ap;
360: int len;
361:
362: va_start(ap, format);
363: len = tm_vsprintf(str, format, ap);
364: va_end(ap);
365:
366: return len;
367: }
368: