Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/buildsystem3/src/core/LuaBind.cc @ 2667

Last change on this file since 2667 was 2664, checked in by rgrieder, 15 years ago

Merged buildsystem2 to buildsystem3.

Note: Bare merge, just resolved conflicts. To testing, no nothing.

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