gawk-diffs
[Top][All Lists]
Advanced

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

[gawk-diffs] [SCM] gawk branch, feature/fixtype, created. gawk-4.1.0-181


From: Andrew J. Schorr
Subject: [gawk-diffs] [SCM] gawk branch, feature/fixtype, created. gawk-4.1.0-1814-g18c6b0f
Date: Mon, 13 Jun 2016 22:41:39 +0000 (UTC)

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, feature/fixtype has been created
        at  18c6b0f85db6683f1d0789e800acfdd35da3ce07 (commit)

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

commit 18c6b0f85db6683f1d0789e800acfdd35da3ce07
Author: Andrew J. Schorr <address@hidden>
Date:   Mon Jun 13 18:39:10 2016 -0400

    Fix usage of scalar type flag bits and fix some bugs in numeric conversions 
and lint checks.

diff --git a/ChangeLog b/ChangeLog
index e6c07ac..9a3636b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,77 @@
+2016-06-12         Andrew J. Schorr     <address@hidden>
+       
+       * awk.h: Improve comment about STRING and NUMBER type assignment.
+       (nondec2awknum): Add endptr argument.
+       (fixtype): New inline function to clarify a scalar's type.
+       * array.c (sort_up_value_type): Call fixtype before checking the value
+       types.
+       * awkgram.y (yylex): Pass NULL endptr argument to nondec2awknum.
+       (valinfo): Remove dead tests: either STRING or NUMBER or both
+       must be set, so there's no reason to continue with checks for NUMCUR or
+       STRCUR.
+       * builtin.c (do_exp, do_int, do_log, do_sqrt, do_sin, do_cos, do_srand):
+       Fix lint check for non-numeric argument.
+       (do_string): Fix lint check for 1st and 2nd args being strings.
+       (do_length): Fix assert to allow for Node_typedregex.
+       Fix lint check for non-string argument.
+       (format_tree): Fix type detection for '%c' arguments.
+       (do_strftime): Fix lint check for non-numeric 2nd argument and
+       lint check for non-string 1st argument.
+       (do_mktime): Fix lint check for non-string argument. Eliminate useless
+       logic to save and restore terminating NUL.
+       (do_system, do_tolower, do_toupper): Fix lint check for non-string
+       argument.
+       (do_atan2, do_lshift, do_rshift, do_and, do_or, do_xor, do_compl,
+       do_intdiv): Fix lint checks for non-numeric args.
+       (do_sub): Attempt to clean up treatment of 3rd argument to gensub
+       despite vague documentation of expected behavior.
+       (do_strnum): Fix bug in number detection logic, and pass new endptr
+       arg to nondec2awknum.
+       (nondec2awknum): Add endptr argument so caller can detect how much
+       of the string was consumed. Eliminate unnecessary logic to save
+       and restore terminating NUL char.
+       (do_typeof): Use a switch to specify which cases are supported, and
+       issue a warning message when a corrupt type is detected.
+       * debug.c (print_memory): At least one of NUMBER and STRING should
+       be set, so no need to check for NUMCUR or STRCUR in addition.
+       * eval.c (cmp_nodes): Use fixtype function to fix arg types.
+       (set_IGNORECASE): Fix logic for acting on value type. Note that
+       setting IGNORECASE to a string value of "0" with NUMCUR set now enables
+       ignorecase, so that's a subtle change in behavior that seems to match
+       the docs.
+       (set_LINT): Try to clean up configuration logic based on type.
+       * ext.c (get_argument): Remove unused variable pcount.
+       * gawkapi.c (node_to_awk_value): Remove pointless test for NUMCUR
+       after calling force_number. Similarly, no need to test for STRCUR
+       after calling force_string.
+       * int_array.c (is_integer): Reject cases where a string value is
+       present that will not be correctly regenerated from the integer;
+       in particular, this could happen where blank space padding is present,
+       leading zeroes are present, or for hex or octal values.
+       Also fix some bugs where a strnum was converted to a NUMBER without
+       turning off the STRING bit.
+       * io.c (redirect_string): Make lint warning message more accurate.
+       (redirect): Change not_string test to use STRING bit, not STRCUR.
+       (pty_vs_pipe): Use fixtype to correct logic for detecting whether a
+       value is anumber.
+       * mpfr.c (mpg_force_number): If NUMCUR is set, there's no need to
+       test is_mpg_number. If it's not, the NODE is corrupt and we've got
+       bigger problems. Fix flag manipulation logic. Always set NUMCUR and
+       clear MAYBE_NUM, 
+       (set_PREC): Fix logic using fixtype function.
+       (do_mpfr_atan2, do_mpfr_intdiv): Fix lint check for non-numeric
+       arguments.
+       (do_mpfr_func, do_mpfr_int, do_mpfr_compl, get_intval, do_mpfr_srand):
+       Fix lint check for non-numeric argument.
+       (do_mpfr_strtonum): Use fixtype and stop testing for NUMCUR bit.
+       * node.c (r_force_number): Eliminate pointless save and restore of
+       terminating NUL char. Always set NUMCUR and clear MAYBE_NUM, and
+       convert STRING to NUMBER if appropriate, fixing bugs in flag
+       manipulations. For non-decimal data, need to consider whether there
+       is trailing non-numeric data in deciding whether a MAYBE_NUM should
+       be converted to a NUMBER, so take advantage of new endptr arg
+       to nondec2awknum.
+
 2016-05-30         Andrew J. Schorr     <address@hidden>
 
        * gawkapi.h (awk_ext_func_t): Rename num_expected_args to
diff --git a/array.c b/array.c
index f805106..afa3795 100644
--- a/array.c
+++ b/array.c
@@ -1157,17 +1157,8 @@ sort_up_value_type(const void *p1, const void *p2)
        }
 
        /* two scalars */
-       /* 2. Resolve MAYBE_NUM, so that have only NUMBER or STRING */
-       if ((n1->flags & MAYBE_NUM) != 0)
-               (void) force_number(n1);
-       if ((n2->flags & MAYBE_NUM) != 0)
-               (void) force_number(n2);
-
-       /* 2.5. Resolve INTIND, so that is STRING, and not NUMBER */
-       if ((n1->flags & INTIND) != 0)
-               (void) force_string(n1);
-       if ((n2->flags & INTIND) != 0)
-               (void) force_string(n2);
+       (void) fixtype(n1);
+       (void) fixtype(n2);
 
        if ((n1->flags & NUMBER) != 0 && (n2->flags & NUMBER) != 0) {
                return cmp_numbers(n1, n2);
diff --git a/awk.h b/awk.h
index 9084e0d..0cbcf04 100644
--- a/awk.h
+++ b/awk.h
@@ -392,8 +392,11 @@ typedef struct exp_node {
 
 /* type = Node_val */
        /*
-        * STRING and NUMBER are mutually exclusive. They represent the
-        * type of a value as assigned.
+        * STRING and NUMBER are mutually exclusive, except for the special
+        * case of an uninitialized value, represented internally by
+        * Nnull_string. They represent the type of a value as assigned.
+        * Nnull_string has both STRING and NUMBER attributes, but all other
+        * scalar values should have precisely one of these bits set.
         *
         * STRCUR and NUMCUR are not mutually exclusive. They represent that
         * the particular type of value is up to date.  For example,
@@ -408,7 +411,8 @@ typedef struct exp_node {
         *
         * MAYBE_NUM is the joker.  It means "this is string data, but
         * the user may have really wanted it to be a number. If we have
-        * to guess, like in a comparison, turn it into a number."
+        * to guess, like in a comparison, turn it into a number if the string
+        * is indeed numeric."
         * For example,    gawk -v a=42 ....
         * Here, `a' gets STRING|STRCUR|MAYBE_NUM and then when used where
         * a number is needed, it gets turned into a NUMBER and STRING
@@ -1401,7 +1405,7 @@ extern NODE *do_or(int nargs);
 extern NODE *do_xor(int nargs);
 extern NODE *do_compl(int nargs);
 extern NODE *do_strtonum(int nargs);
-extern AWKNUM nondec2awknum(char *str, size_t len);
+extern AWKNUM nondec2awknum(char *str, size_t len, char **endptr);
 extern NODE *do_dcgettext(int nargs);
 extern NODE *do_dcngettext(int nargs);
 extern NODE *do_bindtextdomain(int nargs);
@@ -1814,6 +1818,31 @@ force_number(NODE *n)
 
 #endif /* GAWKDEBUG */
 
+/*
+ * In certain contexts, the true type of a scalar value matters, and we
+ * must ascertain whether it is a a NUMBER or a STRING. In such situations,
+ * please use this function to resolve the type.
+ *
+ * It is safe to assume that the return value will be the same NODE,
+ * since force_number on a MAYBE_NUM should always returns the same NODE,
+ * and force_string on an INTIND should as well.
+ *
+ * There is no way to handle a Node_typedregex correctly, so we ignore
+ * that case.
+ */
+static inline NODE *
+fixtype(NODE *n)
+{
+       assert((n->type == Node_val) || (n->type == Node_typedregex));
+       if (n->type == Node_val) {
+               if ((n->flags & MAYBE_NUM) != 0)
+                       return force_number(n);
+               if ((n->flags & INTIND) != 0)
+                       return force_string(n);
+       }
+       return n;
+}
+
 static inline void *
 emalloc_real(size_t count, const char *where, const char *var, const char 
*file, int line)
 {
diff --git a/awkgram.c b/awkgram.c
index bd531ef..c40217c 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -6422,7 +6422,7 @@ retry:
                }
 #endif
                if (base != 10)
-                       d = nondec2awknum(tokstart, strlen(tokstart));
+                       d = nondec2awknum(tokstart, strlen(tokstart), NULL);
                else
                        d = atof(tokstart);
                yylval->memory = make_number(d);
@@ -7031,18 +7031,6 @@ valinfo(NODE *n, Func_print print_func, FILE *fp)
                else
 #endif
                print_func(fp, "%.17g\n", n->numbr);
-       } else if ((n->flags & STRCUR) != 0) {
-               pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false);
-               print_func(fp, "\n");
-       } else if ((n->flags & NUMCUR) != 0) {
-#ifdef HAVE_MPFR
-               if (is_mpg_float(n))
-                       print_func(fp, "%s\n", mpg_fmt("%.17R*g", ROUND_MODE, 
n->mpg_numbr));
-               else if (is_mpg_integer(n))
-                       print_func(fp, "%s\n", mpg_fmt("%Zd", n->mpg_i));
-               else
-#endif
-               print_func(fp, "%.17g\n", n->numbr);
        } else
                print_func(fp, "?? flags %s\n", flags2str(n->flags));
 }
diff --git a/awkgram.y b/awkgram.y
index 752503c..81c6945 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -4002,7 +4002,7 @@ retry:
                }
 #endif
                if (base != 10)
-                       d = nondec2awknum(tokstart, strlen(tokstart));
+                       d = nondec2awknum(tokstart, strlen(tokstart), NULL);
                else
                        d = atof(tokstart);
                yylval->memory = make_number(d);
@@ -4611,18 +4611,6 @@ valinfo(NODE *n, Func_print print_func, FILE *fp)
                else
 #endif
                print_func(fp, "%.17g\n", n->numbr);
-       } else if ((n->flags & STRCUR) != 0) {
-               pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false);
-               print_func(fp, "\n");
-       } else if ((n->flags & NUMCUR) != 0) {
-#ifdef HAVE_MPFR
-               if (is_mpg_float(n))
-                       print_func(fp, "%s\n", mpg_fmt("%.17R*g", ROUND_MODE, 
n->mpg_numbr));
-               else if (is_mpg_integer(n))
-                       print_func(fp, "%s\n", mpg_fmt("%Zd", n->mpg_i));
-               else
-#endif
-               print_func(fp, "%.17g\n", n->numbr);
        } else
                print_func(fp, "?? flags %s\n", flags2str(n->flags));
 }
diff --git a/builtin.c b/builtin.c
index 285b442..90a1fa0 100644
--- a/builtin.c
+++ b/builtin.c
@@ -148,7 +148,7 @@ do_exp(int nargs)
        double d, res;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("exp: received non-numeric argument"));
        d = force_number(tmp)->numbr;
        DEREF(tmp);
@@ -354,9 +354,9 @@ do_index(int nargs)
        POP_TWO_SCALARS(s1, s2);
 
        if (do_lint) {
-               if ((s1->flags & (STRING|STRCUR)) == 0)
+               if ((fixtype(s1)->flags & STRING) == 0)
                        lintwarn(_("index: received non-string first 
argument"));
-               if ((s2->flags & (STRING|STRCUR)) == 0)
+               if ((fixtype(s2)->flags & STRING) == 0)
                        lintwarn(_("index: received non-string second 
argument"));
        }
 
@@ -469,7 +469,7 @@ do_int(int nargs)
        double d;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("int: received non-numeric argument"));
        d = force_number(tmp)->numbr;
        d = double_to_int(d);
@@ -532,9 +532,9 @@ do_length(int nargs)
                return make_number(size);
        }
 
-       assert(tmp->type == Node_val);
+       assert(tmp->type == Node_val || tmp->type == Node_typedregex);
 
-       if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & STRING) == 0)
                lintwarn(_("length: received non-string argument"));
        tmp = force_string(tmp);
 
@@ -563,7 +563,7 @@ do_log(int nargs)
        double d, arg;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("log: received non-numeric argument"));
        arg = force_number(tmp)->numbr;
        if (arg < 0.0)
@@ -1048,9 +1048,7 @@ check_pos:
                case 'c':
                        need_format = false;
                        parse_next_arg();
-                       /* user input that looks numeric is numeric */
-                       if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM)
-                               (void) force_number(arg);
+                       fixtype(arg);
                        if ((arg->flags & NUMBER) != 0) {
                                uval = get_number_uj(arg);
                                if (gawk_mb_cur_max > 1) {
@@ -1727,7 +1725,7 @@ do_sqrt(int nargs)
        double arg;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("sqrt: received non-numeric argument"));
        arg = (double) force_number(tmp)->numbr;
        DEREF(tmp);
@@ -1940,7 +1938,7 @@ do_strftime(int nargs)
 
                if (nargs >= 2) {
                        t2 = POP_SCALAR();
-                       if (do_lint && (t2->flags & (NUMCUR|NUMBER)) == 0)
+                       if (do_lint && (fixtype(t2)->flags & NUMBER) == 0)
                                lintwarn(_("strftime: received non-numeric 
second argument"));
                        (void) force_number(t2);
                        clock_val = get_number_d(t2);
@@ -1966,7 +1964,7 @@ do_strftime(int nargs)
                }
 
                tmp = POP_SCALAR();
-               if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
+               if (do_lint && (fixtype(tmp)->flags & STRING) == 0)
                        lintwarn(_("strftime: received non-string first 
argument"));
        
                t1 = force_string(tmp);
@@ -2039,16 +2037,12 @@ do_mktime(int nargs)
        int month, day, hour, minute, second, count;
        int dst = -1; /* default is unknown */
        time_t then_stamp;
-       char save;
 
        t1 = POP_SCALAR();
-       if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
+       if (do_lint && (fixtype(t1)->flags & STRING) == 0)
                lintwarn(_("mktime: received non-string argument"));
        t1 = force_string(t1);
 
-       save = t1->stptr[t1->stlen];
-       t1->stptr[t1->stlen] = '\0';
-
        count = sscanf(t1->stptr, "%ld %d %d %d %d %d %d",
                        & year, & month, & day,
                        & hour, & minute, & second,
@@ -2062,7 +2056,6 @@ do_mktime(int nargs)
                || (month < 1 || month > 12) ))
                        lintwarn(_("mktime: at least one of the values is out 
of the default range"));
 
-       t1->stptr[t1->stlen] = save;
        DEREF(t1);
 
        if (count < 6
@@ -2100,7 +2093,7 @@ do_system(int nargs)
 
        (void) flush_io();     /* so output is synchronous with gawk's */
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & STRING) == 0)
                lintwarn(_("system: received non-string argument"));
        cmd = force_string(tmp)->stptr;
 
@@ -2370,7 +2363,7 @@ do_tolower(int nargs)
        NODE *t1, *t2;
 
        t1 = POP_SCALAR();
-       if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
+       if (do_lint && (fixtype(t1)->flags & STRING) == 0)
                lintwarn(_("tolower: received non-string argument"));
        t1 = force_string(t1);
        t2 = make_string(t1->stptr, t1->stlen);
@@ -2401,7 +2394,7 @@ do_toupper(int nargs)
        NODE *t1, *t2;
 
        t1 = POP_SCALAR();
-       if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
+       if (do_lint && (fixtype(t1)->flags & STRING) == 0)
                lintwarn(_("toupper: received non-string argument"));
        t1 = force_string(t1);
        t2 = make_string(t1->stptr, t1->stlen);
@@ -2434,9 +2427,9 @@ do_atan2(int nargs)
 
        POP_TWO_SCALARS(t1, t2);
        if (do_lint) {
-               if ((t1->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(t1)->flags & NUMBER) == 0)
                        lintwarn(_("atan2: received non-numeric first 
argument"));
-               if ((t2->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(t2)->flags & NUMBER) == 0)
                        lintwarn(_("atan2: received non-numeric second 
argument"));
        }
        d1 = force_number(t1)->numbr;
@@ -2455,7 +2448,7 @@ do_sin(int nargs)
        double d;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("sin: received non-numeric argument"));
        d = sin((double) force_number(tmp)->numbr);
        DEREF(tmp);
@@ -2471,7 +2464,7 @@ do_cos(int nargs)
        double d;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("cos: received non-numeric argument"));
        d = cos((double) force_number(tmp)->numbr);
        DEREF(tmp);
@@ -2585,7 +2578,7 @@ do_srand(int nargs)
                srandom((unsigned int) (save_seed = (long) time((time_t *) 0)));
        else {
                tmp = POP_SCALAR();
-               if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+               if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                        lintwarn(_("srand: received non-numeric argument"));
                srandom((unsigned int) (save_seed = (long) 
force_number(tmp)->numbr));
                DEREF(tmp);
@@ -2869,31 +2862,24 @@ do_sub(int nargs, unsigned int flags)
                target = POP_STRING();  /* original string */
 
                glob_flag = POP_SCALAR();       /* value of global flag */
-               if ((glob_flag->flags & (STRCUR|STRING)) != 0) {
-                       if (glob_flag->stlen > 0 && (glob_flag->stptr[0] == 'g' 
|| glob_flag->stptr[0] == 'G'))
-                               how_many = -1;
-                       else {
-                               (void) force_number(glob_flag);
-                               d = get_number_d(glob_flag);
-                               if ((glob_flag->flags & NUMCUR) != 0)
-                                       goto set_how_many;
-
-                               warning(_("gensub: third argument `%.*s' 
treated as 1"),
-                                               (int) glob_flag->stlen, 
glob_flag->stptr);
-                               how_many = 1;
-                       }
-               } else {
+               if (((glob_flag->flags & STRING) != 0)
+                       && (glob_flag->stlen > 0
+                               && (glob_flag->stptr[0] == 'g'
+                                       || glob_flag->stptr[0] == 'G')))
+                       how_many = -1;
+               else {
                        (void) force_number(glob_flag);
                        d = get_number_d(glob_flag);
-set_how_many:
                        if (d < 1)
                                how_many = 1;
                        else if (d < LONG_MAX)
                                how_many = d;
                        else
                                how_many = LONG_MAX;
-                       if (d <= 0)
-                               warning(_("gensub: third argument %g treated as 
1"), d);
+                       if (d <= 0) {
+                               (void) force_string(glob_flag);
+                               warning(_("gensub: third argument `%s' treated 
as 1"), glob_flag->stptr);
+                       }
                }
                DEREF(glob_flag);
        } else {
@@ -3353,9 +3339,9 @@ do_lshift(int nargs)
 
        POP_TWO_SCALARS(s1, s2);
        if (do_lint) {
-               if ((s1->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(s1)->flags & NUMBER) == 0)
                        lintwarn(_("lshift: received non-numeric first 
argument"));
-               if ((s2->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(s2)->flags & NUMBER) == 0)
                        lintwarn(_("lshift: received non-numeric second 
argument"));
        }
        val = force_number(s1)->numbr;
@@ -3390,9 +3376,9 @@ do_rshift(int nargs)
 
        POP_TWO_SCALARS(s1, s2);
        if (do_lint) {
-               if ((s1->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(s1)->flags & NUMBER) == 0)
                        lintwarn(_("rshift: received non-numeric first 
argument"));
-               if ((s2->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(s2)->flags & NUMBER) == 0)
                        lintwarn(_("rshift: received non-numeric second 
argument"));
        }
        val = force_number(s1)->numbr;
@@ -3432,7 +3418,7 @@ do_and(int nargs)
 
        for (i = 1; nargs > 0; nargs--, i++) {
                s1 = POP_SCALAR();
-               if (do_lint && (s1->flags & (NUMCUR|NUMBER)) == 0)
+               if (do_lint && (fixtype(s1)->flags & NUMBER) == 0)
                        lintwarn(_("and: argument %d is non-numeric"), i);
 
                val = force_number(s1)->numbr;
@@ -3464,7 +3450,7 @@ do_or(int nargs)
 
        for (i = 1; nargs > 0; nargs--, i++) {
                s1 = POP_SCALAR();
-               if (do_lint && (s1->flags & (NUMCUR|NUMBER)) == 0)
+               if (do_lint && (fixtype(s1)->flags & NUMBER) == 0)
                        lintwarn(_("or: argument %d is non-numeric"), i);
 
                val = force_number(s1)->numbr;
@@ -3496,7 +3482,7 @@ do_xor(int nargs)
        res = 0;        /* silence compiler warning */
        for (i = 1; nargs > 0; nargs--, i++) {
                s1 = POP_SCALAR();
-               if (do_lint && (s1->flags & (NUMCUR|NUMBER)) == 0)
+               if (do_lint && (fixtype(s1)->flags & NUMBER) == 0)
                        lintwarn(_("xor: argument %d is non-numeric"), i);
 
                val = force_number(s1)->numbr;
@@ -3525,7 +3511,7 @@ do_compl(int nargs)
        uintmax_t uval;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("compl: received non-numeric argument"));
        d = force_number(tmp)->numbr;
        DEREF(tmp);
@@ -3550,11 +3536,11 @@ do_strtonum(int nargs)
        NODE *tmp;
        AWKNUM d;
 
-       tmp = POP_SCALAR();
-       if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
-               d = (AWKNUM) force_number(tmp)->numbr;
+       tmp = fixtype(POP_SCALAR());
+       if ((tmp->flags & NUMBER) != 0)
+               d = (AWKNUM) tmp->numbr;
        else if (get_numbase(tmp->stptr, use_lc_numeric) != 10)
-               d = nondec2awknum(tmp->stptr, tmp->stlen);
+               d = nondec2awknum(tmp->stptr, tmp->stlen, NULL);
        else
                d = (AWKNUM) force_number(tmp)->numbr;
 
@@ -3571,10 +3557,9 @@ do_strtonum(int nargs)
  */
 
 AWKNUM
-nondec2awknum(char *str, size_t len)
+nondec2awknum(char *str, size_t len, char **endptr)
 {
        AWKNUM retval = 0.0;
-       char save;
        short val;
        char *start = str;
 
@@ -3583,8 +3568,11 @@ nondec2awknum(char *str, size_t len)
                 * User called strtonum("0x") or some such,
                 * so just quit early.
                 */
-               if (len <= 2)
+               if (len <= 2) {
+                       if (endptr)
+                               *endptr = start;
                        return (AWKNUM) 0.0;
+               }
 
                for (str += 2, len -= 2; len > 0; len--, str++) {
                        switch (*str) {
@@ -3617,14 +3605,21 @@ nondec2awknum(char *str, size_t len)
                                val = *str - 'A' + 10;
                                break;
                        default:
+                               if (endptr)
+                                       *endptr = str;
                                goto done;
                        }
                        retval = (retval * 16) + val;
                }
+               if (endptr)
+                       *endptr = str;
        } else if (*str == '0') {
                for (; len > 0; len--) {
-                       if (! isdigit((unsigned char) *str))
+                       if (! isdigit((unsigned char) *str)) {
+                               if (endptr)
+                                       *endptr = str;
                                goto done;
+                       }
                        else if (*str == '8' || *str == '9') {
                                str = start;
                                goto decimal;
@@ -3632,11 +3627,11 @@ nondec2awknum(char *str, size_t len)
                        retval = (retval * 8) + (*str - '0');
                        str++;
                }
+               if (endptr)
+                       *endptr = str;
        } else {
 decimal:
-               save = str[len];
-               retval = strtod(str, NULL);
-               str[len] = save;
+               retval = strtod(str, endptr);
        }
 done:
        return retval;
@@ -3897,9 +3892,9 @@ do_intdiv(int nargs)
        numerator = POP_SCALAR();
 
        if (do_lint) {
-               if ((numerator->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(numerator)->flags & NUMBER) == 0)
                        lintwarn(_("intdiv: received non-numeric first 
argument"));
-               if ((denominator->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(denominator)->flags & NUMBER) == 0)
                        lintwarn(_("intdiv: received non-numeric second 
argument"));
        }
 
@@ -3958,14 +3953,26 @@ do_typeof(int nargs)
                break;
        case Node_val:
        case Node_var:
-               if (arg == Nnull_string)
-                       res = "unassigned";
-               else if ((arg->flags & STRING) != 0) {
+               switch (arg->flags & (STRING|NUMBER|MAYBE_NUM)) {
+               case STRING:
                        res = "string";
-                       if ((arg->flags & MAYBE_NUM) != 0)
-                               res = "strnum";
-               } else if ((arg->flags & NUMBER) != 0)
+                       break;
+               case NUMBER:
                        res = "number";
+                       break;
+               case STRING|MAYBE_NUM:
+                       res = "strnum";
+                       break;
+               case NUMBER|STRING:
+                       if (arg == Nnull_string) {
+                               res = "unassigned";
+                               break;
+                       }
+                       /* fall through */
+               default:
+                       warning(_("typeof detected invalid flags combination 
`%s'; please file a bug report."), flags2str(arg->flags));
+                       break;
+               }
                break;
        case Node_var_new:
                res = "untyped";
diff --git a/debug.c b/debug.c
index 44caea3..a083062 100644
--- a/debug.c
+++ b/debug.c
@@ -3704,17 +3704,6 @@ print_memory(NODE *m, NODE *func, Func_print print_func, 
FILE *fp)
                                print_func(fp, "%g", m->numbr);
                } else if ((m->flags & STRING) != 0)
                        pp_string_fp(print_func, fp, m->stptr, m->stlen, '"', 
false);
-               else if ((m->flags & NUMCUR) != 0) {
-#ifdef HAVE_MPFR
-                       if ((m->flags & MPFN) != 0)
-                               print_func(fp, "%s", mpg_fmt("%R*g", 
ROUND_MODE, m->mpg_numbr));
-                       else if ((m->flags & MPZN) != 0)
-                               print_func(fp, "%s", mpg_fmt("%Zd", m->mpg_i));
-                       else
-#endif
-                               print_func(fp, "%g", m->numbr);
-               } else if ((m->flags & STRCUR) != 0)
-                       pp_string_fp(print_func, fp, m->stptr, m->stlen, '"', 
false);
                else
                        print_func(fp, "-?-");
                print_func(fp, " [%s]", flags2str(m->flags));
diff --git a/eval.c b/eval.c
index 56c6007..90947dc 100644
--- a/eval.c
+++ b/eval.c
@@ -582,14 +582,8 @@ cmp_nodes(NODE *t1, NODE *t2)
        if (t1 == t2)
                return 0;
 
-       if ((t1->flags & MAYBE_NUM) != 0)
-               (void) force_number(t1);
-       if ((t2->flags & MAYBE_NUM) != 0)
-               (void) force_number(t2);
-       if ((t1->flags & INTIND) != 0)
-               t1 = force_string(t1);
-       if ((t2->flags & INTIND) != 0)
-               t2 = force_string(t2);
+       (void) fixtype(t1);
+       (void) fixtype(t2);
 
        if ((t1->flags & NUMBER) != 0 && (t2->flags & NUMBER) != 0)
                return cmp_numbers(t1, t2);
@@ -698,7 +692,7 @@ void
 set_IGNORECASE()
 {
        static bool warned = false;
-       NODE *n = IGNORECASE_node->var_value;
+       NODE *n;
 
        if ((do_lint || do_traditional) && ! warned) {
                warned = true;
@@ -707,19 +701,13 @@ set_IGNORECASE()
        load_casetable();
        if (do_traditional)
                IGNORECASE = false;
-       else if ((n->flags & (NUMCUR|NUMBER)) != 0)
-               IGNORECASE = ! iszero(n);
-       else if ((n->flags & (STRING|STRCUR)) != 0) {
-               if ((n->flags & MAYBE_NUM) == 0) {
-                       (void) force_string(n);
-                       IGNORECASE = (n->stlen > 0);
-               } else {
-                       (void) force_number(n);
+       else {
+               n = fixtype(IGNORECASE_node->var_value);
+               if ((n->flags & NUMBER) != 0)
                        IGNORECASE = ! iszero(n);
-               }
-       } else
-               IGNORECASE = false;             /* shouldn't happen */
-                 
+               else
+                       IGNORECASE = (n->stlen > 0);
+       }
        set_RS();       /* set_RS() calls set_FS() if need be, for us */
 }
 
@@ -947,49 +935,32 @@ set_LINT()
 {
 #ifndef NO_LINT
        int old_lint = do_lint;
-       NODE *n = LINT_node->var_value;
-
-       if ((n->flags & (STRING|STRCUR)) != 0) {
-               if ((n->flags & MAYBE_NUM) == 0) {
-                       const char *lintval;
-                       size_t lintlen;
-
-                       n = force_string(LINT_node->var_value);
-                       lintval = n->stptr;
-                       lintlen = n->stlen;
-                       if (lintlen > 0) {
-                               do_flags |= DO_LINT_ALL;
-                               if (lintlen == 5 && strncmp(lintval, "fatal", 
5) == 0)
-                                       lintfunc = r_fatal;
-                               else if (lintlen == 7 && strncmp(lintval, 
"invalid", 7) == 0) {
-                                       do_flags &= ~ DO_LINT_ALL;
-                                       do_flags |= DO_LINT_INVALID;
-                               } else
-                                       lintfunc = warning;
-                       } else {
-                               do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
-                               lintfunc = warning;
+       NODE *n = fixtype(LINT_node->var_value);
+
+       lintfunc = r_warning;   /* reset to default */
+       if ((n->flags & STRING) != 0) {
+               const char *lintval;
+               size_t lintlen;
+
+               lintval = n->stptr;
+               lintlen = n->stlen;
+               if (lintlen > 0) {
+                       do_flags |= DO_LINT_ALL;
+                       if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0)
+                               lintfunc = r_fatal;
+                       else if (lintlen == 7 && strncmp(lintval, "invalid", 7) 
== 0) {
+                               do_flags &= ~ DO_LINT_ALL;
+                               do_flags |= DO_LINT_INVALID;
                        }
                } else {
-                       (void) force_number(n);
-                       if (! iszero(n))
-                               do_flags |= DO_LINT_ALL;
-                       else
-                               do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
-                       lintfunc = warning;
+                       do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
                }
-       } else if ((n->flags & (NUMCUR|NUMBER)) != 0) {
-               (void) force_number(n);
+       } else {
                if (! iszero(n))
                        do_flags |= DO_LINT_ALL;
                else
                        do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
-               lintfunc = warning;
-       } else
-               do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);     /* shouldn't 
happen */
-
-       if (! do_lint)
-               lintfunc = warning;
+       }
 
        /* explicitly use warning() here, in case lintfunc == r_fatal */
        if (old_lint != do_lint && old_lint && ! do_lint)
@@ -1546,10 +1517,7 @@ eval_condition(NODE *t)
        if (t == node_Boolean[true])
                return true;
 
-       if ((t->flags & MAYBE_NUM) != 0)
-               force_number(t);
-       else if ((t->flags & INTIND) != 0)
-               force_string(t);
+       (void) fixtype(t);
 
        if ((t->flags & NUMBER) != 0)
                return ! iszero(t);
diff --git a/ext.c b/ext.c
index c0d6f15..ce040ed 100644
--- a/ext.c
+++ b/ext.c
@@ -152,7 +152,7 @@ NODE *
 get_argument(int i)
 {
        NODE *t;
-       int arg_count, pcount;
+       int arg_count;
        INSTRUCTION *pc;
        
        pc = TOP()->code_ptr;           /* Op_ext_builtin instruction */
diff --git a/gawkapi.c b/gawkapi.c
index 8ee6543..b961f79 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -431,21 +431,17 @@ node_to_awk_value(NODE *node, awk_value_t *val, 
awk_valtype_t wanted)
                        val->val_type = AWK_NUMBER;
 
                        (void) force_number(node);
-                       if ((node->flags & NUMCUR) != 0) {
-                               val->num_value = get_number_d(node);
-                               ret = awk_true;
-                       }
+                       val->num_value = get_number_d(node);
+                       ret = awk_true;
                        break;
 
                case AWK_STRING:
                        val->val_type = AWK_STRING;
 
                        (void) force_string(node);
-                       if ((node->flags & STRCUR) != 0) {
-                               val->str_value.str = node->stptr;
-                               val->str_value.len = node->stlen;
-                               ret = awk_true;
-                       }
+                       val->str_value.str = node->stptr;
+                       val->str_value.len = node->stlen;
+                       ret = awk_true;
                        break;
 
                case AWK_SCALAR:
diff --git a/int_array.c b/int_array.c
index a8de3d5..4ba7c98 100644
--- a/int_array.c
+++ b/int_array.c
@@ -89,6 +89,21 @@ is_integer(NODE *symbol, NODE *subs)
        if (subs == Nnull_string || do_mpfr)
                return NULL;
 
+       /*
+        * Protect against MAYBE_NUM values where the string may not regenerate
+        * correctly. There could be white space and/or a non-decimal value.
+        */
+       if ((subs->flags & STRCUR) != 0) {
+               char *cp = subs->stptr;
+
+               if ((cp[0] == '0') || isspace((unsigned char) cp[0])
+                       || (subs->stlen < 1)
+                       || isspace((unsigned char) cp[subs->stlen - 1])
+                       || ((subs->stlen >= 2) && (cp[0] == '-')
+                               && (cp[1] == '0')))
+                       return NULL;
+       }
+
        if ((subs->flags & NUMINT) != 0)
                return & success_node;
 
@@ -107,7 +122,8 @@ is_integer(NODE *symbol, NODE *subs)
         * a[-3]=1; print "-3" in a  -- true
         */
 
-       if ((subs->flags & (STRING|STRCUR)) != 0) {
+       {
+               /* must be a STRING */
                char *cp = subs->stptr, *cpend, *ptr;
                char save;
                size_t len = subs->stlen;
@@ -123,7 +139,7 @@ is_integer(NODE *symbol, NODE *subs)
                if (len == 1 && *cp != '-') {   /* single digit */
                        subs->numbr = (long) (*cp - '0');
                        if ((subs->flags & MAYBE_NUM) != 0) {
-                               subs->flags &= ~MAYBE_NUM;
+                               subs->flags &= ~(MAYBE_NUM|STRING);
                                subs->flags |= NUMBER;
                        }
                        subs->flags |= (NUMCUR|NUMINT);
@@ -141,7 +157,7 @@ is_integer(NODE *symbol, NODE *subs)
                        return NULL;
                subs->numbr = l;
                if ((subs->flags & MAYBE_NUM) != 0) {
-                       subs->flags &= ~MAYBE_NUM;
+                       subs->flags &= ~(MAYBE_NUM|STRING);
                        subs->flags |= NUMBER;
                }
                subs->flags |= NUMCUR;
diff --git a/io.c b/io.c
index db903fd..9d827d7 100644
--- a/io.c
+++ b/io.c
@@ -785,7 +785,7 @@ redirect_string(const char *str, size_t explen, bool 
not_string,
                cant_happen();
        }
        if (do_lint && not_string)
-               lintwarn(_("expression in `%s' redirection only has numeric 
value"),
+               lintwarn(_("expression in `%s' redirection is a number"),
                        what);
 
        if (str == NULL || *str == '\0')
@@ -1083,7 +1083,7 @@ redirect_string(const char *str, size_t explen, bool 
not_string,
 struct redirect *
 redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal)
 {
-       bool not_string = ((redir_exp->flags & STRCUR) == 0);
+       bool not_string = ((redir_exp->flags & STRING) == 0);
 
        redir_exp = force_string(redir_exp);
        return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string,
@@ -3896,8 +3896,7 @@ pty_vs_pipe(const char *command)
         */
        val = in_PROCINFO(command, "pty", NULL);
        if (val) {
-               if ((val->flags & MAYBE_NUM) != 0)
-                       (void) force_number(val);
+               val = fixtype(val);
                if ((val->flags & NUMBER) != 0)
                        return ! iszero(val);
                else
diff --git a/mpfr.c b/mpfr.c
index 35d1ac6..9d270e6 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -341,20 +341,17 @@ done:
 static NODE *
 mpg_force_number(NODE *n)
 {
-       unsigned int newflags = 0;
-
-       if (is_mpg_number(n) && (n->flags & NUMCUR) != 0)
+       if ((n->flags & NUMCUR) != 0)
                return n;
-
-       if ((n->flags & MAYBE_NUM) != 0) {
-               n->flags &= ~(MAYBE_NUM|STRING);
-               newflags = NUMBER;
-       }
+       n->flags |= NUMCUR;
 
        if (force_mpnum(n, (do_non_decimal_data && ! do_traditional), true)) {
-               n->flags |= newflags;
-               n->flags |= NUMCUR;
-       }
+               if ((n->flags & MAYBE_NUM) != 0) {
+                       n->flags &= ~(MAYBE_NUM|STRING);
+                       n->flags |= NUMBER;
+               }
+       } else
+               n->flags &= ~MAYBE_NUM;
        return n;
 }
 
@@ -521,11 +518,9 @@ set_PREC()
        if (! do_mpfr)
                return;
 
-       val = PREC_node->var_value;
-       if ((val->flags & MAYBE_NUM) != 0)
-               force_number(val);
+       val = fixtype(PREC_node->var_value);
 
-       if ((val->flags & STRCUR) != 0) {
+       if ((val->flags & STRING) != 0) {
                int i, j;
 
                /* emulate IEEE-754 binary format */
@@ -675,9 +670,9 @@ do_mpfr_atan2(int nargs)
        t1 = POP_SCALAR();
 
        if (do_lint) {
-               if ((t1->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(t1)->flags & NUMBER) == 0)
                        lintwarn(_("atan2: received non-numeric first 
argument"));
-               if ((t2->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(t2)->flags & NUMBER) == 0)
                        lintwarn(_("atan2: received non-numeric second 
argument"));
        }
        force_number(t1);
@@ -707,7 +702,7 @@ do_mpfr_func(const char *name,
        int tval;
 
        t1 = POP_SCALAR();
-       if (do_lint && (t1->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(t1)->flags & NUMBER) == 0)
                lintwarn(_("%s: received non-numeric argument"), name);
 
        force_number(t1);
@@ -773,7 +768,7 @@ do_mpfr_int(int nargs)
        NODE *tmp, *r;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("int: received non-numeric argument"));
        force_number(tmp);
 
@@ -803,7 +798,7 @@ do_mpfr_compl(int nargs)
        mpz_ptr zptr;
 
        tmp = POP_SCALAR();
-       if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                lintwarn(_("compl: received non-numeric argument"));
 
        force_number(tmp);
@@ -851,7 +846,7 @@ get_intval(NODE *t1, int argnum, const char *op)
 {
        mpz_ptr pz;
 
-       if (do_lint && (t1->flags & (NUMCUR|NUMBER)) == 0)
+       if (do_lint && (fixtype(t1)->flags & NUMBER) == 0)
                lintwarn(_("%s: received non-numeric argument #%d"), op, 
argnum);
 
        (void) force_number(t1);
@@ -1076,8 +1071,8 @@ do_mpfr_strtonum(int nargs)
 {
        NODE *tmp, *r;
 
-       tmp = POP_SCALAR();
-       if ((tmp->flags & (NUMBER|NUMCUR)) == 0) {
+       tmp = fixtype(POP_SCALAR());
+       if ((tmp->flags & NUMBER) == 0) {
                r = mpg_integer();      /* will be changed to MPFR float if 
necessary in force_mpnum() */
                r->stptr = tmp->stptr;
                r->stlen = tmp->stlen;
@@ -1085,7 +1080,6 @@ do_mpfr_strtonum(int nargs)
                r->stptr = NULL;
                r->stlen = 0;
        } else {
-               (void) force_number(tmp);
                if (is_mpg_float(tmp)) {
                        int tval;
                        r = mpg_float();
@@ -1172,7 +1166,7 @@ do_mpfr_srand(int nargs)
        else {
                NODE *tmp;
                tmp = POP_SCALAR();
-               if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+               if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
                        lintwarn(_("srand: received non-numeric argument"));
                force_number(tmp);
                if (is_mpg_float(tmp))
@@ -1213,9 +1207,9 @@ do_mpfr_intdiv(int nargs)
        numerator = POP_SCALAR();
 
        if (do_lint) {
-               if ((numerator->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(numerator)->flags & NUMBER) == 0)
                        lintwarn(_("intdiv: received non-numeric first 
argument"));
-               if ((denominator->flags & (NUMCUR|NUMBER)) == 0)
+               if ((fixtype(denominator)->flags & NUMBER) == 0)
                        lintwarn(_("intdiv: received non-numeric second 
argument"));
        }
 
diff --git a/node.c b/node.c
index 9227cf2..7bc48cb 100644
--- a/node.c
+++ b/node.c
@@ -45,23 +45,25 @@ r_force_number(NODE *n)
 {
        char *cp;
        char *cpend;
-       char save;
        char *ptr;
-       unsigned int newflags;
        extern double strtod();
 
        if ((n->flags & NUMCUR) != 0)
                return n;
 
-       /* all the conditionals are an attempt to avoid the expensive strtod */
+       /*
+        * we should always set NUMCUR and clear MAYBE_NUM, and we may possibly
+        * change STRING to NUMBER of MAYBE_NUM was set and it's a good numeric
+        * string.
+        */
 
-       /* Note: only set NUMCUR if we actually convert some digits */
+       /* all the conditionals are an attempt to avoid the expensive strtod */
 
+       n->flags |= NUMCUR;
        n->numbr = 0.0;
 
-       if (n->stlen == 0) {
-               return n;
-       }
+       if (n->stlen == 0)
+               goto badnum;
 
        cp = n->stptr;
        /*
@@ -72,20 +74,16 @@ r_force_number(NODE *n)
         * This also allows hexadecimal floating point. Ugh.
         */
        if (! do_posix) {
-               if (is_alpha((unsigned char) *cp)) {
-                       return n;
-               } else if (n->stlen == 4 && is_ieee_magic_val(n->stptr)) {
-                       if ((n->flags & MAYBE_NUM) != 0)
-                               n->flags &= ~(MAYBE_NUM|STRING);
-                       n->flags |= NUMBER|NUMCUR;
+               if (is_alpha((unsigned char) *cp))
+                       goto badnum;
+               else if (n->stlen == 4 && is_ieee_magic_val(n->stptr)) {
                        n->numbr = get_ieee_magic_val(n->stptr);
-
-                       return n;
+                       goto goodnum;
                }
                /* else
                        fall through */
        }
-       /* else not POSIX, so
+       /* else POSIX, so
                fall through */
 
        cpend = cp + n->stlen;
@@ -98,52 +96,36 @@ 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 n;
+               goto badnum;
        }
 
-       if ((n->flags & MAYBE_NUM) != 0) {
-               newflags = NUMBER;
-               n->flags &= ~(MAYBE_NUM|STRING);
-       } else
-               newflags = 0;
-
        if (cpend - cp == 1) {          /* only one character */
                if (isdigit((unsigned char) *cp)) {     /* it's a digit! */
                        n->numbr = (AWKNUM)(*cp - '0');
-                       n->flags |= newflags;
-                       n->flags |= NUMCUR;
                        if (cp == n->stptr)             /* no leading spaces */
                                n->flags |= NUMINT;
+                       goto goodnum;
                }
-               return n;
+               goto badnum;
        }
 
-       if (do_non_decimal_data) {      /* main.c assures false if do_posix */
+       if (do_non_decimal_data         /* main.c assures false if do_posix */
+               && ! do_traditional && get_numbase(cp, true) != 10) {
                errno = 0;
-               if (! do_traditional && get_numbase(cp, true) != 10) {
-                       n->numbr = nondec2awknum(cp, cpend - cp);
-                       n->flags |= NUMCUR;
-                       ptr = cpend;
-                       goto finish;
-               }
+               n->numbr = nondec2awknum(cp, cpend - cp, &ptr);
+       } else {
+               errno = 0;
+               n->numbr = (AWKNUM) strtod((const char *) cp, &ptr);
        }
 
-       errno = 0;
-       save = *cpend;
-       *cpend = '\0';
-       n->numbr = (AWKNUM) strtod((const char *) cp, &ptr);
-
        /* POSIX says trailing space is OK for NUMBER */
        while (isspace((unsigned char) *ptr))
                ptr++;
-       *cpend = save;
-finish:
        if (errno == 0) {
-               if (ptr == cpend) {
-                       n->flags |= newflags;
-                       n->flags |= NUMCUR;
-               }
+               if (ptr == cpend)
+                       goto goodnum;
                /* else keep the leading numeric value without updating flags */
+               /* fall through to badnum*/
        } else {
                errno = 0;
                /*
@@ -152,8 +134,21 @@ finish:
                 * We force the numeric value to 0 in such cases.
                 */
                n->numbr = 0;
+               /*
+                * Or should we accept it as a NUMBER even though strtod
+                * threw an error?
+                */
+               /* fall through to badnum*/
        }
+badnum:
+       n->flags &= ~MAYBE_NUM;
+       return n;
 
+goodnum:
+       if ((n->flags & MAYBE_NUM) != 0) {
+               n->flags &= ~(MAYBE_NUM|STRING);
+               n->flags |= NUMBER;
+       }
        return n;
 }
 
diff --git a/test/ChangeLog b/test/ChangeLog
index c83c80e..2a8fb86 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,15 @@
+2016-06-13         Andrew J. Schorr     <address@hidden>
+
+       * Makefile.am (forcenum, ignrcas3, intarray, lintexp, lintindex,
+       lintint, lintlength, lintset, mpfrstrtonum, mpgforcenum, printfchar,
+       strtonum1): New tests.
+       * forcenum.awk, forcenum.ok, ignrcas3.awk, ignrcas3.ok, intarray.awk,
+       intarray.ok, lintexp.awk, lintexp.ok, lintindex.awk, lintindex.ok,
+       lintint.awk, lintint.ok, lintlength.awk, lintlength.ok, lintset.awk,
+       lintset.ok, mpfrstrtonum.awk, mpfrstrtonum.ok, mpgforcenum.awk,
+       mpgforcenum.ok, printfchar.awk, printfchar.ok, strtonum1.awk,
+       strtonum1.ok: New files.
+
 2016-05-30         Arnold D. Robbins     <address@hidden>
 
        * Makefile.am (fsnul1): New test.
diff --git a/test/Makefile.am b/test/Makefile.am
index 546fce3..050a1dd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -300,6 +300,8 @@ EXTRA_DIST = \
        fnparydl-mpfr.ok \
        fnparydl.awk \
        fnparydl.ok \
+       forcenum.awk \
+       forcenum.ok \
        fordel.awk \
        fordel.ok \
        fork.awk \
@@ -460,6 +462,8 @@ EXTRA_DIST = \
        igncfs.ok \
        ignrcas2.awk \
        ignrcas2.ok \
+       ignrcas3.awk \
+       ignrcas3.ok \
        ignrcase.awk \
        ignrcase.in \
        ignrcase.ok \
@@ -502,6 +506,8 @@ EXTRA_DIST = \
        inplace3.2.bak.ok \
        inputred.awk \
        inputred.ok \
+       intarray.awk \
+       intarray.ok \
        intest.awk \
        intest.ok \
        intformat.awk \
@@ -523,9 +529,19 @@ EXTRA_DIST = \
        leadnl.ok \
        lint.awk \
        lint.ok \
+       lintexp.awk \
+       lintexp.ok \
+       lintindex.awk \
+       lintindex.ok \
+       lintint.awk \
+       lintint.ok \
+       lintlength.awk \
+       lintlength.ok \
        lintold.awk \
        lintold.in \
        lintold.ok \
+       lintset.awk \
+       lintset.ok \
        lintwarn.awk \
        lintwarn.ok \
        litoct.awk \
@@ -605,6 +621,10 @@ EXTRA_DIST = \
        mpfrsort.ok \
        mpfrsqrt.awk \
        mpfrsqrt.ok \
+       mpfrstrtonum.awk \
+       mpfrstrtonum.ok \
+       mpgforcenum.awk \
+       mpgforcenum.ok \
        mtchi18n.awk \
        mtchi18n.in \
        mtchi18n.ok \
@@ -769,6 +789,8 @@ EXTRA_DIST = \
        printfbad3.ok \
        printfbad4.awk \
        printfbad4.ok \
+       printfchar.awk \
+       printfchar.ok \
        printfloat.awk \
        printhuge.awk \
        printhuge.ok \
@@ -979,6 +1001,8 @@ EXTRA_DIST = \
        strtod.ok \
        strtonum.awk \
        strtonum.ok \
+       strtonum1.awk \
+       strtonum1.ok \
        subamp.awk \
        subamp.in \
        subamp.ok \
@@ -1124,7 +1148,7 @@ BASIC_TESTS = \
        octsub ofmt ofmta ofmtbig ofmtfidl ofmts ofs1 onlynl opasnidx opasnslf \
        paramasfunc1 paramasfunc2 \
        paramdup paramres paramtyp paramuninitglobal parse1 parsefld parseme \
-       pcntplus posix2008sub prdupval prec printf0 printf1 prmarscl prmreuse \
+       pcntplus posix2008sub prdupval prec printf0 printf1 printfchar prmarscl 
prmreuse \
        prt1eval prtoeval \
        rand randtest range1 readbuf rebrackloc rebt8b1 redfilnm \
        regeq regexpbrack regexpbrack2 \
@@ -1148,13 +1172,13 @@ GAWK_EXT_TESTS = \
        colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 clos1way6 \
        crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \
        devfd devfd1 devfd2 dumpvars errno exit \
-       fieldwdth fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \
+       fieldwdth forcenum fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen 
\
        functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
        genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops gsubind \
-       icasefs icasers id igncdym igncfs ignrcas2 ignrcase \
+       icasefs icasers id igncdym igncfs ignrcas2 ignrcas3 ignrcase \
        incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \
-       include include2 indirectbuiltin indirectcall indirectcall2 \
-       lint lintold lintwarn \
+       include include2 indirectbuiltin indirectcall indirectcall2 intarray \
+       lint lintexp lintindex lintint lintlength lintold lintset lintwarn \
        manyfiles match1 match2 match3 mbstr1 mbstr2 \
        muldimposix \
        nastyparm negtime next nondec nondec2 \
@@ -1166,7 +1190,7 @@ GAWK_EXT_TESTS = \
        rsstart2 rsstart3 rstest6 shadow shadowbuiltin \
        sortfor sortu split_after_fpat \
        splitarg4 strftime \
-       strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
+       strtonum strtonum1 switch2 symtab1 symtab2 symtab3 symtab4 symtab5 
symtab6 \
        symtab7 symtab8 symtab9 \
        typedregex1 typedregex2 typedregex3 typeof1 typeof2 typeof3 typeof4 \
        timeout \
@@ -1179,7 +1203,7 @@ INET_TESTS = inetdayu inetdayt inetechu inetecht
 MACHINE_TESTS = double1 double2 fmtspcl intformat
 
 MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrieee \
-       mpfrexprange mpfrsort mpfrsqrt mpfrbigint
+       mpfrexprange mpfrsort mpfrsqrt mpfrbigint mpfrstrtonum mpgforcenum
 
 LOCALE_CHARSET_TESTS = \
        asort asorti backbigs1 backsmalls1 backsmalls2 \
@@ -1192,7 +1216,7 @@ SHLIB_TESTS = \
 
 # List of the tests which should be run with --lint option:
 NEED_LINT = \
-       defref fmtspcl lintwarn noeffect nofmtch shadow \
+       defref fmtspcl lintexp lintindex lintint lintlength lintwarn noeffect 
nofmtch shadow \
        uninit2 uninit3 uninit4 uninit5 uninitialized
 
 # List of the tests which should be run with --lint-old option:
@@ -1716,6 +1740,16 @@ nondec2::
        @$(AWK) --non-decimal-data -v a=0x1 -f "$(srcdir)"/address@hidden >_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+intarray::
+       @echo $@
+       @$(AWK) --non-decimal-data -f "$(srcdir)"/address@hidden >_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+forcenum::
+       @echo $@
+       @$(AWK) --non-decimal-data -f "$(srcdir)"/address@hidden >_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 nofile::
        @echo $@
        @$(AWK) '{}' no/such/file >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1962,6 +1996,16 @@ mpfrsqrt:
        @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+mpfrstrtonum:
+       @echo $@
+       @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+mpgforcenum:
+       @echo $@
+       @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 mpfrrem:
        @echo $@
        @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
diff --git a/test/Makefile.in b/test/Makefile.in
index 28365b8..3fe7c9e 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -557,6 +557,8 @@ EXTRA_DIST = \
        fnparydl-mpfr.ok \
        fnparydl.awk \
        fnparydl.ok \
+       forcenum.awk \
+       forcenum.ok \
        fordel.awk \
        fordel.ok \
        fork.awk \
@@ -717,6 +719,8 @@ EXTRA_DIST = \
        igncfs.ok \
        ignrcas2.awk \
        ignrcas2.ok \
+       ignrcas3.awk \
+       ignrcas3.ok \
        ignrcase.awk \
        ignrcase.in \
        ignrcase.ok \
@@ -759,6 +763,8 @@ EXTRA_DIST = \
        inplace3.2.bak.ok \
        inputred.awk \
        inputred.ok \
+       intarray.awk \
+       intarray.ok \
        intest.awk \
        intest.ok \
        intformat.awk \
@@ -780,9 +786,19 @@ EXTRA_DIST = \
        leadnl.ok \
        lint.awk \
        lint.ok \
+       lintexp.awk \
+       lintexp.ok \
+       lintindex.awk \
+       lintindex.ok \
+       lintint.awk \
+       lintint.ok \
+       lintlength.awk \
+       lintlength.ok \
        lintold.awk \
        lintold.in \
        lintold.ok \
+       lintset.awk \
+       lintset.ok \
        lintwarn.awk \
        lintwarn.ok \
        litoct.awk \
@@ -862,6 +878,10 @@ EXTRA_DIST = \
        mpfrsort.ok \
        mpfrsqrt.awk \
        mpfrsqrt.ok \
+       mpfrstrtonum.awk \
+       mpfrstrtonum.ok \
+       mpgforcenum.awk \
+       mpgforcenum.ok \
        mtchi18n.awk \
        mtchi18n.in \
        mtchi18n.ok \
@@ -1026,6 +1046,8 @@ EXTRA_DIST = \
        printfbad3.ok \
        printfbad4.awk \
        printfbad4.ok \
+       printfchar.awk \
+       printfchar.ok \
        printfloat.awk \
        printhuge.awk \
        printhuge.ok \
@@ -1236,6 +1258,8 @@ EXTRA_DIST = \
        strtod.ok \
        strtonum.awk \
        strtonum.ok \
+       strtonum1.awk \
+       strtonum1.ok \
        subamp.awk \
        subamp.in \
        subamp.ok \
@@ -1380,7 +1404,7 @@ BASIC_TESTS = \
        octsub ofmt ofmta ofmtbig ofmtfidl ofmts ofs1 onlynl opasnidx opasnslf \
        paramasfunc1 paramasfunc2 \
        paramdup paramres paramtyp paramuninitglobal parse1 parsefld parseme \
-       pcntplus posix2008sub prdupval prec printf0 printf1 prmarscl prmreuse \
+       pcntplus posix2008sub prdupval prec printf0 printf1 printfchar prmarscl 
prmreuse \
        prt1eval prtoeval \
        rand randtest range1 readbuf rebrackloc rebt8b1 redfilnm \
        regeq regexpbrack regexpbrack2 \
@@ -1404,13 +1428,13 @@ GAWK_EXT_TESTS = \
        colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 clos1way6 \
        crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \
        devfd devfd1 devfd2 dumpvars errno exit \
-       fieldwdth fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \
+       fieldwdth forcenum fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen 
\
        functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
        genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops gsubind \
-       icasefs icasers id igncdym igncfs ignrcas2 ignrcase \
+       icasefs icasers id igncdym igncfs ignrcas2 ignrcas3 ignrcase \
        incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \
-       include include2 indirectbuiltin indirectcall indirectcall2 \
-       lint lintold lintwarn \
+       include include2 indirectbuiltin indirectcall indirectcall2 intarray \
+       lint lintexp lintindex lintint lintlength lintold lintset lintwarn \
        manyfiles match1 match2 match3 mbstr1 mbstr2 \
        muldimposix \
        nastyparm negtime next nondec nondec2 \
@@ -1422,7 +1446,7 @@ GAWK_EXT_TESTS = \
        rsstart2 rsstart3 rstest6 shadow shadowbuiltin \
        sortfor sortu split_after_fpat \
        splitarg4 strftime \
-       strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
+       strtonum strtonum1 switch2 symtab1 symtab2 symtab3 symtab4 symtab5 
symtab6 \
        symtab7 symtab8 symtab9 \
        typedregex1 typedregex2 typedregex3 typeof1 typeof2 typeof3 typeof4 \
        timeout \
@@ -1432,7 +1456,7 @@ EXTRA_TESTS = inftest regtest
 INET_TESTS = inetdayu inetdayt inetechu inetecht
 MACHINE_TESTS = double1 double2 fmtspcl intformat
 MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrieee \
-       mpfrexprange mpfrsort mpfrsqrt mpfrbigint
+       mpfrexprange mpfrsort mpfrsqrt mpfrbigint mpfrstrtonum mpgforcenum
 
 LOCALE_CHARSET_TESTS = \
        asort asorti backbigs1 backsmalls1 backsmalls2 \
@@ -1446,7 +1470,7 @@ SHLIB_TESTS = \
 
 # List of the tests which should be run with --lint option:
 NEED_LINT = \
-       defref fmtspcl lintwarn noeffect nofmtch shadow \
+       defref fmtspcl lintexp lintindex lintint lintlength lintwarn noeffect 
nofmtch shadow \
        uninit2 uninit3 uninit4 uninit5 uninitialized
 
 
@@ -2156,6 +2180,16 @@ nondec2::
        @$(AWK) --non-decimal-data -v a=0x1 -f "$(srcdir)"/address@hidden >_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+intarray::
+       @echo $@
+       @$(AWK) --non-decimal-data -f "$(srcdir)"/address@hidden >_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+forcenum::
+       @echo $@
+       @$(AWK) --non-decimal-data -f "$(srcdir)"/address@hidden >_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 nofile::
        @echo $@
        @$(AWK) '{}' no/such/file >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -2401,6 +2435,16 @@ mpfrsqrt:
        @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+mpfrstrtonum:
+       @echo $@
+       @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+mpgforcenum:
+       @echo $@
+       @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 mpfrrem:
        @echo $@
        @$(AWK) -M -f "$(srcdir)"/address@hidden > _$@ 2>&1
@@ -3384,6 +3428,11 @@ printf1:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+printfchar:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 prmarscl:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -3876,6 +3925,11 @@ igncfs:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+ignrcas3:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 ignrcase:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3906,11 +3960,36 @@ lint:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+lintexp:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+lintindex:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+lintint:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+lintlength:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 lintold:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint-old < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+lintset:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 lintwarn:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
@@ -4046,6 +4125,11 @@ strtonum:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+strtonum1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 switch2:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 125b337..641ee5a 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -695,6 +695,11 @@ printf1:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+printfchar:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 prmarscl:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -1187,6 +1192,11 @@ igncfs:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+ignrcas3:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 ignrcase:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1217,11 +1227,36 @@ lint:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+lintexp:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+lintindex:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+lintint:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+lintlength:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 lintold:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint-old < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+lintset:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 lintwarn:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
@@ -1357,6 +1392,11 @@ strtonum:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+strtonum1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 switch2:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/test/forcenum.awk b/test/forcenum.awk
new file mode 100644
index 0000000..54c536c
--- /dev/null
+++ b/test/forcenum.awk
@@ -0,0 +1,8 @@
+BEGIN {
+       # first, make some strnums
+       nf = split("|5apple|+NaN| 6|0x1az|011Q|027", f, "|")
+       for (i = 1; i <= nf; i++) {
+               x = f[i]+0      # trigger strnum conversion to number or string
+               printf "[%s] -> %g (type %s)\n", f[i], f[i], typeof(f[i])
+       }
+}
diff --git a/test/forcenum.ok b/test/forcenum.ok
new file mode 100644
index 0000000..c74eefc
--- /dev/null
+++ b/test/forcenum.ok
@@ -0,0 +1,7 @@
+[] -> 0 (type string)
+[5apple] -> 5 (type string)
+[+NaN] -> nan (type number)
+[ 6] -> 6 (type number)
+[0x1az] -> 26 (type string)
+[011Q] -> 9 (type string)
+[027] -> 23 (type number)
diff --git a/test/ignrcas3.awk b/test/ignrcas3.awk
new file mode 100644
index 0000000..e74eea6
--- /dev/null
+++ b/test/ignrcas3.awk
@@ -0,0 +1,7 @@
+BEGIN {
+       x = "0"
+       print x+0       # trigger NUMCUR
+       IGNORECASE = x  # should enable ignorecase, since x is a non-null string
+       y = "aBc"
+       print (y ~ /abc/)
+}
diff --git a/test/ignrcas3.ok b/test/ignrcas3.ok
new file mode 100644
index 0000000..0d66ea1
--- /dev/null
+++ b/test/ignrcas3.ok
@@ -0,0 +1,2 @@
+0
+1
diff --git a/test/intarray.awk b/test/intarray.awk
new file mode 100644
index 0000000..2c30bd5
--- /dev/null
+++ b/test/intarray.awk
@@ -0,0 +1,10 @@
+BEGIN {
+       nf = split("5 |05|0x4|00| 5|-0x12| 011|-013", f, "|")
+       for (i = 1; i <= nf; i++) {
+               delete g
+               z = f[i]+0      # trigger numeric conversion
+               g[f[i]]
+               for (x in g)
+                       printf "[%s]\n", x
+       }
+}
diff --git a/test/intarray.ok b/test/intarray.ok
new file mode 100644
index 0000000..d4df7b8
--- /dev/null
+++ b/test/intarray.ok
@@ -0,0 +1,8 @@
+[5 ]
+[05]
+[0x4]
+[00]
+[ 5]
+[-0x12]
+[ 011]
+[-013]
diff --git a/test/lintexp.awk b/test/lintexp.awk
new file mode 100644
index 0000000..082d744
--- /dev/null
+++ b/test/lintexp.awk
@@ -0,0 +1,9 @@
+BEGIN {
+       split("0|0a", f, "|")
+       z = exp(f[1])   # no warning, since strnum converted to number
+       x = f[2]+0      # trigger NUMCUR
+       z = exp(f[2])   # should print a warning
+       x = "0"
+       y = x+0         # trigger NUMCUR
+       z = exp(x)      # should print a warning, since x is still a string!
+}
diff --git a/test/lintexp.ok b/test/lintexp.ok
new file mode 100644
index 0000000..33122f6
--- /dev/null
+++ b/test/lintexp.ok
@@ -0,0 +1,2 @@
+gawk: lintexp.awk:5: warning: exp: received non-numeric argument
+gawk: lintexp.awk:8: warning: exp: received non-numeric argument
diff --git a/test/lintindex.awk b/test/lintindex.awk
new file mode 100644
index 0000000..8e6d7e5
--- /dev/null
+++ b/test/lintindex.awk
@@ -0,0 +1,10 @@
+BEGIN {
+       x = 537
+       y = 3
+       z = index(x, y) # should print lint warning
+       # now that STRCUR has been trigged on x and y, check that we still
+       # get the warning
+       z = index(x, y) # should print lint warning
+       if (z != 2)
+               print "oops"
+}
diff --git a/test/lintindex.ok b/test/lintindex.ok
new file mode 100644
index 0000000..b89db6a
--- /dev/null
+++ b/test/lintindex.ok
@@ -0,0 +1,4 @@
+gawk: lintindex.awk:4: warning: index: received non-string first argument
+gawk: lintindex.awk:4: warning: index: received non-string second argument
+gawk: lintindex.awk:7: warning: index: received non-string first argument
+gawk: lintindex.awk:7: warning: index: received non-string second argument
diff --git a/test/lintint.awk b/test/lintint.awk
new file mode 100644
index 0000000..f4f687b
--- /dev/null
+++ b/test/lintint.awk
@@ -0,0 +1,9 @@
+BEGIN {
+       split("0|0a", f, "|")
+       z = int(f[1])   # no warning, since strnum converted to number
+       x = f[2]+0      # trigger NUMCUR
+       z = int(f[2])   # should print a warning
+       x = "0"
+       y = x+0         # trigger NUMCUR
+       z = int(x)      # should print a warning, since x is still a string!
+}
diff --git a/test/lintint.ok b/test/lintint.ok
new file mode 100644
index 0000000..5bd5d58
--- /dev/null
+++ b/test/lintint.ok
@@ -0,0 +1,2 @@
+gawk: lintint.awk:5: warning: int: received non-numeric argument
+gawk: lintint.awk:8: warning: int: received non-numeric argument
diff --git a/test/lintlength.awk b/test/lintlength.awk
new file mode 100644
index 0000000..ad21791
--- /dev/null
+++ b/test/lintlength.awk
@@ -0,0 +1,6 @@
+BEGIN {
+       x = 5
+       z =  length(x)  # should issue a warning
+       y = (x "")      # trigger STRCUR
+       z = length(x)   # should still issue a warning
+}
diff --git a/test/lintlength.ok b/test/lintlength.ok
new file mode 100644
index 0000000..cb369f7
--- /dev/null
+++ b/test/lintlength.ok
@@ -0,0 +1,2 @@
+gawk: lintlength.awk:3: warning: length: received non-string argument
+gawk: lintlength.awk:5: warning: length: received non-string argument
diff --git a/test/lintset.awk b/test/lintset.awk
new file mode 100644
index 0000000..8d52eeb
--- /dev/null
+++ b/test/lintset.awk
@@ -0,0 +1,5 @@
+BEGIN {
+       split("0a", f)  # set f[0] to a strnum that is really a string
+       LINT = f[1]     # lint should be enabled
+       x = exp("0")    # should generate a warning
+}
diff --git a/test/lintset.ok b/test/lintset.ok
new file mode 100644
index 0000000..7d67c61
--- /dev/null
+++ b/test/lintset.ok
@@ -0,0 +1 @@
+gawk: lintset.awk:4: warning: exp: received non-numeric argument
diff --git a/test/mpfrstrtonum.awk b/test/mpfrstrtonum.awk
new file mode 100644
index 0000000..79d6ad1
--- /dev/null
+++ b/test/mpfrstrtonum.awk
@@ -0,0 +1,5 @@
+BEGIN {
+       x = "011"
+       print x+0       # trigger NUMCUR
+       print strtonum(x)
+}
diff --git a/test/mpfrstrtonum.ok b/test/mpfrstrtonum.ok
new file mode 100644
index 0000000..48a9ed4
--- /dev/null
+++ b/test/mpfrstrtonum.ok
@@ -0,0 +1,2 @@
+11
+9
diff --git a/test/mpgforcenum.awk b/test/mpgforcenum.awk
new file mode 100644
index 0000000..b2d0b6f
--- /dev/null
+++ b/test/mpgforcenum.awk
@@ -0,0 +1,5 @@
+BEGIN {
+       split("5apple", f)      # make a strnum
+       x = f[1]+0              # force strnum conversion to number or string
+       print typeof(f[1])      # should be string
+}
diff --git a/test/mpgforcenum.ok b/test/mpgforcenum.ok
new file mode 100644
index 0000000..ee8a39c
--- /dev/null
+++ b/test/mpgforcenum.ok
@@ -0,0 +1 @@
+string
diff --git a/test/printfchar.awk b/test/printfchar.awk
new file mode 100644
index 0000000..9e703c3
--- /dev/null
+++ b/test/printfchar.awk
@@ -0,0 +1,7 @@
+BEGIN {
+       x[65]
+       for (i in x) {
+               # i should be a string
+               printf "%c\n", i        # should print 1st char of string
+       }
+}
diff --git a/test/printfchar.ok b/test/printfchar.ok
new file mode 100644
index 0000000..1e8b314
--- /dev/null
+++ b/test/printfchar.ok
@@ -0,0 +1 @@
+6
diff --git a/test/strtonum1.awk b/test/strtonum1.awk
new file mode 100644
index 0000000..79d6ad1
--- /dev/null
+++ b/test/strtonum1.awk
@@ -0,0 +1,5 @@
+BEGIN {
+       x = "011"
+       print x+0       # trigger NUMCUR
+       print strtonum(x)
+}
diff --git a/test/strtonum1.ok b/test/strtonum1.ok
new file mode 100644
index 0000000..48a9ed4
--- /dev/null
+++ b/test/strtonum1.ok
@@ -0,0 +1,2 @@
+11
+9

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


hooks/post-receive
-- 
gawk



reply via email to

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