xref: /original-bsd/usr.bin/f77/pass1.vax/intr.c (revision 92c664ec)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)intr.c	5.2 (Berkeley) 08/29/85";
9 #endif not lint
10 
11 /*
12  * intr.c
13  *
14  * Routines for handling intrinsic functions, f77 compiler pass 1, 4.2 BSD.
15  *
16  * University of Utah CS Dept modification history:
17  *
18  * $Log:	intr.c,v $
19  * Revision 5.2  85/08/10  04:39:23  donn
20  * Various changes from Jerry Berkman.  We now call the new builtin log10()
21  * instead of the f77 library emulations; we figure out that builtins will
22  * return type double instead of type float; we get rid of lots of
23  * undocumented material; we ifdef 66 code and handle -r8/double flag.
24  *
25  * Revision 5.1  85/08/10  03:47:37  donn
26  * 4.3 alpha
27  *
28  * Revision 1.4  85/02/22  00:54:59  donn
29  * Mark intrinsic functions as having storage class STGINTR.  builtin()
30  * always returns STGEXT nodes.  Notice that the reference to the function
31  * in the external symbol table still uses STGEXT...  I hope this is right.
32  *
33  * Revision 1.3  85/01/15  21:05:40  donn
34  * Changes to distinguish explicit from implicit conversions with intrconv().
35  *
36  * Revision 1.2  84/12/15  01:02:33  donn
37  * Added a case for an integer*4 result from len() in inline().  Previously
38  * only -i2 provoked len() inline, sigh.
39  *
40  */
41 
42 #include "defs.h"
43 
44 extern ftnint intcon[14];
45 extern double realcon[6];
46 
47 union
48 	{
49 	int ijunk;
50 	struct Intrpacked bits;
51 	} packed;
52 
53 struct Intrbits
54 	{
55 	int intrgroup /* :3 */;
56 	int intrstuff /* result type or number of specifics */;
57 	int intrno /* :7 */;
58 	};
59 
60 LOCAL struct Intrblock
61 	{
62 	char intrfname[VL];
63 	struct Intrbits intrval;
64 	} intrtab[ ] =
65 {
66 "int", 		{ INTRCONV, TYLONG },
67 "real", 	{ INTRCONV, TYREAL },
68 "dble", 	{ INTRCONV, TYDREAL },
69 "dreal",	{ INTRCONV, TYDREAL },
70 "cmplx", 	{ INTRCONV, TYCOMPLEX },
71 "dcmplx", 	{ INTRCONV, TYDCOMPLEX },
72 "ifix", 	{ INTRCONV, TYLONG },
73 "idint", 	{ INTRCONV, TYLONG },
74 "float", 	{ INTRCONV, TYREAL },
75 "dfloat",	{ INTRCONV, TYDREAL },
76 "sngl", 	{ INTRCONV, TYREAL },
77 "ichar", 	{ INTRCONV, TYLONG },
78 "char", 	{ INTRCONV, TYCHAR },
79 
80 "max", 		{ INTRMAX, TYUNKNOWN },
81 "max0", 	{ INTRMAX, TYLONG },
82 "amax0", 	{ INTRMAX, TYREAL },
83 "max1", 	{ INTRMAX, TYLONG },
84 "amax1", 	{ INTRMAX, TYREAL },
85 "dmax1", 	{ INTRMAX, TYDREAL },
86 
87 "and",		{ INTRBOOL, TYUNKNOWN, OPBITAND },
88 "or",		{ INTRBOOL, TYUNKNOWN, OPBITOR },
89 "xor",		{ INTRBOOL, TYUNKNOWN, OPBITXOR },
90 "not",		{ INTRBOOL, TYUNKNOWN, OPBITNOT },
91 "lshift",	{ INTRBOOL, TYUNKNOWN, OPLSHIFT },
92 "rshift",	{ INTRBOOL, TYUNKNOWN, OPRSHIFT },
93 
94 "min", 		{ INTRMIN, TYUNKNOWN },
95 "min0", 	{ INTRMIN, TYLONG },
96 "amin0", 	{ INTRMIN, TYREAL },
97 "min1", 	{ INTRMIN, TYLONG },
98 "amin1", 	{ INTRMIN, TYREAL },
99 "dmin1", 	{ INTRMIN, TYDREAL },
100 
101 "aint", 	{ INTRGEN, 2, 0 },
102 "dint", 	{ INTRSPEC, TYDREAL, 1 },
103 
104 "anint", 	{ INTRGEN, 2, 2 },
105 "dnint", 	{ INTRSPEC, TYDREAL, 3 },
106 
107 "nint", 	{ INTRGEN, 4, 4 },
108 "idnint", 	{ INTRGEN, 2, 6 },
109 
110 "abs", 		{ INTRGEN, 6, 8 },
111 "iabs", 	{ INTRGEN, 2, 9 },
112 "dabs", 	{ INTRSPEC, TYDREAL, 11 },
113 "cabs", 	{ INTRSPEC, TYREAL, 12 },
114 "zabs", 	{ INTRSPEC, TYDREAL, 13 },
115 "cdabs",	{ INTRSPEC, TYDREAL, 13 },
116 
117 "mod", 		{ INTRGEN, 4, 14 },
118 "amod", 	{ INTRSPEC, TYREAL, 16 },
119 "dmod", 	{ INTRSPEC, TYDREAL, 17 },
120 
121 "sign", 	{ INTRGEN, 4, 18 },
122 "isign", 	{ INTRGEN, 2, 19 },
123 "dsign", 	{ INTRSPEC, TYDREAL, 21 },
124 
125 "dim", 		{ INTRGEN, 4, 22 },
126 "idim", 	{ INTRGEN, 2, 23 },
127 "ddim", 	{ INTRSPEC, TYDREAL, 25 },
128 
129 "dprod", 	{ INTRSPEC, TYDREAL, 26 },
130 
131 "len", 		{ INTRSPEC, TYLONG, 27 },
132 "index", 	{ INTRSPEC, TYLONG, 29 },
133 
134 "imag", 	{ INTRGEN, 2, 31 },
135 "aimag", 	{ INTRSPEC, TYREAL, 31 },
136 "dimag", 	{ INTRSPEC, TYDREAL, 32 },
137 
138 "conjg", 	{ INTRGEN, 2, 33 },
139 "dconjg", 	{ INTRSPEC, TYDCOMPLEX, 34 },
140 
141 "sqrt", 	{ INTRGEN, 4, 35 },
142 "dsqrt", 	{ INTRSPEC, TYDREAL, 36 },
143 "csqrt", 	{ INTRSPEC, TYCOMPLEX, 37 },
144 "zsqrt", 	{ INTRSPEC, TYDCOMPLEX, 38 },
145 "cdsqrt",	{ INTRSPEC, TYDCOMPLEX, 38 },
146 
147 "exp", 		{ INTRGEN, 4, 39 },
148 "dexp", 	{ INTRSPEC, TYDREAL, 40 },
149 "cexp", 	{ INTRSPEC, TYCOMPLEX, 41 },
150 "zexp", 	{ INTRSPEC, TYDCOMPLEX, 42 },
151 "cdexp",	{ INTRSPEC, TYDCOMPLEX, 42 },
152 
153 "log", 		{ INTRGEN, 4, 43 },
154 "alog", 	{ INTRSPEC, TYREAL, 43 },
155 "dlog", 	{ INTRSPEC, TYDREAL, 44 },
156 "clog", 	{ INTRSPEC, TYCOMPLEX, 45 },
157 "zlog", 	{ INTRSPEC, TYDCOMPLEX, 46 },
158 "cdlog",	{ INTRSPEC, TYDCOMPLEX, 46 },
159 
160 "log10", 	{ INTRGEN, 2, 47 },
161 "alog10", 	{ INTRSPEC, TYREAL, 47 },
162 "dlog10", 	{ INTRSPEC, TYDREAL, 48 },
163 
164 "sin", 		{ INTRGEN, 4, 49 },
165 "dsin", 	{ INTRSPEC, TYDREAL, 50 },
166 "csin", 	{ INTRSPEC, TYCOMPLEX, 51 },
167 "zsin", 	{ INTRSPEC, TYDCOMPLEX, 52 },
168 "cdsin",	{ INTRSPEC, TYDCOMPLEX, 52 },
169 
170 "cos", 		{ INTRGEN, 4, 53 },
171 "dcos", 	{ INTRSPEC, TYDREAL, 54 },
172 "ccos", 	{ INTRSPEC, TYCOMPLEX, 55 },
173 "zcos", 	{ INTRSPEC, TYDCOMPLEX, 56 },
174 "cdcos",	{ INTRSPEC, TYDCOMPLEX, 56 },
175 
176 "tan", 		{ INTRGEN, 2, 57 },
177 "dtan", 	{ INTRSPEC, TYDREAL, 58 },
178 
179 "asin", 	{ INTRGEN, 2, 59 },
180 "dasin", 	{ INTRSPEC, TYDREAL, 60 },
181 
182 "acos", 	{ INTRGEN, 2, 61 },
183 "dacos", 	{ INTRSPEC, TYDREAL, 62 },
184 
185 "atan", 	{ INTRGEN, 2, 63 },
186 "datan", 	{ INTRSPEC, TYDREAL, 64 },
187 
188 "atan2", 	{ INTRGEN, 2, 65 },
189 "datan2", 	{ INTRSPEC, TYDREAL, 66 },
190 
191 "sinh", 	{ INTRGEN, 2, 67 },
192 "dsinh", 	{ INTRSPEC, TYDREAL, 68 },
193 
194 "cosh", 	{ INTRGEN, 2, 69 },
195 "dcosh", 	{ INTRSPEC, TYDREAL, 70 },
196 
197 "tanh", 	{ INTRGEN, 2, 71 },
198 "dtanh", 	{ INTRSPEC, TYDREAL, 72 },
199 
200 "lge",		{ INTRSPEC, TYLOGICAL, 73},
201 "lgt",		{ INTRSPEC, TYLOGICAL, 75},
202 "lle",		{ INTRSPEC, TYLOGICAL, 77},
203 "llt",		{ INTRSPEC, TYLOGICAL, 79},
204 
205 "",		{ INTREND, 0, 0} };
206 
207 
208 LOCAL struct Specblock
209 	{
210 	char atype;
211 	char rtype;
212 	char nargs;
213 	char spxname[XL];
214 	char othername;	/* index into callbyvalue table */
215 	} spectab[ ] =
216 {
217 	{ TYREAL,TYREAL,1,"r_int" },
218 	{ TYDREAL,TYDREAL,1,"d_int" },
219 
220 	{ TYREAL,TYREAL,1,"r_nint" },
221 	{ TYDREAL,TYDREAL,1,"d_nint" },
222 
223 	{ TYREAL,TYSHORT,1,"h_nint" },
224 	{ TYREAL,TYLONG,1,"i_nint" },
225 
226 	{ TYDREAL,TYSHORT,1,"h_dnnt" },
227 	{ TYDREAL,TYLONG,1,"i_dnnt" },
228 
229 	{ TYREAL,TYREAL,1,"r_abs" },
230 	{ TYSHORT,TYSHORT,1,"h_abs" },
231 	{ TYLONG,TYLONG,1,"i_abs" },
232 	{ TYDREAL,TYDREAL,1,"d_abs" },
233 	{ TYCOMPLEX,TYREAL,1,"c_abs" },
234 	{ TYDCOMPLEX,TYDREAL,1,"z_abs" },
235 
236 	{ TYSHORT,TYSHORT,2,"h_mod" },
237 	{ TYLONG,TYLONG,2,"i_mod" },
238 	{ TYREAL,TYREAL,2,"r_mod" },
239 	{ TYDREAL,TYDREAL,2,"d_mod" },
240 
241 	{ TYREAL,TYREAL,2,"r_sign" },
242 	{ TYSHORT,TYSHORT,2,"h_sign" },
243 	{ TYLONG,TYLONG,2,"i_sign" },
244 	{ TYDREAL,TYDREAL,2,"d_sign" },
245 
246 	{ TYREAL,TYREAL,2,"r_dim" },
247 	{ TYSHORT,TYSHORT,2,"h_dim" },
248 	{ TYLONG,TYLONG,2,"i_dim" },
249 	{ TYDREAL,TYDREAL,2,"d_dim" },
250 
251 	{ TYREAL,TYDREAL,2,"d_prod" },
252 
253 	{ TYCHAR,TYSHORT,1,"h_len" },
254 	{ TYCHAR,TYLONG,1,"i_len" },
255 
256 	{ TYCHAR,TYSHORT,2,"h_indx" },
257 	{ TYCHAR,TYLONG,2,"i_indx" },
258 
259 	{ TYCOMPLEX,TYREAL,1,"r_imag" },
260 	{ TYDCOMPLEX,TYDREAL,1,"d_imag" },
261 	{ TYCOMPLEX,TYCOMPLEX,1,"r_cnjg" },
262 	{ TYDCOMPLEX,TYDCOMPLEX,1,"d_cnjg" },
263 
264 	{ TYREAL,TYREAL,1,"r_sqrt", 1 },
265 	{ TYDREAL,TYDREAL,1,"d_sqrt", 1 },
266 	{ TYCOMPLEX,TYCOMPLEX,1,"c_sqrt" },
267 	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_sqrt" },
268 
269 	{ TYREAL,TYREAL,1,"r_exp", 2 },
270 	{ TYDREAL,TYDREAL,1,"d_exp", 2 },
271 	{ TYCOMPLEX,TYCOMPLEX,1,"c_exp" },
272 	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_exp" },
273 
274 	{ TYREAL,TYREAL,1,"r_log", 3 },
275 	{ TYDREAL,TYDREAL,1,"d_log", 3 },
276 	{ TYCOMPLEX,TYCOMPLEX,1,"c_log" },
277 	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_log" },
278 
279 	{ TYREAL,TYREAL,1,"r_lg10", 14 },
280 	{ TYDREAL,TYDREAL,1,"d_lg10", 14 },
281 
282 	{ TYREAL,TYREAL,1,"r_sin", 4 },
283 	{ TYDREAL,TYDREAL,1,"d_sin", 4 },
284 	{ TYCOMPLEX,TYCOMPLEX,1,"c_sin" },
285 	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_sin" },
286 
287 	{ TYREAL,TYREAL,1,"r_cos", 5 },
288 	{ TYDREAL,TYDREAL,1,"d_cos", 5 },
289 	{ TYCOMPLEX,TYCOMPLEX,1,"c_cos" },
290 	{ TYDCOMPLEX,TYDCOMPLEX,1,"z_cos" },
291 
292 	{ TYREAL,TYREAL,1,"r_tan", 6 },
293 	{ TYDREAL,TYDREAL,1,"d_tan", 6 },
294 
295 	{ TYREAL,TYREAL,1,"r_asin", 7 },
296 	{ TYDREAL,TYDREAL,1,"d_asin", 7 },
297 
298 	{ TYREAL,TYREAL,1,"r_acos", 8 },
299 	{ TYDREAL,TYDREAL,1,"d_acos", 8 },
300 
301 	{ TYREAL,TYREAL,1,"r_atan", 9 },
302 	{ TYDREAL,TYDREAL,1,"d_atan", 9 },
303 
304 	{ TYREAL,TYREAL,2,"r_atn2", 10 },
305 	{ TYDREAL,TYDREAL,2,"d_atn2", 10 },
306 
307 	{ TYREAL,TYREAL,1,"r_sinh", 11 },
308 	{ TYDREAL,TYDREAL,1,"d_sinh", 11 },
309 
310 	{ TYREAL,TYREAL,1,"r_cosh", 12 },
311 	{ TYDREAL,TYDREAL,1,"d_cosh", 12 },
312 
313 	{ TYREAL,TYREAL,1,"r_tanh", 13 },
314 	{ TYDREAL,TYDREAL,1,"d_tanh", 13 },
315 
316 	{ TYCHAR,TYLOGICAL,2,"hl_ge" },
317 	{ TYCHAR,TYLOGICAL,2,"l_ge" },
318 
319 	{ TYCHAR,TYLOGICAL,2,"hl_gt" },
320 	{ TYCHAR,TYLOGICAL,2,"l_gt" },
321 
322 	{ TYCHAR,TYLOGICAL,2,"hl_le" },
323 	{ TYCHAR,TYLOGICAL,2,"l_le" },
324 
325 	{ TYCHAR,TYLOGICAL,2,"hl_lt" },
326 	{ TYCHAR,TYLOGICAL,2,"l_lt" },
327 
328 	{ TYDREAL,TYDREAL,2,"d_dprod"}  /* dprod() with dblflag */
329 } ;
330 
331 char callbyvalue[ ][XL] =
332 	{
333 	"sqrt",
334 	"exp",
335 	"log",
336 	"sin",
337 	"cos",
338 	"tan",
339 	"asin",
340 	"acos",
341 	"atan",
342 	"atan2",
343 	"sinh",
344 	"cosh",
345 	"tanh",
346 	"log10"
347 	};
348 
349 expptr intrcall(np, argsp, nargs)
350 Namep np;
351 struct Listblock *argsp;
352 int nargs;
353 {
354 int i, rettype;
355 Addrp ap;
356 register struct Specblock *sp;
357 register struct Chain *cp;
358 expptr inline(), mkcxcon(), mkrealcon();
359 expptr q, ep;
360 int mtype;
361 int op;
362 int f1field, f2field, f3field;
363 
364 packed.ijunk = np->vardesc.varno;
365 f1field = packed.bits.f1;
366 f2field = packed.bits.f2;
367 f3field = packed.bits.f3;
368 if(nargs == 0)
369 	goto badnargs;
370 
371 mtype = 0;
372 for(cp = argsp->listp ; cp ; cp = cp->nextp)
373 	{
374 /* TEMPORARY */ ep = (expptr) (cp->datap);
375 /* TEMPORARY */	if( ISCONST(ep) && ep->headblock.vtype==TYSHORT )
376 /* TEMPORARY */		cp->datap = (tagptr) mkconv(tyint, ep);
377 	mtype = maxtype(mtype, ep->headblock.vtype);
378 	}
379 
380 switch(f1field)
381 	{
382 	case INTRBOOL:
383 		op = f3field;
384 		if( ! ONEOF(mtype, MSKINT|MSKLOGICAL) )
385 			goto badtype;
386 		if(op == OPBITNOT)
387 			{
388 			if(nargs != 1)
389 				goto badnargs;
390 			q = mkexpr(OPBITNOT, argsp->listp->datap, ENULL);
391 			}
392 		else
393 			{
394 			if(nargs != 2)
395 				goto badnargs;
396 			q = mkexpr(op, argsp->listp->datap,
397 				argsp->listp->nextp->datap);
398 			}
399 		frchain( &(argsp->listp) );
400 		free( (charptr) argsp);
401 		return(q);
402 
403 	case INTRCONV:
404 		if (nargs == 1)
405 			{
406 			if(argsp->listp->datap->headblock.vtype == TYERROR)
407 				{
408 				free( (charptr) argsp->listp->datap);
409 				frchain( &(argsp->listp) );
410 				free( (charptr) argsp);
411 				return( errnode() );
412 				}
413 			}
414 		else if (nargs == 2)
415 			{
416 			if(argsp->listp->nextp->datap->headblock.vtype ==
417 				TYERROR ||
418 				argsp->listp->datap->headblock.vtype == TYERROR)
419 				{
420 				free( (charptr) argsp->listp->nextp->datap);
421 				free( (charptr) argsp->listp->datap);
422 				frchain( &(argsp->listp) );
423 				free( (charptr) argsp);
424 				return( errnode() );
425 				}
426 			}
427 		rettype = f2field;
428 		if( ISCOMPLEX(rettype) && nargs==2)
429 			{
430 			expptr qr, qi;
431 			if(dblflag) rettype = TYDCOMPLEX;
432 			qr = (expptr) (argsp->listp->datap);
433 			qi = (expptr) (argsp->listp->nextp->datap);
434 			if(ISCONST(qr) && ISCONST(qi))
435 				q = mkcxcon(qr,qi);
436 			else	q = mkexpr(OPCONV,intrconv(rettype-2,qr),
437 					intrconv(rettype-2,qi));
438 			}
439 		else if(nargs == 1)
440 			{
441 			if(rettype == TYLONG) rettype = tyint;
442 			else if( dblflag )
443 				{
444 				if ( rettype == TYREAL )
445 					rettype = TYDREAL;
446 				else if( rettype == TYCOMPLEX )
447 					rettype = TYDCOMPLEX;
448 				}
449 			q = intrconv(rettype, argsp->listp->datap);
450 			}
451 		else goto badnargs;
452 
453 		q->headblock.vtype = rettype;
454 		frchain(&(argsp->listp));
455 		free( (charptr) argsp);
456 		return(q);
457 
458 	case INTRGEN:
459 		sp = spectab + f3field;
460 #ifdef ONLY66
461 		if(no66flag)
462 			if(sp->atype == mtype)
463 				goto specfunct;
464 			else err66("generic function");
465 #endif
466 
467 		for(i=0; i<f2field ; ++i)
468 			if(sp->atype == mtype)
469 				goto specfunct;
470 			else
471 				++sp;
472 		goto badtype;
473 
474 	case INTRSPEC:
475 		sp = spectab + f3field;
476 		if( dblflag )
477 			{
478 			/* convert specific complex functions to double complex:
479 			 *	 cabs,csqrt,cexp,clog,csin,ccos, aimag
480 			 * and convert real specifics to double:
481 			 *	 amod,alog,alog10
482 			 * (sqrt,cos,sin,... o.k. since go through INTRGEN)
483 			 */
484 			if( (sp->atype==TYCOMPLEX && (sp+1)->atype==TYDCOMPLEX)
485 				||(sp->atype==TYREAL && (sp+1)->atype==TYDREAL))
486 					sp++;
487 			}
488 	specfunct:
489 		if(tyint==TYLONG && ONEOF(sp->rtype,M(TYSHORT)|M(TYLOGICAL))
490 			&& (sp+1)->atype==sp->atype)
491 				++sp;
492 
493 		if(nargs != sp->nargs)
494 			goto badnargs;
495 		if(mtype != sp->atype
496 			&& (!dblflag || f3field != 26 || mtype != TYDREAL ) )
497 				goto badtype;
498 		fixargs(YES, argsp);
499 		if(q = inline(sp-spectab, mtype, argsp->listp))
500 			{
501 			frchain( &(argsp->listp) );
502 			free( (charptr) argsp);
503 			}
504 		else if(sp->othername)
505 			{
506 			ap = builtin(TYDREAL,
507 				varstr(XL, callbyvalue[sp->othername-1]) );
508 			ap->vstg = STGINTR;
509 			q = fixexpr( mkexpr(OPCCALL, ap, argsp) );
510 			if( sp->rtype != TYDREAL )
511 				q = mkconv( sp->rtype, q );
512 			}
513 		else
514 			{
515 			ap = builtin(sp->rtype, varstr(XL, sp->spxname) );
516 			ap->vstg = STGINTR;
517 			q = fixexpr( mkexpr(OPCALL, ap, argsp) );
518 			}
519 		return(q);
520 
521 	case INTRMIN:
522 	case INTRMAX:
523 		if(nargs < 2)
524 			goto badnargs;
525 		if( ! ONEOF(mtype, MSKINT|MSKREAL) )
526 			goto badtype;
527 		argsp->vtype = mtype;
528 		q = mkexpr( (f1field==INTRMIN ? OPMIN : OPMAX), argsp, ENULL);
529 
530 		q->headblock.vtype = mtype;
531 		rettype = f2field;
532 		if(rettype == TYLONG)
533 			rettype = tyint;
534 		else if(rettype == TYUNKNOWN)
535 			rettype = mtype;
536 		else if( dblflag && rettype == TYREAL )
537 			rettype = TYDREAL;
538 		return( intrconv(rettype, q) );
539 
540 	default:
541 		fatali("intrcall: bad intrgroup %d", f1field);
542 	}
543 badnargs:
544 	errstr("bad number of arguments to intrinsic %s",
545 		varstr(VL,np->varname) );
546 	goto bad;
547 
548 badtype:
549 	errstr("bad argument type to intrinsic %s", varstr(VL, np->varname) );
550 
551 bad:
552 	return( errnode() );
553 }
554 
555 
556 
557 
558 intrfunct(s)
559 char s[VL];
560 {
561 register struct Intrblock *p;
562 char nm[VL];
563 register int i;
564 
565 for(i = 0 ; i<VL ; ++s)
566 	nm[i++] = (*s==' ' ? '\0' : *s);
567 
568 for(p = intrtab; p->intrval.intrgroup!=INTREND ; ++p)
569 	{
570 	if( eqn(VL, nm, p->intrfname) )
571 		{
572 		packed.bits.f1 = p->intrval.intrgroup;
573 		packed.bits.f2 = p->intrval.intrstuff;
574 		packed.bits.f3 = p->intrval.intrno;
575 		return(packed.ijunk);
576 		}
577 	}
578 
579 return(0);
580 }
581 
582 
583 
584 
585 
586 Addrp intraddr(np)
587 Namep np;
588 {
589 Addrp q;
590 register struct Specblock *sp;
591 int f3field;
592 
593 if(np->vclass!=CLPROC || np->vprocclass!=PINTRINSIC)
594 	fatalstr("intraddr: %s is not intrinsic", varstr(VL,np->varname));
595 packed.ijunk = np->vardesc.varno;
596 f3field = packed.bits.f3;
597 
598 switch(packed.bits.f1)
599 	{
600 	case INTRGEN:
601 		/* imag, log, and log10 arent specific functions */
602 		if(f3field==31 || f3field==43 || f3field==47)
603 			goto bad;
604 
605 	case INTRSPEC:
606 		sp = spectab + f3field;
607 		if( dblflag )
608 			{
609 			if((sp->atype==TYCOMPLEX && (sp+1)->atype==TYDCOMPLEX)
610 				||(sp->atype==TYREAL && (sp+1)->atype==TYDREAL))
611 					sp++;
612 			else if( f3field==4 )
613 					sp += 2;  /* h_nint -> h_dnnt */
614 			else if( f3field==8 || f3field==18 || f3field==22)
615 					sp += 3;  /* r_{abs,sign,dim} ->d_... */
616 			else if( f3field==26 )
617 					sp = spectab + 81; /* dprod */
618 
619 			}
620 		if(tyint==TYLONG && sp->rtype==TYSHORT)
621 			++sp;
622 		q = builtin(sp->rtype, varstr(XL,sp->spxname) );
623 		q->vstg = STGINTR;
624 		return(q);
625 
626 	case INTRCONV:
627 	case INTRMIN:
628 	case INTRMAX:
629 	case INTRBOOL:
630 	bad:
631 		errstr("cannot pass %s as actual",
632 			varstr(VL,np->varname));
633 		return( (Addrp) errnode() );
634 	}
635 fatali("intraddr: impossible f1=%d\n", (int) packed.bits.f1);
636 /* NOTREACHED */
637 }
638 
639 
640 
641 
642 
643 expptr inline(fno, type, args)
644 int fno;
645 int type;
646 struct Chain *args;
647 {
648 register expptr q, t, t1;
649 
650 switch(fno)
651 	{
652 	case 8:	/* real abs */
653 	case 9:	/* short int abs */
654 	case 10:	/* long int abs */
655 	case 11:	/* double precision abs */
656 		if( addressable(q = (expptr) (args->datap)) )
657 			{
658 			t = q;
659 			q = NULL;
660 			}
661 		else
662 			t = (expptr) mktemp(type,PNULL);
663 		t1 = mkexpr(OPQUEST,
664 			mkexpr(OPLE, intrconv(type,ICON(0)), cpexpr(t)),
665 			mkexpr(OPCOLON, cpexpr(t),
666 				mkexpr(OPNEG, cpexpr(t), ENULL) ));
667 		if(q)
668 			t1 = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(t),q), t1);
669 		frexpr(t);
670 		return(t1);
671 
672 	case 26:	/* dprod */
673 		q = mkexpr(OPSTAR, intrconv(TYDREAL,args->datap), args->nextp->datap);
674 		return(q);
675 
676 	case 27:	/* len of character string */
677 	case 28:
678 		q = (expptr) cpexpr(args->datap->headblock.vleng);
679 		frexpr(args->datap);
680 		return(q);
681 
682 	case 14:	/* half-integer mod */
683 	case 15:	/* mod */
684 		return( mkexpr(OPMOD, (expptr) (args->datap),
685 			(expptr) (args->nextp->datap) ));
686 	}
687 return(NULL);
688 }
689