LCOV - code coverage report
Current view: top level - src/script/cpp_api - s_base.cpp (source / functions) Hit Total Coverage
Test: report Lines: 39 125 31.2 %
Date: 2015-07-11 18:23:49 Functions: 6 16 37.5 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #include "cpp_api/s_base.h"
      21             : #include "cpp_api/s_internal.h"
      22             : #include "cpp_api/s_security.h"
      23             : #include "lua_api/l_object.h"
      24             : #include "serverobject.h"
      25             : #include "debug.h"
      26             : #include "filesys.h"
      27             : #include "log.h"
      28             : #include "mods.h"
      29             : #include "porting.h"
      30             : #include "util/string.h"
      31             : 
      32             : 
      33             : extern "C" {
      34             : #include "lualib.h"
      35             : #if USE_LUAJIT
      36             :         #include "luajit.h"
      37             : #endif
      38             : }
      39             : 
      40             : #include <stdio.h>
      41             : #include <cstdarg>
      42             : 
      43             : 
      44             : class ModNameStorer
      45             : {
      46             : private:
      47             :         lua_State *L;
      48             : public:
      49           0 :         ModNameStorer(lua_State *L_, const std::string &mod_name):
      50           0 :                 L(L_)
      51             :         {
      52             :                 // Store current mod name in registry
      53           0 :                 lua_pushstring(L, mod_name.c_str());
      54           0 :                 lua_setfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
      55           0 :         }
      56           0 :         ~ModNameStorer()
      57           0 :         {
      58             :                 // Clear current mod name from registry
      59           0 :                 lua_pushnil(L);
      60           0 :                 lua_setfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
      61           0 :         }
      62             : };
      63             : 
      64             : 
      65             : /*
      66             :         ScriptApiBase
      67             : */
      68             : 
      69           5 : ScriptApiBase::ScriptApiBase()
      70             : {
      71             :         #ifdef SCRIPTAPI_LOCK_DEBUG
      72           5 :         m_locked = false;
      73             :         #endif
      74             : 
      75           5 :         m_luastack = luaL_newstate();
      76           5 :         FATAL_ERROR_IF(!m_luastack, "luaL_newstate() failed");
      77             : 
      78           5 :         luaL_openlibs(m_luastack);
      79             : 
      80             :         // Add and save an error handler
      81           5 :         lua_pushcfunction(m_luastack, script_error_handler);
      82           5 :         m_errorhandler = lua_gettop(m_luastack);
      83             : 
      84             :         // Make the ScriptApiBase* accessible to ModApiBase
      85           5 :         lua_pushlightuserdata(m_luastack, this);
      86           5 :         lua_setfield(m_luastack, LUA_REGISTRYINDEX, "scriptapi");
      87             : 
      88             :         // If we are using LuaJIT add a C++ wrapper function to catch
      89             :         // exceptions thrown in Lua -> C++ calls
      90             : #if USE_LUAJIT
      91           5 :         lua_pushlightuserdata(m_luastack, (void*) script_exception_wrapper);
      92           5 :         luaJIT_setmode(m_luastack, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
      93           5 :         lua_pop(m_luastack, 1);
      94             : #endif
      95             : 
      96             :         // Add basic globals
      97           5 :         lua_newtable(m_luastack);
      98           5 :         lua_setglobal(m_luastack, "core");
      99             : 
     100           5 :         lua_pushstring(m_luastack, DIR_DELIM);
     101           5 :         lua_setglobal(m_luastack, "DIR_DELIM");
     102             : 
     103           5 :         lua_pushstring(m_luastack, porting::getPlatformName());
     104           5 :         lua_setglobal(m_luastack, "PLATFORM");
     105             : 
     106             :         // m_secure gets set to true inside
     107             :         // ScriptApiSecurity::initializeSecurity(), if neccessary.
     108             :         // Default to false otherwise
     109           5 :         m_secure = false;
     110             : 
     111           5 :         m_server = NULL;
     112           5 :         m_environment = NULL;
     113           5 :         m_guiengine = NULL;
     114           5 : }
     115             : 
     116          10 : ScriptApiBase::~ScriptApiBase()
     117             : {
     118           5 :         lua_close(m_luastack);
     119           5 : }
     120             : 
     121           0 : bool ScriptApiBase::loadMod(const std::string &script_path,
     122             :                 const std::string &mod_name, std::string *error)
     123             : {
     124           0 :         ModNameStorer mod_name_storer(getStack(), mod_name);
     125             : 
     126           0 :         return loadScript(script_path, error);
     127             : }
     128             : 
     129           5 : bool ScriptApiBase::loadScript(const std::string &script_path, std::string *error)
     130             : {
     131           5 :         verbosestream << "Loading and running script from " << script_path << std::endl;
     132             : 
     133           5 :         lua_State *L = getStack();
     134             : 
     135             :         bool ok;
     136           5 :         if (m_secure) {
     137           0 :                 ok = ScriptApiSecurity::safeLoadFile(L, script_path.c_str());
     138             :         } else {
     139           5 :                 ok = !luaL_loadfile(L, script_path.c_str());
     140             :         }
     141           5 :         ok = ok && !lua_pcall(L, 0, 0, m_errorhandler);
     142           5 :         if (!ok) {
     143           0 :                 std::string error_msg = lua_tostring(L, -1);
     144           0 :                 if (error)
     145           0 :                         (*error) = error_msg;
     146           0 :                 errorstream << "========== ERROR FROM LUA ===========" << std::endl
     147           0 :                         << "Failed to load and run script from " << std::endl
     148           0 :                         << script_path << ":" << std::endl << std::endl
     149           0 :                         << error_msg << std::endl << std::endl
     150           0 :                         << "======= END OF ERROR FROM LUA ========" << std::endl;
     151           0 :                 lua_pop(L, 1); // Pop error message from stack
     152           0 :                 return false;
     153             :         }
     154           5 :         return true;
     155             : }
     156             : 
     157           4 : void ScriptApiBase::realityCheck()
     158             : {
     159           4 :         int top = lua_gettop(m_luastack);
     160           4 :         if(top >= 30){
     161           0 :                 dstream<<"Stack is over 30:"<<std::endl;
     162           0 :                 stackDump(dstream);
     163           0 :                 std::string traceback = script_get_backtrace(m_luastack);
     164           0 :                 throw LuaError("Stack is over 30 (reality check)\n" + traceback);
     165             :         }
     166           4 : }
     167             : 
     168           0 : void ScriptApiBase::scriptError()
     169             : {
     170           0 :         throw LuaError(lua_tostring(m_luastack, -1));
     171             : }
     172             : 
     173           0 : void ScriptApiBase::stackDump(std::ostream &o)
     174             : {
     175             :         int i;
     176           0 :         int top = lua_gettop(m_luastack);
     177           0 :         for (i = 1; i <= top; i++) {  /* repeat for each level */
     178           0 :                 int t = lua_type(m_luastack, i);
     179           0 :                 switch (t) {
     180             : 
     181             :                         case LUA_TSTRING:  /* strings */
     182           0 :                                 o<<"\""<<lua_tostring(m_luastack, i)<<"\"";
     183           0 :                                 break;
     184             : 
     185             :                         case LUA_TBOOLEAN:  /* booleans */
     186           0 :                                 o<<(lua_toboolean(m_luastack, i) ? "true" : "false");
     187           0 :                                 break;
     188             : 
     189             :                         case LUA_TNUMBER:  /* numbers */ {
     190             :                                 char buf[10];
     191           0 :                                 snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i));
     192           0 :                                 o<<buf;
     193           0 :                                 break; }
     194             : 
     195             :                         default:  /* other values */
     196           0 :                                 o<<lua_typename(m_luastack, t);
     197           0 :                                 break;
     198             : 
     199             :                 }
     200           0 :                 o<<" ";
     201             :         }
     202           0 :         o<<std::endl;
     203           0 : }
     204             : 
     205           0 : void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
     206             : {
     207           0 :         SCRIPTAPI_PRECHECKHEADER
     208             :         //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
     209             : 
     210             :         // Create object on stack
     211           0 :         ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
     212           0 :         int object = lua_gettop(L);
     213             : 
     214             :         // Get core.object_refs table
     215           0 :         lua_getglobal(L, "core");
     216           0 :         lua_getfield(L, -1, "object_refs");
     217           0 :         luaL_checktype(L, -1, LUA_TTABLE);
     218           0 :         int objectstable = lua_gettop(L);
     219             : 
     220             :         // object_refs[id] = object
     221           0 :         lua_pushnumber(L, cobj->getId()); // Push id
     222           0 :         lua_pushvalue(L, object); // Copy object to top of stack
     223           0 :         lua_settable(L, objectstable);
     224           0 : }
     225             : 
     226           0 : void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
     227             : {
     228           0 :         SCRIPTAPI_PRECHECKHEADER
     229             :         //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
     230             : 
     231             :         // Get core.object_refs table
     232           0 :         lua_getglobal(L, "core");
     233           0 :         lua_getfield(L, -1, "object_refs");
     234           0 :         luaL_checktype(L, -1, LUA_TTABLE);
     235           0 :         int objectstable = lua_gettop(L);
     236             : 
     237             :         // Get object_refs[id]
     238           0 :         lua_pushnumber(L, cobj->getId()); // Push id
     239           0 :         lua_gettable(L, objectstable);
     240             :         // Set object reference to NULL
     241           0 :         ObjectRef::set_null(L);
     242           0 :         lua_pop(L, 1); // pop object
     243             : 
     244             :         // Set object_refs[id] = nil
     245           0 :         lua_pushnumber(L, cobj->getId()); // Push id
     246           0 :         lua_pushnil(L);
     247           0 :         lua_settable(L, objectstable);
     248           0 : }
     249             : 
     250             : // Creates a new anonymous reference if cobj=NULL or id=0
     251           0 : void ScriptApiBase::objectrefGetOrCreate(lua_State *L,
     252             :                 ServerActiveObject *cobj)
     253             : {
     254           0 :         if(cobj == NULL || cobj->getId() == 0){
     255           0 :                 ObjectRef::create(L, cobj);
     256             :         } else {
     257           0 :                 objectrefGet(L, cobj->getId());
     258             :         }
     259           0 : }
     260             : 
     261           0 : void ScriptApiBase::objectrefGet(lua_State *L, u16 id)
     262             : {
     263             :         // Get core.object_refs[i]
     264           0 :         lua_getglobal(L, "core");
     265           0 :         lua_getfield(L, -1, "object_refs");
     266           0 :         luaL_checktype(L, -1, LUA_TTABLE);
     267           0 :         lua_pushnumber(L, id);
     268           0 :         lua_gettable(L, -2);
     269           0 :         lua_remove(L, -2); // object_refs
     270           0 :         lua_remove(L, -2); // core
     271           3 : }

Generated by: LCOV version 1.11