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