#include	"defs.h"
#include	"global.h"

char *
alloc_check(p, e)
char *p, *e;
{
    if (p == NULL)
	Fatal("can't malloc space for %s", e);
    return p;
}

makeuint(s, n)		/* return n byte quantity from string */
byte *s;
int n;
{
    int x;	/* number being constructed */

    x = 0;
    while (n--)  {
	x <<= 8;
	x |= *s++;
    }
    return x;
}

makeint(s, n)		/* return n byte quantity from string */
byte *s;
int n;
{
    int n1;		/* number of bytes	    */
    int x;	/* number being constructed */

    x = *s++;		/* get first (high-order) byte */
    n1 = n--;
    while (n--)  {
	x <<= 8;
	x |= *s++;
    }

    /* NOTE: This code assumes that the right-shift is an arithmetic, rather
    than logical, shift which will propagate the sign bit right.   According
    to Kernighan and Ritchie, this is compiler dependent! */

    x<<=32-8*n1;
    x>>=32-8*n1;  /* sign extend */

    return x;
}

static int i2b();

uinttob(b, x)
byte *b;
unsigned int x;
{
    static unsigned char buf[sizeof(int)+1];
    int i, j, n;

    if (x == 0) {
	b[0] = 0;
	return 1;
    }
    n = i2b((unsigned int)x, buf);
    for (i = 1; i+1 < n && buf[i] == 0; i++)
	;
    for (j = i; j < n; j++)
	b[j-i] = buf[j];
    return n-i;
}

inttob(b, x)
byte *b;
int x;
{
    static unsigned char buf[sizeof(int)+1];
    int i, j, n;

    if (x == 0) {
	b[0] = 0;
	return 1;
    }
    n = i2b((unsigned int)x, buf);
    if (x > 0)
	for (i = 0; i+1 < n && buf[i] == 0 && (buf[i+1]&0x80) == 0; i++)
	    ;
    else
	for (i = 1; i+1 < n && buf[i] == 0xff && (buf[i+1]&0x80); i++)
	    ;
    for (j = i; j < n; j++)
	b[j-i] = buf[j];
    return n-i;
}

static
i2b(x, b)
unsigned int x;
unsigned char *b;
{
    int n;

    if (x == 0) {
	*b = 0;
	return 1;
    }
    n = i2b(x>>8, b);
    *(b+n) = x & 0xff;
    return n+1;
}

numstr(s)
char *s;
{
    for (; *s != '\0'; s++)
	if (!isdigit(*s))
	    return FALSE;
    return TRUE;
}

char *
strsave(s)
char *s;
{
    char *t;
    int len;

    if ((t = malloc((unsigned)(len = strlen(s)+1))) == NULL)
	Fatal("cannot save string %s", s);
    bcopy(s, t, len);
    return t;
}

/* getstrtok:
 *   find the first c in d, put '\0' there, and let *e point the next position.
 */
getstrtok(d, c, e)
char *d;
char c;
char **e;
{
    for (; *d != c && *d != '\0'; d++)
	;
    if (*d == c) {
	*d = '\0';
	*e = d+1;
	return TRUE;
    }
    return FALSE;
}

skipstrblank(d, e)
char *d;
char **e;
{
    for (; *d == ' ' || *d == '\t'; d++)
	;
    *e = d;
}


#define	LOWP	16
#define	FIXP	20
#define	LOWMASK	((1<<LOWP)-1)
#define	D	(1<<(FIXP-LOWP))
#define	H	(1<<(2*LOWP-FIXP))
#define	TPT(x, y)	((x)<<(y))	/* x * 2^y */
#define	DPT(x, y)	((x)>>(y))	/* x / 2^y */

scale_exact(s, d)
int s, d;
{
    int sign;
    unsigned int s1, s0, d1, d0;

    if (s < 0) {
	sign = -1;
	s *= -1;
    } else
	sign = 1;
    s0 = s & LOWMASK;
    d0 = d & LOWMASK;
    s1 = s >> LOWP;
    d1 = d >> LOWP;
    return (sign *
	    (TPT(s1*d1, 2*LOWP-FIXP) +
	     DPT(s1*d0+s0*d1 + DPT(s0*d0, LOWP), FIXP-LOWP))
	    );
}
