Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/LuaBind.cc @ 2632

Last change on this file since 2632 was 2508, checked in by rgrieder, 16 years ago

Bugfix in LuaBind.cc

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Benjamin Knecht
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "LuaBind.h"
30
31#include <fstream>
32#include <map>
33
34#include "lua/lua.hpp"
35#include "tolua/tolua++.h"
36#include "tolua/tolua_bind.h"
37#include "util/String.h"
38#include "CoreIncludes.h"
39
40namespace orxonox
41{
42  LuaBind* LuaBind::singletonRef = NULL;
43
44  LuaBind::LuaBind()
45  {
46    luaState_ = lua_open();
47    luaSource_ = "";
48#if LUA_VERSION_NUM == 501
49    luaL_openlibs(luaState_);
50#else
51    luaopen_base(luaState_);
52    luaopen_string(luaState_);
53    luaopen_table(luaState_);
54    luaopen_math(luaState_);
55    luaopen_io(luaState_);
56    luaopen_debug(luaState_);
57#endif
58    tolua_Core_open(luaState_);
59    output_ = "";
60    isRunning_ = false;
61  }
62
63  void LuaBind::luaPrint(std::string str)
64  {
65    output_ += str;
66//    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
67    COUT(5) << str;
68  }
69
70  /**
71      @brief Loads the specified file line by line
72      @param filename The filename of the file
73      @param luaTags if true, the loaded file gets stripped off luaTags
74  */
75  void LuaBind::loadFile(std::string filename, bool luaTags)
76  {
77    output_ = "";
78    std::ifstream file;
79    file.open(filename.c_str(), std::fstream::in);
80
81    if (!file.is_open())
82    {
83      // some error msg
84    }
85
86    char line[1024*32];
87    std::string levelString = "";
88
89    while (file.good() && !file.eof())
90    {
91      file.getline(line, 1024*32);
92      levelString += line;
93      levelString += "\n";
94    }
95
96    file.close();
97    //std::string output;
98
99    if (luaTags)
100      luaSource_ = replaceLuaTags(levelString);
101    else
102      luaSource_ = levelString;
103    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
104  }
105
106  void LuaBind::loadString(std::string code)
107  {
108    luaSource_ = code;
109    output_ = "";
110  }
111
112#if LUA_VERSION_NUM != 501
113  const char * LuaBind::lua_Chunkreader(lua_State *L, void *data, size_t *size)
114  {
115    LoadS* ls = ((LoadS*)data);
116    if (ls->size == 0) return NULL;
117    *size = ls->size;
118    ls->size = 0;
119    return ls->s;
120  }
121#endif
122  void LuaBind::run()
123  {
124    if (!isRunning_)
125    {
126      isRunning_ = true;
127      int error = 0;
128      std::string init =
129         "local scr = orxonox.LuaBind:getInstance()\n \
130          local debug = print\n \
131          print = function(s)\n \
132              scr:luaPrint(s)\n \
133          end\n \
134          include = function(f)\n \
135              file = assert(io.open(\"" + this->includePath_ + "\"..\"/\"..f))\n \
136              content = file:read(\"*a\")\n \
137              file:close()\n \
138              source = scr:replaceLuaTags(content)\n \
139              assert(loadstring(source))()\n \
140          end\n";
141      init += luaSource_;
142  #if LUA_VERSION_NUM == 501
143      error = luaL_loadstring(luaState_, init.c_str());
144  #else
145      LoadS ls;
146      ls.s = init.c_str();
147      ls.size = init.size();
148      error = lua_load(luaState_, &orxonox::LuaBind::lua_Chunkreader, &ls, init.c_str());
149  #endif
150      if (error == 0)
151      {
152        error = lua_pcall(luaState_, 0, 0, 0);
153      }
154      if (error != 0)
155      {
156        COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
157      }
158      isRunning_ = false;
159    }
160    else
161    {
162      COUT(2) << "Warning: Lua's run is called while running!" << std::endl;
163    }
164  }
165
166  std::string LuaBind::replaceLuaTags(const std::string& text)
167  {
168    // chreate map with all Lua tags
169    std::map<size_t, bool> luaTags;
170    {
171      size_t pos = 0;
172      while ((pos = text.find("<?lua", pos)) != std::string::npos)
173        luaTags[pos++] = true;
174    }
175    {
176      size_t pos = 0;
177      while ((pos = text.find("?>", pos)) != std::string::npos)
178        luaTags[pos++] = false;
179    }
180
181    // erase all tags from the map that are between two quotes
182    {
183      std::map<size_t, bool>::iterator it = luaTags.begin();
184      std::map<size_t, bool>::iterator it2 = it;
185      bool bBetweenQuotes = false;
186      size_t pos = 0;
187      while ((pos = getNextQuote(text, pos)) != std::string::npos)
188      {
189        while ((it != luaTags.end()) && (it->first < pos))
190        {
191          if (bBetweenQuotes) {
192            it2++;
193            if(it->second && !(it2->second) && it2->first < pos)
194              it = ++it2;
195            else
196              luaTags.erase(it++);
197          }
198          else
199            ++it;
200        }
201        bBetweenQuotes = !bBetweenQuotes;
202        pos++;
203      }
204    }
205
206    // check whether on every opening <?lua tag a closing ?> tag follows
207    {
208      bool expectedValue = true;
209      for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
210      {
211        if (it->second == expectedValue)
212          expectedValue = !expectedValue;
213        else
214        {
215          expectedValue = false;
216          break;
217        }
218      }
219      if (!expectedValue) {
220        COUT(2) << "Warning: Error in level file" << std::endl;
221        // todo: errorhandling
222        return "";
223      }
224    }
225
226    // cut the original string into pieces and put them together with print() instead of lua tags
227    std::string output;
228    {
229      std::map<size_t, bool>::iterator it = luaTags.begin();
230      bool bInPrintFunction = true;
231      size_t start = 0;
232      size_t end = 0;
233
234      do
235      {
236        if (it != luaTags.end())
237          end = (*(it++)).first;
238        else
239          end = std::string::npos;
240
241        unsigned int equalSignCounter = 0;
242
243        if (bInPrintFunction)
244        {
245          // count ['='[ and ]'='] and replace tags with print([[ and ]])
246          std::string temp = text.substr(start, end - start);
247          {
248            size_t pos = 0;
249            while ((pos = temp.find('[', pos)) != std::string::npos)
250            {
251              unsigned int tempCounter = 1;
252              size_t tempPos = pos++;
253              while(temp[++tempPos] == '=') {
254                tempCounter++;
255              }
256              if(temp[tempPos] != '[') {
257                tempCounter = 0;
258              }
259              else if(tempCounter == 0) {
260                tempCounter = 1;
261              }
262              if (tempCounter > equalSignCounter)
263                equalSignCounter = tempCounter;
264            }
265          }
266          {
267            size_t pos = 0;
268            while ((pos = temp.find(']', pos)) != std::string::npos)
269            {
270              unsigned int tempCounter = 1;
271              size_t tempPos = pos++;
272              while(temp[++tempPos] == '=') {
273                tempCounter++;
274              }
275              if(temp[tempPos] != ']') {
276                tempCounter = 0;
277              }
278              else if(tempCounter == 0) {
279                tempCounter = 1;
280              }
281              if (tempCounter > equalSignCounter)
282                equalSignCounter = tempCounter;
283            }
284          }
285          std::string equalSigns = "";
286          for(unsigned int i = 0; i < equalSignCounter; i++) {
287            equalSigns += "=";
288          }
289          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
290          start = end + 5;
291        }
292        else
293        {
294          output += text.substr(start, end - start);
295          start = end + 2;
296        }
297
298        bInPrintFunction = !bInPrintFunction;
299      }
300      while (end != std::string::npos);
301    }
302
303    return output;
304  }
305
306}
Note: See TracBrowser for help on using the repository browser.