Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/core/Script.cc @ 1021

Last change on this file since 1021 was 1021, checked in by bknecht, 16 years ago

merged back that script-branch

File size: 7.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Benjamin Knecht
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include "Script.h"
29
30#include <fstream>
31#include <map>
32
33#include "../core/CoreIncludes.h"
34
35extern "C" {
36#include "lualib.h"
37#include "lauxlib.h"
38}
39
40#include "tolua++.h"
41#include "../../util/tolua/tolua_bind.h"
42
43namespace orxonox
44{
45  Script* Script::singletonRef = NULL;
46
47  Script::Script()
48  {
49    luaState_ = lua_open();
50    luaSource_ = "";
51    luaL_openlibs(luaState_);
52    tolua_orxonox_open(luaState_);
53    output_;
54  }
55
56  void Script::luaPrint(std::string str)
57  {
58    output_ += str;
59    COUT(0) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
60  }
61
62  /**
63      @brief Loads the specified file line by line
64      @param filename The filename of the file
65      @param luaTags if true, the loaded file gets stripped off luaTags
66  */
67  void Script::loadFile(std::string filename, bool luaTags)
68  {
69    std::ifstream file;
70    file.open(filename.c_str(), std::fstream::in);
71
72    if (!file.is_open())
73    {
74      // some error msg
75    }
76
77    char line[1024];
78    std::string levelString = "";
79
80    while (file.good() && !file.eof())
81    {
82      file.getline(line, 1024);
83      levelString += line;
84      levelString += "\n";
85    }
86
87    file.close();
88    //std::string output;
89
90    if (luaTags) luaSource_ = replaceLuaTags(levelString);
91    COUT(0) << "ParsedSourceCode: " << luaSource_ << std::endl;
92  }
93
94  void Script::run()
95  {
96    int error = 0;
97    std::string init = "local scr = orxonox.Script:getInstance()\nprint = function(s)\nscr:luaPrint(s)\nend\n";
98    init += luaSource_;
99    error = luaL_loadstring(luaState_, init.c_str());
100    if (error == 0)
101      error = lua_pcall(luaState_, 0, 0, 0);
102    if (error != 0) COUT(0) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
103  }
104
105
106  unsigned int Script::getNextQuote(const std::string& text, unsigned int start)
107  {
108    unsigned int quote = start - 1;
109
110    while ((quote = text.find('\"', quote + 1)) != std::string::npos)
111    {
112      unsigned int backslash = quote;
113      unsigned int numbackslashes = 0;
114      for (; backslash > 0; backslash--, numbackslashes++)
115        if (text[backslash - 1] != '\\')
116          break;
117
118      if (numbackslashes % 2 == 0)
119        break;
120    }
121
122    return quote;
123  }
124
125  std::string Script::replaceLuaTags(const std::string& text)
126  {
127    // chreate map with all Lua tags
128    std::map<unsigned int, bool> luaTags;
129    {
130      unsigned int pos = 0;
131      while ((pos = text.find("<?lua", pos)) != std::string::npos)
132        luaTags[pos++] = true;
133    }
134    {
135      unsigned int pos = 0;
136      while ((pos = text.find("?>", pos)) != std::string::npos)
137        luaTags[pos++] = false;
138    }
139
140    // erase all tags from the map that are between two quotes
141    {
142      std::map<unsigned int, bool>::iterator it = luaTags.begin();
143      std::map<unsigned int, bool>::iterator it2 = it;
144      bool bBetweenQuotes = false;
145      bool bBetweenTags = false;
146      unsigned int pos = 0;
147      while ((pos = getNextQuote(text, pos)) != std::string::npos)
148      {
149        while ((it != luaTags.end()) && (it->first < pos))
150        {
151          if (bBetweenQuotes) {
152            it2++;
153            if(it->second && !(it2->second) && it2->first < pos)
154              it = ++it2;
155            else
156              luaTags.erase(it++);
157          }
158          else
159            ++it;
160        }
161        bBetweenQuotes = !bBetweenQuotes;
162        pos++;
163      }
164    }
165
166    // check whether on every opening <?lua tag a closing ?> tag follows
167    {
168      bool expectedValue = true;
169      for (std::map<unsigned int, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
170      {
171        if ((*it).second == expectedValue)
172          expectedValue = !expectedValue;
173        else
174        {
175          expectedValue = false;
176          break;
177        }
178      }
179      if (!expectedValue) {
180        // todo: errorhandling
181        return "";
182      }
183    }
184
185    // cut the original string into pieces and put them together with print() instead of lua tags
186    std::string output;
187    {
188      std::map<unsigned int, bool>::iterator it = luaTags.begin();
189      bool bInPrintFunction = true;
190      unsigned int start = 0;
191      unsigned int end = 0;
192
193      do
194      {
195        if (it != luaTags.end())
196          end = (*(it++)).first;
197        else
198          end = std::string::npos;
199
200        unsigned int equalSignCounter = 0;
201
202        if (bInPrintFunction)
203        {
204          // count ['='[ and ]'='] and replace tags with print([[ and ]])
205          std::string temp = text.substr(start, end - start);
206          {
207            unsigned int pos = 0;
208            while ((pos = temp.find('[', pos)) != std::string::npos)
209            {
210              unsigned int tempCounter = 1;
211              unsigned int tempPos = pos++;
212              while(temp[++tempPos] == '=') {
213                tempCounter++;
214              }
215              if(temp[tempPos] != '[') {
216                tempCounter = 0;
217              }
218              else if(tempCounter == 0) {
219                tempCounter = 1;
220              }
221              if (tempCounter > equalSignCounter)
222                equalSignCounter = tempCounter;
223            }
224          }
225          {
226            unsigned int pos = 0;
227            while ((pos = temp.find(']', pos)) != std::string::npos)
228            {
229              unsigned int tempCounter = 1;
230              unsigned int tempPos = pos++;
231              while(temp[++tempPos] == '=') {
232                tempCounter++;
233              }
234              if(temp[tempPos] != ']') {
235                tempCounter = 0;
236              }
237              else if(tempCounter == 0) {
238                tempCounter = 1;
239              }
240              if (tempCounter > equalSignCounter)
241                equalSignCounter = tempCounter;
242            }
243          }
244          std::string equalSigns = "";
245          for(unsigned int i = 0; i < equalSignCounter; i++) {
246            equalSigns += "=";
247          }
248          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
249          start = end + 5;
250        }
251        else
252        {
253          output += text.substr(start, end - start);
254          start = end + 2;
255        }
256
257        bInPrintFunction = !bInPrintFunction;
258      }
259      while (end != std::string::npos);
260    }
261
262    return output;
263  }
264
265}
Note: See TracBrowser for help on using the repository browser.