|
|
1.1 root 1: /*
2: * Standard I/O library printf/fprint/sprintf.
3: * Non-portable things:
4: * 1) alignment of arguments is assumed to be completely contiguous.
5: * 2) the smallest number is assumed to negate to itself.
6: * 3) All of long, int, char*, and double are assumed to
7: * be held in an exact number of ints.
8: */
9:
10: #include <stdio.h>
11: #include <sys/mdata.h>
12: #include <ctype.h>
13:
14: /* Avoid calling the new style toupper() function on MSDOS and GEMDOS */
15: #ifdef _toupper
16: #define toupper(c) _toupper(c)
17: #endif
18:
19: union alltypes {
20: char c;
21: int i;
22: unsigned u;
23: long l;
24: double d;
25: char *s;
26: };
27:
28: #define bump(p,s) (p+=sizeof(s)/sizeof(int))
29:
30: char *printi();
31: char *printl();
32: char *_dtefg();
33:
34: static readonly char null[] = "{NULL}";
35:
36: /*
37: * Formatted print to standard output.
38: */
39: printf(args)
40: union alltypes args;
41: {
42: xprintf(stdout, &args);
43: }
44:
45: /*
46: * Formatted print to a specific file.
47: */
48: fprintf(fp, args)
49: FILE *fp;
50: union alltypes args;
51: {
52: xprintf(fp, &args);
53: }
54:
55: /*
56: * Formatted print into given string.
57: * Handcrafted file structure created for putc.
58: */
59: sprintf(sp, args)
60: char *sp;
61: union alltypes args;
62: {
63: FILE file;
64:
65: _stropen(sp, -MAXINT-1, &file);
66: xprintf(&file, &args);
67: putc('\0', &file);
68: }
69:
70: static
71: xprintf(fp, argp)
72: FILE *fp;
73: union alltypes *argp;
74: {
75: register char *cbp;
76: int *iap;
77: register c;
78: char *s;
79: char *cbs;
80: int adj, pad;
81: int prec;
82: int fwidth;
83: int pwidth;
84: int isnumeric;
85: register char *fmt;
86: union alltypes elem;
87: char cbuf[64];
88:
89: iap = (int *)argp;
90: fmt = *(char **)iap;
91: bump(iap, char*);
92: for (;;) {
93: while((c = *fmt++) != '%') {
94: if(c == '\0') {
95: return;
96: }
97: putc(c, fp);
98: }
99: pad = ' ';
100: fwidth = -1;
101: prec = -1;
102: c = *fmt++;
103: if (c == '-') {
104: adj = 1;
105: c = *fmt++;
106: } else
107: adj = 0;
108: if (c == '0') {
109: pad = '0';
110: c = *fmt++;
111: }
112: if (c == '*') {
113: if ((fwidth = *iap++) < 0) {
114: adj = 1;
115: fwidth = -fwidth;
116: }
117: c = *fmt++;
118: } else
119: for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
120: fwidth = fwidth*10 + c-'0';
121: if (c == '.') {
122: c = *fmt++;
123: if (c == '*') {
124: prec = *iap++;
125: c = *fmt++;
126: } else
127: for (prec=0; c>='0' && c<='9'; c=*fmt++)
128: prec = prec*10 + c-'0';
129: }
130: if (c == 'l') {
131: c = *fmt++;
132: if (c=='d' || c=='o' || c=='u' || c=='x')
133: c = toupper(c);
134: }
135: cbp = cbs = cbuf;
136: isnumeric = 1;
137: switch (c) {
138:
139: case 'd':
140: elem.i = *iap++;
141: if (elem.i < 0) {
142: elem.i = -elem.i;
143: *cbp++ = '-';
144: }
145: cbp = printi(cbp, elem.i, 10);
146: break;
147:
148: case 'u':
149: cbp = printi(cbp, *iap++, 10);
150: break;
151:
152: case 'o':
153: cbp = printi(cbp, *iap++, 8);
154: break;
155:
156: case 'x':
157: cbp = printi(cbp, *iap++, 16);
158: break;
159:
160: case 'D':
161: elem.l = *(long *)iap;
162: bump(iap, long);
163: if (elem.l < 0) {
164: elem.l = -elem.l;
165: *cbp++ = '-';
166: }
167: cbp = printl(cbp, elem.l, 10);
168: break;
169:
170: case 'U':
171: cbp = printl(cbp, *(long *)iap, 10);
172: bump(iap, long);
173: break;
174:
175: case 'O':
176: cbp = printl(cbp, *(long *)iap, 8);
177: bump(iap, long);
178: break;
179:
180: case 'X':
181: cbp = printl(cbp, *(long *)iap, 16);
182: bump(iap, long);
183: break;
184:
185: case 'e':
186: case 'f':
187: case 'g':
188: cbp = _dtefg(c, iap, prec, cbp);
189: bump(iap, double);
190: break;
191:
192: case 's':
193: isnumeric = 0;
194: if ((s = *(char **)iap) == NULL)
195: s = null;
196: bump(iap, char*);
197: cbp = cbs = s;
198: while (*cbp++ != '\0')
199: if (prec>=0 && cbp-s>prec)
200: break;
201: cbp--;
202: break;
203:
204: case 'c':
205: isnumeric = 0;
206: *cbp++ = *iap++;
207: break;
208:
209: case 'r':
210: xprintf(fp, *(char ***)iap);
211: bump(iap, char**);
212: break;
213:
214: default:
215: putc(c, fp);
216: continue;
217: }
218: if ((pwidth = fwidth + cbs-cbp) < 0)
219: pwidth = 0;
220: if (!adj) {
221: if (isnumeric && pad == '0' && *cbs == '-')
222: putc(*cbs++, fp);
223: while (pwidth-- != 0)
224: putc(pad, fp);
225: }
226: while (cbs < cbp)
227: putc(*cbs++, fp);
228: if (adj)
229: while (pwidth-- != 0)
230: putc(pad, fp);
231: }
232: }
233:
234: static readonly char digits[] = {
235: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
236: 'A', 'B', 'C', 'D', 'E', 'F'
237: };
238:
239: /*
240: * Print an unsigned integer in base b.
241: */
242: static
243: char *
244: printi(cp, n, b)
245: char *cp;
246: register unsigned n;
247: {
248: register a;
249: register char *ep;
250: char pbuf[10];
251:
252: ep = &pbuf[10];
253: *--ep = 0;
254: for ( ; a = n/b; n=a)
255: *--ep = digits[n%b];
256: *--ep = digits[n];
257: while (*ep)
258: *cp++ = *ep++;
259: return (cp);
260: }
261:
262: /*
263: * Print an unsigned long in base b.
264: */
265: static
266: char *
267: printl(cp, n, b)
268: register char *cp;
269: unsigned long n;
270: register b;
271: {
272: char pbuf[13];
273: unsigned long a;
274: register char *ep;
275:
276: ep = &pbuf[13];
277: *--ep = '\0';
278: for ( ; (a = n/b) != 0; n = a)
279: *--ep = digits[n%b];
280: *--ep = digits[n];
281: while (*ep)
282: *cp++ = *ep++;
283: return (cp);
284: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.