Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1055 was 1048, checked in by rgrieder, 17 years ago
  • final commit for tolua++ displacement
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 "util/tolua/tolua++.h"
41#include "ToLuaBind.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, (void*)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.