diff options
Diffstat (limited to 'lbaselib.c')
| -rw-r--r-- | lbaselib.c | 599 |
1 files changed, 599 insertions, 0 deletions
diff --git a/lbaselib.c b/lbaselib.c new file mode 100644 index 00000000..708ce4ff --- /dev/null +++ b/lbaselib.c | |||
| @@ -0,0 +1,599 @@ | |||
| 1 | /* | ||
| 2 | ** $Id: $ | ||
| 3 | ** Basic library | ||
| 4 | ** See Copyright Notice in lua.h | ||
| 5 | */ | ||
| 6 | |||
| 7 | |||
| 8 | |||
| 9 | #include <ctype.h> | ||
| 10 | #include <stdio.h> | ||
| 11 | #include <stdlib.h> | ||
| 12 | #include <string.h> | ||
| 13 | |||
| 14 | #include "lua.h" | ||
| 15 | |||
| 16 | #include "lauxlib.h" | ||
| 17 | #include "lualib.h" | ||
| 18 | |||
| 19 | |||
| 20 | |||
| 21 | /* | ||
| 22 | ** If your system does not support `stderr', redefine this function, or | ||
| 23 | ** redefine _ERRORMESSAGE so that it won't need _ALERT. | ||
| 24 | */ | ||
| 25 | static int luaB__ALERT (lua_State *L) { | ||
| 26 | fputs(luaL_check_string(L, 1), stderr); | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | |||
| 31 | /* | ||
| 32 | ** Basic implementation of _ERRORMESSAGE. | ||
| 33 | ** The library `liolib' redefines _ERRORMESSAGE for better error information. | ||
| 34 | */ | ||
| 35 | static int luaB__ERRORMESSAGE (lua_State *L) { | ||
| 36 | lua_settop(L, 1); | ||
| 37 | lua_getglobals(L); | ||
| 38 | lua_pushstring(L, LUA_ALERT); | ||
| 39 | lua_rawget(L, -2); | ||
| 40 | if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ | ||
| 41 | luaL_checktype(L, 1, "string"); | ||
| 42 | lua_pushvalue(L, -1); /* function to be called */ | ||
| 43 | lua_pushstring(L, "error: "); | ||
| 44 | lua_pushvalue(L, 1); | ||
| 45 | lua_pushstring(L, "\n"); | ||
| 46 | lua_concat(L, 3); | ||
| 47 | lua_call(L, 1, 0); | ||
| 48 | } | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | |||
| 53 | /* | ||
| 54 | ** If your system does not support `stdout', you can just remove this function. | ||
| 55 | ** If you need, you can define your own `print' function, following this | ||
| 56 | ** model but changing `fputs' to put the strings at a proper place | ||
| 57 | ** (a console window or a log file, for instance). | ||
| 58 | */ | ||
| 59 | static int luaB_print (lua_State *L) { | ||
| 60 | int n = lua_gettop(L); /* number of arguments */ | ||
| 61 | int i; | ||
| 62 | lua_getglobal(L, "tostring"); | ||
| 63 | for (i=1; i<=n; i++) { | ||
| 64 | const char *s; | ||
| 65 | lua_pushvalue(L, -1); /* function to be called */ | ||
| 66 | lua_pushvalue(L, i); /* value to print */ | ||
| 67 | if (lua_call(L, 1, 1) != 0) | ||
| 68 | lua_error(L, NULL); | ||
| 69 | s = lua_tostring(L, -1); /* get result */ | ||
| 70 | if (s == NULL) | ||
| 71 | lua_error(L, "`tostring' must return a string to `print'"); | ||
| 72 | if (i>1) fputs("\t", stdout); | ||
| 73 | fputs(s, stdout); | ||
| 74 | lua_pop(L, 1); /* pop result */ | ||
| 75 | } | ||
| 76 | fputs("\n", stdout); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | static int luaB_tonumber (lua_State *L) { | ||
| 82 | int base = luaL_opt_int(L, 2, 10); | ||
| 83 | if (base == 10) { /* standard conversion */ | ||
| 84 | luaL_checktype(L, 1, "any"); | ||
| 85 | if (lua_isnumber(L, 1)) { | ||
| 86 | lua_pushnumber(L, lua_tonumber(L, 1)); | ||
| 87 | return 1; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | else { | ||
| 91 | const char *s1 = luaL_check_string(L, 1); | ||
| 92 | char *s2; | ||
| 93 | unsigned long n; | ||
| 94 | luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range"); | ||
| 95 | n = strtoul(s1, &s2, base); | ||
| 96 | if (s1 != s2) { /* at least one valid digit? */ | ||
| 97 | while (isspace((unsigned char)*s2)) s2++; /* skip trailing spaces */ | ||
| 98 | if (*s2 == '\0') { /* no invalid trailing characters? */ | ||
| 99 | lua_pushnumber(L, n); | ||
| 100 | return 1; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | lua_pushnil(L); /* else not a number */ | ||
| 105 | return 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | static int luaB_error (lua_State *L) { | ||
| 110 | lua_error(L, luaL_opt_string(L, 1, NULL)); | ||
| 111 | return 0; /* to avoid warnings */ | ||
| 112 | } | ||
| 113 | |||
| 114 | static int luaB_setglobal (lua_State *L) { | ||
| 115 | luaL_checktype(L, 2, "any"); | ||
| 116 | lua_setglobal(L, luaL_check_string(L, 1)); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int luaB_getglobal (lua_State *L) { | ||
| 121 | lua_getglobal(L, luaL_check_string(L, 1)); | ||
| 122 | return 1; | ||
| 123 | } | ||
| 124 | |||
| 125 | static int luaB_tag (lua_State *L) { | ||
| 126 | luaL_checktype(L, 1, "any"); | ||
| 127 | lua_pushnumber(L, lua_tag(L, 1)); | ||
| 128 | return 1; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int luaB_settag (lua_State *L) { | ||
| 132 | luaL_checktype(L, 1, "table"); | ||
| 133 | lua_pushvalue(L, 1); /* push table */ | ||
| 134 | lua_settag(L, luaL_check_int(L, 2)); | ||
| 135 | lua_pop(L, 1); /* remove second argument */ | ||
| 136 | return 1; /* return first argument */ | ||
| 137 | } | ||
| 138 | |||
| 139 | static int luaB_newtag (lua_State *L) { | ||
| 140 | lua_pushnumber(L, lua_newtag(L)); | ||
| 141 | return 1; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int luaB_copytagmethods (lua_State *L) { | ||
| 145 | lua_pushnumber(L, lua_copytagmethods(L, luaL_check_int(L, 1), | ||
| 146 | luaL_check_int(L, 2))); | ||
| 147 | return 1; | ||
| 148 | } | ||
| 149 | |||
| 150 | static int luaB_globals (lua_State *L) { | ||
| 151 | lua_getglobals(L); /* value to be returned */ | ||
| 152 | if (!lua_isnull(L, 1)) { | ||
| 153 | luaL_checktype(L, 1, "table"); | ||
| 154 | lua_pushvalue(L, 1); /* new table of globals */ | ||
| 155 | lua_setglobals(L); | ||
| 156 | } | ||
| 157 | return 1; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int luaB_rawget (lua_State *L) { | ||
| 161 | luaL_checktype(L, 1, "table"); | ||
| 162 | luaL_checktype(L, 2, "any"); | ||
| 163 | lua_rawget(L, -2); | ||
| 164 | return 1; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int luaB_rawset (lua_State *L) { | ||
| 168 | luaL_checktype(L, 1, "table"); | ||
| 169 | luaL_checktype(L, 2, "any"); | ||
| 170 | luaL_checktype(L, 3, "any"); | ||
| 171 | lua_rawset(L, -3); | ||
| 172 | return 1; | ||
| 173 | } | ||
| 174 | |||
| 175 | static int luaB_settagmethod (lua_State *L) { | ||
| 176 | int tag = (int)luaL_check_int(L, 1); | ||
| 177 | const char *event = luaL_check_string(L, 2); | ||
| 178 | luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, | ||
| 179 | "function or nil expected"); | ||
| 180 | lua_pushnil(L); /* to get its tag */ | ||
| 181 | if (strcmp(event, "gc") == 0 && tag != lua_tag(L, -1)) | ||
| 182 | lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua"); | ||
| 183 | lua_pop(L, 1); /* remove the nil */ | ||
| 184 | lua_settagmethod(L, tag, event); | ||
| 185 | return 1; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int luaB_gettagmethod (lua_State *L) { | ||
| 189 | lua_gettagmethod(L, luaL_check_int(L, 1), luaL_check_string(L, 2)); | ||
| 190 | return 1; | ||
| 191 | } | ||
| 192 | |||
| 193 | |||
| 194 | static int luaB_collectgarbage (lua_State *L) { | ||
| 195 | lua_pushnumber(L, lua_collectgarbage(L, luaL_opt_int(L, 1, 0))); | ||
| 196 | return 1; | ||
| 197 | } | ||
| 198 | |||
| 199 | |||
| 200 | static int luaB_type (lua_State *L) { | ||
| 201 | luaL_checktype(L, 1, "any"); | ||
| 202 | lua_pushstring(L, lua_type(L, 1)); | ||
| 203 | return 1; | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | static int luaB_next (lua_State *L) { | ||
| 208 | luaL_checktype(L, 1, "table"); | ||
| 209 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ | ||
| 210 | if (lua_next(L, 1)) | ||
| 211 | return 2; | ||
| 212 | else { | ||
| 213 | lua_pushnil(L); | ||
| 214 | return 1; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | |||
| 219 | static int passresults (lua_State *L, int status, int oldtop) { | ||
| 220 | if (status == 0) { | ||
| 221 | int nresults = lua_gettop(L) - oldtop; | ||
| 222 | if (nresults > 0) | ||
| 223 | return nresults; /* results are already on the stack */ | ||
| 224 | else { | ||
| 225 | lua_pushuserdata(L, NULL); /* at least one result to signal no errors */ | ||
| 226 | return 1; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | else { /* error */ | ||
| 230 | lua_pushnil(L); | ||
| 231 | lua_pushnumber(L, status); /* error code */ | ||
| 232 | return 2; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | static int luaB_dostring (lua_State *L) { | ||
| 237 | int oldtop = lua_gettop(L); | ||
| 238 | size_t l; | ||
| 239 | const char *s = luaL_check_lstr(L, 1, &l); | ||
| 240 | if (*s == '\27') /* binary files start with ESC... */ | ||
| 241 | lua_error(L, "`dostring' cannot run pre-compiled code"); | ||
| 242 | return passresults(L, lua_dobuffer(L, s, l, luaL_opt_string(L, 2, s)), oldtop); | ||
| 243 | } | ||
| 244 | |||
| 245 | |||
| 246 | static int luaB_dofile (lua_State *L) { | ||
| 247 | int oldtop = lua_gettop(L); | ||
| 248 | const char *fname = luaL_opt_string(L, 1, NULL); | ||
| 249 | return passresults(L, lua_dofile(L, fname), oldtop); | ||
| 250 | } | ||
| 251 | |||
| 252 | |||
| 253 | static int luaB_call (lua_State *L) { | ||
| 254 | int oldtop; | ||
| 255 | const char *options = luaL_opt_string(L, 3, ""); | ||
| 256 | int err = 0; /* index of old error method */ | ||
| 257 | int i, status; | ||
| 258 | int n; | ||
| 259 | luaL_checktype(L, 2, "table"); | ||
| 260 | n = lua_getn(L, 2); | ||
| 261 | if (!lua_isnull(L, 4)) { /* set new error method */ | ||
| 262 | lua_getglobal(L, LUA_ERRORMESSAGE); | ||
| 263 | err = lua_gettop(L); /* get index */ | ||
| 264 | lua_pushvalue(L, 4); | ||
| 265 | lua_setglobal(L, LUA_ERRORMESSAGE); | ||
| 266 | } | ||
| 267 | oldtop = lua_gettop(L); /* top before function-call preparation */ | ||
| 268 | /* push function */ | ||
| 269 | lua_pushvalue(L, 1); | ||
| 270 | luaL_checkstack(L, n, "too many arguments"); | ||
| 271 | for (i=0; i<n; i++) /* push arg[1...n] */ | ||
| 272 | lua_rawgeti(L, 2, i+1); | ||
| 273 | status = lua_call(L, n, LUA_MULTRET); | ||
| 274 | if (err != 0) { /* restore old error method */ | ||
| 275 | lua_pushvalue(L, err); | ||
| 276 | lua_setglobal(L, LUA_ERRORMESSAGE); | ||
| 277 | } | ||
| 278 | if (status != 0) { /* error in call? */ | ||
| 279 | if (strchr(options, 'x')) | ||
| 280 | lua_pushnil(L); /* return nil to signal the error */ | ||
| 281 | else | ||
| 282 | lua_error(L, NULL); /* propagate error without additional messages */ | ||
| 283 | return 1; | ||
| 284 | } | ||
| 285 | if (strchr(options, 'p')) /* pack results? */ | ||
| 286 | lua_error(L, "deprecated option `p' in `call'"); | ||
| 287 | return lua_gettop(L) - oldtop; /* results are already on the stack */ | ||
| 288 | } | ||
| 289 | |||
| 290 | |||
| 291 | static int luaB_tostring (lua_State *L) { | ||
| 292 | char buff[64]; | ||
| 293 | switch (lua_type(L, 1)[2]) { | ||
| 294 | case 'm': /* nuMber */ | ||
| 295 | lua_pushstring(L, lua_tostring(L, 1)); | ||
| 296 | return 1; | ||
| 297 | case 'r': /* stRing */ | ||
| 298 | lua_pushvalue(L, 1); | ||
| 299 | return 1; | ||
| 300 | case 'b': /* taBle */ | ||
| 301 | sprintf(buff, "table: %p", lua_topointer(L, 1)); | ||
| 302 | break; | ||
| 303 | case 'n': /* fuNction */ | ||
| 304 | sprintf(buff, "function: %p", lua_topointer(L, 1)); | ||
| 305 | break; | ||
| 306 | case 'e': /* usErdata */ | ||
| 307 | sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), lua_touserdata(L, 1)); | ||
| 308 | break; | ||
| 309 | case 'l': /* niL */ | ||
| 310 | lua_pushstring(L, "nil"); | ||
| 311 | return 1; | ||
| 312 | default: | ||
| 313 | luaL_argerror(L, 1, "value expected"); | ||
| 314 | } | ||
| 315 | lua_pushstring(L, buff); | ||
| 316 | return 1; | ||
| 317 | } | ||
| 318 | |||
| 319 | |||
| 320 | static int luaB_foreachi (lua_State *L) { | ||
| 321 | int n, i; | ||
| 322 | luaL_checktype(L, 1, "table"); | ||
| 323 | luaL_checktype(L, 2, "function"); | ||
| 324 | n = lua_getn(L, 1); | ||
| 325 | for (i=1; i<=n; i++) { | ||
| 326 | lua_pushvalue(L, 2); /* function */ | ||
| 327 | lua_pushnumber(L, i); /* 1st argument */ | ||
| 328 | lua_rawgeti(L, 1, i); /* 2nd argument */ | ||
| 329 | if (lua_call(L, 2, 1) != 0) | ||
| 330 | lua_error(L, NULL); | ||
| 331 | if (!lua_isnil(L, -1)) | ||
| 332 | return 1; | ||
| 333 | lua_pop(L, 1); /* remove nil result */ | ||
| 334 | } | ||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | |||
| 339 | static int luaB_foreach (lua_State *L) { | ||
| 340 | luaL_checktype(L, 1, "table"); | ||
| 341 | luaL_checktype(L, 2, "function"); | ||
| 342 | lua_pushnil(L); /* first index */ | ||
| 343 | for (;;) { | ||
| 344 | if (lua_next(L, 1) == 0) | ||
| 345 | return 0; | ||
| 346 | lua_pushvalue(L, 2); /* function */ | ||
| 347 | lua_pushvalue(L, -3); /* key */ | ||
| 348 | lua_pushvalue(L, -3); /* value */ | ||
| 349 | if (lua_call(L, 2, 1) != 0) lua_error(L, NULL); | ||
| 350 | if (!lua_isnil(L, -1)) | ||
| 351 | return 1; | ||
| 352 | lua_pop(L, 2); /* remove value and result */ | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | |||
| 357 | static int luaB_assert (lua_State *L) { | ||
| 358 | luaL_checktype(L, 1, "any"); | ||
| 359 | if (lua_isnil(L, 1)) | ||
| 360 | luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, "")); | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | |||
| 365 | static int luaB_getn (lua_State *L) { | ||
| 366 | luaL_checktype(L, 1, "table"); | ||
| 367 | lua_pushnumber(L, lua_getn(L, 1)); | ||
| 368 | return 1; | ||
| 369 | } | ||
| 370 | |||
| 371 | |||
| 372 | static int luaB_tinsert (lua_State *L) { | ||
| 373 | int v = lua_gettop(L); /* last argument: to be inserted */ | ||
| 374 | int n, pos; | ||
| 375 | luaL_checktype(L, 1, "table"); | ||
| 376 | n = lua_getn(L, 1); | ||
| 377 | if (v == 2) /* called with only 2 arguments */ | ||
| 378 | pos = n+1; | ||
| 379 | else | ||
| 380 | pos = luaL_check_int(L, 2); /* 2nd argument is the position */ | ||
| 381 | lua_pushstring(L, "n"); | ||
| 382 | lua_pushnumber(L, n+1); | ||
| 383 | lua_rawset(L, 1); /* t.n = n+1 */ | ||
| 384 | for (; n>=pos; n--) { | ||
| 385 | lua_rawgeti(L, 1, n); | ||
| 386 | lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ | ||
| 387 | } | ||
| 388 | lua_pushvalue(L, v); | ||
| 389 | lua_rawseti(L, 1, pos); /* t[pos] = v */ | ||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | |||
| 394 | static int luaB_tremove (lua_State *L) { | ||
| 395 | int pos, n; | ||
| 396 | luaL_checktype(L, 1, "table"); | ||
| 397 | n = lua_getn(L, 1); | ||
| 398 | pos = luaL_opt_int(L, 2, n); | ||
| 399 | if (n <= 0) return 0; /* table is "empty" */ | ||
| 400 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ | ||
| 401 | for ( ;pos<n; pos++) { | ||
| 402 | lua_rawgeti(L, 1, pos+1); | ||
| 403 | lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */ | ||
| 404 | } | ||
| 405 | lua_pushstring(L, "n"); | ||
| 406 | lua_pushnumber(L, n-1); | ||
| 407 | lua_rawset(L, 1); /* t.n = n-1 */ | ||
| 408 | lua_pushnil(L); | ||
| 409 | lua_rawseti(L, 1, n); /* t[n] = nil */ | ||
| 410 | return 1; | ||
| 411 | } | ||
| 412 | |||
| 413 | |||
| 414 | |||
| 415 | |||
| 416 | /* | ||
| 417 | ** {====================================================== | ||
| 418 | ** Quicksort | ||
| 419 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; | ||
| 420 | ** Addison-Wesley, 1993.) | ||
| 421 | */ | ||
| 422 | |||
| 423 | |||
| 424 | static void swap (lua_State *L, int i, int j) { | ||
| 425 | lua_rawgeti(L, 1, i); | ||
| 426 | lua_rawgeti(L, 1, j); | ||
| 427 | lua_rawseti(L, 1, i); | ||
| 428 | lua_rawseti(L, 1, j); | ||
| 429 | } | ||
| 430 | |||
| 431 | static int sort_comp (lua_State *L, int n, int r) { | ||
| 432 | /* WARNING: the caller (auxsort) must ensure stack space */ | ||
| 433 | int res; | ||
| 434 | if (!lua_isnil(L, 2)) { /* function? */ | ||
| 435 | lua_pushvalue(L, 2); | ||
| 436 | if (r) { | ||
| 437 | lua_rawgeti(L, 1, n); /* a[n] */ | ||
| 438 | lua_pushvalue(L, -3); /* pivot */ | ||
| 439 | } | ||
| 440 | else { | ||
| 441 | lua_pushvalue(L, -2); /* pivot */ | ||
| 442 | lua_rawgeti(L, 1, n); /* a[n] */ | ||
| 443 | } | ||
| 444 | if (lua_call(L, 2, 1) != 0) lua_error(L, NULL); | ||
| 445 | res = !lua_isnil(L, -1); | ||
| 446 | } | ||
| 447 | else { /* a < b? */ | ||
| 448 | lua_rawgeti(L, 1, n); /* a[n] */ | ||
| 449 | if (r) | ||
| 450 | res = lua_lessthan(L, -1, -2); | ||
| 451 | else | ||
| 452 | res = lua_lessthan(L, -2, -1); | ||
| 453 | } | ||
| 454 | lua_pop(L, 1); | ||
| 455 | return res; | ||
| 456 | } | ||
| 457 | |||
| 458 | static void auxsort (lua_State *L, int l, int u) { | ||
| 459 | while (l < u) { /* for tail recursion */ | ||
| 460 | int i, j; | ||
| 461 | luaL_checkstack(L, 4, "array too large"); | ||
| 462 | /* sort elements a[l], a[(l+u)/2] and a[u] */ | ||
| 463 | lua_rawgeti(L, 1, u); | ||
| 464 | if (sort_comp(L, l, 0)) /* a[u] < a[l]? */ | ||
| 465 | swap(L, l, u); | ||
| 466 | lua_pop(L, 1); | ||
| 467 | if (u-l == 1) break; /* only 2 elements */ | ||
| 468 | i = (l+u)/2; | ||
| 469 | lua_rawgeti(L, 1, i); /* Pivot = a[i] */ | ||
| 470 | if (sort_comp(L, l, 0)) /* a[i]<a[l]? */ | ||
| 471 | swap(L, l, i); | ||
| 472 | else { | ||
| 473 | if (sort_comp(L, u, 1)) /* a[u]<a[i]? */ | ||
| 474 | swap(L, i, u); | ||
| 475 | } | ||
| 476 | lua_pop(L, 1); /* pop old a[i] */ | ||
| 477 | if (u-l == 2) break; /* only 3 elements */ | ||
| 478 | lua_rawgeti(L, 1, i); /* Pivot */ | ||
| 479 | swap(L, i, u-1); /* put median element as pivot (a[u-1]) */ | ||
| 480 | /* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */ | ||
| 481 | i = l; j = u-1; | ||
| 482 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | ||
| 483 | /* repeat i++ until a[i] >= P */ | ||
| 484 | while (sort_comp(L, ++i, 1)) | ||
| 485 | if (i>u) lua_error(L, "invalid order function for sorting"); | ||
| 486 | /* repeat j-- until a[j] <= P */ | ||
| 487 | while (sort_comp(L, --j, 0)) | ||
| 488 | if (j<l) lua_error(L, "invalid order function for sorting"); | ||
| 489 | if (j<i) break; | ||
| 490 | swap(L, i, j); | ||
| 491 | } | ||
| 492 | swap(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | ||
| 493 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ | ||
| 494 | /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ | ||
| 495 | if (i-l < u-i) { | ||
| 496 | j=l; i=i-1; l=i+2; | ||
| 497 | } | ||
| 498 | else { | ||
| 499 | j=i+1; i=u; u=j-2; | ||
| 500 | } | ||
| 501 | lua_pop(L, 1); /* remove pivot from stack */ | ||
| 502 | auxsort(L, j, i); /* call recursively the smaller one */ | ||
| 503 | } /* repeat the routine for the larger one */ | ||
| 504 | } | ||
| 505 | |||
| 506 | static int luaB_sort (lua_State *L) { | ||
| 507 | int n; | ||
| 508 | luaL_checktype(L, 1, "table"); | ||
| 509 | n = lua_getn(L, 1); | ||
| 510 | if (!lua_isnull(L, 2)) /* is there a 2nd argument? */ | ||
| 511 | luaL_checktype(L, 2, "function"); | ||
| 512 | lua_settop(L, 2); /* make sure there is two arguments */ | ||
| 513 | auxsort(L, 1, n); | ||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | /* }====================================================== */ | ||
| 518 | |||
| 519 | |||
| 520 | |||
| 521 | /* | ||
| 522 | ** {====================================================== | ||
| 523 | ** Deprecated functions to manipulate global environment. | ||
| 524 | ** ======================================================= | ||
| 525 | */ | ||
| 526 | |||
| 527 | |||
| 528 | /* | ||
| 529 | ** gives an explicit error in any attempt to call a deprecated function | ||
| 530 | */ | ||
| 531 | static int deprecated_func (lua_State *L) { | ||
| 532 | luaL_verror(L, "function `%.20s' is deprecated", luaL_check_string(L, -1)); | ||
| 533 | return 0; /* to avoid warnings */ | ||
| 534 | } | ||
| 535 | |||
| 536 | |||
| 537 | #define num_deprecated 4 | ||
| 538 | |||
| 539 | static const char *const deprecated_names [num_deprecated] = { | ||
| 540 | "foreachvar", "nextvar", "rawgetglobal", "rawsetglobal" | ||
| 541 | }; | ||
| 542 | |||
| 543 | |||
| 544 | static void deprecated_funcs (lua_State *L) { | ||
| 545 | int i; | ||
| 546 | for (i=0; i<num_deprecated; i++) { | ||
| 547 | lua_pushstring(L, deprecated_names[i]); | ||
| 548 | lua_pushcclosure(L, deprecated_func, 1); | ||
| 549 | lua_setglobal(L, deprecated_names[i]); | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | |||
| 554 | /* }====================================================== */ | ||
| 555 | |||
| 556 | static const struct luaL_reg base_funcs[] = { | ||
| 557 | {LUA_ALERT, luaB__ALERT}, | ||
| 558 | {LUA_ERRORMESSAGE, luaB__ERRORMESSAGE}, | ||
| 559 | {"call", luaB_call}, | ||
| 560 | {"collectgarbage", luaB_collectgarbage}, | ||
| 561 | {"copytagmethods", luaB_copytagmethods}, | ||
| 562 | {"dofile", luaB_dofile}, | ||
| 563 | {"dostring", luaB_dostring}, | ||
| 564 | {"error", luaB_error}, | ||
| 565 | {"foreach", luaB_foreach}, | ||
| 566 | {"foreachi", luaB_foreachi}, | ||
| 567 | {"getglobal", luaB_getglobal}, | ||
| 568 | {"gettagmethod", luaB_gettagmethod}, | ||
| 569 | {"globals", luaB_globals}, | ||
| 570 | {"newtag", luaB_newtag}, | ||
| 571 | {"next", luaB_next}, | ||
| 572 | {"print", luaB_print}, | ||
| 573 | {"rawget", luaB_rawget}, | ||
| 574 | {"rawset", luaB_rawset}, | ||
| 575 | {"rawgettable", luaB_rawget}, /* for compatibility */ | ||
| 576 | {"rawsettable", luaB_rawset}, /* for compatibility */ | ||
| 577 | {"setglobal", luaB_setglobal}, | ||
| 578 | {"settag", luaB_settag}, | ||
| 579 | {"settagmethod", luaB_settagmethod}, | ||
| 580 | {"tag", luaB_tag}, | ||
| 581 | {"tonumber", luaB_tonumber}, | ||
| 582 | {"tostring", luaB_tostring}, | ||
| 583 | {"type", luaB_type}, | ||
| 584 | {"assert", luaB_assert}, | ||
| 585 | {"getn", luaB_getn}, | ||
| 586 | {"sort", luaB_sort}, | ||
| 587 | {"tinsert", luaB_tinsert}, | ||
| 588 | {"tremove", luaB_tremove} | ||
| 589 | }; | ||
| 590 | |||
| 591 | |||
| 592 | |||
| 593 | void lua_baselibopen (lua_State *L) { | ||
| 594 | luaL_openl(L, base_funcs); | ||
| 595 | lua_pushstring(L, LUA_VERSION); | ||
| 596 | lua_setglobal(L, "_VERSION"); | ||
| 597 | deprecated_funcs(L); | ||
| 598 | } | ||
| 599 | |||
