/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * luascript.cc * * Tue Jan 10 14:43:39 CET 2012 * Copyright 2012 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of Pracro. * * Pracro is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Pracro is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pracro; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "luascript.h" // For atoi #include //#include "luautil.h" #define GLOBAL_POINTER "_pracroGlobalLUAObjectPointerThisShouldBeANameThatIsNotAccidentallyOverwritten" #define DEBUG(x, fmt...) printf(fmt) #define ERR(x, fmt...) printf(fmt) static int _debug(lua_State *L) {/* Pracro::checkParameters(L, Pracro::T_STRING, Pracro::T_END); */ std::string msg = lua_tostring(L, lua_gettop(L)); printf("%s\n", msg.c_str()); return 0; } static int _forward(lua_State *L) {/* Pracro::checkParameters(L, Pracro::T_STRING, Pracro::T_END); */ int x = lua_tonumber(L, lua_gettop(L)); printf("forward %d\n", x); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } lua->out->forward(x * 5); return 0; } static int _turn(lua_State *L) {/* Pracro::checkParameters(L, Pracro::T_STRING, Pracro::T_END); */ int x = lua_tonumber(L, lua_gettop(L)); printf("turn %d\n", x); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } lua->out->turn(-x); return 0; } static int _reset(lua_State *L) {/* Pracro::checkParameters(L, Pracro::T_STRING, Pracro::T_END); */ printf("reset\n"); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } lua->out->reset(); return 0; } LUAScript::LUAScript(OutputWindow *o) { DEBUG(luascript, "LUAScript()\n"); L = NULL; out = o; } LUAScript::~LUAScript() { if(L) { free(L); L = NULL; } DEBUG(luascript, "~LUAScript()\n"); } void LUAScript::init() throw(Exception) { if(L) return; L = luaL_newstate(); if(L == NULL) { ERR(luascript, "Could not create LUA state.\n"); throw Exception("Could not create LUA state."); } luaL_openlibs(L); lua_pushlightuserdata(L, this); // Push the pointer to 'this' instance lua_setglobal(L, GLOBAL_POINTER); // Assign it to a global lua var. lua_register(L, "debug", _debug); lua_register(L, "fremad", _forward); lua_register(L, "drej", _turn); lua_register(L, "reset", _reset); connect(&watcher, SIGNAL(fileChanged(const QString &)), this, SLOT(reload())); } void LUAScript::addFile(std::string src) { file = src.c_str(); FILE *fp = fopen(src.c_str(), "r"); if(fp) { char buf[64]; size_t sz; std::string inc; while((sz = fread(buf, 1, sizeof(buf), fp)) != 0) { inc.append(buf, sz); } fclose(fp); addCode(inc, src); } watcher.addPath(file); } void LUAScript::reload() { printf("Reload\n"); // luaL_error(L, "Terminated due to reload."); // runScript(); } void LUAScript::addCode(std::string c, std::string name) { scripts.push_back(std::make_pair(c, name)); } void LUAScript::run() { /* while(true) { printf("."); fflush(stdout); } */ try { runScript(); } catch(Exception &e) { printf("LUA Error: %s\n", e.msg.c_str()); } } void LUAScript::runScript() throw(Exception) { try { init(); } catch(Exception &e) { throw Exception(e.msg); } if(L == NULL) { ERR(luascript, "LUA state not initialized!"); return; } top = lua_gettop(L); std::vector >::iterator i = scripts.begin(); while(i != scripts.end()) { std::string program = i->first; std::string codename = name(); if(i->second != "") codename += ": " + i->second; DEBUG(luascript, "Running %s: %s\n", codename.c_str(), program.c_str()); if(luaL_loadbuffer(L, program.c_str(), program.size(), codename.c_str())) { ERR(luascript, "loadbuffer: %s\n", lua_tostring(L, lua_gettop(L))); throw Exception(lua_tostring(L, lua_gettop(L))); } // Run the loaded code if(lua_pcall(L, 0, LUA_MULTRET, 0)) { ERR(luascript, "pcall: %s\n" , lua_tostring(L, lua_gettop(L))); throw Exception(lua_tostring(L, lua_gettop(L))); } i++; } } std::string LUAScript::resultString() throw(Exception) { if(top != lua_gettop(L) - 1) { ERR(luascript, "Program did not return a single value.\n"); throw Exception("Program did not return a single value."); } if(lua_isstring(L, lua_gettop(L)) == false) { ERR(luascript, "Program did not return a string value.\n"); throw Exception("Program did not return a string value."); } std::string res = lua_tostring(L, lua_gettop(L)); lua_pop(L, 1); return res; } #ifdef TEST_LUASCRIPT //Additional dependency files //deps: //Required cflags (autoconf vars may be used) //cflags: //Required link options (autoconf vars may be used) //libs: #include "test.h" TEST_BEGIN; // TODO: Put some testcode here (see test.h for usable macros). TEST_TRUE(false, "No tests yet!"); TEST_END; #endif/*TEST_LUASCRIPT*/