|
|
1.1 root 1: #define FLOAT 0
2:
3: /*
4: * _doprnt: common code for printf, fprintf, sprintf
5: * Floating-point code is included or not, depending
6: * on whether the preprocessor variable FLOAT is 1 or 0.
7: */
8:
9: #include <stdio.h>
10: #include <ctype.h>
11: #include "param.h"
12:
13: #define max(a,b) ((a) > (b)? (a): (b))
14: #define min(a,b) ((a) < (b)? (a): (b))
15:
16: /* If this symbol is nonzero, allow '0' as a flag */
17: #define FZERO 1
18:
19:
20: /*
21: * System-supplied routines for floating conversion
22: */
23: char *fcvt();
24: char *ecvt();
25:
26: /* This variable counts output characters. */
27: static int count;
28: static FILE *iop;
29:
30: int _doprnt(format, args, _pfile)
31: char *format;
32: char *args;
33: FILE *_pfile;
34: {
35: /* Current position in format */
36: char *cp;
37:
38: /* Starting and ending points for value to be printed */
39: char *bp, *p;
40:
41: /* Field width and precision */
42: int width, prec;
43:
44: /* Format code */
45: char fcode;
46:
47: /* Number of padding zeroes required on the left */
48: int lzero;
49:
50: /* Flags - nonzero if corresponding character appears in format */
51: bool length; /* l */
52: bool fplus; /* + */
53: bool fminus; /* - */
54: bool fblank; /* blank */
55: bool fsharp; /* # */
56: #if FZERO
57: bool fzero; /* 0 */
58: #endif
59:
60: /* Pointer to sign, "0x", "0X", or empty */
61: char *prefix;
62:
63: /* Exponent or empty */
64: char *suffix;
65:
66: /* Buffer to create exponent */
67: char expbuf[MAXESIZ + 1];
68:
69: /* Number of padding zeroes required on the right */
70: int rzero;
71:
72: /* The value being converted, if real */
73: double dval;
74:
75: /* Output values from fcvt and ecvt */
76: int decpt, sign;
77:
78: /* Scratch */
79: int k;
80:
81: /* Values are developed in this buffer */
82: char buf[max (MAXDIGS, max (MAXFCVT + MAXEXP, MAXECVT) + 1)];
83:
84: /* The value being converted, if integer */
85: long val;
86:
87: /* Set to point to a translate table for digits of whatever radix */
88: char *tab;
89:
90: /* Work variables */
91: int n, hradix, lowbit;
92:
93: iop = _pfile;
94: cp = format;
95: count = 0;
96:
97: /*
98: * The main loop -- this loop goes through one iteration
99: * for each ordinary character or format specification.
100: */
101: while (*cp)
102: if (*cp != '%') {
103: /* Ordinary (non-%) character */
104: putc (*cp++, _pfile);
105: ++count;
106: } else {
107: /*
108: * % has been found.
109: * First, parse the format specification.
110: */
111:
112: /* Scan the <flags> */
113: fplus = fminus = fblank = fsharp = 0;
114: #if FZERO
115: fzero = 0;
116: #endif
117: scan: switch (*++cp) {
118: case '+':
119: fplus = 1;
120: goto scan;
121: case '-':
122: fminus = 1;
123: goto scan;
124: case ' ':
125: fblank = 1;
126: goto scan;
127: case '#':
128: fsharp = 1;
129: goto scan;
130: #if FZERO
131: case '0':
132: fzero = 1;
133: goto scan;
134: #endif
135: }
136:
137: /* Scan the field width */
138: if (*cp == '*') {
139: width = *(int *)args; args += sizeof(int);
140: if (width < 0) {
141: width = -width;
142: fminus = 1;
143: }
144: cp++;
145: } else {
146: width = 0;
147: while (isdigit (*cp)) {
148: n = tonumber (*cp++);
149: width = width * 10 + n;
150: }
151: }
152:
153: /* Scan the precision */
154: if (*cp == '.') {
155:
156: /* '*' instead of digits? */
157: if (*++cp == '*') {
158: prec = *(int *)args; args += sizeof(int);
159: cp++;
160: } else {
161: prec = 0;
162: while (isdigit (*cp)) {
163: n = tonumber (*cp++);
164: prec = prec * 10 + n;
165: }
166: }
167: } else
168: prec = -1;
169:
170: /* Scan the length modifier */
171: length = 0;
172: switch (*cp) {
173: case 'l':
174: length = 1;
175: /* No break */
176: case 'h':
177: cp++;
178: }
179:
180: /*
181: * The character addressed by cp must be the
182: * format letter -- there is nothing left for
183: * it to be.
184: *
185: * The status of the +, -, #, blank, and 0
186: * flags are reflected in the variables
187: * "fplus", "fminus", "fsharp", "fblank",
188: * and "fzero", respectively.
189: * "width" and "prec" contain numbers
190: * corresponding to the digit strings
191: * before and after the decimal point,
192: * respectively. If there was no decimal
193: * point, "prec" is -1.
194: *
195: * The following switch sets things up
196: * for printing. What ultimately gets
197: * printed will be padding blanks, a prefix,
198: * left padding zeroes, a value, right padding
199: * zeroes, a suffix, and more padding
200: * blanks. Padding blanks will not appear
201: * simultaneously on both the left and the
202: * right. Each case in this switch will
203: * compute the value, and leave in several
204: * variables the information necessary to
205: * construct what is to be printed.
206: *
207: * The prefix is a sign, a blank, "0x", "0X",
208: * or null, and is addressed by "prefix".
209: *
210: * The suffix is either null or an exponent,
211: * and is addressed by "suffix".
212: *
213: * The value to be printed starts at "bp"
214: * and continues up to and not including "p".
215: *
216: * "lzero" and "rzero" will contain the number
217: * of padding zeroes required on the left
218: * and right, respectively. If either of
219: * these variables is negative, it will be
220: * treated as if it were zero.
221: *
222: * The number of padding blanks, and whether
223: * they go on the left or the right, will be
224: * computed on exit from the switch.
225: */
226:
227: lzero = 0;
228: prefix = "";
229: rzero = lzero;
230: suffix = prefix;
231:
232: switch (fcode = *cp++) {
233:
234: /*
235: * fixed point representations
236: *
237: * "hradix" is half the radix for the conversion.
238: * Conversion is unsigned unless fcode is 'd'.
239: * HIBIT is 1000...000 binary, and is equal to
240: * the maximum negative number.
241: * We assume a 2's complement machine
242: */
243:
244: case 'd':
245: case 'u':
246: hradix = 5;
247: goto fixed;
248:
249: case 'o':
250: hradix = 4;
251: goto fixed;
252:
253: case 'X':
254: case 'x':
255: hradix = 8;
256:
257: fixed:
258: /* Establish default precision */
259: if (prec < 0)
260: prec = 1;
261:
262: /* Fetch the argument to be printed */
263: if (length)
264: {val = *(long *)args; args += sizeof(long);}
265: else if (fcode == 'd')
266: {val = *(int *)args; args += sizeof(int);}
267: else
268: {val = *(unsigned *)args; args += sizeof(unsigned);}
269:
270: /* If signed conversion, establish sign */
271: if (fcode == 'd') {
272: if (val < 0) {
273: prefix = "-";
274: /*
275: * Negate, checking in
276: * advance for possible
277: * overflow.
278: */
279: if (val != HIBIT)
280: val = -val;
281: } else if (fplus)
282: prefix = "+";
283: else if (fblank)
284: prefix = " ";
285: }
286: #if FZERO
287: if (fzero) {
288: int n = width - strlen (prefix);
289: if (n > prec)
290: prec = n;
291: }
292: #endif
293: /* Set translate table for digits */
294: if (fcode == 'X')
295: tab = "0123456789ABCDEF";
296: else
297: tab = "0123456789abcdef";
298:
299: /* Develop the digits of the value */
300: p = bp = buf + MAXDIGS;
301: while (val) {
302: lowbit = val & 1;
303: val = (val >> 1) & ~HIBIT;
304: *--bp = tab[val % hradix * 2 + lowbit];
305: val = val / hradix;
306: }
307:
308: /* Calculate padding zero requirement */
309: lzero = bp - p + prec;
310:
311: /* Handle the # flag */
312: if (fsharp && bp != p)
313: switch (fcode) {
314: case 'o':
315: if (lzero < 1)
316: lzero = 1;
317: break;
318: case 'x':
319: prefix = "0x";
320: break;
321: case 'X':
322: prefix = "0X";
323: break;
324: }
325:
326: break;
327:
328: case 'E':
329: case 'e':
330: /*
331: * E-format. The general strategy
332: * here is fairly easy: we take
333: * what ecvt gives us and re-format it.
334: */
335:
336: /* Establish default precision */
337: if (prec < 0)
338: prec = 6;
339:
340: /* Fetch the value */
341: dval = *(double *)args; args += sizeof(double);
342:
343: /* Develop the mantissa */
344: bp = ecvt (dval,
345: min (prec + 1, MAXECVT),
346: &decpt,
347: &sign);
348:
349: /* Determine the prefix */
350: e_merge:
351: if (sign)
352: prefix = "-";
353: else if (fplus)
354: prefix = "+";
355: else if (fblank)
356: prefix = " ";
357:
358: /* Place the first digit in the buffer */
359: p = &buf[0];
360: *p++ = *bp != '\0'? *bp++: '0';
361:
362: /* Put in a decimal point if needed */
363: if (prec != 0 || fsharp)
364: *p++ = '.';
365:
366: /* Create the rest of the mantissa */
367: rzero = prec;
368: while (rzero > 0 && *bp!= '\0') {
369: --rzero;
370: *p++ = *bp++;
371: }
372:
373: bp = &buf[0];
374:
375: /* Create the exponent */
376: suffix = &expbuf[MAXESIZ];
377: *suffix = '\0';
378: if (dval != 0) {
379: n = decpt - 1;
380: if (n < 0)
381: n = -n;
382: while (n != 0) {
383: *--suffix = todigit (n % 10);
384: n /= 10;
385: }
386: }
387:
388: /* Prepend leading zeroes to the exponent */
389: while (suffix > &expbuf[MAXESIZ - 2])
390: *--suffix = '0';
391:
392: /* Put in the exponent sign */
393: *--suffix = (decpt > 0 || dval == 0)? '+': '-';
394:
395: /* Put in the e */
396: *--suffix = isupper(fcode)? 'E' : 'e';
397:
398: break;
399:
400: case 'f':
401: /*
402: * F-format floating point. This is
403: * a good deal less simple than E-format.
404: * The overall strategy will be to call
405: * fcvt, reformat its result into buf,
406: * and calculate how many trailing
407: * zeroes will be required. There will
408: * never be any leading zeroes needed.
409: */
410:
411: /* Establish default precision */
412: if (prec < 0)
413: prec = 6;
414:
415: /* Fetch the value */
416: dval = *(double *)args; args += sizeof(double);
417:
418: /* Do the conversion */
419: bp = fcvt (dval,
420: min (prec, MAXFCVT),
421: &decpt,
422: &sign);
423:
424: /* Determine the prefix */
425: f_merge:
426: if (sign && decpt > -prec &&
427: *bp != '\0' && *bp != '0')
428: prefix = "-";
429: else if (fplus)
430: prefix = "+";
431: else if (fblank)
432: prefix = " ";
433:
434: /* Initialize buffer pointer */
435: p = &buf[0];
436:
437: /* Emit the digits before the decimal point */
438: n = decpt;
439: k = 0;
440: if (n <= 0)
441: *p++ = '0';
442: else
443: do if (*bp == '\0' || k >= MAXFSIG)
444: *p++ = '0';
445: else {
446: *p++ = *bp++;
447: ++k;
448: }
449: while (--n != 0);
450:
451: /* Decide whether we need a decimal point */
452: if (fsharp || prec > 0)
453: *p++ = '.';
454:
455: /* Digits (if any) after the decimal point */
456: n = min (prec, MAXFCVT);
457: rzero = prec - n;
458: while (--n >= 0)
459: if (++decpt <= 0
460: || *bp == '\0'
461: || k >= MAXFSIG)
462: *p++ = '0';
463: else {
464: *p++ = *bp++;
465: ++k;
466: }
467:
468: bp = &buf[0];
469:
470: break;
471:
472: case 'G':
473: case 'g':
474: /*
475: * g-format. We play around a bit
476: * and then jump into e or f, as needed.
477: */
478:
479: /* Establish default precision */
480: if (prec < 0)
481: prec = 6;
482:
483: /* Fetch the value */
484: dval = *(double *)args; args += sizeof(double);
485:
486: /* Do the conversion */
487: bp = ecvt (dval,
488: min (prec, MAXECVT),
489: &decpt,
490: &sign);
491: if (dval == 0)
492: decpt = 1;
493:
494: k = prec;
495: if (!fsharp) {
496: n = strlen (bp);
497: if (n < k)
498: k = n;
499: while (k >= 1 && bp[k-1] == '0')
500: --k;
501: }
502:
503: if (decpt < -3 || decpt > prec) {
504: prec = k - 1;
505: goto e_merge;
506: } else {
507: prec = k - decpt;
508: goto f_merge;
509: }
510:
511: case 'c':
512: buf[0] = *(int *)args; args += sizeof(int);
513: bp = &buf[0];
514: p = bp + 1;
515: break;
516:
517: case 's':
518: bp = *(char **)args; args += sizeof(char **);
519: if (prec < 0)
520: prec = MAXINT;
521: for (n=0; *bp++ != '\0' && n < prec; n++);
522: p = --bp;
523: bp -= n;
524: break;
525:
526: case '\0':
527: cp--;
528: break;
529:
530: /* case '%': */
531: default:
532: p = bp = &fcode;
533: p++;
534: break;
535:
536: }
537: if (fcode != '\0') {
538: /* Calculate number of padding blanks */
539: int nblank;
540: nblank = width
541: - (rzero < 0? 0: rzero)
542: - strlen (suffix)
543: - (p - bp)
544: - (lzero < 0? 0: lzero)
545: - strlen (prefix);
546:
547: /* Blanks on left if required */
548: if (!fminus)
549: while (--nblank >= 0)
550: emitchar (' ');
551:
552: /* Prefix, if any */
553: while (*prefix != '\0')
554: emitchar (*prefix++);
555:
556: /* Zeroes on the left */
557: while (--lzero >= 0)
558: emitchar ('0');
559:
560: /* The value itself */
561: while (bp < p)
562: emitchar (*bp++);
563:
564: /* Zeroes on the right */
565: while (--rzero >= 0)
566: emitchar ('0');
567:
568: /* The suffix */
569: while (*suffix != '\0')
570: emitchar (*suffix++);
571:
572: /* Blanks on the right if required */
573: if (fminus)
574: while (--nblank >= 0)
575: emitchar (' ');
576: }
577: }
578:
579: return (_pfile != NULL && ferror (_pfile))? EOF: count;
580: }
581:
582: /* Send a character to the output */
583: static
584: emitchar (c)
585: char c;
586: {
587: putc (c, iop);
588: ++count;
589: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.