From 71cc2e70847d5a3b99c249fa609ea6ba8b1a00d6 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 4 Jul 2013 11:40:00 +0300 Subject: Fix for %c in multibyte locale + new tests. --- builtin.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'builtin.c') diff --git a/builtin.c b/builtin.c index ba1d8dcb..b8e24cb3 100644 --- a/builtin.c +++ b/builtin.c @@ -1097,6 +1097,7 @@ out0: * used to work? 6/2003.) */ cp = arg->stptr; + prec = 1; #if MBS_SUPPORT /* * First character can be multiple bytes if @@ -1108,17 +1109,14 @@ out0: memset(& state, 0, sizeof(state)); count = mbrlen(cp, arg->stlen, & state); - if (count == 0 - || count == (size_t)-1 - || count == (size_t)-2) - goto out2; - prec = count; - goto pr_tail; + if (count > 0) { + prec = count; + /* may need to increase fw so that padding happens, see pr_tail code */ + if (fw > 0) + fw += count - 1; + } } -out2: - ; #endif - prec = 1; goto pr_tail; case 's': need_format = false; @@ -1421,9 +1419,14 @@ mpf1: copy_count = prec; if (fw == 0 && ! have_prec) ; - else if (gawk_mb_cur_max > 1 && (cs1 == 's' || cs1 == 'c')) { - assert(cp == arg->stptr || cp == cpbuf); - copy_count = mbc_byte_count(arg->stptr, prec); + else if (gawk_mb_cur_max > 1) { + if (cs1 == 's') { + assert(cp == arg->stptr || cp == cpbuf); + copy_count = mbc_byte_count(arg->stptr, prec); + } + /* prec was set by code for %c */ + /* else + copy_count = prec; */ } bchunk(cp, copy_count); while (fw > prec) { -- cgit v1.2.3 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