|
|
1.1 root 1: #include <varargs.h>
2:
3: #define SIZE 1024
4: #define FUNSIGN 4
5: #define FSHORT 2
6: #define FLONG 1
7: #define PTR sizeof (char *)
8: #define SHORT sizeof (int)
9: #define INT sizeof (int)
10: #define LONG sizeof (long)
11: #define FLOAT sizeof (double)
12: #define FDIGIT 30
13: #define FDEFLT 8
14: #define IDIGIT 40
15: #define MAXCONV 30
16:
17: static char *out, *eout;
18: static convcount = { 13 };
19:
20: static noconv();
21: static cconv(), dconv(), hconv(), lconv();
22: static oconv(), sconv(), uconv(), xconv();
23:
24: static econv(), fconv(), gconv(), percent();
25: int printcol;
26: static
27: int (*fmtconv[MAXCONV])() =
28: {
29: noconv,
30: cconv, dconv, hconv, lconv,
31: oconv, sconv, uconv, xconv,
32: econv, fconv, gconv, percent,
33: };
34: static
35: char fmtindex[128] =
36: {
37: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39: 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43: 0, 0, 0, 1, 2, 9,10,11, 3, 0, 0, 0, 4, 0, 0, 5,
44: 0, 0, 0, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
45: };
46:
47: fmtinstall(c, f)
48: char c;
49: int (*f)();
50: {
51:
52: c &= 0177;
53: if(fmtindex[c] == 0) {
54: if(convcount >= MAXCONV)
55: return 1;
56: fmtindex[c] = convcount++;
57: }
58: fmtconv[fmtindex[c]] = f;
59: return 0;
60: }
61:
62: char*
63: donprint(s, es, fmt, argpp)
64: char *s, *es;
65: register char *fmt;
66: va_list *argpp;
67: {
68: register int f1, f2, f3, sf1, c;
69: char *sout, *seout;
70:
71: sout = out;
72: seout = eout;
73: out = s;
74: eout = es-1;
75: loop:
76: c = *fmt++;
77: if(c != '%') {
78: if(c == 0) {
79: *out = 0;
80: s = out;
81: out = sout;
82: eout = seout;
83: return s;
84: }
85: if(out < eout)
86: *out++ = c;
87: printcol++;
88: if(c == '\n')
89: printcol = 0; else
90: if(c == '\t')
91: printcol = (printcol+7) & ~7;
92: goto loop;
93: }
94: f1 = 0;
95: f2 = -1;
96: f3 = 0;
97: c = *fmt++;
98: sf1 = 0;
99: if(c == '-') {
100: sf1 = 1;
101: c = *fmt++;
102: }
103: while(c >= '0' && c <= '9') {
104: f1 = f1*10 + c-'0';
105: c = *fmt++;
106: }
107: if(sf1)
108: f1 = -f1;
109: if(c != '.')
110: goto l1;
111: c = *fmt++;
112: while(c >= '0' && c <= '9') {
113: if(f2 < 0)
114: f2 = 0;
115: f2 = f2*10 + c-'0';
116: c = *fmt++;
117: }
118: l1:
119: if(c == 0)
120: fmt--;
121: /* NB: first arg is now a (va_list *) */
122: c = (*fmtconv[fmtindex[c&0177]])(argpp, f1, f2, f3);
123: if(c < 0) {
124: f3 |= -c;
125: c = *fmt++;
126: goto l1;
127: }
128: #ifdef notdef
129: argp += c; /* increment is now done in called routine by va_arg() */
130: #endif
131: goto loop;
132: }
133:
134: numbconv(o, f1, f2, f3, b)
135: va_list *o;
136: {
137: char s[IDIGIT];
138: register long v;
139: register int i, f, n, r;
140:
141: switch(f3 & (FLONG|FSHORT|FUNSIGN)) {
142: case FLONG:
143: v = va_arg(*o, long);
144: r = LONG;
145: break;
146:
147: case FUNSIGN|FLONG:
148: v = va_arg(*o, unsigned long);
149: r = LONG;
150: break;
151:
152: /* NB: a (unsigned) short argument is promoted to an (unsigned) int arg. */
153: case FSHORT:
154: v = (short)va_arg(*o, int);
155: r = SHORT;
156: break;
157:
158: case FUNSIGN|FSHORT:
159: v = (unsigned short)va_arg(*o, unsigned);
160: r = SHORT;
161: break;
162:
163: default:
164: v = va_arg(*o, int);
165: r = INT;
166: break;
167:
168: case FUNSIGN:
169: v = va_arg(*o, unsigned);
170: r = INT;
171: break;
172: }
173: f = 0;
174: if(!(f3 & FUNSIGN) && v < 0) {
175: v = -v;
176: f = 1;
177: }
178: s[IDIGIT-1] = 0;
179: for(i = IDIGIT-2; i >= 1; i--) {
180: n = (unsigned long)v % b;
181: n += '0';
182: if(n > '9')
183: n += 'a' - ('9'+1);
184: s[i] = n;
185: v = (unsigned long)v / b;
186: if(f2 >= 0 && i >= IDIGIT-f2)
187: continue;
188: if(v <= 0)
189: break;
190: }
191: if(f)
192: s[--i] = '-';
193: strconv(s+i, f1, -1);
194: return r;
195: }
196:
197: char*
198: doprint(s, fmt, argp)
199: char *s, *fmt;
200: va_list *argp;
201: {
202:
203: return donprint(s, s+SIZE, fmt, argp);
204: }
205:
206: /*
207: if you change this, change chconv
208: */
209:
210: strconv(o, f1, f2)
211: char *o;
212: {
213: register int n, c;
214: register char *s;
215:
216: n = 0;
217: for(s = o; *s++;)
218: n++;
219: if(f1 >= 0)
220: while(n < f1) {
221: if(out < eout)
222: *out++ = ' ';
223: printcol++;
224: n++;
225: }
226: for(s=o; c = *s++;)
227: if(f2 != 0) {
228: if(out < eout)
229: *out++ = c;
230: printcol++;
231: if(c == '\n')
232: printcol = 0; else
233: if(c == '\t')
234: printcol = (printcol+7) & ~7;
235: f2--;
236: }
237: if(f1 < 0) {
238: f1 = -f1;
239: while(n < f1) {
240: if(out < eout)
241: *out++ = ' ';
242: printcol++;
243: n++;
244: }
245: }
246: }
247:
248: chconv(o, f1)
249: char o;
250: {
251: register int n;
252:
253: n = 1;
254: if(f1 >= 0)
255: while(n < f1) {
256: if(out < eout)
257: *out++ = ' ';
258: printcol++;
259: n++;
260: }
261: if(out < eout)
262: *out++ = o;
263: printcol++;
264: if(o == '\n')
265: printcol = 0; else
266: if(o == '\t')
267: printcol = (printcol+7) & ~7;
268: if(f1 < 0) {
269: f1 = -f1;
270: while(n < f1) {
271: if(out < eout)
272: *out++ = ' ';
273: printcol++;
274: n++;
275: }
276: }
277: }
278:
279: /* ARGSUSED */
280: static
281: noconv(o, f1, f2, f3)
282: char *o;
283: {
284:
285: strconv("***", 0, -1);
286: return 0;
287: }
288:
289: /* ARGSUSED */
290: static
291: cconv(o, f1, f2, f3)
292: va_list *o;
293: {
294: chconv((char)va_arg(*o, int), f1);
295: return INT;
296: }
297:
298: static
299: dconv(o, f1, f2, f3)
300: va_list *o;
301: {
302: int r;
303:
304: r = numbconv(o, f1, f2, f3, 10);
305: return r;
306: }
307:
308: /* ARGSUSED */
309: static
310: hconv(o, f1, f2, f3)
311: {
312: return -FSHORT;
313: }
314:
315: /* ARGSUSED */
316: static
317: lconv(o, f1, f2, f3)
318: {
319:
320: return -FLONG;
321: }
322:
323: static
324: oconv(o, f1, f2, f3)
325: va_list *o;
326: {
327: int r;
328:
329: r = numbconv(o, f1, f2, f3, 8);
330: return r;
331: }
332:
333: /* ARGSUSED */
334: static
335: sconv(o, f1, f2, f3)
336: va_list *o;
337: {
338:
339: strconv(va_arg(*o, char *), f1, f2);
340: return PTR;
341: }
342:
343: /* ARGSUSED */
344: static
345: uconv(o, f1, f2, f3)
346: {
347: return -FUNSIGN;
348: }
349:
350: static
351: xconv(o, f1, f2, f3)
352: va_list *o;
353: {
354: int r;
355:
356: r = numbconv(o, f1, f2, f3, 16);
357: return r;
358: }
359:
360: double pow10(), frexp();
361: /* ARGSUSED */
362: fltconv(f, f1, f2, f3, c)
363: register double f;
364: {
365: char s1[FDIGIT+10], s2[FDIGIT+10];
366: register double g;
367: register int d, i, n, s;
368: double h;
369: int e;
370: int c1, c2, c3;
371:
372: s = 0;
373: if(f < 0) {
374: f = -f;
375: s++;
376: }
377:
378: loop:
379: e = 0;
380: g = 0;
381: if(f != 0) {
382: g = frexp(f, &e);
383: e = e * .30103;
384: d = e/2;
385: h = f * pow10(-d); /* 10**-e in 2 parts */
386: g = h * pow10(d-e);
387: while(g < 1) {
388: e--;
389: g = h * pow10(d-e);
390: }
391: while(g >= 10) {
392: e++;
393: g = h * pow10(d-e);
394: }
395: }
396: if(f2 < 0)
397: f2 = FDEFLT;
398: if(c == 'g' && f2 > 0)
399: f2--;
400: if(f2 > FDIGIT)
401: f2 = FDIGIT;
402: /*
403: * n is number of digits to convert
404: * 1 before, f2 after, 1 extra for rounding
405: */
406: n = f2 + 2;
407: if(c == 'f') {
408: /*
409: * e+1 before, f2 after, 1 extra
410: */
411: n += e;
412: if(n <= 0) {
413: n = 1;
414: g = 0;
415: }
416: }
417: if(n >= FDIGIT+2) {
418: if(c == 'e')
419: f2 = -1;
420: c = 'e';
421: goto loop;
422: }
423: /*
424: * convert n digits
425: */
426: for(i=0; i<n; i++) {
427: d = g;
428: if(d > g)
429: d--;
430: g -= d;
431: s1[i+1] = d + '0';
432: g *= 10;
433: }
434: /*
435: * round by adding .5 into extra digit
436: */
437: d = 5;
438: for(i=n-1; i>=0; i--) {
439: s1[i+1] += d;
440: d = 0;
441: if(s1[i+1] > '9') {
442: s1[i+1] -= 10;
443: d++;
444: }
445: }
446: i = 1;
447: if(d) {
448: s1[0] = '1';
449: e++;
450: i = 0;
451: }
452: /*
453: * copy into final place
454: * c1 digits of leading '0'
455: * c2 digits from conversion
456: * c3 digits after '.'
457: */
458: d = 0;
459: if(s)
460: s2[d++] = '-';
461: c1 = 0;
462: c2 = f2 + 1;
463: c3 = f2;
464: if(c == 'g')
465: if(e >= -5 && e <= f2) {
466: c1 = -e - 1;
467: c3 = c1;
468: if(c1 < 0)
469: c1 = 0;
470: c3 = f2 - e;
471: c = 'h';
472: }
473: if(c == 'f') {
474: c1 = -e;
475: if(c1 < 0)
476: c1 = 0;
477: if(c1 > f2)
478: c1 = c2;
479: c2 += e;
480: if(c2 < 0)
481: c2 = 0;
482: }
483: while(c1 > 0) {
484: if(c1+c2 == c3)
485: s2[d++] = '.';
486: s2[d++] = '0';
487: c1--;
488: }
489: while(c2 > 0) {
490: if(c1+c2 == c3)
491: s2[d++] = '.';
492: s2[d++] = s1[i++];
493: c2--;
494: }
495: /*
496: * strip trailing '0' on g conv
497: */
498: if(c == 'g' || c == 'h') {
499: for(n=d-1; n>=0; n--)
500: if(s2[n] != '0')
501: break;
502: for(i=n; i>=0; i--)
503: if(s2[i] == '.') {
504: d = n;
505: if(i != n)
506: d++;
507: break;
508: }
509: }
510: if(c == 'e' || c == 'g') {
511: s2[d++] = 'e';
512: s2[d++] = '+';
513: c1 = e;
514: if(c1 < 0) {
515: s2[d-1] = '-';
516: c1 = -c1;
517: }
518: if(c1 >= 100) {
519: s2[d++] = c1/100 + '0';
520: c1 %= 100;
521: }
522: s2[d++] = c1/10 + '0';
523: s2[d++] = c1%10 + '0';
524: }
525: s2[d] = 0;
526: strconv(s2, f1, -1);
527: return FLOAT;
528: }
529:
530: static
531: econv(o, f1, f2, f3)
532: va_list *o;
533: {
534:
535: return fltconv(va_arg(*o, double), f1, f2, f3, 'e');
536: }
537:
538: static
539: fconv(o, f1, f2, f3)
540: va_list *o;
541: {
542:
543: return fltconv(va_arg(*o, double), f1, f2, f3, 'f');
544: }
545:
546: static
547: gconv(o, f1, f2, f3)
548: va_list *o;
549: {
550:
551: return fltconv(va_arg(*o, double), f1, f2, f3, 'g');
552: }
553:
554: static
555: percent()
556: {
557:
558: if(out < eout)
559: *out++ = '%';
560: return 0;
561: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.