Fix: DIV and MOD on negative args
This commit is contained in:
parent
2acd7638cc
commit
396c70c16e
@ -782,7 +782,13 @@ CodeOper(expr, true_label, false_label)
|
|||||||
Operands(expr);
|
Operands(expr);
|
||||||
switch(tp->tp_fund) {
|
switch(tp->tp_fund) {
|
||||||
case T_INTEGER:
|
case T_INTEGER:
|
||||||
C_dvi(tp->tp_size);
|
if ((int)(tp->tp_size) == word_size) {
|
||||||
|
C_cal((int)(tp->tp_size) == (int)word_size
|
||||||
|
? "dvi"
|
||||||
|
: "dvil");
|
||||||
|
}
|
||||||
|
C_asp(2*tp->tp_size);
|
||||||
|
C_lfr(tp->tp_size);
|
||||||
break;
|
break;
|
||||||
case T_POINTER:
|
case T_POINTER:
|
||||||
case T_EQUAL:
|
case T_EQUAL:
|
||||||
@ -798,7 +804,13 @@ CodeOper(expr, true_label, false_label)
|
|||||||
Operands(expr);
|
Operands(expr);
|
||||||
switch(tp->tp_fund) {
|
switch(tp->tp_fund) {
|
||||||
case T_INTEGER:
|
case T_INTEGER:
|
||||||
C_rmi(tp->tp_size);
|
if ((int)(tp->tp_size) == word_size) {
|
||||||
|
C_cal((int)(tp->tp_size) == (int)word_size
|
||||||
|
? "rmi"
|
||||||
|
: "rmil");
|
||||||
|
}
|
||||||
|
C_asp(2*tp->tp_size);
|
||||||
|
C_lfr(tp->tp_size);
|
||||||
break;
|
break;
|
||||||
case T_POINTER:
|
case T_POINTER:
|
||||||
case T_EQUAL:
|
case T_EQUAL:
|
||||||
|
|||||||
@ -186,35 +186,28 @@ cstibin(expp)
|
|||||||
node_error(expp, "division by 0");
|
node_error(expp, "division by 0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if (-1)/2==0
|
|
||||||
o1 /= o2;
|
|
||||||
#else
|
|
||||||
if (o1 == 0) break;
|
|
||||||
if ((o1 < 0) != (o2 < 0)) {
|
if ((o1 < 0) != (o2 < 0)) {
|
||||||
o1 = o1/o2 + 1;
|
if (o1 < 0) o1 = -o1;
|
||||||
|
else o2 = -o2;
|
||||||
|
o1 = -((o1+o2-1)/o2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
o1 /= o2;
|
o1 /= o2;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD:
|
case MOD:
|
||||||
if (o2 == 0) {
|
if (o2 == 0) {
|
||||||
node_error(expp, "modulo by 0");
|
node_error(expp, "modulo by 0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if (-1)/2==0
|
|
||||||
o1 %= o2;
|
|
||||||
#else
|
|
||||||
if (o1 == 0) break;
|
|
||||||
if ((o1 < 0) != (o2 < 0)) {
|
if ((o1 < 0) != (o2 < 0)) {
|
||||||
o1 -= (o1 / o2 + 1) * o2;
|
if (o1 < 0) o1 = -o1;
|
||||||
|
else o2 = -o2;
|
||||||
|
o1 = ((o1+o2-1)/o2) * o2 - o1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
o1 %= o2;
|
o1 %= o2;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
|
|||||||
@ -19,6 +19,7 @@ ArraySort.mod
|
|||||||
catch.c
|
catch.c
|
||||||
Traps.mod
|
Traps.mod
|
||||||
XXTermcap.c
|
XXTermcap.c
|
||||||
|
dvi.c
|
||||||
Arguments.c
|
Arguments.c
|
||||||
LtoUset.e
|
LtoUset.e
|
||||||
StrAss.c
|
StrAss.c
|
||||||
|
|||||||
68
lang/m2/libm2/dvi.c
Normal file
68
lang/m2/libm2/dvi.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
(c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module: implementation of DIV and MOD
|
||||||
|
Author: Ceriel J.H. Jacobs
|
||||||
|
Version: $Header$
|
||||||
|
Reason: We cannot use DVI and RMI, because DVI rounds towards 0
|
||||||
|
and Modula-2 requires truncation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <em_abs.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
dvi(j,i)
|
||||||
|
int j,i;
|
||||||
|
{
|
||||||
|
if (j == 0) TRP(EIDIVZ);
|
||||||
|
if ((i < 0) != (j < 0)) {
|
||||||
|
if (i < 0) i = -i;
|
||||||
|
else j = -j;
|
||||||
|
return -((i+j-1)/j);
|
||||||
|
}
|
||||||
|
else return i/j;
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
dvil(j,i)
|
||||||
|
long j,i;
|
||||||
|
{
|
||||||
|
if (j == 0) TRP(EIDIVZ);
|
||||||
|
if ((i < 0) != (j < 0)) {
|
||||||
|
if (i < 0) i = -i;
|
||||||
|
else j = -j;
|
||||||
|
return -((i+j-1)/j);
|
||||||
|
}
|
||||||
|
else return i/j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rmi(j,i)
|
||||||
|
int j,i;
|
||||||
|
{
|
||||||
|
if (j == 0) TRP(EIDIVZ);
|
||||||
|
if (i == 0) return 0;
|
||||||
|
if ((i < 0) != (j < 0)) {
|
||||||
|
if (i < 0) i = -i;
|
||||||
|
else j = -j;
|
||||||
|
return j*((i+j-1)/j)-i;
|
||||||
|
}
|
||||||
|
else return i%j;
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
rmil(j,i)
|
||||||
|
long j,i;
|
||||||
|
{
|
||||||
|
if (j == 0) TRP(EIDIVZ);
|
||||||
|
if (i == 0) return 0L;
|
||||||
|
if ((i < 0) != (j < 0)) {
|
||||||
|
if (i < 0) i = -i;
|
||||||
|
else j = -j;
|
||||||
|
return j*((i+j-1)/j)-i;
|
||||||
|
}
|
||||||
|
else return i%j;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user