Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20120101162054

Diff

Diff from 1.1 to:

Annotations

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

Annotated File View

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