Added Scripting class to bundle up all the Squirrel init code
[supertux.git] / src / scripting / scripting.cpp
1 //  SuperTux
2 //  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
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
17 #include "scripting/scripting.hpp"
18
19 #include <sqstdaux.h>
20 #include <sqstdblob.h>
21 #include <sqstdmath.h>
22 #include <sqstdstring.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "physfs/ifile_stream.hpp"
27 #include "scripting/squirrel_error.hpp"
28 #include "scripting/wrapper.hpp"
29 #include "squirrel_util.hpp"
30 #include "supertux/console.hpp"
31 #include "util/log.hpp"
32
33 #ifdef ENABLE_SQDBG
34 #  include "../../external/squirrel/sqdbg/sqrdbg.h"
35 namespace {
36 HSQREMOTEDBG debugger = NULL;
37 } // namespace
38 #endif
39
40 namespace {
41
42 void printfunc(HSQUIRRELVM, const char* str, ...)
43 {
44   char buf[4096];
45   va_list arglist;
46   va_start(arglist, str);
47   vsnprintf(buf, sizeof(buf), str, arglist);
48   ConsoleBuffer::output << (const char*) buf << std::flush;
49   va_end(arglist);
50 }
51
52 } // namespace
53
54 namespace scripting {
55
56 HSQUIRRELVM global_vm = NULL;
57
58 Scripting::Scripting(bool enable_debugger)
59 {
60   global_vm = sq_open(64);
61   if(global_vm == NULL)
62     throw std::runtime_error("Couldn't initialize squirrel vm");
63
64   if(enable_debugger) {
65 #ifdef ENABLE_SQDBG
66     sq_enabledebuginfo(global_vm, SQTrue);
67     debugger = sq_rdbg_init(global_vm, 1234, SQFalse);
68     if(debugger == NULL)
69       throw SquirrelError(global_vm, "Couldn't initialize squirrel debugger");
70
71     sq_enabledebuginfo(global_vm, SQTrue);
72     log_info << "Waiting for debug client..." << std::endl;
73     if(SQ_FAILED(sq_rdbg_waitforconnections(debugger)))
74       throw SquirrelError(global_vm, "Waiting for debug clients failed");
75     log_info << "debug client connected." << std::endl;
76 #endif
77   }
78
79   sq_pushroottable(global_vm);
80   if(SQ_FAILED(sqstd_register_bloblib(global_vm)))
81     throw SquirrelError(global_vm, "Couldn't register blob lib");
82   if(SQ_FAILED(sqstd_register_mathlib(global_vm)))
83     throw SquirrelError(global_vm, "Couldn't register math lib");
84   if(SQ_FAILED(sqstd_register_stringlib(global_vm)))
85     throw SquirrelError(global_vm, "Couldn't register string lib");
86
87   // remove rand and srand calls from sqstdmath, we'll provide our own
88   sq_pushstring(global_vm, "srand", -1);
89   sq_deleteslot(global_vm, -2, SQFalse);
90   sq_pushstring(global_vm, "rand", -1);
91   sq_deleteslot(global_vm, -2, SQFalse);
92
93   // register supertux API
94   register_supertux_wrapper(global_vm);
95
96   sq_pop(global_vm, 1);
97
98   // register print function
99   sq_setprintfunc(global_vm, printfunc, printfunc);
100   // register default error handlers
101   sqstd_seterrorhandlers(global_vm);
102
103   // try to load default script
104   try {
105     std::string filename = "scripts/default.nut";
106     IFileStream stream(filename);
107     scripting::compile_and_run(global_vm, stream, filename);
108   } catch(std::exception& e) {
109     log_warning << "Couldn't load default.nut: " << e.what() << std::endl;
110   }
111 }
112
113 Scripting::~Scripting()
114 {
115 #ifdef ENABLE_SQDBG
116   if(debugger != NULL) {
117     sq_rdbg_shutdown(debugger);
118     debugger = NULL;
119   }
120 #endif
121
122   if (global_vm)
123     sq_close(global_vm);
124
125   global_vm = NULL;
126 }
127   
128 void
129 Scripting::update_debugger()
130 {
131 #ifdef ENABLE_SQDBG
132   if(debugger != NULL)
133     sq_rdbg_update(debugger);
134 #endif
135 }
136
137 } // namespace scripting
138
139 /* EOF */