aboutsummaryrefslogtreecommitdiffstats
path: root/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin.c')
-rw-r--r--builtin.c465
1 files changed, 304 insertions, 161 deletions
diff --git a/builtin.c b/builtin.c
index 5306a5bd..78f16569 100644
--- a/builtin.c
+++ b/builtin.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2004 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2005 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -20,7 +20,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
@@ -32,10 +32,9 @@
#undef INTBITS
#if HAVE_INTTYPES_H
# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
#endif
#include <math.h>
#include "random.h"
@@ -74,9 +73,6 @@ extern int output_is_tty;
static NODE *sub_common P((NODE *tree, long how_many, int backdigs));
-#ifdef STDC_HEADERS
-#include <float.h>
-#endif
/* Assume IEEE-754 arithmetic on pre-C89 hosts. */
#ifndef FLT_RADIX
#define FLT_RADIX 2
@@ -310,6 +306,13 @@ 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 */
@@ -321,15 +324,6 @@ do_index(NODE *tree)
register const char *p1, *p2;
register size_t l1, l2;
long ret;
-#ifdef MBS_SUPPORT
- size_t mbclen = 0;
- mbstate_t mbs1, mbs2;
- if (gawk_mb_cur_max > 1) {
- memset(&mbs1, 0, sizeof(mbstate_t));
- memset(&mbs2, 0, sizeof(mbstate_t));
- }
-#endif
-
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
@@ -364,19 +358,17 @@ do_index(NODE *tree)
break;
#ifdef MBS_SUPPORT
if (gawk_mb_cur_max > 1) {
- if (strncasecmpmbs(p1, mbs1, p2, mbs2, l2) == 0) {
- ret = 1 + s1->stlen - l1;
- break;
- }
- /* Update l1, and p1. */
- mbclen = mbrlen(p1, l1, &mbs1);
- if ((mbclen == 1) || (mbclen == (size_t) -1)
- || (mbclen == (size_t) -2) || (mbclen == 0)) {
- /* We treat it as a singlebyte character. */
- mbclen = 1;
- }
- l1 -= mbclen;
- p1 += mbclen;
+ const wchar_t *pos;
+
+ s1 = force_wstring(s1);
+ s2 = force_wstring(s2);
+
+ pos = wcasestrstr(s1->wstptr, s1->wstlen, s2->wstptr, s2->wstlen);
+ if (pos == NULL)
+ ret = 0;
+ else
+ ret = pos - s1->wstptr + 1; /* 1-based */
+ goto out;
} else {
#endif
/*
@@ -399,20 +391,23 @@ do_index(NODE *tree)
if (l2 > l1)
break;
if (*p1 == *p2
- && (l2 == 1 || STREQN(p1, p2, l2))) {
+ && (l2 == 1 || (l2 > 0 && memcmp(p1, p2, l2) == 0))) {
ret = 1 + s1->stlen - l1;
break;
}
#ifdef MBS_SUPPORT
if (gawk_mb_cur_max > 1) {
- mbclen = mbrlen(p1, l1, &mbs1);
- if ((mbclen == 1) || (mbclen == (size_t) -1) ||
- (mbclen == (size_t) -2) || (mbclen == 0)) {
- /* We treat it as a singlebyte character. */
- mbclen = 1;
- }
- l1 -= mbclen;
- p1 += mbclen;
+ const wchar_t *pos;
+
+ s1 = force_wstring(s1);
+ s2 = force_wstring(s2);
+
+ pos = wstrstr(s1->wstptr, s1->wstlen, s2->wstptr, s2->wstlen);
+ if (pos == NULL)
+ ret = 0;
+ else
+ ret = pos - s1->wstptr + 1; /* 1-based */
+ goto out;
} else {
l1--;
p1++;
@@ -466,12 +461,36 @@ do_length(NODE *tree)
NODE *tmp;
size_t len;
- tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
- lintwarn(_("length: received non-string argument"));
- len = force_string(tmp)->stlen;
- free_temp(tmp);
- return tmp_number((AWKNUM) len);
+ if (tree->lnode->type == Node_var_array
+ || tree->lnode->type == Node_array_ref) {
+ NODE *array_var = tree->lnode;
+
+ if (array_var->type == Node_array_ref)
+ array_var = array_var->orig_array;
+
+ if (do_lint)
+ lintwarn(_("`length(array)' is a gawk extension"));
+ if (do_posix)
+ goto normal; /* will die as fatal error */
+
+ return tmp_number((AWKNUM) array_var->table_size);
+ } else {
+normal:
+ tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
+ lintwarn(_("length: received non-string argument"));
+ tmp = force_string(tmp);
+#ifdef MBS_SUPPORT
+ if (gawk_mb_cur_max > 1) {
+ tmp = force_wstring(tmp);
+ len = tmp->wstlen;
+ } else
+#endif
+ len = tmp->stlen;
+
+ free_temp(tmp);
+ return tmp_number((AWKNUM) len);
+ }
}
/* do_log --- the log function */
@@ -514,7 +533,7 @@ format_tree(
/* difference of pointers should be of ptrdiff_t type, but let us be kind */
#define bchunk(s, l) if (l) { \
while ((l) > ofre) { \
- long olen = obufout - obuf; \
+ size_t olen = obufout - obuf; \
erealloc(obuf, char *, osiz * 2, "format_tree"); \
ofre += osiz; \
osiz *= 2; \
@@ -528,7 +547,7 @@ format_tree(
/* copy one byte from 's' to 'obufout' checking for space in the process */
#define bchunk_one(s) { \
if (ofre < 1) { \
- long olen = obufout - obuf; \
+ size_t olen = obufout - obuf; \
erealloc(obuf, char *, osiz * 2, "format_tree"); \
ofre += osiz; \
osiz *= 2; \
@@ -540,7 +559,7 @@ format_tree(
/* Is there space for something L big in the buffer? */
#define chksize(l) if ((l) > ofre) { \
- long olen = obufout - obuf; \
+ size_t olen = obufout - obuf; \
erealloc(obuf, char *, osiz * 2, "format_tree"); \
obufout = obuf + olen; \
ofre += osiz; \
@@ -578,7 +597,7 @@ format_tree(
char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */
char *cp;
const char *fill;
- double tmpval;
+ AWKNUM tmpval;
char signchar = FALSE;
size_t len;
int zero_flag = FALSE;
@@ -593,7 +612,7 @@ format_tree(
emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_tree");
obufout = obuf;
osiz = INITIAL_OUT_SIZE;
- ofre = osiz - 1;
+ ofre = osiz - 2;
/*
* Icky problem. If the args make a nested call to printf/sprintf,
@@ -833,7 +852,7 @@ check_pos:
case '#':
alt = TRUE;
goto check_pos;
-#if ENABLE_NLS && defined(HAVE_LOCALE_H)
+#if defined(HAVE_LOCALE_H)
case '\'':
quote_flag = TRUE;
goto check_pos;
@@ -950,9 +969,11 @@ check_pos:
ii = jj = 0;
do {
*--cp = (char) ('0' + uval % 10);
-#if ENABLE_NLS && defined(HAVE_LOCALE_H)
+ uval /= 10;
+#if defined(HAVE_LOCALE_H)
if (quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) {
- *--cp = loc.thousands_sep[0]; /* XXX - assumption it's one char */
+ if (uval) /* only add if more digits coming */
+ *--cp = loc.thousands_sep[0]; /* XXX - assumption it's one char */
if (loc.grouping[ii+1] == 0)
jj = 0; /* keep using current val in loc.grouping[ii] */
else if (loc.grouping[ii+1] == CHAR_MAX)
@@ -963,7 +984,6 @@ check_pos:
}
}
#endif
- uval /= 10;
} while (uval > 0);
/* add more output digits to match the precision */
@@ -1052,9 +1072,11 @@ check_pos:
ii = jj = 0;
do {
*--cp = chbuf[uval % base];
-#if ENABLE_NLS && defined(HAVE_LOCALE_H)
+ uval /= base;
+#if defined(HAVE_LOCALE_H)
if (base == 10 && quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) {
- *--cp = loc.thousands_sep[0]; /* XXX --- assumption it's one char */
+ if (uval) /* only add if more digits coming */
+ *--cp = loc.thousands_sep[0]; /* XXX --- assumption it's one char */
if (loc.grouping[ii+1] == 0)
jj = 0; /* keep using current val in loc.grouping[ii] */
else if (loc.grouping[ii+1] == CHAR_MAX)
@@ -1065,7 +1087,6 @@ check_pos:
}
}
#endif
- uval /= base;
} while (uval > 0);
/* add more output digits to match the precision */
@@ -1130,7 +1151,13 @@ check_pos:
if (! have_prec)
prec = DEFAULT_G_PRECISION;
chksize(fw + prec + 9); /* 9 == slop */
-
+#ifdef VAXCRTL
+ /* pre-ANSI library doesn't handle '0' flag
+ correctly in many cases; reject it */
+ if (zero_flag
+ && (lj || (signchar && signchar != '+')))
+ zero_flag = FALSE;
+#endif
cp = cpbuf;
*cp++ = '%';
if (lj)
@@ -1289,6 +1316,7 @@ do_substr(NODE *tree)
register size_t indx;
size_t length;
double d_index, d_length;
+ size_t src_len;
t1 = force_string(tree_eval(tree->lnode));
t2 = tree_eval(tree->rnode->lnode);
@@ -1352,21 +1380,71 @@ do_substr(NODE *tree)
free_temp(t1);
return Nnull_string;
}
- if (indx >= t1->stlen) {
+
+ /* get total len of input string, for following checks */
+#ifdef 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) {
if (do_lint)
lintwarn(_("substr: start index %g is past end of string"),
d_index);
free_temp(t1);
return Nnull_string;
}
- if (length > t1->stlen - indx) {
+ if (length > src_len - indx) {
if (do_lint)
lintwarn(
_("substr: length %g at start index %g exceeds length of first argument (%lu)"),
- d_length, d_index, (unsigned long int) t1->stlen);
- length = t1->stlen - indx;
+ d_length, d_index, (unsigned long int) src_len);
+ length = src_len - indx;
+ }
+
+#ifdef MBS_SUPPORT
+ if (gawk_mb_cur_max > 1) {
+ /* multibyte case, more work */
+ size_t result;
+ wchar_t *wp;
+ mbstate_t mbs;
+ char *substr, *cp;
+
+ /* force_wstring() already called */
+
+ if (t1->stlen == t1->wstlen)
+ goto single_byte_case;
+
+ /*
+ * Convert the wide chars in t1->wstptr back into m.b. chars.
+ * This is pretty grotty, but it's the most straightforward
+ * way to do things.
+ */
+ memset(& mbs, 0, sizeof(mbs));
+ emalloc(substr, char *, (length * gawk_mb_cur_max) + 2, "do_substr");
+ wp = t1->wstptr + indx;
+ for (cp = substr; length > 0; length--) {
+ result = wcrtomb(cp, *wp, & mbs);
+ if (result == (size_t) -1) /* what to do? break seems best */
+ break;
+ cp += result;
+ wp++;
+ }
+ *cp = '\0';
+ r = make_str_node(substr, cp - substr, ALREADY_MALLOCED);
+ r->flags |= TEMP;
+ } else {
+ /* single byte case, easy */
+single_byte_case:
+ r = tmp_string(t1->stptr + indx, length);
}
+#else
r = tmp_string(t1->stptr + indx, length);
+#endif
+
free_temp(t1);
return r;
}
@@ -1652,51 +1730,117 @@ do_print_rec(register NODE *tree)
fflush(rp->fp);
}
+#ifdef MBS_SUPPORT
+/* wide_tolower_toupper --- lower- or uppercase a multibute string */
+
+typedef int (*isw_func)(wint_t);
+typedef wint_t (*tow_func)(wint_t);
+
+static NODE *
+wide_tolower_toupper(NODE *t1, isw_func iswu, tow_func towl)
+{
+ register unsigned char *cp, *cpe;
+ register unsigned char *cp2;
+ size_t mbclen;
+ mbstate_t mbs, prev_mbs;
+ wchar_t wc;
+ NODE *t2;
+ /*
+ * Since the lowercase char and its uppercase equivalent may occupy
+ * different number of bytes (Turkish `i'), we cannot say the length
+ * of the output string.
+ * This approach is adapted from format_tree().
+ */
+ unsigned char *obuf;
+ size_t osiz, ofre;
+
+ /*
+ * Better 2 spare bytes than 1, consistently with make_str_node().
+ * And we need gawk_mb_cur_max free bytes before we convert the last
+ * char, so we add (gawk_mb_cur_max - 1).
+ */
+ osiz = t1->stlen + 2 + (gawk_mb_cur_max - 1);
+ ofre = osiz - 2;
+ emalloc(obuf, char *, osiz, "wide_tolower_toupper");
+
+ memset(&mbs, 0, sizeof(mbstate_t));
+ cp = (unsigned char *)t1->stptr;
+ cpe = (unsigned char *)(t1->stptr + t1->stlen);
+ cp2 = obuf;
+ while (cp < cpe) {
+ if (ofre < gawk_mb_cur_max) {
+ size_t olen = cp2 - obuf;
+ ofre += osiz;
+ osiz *= 2;
+ erealloc(obuf, char *, osiz, "wide_tolower_toupper");
+ cp2 = obuf + olen;
+ }
+ prev_mbs = mbs;
+ mbclen = (size_t) mbrtowc(&wc, (char *) cp, cpe - cp,
+ &mbs);
+ if (mbclen == 0 || mbclen == (size_t) -1 || mbclen == (size_t) -2) {
+ /* Null wide char, or a problem appeared. */
+ *cp2++ = *cp++;
+ ofre--;
+ continue;
+ }
+
+ /* If the character doesn't need change, copy it. */
+ if (!(*iswu)(wc)) {
+ ofre -= mbclen;
+ while (mbclen--)
+ *cp2++ = *cp++;
+ continue;
+ }
+
+ /* Increment the input pointer. */
+ cp += mbclen;
+
+ /* Write the modified wide character. */
+ mbclen = wcrtomb((char *) cp2, (*towl)(wc), &prev_mbs);
+
+ if (mbclen > 0 && mbclen < (size_t) -2) {
+ /* Increment the output pointer. */
+ cp2 += mbclen;
+ ofre -= mbclen;
+ } else {
+ /* A problem appeared. */
+ cp2++;
+ ofre--;
+ }
+ }
+ t2 = make_str_node(obuf, cp2 - obuf, ALREADY_MALLOCED);
+ t2->flags |= TEMP;
+ return t2;
+}
+#endif
+
/* do_tolower --- lower case a string */
NODE *
do_tolower(NODE *tree)
{
NODE *t1, *t2;
- register unsigned char *cp, *cp2;
-#ifdef MBS_SUPPORT
- size_t mbclen = 0;
- mbstate_t mbs, prev_mbs;
- if (gawk_mb_cur_max > 1)
- memset(&mbs, 0, sizeof(mbstate_t));
-#endif
t1 = tree_eval(tree->lnode);
if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
lintwarn(_("tolower: received non-string argument"));
t1 = force_string(t1);
- t2 = tmp_string(t1->stptr, t1->stlen);
- for (cp = (unsigned char *)t2->stptr,
- cp2 = (unsigned char *)(t2->stptr + t2->stlen); cp < cp2; cp++)
+
#ifdef MBS_SUPPORT
- if (gawk_mb_cur_max > 1) {
- wchar_t wc;
- prev_mbs = mbs;
- mbclen = (size_t) mbrtowc(&wc, (char *) cp, cp2 - cp,
- &mbs);
- if ((mbclen != 1) && (mbclen != (size_t) -1) &&
- (mbclen != (size_t) -2) && (mbclen != 0)) {
- /* a multibyte character. */
- if (iswupper(wc)) {
- wc = towlower(wc);
- wcrtomb((char *) cp, wc, &prev_mbs);
- }
- /* Adjust the pointer. */
- cp += mbclen - 1;
- } else {
- /* Otherwise we treat it as a singlebyte character. */
- if (ISUPPER(*cp))
- *cp = tolower(*cp);
- }
- } else
+ if (gawk_mb_cur_max > 1)
+ t2 = wide_tolower_toupper(t1, iswupper, towlower);
+ else
#endif
- if (ISUPPER(*cp))
- *cp = TOLOWER(*cp);
+ {
+ register unsigned char *cp, *cpe;
+
+ t2 = tmp_string(t1->stptr, t1->stlen);
+ for (cp = (unsigned char *)t2->stptr,
+ cpe = (unsigned char *)(t2->stptr + t2->stlen); cp < cpe; cp++)
+ if (ISUPPER(*cp))
+ *cp = TOLOWER(*cp);
+ }
free_temp(t1);
return t2;
}
@@ -1707,45 +1851,26 @@ NODE *
do_toupper(NODE *tree)
{
NODE *t1, *t2;
- register unsigned char *cp, *cp2;
-#ifdef MBS_SUPPORT
- size_t mbclen = 0;
- mbstate_t mbs, prev_mbs;
- if (gawk_mb_cur_max > 1)
- memset(&mbs, 0, sizeof(mbstate_t));
-#endif
t1 = tree_eval(tree->lnode);
if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
lintwarn(_("toupper: received non-string argument"));
t1 = force_string(t1);
- t2 = tmp_string(t1->stptr, t1->stlen);
- for (cp = (unsigned char *)t2->stptr,
- cp2 = (unsigned char *)(t2->stptr + t2->stlen); cp < cp2; cp++)
+
#ifdef MBS_SUPPORT
- if (gawk_mb_cur_max > 1) {
- wchar_t wc;
- prev_mbs = mbs;
- mbclen = (size_t) mbrtowc(&wc, (char *) cp, cp2 - cp,
- &mbs);
- if ((mbclen != 1) && (mbclen != (size_t) -1) &&
- (mbclen != (size_t) -2) && (mbclen != 0)) {
- /* a multibyte character. */
- if (iswlower(wc)) {
- wc = towupper(wc);
- wcrtomb((char *) cp, wc, &prev_mbs);
- }
- /* Adjust the pointer. */
- cp += mbclen - 1;
- } else {
- /* Otherwise we treat it as a singlebyte character. */
- if (ISLOWER(*cp))
- *cp = toupper(*cp);
- }
- } else
+ if (gawk_mb_cur_max > 1)
+ t2 = wide_tolower_toupper(t1, iswlower, towupper);
+ else
#endif
- if (ISLOWER(*cp))
- *cp = TOUPPER(*cp);
+ {
+ register unsigned char *cp, *cpe;
+
+ t2 = tmp_string(t1->stptr, t1->stlen);
+ for (cp = (unsigned char *)t2->stptr,
+ cpe = (unsigned char *)(t2->stptr + t2->stlen); cp < cpe; cp++)
+ if (ISLOWER(*cp))
+ *cp = TOUPPER(*cp);
+ }
free_temp(t1);
return t2;
}
@@ -1866,7 +1991,7 @@ do_match(NODE *tree)
{
NODE *t1, *dest, *it;
int rstart, len, ii;
- AWKNUM rlength;
+ int rlength;
Regexp *rp;
regoff_t s;
char *start;
@@ -1889,10 +2014,19 @@ do_match(NODE *tree)
assoc_clear(dest);
}
- rstart = research(rp, t1->stptr, 0, t1->stlen, TRUE);
+ rstart = research(rp, t1->stptr, 0, t1->stlen, RE_NEED_START);
if (rstart >= 0) { /* match succeded */
- rstart++; /* 1-based indexing */
- rlength = REEND(rp, t1->stptr) - RESTART(rp, t1->stptr);
+ size_t *wc_indices = NULL;
+
+ rlength = REEND(rp, t1->stptr) - RESTART(rp, t1->stptr); /* byte length */
+#ifdef MBS_SUPPORT
+ if (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 */
if (dest != NULL) {
@@ -1905,8 +2039,18 @@ do_match(NODE *tree)
* matched even if all of them did not.
*/
if ((s = SUBPATSTART(rp, t1->stptr, ii)) != -1) {
+ size_t subpat_start;
+ size_t subpat_len;
+
start = t1->stptr + s;
- len = SUBPATEND(rp, t1->stptr, ii) - s;
+ subpat_start = s;
+ subpat_len = len = SUBPATEND(rp, t1->stptr, ii) - s;
+#ifdef MBS_SUPPORT
+ if (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);
/*
@@ -1930,7 +2074,7 @@ do_match(NODE *tree)
slen = ilen + subseplen + 5;
- it = make_number((AWKNUM) s + 1);
+ it = make_number((AWKNUM) subpat_start + 1);
*assoc_lookup(dest, tmp_string(buf, slen), FALSE) = it;
memcpy(buf, buff, ilen);
@@ -1939,22 +2083,24 @@ do_match(NODE *tree)
slen = ilen + subseplen + 6;
- it = make_number((AWKNUM) len);
+ it = make_number((AWKNUM) subpat_len);
*assoc_lookup(dest, tmp_string(buf, slen), FALSE) = it;
}
}
free(buf);
+ if (wc_indices != NULL)
+ free(wc_indices);
}
} else { /* match failed */
rstart = 0;
- rlength = -1.0;
+ rlength = -1;
}
free_temp(t1);
unref(RSTART_node->var_value);
RSTART_node->var_value = make_number((AWKNUM) rstart);
unref(RLENGTH_node->var_value);
- RLENGTH_node->var_value = make_number(rlength);
+ RLENGTH_node->var_value = make_number((AWKNUM) rlength);
return tmp_number((AWKNUM) rstart);
}
@@ -2079,9 +2225,7 @@ sub_common(NODE *tree, long how_many, int backdigs)
int global = (how_many == -1);
long current;
int lastmatchnonzero;
-#ifdef MBS_SUPPORT
- char *mb_indices;
-#endif
+ char *mb_indices = NULL;
tmp = tree->lnode; /* regexp */
rp = re_update(tmp);
@@ -2095,7 +2239,7 @@ sub_common(NODE *tree, long how_many, int backdigs)
t = force_string(tree_eval(tmp));
/* do the search early to avoid work on non-match */
- if (research(rp, t->stptr, 0, t->stlen, TRUE) == -1 ||
+ if (research(rp, t->stptr, 0, t->stlen, RE_NEED_START) == -1 ||
RESTART(rp, t->stptr) > t->stlen) {
free_temp(t);
free_temp(s);
@@ -2126,7 +2270,7 @@ sub_common(NODE *tree, long how_many, int backdigs)
buf[buflen] = '\0';
buf[buflen + 1] = '\0';
ampersands = 0;
-#ifdef MBS_SUPPORT
+
/*
* Some systems' malloc() can't handle being called with an
* argument of zero. Thus we have to have some special case
@@ -2138,16 +2282,11 @@ sub_common(NODE *tree, long how_many, int backdigs)
if (gawk_mb_cur_max > 1 && repllen > 0) {
emalloc(mb_indices, char *, repllen * sizeof(char), "sub_common");
index_multibyte_buffer(repl, mb_indices, repllen);
- } else
- mb_indices = NULL;
-#endif
+ }
+
for (scan = repl; scan < replend; scan++) {
-#ifdef MBS_SUPPORT
if ((gawk_mb_cur_max == 1 || (repllen > 0 && mb_indices[scan - repl] == 1))
- && (*scan == '&')) {
-#else
- if (*scan == '&') {
-#endif
+ && (*scan == '&')) {
repllen--;
ampersands++;
} else if (*scan == '\\') {
@@ -2230,22 +2369,18 @@ sub_common(NODE *tree, long how_many, int backdigs)
*/
for (scan = repl; scan < replend; scan++)
if (*scan == '&'
-#ifdef MBS_SUPPORT
/*
* Don't test repllen here. A simple "&" could
* end up with repllen == 0.
*/
&& (gawk_mb_cur_max == 1
|| mb_indices[scan - repl] == 1)
-#endif
) {
for (cp = matchstart; cp < matchend; cp++)
*bp++ = *cp;
} else if (*scan == '\\'
-#ifdef MBS_SUPPORT
&& (gawk_mb_cur_max == 1
|| (repllen > 0 && mb_indices[scan - repl] == 1))
-#endif
) {
if (backdigs) { /* gensub, behave sanely */
if (ISDIGIT(scan[1])) {
@@ -2310,7 +2445,7 @@ sub_common(NODE *tree, long how_many, int backdigs)
if ((current >= how_many && !global)
|| ((long) textlen <= 0 && matchstart == matchend)
- || research(rp, t->stptr, text - t->stptr, textlen, TRUE) == -1)
+ || research(rp, t->stptr, text - t->stptr, textlen, RE_NEED_START) == -1)
break;
}
@@ -2338,10 +2473,9 @@ sub_common(NODE *tree, long how_many, int backdigs)
(*after_assign)();
t->flags &= ~(NUMCUR|NUMBER);
}
-#ifdef MBS_SUPPORT
if (mb_indices != NULL)
free(mb_indices);
-#endif
+
return tmp_number((AWKNUM) matches);
}
@@ -2400,10 +2534,17 @@ do_gensub(NODE *tree)
if ((t->flags & (STRCUR|STRING)) != 0) {
if (t->stlen > 0 && (t->stptr[0] == 'g' || t->stptr[0] == 'G'))
how_many = -1;
- else
+ else {
+ d = force_number(t);
+
+ if ((t->flags & NUMCUR) != 0)
+ goto set_how_many;
+
how_many = 1;
+ }
} else {
d = force_number(t);
+set_how_many:
if (d < 1)
how_many = 1;
else if (d < LONG_MAX)
@@ -2541,6 +2682,7 @@ static NODE *
tmp_integer(uintmax_t n)
{
#ifdef HAVE_UINTMAX_T
+/* #ifndef LDBL_MANT_DIG */
/*
* If uintmax_t is so wide that AWKNUM cannot represent all its
* values, strip leading nonzero bits of integers that are so large
@@ -2551,6 +2693,7 @@ tmp_integer(uintmax_t n)
*/
if (AWKNUM_FRACTION_BITS < CHAR_BIT * sizeof n)
n &= ((uintmax_t) 1 << AWKNUM_FRACTION_BITS) - 1;
+/* #endif */ /* LDBL_MANT_DIG */
#endif /* HAVE_UINTMAX_T */
return tmp_number((AWKNUM) n);
@@ -2773,16 +2916,16 @@ NODE *
do_strtonum(NODE *tree)
{
NODE *tmp;
- double d;
+ AWKNUM d;
tmp = tree_eval(tree->lnode);
if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
- d = (double) force_number(tmp);
- else if (isnondecimal(tmp->stptr))
+ d = (AWKNUM) force_number(tmp);
+ else if (isnondecimal(tmp->stptr, TRUE))
d = nondec2awknum(tmp->stptr, tmp->stlen);
else
- d = (double) force_number(tmp);
+ d = (AWKNUM) force_number(tmp);
free_temp(tmp);
return tmp_number((AWKNUM) d);