From 0fafaee9bb38a3ea4b8be4009e9ce99334460ddd Mon Sep 17 00:00:00 2001
From: "Arnold D. Robbins" <arnold@skeeve.com>
Date: Mon, 2 Apr 2018 16:37:17 +0300
Subject: [PATCH] Copy MPZ/MPFR bits also, in r_dupnode.

---
 interpret.h        | 27 ++++++++++++++++++---------
 node.c             | 20 ++++++++++++++++++--
 test/Makefile.am   | 12 ++++++++++--
 test/Makefile.in   | 12 ++++++++++--
 test/mpfrfield.awk | 14 ++++++++++++++
 test/mpfrfield.in  | 10 ++++++++++
 test/mpfrfield.ok  |  1 +
 7 files changed, 81 insertions(+), 15 deletions(-)
 create mode 100644 test/mpfrfield.awk
 create mode 100644 test/mpfrfield.in
 create mode 100644 test/mpfrfield.ok

diff --git a/interpret.h b/interpret.h
index 96e2c89..20fcb7a 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 add959f..fcd2bf3 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/Makefile.am b/test/Makefile.am
index 40e25b2..93a6ee5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -655,6 +655,9 @@ EXTRA_DIST = \
 	mpfrbigint.ok \
 	mpfrexprange.awk \
 	mpfrexprange.ok \
+	mpfrfield.awk \
+	mpfrfield.in \
+	mpfrfield.ok \
 	mpfrieee.awk \
 	mpfrieee.ok \
 	mpfrmemok1.awk \
@@ -1302,8 +1305,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 = \
@@ -2148,6 +2151,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 74405f8..2358988 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -913,6 +913,9 @@ EXTRA_DIST = \
 	mpfrbigint.ok \
 	mpfrexprange.awk \
 	mpfrexprange.ok \
+	mpfrfield.awk \
+	mpfrfield.in \
+	mpfrfield.ok \
 	mpfrieee.awk \
 	mpfrieee.ok \
 	mpfrmemok1.awk \
@@ -1555,8 +1558,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 = \
@@ -2588,6 +2591,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 0000000..35a97b7
--- /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 0000000..05d3344
--- /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 0000000..3736de4
--- /dev/null
+++ b/test/mpfrfield.ok
@@ -0,0 +1 @@
+min 0
-- 
2.14.4

