Fix over-enthusiastic uniqification (adding 0|1 to symbols that didn't need it)
[ccom.git] / c03.c
1 /*
2  * C compiler, phase 1
3  * Handles processing of declarations,
4  * except for top-level processing of
5  * externals.
6  */
7
8 #include <string.h>
9 #include "c0.h"
10
11 /*
12  * Process a sequence of declaration statements
13  */
14 int declist(sclass) int sclass; {
15         register int sc, offset;
16         struct nmlist typer;
17
18         offset = 0;
19         sc = sclass;
20         while (getkeywords(&sclass, &typer)) {
21                 offset = declare(sclass, &typer, offset);
22                 sclass = sc;
23         }
24         return(offset+align(INT, offset, 0));
25 }
26
27 /*
28  * Read the keywords introducing a declaration statement
29  * Store back the storage class, and fill in the type
30  * entry, which looks like a hash table entry.
31  */
32 int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
33         register int skw, tkw, longf;
34         int o, isadecl, ismos, unsignf;
35
36         isadecl = 0;
37         longf = 0;
38         unsignf = 0;
39         tptr->htype = INT;
40         tptr->hstrp = NULL;
41         tptr->hsubsp = NULL;
42         tkw = -1;
43         skw = *scptr;
44         ismos = skw==MOS||skw==MOU? FMOS: 0;
45         for (;;) {
46                 mosflg = isadecl? ismos: 0;
47                 o = symbol();
48                 if (o==NAME && csym->hclass==TYPEDEF) {
49                         if (tkw >= 0)
50                                 error0("type clash");
51                         tkw = csym->htype;
52                         tptr->hsubsp = csym->hsubsp;
53                         tptr->hstrp = csym->hstrp;
54                         isadecl++;
55                         continue;
56                 }
57                 switch (o==KEYW? cval: -1) {
58                 case AUTO:
59                 case STATIC:
60                 case EXTERN:
61                 case REG:
62                 case TYPEDEF:
63                         if (skw && skw!=cval) {
64                                 if (skw==ARG && cval==REG)
65                                         cval = AREG;
66                                 else
67                                         error0("Conflict in storage class");
68                         }
69                         skw = cval;
70                         break;
71
72                 case UNSIGN:
73                         unsignf++;
74                         break;
75
76                 case LONG:
77                         longf++;
78                         break;
79
80                 case ENUM:
81                         if (longf || unsignf)
82                                 error0("Perverse modifier on 'enum'");
83                         strdec(ismos, cval);
84                         cval = INT;
85                         goto types;
86
87                 case UNION:
88                 case STRUCT:
89                         tptr->hstrp = strdec(ismos, cval);
90                         cval = STRUCT;
91                 case INT:
92                 case CHAR:
93                 case FLOAT:
94                 case DOUBLE:
95                 case VOID:
96                 types:
97                         if (tkw>=0 && (tkw!=INT || cval!=INT))
98                                 error0("Type clash");
99                         tkw = cval;
100                         if (unscflg && cval==CHAR)
101                                 unsignf++;
102                         break;
103
104                 default:
105                         peeksym = o;
106                         if (isadecl==0)
107                                 return(0);
108                         if (tkw<0)
109                                 tkw = INT;
110                         if (skw==0)
111                                 skw = blklev==0? DEFXTRN: AUTO;
112                         if (unsignf) {
113                                 if (tkw==INT)
114                                         tkw = UNSIGN;
115                                 else if (tkw==CHAR)
116                                         tkw = UNCHAR;
117                                 else if (tkw==LONG)
118                                         tkw = UNLONG;
119                                 else
120                                         error0("Misplaced 'unsigned'");
121                         }
122                         if (longf) {
123                                 if (tkw==FLOAT)
124                                         tkw = DOUBLE;
125                                 else if (tkw==INT)
126                                         tkw = LONG;
127                                 else if (tkw==UNSIGN)
128                                         tkw = UNLONG;
129                                 else
130                                         error0("Misplaced 'long'");
131                         }
132                         *scptr = skw;
133                         tptr->htype = tkw;
134                         return(1);
135                 }
136                 isadecl++;
137         }
138 }
139
140 /*
141  * Process a structure, union, or enum declaration; a subroutine
142  * of getkeywords.
143  */
144 union str *strdec(mosf, kind) int mosf; int kind; {
145         register int elsize, o;
146         register struct nmlist *ssym;
147         int savebits;
148         struct nmlist **savememlist;
149         union str *savesparent;
150         int savenmems;
151         union str *strp;
152         struct nmlist *ds;
153         struct nmlist *mems[NMEMS];
154         struct nmlist typer;
155         int tagkind;
156
157         if (kind!=ENUM) {
158                 tagkind = STRTAG;
159                 mosflg = FTAG;
160                 if (kind==UNION)
161                         mosflg = FUNION;
162         } else {
163                 tagkind = ENUMTAG;
164                 mosflg = FENUM;
165         }
166         ssym = 0;
167         if ((o=symbol())==NAME) {
168                 ssym = csym;
169                 mosflg = mosf;
170                 o = symbol();
171                 if (o==LBRACE && ssym->hblklev<blklev)
172                         ssym = pushdecl(ssym);
173                 if (ssym->hclass && ssym->hclass!=tagkind) {
174                         defsym = ssym;
175                         redec();
176                         ssym = pushdecl(ssym);
177                 }
178                 if (ssym->hclass==0) {
179                         ssym->hclass = tagkind;
180                         ssym->hstrp = (union str *)Dblock(sizeof(struct SS));
181                         ssym->hstrp->S.ssize = 0;
182                         ssym->hstrp->S.memlist = NULL;
183                 }
184                 strp = ssym->hstrp;
185         } else {
186                 strp = (union str *)Dblock(sizeof(struct SS));
187                 strp->S.ssize = 0;
188                 strp->S.memlist = NULL;
189         }
190         mosflg = 0;
191         if (o != LBRACE) {
192                 if (ssym==0)
193                         goto syntax;
194                 if (ssym->hclass!=tagkind)
195                         error0("Bad structure/union/enum name");
196                 peeksym = o;
197         } else {
198                 ds = defsym;
199                 mosflg = 0;
200                 savebits = bitoffs;
201                 savememlist = memlist;
202                 savesparent = sparent;
203                 savenmems = nmems;
204                 memlist = mems;
205                 sparent = strp;
206                 nmems = 2;
207                 bitoffs = 0;
208                 if (kind==ENUM) {
209                         typer.htype = INT;
210                         typer.hstrp = strp;
211                         declare(ENUM, &typer, 0);
212                 } else
213                         elsize = declist(kind==UNION?MOU:MOS);
214                 bitoffs = savebits;
215 #if 1 /* just save a bit of string space */
216                 if (strp->S.ssize) {
217                         defsym = ssym;
218                         redec();
219                 }
220                 defsym = ds;
221 #else
222                 defsym = ds;
223                 if (strp->S.ssize)
224                         error0("%s redeclared", ssym->name);
225 #endif
226                 strp->S.ssize = elsize;
227                 *memlist++ = NULL;
228                 strp->S.memlist = (struct nmlist **)Dblock((memlist-mems)*sizeof(*memlist));
229                 for (o=0; &mems[o] != memlist; o++)
230                         strp->S.memlist[o] = mems[o];
231                 memlist = savememlist;
232                 sparent = savesparent;
233                 nmems = savenmems;
234                 if ((o = symbol()) != RBRACE)
235                         goto syntax;
236         }
237         return(strp);
238    syntax:
239         decsyn(o);
240         return(0);
241 }
242
243 /*
244  * Process a comma-separated list of declarators
245  */
246 int declare(askw, tptr, offset) int askw; struct nmlist *tptr; int offset; {
247         register unsigned o;
248         register int skw, isunion;
249         struct nmlist abs, *aptr;
250
251         skw = askw;
252         isunion = 0;
253         if (skw==MOU) {
254                 skw = MOS;
255                 isunion++;
256                 mosflg = FMOS;
257                 if ((peeksym=symbol()) == SEMI) {
258                         o = length((union tree *)tptr);
259                         if (o>offset)
260                                 offset = o;
261                 }
262         }
263         do {
264                 if (skw==ENUM && (peeksym=symbol())==RBRACE) {
265                         o = peeksym;
266                         peeksym = -1;
267                         break;
268                 }
269                 if (skw == MOS) {
270                         abs.hclass = 0;
271                         abs.hflag = 0;
272                         abs.htype = 0;
273                         abs.hsubsp = 0;
274                         abs.hstrp = 0;
275                         abs.nextnm = 0;
276                         abs.sparent = 0;
277                         abs.hblklev = blklev;
278                         abs.name = "<none>";
279                         aptr = &abs;
280                 } else
281                         aptr = NULL;
282                 o = decl1(skw, tptr, isunion?0:offset, aptr);
283                 if (isunion) {
284                         o += align(CHAR, o, 0);
285                         if (o>offset)
286                                 offset = o;
287                 } else
288                         offset += o;
289         } while ((o=symbol()) == COMMA);
290         if (o==RBRACE) {
291                 peeksym = o;
292                 o = SEMI;
293         }
294         if (o!=SEMI && (o!=RPARN || skw!=ARG1))
295                 decsyn(o);
296         return(offset);
297 }
298
299 /*
300  * Process a single declarator
301  */
302 int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offset; struct nmlist *absname; {
303         int t1, a, elsize;
304         register int skw;
305         int type;
306         register struct nmlist *dsym;
307         register struct nmlist *tptr;
308         struct tdim dim;
309         int *dp;
310         int isinit;
311
312         skw = askw;
313         tptr = atptr;
314         mosflg = skw==MOS? FMOS: 0;
315         dim.rank = 0;
316         if (((peeksym=symbol())==SEMI || peeksym==RPARN) && absname==NULL)
317                 return(0);
318         /*
319          * Filler field
320          */
321         if (peeksym==COLON && skw==MOS) {
322                 peeksym = -1;
323                 t1 = conexp();
324                 if (t1<0) {
325                         error0("Negative field width");
326                         t1 = 0;
327                 }
328                 elsize = align(tptr->htype, offset, t1);
329                 bitoffs += t1;
330                 return(elsize);
331         }
332         t1 = getype(&dim, absname);
333         if (t1 == -1)
334                 return(0);
335         if (defsym)
336                 absname = NULL;
337         if (tptr->hsubsp) {
338                 type = tptr->htype;
339                 for (a=0; type&XTYPE;) {
340                         if ((type&XTYPE)==ARRAY)
341                                 dim.dimens[dim.rank++] = tptr->hsubsp[a++];
342                         type >>= TYLEN;
343                 }
344         }
345         type = tptr->htype & ~TYPE;
346         while (t1&XTYPE) {
347                 if (type&BIGTYPE) {
348                         typov();
349                         type = t1 = 0;
350                 }
351                 type = type<<TYLEN | (t1 & XTYPE);
352                 t1 >>= TYLEN;
353         }
354         type |= tptr->htype&TYPE;
355         if ((type&XTYPE) == FUNC) {
356                 if (skw==AUTO)
357                         skw = EXTERN;
358                 if ((skw!=EXTERN && skw!=TYPEDEF) && absname==NULL)
359                         error0("Bad func. storage class");
360         }
361         if (defsym)
362                 dsym = defsym;
363         else if (absname)
364                 dsym = absname;
365         else {
366                 error0("Name required in declaration");
367                 return(0);
368         }
369         if (defsym)
370         if (dsym->hblklev<blklev || dsym->hclass==MOS && skw==MOS) {
371                 if (skw==MOS && dsym->sparent==sparent)
372                         redec();
373                 defsym = dsym;
374                 if (skw==EXTERN) {
375                         for (; dsym!=NULL; dsym = dsym->nextnm) {
376                                 if (dsym->hclass==EXTERN
377                                  && strcmp(dsym->name, defsym->name)==0) {
378                                         defsym = dsym;
379                                         break;
380                                 }
381                         }
382                         dsym = defsym;
383                 } else
384                         defsym = dsym = pushdecl(dsym);
385         }
386         if (dim.rank == 0)
387                 dsym->hsubsp = NULL;
388         else {
389                 /*
390                  * If an array is declared twice, make sure the declarations
391                  * agree in dimension.  This happens typically when a .h
392                  * and .c file both declare a variable.
393                  */
394                 if (dsym->hsubsp) {
395                         for (a=0, t1 = dsym->htype;
396                             a<dim.rank && (t1&XTYPE)==ARRAY;
397                             a++, t1 >>= TYLEN)
398                                 /*
399                                  * If we haven't seen a declaration for this
400                                  * dimension yet, take what's been given now.
401                                  */
402                                 if (!dsym->hsubsp[a])
403                                         dsym->hsubsp[a] = dim.dimens[a];
404                                 else if (dim.dimens[a]
405                                     && dim.dimens[a] != dsym->hsubsp[a])
406                                         redec();
407                         if (a<dim.rank || (t1&XTYPE)==ARRAY)
408                                 redec();
409                 } else {
410                         dp = (int *)Dblock(dim.rank*sizeof(dim.rank));
411                         for (a=0; a<dim.rank; a++)
412                                 dp[a] = dim.dimens[a];
413                         dsym->hsubsp = dp;
414                 }
415         }
416         if (!(dsym->hclass==0
417            || ((skw==ARG||skw==AREG) && dsym->hclass==ARG1)
418            || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type))) {
419                 redec();
420                 goto syntax;
421         }
422         if (dsym->hclass && (dsym->htype&TYPE)==STRUCT && (type&TYPE)==STRUCT)
423                 if (dsym->hstrp != tptr->hstrp) {
424                         error0("structure redeclaration");
425                 }
426         dsym->htype = type;
427         if (tptr->hstrp)
428                 dsym->hstrp = tptr->hstrp;
429         if (skw==TYPEDEF) {
430                 dsym->hclass = TYPEDEF;
431                 return(0);
432         }
433         if (skw==ARG1) {
434                 if (paraml==NULL)
435                         paraml = dsym;
436                 else
437                         parame->sparent = (union str *)dsym;
438                 parame = dsym;
439                 dsym->hclass = skw;
440                 return(0);
441         }
442         elsize = 0;
443         if (skw==MOS) {
444                 elsize = length((union tree *)dsym);
445                 if ((peeksym = symbol())==COLON) {
446                         elsize = 0;
447                         peeksym = -1;
448                         t1 = conexp();
449                         a = align(type, offset, t1);
450                         if (dsym->hflag&FFIELD) {
451                                 if (dsym->hstrp->F.bitoffs!=bitoffs
452                                  || dsym->hstrp->F.flen!=t1)
453                                         redec();
454                         } else {
455                                 dsym->hstrp = (union str *)Dblock(sizeof(struct FS));
456                         }
457                         dsym->hflag |= FFIELD;
458                         dsym->hstrp->F.bitoffs = bitoffs;
459                         dsym->hstrp->F.flen = t1;
460                         bitoffs += t1;
461                 } else
462                         a = align(type, offset, 0);
463                 elsize += a;
464                 offset += a;
465                 if (++nmems >= NMEMS) {
466                         error0("Too many structure members");
467                         nmems -= NMEMS/2;
468                         memlist -= NMEMS/2;
469                 }
470                 if (a)
471                         *memlist++ = &structhole;
472                 dsym->hoffset = offset;
473                 *memlist++ = dsym;
474                 dsym->sparent = sparent;
475         }
476         if (skw==REG)
477                 if ((dsym->hoffset = goodreg(dsym)) < 0)
478                         skw = AUTO;
479         dsym->hclass = skw;
480         isinit = 0;
481         if ((a=symbol()) == ASSIGN)
482                 isinit++;
483         else
484                 peeksym = a;
485         if (skw==AUTO) {
486         /*      if (STAUTO < 0) {       */
487  /*fprintf(stderr, "%s autolen %d -> ", dsym->name, autolen);*/
488                         autolen -= rlength((union tree *)dsym);
489                         dsym->hoffset = autolen;
490                         if (autolen < maxauto)
491                                 maxauto = autolen;
492  /*fprintf(stderr, "%d maxauto %d\n", autolen, maxauto);*/
493         /*      } else {                        */
494         /*              dsym->hoffset = autolen;        */
495         /*              autolen += rlength(dsym);       */
496         /*              if (autolen > maxauto)          */
497         /*                      maxauto = autolen;      */
498         /*      }                       */
499                 if (isinit)
500                         cinit(dsym, 0, AUTO);
501                 isinit = 0;
502         } else if (skw==STATIC) {
503                 dsym->hoffset = isn0;
504                 if (isinit) {
505                         outcode("BBN", DATA, LABEL, isn0++);
506                         if (cinit(dsym, 1, STATIC) & ALIGN)
507                                 outcode("B", EVEN);
508                 } else
509                         outcode("BBNBN", BSS, LABEL, isn0++, SSPACE,
510                           rlength((union tree *)dsym));
511                 outcode("B", PROG);
512                 isinit = 0;
513         } else if (skw==REG && isinit) {
514                 cinit(dsym, 0, REG);
515                 isinit = 0;
516         } else if (skw==ENUM) {
517                 if (type!=INT)
518                         error0("Illegal enumeration %s", dsym->name);
519                 dsym->hclass = ENUMCON;
520                 dsym->hoffset = offset;
521                 if (isinit)
522                         cinit(dsym, 0, ENUMCON);
523                 elsize = dsym->hoffset-offset+1;
524                 isinit = 0;
525         }
526         if (absname==0)
527                 prste(dsym);
528         if (isinit)
529                 peeksym = ASSIGN;
530 syntax:
531         return(elsize);
532 }
533
534 /*
535  * Push down an outer-block declaration
536  * after redeclaration in an inner block.
537  */
538 struct nmlist *pushdecl(sp) register struct nmlist *sp; {
539         register struct nmlist *nsp, **hsp;
540
541         nsp = (struct nmlist *)Dblock(sizeof(struct nmlist));
542         *nsp = *sp;
543         nsp->hclass = 0;
544         nsp->hflag &= FKIND;
545         nsp->htype = 0;
546         nsp->hoffset = 0;
547         nsp->hblklev = blklev;
548         nsp->hstrp = NULL;
549         nsp->hsubsp = NULL;
550         nsp->sparent = NULL;
551         hsp = &hshtab[hash(sp->name)];
552         nsp->nextnm = *hsp;
553         *hsp = nsp;
554         return(nsp);
555 }
556
557 /*
558  * Read a declarator and get the implied type
559  */
560 int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname; {
561         static struct nmlist argtype;
562         int type;
563         register int o;
564         register struct nmlist *ds;
565
566         defsym = 0;
567         type = 0;
568         switch(o=symbol()) {
569
570         case TIMES:
571                 type = getype(dimp, absname);
572                 if (type==-1)
573                         return(type);
574                 if (type&BIGTYPE) {
575                         typov();
576                         type = 0;
577                 }
578                 return(type<<TYLEN | PTR);
579
580         case LPARN:
581                 if (absname==NULL || nextchar()!=')') {
582                         type = getype(dimp, absname);
583                         if (type==-1)
584                                 return(type);
585                         if ((o=symbol()) != RPARN)
586                                 goto syntax;
587                         goto getf;
588                 }
589
590         default:
591                 peeksym = o;
592                 if (absname)
593                         goto getf;
594                 break;
595
596         case NAME:
597                 defsym = ds = csym;
598         getf:
599                 switch(o=symbol()) {
600
601                 case LPARN:
602                         if (blklev==0) {
603                                 blklev++;
604                                 ds = defsym;
605                                 declare(ARG1, &argtype, 0);
606                                 defsym = ds;
607                                 blklev--;
608                         } else
609                                 if ((o=symbol()) != RPARN)
610                                         goto syntax;
611                         if (type&BIGTYPE) {
612                                 typov();
613                                 type = 0;
614                         }
615                         type = type<<TYLEN | FUNC;
616                         goto getf;
617
618                 case LBRACK:
619                         if (dimp->rank>=5) {
620                                 error0("Rank too large");
621                                 dimp->rank = 4;
622                         }
623                         if ((o=symbol()) != RBRACK) {
624                                 peeksym = o;
625                                 ds = defsym;
626                                 cval = conexp();
627                                 defsym = ds;
628                                 if ((o=symbol())!=RBRACK)
629                                         goto syntax;
630                         } else {
631                                 if (dimp->rank!=0)
632                                         error0("Null dimension");
633                                 cval = 0;
634                         }
635                         dimp->dimens[dimp->rank++] = cval;
636                         if (type&BIGTYPE) {
637                                 typov();
638                                 type = 0;
639                         }
640                         type = type<<TYLEN | ARRAY;
641                         goto getf;
642                 }
643                 peeksym = o;
644                 return(type);
645         }
646 syntax:
647         decsyn(o);
648         return(-1);
649 }
650
651 /*
652  * More bits required for type than allowed.
653  */
654 void typov() {
655         error0("Type is too complicated");
656 }
657
658 /*
659  * Enforce alignment restrictions in structures,
660  * including bit-field considerations.
661  */
662 int align(type, offset, aflen) int type; int offset; int aflen; {
663         register int a, t, flen;
664         char *ftl;
665
666         flen = aflen;
667         a = offset;
668         t = type;
669         ftl = "Field too long";
670         if (flen==0) {
671                 a += (NBPC+bitoffs-1) / NBPC;
672                 bitoffs = 0;
673         }
674         while ((t&XTYPE)==ARRAY)
675                 t = decref0(t);
676         if (t!=CHAR && t!=UNCHAR) {
677                 a = (a+ALIGN) & ~ALIGN;
678                 if (a>offset)
679                         bitoffs = 0;
680         }
681         if (flen) {
682                 if (type==INT || type==UNSIGN) {
683                         if (flen > NBPW)
684                                 error0(ftl);
685                         if (flen+bitoffs > NBPW) {
686                                 bitoffs = 0;
687                                 a += NCPW;
688                         }
689                 } else if (type==CHAR || type==UNCHAR) {
690                         if (flen > NBPC)
691                                 error0(ftl);
692                         if (flen+bitoffs > NBPC) {
693                                 bitoffs = 0;
694                                 a += 1;
695                         }
696                 } else
697                         error0("Bad type for field");
698         }
699         return(a-offset);
700 }
701
702 /*
703  * Complain about syntax error in declaration
704  */
705 void decsyn(o) int o; {
706         error0("Declaration syntax");
707         errflush(o);
708 }
709
710 /*
711  * Complain about a redeclaration
712  */
713 void redec() {
714         error0("%s redeclared", defsym->name);
715 }
716
717 /*
718  * Determine if a variable is suitable for storage in
719  * a register; if so return the register number
720  */
721 int goodreg(hp) struct nmlist *hp; {
722         int type;
723
724         type = hp->htype;
725         if ((type!=INT && type!=UNSIGN && (type&XTYPE)==0)
726          || (type&XTYPE)>PTR || regvar<3)
727                 return(-1);
728         return(--regvar);
729 }