
/*
** BCD floating-point test package.
** Some Assembly Required - April 1989
** -- Rick Grehan
**
** This is a "shell" you can use to experiment with the BCD
** package.  It includes external definitions to the assembly-
** language routines and the source for the I/O routines
** (which I wrote in C).  The I/O routines are pretty rudimentary,
** but should be useful for getting the numbers in and out.
** 
*/
 
#include <ctype.h>
#define BIAS 16384		/* BIAS for exponent */
typedef struct {
	unsigned int exponent;
	unsigned char mantissa[10];
} bcdtype ;

extern int fltadd();
extern int fltsub();
extern int fltmul();
extern int fltdiv();
extern int fltint();
extern int intflt();
main()
{
	bcdtype bcd1,bcd2,bcd3;
	int intout;

	/*
	* Just do some stuff.
	*/

	bcdin("+9.0E+00",&bcd1);
	bcdout(&bcd1,10); printf("\n");
	bcdin("3.00E+03",&bcd2);
	bcdout(&bcd2,10); printf("\n");
	fltadd(&bcd1,&bcd2,&bcd3);
	bcdout(&bcd3,15); printf("\n");
	if(fltint(&bcd3,&intout)==-1) printf("error\n");
	printf("%d\n",intout);
	if(intflt(intout,&bcd3)==-1) printf("error\n");
	bcdout(&bcd3,15); printf("\n");
}

/*
** Output a BCD floating-point number.
** The number is output in the format:
**     +/-n.nnnnE+/-mmm
** You can specify the number of digits in the mantissa.
*/
int bcdout(bcdnum,digs)
bcdtype *bcdnum;
int digs;			/* Number of mantissa digits */
{
	int i;			/* Index */
	unsigned char ch;	/* Holding variable for each byte */
	unsigned int truexp;	/* True exponent */

	/* Get true exponent and display mantissa sign */
	truexp=((bcdnum->exponent)&0x7FFF)-BIAS;
	if((bcdnum->exponent & 0x8000)==0)
		printf("+");
	else
		printf("-");

	/* Display mantissa digits */
	for(i=0;i<digs;++i)
	{
		ch=bcdnum->mantissa[i/2];
		if(i % 2)
			ch=ch & 15;
		else
			ch=ch >> 4;
		printf("%c",ch+'0');
		if(i==0) printf(".");
	}

	/* Display exponent */
	printf("E%d",truexp-1);
	return;
}

/*
** Input a BCD floating-point number.
** Pass this routine a pointer to a string and a pointer
** to a BCD structure.  String is converted to BCD number.
** String MUST be in the following format:
**   +/-n.nnnnE+/mmm
** You can have as many (up to the limit) n's to the right
** of the decimal point as you want.
** The function returns a 0 if conversion ok, -1 if conversion
** failed.
*/
int bcdin(stng,bcdnum)
unsigned char *stng;
bcdtype *bcdnum;
{
	int i,j;		/* Indices */
	int sign;		/* Sign of mantissa */
	unsigned char ch;	/* Holding var. for characters */
	unsigned int truexp;	/* True exponent */
	int nd;			/* # of digits to left of dpoint */
	int dpfg;		/* Decimal point flag */

	/* Clear the BCD structure */
	bcdnum->exponent=0;
	for(i=0;i<10;++i)
		bcdnum->mantissa[i]=0;

	i=0;
	j=0;
	nd=0;
	dpfg=0;
	/* Look for the sign */
	if(stng[i]=='-')
	{	sign=1; ++i; }
	else
 		if(stng[i]=='+')
		{	sign=0; ++i; }
		else
		if(isdigit(stng[i]))
			sign=0;
	else
		return(-1);

	while(isdigit(stng[i]) || stng[i]=='.')
	{
		if(stng[i]=='.')
			if(dpfg) return(-1);
			else ++dpfg;
		else
		{
			ch=stng[i] - '0';
			if(j%2==0) ch=ch<<4;
			bcdnum->mantissa[j/2] |= ch;
			++j;
			if(dpfg==0) ++nd;
		}
		++i;
	}
	if(stng[i]!='E') return(-1);
	++i;
	/* Get exponent */
	sscanf(&stng[i],"%d",&truexp);
	bcdnum->exponent=truexp+BIAS+nd;
	bcdnum->exponent+=sign<<15;
	return(0);
}

