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