+// $Id$
+//
+// SuperTux
+// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
#include <config.h>
#include <stdexcept>
#include <sstream>
#include "wrapper_util.hpp"
-static void register_function(HSQUIRRELVM v, SQFUNCTION func, const char* name)
+namespace Scripting
{
- sq_pushstring(v, name, -1);
- sq_newclosure(v, func, 0); //create a new function
- sq_createslot(v, -3);
-}
-static void register_class(HSQUIRRELVM v, WrappedClass* wclass)
+std::string squirrel2string(HSQUIRRELVM v, int i)
{
- sq_pushstring(v, wclass->name, -1);
- sq_newclass(v, false);
- for(WrappedFunction* func = wclass->functions; func->name != 0; ++func) {
- register_function(v, func->f, func->name);
+ std::ostringstream os;
+ switch(sq_gettype(v, i))
+ {
+ case OT_NULL:
+ os << "<null>";
+ break;
+ case OT_BOOL: {
+ SQBool p;
+ sq_getbool(v, i, &p);
+ if (p)
+ os << "true";
+ else
+ os << "false";
+ break;
}
- sq_createslot(v, -3);
-}
+ case OT_INTEGER: {
+ int val;
+ sq_getinteger(v, i, &val);
+ os << val;
+ break;
+ }
+ case OT_FLOAT: {
+ float val;
+ sq_getfloat(v, i, &val);
+ os << val;
+ break;
+ }
+ case OT_STRING: {
+ const char* val;
+ sq_getstring(v, i, &val);
+ os << "\"" << val << "\"";
+ break;
+ }
+ case OT_TABLE: {
+ bool first = true;
+ os << "{";
+ sq_pushnull(v); //null iterator
+ while(SQ_SUCCEEDED(sq_next(v,i-1)))
+ {
+ if (!first) {
+ os << ", ";
+ }
+ first = false;
-void register_functions(HSQUIRRELVM v, WrappedFunction* functions)
-{
- sq_pushroottable(v);
- for(WrappedFunction* func = functions; func->name != 0; ++func) {
- register_function(v, func->f, func->name);
+ //here -1 is the value and -2 is the key
+ os << squirrel2string(v, -2) << " => "
+ << squirrel2string(v, -1);
+
+ sq_pop(v,2); //pops key and val before the nex iteration
+ }
+ sq_pop(v, 1);
+ os << "}";
+ break;
}
- sq_pop(v, 1);
-}
+ case OT_ARRAY: {
+ bool first = true;
+ os << "[";
+ sq_pushnull(v); //null iterator
+ while(SQ_SUCCEEDED(sq_next(v,i-1)))
+ {
+ if (!first) {
+ os << ", ";
+ }
+ first = false;
-void register_classes(HSQUIRRELVM v, WrappedClass* classes)
-{
- sq_pushroottable(v);
- for(WrappedClass* wclass = classes; wclass->name != 0; ++wclass) {
- register_class(v, wclass);
+ //here -1 is the value and -2 is the key
+ // we ignore the key, since that is just the index in an array
+ os << squirrel2string(v, -1);
+
+ sq_pop(v,2); //pops key and val before the nex iteration
+ }
+ sq_pop(v, 1);
+ os << "]";
+ break;
+ }
+ case OT_USERDATA:
+ os << "<userdata>";
+ break;
+ case OT_CLOSURE:
+ os << "<closure (function)>";
+ break;
+ case OT_NATIVECLOSURE:
+ os << "<native closure (C function)>";
+ break;
+ case OT_GENERATOR:
+ os << "<generator>";
+ break;
+ case OT_USERPOINTER:
+ os << "userpointer";
+ break;
+ case OT_THREAD:
+ os << "<thread>";
+ break;
+ case OT_CLASS:
+ os << "<class>";
+ break;
+ case OT_INSTANCE:
+ os << "<instance>";
+ break;
+ default:
+ os << "<unknown>";
+ break;
}
- sq_pop(v, 1);
+ return os.str();
}
void print_squirrel_stack(HSQUIRRELVM v)
case OT_USERPOINTER:
printf("userpointer");
break;
+ case OT_THREAD:
+ printf("thread");
+ break;
case OT_CLASS:
printf("class");
break;
printf("--------------------------------------------------------------\n");
}
-//----------------------------------------------------------------------------
-
-SquirrelError::SquirrelError(HSQUIRRELVM v, const std::string& message) throw()
+static SQInteger squirrel_read_char(SQUserPointer file)
{
- std::ostringstream msg;
- msg << "SQuirrel error: " << message << " (";
- const char* lasterr;
- sq_getlasterror(v);
- sq_getstring(v, -1, &lasterr);
- sq_pop(v, 1);
- msg << lasterr << ")";
- this->message = msg.str();
+ std::istream* in = reinterpret_cast<std::istream*> (file);
+ char c = in->get();
+ if(in->eof())
+ return 0;
+ return c;
}
-SquirrelError::~SquirrelError() throw()
-{}
+void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
+{
+ if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true)))
+ throw SquirrelError(vm, "Couldn't parse script");
+}
-const char*
-SquirrelError::what() const throw()
+void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
{
- return message.c_str();
+ compile_script(vm, in, sourcename);
+
+ int oldtop = sq_gettop(vm);
+
+ try {
+ sq_pushroottable(vm);
+ if(SQ_FAILED(sq_call(vm, 1, false)))
+ throw SquirrelError(vm, "Couldn't start script");
+ } catch(...) {
+ sq_settop(vm, oldtop);
+ throw;
+ }
+
+ sq_settop(vm, oldtop);
+}
+
}