Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1097 was 1076, checked in by rgrieder, 17 years ago

two hours of Fuk is very 'enlighting', the whole thing works now.\ncmake. will now build lua, then compile with tolua and finally create the Makefiles for orxonox.\n

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