changed name of some identifiers to more accurately represent their

meaning, and fixed a problem with sometimes not detecting overflow in
constants
This commit is contained in:
ceriel 1989-08-08 09:11:32 +00:00
parent b1347283b9
commit d277946286
5 changed files with 84 additions and 53 deletions

View file

@ -458,7 +458,7 @@ again:
/* Fall through */ /* Fall through */
case End: { case End: {
int sgnswtch = 0; int ovfl = 0;
*np = '\0'; *np = '\0';
if (np >= &buf[NUMSIZE]) { if (np >= &buf[NUMSIZE]) {
@ -466,11 +466,19 @@ again:
lexerror("constant too long"); lexerror("constant too long");
} }
else { 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]; np = &buf[1];
while (*np == '0') np++; while (*np == '0') np++;
tk->TOK_INT = 0; tk->TOK_INT = 0;
while (*np) { while (*np) {
arith old = tk->TOK_INT;
int c; int c;
if (is_dig(*np)) { if (is_dig(*np)) {
@ -480,38 +488,46 @@ again:
assert(is_hex(*np)); assert(is_hex(*np));
c = *np++ - 'A' + 10; c = *np++ - 'A' + 10;
} }
tk->TOK_INT = tk->TOK_INT*base if (tk->TOK_INT < 0 ||
+ c; tk->TOK_INT > ubound) {
sgnswtch += (old < 0) ^ ovfl++;
(tk->TOK_INT < 0); }
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; toktype = card_type;
if (sgnswtch >= 2) { if (ch == 'C' && base == 8) {
lexwarning(W_ORDINARY, "overflow in constant");
}
else if (ch == 'C' && base == 8) {
toktype = char_type; 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"); lexwarning(W_ORDINARY, "character constant out of range");
} }
return tk->tk_symb = INTEGER;
} }
else if (ch == 'D' && base == 10) { if (ch == 'D' && base == 10) {
if (sgnswtch != 0 || if (ovfl != 0 ||
tk->TOK_INT > max_int[(int)long_size]) { tk->TOK_INT > max_int[(int)long_size] ||
lexwarning(W_ORDINARY, "overflow in constant"); tk->TOK_INT < 0) {
ovfl = 1;
} }
toktype = longint_type; toktype = longint_type;
} }
else if (sgnswtch == 0 && else if (ovfl == 0 && tk->TOK_INT >= 0 &&
tk->TOK_INT<=max_int[(int)int_size]) { tk->TOK_INT<=max_int[(int)int_size]) {
toktype = intorcard_type; toktype = intorcard_type;
} }
else if (! chk_bounds(tk->TOK_INT, else if (! chk_bounds(tk->TOK_INT,
full_mask[(int)int_size], full_mask[(int)int_size],
T_CARDINAL)) { T_CARDINAL)) {
lexwarning(W_ORDINARY, "overflow in constant"); ovfl = 1;
} }
if (ovfl)
lexwarning(W_ORDINARY, "overflow in constant");
return tk->tk_symb = INTEGER; return tk->tk_symb = INTEGER;
} }

View file

@ -9,9 +9,7 @@
/* $Header$ */ /* $Header$ */
extern long #define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1)))
mach_long_sign; /* sign bit of the machine long */
extern int
mach_long_size; /* size of long on this machine == sizeof(long) */
extern unsigned int extern unsigned int
wrd_bits; /* Number of bits in a word */ wrd_bits; /* Number of bits in a word */

View file

@ -23,12 +23,11 @@
#include "Lpars.h" #include "Lpars.h"
#include "standards.h" #include "standards.h"
#include "warning.h" #include "warning.h"
#include "const.h"
long mach_long_sign; /* sign bit of the machine long */ arith full_mask[MAXSIZE];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */
int mach_long_size; /* size of long on this machine == sizeof(long) */ arith max_int[MAXSIZE]; /* max_int[1] == 0x7F, max_int[2] == 0x7FFF, .. */
long full_mask[MAXSIZE];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */ arith min_int[MAXSIZE]; /* min_int[1] == 0xFFFFFF80, min_int[2] = 0xFFFF8000,
long max_int[MAXSIZE]; /* max_int[1] == 0x7F, max_int[2] == 0x7FFF, .. */
long min_int[MAXSIZE]; /* min_int[1] == 0xFFFFFF80, min_int[2] = 0xFFFF8000,
... ...
*/ */
unsigned int wrd_bits; /* number of bits in a word */ 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. expression below it, and the result restored in expp.
*/ */
register t_node *right = expp->nd_right; register t_node *right = expp->nd_right;
arith o1 = right->nd_INT; register arith o1 = right->nd_INT;
switch(expp->nd_symb) { switch(expp->nd_symb) {
/* Should not get here /* Should not get here
@ -77,9 +76,9 @@ cstunary(expp)
*/ */
case '-': case '-':
if (o1 == min_int[(int)(right->nd_type->tp_size)]) if (o1 == min_int[(int)(right->nd_type->tp_size)]) {
overflow(expp); overflow(expp);
}
o1 = -o1; o1 = -o1;
break; break;
@ -110,10 +109,10 @@ divide(pdiv, prem)
think on C compilers which do not have think on C compilers which do not have
unsigned long. unsigned long.
*/ */
if (o2 & mach_long_sign) {/* o2 > max_long */ if (o2 & arith_sign) {/* o2 > max_arith */
if (! (o1 >= 0 || o1 < o2)) { if (! (o1 >= 0 || o1 < o2)) {
/* this is the unsigned test /* this is the unsigned test
o1 < o2 for o2 > max_long o1 < o2 for o2 > max_arith
*/ */
*prem = o2 - o1; *prem = o2 - o1;
*pdiv = 1; *pdiv = 1;
@ -122,14 +121,14 @@ divide(pdiv, prem)
*pdiv = 0; *pdiv = 0;
} }
} }
else { /* o2 <= max_long */ else { /* o2 <= max_arith */
long half, bit, hdiv, hrem, rem; arith half, bit, hdiv, hrem, rem;
half = (o1 >> 1) & ~mach_long_sign; half = (o1 >> 1) & ~arith_sign;
bit = o1 & 01; bit = o1 & 01;
/* now o1 == 2 * half + bit /* now o1 == 2 * half + bit
and half <= max_long and half <= max_arith
and bit <= max_long and bit <= max_arith
*/ */
hdiv = half / o2; hdiv = half / o2;
hrem = half % o2; hrem = half % o2;
@ -138,7 +137,7 @@ divide(pdiv, prem)
*prem = rem; *prem = rem;
if (rem < 0 || rem >= o2) { if (rem < 0 || rem >= o2) {
/* that is the unsigned compare /* that is the unsigned compare
rem >= o2 for o2 <= max_long rem >= o2 for o2 <= max_arith
*/ */
*pdiv += 1; *pdiv += 1;
*prem -= o2; *prem -= o2;
@ -153,8 +152,8 @@ cstibin(expp)
expressions below it, and the result restored in expp. expressions below it, and the result restored in expp.
This version is for INTEGER expressions. This version is for INTEGER expressions.
*/ */
arith o1 = expp->nd_left->nd_INT; register arith o1 = expp->nd_left->nd_INT;
arith o2 = expp->nd_right->nd_INT; register arith o2 = expp->nd_right->nd_INT;
register int sz = expp->nd_type->tp_size; register int sz = expp->nd_type->tp_size;
assert(expp->nd_class == Oper); assert(expp->nd_class == Oper);
@ -184,7 +183,17 @@ cstibin(expp)
node_error(expp, "division by 0"); node_error(expp, "division by 0");
return; 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; break;
case MOD: case MOD:
@ -192,7 +201,17 @@ cstibin(expp)
node_error(expp, "modulo by 0"); node_error(expp, "modulo by 0");
return; 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; break;
case '+': case '+':
@ -549,7 +568,7 @@ CutSize(expr)
expr->nd_INT &= full_mask[(int)(tp->tp_size)]; expr->nd_INT &= full_mask[(int)(tp->tp_size)];
} }
else { 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; expr->nd_INT = (expr->nd_INT << nbits) >> nbits;
} }
@ -566,14 +585,12 @@ InitCst()
if (i == MAXSIZE) if (i == MAXSIZE)
fatal("array full_mask too small for this machine"); fatal("array full_mask too small for this machine");
full_mask[i] = bt; 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]; min_int[i] = - max_int[i];
if (! options['s']) min_int[i]--; if (! options['s']) min_int[i]--;
} }
mach_long_size = i; if ((int)long_size > sizeof(arith)) {
mach_long_sign = 1L << (mach_long_size * 8 - 1); fatal("sizeof (arith) insufficient on this machine");
if (long_size > mach_long_size) {
fatal("sizeof (long) insufficient on this machine");
} }
wrd_bits = 8 * (int) word_size; wrd_bits = 8 * (int) word_size;

View file

@ -234,8 +234,8 @@ extern t_type
#define IsBigParamTp(tpx) (0) #define IsBigParamTp(tpx) (0)
#endif PASS_BIG_VAL_AS_VAR #endif PASS_BIG_VAL_AS_VAR
extern long full_mask[]; extern arith full_mask[];
extern long max_int[]; extern arith max_int[];
extern long min_int[]; extern arith min_int[];
#define ufit(n, i) (((n) & ~full_mask[(i)]) == 0) #define ufit(n, i) (((n) & ~full_mask[(i)]) == 0)

View file

@ -298,9 +298,9 @@ chk_bounds(l1, l2, fund)
if (fund == T_INTEGER) { if (fund == T_INTEGER) {
return l2 >= l1; return l2 >= l1;
} }
return (l2 & mach_long_sign ? return (l2 & arith_sign ?
(l1 & mach_long_sign ? l2 >= l1 : 1) : (l1 & arith_sign ? l2 >= l1 : 1) :
(l1 & mach_long_sign ? 0 : l2 >= l1) (l1 & arith_sign ? 0 : l2 >= l1)
); );
} }