/*
 * ltoa(num, base) - return string form of the given number in the
 * given base.
 * 
 * If the base has magnitude greater than 10, the sign of the base
 * determines which case of letters will be used to represent digits
 * larger than 9.  A positive base will use upper-case letters, while
 * a negative base will use lower-case letters.
 * 
 * If the base has magnitude 10, the sign of the base determines whether
 * the number is to be considered signed or unsigned.  A base of +10
 * is considered to be signed, while a base of -10 is considered to
 * be unsigned.  Odd, huh?
 * 
 * Only base 10 is potentially signed; all other bases are unsigned.
 * 
 * For performance reasons there is no check for an invalid base (a base
 * of magnitude less than 1 or greater than 36).
 * 
 * The return value is a pointer to a static buffer that is overwritten
 * with every call.
 *
 * DaviD W. Sanderson
 */

char           *
ltoa(num, obase)
	unsigned long   num;
	int             obase;
{
	unsigned long   base;
	int             neg = 0;/* 1 if num is negative */
	char            a = 'A';

	/*
	 * buf[] is big enough for the longest binary string together
	 * with terminal NUL and possible minus sign.
	 * 
	 * Note that there does not need to be a separate byte allocated
	 * for the minus sign. The minus sign is present only for
	 * numbers to be represented in decimal. Since the base 10
	 * representation of numbers larger than 1 is shorter than
	 * the base 2 representation, there will always be room for
	 * the minus sign in the base 10 string.
	 */
	static char     buf[sizeof(unsigned long) * 8 + 1];

	/* p points to the last char in buf */
	char           *p = buf + (sizeof buf - 1);

	*p = '\0';		/* terminate the string */

	/*
	 * The only signed-ness occurs when obase == +10.
	 * 
	 * If obase == -10, the decimal number is unsigned.
	 */
	if (obase == 10 && (long) num < 0)
	{
		neg = 1;
		num = -(long) num;
	}

	if (obase < 0)
	{
		a = 'a';
		obase = -obase;
	}

	/*
	 * now that obase is nonnegative, assign it to base
	 */
	base = (unsigned long) obase;

	/*
	 * subtract 10 from the code for the letter 'a' since rem
	 * will be 10 more than the offset from a
	 */
	a -= 10;

	do
	{
		long            rem;

		rem = num % base;	/* obtain value of digit */

		*--p = ((rem < 10) ? '0' : a) + rem;
	}
	while ((num /= base) != 0);

	if (neg)
		*--p = '-';

	return p;
}
