Inf and NaN values fixed and printing improved. "This time for sure!"
This commit is contained in:
parent
982a574e32
commit
8909e00b57
8
FIXES
8
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.
|
||||
|
4
bugs-fixed/inf-nan-torture.awk
Normal file
4
bugs-fixed/inf-nan-torture.awk
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
for (i = 1; i <= NF; i++)
|
||||
print i, $i, $i + 0
|
||||
}
|
1
bugs-fixed/inf-nan-torture.in
Normal file
1
bugs-fixed/inf-nan-torture.in
Normal file
@ -0,0 +1 @@
|
||||
-inf -inform inform -nan -nancy nancy -123 0 123 +123 nancy +nancy +nan inform +inform +inf
|
16
bugs-fixed/inf-nan-torture.ok
Normal file
16
bugs-fixed/inf-nan-torture.ok
Normal file
@ -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
|
32
lib.c
32
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;
|
||||
}
|
||||
|
2
main.c
2
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>
|
||||
|
15
tran.c
15
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); \
|
||||
|
Loading…
Reference in New Issue
Block a user