Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

don't panic, no codechanges!
added a link to www.orxonox.net

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 "util/tolua/tolua++.h"
42#include "ToLuaBind.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.