3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #include "common/c_internal.h"
23 std::string script_get_backtrace(lua_State *L)
26 lua_getglobal(L, "debug");
27 if(lua_istable(L, -1)){
28 lua_getfield(L, -1, "traceback");
29 if(lua_isfunction(L, -1)) {
31 if(lua_isstring(L, -1)){
32 s = lua_tostring(L, -1);
41 int script_error_handler(lua_State *L) {
42 lua_getglobal(L, "debug");
43 if (!lua_istable(L, -1)) {
47 lua_getfield(L, -1, "traceback");
48 if (!lua_isfunction(L, -1)) {
53 lua_pushinteger(L, 2);
58 void script_error(lua_State *L)
60 const char *s = lua_tostring(L, -1);
61 std::string str(s ? s : "");
62 throw LuaError(NULL, str);
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 // - removes the table and arguments from the lua stack
70 // - pushes the return value, computed depending on mode
71 void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode)
73 // Insert the return value into the lua stack, below the table
74 assert(lua_gettop(L) >= nargs + 1);
77 int rv = lua_gettop(L) - nargs - 1;
80 // Insert error handler after return value
81 lua_pushcfunction(L, script_error_handler);
82 int errorhandler = rv + 1;
83 lua_insert(L, errorhandler);
85 // Stack now looks like this:
86 // ... <return value = nil> <error handler> <table> <arg#1> <arg#2> ... <arg#n>
88 int table = errorhandler + 1;
91 luaL_checktype(L, table, LUA_TTABLE);
95 bool first_loop = true;
96 while(lua_next(L, table) != 0){
97 // key at index -2 and value at index -1
98 luaL_checktype(L, -1, LUA_TFUNCTION);
100 for(int i = 0; i < nargs; i++)
101 lua_pushvalue(L, arg+i);
102 if(lua_pcall(L, nargs, 1, errorhandler))
105 // Move return value to designated space in stack
108 // Result of first callback is always moved
112 // Otherwise, what happens depends on the mode
113 if(mode == RUN_CALLBACKS_MODE_FIRST)
115 else if(mode == RUN_CALLBACKS_MODE_LAST)
117 else if(mode == RUN_CALLBACKS_MODE_AND ||
118 mode == RUN_CALLBACKS_MODE_AND_SC){
119 if((bool)lua_toboolean(L, rv) == true &&
120 (bool)lua_toboolean(L, -1) == false)
125 else if(mode == RUN_CALLBACKS_MODE_OR ||
126 mode == RUN_CALLBACKS_MODE_OR_SC){
127 if((bool)lua_toboolean(L, rv) == false &&
128 (bool)lua_toboolean(L, -1) == true)
137 // Handle short circuit modes
138 if(mode == RUN_CALLBACKS_MODE_AND_SC &&
139 (bool)lua_toboolean(L, rv) == false)
141 else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
142 (bool)lua_toboolean(L, rv) == true)
145 // value removed, keep key for next iteration
148 // Remove stuff from stack, leaving only the return value
151 // Fix return value in case no callbacks were called
153 if(mode == RUN_CALLBACKS_MODE_AND ||
154 mode == RUN_CALLBACKS_MODE_AND_SC){
156 lua_pushboolean(L, true);
158 else if(mode == RUN_CALLBACKS_MODE_OR ||
159 mode == RUN_CALLBACKS_MODE_OR_SC){
161 lua_pushboolean(L, false);