106 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*=========================================================================*\
 | |
| * Simple exception support
 | |
| * LuaSocket toolkit
 | |
| \*=========================================================================*/
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "lua.h"
 | |
| #include "lauxlib.h"
 | |
| 
 | |
| #include "except.h"
 | |
| 
 | |
| namespace NS_SLUA {
 | |
| 
 | |
| /*=========================================================================*\
 | |
| * Internal function prototypes.
 | |
| \*=========================================================================*/
 | |
| static int global_protect(lua_State *L);
 | |
| static int global_newtry(lua_State *L);
 | |
| static int protected_(lua_State *L);
 | |
| static int finalize(lua_State *L);
 | |
| static int do_nothing(lua_State *L);
 | |
| 
 | |
| /* except functions */
 | |
| static luaL_Reg except_func[] = {
 | |
|     {"newtry",    global_newtry},
 | |
|     {"protect",   global_protect},
 | |
|     {NULL,        NULL}
 | |
| };
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Try factory
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static void wrap(lua_State *L) {
 | |
|     lua_newtable(L);
 | |
|     lua_pushnumber(L, 1);
 | |
|     lua_pushvalue(L, -3);
 | |
|     lua_settable(L, -3);
 | |
|     lua_insert(L, -2);
 | |
|     lua_pop(L, 1);
 | |
| }
 | |
| 
 | |
| static int finalize(lua_State *L) {
 | |
|     if (!lua_toboolean(L, 1)) {
 | |
|         lua_pushvalue(L, lua_upvalueindex(1));
 | |
|         lua_pcall(L, 0, 0, 0);
 | |
|         lua_settop(L, 2);
 | |
|         wrap(L);
 | |
|         lua_error(L);
 | |
|         return 0;
 | |
|     } else return lua_gettop(L);
 | |
| }
 | |
| 
 | |
| static int do_nothing(lua_State *L) { 
 | |
|     (void) L;
 | |
|     return 0; 
 | |
| }
 | |
| 
 | |
| static int global_newtry(lua_State *L) {
 | |
|     lua_settop(L, 1);
 | |
|     if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
 | |
|     lua_pushcclosure(L, finalize, 1);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Protect factory
 | |
| \*-------------------------------------------------------------------------*/
 | |
| static int unwrap(lua_State *L) {
 | |
|     if (lua_istable(L, -1)) {
 | |
|         lua_pushnumber(L, 1);
 | |
|         lua_gettable(L, -2);
 | |
|         lua_pushnil(L);
 | |
|         lua_insert(L, -2);
 | |
|         return 1;
 | |
|     } else return 0;
 | |
| }
 | |
| 
 | |
| static int protected_(lua_State *L) {
 | |
|     lua_pushvalue(L, lua_upvalueindex(1));
 | |
|     lua_insert(L, 1);
 | |
|     if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
 | |
|         if (unwrap(L)) return 2;
 | |
|         else lua_error(L);
 | |
|         return 0;
 | |
|     } else return lua_gettop(L);
 | |
| }
 | |
| 
 | |
| static int global_protect(lua_State *L) {
 | |
|     lua_pushcclosure(L, protected_, 1);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*-------------------------------------------------------------------------*\
 | |
| * Init module
 | |
| \*-------------------------------------------------------------------------*/
 | |
| int except_open(lua_State *L) {
 | |
| #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
 | |
|     luaL_setfuncs(L, except_func, 0);
 | |
| #else
 | |
|     luaL_openlib(L, NULL, except_func, 0);
 | |
| #endif
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| } // end NS_SLUA
 |