diff options
-rw-r--r-- | usr.bin/awk/FIXES | 14 | ||||
-rw-r--r-- | usr.bin/awk/lib.c | 44 | ||||
-rw-r--r-- | usr.bin/awk/main.c | 4 | ||||
-rw-r--r-- | usr.bin/awk/tran.c | 17 |
4 files changed, 49 insertions, 30 deletions
diff --git a/usr.bin/awk/FIXES b/usr.bin/awk/FIXES index cb35981b64d..05f47946793 100644 --- a/usr.bin/awk/FIXES +++ b/usr.bin/awk/FIXES @@ -1,4 +1,4 @@ -/* $OpenBSD: FIXES,v 1.39 2020/12/09 20:00:11 millert Exp $ */ +/* $OpenBSD: FIXES,v 1.40 2020/12/18 21:36:24 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -26,6 +26,18 @@ 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. + December 8, 2020: Merge PR #98: Disallow hex data. Allow only +nan, -nan, +inf, -inf (case independent) to give NaN and infinity values. diff --git a/usr.bin/awk/lib.c b/usr.bin/awk/lib.c index 61d9b7a05ee..8cbdd6d29c6 100644 --- a/usr.bin/awk/lib.c +++ b/usr.bin/awk/lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lib.c,v 1.43 2020/12/17 20:06:09 millert Exp $ */ +/* $OpenBSD: lib.c,v 1.44 2020/12/18 21:36:24 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -31,6 +31,7 @@ THIS SOFTWARE. #include <stdlib.h> #include <stdarg.h> #include <limits.h> +#include <math.h> #include "awk.h" char EMPTY[] = { '\0' }; @@ -784,6 +785,8 @@ 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; @@ -792,47 +795,38 @@ bool is_valid_number(const char *s, bool trailing_stuff_ok, s++; // no hex floating point, sorry - if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + if (s[0] == '0' && tolower((uschar)s[1]) == 'x') return false; // allow +nan, -nan, +inf, -inf, any other letter, no if (s[0] == '+' || s[0] == '-') { - if ((strncasecmp(s+1, "nan", 3) == 0 || - strncasecmp(s+1, "inf", 3) == 0)) { - trailing_stuff_ok = false; - ep = (char *)(long)s + 4; - if (isspace((uschar)*ep)) { - trailing_stuff_ok = true; - do { - ep++; - } while (isspace((uschar)*ep)); - } - if (no_trailing) - *no_trailing = (*ep == '\0'); - if (*ep != '\0' && !trailing_stuff_ok) - return false; - } else if (! isdigit((uschar)s[1]) && s[1] != '.') + is_nan = (strncasecmp(s+1, "nan", 3) == 0); + is_inf = (strncasecmp(s+1, "inf", 3) == 0); + if ((is_nan || is_inf) + && (isspace((uschar)s[4]) || s[4] == '\0')) + goto convert; + else if (! isdigit((uschar)s[1]) && s[1] != '.') return false; - } else if (! isdigit((uschar)s[0]) && s[0] != '.') + } + else if (! isdigit((uschar)s[0]) && s[0] != '.') return false; +convert: errno = 0; r = strtod(s, &ep); 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 - while (isspace((uschar)*ep)) - ep++; + retval = (isspace((uschar)*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/usr.bin/awk/main.c b/usr.bin/awk/main.c index 6aac4d5fa64..5a195940b94 100644 --- a/usr.bin/awk/main.c +++ b/usr.bin/awk/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.46 2020/12/09 20:00:11 millert Exp $ */ +/* $OpenBSD: main.c,v 1.47 2020/12/18 21:36:24 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -23,7 +23,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ -const char *version = "version 20201208"; +const char *version = "version 20201218"; #define DEBUG #include <stdio.h> diff --git a/usr.bin/awk/tran.c b/usr.bin/awk/tran.c index 1ea64d240d8..41a0faa4a4d 100644 --- a/usr.bin/awk/tran.c +++ b/usr.bin/awk/tran.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tran.c,v 1.32 2020/12/09 20:00:11 millert Exp $ */ +/* $OpenBSD: tran.c,v 1.33 2020/12/18 21:36:24 millert Exp $ */ /**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved @@ -419,10 +419,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 */ { int n; double dtemp; + char *p; if ((vp->tval & (NUM | STR)) == 0) funnyvar(vp, "read value of"); @@ -459,7 +470,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) \ + n = (vp->sval = strdup(p)) ? 0 : -1; \ + else if (modf(vp->fval, &dtemp) == 0) /* it's integral */ \ n = asprintf(&vp->sval, "%.30g", vp->fval); \ else \ n = asprintf(&vp->sval, *fmt, vp->fval); \ |