/****************************************************************
* C2BAS2C.C -- convert C floats to BASIC to C & doubles, too *
****************************************************************/

#include
#include "C2BAS2C.H"

union Converter
{
unsigned char uc[10];
unsigned int ui[5];
unsigned long ul[2];
float f[2];
double d[1];
};

/****************************************************************
* GWfloatToTCfloat - convert a GWBASIC float to Turbo C float *
* INP: f - a float in GWBASIC format *
* OUT: the same value in Turbo C format *
****************************************************************/
float GWfloatToTCfloat(float f)
{
union Converter t;
int sign, exp;

t.f[0] = f;

/* Extract the sign & move exponent bias from 0x81 to 0x7f */
sign = t.uc[2]/0x80;
exp = (t.uc[3] - 0x81 + 0x7f) & 0xff;

/* Reassemble them in IEEE 4 byte real number format */
t.ui[1] = (t.ui[1]&0x7f) | (exp<<7) | (sign<<15);
return t.f[0];
}

/****************************************************************
* GWdoubleToTCdouble - convert GWBASIC double to Turbo C *
* INP: d - a double in GWBASIC format *
* OUT: the same value in Turbo C format *
****************************************************************/
double GWdoubleToTCdouble(double d)
{
union Converter t;
int sign, exp;

t.d[0] = d;

/* Extract sign & shift exponent bias from 0x81 to 0x3ff */
sign = t.uc[6]/0x80;
exp = (t.uc[7] - 0x81 + 0x3ff)&0x7ff;

/* Shift right 3 bits (IEEE/8 uses 11 bit exponent!) */
t.ul[0] = (t.ul[0]>>3) + (t.ul[1]<<29);
t.ul[1] >>= 3;

/* Now reassemble them in IEEE 8 byte real number format */
t.ui[3] = (t.ui[3]&0x0f) | (exp<<4) | (sign<<15);

return t.d[0];
}

/****************************************************************
* TCfloatToGWfloat - convert a Turbo C float to GWBASIC float *
* INP: f - a float in Turbo C format *
* OUT: the same value in GWBASIC format *
****************************************************************/
float TCfloatToGWfloat(float f)
{
union Converter t;
int sign, exp;

t.f[0] = f;

/* Extract sign & change exponent bias from 0x7f to 0x81 */
sign = t.uc[3]/0x80;
exp = ((t.ui[1]>>7) - 0x7f + 0x81) & 0xff;

/* Reassemble them in Microsoft BASIC style */
t.ui[1] = (t.ui[1]&0x7f) | (sign<<7) | (exp<<8);

return t.f[0];
}

/****************************************************************
* TCdoubleToGWdouble - convert Turbo C double to GWBASIC *
* INP: d - a double in Turbo C format *
* OUT: the same value in GWBASIC format *
****************************************************************/
double TCdoubleToGWdouble(double d)
{
union Converter t;
int sign, exp;

t.d[0] = d;

/* Extract the sign & exponent, IEEE 8 byte real style */
sign = t.uc[7]/0x80;
exp = t.ui[3]/0x10 - 0x3ff + 0x81;

/* Shift the mantissa */
t.ul[1] = (t.ul[1]<<3) + (t.ul[0]>>29);
t.ul[0] <<= 3;

/* Reassemble them in Microsoft BASIC format */
t.uc[7] = (unsigned char)exp;
t.uc[6] = sign ? t.uc[6]|0x80 : t.uc[6]&0x7f;

return t.d[0];
}

/****************************************************************
* TCstrToGWstr - convert Turbo C strings to GWBASIC *
* INP: d - destination buffer for GWBASIC string *
* s - source buffer holding Turbo C string *
* len - length of the GWBASIC string buffer *
****************************************************************/
void TCstrToGWstr(char *d, char *s, int len)
{
strncpy(d,s,len);
if (strlen(s) < len)
while (strlen(d) < len)
strcat(d," ");
}

/****************************************************************
* GWstrToTCstr - convert GWBASIC strings to Turbo C format *
* INP: d - destination buffer to recieve Turbo C string *
* s - source buffer holding GWBASIC string *
* len - length of the GWBASIC string buffer *
****************************************************************/
void GWstrToTCstr(char *d, char *s, int len)
{
int i;
memcpy(d,s,len);
d[len]=0;
i = len-1;
for (i=len-1; isspace(d[i]); --i)
d[i]=0;
}
