File:  [MW Coherent from dump] / coherent / d / bin / cc / c / n0 / ddecl.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * The routines in this file deal with the declaration of names.
 * The declaration stuff is done here; the parsing is done elsewhere.
 */
#ifdef   vax
#include "INC$LIB:cc0.h"
#else
#include "cc0.h"
#endif

/*
 * This array maps function and parameter types
 * into their defined interface types.
 * fixtype() below knows about this table;
 * if it changes, fixtype() might change too.
 */
static char xtype[] = {
	T_NONE,				/* T_NONE,		*/
	T_INT,		T_UINT,		/* T_CHAR,   T_UCHAR,	*/
	T_INT,		T_UINT,		/* T_SHORT,  T_USHORT,	*/
	T_INT,		T_UINT,		/* T_INT,    T_UINT,	*/
	T_PTR,				/* T_PTR,		*/
	T_LONG,		T_ULONG,	/* T_LONG,   T_ULONG,	*/
	T_DOUBLE,	T_DOUBLE,	/* T_FLOAT,  T_DOUBLE,	*/
	T_VOID,				/* T_VOID,		*/
	T_STRUCT,	T_FSTRUCT,	/* T_STRUCT, T_FSTRUCT,	*/
	T_UNION,	T_FUNION,	/* T_UNION,  T_FUNION,	*/
	T_INT,		T_INT		/* T_ENUM,   T_FENUM	*/
};

/*
 * Declare a variable 'sp' with class 'c', type 't' and structure info 'ip'.
 * Many checks are made here for redeclarations and funny things.
 * For objects of class 'C_MOE', 'x1' is the enumeration value.
 * For objects of class 'C_MOS' and 'C_MOU',
 * 'x1' is the field width in bits and 'x2' is the long offset in bits.
 * 'ronlyf' passes both 'readonly' and 'alien' modifiers.
 */
SYM *
declare(sp, c, t, ndp, ip, ronlyf, x1, x2)
register SYM	*sp;
DIM		*ndp;
INFO		*ip;
unsigned long	x2;
{
	register DIM	*dp, *xdp;
	int		af, ff, rf;
	int		oc, ot;
	unsigned long	value;
	unsigned	offs;

	/*
	 * Demote some function definitions to references.
	 * Adjust the return type of functions returning char, short or float.
	 * If the s_level is wrong, due to missing "extern", check
	 * for redeclaration.
	 */
	if (ndp!=NULL && ndp->d_type==D_FUNC) {
		if (c==C_AUTO || c==C_PAUTO || c==C_SIN
		|| ((c==C_GDEF || c==C_SEX) && (s==SEMI || s==COMMA)))
			c = C_GREF;
		if (ndp->d_dp==NULL && ((ronlyf&S_ALIEN)==0 || t==T_FLOAT))
			t = fixtype(t, sp, "function");
		if (sp->s_level > LL_EXT)
			sp = fixlevel(sp);
	}
	/*
	 * Make certain that the declarator is not
	 * forbidden by the semantics of C. The declaration
	 * reader allows anything that exhibits correct
	 * syntax through.
	 */
	if (c!=C_TYPE && t==T_VOID && !isfunction(ndp)) {
		cerror("illegal use of \"void\" type");
		t = T_INT;
	}
	af = ff = rf = 0;
	for (dp=ndp; dp!=NULL; dp=dp->d_dp) {
		switch (dp->d_type) {

		case D_ARRAY:
			if (ff != 0)
				cerror("function cannot return an array");
			if ((xdp = dp->d_dp) != NULL	/* [10][] */
			&&   xdp->d_type == D_ARRAY
			&&   xdp->d_bound == 0)
				cerror("bad flexible array declaration");
			af = 1;
			ff = 0;
			break;

		case D_FUNC:
			if (ff != 0)
				cerror("function cannot return a function");
			else if (af != 0)
				cerror("cannot declare array of functions");
			af = 0;
			ff = 1;
			break;

		case D_PTR:
			af = ff = 0;
		}
	}
	if (ff!=0 && istruct(t))
		notbook();
	/*
	 * Check for redeclarations.
	 * If the old is "C_ARG" (a function parameter),
	 * then just about any combination is ok.
	 * The types are adjusted in consideration of the passing rules.
	 * Other redeclarations are typechecked.
	 */
	ot = sp->s_type;
	oc = sp->s_class;
	if (oc == C_ARG) {
		dp = ndp;
		if (dp == NULL || isfunction(dp)) {
			t = fixtype(t, sp, "parameter");
			if (istruct(t))
				notbook();
		} else if (dp->d_type == D_ARRAY) {
			dp->d_type = D_PTR;
			dp->d_bound = 0;
		} else if (dp->d_type != D_PTR)
			cerror("functions cannot be parameters");
	} else if (c==C_PAUTO || c==C_PREG) {
		cerror("identifier \"%s\" is not a parameter", sp->s_id);
		c = C_AUTO;
	} else if ((c==C_AUTO || c==C_REG)
	 && ndp!=NULL && ndp->d_type==D_ARRAY && ndp->d_bound==0) {
		cerror("cannot declare flexible automatic array");
	} else if (ot!=T_NONE && ot!=t && !ismemb(oc)) {
		++rf;
	} else if (oc == C_CXT) {
		if (ndp == NULL || ndp->d_type != D_FUNC || ronlyf != 0)
			++rf;
	} else if (oc==C_MOE && c==C_MOE) {
		if (sp->s_value != x1)
			++rf;
	} else if (ismemb(oc) && ismemb(c)) {
		value = x2/NBPBYTE;
		offs = x2%NBPBYTE;
		if (doalign(t) && x1 != 0 && (value&1) != 0) {
			--value;
			offs += 8;
		}
		if (x1 != sp->s_width
		 || value != sp->s_value
		 || offs != sp->s_offset)
			++rf;
	} else if (isdefn(oc) && isdefn(c)) {
		if (oc!=C_GREF && c!=C_GREF)
			++rf;
		else if (c == C_GREF)
			c = oc;
	} else if (oc != C_NONE)
		++rf;
	if (oc != C_NONE && (sp->s_flag&ronlyf) != ronlyf)
		++rf;
	sp->s_class = c;
	sp->s_type  = t;
	dropdim(sp->s_dp);
	sp->s_dp = ndp;
	sp->s_dline = line;
	sp->s_flag |= ronlyf;
	if ((ronlyf&S_ALIEN) != 0) {
		if ( ! isdefn(c) || ndp==NULL || ndp->d_type!=D_FUNC)
			cerror("inappropriate \"alien\" modifier");
		sp->s_seg = SALIEN;
	}
	if (istag(oc) || ot==T_STRUCT || ot==T_UNION || ot==T_ENUM) {
		dropinfo(sp->s_ip);
		sp->s_ip = NULL;
	}
	if (istag(c) || t>T_DOUBLE) {
		sp->s_ip = ip;
		if (istag(c) || t==T_STRUCT || t==T_UNION || t==T_ENUM)
			++ip->i_refc;
	}
	if (istag(c))
		backplug(sp);
	if (c == C_MOE) 
		sp->s_value = x1;
	if (ismemb(c)) {
		value = x2/NBPBYTE;
		offs = x2%NBPBYTE;
		if (doalign(t) && x1 != 0 && (value&1) != 0) {
			--value;
			offs += 8;
		}
		if (value > MAXMEMB)
			cerror("member \"%s\" is not addressable", sp->s_id);
		sp->s_width  = x1;
		sp->s_value  = value;
		sp->s_offset = offs;
	}
	if (rf != 0)
		cerror("identifier \"%s\" is being redeclared", sp->s_id);
	return(sp);
}

/*
 * Decrement reference count of a
 * structure info. block.
 * Free it if the block is now an
 * unreferenced one.
 */
dropinfo(ip)
register INFO	*ip;
{
	if (ip!=NULL && --ip->i_refc==0)
		free((char *) ip);
}

/*
 * Test if a storage class is a global
 * storage class.
 */
isdefn(c)
register int	c;
{
	if (c==C_GDEF || c==C_GREF || c==C_SEX || c==C_SIN)
		return (1);
	return (0);
}

/*
 * Test if a type is one of the structure
 * like types.
 */
istruct(t)
{
	if (t>=T_STRUCT && t<=T_FUNION)
		return (1);
	return (0);
}

/*
 * Test for tag classes.
 */
istag(c)
register int	 c;
{
	if (c==C_STAG || c==C_UTAG || c==C_ETAG)
		return (1);
	return (0);
}

/*
 * Test for one of the type definition classes.
 */
istype(c)
register int	 c;
{
	if (c==C_STAG || c==C_UTAG || c==C_ETAG || c==C_TYPE)
		return (1);
	return (0);
}

/*
 * Test for member classes.
 */
ismemb(c)
register int	c;
{
	if (c==C_MOS || c==C_MOU)
		return (1);
	return (0);
}

/*
 * Examine a "DIM" chain to see if it describes a function.
 */
isfunction(dp)
register DIM	*dp;
{
	register int n;

	for (n = 0; dp!=NULL; dp = dp->d_dp)
		n = (dp->d_type == D_FUNC);
	return (n);
}

/*
 * Given a type t, return the adjusted type xtype[t].
 * Issue a "type adjusted" warning for dangerous cases.
 * This does not determine "dangerous" rigorously,
 * rather it uses facts about the values in xtype[] above;
 * the only cases in which xtype[t]!=t are
 * char->int, uchar->uint, short->int, ushort->uint, float->double.
 */
fixtype(t, sp, s)
register int t;
SYM *sp;
char *s;
{
	register int xt;
	char *ntype;

	xt = xtype[t];
	if (xt != t && mysizes[xt] != mysizes[t]) {
		switch(xt) {
		case T_INT:
			ntype = "int";
			break;
		case T_UINT:
			ntype = "unsigned int";
			break;
		case T_DOUBLE:
			ntype = "double";
			break;
		}
		if (isvariant(VWIDEN))
		cwarn("type of %s \"%s\" adjusted to %s", s, sp->s_id, ntype);
	}
	return(xt);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.