lnodemcu.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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. //== NodeMCU lauxlib.h API extensions ========================================//
  19. #ifdef LUA_USE_ESP
  20. #include "platform.h"
  21. /*
  22. ** Error Reporting Task. We can't pass a string parameter to the error reporter
  23. ** directly through the task interface the call is wrapped in a C closure with
  24. ** the error string as an Upval and this is posted to call the Lua reporter.
  25. */
  26. static int errhandler_aux (lua_State *L) {
  27. lua_getfield(L, LUA_REGISTRYINDEX, "onerror");
  28. if (!lua_isfunction(L, -1)) {
  29. lua_pop(L, 1);
  30. lua_getglobal(L, "print");
  31. }
  32. lua_pushvalue(L, lua_upvalueindex(1));
  33. lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */
  34. return 0;
  35. }
  36. /*
  37. ** Error handler for luaL_pcallx(), called from the lua_pcall() with a single
  38. ** argument -- the thrown error. This plus depth=2 is passed to debug.traceback()
  39. ** to convert into an error message which it handles in a separate posted task.
  40. */
  41. static int errhandler (lua_State *L) {
  42. lua_getglobal(L, "debug");
  43. lua_getfield(L, -1, "traceback");
  44. if (lua_isfunction(L, -1)) {
  45. lua_insert(L, 1); /* insert tracback function above error */
  46. lua_pop(L, 1); /* dump the debug table entry */
  47. lua_pushinteger(L, 2); /* skip this function and traceback */
  48. lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
  49. lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */
  50. luaL_posttask(L, LUA_TASK_HIGH);
  51. }
  52. return 0;
  53. }
  54. /*
  55. ** Use in CBs and other C functions to call a Lua function. This includes
  56. ** an error handler which will catch any error and then post this to the
  57. ** registered reporter function as a separate follow-on task.
  58. */
  59. LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v]
  60. int status;
  61. int base = lua_gettop(L) - narg;
  62. lua_pushcfunction(L, errhandler);
  63. lua_insert(L, base); /* put under args */
  64. status = lua_pcall(L, narg, nres, base);
  65. lua_remove(L, base); /* remove traceback function */
  66. if (status != LUA_OK && status != LUA_ERRRUN) {
  67. lua_gc(L, LUA_GCCOLLECT, 0); /* call onerror directly if handler failed */
  68. lua_pushliteral(L, "out of memory");
  69. lua_pushcclosure(L, errhandler_aux, 1); /* report EOM as upval */
  70. luaL_posttask(L, LUA_TASK_HIGH);
  71. }
  72. return status;
  73. }
  74. static platform_task_handle_t task_handle = 0;
  75. /*
  76. ** Task callback handler. Uses luaN_call to do a protected call with full traceback
  77. */
  78. static void do_task (platform_task_param_t task_fn_ref, uint8_t prio) {
  79. lua_State* L = lua_getstate();
  80. if (prio < 0|| prio > 2)
  81. luaL_error(L, "invalid posk task");
  82. /* Pop the CB func from the Reg */
  83. //dbg_printf("calling Reg[%u]\n", task_fn_ref);
  84. lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
  85. luaL_checkfunction(L, -1);
  86. luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
  87. lua_pushinteger(L, prio);
  88. luaL_pcallx(L, 1, 0);
  89. }
  90. /*
  91. ** Schedule a Lua function for task execution
  92. */
  93. LUALIB_API int luaL_posttask( lua_State* L, int prio ) { // [-1, +0, -]
  94. if (!task_handle)
  95. task_handle = platform_task_get_id(do_task);
  96. if (!lua_isfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH)
  97. luaL_error(L, "invalid posk task");
  98. //void *cl = clvalue(L->top-1);
  99. int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  100. //dbg_printf("posting Reg[%u]=%p\n",task_fn_ref,cl);
  101. if(!platform_post(prio, task_handle, (platform_task_param_t)task_fn_ref)) {
  102. luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
  103. luaL_error(L, "Task queue overflow. Task not posted");
  104. }
  105. return task_fn_ref;
  106. }
  107. #else
  108. LUALIB_API int luaL_posttask( lua_State* L, int prio ) {
  109. return 0;
  110. } /* Dummy stub on host */
  111. #endif
  112. #ifdef LUA_USE_ESP
  113. /*
  114. * Return an LFS function
  115. */
  116. LUALIB_API int luaL_pushlfsmodule (lua_State *L) {
  117. if (lua_pushlfsindex(L) == LUA_TNIL) {
  118. lua_remove(L,-2); /* dump the name to balance the stack */
  119. return 0; /* return nil if LFS not loaded */
  120. }
  121. lua_insert(L, -2);
  122. lua_call(L, 1, 1);
  123. if (!lua_isfunction(L, -1)) {
  124. lua_pop(L, 1);
  125. lua_pushnil(L); /* replace DTS by nil */
  126. }
  127. return 1;
  128. }
  129. /*
  130. * Return an array of functions in LFS
  131. */
  132. LUALIB_API int luaL_pushlfsmodules (lua_State *L) {
  133. if (lua_pushlfsindex(L) == LUA_TNIL)
  134. return 0; /* return nil if LFS not loaded */
  135. lua_call(L, 0, 2);
  136. lua_remove(L, -2); /* remove DTS leaving array */
  137. return 1;
  138. }
  139. /*
  140. * Return the Unix timestamp of the LFS image creation
  141. */
  142. LUALIB_API int luaL_pushlfsdts (lua_State *L) {
  143. if (lua_pushlfsindex(L) == LUA_TNIL)
  144. return 0; /* return nil if LFS not loaded */
  145. lua_call(L, 0, 1);
  146. return 1;
  147. }
  148. #endif
  149. //== NodeMCU lua.h API extensions ============================================//
  150. LUA_API int lua_freeheap (void) {
  151. #ifdef LUA_USE_HOST
  152. return MAX_INT;
  153. #else
  154. return (int) platform_freeheap();
  155. #endif
  156. }
  157. #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
  158. LUA_API int lua_pushstringsarray(lua_State *L, int opt) {
  159. stringtable *tb = NULL;
  160. int i, j;
  161. lua_lock(L);
  162. if (opt == 0)
  163. tb = &G(L)->strt;
  164. #ifdef LUA_USE_ESP
  165. else if (opt == 1 && G(L)->ROstrt.hash)
  166. tb = &G(L)->ROstrt;
  167. #endif
  168. if (tb == NULL) {
  169. setnilvalue(L->top);
  170. api_incr_top(L);
  171. lua_unlock(L);
  172. return 0;
  173. }
  174. Table *t = luaH_new(L, tb->nuse, 0);
  175. sethvalue(L, L->top, t);
  176. api_incr_top(L);
  177. luaC_checkGC(L);
  178. lua_unlock(L);
  179. for (i = 0, j = 1; i < tb->size; i++) {
  180. GCObject *o;
  181. for(o = tb->hash[i]; o; o = o->gch.next) {
  182. TValue v;
  183. setsvalue(L, &v, o);
  184. setobj2s(L, luaH_setnum(L, hvalue(L->top-1), j++), &v);
  185. }
  186. }
  187. return 1;
  188. }
  189. LUA_API void lua_createrotable (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt) {
  190. int i, j;
  191. lu_byte flags = ~0;
  192. const char *plast = (char *)"_";
  193. for (i = 0; e[i].key; i++) {
  194. if (e[i].key[0] == '_' && strcmp(e[i].key,plast)) {
  195. plast = e[i].key;
  196. lua_pushstring(L,e[i].key);
  197. for (j=0; j<TM_EQ; j++){
  198. if(rawtsvalue(L->top-1)==G(L)->tmname[i]) {
  199. flags |= cast_byte(1u<<i);
  200. break;
  201. }
  202. }
  203. lua_pop(L,1);
  204. }
  205. }
  206. t->next = (GCObject *)1;
  207. t->tt = LUA_TROTABLE;
  208. t->marked = LROT_MARKED;
  209. t->flags = flags;
  210. t->lsizenode = i;
  211. t->metatable = cast(Table *, mt);
  212. t->entry = cast(ROTable_entry *, e);
  213. }
  214. #ifdef LUA_USE_ESP
  215. #include "lfunc.h"
  216. /* Push the LClosure of the LFS index function */
  217. LUA_API int lua_pushlfsindex (lua_State *L) {
  218. lua_lock(L);
  219. Proto *p = G(L)->ROpvmain;
  220. if (p) {
  221. Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
  222. cl->l.p = p;
  223. setclvalue(L, L->top, cl);
  224. } else {
  225. setnilvalue(L->top);
  226. }
  227. api_incr_top(L);
  228. lua_unlock(L);
  229. return p ? LUA_TFUNCTION : LUA_TNIL;
  230. }
  231. #endif