BSD 4_3 release
[unix-history] / usr / src / usr.bin / f77 / src / f77pass1 / exec.c
CommitLineData
b21ea081
KM
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
95f51977 8static char sccsid[] = "@(#)exec.c 5.5 (Berkeley) 1/7/86";
b21ea081
KM
9#endif not lint
10
11/*
12 * exec.c
13 *
14 * Routines for handling the semantics of control structures.
15 * F77 compiler, pass 1.
16 *
17 * University of Utah CS Dept modification history:
18 *
bbfb589e 19 * $Log: exec.c,v $
6b16bb5d
DS
20 * Revision 5.6 85/12/20 19:42:46 donn
21 * Change style of error reporting in last fix.
22 *
23 * Revision 5.5 85/12/20 18:54:10 donn
24 * Complain about calls to things which aren't subroutines.
25 *
26 * Revision 5.4 85/12/18 19:57:58 donn
27 * Assignment statements are executable statements -- advance the magic
28 * parser state to forbid DATA statements and statement functions.
29 *
30 * Revision 5.3 85/11/25 00:23:49 donn
31 * 4.3 beta
32 *
bbfb589e
DS
33 * Revision 5.2 85/08/10 04:07:36 donn
34 * Changed an error message to correct spelling and be more accurate.
35 * From Jerry Berkman.
36 *
b21ea081
KM
37 * Revision 2.3 85/03/18 08:03:31 donn
38 * Hacks for conversions from type address to numeric type -- prevent addresses
39 * from being stored in shorts and prevent warnings about implicit conversions.
40 *
41 * Revision 2.2 84/09/03 23:18:30 donn
42 * When a DO loop had the same variable as its loop variable and its limit,
43 * the limit temporary was assigned to AFTER the original value of the variable
44 * was destroyed by assigning the initial value to the loop variable. I
45 * swapped the operands of a comparison and changed the direction of the
46 * operator... This only affected programs when optimizing. (This may not
47 * be enough if something alters the order of evaluation of side effects
48 * later on... sigh.)
49 *
50 * Revision 2.1 84/07/19 12:02:53 donn
51 * Changed comment headers for UofU.
52 *
53 * Revision 1.3 84/07/12 18:35:12 donn
54 * Added change to enddo() to detect open 'if' blocks at the ends of loops.
55 *
56 * Revision 1.2 84/06/08 11:22:53 donn
57 * Fixed bug in exdo() -- if a loop parameter contained an instance of the loop
58 * variable and the optimizer was off, the loop variable got converted to
59 * register before the parameters were processed and so the loop parameters
60 * were initialized from garbage in the register instead of the memory version
61 * of the loop variable.
62 *
63 */
64
b21ea081
KM
65#include "defs.h"
66#include "optim.h"
67
68
69/* Logical IF codes
70*/
71
72
73exif(p)
74expptr p;
75{
76register int k;
77pushctl(CTLIF);
78ctlstack->elselabel = newlabel();
79
80if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
81 {
82 if(k != TYERROR)
83 err("non-logical expression in IF statement");
84 frexpr(p);
85 }
86else if (optimflag)
87 optbuff (SKIFN, p, ctlstack->elselabel, 0);
88else
89 putif (p, ctlstack->elselabel);
90}
91
92
93
94exelif(p)
95expptr p;
96{
97int k,oldelse;
98
99if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
100 {
101 if(k != TYERROR)
102 err("non-logical expression in IF statement");
103 frexpr(p);
104 }
105else {
106 if(ctlstack->ctltype == CTLIF)
107 {
108 if(ctlstack->endlabel == 0) ctlstack->endlabel = newlabel();
109 oldelse=ctlstack->elselabel;
110 ctlstack->elselabel = newlabel();
111 if (optimflag)
112 {
113 optbuff (SKGOTO, 0, ctlstack->endlabel, 0);
114 optbuff (SKLABEL, 0, oldelse, 0);
115 optbuff (SKIFN, p, ctlstack->elselabel, 0);
116 }
117 else
118 {
119 putgoto (ctlstack->endlabel);
120 putlabel (oldelse);
121 putif (p, ctlstack->elselabel);
122 }
123 }
124 else execerr("elseif out of place", CNULL);
125 }
126}
127
128
129
130
131
132exelse()
133{
134if(ctlstack->ctltype==CTLIF)
135 {
136 if(ctlstack->endlabel == 0)
137 ctlstack->endlabel = newlabel();
138 ctlstack->ctltype = CTLELSE;
139 if (optimflag)
140 {
141 optbuff (SKGOTO, 0, ctlstack->endlabel, 0);
142 optbuff (SKLABEL, 0, ctlstack->elselabel, 0);
143 }
144 else
145 {
146 putgoto (ctlstack->endlabel);
147 putlabel (ctlstack->elselabel);
148 }
149 }
150
151else execerr("else out of place", CNULL);
152}
153
154
155exendif()
156{
157if (ctlstack->ctltype == CTLIF)
158 {
159 if (optimflag)
160 {
161 optbuff (SKLABEL, 0, ctlstack->elselabel, 0);
162 if (ctlstack->endlabel)
163 optbuff (SKLABEL, 0, ctlstack->endlabel, 0);
164 }
165 else
166 {
167 putlabel (ctlstack->elselabel);
168 if (ctlstack->endlabel)
169 putlabel (ctlstack->endlabel);
170 }
171 popctl ();
172 }
173else if (ctlstack->ctltype == CTLELSE)
174 {
175 if (optimflag)
176 optbuff (SKLABEL, 0, ctlstack->endlabel, 0);
177 else
178 putlabel (ctlstack->endlabel);
179 popctl ();
180 }
181else
182 execerr("endif out of place", CNULL);
183}
184
185
186
187LOCAL pushctl(code)
188int code;
189{
190register int i;
191
192/* fprintf(diagfile,"old blklevel %d \n",blklevel); dmpframe(ctlstack); */
193if(++ctlstack >= lastctl)
194 many("loops or if-then-elses", 'c');
195ctlstack->ctltype = code;
196for(i = 0 ; i < 4 ; ++i)
197 ctlstack->ctlabels[i] = 0;
198++blklevel;
199}
200
201
202LOCAL popctl()
203{
204if( ctlstack-- < ctls )
205 fatal("control stack empty");
206--blklevel;
207}
208
209
210
211LOCAL poplab()
212{
213register struct Labelblock *lp;
214
215for(lp = labeltab ; lp < highlabtab ; ++lp)
216 if(lp->labdefined)
217 {
218 /* mark all labels in inner blocks unreachable */
219 if(lp->blklevel > blklevel)
220 lp->labinacc = YES;
221 }
222 else if(lp->blklevel > blklevel)
223 {
224 /* move all labels referred to in inner blocks out a level */
225 lp->blklevel = blklevel;
226 }
227}
228\f
229
230
231/* BRANCHING CODE
232*/
233
234exgoto(lab)
235struct Labelblock *lab;
236{
237if (optimflag)
238 optbuff (SKGOTO, 0, lab->labelno, 0);
239else
240 putgoto (lab->labelno);
241}
242
243
244
245
246
247
248
249exequals(lp, rp)
250register struct Primblock *lp;
251register expptr rp;
252{
253register Namep np;
254
255if(lp->tag != TPRIM)
256 {
257 err("assignment to a non-variable");
258 frexpr(lp);
259 frexpr(rp);
260 }
261else if(lp->namep->vclass!=CLVAR && lp->argsp)
262 {
263 if(parstate >= INEXEC)
bbfb589e 264 err("undimensioned array or statement function out of order");
b21ea081
KM
265 else
266 mkstfunct(lp, rp);
267 }
268else
269 {
270 np = (Namep) lp->namep;
271 if (np->vclass == CLPROC && np->vprocclass == PTHISPROC
272 && proctype == TYSUBR)
273 {
274 err("assignment to a subroutine name");
275 return;
276 }
277 if(parstate < INDATA)
278 enddcl();
6b16bb5d 279 parstate = INEXEC;
b21ea081
KM
280 if (optimflag)
281 optbuff (SKEQ, mkexpr(OPASSIGN, mklhs(lp), fixtype(rp)), 0, 0);
282 else
283 puteq (mklhs(lp), fixtype(rp));
284 }
285}
286
287
288
289mkstfunct(lp, rp)
290struct Primblock *lp;
291expptr rp;
292{
293register struct Primblock *p;
294register Namep np;
295chainp args;
296
297if(parstate < INDATA)
298 {
299 enddcl();
300 parstate = INDATA;
301 }
302
303np = lp->namep;
304if(np->vclass == CLUNKNOWN)
305 np->vclass = CLPROC;
306else
307 {
308 dclerr("redeclaration of statement function", np);
309 return;
310 }
311np->vprocclass = PSTFUNCT;
312np->vstg = STGSTFUNCT;
313impldcl(np);
314args = (lp->argsp ? lp->argsp->listp : CHNULL);
315np->varxptr.vstfdesc = mkchain(args , rp );
316
317for( ; args ; args = args->nextp)
318 if( args->datap->tag!=TPRIM ||
319 (p = (struct Primblock *) (args->datap) )->argsp ||
320 p->fcharp || p->lcharp )
321 err("non-variable argument in statement function definition");
322 else
323 {
324 args->datap = (tagptr) (p->namep);
325 vardcl(p->namep);
326 free(p);
327 }
328}
329
330
331
332excall(name, args, nstars, labels)
333Namep name;
334struct Listblock *args;
335int nstars;
336struct Labelblock *labels[ ];
337{
338register expptr p;
339
6b16bb5d
DS
340if (name->vdcldone)
341 if (name->vclass != CLPROC && name->vclass != CLENTRY)
342 {
343 dclerr("call to non-subroutine", name);
344 return;
345 }
346 else if (name->vtype != TYSUBR)
347 {
348 dclerr("subroutine invocation of function", name);
349 return;
350 }
b21ea081
KM
351settype(name, TYSUBR, ENULL);
352p = mkfunct( mkprim(name, args, CHNULL) );
353p->exprblock.vtype = p->exprblock.leftp->headblock.vtype = TYINT;
354if (nstars > 0)
355 if (optimflag)
356 optbuff (SKCMGOTO, p, nstars, labels);
357 else
358 putcmgo (p, nstars, labels);
359else
360 if (optimflag)
361 optbuff (SKCALL, p, 0, 0);
362 else
363 putexpr (p);
364}
365
366
367
368exstop(stop, p)
369int stop;
370register expptr p;
371{
372char *q;
373int n;
374expptr mkstrcon();
375
376if(p)
377 {
378 if( ! ISCONST(p) )
379 {
380 execerr("pause/stop argument must be constant", CNULL);
381 frexpr(p);
382 p = mkstrcon(0, CNULL);
383 }
384 else if( ISINT(p->constblock.vtype) )
385 {
386 q = convic(p->constblock.const.ci);
387 n = strlen(q);
388 if(n > 0)
389 {
390 p->constblock.const.ccp = copyn(n, q);
391 p->constblock.vtype = TYCHAR;
392 p->constblock.vleng = (expptr) ICON(n);
393 }
394 else
395 p = (expptr) mkstrcon(0, CNULL);
396 }
397 else if(p->constblock.vtype != TYCHAR)
398 {
399 execerr("pause/stop argument must be integer or string", CNULL);
400 p = (expptr) mkstrcon(0, CNULL);
401 }
402 }
403else p = (expptr) mkstrcon(0, CNULL);
404
405if (optimflag)
406 optbuff ((stop ? SKSTOP : SKPAUSE), p, 0, 0);
407else
408 putexpr (call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p));
409}
410
411\f
412/* UCB DO LOOP CODE */
413
414#define DOINIT par[0]
415#define DOLIMIT par[1]
416#define DOINCR par[2]
417
418#define CONSTINIT const[0]
419#define CONSTLIMIT const[1]
420#define CONSTINCR const[2]
421
422#define VARSTEP 0
423#define POSSTEP 1
424#define NEGSTEP 2
425
426
427exdo(range, spec)
428int range;
429chainp spec;
430
431{
432 register expptr p, q;
433 expptr q1;
434 register Namep np;
435 chainp cp;
436 register int i;
437 int dotype, incsign;
438 Addrp dovarp, dostgp;
439 expptr par[3];
440 expptr const[3];
441 Slotp doslot;
442
443 pushctl(CTLDO);
444 dorange = ctlstack->dolabel = range;
445 np = (Namep) (spec->datap);
446 ctlstack->donamep = NULL;
447 if(np->vdovar)
448 {
449 errstr("nested loops with variable %s", varstr(VL,np->varname));
450 return;
451 }
452
453 dovarp = mkplace(np);
454 dotype = dovarp->vtype;
455
456 if( ! ONEOF(dotype, MSKINT|MSKREAL) )
457 {
458 err("bad type on DO variable");
459 return;
460 }
461
462
463 for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp)
464 {
465 p = fixtype((expptr) cpexpr((tagptr) q = cp->datap));
466 if(!ONEOF(p->headblock.vtype, MSKINT|MSKREAL) )
467 {
468 err("bad type on DO parameter");
469 return;
470 }
471
472
473 if (ISCONST(q))
474 const[i] = mkconv(dotype, q);
475 else
476 {
477 frexpr(q);
478 const[i] = NULL;
479 }
480
481 par[i++] = mkconv(dotype, p);
482 }
483
484 frchain(&spec);
485 switch(i)
486 {
487 case 0:
488 case 1:
489 err("too few DO parameters");
490 return;
491
492 case 2:
493 DOINCR = (expptr) ICON(1);
494 CONSTINCR = ICON(1);
495
496 case 3:
497 break;
498
499 default:
500 err("too many DO parameters");
501 return;
502 }
503
504 ctlstack->donamep = np;
505
506 np->vdovar = YES;
507 if( !optimflag && enregister(np) )
508 {
509 /* stgp points to a storage version, varp to a register version */
510 dostgp = dovarp;
511 dovarp = mkplace(np);
512 }
513 else
514 dostgp = NULL;
515
516 for (i = 0; i < 4; i++)
517 ctlstack->ctlabels[i] = newlabel();
518
519 if( CONSTLIMIT )
520 ctlstack->domax = DOLIMIT;
521 else
522 ctlstack->domax = (expptr) mktemp(dotype, PNULL);
523
524 if( CONSTINCR )
525 {
526 ctlstack->dostep = DOINCR;
527 if( (incsign = conssgn(CONSTINCR)) == 0)
528 err("zero DO increment");
529 ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
530 }
531 else
532 {
533 ctlstack->dostep = (expptr) mktemp(dotype, PNULL);
534 ctlstack->dostepsign = VARSTEP;
535 }
536
537if (optimflag)
538 doslot = optbuff (SKDOHEAD,0,0,ctlstack);
539
540if( CONSTLIMIT && CONSTINIT && ctlstack->dostepsign!=VARSTEP)
541 {
542 if (optimflag)
543 optbuff (SKEQ,mkexpr(OPASSIGN,cpexpr(dovarp),cpexpr(DOINIT)),
544 0,0);
545 else
546 puteq (cpexpr(dovarp), cpexpr(DOINIT));
547 if( ! onetripflag )
548 {
549 q = mkexpr(OPMINUS, cpexpr(CONSTLIMIT), cpexpr(CONSTINIT));
550 if((incsign * conssgn(q)) == -1)
551 {
552 warn("DO range never executed");
553 if (optimflag)
554 optbuff (SKGOTO,0,ctlstack->endlabel,0);
555 else
556 putgoto (ctlstack->endlabel);
557 }
558 frexpr(q);
559 }
560 }
561
562
563else if (ctlstack->dostepsign != VARSTEP && !onetripflag)
564 {
565 if (CONSTLIMIT)
566 q = (expptr) cpexpr(ctlstack->domax);
567 else
568 q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT);
569 q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT);
570 q = mkexpr( (ctlstack->dostepsign == POSSTEP ? OPGE : OPLE),
571 q, q1);
572 if (optimflag)
573 optbuff (SKIFN,q, ctlstack->endlabel,0);
574 else
575 putif (q, ctlstack->endlabel);
576 }
577else
578 {
579 if (!CONSTLIMIT)
580 if (optimflag)
581 optbuff (SKEQ,
582 mkexpr(OPASSIGN,cpexpr(ctlstack->domax),DOLIMIT),0,0);
583 else
584 puteq (cpexpr(ctlstack->domax), DOLIMIT);
585 q = DOINIT;
586 if (!onetripflag)
587 q = mkexpr(OPMINUS, q,
588 mkexpr(OPASSIGN, cpexpr(ctlstack->dostep),
589 DOINCR) );
590 if (optimflag)
591 optbuff (SKEQ,mkexpr(OPASSIGN,cpexpr(dovarp), q),0,0);
592 else
593 puteq (cpexpr(dovarp), q);
594 if (onetripflag && ctlstack->dostepsign == VARSTEP)
595 if (optimflag)
596 optbuff (SKEQ,
597 mkexpr(OPASSIGN,cpexpr(ctlstack->dostep),DOINCR),0,0);
598 else
599 puteq (cpexpr(ctlstack->dostep), DOINCR);
600 }
601
602if (ctlstack->dostepsign == VARSTEP)
603 {
604 expptr incr,test;
605 if (onetripflag)
606 if (optimflag)
607 optbuff (SKGOTO,0,ctlstack->dobodylabel,0);
608 else
609 putgoto (ctlstack->dobodylabel);
610 else
611 if (optimflag)
612 optbuff (SKIFN,mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)),
613 ctlstack->doneglabel,0);
614 else
615 putif (mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)),
616 ctlstack->doneglabel);
617 if (optimflag)
618 optbuff (SKLABEL,0,ctlstack->doposlabel,0);
619 else
620 putlabel (ctlstack->doposlabel);
621 incr = mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep));
622 test = mkexpr(OPLE, incr, cpexpr(ctlstack->domax));
623 if (optimflag)
624 optbuff (SKIFN,test, ctlstack->endlabel,0);
625 else
626 putif (test, ctlstack->endlabel);
627 }
628
629if (optimflag)
630 optbuff (SKLABEL,0,ctlstack->dobodylabel,0);
631else
632 putlabel (ctlstack->dobodylabel);
633if (dostgp)
634 {
635 if (optimflag)
636 optbuff (SKEQ,mkexpr(OPASSIGN,dostgp, dovarp),0,0);
637 else
638 puteq (dostgp, dovarp);
639 }
640else
641 frexpr(dovarp);
642if (optimflag)
643 doslot->nullslot = optbuff (SKNULL,0,0,0);
644
645frexpr(CONSTINIT);
646frexpr(CONSTLIMIT);
647frexpr(CONSTINCR);
648}
649
650\f
651enddo(here)
652int here;
653
654{
655 register struct Ctlframe *q;
656 Namep np;
657 Addrp ap, rv;
658 expptr t;
659 register int i;
660 Slotp doslot;
661
662 while (here == dorange)
663 {
664 while (ctlstack->ctltype == CTLIF || ctlstack->ctltype == CTLELSE)
665 {
666 execerr("missing endif", CNULL);
667 exendif();
668 }
669
670 if (np = ctlstack->donamep)
671 {
672 rv = mkplace (np);
673
674 t = mkexpr(OPPLUSEQ, cpexpr(rv), cpexpr(ctlstack->dostep) );
675
676 if (optimflag)
677 doslot = optbuff (SKENDDO,0,0,ctlstack);
678
679 if (ctlstack->dostepsign == VARSTEP)
680 if (optimflag)
681 {
682 optbuff (SKIFN,
683 mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)),
684 ctlstack->doposlabel,0);
685 optbuff (SKLABEL,0,ctlstack->doneglabel,0);
686 optbuff (SKIFN,mkexpr(OPLT, t, ctlstack->domax),
687 ctlstack->dobodylabel,0);
688 }
689 else
690 {
691 putif (mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)),
692 ctlstack->doposlabel);
693 putlabel (ctlstack->doneglabel);
694 putif (mkexpr(OPLT, t, ctlstack->domax),
695 ctlstack->dobodylabel);
696 }
697 else
698 {
699 int op;
700 op = (ctlstack->dostepsign == POSSTEP ? OPGT : OPLT);
701 if (optimflag)
702 optbuff (SKIFN, mkexpr(op,t,ctlstack->domax),
703 ctlstack->dobodylabel,0);
704 else
705 putif (mkexpr(op, t, ctlstack->domax),
706 ctlstack->dobodylabel);
707 }
708 if (optimflag)
709 optbuff (SKLABEL,0,ctlstack->endlabel,0);
710 else
711 putlabel (ctlstack->endlabel);
712
713 if (ap = memversion(np))
714 {
715 if (optimflag)
716 optbuff (SKEQ,mkexpr(OPASSIGN,ap, rv),0,0);
717 else
718 puteq (ap, rv);
719 }
720 else
721 frexpr(rv);
722 for (i = 0; i < 4; i++)
723 ctlstack->ctlabels[i] = 0;
724 if (!optimflag)
725 deregister(ctlstack->donamep);
726 ctlstack->donamep->vdovar = NO;
727 if (optimflag)
728 doslot->nullslot = optbuff (SKNULL,0,0,0);
729 }
730
731 popctl();
732 poplab();
733
734 dorange = 0;
735 for (q = ctlstack; q >= ctls; --q)
736 if (q->ctltype == CTLDO)
737 {
738 dorange = q->dolabel;
739 break;
740 }
741 }
742}
743
744\f
745exassign(vname, labelval)
746Namep vname;
747struct Labelblock *labelval;
748{
749Addrp p;
750expptr mkaddcon();
751
752p = mkplace(vname);
753#if SZADDR > SZSHORT
754if( p->vtype == TYSHORT )
755 err("insufficient precision in ASSIGN variable");
756else
757#endif
758if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
759 err("noninteger assign variable");
760else
761 {
762 if (optimflag)
763 optbuff (SKASSIGN, p, labelval->labelno, 0);
764 else
765 puteq (p, intrconv(p->vtype, mkaddcon(labelval->labelno)));
766 }
767}
768
769
770
771exarif(expr, neglab, zerlab, poslab)
772expptr expr;
773struct Labelblock *neglab, *zerlab, *poslab;
774{
775register int lm, lz, lp;
776struct Labelblock *labels[3];
777
778lm = neglab->labelno;
779lz = zerlab->labelno;
780lp = poslab->labelno;
781expr = fixtype(expr);
782
783if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) )
784 {
785 err("invalid type of arithmetic if expression");
786 frexpr(expr);
787 }
788else
789 {
790 if(lm == lz)
791 exar2(OPLE, expr, lm, lp);
792 else if(lm == lp)
793 exar2(OPNE, expr, lm, lz);
794 else if(lz == lp)
795 exar2(OPGE, expr, lz, lm);
796 else
797 if (optimflag)
798 {
799 labels[0] = neglab;
800 labels[1] = zerlab;
801 labels[2] = poslab;
802 optbuff (SKARIF, expr, 0, labels);
803 }
804 else
805 prarif(expr, lm, lz, lp);
806 }
807}
808
809
810
811LOCAL exar2 (op, e, l1, l2)
812int op;
813expptr e;
814int l1,l2;
815{
816if (optimflag)
817 {
818 optbuff (SKIFN, mkexpr(op, e, ICON(0)), l2, 0);
819 optbuff (SKGOTO, 0, l1, 0);
820 }
821else
822 {
823 putif (mkexpr(op, e, ICON(0)), l2);
824 putgoto (l1);
825 }
826}
827
828
829exreturn(p)
830register expptr p;
831{
832if(procclass != CLPROC)
833 warn("RETURN statement in main or block data");
834if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
835 {
836 err("alternate return in nonsubroutine");
837 p = 0;
838 }
839
840if(p)
841 if (optimflag)
842 optbuff (SKRETURN, p, retlabel, 0);
843 else
844 {
845 putforce (TYINT, p);
846 putgoto (retlabel);
847 }
848else
849 if (optimflag)
850 optbuff (SKRETURN, p,
851 (proctype==TYSUBR ? ret0label : retlabel), 0);
852 else
853 putgoto (proctype==TYSUBR ? ret0label : retlabel);
854}
855
856
857
858exasgoto(labvar)
859struct Hashentry *labvar;
860{
861register Addrp p;
862
863p = mkplace(labvar);
864if( ! ISINT(p->vtype) )
865 err("assigned goto variable must be integer");
866else
867 if (optimflag)
868 optbuff (SKASGOTO, p, 0, 0);
869 else
870 putbranch (p);
871}