src/ai/squirrel/core.cpp
branchnoai
changeset 9393 04bd925b9069
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/squirrel/core.cpp	Thu Mar 15 00:01:33 2007 +0000
@@ -0,0 +1,171 @@
+/* $Id$ */
+
+/** @file core.hpp the implementation of the SquirrelCore class. It handles all Squirrel-stuff and gives a nice API back to work with. */
+
+#ifdef _UNICODE
+/* Disable unicode for squirrel to allow compilation with MINGW
+ * and simplify coding for WIN32 (squirrel headers miss a lot of "string" functions)
+ */
+#undef _UNICODE
+#endif
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <stdarg.h>
+#include "../../stdafx.h"
+#include "../../debug.h"
+#include "core.hpp"
+
+void SquirrelCore::CompileError(HSQUIRRELVM vm, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column)
+{
+#ifdef _SQ64
+	printf("Error %s:%ld/%ld: %s\n", source, line, column, desc);
+#else
+	printf("Error %s:%d/%d: %s\n", source, line, column, desc);
+#endif
+}
+
+void SquirrelCore::RunError(HSQUIRRELVM vm, const char *error)
+{
+	printf("%s\n", error);
+}
+
+SQInteger SquirrelCore::_RunError(HSQUIRRELVM vm)
+{
+	const SQChar *sErr = 0;
+
+	if (sq_gettop(vm) >= 1) {
+		if (SQ_SUCCEEDED(sq_getstring(vm, -1, &sErr))) {
+			SquirrelCore::RunError(vm, sErr);
+		}
+	}
+
+	SquirrelCore::RunError(vm, "Unknown error");
+	return 0;
+}
+
+void SquirrelCore::PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...)
+{
+	va_list arglist;
+	va_start(arglist, s);
+	vprintf(s, arglist);
+	va_end(arglist);
+	printf("\n");
+}
+
+void SquirrelCore::AddMethod(const char *method_name, SQFUNCTION proc, uint nparam, const char *params)
+{
+	sq_pushstring(this->vm, method_name, -1);
+	sq_newclosure(this->vm, proc, 0);
+	sq_setparamscheck(this->vm, nparam, params);
+	sq_setnativeclosurename(this->vm, -1, method_name);
+	sq_createslot(this->vm, -3);
+}
+
+void SquirrelCore::AddMethod(const char *method_name, SQFUNCTION proc)
+{
+	sq_pushstring(this->vm, method_name, -1);
+	sq_newclosure(this->vm, proc, 0);
+	sq_setnativeclosurename(this->vm, -1, method_name);
+	sq_createslot(this->vm, -3);
+}
+
+void SquirrelCore::AddClassBegin(const char *class_name)
+{
+	sq_pushroottable(this->vm);
+	sq_pushstring(this->vm, class_name, -1);
+	sq_newclass(this->vm, SQFalse);
+}
+
+void SquirrelCore::AddClassEnd()
+{
+	sq_createslot(vm, -3);
+}
+
+void SquirrelCore::CallMethod(HSQOBJECT instance, const char *method_name)
+{
+	/* Store the current top */
+	int top = sq_gettop(this->vm);
+	/* Go to the instance-root */
+	sq_pushobject(this->vm, instance);
+	/* Find the function-name inside the script */
+	sq_pushstring(this->vm, method_name, -1);
+	if (SQ_FAILED(sq_get(this->vm, -2))) {
+		DEBUG(misc, 0, "[squirrel] Could not find '%s' in the class", method_name);
+		sq_settop(this->vm, top);
+		return;
+	}
+	/* Call the method */
+	sq_pushobject(this->vm, instance);
+	sq_call(this->vm, 1, 0, 0);
+	/* Reset the top */
+	sq_settop(this->vm, top);
+}
+
+bool SquirrelCore::CreateClassInstance(const char *class_name, void *real_instance, HSQOBJECT *instance)
+{
+	int oldtop = sq_gettop(this->vm);
+
+	/* First, find the class */
+	sq_pushroottable(this->vm);
+	sq_pushstring(this->vm, class_name, -1);
+	if (SQ_FAILED(sq_get(this->vm, -2))) {
+		DEBUG(misc, 0, "[squirrel] Failed to find class by the name '%s'", class_name);
+		sq_settop(this->vm, oldtop);
+		return false;
+	}
+
+	/* Create the instance */
+	if (SQ_FAILED(sq_createinstance(this->vm, -1))) {
+		DEBUG(misc, 0, "[squirrel] Failed to create instance for class '%s'", class_name);
+		sq_settop(this->vm, oldtop);
+		return false;
+	}
+
+	if (instance != NULL) {
+		/* Find our instance */
+		sq_getstackobj(this->vm, -1, instance);
+		/* Add a reference to it, so it survives for ever */
+		sq_addref(this->vm, instance);
+	}
+	/* Store it in the class */
+	sq_setinstanceup(this->vm, -1, real_instance);
+
+	/* Reset the top */
+	sq_settop(this->vm, oldtop);
+
+	return true;
+}
+
+SquirrelCore::SquirrelCore()
+{
+	this->vm = sq_open(1024);
+
+	/* Handle compile-errors ourself, so we can display it nicely */
+	sq_setcompilererrorhandler(this->vm, &SquirrelCore::CompileError);
+	sq_notifyallexceptions(this->vm, SQTrue);
+	/* Set a good print-function */
+	sq_setprintfunc(this->vm, &SquirrelCore::PrintFunc);
+	/* Handle runtime-errors ourself, so we can display it nicely */
+	sq_newclosure(this->vm, &SquirrelCore::_RunError, 0);
+	sq_seterrorhandler(this->vm);
+
+	sq_pushroottable(this->vm);
+}
+
+bool SquirrelCore::LoadScript(const char *script)
+{
+	/* Load and run the script */
+	if (SQ_FAILED(sqstd_dofile(this->vm, script, SQFalse, SQTrue))) {
+		DEBUG(misc, 0, "[squirrel] Failed to compile '%s'", script);
+		return false;
+	}
+
+	return true;
+}
+
+SquirrelCore::~SquirrelCore()
+{
+	/* Clean up the stuff */
+	sq_pop(this->vm, 1);
+	sq_close(this->vm);
+}