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[] = "@(#)proc.c 5.5 (Berkeley) 01/07/86"; 9 #endif not lint 10 11 /* 12 * proc.c 13 * 14 * Routines for handling procedures, f77 compiler, pass 1. 15 * 16 * University of Utah CS Dept modification history: 17 * 18 * $Log: proc.c,v $ 19 * Revision 5.6 86/01/06 16:28:06 donn 20 * Sigh. We can't commit to defining a symbol as a variable instead of a 21 * function based only on what we have seen through the declaration section; 22 * this was properly handled for normal variables but not for arguments. 23 * 24 * Revision 5.5 86/01/01 21:59:17 donn 25 * Pick up CHARACTER*(*) declarations for variables which aren't dummy 26 * arguments, and complain about them. 27 * 28 * Revision 5.4 85/12/20 19:18:35 donn 29 * Don't assume that dummy procedures of unknown type are functions of type 30 * undefined until the user (mis-)uses them that way -- they may also be 31 * subroutines. 32 * 33 * Revision 5.3 85/09/30 23:21:07 donn 34 * Print space with prspace() in outlocvars() so that alignment is preserved. 35 * 36 * Revision 5.2 85/08/10 05:03:34 donn 37 * Support for NAMELIST i/o from Jerry Berkman. 38 * 39 * Revision 5.1 85/08/10 03:49:14 donn 40 * 4.3 alpha 41 * 42 * Revision 3.11 85/06/04 03:45:29 donn 43 * Changed retval() to recognize that a function declaration might have 44 * bombed out earlier, leaving an error node behind... 45 * 46 * Revision 3.10 85/03/08 23:13:06 donn 47 * Finally figured out why function calls and array elements are not legal 48 * dummy array dimension declarator elements. Hacked safedim() to stop 'em. 49 * 50 * Revision 3.9 85/02/02 00:26:10 donn 51 * Removed the call to entrystab() in enddcl() -- this was redundant (it was 52 * also done in startproc()) and confusing to dbx to boot. 53 * 54 * Revision 3.8 85/01/14 04:21:53 donn 55 * Added changes to implement Jerry's '-q' option. 56 * 57 * Revision 3.7 85/01/11 21:10:35 donn 58 * In conjunction with other changes to implement SAVE statements, function 59 * nameblocks were changed to make it appear that they are 'saved' too -- 60 * this arranges things so that function return values are forced out of 61 * register before a return. 62 * 63 * Revision 3.6 84/12/10 19:27:20 donn 64 * comblock() signals an illegal common block name by returning a null pointer, 65 * but incomm() wasn't able to handle it, leading to core dumps. I put the 66 * fix in incomm() to pick up null common blocks. 67 * 68 * Revision 3.5 84/11/21 20:33:31 donn 69 * It seems that I/O elements are treated as character strings so that their 70 * length can be passed to the I/O routines... Unfortunately the compiler 71 * assumes that no temporaries can be of type CHARACTER and casually tosses 72 * length and type info away when removing TEMP blocks. This has been fixed... 73 * 74 * Revision 3.4 84/11/05 22:19:30 donn 75 * Fixed a silly bug in the last fix. 76 * 77 * Revision 3.3 84/10/29 08:15:23 donn 78 * Added code to check the type and shape of subscript declarations, 79 * per Jerry Berkman's suggestion. 80 * 81 * Revision 3.2 84/10/29 05:52:07 donn 82 * Added change suggested by Jerry Berkman to report an error when an array 83 * is redimensioned. 84 * 85 * Revision 3.1 84/10/13 02:12:31 donn 86 * Merged Jerry Berkman's version into mine. 87 * 88 * Revision 2.1 84/07/19 12:04:09 donn 89 * Changed comment headers for UofU. 90 * 91 * Revision 1.6 84/07/19 11:32:15 donn 92 * Incorporated fix to setbound() to detect backward array subscript limits. 93 * The fix is by Bob Corbett, donated by Jerry Berkman. 94 * 95 * Revision 1.5 84/07/18 18:25:50 donn 96 * Fixed problem with doentry() where a placeholder for a return value 97 * was not allocated if the first entry didn't require one but a later 98 * entry did. 99 * 100 * Revision 1.4 84/05/24 20:52:09 donn 101 * Installed firewall #ifdef around the code that recycles stack temporaries, 102 * since it seems to be broken and lacks a good fix for the time being. 103 * 104 * Revision 1.3 84/04/16 09:50:46 donn 105 * Fixed mkargtemp() so that it only passes back a copy of a temporary, keeping 106 * the original for its own use. This fixes a set of bugs that are caused by 107 * elements in the argtemplist getting stomped on. 108 * 109 * Revision 1.2 84/02/28 21:12:58 donn 110 * Added Berkeley changes for subroutine call argument temporaries fix. 111 * 112 */ 113 114 #include "defs.h" 115 116 #ifdef SDB 117 # include <a.out.h> 118 # ifndef N_SO 119 # include <stab.h> 120 # endif 121 #endif 122 123 extern flag namesflag; 124 125 typedef 126 struct SizeList 127 { 128 struct SizeList *next; 129 ftnint size; 130 struct VarList *vars; 131 } 132 sizelist; 133 134 135 typedef 136 struct VarList 137 { 138 struct VarList *next; 139 Namep np; 140 struct Equivblock *ep; 141 } 142 varlist; 143 144 145 LOCAL sizelist *varsizes; 146 147 148 /* start a new procedure */ 149 150 newproc() 151 { 152 if(parstate != OUTSIDE) 153 { 154 execerr("missing end statement", CNULL); 155 endproc(); 156 } 157 158 parstate = INSIDE; 159 procclass = CLMAIN; /* default */ 160 } 161 162 163 164 /* end of procedure. generate variables, epilogs, and prologs */ 165 166 endproc() 167 { 168 struct Labelblock *lp; 169 170 if(parstate < INDATA) 171 enddcl(); 172 if(ctlstack >= ctls) 173 err("DO loop or BLOCK IF not closed"); 174 for(lp = labeltab ; lp < labtabend ; ++lp) 175 if(lp->stateno!=0 && lp->labdefined==NO) 176 errstr("missing statement number %s", convic(lp->stateno) ); 177 178 if (optimflag) 179 optimize(); 180 181 outiodata(); 182 epicode(); 183 procode(); 184 donmlist(); 185 dobss(); 186 187 #if FAMILY == PCC 188 putbracket(); 189 #endif 190 fixlwm(); 191 procinit(); /* clean up for next procedure */ 192 } 193 194 195 196 /* End of declaration section of procedure. Allocate storage. */ 197 198 enddcl() 199 { 200 register struct Entrypoint *ep; 201 202 parstate = INEXEC; 203 docommon(); 204 doequiv(); 205 docomleng(); 206 for(ep = entries ; ep ; ep = ep->entnextp) { 207 doentry(ep); 208 } 209 } 210 211 /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */ 212 213 /* Main program or Block data */ 214 215 startproc(prgname, class) 216 Namep prgname; 217 int class; 218 { 219 struct Extsym *progname; 220 register struct Entrypoint *p; 221 222 if(prgname) 223 procname = prgname->varname; 224 if(namesflag == YES) { 225 fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") ); 226 if(prgname) 227 fprintf(diagfile, " %s", varstr(XL, procname) ); 228 fprintf(diagfile, ":\n"); 229 } 230 231 if( prgname ) 232 progname = newentry( prgname ); 233 else 234 progname = NULL; 235 236 p = ALLOC(Entrypoint); 237 if(class == CLMAIN) 238 puthead("MAIN_", CLMAIN); 239 else 240 puthead(CNULL, CLBLOCK); 241 if(class == CLMAIN) 242 newentry( mkname(5, "MAIN") ); 243 p->entryname = progname; 244 p->entrylabel = newlabel(); 245 entries = p; 246 247 procclass = class; 248 retlabel = newlabel(); 249 #ifdef SDB 250 if(sdbflag) { 251 entrystab(p,class); 252 } 253 #endif 254 } 255 256 /* subroutine or function statement */ 257 258 struct Extsym *newentry(v) 259 register Namep v; 260 { 261 register struct Extsym *p; 262 263 p = mkext( varunder(VL, v->varname) ); 264 265 if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) ) 266 { 267 if(p == 0) 268 dclerr("invalid entry name", v); 269 else dclerr("external name already used", v); 270 return(0); 271 } 272 v->vstg = STGAUTO; 273 v->vprocclass = PTHISPROC; 274 v->vclass = CLPROC; 275 p->extstg = STGEXT; 276 p->extinit = YES; 277 return(p); 278 } 279 280 281 entrypt(class, type, length, entname, args) 282 int class, type; 283 ftnint length; 284 Namep entname; 285 chainp args; 286 { 287 struct Extsym *entry; 288 register Namep q; 289 register struct Entrypoint *p, *ep; 290 291 if(namesflag == YES) { 292 if(class == CLENTRY) 293 fprintf(diagfile, " entry "); 294 if(entname) 295 fprintf(diagfile, " %s", varstr(XL, entname->varname) ); 296 fprintf(diagfile, ":\n"); 297 } 298 299 if( entname->vclass == CLPARAM ) { 300 errstr("entry name %s used in 'parameter' statement", 301 varstr(XL, entname->varname) ); 302 return; 303 } 304 if( ((type == TYSUBR) || (class == CLENTRY && proctype == TYSUBR)) 305 && (entname->vtype != TYUNKNOWN && entname->vtype != TYSUBR) ) { 306 errstr("subroutine entry %s previously declared", 307 varstr(XL, entname->varname) ); 308 return; 309 } 310 if( (entname->vstg != STGEXT && entname->vstg != STGUNKNOWN) 311 || (entname->vdim != NULL) ) { 312 errstr("subroutine or function entry %s previously declared", 313 varstr(XL, entname->varname) ); 314 return; 315 } 316 317 if( (class == CLPROC || class == CLENTRY) && type != TYSUBR ) 318 /* arrange to save function return values */ 319 entname->vsave = YES; 320 321 entry = newentry( entname ); 322 323 if(class != CLENTRY) 324 puthead( varstr(XL, procname = entry->extname), class); 325 q = mkname(VL, nounder(XL,entry->extname) ); 326 327 if( (type = lengtype(type, (int) length)) != TYCHAR) 328 length = 0; 329 if(class == CLPROC) 330 { 331 procclass = CLPROC; 332 proctype = type; 333 procleng = length; 334 335 retlabel = newlabel(); 336 if(type == TYSUBR) 337 ret0label = newlabel(); 338 } 339 340 p = ALLOC(Entrypoint); 341 if(entries) /* put new block at end of entries list */ 342 { 343 for(ep = entries; ep->entnextp; ep = ep->entnextp) 344 ; 345 ep->entnextp = p; 346 } 347 else 348 entries = p; 349 350 p->entryname = entry; 351 p->arglist = args; 352 p->entrylabel = newlabel(); 353 p->enamep = q; 354 355 if(class == CLENTRY) 356 { 357 class = CLPROC; 358 if(proctype == TYSUBR) 359 type = TYSUBR; 360 } 361 362 q->vclass = class; 363 q->vprocclass = PTHISPROC; 364 settype(q, type, (int) length); 365 /* hold all initial entry points till end of declarations */ 366 if(parstate >= INDATA) { 367 doentry(p); 368 } 369 #ifdef SDB 370 if(sdbflag) 371 { /* may need to preserve CLENTRY here */ 372 entrystab(p,class); 373 } 374 #endif 375 } 376 377 /* generate epilogs */ 378 379 LOCAL epicode() 380 { 381 register int i; 382 383 if(procclass==CLPROC) 384 { 385 if(proctype==TYSUBR) 386 { 387 putlabel(ret0label); 388 if(substars) 389 putforce(TYINT, ICON(0) ); 390 putlabel(retlabel); 391 goret(TYSUBR); 392 } 393 else { 394 putlabel(retlabel); 395 if(multitype) 396 { 397 typeaddr = autovar(1, TYADDR, PNULL); 398 putbranch( cpexpr(typeaddr) ); 399 for(i = 0; i < NTYPES ; ++i) 400 if(rtvlabel[i] != 0) 401 { 402 putlabel(rtvlabel[i]); 403 retval(i); 404 } 405 } 406 else 407 retval(proctype); 408 } 409 } 410 411 else if(procclass != CLBLOCK) 412 { 413 putlabel(retlabel); 414 goret(TYSUBR); 415 } 416 } 417 418 419 /* generate code to return value of type t */ 420 421 LOCAL retval(t) 422 register int t; 423 { 424 register Addrp p; 425 426 switch(t) 427 { 428 case TYCHAR: 429 case TYCOMPLEX: 430 case TYDCOMPLEX: 431 break; 432 433 case TYLOGICAL: 434 t = tylogical; 435 case TYADDR: 436 case TYSHORT: 437 case TYLONG: 438 p = (Addrp) cpexpr(retslot); 439 p->vtype = t; 440 putforce(t, p); 441 break; 442 443 case TYREAL: 444 case TYDREAL: 445 p = (Addrp) cpexpr(retslot); 446 p->vtype = t; 447 putforce(t, p); 448 break; 449 450 case TYERROR: 451 return; /* someone else already complained */ 452 453 default: 454 badtype("retval", t); 455 } 456 goret(t); 457 } 458 459 460 /* Allocate extra argument array if needed. Generate prologs. */ 461 462 LOCAL procode() 463 { 464 register struct Entrypoint *p; 465 Addrp argvec; 466 467 #if TARGET==GCOS 468 argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL); 469 #else 470 if(lastargslot>0 && nentry>1) 471 #if TARGET == VAX 472 argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL); 473 #else 474 argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL); 475 #endif 476 else 477 argvec = NULL; 478 #endif 479 480 481 #if TARGET == PDP11 482 /* for the optimizer */ 483 if(fudgelabel) 484 putlabel(fudgelabel); 485 #endif 486 487 for(p = entries ; p ; p = p->entnextp) 488 prolog(p, argvec); 489 490 #if FAMILY == PCC 491 putrbrack(procno); 492 #endif 493 494 prendproc(); 495 } 496 497 498 /* 499 * manipulate argument lists (allocate argument slot positions) 500 * keep track of return types and labels 501 */ 502 503 LOCAL doentry(ep) 504 struct Entrypoint *ep; 505 { 506 register int type; 507 register Namep np; 508 chainp p; 509 register Namep q; 510 Addrp mkarg(); 511 512 ++nentry; 513 if(procclass == CLMAIN) 514 { 515 if (optimflag) 516 optbuff (SKLABEL, 0, ep->entrylabel, 0); 517 else 518 putlabel(ep->entrylabel); 519 return; 520 } 521 else if(procclass == CLBLOCK) 522 return; 523 524 impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) ); 525 type = np->vtype; 526 if(proctype == TYUNKNOWN) 527 if( (proctype = type) == TYCHAR) 528 procleng = (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)); 529 530 if(proctype == TYCHAR) 531 { 532 if(type != TYCHAR) 533 err("noncharacter entry of character function"); 534 else if( (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)) != procleng) 535 err("mismatched character entry lengths"); 536 } 537 else if(type == TYCHAR) 538 err("character entry of noncharacter function"); 539 else if(type != proctype) 540 multitype = YES; 541 if(rtvlabel[type] == 0) 542 rtvlabel[type] = newlabel(); 543 ep->typelabel = rtvlabel[type]; 544 545 if(type == TYCHAR) 546 { 547 if(chslot < 0) 548 { 549 chslot = nextarg(TYADDR); 550 chlgslot = nextarg(TYLENG); 551 } 552 np->vstg = STGARG; 553 np->vardesc.varno = chslot; 554 if(procleng < 0) 555 np->vleng = (expptr) mkarg(TYLENG, chlgslot); 556 } 557 else if( ISCOMPLEX(type) ) 558 { 559 np->vstg = STGARG; 560 if(cxslot < 0) 561 cxslot = nextarg(TYADDR); 562 np->vardesc.varno = cxslot; 563 } 564 else if(type != TYSUBR) 565 { 566 if(retslot == NULL) 567 retslot = autovar(1, TYDREAL, PNULL); 568 np->vstg = STGAUTO; 569 np->voffset = retslot->memoffset->constblock.const.ci; 570 } 571 572 for(p = ep->arglist ; p ; p = p->nextp) 573 if(! (( q = (Namep) (p->datap) )->vdcldone) ) 574 q->vardesc.varno = nextarg(TYADDR); 575 576 for(p = ep->arglist ; p ; p = p->nextp) 577 if(! (( q = (Namep) (p->datap) )->vdcldone) ) 578 { 579 if(q->vclass == CLPROC && q->vtype == TYUNKNOWN) 580 continue; 581 impldcl(q); 582 if(q->vtype == TYCHAR) 583 { 584 if(q->vleng == NULL) /* character*(*) */ 585 q->vleng = (expptr) 586 mkarg(TYLENG, nextarg(TYLENG) ); 587 else if(nentry == 1) 588 nextarg(TYLENG); 589 } 590 else if(q->vclass==CLPROC && nentry==1) 591 nextarg(TYLENG) ; 592 #ifdef SDB 593 if(sdbflag) { 594 namestab(q); 595 } 596 #endif 597 } 598 599 if (optimflag) 600 optbuff (SKLABEL, 0, ep->entrylabel, 0); 601 else 602 putlabel(ep->entrylabel); 603 } 604 605 606 607 LOCAL nextarg(type) 608 int type; 609 { 610 int k; 611 k = lastargslot; 612 lastargslot += typesize[type]; 613 return(k); 614 } 615 616 /* generate variable references */ 617 618 LOCAL dobss() 619 { 620 register struct Hashentry *p; 621 register Namep q; 622 register int i; 623 int align; 624 ftnint leng, iarrl; 625 char *memname(); 626 int qstg, qclass, qtype; 627 628 pruse(asmfile, USEBSS); 629 varsizes = NULL; 630 631 for(p = hashtab ; p<lasthash ; ++p) 632 if(q = p->varp) 633 { 634 qstg = q->vstg; 635 qtype = q->vtype; 636 qclass = q->vclass; 637 638 if( (qclass==CLUNKNOWN && qstg!=STGARG) || 639 (qclass==CLVAR && qstg==STGUNKNOWN) ) 640 warn1("local variable %s never used", varstr(VL,q->varname) ); 641 else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG) 642 mkext(varunder(VL, q->varname)) ->extstg = STGEXT; 643 644 if (qclass == CLVAR && qstg == STGBSS) 645 { 646 if (SMALLVAR(q->varsize)) 647 { 648 enlist(q->varsize, q, NULL); 649 q->inlcomm = NO; 650 } 651 else 652 { 653 if (q->init == NO) 654 { 655 preven(ALIDOUBLE); 656 prlocvar(memname(qstg, q->vardesc.varno), q->varsize); 657 q->inlcomm = YES; 658 } 659 else 660 prlocdata(memname(qstg, q->vardesc.varno), q->varsize, 661 q->vtype, q->initoffset, &(q->inlcomm)); 662 } 663 } 664 else if(qclass==CLVAR && qstg!=STGARG) 665 { 666 if(q->vdim && !ISICON(q->vdim->nelt) ) 667 dclerr("adjustable dimension on non-argument", q); 668 if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng))) 669 dclerr("adjustable leng on nonargument", q); 670 } 671 672 chkdim(q); 673 } 674 675 for (i = 0 ; i < nequiv ; ++i) 676 if ( (leng = eqvclass[i].eqvleng) != 0 ) 677 { 678 if (SMALLVAR(leng)) 679 enlist(leng, NULL, eqvclass + i); 680 else if (eqvclass[i].init == NO) 681 { 682 preven(ALIDOUBLE); 683 prlocvar(memname(STGEQUIV, i), leng); 684 eqvclass[i].inlcomm = YES; 685 } 686 else 687 prlocdata(memname(STGEQUIV, i), leng, TYDREAL, 688 eqvclass[i].initoffset, &(eqvclass[i].inlcomm)); 689 } 690 691 outlocvars(); 692 #ifdef SDB 693 if(sdbflag) { 694 for(p = hashtab ; p<lasthash ; ++p) if(q = p->varp) { 695 qstg = q->vstg; 696 qclass = q->vclass; 697 if( ONEOF(qclass, M(CLVAR))) { 698 if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) ) namestab(q); 699 } 700 } 701 } 702 #endif 703 704 close(vdatafile); 705 close(vchkfile); 706 unlink(vdatafname); 707 unlink(vchkfname); 708 vdatahwm = 0; 709 } 710 711 712 713 donmlist() 714 { 715 register struct Hashentry *p; 716 register Namep q; 717 718 pruse(asmfile, USEINIT); 719 720 for(p=hashtab; p<lasthash; ++p) 721 if( (q = p->varp) && q->vclass==CLNAMELIST) 722 namelist(q); 723 } 724 725 726 doext() 727 { 728 struct Extsym *p; 729 730 for(p = extsymtab ; p<nextext ; ++p) 731 prext(p); 732 } 733 734 735 736 737 ftnint iarrlen(q) 738 register Namep q; 739 { 740 ftnint leng; 741 742 leng = typesize[q->vtype]; 743 if(leng <= 0) 744 return(-1); 745 if(q->vdim) 746 if( ISICON(q->vdim->nelt) ) 747 leng *= q->vdim->nelt->constblock.const.ci; 748 else return(-1); 749 if(q->vleng) 750 if( ISICON(q->vleng) ) 751 leng *= q->vleng->constblock.const.ci; 752 else return(-1); 753 return(leng); 754 } 755 756 /* This routine creates a static block representing the namelist. 757 An equivalent declaration of the structure produced is: 758 struct namelist 759 { 760 char namelistname[16]; 761 struct namelistentry 762 { 763 char varname[16]; # 16 plus null padding -> 20 764 char *varaddr; 765 short int type; 766 short int len; # length of type 767 struct dimensions *dimp; # null means scalar 768 } names[]; 769 }; 770 771 struct dimensions 772 { 773 int numberofdimensions; 774 int numberofelements 775 int baseoffset; 776 int span[numberofdimensions]; 777 }; 778 where the namelistentry list terminates with a null varname 779 If dimp is not null, then the corner element of the array is at 780 varaddr. However, the element with subscripts (i1,...,in) is at 781 varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...) 782 */ 783 784 namelist(np) 785 Namep np; 786 { 787 register chainp q; 788 register Namep v; 789 register struct Dimblock *dp; 790 char *memname(); 791 int type, dimno, dimoffset; 792 flag bad; 793 794 795 preven(ALILONG); 796 fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno)); 797 putstr(asmfile, varstr(VL, np->varname), 16); 798 dimno = ++lastvarno; 799 dimoffset = 0; 800 bad = NO; 801 802 for(q = np->varxptr.namelist ; q ; q = q->nextp) 803 { 804 vardcl( v = (Namep) (q->datap) ); 805 type = v->vtype; 806 if( ONEOF(v->vstg, MSKSTATIC) ) 807 { 808 preven(ALILONG); 809 putstr(asmfile, varstr(VL,v->varname), 16); 810 praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset); 811 prconi(asmfile, TYSHORT, type ); 812 prconi(asmfile, TYSHORT, 813 type==TYCHAR ? 814 (v->vleng->constblock.const.ci) : 815 (ftnint) typesize[type]); 816 if(v->vdim) 817 { 818 praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset); 819 dimoffset += (3 + v->vdim->ndim) * SZINT; 820 } 821 else 822 praddr(asmfile, STGNULL,0,(ftnint) 0); 823 } 824 else 825 { 826 dclerr("may not appear in namelist", v); 827 bad = YES; 828 } 829 } 830 831 if(bad) 832 return; 833 834 putstr(asmfile, "", 16); 835 836 if(dimoffset > 0) 837 { 838 fprintf(asmfile, LABELFMT, memname(STGINIT,dimno)); 839 for(q = np->varxptr.namelist ; q ; q = q->nextp) 840 if(dp = q->datap->nameblock.vdim) 841 { 842 int i; 843 prconi(asmfile, TYINT, (ftnint) (dp->ndim) ); 844 prconi(asmfile, TYINT, 845 (ftnint) (dp->nelt->constblock.const.ci) ); 846 prconi(asmfile, TYINT, 847 (ftnint) (dp->baseoffset->constblock.const.ci)); 848 for(i=0; i<dp->ndim ; ++i) 849 prconi(asmfile, TYINT, 850 dp->dims[i].dimsize->constblock.const.ci); 851 } 852 } 853 854 } 855 856 LOCAL docommon() 857 { 858 register struct Extsym *p; 859 register chainp q; 860 struct Dimblock *t; 861 expptr neltp; 862 register Namep v; 863 ftnint size; 864 int type; 865 866 for(p = extsymtab ; p<nextext ; ++p) 867 if(p->extstg==STGCOMMON) 868 { 869 #ifdef SDB 870 if(sdbflag) 871 prstab(varstr(XL,p->extname), N_BCOMM, 0, 0); 872 #endif 873 for(q = p->extp ; q ; q = q->nextp) 874 { 875 v = (Namep) (q->datap); 876 if(v->vdcldone == NO) 877 vardcl(v); 878 type = v->vtype; 879 if(p->extleng % typealign[type] != 0) 880 { 881 dclerr("common alignment", v); 882 p->extleng = roundup(p->extleng, typealign[type]); 883 } 884 v->voffset = p->extleng; 885 v->vardesc.varno = p - extsymtab; 886 if(type == TYCHAR) 887 size = v->vleng->constblock.const.ci; 888 else size = typesize[type]; 889 if(t = v->vdim) 890 if( (neltp = t->nelt) && ISCONST(neltp) ) 891 size *= neltp->constblock.const.ci; 892 else 893 dclerr("adjustable array in common", v); 894 p->extleng += size; 895 #ifdef SDB 896 if(sdbflag) 897 { 898 namestab(v); 899 } 900 #endif 901 } 902 903 frchain( &(p->extp) ); 904 #ifdef SDB 905 if(sdbflag) 906 prstab(varstr(XL,p->extname), N_ECOMM, 0, 0); 907 #endif 908 } 909 } 910 911 912 913 914 915 LOCAL docomleng() 916 { 917 register struct Extsym *p; 918 919 for(p = extsymtab ; p < nextext ; ++p) 920 if(p->extstg == STGCOMMON) 921 { 922 if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng 923 && !eqn(XL,"_BLNK__ ",p->extname) ) 924 warn1("incompatible lengths for common block %s", 925 nounder(XL, p->extname) ); 926 if(p->maxleng < p->extleng) 927 p->maxleng = p->extleng; 928 p->extleng = 0; 929 } 930 } 931 932 933 934 935 /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */ 936 937 /* frees a temporary block */ 938 939 frtemp(p) 940 Tempp p; 941 { 942 Addrp t; 943 944 if (optimflag) 945 { 946 if (p->tag != TTEMP) 947 badtag ("frtemp",p->tag); 948 t = p->memalloc; 949 } 950 else 951 t = (Addrp) p; 952 953 /* restore clobbered character string lengths */ 954 if(t->vtype==TYCHAR && t->varleng!=0) 955 { 956 frexpr(t->vleng); 957 t->vleng = ICON(t->varleng); 958 } 959 960 /* put block on chain of temps to be reclaimed */ 961 holdtemps = mkchain(t, holdtemps); 962 } 963 964 965 966 /* allocate an automatic variable slot */ 967 968 Addrp autovar(nelt, t, lengp) 969 register int nelt, t; 970 expptr lengp; 971 { 972 ftnint leng; 973 register Addrp q; 974 975 if(lengp) 976 if( ISICON(lengp) ) 977 leng = lengp->constblock.const.ci; 978 else { 979 fatal("automatic variable of nonconstant length"); 980 } 981 else 982 leng = typesize[t]; 983 autoleng = roundup( autoleng, typealign[t]); 984 985 q = ALLOC(Addrblock); 986 q->tag = TADDR; 987 q->vtype = t; 988 if(lengp) 989 { 990 q->vleng = ICON(leng); 991 q->varleng = leng; 992 } 993 q->vstg = STGAUTO; 994 q->memno = newlabel(); 995 q->ntempelt = nelt; 996 #if TARGET==PDP11 || TARGET==VAX 997 /* stack grows downward */ 998 autoleng += nelt*leng; 999 q->memoffset = ICON( - autoleng ); 1000 #else 1001 q->memoffset = ICON( autoleng ); 1002 autoleng += nelt*leng; 1003 #endif 1004 1005 return(q); 1006 } 1007 1008 1009 1010 /* 1011 * create a temporary block (TTEMP) when optimizing, 1012 * an ordinary TADDR block when not optimizing 1013 */ 1014 1015 Tempp mktmpn(nelt, type, lengp) 1016 int nelt; 1017 register int type; 1018 expptr lengp; 1019 { 1020 ftnint leng; 1021 chainp p, oldp; 1022 register Tempp q; 1023 Addrp altemp; 1024 1025 if (! optimflag) 1026 return ( (Tempp) mkaltmpn(nelt,type,lengp) ); 1027 if(type==TYUNKNOWN || type==TYERROR) 1028 badtype("mktmpn", type); 1029 1030 if(type==TYCHAR) 1031 if( ISICON(lengp) ) 1032 leng = lengp->constblock.const.ci; 1033 else { 1034 err("adjustable length"); 1035 return( (Tempp) errnode() ); 1036 } 1037 else 1038 leng = typesize[type]; 1039 1040 q = ALLOC(Tempblock); 1041 q->tag = TTEMP; 1042 q->vtype = type; 1043 if(type == TYCHAR) 1044 { 1045 q->vleng = ICON(leng); 1046 q->varleng = leng; 1047 } 1048 1049 altemp = ALLOC(Addrblock); 1050 altemp->tag = TADDR; 1051 altemp->vstg = STGUNKNOWN; 1052 q->memalloc = altemp; 1053 1054 q->ntempelt = nelt; 1055 q->istemp = YES; 1056 return(q); 1057 } 1058 1059 1060 1061 Addrp mktemp(type, lengp) 1062 int type; 1063 expptr lengp; 1064 { 1065 return( (Addrp) mktmpn(1,type,lengp) ); 1066 } 1067 1068 1069 1070 /* allocate a temporary location for the given temporary block; 1071 if already allocated, return its location */ 1072 1073 Addrp altmpn(tp) 1074 Tempp tp; 1075 1076 { 1077 Addrp t, q; 1078 1079 if (tp->tag != TTEMP) 1080 badtag ("altmpn",tp->tag); 1081 1082 t = tp->memalloc; 1083 if (t->vstg != STGUNKNOWN) 1084 { 1085 if (tp->vtype == TYCHAR) 1086 { 1087 /* 1088 * Unformatted I/O parameters are treated like character 1089 * strings (sigh) -- propagate type and length. 1090 */ 1091 t = (Addrp) cpexpr(t); 1092 t->vtype = tp->vtype; 1093 t->vleng = tp->vleng; 1094 t->varleng = tp->varleng; 1095 } 1096 return (t); 1097 } 1098 1099 q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng); 1100 cpn (sizeof(struct Addrblock), (char*)q, (char*)t); 1101 free ( (charptr) q); 1102 return(t); 1103 } 1104 1105 1106 1107 /* create and allocate space immediately for a temporary */ 1108 1109 Addrp mkaltemp(type,lengp) 1110 int type; 1111 expptr lengp; 1112 { 1113 return (mkaltmpn(1,type,lengp)); 1114 } 1115 1116 1117 1118 Addrp mkaltmpn(nelt,type,lengp) 1119 int nelt; 1120 register int type; 1121 expptr lengp; 1122 { 1123 ftnint leng; 1124 chainp p, oldp; 1125 register Addrp q; 1126 1127 if(type==TYUNKNOWN || type==TYERROR) 1128 badtype("mkaltmpn", type); 1129 1130 if(type==TYCHAR) 1131 if( ISICON(lengp) ) 1132 leng = lengp->constblock.const.ci; 1133 else { 1134 err("adjustable length"); 1135 return( (Addrp) errnode() ); 1136 } 1137 1138 /* 1139 * if a temporary of appropriate shape is on the templist, 1140 * remove it from the list and return it 1141 */ 1142 1143 #ifdef notdef 1144 /* 1145 * This code is broken until SKFRTEMP slots can be processed in putopt() 1146 * instead of in optimize() -- all kinds of things in putpcc.c can 1147 * bomb because of this. Sigh. 1148 */ 1149 for(oldp=CHNULL, p=templist ; p ; oldp=p, p=p->nextp) 1150 { 1151 q = (Addrp) (p->datap); 1152 if(q->vtype==type && q->ntempelt==nelt && 1153 (type!=TYCHAR || q->vleng->constblock.const.ci==leng) ) 1154 { 1155 if(oldp) 1156 oldp->nextp = p->nextp; 1157 else 1158 templist = p->nextp; 1159 free( (charptr) p); 1160 1161 if (debugflag[14]) 1162 fprintf(diagfile,"mkaltmpn reusing offset %d\n", 1163 q->memoffset->constblock.const.ci); 1164 return(q); 1165 } 1166 } 1167 #endif notdef 1168 q = autovar(nelt, type, lengp); 1169 q->istemp = YES; 1170 1171 if (debugflag[14]) 1172 fprintf(diagfile,"mkaltmpn new offset %d\n", 1173 q->memoffset->constblock.const.ci); 1174 return(q); 1175 } 1176 1177 1178 1179 /* The following routine is a patch which is only needed because the */ 1180 /* code for processing actual arguments for calls does not allocate */ 1181 /* the temps it needs before optimization takes place. A better */ 1182 /* solution is possible, but I do not have the time to implement it */ 1183 /* now. */ 1184 /* */ 1185 /* Robert P. Corbett */ 1186 1187 Addrp 1188 mkargtemp(type, lengp) 1189 int type; 1190 expptr lengp; 1191 { 1192 ftnint leng; 1193 chainp oldp, p; 1194 Addrp q; 1195 1196 if (type == TYUNKNOWN || type == TYERROR) 1197 badtype("mkargtemp", type); 1198 1199 if (type == TYCHAR) 1200 { 1201 if (ISICON(lengp)) 1202 leng = lengp->constblock.const.ci; 1203 else 1204 { 1205 err("adjustable length"); 1206 return ((Addrp) errnode()); 1207 } 1208 } 1209 1210 oldp = CHNULL; 1211 p = argtemplist; 1212 1213 while (p) 1214 { 1215 q = (Addrp) (p->datap); 1216 if (q->vtype == type 1217 && (type != TYCHAR || q->vleng->constblock.const.ci == leng)) 1218 { 1219 if (oldp) 1220 oldp->nextp = p->nextp; 1221 else 1222 argtemplist = p->nextp; 1223 1224 p->nextp = activearglist; 1225 activearglist = p; 1226 1227 return ((Addrp) cpexpr(q)); 1228 } 1229 1230 oldp = p; 1231 p = p->nextp; 1232 } 1233 1234 q = autovar(1, type, lengp); 1235 activearglist = mkchain(q, activearglist); 1236 return ((Addrp) cpexpr(q)); 1237 } 1238 1239 /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ 1240 1241 struct Extsym *comblock(len, s) 1242 register int len; 1243 register char *s; 1244 { 1245 struct Extsym *p; 1246 1247 if(len == 0) 1248 { 1249 s = BLANKCOMMON; 1250 len = strlen(s); 1251 } 1252 p = mkext( varunder(len, s) ); 1253 if(p->extstg == STGUNKNOWN) 1254 p->extstg = STGCOMMON; 1255 else if(p->extstg != STGCOMMON) 1256 { 1257 errstr("%s cannot be a common block name", s); 1258 return(0); 1259 } 1260 1261 return( p ); 1262 } 1263 1264 1265 incomm(c, v) 1266 struct Extsym *c; 1267 Namep v; 1268 { 1269 if(v->vstg != STGUNKNOWN) 1270 dclerr("incompatible common declaration", v); 1271 else 1272 { 1273 if(c == (struct Extsym *) 0) 1274 return; /* Illegal common block name upstream */ 1275 v->vstg = STGCOMMON; 1276 c->extp = hookup(c->extp, mkchain(v,CHNULL) ); 1277 } 1278 } 1279 1280 1281 1282 1283 settype(v, type, length) 1284 register Namep v; 1285 register int type; 1286 register int length; 1287 { 1288 if(type == TYUNKNOWN) 1289 return; 1290 1291 if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG) 1292 { 1293 v->vtype = TYSUBR; 1294 frexpr(v->vleng); 1295 } 1296 else if(type < 0) /* storage class set */ 1297 { 1298 if(v->vstg == STGUNKNOWN) 1299 v->vstg = - type; 1300 else if(v->vstg != -type) 1301 dclerr("incompatible storage declarations", v); 1302 } 1303 else if(v->vtype == TYUNKNOWN) 1304 { 1305 if( (v->vtype = lengtype(type, length))==TYCHAR ) 1306 { 1307 if(length >= 0) 1308 v->vleng = ICON(length); 1309 else if(v->vstg != STGARG) 1310 dclerr("adjustable length character variable that is not a dummy argument", v); 1311 } 1312 } 1313 else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.const.ci!=length) ) 1314 dclerr("incompatible type declarations", v); 1315 } 1316 1317 1318 1319 1320 1321 lengtype(type, length) 1322 register int type; 1323 register int length; 1324 { 1325 switch(type) 1326 { 1327 case TYREAL: 1328 if(length == 8) 1329 return(TYDREAL); 1330 if(length == 4) 1331 goto ret; 1332 break; 1333 1334 case TYCOMPLEX: 1335 if(length == 16) 1336 return(TYDCOMPLEX); 1337 if(length == 8) 1338 goto ret; 1339 break; 1340 1341 case TYSHORT: 1342 case TYDREAL: 1343 case TYDCOMPLEX: 1344 case TYCHAR: 1345 case TYUNKNOWN: 1346 case TYSUBR: 1347 case TYERROR: 1348 goto ret; 1349 1350 case TYLOGICAL: 1351 if(length == typesize[TYLOGICAL]) 1352 goto ret; 1353 break; 1354 1355 case TYLONG: 1356 if(length == 0) 1357 return(tyint); 1358 if(length == 2) 1359 return(TYSHORT); 1360 if(length == 4) 1361 goto ret; 1362 break; 1363 default: 1364 badtype("lengtype", type); 1365 } 1366 1367 if(length != 0) 1368 err("incompatible type-length combination"); 1369 1370 ret: 1371 return(type); 1372 } 1373 1374 1375 1376 1377 1378 setintr(v) 1379 register Namep v; 1380 { 1381 register int k; 1382 1383 if(v->vstg == STGUNKNOWN) 1384 v->vstg = STGINTR; 1385 else if(v->vstg!=STGINTR) 1386 dclerr("incompatible use of intrinsic function", v); 1387 if(v->vclass==CLUNKNOWN) 1388 v->vclass = CLPROC; 1389 if(v->vprocclass == PUNKNOWN) 1390 v->vprocclass = PINTRINSIC; 1391 else if(v->vprocclass != PINTRINSIC) 1392 dclerr("invalid intrinsic declaration", v); 1393 if(k = intrfunct(v->varname)) 1394 v->vardesc.varno = k; 1395 else 1396 dclerr("unknown intrinsic function", v); 1397 } 1398 1399 1400 1401 setext(v) 1402 register Namep v; 1403 { 1404 if(v->vclass == CLUNKNOWN) 1405 v->vclass = CLPROC; 1406 else if(v->vclass != CLPROC) 1407 dclerr("conflicting declarations", v); 1408 1409 if(v->vprocclass == PUNKNOWN) 1410 v->vprocclass = PEXTERNAL; 1411 else if(v->vprocclass != PEXTERNAL) 1412 dclerr("conflicting declarations", v); 1413 } 1414 1415 1416 1417 1418 /* create dimensions block for array variable */ 1419 1420 setbound(v, nd, dims) 1421 register Namep v; 1422 int nd; 1423 struct { expptr lb, ub; } dims[ ]; 1424 { 1425 register expptr q, t; 1426 register struct Dimblock *p; 1427 int i; 1428 1429 if(v->vclass == CLUNKNOWN) 1430 v->vclass = CLVAR; 1431 else if(v->vclass != CLVAR) 1432 { 1433 dclerr("only variables may be arrays", v); 1434 return; 1435 } 1436 if(v->vdim) 1437 { 1438 dclerr("redimensioned array", v); 1439 return; 1440 } 1441 1442 v->vdim = p = (struct Dimblock *) 1443 ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) ); 1444 p->ndim = nd; 1445 p->nelt = ICON(1); 1446 1447 for(i=0 ; i<nd ; ++i) 1448 { 1449 #ifdef SDB 1450 if(sdbflag) { 1451 /* Save the bounds trees built up by the grammar routines for use in stabs */ 1452 1453 if(dims[i].lb == NULL) p->dims[i].lb=ICON(1); 1454 else p->dims[i].lb= (expptr) cpexpr(dims[i].lb); 1455 if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL; 1456 else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL); 1457 1458 if(dims[i].ub == NULL) p->dims[i].ub=ICON(1); 1459 else p->dims[i].ub = (expptr) cpexpr(dims[i].ub); 1460 if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL; 1461 else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL); 1462 } 1463 #endif 1464 if( (q = dims[i].ub) == NULL) 1465 { 1466 if(i == nd-1) 1467 { 1468 frexpr(p->nelt); 1469 p->nelt = NULL; 1470 } 1471 else 1472 err("only last bound may be asterisk"); 1473 p->dims[i].dimsize = ICON(1);; 1474 p->dims[i].dimexpr = NULL; 1475 } 1476 else 1477 { 1478 if(dims[i].lb) 1479 { 1480 q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb)); 1481 q = mkexpr(OPPLUS, q, ICON(1) ); 1482 } 1483 if( ISCONST(q) ) 1484 { 1485 if (!ISINT(q->headblock.vtype)) { 1486 dclerr("dimension bounds must be integer expression", v); 1487 frexpr(q); 1488 q = ICON(0); 1489 } 1490 if ( q->constblock.const.ci <= 0) 1491 { 1492 dclerr("array bounds out of sequence", v); 1493 frexpr(q); 1494 q = ICON(0); 1495 } 1496 p->dims[i].dimsize = q; 1497 p->dims[i].dimexpr = (expptr) PNULL; 1498 } 1499 else { 1500 p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL); 1501 p->dims[i].dimexpr = q; 1502 } 1503 if(p->nelt) 1504 p->nelt = mkexpr(OPSTAR, p->nelt, 1505 cpexpr(p->dims[i].dimsize) ); 1506 } 1507 } 1508 1509 q = dims[nd-1].lb; 1510 if(q == NULL) 1511 q = ICON(1); 1512 1513 for(i = nd-2 ; i>=0 ; --i) 1514 { 1515 t = dims[i].lb; 1516 if(t == NULL) 1517 t = ICON(1); 1518 if(p->dims[i].dimsize) 1519 q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) ); 1520 } 1521 1522 if( ISCONST(q) ) 1523 { 1524 p->baseoffset = q; 1525 p->basexpr = NULL; 1526 } 1527 else 1528 { 1529 p->baseoffset = (expptr) autovar(1, tyint, PNULL); 1530 p->basexpr = q; 1531 } 1532 } 1533 1534 1535 1536 /* 1537 * Check the dimensions of q to ensure that they are appropriately defined. 1538 */ 1539 LOCAL chkdim(q) 1540 register Namep q; 1541 { 1542 register struct Dimblock *p; 1543 register int i; 1544 expptr e; 1545 1546 if (q == NULL) 1547 return; 1548 if (q->vclass != CLVAR) 1549 return; 1550 if (q->vdim == NULL) 1551 return; 1552 p = q->vdim; 1553 for (i = 0; i < p->ndim; ++i) 1554 { 1555 #ifdef SDB 1556 if (sdbflag) 1557 { 1558 if (e = p->dims[i].lb) 1559 chkdime(e, q); 1560 if (e = p->dims[i].ub) 1561 chkdime(e, q); 1562 } 1563 else 1564 #endif SDB 1565 if (e = p->dims[i].dimexpr) 1566 chkdime(e, q); 1567 } 1568 } 1569 1570 1571 1572 /* 1573 * The actual checking for chkdim() -- examines each expression. 1574 */ 1575 LOCAL chkdime(expr, q) 1576 expptr expr; 1577 Namep q; 1578 { 1579 register expptr e; 1580 1581 e = fixtype(cpexpr(expr)); 1582 if (!ISINT(e->exprblock.vtype)) 1583 dclerr("non-integer dimension", q); 1584 else if (!safedim(e)) 1585 dclerr("undefined dimension", q); 1586 frexpr(e); 1587 return; 1588 } 1589 1590 1591 1592 /* 1593 * A recursive routine to find undefined variables in dimension expressions. 1594 */ 1595 LOCAL safedim(e) 1596 expptr e; 1597 { 1598 chainp cp; 1599 1600 if (e == NULL) 1601 return 1; 1602 switch (e->tag) 1603 { 1604 case TEXPR: 1605 if (e->exprblock.opcode == OPCALL || e->exprblock.opcode == OPCCALL) 1606 return 0; 1607 return safedim(e->exprblock.leftp) && safedim(e->exprblock.rightp); 1608 case TADDR: 1609 switch (e->addrblock.vstg) 1610 { 1611 case STGCOMMON: 1612 case STGARG: 1613 case STGCONST: 1614 case STGEQUIV: 1615 if (e->addrblock.isarray) 1616 return 0; 1617 return safedim(e->addrblock.memoffset); 1618 default: 1619 return 0; 1620 } 1621 case TCONST: 1622 case TTEMP: 1623 return 1; 1624 } 1625 return 0; 1626 } 1627 1628 1629 1630 LOCAL enlist(size, np, ep) 1631 ftnint size; 1632 Namep np; 1633 struct Equivblock *ep; 1634 { 1635 register sizelist *sp; 1636 register sizelist *t; 1637 register varlist *p; 1638 1639 sp = varsizes; 1640 1641 if (sp == NULL) 1642 { 1643 sp = ALLOC(SizeList); 1644 sp->size = size; 1645 varsizes = sp; 1646 } 1647 else 1648 { 1649 while (sp->size != size) 1650 { 1651 if (sp->next != NULL && sp->next->size <= size) 1652 sp = sp->next; 1653 else 1654 { 1655 t = sp; 1656 sp = ALLOC(SizeList); 1657 sp->size = size; 1658 sp->next = t->next; 1659 t->next = sp; 1660 } 1661 } 1662 } 1663 1664 p = ALLOC(VarList); 1665 p->next = sp->vars; 1666 p->np = np; 1667 p->ep = ep; 1668 1669 sp->vars = p; 1670 1671 return; 1672 } 1673 1674 1675 1676 outlocvars() 1677 { 1678 1679 register varlist *first, *last; 1680 register varlist *vp, *t; 1681 register sizelist *sp, *sp1; 1682 register Namep np; 1683 register struct Equivblock *ep; 1684 register int i; 1685 register int alt; 1686 register int type; 1687 char sname[100]; 1688 char setbuff[100]; 1689 1690 sp = varsizes; 1691 if (sp == NULL) 1692 return; 1693 1694 vp = sp->vars; 1695 if (vp->np != NULL) 1696 { 1697 np = vp->np; 1698 sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel, 1699 np->vardesc.varno); 1700 } 1701 else 1702 { 1703 i = vp->ep - eqvclass; 1704 sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart); 1705 } 1706 1707 first = last = NULL; 1708 alt = NO; 1709 1710 while (sp != NULL) 1711 { 1712 vp = sp->vars; 1713 while (vp != NULL) 1714 { 1715 t = vp->next; 1716 if (alt == YES) 1717 { 1718 alt = NO; 1719 vp->next = first; 1720 first = vp; 1721 } 1722 else 1723 { 1724 alt = YES; 1725 if (last != NULL) 1726 last->next = vp; 1727 else 1728 first = vp; 1729 vp->next = NULL; 1730 last = vp; 1731 } 1732 vp = t; 1733 } 1734 sp1 = sp; 1735 sp = sp->next; 1736 free((char *) sp1); 1737 } 1738 1739 vp = first; 1740 while(vp != NULL) 1741 { 1742 if (vp->np != NULL) 1743 { 1744 np = vp->np; 1745 sprintf(sname, "v.%d", np->vardesc.varno); 1746 if (np->init) 1747 prlocdata(sname, np->varsize, np->vtype, np->initoffset, 1748 &(np->inlcomm)); 1749 else 1750 { 1751 pralign(typealign[np->vtype]); 1752 fprintf(initfile, "%s:\n", sname); 1753 prspace(np->varsize); 1754 } 1755 np->inlcomm = NO; 1756 } 1757 else 1758 { 1759 ep = vp->ep; 1760 i = ep - eqvclass; 1761 if (ep->eqvleng >= 8) 1762 type = TYDREAL; 1763 else if (ep->eqvleng >= 4) 1764 type = TYLONG; 1765 else if (ep->eqvleng >= 2) 1766 type = TYSHORT; 1767 else 1768 type = TYCHAR; 1769 sprintf(sname, "q.%d", i + eqvstart); 1770 if (ep->init) 1771 prlocdata(sname, ep->eqvleng, type, ep->initoffset, 1772 &(ep->inlcomm)); 1773 else 1774 { 1775 pralign(typealign[type]); 1776 fprintf(initfile, "%s:\n", sname); 1777 prspace(ep->eqvleng); 1778 } 1779 ep->inlcomm = NO; 1780 } 1781 t = vp; 1782 vp = vp->next; 1783 free((char *) t); 1784 } 1785 fprintf(initfile, "%s\n", setbuff); 1786 return; 1787 } 1788