except.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*=========================================================================*\
  2. * Simple exception support
  3. * LuaSocket toolkit
  4. \*=========================================================================*/
  5. #include <stdio.h>
  6. #include "lua.h"
  7. #include "lauxlib.h"
  8. #include "except.h"
  9. /*=========================================================================*\
  10. * Internal function prototypes.
  11. \*=========================================================================*/
  12. static int global_protect(lua_State *L);
  13. static int global_newtry(lua_State *L);
  14. static int protected_(lua_State *L);
  15. static int finalize(lua_State *L);
  16. static int do_nothing(lua_State *L);
  17. /* except functions */
  18. static luaL_Reg func[] = {
  19. {"newtry", global_newtry},
  20. {"protect", global_protect},
  21. {NULL, NULL}
  22. };
  23. /*-------------------------------------------------------------------------*\
  24. * Try factory
  25. \*-------------------------------------------------------------------------*/
  26. static void wrap(lua_State *L) {
  27. lua_newtable(L);
  28. lua_pushnumber(L, 1);
  29. lua_pushvalue(L, -3);
  30. lua_settable(L, -3);
  31. lua_insert(L, -2);
  32. lua_pop(L, 1);
  33. }
  34. static int finalize(lua_State *L) {
  35. if (!lua_toboolean(L, 1)) {
  36. lua_pushvalue(L, lua_upvalueindex(1));
  37. lua_pcall(L, 0, 0, 0);
  38. lua_settop(L, 2);
  39. wrap(L);
  40. lua_error(L);
  41. return 0;
  42. } else return lua_gettop(L);
  43. }
  44. static int do_nothing(lua_State *L) {
  45. (void) L;
  46. return 0;
  47. }
  48. static int global_newtry(lua_State *L) {
  49. lua_settop(L, 1);
  50. if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
  51. lua_pushcclosure(L, finalize, 1);
  52. return 1;
  53. }
  54. /*-------------------------------------------------------------------------*\
  55. * Protect factory
  56. \*-------------------------------------------------------------------------*/
  57. static int unwrap(lua_State *L) {
  58. if (lua_istable(L, -1)) {
  59. lua_pushnumber(L, 1);
  60. lua_gettable(L, -2);
  61. lua_pushnil(L);
  62. lua_insert(L, -2);
  63. return 1;
  64. } else return 0;
  65. }
  66. static int protected_(lua_State *L) {
  67. lua_pushvalue(L, lua_upvalueindex(1));
  68. lua_insert(L, 1);
  69. if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
  70. if (unwrap(L)) return 2;
  71. else lua_error(L);
  72. return 0;
  73. } else return lua_gettop(L);
  74. }
  75. static int global_protect(lua_State *L) {
  76. lua_pushcclosure(L, protected_, 1);
  77. return 1;
  78. }
  79. /*-------------------------------------------------------------------------*\
  80. * Init module
  81. \*-------------------------------------------------------------------------*/
  82. int except_open(lua_State *L) {
  83. #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
  84. luaL_setfuncs(L, func, 0);
  85. #else
  86. luaL_openlib(L, NULL, func, 0);
  87. #endif
  88. return 0;
  89. }