source: Plugins/luaScripting/Script.cpp @ 18

Revision 18, 7.1 KB checked in by art, 13 years ago (diff)
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 0
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         for (i = 1; i <= top; i++) { /* repeat for each level */
27                 int t = lua_type(L, i);
28                 switch (t) {
29 
30                         case LUA_TSTRING: /* strings */
31                                 printf("string: `%s'", lua_tostring(L, i));
32                                 break;
33 
34                        case LUA_TBOOLEAN: /* booleans */
35                                 printf(lua_toboolean(L, i) ? "true" : "false");
36                                 break;
37 
38                        case LUA_TNUMBER: /* numbers */
39                                printf("number: %g", lua_tonumber(L, i));
40                                 break;
41 
42                        default: /* other values */
43                                 printf("type: %s", lua_typename(L, t));
44                                 break;
45 
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        return OK;
111}
112               
113//----------------------------------------------------------------------------------
114Result LuaScript::unloadRes()
115{
116        if (isResLoaded())
117        {
118                luaL_unref(State, LUA_REGISTRYINDEX, mFuncRef);
119                mFuncRef = LUA_NOREF;
120        }
121       
122        return OK;
123}
124
125
126//----------------------------------------------------------------------------------
127Result LuaScript::run()
128{
129        // check consistency
130        if (lua_gettop(State))
131        {
132                pushErrorMessage(std::string("luaScript: The stack must be empty when calling a function!"));
133                return SCRIPT_ERROR;
134        }
135       
136        // load the script on the top
137        lua_rawgeti(State, LUA_REGISTRYINDEX, mFuncRef);
138        lua_getfield(State, -1, "main");
139
140        if (lua_isfunction(State, -1))
141        {
142                // let lua run the script and check for return codes
143                int32 res = lua_pcall(State, 0, LUA_MULTRET, 0);
144       
145                if (res != 0){
146                        // get error from the lua stack and give it in the log file
147                        const char* error = lua_tostring(State, -1);
148                        lua_pop(State, lua_gettop(State));
149                        pushErrorMessage(std::string("luaScript: Error in execution - ") + std::string(error));
150                        return SCRIPT_ERROR;
151                }       
152        }
153       
154        // we just run the script, we are not interested in results, so clear the stack
155        lua_pop(State, lua_gettop(State));
156
157        return OK;
158}
159
160
161//----------------------------------------------------------------------------------
162Result LuaScript::callfunc(const std::string& funcName, ScriptResult& result)
163{
164        // check consistency
165        if (lua_gettop(State))
166        {
167                pushErrorMessage(std::string("luaScript: The stack must be empty when calling a function!"));
168                return SCRIPT_ERROR;
169        }
170
171        // load the script on the top
172        lua_rawgeti(State, LUA_REGISTRYINDEX, mFuncRef);
173
174        // set the function to be called
175        lua_getfield(State, -1, funcName.c_str());
176
177        // check if is a valid function
178        if (lua_gettop(State) == 0 || lua_isfunction(State, -1) == 0){
179                lua_pop(State, lua_gettop(State));
180                pushErrorMessage(std::string("luaScript: Can not find function ") + funcName);
181                return SCRIPT_FUNCTION_NOT_FOUND;
182        }
183
184        // parameter count
185        int32 argn = 0;
186       
187        // ok retrieve arguments from the argument list and push them on lua stack
188        while (true)
189        {
190                // get the arguemnt
191                std::string type, value;
192                int32 count = popArgument(funcName, type, value);
193                if (count == -1) break;
194
195                // now check for the type and do conversion
196                try{
197                        if (type == "string")
198                                lua_pushstring(State, value.c_str());
199                        else if (type == "number")
200                                lua_pushnumber(State, boost::lexical_cast<lua_Number>(value));
201                        else if (type == "bool"){
202                                if (value == "yes" || value == "true" || value == "on" || value == "1")
203                                        lua_pushboolean(State, 1);
204                                else
205                                        lua_pushboolean(State, 0);
206                        }
207                } catch (boost::bad_lexical_cast s) {
208                        pushErrorMessage(std::string("luaScript: Wrong parameter value ") + value + std::string(" of type ") + type);
209                        return SCRIPT_WRONG_PARAMETER_VALUE;
210                }
211               
212                // increase argument number
213                argn ++;
214        }
215
216        // call the function and check for return code
217        int32 res = lua_pcall(State, argn, LUA_MULTRET, 0);
218
219        if (res != 0){
220                // get error from the lua stack and give it in the log file
221                const char* error = lua_tostring(State, -1);
222                lua_pop(State, lua_gettop(State));
223                pushErrorMessage(std::string("luaScript: Error in execution - ") + std::string(error));
224                return SCRIPT_ERROR;
225        }
226
227        // now retrieve all results from the stack and return
228        // do only get results until the last element on the stack
229        // because this is our environment tabkle
230        result.empty();
231        while (lua_gettop(State) > 1){
232                const char* str = lua_popstring(State);
233                result , std::string(str);
234        }
235
236        // remove the last element from the stack
237        lua_pop(State, 1);
238       
239        return OK;
240}
Note: See TracBrowser for help on using the repository browser.