gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, gawk_mpfr, updated. 0221eb79f43f4ef5c8d7


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, gawk_mpfr, updated. 0221eb79f43f4ef5c8d74759679a501607936d19
Date: Fri, 17 Feb 2012 04:34:51 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, gawk_mpfr has been updated
       via  0221eb79f43f4ef5c8d74759679a501607936d19 (commit)
      from  06a6f16495e2a3d0cb664fc473107d3cdbe6f11e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=0221eb79f43f4ef5c8d74759679a501607936d19

commit 0221eb79f43f4ef5c8d74759679a501607936d19
Author: john haque <address@hidden>
Date:   Thu Feb 16 15:44:26 2012 -0600

    New interpreter routine for MPFR.

diff --git a/array.c b/array.c
index e3bdbf5..7220d7e 100644
--- a/array.c
+++ b/array.c
@@ -785,8 +785,8 @@ do_adump(int nargs)
         */
 
        if (nargs == 2) {
-               tmp = POP_SCALAR();
-               depth = (long) force_number(tmp);
+               tmp = POP_NUMBER();
+               depth = get_number_si(tmp);
                DEREF(tmp);
        }
        symbol = POP_PARAM();
@@ -1218,8 +1218,8 @@ sort_down_value_type(const void *p1, const void *p2)
 static int
 sort_user_func(const void *p1, const void *p2)
 {
-       NODE *idx1, *idx2, *val1, *val2;
-       AWKNUM ret;
+       NODE *idx1, *idx2, *val1, *val2, *r;
+       int ret;
        INSTRUCTION *code;
 
        idx1 = *((NODE *const *) p1);
@@ -1246,9 +1246,16 @@ sort_user_func(const void *p1, const void *p2)
        (void) (*interpret)(code);
 
        /* return value of the comparison function */
-       POP_NUMBER(ret);
-
-       return (ret < 0.0) ? -1 : (ret > 0.0);
+       r = POP_NUMBER();
+#ifdef HAVE_MPFR
+       /* mpfr_sgn: Return a positive value if op > 0, zero if op = 0, and a 
negative value if op < 0. */
+       if (r->flags & MPFN)
+               ret = mpfr_sgn(r->mpfr_numbr);
+       else
+#endif
+               ret = (r->numbr < 0.0) ? -1 : (r->numbr > 0.0);
+       DEREF(r);
+       return ret;
 }
 
 
diff --git a/awk.h b/awk.h
index f08c10b..9f2e904 100644
--- a/awk.h
+++ b/awk.h
@@ -201,6 +201,7 @@ typedef void *stackoverflow_context_t;
 #include <gmp.h>
 #include <mpfr.h>
 #ifndef MPFR_RNDN
+/* for compatibility with MPFR 2.X */
 #define MPFR_RNDN GMP_RNDN
 #define MPFR_RNDZ GMP_RNDZ
 #define MPFR_RNDU GMP_RNDU
@@ -1020,7 +1021,8 @@ extern int sourceline;
 extern char *source;
 extern int (*interpret)(INSTRUCTION *);        /* interpreter routine */
 extern NODE *(*make_number)(AWKNUM );
-extern AWKNUM (*m_force_number)(NODE *);
+extern NODE *(*m_force_number)(NODE *);
+extern NODE *(*format_val)(const char *, int, NODE *);
 
 #if __GNUC__ < 2
 extern NODE *_t;       /* used as temporary in macros */
@@ -1105,6 +1107,9 @@ extern struct lconv loc;
 #ifdef HAVE_MPFR
 extern mpfr_prec_t     PRECISION;
 extern mpfr_rnd_t      RND_MODE;
+extern mpfr_t MNR;
+extern mpfr_t MFNR;
+extern mpz_t mpzval;
 #endif
 
 
@@ -1165,9 +1170,6 @@ extern STACK_ITEM *stack_top;
 #define POP_PARAM()    ({ NODE *_t = POP(); \
                _t->type == Node_var_array ? _t : get_array(_t, FALSE); })
 
-#define POP_NUMBER(x) ({ NODE *_t = POP_SCALAR(); x = force_number(_t); 
DEREF(_t); })
-#define TOP_NUMBER(x) ({ NODE *_t = TOP_SCALAR(); x = force_number(_t); 
DEREF(_t); })
-
 #define POP_SCALAR()   ({ NODE *_t = POP(); _t->type != Node_var_array ? _t \
                : (fatal(_("attempt to use array `%s' in a scalar context"), 
array_vname(_t)), _t);})
 #define TOP_SCALAR()   ({ NODE *_t = TOP(); _t->type != Node_var_array ? _t \
@@ -1184,9 +1186,6 @@ extern STACK_ITEM *stack_top;
 #define POP_PARAM()    (_t = POP(), \
                _t->type == Node_var_array ? _t : get_array(_t, FALSE))
 
-#define POP_NUMBER(x) (_t = POP_SCALAR(), x = force_number(_t), DEREF(_t))
-#define TOP_NUMBER(x) (_t = TOP_SCALAR(), x = force_number(_t), DEREF(_t))
-
 #define POP_SCALAR()   (_t = POP(), _t->type != Node_var_array ? _t \
                : (fatal(_("attempt to use array `%s' in a scalar context"), 
array_vname(_t)), _t))
 #define TOP_SCALAR()   (_t = TOP(), _t->type != Node_var_array ? _t \
@@ -1197,6 +1196,9 @@ extern STACK_ITEM *stack_top;
 
 #endif /* __GNUC__ */
 
+#define POP_NUMBER() force_number(POP_SCALAR())
+#define TOP_NUMBER() force_number(TOP_SCALAR())
+
 /* ------------------------- Pseudo-functions ------------------------- */
 #ifdef HAVE_MPFR
 /* conversion to C types */
@@ -1211,6 +1213,10 @@ extern STACK_ITEM *stack_top;
 
 #define is_nonzero_num(n)      (((n)->flags & MPFN) ? (! 
mpfr_zero_p((n)->mpfr_numbr)) \
                                : ((n)->numbr != 0.0))
+
+/* increment NR or FNR */
+#define INCREMNT(X)            (do_mpfr && X == (LONG_MAX - 1)) ? \
+                               (mpfr_add_ui(M##X, M##X, 1, RND_MODE), X = 0) : 
X++
 #else
 #define get_number_ui(n)       (unsigned long) (n)->numbr
 #define get_number_si(n)       (long) (n)->numbr
@@ -1218,6 +1224,8 @@ extern STACK_ITEM *stack_top;
 #define get_number_uj(n)       (uintmax_t) (n)->numbr
 
 #define is_nonzero_num(n)      ((n)->numbr != 0.0)
+
+#define INCREMNT(X)            X++
 #endif
 
 #define is_identchar(c)                (isalnum(c) || (c) == '_')
@@ -1277,8 +1285,8 @@ extern NODE *r_force_string(NODE *s);
 #define dupnode(n)     __extension__ ({ NODE *_tn = (n); \
        (_tn->flags & MALLOC) ? (_tn->valref++, _tn) : r_dupnode(_tn); })
 
-#define        force_number(n) __extension__ ({ NODE *_tn = (n);\
-       (_tn->flags & NUMCUR) ? _tn->numbr : m_force_number(_tn); })
+#define        force_number(n) __extension__ ({ NODE *_tn = (n); \
+       (_tn->flags & NUMCUR) ? _tn : m_force_number(_tn); })
 
 #define        force_string(s) __extension__ ({ NODE *_ts = (s); 
m_force_string(_ts); })
 
@@ -1419,6 +1427,9 @@ extern INSTRUCTION *POP_CODE(void);
 extern void init_interpret(void);
 extern int r_interpret(INSTRUCTION *);
 extern int debug_interpret(INSTRUCTION *);
+#ifdef HAVE_MPFR
+extern int mpfr_interpret(INSTRUCTION *);
+#endif
 extern int cmp_nodes(NODE *p1, NODE *p2);
 extern void set_IGNORECASE(void);
 extern void set_OFS(void);
@@ -1517,29 +1528,31 @@ extern void update_global_values();
 extern long getenv_long(const char *name);
 
 /* mpfr.c */
-#ifdef HAVE_MPFR
 extern void set_PREC(void);
 extern void set_RNDMODE(void);
-extern NODE *do_and_mpfr(int);
-extern NODE *do_atan2_mpfr(int);
-extern NODE *do_compl_mpfr(int);
-extern NODE *do_cos_mpfr(int);
-extern NODE *do_exp_mpfr(int);
-extern NODE *do_int_mpfr(int);
-extern NODE *do_log_mpfr(int);
-extern NODE *do_lshift_mpfr(int);
-extern NODE *do_or_mpfr(int);
-extern NODE *do_rand_mpfr(int);
-extern NODE *do_rhift_mpfr(int);
-extern NODE *do_sin_mpfr(int);
-extern NODE *do_sqrt_mpfr(int);
-extern NODE *do_srand_mpfr(int);
-extern NODE *do_strtonum_mpfr(int);
-extern NODE *do_xor_mpfr(int);
+#ifdef HAVE_MPFR
+extern void mpfr_update_var(NODE *);
+extern long mpfr_set_var(NODE *);
+extern NODE *do_mpfr_and(int);
+extern NODE *do_mpfr_atan2(int);
+extern NODE *do_mpfr_compl(int);
+extern NODE *do_mpfr_cos(int);
+extern NODE *do_mpfr_exp(int);
+extern NODE *do_mpfr_int(int);
+extern NODE *do_mpfr_log(int);
+extern NODE *do_mpfr_lshift(int);
+extern NODE *do_mpfr_or(int);
+extern NODE *do_mpfr_rand(int);
+extern NODE *do_mpfr_rhift(int);
+extern NODE *do_mpfr_sin(int);
+extern NODE *do_mpfr_sqrt(int);
+extern NODE *do_mpfr_srand(int);
+extern NODE *do_mpfr_strtonum(int);
+extern NODE *do_mpfr_xor(int);
 extern void init_mpfr(const char *);
-extern AWKNUM force_mpfr_number(NODE *n);
 extern NODE *mpfr_node();
-extern NODE *make_mpfr_number(double x);
+extern void op_assign_mpfr(OPCODE op);
+const char *mpfr_fmt(const char *mesg, ...);
 #endif
 /* msg.c */
 extern void gawk_exit(int status);
@@ -1566,8 +1579,8 @@ extern int pp_func(INSTRUCTION *pc, void *);
 extern void pp_string_fp(Func_print print_func, FILE *fp, const char *str,
                size_t namelen, int delim, int breaklines);
 /* node.c */
-extern AWKNUM r_force_number(NODE *n);
-extern NODE *format_val(const char *format, int index, NODE *s);
+extern NODE *r_force_number(NODE *n);
+extern NODE *r_format_val(const char *format, int index, NODE *s);
 extern NODE *r_dupnode(NODE *n);
 extern NODE *r_make_number(AWKNUM x);
 extern NODE *r_make_str_node(const char *s, size_t len, int flags);
diff --git a/awkgram.c b/awkgram.c
index f7c74f3..edf9932 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -712,20 +712,20 @@ static const yytype_uint16 yyrline[] =
      322,   331,   341,   343,   345,   351,   356,   357,   361,   380,
      379,   413,   415,   420,   421,   434,   439,   440,   444,   446,
      448,   455,   545,   587,   629,   742,   749,   756,   766,   775,
-     784,   793,   808,   824,   823,   847,   859,   859,   953,   953,
-     978,  1001,  1007,  1008,  1014,  1015,  1022,  1027,  1039,  1053,
-    1055,  1066,  1071,  1073,  1081,  1083,  1092,  1093,  1101,  1106,
-    1106,  1117,  1121,  1129,  1130,  1133,  1135,  1140,  1141,  1150,
-    1151,  1156,  1161,  1167,  1169,  1171,  1178,  1179,  1185,  1186,
-    1191,  1193,  1198,  1200,  1202,  1204,  1210,  1217,  1219,  1221,
-    1237,  1247,  1254,  1256,  1261,  1263,  1265,  1273,  1275,  1280,
-    1282,  1287,  1289,  1291,  1341,  1343,  1345,  1347,  1349,  1351,
-    1353,  1355,  1378,  1383,  1388,  1413,  1419,  1421,  1423,  1425,
-    1427,  1429,  1434,  1438,  1469,  1471,  1477,  1483,  1496,  1497,
-    1498,  1503,  1508,  1512,  1516,  1534,  1547,  1552,  1588,  1606,
-    1607,  1613,  1614,  1619,  1621,  1628,  1645,  1662,  1664,  1671,
-    1676,  1684,  1694,  1706,  1715,  1719,  1723,  1727,  1731,  1735,
-    1738,  1740,  1744,  1748,  1752
+     784,   793,   808,   824,   823,   847,   859,   859,   954,   954,
+     979,  1002,  1008,  1009,  1015,  1016,  1023,  1028,  1040,  1054,
+    1056,  1067,  1072,  1074,  1082,  1084,  1093,  1094,  1102,  1107,
+    1107,  1118,  1122,  1130,  1131,  1134,  1136,  1141,  1142,  1151,
+    1152,  1157,  1162,  1168,  1170,  1172,  1179,  1180,  1186,  1187,
+    1192,  1194,  1199,  1201,  1203,  1205,  1211,  1218,  1220,  1222,
+    1238,  1248,  1255,  1257,  1262,  1264,  1266,  1274,  1276,  1281,
+    1283,  1288,  1290,  1292,  1342,  1344,  1346,  1348,  1350,  1352,
+    1354,  1356,  1379,  1384,  1389,  1414,  1420,  1422,  1424,  1426,
+    1428,  1430,  1435,  1439,  1471,  1473,  1479,  1485,  1498,  1499,
+    1500,  1505,  1510,  1514,  1518,  1536,  1549,  1554,  1590,  1608,
+    1609,  1615,  1616,  1621,  1623,  1630,  1647,  1664,  1666,  1673,
+    1678,  1686,  1696,  1708,  1717,  1721,  1725,  1729,  1733,  1737,
+    1740,  1742,  1746,  1750,  1754
 };
 #endif
 
@@ -2897,6 +2897,7 @@ regular_loop:
                                        && (yyvsp[(3) - 
(4)])->nexti->nexti->nexti == (yyvsp[(3) - (4)])->lasti
                                        && (yyvsp[(3) - 
(4)])->nexti->nexti->opcode == Op_push_i
                                        && (yyvsp[(3) - 
(4)])->nexti->nexti->memory->type == Node_val
+                                       && ((yyvsp[(3) - 
(4)])->nexti->nexti->memory->flags & MPFN) == 0
                                        && (yyvsp[(3) - 
(4)])->nexti->nexti->memory->numbr == 0.0)
                        )
                ) {
@@ -2981,14 +2982,14 @@ regular_loop:
   case 58:
 
 /* Line 1821 of yacc.c  */
-#line 953 "awkgram.y"
+#line 954 "awkgram.y"
     { sub_counter = 0; }
     break;
 
   case 59:
 
 /* Line 1821 of yacc.c  */
-#line 954 "awkgram.y"
+#line 955 "awkgram.y"
     {
                char *arr = (yyvsp[(2) - (4)])->lextok;
 
@@ -3018,7 +3019,7 @@ regular_loop:
   case 60:
 
 /* Line 1821 of yacc.c  */
-#line 983 "awkgram.y"
+#line 984 "awkgram.y"
     {
                static short warned = FALSE;
                char *arr = (yyvsp[(3) - (4)])->lextok;
@@ -3042,35 +3043,35 @@ regular_loop:
   case 61:
 
 /* Line 1821 of yacc.c  */
-#line 1002 "awkgram.y"
+#line 1003 "awkgram.y"
     {  (yyval) = optimize_assignment((yyvsp[(1) - (1)])); }
     break;
 
   case 62:
 
 /* Line 1821 of yacc.c  */
-#line 1007 "awkgram.y"
+#line 1008 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 63:
 
 /* Line 1821 of yacc.c  */
-#line 1009 "awkgram.y"
+#line 1010 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 64:
 
 /* Line 1821 of yacc.c  */
-#line 1014 "awkgram.y"
+#line 1015 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 65:
 
 /* Line 1821 of yacc.c  */
-#line 1016 "awkgram.y"
+#line 1017 "awkgram.y"
     {
                if ((yyvsp[(1) - (2)]) == NULL)
                        (yyval) = list_create((yyvsp[(2) - (2)]));
@@ -3082,14 +3083,14 @@ regular_loop:
   case 66:
 
 /* Line 1821 of yacc.c  */
-#line 1023 "awkgram.y"
+#line 1024 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 67:
 
 /* Line 1821 of yacc.c  */
-#line 1028 "awkgram.y"
+#line 1029 "awkgram.y"
     {
                INSTRUCTION *casestmt = (yyvsp[(5) - (5)]);
                if ((yyvsp[(5) - (5)]) == NULL)
@@ -3106,7 +3107,7 @@ regular_loop:
   case 68:
 
 /* Line 1821 of yacc.c  */
-#line 1040 "awkgram.y"
+#line 1041 "awkgram.y"
     {
                INSTRUCTION *casestmt = (yyvsp[(4) - (4)]);
                if ((yyvsp[(4) - (4)]) == NULL)
@@ -3122,14 +3123,14 @@ regular_loop:
   case 69:
 
 /* Line 1821 of yacc.c  */
-#line 1054 "awkgram.y"
+#line 1055 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 70:
 
 /* Line 1821 of yacc.c  */
-#line 1056 "awkgram.y"
+#line 1057 "awkgram.y"
     { 
                NODE *n = (yyvsp[(2) - (2)])->memory;
                (void) force_number(n);
@@ -3145,7 +3146,7 @@ regular_loop:
   case 71:
 
 /* Line 1821 of yacc.c  */
-#line 1067 "awkgram.y"
+#line 1068 "awkgram.y"
     {
                bcfree((yyvsp[(1) - (2)]));
                (yyval) = (yyvsp[(2) - (2)]);
@@ -3155,14 +3156,14 @@ regular_loop:
   case 72:
 
 /* Line 1821 of yacc.c  */
-#line 1072 "awkgram.y"
+#line 1073 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 73:
 
 /* Line 1821 of yacc.c  */
-#line 1074 "awkgram.y"
+#line 1075 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->opcode = Op_push_re;
                (yyval) = (yyvsp[(1) - (1)]);
@@ -3172,21 +3173,21 @@ regular_loop:
   case 74:
 
 /* Line 1821 of yacc.c  */
-#line 1082 "awkgram.y"
+#line 1083 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 75:
 
 /* Line 1821 of yacc.c  */
-#line 1084 "awkgram.y"
+#line 1085 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 77:
 
 /* Line 1821 of yacc.c  */
-#line 1094 "awkgram.y"
+#line 1095 "awkgram.y"
     {
                (yyval) = (yyvsp[(2) - (3)]);
          }
@@ -3195,7 +3196,7 @@ regular_loop:
   case 78:
 
 /* Line 1821 of yacc.c  */
-#line 1101 "awkgram.y"
+#line 1102 "awkgram.y"
     {
                in_print = FALSE;
                in_parens = 0;
@@ -3206,14 +3207,14 @@ regular_loop:
   case 79:
 
 /* Line 1821 of yacc.c  */
-#line 1106 "awkgram.y"
+#line 1107 "awkgram.y"
     { in_print = FALSE; in_parens = 0; }
     break;
 
   case 80:
 
 /* Line 1821 of yacc.c  */
-#line 1107 "awkgram.y"
+#line 1108 "awkgram.y"
     {
                if ((yyvsp[(1) - (3)])->redir_type == redirect_twoway
                        && (yyvsp[(3) - (3)])->lasti->opcode == 
Op_K_getline_redir
@@ -3226,7 +3227,7 @@ regular_loop:
   case 81:
 
 /* Line 1821 of yacc.c  */
-#line 1118 "awkgram.y"
+#line 1119 "awkgram.y"
     {
                (yyval) = mk_condition((yyvsp[(3) - (6)]), (yyvsp[(1) - (6)]), 
(yyvsp[(6) - (6)]), NULL, NULL);
          }
@@ -3235,7 +3236,7 @@ regular_loop:
   case 82:
 
 /* Line 1821 of yacc.c  */
-#line 1123 "awkgram.y"
+#line 1124 "awkgram.y"
     {
                (yyval) = mk_condition((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]), 
(yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(9) - (9)]));
          }
@@ -3244,14 +3245,14 @@ regular_loop:
   case 87:
 
 /* Line 1821 of yacc.c  */
-#line 1140 "awkgram.y"
+#line 1141 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 88:
 
 /* Line 1821 of yacc.c  */
-#line 1142 "awkgram.y"
+#line 1143 "awkgram.y"
     {
                bcfree((yyvsp[(1) - (2)]));
                (yyval) = (yyvsp[(2) - (2)]);
@@ -3261,21 +3262,21 @@ regular_loop:
   case 89:
 
 /* Line 1821 of yacc.c  */
-#line 1150 "awkgram.y"
+#line 1151 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 90:
 
 /* Line 1821 of yacc.c  */
-#line 1152 "awkgram.y"
+#line 1153 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]) ; }
     break;
 
   case 91:
 
 /* Line 1821 of yacc.c  */
-#line 1157 "awkgram.y"
+#line 1158 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->param_count = 0;
                (yyval) = list_create((yyvsp[(1) - (1)]));
@@ -3285,7 +3286,7 @@ regular_loop:
   case 92:
 
 /* Line 1821 of yacc.c  */
-#line 1162 "awkgram.y"
+#line 1163 "awkgram.y"
     {
                (yyvsp[(3) - (3)])->param_count =  (yyvsp[(1) - 
(3)])->lasti->param_count + 1;
                (yyval) = list_append((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]));
@@ -3296,63 +3297,63 @@ regular_loop:
   case 93:
 
 /* Line 1821 of yacc.c  */
-#line 1168 "awkgram.y"
+#line 1169 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 94:
 
 /* Line 1821 of yacc.c  */
-#line 1170 "awkgram.y"
+#line 1171 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (2)]); }
     break;
 
   case 95:
 
 /* Line 1821 of yacc.c  */
-#line 1172 "awkgram.y"
+#line 1173 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (3)]); }
     break;
 
   case 96:
 
 /* Line 1821 of yacc.c  */
-#line 1178 "awkgram.y"
+#line 1179 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 97:
 
 /* Line 1821 of yacc.c  */
-#line 1180 "awkgram.y"
+#line 1181 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 98:
 
 /* Line 1821 of yacc.c  */
-#line 1185 "awkgram.y"
+#line 1186 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 99:
 
 /* Line 1821 of yacc.c  */
-#line 1187 "awkgram.y"
+#line 1188 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 100:
 
 /* Line 1821 of yacc.c  */
-#line 1192 "awkgram.y"
+#line 1193 "awkgram.y"
     {  (yyval) = mk_expression_list(NULL, (yyvsp[(1) - (1)])); }
     break;
 
   case 101:
 
 /* Line 1821 of yacc.c  */
-#line 1194 "awkgram.y"
+#line 1195 "awkgram.y"
     {
                (yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - 
(3)]));
                yyerrok;
@@ -3362,35 +3363,35 @@ regular_loop:
   case 102:
 
 /* Line 1821 of yacc.c  */
-#line 1199 "awkgram.y"
+#line 1200 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 103:
 
 /* Line 1821 of yacc.c  */
-#line 1201 "awkgram.y"
+#line 1202 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 104:
 
 /* Line 1821 of yacc.c  */
-#line 1203 "awkgram.y"
+#line 1204 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 105:
 
 /* Line 1821 of yacc.c  */
-#line 1205 "awkgram.y"
+#line 1206 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 106:
 
 /* Line 1821 of yacc.c  */
-#line 1211 "awkgram.y"
+#line 1212 "awkgram.y"
     {
                if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == 
Op_match_rec)
                        lintwarn_ln((yyvsp[(2) - (3)])->source_line,
@@ -3402,21 +3403,21 @@ regular_loop:
   case 107:
 
 /* Line 1821 of yacc.c  */
-#line 1218 "awkgram.y"
+#line 1219 "awkgram.y"
     {  (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) 
- (3)])); }
     break;
 
   case 108:
 
 /* Line 1821 of yacc.c  */
-#line 1220 "awkgram.y"
+#line 1221 "awkgram.y"
     {  (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) 
- (3)])); }
     break;
 
   case 109:
 
 /* Line 1821 of yacc.c  */
-#line 1222 "awkgram.y"
+#line 1223 "awkgram.y"
     {
                if ((yyvsp[(1) - (3)])->lasti->opcode == Op_match_rec)
                        warning_ln((yyvsp[(2) - (3)])->source_line,
@@ -3437,7 +3438,7 @@ regular_loop:
   case 110:
 
 /* Line 1821 of yacc.c  */
-#line 1238 "awkgram.y"
+#line 1239 "awkgram.y"
     {
                if (do_lint_old)
                        warning_ln((yyvsp[(2) - (3)])->source_line,
@@ -3452,7 +3453,7 @@ regular_loop:
   case 111:
 
 /* Line 1821 of yacc.c  */
-#line 1248 "awkgram.y"
+#line 1249 "awkgram.y"
     {
                if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == 
Op_match_rec)
                        lintwarn_ln((yyvsp[(2) - (3)])->source_line,
@@ -3464,35 +3465,35 @@ regular_loop:
   case 112:
 
 /* Line 1821 of yacc.c  */
-#line 1255 "awkgram.y"
+#line 1256 "awkgram.y"
     { (yyval) = mk_condition((yyvsp[(1) - (5)]), (yyvsp[(2) - (5)]), 
(yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])); }
     break;
 
   case 113:
 
 /* Line 1821 of yacc.c  */
-#line 1257 "awkgram.y"
+#line 1258 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 114:
 
 /* Line 1821 of yacc.c  */
-#line 1262 "awkgram.y"
+#line 1263 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 115:
 
 /* Line 1821 of yacc.c  */
-#line 1264 "awkgram.y"
+#line 1265 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 116:
 
 /* Line 1821 of yacc.c  */
-#line 1266 "awkgram.y"
+#line 1267 "awkgram.y"
     {  
                (yyvsp[(2) - (2)])->opcode = Op_assign_quotient;
                (yyval) = (yyvsp[(2) - (2)]);
@@ -3502,49 +3503,49 @@ regular_loop:
   case 117:
 
 /* Line 1821 of yacc.c  */
-#line 1274 "awkgram.y"
+#line 1275 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 118:
 
 /* Line 1821 of yacc.c  */
-#line 1276 "awkgram.y"
+#line 1277 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 119:
 
 /* Line 1821 of yacc.c  */
-#line 1281 "awkgram.y"
+#line 1282 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 120:
 
 /* Line 1821 of yacc.c  */
-#line 1283 "awkgram.y"
+#line 1284 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 121:
 
 /* Line 1821 of yacc.c  */
-#line 1288 "awkgram.y"
+#line 1289 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 122:
 
 /* Line 1821 of yacc.c  */
-#line 1290 "awkgram.y"
+#line 1291 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 123:
 
 /* Line 1821 of yacc.c  */
-#line 1292 "awkgram.y"
+#line 1293 "awkgram.y"
     {
                int count = 2;
                int is_simple_var = FALSE;
@@ -3596,49 +3597,49 @@ regular_loop:
   case 125:
 
 /* Line 1821 of yacc.c  */
-#line 1344 "awkgram.y"
+#line 1345 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 126:
 
 /* Line 1821 of yacc.c  */
-#line 1346 "awkgram.y"
+#line 1347 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 127:
 
 /* Line 1821 of yacc.c  */
-#line 1348 "awkgram.y"
+#line 1349 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 128:
 
 /* Line 1821 of yacc.c  */
-#line 1350 "awkgram.y"
+#line 1351 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 129:
 
 /* Line 1821 of yacc.c  */
-#line 1352 "awkgram.y"
+#line 1353 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 130:
 
 /* Line 1821 of yacc.c  */
-#line 1354 "awkgram.y"
+#line 1355 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 131:
 
 /* Line 1821 of yacc.c  */
-#line 1356 "awkgram.y"
+#line 1357 "awkgram.y"
     {
                /*
                 * In BEGINFILE/ENDFILE, allow `getline var < file'
@@ -3666,7 +3667,7 @@ regular_loop:
   case 132:
 
 /* Line 1821 of yacc.c  */
-#line 1379 "awkgram.y"
+#line 1380 "awkgram.y"
     {
                (yyvsp[(2) - (2)])->opcode = Op_postincrement;
                (yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - 
(2)]));
@@ -3676,7 +3677,7 @@ regular_loop:
   case 133:
 
 /* Line 1821 of yacc.c  */
-#line 1384 "awkgram.y"
+#line 1385 "awkgram.y"
     {
                (yyvsp[(2) - (2)])->opcode = Op_postdecrement;
                (yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - 
(2)]));
@@ -3686,7 +3687,7 @@ regular_loop:
   case 134:
 
 /* Line 1821 of yacc.c  */
-#line 1389 "awkgram.y"
+#line 1390 "awkgram.y"
     {
                if (do_lint_old) {
                    warning_ln((yyvsp[(4) - (5)])->source_line,
@@ -3711,7 +3712,7 @@ regular_loop:
   case 135:
 
 /* Line 1821 of yacc.c  */
-#line 1414 "awkgram.y"
+#line 1415 "awkgram.y"
     {
                  (yyval) = mk_getline((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), 
(yyvsp[(1) - (4)]), (yyvsp[(2) - (4)])->redir_type);
                  bcfree((yyvsp[(2) - (4)]));
@@ -3721,49 +3722,49 @@ regular_loop:
   case 136:
 
 /* Line 1821 of yacc.c  */
-#line 1420 "awkgram.y"
+#line 1421 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 137:
 
 /* Line 1821 of yacc.c  */
-#line 1422 "awkgram.y"
+#line 1423 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 138:
 
 /* Line 1821 of yacc.c  */
-#line 1424 "awkgram.y"
+#line 1425 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 139:
 
 /* Line 1821 of yacc.c  */
-#line 1426 "awkgram.y"
+#line 1427 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 140:
 
 /* Line 1821 of yacc.c  */
-#line 1428 "awkgram.y"
+#line 1429 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 141:
 
 /* Line 1821 of yacc.c  */
-#line 1430 "awkgram.y"
+#line 1431 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 142:
 
 /* Line 1821 of yacc.c  */
-#line 1435 "awkgram.y"
+#line 1436 "awkgram.y"
     {
                (yyval) = list_create((yyvsp[(1) - (1)]));
          }
@@ -3772,7 +3773,7 @@ regular_loop:
   case 143:
 
 /* Line 1821 of yacc.c  */
-#line 1439 "awkgram.y"
+#line 1440 "awkgram.y"
     {
                if ((yyvsp[(2) - (2)])->opcode == Op_match_rec) {
                        (yyvsp[(2) - (2)])->opcode = Op_nomatch;
@@ -3783,6 +3784,7 @@ regular_loop:
                } else {
                        if (do_optimize > 1 && (yyvsp[(2) - (2)])->nexti == 
(yyvsp[(2) - (2)])->lasti
                                        && (yyvsp[(2) - (2)])->nexti->opcode == 
Op_push_i
+                                       && ((yyvsp[(2) - 
(2)])->nexti->memory->flags & MPFN) == 0
                        ) {
                                NODE *n = (yyvsp[(2) - (2)])->nexti->memory;
                                if ((n->flags & (STRCUR|STRING)) != 0) {
@@ -3808,14 +3810,14 @@ regular_loop:
   case 144:
 
 /* Line 1821 of yacc.c  */
-#line 1470 "awkgram.y"
+#line 1472 "awkgram.y"
     { (yyval) = (yyvsp[(2) - (3)]); }
     break;
 
   case 145:
 
 /* Line 1821 of yacc.c  */
-#line 1472 "awkgram.y"
+#line 1474 "awkgram.y"
     {
                (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
                if ((yyval) == NULL)
@@ -3826,7 +3828,7 @@ regular_loop:
   case 146:
 
 /* Line 1821 of yacc.c  */
-#line 1478 "awkgram.y"
+#line 1480 "awkgram.y"
     {
                (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
                if ((yyval) == NULL)
@@ -3837,7 +3839,7 @@ regular_loop:
   case 147:
 
 /* Line 1821 of yacc.c  */
-#line 1484 "awkgram.y"
+#line 1486 "awkgram.y"
     {
                static short warned1 = FALSE;
 
@@ -3855,7 +3857,7 @@ regular_loop:
   case 150:
 
 /* Line 1821 of yacc.c  */
-#line 1499 "awkgram.y"
+#line 1501 "awkgram.y"
     {
                (yyvsp[(1) - (2)])->opcode = Op_preincrement;
                (yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - 
(2)]));
@@ -3865,7 +3867,7 @@ regular_loop:
   case 151:
 
 /* Line 1821 of yacc.c  */
-#line 1504 "awkgram.y"
+#line 1506 "awkgram.y"
     {
                (yyvsp[(1) - (2)])->opcode = Op_predecrement;
                (yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - 
(2)]));
@@ -3875,7 +3877,7 @@ regular_loop:
   case 152:
 
 /* Line 1821 of yacc.c  */
-#line 1509 "awkgram.y"
+#line 1511 "awkgram.y"
     {
                (yyval) = list_create((yyvsp[(1) - (1)]));
          }
@@ -3884,7 +3886,7 @@ regular_loop:
   case 153:
 
 /* Line 1821 of yacc.c  */
-#line 1513 "awkgram.y"
+#line 1515 "awkgram.y"
     {
                (yyval) = list_create((yyvsp[(1) - (1)]));
          }
@@ -3893,7 +3895,7 @@ regular_loop:
   case 154:
 
 /* Line 1821 of yacc.c  */
-#line 1517 "awkgram.y"
+#line 1519 "awkgram.y"
     {
                if ((yyvsp[(2) - (2)])->lasti->opcode == Op_push_i
                        && ((yyvsp[(2) - (2)])->lasti->memory->flags & 
(STRCUR|STRING)) == 0
@@ -3916,7 +3918,7 @@ regular_loop:
   case 155:
 
 /* Line 1821 of yacc.c  */
-#line 1535 "awkgram.y"
+#line 1537 "awkgram.y"
     {
            /*
             * was: $$ = $2
@@ -3931,7 +3933,7 @@ regular_loop:
   case 156:
 
 /* Line 1821 of yacc.c  */
-#line 1548 "awkgram.y"
+#line 1550 "awkgram.y"
     {
                func_use((yyvsp[(1) - (1)])->lasti->func_name, FUNC_USE);
                (yyval) = (yyvsp[(1) - (1)]);
@@ -3941,7 +3943,7 @@ regular_loop:
   case 157:
 
 /* Line 1821 of yacc.c  */
-#line 1553 "awkgram.y"
+#line 1555 "awkgram.y"
     {
                /* indirect function call */
                INSTRUCTION *f, *t;
@@ -3979,7 +3981,7 @@ regular_loop:
   case 158:
 
 /* Line 1821 of yacc.c  */
-#line 1589 "awkgram.y"
+#line 1591 "awkgram.y"
     {
                param_sanity((yyvsp[(3) - (4)]));
                (yyvsp[(1) - (4)])->opcode = Op_func_call;
@@ -3998,42 +4000,42 @@ regular_loop:
   case 159:
 
 /* Line 1821 of yacc.c  */
-#line 1606 "awkgram.y"
+#line 1608 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 160:
 
 /* Line 1821 of yacc.c  */
-#line 1608 "awkgram.y"
+#line 1610 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 161:
 
 /* Line 1821 of yacc.c  */
-#line 1613 "awkgram.y"
+#line 1615 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 162:
 
 /* Line 1821 of yacc.c  */
-#line 1615 "awkgram.y"
+#line 1617 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (2)]); }
     break;
 
   case 163:
 
 /* Line 1821 of yacc.c  */
-#line 1620 "awkgram.y"
+#line 1622 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 164:
 
 /* Line 1821 of yacc.c  */
-#line 1622 "awkgram.y"
+#line 1624 "awkgram.y"
     {
                (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
          }
@@ -4042,7 +4044,7 @@ regular_loop:
   case 165:
 
 /* Line 1821 of yacc.c  */
-#line 1629 "awkgram.y"
+#line 1631 "awkgram.y"
     {
                INSTRUCTION *ip = (yyvsp[(1) - (1)])->lasti; 
                int count = ip->sub_count;      /* # of SUBSEP-seperated 
expressions */
@@ -4061,7 +4063,7 @@ regular_loop:
   case 166:
 
 /* Line 1821 of yacc.c  */
-#line 1646 "awkgram.y"
+#line 1648 "awkgram.y"
     {
                INSTRUCTION *t = (yyvsp[(2) - (3)]);
                if ((yyvsp[(2) - (3)]) == NULL) {
@@ -4080,14 +4082,14 @@ regular_loop:
   case 167:
 
 /* Line 1821 of yacc.c  */
-#line 1663 "awkgram.y"
+#line 1665 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 168:
 
 /* Line 1821 of yacc.c  */
-#line 1665 "awkgram.y"
+#line 1667 "awkgram.y"
     {
                (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
          }
@@ -4096,14 +4098,14 @@ regular_loop:
   case 169:
 
 /* Line 1821 of yacc.c  */
-#line 1672 "awkgram.y"
+#line 1674 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (2)]); }
     break;
 
   case 170:
 
 /* Line 1821 of yacc.c  */
-#line 1677 "awkgram.y"
+#line 1679 "awkgram.y"
     {
                char *var_name = (yyvsp[(1) - (1)])->lextok;
 
@@ -4116,7 +4118,7 @@ regular_loop:
   case 171:
 
 /* Line 1821 of yacc.c  */
-#line 1685 "awkgram.y"
+#line 1687 "awkgram.y"
     {
                char *arr = (yyvsp[(1) - (2)])->lextok;
                (yyvsp[(1) - (2)])->memory = variable((yyvsp[(1) - 
(2)])->source_line, arr, Node_var_new);
@@ -4128,7 +4130,7 @@ regular_loop:
   case 172:
 
 /* Line 1821 of yacc.c  */
-#line 1695 "awkgram.y"
+#line 1697 "awkgram.y"
     {
                INSTRUCTION *ip = (yyvsp[(1) - (1)])->nexti;
                if (ip->opcode == Op_push
@@ -4145,7 +4147,7 @@ regular_loop:
   case 173:
 
 /* Line 1821 of yacc.c  */
-#line 1707 "awkgram.y"
+#line 1709 "awkgram.y"
     {
                (yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)]));
                if ((yyvsp[(3) - (3)]) != NULL)
@@ -4156,7 +4158,7 @@ regular_loop:
   case 174:
 
 /* Line 1821 of yacc.c  */
-#line 1716 "awkgram.y"
+#line 1718 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->opcode = Op_postincrement;
          }
@@ -4165,7 +4167,7 @@ regular_loop:
   case 175:
 
 /* Line 1821 of yacc.c  */
-#line 1720 "awkgram.y"
+#line 1722 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->opcode = Op_postdecrement;
          }
@@ -4174,49 +4176,49 @@ regular_loop:
   case 176:
 
 /* Line 1821 of yacc.c  */
-#line 1723 "awkgram.y"
+#line 1725 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 178:
 
 /* Line 1821 of yacc.c  */
-#line 1731 "awkgram.y"
+#line 1733 "awkgram.y"
     { yyerrok; }
     break;
 
   case 179:
 
 /* Line 1821 of yacc.c  */
-#line 1735 "awkgram.y"
+#line 1737 "awkgram.y"
     { yyerrok; }
     break;
 
   case 182:
 
 /* Line 1821 of yacc.c  */
-#line 1744 "awkgram.y"
+#line 1746 "awkgram.y"
     { yyerrok; }
     break;
 
   case 183:
 
 /* Line 1821 of yacc.c  */
-#line 1748 "awkgram.y"
+#line 1750 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); yyerrok; }
     break;
 
   case 184:
 
 /* Line 1821 of yacc.c  */
-#line 1752 "awkgram.y"
+#line 1754 "awkgram.y"
     { yyerrok; }
     break;
 
 
 
 /* Line 1821 of yacc.c  */
-#line 4232 "awkgram.c"
+#line 4234 "awkgram.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -4447,7 +4449,7 @@ yyreturn:
 
 
 /* Line 2067 of yacc.c  */
-#line 1754 "awkgram.y"
+#line 1756 "awkgram.y"
 
 
 struct token {
@@ -4491,7 +4493,7 @@ tokcompare(const void *l, const void *r)
  */
 
 #ifdef HAVE_MPFR
-#define MPF(F) F##_mpfr
+#define MPF(F) do_mpfr_##F
 #else
 #define MPF(F) 0
 #endif
@@ -4504,20 +4506,20 @@ static const struct token tokentab[] = {
 #ifdef ARRAYDEBUG
 {"adump",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1)|A(2),        
do_adump,       0},
 #endif
-{"and",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_and, 
MPF(do_and)},
+{"and",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_and, 
MPF(and)},
 #ifdef ARRAYDEBUG
 {"aoption",    Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_aoption,     
0},
 #endif
 {"asort",      Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3),   
do_asort,       0},
 {"asorti",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3),   
do_asorti,      0},
-{"atan2",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2),   do_atan2,       
MPF(do_atan2)},
+{"atan2",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2),   do_atan2,       
MPF(atan2)},
 {"bindtextdomain",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2),        
do_bindtextdomain,      0},
 {"break",      Op_K_break,      LEX_BREAK,     0,              0,      0},
 {"case",       Op_K_case,       LEX_CASE,      GAWKX,          0,      0},
 {"close",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1)|A(2),      
do_close,       0},
-{"compl",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_compl,       
MPF(do_compl)},
+{"compl",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_compl,       
MPF(compl)},
 {"continue",   Op_K_continue, LEX_CONTINUE,    0,              0,      0},
-{"cos",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_cos, 
MPF(do_cos)},
+{"cos",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_cos, 
MPF(cos)},
 {"dcgettext",  Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3),   
do_dcgettext,   0},
 {"dcngettext", Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3)|A(4)|A(5), 
do_dcngettext,  0},
 {"default",    Op_K_default,    LEX_DEFAULT,   GAWKX,          0,      0},
@@ -4526,7 +4528,7 @@ static const struct token tokentab[] = {
 {"else",       Op_K_else,       LEX_ELSE,      0,              0,      0},
 {"eval",       Op_symbol,       LEX_EVAL,      0,              0,      0},
 {"exit",       Op_K_exit,       LEX_EXIT,      0,              0,      0},
-{"exp",                Op_builtin,      LEX_BUILTIN,   A(1),           do_exp, 
MPF(do_exp)},
+{"exp",                Op_builtin,      LEX_BUILTIN,   A(1),           do_exp, 
MPF(exp)},
 {"extension",  Op_builtin,      LEX_BUILTIN,   GAWKX|A(2),     do_ext, 0},
 {"fflush",     Op_builtin,      LEX_BUILTIN,   RESX|A(0)|A(1), do_fflush,      
0},
 {"for",                Op_K_for,        LEX_FOR,       BREAK|CONTINUE, 0,      
0},
@@ -4539,29 +4541,29 @@ static const struct token tokentab[] = {
 {"in",         Op_symbol,       LEX_IN,        0,              0,      0},
 {"include",  Op_symbol,         LEX_INCLUDE,   GAWKX,  0,      0},
 {"index",      Op_builtin,      LEX_BUILTIN,   A(2),           do_index,       
0},
-{"int",                Op_builtin,      LEX_BUILTIN,   A(1),           do_int, 
MPF(do_int)},
+{"int",                Op_builtin,      LEX_BUILTIN,   A(1),           do_int, 
MPF(int)},
 {"isarray",    Op_builtin,      LEX_BUILTIN,   GAWKX|A(1),     do_isarray,     
0},
 {"length",     Op_builtin,      LEX_LENGTH,    A(0)|A(1),      do_length,      
0},
-{"log",                Op_builtin,      LEX_BUILTIN,   A(1),           do_log, 
MPF(do_log)},
-{"lshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_lshift,      
MPF(do_lshift)},
+{"log",                Op_builtin,      LEX_BUILTIN,   A(1),           do_log, 
MPF(log)},
+{"lshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_lshift,      
MPF(lshift)},
 {"match",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_match,    
0},
 {"mktime",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1),     do_mktime,      
0},
 {"next",       Op_K_next,       LEX_NEXT,      0,              0,      0},
 {"nextfile",   Op_K_nextfile, LEX_NEXTFILE,    GAWKX,          0,      0},
-{"or",         Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_or,  
MPF(do_or)},
+{"or",         Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_or,  
MPF(or)},
 {"patsplit",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(2)|A(3)|A(4), 
do_patsplit,      0},
 {"print",      Op_K_print,      LEX_PRINT,     0,              0,      0},
 {"printf",     Op_K_printf,     LEX_PRINTF,    0,              0,      0},
-{"rand",       Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0),   do_rand,        
MPF(do_rand)},
+{"rand",       Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0),   do_rand,        
MPF(rand)},
 {"return",     Op_K_return,     LEX_RETURN,    NOT_OLD,        0,      0},
-{"rshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_rshift,      
MPF(do_rhift)},
-{"sin",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_sin, 
MPF(do_sin)},
+{"rshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_rshift,      
MPF(rhift)},
+{"sin",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_sin, 
MPF(sin)},
 {"split",      Op_builtin,      LEX_BUILTIN,   A(2)|A(3)|A(4), do_split,       
0},
 {"sprintf",    Op_builtin,      LEX_BUILTIN,   0,              do_sprintf,     
0},
-{"sqrt",       Op_builtin,      LEX_BUILTIN,   A(1),           do_sqrt,        
MPF(do_sqrt)},
-{"srand",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0)|A(1), do_srand,    
MPF(do_srand)},
+{"sqrt",       Op_builtin,      LEX_BUILTIN,   A(1),           do_sqrt,        
MPF(sqrt)},
+{"srand",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0)|A(1), do_srand,    
MPF(srand)},
 {"strftime",   Op_builtin,      LEX_BUILTIN,   GAWKX|A(0)|A(1)|A(2)|A(3), 
do_strftime, 0},
-{"strtonum",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_strtonum, 
MPF(do_strtonum)},
+{"strtonum",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_strtonum, 
MPF(strtonum)},
 {"sub",                Op_sub_builtin,  LEX_BUILTIN,   NOT_OLD|A(2)|A(3), 0,   
0},
 {"substr",     Op_builtin,      LEX_BUILTIN,   A(2)|A(3),      do_substr,      
0},
 {"switch",     Op_K_switch,     LEX_SWITCH,    GAWKX|BREAK,    0,      0},
@@ -4570,7 +4572,7 @@ static const struct token tokentab[] = {
 {"tolower",    Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_tolower,     
0},
 {"toupper",    Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_toupper,     
0},
 {"while",      Op_K_while,      LEX_WHILE,     BREAK|CONTINUE, 0,      0},
-{"xor",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_xor, 
MPF(do_xor)},
+{"xor",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_xor, 
MPF(xor)},
 };
 
 #if MBS_SUPPORT
@@ -6576,6 +6578,8 @@ parms_shadow(INSTRUCTION *pc, int *shadow)
 void
 valinfo(NODE *n, Func_print print_func, FILE *fp)
 {
+       /* FIXME -- MPFR */
+
        if (n == Nnull_string)
                print_func(fp, "uninitialized scalar\n");
        else if (n->flags & STRING) {
@@ -7135,11 +7139,11 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION 
*op)
                ip1 = s1->nexti;
                if (do_optimize > 1
                                && ip1 == s1->lasti && ip1->opcode == Op_push_i
-                               && (ip1->memory->flags & (STRCUR|STRING)) == 0
-                               && (ip2->memory->flags & (STRCUR|STRING)) == 0
+                               && (ip1->memory->flags & (MPFN|STRCUR|STRING)) 
== 0
+                               && (ip2->memory->flags & (MPFN|STRCUR|STRING)) 
== 0
                ) {
                        NODE *n1 = ip1->memory, *n2 = ip2->memory;
-                       res = force_number(n1);
+                       res = force_number(n1)->numbr;
                        (void) force_number(n2);
                        switch (op->opcode) {
                        case Op_times:
diff --git a/awkgram.y b/awkgram.y
index 74a5611..b6fd00c 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -870,6 +870,7 @@ simple_stmt
                                        && $3->nexti->nexti->nexti == $3->lasti
                                        && $3->nexti->nexti->opcode == Op_push_i
                                        && $3->nexti->nexti->memory->type == 
Node_val
+                                       && ($3->nexti->nexti->memory->flags & 
MPFN) == 0
                                        && $3->nexti->nexti->memory->numbr == 
0.0)
                        )
                ) {
@@ -1446,6 +1447,7 @@ non_post_simp_exp
                } else {
                        if (do_optimize > 1 && $2->nexti == $2->lasti
                                        && $2->nexti->opcode == Op_push_i
+                                       && ($2->nexti->memory->flags & MPFN) == 0
                        ) {
                                NODE *n = $2->nexti->memory;
                                if ((n->flags & (STRCUR|STRING)) != 0) {
@@ -1794,7 +1796,7 @@ tokcompare(const void *l, const void *r)
  */
 
 #ifdef HAVE_MPFR
-#define MPF(F) F##_mpfr
+#define MPF(F) do_mpfr_##F
 #else
 #define MPF(F) 0
 #endif
@@ -1807,20 +1809,20 @@ static const struct token tokentab[] = {
 #ifdef ARRAYDEBUG
 {"adump",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1)|A(2),        
do_adump,       0},
 #endif
-{"and",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_and, 
MPF(do_and)},
+{"and",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_and, 
MPF(and)},
 #ifdef ARRAYDEBUG
 {"aoption",    Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_aoption,     
0},
 #endif
 {"asort",      Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3),   
do_asort,       0},
 {"asorti",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3),   
do_asorti,      0},
-{"atan2",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2),   do_atan2,       
MPF(do_atan2)},
+{"atan2",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2),   do_atan2,       
MPF(atan2)},
 {"bindtextdomain",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2),        
do_bindtextdomain,      0},
 {"break",      Op_K_break,      LEX_BREAK,     0,              0,      0},
 {"case",       Op_K_case,       LEX_CASE,      GAWKX,          0,      0},
 {"close",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1)|A(2),      
do_close,       0},
-{"compl",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_compl,       
MPF(do_compl)},
+{"compl",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_compl,       
MPF(compl)},
 {"continue",   Op_K_continue, LEX_CONTINUE,    0,              0,      0},
-{"cos",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_cos, 
MPF(do_cos)},
+{"cos",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_cos, 
MPF(cos)},
 {"dcgettext",  Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3),   
do_dcgettext,   0},
 {"dcngettext", Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2)|A(3)|A(4)|A(5), 
do_dcngettext,  0},
 {"default",    Op_K_default,    LEX_DEFAULT,   GAWKX,          0,      0},
@@ -1829,7 +1831,7 @@ static const struct token tokentab[] = {
 {"else",       Op_K_else,       LEX_ELSE,      0,              0,      0},
 {"eval",       Op_symbol,       LEX_EVAL,      0,              0,      0},
 {"exit",       Op_K_exit,       LEX_EXIT,      0,              0,      0},
-{"exp",                Op_builtin,      LEX_BUILTIN,   A(1),           do_exp, 
MPF(do_exp)},
+{"exp",                Op_builtin,      LEX_BUILTIN,   A(1),           do_exp, 
MPF(exp)},
 {"extension",  Op_builtin,      LEX_BUILTIN,   GAWKX|A(2),     do_ext, 0},
 {"fflush",     Op_builtin,      LEX_BUILTIN,   RESX|A(0)|A(1), do_fflush,      
0},
 {"for",                Op_K_for,        LEX_FOR,       BREAK|CONTINUE, 0,      
0},
@@ -1842,29 +1844,29 @@ static const struct token tokentab[] = {
 {"in",         Op_symbol,       LEX_IN,        0,              0,      0},
 {"include",  Op_symbol,         LEX_INCLUDE,   GAWKX,  0,      0},
 {"index",      Op_builtin,      LEX_BUILTIN,   A(2),           do_index,       
0},
-{"int",                Op_builtin,      LEX_BUILTIN,   A(1),           do_int, 
MPF(do_int)},
+{"int",                Op_builtin,      LEX_BUILTIN,   A(1),           do_int, 
MPF(int)},
 {"isarray",    Op_builtin,      LEX_BUILTIN,   GAWKX|A(1),     do_isarray,     
0},
 {"length",     Op_builtin,      LEX_LENGTH,    A(0)|A(1),      do_length,      
0},
-{"log",                Op_builtin,      LEX_BUILTIN,   A(1),           do_log, 
MPF(do_log)},
-{"lshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_lshift,      
MPF(do_lshift)},
+{"log",                Op_builtin,      LEX_BUILTIN,   A(1),           do_log, 
MPF(log)},
+{"lshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_lshift,      
MPF(lshift)},
 {"match",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_match,    
0},
 {"mktime",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1),     do_mktime,      
0},
 {"next",       Op_K_next,       LEX_NEXT,      0,              0,      0},
 {"nextfile",   Op_K_nextfile, LEX_NEXTFILE,    GAWKX,          0,      0},
-{"or",         Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_or,  
MPF(do_or)},
+{"or",         Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_or,  
MPF(or)},
 {"patsplit",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(2)|A(3)|A(4), 
do_patsplit,      0},
 {"print",      Op_K_print,      LEX_PRINT,     0,              0,      0},
 {"printf",     Op_K_printf,     LEX_PRINTF,    0,              0,      0},
-{"rand",       Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0),   do_rand,        
MPF(do_rand)},
+{"rand",       Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0),   do_rand,        
MPF(rand)},
 {"return",     Op_K_return,     LEX_RETURN,    NOT_OLD,        0,      0},
-{"rshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_rshift,      
MPF(do_rhift)},
-{"sin",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_sin, 
MPF(do_sin)},
+{"rshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_rshift,      
MPF(rhift)},
+{"sin",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_sin, 
MPF(sin)},
 {"split",      Op_builtin,      LEX_BUILTIN,   A(2)|A(3)|A(4), do_split,       
0},
 {"sprintf",    Op_builtin,      LEX_BUILTIN,   0,              do_sprintf,     
0},
-{"sqrt",       Op_builtin,      LEX_BUILTIN,   A(1),           do_sqrt,        
MPF(do_sqrt)},
-{"srand",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0)|A(1), do_srand,    
MPF(do_srand)},
+{"sqrt",       Op_builtin,      LEX_BUILTIN,   A(1),           do_sqrt,        
MPF(sqrt)},
+{"srand",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(0)|A(1), do_srand,    
MPF(srand)},
 {"strftime",   Op_builtin,      LEX_BUILTIN,   GAWKX|A(0)|A(1)|A(2)|A(3), 
do_strftime, 0},
-{"strtonum",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_strtonum, 
MPF(do_strtonum)},
+{"strtonum",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_strtonum, 
MPF(strtonum)},
 {"sub",                Op_sub_builtin,  LEX_BUILTIN,   NOT_OLD|A(2)|A(3), 0,   
0},
 {"substr",     Op_builtin,      LEX_BUILTIN,   A(2)|A(3),      do_substr,      
0},
 {"switch",     Op_K_switch,     LEX_SWITCH,    GAWKX|BREAK,    0,      0},
@@ -1873,7 +1875,7 @@ static const struct token tokentab[] = {
 {"tolower",    Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_tolower,     
0},
 {"toupper",    Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_toupper,     
0},
 {"while",      Op_K_while,      LEX_WHILE,     BREAK|CONTINUE, 0,      0},
-{"xor",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_xor, 
MPF(do_xor)},
+{"xor",                Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_xor, 
MPF(xor)},
 };
 
 #if MBS_SUPPORT
@@ -3879,6 +3881,8 @@ parms_shadow(INSTRUCTION *pc, int *shadow)
 void
 valinfo(NODE *n, Func_print print_func, FILE *fp)
 {
+       /* FIXME -- MPFR */
+
        if (n == Nnull_string)
                print_func(fp, "uninitialized scalar\n");
        else if (n->flags & STRING) {
@@ -4438,11 +4442,11 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION 
*op)
                ip1 = s1->nexti;
                if (do_optimize > 1
                                && ip1 == s1->lasti && ip1->opcode == Op_push_i
-                               && (ip1->memory->flags & (STRCUR|STRING)) == 0
-                               && (ip2->memory->flags & (STRCUR|STRING)) == 0
+                               && (ip1->memory->flags & (MPFN|STRCUR|STRING)) 
== 0
+                               && (ip2->memory->flags & (MPFN|STRCUR|STRING)) 
== 0
                ) {
                        NODE *n1 = ip1->memory, *n2 = ip2->memory;
-                       res = force_number(n1);
+                       res = force_number(n1)->numbr;
                        (void) force_number(n2);
                        switch (op->opcode) {
                        case Op_times:
diff --git a/builtin.c b/builtin.c
index 0c9553a..d403b7a 100644
--- a/builtin.c
+++ b/builtin.c
@@ -135,7 +135,7 @@ do_exp(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("exp: received non-numeric argument"));
-       d = force_number(tmp);
+       d = force_number(tmp)->numbr;
        DEREF(tmp);
        errno = 0;
        res = exp(d);
@@ -459,7 +459,7 @@ do_int(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("int: received non-numeric argument"));
-       d = force_number(tmp);
+       d = force_number(tmp)->numbr;
        d = double_to_int(d);
        DEREF(tmp);
        return make_number((AWKNUM) d);
@@ -537,7 +537,7 @@ do_log(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("log: received non-numeric argument"));
-       arg = (double) force_number(tmp);
+       arg = force_number(tmp)->numbr;
        if (arg < 0.0)
                warning(_("log: received negative argument %g"), arg);
        d = log(arg);
@@ -644,7 +644,6 @@ format_tree(
        char *chp;
        size_t copy_count, char_count;
 #ifdef HAVE_MPFR
-       extern mpz_t mpzval;    /* initialized in mpfr.c */
        enum { MPFR_INT_WITH_PREC = 1, MPFR_INT_WITHOUT_PREC, MPFR_FLOAT } 
mpfr_fmt_type;
 #endif
        static const char sp[] = " ";
@@ -869,7 +868,8 @@ check_pos:
                        } else {
                                parse_next_arg();
                        }
-                       *cur = force_number(arg);
+                       (void) force_number(arg);
+                       *cur = get_number_si(arg);
                        if (*cur < 0 && cur == &fw) {
                                *cur = -*cur;
                                lj++;
@@ -977,7 +977,7 @@ check_pos:
                        if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM)
                                (void) force_number(arg);
                        if (arg->flags & NUMBER) {
-                               uval = (uintmax_t) arg->numbr;
+                               uval = get_number_uj(arg);
 #if MBS_SUPPORT
                                if (gawk_mb_cur_max > 1) {
                                        char buf[100];
@@ -1183,17 +1183,40 @@ out2:
 
 #ifdef HAVE_MPFR
                        if (arg->flags & MPFN) {
+                               mpfr_ptr mt;
 mpfr_int:
-                               if (have_prec && prec == 0)
-                                       zero_flag = FALSE;
+                               mt = arg->mpfr_numbr;
+                               if (! mpfr_number_p(mt)) {
+                                       /* inf or NaN */
+                                       cs1 = 'g';
+                                       goto format_float;
+                               }
+
+                               if (cs1 != 'd' && cs1 != 'i') {
+                                       if (mpfr_sgn(mt) < 0) {
+                                               if (! mpfr_fits_intmax_p(mt, 
RND_MODE)) {
+                                                       /* -ve number is too 
large */
+                                                       cs1 = 'g';
+                                                       goto format_float;
+                                               }
+                                               uval = (uintmax_t) 
mpfr_get_sj(mt, RND_MODE);
+                                               goto format_fixed_int;
+                                       }
+                                       signchar = FALSE;       /* Don't print 
'+' */
+                               }
+
+                               /* See comments above about when to fill with 
zeros */
+                               zero_flag = (! lj
+                                                   && ((zero_flag && ! 
have_prec)
+                                                        || (fw == 0 && 
have_prec)));
 
-                               (void) mpfr_get_z(mpzval, arg->mpfr_numbr, 
MPFR_RNDZ);
-                               mpfr_fmt_type = have_prec ? MPFR_INT_WITH_PREC 
: MPFR_INT_WITHOUT_PREC;
+                               (void) mpfr_get_z(mpzval, mt, MPFR_RNDZ);       
/* convert to GMP int */
+                               mpfr_fmt_type = have_prec ? MPFR_INT_WITH_PREC 
: MPFR_INT_WITHOUT_PREC;
                                goto format_int;
                        } else
 #endif
-                       tmpval = arg->numbr;
- 
+                               tmpval = arg->numbr;
+
                        /*
                         * ``The result of converting a zero value with a
                         * precision of zero is no characters.''
@@ -1211,14 +1234,14 @@ mpfr_int:
 
                        if (tmpval < 0) {
                                uval = (uintmax_t) (intmax_t) tmpval;
-                               if ((AWKNUM)(intmax_t)uval !=
-                                   double_to_int(tmpval))
+                               if ((AWKNUM)(intmax_t)uval != 
double_to_int(tmpval))
                                        goto out_of_range;
                        } else {
                                uval = (uintmax_t) tmpval;
                                if ((AWKNUM)uval != double_to_int(tmpval))
                                        goto out_of_range;
                        }
+       format_fixed_int:
                        /*
                         * When to fill with zeroes is of course not simple.
                         * First: No zero fill if left-justifying.
@@ -1319,8 +1342,10 @@ mpfr_int:
      format_float:
                        if ((arg->flags & MPFN) == 0)
                                tmpval = arg->numbr;
+#ifdef HAVE_MPFR
                        else
                                mpfr_fmt_type = MPFR_FLOAT;
+#endif
                        if (! have_prec)
                                prec = DEFAULT_G_PRECISION;
      format_int:
@@ -1339,7 +1364,7 @@ mpfr_int:
                                *cp++ = '\'';
 
 #ifdef HAVE_MPFR
-                       if (do_mpfr) {
+                       if (arg->flags & MPFN) {
                                if (mpfr_fmt_type == MPFR_INT_WITH_PREC) {
                                        strcpy(cp, "*.*Z");
                                        cp += 4;
@@ -1375,7 +1400,7 @@ mpfr_int:
                                                while ((n = 
mpfr_snprintf(obufout, ofre, cpbuf,
                                                             (int) fw, mpzval)) 
>= ofre)
                                                        chksize(n)
-                                       } else {        
+                                       } else {
                                                while ((n = 
mpfr_snprintf(obufout, ofre, cpbuf,
                                                             (int) fw, (int) 
prec, RND_MODE,
                                                             arg->mpfr_numbr)) 
>= ofre)
@@ -1546,7 +1571,7 @@ do_sqrt(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("sqrt: received non-numeric argument"));
-       arg = (double) force_number(tmp);
+       arg = (double) force_number(tmp)->numbr;
        DEREF(tmp);
        if (arg < 0.0)
                warning(_("sqrt: called with negative argument %g"), arg);
@@ -1565,9 +1590,16 @@ do_substr(int nargs)
        double d_index = 0, d_length = 0;
        size_t src_len;
 
-       if (nargs == 3)
-               POP_NUMBER(d_length);
-       POP_NUMBER(d_index);
+       if (nargs == 3) {
+               t1 = POP_NUMBER();
+               d_length = get_number_d(t1);
+               DEREF(t1);
+       }
+
+       t1 = POP_NUMBER();
+       d_index = get_number_d(t1);
+       DEREF(t1);
+
        t1 = POP_STRING();
 
        if (nargs == 3) {
@@ -1751,7 +1783,8 @@ do_strftime(int nargs)
                        t2 = POP_SCALAR();
                        if (do_lint && (t2->flags & (NUMCUR|NUMBER)) == 0)
                                lintwarn(_("strftime: received non-numeric 
second argument"));
-                       clock_val = (long) force_number(t2);
+                       (void) force_number(t2);
+                       clock_val = get_number_si(t2);
                        if (clock_val < 0)
                                fatal(_("strftime: second argument less than 0 
or too big for time_t"));
                        fclock = (time_t) clock_val;
@@ -2169,8 +2202,8 @@ do_atan2(int nargs)
                if ((t2->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("atan2: received non-numeric second 
argument"));
        }
-       d1 = force_number(t1);
-       d2 = force_number(t2);
+       d1 = force_number(t1)->numbr;
+       d2 = force_number(t2)->numbr;
        DEREF(t1);
        DEREF(t2);
        return make_number((AWKNUM) atan2(d1, d2));
@@ -2187,7 +2220,7 @@ do_sin(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("sin: received non-numeric argument"));
-       d = sin((double) force_number(tmp));
+       d = sin((double) force_number(tmp)->numbr);
        DEREF(tmp);
        return make_number((AWKNUM) d);
 }
@@ -2203,7 +2236,7 @@ do_cos(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("cos: received non-numeric argument"));
-       d = cos((double) force_number(tmp));
+       d = cos((double) force_number(tmp)->numbr);
        DEREF(tmp);
        return make_number((AWKNUM) d);
 }
@@ -2256,7 +2289,7 @@ do_srand(int nargs)
                tmp = POP_SCALAR();
                if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("srand: received non-numeric argument"));
-               srandom((unsigned int) (save_seed = (long) force_number(tmp)));
+               srandom((unsigned int) (save_seed = (long) 
force_number(tmp)->numbr));
                DEREF(tmp);
        }
        return make_number((AWKNUM) ret);
@@ -2533,15 +2566,16 @@ do_sub(int nargs, unsigned int flags)
                        if (t1->stlen > 0 && (t1->stptr[0] == 'g' || 
t1->stptr[0] == 'G'))
                                how_many = -1;
                        else {
-                               d = force_number(t1);
-
+                               (void) force_number(t1);
+                               d = get_number_d(t1);
                                if ((t1->flags & NUMCUR) != 0)
                                        goto set_how_many;
 
                                how_many = 1;
                        }
                } else {
-                       d = force_number(t1);
+                       (void) force_number(t1);
+                       d = get_number_d(t1);
 set_how_many:
                        if (d < 1)
                                how_many = 1;
@@ -2847,8 +2881,8 @@ do_lshift(int nargs)
                if ((s2->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("lshift: received non-numeric second 
argument"));
        }
-       val = force_number(s1);
-       shift = force_number(s2);
+       val = force_number(s1)->numbr;
+       shift = force_number(s2)->numbr;
        if (do_lint) {
                if (val < 0 || shift < 0)
                        lintwarn(_("lshift(%lf, %lf): negative values will give 
strange results"), val, shift);
@@ -2884,8 +2918,8 @@ do_rshift(int nargs)
                if ((s2->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("rshift: received non-numeric second 
argument"));
        }
-       val = force_number(s1);
-       shift = force_number(s2);
+       val = force_number(s1)->numbr;
+       shift = force_number(s2)->numbr;
        if (do_lint) {
                if (val < 0 || shift < 0)
                        lintwarn(_("rshift(%lf, %lf): negative values will give 
strange results"), val, shift);
@@ -2921,8 +2955,8 @@ do_and(int nargs)
                if ((s2->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("and: received non-numeric second 
argument"));
        }
-       left = force_number(s1);
-       right = force_number(s2);
+       left = force_number(s1)->numbr;
+       right = force_number(s2)->numbr;
        if (do_lint) {
                if (left < 0 || right < 0)
                        lintwarn(_("and(%lf, %lf): negative values will give 
strange results"), left, right);
@@ -2956,8 +2990,8 @@ do_or(int nargs)
                if ((s2->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("or: received non-numeric second argument"));
        }
-       left = force_number(s1);
-       right = force_number(s2);
+       left = force_number(s1)->numbr;
+       right = force_number(s2)->numbr;
        if (do_lint) {
                if (left < 0 || right < 0)
                        lintwarn(_("or(%lf, %lf): negative values will give 
strange results"), left, right);
@@ -2985,8 +3019,6 @@ do_xor(int nargs)
        AWKNUM left, right;
 
        POP_TWO_SCALARS(s1, s2);
-       left = force_number(s1);
-       right = force_number(s2);
 
        if (do_lint) {
                if ((s1->flags & (NUMCUR|NUMBER)) == 0)
@@ -2994,8 +3026,8 @@ do_xor(int nargs)
                if ((s2->flags & (NUMCUR|NUMBER)) == 0)
                        lintwarn(_("xor: received non-numeric second 
argument"));
        }
-       left = force_number(s1);
-       right = force_number(s2);
+       left = force_number(s1)->numbr;
+       right = force_number(s2)->numbr;
        if (do_lint) {
                if (left < 0 || right < 0)
                        lintwarn(_("xor(%lf, %lf): negative values will give 
strange results"), left, right);
@@ -3025,7 +3057,7 @@ do_compl(int nargs)
        tmp = POP_SCALAR();
        if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
                lintwarn(_("compl: received non-numeric argument"));
-       d = force_number(tmp);
+       d = force_number(tmp)->numbr;
        DEREF(tmp);
 
        if (do_lint) {
@@ -3052,11 +3084,11 @@ do_strtonum(int nargs)
 
        tmp = POP_SCALAR();
        if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
-               d = (AWKNUM) force_number(tmp);
+               d = (AWKNUM) force_number(tmp)->numbr;
        else if (get_numbase(tmp->stptr, use_lc_numeric) != 10)
                d = nondec2awknum(tmp->stptr, tmp->stlen);
        else
-               d = (AWKNUM) force_number(tmp);
+               d = (AWKNUM) force_number(tmp)->numbr;
 
        DEREF(tmp);
        return make_number((AWKNUM) d);
@@ -3306,7 +3338,10 @@ do_dcngettext(int nargs)
        }
 #endif
 
-       POP_NUMBER(d);  /* third argument */
+       t2 = POP_NUMBER();      /* third argument */
+       d = get_number_d(t2);
+       DEREF(t2);
+
        number = (unsigned long) double_to_int(d);
        t2 = POP_STRING();      /* second argument */
        string2 = t2->stptr;
diff --git a/eval.c b/eval.c
index ffe7bdd..920855a 100644
--- a/eval.c
+++ b/eval.c
@@ -583,9 +583,19 @@ cmp_nodes(NODE *t1, NODE *t2)
        if (t1->flags & INTIND)
                t1 = force_string(t1);
        if (t2->flags & INTIND)
-               t2 = force_string(t2);  
+               t2 = force_string(t2);
 
        if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) {
+#ifdef HAVE_MPFR
+               if (t1->flags & MPFN) {
+                       assert((t2->flags & MPFN) != 0);
+                       
+                       /* Note: returns zero if either t1 or t2 is NaN */
+                       return mpfr_cmp(t1->mpfr_numbr, t2->mpfr_numbr);
+               }
+               assert((t2->flags & MPFN) == 0);
+#endif
+
                if (t1->numbr == t2->numbr)
                        ret = 0;
                /* don't subtract, in case one or both are infinite */
@@ -1023,10 +1033,12 @@ update_ERRNO()
 void
 update_NR()
 {
-       double d;
-
-       d = get_number_d(NR_node->var_value);
-       if (d != NR) {
+#ifdef HAVE_MPFR
+       if ((NR_node->var_value->flags & MPFN) != 0)
+               mpfr_update_var(NR_node);
+       else
+#endif
+       if (NR_node->var_value->numbr != NR) {
                unref(NR_node->var_value);
                NR_node->var_value = make_number((AWKNUM) NR);
        }
@@ -1053,10 +1065,12 @@ update_NF()
 void
 update_FNR()
 {
-       double d;
-
-       d = get_number_d(FNR_node->var_value);
-       if (d != FNR) {
+#ifdef HAVE_MPFR
+       if ((FNR_node->var_value->flags & MPFN) != 0)
+               mpfr_update_var(FNR_node);
+       else
+#endif
+       if (FNR_node->var_value->numbr != FNR) {
                unref(FNR_node->var_value);
                FNR_node->var_value = make_number((AWKNUM) FNR);
        }
@@ -1156,7 +1170,9 @@ r_get_field(NODE *n, Func_ptr *assign, int reference)
                }
        }
 
-       field_num = (long) force_number(n);
+       (void) force_number(n);
+       field_num = get_number_si(n);
+
        if (field_num < 0)
                fatal(_("attempt to access field %ld"), field_num);
 
@@ -1495,7 +1511,7 @@ eval_condition(NODE *t)
                force_number(t);
 
        if ((t->flags & NUMBER) != 0)
-               return (t->numbr != 0.0);
+               return is_nonzero_num(t);
 
        return (t->stlen != 0);
 }
@@ -1527,13 +1543,16 @@ static void
 op_assign(OPCODE op)
 {
        NODE **lhs;
-       NODE *t1;
+       NODE *t1, *t2;
        AWKNUM x = 0.0, x1, x2;
 
        lhs = POP_ADDRESS();
        t1 = *lhs;
-       x1 = force_number(t1);
-       TOP_NUMBER(x2);
+       x1 = force_number(t1)->numbr;
+
+       t2 = TOP_SCALAR();
+       x2 = force_number(t2)->numbr;
+       DEREF(t2);
 
        switch (op) {
        case Op_assign_plus:
@@ -1583,7 +1602,6 @@ op_assign(OPCODE op)
        REPLACE(t1);
 }
 
-
 /* PUSH_CODE --- push a code onto the runtime stack */
 
 void
@@ -1700,13 +1718,19 @@ init_interpret()
 
        /* initialize TRUE and FALSE nodes */
        node_Boolean[FALSE] = make_number(0);
-       node_Boolean[FALSE]->flags |= NUMINT;
        node_Boolean[TRUE] = make_number(1.0);
-       node_Boolean[TRUE]->flags |= NUMINT;
+       if ((node_Boolean[FALSE]->flags & MPFN) == 0) {
+               node_Boolean[FALSE]->flags |= NUMINT;
+               node_Boolean[TRUE]->flags |= NUMINT;
+       }
 
        /* select the interpreter routine */
        if (do_debug)
                interpret = debug_interpret;
+#ifdef HAVE_MPFR
+       else if (do_mpfr)
+               interpret = mpfr_interpret;
+#endif
        else
                interpret = r_interpret;
 }
@@ -1722,3 +1746,10 @@ init_interpret()
 #undef DEBUGGING
 #undef r_interpret
 
+#ifdef HAVE_MPFR
+#define r_interpret mpfr_interpret
+#define EXE_MPFR 1
+#include "interpret.h"
+#undef EXE_MPFR
+#undef r_interpret
+#endif
diff --git a/int_array.c b/int_array.c
index 9dd20be..d998310 100644
--- a/int_array.c
+++ b/int_array.c
@@ -86,7 +86,7 @@ is_integer(NODE *symbol, NODE *subs)
        long l;
        AWKNUM d;
 
-       if (subs == Nnull_string)
+       if (subs == Nnull_string || do_mpfr)
                return NULL;
 
        if ((subs->flags & NUMINT) != 0)
diff --git a/interpret.h b/interpret.h
index 67a702e..83e7805 100644
--- a/interpret.h
+++ b/interpret.h
@@ -1,31 +1,27 @@
 /*
- * interpret:
- *   code is a list of instructions to run. returns the exit value
- *      from the awk code.
- */
- 
- /* N.B.:
- *   1) reference counting done for both number and string values.
- *   2) Stack operations:
- *       Use REPLACE[_XX] if last stack operation was TOP[_XX],
- *       PUSH[_XX] if last operation was POP[_XX] instead. 
- *   3) UPREF and DREF -- see awk.h 
+ * interpret ---  code is a list of instructions to run.
  */
 
+#ifdef EXE_MPFR
+#define NV(r)  r->mpfr_numbr
+#else
+#define NV(r)  r->numbr
+#endif
+
+
 int
 r_interpret(INSTRUCTION *code)
 {
        INSTRUCTION *pc;   /* current instruction */
+       OPCODE op;      /* current opcode */
        NODE *r = NULL;
        NODE *m;
        INSTRUCTION *ni;
        NODE *t1, *t2;
-       NODE *f;        /* function definition */
        NODE **lhs;
-       AWKNUM x, x1, x2;
+       AWKNUM x;
        int di;
        Regexp *rp;
-       int stdio_problem = FALSE;
 
 /* array subscript */
 #define mk_sub(n)      (n == 1 ? POP_SCALAR() : concat_exp(n, TRUE))
@@ -52,11 +48,11 @@ top:
                        sourceline = pc->source_line;
 
 #ifdef DEBUGGING
-               if (! pre_execute(&pc))
+               if (! pre_execute(& pc))
                        goto top;
 #endif
 
-               switch (pc->opcode) {
+               switch ((op = pc->opcode)) {
                case Op_rule:
                        currule = pc->in_rule;   /* for sole use in Op_K_next, 
Op_K_nextfile, Op_K_getline */
                        /* fall through */
@@ -65,6 +61,9 @@ top:
                        break;
 
                case Op_atexit:
+               {
+                       int stdio_problem = FALSE;
+
                        /* avoid false source indications */
                        source = NULL;
                        sourceline = 0;
@@ -87,6 +86,7 @@ top:
                         */
                        if (stdio_problem && ! exiting && exit_val == 0)
                                exit_val = 1;
+               }
                        break;
 
                case Op_stop:
@@ -147,7 +147,7 @@ top:
                                break;
 
                        case Node_var_array:
-                               if (pc->opcode == Op_push_arg)
+                               if (op == Op_push_arg)
                                        PUSH(m);
                                else
                                        fatal(_("attempt to use array `%s' in a 
scalar context"),
@@ -303,8 +303,7 @@ top:
                        t1 = POP_SCALAR();
                        di = eval_condition(t1);
                        DEREF(t1);
-                       if ((pc->opcode == Op_and && di)
-                                       || (pc->opcode == Op_or && ! di))
+                       if ((op == Op_and && di) || (op == Op_or && ! di))
                                break;
                        r = node_Boolean[di];
                        UPREF(r);
@@ -366,128 +365,198 @@ top:
                        break;
 
                case Op_plus_i:
-                       x2 = force_number(pc->memory);
+                       t2 = force_number(pc->memory);
                        goto plus;
-
                case Op_plus:
-                       POP_NUMBER(x2);
+                       t2 = POP_NUMBER();
 plus:
-                       TOP_NUMBER(x1);
-                       r = make_number(x1 + x2);
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_add(NV(r), NV(t1), NV(t2), RND_MODE);
+#else
+                       r = make_number(NV(t1) + NV(t2));
+#endif
+                       DEREF(t1);
+                       if (op == Op_plus)
+                               DEREF(t2);
                        REPLACE(r);
                        break;
 
                case Op_minus_i:
-                       x2 = force_number(pc->memory);
+                       t2 = force_number(pc->memory);
                        goto minus;
-
                case Op_minus:
-                       POP_NUMBER(x2);
+                       t2 = POP_NUMBER();
 minus:
-                       TOP_NUMBER(x1);
-                       r = make_number(x1 - x2);
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_sub(NV(r), NV(t1), NV(t2), RND_MODE);
+#else
+                       r = make_number(NV(t1) - NV(t2));
+#endif
+                       DEREF(t1);
+                       if (op == Op_minus)
+                               DEREF(t2);
                        REPLACE(r);
                        break;
 
                case Op_times_i:
-                       x2 = force_number(pc->memory);
+                       t2 = force_number(pc->memory);
                        goto times;
-
                case Op_times:
-                       POP_NUMBER(x2);
+                       t2 = POP_NUMBER();
 times:
-                       TOP_NUMBER(x1);
-                       r = make_number(x1 * x2);
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_mul(NV(r), NV(t1), NV(t2), RND_MODE);
+#else
+                       r = make_number(NV(t1) * NV(t2));
+#endif
+                       DEREF(t1);
+                       if (op == Op_times)
+                               DEREF(t2);
                        REPLACE(r);
                        break;
 
                case Op_exp_i:
-                       x2 = force_number(pc->memory);
-                       goto exponent;
-
+                       t2 = force_number(pc->memory);
+                       goto exp;
                case Op_exp:
-                       POP_NUMBER(x2);
-exponent:
-                       TOP_NUMBER(x1);
-                       x = calc_exp(x1, x2);
+                       t2 = POP_NUMBER();
+exp:
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_pow(NV(r), NV(t1), NV(t2), RND_MODE);
+#else
+                       x = calc_exp(NV(t1), NV(t2));
                        r = make_number(x);
+#endif
+                       DEREF(t1);
+                       if (op == Op_exp)
+                               DEREF(t2);
                        REPLACE(r);
                        break;
 
                case Op_quotient_i:
-                       x2 = force_number(pc->memory);
+                       t2 = force_number(pc->memory);
                        goto quotient;
-
                case Op_quotient:
-                       POP_NUMBER(x2);
+                       t2 = POP_NUMBER();
 quotient:
-                       if (x2 == 0)
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_div(NV(r), NV(t1), NV(t2), RND_MODE);
+#else
+                       if (NV(t2) == 0)
                                fatal(_("division by zero attempted"));
-
-                       TOP_NUMBER(x1);
-                       x = x1 / x2;
+                       x = NV(t1) / NV(t2);
                        r = make_number(x);
+#endif
+                       DEREF(t1);
+                       if (op == Op_quotient)
+                               DEREF(t2);
                        REPLACE(r);
                        break;          
 
                case Op_mod_i:
-                       x2 = force_number(pc->memory);
+                       t2 = force_number(pc->memory);
                        goto mod;
-
                case Op_mod:
-                       POP_NUMBER(x2);
+                       t2 = POP_NUMBER();
 mod:
-                       if (x2 == 0)
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_fmod(NV(r), NV(t1), NV(t2), RND_MODE);
+#else
+                       if (NV(t2) == 0)
                                fatal(_("division by zero attempted in `%%'"));
-
-                       TOP_NUMBER(x1);
 #ifdef HAVE_FMOD
-                       x = fmod(x1, x2);
+                       x = fmod(NV(t1), NV(t2));
 #else  /* ! HAVE_FMOD */
-                       (void) modf(x1 / x2, &x);
-                       x = x1 - x * x2;
+                       (void) modf(NV(t1) / NV(t2), &x);
+                       x = NV(t1) - x * NV(t2);
 #endif /* ! HAVE_FMOD */
                        r = make_number(x);
+#endif
+                       DEREF(t1);
+                       if (op == Op_mod)
+                               DEREF(t2);
                        REPLACE(r);
-                       break;          
+                       break;
 
                case Op_preincrement:
                case Op_predecrement:
-                       x2 = pc->opcode == Op_preincrement ? 1.0 : -1.0;
+                       x = op == Op_preincrement ? 1.0 : -1.0;
                        lhs = TOP_ADDRESS();
                        t1 = *lhs;
-                       x1 = force_number(t1);
+                       force_number(t1);
                        if (t1->valref == 1 && t1->flags == 
(MALLOC|NUMCUR|NUMBER)) {
                                /* optimization */
-                               t1->numbr = x1 + x2;
+#ifdef EXE_MPFR
+                               mpfr_add_d(NV(t1), NV(t1), x, RND_MODE);
+#else
+                               NV(t1) += x;
+#endif
+                               r = t1;
                        } else {
+#ifdef EXE_MPFR
+                               r = *lhs = mpfr_node();
+                               mpfr_add_d(NV(r), NV(t1), x, RND_MODE);
+#else
+                               r = *lhs = make_number(NV(t1) + x);
+#endif
                                unref(t1);
-                               t1 = *lhs = make_number(x1 + x2);
                        }
-                       UPREF(t1);
-                       REPLACE(t1);
+                       UPREF(r);
+                       REPLACE(r);
                        break;
 
                case Op_postincrement:
                case Op_postdecrement:
-                       x2 = pc->opcode == Op_postincrement ? 1.0 : -1.0;
+                       x = op == Op_postincrement ? 1.0 : -1.0;
                        lhs = TOP_ADDRESS();
                        t1 = *lhs;
-                       x1 = force_number(t1);
+                       force_number(t1);
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_set(NV(r), NV(t1), RND_MODE);      /* r = t1 */
                        if (t1->valref == 1 && t1->flags == 
(MALLOC|NUMCUR|NUMBER)) {
                                /* optimization */
-                               t1->numbr = x1 + x2;
+                               mpfr_add_d(NV(t1), NV(t1), x, RND_MODE);
                        } else {
+                               t2 = *lhs = mpfr_node();
+                               mpfr_add_d(NV(t2), NV(t1), x, RND_MODE);
                                unref(t1);
-                               *lhs = make_number(x1 + x2);
                        }
-                       r = make_number(x1);
+#else
+                       r = make_number(NV(t1));
+                       if (t1->valref == 1 && t1->flags == 
(MALLOC|NUMCUR|NUMBER)) {
+                               /* optimization */
+                               NV(t1) += x;
+                       } else {
+                               *lhs = make_number(NV(t1) + x);
+                               unref(t1);
+                       }
+#endif
                        REPLACE(r);
                        break;
 
                case Op_unary_minus:
-                       TOP_NUMBER(x1);
-                       r = make_number(-x1);
+                       t1 = TOP_NUMBER();
+#ifdef EXE_MPFR
+                       r = mpfr_node();
+                       mpfr_set(NV(r), NV(t1), RND_MODE);      /* r = t1 */
+                       mpfr_neg(NV(r), NV(r), RND_MODE);       /* change sign 
*/
+#else
+                       r = make_number(-NV(t1));
+#endif
+                       DEREF(t1);
                        REPLACE(r);
                        break;
 
@@ -532,7 +601,7 @@ mod:
 
                        Func_ptr assign;
                        t1 = TOP_SCALAR();
-                       lhs = r_get_field(t1, &assign, FALSE);
+                       lhs = r_get_field(t1, & assign, FALSE);
                        decr_sp();
                        DEREF(t1);
                        unref(*lhs);
@@ -555,7 +624,7 @@ mod:
                                *lhs = dupnode(t1);
                        }
 
-                       if (t1 != t2 && t1->valref == 1) {
+                       if (t1 != t2 && t1->valref == 1 && (t1->flags & MPFN) 
== 0) {
                                size_t nlen = t1->stlen + t2->stlen;
 
                                erealloc(t1->stptr, char *, nlen + 2, 
"r_interpret");
@@ -592,7 +661,11 @@ mod:
                case Op_assign_quotient:
                case Op_assign_mod:
                case Op_assign_exp:
-                       op_assign(pc->opcode);
+#ifdef EXE_MPFR
+                       op_mpfr_assign(op);
+#else
+                       op_assign(op);
+#endif
                        break;
 
                case Op_var_update:        /* update value of NR, FNR or NF */
@@ -601,8 +674,18 @@ mod:
 
                case Op_var_assign:
                case Op_field_assign:
+                       r = TOP();
+#ifdef EXE_MPFR
+                               di = mpfr_sgn(NV(r));
+#else
+                       if (NV(r) < 0.0)
+                               di = -1;
+                       else
+                               di = (NV(r) > 0.0);
+#endif
+
                        if (pc->assign_ctxt == Op_sub_builtin
-                               && TOP()->numbr == 0.0  /* top of stack has a 
number == 0 */
+                               && di == 0      /* top of stack has a number == 
0 */
                        ) {
                                /* There wasn't any substitutions. If the 
target is a FIELD,
                                 * this means no field re-splitting or $0 
reconstruction.
@@ -612,14 +695,14 @@ mod:
                                break;
                        } else if ((pc->assign_ctxt == Op_K_getline
                                        || pc->assign_ctxt == 
Op_K_getline_redir)
-                               && TOP()->numbr <= 0.0  /* top of stack has a 
number <= 0 */
+                               && di <= 0      /* top of stack has a number <= 
0 */
                        ) {
                                /* getline returned EOF or error */
 
                                break;
                        }
 
-                       if (pc->opcode == Op_var_assign)
+                       if (op == Op_var_assign)
                                pc->assign_var();
                        else
                                pc->field_assign();
@@ -649,7 +732,6 @@ mod:
 
                        if (di) {
                                /* match found */
-
                                t2 = POP_SCALAR();
                                DEREF(t2);
                                JUMPTO(pc->target_jmp);
@@ -671,9 +753,10 @@ mod:
                case Op_in_array:
                        t1 = POP_ARRAY();
                        t2 = mk_sub(pc->expr_count);
-                       di = (in_array(t1, t2) != NULL);
+                       r = node_Boolean[(in_array(t1, t2) != NULL)];
                        DEREF(t2);
-                       PUSH(make_number((AWKNUM) di));
+                       UPREF(r);
+                       PUSH(r);
                        break;
 
                case Op_arrayfor_init:
@@ -816,8 +899,8 @@ match_re:
 
                        di = research(rp, t1->stptr, 0, t1->stlen,
                                                                avoid_dfa(m, 
t1->stptr, t1->stlen));
-                       di = (di == -1) ^ (pc->opcode != Op_nomatch);
-                       if(pc->opcode != Op_match_rec) {
+                       di = (di == -1) ^ (op != Op_nomatch);
+                       if (op != Op_match_rec) {
                                decr_sp();
                                DEREF(t1);
                        }
@@ -842,9 +925,9 @@ match_re:
 
                case Op_indirect_func_call:
                {
+                       NODE *f = NULL;
                        int arg_count;
 
-                       f = NULL;
                        arg_count = (pc + 1)->expr_count;
                        t1 = PEEK(arg_count);   /* indirect var */
                        assert(t1->type == Node_val);   /* @a[1](p) not allowed 
in grammar */
@@ -855,7 +938,8 @@ match_re:
                                if (f != NULL && strcmp(f->vname, t1->stptr) == 
0) {
                                        /* indirect var hasn't been reassigned 
*/
 
-                                       goto func_call;
+                                       ni = setup_frame(pc);
+                                       JUMPTO(ni);     /* Op_func */
                                }
                                f = lookup(t1->stptr);
                        }
@@ -865,10 +949,14 @@ match_re:
                                                pc->func_name); 
                        pc->func_body = f;     /* save for next call */
 
-                       goto func_call;
+                       ni = setup_frame(pc);
+                       JUMPTO(ni);     /* Op_func */
                }
 
                case Op_func_call:
+               {
+                       NODE *f;
+
                        /* retrieve function definition node */
                        f = pc->func_body;
                        if (f == NULL) {
@@ -894,11 +982,9 @@ match_re:
                                JUMPTO(ni);
                        }
 
-func_call:
                        ni = setup_frame(pc);
-                                               
-                       /* run the function instructions */
-                       JUMPTO(ni);             /* Op_func */
+                       JUMPTO(ni);     /* Op_func */
+               }
 
                case Op_K_return:
                        m = POP_SCALAR();       /* return value */
@@ -1074,8 +1160,10 @@ func_call:
                                fatal(_("`exit' cannot be called in the current 
context"));
 
                        exiting = TRUE;
-                       POP_NUMBER(x1);
-                       exit_val = (int) x1;
+                       t1 = POP_SCALAR();
+                       (void) force_number(t1);
+                       exit_val = (int) get_number_si(t1);
+                       DEREF(t1);
 #ifdef VMS
                        if (exit_val == 0)
                                exit_val = EXIT_SUCCESS;
@@ -1171,7 +1259,7 @@ func_call:
                        break;
 
                default:
-                       fatal(_("Sorry, don't know how to interpret `%s'"), 
opcode2str(pc->opcode));
+                       fatal(_("Sorry, don't know how to interpret `%s'"), 
opcode2str(op));
                }
 
                JUMPTO(pc->nexti);
@@ -1185,3 +1273,4 @@ func_call:
 #undef JUMPTO
 }
 
+#undef NV
diff --git a/io.c b/io.c
index 3eaceb8..66847e5 100644
--- a/io.c
+++ b/io.c
@@ -233,7 +233,6 @@ extern NODE *ARGIND_node;
 extern NODE *ERRNO_node;
 extern NODE **fields_arr;
 
-/* init_io --- set up timeout related variables */
 
 void
 init_io()
@@ -391,6 +390,10 @@ nextfile(IOBUF **curfile, int skipping)
                        /* This is a kludge.  */
                        unref(FILENAME_node->var_value);
                        FILENAME_node->var_value = dupnode(arg);
+#ifdef HAVE_MPFR
+                       if (FNR_node->var_value->flags & MPFN)
+                               mpfr_set_d(MFNR, 0.0, RND_MODE);
+#endif
                        FNR = 0;
                        iop = *curfile = iop_alloc(fd, fname, &mybuf, FALSE);
                        if (fd == INVALID_HANDLE)
@@ -437,7 +440,12 @@ void
 set_FNR()
 {
        (void) force_number(FNR_node->var_value);
-       FNR = get_number_si(FNR_node->var_value);
+#ifdef HAVE_MPFR
+       if ((FNR_node->var_value->flags & MPFN) != 0)
+               FNR = mpfr_set_var(FNR_node);
+       else
+#endif
+       FNR = FNR_node->var_value->numbr;
 }
 
 /* set_NR --- update internal NR from awk variable */
@@ -446,7 +454,12 @@ void
 set_NR()
 {
        (void) force_number(NR_node->var_value);
-       NR = get_number_si(NR_node->var_value);
+#ifdef HAVE_MPFR
+       if ((NR_node->var_value->flags & MPFN) != 0)
+               NR = mpfr_set_var(NR_node);
+       else
+#endif
+       NR = NR_node->var_value->numbr;
 }
 
 /* inrec --- This reads in a record from the input file */
@@ -470,8 +483,8 @@ inrec(IOBUF *iop, int *errcode)
                if (*errcode > 0)
                        update_ERRNO_saved(*errcode);
        } else {
-               NR += 1;
-               FNR += 1;
+               INCREMNT(NR);
+               INCREMNT(FNR);
                set_record(begin, cnt);
        }
 
@@ -2302,8 +2315,8 @@ do_getline(int intovar, IOBUF *iop)
 
        if (cnt == EOF)
                return NULL;    /* try next file */
-       NR++;
-       FNR++;
+       INCREMNT(NR);
+       INCREMNT(FNR);
 
        if (! intovar)  /* no optional var. */
                set_record(s, cnt);
@@ -3256,7 +3269,7 @@ pty_vs_pipe(const char *command)
                if (val->flags & MAYBE_NUM)
                        (void) force_number(val);
                if (val->flags & NUMBER)
-                       return (val->numbr != 0.0);
+                       return is_nonzero_num(val);
                else
                        return (val->stlen != 0);
        }
@@ -3389,8 +3402,10 @@ get_read_timeout(IOBUF *iop)
                } else  /* use cached full index */
                        val = in_array(PROCINFO_node, full_idx);
 
-               if (val != NULL)
-                       tmout = (long) force_number(val);
+               if (val != NULL) {
+                       (void) force_number(val);
+                       tmout = get_number_si(val);
+               }
        } else
                tmout = read_default_timeout;   /* initialized from env. 
variable in init_io() */
 
diff --git a/main.c b/main.c
index a7ebb29..00a63d5 100644
--- a/main.c
+++ b/main.c
@@ -450,7 +450,9 @@ main(int argc, char **argv)
                        break;
 
                case 'M':
+#ifdef HAVE_MPFR
                        do_flags |= DO_MPFR;
+#endif
                        break;
 
                case 'P':
@@ -956,9 +958,7 @@ static const struct varinit varinit[] = {
 {&FPAT_node,   "FPAT",         "[^[:space:]]+", 0,  NULL, set_FPAT,    FALSE, 
NON_STANDARD },
 {&IGNORECASE_node, "IGNORECASE", NULL, 0,  NULL, set_IGNORECASE,       FALSE, 
NON_STANDARD },
 {&LINT_node,   "LINT",         NULL,   0,  NULL, set_LINT,     FALSE, 
NON_STANDARD },
-#ifdef HAVE_MPFR
 {&PREC_node,   "PREC",         NULL,   DEFAULT_PREC,   NULL,   set_PREC,       
FALSE,  NON_STANDARD},  
-#endif
 {&NF_node,     "NF",           NULL,   -1, update_NF, set_NF,  FALSE, 0 },
 {&NR_node,     "NR",           NULL,   0,  update_NR, set_NR,  TRUE, 0 },
 {&OFMT_node,   "OFMT",         "%.6g", 0,  NULL, set_OFMT,     TRUE, 0 },
@@ -966,9 +966,7 @@ static const struct varinit varinit[] = {
 {&ORS_node,    "ORS",          "\n",   0,  NULL, set_ORS,      TRUE, 0 },
 {NULL,         "PROCINFO",     NULL,   0,  NULL, NULL, FALSE, NO_INSTALL | 
NON_STANDARD },
 {&RLENGTH_node, "RLENGTH",     NULL,   0,  NULL, NULL, FALSE, 0 },
-#ifdef HAVE_MPFR
 {&RNDMODE_node, "RNDMODE",     DEFAULT_RNDMODE,        0,  NULL, set_RNDMODE,  
FALSE, NON_STANDARD },
-#endif
 {&RS_node,     "RS",           "\n",   0,  NULL, set_RS,       TRUE, 0 },
 {&RSTART_node, "RSTART",       NULL,   0,  NULL, NULL, FALSE, 0 },
 {&RT_node,     "RT",           "",     0,  NULL, NULL, FALSE, NON_STANDARD },
diff --git a/mpfr.c b/mpfr.c
index 677bdcd..0875bc6 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -25,12 +25,28 @@
 
 #include "awk.h"
 
-#ifdef HAVE_MPFR
+#ifndef HAVE_MPFR
+
+void
+set_PREC()
+{
+       /* dummy function */
+}
+
+void
+set_RNDMODE()
+{
+       /* dummy function */
+}
+
+#else
 
 #ifndef mp_bitcnt_t
 #define        mp_bitcnt_t unsigned long
 #endif
 
+extern NODE **fmt_list;          /* declared in eval.c */
+
 #define POP_TWO_SCALARS(s1, s2) \
 s2 = POP_SCALAR(); \
 s1 = POP(); \
@@ -40,8 +56,14 @@ fatal(_("attempt to use array `%s' in a scalar context"), 
array_vname(s1)); \
 }} while (FALSE)
 
 mpz_t mpzval;  /* GMP integer type; used as temporary in many places */
+mpfr_t MNR;
+mpfr_t MFNR;
 
 static mpfr_rnd_t mpfr_rnd_mode(const char *mode, size_t mode_len);
+static NODE *get_bit_ops(NODE **p1, NODE **p2, const char *op);
+static NODE *mpfr_force_number(NODE *n);
+static NODE *mpfr_make_number(double);
+static NODE *mpfr_format_val(const char *format, int index, NODE *s);
 
 
 /* init_mpfr --- set up MPFR related variables */
@@ -52,9 +74,14 @@ init_mpfr(const char *rnd_mode)
        mpfr_set_default_prec(PRECISION);
        RND_MODE = mpfr_rnd_mode(rnd_mode, strlen(rnd_mode));
        mpfr_set_default_rounding_mode(RND_MODE);
-       make_number = make_mpfr_number;
-       m_force_number = force_mpfr_number;
+       make_number = mpfr_make_number;
+       m_force_number = mpfr_force_number;
+       format_val = mpfr_format_val;
        mpz_init(mpzval);
+       mpfr_init(MNR);
+       mpfr_set_d(MNR, 0.0, RND_MODE);
+       mpfr_init(MFNR);
+       mpfr_set_d(MFNR, 0.0, RND_MODE);
 }
 
 /* mpfr_node --- allocate a node to store a MPFR number */
@@ -79,8 +106,8 @@ mpfr_node()
 
 /* mpfr_make_number --- make a MPFR number node and initialize with a double */
 
-NODE *
-make_mpfr_number(double x)
+static NODE *
+mpfr_make_number(double x)
 {
        NODE *r;
        r = mpfr_node();
@@ -90,8 +117,8 @@ make_mpfr_number(double x)
 
 /* mpfr_force_number --- force a value to be a MPFR number */
 
-AWKNUM
-force_mpfr_number(NODE *n)
+static NODE *
+mpfr_force_number(NODE *n)
 {
        char *cp, *cpend, *ptr;
        char save;
@@ -99,7 +126,7 @@ force_mpfr_number(NODE *n)
        unsigned int newflags = 0;
 
        if ((n->flags & (MPFN|NUMCUR)) == (MPFN|NUMCUR))
-               return 0;
+               return n;
 
        if (n->flags & MAYBE_NUM) {
                n->flags &= ~MAYBE_NUM;
@@ -110,18 +137,17 @@ force_mpfr_number(NODE *n)
                n->flags |= MPFN;
                mpfr_init(n->mpfr_numbr);
        }
-
-       mpfr_set_d(n->mpfr_numbr, 0.0, RND_MODE);       /* initialize to 0.0 */
+       mpfr_set_d(n->mpfr_numbr, 0.0, RND_MODE);
 
        if (n->stlen == 0)
-               return 0;
+               return n;
 
        cp = n->stptr;
        cpend = n->stptr + n->stlen;
        while (cp < cpend && isspace((unsigned char) *cp))
                cp++;
        if (cp == cpend)        /* only spaces */
-               return 0;
+               return n;
        
        save = *cpend;
        *cpend = '\0';
@@ -141,27 +167,139 @@ force_mpfr_number(NODE *n)
                n->flags |= NUMCUR;
        }
        errno = 0;
-       return 0;
+       return n;
+}
+
+/* mpfr_format_val --- format a numeric value based on format */
+
+static NODE *
+mpfr_format_val(const char *format, int index, NODE *s)
+{
+       NODE *dummy[2], *r;
+       unsigned int oflags;
+
+       /* create dummy node for a sole use of format_tree */
+       dummy[1] = s;
+       oflags = s->flags;
+
+       if (mpfr_integer_p(s->mpfr_numbr)) {
+               /* integral value, use %d */
+               r = format_tree("%d", 2, dummy, 2);
+               s->stfmt = -1;
+       } else {
+               r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
+               assert(r != NULL);
+               s->stfmt = (char) index;
+       }
+       s->flags = oflags;
+       s->stlen = r->stlen;
+       if ((s->flags & STRCUR) != 0)
+               efree(s->stptr);
+       s->stptr = r->stptr;
+       freenode(r);    /* Do not unref(r)! We want to keep s->stptr == 
r->stpr.  */
+ 
+       s->flags |= STRCUR;
+       free_wstr(s);
+       return s;
+}
+
+
+/*
+ * mpfr_update_var --- update NR or FNR. 
+ *     NR_node(mpfr_t)  = MNR(mpfr_t) * LONG_MAX + NR(long) 
+ */
+
+/*
+ * Test:
+ * $ ./gawk -M 'BEGIN{NR=0x7FFFFFFFL; print NR} END{ print NR, NR-0x7FFFFFFFL, 
FNR}' awk.h
+ */
+
+void
+mpfr_update_var(NODE *n)
+{
+       NODE *val = n->var_value;
+       long nl;
+       mpfr_ptr nm;
+
+       if (n == NR_node) {
+               nl = NR;
+               nm = MNR;
+       } else if (n == FNR_node) {
+               nl = FNR;
+               nm = MFNR;
+       } else
+               cant_happen();
+
+       if (mpfr_zero_p(nm)) {
+               double d;
+
+               /* Efficiency hack for NR < LONG_MAX */
+               d = mpfr_get_d(val->mpfr_numbr, RND_MODE);
+               if (d != nl) {
+                       unref(n->var_value);
+                       n->var_value = make_number((AWKNUM) nl);
+               }
+       } else {
+               unref(n->var_value);
+               val = n->var_value = mpfr_node();
+               mpfr_mul_si(val->mpfr_numbr, nm, LONG_MAX, RND_MODE);
+               mpfr_add_si(val->mpfr_numbr, val->mpfr_numbr, nl, RND_MODE);
+       }
+}
+
+
+/* mpfr_set_var --- set NR or FNR */
+
+long
+mpfr_set_var(NODE *n)
+{
+       long l;
+       mpfr_ptr nm;
+       mpfr_ptr p = n->var_value->mpfr_numbr;
+       int neg = FALSE;
+
+       if (n == NR_node)
+               nm = MNR;
+       else if (n == FNR_node)
+               nm = MFNR;
+       else
+               cant_happen();
+
+       mpfr_get_z(mpzval, p, MPFR_RNDZ);
+       if (mpfr_signbit(p)) {
+               neg = TRUE;
+               mpz_neg(mpzval, mpzval);
+       }               
+       l = mpz_fdiv_q_ui(mpzval, mpzval, LONG_MAX);
+       if (neg) {
+               mpz_neg(mpzval, mpzval);
+               l = -l;
+       }
+       
+       mpfr_set_z(nm, mpzval, RND_MODE);       /* quotient (MNR) */
+       return l;       /* remainder (NR) */
 }
 
+
 /* set_PREC --- update MPFR PRECISION related variables when PREC assigned to 
*/
 
 void
 set_PREC()
 {
+       /* TODO: "DOUBLE", "QUAD", "OCT", .. */
+
        if (do_mpfr) {
                long l;
                NODE *val = PREC_node->var_value;
 
-               l = (long) force_number(val);
-               if ((val->flags & MPFN) != 0)
-                       l = mpfr_get_si(val->mpfr_numbr, RND_MODE);             
+               (void) force_number(val);
+               l = get_number_si(val);         
 
                if (l >= MPFR_PREC_MIN && l <= MPFR_PREC_MAX) {
                        mpfr_set_default_prec(l);
                        PRECISION = mpfr_get_default_prec();
                } else
-                       warning(_("Invalid PREC value: %ld"), l);               
        
+                       warning(_("Invalid PREC value: %ld"), l);
        }
 }
 
@@ -210,40 +348,113 @@ set_RNDMODE()
        }
 }
 
+/* get_bit_ops --- get the numeric operands of a binary function */
+
+static NODE *
+get_bit_ops(NODE **p1, NODE **p2, const char *op)
+{
+       NODE *t1, *t2;
+       mpfr_ptr left, right;
+
+       *p2 = t2 = POP_SCALAR();
+       *p1 = t1 = POP_SCALAR();
+
+       if (do_lint) {
+               if ((t1->flags & (NUMCUR|NUMBER)) == 0)
+                       lintwarn(_("%s: received non-numeric first argument"), 
op);
+               if ((t2->flags & (NUMCUR|NUMBER)) == 0)
+                       lintwarn(_("%s: received non-numeric second argument"), 
op);
+       }
+
+       left = force_number(t1)->mpfr_numbr;
+       right = force_number(t2)->mpfr_numbr;
 
-/* do_and_mpfr --- perform an & operation */
+       if (! mpfr_number_p(left)) {
+               /* [+-]inf or NaN */
+               DEREF(t2);
+               return t1;
+       }
+
+       if (! mpfr_number_p(right)) {
+               /* [+-]inf or NaN */
+               DEREF(t1);
+               return t2;
+       }
+
+       if (do_lint) {
+               if (mpfr_signbit(left) || mpfr_signbit(right))
+                       lintwarn("%s",
+               mpfr_fmt(_("%s(%Rg, %Rg): negative values will give strange 
results"),
+                                       op, left, right)
+                               );
+               if (! mpfr_integer_p(left) || ! mpfr_integer_p(right))
+                       lintwarn("%s",
+               mpfr_fmt(_("%s(%Rg, %Rg): fractional values will be truncated"),
+                                       op, left, right)
+                               );
+       }
+       return NULL;
+}
+
+
+/* do_and --- perform an & operation */
 
 NODE *
-do_and_mpfr(int nargs)
+do_mpfr_and(int nargs)
 {
-       NODE *t1, *t2;
+       NODE *t1, *t2, *res;
+       mpz_t z;
+
+       if ((res = get_bit_ops(& t1, & t2, "and")) != NULL)
+               return res;
 
-       POP_TWO_SCALARS(t1, t2);
+       mpz_init(z);
+       mpfr_get_z(mpzval, t1->mpfr_numbr, MPFR_RNDZ);  /* float to integer 
conversion */
+       mpfr_get_z(z, t2->mpfr_numbr, MPFR_RNDZ);       /* Same */      
+       mpz_and(z, mpzval, z);
+
+       res = mpfr_node();
+       mpfr_set_z(res->mpfr_numbr, z, RND_MODE);       /* integer to float 
conversion */
+       mpz_clear(z);
 
        DEREF(t1);
        DEREF(t2);
-       return dupnode(Nnull_string);
+       return res;
 }
 
 /* do_atan2 --- do the atan2 function */
 
 NODE *
-do_atan2_mpfr(int nargs)
+do_mpfr_atan2(int nargs)
 {
-       NODE *t1, *t2;
+       NODE *t1, *t2, *res;
+
+       t2 = POP_SCALAR();
+       t1 = POP_SCALAR();
+
+       if (do_lint) {
+               if ((t1->flags & (NUMCUR|NUMBER)) == 0)
+                       lintwarn(_("atan2: received non-numeric first 
argument"));
+               if ((t2->flags & (NUMCUR|NUMBER)) == 0)
+                       lintwarn(_("atan2: received non-numeric second 
argument"));
+       }
+       force_number(t1);
+       force_number(t2);
 
-       POP_TWO_SCALARS(t1, t2);
+       res = mpfr_node();
+       /* See MPFR documentation for handling of special values like +inf as 
an argument */ 
+       mpfr_atan2(res->mpfr_numbr, t1->mpfr_numbr, t2->mpfr_numbr, RND_MODE);
 
        DEREF(t1);
        DEREF(t2);
-       return dupnode(Nnull_string);
+       return res;
 }
 
 
 /* do_compl --- perform a ~ operation */
 
 NODE *
-do_compl_mpfr(int nargs)
+do_mpfr_compl(int nargs)
 {
        NODE *tmp;
 
@@ -256,7 +467,7 @@ do_compl_mpfr(int nargs)
 /* do_cos --- do the cos function */
 
 NODE *
-do_cos_mpfr(int nargs)
+do_mpfr_cos(int nargs)
 {
        NODE *tmp;
 
@@ -269,7 +480,7 @@ do_cos_mpfr(int nargs)
 /* do_exp --- exponential function */
 
 NODE *
-do_exp_mpfr(int nargs)
+do_mpfr_exp(int nargs)
 {
        NODE *tmp;
 
@@ -282,7 +493,7 @@ do_exp_mpfr(int nargs)
 /* do_int --- convert double to int for awk */
 
 NODE *
-do_int_mpfr(int nargs)
+do_mpfr_int(int nargs)
 {
        NODE *tmp;
 
@@ -295,7 +506,7 @@ do_int_mpfr(int nargs)
 /* do_log --- the log function */
 
 NODE *
-do_log_mpfr(int nargs)
+do_mpfr_log(int nargs)
 {
        NODE *tmp;
 
@@ -307,7 +518,6 @@ do_log_mpfr(int nargs)
 
 
 /* do_lshift --- perform a << operation */
-
 /*
  * Test:
  * $ ./gawk 'BEGIN { print lshift(1, 52) }'
@@ -319,70 +529,20 @@ do_log_mpfr(int nargs)
  */
 
 NODE *
-do_lshift_mpfr(int nargs)
+do_mpfr_lshift(int nargs)
 {
        NODE *t1, *t2, *res;
-       mpfr_ptr left, right;
        mp_bitcnt_t shift;
 
-       POP_TWO_SCALARS(t1, t2);
-       if (do_lint) {
-               if ((t1->flags & (NUMCUR|NUMBER)) == 0)
-                       lintwarn(_("lshift: received non-numeric first 
argument"));
-               if ((t2->flags & (NUMCUR|NUMBER)) == 0)
-                       lintwarn(_("lshift: received non-numeric second 
argument"));
-       }
-
-       (void) force_number(t1);
-       (void) force_number(t2);
-
-       assert((t1->flags & MPFN) != 0);
-       assert((t2->flags & MPFN) != 0);
-
-       left = t1->mpfr_numbr;
-       right = t2->mpfr_numbr;         /* shift */
+       if ((res = get_bit_ops(& t1, & t2, "lshift")) != NULL)
+               return res;
 
-       if (! mpfr_number_p(left)) {
-               /* [+-]inf or NaN */
-               res = dupnode(t1);
-               goto finish;
-       }
-
-       if (! mpfr_number_p(right)) {
-               /* [+-]inf or NaN */
-               res = dupnode(t2);
-               goto finish;
-       }
-
-       if (do_lint) {
-               char *tmp = NULL;
-               if (mpfr_signbit(left) || mpfr_signbit(right)) {
-                       (void) mpfr_asprintf(& tmp,
-                               _("lshift(%Rg, %Rg): negative values will give 
strange results"), left, right);
-                       if (tmp != NULL) {
-                               lintwarn("%s", tmp);
-                               mpfr_free_str(tmp);
-                               tmp = NULL;
-                       }
-               }
-               if (! mpfr_integer_p(left) || ! mpfr_integer_p(right)) {
-                       (void) mpfr_asprintf(& tmp,
-                               _("lshift(%Rg, %Rg): fractional values will be 
truncated"), left, right);
-                       if (tmp != NULL) {
-                               lintwarn("%s", tmp);
-                               mpfr_free_str(tmp);
-                       }
-               }
-       }
-
-       (void) mpfr_get_z(mpzval, left, MPFR_RNDZ);     /* mpfr_t (float) => 
mpz_t (integer) conversion */
-       shift = mpfr_get_ui(right, MPFR_RNDZ);          /* mpfr_t (float) => 
unsigned long conversion */
+       mpfr_get_z(mpzval, t1->mpfr_numbr, MPFR_RNDZ);  /* mpfr_t (float) => 
mpz_t (integer) conversion */
+       shift = mpfr_get_ui(t2->mpfr_numbr, MPFR_RNDZ);         /* mpfr_t 
(float) => unsigned long conversion */
        mpz_mul_2exp(mpzval, mpzval, shift);            /* mpzval = mpzval * 
2^shift */
 
        res = mpfr_node();
-       (void) mpfr_set_z(res->mpfr_numbr, mpzval, RND_MODE);   /* mpz_t => 
mpfr_t conversion */
-
-finish:
+       mpfr_set_z(res->mpfr_numbr, mpzval, RND_MODE);  /* integer to float 
conversion */
        DEREF(t1);
        DEREF(t2);
        return res;
@@ -392,7 +552,7 @@ finish:
 /* do_or --- perform an | operation */
 
 NODE *
-do_or_mpfr(int nargs)
+do_mpfr_or(int nargs)
 {
        NODE *s1, *s2;
 
@@ -406,7 +566,7 @@ do_or_mpfr(int nargs)
 /* do_rand --- do the rand function */
 
 NODE *
-do_rand_mpfr(int nargs ATTRIBUTE_UNUSED)
+do_mpfr_rand(int nargs ATTRIBUTE_UNUSED)
 {
        return dupnode(Nnull_string);
 }
@@ -439,71 +599,21 @@ do_rand_mpfr(int nargs ATTRIBUTE_UNUSED)
  */
 
 NODE *
-do_rhift_mpfr(int nargs)
+do_mpfr_rhift(int nargs)
 {
        NODE *t1, *t2, *res;
-       mpfr_ptr left, right;
        mp_bitcnt_t shift;
 
-       POP_TWO_SCALARS(t1, t2);
-       if (do_lint) {
-               if ((t1->flags & (NUMCUR|NUMBER)) == 0)
-                       lintwarn(_("rshift: received non-numeric first 
argument"));
-               if ((t2->flags & (NUMCUR|NUMBER)) == 0)
-                       lintwarn(_("rshift: received non-numeric second 
argument"));
-       }
-
-       (void) force_number(t1);
-       (void) force_number(t2);
-
-       assert((t1->flags & MPFN) != 0);
-       assert((t2->flags & MPFN) != 0);
-
-       left = t1->mpfr_numbr;
-       right = t2->mpfr_numbr;         /* shift */
-
-       if (! mpfr_number_p(left)) {
-               /* [+-]inf or NaN */
-               res = dupnode(t1);
-               goto finish;
-       }
-
-       if (! mpfr_number_p(right)) {
-               /* [+-]inf or NaN */
-               res = dupnode(t2);
-               goto finish;
-       }
-
-       if (do_lint) {
-               char *tmp = NULL;
-               if (mpfr_signbit(left) || mpfr_signbit(right)) {
-                       (void) mpfr_asprintf(& tmp,
-                               _("rshift(%Rg, %Rg): negative values will give 
strange results"), left, right);
-                       if (tmp != NULL) {
-                               lintwarn("%s", tmp);
-                               mpfr_free_str(tmp);
-                               tmp = NULL;
-                       }
-               }
-
-               if (! mpfr_integer_p(left) || ! mpfr_integer_p(right)) {
-                       (void) mpfr_asprintf(& tmp,
-                               _("rshift(%Rg, %Rg): fractional values will be 
truncated"), left, right);
-                       if (tmp != NULL) {
-                               lintwarn("%s", tmp);
-                               mpfr_free_str(tmp);
-                       }
-               }
-       }
+       if ((res = get_bit_ops(& t1, & t2, "rshift")) != NULL)
+               return res;
 
-       (void) mpfr_get_z(mpzval, left, MPFR_RNDZ);     /* mpfr_t (float) => 
mpz_t (integer) conversion */
-       shift = mpfr_get_ui(right, MPFR_RNDZ);          /* mpfr_t (float) => 
unsigned long conversion */
+       mpfr_get_z(mpzval, t1->mpfr_numbr, MPFR_RNDZ);  /* mpfr_t (float) => 
mpz_t (integer) conversion */
+       shift = mpfr_get_ui(t2->mpfr_numbr, MPFR_RNDZ);         /* mpfr_t 
(float) => unsigned long conversion */
        mpz_fdiv_q_2exp(mpzval, mpzval, shift);         /* mpzval = mpzval / 
2^shift, round towards −inf */
 
        res = mpfr_node();
-       (void) mpfr_set_z(res->mpfr_numbr, mpzval, RND_MODE);   /* mpz_t => 
mpfr_t conversion */
+       mpfr_set_z(res->mpfr_numbr, mpzval, RND_MODE);  /* integer to float 
conversion */
 
-finish:
        DEREF(t1);
        DEREF(t2);
        return res;
@@ -513,7 +623,7 @@ finish:
 /* do_sin --- do the sin function */
 
 NODE *
-do_sin_mpfr(int nargs)
+do_mpfr_sin(int nargs)
 {
        NODE *tmp;
 
@@ -526,7 +636,7 @@ do_sin_mpfr(int nargs)
 /* do_sqrt --- do the sqrt function */
 
 NODE *
-do_sqrt_mpfr(int nargs)
+do_mpfr_sqrt(int nargs)
 {
        NODE *tmp;
 
@@ -539,7 +649,7 @@ do_sqrt_mpfr(int nargs)
 /* do_srand --- seed the random number generator */
 
 NODE *
-do_srand_mpfr(int nargs)
+do_mpfr_srand(int nargs)
 {
        NODE *tmp;
 
@@ -556,7 +666,7 @@ do_srand_mpfr(int nargs)
 /* do_strtonum --- the strtonum function */
 
 NODE *
-do_strtonum_mpfr(int nargs)
+do_mpfr_strtonum(int nargs)
 {
        NODE *tmp;
 
@@ -570,7 +680,7 @@ do_strtonum_mpfr(int nargs)
 /* do_xor --- perform an ^ operation */
 
 NODE *
-do_xor_mpfr(int nargs)
+do_mpfr_xor(int nargs)
 {
        NODE *s1, *s2;
 
@@ -581,5 +691,73 @@ do_xor_mpfr(int nargs)
        return dupnode(Nnull_string);
 }
 
-#endif
 
+/* op_mpfr_assign --- assignment operators excluding = */
+ 
+void
+op_mpfr_assign(OPCODE op)
+{
+       NODE **lhs;
+       NODE *t1, *t2, *r;
+       mpfr_ptr p1, p2;
+
+       lhs = POP_ADDRESS();
+       t1 = *lhs;
+       p1 = force_number(t1)->mpfr_numbr;
+
+       t2 = TOP_SCALAR();
+       p2 = force_number(t2)->mpfr_numbr;
+
+       r = mpfr_node();
+       switch (op) {
+       case Op_assign_plus:
+               mpfr_add(r->mpfr_numbr, p1, p2, RND_MODE);
+               break;
+       case Op_assign_minus:
+               mpfr_sub(r->mpfr_numbr, p1, p2, RND_MODE);
+               break;
+       case Op_assign_times:
+               mpfr_mul(r->mpfr_numbr, p1, p2, RND_MODE);
+               break;
+       case Op_assign_quotient:
+               mpfr_div(r->mpfr_numbr, p1, p2, RND_MODE);
+               break;
+       case Op_assign_mod:
+               mpfr_fmod(r->mpfr_numbr, p1, p2, RND_MODE);
+               break;
+       case Op_assign_exp:
+               mpfr_pow(r->mpfr_numbr, p1, p2, RND_MODE);
+               break;
+       default:
+               break;
+       }
+
+       DEREF(t2);
+       unref(*lhs);
+       *lhs = r;
+
+       UPREF(r);
+       REPLACE(r);
+}
+
+
+/* mpfr_fmt --- output formatted string with special MPFR/GMP conversion 
specifiers */
+
+const char *
+mpfr_fmt(const char *mesg, ...)
+{
+       static char *tmp = NULL;
+       int ret;
+       va_list args;
+
+       if (tmp != NULL)
+               mpfr_free_str(tmp);
+       va_start(args, mesg);
+       ret = mpfr_vasprintf(& tmp, mesg, args);
+       va_end(args);
+       if (ret >= 0 && tmp != NULL)
+               return tmp;
+       return mesg;
+}
+
+#endif
diff --git a/msg.c b/msg.c
index 10f3837..6f66295 100644
--- a/msg.c
+++ b/msg.c
@@ -62,6 +62,20 @@ err(const char *s, const char *emsg, va_list argp)
 
                (void) fprintf(stderr, "%d: ", sourceline);
        }
+
+#ifdef HAVE_MPFR
+       if (FNR_node && (FNR_node->var_value->flags & MPFN) != 0) {
+               mpfr_update_var(FNR_node);
+               mpfr_get_z(mpzval, FNR_node->var_value->mpfr_numbr, MPFR_RNDZ);
+               if (mpz_sgn(mpzval) > 0) {
+                       file = FILENAME_node->var_value->stptr;
+                       (void) putc('(', stderr);
+                       if (file)
+                               (void) fprintf(stderr, "FILENAME=%s ", file);
+                       (void) mpfr_fprintf(stderr, "FNR=%Zd) ", mpzval);
+               }
+       } else
+#endif
        if (FNR > 0) {
                file = FILENAME_node->var_value->stptr;
                (void) putc('(', stderr);
@@ -69,6 +83,7 @@ err(const char *s, const char *emsg, va_list argp)
                        (void) fprintf(stderr, "FILENAME=%s ", file);
                (void) fprintf(stderr, "FNR=%ld) ", FNR);
        }
+
        (void) fprintf(stderr, "%s", s);
        vfprintf(stderr, emsg, argp);
        (void) fprintf(stderr, "\n");
diff --git a/node.c b/node.c
index e917da0..2166f6e 100644
--- a/node.c
+++ b/node.c
@@ -32,11 +32,12 @@ static AWKNUM get_ieee_magic_val(const char *val);
 extern NODE **fmt_list;          /* declared in eval.c */
 
 NODE *(*make_number)(AWKNUM ) = r_make_number;
-AWKNUM (*m_force_number)(NODE *) = r_force_number;
+NODE *(*m_force_number)(NODE *) = r_force_number;
+NODE *(*format_val)(const char *, int, NODE *) = r_format_val;
 
 /* force_number --- force a value to be numeric */
 
-AWKNUM
+NODE *
 r_force_number(NODE *n)
 {
        char *cp;
@@ -47,7 +48,7 @@ r_force_number(NODE *n)
        extern double strtod();
 
        if (n->flags & NUMCUR)
-               return n->numbr;
+               return n;
 
        /* all the conditionals are an attempt to avoid the expensive strtod */
 
@@ -56,7 +57,7 @@ r_force_number(NODE *n)
        n->numbr = 0.0;
 
        if (n->stlen == 0) {
-               return 0.0;
+               return n;
        }
 
        cp = n->stptr;
@@ -69,14 +70,14 @@ r_force_number(NODE *n)
         */
        if (! do_posix) {
                if (isalpha((unsigned char) *cp)) {
-                       return 0.0;
+                       return n;
                } else if (n->stlen == 4 && is_ieee_magic_val(n->stptr)) {
                        if (n->flags & MAYBE_NUM)
                                n->flags &= ~MAYBE_NUM;
                        n->flags |= NUMBER|NUMCUR;
                        n->numbr = get_ieee_magic_val(n->stptr);
 
-                       return n->numbr;
+                       return n;
                }
                /* else
                        fall through */
@@ -94,7 +95,7 @@ r_force_number(NODE *n)
                                        /* CANNOT do non-decimal and saw 0x */
                    || (! do_non_decimal_data && cp[0] == '0'
                        && (cp[1] == 'x' || cp[1] == 'X'))))) {
-               return 0.0;
+               return n;
        }
 
        if (n->flags & MAYBE_NUM) {
@@ -111,7 +112,7 @@ r_force_number(NODE *n)
                        if (cp == n->stptr)             /* no leading spaces */
                                n->flags |= NUMINT;
                }
-               return n->numbr;
+               return n;
        }
 
        if (do_non_decimal_data) {      /* main.c assures false if do_posix */
@@ -141,7 +142,7 @@ finish:
                errno = 0;
        }
 
-       return n->numbr;
+       return n;
 }
 
 
@@ -164,10 +165,10 @@ static const char *values[] = {
 };
 #define        NVAL    (sizeof(values)/sizeof(values[0]))
 
-/* format_val --- format a numeric value based on format */
+/* r_format_val --- format a numeric value based on format */
 
 NODE *
-format_val(const char *format, int index, NODE *s)
+r_format_val(const char *format, int index, NODE *s)
 {
        char buf[BUFSIZ];
        char *sp = buf;
@@ -191,11 +192,7 @@ format_val(const char *format, int index, NODE *s)
         */
 
        /* not an integral value, or out of range */
-       if (
-#ifdef HAVE_MPFR
-               (s->flags & MPFN) != 0 || 
-#endif
-               (val = double_to_int(s->numbr)) != s->numbr
+       if ((val = double_to_int(s->numbr)) != s->numbr
                        || val <= LONG_MIN || val >= LONG_MAX
        ) {
                /*
@@ -214,12 +211,7 @@ format_val(const char *format, int index, NODE *s)
                dummy[1] = s;
                oflags = s->flags;
 
-               if (
-#ifdef HAVE_MPFR
-                       ((s->flags & MPFN) != 0 && 
mpfr_integer_p(s->mpfr_numbr)) ||
-#endif
-                       ((s->flags & MPFN) == 0 && val == s->numbr)
-               ) {
+               if (val == s->numbr) {
                        /* integral value, but outside range of %ld, use %.0f */
                        r = format_tree("%.0f", 4, dummy, 2);
                        s->stfmt = -1;
@@ -633,7 +625,7 @@ get_numbase(const char *s, int use_locale)
        }
 
        if (! isdigit((unsigned char) s[1])
-               || s[1] == '8' || s[1] == '9'
+                       || s[1] == '8' || s[1] == '9'
        )
                return 10;
        return 8;
diff --git a/str_array.c b/str_array.c
index 7ce617e..4bd993e 100644
--- a/str_array.c
+++ b/str_array.c
@@ -158,7 +158,7 @@ str_lookup(NODE *symbol, NODE *subs)
                * never be used.
                */
 
-               if (subs->flags & NUMCUR) {
+               if ((subs->flags & (MPFN|NUMCUR)) == NUMCUR) {
                        tmp->numbr = subs->numbr;
                        tmp->flags |= NUMCUR;
                }
@@ -187,7 +187,6 @@ str_lookup(NODE *symbol, NODE *subs)
 static NODE **
 str_exists(NODE *symbol, NODE *subs)
 {
-       NODE **lhs;
        unsigned long hash1;
        size_t code1;
 
@@ -196,8 +195,7 @@ str_exists(NODE *symbol, NODE *subs)
 
        subs = force_string(subs);
        hash1 = hash(subs->stptr, subs->stlen, (unsigned long) 
symbol->array_size, & code1);
-       lhs = str_find(symbol, subs, code1, hash1);
-       return lhs;
+       return str_find(symbol, subs, code1, hash1);
 }
 
 /* str_clear --- flush all the values in symbol[] */
diff --git a/test/Makefile.am b/test/Makefile.am
index 943dbd9..2bbc553 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -873,6 +873,10 @@ PGAWKPROG = ../pgawk$(EXEEXT)
 AWK = LC_ALL=$${GAWKLOCALE:-C} LANG=$${GAWKLOCALE:-C} $(AWKPROG)
 PGAWK = LC_ALL=$${GAWKLOCALE:-C} LANG=$${GAWKLOCALE:-C} $(PGAWKPROG)
 
+check-mpfr: AWK+=-M
+
+check-mpfr: check
+
 # Message stuff is to make it a little easier to follow.
 # Make the pass-fail last and dependent on others to avoid
 # spurious errors if `make -j' in effect.
diff --git a/test/Makefile.in b/test/Makefile.in
index a389929..f56ee6c 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1225,6 +1225,10 @@ uninstall-am:
        mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
 
 
+check-mpfr: AWK+=-M
+
+check-mpfr: check
+
 # Message stuff is to make it a little easier to follow.
 # Make the pass-fail last and dependent on others to avoid
 # spurious errors if `make -j' in effect.

-----------------------------------------------------------------------

Summary of changes:
 array.c          |   21 ++-
 awk.h            |   73 +++++----
 awkgram.c        |  308 ++++++++++++++++++-----------------
 awkgram.y        |   44 +++---
 builtin.c        |  125 +++++++++-----
 eval.c           |   65 ++++++--
 int_array.c      |    2 +-
 interpret.h      |  273 ++++++++++++++++++++-----------
 io.c             |   35 +++-
 main.c           |    6 +-
 mpfr.c           |  482 +++++++++++++++++++++++++++++++++++++-----------------
 msg.c            |   15 ++
 node.c           |   38 ++---
 str_array.c      |    6 +-
 test/Makefile.am |    4 +
 test/Makefile.in |    4 +
 16 files changed, 944 insertions(+), 557 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]