846 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			846 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************
 | 
						|
Copyright 1990 by AT&T Bell Laboratories and 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 "defs.h"
 | 
						|
#include "names.h"
 | 
						|
 | 
						|
void cast_args ();
 | 
						|
 | 
						|
union
 | 
						|
	{
 | 
						|
	int ijunk;
 | 
						|
	struct Intrpacked bits;
 | 
						|
	} packed;
 | 
						|
 | 
						|
struct Intrbits
 | 
						|
	{
 | 
						|
	char intrgroup /* :3 */;
 | 
						|
	char intrstuff /* result type or number of generics */;
 | 
						|
	char intrno /* :7 */;
 | 
						|
	char dblcmplx;
 | 
						|
	char dblintrno;	/* for -r8 */
 | 
						|
	};
 | 
						|
 | 
						|
/* List of all intrinsic functions.  */
 | 
						|
 | 
						|
LOCAL struct Intrblock
 | 
						|
	{
 | 
						|
	char intrfname[8];
 | 
						|
	struct Intrbits intrval;
 | 
						|
	} intrtab[ ] =
 | 
						|
{
 | 
						|
"int", 		{ INTRCONV, TYLONG },
 | 
						|
"real", 	{ INTRCONV, TYREAL, 1 },
 | 
						|
		/* 1 ==> real(TYDCOMPLEX) yields TYDREAL */
 | 
						|
"dble", 	{ INTRCONV, TYDREAL },
 | 
						|
"cmplx", 	{ INTRCONV, TYCOMPLEX },
 | 
						|
"dcmplx", 	{ INTRCONV, TYDCOMPLEX, 0, 1 },
 | 
						|
"ifix", 	{ INTRCONV, TYLONG },
 | 
						|
"idint", 	{ INTRCONV, TYLONG },
 | 
						|
"float", 	{ INTRCONV, TYREAL },
 | 
						|
"dfloat",	{ INTRCONV, TYDREAL },
 | 
						|
"sngl", 	{ INTRCONV, TYREAL },
 | 
						|
"ichar", 	{ INTRCONV, TYLONG },
 | 
						|
"iachar", 	{ INTRCONV, TYLONG },
 | 
						|
"char", 	{ INTRCONV, TYCHAR },
 | 
						|
"achar", 	{ INTRCONV, TYCHAR },
 | 
						|
 | 
						|
/* any MAX or MIN can be used with any types; the compiler will cast them
 | 
						|
   correctly.  So rules against bad syntax in these expressions are not
 | 
						|
   enforced */
 | 
						|
 | 
						|
"max", 		{ INTRMAX, TYUNKNOWN },
 | 
						|
"max0", 	{ INTRMAX, TYLONG },
 | 
						|
"amax0", 	{ INTRMAX, TYREAL },
 | 
						|
"max1", 	{ INTRMAX, TYLONG },
 | 
						|
"amax1", 	{ INTRMAX, TYREAL },
 | 
						|
"dmax1", 	{ INTRMAX, TYDREAL },
 | 
						|
 | 
						|
"and",		{ INTRBOOL, TYUNKNOWN, OPBITAND },
 | 
						|
"or",		{ INTRBOOL, TYUNKNOWN, OPBITOR },
 | 
						|
"xor",		{ INTRBOOL, TYUNKNOWN, OPBITXOR },
 | 
						|
"not",		{ INTRBOOL, TYUNKNOWN, OPBITNOT },
 | 
						|
"lshift",	{ INTRBOOL, TYUNKNOWN, OPLSHIFT },
 | 
						|
"rshift",	{ INTRBOOL, TYUNKNOWN, OPRSHIFT },
 | 
						|
 | 
						|
"min", 		{ INTRMIN, TYUNKNOWN },
 | 
						|
"min0", 	{ INTRMIN, TYLONG },
 | 
						|
"amin0", 	{ INTRMIN, TYREAL },
 | 
						|
"min1", 	{ INTRMIN, TYLONG },
 | 
						|
"amin1", 	{ INTRMIN, TYREAL },
 | 
						|
"dmin1", 	{ INTRMIN, TYDREAL },
 | 
						|
 | 
						|
"aint", 	{ INTRGEN, 2, 0 },
 | 
						|
"dint", 	{ INTRSPEC, TYDREAL, 1 },
 | 
						|
 | 
						|
"anint", 	{ INTRGEN, 2, 2 },
 | 
						|
"dnint", 	{ INTRSPEC, TYDREAL, 3 },
 | 
						|
 | 
						|
"nint", 	{ INTRGEN, 4, 4 },
 | 
						|
"idnint", 	{ INTRGEN, 2, 6 },
 | 
						|
 | 
						|
"abs", 		{ INTRGEN, 6, 8 },
 | 
						|
"iabs", 	{ INTRGEN, 2, 9 },
 | 
						|
"dabs", 	{ INTRSPEC, TYDREAL, 11 },
 | 
						|
"cabs", 	{ INTRSPEC, TYREAL, 12, 0, 13 },
 | 
						|
"zabs", 	{ INTRSPEC, TYDREAL, 13, 1 },
 | 
						|
 | 
						|
"mod", 		{ INTRGEN, 4, 14 },
 | 
						|
"amod", 	{ INTRSPEC, TYREAL, 16, 0, 17 },
 | 
						|
"dmod", 	{ INTRSPEC, TYDREAL, 17 },
 | 
						|
 | 
						|
"sign", 	{ INTRGEN, 4, 18 },
 | 
						|
"isign", 	{ INTRGEN, 2, 19 },
 | 
						|
"dsign", 	{ INTRSPEC, TYDREAL, 21 },
 | 
						|
 | 
						|
"dim", 		{ INTRGEN, 4, 22 },
 | 
						|
"idim", 	{ INTRGEN, 2, 23 },
 | 
						|
"ddim", 	{ INTRSPEC, TYDREAL, 25 },
 | 
						|
 | 
						|
"dprod", 	{ INTRSPEC, TYDREAL, 26 },
 | 
						|
 | 
						|
"len", 		{ INTRSPEC, TYLONG, 27 },
 | 
						|
"index", 	{ INTRSPEC, TYLONG, 29 },
 | 
						|
 | 
						|
"imag", 	{ INTRGEN, 2, 31 },
 | 
						|
"aimag", 	{ INTRSPEC, TYREAL, 31, 0, 32 },
 | 
						|
"dimag", 	{ INTRSPEC, TYDREAL, 32 },
 | 
						|
 | 
						|
"conjg", 	{ INTRGEN, 2, 33 },
 | 
						|
"dconjg", 	{ INTRSPEC, TYDCOMPLEX, 34, 1 },
 | 
						|
 | 
						|
"sqrt", 	{ INTRGEN, 4, 35 },
 | 
						|
"dsqrt", 	{ INTRSPEC, TYDREAL, 36 },
 | 
						|
"csqrt", 	{ INTRSPEC, TYCOMPLEX, 37, 0, 38 },
 | 
						|
"zsqrt", 	{ INTRSPEC, TYDCOMPLEX, 38, 1 },
 | 
						|
 | 
						|
"exp", 		{ INTRGEN, 4, 39 },
 | 
						|
"dexp", 	{ INTRSPEC, TYDREAL, 40 },
 | 
						|
"cexp", 	{ INTRSPEC, TYCOMPLEX, 41, 0, 42 },
 | 
						|
"zexp", 	{ INTRSPEC, TYDCOMPLEX, 42, 1 },
 | 
						|
 | 
						|
"log", 		{ INTRGEN, 4, 43 },
 | 
						|
"alog", 	{ INTRSPEC, TYREAL, 43, 0, 44 },
 | 
						|
"dlog", 	{ INTRSPEC, TYDREAL, 44 },
 | 
						|
"clog", 	{ INTRSPEC, TYCOMPLEX, 45, 0, 46 },
 | 
						|
"zlog", 	{ INTRSPEC, TYDCOMPLEX, 46, 1 },
 | 
						|
 | 
						|
"log10", 	{ INTRGEN, 2, 47 },
 | 
						|
"alog10", 	{ INTRSPEC, TYREAL, 47, 0, 48 },
 | 
						|
"dlog10", 	{ INTRSPEC, TYDREAL, 48 },
 | 
						|
 | 
						|
"sin", 		{ INTRGEN, 4, 49 },
 | 
						|
"dsin", 	{ INTRSPEC, TYDREAL, 50 },
 | 
						|
"csin", 	{ INTRSPEC, TYCOMPLEX, 51, 0, 52 },
 | 
						|
"zsin", 	{ INTRSPEC, TYDCOMPLEX, 52, 1 },
 | 
						|
 | 
						|
"cos", 		{ INTRGEN, 4, 53 },
 | 
						|
"dcos", 	{ INTRSPEC, TYDREAL, 54 },
 | 
						|
"ccos", 	{ INTRSPEC, TYCOMPLEX, 55, 0, 56 },
 | 
						|
"zcos", 	{ INTRSPEC, TYDCOMPLEX, 56, 1 },
 | 
						|
 | 
						|
"tan", 		{ INTRGEN, 2, 57 },
 | 
						|
"dtan", 	{ INTRSPEC, TYDREAL, 58 },
 | 
						|
 | 
						|
"asin", 	{ INTRGEN, 2, 59 },
 | 
						|
"dasin", 	{ INTRSPEC, TYDREAL, 60 },
 | 
						|
 | 
						|
"acos", 	{ INTRGEN, 2, 61 },
 | 
						|
"dacos", 	{ INTRSPEC, TYDREAL, 62 },
 | 
						|
 | 
						|
"atan", 	{ INTRGEN, 2, 63 },
 | 
						|
"datan", 	{ INTRSPEC, TYDREAL, 64 },
 | 
						|
 | 
						|
"atan2", 	{ INTRGEN, 2, 65 },
 | 
						|
"datan2", 	{ INTRSPEC, TYDREAL, 66 },
 | 
						|
 | 
						|
"sinh", 	{ INTRGEN, 2, 67 },
 | 
						|
"dsinh", 	{ INTRSPEC, TYDREAL, 68 },
 | 
						|
 | 
						|
"cosh", 	{ INTRGEN, 2, 69 },
 | 
						|
"dcosh", 	{ INTRSPEC, TYDREAL, 70 },
 | 
						|
 | 
						|
"tanh", 	{ INTRGEN, 2, 71 },
 | 
						|
"dtanh", 	{ INTRSPEC, TYDREAL, 72 },
 | 
						|
 | 
						|
"lge",		{ INTRSPEC, TYLOGICAL, 73},
 | 
						|
"lgt",		{ INTRSPEC, TYLOGICAL, 75},
 | 
						|
"lle",		{ INTRSPEC, TYLOGICAL, 77},
 | 
						|
"llt",		{ INTRSPEC, TYLOGICAL, 79},
 | 
						|
 | 
						|
#if 0
 | 
						|
"epbase",	{ INTRCNST, 4, 0 },
 | 
						|
"epprec",	{ INTRCNST, 4, 4 },
 | 
						|
"epemin",	{ INTRCNST, 2, 8 },
 | 
						|
"epemax",	{ INTRCNST, 2, 10 },
 | 
						|
"eptiny",	{ INTRCNST, 2, 12 },
 | 
						|
"ephuge",	{ INTRCNST, 4, 14 },
 | 
						|
"epmrsp",	{ INTRCNST, 2, 18 },
 | 
						|
#endif
 | 
						|
 | 
						|
"fpexpn",	{ INTRGEN, 4, 81 },
 | 
						|
"fpabsp",	{ INTRGEN, 2, 85 },
 | 
						|
"fprrsp",	{ INTRGEN, 2, 87 },
 | 
						|
"fpfrac",	{ INTRGEN, 2, 89 },
 | 
						|
"fpmake",	{ INTRGEN, 2, 91 },
 | 
						|
"fpscal",	{ INTRGEN, 2, 93 },
 | 
						|
 | 
						|
"" };
 | 
						|
 | 
						|
 | 
						|
LOCAL struct Specblock
 | 
						|
	{
 | 
						|
	char atype;		/* Argument type; every arg must have
 | 
						|
				   this type */
 | 
						|
	char rtype;		/* Result type */
 | 
						|
	char nargs;		/* Number of arguments */
 | 
						|
	char spxname[8];	/* Name of the function in Fortran */
 | 
						|
	char othername;		/* index into callbyvalue table */
 | 
						|
	} spectab[ ] =
 | 
						|
{
 | 
						|
	{ TYREAL,TYREAL,1,"r_int" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_int" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_nint" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_nint" },
 | 
						|
 | 
						|
	{ TYREAL,TYSHORT,1,"h_nint" },
 | 
						|
	{ TYREAL,TYLONG,1,"i_nint" },
 | 
						|
 | 
						|
	{ TYDREAL,TYSHORT,1,"h_dnnt" },
 | 
						|
	{ TYDREAL,TYLONG,1,"i_dnnt" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_abs" },
 | 
						|
	{ TYSHORT,TYSHORT,1,"h_abs" },
 | 
						|
	{ TYLONG,TYLONG,1,"i_abs" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_abs" },
 | 
						|
	{ TYCOMPLEX,TYREAL,1,"c_abs" },
 | 
						|
	{ TYDCOMPLEX,TYDREAL,1,"z_abs" },
 | 
						|
 | 
						|
	{ TYSHORT,TYSHORT,2,"h_mod" },
 | 
						|
	{ TYLONG,TYLONG,2,"i_mod" },
 | 
						|
	{ TYREAL,TYREAL,2,"r_mod" },
 | 
						|
	{ TYDREAL,TYDREAL,2,"d_mod" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,2,"r_sign" },
 | 
						|
	{ TYSHORT,TYSHORT,2,"h_sign" },
 | 
						|
	{ TYLONG,TYLONG,2,"i_sign" },
 | 
						|
	{ TYDREAL,TYDREAL,2,"d_sign" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,2,"r_dim" },
 | 
						|
	{ TYSHORT,TYSHORT,2,"h_dim" },
 | 
						|
	{ TYLONG,TYLONG,2,"i_dim" },
 | 
						|
	{ TYDREAL,TYDREAL,2,"d_dim" },
 | 
						|
 | 
						|
	{ TYREAL,TYDREAL,2,"d_prod" },
 | 
						|
 | 
						|
	{ TYCHAR,TYSHORT,1,"h_len" },
 | 
						|
	{ TYCHAR,TYLONG,1,"i_len" },
 | 
						|
 | 
						|
	{ TYCHAR,TYSHORT,2,"h_indx" },
 | 
						|
	{ TYCHAR,TYLONG,2,"i_indx" },
 | 
						|
 | 
						|
	{ TYCOMPLEX,TYREAL,1,"r_imag" },
 | 
						|
	{ TYDCOMPLEX,TYDREAL,1,"d_imag" },
 | 
						|
	{ TYCOMPLEX,TYCOMPLEX,1,"r_cnjg" },
 | 
						|
	{ TYDCOMPLEX,TYDCOMPLEX,1,"d_cnjg" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_sqrt", 1 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_sqrt", 1 },
 | 
						|
	{ TYCOMPLEX,TYCOMPLEX,1,"c_sqrt" },
 | 
						|
	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_sqrt" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_exp", 2 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_exp", 2 },
 | 
						|
	{ TYCOMPLEX,TYCOMPLEX,1,"c_exp" },
 | 
						|
	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_exp" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_log", 3 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_log", 3 },
 | 
						|
	{ TYCOMPLEX,TYCOMPLEX,1,"c_log" },
 | 
						|
	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_log" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_lg10" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_lg10" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_sin", 4 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_sin", 4 },
 | 
						|
	{ TYCOMPLEX,TYCOMPLEX,1,"c_sin" },
 | 
						|
	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_sin" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_cos", 5 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_cos", 5 },
 | 
						|
	{ TYCOMPLEX,TYCOMPLEX,1,"c_cos" },
 | 
						|
	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_cos" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_tan", 6 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_tan", 6 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_asin", 7 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_asin", 7 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_acos", 8 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_acos", 8 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_atan", 9 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_atan", 9 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,2,"r_atn2", 10 },
 | 
						|
	{ TYDREAL,TYDREAL,2,"d_atn2", 10 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_sinh", 11 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_sinh", 11 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_cosh", 12 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_cosh", 12 },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_tanh", 13 },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_tanh", 13 },
 | 
						|
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"hl_ge" },
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"l_ge" },
 | 
						|
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"hl_gt" },
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"l_gt" },
 | 
						|
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"hl_le" },
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"l_le" },
 | 
						|
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"hl_lt" },
 | 
						|
	{ TYCHAR,TYLOGICAL,2,"l_lt" },
 | 
						|
 | 
						|
	{ TYREAL,TYSHORT,1,"hr_expn" },
 | 
						|
	{ TYREAL,TYLONG,1,"ir_expn" },
 | 
						|
	{ TYDREAL,TYSHORT,1,"hd_expn" },
 | 
						|
	{ TYDREAL,TYLONG,1,"id_expn" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_absp" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_absp" },
 | 
						|
 | 
						|
	{ TYREAL,TYDREAL,1,"r_rrsp" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_rrsp" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,1,"r_frac" },
 | 
						|
	{ TYDREAL,TYDREAL,1,"d_frac" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,2,"r_make" },
 | 
						|
	{ TYDREAL,TYDREAL,2,"d_make" },
 | 
						|
 | 
						|
	{ TYREAL,TYREAL,2,"r_scal" },
 | 
						|
	{ TYDREAL,TYDREAL,2,"d_scal" },
 | 
						|
	{ 0 }
 | 
						|
} ;
 | 
						|
 | 
						|
#if 0
 | 
						|
LOCAL struct Incstblock
 | 
						|
	{
 | 
						|
	char atype;
 | 
						|
	char rtype;
 | 
						|
	char constno;
 | 
						|
	} consttab[ ] =
 | 
						|
{
 | 
						|
	{ TYSHORT, TYLONG, 0 },
 | 
						|
	{ TYLONG, TYLONG, 1 },
 | 
						|
	{ TYREAL, TYLONG, 2 },
 | 
						|
	{ TYDREAL, TYLONG, 3 },
 | 
						|
 | 
						|
	{ TYSHORT, TYLONG, 4 },
 | 
						|
	{ TYLONG, TYLONG, 5 },
 | 
						|
	{ TYREAL, TYLONG, 6 },
 | 
						|
	{ TYDREAL, TYLONG, 7 },
 | 
						|
 | 
						|
	{ TYREAL, TYLONG, 8 },
 | 
						|
	{ TYDREAL, TYLONG, 9 },
 | 
						|
 | 
						|
	{ TYREAL, TYLONG, 10 },
 | 
						|
	{ TYDREAL, TYLONG, 11 },
 | 
						|
 | 
						|
	{ TYREAL, TYREAL, 0 },
 | 
						|
	{ TYDREAL, TYDREAL, 1 },
 | 
						|
 | 
						|
	{ TYSHORT, TYLONG, 12 },
 | 
						|
	{ TYLONG, TYLONG, 13 },
 | 
						|
	{ TYREAL, TYREAL, 2 },
 | 
						|
	{ TYDREAL, TYDREAL, 3 },
 | 
						|
 | 
						|
	{ TYREAL, TYREAL, 4 },
 | 
						|
	{ TYDREAL, TYDREAL, 5 }
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
char *callbyvalue[ ] =
 | 
						|
	{0,
 | 
						|
	"sqrt",
 | 
						|
	"exp",
 | 
						|
	"log",
 | 
						|
	"sin",
 | 
						|
	"cos",
 | 
						|
	"tan",
 | 
						|
	"asin",
 | 
						|
	"acos",
 | 
						|
	"atan",
 | 
						|
	"atan2",
 | 
						|
	"sinh",
 | 
						|
	"cosh",
 | 
						|
	"tanh"
 | 
						|
	};
 | 
						|
 | 
						|
 void
 | 
						|
r8fix()	/* adjust tables for -r8 */
 | 
						|
{
 | 
						|
	register struct Intrblock *I;
 | 
						|
	register struct Specblock *S;
 | 
						|
 | 
						|
	for(I = intrtab; I->intrfname[0]; I++)
 | 
						|
		if (I->intrval.intrgroup != INTRGEN)
 | 
						|
		    switch(I->intrval.intrstuff) {
 | 
						|
			case TYREAL:
 | 
						|
				I->intrval.intrstuff = TYDREAL;
 | 
						|
				I->intrval.intrno = I->intrval.dblintrno;
 | 
						|
				break;
 | 
						|
			case TYCOMPLEX:
 | 
						|
				I->intrval.intrstuff = TYDCOMPLEX;
 | 
						|
				I->intrval.intrno = I->intrval.dblintrno;
 | 
						|
				I->intrval.dblcmplx = 1;
 | 
						|
			}
 | 
						|
 | 
						|
	for(S = spectab; S->atype; S++)
 | 
						|
	    switch(S->atype) {
 | 
						|
		case TYCOMPLEX:
 | 
						|
			S->atype = TYDCOMPLEX;
 | 
						|
			if (S->rtype == TYREAL)
 | 
						|
				S->rtype = TYDREAL;
 | 
						|
			else if (S->rtype == TYCOMPLEX)
 | 
						|
				S->rtype = TYDCOMPLEX;
 | 
						|
			switch(S->spxname[0]) {
 | 
						|
				case 'r':
 | 
						|
					S->spxname[0] = 'd';
 | 
						|
					break;
 | 
						|
				case 'c':
 | 
						|
					S->spxname[0] = 'z';
 | 
						|
					break;
 | 
						|
				default:
 | 
						|
					Fatal("r8fix bug");
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		case TYREAL:
 | 
						|
			S->atype = TYDREAL;
 | 
						|
			switch(S->rtype) {
 | 
						|
			    case TYREAL:
 | 
						|
				S->rtype = TYDREAL;
 | 
						|
				if (S->spxname[0] != 'r')
 | 
						|
					Fatal("r8fix bug");
 | 
						|
				S->spxname[0] = 'd';
 | 
						|
			    case TYDREAL:	/* d_prod */
 | 
						|
				break;
 | 
						|
 | 
						|
			    case TYSHORT:
 | 
						|
				if (!strcmp(S->spxname, "hr_expn"))
 | 
						|
					S->spxname[1] = 'd';
 | 
						|
				else if (!strcmp(S->spxname, "h_nint"))
 | 
						|
					strcpy(S->spxname, "h_dnnt");
 | 
						|
				else Fatal("r8fix bug");
 | 
						|
				break;
 | 
						|
 | 
						|
			    case TYLONG:
 | 
						|
				if (!strcmp(S->spxname, "ir_expn"))
 | 
						|
					S->spxname[1] = 'd';
 | 
						|
				else if (!strcmp(S->spxname, "i_nint"))
 | 
						|
					strcpy(S->spxname, "i_dnnt");
 | 
						|
				else Fatal("r8fix bug");
 | 
						|
				break;
 | 
						|
 | 
						|
			    default:
 | 
						|
				Fatal("r8fix bug");
 | 
						|
			    }
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
expptr intrcall(np, argsp, nargs)
 | 
						|
Namep np;
 | 
						|
struct Listblock *argsp;
 | 
						|
int nargs;
 | 
						|
{
 | 
						|
	int i, rettype;
 | 
						|
	Addrp ap;
 | 
						|
	register struct Specblock *sp;
 | 
						|
	register struct Chain *cp;
 | 
						|
	expptr Inline(), mkcxcon(), mkrealcon();
 | 
						|
	expptr q, ep;
 | 
						|
	int mtype;
 | 
						|
	int op;
 | 
						|
	int f1field, f2field, f3field;
 | 
						|
 | 
						|
	packed.ijunk = np->vardesc.varno;
 | 
						|
	f1field = packed.bits.f1;
 | 
						|
	f2field = packed.bits.f2;
 | 
						|
	f3field = packed.bits.f3;
 | 
						|
	if(nargs == 0)
 | 
						|
		goto badnargs;
 | 
						|
 | 
						|
	mtype = 0;
 | 
						|
	for(cp = argsp->listp ; cp ; cp = cp->nextp)
 | 
						|
	{
 | 
						|
		ep = (expptr)cp->datap;
 | 
						|
		if( ISCONST(ep) && ep->headblock.vtype==TYSHORT )
 | 
						|
			cp->datap = (char *) mkconv(tyint, ep);
 | 
						|
		mtype = maxtype(mtype, ep->headblock.vtype);
 | 
						|
	}
 | 
						|
 | 
						|
	switch(f1field)
 | 
						|
	{
 | 
						|
	case INTRBOOL:
 | 
						|
		op = f3field;
 | 
						|
		if( ! ONEOF(mtype, MSKINT|MSKLOGICAL) )
 | 
						|
			goto badtype;
 | 
						|
		if(op == OPBITNOT)
 | 
						|
		{
 | 
						|
			if(nargs != 1)
 | 
						|
				goto badnargs;
 | 
						|
			q = mkexpr(OPBITNOT, (expptr)argsp->listp->datap, ENULL);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			if(nargs != 2)
 | 
						|
				goto badnargs;
 | 
						|
			q = mkexpr(op, (expptr)argsp->listp->datap,
 | 
						|
			    		(expptr)argsp->listp->nextp->datap);
 | 
						|
		}
 | 
						|
		frchain( &(argsp->listp) );
 | 
						|
		free( (charptr) argsp);
 | 
						|
		return(q);
 | 
						|
 | 
						|
	case INTRCONV:
 | 
						|
		rettype = f2field;
 | 
						|
		if(rettype == TYLONG)
 | 
						|
			rettype = tyint;
 | 
						|
		if( ISCOMPLEX(rettype) && nargs==2)
 | 
						|
		{
 | 
						|
			expptr qr, qi;
 | 
						|
			qr = (expptr) argsp->listp->datap;
 | 
						|
			qi = (expptr) argsp->listp->nextp->datap;
 | 
						|
			if(ISCONST(qr) && ISCONST(qi))
 | 
						|
				q = mkcxcon(qr,qi);
 | 
						|
			else	q = mkexpr(OPCONV,mkconv(rettype-2,qr),
 | 
						|
			    mkconv(rettype-2,qi));
 | 
						|
		}
 | 
						|
		else if(nargs == 1) {
 | 
						|
			if (f3field && ((Exprp)argsp->listp->datap)->vtype
 | 
						|
					== TYDCOMPLEX)
 | 
						|
				rettype = TYDREAL;
 | 
						|
			q = mkconv(rettype+100, (expptr)argsp->listp->datap);
 | 
						|
			}
 | 
						|
		else goto badnargs;
 | 
						|
 | 
						|
		q->headblock.vtype = rettype;
 | 
						|
		frchain(&(argsp->listp));
 | 
						|
		free( (charptr) argsp);
 | 
						|
		return(q);
 | 
						|
 | 
						|
 | 
						|
#if 0
 | 
						|
	case INTRCNST:
 | 
						|
 | 
						|
/* Machine-dependent f77 stuff that f2c omits:
 | 
						|
 | 
						|
intcon contains
 | 
						|
	radix for short int
 | 
						|
	radix for long int
 | 
						|
	radix for single precision
 | 
						|
	radix for double precision
 | 
						|
	precision for short int
 | 
						|
	precision for long int
 | 
						|
	precision for single precision
 | 
						|
	precision for double precision
 | 
						|
	emin for single precision
 | 
						|
	emin for double precision
 | 
						|
	emax for single precision
 | 
						|
	emax for double prcision
 | 
						|
	largest short int
 | 
						|
	largest long int
 | 
						|
 | 
						|
realcon contains
 | 
						|
	tiny for single precision
 | 
						|
	tiny for double precision
 | 
						|
	huge for single precision
 | 
						|
	huge for double precision
 | 
						|
	mrsp (epsilon) for single precision
 | 
						|
	mrsp (epsilon) for double precision
 | 
						|
*/
 | 
						|
	{	register struct Incstblock *cstp;
 | 
						|
		extern ftnint intcon[14];
 | 
						|
		extern double realcon[6];
 | 
						|
 | 
						|
		cstp = consttab + f3field;
 | 
						|
		for(i=0 ; i<f2field ; ++i)
 | 
						|
			if(cstp->atype == mtype)
 | 
						|
				goto foundconst;
 | 
						|
			else
 | 
						|
				++cstp;
 | 
						|
		goto badtype;
 | 
						|
 | 
						|
foundconst:
 | 
						|
		switch(cstp->rtype)
 | 
						|
		{
 | 
						|
		case TYLONG:
 | 
						|
			return(mkintcon(intcon[cstp->constno]));
 | 
						|
 | 
						|
		case TYREAL:
 | 
						|
		case TYDREAL:
 | 
						|
			return(mkrealcon(cstp->rtype,
 | 
						|
			    realcon[cstp->constno]) );
 | 
						|
 | 
						|
		default:
 | 
						|
			Fatal("impossible intrinsic constant");
 | 
						|
		}
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	case INTRGEN:
 | 
						|
		sp = spectab + f3field;
 | 
						|
		if(no66flag)
 | 
						|
			if(sp->atype == mtype)
 | 
						|
				goto specfunct;
 | 
						|
			else err66("generic function");
 | 
						|
 | 
						|
		for(i=0; i<f2field ; ++i)
 | 
						|
			if(sp->atype == mtype)
 | 
						|
				goto specfunct;
 | 
						|
			else
 | 
						|
				++sp;
 | 
						|
		warn1 ("bad argument type to intrinsic %s", np->fvarname);
 | 
						|
 | 
						|
/* Made this a warning rather than an error so things like "log (5) ==>
 | 
						|
   log (5.0)" can be accommodated.  When none of these cases matches, the
 | 
						|
   argument is cast up to the first type in the spectab list; this first
 | 
						|
   type is assumed to be the "smallest" type, e.g. REAL before DREAL
 | 
						|
   before COMPLEX, before DCOMPLEX */
 | 
						|
 | 
						|
		sp = spectab + f3field;
 | 
						|
		mtype = sp -> atype;
 | 
						|
		goto specfunct;
 | 
						|
 | 
						|
	case INTRSPEC:
 | 
						|
		sp = spectab + f3field;
 | 
						|
specfunct:
 | 
						|
		if(tyint==TYLONG && ONEOF(sp->rtype,M(TYSHORT)|M(TYLOGICAL))
 | 
						|
		    && (sp+1)->atype==sp->atype)
 | 
						|
			++sp;
 | 
						|
 | 
						|
		if(nargs != sp->nargs)
 | 
						|
			goto badnargs;
 | 
						|
		if(mtype != sp->atype)
 | 
						|
			goto badtype;
 | 
						|
 | 
						|
/* NOTE!!  I moved fixargs (YES) into the ELSE branch so that constants in
 | 
						|
   the inline expression wouldn't get put into the constant table */
 | 
						|
 | 
						|
		fixargs (NO, argsp);
 | 
						|
		cast_args (mtype, argsp -> listp);
 | 
						|
 | 
						|
		if(q = Inline((int)(sp-spectab), mtype, argsp->listp))
 | 
						|
		{
 | 
						|
			frchain( &(argsp->listp) );
 | 
						|
			free( (charptr) argsp);
 | 
						|
		} else {
 | 
						|
 | 
						|
		    if(sp->othername) {
 | 
						|
			/* C library routines that return double... */
 | 
						|
			/* sp->rtype might be TYREAL */
 | 
						|
			ap = builtin(sp->rtype,
 | 
						|
				callbyvalue[sp->othername], 1);
 | 
						|
			q = fixexpr((Exprp)
 | 
						|
				mkexpr(OPCCALL, (expptr)ap, (expptr)argsp) );
 | 
						|
		    } else {
 | 
						|
			fixargs(YES, argsp);
 | 
						|
			ap = builtin(sp->rtype, sp->spxname, 0);
 | 
						|
			q = fixexpr((Exprp)
 | 
						|
				mkexpr(OPCALL, (expptr)ap, (expptr)argsp) );
 | 
						|
		    } /* else */
 | 
						|
		} /* else */
 | 
						|
		return(q);
 | 
						|
 | 
						|
	case INTRMIN:
 | 
						|
	case INTRMAX:
 | 
						|
		if(nargs < 2)
 | 
						|
			goto badnargs;
 | 
						|
		if( ! ONEOF(mtype, MSKINT|MSKREAL) )
 | 
						|
			goto badtype;
 | 
						|
		argsp->vtype = mtype;
 | 
						|
		q = mkexpr( (f1field==INTRMIN ? OPMIN : OPMAX), (expptr)argsp, ENULL);
 | 
						|
 | 
						|
		q->headblock.vtype = mtype;
 | 
						|
		rettype = f2field;
 | 
						|
		if(rettype == TYLONG)
 | 
						|
			rettype = tyint;
 | 
						|
		else if(rettype == TYUNKNOWN)
 | 
						|
			rettype = mtype;
 | 
						|
		return( mkconv(rettype, q) );
 | 
						|
 | 
						|
	default:
 | 
						|
		fatali("intrcall: bad intrgroup %d", f1field);
 | 
						|
	}
 | 
						|
badnargs:
 | 
						|
	errstr("bad number of arguments to intrinsic %s", np->fvarname);
 | 
						|
	goto bad;
 | 
						|
 | 
						|
badtype:
 | 
						|
	errstr("bad argument type to intrinsic %s", np->fvarname);
 | 
						|
 | 
						|
bad:
 | 
						|
	return( errnode() );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
intrfunct(s)
 | 
						|
char *s;
 | 
						|
{
 | 
						|
	register struct Intrblock *p;
 | 
						|
 | 
						|
	for(p = intrtab; p->intrval.intrgroup!=INTREND ; ++p)
 | 
						|
	{
 | 
						|
		if( !strcmp(s, p->intrfname) )
 | 
						|
		{
 | 
						|
			packed.bits.f1 = p->intrval.intrgroup;
 | 
						|
			packed.bits.f2 = p->intrval.intrstuff;
 | 
						|
			packed.bits.f3 = p->intrval.intrno;
 | 
						|
			packed.bits.f4 = p->intrval.dblcmplx;
 | 
						|
			return(packed.ijunk);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Addrp intraddr(np)
 | 
						|
Namep np;
 | 
						|
{
 | 
						|
	Addrp q;
 | 
						|
	register struct Specblock *sp;
 | 
						|
	int f3field;
 | 
						|
 | 
						|
	if(np->vclass!=CLPROC || np->vprocclass!=PINTRINSIC)
 | 
						|
		fatalstr("intraddr: %s is not intrinsic", np->fvarname);
 | 
						|
	packed.ijunk = np->vardesc.varno;
 | 
						|
	f3field = packed.bits.f3;
 | 
						|
 | 
						|
	switch(packed.bits.f1)
 | 
						|
	{
 | 
						|
	case INTRGEN:
 | 
						|
		/* imag, log, and log10 arent specific functions */
 | 
						|
		if(f3field==31 || f3field==43 || f3field==47)
 | 
						|
			goto bad;
 | 
						|
 | 
						|
	case INTRSPEC:
 | 
						|
		sp = spectab + f3field;
 | 
						|
		if(tyint==TYLONG && sp->rtype==TYSHORT)
 | 
						|
			++sp;
 | 
						|
		q = builtin(sp->rtype, sp->spxname,
 | 
						|
			sp->othername ? 1 : 0);
 | 
						|
		return(q);
 | 
						|
 | 
						|
	case INTRCONV:
 | 
						|
	case INTRMIN:
 | 
						|
	case INTRMAX:
 | 
						|
	case INTRBOOL:
 | 
						|
	case INTRCNST:
 | 
						|
bad:
 | 
						|
		errstr("cannot pass %s as actual", np->fvarname);
 | 
						|
		return((Addrp)errnode());
 | 
						|
	}
 | 
						|
	fatali("intraddr: impossible f1=%d\n", (int) packed.bits.f1);
 | 
						|
	/* NOT REACHED */ return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void cast_args (maxtype, args)
 | 
						|
int maxtype;
 | 
						|
chainp args;
 | 
						|
{
 | 
						|
    for (; args; args = args -> nextp) {
 | 
						|
	expptr e = (expptr) args->datap;
 | 
						|
	if (e -> headblock.vtype != maxtype)
 | 
						|
	    if (e -> tag == TCONST)
 | 
						|
		args->datap = (char *) mkconv(maxtype, e);
 | 
						|
	    else {
 | 
						|
		Addrp temp = mktmp(maxtype, ENULL);
 | 
						|
 | 
						|
		puteq(cpexpr((expptr)temp), e);
 | 
						|
		args->datap = (char *)temp;
 | 
						|
	    } /* else */
 | 
						|
    } /* for */
 | 
						|
} /* cast_args */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
expptr Inline(fno, type, args)
 | 
						|
int fno;
 | 
						|
int type;
 | 
						|
struct Chain *args;
 | 
						|
{
 | 
						|
	register expptr q, t, t1;
 | 
						|
 | 
						|
	switch(fno)
 | 
						|
	{
 | 
						|
	case 8:	/* real abs */
 | 
						|
	case 9:	/* short int abs */
 | 
						|
	case 10:	/* long int abs */
 | 
						|
	case 11:	/* double precision abs */
 | 
						|
		if( addressable(q = (expptr) args->datap) )
 | 
						|
		{
 | 
						|
			t = q;
 | 
						|
			q = NULL;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			t = (expptr) mktmp(type,ENULL);
 | 
						|
		t1 = mkexpr(type == TYREAL && forcedouble ? OPDABS : OPABS,
 | 
						|
			cpexpr(t), ENULL);
 | 
						|
		if(q)
 | 
						|
			t1 = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(t),q), t1);
 | 
						|
		frexpr(t);
 | 
						|
		return(t1);
 | 
						|
 | 
						|
	case 26:	/* dprod */
 | 
						|
		q = mkexpr(OPSTAR, mkconv(TYDREAL,(expptr)args->datap),
 | 
						|
			(expptr)args->nextp->datap);
 | 
						|
		return(q);
 | 
						|
 | 
						|
	case 27:	/* len of character string */
 | 
						|
		q = (expptr) cpexpr(((tagptr)args->datap)->headblock.vleng);
 | 
						|
		frexpr((expptr)args->datap);
 | 
						|
		return(q);
 | 
						|
 | 
						|
	case 14:	/* half-integer mod */
 | 
						|
	case 15:	/* mod */
 | 
						|
		return mkexpr(OPMOD, (expptr) args->datap,
 | 
						|
		    		(expptr) args->nextp->datap);
 | 
						|
	}
 | 
						|
	return(NULL);
 | 
						|
}
 |