From c3e4d0cf3f1fd24164e0a58db23b86b56c6dc7c8 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 8 Sep 2013 12:46:20 +0200 Subject: Fixes based on problems from a static checker. --- builtin.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index b8e24cb3..eb823ac1 100644 --- a/builtin.c +++ b/builtin.c @@ -2955,13 +2955,16 @@ set_how_many: done: DEREF(s); - if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL) + if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL) { efree(buf); + buf = NULL; + } if (flags & GENSUB) { if (matches > 0) { /* return the result string */ DEREF(t); + assert(buf != NULL); return make_str_node(buf, textlen, ALREADY_MALLOCED); } -- cgit v1.2.3 From 2fcffaeee37416708fab505209a55ddd32846463 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 13 Sep 2013 15:37:25 +0300 Subject: Fix problem when extending NF. See test/nfloop. --- builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index eb823ac1..9258ea60 100644 --- a/builtin.c +++ b/builtin.c @@ -2159,7 +2159,7 @@ do_print_rec(int nargs, int redirtype) f0 = fields_arr[0]; - if (do_lint && f0 == Nnull_string) + if (do_lint && (f0->flags & NULL_FIELD) != 0) lintwarn(_("reference to uninitialized field `$%d'"), 0); efwrite(f0->stptr, sizeof(char), f0->stlen, fp, "print", rp, false); -- cgit v1.2.3 From 026a126c27f648839325c7fadb37c42d2935f467 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 25 Sep 2013 12:59:21 +0300 Subject: Improvements in the random number generator. --- builtin.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 9258ea60..925a92bd 100644 --- a/builtin.c +++ b/builtin.c @@ -2372,6 +2372,8 @@ static char *const state = (char *const) istate; NODE * do_rand(int nargs ATTRIBUTE_UNUSED) { + double tmprand; +#define RAND_DIVISOR ((double)GAWK_RANDOM_MAX+1.0) if (firstrand) { (void) initstate((unsigned) 1, state, SIZEOF_STATE); /* don't need to srandom(1), initstate() does it for us. */ @@ -2383,7 +2385,24 @@ do_rand(int nargs ATTRIBUTE_UNUSED) * * 0 <= n < 1 */ - return make_number((AWKNUM) (random() % GAWK_RANDOM_MAX) / GAWK_RANDOM_MAX); + /* + * Date: Wed, 28 Aug 2013 17:52:46 -0700 + * From: Bob Jewett + * + * Call random() twice to fill in more bits in the value + * of the double. Also, there is a bug in random() such + * that when the values of successive values are combined + * like (rand1*rand2)^2, (rand3*rand4)^2, ... the + * resulting time series is not white noise. The + * following also seems to fix that bug. + * + * The add/subtract 0.5 keeps small bits from filling + * below 2^-53 in the double, not that anyone should be + * looking down there. + */ + + tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); + return make_number((AWKNUM) (tmprand - 0.5)); } /* do_srand --- seed the random number generator */ -- cgit v1.2.3 From a7fd49bcce48fdda13d635d9b6f946c11abae35b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 16 Oct 2013 05:27:11 +0300 Subject: Minor fix in do_rand(). --- builtin.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 925a92bd..740c88b2 100644 --- a/builtin.c +++ b/builtin.c @@ -2399,9 +2399,44 @@ do_rand(int nargs ATTRIBUTE_UNUSED) * The add/subtract 0.5 keeps small bits from filling * below 2^-53 in the double, not that anyone should be * looking down there. + * + * Date: Wed, 25 Sep 2013 10:45:38 -0600 (MDT) + * From: "Nelson H. F. Beebe" + * (4) The code is typical of many published fragments for converting + * from integer to floating-point, and I discuss the serious pitfalls + * in my book, because it leads to platform-dependent behavior at the + * end points of the interval [0,1] + * + * (5) the documentation in the gawk info node says + * + * `rand()' + * Return a random number. The values of `rand()' are uniformly + * distributed between zero and one. The value could be zero but is + * never one.(1) + * + * The division by RAND_DIVISOR may not guarantee that 1.0 is never + * returned: the programmer forgot the platform-dependent issue of + * rounding. + * + * For points 4 and 5, the safe way is a loop: + * + * double + * rand(void) // return value in [0.0, 1.0) + * { + * value = internal_rand(); + * + * while (value == 1.0) + * value = internal_rand(); + * + * return (value); + * } */ tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); + + while (tmprand == 1.0) + tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); + return make_number((AWKNUM) (tmprand - 0.5)); } -- cgit v1.2.3 From a0ca839420118a77a19a8ab05d08f58a076edd17 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 17 Oct 2013 22:08:24 +0300 Subject: Additional fix in do_rand. --- builtin.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 740c88b2..4f1914f4 100644 --- a/builtin.c +++ b/builtin.c @@ -2432,12 +2432,13 @@ do_rand(int nargs ATTRIBUTE_UNUSED) * } */ - tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); + do { + tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) + / RAND_DIVISOR); + tmprand -= 0.5; + } while (tmprand == 1.0); - while (tmprand == 1.0) - tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); - - return make_number((AWKNUM) (tmprand - 0.5)); + return make_number((AWKNUM) tmprand); } /* do_srand --- seed the random number generator */ -- cgit v1.2.3 From 62c42c359af9b08180d25d3075a1b8ca5d52dee6 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 1 Nov 2013 09:34:56 +0200 Subject: Additional work for EPIPE errors on stdout. --- builtin.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 9258ea60..bb7050b0 100644 --- a/builtin.c +++ b/builtin.c @@ -125,6 +125,11 @@ efwrite(const void *ptr, return; wrerror: + /* die silently on EPIPE to stdout */ + if (fp == stdout && errno == EPIPE) + gawk_exit(EXIT_FATAL); + + /* otherwise die verbosely */ fatal(_("%s to \"%s\" failed (%s)"), from, rp ? rp->value : _("standard output"), errno ? strerror(errno) : _("reason unknown")); -- cgit v1.2.3 From 71e06c39df20400fbc04d7a3eba04700c27928f8 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 10 Dec 2013 21:04:14 +0200 Subject: Remove unneeded Floor and Ceil wrapper functions. --- builtin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index bb7050b0..7a969cbc 100644 --- a/builtin.c +++ b/builtin.c @@ -469,9 +469,9 @@ double double_to_int(double d) { if (d >= 0) - d = Floor(d); + d = floor(d); else - d = Ceil(d); + d = ceil(d); return d; } -- cgit v1.2.3 From d80438ac6fef9137ab0450f02cd507d422aa9c32 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 27 Feb 2014 06:01:30 +0200 Subject: Lots of enum/int fixes. --- builtin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 7a969cbc..72aea3b0 100644 --- a/builtin.c +++ b/builtin.c @@ -719,7 +719,7 @@ format_tree( mpz_ptr zi; mpfr_ptr mf; #endif - enum { MP_INT_WITH_PREC = 1, MP_INT_WITHOUT_PREC, MP_FLOAT } fmt_type; + enum { MP_NONE = 0, MP_INT_WITH_PREC = 1, MP_INT_WITHOUT_PREC, MP_FLOAT } fmt_type; static const char sp[] = " "; static const char zero_string[] = "0"; @@ -817,7 +817,7 @@ format_tree( mf = NULL; zi = NULL; #endif - fmt_type = 0; + fmt_type = MP_NONE; lj = alt = big_flag = bigbig_flag = small_flag = false; fill = sp; -- cgit v1.2.3 From 31206f0309881ee76cb7aba8c7537b15c34b78aa Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 5 Mar 2014 22:28:40 +0200 Subject: Minor fix for mktime. --- builtin.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 72aea3b0..ffc303ab 100644 --- a/builtin.c +++ b/builtin.c @@ -1999,10 +1999,10 @@ do_mktime(int nargs) & hour, & minute, & second, & dst); - if (do_lint /* Ready? Set! Go: */ - && ( (second < 0 || second > 60) - || (minute < 0 || minute > 60) - || (hour < 0 || hour > 23) + if ( do_lint /* Ready? Set! Go: */ + && ( (second < 0 || second > 60) + || (minute < 0 || minute > 59) + || (hour < 0 || hour > 23) /* FIXME ISO 8601 allows 24 ? */ || (day < 1 || day > 31) || (month < 1 || month > 12) )) lintwarn(_("mktime: at least one of the values is out of the default range")); -- cgit v1.2.3 From 379f62687358dfda19694dea92389e092372fc2c Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 10 Mar 2014 22:35:01 +0200 Subject: Fix thousands separator problems and update doc. --- builtin.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index ffc303ab..7a6bfc62 100644 --- a/builtin.c +++ b/builtin.c @@ -994,9 +994,7 @@ check_pos: goto check_pos; case '\'': #if defined(HAVE_LOCALE_H) - /* allow quote_flag if there is a thousands separator. */ - if (loc.thousands_sep[0] != '\0') - quote_flag = true; + quote_flag = true; goto check_pos; #else goto retry; @@ -1196,6 +1194,9 @@ out0: } if (i < 1) goto out_of_range; +#if defined(HAVE_LOCALE_H) + quote_flag = (quote_flag && loc.thousands_sep[0] != 0); +#endif chp = &cpbufs[1].buf[i-1]; ii = jj = 0; do { @@ -1203,8 +1204,14 @@ out0: chp--; i--; #if defined(HAVE_LOCALE_H) if (quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) { - if (i) /* only add if more digits coming */ - PREPEND(loc.thousands_sep[0]); /* XXX - assumption it's one char */ + if (i) { /* only add if more digits coming */ + int k; + const char *ts = loc.thousands_sep; + + for (k = strlen(ts) - 1; k >= 0; k--) { + PREPEND(ts[k]); + } + } if (loc.grouping[ii+1] == 0) jj = 0; /* keep using current val in loc.grouping[ii] */ else if (loc.grouping[ii+1] == CHAR_MAX) @@ -1359,6 +1366,9 @@ mpf1: } #ifdef HAVE_MPFR int0: +#endif +#if defined(HAVE_LOCALE_H) + quote_flag = (quote_flag && loc.thousands_sep[0] != 0); #endif /* * When to fill with zeroes is of course not simple. @@ -1378,8 +1388,14 @@ mpf1: uval /= base; #if defined(HAVE_LOCALE_H) if (base == 10 && quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) { - if (uval) /* only add if more digits coming */ - PREPEND(loc.thousands_sep[0]); /* XXX --- assumption it's one char */ + if (uval) { /* only add if more digits coming */ + int k; + const char *ts = loc.thousands_sep; + + for (k = strlen(ts) - 1; k >= 0; k--) { + PREPEND(ts[k]); + } + } if (loc.grouping[ii+1] == 0) jj = 0; /* keep using current val in loc.grouping[ii] */ else if (loc.grouping[ii+1] == CHAR_MAX) -- cgit v1.2.3 From 69d85d51dfd0f2e3b464585633d270f06fa1e846 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 31 Mar 2014 22:17:13 +0300 Subject: Update copyright years on files changed in 2014. --- builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index 7a6bfc62..b5d38d8d 100644 --- a/builtin.c +++ b/builtin.c @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 1986, 1988, 1989, 1991-2013 the Free Software Foundation, Inc. + * Copyright (C) 1986, 1988, 1989, 1991-2014 the Free Software Foundation, Inc. * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. -- cgit v1.2.3