|
|
BSD 4.3
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
static char sccsid[] = "@(#)conv.c 5.1 (Berkeley) 6/7/85";
#endif not lint
/*
* conv.c
*
* Routines for type conversions, f77 compiler pass 1.
*
* University of Utah CS Dept modification history:
*
* $Log: conv.c,v $
* Revision 1.1.1.1 2018/04/24 16:12:54 root
* BSD 4.3
*
* Revision 2.2 85/06/07 21:09:29 root
* Add copyright
*
* Revision 2.1 84/07/19 12:02:29 donn
* Changed comment headers for UofU.
*
* Revision 1.2 84/04/13 01:07:02 donn
* Fixed value of dminreal to be -1.7e38 + epsilon instead of -2.59e33, per
* Bob Corbett's approval.
*
*/
#include "defs.h"
#include "conv.h"
int badvalue;
/* The following constants are used to check the limits of */
/* conversions. Dmaxword is the largest double precision */
/* number which can be converted to a two-byte integer */
/* without overflow. Dminword is the smallest double */
/* precision value which can be converted to a two-byte */
/* integer without overflow. Dmaxint and dminint are the */
/* analogous values for four-byte integers. */
LOCAL long dmaxword[] = { 0xfeff47ff, 0xffffffff };
LOCAL long dminword[] = { 0x00ffc800, 0xffffffff };
LOCAL long dmaxint[] = { 0xffff4fff, 0xfffffeff };
LOCAL long dminint[] = { 0x0000d000, 0xffff00ff };
LOCAL long dmaxreal[] = { 0xffff7fff, 0xffff7fff };
LOCAL long dminreal[] = { 0xffffffff, 0xffff7fff };
/* The routines which follow are used to convert */
/* constants into constants of other types. */
LOCAL char *
grabbits(len, cp)
int len;
Constp cp;
{
static char *toobig = "bit value too large";
register char *p;
register char *bits;
register int i;
register int k;
register int lenb;
bits = cp->const.ccp;
lenb = cp->vleng->constblock.const.ci;
p = (char *) ckalloc(len);
if (len >= lenb)
k = lenb;
else
{
k = len;
if ( badvalue == 0 )
{
#if (TARGET == PDP11 || TARGET == VAX)
i = len;
while ( i < lenb && bits[i] == 0 )
i++;
if (i < lenb)
badvalue = 1;
#else
i = lenb - len - 1;
while ( i >= 0 && bits[i] == 0)
i--;
if (i >= 0)
badvalue = 1;
#endif
if (badvalue)
warn(toobig);
}
}
#if (TARGET == PDP11 || TARGET == VAX)
i = 0;
while (i < k)
{
p[i] = bits[i];
i++;
}
#else
i = lenb;
while (k > 0)
p[--k] = bits[--i];
#endif
return (p);
}
LOCAL char *
grabbytes(len, cp)
int len;
Constp cp;
{
register char *p;
register char *bytes;
register int i;
register int k;
register int lenb;
bytes = cp->const.ccp;
lenb = cp->vleng->constblock.const.ci;
p = (char *) ckalloc(len);
if (len >= lenb)
k = lenb;
else
k = len;
i = 0;
while (i < k)
{
p[i] = bytes[i];
i++;
}
while (i < len)
p[i++] = BLANK;
return (p);
}
LOCAL expptr
cshort(cp)
Constp cp;
{
static char *toobig = "data value too large";
static char *reserved = "reserved operand assigned to an integer";
static char *compat1 = "logical datum assigned to an integer variable";
static char *compat2 = "character datum assigned to an integer variable";
register expptr p;
register short *shortp;
register ftnint value;
register long *rp;
register double *minp;
register double *maxp;
realvalue x;
switch (cp->vtype)
{
case TYBITSTR:
shortp = (short *) grabbits(2, cp);
p = (expptr) mkconst(TYSHORT);
p->constblock.const.ci = *shortp;
free((char *) shortp);
break;
case TYSHORT:
p = (expptr) cpexpr(cp);
break;
case TYLONG:
value = cp->const.ci;
if (value >= MINWORD && value <= MAXWORD)
{
p = (expptr) mkconst(TYSHORT);
p->constblock.const.ci = value;
}
else
{
if (badvalue <= 1)
{
badvalue = 2;
err(toobig);
}
p = errnode();
}
break;
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
minp = (double *) dminword;
maxp = (double *) dmaxword;
rp = (long *) &(cp->const.cd[0]);
x.q.word1 = rp[0];
x.q.word2 = rp[1];
if (x.f.sign == 1 && x.f.exp == 0)
{
if (badvalue <= 1)
{
badvalue = 2;
err(reserved);
}
p = errnode();
}
else if (x.d >= *minp && x.d <= *maxp)
{
p = (expptr) mkconst(TYSHORT);
p->constblock.const.ci = x.d;
}
else
{
if (badvalue <= 1)
{
badvalue = 2;
err(toobig);
}
p = errnode();
}
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0 )
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
shortp = (short *) grabbytes(2, cp);
p = (expptr) mkconst(TYSHORT);
p->constblock.const.ci = *shortp;
free((char *) shortp);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
clong(cp)
Constp cp;
{
static char *toobig = "data value too large";
static char *reserved = "reserved operand assigned to an integer";
static char *compat1 = "logical datum assigned to an integer variable";
static char *compat2 = "character datum assigned to an integer variable";
register expptr p;
register ftnint *longp;
register long *rp;
register double *minp;
register double *maxp;
realvalue x;
switch (cp->vtype)
{
case TYBITSTR:
longp = (ftnint *) grabbits(4, cp);
p = (expptr) mkconst(TYLONG);
p->constblock.const.ci = *longp;
free((char *) longp);
break;
case TYSHORT:
p = (expptr) mkconst(TYLONG);
p->constblock.const.ci = cp->const.ci;
break;
case TYLONG:
p = (expptr) cpexpr(cp);
break;
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
minp = (double *) dminint;
maxp = (double *) dmaxint;
rp = (long *) &(cp->const.cd[0]);
x.q.word1 = rp[0];
x.q.word2 = rp[1];
if (x.f.sign == 1 && x.f.exp == 0)
{
if (badvalue <= 1)
{
badvalue = 2;
err(reserved);
}
p = errnode();
}
else if (x.d >= *minp && x.d <= *maxp)
{
p = (expptr) mkconst(TYLONG);
p->constblock.const.ci = x.d;
}
else
{
if (badvalue <= 1)
{
badvalue = 2;
err(toobig);
}
p = errnode();
}
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0 )
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
longp = (ftnint *) grabbytes(4, cp);
p = (expptr) mkconst(TYLONG);
p->constblock.const.ci = *longp;
free((char *) longp);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
creal(cp)
Constp cp;
{
static char *toobig = "data value too large";
static char *compat1 = "logical datum assigned to a real variable";
static char *compat2 = "character datum assigned to a real variable";
register expptr p;
register long *longp;
register long *rp;
register double *minp;
register double *maxp;
realvalue x;
float y;
switch (cp->vtype)
{
case TYBITSTR:
longp = (long *) grabbits(4, cp);
p = (expptr) mkconst(TYREAL);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = *longp;
free((char *) longp);
break;
case TYSHORT:
case TYLONG:
p = (expptr) mkconst(TYREAL);
p->constblock.const.cd[0] = cp->const.ci;
break;
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
minp = (double *) dminreal;
maxp = (double *) dmaxreal;
rp = (long *) &(cp->const.cd[0]);
x.q.word1 = rp[0];
x.q.word2 = rp[1];
if (x.f.sign == 1 && x.f.exp == 0)
{
p = (expptr) mkconst(TYREAL);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = x.q.word1;
}
else if (x.d >= *minp && x.d <= *maxp)
{
p = (expptr) mkconst(TYREAL);
y = x.d;
p->constblock.const.cd[0] = y;
}
else
{
if (badvalue <= 1)
{
badvalue = 2;
err(toobig);
}
p = errnode();
}
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0)
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
longp = (long *) grabbytes(4, cp);
p = (expptr) mkconst(TYREAL);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = *longp;
free((char *) longp);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
cdreal(cp)
Constp cp;
{
static char *compat1 =
"logical datum assigned to a double precision variable";
static char *compat2 =
"character datum assigned to a double precision variable";
register expptr p;
register long *longp;
register long *rp;
switch (cp->vtype)
{
case TYBITSTR:
longp = (long *) grabbits(8, cp);
p = (expptr) mkconst(TYDREAL);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[1] = longp[1];
free((char *) longp);
break;
case TYSHORT:
case TYLONG:
p = (expptr) mkconst(TYDREAL);
p->constblock.const.cd[0] = cp->const.ci;
break;
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
p = (expptr) mkconst(TYDREAL);
longp = (long *) &(cp->const.cd[0]);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[1] = longp[1];
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0 )
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
longp = (long *) grabbytes(8, cp);
p = (expptr) mkconst(TYDREAL);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[1] = longp[1];
free((char *) longp);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
ccomplex(cp)
Constp cp;
{
static char *toobig = "data value too large";
static char *compat1 = "logical datum assigned to a complex variable";
static char *compat2 = "character datum assigned to a complex variable";
register expptr p;
register long *longp;
register long *rp;
register double *minp;
register double *maxp;
realvalue re, im;
int overflow;
float x;
switch (cp->vtype)
{
case TYBITSTR:
longp = (long *) grabbits(8, cp);
p = (expptr) mkconst(TYCOMPLEX);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[2] = longp[1];
free((char *) longp);
break;
case TYSHORT:
case TYLONG:
p = (expptr) mkconst(TYCOMPLEX);
p->constblock.const.cd[0] = cp->const.ci;
break;
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
overflow = 0;
minp = (double *) dminreal;
maxp = (double *) dmaxreal;
rp = (long *) &(cp->const.cd[0]);
re.q.word1 = rp[0];
re.q.word2 = rp[1];
im.q.word1 = rp[2];
im.q.word2 = rp[3];
if (((re.f.sign == 0 || re.f.exp != 0) &&
(re.d < *minp || re.d > *maxp)) ||
((im.f.sign == 0 || re.f.exp != 0) &&
(im.d < *minp || re.d > *maxp)))
{
if (badvalue <= 1)
{
badvalue = 2;
err(toobig);
}
p = errnode();
}
else
{
p = (expptr) mkconst(TYCOMPLEX);
if (re.f.sign == 1 && re.f.exp == 0)
re.q.word2 = 0;
else
{
x = re.d;
re.d = x;
}
if (im.f.sign == 1 && im.f.exp == 0)
im.q.word2 = 0;
else
{
x = im.d;
im.d = x;
}
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = re.q.word1;
rp[1] = re.q.word2;
rp[2] = im.q.word1;
rp[3] = im.q.word2;
}
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0)
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
longp = (long *) grabbytes(8, cp);
p = (expptr) mkconst(TYCOMPLEX);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[2] = longp[1];
free((char *) longp);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
cdcomplex(cp)
Constp cp;
{
static char *compat1 = "logical datum assigned to a complex variable";
static char *compat2 = "character datum assigned to a complex variable";
register expptr p;
register long *longp;
register long *rp;
switch (cp->vtype)
{
case TYBITSTR:
longp = (long *) grabbits(16, cp);
p = (expptr) mkconst(TYDCOMPLEX);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[1] = longp[1];
rp[2] = longp[2];
rp[3] = longp[3];
free((char *) longp);
break;
case TYSHORT:
case TYLONG:
p = (expptr) mkconst(TYDCOMPLEX);
p->constblock.const.cd[0] = cp->const.ci;
break;
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
p = (expptr) mkconst(TYDCOMPLEX);
longp = (long *) &(cp->const.cd[0]);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[1] = longp[1];
rp[2] = longp[2];
rp[3] = longp[3];
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0 )
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
longp = (long *) grabbytes(16, cp);
p = (expptr) mkconst(TYDCOMPLEX);
rp = (long *) &(p->constblock.const.cd[0]);
rp[0] = longp[0];
rp[1] = longp[1];
rp[2] = longp[2];
rp[3] = longp[3];
free((char *) longp);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
clogical(cp)
Constp cp;
{
static char *compat1 = "numeric datum assigned to a logical variable";
static char *compat2 = "character datum assigned to a logical variable";
register expptr p;
register long *longp;
register short *shortp;
register int size;
size = typesize[tylogical];
switch (cp->vtype)
{
case TYBITSTR:
p = (expptr) mkconst(tylogical);
if (tylogical == TYSHORT)
{
shortp = (short *) grabbits(size, cp);
p->constblock.const.ci = (int) *shortp;
free((char *) shortp);
}
else
{
longp = (long *) grabbits(size, cp);
p->constblock.const.ci = *longp;
free((char *) longp);
}
break;
case TYSHORT:
case TYLONG:
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYLOGICAL:
p = (expptr) cpexpr(cp);
p->constblock.vtype = tylogical;
break;
case TYCHAR:
if ( !ftn66flag && badvalue == 0 )
{
badvalue = 1;
warn(compat2);
}
case TYHOLLERITH:
p = (expptr) mkconst(tylogical);
if (tylogical == TYSHORT)
{
shortp = (short *) grabbytes(size, cp);
p->constblock.const.ci = (int) *shortp;
free((char *) shortp);
}
else
{
longp = (long *) grabbytes(4, cp);
p->constblock.const.ci = *longp;
free((char *) longp);
}
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
LOCAL expptr
cchar(len, cp)
int len;
Constp cp;
{
static char *compat1 = "numeric datum assigned to a character variable";
static char *compat2 = "logical datum assigned to a character variable";
register expptr p;
register char *value;
switch (cp->vtype)
{
case TYBITSTR:
value = grabbits(len, cp);
p = (expptr) mkstrcon(len, value);
free(value);
break;
case TYSHORT:
case TYLONG:
case TYREAL:
case TYDREAL:
case TYCOMPLEX:
case TYDCOMPLEX:
if (badvalue <= 1)
{
badvalue = 2;
err(compat1);
}
p = errnode();
break;
case TYLOGICAL:
if (badvalue <= 1)
{
badvalue = 2;
err(compat2);
}
p = errnode();
break;
case TYCHAR:
case TYHOLLERITH:
value = grabbytes(len, cp);
p = (expptr) mkstrcon(len, value);
free(value);
break;
case TYERROR:
p = errnode();
break;
}
return (p);
}
expptr
convconst(type, len, const)
int type;
int len;
Constp const;
{
register expptr p;
switch (type)
{
case TYSHORT:
p = cshort(const);
break;
case TYLONG:
p = clong(const);
break;
case TYREAL:
p = creal(const);
break;
case TYDREAL:
p = cdreal(const);
break;
case TYCOMPLEX:
p = ccomplex(const);
break;
case TYDCOMPLEX:
p = cdcomplex(const);
break;
case TYLOGICAL:
p = clogical(const);
break;
case TYCHAR:
p = cchar(len, const);
break;
case TYERROR:
case TYUNKNOWN:
p = errnode();
break;
default:
badtype("convconst", type);
}
return (p);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.