xref: /csrg-svn/usr.bin/f77/pass1.vax/proc.c (revision 47955)
1*47955Sbostic /*-
2*47955Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47955Sbostic  * All rights reserved.
4*47955Sbostic  *
5*47955Sbostic  * %sccs.include.proprietary.c%
622861Smckusick  */
722861Smckusick 
822861Smckusick #ifndef lint
9*47955Sbostic static char sccsid[] = "@(#)proc.c	5.9 (Berkeley) 04/12/91";
10*47955Sbostic #endif /* not lint */
1122861Smckusick 
1222861Smckusick /*
1322861Smckusick  * proc.c
1422861Smckusick  *
1522861Smckusick  * Routines for handling procedures, f77 compiler, pass 1.
1622861Smckusick  *
1722861Smckusick  * University of Utah CS Dept modification history:
1822861Smckusick  *
1922861Smckusick  * $Log:	proc.c,v $
2026009Sdonn  * Revision 5.9  86/01/28  22:30:28  donn
2126009Sdonn  * Let functions of type character have adjustable length.
2226009Sdonn  *
2325816Sdonn  * Revision 5.8  86/01/10  19:02:19  donn
2425816Sdonn  * More dbx hacking -- filter out incomplete declarations (with bogus types).
2525816Sdonn  *
2625816Sdonn  * Revision 5.7  86/01/10  13:53:02  donn
2725816Sdonn  * Since we now postpone determination of the type of an argument, we must
2825816Sdonn  * make sure to emit stab information at the end of the routine when we
2925816Sdonn  * definitely have the type.  Notice some care was taken to make sure that
3025816Sdonn  * arguments appear in order in the output file since that's how dbx wants
3125816Sdonn  * them.  Also a minor change for dummy procedures.
3225816Sdonn  *
3325744Sdonn  * Revision 5.6  86/01/06  16:28:06  donn
3425744Sdonn  * Sigh.  We can't commit to defining a symbol as a variable instead of a
3525744Sdonn  * function based only on what we have seen through the declaration section;
3625744Sdonn  * this was properly handled for normal variables but not for arguments.
3725744Sdonn  *
3825744Sdonn  * Revision 5.5  86/01/01  21:59:17  donn
3925744Sdonn  * Pick up CHARACTER*(*) declarations for variables which aren't dummy
4025744Sdonn  * arguments, and complain about them.
4125744Sdonn  *
4225744Sdonn  * Revision 5.4  85/12/20  19:18:35  donn
4325744Sdonn  * Don't assume that dummy procedures of unknown type are functions of type
4425744Sdonn  * undefined until the user (mis-)uses them that way -- they may also be
4525744Sdonn  * subroutines.
4625744Sdonn  *
4725103Sdonn  * Revision 5.3  85/09/30  23:21:07  donn
4825103Sdonn  * Print space with prspace() in outlocvars() so that alignment is preserved.
4925103Sdonn  *
5024484Sdonn  * Revision 5.2  85/08/10  05:03:34  donn
5124484Sdonn  * Support for NAMELIST i/o from Jerry Berkman.
5224484Sdonn  *
5324484Sdonn  * Revision 5.1  85/08/10  03:49:14  donn
5424484Sdonn  * 4.3 alpha
5524484Sdonn  *
5623477Smckusick  * Revision 3.11  85/06/04  03:45:29  donn
5723477Smckusick  * Changed retval() to recognize that a function declaration might have
5823477Smckusick  * bombed out earlier, leaving an error node behind...
5923477Smckusick  *
6022861Smckusick  * Revision 3.10  85/03/08  23:13:06  donn
6122861Smckusick  * Finally figured out why function calls and array elements are not legal
6222861Smckusick  * dummy array dimension declarator elements.  Hacked safedim() to stop 'em.
6322861Smckusick  *
6422861Smckusick  * Revision 3.9  85/02/02  00:26:10  donn
6522861Smckusick  * Removed the call to entrystab() in enddcl() -- this was redundant (it was
6622861Smckusick  * also done in startproc()) and confusing to dbx to boot.
6722861Smckusick  *
6822861Smckusick  * Revision 3.8  85/01/14  04:21:53  donn
6922861Smckusick  * Added changes to implement Jerry's '-q' option.
7022861Smckusick  *
7122861Smckusick  * Revision 3.7  85/01/11  21:10:35  donn
7222861Smckusick  * In conjunction with other changes to implement SAVE statements, function
7322861Smckusick  * nameblocks were changed to make it appear that they are 'saved' too --
7422861Smckusick  * this arranges things so that function return values are forced out of
7522861Smckusick  * register before a return.
7622861Smckusick  *
7722861Smckusick  * Revision 3.6  84/12/10  19:27:20  donn
7822861Smckusick  * comblock() signals an illegal common block name by returning a null pointer,
7922861Smckusick  * but incomm() wasn't able to handle it, leading to core dumps.  I put the
8022861Smckusick  * fix in incomm() to pick up null common blocks.
8122861Smckusick  *
8222861Smckusick  * Revision 3.5  84/11/21  20:33:31  donn
8322861Smckusick  * It seems that I/O elements are treated as character strings so that their
8422861Smckusick  * length can be passed to the I/O routines...  Unfortunately the compiler
8522861Smckusick  * assumes that no temporaries can be of type CHARACTER and casually tosses
8622861Smckusick  * length and type info away when removing TEMP blocks.  This has been fixed...
8722861Smckusick  *
8822861Smckusick  * Revision 3.4  84/11/05  22:19:30  donn
8922861Smckusick  * Fixed a silly bug in the last fix.
9022861Smckusick  *
9122861Smckusick  * Revision 3.3  84/10/29  08:15:23  donn
9222861Smckusick  * Added code to check the type and shape of subscript declarations,
9322861Smckusick  * per Jerry Berkman's suggestion.
9422861Smckusick  *
9522861Smckusick  * Revision 3.2  84/10/29  05:52:07  donn
9622861Smckusick  * Added change suggested by Jerry Berkman to report an error when an array
9722861Smckusick  * is redimensioned.
9822861Smckusick  *
9922861Smckusick  * Revision 3.1  84/10/13  02:12:31  donn
10022861Smckusick  * Merged Jerry Berkman's version into mine.
10122861Smckusick  *
10222861Smckusick  * Revision 2.1  84/07/19  12:04:09  donn
10322861Smckusick  * Changed comment headers for UofU.
10422861Smckusick  *
10522861Smckusick  * Revision 1.6  84/07/19  11:32:15  donn
10622861Smckusick  * Incorporated fix to setbound() to detect backward array subscript limits.
10722861Smckusick  * The fix is by Bob Corbett, donated by Jerry Berkman.
10822861Smckusick  *
10922861Smckusick  * Revision 1.5  84/07/18  18:25:50  donn
11022861Smckusick  * Fixed problem with doentry() where a placeholder for a return value
11122861Smckusick  * was not allocated if the first entry didn't require one but a later
11222861Smckusick  * entry did.
11322861Smckusick  *
11422861Smckusick  * Revision 1.4  84/05/24  20:52:09  donn
11522861Smckusick  * Installed firewall #ifdef around the code that recycles stack temporaries,
11622861Smckusick  * since it seems to be broken and lacks a good fix for the time being.
11722861Smckusick  *
11822861Smckusick  * Revision 1.3  84/04/16  09:50:46  donn
11922861Smckusick  * Fixed mkargtemp() so that it only passes back a copy of a temporary, keeping
12022861Smckusick  * the original for its own use.  This fixes a set of bugs that are caused by
12122861Smckusick  * elements in the argtemplist getting stomped on.
12222861Smckusick  *
12322861Smckusick  * Revision 1.2  84/02/28  21:12:58  donn
12422861Smckusick  * Added Berkeley changes for subroutine call argument temporaries fix.
12522861Smckusick  *
12622861Smckusick  */
12722861Smckusick 
12822861Smckusick #include "defs.h"
12922861Smckusick 
13022861Smckusick #ifdef SDB
13122861Smckusick #	include <a.out.h>
13222861Smckusick #	ifndef N_SO
13322861Smckusick #		include <stab.h>
13422861Smckusick #	endif
13522861Smckusick #endif
13622861Smckusick 
13722861Smckusick extern flag namesflag;
13822861Smckusick 
13922861Smckusick typedef
14022861Smckusick   struct SizeList
14122861Smckusick     {
14222861Smckusick       struct SizeList *next;
14322861Smckusick       ftnint size;
14422861Smckusick       struct VarList *vars;
14522861Smckusick     }
14622861Smckusick   sizelist;
14722861Smckusick 
14822861Smckusick 
14922861Smckusick typedef
15022861Smckusick   struct VarList
15122861Smckusick     {
15222861Smckusick       struct VarList *next;
15322861Smckusick       Namep np;
15422861Smckusick       struct Equivblock *ep;
15522861Smckusick     }
15622861Smckusick   varlist;
15722861Smckusick 
15822861Smckusick 
15922861Smckusick LOCAL sizelist *varsizes;
16022861Smckusick 
16122861Smckusick 
16222861Smckusick /* start a new procedure */
16322861Smckusick 
newproc()16422861Smckusick newproc()
16522861Smckusick {
16622861Smckusick if(parstate != OUTSIDE)
16722861Smckusick 	{
16822861Smckusick 	execerr("missing end statement", CNULL);
16922861Smckusick 	endproc();
17022861Smckusick 	}
17122861Smckusick 
17222861Smckusick parstate = INSIDE;
17322861Smckusick procclass = CLMAIN;	/* default */
17422861Smckusick }
17522861Smckusick 
17622861Smckusick 
17722861Smckusick 
17822861Smckusick /* end of procedure. generate variables, epilogs, and prologs */
17922861Smckusick 
endproc()18022861Smckusick endproc()
18122861Smckusick {
18222861Smckusick struct Labelblock *lp;
18322861Smckusick 
18422861Smckusick if(parstate < INDATA)
18522861Smckusick 	enddcl();
18622861Smckusick if(ctlstack >= ctls)
18722861Smckusick 	err("DO loop or BLOCK IF not closed");
18822861Smckusick for(lp = labeltab ; lp < labtabend ; ++lp)
18922861Smckusick 	if(lp->stateno!=0 && lp->labdefined==NO)
19022861Smckusick 		errstr("missing statement number %s", convic(lp->stateno) );
19122861Smckusick 
19222861Smckusick if (optimflag)
19322861Smckusick   optimize();
19422861Smckusick 
19522861Smckusick outiodata();
19622861Smckusick epicode();
19722861Smckusick procode();
19822861Smckusick donmlist();
19922861Smckusick dobss();
20022861Smckusick 
20122861Smckusick #if FAMILY == PCC
20222861Smckusick 	putbracket();
20322861Smckusick #endif
20422861Smckusick fixlwm();
20522861Smckusick procinit();	/* clean up for next procedure */
20622861Smckusick }
20722861Smckusick 
20822861Smckusick 
20922861Smckusick 
21022861Smckusick /* End of declaration section of procedure.  Allocate storage. */
21122861Smckusick 
enddcl()21222861Smckusick enddcl()
21322861Smckusick {
21422861Smckusick register struct Entrypoint *ep;
21522861Smckusick 
21622861Smckusick parstate = INEXEC;
21722861Smckusick docommon();
21822861Smckusick doequiv();
21922861Smckusick docomleng();
22022861Smckusick for(ep = entries ; ep ; ep = ep->entnextp) {
22122861Smckusick 	doentry(ep);
22222861Smckusick }
22322861Smckusick }
22422861Smckusick 
22522861Smckusick /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
22622861Smckusick 
22722861Smckusick /* Main program or Block data */
22822861Smckusick 
startproc(prgname,class)22922861Smckusick startproc(prgname, class)
23022861Smckusick Namep prgname;
23122861Smckusick int class;
23222861Smckusick {
23322861Smckusick struct Extsym *progname;
23422861Smckusick register struct Entrypoint *p;
23522861Smckusick 
23622861Smckusick if(prgname)
23722861Smckusick 	procname = prgname->varname;
23822861Smckusick if(namesflag == YES) {
23922861Smckusick 	fprintf(diagfile, "   %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
24022861Smckusick 	if(prgname)
24122861Smckusick 		fprintf(diagfile, " %s", varstr(XL, procname) );
24222861Smckusick 	fprintf(diagfile, ":\n");
24322861Smckusick 	}
24422861Smckusick 
24522861Smckusick if( prgname )
24622861Smckusick 	progname = newentry( prgname );
24722861Smckusick else
24822861Smckusick 	progname = NULL;
24922861Smckusick 
25022861Smckusick p = ALLOC(Entrypoint);
25122861Smckusick if(class == CLMAIN)
25222861Smckusick 	puthead("MAIN_", CLMAIN);
25322861Smckusick else
25422861Smckusick 	puthead(CNULL, CLBLOCK);
25522861Smckusick if(class == CLMAIN)
25622861Smckusick 	newentry( mkname(5, "MAIN") );
25722861Smckusick p->entryname = progname;
25822861Smckusick p->entrylabel = newlabel();
25922861Smckusick entries = p;
26022861Smckusick 
26122861Smckusick procclass = class;
26222861Smckusick retlabel = newlabel();
26322861Smckusick #ifdef SDB
26422861Smckusick if(sdbflag) {
26522861Smckusick          entrystab(p,class);
26622861Smckusick }
26722861Smckusick #endif
26822861Smckusick }
26922861Smckusick 
27022861Smckusick /* subroutine or function statement */
27122861Smckusick 
newentry(v)27222861Smckusick struct Extsym *newentry(v)
27322861Smckusick register Namep v;
27422861Smckusick {
27522861Smckusick register struct Extsym *p;
27622861Smckusick 
27722861Smckusick p = mkext( varunder(VL, v->varname) );
27822861Smckusick 
27922861Smckusick if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
28022861Smckusick 	{
28122861Smckusick 	if(p == 0)
28222861Smckusick 		dclerr("invalid entry name", v);
28322861Smckusick 	else	dclerr("external name already used", v);
28422861Smckusick 	return(0);
28522861Smckusick 	}
28622861Smckusick v->vstg = STGAUTO;
28722861Smckusick v->vprocclass = PTHISPROC;
28822861Smckusick v->vclass = CLPROC;
28922861Smckusick p->extstg = STGEXT;
29022861Smckusick p->extinit = YES;
29122861Smckusick return(p);
29222861Smckusick }
29322861Smckusick 
29422861Smckusick 
entrypt(class,type,length,entname,args)29522861Smckusick entrypt(class, type, length, entname, args)
29622861Smckusick int class, type;
29722861Smckusick ftnint length;
29822861Smckusick Namep entname;
29922861Smckusick chainp args;
30022861Smckusick {
30122861Smckusick struct Extsym *entry;
30222861Smckusick register Namep q;
30322861Smckusick register struct Entrypoint *p, *ep;
30422861Smckusick 
30522861Smckusick if(namesflag == YES) {
30622861Smckusick 	if(class == CLENTRY)
30722861Smckusick 		fprintf(diagfile, "       entry ");
30822861Smckusick 	if(entname)
30922861Smckusick 		fprintf(diagfile, "   %s", varstr(XL, entname->varname) );
31022861Smckusick 	fprintf(diagfile, ":\n");
31122861Smckusick 	}
31222861Smckusick 
31322861Smckusick if( entname->vclass == CLPARAM ) {
31422861Smckusick 	errstr("entry name %s used in 'parameter' statement",
31522861Smckusick 		varstr(XL, entname->varname) );
31622861Smckusick 	return;
31722861Smckusick 	}
31822861Smckusick if( ((type == TYSUBR) || (class == CLENTRY && proctype == TYSUBR))
31922861Smckusick 	&& (entname->vtype != TYUNKNOWN && entname->vtype != TYSUBR) ) {
32022861Smckusick 	errstr("subroutine entry %s previously declared",
32122861Smckusick 		varstr(XL, entname->varname) );
32222861Smckusick 	return;
32322861Smckusick 	}
32422861Smckusick if(  (entname->vstg != STGEXT && entname->vstg != STGUNKNOWN)
32522861Smckusick 	||  (entname->vdim != NULL) ) {
32622861Smckusick 	errstr("subroutine or function entry %s previously declared",
32722861Smckusick 		varstr(XL, entname->varname) );
32822861Smckusick 	return;
32922861Smckusick 	}
33022861Smckusick 
33122861Smckusick if( (class == CLPROC || class == CLENTRY) && type != TYSUBR )
33222861Smckusick 	/* arrange to save function return values */
33322861Smckusick 	entname->vsave = YES;
33422861Smckusick 
33522861Smckusick entry = newentry( entname );
33622861Smckusick 
33722861Smckusick if(class != CLENTRY)
33822861Smckusick 	puthead( varstr(XL, procname = entry->extname), class);
33922861Smckusick q = mkname(VL, nounder(XL,entry->extname) );
34022861Smckusick 
34122861Smckusick if( (type = lengtype(type, (int) length)) != TYCHAR)
34222861Smckusick 	length = 0;
34322861Smckusick if(class == CLPROC)
34422861Smckusick 	{
34522861Smckusick 	procclass = CLPROC;
34622861Smckusick 	proctype = type;
34722861Smckusick 	procleng = length;
34822861Smckusick 
34922861Smckusick 	retlabel = newlabel();
35022861Smckusick 	if(type == TYSUBR)
35122861Smckusick 		ret0label = newlabel();
35222861Smckusick 	}
35322861Smckusick 
35422861Smckusick p = ALLOC(Entrypoint);
35522861Smckusick if(entries)	/* put new block at end of entries list */
35622861Smckusick 	{
35722861Smckusick 	for(ep = entries; ep->entnextp; ep = ep->entnextp)
35822861Smckusick 		;
35922861Smckusick 	ep->entnextp = p;
36022861Smckusick 	}
36122861Smckusick else
36222861Smckusick 	entries = p;
36322861Smckusick 
36422861Smckusick p->entryname = entry;
36522861Smckusick p->arglist = args;
36622861Smckusick p->entrylabel = newlabel();
36722861Smckusick p->enamep = q;
36822861Smckusick 
36922861Smckusick if(class == CLENTRY)
37022861Smckusick 	{
37122861Smckusick 	class = CLPROC;
37222861Smckusick 	if(proctype == TYSUBR)
37322861Smckusick 		type = TYSUBR;
37422861Smckusick 	}
37522861Smckusick 
37622861Smckusick q->vclass = class;
37722861Smckusick q->vprocclass = PTHISPROC;
37822861Smckusick settype(q, type, (int) length);
37922861Smckusick /* hold all initial entry points till end of declarations */
38022861Smckusick if(parstate >= INDATA) {
38122861Smckusick 	doentry(p);
38222861Smckusick }
38322861Smckusick #ifdef SDB
38422861Smckusick 	if(sdbflag)
38522861Smckusick 	{ /* may need to preserve CLENTRY here */
38622861Smckusick 	entrystab(p,class);
38722861Smckusick 	}
38822861Smckusick #endif
38922861Smckusick }
39022861Smckusick 
39122861Smckusick /* generate epilogs */
39222861Smckusick 
epicode()39322861Smckusick LOCAL epicode()
39422861Smckusick {
39522861Smckusick register int i;
39622861Smckusick 
39722861Smckusick if(procclass==CLPROC)
39822861Smckusick 	{
39922861Smckusick 	if(proctype==TYSUBR)
40022861Smckusick 		{
40122861Smckusick 		putlabel(ret0label);
40222861Smckusick 		if(substars)
40322861Smckusick 			putforce(TYINT, ICON(0) );
40422861Smckusick 		putlabel(retlabel);
40522861Smckusick 		goret(TYSUBR);
40622861Smckusick 		}
40722861Smckusick 	else	{
40822861Smckusick 		putlabel(retlabel);
40922861Smckusick 		if(multitype)
41022861Smckusick 			{
41122861Smckusick 			typeaddr = autovar(1, TYADDR, PNULL);
41222861Smckusick 			putbranch( cpexpr(typeaddr) );
41322861Smckusick 			for(i = 0; i < NTYPES ; ++i)
41422861Smckusick 				if(rtvlabel[i] != 0)
41522861Smckusick 					{
41622861Smckusick 					putlabel(rtvlabel[i]);
41722861Smckusick 					retval(i);
41822861Smckusick 					}
41922861Smckusick 			}
42022861Smckusick 		else
42122861Smckusick 			retval(proctype);
42222861Smckusick 		}
42322861Smckusick 	}
42422861Smckusick 
42522861Smckusick else if(procclass != CLBLOCK)
42622861Smckusick 	{
42722861Smckusick 	putlabel(retlabel);
42822861Smckusick 	goret(TYSUBR);
42922861Smckusick 	}
43022861Smckusick }
43122861Smckusick 
43222861Smckusick 
43322861Smckusick /* generate code to return value of type  t */
43422861Smckusick 
retval(t)43522861Smckusick LOCAL retval(t)
43622861Smckusick register int t;
43722861Smckusick {
43822861Smckusick register Addrp p;
43922861Smckusick 
44022861Smckusick switch(t)
44122861Smckusick 	{
44222861Smckusick 	case TYCHAR:
44322861Smckusick 	case TYCOMPLEX:
44422861Smckusick 	case TYDCOMPLEX:
44522861Smckusick 		break;
44622861Smckusick 
44722861Smckusick 	case TYLOGICAL:
44822861Smckusick 		t = tylogical;
44922861Smckusick 	case TYADDR:
45022861Smckusick 	case TYSHORT:
45122861Smckusick 	case TYLONG:
45222861Smckusick 		p = (Addrp) cpexpr(retslot);
45322861Smckusick 		p->vtype = t;
45422861Smckusick 		putforce(t, p);
45522861Smckusick 		break;
45622861Smckusick 
45722861Smckusick 	case TYREAL:
45822861Smckusick 	case TYDREAL:
45922861Smckusick 		p = (Addrp) cpexpr(retslot);
46022861Smckusick 		p->vtype = t;
46122861Smckusick 		putforce(t, p);
46222861Smckusick 		break;
46322861Smckusick 
46423477Smckusick 	case TYERROR:
46523477Smckusick 		return;		/* someone else already complained */
46623477Smckusick 
46722861Smckusick 	default:
46822861Smckusick 		badtype("retval", t);
46922861Smckusick 	}
47022861Smckusick goret(t);
47122861Smckusick }
47222861Smckusick 
47322861Smckusick 
47422861Smckusick /* Allocate extra argument array if needed. Generate prologs. */
47522861Smckusick 
procode()47622861Smckusick LOCAL procode()
47722861Smckusick {
47822861Smckusick register struct Entrypoint *p;
47922861Smckusick Addrp argvec;
48022861Smckusick 
48122861Smckusick #if TARGET==GCOS
48222861Smckusick 	argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
48322861Smckusick #else
48422861Smckusick 	if(lastargslot>0 && nentry>1)
48522861Smckusick #if TARGET == VAX
48622861Smckusick 		argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL);
48722861Smckusick #else
48822861Smckusick 		argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
48922861Smckusick #endif
49022861Smckusick 	else
49122861Smckusick 		argvec = NULL;
49222861Smckusick #endif
49322861Smckusick 
49422861Smckusick 
49522861Smckusick #if TARGET == PDP11
49622861Smckusick 	/* for the optimizer */
49722861Smckusick 	if(fudgelabel)
49822861Smckusick 		putlabel(fudgelabel);
49922861Smckusick #endif
50022861Smckusick 
50122861Smckusick for(p = entries ; p ; p = p->entnextp)
50222861Smckusick 	prolog(p, argvec);
50322861Smckusick 
50422861Smckusick #if FAMILY == PCC
50522861Smckusick 	putrbrack(procno);
50622861Smckusick #endif
50722861Smckusick 
50822861Smckusick prendproc();
50922861Smckusick }
51022861Smckusick 
51122861Smckusick 
51222861Smckusick /*
51325744Sdonn  * manipulate argument lists (allocate argument slot positions)
51422861Smckusick  * keep track of return types and labels
51522861Smckusick  */
51622861Smckusick 
doentry(ep)51722861Smckusick LOCAL doentry(ep)
51822861Smckusick struct Entrypoint *ep;
51922861Smckusick {
52022861Smckusick register int type;
52122861Smckusick register Namep np;
52222861Smckusick chainp p;
52322861Smckusick register Namep q;
52422861Smckusick Addrp mkarg();
52522861Smckusick 
52622861Smckusick ++nentry;
52722861Smckusick if(procclass == CLMAIN)
52822861Smckusick 	{
52922861Smckusick 	if (optimflag)
53022861Smckusick 		optbuff (SKLABEL, 0, ep->entrylabel, 0);
53122861Smckusick 	else
53222861Smckusick 		putlabel(ep->entrylabel);
53322861Smckusick 	return;
53422861Smckusick 	}
53522861Smckusick else if(procclass == CLBLOCK)
53622861Smckusick 	return;
53722861Smckusick 
53822861Smckusick impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) );
53922861Smckusick type = np->vtype;
54022861Smckusick if(proctype == TYUNKNOWN)
54122861Smckusick 	if( (proctype = type) == TYCHAR)
54233257Sbostic 		procleng = (np->vleng ? np->vleng->constblock.constant.ci : (ftnint) (-1));
54322861Smckusick 
54422861Smckusick if(proctype == TYCHAR)
54522861Smckusick 	{
54622861Smckusick 	if(type != TYCHAR)
54722861Smckusick 		err("noncharacter entry of character function");
54833257Sbostic 	else if( (np->vleng ? np->vleng->constblock.constant.ci : (ftnint) (-1)) != procleng)
54922861Smckusick 		err("mismatched character entry lengths");
55022861Smckusick 	}
55122861Smckusick else if(type == TYCHAR)
55222861Smckusick 	err("character entry of noncharacter function");
55322861Smckusick else if(type != proctype)
55422861Smckusick 	multitype = YES;
55522861Smckusick if(rtvlabel[type] == 0)
55622861Smckusick 	rtvlabel[type] = newlabel();
55722861Smckusick ep->typelabel = rtvlabel[type];
55822861Smckusick 
55922861Smckusick if(type == TYCHAR)
56022861Smckusick 	{
56122861Smckusick 	if(chslot < 0)
56222861Smckusick 		{
56322861Smckusick 		chslot = nextarg(TYADDR);
56422861Smckusick 		chlgslot = nextarg(TYLENG);
56522861Smckusick 		}
56622861Smckusick 	np->vstg = STGARG;
56722861Smckusick 	np->vardesc.varno = chslot;
56822861Smckusick 	if(procleng < 0)
56922861Smckusick 		np->vleng = (expptr) mkarg(TYLENG, chlgslot);
57022861Smckusick 	}
57122861Smckusick else if( ISCOMPLEX(type) )
57222861Smckusick 	{
57322861Smckusick 	np->vstg = STGARG;
57422861Smckusick 	if(cxslot < 0)
57522861Smckusick 		cxslot = nextarg(TYADDR);
57622861Smckusick 	np->vardesc.varno = cxslot;
57722861Smckusick 	}
57822861Smckusick else if(type != TYSUBR)
57922861Smckusick 	{
58022861Smckusick 	if(retslot == NULL)
58122861Smckusick 		retslot = autovar(1, TYDREAL, PNULL);
58222861Smckusick 	np->vstg = STGAUTO;
58333257Sbostic 	np->voffset = retslot->memoffset->constblock.constant.ci;
58422861Smckusick 	}
58522861Smckusick 
58622861Smckusick for(p = ep->arglist ; p ; p = p->nextp)
58722861Smckusick 	if(! (( q = (Namep) (p->datap) )->vdcldone) )
58822861Smckusick 		q->vardesc.varno = nextarg(TYADDR);
58922861Smckusick 
59022861Smckusick for(p = ep->arglist ; p ; p = p->nextp)
59122861Smckusick 	if(! (( q = (Namep) (p->datap) )->vdcldone) )
59222861Smckusick 		{
59325744Sdonn 		if(q->vclass == CLPROC && q->vtype == TYUNKNOWN)
59425744Sdonn 			continue;
59522861Smckusick 		impldcl(q);
59622861Smckusick 		if(q->vtype == TYCHAR)
59722861Smckusick 			{
59822861Smckusick 			if(q->vleng == NULL)	/* character*(*) */
59922861Smckusick 				q->vleng = (expptr)
60022861Smckusick 						mkarg(TYLENG, nextarg(TYLENG) );
60122861Smckusick 			else if(nentry == 1)
60222861Smckusick 				nextarg(TYLENG);
60322861Smckusick 			}
60422861Smckusick 		else if(q->vclass==CLPROC && nentry==1)
60522861Smckusick 			nextarg(TYLENG) ;
60622861Smckusick 		}
60722861Smckusick 
60822861Smckusick if (optimflag)
60922861Smckusick 	optbuff (SKLABEL, 0, ep->entrylabel, 0);
61022861Smckusick else
61122861Smckusick 	putlabel(ep->entrylabel);
61222861Smckusick }
61322861Smckusick 
61422861Smckusick 
61522861Smckusick 
nextarg(type)61622861Smckusick LOCAL nextarg(type)
61722861Smckusick int type;
61822861Smckusick {
61922861Smckusick int k;
62022861Smckusick k = lastargslot;
62122861Smckusick lastargslot += typesize[type];
62222861Smckusick return(k);
62322861Smckusick }
62422861Smckusick 
62522861Smckusick /* generate variable references */
62622861Smckusick 
dobss()62722861Smckusick LOCAL dobss()
62822861Smckusick {
62922861Smckusick register struct Hashentry *p;
63022861Smckusick register Namep q;
63122861Smckusick register int i;
63222861Smckusick int align;
63322861Smckusick ftnint leng, iarrl;
63422861Smckusick char *memname();
63522861Smckusick int qstg, qclass, qtype;
63622861Smckusick 
63722861Smckusick pruse(asmfile, USEBSS);
63822861Smckusick varsizes = NULL;
63922861Smckusick 
64022861Smckusick for(p = hashtab ; p<lasthash ; ++p)
64122861Smckusick     if(q = p->varp)
64222861Smckusick 	{
64322861Smckusick 	qstg = q->vstg;
64422861Smckusick 	qtype = q->vtype;
64522861Smckusick 	qclass = q->vclass;
64622861Smckusick 
64722861Smckusick 	if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
64822861Smckusick 	    (qclass==CLVAR && qstg==STGUNKNOWN) )
64922861Smckusick 		warn1("local variable %s never used", varstr(VL,q->varname) );
65022861Smckusick 	else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG)
65122861Smckusick 		mkext(varunder(VL, q->varname)) ->extstg = STGEXT;
65222861Smckusick 
65322861Smckusick 	if (qclass == CLVAR && qstg == STGBSS)
65422861Smckusick 	  {
65522861Smckusick 	    if (SMALLVAR(q->varsize))
65622861Smckusick 	      {
65722861Smckusick 		enlist(q->varsize, q, NULL);
65822861Smckusick 		q->inlcomm = NO;
65922861Smckusick 	      }
66022861Smckusick 	    else
66122861Smckusick 	      {
66222861Smckusick 		if (q->init == NO)
66322861Smckusick 		  {
66422861Smckusick 		    preven(ALIDOUBLE);
66522861Smckusick 		    prlocvar(memname(qstg, q->vardesc.varno), q->varsize);
66622861Smckusick 		    q->inlcomm = YES;
66722861Smckusick 		  }
66822861Smckusick 		else
66922861Smckusick 		  prlocdata(memname(qstg, q->vardesc.varno), q->varsize,
67022861Smckusick 			    q->vtype, q->initoffset, &(q->inlcomm));
67122861Smckusick 	      }
67222861Smckusick 	  }
67322861Smckusick 	else if(qclass==CLVAR && qstg!=STGARG)
67422861Smckusick 		{
67522861Smckusick 		if(q->vdim && !ISICON(q->vdim->nelt) )
67622861Smckusick 			dclerr("adjustable dimension on non-argument", q);
67722861Smckusick 		if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng)))
67822861Smckusick 			dclerr("adjustable leng on nonargument", q);
67922861Smckusick 		}
68022861Smckusick 
68122861Smckusick 	chkdim(q);
68222861Smckusick 	}
68322861Smckusick 
68422861Smckusick for (i = 0 ; i < nequiv ; ++i)
68522861Smckusick   if ( (leng = eqvclass[i].eqvleng) != 0 )
68622861Smckusick     {
68722861Smckusick       if (SMALLVAR(leng))
68822861Smckusick 	enlist(leng, NULL, eqvclass + i);
68922861Smckusick       else if (eqvclass[i].init == NO)
69022861Smckusick 	{
69122861Smckusick 	  preven(ALIDOUBLE);
69222861Smckusick 	  prlocvar(memname(STGEQUIV, i), leng);
69322861Smckusick 	  eqvclass[i].inlcomm = YES;
69422861Smckusick 	}
69522861Smckusick       else
69622861Smckusick 	prlocdata(memname(STGEQUIV, i), leng, TYDREAL,
69722861Smckusick 		  eqvclass[i].initoffset, &(eqvclass[i].inlcomm));
69822861Smckusick     }
69922861Smckusick 
70022861Smckusick   outlocvars();
70122861Smckusick #ifdef SDB
70222861Smckusick     if(sdbflag) {
70325816Sdonn       register struct Entrypoint *ep;
70425816Sdonn       register chainp cp;
70525816Sdonn 
70625816Sdonn       for (ep = entries; ep; ep = ep->entnextp)
70725816Sdonn 	for (cp = ep->arglist ; cp ; cp = cp->nextp)
70825816Sdonn 	  if ((q = (Namep) cp->datap) && q->vstg == STGARG) {
70925816Sdonn 	    q->vdcldone = YES;
71025816Sdonn 	    namestab(q);
71125816Sdonn 	  }
71225816Sdonn       for (p = hashtab ; p<lasthash ; ++p) if(q = p->varp) {
71325816Sdonn 	if (q->vtype == TYUNKNOWN || q->vtype == TYERROR)
71425816Sdonn 	  continue;
71525816Sdonn 	qstg = q->vstg;
71625816Sdonn 	qclass = q->vclass;
71725816Sdonn 	q->vdcldone = YES;
71825816Sdonn 	if ( ONEOF(qclass, M(CLVAR)|M(CLPARAM)|M(CLPROC)) ) {
71925816Sdonn 	  if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) )
72025816Sdonn 	    namestab(q);
72125816Sdonn 	}
72222861Smckusick       }
72322861Smckusick     }
72422861Smckusick #endif
72522861Smckusick 
72622861Smckusick   close(vdatafile);
72722861Smckusick   close(vchkfile);
72822861Smckusick   unlink(vdatafname);
72922861Smckusick   unlink(vchkfname);
73022861Smckusick   vdatahwm = 0;
73122861Smckusick }
73222861Smckusick 
73322861Smckusick 
73422861Smckusick 
donmlist()73522861Smckusick donmlist()
73622861Smckusick {
73722861Smckusick register struct Hashentry *p;
73822861Smckusick register Namep q;
73922861Smckusick 
74022861Smckusick pruse(asmfile, USEINIT);
74122861Smckusick 
74222861Smckusick for(p=hashtab; p<lasthash; ++p)
74322861Smckusick 	if( (q = p->varp) && q->vclass==CLNAMELIST)
74422861Smckusick 		namelist(q);
74522861Smckusick }
74622861Smckusick 
74722861Smckusick 
doext()74822861Smckusick doext()
74922861Smckusick {
75022861Smckusick struct Extsym *p;
75122861Smckusick 
75222861Smckusick for(p = extsymtab ; p<nextext ; ++p)
75322861Smckusick 	prext(p);
75422861Smckusick }
75522861Smckusick 
75622861Smckusick 
75722861Smckusick 
75822861Smckusick 
iarrlen(q)75922861Smckusick ftnint iarrlen(q)
76022861Smckusick register Namep q;
76122861Smckusick {
76222861Smckusick ftnint leng;
76322861Smckusick 
76422861Smckusick leng = typesize[q->vtype];
76522861Smckusick if(leng <= 0)
76622861Smckusick 	return(-1);
76722861Smckusick if(q->vdim)
76822861Smckusick 	if( ISICON(q->vdim->nelt) )
76933257Sbostic 		leng *= q->vdim->nelt->constblock.constant.ci;
77022861Smckusick 	else	return(-1);
77122861Smckusick if(q->vleng)
77222861Smckusick 	if( ISICON(q->vleng) )
77333257Sbostic 		leng *= q->vleng->constblock.constant.ci;
77422861Smckusick 	else 	return(-1);
77522861Smckusick return(leng);
77622861Smckusick }
77722861Smckusick 
77822861Smckusick /* This routine creates a static block representing the namelist.
77922861Smckusick    An equivalent declaration of the structure produced is:
78022861Smckusick 	struct namelist
78122861Smckusick 		{
78222861Smckusick 		char namelistname[16];
78322861Smckusick 		struct namelistentry
78422861Smckusick 			{
78524484Sdonn 			char varname[16]; #  16 plus null padding -> 20
78622861Smckusick 			char *varaddr;
78724484Sdonn 			short int type;
78824484Sdonn 			short int len;	# length of type
78922861Smckusick 			struct dimensions *dimp; # null means scalar
79022861Smckusick 			} names[];
79122861Smckusick 		};
79222861Smckusick 
79322861Smckusick 	struct dimensions
79422861Smckusick 		{
79522861Smckusick 		int numberofdimensions;
79622861Smckusick 		int numberofelements
79722861Smckusick 		int baseoffset;
79822861Smckusick 		int span[numberofdimensions];
79922861Smckusick 		};
80022861Smckusick    where the namelistentry list terminates with a null varname
80122861Smckusick    If dimp is not null, then the corner element of the array is at
80222861Smckusick    varaddr.  However,  the element with subscripts (i1,...,in) is at
80322861Smckusick    varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...)
80422861Smckusick */
80522861Smckusick 
namelist(np)80622861Smckusick namelist(np)
80722861Smckusick Namep np;
80822861Smckusick {
80922861Smckusick register chainp q;
81022861Smckusick register Namep v;
81122861Smckusick register struct Dimblock *dp;
81222861Smckusick char *memname();
81322861Smckusick int type, dimno, dimoffset;
81422861Smckusick flag bad;
81522861Smckusick 
81622861Smckusick 
81722861Smckusick preven(ALILONG);
81822861Smckusick fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno));
81922861Smckusick putstr(asmfile, varstr(VL, np->varname), 16);
82022861Smckusick dimno = ++lastvarno;
82122861Smckusick dimoffset = 0;
82222861Smckusick bad = NO;
82322861Smckusick 
82422861Smckusick for(q = np->varxptr.namelist ; q ; q = q->nextp)
82522861Smckusick 	{
82622861Smckusick 	vardcl( v = (Namep) (q->datap) );
82722861Smckusick 	type = v->vtype;
82822861Smckusick 	if( ONEOF(v->vstg, MSKSTATIC) )
82922861Smckusick 		{
83022861Smckusick 		preven(ALILONG);
83122861Smckusick 		putstr(asmfile, varstr(VL,v->varname), 16);
83222861Smckusick 		praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset);
83324484Sdonn 		prconi(asmfile, TYSHORT, type );
83424484Sdonn 		prconi(asmfile, TYSHORT,
83522861Smckusick 			type==TYCHAR ?
83633257Sbostic 			    (v->vleng->constblock.constant.ci) :
83724484Sdonn 					(ftnint) typesize[type]);
83822861Smckusick 		if(v->vdim)
83922861Smckusick 			{
84022861Smckusick 			praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset);
84124484Sdonn 			dimoffset += (3 + v->vdim->ndim) * SZINT;
84222861Smckusick 			}
84322861Smckusick 		else
84422861Smckusick 			praddr(asmfile, STGNULL,0,(ftnint) 0);
84522861Smckusick 		}
84622861Smckusick 	else
84722861Smckusick 		{
84822861Smckusick 		dclerr("may not appear in namelist", v);
84922861Smckusick 		bad = YES;
85022861Smckusick 		}
85122861Smckusick 	}
85222861Smckusick 
85322861Smckusick if(bad)
85422861Smckusick 	return;
85522861Smckusick 
85622861Smckusick putstr(asmfile, "", 16);
85722861Smckusick 
85822861Smckusick if(dimoffset > 0)
85922861Smckusick 	{
86022861Smckusick 	fprintf(asmfile, LABELFMT, memname(STGINIT,dimno));
86122861Smckusick 	for(q = np->varxptr.namelist ; q ; q = q->nextp)
86222861Smckusick 		if(dp = q->datap->nameblock.vdim)
86322861Smckusick 			{
86422861Smckusick 			int i;
86522861Smckusick 			prconi(asmfile, TYINT, (ftnint) (dp->ndim) );
86622861Smckusick 			prconi(asmfile, TYINT,
86733257Sbostic 				(ftnint) (dp->nelt->constblock.constant.ci) );
86822861Smckusick 			prconi(asmfile, TYINT,
86933257Sbostic 				(ftnint) (dp->baseoffset->constblock.constant.ci));
87022861Smckusick 			for(i=0; i<dp->ndim ; ++i)
87122861Smckusick 				prconi(asmfile, TYINT,
87233257Sbostic 					dp->dims[i].dimsize->constblock.constant.ci);
87322861Smckusick 			}
87422861Smckusick 	}
87522861Smckusick 
87622861Smckusick }
87722861Smckusick 
docommon()87822861Smckusick LOCAL docommon()
87922861Smckusick {
88022861Smckusick register struct Extsym *p;
88122861Smckusick register chainp q;
88222861Smckusick struct Dimblock *t;
88322861Smckusick expptr neltp;
88422861Smckusick register Namep v;
88522861Smckusick ftnint size;
88622861Smckusick int type;
88722861Smckusick 
88822861Smckusick for(p = extsymtab ; p<nextext ; ++p)
88922861Smckusick 	if(p->extstg==STGCOMMON)
89022861Smckusick 		{
89122861Smckusick #ifdef SDB
89222861Smckusick 		if(sdbflag)
89322861Smckusick 			prstab(varstr(XL,p->extname), N_BCOMM, 0, 0);
89422861Smckusick #endif
89522861Smckusick 		for(q = p->extp ; q ; q = q->nextp)
89622861Smckusick 			{
89722861Smckusick 			v = (Namep) (q->datap);
89822861Smckusick 			if(v->vdcldone == NO)
89922861Smckusick 				vardcl(v);
90022861Smckusick 			type = v->vtype;
90122861Smckusick 			if(p->extleng % typealign[type] != 0)
90222861Smckusick 				{
90322861Smckusick 				dclerr("common alignment", v);
90422861Smckusick 				p->extleng = roundup(p->extleng, typealign[type]);
90522861Smckusick 				}
90622861Smckusick 			v->voffset = p->extleng;
90722861Smckusick 			v->vardesc.varno = p - extsymtab;
90822861Smckusick 			if(type == TYCHAR)
90933257Sbostic 				size = v->vleng->constblock.constant.ci;
91022861Smckusick 			else	size = typesize[type];
91122861Smckusick 			if(t = v->vdim)
91222861Smckusick 				if( (neltp = t->nelt) && ISCONST(neltp) )
91333257Sbostic 					size *= neltp->constblock.constant.ci;
91422861Smckusick 				else
91522861Smckusick 					dclerr("adjustable array in common", v);
91622861Smckusick 			p->extleng += size;
91722861Smckusick #ifdef SDB
91822861Smckusick 			if(sdbflag)
91922861Smckusick 				{
92022861Smckusick 				namestab(v);
92122861Smckusick 				}
92222861Smckusick #endif
92322861Smckusick 			}
92422861Smckusick 
92522861Smckusick 		frchain( &(p->extp) );
92622861Smckusick #ifdef SDB
92722861Smckusick 		if(sdbflag)
92822861Smckusick 			prstab(varstr(XL,p->extname), N_ECOMM, 0, 0);
92922861Smckusick #endif
93022861Smckusick 		}
93122861Smckusick }
93222861Smckusick 
93322861Smckusick 
93422861Smckusick 
93522861Smckusick 
93622861Smckusick 
docomleng()93722861Smckusick LOCAL docomleng()
93822861Smckusick {
93922861Smckusick register struct Extsym *p;
94022861Smckusick 
94122861Smckusick for(p = extsymtab ; p < nextext ; ++p)
94222861Smckusick 	if(p->extstg == STGCOMMON)
94322861Smckusick 		{
94422861Smckusick 		if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
94522861Smckusick 		    && !eqn(XL,"_BLNK__ ",p->extname) )
94622861Smckusick 			warn1("incompatible lengths for common block %s",
94722861Smckusick 				nounder(XL, p->extname) );
94822861Smckusick 		if(p->maxleng < p->extleng)
94922861Smckusick 			p->maxleng = p->extleng;
95022861Smckusick 		p->extleng = 0;
95122861Smckusick 	}
95222861Smckusick }
95322861Smckusick 
95422861Smckusick 
95522861Smckusick 
95622861Smckusick 
95722861Smckusick /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
95822861Smckusick 
95922861Smckusick /*  frees a temporary block  */
96022861Smckusick 
frtemp(p)96122861Smckusick frtemp(p)
96222861Smckusick Tempp p;
96322861Smckusick {
96422861Smckusick Addrp t;
96522861Smckusick 
96622861Smckusick if (optimflag)
96722861Smckusick 	{
96822861Smckusick 	if (p->tag != TTEMP)
96922861Smckusick 		badtag ("frtemp",p->tag);
97022861Smckusick 	t = p->memalloc;
97122861Smckusick 	}
97222861Smckusick else
97322861Smckusick 	t = (Addrp) p;
97422861Smckusick 
97522861Smckusick /* restore clobbered character string lengths */
97622861Smckusick if(t->vtype==TYCHAR && t->varleng!=0)
97722861Smckusick 	{
97822861Smckusick 	frexpr(t->vleng);
97922861Smckusick 	t->vleng = ICON(t->varleng);
98022861Smckusick 	}
98122861Smckusick 
98222861Smckusick /* put block on chain of temps to be reclaimed */
98322861Smckusick holdtemps = mkchain(t, holdtemps);
98422861Smckusick }
98522861Smckusick 
98622861Smckusick 
98722861Smckusick 
98822861Smckusick /* allocate an automatic variable slot */
98922861Smckusick 
autovar(nelt,t,lengp)99022861Smckusick Addrp autovar(nelt, t, lengp)
99122861Smckusick register int nelt, t;
99222861Smckusick expptr lengp;
99322861Smckusick {
99422861Smckusick ftnint leng;
99522861Smckusick register Addrp q;
99622861Smckusick 
99722861Smckusick if(lengp)
99822861Smckusick 	if( ISICON(lengp) )
99933257Sbostic 		leng = lengp->constblock.constant.ci;
100022861Smckusick 	else	{
100122861Smckusick 		fatal("automatic variable of nonconstant length");
100222861Smckusick 		}
100322861Smckusick else
100422861Smckusick 	leng = typesize[t];
100522861Smckusick autoleng = roundup( autoleng, typealign[t]);
100622861Smckusick 
100722861Smckusick q = ALLOC(Addrblock);
100822861Smckusick q->tag = TADDR;
100922861Smckusick q->vtype = t;
101022861Smckusick if(lengp)
101122861Smckusick 	{
101222861Smckusick 	q->vleng = ICON(leng);
101322861Smckusick 	q->varleng = leng;
101422861Smckusick 	}
101522861Smckusick q->vstg = STGAUTO;
101622861Smckusick q->memno = newlabel();
101722861Smckusick q->ntempelt = nelt;
101822861Smckusick #if TARGET==PDP11 || TARGET==VAX
101922861Smckusick 	/* stack grows downward */
102022861Smckusick 	autoleng += nelt*leng;
102122861Smckusick 	q->memoffset = ICON( - autoleng );
102222861Smckusick #else
102322861Smckusick 	q->memoffset = ICON( autoleng );
102422861Smckusick 	autoleng += nelt*leng;
102522861Smckusick #endif
102622861Smckusick 
102722861Smckusick return(q);
102822861Smckusick }
102922861Smckusick 
103022861Smckusick 
103122861Smckusick 
103222861Smckusick /*
103322861Smckusick  *  create a temporary block (TTEMP) when optimizing,
103422861Smckusick  *  an ordinary TADDR block when not optimizing
103522861Smckusick  */
103622861Smckusick 
mktmpn(nelt,type,lengp)103722861Smckusick Tempp mktmpn(nelt, type, lengp)
103822861Smckusick int nelt;
103922861Smckusick register int type;
104022861Smckusick expptr lengp;
104122861Smckusick {
104222861Smckusick ftnint leng;
104322861Smckusick chainp p, oldp;
104422861Smckusick register Tempp q;
104522861Smckusick Addrp altemp;
104622861Smckusick 
104722861Smckusick if (! optimflag)
104822861Smckusick 	return ( (Tempp) mkaltmpn(nelt,type,lengp) );
104922861Smckusick if(type==TYUNKNOWN || type==TYERROR)
105022861Smckusick 	badtype("mktmpn", type);
105122861Smckusick 
105222861Smckusick if(type==TYCHAR)
105322861Smckusick 	if( ISICON(lengp) )
105433257Sbostic 		leng = lengp->constblock.constant.ci;
105522861Smckusick 	else	{
105622861Smckusick 		err("adjustable length");
105722861Smckusick 		return( (Tempp) errnode() );
105822861Smckusick 		}
105922861Smckusick else
106022861Smckusick 	leng = typesize[type];
106122861Smckusick 
106222861Smckusick q = ALLOC(Tempblock);
106322861Smckusick q->tag = TTEMP;
106422861Smckusick q->vtype = type;
106522861Smckusick if(type == TYCHAR)
106622861Smckusick 	{
106722861Smckusick 	q->vleng = ICON(leng);
106822861Smckusick 	q->varleng = leng;
106922861Smckusick 	}
107022861Smckusick 
107122861Smckusick altemp = ALLOC(Addrblock);
107222861Smckusick altemp->tag = TADDR;
107322861Smckusick altemp->vstg = STGUNKNOWN;
107422861Smckusick q->memalloc = altemp;
107522861Smckusick 
107622861Smckusick q->ntempelt = nelt;
107722861Smckusick q->istemp = YES;
107822861Smckusick return(q);
107922861Smckusick }
108022861Smckusick 
108122861Smckusick 
108222861Smckusick 
mktemp(type,lengp)108322861Smckusick Addrp mktemp(type, lengp)
108422861Smckusick int type;
108522861Smckusick expptr lengp;
108622861Smckusick {
108722861Smckusick return( (Addrp) mktmpn(1,type,lengp) );
108822861Smckusick }
108922861Smckusick 
109022861Smckusick 
109122861Smckusick 
109222861Smckusick /*  allocate a temporary location for the given temporary block;
109322861Smckusick     if already allocated, return its location  */
109422861Smckusick 
altmpn(tp)109522861Smckusick Addrp altmpn(tp)
109622861Smckusick Tempp tp;
109722861Smckusick 
109822861Smckusick {
109922861Smckusick Addrp t, q;
110022861Smckusick 
110122861Smckusick if (tp->tag != TTEMP)
110222861Smckusick 	badtag ("altmpn",tp->tag);
110322861Smckusick 
110422861Smckusick t = tp->memalloc;
110522861Smckusick if (t->vstg != STGUNKNOWN)
110622861Smckusick 	{
110722861Smckusick 	if (tp->vtype == TYCHAR)
110822861Smckusick 		{
110922861Smckusick 		/*
111022861Smckusick 		 * Unformatted I/O parameters are treated like character
111122861Smckusick 		 *	strings (sigh) -- propagate type and length.
111222861Smckusick 		 */
111322861Smckusick 		t = (Addrp) cpexpr(t);
111422861Smckusick 		t->vtype = tp->vtype;
111522861Smckusick 		t->vleng = tp->vleng;
111622861Smckusick 		t->varleng = tp->varleng;
111722861Smckusick 		}
111822861Smckusick 	return (t);
111922861Smckusick 	}
112022861Smckusick 
112122861Smckusick q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng);
112222861Smckusick cpn (sizeof(struct Addrblock), (char*)q, (char*)t);
112322861Smckusick free ( (charptr) q);
112422861Smckusick return(t);
112522861Smckusick }
112622861Smckusick 
112722861Smckusick 
112822861Smckusick 
112922861Smckusick /*  create and allocate space immediately for a temporary  */
113022861Smckusick 
mkaltemp(type,lengp)113122861Smckusick Addrp mkaltemp(type,lengp)
113222861Smckusick int type;
113322861Smckusick expptr lengp;
113422861Smckusick {
113522861Smckusick return (mkaltmpn(1,type,lengp));
113622861Smckusick }
113722861Smckusick 
113822861Smckusick 
113922861Smckusick 
mkaltmpn(nelt,type,lengp)114022861Smckusick Addrp mkaltmpn(nelt,type,lengp)
114122861Smckusick int nelt;
114222861Smckusick register int type;
114322861Smckusick expptr lengp;
114422861Smckusick {
114522861Smckusick ftnint leng;
114622861Smckusick chainp p, oldp;
114722861Smckusick register Addrp q;
114822861Smckusick 
114922861Smckusick if(type==TYUNKNOWN || type==TYERROR)
115022861Smckusick 	badtype("mkaltmpn", type);
115122861Smckusick 
115222861Smckusick if(type==TYCHAR)
115322861Smckusick 	if( ISICON(lengp) )
115433257Sbostic 		leng = lengp->constblock.constant.ci;
115522861Smckusick 	else	{
115622861Smckusick 		err("adjustable length");
115722861Smckusick 		return( (Addrp) errnode() );
115822861Smckusick 		}
115922861Smckusick 
116022861Smckusick /*
116122861Smckusick  * if a temporary of appropriate shape is on the templist,
116222861Smckusick  * remove it from the list and return it
116322861Smckusick  */
116422861Smckusick 
116522861Smckusick #ifdef notdef
116622861Smckusick /*
116722861Smckusick  * This code is broken until SKFRTEMP slots can be processed in putopt()
116822861Smckusick  *	instead of in optimize() -- all kinds of things in putpcc.c can
116922861Smckusick  *	bomb because of this.  Sigh.
117022861Smckusick  */
117122861Smckusick for(oldp=CHNULL, p=templist  ;  p  ;  oldp=p, p=p->nextp)
117222861Smckusick 	{
117322861Smckusick 	q = (Addrp) (p->datap);
117422861Smckusick 	if(q->vtype==type && q->ntempelt==nelt &&
117533257Sbostic 	    (type!=TYCHAR || q->vleng->constblock.constant.ci==leng) )
117622861Smckusick 		{
117722861Smckusick 		if(oldp)
117822861Smckusick 			oldp->nextp = p->nextp;
117922861Smckusick 		else
118022861Smckusick 			templist = p->nextp;
118122861Smckusick 		free( (charptr) p);
118222861Smckusick 
118322861Smckusick 		if (debugflag[14])
118422861Smckusick 			fprintf(diagfile,"mkaltmpn reusing offset %d\n",
118533257Sbostic 				q->memoffset->constblock.constant.ci);
118622861Smckusick 		return(q);
118722861Smckusick 		}
118822861Smckusick 	}
118922861Smckusick #endif notdef
119022861Smckusick q = autovar(nelt, type, lengp);
119122861Smckusick q->istemp = YES;
119222861Smckusick 
119322861Smckusick if (debugflag[14])
119422861Smckusick 	fprintf(diagfile,"mkaltmpn new offset %d\n",
119533257Sbostic 		q->memoffset->constblock.constant.ci);
119622861Smckusick return(q);
119722861Smckusick }
119822861Smckusick 
119922861Smckusick 
120022861Smckusick 
120122861Smckusick /*  The following routine is a patch which is only needed because the	*/
120222861Smckusick /*  code for processing actual arguments for calls does not allocate	*/
120322861Smckusick /*  the temps it needs before optimization takes place.  A better	*/
120422861Smckusick /*  solution is possible, but I do not have the time to implement it	*/
120522861Smckusick /*  now.								*/
120622861Smckusick /*									*/
120722861Smckusick /*					Robert P. Corbett		*/
120822861Smckusick 
120922861Smckusick Addrp
mkargtemp(type,lengp)121022861Smckusick mkargtemp(type, lengp)
121122861Smckusick int type;
121222861Smckusick expptr lengp;
121322861Smckusick {
121422861Smckusick   ftnint leng;
121522861Smckusick   chainp oldp, p;
121622861Smckusick   Addrp q;
121722861Smckusick 
121822861Smckusick   if (type == TYUNKNOWN || type == TYERROR)
121922861Smckusick     badtype("mkargtemp", type);
122022861Smckusick 
122122861Smckusick   if (type == TYCHAR)
122222861Smckusick     {
122322861Smckusick       if (ISICON(lengp))
122433257Sbostic 	leng = lengp->constblock.constant.ci;
122522861Smckusick       else
122622861Smckusick 	{
122722861Smckusick 	  err("adjustable length");
122822861Smckusick 	  return ((Addrp) errnode());
122922861Smckusick 	}
123022861Smckusick     }
123122861Smckusick 
123222861Smckusick   oldp = CHNULL;
123322861Smckusick   p = argtemplist;
123422861Smckusick 
123522861Smckusick   while (p)
123622861Smckusick     {
123722861Smckusick       q = (Addrp) (p->datap);
123822861Smckusick       if (q->vtype == type
123933257Sbostic 	  && (type != TYCHAR || q->vleng->constblock.constant.ci == leng))
124022861Smckusick 	{
124122861Smckusick 	  if (oldp)
124222861Smckusick 	    oldp->nextp = p->nextp;
124322861Smckusick 	  else
124422861Smckusick 	    argtemplist = p->nextp;
124522861Smckusick 
124622861Smckusick 	  p->nextp = activearglist;
124722861Smckusick 	  activearglist = p;
124822861Smckusick 
124922861Smckusick 	  return ((Addrp) cpexpr(q));
125022861Smckusick 	}
125122861Smckusick 
125222861Smckusick       oldp = p;
125322861Smckusick       p = p->nextp;
125422861Smckusick     }
125522861Smckusick 
125622861Smckusick   q = autovar(1, type, lengp);
125722861Smckusick   activearglist = mkchain(q, activearglist);
125822861Smckusick   return ((Addrp) cpexpr(q));
125922861Smckusick }
126022861Smckusick 
126122861Smckusick /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
126222861Smckusick 
comblock(len,s)126322861Smckusick struct Extsym *comblock(len, s)
126422861Smckusick register int len;
126522861Smckusick register char *s;
126622861Smckusick {
126722861Smckusick struct Extsym *p;
126822861Smckusick 
126922861Smckusick if(len == 0)
127022861Smckusick 	{
127122861Smckusick 	s = BLANKCOMMON;
127222861Smckusick 	len = strlen(s);
127322861Smckusick 	}
127422861Smckusick p = mkext( varunder(len, s) );
127522861Smckusick if(p->extstg == STGUNKNOWN)
127622861Smckusick 	p->extstg = STGCOMMON;
127722861Smckusick else if(p->extstg != STGCOMMON)
127822861Smckusick 	{
127922861Smckusick 	errstr("%s cannot be a common block name", s);
128022861Smckusick 	return(0);
128122861Smckusick 	}
128222861Smckusick 
128322861Smckusick return( p );
128422861Smckusick }
128522861Smckusick 
128622861Smckusick 
128722861Smckusick incomm(c, v)
128822861Smckusick struct Extsym *c;
128922861Smckusick Namep v;
129022861Smckusick {
129122861Smckusick if(v->vstg != STGUNKNOWN)
129222861Smckusick 	dclerr("incompatible common declaration", v);
129322861Smckusick else
129422861Smckusick 	{
129522861Smckusick 	if(c == (struct Extsym *) 0)
129622861Smckusick 		return;		/* Illegal common block name upstream */
129722861Smckusick 	v->vstg = STGCOMMON;
129822861Smckusick 	c->extp = hookup(c->extp, mkchain(v,CHNULL) );
129922861Smckusick 	}
130022861Smckusick }
130122861Smckusick 
130222861Smckusick 
130322861Smckusick 
130422861Smckusick 
settype(v,type,length)130522861Smckusick settype(v, type, length)
130622861Smckusick register Namep  v;
130722861Smckusick register int type;
130822861Smckusick register int length;
130922861Smckusick {
131022861Smckusick if(type == TYUNKNOWN)
131122861Smckusick 	return;
131222861Smckusick 
131322861Smckusick if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
131422861Smckusick 	{
131522861Smckusick 	v->vtype = TYSUBR;
131622861Smckusick 	frexpr(v->vleng);
131722861Smckusick 	}
131822861Smckusick else if(type < 0)	/* storage class set */
131922861Smckusick 	{
132022861Smckusick 	if(v->vstg == STGUNKNOWN)
132122861Smckusick 		v->vstg = - type;
132222861Smckusick 	else if(v->vstg != -type)
132322861Smckusick 		dclerr("incompatible storage declarations", v);
132422861Smckusick 	}
132522861Smckusick else if(v->vtype == TYUNKNOWN)
132622861Smckusick 	{
132725744Sdonn 	if( (v->vtype = lengtype(type, length))==TYCHAR )
132825744Sdonn 		{
132925744Sdonn 		if(length >= 0)
133025744Sdonn 			v->vleng = ICON(length);
133126009Sdonn 		else if(!(v->vstg == STGARG || v->vclass == CLENTRY ||
133226009Sdonn 			  (v->vclass == CLPROC && v->vprocclass == PTHISPROC)))
133326009Sdonn 			{
133426009Sdonn 			dclerr("illegal adjustable length character variable", v);
133526009Sdonn 			v->vleng = ICON(0);
133626009Sdonn 			}
133725744Sdonn 		}
133822861Smckusick 	}
133933257Sbostic else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.constant.ci!=length) )
134022861Smckusick 	dclerr("incompatible type declarations", v);
134122861Smckusick }
134222861Smckusick 
134322861Smckusick 
134422861Smckusick 
134522861Smckusick 
134622861Smckusick 
lengtype(type,length)134722861Smckusick lengtype(type, length)
134822861Smckusick register int type;
134922861Smckusick register int length;
135022861Smckusick {
135122861Smckusick switch(type)
135222861Smckusick 	{
135322861Smckusick 	case TYREAL:
135422861Smckusick 		if(length == 8)
135522861Smckusick 			return(TYDREAL);
135622861Smckusick 		if(length == 4)
135722861Smckusick 			goto ret;
135822861Smckusick 		break;
135922861Smckusick 
136022861Smckusick 	case TYCOMPLEX:
136122861Smckusick 		if(length == 16)
136222861Smckusick 			return(TYDCOMPLEX);
136322861Smckusick 		if(length == 8)
136422861Smckusick 			goto ret;
136522861Smckusick 		break;
136622861Smckusick 
136722861Smckusick 	case TYSHORT:
136822861Smckusick 	case TYDREAL:
136922861Smckusick 	case TYDCOMPLEX:
137022861Smckusick 	case TYCHAR:
137122861Smckusick 	case TYUNKNOWN:
137222861Smckusick 	case TYSUBR:
137322861Smckusick 	case TYERROR:
137422861Smckusick 		goto ret;
137522861Smckusick 
137622861Smckusick 	case TYLOGICAL:
137722861Smckusick 		if(length == typesize[TYLOGICAL])
137822861Smckusick 			goto ret;
137922861Smckusick 		break;
138022861Smckusick 
138122861Smckusick 	case TYLONG:
138222861Smckusick 		if(length == 0)
138322861Smckusick 			return(tyint);
138422861Smckusick 		if(length == 2)
138522861Smckusick 			return(TYSHORT);
138622861Smckusick 		if(length == 4)
138722861Smckusick 			goto ret;
138822861Smckusick 		break;
138922861Smckusick 	default:
139022861Smckusick 		badtype("lengtype", type);
139122861Smckusick 	}
139222861Smckusick 
139322861Smckusick if(length != 0)
139422861Smckusick 	err("incompatible type-length combination");
139522861Smckusick 
139622861Smckusick ret:
139722861Smckusick 	return(type);
139822861Smckusick }
139922861Smckusick 
140022861Smckusick 
140122861Smckusick 
140222861Smckusick 
140322861Smckusick 
setintr(v)140422861Smckusick setintr(v)
140522861Smckusick register Namep  v;
140622861Smckusick {
140722861Smckusick register int k;
140822861Smckusick 
140922861Smckusick if(v->vstg == STGUNKNOWN)
141022861Smckusick 	v->vstg = STGINTR;
141122861Smckusick else if(v->vstg!=STGINTR)
141222861Smckusick 	dclerr("incompatible use of intrinsic function", v);
141322861Smckusick if(v->vclass==CLUNKNOWN)
141422861Smckusick 	v->vclass = CLPROC;
141522861Smckusick if(v->vprocclass == PUNKNOWN)
141622861Smckusick 	v->vprocclass = PINTRINSIC;
141722861Smckusick else if(v->vprocclass != PINTRINSIC)
141822861Smckusick 	dclerr("invalid intrinsic declaration", v);
141922861Smckusick if(k = intrfunct(v->varname))
142022861Smckusick 	v->vardesc.varno = k;
142122861Smckusick else
142222861Smckusick 	dclerr("unknown intrinsic function", v);
142322861Smckusick }
142422861Smckusick 
142522861Smckusick 
142622861Smckusick 
setext(v)142722861Smckusick setext(v)
142822861Smckusick register Namep  v;
142922861Smckusick {
143022861Smckusick if(v->vclass == CLUNKNOWN)
143122861Smckusick 	v->vclass = CLPROC;
143222861Smckusick else if(v->vclass != CLPROC)
143322861Smckusick 	dclerr("conflicting declarations", v);
143422861Smckusick 
143522861Smckusick if(v->vprocclass == PUNKNOWN)
143622861Smckusick 	v->vprocclass = PEXTERNAL;
143722861Smckusick else if(v->vprocclass != PEXTERNAL)
143822861Smckusick 	dclerr("conflicting declarations", v);
143922861Smckusick }
144022861Smckusick 
144122861Smckusick 
144222861Smckusick 
144322861Smckusick 
144422861Smckusick /* create dimensions block for array variable */
144522861Smckusick 
setbound(v,nd,dims)144622861Smckusick setbound(v, nd, dims)
144722861Smckusick register Namep  v;
144822861Smckusick int nd;
144922861Smckusick struct { expptr lb, ub; } dims[ ];
145022861Smckusick {
145122861Smckusick register expptr q, t;
145222861Smckusick register struct Dimblock *p;
145322861Smckusick int i;
145422861Smckusick 
145522861Smckusick if(v->vclass == CLUNKNOWN)
145622861Smckusick 	v->vclass = CLVAR;
145722861Smckusick else if(v->vclass != CLVAR)
145822861Smckusick 	{
145922861Smckusick 	dclerr("only variables may be arrays", v);
146022861Smckusick 	return;
146122861Smckusick 	}
146222861Smckusick if(v->vdim)
146322861Smckusick 	{
146422861Smckusick 	dclerr("redimensioned array", v);
146522861Smckusick 	return;
146622861Smckusick 	}
146722861Smckusick 
146822861Smckusick v->vdim = p = (struct Dimblock *)
146922861Smckusick 		ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) );
147022861Smckusick p->ndim = nd;
147122861Smckusick p->nelt = ICON(1);
147222861Smckusick 
147322861Smckusick for(i=0 ; i<nd ; ++i)
147422861Smckusick 	{
147522861Smckusick #ifdef SDB
147622861Smckusick         if(sdbflag) {
147722861Smckusick /* Save the bounds trees built up by the grammar routines for use in stabs */
147822861Smckusick 
147922861Smckusick 		if(dims[i].lb == NULL) p->dims[i].lb=ICON(1);
148022861Smckusick         	else p->dims[i].lb= (expptr) cpexpr(dims[i].lb);
148122861Smckusick                 if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL;
148222861Smckusick                 else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL);
148322861Smckusick 
148422861Smckusick 		if(dims[i].ub == NULL) p->dims[i].ub=ICON(1);
148522861Smckusick         	else p->dims[i].ub = (expptr) cpexpr(dims[i].ub);
148622861Smckusick                 if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL;
148722861Smckusick                 else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL);
148822861Smckusick 	}
148922861Smckusick #endif
149022861Smckusick 	if( (q = dims[i].ub) == NULL)
149122861Smckusick 		{
149222861Smckusick 		if(i == nd-1)
149322861Smckusick 			{
149422861Smckusick 			frexpr(p->nelt);
149522861Smckusick 			p->nelt = NULL;
149622861Smckusick 			}
149722861Smckusick 		else
149822861Smckusick 			err("only last bound may be asterisk");
149922861Smckusick 		p->dims[i].dimsize = ICON(1);;
150022861Smckusick 		p->dims[i].dimexpr = NULL;
150122861Smckusick 		}
150222861Smckusick 	else
150322861Smckusick 		{
150422861Smckusick 		if(dims[i].lb)
150522861Smckusick 			{
150622861Smckusick 			q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
150722861Smckusick 			q = mkexpr(OPPLUS, q, ICON(1) );
150822861Smckusick 			}
150922861Smckusick 		if( ISCONST(q) )
151022861Smckusick 			{
151122861Smckusick 			if (!ISINT(q->headblock.vtype)) {
151222861Smckusick 			   dclerr("dimension bounds must be integer expression", v);
151322861Smckusick 			   frexpr(q);
151422861Smckusick 			   q = ICON(0);
151522861Smckusick 			   }
151633257Sbostic 			if ( q->constblock.constant.ci <= 0)
151722861Smckusick 			   {
151822861Smckusick 			   dclerr("array bounds out of sequence", v);
151922861Smckusick 			   frexpr(q);
152022861Smckusick 			   q = ICON(0);
152122861Smckusick 			   }
152222861Smckusick 			p->dims[i].dimsize = q;
152322861Smckusick 			p->dims[i].dimexpr = (expptr) PNULL;
152422861Smckusick 			}
152522861Smckusick 		else	{
152622861Smckusick 			p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL);
152722861Smckusick 			p->dims[i].dimexpr = q;
152822861Smckusick 			}
152922861Smckusick 		if(p->nelt)
153022861Smckusick 			p->nelt = mkexpr(OPSTAR, p->nelt,
153122861Smckusick 					cpexpr(p->dims[i].dimsize) );
153222861Smckusick 		}
153322861Smckusick 	}
153422861Smckusick 
153522861Smckusick q = dims[nd-1].lb;
153622861Smckusick if(q == NULL)
153722861Smckusick 	q = ICON(1);
153822861Smckusick 
153922861Smckusick for(i = nd-2 ; i>=0 ; --i)
154022861Smckusick 	{
154122861Smckusick 	t = dims[i].lb;
154222861Smckusick 	if(t == NULL)
154322861Smckusick 		t = ICON(1);
154422861Smckusick 	if(p->dims[i].dimsize)
154522861Smckusick 		q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
154622861Smckusick 	}
154722861Smckusick 
154822861Smckusick if( ISCONST(q) )
154922861Smckusick 	{
155022861Smckusick 	p->baseoffset = q;
155122861Smckusick 	p->basexpr = NULL;
155222861Smckusick 	}
155322861Smckusick else
155422861Smckusick 	{
155522861Smckusick 	p->baseoffset = (expptr) autovar(1, tyint, PNULL);
155622861Smckusick 	p->basexpr = q;
155722861Smckusick 	}
155822861Smckusick }
155922861Smckusick 
156022861Smckusick 
156122861Smckusick 
156222861Smckusick /*
156322861Smckusick  * Check the dimensions of q to ensure that they are appropriately defined.
156422861Smckusick  */
chkdim(q)156522861Smckusick LOCAL chkdim(q)
156622861Smckusick register Namep q;
156722861Smckusick {
156822861Smckusick   register struct Dimblock *p;
156922861Smckusick   register int i;
157022861Smckusick   expptr e;
157122861Smckusick 
157222861Smckusick   if (q == NULL)
157322861Smckusick     return;
157422861Smckusick   if (q->vclass != CLVAR)
157522861Smckusick     return;
157622861Smckusick   if (q->vdim == NULL)
157722861Smckusick     return;
157822861Smckusick   p = q->vdim;
157922861Smckusick   for (i = 0; i < p->ndim; ++i)
158022861Smckusick     {
158122861Smckusick #ifdef SDB
158222861Smckusick       if (sdbflag)
158322861Smckusick 	{
158422861Smckusick 	  if (e = p->dims[i].lb)
158522861Smckusick 	    chkdime(e, q);
158622861Smckusick 	  if (e = p->dims[i].ub)
158722861Smckusick 	    chkdime(e, q);
158822861Smckusick 	}
158922861Smckusick       else
159022861Smckusick #endif SDB
159122861Smckusick       if (e = p->dims[i].dimexpr)
159222861Smckusick 	chkdime(e, q);
159322861Smckusick     }
159422861Smckusick }
159522861Smckusick 
159622861Smckusick 
159722861Smckusick 
159822861Smckusick /*
159922861Smckusick  * The actual checking for chkdim() -- examines each expression.
160022861Smckusick  */
chkdime(expr,q)160122861Smckusick LOCAL chkdime(expr, q)
160222861Smckusick expptr expr;
160322861Smckusick Namep q;
160422861Smckusick {
160522861Smckusick   register expptr e;
160622861Smckusick 
160722861Smckusick   e = fixtype(cpexpr(expr));
160822861Smckusick   if (!ISINT(e->exprblock.vtype))
160922861Smckusick     dclerr("non-integer dimension", q);
161022861Smckusick   else if (!safedim(e))
161122861Smckusick     dclerr("undefined dimension", q);
161222861Smckusick   frexpr(e);
161322861Smckusick   return;
161422861Smckusick }
161522861Smckusick 
161622861Smckusick 
161722861Smckusick 
161822861Smckusick /*
161922861Smckusick  * A recursive routine to find undefined variables in dimension expressions.
162022861Smckusick  */
safedim(e)162122861Smckusick LOCAL safedim(e)
162222861Smckusick expptr e;
162322861Smckusick {
162422861Smckusick   chainp cp;
162522861Smckusick 
162622861Smckusick   if (e == NULL)
162722861Smckusick     return 1;
162822861Smckusick   switch (e->tag)
162922861Smckusick     {
163022861Smckusick       case TEXPR:
163122861Smckusick 	if (e->exprblock.opcode == OPCALL || e->exprblock.opcode == OPCCALL)
163222861Smckusick 	  return 0;
163322861Smckusick 	return safedim(e->exprblock.leftp) && safedim(e->exprblock.rightp);
163422861Smckusick       case TADDR:
163522861Smckusick 	switch (e->addrblock.vstg)
163622861Smckusick 	  {
163722861Smckusick 	    case STGCOMMON:
163822861Smckusick 	    case STGARG:
163922861Smckusick 	    case STGCONST:
164022861Smckusick 	    case STGEQUIV:
164122861Smckusick 	      if (e->addrblock.isarray)
164222861Smckusick 		return 0;
164322861Smckusick 	      return safedim(e->addrblock.memoffset);
164422861Smckusick 	    default:
164522861Smckusick 	      return 0;
164622861Smckusick 	  }
164722861Smckusick       case TCONST:
164822861Smckusick       case TTEMP:
164922861Smckusick 	return 1;
165022861Smckusick     }
165122861Smckusick   return 0;
165222861Smckusick }
165322861Smckusick 
165422861Smckusick 
165522861Smckusick 
enlist(size,np,ep)165622861Smckusick LOCAL enlist(size, np, ep)
165722861Smckusick ftnint size;
165822861Smckusick Namep np;
165922861Smckusick struct Equivblock *ep;
166022861Smckusick {
166122861Smckusick   register sizelist *sp;
166222861Smckusick   register sizelist *t;
166322861Smckusick   register varlist *p;
166422861Smckusick 
166522861Smckusick   sp = varsizes;
166622861Smckusick 
166722861Smckusick   if (sp == NULL)
166822861Smckusick     {
166922861Smckusick       sp = ALLOC(SizeList);
167022861Smckusick       sp->size = size;
167122861Smckusick       varsizes = sp;
167222861Smckusick     }
167322861Smckusick   else
167422861Smckusick     {
167522861Smckusick       while (sp->size != size)
167622861Smckusick 	{
167722861Smckusick 	  if (sp->next != NULL && sp->next->size <= size)
167822861Smckusick 	    sp = sp->next;
167922861Smckusick 	  else
168022861Smckusick 	    {
168122861Smckusick 	      t = sp;
168222861Smckusick 	      sp = ALLOC(SizeList);
168322861Smckusick 	      sp->size = size;
168422861Smckusick 	      sp->next = t->next;
168522861Smckusick 	      t->next = sp;
168622861Smckusick 	    }
168722861Smckusick 	}
168822861Smckusick     }
168922861Smckusick 
169022861Smckusick   p = ALLOC(VarList);
169122861Smckusick   p->next = sp->vars;
169222861Smckusick   p->np = np;
169322861Smckusick   p->ep = ep;
169422861Smckusick 
169522861Smckusick   sp->vars = p;
169622861Smckusick 
169722861Smckusick   return;
169822861Smckusick }
169922861Smckusick 
170022861Smckusick 
170122861Smckusick 
outlocvars()170222861Smckusick outlocvars()
170322861Smckusick {
170422861Smckusick 
170522861Smckusick   register varlist *first, *last;
170622861Smckusick   register varlist *vp, *t;
170722861Smckusick   register sizelist *sp, *sp1;
170822861Smckusick   register Namep np;
170922861Smckusick   register struct Equivblock *ep;
171022861Smckusick   register int i;
171122861Smckusick   register int alt;
171222861Smckusick   register int type;
171322861Smckusick   char sname[100];
171422861Smckusick   char setbuff[100];
171522861Smckusick 
171622861Smckusick   sp = varsizes;
171722861Smckusick   if (sp == NULL)
171822861Smckusick     return;
171922861Smckusick 
172022861Smckusick   vp = sp->vars;
172122861Smckusick   if (vp->np != NULL)
172222861Smckusick     {
172322861Smckusick       np = vp->np;
172422861Smckusick       sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel,
172522861Smckusick 	      np->vardesc.varno);
172622861Smckusick     }
172722861Smckusick   else
172822861Smckusick     {
172922861Smckusick       i = vp->ep - eqvclass;
173022861Smckusick       sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart);
173122861Smckusick     }
173222861Smckusick 
173322861Smckusick   first = last = NULL;
173422861Smckusick   alt = NO;
173522861Smckusick 
173622861Smckusick   while (sp != NULL)
173722861Smckusick     {
173822861Smckusick       vp = sp->vars;
173922861Smckusick       while (vp != NULL)
174022861Smckusick 	{
174122861Smckusick 	  t = vp->next;
174222861Smckusick 	  if (alt == YES)
174322861Smckusick 	    {
174422861Smckusick 	      alt = NO;
174522861Smckusick 	      vp->next = first;
174622861Smckusick 	      first = vp;
174722861Smckusick 	    }
174822861Smckusick 	  else
174922861Smckusick 	    {
175022861Smckusick 	      alt = YES;
175122861Smckusick 	      if (last != NULL)
175222861Smckusick 	        last->next = vp;
175322861Smckusick 	      else
175422861Smckusick 		first = vp;
175522861Smckusick 	      vp->next = NULL;
175622861Smckusick 	      last = vp;
175722861Smckusick 	    }
175822861Smckusick 	  vp = t;
175922861Smckusick 	}
176022861Smckusick       sp1 = sp;
176122861Smckusick       sp = sp->next;
176222861Smckusick       free((char *) sp1);
176322861Smckusick     }
176422861Smckusick 
176522861Smckusick   vp = first;
176622861Smckusick   while(vp != NULL)
176722861Smckusick     {
176822861Smckusick       if (vp->np != NULL)
176922861Smckusick 	{
177022861Smckusick 	  np = vp->np;
177122861Smckusick 	  sprintf(sname, "v.%d", np->vardesc.varno);
177222861Smckusick 	  if (np->init)
177322861Smckusick 	    prlocdata(sname, np->varsize, np->vtype, np->initoffset,
177422861Smckusick 		      &(np->inlcomm));
177522861Smckusick 	  else
177622861Smckusick 	    {
177722861Smckusick 	      pralign(typealign[np->vtype]);
177825103Sdonn 	      fprintf(initfile, "%s:\n", sname);
177925103Sdonn 	      prspace(np->varsize);
178022861Smckusick 	    }
178122861Smckusick 	  np->inlcomm = NO;
178222861Smckusick 	}
178322861Smckusick       else
178422861Smckusick 	{
178522861Smckusick 	  ep = vp->ep;
178622861Smckusick 	  i = ep - eqvclass;
178722861Smckusick 	  if (ep->eqvleng >= 8)
178822861Smckusick 	    type = TYDREAL;
178922861Smckusick 	  else if (ep->eqvleng >= 4)
179022861Smckusick 	    type = TYLONG;
179122861Smckusick 	  else if (ep->eqvleng >= 2)
179222861Smckusick 	    type = TYSHORT;
179322861Smckusick 	  else
179422861Smckusick 	    type = TYCHAR;
179522861Smckusick 	  sprintf(sname, "q.%d", i + eqvstart);
179622861Smckusick 	  if (ep->init)
179722861Smckusick 	    prlocdata(sname, ep->eqvleng, type, ep->initoffset,
179822861Smckusick 		      &(ep->inlcomm));
179922861Smckusick 	  else
180022861Smckusick 	    {
180122861Smckusick 	      pralign(typealign[type]);
180225103Sdonn 	      fprintf(initfile, "%s:\n", sname);
180325103Sdonn 	      prspace(ep->eqvleng);
180422861Smckusick 	    }
180522861Smckusick 	  ep->inlcomm = NO;
180622861Smckusick 	}
180722861Smckusick       t = vp;
180822861Smckusick       vp = vp->next;
180922861Smckusick       free((char *) t);
181022861Smckusick     }
181122861Smckusick   fprintf(initfile, "%s\n", setbuff);
181222861Smckusick   return;
181322861Smckusick }
1814