Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/core/Script.cc @ 1037

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

moved tolua from util to core because of circular dependencies
reverted some bugfixes in ParticleInterface

File size: 7.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Benjamin Knecht
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include "Script.h"
29
30#include <fstream>
31#include <map>
32
33#include "CoreIncludes.h"
34
35extern "C" {
36#include "lualib.h"
37#include "lauxlib.h"
38}
39
40#include "tolua/tolua++.h"
41#include "tolua/tolua_bind.h"
42
43namespace orxonox
44{
45  Script* Script::singletonRef = NULL;
46
47  Script::Script()
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_orxonox_open(luaState_);
62    output_ = "";
63  }
64
65  void Script::luaPrint(std::string str)
66  {
67    output_ += str;
68    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
69  }
70
71  /**
72      @brief Loads the specified file line by line
73      @param filename The filename of the file
74      @param luaTags if true, the loaded file gets stripped off luaTags
75  */
76  void Script::loadFile(std::string filename, bool luaTags)
77  {
78    std::ifstream file;
79    file.open(filename.c_str(), std::fstream::in);
80
81    if (!file.is_open())
82    {
83      // some error msg
84    }
85
86    char line[1024];
87    std::string levelString = "";
88
89    while (file.good() && !file.eof())
90    {
91      file.getline(line, 1024);
92      levelString += line;
93      levelString += "\n";
94    }
95
96    file.close();
97    //std::string output;
98
99    if (luaTags) luaSource_ = replaceLuaTags(levelString);
100    COUT(4) << "ParsedSourceCode: " << luaSource_ << std::endl;
101  }
102
103  void Script::run()
104  {
105    int error = 0;
106    std::string init = "local scr = orxonox.Script:getInstance()\nprint = function(s)\nscr:luaPrint(s)\nend\n";
107    init += luaSource_;
108#if LUA_VERSION_NUM == 501
109    error = luaL_loadstring(luaState_, init.c_str());
110#else
111    error = lua_load(luaState_, &orxonox::Script::lua_Chunkreader, init.c_str(), "init");
112#endif
113    if (error == 0)
114      error = lua_pcall(luaState_, 0, 0, 0);
115    if (error != 0) COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
116  }
117
118  unsigned int Script::getNextQuote(const std::string& text, unsigned int start)
119  {
120    unsigned int quote = start - 1;
121
122    while ((quote = text.find('\"', quote + 1)) != std::string::npos)
123    {
124      unsigned int backslash = quote;
125      unsigned int numbackslashes = 0;
126      for (; backslash > 0; backslash--, numbackslashes++)
127        if (text[backslash - 1] != '\\')
128          break;
129
130      if (numbackslashes % 2 == 0)
131        break;
132    }
133
134    return quote;
135  }
136
137  std::string Script::replaceLuaTags(const std::string& text)
138  {
139    // chreate map with all Lua tags
140    std::map<unsigned int, bool> luaTags;
141    {
142      unsigned int pos = 0;
143      while ((pos = text.find("<?lua", pos)) != std::string::npos)
144        luaTags[pos++] = true;
145    }
146    {
147      unsigned int pos = 0;
148      while ((pos = text.find("?>", pos)) != std::string::npos)
149        luaTags[pos++] = false;
150    }
151
152    // erase all tags from the map that are between two quotes
153    {
154      std::map<unsigned int, bool>::iterator it = luaTags.begin();
155      std::map<unsigned int, bool>::iterator it2 = it;
156      bool bBetweenQuotes = false;
157      unsigned int pos = 0;
158      while ((pos = getNextQuote(text, pos)) != std::string::npos)
159      {
160        while ((it != luaTags.end()) && (it->first < pos))
161        {
162          if (bBetweenQuotes) {
163            it2++;
164            if(it->second && !(it2->second) && it2->first < pos)
165              it = ++it2;
166            else
167              luaTags.erase(it++);
168          }
169          else
170            ++it;
171        }
172        bBetweenQuotes = !bBetweenQuotes;
173        pos++;
174      }
175    }
176
177    // check whether on every opening <?lua tag a closing ?> tag follows
178    {
179      bool expectedValue = true;
180      for (std::map<unsigned int, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
181      {
182        if ((*it).second == expectedValue)
183          expectedValue = !expectedValue;
184        else
185        {
186          expectedValue = false;
187          break;
188        }
189      }
190      if (!expectedValue) {
191        // todo: errorhandling
192        return "";
193      }
194    }
195
196    // cut the original string into pieces and put them together with print() instead of lua tags
197    std::string output;
198    {
199      std::map<unsigned int, bool>::iterator it = luaTags.begin();
200      bool bInPrintFunction = true;
201      unsigned int start = 0;
202      unsigned int end = 0;
203
204      do
205      {
206        if (it != luaTags.end())
207          end = (*(it++)).first;
208        else
209          end = std::string::npos;
210
211        unsigned int equalSignCounter = 0;
212
213        if (bInPrintFunction)
214        {
215          // count ['='[ and ]'='] and replace tags with print([[ and ]])
216          std::string temp = text.substr(start, end - start);
217          {
218            unsigned int pos = 0;
219            while ((pos = temp.find('[', pos)) != std::string::npos)
220            {
221              unsigned int tempCounter = 1;
222              unsigned int tempPos = pos++;
223              while(temp[++tempPos] == '=') {
224                tempCounter++;
225              }
226              if(temp[tempPos] != '[') {
227                tempCounter = 0;
228              }
229              else if(tempCounter == 0) {
230                tempCounter = 1;
231              }
232              if (tempCounter > equalSignCounter)
233                equalSignCounter = tempCounter;
234            }
235          }
236          {
237            unsigned int pos = 0;
238            while ((pos = temp.find(']', pos)) != std::string::npos)
239            {
240              unsigned int tempCounter = 1;
241              unsigned int tempPos = pos++;
242              while(temp[++tempPos] == '=') {
243                tempCounter++;
244              }
245              if(temp[tempPos] != ']') {
246                tempCounter = 0;
247              }
248              else if(tempCounter == 0) {
249                tempCounter = 1;
250              }
251              if (tempCounter > equalSignCounter)
252                equalSignCounter = tempCounter;
253            }
254          }
255          std::string equalSigns = "";
256          for(unsigned int i = 0; i < equalSignCounter; i++) {
257            equalSigns += "=";
258          }
259          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
260          start = end + 5;
261        }
262        else
263        {
264          output += text.substr(start, end - start);
265          start = end + 2;
266        }
267
268        bInPrintFunction = !bInPrintFunction;
269      }
270      while (end != std::string::npos);
271    }
272
273    return output;
274  }
275
276}
Note: See TracBrowser for help on using the repository browser.