aboutsummaryrefslogtreecommitdiffstats
path: root/missing_d/strtod.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-07-16 13:09:56 +0300
committerArnold D. Robbins <arnold@skeeve.com>2010-07-16 13:09:56 +0300
commitbc70de7b3302d5a81515b901cae376b8b51d2004 (patch)
treed36d6743e65697f6923b79d0ea8f9f9bf4ef7398 /missing_d/strtod.c
parentb9e4a1fd4c8c8753ab8a9887bab55f03efe1e3e2 (diff)
downloadegawk-bc70de7b3302d5a81515b901cae376b8b51d2004.tar.gz
egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.tar.bz2
egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.zip
Move to gawk-3.1.0.
Diffstat (limited to 'missing_d/strtod.c')
-rw-r--r--missing_d/strtod.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/missing_d/strtod.c b/missing_d/strtod.c
new file mode 100644
index 00000000..cdcefe9f
--- /dev/null
+++ b/missing_d/strtod.c
@@ -0,0 +1,126 @@
+/*
+ * strtod.c
+ *
+ * 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.
+ */
+
+#if 0
+#include <ctype.h>
+#endif
+
+extern double atof();
+
+double
+gawk_strtod(s, ptr)
+register const char *s;
+register const char **ptr;
+{
+ double ret = 0.0;
+ const char *start = s;
+ const char *begin = NULL;
+ int success = 0;
+
+ /* optional white space */
+ while (isspace(*s))
+ s++;
+
+ /* optional sign */
+ if (*s == '+' || *s == '-') {
+ s++;
+ if (*(s-1) == '-')
+ begin = s - 1;
+ else
+ begin = s;
+ }
+
+ /* string of digits with optional decimal point */
+ if (isdigit(*s) && ! begin)
+ begin = s;
+
+ while (isdigit(*s)) {
+ /* don't succeed on 0x... */
+ if (*s > '0')
+ success++;
+ s++;
+ }
+
+ if (*s == '.') {
+ if (! begin)
+ begin = s;
+ s++;
+ while (isdigit(*s))
+ s++;
+ success++;
+ }
+
+ if (s == start || success == 0) /* nothing there */
+ goto out;
+
+ /*
+ * optional 'e' or 'E'
+ * followed by optional sign or space
+ * followed by an integer
+ */
+
+ if ((*s == 'e' || *s == 'E')
+ && (isdigit(s[1])
+ || ((s[1] == '-' || s[1] == '+') && isdigit(s[2])))) {
+ s++;
+
+ if (*s == '+' || *s == '-')
+ s++;
+
+ while (isdigit(*s))
+ s++;
+ }
+
+ /* go for it */
+ ret = atof(begin);
+
+out:
+ if (! success)
+ s = start; /* in case all we did was skip whitespace */
+
+ if (ptr)
+ *ptr = s;
+
+ return ret;
+}
+
+#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