C compiler from 211bsd.git commit 98921db
[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                                 error("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                                         error("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                                 error("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                                 error("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                                         error("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                                         error("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                         error("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                         error("%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                         error("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                         error("Bad func. storage class");
360         }
361         if (defsym)
362                 dsym = defsym;
363         else if (absname)
364                 dsym = absname;
365         else {
366                 error("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                         error("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                         error("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                         autolen -= rlength((union tree *)dsym);
488                         dsym->hoffset = autolen;
489                         if (autolen < maxauto)
490                                 maxauto = autolen;
491         /*      } else {                        */
492         /*              dsym->hoffset = autolen;        */
493         /*              autolen += rlength(dsym);       */
494         /*              if (autolen > maxauto)          */
495         /*                      maxauto = autolen;      */
496         /*      }                       */
497                 if (isinit)
498                         cinit(dsym, 0, AUTO);
499                 isinit = 0;
500         } else if (skw==STATIC) {
501                 dsym->hoffset = isn;
502                 if (isinit) {
503                         outcode("BBN", DATA, LABEL, isn++);
504                         if (cinit(dsym, 1, STATIC) & ALIGN)
505                                 outcode("B", EVEN);
506                 } else
507                         outcode("BBNBN", BSS, LABEL, isn++, SSPACE,
508                           rlength((union tree *)dsym));
509                 outcode("B", PROG);
510                 isinit = 0;
511         } else if (skw==REG && isinit) {
512                 cinit(dsym, 0, REG);
513                 isinit = 0;
514         } else if (skw==ENUM) {
515                 if (type!=INT)
516                         error("Illegal enumeration %s", dsym->name);
517                 dsym->hclass = ENUMCON;
518                 dsym->hoffset = offset;
519                 if (isinit)
520                         cinit(dsym, 0, ENUMCON);
521                 elsize = dsym->hoffset-offset+1;
522                 isinit = 0;
523         }
524         if (absname==0)
525                 prste(dsym);
526         if (isinit)
527                 peeksym = ASSIGN;
528 syntax:
529         return(elsize);
530 }
531
532 /*
533  * Push down an outer-block declaration
534  * after redeclaration in an inner block.
535  */
536 struct nmlist *pushdecl(sp) register struct nmlist *sp; {
537         register struct nmlist *nsp, **hsp;
538
539         nsp = (struct nmlist *)Dblock(sizeof(struct nmlist));
540         *nsp = *sp;
541         nsp->hclass = 0;
542         nsp->hflag &= FKIND;
543         nsp->htype = 0;
544         nsp->hoffset = 0;
545         nsp->hblklev = blklev;
546         nsp->hstrp = NULL;
547         nsp->hsubsp = NULL;
548         nsp->sparent = NULL;
549         hsp = &hshtab[hash(sp->name)];
550         nsp->nextnm = *hsp;
551         *hsp = nsp;
552         return(nsp);
553 }
554
555 /*
556  * Read a declarator and get the implied type
557  */
558 int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname; {
559         static struct nmlist argtype;
560         int type;
561         register int o;
562         register struct nmlist *ds;
563
564         defsym = 0;
565         type = 0;
566         switch(o=symbol()) {
567
568         case TIMES:
569                 type = getype(dimp, absname);
570                 if (type==-1)
571                         return(type);
572                 if (type&BIGTYPE) {
573                         typov();
574                         type = 0;
575                 }
576                 return(type<<TYLEN | PTR);
577
578         case LPARN:
579                 if (absname==NULL || nextchar()!=')') {
580                         type = getype(dimp, absname);
581                         if (type==-1)
582                                 return(type);
583                         if ((o=symbol()) != RPARN)
584                                 goto syntax;
585                         goto getf;
586                 }
587
588         default:
589                 peeksym = o;
590                 if (absname)
591                         goto getf;
592                 break;
593
594         case NAME:
595                 defsym = ds = csym;
596         getf:
597                 switch(o=symbol()) {
598
599                 case LPARN:
600                         if (blklev==0) {
601                                 blklev++;
602                                 ds = defsym;
603                                 declare(ARG1, &argtype, 0);
604                                 defsym = ds;
605                                 blklev--;
606                         } else
607                                 if ((o=symbol()) != RPARN)
608                                         goto syntax;
609                         if (type&BIGTYPE) {
610                                 typov();
611                                 type = 0;
612                         }
613                         type = type<<TYLEN | FUNC;
614                         goto getf;
615
616                 case LBRACK:
617                         if (dimp->rank>=5) {
618                                 error("Rank too large");
619                                 dimp->rank = 4;
620                         }
621                         if ((o=symbol()) != RBRACK) {
622                                 peeksym = o;
623                                 ds = defsym;
624                                 cval = conexp();
625                                 defsym = ds;
626                                 if ((o=symbol())!=RBRACK)
627                                         goto syntax;
628                         } else {
629                                 if (dimp->rank!=0)
630                                         error("Null dimension");
631                                 cval = 0;
632                         }
633                         dimp->dimens[dimp->rank++] = cval;
634                         if (type&BIGTYPE) {
635                                 typov();
636                                 type = 0;
637                         }
638                         type = type<<TYLEN | ARRAY;
639                         goto getf;
640                 }
641                 peeksym = o;
642                 return(type);
643         }
644 syntax:
645         decsyn(o);
646         return(-1);
647 }
648
649 /*
650  * More bits required for type than allowed.
651  */
652 void typov() {
653         error("Type is too complicated");
654 }
655
656 /*
657  * Enforce alignment restrictions in structures,
658  * including bit-field considerations.
659  */
660 int align(type, offset, aflen) int type; int offset; int aflen; {
661         register int a, t, flen;
662         char *ftl;
663
664         flen = aflen;
665         a = offset;
666         t = type;
667         ftl = "Field too long";
668         if (flen==0) {
669                 a += (NBPC+bitoffs-1) / NBPC;
670                 bitoffs = 0;
671         }
672         while ((t&XTYPE)==ARRAY)
673                 t = decref(t);
674         if (t!=CHAR && t!=UNCHAR) {
675                 a = (a+ALIGN) & ~ALIGN;
676                 if (a>offset)
677                         bitoffs = 0;
678         }
679         if (flen) {
680                 if (type==INT || type==UNSIGN) {
681                         if (flen > NBPW)
682                                 error(ftl);
683                         if (flen+bitoffs > NBPW) {
684                                 bitoffs = 0;
685                                 a += NCPW;
686                         }
687                 } else if (type==CHAR || type==UNCHAR) {
688                         if (flen > NBPC)
689                                 error(ftl);
690                         if (flen+bitoffs > NBPC) {
691                                 bitoffs = 0;
692                                 a += 1;
693                         }
694                 } else
695                         error("Bad type for field");
696         }
697         return(a-offset);
698 }
699
700 /*
701  * Complain about syntax error in declaration
702  */
703 void decsyn(o) int o; {
704         error("Declaration syntax");
705         errflush(o);
706 }
707
708 /*
709  * Complain about a redeclaration
710  */
711 void redec() {
712         error("%s redeclared", defsym->name);
713 }
714
715 /*
716  * Determine if a variable is suitable for storage in
717  * a register; if so return the register number
718  */
719 int goodreg(hp) struct nmlist *hp; {
720         int type;
721
722         type = hp->htype;
723         if ((type!=INT && type!=UNSIGN && (type&XTYPE)==0)
724          || (type&XTYPE)>PTR || regvar<3)
725                 return(-1);
726         return(--regvar);
727 }