summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew J. Schorr <aschorr@telemetry-investments.com>2016-06-13 18:39:10 -0400
committerAndrew J. Schorr <aschorr@telemetry-investments.com>2016-06-13 18:39:10 -0400
commit18c6b0f85db6683f1d0789e800acfdd35da3ce07 (patch)
tree6f2bd19e71ca42fb2a784451b9486b652fc00090
parent0e02913c51b1d737b4d283901e22c57b954e65ae (diff)
downloadgawk-18c6b0f85db6683f1d0789e800acfdd35da3ce07.tar.gz
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks.
-rw-r--r--ChangeLog74
-rw-r--r--array.c13
-rw-r--r--awk.h37
-rw-r--r--awkgram.c14
-rw-r--r--awkgram.y14
-rw-r--r--builtin.c149
-rw-r--r--debug.c11
-rw-r--r--eval.c90
-rw-r--r--ext.c2
-rw-r--r--gawkapi.c14
-rw-r--r--int_array.c22
-rw-r--r--io.c7
-rw-r--r--mpfr.c48
-rw-r--r--node.c83
-rw-r--r--test/ChangeLog12
-rw-r--r--test/Makefile.am60
-rw-r--r--test/Makefile.in100
-rw-r--r--test/Maketests40
-rw-r--r--test/forcenum.awk8
-rw-r--r--test/forcenum.ok7
-rw-r--r--test/ignrcas3.awk7
-rw-r--r--test/ignrcas3.ok2
-rw-r--r--test/intarray.awk10
-rw-r--r--test/intarray.ok8
-rw-r--r--test/lintexp.awk9
-rw-r--r--test/lintexp.ok2
-rw-r--r--test/lintindex.awk10
-rw-r--r--test/lintindex.ok4
-rw-r--r--test/lintint.awk9
-rw-r--r--test/lintint.ok2
-rw-r--r--test/lintlength.awk6
-rw-r--r--test/lintlength.ok2
-rw-r--r--test/lintset.awk5
-rw-r--r--test/lintset.ok1
-rw-r--r--test/mpfrstrtonum.awk5
-rw-r--r--test/mpfrstrtonum.ok2
-rw-r--r--test/mpgforcenum.awk5
-rw-r--r--test/mpgforcenum.ok1
-rw-r--r--test/printfchar.awk7
-rw-r--r--test/printfchar.ok1
-rw-r--r--test/strtonum1.awk5
-rw-r--r--test/strtonum1.ok2
42 files changed, 622 insertions, 288 deletions
diff --git a/ChangeLog b/ChangeLog
index e6c07ace..9a3636b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,77 @@
+2016-06-12 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * 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 <aschorr@telemetry-investments.com>
* gawkapi.h (awk_ext_func_t): Rename num_expected_args to
diff --git a/array.c b/array.c
index f8051065..afa37954 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 9084e0d3..0cbcf049 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 bd531efb..c40217c4 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 752503cc..81c6945b 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 285b442b..90a1fa07 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 44caea31..a0830621 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 56c6007f..90947dc5 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 c0d6f150..ce040ed7 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 8ee6543b..b961f797 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 a8de3d55..4ba7c98b 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 db903fd7..9d827d75 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 35d1ac62..9d270e63 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 9227cf2d..7bc48cb9 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 c83c80e9..2a8fb86c 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,15 @@
+2016-06-13 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * 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 <arnold@skeeve.com>
* Makefile.am (fsnul1): New test.
diff --git a/test/Makefile.am b/test/Makefile.am
index 546fce3d..050a1dd3 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)"/$@.awk >_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+intarray::
+ @echo $@
+ @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+forcenum::
+ @echo $@
+ @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
nofile::
@echo $@
@$(AWK) '{}' no/such/file >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1962,6 +1996,16 @@ mpfrsqrt:
@$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mpfrstrtonum:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+mpgforcenum:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
mpfrrem:
@echo $@
@$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
diff --git a/test/Makefile.in b/test/Makefile.in
index 28365b83..3fe7c9ee 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)"/$@.awk >_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+intarray::
+ @echo $@
+ @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+forcenum::
+ @echo $@
+ @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
nofile::
@echo $@
@$(AWK) '{}' no/such/file >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -2401,6 +2435,16 @@ mpfrsqrt:
@$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mpfrstrtonum:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+mpgforcenum:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
mpfrrem:
@echo $@
@$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
@@ -3384,6 +3428,11 @@ printf1:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+printfchar:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
prmarscl:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3876,6 +3925,11 @@ igncfs:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+ignrcas3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
ignrcase:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3906,11 +3960,36 @@ lint:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+lintexp:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+lintindex:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+lintint:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+lintlength:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
lintold:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint-old < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+lintset:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
lintwarn:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -4046,6 +4125,11 @@ strtonum:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+strtonum1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
switch2:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 125b337e..641ee5a7 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -695,6 +695,11 @@ printf1:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+printfchar:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
prmarscl:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1187,6 +1192,11 @@ igncfs:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+ignrcas3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
ignrcase:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1217,11 +1227,36 @@ lint:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+lintexp:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+lintindex:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+lintint:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+lintlength:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
lintold:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint-old < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+lintset:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
lintwarn:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1357,6 +1392,11 @@ strtonum:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+strtonum1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
switch2:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/forcenum.awk b/test/forcenum.awk
new file mode 100644
index 00000000..54c536c9
--- /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 00000000..c74eefc7
--- /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 00000000..e74eea64
--- /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 00000000..0d66ea1a
--- /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 00000000..2c30bd5f
--- /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 00000000..d4df7b8c
--- /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 00000000..082d7447
--- /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 00000000..33122f6d
--- /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 00000000..8e6d7e56
--- /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 00000000..b89db6a5
--- /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 00000000..f4f687b0
--- /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 00000000..5bd5d589
--- /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 00000000..ad217912
--- /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 00000000..cb369f7f
--- /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 00000000..8d52eeb4
--- /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 00000000..7d67c614
--- /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 00000000..79d6ad13
--- /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 00000000..48a9ed43
--- /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 00000000..b2d0b6f1
--- /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 00000000..ee8a39c3
--- /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 00000000..9e703c31
--- /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 00000000..1e8b3149
--- /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 00000000..79d6ad13
--- /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 00000000..48a9ed43
--- /dev/null
+++ b/test/strtonum1.ok
@@ -0,0 +1,2 @@
+11
+9