769 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			769 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************
 | |
| Copyright 1990, 1991 by AT&T Bell Laboratories, Bellcore.
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this software
 | |
| and its documentation for any purpose and without fee is hereby
 | |
| granted, provided that the above copyright notice appear in all
 | |
| copies and that both that the copyright notice and this
 | |
| permission notice and warranty disclaimer appear in supporting
 | |
| documentation, and that the names of AT&T Bell Laboratories or
 | |
| Bellcore or any of their entities not be used in advertising or
 | |
| publicity pertaining to distribution of the software without
 | |
| specific, written prior permission.
 | |
| 
 | |
| AT&T and Bellcore disclaim all warranties with regard to this
 | |
| software, including all implied warranties of merchantability
 | |
| and fitness.  In no event shall AT&T or Bellcore be liable for
 | |
| any special, indirect or consequential damages or any damages
 | |
| whatsoever resulting from loss of use, data or profits, whether
 | |
| in an action of contract, negligence or other tortious action,
 | |
| arising out of or in connection with the use or performance of
 | |
| this software.
 | |
| ****************************************************************/
 | |
| 
 | |
| #include "sysdep.h"
 | |
| 
 | |
| #include "ftypes.h"
 | |
| #include "defines.h"
 | |
| #include "machdefs.h"
 | |
| 
 | |
| #define MAXDIM 20
 | |
| #define MAXINCLUDES 10
 | |
| #define MAXLITERALS 200		/* Max number of constants in the literal
 | |
| 				   pool */
 | |
| #define MAXTOKENLEN 302		/* length of longest token */
 | |
| #define MAXCTL 20
 | |
| #define MAXHASH 401
 | |
| #define MAXSTNO 801
 | |
| #define MAXEXT 200
 | |
| #define MAXEQUIV 150
 | |
| #define MAXLABLIST 125		/* Max number of labels in an alternate
 | |
| 				   return CALL */
 | |
| 
 | |
| /* These are the primary pointer types used in the compiler */
 | |
| 
 | |
| typedef union Expression *expptr, *tagptr;
 | |
| typedef struct Chain *chainp;
 | |
| typedef struct Addrblock *Addrp;
 | |
| typedef struct Constblock *Constp;
 | |
| typedef struct Exprblock *Exprp;
 | |
| typedef struct Nameblock *Namep;
 | |
| 
 | |
| extern FILEP opf();
 | |
| extern FILEP infile;
 | |
| extern FILEP diagfile;
 | |
| extern FILEP textfile;
 | |
| extern FILEP asmfile;
 | |
| extern FILEP c_file;		/* output file for all functions; extern
 | |
| 				   declarations will have to be prepended */
 | |
| extern FILEP pass1_file;	/* Temp file to hold the function bodies
 | |
| 				   read on pass 1 */
 | |
| extern FILEP expr_file;		/* Debugging file */
 | |
| extern FILEP initfile;		/* Intermediate data file pointer */
 | |
| extern FILEP blkdfile;		/* BLOCK DATA file */
 | |
| 
 | |
| extern int current_ftn_file;
 | |
| 
 | |
| extern char *blkdfname, *initfname, *sortfname;
 | |
| extern long int headoffset;	/* Since the header block requires data we
 | |
| 				   don't know about until AFTER each
 | |
| 				   function has been processed, we keep a
 | |
| 				   pointer to the current (dummy) header
 | |
| 				   block (at the top of the assembly file)
 | |
| 				   here */
 | |
| 
 | |
| extern char main_alias[];	/* name given to PROGRAM psuedo-op */
 | |
| extern char token [ ];
 | |
| extern int toklen;
 | |
| extern long lineno;
 | |
| extern char *infname;
 | |
| extern int needkwd;
 | |
| extern struct Labelblock *thislabel;
 | |
| 
 | |
| /* Used to allow runtime expansion of internal tables.  In particular,
 | |
|    these values can exceed their associated constants */
 | |
| 
 | |
| extern int maxctl;
 | |
| extern int maxequiv;
 | |
| extern int maxstno;
 | |
| extern int maxhash;
 | |
| extern int maxext;
 | |
| 
 | |
| extern flag nowarnflag;
 | |
| extern flag ftn66flag;		/* Generate warnings when weird f77
 | |
| 				   features are used (undeclared dummy
 | |
| 				   procedure, non-char initialized with
 | |
| 				   string, 1-dim subscript in EQUIV) */
 | |
| extern flag no66flag;		/* Generate an error when a generic
 | |
| 				   function (f77 feature) is used */
 | |
| extern flag noextflag;		/* Generate an error when an extension to
 | |
| 				   Fortran 77 is used (hex/oct/bin
 | |
| 				   constants, automatic, static, double
 | |
| 				   complex types) */
 | |
| extern flag zflag;		/* enable double complex intrinsics */
 | |
| extern flag shiftcase;
 | |
| extern flag undeftype;
 | |
| extern flag shortsubs;		/* Use short subscripts on arrays? */
 | |
| extern flag onetripflag;	/* if true, always execute DO loop body */
 | |
| extern flag checksubs;
 | |
| extern flag debugflag;
 | |
| extern int nerr;
 | |
| extern int nwarn;
 | |
| 
 | |
| extern int parstate;
 | |
| extern flag headerdone;		/* True iff the current procedure's header
 | |
| 				   data has been written */
 | |
| extern int blklevel;
 | |
| extern flag saveall;
 | |
| extern flag substars;		/* True iff some formal parameter is an
 | |
| 				   asterisk */
 | |
| extern int impltype[ ];
 | |
| extern ftnint implleng[ ];
 | |
| extern int implstg[ ];
 | |
| 
 | |
| extern int tycomplex, tyint, tyioint, tyreal;
 | |
| extern int tylogical;		/* TY____ of the implementation of   logical.
 | |
| 				   This will be LONG unless '-2' is given
 | |
| 				   on the command line */
 | |
| extern int type_choice[];
 | |
| extern char *typename[];
 | |
| 
 | |
| extern int typesize[];	/* size (in bytes) of an object of each
 | |
| 				   type.  Indexed by TY___ macros */
 | |
| extern int typealign[];
 | |
| extern int proctype;	/* Type of return value in this procedure */
 | |
| extern char * procname;	/* External name of the procedure, or last ENTRY name */
 | |
| extern int rtvlabel[ ];	/* Return value labels, indexed by TY___ macros */
 | |
| extern Addrp retslot;
 | |
| extern Addrp xretslot[];
 | |
| extern int cxslot;	/* Complex return argument slot (frame pointer offset)*/
 | |
| extern int chslot;	/* Character return argument slot (fp offset) */
 | |
| extern int chlgslot;	/* Argument slot for length of character buffer */
 | |
| extern int procclass;	/* Class of the current procedure:  either CLPROC,
 | |
| 			   CLMAIN, CLBLOCK or CLUNKNOWN */
 | |
| extern ftnint procleng;	/* Length of function return value (e.g. char
 | |
| 			   string length).  If this is -1, then the length is
 | |
| 			   not known at compile time */
 | |
| extern int nentry;	/* Number of entry points (other than the original
 | |
| 			   function call) into this procedure */
 | |
| extern flag multitype;	/* YES iff there is more than one return value
 | |
| 			   possible */
 | |
| extern int blklevel;
 | |
| extern long lastiolabno;
 | |
| extern int lastlabno;
 | |
| extern int lastvarno;
 | |
| extern int lastargslot;	/* integer offset pointing to the next free
 | |
| 			   location for an argument to the current routine */
 | |
| extern int argloc;
 | |
| extern int autonum[];		/* for numbering
 | |
| 				   automatic variables, e.g. temporaries */
 | |
| extern int retlabel;
 | |
| extern int ret0label;
 | |
| extern int dorange;		/* Number of the label which terminates
 | |
| 				   the innermost DO loop */
 | |
| extern int regnum[ ];		/* Numbers of DO indicies named in
 | |
| 				   regnamep   (below) */
 | |
| extern Namep regnamep[ ];	/* List of DO indicies in registers */
 | |
| extern int maxregvar;		/* number of elts in   regnamep   */
 | |
| extern int highregvar;		/* keeps track of the highest register
 | |
| 				   number used by DO index allocator */
 | |
| extern int nregvar;		/* count of DO indicies in registers */
 | |
| 
 | |
| extern chainp templist[];
 | |
| extern int maxdim;
 | |
| extern chainp earlylabs;
 | |
| extern chainp holdtemps;
 | |
| extern struct Entrypoint *entries;
 | |
| extern struct Rplblock *rpllist;
 | |
| extern struct Chain *curdtp;
 | |
| extern ftnint curdtelt;
 | |
| extern chainp allargs;		/* union of args in entries */
 | |
| extern int nallargs;		/* total number of args */
 | |
| extern int nallchargs;		/* total number of character args */
 | |
| extern flag toomanyinit;	/* True iff too many initializers in a
 | |
| 				   DATA statement */
 | |
| 
 | |
| extern flag inioctl;
 | |
| extern int iostmt;
 | |
| extern Addrp ioblkp;
 | |
| extern int nioctl;
 | |
| extern int nequiv;
 | |
| extern int eqvstart;	/* offset to eqv number to guarantee uniqueness
 | |
| 			   and prevent <something> from going negative */
 | |
| extern int nintnames;
 | |
| 
 | |
| /* Chain of tagged blocks */
 | |
| 
 | |
| struct Chain
 | |
| 	{
 | |
| 	chainp nextp;
 | |
| 	char * datap;		/* Tagged block */
 | |
| 	};
 | |
| 
 | |
| extern chainp chains;
 | |
| 
 | |
| /* Recall that   field   is intended to hold four-bit characters */
 | |
| 
 | |
| /* This structure exists only to defeat the type checking */
 | |
| 
 | |
| struct Headblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	field vclass;
 | |
| 	field vstg;
 | |
| 	expptr vleng;		/* Expression for length of char string -
 | |
| 				   this may be a constant, or an argument
 | |
| 				   generated by mkarg() */
 | |
| 	} ;
 | |
| 
 | |
| /* Control construct info (for do loops, else, etc) */
 | |
| 
 | |
| struct Ctlframe
 | |
| 	{
 | |
| 	unsigned ctltype:8;
 | |
| 	unsigned dostepsign:8;	/* 0 - variable, 1 - pos, 2 - neg */
 | |
| 	unsigned dowhile:1;
 | |
| 	int ctlabels[4];	/* Control labels, defined below */
 | |
| 	int dolabel;		/* label marking end of this DO loop */
 | |
| 	Namep donamep;		/* DO index variable */
 | |
| 	expptr domax;		/* constant or temp variable holding MAX
 | |
| 				   loop value; or expr of while(expr) */
 | |
| 	expptr dostep;		/* expression */
 | |
| 	Namep loopname;
 | |
| 	};
 | |
| #define endlabel ctlabels[0]
 | |
| #define elselabel ctlabels[1]
 | |
| #define dobodylabel ctlabels[1]
 | |
| #define doposlabel ctlabels[2]
 | |
| #define doneglabel ctlabels[3]
 | |
| extern struct Ctlframe *ctls;		/* Keeps info on DO and BLOCK IF
 | |
| 					   structures - this is the stack
 | |
| 					   bottom */
 | |
| extern struct Ctlframe *ctlstack;	/* Pointer to current nesting
 | |
| 					   level */
 | |
| extern struct Ctlframe *lastctl;	/* Point to end of
 | |
| 					   dynamically-allocated array */
 | |
| 
 | |
| typedef struct {
 | |
| 	int type;
 | |
| 	chainp cp;
 | |
| 	} Atype;
 | |
| 
 | |
| typedef struct {
 | |
| 	int nargs, changes;
 | |
| 	Atype atypes[1];
 | |
| 	} Argtypes;
 | |
| 
 | |
| /* External Symbols */
 | |
| 
 | |
| struct Extsym
 | |
| 	{
 | |
| 	char *fextname;		/* Fortran version of external name */
 | |
| 	char *cextname;		/* C version of external name */
 | |
| 	field extstg;		/* STG -- should be COMMON, UNKNOWN or EXT
 | |
| 				   */
 | |
| 	unsigned extype:4;	/* for transmitting type to output routines */
 | |
| 	unsigned used_here:1;	/* Boolean - true on the second pass
 | |
| 				   through a function if the block has
 | |
| 				   been referenced */
 | |
| 	unsigned exused:1;	/* Has been used (for help with error msgs
 | |
| 				   about externals typed differently in
 | |
| 				   different modules) */
 | |
| 	unsigned exproto:1;	/* type specified in a .P file */
 | |
| 	unsigned extinit:1;	/* Procedure has been defined,
 | |
| 				   or COMMON has DATA */
 | |
| 	unsigned extseen:1;	/* True if previously referenced */
 | |
| 	chainp extp;		/* List of identifiers in the common
 | |
| 				   block for this function, stored as
 | |
| 				   Namep (hash table pointers) */
 | |
| 	chainp allextp;		/* List of lists of identifiers; we keep one
 | |
| 				   list for each layout of this common block */
 | |
| 	int curno;		/* current number for this common block,
 | |
| 				   used for constructing appending _nnn
 | |
| 				   to the common block name */
 | |
| 	int maxno;		/* highest curno value for this common block */
 | |
| 	ftnint extleng;
 | |
| 	ftnint maxleng;
 | |
| 	Argtypes *arginfo;
 | |
| 	};
 | |
| typedef struct Extsym Extsym;
 | |
| 
 | |
| extern Extsym *extsymtab;	/* External symbol table */
 | |
| extern Extsym *nextext;
 | |
| extern Extsym *lastext;
 | |
| extern int complex_seen, dcomplex_seen;
 | |
| 
 | |
| /* Statement labels */
 | |
| 
 | |
| struct Labelblock
 | |
| 	{
 | |
| 	int labelno;		/* Internal label */
 | |
| 	unsigned blklevel:8;	/* level of nesting , for branch-in-loop
 | |
| 				   checking */
 | |
| 	unsigned labused:1;
 | |
| 	unsigned fmtlabused:1;
 | |
| 	unsigned labinacc:1;	/* inaccessible? (i.e. has its scope
 | |
| 				   vanished) */
 | |
| 	unsigned labdefined:1;	/* YES or NO */
 | |
| 	unsigned labtype:2;	/* LAB{FORMAT,EXEC,etc} */
 | |
| 	ftnint stateno;		/* Original label */
 | |
| 	char *fmtstring;	/* format string */
 | |
| 	};
 | |
| 
 | |
| extern struct Labelblock *labeltab;	/* Label table - keeps track of
 | |
| 					   all labels, including undefined */
 | |
| extern struct Labelblock *labtabend;
 | |
| extern struct Labelblock *highlabtab;
 | |
| 
 | |
| /* Entry point list */
 | |
| 
 | |
| struct Entrypoint
 | |
| 	{
 | |
| 	struct Entrypoint *entnextp;
 | |
| 	Extsym *entryname;	/* Name of this ENTRY */
 | |
| 	chainp arglist;
 | |
| 	int typelabel;			/* Label for function exit; this
 | |
| 					   will return the proper type of
 | |
| 					   object */
 | |
| 	Namep enamep;			/* External name */
 | |
| 	};
 | |
| 
 | |
| /* Primitive block, or Primary block.  This is a general template returned
 | |
|    by the parser, which will be interpreted in context.  It is a template
 | |
|    for an identifier (variable name, function name), parenthesized
 | |
|    arguments (array subscripts, function parameters) and substring
 | |
|    specifications. */
 | |
| 
 | |
| struct Primblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	Namep namep;			/* Pointer to structure Nameblock */
 | |
| 	struct Listblock *argsp;
 | |
| 	expptr fcharp;			/* first-char-index-pointer (in
 | |
| 					   substring) */
 | |
| 	expptr lcharp;			/* last-char-index-pointer (in
 | |
| 					   substring) */
 | |
| 	};
 | |
| 
 | |
| 
 | |
| struct Hashentry
 | |
| 	{
 | |
| 	int hashval;
 | |
| 	Namep varp;
 | |
| 	};
 | |
| extern struct Hashentry *hashtab;	/* Hash table */
 | |
| extern struct Hashentry *lasthash;
 | |
| 
 | |
| struct Intrpacked	/* bits for intrinsic function description */
 | |
| 	{
 | |
| 	unsigned f1:3;
 | |
| 	unsigned f2:4;
 | |
| 	unsigned f3:7;
 | |
| 	unsigned f4:1;
 | |
| 	};
 | |
| 
 | |
| struct Nameblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	field vclass;
 | |
| 	field vstg;
 | |
| 	expptr vleng;		/* length of character string, if applicable */
 | |
| 	char *fvarname;		/* name in the Fortran source */
 | |
| 	char *cvarname;		/* name in the resulting C */
 | |
| 	chainp vlastdim;	/* datap points to new_vars entry for the */
 | |
| 				/* system variable, if any, storing the final */
 | |
| 				/* dimension; we zero the datap if this */
 | |
| 				/* variable is needed */
 | |
| 	unsigned vprocclass:3;	/* P____ macros - selects the   varxptr
 | |
| 				   field below */
 | |
| 	unsigned vdovar:1;	/* "is it a DO variable?" for register
 | |
| 				   and multi-level loop	checking */
 | |
| 	unsigned vdcldone:1;	/* "do I think I'm done?" - set when the
 | |
| 				   context is sufficient to determine its
 | |
| 				   status */
 | |
| 	unsigned vadjdim:1;	/* "adjustable dimension?" - needed for
 | |
| 				   information about copies */
 | |
| 	unsigned vsave:1;
 | |
| 	unsigned vimpldovar:1;	/* used to prevent erroneous error messages
 | |
| 				   for variables used only in DATA stmt
 | |
| 				   implicit DOs */
 | |
| 	unsigned vis_assigned:1;/* True if this variable has had some
 | |
| 				   label ASSIGNED to it; hence
 | |
| 				   varxptr.assigned_values is valid */
 | |
| 	unsigned vimplstg:1;	/* True if storage type is assigned implicitly;
 | |
| 				   this allows a COMMON variable to participate
 | |
| 				   in a DIMENSION before the COMMON declaration.
 | |
| 				   */
 | |
| 	unsigned vcommequiv:1;	/* True if EQUIVALENCEd onto STGCOMMON */
 | |
| 	unsigned vfmt_asg:1;	/* True if char *var_fmt needed */
 | |
| 	unsigned vpassed:1;	/* True if passed as a character-variable arg */
 | |
| 	unsigned vknownarg:1;	/* True if seen in a previous entry point */
 | |
| 	unsigned visused:1;	/* True if variable is referenced -- so we */
 | |
| 				/* can omit variables that only appear in DATA */
 | |
| 	unsigned vnamelist:1;	/* Appears in a NAMELIST */
 | |
| 	unsigned vimpltype:1;	/* True if implicitly typed and not
 | |
| 				   invoked as a function or subroutine
 | |
| 				   (so we can consistently type procedures
 | |
| 				   declared external and passed as args
 | |
| 				   but never invoked).
 | |
| 				   */
 | |
| 	unsigned vtypewarned:1;	/* so we complain just once about
 | |
| 				   changed types of external procedures */
 | |
| 	unsigned vinftype:1;	/* so we can restore implicit type to a
 | |
| 				   procedure if it is invoked as a function
 | |
| 				   after being given a different type by -it */
 | |
| 	unsigned vinfproc:1;	/* True if -it infers this to be a procedure */
 | |
| 	unsigned vcalled:1;	/* has been invoked */
 | |
| 	unsigned vdimfinish:1;	/* need to invoke dim_finish() */
 | |
| 
 | |
| /* The   vardesc   union below is used to store the number of an intrinsic
 | |
|    function (when vstg == STGINTR and vprocclass == PINTRINSIC), or to
 | |
|    store the index of this external symbol in   extsymtab   (when vstg ==
 | |
|    STGEXT and vprocclass == PEXTERNAL) */
 | |
| 
 | |
| 	union	{
 | |
| 		int varno;		/* Return variable for a function.
 | |
| 					   This is used when a function is
 | |
| 					   assigned a return value.  Also
 | |
| 					   used to point to the COMMON
 | |
| 					   block, when this is a field of
 | |
| 					   that block.  Also points to
 | |
| 					   EQUIV block when STGEQUIV */
 | |
| 		struct Intrpacked intrdesc;	/* bits for intrinsic function*/
 | |
| 		} vardesc;
 | |
| 	struct Dimblock *vdim;	/* points to the dimensions if they exist */
 | |
| 	ftnint voffset;		/* offset in a storage block (the variable
 | |
| 				   name will be "v.%d", voffset in a
 | |
| 				   common blck on the vax).  Also holds
 | |
| 				   pointers for automatic variables.  When
 | |
| 				   STGEQUIV, this is -(offset from array
 | |
| 				   base) */
 | |
| 	union	{
 | |
| 		chainp namelist;	/* points to names in the NAMELIST,
 | |
| 					   if this is a NAMELIST name */
 | |
| 		chainp vstfdesc;	/* points to (formals, expr) pair */
 | |
| 		chainp assigned_values;	/* list of integers, each being a
 | |
| 					   statement label assigned to
 | |
| 					   this variable in the current function */
 | |
| 		} varxptr;
 | |
| 	int argno;		/* for multiple entries */
 | |
| 	Argtypes *arginfo;
 | |
| 	};
 | |
| 
 | |
| 
 | |
| /* PARAMETER statements */
 | |
| 
 | |
| struct Paramblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	field vclass;
 | |
| 	field vstg;
 | |
| 	expptr vleng;
 | |
| 	char *fvarname;
 | |
| 	char *cvarname;
 | |
| 	expptr paramval;
 | |
| 	} ;
 | |
| 
 | |
| 
 | |
| /* Expression block */
 | |
| 
 | |
| struct Exprblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	field vclass;
 | |
| 	field vstg;
 | |
| 	expptr vleng;		/* in the case of a character expression, this
 | |
| 				   value is inherited from the children */
 | |
| 	unsigned opcode;
 | |
| 	expptr leftp;
 | |
| 	expptr rightp;
 | |
| 	};
 | |
| 
 | |
| 
 | |
| union Constant
 | |
| 	{
 | |
| 	struct {
 | |
| 		char *ccp0;
 | |
| 		ftnint blanks;
 | |
| 		} ccp1;
 | |
| 	ftnint ci;		/* Constant long integer */
 | |
| 	double cd[2];
 | |
| 	char *cds[2];
 | |
| 	};
 | |
| #define ccp ccp1.ccp0
 | |
| 
 | |
| struct Constblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	field vclass;
 | |
| 	field vstg;		/* vstg = 1 when using Const.cds */
 | |
| 	expptr vleng;
 | |
| 	union Constant Const;
 | |
| 	};
 | |
| 
 | |
| 
 | |
| struct Listblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	chainp listp;
 | |
| 	};
 | |
| 
 | |
| 
 | |
| 
 | |
| /* Address block - this is the FINAL form of identifiers before being
 | |
|    sent to pass 2.  We'll want to add the original identifier here so that it can
 | |
|    be preserved in the translation.
 | |
| 
 | |
|    An example identifier is q.7.  The "q" refers to the storage class
 | |
|    (field vstg), the 7 to the variable number (int memno). */
 | |
| 
 | |
| struct Addrblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	field vclass;
 | |
| 	field vstg;
 | |
| 	expptr vleng;
 | |
| 	/* put union...user here so the beginning of an Addrblock
 | |
| 	 * is the same as a Constblock.
 | |
| 	 */
 | |
| 	union {
 | |
| 	    Namep name;		/* contains a pointer into the hash table */
 | |
| 	    char ident[IDENT_LEN + 1];	/* C string form of identifier */
 | |
| 	    char *Charp;
 | |
| 	    union Constant Const;	/* Constant value */
 | |
| 	    struct {
 | |
| 		double dfill[2];
 | |
| 		field vstg1;
 | |
| 		} kludge;	/* so we can distinguish string vs binary
 | |
| 				 * floating-point constants */
 | |
| 	} user;
 | |
| 	long memno;		/* when vstg == STGCONST, this is the
 | |
| 				   numeric part of the assembler label
 | |
| 				   where the constant value is stored */
 | |
| 	expptr memoffset;	/* used in subscript computations, usually */
 | |
| 	unsigned istemp:1;	/* used in stack management of temporary
 | |
| 				   variables */
 | |
| 	unsigned isarray:1;	/* used to show that memoffset is
 | |
| 				   meaningful, even if zero */
 | |
| 	unsigned ntempelt:10;	/* for representing temporary arrays, as
 | |
| 				   in concatenation */
 | |
| 	unsigned dbl_builtin:1;	/* builtin to be declared double */
 | |
| 	unsigned charleng:1;	/* so saveargtypes can get i/o calls right */
 | |
| 	ftnint varleng;		/* holds a copy of a constant length which
 | |
| 				   is stored in the   vleng   field (e.g.
 | |
| 				   a double is 8 bytes) */
 | |
| 	int uname_tag;		/* Tag describing which of the unions()
 | |
| 				   below to use */
 | |
| 	char *Field;		/* field name when dereferencing a struct */
 | |
| }; /* struct Addrblock */
 | |
| 
 | |
| 
 | |
| /* Errorbock - placeholder for errors, to allow the compilation to
 | |
|    continue */
 | |
| 
 | |
| struct Errorblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	field vtype;
 | |
| 	};
 | |
| 
 | |
| 
 | |
| /* Implicit DO block, especially related to DATA statements.  This block
 | |
|    keeps track of the compiler's location in the implicit DO while it's
 | |
|    running.  In particular, the   isactive and isbusy   flags tell where
 | |
|    it is */
 | |
| 
 | |
| struct Impldoblock
 | |
| 	{
 | |
| 	field tag;
 | |
| 	unsigned isactive:1;
 | |
| 	unsigned isbusy:1;
 | |
| 	Namep varnp;
 | |
| 	Constp varvp;
 | |
| 	chainp impdospec;
 | |
| 	expptr implb;
 | |
| 	expptr impub;
 | |
| 	expptr impstep;
 | |
| 	ftnint impdiff;
 | |
| 	ftnint implim;
 | |
| 	struct Chain *datalist;
 | |
| 	};
 | |
| 
 | |
| 
 | |
| /* Each of these components has a first field called   tag.   This union
 | |
|    exists just for allocation simplicity */
 | |
| 
 | |
| union Expression
 | |
| 	{
 | |
| 	field tag;
 | |
| 	struct Addrblock addrblock;
 | |
| 	struct Constblock constblock;
 | |
| 	struct Errorblock errorblock;
 | |
| 	struct Exprblock exprblock;
 | |
| 	struct Headblock headblock;
 | |
| 	struct Impldoblock impldoblock;
 | |
| 	struct Listblock listblock;
 | |
| 	struct Nameblock nameblock;
 | |
| 	struct Paramblock paramblock;
 | |
| 	struct Primblock primblock;
 | |
| 	} ;
 | |
| 
 | |
| 
 | |
| 
 | |
| struct Dimblock
 | |
| 	{
 | |
| 	int ndim;
 | |
| 	expptr nelt;		/* This is NULL if the array is unbounded */
 | |
| 	expptr baseoffset;	/* a constant or local variable holding
 | |
| 				   the offset in this procedure */
 | |
| 	expptr basexpr;		/* expression for comuting the offset, if
 | |
| 				   it's not constant.  If this is
 | |
| 				   non-null, the register named in
 | |
| 				   baseoffset will get initialized to this
 | |
| 				   value in the procedure's prolog */
 | |
| 	struct
 | |
| 		{
 | |
| 		expptr dimsize;	/* constant or register holding the size
 | |
| 				   of this dimension */
 | |
| 		expptr dimexpr;	/* as above in basexpr, this is an
 | |
| 				   expression for computing a variable
 | |
| 				   dimension */
 | |
| 		} dims[1];	/* Dimblocks are allocated with enough
 | |
| 				   space for this to become dims[ndim] */
 | |
| 	};
 | |
| 
 | |
| 
 | |
| /* Statement function identifier stack - this holds the name and value of
 | |
|    the parameters in a statement function invocation.  For example,
 | |
| 
 | |
| 	f(x,y,z)=x+y+z
 | |
| 		.
 | |
| 		.
 | |
| 	y = f(1,2,3)
 | |
| 
 | |
|    generates a stack of depth 3, with <x 1>, <y 2>, <z 3> AT THE INVOCATION, NOT
 | |
|    at the definition */
 | |
| 
 | |
| struct Rplblock	/* name replacement block */
 | |
| 	{
 | |
| 	struct Rplblock *rplnextp;
 | |
| 	Namep rplnp;		/* Name of the formal parameter */
 | |
| 	expptr rplvp;		/* Value of the actual parameter */
 | |
| 	expptr rplxp;		/* Initialization of temporary variable,
 | |
| 				   if required; else null */
 | |
| 	int rpltag;		/* Tag on the value of the actual param */
 | |
| 	};
 | |
| 
 | |
| 
 | |
| 
 | |
| /* Equivalence block */
 | |
| 
 | |
| struct Equivblock
 | |
| 	{
 | |
| 	struct Eqvchain *equivs;	/* List (Eqvchain) of primblocks
 | |
| 					   holding variable identifiers */
 | |
| 	flag eqvinit;
 | |
| 	long int eqvtop;
 | |
| 	long int eqvbottom;
 | |
| 	int eqvtype;
 | |
| 	} ;
 | |
| #define eqvleng eqvtop
 | |
| 
 | |
| extern struct Equivblock *eqvclass;
 | |
| 
 | |
| 
 | |
| struct Eqvchain
 | |
| 	{
 | |
| 	struct Eqvchain *eqvnextp;
 | |
| 	union
 | |
| 		{
 | |
| 		struct Primblock *eqvlhs;
 | |
| 		Namep eqvname;
 | |
| 		} eqvitem;
 | |
| 	long int eqvoffset;
 | |
| 	} ;
 | |
| 
 | |
| 
 | |
| 
 | |
| /* For allocation purposes only, and to keep lint quiet.  In particular,
 | |
|    don't count on the tag being able to tell you which structure is used */
 | |
| 
 | |
| 
 | |
| /* There is a tradition in Fortran that the compiler not generate the same
 | |
|    bit pattern more than is necessary.  This structure is used to do just
 | |
|    that; if two integer constants have the same bit pattern, just generate
 | |
|    it once.  This could be expanded to optimize without regard to type, by
 | |
|    removing the type check in   putconst()   */
 | |
| 
 | |
| struct Literal
 | |
| 	{
 | |
| 	short littype;
 | |
| 	short litnum;			/* numeric part of the assembler
 | |
| 					   label for this constant value */
 | |
| 	int lituse;		/* usage count */
 | |
| 	union	{
 | |
| 		ftnint litival;
 | |
| 		double litdval[2];
 | |
| 		ftnint litival2[2];	/* length, nblanks for strings */
 | |
| 		} litval;
 | |
| 	char *cds[2];
 | |
| 	};
 | |
| 
 | |
| extern struct Literal *litpool;
 | |
| extern int maxliterals, nliterals;
 | |
| extern char Letters[];
 | |
| #define letter(x) Letters[x]
 | |
| 
 | |
| struct Dims { expptr lb, ub; };
 | |
| 
 | |
| 
 | |
| /* popular functions with non integer return values */
 | |
| 
 | |
| 
 | |
| int *ckalloc();
 | |
| char *varstr(), *nounder(), *addunder();
 | |
| char *copyn(), *copys();
 | |
| chainp hookup(), mkchain(), revchain();
 | |
| ftnint convci();
 | |
| char *convic();
 | |
| char *setdoto();
 | |
| double convcd();
 | |
| Namep mkname();
 | |
| struct Labelblock *mklabel(), *execlab();
 | |
| Extsym *mkext(), *newentry();
 | |
| expptr addrof(), call1(), call2(), call3(), call4();
 | |
| Addrp builtin(), mktmp(), mktmp0(), mktmpn(), autovar();
 | |
| Addrp mkplace(), mkaddr(), putconst(), memversion();
 | |
| expptr mkprim(), mklhs(), mkexpr(), mkconv(), mkfunct(), fixexpr(), fixtype();
 | |
| expptr errnode(), mkaddcon(), mkintcon(), putcxop();
 | |
| tagptr cpexpr();
 | |
| ftnint lmin(), lmax(), iarrlen();
 | |
| char *dbconst(), *flconst();
 | |
| 
 | |
| void puteq (), putex1 ();
 | |
| expptr putx (), putsteq (), putassign ();
 | |
| 
 | |
| extern int forcedouble;		/* force real functions to double */
 | |
| extern int doin_setbound;	/* special handling for array bounds */
 | |
| extern int Ansi;
 | |
| extern char *cds(), *cpstring(), *dtos(), *string_num();
 | |
| extern char *c_type_decl();
 | |
| extern char hextoi_tab[];
 | |
| #define hextoi(x) hextoi_tab[(x) & 0xff]
 | |
| extern char *casttypes[], *ftn_types[], *protorettypes[], *usedcasts[];
 | |
| extern int Castargs, infertypes;
 | |
| extern FILE *protofile;
 | |
| extern void exit(), inferdcl(), protowrite(), save_argtypes();
 | |
| extern char binread[], binwrite[], textread[], textwrite[];
 | |
| extern char *ei_first, *ei_last, *ei_next;
 | |
| extern char *wh_first, *wh_last, *wh_next;
 | |
| extern void putwhile();
 | |
| extern char *halign;
 |