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:
parent
b1347283b9
commit
d277946286
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue