revised the administration of Value expressions
This commit is contained in:
		
							parent
							
								
									fac31cce07
								
							
						
					
					
						commit
						66c571d217
					
				
					 14 changed files with 317 additions and 295 deletions
				
			
		|  | @ -190,10 +190,10 @@ idf.o: LLlex.h Lpars.h align.h alloc.h arith.h assert.h botch_free.h debug.h dec | ||||||
| declarator.o: Lpars.h alloc.h arith.h botch_free.h declar.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h | declarator.o: Lpars.h alloc.h arith.h botch_free.h declar.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h | ||||||
| decspecs.o: Lpars.h arith.h decspecs.h def.h level.h nobitfield.h spec_arith.h type.h | decspecs.o: Lpars.h arith.h decspecs.h def.h level.h nobitfield.h spec_arith.h type.h | ||||||
| struct.o: LLlex.h Lpars.h align.h arith.h assert.h botch_free.h debug.h def.h field.h idf.h level.h nobitfield.h nopp.h sizes.h spec_arith.h stack.h storage.h struct.h type.h | struct.o: LLlex.h Lpars.h align.h arith.h assert.h botch_free.h debug.h def.h field.h idf.h level.h nobitfield.h nopp.h sizes.h spec_arith.h stack.h storage.h struct.h type.h | ||||||
| expr.o: LLlex.h Lpars.h alloc.h arith.h botch_free.h declar.h decspecs.h def.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h | expr.o: LLlex.h Lpars.h alloc.h arith.h botch_free.h declar.h decspecs.h def.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h level.h | ||||||
| ch7.o: Lpars.h arith.h assert.h debug.h def.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h struct.h type.h | ch7.o: Lpars.h arith.h assert.h debug.h def.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h struct.h type.h | ||||||
| ch7bin.o: Lpars.h arith.h botch_free.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h storage.h struct.h type.h | ch7bin.o: Lpars.h arith.h botch_free.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h storage.h struct.h type.h | ||||||
| cstoper.o: Lpars.h arith.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h target_sizes.h type.h | cstoper.o: Lpars.h arith.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h target_sizes.h type.h assert.h | ||||||
| arith.o: Lpars.h alloc.h arith.h botch_free.h expr.h field.h idf.h label.h mes.h nobitfield.h nopp.h spec_arith.h storage.h type.h | arith.o: Lpars.h alloc.h arith.h botch_free.h expr.h field.h idf.h label.h mes.h nobitfield.h nopp.h spec_arith.h storage.h type.h | ||||||
| alloc.o: alloc.h assert.h debug.h myalloc.h | alloc.o: alloc.h assert.h debug.h myalloc.h | ||||||
| code.o: LLlex.h Lpars.h alloc.h arith.h assert.h atw.h botch_free.h code.h dataflow.h debug.h declar.h decspecs.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nopp.h sizes.h spec_arith.h specials.h stack.h storage.h type.h use_tmp.h | code.o: LLlex.h Lpars.h alloc.h arith.h assert.h atw.h botch_free.h code.h dataflow.h debug.h declar.h decspecs.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nopp.h sizes.h spec_arith.h specials.h stack.h storage.h type.h use_tmp.h | ||||||
|  |  | ||||||
|  | @ -257,18 +257,16 @@ float2float(expp, tp) | ||||||
| 	*/ | 	*/ | ||||||
| 	 | 	 | ||||||
| 	fp_used = 1; | 	fp_used = 1; | ||||||
| 	if (is_fp_cst(*expp))	{ | 	if (is_fp_cst(*expp)) | ||||||
| 		(*expp)->ex_type = tp; | 		(*expp)->ex_type = tp; | ||||||
| 	} | 	else | ||||||
| 	else	{ |  | ||||||
| 		*expp = arith2arith(tp, FLOAT2FLOAT, *expp); | 		*expp = arith2arith(tp, FLOAT2FLOAT, *expp); | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| array2pointer(expp) | array2pointer(expp) | ||||||
| 	struct expr **expp; | 	struct expr **expp; | ||||||
| { | { | ||||||
| 	/*	The expression, which must be an array, it is converted
 | 	/*	The expression, which must be an array, is converted
 | ||||||
| 		to a pointer. | 		to a pointer. | ||||||
| 	*/ | 	*/ | ||||||
| 	(*expp)->ex_type = | 	(*expp)->ex_type = | ||||||
|  | @ -278,13 +276,29 @@ array2pointer(expp) | ||||||
| function2pointer(expp) | function2pointer(expp) | ||||||
| 	struct expr **expp; | 	struct expr **expp; | ||||||
| { | { | ||||||
| 	/*	The expression, which must be a function, it is converted
 | 	/*	The expression, which must be a function, is converted
 | ||||||
| 		to a pointer to the function. | 		to a pointer to the function. | ||||||
| 	*/ | 	*/ | ||||||
| 	(*expp)->ex_type = | 	(*expp)->ex_type = | ||||||
| 		construct_type(POINTER, (*expp)->ex_type, (arith)0); | 		construct_type(POINTER, (*expp)->ex_type, (arith)0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | string2pointer(expp) | ||||||
|  | 	struct expr **expp; | ||||||
|  | { | ||||||
|  | 	/*	The expression, which must be a string constant, is converted
 | ||||||
|  | 		to a pointer to the string-containing area. | ||||||
|  | 	*/ | ||||||
|  | 	struct expr *ex = *expp; | ||||||
|  | 	label lbl = data_label(); | ||||||
|  | 
 | ||||||
|  | 	code_string(ex->SG_VALUE, ex->SG_LEN, lbl); | ||||||
|  | 	ex->ex_class = Value; | ||||||
|  | 	ex->VL_CLASS = Label; | ||||||
|  | 	ex->VL_LBL = lbl; | ||||||
|  | 	ex->VL_VALUE = (arith)0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| opnd2integral(expp, oper) | opnd2integral(expp, oper) | ||||||
| 	struct expr **expp; | 	struct expr **expp; | ||||||
| 	int oper; | 	int oper; | ||||||
|  | @ -421,6 +435,10 @@ any2opnd(expp, oper) | ||||||
| 	case ARRAY: | 	case ARRAY: | ||||||
| 		array2pointer(expp); | 		array2pointer(expp); | ||||||
| 		break; | 		break; | ||||||
|  | 	case POINTER: | ||||||
|  | 		if ((*expp)->ex_class == String) | ||||||
|  | 			string2pointer(expp); | ||||||
|  | 		break; | ||||||
| #ifndef NOBITFIELD | #ifndef NOBITFIELD | ||||||
| 	case FIELD: | 	case FIELD: | ||||||
| 		field2arith(expp); | 		field2arith(expp); | ||||||
|  |  | ||||||
|  | @ -109,6 +109,7 @@ ch7sel(expp, oper, idf) | ||||||
| 			struct oper *op = &((*expp)->ex_object.ex_oper); | 			struct oper *op = &((*expp)->ex_object.ex_oper); | ||||||
| 			 | 			 | ||||||
| 			if (op->op_oper == '.' || op->op_oper == ARROW)	{ | 			if (op->op_oper == '.' || op->op_oper == ARROW)	{ | ||||||
|  | 				ASSERT(is_cp_cst(op->op_right)); | ||||||
| 				op->op_right->VL_VALUE += sd->sd_offset; | 				op->op_right->VL_VALUE += sd->sd_offset; | ||||||
| 				(*expp)->ex_type = sd->sd_type; | 				(*expp)->ex_type = sd->sd_type; | ||||||
| 				if ((*expp)->ex_type == error_type) | 				if ((*expp)->ex_type == error_type) | ||||||
|  | @ -188,6 +189,8 @@ ch7cast(expp, oper, tp) | ||||||
| 		function2pointer(expp); | 		function2pointer(expp); | ||||||
| 	if ((*expp)->ex_type->tp_fund == ARRAY) | 	if ((*expp)->ex_type->tp_fund == ARRAY) | ||||||
| 		array2pointer(expp); | 		array2pointer(expp); | ||||||
|  | 	if ((*expp)->ex_class == String) | ||||||
|  | 		string2pointer(expp); | ||||||
| 	oldtp = (*expp)->ex_type; | 	oldtp = (*expp)->ex_type; | ||||||
| 	if (oldtp == tp) | 	if (oldtp == tp) | ||||||
| 		{}			/* life is easy */ | 		{}			/* life is easy */ | ||||||
|  |  | ||||||
|  | @ -46,13 +46,11 @@ ch7mon(oper, expp) | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case '&': | 	case '&': | ||||||
| 		if ((*expp)->ex_type->tp_fund == ARRAY)	{ | 		if ((*expp)->ex_type->tp_fund == ARRAY) | ||||||
| 			array2pointer(expp); | 			array2pointer(expp); | ||||||
| 		} |  | ||||||
| 		else | 		else | ||||||
| 		if ((*expp)->ex_type->tp_fund == FUNCTION)	{ | 		if ((*expp)->ex_type->tp_fund == FUNCTION) | ||||||
| 			function2pointer(expp); | 			function2pointer(expp); | ||||||
| 		} |  | ||||||
| 		else | 		else | ||||||
| #ifndef NOBITFIELD | #ifndef NOBITFIELD | ||||||
| 		if ((*expp)->ex_type->tp_fund == FIELD)	{ | 		if ((*expp)->ex_type->tp_fund == FIELD)	{ | ||||||
|  | @ -65,12 +63,15 @@ ch7mon(oper, expp) | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			/* assume that enums are already filtered out	*/ | 			/* assume that enums are already filtered out	*/ | ||||||
| 			if ((*expp)->ex_class == Value && (*expp)->VL_IDF) { | 			if (	(*expp)->ex_class == Value | ||||||
|  | 			&&	(*expp)->VL_CLASS == Name | ||||||
|  | 			) { | ||||||
| 				register struct def *def = | 				register struct def *def = | ||||||
| 					(*expp)->VL_IDF->id_def; | 					(*expp)->VL_IDF->id_def; | ||||||
| 
 | 
 | ||||||
| 				/*	&<var> indicates that <var> cannot
 | 				/*	&<var> indicates that <var>
 | ||||||
| 					be used as register anymore | 					cannot be used as register | ||||||
|  | 					anymore | ||||||
| 				*/ | 				*/ | ||||||
| 				if (def->df_sc == REGISTER) { | 				if (def->df_sc == REGISTER) { | ||||||
| 					expr_error(*expp, | 					expr_error(*expp, | ||||||
|  | @ -98,11 +99,7 @@ ch7mon(oper, expp) | ||||||
| 		any2arith(expp, oper); | 		any2arith(expp, oper); | ||||||
| 		if (is_cp_cst(*expp))	{ | 		if (is_cp_cst(*expp))	{ | ||||||
| 			arith o1 = (*expp)->VL_VALUE; | 			arith o1 = (*expp)->VL_VALUE; | ||||||
| 			if (oper == '-') | 			(*expp)->VL_VALUE = (oper == '-') ? -o1 : ~o1; | ||||||
| 				o1 = -o1; |  | ||||||
| 			else |  | ||||||
| 				o1 = ~o1; |  | ||||||
| 			(*expp)->VL_VALUE = o1; |  | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		if (is_fp_cst(*expp)) | 		if (is_fp_cst(*expp)) | ||||||
|  | @ -118,9 +115,7 @@ ch7mon(oper, expp) | ||||||
| 			any2arith(expp, oper); | 			any2arith(expp, oper); | ||||||
| 		opnd2test(expp, '!'); | 		opnd2test(expp, '!'); | ||||||
| 		if (is_cp_cst(*expp))	{ | 		if (is_cp_cst(*expp))	{ | ||||||
| 			arith o1 = (*expp)->VL_VALUE; | 			(*expp)->VL_VALUE = !((*expp)->VL_VALUE); | ||||||
| 			o1 = !o1; |  | ||||||
| 			(*expp)->VL_VALUE = o1; |  | ||||||
| 			(*expp)->ex_type = int_type; | 			(*expp)->ex_type = int_type; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
|  | @ -133,7 +128,7 @@ ch7mon(oper, expp) | ||||||
| 		break; | 		break; | ||||||
| 	case SIZEOF: | 	case SIZEOF: | ||||||
| 		if (	(*expp)->ex_class == Value | 		if (	(*expp)->ex_class == Value | ||||||
| 		&&	(*expp)->VL_IDF | 		&&	(*expp)->VL_CLASS == Name | ||||||
| 		&&	(*expp)->VL_IDF->id_def->df_formal_array | 		&&	(*expp)->VL_IDF->id_def->df_formal_array | ||||||
| 		) | 		) | ||||||
| 			warning("sizeof formal array %s is sizeof pointer!", | 			warning("sizeof formal array %s is sizeof pointer!", | ||||||
|  |  | ||||||
|  | @ -59,11 +59,41 @@ famous_first_words() | ||||||
| 	C_ms_emx(word_size, pointer_size); | 	C_ms_emx(word_size, pointer_size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static struct string_cst *str_list = 0; | ||||||
|  | 
 | ||||||
|  | code_string(val, len, dlb) | ||||||
|  | 	char *val; | ||||||
|  | 	int len; | ||||||
|  | 	label dlb; | ||||||
|  | { | ||||||
|  | 	struct string_cst *sc = new_string_cst(); | ||||||
|  | 
 | ||||||
|  | 	C_ina_dlb(dlb); | ||||||
|  | 	sc->next = str_list; | ||||||
|  | 	str_list = sc; | ||||||
|  | 	sc->sc_value = val; | ||||||
|  | 	sc->sc_len = len; | ||||||
|  | 	sc->sc_dlb = dlb; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | def_strings(sc) | ||||||
|  | 	register struct string_cst *sc; | ||||||
|  | { | ||||||
|  | 	if (sc) { | ||||||
|  | 		def_strings(sc->next); | ||||||
|  | 		C_df_dlb(sc->sc_dlb); | ||||||
|  | 		C_con_scon(sc->sc_value, sc->sc_len); | ||||||
|  | 		free_string_cst(sc); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| end_code() | end_code() | ||||||
| { | { | ||||||
| 	/*	end_code() performs the actions to be taken when closing
 | 	/*	end_code() performs the actions to be taken when closing
 | ||||||
| 		the output stream. | 		the output stream. | ||||||
| 	*/ | 	*/ | ||||||
|  | 	def_strings(str_list); | ||||||
|  | 	str_list = 0; | ||||||
| 	C_ms_src((arith)(LineNumber - 2), FileName); | 	C_ms_src((arith)(LineNumber - 2), FileName); | ||||||
| 	C_close(); | 	C_close(); | ||||||
| } | } | ||||||
|  | @ -351,6 +381,7 @@ loc_init(expr, id) | ||||||
| 	*/ | 	*/ | ||||||
| 	register struct type *tp = id->id_def->df_type; | 	register struct type *tp = id->id_def->df_type; | ||||||
| 	 | 	 | ||||||
|  | 	ASSERT(id->id_def->df_sc != STATIC); | ||||||
| 	/* automatic aggregates cannot be initialised. */ | 	/* automatic aggregates cannot be initialised. */ | ||||||
| 	switch (tp->tp_fund)	{ | 	switch (tp->tp_fund)	{ | ||||||
| 	case ARRAY: | 	case ARRAY: | ||||||
|  | @ -374,9 +405,14 @@ loc_init(expr, id) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else	{	/* not embraced	*/ | 	else	{	/* not embraced	*/ | ||||||
|  | 		struct value vl; | ||||||
|  | 
 | ||||||
| 		ch7cast(&expr, '=', tp); | 		ch7cast(&expr, '=', tp); | ||||||
| 		EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); | 		EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||||
| 		store_val(id, tp, (arith) 0); | 		vl.vl_class = Name; | ||||||
|  | 		vl.vl_data.vl_idf = id; | ||||||
|  | 		vl.vl_value = (arith)0; | ||||||
|  | 		store_val(&vl, tp); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,15 @@ struct stat_block	{ | ||||||
| 
 | 
 | ||||||
| /* ALLOCDEF "stat_block" */ | /* ALLOCDEF "stat_block" */ | ||||||
| 
 | 
 | ||||||
|  | struct string_cst	{	/* storing string constants */ | ||||||
|  | 	struct string_cst *next; | ||||||
|  | 	char *sc_value; | ||||||
|  | 	int sc_len; | ||||||
|  | 	label sc_dlb; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* ALLOCDEF "string_cst" */ | ||||||
|  | 
 | ||||||
| #define	LVAL	0 | #define	LVAL	0 | ||||||
| #define	RVAL	1 | #define	RVAL	1 | ||||||
| #define	FALSE	0 | #define	FALSE	0 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ | ||||||
| #include	"expr.h" | #include	"expr.h" | ||||||
| #include	"sizes.h" | #include	"sizes.h" | ||||||
| #include	"Lpars.h" | #include	"Lpars.h" | ||||||
|  | #include	"assert.h" | ||||||
| 
 | 
 | ||||||
| long mach_long_sign;	/* sign bit of the machine long */ | long mach_long_sign;	/* sign bit of the machine long */ | ||||||
| int mach_long_size;	/* size of long on this machine == sizeof(long) */ | int mach_long_size;	/* size of long on this machine == sizeof(long) */ | ||||||
|  | @ -21,13 +22,14 @@ cstbin(expp, oper, expr) | ||||||
| 	struct expr **expp, *expr; | 	struct expr **expp, *expr; | ||||||
| { | { | ||||||
| 	/*	The operation oper is performed on the constant
 | 	/*	The operation oper is performed on the constant
 | ||||||
| 		expressions *expp and expr, and the result restored in | 		expressions *expp(ld) and expr(ct), and the result restored in | ||||||
| 		*expp. | 		*expp. | ||||||
| 	*/ | 	*/ | ||||||
| 	arith o1 = (*expp)->VL_VALUE; | 	arith o1 = (*expp)->VL_VALUE; | ||||||
| 	arith o2 = expr->VL_VALUE; | 	arith o2 = expr->VL_VALUE; | ||||||
| 	int uns = (*expp)->ex_type->tp_unsigned; | 	int uns = (*expp)->ex_type->tp_unsigned; | ||||||
| 
 | 
 | ||||||
|  | 	ASSERT(is_ld_cst(*expp) && is_cp_cst(expr)); | ||||||
| 	switch (oper)	{ | 	switch (oper)	{ | ||||||
| 	case '*': | 	case '*': | ||||||
| 		o1 *= o2; | 		o1 *= o2; | ||||||
|  | @ -190,6 +192,7 @@ cut_size(expr) | ||||||
| 	int uns = expr->ex_type->tp_unsigned; | 	int uns = expr->ex_type->tp_unsigned; | ||||||
| 	int size = (int) expr->ex_type->tp_size; | 	int size = (int) expr->ex_type->tp_size; | ||||||
| 
 | 
 | ||||||
|  | 	ASSERT(expr->ex_class == Value); | ||||||
| 	if (uns) { | 	if (uns) { | ||||||
| 		if (o1 & ~full_mask[size]) | 		if (o1 & ~full_mask[size]) | ||||||
| 			expr_warning(expr, | 			expr_warning(expr, | ||||||
|  |  | ||||||
|  | @ -331,14 +331,24 @@ p1_expr(lvl, expr) | ||||||
| 		expr->ex_class == Type ? "Type" : "UNKNOWN CLASS" | 		expr->ex_class == Type ? "Type" : "UNKNOWN CLASS" | ||||||
| 	); | 	); | ||||||
| 	switch (expr->ex_class)	{ | 	switch (expr->ex_class)	{ | ||||||
| 		struct value *v; |  | ||||||
| 		struct oper *o; | 		struct oper *o; | ||||||
| 	case Value: | 	case Value: | ||||||
| 		v = &expr->ex_object.ex_value; | 		switch (expr->VL_CLASS) { | ||||||
| 		if (v->vl_idf) | 		case Const: | ||||||
| 			printf("%s + ", v->vl_idf->id_text); | 			printf("(Const) "); | ||||||
|  | 			break; | ||||||
|  | 		case Name: | ||||||
|  | 			printf("(Name) %s + ", expr->VL_IDF->id_text); | ||||||
|  | 			break; | ||||||
|  | 		case Label: | ||||||
|  | 			printf("(Label) .%lu + ", expr->VL_LBL); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			printf("(Unknown) "); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| 		printf(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n", | 		printf(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n", | ||||||
| 				v->vl_value); | 			expr->VL_VALUE); | ||||||
| 		break; | 		break; | ||||||
| 	case String: | 	case String: | ||||||
| 	{ | 	{ | ||||||
|  |  | ||||||
|  | @ -80,22 +80,17 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 	register gencode = (code == TRUE); | 	register gencode = (code == TRUE); | ||||||
| 
 | 
 | ||||||
| 	switch (expr->ex_class)	{ | 	switch (expr->ex_class)	{ | ||||||
| 
 |  | ||||||
| 	case Value:	/* just a simple value	*/ | 	case Value:	/* just a simple value	*/ | ||||||
| 		if (gencode) | 		if (gencode) | ||||||
| 			load_val(expr, val); | 			load_val(expr, val); | ||||||
| 		break; | 		break; | ||||||
| 
 |  | ||||||
| 	case String:	/* a string constant	*/ | 	case String:	/* a string constant	*/ | ||||||
|  | 		expr_warning(expr, "(DEBUG) value-class 'String' seen"); | ||||||
| 		if (gencode) { | 		if (gencode) { | ||||||
| 			label datlab = data_label(); | 			string2pointer(&expr); | ||||||
| 			 | 			C_lae_dlb(expr->VL_LBL, expr->VL_VALUE); | ||||||
| 			C_df_dlb(datlab); |  | ||||||
| 			C_con_scon(expr->SG_VALUE, (arith)expr->SG_LEN); |  | ||||||
| 			C_lae_dlb(datlab, (arith)0); |  | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 
 |  | ||||||
| 	case Float:	/* a floating constant	*/ | 	case Float:	/* a floating constant	*/ | ||||||
| 		if (gencode) { | 		if (gencode) { | ||||||
| 			label datlab = data_label(); | 			label datlab = data_label(); | ||||||
|  | @ -106,7 +101,6 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 			C_loi(expr->ex_type->tp_size); | 			C_loi(expr->ex_type->tp_size); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 
 |  | ||||||
| 	case Oper:	/* compound expression	*/ | 	case Oper:	/* compound expression	*/ | ||||||
| 	{ | 	{ | ||||||
| 		register int oper = expr->OP_OPER; | 		register int oper = expr->OP_OPER; | ||||||
|  | @ -116,7 +110,6 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 
 | 
 | ||||||
| 		if (tp->tp_fund == ERRONEOUS)	/* stop immediately */ | 		if (tp->tp_fund == ERRONEOUS)	/* stop immediately */ | ||||||
| 			break; | 			break; | ||||||
| 
 |  | ||||||
| 		switch (oper)	{ | 		switch (oper)	{ | ||||||
| 		case '+': | 		case '+': | ||||||
| 			/*	We have the following possibilities :
 | 			/*	We have the following possibilities :
 | ||||||
|  | @ -366,8 +359,10 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 				store_block(tp->tp_size, tp->tp_align); | 				store_block(tp->tp_size, tp->tp_align); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				store_val(leftop->VL_IDF, leftop->ex_type, | 				store_val( | ||||||
| 					leftop->VL_VALUE); | 					&(leftop->ex_object.ex_value), | ||||||
|  | 					leftop->ex_type | ||||||
|  | 				); | ||||||
| 			break; | 			break; | ||||||
| 		case PLUSAB: | 		case PLUSAB: | ||||||
| 		case MINAB: | 		case MINAB: | ||||||
|  | @ -410,8 +405,10 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 				assop(tp, oper); | 				assop(tp, oper); | ||||||
| 				if (gencode) | 				if (gencode) | ||||||
| 					C_dup(roundup(tp->tp_size)); | 					C_dup(roundup(tp->tp_size)); | ||||||
| 				store_val(leftop->VL_IDF, leftop->ex_type, | 				store_val( | ||||||
| 					leftop->VL_VALUE); | 					&(leftop->ex_object.ex_value), | ||||||
|  | 					leftop->ex_type | ||||||
|  | 				); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case '(': | 		case '(': | ||||||
|  | @ -433,7 +430,9 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 				EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); | 				EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||||
| 				ParSize += ATW(expr->ex_type->tp_size); | 				ParSize += ATW(expr->ex_type->tp_size); | ||||||
| 			} | 			} | ||||||
| 			if (leftop->ex_class == Value && leftop->VL_IDF != 0) { | 			if (	leftop->ex_class == Value | ||||||
|  | 			&&	leftop->VL_CLASS == Name | ||||||
|  | 			) { | ||||||
| 				/* just an example:
 | 				/* just an example:
 | ||||||
| 					main() { (*((int (*)())0))(); } | 					main() { (*((int (*)())0))(); } | ||||||
| 				*/ | 				*/ | ||||||
|  | @ -466,11 +465,13 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 		} | 		} | ||||||
| 		case '.': | 		case '.': | ||||||
| 			EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL); | 			EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL); | ||||||
|  | 			ASSERT(is_cp_cst(rightop)); | ||||||
| 			if (gencode) | 			if (gencode) | ||||||
| 				C_adp(rightop->VL_VALUE); | 				C_adp(rightop->VL_VALUE); | ||||||
| 			break; | 			break; | ||||||
| 		case ARROW: | 		case ARROW: | ||||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||||
|  | 			ASSERT(is_cp_cst(rightop)); | ||||||
| 			if (gencode) | 			if (gencode) | ||||||
| 				C_adp(rightop->VL_VALUE); | 				C_adp(rightop->VL_VALUE); | ||||||
| 			break; | 			break; | ||||||
|  | @ -532,8 +533,10 @@ EVAL(expr, val, code, true_label, false_label) | ||||||
| 				free_tmp_var(old_offset); | 				free_tmp_var(old_offset); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				store_val(leftop->VL_IDF, leftop->ex_type, | 				store_val( | ||||||
| 					leftop->VL_VALUE); | 					&(leftop->ex_object.ex_value), | ||||||
|  | 					leftop->ex_type | ||||||
|  | 				); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		case '?':	/* must be followed by ':'	*/ | 		case '?':	/* must be followed by ':'	*/ | ||||||
|  | @ -841,62 +844,70 @@ free_tmp_var(oldoffset) | ||||||
| 	- into an automatic local variable | 	- into an automatic local variable | ||||||
| 	- into a local static variable | 	- into a local static variable | ||||||
| 	- absolute addressing | 	- absolute addressing | ||||||
| 	When the destination is described by an (lvalue) expression, the call |  | ||||||
| 	is "store_val(ex->VL_IDF, ex->ex_type, ex->VL_VALUE)" |  | ||||||
| */ | */ | ||||||
| store_val(id, tp, offs) | store_val(vl, tp) | ||||||
| 	register struct idf *id; | 	register struct value *vl; | ||||||
| 	struct type *tp; | 	struct type *tp; | ||||||
| 	arith offs; |  | ||||||
| { | { | ||||||
| 	arith size = tp->tp_size; | 	arith size = tp->tp_size; | ||||||
| 	int tpalign = tp->tp_align; | 	int tpalign = tp->tp_align; | ||||||
|  | 	int al_on_word; | ||||||
|  | 	register int inword; | ||||||
|  | 	register int indword; | ||||||
|  | 	arith val = vl->vl_value; | ||||||
| 
 | 
 | ||||||
| 	if (id)	{ | 	if (vl->vl_class == Const)	{	/* absolute addressing */ | ||||||
|  | 		load_cst(val, pointer_size); | ||||||
|  | 		store_block(size, tpalign); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	al_on_word = (tpalign % word_align == 0); | ||||||
|  | 	if (!(inword = (size == word_size && al_on_word))) | ||||||
|  | 		indword = (size == dword_size && al_on_word); | ||||||
|  | 
 | ||||||
|  | 	if (vl->vl_class == Name)	{ | ||||||
|  | 		register struct idf *id = vl->vl_data.vl_idf; | ||||||
| 		register struct def *df = id->id_def; | 		register struct def *df = id->id_def; | ||||||
| 		int al_on_word = (tpalign % word_align == 0); |  | ||||||
| 		register inword = (size == word_size && al_on_word); |  | ||||||
| 		register indword = (size == dword_size && al_on_word); |  | ||||||
| 
 | 
 | ||||||
| 		if (df->df_level == L_GLOBAL)	{ | 		if (df->df_level == L_GLOBAL)	{ | ||||||
| 			if (inword) | 			if (inword) | ||||||
| 				C_ste_dnam(id->id_text, offs); | 				C_ste_dnam(id->id_text, val); | ||||||
| 			else | 			else | ||||||
| 			if (indword) | 			if (indword) | ||||||
| 				C_sde_dnam(id->id_text, offs); | 				C_sde_dnam(id->id_text, val); | ||||||
| 			else { | 			else { | ||||||
| 				C_lae_dnam(id->id_text, offs); | 				C_lae_dnam(id->id_text, val); | ||||||
| 				store_block(size, tpalign); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		if (df->df_sc == STATIC)	{ |  | ||||||
| 			if (inword) |  | ||||||
| 				C_ste_dlb((label)df->df_address, offs); |  | ||||||
| 			else |  | ||||||
| 			if (indword) |  | ||||||
| 				C_sde_dlb((label)df->df_address, offs); |  | ||||||
| 			else { |  | ||||||
| 				C_lae_dlb((label)df->df_address, offs); |  | ||||||
| 				store_block(size, tpalign); | 				store_block(size, tpalign); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
|  | 			ASSERT(df->df_sc != STATIC); | ||||||
| 			if (inword) | 			if (inword) | ||||||
| 				C_stl(df->df_address + offs); | 				C_stl(df->df_address + val); | ||||||
| 			else | 			else | ||||||
| 			if (indword) | 			if (indword) | ||||||
| 				C_sdl(df->df_address + offs); | 				C_sdl(df->df_address + val); | ||||||
| 			else	{ | 			else	{ | ||||||
| 				C_lal(df->df_address + offs); | 				C_lal(df->df_address + val); | ||||||
| 				store_block(size, tpalign); | 				store_block(size, tpalign); | ||||||
| 				df->df_register = REG_NONE; | 				df->df_register = REG_NONE; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else	{	/* absolute addressing */ | 	else {	 | ||||||
| 		load_cst(offs, pointer_size); | 		label dlb = vl->vl_data.vl_lbl; | ||||||
| 		store_block(size, tpalign); | 
 | ||||||
|  | 		ASSERT(vl->vl_class == Label); | ||||||
|  | 		if (inword) | ||||||
|  | 			C_ste_dlb(dlb, val); | ||||||
|  | 		else | ||||||
|  | 		if (indword) | ||||||
|  | 			C_sde_dlb(dlb, val); | ||||||
|  | 		else { | ||||||
|  | 			C_lae_dlb(dlb, val); | ||||||
|  | 			store_block(size, tpalign); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -914,101 +925,96 @@ load_val(expr, val) | ||||||
| 	struct expr *expr;	/* expression containing the value	*/ | 	struct expr *expr;	/* expression containing the value	*/ | ||||||
| 	int val;		/* generate either LVAL or RVAL		*/ | 	int val;		/* generate either LVAL or RVAL		*/ | ||||||
| { | { | ||||||
| 	register struct idf *id; |  | ||||||
| 	register struct type *tp = expr->ex_type; | 	register struct type *tp = expr->ex_type; | ||||||
| 	register struct def *df; | 	register int rvalue = (val == RVAL && expr->ex_lvalue != 0); | ||||||
| 	register rvalue = (val == RVAL && expr->ex_lvalue != 0); |  | ||||||
| 	register arith exval = expr->VL_VALUE; |  | ||||||
| 	register arith size = tp->tp_size; | 	register arith size = tp->tp_size; | ||||||
| 	register tpalign = tp->tp_align; | 	register int tpalign = tp->tp_align; | ||||||
| 	register al_on_word = (tpalign % word_align == 0); | 	register int al_on_word; | ||||||
|  | 	register int inword, indword; | ||||||
|  | 	register arith val = expr->VL_VALUE; | ||||||
| 
 | 
 | ||||||
| 	if ((id = expr->VL_IDF) == 0)	{ | 	if (expr->VL_CLASS == Const)	{ | ||||||
| 		/* Note: enum constants are also dealt with here */ | 		if (rvalue)	{ /* absolute addressing */ | ||||||
| 		if (rvalue)	{ | 			load_cst(val, pointer_size); | ||||||
| 			/* absolute addressing
 |  | ||||||
| 			*/ |  | ||||||
| 			load_cst(exval, pointer_size); |  | ||||||
| 			load_block(size, tpalign); | 			load_block(size, tpalign); | ||||||
| 		} | 		} | ||||||
| 		else	/* integer, unsigned, long, enum etc	*/ | 		else	/* integer, unsigned, long, enum etc	*/ | ||||||
| 			load_cst(exval, size); | 			load_cst(val, size); | ||||||
|  | 		return; | ||||||
| 	} | 	} | ||||||
| 	else | 	if (rvalue) { | ||||||
| 	if ((df = id->id_def)->df_type->tp_fund == FUNCTION) | 		al_on_word = (tpalign % word_align == 0); | ||||||
| 		/*	the previous statement tried to catch a function
 | 		if (!(inword = (size == word_size && al_on_word))) | ||||||
| 			identifier, which may be cast to a pointer to a | 			indword = (size == dword_size && al_on_word); | ||||||
| 			function. | 	} | ||||||
| 			ASSERT(!(rvalue)); ??? | 	if (expr->VL_CLASS == Label) { | ||||||
| 		*/ |  | ||||||
| 		C_lpi(id->id_text); |  | ||||||
| 	else |  | ||||||
| 	if (df->df_level == L_GLOBAL)	{ |  | ||||||
| 		if (rvalue)	{ | 		if (rvalue)	{ | ||||||
| 			if (size == word_size && al_on_word) | 			if (inword) | ||||||
| 				C_loe_dnam(id->id_text, exval); | 				C_loe_dlb(expr->VL_LBL, val); | ||||||
| 			else | 			else | ||||||
| 			if (size == dword_size && al_on_word) | 			if (indword) | ||||||
| 				C_lde_dnam(id->id_text, exval); | 				C_lde_dlb(expr->VL_LBL, val); | ||||||
| 			else { | 			else { | ||||||
| 				C_lae_dnam(id->id_text, exval); | 				C_lae_dlb(expr->VL_LBL, val); | ||||||
| 				load_block(size, tpalign); | 				load_block(size, tpalign); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 		} | 		} | ||||||
| 		else	{ | 		else	{ | ||||||
| 			C_lae_dnam(id->id_text, (arith)0); | 			C_lae_dlb(expr->VL_LBL, (arith)0); | ||||||
| 			C_adp(exval); | 			C_adp(val); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | 	else { | ||||||
| 	if (df->df_sc == STATIC)	{ | 		register struct idf *id = expr->VL_IDF; | ||||||
| 		if (rvalue)	{ | 		register struct def *df; | ||||||
| 			if (size == word_size && al_on_word) |  | ||||||
| 				C_loe_dlb((label)df->df_address, exval); |  | ||||||
| 			else |  | ||||||
| 			if (size == dword_size && al_on_word) |  | ||||||
| 				C_lde_dlb((label)df->df_address, exval); |  | ||||||
| 			else	{ |  | ||||||
| 				C_lae_dlb((label)df->df_address, exval); |  | ||||||
| 				load_block(size, tpalign); |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
|  | 		ASSERT(expr->VL_CLASS == Name); | ||||||
|  | 		if ((df = id->id_def)->df_type->tp_fund == FUNCTION) | ||||||
|  | 			/*	the previous statement tried to catch a function
 | ||||||
|  | 				identifier, which may be cast to a pointer to a | ||||||
|  | 				function. | ||||||
|  | 				ASSERT(!(rvalue)); ??? | ||||||
|  | 			*/ | ||||||
|  | 			C_lpi(id->id_text); | ||||||
|  | 		else | ||||||
|  | 		if (df->df_level == L_GLOBAL)	{ | ||||||
|  | 			if (rvalue)	{ | ||||||
|  | 				if (inword) | ||||||
|  | 					C_loe_dnam(id->id_text, val); | ||||||
|  | 				else | ||||||
|  | 				if (indword) | ||||||
|  | 					C_lde_dnam(id->id_text, val); | ||||||
|  | 				else { | ||||||
|  | 					C_lae_dnam(id->id_text, val); | ||||||
|  | 					load_block(size, tpalign); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else	{ | ||||||
|  | 				C_lae_dnam(id->id_text, (arith)0); | ||||||
|  | 				C_adp(val); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		else	{ | 		else	{ | ||||||
| 			C_lae_dlb((label)df->df_address, (arith)0); | 			ASSERT(df->df_sc != STATIC); | ||||||
| 			C_adp(exval); | 			if (rvalue)	{ | ||||||
| 		} | 				if (inword) | ||||||
| 	} | 					C_lol(df->df_address + val); | ||||||
| 	else	{ | 				else | ||||||
| 		if (rvalue)	{ | 				if (indword) | ||||||
| 			if (size == word_size && al_on_word) | 					C_ldl(df->df_address + val); | ||||||
| 				C_lol(df->df_address + exval); | 				else { | ||||||
| 			else | 					C_lal(df->df_address + val); | ||||||
| 			if (size == dword_size && al_on_word) | 					load_block(size, tpalign); | ||||||
| 				C_ldl(df->df_address + exval); | 					df->df_register = REG_NONE; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 			else	{ | 			else	{ | ||||||
| 				C_lal(df->df_address + exval); | 				C_lal(df->df_address); | ||||||
| 				load_block(size, tpalign); | 				C_adp(val); | ||||||
| 				df->df_register = REG_NONE; | 				df->df_register = REG_NONE; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else	{ |  | ||||||
| 			/*	following code may be used when
 |  | ||||||
| 				comparing addresses as in the following |  | ||||||
| 				example: |  | ||||||
| 				f() { |  | ||||||
| 					int a[10], *i; |  | ||||||
| 					for (i = &a[0]; i < &a[10]; i++) ...; |  | ||||||
| 				} |  | ||||||
| 				We don't accept the contents of a[10] to |  | ||||||
| 				be legitimate, so the RVAL of it may |  | ||||||
| 				contain a big mess. |  | ||||||
| 			*/ |  | ||||||
| 			C_lal(df->df_address); |  | ||||||
| 			C_adp(exval); |  | ||||||
| 			df->df_register = REG_NONE; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ | ||||||
| #include	"declar.h" | #include	"declar.h" | ||||||
| #include	"storage.h" | #include	"storage.h" | ||||||
| #include	"sizes.h" | #include	"sizes.h" | ||||||
|  | #include	"level.h" | ||||||
| 
 | 
 | ||||||
| extern char *symbol2str(); | extern char *symbol2str(); | ||||||
| extern char options[]; | extern char options[]; | ||||||
|  | @ -184,10 +185,17 @@ idf2expr(expr) | ||||||
| 		) ? 0 : 1; | 		) ? 0 : 1; | ||||||
| 	expr->ex_class = Value; | 	expr->ex_class = Value; | ||||||
| 	if (def->df_sc == ENUM)	{ | 	if (def->df_sc == ENUM)	{ | ||||||
| 		expr->VL_IDF = 0; | 		expr->VL_CLASS = Const; | ||||||
| 		expr->VL_VALUE = def->df_address; | 		expr->VL_VALUE = def->df_address; | ||||||
| 	} | 	} | ||||||
| 	else	{ | 	else | ||||||
|  | 	if (def->df_sc == STATIC && def->df_level >= L_LOCAL) { | ||||||
|  | 		expr->VL_CLASS = Label; | ||||||
|  | 		expr->VL_LBL = def->df_address; | ||||||
|  | 		expr->VL_VALUE = (arith)0; | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		expr->VL_CLASS = Name; | ||||||
| 		expr->VL_IDF = idf; | 		expr->VL_IDF = idf; | ||||||
| 		expr->VL_VALUE = (arith)0; | 		expr->VL_VALUE = (arith)0; | ||||||
| 	} | 	} | ||||||
|  | @ -246,6 +254,7 @@ intexpr(ivalue, fund) | ||||||
| 		crash("(intexpr) bad fund %s\n", symbol2str(fund)); | 		crash("(intexpr) bad fund %s\n", symbol2str(fund)); | ||||||
| 	} | 	} | ||||||
| 	expr->ex_class = Value; | 	expr->ex_class = Value; | ||||||
|  | 	expr->VL_CLASS = Const; | ||||||
| 	expr->VL_VALUE = ivalue; | 	expr->VL_VALUE = ivalue; | ||||||
| 	 | 	 | ||||||
| 	cut_size(expr); | 	cut_size(expr); | ||||||
|  | @ -421,7 +430,7 @@ is_cp_cst(expr) | ||||||
| 	/*	An expression is a `compile-time constant' if it is a
 | 	/*	An expression is a `compile-time constant' if it is a
 | ||||||
| 		load-time constant, and the idf is not there. | 		load-time constant, and the idf is not there. | ||||||
| 	*/ | 	*/ | ||||||
| 	return is_ld_cst(expr) && expr->VL_IDF == 0; | 	return is_ld_cst(expr) && expr->VL_CLASS == Const; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
|  |  | ||||||
|  | @ -5,9 +5,18 @@ | ||||||
| 	a union of various goodies, we define them first; so be patient. | 	a union of various goodies, we define them first; so be patient. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
|  | /* classes of value */ | ||||||
|  | #define Const	1 | ||||||
|  | #define Name	2 | ||||||
|  | #define Label	3 | ||||||
|  | 
 | ||||||
| struct value	{ | struct value	{ | ||||||
| 	struct idf *vl_idf;		/* idf of an external name or 0 */ | 	int vl_class;		/* Const, Name or Label	*/ | ||||||
| 	arith vl_value;			/* constant, or offset if idf != 0 */ | 	arith vl_value;		/* constant value or offset */ | ||||||
|  | 	union { | ||||||
|  | 		struct idf *vl_idf;	/* external name */ | ||||||
|  | 		label vl_lbl;		/* compiler-generated label */ | ||||||
|  | 	} vl_data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct string	{ | struct string	{ | ||||||
|  | @ -53,8 +62,10 @@ struct expr	{ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* some abbreviated selections	*/ | /* some abbreviated selections	*/ | ||||||
|  | #define VL_CLASS	ex_object.ex_value.vl_class | ||||||
| #define	VL_VALUE	ex_object.ex_value.vl_value | #define	VL_VALUE	ex_object.ex_value.vl_value | ||||||
| #define	VL_IDF		ex_object.ex_value.vl_idf | #define	VL_IDF		ex_object.ex_value.vl_data.vl_idf | ||||||
|  | #define	VL_LBL		ex_object.ex_value.vl_data.vl_lbl | ||||||
| #define	SG_VALUE	ex_object.ex_string.sg_value | #define	SG_VALUE	ex_object.ex_string.sg_value | ||||||
| #define SG_LEN		ex_object.ex_string.sg_len | #define SG_LEN		ex_object.ex_string.sg_len | ||||||
| #define	SG_DATLAB	ex_object.ex_string.sg_datlab | #define	SG_DATLAB	ex_object.ex_string.sg_datlab | ||||||
|  |  | ||||||
|  | @ -47,7 +47,6 @@ eval_field(expr, code) | ||||||
| 
 | 
 | ||||||
| 	ASSERT(leftop->ex_type->tp_fund == FIELD); | 	ASSERT(leftop->ex_type->tp_fund == FIELD); | ||||||
| 	ASSERT(asize == word_size);	/* make sure that C_loc() is legal */ | 	ASSERT(asize == word_size);	/* make sure that C_loc() is legal */ | ||||||
| 
 |  | ||||||
| 	leftop->ex_type = atype;	/* this is cheating but it works... */ | 	leftop->ex_type = atype;	/* this is cheating but it works... */ | ||||||
| 
 | 
 | ||||||
| 	/*	Note that op is either an assignment operator or an increment/
 | 	/*	Note that op is either an assignment operator or an increment/
 | ||||||
|  | @ -60,26 +59,21 @@ eval_field(expr, code) | ||||||
| 		conversion(tp, atype); | 		conversion(tp, atype); | ||||||
| 		C_loc(fd->fd_mask); | 		C_loc(fd->fd_mask); | ||||||
| 		C_and(asize); | 		C_and(asize); | ||||||
| 		if (code == TRUE)	{ | 		if (code == TRUE) | ||||||
| 			C_dup(asize); | 			C_dup(asize); | ||||||
| 		} |  | ||||||
| 		C_loc((arith)fd->fd_shift); | 		C_loc((arith)fd->fd_shift); | ||||||
| 
 |  | ||||||
| 		if (atype->tp_unsigned) | 		if (atype->tp_unsigned) | ||||||
| 			C_slu(asize); | 			C_slu(asize); | ||||||
| 		else | 		else | ||||||
| 			C_sli(asize); | 			C_sli(asize); | ||||||
| 
 |  | ||||||
| 		C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize)))); | 		C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize)))); | ||||||
| 
 |  | ||||||
| 		if (leftop->ex_depth == 0)	{	/* simple case	*/ | 		if (leftop->ex_depth == 0)	{	/* simple case	*/ | ||||||
| 			load_val(leftop, RVAL); | 			load_val(leftop, RVAL); | ||||||
| 			C_and(asize); | 			C_and(asize); | ||||||
| 			C_ior(asize); | 			C_ior(asize); | ||||||
| 			store_val( | 			store_val( | ||||||
| 				leftop->VL_IDF, | 				&(leftop->ex_object.ex_value), | ||||||
| 				leftop->ex_type, | 				leftop->ex_type | ||||||
| 				leftop->VL_VALUE |  | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 		else	{			/* complex case	*/ | 		else	{			/* complex case	*/ | ||||||
|  | @ -98,13 +92,11 @@ eval_field(expr, code) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else {		/* treat ++F as F += 1 and --F as F -= 1	*/ | 	else {		/* treat ++F as F += 1 and --F as F -= 1	*/ | ||||||
| 
 |  | ||||||
| 		/*	F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
 | 		/*	F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
 | ||||||
| 					(f&~(mask<<shift)) | 					(f&~(mask<<shift)) | ||||||
| 		*/ | 		*/ | ||||||
| 		if (leftop->ex_depth == 0)	{	/* simple case	*/ | 		if (leftop->ex_depth == 0)	/* simple case	*/ | ||||||
| 			load_val(leftop, RVAL); | 			load_val(leftop, RVAL); | ||||||
| 		} |  | ||||||
| 		else	{			/* complex case	*/ | 		else	{			/* complex case	*/ | ||||||
| 			tmpvar = tmp_pointer_var(&old_offset); | 			tmpvar = tmp_pointer_var(&old_offset); | ||||||
| 			EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | 			EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||||
|  | @ -113,26 +105,18 @@ eval_field(expr, code) | ||||||
| 			C_sti(pointer_size); | 			C_sti(pointer_size); | ||||||
| 			C_loi(asize); | 			C_loi(asize); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		C_loc((arith)fd->fd_shift); | 		C_loc((arith)fd->fd_shift); | ||||||
| 
 |  | ||||||
| 		if (atype->tp_unsigned) | 		if (atype->tp_unsigned) | ||||||
| 			C_sru(asize); | 			C_sru(asize); | ||||||
| 		else | 		else | ||||||
| 			C_sri(asize); | 			C_sri(asize); | ||||||
| 
 |  | ||||||
| 		C_loc(fd->fd_mask); | 		C_loc(fd->fd_mask); | ||||||
| 		C_and(asize); | 		C_and(asize); | ||||||
| 
 | 		if (code == TRUE && (op == POSTINCR || op == POSTDECR)) | ||||||
| 		if (code == TRUE && (op == POSTINCR || op == POSTDECR))	{ |  | ||||||
| 			C_dup(asize); | 			C_dup(asize); | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | 		EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||||
| 		conversion(tp, atype); | 		conversion(tp, atype); | ||||||
| 
 | 		/* generate code for the operator */ | ||||||
| 		/* generate the code for the operator
 |  | ||||||
| 		*/ |  | ||||||
| 		if (op == PLUSPLUS || op == POSTINCR) | 		if (op == PLUSPLUS || op == POSTINCR) | ||||||
| 			assop(atype, PLUSAB); | 			assop(atype, PLUSAB); | ||||||
| 		else | 		else | ||||||
|  | @ -140,31 +124,23 @@ eval_field(expr, code) | ||||||
| 			assop(atype, MINAB); | 			assop(atype, MINAB); | ||||||
| 		else | 		else | ||||||
| 			assop(atype, op); | 			assop(atype, op); | ||||||
| 
 |  | ||||||
| 		C_loc(fd->fd_mask); | 		C_loc(fd->fd_mask); | ||||||
| 		C_and(asize); | 		C_and(asize); | ||||||
| 
 | 		if (code == TRUE && op != POSTINCR && op != POSTDECR) | ||||||
| 		if (code == TRUE && op != POSTINCR && op != POSTDECR)	{ |  | ||||||
| 			C_dup(asize); | 			C_dup(asize); | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		C_loc((arith)fd->fd_shift); | 		C_loc((arith)fd->fd_shift); | ||||||
| 
 |  | ||||||
| 		if (atype->tp_unsigned) | 		if (atype->tp_unsigned) | ||||||
| 			C_slu(asize); | 			C_slu(asize); | ||||||
| 		else | 		else | ||||||
| 			C_sli(asize); | 			C_sli(asize); | ||||||
| 
 |  | ||||||
| 		C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize)))); | 		C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize)))); | ||||||
| 
 |  | ||||||
| 		if (leftop->ex_depth == 0)	{ | 		if (leftop->ex_depth == 0)	{ | ||||||
| 			load_val(leftop, RVAL); | 			load_val(leftop, RVAL); | ||||||
| 			C_and(asize); | 			C_and(asize); | ||||||
| 			C_ior(asize); | 			C_ior(asize); | ||||||
| 			store_val( | 			store_val( | ||||||
| 				leftop->VL_IDF, | 				&(leftop->ex_object.ex_value), | ||||||
| 				leftop->ex_type, | 				leftop->ex_type | ||||||
| 				leftop->VL_VALUE |  | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 		else	{ | 		else	{ | ||||||
|  | @ -179,7 +155,6 @@ eval_field(expr, code) | ||||||
| 			free_tmp_var(old_offset); | 			free_tmp_var(old_offset); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	if (code == TRUE) { | 	if (code == TRUE) { | ||||||
| 		/*	Take care that the effective value stored in
 | 		/*	Take care that the effective value stored in
 | ||||||
| 			the bit field (i.e. the value that is got on | 			the bit field (i.e. the value that is got on | ||||||
|  | @ -193,7 +168,6 @@ eval_field(expr, code) | ||||||
| 			C_loc(shift); | 			C_loc(shift); | ||||||
| 			C_sri(asize); | 			C_sri(asize); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		conversion(atype, tp); | 		conversion(atype, tp); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,7 +27,6 @@ char *symbol2str(); | ||||||
| char *long2str(); | char *long2str(); | ||||||
| 
 | 
 | ||||||
| struct expr *do_array(), *do_struct(), *IVAL(); | struct expr *do_array(), *do_struct(), *IVAL(); | ||||||
| struct expr *strings = 0; /* list of string constants within initialiser */ |  | ||||||
| 
 | 
 | ||||||
| /*	do_ival() performs the initialisation of a global variable
 | /*	do_ival() performs the initialisation of a global variable
 | ||||||
| 	of type tp with the initialisation expression expr by calling IVAL(). | 	of type tp with the initialisation expression expr by calling IVAL(). | ||||||
|  | @ -39,33 +38,8 @@ do_ival(tpp, expr) | ||||||
| { | { | ||||||
| 	if (IVAL(tpp, expr) != 0) | 	if (IVAL(tpp, expr) != 0) | ||||||
| 		too_many_initialisers(expr); | 		too_many_initialisers(expr); | ||||||
| 
 |  | ||||||
| 	/*	The following loop declares the string constants
 |  | ||||||
| 		used in the initialisation. |  | ||||||
| 		The code for these string constants may not appear in |  | ||||||
| 		the code of the initialisation because a data label |  | ||||||
| 		in EM causes the current initialisation to be completed. |  | ||||||
| 		E.g. char *s[] = {"hello", "world"}; |  | ||||||
| 	*/ |  | ||||||
| 	while (strings != 0) { |  | ||||||
| 		C_df_dlb(strings->SG_DATLAB); |  | ||||||
| 		C_con_scon(strings->SG_VALUE, (arith)strings->SG_LEN); |  | ||||||
| 		strings = strings->next; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| /*	store_string() collects the string constants appearing in an
 |  | ||||||
| 	initialisation. |  | ||||||
| */ |  | ||||||
| store_string(expr) |  | ||||||
| 	struct expr *expr; |  | ||||||
| { |  | ||||||
| 	expr->next = strings; |  | ||||||
| 	strings = expr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /*	IVAL() recursively guides the initialisation expression through the
 | /*	IVAL() recursively guides the initialisation expression through the
 | ||||||
| 	different routines for the different types of initialisation: | 	different routines for the different types of initialisation: | ||||||
| 	-	array initialisation | 	-	array initialisation | ||||||
|  | @ -89,18 +63,14 @@ IVAL(tpp, expr) | ||||||
| 		/* array initialisation	*/ | 		/* array initialisation	*/ | ||||||
| 		if (valid_type(tp->tp_up, "array element") == 0) | 		if (valid_type(tp->tp_up, "array element") == 0) | ||||||
| 			return 0; | 			return 0; | ||||||
| 		if (ISCOMMA(expr))	{ | 		if (ISCOMMA(expr)) /* list of initialisation expressions */ | ||||||
| 			/* list of initialisation expressions */ |  | ||||||
| 			return do_array(expr, tpp); | 			return do_array(expr, tpp); | ||||||
| 		} | 		/* catch initialisations like char s[] = "I am a string" */ | ||||||
| 		/*	There might be an initialisation of a string
 |  | ||||||
| 			like char s[] = "I am a string" |  | ||||||
| 		*/ |  | ||||||
| 		if (tp->tp_up->tp_fund == CHAR && expr->ex_class == String) | 		if (tp->tp_up->tp_fund == CHAR && expr->ex_class == String) | ||||||
| 			init_string(tpp, expr); | 			init_string(tpp, expr); | ||||||
| 		else /* " int i[24] = 12;"	*/ | 		else /* " int i[24] = 12;"	*/ | ||||||
| 			check_and_pad(expr, tpp); | 			check_and_pad(expr, tpp); | ||||||
| 		return 0;	/* nothing left	*/ | 		break; | ||||||
| 	case STRUCT: | 	case STRUCT: | ||||||
| 		/* struct initialisation */ | 		/* struct initialisation */ | ||||||
| 		if (valid_type(tp, "struct") == 0) | 		if (valid_type(tp, "struct") == 0) | ||||||
|  | @ -109,12 +79,12 @@ IVAL(tpp, expr) | ||||||
| 			return do_struct(expr, tp); | 			return do_struct(expr, tp); | ||||||
| 		/* "struct foo f = 12;"	*/ | 		/* "struct foo f = 12;"	*/ | ||||||
| 		check_and_pad(expr, tpp); | 		check_and_pad(expr, tpp); | ||||||
| 		return 0; | 		break; | ||||||
| 	case UNION: | 	case UNION: | ||||||
| 		error("union initialisation not allowed"); | 		error("union initialisation not allowed"); | ||||||
| 		return 0; | 		break; | ||||||
| 	case ERRONEOUS: | 	case ERRONEOUS: | ||||||
| 		return 0; | 		break; | ||||||
| 	default: /* fundamental type	*/ | 	default: /* fundamental type	*/ | ||||||
| 		if (ISCOMMA(expr))	{ /* " int i = {12};"	*/ | 		if (ISCOMMA(expr))	{ /* " int i = {12};"	*/ | ||||||
| 			if (IVAL(tpp, expr->OP_LEFT) != 0) | 			if (IVAL(tpp, expr->OP_LEFT) != 0) | ||||||
|  | @ -127,9 +97,9 @@ IVAL(tpp, expr) | ||||||
| 		} | 		} | ||||||
| 		/* "int i = 12;"	*/ | 		/* "int i = 12;"	*/ | ||||||
| 		check_ival(expr, tp); | 		check_ival(expr, tp); | ||||||
| 		return 0; | 		break; | ||||||
| 	} | 	} | ||||||
| 	/* NOTREACHED */ | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*	do_array() initialises the members of an array described
 | /*	do_array() initialises the members of an array described
 | ||||||
|  | @ -451,20 +421,18 @@ check_ival(expr, type) | ||||||
| 	case LONG: | 	case LONG: | ||||||
| 	case ENUM: | 	case ENUM: | ||||||
| 		ch7cast(&expr, '=', type); | 		ch7cast(&expr, '=', type); | ||||||
| 		if (!is_cp_cst(expr))	{ | 		if (is_cp_cst(expr)) | ||||||
|  | 			con_int(expr); | ||||||
|  | 		else | ||||||
| 			illegal_init_cst(expr); | 			illegal_init_cst(expr); | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		con_int(expr); |  | ||||||
| 		break; | 		break; | ||||||
| #ifndef NOBITFIELD | #ifndef NOBITFIELD | ||||||
| 	case FIELD: | 	case FIELD: | ||||||
| 		ch7cast(&expr, '=', type->tp_up); | 		ch7cast(&expr, '=', type->tp_up); | ||||||
| 		if (!is_cp_cst(expr))	{ | 		if (is_cp_cst(expr)) | ||||||
|  | 			put_bf(type, expr->VL_VALUE); | ||||||
|  | 		else | ||||||
| 			illegal_init_cst(expr); | 			illegal_init_cst(expr); | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		put_bf(type, expr->VL_VALUE); |  | ||||||
| 		break; | 		break; | ||||||
| #endif NOBITFIELD | #endif NOBITFIELD | ||||||
| 	case FLOAT: | 	case FLOAT: | ||||||
|  | @ -475,14 +443,13 @@ check_ival(expr, type) | ||||||
| 		else | 		else | ||||||
| 		if (expr->ex_class == Oper && expr->OP_OPER == INT2FLOAT) { | 		if (expr->ex_class == Oper && expr->OP_OPER == INT2FLOAT) { | ||||||
| 			expr = expr->OP_RIGHT; | 			expr = expr->OP_RIGHT; | ||||||
| 			if (!is_cp_cst(expr))	{ | 			if (is_cp_cst(expr)) | ||||||
|  | 				C_con_fcon( | ||||||
|  | 					long2str((long)expr->VL_VALUE, 10), | ||||||
|  | 					type->tp_size | ||||||
|  | 				); | ||||||
|  | 			else  | ||||||
| 				illegal_init_cst(expr); | 				illegal_init_cst(expr); | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 			C_con_fcon( |  | ||||||
| 				long2str((long)expr->VL_VALUE, 10), |  | ||||||
| 				type->tp_size |  | ||||||
| 			); |  | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 			illegal_init_cst(expr); | 			illegal_init_cst(expr); | ||||||
|  | @ -493,55 +460,35 @@ check_ival(expr, type) | ||||||
| 		case Oper: | 		case Oper: | ||||||
| 			illegal_init_cst(expr); | 			illegal_init_cst(expr); | ||||||
| 			break; | 			break; | ||||||
| 		case String:	/* char *s = "...." */ |  | ||||||
| 		{ |  | ||||||
| 			label datlab = data_label(); |  | ||||||
| 			 |  | ||||||
| 			C_ina_dlb(datlab); |  | ||||||
| 			C_con_dlb(datlab, (arith)0); |  | ||||||
| 			expr->SG_DATLAB = datlab; |  | ||||||
| 			store_string(expr); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		case Value: | 		case Value: | ||||||
| 		{ | 		{ | ||||||
| 			struct value *vl = &(expr->ex_object.ex_value); |  | ||||||
| 			struct idf *idf = vl->vl_idf; |  | ||||||
| 
 |  | ||||||
| 			ASSERT(expr->ex_type->tp_fund == POINTER); | 			ASSERT(expr->ex_type->tp_fund == POINTER); | ||||||
| 			if (expr->ex_type->tp_up->tp_fund == FUNCTION) { | 			if (expr->ex_type->tp_up->tp_fund == FUNCTION) { | ||||||
| 				if (idf) | 				if (expr->VL_CLASS == Name) | ||||||
| 					C_con_pnam(idf->id_text); | 					C_con_pnam(expr->VL_IDF->id_text); | ||||||
| 				else	/* int (*func)() = 0	*/ | 				else	/* int (*func)() = 0	*/ | ||||||
| 					con_int(expr); | 					con_int(expr); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			if (idf) { | 			if (expr->VL_CLASS == Name) { | ||||||
| 				register struct def *def = idf->id_def; | 				register struct idf *id = expr->VL_IDF; | ||||||
| 
 | 
 | ||||||
| 				if (def->df_level >= L_LOCAL) { | 				if (id ->id_def->df_level >= L_LOCAL) | ||||||
| 					if (def->df_sc != STATIC) | 					expr_error(expr, | ||||||
| 						/*	Eg.  int a;
 | 						"illegal initialisation"); | ||||||
| 							static int *p = &a; |  | ||||||
| 						*/ |  | ||||||
| 						expr_error(expr, |  | ||||||
| 							"illegal initialisation" |  | ||||||
| 						); |  | ||||||
| 					else |  | ||||||
| 						C_con_dlb( |  | ||||||
| 							(label)def->df_address, |  | ||||||
| 							vl->vl_value |  | ||||||
| 						); |  | ||||||
| 				} |  | ||||||
| 				else | 				else | ||||||
| 					C_con_dnam(idf->id_text, vl->vl_value); | 					C_con_dnam(id->id_text, expr->VL_VALUE); | ||||||
| 			} | 			} | ||||||
|  | 			else | ||||||
|  | 			if (expr->VL_CLASS == Label) | ||||||
|  | 				C_con_dlb(expr->VL_LBL, expr->VL_VALUE); | ||||||
| 			else | 			else | ||||||
| 				con_int(expr); | 				con_int(expr); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | 		case String: | ||||||
| 		default: | 		default: | ||||||
| 			crash("(check_ival) illegal initialisation expression"); | 			crash("(check_ival) illegal value class"); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case ERRONEOUS: | 	case ERRONEOUS: | ||||||
|  | @ -565,6 +512,7 @@ init_string(tpp, expr) | ||||||
| 	char *s = expr->SG_VALUE; | 	char *s = expr->SG_VALUE; | ||||||
| 	arith ntopad; | 	arith ntopad; | ||||||
| 
 | 
 | ||||||
|  | 	ASSERT(expr->ex_class == String); | ||||||
| 	length = expr->SG_LEN; | 	length = expr->SG_LEN; | ||||||
| 	if (tp->tp_size == (arith)-1)	{ | 	if (tp->tp_size == (arith)-1)	{ | ||||||
| 		/* set the dimension	*/ | 		/* set the dimension	*/ | ||||||
|  | @ -604,21 +552,22 @@ put_bf(tp, val) | ||||||
| 	static arith offset = (arith)-1; | 	static arith offset = (arith)-1; | ||||||
| 	register struct field *fd = tp->tp_field; | 	register struct field *fd = tp->tp_field; | ||||||
| 	register struct sdef *sd =  fd->fd_sdef; | 	register struct sdef *sd =  fd->fd_sdef; | ||||||
| 	static struct expr expr; | 	static struct expr exp; | ||||||
| 
 | 
 | ||||||
| 	ASSERT(sd); | 	ASSERT(sd); | ||||||
| 	if (offset == (arith)-1) { | 	if (offset == (arith)-1) { | ||||||
| 		/* first bitfield in this field	*/ | 		/* first bitfield in this field	*/ | ||||||
| 		offset = sd->sd_offset; | 		offset = sd->sd_offset; | ||||||
| 		expr.ex_type = tp->tp_up; | 		exp.ex_type = tp->tp_up; | ||||||
| 		expr.ex_class = Value; | 		exp.ex_class = Value; | ||||||
|  | 		exp.VL_CLASS = Const; | ||||||
| 	} | 	} | ||||||
| 	if (val != 0)	/* insert the value into "field"	*/ | 	if (val != 0)	/* insert the value into "field"	*/ | ||||||
| 		field |= (val & fd->fd_mask) << fd->fd_shift; | 		field |= (val & fd->fd_mask) << fd->fd_shift; | ||||||
| 	if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) { | 	if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) { | ||||||
| 		/* the selector was the last stored at this address	*/ | 		/* the selector was the last stored at this address	*/ | ||||||
| 		expr.VL_VALUE = field; | 		exp.VL_VALUE = field; | ||||||
| 		con_int(&expr); | 		con_int(&exp); | ||||||
| 		field = (arith)0; | 		field = (arith)0; | ||||||
| 		offset = (arith)-1; | 		offset = (arith)-1; | ||||||
| 	} | 	} | ||||||
|  | @ -654,27 +603,28 @@ valid_type(tp, str) | ||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| con_int(expr) | con_int(ex) | ||||||
| 	register struct expr *expr; | 	register struct expr *ex; | ||||||
| { | { | ||||||
| 	register struct type *tp = expr->ex_type; | 	register struct type *tp = ex->ex_type; | ||||||
| 
 | 
 | ||||||
|  | 	ASSERT(is_cp_cst(ex)); | ||||||
| 	if (tp->tp_unsigned) | 	if (tp->tp_unsigned) | ||||||
| 		C_con_ucon(long2str((long)expr->VL_VALUE, -10), tp->tp_size); | 		C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size); | ||||||
| 	else | 	else | ||||||
| 		C_con_icon(long2str((long)expr->VL_VALUE, 10), tp->tp_size); | 		C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| illegal_init_cst(expr) | illegal_init_cst(ex) | ||||||
| 	struct expr *expr; | 	struct expr *ex; | ||||||
| { | { | ||||||
| 	expr_error(expr, "illegal initialisation constant"); | 	expr_error(ex, "illegal initialisation constant"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| too_many_initialisers(expr) | too_many_initialisers(ex) | ||||||
| 	struct expr *expr; | 	struct expr *ex; | ||||||
| { | { | ||||||
| 	expr_error(expr, "too many initialisers"); | 	expr_error(ex, "too many initialisers"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| aggregate_type(tp) | aggregate_type(tp) | ||||||
|  |  | ||||||
|  | @ -124,6 +124,7 @@ code_case(expr) | ||||||
| 	register struct case_entry *ce; | 	register struct case_entry *ce; | ||||||
| 	register struct switch_hdr *sh = switch_stack; | 	register struct switch_hdr *sh = switch_stack; | ||||||
| 	 | 	 | ||||||
|  | 	ASSERT(is_cp_cst(expr)); | ||||||
| 	if (sh == 0)	{ | 	if (sh == 0)	{ | ||||||
| 		error("case statement not in switch"); | 		error("case statement not in switch"); | ||||||
| 		return; | 		return; | ||||||
|  | @ -133,14 +134,11 @@ code_case(expr) | ||||||
| 		/* is probably 0 anyway */ | 		/* is probably 0 anyway */ | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	 |  | ||||||
| 	expr->ex_type = sh->sh_type; | 	expr->ex_type = sh->sh_type; | ||||||
| 	cut_size(expr); | 	cut_size(expr); | ||||||
| 	 |  | ||||||
| 	ce = new_case_entry(); | 	ce = new_case_entry(); | ||||||
| 	C_df_ilb(ce->ce_label = text_label()); | 	C_df_ilb(ce->ce_label = text_label()); | ||||||
| 	ce->ce_value = val = expr->VL_VALUE; | 	ce->ce_value = val = expr->VL_VALUE; | ||||||
| 	 |  | ||||||
| 	if (sh->sh_entries == 0)	{ | 	if (sh->sh_entries == 0)	{ | ||||||
| 		/* first case entry	*/ | 		/* first case entry	*/ | ||||||
| 		ce->next = (struct case_entry *) 0; | 		ce->next = (struct case_entry *) 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue