Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3079 was 3068, checked in by landauf, 16 years ago

removing svn:mergeinfo again after sound2 merge

  • Property svn:eol-style set to native
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::getMediaPathString();
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.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.