xref: /csrg-svn/usr.bin/f77/pass1.tahoe/proc.c (revision 47951)
1*47951Sbostic /*-
2*47951Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47951Sbostic  * All rights reserved.
4*47951Sbostic  *
5*47951Sbostic  * %sccs.include.proprietary.c%
643220Sbostic  */
743220Sbostic 
843220Sbostic #ifndef lint
9*47951Sbostic static char sccsid[] = "@(#)proc.c	5.3 (Berkeley) 04/12/91";
10*47951Sbostic #endif /* not lint */
1143220Sbostic 
1243220Sbostic /*
1343220Sbostic  * proc.c
1443220Sbostic  *
1543220Sbostic  * Routines for handling procedures, f77 compiler, pass 1.
1643220Sbostic  *
1743220Sbostic  * University of Utah CS Dept modification history:
1843220Sbostic  *
1943220Sbostic  * $Header: proc.c,v 3.11 85/06/04 03:45:29 donn Exp $
2043220Sbostic  * $Log:	proc.c,v $
2143220Sbostic  * Revision 3.11  85/06/04  03:45:29  donn
2243220Sbostic  * Changed retval() to recognize that a function declaration might have
2343220Sbostic  * bombed out earlier, leaving an error node behind...
2443220Sbostic  *
2543220Sbostic  * Revision 3.10  85/03/08  23:13:06  donn
2643220Sbostic  * Finally figured out why function calls and array elements are not legal
2743220Sbostic  * dummy array dimension declarator elements.  Hacked safedim() to stop 'em.
2843220Sbostic  *
2943220Sbostic  * Revision 3.9  85/02/02  00:26:10  donn
3043220Sbostic  * Removed the call to entrystab() in enddcl() -- this was redundant (it was
3143220Sbostic  * also done in startproc()) and confusing to dbx to boot.
3243220Sbostic  *
3343220Sbostic  * Revision 3.8  85/01/14  04:21:53  donn
3443220Sbostic  * Added changes to implement Jerry's '-q' option.
3543220Sbostic  *
3643220Sbostic  * Revision 3.7  85/01/11  21:10:35  donn
3743220Sbostic  * In conjunction with other changes to implement SAVE statements, function
3843220Sbostic  * nameblocks were changed to make it appear that they are 'saved' too --
3943220Sbostic  * this arranges things so that function return values are forced out of
4043220Sbostic  * register before a return.
4143220Sbostic  *
4243220Sbostic  * Revision 3.6  84/12/10  19:27:20  donn
4343220Sbostic  * comblock() signals an illegal common block name by returning a null pointer,
4443220Sbostic  * but incomm() wasn't able to handle it, leading to core dumps.  I put the
4543220Sbostic  * fix in incomm() to pick up null common blocks.
4643220Sbostic  *
4743220Sbostic  * Revision 3.5  84/11/21  20:33:31  donn
4843220Sbostic  * It seems that I/O elements are treated as character strings so that their
4943220Sbostic  * length can be passed to the I/O routines...  Unfortunately the compiler
5043220Sbostic  * assumes that no temporaries can be of type CHARACTER and casually tosses
5143220Sbostic  * length and type info away when removing TEMP blocks.  This has been fixed...
5243220Sbostic  *
5343220Sbostic  * Revision 3.4  84/11/05  22:19:30  donn
5443220Sbostic  * Fixed a silly bug in the last fix.
5543220Sbostic  *
5643220Sbostic  * Revision 3.3  84/10/29  08:15:23  donn
5743220Sbostic  * Added code to check the type and shape of subscript declarations,
5843220Sbostic  * per Jerry Berkman's suggestion.
5943220Sbostic  *
6043220Sbostic  * Revision 3.2  84/10/29  05:52:07  donn
6143220Sbostic  * Added change suggested by Jerry Berkman to report an error when an array
6243220Sbostic  * is redimensioned.
6343220Sbostic  *
6443220Sbostic  * Revision 3.1  84/10/13  02:12:31  donn
6543220Sbostic  * Merged Jerry Berkman's version into mine.
6643220Sbostic  *
6743220Sbostic  * Revision 2.1  84/07/19  12:04:09  donn
6843220Sbostic  * Changed comment headers for UofU.
6943220Sbostic  *
7043220Sbostic  * Revision 1.6  84/07/19  11:32:15  donn
7143220Sbostic  * Incorporated fix to setbound() to detect backward array subscript limits.
7243220Sbostic  * The fix is by Bob Corbett, donated by Jerry Berkman.
7343220Sbostic  *
7443220Sbostic  * Revision 1.5  84/07/18  18:25:50  donn
7543220Sbostic  * Fixed problem with doentry() where a placeholder for a return value
7643220Sbostic  * was not allocated if the first entry didn't require one but a later
7743220Sbostic  * entry did.
7843220Sbostic  *
7943220Sbostic  * Revision 1.4  84/05/24  20:52:09  donn
8043220Sbostic  * Installed firewall #ifdef around the code that recycles stack temporaries,
8143220Sbostic  * since it seems to be broken and lacks a good fix for the time being.
8243220Sbostic  *
8343220Sbostic  * Revision 1.3  84/04/16  09:50:46  donn
8443220Sbostic  * Fixed mkargtemp() so that it only passes back a copy of a temporary, keeping
8543220Sbostic  * the original for its own use.  This fixes a set of bugs that are caused by
8643220Sbostic  * elements in the argtemplist getting stomped on.
8743220Sbostic  *
8843220Sbostic  * Revision 1.2  84/02/28  21:12:58  donn
8943220Sbostic  * Added Berkeley changes for subroutine call argument temporaries fix.
9043220Sbostic  *
9143220Sbostic  */
9243220Sbostic 
9343220Sbostic #include "defs.h"
9443220Sbostic 
9543220Sbostic #ifdef SDB
9643220Sbostic #	include <a.out.h>
9743220Sbostic #	ifndef N_SO
9843220Sbostic #		include <stab.h>
9943220Sbostic #	endif
10043220Sbostic #endif
10143220Sbostic 
10243220Sbostic extern flag namesflag;
10343220Sbostic 
10443220Sbostic typedef
10543220Sbostic   struct SizeList
10643220Sbostic     {
10743220Sbostic       struct SizeList *next;
10843220Sbostic       ftnint size;
10943220Sbostic       struct VarList *vars;
11043220Sbostic     }
11143220Sbostic   sizelist;
11243220Sbostic 
11343220Sbostic 
11443220Sbostic typedef
11543220Sbostic   struct VarList
11643220Sbostic     {
11743220Sbostic       struct VarList *next;
11843220Sbostic       Namep np;
11943220Sbostic       struct Equivblock *ep;
12043220Sbostic     }
12143220Sbostic   varlist;
12243220Sbostic 
12343220Sbostic 
12443220Sbostic LOCAL sizelist *varsizes;
12543220Sbostic 
12643220Sbostic 
12743220Sbostic /* start a new procedure */
12843220Sbostic 
newproc()12943220Sbostic newproc()
13043220Sbostic {
13143220Sbostic if(parstate != OUTSIDE)
13243220Sbostic 	{
13343220Sbostic 	execerr("missing end statement", CNULL);
13443220Sbostic 	endproc();
13543220Sbostic 	}
13643220Sbostic 
13743220Sbostic parstate = INSIDE;
13843220Sbostic procclass = CLMAIN;	/* default */
13943220Sbostic }
14043220Sbostic 
14143220Sbostic 
14243220Sbostic 
14343220Sbostic /* end of procedure. generate variables, epilogs, and prologs */
14443220Sbostic 
endproc()14543220Sbostic endproc()
14643220Sbostic {
14743220Sbostic struct Labelblock *lp;
14843220Sbostic 
14943220Sbostic if(parstate < INDATA)
15043220Sbostic 	enddcl();
15143220Sbostic if(ctlstack >= ctls)
15243220Sbostic 	err("DO loop or BLOCK IF not closed");
15343220Sbostic for(lp = labeltab ; lp < labtabend ; ++lp)
15443220Sbostic 	if(lp->stateno!=0 && lp->labdefined==NO)
15543220Sbostic 		errstr("missing statement number %s", convic(lp->stateno) );
15643220Sbostic 
15743220Sbostic if (optimflag)
15843220Sbostic   optimize();
15943220Sbostic 
16043220Sbostic outiodata();
16143220Sbostic epicode();
16243220Sbostic procode();
16343220Sbostic donmlist();
16443220Sbostic dobss();
16543220Sbostic 
16643220Sbostic #if FAMILY == PCC
16743220Sbostic 	putbracket();
16843220Sbostic #endif
16943220Sbostic procinit();	/* clean up for next procedure */
17043220Sbostic }
17143220Sbostic 
17243220Sbostic 
17343220Sbostic 
17443220Sbostic /* End of declaration section of procedure.  Allocate storage. */
17543220Sbostic 
enddcl()17643220Sbostic enddcl()
17743220Sbostic {
17843220Sbostic register struct Entrypoint *ep;
17943220Sbostic 
18043220Sbostic parstate = INEXEC;
18143220Sbostic docommon();
18243220Sbostic doequiv();
18343220Sbostic docomleng();
18443220Sbostic for(ep = entries ; ep ; ep = ep->entnextp) {
18543220Sbostic 	doentry(ep);
18643220Sbostic }
18743220Sbostic }
18843220Sbostic 
18943220Sbostic /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
19043220Sbostic 
19143220Sbostic /* Main program or Block data */
19243220Sbostic 
startproc(prgname,class)19343220Sbostic startproc(prgname, class)
19443220Sbostic Namep prgname;
19543220Sbostic int class;
19643220Sbostic {
19743220Sbostic struct Extsym *progname;
19843220Sbostic register struct Entrypoint *p;
19943220Sbostic 
20043220Sbostic if(prgname)
20143220Sbostic 	procname = prgname->varname;
20243220Sbostic if(namesflag == YES) {
20343220Sbostic 	fprintf(diagfile, "   %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
20443220Sbostic 	if(prgname)
20543220Sbostic 		fprintf(diagfile, " %s", varstr(XL, procname) );
20643220Sbostic 	fprintf(diagfile, ":\n");
20743220Sbostic 	}
20843220Sbostic 
20943220Sbostic if( prgname )
21043220Sbostic 	progname = newentry( prgname );
21143220Sbostic else
21243220Sbostic 	progname = NULL;
21343220Sbostic 
21443220Sbostic p = ALLOC(Entrypoint);
21543220Sbostic if(class == CLMAIN)
21643220Sbostic 	puthead("MAIN_", CLMAIN);
21743220Sbostic else
21843220Sbostic 	puthead(CNULL, CLBLOCK);
21943220Sbostic if(class == CLMAIN)
22043220Sbostic 	newentry( mkname(5, "MAIN") );
22143220Sbostic p->entryname = progname;
22243220Sbostic p->entrylabel = newlabel();
22343220Sbostic entries = p;
22443220Sbostic 
22543220Sbostic procclass = class;
22643220Sbostic retlabel = newlabel();
22743220Sbostic #ifdef SDB
22843220Sbostic if(sdbflag) {
22943220Sbostic          entrystab(p,class);
23043220Sbostic }
23143220Sbostic #endif
23243220Sbostic }
23343220Sbostic 
23443220Sbostic /* subroutine or function statement */
23543220Sbostic 
newentry(v)23643220Sbostic struct Extsym *newentry(v)
23743220Sbostic register Namep v;
23843220Sbostic {
23943220Sbostic register struct Extsym *p;
24043220Sbostic 
24143220Sbostic p = mkext( varunder(VL, v->varname) );
24243220Sbostic 
24343220Sbostic if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
24443220Sbostic 	{
24543220Sbostic 	if(p == 0)
24643220Sbostic 		dclerr("invalid entry name", v);
24743220Sbostic 	else	dclerr("external name already used", v);
24843220Sbostic 	return(0);
24943220Sbostic 	}
25043220Sbostic v->vstg = STGAUTO;
25143220Sbostic v->vprocclass = PTHISPROC;
25243220Sbostic v->vclass = CLPROC;
25343220Sbostic p->extstg = STGEXT;
25443220Sbostic p->extinit = YES;
25543220Sbostic return(p);
25643220Sbostic }
25743220Sbostic 
25843220Sbostic 
entrypt(class,type,length,entname,args)25943220Sbostic entrypt(class, type, length, entname, args)
26043220Sbostic int class, type;
26143220Sbostic ftnint length;
26243220Sbostic Namep entname;
26343220Sbostic chainp args;
26443220Sbostic {
26543220Sbostic struct Extsym *entry;
26643220Sbostic register Namep q;
26743220Sbostic register struct Entrypoint *p, *ep;
26843220Sbostic 
26943220Sbostic if(namesflag == YES) {
27043220Sbostic 	if(class == CLENTRY)
27143220Sbostic 		fprintf(diagfile, "       entry ");
27243220Sbostic 	if(entname)
27343220Sbostic 		fprintf(diagfile, "   %s", varstr(XL, entname->varname) );
27443220Sbostic 	fprintf(diagfile, ":\n");
27543220Sbostic 	}
27643220Sbostic 
27743220Sbostic if( entname->vclass == CLPARAM ) {
27843220Sbostic 	errstr("entry name %s used in 'parameter' statement",
27943220Sbostic 		varstr(XL, entname->varname) );
28043220Sbostic 	return;
28143220Sbostic 	}
28243220Sbostic if( ((type == TYSUBR) || (class == CLENTRY && proctype == TYSUBR))
28343220Sbostic 	&& (entname->vtype != TYUNKNOWN && entname->vtype != TYSUBR) ) {
28443220Sbostic 	errstr("subroutine entry %s previously declared",
28543220Sbostic 		varstr(XL, entname->varname) );
28643220Sbostic 	return;
28743220Sbostic 	}
28843220Sbostic if(  (entname->vstg != STGEXT && entname->vstg != STGUNKNOWN)
28943220Sbostic 	||  (entname->vdim != NULL) ) {
29043220Sbostic 	errstr("subroutine or function entry %s previously declared",
29143220Sbostic 		varstr(XL, entname->varname) );
29243220Sbostic 	return;
29343220Sbostic 	}
29443220Sbostic 
29543220Sbostic if( (class == CLPROC || class == CLENTRY) && type != TYSUBR )
29643220Sbostic 	/* arrange to save function return values */
29743220Sbostic 	entname->vsave = YES;
29843220Sbostic 
29943220Sbostic entry = newentry( entname );
30043220Sbostic 
30143220Sbostic if(class != CLENTRY)
30243220Sbostic 	puthead( varstr(XL, procname = entry->extname), class);
30343220Sbostic q = mkname(VL, nounder(XL,entry->extname) );
30443220Sbostic 
30543220Sbostic if( (type = lengtype(type, (int) length)) != TYCHAR)
30643220Sbostic 	length = 0;
30743220Sbostic if(class == CLPROC)
30843220Sbostic 	{
30943220Sbostic 	procclass = CLPROC;
31043220Sbostic 	proctype = type;
31143220Sbostic 	procleng = length;
31243220Sbostic 
31343220Sbostic 	retlabel = newlabel();
31443220Sbostic 	if(type == TYSUBR)
31543220Sbostic 		ret0label = newlabel();
31643220Sbostic 	}
31743220Sbostic 
31843220Sbostic p = ALLOC(Entrypoint);
31943220Sbostic if(entries)	/* put new block at end of entries list */
32043220Sbostic 	{
32143220Sbostic 	for(ep = entries; ep->entnextp; ep = ep->entnextp)
32243220Sbostic 		;
32343220Sbostic 	ep->entnextp = p;
32443220Sbostic 	}
32543220Sbostic else
32643220Sbostic 	entries = p;
32743220Sbostic 
32843220Sbostic p->entryname = entry;
32943220Sbostic p->arglist = args;
33043220Sbostic p->entrylabel = newlabel();
33143220Sbostic p->enamep = q;
33243220Sbostic 
33343220Sbostic if(class == CLENTRY)
33443220Sbostic 	{
33543220Sbostic 	class = CLPROC;
33643220Sbostic 	if(proctype == TYSUBR)
33743220Sbostic 		type = TYSUBR;
33843220Sbostic 	}
33943220Sbostic 
34043220Sbostic q->vclass = class;
34143220Sbostic q->vprocclass = PTHISPROC;
34243220Sbostic settype(q, type, (int) length);
34343220Sbostic /* hold all initial entry points till end of declarations */
34443220Sbostic if(parstate >= INDATA) {
34543220Sbostic 	doentry(p);
34643220Sbostic }
34743220Sbostic #ifdef SDB
34843220Sbostic 	if(sdbflag)
34943220Sbostic 	{ /* may need to preserve CLENTRY here */
35043220Sbostic 	entrystab(p,class);
35143220Sbostic 	}
35243220Sbostic #endif
35343220Sbostic }
35443220Sbostic 
35543220Sbostic /* generate epilogs */
35643220Sbostic 
epicode()35743220Sbostic LOCAL epicode()
35843220Sbostic {
35943220Sbostic register int i;
36043220Sbostic 
36143220Sbostic if(procclass==CLPROC)
36243220Sbostic 	{
36343220Sbostic 	if(proctype==TYSUBR)
36443220Sbostic 		{
36543220Sbostic 		putlabel(ret0label);
36643220Sbostic 		if(substars)
36743220Sbostic 			putforce(TYINT, ICON(0) );
36843220Sbostic 		putlabel(retlabel);
36943220Sbostic 		goret(TYSUBR);
37043220Sbostic 		}
37143220Sbostic 	else	{
37243220Sbostic 		putlabel(retlabel);
37343220Sbostic 		if(multitype)
37443220Sbostic 			{
37543220Sbostic 			typeaddr = autovar(1, TYADDR, PNULL);
37643220Sbostic 			putbranch( cpexpr(typeaddr) );
37743220Sbostic 			for(i = 0; i < NTYPES ; ++i)
37843220Sbostic 				if(rtvlabel[i] != 0)
37943220Sbostic 					{
38043220Sbostic 					putlabel(rtvlabel[i]);
38143220Sbostic 					retval(i);
38243220Sbostic 					}
38343220Sbostic 			}
38443220Sbostic 		else
38543220Sbostic 			retval(proctype);
38643220Sbostic 		}
38743220Sbostic 	}
38843220Sbostic 
38943220Sbostic else if(procclass != CLBLOCK)
39043220Sbostic 	{
39143220Sbostic 	putlabel(retlabel);
39243220Sbostic 	goret(TYSUBR);
39343220Sbostic 	}
39443220Sbostic }
39543220Sbostic 
39643220Sbostic 
39743220Sbostic /* generate code to return value of type  t */
39843220Sbostic 
retval(t)39943220Sbostic LOCAL retval(t)
40043220Sbostic register int t;
40143220Sbostic {
40243220Sbostic register Addrp p;
40343220Sbostic 
40443220Sbostic switch(t)
40543220Sbostic 	{
40643220Sbostic 	case TYCHAR:
40743220Sbostic 	case TYCOMPLEX:
40843220Sbostic 	case TYDCOMPLEX:
40943220Sbostic 		break;
41043220Sbostic 
41143220Sbostic 	case TYLOGICAL:
41243220Sbostic 		t = tylogical;
41343220Sbostic 	case TYADDR:
41443220Sbostic 	case TYSHORT:
41543220Sbostic 	case TYLONG:
41643220Sbostic 		p = (Addrp) cpexpr(retslot);
41743220Sbostic 		p->vtype = t;
41843220Sbostic 		putforce(t, p);
41943220Sbostic 		break;
42043220Sbostic 
42143220Sbostic 	case TYREAL:
42243220Sbostic 	case TYDREAL:
42343220Sbostic 		p = (Addrp) cpexpr(retslot);
42443220Sbostic 		p->vtype = t;
42543220Sbostic 		putforce(t, p);
42643220Sbostic 		break;
42743220Sbostic 
42843220Sbostic 	case TYERROR:
42943220Sbostic 		return;		/* someone else already complained */
43043220Sbostic 
43143220Sbostic 	default:
43243220Sbostic 		badtype("retval", t);
43343220Sbostic 	}
43443220Sbostic goret(t);
43543220Sbostic }
43643220Sbostic 
43743220Sbostic 
43843220Sbostic /* Allocate extra argument array if needed. Generate prologs. */
43943220Sbostic 
procode()44043220Sbostic LOCAL procode()
44143220Sbostic {
44243220Sbostic register struct Entrypoint *p;
44343220Sbostic Addrp argvec;
44443220Sbostic 
44543220Sbostic #if TARGET==GCOS
44643220Sbostic 	argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
44743220Sbostic #else
44843220Sbostic 	if(lastargslot>0 && nentry>1)
44943220Sbostic #if TARGET == VAX || TARGET == TAHOE
45043220Sbostic 		argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL);
45143220Sbostic #else
45243220Sbostic 		argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
45343220Sbostic #endif
45443220Sbostic 	else
45543220Sbostic 		argvec = NULL;
45643220Sbostic #endif
45743220Sbostic 
45843220Sbostic 
45943220Sbostic #if TARGET == PDP11
46043220Sbostic 	/* for the optimizer */
46143220Sbostic 	if(fudgelabel)
46243220Sbostic 		putlabel(fudgelabel);
46343220Sbostic #endif
46443220Sbostic 
46543220Sbostic for(p = entries ; p ; p = p->entnextp)
46643220Sbostic 	prolog(p, argvec);
46743220Sbostic 
46843220Sbostic #if FAMILY == PCC
46943220Sbostic 	putrbrack(procno);
47043220Sbostic #endif
47143220Sbostic 
47243220Sbostic prendproc();
47343220Sbostic }
47443220Sbostic 
47543220Sbostic 
47643220Sbostic /*
47743220Sbostic    manipulate argument lists (allocate argument slot positions)
47843220Sbostic  * keep track of return types and labels
47943220Sbostic  */
48043220Sbostic 
doentry(ep)48143220Sbostic LOCAL doentry(ep)
48243220Sbostic struct Entrypoint *ep;
48343220Sbostic {
48443220Sbostic register int type;
48543220Sbostic register Namep np;
48643220Sbostic chainp p;
48743220Sbostic register Namep q;
48843220Sbostic Addrp mkarg();
48943220Sbostic 
49043220Sbostic ++nentry;
49143220Sbostic if(procclass == CLMAIN)
49243220Sbostic 	{
49343220Sbostic 	if (optimflag)
49443220Sbostic 		optbuff (SKLABEL, 0, ep->entrylabel, 0);
49543220Sbostic 	else
49643220Sbostic 		putlabel(ep->entrylabel);
49743220Sbostic 	return;
49843220Sbostic 	}
49943220Sbostic else if(procclass == CLBLOCK)
50043220Sbostic 	return;
50143220Sbostic 
50243220Sbostic impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) );
50343220Sbostic type = np->vtype;
50443220Sbostic if(proctype == TYUNKNOWN)
50543220Sbostic 	if( (proctype = type) == TYCHAR)
50646305Sbostic 		procleng = (np->vleng ? np->vleng->constblock.constant.ci : (ftnint) (-1));
50743220Sbostic 
50843220Sbostic if(proctype == TYCHAR)
50943220Sbostic 	{
51043220Sbostic 	if(type != TYCHAR)
51143220Sbostic 		err("noncharacter entry of character function");
51246305Sbostic 	else if( (np->vleng ? np->vleng->constblock.constant.ci : (ftnint) (-1)) != procleng)
51343220Sbostic 		err("mismatched character entry lengths");
51443220Sbostic 	}
51543220Sbostic else if(type == TYCHAR)
51643220Sbostic 	err("character entry of noncharacter function");
51743220Sbostic else if(type != proctype)
51843220Sbostic 	multitype = YES;
51943220Sbostic if(rtvlabel[type] == 0)
52043220Sbostic 	rtvlabel[type] = newlabel();
52143220Sbostic ep->typelabel = rtvlabel[type];
52243220Sbostic 
52343220Sbostic if(type == TYCHAR)
52443220Sbostic 	{
52543220Sbostic 	if(chslot < 0)
52643220Sbostic 		{
52743220Sbostic 		chslot = nextarg(TYADDR);
52843220Sbostic 		chlgslot = nextarg(TYLENG);
52943220Sbostic 		}
53043220Sbostic 	np->vstg = STGARG;
53143220Sbostic 	np->vardesc.varno = chslot;
53243220Sbostic 	if(procleng < 0)
53343220Sbostic 		np->vleng = (expptr) mkarg(TYLENG, chlgslot);
53443220Sbostic 	}
53543220Sbostic else if( ISCOMPLEX(type) )
53643220Sbostic 	{
53743220Sbostic 	np->vstg = STGARG;
53843220Sbostic 	if(cxslot < 0)
53943220Sbostic 		cxslot = nextarg(TYADDR);
54043220Sbostic 	np->vardesc.varno = cxslot;
54143220Sbostic 	}
54243220Sbostic else if(type != TYSUBR)
54343220Sbostic 	{
54443220Sbostic 	if(retslot == NULL)
54543220Sbostic 		retslot = autovar(1, TYDREAL, PNULL);
54643220Sbostic 	np->vstg = STGAUTO;
54746305Sbostic 	np->voffset = retslot->memoffset->constblock.constant.ci;
54843220Sbostic 	}
54943220Sbostic 
55043220Sbostic for(p = ep->arglist ; p ; p = p->nextp)
55143220Sbostic 	if(! (( q = (Namep) (p->datap) )->vdcldone) )
55243220Sbostic 		q->vardesc.varno = nextarg(TYADDR);
55343220Sbostic 
55443220Sbostic for(p = ep->arglist ; p ; p = p->nextp)
55543220Sbostic 	if(! (( q = (Namep) (p->datap) )->vdcldone) )
55643220Sbostic 		{
55743220Sbostic 		impldcl(q);
55843220Sbostic 		q->vdcldone = YES;
55943220Sbostic 		if(q->vtype == TYCHAR)
56043220Sbostic 			{
56143220Sbostic 			if(q->vleng == NULL)	/* character*(*) */
56243220Sbostic 				q->vleng = (expptr)
56343220Sbostic 						mkarg(TYLENG, nextarg(TYLENG) );
56443220Sbostic 			else if(nentry == 1)
56543220Sbostic 				nextarg(TYLENG);
56643220Sbostic 			}
56743220Sbostic 		else if(q->vclass==CLPROC && nentry==1)
56843220Sbostic 			nextarg(TYLENG) ;
56943220Sbostic #ifdef SDB
57043220Sbostic 		if(sdbflag) {
57143220Sbostic 			namestab(q);
57243220Sbostic 		}
57343220Sbostic #endif
57443220Sbostic 		}
57543220Sbostic 
57643220Sbostic if (optimflag)
57743220Sbostic 	optbuff (SKLABEL, 0, ep->entrylabel, 0);
57843220Sbostic else
57943220Sbostic 	putlabel(ep->entrylabel);
58043220Sbostic }
58143220Sbostic 
58243220Sbostic 
58343220Sbostic 
nextarg(type)58443220Sbostic LOCAL nextarg(type)
58543220Sbostic int type;
58643220Sbostic {
58743220Sbostic int k;
58843220Sbostic k = lastargslot;
58943220Sbostic lastargslot += typesize[type];
59043220Sbostic return(k);
59143220Sbostic }
59243220Sbostic 
59343220Sbostic /* generate variable references */
59443220Sbostic 
dobss()59543220Sbostic LOCAL dobss()
59643220Sbostic {
59743220Sbostic register struct Hashentry *p;
59843220Sbostic register Namep q;
59943220Sbostic register int i;
60043220Sbostic int align;
60143220Sbostic ftnint leng, iarrl;
60243220Sbostic char *memname();
60343220Sbostic int qstg, qclass, qtype;
60443220Sbostic 
60543220Sbostic pruse(asmfile, USEBSS);
60643220Sbostic varsizes = NULL;
60743220Sbostic 
60843220Sbostic for(p = hashtab ; p<lasthash ; ++p)
60943220Sbostic     if(q = p->varp)
61043220Sbostic 	{
61143220Sbostic 	qstg = q->vstg;
61243220Sbostic 	qtype = q->vtype;
61343220Sbostic 	qclass = q->vclass;
61443220Sbostic 
61543220Sbostic 	if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
61643220Sbostic 	    (qclass==CLVAR && qstg==STGUNKNOWN) )
61743220Sbostic 		warn1("local variable %s never used", varstr(VL,q->varname) );
61843220Sbostic 	else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG)
61943220Sbostic 		mkext(varunder(VL, q->varname)) ->extstg = STGEXT;
62043220Sbostic 
62143220Sbostic 	if (qclass == CLVAR && qstg == STGBSS)
62243220Sbostic 	  {
62343220Sbostic 	    if (SMALLVAR(q->varsize))
62443220Sbostic 	      {
62543220Sbostic 		enlist(q->varsize, q, NULL);
62643220Sbostic 		q->inlcomm = NO;
62743220Sbostic 	      }
62843220Sbostic 	    else
62943220Sbostic 	      {
63043220Sbostic 		if (q->init == NO)
63143220Sbostic 		  {
63243220Sbostic 		    preven(ALIDOUBLE);
63343220Sbostic 		    prlocvar(memname(qstg, q->vardesc.varno), q->varsize);
63443220Sbostic 		    q->inlcomm = YES;
63543220Sbostic 		  }
63643220Sbostic 		else
63743220Sbostic 		  prlocdata(memname(qstg, q->vardesc.varno), q->varsize,
63843220Sbostic 			    q->vtype, q->initoffset, &(q->inlcomm));
63943220Sbostic 	      }
64043220Sbostic 	  }
64143220Sbostic 	else if(qclass==CLVAR && qstg!=STGARG)
64243220Sbostic 		{
64343220Sbostic 		if(q->vdim && !ISICON(q->vdim->nelt) )
64443220Sbostic 			dclerr("adjustable dimension on non-argument", q);
64543220Sbostic 		if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng)))
64643220Sbostic 			dclerr("adjustable leng on nonargument", q);
64743220Sbostic 		}
64843220Sbostic 
64943220Sbostic 	chkdim(q);
65043220Sbostic 	}
65143220Sbostic 
65243220Sbostic for (i = 0 ; i < nequiv ; ++i)
65343220Sbostic   if ( (leng = eqvclass[i].eqvleng) != 0 )
65443220Sbostic     {
65543220Sbostic       if (SMALLVAR(leng))
65643220Sbostic 	enlist(leng, NULL, eqvclass + i);
65743220Sbostic       else if (eqvclass[i].init == NO)
65843220Sbostic 	{
65943220Sbostic 	  preven(ALIDOUBLE);
66043220Sbostic 	  prlocvar(memname(STGEQUIV, i), leng);
66143220Sbostic 	  eqvclass[i].inlcomm = YES;
66243220Sbostic 	}
66343220Sbostic       else
66443220Sbostic 	prlocdata(memname(STGEQUIV, i), leng, TYDREAL,
66543220Sbostic 		  eqvclass[i].initoffset, &(eqvclass[i].inlcomm));
66643220Sbostic     }
66743220Sbostic 
66843220Sbostic   outlocvars();
66943220Sbostic #ifdef SDB
67043220Sbostic     if(sdbflag) {
67143220Sbostic       for(p = hashtab ; p<lasthash ; ++p) if(q = p->varp) {
67243220Sbostic 	  qstg = q->vstg;
67343220Sbostic 	  qclass = q->vclass;
67443220Sbostic           if( ONEOF(qclass, M(CLVAR))) {
67543220Sbostic 	     if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) ) namestab(q);
67643220Sbostic 	  }
67743220Sbostic       }
67843220Sbostic     }
67943220Sbostic #endif
68043220Sbostic 
68143220Sbostic   close(vdatafile);
68243220Sbostic   close(vchkfile);
68343220Sbostic   unlink(vdatafname);
68443220Sbostic   unlink(vchkfname);
68543220Sbostic   vdatahwm = 0;
68643220Sbostic }
68743220Sbostic 
68843220Sbostic 
68943220Sbostic 
donmlist()69043220Sbostic donmlist()
69143220Sbostic {
69243220Sbostic register struct Hashentry *p;
69343220Sbostic register Namep q;
69443220Sbostic 
69543220Sbostic pruse(asmfile, USEINIT);
69643220Sbostic 
69743220Sbostic for(p=hashtab; p<lasthash; ++p)
69843220Sbostic 	if( (q = p->varp) && q->vclass==CLNAMELIST)
69943220Sbostic 		namelist(q);
70043220Sbostic }
70143220Sbostic 
70243220Sbostic 
doext()70343220Sbostic doext()
70443220Sbostic {
70543220Sbostic struct Extsym *p;
70643220Sbostic 
70743220Sbostic for(p = extsymtab ; p<nextext ; ++p)
70843220Sbostic 	prext(p);
70943220Sbostic }
71043220Sbostic 
71143220Sbostic 
71243220Sbostic 
71343220Sbostic 
iarrlen(q)71443220Sbostic ftnint iarrlen(q)
71543220Sbostic register Namep q;
71643220Sbostic {
71743220Sbostic ftnint leng;
71843220Sbostic 
71943220Sbostic leng = typesize[q->vtype];
72043220Sbostic if(leng <= 0)
72143220Sbostic 	return(-1);
72243220Sbostic if(q->vdim)
72343220Sbostic 	if( ISICON(q->vdim->nelt) )
72446305Sbostic 		leng *= q->vdim->nelt->constblock.constant.ci;
72543220Sbostic 	else	return(-1);
72643220Sbostic if(q->vleng)
72743220Sbostic 	if( ISICON(q->vleng) )
72846305Sbostic 		leng *= q->vleng->constblock.constant.ci;
72943220Sbostic 	else 	return(-1);
73043220Sbostic return(leng);
73143220Sbostic }
73243220Sbostic 
73343220Sbostic /* This routine creates a static block representing the namelist.
73443220Sbostic    An equivalent declaration of the structure produced is:
73543220Sbostic 	struct namelist
73643220Sbostic 		{
73743220Sbostic 		char namelistname[16];
73843220Sbostic 		struct namelistentry
73943220Sbostic 			{
74043220Sbostic 			char varname[16];
74143220Sbostic 			char *varaddr;
74243220Sbostic 			int type; # negative means -type= number of chars
74343220Sbostic 			struct dimensions *dimp; # null means scalar
74443220Sbostic 			} names[];
74543220Sbostic 		};
74643220Sbostic 
74743220Sbostic 	struct dimensions
74843220Sbostic 		{
74943220Sbostic 		int numberofdimensions;
75043220Sbostic 		int numberofelements
75143220Sbostic 		int baseoffset;
75243220Sbostic 		int span[numberofdimensions];
75343220Sbostic 		};
75443220Sbostic    where the namelistentry list terminates with a null varname
75543220Sbostic    If dimp is not null, then the corner element of the array is at
75643220Sbostic    varaddr.  However,  the element with subscripts (i1,...,in) is at
75743220Sbostic    varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...)
75843220Sbostic */
75943220Sbostic 
namelist(np)76043220Sbostic namelist(np)
76143220Sbostic Namep np;
76243220Sbostic {
76343220Sbostic register chainp q;
76443220Sbostic register Namep v;
76543220Sbostic register struct Dimblock *dp;
76643220Sbostic char *memname();
76743220Sbostic int type, dimno, dimoffset;
76843220Sbostic flag bad;
76943220Sbostic 
77043220Sbostic 
77143220Sbostic preven(ALILONG);
77243220Sbostic fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno));
77343220Sbostic putstr(asmfile, varstr(VL, np->varname), 16);
77443220Sbostic dimno = ++lastvarno;
77543220Sbostic dimoffset = 0;
77643220Sbostic bad = NO;
77743220Sbostic 
77843220Sbostic for(q = np->varxptr.namelist ; q ; q = q->nextp)
77943220Sbostic 	{
78043220Sbostic 	vardcl( v = (Namep) (q->datap) );
78143220Sbostic 	type = v->vtype;
78243220Sbostic 	if( ONEOF(v->vstg, MSKSTATIC) )
78343220Sbostic 		{
78443220Sbostic 		preven(ALILONG);
78543220Sbostic 		putstr(asmfile, varstr(VL,v->varname), 16);
78643220Sbostic 		praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset);
78743220Sbostic 		prconi(asmfile, TYINT,
78843220Sbostic 			type==TYCHAR ?
78946305Sbostic 			    -(v->vleng->constblock.constant.ci) : (ftnint) type);
79043220Sbostic 		if(v->vdim)
79143220Sbostic 			{
79243220Sbostic 			praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset);
79343220Sbostic 			dimoffset += 3 + v->vdim->ndim;
79443220Sbostic 			}
79543220Sbostic 		else
79643220Sbostic 			praddr(asmfile, STGNULL,0,(ftnint) 0);
79743220Sbostic 		}
79843220Sbostic 	else
79943220Sbostic 		{
80043220Sbostic 		dclerr("may not appear in namelist", v);
80143220Sbostic 		bad = YES;
80243220Sbostic 		}
80343220Sbostic 	}
80443220Sbostic 
80543220Sbostic if(bad)
80643220Sbostic 	return;
80743220Sbostic 
80843220Sbostic putstr(asmfile, "", 16);
80943220Sbostic 
81043220Sbostic if(dimoffset > 0)
81143220Sbostic 	{
81243220Sbostic 	fprintf(asmfile, LABELFMT, memname(STGINIT,dimno));
81343220Sbostic 	for(q = np->varxptr.namelist ; q ; q = q->nextp)
81443220Sbostic 		if(dp = q->datap->nameblock.vdim)
81543220Sbostic 			{
81643220Sbostic 			int i;
81743220Sbostic 			prconi(asmfile, TYINT, (ftnint) (dp->ndim) );
81843220Sbostic 			prconi(asmfile, TYINT,
81946305Sbostic 				(ftnint) (dp->nelt->constblock.constant.ci) );
82043220Sbostic 			prconi(asmfile, TYINT,
82146305Sbostic 				(ftnint) (dp->baseoffset->constblock.constant.ci));
82243220Sbostic 			for(i=0; i<dp->ndim ; ++i)
82343220Sbostic 				prconi(asmfile, TYINT,
82446305Sbostic 					dp->dims[i].dimsize->constblock.constant.ci);
82543220Sbostic 			}
82643220Sbostic 	}
82743220Sbostic 
82843220Sbostic }
82943220Sbostic 
docommon()83043220Sbostic LOCAL docommon()
83143220Sbostic {
83243220Sbostic register struct Extsym *p;
83343220Sbostic register chainp q;
83443220Sbostic struct Dimblock *t;
83543220Sbostic expptr neltp;
83643220Sbostic register Namep v;
83743220Sbostic ftnint size;
83843220Sbostic int type;
83943220Sbostic 
84043220Sbostic for(p = extsymtab ; p<nextext ; ++p)
84143220Sbostic 	if(p->extstg==STGCOMMON)
84243220Sbostic 		{
84343220Sbostic #ifdef SDB
84443220Sbostic 		if(sdbflag)
84543220Sbostic 			prstab(varstr(XL,p->extname), N_BCOMM, 0, 0);
84643220Sbostic #endif
84743220Sbostic 		for(q = p->extp ; q ; q = q->nextp)
84843220Sbostic 			{
84943220Sbostic 			v = (Namep) (q->datap);
85043220Sbostic 			if(v->vdcldone == NO)
85143220Sbostic 				vardcl(v);
85243220Sbostic 			type = v->vtype;
85343220Sbostic 			if(p->extleng % typealign[type] != 0)
85443220Sbostic 				{
85543220Sbostic 				dclerr("common alignment", v);
85643220Sbostic 				p->extleng = roundup(p->extleng, typealign[type]);
85743220Sbostic 				}
85843220Sbostic 			v->voffset = p->extleng;
85943220Sbostic 			v->vardesc.varno = p - extsymtab;
86043220Sbostic 			if(type == TYCHAR)
86146305Sbostic 				size = v->vleng->constblock.constant.ci;
86243220Sbostic 			else	size = typesize[type];
86343220Sbostic 			if(t = v->vdim)
86443220Sbostic 				if( (neltp = t->nelt) && ISCONST(neltp) )
86546305Sbostic 					size *= neltp->constblock.constant.ci;
86643220Sbostic 				else
86743220Sbostic 					dclerr("adjustable array in common", v);
86843220Sbostic 			p->extleng += size;
86943220Sbostic #ifdef SDB
87043220Sbostic 			if(sdbflag)
87143220Sbostic 				{
87243220Sbostic 				namestab(v);
87343220Sbostic 				}
87443220Sbostic #endif
87543220Sbostic 			}
87643220Sbostic 
87743220Sbostic 		frchain( &(p->extp) );
87843220Sbostic #ifdef SDB
87943220Sbostic 		if(sdbflag)
88043220Sbostic 			prstab(varstr(XL,p->extname), N_ECOMM, 0, 0);
88143220Sbostic #endif
88243220Sbostic 		}
88343220Sbostic }
88443220Sbostic 
88543220Sbostic 
88643220Sbostic 
88743220Sbostic 
88843220Sbostic 
docomleng()88943220Sbostic LOCAL docomleng()
89043220Sbostic {
89143220Sbostic register struct Extsym *p;
89243220Sbostic 
89343220Sbostic for(p = extsymtab ; p < nextext ; ++p)
89443220Sbostic 	if(p->extstg == STGCOMMON)
89543220Sbostic 		{
89643220Sbostic 		if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
89743220Sbostic 		    && !eqn(XL,"_BLNK__ ",p->extname) )
89843220Sbostic 			warn1("incompatible lengths for common block %s",
89943220Sbostic 				nounder(XL, p->extname) );
90043220Sbostic 		if(p->maxleng < p->extleng)
90143220Sbostic 			p->maxleng = p->extleng;
90243220Sbostic 		p->extleng = 0;
90343220Sbostic 	}
90443220Sbostic }
90543220Sbostic 
90643220Sbostic 
90743220Sbostic 
90843220Sbostic 
90943220Sbostic /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
91043220Sbostic 
91143220Sbostic /*  frees a temporary block  */
91243220Sbostic 
frtemp(p)91343220Sbostic frtemp(p)
91443220Sbostic Tempp p;
91543220Sbostic {
91643220Sbostic Addrp t;
91743220Sbostic 
91843220Sbostic if (optimflag)
91943220Sbostic 	{
92043220Sbostic 	if (p->tag != TTEMP)
92143220Sbostic 		badtag ("frtemp",p->tag);
92243220Sbostic 	t = p->memalloc;
92343220Sbostic 	}
92443220Sbostic else
92543220Sbostic 	t = (Addrp) p;
92643220Sbostic 
92743220Sbostic /* restore clobbered character string lengths */
92843220Sbostic if(t->vtype==TYCHAR && t->varleng!=0)
92943220Sbostic 	{
93043220Sbostic 	frexpr(t->vleng);
93143220Sbostic 	t->vleng = ICON(t->varleng);
93243220Sbostic 	}
93343220Sbostic 
93443220Sbostic /* put block on chain of temps to be reclaimed */
93543220Sbostic holdtemps = mkchain(t, holdtemps);
93643220Sbostic }
93743220Sbostic 
93843220Sbostic 
93943220Sbostic 
94043220Sbostic /* allocate an automatic variable slot */
94143220Sbostic 
autovar(nelt,t,lengp)94243220Sbostic Addrp autovar(nelt, t, lengp)
94343220Sbostic register int nelt, t;
94443220Sbostic expptr lengp;
94543220Sbostic {
94643220Sbostic ftnint leng;
94743220Sbostic register Addrp q;
94843220Sbostic 
94943220Sbostic if(lengp)
95043220Sbostic 	if( ISICON(lengp) )
95146305Sbostic 		leng = lengp->constblock.constant.ci;
95243220Sbostic 	else	{
95343220Sbostic 		fatal("automatic variable of nonconstant length");
95443220Sbostic 		}
95543220Sbostic else
95643220Sbostic 	leng = typesize[t];
95743220Sbostic autoleng = roundup( autoleng, typealign[t]);
95843220Sbostic 
95943220Sbostic q = ALLOC(Addrblock);
96043220Sbostic q->tag = TADDR;
96143220Sbostic q->vtype = t;
96243220Sbostic if(lengp)
96343220Sbostic 	{
96443220Sbostic 	q->vleng = ICON(leng);
96543220Sbostic 	q->varleng = leng;
96643220Sbostic 	}
96743220Sbostic q->vstg = STGAUTO;
96843220Sbostic q->memno = newlabel();
96943220Sbostic q->ntempelt = nelt;
97043220Sbostic #if TARGET==PDP11 || TARGET==VAX || TARGET == TAHOE
97143220Sbostic 	/* stack grows downward */
97243220Sbostic 	autoleng += nelt*leng;
97343220Sbostic 	q->memoffset = ICON( - autoleng );
97443220Sbostic #else
97543220Sbostic 	q->memoffset = ICON( autoleng );
97643220Sbostic 	autoleng += nelt*leng;
97743220Sbostic #endif
97843220Sbostic 
97943220Sbostic return(q);
98043220Sbostic }
98143220Sbostic 
98243220Sbostic 
98343220Sbostic 
98443220Sbostic /*
98543220Sbostic  *  create a temporary block (TTEMP) when optimizing,
98643220Sbostic  *  an ordinary TADDR block when not optimizing
98743220Sbostic  */
98843220Sbostic 
mktmpn(nelt,type,lengp)98943220Sbostic Tempp mktmpn(nelt, type, lengp)
99043220Sbostic int nelt;
99143220Sbostic register int type;
99243220Sbostic expptr lengp;
99343220Sbostic {
99443220Sbostic ftnint leng;
99543220Sbostic chainp p, oldp;
99643220Sbostic register Tempp q;
99743220Sbostic Addrp altemp;
99843220Sbostic 
99943220Sbostic if (! optimflag)
100043220Sbostic 	return ( (Tempp) mkaltmpn(nelt,type,lengp) );
100143220Sbostic if(type==TYUNKNOWN || type==TYERROR)
100243220Sbostic 	badtype("mktmpn", type);
100343220Sbostic 
100443220Sbostic if(type==TYCHAR)
100543220Sbostic 	if( ISICON(lengp) )
100646305Sbostic 		leng = lengp->constblock.constant.ci;
100743220Sbostic 	else	{
100843220Sbostic 		err("adjustable length");
100943220Sbostic 		return( (Tempp) errnode() );
101043220Sbostic 		}
101143220Sbostic else
101243220Sbostic 	leng = typesize[type];
101343220Sbostic 
101443220Sbostic q = ALLOC(Tempblock);
101543220Sbostic q->tag = TTEMP;
101643220Sbostic q->vtype = type;
101743220Sbostic if(type == TYCHAR)
101843220Sbostic 	{
101943220Sbostic 	q->vleng = ICON(leng);
102043220Sbostic 	q->varleng = leng;
102143220Sbostic 	}
102243220Sbostic 
102343220Sbostic altemp = ALLOC(Addrblock);
102443220Sbostic altemp->tag = TADDR;
102543220Sbostic altemp->vstg = STGUNKNOWN;
102643220Sbostic q->memalloc = altemp;
102743220Sbostic 
102843220Sbostic q->ntempelt = nelt;
102943220Sbostic q->istemp = YES;
103043220Sbostic return(q);
103143220Sbostic }
103243220Sbostic 
103343220Sbostic 
103443220Sbostic 
mktemp(type,lengp)103543220Sbostic Addrp mktemp(type, lengp)
103643220Sbostic int type;
103743220Sbostic expptr lengp;
103843220Sbostic {
103943220Sbostic return( (Addrp) mktmpn(1,type,lengp) );
104043220Sbostic }
104143220Sbostic 
104243220Sbostic 
104343220Sbostic 
104443220Sbostic /*  allocate a temporary location for the given temporary block;
104543220Sbostic     if already allocated, return its location  */
104643220Sbostic 
altmpn(tp)104743220Sbostic Addrp altmpn(tp)
104843220Sbostic Tempp tp;
104943220Sbostic 
105043220Sbostic {
105143220Sbostic Addrp t, q;
105243220Sbostic 
105343220Sbostic if (tp->tag != TTEMP)
105443220Sbostic 	badtag ("altmpn",tp->tag);
105543220Sbostic 
105643220Sbostic t = tp->memalloc;
105743220Sbostic if (t->vstg != STGUNKNOWN)
105843220Sbostic 	{
105943220Sbostic 	if (tp->vtype == TYCHAR)
106043220Sbostic 		{
106143220Sbostic 		/*
106243220Sbostic 		 * Unformatted I/O parameters are treated like character
106343220Sbostic 		 *	strings (sigh) -- propagate type and length.
106443220Sbostic 		 */
106543220Sbostic 		t = (Addrp) cpexpr(t);
106643220Sbostic 		t->vtype = tp->vtype;
106743220Sbostic 		t->vleng = tp->vleng;
106843220Sbostic 		t->varleng = tp->varleng;
106943220Sbostic 		}
107043220Sbostic 	return (t);
107143220Sbostic 	}
107243220Sbostic 
107343220Sbostic q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng);
107443220Sbostic cpn (sizeof(struct Addrblock), (char*)q, (char*)t);
107543220Sbostic free ( (charptr) q);
107643220Sbostic return(t);
107743220Sbostic }
107843220Sbostic 
107943220Sbostic 
108043220Sbostic 
108143220Sbostic /*  create and allocate space immediately for a temporary  */
108243220Sbostic 
mkaltemp(type,lengp)108343220Sbostic Addrp mkaltemp(type,lengp)
108443220Sbostic int type;
108543220Sbostic expptr lengp;
108643220Sbostic {
108743220Sbostic return (mkaltmpn(1,type,lengp));
108843220Sbostic }
108943220Sbostic 
109043220Sbostic 
109143220Sbostic 
mkaltmpn(nelt,type,lengp)109243220Sbostic Addrp mkaltmpn(nelt,type,lengp)
109343220Sbostic int nelt;
109443220Sbostic register int type;
109543220Sbostic expptr lengp;
109643220Sbostic {
109743220Sbostic ftnint leng;
109843220Sbostic chainp p, oldp;
109943220Sbostic register Addrp q;
110043220Sbostic 
110143220Sbostic if(type==TYUNKNOWN || type==TYERROR)
110243220Sbostic 	badtype("mkaltmpn", type);
110343220Sbostic 
110443220Sbostic if(type==TYCHAR)
110543220Sbostic 	if( ISICON(lengp) )
110646305Sbostic 		leng = lengp->constblock.constant.ci;
110743220Sbostic 	else	{
110843220Sbostic 		err("adjustable length");
110943220Sbostic 		return( (Addrp) errnode() );
111043220Sbostic 		}
111143220Sbostic 
111243220Sbostic /*
111343220Sbostic  * if a temporary of appropriate shape is on the templist,
111443220Sbostic  * remove it from the list and return it
111543220Sbostic  */
111643220Sbostic 
111743220Sbostic #ifdef notdef
111843220Sbostic /*
111943220Sbostic  * This code is broken until SKFRTEMP slots can be processed in putopt()
112043220Sbostic  *	instead of in optimize() -- all kinds of things in putpcc.c can
112143220Sbostic  *	bomb because of this.  Sigh.
112243220Sbostic  */
112343220Sbostic for(oldp=CHNULL, p=templist  ;  p  ;  oldp=p, p=p->nextp)
112443220Sbostic 	{
112543220Sbostic 	q = (Addrp) (p->datap);
112643220Sbostic 	if(q->vtype==type && q->ntempelt==nelt &&
112746305Sbostic 	    (type!=TYCHAR || q->vleng->constblock.constant.ci==leng) )
112843220Sbostic 		{
112943220Sbostic 		if(oldp)
113043220Sbostic 			oldp->nextp = p->nextp;
113143220Sbostic 		else
113243220Sbostic 			templist = p->nextp;
113343220Sbostic 		free( (charptr) p);
113443220Sbostic 
113543220Sbostic 		if (debugflag[14])
113643220Sbostic 			fprintf(diagfile,"mkaltmpn reusing offset %d\n",
113746305Sbostic 				q->memoffset->constblock.constant.ci);
113843220Sbostic 		return(q);
113943220Sbostic 		}
114043220Sbostic 	}
114143220Sbostic #endif notdef
114243220Sbostic q = autovar(nelt, type, lengp);
114343220Sbostic q->istemp = YES;
114443220Sbostic 
114543220Sbostic if (debugflag[14])
114643220Sbostic 	fprintf(diagfile,"mkaltmpn new offset %d\n",
114746305Sbostic 		q->memoffset->constblock.constant.ci);
114843220Sbostic return(q);
114943220Sbostic }
115043220Sbostic 
115143220Sbostic 
115243220Sbostic 
115343220Sbostic /*  The following routine is a patch which is only needed because the	*/
115443220Sbostic /*  code for processing actual arguments for calls does not allocate	*/
115543220Sbostic /*  the temps it needs before optimization takes place.  A better	*/
115643220Sbostic /*  solution is possible, but I do not have the time to implement it	*/
115743220Sbostic /*  now.								*/
115843220Sbostic /*									*/
115943220Sbostic /*					Robert P. Corbett		*/
116043220Sbostic 
116143220Sbostic Addrp
mkargtemp(type,lengp)116243220Sbostic mkargtemp(type, lengp)
116343220Sbostic int type;
116443220Sbostic expptr lengp;
116543220Sbostic {
116643220Sbostic   ftnint leng;
116743220Sbostic   chainp oldp, p;
116843220Sbostic   Addrp q;
116943220Sbostic 
117043220Sbostic   if (type == TYUNKNOWN || type == TYERROR)
117143220Sbostic     badtype("mkargtemp", type);
117243220Sbostic 
117343220Sbostic   if (type == TYCHAR)
117443220Sbostic     {
117543220Sbostic       if (ISICON(lengp))
117646305Sbostic 	leng = lengp->constblock.constant.ci;
117743220Sbostic       else
117843220Sbostic 	{
117943220Sbostic 	  err("adjustable length");
118043220Sbostic 	  return ((Addrp) errnode());
118143220Sbostic 	}
118243220Sbostic     }
118343220Sbostic 
118443220Sbostic   oldp = CHNULL;
118543220Sbostic   p = argtemplist;
118643220Sbostic 
118743220Sbostic   while (p)
118843220Sbostic     {
118943220Sbostic       q = (Addrp) (p->datap);
119043220Sbostic       if (q->vtype == type
119146305Sbostic 	  && (type != TYCHAR || q->vleng->constblock.constant.ci == leng))
119243220Sbostic 	{
119343220Sbostic 	  if (oldp)
119443220Sbostic 	    oldp->nextp = p->nextp;
119543220Sbostic 	  else
119643220Sbostic 	    argtemplist = p->nextp;
119743220Sbostic 
119843220Sbostic 	  p->nextp = activearglist;
119943220Sbostic 	  activearglist = p;
120043220Sbostic 
120143220Sbostic 	  return ((Addrp) cpexpr(q));
120243220Sbostic 	}
120343220Sbostic 
120443220Sbostic       oldp = p;
120543220Sbostic       p = p->nextp;
120643220Sbostic     }
120743220Sbostic 
120843220Sbostic   q = autovar(1, type, lengp);
120943220Sbostic   activearglist = mkchain(q, activearglist);
121043220Sbostic   return ((Addrp) cpexpr(q));
121143220Sbostic }
121243220Sbostic 
121343220Sbostic /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
121443220Sbostic 
comblock(len,s)121543220Sbostic struct Extsym *comblock(len, s)
121643220Sbostic register int len;
121743220Sbostic register char *s;
121843220Sbostic {
121943220Sbostic struct Extsym *p;
122043220Sbostic 
122143220Sbostic if(len == 0)
122243220Sbostic 	{
122343220Sbostic 	s = BLANKCOMMON;
122443220Sbostic 	len = strlen(s);
122543220Sbostic 	}
122643220Sbostic p = mkext( varunder(len, s) );
122743220Sbostic if(p->extstg == STGUNKNOWN)
122843220Sbostic 	p->extstg = STGCOMMON;
122943220Sbostic else if(p->extstg != STGCOMMON)
123043220Sbostic 	{
123143220Sbostic 	errstr("%s cannot be a common block name", s);
123243220Sbostic 	return(0);
123343220Sbostic 	}
123443220Sbostic 
123543220Sbostic return( p );
123643220Sbostic }
123743220Sbostic 
123843220Sbostic 
123943220Sbostic incomm(c, v)
124043220Sbostic struct Extsym *c;
124143220Sbostic Namep v;
124243220Sbostic {
124343220Sbostic if(v->vstg != STGUNKNOWN)
124443220Sbostic 	dclerr("incompatible common declaration", v);
124543220Sbostic else
124643220Sbostic 	{
124743220Sbostic 	if(c == (struct Extsym *) 0)
124843220Sbostic 		return;		/* Illegal common block name upstream */
124943220Sbostic 	v->vstg = STGCOMMON;
125043220Sbostic 	c->extp = hookup(c->extp, mkchain(v,CHNULL) );
125143220Sbostic 	}
125243220Sbostic }
125343220Sbostic 
125443220Sbostic 
125543220Sbostic 
125643220Sbostic 
settype(v,type,length)125743220Sbostic settype(v, type, length)
125843220Sbostic register Namep  v;
125943220Sbostic register int type;
126043220Sbostic register int length;
126143220Sbostic {
126243220Sbostic if(type == TYUNKNOWN)
126343220Sbostic 	return;
126443220Sbostic 
126543220Sbostic if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
126643220Sbostic 	{
126743220Sbostic 	v->vtype = TYSUBR;
126843220Sbostic 	frexpr(v->vleng);
126943220Sbostic 	}
127043220Sbostic else if(type < 0)	/* storage class set */
127143220Sbostic 	{
127243220Sbostic 	if(v->vstg == STGUNKNOWN)
127343220Sbostic 		v->vstg = - type;
127443220Sbostic 	else if(v->vstg != -type)
127543220Sbostic 		dclerr("incompatible storage declarations", v);
127643220Sbostic 	}
127743220Sbostic else if(v->vtype == TYUNKNOWN)
127843220Sbostic 	{
127943220Sbostic 	if( (v->vtype = lengtype(type, length))==TYCHAR && length>=0)
128043220Sbostic 		v->vleng = ICON(length);
128143220Sbostic 	}
128246305Sbostic else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.constant.ci!=length) )
128343220Sbostic 	dclerr("incompatible type declarations", v);
128443220Sbostic }
128543220Sbostic 
128643220Sbostic 
128743220Sbostic 
128843220Sbostic 
128943220Sbostic 
lengtype(type,length)129043220Sbostic lengtype(type, length)
129143220Sbostic register int type;
129243220Sbostic register int length;
129343220Sbostic {
129443220Sbostic switch(type)
129543220Sbostic 	{
129643220Sbostic 	case TYREAL:
129743220Sbostic 		if(length == 8)
129843220Sbostic 			return(TYDREAL);
129943220Sbostic 		if(length == 4)
130043220Sbostic 			goto ret;
130143220Sbostic 		break;
130243220Sbostic 
130343220Sbostic 	case TYCOMPLEX:
130443220Sbostic 		if(length == 16)
130543220Sbostic 			return(TYDCOMPLEX);
130643220Sbostic 		if(length == 8)
130743220Sbostic 			goto ret;
130843220Sbostic 		break;
130943220Sbostic 
131043220Sbostic 	case TYSHORT:
131143220Sbostic 	case TYDREAL:
131243220Sbostic 	case TYDCOMPLEX:
131343220Sbostic 	case TYCHAR:
131443220Sbostic 	case TYUNKNOWN:
131543220Sbostic 	case TYSUBR:
131643220Sbostic 	case TYERROR:
131743220Sbostic 		goto ret;
131843220Sbostic 
131943220Sbostic 	case TYLOGICAL:
132043220Sbostic 		if(length == typesize[TYLOGICAL])
132143220Sbostic 			goto ret;
132243220Sbostic 		break;
132343220Sbostic 
132443220Sbostic 	case TYLONG:
132543220Sbostic 		if(length == 0 )
132643220Sbostic 			return(tyint);
132743220Sbostic 		if(length == 2)
132843220Sbostic 			return(TYSHORT);
132943220Sbostic 		if(length == 4 )
133043220Sbostic 			goto ret;
133143220Sbostic 		break;
133243220Sbostic 	default:
133343220Sbostic 		badtype("lengtype", type);
133443220Sbostic 	}
133543220Sbostic 
133643220Sbostic if(length != 0)
133743220Sbostic 	err("incompatible type-length combination");
133843220Sbostic 
133943220Sbostic ret:
134043220Sbostic 	return(type);
134143220Sbostic }
134243220Sbostic 
134343220Sbostic 
134443220Sbostic 
134543220Sbostic 
134643220Sbostic 
setintr(v)134743220Sbostic setintr(v)
134843220Sbostic register Namep  v;
134943220Sbostic {
135043220Sbostic register int k;
135143220Sbostic 
135243220Sbostic if(v->vstg == STGUNKNOWN)
135343220Sbostic 	v->vstg = STGINTR;
135443220Sbostic else if(v->vstg!=STGINTR)
135543220Sbostic 	dclerr("incompatible use of intrinsic function", v);
135643220Sbostic if(v->vclass==CLUNKNOWN)
135743220Sbostic 	v->vclass = CLPROC;
135843220Sbostic if(v->vprocclass == PUNKNOWN)
135943220Sbostic 	v->vprocclass = PINTRINSIC;
136043220Sbostic else if(v->vprocclass != PINTRINSIC)
136143220Sbostic 	dclerr("invalid intrinsic declaration", v);
136243220Sbostic if(k = intrfunct(v->varname))
136343220Sbostic 	v->vardesc.varno = k;
136443220Sbostic else
136543220Sbostic 	dclerr("unknown intrinsic function", v);
136643220Sbostic }
136743220Sbostic 
136843220Sbostic 
136943220Sbostic 
setext(v)137043220Sbostic setext(v)
137143220Sbostic register Namep  v;
137243220Sbostic {
137343220Sbostic if(v->vclass == CLUNKNOWN)
137443220Sbostic 	v->vclass = CLPROC;
137543220Sbostic else if(v->vclass != CLPROC)
137643220Sbostic 	dclerr("conflicting declarations", v);
137743220Sbostic 
137843220Sbostic if(v->vprocclass == PUNKNOWN)
137943220Sbostic 	v->vprocclass = PEXTERNAL;
138043220Sbostic else if(v->vprocclass != PEXTERNAL)
138143220Sbostic 	dclerr("conflicting declarations", v);
138243220Sbostic }
138343220Sbostic 
138443220Sbostic 
138543220Sbostic 
138643220Sbostic 
138743220Sbostic /* create dimensions block for array variable */
138843220Sbostic 
setbound(v,nd,dims)138943220Sbostic setbound(v, nd, dims)
139043220Sbostic register Namep  v;
139143220Sbostic int nd;
139243220Sbostic struct { expptr lb, ub; } dims[ ];
139343220Sbostic {
139443220Sbostic register expptr q, t;
139543220Sbostic register struct Dimblock *p;
139643220Sbostic int i;
139743220Sbostic 
139843220Sbostic if(v->vclass == CLUNKNOWN)
139943220Sbostic 	v->vclass = CLVAR;
140043220Sbostic else if(v->vclass != CLVAR)
140143220Sbostic 	{
140243220Sbostic 	dclerr("only variables may be arrays", v);
140343220Sbostic 	return;
140443220Sbostic 	}
140543220Sbostic if(v->vdim)
140643220Sbostic 	{
140743220Sbostic 	dclerr("redimensioned array", v);
140843220Sbostic 	return;
140943220Sbostic 	}
141043220Sbostic 
141143220Sbostic v->vdim = p = (struct Dimblock *)
141243220Sbostic 		ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) );
141343220Sbostic p->ndim = nd;
141443220Sbostic p->nelt = ICON(1);
141543220Sbostic 
141643220Sbostic for(i=0 ; i<nd ; ++i)
141743220Sbostic 	{
141843220Sbostic #ifdef SDB
141943220Sbostic         if(sdbflag) {
142043220Sbostic /* Save the bounds trees built up by the grammar routines for use in stabs */
142143220Sbostic 
142243220Sbostic 		if(dims[i].lb == NULL) p->dims[i].lb=ICON(1);
142343220Sbostic         	else p->dims[i].lb= (expptr) cpexpr(dims[i].lb);
142443220Sbostic                 if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL;
142543220Sbostic                 else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL);
142643220Sbostic 
142743220Sbostic 		if(dims[i].ub == NULL) p->dims[i].ub=ICON(1);
142843220Sbostic         	else p->dims[i].ub = (expptr) cpexpr(dims[i].ub);
142943220Sbostic                 if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL;
143043220Sbostic                 else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL);
143143220Sbostic 	}
143243220Sbostic #endif
143343220Sbostic 	if( (q = dims[i].ub) == NULL)
143443220Sbostic 		{
143543220Sbostic 		if(i == nd-1)
143643220Sbostic 			{
143743220Sbostic 			frexpr(p->nelt);
143843220Sbostic 			p->nelt = NULL;
143943220Sbostic 			}
144043220Sbostic 		else
144143220Sbostic 			err("only last bound may be asterisk");
144243220Sbostic 		p->dims[i].dimsize = ICON(1);;
144343220Sbostic 		p->dims[i].dimexpr = NULL;
144443220Sbostic 		}
144543220Sbostic 	else
144643220Sbostic 		{
144743220Sbostic 		if(dims[i].lb)
144843220Sbostic 			{
144943220Sbostic 			q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
145043220Sbostic 			q = mkexpr(OPPLUS, q, ICON(1) );
145143220Sbostic 			}
145243220Sbostic 		if( ISCONST(q) )
145343220Sbostic 			{
145443220Sbostic 			if (!ISINT(q->headblock.vtype)) {
145543220Sbostic 			   dclerr("dimension bounds must be integer expression", v);
145643220Sbostic 			   frexpr(q);
145743220Sbostic 			   q = ICON(0);
145843220Sbostic 			   }
145946305Sbostic 			if ( q->constblock.constant.ci <= 0)
146043220Sbostic 			   {
146143220Sbostic 			   dclerr("array bounds out of sequence", v);
146243220Sbostic 			   frexpr(q);
146343220Sbostic 			   q = ICON(0);
146443220Sbostic 			   }
146543220Sbostic 			p->dims[i].dimsize = q;
146643220Sbostic 			p->dims[i].dimexpr = (expptr) PNULL;
146743220Sbostic 			}
146843220Sbostic 		else	{
146943220Sbostic 			p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL);
147043220Sbostic 			p->dims[i].dimexpr = q;
147143220Sbostic 			}
147243220Sbostic 		if(p->nelt)
147343220Sbostic 			p->nelt = mkexpr(OPSTAR, p->nelt,
147443220Sbostic 					cpexpr(p->dims[i].dimsize) );
147543220Sbostic 		}
147643220Sbostic 	}
147743220Sbostic 
147843220Sbostic q = dims[nd-1].lb;
147943220Sbostic if(q == NULL)
148043220Sbostic 	q = ICON(1);
148143220Sbostic 
148243220Sbostic for(i = nd-2 ; i>=0 ; --i)
148343220Sbostic 	{
148443220Sbostic 	t = dims[i].lb;
148543220Sbostic 	if(t == NULL)
148643220Sbostic 		t = ICON(1);
148743220Sbostic 	if(p->dims[i].dimsize)
148843220Sbostic 		q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
148943220Sbostic 	}
149043220Sbostic 
149143220Sbostic if( ISCONST(q) )
149243220Sbostic 	{
149343220Sbostic 	p->baseoffset = q;
149443220Sbostic 	p->basexpr = NULL;
149543220Sbostic 	}
149643220Sbostic else
149743220Sbostic 	{
149843220Sbostic 	p->baseoffset = (expptr) autovar(1, tyint, PNULL);
149943220Sbostic 	p->basexpr = q;
150043220Sbostic 	}
150143220Sbostic }
150243220Sbostic 
150343220Sbostic 
150443220Sbostic 
150543220Sbostic /*
150643220Sbostic  * Check the dimensions of q to ensure that they are appropriately defined.
150743220Sbostic  */
chkdim(q)150843220Sbostic LOCAL chkdim(q)
150943220Sbostic register Namep q;
151043220Sbostic {
151143220Sbostic   register struct Dimblock *p;
151243220Sbostic   register int i;
151343220Sbostic   expptr e;
151443220Sbostic 
151543220Sbostic   if (q == NULL)
151643220Sbostic     return;
151743220Sbostic   if (q->vclass != CLVAR)
151843220Sbostic     return;
151943220Sbostic   if (q->vdim == NULL)
152043220Sbostic     return;
152143220Sbostic   p = q->vdim;
152243220Sbostic   for (i = 0; i < p->ndim; ++i)
152343220Sbostic     {
152443220Sbostic #ifdef SDB
152543220Sbostic       if (sdbflag)
152643220Sbostic 	{
152743220Sbostic 	  if (e = p->dims[i].lb)
152843220Sbostic 	    chkdime(e, q);
152943220Sbostic 	  if (e = p->dims[i].ub)
153043220Sbostic 	    chkdime(e, q);
153143220Sbostic 	}
153243220Sbostic       else
153343220Sbostic #endif SDB
153443220Sbostic       if (e = p->dims[i].dimexpr)
153543220Sbostic 	chkdime(e, q);
153643220Sbostic     }
153743220Sbostic }
153843220Sbostic 
153943220Sbostic 
154043220Sbostic 
154143220Sbostic /*
154243220Sbostic  * The actual checking for chkdim() -- examines each expression.
154343220Sbostic  */
chkdime(expr,q)154443220Sbostic LOCAL chkdime(expr, q)
154543220Sbostic expptr expr;
154643220Sbostic Namep q;
154743220Sbostic {
154843220Sbostic   register expptr e;
154943220Sbostic 
155043220Sbostic   e = fixtype(cpexpr(expr));
155143220Sbostic   if (!ISINT(e->exprblock.vtype))
155243220Sbostic     dclerr("non-integer dimension", q);
155343220Sbostic   else if (!safedim(e))
155443220Sbostic     dclerr("undefined dimension", q);
155543220Sbostic   frexpr(e);
155643220Sbostic   return;
155743220Sbostic }
155843220Sbostic 
155943220Sbostic 
156043220Sbostic 
156143220Sbostic /*
156243220Sbostic  * A recursive routine to find undefined variables in dimension expressions.
156343220Sbostic  */
safedim(e)156443220Sbostic LOCAL safedim(e)
156543220Sbostic expptr e;
156643220Sbostic {
156743220Sbostic   chainp cp;
156843220Sbostic 
156943220Sbostic   if (e == NULL)
157043220Sbostic     return 1;
157143220Sbostic   switch (e->tag)
157243220Sbostic     {
157343220Sbostic       case TEXPR:
157443220Sbostic 	if (e->exprblock.opcode == OPCALL || e->exprblock.opcode == OPCCALL)
157543220Sbostic 	  return 0;
157643220Sbostic 	return safedim(e->exprblock.leftp) && safedim(e->exprblock.rightp);
157743220Sbostic       case TADDR:
157843220Sbostic 	switch (e->addrblock.vstg)
157943220Sbostic 	  {
158043220Sbostic 	    case STGCOMMON:
158143220Sbostic 	    case STGARG:
158243220Sbostic 	    case STGCONST:
158343220Sbostic 	    case STGEQUIV:
158443220Sbostic 	      if (e->addrblock.isarray)
158543220Sbostic 		return 0;
158643220Sbostic 	      return safedim(e->addrblock.memoffset);
158743220Sbostic 	    default:
158843220Sbostic 	      return 0;
158943220Sbostic 	  }
159043220Sbostic       case TCONST:
159143220Sbostic       case TTEMP:
159243220Sbostic 	return 1;
159343220Sbostic     }
159443220Sbostic   return 0;
159543220Sbostic }
159643220Sbostic 
159743220Sbostic 
159843220Sbostic 
enlist(size,np,ep)159943220Sbostic LOCAL enlist(size, np, ep)
160043220Sbostic ftnint size;
160143220Sbostic Namep np;
160243220Sbostic struct Equivblock *ep;
160343220Sbostic {
160443220Sbostic   register sizelist *sp;
160543220Sbostic   register sizelist *t;
160643220Sbostic   register varlist *p;
160743220Sbostic 
160843220Sbostic   sp = varsizes;
160943220Sbostic 
161043220Sbostic   if (sp == NULL)
161143220Sbostic     {
161243220Sbostic       sp = ALLOC(SizeList);
161343220Sbostic       sp->size = size;
161443220Sbostic       varsizes = sp;
161543220Sbostic     }
161643220Sbostic   else
161743220Sbostic     {
161843220Sbostic       while (sp->size != size)
161943220Sbostic 	{
162043220Sbostic 	  if (sp->next != NULL && sp->next->size <= size)
162143220Sbostic 	    sp = sp->next;
162243220Sbostic 	  else
162343220Sbostic 	    {
162443220Sbostic 	      t = sp;
162543220Sbostic 	      sp = ALLOC(SizeList);
162643220Sbostic 	      sp->size = size;
162743220Sbostic 	      sp->next = t->next;
162843220Sbostic 	      t->next = sp;
162943220Sbostic 	    }
163043220Sbostic 	}
163143220Sbostic     }
163243220Sbostic 
163343220Sbostic   p = ALLOC(VarList);
163443220Sbostic   p->next = sp->vars;
163543220Sbostic   p->np = np;
163643220Sbostic   p->ep = ep;
163743220Sbostic 
163843220Sbostic   sp->vars = p;
163943220Sbostic 
164043220Sbostic   return;
164143220Sbostic }
164243220Sbostic 
164343220Sbostic 
164443220Sbostic 
outlocvars()164543220Sbostic outlocvars()
164643220Sbostic {
164743220Sbostic 
164843220Sbostic   register varlist *first, *last;
164943220Sbostic   register varlist *vp, *t;
165043220Sbostic   register sizelist *sp, *sp1;
165143220Sbostic   register Namep np;
165243220Sbostic   register struct Equivblock *ep;
165343220Sbostic   register int i;
165443220Sbostic   register int alt;
165543220Sbostic   register int type;
165643220Sbostic   char sname[100];
165743220Sbostic   char setbuff[100];
165843220Sbostic 
165943220Sbostic   sp = varsizes;
166043220Sbostic   if (sp == NULL)
166143220Sbostic     return;
166243220Sbostic 
166343220Sbostic   vp = sp->vars;
166443220Sbostic   if (vp->np != NULL)
166543220Sbostic     {
166643220Sbostic       np = vp->np;
166743220Sbostic       sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel,
166843220Sbostic 	      np->vardesc.varno);
166943220Sbostic     }
167043220Sbostic   else
167143220Sbostic     {
167243220Sbostic       i = vp->ep - eqvclass;
167343220Sbostic       sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart);
167443220Sbostic     }
167543220Sbostic 
167643220Sbostic   first = last = NULL;
167743220Sbostic   alt = NO;
167843220Sbostic 
167943220Sbostic   while (sp != NULL)
168043220Sbostic     {
168143220Sbostic       vp = sp->vars;
168243220Sbostic       while (vp != NULL)
168343220Sbostic 	{
168443220Sbostic 	  t = vp->next;
168543220Sbostic 	  if (alt == YES)
168643220Sbostic 	    {
168743220Sbostic 	      alt = NO;
168843220Sbostic 	      vp->next = first;
168943220Sbostic 	      first = vp;
169043220Sbostic 	    }
169143220Sbostic 	  else
169243220Sbostic 	    {
169343220Sbostic 	      alt = YES;
169443220Sbostic 	      if (last != NULL)
169543220Sbostic 	        last->next = vp;
169643220Sbostic 	      else
169743220Sbostic 		first = vp;
169843220Sbostic 	      vp->next = NULL;
169943220Sbostic 	      last = vp;
170043220Sbostic 	    }
170143220Sbostic 	  vp = t;
170243220Sbostic 	}
170343220Sbostic       sp1 = sp;
170443220Sbostic       sp = sp->next;
170543220Sbostic       free((char *) sp1);
170643220Sbostic     }
170743220Sbostic 
170843220Sbostic   vp = first;
170943220Sbostic   while(vp != NULL)
171043220Sbostic     {
171143220Sbostic       if (vp->np != NULL)
171243220Sbostic 	{
171343220Sbostic 	  np = vp->np;
171443220Sbostic 	  sprintf(sname, "v.%d", np->vardesc.varno);
171543220Sbostic 	  pralign(typealign[np->vtype]);
171643220Sbostic 	  if (np->init)
171743220Sbostic 	    prlocdata(sname, np->varsize, np->vtype, np->initoffset,
171843220Sbostic 		      &(np->inlcomm));
171943220Sbostic 	  else
172043220Sbostic 	    {
172143220Sbostic 	      if (typealign[np->vtype] == 1)
172243220Sbostic 		  pralign(3);
172343220Sbostic 	      fprintf(initfile, "%s:\n\t.space\t%d\n", sname,
172443220Sbostic 		      np->varsize);
172543220Sbostic 	    }
172643220Sbostic 	  np->inlcomm = NO;
172743220Sbostic 	}
172843220Sbostic       else
172943220Sbostic 	{
173043220Sbostic 	  ep = vp->ep;
173143220Sbostic 	  i = ep - eqvclass;
173243220Sbostic 	  if (ep->eqvleng >= 8)
173343220Sbostic 	    type = TYDREAL;
173443220Sbostic 	  else if (ep->eqvleng >= 4)
173543220Sbostic 	    type = TYLONG;
173643220Sbostic 	  else if (ep->eqvleng >= 2)
173743220Sbostic 	    type = TYSHORT;
173843220Sbostic 	  else
173943220Sbostic 	    type = TYCHAR;
174043220Sbostic 	  sprintf(sname, "q.%d", i + eqvstart);
174143220Sbostic 	  if (ep->init)
174243220Sbostic 	    prlocdata(sname, ep->eqvleng, type, ep->initoffset,
174343220Sbostic 		      &(ep->inlcomm));
174443220Sbostic 	  else
174543220Sbostic 	    {
174643220Sbostic 	      pralign(typealign[type]);
174743220Sbostic 	      fprintf(initfile, "%s:\n\t.space\t%d\n", sname, ep->eqvleng);
174843220Sbostic 	    }
174943220Sbostic 	  ep->inlcomm = NO;
175043220Sbostic 	}
175143220Sbostic       t = vp;
175243220Sbostic       vp = vp->next;
175343220Sbostic       free((char *) t);
175443220Sbostic     }
175543220Sbostic   fprintf(initfile, "%s\n", setbuff);
175643220Sbostic   return;
175743220Sbostic }
1758