#include "sysdeps.h"
#include "macos_util.h"
#include "xlowmem.h"
#include <string.h>
#include <MacTypes.h>
#include <CodeFragments.h>

#define DEBUG 0
#include "debug.h"


/*
 *  Find symbol in shared library (using CFM)
 *  lib and sym must be Pascal strings!
 */

typedef OpaqueCFragConnectionID * 	ConnectionID;
typedef unsigned char				SymClass;

static uint32 FindLibSymbol(Str63 lib, Str255 sym)
{
	ConnectionID conn_id = 0;
	Ptr main_addr = NULL;
	Str255 err = "";
	Ptr sym_addr = NULL;
	SymClass sym_class = 0;
	
	int16 res;
	res = GetSharedLibrary(lib, FOURCC('p','w','p','c'), 1, &conn_id, &main_addr, err);
	D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", res, conn_id, main_addr));
	if (res)
		return NULL;
	res = FindSymbol(conn_id, sym, &sym_addr, &sym_class);
	D(bug(" FindSymbol: ret %d, sym_addr %p, sym_class %ld\n", res, sym_addr, sym_class));//!!??		CloseConnection(&conn_id);
	if (res)
		return NULL;
	else
		return (uint32)sym_addr;
}

uint32 FindLibSymbol(char *lib_name, char *sym_name)
{
	Str63 lib;
	memcpy(&lib[0], lib_name, lib_name[0]+1);
	
	Str255 sym;
	memcpy(&sym[0], sym_name, sym_name[0]+1);
	
	return FindLibSymbol(lib, sym);
}


/*
 *  Memory allocators in MacOS system heap zone
 */

uint32 Mac_sysalloc(uint32 size)
{
	return (uint32)NewPtrSys(size);
}

void Mac_sysfree(uint32 addr)
{
	DisposePtr((char *)addr);
}


/*
 *  Glue for calling MacOS routines
 */
 
#define prolog			;\
	mflr	r0			;\
	stw		r0,8(r1)	;\
	stw		r2,12(r1)	;\
	stwu	r1,-64(r1)	;\
	lwz		r0,0(r3)	;\
	lwz		r2,4(r3)	;\
	mtctr	r0

#define epilog			;\
	bctrl				;\
	lwz		r0,64+8(r1)	;\
	lwz		r2,64+12(r1);\
	mtlr	r0			;\
	addi	r1,r1,64	;\
	blr

asm uint32 call_macos(register uint32 tvect)
{
	prolog
	epilog
}

asm uint32 call_macos1(register uint32 tvect, register uint32 arg1)
{
	prolog
	mr	r3,r4
	epilog
}

asm uint32 call_macos2(register uint32 tvect, register uint32 arg1, register uint32 arg2)
{
	prolog
	mr	r3,r4
	mr	r4,r5
	epilog
}

asm uint32 call_macos3(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3)
{
	prolog
	mr	r3,r4
	mr	r4,r5
	mr	r5,r6
	epilog
}

asm uint32 call_macos4(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4)
{
	prolog
	mr	r3,r4
	mr	r4,r5
	mr	r5,r6
	mr	r6,r7
	epilog
}

asm uint32 call_macos5(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4, register uint32 arg5)
{
	prolog
	mr	r3,r4
	mr	r4,r5
	mr	r5,r6
	mr	r6,r7
	mr	r7,r8
	epilog
}

asm uint32 call_macos6(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4, register uint32 arg5, register uint32 arg6)
{
	prolog
	mr	r3,r4
	mr	r4,r5
	mr	r5,r6
	mr	r6,r7
	mr	r7,r8
	mr	r8,r9
	epilog
}

asm uint32 call_macos7(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4, register uint32 arg5, register uint32 arg6, register uint32 arg7)
{
	prolog
	mr	r3,r4
	mr	r4,r5
	mr	r5,r6
	mr	r6,r7
	mr	r7,r8
	mr	r8,r9
	mr	r9,r10
	epilog
}


/*
 *  Some standard C library implementations
 */

extern "C" void *memcpy(void *dest, const void *src, size_t n);
void *memcpy(void *dest, const void *src, size_t n)
{
	BlockMoveData(src, dest, n);
	return dest;
}

extern "C" void *memset(void *s, int c, size_t n);
void *memset(void *s, int c, size_t n)
{
	if (c == 0)
		BlockZero(s, n);
	else {
		char *p = (char *)s;
		n++;
		while (--n)
			*p++ = c;
	}
	return s;
}

extern "C" int memcmp(const void *s1, const void *s2, size_t n);
int memcmp(const void *s1, const void *s2, size_t n)
{
	const unsigned char *d = (const unsigned char *)s1;
	const unsigned char *s = (const unsigned char *)s2;
	n++;
	while (--n) {
		int r;
		if (r = (*d - *s))
			return r;
		++d;
		++s;
	}
	return 0;
}

extern "C" int printf(const char *format, ...);
int printf(const char *format, ...)
{
	return 0;
}
