lnodemcu.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. ** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
  3. ** Tag methods
  4. ** See Copyright Notice in lua.h
  5. */
  6. #define lnodemcu_c
  7. #define LUA_CORE
  8. #include "lua.h"
  9. #include <string.h>
  10. #include "lobject.h"
  11. #include "lstate.h"
  12. #include "lauxlib.h"
  13. #include "lgc.h"
  14. #include "lstring.h"
  15. #include "ltable.h"
  16. #include "ltm.h"
  17. #include "lnodemcu.h"
  18. #include "platform.h"
  19. /*
  20. ** Error Reporting Task. We can't pass a string parameter to the error reporter
  21. ** directly through the task interface the call is wrapped in a C closure with
  22. ** the error string as an Upval and this is posted to call the Lua reporter.
  23. */
  24. static int errhandler_aux (lua_State *L) {
  25. lua_getfield(L, LUA_REGISTRYINDEX, "onerror");
  26. if (!lua_isfunction(L, -1)) {
  27. lua_pop(L, 1);
  28. lua_getglobal(L, "print");
  29. }
  30. lua_pushvalue(L, lua_upvalueindex(1));
  31. lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */
  32. return 0;
  33. }
  34. /*
  35. ** Error handler for luaL_pcallx(), called from the lua_pcall() with a single
  36. ** argument -- the thrown error. This plus depth=2 is passed to debug.traceback()
  37. ** to convert into an error message which it handles in a separate posted task.
  38. */
  39. static int errhandler (lua_State *L) {
  40. lua_getglobal(L, "debug");
  41. lua_getfield(L, -1, "traceback");
  42. if (lua_isfunction(L, -1)) {
  43. lua_insert(L, 1); /* insert tracback function above error */
  44. lua_pop(L, 1); /* dump the debug table entry */
  45. lua_pushinteger(L, 2); /* skip this function and traceback */
  46. lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
  47. lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */
  48. luaL_posttask(L, LUA_TASK_HIGH);
  49. }
  50. return 0;
  51. }
  52. /*
  53. ** Use in CBs and other C functions to call a Lua function. This includes
  54. ** an error handler which will catch any error and then post this to the
  55. ** registered reporter function as a separate follow-on task.
  56. */
  57. LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v]
  58. int status;
  59. int base = lua_gettop(L) - narg;
  60. lua_pushcfunction(L, errhandler);
  61. lua_insert(L, base); /* put under args */
  62. status = lua_pcall(L, narg, nres, base);
  63. lua_remove(L, base); /* remove traceback function */
  64. if (status != LUA_OK && status != LUA_ERRRUN) {
  65. lua_gc(L, LUA_GCCOLLECT, 0); /* call onerror directly if handler failed */
  66. lua_pushliteral(L, "out of memory");
  67. lua_pushcclosure(L, errhandler_aux, 1); /* report EOM as upval */
  68. luaL_posttask(L, LUA_TASK_HIGH);
  69. }
  70. return status;
  71. }
  72. static platform_task_handle_t task_handle = 0;
  73. /*
  74. ** Task callback handler. Uses luaN_call to do a protected call with full traceback
  75. */
  76. static void do_task (platform_task_param_t task_fn_ref, uint8_t prio) {
  77. lua_State* L = lua_getstate();
  78. if (prio < 0|| prio > 2)
  79. luaL_error(L, "invalid posk task");
  80. /* Pop the CB func from the Reg */
  81. //dbg_printf("calling Reg[%u]\n", task_fn_ref);
  82. lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
  83. luaL_checkfunction(L, -1);
  84. luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
  85. lua_pushinteger(L, prio);
  86. luaL_pcallx(L, 1, 0);
  87. }
  88. /*
  89. ** Schedule a Lua function for task execution
  90. */
  91. #include "lstate.h" /*DEBUG*/
  92. LUALIB_API int luaL_posttask( lua_State* L, int prio ) { // [-1, +0, -]
  93. if (!task_handle)
  94. task_handle = platform_task_get_id(do_task);
  95. if (!lua_isfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH)
  96. luaL_error(L, "invalid posk task");
  97. //void *cl = clvalue(L->top-1);
  98. int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  99. //dbg_printf("posting Reg[%u]=%p\n",task_fn_ref,cl);
  100. if(!platform_post(prio, task_handle, (platform_task_param_t)task_fn_ref)) {
  101. luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
  102. luaL_error(L, "Task queue overflow. Task not posted");
  103. }
  104. return task_fn_ref;
  105. }
  106. LUA_API void lua_createrotable (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt) {
  107. int i, j;
  108. lu_byte flags = ~0;
  109. const char *plast = (char *)"_";
  110. for (i = 0; e[i].key; i++) {
  111. if (e[i].key[0] == '_' && strcmp(e[i].key,plast)) {
  112. plast = e[i].key;
  113. lua_pushstring(L,e[i].key);
  114. for (j=0; j<TM_EQ; j++){
  115. if(rawtsvalue(L->top-1)==G(L)->tmname[i]) {
  116. flags |= cast_byte(1u<<i);
  117. break;
  118. }
  119. }
  120. lua_pop(L,1);
  121. }
  122. }
  123. t->next = (GCObject *)1;
  124. t->tt = LUA_TROTABLE;
  125. t->marked = LROT_MARKED;
  126. t->flags = flags;
  127. t->lsizenode = i;
  128. t->metatable = cast(Table *, mt);
  129. t->entry = cast(ROTable_entry *, e);
  130. }