Procházet zdrojové kódy

changed name of some identifiers to more accurately represent their
meaning, and fixed a problem with sometimes not detecting overflow in
constants

ceriel před 35 roky
rodič
revize
7c75d4cd21
5 změnil soubory, kde provedl 84 přidání a 53 odebrání
  1. 33 17
      lang/m2/comp/LLlex.c
  2. 2 4
      lang/m2/comp/const.h
  3. 43 26
      lang/m2/comp/cstoper.c
  4. 3 3
      lang/m2/comp/type.H
  5. 3 3
      lang/m2/comp/type.c

+ 33 - 17
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;
 				}
 

+ 2 - 4
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 */

+ 43 - 26
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;

+ 3 - 3
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)

+ 3 - 3
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)
 	       );
 }