Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2733 was 2710, checked in by rgrieder, 16 years ago

Merged buildsystem3 containing buildsystem2 containing Adi's buildsystem branch back to the trunk.
Please update the media directory if you were not using buildsystem3 before.

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