Skip to content

Commit

Permalink
Math priority fixes, and &&/|| had assignment suppression reversed.
Browse files Browse the repository at this point in the history
  • Loading branch information
landley committed Jan 2, 2023
1 parent 9dc62c6 commit 97c15e2
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
6 changes: 6 additions & 0 deletions tests/sh.test
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ testing "nesting ? :" \
testing "inherited assignment suppression" 'echo $((0 ? (x++) : 2)); echo $x' \
"2\n\n" "" ""
testing "boolean vs logical" 'echo $((2|4&&8))' '1\n' '' ''
testing "&& vs || priority" \
'echo $((w++||x++&&y++||z++)) w=$w x=$x y=$y z=$z' \
'0 w=1 x=1 y= z=1\n' '' ''
testing "|| vs && priority" \
'echo $((w++&&x++||y++&&z++)) w=$w x=$x y=$y z=$z' \
'0 w=1 x= y=1 z=\n' '' ''

# Loops and flow control
testing "case" 'for i in A C J B; do case "$i" in A) echo got A ;; B) echo and B ;; C) echo then C ;; *) echo default ;; esac; done' \
Expand Down
41 changes: 21 additions & 20 deletions toys/pending/sh.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ static int recalculate(long long *dd, char **ss, int lvl)
// At lvl 0 "" is ok, anything higher needs a non-empty equation
if (lvl || (cc && cc!=')')) return 0;
*dd = 0;

return 1;
}

Expand Down Expand Up @@ -660,16 +661,16 @@ static int recalculate(long long *dd, char **ss, int lvl)
}

// x**y binds first
if (lvl<=13) while (strstart(nospace(ss), "**")) {
if (!recalculate(&ee, ss, noa|14)) return 0;
if (lvl<=14) while (strstart(nospace(ss), "**")) {
if (!recalculate(&ee, ss, noa|15)) return 0;
if (ee<0) perror_msg("** < 0");
for (ff = *dd, *dd = 1; ee; ee--) *dd *= ff;
}

// w*x/y%z bind next
if (lvl<=12) while ((cc = **nospace(ss)) && strchr("*/%", cc)) {
if (lvl<=13) while ((cc = **nospace(ss)) && strchr("*/%", cc)) {
++*ss;
if (!recalculate(&ee, ss, noa|13)) return 0;
if (!recalculate(&ee, ss, noa|14)) return 0;
if (cc=='*') *dd *= ee;
else if (cc=='%') *dd %= ee;
else if (!ee) {
Expand All @@ -679,61 +680,61 @@ static int recalculate(long long *dd, char **ss, int lvl)
}

// x+y-z
if (lvl<=11) while ((cc = **nospace(ss)) && strchr("+-", cc)) {
if (lvl<=12) while ((cc = **nospace(ss)) && strchr("+-", cc)) {
++*ss;
if (!recalculate(&ee, ss, noa|12)) return 0;
if (!recalculate(&ee, ss, noa|13)) return 0;
if (cc=='+') *dd += ee;
else *dd -= ee;
}

// x<<y >>

if (lvl<=10) while ((cc = **nospace(ss)) && strchr("<>", cc) && cc==(*ss)[1]){
if (lvl<=11) while ((cc = **nospace(ss)) && strchr("<>", cc) && cc==(*ss)[1]){
*ss += 2;
if (!recalculate(&ee, ss, noa|11)) return 0;
if (!recalculate(&ee, ss, noa|12)) return 0;
if (cc == '<') *dd <<= ee;
else *dd >>= ee;
}

// x<y <= > >=
if (lvl<=9) while ((cc = **nospace(ss)) && strchr("<>", cc)) {
if (lvl<=10) while ((cc = **nospace(ss)) && strchr("<>", cc)) {
if ((ii = *++*ss=='=')) ++*ss;
if (!recalculate(&ee, ss, noa|10)) return 0;
if (!recalculate(&ee, ss, noa|11)) return 0;
if (cc=='<') *dd = ii ? (*dd<=ee) : (*dd<ee);
else *dd = ii ? (*dd>=ee) : (*dd>ee);
}

if (lvl<=8) while ((cc = **nospace(ss)) && strchr("=!", cc) && (*ss)[1]=='='){
if (lvl<=9) while ((cc = **nospace(ss)) && strchr("=!", cc) && (*ss)[1]=='='){
*ss += 2;
if (!recalculate(&ee, ss, noa|9)) return 0;
if (!recalculate(&ee, ss, noa|10)) return 0;
*dd = (cc=='!') ? *dd != ee : *dd == ee;
}

if (lvl<=7) while (**nospace(ss)=='&' && (*ss)[1]!='&') {
if (lvl<=8) while (**nospace(ss)=='&' && (*ss)[1]!='&') {
++*ss;
if (!recalculate(&ee, ss, noa|8)) return 0;
if (!recalculate(&ee, ss, noa|9)) return 0;
*dd &= ee;
}

if (lvl<=6) while (**nospace(ss)=='^') {
if (lvl<=7) while (**nospace(ss)=='^') {
++*ss;
if (!recalculate(&ee, ss, noa|7)) return 0;
if (!recalculate(&ee, ss, noa|8)) return 0;
*dd ^= ee;
}

if (lvl<=5) while (**nospace(ss)=='|' && (*ss)[1]!='|') {
if (lvl<=6) while (**nospace(ss)=='|' && (*ss)[1]!='|') {
++*ss;
if (!recalculate(&ee, ss, noa|6)) return 0;
if (!recalculate(&ee, ss, noa|7)) return 0;
*dd |= ee;
}

if (lvl<=5) while (strstart(nospace(ss), "&&")) {
if (!recalculate(&ee, ss, noa|6|NO_ASSIGN*!!*dd)) return 0;
if (!recalculate(&ee, ss, noa|6|NO_ASSIGN*!*dd)) return 0;
*dd = *dd && ee;
}

if (lvl<=4) while (strstart(nospace(ss), "||")) {
if (!recalculate(&ee, ss, noa|5|NO_ASSIGN*!*dd)) return 0;
if (!recalculate(&ee, ss, noa|5|NO_ASSIGN*!!*dd)) return 0;
*dd = *dd || ee;
}

Expand Down

0 comments on commit 97c15e2

Please sign in to comment.