Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20121022092540

Diff

Diff from 1.8 to:

Annotations

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

Annotated File View

plunky
1.8
1 /*      $Id: pftn.c,v 1.8 2012/10/22 09:25: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 {
plunky
1.8
106         struct params *prev;
ragge
1.1
107         struct symtab *sym;
plunky
1.8
108 } *lparam;
ragge
1.1
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);
plunky
1.6
164                 tprint(q->n_typeq->n_qual);
ragge
1.1
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 ");
plunky
1.6
184                 tprint(typequal);
ragge
1.1
185                 printf(", %s\n"scnames(class));
186                 printf("        previous def'n: ");
plunky
1.6
187                 tprint(stpstq);
ragge
1.1
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));
plunky
1.8
479         p->prev = lparam;
ragge
1.1
480         p->sym = sym;
481         lparam = p;
482 }
483
484 /*
485  * end of function
486  */
487 void
plunky
1.3
488 ftnend(void)
ragge
1.1
489 {
490         struct attr *gc, *gd;
491         extern NODE *cftnod;
492         extern struct savbc *savbc;
493         extern struct swdef *swpole;
494         extern int tvaloff;
495         char *c;
496
497         if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
498                 plabel(retlab);
499                 if (cftnod)
500                         ecomp(buildtree(FORCEcftnodNIL));
501                 efcode(); /* struct return handled here */
502                 if ((c = cftnsp->soname) == NULL)
503                         c = addname(exname(cftnsp->sname));
504                 SETOFF(maxautooffALCHAR);
505                 send_passt(IP_EPILOGmaxautooff/SZCHARc,
506                     cftnsp->stypecftnsp->sclass == EXTDEFretlabtvaloff);
507         }
508
509         cftnod = NIL;
510         tcheck();
511         brklab = contlab = retlab = NOLAB;
512         flostat = 0;
513         if (nerrors == 0) {
514                 if (savbc != NULL)
515                         cerror("bcsave error");
516                 if (lparam != NULL)
517                         cerror("parameter reset error");
518                 if (swpole != NULL)
519                         cerror("switch error");
520         }
521         if (cftnsp) {
522                 gc = attr_find(cftnsp->sapGCC_ATYP_CONSTRUCTOR);
523                 gd = attr_find(cftnsp->sapGCC_ATYP_DESTRUCTOR);
524                 if (gc || gd) {
525                         struct symtab sts = *cftnsp;
526                         NODE *p;
527                         sts.stype = INCREF(sts.stype);
528                         p = nametree(&sts);
529                         p->n_op = ICON;
530                         if (gc) {
531                                 locctr(CTORS, &sts);
532                                 inval(0SZPOINT(0), p);
533                         }
534                         if (gd) {
535                                 locctr(DTORS, &sts);
536                                 inval(0SZPOINT(0), p);
537                         }
538                         tfree(p);
539                 }
540         }
541         savbc = NULL;
542         lparam = NULL;
543         cftnsp = NULL;
544         maxautooff = autooff = AUTOINIT;
545         reached = 1;
546
547         if (isinlining)
548                 inline_end();
549         inline_prtout();
550
551         tmpfree(); /* Release memory resources */
552 }
553
554 static struct symtab nulsym = {
555         NULLNULLNULL0000"null""null"INT0NULLNULL
556 };
557
558 void
plunky
1.3
559 dclargs(void)
ragge
1.1
560 {
561         union dimfun *df;
562         union arglist *al, *al2, *alb;
563         struct params *a;
564         struct symtab *p, **parr = NULL/* XXX gcc */
565         int i;
566
567         /*
568          * Deal with fun(void) properly.
569          */
570         if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID)
571                 goto done;
572
573         if (cftnsp->sdown && cftnsp->sdown->sclass != NSPACE) {
574                 /* first arg is a pointer to the "sprev" class */
575                 p = cxxstrvar(cftnsp->sdown);
576                 ssave(p);
577                 nparams++;
578         }
579         /*
580          * Generate a list for bfcode().
581          * Parameters were pushed in reverse order.
582          */
583         if (nparams != 0)
584                 parr = tmpalloc(sizeof(struct symtab *) * nparams);
585
586         if (nparams)
587             for (a = lparami = 0a != NULLa = a->prev) {
588                 p = a->sym;
589                 parr[i++] = p;
590                 if (p == NULL) {
591                         uerror("parameter %d name missing"i);
592                         p = &nulsym/* empty symtab */
593                 }
594                 if (p->stype == FARG)
595                         p->stype = INT;
596                 if (ISARY(p->stype)) {
597                         p->stype += (PTR-ARY);
598                         p->sdf++;
599                 } else if (ISFTN(p->stype)) {
600                         werror("function declared as argument");
601                         p->stype = INCREF(p->stype);
602                 }
603 #ifdef STABS
604                 if (gflag)
605                         stabs_newsym(p);
606 #endif
607         }
608         if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
609                 /*
610                  * Check against prototype of oldstyle function.
611                  */
612                 alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
613                 for (i = 0i < nparamsi++) {
614                         TWORD type = parr[i]->stype;
615                         (al2++)->type = type;
616                         if (ISSOU(BTYPE(type)))
617                                 (al2++)->sap = parr[i]->sap;
618                         while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
619                                 type = DECREF(type);
620                         if (type > BTMASK)
621                                 (al2++)->df = parr[i]->sdf;
622                 }
623                 al2->type = TNULL;
624                 intcompare = 1;
625                 if (chkftn(alalb))
626                         uerror("function doesn't match prototype");
627                 intcompare = 0;
628
629         }
630
631         if (oldstyle && nparams) {
632                 /* Must recalculate offset for oldstyle args here */
633                 argoff = ARGINIT;
634                 for (i = 0i < nparamsi++) {
635                         parr[i]->soffset = NOOFFSET;
636                         oalloc(parr[i], &argoff);
637                 }
638         }
639
640 done:   autooff = AUTOINIT;
641
642         plabel(prolab); /* after prolog, used in optimization */
643         retlab = getlab();
644         bfcode(parrnparams);
645         if (fun_inline &&
646             (xinline || attr_find(cftnsp->sapGCC_ATYP_ALW_INL)))
647                 inline_args(parrnparams);
648         plabel(getlab()); /* used when spilling */
649         if (parlink)
650                 ecomp(parlink);
651         parlink = NIL;
652         lparam = NULL;
653         nparams = 0;
654         symclear(1);    /* In case of function pointer args */
655 }
656
657 /*
658  * basic attributes for structs and enums
659  */
660 static struct attr *
661 seattr(void)
662 {
663         return attr_add(attr_new(GCC_ATYP_ALIGNED4), attr_new(ATTR_STRUCT2));
664 }
665
666 /*
667  * Struct/union/enum symtab construction.
668  */
669 static void
670 defstr(struct symtab *spint class)
671 {
672         sp->sclass = (char)class;
673         if (class == STNAME || class == CLNAME)
674                 sp->stype = STRTY;
675         else if (class == UNAME)
676                 sp->stype = UNIONTY;
677         else if (class == ENAME)
678                 sp->stype = ENUMTY;
679 }
680
681 /*
682  * Declare a struct/union/enum tag.
683  * If not found, create a new tag with UNDEF type.
684  */
685 static struct symtab *
686 deftag(char *nameint class)
687 {
688         struct symtab *sp;
689
690         if ((sp = cxxdclstr(name))->sap == NULL) {
691                 /* New tag */
692                 defstr(spclass);
693         } else if (sp->sclass != class)
694                 uerror("tag %s redeclared"name);
695         return sp;
696 }
697
698 /*
699  * reference to a structure or union, with no definition
700  */
701 NODE *
702 rstruct(char *tagint soru)
703 {
704         struct symtab *sp;
705
706         sp = deftag(tagsoru);
707         if (sp->sap == NULL)
708                 sp->sap = seattr();
709         return mkty(sp->stype0sp->sap);
710 }
711
712 static int enumlowenumhigh;
713 int enummer;
714
715 /*
716  * Declare a member of enum.
717  */
718 void
719 moedef(char *name)
720 {
721         struct symtab *sp;
722
723         sp = lookup(nameSNORMAL);
724         if (sp->stype == UNDEF || (sp->slevel < blevel)) {
725                 if (sp->stype != UNDEF)
726                         sp = hide(sp);
727                 sp->stype = INT/* always */
728                 sp->sclass = MOE;
729                 sp->soffset = enummer;
730         } else
731                 uerror("%s redeclared"name);
732         if (enummer < enumlow)
733                 enumlow = enummer;
734         if (enummer > enumhigh)
735                 enumhigh = enummer;
736         enummer++;
737 }
738
739 /*
740  * Declare an enum tag.  Complain if already defined.
741  */
742 struct symtab *
743 enumhd(char *name)
744 {
745         struct attr *ap;
746         struct symtab *sp;
747
748         enummer = enumlow = enumhigh = 0;
749         if (name == NULL)
750                 return NULL;
751
752         sp = deftag(nameENAME);
753         if (sp->stype != ENUMTY) {
754                 if (sp->slevel == blevel)
755                         uerror("%s redeclared"name);
756                 sp = hide(sp);
757                 defstr(spENAME);
758         }
759         if (sp->sap == NULL)
760                 ap = sp->sap = attr_new(ATTR_STRUCT4);
761         else
762                 ap = attr_find(sp->sapATTR_STRUCT);
763         ap->amlist = sp;
764         return sp;
765 }
766
767 /*
768  * finish declaration of an enum
769  */
770 NODE *
771 enumdcl(struct symtab *sp)
772 {
773         NODE *p;
774         TWORD t;
775
776 #ifdef ENUMSIZE
777         t = ENUMSIZE(enumhighenumlow);
778 #else
779         t = ctype(enumlow < 0 ? INT : UNSIGNED);
780 #ifdef notdef
781         if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR)
782                 t = ctype(CHAR);
783         else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT)
784                 t = ctype(SHORT);
785         else
786                 t = ctype(INT);
787 #endif
788 #endif
789         
790         if (sp)
791                 sp->stype = t;
792         p = mkty(t00);
793         p->n_sp = sp;
794         return p;
795 }
796
797 /*
798  * Handle reference to an enum
799  */
800 NODE *
801 enumref(char *name)
802 {
803         struct symtab *sp;
804         NODE *p;
805
806         sp = lookup(nameSTAGNAME);
807
808 #ifdef notdef
809         /*
810          * 6.7.2.3 Clause 2:
811          * "A type specifier of the form 'enum identifier' without an
812          *  enumerator list shall only appear after the type it specifies
813          *  is complete."
814          */
815         if (sp->sclass != ENAME)
816                 uerror("enum %s undeclared"name);
817 #endif
818         if (sp->sclass == SNULL) {
819                 /* declare existence of enum */
820                 sp = enumhd(name);
821                 sp->stype = ENUMTY;
822         }
823
824         p = mkty(sp->stype0sp->sap);
825         p->n_sp = sp;
826         return p;
827 }
828
829 /*
830  * begining of structure or union declaration
831  * It's an error if this routine is called twice with the same struct.
832  */
833 struct rstack *
834 bstruct(char *nameint soruNODE *gp)
835 {
836         struct rstack *r;
837         struct symtab *sp;
838         struct attr *ap, *gap;
839         char nbuf[20];
840
841         gap = gp ? gcc_attr_parse(gp) : NULL;
842
843         if (name == NULL) {
844                 static int ancnt;
845                 sprintf(nbuf"__%%ANON%d"ancnt++);
846                 name = addname(nbuf);
847         }
848
849         if (name != NULL) {
850                 sp = deftag(namesoru);
851                 if (sp->sap == NULL)
852                         sp->sap = seattr();
853                 ap = attr_find(sp->sapGCC_ATYP_ALIGNED);
854                 if (ap->iarg(0) != 0) {
855                         if (sp->slevel < blevel) {
856                                 sp = hide(sp);
857                                 defstr(spsoru);
858                                 sp->sap = seattr();
859                         } else
860                                 uerror("%s redeclared"name);
861                 }
862                 INSSYM(sp);
863                 nscur = sp;
864                 gap = sp->sap = attr_add(sp->sapgap);
865         } else {
866                 gap = attr_add(seattr(), gap);
867                 sp = getsymtab("__%"SNORMAL);
868         }
869
870         r = tmpcalloc(sizeof(struct rstack));
871         r->rsou = soru;
872         r->rsym = sp;
873 //      r->rb = NULL;
874         r->ap = gap;
875         r->rnext = rpole;
876         rpole = r;
877
878         return r;
879 }
880
881 /*
882  * Called after a struct is declared to restore the environment.
883  * - If ALSTRUCT is defined, this will be the struct alignment and the
884  *   struct size will be a multiple of ALSTRUCT, otherwise it will use
885  *   the alignment of the largest struct member.
886  */
887 NODE *
888 dclstruct(struct rstack *r)
889 {
890         NODE *n;
891         struct attr *aps, *apb;
892         struct symtab *sp;
893         int alsasz;
894
895         apb = attr_find(r->apGCC_ATYP_ALIGNED);
896         aps = attr_find(r->apATTR_STRUCT);
897 //      aps->amlist = r->rb;
898         aps->amlist = nscur->sup;
899
900 #ifdef ALSTRUCT
901         al = ALSTRUCT;
902 #else
903         al = ALCHAR;
904 #endif
905
906         /*
907          * extract size and alignment, calculate offsets
908          */
909         for (sp = /* r->rb */nscur->supspsp = sp->snext) {
910                 sp->sdown = r->rsym;
911                 if (ISFTN(sp->stype))
912                         continue;
913                 sa = talign(sp->stypesp->sap);
914                 if (sp->sclass & FIELD)
915                         sz = sp->sclass&FLDSIZ;
916                 else
917                         sz = (int)tsize(sp->stypesp->sdfsp->sap);
918                 if (sz > rpole->rstr)
919                         rpole->rstr = sz;  /* for use with unions */
920                 /*
921                  * set al, the alignment, to the lcm of the alignments
922                  * of the members.
923                  */
924                 SETOFF(alsa);
925         }
926
927         SETOFF(rpole->rstral);
928
929         aps->amsize = rpole->rstr;
930         apb->iarg(0) = al;
931
932 #ifdef PCC_DEBUG
933         if (ddebug) {
934                 printf("dclstruct(%s): size=%d, align=%d\n",
935                     r->rsym ? r->rsym->sname : "??",
936                     aps->amsizeapb->iarg(0));
937         }
938         if (ddebug>1) {
939                 printf("\tsize %d align %d link %p\n",
940                     aps->amsizeapb->iarg(0), aps->amlist);
941                 for (sp = aps->amlistsp != NULLsp = sp->snext) {
942                         printf("\tmember %s(%p)\n"sp->snamesp);
943                 }
944         }
945 #endif
946
947 #ifdef STABS
948         if (gflag)
949                 stabs_struct(r->rsymr->ap);
950 #endif
951
952         rpole = r->rnext;
953         n = mkty(r->rsou == STNAME ? STRTY : UNIONTY0r->ap);
954         n->n_sp = r->rsym;
955
956         POPSYM();
957
958         n->n_qual |= 1/* definition place XXX used by attributes */
959         return n;
960 }
961
962 /*
963  * Add a new member to the current struct or union being declared.
964  */
965 void
966 soumemb(NODE *nchar *nameint class)
967 {
968         struct symtab *sp, *lsp;
969         int incomptszal;
970         TWORD t;
971  
972         if (rpole == NULL)
973                 cerror("soumemb");
974  
975         /* check if tag name exists */
976         lsp = NULL;
977         for (sp = /* rpole->rb */ nscur->supsp != NULLlsp = spsp = sp->snext)
978                 if (*name != '*' && sp->sname == name && class == sp->sclass)
979                         uerror("redeclaration of %s"name);
980
981         sp = getsymtab(nameSMOSNAME);
982 #if 0
983         if (rpole->rb == NULL)
984                 rpole->rb = sp;
985         else
986                 lsp->snext = sp;
987 #endif
988         if (nscur->sup == NULL)
989                 nscur->sup = sp;
990         else
991                 lsp->snext = sp;
992
993         n->n_sp = sp;
994         sp->stype = n->n_type;
995         sp->squal = n->n_qual;
996         sp->slevel = blevel;
997         sp->sap = n->n_ap;
998         sp->sdf = n->n_df;
999         sp->sdown = rpole->rsym;
1000
1001         if (class & FIELD) {
1002                 sp->sclass = (char)class;
1003                 falloc(spclass&FLDSIZNIL);
1004         } else if (class == STATIC) {
1005                 sp->sclass = USTATIC;
1006                 cxxsetname(sp);
1007         } else if (ISFTN(sp->stype)) {
1008                 sp->sclass = EXTERN;
1009                 cxxsetname(sp);
1010         } else if (rpole->rsou == STNAME || rpole->rsou == UNAME) {
1011                 sp->sclass = rpole->rsou == STNAME ? MOS : MOU;
1012                 if (sp->sclass == MOU)
1013                         rpole->rstr = 0;
1014                 al = talign(sp->stypesp->sap);
1015                 tsz = (int)tsize(sp->stypesp->sdfsp->sap);
1016                 sp->soffset = upoff(tszal, &rpole->rstr);
1017         }
1018
1019         /*
1020          * 6.7.2.1 clause 16:
1021          * "...the last member of a structure with more than one
1022          *  named member may have incomplete array type;"
1023          */
1024         if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET)
1025                 incomp = 1;
1026         else
1027                 incomp = 0;
1028         if ((rpole->flags & LASTELM) || (/* rpole->rb */ nscur->sup == sp && incomp == 1))
1029                 uerror("incomplete array in struct");
1030         if (incomp == 1)
1031                 rpole->flags |= LASTELM;
1032
1033         /*
1034          * 6.7.2.1 clause 2:
1035          * "...such a structure shall not be a member of a structure
1036          *  or an element of an array."
1037          */
1038         t = sp->stype;
1039         if (rpole->rsou != STNAME || BTYPE(t) != STRTY)
1040                 return/* not for unions */
1041         while (ISARY(t))
1042                 t = DECREF(t);
1043         if (ISPTR(t))
1044                 return;
1045
1046         if ((lsp = strmemb(sp->sap)) != NULL) {
1047                 for (; lsp->snextlsp = lsp->snext)
1048                         ;
1049                 if (ISARY(lsp->stype) && lsp->snext &&
1050                     lsp->sdf->ddim == NOOFFSET)
1051                         uerror("incomplete struct in struct");
1052         }
1053 }
1054
1055 /*
1056  * error printing routine in parser
1057  */
1058 void
1059 yyerror(char *s)
1060 {
1061         uerror(s);
1062 }
1063
1064 void yyaccpt(void);
1065 void
1066 yyaccpt(void)
1067 {
1068         ftnend();
1069 }
1070
1071 /*
1072  * p is top of type list given to tymerge later.
1073  * Find correct CALL node and declare parameters from there.
1074  */
1075 void
1076 ftnarg(NODE *p)
1077 {
1078         NODE *q;
1079
1080 #ifdef PCC_DEBUG
1081         if (ddebug > 2)
1082                 printf("ftnarg(%p)\n"p);
1083 #endif
1084         /*
1085          * Push argument symtab entries onto param stack in reverse order,
1086          * due to the nature of the stack it will be reclaimed correct.
1087          */
1088         for (; p->n_op != NAMEp = p->n_left) {
1089                 if (p->n_op == UCALL && p->n_left->n_op == NAME)
1090                         return/* Nothing to enter */
1091                 if (p->n_op == CALL &&
1092                     (p->n_left->n_op == NAME || p->n_left->n_op == NMLIST))
1093                         break;
1094         }
1095
1096         p = p->n_right;
1097         while (p->n_op == CM) {
1098                 q = p->n_right;
1099                 if (q->n_op != ELLIPSIS) {
1100                         ssave(q->n_sp);
1101                         nparams++;
1102 #ifdef PCC_DEBUG
1103                         if (ddebug > 2)
1104                                 printf("        saving sym %s (%p) from (%p)\n",
1105                                     q->n_sp->snameq->n_spq);
1106 #endif
1107                 }
1108                 p = p->n_left;
1109         }
1110         ssave(p->n_sp);
1111         if (p->n_type != VOID)
1112                 nparams++;
1113
1114 #ifdef PCC_DEBUG
1115         if (ddebug > 2)
1116                 printf("        saving sym %s (%p) from (%p)\n",
1117                     nparams ? p->n_sp->sname : "<noname>"p->n_spp);
1118 #endif
1119 }
1120
1121 /*
1122  * compute the alignment of an object with type ty, sizeoff index s
1123  */
1124 int
1125 talign(unsigned int tystruct attr *apl)
1126 {
1127         struct attr *al;
1128         int a;
1129
1130         for (; ty > BTMASKty = DECREF(ty)) {
1131                 switch (ty & TMASK) {
1132                 case PTR:
1133                         return(ALPOINT);
1134                 case ARY:
1135                         continue;
1136                 case FTN:
1137                         cerror("compiler takes alignment of function");
1138                 }
1139         }
1140
1141         /* check for alignment attribute */
1142         if ((al = attr_find(aplGCC_ATYP_ALIGNED))) {
1143                 if ((a = al->iarg(0)) == 0) {
1144                         uerror("no alignment");
1145                         a = ALINT;
1146                 } 
1147                 return a;
1148         }
1149
1150         ty = BTYPE(ty);
1151         if (ty >= CHAR && ty <= ULONGLONG && ISUNSIGNED(ty))
1152                 ty = DEUNSIGN(ty);
1153
1154         switch (ty) {
1155         case BOOLa = ALBOOLbreak;
1156         case CHARa = ALCHARbreak;
1157         case SHORTa = ALSHORTbreak;
1158         case INTa = ALINTbreak;
1159         case LONGa = ALLONGbreak;
1160         case LONGLONGa = ALLONGLONGbreak;
1161         case FLOATa = ALFLOATbreak;
1162         case DOUBLEa = ALDOUBLEbreak;
1163         case LDOUBLEa = ALLDOUBLEbreak;
1164         default:
1165                 uerror("no alignment");
1166                 a = ALINT;
1167         }
1168         return a;
1169 }
1170
1171 short sztable[] = { 0SZBOOLSZCHARSZCHARSZSHORTSZSHORTSZINTSZINT,
1172         SZLONGSZLONGSZLONGLONGSZLONGLONGSZFLOATSZDOUBLESZLDOUBLE };
1173
1174 /* compute the size associated with type ty,
1175  *  dimoff d, and sizoff s */
1176 /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
1177 OFFSZ
1178 tsize(TWORD tyunion dimfun *dstruct attr *apl)
1179 {
1180         struct attr *ap, *ap2;
1181         OFFSZ multsz;
1182
1183         mult = 1;
1184
1185         for (; ty > BTMASKty = DECREF(ty)) {
1186                 switch (ty & TMASK) {
1187
1188                 case FTN:
1189                         uerror"cannot take size of function");
1190                 case PTR:
1191                         returnSZPOINT(ty) * mult );
1192                 case ARY:
1193                         if (d->ddim == NOOFFSET)
1194                                 return 0;
1195                         if (d->ddim < 0)
1196                                 cerror("tsize: dynarray");
1197                         mult *= d->ddim;
1198                         d++;
1199                 }
1200         }
1201
1202         if (ty == VOID)
1203                 ty = CHAR;
1204         if (ty <= LDOUBLE)
1205                 sz = sztable[ty];
1206         else if (ISSOU(ty)) {
1207                 if ((ap = strattr(apl)) == NULL ||
1208                     (ap2 = attr_find(aplGCC_ATYP_ALIGNED)) == NULL ||
1209                     (ap2->iarg(0) == 0)) {
1210                         uerror("unknown structure/union/enum");
1211                         sz = SZINT;
1212                 } else
1213                         sz = ap->amsize;
1214         } else {
1215                 uerror("unknown type");
1216                 sz = SZINT;
1217         }
1218
1219         return((unsigned int)sz * mult);
1220 }
1221
1222 /*
1223  * Save string (and print it out).  If wide then wide string.
1224  */
1225 NODE *
1226 strend(int widechar *str)
1227 {
1228         struct symtab *sp;
1229         NODE *p;
1230
1231         /* If an identical string is already emitted, just forget this one */
1232         if (wide) {
1233                 /* Do not save wide strings, at least not now */
1234                 sp = getsymtab(strSSTRING|STEMP);
1235         } else {
1236                 str = addstring(str);   /* enter string in string table */
1237                 sp = lookup(strSSTRING);      /* check for existance */
1238         }
1239
1240         if (sp->soffset == 0) { /* No string */
1241                 char *wr;
1242                 int i;
1243
1244                 sp->sclass = STATIC;
1245                 sp->slevel = 1;
1246                 sp->soffset = getlab();
1247                 sp->squal = (CON >> TSHIFT);
1248                 sp->sdf = permalloc(sizeof(union dimfun));
1249                 if (wide) {
1250                         sp->stype = WCHAR_TYPE+ARY;
1251                 } else {
1252                         if (xuchar) {
1253                                 sp->stype = UCHAR+ARY;