/* 
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
 */
#include "bootloader.h"

void
blockprint(__u64 zero_offset, char *buf, int nbytes)
{
    int i;
    for (i = 0; i < nbytes; i += 16)
    {
	int j;
	printf("%lld:", zero_offset + i);
	for (j = 0; j < 16; j++)
	{
	    printf(" %02x", buf[i + j] & 0xff);
	}
	printf("\r\n");
    }
}

static char *__free = 0;

char *malloc_aligned(int nbytes, int align)
{
    /* allocate */
    __free -= nbytes;
    /* align */
    __free = (char *)(((unsigned)__free) & ~(align - 1));

    if (0) printf("malloc_aligned(%d) = %x\n", nbytes, (unsigned) __free);

    return __free;
}

void *malloc(size_t nbytes)
{
    return malloc_aligned(nbytes, 8);
}

void *calloc(unsigned nitems, unsigned size)
{
	unsigned l = nitems * size;
	void *p = malloc(l);
	memset(p, 0, l);
	return p;
}

void mark (void **ptr)
{
    *ptr = (void *) __free;
}

void release (void *ptr)
{
    __free = (char *) ptr;
}

void malloc_init(char *free)
{
    __free = free;
}

/* some of these are lifted from linux/lib */
char * strpbrk(const char * cs,const char * ct)
{
	const char *sc1,*sc2;

	for( sc1 = cs; *sc1 != '\0'; ++sc1) {
		for( sc2 = ct; *sc2 != '\0'; ++sc2) {
			if (*sc1 == *sc2)
				return (char *) sc1;
		}
	}
	return NULL;
}
size_t strspn(const char *s, const char *accept)
{
	const char *p;
	const char *a;
	size_t count = 0;

	for (p = s; *p != '\0'; ++p) {
		for (a = accept; *a != '\0'; ++a) {
			if (*p == *a)
				break;
		}
		if (*a == '\0')
			return count;
		++count;
	}

	return count;
}
char * strtok(char * s,const char * ct)
{
	char *sbegin, *send;
	static char * ___strtok = NULL;

	sbegin  = s ? s : ___strtok;
	if (!sbegin) {
		return NULL;
	}
	sbegin += strspn(sbegin,ct);
	if (*sbegin == '\0') {
		___strtok = NULL;
		return( NULL );
	}
	send = strpbrk( sbegin, ct);
	if (send && *send != '\0')
		*send++ = '\0';
	___strtok = send;
	return (sbegin);
}

int strncmp(const char * cs,const char * ct,size_t count)
{
	register signed char __res = 0;

	while (count) {
		if ((__res = *cs - *ct++) != 0 || !*cs++)
			break;
		count--;
	}

	return __res;
}

void * memset(void * s,int c,size_t count)
{
	char *xs = (char *) s;

	while (count--)
		*xs++ = c;

	return s;
}

int streq(const char *a, const char *b)
{
    if (a == b)
	return 1;

    while (*a != '\0' && *b != '\0' && *a++ == *b++)
    {
    }

    return *a == '\0' && *b == '\0';
}

char *strcpy(char *dest, const char *src)
{
	char *savedest = dest;

	while((*dest++ = *src++));

	return savedest;
}

char *strcat(char *dest, const char *src)
{
	char *savedest = dest;

	/* go to end of 'dest' string */
	while (*dest != '\0')
		dest++;

	strcpy(dest, src);

	return savedest;
}

int memcmp(const void * cs,const void * ct,size_t count)
{
	const unsigned char *su1, *su2;
	signed char res = 0;

	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
		if ((res = *su1 - *su2) != 0)
			break;
	return res;
}

char * strstr(const char * s1,const char * s2)
{
	int l1, l2;

	l2 = strlen(s2);
	if (!l2)
		return (char *) s1;
	l1 = strlen(s1);
	while (l1 >= l2) {
		l1--;
		if (!memcmp(s1,s2,l2))
			return (char *) s1;
		s1++;
	}
	return NULL;
}

void bzero(char *p, size_t len)
{
	/* slow but safe */
	while (len--)
	    *p++ = 0;
}

void *memcpy(void *d, const void *s, size_t len)
{
	char *dest = (char *)d;
	const char *source = (const char *)s;

	while (len--)
		*dest++ = *source++;
	return d;
}

size_t strlen(const char * s)
{
        const char *sc;

        for (sc = s; *sc != '\0'; ++sc)
                /* nothing */;
        return sc - s;
}

size_t strnlen(const char * s, size_t count)
{
	const char *sc;

	for (sc = s; count-- && *sc != '\0'; ++sc)
		/* nothing */;
	return sc - s;
}

/* Copyright (C) 1999 Jason L. Eckhardt (jle@cygnus.com) */
char *enter_text(char *txt, int maxchars)
{
    char c;
    int pos;
    for (pos = 0; txt[pos]; pos++);	/* calculate no. of chars */
    if (pos > maxchars)	/* if input too long, shorten it */
    {
	pos = maxchars;
	txt[pos] = '\0';
    }
    printf(txt);		/* print initial text */
    do
    {
	c = getchar();
	if (c == 13)
	{			/* CR -> finish! */
	    if (pos <= maxchars)
		txt[pos] = 0;
	    else
		txt[maxchars] = '\0';
	    return txt;
	};
	if (c == '\b' || c == 127 )
	{			/* BS -> delete prev. char */
	    if (pos)
	    {
		pos--;
		c='\b';
		putchar(c);
		putchar(' ');
		putchar(c);
	    }
	} else if (c == 21)
	{			/* CTRL-U */
	    while (pos)
	    {
		pos--;
		c='\b';
		putchar(c);
		putchar(' ');
		putchar(c);
	    }
	    txt[0] = 0;
	} else if ((pos < maxchars) && c >= ' ')
	{
	    txt[pos] = c;
	    pos++;
	    putchar(c);
	}
    }
    while (c != 13);
    return txt;
}
/**
 * strrchr - Find the last occurrence of a character in a string
 * @s: The string to be searched
 * @c: The character to search for
 */
char * strrchr(const char * s, int c)
{
       const char *p = s + strlen(s);
       do {
           if (*p == (char)c)
               return (char *)p;
       } while (--p >= s);
       return NULL;
}
/**
 * strncpy - Copy a length-limited, %NUL-terminated string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 * @count: The maximum number of bytes to copy
 *
 * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
 * However, the result is not %NUL-terminated if the source exceeds
 * @count bytes.
 */
char * strncpy(char * dest,const char *src,size_t count)
{
	char *tmp = dest;

	while (count-- && (*dest++ = *src++) != '\0')
		/* nothing */;

	return tmp;
}
/**
 * strchr - Find the first occurrence of a character in a string
 * @s: The string to be searched
 * @c: The character to search for
 */
char * strchr(const char * s, int c)
{
	while (*s != (char)c) {
		if (*s == '\0')
			return NULL;
		++s;
	}
	return (char *) s;
}
