Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2663 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 8.1 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_s = NULL;
43
44  LuaBind::LuaBind()
45  {
46    assert(LuaBind::singletonRef_s == 0);
47    LuaBind::singletonRef_s = this;
48
49    luaState_ = lua_open();
50    luaSource_ = "";
51#if LUA_VERSION_NUM == 501
52    luaL_openlibs(luaState_);
53#else
54    luaopen_base(luaState_);
55    luaopen_string(luaState_);
56    luaopen_table(luaState_);
57    luaopen_math(luaState_);
58    luaopen_io(luaState_);
59    luaopen_debug(luaState_);
60#endif
61    tolua_Core_open(luaState_);
62    output_ = "";
63    isRunning_ = false;
64  }
65
66  void LuaBind::luaPrint(std::string str)
67  {
68    output_ += str;
69//    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
70    COUT(5) << str;
71  }
72
73  /**
74      @brief Loads the specified file line by line
75      @param filename The filename of the file
76      @param luaTags if true, the loaded file gets stripped off luaTags
77  */
78  void LuaBind::loadFile(std::string filename, bool luaTags)
79  {
80    output_ = "";
81    std::ifstream file;
82    file.open(filename.c_str(), std::fstream::in);
83
84    if (!file.is_open())
85    {
86      // some error msg
87    }
88
89    char line[1024*32];
90    std::string levelString = "";
91
92    while (file.good() && !file.eof())
93    {
94      file.getline(line, 1024*32);
95      levelString += line;
96      levelString += "\n";
97    }
98
99    file.close();
100    //std::string output;
101
102    if (luaTags)
103      luaSource_ = replaceLuaTags(levelString);
104    else
105      luaSource_ = levelString;
106    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
107  }
108
109  void LuaBind::loadString(std::string code)
110  {
111    luaSource_ = code;
112    output_ = "";
113  }
114
115#if LUA_VERSION_NUM != 501
116  const char * LuaBind::lua_Chunkreader(lua_State *L, void *data, size_t *size)
117  {
118    LoadS* ls = ((LoadS*)data);
119    if (ls->size == 0) return NULL;
120    *size = ls->size;
121    ls->size = 0;
122    return ls->s;
123  }
124#endif
125  void LuaBind::run()
126  {
127    if (!isRunning_)
128    {
129      isRunning_ = true;
130      int error = 0;
131      std::string init =
132         "local scr = orxonox.LuaBind:getInstance()\n \
133          local debug = print\n \
134          print = function(s)\n \
135              scr:luaPrint(s)\n \
136          end\n \
137          include = function(f)\n \
138              file = assert(io.open(\"" + this->includePath_ + "\"..\"/\"..f))\n \
139              content = file:read(\"*a\")\n \
140              file:close()\n \
141              source = scr:replaceLuaTags(content)\n \
142              assert(loadstring(source))()\n \
143          end\n";
144      init += luaSource_;
145  #if LUA_VERSION_NUM == 501
146      error = luaL_loadstring(luaState_, init.c_str());
147  #else
148      LoadS ls;
149      ls.s = init.c_str();
150      ls.size = init.size();
151      error = lua_load(luaState_, &orxonox::LuaBind::lua_Chunkreader, &ls, init.c_str());
152  #endif
153      if (error == 0)
154      {
155        error = lua_pcall(luaState_, 0, 0, 0);
156      }
157      if (error != 0)
158      {
159        COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
160      }
161      isRunning_ = false;
162    }
163    else
164    {
165      COUT(2) << "Warning: Lua's run is called while running!" << std::endl;
166    }
167  }
168
169  std::string LuaBind::replaceLuaTags(const std::string& text)
170  {
171    // chreate map with all Lua tags
172    std::map<size_t, bool> luaTags;
173    {
174      size_t pos = 0;
175      while ((pos = text.find("<?lua", pos)) != std::string::npos)
176        luaTags[pos++] = true;
177    }
178    {
179      size_t pos = 0;
180      while ((pos = text.find("?>", pos)) != std::string::npos)
181        luaTags[pos++] = false;
182    }
183
184    // erase all tags from the map that are between two quotes
185    {
186      std::map<size_t, bool>::iterator it = luaTags.begin();
187      std::map<size_t, bool>::iterator it2 = it;
188      bool bBetweenQuotes = false;
189      size_t pos = 0;
190      while ((pos = getNextQuote(text, pos)) != std::string::npos)
191      {
192        while ((it != luaTags.end()) && (it->first < pos))
193        {
194          if (bBetweenQuotes) {
195            it2++;
196            if(it->second && !(it2->second) && it2->first < pos)
197              it = ++it2;
198            else
199              luaTags.erase(it++);
200          }
201          else
202            ++it;
203        }
204        bBetweenQuotes = !bBetweenQuotes;
205        pos++;
206      }
207    }
208
209    // check whether on every opening <?lua tag a closing ?> tag follows
210    {
211      bool expectedValue = true;
212      for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
213      {
214        if (it->second == expectedValue)
215          expectedValue = !expectedValue;
216        else
217        {
218          expectedValue = false;
219          break;
220        }
221      }
222      if (!expectedValue) {
223        COUT(2) << "Warning: Error in level file" << std::endl;
224        // todo: errorhandling
225        return "";
226      }
227    }
228
229    // cut the original string into pieces and put them together with print() instead of lua tags
230    std::string output;
231    {
232      std::map<size_t, bool>::iterator it = luaTags.begin();
233      bool bInPrintFunction = true;
234      size_t start = 0;
235      size_t end = 0;
236
237      do
238      {
239        if (it != luaTags.end())
240          end = (*(it++)).first;
241        else
242          end = std::string::npos;
243
244        unsigned int equalSignCounter = 0;
245
246        if (bInPrintFunction)
247        {
248          // count ['='[ and ]'='] and replace tags with print([[ and ]])
249          std::string temp = text.substr(start, end - start);
250          {
251            size_t pos = 0;
252            while ((pos = temp.find('[', pos)) != std::string::npos)
253            {
254              unsigned int tempCounter = 1;
255              size_t tempPos = pos++;
256              while(temp[++tempPos] == '=') {
257                tempCounter++;
258              }
259              if(temp[tempPos] != '[') {
260                tempCounter = 0;
261              }
262              else if(tempCounter == 0) {
263                tempCounter = 1;
264              }
265              if (tempCounter > equalSignCounter)
266                equalSignCounter = tempCounter;
267            }
268          }
269          {
270            size_t pos = 0;
271            while ((pos = temp.find(']', pos)) != std::string::npos)
272            {
273              unsigned int tempCounter = 1;
274              size_t tempPos = pos++;
275              while(temp[++tempPos] == '=') {
276                tempCounter++;
277              }
278              if(temp[tempPos] != ']') {
279                tempCounter = 0;
280              }
281              else if(tempCounter == 0) {
282                tempCounter = 1;
283              }
284              if (tempCounter > equalSignCounter)
285                equalSignCounter = tempCounter;
286            }
287          }
288          std::string equalSigns = "";
289          for(unsigned int i = 0; i < equalSignCounter; i++) {
290            equalSigns += "=";
291          }
292          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
293          start = end + 5;
294        }
295        else
296        {
297          output += text.substr(start, end - start);
298          start = end + 2;
299        }
300
301        bInPrintFunction = !bInPrintFunction;
302      }
303      while (end != std::string::npos);
304    }
305
306    return output;
307  }
308
309}
Note: See TracBrowser for help on using the repository browser.