Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1076 was 1076, checked in by rgrieder, 16 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
RevLine 
[946]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1056]3 *                    > www.orxonox.net <
[946]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"
[956]30
31#include <fstream>
[996]32#include <map>
[956]33
[1037]34#include "CoreIncludes.h"
[996]35
[954]36extern "C" {
[1048]37#include <lualib.h>
38#include <lauxlib.h>
[954]39}
[946]40
[1076]41#include "tolua++.h"
42#include "tolua/tolua_bind.h"
[946]43
44namespace orxonox
45{
[1019]46  Script* Script::singletonRef = NULL;
[996]47
[946]48  Script::Script()
49  {
[999]50    luaState_ = lua_open();
51    luaSource_ = "";
[1029]52#if LUA_VERSION_NUM == 501
[1019]53    luaL_openlibs(luaState_);
[1029]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
[1019]62    tolua_orxonox_open(luaState_);
[1034]63    output_ = "";
[996]64  }
[956]65
[996]66  void Script::luaPrint(std::string str)
[946]67  {
[1019]68    output_ += str;
[1024]69    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
[946]70  }
71
[956]72  /**
73      @brief Loads the specified file line by line
74      @param filename The filename of the file
[996]75      @param luaTags if true, the loaded file gets stripped off luaTags
[956]76  */
[996]77  void Script::loadFile(std::string filename, bool luaTags)
[956]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];
[999]88    std::string levelString = "";
[956]89
90    while (file.good() && !file.eof())
91    {
92      file.getline(line, 1024);
[999]93      levelString += line;
[1019]94      levelString += "\n";
[956]95    }
96
[996]97    file.close();
98    //std::string output;
[956]99
[999]100    if (luaTags) luaSource_ = replaceLuaTags(levelString);
[1024]101    COUT(4) << "ParsedSourceCode: " << luaSource_ << std::endl;
[956]102  }
103
[996]104  void Script::run()
[956]105  {
[996]106    int error = 0;
[1019]107    std::string init = "local scr = orxonox.Script:getInstance()\nprint = function(s)\nscr:luaPrint(s)\nend\n";
[999]108    init += luaSource_;
[1029]109#if LUA_VERSION_NUM == 501
[996]110    error = luaL_loadstring(luaState_, init.c_str());
[1029]111#else
[1038]112    error = lua_load(luaState_, &orxonox::Script::lua_Chunkreader, (void*)init.c_str(), "init");
[1029]113#endif
[996]114    if (error == 0)
115      error = lua_pcall(luaState_, 0, 0, 0);
[1024]116    if (error != 0) COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
[996]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)
[956]124    {
[996]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();
[1019]156      std::map<unsigned int, bool>::iterator it2 = it;
[996]157      bool bBetweenQuotes = false;
158      unsigned int pos = 0;
159      while ((pos = getNextQuote(text, pos)) != std::string::npos)
[956]160      {
[1019]161        while ((it != luaTags.end()) && (it->first < pos))
[996]162        {
[1019]163          if (bBetweenQuotes) {
164            it2++;
165            if(it->second && !(it2->second) && it2->first < pos)
166              it = ++it2;
167            else
168              luaTags.erase(it++);
169          }
[996]170          else
171            ++it;
172        }
173        bBetweenQuotes = !bBetweenQuotes;
174        pos++;
[956]175      }
[996]176    }
[956]177
[996]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)
[956]182      {
[996]183        if ((*it).second == expectedValue)
184          expectedValue = !expectedValue;
185        else
186        {
187          expectedValue = false;
188          break;
189        }
[956]190      }
[996]191      if (!expectedValue) {
192        // todo: errorhandling
193        return "";
194      }
[956]195    }
[996]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          }
[1019]260          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
[996]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;
[956]275  }
276
[946]277}
Note: See TracBrowser for help on using the repository browser.