#include <unistd.h>

#include "SPAD-API.H"

LIST_ENTRY KERNEL$LIST_END;

char *KERNEL$ERROR_MSG(void)
{
	static char err[__MAX_STR_LEN] = "";
	return err;
}

int KERNEL$STDIN() { return 0; }
int KERNEL$STDOUT() { return 1; }
int KERNEL$STDERR() { return 2; }

static char printf_buffer[4096];

int _vfprintf(int h, __const__ char *fmt, va_list args)
{
	int r;
	char *pb;
	vsnprintf(printf_buffer, sizeof printf_buffer, fmt, args);
	pb = printf_buffer;
	while (*pb) {
		r = write(h, pb, strlen(pb));
		if (__unlikely(r <= 0)) return -1;
		pb += r;
	}
	return strlen(printf_buffer);
}

int _fprintf(int h, __const__ char *fmt, ...)
{
	int r;
	va_list va;
	va_start(va, fmt);
	r = _vfprintf(h, fmt, va);
	va_end(va);
	return r;
}

int _veprintf(__const__ char *fmt, va_list args)
{
	return _vfprintf(KERNEL$STDERR(), fmt, args);
}

int _eprintf(__const__ char *fmt, ...)
{
	int r;
	va_list va;
	va_start(va, fmt);
	r = _veprintf(fmt, va);
	va_end(va);
	return r;
}

int _vprintf(__const__ char *fmt, va_list args)
{
	return _vfprintf(KERNEL$STDOUT(), fmt, args);
}

int _printf(__const__ char *fmt, ...)
{
	int r;
	va_list va;
	va_start(va, fmt);
	r = _vprintf(fmt, va);
	va_end(va);
	return r;
}

void KERNEL$SUICIDE(__const__ char *fmt, ...)
{
	va_list va;
	_eprintf("SUICIDE: ");
	va_start(va, fmt);
	_veprintf(fmt, va);
	va_end(va);
	_eprintf("\n");
	abort();
}

int _memcasecmp(__const__ void *s1, __const__ void *s2, size_t count)
{
	__const__ char *p1 = s1, *p2 = s2;
	while (count--) {
		unsigned char c1 = *p1, c2 = *p2;
		if (c1 >= 'a' && c1 <= 'z') c1 -= 0x20;
		if (c2 >= 'a' && c2 <= 'z') c2 -= 0x20;
		if (__unlikely(c1 != c2)) return c2 - c1;
		p1++, p2++;
	}
	return 0;
}

size_t strlcpy(char *dest, __const__ char *src, size_t count)
{
	size_t l = strlen(src);
	if (__likely(l < count)) {
		strcpy(dest, src);
	} else if (count) {
		memcpy(dest, src, count - 1);
		dest[count - 1] = 0;
	}
	return l;
}

size_t strlcat(char *dest, __const__ char *src, size_t count)
{
	size_t l = strlen(dest);
	size_t ll = strlen(src);
	if (l + ll < count) {
		strcat(dest, src);
	} else if (count) {
		memcpy(dest + l, src, count - l - 1);
		dest[count - 1] = 0;
	}
	return l + ll;
}

__u64 KERNEL$GET_MEMORY_SIZE(int type)
{
#ifdef __linux__
	{
		int i, r;
		__u64 mem;
		FILE *f;
		f = popen("cat /proc/meminfo 2>/dev/null|awk '{if ($1==\"MemFree:\"||$1==\"Buffers:\"||$1==\"Cached:\") p += $2} END {print p}' 2>/dev/null", "r");
		/* ||$1==\"SwapFree:\"*/
		if (__unlikely(!f)) goto no_popen;
		i = fscanf(f, "%"__64_format"d", &mem);
		r = pclose(f);
		/*printf("%d %d %lld\n", i, r, mem);*/
		if (__likely(i == 1) && __likely(!r)) return mem << 10;
		no_popen:;
	}
#endif
	return 128 << 20;
}


