/erlmon-1.0/src/lua.erl

http://github.com/darrikmazey/erlmon · Erlang · 316 lines · 275 code · 37 blank · 4 comment · 2 complexity · 372e103bc2907ee2de12173b643f419e MD5 · raw file

  1. -module(lua).
  2. -export([new_state/0,
  3. close/1,
  4. call/3,
  5. concat/2,
  6. dostring/2,
  7. dofile/2,
  8. dump_table/2,
  9. getfield/3,
  10. getglobal/2,
  11. gettable/3,
  12. gettable/2,
  13. gettop/1,
  14. next/2,
  15. pop/1,
  16. push/2,
  17. pushboolean/2,
  18. pushinteger/2,
  19. pushstring/2,
  20. pushnil/1,
  21. pushnumber/2,
  22. remove/2,
  23. setfield/3,
  24. setglobal/2,
  25. toboolean/2,
  26. tointeger/2,
  27. tolstring/2,
  28. tonumber/2,
  29. type/2,
  30. type_atom/2
  31. ]).
  32. -include("lua.hrl").
  33. -include("lua_api.hrl").
  34. new_state() ->
  35. {ok, lua_driver:open()}.
  36. close(L) ->
  37. lua_driver:close(L).
  38. dostring(#lua{port=Port}, Code) ->
  39. port_command(Port, term_to_binary({?ERL_LUAL_DOSTRING, Code})),
  40. receive_simple_response().
  41. dofile(#lua{port=Port}, Filename) ->
  42. port_command(Port, term_to_binary({?ERL_LUAL_DOFILE, Filename})),
  43. receive_simple_response().
  44. call(L, Args, Results) ->
  45. command(L, {?ERL_LUA_CALL, Args, Results}),
  46. receive_simple_response().
  47. concat(L, N) ->
  48. command(L, {?ERL_LUA_CONCAT, N}).
  49. dump_table(L, N) ->
  50. dump_table(L, N, none).
  51. dump_table(L, N, NextKey) ->
  52. io:format("dump_table(~p, ~p)~n", [N, NextKey]),
  53. case NextKey of
  54. none ->
  55. Str=lists:concat(["tmpkey, tmpval = pairs(", N, ")(", N, ")"]);
  56. NK ->
  57. Str=lists:concat(["tmpkey, tmpval = pairs(", N, ")(", N, ", \"", NK, "\")"])
  58. end,
  59. io:format("Str == ~p~n", [Str]),
  60. lual:dostring(L, Str),
  61. lua:getglobal(L, "tmpkey"),
  62. {ok, T} = lua:type(L, -1),
  63. case T of
  64. ?LUA_TNIL -> [];
  65. _ ->
  66. {ok, K} = lua:tolstring(L, -1),
  67. lua:remove(L, -1),
  68. lua:getglobal(L, "tmpval"),
  69. {ok, VT} = lua:type(L, -1),
  70. io:format("type == ~p~n", [VT]),
  71. case VT of
  72. ?LUA_TNUMBER ->
  73. {ok, V} = lua:tonumber(L, -1);
  74. ?LUA_TTABLE ->
  75. V = dump_table(L, lists:concat([N, ".", K]));
  76. _ ->
  77. {ok, V} = lua:tolstring(L, -1)
  78. end,
  79. lua:remove(L, -1),
  80. [{list_to_atom(K),V}|dump_table(L, N, K)]
  81. end.
  82. getfield(L, global, Name) ->
  83. getglobal(L, Name);
  84. getfield(L, Index, Name) ->
  85. command(L, {?ERL_LUA_GETFIELD, Index, Name}),
  86. receive_simple_response().
  87. getglobal(L, Name) ->
  88. command(L, {?ERL_LUA_GETGLOBAL, Name}),
  89. receive_simple_response().
  90. gettable(L, global, Name) when is_atom(Name) ->
  91. gettable(L, global, atom_to_list(Name));
  92. gettable(L, global, Name) ->
  93. getfield(L, global, Name),
  94. {ok, T} = gettop(L),
  95. Table = gettable(L, T),
  96. lua:remove(L, T),
  97. Table.
  98. gettable(L, T) ->
  99. pushnil(L),
  100. gettablekey(L, T).
  101. gettablekey(L, T) ->
  102. next(L, T),
  103. {ok, OT} = gettop(L),
  104. case OT of
  105. T ->
  106. [];
  107. _ ->
  108. %% values can be tables or anything else
  109. %% recurse on tables
  110. case type_atom(L, -1) of
  111. {ok, table} ->
  112. %% keys can be strings or numbers
  113. case type_atom(L, -2) of
  114. {ok, number} ->
  115. {ok, Key} = tonumber(L, -2);
  116. _KT ->
  117. {ok, Key} = tolstring(L, -2)
  118. end,
  119. KV = {Key, gettable(L, T + 2)},
  120. remove(L, -1),
  121. [KV|gettablekey(L, T)];
  122. _TA ->
  123. {ok, _Type, Val} = pop(L),
  124. %% keys can be strings or numbers
  125. case type_atom(L, -1) of
  126. {ok, number} ->
  127. {ok, Key} = tonumber(L, -1);
  128. _KT ->
  129. {ok, Key} = tolstring(L, -1)
  130. end,
  131. [{Key, Val}|gettablekey(L, T)]
  132. end
  133. end.
  134. gettop(L) ->
  135. command(L, {?ERL_LUA_GETTOP}),
  136. receive_valued_response().
  137. next(L, Index) ->
  138. command(L, {?ERL_LUA_NEXT, Index}),
  139. receive_simple_response().
  140. pop(L) ->
  141. {ok, R} = gettop(L),
  142. if
  143. R < 1 ->
  144. {ok, empty};
  145. true ->
  146. {ok, T} = type_atom(L, R),
  147. case T of
  148. number ->
  149. {ok, N} = tonumber(L, R),
  150. remove(L, R),
  151. {ok, number, N};
  152. string ->
  153. {ok, N} = tolstring(L, R),
  154. remove(L, R),
  155. {ok, string, N};
  156. boolean ->
  157. {other, N} = toboolean(L, R),
  158. remove(L, R),
  159. {ok, boolean, N};
  160. function ->
  161. remove(L, R),
  162. {ok, function, function};
  163. _ ->
  164. remove(L, R),
  165. {ok, unknown, unknown}
  166. end
  167. end.
  168. push(L, Term) when is_number(Term) ->
  169. pushnumber(L, Term);
  170. push(L, Term) when is_list(Term) ->
  171. pushstring(L, Term);
  172. push(L, true) ->
  173. pushboolean(L, true);
  174. push(L, false) ->
  175. pushboolean(L, false);
  176. push(L, Term) when is_atom(Term) ->
  177. pushstring(L, atom_to_list(Term)).
  178. pushboolean(L, Bool) ->
  179. command(L, {?ERL_LUA_PUSHBOOLEAN, Bool}),
  180. receive_simple_response().
  181. pushinteger(L, Int) when is_integer(Int) ->
  182. command(L, {?ERL_LUA_PUSHINTEGER, Int}),
  183. receive_simple_response().
  184. pushstring(L, String) when is_list(String) ->
  185. command(L, {?ERL_LUA_PUSHSTRING, String}),
  186. receive_simple_response().
  187. pushnil(L) ->
  188. command(L, {?ERL_LUA_PUSHNIL}),
  189. receive_simple_response().
  190. pushnumber(L, Num) when is_number(Num) ->
  191. command(L, {?ERL_LUA_PUSHNUMBER, Num}),
  192. receive_simple_response().
  193. remove(L, Index) ->
  194. command(L, {?ERL_LUA_REMOVE, Index}),
  195. receive_simple_response().
  196. setfield(L, global, Name) ->
  197. setglobal(L, Name);
  198. setfield(L, Index, Name) ->
  199. command(L, {?ERL_LUA_SETFIELD, Index, Name}),
  200. receive_simple_response().
  201. setglobal(L, Name) ->
  202. command(L, {?ERL_LUA_SETGLOBAL, Name}),
  203. receive_simple_response().
  204. toboolean(L, Index) ->
  205. command(L, {?ERL_LUA_TOBOOLEAN, Index}),
  206. receive_valued_response().
  207. tointeger(L, Index) ->
  208. command(L, {?ERL_LUA_TOINTEGER, Index}),
  209. receive_valued_response().
  210. tolstring(L, Index) ->
  211. command(L, {?ERL_LUA_TOLSTRING, Index}),
  212. receive_valued_response().
  213. tonumber(L, Index) ->
  214. command(L, {?ERL_LUA_TONUMBER, Index}),
  215. {ok, Value} = receive_valued_response(),
  216. Value2 = list_to_binary(Value),
  217. {ok, binary_to_term(Value2)}.
  218. type(L, Index) ->
  219. command(L, {?ERL_LUA_TYPE, Index}),
  220. receive_valued_response().
  221. type_atom(L, Index) ->
  222. command(L, {?ERL_LUA_TYPE, Index}),
  223. R = receive_valued_response(),
  224. case R of
  225. {ok, Str} ->
  226. {ok, type_int_to_atom(Str)};
  227. _ ->
  228. R
  229. end.
  230. type_int_to_atom(TypeInt) when is_integer(TypeInt) ->
  231. case TypeInt of
  232. 0 ->
  233. Atom = nil;
  234. 1 ->
  235. Atom = boolean;
  236. 2 ->
  237. Atom = light_user_data;
  238. 3 ->
  239. Atom = number;
  240. 4 ->
  241. Atom = string;
  242. 5 ->
  243. Atom = table;
  244. 6 ->
  245. Atom = function;
  246. 7 ->
  247. Atom = user_data;
  248. 8 ->
  249. Atom = thread;
  250. _ ->
  251. Atom = unknown
  252. end,
  253. Atom.
  254. command(#lua{port=Port}, Data) ->
  255. port_command(Port, term_to_binary(Data)).
  256. receive_simple_response() ->
  257. receive
  258. ok ->
  259. ok;
  260. error ->
  261. {error, lua_error};
  262. {error, Reason} ->
  263. {error, Reason};
  264. Other ->
  265. {other, Other}
  266. after ?STD_TIMEOUT ->
  267. {error, timeout}
  268. end.
  269. receive_valued_response() ->
  270. receive
  271. {ok, Str} ->
  272. {ok, Str};
  273. error ->
  274. {error, lua_error};
  275. Other ->
  276. {other, Other}
  277. after ?STD_TIMEOUT ->
  278. {error, timeout}
  279. end.