diff options
Diffstat (limited to 'builtin.c')
-rw-r--r-- | builtin.c | 289 |
1 files changed, 200 insertions, 89 deletions
@@ -3,7 +3,7 @@ */ /* - * Copyright (C) 1986, 1988, 1989, 1991-2014 the Free Software Foundation, Inc. + * Copyright (C) 1986, 1988, 1989, 1991-2015 the Free Software Foundation, Inc. * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. @@ -129,10 +129,14 @@ wrerror: if (fp == stdout && errno == EPIPE) gawk_exit(EXIT_FATAL); + /* otherwise die verbosely */ - fatal(_("%s to \"%s\" failed (%s)"), from, - rp ? rp->value : _("standard output"), - errno ? strerror(errno) : _("reason unknown")); + if ((rp != NULL) ? is_non_fatal_redirect(rp->value) : is_non_fatal_std(fp)) + update_ERRNO_int(errno); + else + fatal(_("%s to \"%s\" failed (%s)"), from, + rp ? rp->value : _("standard output"), + errno ? strerror(errno) : _("reason unknown")); } /* do_exp --- exponential function */ @@ -247,7 +251,6 @@ do_fflush(int nargs) return make_number((AWKNUM) status); } -#if MBS_SUPPORT /* strncasecmpmbs --- like strncasecmp (multibyte string version) */ int @@ -327,14 +330,6 @@ index_multibyte_buffer(char* src, char* dest, int len) dest[idx] = mbclen; } } -#else -/* a dummy function */ -static void -index_multibyte_buffer(char* src ATTRIBUTE_UNUSED, char* dest ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) -{ - cant_happen(); -} -#endif /* do_index --- find index of a string */ @@ -345,7 +340,6 @@ do_index(int nargs) const char *p1, *p2; size_t l1, l2; long ret; -#if MBS_SUPPORT bool do_single_byte = false; mbstate_t mbs1, mbs2; @@ -353,7 +347,6 @@ do_index(int nargs) memset(& mbs1, 0, sizeof(mbstate_t)); memset(& mbs2, 0, sizeof(mbstate_t)); } -#endif POP_TWO_SCALARS(s1, s2); @@ -383,7 +376,6 @@ do_index(int nargs) goto out; } -#if MBS_SUPPORT if (gawk_mb_cur_max > 1) { s1 = force_wstring(s1); s2 = force_wstring(s2); @@ -394,14 +386,12 @@ do_index(int nargs) do_single_byte = ((s1->wstlen == 0 && s1->stlen > 0) || (s2->wstlen == 0 && s2->stlen > 0)); } -#endif /* IGNORECASE will already be false if posix */ if (IGNORECASE) { while (l1 > 0) { if (l2 > l1) break; -#if MBS_SUPPORT if (! do_single_byte && gawk_mb_cur_max > 1) { const wchar_t *pos; @@ -412,21 +402,18 @@ do_index(int nargs) ret = pos - s1->wstptr + 1; /* 1-based */ goto out; } else { -#endif - /* - * Could use tolower(*p1) == tolower(*p2) here. - * See discussion in eval.c as to why not. - */ - if (casetable[(unsigned char)*p1] == casetable[(unsigned char)*p2] - && (l2 == 1 || strncasecmp(p1, p2, l2) == 0)) { - ret = 1 + s1->stlen - l1; - break; - } - l1--; - p1++; -#if MBS_SUPPORT + /* + * Could use tolower(*p1) == tolower(*p2) here. + * See discussion in eval.c as to why not. + */ + if (casetable[(unsigned char)*p1] == casetable[(unsigned char)*p2] + && (l2 == 1 || strncasecmp(p1, p2, l2) == 0)) { + ret = 1 + s1->stlen - l1; + break; + } + l1--; + p1++; } -#endif } } else { while (l1 > 0) { @@ -437,7 +424,6 @@ do_index(int nargs) ret = 1 + s1->stlen - l1; break; } -#if MBS_SUPPORT if (! do_single_byte && gawk_mb_cur_max > 1) { const wchar_t *pos; @@ -451,10 +437,6 @@ do_index(int nargs) l1--; p1++; } -#else - l1--; - p1++; -#endif } } out: @@ -532,6 +514,9 @@ do_length(int nargs) * Support for deferred loading of array elements requires that * we use the array length interface even though it isn't * necessary for the built-in array types. + * + * 1/2015: The deferred arrays are gone, but this is probably + * still a good idea. */ size = assoc_length(tmp); @@ -544,7 +529,6 @@ do_length(int nargs) lintwarn(_("length: received non-string argument")); tmp = force_string(tmp); -#if MBS_SUPPORT if (gawk_mb_cur_max > 1) { tmp = force_wstring(tmp); len = tmp->wstlen; @@ -555,7 +539,6 @@ do_length(int nargs) if (len == 0 && tmp->stlen > 0) len = tmp->stlen; } else -#endif len = tmp->stlen; DEREF(tmp); @@ -928,7 +911,10 @@ check_pos: case '*': if (cur == NULL) break; - if (! do_traditional && isdigit((unsigned char) *s1)) { + if (! do_traditional && used_dollar && ! isdigit((unsigned char) *s1)) { + fatal(_("fatal: must use `count$' on all formats or none")); + break; /* silence warnings */ + } else if (! do_traditional && isdigit((unsigned char) *s1)) { int val = 0; for (; n0 > 0 && *s1 && isdigit((unsigned char) *s1); s1++, n0--) { @@ -1058,7 +1044,6 @@ check_pos: (void) force_number(arg); if ((arg->flags & NUMBER) != 0) { uval = get_number_uj(arg); -#if MBS_SUPPORT if (gawk_mb_cur_max > 1) { char buf[100]; wchar_t wc; @@ -1099,7 +1084,7 @@ out0: ; /* else, fall through */ -#endif + cpbuf[0] = uval; prec = 1; cp = cpbuf; @@ -1113,7 +1098,6 @@ out0: */ cp = arg->stptr; prec = 1; -#if MBS_SUPPORT /* * First character can be multiple bytes if * it's a multibyte character. Grr. @@ -1131,7 +1115,6 @@ out0: fw += count - 1; } } -#endif goto pr_tail; case 's': need_format = false; @@ -1660,7 +1643,7 @@ do_printf(int nargs, int redirtype) FILE *fp = NULL; NODE *tmp; struct redirect *rp = NULL; - int errflg; /* not used, sigh */ + int errflg = 0; NODE *redir_exp = NULL; if (nargs == 0) { @@ -1671,7 +1654,7 @@ do_printf(int nargs, int redirtype) redir_exp = TOP(); if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); DEREF(redir_exp); decr_sp(); } @@ -1684,9 +1667,13 @@ do_printf(int nargs, int redirtype) redir_exp = PEEK(nargs); if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); if (rp != NULL) fp = rp->output.fp; + else if (errflg) { + update_ERRNO_int(errflg); + return; + } } else if (do_debug) /* only the debugger can change the default output */ fp = output_fp; else @@ -1805,13 +1792,11 @@ do_substr(int nargs) if (nargs == 2) { /* third arg. missing */ /* use remainder of string */ length = t1->stlen - indx; /* default to bytes */ -#if MBS_SUPPORT if (gawk_mb_cur_max > 1) { t1 = force_wstring(t1); if (t1->wstlen > 0) /* use length of wide char string if we have one */ length = t1->wstlen - indx; } -#endif d_length = length; /* set here in case used in diagnostics, below */ } @@ -1824,12 +1809,10 @@ do_substr(int nargs) } /* get total len of input string, for following checks */ -#if MBS_SUPPORT if (gawk_mb_cur_max > 1) { t1 = force_wstring(t1); src_len = t1->wstlen; } else -#endif src_len = t1->stlen; if (indx >= src_len) { @@ -1847,7 +1830,6 @@ do_substr(int nargs) length = src_len - indx; } -#if MBS_SUPPORT /* force_wstring() already called */ if (gawk_mb_cur_max == 1 || t1->wstlen == t1->stlen) /* single byte case */ @@ -1877,9 +1859,6 @@ do_substr(int nargs) *cp = '\0'; r = make_str_node(substr, cp - substr, ALREADY_MALLOCED); } -#else - r = make_string(t1->stptr + indx, length); -#endif DEREF(t1); return r; @@ -2107,7 +2086,7 @@ void do_print(int nargs, int redirtype) { struct redirect *rp = NULL; - int errflg; /* not used, sigh */ + int errflg = 0; FILE *fp = NULL; int i; NODE *redir_exp = NULL; @@ -2119,9 +2098,13 @@ do_print(int nargs, int redirtype) redir_exp = PEEK(nargs); if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); if (rp != NULL) fp = rp->output.fp; + else if (errflg) { + update_ERRNO_int(errflg); + return; + } } else if (do_debug) /* only the debugger can change the default output */ fp = output_fp; else @@ -2177,13 +2160,13 @@ do_print_rec(int nargs, int redirtype) FILE *fp = NULL; NODE *f0; struct redirect *rp = NULL; - int errflg; /* not used, sigh */ + int errflg = 0; NODE *redir_exp = NULL; assert(nargs == 0); if (redirtype != 0) { redir_exp = TOP(); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); if (rp != NULL) fp = rp->output.fp; DEREF(redir_exp); @@ -2191,6 +2174,11 @@ do_print_rec(int nargs, int redirtype) } else fp = output_fp; + if (errflg) { + update_ERRNO_int(errflg); + return; + } + if (fp == NULL) return; @@ -2211,7 +2199,6 @@ do_print_rec(int nargs, int redirtype) rp->output.gawk_fflush(rp->output.fp, rp->output.opaque); } -#if MBS_SUPPORT /* is_wupper --- function version of iswupper for passing function pointers */ @@ -2276,7 +2263,6 @@ wide_tolower(wchar_t *wstr, size_t wlen) { wide_change_case(wstr, wlen, is_wupper, to_wlower); } -#endif /* do_tolower --- lower case a string */ @@ -2299,14 +2285,11 @@ do_tolower(int nargs) cp < cp2; cp++) if (isupper(*cp)) *cp = tolower(*cp); - } -#if MBS_SUPPORT - else { + } else { force_wstring(t2); wide_tolower(t2->wstptr, t2->wstlen); wstr2str(t2); } -#endif DEREF(t1); return t2; @@ -2333,14 +2316,11 @@ do_toupper(int nargs) cp < cp2; cp++) if (islower(*cp)) *cp = toupper(*cp); - } -#if MBS_SUPPORT - else { + } else { force_wstring(t2); wide_toupper(t2->wstptr, t2->wstlen); wstr2str(t2); } -#endif DEREF(t1); return t2; @@ -2551,13 +2531,12 @@ do_match(int nargs) size_t *wc_indices = NULL; rlength = REEND(rp, t1->stptr) - RESTART(rp, t1->stptr); /* byte length */ -#if MBS_SUPPORT if (rlength > 0 && gawk_mb_cur_max > 1) { t1 = str2wstr(t1, & wc_indices); rlength = wc_indices[rstart + rlength - 1] - wc_indices[rstart] + 1; rstart = wc_indices[rstart]; } -#endif + rstart++; /* now it's 1-based indexing */ /* Build the array only if the caller wants the optional subpatterns */ @@ -2579,12 +2558,10 @@ do_match(int nargs) start = t1->stptr + s; subpat_start = s; subpat_len = len = SUBPATEND(rp, t1->stptr, ii) - s; -#if MBS_SUPPORT if (len > 0 && gawk_mb_cur_max > 1) { subpat_start = wc_indices[s]; subpat_len = wc_indices[s + len - 1] - subpat_start + 1; } -#endif it = make_string(start, len); it->flags |= MAYBE_NUM; /* user input */ @@ -2803,6 +2780,8 @@ do_sub(int nargs, unsigned int flags) if ((t1->flags & NUMCUR) != 0) goto set_how_many; + warning(_("gensub: third argument `%.*s' treated as 1"), + (int) t1->stlen, t1->stptr); how_many = 1; } } else { @@ -2815,8 +2794,8 @@ set_how_many: how_many = d; else how_many = LONG_MAX; - if (d == 0) - warning(_("gensub: third argument of 0 treated as 1")); + if (d <= 0) + warning(_("gensub: third argument %g treated as 1"), d); } DEREF(t1); @@ -3093,6 +3072,146 @@ done: return make_number((AWKNUM) matches); } +/* call_sub --- call do_sub indirectly */ + +NODE * +call_sub(const char *name, int nargs) +{ + unsigned int flags = 0; + NODE *regex, *replace, *glob_flag; + NODE **lhs, *rhs; + NODE *zero = make_number(0.0); + NODE *result; + + if (name[0] == 'g') { + if (name[1] == 'e') + flags = GENSUB; + else + flags = GSUB; + } + + if (flags == 0 || flags == GSUB) { + /* sub or gsub */ + if (nargs != 2) + fatal(_("%s: can be called indirectly only with two arguments"), name); + + replace = POP_STRING(); + regex = POP(); /* the regex */ + /* + * push regex + * push replace + * push $0 + */ + regex = make_regnode(Node_regex, regex); + PUSH(regex); + PUSH(replace); + lhs = r_get_field(zero, (Func_ptr *) 0, true); + nargs++; + PUSH_ADDRESS(lhs); + } else { + /* gensub */ + if (nargs == 4) + rhs = POP(); + else + rhs = NULL; + glob_flag = POP_STRING(); + replace = POP_STRING(); + regex = POP(); /* the regex */ + /* + * push regex + * push replace + * push glob_flag + * if (nargs = 3) { + * push $0 + * nargs++ + * } + */ + regex = make_regnode(Node_regex, regex); + PUSH(regex); + PUSH(replace); + PUSH(glob_flag); + if (rhs == NULL) { + lhs = r_get_field(zero, (Func_ptr *) 0, true); + rhs = *lhs; + UPREF(rhs); + PUSH(rhs); + nargs++; + } + PUSH(rhs); + } + + + unref(zero); + result = do_sub(nargs, flags); + if (flags != GENSUB) + reset_record(); + return result; +} + +/* call_match --- call do_match indirectly */ + +NODE * +call_match(int nargs) +{ + NODE *regex, *text, *array; + NODE *result; + + regex = text = array = NULL; + if (nargs == 3) + array = POP(); + regex = POP(); + + /* Don't need to pop the string just to push it back ... */ + + regex = make_regnode(Node_regex, regex); + PUSH(regex); + + if (array) + PUSH(array); + + result = do_match(nargs); + return result; +} + +/* call_split_func --- call do_split or do_pat_split indirectly */ + +NODE * +call_split_func(const char *name, int nargs) +{ + NODE *regex, *seps; + NODE *result; + + regex = seps = NULL; + if (nargs < 2) + fatal(_("indirect call to %s requires at least two arguments"), + name); + + if (nargs == 4) + seps = POP(); + + if (nargs >= 3) { + regex = POP_STRING(); + regex = make_regnode(Node_regex, regex); + } else { + if (name[0] == 's') { + regex = make_regnode(Node_regex, FS_node->var_value); + regex->re_flags |= FS_DFLT; + } else + regex = make_regnode(Node_regex, FPAT_node->var_value); + nargs++; + } + + /* Don't need to pop the string or the data array */ + + PUSH(regex); + + if (seps) + PUSH(seps); + + result = (name[0] == 's') ? do_split(nargs) : do_patsplit(nargs); + + return result; +} /* make_integer - Convert an integer to a number node. */ @@ -3633,7 +3752,7 @@ do_bindtextdomain(int nargs) return make_string(the_result, strlen(the_result)); } -/* do_div --- do integer division, return quotient and remainder in dest array */ +/* do_intdiv --- do integer division, return quotient and remainder in dest array */ /* * We define the semantics as: @@ -3644,7 +3763,7 @@ do_bindtextdomain(int nargs) */ NODE * -do_div(int nargs) +do_intdiv(int nargs) { NODE *numerator, *denominator, *result; double num, denom, quotient, remainder; @@ -3652,7 +3771,7 @@ do_div(int nargs) result = POP_PARAM(); if (result->type != Node_var_array) - fatal(_("div: third argument is not an array")); + fatal(_("intdiv: third argument is not an array")); assoc_clear(result); denominator = POP_SCALAR(); @@ -3660,9 +3779,9 @@ do_div(int nargs) if (do_lint) { if ((numerator->flags & (NUMCUR|NUMBER)) == 0) - lintwarn(_("div: received non-numeric first argument")); + lintwarn(_("intdiv: received non-numeric first argument")); if ((denominator->flags & (NUMCUR|NUMBER)) == 0) - lintwarn(_("div: received non-numeric second argument")); + lintwarn(_("intdiv: received non-numeric second argument")); } (void) force_number(numerator); @@ -3671,7 +3790,7 @@ do_div(int nargs) denom = double_to_int(get_number_d(denominator)); if (denom == 0.0) - fatal(_("div: division by zero attempted")); + fatal(_("intdiv: division by zero attempted")); quotient = double_to_int(num / denom); /* @@ -3705,7 +3824,6 @@ do_div(int nargs) static size_t mbc_byte_count(const char *ptr, size_t numchars) { -#if MBS_SUPPORT mbstate_t cur_state; size_t sum = 0; int mb_len; @@ -3726,9 +3844,6 @@ mbc_byte_count(const char *ptr, size_t numchars) } return sum; -#else - return numchars; -#endif } /* mbc_char_count --- return number of m.b. chars in string, up to numbytes bytes */ @@ -3736,7 +3851,6 @@ mbc_byte_count(const char *ptr, size_t numchars) static size_t mbc_char_count(const char *ptr, size_t numbytes) { -#if MBS_SUPPORT mbstate_t cur_state; size_t sum = 0; int mb_len; @@ -3759,7 +3873,4 @@ mbc_char_count(const char *ptr, size_t numbytes) } return sum; -#else - return numbytes; -#endif } |