Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120322185140

Diff

Diff from 1.2 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cxxcom/pftn.c

Annotated File View

plunky
1.2
1 /*      $Id: pftn.c,v 1.2 2012/03/22 18:51:40 plunky Exp $      */
ragge
1.1
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 /*
27  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  *
33  * Redistributions of source code and documentation must retain the above
34  * copyright notice, this list of conditions and the following disclaimer.
35  * Redistributions in binary form must reproduce the above copyright
36  * notice, this list of conditionsand the following disclaimer in the
37  * documentation and/or other materials provided with the distribution.
38  * All advertising materials mentioning features or use of this software
39  * must display the following acknowledgement:
40  *      This product includes software developed or owned by Caldera
41  *      International, Inc.
42  * Neither the name of Caldera International, Inc. nor the names of other
43  * contributors may be used to endorse or promote products derived from
44  * this software without specific prior written permission.
45  *
46  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
47  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
48  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
51  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
55  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
56  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
57  * POSSIBILITY OF SUCH DAMAGE.
58  */
59
60 /*
61  * Many changes from the 32V sources, among them:
62  * - New symbol table manager (moved to another file).
63  * - Prototype saving/checks.
64  */
65
66 # include "pass1.h"
67
68 #include "cgram.h"
69
70 struct symtab *cftnsp;
71 int arglistcntdimfuncnt;      /* statistics */
72 int symtabcntsuedefcnt;       /* statistics */
73 int autooff,            /* the next unused automatic offset */
74     maxautooff,         /* highest used automatic offset in function */
75     argoff;             /* the next unused argument offset */
76 int retlab = NOLAB;     /* return label for subroutine */
77 int brklab;
78 int contlab;
79 int flostat;
80 int blevel;
81 int reachedprolab;
82
83 struct params;
84
85 #define MKTY(p, t, d, s) r = talloc(); *r = *p; \
86         r = argcast(rtds); *p = *rnfree(r);
87
88 /*
89  * Linked list stack while reading in structs.
90  */
91 struct rstack {
92         struct  rstack *rnext;
93         int     rsou;
94         int     rstr;
95         struct  symtab *rsym;
96 //      struct  symtab *rb;
97         struct  attr *ap;
98         int     flags;
99 #define LASTELM 1
100 } *rpole;
101
102 /*
103  * Linked list for parameter (and struct elements) declaration.
104  */
105 static struct params {
106         struct params *next, *prev;
107         struct symtab *sym;
108 } *lpole, *lparam;
109 static int nparams;
110
111 /* defines used for getting things off of the initialization stack */
112
113 NODE *arrstk[10];
114 int arrstkp;
115 static int intcompare;
116 NODE *parlink;
117
118 void fixtype(NODE *pint class);
119 int fixclass(int classTWORD type);
120 static void dynalloc(struct symtab *pint *poff);
121 static void evalidx(struct symtab *p);
122 int isdyn(struct symtab *p);
123 void inforce(OFFSZ n);
124 void vfdalign(int n);
125 static void ssave(struct symtab *);
126 #ifdef PCC_DEBUG
127 static void alprint(union arglist *alint in);
128 #endif
129 static void lcommadd(struct symtab *sp);
130 static NODE *mkcmplx(NODE *pTWORD dt);
131 extern int fun_inline;
132
133 /*
134  * Declaration of an identifier.  Handles redeclarations, hiding,
135  * incomplete types and forward declarations.
136  *
137  * q is a TYPE node setup after parsing with n_type, n_df and n_ap.
138  * n_sp is a pointer to the not-yet initalized symbol table entry
139  * unless it's a redeclaration or supposed to hide a variable.
140  */
141
142 void
143 defid(NODE *qint class)
144 {
145         struct attr *ap;
146         struct symtab *p;
147         TWORD typequal;
148         TWORD stpstq;
149         int scl;
150         union dimfun *dsym, *ddef;
151         int slevtempchanged;
152
153         if (q == NIL)
154                 return;  /* an error was detected */
155
156         p = q->n_sp;
157
158         if (p->sname == NULL)
159                 cerror("defining null identifier");
160
161 #ifdef PCC_DEBUG
162         if (ddebug) {
163                 printf("defid(%s (%p), "p->snamep);
164                 tprint(stdoutq->n_typeq->n_qual);
165                 printf(", %s, (%p)), level %d\n\t"scnames(class),
166                     q->n_dfblevel);
167                 dump_attr(q->n_ap);
168         }
169 #endif
170
171         fixtype(qclass);
172
173         type = q->n_type;
174         qual = q->n_qual;
175         class = fixclass(classtype);
176
177         stp = p->stype;
178         stq = p->squal;
179         slev = p->slevel;
180
181 #ifdef PCC_DEBUG
182         if (ddebug) {
183                 printf("        modified to ");
184                 tprint(stdouttypequal);
185                 printf(", %s\n"scnames(class));
186                 printf("        previous def'n: ");
187                 tprint(stdoutstpstq);
188                 printf(", %s, (%p,%p)), level %d\n",
189                     scnames(p->sclass), p->sdfp->sapslev);
190         }
191 #endif
192
193         if (blevel == 1) {
194                 switch (class) {
195                 default:
196                         if (!(class&FIELD) && !ISFTN(type))
197                                 uerror("declared argument %s missing",
198                                     p->sname );
199                 case MOS:
200                 case MOU:
201                         cerror("field5");
202                 case TYPEDEF:
203                 case PARAM:
204                         ;
205                 }
206         }
207
208         if (stp == UNDEF)
209                 goto enter/* New symbol */
210
211         if (type != stp)
212                 goto mismatch;
213
214         if (blevel > slev && (class == AUTO || class == REGISTER))
215                 /* new scope */
216                 goto mismatch;
217
218         /*
219          * test (and possibly adjust) dimensions.
220          * also check that prototypes are correct.
221          */
222         dsym = p->sdf;
223         ddef = q->n_df;
224         changed = 0;
225         for (temp = typetemp & TMASKtemp = DECREF(temp)) {
226                 if (ISARY(temp)) {
227                         if (dsym->ddim == NOOFFSET) {
228                                 dsym->ddim = ddef->ddim;
229                                 changed = 1;
230                         } else if (ddef->ddim != NOOFFSET &&
231                             dsym->ddim!=ddef->ddim) {
232                                 goto mismatch;
233                         }
234                         ++dsym;
235                         ++ddef;
236                 } else if (ISFTN(temp)) {
237                         /* add a late-defined prototype here */
238                         if (cftnsp == NULL && dsym->dfun == NULL)
239                                 dsym->dfun = ddef->dfun;
240                         if (!oldstyle && ddef->dfun != NULL &&
241                             chkftn(dsym->dfunddef->dfun))
242                                 uerror("declaration doesn't match prototype");
243                         dsym++, ddef++;
244                 }
245         }
246 #ifdef STABS
247         if (changed && gflag)
248                 stabs_chgsym(p); /* symbol changed */
249 #endif
250
251         /* check that redeclarations are to the same structure */
252         if (temp == STRTY || temp == UNIONTY) {
253                 if (strmemb(p->sap) != strmemb(q->n_ap))
254                         goto mismatch;
255         }
256
257         scl = p->sclass;
258
259 #ifdef PCC_DEBUG
260         if (ddebug)
261                 printf("        previous class: %s\n"scnames(scl));
262 #endif
263
264         /*
265          * Its allowed to add attributes to existing declarations.
266          * Be careful though not to trash existing attributes.
267          * XXX - code below is probably not correct.
268          */
269         if (p->sap && p->sap->atype <= ATTR_MAX) {
270                 /* nothing special, just overwrite */
271                 p->sap = q->n_ap;
272         } else {
273                 if (p->slevel == blevel) {
274                         for (ap = q->n_apapap = ap->next) {
275                                 if (ap->atype > ATTR_MAX)
276                                         p->sap = attr_add(p->sapattr_dup(ap3));
277                         }
278                 } else
279                         p->sap = q->n_ap;
280         }
281
282         if (class & FIELD)
283                 cerror("field1");
284         switch(class) {
285
286         case EXTERN:
287                 if (pragma_renamed)
288                         p->soname = pragma_renamed;
289                 pragma_renamed = NULL;
290                 switchscl ){
291                 case STATIC:
292                 case USTATIC:
293                         ifslev==0 )
294                                 goto done;
295                         break;
296                 case EXTDEF:
297                 case EXTERN:
298                         goto done;
299                 case SNULL:
300                         if (p->sflags & SINLINE) {
301                                 p->sclass = EXTDEF;
302                                 inline_ref(p);
303                                 goto done;
304                         }
305                         break;
306                 }
307                 break;
308
309         case STATIC:
310                 if (scl==USTATIC || (scl==EXTERN && blevel==0)) {
311                         p->sclass = STATIC;
312                         goto done;
313                 }
314                 if (changed || (scl == STATIC && blevel == slev))
315                         goto done/* identical redeclaration */
316                 break;
317
318         case USTATIC:
319                 if (scl==STATIC || scl==USTATIC)
320                         goto done;
321                 break;
322
323         case TYPEDEF:
324                 if (scl == class)
325                         goto done;
326                 break;
327
328         case MOU:
329         case MOS:
330                 cerror("field6");
331
332         case EXTDEF:
333                 switch (scl) {
334                 case EXTERN:
335                         p->sclass = EXTDEF;
336                         goto done;
337                 case USTATIC:
338                         p->sclass = STATIC;
339                         goto done;
340                 case SNULL:
341                         /*
342                          * Handle redeclarations of inlined functions.
343                          * This is allowed if the previous declaration is of
344                          * type gnu_inline.
345                          */
346                         if (attr_find(p->sapGCC_ATYP_GNU_INLINE))
347                                 goto done;
348                         break;
349                 }
350                 break;
351
352         case AUTO:
353         case REGISTER:
354                 break;  /* mismatch.. */
355         case SNULL:
356                 if (fun_inline && ISFTN(type))
357                         goto done;
358                 break;
359         }
360
361         mismatch:
362
363         /*
364          * Only allowed for automatic variables.
365          */
366         if (blevel <= slev || class == EXTERN) {
367                 uerror("redeclaration of %s"p->sname);
368                 return;
369         }
370         q->n_sp = p = hide(p);
371
372         enter:  /* make a new entry */
373
374 #ifdef PCC_DEBUG
375         if(ddebug)
376                 printf("        new entry made\n");
377 #endif
378         if (type < BTMASK && (ap = attr_find(q->n_apGCC_ATYP_MODE))) {
379                 type = ENUNSIGN(ap->iarg(0));
380                 if (type == XTYPE)
381                         uerror("fix XTYPE basetyp");
382         }
383         p->stype = type;
384         p->squal = qual;
385         p->sclass = (char)class;
386         p->slevel = (char)blevel;
387         p->soffset = NOOFFSET;
388 #if 0
389         if (class != TYPEDEF && blevel == 0)
390                 p->soname = decoratename(pNM_NORMAL);
391 #endif
392         if (q->n_ap)
393                 p->sap = attr_add(q->n_app->sap);
394
395         /* copy dimensions */
396         p->sdf = q->n_df;
397         /* Do not save param info for old-style functions */
398         if (ISFTN(type) && oldstyle)
399                 p->sdf->dfun = NULL;
400
401         if (arrstkp)
402                 evalidx(p);
403
404         /* allocate offsets */
405         if (class&FIELD) {
406                 cerror("field2");  /* new entry */
407         } else switch (class) {
408
409         case REGISTER:
410                 cerror("register var");
411
412         case AUTO:
413                 if (isdyn(p)) {
414                         p->sflags |= SDYNARRAY;
415                         dynalloc(p, &autooff);
416                 } else
417                         oalloc(p, &autooff);
418                 break;
419
420         case PARAM:
421                 if (q->n_type != FARG)
422                         oalloc(p, &argoff);
423                 break;
424                 
425         case STATIC:
426         case EXTDEF:
427         case EXTERN:
428                 p->soffset = getlab();
429                 if (pragma_renamed)
430                         p->soname = pragma_renamed;
431                 pragma_renamed = NULL;
432                 break;
433
434         case MOU:
435         case MOS:
436                 cerror("field7");
437         case SNULL:
438 #ifdef notdef
439                 if (fun_inline) {
440                         p->slevel = 1;
441                         p->soffset = getlab();
442                 }
443 #endif
444                 break;
445         }
446
447 #ifdef STABS
448         if (gflag && p->stype != FARG)
449                 stabs_newsym(p);
450 #endif
451
452 done:
453         cxxsetname(p);
454         fixdef(p);      /* Leave last word to target */
455 #ifndef HAVE_WEAKREF
456         {
457                 struct attr *at;
458
459                 /* Refer renamed function */
460                 if ((at = attr_find(p->sapGCC_ATYP_WEAKREF)))
461                         p->soname = at->sarg(0);
462         }
463 #endif
464 #ifdef PCC_DEBUG
465         if (ddebug) {
466                 printf"       sdf, offset: %p, %d\n\t",
467                     p->sdfp->soffset);
468                 dump_attr(p->sap);
469         }
470 #endif
471 }
472
473 void
474 ssave(struct symtab *sym)
475 {
476         struct params *p;
477
478         p = tmpalloc(sizeof(struct params));
479         p->next = NULL;
480         p->sym = sym;
481
482         if ((p->prev = lparam) == NULL)
483                 lpole = p;
484         else
485                 lparam->next = p;
486         lparam = p;
487 }
488
489 /*
490  * end of function
491  */
492 void
493 ftnend()
494 {
495         struct attr *gc, *gd;
496         extern NODE *cftnod;
497         extern struct savbc *savbc;
498         extern struct swdef *swpole;
499         extern int tvaloff;
500         char *c;
501
502         if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
503                 plabel(retlab);
504                 if (cftnod)
505                         ecomp(buildtree(FORCEcftnodNIL));
506                 efcode(); /* struct return handled here */
507                 if ((c = cftnsp->soname) == NULL)
508                         c = addname(exname(cftnsp->sname));
509                 SETOFF(maxautooffALCHAR);
510                 send_passt(IP_EPILOGmaxautooff/SZCHARc,
511                     cftnsp->stypecftnsp->sclass == EXTDEFretlabtvaloff);
512         }
513
514         cftnod = NIL;
515         tcheck();
516         brklab = contlab = retlab = NOLAB;
517         flostat = 0;
518         if (nerrors == 0) {
519                 if (savbc != NULL)
520                         cerror("bcsave error");
521                 if (lparam != NULL)
522                         cerror("parameter reset error");
523                 if (swpole != NULL)
524                         cerror("switch error");
525         }
526         if (cftnsp) {
527                 gc = attr_find(cftnsp->sapGCC_ATYP_CONSTRUCTOR);
528                 gd = attr_find(cftnsp->sapGCC_ATYP_DESTRUCTOR);
529                 if (gc || gd) {
530                         struct symtab sts = *cftnsp;
531                         NODE *p;
532                         sts.stype = INCREF(sts.stype);
533                         p = nametree(&sts);
534                         p->n_op = ICON;
535                         if (gc) {
536                                 locctr(CTORS, &sts);
537                                 inval(0SZPOINT(0), p);
538                         }
539                         if (gd) {
540                                 locctr(DTORS, &sts);
541                                 inval(0SZPOINT(0), p);
542                         }
543                         tfree(p);
544                 }
545         }
546         savbc = NULL;
547         lparam = NULL;
548         cftnsp = NULL;
549         maxautooff = autooff = AUTOINIT;
550         reached = 1;
551
552         if (isinlining)
553                 inline_end();
554         inline_prtout();
555
556         tmpfree(); /* Release memory resources */
557 }
558
559 static struct symtab nulsym = {
560         NULLNULLNULL0000"null""null"INT0NULLNULL
561 };
562
563 void
564 dclargs()
565 {
566         union dimfun *df;
567         union arglist *al, *al2, *alb;
568         struct params *a;
569         struct symtab *p, **parr = NULL/* XXX gcc */
570         int i;
571
572         /*
573          * Deal with fun(void) properly.
574          */
575         if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID)
576                 goto done;
577
578         if (cftnsp->sdown && cftnsp->sdown->sclass != NSPACE) {
579                 /* first arg is a pointer to the "sprev" class */
580                 p = cxxstrvar(cftnsp->sdown);
581                 ssave(p);
582                 nparams++;
583         }
584         /*
585          * Generate a list for bfcode().
586          * Parameters were pushed in reverse order.
587          */
588         if (nparams != 0)
589                 parr = tmpalloc(sizeof(struct symtab *) * nparams);
590
591         if (nparams)
592             for (a = lparami = 0a != NULLa = a->prev) {
593                 p = a->sym;
594                 parr[i++] = p;
595                 if (p == NULL) {
596                         uerror("parameter %d name missing"i);
597                         p = &nulsym/* empty symtab */
598                 }
599                 if (p->stype == FARG)
600                         p->stype = INT;
601                 if (ISARY(p->stype)) {
602                         p->stype += (PTR-ARY);
603                         p->sdf++;
604                 } else if (ISFTN(p->stype)) {
605                         werror("function declared as argument");
606                         p->stype = INCREF(p->stype);
607                 }
608 #ifdef STABS
609                 if (gflag)
610                         stabs_newsym(p);
611 #endif
612         }
613         if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
614                 /*
615                  * Check against prototype of oldstyle function.
616                  */
617                 alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
618                 for (i = 0i < nparamsi++) {
619                         TWORD type = parr[i]->stype;
620                         (al2++)->type = type;
621                         if (ISSOU(BTYPE(type)))
622                                 (al2++)->sap = parr[i]->sap;
623                         while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
624                                 type = DECREF(type);
625                         if (type > BTMASK)
626                                 (al2++)->df = parr[i]->sdf;
627                 }
628                 al2->type = TNULL;
629                 intcompare = 1;
630                 if (chkftn(alalb))
631                         uerror("function doesn't match prototype");
632                 intcompare = 0;
633
634         }
635
636         if (oldstyle && nparams) {
637                 /* Must recalculate offset for oldstyle args here */
638                 argoff = ARGINIT;
639                 for (i = 0i < nparamsi++) {
640                         parr[i]->soffset = NOOFFSET;
641                         oalloc(parr[i], &argoff);
642                 }
643         }
644
645 done:   autooff = AUTOINIT;
646
647         plabel(prolab); /* after prolog, used in optimization */
648         retlab = getlab();
649         bfcode(parrnparams);
650         if (fun_inline &&
651             (xinline || attr_find(cftnsp->sapGCC_ATYP_ALW_INL)))
652                 inline_args(parrnparams);
653         plabel(getlab()); /* used when spilling */
654         if (parlink)
655                 ecomp(parlink);
656         parlink = NIL;
657         lparam = NULL;
658         nparams = 0;
659         symclear(1);    /* In case of function pointer args */
660 }
661
662 /*
663  * basic attributes for structs and enums
664  */
665 static struct attr *
666 seattr(void)
667 {
668         return attr_add(attr_new(GCC_ATYP_ALIGNED4), attr_new(ATTR_STRUCT2));
669 }
670
671 /*
672  * Struct/union/enum symtab construction.
673  */
674 static void
675 defstr(struct symtab *spint class)
676 {
677         sp->sclass = (char)class;
678         if (class == STNAME || class == CLNAME)
679                 sp->stype = STRTY;
680         else if (class == UNAME)
681                 sp->stype = UNIONTY;
682         else if (class == ENAME)
683                 sp->stype = ENUMTY;
684 }
685
686 /*
687  * Declare a struct/union/enum tag.
688  * If not found, create a new tag with UNDEF type.
689  */
690 static struct symtab *
691 deftag(char *nameint class)
692 {
693         struct symtab *sp;
694
695         if ((sp = cxxdclstr(name))->sap == NULL) {
696                 /* New tag */
697                 defstr(spclass);
698         } else if (sp->sclass != class)
699                 uerror("tag %s redeclared"name);
700         return sp;
701 }
702
703 /*
704  * reference to a structure or union, with no definition
705  */
706 NODE *
707 rstruct(char *tagint soru)
708 {
709         struct symtab *sp;
710
711         sp = deftag(tagsoru);
712         if (sp->sap == NULL)
713                 sp->sap = seattr();
714         return mkty(sp->stype0sp->sap);
715 }
716
717 static int enumlowenumhigh;
718 int enummer;
719
720 /*
721  * Declare a member of enum.
722  */
723 void
724 moedef(char *name)
725 {
726         struct symtab *sp;
727
728         sp = lookup(nameSNORMAL);
729         if (sp->stype == UNDEF || (sp->slevel < blevel)) {
730                 if (sp->stype != UNDEF)
731                         sp = hide(sp);
732                 sp->stype = INT/* always */
733                 sp->sclass = MOE;
734                 sp->soffset = enummer;
735         } else
736                 uerror("%s redeclared"name);
737         if (enummer < enumlow)
738                 enumlow = enummer;
739         if (enummer > enumhigh)
740                 enumhigh = enummer;
741         enummer++;
742 }
743
744 /*
745  * Declare an enum tag.  Complain if already defined.
746  */
747 struct symtab *
748 enumhd(char *name)
749 {
750         struct attr *ap;
751         struct symtab *sp;
752
753         enummer = enumlow = enumhigh = 0;
754         if (name == NULL)
755                 return NULL;
756
757         sp = deftag(nameENAME);
758         if (sp->stype != ENUMTY) {
759                 if (sp->slevel == blevel)
760                         uerror("%s redeclared"name);
761                 sp = hide(sp);
762                 defstr(spENAME);
763         }
764         if (sp->sap == NULL)
765                 ap = sp->sap = attr_new(ATTR_STRUCT4);
766         else
767                 ap = attr_find(sp->sapATTR_STRUCT);
768         ap->amlist = sp;
769         return sp;
770 }
771
772 /*
773  * finish declaration of an enum
774  */
775 NODE *
776 enumdcl(struct symtab *sp)
777 {
778         NODE *p;
779         TWORD t;
780
781 #ifdef ENUMSIZE
782         t = ENUMSIZE(enumhighenumlow);
783 #else
784         t = ctype(enumlow < 0 ? INT : UNSIGNED);
785 #ifdef notdef
786         if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR)
787                 t = ctype(CHAR);
788         else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT)
789                 t = ctype(SHORT);
790         else
791                 t = ctype(INT);
792 #endif
793 #endif
794         
795         if (sp)
796                 sp->stype = t;
797         p = mkty(t00);
798         p->n_sp = sp;
799         return p;
800 }
801
802 /*
803  * Handle reference to an enum
804  */
805 NODE *
806 enumref(char *name)
807 {
808         struct symtab *sp;
809         NODE *p;
810
811         sp = lookup(nameSTAGNAME);
812
813 #ifdef notdef
814         /*
815          * 6.7.2.3 Clause 2:
816          * "A type specifier of the form 'enum identifier' without an
817          *  enumerator list shall only appear after the type it specifies
818          *  is complete."
819          */
820         if (sp->sclass != ENAME)
821                 uerror("enum %s undeclared"name);
822 #endif
823         if (sp->sclass == SNULL) {
824                 /* declare existence of enum */
825                 sp = enumhd(name);
826                 sp->stype = ENUMTY;
827         }
828
829         p = mkty(sp->stype0sp->sap);
830         p->n_sp = sp;
831         return p;
832 }
833
834 /*
835  * begining of structure or union declaration
836  * It's an error if this routine is called twice with the same struct.
837  */
838 struct rstack *
839 bstruct(char *nameint soruNODE *gp)
840 {
841         struct rstack *r;
842         struct symtab *sp;
843         struct attr *ap, *gap;
844         char nbuf[20];
845
846         gap = gp ? gcc_attr_parse(gp) : NULL;
847
848         if (name == NULL) {
849                 static int ancnt;
850                 sprintf(nbuf"__%%ANON%d"ancnt++);
851                 name = addname(nbuf);
852         }
853
854         if (name != NULL) {
855                 sp = deftag(namesoru);
856                 if (sp->sap == NULL)
857                         sp->sap = seattr();
858                 ap = attr_find(sp->sapGCC_ATYP_ALIGNED);
859                 if (ap->iarg(0) != 0) {
860                         if (sp->slevel < blevel) {
861                                 sp = hide(sp);
862                                 defstr(spsoru);
863                                 sp->sap = seattr();
864                         } else
865                                 uerror("%s redeclared"name);
866                 }
867                 INSSYM(sp);
868                 nscur = sp;
869                 gap = sp->sap = attr_add(sp->sapgap);
870         } else {
871                 gap = attr_add(seattr(), gap);
872                 sp = getsymtab("__%"SNORMAL);
873         }
874
875         r = tmpcalloc(sizeof(struct rstack));
876         r->rsou = soru;
877         r->rsym = sp;
878 //      r->rb = NULL;
879         r->ap = gap;
880         r->rnext = rpole;
881         rpole = r;
882
883         return r;
884 }
885
886 /*
887  * Called after a struct is declared to restore the environment.
888  * - If ALSTRUCT is defined, this will be the struct alignment and the
889  *   struct size will be a multiple of ALSTRUCT, otherwise it will use
890  *   the alignment of the largest struct member.
891  */
892 NODE *
893 dclstruct(struct rstack *r)
894 {
895         NODE *n;
896         struct attr *aps, *apb;
897         struct symtab *sp;
898         int alsasz;
899
900         apb = attr_find(r->apGCC_ATYP_ALIGNED);
901         aps = attr_find(r->apATTR_STRUCT);
902 //      aps->amlist = r->rb;
903         aps->amlist = nscur->sup;
904
905 #ifdef ALSTRUCT
906         al = ALSTRUCT;
907 #else
908         al = ALCHAR;
909 #endif
910
911         /*
912          * extract size and alignment, calculate offsets
913          */
914         for (sp = /* r->rb */nscur->supspsp = sp->snext) {
915                 sp->sdown = r->rsym;
916                 if (ISFTN(sp->stype))
917                         continue;
918                 sa = talign(sp->stypesp->sap);
919                 if (sp->sclass & FIELD)
920                         sz = sp->sclass&FLDSIZ;
921                 else
922                         sz = (int)tsize(sp->stypesp->sdfsp->sap);
923                 if (sz > rpole->rstr)
924                         rpole->rstr = sz;  /* for use with unions */
925                 /*
926                  * set al, the alignment, to the lcm of the alignments
927                  * of the members.
928                  */
929                 SETOFF(alsa);
930         }
931
932         SETOFF(rpole->rstral);
933
934         aps->amsize = rpole->rstr;
935         apb->iarg(0) = al;
936
937 #ifdef PCC_DEBUG
938         if (ddebug) {
939                 printf("dclstruct(%s): size=%d, align=%d\n",
940                     r->rsym ? r->rsym->sname : "??",
941                     aps->amsizeapb->iarg(0));
942         }
943         if (ddebug>1) {
944                 printf("\tsize %d align %d link %p\n",
945                     aps->amsizeapb->iarg(0), aps->amlist);
946                 for (sp = aps->amlistsp != NULLsp = sp->snext) {
947                         printf("\tmember %s(%p)\n"sp->snamesp);
948                 }
949         }
950 #endif
951
952 #ifdef STABS
953         if (gflag)
954                 stabs_struct(r->rsymr->ap);
955 #endif
956
957         rpole = r->rnext;
958         n = mkty(r->rsou == STNAME ? STRTY : UNIONTY0r->ap);
959         n->n_sp = r->rsym;
960
961         POPSYM();
962
963         n->n_qual |= 1/* definition place XXX used by attributes */
964         return n;
965 }
966
967 /*
968  * Add a new member to the current struct or union being declared.
969  */
970 void
971 soumemb(NODE *nchar *nameint class)
972 {
973         struct symtab *sp, *lsp;
974         int incomptszal;
975         TWORD t;
976  
977         if (rpole == NULL)
978                 cerror("soumemb");
979  
980         /* check if tag name exists */
981         lsp = NULL;
982         for (sp = /* rpole->rb */ nscur->supsp != NULLlsp = spsp = sp->snext)
983                 if (*name != '*' && sp->sname == name && class == sp->sclass)
984                         uerror("redeclaration of %s"name);
985
986         sp = getsymtab(nameSMOSNAME);
987 #if 0
988         if (rpole->rb == NULL)
989                 rpole->rb = sp;
990         else
991                 lsp->snext = sp;
992 #endif
993         if (nscur->sup == NULL)
994                 nscur->sup = sp;
995         else
996                 lsp->snext = sp;
997
998         n->n_sp = sp;
999         sp->stype = n->n_type;
1000         sp->squal = n->n_qual;
1001         sp->slevel = blevel;
1002         sp->sap = n->n_ap;
1003         sp->sdf = n->n_df;
1004         sp->sdown = rpole->rsym;
1005
1006         if (class & FIELD) {
1007                 sp->sclass = (char)class;
1008                 falloc(spclass&FLDSIZNIL);
1009         } else if (class == STATIC) {
1010                 sp->sclass = USTATIC;
1011                 cxxsetname(sp);
1012         } else if (ISFTN(sp->stype)) {
1013                 sp->sclass = EXTERN;
1014                 cxxsetname(sp);
1015         } else if (rpole->rsou == STNAME || rpole->rsou == UNAME) {
1016                 sp->sclass = rpole->rsou == STNAME ? MOS : MOU;
1017                 if (sp->sclass == MOU)
1018                         rpole->rstr = 0;
1019                 al = talign(sp->stypesp->sap);
1020                 tsz = (int)tsize(sp->stypesp->sdfsp->sap);
1021                 sp->soffset = upoff(tszal, &rpole->rstr);
1022         }
1023
1024         /*
1025          * 6.7.2.1 clause 16:
1026          * "...the last member of a structure with more than one
1027          *  named member may have incomplete array type;"
1028          */
1029         if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1030                 incomp = 1;
1031         else
1032                 incomp = 0;
1033         if ((rpole->flags & LASTELM) || (/* rpole->rb */ nscur->sup == sp && incomp == 1))
1034                 uerror("incomplete array in struct");
1035         if (incomp == 1)
1036                 rpole->flags |= LASTELM;
1037
1038         /*
1039          * 6.7.2.1 clause 2:
1040          * "...such a structure shall not be a member of a structure
1041          *  or an element of an array."
1042          */
1043         t = sp->stype;
1044         if (rpole->rsou != STNAME || BTYPE(t) != STRTY)
1045                 return/* not for unions */
1046         while (ISARY(t))
1047                 t = DECREF(t);
1048         if (ISPTR(t))
1049                 return;
1050
1051         if ((lsp = strmemb(sp->sap)) != NULL) {
1052                 for (; lsp->snextlsp = lsp->snext)
1053                         ;
1054                 if (ISARY(lsp->stype) && lsp->snext &&
1055                     lsp->sdf->ddim == NOOFFSET)
1056                         uerror("incomplete struct in struct");
1057         }
1058 }
1059
1060 /*
1061  * error printing routine in parser
1062  */
1063 void
1064 yyerror(char *s)
1065 {
1066         uerror(s);
1067 }
1068
1069 void yyaccpt(void);
1070 void
1071 yyaccpt(void)
1072 {
1073         ftnend();
1074 }
1075
1076 /*
1077  * p is top of type list given to tymerge later.
1078  * Find correct CALL node and declare parameters from there.
1079  */
1080 void
1081 ftnarg(NODE *p)
1082 {
1083         NODE *q;
1084
1085 #ifdef PCC_DEBUG
1086         if (ddebug > 2)
1087                 printf("ftnarg(%p)\n"p);
1088 #endif
1089         /*
1090          * Push argument symtab entries onto param stack in reverse order,
1091          * due to the nature of the stack it will be reclaimed correct.
1092          */
1093         for (; p->n_op != NAMEp = p->n_left) {
1094                 if (p->n_op == UCALL && p->n_left->n_op == NAME)
1095                         return/* Nothing to enter */
1096                 if (p->n_op == CALL &&
1097                     (p->n_left->n_op == NAME || p->n_left->n_op == NMLIST))
1098                         break;
1099         }
1100
1101         p = p->n_right;
1102         while (p->n_op == CM) {
1103                 q = p->n_right;
1104                 if (q->n_op != ELLIPSIS) {
1105                         ssave(q->n_sp);
1106                         nparams++;
1107 #ifdef PCC_DEBUG
1108                         if (ddebug > 2)
1109                                 printf("        saving sym %s (%p) from (%p)\n",
1110                                     q->n_sp->snameq->n_spq);
1111 #endif
1112                 }
1113                 p = p->n_left;
1114         }
1115         ssave(p->n_sp);
1116         if (p->n_type != VOID)
1117                 nparams++;
1118
1119 #ifdef PCC_DEBUG
1120         if (ddebug > 2)
1121                 printf("        saving sym %s (%p) from (%p)\n",
1122                     nparams ? p->n_sp->sname : "<noname>"p->n_spp);
1123 #endif
1124 }
1125
1126 /*
1127  * compute the alignment of an object with type ty, sizeoff index s
1128  */
1129 int
1130 talign(unsigned int tystruct attr *apl)
1131 {
1132         struct attr *al;
1133         int a;
1134
1135         for (; ty > BTMASKty = DECREF(ty)) {
1136                 switch (ty & TMASK) {
1137                 case PTR:
1138                         return(ALPOINT);
1139                 case ARY:
1140                         continue;
1141                 case FTN:
1142                         cerror("compiler takes alignment of function");
1143                 }
1144         }
1145
1146         /* check for alignment attribute */
1147         if ((al = attr_find(aplGCC_ATYP_ALIGNED))) {
1148                 if ((a = al->iarg(0)) == 0) {
1149                         uerror("no alignment");
1150                         a = ALINT;
1151                 } 
1152                 return a;
1153         }
1154
1155         ty = BTYPE(ty);
1156         if (ty >= CHAR && ty <= ULONGLONG && ISUNSIGNED(ty))
1157                 ty = DEUNSIGN(ty);
1158
1159         switch (ty) {
1160         case BOOLa = ALBOOLbreak;
1161         case CHARa = ALCHARbreak;
1162         case SHORTa = ALSHORTbreak;
1163         case INTa = ALINTbreak;
1164         case LONGa = ALLONGbreak;
1165         case LONGLONGa = ALLONGLONGbreak;
1166         case FLOATa = ALFLOATbreak;
1167         case DOUBLEa = ALDOUBLEbreak;
1168         case LDOUBLEa = ALLDOUBLEbreak;
1169         default:
1170                 uerror("no alignment");
1171                 a = ALINT;
1172         }
1173         return a;
1174 }
1175
1176 short sztable[] = { 0SZBOOLSZCHARSZCHARSZSHORTSZSHORTSZINTSZINT,
1177         SZLONGSZLONGSZLONGLONGSZLONGLONGSZFLOATSZDOUBLESZLDOUBLE };
1178
1179 /* compute the size associated with type ty,
1180  *  dimoff d, and sizoff s */
1181 /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
1182 OFFSZ
1183 tsize(TWORD tyunion dimfun *dstruct attr *apl)
1184 {
1185         struct attr *ap, *ap2;
1186         OFFSZ multsz;
1187
1188         mult = 1;
1189
1190         for (; ty > BTMASKty = DECREF(ty)) {
1191                 switch (ty & TMASK) {
1192
1193                 case FTN:
1194                         uerror"cannot take size of function");
1195                 case PTR:
1196                         returnSZPOINT(ty) * mult );
1197                 case ARY:
1198                         if (d->ddim == NOOFFSET)
1199                                 return 0;
1200                         if (d->ddim < 0)
1201                                 cerror("tsize: dynarray");
1202                         mult *= d->ddim;
1203                         d++;
1204                 }
1205         }
1206
1207         if (ty == VOID)
1208                 ty = CHAR;
1209         if (ty <= LDOUBLE)
1210                 sz = sztable[ty];
1211         else if (ISSOU(ty)) {
1212                 if ((ap = strattr(apl)) == NULL ||
1213                     (ap2 = attr_find(aplGCC_ATYP_ALIGNED)) == NULL ||
1214                     (ap2->iarg(0) == 0)) {
1215                         uerror("unknown structure/union/enum");
1216                         sz = SZINT;
1217                 } else
1218                         sz = ap->amsize;
1219         } else {
1220                 uerror("unknown type");
1221                 sz = SZINT;
1222         }
1223
1224         return((unsigned int)sz * mult);
1225 }
1226
1227 /*
1228  * Save string (and print it out).  If wide then wide string.
1229  */
1230 NODE *
1231 strend(int widechar *str)
1232 {
1233         struct symtab *sp;
1234         NODE *p;
1235
1236         /* If an identical string is already emitted, just forget this one */
1237         if (wide) {
1238                 /* Do not save wide strings, at least not now */
1239                 sp = getsymtab(strSSTRING|STEMP);
1240         } else {
1241                 str = addstring(str);   /* enter string in string table */
1242                 sp = lookup(strSSTRING);      /* check for existance */
1243         }
1244
1245         if (sp->soffset == 0) { /* No string */
1246                 char *wr;
1247                 int i;
1248
1249                 sp->sclass = STATIC;
1250                 sp->slevel = 1;
1251                 sp->soffset = getlab();
1252                 sp->squal = (CON >> TSHIFT);
1253                 sp->sdf = permalloc(sizeof(union dimfun));
1254                 if (wide) {
1255                         sp->stype = WCHAR_TYPE+ARY;
1256                 } else {
1257                         if (xuchar) {
1258                                 sp->stype = UCHAR+ARY;
1259                         } else {
1260                                 sp->stype = CHAR+ARY;
1261                         }
1262                 }
1263                 for (wr = sp->snamei = 1; *wri++)
1264                         if (*wr++ == '\\')
1265                            &nb