--- /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);
+}