src/ai/squirrel/core.cpp
branchnoai
changeset 9393 04bd925b9069
equal deleted inserted replaced
9392:7791ceeea57b 9393:04bd925b9069
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file core.hpp the implementation of the SquirrelCore class. It handles all Squirrel-stuff and gives a nice API back to work with. */
       
     4 
       
     5 #ifdef _UNICODE
       
     6 /* Disable unicode for squirrel to allow compilation with MINGW
       
     7  * and simplify coding for WIN32 (squirrel headers miss a lot of "string" functions)
       
     8  */
       
     9 #undef _UNICODE
       
    10 #endif
       
    11 #include <squirrel.h>
       
    12 #include <sqstdio.h>
       
    13 #include <stdarg.h>
       
    14 #include "../../stdafx.h"
       
    15 #include "../../debug.h"
       
    16 #include "core.hpp"
       
    17 
       
    18 void SquirrelCore::CompileError(HSQUIRRELVM vm, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column)
       
    19 {
       
    20 #ifdef _SQ64
       
    21 	printf("Error %s:%ld/%ld: %s\n", source, line, column, desc);
       
    22 #else
       
    23 	printf("Error %s:%d/%d: %s\n", source, line, column, desc);
       
    24 #endif
       
    25 }
       
    26 
       
    27 void SquirrelCore::RunError(HSQUIRRELVM vm, const char *error)
       
    28 {
       
    29 	printf("%s\n", error);
       
    30 }
       
    31 
       
    32 SQInteger SquirrelCore::_RunError(HSQUIRRELVM vm)
       
    33 {
       
    34 	const SQChar *sErr = 0;
       
    35 
       
    36 	if (sq_gettop(vm) >= 1) {
       
    37 		if (SQ_SUCCEEDED(sq_getstring(vm, -1, &sErr))) {
       
    38 			SquirrelCore::RunError(vm, sErr);
       
    39 		}
       
    40 	}
       
    41 
       
    42 	SquirrelCore::RunError(vm, "Unknown error");
       
    43 	return 0;
       
    44 }
       
    45 
       
    46 void SquirrelCore::PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...)
       
    47 {
       
    48 	va_list arglist;
       
    49 	va_start(arglist, s);
       
    50 	vprintf(s, arglist);
       
    51 	va_end(arglist);
       
    52 	printf("\n");
       
    53 }
       
    54 
       
    55 void SquirrelCore::AddMethod(const char *method_name, SQFUNCTION proc, uint nparam, const char *params)
       
    56 {
       
    57 	sq_pushstring(this->vm, method_name, -1);
       
    58 	sq_newclosure(this->vm, proc, 0);
       
    59 	sq_setparamscheck(this->vm, nparam, params);
       
    60 	sq_setnativeclosurename(this->vm, -1, method_name);
       
    61 	sq_createslot(this->vm, -3);
       
    62 }
       
    63 
       
    64 void SquirrelCore::AddMethod(const char *method_name, SQFUNCTION proc)
       
    65 {
       
    66 	sq_pushstring(this->vm, method_name, -1);
       
    67 	sq_newclosure(this->vm, proc, 0);
       
    68 	sq_setnativeclosurename(this->vm, -1, method_name);
       
    69 	sq_createslot(this->vm, -3);
       
    70 }
       
    71 
       
    72 void SquirrelCore::AddClassBegin(const char *class_name)
       
    73 {
       
    74 	sq_pushroottable(this->vm);
       
    75 	sq_pushstring(this->vm, class_name, -1);
       
    76 	sq_newclass(this->vm, SQFalse);
       
    77 }
       
    78 
       
    79 void SquirrelCore::AddClassEnd()
       
    80 {
       
    81 	sq_createslot(vm, -3);
       
    82 }
       
    83 
       
    84 void SquirrelCore::CallMethod(HSQOBJECT instance, const char *method_name)
       
    85 {
       
    86 	/* Store the current top */
       
    87 	int top = sq_gettop(this->vm);
       
    88 	/* Go to the instance-root */
       
    89 	sq_pushobject(this->vm, instance);
       
    90 	/* Find the function-name inside the script */
       
    91 	sq_pushstring(this->vm, method_name, -1);
       
    92 	if (SQ_FAILED(sq_get(this->vm, -2))) {
       
    93 		DEBUG(misc, 0, "[squirrel] Could not find '%s' in the class", method_name);
       
    94 		sq_settop(this->vm, top);
       
    95 		return;
       
    96 	}
       
    97 	/* Call the method */
       
    98 	sq_pushobject(this->vm, instance);
       
    99 	sq_call(this->vm, 1, 0, 0);
       
   100 	/* Reset the top */
       
   101 	sq_settop(this->vm, top);
       
   102 }
       
   103 
       
   104 bool SquirrelCore::CreateClassInstance(const char *class_name, void *real_instance, HSQOBJECT *instance)
       
   105 {
       
   106 	int oldtop = sq_gettop(this->vm);
       
   107 
       
   108 	/* First, find the class */
       
   109 	sq_pushroottable(this->vm);
       
   110 	sq_pushstring(this->vm, class_name, -1);
       
   111 	if (SQ_FAILED(sq_get(this->vm, -2))) {
       
   112 		DEBUG(misc, 0, "[squirrel] Failed to find class by the name '%s'", class_name);
       
   113 		sq_settop(this->vm, oldtop);
       
   114 		return false;
       
   115 	}
       
   116 
       
   117 	/* Create the instance */
       
   118 	if (SQ_FAILED(sq_createinstance(this->vm, -1))) {
       
   119 		DEBUG(misc, 0, "[squirrel] Failed to create instance for class '%s'", class_name);
       
   120 		sq_settop(this->vm, oldtop);
       
   121 		return false;
       
   122 	}
       
   123 
       
   124 	if (instance != NULL) {
       
   125 		/* Find our instance */
       
   126 		sq_getstackobj(this->vm, -1, instance);
       
   127 		/* Add a reference to it, so it survives for ever */
       
   128 		sq_addref(this->vm, instance);
       
   129 	}
       
   130 	/* Store it in the class */
       
   131 	sq_setinstanceup(this->vm, -1, real_instance);
       
   132 
       
   133 	/* Reset the top */
       
   134 	sq_settop(this->vm, oldtop);
       
   135 
       
   136 	return true;
       
   137 }
       
   138 
       
   139 SquirrelCore::SquirrelCore()
       
   140 {
       
   141 	this->vm = sq_open(1024);
       
   142 
       
   143 	/* Handle compile-errors ourself, so we can display it nicely */
       
   144 	sq_setcompilererrorhandler(this->vm, &SquirrelCore::CompileError);
       
   145 	sq_notifyallexceptions(this->vm, SQTrue);
       
   146 	/* Set a good print-function */
       
   147 	sq_setprintfunc(this->vm, &SquirrelCore::PrintFunc);
       
   148 	/* Handle runtime-errors ourself, so we can display it nicely */
       
   149 	sq_newclosure(this->vm, &SquirrelCore::_RunError, 0);
       
   150 	sq_seterrorhandler(this->vm);
       
   151 
       
   152 	sq_pushroottable(this->vm);
       
   153 }
       
   154 
       
   155 bool SquirrelCore::LoadScript(const char *script)
       
   156 {
       
   157 	/* Load and run the script */
       
   158 	if (SQ_FAILED(sqstd_dofile(this->vm, script, SQFalse, SQTrue))) {
       
   159 		DEBUG(misc, 0, "[squirrel] Failed to compile '%s'", script);
       
   160 		return false;
       
   161 	}
       
   162 
       
   163 	return true;
       
   164 }
       
   165 
       
   166 SquirrelCore::~SquirrelCore()
       
   167 {
       
   168 	/* Clean up the stuff */
       
   169 	sq_pop(this->vm, 1);
       
   170 	sq_close(this->vm);
       
   171 }