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