summaryrefslogtreecommitdiff
path: root/Src/math.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2015-05-05 23:32:59 +0200
committerAxel Beckert <abe@deuxchevaux.org>2015-05-05 23:58:59 +0200
commitdb38e167634b6c2217eec3a5aafc37c46d9e5a8d (patch)
treedaa342d423febbd3a5a7ef97053037677fab004a /Src/math.c
parent01eea47617a6e06debdb4330f92ae69f92089fd2 (diff)
parent3c3c8d3d13fd4cf6c03f81ca8dc18a1efd561728 (diff)
downloadzsh-db38e167634b6c2217eec3a5aafc37c46d9e5a8d.tar.gz
zsh-db38e167634b6c2217eec3a5aafc37c46d9e5a8d.zip
Merge branch 'upstream' into debian
Diffstat (limited to 'Src/math.c')
-rw-r--r--Src/math.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/Src/math.c b/Src/math.c
index 266569827..97a97b32b 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -288,11 +288,11 @@ static int type[TOKCOUNT] =
{
/* 0 */ LR, LR|OP_OP|OP_OPF, RL, RL, RL|OP_OP|OP_OPF,
/* 5 */ RL|OP_OP|OP_OPF, RL, RL, LR|OP_A2IO, LR|OP_A2IO,
-/* 10 */ LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2IO, LR|OP_A2,
+/* 10 */ LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2, LR|OP_A2,
/* 15 */ LR|OP_A2, LR|OP_A2IO, LR|OP_A2IO, LR|OP_A2IR, LR|OP_A2IR,
/* 20 */ LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, BOOL|OP_A2IO,
/* 25 */ BOOL|OP_A2IO, LR|OP_A2IO, RL|OP_OP, RL|OP_OP, RL|OP_E2,
-/* 30 */ RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2IO,
+/* 30 */ RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2,
/* 35 */ RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
/* 40 */ BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL|OP_OP,
/* 45 */ RL, RL, LR|OP_OPF, LR|OP_OPF, RL|OP_A2,
@@ -336,16 +336,27 @@ enum prec_type {
static mnumber
getmathparam(struct mathvalue *mptr)
{
+ mnumber result;
if (!mptr->pval) {
char *s = mptr->lval;
mptr->pval = (Value)zhalloc(sizeof(struct value));
if (!getvalue(mptr->pval, &s, 1))
{
mptr->pval = NULL;
+ if (isset(FORCEFLOAT)) {
+ result.type = MN_FLOAT;
+ result.u.d = 0.0;
+ return result;
+ }
return zero_mnumber;
}
}
- return getnumvalue(mptr->pval);
+ result = getnumvalue(mptr->pval);
+ if (isset(FORCEFLOAT) && result.type == MN_INTEGER) {
+ result.type = MN_FLOAT;
+ result.u.d = (double)result.u.l;
+ }
+ return result;
}
static mnumber
@@ -449,12 +460,14 @@ lexconstant(void)
nptr++;
if (*nptr == '0') {
+ int lowchar;
nptr++;
- if (*nptr == 'x' || *nptr == 'X') {
+ lowchar = tolower(*nptr);
+ if (lowchar == 'x' || lowchar == 'b') {
/* Let zstrtol parse number with base */
yyval.u.l = zstrtol_underscore(ptr, &ptr, 0, 1);
/* Should we set lastbase here? */
- lastbase = 16;
+ lastbase = (lowchar == 'b') ? 2 : 16;
if (isset(FORCEFLOAT))
{
yyval.type = MN_FLOAT;
@@ -878,6 +891,8 @@ getcvar(char *s)
static mnumber
setmathvar(struct mathvalue *mvp, mnumber v)
{
+ Param pm;
+
if (mvp->pval) {
/*
* This value may have been hanging around for a while.
@@ -907,7 +922,32 @@ setmathvar(struct mathvalue *mvp, mnumber v)
if (noeval)
return v;
untokenize(mvp->lval);
- setnparam(mvp->lval, v);
+ pm = setnparam(mvp->lval, v);
+ if (pm) {
+ /*
+ * If we are performing an assignment, we return the
+ * number with the same type as the parameter we are
+ * assigning to, in the spirit of the way assignments
+ * in C work. Note this was a change to long-standing
+ * zsh behaviour.
+ */
+ switch (PM_TYPE(pm->node.flags)) {
+ case PM_INTEGER:
+ if (v.type != MN_INTEGER) {
+ v.u.l = (zlong)v.u.d;
+ v.type = MN_INTEGER;
+ }
+ break;
+
+ case PM_EFLOAT:
+ case PM_FFLOAT:
+ if (v.type != MN_FLOAT) {
+ v.u.d = (double)v.u.l;
+ v.type = MN_FLOAT;
+ }
+ break;
+ }
+ }
return v;
}
@@ -1131,7 +1171,9 @@ op(int what)
* Any integer mod -1 is the same as any integer mod 1
* i.e. zero.
*/
- if (b.u.l == -1)
+ if (c.type == MN_FLOAT)
+ c.u.d = fmod(a.u.d, b.u.d);
+ else if (b.u.l == -1)
c.u.l = 0;
else
c.u.l = a.u.l % b.u.l;
@@ -1356,6 +1398,8 @@ matheval(char *s)
if (!mlevel)
outputradix = outputunderscore = 0;
+ if (*s == Nularg)
+ s++;
if (!*s) {
x.type = MN_INTEGER;
x.u.l = 0;
@@ -1393,6 +1437,8 @@ mathevalarg(char *s, char **ss)
*
* To avoid a more opaque error further in, bail out here.
*/
+ if (*s == Nularg)
+ s++;
if (!*s) {
zerr("bad math expression: empty string");
return (zlong)0;