* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / cc / ccom / init.c
blob17e6f9d92733f75ba65573268cdae32d607d31c8
1 /* $Id: init.c,v 1.62 2011/02/19 17:23:39 ragge Exp $ */
3 /*
4 * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se).
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
37 * Redistributions of source code and documentation must retain the above
38 * copyright notice, this list of conditions and the following disclaimer.
39 * Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed or owned by Caldera
45 * International, Inc.
46 * Neither the name of Caldera International, Inc. nor the names of other
47 * contributors may be used to endorse or promote products derived from
48 * this software without specific prior written permission.
50 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
51 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
55 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
60 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
64 #include "pass1.h"
65 #include <string.h>
68 * The following machine-dependent routines may be called during
69 * initialization:
71 * zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ.
72 * infld(CONSZ off, int fsz, CONSZ val)
73 * - sets the bitfield val starting at off and size fsz.
74 * ninval(CONSZ off, int fsz, NODE *)
75 * - prints an integer constant which may have
76 * a label associated with it, located at off and
77 * size fsz.
79 * Initialization may be of different kind:
80 * - Initialization at compile-time, all values are constants and laid
81 * out in memory. Static or extern variables outside functions.
82 * - Initialization at run-time, written to their values as code.
84 * Currently run-time-initialized variables are only initialized by using
85 * move instructions. An optimization might be to detect that it is
86 * initialized with constants and therefore copied from readonly memory.
90 * The base element(s) of an initialized variable is kept in a linked
91 * list, allocated while initialized.
93 * When a scalar is found, entries are popped of the instk until it's
94 * possible to find an entry for a new scalar; then onstk() is called
95 * to get the correct type and size of that scalar.
97 * If a right brace is found, pop the stack until a matching left brace
98 * were found while filling the elements with zeros. This left brace is
99 * also marking where the current level is for designated initializations.
101 * Position entries are increased when traversing back down into the stack.
105 * Good-to-know entries from symtab:
106 * soffset - # of bits from beginning of this structure.
110 * TO FIX:
111 * - Alignment of structs on like i386 char members.
114 int idebug;
117 * Struct used in array initialisation.
119 static struct instk {
120 struct instk *in_prev; /* linked list */
121 struct symtab *in_lnk; /* member in structure initializations */
122 struct symtab *in_sym; /* symtab index */
123 union dimfun *in_df; /* dimenston of array */
124 TWORD in_t; /* type for this level */
125 int in_n; /* number of arrays seen so far */
126 int in_fl; /* flag which says if this level is controlled by {} */
127 } *pstk, pbase;
129 static struct symtab *csym;
131 #ifdef PCC_DEBUG
132 static void prtstk(struct instk *in);
133 #endif
136 * Linked lists for initializations.
138 struct ilist {
139 struct ilist *next;
140 CONSZ off; /* bit offset of this entry */
141 int fsz; /* bit size of this entry */
142 NODE *n; /* node containing this data info */
145 struct llist {
146 SLIST_ENTRY(llist) next;
147 CONSZ begsz; /* bit offset of this entry */
148 struct ilist *il;
150 static SLIST_HEAD(llh, llist) lpole;
151 static CONSZ basesz;
152 static int numents; /* # of array entries allocated */
154 static struct initctx {
155 struct initctx *prev;
156 struct instk *pstk;
157 struct symtab *psym;
158 struct llh lpole;
159 CONSZ basesz;
160 int numents;
161 } *inilnk;
163 static struct ilist *
164 getil(struct ilist *next, CONSZ b, int sz, NODE *n)
166 struct ilist *il = tmpalloc(sizeof(struct ilist));
168 il->off = b;
169 il->fsz = sz;
170 il->n = n;
171 il->next = next;
172 return il;
176 * Allocate a new struct defining a block of initializers appended to the
177 * end of the llist. Return that entry.
179 static struct llist *
180 getll(void)
182 struct llist *ll;
184 ll = tmpalloc(sizeof(struct llist));
185 ll->begsz = numents * basesz;
186 ll->il = NULL;
187 SLIST_INSERT_LAST(&lpole, ll, next);
188 numents++;
189 return ll;
193 * Return structure containing off bitnumber.
194 * Allocate more entries, if needed.
196 static struct llist *
197 setll(OFFSZ off)
199 struct llist *ll = NULL;
201 /* Ensure that we have enough entries */
202 while (off >= basesz * numents)
203 ll = getll();
205 if (ll != NULL && ll->begsz <= off && ll->begsz + basesz > off)
206 return ll;
208 SLIST_FOREACH(ll, &lpole, next)
209 if (ll->begsz <= off && ll->begsz + basesz > off)
210 break;
211 return ll; /* ``cannot fail'' */
215 * beginning of initialization; allocate space to store initialized data.
216 * remember storage class for writeout in endinit().
217 * p is the newly declarated type.
219 void
220 beginit(struct symtab *sp)
222 struct initctx *ict;
223 struct instk *is = &pbase;
225 #ifdef PCC_DEBUG
226 if (idebug)
227 printf("beginit(%p), sclass %s\n", sp, scnames(sp->sclass));
228 #endif
230 if (pstk) {
231 #ifdef PCC_DEBUG
232 if (idebug)
233 printf("beginit: saving ctx pstk %p\n", pstk);
234 #endif
235 /* save old context */
236 ict = tmpalloc(sizeof(struct initctx));
237 ict->prev = inilnk;
238 inilnk = ict;
239 ict->pstk = pstk;
240 ict->psym = csym;
241 ict->lpole = lpole;
242 ict->basesz = basesz;
243 ict->numents = numents;
244 is = tmpalloc(sizeof(struct instk));
246 csym = sp;
248 numents = 0; /* no entries in array list */
249 if (ISARY(sp->stype)) {
250 basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->sap);
251 if (basesz == 0) {
252 uerror("array has incomplete type");
253 basesz = SZINT;
255 } else
256 basesz = tsize(DECREF(sp->stype), sp->sdf, sp->sap);
257 SLIST_INIT(&lpole);
259 /* first element */
260 if (ISSOU(sp->stype)) {
261 is->in_lnk = strmemb(sp->sap);
262 } else
263 is->in_lnk = NULL;
264 is->in_n = 0;
265 is->in_t = sp->stype;
266 is->in_sym = sp;
267 is->in_df = sp->sdf;
268 is->in_fl = 0;
269 is->in_prev = NULL;
270 pstk = is;
274 * Push a new entry on the initializer stack.
275 * The new entry will be "decremented" to the new sub-type of the previous
276 * entry when called.
277 * Popping of entries is done elsewhere.
279 static void
280 stkpush(void)
282 struct instk *is;
283 struct symtab *sq, *sp;
284 TWORD t;
286 if (pstk == NULL) {
287 sp = csym;
288 t = 0;
289 } else {
290 t = pstk->in_t;
291 sp = pstk->in_sym;
294 #ifdef PCC_DEBUG
295 if (idebug) {
296 printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass));
297 tprint(stdout, t, 0);
299 #endif
302 * Figure out what the next initializer will be, and push it on
303 * the stack. If this is an array, just decrement type, if it
304 * is a struct or union, extract the next element.
306 is = tmpalloc(sizeof(struct instk));
307 is->in_fl = 0;
308 is->in_n = 0;
309 if (pstk == NULL) {
310 /* stack empty */
311 is->in_lnk = ISSOU(sp->stype) ? strmemb(sp->sap) : NULL;
312 is->in_t = sp->stype;
313 is->in_sym = sp;
314 is->in_df = sp->sdf;
315 } else if (ISSOU(t)) {
316 sq = pstk->in_lnk;
317 if (sq == NULL) {
318 uerror("excess of initializing elements");
319 } else {
320 is->in_lnk = ISSOU(sq->stype) ? strmemb(sq->sap) : NULL;
321 is->in_t = sq->stype;
322 is->in_sym = sq;
323 is->in_df = sq->sdf;
325 } else if (ISARY(t)) {
326 is->in_lnk = ISSOU(DECREF(t)) ? strmemb(pstk->in_sym->sap) : 0;
327 is->in_t = DECREF(t);
328 is->in_sym = sp;
329 if (pstk->in_df->ddim != NOOFFSET && pstk->in_df->ddim &&
330 pstk->in_n >= pstk->in_df->ddim) {
331 werror("excess of initializing elements");
332 pstk->in_n--;
334 is->in_df = pstk->in_df+1;
335 } else
336 uerror("too many left braces");
337 is->in_prev = pstk;
338 pstk = is;
340 #ifdef PCC_DEBUG
341 if (idebug) {
342 printf(" newtype ");
343 tprint(stdout, is->in_t, 0);
344 printf("\n");
346 #endif
350 * pop down to either next level that can handle a new initializer or
351 * to the next braced level.
353 static void
354 stkpop(void)
356 #ifdef PCC_DEBUG
357 if (idebug)
358 printf("stkpop\n");
359 #endif
360 for (; pstk; pstk = pstk->in_prev) {
361 if (pstk->in_t == STRTY && pstk->in_lnk != NULL) {
362 pstk->in_lnk = pstk->in_lnk->snext;
363 if (pstk->in_lnk != NULL)
364 break;
366 if (ISSOU(pstk->in_t) && pstk->in_fl)
367 break; /* need } */
368 if (ISARY(pstk->in_t)) {
369 pstk->in_n++;
370 if (pstk->in_fl)
371 break;
372 if (pstk->in_df->ddim == NOOFFSET ||
373 pstk->in_n < pstk->in_df->ddim)
374 break; /* ger more elements */
377 #ifdef PCC_DEBUG
378 if (idebug > 1)
379 prtstk(pstk);
380 #endif
384 * Count how many elements an array may consist of.
386 static int
387 acalc(struct instk *is, int n)
389 if (is == NULL || !ISARY(is->in_t))
390 return 0;
391 return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n;
395 * Find current bit offset of the top element on the stack from
396 * the beginning of the aggregate.
398 static CONSZ
399 findoff(void)
401 struct instk *is;
402 OFFSZ off;
404 #ifdef PCC_DEBUG
405 if (ISARY(pstk->in_t))
406 cerror("findoff on bad type %x", pstk->in_t);
407 #endif
410 * Offset calculations. If:
411 * - previous type is STRTY, soffset has in-struct offset.
412 * - this type is ARY, offset is ninit*stsize.
414 for (off = 0, is = pstk; is; is = is->in_prev) {
415 if (is->in_prev && is->in_prev->in_t == STRTY)
416 off += is->in_sym->soffset;
417 if (ISARY(is->in_t)) {
418 /* suesize is the basic type, so adjust */
419 TWORD t = is->in_t;
420 OFFSZ o;
421 while (ISARY(t))
422 t = DECREF(t);
423 if (ISPTR(t)) {
424 o = SZPOINT(t); /* XXX use tsize() */
425 } else {
426 o = tsize(t, is->in_sym->sdf, is->in_sym->sap);
428 off += o * acalc(is, 1);
429 while (is->in_prev && ISARY(is->in_prev->in_t)) {
430 if (is->in_prev->in_prev &&
431 is->in_prev->in_prev->in_t == STRTY)
432 off += is->in_sym->soffset;
433 is = is->in_prev;
437 #ifdef PCC_DEBUG
438 if (idebug>1) {
439 printf("findoff: off %lld\n", off);
440 prtstk(pstk);
442 #endif
443 return off;
447 * Insert the node p with size fsz at position off.
448 * Bit fields are already dealt with, so a node of correct type
449 * with correct alignment and correct bit offset is given.
451 static void
452 nsetval(CONSZ off, int fsz, NODE *p)
454 struct llist *ll;
455 struct ilist *il;
457 if (idebug>1)
458 printf("setval: off %lld fsz %d p %p\n", off, fsz, p);
460 if (fsz == 0)
461 return;
463 ll = setll(off);
464 off -= ll->begsz;
465 if (ll->il == NULL) {
466 ll->il = getil(NULL, off, fsz, p);
467 } else {
468 il = ll->il;
469 if (il->off > off) {
470 ll->il = getil(ll->il, off, fsz, p);
471 } else {
472 for (il = ll->il; il->next; il = il->next)
473 if (il->off <= off && il->next->off > off)
474 break;
475 if (il->off == off) {
476 /* replace */
477 nfree(il->n);
478 il->n = p;
479 } else
480 il->next = getil(il->next, off, fsz, p);
486 * take care of generating a value for the initializer p
487 * inoff has the current offset (last bit written)
488 * in the current word being generated
489 * Returns the offset.
491 CONSZ
492 scalinit(NODE *p)
494 CONSZ woff;
495 NODE *q;
496 int fsz;
498 #ifdef PCC_DEBUG
499 if (idebug > 2) {
500 printf("scalinit(%p)\n", p);
501 fwalk(p, eprint, 0);
502 prtstk(pstk);
504 #endif
506 if (nerrors)
507 return 0;
509 p = optim(p);
511 #ifdef notdef /* leave to the target to decide if useable */
512 if (csym->sclass != AUTO && p->n_op != ICON &&
513 p->n_op != FCON && p->n_op != NAME)
514 cerror("scalinit not leaf");
515 #endif
517 /* Out of elements? */
518 if (pstk == NULL) {
519 uerror("excess of initializing elements");
520 return 0;
524 * Get to the simple type if needed.
526 while (ISSOU(pstk->in_t) || ISARY(pstk->in_t)) {
527 stkpush();
528 /* If we are doing auto struct init */
529 if (ISSOU(pstk->in_t) && ISSOU(p->n_type) &&
530 suemeq(pstk->in_sym->sap, p->n_ap))
531 break;
534 if (ISSOU(pstk->in_t) == 0) {
535 /* let buildtree do typechecking (and casting) */
536 q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_df,
537 pstk->in_sym->sap);
538 p = buildtree(ASSIGN, q, p);
539 nfree(p->n_left);
540 q = optim(p->n_right);
541 nfree(p);
542 } else
543 q = p;
545 woff = findoff();
547 /* bitfield sizes are special */
548 if (pstk->in_sym->sclass & FIELD)
549 fsz = -(pstk->in_sym->sclass & FLDSIZ);
550 else
551 fsz = (int)tsize(pstk->in_t, pstk->in_sym->sdf,
552 pstk->in_sym->sap);
554 nsetval(woff, fsz, q);
556 stkpop();
557 #ifdef PCC_DEBUG
558 if (idebug > 2) {
559 printf("scalinit e(%p)\n", q);
561 #endif
562 return woff;
566 * Generate code to insert a value into a bitfield.
568 static void
569 insbf(OFFSZ off, int fsz, int val)
571 struct symtab sym;
572 NODE *p, *r;
573 TWORD typ;
575 #ifdef PCC_DEBUG
576 if (idebug > 1)
577 printf("insbf: off %lld fsz %d val %d\n", off, fsz, val);
578 #endif
580 if (fsz == 0)
581 return;
583 /* small opt: do char instead of bf asg */
584 if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR)
585 typ = CHAR;
586 else
587 typ = INT;
588 /* Fake a struct reference */
589 p = buildtree(ADDROF, nametree(csym), NIL);
590 sym.stype = typ;
591 sym.squal = 0;
592 sym.sdf = 0;
593 sym.sap = MKAP(typ);
594 sym.soffset = (int)off;
595 sym.sclass = (char)(typ == INT ? FIELD | fsz : MOU);
596 r = xbcon(0, &sym, typ);
597 p = block(STREF, p, r, INT, 0, MKAP(INT));
598 ecode(buildtree(ASSIGN, stref(p), bcon(val)));
602 * Clear a bitfield, starting at off and size fsz.
604 static void
605 clearbf(OFFSZ off, OFFSZ fsz)
607 /* Pad up to the next even initializer */
608 if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) {
609 int ba = (int)(((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off);
610 if (ba > fsz)
611 ba = (int)fsz;
612 insbf(off, ba, 0);
613 off += ba;
614 fsz -= ba;
616 while (fsz >= SZCHAR) {
617 insbf(off, SZCHAR, 0);
618 off += SZCHAR;
619 fsz -= SZCHAR;
621 if (fsz)
622 insbf(off, fsz, 0);
626 * final step of initialization.
627 * print out init nodes and generate copy code (if needed).
629 void
630 endinit(void)
632 struct llist *ll;
633 struct ilist *il;
634 int fsz;
635 OFFSZ lastoff, tbit;
637 #ifdef PCC_DEBUG
638 if (idebug)
639 printf("endinit()\n");
640 #endif
642 if (csym->sclass != AUTO)
643 defloc(csym);
645 /* Calculate total block size */
646 if (ISARY(csym->stype) && csym->sdf->ddim == NOOFFSET) {
647 tbit = numents*basesz; /* open-ended arrays */
648 csym->sdf->ddim = numents;
649 if (csym->sclass == AUTO) { /* Get stack space */
650 csym->soffset = NOOFFSET;
651 oalloc(csym, &autooff);
653 } else
654 tbit = tsize(csym->stype, csym->sdf, csym->sap);
656 /* Traverse all entries and print'em out */
657 lastoff = 0;
658 SLIST_FOREACH(ll, &lpole, next) {
659 for (il = ll->il; il; il = il->next) {
660 #ifdef PCC_DEBUG
661 if (idebug > 1) {
662 printf("off %lld size %d val %lld type ",
663 ll->begsz+il->off, il->fsz, il->n->n_lval);
664 tprint(stdout, il->n->n_type, 0);
665 printf("\n");
667 #endif
668 fsz = il->fsz;
669 if (csym->sclass == AUTO) {
670 struct symtab sym;
671 NODE *p, *r, *n;
673 if (ll->begsz + il->off > lastoff)
674 clearbf(lastoff,
675 (ll->begsz + il->off) - lastoff);
677 /* Fake a struct reference */
678 p = buildtree(ADDROF, nametree(csym), NIL);
679 n = il->n;
680 sym.stype = n->n_type;
681 sym.squal = n->n_qual;
682 sym.sdf = n->n_df;
683 sym.sap = n->n_ap;
684 sym.soffset = (int)(ll->begsz + il->off);
685 sym.sclass = (char)(fsz < 0 ? FIELD | -fsz : 0);
686 r = xbcon(0, &sym, INT);
687 p = block(STREF, p, r, INT, 0, MKAP(INT));
688 ecomp(buildtree(ASSIGN, stref(p), il->n));
689 if (fsz < 0)
690 fsz = -fsz;
692 } else {
693 if (ll->begsz + il->off > lastoff)
694 zbits(lastoff,
695 (ll->begsz + il->off) - lastoff);
696 if (fsz < 0) {
697 fsz = -fsz;
698 infld(il->off, fsz, il->n->n_lval);
699 } else
700 ninval(il->off, fsz, il->n);
701 tfree(il->n);
703 lastoff = ll->begsz + il->off + fsz;
706 if (csym->sclass == AUTO) {
707 clearbf(lastoff, tbit-lastoff);
708 } else
709 zbits(lastoff, tbit-lastoff);
711 endictx();
714 void
715 endictx(void)
717 struct initctx *ict = inilnk;
719 if (ict == NULL)
720 return;
722 pstk = ict->pstk;
723 csym = ict->psym;
724 lpole = ict->lpole;
725 basesz = ict->basesz;
726 numents = ict->numents;
727 inilnk = inilnk->prev;
728 #ifdef PCC_DEBUG
729 if (idebug)
730 printf("endinit: restoring ctx pstk %p\n", pstk);
731 #endif
735 * process an initializer's left brace
737 void
738 ilbrace()
741 #ifdef PCC_DEBUG
742 if (idebug)
743 printf("ilbrace()\n");
744 #endif
746 if (pstk == NULL)
747 return;
749 stkpush();
750 pstk->in_fl = 1; /* mark lbrace */
751 #ifdef PCC_DEBUG
752 if (idebug > 1)
753 prtstk(pstk);
754 #endif
758 * called when a '}' is seen
760 void
761 irbrace()
763 #ifdef PCC_DEBUG
764 if (idebug)
765 printf("irbrace()\n");
766 if (idebug > 2)
767 prtstk(pstk);
768 #endif
770 if (pstk == NULL)
771 return;
773 /* Got right brace, search for corresponding in the stack */
774 for (; pstk->in_prev != NULL; pstk = pstk->in_prev) {
775 if(!pstk->in_fl)
776 continue;
778 /* we have one now */
780 pstk->in_fl = 0; /* cancel { */
781 if (ISARY(pstk->in_t))
782 pstk->in_n = pstk->in_df->ddim;
783 else if (pstk->in_t == STRTY) {
784 while (pstk->in_lnk != NULL &&
785 pstk->in_lnk->snext != NULL)
786 pstk->in_lnk = pstk->in_lnk->snext;
788 stkpop();
789 return;
794 * Create a new init stack based on given elements.
796 static void
797 mkstack(NODE *p)
800 #ifdef PCC_DEBUG
801 if (idebug) {
802 printf("mkstack: %p\n", p);
803 if (idebug > 1 && p)
804 fwalk(p, eprint, 0);
806 #endif
808 if (p == NULL)
809 return;
810 mkstack(p->n_left);
812 switch (p->n_op) {
813 case LB: /* Array index */
814 if (p->n_right->n_op != ICON)
815 cerror("mkstack");
816 if (!ISARY(pstk->in_t))
817 uerror("array indexing non-array");
818 pstk->in_n = (int)p->n_right->n_lval;
819 nfree(p->n_right);
820 break;
822 case NAME:
823 if (pstk->in_lnk) {
824 for (; pstk->in_lnk; pstk->in_lnk = pstk->in_lnk->snext)
825 if (pstk->in_lnk->sname == (char *)p->n_sp)
826 break;
827 if (pstk->in_lnk == NULL)
828 uerror("member missing");
829 } else {
830 uerror("not a struct/union");
832 break;
833 default:
834 cerror("mkstack2");
836 nfree(p);
837 stkpush();
842 * Initialize a specific element, as per C99.
844 void
845 desinit(NODE *p)
847 int op = p->n_op;
849 if (pstk == NULL)
850 stkpush(); /* passed end of array */
851 while (pstk->in_prev && pstk->in_fl == 0)
852 pstk = pstk->in_prev; /* Empty stack */
854 if (ISSOU(pstk->in_t))
855 pstk->in_lnk = strmemb(pstk->in_sym->sap);
857 mkstack(p); /* Setup for assignment */
859 /* pop one step if SOU, ilbrace will push */
860 if (op == NAME || op == LB)
861 pstk = pstk->in_prev;
863 #ifdef PCC_DEBUG
864 if (idebug > 1) {
865 printf("desinit e\n");
866 prtstk(pstk);
868 #endif
872 * Convert a string to an array of char/wchar for asginit.
874 static void
875 strcvt(NODE *p)
877 NODE *q = p;
878 char *s;
879 int i;
881 #ifdef mach_arm
882 /* XXX */
883 if (p->n_op == UMUL && p->n_left->n_op == ADDROF)
884 p = p->n_left->n_left;
885 #endif
887 for (s = p->n_sp->sname; *s != 0; ) {
888 if (*s++ == '\\') {
889 i = esccon(&s);
890 } else
891 i = (unsigned char)s[-1];
892 asginit(bcon(i));
894 tfree(q);
898 * Do an assignment to a struct element.
900 void
901 asginit(NODE *p)
903 int g;
905 #ifdef PCC_DEBUG
906 if (idebug)
907 printf("asginit %p\n", p);
908 if (idebug > 1 && p)
909 fwalk(p, eprint, 0);
910 #endif
912 /* convert string to array of char/wchar */
913 if (p && (DEUNSIGN(p->n_type) == ARY+CHAR ||
914 p->n_type == ARY+WCHAR_TYPE)) {
915 TWORD t;
917 t = p->n_type == ARY+WCHAR_TYPE ? ARY+WCHAR_TYPE : ARY+CHAR;
919 * ...but only if next element is ARY+CHAR, otherwise
920 * just fall through.
923 /* HACKHACKHACK */
924 struct instk *is = pstk;
926 if (pstk == NULL)
927 stkpush();
928 while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
929 stkpush();
930 if (pstk->in_prev &&
931 (DEUNSIGN(pstk->in_prev->in_t) == t ||
932 pstk->in_prev->in_t == t)) {
933 pstk = pstk->in_prev;
934 if ((g = pstk->in_fl) == 0)
935 pstk->in_fl = 1; /* simulate ilbrace */
937 strcvt(p);
938 if (g == 0)
939 irbrace(); /* will fill with zeroes */
940 return;
941 } else
942 pstk = is; /* no array of char */
943 /* END HACKHACKHACK */
946 if (p == NULL) { /* only end of compound stmt */
947 irbrace();
948 } else /* assign next element */
949 scalinit(p);
952 #ifdef PCC_DEBUG
953 void
954 prtstk(struct instk *in)
956 int i, o = 0;
958 printf("init stack:\n");
959 for (; in != NULL; in = in->in_prev) {
960 for (i = 0; i < o; i++)
961 printf(" ");
962 printf("%p) '%s' ", in, in->in_sym->sname);
963 tprint(stdout, in->in_t, 0);
964 printf(" %s ", scnames(in->in_sym->sclass));
965 if (in->in_df /* && in->in_df->ddim */)
966 printf("arydim=%d ", in->in_df->ddim);
967 printf("ninit=%d ", in->in_n);
968 if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t))
969 printf("stsize=%d ",
970 (int)tsize(in->in_t, in->in_df, in->in_sym->sap));
971 if (in->in_fl) printf("{ ");
972 printf("soff=%d ", in->in_sym->soffset);
973 if (in->in_t == STRTY) {
974 if (in->in_lnk)
975 printf("curel %s ", in->in_lnk->sname);
976 else
977 printf("END struct");
979 printf("\n");
980 o++;
983 #endif
986 * Do a simple initialization.
987 * At block 0, just print out the value, at higher levels generate
988 * appropriate code.
990 void
991 simpleinit(struct symtab *sp, NODE *p)
993 NODE *q, *r, *nt;
994 TWORD t;
995 int sz;
997 /* May be an initialization of an array of char by a string */
998 if ((DEUNSIGN(p->n_type) == ARY+CHAR &&
999 DEUNSIGN(sp->stype) == ARY+CHAR) ||
1000 (DEUNSIGN(p->n_type) == DEUNSIGN(ARY+WCHAR_TYPE) &&
1001 DEUNSIGN(sp->stype) == DEUNSIGN(ARY+WCHAR_TYPE))) {
1002 /* Handle "aaa" as { 'a', 'a', 'a' } */
1003 beginit(sp);
1004 strcvt(p);
1005 if (csym->sdf->ddim == NOOFFSET)
1006 scalinit(bcon(0)); /* Null-term arrays */
1007 endinit();
1008 return;
1011 nt = nametree(sp);
1012 switch (sp->sclass) {
1013 case STATIC:
1014 case EXTDEF:
1015 q = nt;
1016 #ifndef NO_COMPLEX
1017 if (ANYCX(q) || ANYCX(p)) {
1018 r = cxop(ASSIGN, q, p);
1019 /* XXX must unwind the code generated here */
1020 /* We can rely on correct code generated */
1021 p = r->n_left->n_right->n_left;
1022 r->n_left->n_right->n_left = bcon(0);
1023 tfree(r);
1024 defloc(sp);
1025 r = p->n_left->n_right;
1026 sz = (int)tsize(r->n_type, r->n_df, r->n_ap);
1027 ninval(0, sz, r);
1028 ninval(0, sz, p->n_right->n_right);
1029 tfree(p);
1030 break;
1032 #endif
1033 p = optim(buildtree(ASSIGN, nt, p));
1034 defloc(sp);
1035 q = p->n_right;
1036 t = q->n_type;
1037 sz = (int)tsize(t, q->n_df, q->n_ap);
1038 ninval(0, sz, q);
1039 tfree(p);
1040 break;
1042 case AUTO:
1043 case REGISTER:
1044 if (ISARY(sp->stype))
1045 cerror("no array init");
1046 q = nt;
1047 #ifndef NO_COMPLEX
1049 if (ANYCX(q) || ANYCX(p))
1050 r = cxop(ASSIGN, q, p);
1051 else
1052 #endif
1053 r = buildtree(ASSIGN, q, p);
1054 ecomp(r);
1055 break;
1057 default:
1058 uerror("illegal initialization");