463 lines
12 KiB

  1. /*
  2. ** $Id: lbaselib.c,v 1.274 2012/04/27 14:13:19 roberto Exp $
  3. ** Basic library
  4. ** See Copyright Notice in lua.h
  5. */
  6. #if defined HAVE_CONFIG_H // LOL BEGIN
  7. # include "config.h"
  8. #endif // LOL END
  9. #include <ctype.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #define lbaselib_c
  14. #define LUA_LIB
  15. #include "lua.h"
  16. #include "lauxlib.h"
  17. #include "lualib.h"
  18. static int luaB_print (lua_State *L) {
  19. int n = lua_gettop(L); /* number of arguments */
  20. int i;
  21. lua_getglobal(L, "tostring");
  22. for (i=1; i<=n; i++) {
  23. const char *s;
  24. size_t l;
  25. lua_pushvalue(L, -1); /* function to be called */
  26. lua_pushvalue(L, i); /* value to print */
  27. lua_call(L, 1, 1);
  28. s = lua_tolstring(L, -1, &l); /* get result */
  29. if (s == NULL)
  30. return luaL_error(L,
  31. LUA_QL("tostring") " must return a string to " LUA_QL("print"));
  32. if (i>1) luai_writestring("\t", 1);
  33. luai_writestring(s, l);
  34. lua_pop(L, 1); /* pop result */
  35. }
  36. luai_writeline();
  37. return 0;
  38. }
  39. #define SPACECHARS " \f\n\r\t\v"
  40. static int luaB_tonumber (lua_State *L) {
  41. if (lua_isnoneornil(L, 2)) { /* standard conversion */
  42. int isnum;
  43. lua_Number n = lua_tonumberx(L, 1, &isnum);
  44. if (isnum) {
  45. lua_pushnumber(L, n);
  46. return 1;
  47. } /* else not a number; must be something */
  48. luaL_checkany(L, 1);
  49. }
  50. else {
  51. size_t l;
  52. const char *s = luaL_checklstring(L, 1, &l);
  53. const char *e = s + l; /* end point for 's' */
  54. int base = luaL_checkint(L, 2);
  55. int neg = 0;
  56. luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
  57. s += strspn(s, SPACECHARS); /* skip initial spaces */
  58. if (*s == '-') { s++; neg = 1; } /* handle signal */
  59. else if (*s == '+') s++;
  60. if (isalnum((unsigned char)*s)) {
  61. lua_Number n = 0;
  62. do {
  63. int digit = (isdigit((unsigned char)*s)) ? *s - '0'
  64. : toupper((unsigned char)*s) - 'A' + 10;
  65. if (digit >= base) break; /* invalid numeral; force a fail */
  66. n = n * (lua_Number)base + (lua_Number)digit;
  67. s++;
  68. } while (isalnum((unsigned char)*s));
  69. s += strspn(s, SPACECHARS); /* skip trailing spaces */
  70. if (s == e) { /* no invalid trailing characters? */
  71. lua_pushnumber(L, (neg) ? -n : n);
  72. return 1;
  73. } /* else not a number */
  74. } /* else not a number */
  75. }
  76. lua_pushnil(L); /* not a number */
  77. return 1;
  78. }
  79. static int luaB_error (lua_State *L) {
  80. int level = luaL_optint(L, 2, 1);
  81. lua_settop(L, 1);
  82. if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
  83. luaL_where(L, level);
  84. lua_pushvalue(L, 1);
  85. lua_concat(L, 2);
  86. }
  87. return lua_error(L);
  88. }
  89. static int luaB_getmetatable (lua_State *L) {
  90. luaL_checkany(L, 1);
  91. if (!lua_getmetatable(L, 1)) {
  92. lua_pushnil(L);
  93. return 1; /* no metatable */
  94. }
  95. luaL_getmetafield(L, 1, "__metatable");
  96. return 1; /* returns either __metatable field (if present) or metatable */
  97. }
  98. static int luaB_setmetatable (lua_State *L) {
  99. int t = lua_type(L, 2);
  100. luaL_checktype(L, 1, LUA_TTABLE);
  101. luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  102. "nil or table expected");
  103. if (luaL_getmetafield(L, 1, "__metatable"))
  104. return luaL_error(L, "cannot change a protected metatable");
  105. lua_settop(L, 2);
  106. lua_setmetatable(L, 1);
  107. return 1;
  108. }
  109. static int luaB_rawequal (lua_State *L) {
  110. luaL_checkany(L, 1);
  111. luaL_checkany(L, 2);
  112. lua_pushboolean(L, lua_rawequal(L, 1, 2));
  113. return 1;
  114. }
  115. static int luaB_rawlen (lua_State *L) {
  116. int t = lua_type(L, 1);
  117. luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
  118. "table or string expected");
  119. lua_pushinteger(L, lua_rawlen(L, 1));
  120. return 1;
  121. }
  122. static int luaB_rawget (lua_State *L) {
  123. luaL_checktype(L, 1, LUA_TTABLE);
  124. luaL_checkany(L, 2);
  125. lua_settop(L, 2);
  126. lua_rawget(L, 1);
  127. return 1;
  128. }
  129. static int luaB_rawset (lua_State *L) {
  130. luaL_checktype(L, 1, LUA_TTABLE);
  131. luaL_checkany(L, 2);
  132. luaL_checkany(L, 3);
  133. lua_settop(L, 3);
  134. lua_rawset(L, 1);
  135. return 1;
  136. }
  137. static int luaB_collectgarbage (lua_State *L) {
  138. static const char *const opts[] = {"stop", "restart", "collect",
  139. "count", "step", "setpause", "setstepmul",
  140. "setmajorinc", "isrunning", "generational", "incremental", NULL};
  141. static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
  142. LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
  143. LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
  144. int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
  145. int ex = luaL_optint(L, 2, 0);
  146. int res = lua_gc(L, o, ex);
  147. switch (o) {
  148. case LUA_GCCOUNT: {
  149. int b = lua_gc(L, LUA_GCCOUNTB, 0);
  150. lua_pushnumber(L, res + ((lua_Number)b/1024));
  151. lua_pushinteger(L, b);
  152. return 2;
  153. }
  154. case LUA_GCSTEP: case LUA_GCISRUNNING: {
  155. lua_pushboolean(L, res);
  156. return 1;
  157. }
  158. default: {
  159. lua_pushinteger(L, res);
  160. return 1;
  161. }
  162. }
  163. }
  164. static int luaB_type (lua_State *L) {
  165. luaL_checkany(L, 1);
  166. lua_pushstring(L, luaL_typename(L, 1));
  167. return 1;
  168. }
  169. static int pairsmeta (lua_State *L, const char *method, int iszero,
  170. lua_CFunction iter) {
  171. if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */
  172. luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */
  173. lua_pushcfunction(L, iter); /* will return generator, */
  174. lua_pushvalue(L, 1); /* state, */
  175. if (iszero) lua_pushinteger(L, 0); /* and initial value */
  176. else lua_pushnil(L);
  177. }
  178. else {
  179. lua_pushvalue(L, 1); /* argument 'self' to metamethod */
  180. lua_call(L, 1, 3); /* get 3 values from metamethod */
  181. }
  182. return 3;
  183. }
  184. static int luaB_next (lua_State *L) {
  185. luaL_checktype(L, 1, LUA_TTABLE);
  186. lua_settop(L, 2); /* create a 2nd argument if there isn't one */
  187. if (lua_next(L, 1))
  188. return 2;
  189. else {
  190. lua_pushnil(L);
  191. return 1;
  192. }
  193. }
  194. static int luaB_pairs (lua_State *L) {
  195. return pairsmeta(L, "__pairs", 0, luaB_next);
  196. }
  197. static int ipairsaux (lua_State *L) {
  198. int i = luaL_checkint(L, 2);
  199. luaL_checktype(L, 1, LUA_TTABLE);
  200. i++; /* next value */
  201. lua_pushinteger(L, i);
  202. lua_rawgeti(L, 1, i);
  203. return (lua_isnil(L, -1)) ? 1 : 2;
  204. }
  205. static int luaB_ipairs (lua_State *L) {
  206. return pairsmeta(L, "__ipairs", 1, ipairsaux);
  207. }
  208. static int load_aux (lua_State *L, int status) {
  209. if (status == LUA_OK)
  210. return 1;
  211. else {
  212. lua_pushnil(L);
  213. lua_insert(L, -2); /* put before error message */
  214. return 2; /* return nil plus error message */
  215. }
  216. }
  217. static int luaB_loadfile (lua_State *L) {
  218. const char *fname = luaL_optstring(L, 1, NULL);
  219. const char *mode = luaL_optstring(L, 2, NULL);
  220. int env = !lua_isnone(L, 3); /* 'env' parameter? */
  221. int status = luaL_loadfilex(L, fname, mode);
  222. if (status == LUA_OK && env) { /* 'env' parameter? */
  223. lua_pushvalue(L, 3);
  224. lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
  225. }
  226. return load_aux(L, status);
  227. }
  228. /*
  229. ** {======================================================
  230. ** Generic Read function
  231. ** =======================================================
  232. */
  233. /*
  234. ** reserved slot, above all arguments, to hold a copy of the returned
  235. ** string to avoid it being collected while parsed. 'load' has four
  236. ** optional arguments (chunk, source name, mode, and environment).
  237. */
  238. #define RESERVEDSLOT 5
  239. /*
  240. ** Reader for generic `load' function: `lua_load' uses the
  241. ** stack for internal stuff, so the reader cannot change the
  242. ** stack top. Instead, it keeps its resulting string in a
  243. ** reserved slot inside the stack.
  244. */
  245. static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
  246. (void)(ud); /* not used */
  247. luaL_checkstack(L, 2, "too many nested functions");
  248. lua_pushvalue(L, 1); /* get function */
  249. lua_call(L, 0, 1); /* call it */
  250. if (lua_isnil(L, -1)) {
  251. lua_pop(L, 1); /* pop result */
  252. *size = 0;
  253. return NULL;
  254. }
  255. else if (!lua_isstring(L, -1))
  256. luaL_error(L, "reader function must return a string");
  257. lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
  258. return lua_tolstring(L, RESERVEDSLOT, size);
  259. }
  260. static int luaB_load (lua_State *L) {
  261. int status;
  262. size_t l;
  263. int top = lua_gettop(L);
  264. const char *s = lua_tolstring(L, 1, &l);
  265. const char *mode = luaL_optstring(L, 3, "bt");
  266. if (s != NULL) { /* loading a string? */
  267. const char *chunkname = luaL_optstring(L, 2, s);
  268. status = luaL_loadbufferx(L, s, l, chunkname, mode);
  269. }
  270. else { /* loading from a reader function */
  271. const char *chunkname = luaL_optstring(L, 2, "=(load)");
  272. luaL_checktype(L, 1, LUA_TFUNCTION);
  273. lua_settop(L, RESERVEDSLOT); /* create reserved slot */
  274. status = lua_load(L, generic_reader, NULL, chunkname, mode);
  275. }
  276. if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */
  277. lua_pushvalue(L, 4); /* environment for loaded function */
  278. lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */
  279. }
  280. return load_aux(L, status);
  281. }
  282. /* }====================================================== */
  283. static int dofilecont (lua_State *L) {
  284. return lua_gettop(L) - 1;
  285. }
  286. static int luaB_dofile (lua_State *L) {
  287. const char *fname = luaL_optstring(L, 1, NULL);
  288. lua_settop(L, 1);
  289. if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L);
  290. lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
  291. return dofilecont(L);
  292. }
  293. static int luaB_assert (lua_State *L) {
  294. if (!lua_toboolean(L, 1))
  295. return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
  296. return lua_gettop(L);
  297. }
  298. static int luaB_select (lua_State *L) {
  299. int n = lua_gettop(L);
  300. if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
  301. lua_pushinteger(L, n-1);
  302. return 1;
  303. }
  304. else {
  305. int i = luaL_checkint(L, 1);
  306. if (i < 0) i = n + i;
  307. else if (i > n) i = n;
  308. luaL_argcheck(L, 1 <= i, 1, "index out of range");
  309. return n - i;
  310. }
  311. }
  312. static int finishpcall (lua_State *L, int status) {
  313. if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */
  314. lua_settop(L, 0); /* create space for return values */
  315. lua_pushboolean(L, 0);
  316. lua_pushstring(L, "stack overflow");
  317. return 2; /* return false, msg */
  318. }
  319. lua_pushboolean(L, status); /* first result (status) */
  320. lua_replace(L, 1); /* put first result in first slot */
  321. return lua_gettop(L);
  322. }
  323. static int pcallcont (lua_State *L) {
  324. int status = lua_getctx(L, NULL);
  325. return finishpcall(L, (status == LUA_YIELD));
  326. }
  327. static int luaB_pcall (lua_State *L) {
  328. int status;
  329. luaL_checkany(L, 1);
  330. lua_pushnil(L);
  331. lua_insert(L, 1); /* create space for status result */
  332. status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
  333. return finishpcall(L, (status == LUA_OK));
  334. }
  335. static int luaB_xpcall (lua_State *L) {
  336. int status;
  337. int n = lua_gettop(L);
  338. luaL_argcheck(L, n >= 2, 2, "value expected");
  339. lua_pushvalue(L, 1); /* exchange function... */
  340. lua_copy(L, 2, 1); /* ...and error handler */
  341. lua_replace(L, 2);
  342. status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont);
  343. return finishpcall(L, (status == LUA_OK));
  344. }
  345. static int luaB_tostring (lua_State *L) {
  346. luaL_checkany(L, 1);
  347. luaL_tolstring(L, 1, NULL);
  348. return 1;
  349. }
  350. static const luaL_Reg base_funcs[] = {
  351. {"assert", luaB_assert},
  352. {"collectgarbage", luaB_collectgarbage},
  353. {"dofile", luaB_dofile},
  354. {"error", luaB_error},
  355. {"getmetatable", luaB_getmetatable},
  356. {"ipairs", luaB_ipairs},
  357. {"loadfile", luaB_loadfile},
  358. {"load", luaB_load},
  359. #if defined(LUA_COMPAT_LOADSTRING)
  360. {"loadstring", luaB_load},
  361. #endif
  362. {"next", luaB_next},
  363. {"pairs", luaB_pairs},
  364. {"pcall", luaB_pcall},
  365. {"print", luaB_print},
  366. {"rawequal", luaB_rawequal},
  367. {"rawlen", luaB_rawlen},
  368. {"rawget", luaB_rawget},
  369. {"rawset", luaB_rawset},
  370. {"select", luaB_select},
  371. {"setmetatable", luaB_setmetatable},
  372. {"tonumber", luaB_tonumber},
  373. {"tostring", luaB_tostring},
  374. {"type", luaB_type},
  375. {"xpcall", luaB_xpcall},
  376. {NULL, NULL}
  377. };
  378. LUAMOD_API int luaopen_base (lua_State *L) {
  379. /* set global _G */
  380. lua_pushglobaltable(L);
  381. lua_pushglobaltable(L);
  382. lua_setfield(L, -2, "_G");
  383. /* open lib into global table */
  384. luaL_setfuncs(L, base_funcs, 0);
  385. lua_pushliteral(L, LUA_VERSION);
  386. lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */
  387. return 1;
  388. }