/*

Long package amended and extended to support BDS 1.50 library

added	lcomp - compare two strings (as per documentation)
	ltoas - long to ascii scaled
	atols - ascii to long scaled

	function numbers 0,7,8 have not yet been identified
	and are marked as UK1,UK3,UK4 below.

	a few functions in the documentation have not been done
	yet but are trivial to implement when required.

*/
#define   UK1     0
#define   COMP    1
#define   ADD     2
#define   SUB     3
#define   MUL     4
#define   DIV     5
#define   MOD     6
#define   UK3     7
#define   UK4     8

/*   ladd adds the addend and augend to produce a 32 bit
   signed result in sum.  A pointer to sum is returned.  */

char *ladd(sum,addend,augend)
char sum[], addend[], augend[];
{
	char *long();
	return (long(ADD,sum,addend,augend));
}

/*   lsub subtracts subtrahend from minuend and places the
   32 bit signed difference in difference.  A pointer to
   difference is returned.                              */

char *lsub(difference,minuend,subtrahend)
char difference[], minuend[], subtrahend[];
{
	char *long();
	return (long(SUB,difference,minuend,subtrahend));
}

/*   lmul multiplies plier and plicand together and places
   the signed low order 32 bit product in product.  A
   pointer to product is returned.                      */

char *lmul(product,plier,plicand)
char product[], plier[], plicand[];
{
	char *long();
	return (long(MUL,product,plier,plicand));
}

/*	scale must be from 0 to 9	*/

char *lmuls(product,plier,plicand,scale)
char product[],plier[],plicand[]; int scale;
{
	char *long();
	char ten[4],five[4];
	ten[3]=0x0a; ten[1]=ten[2]=ten[0]=0;
	five[3]=0x05; five[1]=five[2]=five[0]=0;

	long(MUL,product,plier,plicand);
		/*	round and scale		*/
	while (scale--) {
		long(ADD,product,product,five);
		long(DIV,product,product,ten);
	}
	return(&product);
}	

/*   ldiv divides dividend by divisor and places the signed
   low order 32 bits of the quotient in quotient.  A
   pointer to quotient is returned.
   ldivs takes account of a scale when performing the
   division - 0 <= scale < 10                   */

char *ldiv(quotient,dividend,divisor)
char quotient[], dividend[], divisor[];
{
	char *long();
	return (long(DIV,quotient,dividend,divisor));
}


char *ldivs(quotient,dividend,divisor,scale)
char quotient[], dividend[], divisor[]; int scale;
{
	char *long();
	char ten[4];
	ten[3]=0x0a; ten[1]=ten[2]=ten[0]=0;

	while (scale--)
		long(MUL,dividend,dividend,ten);
	long(DIV,quotient,dividend,divisor);
}

/*   lmod places the 31 bit positive remainder resulting
   from the division of dividend by divisor into residue.
   A pointer to residue is returned.                   */

char *lmod(residue,dividend,divisor)
char residue[], dividend[], divisor[];
{
	char *long();

	
	return (long(MOD,residue,dividend,divisor));
}

/*   lneg places the 32 bit signed negative of orignum in
   negnum and returns a pointer to it.                  */

char *lneg(negnum,orignum)
char negnum[], orignum[];
{
	char *long(), work[4], i;
	for (i=0; i<4; ++i) work[i]=0;
	return (long(SUB,negnum,work,orignum));
}

/*   lcomp returns -1,0,1 depending on result of left<right,l=r,l>r  */

int lcomp(left,right)
char left[], right[];
{
	return(long(COMP,left,right));
}

/*   itol converts an integer to long form.  A pointer
   to the longform is returned.                       */

char *itol(longform,i)
char longform[];
int i;
{
	longform[1]=longform[0]=0;
	if (i<0) longform[1]=longform[0]=0xff;
	longform[2]=i>>8;
	longform[3]=i&0xff;
	return longform;
}

/*   ltoi returns a properly signed integer containing the
   low order 15 bits of precision of the long integer
	longint.  The value of this integer is placed in i and
   is returned by this function.                         */

ltoi(longint)
char longint[4];
{
	int i;
	char work[4];

	for (i=0; i<4; ++i) work[i]=longint[i];
	if (work[0]>127) lneg(work,work);
	i=(work[2]<<8)+work[3];
	if (longint[0]>127) i=-i;
	return i;
}

/*   atol converts the ASCII string s to a long integer
   placed in longint and returns a pointer to longint.
   Acceptable format for atol is:  any amount of white
   space followed by an optional sign followed by a string
   of decimal digits.  The first non-decimal digit stops
   the scan.  The method used is an adaptation of that
   presented in Kernighan and Ritchie.                */

char *atols(longint,s,scale)
char longint[]; char s[]; int scale;
{
	int i, j;
	char wstr[20];
	char *wptr,*sptr;

	sptr = &s[0];
	wptr = &wstr[0];


/* white space */
	while (*sptr == ' ' || *sptr == '\t')
		sptr++;
/* a sign */
	if (*sptr == '-' || *sptr == '+')
		*wptr++ = *sptr++;

/* integral digits */
	while (isdigit(*sptr))
		*wptr++ = *sptr++;

/* have we got a dot */
	if (*sptr == '.') {
		sptr++;
		while (scale--)
			if (isdigit(*sptr))
				*wptr++ = *sptr++;
			else
				*wptr++ = '0';
		}
	else
		while (scale--)
			*wptr++ = '0';
/* end of string */
	*wptr++ = 0;

	return(atol(longint,wstr));
}	
	

char *atol(longint,s)
char longint[], s[];
{
	char work[4], ten[4];
	int i, j, n, sign;
	/* form a constant.. */

	ten[3]=0x0a; ten[1]=ten[2]=ten[0]=0;
	/*   first skip white space... */
	for (i=0; s[i]==' ' || s[i]=='\n' || s[i]=='\t'; i++);

	/*   now get the sign... */

	sign=1;
	if (s[i]=='+' || s[i]=='-')
		sign=(s[i++]=='+') ? 1 : -1;

	/*   and convert the string straightforwardly... */

	for (j=0; j<4; ++j) longint[j]=0;
	while (s[i]>='0' && s[i]<='9') {
		for (j=0; j<4; ++j) work[j]=0;
		work[3]=s[i++]-'0';
		lmul(longint,ten,longint);
		ladd(longint,longint,work);
	}

	/*   not forgetting the original sign... */

	if (sign==-1) lneg(longint,longint);
	return longint;
}

/*   ltoa converts the long integer longint to an ASCII
   string which is placed in s.  If longint is negative a
   minus sign is prefixes the string.  The algorithm used
   is an adaptation of itoa presented in Kernighan and
   Ritchie.                                          */

ltoas(sptr,inlong,scale)
char *sptr; char inlong[]; int scale;
{
	int i, j;
	char work[20];
	char *wptr,*fptr,*tptr;

/* Special case - get rid of integers */

	if (scale == 0)
		return(ltoa(sptr,inlong));

/*	get the full string	*/

	ltoa(work,inlong);

	wptr = &work[0];

/*	minimum length		*/

	if (*wptr == '-')
		j = scale + 3;
	else
		j = scale + 2;

	i = strlen(wptr) + 1;

	if (j < i)
		j = i;

/*	point at last digits	*/

	fptr = &wptr[i-2];
	tptr = sptr + j;
	*tptr-- = 0;

	while (scale--)
		if ((fptr < wptr) || (*fptr == '-'))
			*tptr-- = '0';
		else
			*tptr-- = *fptr--;

	*tptr-- = '.';
	if ((fptr < wptr) || (*fptr == '-'))
		*tptr-- = '0';

	while (fptr >= wptr)
		*tptr-- = *fptr--;

	return (sptr);
}

ltoa(s,inlong)
char s[], inlong[];
{
	char c, work[4], ten[4], longint[4];
	int i, j, k, sign;

	ten[3]=0x0a; ten[1]=ten[2]=ten[0]=0;
	sign=1;

	for(i=0 ; i<4 ; i++) longint[i] = inlong[i];

	/*   check the sign... */

	if (longint[0]>127) {
		sign=-1;

		lneg(longint,longint);
	}

	/*   convert, generating digits backwards in s[]... */

	i=0;
	do {
		lmod(work,longint,ten);
		s[i++]=work[3]+'0';
		ldiv(longint,longint,ten);

	} while ((longint[0]|longint[1]|longint[2]|
		longint[3])!=0);

	/*   postfix a minus sign if needed... */

	if (sign==-1) s[i++]='-';
	s[i]='\0';

	/*   and turn the whole thing around in place. */

	k=strlen(s);
	for (i=0, j=k-1; i<j; i++, j--) {
		c=s[i]; s[i]=s[j]; s[j]=c;
	}
	return s;
}
ing around in place. */

	k=strlen(s);