diff options
author | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2016-06-13 18:39:10 -0400 |
---|---|---|
committer | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2016-06-13 18:39:10 -0400 |
commit | 18c6b0f85db6683f1d0789e800acfdd35da3ce07 (patch) | |
tree | 6f2bd19e71ca42fb2a784451b9486b652fc00090 | |
parent | 0e02913c51b1d737b4d283901e22c57b954e65ae (diff) | |
download | egawk-18c6b0f85db6683f1d0789e800acfdd35da3ce07.tar.gz egawk-18c6b0f85db6683f1d0789e800acfdd35da3ce07.tar.bz2 egawk-18c6b0f85db6683f1d0789e800acfdd35da3ce07.zip |
Fix usage of scalar type flag bits and fix some bugs in numeric conversions and lint checks.
42 files changed, 622 insertions, 288 deletions
@@ -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 @@ -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); @@ -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) { @@ -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)); } @@ -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)); } @@ -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"; @@ -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)); @@ -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); @@ -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 */ @@ -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; @@ -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 @@ -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")); } @@ -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 |