668 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			668 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Header$ */
 | 
						|
/*	IDENTIFIER  FIDDLING & SYMBOL TABLE HANDLING	*/
 | 
						|
 | 
						|
#include	"nofloat.h"
 | 
						|
#include	"debug.h"
 | 
						|
#include	"idfsize.h"
 | 
						|
#include	"botch_free.h"
 | 
						|
#include	"nopp.h"
 | 
						|
#include	"alloc.h"
 | 
						|
#include	"arith.h"
 | 
						|
#include	"align.h"
 | 
						|
#include	"LLlex.h"
 | 
						|
#include	"level.h"
 | 
						|
#include	"stack.h"
 | 
						|
#include	"idf.h"
 | 
						|
#include	"label.h"
 | 
						|
#include	"def.h"
 | 
						|
#include	"type.h"
 | 
						|
#include	"struct.h"
 | 
						|
#include	"declar.h"
 | 
						|
#include	"decspecs.h"
 | 
						|
#include	"sizes.h"
 | 
						|
#include	"Lpars.h"
 | 
						|
#include	"assert.h"
 | 
						|
#include	"specials.h"	/* registration of special identifiers	*/
 | 
						|
#include	"storage.h"
 | 
						|
 | 
						|
int idfsize = IDFSIZE;
 | 
						|
extern char options[];
 | 
						|
 | 
						|
char sp_occurred[SP_TOTAL];	/* indicate occurrence of special id	*/
 | 
						|
 | 
						|
struct idf *idf_hashtable[HASHSIZE];
 | 
						|
	/*	All identifiers can in principle be reached through
 | 
						|
		idf_hashtable; idf_hashtable[hc] is the start of a chain of
 | 
						|
		idf's whose tags all hash to hc. Each idf is the start of
 | 
						|
		a chain of def's for that idf, sorted according to level,
 | 
						|
		with the most recent one on top.
 | 
						|
		Any identifier occurring on a level is entered into this
 | 
						|
		list, regardless of the nature of its declaration
 | 
						|
		(variable, selector, structure tag, etc.).
 | 
						|
	*/
 | 
						|
 | 
						|
struct idf *
 | 
						|
idf_hashed(tg, size, hc)
 | 
						|
	char *tg;
 | 
						|
	int size;		/* includes the '\0' character */
 | 
						|
	int hc;
 | 
						|
{
 | 
						|
	/*	The tag tg with length size and known hash value hc is
 | 
						|
		looked up in the identifier table; if not found, it is
 | 
						|
		entered. A pointer to it is returned.
 | 
						|
		The identifier has already been truncated to idfsize
 | 
						|
		characters.
 | 
						|
	*/
 | 
						|
	register struct idf **hook = &idf_hashtable[hc], *notch;
 | 
						|
 | 
						|
	while ((notch = *hook))	{
 | 
						|
		register cmp = strcmp(tg, notch->id_text);
 | 
						|
 | 
						|
		if (cmp < 0)
 | 
						|
			break;
 | 
						|
		else
 | 
						|
		if (cmp == 0)	{
 | 
						|
			/*	suppose that special identifiers, as
 | 
						|
				"setjmp", are already inserted
 | 
						|
			*/
 | 
						|
			sp_occurred[notch->id_special] = 1;
 | 
						|
			return notch;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			hook = ¬ch->next;
 | 
						|
	}
 | 
						|
	/* a new struct idf must be inserted at the hook */
 | 
						|
	notch = new_idf();
 | 
						|
	clear((char *)notch, sizeof(struct idf));
 | 
						|
	notch->next = *hook;
 | 
						|
	*hook = notch;		/* hooked in */
 | 
						|
	notch->id_text = Salloc(tg, size);
 | 
						|
#ifndef NOPP
 | 
						|
	notch->id_resmac = 0;
 | 
						|
#endif NOPP
 | 
						|
	return notch;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef	DEBUG
 | 
						|
hash_stat()
 | 
						|
{
 | 
						|
	if (options['h'])	{
 | 
						|
		register int i;
 | 
						|
		
 | 
						|
		print("Hash table tally:\n");
 | 
						|
		for (i = 0; i < HASHSIZE; i++)	{
 | 
						|
			register struct idf *notch = idf_hashtable[i];
 | 
						|
			int cnt = 0;
 | 
						|
	
 | 
						|
			while (notch)	{
 | 
						|
				cnt++;
 | 
						|
				notch = notch->next;
 | 
						|
			}
 | 
						|
			print("%d %d\n", i, cnt);
 | 
						|
		}
 | 
						|
		print("End hash table tally\n");
 | 
						|
	}		
 | 
						|
}
 | 
						|
#endif	DEBUG
 | 
						|
 | 
						|
struct idf *
 | 
						|
str2idf(tg)
 | 
						|
	char tg[];
 | 
						|
{
 | 
						|
	/*	str2idf() returns an entry in the symbol table for the
 | 
						|
		identifier tg.  If necessary, an entry is created.
 | 
						|
		It is used where the text of the identifier is available
 | 
						|
		but its hash value is not; otherwise idf_hashed() is to
 | 
						|
		be used.
 | 
						|
	*/
 | 
						|
	register char *cp = tg;
 | 
						|
	register int hash;
 | 
						|
	register int pos = -1;
 | 
						|
	register int ch;
 | 
						|
	char ntg[IDFSIZE + 1];
 | 
						|
	register char *ncp = ntg;
 | 
						|
 | 
						|
	hash = STARTHASH();
 | 
						|
	while (++pos < idfsize && (ch = *cp++))	{
 | 
						|
		*ncp++ = ch;
 | 
						|
		hash = ENHASH(hash, ch, pos);
 | 
						|
	}
 | 
						|
	hash = STOPHASH(hash);
 | 
						|
	*ncp++ = '\0';
 | 
						|
	return idf_hashed(ntg, ncp - ntg, hash);
 | 
						|
}
 | 
						|
 | 
						|
struct idf *
 | 
						|
gen_idf()
 | 
						|
{
 | 
						|
	/*	A new idf is created out of nowhere, to serve as an
 | 
						|
		anonymous name.
 | 
						|
	*/
 | 
						|
	static int name_cnt;
 | 
						|
	char buff[100];
 | 
						|
	char *sprint();
 | 
						|
 | 
						|
	sprint(buff, "#%d in %s, line %u",
 | 
						|
			++name_cnt, dot.tk_file, dot.tk_line);
 | 
						|
	return str2idf(buff);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
is_anon_idf(idf)
 | 
						|
	struct idf *idf;
 | 
						|
{
 | 
						|
	return idf->id_text[0] == '#';
 | 
						|
}
 | 
						|
 | 
						|
declare_idf(ds, dc, lvl)
 | 
						|
	struct decspecs *ds;
 | 
						|
	struct declarator *dc;
 | 
						|
{
 | 
						|
	/*	The identifier inside dc is declared on the level lvl, with
 | 
						|
		properties deduced from the decspecs ds and the declarator
 | 
						|
		dc.
 | 
						|
		The level is given explicitly to be able to insert, e.g.,
 | 
						|
		labels on the outermost level inside the function.
 | 
						|
		This routine implements the rich semantics of C
 | 
						|
		declarations.
 | 
						|
	*/
 | 
						|
	register struct idf *idf = dc->dc_idf;
 | 
						|
	register int sc = ds->ds_sc;
 | 
						|
		/*	This local copy is essential:
 | 
						|
				char b(), c;
 | 
						|
			makes b GLOBAL and c AUTO.
 | 
						|
		*/
 | 
						|
	register struct def *def = idf->id_def;		/* may be NULL */
 | 
						|
	register struct type *type;
 | 
						|
	struct stack_level *stl = stack_level_of(lvl);
 | 
						|
	char formal_array = 0;
 | 
						|
	
 | 
						|
	/* determine the present type */
 | 
						|
	if (ds->ds_type == 0)	{
 | 
						|
		/*	at the L_FORMAL1 level there is no type specified yet
 | 
						|
		*/
 | 
						|
		ASSERT(lvl == L_FORMAL1);
 | 
						|
		type = int_type;	/* may change at L_FORMAL2 */
 | 
						|
	}
 | 
						|
	else	{
 | 
						|
		/* combine the decspecs and the declarator into one type */
 | 
						|
		type = declare_type(ds->ds_type, dc);
 | 
						|
		if (type->tp_size <= (arith)0 &&
 | 
						|
		    actual_declaration(sc, type))	{
 | 
						|
			if (type->tp_size == (arith) -1) {
 | 
						|
				/* the type is not yet known,
 | 
						|
				   but it has to be:
 | 
						|
				*/
 | 
						|
				extern char *symbol2str();
 | 
						|
				error("unknown %s-type",
 | 
						|
					symbol2str(type->tp_fund));
 | 
						|
			}
 | 
						|
			else if (type->tp_fund != LABEL) {
 | 
						|
				/* CJ */
 | 
						|
				warning("%s has size 0", idf->id_text);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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);
 | 
						|
			type = construct_type(POINTER, type, (arith)0);
 | 
						|
			break;
 | 
						|
		case ARRAY:	/* RM 10.1	*/
 | 
						|
			type = construct_type(POINTER, type->tp_up, (arith)0);
 | 
						|
			formal_array = 1;
 | 
						|
			break;
 | 
						|
#ifndef NOFLOAT
 | 
						|
		case FLOAT:	/* RM 10.1	*/
 | 
						|
			type = double_type;
 | 
						|
			break;
 | 
						|
#endif NOFLOAT
 | 
						|
		case CHAR:
 | 
						|
		case SHORT:
 | 
						|
			/*	The RM is not clear about this: we must
 | 
						|
				convert the parameter from int (they have
 | 
						|
				been pushed as ints) to the specified type.
 | 
						|
				The conversion to type int or uint is not
 | 
						|
				allowed.
 | 
						|
			*/
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	/*	The tests on types, postponed from do_decspecs(), can now
 | 
						|
		be performed.
 | 
						|
	*/
 | 
						|
	/* update the storage class */
 | 
						|
	if (type && type->tp_fund == FUNCTION)	{
 | 
						|
		if (sc == 0 || (ds->ds_sc_given && sc == AUTO))	/* RM 8.1 */
 | 
						|
			sc = GLOBAL;
 | 
						|
		else
 | 
						|
		if (sc == REGISTER) {
 | 
						|
			error("function has illegal storage class");
 | 
						|
			ds->ds_sc = sc = GLOBAL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	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 */
 | 
						|
		/* 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);
 | 
						|
	}
 | 
						|
	if (def && def->df_level >= lvl)	{
 | 
						|
		/*	There is already a declaration for idf on this
 | 
						|
			level, or even more inside.
 | 
						|
			The rules differ for different levels.
 | 
						|
		*/
 | 
						|
		switch (lvl)	{
 | 
						|
		case L_GLOBAL:
 | 
						|
			global_redecl(idf, sc, type);
 | 
						|
			break;
 | 
						|
		case L_FORMAL1:	/* formal declaration */
 | 
						|
			error("formal %s redeclared", idf->id_text);
 | 
						|
			break;
 | 
						|
		case L_FORMAL2:	/* formal definition */
 | 
						|
		default:	/* local */
 | 
						|
			error("%s redeclared", idf->id_text);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else	/* the idf is unknown on this level */
 | 
						|
	if (lvl == L_FORMAL2 && sc != ENUM && good_formal(def, idf))	{
 | 
						|
		/* formal declaration, update only */
 | 
						|
		def->df_type = type;
 | 
						|
		def->df_formal_array = formal_array;
 | 
						|
		def->df_sc = sc;
 | 
						|
		def->df_level = L_FORMAL2;	/* CJ */
 | 
						|
		if (sc == REGISTER) def->df_register = REG_BONUS;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if (	lvl >= L_LOCAL &&
 | 
						|
		(type->tp_fund == FUNCTION || sc == EXTERN)
 | 
						|
	)	{
 | 
						|
		/*	extern declaration inside function is treated the
 | 
						|
			same way as global extern declaration
 | 
						|
		*/
 | 
						|
		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 */
 | 
						|
		register struct def *newdef = new_def();
 | 
						|
 | 
						|
		clear((char *)newdef, sizeof(struct def));
 | 
						|
		newdef->next = def;
 | 
						|
		newdef->df_level = lvl;
 | 
						|
		newdef->df_type = type;
 | 
						|
		newdef->df_sc = sc;
 | 
						|
		if (lvl == L_FORMAL1)	/* CJ */
 | 
						|
			newdef->df_register = REG_DEFAULT;
 | 
						|
		/* 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 REGISTER:
 | 
						|
			case AUTO:
 | 
						|
				if (type->tp_size == (arith)-1) {
 | 
						|
					error("size of local %s unknown",
 | 
						|
						idf->id_text);
 | 
						|
				/** type = idf->id_def->df_type = int_type; **/
 | 
						|
				}
 | 
						|
				newdef->df_register =
 | 
						|
					(sc == REGISTER) ? REG_BONUS
 | 
						|
					: REG_DEFAULT;
 | 
						|
				newdef->df_address =
 | 
						|
				stl->sl_max_block =
 | 
						|
				stl->sl_local_offset =
 | 
						|
					-align(-stl->sl_local_offset +
 | 
						|
						type->tp_size, type->tp_align);
 | 
						|
				break;
 | 
						|
			case STATIC:
 | 
						|
				newdef->df_address = (arith) data_label();
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
actual_declaration(sc, tp)
 | 
						|
	int sc;
 | 
						|
	struct type *tp;
 | 
						|
{
 | 
						|
	/*	An actual_declaration needs space, right here and now.
 | 
						|
	*/
 | 
						|
	register int fund = tp->tp_fund;
 | 
						|
	
 | 
						|
	if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */
 | 
						|
		return 0;
 | 
						|
	if (fund == FUNCTION || fund == ARRAY)
 | 
						|
		/* allocation solved in other ways */
 | 
						|
		return 0;
 | 
						|
	/* to be allocated */
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
global_redecl(idf, new_sc, tp)
 | 
						|
	register struct idf *idf;
 | 
						|
	register struct type *tp;
 | 
						|
{
 | 
						|
	/*	A global identifier may be declared several times,
 | 
						|
		provided the declarations do not conflict; they might
 | 
						|
		conflict in type (or supplement each other in the case of
 | 
						|
		an array) or they might conflict or supplement each other
 | 
						|
		in storage class.
 | 
						|
	*/
 | 
						|
	register struct def *def = idf->id_def;
 | 
						|
 | 
						|
	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
 | 
						|
		)	{
 | 
						|
			error("redeclaration of %s with different type",
 | 
						|
				idf->id_text);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		/* Multiple array declaration; this may be interesting */
 | 
						|
		if (tp->tp_size < 0)	{	/* new decl has [] */
 | 
						|
			/* nothing new */
 | 
						|
		}
 | 
						|
		else
 | 
						|
		if (otp->tp_size < 0)	{	/* old decl has [] */
 | 
						|
			def->df_type = tp;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		if (tp->tp_size != otp->tp_size)
 | 
						|
			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
 | 
						|
		for new_sc.
 | 
						|
		For now we have:
 | 
						|
			EXTERN:		we have seen the word "extern"
 | 
						|
			GLOBAL:		the item was declared on the outer
 | 
						|
					level, without either "extern" or
 | 
						|
					"static".
 | 
						|
			STATIC:		we have seen the word "static"
 | 
						|
			IMPLICIT:	function declaration inferred from
 | 
						|
					call
 | 
						|
	*/
 | 
						|
	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 */
 | 
						|
		case EXTERN:
 | 
						|
		case GLOBAL:
 | 
						|
			break;
 | 
						|
		case STATIC:
 | 
						|
			if (def->df_initialized)	{
 | 
						|
				error("cannot redeclare %s to static",
 | 
						|
					idf->id_text);
 | 
						|
			}
 | 
						|
			else	{
 | 
						|
				warning("%s redeclared to static",
 | 
						|
						idf->id_text);
 | 
						|
			}
 | 
						|
			def->df_sc = new_sc;
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			crash("bad storage class");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case GLOBAL:
 | 
						|
		switch (new_sc)	{	/* the new storage class */
 | 
						|
		case EXTERN:
 | 
						|
			def->df_sc = EXTERN;
 | 
						|
			break;
 | 
						|
		case GLOBAL:
 | 
						|
			break;
 | 
						|
		case STATIC:
 | 
						|
			if (def->df_initialized)
 | 
						|
				error("cannot redeclare %s to static",
 | 
						|
					idf->id_text);
 | 
						|
			else	{
 | 
						|
				if (options['R'])
 | 
						|
					warning("%s redeclared to static",
 | 
						|
						idf->id_text);
 | 
						|
				def->df_sc = STATIC;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			crash("bad storage class");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case STATIC:
 | 
						|
		switch (new_sc)	{	/* the new storage class */
 | 
						|
		case EXTERN:
 | 
						|
			if (def->df_initialized)
 | 
						|
				error("cannot redeclare %s to extern",
 | 
						|
					idf->id_text);
 | 
						|
			else	{
 | 
						|
				warning("%s redeclared to extern",
 | 
						|
					idf->id_text);
 | 
						|
				def->df_sc = EXTERN;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		case GLOBAL:
 | 
						|
		case STATIC:
 | 
						|
			if (def->df_type->tp_fund != FUNCTION)
 | 
						|
				warning("%s was already static",
 | 
						|
					idf->id_text);
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			crash("bad storage class");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case IMPLICIT:
 | 
						|
		switch (new_sc)	{	/* the new storage class */
 | 
						|
		case EXTERN:
 | 
						|
		case GLOBAL:
 | 
						|
			def->df_sc = new_sc;
 | 
						|
			break;
 | 
						|
		case STATIC:
 | 
						|
			if (options['R'])
 | 
						|
				warning("%s was implicitly declared as extern",
 | 
						|
					idf->id_text);
 | 
						|
			def->df_sc = new_sc;
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			crash("bad storage class");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case ENUM:
 | 
						|
	case TYPEDEF:
 | 
						|
		error("illegal redeclaration of %s", idf->id_text);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		crash("bad storage class");
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
good_formal(def, idf)
 | 
						|
	register struct def *def;
 | 
						|
	register struct idf *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 (!is_anon_idf(idf))
 | 
						|
			error("%s not in parameter list", idf->id_text);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	ASSERT(def->df_sc == FORMAL);	/* CJ */
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
declare_params(dc)
 | 
						|
	register struct declarator *dc;
 | 
						|
{
 | 
						|
	/*	Declares the formal parameters if they exist.
 | 
						|
	*/
 | 
						|
	register struct formal *fm = dc->dc_formal;
 | 
						|
	
 | 
						|
	while (fm)	{
 | 
						|
		declare_parameter(fm->fm_idf);
 | 
						|
		fm = fm->next;
 | 
						|
	}
 | 
						|
	free_formals(dc->dc_formal);
 | 
						|
	dc->dc_formal = 0;
 | 
						|
}
 | 
						|
 | 
						|
init_idf(idf)
 | 
						|
	register struct idf *idf;
 | 
						|
{
 | 
						|
	/*	The topmost definition of idf is set to initialized.
 | 
						|
	*/
 | 
						|
	register struct def *def = idf->id_def;	/* the topmost */
 | 
						|
	
 | 
						|
	if (def->df_initialized)
 | 
						|
		error("multiple initialization of %s", idf->id_text);
 | 
						|
	if (def->df_sc == TYPEDEF)	{
 | 
						|
		warning("typedef cannot be initialized");
 | 
						|
		def->df_sc == EXTERN;		/* ??? *//* What else ? */
 | 
						|
	}
 | 
						|
	def->df_initialized = 1;
 | 
						|
}
 | 
						|
 | 
						|
declare_parameter(idf)
 | 
						|
	struct idf *idf;
 | 
						|
{
 | 
						|
	/*	idf is declared as a formal.
 | 
						|
	*/
 | 
						|
	add_def(idf, FORMAL, int_type, level);
 | 
						|
}
 | 
						|
 | 
						|
declare_enum(tp, idf, l)
 | 
						|
	struct type *tp;
 | 
						|
	struct idf *idf;
 | 
						|
	arith l;
 | 
						|
{
 | 
						|
	/*	idf is declared as an enum constant with value l.
 | 
						|
	*/
 | 
						|
	add_def(idf, ENUM, tp, level);
 | 
						|
	idf->id_def->df_address = l;
 | 
						|
}
 | 
						|
 | 
						|
declare_formals(fp)
 | 
						|
	arith *fp;
 | 
						|
{
 | 
						|
	/*	Declares those formals as int that haven't been declared
 | 
						|
		by the user.
 | 
						|
		An address is assigned to each formal parameter.
 | 
						|
		The total size of the formals is returned in *fp;
 | 
						|
	*/
 | 
						|
	register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
 | 
						|
	arith f_offset = (arith)0;
 | 
						|
 | 
						|
#ifdef	DEBUG
 | 
						|
	if (options['t'])
 | 
						|
		dumpidftab("start declare_formals", 0);
 | 
						|
#endif	DEBUG
 | 
						|
	while (se)	{
 | 
						|
		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);
 | 
						|
		formal_cvt(def); /* cvt int to char or short, if necessary */
 | 
						|
		se = se->next;
 | 
						|
		def->df_level = L_FORMAL2;	/* CJ */
 | 
						|
	}
 | 
						|
	*fp = f_offset;
 | 
						|
}
 | 
						|
 | 
						|
add_def(idf, sc, tp, lvl)
 | 
						|
	struct idf *idf;
 | 
						|
	struct type *tp;
 | 
						|
	int lvl;
 | 
						|
	int sc;
 | 
						|
{
 | 
						|
	/*	The identifier idf is declared on level lvl with storage
 | 
						|
		class sc and type tp, through a faked C declaration.
 | 
						|
		This is probably the wrong way to structure the problem,
 | 
						|
		but it will have to do for the time being.
 | 
						|
	*/
 | 
						|
	struct decspecs Ds; struct declarator Dc;
 | 
						|
 | 
						|
	Ds = null_decspecs;
 | 
						|
	Ds.ds_type = tp;
 | 
						|
	Ds.ds_sc = sc;
 | 
						|
	Dc = null_declarator;
 | 
						|
	Dc.dc_idf = idf;
 | 
						|
	declare_idf(&Ds, &Dc, lvl);
 | 
						|
}
 | 
						|
 | 
						|
update_ahead(idf)
 | 
						|
	register struct idf *idf;
 | 
						|
{
 | 
						|
	/*	The tk_symb of the token ahead is updated in the light of new
 | 
						|
		information about the identifier idf.
 | 
						|
	*/
 | 
						|
	register int tk_symb = AHEAD;
 | 
						|
 | 
						|
	if (	(tk_symb == IDENTIFIER || tk_symb == TYPE_IDENTIFIER) &&
 | 
						|
		ahead.tk_idf == idf
 | 
						|
	)
 | 
						|
		AHEAD = idf->id_def && idf->id_def->df_sc == TYPEDEF ?
 | 
						|
				TYPE_IDENTIFIER : IDENTIFIER;
 | 
						|
}
 | 
						|
 | 
						|
free_formals(fm)
 | 
						|
	register struct formal *fm;
 | 
						|
{
 | 
						|
	while (fm)	{
 | 
						|
		struct formal *tmp = fm->next;
 | 
						|
 | 
						|
		free_formal(fm);
 | 
						|
		fm = tmp;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
char hmask[IDFSIZE];
 | 
						|
 | 
						|
init_hmask()
 | 
						|
{
 | 
						|
	/*	A simple congruence random number generator, as
 | 
						|
		described in Knuth, vol 2.
 | 
						|
	*/
 | 
						|
	register int h, rnd = HASH_X;
 | 
						|
	
 | 
						|
	for (h = 0; h < IDFSIZE; h++)	{
 | 
						|
		hmask[h] = rnd;
 | 
						|
		rnd = (HASH_A * rnd + HASH_C) & HASHMASK;
 | 
						|
	}
 | 
						|
}
 |