source: Plugins/luaScripting/Script.cpp @ 27

Revision 27, 7.2 KB checked in by art, 12 years ago (diff)

nrScript: using of subscripts is now possible

Line 
1/***************************************************************************
2 *                                                                         *
3 *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
4 *       mailto: <tevs@mpi-sb.mpg.de>                                      *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 ***************************************************************************/
12
13#include "Script.h"
14#include <boost/lexical_cast.hpp>
15
16lua_State*      LuaScript::State = NULL;
17
18#if 1
19// Dump all the contents of your lua_state (Lua Stack)
20 // Find out the location of ur table and try to print out the details by
21 // modifying the below code
22
23 static void stackDump (lua_State *L) {
24         int i;
25         int top = lua_gettop(L);
26         printf("Stack has %d elements\n", top);
27         for (i = 1; i <= top; i++) { /* repeat for each level */
28                 int t = lua_type(L, i);
29                 switch (t) {
30
31                         case LUA_TSTRING: /* strings */
32                                 printf("string: `%s'", lua_tostring(L, i));
33                                 break;
34
35                        case LUA_TBOOLEAN: /* booleans */
36                                 printf(lua_toboolean(L, i) ? "true" : "false");
37                                 break;
38
39                        case LUA_TNUMBER: /* numbers */
40                                printf("number: %g", lua_tonumber(L, i));
41                                 break;
42
43                        default: /* other values */
44                                 printf("type: %s", lua_typename(L, t));
45                                 break;
46                 }
47                 printf("\n"); /* put a separator */
48         }
49         printf("\n"); /* end the listing */
50 }
51#endif
52
53//----------------------------------------------------------------------------------
54LuaScript::LuaScript() : IScript("LuaScript")
55{
56        mFuncRef = LUA_NOREF;
57}
58
59//----------------------------------------------------------------------------------
60LuaScript::~LuaScript()
61{
62
63}
64
65
66//----------------------------------------------------------------------------------
67Result LuaScript::loadFromString(const std::string& str)
68{
69        static bool loaded = false;
70
71        // load lua from string
72        mContent = str;
73
74        // first check if there is a lua function calling loadScript
75        // which is able to load scripts and setup environments
76        lua_getglobal(State, "loadstringscript");
77        if (lua_isfunction(State, -1))
78        {
79                // ok the function is defined, so use it to load scripts
80                lua_pushstring(State, str.c_str());
81                if (lua_pcall(State, 1, 1, 0))
82                {
83                        const char* error = lua_tostring(State, -1);
84                        lua_pop(State, lua_gettop(State));
85                        pushErrorMessage(std::string("luaScript: Error in execution in loadstringscript - ") + std::string(error));
86                        return SCRIPT_ERROR;
87                }
88                loaded = true;
89
90        // the function is not defined, so load the stuff in the default way
91        }else{
92                // use the default function instead
93                int32 result = luaL_dostring(State, mContent.c_str());
94                if (result == LUA_ERRSYNTAX){
95                        NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "luaScript: Error in script %s", getResName().c_str());
96                        return SCRIPT_PARSE_ERROR;
97                }else if (result == LUA_ERRMEM){
98                        NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "luaScript: Not enough memory to load script %s", getResName().c_str());
99                        return OUT_OF_MEMORY;
100                }
101        }
102
103        // now let keep the script in memory
104        mFuncRef = luaL_ref(State, LUA_REGISTRYINDEX);
105        if (mFuncRef == LUA_REFNIL && loaded){
106                NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "luaScript: Script could not be compiled %s", getResName().c_str());
107                return SCRIPT_ERROR;
108        }
109
110        notifyLoaded();
111
112        return OK;
113}
114
115//----------------------------------------------------------------------------------
116Result LuaScript::unloadRes()
117{
118        if (isResLoaded())
119        {
120                luaL_unref(State, LUA_REGISTRYINDEX, mFuncRef);
121                mFuncRef = LUA_NOREF;
122        }
123
124        return OK;
125}
126
127
128//----------------------------------------------------------------------------------
129Result LuaScript::run()
130{
131        // check consistency
132        if (lua_gettop(State))
133        {
134                pushErrorMessage(std::string("luaScript: The stack must be empty when calling a function!"));
135                stackDump(State);
136                return SCRIPT_ERROR;
137        }
138
139        // load the script on the top
140        lua_rawgeti(State, LUA_REGISTRYINDEX, mFuncRef);
141        lua_getfield(State, -1, "main");
142
143        if (lua_isfunction(State, -1))
144        {
145                // let lua run the script and check for return codes
146                int32 res = lua_pcall(State, 0, LUA_MULTRET, 0);
147
148                if (res != 0){
149                        // get error from the lua stack and give it in the log file
150                        const char* error = lua_tostring(State, -1);
151                        lua_pop(State, lua_gettop(State));
152                        pushErrorMessage(std::string("luaScript: Error in execution - ") + std::string(error));
153                        return SCRIPT_ERROR;
154                }
155        }
156
157        // we just run the script, we are not interested in results, so clear the stack
158        lua_pop(State, lua_gettop(State));
159
160        return OK;
161}
162
163
164//----------------------------------------------------------------------------------
165Result LuaScript::callfunc(const std::string& funcName, ScriptResult& result)
166{
167        // check consistency
168        if (lua_gettop(State))
169        {
170                pushErrorMessage(std::string("luaScript: The stack must be empty when calling a function!"));
171                stackDump(State);
172                return SCRIPT_ERROR;
173        }
174
175        // load the script on the top
176        lua_rawgeti(State, LUA_REGISTRYINDEX, mFuncRef);
177
178        // set the function to be called
179        lua_getfield(State, -1, funcName.c_str());
180
181        // check if is a valid function
182        if (lua_gettop(State) == 0 || lua_isfunction(State, -1) == 0){
183                lua_pop(State, lua_gettop(State));
184                pushErrorMessage(std::string("luaScript: Can not find function ") + funcName);
185                return SCRIPT_FUNCTION_NOT_FOUND;
186        }
187
188        // parameter count
189        int32 argn = 0;
190
191        // ok retrieve arguments from the argument list and push them on lua stack
192        while (true)
193        {
194                // get the arguemnt
195                std::string type, value;
196                int32 count = popArgument(funcName, type, value);
197                if (count == -1) break;
198
199                // now check for the type and do conversion
200                try{
201                        if (type == "string")
202                                lua_pushstring(State, value.c_str());
203                        else if (type == "number")
204                                lua_pushnumber(State, boost::lexical_cast<lua_Number>(value));
205                        else if (type == "bool"){
206                                if (value == "yes" || value == "true" || value == "on" || value == "1")
207                                        lua_pushboolean(State, 1);
208                                else
209                                        lua_pushboolean(State, 0);
210                        }
211                } catch (boost::bad_lexical_cast s) {
212                        pushErrorMessage(std::string("luaScript: Wrong parameter value ") + value + std::string(" of type ") + type);
213                        return SCRIPT_WRONG_PARAMETER_VALUE;
214                }
215
216                // increase argument number
217                argn ++;
218        }
219
220        // call the function and check for return code
221        int32 res = lua_pcall(State, argn, LUA_MULTRET, 0);
222
223        if (res != 0){
224                // get error from the lua stack and give it in the log file
225                const char* error = lua_tostring(State, -1);
226                lua_pop(State, lua_gettop(State));
227                pushErrorMessage(std::string("luaScript: Error in execution - ") + std::string(error));
228                return SCRIPT_ERROR;
229        }
230
231        // now retrieve all results from the stack and return
232        // do only get results until the last element on the stack
233        // because this is our environment tabkle
234        result.empty();
235        while (lua_gettop(State) > 1){
236                const char* str = lua_popstring(State);
237                result = result , std::string(str);
238        }
239
240        // remove the last element from the stack
241        lua_pop(State, 1);
242
243        return OK;
244}
Note: See TracBrowser for help on using the repository browser.