Commit | Line | Data |
---|---|---|
3823a6ae DR |
1 | # |
2 | /* C compiler | |
3 | * | |
4 | * | |
5 | */ | |
6 | ||
7 | #include "c0.h" | |
8 | ||
9 | /* | |
10 | * Process a single external definition | |
11 | */ | |
12 | extdef() | |
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; | |
85 | syntax: | |
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 | */ | |
99 | cfunc() | |
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 | */ | |
136 | cinit(anp, flex, sclass) | |
137 | struct 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 | */ | |
242 | strinit(np, sclass) | |
243 | struct 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 | */ | |
284 | setinit(anp) | |
285 | struct 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 | */ | |
298 | statement() | |
299 | { | |
300 | register o, o1, o2; | |
301 | int o3; | |
302 | struct tnode *np; | |
303 | int sauto, sreg; | |
304 | ||
305 | stmt: | |
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 | ||
523 | semi: | |
524 | if ((o=symbol())==SEMI) | |
525 | return; | |
526 | syntax: | |
527 | error("Statement syntax"); | |
528 | errflush(o); | |
529 | } | |
530 | ||
531 | /* | |
532 | * Process a for statement. | |
533 | */ | |
534 | forstmt() | |
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 | */ | |
586 | struct tnode * | |
587 | pexpr() | |
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); | |
597 | syntax: | |
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 | */ | |
607 | pswitch() | |
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 | */ | |
642 | struct hshtab hreg { REG, 0, 0, NULL, NULL, 0 }; | |
643 | struct tnode areg { NAME, 0, NULL, NULL, &hreg}; | |
644 | funchead() | |
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 | ||
686 | blockhead() | |
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 | */ | |
702 | blkend() | |
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 | */ | |
753 | prste(acs) | |
754 | struct 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 | */ | |
784 | errflush(ao) | |
785 | { | |
786 | register o; | |
787 | ||
788 | o = ao; | |
789 | while(o>RBRACE) /* ; { } */ | |
790 | o = symbol(); | |
791 | peeksym = o; | |
792 | } |