예제 #1
0
static void update_inner_tables_once(lua_State *L, int src, int dst, int updated)
{
   lutro_checked_stack_begin();

   assert(lua_istable(L, src));
   assert(lua_istable(L, dst));
   assert(lua_istable(L, updated));

   src = lua_absindex(L, src);
   dst = lua_absindex(L, dst);
   updated = lua_absindex(L, updated);

   lua_pushnil(L);
   while (lua_next(L, src))
   {
      lua_pushvalue(L, -2);
      lua_gettable(L, dst);

      if (!lua_compare(L, -2, -1, LUA_OPEQ) && lua_istable(L, -2))
      {
         deep_update_once(L, -1, -2, updated);
         lua_pushvalue(L, -3);
         lua_pushvalue(L, -2);
         lua_settable(L, dst);
      }

      lua_pop(L, 2);
   }

   lutro_checked_stack_assert(0);
}
예제 #2
0
void deep_update_once(lua_State *L, int src, int dst, int updated)
{
   assert(lua_istable(L, src));
   assert(lua_istable(L, dst));
   assert(lua_istable(L, updated));

   src = lua_absindex(L, src);
   dst = lua_absindex(L, dst);
   updated = lua_absindex(L, updated);

   lutro_checked_stack_begin();

   lua_pushvalue(L, dst);
   lua_gettable(L, updated);

   if (lua_isnoneornil(L, -1))
   {
      lua_pop(L, 1);

      lua_pushvalue(L, dst);
      lua_pushboolean(L, 1);
      lua_settable(L, updated);

      int top = lua_gettop(L);
      int src_mt = lua_getmetatable(L, src);
      int dst_mt = lua_getmetatable(L, dst);
      if (src_mt && dst_mt)
         deep_update_once(L, src_mt, dst_mt, updated);

      lua_pop(L, lua_gettop(L) - top);

      lua_pushnil(L);
      while (lua_next(L, src))
      {
         if (lua_istable(L, -1))
         {
            lua_pushvalue(L, -2);
            lua_gettable(L, dst);

            deep_update_once(L, -2, -1, updated);
            lua_pop(L, 2);
         }
         else
         {
            lua_pushvalue(L, -2);
            lua_insert(L, -2);
            lua_settable(L, dst);
         }
      }
   }
   else
      lua_pop(L, 1);

   lutro_checked_stack_assert(0);
}
예제 #3
0
// copies stuff from table dst to table src
static inline void shallow_update(lua_State *L, int src, int dst)
{
   lutro_checked_stack_begin();

   assert(lua_istable(L, src));
   assert(lua_istable(L, dst));

   src = lua_absindex(L, src);
   dst = lua_absindex(L, dst);

   lua_pushnil(L);
   while (lua_next(L, src))
   {
      lua_pushvalue(L, -2);
      lua_insert(L, -2);
      lua_settable(L, dst);
   }

   lutro_checked_stack_assert(0);
}
예제 #4
0
void lutro_init()
{
   L = luaL_newstate();
   luaL_openlibs(L);

#ifdef HAVE_JIT
   luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
#endif

   lutro_checked_stack_begin();

   init_settings(L);

   lutro_preload(L, lutro_core_preload, "lutro");
   lutro_preload(L, lutro_graphics_preload, "lutro.graphics");
   lutro_preload(L, lutro_audio_preload, "lutro.audio");
   lutro_preload(L, lutro_input_preload, "lutro.input");
   lutro_preload(L, lutro_filesystem_preload, "lutro.filesystem");
   lutro_preload(L, lutro_timer_preload, "lutro.timer");
#ifdef HAVE_INOTIFY
   lutro_preload(L, lutro_live_preload, "lutro.live");
#endif

   // if any of these requires fail, the checked stack assertion at the end will
   // be triggered. remember that assertions are only avaialable in debug mode.
   lutro_require(L, "lutro", 1);
   lutro_require(L, "lutro.graphics", 1);
   lutro_require(L, "lutro.audio", 1);
   lutro_require(L, "lutro.input", 1);
   lutro_require(L, "lutro.filesystem", 1);
   lutro_require(L, "lutro.timer", 1);
#ifdef HAVE_INOTIFY
   lutro_require(L, "lutro.live", 1);
#endif

   lutro_checked_stack_assert(0);
}
예제 #5
0
// TODO: check if there's anything else that needs to be backed up
static int live_hotswap(lua_State *L, const char *filename)
{
   char modname[PATH_MAX_LENGTH];
   int success = 1;

   lutro_checked_stack_begin();

   // backup _G then drop it
   lua_pushglobaltable(L);
   lua_newtable(L);
   shallow_update(L, -2, -1);
   lua_remove(L, -2);

   lutro_relpath_to_modname(modname, filename);

   // backup module state
   get_package_loaded(L, modname);

   // force reloading of the module
   lua_pushnil(L);
   set_package_loaded(L, modname);

   if(!lutro_require(L, modname, 0))
   {
      fprintf(stderr, "lutro.live lua error: %s\n", lua_tostring(L, -1));
      lua_pop(L, 1);

      lua_pushglobaltable(L);
      shallow_update(L, -3, -1);
      lua_pop(L, 1); // error and backups

      success = 0;
   }
   else
   {
      lua_newtable(L); // to keep track of updated keys

      if (lua_istable(L, -3))
         deep_update_once(L, -2, -3, -1);

      // drop newmod
      lua_remove(L, -2);

      // restore _G then drop it
      lua_pushglobaltable(L);
      update_inner_tables_once(L, -4, -1, -2);
      lua_pop(L, 1);

      lua_pop(L, 1); // drop updated key table
   }

   // restore oldmod
   set_package_loaded(L, modname);

   lua_pop(L, 1); // _G backup

   if (success && settings.live_call_load)
   {
      lua_getglobal(L, "lutro");
      lua_getfield(L, -1, "load");

      // assume load is defined.
      if(lua_pcall(L, 0, 0, 0))
      {
         // TODO: dump stacktrace
         fprintf(stderr, "%s\n", lua_tostring(L, -1));
         lua_pop(L, 1);
      }
      lua_pop(L, 1);
   }

   lutro_checked_stack_assert(0);

   return success;
}