]> git.lizzy.rs Git - minetest.git/blob - src/script/common/c_internal.cpp
2866cfe86449cc7f78f7b07fe8ae787ba81c7d26
[minetest.git] / src / script / common / c_internal.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "common/c_internal.h"
21 #include "debug.h"
22
23 std::string script_get_backtrace(lua_State *L)
24 {
25         std::string s;
26         lua_getglobal(L, "debug");
27         if(lua_istable(L, -1)){
28                 lua_getfield(L, -1, "traceback");
29                 if(lua_isfunction(L, -1)) {
30                         lua_call(L, 0, 1);
31                         if(lua_isstring(L, -1)){
32                                 s = lua_tostring(L, -1);
33                         }
34                 }
35                 lua_pop(L, 1);
36         }
37         lua_pop(L, 1);
38         return s;
39 }
40
41 int script_error_handler(lua_State *L) {
42         lua_getglobal(L, "debug");
43         if (!lua_istable(L, -1)) {
44                 lua_pop(L, 1);
45                 return 1;
46         }
47         lua_getfield(L, -1, "traceback");
48         if (!lua_isfunction(L, -1)) {
49                 lua_pop(L, 2);
50                 return 1;
51         }
52         lua_pushvalue(L, 1);
53         lua_pushinteger(L, 2);
54         lua_call(L, 2, 1);
55         return 1;
56 }
57
58 void script_error(lua_State *L)
59 {
60         const char *s = lua_tostring(L, -1);
61         std::string str(s ? s : "");
62         throw LuaError(NULL, str);
63 }
64
65 // Push the list of callbacks (a lua table).
66 // Then push nargs arguments.
67 // Then call this function, which
68 // - runs the callbacks
69 // - replaces the table and arguments with the return value,
70 //     computed depending on mode
71 void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode)
72 {
73         assert(lua_gettop(L) >= nargs + 1);
74
75         // Insert error handler
76         lua_pushcfunction(L, script_error_handler);
77         int errorhandler = lua_gettop(L) - nargs - 1;
78         lua_insert(L, errorhandler);
79
80         // Insert minetest.run_callbacks between error handler and table
81         lua_getglobal(L, "minetest");
82         lua_getfield(L, -1, "run_callbacks");
83         lua_remove(L, -2);
84         lua_insert(L, errorhandler + 1);
85
86         // Insert mode after table
87         lua_pushnumber(L, (int) mode);
88         lua_insert(L, errorhandler + 3);
89
90         // Stack now looks like this:
91         // ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n>
92
93         if (lua_pcall(L, nargs + 2, 1, errorhandler)) {
94                 script_error(L);
95         }
96
97         lua_remove(L, -2); // Remove error handler
98 }
99
100