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