Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/core/Script.cc @ 1638

Last change on this file since 1638 was 1638, checked in by rgrieder, 16 years ago

merged input branch into gui test branch (was about time)
svn save (it's still a mess and CMLs haven't been updated)
I'll have to create a special project to create the tolua_bind files for tolua itself anyway..

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