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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
/*
* gawk wrapper for strtod
*/
/*
* Stupid version of System V strtod(3) library routine.
* Does no overflow/underflow checking.
*
* A real number is defined to be
* optional leading white space
* optional sign
* string of digits with optional decimal point
* optional 'e' or 'E'
* followed by optional sign or space
* followed by an integer
*
* if ptr is not NULL a pointer to the character terminating the
* scan is returned in *ptr. If no number formed, *ptr is set to str
* and 0 is returned.
*
* For speed, we don't do the conversion ourselves. Instead, we find
* the end of the number and then call atof() to do the dirty work.
* This bought us a 10% speedup on a sample program at uunet.uu.net.
*
* Fall 2000: Changed to enforce C89 semantics, so that 0x... returns 0.
* C99 has hexadecimal floating point numbers.
*
* Summer 2001. Try to make it smarter, so that a string like "0000"
* doesn't look like we failed. Sigh.
*
* Xmass 2002. Fix a bug in ptr determination, eg. for "0e0".
*
* Spring 2004. Update for I18N. Oh joy.
*/
#if 0
#include <ctype.h>
#endif
extern double atof();
double
gawk_strtod(s, ptr)
const char *s;
const char **ptr;
{
const char *start = s; /* save original start of string */
const char *begin = NULL; /* where the number really begins */
int dig = 0;
int dig0 = 0;
/* optional white space */
while (isspace(*s))
s++;
begin = s;
/* optional sign */
if (*s == '+' || *s == '-')
s++;
/* string of digits with optional decimal point */
while (*s == '0') {
s++;
dig0++;
}
while (isdigit(*s)) {
s++;
dig++;
}
if (
#if defined(HAVE_LOCALE_H)
loc.decimal_point != NULL && do_posix
? *s == loc.decimal_point[0]
: *s == '.'
#else
*s == '.'
#endif
) {
s++;
while (*s == '0') {
s++;
dig0++;
}
while (isdigit(*s)) {
s++;
dig++;
}
}
dig0 += dig; /* any digit has appeared */
/*
* optional 'e' or 'E'
* if a digit (or at least zero) was seen
* followed by optional sign
* followed by an integer
*/
if (dig0
&& (*s == 'e' || *s == 'E')
&& (isdigit(s[1])
|| ((s[1] == '-' || s[1] == '+') && isdigit(s[2])))) {
s++;
if (*s == '+' || *s == '-')
s++;
while (isdigit(*s))
s++;
}
/* In case we haven't found a number, set ptr to start. */
if (ptr)
*ptr = (dig0 ? s : start);
/* Go for it. */
return (dig ? atof(begin) : 0.0);
}
#ifdef TEST
int
main(argc, argv)
int argc;
char **argv;
{
double d;
char *p;
for (argc--, argv++; argc; argc--, argv++) {
d = strtod (*argv, & p);
printf ("%lf [%s]\n", d, p);
}
return 0;
}
#endif
|