diff --git a/lang/m2/comp/LLlex.c b/lang/m2/comp/LLlex.c index 39b07907b..e13405611 100644 --- a/lang/m2/comp/LLlex.c +++ b/lang/m2/comp/LLlex.c @@ -458,7 +458,7 @@ again: /* Fall through */ case End: { - int sgnswtch = 0; + int ovfl = 0; *np = '\0'; if (np >= &buf[NUMSIZE]) { @@ -466,11 +466,19 @@ again: lexerror("constant too long"); } else { + /* The upperbound will be the same as + when computed with something like + max(unsigned long) / base (when base + is even). The problem is that + unsigned long or unsigned arith is + not accepted by all compilers + */ + arith ubound = max_int[sizeof(arith)] + / (base >> 1); np = &buf[1]; while (*np == '0') np++; tk->TOK_INT = 0; while (*np) { - arith old = tk->TOK_INT; int c; if (is_dig(*np)) { @@ -480,38 +488,46 @@ again: assert(is_hex(*np)); c = *np++ - 'A' + 10; } - tk->TOK_INT = tk->TOK_INT*base - + c; - sgnswtch += (old < 0) ^ - (tk->TOK_INT < 0); + if (tk->TOK_INT < 0 || + tk->TOK_INT > ubound) { + ovfl++; + } + tk->TOK_INT = tk->TOK_INT*base; + if (tk->TOK_INT < 0 && + tk->TOK_INT + c >= 0) { + ovfl++; + } + tk->TOK_INT += c; } } toktype = card_type; - if (sgnswtch >= 2) { -lexwarning(W_ORDINARY, "overflow in constant"); - } - else if (ch == 'C' && base == 8) { + if (ch == 'C' && base == 8) { toktype = char_type; - if (sgnswtch != 0 || tk->TOK_INT>255) { + if (ovfl != 0 || tk->TOK_INT>255 || + tk->TOK_INT < 0) { lexwarning(W_ORDINARY, "character constant out of range"); } + return tk->tk_symb = INTEGER; } - else if (ch == 'D' && base == 10) { - if (sgnswtch != 0 || - tk->TOK_INT > max_int[(int)long_size]) { -lexwarning(W_ORDINARY, "overflow in constant"); + if (ch == 'D' && base == 10) { + if (ovfl != 0 || + tk->TOK_INT > max_int[(int)long_size] || + tk->TOK_INT < 0) { + ovfl = 1; } toktype = longint_type; } - else if (sgnswtch == 0 && + else if (ovfl == 0 && tk->TOK_INT >= 0 && tk->TOK_INT<=max_int[(int)int_size]) { toktype = intorcard_type; } else if (! chk_bounds(tk->TOK_INT, full_mask[(int)int_size], T_CARDINAL)) { -lexwarning(W_ORDINARY, "overflow in constant"); + ovfl = 1; } + if (ovfl) +lexwarning(W_ORDINARY, "overflow in constant"); return tk->tk_symb = INTEGER; } diff --git a/lang/m2/comp/const.h b/lang/m2/comp/const.h index 9c7f590ef..4aa261a63 100644 --- a/lang/m2/comp/const.h +++ b/lang/m2/comp/const.h @@ -9,9 +9,7 @@ /* $Header$ */ -extern long - mach_long_sign; /* sign bit of the machine long */ -extern int - mach_long_size; /* size of long on this machine == sizeof(long) */ +#define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1))) + extern unsigned int wrd_bits; /* Number of bits in a word */ diff --git a/lang/m2/comp/cstoper.c b/lang/m2/comp/cstoper.c index 0ee16fa7d..def4c48dc 100644 --- a/lang/m2/comp/cstoper.c +++ b/lang/m2/comp/cstoper.c @@ -23,12 +23,11 @@ #include "Lpars.h" #include "standards.h" #include "warning.h" +#include "const.h" -long mach_long_sign; /* sign bit of the machine long */ -int mach_long_size; /* size of long on this machine == sizeof(long) */ -long full_mask[MAXSIZE];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */ -long max_int[MAXSIZE]; /* max_int[1] == 0x7F, max_int[2] == 0x7FFF, .. */ -long min_int[MAXSIZE]; /* min_int[1] == 0xFFFFFF80, min_int[2] = 0xFFFF8000, +arith full_mask[MAXSIZE];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */ +arith max_int[MAXSIZE]; /* max_int[1] == 0x7F, max_int[2] == 0x7FFF, .. */ +arith min_int[MAXSIZE]; /* min_int[1] == 0xFFFFFF80, min_int[2] = 0xFFFF8000, ... */ unsigned int wrd_bits; /* number of bits in a word */ @@ -68,7 +67,7 @@ cstunary(expp) expression below it, and the result restored in expp. */ register t_node *right = expp->nd_right; - arith o1 = right->nd_INT; + register arith o1 = right->nd_INT; switch(expp->nd_symb) { /* Should not get here @@ -77,9 +76,9 @@ cstunary(expp) */ case '-': - if (o1 == min_int[(int)(right->nd_type->tp_size)]) + if (o1 == min_int[(int)(right->nd_type->tp_size)]) { overflow(expp); - + } o1 = -o1; break; @@ -110,10 +109,10 @@ divide(pdiv, prem) think on C compilers which do not have unsigned long. */ - if (o2 & mach_long_sign) {/* o2 > max_long */ + if (o2 & arith_sign) {/* o2 > max_arith */ if (! (o1 >= 0 || o1 < o2)) { /* this is the unsigned test - o1 < o2 for o2 > max_long + o1 < o2 for o2 > max_arith */ *prem = o2 - o1; *pdiv = 1; @@ -122,14 +121,14 @@ divide(pdiv, prem) *pdiv = 0; } } - else { /* o2 <= max_long */ - long half, bit, hdiv, hrem, rem; + else { /* o2 <= max_arith */ + arith half, bit, hdiv, hrem, rem; - half = (o1 >> 1) & ~mach_long_sign; + half = (o1 >> 1) & ~arith_sign; bit = o1 & 01; /* now o1 == 2 * half + bit - and half <= max_long - and bit <= max_long + and half <= max_arith + and bit <= max_arith */ hdiv = half / o2; hrem = half % o2; @@ -138,7 +137,7 @@ divide(pdiv, prem) *prem = rem; if (rem < 0 || rem >= o2) { /* that is the unsigned compare - rem >= o2 for o2 <= max_long + rem >= o2 for o2 <= max_arith */ *pdiv += 1; *prem -= o2; @@ -153,8 +152,8 @@ cstibin(expp) expressions below it, and the result restored in expp. This version is for INTEGER expressions. */ - arith o1 = expp->nd_left->nd_INT; - arith o2 = expp->nd_right->nd_INT; + register arith o1 = expp->nd_left->nd_INT; + register arith o2 = expp->nd_right->nd_INT; register int sz = expp->nd_type->tp_size; assert(expp->nd_class == Oper); @@ -184,7 +183,17 @@ cstibin(expp) node_error(expp, "division by 0"); return; } - o1 /= o2; /* ??? */ +#if (-1)/2==0 + o1 /= o2; +#else + if (o1 == 0) break; + if ((o1 < 0) != (o2 < 0)) { + o1 = o1/o2 + 1; + } + else { + o1 /= o2; + } +#endif break; case MOD: @@ -192,7 +201,17 @@ cstibin(expp) node_error(expp, "modulo by 0"); return; } - o1 %= o2; /* ??? */ +#if (-1)/2==0 + o1 %= o2; +#else + if (o1 == 0) break; + if ((o1 < 0) != (o2 < 0)) { + o1 -= (o1 / o2 + 1) * o2; + } + else { + o1 %= o2; + } +#endif break; case '+': @@ -549,7 +568,7 @@ CutSize(expr) expr->nd_INT &= full_mask[(int)(tp->tp_size)]; } else { - int nbits = (int) (mach_long_size - tp->tp_size) * 8; + int nbits = (int) (sizeof(arith) - tp->tp_size) * 8; expr->nd_INT = (expr->nd_INT << nbits) >> nbits; } @@ -566,14 +585,12 @@ InitCst() if (i == MAXSIZE) fatal("array full_mask too small for this machine"); full_mask[i] = bt; - max_int[i] = bt & ~(1L << ((i << 3) - 1)); + max_int[i] = bt & ~(1L << ((8 * i) - 1)); min_int[i] = - max_int[i]; if (! options['s']) min_int[i]--; } - mach_long_size = i; - mach_long_sign = 1L << (mach_long_size * 8 - 1); - if (long_size > mach_long_size) { - fatal("sizeof (long) insufficient on this machine"); + if ((int)long_size > sizeof(arith)) { + fatal("sizeof (arith) insufficient on this machine"); } wrd_bits = 8 * (int) word_size; diff --git a/lang/m2/comp/type.H b/lang/m2/comp/type.H index 753d4d8fe..417d70f94 100644 --- a/lang/m2/comp/type.H +++ b/lang/m2/comp/type.H @@ -234,8 +234,8 @@ extern t_type #define IsBigParamTp(tpx) (0) #endif PASS_BIG_VAL_AS_VAR -extern long full_mask[]; -extern long max_int[]; -extern long min_int[]; +extern arith full_mask[]; +extern arith max_int[]; +extern arith min_int[]; #define ufit(n, i) (((n) & ~full_mask[(i)]) == 0) diff --git a/lang/m2/comp/type.c b/lang/m2/comp/type.c index 64da373a5..7510cb54d 100644 --- a/lang/m2/comp/type.c +++ b/lang/m2/comp/type.c @@ -298,9 +298,9 @@ chk_bounds(l1, l2, fund) if (fund == T_INTEGER) { return l2 >= l1; } - return (l2 & mach_long_sign ? - (l1 & mach_long_sign ? l2 >= l1 : 1) : - (l1 & mach_long_sign ? 0 : l2 >= l1) + return (l2 & arith_sign ? + (l1 & arith_sign ? l2 >= l1 : 1) : + (l1 & arith_sign ? 0 : l2 >= l1) ); }