OpenBSD-4.6/usr.bin/pcc/ccom/init.c
/* $OpenBSD: init.c,v 1.8 2008/08/17 18:40:12 ragge Exp $ */
/*
* Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code and documentation must retain the above
* copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "pass1.h"
#include <string.h>
/*
* The following machine-dependent routines may be called during
* initialization:
*
* zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ.
* infld(CONSZ off, int fsz, CONSZ val)
* - sets the bitfield val starting at off and size fsz.
* ninval(CONSZ off, int fsz, NODE *)
* - prints an integer constant which may have
* a label associated with it, located at off and
* size fsz.
*
* Initialization may be of different kind:
* - Initialization at compile-time, all values are constants and laid
* out in memory. Static or extern variables outside functions.
* - Initialization at run-time, written to their values as code.
*
* Currently run-time-initialized variables are only initialized by using
* move instructions. An optimization might be to detect that it is
* initialized with constants and therefore copied from readonly memory.
*/
/*
* The base element(s) of an initialized variable is kept in a linked
* list, allocated while initialized.
*
* When a scalar is found, entries are popped of the instk until it's
* possible to find an entry for a new scalar; then onstk() is called
* to get the correct type and size of that scalar.
*
* If a right brace is found, pop the stack until a matching left brace
* were found while filling the elements with zeros. This left brace is
* also marking where the current level is for designated initializations.
*
* Position entries are increased when traversing back down into the stack.
*/
/*
* Good-to-know entries from symtab:
* soffset - # of bits from beginning of this structure.
*/
/*
* TO FIX:
* - Alignment of structs on like i386 char members.
*/
int idebug;
/*
* Struct used in array initialisation.
*/
static struct instk {
struct instk *in_prev; /* linked list */
struct symtab *in_lnk; /* member in structure initializations */
struct symtab *in_sym; /* symtab index */
union dimfun *in_df; /* dimenston of array */
TWORD in_t; /* type for this level */
int in_n; /* number of arrays seen so far */
int in_fl; /* flag which says if this level is controlled by {} */
} *pstk, pbase;
static struct symtab *csym;
#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
#ifdef PCC_DEBUG
static void prtstk(struct instk *in);
#endif
/*
* Linked lists for initializations.
*/
struct ilist {
struct ilist *next;
CONSZ off; /* bit offset of this entry */
int fsz; /* bit size of this entry */
NODE *n; /* node containing this data info */
};
struct llist {
SLIST_ENTRY(llist) next;
CONSZ begsz; /* bit offset of this entry */
struct ilist *il;
} *curll;
static SLIST_HEAD(, llist) lpole;
static CONSZ basesz;
static int numents; /* # of array entries allocated */
static struct ilist *
getil(struct ilist *next, CONSZ b, int sz, NODE *n)
{
struct ilist *il = tmpalloc(sizeof(struct ilist));
il->off = b;
il->fsz = sz;
il->n = n;
il->next = next;
return il;
}
/*
* Allocate a new struct defining a block of initializers appended to the
* end of the llist. Return that entry.
*/
static struct llist *
getll(void)
{
struct llist *ll;
ll = tmpalloc(sizeof(struct llist));
ll->begsz = numents * basesz;
ll->il = NULL;
SLIST_INSERT_LAST(&lpole, ll, next);
numents++;
return ll;
}
/*
* Return structure containing off bitnumber.
* Allocate more entries, if needed.
*/
static struct llist *
setll(OFFSZ off)
{
struct llist *ll = NULL;
/* Ensure that we have enough entries */
while (off >= basesz * numents)
ll = getll();
if (ll != NULL && ll->begsz <= off && ll->begsz + basesz > off)
return ll;
SLIST_FOREACH(ll, &lpole, next)
if (ll->begsz <= off && ll->begsz + basesz > off)
break;
return ll; /* ``cannot fail'' */
}
/*
* beginning of initialization; allocate space to store initialized data.
* remember storage class for writeout in endinit().
* p is the newly declarated type.
*/
void
beginit(struct symtab *sp)
{
struct instk *is = &pbase;
struct llist *ll;
#ifdef PCC_DEBUG
if (idebug)
printf("beginit(), sclass %s\n", scnames(sp->sclass));
#endif
csym = sp;
numents = 0; /* no entries in array list */
if (ISARY(sp->stype))
basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->ssue);
else
basesz = tsize(DECREF(sp->stype), sp->sdf, sp->ssue);
SLIST_INIT(&lpole);
curll = ll = getll(); /* at least first entry in list */
/* first element */
is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL;
is->in_n = 0;
is->in_t = sp->stype;
is->in_sym = sp;
is->in_df = sp->sdf;
is->in_fl = 0;
is->in_prev = NULL;
pstk = is;
}
/*
* Push a new entry on the initializer stack.
* The new entry will be "decremented" to the new sub-type of the previous
* entry when called.
* Popping of entries is done elsewhere.
*/
static void
stkpush(void)
{
struct instk *is;
struct symtab *sq, *sp;
TWORD t;
if (pstk == NULL) {
sp = csym;
t = 0;
} else {
t = pstk->in_t;
sp = pstk->in_sym;
}
#ifdef PCC_DEBUG
if (idebug) {
printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass));
tprint(stdout, t, 0);
}
#endif
/*
* Figure out what the next initializer will be, and push it on
* the stack. If this is an array, just decrement type, if it
* is a struct or union, extract the next element.
*/
is = tmpalloc(sizeof(struct instk));
is->in_fl = 0;
is->in_n = 0;
if (pstk == NULL) {
/* stack empty */
is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL;
is->in_t = sp->stype;
is->in_sym = sp;
is->in_df = sp->sdf;
} else if (ISSOU(t)) {
sq = pstk->in_lnk;
if (sq == NULL) {
uerror("excess of initializing elements");
} else {
is->in_lnk = ISSOU(sq->stype) ? sq->ssue->sylnk : 0;
is->in_t = sq->stype;
is->in_sym = sq;
is->in_df = sq->sdf;
}
} else if (ISARY(t)) {
is->in_lnk = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->sylnk : 0;
is->in_t = DECREF(t);
is->in_sym = sp;
if (pstk->in_df->ddim != NOOFFSET &&
pstk->in_n >= pstk->in_df->ddim) {
werror("excess of initializing elements");
pstk->in_n--;
}
if (ISARY(is->in_t))
is->in_df = pstk->in_df+1;
} else
uerror("too many left braces");
is->in_prev = pstk;
pstk = is;
#ifdef PCC_DEBUG
if (idebug) {
printf(" newtype ");
tprint(stdout, is->in_t, 0);
printf("\n");
}
#endif
}
/*
* pop down to either next level that can handle a new initializer or
* to the next braced level.
*/
static void
stkpop(void)
{
#ifdef PCC_DEBUG
if (idebug)
printf("stkpop\n");
#endif
for (; pstk; pstk = pstk->in_prev) {
if (pstk->in_t == STRTY && pstk->in_lnk != NULL) {
pstk->in_lnk = pstk->in_lnk->snext;
if (pstk->in_lnk != NULL)
break;
}
if (ISSOU(pstk->in_t) && pstk->in_fl)
break; /* need } */
if (ISARY(pstk->in_t)) {
pstk->in_n++;
if (pstk->in_fl)
break;
if (pstk->in_df->ddim == NOOFFSET ||
pstk->in_n < pstk->in_df->ddim)
break; /* ger more elements */
}
}
#ifdef PCC_DEBUG
if (idebug > 1)
prtstk(pstk);
#endif
}
/*
* Count how many elements an array may consist of.
*/
static int
acalc(struct instk *is, int n)
{
if (is == NULL || !ISARY(is->in_t))
return 0;
return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n;
}
/*
* Find current bit offset of the top element on the stack from
* the beginning of the aggregate.
*/
static CONSZ
findoff(void)
{
struct instk *is;
OFFSZ off;
#ifdef PCC_DEBUG
if (ISARY(pstk->in_t) || ISSOU(pstk->in_t))
cerror("findoff on bad type");
#endif
/*
* Offset calculations. If:
* - previous type is STRTY, soffset has in-struct offset.
* - this type is ARY, offset is ninit*stsize.
*/
for (off = 0, is = pstk; is; is = is->in_prev) {
if (is->in_prev && is->in_prev->in_t == STRTY)
off += is->in_sym->soffset;
if (ISARY(is->in_t)) {
/* suesize is the basic type, so adjust */
TWORD t = is->in_t;
OFFSZ o;
while (ISARY(t))
t = DECREF(t);
o = ISPTR(t) ? SZPOINT(t) : is->in_sym->ssue->suesize;
off += o * acalc(is, 1);
while (is->in_prev && ISARY(is->in_prev->in_t)) {
if (is->in_prev->in_prev &&
is->in_prev->in_prev->in_t == STRTY)
off += is->in_sym->soffset;
is = is->in_prev;
}
}
}
#ifdef PCC_DEBUG
if (idebug>1) {
printf("findoff: off %lld\n", off);
prtstk(pstk);
}
#endif
return off;
}
/*
* Insert the node p with size fsz at position off.
* Bit fields are already dealt with, so a node of correct type
* with correct alignment and correct bit offset is given.
*/
static void
nsetval(CONSZ off, int fsz, NODE *p)
{
struct llist *ll;
struct ilist *il;
if (idebug>1)
printf("setval: off %lld fsz %d p %p\n", off, fsz, p);
if (fsz == 0)
return;
ll = setll(off);
off -= ll->begsz;
if (ll->il == NULL) {
ll->il = getil(NULL, off, fsz, p);
} else {
il = ll->il;
if (il->off > off) {
ll->il = getil(ll->il, off, fsz, p);
} else {
for (il = ll->il; il->next; il = il->next)
if (il->off <= off && il->next->off > off)
break;
if (il->off == off) {
/* replace */
nfree(il->n);
il->n = p;
} else
il->next = getil(il->next, off, fsz, p);
}
}
}
/*
* take care of generating a value for the initializer p
* inoff has the current offset (last bit written)
* in the current word being generated
*/
void
scalinit(NODE *p)
{
CONSZ woff;
NODE *q;
int fsz;
#ifdef PCC_DEBUG
if (idebug > 2) {
printf("scalinit(%p)\n", p);
fwalk(p, eprint, 0);
prtstk(pstk);
}
#endif
if (nerrors)
return;
p = optim(p);
#ifdef notdef /* leave to the target to decide if useable */
if (csym->sclass != AUTO && p->n_op != ICON &&
p->n_op != FCON && p->n_op != NAME)
cerror("scalinit not leaf");
#endif
/* Out of elements? */
if (pstk == NULL) {
uerror("excess of initializing elements");
return;
}
/*
* Get to the simple type if needed.
*/
while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
stkpush();
/* let buildtree do typechecking (and casting) */
q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_sym->sdf,
pstk->in_sym->ssue);
p = buildtree(ASSIGN, q, p);
nfree(p->n_left);
q = optim(p->n_right);
nfree(p);
/* bitfield sizes are special */
if (pstk->in_sym->sclass & FIELD)
fsz = -(pstk->in_sym->sclass & FLDSIZ);
else
fsz = tsize(pstk->in_t, pstk->in_sym->sdf, pstk->in_sym->ssue);
woff = findoff();
nsetval(woff, fsz, q);
stkpop();
#ifdef PCC_DEBUG
if (idebug > 2) {
printf("scalinit e(%p)\n", p);
}
#endif
}
/*
* Generate code to insert a value into a bitfield.
*/
static void
insbf(OFFSZ off, int fsz, int val)
{
struct symtab sym;
NODE *p, *r;
TWORD typ;
#ifdef PCC_DEBUG
if (idebug > 1)
printf("insbf: off %lld fsz %d val %d\n", off, fsz, val);
#endif
if (fsz == 0)
return;
/* small opt: do char instead of bf asg */
if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR)
typ = CHAR;
else
typ = INT;
/* Fake a struct reference */
p = buildtree(ADDROF, nametree(csym), NIL);
sym.stype = typ;
sym.squal = 0;
sym.sdf = 0;
sym.ssue = MKSUE(typ);
sym.soffset = off;
sym.sclass = typ == INT ? FIELD | fsz : MOU;
r = xbcon(0, &sym, typ);
p = block(STREF, p, r, INT, 0, MKSUE(INT));
ecode(buildtree(ASSIGN, stref(p), bcon(val)));
}
/*
* Clear a bitfield, starting at off and size fsz.
*/
static void
clearbf(OFFSZ off, OFFSZ fsz)
{
/* Pad up to the next even initializer */
if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) {
int ba = ((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off;
if (ba > fsz)
ba = fsz;
insbf(off, ba, 0);
off += ba;
fsz -= ba;
}
while (fsz >= SZCHAR) {
insbf(off, SZCHAR, 0);
off += SZCHAR;
fsz -= SZCHAR;
}
if (fsz)
insbf(off, fsz, 0);
}
/*
* final step of initialization.
* print out init nodes and generate copy code (if needed).
*/
void
endinit(void)
{
struct llist *ll;
struct ilist *il;
int fsz;
OFFSZ lastoff, tbit;
#ifdef PCC_DEBUG
if (idebug)
printf("endinit()\n");
#endif
if (csym->sclass != AUTO)
defloc(csym);
/* Calculate total block size */
if (ISARY(csym->stype) && csym->sdf->ddim == NOOFFSET) {
tbit = numents*basesz; /* open-ended arrays */
csym->sdf->ddim = numents;
if (csym->sclass == AUTO) { /* Get stack space */
csym->soffset = NOOFFSET;
oalloc(csym, &autooff);
}
} else
tbit = tsize(csym->stype, csym->sdf, csym->ssue);
/* Traverse all entries and print'em out */
lastoff = 0;
SLIST_FOREACH(ll, &lpole, next) {
for (il = ll->il; il; il = il->next) {
#ifdef PCC_DEBUG
if (idebug > 1) {
printf("off %lld size %d val %lld type ",
ll->begsz+il->off, il->fsz, il->n->n_lval);
tprint(stdout, il->n->n_type, 0);
printf("\n");
}
#endif
fsz = il->fsz;
if (csym->sclass == AUTO) {
struct symtab sym;
NODE *p, *r, *n;
if (ll->begsz + il->off > lastoff)
clearbf(lastoff,
(ll->begsz + il->off) - lastoff);
/* Fake a struct reference */
p = buildtree(ADDROF, nametree(csym), NIL);
n = il->n;
sym.stype = n->n_type;
sym.squal = n->n_qual;
sym.sdf = n->n_df;
sym.ssue = n->n_sue;
sym.soffset = ll->begsz + il->off;
sym.sclass = fsz < 0 ? FIELD | -fsz : 0;
r = xbcon(0, &sym, INT);
p = block(STREF, p, r, INT, 0, MKSUE(INT));
ecomp(buildtree(ASSIGN, stref(p), il->n));
if (fsz < 0)
fsz = -fsz;
} else {
if (ll->begsz + il->off > lastoff)
zbits(lastoff,
(ll->begsz + il->off) - lastoff);
if (fsz < 0) {
fsz = -fsz;
infld(il->off, fsz, il->n->n_lval);
} else
ninval(il->off, fsz, il->n);
tfree(il->n);
}
lastoff = ll->begsz + il->off + fsz;
}
}
if (csym->sclass == AUTO) {
clearbf(lastoff, tbit-lastoff);
} else
zbits(lastoff, tbit-lastoff);
}
/*
* process an initializer's left brace
*/
void
ilbrace()
{
#ifdef PCC_DEBUG
if (idebug)
printf("ilbrace()\n");
#endif
if (pstk == NULL)
return;
stkpush();
pstk->in_fl = 1; /* mark lbrace */
#ifdef PCC_DEBUG
if (idebug > 1)
prtstk(pstk);
#endif
}
/*
* called when a '}' is seen
*/
void
irbrace()
{
#ifdef PCC_DEBUG
if (idebug)
printf("irbrace()\n");
if (idebug > 2)
prtstk(pstk);
#endif
if (pstk == NULL)
return;
/* Got right brace, search for corresponding in the stack */
for (; pstk->in_prev != NULL; pstk = pstk->in_prev) {
if(!pstk->in_fl)
continue;
/* we have one now */
pstk->in_fl = 0; /* cancel { */
if (ISARY(pstk->in_t))
pstk->in_n = pstk->in_df->ddim;
else if (pstk->in_t == STRTY) {
while (pstk->in_lnk != NULL &&
pstk->in_lnk->snext != NULL)
pstk->in_lnk = pstk->in_lnk->snext;
}
stkpop();
return;
}
}
/*
* Create a new init stack based on given elements.
*/
static void
mkstack(NODE *p)
{
#ifdef PCC_DEBUG
if (idebug)
printf("mkstack: %p\n", p);
#endif
if (p == NULL)
return;
mkstack(p->n_left);
switch (p->n_op) {
case LB: /* Array index */
if (p->n_right->n_op != ICON)
cerror("mkstack");
if (!ISARY(pstk->in_t))
uerror("array indexing non-array");
pstk->in_n = p->n_right->n_lval;
nfree(p->n_right);
break;
case NAME:
if (pstk->in_lnk) {
for (; pstk->in_lnk; pstk->in_lnk = pstk->in_lnk->snext)
if (pstk->in_lnk->sname == (char *)p->n_sp)
break;
if (pstk->in_lnk == NULL)
uerror("member missing");
} else {
uerror("not a struct/union");
}
break;
default:
cerror("mkstack2");
}
nfree(p);
stkpush();
}
/*
* Initialize a specific element, as per C99.
*/
void
desinit(NODE *p)
{
int op = p->n_op;
if (pstk == NULL)
stkpush(); /* passed end of array */
while (pstk->in_prev && pstk->in_fl == 0)
pstk = pstk->in_prev; /* Empty stack */
if (ISSOU(pstk->in_t))
pstk->in_lnk = pstk->in_sym->ssue->sylnk;
mkstack(p); /* Setup for assignment */
/* pop one step if SOU, ilbrace will push */
if (op == NAME || op == LB)
pstk = pstk->in_prev;
#ifdef PCC_DEBUG
if (idebug > 1) {
printf("desinit e\n");
prtstk(pstk);
}
#endif
}
/*
* Convert a string to an array of char/wchar for asginit.
*/
static void
strcvt(NODE *p)
{
char *s;
int i;
for (s = p->n_sp->sname; *s != 0; ) {
if (*s++ == '\\') {
i = esccon(&s);
} else
i = (unsigned char)s[-1];
asginit(bcon(i));
}
tfree(p);
}
/*
* Do an assignment to a struct element.
*/
void
asginit(NODE *p)
{
int g;
#ifdef PCC_DEBUG
if (idebug)
printf("asginit %p\n", p);
if (idebug > 1 && p)
fwalk(p, eprint, 0);
#endif
/* convert string to array of char */
if (p && DEUNSIGN(p->n_type) == ARY+CHAR) {
/*
* ...but only if next element is ARY+CHAR, otherwise
* just fall through.
*/
/* HACKHACKHACK */
struct instk *is = pstk;
if (pstk == NULL)
stkpush();
while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
stkpush();
if (pstk->in_prev &&
DEUNSIGN(pstk->in_prev->in_t) == ARY+CHAR) {
pstk = pstk->in_prev;
if ((g = pstk->in_fl) == 0)
pstk->in_fl = 1; /* simulate ilbrace */
strcvt(p);
if (g == 0)
irbrace();
return;
} else
pstk = is; /* no array of char */
/* END HACKHACKHACK */
}
if (p == NULL) { /* only end of compound stmt */
irbrace();
} else /* assign next element */
scalinit(p);
}
#ifdef PCC_DEBUG
void
prtstk(struct instk *in)
{
int i, o = 0;
printf("init stack:\n");
for (; in != NULL; in = in->in_prev) {
for (i = 0; i < o; i++)
printf(" ");
printf("%p) '%s' ", in, in->in_sym->sname);
tprint(stdout, in->in_t, 0);
printf(" %s ", scnames(in->in_sym->sclass));
if (in->in_df && in->in_df->ddim)
printf("arydim=%d ", in->in_df->ddim);
printf("ninit=%d ", in->in_n);
if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t))
printf("stsize=%d ", in->in_sym->ssue->suesize);
if (in->in_fl) printf("{ ");
printf("soff=%d ", in->in_sym->soffset);
if (in->in_t == STRTY) {
if (in->in_lnk)
printf("curel %s ", in->in_lnk->sname);
else
printf("END struct");
}
printf("\n");
o++;
}
}
#endif
/*
* Do a simple initialization.
* At block 0, just print out the value, at higher levels generate
* appropriate code.
*/
void
simpleinit(struct symtab *sp, NODE *p)
{
/* May be an initialization of an array of char by a string */
if ((DEUNSIGN(p->n_type) == ARY+CHAR &&
DEUNSIGN(sp->stype) == ARY+CHAR) ||
(DEUNSIGN(p->n_type) == ARY+WCHAR_TYPE &&
DEUNSIGN(sp->stype) == ARY+WCHAR_TYPE)) {
/* Handle "aaa" as { 'a', 'a', 'a' } */
beginit(sp);
strcvt(p);
if (csym->sdf->ddim == NOOFFSET)
scalinit(bcon(0)); /* Null-term arrays */
endinit();
return;
}
switch (sp->sclass) {
case STATIC:
case EXTDEF:
p = optim(buildtree(ASSIGN, nametree(sp), p));
defloc(sp);
ninval(0, p->n_right->n_sue->suesize, p->n_right);
tfree(p);
break;
case AUTO:
case REGISTER:
if (ISARY(sp->stype))
cerror("no array init");
ecomp(buildtree(ASSIGN, nametree(sp), p));
break;
default:
uerror("illegal initialization");
}
}