Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/Script.cc @ 1848

Last change on this file since 1848 was 1810, checked in by rgrieder, 16 years ago

merged ceguilua branch back to trunk

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