Massive copyright update. I'm sorry if I'm crediting Matze for something he didn...
[supertux.git] / src / scripting / wrapper_util.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <config.h>
21
22 #include <stdexcept>
23 #include <sstream>
24 #include "wrapper_util.hpp"
25
26 namespace Scripting
27 {
28
29 std::string squirrel2string(HSQUIRRELVM v, int i)
30 {
31   std::ostringstream os;
32   switch(sq_gettype(v, i))
33     {
34     case OT_NULL:
35       os << "<null>";        
36       break;
37     case OT_BOOL: {
38       SQBool p;
39       sq_getbool(v, i, &p);
40       if (p) 
41         os << "true";
42       else
43         os << "false";
44       break;
45     }
46     case OT_INTEGER: {
47       int val;
48       sq_getinteger(v, i, &val);
49       os << val;
50       break;
51     }
52     case OT_FLOAT: {
53       float val;
54       sq_getfloat(v, i, &val);
55       os << val;
56       break;
57     }
58     case OT_STRING: {
59       const char* val;
60       sq_getstring(v, i, &val);
61       os << "\"" << val << "\"";
62       break;    
63     }
64     case OT_TABLE: {
65       bool first = true;
66       os << "{";
67       sq_pushnull(v);  //null iterator
68       while(SQ_SUCCEEDED(sq_next(v,i-1)))
69         {
70           if (!first) {
71             os << ", ";
72           }
73           first = false;
74
75           //here -1 is the value and -2 is the key
76           os << squirrel2string(v, -2) << " => " 
77              << squirrel2string(v, -1);
78                               
79           sq_pop(v,2); //pops key and val before the nex iteration
80         }
81       sq_pop(v, 1);
82       os << "}";
83       break;
84     }
85     case OT_ARRAY: {
86       bool first = true;
87       os << "[";
88       sq_pushnull(v);  //null iterator
89       while(SQ_SUCCEEDED(sq_next(v,i-1)))
90         {
91           if (!first) {
92             os << ", ";
93           }
94           first = false;
95
96           //here -1 is the value and -2 is the key
97           // we ignore the key, since that is just the index in an array
98           os << squirrel2string(v, -1);
99                               
100           sq_pop(v,2); //pops key and val before the nex iteration
101         }
102       sq_pop(v, 1);
103       os << "]";
104       break;
105     }
106     case OT_USERDATA:
107       os << "<userdata>";
108       break;
109     case OT_CLOSURE:        
110       os << "<closure (function)>";
111       break;
112     case OT_NATIVECLOSURE:
113       os << "<native closure (C function)>";
114       break;
115     case OT_GENERATOR:
116       os << "<generator>";
117       break;
118     case OT_USERPOINTER:
119       os << "userpointer";
120       break;
121     case OT_THREAD:
122       os << "<thread>";
123       break;
124     case OT_CLASS:
125       os << "<class>";
126       break;
127     case OT_INSTANCE:
128       os << "<instance>";
129       break;
130     default:
131       os << "<unknown>";
132       break;
133     }
134   return os.str();
135 }
136
137 void print_squirrel_stack(HSQUIRRELVM v)
138 {
139     printf("--------------------------------------------------------------\n");
140     int count = sq_gettop(v);
141     for(int i = 1; i <= count; ++i) {
142         printf("%d: ",i);
143         switch(sq_gettype(v, i))
144         {
145             case OT_NULL:
146                 printf("null");        
147                 break;
148             case OT_INTEGER: {
149                 int val;
150                 sq_getinteger(v, i, &val);
151                 printf("integer (%d)", val);
152                 break;
153             }
154             case OT_FLOAT: {
155                 float val;
156                 sq_getfloat(v, i, &val);
157                 printf("float (%f)", val);
158                 break;
159             }
160             case OT_STRING: {
161                 const char* val;
162                 sq_getstring(v, i, &val);
163                 printf("string (%s)", val);
164                 break;    
165             }
166             case OT_TABLE:
167                 printf("table");
168                 break;
169             case OT_ARRAY:
170                 printf("array");
171                 break;
172             case OT_USERDATA:
173                 printf("userdata");
174                 break;
175             case OT_CLOSURE:        
176                 printf("closure(function)");    
177                 break;
178             case OT_NATIVECLOSURE:
179                 printf("native closure(C function)");
180                 break;
181             case OT_GENERATOR:
182                 printf("generator");
183                 break;
184             case OT_USERPOINTER:
185                 printf("userpointer");
186                 break;
187             case OT_THREAD:
188                 printf("thread");
189                 break;
190             case OT_CLASS:
191                 printf("class");
192                 break;
193             case OT_INSTANCE:
194                 printf("instance");
195                 break;
196             default:
197                 printf("unknown?!?");
198                 break;
199         }
200         printf("\n");
201     }
202     printf("--------------------------------------------------------------\n");
203 }
204
205 static SQInteger squirrel_read_char(SQUserPointer file)
206 {
207   std::istream* in = reinterpret_cast<std::istream*> (file);
208   char c = in->get();
209   if(in->eof())
210     return 0;
211   return c;
212 }
213
214 void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
215 {
216   if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true)))
217     throw SquirrelError(vm, "Couldn't parse script");  
218 }
219
220 void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
221 {
222   compile_script(vm, in, sourcename);
223   
224   int oldtop = sq_gettop(vm);
225
226   try {
227     sq_pushroottable(vm);
228     if(SQ_FAILED(sq_call(vm, 1, false)))
229       throw SquirrelError(vm, "Couldn't start script");
230   } catch(...) {
231     sq_settop(vm, oldtop);
232     throw;
233   }
234
235   sq_settop(vm, oldtop);
236 }
237
238 }