xref: /csrg-svn/usr.bin/f77/pass1.vax/proc.c (revision 24484)
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