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