aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--interpret.h27
-rw-r--r--node.c20
-rw-r--r--test/ChangeLog6
-rw-r--r--test/Makefile.am12
-rw-r--r--test/Makefile.in12
-rw-r--r--test/mpfrfield.awk14
-rw-r--r--test/mpfrfield.in10
-rw-r--r--test/mpfrfield.ok1
9 files changed, 102 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index ff451ac9..c0012ba4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2018-04-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ Fix a nasty MPFR bug in r_dupnode. If the value being copied
+ is MPFN / MPFR, copy those bits over too. Thanks to
+ Noah Dean <N.Dean@gaminglabs.com> for the report.
+
+ * node.c (r_dupnode): Check for MPFN / MPFR and copy the bits
+ over as needed.
+
+ Unrelated:
+
+ * interpret.h (UNFIELD): Turn into an inline function and
+ let UNFIELD macro call it, allows stepping in with a debugger.
+ (unfield): Function holding former body of UNFIELD macro.
+
2018-03-26 Arnold D. Robbins <arnold@skeeve.com>
Remove the tail recursion optimization. It's fundamentally
diff --git a/interpret.h b/interpret.h
index 96e2c890..20fcb7ad 100644
--- a/interpret.h
+++ b/interpret.h
@@ -32,16 +32,25 @@
* valref 1, that effectively means that this is an assignment like "$n = $n",
* so a no-op, other than triggering $0 reconstitution.
*/
-#define UNFIELD(l, r) \
-{ \
- /* if was a field, turn it into a var */ \
- if ((r->flags & MALLOC) != 0 || r->valref == 1) { \
- l = r; \
- } else { \
- l = dupnode(r); \
- DEREF(r); \
- } \
+
+// not a macro so we can step into it with a debugger
+#ifndef UNFIELD_DEFINED
+#define UNFIELD_DEFINED 1
+static inline void
+unfield(NODE **l, NODE **r)
+{
+ /* if was a field, turn it into a var */
+ if (((*r)->flags & MALLOC) != 0 || (*r)->valref == 1) {
+ (*l) = (*r);
+ } else {
+ (*l) = dupnode(*r);
+ DEREF(*r);
+ }
}
+
+#define UNFIELD(l, r) unfield(& (l), & (r))
+#endif
+
int
r_interpret(INSTRUCTION *code)
{
diff --git a/node.c b/node.c
index add959f7..fcd2bf33 100644
--- a/node.c
+++ b/node.c
@@ -306,8 +306,24 @@ r_dupnode(NODE *n)
}
#endif
- getnode(r);
- *r = *n;
+#ifdef HAVE_MPFR
+ if ((n->flags & MPZN) != 0) {
+ r = mpg_integer();
+ mpz_set(r->mpg_i, n->mpg_i);
+ r->flags = n->flags;
+ } else if ((n->flags & MPFN) != 0) {
+ r = mpg_float();
+ int tval = mpfr_set(r->mpg_numbr, n->mpg_numbr, ROUND_MODE);
+ IEEE_FMT(r->mpg_numbr, tval);
+ r->flags = n->flags;
+ } else {
+#endif
+ getnode(r);
+ *r = *n;
+#ifdef HAVE_MPFR
+ }
+#endif
+
r->flags |= MALLOC;
r->valref = 1;
/*
diff --git a/test/ChangeLog b/test/ChangeLog
index e075e3ac..5f806e11 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,9 @@
+2018-04-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (EXTRA_DIST): Add files for mpfrfield.
+ (MPFR_TESTS): Add mpfrfield.
+ * mpfrfield.awk, mpfrfield.awk, mpfrfield.ok: New files.
+
2018-03-26 Arnold D. Robbins <arnold@skeeve.com>
* fwtest3.in, mmap8k.awk, mmap8k.ok, rsstart2.in: New files.
diff --git a/test/Makefile.am b/test/Makefile.am
index bfb0c4b3..fe4fd816 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -658,6 +658,9 @@ EXTRA_DIST = \
mpfrbigint.ok \
mpfrexprange.awk \
mpfrexprange.ok \
+ mpfrfield.awk \
+ mpfrfield.in \
+ mpfrfield.ok \
mpfrieee.awk \
mpfrieee.ok \
mpfrmemok1.awk \
@@ -1307,8 +1310,8 @@ INET_TESTS = inetdayu inetdayt inetechu inetecht
MACHINE_TESTS = double1 double2 fmtspcl intformat
-MPFR_TESTS = mpfrbigint mpfrexprange mpfrieee mpfrmemok1 mpfrnegzero \
- mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \
+MPFR_TESTS = mpfrbigint mpfrexprange mpfrfield mpfrieee mpfrmemok1 \
+ mpfrnegzero mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \
mpfrstrtonum mpgforcenum mpfruplus
LOCALE_CHARSET_TESTS = \
@@ -2140,6 +2143,11 @@ mpfrmemok1:
@$(AWK) -p- -M -f "$(srcdir)"/$@.awk 2>&1 | sed 1d > _$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mpfrfield:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk "$(srcdir)"/$@.in > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
jarebug::
@echo $@
@"$(srcdir)"/$@.sh "$(AWKPROG)" "$(srcdir)"/$@.awk "$(srcdir)"/$@.in "_$@"
diff --git a/test/Makefile.in b/test/Makefile.in
index 1f2ff766..33e2b0bf 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -916,6 +916,9 @@ EXTRA_DIST = \
mpfrbigint.ok \
mpfrexprange.awk \
mpfrexprange.ok \
+ mpfrfield.awk \
+ mpfrfield.in \
+ mpfrfield.ok \
mpfrieee.awk \
mpfrieee.ok \
mpfrmemok1.awk \
@@ -1560,8 +1563,8 @@ ARRAYDEBUG_TESTS = arrdbg
EXTRA_TESTS = inftest regtest ignrcas3
INET_TESTS = inetdayu inetdayt inetechu inetecht
MACHINE_TESTS = double1 double2 fmtspcl intformat
-MPFR_TESTS = mpfrbigint mpfrexprange mpfrieee mpfrmemok1 mpfrnegzero \
- mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \
+MPFR_TESTS = mpfrbigint mpfrexprange mpfrfield mpfrieee mpfrmemok1 \
+ mpfrnegzero mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \
mpfrstrtonum mpgforcenum mpfruplus
LOCALE_CHARSET_TESTS = \
@@ -2580,6 +2583,11 @@ mpfrmemok1:
@$(AWK) -p- -M -f "$(srcdir)"/$@.awk 2>&1 | sed 1d > _$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mpfrfield:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk "$(srcdir)"/$@.in > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
jarebug::
@echo $@
@"$(srcdir)"/$@.sh "$(AWKPROG)" "$(srcdir)"/$@.awk "$(srcdir)"/$@.in "_$@"
diff --git a/test/mpfrfield.awk b/test/mpfrfield.awk
new file mode 100644
index 00000000..35a97b70
--- /dev/null
+++ b/test/mpfrfield.awk
@@ -0,0 +1,14 @@
+#! /bin/gawk -Mf
+
+NR == 1 {
+ min = $1
+}
+
+{
+ if ($1 < min)
+ min = $1
+}
+
+END {
+ print "min", min
+}
diff --git a/test/mpfrfield.in b/test/mpfrfield.in
new file mode 100644
index 00000000..05d33444
--- /dev/null
+++ b/test/mpfrfield.in
@@ -0,0 +1,10 @@
+7
+9
+1
+3
+9
+1
+9
+5
+0
+8
diff --git a/test/mpfrfield.ok b/test/mpfrfield.ok
new file mode 100644
index 00000000..3736de4d
--- /dev/null
+++ b/test/mpfrfield.ok
@@ -0,0 +1 @@
+min 0