Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140620070448

Diff

Diff from 1.11 to:

Annotations

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

Annotated File View

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