newer version
This commit is contained in:
		
							parent
							
								
									629b8fdb88
								
							
						
					
					
						commit
						6ff4d852e1
					
				
					 8 changed files with 190 additions and 22 deletions
				
			
		|  | @ -50,6 +50,8 @@ chk_expr(expp, const) | ||||||
| 		return chk_call(expp, const); | 		return chk_call(expp, const); | ||||||
| 	case Link: | 	case Link: | ||||||
| 		return chk_name(expp, const); | 		return chk_name(expp, const); | ||||||
|  | 	default: | ||||||
|  | 		assert(0); | ||||||
| 	} | 	} | ||||||
| 	/*NOTREACHED*/ | 	/*NOTREACHED*/ | ||||||
| } | } | ||||||
|  | @ -58,7 +60,85 @@ int | ||||||
| chk_set(expp, const) | chk_set(expp, const) | ||||||
| 	register struct node *expp; | 	register struct node *expp; | ||||||
| { | { | ||||||
| 	/* ??? */ | 	struct type *tp; | ||||||
|  | 	struct def *df; | ||||||
|  | 	register struct node *nd; | ||||||
|  | 	extern struct def *findname(); | ||||||
|  | 
 | ||||||
|  | 	assert(expp->nd_symb == SET); | ||||||
|  | 
 | ||||||
|  | 	/* First determine the type of the set
 | ||||||
|  | 	*/ | ||||||
|  | 	if (expp->nd_left) { | ||||||
|  | 		/* A type was given. Check it out
 | ||||||
|  | 		*/ | ||||||
|  | 		df = findname(expp->nd_left); | ||||||
|  | 		if ((df->df_kind != D_TYPE && df->df_kind != D_ERROR) || | ||||||
|  | 		    (df->df_type->tp_fund != SET)) { | ||||||
|  | 			node_error(expp, "Illegal set type"); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		tp = df->df_type; | ||||||
|  | 	} | ||||||
|  | 	else	tp = bitset_type; | ||||||
|  | 
 | ||||||
|  | 	/* Now check the elements given
 | ||||||
|  | 	*/ | ||||||
|  | 	nd = expp->nd_right; | ||||||
|  | 	while (nd) { | ||||||
|  | 		assert(nd->nd_class == Link && nd->nd_symb == ','); | ||||||
|  | 		if (!chk_el(nd->nd_left, const, tp->next, 0)) return 0; | ||||||
|  | 		nd = nd->nd_right; | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | chk_el(expp, const, tp, level) | ||||||
|  | 	struct node *expp; | ||||||
|  | 	struct type *tp; | ||||||
|  | { | ||||||
|  | 	/*	Check elements of a set. This routine may call itself
 | ||||||
|  | 		recursively, but only once. | ||||||
|  | 	*/ | ||||||
|  | 	if (expp->nd_class == Link && expp->nd_symb == UPTO) { | ||||||
|  | 		/*  { ... , expr1 .. expr2,  ... } */ | ||||||
|  | 		if (level) { | ||||||
|  | 			node_error(expp, "Illegal set element"); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		if (!chk_el(expp->nd_left, const, tp, 1) || | ||||||
|  | 		    !chk_el(expp->nd_right, const, tp, 1)) { | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		if (expp->nd_left->nd_class == Value && | ||||||
|  | 		    expp->nd_right->nd_class == Value) { | ||||||
|  | 		    	if (expp->nd_left->nd_INT > expp->nd_right->nd_INT) { | ||||||
|  | node_error(expp, "Lower bound exceeds upper bound in range"); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	if (!chk_expr(expp, const)) return 0; | ||||||
|  | 	if (!TstCompat(tp, expp->nd_type)) { | ||||||
|  | 		node_error(expp, "Set element has incompatible type"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	if (expp->nd_class == Value) { | ||||||
|  | 	    	if ((tp->tp_fund != ENUMERATION && | ||||||
|  | 		     (expp->nd_INT < tp->sub_lb || expp->nd_INT > tp->sub_ub)) | ||||||
|  | 		   || | ||||||
|  | 		    (tp->tp_fund == ENUMERATION && | ||||||
|  | 		     (expp->nd_INT < 0 || expp->nd_INT > tp->enm_ncst)) | ||||||
|  | 		   ) { | ||||||
|  | 			node_error(expp, "Set element out of range"); | ||||||
|  | #ifdef DEBUG | ||||||
|  | 			debug("%d (%d, %d)", (int) expp->nd_INT, (int) tp->sub_lb, (int) tp->sub_ub); | ||||||
|  | #endif | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,5 +8,4 @@ extern int | ||||||
| 	mach_long_size;	/* size of long on this machine == sizeof(long) */ | 	mach_long_size;	/* size of long on this machine == sizeof(long) */ | ||||||
| extern arith | extern arith | ||||||
| 	max_int,	/* maximum integer on target machine	*/ | 	max_int,	/* maximum integer on target machine	*/ | ||||||
| 	max_unsigned,	/* maximum unsigned on target machine	*/ | 	max_unsigned;	/* maximum unsigned on target machine	*/ | ||||||
| 	max_longint;	/* maximum longint on target machine	*/ |  | ||||||
|  |  | ||||||
|  | @ -267,10 +267,10 @@ init_cst() | ||||||
| 	} | 	} | ||||||
| 	mach_long_size = i; | 	mach_long_size = i; | ||||||
| 	mach_long_sign = 1 << (mach_long_size * 8 - 1); | 	mach_long_sign = 1 << (mach_long_size * 8 - 1); | ||||||
| 	if (sizeof(long) < mach_long_size) | 	if (int_size > mach_long_size) { | ||||||
| 		fatal("sizeof (long) insufficient on this machine"); | 		fatal("sizeof (long) insufficient on this machine"); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	max_int = full_mask[int_size] & ~(1 << (int_size * 8 - 1)); | 	max_int = full_mask[int_size] & ~(1 << (int_size * 8 - 1)); | ||||||
| 	max_longint = full_mask[lint_size] & ~(1 << (lint_size * 8 - 1)); |  | ||||||
| 	max_unsigned = full_mask[int_size]; | 	max_unsigned = full_mask[int_size]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -233,8 +233,8 @@ IdentList(struct node **p;) | ||||||
| 
 | 
 | ||||||
| SubrangeType(struct type **ptp;) | SubrangeType(struct type **ptp;) | ||||||
| { | { | ||||||
| 	struct type *tp; | 	struct node *nd1, *nd2; | ||||||
| 	struct node *nd1 = 0, *nd2 = 0; | 	extern struct type *subr_type(); | ||||||
| }: | }: | ||||||
| 	/* | 	/* | ||||||
| 	   This is not exactly the rule in the new report, but see | 	   This is not exactly the rule in the new report, but see | ||||||
|  | @ -243,17 +243,7 @@ SubrangeType(struct type **ptp;) | ||||||
| 	'[' ConstExpression(&nd1) | 	'[' ConstExpression(&nd1) | ||||||
| 	UPTO ConstExpression(&nd2) | 	UPTO ConstExpression(&nd2) | ||||||
| 	']' | 	']' | ||||||
| 	/* | 			{ *ptp = subr_type(nd1, nd2); } | ||||||
| 	   Evaluate the expressions. Check that they are indeed constant. |  | ||||||
| 	   ??? |  | ||||||
| 	   Leave the basetype of the subrange in tp; |  | ||||||
| 	*/ |  | ||||||
| 			{ |  | ||||||
| 			  /* For the time being: */ |  | ||||||
| 			  tp = int_type; |  | ||||||
| 			  tp = construct_type(SUBRANGE, tp); |  | ||||||
| 			  *ptp = tp; |  | ||||||
| 			} |  | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| ArrayType(struct type **ptp;) | ArrayType(struct type **ptp;) | ||||||
|  | @ -350,10 +340,11 @@ CaseLabels | ||||||
| SetType(struct type **ptp;) | SetType(struct type **ptp;) | ||||||
| { | { | ||||||
| 	struct type *tp; | 	struct type *tp; | ||||||
|  | 	struct type *set_type(); | ||||||
| } : | } : | ||||||
| 	SET OF SimpleType(&tp) | 	SET OF SimpleType(&tp) | ||||||
| 			{ | 			{  | ||||||
| 			  *ptp = construct_type(SET, tp); | 			  *ptp = set_type(tp); | ||||||
| 			} | 			} | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ GetFile(name) | ||||||
| 	*/ | 	*/ | ||||||
| 	extern char *DEFPATH[]; | 	extern char *DEFPATH[]; | ||||||
| 	char buf[256]; | 	char buf[256]; | ||||||
|  | 	char *strcpy(), *strcat(); | ||||||
| 
 | 
 | ||||||
| 	(void) strcpy(buf, name); | 	(void) strcpy(buf, name); | ||||||
| 	if (strlen(buf) > 10) { | 	if (strlen(buf) > 10) { | ||||||
|  |  | ||||||
|  | @ -91,6 +91,7 @@ ConstExpression(struct node **pnd;): | ||||||
| 		     ( debug("Constant expression:"), | 		     ( debug("Constant expression:"), | ||||||
| 		       PrNode(*pnd))); | 		       PrNode(*pnd))); | ||||||
| 		  (void) chk_expr(*pnd, 1); | 		  (void) chk_expr(*pnd, 1); | ||||||
|  | 		  DO_DEBUG(3, PrNode(*pnd)); | ||||||
| 		} | 		} | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,8 @@ static char *RcsId = "$Header$"; | ||||||
| #include	"idf.h" | #include	"idf.h" | ||||||
| #include	"LLlex.h" | #include	"LLlex.h" | ||||||
| #include	"node.h" | #include	"node.h" | ||||||
|  | #include	"const.h" | ||||||
|  | #include	"debug.h" | ||||||
| 
 | 
 | ||||||
| /*	To be created dynamically in main() from defaults or from command
 | /*	To be created dynamically in main() from defaults or from command
 | ||||||
| 	line parameters. | 	line parameters. | ||||||
|  | @ -129,6 +131,7 @@ init_types() | ||||||
| 	register struct type *tp; | 	register struct type *tp; | ||||||
| 
 | 
 | ||||||
| 	char_type = standard_type(CHAR, 1, (arith) 1); | 	char_type = standard_type(CHAR, 1, (arith) 1); | ||||||
|  | 	char_type->enm_ncst = 256; | ||||||
| 	bool_type = standard_type(BOOLEAN, 1, (arith) 1); | 	bool_type = standard_type(BOOLEAN, 1, (arith) 1); | ||||||
| 	int_type = standard_type(INTEGER, int_align, int_size); | 	int_type = standard_type(INTEGER, int_align, int_size); | ||||||
| 	longint_type = standard_type(LONGINT, lint_align, lint_size); | 	longint_type = standard_type(LONGINT, lint_align, lint_size); | ||||||
|  | @ -217,8 +220,87 @@ chk_basesubrange(tp, base) | ||||||
| 	else if (base != card_type && base != int_type) { | 	else if (base != card_type && base != int_type) { | ||||||
| 		error("Illegal base for a subrange"); | 		error("Illegal base for a subrange"); | ||||||
| 	} | 	} | ||||||
|  | 	else if (base == int_type && tp->next == card_type && | ||||||
|  | 		 (tp->sub_ub > max_int || tp->sub_ub)) { | ||||||
|  | 		error("Upperbound to large for type INTEGER"); | ||||||
|  | 	} | ||||||
| 	else if (base != tp->next && base != int_type) { | 	else if (base != tp->next && base != int_type) { | ||||||
| 		error("Specified base does not conform"); | 		error("Specified base does not conform"); | ||||||
| 	} | 	} | ||||||
| 	tp->next = base; | 	tp->next = base; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | struct type * | ||||||
|  | subr_type(lb, ub) | ||||||
|  | 	struct node *lb, *ub; | ||||||
|  | { | ||||||
|  | 	/*	Construct a subrange type from the constant expressions
 | ||||||
|  | 		indicated by "lb" and "ub", but first perform some | ||||||
|  | 		checks | ||||||
|  | 	*/ | ||||||
|  | 	register struct type *tp = lb->nd_type; | ||||||
|  | 
 | ||||||
|  | 	if (!TstCompat(lb->nd_type, ub->nd_type)) { | ||||||
|  | 		node_error(ub, "Types of subrange bounds not compatible"); | ||||||
|  | 		return error_type; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (tp->tp_fund == SUBRANGE) tp = tp->next; | ||||||
|  | 	if (tp == intorcard_type) tp = card_type;	/* lower bound > 0 */ | ||||||
|  | 
 | ||||||
|  | 	/* Check base type
 | ||||||
|  | 	*/ | ||||||
|  | 	if (tp != int_type && tp != card_type && tp != char_type && | ||||||
|  | 	    tp->tp_fund != ENUMERATION) { | ||||||
|  | 		/* BOOLEAN is also an ENUMERATION type
 | ||||||
|  | 		*/ | ||||||
|  | 		node_error(ub, "Illegal base type for subrange"); | ||||||
|  | 		return error_type; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Check bounds
 | ||||||
|  | 	*/ | ||||||
|  | 	if (lb->nd_INT > ub->nd_INT) { | ||||||
|  | 		node_error(ub, "Lower bound exceeds upper bound"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Now construct resulting type
 | ||||||
|  | 	*/ | ||||||
|  | 	tp = construct_type(SUBRANGE, tp); | ||||||
|  | 	tp->sub_lb = lb->nd_INT; | ||||||
|  | 	tp->sub_ub = ub->nd_INT; | ||||||
|  | 	DO_DEBUG(2,debug("Creating subrange type %ld-%ld", (long)lb->nd_INT,(long)ub->nd_INT)); | ||||||
|  | 	return tp; | ||||||
|  | } | ||||||
|  | #define MAX_SET	1024	/* ??? Maximum number of elements in a set */ | ||||||
|  | 
 | ||||||
|  | struct type * | ||||||
|  | set_type(tp) | ||||||
|  | 	struct type *tp; | ||||||
|  | { | ||||||
|  | 	/*	Construct a set type with base type "tp", but first
 | ||||||
|  | 		perform some checks | ||||||
|  | 	*/ | ||||||
|  | 	int lb, ub; | ||||||
|  | 
 | ||||||
|  | 	if (tp->tp_fund == SUBRANGE) { | ||||||
|  | 		if ((lb = tp->sub_lb) < 0 || (ub = tp->sub_ub) > MAX_SET - 1) { | ||||||
|  | 			error("Set type limits exceeded"); | ||||||
|  | 			return error_type; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if (tp->tp_fund == ENUMERATION || tp == char_type) { | ||||||
|  | 		lb = 0; | ||||||
|  | 		if ((ub = tp->enm_ncst - 1) > MAX_SET - 1) { | ||||||
|  | 			error("Set type limits exceeded"); | ||||||
|  | 			return error_type; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		error("illegal base type for set"); | ||||||
|  | 		return error_type; | ||||||
|  | 	} | ||||||
|  | 	tp = construct_type(SET, tp); | ||||||
|  | 	tp->tp_size = align(((ub - lb) + 7)/8, wrd_align); | ||||||
|  | 	return tp; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -19,6 +19,10 @@ TstTypeEquiv(tp1, tp2) | ||||||
| 	*/ | 	*/ | ||||||
| 
 | 
 | ||||||
| 	return     tp1 == tp2 | 	return     tp1 == tp2 | ||||||
|  | 		|| | ||||||
|  | 		   tp1 == error_type | ||||||
|  | 		|| | ||||||
|  | 		   tp2 == error_type | ||||||
| 		|| | 		|| | ||||||
| 		   (  | 		   (  | ||||||
| 		     tp1 && tp1->tp_fund == PROCEDURE | 		     tp1 && tp1->tp_fund == PROCEDURE | ||||||
|  | @ -61,9 +65,19 @@ TstCompat(tp1, tp2) | ||||||
| 		Modula-2 Report for a definition of "compatible". | 		Modula-2 Report for a definition of "compatible". | ||||||
| 	*/ | 	*/ | ||||||
| 	if (TstTypeEquiv(tp1, tp2)) return 1; | 	if (TstTypeEquiv(tp1, tp2)) return 1; | ||||||
| 	if (tp2->tp_fund == SUBRANGE) tp1 = tp1->next; | 	if (tp1->tp_fund == SUBRANGE) tp1 = tp1->next; | ||||||
| 	if (tp2->tp_fund == SUBRANGE) tp1 = tp1->next; | 	if (tp2->tp_fund == SUBRANGE) tp2 = tp2->next; | ||||||
| 	return	tp1 == tp2 | 	return	tp1 == tp2 | ||||||
|  | 	    || | ||||||
|  | 		(  tp1 == intorcard_type | ||||||
|  | 		&& | ||||||
|  | 		   (tp2 == int_type || tp2 == card_type) | ||||||
|  | 		) | ||||||
|  | 	    || | ||||||
|  | 		(  tp2 == intorcard_type | ||||||
|  | 		&& | ||||||
|  | 		   (tp1 == int_type || tp1 == card_type) | ||||||
|  | 		) | ||||||
| 	    || | 	    || | ||||||
| 		(  tp1 == address_type | 		(  tp1 == address_type | ||||||
| 		&&  | 		&&  | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue