home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD2.bin
/
bbs
/
gnu
/
f2c-1993.04.28-src.lha
/
f2c-1993.04.28
/
src
/
expr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-28
|
61KB
|
3,043 lines
/****************************************************************
Copyright 1990, 1991, 1992, 1993 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 "output.h"
#include "names.h"
LOCAL void conspower(), consbinop(), zdiv();
LOCAL expptr fold(), mkpower(), stfcall();
#ifndef stfcall_MAX
#define stfcall_MAX 144
#endif
typedef struct { double dreal, dimag; } dcomplex;
extern char dflttype[26];
extern int htype;
/* little routines to create constant blocks */
Constp mkconst(t)
register int t;
{
register Constp p;
p = ALLOC(Constblock);
p->tag = TCONST;
p->vtype = t;
return(p);
}
/* mklogcon -- Make Logical Constant */
expptr mklogcon(l)
register int l;
{
register Constp p;
p = mkconst(tylog);
p->Const.ci = l;
return( (expptr) p );
}
/* mkintcon -- Make Integer Constant */
expptr mkintcon(l)
ftnint l;
{
register Constp p;
p = mkconst(tyint);
p->Const.ci = l;
return( (expptr) p );
}
/* mkaddcon -- Make Address Constant, given integer value */
expptr mkaddcon(l)
register long l;
{
register Constp p;
p = mkconst(TYADDR);
p->Const.ci = l;
return( (expptr) p );
}
/* mkrealcon -- Make Real Constant. The type t is assumed
to be TYREAL or TYDREAL */
expptr mkrealcon(t, d)
register int t;
char *d;
{
register Constp p;
p = mkconst(t);
p->Const.cds[0] = cds(d,CNULL);
p->vstg = 1;
return( (expptr) p );
}
/* mkbitcon -- Make bit constant. Reads the input string, which is
assumed to correctly specify a number in base 2^shift (where shift
is the input parameter). shift may not exceed 4, i.e. only binary,
quad, octal and hex bases may be input. Constants may not exceed 32
bits, or whatever the size of (struct Constblock).ci may be. */
expptr mkbitcon(shift, leng, s)
int shift;
int leng;
char *s;
{
register Constp p;
register long x;
p = mkconst(TYLONG);
x = 0;
while(--leng >= 0)
if(*s != ' ')
x = (x << shift) | hextoi(*s++);
/* mwm wanted to change the type to short for short constants,
* but this is dangerous -- there is no syntax for long constants
* with small values.
*/
p->Const.ci = x;
return( (expptr) p );
}
/* mkstrcon -- Make string constant. Allocates storage and initializes
the memory for a copy of the input Fortran-string. */
expptr mkstrcon(l,v)
int l;
register char *v;
{
register Constp p;
register char *s;
p = mkconst(TYCHAR);
p->vleng = ICON(l);
p->Const.ccp = s = (char *) ckalloc(l+1);
p->Const.ccp1.blanks = 0;
while(--l >= 0)
*s++ = *v++;
*s = '\0';
return( (expptr) p );
}
/* mkcxcon -- Make complex contsant. A complex number is a pair of
values, each of which may be integer, real or double. */
expptr mkcxcon(realp,imagp)
register expptr realp, imagp;
{
int rtype, itype;
register Constp p;
expptr errnode();
rtype = realp->headblock.vtype;
itype = imagp->headblock.vtype;
if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
{
p = mkconst( (rtype==TYDREAL||itype==TYDREAL)
? TYDCOMPLEX : tycomplex);
if (realp->constblock.vstg || imagp->constblock.vstg) {
p->vstg = 1;
p->Const.cds[0] = ISINT(rtype)
? string_num("", realp->constblock.Const.ci)
: realp->constblock.vstg
? realp->constblock.Const.cds[0]
: dtos(realp->constblock.Const.cd[0]);
p->Const.cds[1] = ISINT(itype)
? string_num("", imagp->constblock.Const.ci)
: imagp->constblock.vstg
? imagp->constblock.Const.cds[0]
: dtos(imagp->constblock.Const.cd[0]);
}
else {
p->Const.cd[0] = ISINT(rtype)
? realp->constblock.Const.ci
: realp->constblock.Const.cd[0];
p->Const.cd[1] = ISINT(itype)
? imagp->constblock.Const.ci
: imagp->constblock.Const.cd[0];
}
}
else
{
err("invalid complex constant");
p = (Constp)errnode();
}
frexpr(realp);
frexpr(imagp);
return( (expptr) p );
}
/* errnode -- Allocate a new error block */
expptr errnode()
{
struct Errorblock *p;
p = ALLOC(Errorblock);
p->tag = TERROR;
p->vtype = TYERROR;
return( (expptr) p );
}
/* mkconv -- Make type conversion. Cast expression p into type t.
Note that casting to a character copies only the first sizeof(char)
bytes. */
expptr mkconv(t, p)
register int t;
register expptr p;
{
register expptr q;
register int pt, charwarn = 1;
expptr opconv();
if (t >= 100) {
t -= 100;
charwarn = 0;
}
if(t==TYUNKNOWN || t==TYERROR)
badtype("mkconv", t);
pt = p->headblock.vtype;
/* Casting to the same type is a no-op */
if(t == pt)
return(p);
/* If we're casting a constant which is not in the literal table ... */
else if( ISCONST(p) && pt!=TYADDR && pt != TYCHAR)
{
if (ISINT(t) && ISINT(pt) || ISREAL(t) && ISREAL(pt)) {
/* avoid trouble with -i2 */
p->headblock.vtype = t;
return p;
}
q = (expptr) mkconst(t);
consconv(t, &q->constblock, &p->constblock );
frexpr(p);
}
else {
if (pt == TYCHAR && t != TYADDR && charwarn
&& (!halign || p->tag != TADDR
|| p->addrblock.uname_tag != UNAM_CONST))
warn(
"ichar([first char. of] char. string) assumed for conversion to numeric");
q = opconv(p, t);
}
if(t == TYCHAR)
q->constblock.vleng = ICON(1);
return(q);
}
/* opconv -- Convert expression p to type t using the main
expression evaluator; returns an OPCONV expression, I think 14-jun-88 mwm */
expptr opconv(p, t)
expptr p;
int t;
{
register expptr q;
if (t == TYSUBR)
err("illegal use of subroutine name");
q = mkexpr(OPCONV, p, ENULL);
q->headblock.vtype = t;
return(q);
}
/* addrof -- Create an ADDR expression operation */
expptr addrof(p)
expptr p;
{
return( mkexpr(OPADDR, p, ENULL) );
}
/* cpexpr - Returns a new copy of input expression p */
tagptr cpexpr(p)
register tagptr p;
{
register tagptr e;
int tag;
register chainp ep, pp;
tagptr cpblock();
/* This table depends on the ordering of the T macros, e.g. TNAME */
static int blksize[ ] =
{
0,
sizeof(struct Nameblock),
sizeof(struct Constblock),
sizeof(struct Exprblock),
sizeof(struct Addrblock),
sizeof(struct Primblock),
sizeof(struct Listblock),
sizeof(struct Impldoblock),
sizeof(struct Errorblock)
};
if(p == NULL)
return(NULL);
/* TNAMEs are special, and don't get copied. Each name in the current
symbol table has a unique TNAME structure. */
if( (tag = p->tag) == TNAME)
return(p);
e = cpblock(blksize[p->tag], (char *)p);
switch(tag)
{
case TCONST:
if(e->constblock.vtype == TYCHAR)
{
e->constblock.Const.ccp =
copyn((int)e->constblock.vleng->constblock.Const.ci+1,
e->constblock.Const.ccp);
e->constblock.vleng =
(expptr) cpexpr(e->constblock.vleng);
}
case TERROR:
break;
case TEXPR:
e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp);
e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
break;
case TLIST:
if(pp = p->listblock.listp)
{
ep = e->listblock.listp =
mkchain((char *)cpexpr((tagptr)pp->datap), CHNULL);
for(pp = pp->nextp ; pp ; pp = pp->nextp)
ep = ep->nextp =
mkchain((char *)cpexpr((tagptr)pp->datap),
CHNULL);
}
break;
case TADDR:
e->a