lbaselib.c (15731B)
1 /* 2 ** $Id: lbaselib.c $ 3 ** Basic library 4 ** See Copyright Notice in lua.h 5 */ 6 7 #define lbaselib_c 8 #define LUA_LIB 9 10 #include "lprefix.h" 11 12 13 #include <ctype.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include "lua.h" 19 20 #include "lauxlib.h" 21 #include "lualib.h" 22 #include "llimits.h" 23 24 25 static int luaB_print (lua_State *L) { 26 int n = lua_gettop(L); /* number of arguments */ 27 int i; 28 for (i = 1; i <= n; i++) { /* for each argument */ 29 size_t l; 30 const char *s = luaL_tolstring(L, i, &l); /* convert it to string */ 31 if (i > 1) /* not the first element? */ 32 lua_writestring("\t", 1); /* add a tab before it */ 33 lua_writestring(s, l); /* print it */ 34 lua_pop(L, 1); /* pop result */ 35 } 36 lua_writeline(); 37 return 0; 38 } 39 40 41 /* 42 ** Creates a warning with all given arguments. 43 ** Check first for errors; otherwise an error may interrupt 44 ** the composition of a warning, leaving it unfinished. 45 */ 46 static int luaB_warn (lua_State *L) { 47 int n = lua_gettop(L); /* number of arguments */ 48 int i; 49 luaL_checkstring(L, 1); /* at least one argument */ 50 for (i = 2; i <= n; i++) 51 luaL_checkstring(L, i); /* make sure all arguments are strings */ 52 for (i = 1; i < n; i++) /* compose warning */ 53 lua_warning(L, lua_tostring(L, i), 1); 54 lua_warning(L, lua_tostring(L, n), 0); /* close warning */ 55 return 0; 56 } 57 58 59 #define SPACECHARS " \f\n\r\t\v" 60 61 static const char *b_str2int (const char *s, unsigned base, lua_Integer *pn) { 62 lua_Unsigned n = 0; 63 int neg = 0; 64 s += strspn(s, SPACECHARS); /* skip initial spaces */ 65 if (*s == '-') { s++; neg = 1; } /* handle sign */ 66 else if (*s == '+') s++; 67 if (!isalnum(cast_uchar(*s))) /* no digit? */ 68 return NULL; 69 do { 70 unsigned digit = cast_uint(isdigit(cast_uchar(*s)) 71 ? *s - '0' 72 : (toupper(cast_uchar(*s)) - 'A') + 10); 73 if (digit >= base) return NULL; /* invalid numeral */ 74 n = n * base + digit; 75 s++; 76 } while (isalnum(cast_uchar(*s))); 77 s += strspn(s, SPACECHARS); /* skip trailing spaces */ 78 *pn = (lua_Integer)((neg) ? (0u - n) : n); 79 return s; 80 } 81 82 83 static int luaB_tonumber (lua_State *L) { 84 if (lua_isnoneornil(L, 2)) { /* standard conversion? */ 85 if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ 86 lua_settop(L, 1); /* yes; return it */ 87 return 1; 88 } 89 else { 90 size_t l; 91 const char *s = lua_tolstring(L, 1, &l); 92 if (s != NULL && lua_stringtonumber(L, s) == l + 1) 93 return 1; /* successful conversion to number */ 94 /* else not a number */ 95 luaL_checkany(L, 1); /* (but there must be some parameter) */ 96 } 97 } 98 else { 99 size_t l; 100 const char *s; 101 lua_Integer n = 0; /* to avoid warnings */ 102 lua_Integer base = luaL_checkinteger(L, 2); 103 luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ 104 s = lua_tolstring(L, 1, &l); 105 luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); 106 if (b_str2int(s, cast_uint(base), &n) == s + l) { 107 lua_pushinteger(L, n); 108 return 1; 109 } /* else not a number */ 110 } /* else not a number */ 111 luaL_pushfail(L); /* not a number */ 112 return 1; 113 } 114 115 116 static int luaB_error (lua_State *L) { 117 int level = (int)luaL_optinteger(L, 2, 1); 118 lua_settop(L, 1); 119 if (lua_type(L, 1) == LUA_TSTRING && level > 0) { 120 luaL_where(L, level); /* add extra information */ 121 lua_pushvalue(L, 1); 122 lua_concat(L, 2); 123 } 124 return lua_error(L); 125 } 126 127 128 static int luaB_getmetatable (lua_State *L) { 129 luaL_checkany(L, 1); 130 if (!lua_getmetatable(L, 1)) { 131 lua_pushnil(L); 132 return 1; /* no metatable */ 133 } 134 luaL_getmetafield(L, 1, "__metatable"); 135 return 1; /* returns either __metatable field (if present) or metatable */ 136 } 137 138 139 static int luaB_setmetatable (lua_State *L) { 140 int t = lua_type(L, 2); 141 luaL_checktype(L, 1, LUA_TTABLE); 142 luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); 143 if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)) 144 return luaL_error(L, "cannot change a protected metatable"); 145 lua_settop(L, 2); 146 lua_setmetatable(L, 1); 147 return 1; 148 } 149 150 151 static int luaB_rawequal (lua_State *L) { 152 luaL_checkany(L, 1); 153 luaL_checkany(L, 2); 154 lua_pushboolean(L, lua_rawequal(L, 1, 2)); 155 return 1; 156 } 157 158 159 static int luaB_rawlen (lua_State *L) { 160 int t = lua_type(L, 1); 161 luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, 162 "table or string"); 163 lua_pushinteger(L, l_castU2S(lua_rawlen(L, 1))); 164 return 1; 165 } 166 167 168 static int luaB_rawget (lua_State *L) { 169 luaL_checktype(L, 1, LUA_TTABLE); 170 luaL_checkany(L, 2); 171 lua_settop(L, 2); 172 lua_rawget(L, 1); 173 return 1; 174 } 175 176 static int luaB_rawset (lua_State *L) { 177 luaL_checktype(L, 1, LUA_TTABLE); 178 luaL_checkany(L, 2); 179 luaL_checkany(L, 3); 180 lua_settop(L, 3); 181 lua_rawset(L, 1); 182 return 1; 183 } 184 185 186 static int pushmode (lua_State *L, int oldmode) { 187 if (oldmode == -1) 188 luaL_pushfail(L); /* invalid call to 'lua_gc' */ 189 else 190 lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" 191 : "generational"); 192 return 1; 193 } 194 195 196 /* 197 ** check whether call to 'lua_gc' was valid (not inside a finalizer) 198 */ 199 #define checkvalres(res) { if (res == -1) break; } 200 201 static int luaB_collectgarbage (lua_State *L) { 202 static const char *const opts[] = {"stop", "restart", "collect", 203 "count", "step", "isrunning", "generational", "incremental", 204 "param", NULL}; 205 static const char optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, 206 LUA_GCCOUNT, LUA_GCSTEP, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC, 207 LUA_GCPARAM}; 208 int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; 209 switch (o) { 210 case LUA_GCCOUNT: { 211 int k = lua_gc(L, o); 212 int b = lua_gc(L, LUA_GCCOUNTB); 213 checkvalres(k); 214 lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024)); 215 return 1; 216 } 217 case LUA_GCSTEP: { 218 lua_Integer n = luaL_optinteger(L, 2, 0); 219 int res = lua_gc(L, o, cast_sizet(n)); 220 checkvalres(res); 221 lua_pushboolean(L, res); 222 return 1; 223 } 224 case LUA_GCISRUNNING: { 225 int res = lua_gc(L, o); 226 checkvalres(res); 227 lua_pushboolean(L, res); 228 return 1; 229 } 230 case LUA_GCGEN: { 231 return pushmode(L, lua_gc(L, o)); 232 } 233 case LUA_GCINC: { 234 return pushmode(L, lua_gc(L, o)); 235 } 236 case LUA_GCPARAM: { 237 static const char *const params[] = { 238 "minormul", "majorminor", "minormajor", 239 "pause", "stepmul", "stepsize", NULL}; 240 static const char pnum[] = { 241 LUA_GCPMINORMUL, LUA_GCPMAJORMINOR, LUA_GCPMINORMAJOR, 242 LUA_GCPPAUSE, LUA_GCPSTEPMUL, LUA_GCPSTEPSIZE}; 243 int p = pnum[luaL_checkoption(L, 2, NULL, params)]; 244 lua_Integer value = luaL_optinteger(L, 3, -1); 245 lua_pushinteger(L, lua_gc(L, o, p, (int)value)); 246 return 1; 247 } 248 default: { 249 int res = lua_gc(L, o); 250 checkvalres(res); 251 lua_pushinteger(L, res); 252 return 1; 253 } 254 } 255 luaL_pushfail(L); /* invalid call (inside a finalizer) */ 256 return 1; 257 } 258 259 260 static int luaB_type (lua_State *L) { 261 int t = lua_type(L, 1); 262 luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); 263 lua_pushstring(L, lua_typename(L, t)); 264 return 1; 265 } 266 267 268 static int luaB_next (lua_State *L) { 269 luaL_checktype(L, 1, LUA_TTABLE); 270 lua_settop(L, 2); /* create a 2nd argument if there isn't one */ 271 if (lua_next(L, 1)) 272 return 2; 273 else { 274 lua_pushnil(L); 275 return 1; 276 } 277 } 278 279 280 static int pairscont (lua_State *L, int status, lua_KContext k) { 281 (void)L; (void)status; (void)k; /* unused */ 282 return 3; 283 } 284 285 static int luaB_pairs (lua_State *L) { 286 luaL_checkany(L, 1); 287 if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */ 288 lua_pushcfunction(L, luaB_next); /* will return generator, */ 289 lua_pushvalue(L, 1); /* state, */ 290 lua_pushnil(L); /* and initial value */ 291 } 292 else { 293 lua_pushvalue(L, 1); /* argument 'self' to metamethod */ 294 lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */ 295 } 296 return 3; 297 } 298 299 300 /* 301 ** Traversal function for 'ipairs' 302 */ 303 static int ipairsaux (lua_State *L) { 304 lua_Integer i = luaL_checkinteger(L, 2); 305 i = luaL_intop(+, i, 1); 306 lua_pushinteger(L, i); 307 return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; 308 } 309 310 311 /* 312 ** 'ipairs' function. Returns 'ipairsaux', given "table", 0. 313 ** (The given "table" may not be a table.) 314 */ 315 static int luaB_ipairs (lua_State *L) { 316 luaL_checkany(L, 1); 317 lua_pushcfunction(L, ipairsaux); /* iteration function */ 318 lua_pushvalue(L, 1); /* state */ 319 lua_pushinteger(L, 0); /* initial value */ 320 return 3; 321 } 322 323 324 static int load_aux (lua_State *L, int status, int envidx) { 325 if (l_likely(status == LUA_OK)) { 326 if (envidx != 0) { /* 'env' parameter? */ 327 lua_pushvalue(L, envidx); /* environment for loaded function */ 328 if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ 329 lua_pop(L, 1); /* remove 'env' if not used by previous call */ 330 } 331 return 1; 332 } 333 else { /* error (message is on top of the stack) */ 334 luaL_pushfail(L); 335 lua_insert(L, -2); /* put before error message */ 336 return 2; /* return fail plus error message */ 337 } 338 } 339 340 341 static const char *getMode (lua_State *L, int idx) { 342 const char *mode = luaL_optstring(L, idx, "bt"); 343 if (strchr(mode, 'B') != NULL) /* Lua code cannot use fixed buffers */ 344 luaL_argerror(L, idx, "invalid mode"); 345 return mode; 346 } 347 348 349 static int luaB_loadfile (lua_State *L) { 350 const char *fname = luaL_optstring(L, 1, NULL); 351 const char *mode = getMode(L, 2); 352 int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ 353 int status = luaL_loadfilex(L, fname, mode); 354 return load_aux(L, status, env); 355 } 356 357 358 /* 359 ** {====================================================== 360 ** Generic Read function 361 ** ======================================================= 362 */ 363 364 365 /* 366 ** reserved slot, above all arguments, to hold a copy of the returned 367 ** string to avoid it being collected while parsed. 'load' has four 368 ** optional arguments (chunk, source name, mode, and environment). 369 */ 370 #define RESERVEDSLOT 5 371 372 373 /* 374 ** Reader for generic 'load' function: 'lua_load' uses the 375 ** stack for internal stuff, so the reader cannot change the 376 ** stack top. Instead, it keeps its resulting string in a 377 ** reserved slot inside the stack. 378 */ 379 static const char *generic_reader (lua_State *L, void *ud, size_t *size) { 380 (void)(ud); /* not used */ 381 luaL_checkstack(L, 2, "too many nested functions"); 382 lua_pushvalue(L, 1); /* get function */ 383 lua_call(L, 0, 1); /* call it */ 384 if (lua_isnil(L, -1)) { 385 lua_pop(L, 1); /* pop result */ 386 *size = 0; 387 return NULL; 388 } 389 else if (l_unlikely(!lua_isstring(L, -1))) 390 luaL_error(L, "reader function must return a string"); 391 lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ 392 return lua_tolstring(L, RESERVEDSLOT, size); 393 } 394 395 396 static int luaB_load (lua_State *L) { 397 int status; 398 size_t l; 399 const char *s = lua_tolstring(L, 1, &l); 400 const char *mode = getMode(L, 3); 401 int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ 402 if (s != NULL) { /* loading a string? */ 403 const char *chunkname = luaL_optstring(L, 2, s); 404 status = luaL_loadbufferx(L, s, l, chunkname, mode); 405 } 406 else { /* loading from a reader function */ 407 const char *chunkname = luaL_optstring(L, 2, "=(load)"); 408 luaL_checktype(L, 1, LUA_TFUNCTION); 409 lua_settop(L, RESERVEDSLOT); /* create reserved slot */ 410 status = lua_load(L, generic_reader, NULL, chunkname, mode); 411 } 412 return load_aux(L, status, env); 413 } 414 415 /* }====================================================== */ 416 417 418 static int dofilecont (lua_State *L, int d1, lua_KContext d2) { 419 (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ 420 return lua_gettop(L) - 1; 421 } 422 423 424 static int luaB_dofile (lua_State *L) { 425 const char *fname = luaL_optstring(L, 1, NULL); 426 lua_settop(L, 1); 427 if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK)) 428 return lua_error(L); 429 lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); 430 return dofilecont(L, 0, 0); 431 } 432 433 434 static int luaB_assert (lua_State *L) { 435 if (l_likely(lua_toboolean(L, 1))) /* condition is true? */ 436 return lua_gettop(L); /* return all arguments */ 437 else { /* error */ 438 luaL_checkany(L, 1); /* there must be a condition */ 439 lua_remove(L, 1); /* remove it */ 440 lua_pushliteral(L, "assertion failed!"); /* default message */ 441 lua_settop(L, 1); /* leave only message (default if no other one) */ 442 return luaB_error(L); /* call 'error' */ 443 } 444 } 445 446 447 static int luaB_select (lua_State *L) { 448 int n = lua_gettop(L); 449 if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { 450 lua_pushinteger(L, n-1); 451 return 1; 452 } 453 else { 454 lua_Integer i = luaL_checkinteger(L, 1); 455 if (i < 0) i = n + i; 456 else if (i > n) i = n; 457 luaL_argcheck(L, 1 <= i, 1, "index out of range"); 458 return n - (int)i; 459 } 460 } 461 462 463 /* 464 ** Continuation function for 'pcall' and 'xpcall'. Both functions 465 ** already pushed a 'true' before doing the call, so in case of success 466 ** 'finishpcall' only has to return everything in the stack minus 467 ** 'extra' values (where 'extra' is exactly the number of items to be 468 ** ignored). 469 */ 470 static int finishpcall (lua_State *L, int status, lua_KContext extra) { 471 if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */ 472 lua_pushboolean(L, 0); /* first result (false) */ 473 lua_pushvalue(L, -2); /* error message */ 474 return 2; /* return false, msg */ 475 } 476 else 477 return lua_gettop(L) - (int)extra; /* return all results */ 478 } 479 480 481 static int luaB_pcall (lua_State *L) { 482 int status; 483 luaL_checkany(L, 1); 484 lua_pushboolean(L, 1); /* first result if no errors */ 485 lua_insert(L, 1); /* put it in place */ 486 status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); 487 return finishpcall(L, status, 0); 488 } 489 490 491 /* 492 ** Do a protected call with error handling. After 'lua_rotate', the 493 ** stack will have <f, err, true, f, [args...]>; so, the function passes 494 ** 2 to 'finishpcall' to skip the 2 first values when returning results. 495 */ 496 static int luaB_xpcall (lua_State *L) { 497 int status; 498 int n = lua_gettop(L); 499 luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ 500 lua_pushboolean(L, 1); /* first result */ 501 lua_pushvalue(L, 1); /* function */ 502 lua_rotate(L, 3, 2); /* move them below function's arguments */ 503 status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); 504 return finishpcall(L, status, 2); 505 } 506 507 508 static int luaB_tostring (lua_State *L) { 509 luaL_checkany(L, 1); 510 luaL_tolstring(L, 1, NULL); 511 return 1; 512 } 513 514 515 static const luaL_Reg base_funcs[] = { 516 {"assert", luaB_assert}, 517 {"collectgarbage", luaB_collectgarbage}, 518 {"dofile", luaB_dofile}, 519 {"error", luaB_error}, 520 {"getmetatable", luaB_getmetatable}, 521 {"ipairs", luaB_ipairs}, 522 {"loadfile", luaB_loadfile}, 523 {"load", luaB_load}, 524 {"next", luaB_next}, 525 {"pairs", luaB_pairs}, 526 {"pcall", luaB_pcall}, 527 {"print", luaB_print}, 528 {"warn", luaB_warn}, 529 {"rawequal", luaB_rawequal}, 530 {"rawlen", luaB_rawlen}, 531 {"rawget", luaB_rawget}, 532 {"rawset", luaB_rawset}, 533 {"select", luaB_select}, 534 {"setmetatable", luaB_setmetatable}, 535 {"tonumber", luaB_tonumber}, 536 {"tostring", luaB_tostring}, 537 {"type", luaB_type}, 538 {"xpcall", luaB_xpcall}, 539 /* placeholders */ 540 {LUA_GNAME, NULL}, 541 {"_VERSION", NULL}, 542 {NULL, NULL} 543 }; 544 545 546 LUAMOD_API int luaopen_base (lua_State *L) { 547 /* open lib into global table */ 548 lua_pushglobaltable(L); 549 luaL_setfuncs(L, base_funcs, 0); 550 /* set global _G */ 551 lua_pushvalue(L, -1); 552 lua_setfield(L, -2, LUA_GNAME); 553 /* set global _VERSION */ 554 lua_pushliteral(L, LUA_VERSION); 555 lua_setfield(L, -2, "_VERSION"); 556 return 1; 557 } 558