squirrel_util.cpp 6.0 KB

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