Research V7 development
[unix-history] / usr / src / cmd / c / c02.c
CommitLineData
3823a6ae
DR
1#
2/* C compiler
3 *
4 *
5 */
6
7#include "c0.h"
8
9/*
10 * Process a single external definition
11 */
12extdef()
13{
14 register o;
15 int sclass, scflag, *cb;
16 struct hshtab typer;
17 register struct hshtab *ds;
18
19 if(((o=symbol())==EOFC) || o==SEMI)
20 return;
21 peeksym = o;
22 sclass = 0;
23 blklev = 0;
24 if (getkeywords(&sclass, &typer)==0) {
25 sclass = EXTERN;
26 if (peeksym!=NAME)
27 goto syntax;
28 }
29 scflag = 0;
30 if (sclass==DEFXTRN) {
31 scflag++;
32 sclass = EXTERN;
33 }
34 if (sclass!=EXTERN && sclass!=STATIC && sclass!=TYPEDEF)
35 error("Illegal storage class");
36 do {
37 defsym = 0;
38 paraml = 0;
39 parame = 0;
40 if (sclass==TYPEDEF) {
41 decl1(TYPEDEF, &typer, 0, NULL);
42 continue;
43 }
44 decl1(EXTERN, &typer, 0, NULL);
45 if ((ds=defsym)==0)
46 return;
47 funcsym = ds;
48 if ((ds->type&XTYPE)==FUNC) {
49 if ((peeksym=symbol())==LBRACE || peeksym==KEYW
50 || (peeksym==NAME && csym->hclass==TYPEDEF)) {
51 funcblk.type = decref(ds->type);
52 funcblk.strp = ds->strp;
53 setinit(ds);
54 outcode("BS", SYMDEF, sclass==EXTERN?ds->name:"");
55 cfunc();
56 return;
57 }
58 if (paraml)
59 error("Inappropriate parameters");
60 } else if ((o=symbol())==COMMA || o==SEMI) {
61 peeksym = o;
62 o = (length(ds)+ALIGN) & ~ALIGN;
63 if (sclass==STATIC) {
64 setinit(ds);
65 outcode("BSBBSBN", SYMDEF, "", BSS, NLABEL, ds->name, SSPACE, o);
66 } else if (scflag)
67 outcode("BSN", CSPACE, ds->name, o);
68 } else {
69 if (o!=ASSIGN)
70 peeksym = o;
71 setinit(ds);
72 if (sclass==EXTERN)
73 outcode("BS", SYMDEF, ds->name);
74 outcode("BBS", DATA, NLABEL, ds->name);
75 cb = funcbase;
76 if (cinit(ds, 1, sclass) & ALIGN)
77 outcode("B", EVEN);
78 if (maxdecl > cb)
79 cb = maxdecl;
80 funcbase = cb;
81 }
82 } while ((o=symbol())==COMMA);
83 if (o==SEMI)
84 return;
85syntax:
86 if (o==RBRACE) {
87 error("Too many }'s");
88 peeksym = 0;
89 return;
90 }
91 error("External definition syntax");
92 errflush(o);
93 statement();
94}
95
96/*
97 * Process a function definition.
98 */
99cfunc()
100{
101 register int *cb;
102 register sloc;
103
104 sloc = isn;
105 isn =+ 2;
106 outcode("BBS", PROG, RLABEL, funcsym->name);
107 if (proflg)
108 outcode("BN", PROFIL, isn++);
109 cb = curbase;
110 regvar = 5;
111 autolen = STAUTO;
112 maxauto = STAUTO;
113 blklev = 1;
114 declist(ARG);
115 outcode("B", SAVE);
116 funchead();
117 branch(sloc);
118 label(sloc+1);
119 retlab = isn++;
120 blklev = 0;
121 if ((peeksym = symbol()) != LBRACE)
122 error("Compound statement required");
123 statement();
124 outcode("BNB", LABEL, retlab, RETRN);
125 label(sloc);
126 outcode("BN", SETSTK, -maxauto);
127 branch(sloc+1);
128 if (cb < maxdecl)
129 cb = maxdecl;
130 curbase = funcbase = cb;
131}
132
133/*
134 * Process the initializers for an external definition.
135 */
136cinit(anp, flex, sclass)
137struct hshtab *anp;
138{
139 register struct phshtab *np;
140 register nel, ninit;
141 int width, isarray, o, brace, realtype, *cb;
142 struct tnode *s;
143
144 cb = funcbase;
145 np = gblock(sizeof(*np));
146 funcbase = curbase;
147 cpysymb(np, anp);
148 realtype = np->type;
149 isarray = 0;
150 if ((realtype&XTYPE) == ARRAY)
151 isarray++;
152 else
153 flex = 0;
154 width = length(np);
155 nel = 1;
156 /*
157 * If it's an array, find the number of elements.
158 * temporarily modify to look like kind of thing it's
159 * an array of.
160 */
161 if (sclass==AUTO)
162 if (isarray || realtype==STRUCT)
163 error("No auto. aggregate initialization");
164 if (isarray) {
165 np->type = decref(realtype);
166 np->subsp++;
167 if (width==0 && flex==0)
168 error("0-length row: %.8s", anp->name);
169 o = length(np);
170 /* nel = ldiv(0, width, o); */
171 nel = (unsigned)width/o;
172 width = o;
173 }
174 brace = 0;
175 if ((peeksym=symbol())==LBRACE && (isarray || np->type!=STRUCT)) {
176 peeksym = -1;
177 brace++;
178 }
179 ninit = 0;
180 do {
181 if ((o=symbol())==RBRACE)
182 break;
183 peeksym = o;
184 if (o==STRING && realtype==ARRAY+CHAR) {
185 if (sclass==AUTO)
186 error("No strings in automatic");
187 peeksym = -1;
188 putstr(0, flex?10000:nel);
189 ninit =+ nchstr;
190 o = symbol();
191 break;
192 } else if (np->type==STRUCT) {
193 strinit(np, sclass);
194 } else if ((np->type&ARRAY)==ARRAY || peeksym==LBRACE)
195 cinit(np, 0, sclass);
196 else {
197 initflg++;
198 s = tree();
199 initflg = 0;
200 if (np->hflag&FFIELD)
201 error("No field initialization");
202 *cp++ = nblock(np);
203 *cp++ = s;
204 build(ASSIGN);
205 if (sclass==AUTO||sclass==REG)
206 rcexpr(*--cp);
207 else if (sclass==ENUMCON) {
208 if (s->op!=CON)
209 error("Illegal enum constant for %.8s", anp->name);
210 anp->hoffset = s->value;
211 } else
212 rcexpr(block(INIT,np->type,NULL,NULL,(*--cp)->tr2));
213 }
214 ninit++;
215 if ((ninit&077)==0 && sclass==EXTERN)
216 outcode("BS", SYMDEF, "");
217 } while ((o=symbol())==COMMA && (ninit<nel || brace || flex));
218 if (brace==0 || o!=RBRACE)
219 peeksym = o;
220 /*
221 * If there are too few initializers, allocate
222 * more storage.
223 * If there are too many initializers, extend
224 * the declared size for benefit of "sizeof"
225 */
226 if (ninit<nel && sclass!=AUTO)
227 outcode("BN", SSPACE, (nel-ninit)*width);
228 else if (ninit>nel) {
229 if (flex && nel==0) {
230 np->subsp[-1] = ninit;
231 } else
232 error("Too many initializers: %.8s", anp->name);
233 nel = ninit;
234 }
235 curbase = funcbase = cb;
236 return(nel*width);
237}
238
239/*
240 * Initialize a structure
241 */
242strinit(np, sclass)
243struct tnode *np;
244{
245 register struct hshtab **mlp;
246 static zerloc;
247 register int o, brace;
248
249 if ((mlp = np->strp->memlist)==NULL) {
250 mlp = &zerloc;
251 error("Undefined structure initialization");
252 }
253 brace = 0;
254 if ((o = symbol()) == LBRACE)
255 brace++;
256 else
257 peeksym = o;
258 do {
259 if ((o=symbol()) == RBRACE)
260 break;
261 peeksym = o;
262 if (*mlp==0) {
263 error("Too many structure initializers");
264 cinit(&funcblk, 0, sclass);
265 } else
266 cinit(*mlp++, 0, sclass);
267 if (*mlp == &structhole) {
268 outcode("B", EVEN);
269 mlp++;
270 }
271 } while ((o=symbol())==COMMA && (*mlp || brace));
272 if (sclass!=AUTO && sclass!=REG) {
273 if (*mlp)
274 outcode("BN", SSPACE, np->strp->ssize - (*mlp)->hoffset);
275 outcode("B", EVEN);
276 }
277 if (o!=RBRACE || brace==0)
278 peeksym = o;
279}
280
281/*
282 * Mark already initialized
283 */
284setinit(anp)
285struct hshtab *anp;
286{
287 register struct hshtab *np;
288
289 np = anp;
290 if (np->hflag&FINIT)
291 error("%s multiply defined", np->name);
292 np->hflag =| FINIT;
293}
294
295/*
296 * Process one statement in a function.
297 */
298statement()
299{
300 register o, o1, o2;
301 int o3;
302 struct tnode *np;
303 int sauto, sreg;
304
305stmt:
306 switch(o=symbol()) {
307
308 case EOFC:
309 error("Unexpected EOF");
310 case SEMI:
311 return;
312
313 case LBRACE:
314 sauto = autolen;
315 sreg = regvar;
316 blockhead();
317 while (!eof) {
318 if ((o=symbol())==RBRACE) {
319 autolen = sauto;
320 if (sreg!=regvar)
321 outcode("BN", SETREG, sreg);
322 regvar = sreg;
323 blkend();
324 return;
325 }
326 peeksym = o;
327 statement();
328 }
329 error("Missing '}'");
330 return;
331
332 case KEYW:
333 switch(cval) {
334
335 case GOTO:
336 if (o1 = simplegoto())
337 branch(o1);
338 else
339 dogoto();
340 goto semi;
341
342 case RETURN:
343 doret();
344 goto semi;
345
346 case IF:
347 np = pexpr();
348 o2 = 0;
349 if ((o1=symbol())==KEYW) switch (cval) {
350 case GOTO:
351 if (o2=simplegoto())
352 goto simpif;
353 cbranch(np, o2=isn++, 0);
354 dogoto();
355 label(o2);
356 goto hardif;
357
358 case RETURN:
359 if (nextchar()==';') {
360 o2 = retlab;
361 goto simpif;
362 }
363 cbranch(np, o1=isn++, 0);
364 doret();
365 label(o1);
366 o2++;
367 goto hardif;
368
369 case BREAK:
370 o2 = brklab;
371 goto simpif;
372
373 case CONTIN:
374 o2 = contlab;
375 simpif:
376 chconbrk(o2);
377 cbranch(np, o2, 1);
378 hardif:
379 if ((o=symbol())!=SEMI)
380 goto syntax;
381 if ((o1=symbol())==KEYW && cval==ELSE)
382 goto stmt;
383 peeksym = o1;
384 return;
385 }
386 peeksym = o1;
387 cbranch(np, o1=isn++, 0);
388 statement();
389 if ((o=symbol())==KEYW && cval==ELSE) {
390 o2 = isn++;
391 branch(o2);
392 label(o1);
393 statement();
394 label(o2);
395 return;
396 }
397 peeksym = o;
398 label(o1);
399 return;
400
401 case WHILE:
402 o1 = contlab;
403 o2 = brklab;
404 label(contlab = isn++);
405 cbranch(pexpr(), brklab=isn++, 0);
406 statement();
407 branch(contlab);
408 label(brklab);
409 contlab = o1;
410 brklab = o2;
411 return;
412
413 case BREAK:
414 chconbrk(brklab);
415 branch(brklab);
416 goto semi;
417
418 case CONTIN:
419 chconbrk(contlab);
420 branch(contlab);
421 goto semi;
422
423 case DO:
424 o1 = contlab;
425 o2 = brklab;
426 contlab = isn++;
427 brklab = isn++;
428 label(o3 = isn++);
429 statement();
430 label(contlab);
431 contlab = o1;
432 if ((o=symbol())==KEYW && cval==WHILE) {
433 cbranch(tree(), o3, 1);
434 label(brklab);
435 brklab = o2;
436 goto semi;
437 }
438 goto syntax;
439
440 case CASE:
441 o1 = conexp();
442 if ((o=symbol())!=COLON)
443 goto syntax;
444 if (swp==0) {
445 error("Case not in switch");
446 goto stmt;
447 }
448 if(swp>=swtab+SWSIZ) {
449 error("Switch table overflow");
450 } else {
451 swp->swlab = isn;
452 (swp++)->swval = o1;
453 label(isn++);
454 }
455 goto stmt;
456
457 case SWITCH:
458 o1 = brklab;
459 brklab = isn++;
460 np = pexpr();
461 chkw(np, -1);
462 rcexpr(block(RFORCE,0,NULL,NULL,np));
463 pswitch();
464 brklab = o1;
465 return;
466
467 case DEFAULT:
468 if (swp==0)
469 error("Default not in switch");
470 if (deflab)
471 error("More than 1 'default'");
472 if ((o=symbol())!=COLON)
473 goto syntax;
474 label(deflab = isn++);
475 goto stmt;
476
477 case FOR:
478 o1 = contlab;
479 o2 = brklab;
480 contlab = isn++;
481 brklab = isn++;
482 if (o=forstmt())
483 goto syntax;
484 label(brklab);
485 contlab = o1;
486 brklab = o2;
487 return;
488
489 case ELSE:
490 error("Inappropriate 'else'");
491 statement();
492 return;
493 }
494 error("Unknown keyword");
495 goto syntax;
496
497 case NAME:
498 if (nextchar()==':') {
499 peekc = 0;
500 o1 = csym;
501 if (o1->hclass>0) {
502 if (o1->hblklev==0) {
503 pushdecl(o1);
504 o1->hoffset = 0;
505 } else {
506 defsym = o1;
507 redec();
508 goto stmt;
509 }
510 }
511 o1->hclass = STATIC;
512 o1->htype = ARRAY;
513 o1->hflag =| FLABL;
514 if (o1->hoffset==0)
515 o1->hoffset = isn++;
516 label(o1->hoffset);
517 goto stmt;
518 }
519 }
520 peeksym = o;
521 rcexpr(tree());
522
523semi:
524 if ((o=symbol())==SEMI)
525 return;
526syntax:
527 error("Statement syntax");
528 errflush(o);
529}
530
531/*
532 * Process a for statement.
533 */
534forstmt()
535{
536 register int l, o, sline;
537 int sline1, *ss;
538 struct tnode *st;
539
540 if ((o=symbol()) != LPARN)
541 return(o);
542 if ((o=symbol()) != SEMI) { /* init part */
543 peeksym = o;
544 rcexpr(tree());
545 if ((o=symbol()) != SEMI)
546 return(o);
547 }
548 label(contlab);
549 if ((o=symbol()) != SEMI) { /* test part */
550 peeksym = o;
551 cbranch(tree(), brklab, 0);
552 if ((o=symbol()) != SEMI)
553 return(o);
554 }
555 if ((peeksym=symbol()) == RPARN) { /* incr part */
556 peeksym = -1;
557 statement();
558 branch(contlab);
559 return(0);
560 }
561 l = contlab;
562 contlab = isn++;
563 st = tree();
564 sline = line;
565 if ((o=symbol()) != RPARN)
566 return(o);
567 ss = funcbase;
568 funcbase = curbase;
569 statement();
570 sline1 = line;
571 line = sline;
572 label(contlab);
573 rcexpr(st);
574 line = sline1;
575 if (ss < maxdecl)
576 ss = maxdecl;
577 curbase = funcbase = ss;
578 branch(l);
579 return(0);
580}
581
582/*
583 * A parenthesized expression,
584 * as after "if".
585 */
586struct tnode *
587pexpr()
588{
589 register o, t;
590
591 if ((o=symbol())!=LPARN)
592 goto syntax;
593 t = tree();
594 if ((o=symbol())!=RPARN)
595 goto syntax;
596 return(t);
597syntax:
598 error("Statement syntax");
599 errflush(o);
600 return(0);
601}
602
603/*
604 * The switch statement, which involves collecting the
605 * constants and labels for the cases.
606 */
607pswitch()
608{
609 register struct swtab *cswp, *sswp;
610 int dl, swlab;
611
612 cswp = sswp = swp;
613 if (swp==0)
614 cswp = swp = swtab;
615 branch(swlab=isn++);
616 dl = deflab;
617 deflab = 0;
618 statement();
619 branch(brklab);
620 label(swlab);
621 if (deflab==0)
622 deflab = brklab;
623 outcode("BNN", SWIT, deflab, line);
624 for (; cswp < swp; cswp++)
625 outcode("NN", cswp->swlab, cswp->swval);
626 outcode("0");
627 label(brklab);
628 deflab = dl;
629 swp = sswp;
630}
631
632/*
633 * funchead is called at the start of each function
634 * to process the arguments, which have been linked in a list.
635 * This list is necessary because in
636 * f(a, b) float b; int a; ...
637 * the names are seen before the types.
638 */
639/*
640 * Structure resembling a block for a register variable.
641 */
642struct hshtab hreg { REG, 0, 0, NULL, NULL, 0 };
643struct tnode areg { NAME, 0, NULL, NULL, &hreg};
644funchead()
645{
646 register pl;
647 register struct hshtab *cs;
648 struct tnode *bstack[2];
649
650 pl = STARG;
651 while(paraml) {
652 parame->hoffset = 0;
653 cs = paraml;
654 paraml = paraml->hoffset;
655 if (cs->htype==FLOAT)
656 cs->htype = DOUBLE;
657 cs->hoffset = pl;
658 if ((cs->htype&XTYPE) == ARRAY) {
659 cs->htype =- (ARRAY-PTR); /* set ptr */
660 cs->subsp++; /* pop dims */
661 }
662 pl =+ rlength(cs);
663 if (cs->hclass==AREG && (hreg.hoffset=goodreg(cs))>=0) {
664 bstack[0] = &areg;
665 bstack[1] = nblock(cs);
666 cp = &bstack[2];
667 areg.type = cs->htype;
668 cs->hclass = AUTO;
669 build(ASSIGN);
670 rcexpr(bstack[0]);
671 cs->hoffset = hreg.hoffset;
672 cs->hclass = REG;
673 } else
674 cs->hclass = AUTO;
675 prste(cs);
676 }
677 for (cs=hshtab; cs<hshtab+HSHSIZ; cs++) {
678 if (cs->name[0] == '\0')
679 continue;
680 if (cs->hclass == ARG || cs->hclass==AREG)
681 error("Not an argument: %.8s", cs->name);
682 }
683 outcode("BN", SETREG, regvar);
684}
685
686blockhead()
687{
688 register r;
689
690 r = regvar;
691 blklev++;
692 declist(0);
693 if (r != regvar)
694 outcode("BN", SETREG, regvar);
695}
696
697/*
698 * After the end of a block, delete local
699 * symbols; save those that are external.
700 * Also complain about undefined labels.
701 */
702blkend()
703{
704 register struct hshtab *cs, *ncs;
705 struct hshtab *endcs;
706 register i;
707
708 blklev--;
709 for (cs=hshtab; cs->name[0] && cs<hshtab+HSHSIZ-1; ++cs)
710 ;
711 endcs = cs;
712 do if (cs->name[0]) {
713 if (cs->hblklev <= blklev)
714 continue;
715 if ((cs->hclass!=EXTERN || blklev!=0)
716 && ((cs->hflag&FLABL)==0 || blklev==0)) {
717 if (cs->hclass==0)
718 error("%.8s undefined", cs->name);
719 if ((ncs = cs->hpdown)==NULL) {
720 cs->name[0] = '\0';
721 hshused--;
722 cs->hflag =& FKEYW;
723 } else {
724 cpysymb(cs, ncs);
725 }
726 continue;
727 }
728 /*
729 * Retained name; must rehash.
730 */
731 for (i=0; i<NCPS; i++)
732 symbuf[i] = cs->name[i];
733 mossym = cs->hflag&FMOS;
734 lookup();
735 if ((ncs=csym) != cs) {
736 cs->name[0] = '\0';
737 hshused--;
738 i = ncs->hflag;
739 cpysymb(ncs, cs);
740 ncs->hflag =| i&FKEYW;
741 cs->hflag =& FKEYW;
742 }
743 if (ncs->hblklev>1 || (ncs->hblklev>0 && ncs->hclass==EXTERN))
744 ncs->hblklev--;
745 } while ((cs = (cs<&hshtab[HSHSIZ-1])? ++cs: hshtab) != endcs);
746}
747
748/*
749 * write out special definitions of local symbols for
750 * benefit of the debugger. None of these are used
751 * by the assembler except to save them.
752 */
753prste(acs)
754struct hshtab *acs;
755{
756 register struct hshtab *cs;
757 register nkind;
758
759 cs = acs;
760 switch (cs->hclass) {
761 case REG:
762 nkind = RNAME;
763 break;
764
765 case AUTO:
766 nkind = ANAME;
767 break;
768
769 case STATIC:
770 nkind = SNAME;
771 break;
772
773 default:
774 return;
775
776 }
777 outcode("BSN", nkind, cs->name, cs->hoffset);
778}
779
780/*
781 * In case of error, skip to the next
782 * statement delimiter.
783 */
784errflush(ao)
785{
786 register o;
787
788 o = ao;
789 while(o>RBRACE) /* ; { } */
790 o = symbol();
791 peeksym = o;
792}