File:  [MW Coherent from dump] / coherent / d / bin / cc / c / n0 / init.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

/*
 * C compiler.
 * Initializers.
 * (All storage classes).
 */
#ifdef   vax
#include "INC$LIB:cc0.h"
#else
#include "cc0.h"
#endif

init(sp, dp, bo, flex)
register SYM	*sp;
register DIM	*dp;
sizeof_t	bo;
int		flex;
{
	register int	t;
	DIM		*ndp;
	TREE		*tp;
	sizeof_t	width, nbe, nel, ninit;
	int		brace, c, adj;

	t  = sp->s_type;
	width = sdsize(sp, dp);
	ndp = dp;
	if (dp!=NULL && dp->d_type==D_ARRAY) {
		if (dp->d_bound != 0)
			flex = 0;
		ndp = dp->d_dp;
		if (width==0 && !flex)
			cerror("array row has 0 length");
	} else
		flex = 0;
	nel = 0;
	nbe = sdsize(sp, ndp);
	if (nbe != 0)
		nel = width/nbe;
	brace = 0;
	if (s==LBRACE && (dp!=NULL || !istruct(t))) {
		++brace;
		lex();
	} else if (s!=LBRACE && (dp!=NULL || istruct(t)))
		notbook();
	ninit = 0;
	while (s != RBRACE) {
		if (ndp==NULL && istruct(t))
			sinit(sp, bo);
		else if (ndp!=NULL && ndp->d_type==D_ARRAY)
			init(sp, ndp, bo, 0);
		else {
			adj = 0;
			if (s==STRING && t<T_INT && ndp==NULL) {
again:				while ((c = getmap('\"')) >= 0) {
					newtree(sizeof(TREE));
					icollect(bicon(c), bo, sp, ndp);
					++ninit;
					++bo;
				}
				if (lex() == STRING) {
					++adj;
					goto again;
				}
				if (adj)
					notbook();
				if (!flex && ninit==nel) {
					cwarn("string initializer not terminated by NUL");
					break;
				}
				newtree(sizeof(TREE));
				icollect(bicon(0), bo, sp, ndp);
				++ninit;
				break;
			}
			newtree(sizeof(TREE));
			++ininit;
			tp = expr();
			--ininit;
			icollect(tp, bo, sp, ndp);
		}
		++ninit;
		bo += nbe;
		if (s != COMMA)
			break;
		if (ninit>=nel && !flex) {
			if (brace) {
				lex();
				if (s == RBRACE)
					cwarn("trailing ',' in initialization list");
				else {
					cerror("too many initializers");
					iskip();
				}
			}
			break;
		}
		itrail();
	}
	if (brace)
		mustbe(RBRACE);
	if (ninit < nel) {
		c = sp->s_class;
		if (c==C_GDEF || c==C_SIN || c==C_SEX) {
			bput(BLOCK);
			zput(nbe*(nel-ninit));
		}
	}
	if (ninit > nel) {
		if (!flex)
			cerror("too many initializers");
		if (dp != NULL)
			dp->d_bound = ninit;
	}
}

/*
 * Initialize a structure.
 * Create a fake variable for each member;
 * this is necessary for the call to build() in iassign()
 * to do the correct things.
 */
sinit(sp, bo)
SYM	*sp;
sizeof_t bo;
{
	register SYM	*mp;
	register INFO	*ip;
	register int	n;
	int		brace, c, t, f;
	sizeof_t	mo, lo;
	SYM		sym;

	c = sp->s_class;
	t = sp->s_type;
	if (t==T_UNION || t==T_FUNION)
		cerror("cannot initialize unions");
	if (t==T_FSTRUCT || t==T_FUNION)
		return;
	ip = sp->s_ip;
	sym.s_class = c;
	sym.s_value = sp->s_value;
	brace = 0;
	if (s == LBRACE) {
		++brace;
		lex();
	}
	lo = n = f = 0;
	while (s != RBRACE) {
		if (n >= ip->i_nsp) {
			if (f == 0) {
				cerror("too many structure initializers");
				++f;
			}
			sym.s_type = T_INT;
			sym.s_dp = sym.s_ip = NULL;
			mo = 0;
		} else {
			mp = ip->i_sp[n++];
			sym.s_type = mp->s_type;
			sym.s_dp   = mp->s_dp;
			sym.s_ip   = mp->s_ip;
			mo = mp->s_value;
			if (mp->s_width != 0)
				cerror("cannot initialize fields");
			if (!isauto(&sym) && lo!=mo) {
				bput(BLOCK);
				zput(mo-lo);
				lo = mo;
			}
		}
		init(&sym, sym.s_dp, bo+mo, 0);
		lo += ssize(&sym);
		if (s != COMMA || (n>=ip->i_nsp && !brace))
			break;
		itrail();
	}
	if (brace)
		mustbe(RBRACE);
	if (t==T_STRUCT && (c==C_GDEF || c==C_SIN || c==C_SEX)) {
		if ((mo = ip->i_size-lo) > 0) {
			bput(BLOCK);
			zput(mo);
		}
	}
}

/*
 * Fetch the next symbol.
 * The current symbol is a COMMA.
 * If the new symbol is '}', the program has said ", }"; this is legal.
 * If you pull the comments here, it becomes not quite so legal.
 */
static
itrail()
{
	lex();
	if (s == RBRACE)
		cwarn("trailing ',' in initialization list");
}

/*
 * An initialization starting with '{' contains too many initializers.
 * Skip initializers to the matching '}' or EOF.
 */
static
iskip()
{
	register int braces;

	braces = 0;
	for(;;) {
		if (s == LBRACE)
			++braces;
		else if (s == RBRACE) {
			if (braces == 0)
				return;
			else
				--braces;
		}
		else if (s == EOF)
			return;
		lex();
	}
}

/*
 * Return true if symbol "sp" is an automatic,
 * in the sense that an assigment statement must be generated
 * for the initialization item.
 * Registers are considered auto.
 */
isauto(sp)
register SYM	*sp;
{
	register int	c;

	c = sp->s_class;
	if (c==C_AUTO || c==C_PAUTO || c==C_REG)
		return (1);
	return (0);
}

/*
 * This routine actually performs the initialization.
 * Either an assignment node is built up and evaluated for effect,
 * or an initialization tree is output.
 */
icollect(tp, bo, sp, dp)
register TREE	*tp;
sizeof_t	bo;
register SYM	*sp;
DIM		*dp;
{
	register TREE	*ip;

	if (isauto(sp)) {
		iassign(sp, dp, bo, tp);
		return;
	}
	ip = talloc();
	ip->t_op = INIT;
	ip->t_type = sp->s_type;
	ip->t_dp = dp;
	ip->t_ip = sp->s_ip;
	ip->t_lp = tp;
	tput(IEXPR, 0, ip);
}

/*
 * Actually do the assignment for an automatic initialization thing.
 */
iassign(sp, dp, bo, tp)
register SYM	*sp;
register TREE	*tp;
sizeof_t	bo;
DIM		*dp;
{
	register TREE	*ip;
	DIM		*ssdp;

	ssdp = sp->s_dp;
	sp->s_dp = dp;
	ip = bid(sp);
	sp->s_dp = ssdp;
	if (sp->s_class != C_REG)
		ip->t_offs += bo;
	tp = build(ASSIGN, ip, tp);
	tput(EEXPR, 0, tp);
}

unix.superglobalmegacorp.com

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