modified the treatment of op=, ++ and -- operators
This commit is contained in:
		
							parent
							
								
									42112db262
								
							
						
					
					
						commit
						5af21dfc79
					
				
					 15 changed files with 421 additions and 601 deletions
				
			
		|  | @ -17,7 +17,8 @@ EMELIB = $(EM)/modules/lib/libeme.a | |||
| STRLIB = $(EM)/modules/lib/libstr.a | ||||
| PRTLIB = $(EM)/modules/lib/libprint.a | ||||
| EMMESLIB = $(EM)/modules/lib/libem_mes.a | ||||
| CH3LIB = $(EM)/modules/lib/libch3.a | ||||
| #CH3LIB = $(EM)/modules/lib/libch3.a | ||||
| CH3LIB = | ||||
| LIBS = $(CH3LIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) $(SYSLIB) | ||||
| ELIBS = $(CH3LIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) $(SYSLIB) | ||||
| LIB_INCLUDES = $(EM)/modules/h | ||||
|  |  | |||
|  | @ -423,6 +423,10 @@ is_asgn_op(oper) | |||
| 	case ANDAB: | ||||
| 	case ORAB: | ||||
| 	case XORAB: | ||||
| 	case PLUSPLUS: | ||||
| 	case POSTINCR: | ||||
| 	case MINMIN: | ||||
| 	case POSTDECR: | ||||
| 		return 1; | ||||
| 	default: | ||||
| 		return 0; | ||||
|  |  | |||
|  | @ -1,10 +1,14 @@ | |||
| /* $Header$ */ | ||||
| /*	B L O C K   S T O R I N G   A N D   L O A D I N G	*/ | ||||
| 
 | ||||
| #include	<em.h> | ||||
| #include	"arith.h" | ||||
| #include	"sizes.h" | ||||
| #include	"atw.h" | ||||
| #include <em.h> | ||||
| #include "arith.h" | ||||
| #include "sizes.h" | ||||
| #include "atw.h" | ||||
| #ifndef STB | ||||
| #include "label.h" | ||||
| #include "stack.h" | ||||
| #endif STB | ||||
| 
 | ||||
| /*	Because EM does not support the loading and storing of
 | ||||
| 	objects having other sizes than word fragment and multiple, | ||||
|  | @ -38,17 +42,33 @@ store_block(sz, al) | |||
| 	arith sz; | ||||
| 	int al; | ||||
| { | ||||
| 	/* Next condition contains Lots of Irritating Stupid Parentheses
 | ||||
| 	*/ | ||||
| 	if ( | ||||
| 		((sz == al) && (word_align % al == 0)) || | ||||
| 		( | ||||
| 			(sz % word_size == 0 || word_size % sz == 0) && | ||||
| 			(al % word_align == 0) | ||||
| 		) | ||||
| 	) | ||||
| 	)	/* Lots of Irritating Stupid Parentheses */ | ||||
| 		C_sti(sz); | ||||
| 	else	{ | ||||
| 	else { | ||||
| #ifndef STB | ||||
| 		arith src, dst, src_offs, dst_offs; | ||||
| 
 | ||||
| 		/* allocate two pointer temporaries */ | ||||
| 		src = tmp_pointer_var(&src_offs); | ||||
| 		dst = tmp_pointer_var(&dst_offs); | ||||
| 
 | ||||
| 		/* load the addresses */ | ||||
| 		C_lal(dst); | ||||
| 		C_sti(pointer_size); | ||||
| 		C_lor((arith)1);	/* push current sp */ | ||||
| 		C_lal(src); | ||||
| 		C_sti(pointer_size); | ||||
| 		copy_loop(sz, src, dst); | ||||
| 		C_asp(ATW(sz)); | ||||
| 		free_tmp_var(dst_offs); | ||||
| 		free_tmp_var(src_offs); | ||||
| #else STB | ||||
| 		/*	address of destination lies on the stack	*/ | ||||
| 
 | ||||
| 		/*	push address of first byte of block on stack onto
 | ||||
|  | @ -60,6 +80,7 @@ store_block(sz, al) | |||
| 		C_loc(sz);		/* number of bytes to transfer	*/ | ||||
| 		C_cal("__stb");		/* call transfer routine	*/ | ||||
| 		C_asp(pointer_size + pointer_size + int_size + ATW(sz)); | ||||
| #endif STB | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -75,7 +96,23 @@ load_block(sz, al) | |||
| 	if (al % word_align == 0) | ||||
| 		C_loi(esz); | ||||
| 	else { | ||||
| 		/* do not try to understand this...	*/ | ||||
| #ifndef STB | ||||
| 		arith src, dst, src_offs, dst_offs; | ||||
| 
 | ||||
| 		/* allocate two pointer temporaries */ | ||||
| 		src = tmp_pointer_var(&src_offs); | ||||
| 		dst = tmp_pointer_var(&dst_offs); | ||||
| 
 | ||||
| 		C_lal(src); | ||||
| 		C_sti(pointer_size); | ||||
| 		C_asp(-esz);		/* allocate stack block */ | ||||
| 		C_lor((arith)1);	/* push & of stack block as dst	*/ | ||||
| 		C_lal(dst); | ||||
| 		C_sti(pointer_size); | ||||
| 		copy_loop(sz, src, dst); | ||||
| 		free_tmp_var(dst_offs); | ||||
| 		free_tmp_var(src_offs); | ||||
| #else STB | ||||
| 		C_asp(-(esz - pointer_size));	/* allocate stack block */ | ||||
| 		C_lor((arith)1);	/* push & of stack block as dst	*/ | ||||
| 		C_dup(pointer_size);		/* fetch source address	*/ | ||||
|  | @ -84,5 +121,38 @@ load_block(sz, al) | |||
| 		C_loc(sz);			/* # bytes to copy	*/ | ||||
| 		C_cal("__stb");			/* library copy routine	*/ | ||||
| 		C_asp(int_size + pointer_size + pointer_size); | ||||
| #endif STB | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #ifndef STB | ||||
| copy_loop(sz, src, dst) | ||||
| 	arith sz, src, dst; | ||||
| { | ||||
| 	/* generate inline byte-copy loop */ | ||||
| 	label l_cont = text_label(), l_stop = text_label(); | ||||
| 
 | ||||
| 	C_loc(sz);		/* amount of bytes */ | ||||
| 	C_df_ilb(l_cont); | ||||
| 	C_dup(word_size); | ||||
| 	C_zle(l_stop); | ||||
| 	C_dec(); | ||||
| 	C_lal(src); | ||||
| 	C_loi(pointer_size); | ||||
| 	C_dup(pointer_size); | ||||
| 	C_adp((arith)1); | ||||
| 	C_lal(src); | ||||
| 	C_sti(pointer_size); | ||||
| 	C_loi((arith)1); | ||||
| 	C_lal(dst); | ||||
| 	C_loi(pointer_size); | ||||
| 	C_dup(pointer_size); | ||||
| 	C_adp((arith)1); | ||||
| 	C_lal(dst); | ||||
| 	C_sti(pointer_size); | ||||
| 	C_sti((arith)1); | ||||
| 	C_bra(l_cont); | ||||
| 	C_df_ilb(l_stop); | ||||
| 	C_asp(word_size); | ||||
| } | ||||
| #endif STB | ||||
|  |  | |||
|  | @ -121,11 +121,9 @@ ch7sel(expp, oper, idf) | |||
| 						intexpr(sd->sd_offset, INT)); | ||||
| 		} | ||||
| 	} | ||||
| 	else	{ | ||||
| 		/* oper == ARROW */ | ||||
| 	else /* oper == ARROW */ | ||||
| 		*expp = new_oper(sd->sd_type, | ||||
| 			*expp, oper, intexpr(sd->sd_offset, INT)); | ||||
| 	} | ||||
| 	(*expp)->ex_lvalue = (sd->sd_type->tp_fund != ARRAY); | ||||
| } | ||||
| 
 | ||||
|  | @ -135,44 +133,7 @@ ch7incr(expp, oper) | |||
| 	/*	The monadic prefix/postfix incr/decr operator oper is
 | ||||
| 		applied to *expp. | ||||
| 	*/ | ||||
| 	arith addend; | ||||
| 	struct expr *expr; | ||||
| 	register int fund = (*expp)->ex_type->tp_fund; | ||||
| 
 | ||||
| 	if (!(*expp)->ex_lvalue)	{ | ||||
| 		expr_error(*expp, "no lvalue with %s", symbol2str(oper)); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (fund == ENUM)	{ | ||||
| 		expr_warning(*expp, "%s on enum", symbol2str(oper)); | ||||
| 		addend = (arith)1; | ||||
| 	} | ||||
| 	else | ||||
| 	if (is_arith_type((*expp)->ex_type)) | ||||
| 		addend = (arith)1; | ||||
| 	else | ||||
| 	if (fund == POINTER) | ||||
| 		addend = size_of_type((*expp)->ex_type->tp_up, "object"); | ||||
| #ifndef NOBITFIELD | ||||
| 	else | ||||
| 	if (fund == FIELD) | ||||
| 		addend = (arith)1; | ||||
| #endif NOBITFIELD | ||||
| 	else	{ | ||||
| 		expr_error(*expp, "%s on %s", | ||||
| 				symbol2str(oper), | ||||
| 				symbol2str((*expp)->ex_type->tp_fund) | ||||
| 			); | ||||
| 		return; | ||||
| 	} | ||||
| 	expr = intexpr(addend, INT); | ||||
| 	ch7cast(&expr, CAST, (*expp)->ex_type); | ||||
| #ifndef NOBITFIELD | ||||
| 	if (fund == FIELD) | ||||
| 		*expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr); | ||||
| 	else | ||||
| #endif NOBITFIELD | ||||
| 		*expp = new_oper((*expp)->ex_type, *expp, oper, expr); | ||||
| 	ch7asgn(expp, oper, intexpr((arith)1, INT)); | ||||
| } | ||||
| 
 | ||||
| ch7cast(expp, oper, tp) | ||||
|  | @ -293,10 +254,8 @@ ch7cast(expp, oper, tp) | |||
| 			(*expp)->ex_type = tp; | ||||
| 	} | ||||
| 	else | ||||
| 	if (oldtp->tp_fund == ERRONEOUS)	{ | ||||
| 		/* we just won't look */ | ||||
| 		(*expp)->ex_type = tp;		/* brute force */ | ||||
| 	} | ||||
| 	if (oldtp->tp_fund == ERRONEOUS) /* we just won't look */ | ||||
| 		(*expp)->ex_type = tp;	/* brute force */ | ||||
| 	else | ||||
| 	if (oldtp->tp_size == tp->tp_size && oper == CAST)	{ | ||||
| 		expr_warning(*expp, "dubious conversion based on equal size"); | ||||
|  | @ -365,7 +324,6 @@ ch7asgn(expp, oper, expr) | |||
| 		else | ||||
| 			expr = extmp; | ||||
| 	} | ||||
| 
 | ||||
| #ifndef NOBITFIELD | ||||
| 	if (fund == FIELD) | ||||
| 		*expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr); | ||||
|  | @ -374,7 +332,6 @@ ch7asgn(expp, oper, expr) | |||
| #else NOBITFIELD | ||||
| 	*expp = new_oper((*expp)->ex_type, *expp, oper, expr); | ||||
| #endif NOBITFIELD | ||||
| 
 | ||||
| 	(*expp)->OP_TYPE = tp;	/* for EVAL() */ | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -82,16 +82,6 @@ ch7bin(expp, oper, expr) | |||
| 		break; | ||||
| 	case '%': | ||||
| 	case MODAB: | ||||
| /*** NB  "not float" means "integral" !!!
 | ||||
| 		fund = arithbalance(expp, oper, &expr); | ||||
| 		if (fund == DOUBLE)	{ | ||||
| 			expr_error(*expp, "floating operand to %s",  | ||||
| 				symbol2str(oper)); | ||||
| 			erroneous2int(expp); | ||||
| 		} | ||||
| 		else | ||||
| 			non_commutative_binop(expp, oper, expr); | ||||
| ***/ | ||||
| 		opnd2integral(expp, oper); | ||||
| 		opnd2integral(&expr, oper); | ||||
| 		fund = arithbalance(expp, oper, &expr); | ||||
|  | @ -111,21 +101,19 @@ ch7bin(expp, oper, expr) | |||
| 		non_commutative_binop(expp, oper, expr); | ||||
| 		break; | ||||
| 	case '+': | ||||
| 		if (expr->ex_type->tp_fund == POINTER)	{ | ||||
| 			/* swap operands */ | ||||
| 		if (expr->ex_type->tp_fund == POINTER)	{ /* swap operands */ | ||||
| 			struct expr *etmp = expr; | ||||
| 			expr = *expp; | ||||
| 			*expp = etmp; | ||||
| 		} | ||||
| 		/*FALLTHROUGH*/ | ||||
| 	case PLUSAB: | ||||
| 	case POSTINCR: | ||||
| 	case PLUSPLUS: | ||||
| 		if ((*expp)->ex_type->tp_fund == POINTER)	{ | ||||
| 			pointer_arithmetic(expp, oper, &expr); | ||||
| 			if (	expr->ex_type->tp_size != | ||||
| 				(*expp)->ex_type->tp_size | ||||
| 			)	{ | ||||
| 			if (expr->ex_type->tp_size != (*expp)->ex_type->tp_size) | ||||
| 				ch7cast(&expr, CAST, (*expp)->ex_type); | ||||
| 			} | ||||
| 			pointer_binary(expp, oper, expr); | ||||
| 		} | ||||
| 		else	{ | ||||
|  | @ -138,6 +126,8 @@ ch7bin(expp, oper, expr) | |||
| 		break; | ||||
| 	case '-': | ||||
| 	case MINAB: | ||||
| 	case POSTDECR: | ||||
| 	case MINMIN: | ||||
| 		if ((*expp)->ex_type->tp_fund == POINTER)	{ | ||||
| 			if (expr->ex_type->tp_fund == POINTER) | ||||
| 				pntminuspnt(expp, oper, expr); | ||||
|  | @ -231,13 +221,11 @@ ch7bin(expp, oper, expr) | |||
| 		if (	is_struct_or_union((*expp)->ex_type->tp_fund) | ||||
| 		||	is_struct_or_union(expr->ex_type->tp_fund) | ||||
| 		)	{ | ||||
| 			if ((*expp)->ex_type != expr->ex_type)	{ | ||||
| 			if ((*expp)->ex_type != expr->ex_type) | ||||
| 				expr_error(*expp, "illegal balance"); | ||||
| 			} | ||||
| 		} | ||||
| 		else	{ | ||||
| 		else | ||||
| 			relbalance(expp, oper, &expr); | ||||
| 		} | ||||
| 		*expp = new_oper((*expp)->ex_type, *expp, oper, expr); | ||||
| 		break; | ||||
| 	case '?': | ||||
|  |  | |||
|  | @ -28,16 +28,15 @@ | |||
| #include	"atw.h" | ||||
| #include	"assert.h" | ||||
| 
 | ||||
| static struct stmt_block *stmt_stack; | ||||
| 
 | ||||
| char *symbol2str(); | ||||
| #ifndef NOFLOAT | ||||
| int fp_used; | ||||
| #endif NOFLOAT | ||||
| label lab_count = 1; | ||||
| label datlab_count = 1; | ||||
| 
 | ||||
| #ifndef NOFLOAT | ||||
| int fp_used; | ||||
| #endif NOFLOAT | ||||
| 
 | ||||
| extern char options[]; | ||||
| char *symbol2str(); | ||||
| 
 | ||||
| init_code(dst_file) | ||||
| 	char *dst_file; | ||||
|  | @ -112,16 +111,11 @@ prepend_scopes(dst_file) | |||
| 		fatal("cannot create %s", dst_file ? dst_file : "stdout"); | ||||
| 	famous_first_words(); | ||||
| 	while (se != 0)	{ | ||||
| 		register struct idf *idf = se->se_idf; | ||||
| 		register struct def *def = idf->id_def; | ||||
| 		register struct idf *id = se->se_idf; | ||||
| 		register struct def *df = id->id_def; | ||||
| 		 | ||||
| 		if (def && | ||||
| 			(	def->df_initialized || | ||||
| 				def->df_used || | ||||
| 				def->df_alloc | ||||
| 			) | ||||
| 		) | ||||
| 			code_scope(idf->id_text, def); | ||||
| 		if (df && (df->df_initialized || df->df_used || df->df_alloc)) | ||||
| 			code_scope(id->id_text, df); | ||||
| 		se = se->next; | ||||
| 	} | ||||
| 	C_close(); | ||||
|  | @ -198,7 +192,6 @@ begin_proc(name, def)	/* to be called when entering a procedure	*/ | |||
| 	} | ||||
| 	else | ||||
| 		func_res_label = 0; | ||||
| 
 | ||||
| 	/*	Special arrangements if the function result doesn't fit in
 | ||||
| 		the function return area of the EM machine.  The size of | ||||
| 		the function return area is implementation dependent. | ||||
|  | @ -206,15 +199,12 @@ begin_proc(name, def)	/* to be called when entering a procedure	*/ | |||
| 	lab_count = (label) 1; | ||||
| 	return_label = text_label(); | ||||
| 	return_expr_occurred = 0; | ||||
| 
 | ||||
| 	if (options['p'])	{	/* profiling */ | ||||
| 		if (strcmp(last_fn_given, FileName) != 0)	{ | ||||
| 			/* previous function came from other file */ | ||||
| 			C_df_dlb(file_name_label = data_label()); | ||||
| 			C_con_scon( | ||||
| 				last_fn_given = FileName, | ||||
| 				(arith)(strlen(FileName) + 1) | ||||
| 			); | ||||
| 			C_con_scon(last_fn_given = FileName, | ||||
| 				(arith)(strlen(FileName) + 1)); | ||||
| 		} | ||||
| 		/* enable debug trace of EM source */ | ||||
| 		C_fil_dlb(file_name_label, (arith)0); | ||||
|  | @ -345,17 +335,14 @@ code_declaration(idf, expr, lvl, sc) | |||
| 	} | ||||
| 	else | ||||
| 	if (lvl >= L_LOCAL)	{	/* local variable	*/ | ||||
| 		/* they are STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or
 | ||||
| 		   REGISTER | ||||
| 		*/ | ||||
| 		/* STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or REGISTER */ | ||||
| 		switch (def_sc)	{ | ||||
| 		case STATIC: | ||||
| 			/*	they are handled on the spot and get an
 | ||||
| 				integer label in EM. | ||||
| 			*/ | ||||
| 			C_df_dlb((label)def->df_address); | ||||
| 			if (expr)	{ | ||||
| 				/* there is an initialisation	*/ | ||||
| 			if (expr) { /* there is an initialisation */ | ||||
| 				do_ival(&(def->df_type), expr); | ||||
| 				free_expression(expr); | ||||
| 			} | ||||
|  | @ -364,8 +351,7 @@ code_declaration(idf, expr, lvl, sc) | |||
| 					error("size of %s unknown", text); | ||||
| 					size = (arith)0; | ||||
| 				} | ||||
| 				C_bss_cst(align(size, word_align), | ||||
| 							(arith)0, 1); | ||||
| 				C_bss_cst(align(size, word_align), (arith)0, 1); | ||||
| 			} | ||||
| 			break; | ||||
| 		case EXTERN: | ||||
|  | @ -399,7 +385,6 @@ loc_init(expr, id) | |||
| 	register struct type *tp = id->id_def->df_type; | ||||
| 	 | ||||
| 	ASSERT(id->id_def->df_sc != STATIC); | ||||
| 	/* automatic aggregates cannot be initialised. */ | ||||
| 	switch (tp->tp_fund)	{ | ||||
| 	case ARRAY: | ||||
| 	case STRUCT: | ||||
|  | @ -408,7 +393,6 @@ loc_init(expr, id) | |||
| 		free_expression(expr); | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	if (ISCOMMA(expr))	{	/* embraced: int i = {12};	*/ | ||||
| 		if (options['R'])	{ | ||||
| 			if (ISCOMMA(expr->OP_LEFT)) /* int i = {{1}} */ | ||||
|  | @ -463,14 +447,15 @@ formal_cvt(df) | |||
| 	*/ | ||||
| 	register struct type *tp = df->df_type; | ||||
| 
 | ||||
| 	if (tp->tp_size != int_size) | ||||
| 		if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) { | ||||
| 			C_lol(df->df_address); | ||||
| 			conversion(int_type, df->df_type); | ||||
| 			C_lal(df->df_address); | ||||
| 			C_sti(tp->tp_size); | ||||
| 			df->df_register = REG_NONE; | ||||
| 		} | ||||
| 	if (tp->tp_size != int_size && | ||||
| 		(tp->tp_fund == CHAR || tp->tp_fund == SHORT) | ||||
| 	) { | ||||
| 		C_lol(df->df_address); | ||||
| 		/* conversion(int_type, df->df_type); ??? */ | ||||
| 		C_lal(df->df_address); | ||||
| 		C_sti(tp->tp_size); | ||||
| 		df->df_register = REG_NONE; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| code_expr(expr, val, code, tlbl, flbl) | ||||
|  | @ -478,8 +463,7 @@ code_expr(expr, val, code, tlbl, flbl) | |||
| 	label tlbl, flbl; | ||||
| { | ||||
| 	/*	code_expr() is the parser's interface to the expression code
 | ||||
| 		generator. | ||||
| 		If line number trace is wanted, it generates a | ||||
| 		generator.  If line number trace is wanted, it generates a | ||||
| 		lin instruction.  EVAL() is called directly. | ||||
| 	*/ | ||||
| 	if (options['p'])	/* profiling	*/ | ||||
|  | @ -493,6 +477,8 @@ code_expr(expr, val, code, tlbl, flbl) | |||
| 	EM labels where a subsequent break or continue causes | ||||
| 	the program to jump to. | ||||
| */ | ||||
| static struct stmt_block *stmt_stack;	/* top of statement stack */ | ||||
| 
 | ||||
| /*	code_break() generates EM code needed at the occurrence of "break":
 | ||||
| 	it generates a branch instruction to the break label of the | ||||
| 	innermost statement in which break has a meaning. | ||||
|  | @ -504,11 +490,10 @@ code_break() | |||
| { | ||||
| 	register struct stmt_block *stmt_block = stmt_stack; | ||||
| 
 | ||||
| 	if (stmt_block)	{ | ||||
| 	if (stmt_block) | ||||
| 		C_bra(stmt_block->st_break); | ||||
| 		return; | ||||
| 	} | ||||
| 	error("break not inside for, while, do or switch"); | ||||
| 	else | ||||
| 		error("break not inside for, while, do or switch"); | ||||
| } | ||||
| 
 | ||||
| /*	code_continue() generates EM code needed at the occurrence of
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| /* $Header$ */ | ||||
| /*	D E C L A R A T O R   M A N I P U L A T I O N		*/ | ||||
| 
 | ||||
| #include	"botch_free.h"	/* UF */ | ||||
| #include	"botch_free.h" | ||||
| #include	"alloc.h" | ||||
| #include	"arith.h" | ||||
| #include	"type.h" | ||||
|  |  | |||
|  | @ -17,7 +17,6 @@ | |||
| #include	"parbufsize.h"	 | ||||
| #include	"textsize.h"	 | ||||
| #include	"idfsize.h"	 | ||||
| 
 | ||||
| #include	"assert.h" | ||||
| #include	"alloc.h" | ||||
| #include	"class.h" | ||||
|  | @ -301,14 +300,10 @@ PRIVATE | |||
| do_elif() | ||||
| { | ||||
| 	if (nestlevel < 0 || (ifstack[nestlevel])) { | ||||
| 		/* invalid elif encountered..		*/ | ||||
| 		lexerror("#elif without corresponding #if"); | ||||
| 		SkipRestOfLine(); | ||||
| 	} | ||||
| 	else { | ||||
| 		/*	restart at this level as if a #if
 | ||||
| 			is detected. | ||||
| 		*/ | ||||
| 	else { /* restart at this level as if a #if is detected.  */ | ||||
| 		nestlevel--; | ||||
| 		push_if(); | ||||
| 		skip_block(); | ||||
|  | @ -377,8 +372,7 @@ do_undef() | |||
| 		if (id && id->id_macro) { /* forget the macro */ | ||||
| 			free_macro(id->id_macro); | ||||
| 			id->id_macro = (struct macro *) 0; | ||||
| 		} | ||||
| 		/* else: don't complain */ | ||||
| 		} /* else: don't complain */ | ||||
| 	} | ||||
| 	else | ||||
| 		lexerror("illegal #undef construction"); | ||||
|  | @ -470,8 +464,7 @@ macro_def(id, text, nformals, length, flags) | |||
| 			if (macroeq(newdef->mc_text, text)) | ||||
| 				return; | ||||
| 			lexwarning("redefine \"%s\"", id->id_text); | ||||
| 		} | ||||
| 		/* else: overwrite pre-definition	*/ | ||||
| 		} /* else: overwrite pre-definition	*/ | ||||
| 	} | ||||
| 	else | ||||
| 		id->id_macro = newdef = new_macro(); | ||||
|  |  | |||
|  | @ -1,17 +1,6 @@ | |||
| /* $Header$ */ | ||||
| /* EXPRESSION-CODE GENERATOR */ | ||||
| 
 | ||||
| /*	main functions :
 | ||||
| 		EVAL()			-- expression tree evaluator | ||||
| 		tmp_pointer_var()	-- deliver temporary pointer variable | ||||
| 		free_tmp_var()		-- return the pointer var | ||||
| 		store_val()		-- store primary expression | ||||
| 		load_val()		-- load primary expression | ||||
| 	auxiliary functions: | ||||
| 		assop() | ||||
| 		compare() | ||||
| */ | ||||
| 
 | ||||
| #include	"nofloat.h" | ||||
| #include	<em.h> | ||||
| #include	"debug.h" | ||||
|  | @ -40,45 +29,40 @@ char *symbol2str(); | |||
| char *long2str(); | ||||
| arith tmp_pointer_var(); | ||||
| 
 | ||||
| /*	EVAL() serves as the main expression tree evaluator, which turns
 | ||||
| 	any legal expression tree into legal EM code. | ||||
| 	The parameters describe how EVAL should treat the expression tree: | ||||
| /*	EVAL() is the main expression-tree evaluator, which turns
 | ||||
| 	any legal expression tree into EM code. Parameters: | ||||
| 
 | ||||
| 	struct expr *expr:	pointer to root of the expression tree to | ||||
| 				be evaluated | ||||
| 	struct expr *expr | ||||
| 		pointer to root of the expression tree to be evaluated | ||||
| 
 | ||||
| 	int val:		indicates whether the resulting expression | ||||
| 				is to be dereferenced (if val == RVAL and | ||||
| 				expr->ex_lvalue == 1) or not (val == LVAL). | ||||
| 				The latter case indicates that the resulting | ||||
| 				expression is an lvalue expression which should | ||||
| 				not be dereferenced by EVAL | ||||
| 	int val | ||||
| 		indicates whether the resulting expression is to be | ||||
| 		dereferenced (if val == RVAL and expr->ex_lvalue == 1) | ||||
| 		or not (val == LVAL).  The latter case indicates that | ||||
| 		the resulting expression is an lvalue expression which | ||||
| 		should not be dereferenced by EVAL | ||||
| 	 | ||||
| 	int code:		indicates whether the expression tree must be | ||||
| 				turned into EM code or not. E.g. the expression | ||||
| 				statement "12;" delivers the expression "12" to | ||||
| 				EVAL while this should not result in any EM | ||||
| 				code | ||||
| 	int code | ||||
| 		indicates whether the expression tree must be turned | ||||
| 		into EM code or not. E.g. the expression statement "12;" | ||||
| 		delivers the expression "12" to EVAL while this should | ||||
| 		not result in any EM code | ||||
| 	 | ||||
| 	label false_label: | ||||
| 	label true_label:	if the expression is a logical or relational | ||||
| 				expression and if the loop of the program | ||||
| 				depends on the resulting value then EVAL | ||||
| 				generates jumps to the specified program | ||||
| 				labels, in case they are specified | ||||
| 				(i.e. are non-zero) | ||||
| 	label false_label, label true_label | ||||
| 		if the expression is a logical or relational expression | ||||
| 		and if the loop of the program depends on the resulting | ||||
| 		value then EVAL generates jumps to the specified program | ||||
| 		labels, in case they are specified (i.e. are non-zero) | ||||
| */ | ||||
| 
 | ||||
| EVAL(expr, val, code, true_label, false_label) | ||||
| 	register struct expr *expr;	/* the expression tree itself	*/ | ||||
| 	int val;		/* either RVAL or LVAL			*/ | ||||
| 	int code;		/* generate explicit code or not	*/ | ||||
| 	label true_label; | ||||
| 	label false_label;	/* labels to jump to in logical expr's	*/ | ||||
| 	register struct expr *expr; | ||||
| 	int val, code; | ||||
| 	label true_label, false_label; | ||||
| { | ||||
| 	register int gencode = (code == TRUE); | ||||
| 
 | ||||
| 	switch (expr->ex_class)	{ | ||||
| 	switch (expr->ex_class) { | ||||
| 	case Value:	/* just a simple value	*/ | ||||
| 		if (gencode) | ||||
| 			load_val(expr, val); | ||||
|  | @ -107,23 +91,22 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 	case Oper:	/* compound expression	*/ | ||||
| 	{ | ||||
| 		int oper = expr->OP_OPER; | ||||
| 		register struct expr *leftop = expr->OP_LEFT; | ||||
| 		register struct expr *rightop = expr->OP_RIGHT; | ||||
| 		register struct expr *left = expr->OP_LEFT; | ||||
| 		register struct expr *right = expr->OP_RIGHT; | ||||
| 		register struct type *tp = expr->OP_TYPE; | ||||
| 
 | ||||
| 		if (tp->tp_fund == ERRONEOUS)	/* stop immediately */ | ||||
| 			break; | ||||
| 		switch (oper)	{ | ||||
| 		switch (oper) { | ||||
| 		case '+': | ||||
| 			/*	We have the following possibilities :
 | ||||
| 				int + int, pointer + int, pointer + long, | ||||
| 				long + long, double + double | ||||
| 			*/ | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 
 | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) { | ||||
| 				switch (tp->tp_fund)	{ | ||||
| 				switch (tp->tp_fund) { | ||||
| 				case INT: | ||||
| 				case LONG: | ||||
| 					if (tp->tp_unsigned) | ||||
|  | @ -132,7 +115,7 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 						C_adi(tp->tp_size); | ||||
| 					break; | ||||
| 				case POINTER: | ||||
| 					C_ads(rightop->ex_type->tp_size); | ||||
| 					C_ads(right->ex_type->tp_size); | ||||
| 					break; | ||||
| #ifndef NOFLOAT | ||||
| 				case DOUBLE: | ||||
|  | @ -145,10 +128,10 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 			} | ||||
| 			break; | ||||
| 		case '-': | ||||
| 			if (leftop == 0)	{	/* unary	*/ | ||||
| 				EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (left == 0) {	/* unary	*/ | ||||
| 				EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 				if (gencode) { | ||||
| 					switch (tp->tp_fund)	{ | ||||
| 					switch (tp->tp_fund) { | ||||
| 					case INT: | ||||
| 					case LONG: | ||||
| 					case POINTER: | ||||
|  | @ -165,16 +148,15 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 			/*	Binary: we have the following flavours:
 | ||||
| 			/*	else binary; we have the following flavours:
 | ||||
| 				int - int, pointer - int, pointer - long, | ||||
| 				pointer - pointer, long - long, double - double | ||||
| 			*/ | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 
 | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (!gencode) | ||||
| 				break; | ||||
| 			switch (tp->tp_fund)	{ | ||||
| 			switch (tp->tp_fund) { | ||||
| 			case INT: | ||||
| 			case LONG: | ||||
| 				if (tp->tp_unsigned) | ||||
|  | @ -183,11 +165,11 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 					C_sbi(tp->tp_size); | ||||
| 				break; | ||||
| 			case POINTER: | ||||
| 				if (rightop->ex_type->tp_fund == POINTER) | ||||
| 				if (right->ex_type->tp_fund == POINTER) | ||||
| 					C_sbs(pointer_size); | ||||
| 				else	{ | ||||
| 					C_ngi(rightop->ex_type->tp_size); | ||||
| 					C_ads(rightop->ex_type->tp_size); | ||||
| 				else { | ||||
| 					C_ngi(right->ex_type->tp_size); | ||||
| 					C_ads(right->ex_type->tp_size); | ||||
| 				} | ||||
| 				break; | ||||
| #ifndef NOFLOAT | ||||
|  | @ -200,13 +182,13 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 			} | ||||
| 			break; | ||||
| 		case '*': | ||||
| 			if (leftop == 0)	/* unary	*/ | ||||
| 				EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			else	{		/* binary	*/ | ||||
| 				EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 				EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (left == 0) /* unary */ | ||||
| 				EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			else { /* binary */ | ||||
| 				EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 				EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 				if (gencode) | ||||
| 					switch (tp->tp_fund)	{ | ||||
| 					switch (tp->tp_fund) { | ||||
| 					case INT: | ||||
| 					case LONG: | ||||
| 					case POINTER: | ||||
|  | @ -226,10 +208,10 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 			} | ||||
| 			break; | ||||
| 		case '/': | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) | ||||
| 				switch (tp->tp_fund)	{ | ||||
| 				switch (tp->tp_fund) { | ||||
| 				case INT: | ||||
| 				case LONG: | ||||
| 				case POINTER: | ||||
|  | @ -248,8 +230,8 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 				} | ||||
| 			break; | ||||
| 		case '%': | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG); | ||||
| 			if (gencode) | ||||
| 				if (tp->tp_unsigned) | ||||
|  | @ -258,8 +240,8 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 					C_rmi(tp->tp_size); | ||||
| 			break; | ||||
| 		case LEFT: | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) | ||||
| 				if (tp->tp_unsigned) | ||||
| 					C_slu(tp->tp_size); | ||||
|  | @ -267,8 +249,8 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 					C_sli(tp->tp_size); | ||||
| 			break; | ||||
| 		case RIGHT: | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) | ||||
| 				if (tp->tp_unsigned) | ||||
| 					C_sru(tp->tp_size); | ||||
|  | @ -281,16 +263,16 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 		case GREATEREQ: | ||||
| 		case EQUAL: | ||||
| 		case NOTEQUAL: | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) { | ||||
| 				/* The operands have the same type */ | ||||
| 				arith size = leftop->ex_type->tp_size; | ||||
| 				arith size = left->ex_type->tp_size; | ||||
| 				 | ||||
| 				switch (tp->tp_fund)	{ | ||||
| 				switch (tp->tp_fund) { | ||||
| 				case INT: | ||||
| 				case LONG: | ||||
| 					if (leftop->ex_type->tp_unsigned) | ||||
| 					if (left->ex_type->tp_unsigned) | ||||
| 						C_cmu(size); | ||||
| 					else | ||||
| 						C_cmi(size); | ||||
|  | @ -310,11 +292,11 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 				default: | ||||
| 					CRASH(); | ||||
| 				} | ||||
| 				if (true_label != 0)	{ | ||||
| 				if (true_label != 0) { | ||||
| 					compare(oper, true_label); | ||||
| 					C_bra(false_label); | ||||
| 				} | ||||
| 				else	{ | ||||
| 				else { | ||||
| 					label l_true = text_label(); | ||||
| 					label l_end = text_label(); | ||||
| 
 | ||||
|  | @ -331,14 +313,14 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 		case '|': | ||||
| 		case '^': | ||||
| 			/* both operands should have type int	*/ | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) { | ||||
| 				arith size = tp->tp_size; | ||||
| 
 | ||||
| 				if (size < word_size) | ||||
| 					size = word_size; | ||||
| 				switch (oper)	{ | ||||
| 				switch (oper) { | ||||
| 				case '&': | ||||
| 					C_and(size); | ||||
| 					break; | ||||
|  | @ -353,26 +335,21 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 			break; | ||||
| 		case '=': | ||||
| #ifndef NOBITFIELD | ||||
| 			if (leftop->ex_type->tp_fund == FIELD)	{ | ||||
| 				/*	assignment to bitfield variable
 | ||||
| 				*/ | ||||
| 			if (left->ex_type->tp_fund == FIELD) { | ||||
| 				eval_field(expr, code); | ||||
| 				break; | ||||
| 			} | ||||
| #endif NOBITFIELD | ||||
| 			EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) | ||||
| 				C_dup(ATW(tp->tp_size)); | ||||
| 
 | ||||
| 			if (leftop->ex_class != Value) { | ||||
| 				EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			if (left->ex_class != Value) { | ||||
| 				EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				store_block(tp->tp_size, tp->tp_align); | ||||
| 			} | ||||
| 			else | ||||
| 				store_val( | ||||
| 					&(leftop->ex_object.ex_value), | ||||
| 					leftop->ex_type | ||||
| 				); | ||||
| 				store_val(&(left->ex_object.ex_value), | ||||
| 					left->ex_type); | ||||
| 			break; | ||||
| 		case PLUSAB: | ||||
| 		case MINAB: | ||||
|  | @ -384,47 +361,60 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 		case ANDAB: | ||||
| 		case XORAB: | ||||
| 		case ORAB: | ||||
| 		case POSTINCR: | ||||
| 		case POSTDECR: | ||||
| 		case PLUSPLUS: | ||||
| 		case MINMIN: | ||||
| 		{ | ||||
| 			arith old_offset; | ||||
| 			arith tmpvar = tmp_pointer_var(&old_offset); | ||||
| 
 | ||||
| 			arith old_offset, tmp; | ||||
| 			int compl;	/* Complexity of left operand */ | ||||
| #ifndef NOBITFIELD | ||||
| 			if (leftop->ex_type->tp_fund == FIELD)	{ | ||||
| 			if (left->ex_type->tp_fund == FIELD) { | ||||
| 				eval_field(expr, code); | ||||
| 				break; | ||||
| 			} | ||||
| #endif NOBITFIELD | ||||
| 			if (leftop->ex_class != Value) { | ||||
| 				EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				C_lal(tmpvar); | ||||
| 				C_sti(pointer_size); | ||||
| 				C_lal(tmpvar); | ||||
| 				C_loi(pointer_size); | ||||
| 				C_loi(leftop->ex_type->tp_size); | ||||
| 			if (left->ex_class == Value) { | ||||
| 				compl = 0; /* Value */ | ||||
| 				load_val(left, RVAL); | ||||
| 			} | ||||
| 			else	{ | ||||
| 				load_val(leftop, RVAL); | ||||
| 			} | ||||
| 			conversion(leftop->ex_type, tp); | ||||
| 			EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			assop(tp, oper); | ||||
| 			conversion(tp, leftop->ex_type); | ||||
| 			if (gencode) | ||||
| 				C_dup(toword(leftop->ex_type->tp_size)); | ||||
| 			if (leftop->ex_class != Value) { | ||||
| 				C_lal(tmpvar); | ||||
| 				C_loi(pointer_size); | ||||
| 				C_sti(leftop->ex_type->tp_size); | ||||
| 				free_tmp_var(old_offset); | ||||
| 			else | ||||
| 			if (left->ex_depth == 1 && left->OP_OPER == ARROW) { | ||||
| 				compl = 1; /* Value->sel */ | ||||
| 				ASSERT(left->OP_LEFT->ex_class == Value); | ||||
| 				EVAL(left, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			} | ||||
| 			else { | ||||
| 				store_val( | ||||
| 					&(leftop->ex_object.ex_value), | ||||
| 					leftop->ex_type | ||||
| 				); | ||||
| 				compl = 2; /* otherwise */ | ||||
| 				tmp = tmp_pointer_var(&old_offset); | ||||
| 				EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				C_dup(pointer_size); | ||||
| 				C_lal(tmp); | ||||
| 				C_sti(pointer_size); | ||||
| 				C_loi(left->ex_type->tp_size); | ||||
| 			} | ||||
| 			conversion(left->ex_type, tp); | ||||
| 			if (gencode && (oper == POSTINCR || oper == POSTDECR)) | ||||
| 				C_dup(tp->tp_size); | ||||
| 			EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			assop(tp, oper); | ||||
| 			if (gencode && oper != POSTINCR && oper != POSTDECR) | ||||
| 				C_dup(tp->tp_size); | ||||
| 			conversion(tp, left->ex_type); | ||||
| 			if (compl == 0) | ||||
| 				store_val(&(left->ex_object.ex_value), | ||||
| 					left->ex_type); | ||||
| 			else | ||||
| 			if (compl == 1) { | ||||
| 				EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				C_sti(left->ex_type->tp_size); | ||||
| 			} | ||||
| 			else { | ||||
| 				C_lal(tmp);	/* always init'd */ | ||||
| 				C_loi(pointer_size); | ||||
| 				C_sti(left->ex_type->tp_size); | ||||
| 				free_tmp_var(old_offset); | ||||
| 			} | ||||
| 			if (gencode) | ||||
| 				conversion(leftop->ex_type, expr->ex_type); | ||||
| 			break; | ||||
| 		} | ||||
| 		case '(': | ||||
|  | @ -432,7 +422,7 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 			register struct expr *ex; | ||||
| 			arith ParSize = (arith)0; | ||||
| 
 | ||||
| 			if ((ex = rightop) != NILEXPR)	{ | ||||
| 			if ((ex = right) != NILEXPR) { | ||||
| 				/* function call with parameters*/ | ||||
| 				while (	ex->ex_class == Oper && | ||||
| 					ex->OP_OPER == PARCOMMA | ||||
|  | @ -445,24 +435,19 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 				EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				ParSize += ATW(ex->ex_type->tp_size); | ||||
| 			} | ||||
| 			if (	leftop->ex_class == Value | ||||
| 			&&	leftop->VL_CLASS == Name | ||||
| 			) { | ||||
| 				/* just an example:
 | ||||
| 					main() { (*((int (*)())0))(); } | ||||
| 				*/ | ||||
| 				C_cal(leftop->VL_IDF->id_text); | ||||
| 			if (left->ex_class == Value && left->VL_CLASS == Name) { | ||||
| 				/* e.g., main() { (*((int (*)())0))(); } */ | ||||
| 				C_cal(left->VL_IDF->id_text); | ||||
| #ifdef	DATAFLOW | ||||
| 				{	extern char options[]; | ||||
| 					if (options['d']) | ||||
| 						DfaCallFunction( | ||||
| 							leftop->VL_IDF->id_text | ||||
| 						); | ||||
| 							left->VL_IDF->id_text); | ||||
| 				} | ||||
| #endif	DATAFLOW | ||||
| 			} | ||||
| 			else	{ | ||||
| 				EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			else { | ||||
| 				EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				C_cai(); | ||||
| 			} | ||||
| 			/* remove parameters from stack	*/ | ||||
|  | @ -479,124 +464,53 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 			break; | ||||
| 		} | ||||
| 		case '.': | ||||
| 			EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			ASSERT(is_cp_cst(rightop)); | ||||
| 			EVAL(left, LVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			ASSERT(is_cp_cst(right)); | ||||
| 			if (gencode) | ||||
| 				C_adp(rightop->VL_VALUE); | ||||
| 				C_adp(right->VL_VALUE); | ||||
| 			break; | ||||
| 		case ARROW: | ||||
| 			EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			ASSERT(is_cp_cst(rightop)); | ||||
| 			EVAL(left, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			ASSERT(is_cp_cst(right)); | ||||
| 			if (gencode) | ||||
| 				C_adp(rightop->VL_VALUE); | ||||
| 				C_adp(right->VL_VALUE); | ||||
| 			break; | ||||
| 		case ',': | ||||
| 			EVAL(leftop, RVAL, FALSE, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			break; | ||||
| 		case '~': | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) | ||||
| 				C_com(tp->tp_size); | ||||
| 			break; | ||||
| 		case POSTINCR: | ||||
| 		case POSTDECR: | ||||
| 		case PLUSPLUS: | ||||
| 		case MINMIN: | ||||
| 		{ | ||||
| 			arith old_offset, tmp; | ||||
| 			arith esize = tp->tp_size; | ||||
| 			int compl;	/* Complexity of left operand */ | ||||
| #ifndef NOBITFIELD | ||||
| 			if (leftop->ex_type->tp_fund == FIELD)	{ | ||||
| 				eval_field(expr, code); | ||||
| 				break; | ||||
| 			} | ||||
| #endif NOBITFIELD | ||||
| 			if (leftop->ex_class == Value) { | ||||
| 				compl = 0; /* Value */ | ||||
| 				load_val(leftop, RVAL); | ||||
| 			} | ||||
| 			else | ||||
| 			if (leftop->ex_depth == 1 && leftop->OP_OPER == ARROW) { | ||||
| 				compl = 1; /* Value->sel */ | ||||
| 				ASSERT(leftop->OP_LEFT->ex_class == Value); | ||||
| 				EVAL(leftop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			} | ||||
| 			else { | ||||
| 				compl = 2; /* otherwise */ | ||||
| 				tmp = tmp_pointer_var(&old_offset); | ||||
| 				EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				C_dup(pointer_size); | ||||
| 				C_lal(tmp); | ||||
| 				C_sti(pointer_size); | ||||
| 				C_loi(esize); | ||||
| 			} | ||||
| 
 | ||||
| 			/*	We made the choice to put this stuff here
 | ||||
| 				and not to put the conversion in the expression | ||||
| 				tree because this conversion is EM dependent | ||||
| 				and not described in C | ||||
| 			*/ | ||||
| 			if (esize < word_size)	{ | ||||
| 				conversion(tp, word_type); | ||||
| 				esize = word_size; | ||||
| 			} | ||||
| 
 | ||||
| 			if (gencode && (oper == POSTINCR || oper == POSTDECR)) | ||||
| 				C_dup(esize); | ||||
| 			EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 			assop(tp, oper); | ||||
| 			if (gencode && (oper == PLUSPLUS || oper == MINMIN)) | ||||
| 				C_dup(esize); | ||||
| 			if (tp->tp_size < word_size) | ||||
| 				conversion(word_type, tp); | ||||
| 			if (compl == 0) { | ||||
| 				store_val( | ||||
| 					&(leftop->ex_object.ex_value), | ||||
| 					leftop->ex_type | ||||
| 				); | ||||
| 			} | ||||
| 			else | ||||
| 			if (compl == 1) { | ||||
| 				EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 				C_sti(tp->tp_size); | ||||
| 			} | ||||
| 			else { | ||||
| 				C_lal(tmp);	/* always init'd */ | ||||
| 				C_loi(pointer_size); | ||||
| 				C_sti(tp->tp_size); | ||||
| 				free_tmp_var(old_offset); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		case '?':	/* must be followed by ':'	*/ | ||||
| 		{ | ||||
| 			label l_true = text_label(); | ||||
| 			label l_false = text_label(); | ||||
| 			label l_end = text_label(); | ||||
| 
 | ||||
| 			EVAL(leftop, RVAL, TRUE, l_true, l_false); | ||||
| 			EVAL(left, RVAL, TRUE, l_true, l_false); | ||||
| 			C_df_ilb(l_true); | ||||
| 			EVAL(rightop->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			C_bra(l_end); | ||||
| 			C_df_ilb(l_false); | ||||
| 			EVAL(rightop->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			C_df_ilb(l_end); | ||||
| 			break; | ||||
| 		} | ||||
| 		case AND: | ||||
| 			if (true_label == 0)	{ | ||||
| 			if (true_label == 0) { | ||||
| 				label l_true = text_label(); | ||||
| 				label l_false = text_label(); | ||||
| 				label l_maybe = text_label(); | ||||
| 				label l_end = text_label(); | ||||
| 
 | ||||
| 				EVAL(leftop, RVAL, TRUE, l_maybe, l_false); | ||||
| 				EVAL(left, RVAL, TRUE, l_maybe, l_false); | ||||
| 				C_df_ilb(l_maybe); | ||||
| 				if (gencode)	{ | ||||
| 					EVAL(rightop, RVAL, TRUE, | ||||
| 							l_true, l_false); | ||||
| 				if (gencode) { | ||||
| 					EVAL(right, RVAL, TRUE, l_true, | ||||
| 						l_false); | ||||
| 					C_df_ilb(l_true); | ||||
| 					C_loc((arith)1); | ||||
| 					C_bra(l_end); | ||||
|  | @ -605,32 +519,32 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 					C_df_ilb(l_end); | ||||
| 				} | ||||
| 				else { | ||||
| 					EVAL(rightop, RVAL, FALSE, l_false, | ||||
| 					EVAL(right, RVAL, FALSE, l_false, | ||||
| 						l_false); | ||||
| 					C_df_ilb(l_false); | ||||
| 				} | ||||
| 			} | ||||
| 			else	{ | ||||
| 			else { | ||||
| 				label l_maybe = text_label(); | ||||
| 
 | ||||
| 				EVAL(leftop, RVAL, TRUE, l_maybe, false_label); | ||||
| 				EVAL(left, RVAL, TRUE, l_maybe, false_label); | ||||
| 				C_df_ilb(l_maybe); | ||||
| 				EVAL(rightop, RVAL, code, true_label, | ||||
| 				EVAL(right, RVAL, code, true_label, | ||||
| 					false_label); | ||||
| 			} | ||||
| 			break; | ||||
| 		case OR: | ||||
| 			if (true_label == 0)	{ | ||||
| 			if (true_label == 0) { | ||||
| 				label l_true = text_label(); | ||||
| 				label l_false = text_label(); | ||||
| 				label l_maybe = text_label(); | ||||
| 				label l_end = text_label(); | ||||
| 
 | ||||
| 				EVAL(leftop, RVAL, TRUE, l_true, l_maybe); | ||||
| 				EVAL(left, RVAL, TRUE, l_true, l_maybe); | ||||
| 				C_df_ilb(l_maybe); | ||||
| 				if (gencode)	{ | ||||
| 					EVAL(rightop, RVAL, TRUE, | ||||
| 							l_true, l_false); | ||||
| 				if (gencode) { | ||||
| 					EVAL(right, RVAL, TRUE, l_true, | ||||
| 						l_false); | ||||
| 					C_df_ilb(l_false); | ||||
| 					C_loc((arith)0); | ||||
| 					C_bra(l_end); | ||||
|  | @ -638,30 +552,30 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 					C_loc((arith)1); | ||||
| 					C_df_ilb(l_end); | ||||
| 				} | ||||
| 				else	{ | ||||
| 					EVAL(rightop, RVAL, FALSE, l_true, | ||||
| 				else { | ||||
| 					EVAL(right, RVAL, FALSE, l_true, | ||||
| 						l_true); | ||||
| 					C_df_ilb(l_true); | ||||
| 				} | ||||
| 			} | ||||
| 			else	{ | ||||
| 			else { | ||||
| 				label l_maybe = text_label(); | ||||
| 
 | ||||
| 				EVAL(leftop, RVAL, TRUE, true_label, l_maybe); | ||||
| 				EVAL(left, RVAL, TRUE, true_label, l_maybe); | ||||
| 				C_df_ilb(l_maybe); | ||||
| 				EVAL(rightop, RVAL, code, true_label, | ||||
| 				EVAL(right, RVAL, code, true_label, | ||||
| 					false_label); | ||||
| 			} | ||||
| 			break; | ||||
| 		case '!': | ||||
| 			if (true_label == 0)	{ | ||||
| 				if (gencode)	{ | ||||
| 			if (true_label == 0) { | ||||
| 				if (gencode) { | ||||
| 					label l_true = text_label(); | ||||
| 					label l_false = text_label(); | ||||
| 					label l_end = text_label(); | ||||
| 
 | ||||
| 					EVAL(rightop, RVAL, TRUE, | ||||
| 							l_false, l_true); | ||||
| 					EVAL(right, RVAL, TRUE, l_false, | ||||
| 						l_true); | ||||
| 					C_df_ilb(l_false); | ||||
| 					C_loc((arith)0); | ||||
| 					C_bra(l_end); | ||||
|  | @ -670,11 +584,11 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 					C_df_ilb(l_end); | ||||
| 				} | ||||
| 				else | ||||
| 					EVAL(rightop, RVAL, FALSE, | ||||
| 							NO_LABEL, NO_LABEL); | ||||
| 					EVAL(right, RVAL, FALSE, NO_LABEL, | ||||
| 						NO_LABEL); | ||||
| 			} | ||||
| 			else | ||||
| 				EVAL(rightop, RVAL, code, false_label, | ||||
| 				EVAL(right, RVAL, code, false_label, | ||||
| 								true_label); | ||||
| 			break; | ||||
| 		case INT2INT: | ||||
|  | @ -683,14 +597,13 @@ EVAL(expr, val, code, true_label, false_label) | |||
| 		case FLOAT2INT: | ||||
| 		case FLOAT2FLOAT: | ||||
| #endif NOFLOAT | ||||
| 			EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			EVAL(right, RVAL, code, NO_LABEL, NO_LABEL); | ||||
| 			if (gencode) | ||||
| 				conversion(rightop->ex_type, leftop->ex_type); | ||||
| 				conversion(right->ex_type, left->ex_type); | ||||
| 			break; | ||||
| 		default: | ||||
| 			crash("(EVAL) bad operator %s\n", symbol2str(oper)); | ||||
| 		} | ||||
| 
 | ||||
| 		/*	If the rvalue of the expression is required but
 | ||||
| 			only its lvalue is evaluated, its rvalue is | ||||
| 			loaded by the following statements: | ||||
|  | @ -710,7 +623,7 @@ compare(relop, lbl) | |||
| 	int relop; | ||||
| 	label lbl; | ||||
| { | ||||
| 	switch (relop)	{ | ||||
| 	switch (relop) { | ||||
| 	case '<': | ||||
| 		C_zlt(lbl); | ||||
| 		break; | ||||
|  | @ -744,13 +657,13 @@ assop(type, oper) | |||
| 
 | ||||
| 	if ((size = type->tp_size) < word_size) | ||||
| 		size = word_size; | ||||
| 	switch (type->tp_fund)	{ | ||||
| 	switch (type->tp_fund) { | ||||
| 	case CHAR: | ||||
| 	case SHORT: | ||||
| 	case INT: | ||||
| 	case LONG: | ||||
| 	case ENUM: | ||||
| 		switch (oper)	{ | ||||
| 		switch (oper) { | ||||
| 		case PLUSAB: | ||||
| 		case PLUSPLUS: | ||||
| 		case POSTINCR: | ||||
|  | @ -811,7 +724,7 @@ assop(type, oper) | |||
| #ifndef NOFLOAT | ||||
| 	case FLOAT: | ||||
| 	case DOUBLE: | ||||
| 		switch (oper)	{ | ||||
| 		switch (oper) { | ||||
| 		case PLUSAB: | ||||
| 		case PLUSPLUS: | ||||
| 		case POSTINCR: | ||||
|  | @ -888,21 +801,19 @@ store_val(vl, tp) | |||
| 	register int indword; | ||||
| 	arith val = vl->vl_value; | ||||
| 
 | ||||
| 	if (vl->vl_class == Const)	{	/* absolute addressing */ | ||||
| 	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)	{ | ||||
| 	if (vl->vl_class == Name) { | ||||
| 		register struct idf *id = vl->vl_data.vl_idf; | ||||
| 		register struct def *df = id->id_def; | ||||
| 
 | ||||
| 		if (df->df_level == L_GLOBAL)	{ | ||||
| 		if (df->df_level == L_GLOBAL) { | ||||
| 			if (inword) | ||||
| 				C_ste_dnam(id->id_text, val); | ||||
| 			else | ||||
|  | @ -920,7 +831,7 @@ store_val(vl, tp) | |||
| 			else | ||||
| 			if (indword) | ||||
| 				C_sdl(df->df_address + val); | ||||
| 			else	{ | ||||
| 			else { | ||||
| 				C_lal(df->df_address + val); | ||||
| 				store_block(size, tpalign); | ||||
| 				df->df_register = REG_NONE; | ||||
|  | @ -965,8 +876,8 @@ load_val(expr, val) | |||
| 	register int inword, indword; | ||||
| 	arith val = expr->VL_VALUE; | ||||
| 
 | ||||
| 	if (expr->VL_CLASS == Const)	{ | ||||
| 		if (rvalue)	{ /* absolute addressing */ | ||||
| 	if (expr->VL_CLASS == Const) { | ||||
| 		if (rvalue) { /* absolute addressing */ | ||||
| 			load_cst(val, pointer_size); | ||||
| 			load_block(size, tpalign); | ||||
| 		} | ||||
|  | @ -980,7 +891,7 @@ load_val(expr, val) | |||
| 			indword = (size == dword_size && al_on_word); | ||||
| 	} | ||||
| 	if (expr->VL_CLASS == Label) { | ||||
| 		if (rvalue)	{ | ||||
| 		if (rvalue) { | ||||
| 			if (inword) | ||||
| 				C_loe_dlb(expr->VL_LBL, val); | ||||
| 			else | ||||
|  | @ -992,7 +903,7 @@ load_val(expr, val) | |||
| 			} | ||||
| 
 | ||||
| 		} | ||||
| 		else	{ | ||||
| 		else { | ||||
| 			C_lae_dlb(expr->VL_LBL, (arith)0); | ||||
| 			C_adp(val); | ||||
| 		} | ||||
|  | @ -1010,8 +921,8 @@ load_val(expr, val) | |||
| 			*/ | ||||
| 			C_lpi(id->id_text); | ||||
| 		else | ||||
| 		if (df->df_level == L_GLOBAL)	{ | ||||
| 			if (rvalue)	{ | ||||
| 		if (df->df_level == L_GLOBAL) { | ||||
| 			if (rvalue) { | ||||
| 				if (inword) | ||||
| 					C_loe_dnam(id->id_text, val); | ||||
| 				else | ||||
|  | @ -1022,14 +933,14 @@ load_val(expr, val) | |||
| 					load_block(size, tpalign); | ||||
| 				} | ||||
| 			} | ||||
| 			else	{ | ||||
| 			else { | ||||
| 				C_lae_dnam(id->id_text, (arith)0); | ||||
| 				C_adp(val); | ||||
| 			} | ||||
| 		} | ||||
| 		else	{ | ||||
| 		else { | ||||
| 			ASSERT(df->df_sc != STATIC); | ||||
| 			if (rvalue)	{ | ||||
| 			if (rvalue) { | ||||
| 				if (inword) | ||||
| 					C_lol(df->df_address + val); | ||||
| 				else | ||||
|  | @ -1041,7 +952,7 @@ load_val(expr, val) | |||
| 					df->df_register = REG_NONE; | ||||
| 				} | ||||
| 			} | ||||
| 			else	{ | ||||
| 			else { | ||||
| 				C_lal(df->df_address); | ||||
| 				C_adp(val); | ||||
| 				df->df_register = REG_NONE; | ||||
|  |  | |||
|  | @ -92,14 +92,14 @@ rank_of(oper) | |||
| } | ||||
| 
 | ||||
| int | ||||
| rank_of_expression(expr) | ||||
| 	register struct expr *expr; | ||||
| rank_of_expression(ex) | ||||
| 	register struct expr *ex; | ||||
| { | ||||
| 	/*	Returns the rank of the top node in the expression.
 | ||||
| 	*/ | ||||
| 	if (!expr || (expr->ex_flags & EX_PARENS) || expr->ex_class != Oper) | ||||
| 	if (!ex || (ex->ex_flags & EX_PARENS) || ex->ex_class != Oper) | ||||
| 		return 0; | ||||
| 	return rank_of(expr->OP_OPER); | ||||
| 	return rank_of(ex->OP_OPER); | ||||
| } | ||||
| 
 | ||||
| check_conditional(expr, oper, pos_descr) | ||||
|  | @ -158,15 +158,12 @@ idf2expr(expr) | |||
| 	register struct def *def = idf->id_def; | ||||
| 	 | ||||
| 	if (def == 0)	{ | ||||
| 		if (AHEAD == '(')	{ | ||||
| 			/* Function call, so declare the name IMPLICITly. */ | ||||
| 			/* See RM 13. */ | ||||
| 			add_def(idf, IMPLICIT, funint_type, level); | ||||
| 		} | ||||
| 		if (AHEAD == '(') /* function call, declare name IMPLICITly */ | ||||
| 			add_def(idf, IMPLICIT, funint_type, level); /* RM 13 */ | ||||
| 		else	{ | ||||
| 			if (!is_anon_idf(idf)) | ||||
| 				error("%s undefined", idf->id_text); | ||||
| 			/* Declare the idf anyway */ | ||||
| 			/* declare idf anyway */ | ||||
| 			add_def(idf, 0, error_type, level); | ||||
| 		} | ||||
| 		def = idf->id_def; | ||||
|  | @ -254,25 +251,24 @@ intexpr(ivalue, fund) | |||
| 	clear((char *)expr, sizeof(struct expr)); | ||||
| 	expr->ex_file = dot.tk_file; | ||||
| 	expr->ex_line = dot.tk_line; | ||||
| 	 | ||||
| 	fill_int_expr(expr, ivalue, fund); | ||||
| 	return expr; | ||||
| } | ||||
| 
 | ||||
| fill_int_expr(expr, ivalue, fund) | ||||
| 	register struct expr *expr; | ||||
| fill_int_expr(ex, ivalue, fund) | ||||
| 	register struct expr *ex; | ||||
| 	arith ivalue; | ||||
| 	int fund; | ||||
| { | ||||
| 	/*	Details derived from ivalue and fund are put into the
 | ||||
| 		constant integer expression expr. | ||||
| 		constant integer expression ex. | ||||
| 	*/ | ||||
| 	switch (fund) { | ||||
| 	case INT: | ||||
| 		expr->ex_type = int_type; | ||||
| 		ex->ex_type = int_type; | ||||
| 		break; | ||||
| 	case LONG: | ||||
| 		expr->ex_type = long_type; | ||||
| 		ex->ex_type = long_type; | ||||
| 		break; | ||||
| 	case UNSIGNED: | ||||
| 		/*	We cannot make a test like
 | ||||
|  | @ -284,20 +280,18 @@ fill_int_expr(expr, ivalue, fund) | |||
| 			answer.  We assume that the type "unsigned long" | ||||
| 			is not part of portable C ! | ||||
| 		*/ | ||||
| 		expr->ex_type =  | ||||
| 			(ivalue & ~max_unsigned) ? long_type : uint_type; | ||||
| 		ex->ex_type = (ivalue & ~max_unsigned) ? long_type : uint_type; | ||||
| 		break; | ||||
| 	case INTEGER: | ||||
| 		expr->ex_type = (ivalue <= max_int) ? int_type : long_type; | ||||
| 		ex->ex_type = (ivalue <= max_int) ? int_type : long_type; | ||||
| 		break; | ||||
| 	default: | ||||
| 		crash("(intexpr) bad fund %s\n", symbol2str(fund)); | ||||
| 	} | ||||
| 	expr->ex_class = Value; | ||||
| 	expr->VL_CLASS = Const; | ||||
| 	expr->VL_VALUE = ivalue; | ||||
| 	 | ||||
| 	cut_size(expr); | ||||
| 	ex->ex_class = Value; | ||||
| 	ex->VL_CLASS = Const; | ||||
| 	ex->VL_VALUE = ivalue; | ||||
| 	cut_size(ex); | ||||
| } | ||||
| 
 | ||||
| struct expr * | ||||
|  | @ -344,8 +338,7 @@ new_oper(tp, e1, oper, e2) | |||
| 		int e1_flags = e1 ? e1->ex_flags : 0; | ||||
| 		 | ||||
| 		expr->ex_depth = | ||||
| 			(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) | ||||
| 				+ 1; | ||||
| 			(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1; | ||||
| 		expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS; | ||||
| 	} | ||||
| 	op = &expr->ex_object.ex_oper; | ||||
|  | @ -353,7 +346,6 @@ new_oper(tp, e1, oper, e2) | |||
| 	op->op_oper = oper; | ||||
| 	op->op_left = e1; | ||||
| 	op->op_right = e2; | ||||
| 
 | ||||
| 	return expr; | ||||
| } | ||||
| 
 | ||||
|  | @ -397,17 +389,14 @@ chk_cst_expr(expp) | |||
| #endif	DEBUG | ||||
| 	if (	fund != CHAR && fund != SHORT && fund != INT && | ||||
| 		fund != ENUM && fund != LONG | ||||
| 	)	{ | ||||
| 	) | ||||
| 		expr_error(expr, "non-numerical constant expression"), err++; | ||||
| 	} | ||||
| 	else | ||||
| 	if (!is_ld_cst(expr)) | ||||
| 		expr_error(expr, "expression is not constant"), err++; | ||||
| 	 | ||||
| 	if (options['R'])	{ | ||||
| 		if (flags & EX_CAST) | ||||
| 			expr_warning(expr, | ||||
| 				"cast in constant expression"); | ||||
| 			expr_warning(expr, "cast in constant expression"); | ||||
| 		if (flags & EX_LOGICAL) | ||||
| 			expr_warning(expr, | ||||
| 				"logical operator in constant expression"); | ||||
|  | @ -475,11 +464,11 @@ free_expression(expr) | |||
| { | ||||
| 	/*	The expression expr is freed recursively.
 | ||||
| 	*/ | ||||
| 	if (!expr) | ||||
| 		return; | ||||
| 	if (expr->ex_class == Oper)	{ | ||||
| 		free_expression(expr->OP_LEFT); | ||||
| 		free_expression(expr->OP_RIGHT); | ||||
| 	if (expr) { | ||||
| 		if (expr->ex_class == Oper)	{ | ||||
| 			free_expression(expr->OP_LEFT); | ||||
| 			free_expression(expr->OP_RIGHT); | ||||
| 		} | ||||
| 		free_expr(expr); | ||||
| 	} | ||||
| 	free_expr(expr); | ||||
| } | ||||
|  |  | |||
|  | @ -5,9 +5,7 @@ | |||
| 
 | ||||
| #ifndef NOBITFIELD | ||||
| #include	<em.h> | ||||
| 
 | ||||
| #include	"debug.h" | ||||
| 
 | ||||
| #include	"arith.h" | ||||
| #include	"type.h" | ||||
| #include	"idf.h" | ||||
|  | @ -27,39 +25,33 @@ char *symbol2str();		/* symbol2str.c	*/ | |||
| 	tree and are therefore dealt with in this function. | ||||
| 	The actions taken at any operation are described clearly by the | ||||
| 	code for this actions. | ||||
| 	Note: the bitfields are packed in target machine integers! | ||||
| 	Notes | ||||
| 	[1]	the bitfields are packed in target machine integers! | ||||
| 	[2]	op is either an assignment operator or an increment/ | ||||
| 		decrement operator | ||||
| 	[3]	atype: the type in which the bitfield arithmetic is done; | ||||
| 		and in which bitfields are stored! | ||||
| */ | ||||
| eval_field(expr, code) | ||||
| 	struct expr *expr; | ||||
| 	int code; | ||||
| { | ||||
| 	int op = expr->OP_OPER; | ||||
| 	struct expr *leftop = expr->OP_LEFT; | ||||
| 	struct expr *rightop = expr->OP_RIGHT; | ||||
| 	struct field *fd = leftop->ex_type->tp_field; | ||||
| 	register struct expr *leftop = expr->OP_LEFT; | ||||
| 	register struct expr *rightop = expr->OP_RIGHT; | ||||
| 	register struct field *fd = leftop->ex_type->tp_field; | ||||
| 	struct type *tp = leftop->ex_type->tp_up; | ||||
| 	arith old_offset, tmpvar; | ||||
| 
 | ||||
| 	/*	The type in which the bitfield arithmetic is done;
 | ||||
| 		AND IN WHICH BITFIELDS ARE STORED! | ||||
| 	*/ | ||||
| 	struct type *atype = tp->tp_unsigned ? uword_type : word_type; | ||||
| 	arith asize = atype->tp_size; | ||||
| 
 | ||||
| 	/* First some assertions to be sure that the rest is legal */ | ||||
| 	ASSERT(asize == word_size);	/* make sure that C_loc() is legal */ | ||||
| 	ASSERT(leftop->ex_type->tp_fund == FIELD); | ||||
| 
 | ||||
| 	leftop->ex_type = atype;	/* this is cheating but it works... */ | ||||
| 
 | ||||
| 	/*	Note that op is either an assignment operator or an increment/
 | ||||
| 		decrement operator | ||||
| 	*/ | ||||
| 	if (op == '=') { | ||||
| 		/*	F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f)
 | ||||
| 		*/ | ||||
| 		/* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */ | ||||
| 		ASSERT(tp == rightop->ex_type); | ||||
| 
 | ||||
| 		EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 		conversion(tp, atype); | ||||
| 		C_loc(fd->fd_mask); | ||||
|  | @ -116,10 +108,9 @@ eval_field(expr, code) | |||
| 		C_and(asize); | ||||
| 		if (code == TRUE && (op == POSTINCR || op == POSTDECR)) | ||||
| 			C_dup(asize); | ||||
| 
 | ||||
| 		/* the 'op' operation: */ | ||||
| 		conversion(atype, rightop->ex_type); | ||||
| 		EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 		/* the 'op' operation: */ | ||||
| 		if (op == PLUSPLUS || op == POSTINCR) | ||||
| 			assop(rightop->ex_type, PLUSAB); | ||||
| 		else | ||||
|  | @ -128,7 +119,6 @@ eval_field(expr, code) | |||
| 		else | ||||
| 			assop(rightop->ex_type, op); | ||||
| 		conversion(rightop->ex_type, atype); | ||||
| 
 | ||||
| 		C_loc(fd->fd_mask); | ||||
| 		C_and(asize); | ||||
| 		if (code == TRUE && op != POSTINCR && op != POSTDECR) | ||||
|  |  | |||
|  | @ -201,7 +201,6 @@ declare_idf(ds, dc, lvl) | |||
| 	/* some additional work for formal definitions */ | ||||
| 	if (lvl == L_FORMAL2)	{ | ||||
| 		switch (type->tp_fund)	{ | ||||
| 	 | ||||
| 		case FUNCTION: | ||||
| 			warning("%s is a function; cannot be formal", | ||||
| 				idf->id_text); | ||||
|  | @ -227,7 +226,6 @@ declare_idf(ds, dc, lvl) | |||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/*	The tests on types, postponed from do_decspecs(), can now
 | ||||
| 		be performed. | ||||
| 	*/ | ||||
|  | @ -241,23 +239,15 @@ declare_idf(ds, dc, lvl) | |||
| 			ds->ds_sc = sc = GLOBAL; | ||||
| 		} | ||||
| 	} | ||||
| 	else	{				/* non-FUNCTION */ | ||||
| 	else	/* non-FUNCTION */ | ||||
| 		if (sc == 0) | ||||
| 			sc = | ||||
| 				lvl == L_GLOBAL ? | ||||
| 					GLOBAL : | ||||
| 				lvl == L_FORMAL1 || lvl == L_FORMAL2 ? | ||||
| 					FORMAL : | ||||
| 					AUTO; | ||||
| 	} | ||||
| 	 | ||||
| 	if (options['R'])	{ | ||||
| 		/* some special K & R tests */ | ||||
| 		 | ||||
| 			sc =	lvl == L_GLOBAL ? GLOBAL | ||||
| 				: lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL | ||||
| 				: AUTO; | ||||
| 	if (options['R']) { /* some special K & R tests */ | ||||
| 		/* is it also an enum? */ | ||||
| 		if (idf->id_enum && idf->id_enum->tg_level == level) | ||||
| 			warning("%s is also an enum tag", idf->id_text); | ||||
| 		 | ||||
| 		/* is it a universal typedef? */ | ||||
| 		if (def && def->df_level == L_UNIVERSAL) | ||||
| 			warning("redeclaring reserved word %s", idf->id_text); | ||||
|  | @ -299,15 +289,13 @@ declare_idf(ds, dc, lvl) | |||
| 		*/ | ||||
| 		if (	options['R'] && | ||||
| 			(sc == STATIC && type->tp_fund == FUNCTION) | ||||
| 		)	{ | ||||
| 		) | ||||
| 			if (!is_anon_idf(idf)) | ||||
| 				warning("non-global static function %s", | ||||
| 					idf->id_text); | ||||
| 		} | ||||
| 		declare_idf(ds, dc, L_GLOBAL); | ||||
| 	} | ||||
| 	else	{ | ||||
| 		/* fill in the def block */ | ||||
| 	else	{ /* fill in the def block */ | ||||
| 		register struct def *newdef = new_def(); | ||||
| 
 | ||||
| 		clear((char *)newdef, sizeof(struct def)); | ||||
|  | @ -315,24 +303,19 @@ declare_idf(ds, dc, lvl) | |||
| 		newdef->df_level = lvl; | ||||
| 		newdef->df_type = type; | ||||
| 		newdef->df_sc = sc; | ||||
| 
 | ||||
| 		/* link it into the name list in the proper place */ | ||||
| 		idf->id_def = newdef; | ||||
| 		update_ahead(idf); | ||||
| 		stack_idf(idf, stl); | ||||
| 		 | ||||
| 		/*	We now calculate the address.
 | ||||
| 			Globals have names and don't get addresses, they | ||||
| 			get numbers instead (through data_label()). | ||||
| 			Formals are handled by declare_formals(). | ||||
| 			So here we hand out local addresses only. | ||||
| 		*/ | ||||
| 
 | ||||
| 		if (lvl >= L_LOCAL)	{ | ||||
| 			ASSERT(sc); | ||||
| 			switch (sc)	{ | ||||
| 			case 0: | ||||
| 				crash("local sc == 0"); | ||||
| 				break; | ||||
| 			case REGISTER: | ||||
| 			case AUTO: | ||||
| 				if (type->tp_size == (arith)-1) { | ||||
|  | @ -341,8 +324,8 @@ declare_idf(ds, dc, lvl) | |||
| 				/** type = idf->id_def->df_type = int_type; **/ | ||||
| 				} | ||||
| 				idf->id_def->df_register = | ||||
| 					(sc == REGISTER) | ||||
| 						? REG_BONUS : REG_DEFAULT; | ||||
| 					(sc == REGISTER) ? REG_BONUS | ||||
| 					: REG_DEFAULT; | ||||
| 				idf->id_def->df_address = | ||||
| 				stl->sl_max_block = | ||||
| 				stl->sl_local_offset = | ||||
|  | @ -358,17 +341,17 @@ declare_idf(ds, dc, lvl) | |||
| } | ||||
| 
 | ||||
| actual_declaration(sc, tp) | ||||
| 	int sc; | ||||
| 	struct type *tp; | ||||
| { | ||||
| 	/*	An actual_declaration needs space, right here and now.
 | ||||
| 	*/ | ||||
| 	register int fund = tp->tp_fund; | ||||
| 	 | ||||
| 	/* virtual declarations */ | ||||
| 	if (sc == ENUM || sc == TYPEDEF) | ||||
| 	if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */ | ||||
| 		return 0; | ||||
| 	/* allocation solved in other ways */ | ||||
| 	if (fund == FUNCTION || fund == ARRAY) | ||||
| 		/* allocation solved in other ways */ | ||||
| 		return 0; | ||||
| 	/* to be allocated */ | ||||
| 	return 1; | ||||
|  | @ -388,7 +371,6 @@ global_redecl(idf, new_sc, tp) | |||
| 
 | ||||
| 	if (tp != def->df_type)	{ | ||||
| 		register struct type *otp = def->df_type; | ||||
| 
 | ||||
| 		if (	tp->tp_fund != ARRAY || otp->tp_fund != ARRAY || | ||||
| 			tp->tp_up != otp->tp_up | ||||
| 		)	{ | ||||
|  | @ -409,9 +391,8 @@ global_redecl(idf, new_sc, tp) | |||
| 			error("inconsistent size in redeclaration of array %s", | ||||
| 				idf->id_text); | ||||
| 	} | ||||
| 
 | ||||
| 	/*	Now we may be able to update the storage class.	*/ | ||||
| 	/*	Clean out this mess as soon as we know all the possibilities
 | ||||
| 	/*	Now we may be able to update the storage class.
 | ||||
| 		Clean out this mess as soon as we know all the possibilities | ||||
| 		for new_sc. | ||||
| 		For now we have: | ||||
| 			EXTERN:		we have seen the word "extern" | ||||
|  | @ -424,7 +405,6 @@ global_redecl(idf, new_sc, tp) | |||
| 	*/ | ||||
| 	if (new_sc == IMPLICIT) | ||||
| 		return;			/* no new information */ | ||||
| 	 | ||||
| 	switch (def->df_sc)	{	/* the old storage class */ | ||||
| 	case EXTERN: | ||||
| 		switch (new_sc)	{	/* the new storage class */ | ||||
|  | @ -456,10 +436,9 @@ global_redecl(idf, new_sc, tp) | |||
| 		case GLOBAL: | ||||
| 			break; | ||||
| 		case STATIC: | ||||
| 			if (def->df_initialized)	{ | ||||
| 			if (def->df_initialized) | ||||
| 				error("cannot redeclare %s to static", | ||||
| 					idf->id_text); | ||||
| 			} | ||||
| 			else	{ | ||||
| 				if (options['R']) | ||||
| 					warning("%s redeclared to static", | ||||
|  | @ -475,10 +454,9 @@ global_redecl(idf, new_sc, tp) | |||
| 	case STATIC: | ||||
| 		switch (new_sc)	{	/* the new storage class */ | ||||
| 		case EXTERN: | ||||
| 			if (def->df_initialized)	{ | ||||
| 			if (def->df_initialized) | ||||
| 				error("cannot redeclare %s to extern", | ||||
| 					idf->id_text); | ||||
| 			} | ||||
| 			else	{ | ||||
| 				warning("%s redeclared to extern", | ||||
| 					idf->id_text); | ||||
|  | @ -531,11 +509,9 @@ good_formal(def, idf) | |||
| 	/*	Succeeds if def is a proper L_FORMAL1 definition and
 | ||||
| 		gives an error message otherwise. | ||||
| 	*/ | ||||
| 	if (!def || def->df_level != L_FORMAL1)	{ | ||||
| 		/* not in parameter list */ | ||||
| 	if (!def || def->df_level != L_FORMAL1)	{ /* not in parameter list */ | ||||
| 		if (!is_anon_idf(idf)) | ||||
| 			error("%s not in parameter list", | ||||
| 				idf->id_text); | ||||
| 			error("%s not in parameter list", idf->id_text); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
|  | @ -610,17 +586,12 @@ declare_formals(fp) | |||
| 		register struct def *def = se->se_idf->id_def; | ||||
| 		 | ||||
| 		def->df_address = f_offset; | ||||
| 
 | ||||
| 		/*	the alignment convention for parameters is: align on
 | ||||
| 			word boundaries, i.e. take care that the following | ||||
| 			parameter starts on a new word boundary. | ||||
| 		*/ | ||||
| 		f_offset = align(f_offset + def->df_type->tp_size, word_align); | ||||
| 
 | ||||
| 		/*	the following is absurd: any char or short formal
 | ||||
| 			must be converted from integer to that type | ||||
| 		*/ | ||||
| 		formal_cvt(def); | ||||
| 		formal_cvt(def); /* cvt int to char or short, if necessary */ | ||||
| 		se = se->next; | ||||
| 	} | ||||
| 	*fp = f_offset; | ||||
|  |  | |||
|  | @ -24,7 +24,6 @@ | |||
| 
 | ||||
| char *symbol2str(); | ||||
| char *long2str(); | ||||
| 
 | ||||
| struct expr *do_array(), *do_struct(), *IVAL(); | ||||
| 
 | ||||
| /*	do_ival() performs the initialisation of a global variable
 | ||||
|  | @ -58,26 +57,23 @@ IVAL(tpp, ex) | |||
| 	register struct type *tp = *tpp; | ||||
| 	 | ||||
| 	switch (tp->tp_fund) { | ||||
| 	case ARRAY: | ||||
| 		/* array initialisation	*/ | ||||
| 	case ARRAY: /* array initialisation	*/ | ||||
| 		if (valid_type(tp->tp_up, "array element") == 0) | ||||
| 			return 0; | ||||
| 		if (ISCOMMA(ex)) /* list of initialisation expressions */ | ||||
| 			return do_array(ex, tpp); | ||||
| 		/* catch initialisations like char s[] = "I am a string" */ | ||||
| 		if (tp->tp_up->tp_fund == CHAR && ex->ex_class == String) | ||||
| 			/* initialisation like char s[] = "I am a string" */ | ||||
| 			ch_array(tpp, ex); | ||||
| 		else /* " int i[24] = 12;"	*/ | ||||
| 			check_and_pad(ex, tpp); | ||||
| 		break; | ||||
| 	case STRUCT: | ||||
| 		/* struct initialisation */ | ||||
| 	case STRUCT: /* struct initialisation */ | ||||
| 		if (valid_type(tp, "struct") == 0) | ||||
| 			return 0; | ||||
| 		if (ISCOMMA(ex)) /* list of initialisation expressions */ | ||||
| 			return do_struct(ex, tp); | ||||
| 		/* "struct foo f = 12;"	*/ | ||||
| 		check_and_pad(ex, tpp); | ||||
| 		check_and_pad(ex, tpp); /* "struct foo f = 12;"	*/ | ||||
| 		break; | ||||
| 	case UNION: | ||||
| 		error("union initialisation not allowed"); | ||||
|  | @ -85,7 +81,7 @@ IVAL(tpp, ex) | |||
| 	case ERRONEOUS: | ||||
| 		break; | ||||
| 	default: /* fundamental type	*/ | ||||
| 		if (ISCOMMA(ex))	{ /* " int i = {12};"	*/ | ||||
| 		if (ISCOMMA(ex)) { /* " int i = {12};"	*/ | ||||
| 			if (IVAL(tpp, ex->OP_LEFT) != 0) | ||||
| 				too_many_initialisers(ex); | ||||
| 			/*	return remainings of the list for the
 | ||||
|  | @ -94,8 +90,7 @@ IVAL(tpp, ex) | |||
| 			*/ | ||||
| 			return ex->OP_RIGHT; | ||||
| 		} | ||||
| 		/* "int i = 12;"	*/ | ||||
| 		check_ival(ex, tp); | ||||
| 		check_ival(ex, tp); /* "int i = 12;" */ | ||||
| 		break; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | @ -131,8 +126,7 @@ do_array(ex, tpp) | |||
| 		is completely foolish, we did it!! (no applause, thank you) | ||||
| 	*/ | ||||
| 	if (tp->tp_up->tp_fund == CHAR) { | ||||
| 		register struct expr *f = ex->OP_LEFT; | ||||
| 		register struct expr *g = 0; | ||||
| 		register struct expr *f = ex->OP_LEFT, *g = NILEXPR; | ||||
| 
 | ||||
| 		while (ISCOMMA(f)) {	/* eat the brackets!!!	*/ | ||||
| 			g = f; | ||||
|  | @ -150,8 +144,7 @@ do_array(ex, tpp) | |||
| 		/* declared with unknown size: [] */ | ||||
| 		for (elem_count = 0; ex; elem_count++) { | ||||
| 			/* eat whole initialisation expression	*/ | ||||
| 			if (ISCOMMA(ex->OP_LEFT)) { | ||||
| 				/* the member expression is embraced	*/ | ||||
| 			if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */ | ||||
| 				if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0) | ||||
| 					too_many_initialisers(ex); | ||||
| 				ex = ex->OP_RIGHT; | ||||
|  | @ -172,15 +165,13 @@ do_array(ex, tpp) | |||
| 		arith dim = tp->tp_size / tp->tp_up->tp_size; | ||||
| 
 | ||||
| 		for (elem_count = 0; elem_count < dim && ex; elem_count++) { | ||||
| 			if (ISCOMMA(ex->OP_LEFT)) { | ||||
| 				/* embraced member initialisation	*/ | ||||
| 			if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */ | ||||
| 				if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0) | ||||
| 					too_many_initialisers(ex); | ||||
| 				ex = ex->OP_RIGHT; | ||||
| 			} | ||||
| 			else { | ||||
| 				if (aggregate_type(tp->tp_up)) | ||||
| 					/* the member is an aggregate	*/ | ||||
| 					ex = IVAL(&(tp->tp_up), ex); | ||||
| 				else { | ||||
| 					check_ival(ex->OP_LEFT, tp->tp_up); | ||||
|  | @ -194,7 +185,7 @@ do_array(ex, tpp) | |||
| 				is returned | ||||
| 			*/ | ||||
| 			return ex; | ||||
| 		if ((ex == 0) && elem_count < dim) { | ||||
| 		if ((ex == 0) && elem_count < dim) | ||||
| 			/*	the expression tree is completely absorbed
 | ||||
| 				but there are still members which must be | ||||
| 				initialised with zeroes | ||||
|  | @ -202,7 +193,6 @@ do_array(ex, tpp) | |||
| 			do | ||||
| 				pad(tp->tp_up); | ||||
| 			while (++elem_count < dim); | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -245,16 +235,14 @@ do_struct(ex, tp) | |||
| 						definition. | ||||
| 					*/ | ||||
| 					put_bf(sd->sd_type, (arith)0); | ||||
| 				else { | ||||
| 					/* fundamental type, not embraced */ | ||||
| 				else { /* fundamental type, not embraced */ | ||||
| 					check_ival(ex->OP_LEFT, sd->sd_type); | ||||
| 					ex = ex->OP_RIGHT; | ||||
| 				} | ||||
| #endif NOBITFIELD | ||||
| 			} | ||||
| 		} | ||||
| 		/* align upto the next selector	boundary	*/ | ||||
| 		if (sd->sd_sdef) | ||||
| 		if (sd->sd_sdef) /* align upto the next selector boundary */ | ||||
| 			bytes_upto_here += zero_bytes(sd); | ||||
| 		if (last_offset != sd->sd_offset) { | ||||
| 			/* don't take the field-width more than once	*/ | ||||
|  | @ -266,9 +254,7 @@ do_struct(ex, tp) | |||
| 	} | ||||
| 	/* perfect fit if (ex && (sd == 0)) holds	*/ | ||||
| 	if ((ex == 0) && (sd != 0)) { | ||||
| 		/*	there are selectors left which must be padded with
 | ||||
| 			zeroes | ||||
| 		*/ | ||||
| 		/* there are selectors left which must be padded with zeroes */ | ||||
| 		do { | ||||
| 			pad(sd->sd_type); | ||||
| 			/* take care of the alignment restrictions	*/ | ||||
|  | @ -307,7 +293,7 @@ check_and_pad(ex, tpp) | |||
| 			*/ | ||||
| 			tp = *tpp = construct_type(ARRAY, tp->tp_up, (arith)1); | ||||
| 		else { | ||||
| 			register dim = tp->tp_size / tp->tp_up->tp_size; | ||||
| 			register int dim = tp->tp_size / tp->tp_up->tp_size; | ||||
| 			/* pad remaining members with zeroes */ | ||||
| 			while (--dim > 0) | ||||
| 				pad(tp->tp_up); | ||||
|  | @ -320,7 +306,7 @@ check_and_pad(ex, tpp) | |||
| 		if (valid_type(tp, "struct") == 0) | ||||
| 			return; | ||||
| 		check_and_pad(ex, &(sd->sd_type)); | ||||
| 		/* Next selector is aligned by adding extra zeroes */ | ||||
| 		/* next selector is aligned by adding extra zeroes */ | ||||
| 		if (sd->sd_sdef) | ||||
| 			zero_bytes(sd); | ||||
| 		while (sd = sd->sd_sdef) { /* pad remaining selectors	*/ | ||||
|  | @ -346,10 +332,8 @@ pad(tp) | |||
| 
 | ||||
| 		if (valid_type(tp->tp_up, "array element") == 0) | ||||
| 			return; | ||||
| 
 | ||||
| 		dim = tp->tp_size / tp->tp_up->tp_size; | ||||
| 
 | ||||
| 		/* Assume the dimension is known	*/ | ||||
| 		/* assume dimension is known	*/ | ||||
| 		while (dim-- > 0) | ||||
| 			pad(tp->tp_up); | ||||
| 		break; | ||||
|  | @ -360,7 +344,6 @@ pad(tp) | |||
| 
 | ||||
| 		if (valid_type(tp, "struct") == 0) | ||||
| 			return; | ||||
| 
 | ||||
| 		do { | ||||
| 			pad(sdef->sd_type); | ||||
| 			if (sdef->sd_sdef) | ||||
|  | @ -462,10 +445,8 @@ check_ival(ex, tp) | |||
| 			/* float f = 1; */ | ||||
| 			ex = ex->OP_RIGHT; | ||||
| 			if (is_cp_cst(ex)) | ||||
| 				C_con_fcon( | ||||
| 					long2str((long)ex->VL_VALUE, 10), | ||||
| 					tp->tp_size | ||||
| 				); | ||||
| 				C_con_fcon(long2str((long)ex->VL_VALUE, 10), | ||||
| 					tp->tp_size); | ||||
| 			else  | ||||
| 				illegal_init_cst(ex); | ||||
| 		} | ||||
|  | @ -509,7 +490,7 @@ ch_array(tpp, ex) | |||
| 
 | ||||
| 	ASSERT(ex->ex_class == String); | ||||
| 	length = ex->SG_LEN; | ||||
| 	if (tp->tp_size == (arith)-1)	{ | ||||
| 	if (tp->tp_size == (arith)-1) { | ||||
| 		/* set the dimension	*/ | ||||
| 		tp = *tpp = construct_type(ARRAY, tp->tp_up, length); | ||||
| 		ntopad = align(tp->tp_size, word_align) - tp->tp_size; | ||||
|  | @ -591,8 +572,7 @@ zero_bytes(sd) | |||
| 	/*	fills the space between a selector of a struct
 | ||||
| 		and the next selector of that struct with zero-bytes. | ||||
| 	*/ | ||||
| 	register int n = | ||||
| 		sd->sd_sdef->sd_offset - sd->sd_offset - | ||||
| 	register int n = sd->sd_sdef->sd_offset - sd->sd_offset - | ||||
| 		size_of_type(sd->sd_type, "struct member"); | ||||
| 	register count = n; | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,7 +7,6 @@ | |||
| #include	"debug.h"	/* UF */ | ||||
| #include	"pathlength.h"	/* UF */ | ||||
| #include	"strsize.h"	/* UF */ | ||||
| 
 | ||||
| #include	"alloc.h" | ||||
| #include	"idf.h" | ||||
| #include	"input.h" | ||||
|  | @ -52,13 +51,11 @@ replace(idef) | |||
| 		} | ||||
| 		actpars = getactuals(idef);	/* get act.param. list	*/ | ||||
| 	} | ||||
| 	if ((flags & PREDEF) && (UnknownIdIsZero == 0)) | ||||
| 		/* don't replace this one...	*/ | ||||
| 			return 0; | ||||
| 	if ((flags & PREDEF) && (UnknownIdIsZero == 0)) /* don't replace */ | ||||
| 		return 0; | ||||
| 	if (flags & FUNC)	/* this macro leads to special action	*/ | ||||
| 		macro_func(idef); | ||||
| 	/* create and input buffer	*/ | ||||
| 	reptext = macro2buffer(idef, actpars, &size); | ||||
| 	reptext = macro2buffer(idef, actpars, &size); /* create input buffer */ | ||||
| 	InsertText(reptext, size); | ||||
| 	return 1; | ||||
| } | ||||
|  | @ -74,8 +71,7 @@ macro_func(idef) | |||
| 		replacement texts must be evaluated at the time they are | ||||
| 		used. | ||||
| 	*/ | ||||
| 	/* This switch is very blunt...	*/ | ||||
| 	switch (idef->id_text[2]) { | ||||
| 	switch (idef->id_text[2]) { /* This switch is very blunt... */ | ||||
| 	case 'F' :			/* __FILE__	*/ | ||||
| 		FilNamBuf[0] = '"'; | ||||
| 		strcpy(&FilNamBuf[1], FileName); | ||||
|  | @ -126,8 +122,7 @@ macro2buffer(idef, actpars, siztext) | |||
| 			for (p = actpars[n - 1]; *p; p++) { | ||||
| 				text[pos++] = *p; | ||||
| 				if (pos == size) | ||||
| 					text = Srealloc(text, | ||||
| 							size += RSTRSIZE); | ||||
| 					text = Srealloc(text, size += RSTRSIZE); | ||||
| 			} | ||||
| 		} | ||||
| 		else { | ||||
|  |  | |||
|  | @ -27,7 +27,6 @@ static struct switch_hdr *switch_stack = 0; | |||
| 	- the expression E in "switch(E)" is cast to 'int' (RM 9.7) | ||||
| 	- the expression E in "case E:" must be 'int' (RM 9.7) | ||||
| 	- the values in the CSA/CSB tables are words (EM 7.4) | ||||
| 
 | ||||
| 	For simplicity, we suppose int_size == word_size. | ||||
| */ | ||||
| 
 | ||||
|  | @ -42,7 +41,7 @@ code_startswitch(expp) | |||
| 	register struct switch_hdr *sh = new_switch_hdr(); | ||||
| 	int fund = any2arith(expp, SWITCH);	/* INT, LONG or DOUBLE */ | ||||
| 	 | ||||
| 	switch (fund)	{ | ||||
| 	switch (fund) { | ||||
| 	case LONG: | ||||
| 		if (options['R']) | ||||
| 			warning("long in switch (cast to int)"); | ||||
|  | @ -55,7 +54,6 @@ code_startswitch(expp) | |||
| 		break; | ||||
| #endif NOFLOAT | ||||
| 	} | ||||
| 	 | ||||
| 	stack_stmt(l_break, NO_LABEL); | ||||
| 	sh->sh_break = l_break; | ||||
| 	sh->sh_default = 0; | ||||
|  | @ -66,8 +64,8 @@ code_startswitch(expp) | |||
| 	sh->sh_entries = (struct case_entry *) 0; /* case-entry list	*/ | ||||
| 	sh->next = switch_stack;	/* push onto switch-stack	*/ | ||||
| 	switch_stack = sh; | ||||
| 	/* evaluate the switch expr.	*/ | ||||
| 	code_expr(*expp, RVAL, TRUE, NO_LABEL, NO_LABEL); | ||||
| 					/* evaluate the switch expr.	*/ | ||||
| 	C_bra(l_table);			/* goto start of switch_table	*/ | ||||
| } | ||||
| 
 | ||||
|  | @ -93,7 +91,7 @@ code_endswitch() | |||
| 		ce = sh->sh_entries; | ||||
| 		for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) { | ||||
| 			ASSERT(ce); | ||||
| 			if (val == ce->ce_value)	{ | ||||
| 			if (val == ce->ce_value) { | ||||
| 				C_rom_ilb(ce->ce_label); | ||||
| 				ce = ce->next; | ||||
| 			} | ||||
|  | @ -103,9 +101,9 @@ code_endswitch() | |||
| 		C_lae_dlb(tablabel, (arith)0); /* perform the switch	*/ | ||||
| 		C_csa(sh->sh_type->tp_size); | ||||
| 	} | ||||
| 	else	{ /* CSB */ | ||||
| 	else { /* CSB */ | ||||
| 		C_rom_cst((arith)sh->sh_nrofentries); | ||||
| 		for (ce = sh->sh_entries; ce; ce = ce->next)	{ | ||||
| 		for (ce = sh->sh_entries; ce; ce = ce->next) { | ||||
| 			/* generate the entries: value + prog.label	*/ | ||||
| 			C_rom_cst(ce->ce_value); | ||||
| 			C_rom_ilb(ce->ce_label); | ||||
|  | @ -115,11 +113,9 @@ code_endswitch() | |||
| 	} | ||||
| 	C_df_ilb(sh->sh_break); | ||||
| 	switch_stack = sh->next;	/* unstack the switch descriptor */ | ||||
| 	 | ||||
| 	/* free the allocated switch structure	*/ | ||||
| 	ce = sh->sh_entries; | ||||
| 	while (ce)	{ | ||||
| 	for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */ | ||||
| 		register struct case_entry *tmp = ce->next; | ||||
| 
 | ||||
| 		free_case_entry(ce); | ||||
| 		ce = tmp; | ||||
| 	} | ||||
|  | @ -135,28 +131,23 @@ code_case(expr) | |||
| 	register struct switch_hdr *sh = switch_stack; | ||||
| 	 | ||||
| 	ASSERT(is_cp_cst(expr)); | ||||
| 	if (sh == 0)	{ | ||||
| 	if (sh == 0) { | ||||
| 		error("case statement not in switch"); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (expr->ex_flags & EX_ERROR)	{ | ||||
| 		/* is probably 0 anyway */ | ||||
| 	if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */ | ||||
| 		return; | ||||
| 	} | ||||
| 	ch7cast(&expr, SWITCH, sh->sh_type); | ||||
| 	ce = new_case_entry(); | ||||
| 	C_df_ilb(ce->ce_label = text_label()); | ||||
| 	ce->ce_value = val = expr->VL_VALUE; | ||||
| 	if (sh->sh_entries == 0)	{ | ||||
| 		/* first case entry	*/ | ||||
| 	if (sh->sh_entries == 0) { /* first case entry	*/ | ||||
| 		ce->next = (struct case_entry *) 0; | ||||
| 		sh->sh_entries = ce; | ||||
| 		sh->sh_lowerbd = sh->sh_upperbd = val; | ||||
| 		sh->sh_nrofentries = 1; | ||||
| 	} | ||||
| 	else	{ | ||||
| 		/* second etc. case entry		*/ | ||||
| 		/* find the proper place to put ce into the list	*/ | ||||
| 	else { /* second etc. case entry; put ce into proper place */ | ||||
| 		register struct case_entry *c1 = sh->sh_entries, *c2 = 0; | ||||
| 		 | ||||
| 		if (val < sh->sh_lowerbd) | ||||
|  | @ -164,37 +155,34 @@ code_case(expr) | |||
| 		else | ||||
| 		if (val > sh->sh_upperbd) | ||||
| 			sh->sh_upperbd = val; | ||||
| 		while (c1 && c1->ce_value < ce->ce_value)	{ | ||||
| 		while (c1 && c1->ce_value < ce->ce_value) { | ||||
| 			c2 = c1; | ||||
| 			c1 = c1->next; | ||||
| 		} | ||||
| 		/*	At this point three cases are possible:
 | ||||
| 			1: c1 != 0 && c2 != 0: | ||||
| 				insert ce somewhere in the middle | ||||
| 			2: c1 != 0 && c2 == 0: | ||||
| 				insert ce right after the head | ||||
| 			3: c1 == 0 && c2 != 0: | ||||
| 				append ce to last element | ||||
| 			1: c1 != 0 && c2 != 0: insert ce somewhere in the middle | ||||
| 			2: c1 != 0 && c2 == 0: insert ce right after the head | ||||
| 			3: c1 == 0 && c2 != 0: append ce to last element | ||||
| 			The case c1 == 0 && c2 == 0 cannot occur, since | ||||
| 			the list is guaranteed not to be empty. | ||||
| 			the list is guaranteed to be non-empty. | ||||
| 		*/ | ||||
| 		if (c1)	{ | ||||
| 			if (c1->ce_value == ce->ce_value)	{ | ||||
| 		if (c1) { | ||||
| 			if (c1->ce_value == ce->ce_value) { | ||||
| 				error("multiple case entry for value %ld", | ||||
| 					ce->ce_value); | ||||
| 				free_case_entry(ce); | ||||
| 				return; | ||||
| 			} | ||||
| 			if (c2)	{ | ||||
| 			if (c2) { | ||||
| 				ce->next = c2->next; | ||||
| 				c2->next = ce; | ||||
| 			} | ||||
| 			else	{ | ||||
| 			else { | ||||
| 				ce->next = sh->sh_entries; | ||||
| 				sh->sh_entries = ce; | ||||
| 			} | ||||
| 		} | ||||
| 		else	{ | ||||
| 		else { | ||||
| 			ASSERT(c2); | ||||
| 			ce->next = (struct case_entry *) 0; | ||||
| 			c2->next = ce; | ||||
|  | @ -207,13 +195,11 @@ code_default() | |||
| { | ||||
| 	register struct switch_hdr *sh = switch_stack; | ||||
| 
 | ||||
| 	if (sh == 0)	{ | ||||
| 	if (sh == 0) | ||||
| 		error("default not in switch"); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (sh->sh_default != 0)	{ | ||||
| 	else | ||||
| 	if (sh->sh_default != 0) | ||||
| 		error("multiple entry for default in switch"); | ||||
| 		return; | ||||
| 	} | ||||
| 	C_df_ilb(sh->sh_default = text_label()); | ||||
| 	else | ||||
| 		C_df_ilb(sh->sh_default = text_label()); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue