aboutsummaryrefslogtreecommitdiffstats
path: root/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin.c')
-rw-r--r--builtin.c356
1 files changed, 268 insertions, 88 deletions
diff --git a/builtin.c b/builtin.c
index 44e0b85c..9134e024 100644
--- a/builtin.c
+++ b/builtin.c
@@ -80,8 +80,10 @@ extern FILE *output_fp;
#define POP_TWO_SCALARS(s1, s2) \
s2 = POP_SCALAR(); \
s1 = POP(); \
-if ((s1)->type == Node_var_array) \
- DEREF(s2), fatal(_("attempt to use array `%s' in a scalar context"), array_vname(s1)), 0
+do { if (s1->type == Node_var_array) { \
+DEREF(s2); \
+fatal(_("attempt to use array `%s' in a scalar context"), array_vname(s1)); \
+}} while (FALSE)
/*
@@ -133,7 +135,7 @@ do_exp(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("exp: received non-numeric argument"));
- d = force_number(tmp);
+ d = force_number(tmp)->numbr;
DEREF(tmp);
errno = 0;
res = exp(d);
@@ -334,8 +336,10 @@ do_index(int nargs)
if ((s2->flags & (STRING|STRCUR)) == 0)
lintwarn(_("index: received non-string second argument"));
}
- force_string(s1);
- force_string(s2);
+
+ s1 = force_string(s1);
+ s2 = force_string(s2);
+
p1 = s1->stptr;
p2 = s2->stptr;
l1 = s1->stlen;
@@ -455,7 +459,7 @@ do_int(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("int: received non-numeric argument"));
- d = force_number(tmp);
+ d = force_number(tmp)->numbr;
d = double_to_int(d);
DEREF(tmp);
return make_number((AWKNUM) d);
@@ -502,7 +506,7 @@ do_length(int nargs)
if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
lintwarn(_("length: received non-string argument"));
- (void) force_string(tmp);
+ tmp = force_string(tmp);
#if MBS_SUPPORT
if (gawk_mb_cur_max > 1) {
@@ -533,7 +537,7 @@ do_log(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("log: received non-numeric argument"));
- arg = (double) force_number(tmp);
+ arg = force_number(tmp)->numbr;
if (arg < 0.0)
warning(_("log: received negative argument %g"), arg);
d = log(arg);
@@ -542,6 +546,42 @@ do_log(int nargs)
}
+#ifdef HAVE_MPFR
+
+/*
+ * mpz2mpfr --- convert an arbitrary-precision integer to a float
+ * without any loss of precision. The returned value is only
+ * good for temporary use.
+ */
+
+
+static mpfr_ptr
+mpz2mpfr(mpz_ptr zi)
+{
+ size_t prec;
+ static mpfr_t mpfrval;
+ static int inited = FALSE;
+ int tval;
+
+ /* estimate minimum precision for exact conversion */
+ prec = mpz_sizeinbase(zi, 2); /* most significant 1 bit position starting at 1 */
+ prec -= (size_t) mpz_scan1(zi, 0); /* least significant 1 bit index starting at 0 */
+ if (prec < MPFR_PREC_MIN)
+ prec = MPFR_PREC_MIN;
+ else if (prec > MPFR_PREC_MAX)
+ prec = MPFR_PREC_MAX;
+
+ if (! inited) {
+ mpfr_init2(mpfrval, prec);
+ inited = TRUE;
+ } else
+ mpfr_set_prec(mpfrval, prec);
+ tval = mpfr_set_z(mpfrval, zi, ROUND_MODE);
+ IEEE_FMT(mpfrval, tval);
+ return mpfrval;
+}
+#endif
+
/*
* format_tree() formats arguments of sprintf,
* and accordingly to a fmt_string providing a format like in
@@ -599,7 +639,7 @@ format_tree(
size_t cur_arg = 0;
NODE *r = NULL;
- int i;
+ int i, nc;
int toofew = FALSE;
char *obuf, *obufout;
size_t osiz, ofre;
@@ -631,7 +671,7 @@ format_tree(
char *cend = &cpbufs[0].stackbuf[sizeof(cpbufs[0].stackbuf)];
char *cp;
const char *fill;
- AWKNUM tmpval;
+ AWKNUM tmpval = 0.0;
char signchar = FALSE;
size_t len;
int zero_flag = FALSE;
@@ -639,6 +679,12 @@ format_tree(
int ii, jj;
char *chp;
size_t copy_count, char_count;
+#ifdef HAVE_MPFR
+ mpz_ptr zi;
+ mpfr_ptr mf;
+#endif
+ enum { MP_INT_WITH_PREC = 1, MP_INT_WITHOUT_PREC, MP_FLOAT } fmt_type;
+
static const char sp[] = " ";
static const char zero_string[] = "0";
static const char lchbuf[] = "0123456789abcdef";
@@ -726,10 +772,17 @@ format_tree(
prec = 0;
base = 0;
argnum = 0;
+ base = 0;
have_prec = FALSE;
signchar = FALSE;
zero_flag = FALSE;
quote_flag = FALSE;
+#ifdef HAVE_MPFR
+ mf = NULL;
+ zi = NULL;
+#endif
+ fmt_type = 0;
+
lj = alt = big_flag = bigbig_flag = small_flag = FALSE;
fill = sp;
cp = cend;
@@ -861,7 +914,8 @@ check_pos:
} else {
parse_next_arg();
}
- *cur = force_number(arg);
+ (void) force_number(arg);
+ *cur = get_number_si(arg);
if (*cur < 0 && cur == &fw) {
*cur = -*cur;
lj++;
@@ -969,7 +1023,7 @@ check_pos:
if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM)
(void) force_number(arg);
if (arg->flags & NUMBER) {
- uval = (uintmax_t) arg->numbr;
+ uval = get_number_uj(arg);
#if MBS_SUPPORT
if (gawk_mb_cur_max > 1) {
char buf[100];
@@ -1052,7 +1106,16 @@ out2:
case 'i':
need_format = FALSE;
parse_next_arg();
- tmpval = force_number(arg);
+ (void) force_number(arg);
+#ifdef HAVE_MPFR
+ if (is_mpg_float(arg))
+ goto mpf0;
+ else if (is_mpg_integer(arg))
+ goto mpz0;
+ else
+#endif
+ tmpval = arg->numbr;
+
/*
* Check for Nan or Inf.
*/
@@ -1163,7 +1226,78 @@ out2:
base += 8;
need_format = FALSE;
parse_next_arg();
- tmpval = force_number(arg);
+ (void) force_number(arg);
+#ifdef HAVE_MPFR
+ if (is_mpg_integer(arg)) {
+mpz0:
+ zi = arg->mpg_i;
+
+ if (cs1 != 'd' && cs1 != 'i') {
+ if (mpz_sgn(zi) <= 0) {
+ /*
+ * Negative value or 0 requires special handling.
+ * Unlike MPFR, GMP does not allow conversion
+ * to (u)intmax_t. So we first convert GMP type to
+ * a MPFR type.
+ */
+ mf = mpz2mpfr(zi);
+ goto mpf1;
+ }
+ signchar = FALSE; /* Don't print '+' */
+ }
+
+ /* See comments above about when to fill with zeros */
+ zero_flag = (! lj
+ && ((zero_flag && ! have_prec)
+ || (fw == 0 && have_prec)));
+
+ fmt_type = have_prec ? MP_INT_WITH_PREC : MP_INT_WITHOUT_PREC;
+ goto fmt0;
+
+ } else if (is_mpg_float(arg)) {
+mpf0:
+ mf = arg->mpg_numbr;
+ if (! mpfr_number_p(mf)) {
+ /* inf or NaN */
+ cs1 = 'g';
+ fmt_type = MP_FLOAT;
+ goto fmt1;
+ }
+
+ if (cs1 != 'd' && cs1 != 'i') {
+mpf1:
+ /*
+ * The output of printf("%#.0x", 0) is 0 instead of 0x, hence <= in
+ * the comparison below.
+ */
+ if (mpfr_sgn(mf) <= 0) {
+ if (! mpfr_fits_intmax_p(mf, ROUND_MODE)) {
+ /* -ve number is too large */
+ cs1 = 'g';
+ fmt_type = MP_FLOAT;
+ goto fmt1;
+ }
+
+ tmpval = uval = (uintmax_t) mpfr_get_sj(mf, ROUND_MODE);
+ if (! alt && have_prec && prec == 0 && tmpval == 0)
+ goto pr_tail; /* printf("%.0x", 0) is no characters */
+ goto int0;
+ }
+ signchar = FALSE; /* Don't print '+' */
+ }
+
+ /* See comments above about when to fill with zeros */
+ zero_flag = (! lj
+ && ((zero_flag && ! have_prec)
+ || (fw == 0 && have_prec)));
+
+ (void) mpfr_get_z(mpzval, mf, MPFR_RNDZ); /* convert to GMP integer */
+ fmt_type = have_prec ? MP_INT_WITH_PREC : MP_INT_WITHOUT_PREC;
+ zi = mpzval;
+ goto fmt0;
+ } else
+#endif
+ tmpval = arg->numbr;
/*
* ``The result of converting a zero value with a
@@ -1182,14 +1316,16 @@ out2:
if (tmpval < 0) {
uval = (uintmax_t) (intmax_t) tmpval;
- if ((AWKNUM)(intmax_t)uval !=
- double_to_int(tmpval))
+ if ((AWKNUM)(intmax_t)uval != double_to_int(tmpval))
goto out_of_range;
} else {
uval = (uintmax_t) tmpval;
if ((AWKNUM)uval != double_to_int(tmpval))
goto out_of_range;
}
+#ifdef HAVE_MPFR
+ int0:
+#endif
/*
* When to fill with zeroes is of course not simple.
* First: No zero fill if left-justifying.
@@ -1272,7 +1408,7 @@ out2:
lintwarn(_("[s]printf: value %g is out of range for `%%%c' format"),
(double) tmpval, cs1);
cs1 = 'g';
- goto format_float;
+ goto fmt1;
case 'F':
#if ! defined(PRINTF_HAS_F_FORMAT) || PRINTF_HAS_F_FORMAT != 1
@@ -1286,11 +1422,28 @@ out2:
case 'E':
need_format = FALSE;
parse_next_arg();
- tmpval = force_number(arg);
- format_float:
+ (void) force_number(arg);
+
+ if (! is_mpg_number(arg))
+ tmpval = arg->numbr;
+#ifdef HAVE_MPFR
+ else if (is_mpg_float(arg)) {
+ mf = arg->mpg_numbr;
+ fmt_type = MP_FLOAT;
+ } else {
+ /* arbitrary-precision integer, convert to MPFR float */
+ assert(mf == NULL);
+ mf = mpz2mpfr(arg->mpg_i);
+ fmt_type = MP_FLOAT;
+ }
+#endif
+ fmt1:
if (! have_prec)
prec = DEFAULT_G_PRECISION;
- chksize(fw + prec + 9); /* 9 == slop */
+#ifdef HAVE_MPFR
+ fmt0:
+#endif
+ chksize(fw + prec + 11); /* 11 == slop */
cp = cpbuf;
*cp++ = '%';
if (lj)
@@ -1303,25 +1456,46 @@ out2:
*cp++ = '0';
if (quote_flag)
*cp++ = '\'';
- strcpy(cp, "*.*");
- cp += 3;
- *cp++ = cs1;
- *cp = '\0';
+
#if defined(LC_NUMERIC)
if (quote_flag && ! use_lc_numeric)
setlocale(LC_NUMERIC, "");
#endif
- {
- int n;
- while ((n = snprintf(obufout, ofre, cpbuf,
- (int) fw, (int) prec,
- (double) tmpval)) >= ofre)
- chksize(n)
+
+ switch (fmt_type) {
+#ifdef HAVE_MPFR
+ case MP_INT_WITH_PREC:
+ sprintf(cp, "*.*Z%c", cs1);
+ while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
+ (int) fw, (int) prec, zi)) >= ofre)
+ chksize(nc)
+ break;
+ case MP_INT_WITHOUT_PREC:
+ sprintf(cp, "*Z%c", cs1);
+ while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
+ (int) fw, zi)) >= ofre)
+ chksize(nc)
+ break;
+ case MP_FLOAT:
+ sprintf(cp, "*.*R*%c", cs1);
+ while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
+ (int) fw, (int) prec, ROUND_MODE, mf)) >= ofre)
+ chksize(nc)
+ break;
+#endif
+ default:
+ sprintf(cp, "*.*%c", cs1);
+ while ((nc = snprintf(obufout, ofre, cpbuf,
+ (int) fw, (int) prec,
+ (double) tmpval)) >= ofre)
+ chksize(nc)
}
+
#if defined(LC_NUMERIC)
if (quote_flag && ! use_lc_numeric)
setlocale(LC_NUMERIC, "C");
#endif
+
len = strlen(obufout);
ofre -= len;
obufout += len;
@@ -1362,6 +1536,7 @@ out:
if (obuf != NULL)
efree(obuf);
}
+
if (r == NULL)
gawk_exit(EXIT_FATAL);
return r;
@@ -1386,7 +1561,7 @@ printf_common(int nargs)
}
}
- force_string(args_array[0]);
+ args_array[0] = force_string(args_array[0]);
r = format_tree(args_array[0]->stptr, args_array[0]->stlen, args_array, nargs);
for (i = 0; i < nargs; i++)
DEREF(args_array[i]);
@@ -1473,7 +1648,7 @@ do_sqrt(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("sqrt: received non-numeric argument"));
- arg = (double) force_number(tmp);
+ arg = (double) force_number(tmp)->numbr;
DEREF(tmp);
if (arg < 0.0)
warning(_("sqrt: called with negative argument %g"), arg);
@@ -1492,19 +1667,26 @@ do_substr(int nargs)
double d_index = 0, d_length = 0;
size_t src_len;
- if (nargs == 3)
- POP_NUMBER(d_length);
- POP_NUMBER(d_index);
+ if (nargs == 3) {
+ t1 = POP_NUMBER();
+ d_length = get_number_d(t1);
+ DEREF(t1);
+ }
+
+ t1 = POP_NUMBER();
+ d_index = get_number_d(t1);
+ DEREF(t1);
+
t1 = POP_STRING();
if (nargs == 3) {
if (! (d_length >= 1)) {
- if (do_lint == LINT_ALL)
+ if (do_lint == DO_LINT_ALL)
lintwarn(_("substr: length %g is not >= 1"), d_length);
- else if (do_lint == LINT_INVALID && ! (d_length >= 0))
+ else if (do_lint == DO_LINT_INVALID && ! (d_length >= 0))
lintwarn(_("substr: length %g is not >= 0"), d_length);
DEREF(t1);
- return Nnull_string;
+ return dupnode(Nnull_string);
}
if (do_lint) {
if (double_to_int(d_length) != d_length)
@@ -1555,10 +1737,10 @@ do_substr(int nargs)
if (t1->stlen == 0) {
/* substr("", 1, 0) produces a warning only if LINT_ALL */
- if (do_lint && (do_lint == LINT_ALL || ((indx | length) != 0)))
+ if (do_lint && (do_lint == DO_LINT_ALL || ((indx | length) != 0)))
lintwarn(_("substr: source string is zero length"));
DEREF(t1);
- return Nnull_string;
+ return dupnode(Nnull_string);
}
/* get total len of input string, for following checks */
@@ -1575,7 +1757,7 @@ do_substr(int nargs)
lintwarn(_("substr: start index %g is past end of string"),
d_index);
DEREF(t1);
- return Nnull_string;
+ return dupnode(Nnull_string);
}
if (length > src_len - indx) {
if (do_lint)
@@ -1673,12 +1855,13 @@ do_strftime(int nargs)
do_gmt = (t3->stlen > 0);
DEREF(t3);
}
-
+
if (nargs >= 2) {
t2 = POP_SCALAR();
if (do_lint && (t2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("strftime: received non-numeric second argument"));
- clock_val = (long) force_number(t2);
+ (void) force_number(t2);
+ clock_val = get_number_si(t2);
if (clock_val < 0)
fatal(_("strftime: second argument less than 0 or too big for time_t"));
fclock = (time_t) clock_val;
@@ -1688,6 +1871,7 @@ do_strftime(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
lintwarn(_("strftime: received non-string first argument"));
+
t1 = force_string(tmp);
format = t1->stptr;
formatlen = t1->stlen;
@@ -1770,13 +1954,13 @@ do_mktime(int nargs)
& hour, & minute, & second,
& dst);
- if (do_lint /* Ready? Set! Go: */
- && ( (second < 0 || second > 60)
- || (minute < 0 || minute > 60)
- || (hour < 0 || hour > 23)
- || (day < 1 || day > 31)
- || (month < 1 || month > 12) ))
- lintwarn(_("mktime: at least one of the values is out of the default range"));
+ if (do_lint /* Ready? Set! Go: */
+ && ( (second < 0 || second > 60)
+ || (minute < 0 || minute > 60)
+ || (hour < 0 || hour > 23)
+ || (day < 1 || day > 31)
+ || (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);
@@ -1837,11 +2021,9 @@ do_system(int nargs)
return make_number((AWKNUM) ret);
}
-extern NODE **fmt_list; /* declared in eval.c */
-
/* do_print --- print items, separated by OFS, terminated with ORS */
-void
+void
do_print(int nargs, int redirtype)
{
struct redirect *rp = NULL;
@@ -1849,7 +2031,7 @@ do_print(int nargs, int redirtype)
FILE *fp = NULL;
int i;
NODE *redir_exp = NULL;
- NODE *tmp;
+ NODE *tmp = NULL;
assert(nargs <= max_args);
@@ -1870,12 +2052,10 @@ do_print(int nargs, int redirtype)
DEREF(args_array[i]);
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(tmp));
}
- if (do_lint && tmp->type == Node_var_new)
- lintwarn(_("reference to uninitialized variable `%s'"),
- tmp->vname);
+
if ((tmp->flags & (NUMBER|STRING)) == NUMBER) {
if (OFMTidx == CONVFMTidx)
- (void) force_string(tmp);
+ args_array[i] = force_string(tmp);
else
args_array[i] = format_val(OFMT, OFMTidx, tmp);
}
@@ -2099,8 +2279,8 @@ do_atan2(int nargs)
if ((t2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("atan2: received non-numeric second argument"));
}
- d1 = force_number(t1);
- d2 = force_number(t2);
+ d1 = force_number(t1)->numbr;
+ d2 = force_number(t2)->numbr;
DEREF(t1);
DEREF(t2);
return make_number((AWKNUM) atan2(d1, d2));
@@ -2117,7 +2297,7 @@ do_sin(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("sin: received non-numeric argument"));
- d = sin((double) force_number(tmp));
+ d = sin((double) force_number(tmp)->numbr);
DEREF(tmp);
return make_number((AWKNUM) d);
}
@@ -2133,7 +2313,7 @@ do_cos(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("cos: received non-numeric argument"));
- d = cos((double) force_number(tmp));
+ d = cos((double) force_number(tmp)->numbr);
DEREF(tmp);
return make_number((AWKNUM) d);
}
@@ -2186,7 +2366,7 @@ do_srand(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("srand: received non-numeric argument"));
- srandom((unsigned int) (save_seed = (long) force_number(tmp)));
+ srandom((unsigned int) (save_seed = (long) force_number(tmp)->numbr));
DEREF(tmp);
}
return make_number((AWKNUM) ret);
@@ -2267,7 +2447,7 @@ do_match(int nargs)
it->flags |= MAYBE_NUM; /* user input */
sub = make_number((AWKNUM) (ii));
- lhs = assoc_lookup(dest, sub, FALSE);
+ lhs = assoc_lookup(dest, sub);
unref(*lhs);
*lhs = it;
unref(sub);
@@ -2290,7 +2470,7 @@ do_match(int nargs)
it = make_number((AWKNUM) subpat_start + 1);
sub = make_string(buf, slen);
- lhs = assoc_lookup(dest, sub, FALSE);
+ lhs = assoc_lookup(dest, sub);
unref(*lhs);
*lhs = it;
unref(sub);
@@ -2303,7 +2483,7 @@ do_match(int nargs)
it = make_number((AWKNUM) subpat_len);
sub = make_string(buf, slen);
- lhs = assoc_lookup(dest, sub, FALSE);
+ lhs = assoc_lookup(dest, sub);
unref(*lhs);
*lhs = it;
unref(sub);
@@ -2463,15 +2643,16 @@ do_sub(int nargs, unsigned int flags)
if (t1->stlen > 0 && (t1->stptr[0] == 'g' || t1->stptr[0] == 'G'))
how_many = -1;
else {
- d = force_number(t1);
-
+ (void) force_number(t1);
+ d = get_number_d(t1);
if ((t1->flags & NUMCUR) != 0)
goto set_how_many;
how_many = 1;
}
} else {
- d = force_number(t1);
+ (void) force_number(t1);
+ d = get_number_d(t1);
set_how_many:
if (d < 1)
how_many = 1;
@@ -2777,8 +2958,8 @@ do_lshift(int nargs)
if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("lshift: received non-numeric second argument"));
}
- val = force_number(s1);
- shift = force_number(s2);
+ val = force_number(s1)->numbr;
+ shift = force_number(s2)->numbr;
if (do_lint) {
if (val < 0 || shift < 0)
lintwarn(_("lshift(%lf, %lf): negative values will give strange results"), val, shift);
@@ -2814,8 +2995,8 @@ do_rshift(int nargs)
if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("rshift: received non-numeric second argument"));
}
- val = force_number(s1);
- shift = force_number(s2);
+ val = force_number(s1)->numbr;
+ shift = force_number(s2)->numbr;
if (do_lint) {
if (val < 0 || shift < 0)
lintwarn(_("rshift(%lf, %lf): negative values will give strange results"), val, shift);
@@ -2851,8 +3032,8 @@ do_and(int nargs)
if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("and: received non-numeric second argument"));
}
- left = force_number(s1);
- right = force_number(s2);
+ left = force_number(s1)->numbr;
+ right = force_number(s2)->numbr;
if (do_lint) {
if (left < 0 || right < 0)
lintwarn(_("and(%lf, %lf): negative values will give strange results"), left, right);
@@ -2886,8 +3067,8 @@ do_or(int nargs)
if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("or: received non-numeric second argument"));
}
- left = force_number(s1);
- right = force_number(s2);
+ left = force_number(s1)->numbr;
+ right = force_number(s2)->numbr;
if (do_lint) {
if (left < 0 || right < 0)
lintwarn(_("or(%lf, %lf): negative values will give strange results"), left, right);
@@ -2915,8 +3096,6 @@ do_xor(int nargs)
AWKNUM left, right;
POP_TWO_SCALARS(s1, s2);
- left = force_number(s1);
- right = force_number(s2);
if (do_lint) {
if ((s1->flags & (NUMCUR|NUMBER)) == 0)
@@ -2924,8 +3103,8 @@ do_xor(int nargs)
if ((s2->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("xor: received non-numeric second argument"));
}
- left = force_number(s1);
- right = force_number(s2);
+ left = force_number(s1)->numbr;
+ right = force_number(s2)->numbr;
if (do_lint) {
if (left < 0 || right < 0)
lintwarn(_("xor(%lf, %lf): negative values will give strange results"), left, right);
@@ -2955,12 +3134,10 @@ do_compl(int nargs)
tmp = POP_SCALAR();
if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
lintwarn(_("compl: received non-numeric argument"));
- d = force_number(tmp);
+ d = force_number(tmp)->numbr;
DEREF(tmp);
if (do_lint) {
- 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);
if (double_to_int(d) != d)
@@ -2982,11 +3159,11 @@ do_strtonum(int nargs)
tmp = POP_SCALAR();
if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
- d = (AWKNUM) force_number(tmp);
- else if (isnondecimal(tmp->stptr, use_lc_numeric))
+ d = (AWKNUM) force_number(tmp)->numbr;
+ else if (get_numbase(tmp->stptr, use_lc_numeric) != 10)
d = nondec2awknum(tmp->stptr, tmp->stlen);
else
- d = (AWKNUM) force_number(tmp);
+ d = (AWKNUM) force_number(tmp)->numbr;
DEREF(tmp);
return make_number((AWKNUM) d);
@@ -3236,7 +3413,10 @@ do_dcngettext(int nargs)
}
#endif
- POP_NUMBER(d); /* third argument */
+ t2 = POP_NUMBER(); /* third argument */
+ d = get_number_d(t2);
+ DEREF(t2);
+
number = (unsigned long) double_to_int(d);
t2 = POP_STRING(); /* second argument */
string2 = t2->stptr;