From 373efa085dcea5fe6b4539cd875b6bd8645f16fa Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sun, 13 May 2018 10:02:01 +0200 Subject: Nelson H. F. Beebe: 19597 (rebased 42369): return Inf, NaN etc from floating point operations instead of errors to allow non-stop IEEE 754 arithmetic --- Src/math.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'Src/math.c') diff --git a/Src/math.c b/Src/math.c index c3831602b..cdfe80bb4 100644 --- a/Src/math.c +++ b/Src/math.c @@ -578,6 +578,37 @@ int outputradix; /**/ int outputunderscore; +#ifndef HAVE_ISINF +/**/ +int +isinf(double x) +{ + if ((-1.0 < x) && (x < 1.0)) /* x is small, and thus finite */ + return (0); + else if ((x + x) == x) /* only true if x == Infinity */ + return (1); + else /* must be finite (normal or subnormal), or NaN */ + return (0); +} +#endif + +#if !defined(HAVE_ISNAN) +/**/ +static double +store(double *x) +{ + return (*x); +} + +/**/ +int +isnan(double x) +{ + /* (x != x) should be sufficient, but some compilers incorrectly optimize it away */ + return (store(&x) != store(&x)); +} +#endif + /**/ static int zzlex(void) @@ -791,6 +822,21 @@ zzlex(void) break; /* Fall through! */ default: + if (strcmp(ptr-1, "NaN") == 0) { + yyval.type = MN_FLOAT; + yyval.u.d = 0.0; + yyval.u.d /= yyval.u.d; + ptr += 2; + return NUM; + } + else if (strcmp(ptr-1, "Inf") == 0) { + yyval.type = MN_FLOAT; + yyval.u.d = 0.0; + yyval.u.d = 1.0 / yyval.u.d; + ptr += 2; + return NUM; + } + if (idigit(*--ptr) || *ptr == '.') return lexconstant(); if (*ptr == '#') { @@ -1068,10 +1114,6 @@ callmathfunc(char *o) static int notzero(mnumber a) { - if ((a.type & MN_INTEGER) ? a.u.l == 0 : a.u.d == 0.0) { - zerr("division by zero"); - return 0; - } return 1; } -- cgit v1.2.3 From a93abe1170a438d45d94b3a7f924553f5cf69cee Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sun, 13 May 2018 10:13:42 +0200 Subject: 42488: test cases for 42369 and address some issues in the code --- ChangeLog | 4 ++++ Src/Modules/mathfunc.c | 51 +++++++++++++++++--------------------------------- Src/builtin.c | 10 ++++++++-- Src/math.c | 37 ++++++++++++++++++------------------ Test/B03print.ztst | 11 +++++++++++ Test/C01arith.ztst | 34 +++++++++++++++++++++++++++++++++ Test/V03mathfunc.ztst | 4 ++-- 7 files changed, 95 insertions(+), 56 deletions(-) (limited to 'Src/math.c') diff --git a/ChangeLog b/ChangeLog index 7d0c66bd1..50a32653d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2018-05-13 Oliver Kiddle + * 42488: Src/Modules/mathfunc.c, Src/builtin.c, Src/math.c, + Test/B03print.ztst, Test/C01arith.ztst, Test/V03mathfunc.ztst: + test cases for 42369 and address some issues in the code + * Nelson H. F. Beebe: 19597 (rebased 42369): Src/math.c, Src/params.c. Src/Modules/mathfunc.c, configure.ac: return Inf, NaN etc from floating point operations instead diff --git a/Src/Modules/mathfunc.c b/Src/Modules/mathfunc.c index a62154c50..01a2913ef 100644 --- a/Src/Modules/mathfunc.c +++ b/Src/Modules/mathfunc.c @@ -93,22 +93,6 @@ MS_RAND48 * conversion), atan2. */ -/* Flags for bounds. Note these must start at 1, not 0. */ - -enum { - BF_POS = 1, /* must be positive */ - BF_NONNEG = 2, /* must be non-negative */ - BF_FRAC = 3, /* must be -1 <= x <= 1 */ - BF_GE1 = 4, /* must be >= 1 */ - BF_FRACO = 5, /* must be in open range -1 < x < 1 */ - BF_INTPOS = 6, /* must be non-integer or positive */ - BF_GTRM1 = 7, /* must be > -1 */ - BF_NONZ = 8, /* must be nonzero */ - BF_POS2 = 9 /* second argument must be positive */ -}; - -#define BFLAG(x) ((x) << 8) - /* * Flags for type of function: unlike the above, these must * be individually bit-testable. @@ -121,18 +105,18 @@ enum { TF_NOASS = 8 /* don't assign result as double */ }; -#define TFLAG(x) ((x) << 16) +#define TFLAG(x) ((x) << 8) static struct mathfunc mftab[] = { - NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | BFLAG(BF_FRAC) | + NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | TFLAG(TF_NOCONV|TF_NOASS)), - NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS | BFLAG(BF_FRAC)), - NUMMATHFUNC("acosh", math_func, 1, 1, MF_ACOSH | BFLAG(BF_GE1)), - NUMMATHFUNC("asin", math_func, 1, 1, MF_ASIN | BFLAG(BF_FRAC)), + NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS), + NUMMATHFUNC("acosh", math_func, 1, 1, MF_ACOSH), + NUMMATHFUNC("asin", math_func, 1, 1, MF_ASIN), NUMMATHFUNC("asinh", math_func, 1, 1, MF_ASINH), NUMMATHFUNC("atan", math_func, 1, 2, MF_ATAN), - NUMMATHFUNC("atanh", math_func, 1, 1, MF_ATANH | BFLAG(BF_FRACO)), + NUMMATHFUNC("atanh", math_func, 1, 1, MF_ATANH), NUMMATHFUNC("cbrt", math_func, 1, 1, MF_CBRT), NUMMATHFUNC("ceil", math_func, 1, 1, MF_CEIL), NUMMATHFUNC("copysign", math_func, 2, 2, MF_COPYSIGN), @@ -146,20 +130,19 @@ static struct mathfunc mftab[] = { NUMMATHFUNC("float", math_func, 1, 1, MF_FLOAT), NUMMATHFUNC("floor", math_func, 1, 1, MF_FLOOR), NUMMATHFUNC("fmod", math_func, 2, 2, MF_FMOD), - NUMMATHFUNC("gamma", math_func, 1, 1, MF_GAMMA | BFLAG(BF_INTPOS)), + NUMMATHFUNC("gamma", math_func, 1, 1, MF_GAMMA), NUMMATHFUNC("hypot", math_func, 2, 2, MF_HYPOT), - NUMMATHFUNC("ilogb", math_func, 1, 1, MF_ILOGB | BFLAG(BF_NONZ) | - TFLAG(TF_NOASS)), + NUMMATHFUNC("ilogb", math_func, 1, 1, MF_ILOGB | TFLAG(TF_NOASS)), NUMMATHFUNC("int", math_func, 1, 1, MF_INT | TFLAG(TF_NOASS)), NUMMATHFUNC("j0", math_func, 1, 1, MF_J0), NUMMATHFUNC("j1", math_func, 1, 1, MF_J1), NUMMATHFUNC("jn", math_func, 2, 2, MF_JN | TFLAG(TF_INT1)), NUMMATHFUNC("ldexp", math_func, 2, 2, MF_LDEXP | TFLAG(TF_INT2)), - NUMMATHFUNC("lgamma", math_func, 1, 1, MF_LGAMMA | BFLAG(BF_INTPOS)), - NUMMATHFUNC("log", math_func, 1, 1, MF_LOG | BFLAG(BF_POS)), - NUMMATHFUNC("log10", math_func, 1, 1, MF_LOG10 | BFLAG(BF_POS)), - NUMMATHFUNC("log1p", math_func, 1, 1, MF_LOG1P | BFLAG(BF_GTRM1)), - NUMMATHFUNC("logb", math_func, 1, 1, MF_LOGB | BFLAG(BF_NONZ)), + NUMMATHFUNC("lgamma", math_func, 1, 1, MF_LGAMMA), + NUMMATHFUNC("log", math_func, 1, 1, MF_LOG), + NUMMATHFUNC("log10", math_func, 1, 1, MF_LOG10), + NUMMATHFUNC("log1p", math_func, 1, 1, MF_LOG1P), + NUMMATHFUNC("logb", math_func, 1, 1, MF_LOGB), NUMMATHFUNC("nextafter", math_func, 2, 2, MF_NEXTAFTER), #ifdef HAVE_ERAND48 STRMATHFUNC("rand48", math_string, MS_RAND48), @@ -171,12 +154,12 @@ static struct mathfunc mftab[] = { #endif NUMMATHFUNC("sin", math_func, 1, 1, MF_SIN), NUMMATHFUNC("sinh", math_func, 1, 1, MF_SINH), - NUMMATHFUNC("sqrt", math_func, 1, 1, MF_SQRT | BFLAG(BF_NONNEG)), + NUMMATHFUNC("sqrt", math_func, 1, 1, MF_SQRT), NUMMATHFUNC("tan", math_func, 1, 1, MF_TAN), NUMMATHFUNC("tanh", math_func, 1, 1, MF_TANH), - NUMMATHFUNC("y0", math_func, 1, 1, MF_Y0 | BFLAG(BF_POS)), - NUMMATHFUNC("y1", math_func, 1, 1, MF_Y1 | BFLAG(BF_POS)), - NUMMATHFUNC("yn", math_func, 2, 2, MF_YN | BFLAG(BF_POS2) | TFLAG(TF_INT1)) + NUMMATHFUNC("y0", math_func, 1, 1, MF_Y0), + NUMMATHFUNC("y1", math_func, 1, 1, MF_Y1), + NUMMATHFUNC("yn", math_func, 2, 2, MF_YN | TFLAG(TF_INT1)) }; /**/ diff --git a/Src/builtin.c b/Src/builtin.c index 73cfe7ad1..931605c6e 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -5234,8 +5234,14 @@ bin_print(char *name, char **args, Options ops, int func) errflag &= ~ERRFLAG_ERROR; ret = 1; } - print_val(doubleval) - break; + /* force consistent form for Inf/NaN output */ + if (isnan(doubleval)) + count += fputs("nan", fout); + else if (isinf(doubleval)) + count += fputs((doubleval < 0.0) ? "-inf" : "inf", fout); + else + print_val(doubleval) + break; case 3: #ifdef ZSH_64_BIT_UTYPE *d++ = 'l'; diff --git a/Src/math.c b/Src/math.c index cdfe80bb4..32bccc6e9 100644 --- a/Src/math.c +++ b/Src/math.c @@ -593,7 +593,6 @@ isinf(double x) #endif #if !defined(HAVE_ISNAN) -/**/ static double store(double *x) { @@ -816,27 +815,11 @@ zzlex(void) ptr++; break; } - case ' ': + case ' ': /* Fall through! */ case '\t': case '\n': break; - /* Fall through! */ default: - if (strcmp(ptr-1, "NaN") == 0) { - yyval.type = MN_FLOAT; - yyval.u.d = 0.0; - yyval.u.d /= yyval.u.d; - ptr += 2; - return NUM; - } - else if (strcmp(ptr-1, "Inf") == 0) { - yyval.type = MN_FLOAT; - yyval.u.d = 0.0; - yyval.u.d = 1.0 / yyval.u.d; - ptr += 2; - return NUM; - } - if (idigit(*--ptr) || *ptr == '.') return lexconstant(); if (*ptr == '#') { @@ -860,6 +843,20 @@ zzlex(void) p = ptr; ptr = ie; + if (ie - p == 3) { + if (strncasecmp(p, "NaN", 3) == 0) { + yyval.type = MN_FLOAT; + yyval.u.d = 0.0; + yyval.u.d /= yyval.u.d; + return NUM; + } + else if (strncasecmp(p, "Inf", 3) == 0) { + yyval.type = MN_FLOAT; + yyval.u.d = 0.0; + yyval.u.d = 1.0 / yyval.u.d; + return NUM; + } + } if (*ptr == '[' || (!cct && *ptr == '(')) { char op = *ptr, cp = ((*ptr == '[') ? ']' : ')'); int l; @@ -1114,6 +1111,10 @@ callmathfunc(char *o) static int notzero(mnumber a) { + if ((a.type & MN_INTEGER) && a.u.l == 0) { + zerr("division by zero"); + return 0; + } return 1; } diff --git a/Test/B03print.ztst b/Test/B03print.ztst index c65568ad9..0ef3743ce 100644 --- a/Test/B03print.ztst +++ b/Test/B03print.ztst @@ -86,6 +86,17 @@ >123.45 678 >90.1 0 + nan=0 inf=1 Infinity=2 + printf '%.1f\n' -inf Infinity Inf nan NaN -Inf -0.0 +0:infinity constants +>-inf +>inf +>inf +>nan +>nan +>-inf +>-0.0 + print -f 'arg: %b\n' -C2 '\x41' '\x42' '\x43' 0:override -C when -f was given >arg: A diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst index 30409adf3..77a46ebd5 100644 --- a/Test/C01arith.ztst +++ b/Test/C01arith.ztst @@ -302,6 +302,40 @@ ?(eval):1: bad math expression: operator expected at `2 ' # ` for emacs shell mode + in=1 info=2 Infinity=3 Inf=4 + print $(( in )) $(( info )) $(( Infinity )) $(( $Inf )) $(( inf )) $(( INF )) $(( Inf )) $(( iNF )) +0:Infinity parsing +>1 2 3 4 Inf Inf Inf Inf + + integer Inf + print $(( Inf[0] )) +1:Refer to Inf with an array subscript +?(eval):2: bad base syntax + + (( NaN = 1 )) +2:Assign to NaN +?(eval):1: bad math expression: lvalue required + + a='Inf' + (( b = 1e500 )) + print $((1e500)) $(($((1e500)))) $(( a )) $b $(( b )) $(( 3.0 / 0 )) +0:Overflow to infinity +>Inf Inf Inf Inf Inf Inf + + print $((1e500)) + print $(( $((1e500)) )) +0:Reinput infinity value into math context +>Inf +>Inf + + print $((1e500/1e500)) $((-1e500/1e500)) $(( 24. % 0 )) +0:NaN results +>NaN NaN NaN + + (( 3 / 0 )) +2:Integer division by zero +?(eval):1: division by zero + integer varassi print $(( varassi = 5.5 / 2.0 )) print $varassi diff --git a/Test/V03mathfunc.ztst b/Test/V03mathfunc.ztst index 1edb7a279..d6b4e0987 100644 --- a/Test/V03mathfunc.ztst +++ b/Test/V03mathfunc.ztst @@ -100,8 +100,8 @@ F:This test fails if your math library doesn't have erand48(). >1.50000 print $(( sqrt(-1) )) -1:Non-negative argument checking for square roots. -?(eval):1: math: argument to sqrt out of range +0:Non-negative argument checking for square roots. +>NaN # Simple test that the pseudorandom number generators are producing # something that could conceivably be pseudorandom numbers in a -- cgit v1.2.3 From baedd62f0d601bf03d99b2366a8ace42268e88ed Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Tue, 31 Jul 2018 22:15:58 +0900 Subject: 43219 (except term{cap,info}.c): fix several memory leaks --- ChangeLog | 6 ++++++ Src/Modules/db_gdbm.c | 5 ++++- Src/Modules/pcre.c | 1 + Src/Zle/compcore.c | 2 ++ Src/init.c | 3 ++- Src/math.c | 2 +- Src/subst.c | 2 +- 7 files changed, 17 insertions(+), 4 deletions(-) (limited to 'Src/math.c') diff --git a/ChangeLog b/ChangeLog index 465320208..e8acff0eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-07-31 Jun-ichi Takimoto + + * 43219 (except term{cap,info}.c): Src/Modules/db_gdbm.c, + Src/Modules/pcre.c, Src/Zle/compcore.c, Src/init.c, Src/math.c, + Src/subst.c: fix several memory leaks + 2018-07-30 Peter Stephenson * 43225: Src/Zle/zle_main.c: recalculate timeout after calling diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c index 5f776f407..ed702b912 100644 --- a/Src/Modules/db_gdbm.c +++ b/Src/Modules/db_gdbm.c @@ -359,7 +359,7 @@ gdbmsetfn(Param pm, char *val) } if (val) { - pm->u.str = ztrdup(val); + pm->u.str = val; pm->node.flags |= PM_UPTODATE; } @@ -732,6 +732,9 @@ static int remove_tied_name( const char *name ) { p++; } + if (*p) + zsfree(*p); + /* Copy x+1 to x */ while (*p) { *p=*(p+1); diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c index 15ee34bc8..6289e003e 100644 --- a/Src/Modules/pcre.c +++ b/Src/Modules/pcre.c @@ -380,6 +380,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) if (ovec) zfree(ovec, ovecsize*sizeof(int)); + zsfree(plaintext); return return_value; } diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index fd415da89..8eca39447 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -3556,6 +3556,8 @@ freematches(Cmgroup g, int cm) } free(g->expls); } + if (g->widths) + free(g->widths); zsfree(g->name); free(g); diff --git a/Src/init.c b/Src/init.c index c5372665a..e9e6be9b4 100644 --- a/Src/init.c +++ b/Src/init.c @@ -459,7 +459,8 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp, /* -c command */ *cmdp = *argv; new_opts[INTERACTIVE] &= 1; - scriptname = scriptfilename = ztrdup("zsh"); + if (toplevel) + scriptname = scriptfilename = ztrdup("zsh"); } else if (**argv == 'o') { if (!*++*argv) argv++; diff --git a/Src/math.c b/Src/math.c index 32bccc6e9..4b7ecf0ab 100644 --- a/Src/math.c +++ b/Src/math.c @@ -535,7 +535,7 @@ lexconstant(void) for (ptr2 = ptr; ptr2 < nptr; ptr2++) { if (*ptr2 == '_') { int len = nptr - ptr; - ptr = ztrdup(ptr); + ptr = dupstring(ptr); for (ptr2 = ptr; len; len--) { if (*ptr2 == '_') chuck(ptr2); diff --git a/Src/subst.c b/Src/subst.c index a265a187e..c1021fbf3 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -3169,7 +3169,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, zip = hmkarray(sval); } if (!isarr) { - aval = mkarray(val); + aval = hmkarray(val); isarr = 1; } if (zip) { -- cgit v1.2.3 From 225b35c9070f94cf79c90c33ffcee84b281f894d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 8 Aug 2018 17:11:54 +0100 Subject: 43261: Fix unary minus with base. Apply unary minus to a complete lexical constant rather than the first component that comes along. --- ChangeLog | 5 +++++ Src/math.c | 15 +++++++++++++-- Test/C01arith.ztst | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'Src/math.c') diff --git a/ChangeLog b/ChangeLog index 7a4cb05a2..28f70f48a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-08-08 Peter Stephenson + + * 43261: Src/math.c, Test/C01arith.ztst: Apply unary minus to + entire lexical constant, so base doesn't get treated as negative. + 2018-08-07 Peter Stephenson * Anton Shestakov: 43254: Completion/Unix/Command/_hg: Remove hg diff --git a/Src/math.c b/Src/math.c index 4b7ecf0ab..b08e05cb4 100644 --- a/Src/math.c +++ b/Src/math.c @@ -640,8 +640,19 @@ zzlex(void) } if (unary) { if (idigit(*ptr) || *ptr == '.') { - ptr--; - return lexconstant(); + int ctype = lexconstant(); + if (ctype == NUM) + { + if (yyval.type == MN_FLOAT) + { + yyval.u.d = -yyval.u.d; + } + else + { + yyval.u.l = -yyval.u.l; + } + } + return ctype; } else return UMINUS; } else diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst index 77a46ebd5..f1364ab36 100644 --- a/Test/C01arith.ztst +++ b/Test/C01arith.ztst @@ -467,3 +467,7 @@ >6 >4 ?(eval):6: bad math expression: lvalue required + + print $(( -2#101-16#f )) +0: Unary minus doesn't apply to base but to number as a whole. +>-20 -- cgit v1.2.3