Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ceguilua/src/core/Script.cc @ 1875

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

Implemented lua and ceguilua as far as it works now with visual studio. Next (not so big) step is to integrate it in CMake (already did the most part).

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