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