/* Smalltalk from Squeak4.6 with VMMaker 4.21.5 translated as C source on 21 September 2025 2:02:15 pm */
/* Automatically generated by
	SmartSyntaxPluginCodeGenerator VMMaker-dtl.452 uuid: c05043a9-bcd9-4669-9960-d289ab89e02c
   from
	AsynchFilePlugin VMMaker-dtl.452 uuid: c05043a9-bcd9-4669-9960-d289ab89e02c
 */
static char __buildInfo[] = "AsynchFilePlugin VMMaker-dtl.452 uuid: c05043a9-bcd9-4669-9960-d289ab89e02c " __DATE__ ;




/* Configuration options */
#include "sqConfig.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
/*  The virtual machine proxy definition */
#include "sqVirtualMachine.h"
/* Platform specific definitions */
#include "sqPlatformSpecific.h"

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */
#ifdef SQUEAK_BUILTIN_PLUGIN
#undef EXPORT
// was #undef EXPORT(returnType) but screws NorCroft cc
#define EXPORT(returnType) static returnType
#endif
#include "AsynchFilePlugin.h"

#include "sqMemoryAccess.h"


/*** Constants ***/
#define PrimErrBadArgument 3

/*** Function Prototypes ***/
#pragma export on
EXPORT(const char*) getModuleName(void);
#pragma export off
static sqInt halt(void);
#pragma export on
EXPORT(sqInt) initialiseModule(void);
EXPORT(sqInt) moduleUnloaded(char *aModuleName);
EXPORT(sqInt) primitiveAsyncFileClose(void);
EXPORT(sqInt) primitiveAsyncFileOpen(void);
EXPORT(sqInt) primitiveAsyncFileReadResult(void);
EXPORT(sqInt) primitiveAsyncFileReadStart(void);
EXPORT(sqInt) primitiveAsyncFileWriteResult(void);
EXPORT(sqInt) primitiveAsyncFileWriteStart(void);
EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
EXPORT(sqInt) shutdownModule(void);
#pragma export off
/*** Variables ***/

#ifdef SQUEAK_BUILTIN_PLUGIN
extern
#endif
struct VirtualMachine* interpreterProxy;
static const char *moduleName =
#ifdef SQUEAK_BUILTIN_PLUGIN
	"AsynchFilePlugin 21 September 2025 (i)"
#else
	"AsynchFilePlugin 21 September 2025 (e)"
#endif
;
static void * sCOAFfn;
static sqInt simulator;



/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

EXPORT(const char*) getModuleName(void) {
	return moduleName;
}

static sqInt halt(void) {
	;
	return null;
}


/*	Initialise the module */

EXPORT(sqInt) initialiseModule(void) {
	sCOAFfn = interpreterProxy->ioLoadFunctionFrom("secCanOpenAsyncFileOfSizeWritable", "SecurityPlugin");
	return asyncFileInit();
}


/*	The module with the given name was just unloaded. 
	Make sure we have no dangling references. */

EXPORT(sqInt) moduleUnloaded(char *aModuleName) {
	if ((strcmp(aModuleName, "SecurityPlugin")) == 0) {

		/* The security plugin just shut down. How odd. Zero the function pointer we have into it */

		sCOAFfn = 0;
	}
	return null;
}

EXPORT(sqInt) primitiveAsyncFileClose(void) {
	AsyncFile * f;
	sqInt fh;

	fh = interpreterProxy->stackValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	/* begin asyncFileValueOf: */
	if ((interpreterProxy->isBytes(fh)) && ((interpreterProxy->byteSizeOf(fh)) == (sizeof(AsyncFile)))) {
		f = ((AsyncFile *) (interpreterProxy->firstIndexableField(fh)));
		goto l1;
	}
	interpreterProxy->primitiveFailFor(PrimErrBadArgument);
	f = null;
l1:	/* end asyncFileValueOf: */;
	if (interpreterProxy->failed()) {
		return null;
	}
	asyncFileClose(f);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(1);
	return null;
}

EXPORT(sqInt) primitiveAsyncFileOpen(void) {
	sqInt fOop;
	sqInt okToOpen;
	sqInt fileNameSize;
	AsyncFile * f;
	char *fileName;
	sqInt writeFlag;
	sqInt semaIndex;

	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2)));
	fileName = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2))));
	writeFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
	semaIndex = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}

	/* If the security plugin can be loaded, use it to check for permission.
	If not, assume it's ok */

	fileNameSize = interpreterProxy->byteSizeOf(oopForPointer(fileName) - BASE_HEADER_SIZE);
	if (sCOAFfn != 0) {
		okToOpen = ((sqInt (*) (char *, sqInt, sqInt)) sCOAFfn)(fileName, fileNameSize, writeFlag);
		if (!(okToOpen)) {
			interpreterProxy->primitiveFail();
			return null;
		}
	}
	fOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), sizeof(AsyncFile));
	/* begin asyncFileValueOf: */
	if ((interpreterProxy->isBytes(fOop)) && ((interpreterProxy->byteSizeOf(fOop)) == (sizeof(AsyncFile)))) {
		f = ((AsyncFile *) (interpreterProxy->firstIndexableField(fOop)));
		goto l1;
	}
	interpreterProxy->primitiveFailFor(PrimErrBadArgument);
	f = null;
l1:	/* end asyncFileValueOf: */;
	if (!(interpreterProxy->failed())) {
		asyncFileOpen(f, fileName, fileNameSize, writeFlag, semaIndex);
	}
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->popthenPush(4, fOop);
	return null;
}

EXPORT(sqInt) primitiveAsyncFileReadResult(void) {
	sqInt startIndex;
	sqInt r;
	sqInt count;
	char *bufferPtr;
	AsyncFile * f;
	sqInt bufferSize;
	sqInt fhandle;
	sqInt buffer;
	sqInt start;
	sqInt num;
	sqInt _return_value;

	fhandle = interpreterProxy->stackValue(3);
	buffer = interpreterProxy->stackValue(2);
	start = interpreterProxy->stackIntegerValue(1);
	num = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	/* begin asyncFileValueOf: */
	if ((interpreterProxy->isBytes(fhandle)) && ((interpreterProxy->byteSizeOf(fhandle)) == (sizeof(AsyncFile)))) {
		f = ((AsyncFile *) (interpreterProxy->firstIndexableField(fhandle)));
		goto l1;
	}
	interpreterProxy->primitiveFailFor(PrimErrBadArgument);
	f = null;
l1:	/* end asyncFileValueOf: */;
	count = num;
	startIndex = start;

	/* in bytes or words */

	bufferSize = interpreterProxy->slotSizeOf(buffer);
	if (interpreterProxy->isWords(buffer)) {

		/* covert word counts to byte counts */

		count = count * 4;
		startIndex = ((startIndex - 1) * 4) + 1;
		bufferSize = bufferSize * 4;
	}
	interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= bufferSize));
	if (interpreterProxy->failed()) {
		return null;
	}
	bufferPtr = ((interpreterProxy->firstIndexableField(buffer)) + startIndex) - 1;
	r = asyncFileReadResult(f, ((void *)bufferPtr), count);
	_return_value = interpreterProxy->integerObjectOf(r);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->popthenPush(5, _return_value);
	return null;
}

EXPORT(sqInt) primitiveAsyncFileReadStart(void) {
	AsyncFile * f;
	sqInt fHandle;
	sqInt fPosition;
	sqInt count;

	fHandle = interpreterProxy->stackValue(2);
	fPosition = interpreterProxy->stackIntegerValue(1);
	count = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	/* begin asyncFileValueOf: */
	if ((interpreterProxy->isBytes(fHandle)) && ((interpreterProxy->byteSizeOf(fHandle)) == (sizeof(AsyncFile)))) {
		f = ((AsyncFile *) (interpreterProxy->firstIndexableField(fHandle)));
		goto l1;
	}
	interpreterProxy->primitiveFailFor(PrimErrBadArgument);
	f = null;
l1:	/* end asyncFileValueOf: */;
	if (interpreterProxy->failed()) {
		return null;
	}
	asyncFileReadStart(f, fPosition, count);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(3);
	return null;
}

EXPORT(sqInt) primitiveAsyncFileWriteResult(void) {
	sqInt r;
	AsyncFile * f;
	sqInt fHandle;
	sqInt _return_value;

	fHandle = interpreterProxy->stackValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	/* begin asyncFileValueOf: */
	if ((interpreterProxy->isBytes(fHandle)) && ((interpreterProxy->byteSizeOf(fHandle)) == (sizeof(AsyncFile)))) {
		f = ((AsyncFile *) (interpreterProxy->firstIndexableField(fHandle)));
		goto l1;
	}
	interpreterProxy->primitiveFailFor(PrimErrBadArgument);
	f = null;
l1:	/* end asyncFileValueOf: */;
	if (interpreterProxy->failed()) {
		return null;
	}
	r = asyncFileWriteResult(f);
	_return_value = interpreterProxy->integerObjectOf(r);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->popthenPush(2, _return_value);
	return null;
}

EXPORT(sqInt) primitiveAsyncFileWriteStart(void) {
	sqInt startIndex;
	sqInt count;
	char *bufferPtr;
	AsyncFile * f;
	sqInt bufferSize;
	sqInt fHandle;
	sqInt fPosition;
	sqInt buffer;
	sqInt start;
	sqInt num;

	fHandle = interpreterProxy->stackValue(4);
	fPosition = interpreterProxy->stackIntegerValue(3);
	buffer = interpreterProxy->stackValue(2);
	start = interpreterProxy->stackIntegerValue(1);
	num = interpreterProxy->stackIntegerValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	/* begin asyncFileValueOf: */
	if ((interpreterProxy->isBytes(fHandle)) && ((interpreterProxy->byteSizeOf(fHandle)) == (sizeof(AsyncFile)))) {
		f = ((AsyncFile *) (interpreterProxy->firstIndexableField(fHandle)));
		goto l1;
	}
	interpreterProxy->primitiveFailFor(PrimErrBadArgument);
	f = null;
l1:	/* end asyncFileValueOf: */;
	count = num;
	startIndex = start;

	/* in bytes or words */

	bufferSize = interpreterProxy->slotSizeOf(buffer);
	if (interpreterProxy->isWords(buffer)) {

		/* covert word counts to byte counts */

		count = count * 4;
		startIndex = ((startIndex - 1) * 4) + 1;
		bufferSize = bufferSize * 4;
	}
	interpreterProxy->success((startIndex >= 1) && (((startIndex + count) - 1) <= bufferSize));
	if (interpreterProxy->failed()) {
		return null;
	}
	bufferPtr = ((interpreterProxy->firstIndexableField(buffer)) + startIndex) - 1;
	asyncFileWriteStart(f, fPosition, ((void *)bufferPtr), count);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(5);
	return null;
}


/*	Note: This is coded so that is can be run from Squeak. */

EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) {
	sqInt ok;

	interpreterProxy = anInterpreter;
	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
	if (ok == 0) {
		return 0;
	}
	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
	return ok;
}


/*	Initialise the module */

EXPORT(sqInt) shutdownModule(void) {
	return asyncFileShutdown();
}


#ifdef SQUEAK_BUILTIN_PLUGIN


void* AsynchFilePlugin_exports[][3] = {
	{"AsynchFilePlugin", "primitiveAsyncFileWriteResult", (void*)primitiveAsyncFileWriteResult},
	{"AsynchFilePlugin", "shutdownModule", (void*)shutdownModule},
	{"AsynchFilePlugin", "primitiveAsyncFileReadResult", (void*)primitiveAsyncFileReadResult},
	{"AsynchFilePlugin", "moduleUnloaded", (void*)moduleUnloaded},
	{"AsynchFilePlugin", "primitiveAsyncFileReadStart", (void*)primitiveAsyncFileReadStart},
	{"AsynchFilePlugin", "initialiseModule", (void*)initialiseModule},
	{"AsynchFilePlugin", "setInterpreter", (void*)setInterpreter},
	{"AsynchFilePlugin", "primitiveAsyncFileOpen", (void*)primitiveAsyncFileOpen},
	{"AsynchFilePlugin", "getModuleName", (void*)getModuleName},
	{"AsynchFilePlugin", "primitiveAsyncFileWriteStart", (void*)primitiveAsyncFileWriteStart},
	{"AsynchFilePlugin", "primitiveAsyncFileClose", (void*)primitiveAsyncFileClose},
	{NULL, NULL, NULL}
};


#endif /* ifdef SQ_BUILTIN_PLUGIN */

