gawk-diffs
[Top][All Lists]
Advanced

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

[gawk-diffs] [SCM] gawk branch, num-handler, updated. b97f64ab95ef7407de


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, num-handler, updated. b97f64ab95ef7407de4ce4f14b3477b8d62e5430
Date: Fri, 11 Jan 2013 12:44:05 +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, num-handler has been updated
       via  b97f64ab95ef7407de4ce4f14b3477b8d62e5430 (commit)
      from  d898d83434007253f314c8f3fabcb2686820026a (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=b97f64ab95ef7407de4ce4f14b3477b8d62e5430

commit b97f64ab95ef7407de4ce4f14b3477b8d62e5430
Author: John Haque <address@hidden>
Date:   Fri Jan 11 06:12:15 2013 -0600

    More printf formatting changes.

diff --git a/ChangeLog b/ChangeLog
index 389c61f..8125721 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-01-11         John Haque      <address@hidden>
+
+       Finish format_tree() refactoring.
+
+       * awk.h (struct fmt_list_item): New definition.
+       * builtin.c (fmt_parse): New routine to parse a single format code.
+       (format_tree): Adjusted.
+       * eval.c (fmt_index): (Pre-)compile and store format codes.
+       * double.c (format_awknum_val): Reworked to use compiled
+       format codes.
+       * mpfr.c (mpfp_format_val): Ditto.
+
 2013-01-03         John Haque      <address@hidden>
 
        Refactor format_tree() to seperate number formatting code.
diff --git a/TODO.NUMH b/TODO.NUMH
index 838b0f9..d95ed55 100644
--- a/TODO.NUMH
+++ b/TODO.NUMH
@@ -2,7 +2,7 @@
 
   [1] Remove direct calls to format_tree() in number to string (force_string)
 routines. Fix CONVFMT = "%s"/"%c" crash; present in all known gawk versions.
-Cache parsed format code in fmt_idx() ... 
+Cache parsed format code in fmt_idx() ...      DONE
 
   [2] Try to format NaN/inf in main gawk code, and not in the individual 
handlers.
 
@@ -14,3 +14,27 @@ May require additional tests e.g. SIZE_MAX <= UINT_MAX. In a 
nutshell, don't do
                        number => double => integer
 
 * Restore constant-folding code for numbers.
+
+* Consider special handling of integer-indexed arrays with non-double
+number handlers.
+       - Choose a reasonable range for integer indices.
+               #if SIZEOF_LONG <= 8
+               typedef gawk_int_t      long
+               #define GAWK_INT_MAX    LONG_MAX
+               #define GAWK_INT_MIN    LONG_MIN
+               #define GAWK_INT_BIT    SIZEOF_LONG * 8  ### may not need this
+               #else
+               typedef gawk_int_t      int
+               #define GAWK_INT_MAX    INT_MAX
+               #define GAWK_INT_MIN    INT_MIN
+               #define GAWK_INT_BIT    SIZEOF_INT * 8
+               #endif
+       Install gaurd code in array handlers (or adjust the defs) for size
+       anything but 4 or 8 (overthinking?). Use gawk_int_t instead
+       of int32_t or int64_t.
+
+       - Use additional struct field number_fits_gawk_int()
+       (MPFR has similarly named routines, e.g. mpfr_fits_slong()),
+       and avoid checking after conversion. Note that the type is
+       gawk_int_t and NOT necessarily long.
+
diff --git a/array.c b/array.c
index c5090d9..99dfa45 100644
--- a/array.c
+++ b/array.c
@@ -26,7 +26,6 @@
 #include "awk.h"
 
 extern FILE *output_fp;
-extern NODE **fmt_list;          /* declared in eval.c */
 
 static size_t SUBSEPlen;
 static char *SUBSEP;
@@ -72,7 +71,6 @@ register_array_func(afunc_t *afunc)
        return false;
 }
 
-
 /* array_init --- register all builtin array types */
 
 void
@@ -677,7 +675,7 @@ value_info(NODE *n)
                fprintf(output_fp, "][");
                fprintf(output_fp, "stfmt=%d, ", n->stfmt);     
                fprintf(output_fp, "CONVFMT=\"%s\"", n->stfmt <= -1 ? "%ld"
-                                       : fmt_list[n->stfmt]->stptr);
+                                       : fmt_list[n->stfmt].fmt->stptr);
        }
 }
 
diff --git a/awk.h b/awk.h
index e459a95..85b0ff7 100644
--- a/awk.h
+++ b/awk.h
@@ -732,7 +732,6 @@ typedef struct exp_instruction {
 #define GENSUB          0x02   /* builtin is gensub */
 #define LITERAL         0x04   /* target is a literal string */
 
-
 /* Op_K_exit */
 #define target_end      d.di
 #define target_atexit   x.xi   
@@ -896,7 +895,8 @@ typedef struct {
        NODE *(*gawk_fmt_number)(const char *, int, NODE *);   /* stringify a 
numeric value
                                                                  based on awk 
input/output format */
 
-       int (*gawk_format_printf)(NODE *, struct format_spec *, struct 
print_fmt_buf *); /* (s)printf format */
+       /* (s)printf formatting of numbers */
+       int (*gawk_format_printf)(NODE *, struct format_spec *, struct 
print_fmt_buf *);
 
        /* conversion to C types */
        double (*gawk_todouble)(const NODE *);         /* number to double */
@@ -924,6 +924,11 @@ typedef struct {
 } numbr_handler_t;
 
 
+struct fmt_list_item {
+       NODE *fmt;                   /* format string */ 
+       struct format_spec *spec;    /* parsed format code */
+};
+
 typedef struct iobuf {
        awk_input_buf_t public; /* exposed to extensions */
        char *buf;              /* start data buffer */
@@ -1111,6 +1116,7 @@ extern uintmax_t (*get_number_uj)(const NODE *);
 extern int (*sgn_number)(const NODE *);
 extern int (*format_number_printf)(NODE *, struct format_spec *, struct 
print_fmt_buf *);
 
+extern struct fmt_list_item *fmt_list;
 
 /* built-in array types */
 extern afunc_t str_array_func[];
diff --git a/awklib/eg/lib/repl_math.awk b/awklib/eg/lib/repl_math.awk
index a57be27..1788533 100644
--- a/awklib/eg/lib/repl_math.awk
+++ b/awklib/eg/lib/repl_math.awk
@@ -74,10 +74,10 @@ function setup_repl_math( \
 #
 # atan2(y, x) =        atan(y/x),              x > 0
 #             =        atan(y/x) + pi,         x < 0, y >= 0
-#             = atan(y/x) - pi,                x < 0, y < 0
-#             = pi/2,                  x = 0, y > 0
-#             = -pi/2,                 x = 0, y < 0
-#             = ?                      x = 0, y = 0
+#             =        atan(y/x) - pi,         x < 0, y < 0
+#             =        pi/2,                   x = 0, y > 0
+#             =        -pi/2,                  x = 0, y < 0
+#             =        ?                       x = 0, y = 0
 #
 
 function euler_atan2(y, x,     \
@@ -114,7 +114,7 @@ function euler_atan2(y, x,  \
        }
 
        if (x == plus_inf)
-               return atan2(y, x)      # use builtin, -0 or -0
+               return atan2(y, x)      # use builtin, returns +0 or -0
        if (x == minus_inf) {
                if (y >= 0)
                        return 4 * __PI_OVER_4__
@@ -133,7 +133,9 @@ function euler_atan2(y, x,  \
                if (y > x)
                        return sign * (2 * __PI_OVER_4__ - 
euler_atan_one_over(y / x))
                return sign * euler_atan_one_over(x / y)
-       } else if (x < 0) {
+       }
+
+       if (x < 0) {
                if (y == 0) {
                        if (atan2(y, x) < 0)    # use builtin to detect sign
                                return - 4 * __PI_OVER_4__
@@ -154,8 +156,11 @@ function euler_atan2(y, x, \
                return - euler_atan_one_over(x / y) + 4 * __PI_OVER_4__
        }
 
-       # x == +0/-0 and y == +0/-0
-       return atan2(y, x);     # use builtin
+       if (atan2(y, x) < 0)    # atan2(-0, -0)
+               return - 4.0 * __PI_OVER_4__
+       if (atan2(y, x) > 0)    # atan2(+0, -0)
+               return 4.0 * __PI_OVER_4__
+       return 0;       # atan2(+0, +0) or atan2(-0, 0)
 }
 
 
@@ -225,7 +230,7 @@ function repl_sin(x,        \
                return "nan" + 0
 
        if (x < 0) {
-               # sin(x) = - sin(x)
+               # sin(-x) = - sin(x)
                sign = -1
                x = -x
        } else
diff --git a/builtin.c b/builtin.c
index 720a12c..8559c39 100644
--- a/builtin.c
+++ b/builtin.c
@@ -23,7 +23,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
  */
 
-
 #include "awk.h"
 #if defined(HAVE_FCNTL_H)
 #include <fcntl.h>
@@ -2135,10 +2134,22 @@ get_fmt_buf()
        return outb;
 }
 
+/* fmt_parse --- parse a single format code */  
 
-#      define CP               cpbuf_start(outb)
-#      define CEND             cpbuf_end(outb)
-#      define CPBUF            cpbuf(outb)
+struct format_spec *
+fmt_parse(NODE *n, const char *fmt_string, size_t fmt_len)
+{
+       struct format_spec *spec = NULL;
+
+       spec = (struct format_spec *) format_tree(fmt_string, fmt_len, NULL, 
LONG_MIN);
+       if (spec != NULL && n == CONVFMT_node
+               && (spec->fmtchar == 's' || spec->fmtchar == 'c')
+       ) {
+               efree(spec);
+               spec = NULL;
+       }
+       return spec;
+}
 
 
 /* format_nondecimal --- output a nondecimal number according to a format */
@@ -2150,6 +2161,9 @@ format_nondecimal(uintmax_t val, struct format_spec 
*spec, struct print_fmt_buf
        int ii, jj;
        const char *chbuf = spec->chbuf;
 
+#      define CP               cpbuf_start(outb)
+#      define CEND             cpbuf_end(outb)
+
        /*
         * When to fill with zeroes is of course not simple.
         * First: No zero fill if left-justifying.
@@ -2208,6 +2222,9 @@ format_nondecimal(uintmax_t val, struct format_spec 
*spec, struct print_fmt_buf
                spec->fw = spec->prec;
        spec->prec = CEND - CP;
        pr_num_tail(CP, spec->prec, spec, outb);
+
+#undef CP
+#undef CEND
 }
 
 
@@ -2230,7 +2247,7 @@ format_tree(
        long num_args)
 {
        size_t cur_arg = 0;
-       NODE *r = NULL;
+       NODE *retval = NULL;
        bool toofew = false;
        const char *s0, *s1;
        int cs1;
@@ -2247,6 +2264,12 @@ format_tree(
        struct print_fmt_buf *outb;
        struct format_spec spec;
 
+#      define CP               cpbuf_start(outb)
+#      define CEND             cpbuf_end(outb)
+#      define CPBUF            cpbuf(outb)
+
+/* parse a single format specifier */
+#define do_parse_fmt   (num_args == LONG_MIN)
 
        /*
         * Check first for use of `count$'.
@@ -2257,7 +2280,9 @@ format_tree(
         * Otherwise, return the current argument.
         */
 #define parse_next_arg() { \
-       if (argnum > 0) { \
+       if (do_parse_fmt) \
+               goto out; \
+       else if (argnum > 0) { \
                if (cur_arg > 1) { \
                        msg(_("fatal: must use `count$' on all formats or 
none")); \
                        goto out; \
@@ -2384,6 +2409,8 @@ check_pos:
                                msg(_("fatal: `$' is not permitted in awk 
formats"));
                                goto out;
                        }
+                       if (do_parse_fmt)
+                               goto out;
 
                        if (cur == & spec.fw) {
                                argnum = spec.fw;
@@ -2532,6 +2559,7 @@ check_pos:
                        goto retry;
                case 'c':
                        need_format = false;
+                       spec.fmtchar = cs1;
                        parse_next_arg();
                        /* user input that looks numeric is numeric */
                        if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM)
@@ -2605,6 +2633,7 @@ out2:
                        goto pr_tail;
                case 's':
                        need_format = false;
+                       spec.fmtchar = cs1;
                        parse_next_arg();
                        arg = force_string(arg);
                        if (spec.fw == 0 && ! spec.have_prec)
@@ -2658,6 +2687,7 @@ out2:
                case 'i':
        fmt1:
                        need_format = false;
+                       spec.fmtchar = cs1;
                        parse_next_arg();
                        (void) force_number(arg);
                        spec.fmtchar = cs1;
@@ -2668,8 +2698,12 @@ out2:
                        break;
 
                default:
-                       if (do_lint && isalpha(cs1))
+                       if (isalpha(cs1)) {
+                               if (do_lint)
        lintwarn(_("ignoring unknown format specifier character `%c': no 
argument converted"), cs1);
+                               if (do_parse_fmt)
+                                       goto out;
+                       }
                        break;
                }
                if (toofew) {
@@ -2689,12 +2723,28 @@ out2:
        }
 
        bchunk(outb, s0, s1 - s0);
-       r = buf2node(outb);
+       retval = bytes2node(outb, NULL);
 out:
        free_fmt_buf(outb);
 
-       if (r == NULL)
-               gawk_exit(EXIT_FATAL);
-       return r;
+       if (do_parse_fmt) {
+               struct format_spec *cp_spec;
+
+               assert(retval == NULL);
+               if (spec.fmtchar == (char) 0)
+                       return NULL;
+               emalloc(cp_spec, struct format_spec *, sizeof (*cp_spec), 
"format_tree");
+               *cp_spec = spec;
+               return (NODE *) cp_spec;
+       }
+
+       if (retval == NULL)
+               gawk_exit(EXIT_FATAL);  /* debugger needs this */
+
+       return retval;
+
+#undef CP
+#undef CEND
+#undef CPBUF
 }
 
diff --git a/double.c b/double.c
index b5b7458..d127e3a 100644
--- a/double.c
+++ b/double.c
@@ -42,8 +42,6 @@ extern void srandom(unsigned long seed);
  */
 #define GAWK_RANDOM_MAX 0x7fffffffL
 
-extern NODE **fmt_list;          /* declared in eval.c */
-
 /* exported routines */
 
 static NODE *make_awknum(AWKNUM);
@@ -1005,10 +1003,18 @@ format_awknum_val(const char *format, int index, NODE 
*s)
         * < and > so that things work correctly on systems with 64 bit 
integers.
         */
 
+       if ((s->flags & STRCUR) != 0)
+               efree(s->stptr);
+       free_wstr(s);
+
+
        /* not an integral value, or out of range */
        if ((val = double_to_int(s->numbr)) != s->numbr
                        || val <= LONG_MIN || val >= LONG_MAX
        ) {
+               struct format_spec spec;
+               struct print_fmt_buf *outb;
+
                /*
                 * Once upon a time, we just blindly did this:
                 *      sprintf(sp, format, s->numbr);
@@ -1018,30 +1024,24 @@ format_awknum_val(const char *format, int index, NODE 
*s)
                 * and just always format the value ourselves.
                 */
 
-               NODE *dummy[2], *r;
-               unsigned int oflags;
-
-               /* create dummy node for a sole use of format_tree */
-               dummy[1] = s;
-               oflags = s->flags;
+               /* XXX: format_spec copied since can be altered in the 
formatting routine */
 
                if (val == s->numbr) {
                        /* integral value, but outside range of %ld, use %.0f */
-                       r = format_tree("%.0f", 4, dummy, 2);
+                       spec = *fmt_list[INT_0f_FMT_INDEX].spec;
                        s->stfmt = -1;
                } else {
-                       r = format_tree(format, fmt_list[index]->stlen, dummy, 
2);
-                       assert(r != NULL);
-                       s->stfmt = (char) index;
+                       assert(fmt_list[index].spec != NULL);   /* or can use 
fmt_parse() --- XXX */
+                       spec = *fmt_list[index].spec;
+                       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.  */
-
-               goto no_malloc;
+
+               outb = get_fmt_buf();
+               (void) format_awknum_printf(s, & spec, outb);
+               (void) bytes2node(outb, s);
+               free_fmt_buf(outb);
+
+               s->stptr[s->stlen] = '\0';
        } else {
                /*
                 * integral value; force conversion to long only once.
@@ -1060,14 +1060,12 @@ format_awknum_val(const char *format, int index, NODE 
*s)
                        s->flags &= ~(INTIND|NUMBER);
                        s->flags |= STRING;
                }
+
+               emalloc(s->stptr, char *, s->stlen + 2, "format_awknum_val");
+               memcpy(s->stptr, sp, s->stlen + 1);
        }
-       if (s->stptr != NULL)
-               efree(s->stptr);
-       emalloc(s->stptr, char *, s->stlen + 2, "format_awknum_val");
-       memcpy(s->stptr, sp, s->stlen + 1);
-no_malloc:
+       
        s->flags |= STRCUR;
-       free_wstr(s);
        return s;
 }
 
@@ -1507,4 +1505,7 @@ fmt1:
        }
 
        return -1;
+#undef CP
+#undef CEND
+#undef CPBUF
 }
diff --git a/eval.c b/eval.c
index b2cd797..537f26c 100644
--- a/eval.c
+++ b/eval.c
@@ -817,7 +817,7 @@ set_ORS()
 
 /* fmt_ok --- is the conversion format a valid one? */
 
-NODE **fmt_list = NULL;
+struct fmt_list_item *fmt_list = NULL;
 static int fmt_index(NODE *n);
 
 bool
@@ -859,18 +859,53 @@ static int
 fmt_index(NODE *n)
 {
        int ix = 0;
-       static int fmt_num = 4;
+       static int fmt_num = 6;
        static int fmt_hiwater = 0;
+       struct format_spec *spec = NULL;
+       extern struct format_spec *fmt_parse(NODE *, const char *, size_t);
+
+       /*
+        *      BEGIN { CONVFMT="%s"; print 1.1234567 "X" }
+        *      number -> force_string -> CONVFMT = %s -> force_string -> ...
+        */
+
+       if (fmt_list == NULL) {
+               NODE *t;
+
+               emalloc(fmt_list, struct fmt_list_item *, fmt_num * 
sizeof(*fmt_list), "fmt_index");
+
+               /*
+                * XXX: Insert "%d" and "%.0f" at known indices, used to 
convert integers.
+                * The indices are defined using `enum { INT_d_FMT_INDEX, 
INT_0f_FMT_INDEX }'
+                * in format.h;
+                * We want to avoid calling format_tree() directly in case the 
current
+                * number handler hasn't been initialized, or we need a 
different handler;
+                * may also be a bit more efficient.
+                */
+
+               t = make_string("%d", 2);
+               spec = fmt_parse(CONVFMT_node, t->stptr, t->stlen);
+               assert(spec != NULL);
+               fmt_list[fmt_hiwater].fmt = t;
+               fmt_list[fmt_hiwater].spec = spec;
+               fmt_hiwater++;
+
+               t = make_string("%.0f", 4);
+               spec = fmt_parse(CONVFMT_node, t->stptr, t->stlen);
+               assert(spec != NULL);
+               fmt_list[fmt_hiwater].fmt = t;
+               fmt_list[fmt_hiwater].spec = spec;
+               fmt_hiwater++;
+       }
 
-       if (fmt_list == NULL)
-               emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), 
"fmt_index");
        n = force_string(n);
        while (ix < fmt_hiwater) {
-               if (cmp_nodes(fmt_list[ix], n) == 0)
+               if (cmp_nodes(fmt_list[ix].fmt, n) == 0)
                        return ix;
                ix++;
        }
        /* not found */
+
        n->stptr[n->stlen] = '\0';
        if (do_lint && ! fmt_ok(n->stptr))
                lintwarn(_("bad `%sFMT' specification `%s'"),
@@ -878,11 +913,23 @@ fmt_index(NODE *n)
                          : n == OFMT_node->var_value ? "O"
                          : "", n->stptr);
 
+       if (n == CONVFMT_node->var_value) {
+               /* XXX -- %s or %c not allowed for CONVFMT */
+               spec = fmt_parse(CONVFMT_node, n->stptr, n->stlen);
+               if (spec == NULL)
+                       fatal(_("invalid CONVFMT specification `%s'"), 
n->stptr);
+       } else if (n == OFMT_node->var_value) {
+               spec = fmt_parse(OFMT_node, n->stptr, n->stlen);
+               if (spec == NULL)
+                       fatal(_("invalid OFMT specification `%s'"), n->stptr);
+       }
+
        if (fmt_hiwater >= fmt_num) {
                fmt_num *= 2;
-               erealloc(fmt_list, NODE **, fmt_num * sizeof(*fmt_list), 
"fmt_index");
+               erealloc(fmt_list, struct fmt_list_item *, fmt_num * 
sizeof(*fmt_list), "fmt_index");
        }
-       fmt_list[fmt_hiwater] = dupnode(n);
+       fmt_list[fmt_hiwater].fmt = dupnode(n);
+       fmt_list[fmt_hiwater].spec = spec;
        return fmt_hiwater++;
 }
 
@@ -892,7 +939,7 @@ void
 set_OFMT()
 {
        OFMTidx = fmt_index(OFMT_node->var_value);
-       OFMT = fmt_list[OFMTidx]->stptr;
+       OFMT = fmt_list[OFMTidx].fmt->stptr;
 }
 
 /* set_CONVFMT --- track CONVFMT correctly */
@@ -901,7 +948,7 @@ void
 set_CONVFMT()
 {
        CONVFMTidx = fmt_index(CONVFMT_node->var_value);
-       CONVFMT = fmt_list[CONVFMTidx]->stptr;
+       CONVFMT = fmt_list[CONVFMTidx].fmt->stptr;
 }
 
 /* set_LINT --- update LINT as appropriate */
diff --git a/format.h b/format.h
index 1418a8b..74d6f51 100644
--- a/format.h
+++ b/format.h
@@ -1,3 +1,28 @@
+/*
+ * format.h - (s)printf formatting related definitions.
+ */
+
+/* 
+ * Copyright (C) 2012 the Free Software Foundation, Inc.
+ * 
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ * 
+ * GAWK is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * GAWK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
+ */
+
 /* format specification */
 
 struct format_spec {
@@ -15,6 +40,10 @@ struct format_spec {
        char fmtchar;
 };
 
+/* indices in `fmt_index' for "%d" and "%.0f" */
+
+enum { INT_d_FMT_INDEX, INT_0f_FMT_INDEX };
+
 
 /* struct to manage awk (s)printf formatted string */
 
@@ -97,18 +126,21 @@ buf_adjust(struct print_fmt_buf *outb, size_t len)
        outb->room_left -= len;
 }
 
-/* buf2node --- convert bytes to string NODE */
+/* bytes2node --- convert bytes to string NODE */
 
 static inline NODE *
-buf2node(struct print_fmt_buf *outb)
+bytes2node(struct print_fmt_buf *outb, NODE *node)
 {
-       NODE *node;
-       node = make_str_node(outb->buf, outb->dataend - outb->buf, 
ALREADY_MALLOCED);
+       /* FIXME -- realloc buf? AFAIK, never done before or an issue at all -- 
JH */
+       if (node != NULL) {
+               node->stptr = outb->buf;
+               node->stlen = outb->dataend - outb->buf;
+       } else
+               node = make_str_node(outb->buf, outb->dataend - outb->buf, 
ALREADY_MALLOCED);
        outb->buf = NULL;
        return node;
 }
 
-
 /* tmpbuf_prepend --- prepend one byte to temporary buffer */
 
 static inline void
diff --git a/mpfr.c b/mpfr.c
index edb8fd7..f0b7c3f 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -46,8 +46,6 @@ typedef mp_exp_t mpfr_exp_t;
 #define DEFAULT_PREC           53
 #define DEFAULT_ROUNDMODE      "N"             /* round to nearest */
 
-extern NODE **fmt_list;          /* declared in eval.c */
-
 /* exported functions */
 static NODE *mpfp_make_number(AWKNUM);
 static int mpfp_compare(const NODE *, const NODE *);
@@ -99,7 +97,6 @@ static NODE *do_mpfp_srand(int);
 static NODE *do_mpfp_strtonum(int);
 static NODE *do_mpfp_xor(int);
 
-
 /* internal functions */
 static NODE *mpfp_make_node(unsigned int type);
 static int mpfp_format_ieee(mpfr_ptr, int);
@@ -108,7 +105,6 @@ static int mpfp_strtoui(mpz_ptr, char *, size_t, char **, 
int);
 static mpfr_rnd_t mpfp_get_rounding_mode(const char rmode);
 static mpfr_ptr mpz2mpfr(mpz_ptr mpz_val, mpfr_ptr mpfr_val);
 
-
 static mpfr_rnd_t ROUND_MODE;
 static mpz_t MNR;
 static mpz_t MFNR;
@@ -602,35 +598,35 @@ mpfp_force_number(NODE *n)
 static NODE *
 mpfp_format_val(const char *format, int index, NODE *s)
 {
-       NODE *dummy[2], *r;
-       unsigned int oflags;
+       struct format_spec spec;
+       struct print_fmt_buf *outb;
+
+       if ((s->flags & STRCUR) != 0)
+               efree(s->stptr);
+       free_wstr(s);
 
-       /* create dummy node for a sole use of format_tree */
-       dummy[1] = s;
-       oflags = s->flags;
+       /* XXX: format_spec copied since can be altered in the formatting 
routine */
 
        if (is_mpfp_integer(s) || mpfr_integer_p(s->qnumbr)) {
                /* integral value, use %d */
-               r = format_tree("%d", 2, dummy, 2);
+               spec = *fmt_list[INT_d_FMT_INDEX].spec;
                s->stfmt = -1;
        } else {
-               r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
-               assert(r != NULL);
+               assert(fmt_list[index].spec != NULL);   /* or can use 
fmt_parse() --- XXX */
+               spec = *fmt_list[index].spec;
                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);
+
+       outb = get_fmt_buf();
+       mpfp_format_printf(s, & spec, outb);
+       (void) bytes2node(outb, s);
+       free_fmt_buf(outb);
+
+       s->stptr[s->stlen] = '\0';
+       s->flags |= STRCUR;
        return s;
 }
 
-
 /* mpfp_str2node --- create an arbitrary-pecision number from string */
 
 static NODE *
@@ -968,8 +964,25 @@ mpfp_negate_num(NODE *n)
                int tval;
                tval = mpfr_neg(n->qnumbr, n->qnumbr, ROUND_MODE);
                IEEE_FMT(n->qnumbr, tval);
-       } else /* if (is_mpfp_integer(n)) */
-               mpz_neg(n->qnumbr, n->qnumbr);
+       } else {
+               /* GMP integer */
+               if (mpz_sgn(MPZ_T(n->qnumbr)) == 0) {
+                       /*
+                        * The result should be -0.0, a float.
+                        * XXX: atan2(0, -0) is PI not 0.
+                        */ 
+                       mpz_clear(n->qnumbr);
+                       efree(n->qnumbr);
+                       n->flags &= ~MPZN;
+                       emalloc(n->qnumbr, void *, sizeof (mpfr_t), 
"mpfp_negate_num");
+                       mpfr_init(n->qnumbr);
+                       n->flags |= MPFN;
+
+                       /* XXX: assuming IEEE 754 double, or could use 
mpfr_set_str(op, "-0.0", ...) */
+                       mpfr_set_d(n->qnumbr, -0.0, ROUND_MODE);
+               } else
+                       mpz_neg(n->qnumbr, n->qnumbr);
+       }
 }
 
 /* do_mpfp_atan2 --- do the atan2 function */
@@ -1797,7 +1810,6 @@ mpfp_format_printf(NODE *arg, struct format_spec *spec, 
struct print_fmt_buf *ou
        char *cp;
        char cs1;
        int nc;
-       /* const char *chbuf; */
 
 #      define CP               cpbuf_start(outb)
 #      define CEND             cpbuf_end(outb)
@@ -1849,56 +1861,53 @@ mpz0:
                        mpfmt_spec = spec->have_prec ? MP_INT_WITH_PREC : 
MP_INT_WITHOUT_PREC;
                        goto fmt0;
 
-               } else {
-                       assert(is_mpfp_float(arg) == true);
+               }
+
+               assert(is_mpfp_float(arg) == true);
 mpf0:
-                       mf = arg->qnumbr;
-                       if (! mpfr_number_p(mf)) {
-                               /* inf or NaN */
-                               cs1 = 'g';
-                               mpfmt_spec = MP_FLOAT;
-                               goto fmt1;
-                       }
+               mf = arg->qnumbr;
+               if (! mpfr_number_p(mf)) {
+                       /* inf or NaN */
+                       cs1 = 'g';
+                       mpfmt_spec = MP_FLOAT;
+                       goto fmt1;
+               }
 
-                       if (cs1 != 'd' && cs1 != 'i') {
+               if (cs1 != 'd' && cs1 != 'i') {
 mpf1:
-                               /*
-                                * The output of printf("%#.0x", 0) is 0 
instead of 0x, hence <= in
-                                * the comparison below.
-                                */
-                               if (mpfr_sgn(mf) <= 0) {
-                                       if (! mpfr_fits_intmax_p(mf, 
ROUND_MODE)) {
-                                               /* -ve number is too large */
-                                               cs1 = 'g';
-                                               mpfmt_spec = MP_FLOAT;
-                                               goto fmt1;
-                                       }
-
-                                       uval = (uintmax_t) mpfr_get_sj(mf, 
ROUND_MODE);
-                                       if (! spec->alt && spec->have_prec && 
spec->prec == 0 && uval == 0) {
-                                               /* printf("%.0x", 0) is no 
characters */
-                                               pr_num_tail(cp, 0, spec, outb);
-                                               return 0;
-                                       }
-
-                                       /* spec->fmtchar = cs1; */
-                                       /* spec->chbuf = chbuf; */
-                                       format_nondecimal(uval, spec, outb);
-                                       return 0;
+                       /*
+                        * The output of printf("%#.0x", 0) is 0 instead of 0x, 
hence <= in
+                        * the comparison below.
+                        */
+                       if (mpfr_sgn(mf) <= 0) {
+                               if (! mpfr_fits_intmax_p(mf, ROUND_MODE)) {
+                                       /* -ve number is too large */
+                                       cs1 = 'g';
+                                       mpfmt_spec = MP_FLOAT;
+                                       goto fmt1;
                                }
-                               spec->signchar = '\0';  /* Don't print '+' */
+
+                               uval = (uintmax_t) mpfr_get_sj(mf, ROUND_MODE);
+                               if (! spec->alt && spec->have_prec && 
spec->prec == 0 && uval == 0) {
+                                       /* printf("%.0x", 0) is no characters */
+                                       pr_num_tail(cp, 0, spec, outb);
+                               } else
+                                       format_nondecimal(uval, spec, outb);
+                               return 0;
                        }
+                       spec->signchar = '\0';  /* Don't print '+' */
+               }
 
-                       /* See comments above about when to fill with zeros */
-                       spec->zero_flag = (! spec->lj
-                                           && ((spec->zero_flag && ! 
spec->have_prec)
-                                                || (spec->fw == 0 && 
spec->have_prec)));
+               /* See comments above about when to fill with zeros */
+               spec->zero_flag = (! spec->lj
+                                   && ((spec->zero_flag && ! spec->have_prec)
+                                        || (spec->fw == 0 && 
spec->have_prec)));
                        
-                       (void) mpfr_get_z(_mpzval, mf, MPFR_RNDZ);      /* 
convert to GMP integer */
-                       mpfmt_spec = spec->have_prec ? MP_INT_WITH_PREC : 
MP_INT_WITHOUT_PREC;
-                       zi = _mpzval;
-                       goto fmt0;
-               }
+               (void) mpfr_get_z(_mpzval, mf, MPFR_RNDZ);      /* convert to 
GMP integer */
+               mpfmt_spec = spec->have_prec ? MP_INT_WITH_PREC : 
MP_INT_WITHOUT_PREC;
+               zi = _mpzval;
+               goto fmt0;
+
 
 #if 0
 out_of_range:
@@ -1960,19 +1969,19 @@ fmt0:
                case MP_INT_WITH_PREC:
                        sprintf(cp, "*.*Z%c", cs1);
                        while ((nc = mpfr_snprintf(buf_end(outb), 
buf_space(outb), CPBUF,
-                                       (int) spec->fw, (int) spec->prec, zi)) 
>= buf_space(outb))
+               (int) spec->fw, (int) spec->prec, zi)) >= buf_space(outb))
                                chksize(outb, nc + 1);
                        break;
                case MP_INT_WITHOUT_PREC:
                        sprintf(cp, "*Z%c", cs1);
                        while ((nc = mpfr_snprintf(buf_end(outb), 
buf_space(outb), CPBUF,
-                                       (int) spec->fw, zi)) >= buf_space(outb))
+               (int) spec->fw, zi)) >= buf_space(outb))
                                chksize(outb, nc + 1);
                        break;
                case MP_FLOAT:
                        sprintf(cp, "*.*R*%c", cs1);
                        while ((nc = mpfr_snprintf(buf_end(outb), 
buf_space(outb), CPBUF,
-                                       (int) spec->fw, (int) spec->prec, 
ROUND_MODE, mf)) >= buf_space(outb))
+               (int) spec->fw, (int) spec->prec, ROUND_MODE, mf)) >= 
buf_space(outb))
                                chksize(outb, nc + 1);
                        break;
                default:
@@ -1992,8 +2001,11 @@ fmt0:
        }
 
        return -1;
-}
 
+#undef CP
+#undef CEND
+#undef CPBUF
+}
 
 #else
 

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

Summary of changes:
 ChangeLog                   |   12 +++
 TODO.NUMH                   |   26 +++++++-
 array.c                     |    4 +-
 awk.h                       |   10 ++-
 awklib/eg/lib/repl_math.awk |   23 ++++---
 builtin.c                   |   72 +++++++++++++++++---
 double.c                    |   53 ++++++++-------
 eval.c                      |   65 +++++++++++++++---
 format.h                    |   42 ++++++++++--
 mpfr.c                      |  156 +++++++++++++++++++++++--------------------
 10 files changed, 325 insertions(+), 138 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

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