aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2020-12-18 11:57:48 +0200
committerArnold D. Robbins <arnold@skeeve.com>2020-12-18 11:57:48 +0200
commit8909e00b57874e5858a210bc3a7e9e56e10eda35 (patch)
treedb83320920f990dba04c735f5df721bfab2dfcac
parent982a574e3282e0cb650b6e34f694ca191cb73fd4 (diff)
downloadone-true-awk-8909e00b57874e5858a210bc3a7e9e56e10eda35.tar.gz
Inf and NaN values fixed and printing improved. "This time for sure!"
-rw-r--r--FIXES8
-rw-r--r--bugs-fixed/inf-nan-torture.awk4
-rw-r--r--bugs-fixed/inf-nan-torture.in1
-rw-r--r--bugs-fixed/inf-nan-torture.ok16
-rw-r--r--lib.c32
-rw-r--r--main.c2
-rw-r--r--tran.c15
7 files changed, 61 insertions, 17 deletions
diff --git a/FIXES b/FIXES
index 0add0eb..20b4bd8 100644
--- a/FIXES
+++ b/FIXES
@@ -25,6 +25,14 @@ THIS SOFTWARE.
This file lists all bug fixes, changes, etc., made since the AWK book
was sent to the printers in August, 1987.
+December 18, 2020:
+ Fix problems converting inf and NaN values in lib.c:is_valid_number.
+ Enhance number to string conversion to do the right thing for
+ NaN and inf values. Things are now pretty much the same as in
+ gawk. (Found a gawk bug while we're at it.) Added a torture
+ test for these values. Thanks to Arnold Robbins. Allows closing
+ of PR #101.
+
December 15, 2020:
Merge PR #99, which gets the right header for strcasecmp.
Thanks to GitHub user michaelforney.
diff --git a/bugs-fixed/inf-nan-torture.awk b/bugs-fixed/inf-nan-torture.awk
new file mode 100644
index 0000000..8d145f2
--- /dev/null
+++ b/bugs-fixed/inf-nan-torture.awk
@@ -0,0 +1,4 @@
+{
+ for (i = 1; i <= NF; i++)
+ print i, $i, $i + 0
+}
diff --git a/bugs-fixed/inf-nan-torture.in b/bugs-fixed/inf-nan-torture.in
new file mode 100644
index 0000000..45dfdc8
--- /dev/null
+++ b/bugs-fixed/inf-nan-torture.in
@@ -0,0 +1 @@
+-inf -inform inform -nan -nancy nancy -123 0 123 +123 nancy +nancy +nan inform +inform +inf
diff --git a/bugs-fixed/inf-nan-torture.ok b/bugs-fixed/inf-nan-torture.ok
new file mode 100644
index 0000000..40d3194
--- /dev/null
+++ b/bugs-fixed/inf-nan-torture.ok
@@ -0,0 +1,16 @@
+1 -inf -inf
+2 -inform 0
+3 inform 0
+4 -nan -nan
+5 -nancy 0
+6 nancy 0
+7 -123 -123
+8 0 0
+9 123 123
+10 +123 123
+11 nancy 0
+12 +nancy 0
+13 +nan +nan
+14 inform 0
+15 +inform 0
+16 +inf +inf
diff --git a/lib.c b/lib.c
index c200114..e8310a9 100644
--- a/lib.c
+++ b/lib.c
@@ -784,46 +784,48 @@ bool is_valid_number(const char *s, bool trailing_stuff_ok,
double r;
char *ep;
bool retval = false;
+ bool is_nan = false;
+ bool is_inf = false;
if (no_trailing)
*no_trailing = false;
- while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
+ while (isspace(*s))
s++;
- if (s[0] == '0' && tolower(s[1]) == 'x') // no hex floating point, sorry
+ // no hex floating point, sorry
+ if (s[0] == '0' && tolower(s[1]) == 'x')
return false;
// allow +nan, -nan, +inf, -inf, any other letter, no
if (s[0] == '+' || s[0] == '-') {
- if (strcasecmp(s+1, "nan") == 0 || strcasecmp(s+1, "inf") == 0)
- return true;
+ is_nan = (strncasecmp(s+1, "nan", 3) == 0);
+ is_inf = (strncasecmp(s+1, "inf", 3) == 0);
+ if ((is_nan || is_inf)
+ && (isspace(s[4]) || s[4] == '\0'))
+ goto convert;
else if (! isdigit(s[1]) && s[1] != '.')
return false;
}
else if (! isdigit(s[0]) && s[0] != '.')
return false;
+convert:
errno = 0;
r = strtod(s, &ep);
- if (ep == s || r == HUGE_VAL || errno == ERANGE)
+ if (ep == s || errno == ERANGE)
return false;
+ if (isnan(r) && s[0] == '-' && signbit(r) == 0)
+ r = -r;
+
if (result != NULL)
*result = r;
- /*
- * check for trailing stuff
- * allow \r as well. windows files aren't going to go away.
- */
- while (*ep == ' ' || *ep == '\t' || *ep == '\n' || *ep == '\r')
- ep++;
+ retval = (isspace(*ep) || *ep == '\0' || trailing_stuff_ok);
- if (no_trailing)
+ if (no_trailing != NULL)
*no_trailing = (*ep == '\0');
- // return true if found the end, or trailing stuff is allowed
- retval = (*ep == '\0') || trailing_stuff_ok;
-
return retval;
}
diff --git a/main.c b/main.c
index 22e52f6..5970cb4 100644
--- a/main.c
+++ b/main.c
@@ -22,7 +22,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
-const char *version = "version 20201215";
+const char *version = "version 20201218";
#define DEBUG
#include <stdio.h>
diff --git a/tran.c b/tran.c
index 0ce45db..add9d85 100644
--- a/tran.c
+++ b/tran.c
@@ -418,10 +418,21 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */
return(vp->fval);
}
+static char *get_inf_nan(double d)
+{
+ if (isinf(d)) {
+ return (d < 0 ? "-inf" : "+inf");
+ } else if (isnan(d)) {
+ return (signbit(d) != 0 ? "-nan" : "+nan");
+ } else
+ return NULL;
+}
+
static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
{
char s[256];
double dtemp;
+ char *p;
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, "read value of");
@@ -458,7 +469,9 @@ static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cel
{ \
if (freeable(vp)) \
xfree(vp->sval); \
- if (modf(vp->fval, &dtemp) == 0) /* it's integral */ \
+ if ((p = get_inf_nan(vp->fval)) != NULL) \
+ strcpy(s, p); \
+ else if (modf(vp->fval, &dtemp) == 0) /* it's integral */ \
snprintf(s, sizeof (s), "%.30g", vp->fval); \
else \
snprintf(s, sizeof (s), *fmt, vp->fval); \