summaryrefslogtreecommitdiff
path: root/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin.c')
-rw-r--r--builtin.c363
1 files changed, 235 insertions, 128 deletions
diff --git a/builtin.c b/builtin.c
index f9cb44c9..e660c0e2 100644
--- a/builtin.c
+++ b/builtin.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2002 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -34,6 +34,10 @@
#include <math.h>
#include "random.h"
+#ifndef SIZE_MAX /* C99 constant, can't rely on it everywhere */
+#define SIZE_MAX ((size_t) -1)
+#endif
+
/* can declare these, since we always use the random shipped with gawk */
extern char *initstate P((unsigned long seed, char *state, long n));
extern char *setstate P((char *state));
@@ -43,7 +47,7 @@ extern void srandom P((unsigned long seed));
extern NODE **fields_arr;
extern int output_is_tty;
-static NODE *sub_common P((NODE *tree, int how_many, int backdigs));
+static NODE *sub_common P((NODE *tree, long how_many, int backdigs));
#ifdef _CRAY
/* Work around a problem in conversion of doubles to exact integers. */
@@ -118,7 +122,7 @@ do_exp(NODE *tree)
double d, res;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("exp: received non-numeric argument"));
d = force_number(tmp);
free_temp(tmp);
@@ -138,7 +142,7 @@ do_exp(NODE *tree)
*/
static FILE *
-stdfile(char *name, size_t len)
+stdfile(const char *name, size_t len)
{
if (len == 11) {
if (STREQN(name, "/dev/stderr", 11))
@@ -159,7 +163,7 @@ do_fflush(NODE *tree)
NODE *tmp;
FILE *fp;
int status = 0;
- char *file;
+ const char *file;
/* fflush() --- flush stdout */
if (tree == NULL) {
@@ -275,13 +279,13 @@ NODE *
do_index(NODE *tree)
{
NODE *s1, *s2;
- register char *p1, *p2;
+ register const char *p1, *p2;
register size_t l1, l2;
long ret;
#ifdef MBS_SUPPORT
size_t mbclen = 0;
mbstate_t mbs1, mbs2;
- if (MB_CUR_MAX > 1) {
+ if (gawk_mb_cur_max > 1) {
memset(&mbs1, 0, sizeof(mbstate_t));
memset(&mbs2, 0, sizeof(mbstate_t));
}
@@ -291,9 +295,9 @@ do_index(NODE *tree)
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
if (do_lint) {
- if ((s1->flags & (STRING|STR)) == 0)
+ if ((s1->flags & (STRING|STRCUR)) == 0)
lintwarn(_("index: received non-string first argument"));
- if ((s2->flags & (STRING|STR)) == 0)
+ if ((s2->flags & (STRING|STRCUR)) == 0)
lintwarn(_("index: received non-string second argument"));
}
force_string(s1);
@@ -320,7 +324,7 @@ do_index(NODE *tree)
if (l2 > l1)
break;
#ifdef MBS_SUPPORT
- if (MB_CUR_MAX > 1) {
+ if (gawk_mb_cur_max > 1) {
if (strncasecmpmbs(p1, mbs1, p2, mbs2, l2) == 0) {
ret = 1 + s1->stlen - l1;
break;
@@ -357,7 +361,7 @@ do_index(NODE *tree)
break;
}
#ifdef MBS_SUPPORT
- if (MB_CUR_MAX > 1) {
+ if (gawk_mb_cur_max > 1) {
mbclen = mbrlen(p1, l1, &mbs1);
if ((mbclen == 1) || (mbclen == (size_t) -1) ||
(mbclen == (size_t) -2) || (mbclen == 0)) {
@@ -403,7 +407,7 @@ do_int(NODE *tree)
double d;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("int: received non-numeric argument"));
d = force_number(tmp);
d = double_to_int(d);
@@ -420,7 +424,7 @@ do_length(NODE *tree)
size_t len;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (STRING|STR)) == 0)
+ if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
lintwarn(_("length: received non-string argument"));
len = force_string(tmp)->stlen;
free_temp(tmp);
@@ -436,7 +440,7 @@ do_log(NODE *tree)
double d, arg;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("log: received non-numeric argument"));
arg = (double) force_number(tmp);
if (arg < 0.0)
@@ -459,9 +463,9 @@ do_log(NODE *tree)
NODE *
format_tree(
const char *fmt_string,
- int n0,
+ size_t n0,
register NODE *carg,
- int num_args)
+ long num_args)
{
/* copy 'l' bytes from 's' to 'obufout' checking for space in the process */
/* difference of pointers should be of ptrdiff_t type, but let us be kind */
@@ -513,7 +517,7 @@ format_tree(
int toofew = FALSE;
char *obuf, *obufout;
size_t osiz, ofre;
- char *chbuf;
+ const char *chbuf;
const char *s0, *s1;
int cs1;
NODE *arg;
@@ -530,15 +534,15 @@ format_tree(
char cpbuf[30]; /* if we have numbers bigger than 30 */
char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */
char *cp;
- char *fill;
+ const char *fill;
double tmpval;
char signchar = FALSE;
size_t len;
int zero_flag = FALSE;
- static char sp[] = " ";
- static char zero_string[] = "0";
- static char lchbuf[] = "0123456789abcdef";
- static char Uchbuf[] = "0123456789ABCDEF";
+ static const char sp[] = " ";
+ static const char zero_string[] = "0";
+ static const char lchbuf[] = "0123456789abcdef";
+ static const char Uchbuf[] = "0123456789ABCDEF";
#define INITIAL_OUT_SIZE 512
emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_tree");
@@ -643,7 +647,7 @@ format_tree(
s1++;
retry:
- if (n0-- <= 0) /* ran out early! */
+ if (n0-- == 0) /* ran out early! */
break;
switch (cs1 = *s1++) {
@@ -654,6 +658,13 @@ check_pos:
goto retry;
case '%':
need_format = FALSE;
+ /*
+ * 29 Oct. 2002:
+ * The C99 standard pages 274 and 279 seem to imply that
+ * since there's no arg converted, the field width doesn't
+ * apply. The code already was that way, but this
+ * comment documents it, at least in the code.
+ */
bchunk_one("%");
s0 = s1;
break;
@@ -708,7 +719,7 @@ check_pos:
if (argnum <= 0)
fatal(_("arg count with `$' must be > 0"));
if (argnum >= num_args)
- fatal(_("arg count %d greater than total number of supplied arguments"), argnum);
+ fatal(_("arg count %ld greater than total number of supplied arguments"), argnum);
} else
fatal(_("`$' not permitted after period in format"));
goto retry;
@@ -1065,7 +1076,7 @@ check_pos:
if (toofew)
fatal("%s\n\t`%s'\n\t%*s%s",
_("not enough arguments to satisfy format string"),
- fmt_string, s1 - fmt_string - 1, "",
+ fmt_string, (int) (s1 - fmt_string - 1), "",
_("^ ran out for this one"));
}
if (do_lint) {
@@ -1106,6 +1117,29 @@ do_sprintf(NODE *tree)
return r;
}
+/*
+ * redirect_to_fp --- return fp for redirection, NULL on failure
+ * or stdout if no redirection, used by all print routines
+ */
+
+static inline FILE *
+redirect_to_fp(NODE *tree, struct redirect **rpp)
+{
+ int errflg; /* not used, sigh */
+ struct redirect *rp;
+
+ if (tree == NULL)
+ return stdout;
+
+ rp = redirect(tree, &errflg);
+ if (rp != NULL) {
+ *rpp = rp;
+ return rp->fp;
+ }
+
+ return NULL;
+}
+
/* do_printf --- perform printf, including redirection */
void
@@ -1123,18 +1157,9 @@ do_printf(NODE *tree)
fatal(_("printf: no arguments"));
}
- if (tree->rnode != NULL) {
- int errflg; /* not used, sigh */
-
- rp = redirect(tree->rnode, &errflg);
- if (rp != NULL) {
- fp = rp->fp;
- if (fp == NULL)
- return;
- } else
- return;
- } else
- fp = stdout;
+ fp = redirect_to_fp(tree->rnode, & rp);
+ if (fp == NULL)
+ return;
tree->lnode->printf_count = tree->printf_count;
tree = do_sprintf(tree->lnode);
efwrite(tree->stptr, sizeof(char), tree->stlen, fp, "printf", rp, TRUE);
@@ -1152,7 +1177,7 @@ do_sqrt(NODE *tree)
double arg;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("sqrt: received non-numeric argument"));
arg = (double) force_number(tmp);
free_temp(tmp);
@@ -1187,48 +1212,66 @@ do_substr(NODE *tree)
lintwarn(_("substr: non-integer start index %g will be truncated"),
d_index);
- indx = d_index - 1; /* awk indices are from 1, C's are from 0 */
+ /* awk indices are from 1, C's are from 0 */
+ if (d_index <= SIZE_MAX)
+ indx = d_index - 1;
+ else
+ indx = SIZE_MAX;
if (tree->rnode->rnode == NULL) { /* third arg. missing */
/* use remainder of string */
length = t1->stlen - indx;
+ d_length = length; /* set here in case used in diagnostics, below */
} else {
t3 = tree_eval(tree->rnode->rnode->lnode);
d_length = force_number(t3);
free_temp(t3);
if (d_length <= 0.0) {
- if (do_lint)
+ if (do_lint == LINT_ALL)
lintwarn(_("substr: length %g is <= 0"), d_length);
+ else if (do_lint == LINT_INVALID && d_length < 0)
+ lintwarn(_("substr: length %g is < 0"), d_length);
free_temp(t1);
return Nnull_string;
}
- if (do_lint && double_to_int(d_length) != d_length)
- lintwarn(
- _("substr: non-integer length %g will be truncated"),
- d_length);
- length = d_length;
+ if (do_lint) {
+ if (double_to_int(d_length) != d_length)
+ lintwarn(
+ _("substr: non-integer length %g will be truncated"),
+ d_length);
+
+ if (d_length > SIZE_MAX)
+ lintwarn(
+ _("substr: length %g too big for string indexing, truncating to %g"),
+ d_length, (double) SIZE_MAX);
+ }
+ if (d_length <= SIZE_MAX)
+ length = d_length;
+ else
+ length = SIZE_MAX;
}
if (t1->stlen == 0) {
- if (do_lint)
+ /* substr("", 1, 0) produces a warning only if LINT_ALL */
+ if (do_lint && (do_lint == LINT_ALL || ((indx | length) != 0)))
lintwarn(_("substr: source string is zero length"));
free_temp(t1);
return Nnull_string;
}
- if ((indx + length) > t1->stlen) {
- if (do_lint)
- lintwarn(
- _("substr: length %d at start index %d exceeds length of first argument (%d)"),
- length, indx+1, t1->stlen);
- length = t1->stlen - indx;
- }
if (indx >= t1->stlen) {
if (do_lint)
- lintwarn(_("substr: start index %d is past end of string"),
- indx+1);
+ lintwarn(_("substr: start index %g is past end of string"),
+ d_index);
free_temp(t1);
return Nnull_string;
}
+ if (length > t1->stlen - 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;
+ }
r = tmp_string(t1->stptr + indx, length);
free_temp(t1);
return r;
@@ -1246,8 +1289,8 @@ do_strftime(NODE *tree)
size_t buflen, bufsize;
char buf[BUFSIZ];
/* FIXME: One day make %d be %e, after C 99 is common. */
- static char def_format[] = "%a %b %d %H:%M:%S %Z %Y";
- char *format;
+ static const char def_format[] = "%a %b %d %H:%M:%S %Z %Y";
+ const char *format;
int formatlen;
/* set defaults first */
@@ -1259,7 +1302,7 @@ do_strftime(NODE *tree)
if (tree != NULL) { /* have args */
if (tree->lnode != NULL) {
NODE *tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (STRING|STR)) == 0)
+ if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
lintwarn(_("strftime: received non-string first argument"));
t1 = force_string(tmp);
format = t1->stptr;
@@ -1274,7 +1317,7 @@ do_strftime(NODE *tree)
if (tree->rnode != NULL) {
t2 = tree_eval(tree->rnode->lnode);
- if (do_lint && (t2->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (t2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("strftime: received non-numeric second argument"));
fclock = (time_t) force_number(t2);
free_temp(t2);
@@ -1315,7 +1358,7 @@ do_strftime(NODE *tree)
/* do_systime --- get the time of day */
NODE *
-do_systime(NODE *tree)
+do_systime(NODE *tree ATTRIBUTE_UNUSED)
{
time_t lclock;
@@ -1337,7 +1380,7 @@ do_mktime(NODE *tree)
char save;
t1 = tree_eval(tree->lnode);
- if (do_lint && (t1->flags & (STRING|STR)) == 0)
+ if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
lintwarn(_("mktime: received non-string argument"));
t1 = force_string(t1);
@@ -1382,7 +1425,7 @@ do_system(NODE *tree)
(void) flush_io(); /* so output is synchronous with gawk's */
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (STRING|STR)) == 0)
+ if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
lintwarn(_("system: received non-string argument"));
cmd = force_string(tmp)->stptr;
@@ -1408,7 +1451,8 @@ do_system(NODE *tree)
os_restore_mode(fileno(stdin));
ret = system(cmd);
- ret = (ret >> 8) & 0xff;
+ if (ret != -1)
+ ret = WEXITSTATUS(ret);
if ((BINMODE & 1) != 0)
os_setbinmode(fileno(stdin), O_BINARY);
@@ -1432,18 +1476,9 @@ do_print(register NODE *tree)
NODE *save;
NODE *tval;
- if (tree->rnode) {
- int errflg; /* not used, sigh */
-
- rp = redirect(tree->rnode, &errflg);
- if (rp != NULL) {
- fp = rp->fp;
- if (fp == NULL)
- return;
- } else
- return;
- } else
- fp = stdout;
+ fp = redirect_to_fp(tree->rnode, & rp);
+ if (fp == NULL)
+ return;
/*
* General idea is to evaluate all the expressions first and
@@ -1493,6 +1528,32 @@ do_print(register NODE *tree)
free(t);
}
+/* do_print_rec --- special case printing of $0, for speed */
+
+void
+do_print_rec(register NODE *tree)
+{
+ struct redirect *rp = NULL;
+ register FILE *fp;
+ register NODE *f0;
+
+ fp = redirect_to_fp(tree->rnode, & rp);
+ if (fp == NULL)
+ return;
+
+ if (! field0_valid)
+ (void) get_field(0L, NULL); /* rebuild record */
+
+ f0 = fields_arr[0];
+ efwrite(f0->stptr, sizeof(char), f0->stlen, fp, "print", rp, FALSE);
+
+ if (ORSlen > 0)
+ efwrite(ORS, sizeof(char), (size_t) ORSlen, fp, "print", rp, TRUE);
+
+ if (rp != NULL && (rp->flag & RED_TWOWAY) != 0)
+ fflush(rp->fp);
+}
+
/* do_tolower --- lower case a string */
NODE *
@@ -1503,37 +1564,37 @@ do_tolower(NODE *tree)
#ifdef MBS_SUPPORT
size_t mbclen = 0;
mbstate_t mbs, prev_mbs;
- if (MB_CUR_MAX > 1)
+ if (gawk_mb_cur_max > 1)
memset(&mbs, 0, sizeof(mbstate_t));
#endif
t1 = tree_eval(tree->lnode);
- if (do_lint && (t1->flags & (STRING|STR)) == 0)
+ 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 (MB_CUR_MAX > 1) {
+ if (gawk_mb_cur_max > 1) {
wchar_t wc;
prev_mbs = mbs;
- mbclen = (size_t) mbrtowc(&wc, cp, cp2 - cp, &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))
- {
+ if (iswupper(wc)) {
wc = towlower(wc);
- wcrtomb(cp, wc, &prev_mbs);
+ wcrtomb((char *) cp, wc, &prev_mbs);
}
/* Adjust the pointer. */
cp += mbclen - 1;
- } else {
+ } else {
/* Otherwise we treat it as a singlebyte character. */
if (ISUPPER(*cp))
*cp = tolower(*cp);
- }
+ }
} else
#endif
if (ISUPPER(*cp))
@@ -1552,37 +1613,37 @@ do_toupper(NODE *tree)
#ifdef MBS_SUPPORT
size_t mbclen = 0;
mbstate_t mbs, prev_mbs;
- if (MB_CUR_MAX > 1)
+ if (gawk_mb_cur_max > 1)
memset(&mbs, 0, sizeof(mbstate_t));
#endif
t1 = tree_eval(tree->lnode);
- if (do_lint && (t1->flags & (STRING|STR)) == 0)
+ 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 (MB_CUR_MAX > 1) {
+ if (gawk_mb_cur_max > 1) {
wchar_t wc;
prev_mbs = mbs;
- mbclen = (size_t) mbrtowc(&wc, cp, cp2 - cp, &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))
- {
+ if (iswlower(wc)) {
wc = towupper(wc);
- wcrtomb(cp, wc, &prev_mbs);
+ wcrtomb((char *) cp, wc, &prev_mbs);
}
/* Adjust the pointer. */
cp += mbclen - 1;
- } else {
+ } else {
/* Otherwise we treat it as a singlebyte character. */
if (ISLOWER(*cp))
*cp = toupper(*cp);
- }
+ }
} else
#endif
if (ISLOWER(*cp))
@@ -1602,9 +1663,9 @@ do_atan2(NODE *tree)
t1 = tree_eval(tree->lnode);
t2 = tree_eval(tree->rnode->lnode);
if (do_lint) {
- if ((t1->flags & (NUM|NUMBER)) == 0)
+ if ((t1->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("atan2: received non-numeric first argument"));
- if ((t2->flags & (NUM|NUMBER)) == 0)
+ if ((t2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("atan2: received non-numeric second argument"));
}
d1 = force_number(t1);
@@ -1623,7 +1684,7 @@ do_sin(NODE *tree)
double d;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("sin: received non-numeric argument"));
d = sin((double) force_number(tmp));
free_temp(tmp);
@@ -1639,7 +1700,7 @@ do_cos(NODE *tree)
double d;
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("cos: received non-numeric argument"));
d = cos((double) force_number(tmp));
free_temp(tmp);
@@ -1653,7 +1714,7 @@ static char state[512];
/* ARGSUSED */
NODE *
-do_rand(NODE *tree)
+do_rand(NODE *tree ATTRIBUTE_UNUSED)
{
if (firstrand) {
(void) initstate((unsigned) 1, state, sizeof state);
@@ -1683,7 +1744,7 @@ do_srand(NODE *tree)
srandom((unsigned int) (save_seed = (long) time((time_t *) 0)));
else {
tmp = tree_eval(tree->lnode);
- if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("srand: received non-numeric argument"));
srandom((unsigned int) (save_seed = (long) force_number(tmp)));
free_temp(tmp);
@@ -1693,7 +1754,7 @@ do_srand(NODE *tree)
/* do_match --- match a regexp, set RSTART and RLENGTH,
* optional third arg is array filled with text of
- * subpatterns enclosed in parens.
+ * subpatterns enclosed in parens and start and len info.
*/
NODE *
@@ -1705,6 +1766,11 @@ do_match(NODE *tree)
Regexp *rp;
regoff_t s;
char *start;
+ char *buf = NULL;
+ char buff[100];
+ size_t amt, oldamt = 0, ilen, slen;
+ char *subsepstr;
+ size_t subseplen;
t1 = force_string(tree_eval(tree->lnode));
tree = tree->rnode;
@@ -1730,14 +1796,50 @@ do_match(NODE *tree)
/* Build the array only if the caller wants the optional subpatterns */
if (dest != NULL) {
- for (ii = 0; (s = SUBPATSTART(rp, t1->stptr, ii)) != -1; ii++) {
+ subsepstr = SUBSEP_node->var_value->stptr;
+ subseplen = SUBSEP_node->var_value->stlen;
+
+ for (ii = 0; ii < NUMSUBPATS(rp, t1->stptr)
+ && (s = SUBPATSTART(rp, t1->stptr, ii)) != -1; ii++) {
start = t1->stptr + s;
len = SUBPATEND(rp, t1->stptr, ii) - s;
it = make_string(start, len);
- it->flags |= MAYBE_NUM;
+ /*
+ * assoc_lookup() does free_temp() on 2nd arg.
+ */
*assoc_lookup(dest, tmp_number((AWKNUM) (ii)), FALSE) = it;
+
+ sprintf(buff, "%d", ii);
+ ilen = strlen(buff);
+ amt = ilen + subseplen + strlen("length") + 2;
+
+ if (oldamt == 0) {
+ emalloc(buf, char *, amt, "do_match");
+ } else if (amt > oldamt) {
+ erealloc(buf, char *, amt, "do_match");
+ }
+ oldamt = amt;
+ memcpy(buf, buff, ilen);
+ memcpy(buf + ilen, subsepstr, subseplen);
+ memcpy(buf + ilen + subseplen, "start", 6);
+
+ slen = ilen + subseplen + 5;
+
+ it = make_number((AWKNUM) s + 1);
+ *assoc_lookup(dest, tmp_string(buf, slen), FALSE) = it;
+
+ memcpy(buf, buff, ilen);
+ memcpy(buf + ilen, subsepstr, subseplen);
+ memcpy(buf + ilen + subseplen, "length", 7);
+
+ slen = ilen + subseplen + 6;
+
+ it = make_number((AWKNUM) len);
+ *assoc_lookup(dest, tmp_string(buf, slen), FALSE) = it;
}
+
+ free(buf);
}
} else { /* match failed */
rstart = 0;
@@ -1817,7 +1919,7 @@ do_match(NODE *tree)
*/
static NODE *
-sub_common(NODE *tree, int how_many, int backdigs)
+sub_common(NODE *tree, long how_many, int backdigs)
{
register char *scan;
register char *bp, *cp;
@@ -1849,13 +1951,14 @@ sub_common(NODE *tree, int how_many, int backdigs)
char *mb_indices;
#endif
- tmp = tree->lnode;
+ tmp = tree->lnode; /* regexp */
rp = re_update(tmp);
- tree = tree->rnode;
+ tree = tree->rnode; /* replacement text */
s = tree->lnode;
+ s = force_string(tree_eval(s));
- tree = tree->rnode;
+ tree = tree->rnode; /* original string */
tmp = tree->lnode;
t = force_string(tree_eval(tmp));
@@ -1863,6 +1966,7 @@ sub_common(NODE *tree, int how_many, int backdigs)
if (research(rp, t->stptr, 0, t->stlen, TRUE) == -1 ||
RESTART(rp, t->stptr) > t->stlen) {
free_temp(t);
+ free_temp(s);
return tmp_number((AWKNUM) 0.0);
}
@@ -1883,7 +1987,6 @@ sub_common(NODE *tree, int how_many, int backdigs)
textlen = t->stlen;
buflen = textlen + 2;
- s = force_string(tree_eval(s));
repl = s->stptr;
replend = repl + s->stlen;
repllen = replend - repl;
@@ -1900,7 +2003,7 @@ sub_common(NODE *tree, int how_many, int backdigs)
* sub(/foo/, "", mystring)
* for example.
*/
- if (MB_CUR_MAX > 1 && repllen > 0) {
+ 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
@@ -1908,7 +2011,7 @@ sub_common(NODE *tree, int how_many, int backdigs)
#endif
for (scan = repl; scan < replend; scan++) {
#ifdef MBS_SUPPORT
- if ((MB_CUR_MAX == 1 || (repllen > 0 && mb_indices[scan - repl] == 1))
+ if ((gawk_mb_cur_max == 1 || (repllen > 0 && mb_indices[scan - repl] == 1))
&& (*scan == '&')) {
#else
if (*scan == '&') {
@@ -1969,9 +2072,13 @@ sub_common(NODE *tree, int how_many, int backdigs)
/*
* If the current match matched the null string,
* and the last match didn't and did a replacement,
- * then skip this one.
+ * and the match of the null string is at the front of
+ * the text (meaning right after end of the previous
+ * replacement), then skip this one.
*/
- if (lastmatchnonzero && matchstart == matchend) {
+ if (matchstart == matchend
+ && lastmatchnonzero
+ && matchstart == text) {
lastmatchnonzero = FALSE;
matches--;
goto empty;
@@ -1983,7 +2090,7 @@ sub_common(NODE *tree, int how_many, int backdigs)
*/
for (scan = repl; scan < replend; scan++)
#ifdef MBS_SUPPORT
- if ((MB_CUR_MAX == 1
+ if ((gawk_mb_cur_max == 1
|| (repllen > 0 && mb_indices[scan - repl] == 1))
&& (*scan == '&'))
#else
@@ -1992,7 +2099,7 @@ sub_common(NODE *tree, int how_many, int backdigs)
for (cp = matchstart; cp < matchend; cp++)
*bp++ = *cp;
#ifdef MBS_SUPPORT
- else if ((MB_CUR_MAX == 1
+ else if ((gawk_mb_cur_max == 1
|| (repllen > 0 && mb_indices[scan - repl] == 1))
&& (*scan == '\\')) {
#else
@@ -2081,7 +2188,7 @@ sub_common(NODE *tree, int how_many, int backdigs)
}
if (after_assign != NULL)
(*after_assign)();
- t->flags &= ~(NUM|NUMBER);
+ t->flags &= ~(NUMCUR|NUMBER);
}
#ifdef MBS_SUPPORT
if (mb_indices != NULL)
@@ -2142,7 +2249,7 @@ do_gensub(NODE *tree)
n3.lnode = target;
n2.rnode = & n3;
- if ((t->flags & (STR|STRING)) != 0) {
+ if ((t->flags & (STRCUR|STRING)) != 0) {
if (t->stlen > 0 && (t->stptr[0] == 'g' || t->stptr[0] == 'G'))
how_many = -1;
else
@@ -2264,9 +2371,9 @@ do_lshift(NODE *tree)
shift = force_number(s2);
if (do_lint) {
- if ((s1->flags & (NUM|NUMBER)) == 0)
+ if ((s1->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("lshift: received non-numeric first argument"));
- if ((s2->flags & (NUM|NUMBER)) == 0)
+ if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("lshift: received non-numeric first argument"));
if (val < 0 || shift < 0)
lintwarn(_("lshift(%lf, %lf): negative values will give strange results"), val, shift);
@@ -2301,9 +2408,9 @@ do_rshift(NODE *tree)
shift = force_number(s2);
if (do_lint) {
- if ((s1->flags & (NUM|NUMBER)) == 0)
+ if ((s1->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("rshift: received non-numeric first argument"));
- if ((s2->flags & (NUM|NUMBER)) == 0)
+ if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("rshift: received non-numeric first argument"));
if (val < 0 || shift < 0)
lintwarn(_("rshift(%lf, %lf): negative values will give strange results"), val, shift);
@@ -2338,9 +2445,9 @@ do_and(NODE *tree)
right = force_number(s2);
if (do_lint) {
- if ((s1->flags & (NUM|NUMBER)) == 0)
+ if ((s1->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("and: received non-numeric first argument"));
- if ((s2->flags & (NUM|NUMBER)) == 0)
+ if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("and: received non-numeric first argument"));
if (left < 0 || right < 0)
lintwarn(_("and(%lf, %lf): negative values will give strange results"), left, right);
@@ -2373,9 +2480,9 @@ do_or(NODE *tree)
right = force_number(s2);
if (do_lint) {
- if ((s1->flags & (NUM|NUMBER)) == 0)
+ if ((s1->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("or: received non-numeric first argument"));
- if ((s2->flags & (NUM|NUMBER)) == 0)
+ if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("or: received non-numeric first argument"));
if (left < 0 || right < 0)
lintwarn(_("or(%lf, %lf): negative values will give strange results"), left, right);
@@ -2408,9 +2515,9 @@ do_xor(NODE *tree)
right = force_number(s2);
if (do_lint) {
- if ((s1->flags & (NUM|NUMBER)) == 0)
+ if ((s1->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("xor: received non-numeric first argument"));
- if ((s2->flags & (NUM|NUMBER)) == 0)
+ if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("xor: received non-numeric first argument"));
if (left < 0 || right < 0)
lintwarn(_("xor(%lf, %lf): negative values will give strange results"), left, right);
@@ -2442,7 +2549,7 @@ do_compl(NODE *tree)
free_temp(tmp);
if (do_lint) {
- if ((tmp->flags & (NUM|NUMBER)) == 0)
+ if ((tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("compl: received non-numeric argument"));
if (d < 0)
lintwarn(_("compl(%lf): negative value will give strange results"), d);
@@ -2561,9 +2668,9 @@ done:
static int
localecategory_from_argument(NODE *tree)
{
- static struct category_table {
+ static const struct category_table {
int val;
- char *name;
+ const char *name;
} cat_tab[] = {
#ifdef LC_ALL
{ LC_ALL, "LC_ALL" },