[9] | 1 | /*
|
---|
| 2 | * fltpr.c - print floating point numbers
|
---|
| 3 | */
|
---|
| 4 | /* $Header: /cvsup/minix/src/lib/fphook/fphook.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
|
---|
| 5 |
|
---|
| 6 | #ifndef NOFLOAT
|
---|
| 7 | #include <string.h>
|
---|
| 8 | #include <stdarg.h>
|
---|
| 9 | #include "../stdio/loc_incl.h"
|
---|
| 10 | int _fp_hook = 1;
|
---|
| 11 |
|
---|
| 12 | static char *
|
---|
| 13 | _pfloat(long double r, register char *s, int n, int flags)
|
---|
| 14 | {
|
---|
| 15 | register char *s1;
|
---|
| 16 | int sign, dp;
|
---|
| 17 | register int i;
|
---|
| 18 |
|
---|
| 19 | s1 = _fcvt(r, n, &dp, &sign);
|
---|
| 20 | if (sign)
|
---|
| 21 | *s++ = '-';
|
---|
| 22 | else if (flags & FL_SIGN)
|
---|
| 23 | *s++ = '+';
|
---|
| 24 | else if (flags & FL_SPACE)
|
---|
| 25 | *s++ = ' ';
|
---|
| 26 |
|
---|
| 27 | if (dp<=0)
|
---|
| 28 | *s++ = '0';
|
---|
| 29 | for (i=dp; i>0; i--)
|
---|
| 30 | if (*s1) *s++ = *s1++;
|
---|
| 31 | else *s++ = '0';
|
---|
| 32 | if (((i=n) > 0) || (flags & FL_ALT))
|
---|
| 33 | *s++ = '.';
|
---|
| 34 | while (++dp <= 0) {
|
---|
| 35 | if (--i<0)
|
---|
| 36 | break;
|
---|
| 37 | *s++ = '0';
|
---|
| 38 | }
|
---|
| 39 | while (--i >= 0)
|
---|
| 40 | if (*s1) *s++ = *s1++;
|
---|
| 41 | else *s++ = '0';
|
---|
| 42 | return s;
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | static char *
|
---|
| 46 | _pscien(long double r, register char *s, int n, int flags)
|
---|
| 47 | {
|
---|
| 48 | int sign, dp;
|
---|
| 49 | register char *s1;
|
---|
| 50 |
|
---|
| 51 | s1 = _ecvt(r, n + 1, &dp, &sign);
|
---|
| 52 | if (sign)
|
---|
| 53 | *s++ = '-';
|
---|
| 54 | else if (flags & FL_SIGN)
|
---|
| 55 | *s++ = '+';
|
---|
| 56 | else if (flags & FL_SPACE)
|
---|
| 57 | *s++ = ' ';
|
---|
| 58 |
|
---|
| 59 | *s++ = *s1++;
|
---|
| 60 | if ((n > 0) || (flags & FL_ALT))
|
---|
| 61 | *s++ = '.';
|
---|
| 62 | while (--n >= 0)
|
---|
| 63 | if (*s1) *s++ = *s1++;
|
---|
| 64 | else *s++ = '0';
|
---|
| 65 | *s++ = 'e';
|
---|
| 66 | if ( r != 0 ) --dp ;
|
---|
| 67 | if ( dp<0 ) {
|
---|
| 68 | *s++ = '-' ; dp= -dp ;
|
---|
| 69 | } else {
|
---|
| 70 | *s++ = '+' ;
|
---|
| 71 | }
|
---|
| 72 | if (dp >= 100) {
|
---|
| 73 | *s++ = '0' + (dp / 100);
|
---|
| 74 | dp %= 100;
|
---|
| 75 | }
|
---|
| 76 | *s++ = '0' + (dp/10);
|
---|
| 77 | *s++ = '0' + (dp%10);
|
---|
| 78 | return s;
|
---|
| 79 | }
|
---|
| 80 |
|
---|
| 81 | #define NDIGINEXP(exp) (((exp) >= 100 || (exp) <= -100) ? 3 : 2)
|
---|
| 82 | #define LOW_EXP -4
|
---|
| 83 | #define USE_EXP(exp, ndigits) (((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
|
---|
| 84 |
|
---|
| 85 | static char *
|
---|
| 86 | _gcvt(long double value, int ndigit, char *s, int flags)
|
---|
| 87 | {
|
---|
| 88 | int sign, dp;
|
---|
| 89 | register char *s1, *s2;
|
---|
| 90 | register int i;
|
---|
| 91 | register int nndigit = ndigit;
|
---|
| 92 |
|
---|
| 93 | s1 = _ecvt(value, ndigit, &dp, &sign);
|
---|
| 94 | s2 = s;
|
---|
| 95 | if (sign) *s2++ = '-';
|
---|
| 96 | else if (flags & FL_SIGN)
|
---|
| 97 | *s2++ = '+';
|
---|
| 98 | else if (flags & FL_SPACE)
|
---|
| 99 | *s2++ = ' ';
|
---|
| 100 |
|
---|
| 101 | if (!(flags & FL_ALT))
|
---|
| 102 | for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
|
---|
| 103 | nndigit--;
|
---|
| 104 |
|
---|
| 105 | if (USE_EXP(dp,ndigit)) {
|
---|
| 106 | /* Use E format */
|
---|
| 107 | dp--;
|
---|
| 108 | *s2++ = *s1++;
|
---|
| 109 | if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
|
---|
| 110 | while (--nndigit > 0) *s2++ = *s1++;
|
---|
| 111 | *s2++ = 'e';
|
---|
| 112 | if (dp < 0) {
|
---|
| 113 | *s2++ = '-';
|
---|
| 114 | dp = -dp;
|
---|
| 115 | }
|
---|
| 116 | else *s2++ = '+';
|
---|
| 117 | s2 += NDIGINEXP(dp);
|
---|
| 118 | *s2 = 0;
|
---|
| 119 | for (i = NDIGINEXP(dp); i > 0; i--) {
|
---|
| 120 | *--s2 = dp % 10 + '0';
|
---|
| 121 | dp /= 10;
|
---|
| 122 | }
|
---|
| 123 | return s;
|
---|
| 124 | }
|
---|
| 125 | /* Use f format */
|
---|
| 126 | if (dp <= 0) {
|
---|
| 127 | if (*s1 != '0') {
|
---|
| 128 | /* otherwise the whole number is 0 */
|
---|
| 129 | *s2++ = '0';
|
---|
| 130 | *s2++ = '.';
|
---|
| 131 | }
|
---|
| 132 | while (dp < 0) {
|
---|
| 133 | dp++;
|
---|
| 134 | *s2++ = '0';
|
---|
| 135 | }
|
---|
| 136 | }
|
---|
| 137 | for (i = 1; i <= nndigit; i++) {
|
---|
| 138 | *s2++ = *s1++;
|
---|
| 139 | if (i == dp) *s2++ = '.';
|
---|
| 140 | }
|
---|
| 141 | if (i <= dp) {
|
---|
| 142 | while (i++ <= dp) *s2++ = '0';
|
---|
| 143 | *s2++ = '.';
|
---|
| 144 | }
|
---|
| 145 | if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
|
---|
| 146 | *s2 = '\0';
|
---|
| 147 | return s;
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | char *
|
---|
| 151 | _f_print(va_list *ap, int flags, char *s, char c, int precision)
|
---|
| 152 | {
|
---|
| 153 | register char *old_s = s;
|
---|
| 154 | long double ld_val;
|
---|
| 155 |
|
---|
| 156 | if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
|
---|
| 157 | else ld_val = (long double) va_arg(*ap, double);
|
---|
| 158 |
|
---|
| 159 | switch(c) {
|
---|
| 160 | case 'f':
|
---|
| 161 | s = _pfloat(ld_val, s, precision, flags);
|
---|
| 162 | break;
|
---|
| 163 | case 'e':
|
---|
| 164 | case 'E':
|
---|
| 165 | s = _pscien(ld_val, s, precision , flags);
|
---|
| 166 | break;
|
---|
| 167 | case 'g':
|
---|
| 168 | case 'G':
|
---|
| 169 | s = _gcvt(ld_val, precision, s, flags);
|
---|
| 170 | s += strlen(s);
|
---|
| 171 | break;
|
---|
| 172 | }
|
---|
| 173 | if ( c == 'E' || c == 'G') {
|
---|
| 174 | while (*old_s && *old_s != 'e') old_s++;
|
---|
| 175 | if (*old_s == 'e') *old_s = 'E';
|
---|
| 176 | }
|
---|
| 177 | return s;
|
---|
| 178 | }
|
---|
| 179 | #endif /* NOFLOAT */
|
---|
| 180 | /* $Header: /cvsup/minix/src/lib/fphook/fphook.c,v 1.1.1.1 2005/04/21 14:56:11 beng Exp $ */
|
---|
| 181 |
|
---|
| 182 | #include <stdlib.h>
|
---|
| 183 | #include "../ansi/ext_fmt.h"
|
---|
| 184 |
|
---|
| 185 | void _str_ext_cvt(const char *s, char **ss, struct EXTEND *e);
|
---|
| 186 | double _ext_dbl_cvt(struct EXTEND *e);
|
---|
| 187 |
|
---|
| 188 | double
|
---|
| 189 | strtod(const char *p, char **pp)
|
---|
| 190 | {
|
---|
| 191 | struct EXTEND e;
|
---|
| 192 |
|
---|
| 193 | _str_ext_cvt(p, pp, &e);
|
---|
| 194 | return _ext_dbl_cvt(&e);
|
---|
| 195 | }
|
---|