Unified · Split
| @@ -1,53 +1,33 @@ | ||
| 1 | −Lua Copyright Notice | |
| 2 | −-------------------- | |
| 1 | +Lua License | |
| 2 | +----------- | |
| 3 | 3 | |
| 4 | −Lua is free and non-proprietary. | |
| 5 | −It can be used for both academic and commercial purposes at absolutely no cost. | |
| 6 | −There are no royalties or GNU-like "copyleft" restrictions. | |
| 7 | −Lua (probably) qualifies as Open Source software. | |
| 8 | −Nevertheless, Lua is not in the public domain and TeCGraf keeps its copyright. | |
| 4 | +Lua is licensed under the terms of the MIT license reproduced below. | |
| 5 | +This means that Lua is free software and can be used for both academic | |
| 6 | +and commercial purposes at absolutely no cost. | |
| 9 | 7 | |
| 10 | −If you use Lua, please give us credit (a nice way to do this is to include a | |
| 11 | −Lua logo in a web page for your product), but we would appreciate *not* | |
| 12 | −receiving lengthy legal documents to sign. | |
| 13 | − | |
| 14 | −The legal details are below. | |
| 8 | +For details and rationale, see http://www.lua.org/license.html . | |
| 15 | 9 | |
| 16 | 10 | =============================================================================== |
| 17 | 11 | |
| 18 | −Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. | |
| 19 | − | |
| 20 | −Permission is hereby granted, without written agreement and without license | |
| 21 | −or royalty fees, to use, copy, modify, translate, and distribute | |
| 22 | −this software and its documentation (hereby called the "package") | |
| 23 | −for any purpose, including commercial applications, subject to | |
| 24 | −the following conditions: | |
| 25 | − | |
| 26 | − * The above copyright notice and this permission notice shall appear in all | |
| 27 | − copies or substantial portions of this package. | |
| 28 | − | |
| 29 | − * The origin of this package must not be misrepresented; you must not | |
| 30 | − claim that you wrote the original package. If you use this package in a | |
| 31 | − product, an acknowledgment in the product documentation would be greatly | |
| 32 | − appreciated (but it is not required). | |
| 33 | − | |
| 34 | − * Altered source versions must be plainly marked as such, and must not be | |
| 35 | − misrepresented as being the original package. | |
| 36 | − | |
| 37 | −The authors specifically disclaim any warranties, including, but not limited | |
| 38 | −to, the implied warranties of merchantability and fitness for a particular | |
| 39 | −purpose. The package provided hereunder is on an "as is" basis, and the | |
| 40 | −authors have no obligation to provide maintenance, support, updates, | |
| 41 | −enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the | |
| 42 | −authors be held liable to any party for direct, indirect, special, | |
| 43 | −incidental, or consequential damages arising out of the use of this package | |
| 44 | −and its documentation. | |
| 45 | − | |
| 46 | −The Lua language and this implementation have been entirely designed and written | |
| 47 | −by Waldemar Celes, Roberto Ierusalimschy, and Luiz Henrique de Figueiredo | |
| 48 | −at TeCGraf, PUC-Rio in Brazil. | |
| 49 | − | |
| 50 | −This implementation contains no third-party code. | |
| 12 | +Copyright (C) 2003 Tecgraf, PUC-Rio. | |
| 13 | + | |
| 14 | +Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 15 | +of this software and associated documentation files (the "Software"), to deal | |
| 16 | +in the Software without restriction, including without limitation the rights | |
| 17 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 18 | +copies of the Software, and to permit persons to whom the Software is | |
| 19 | +furnished to do so, subject to the following conditions: | |
| 20 | + | |
| 21 | +The above copyright notice and this permission notice shall be included in | |
| 22 | +all copies or substantial portions of the Software. | |
| 23 | + | |
| 24 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 25 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 26 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 27 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 28 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 29 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 30 | +THE SOFTWARE. | |
| 51 | 31 | |
| 52 | 32 | =============================================================================== |
| 53 | 33 | |
| @@ -1,97 +0,0 @@ | ||
| 1 | −diff -r lua-4.0/include/lua.h lua/include/lua.h | |
| 2 | −2c2 | |
| 3 | −< ** $Id: lua.h,v 1.79 2000/10/31 12:44:07 roberto Exp $ | |
| 4 | −--- | |
| 5 | −> ** $Id: lua.h,v 1.79a 2000/10/31 12:44:07 roberto Exp $ | |
| 6 | −25c25 | |
| 7 | −< #define LUA_VERSION "Lua 4.0" | |
| 8 | −--- | |
| 9 | −> #define LUA_VERSION "Lua 4.0.1" | |
| 10 | −diff -r lua-4.0/src/lapi.c lua/src/lapi.c | |
| 11 | −2c2 | |
| 12 | −< ** $Id: lapi.c,v 1.110 2000/10/30 12:50:09 roberto Exp $ | |
| 13 | −--- | |
| 14 | −> ** $Id: lapi.c,v 1.110a 2000/10/30 12:50:09 roberto Exp $ | |
| 15 | −488c488 | |
| 16 | −< TString *ts = luaS_newudata(L, size, NULL); | |
| 17 | −--- | |
| 18 | −> TString *ts = luaS_newudata(L, (size==0) ? 1 : size, NULL); | |
| 19 | −diff -r lua-4.0/src/ldo.c lua/src/ldo.c | |
| 20 | −2c2 | |
| 21 | −< ** $Id: ldo.c,v 1.109 2000/10/30 12:38:50 roberto Exp $ | |
| 22 | −--- | |
| 23 | −> ** $Id: ldo.c,v 1.109a 2000/10/30 12:38:50 roberto Exp $ | |
| 24 | −247c247,249 | |
| 25 | −< luaC_checkGC(L); | |
| 26 | −--- | |
| 27 | −> /* before parsing, give a (good) chance to GC */ | |
| 28 | −> if (L->nblocks/8 >= L->GCthreshold/10) | |
| 29 | −> luaC_collectgarbage(L); | |
| 30 | −277,278c279,280 | |
| 31 | −< filename = lua_tostring(L, -1); /* filename = '@'..filename */ | |
| 32 | −< lua_pop(L, 1); /* OK: there is no GC during parser */ | |
| 33 | −--- | |
| 34 | −> c = lua_gettop(L); | |
| 35 | −> filename = lua_tostring(L, c); /* filename = '@'..filename */ | |
| 36 | −280a283 | |
| 37 | −> lua_remove(L, c); /* remove `filename' from the stack */ | |
| 38 | −diff -r lua-4.0/src/lgc.c lua/src/lgc.c | |
| 39 | −2c2 | |
| 40 | −< ** $Id: lgc.c,v 1.72 2000/10/26 12:47:05 roberto Exp $ | |
| 41 | −--- | |
| 42 | −> ** $Id: lgc.c,v 1.72+ 2000/10/26 12:47:05 roberto Exp $ | |
| 43 | −339c339 | |
| 44 | −< static void luaC_collectgarbage (lua_State *L) { | |
| 45 | −--- | |
| 46 | −> void luaC_collectgarbage (lua_State *L) { | |
| 47 | −diff -r lua-4.0/src/lgc.h lua/src/lgc.h | |
| 48 | −2c2 | |
| 49 | −< ** $Id: lgc.h,v 1.8 2000/10/02 14:47:43 roberto Exp $ | |
| 50 | −--- | |
| 51 | −> ** $Id: lgc.h,v 1.9 2001/02/02 16:23:20 roberto Exp $ | |
| 52 | −14a15 | |
| 53 | −> void luaC_collectgarbage (lua_State *L); | |
| 54 | −diff -r lua-4.0/src/lib/lbaselib.c lua/src/lib/lbaselib.c | |
| 55 | −2c2 | |
| 56 | −< ** $Id: lbaselib.c,v 1.17 2000/11/06 13:45:18 roberto Exp $ | |
| 57 | −--- | |
| 58 | −> ** $Id: lbaselib.c,v 1.17a 2000/11/06 13:45:18 roberto Exp $ | |
| 59 | −168c168 | |
| 60 | −< lua_rawget(L, -2); | |
| 61 | −--- | |
| 62 | −> lua_rawget(L, 1); | |
| 63 | −176c176 | |
| 64 | −< lua_rawset(L, -3); | |
| 65 | −--- | |
| 66 | −> lua_rawset(L, 1); | |
| 67 | −260c260 | |
| 68 | −< if (*s == '\27') /* binary files start with ESC... */ | |
| 69 | −--- | |
| 70 | −> if (*s == '\33') /* binary files start with ESC... */ | |
| 71 | −diff -r lua-4.0/src/lparser.c lua/src/lparser.c | |
| 72 | −2c2 | |
| 73 | −< ** $Id: lparser.c,v 1.116 2000/10/27 11:39:52 roberto Exp $ | |
| 74 | −--- | |
| 75 | −> ** $Id: lparser.c,v 1.117 2000/11/29 11:57:42 roberto Exp $ | |
| 76 | −1000c1000 | |
| 77 | −< if (!block_follow(ls->t.token)) | |
| 78 | −--- | |
| 79 | −> if (!block_follow(ls->t.token) && ls->t.token != ';') | |
| 80 | −diff -r lua-4.0/src/lstring.c lua/src/lstring.c | |
| 81 | −2c2 | |
| 82 | −< ** $Id: lstring.c,v 1.45 2000/10/30 17:49:19 roberto Exp $ | |
| 83 | −--- | |
| 84 | −> ** $Id: lstring.c,v 1.45a 2000/10/30 17:49:19 roberto Exp $ | |
| 85 | −122c122 | |
| 86 | −< ts->u.d.value = (udata == NULL) ? uts+1 : udata; | |
| 87 | −--- | |
| 88 | −> ts->u.d.value = (s > 0) ? uts+1 : udata; | |
| 89 | −diff -r lua-4.0/src/lvm.c lua/src/lvm.c | |
| 90 | −2c2 | |
| 91 | −< ** $Id: lvm.c,v 1.146 2000/10/26 12:47:05 roberto Exp $ | |
| 92 | −--- | |
| 93 | −> ** $Id: lvm.c,v 1.146a 2000/10/26 12:47:05 roberto Exp $ | |
| 94 | −82c82 | |
| 95 | −< luaD_lineHook(L, base-2, newline, linehook); | |
| 96 | −--- | |
| 97 | −> luaD_lineHook(L, base-1, newline, linehook); | |
| @@ -1,4 +1,52 @@ | ||
| 1 | −This is Lua 4.0. | |
| 1 | +This is Lua 5.0. | |
| 2 | + | |
| 3 | +* Changes from version 4.0 to 5.0 | |
| 4 | + ------------------------------- | |
| 5 | + Language: | |
| 6 | + + lexical scoping. | |
| 7 | + + Lua coroutines. | |
| 8 | + + standard libraries now packaged in tables. | |
| 9 | + + tags replaced by metatables and tag methods replaced by metamethods, | |
| 10 | + stored in metatables. | |
| 11 | + + proper tail calls. | |
| 12 | + + each function can have its own global table, which can be shared. | |
| 13 | + + new __newindex metamethod, called when we insert a new key into a table. | |
| 14 | + + new block comments: --[[ ... ]]. | |
| 15 | + + new generic for. | |
| 16 | + + new weak tables. | |
| 17 | + + new boolean type. | |
| 18 | + + new syntax "local function". | |
| 19 | + + (f()) returns the first value returned by f. | |
| 20 | + + {f()} fills a table with all values returned by f. | |
| 21 | + + \n ignored in [[\n . | |
| 22 | + + fixed and-or priorities. | |
| 23 | + + more general syntax for function definition (e.g. function a.x.y:f()...end). | |
| 24 | + + more general syntax for function calls (e.g. (print or write)(9)). | |
| 25 | + + new functions (time/date, tmpfile, unpack, require, load*, etc.). | |
| 26 | + API: | |
| 27 | + + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer. | |
| 28 | + + introduced lightweight userdata, a simple "void*" without a metatable. | |
| 29 | + + new error handling protocol: the core no longer prints error messages; | |
| 30 | + all errors are reported to the caller on the stack. | |
| 31 | + + new lua_atpanic for host cleanup. | |
| 32 | + + new, signal-safe, hook scheme. | |
| 33 | + Implementation: | |
| 34 | + + new license: MIT. | |
| 35 | + + new, faster, register-based virtual machine. | |
| 36 | + + support for external multithreading and coroutines. | |
| 37 | + + new and consistent error message format. | |
| 38 | + + the core no longer needs "stdio.h" for anything (except for a single | |
| 39 | + use of sprintf to convert numbers to strings). | |
| 40 | + + lua.c now runs the environment variable LUA_INIT, if present. It can | |
| 41 | + be "@filename", to run a file, or the chunk itself. | |
| 42 | + + support for user extensions in lua.c. | |
| 43 | + sample implementation given for command line editing. | |
| 44 | + + new dynamic loading library, active by default on several platforms. | |
| 45 | + + safe garbage-collector metamethods. | |
| 46 | + + precompiled bytecodes checked for integrity (secure binary dostring). | |
| 47 | + + strings are fully aligned. | |
| 48 | + + position capture in string.find. | |
| 49 | + + read('*l') can read lines with embedded zeros. | |
| 2 | 50 | |
| 3 | 51 | * Changes from version 3.2 to 4.0 |
| 4 | 52 | ------------------------------- |
| @@ -18,7 +66,7 @@ This is Lua 4.0. · 13 unmodified lines | ||
| 18 | 66 | + New API: fully re-entrant, simpler, and more efficient. |
| 19 | 67 | + New debug API. |
| 20 | 68 | Implementation: |
| 21 | − + cleaner virtual machine -- at least 20% faster. | |
| 69 | + + faster than ever: cleaner virtual machine and new hashing algorithm. | |
| 22 | 70 | + non-recursive garbage-collector algorithm. |
| 23 | 71 | + reduced memory usage for programs with many strings. |
| 24 | 72 | + improved treatment for memory allocation errors. |
| @@ -1,16 +1,18 @@ | ||
| 1 | −This is Lua 4.0. | |
| 1 | +This is Lua 5.0. | |
| 2 | 2 | |
| 3 | 3 | * Installation |
| 4 | 4 | ------------ |
| 5 | 5 | Building Lua on a Unix system should be very easy: |
| 6 | 6 | |
| 7 | − 1. Edit "config" to suit your platform, if at all necessary. | |
| 7 | + 1. Read "config" and edit it to suit your platform and needs. | |
| 8 | + We strongly recommend that you enable support for dynamic loading, | |
| 9 | + if your platform allows it. | |
| 8 | 10 | 2. Do "make". |
| 9 | 11 | 3. If you want to install Lua in an "official" place in your system, |
| 10 | 12 | then do "make install". The official place and the way to install |
| 11 | 13 | files are defined in "config". You may have to be root to do this. |
| 12 | 14 | |
| 13 | − See below for instructions for Windows and Macintosh. | |
| 15 | + See below for instructions for Windows and other systems. | |
| 14 | 16 | |
| 15 | 17 | * What you get |
| 16 | 18 | ------------ |
| @@ -20,7 +22,7 @@ This is Lua 4.0. · 3 unmodified lines | ||
| 20 | 22 | * include files in ./include. |
| 21 | 23 | These are the only directories you need for development. |
| 22 | 24 | |
| 23 | − There man pages for lua and luac in both nroff and html, and a reference | |
| 25 | + There are man pages for lua and luac, in both nroff and html; a reference | |
| 24 | 26 | manual in html in ./doc, some sample code in ./test, and some useful stuff |
| 25 | 27 | in ./etc. You don't need these directories for development. |
| 26 | 28 | |
| @@ -35,38 +37,44 @@ This is Lua 4.0. · 8 unmodified lines | ||
| 35 | 37 | * Shared libraries |
| 36 | 38 | ---------------- |
| 37 | 39 | If you are running Linux, do "make so" after "make" succeeds. |
| 38 | − This will create shared libraries in ./lib. It's probably better to | |
| 39 | − build shared libraries before "make install". | |
| 40 | + This will create shared libraries in ./lib. | |
| 41 | + To install those shared libraries in an official place, do "make soinstall". | |
| 40 | 42 | |
| 41 | 43 | If you want the interpreter and the compiler to use shared libraries, |
| 42 | − then do "make sobin" too. | |
| 44 | + then do "make sobin" too. You may want to do this before "make install". | |
| 43 | 45 | |
| 44 | − You may need to include lib/ in the LD_LIBRAY_PATH environment variable | |
| 45 | − to link programs that use the shared libraries if you don't put them in | |
| 46 | − the "official" places with "make install". | |
| 46 | + If you only want the shared libraries, you may want to add -fPIC to MYCFLAGS | |
| 47 | + in "config". Also, you may need to run "ldconfig" as root. | |
| 48 | + | |
| 49 | + You may need to include ./lib in the LD_LIBRARY_PATH environment variable | |
| 50 | + to link programs that use the shared libraries if you don't put them in the | |
| 51 | + official places with "make install". (You may need to use the full path.) | |
| 47 | 52 | |
| 48 | 53 | Building shared libraries in other systems is similar but details differ; |
| 49 | 54 | you may need to fix a few details in the top-level Makefile. |
| 50 | 55 | |
| 51 | −* Installation on Windows or Macintosh | |
| 52 | − ------------------------------------ | |
| 53 | − The instructions for building Lua on a Mac or Windows machine depend on | |
| 54 | − the particular compiler you are using. | |
| 55 | − The simplest way is to create a folder with all .c and .h files. | |
| 56 | − Then create projects for the core library, the standard library, | |
| 57 | − the interpreter, and the compiler, as follows: | |
| 56 | +* Installation on Windows and other systems | |
| 57 | + ----------------------------------------------------- | |
| 58 | + The instructions for building Lua on other systems machine depend on the | |
| 59 | + particular compiler you are using. The simplest way is to create a folder | |
| 60 | + with all .c and .h files, and then create projects for the core library, | |
| 61 | + the standard library, the interpreter, and the compiler, as follows: | |
| 58 | 62 | |
| 59 | − core lib: lapi.c lcode.c ldebug.c ldo.c lfunc.c lgc.c llex.c lmem.c | |
| 60 | − lobject.c lparser.c lstate.c lstring.c ltable.c ltests.c | |
| 61 | − ltm.c lundump.c lvm.c lzio.c | |
| 63 | + core lib: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c | |
| 64 | + lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c | |
| 65 | + ltable.c ltests.c ltm.c lundump.c lvm.c lzio.c | |
| 62 | 66 | |
| 63 | − standard lib: lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c lstrlib.c | |
| 67 | + standard lib: lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c ltablib.c | |
| 68 | + lstrlib.c loadlib.c | |
| 64 | 69 | |
| 65 | 70 | interpreter: core lib, standard lib, lua.c |
| 66 | 71 | |
| 67 | − compiler: core lib, dump.c luac.c opt.c print.c stubs.c | |
| 72 | + compiler: core lib, standard lib, luac.c print.c | |
| 73 | + and also lopcodes.c (with LUA_OPNAMES defined) from core. | |
| 68 | 74 | |
| 69 | 75 | Of course, to use Lua as a library, you'll have to know how to create |
| 70 | 76 | and use libraries with your compiler. |
| 71 | 77 | |
| 78 | + Also, read "config" to see what can be customized at compilation time. | |
| 79 | + | |
| 72 | 80 | (end of INSTALL) |
| @@ -1,133 +1,130 @@ | ||
| 1 | −MANIFEST contents of Lua 4.0 distribution on Mon Nov 6 19:15:16 EDT 2000 | |
| 2 | −lua | |
| 3 | −lua/COPYRIGHT | |
| 4 | −lua/HISTORY | |
| 5 | −lua/INSTALL | |
| 6 | −lua/MANIFEST | |
| 7 | −lua/Makefile | |
| 8 | −lua/README | |
| 9 | −lua/bin | |
| 10 | −lua/config | |
| 11 | −lua/doc | |
| 12 | −lua/doc/idx.html | |
| 13 | −lua/doc/index.html | |
| 14 | −lua/doc/logo.gif | |
| 15 | −lua/doc/lua.1 | |
| 16 | −lua/doc/lua.html | |
| 17 | −lua/doc/luac.1 | |
| 18 | −lua/doc/luac.html | |
| 19 | −lua/doc/manual.html | |
| 20 | −lua/doc/readme.html | |
| 21 | −lua/etc | |
| 22 | −lua/etc/Makefile | |
| 23 | −lua/etc/README | |
| 24 | −lua/etc/bin2c.c | |
| 25 | −lua/etc/def.lua | |
| 26 | −lua/etc/lua.ico | |
| 27 | −lua/etc/lua.magic | |
| 28 | −lua/etc/lua.xpm | |
| 29 | −lua/etc/min.c | |
| 30 | −lua/etc/setfallback.lua | |
| 31 | −lua/etc/stdcall.lua | |
| 32 | −lua/etc/trace.c | |
| 33 | −lua/include | |
| 34 | −lua/include/Makefile | |
| 35 | −lua/include/lauxlib.h | |
| 36 | −lua/include/lua.h | |
| 37 | −lua/include/luadebug.h | |
| 38 | −lua/include/lualib.h | |
| 39 | −lua/lib | |
| 40 | −lua/src | |
| 41 | −lua/src/Makefile | |
| 42 | −lua/src/lapi.c | |
| 43 | −lua/src/lapi.h | |
| 44 | −lua/src/lcode.c | |
| 45 | −lua/src/lcode.h | |
| 46 | −lua/src/ldebug.c | |
| 47 | −lua/src/ldebug.h | |
| 48 | −lua/src/ldo.c | |
| 49 | −lua/src/ldo.h | |
| 50 | −lua/src/lfunc.c | |
| 51 | −lua/src/lfunc.h | |
| 52 | −lua/src/lgc.c | |
| 53 | −lua/src/lgc.h | |
| 54 | −lua/src/lib | |
| 55 | −lua/src/lib/Makefile | |
| 56 | −lua/src/lib/README | |
| 57 | −lua/src/lib/lauxlib.c | |
| 58 | −lua/src/lib/lbaselib.c | |
| 59 | −lua/src/lib/ldblib.c | |
| 60 | −lua/src/lib/liolib.c | |
| 61 | −lua/src/lib/lmathlib.c | |
| 62 | −lua/src/lib/lstrlib.c | |
| 63 | −lua/src/llex.c | |
| 64 | −lua/src/llex.h | |
| 65 | −lua/src/llimits.h | |
| 66 | −lua/src/lmem.c | |
| 67 | −lua/src/lmem.h | |
| 68 | −lua/src/lobject.c | |
| 69 | −lua/src/lobject.h | |
| 70 | −lua/src/lopcodes.h | |
| 71 | −lua/src/lparser.c | |
| 72 | −lua/src/lparser.h | |
| 73 | −lua/src/lstate.c | |
| 74 | −lua/src/lstate.h | |
| 75 | −lua/src/lstring.c | |
| 76 | −lua/src/lstring.h | |
| 77 | −lua/src/ltable.c | |
| 78 | −lua/src/ltable.h | |
| 79 | −lua/src/ltests.c | |
| 80 | −lua/src/ltm.c | |
| 81 | −lua/src/ltm.h | |
| 82 | −lua/src/lua | |
| 83 | −lua/src/lua/Makefile | |
| 84 | −lua/src/lua/README | |
| 85 | −lua/src/lua/lua.c | |
| 86 | −lua/src/luac | |
| 87 | −lua/src/luac/Makefile | |
| 88 | −lua/src/luac/README | |
| 89 | −lua/src/luac/dump.c | |
| 90 | −lua/src/luac/luac.c | |
| 91 | −lua/src/luac/luac.h | |
| 92 | −lua/src/luac/opt.c | |
| 93 | −lua/src/luac/print.c | |
| 94 | −lua/src/luac/print.h | |
| 95 | −lua/src/luac/stubs.c | |
| 96 | −lua/src/lundump.c | |
| 97 | −lua/src/lundump.h | |
| 98 | −lua/src/lvm.c | |
| 99 | −lua/src/lvm.h | |
| 100 | −lua/src/lzio.c | |
| 101 | −lua/src/lzio.h | |
| 102 | −lua/test | |
| 103 | −lua/test/README | |
| 104 | −lua/test/bisect.lua | |
| 105 | −lua/test/cf-for.lua | |
| 106 | −lua/test/cf.lua | |
| 107 | −lua/test/examples | |
| 108 | −lua/test/examples/ps | |
| 109 | −lua/test/examples/ps/hilbert.lua | |
| 110 | −lua/test/examples/ps/ps.lua | |
| 111 | −lua/test/examples/www | |
| 112 | −lua/test/examples/www/README | |
| 113 | −lua/test/examples/www/db.lua | |
| 114 | −lua/test/examples/www/staff.lua | |
| 115 | −lua/test/examples/www/template.html | |
| 116 | −lua/test/factorial.lua | |
| 117 | −lua/test/fib.lua | |
| 118 | −lua/test/globals.lua | |
| 119 | −lua/test/hello.lua | |
| 120 | −lua/test/life.lua | |
| 121 | −lua/test/lisp.lua | |
| 122 | −lua/test/lua | |
| 123 | −lua/test/luac | |
| 124 | −lua/test/old.lua | |
| 125 | −lua/test/qp.lua | |
| 126 | −lua/test/save.lua | |
| 127 | −lua/test/sort.lua | |
| 128 | −lua/test/table.lua | |
| 129 | −lua/test/trace-calls.lua | |
| 130 | −lua/test/trace-globals.lua | |
| 131 | −lua/test/undefined.lua | |
| 132 | −lua/test/webform.lua | |
| 1 | +MANIFEST contents of Lua 5.0 distribution on Fri Apr 11 11:01:08 BRT 2003 | |
| 2 | +lua-5.0 | |
| 3 | +lua-5.0/COPYRIGHT | |
| 4 | +lua-5.0/HISTORY | |
| 5 | +lua-5.0/INSTALL | |
| 6 | +lua-5.0/MANIFEST | |
| 7 | +lua-5.0/Makefile | |
| 8 | +lua-5.0/README | |
| 9 | +lua-5.0/bin | |
| 10 | +lua-5.0/build | |
| 11 | +lua-5.0/config | |
| 12 | +lua-5.0/configure | |
| 13 | +lua-5.0/doc | |
| 14 | +lua-5.0/doc/logo.gif | |
| 15 | +lua-5.0/doc/lua.1 | |
| 16 | +lua-5.0/doc/lua.html | |
| 17 | +lua-5.0/doc/luac.1 | |
| 18 | +lua-5.0/doc/luac.html | |
| 19 | +lua-5.0/doc/manual.html | |
| 20 | +lua-5.0/doc/readme.html | |
| 21 | +lua-5.0/etc | |
| 22 | +lua-5.0/etc/.exrc | |
| 23 | +lua-5.0/etc/Makefile | |
| 24 | +lua-5.0/etc/README | |
| 25 | +lua-5.0/etc/bin2c.c | |
| 26 | +lua-5.0/etc/compat.lua | |
| 27 | +lua-5.0/etc/doall.lua | |
| 28 | +lua-5.0/etc/lua.ico | |
| 29 | +lua-5.0/etc/lua.magic | |
| 30 | +lua-5.0/etc/lua.xpm | |
| 31 | +lua-5.0/etc/luser_number.h | |
| 32 | +lua-5.0/etc/luser_tests.h | |
| 33 | +lua-5.0/etc/min.c | |
| 34 | +lua-5.0/etc/noparser.c | |
| 35 | +lua-5.0/etc/saconfig.c | |
| 36 | +lua-5.0/etc/trace.c | |
| 37 | +lua-5.0/include | |
| 38 | +lua-5.0/include/Makefile | |
| 39 | +lua-5.0/include/lauxlib.h | |
| 40 | +lua-5.0/include/lua.h | |
| 41 | +lua-5.0/include/lualib.h | |
| 42 | +lua-5.0/lib | |
| 43 | +lua-5.0/src | |
| 44 | +lua-5.0/src/Makefile | |
| 45 | +lua-5.0/src/README | |
| 46 | +lua-5.0/src/lapi.c | |
| 47 | +lua-5.0/src/lapi.h | |
| 48 | +lua-5.0/src/lcode.c | |
| 49 | +lua-5.0/src/lcode.h | |
| 50 | +lua-5.0/src/ldebug.c | |
| 51 | +lua-5.0/src/ldebug.h | |
| 52 | +lua-5.0/src/ldo.c | |
| 53 | +lua-5.0/src/ldo.h | |
| 54 | +lua-5.0/src/ldump.c | |
| 55 | +lua-5.0/src/lfunc.c | |
| 56 | +lua-5.0/src/lfunc.h | |
| 57 | +lua-5.0/src/lgc.c | |
| 58 | +lua-5.0/src/lgc.h | |
| 59 | +lua-5.0/src/lib | |
| 60 | +lua-5.0/src/lib/Makefile | |
| 61 | +lua-5.0/src/lib/README | |
| 62 | +lua-5.0/src/lib/lauxlib.c | |
| 63 | +lua-5.0/src/lib/lbaselib.c | |
| 64 | +lua-5.0/src/lib/ldblib.c | |
| 65 | +lua-5.0/src/lib/liolib.c | |
| 66 | +lua-5.0/src/lib/lmathlib.c | |
| 67 | +lua-5.0/src/lib/loadlib.c | |
| 68 | +lua-5.0/src/lib/lstrlib.c | |
| 69 | +lua-5.0/src/lib/ltablib.c | |
| 70 | +lua-5.0/src/llex.c | |
| 71 | +lua-5.0/src/llex.h | |
| 72 | +lua-5.0/src/llimits.h | |
| 73 | +lua-5.0/src/lmem.c | |
| 74 | +lua-5.0/src/lmem.h | |
| 75 | +lua-5.0/src/lobject.c | |
| 76 | +lua-5.0/src/lobject.h | |
| 77 | +lua-5.0/src/lopcodes.c | |
| 78 | +lua-5.0/src/lopcodes.h | |
| 79 | +lua-5.0/src/lparser.c | |
| 80 | +lua-5.0/src/lparser.h | |
| 81 | +lua-5.0/src/lstate.c | |
| 82 | +lua-5.0/src/lstate.h | |
| 83 | +lua-5.0/src/lstring.c | |
| 84 | +lua-5.0/src/lstring.h | |
| 85 | +lua-5.0/src/ltable.c | |
| 86 | +lua-5.0/src/ltable.h | |
| 87 | +lua-5.0/src/ltests.c | |
| 88 | +lua-5.0/src/ltm.c | |
| 89 | +lua-5.0/src/ltm.h | |
| 90 | +lua-5.0/src/lua | |
| 91 | +lua-5.0/src/lua/Makefile | |
| 92 | +lua-5.0/src/lua/README | |
| 93 | +lua-5.0/src/lua/lua.c | |
| 94 | +lua-5.0/src/luac | |
| 95 | +lua-5.0/src/luac/Makefile | |
| 96 | +lua-5.0/src/luac/README | |
| 97 | +lua-5.0/src/luac/luac.c | |
| 98 | +lua-5.0/src/luac/print.c | |
| 99 | +lua-5.0/src/lundump.c | |
| 100 | +lua-5.0/src/lundump.h | |
| 101 | +lua-5.0/src/lvm.c | |
| 102 | +lua-5.0/src/lvm.h | |
| 103 | +lua-5.0/src/lzio.c | |
| 104 | +lua-5.0/src/lzio.h | |
| 105 | +lua-5.0/test | |
| 106 | +lua-5.0/test/README | |
| 107 | +lua-5.0/test/bisect.lua | |
| 108 | +lua-5.0/test/cf.lua | |
| 109 | +lua-5.0/test/compat.lua | |
| 110 | +lua-5.0/test/echo.lua | |
| 111 | +lua-5.0/test/env.lua | |
| 112 | +lua-5.0/test/factorial.lua | |
| 113 | +lua-5.0/test/fib.lua | |
| 114 | +lua-5.0/test/fibfor.lua | |
| 115 | +lua-5.0/test/globals.lua | |
| 116 | +lua-5.0/test/hello.lua | |
| 117 | +lua-5.0/test/life.lua | |
| 118 | +lua-5.0/test/lua | |
| 119 | +lua-5.0/test/luac | |
| 120 | +lua-5.0/test/luac.lua | |
| 121 | +lua-5.0/test/printf.lua | |
| 122 | +lua-5.0/test/readonly.lua | |
| 123 | +lua-5.0/test/sieve.lua | |
| 124 | +lua-5.0/test/sort.lua | |
| 125 | +lua-5.0/test/table.lua | |
| 126 | +lua-5.0/test/trace-calls.lua | |
| 127 | +lua-5.0/test/trace-globals.lua | |
| 128 | +lua-5.0/test/undefined.lua | |
| 129 | +lua-5.0/test/xd.lua | |
| 133 | 130 | END OF MANIFEST |
| @@ -1,41 +1,99 @@ | ||
| 1 | 1 | # makefile for Lua hierarchy |
| 2 | 2 | # see INSTALL for installation instructions |
| 3 | −# see file "config" for customization instructions | |
| 3 | +# see config for customization instructions | |
| 4 | 4 | |
| 5 | 5 | LUA= . |
| 6 | 6 | |
| 7 | 7 | include $(LUA)/config |
| 8 | 8 | |
| 9 | −# primary targets (only "all" and "clean" are useful after distribution) | |
| 10 | −all clean co klean: | |
| 9 | +# primary targets ("co" and "klean" are used for making the distribution) | |
| 10 | +all clean co klean: dirs | |
| 11 | 11 | cd include; $(MAKE) $@ |
| 12 | 12 | cd src; $(MAKE) $@ |
| 13 | − cd src/luac; $(MAKE) $@ | |
| 14 | 13 | cd src/lib; $(MAKE) $@ |
| 14 | + cd src/luac; $(MAKE) $@ | |
| 15 | 15 | cd src/lua; $(MAKE) $@ |
| 16 | 16 | |
| 17 | +# in case they were not created during unpacking | |
| 18 | +dirs: bin lib | |
| 19 | + | |
| 20 | +bin lib: | |
| 21 | + mkdir -p $@ | |
| 22 | + | |
| 23 | +# simple test to see Lua working | |
| 24 | +test: all | |
| 25 | + bin/lua test/hello.lua | |
| 26 | + | |
| 17 | 27 | # remove debug information from binaries |
| 18 | 28 | strip: |
| 19 | − strip bin/lua bin/luac | |
| 29 | + $(STRIP) bin/* | |
| 20 | 30 | |
| 21 | 31 | # official installation |
| 22 | 32 | install: all strip |
| 23 | 33 | mkdir -p $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) |
| 24 | 34 | $(INSTALL_EXEC) bin/* $(INSTALL_BIN) |
| 25 | 35 | $(INSTALL_DATA) include/*.h $(INSTALL_INC) |
| 26 | − $(INSTALL_DATA) lib/lib* $(INSTALL_LIB) | |
| 36 | + $(INSTALL_DATA) lib/*.a $(INSTALL_LIB) | |
| 27 | 37 | $(INSTALL_DATA) doc/*.1 $(INSTALL_MAN) |
| 28 | 38 | |
| 29 | 39 | # shared libraries (for Linux) |
| 30 | 40 | so: |
| 31 | 41 | ld -o lib/liblua.so.$V -shared src/*.o |
| 32 | 42 | ld -o lib/liblualib.so.$V -shared src/lib/*.o |
| 33 | − cd lib; ln -s liblua.so.$V liblua.so; ln -s liblualib.so.$V liblualib.so | |
| 43 | + cd lib; ln -fs liblua.so.$V liblua.so; ln -fs liblualib.so.$V liblualib.so | |
| 34 | 44 | |
| 35 | 45 | # binaries using shared libraries |
| 36 | 46 | sobin: |
| 37 | − rm -f bin/lua bin/luac | |
| 47 | + rm -f bin/* | |
| 38 | 48 | cd src/lua; $(MAKE) |
| 39 | 49 | cd src/luac; $(MAKE) |
| 40 | 50 | |
| 51 | +# install shared libraries | |
| 52 | +soinstall: | |
| 53 | + $(INSTALL_EXEC) lib/*.so.* $(INSTALL_LIB) | |
| 54 | + cd $(INSTALL_LIB); ln -fs liblua.so.$V liblua.so; ln -fs liblualib.so.$V liblualib.so | |
| 55 | + | |
| 56 | +# clean shared libraries | |
| 57 | +soclean: | |
| 58 | + rm -f lib/*.so* bin/* | |
| 59 | + | |
| 60 | +# echo config parameters | |
| 61 | +echo: | |
| 62 | + @echo "" | |
| 63 | + @echo "These are the parameters currently set in $(LUA)/config to build Lua $V:" | |
| 64 | + @echo "" | |
| 65 | + @echo "LOADLIB = $(LOADLIB)" | |
| 66 | + @echo "DLLIB = $(DLLIB)" | |
| 67 | + @echo "NUMBER = $(NUMBER)" | |
| 68 | + @echo "POPEN = $(POPEN)" | |
| 69 | + @echo "TMPNAM = $(TMPNAM)" | |
| 70 | + @echo "DEGREES = $(DEGREES)" | |
| 71 | + @echo "USERCONF = $(USERCONF)" | |
| 72 | + @echo "CC = $(CC)" | |
| 73 | + @echo "WARN = $(WARN)" | |
| 74 | + @echo "MYCFLAGS = $(MYCFLAGS)" | |
| 75 | + @echo "MYLDFLAGS = $(MYLDFLAGS)" | |
| 76 | + @echo "EXTRA_LIBS = $(EXTRA_LIBS)" | |
| 77 | + @echo "AR = $(AR)" | |
| 78 | + @echo "RANLIB = $(RANLIB)" | |
| 79 | + @echo "STRIP = $(STRIP)" | |
| 80 | + @echo "INSTALL_ROOT = $(INSTALL_ROOT)" | |
| 81 | + @echo "INSTALL_BIN = $(INSTALL_BIN)" | |
| 82 | + @echo "INSTALL_INC = $(INSTALL_INC)" | |
| 83 | + @echo "INSTALL_LIB = $(INSTALL_LIB)" | |
| 84 | + @echo "INSTALL_MAN = $(INSTALL_MAN)" | |
| 85 | + @echo "INSTALL_EXEC = $(INSTALL_EXEC)" | |
| 86 | + @echo "INSTALL_DATA = $(INSTALL_DATA)" | |
| 87 | + @echo "" | |
| 88 | + @echo "Edit $(LUA)/config if needed to suit your platform and then run make." | |
| 89 | + @echo "" | |
| 90 | + | |
| 91 | +# turn config into Lua code | |
| 92 | +# uncomment the last sed expression if you want nil instead of empty strings | |
| 93 | +lecho: | |
| 94 | + @echo "-- $(LUA)/config for Lua $V" | |
| 95 | + @echo "VERSION = '$(V)'" | |
| 96 | + @make echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/' | |
| 97 | + @echo "-- EOF" | |
| 98 | + | |
| 41 | 99 | # (end of Makefile) |
| @@ -1,72 +1,44 @@ | ||
| 1 | −This is Lua 4.0. | |
| 2 | −See HISTORY for a summary of changes since the last version. | |
| 1 | +This is Lua 5.0. | |
| 2 | +See HISTORY for a summary of changes since the last released version. | |
| 3 | 3 | |
| 4 | 4 | * What is Lua? |
| 5 | 5 | ------------ |
| 6 | 6 | Lua is a powerful, light-weight programming language designed for extending |
| 7 | 7 | applications. Lua is also frequently used as a general-purpose, stand-alone |
| 8 | − language. | |
| 8 | + language. Lua is free software. | |
| 9 | 9 | |
| 10 | − Lua combines simple procedural syntax (similar to Pascal) with powerful | |
| 11 | − data description constructs based on associative arrays and extensible | |
| 12 | − semantics. Lua is dynamically typed, interpreted from bytecodes, and has | |
| 13 | − automatic memory management, making it ideal for configuration, scripting, | |
| 14 | − and rapid prototyping. | |
| 15 | − | |
| 16 | − Lua is a language engine that you can embed into your application. | |
| 17 | − This means that, besides syntax and semantics, Lua has an API that | |
| 18 | − allows the application to exchange data with Lua programs and also to | |
| 19 | − extend Lua with C functions. In this sense, Lua can be regarded as a | |
| 20 | − language framework for building domain-specific languages. | |
| 21 | − | |
| 22 | − Lua is implemented as a small library of C functions, written in ANSI C, | |
| 23 | − and compiles unmodified in all known platforms. The implementation goals | |
| 24 | − are simplicity, efficiency, portability, and low embedding cost. | |
| 25 | − The result is a fast language engine with small footprint, making it | |
| 26 | − ideal in embedded systems too. | |
| 27 | − | |
| 28 | − Lua was awarded the first prize (technological category) in the | |
| 29 | − Second Compaq Award for Research and Development in Computer Science in 1997. | |
| 30 | − This award was a joint venture of Compaq Computer in Brazil, the Brazilian | |
| 31 | − Ministry of Science and Technology, and the Brazilian Academy of Sciences. | |
| 10 | + For complete information, visit Lua's web site at http://www.lua.org/ . | |
| 11 | + For an executive summary, see http://www.lua.org/about.html . | |
| 32 | 12 | |
| 33 | 13 | Lua has been used in many different projects around the world. |
| 34 | − For a short list, see http://www.tecgraf.puc-rio.br/lua/uses.html . | |
| 14 | + For a short list, see http://www.lua.org/uses.html . | |
| 35 | 15 | |
| 36 | 16 | * Availability |
| 37 | 17 | ------------ |
| 38 | − Lua is freely available for both academic and commercial purposes and | |
| 39 | − can be downloaded from the sites below. See COPYRIGHT for details. | |
| 40 | − | |
| 41 | − Home page: http://www.tecgraf.puc-rio.br/lua/ | |
| 42 | − http://csg.uwaterloo.ca/~lhf/lua/ | |
| 43 | − In Brazil: ftp://ftp.tecgraf.puc-rio.br/pub/lua/ | |
| 44 | − In Canada: ftp://csg.uwaterloo.ca/pub/lhf/lua/ | |
| 45 | − In the US: ftp://ftp.freesoftware.com/pub/languages/lua/ | |
| 46 | − In Germany: ftp://ftp.uni-trier.de/pub/languages/lua/ | |
| 47 | − In Germany: ftp://ftp.gwdg.de/pub/languages/lua/ | |
| 48 | − In Greece: ftp://ftp.ntua.gr/pub/lang/lua/ | |
| 49 | − In Japan: ftp://ftp.u-aizu.ac.jp/pub/lang/lua/ | |
| 50 | − In Denmark: ftp://ftp.ucore.com/lua/dist | |
| 18 | + Lua is freely available for both academic and commercial purposes. | |
| 19 | + See COPYRIGHT and http://www.lua.org/license.html for details. | |
| 20 | + Lua can be downloaded from its official site http://www.lua.org/ and | |
| 21 | + several other sites aroung the world. For a complete list of mirror sites, | |
| 22 | + see http://www.lua.org/mirrors.html . | |
| 51 | 23 | |
| 52 | 24 | * Installation |
| 53 | 25 | ------------ |
| 54 | − See INSTALL. | |
| 26 | + Lua is implemented in pure ANSI C, and compiles unmodified in all known | |
| 27 | + platforms that have an ANSI C compiler. Under Unix, simply typing "make" | |
| 28 | + should work. See INSTALL for detailed instructions. | |
| 55 | 29 | |
| 56 | 30 | * Contacting the authors |
| 57 | 31 | ---------------------- |
| 58 | − Lua was designed and implemented by Waldemar Celes, Roberto Ierusalimschy | |
| 59 | − and Luiz Henrique de Figueiredo. | |
| 60 | − They can be contacted by email at lua@tecgraf.puc-rio.br. | |
| 61 | − | |
| 62 | 32 | Send your comments, questions, and bug reports to lua@tecgraf.puc-rio.br. |
| 33 | + For more information about the authors, see http://www.lua.org/authors.html . | |
| 63 | 34 | For reporting bugs, try also the mailing list: lua-l@tecgraf.puc-rio.br. |
| 64 | 35 | For more information about this list, including instructions on how to |
| 65 | − subscribe, see http://www.tecgraf.puc-rio.br/lua/lua-l.html . | |
| 36 | + subscribe and access the archives, see http://www.lua.org/lua-l.html . | |
| 66 | 37 | |
| 67 | − Lua is developed at TeCGraf, the Computer Graphics Technology Group | |
| 68 | − of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro in Brazil). | |
| 69 | − TeCGraf is a laboratory of the Department of Computer Science. | |
| 70 | − Dozens of industrial products developed by TeCGraf use Lua. | |
| 38 | +* Origin | |
| 39 | + ------ | |
| 40 | + Lua is developed at Tecgraf, the Computer Graphics Technology Group | |
| 41 | + of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro in Brazil). | |
| 42 | + Tecgraf is a laboratory of the Department of Computer Science. | |
| 71 | 43 | |
| 72 | 44 | (end of README) |
| @@ -1,19 +0,0 @@ | ||
| 1 | −This is an update of Lua 4.0 that includes the following bug fixes and | |
| 2 | −improvements: | |
| 3 | − | |
| 4 | −lua/src/lapi.c | |
| 5 | −lua/src/lstring.c | |
| 6 | − Fixed a bug in lua_pushuserdata(L, NULL) | |
| 7 | −lua/src/ldo.c | |
| 8 | −lua/src/lgc.c | |
| 9 | −lua/src/lgc.h | |
| 10 | − Give a good chance for GC before parsing | |
| 11 | −lua/src/lparser.c | |
| 12 | − Fixed a bug (did not accept `;' after a `return') | |
| 13 | −lua/src/lvm.c | |
| 14 | − Fixed a bug (linehook off by 1) | |
| 15 | −lua/src/lib/lbaselib.c | |
| 16 | − Fixed a bug in rawget and rawset (seg. fault if given extra arguments) | |
| 17 | − Fixed a bug in dostring (identification of precompiled chunks) | |
| 18 | − | |
| 19 | −To use simply open this tarball over the original Lua 4.0 source. | |
| @@ -0,0 +1,33 @@ | ||
| 1 | +# If you don't want to use make, run this script. | |
| 2 | +# But make sure you read config to see what can be customized. | |
| 3 | + | |
| 4 | + | |
| 5 | +# Easiest way to build bin/lua: | |
| 6 | +# cc -O2 -o bin/lua -Iinclude -Isrc src/*.c src/lib/*.c src/lua/*.c -lm -ldl | |
| 7 | + | |
| 8 | + | |
| 9 | +# Easiest way to build Lua libraries and executables: | |
| 10 | +echo -n 'building core library... ' | |
| 11 | +cd src | |
| 12 | +cc -O2 -c -I../include *.c | |
| 13 | +ar rc ../lib/liblua.a *.o | |
| 14 | +rm -f *.o | |
| 15 | + | |
| 16 | +echo -n 'standard library... ' | |
| 17 | +cd lib | |
| 18 | +cc -O2 -c -I../../include *.c | |
| 19 | +ar rc ../../lib/liblualib.a *.o | |
| 20 | +rm -f *.o | |
| 21 | + | |
| 22 | +echo -n 'lua... ' | |
| 23 | +cd ../lua | |
| 24 | +cc -O2 -o ../../bin/lua -I../../include *.c ../../lib/*.a -lm -ldl | |
| 25 | + | |
| 26 | +echo -n 'luac... ' | |
| 27 | +cd ../luac | |
| 28 | +cc -O2 -o ../../bin/luac -I../../include -I.. *.c -DLUA_OPNAMES ../lopcodes.c ../../lib/*.a | |
| 29 | + | |
| 30 | +echo 'done' | |
| 31 | + | |
| 32 | +cd ../.. | |
| 33 | +bin/lua test/hello.lua | |
| @@ -1,100 +1,178 @@ | ||
| 1 | −# configuration file for making Lua | |
| 1 | +# configuration file for making Lua 5.0 | |
| 2 | 2 | # see INSTALL for installation instructions |
| 3 | 3 | |
| 4 | −# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= | |
| 4 | +# These are default values. Skip this section and see the explanations below. | |
| 5 | + | |
| 6 | +LOADLIB= | |
| 7 | +DLLIB= | |
| 8 | +NUMBER= | |
| 9 | +POPEN= | |
| 10 | +TMPNAM= | |
| 11 | +DEGREES= | |
| 12 | +USERCONF= | |
| 5 | 13 | |
| 6 | −# ------------------------------------------------------------------ Lua | |
| 14 | +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= | |
| 7 | 15 | |
| 8 | −# Lua uses double for numbers. To change this, uncomment one of the lines below. | |
| 9 | −#NUMBER= -DLUA_NUM_TYPE=double | |
| 10 | −#NUMBER= -DLUA_NUM_TYPE=float | |
| 11 | −#NUMBER= -DLUA_NUM_TYPE=long | |
| 12 | −# Optionally, you may also want change how numbers are converted to strings, | |
| 13 | −# and vice-versa. Look for LUA_NUMBER in llimits.h and in the rest of the code. | |
| 16 | +# --------------------------------------------------------------- Lua libraries | |
| 17 | + | |
| 18 | +# Support for dynamically loading C libraries for Lua is a very important | |
| 19 | +# feature, which we strongly recommend be enabled. By default, this support is | |
| 20 | +# enabled on Windows systems (see below) but disabled on other systems because | |
| 21 | +# it relies on system-dependent code that is not part of ANSI C. For more | |
| 22 | +# information on dynamic loading, read the comments in src/lib/liolib.c . | |
| 23 | +# | |
| 24 | +# To enable support for dynamic loading on Unix systems that support the dlfcn | |
| 25 | +# interface (e.g., Linux, Solaris, IRIX, BSD, AIX, HPUX, and probably others), | |
| 26 | +# uncomment the next two lines. | |
| 27 | +# | |
| 28 | +#LOADLIB= -DUSE_DLOPEN=1 | |
| 29 | +#DLLIB= -ldl | |
| 30 | +# | |
| 31 | +# In Linux with gcc, you should also uncomment the next definition for | |
| 32 | +# MYLDFLAGS, which passes -E (= -export-dynamic) to the linker. This option | |
| 33 | +# allows dynamic libraries to link back to the `lua' program, so that they do | |
| 34 | +# not need the Lua libraries. (Other systems may have an equivalent facility.) | |
| 35 | +# | |
| 36 | +#MYLDFLAGS= -Wl,-E | |
| 37 | +# | |
| 38 | +# On Windows systems. support for dynamic loading is enabled by default. | |
| 39 | +# To disable this support, uncomment the next line. | |
| 40 | +# | |
| 41 | +#LOADLIB= -DUSE_DLL=0 | |
| 42 | + | |
| 43 | +# The Lua IO library (src/lib/liolib.c) has support for pipes using popen and | |
| 44 | +# pclose. This support is enabled by default on POSIX systems. | |
| 45 | +# If your system is not POSIX but has popen and pclose, define USE_POPEN=1. | |
| 46 | +# If you don't want to support pipes, define USE_POPEN=0. | |
| 47 | +# | |
| 48 | +#POPEN= -DUSE_POPEN=1 | |
| 49 | +#POPEN= -DUSE_POPEN=0 | |
| 50 | +# | |
| 51 | +# The form below will probably work in (some) Windows systems. | |
| 52 | +# | |
| 53 | +#POPEN= -DUSE_POPEN=1 -Dpopen=_popen -Dpclose=_pclose | |
| 54 | + | |
| 55 | +# The Lua OS library (src/lib/liolib.c) exports an interface to the C function | |
| 56 | +# tmpnam, which gcc now thinks is `dangerous'. So, support for tmpnam is | |
| 57 | +# disabled by default when compiling with gcc. | |
| 58 | +# If you still want to use tmpnam, define USE_TMPNAME=1. If you don't want to | |
| 59 | +# use tmpnam even if you're not compiling with gcc, define USE_TMPNAME=0. | |
| 60 | +# | |
| 61 | +#TMPNAM= -DUSE_TMPNAME=1 | |
| 62 | +#TMPNAM= -DUSE_TMPNAME=0 | |
| 63 | + | |
| 64 | +# The Lua math library (src/lib/lmathlib.c) now operates in radians, unlike | |
| 65 | +# previous versions of Lua, which used degrees. To use degrees instead of | |
| 66 | +# radians, define USE_DEGREES. | |
| 67 | +# | |
| 68 | +#DEGREES= -DUSE_DEGREES | |
| 69 | + | |
| 70 | +# ------------------------------------------------------------------ Lua core | |
| 71 | + | |
| 72 | +# Lua uses double for numbers. To change this, uncomment and edit the following | |
| 73 | +# line, changing USE_XXX to one of USE_DOUBLE, USE_FLOAT, USE_LONG, USE_INT. | |
| 74 | +# | |
| 75 | +#NUMBER= -DLUA_USER_H='"../etc/luser_number.h"' -DUSE_XXX | |
| 76 | + | |
| 77 | +# When compiling Lua with gcc on a Pentium machine, using a fast rounding | |
| 78 | +# method for the conversion of doubles to ints can give around 20% speed | |
| 79 | +# improvement. To use this rounding method, uncomment the following line. | |
| 80 | +#NUMBER= -DLUA_USER_H='"../etc/luser_number.h"' -DUSE_FASTROUND | |
| 81 | + | |
| 82 | +# For partial compatibility with old upvalue syntax, define LUA_COMPATUPSYNTAX. | |
| 83 | +# For partial compatibility with old upvalue behavior in C functions, define | |
| 84 | +# LUA_COMPATUPVALUES. Add these definitions to MYCFLAGS. | |
| 85 | +# | |
| 86 | +# -DLUA_COMPATUPSYNTAX -DLUA_COMPATUPVALUES | |
| 87 | + | |
| 88 | +# ------------------------------------------------------------- Lua interpreter | |
| 14 | 89 | |
| 15 | −# If you want support for pipes, uncomment the following line. | |
| 16 | −# You need popen in your C library. | |
| 17 | −#POPEN= -DPOPEN | |
| 90 | +# The stand-alone Lua interpreter needs the math functions, which are usually | |
| 91 | +# in libm.a (-lm). If your C library already includes the math functions, | |
| 92 | +# or if you are using a modified interpreter that does not need them, | |
| 93 | +# then comment the following line or add the appropriates libraries. | |
| 94 | +# | |
| 95 | +EXTRA_LIBS= -lm | |
| 18 | 96 | |
| 19 | −# If you need compatibility with previous versions, edit and uncomment the | |
| 20 | −# definition of COMPAT below. | |
| 21 | −# Use -DLUA_COMPAT_READPATTERN if you need complex read patterns. | |
| 22 | −# Use -DLUA_COMPAT_ARGRET if you need the old semantics that used only the | |
| 23 | −# first value returned by a function when it is called as the last parameter. | |
| 24 | −# Use -DLUA_DEPRECATEDFUNCS if you need the obsolete functions in the standard | |
| 25 | −# Lua library (not recommended). | |
| 26 | −#COMPAT= -DLUA_COMPAT_READPATTERN -DLUA_COMPAT_ARGRET -DLUA_DEPRECATEDFUNCS | |
| 97 | +# If you want to customize the stand-alone Lua interpreter, uncomment and | |
| 98 | +# edit the following two lines; also edit etc/saconfig.c to suit your needs. | |
| 99 | +# -DUSE_READLINE adds line editing and history to the interpreter. You need | |
| 100 | +# to add -lreadline (and perhaps also -lhistory and -lcurses or -lncurses) | |
| 101 | +# to EXTRA_LIBS. | |
| 102 | +# | |
| 103 | +#USERCONF=-DLUA_USERCONFIG='"$(LUA)/etc/saconfig.c"' -DUSE_READLINE | |
| 104 | +#EXTRA_LIBS= -lm -ldl -lreadline # -lhistory -lcurses -lncurses | |
| 27 | 105 | |
| 28 | 106 | # ------------------------------------------------------------------ C compiler |
| 29 | 107 | |
| 30 | −# You need an ANSI C compiler. gcc is a popular one. | |
| 108 | +# You need an ANSI C compiler. gcc is a popular one. We do not use -ansi in | |
| 109 | +# WARN because it disables POSIX features used in the libraries. | |
| 110 | +# | |
| 31 | 111 | CC= gcc |
| 32 | −WARN= -ansi -pedantic -Wall | |
| 33 | − | |
| 34 | −# On IRIX, cc is a good ANSI compiler. | |
| 35 | −#CC= cc | |
| 36 | −#WARN= -ansi -fullwarn | |
| 37 | − | |
| 38 | −# On Solaris, cc is optional. You may have to add -Dsparc if you use -Xc. | |
| 39 | −#CC= cc | |
| 40 | −#WARN= -Xc # -Dsparc | |
| 41 | − | |
| 42 | −# ------------------------------------------------------------------ C library | |
| 112 | +WARN= -Wall | |
| 43 | 113 | |
| 44 | −# If your C library is not POSIX compliant, comment the following line. | |
| 45 | −POSIX= -D_POSIX_SOURCE | |
| 114 | +# ------------------------------------------------------------------ C options | |
| 46 | 115 | |
| 47 | −# If your C library does not have the newer ANSI functions strerror, strcoll, | |
| 48 | −# and locale support, uncomment the following line. SunOs 4.1.x is one example. | |
| 49 | −#OLD_ANSI= -DOLD_ANSI | |
| 116 | +# Write here any options you may need for your C compiler. | |
| 117 | +# If you are using gcc, -O3 will get you a faster but larger code. You can | |
| 118 | +# also add -fomit-frame-pointer to get even faster code at the cost of losing | |
| 119 | +# debug information. If you only want the shared libraries, you may want to | |
| 120 | +# add -fPIC to MYCFLAGS. | |
| 121 | +# | |
| 122 | +MYCFLAGS= -O2 | |
| 123 | +#MYCFLAGS= -O3 -fomit-frame-pointer # -fPIC | |
| 50 | 124 | |
| 51 | −# In SunOs 4.1.x, standard headers in /usr/include are not ANSI, | |
| 52 | −# so uncomment the following line to avoid prototypes warnings. | |
| 53 | −#EXTRA_INCS= -I/usr/5include | |
| 54 | − | |
| 55 | −# The stand-alone Lua interpreter needs the math functions, which are usually | |
| 56 | −# in libm.a (-lm). If your C library already includes the math functions, | |
| 57 | −# or if you are using a modified interpreter that does not need them, | |
| 58 | −# then comment the following line. | |
| 59 | −EXTRA_LIBS= -lm | |
| 125 | +# Write here any options you may need for your C linker. | |
| 126 | +#MYLDFLAGS= | |
| 60 | 127 | |
| 61 | 128 | # ------------------------------------------------------------------ librarian |
| 62 | 129 | |
| 63 | 130 | # This should work in all Unix systems. |
| 131 | +# | |
| 64 | 132 | AR= ar rcu |
| 65 | 133 | |
| 66 | 134 | # If your system doesn't have (or need) ranlib, use RANLIB=true. |
| 67 | 135 | # On some systems, "ar s" does what ranlib would do. |
| 136 | +# | |
| 68 | 137 | RANLIB= ranlib |
| 69 | 138 | #RANLIB= ar s |
| 70 | 139 | #RANLIB= true |
| 71 | 140 | |
| 141 | +# ------------------------------------------------------------------ stripper | |
| 142 | + | |
| 143 | +# This should work in all Unix systems, but you may want to add options. | |
| 144 | +# | |
| 145 | +STRIP= strip | |
| 146 | + | |
| 72 | 147 | # ------------------------------------------------------------------ install |
| 73 | 148 | |
| 74 | 149 | # Locations for "make install". You may need to be root do "make install". |
| 150 | +# | |
| 75 | 151 | INSTALL_ROOT= /usr/local |
| 76 | 152 | INSTALL_BIN= $(INSTALL_ROOT)/bin |
| 77 | 153 | INSTALL_INC= $(INSTALL_ROOT)/include |
| 78 | 154 | INSTALL_LIB= $(INSTALL_ROOT)/lib |
| 79 | 155 | INSTALL_MAN= $(INSTALL_ROOT)/man/man1 |
| 80 | 156 | |
| 81 | −# You might prefer to use "install" if you have it. | |
| 157 | +# You may prefer to use "install" instead of "cp" if you have it. | |
| 158 | +# If you use "install", you may also want to change the permissions after -m. | |
| 159 | +# | |
| 82 | 160 | INSTALL_EXEC= cp |
| 83 | 161 | INSTALL_DATA= cp |
| 84 | 162 | #INSTALL_EXEC= install -m 0755 |
| 85 | 163 | #INSTALL_DATA= install -m 0644 |
| 86 | 164 | |
| 87 | −# == END OF USER SETTINGS. DO NOT CHANGE ANYTHING BELOW THIS LINE ============= | |
| 165 | +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= | |
| 166 | + | |
| 167 | +V=5.0 | |
| 88 | 168 | |
| 89 | 169 | BIN= $(LUA)/bin |
| 90 | 170 | INC= $(LUA)/include |
| 91 | 171 | LIB= $(LUA)/lib |
| 92 | 172 | |
| 93 | 173 | INCS= -I$(INC) $(EXTRA_INCS) |
| 94 | −DEFS= $(COMPAT) $(NUMBER) $(OLD_ANSI) $(EXTRA_DEFS) | |
| 95 | − | |
| 96 | −CFLAGS= -O2 $(WARN) $(INCS) $(DEFS) | |
| 174 | +DEFS= $(NUMBER) $(EXTRA_DEFS) | |
| 97 | 175 | |
| 98 | −V=4.0 | |
| 176 | +CFLAGS= $(MYCFLAGS) $(WARN) $(INCS) $(DEFS) | |
| 99 | 177 | |
| 100 | 178 | # (end of config) |
| @@ -0,0 +1,9 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | + | |
| 3 | +# Lua does not use GNU autoconf; just edit ./config if needed to suit your | |
| 4 | +# platform and then run make. | |
| 5 | + | |
| 6 | +# This shows the parameters currently set in ./config: | |
| 7 | +make echo | |
| 8 | + | |
| 9 | +# If you want config as a Lua program, run "make lecho". | |
| @@ -1,411 +0,0 @@ | ||
| 1 | −<HTML> | |
| 2 | −<HEAD> | |
| 3 | −<TITLE>Lua 4.0 Reference Manual - Word Index</TITLE> | |
| 4 | −</HEAD> | |
| 5 | − | |
| 6 | −<BODY BGCOLOR="#FFFFFF"> | |
| 7 | − | |
| 8 | −<HR> | |
| 9 | −<H1> | |
| 10 | −<IMG SRC="logo.gif" ALT="Lua" ALIGN="bottom"> | |
| 11 | −<A HREF="index.html">Reference manual</A> | |
| 12 | −- word index | |
| 13 | −</H1> | |
| 14 | − | |
| 15 | −<A HREF="manual.html#.."><TT>..</TT></A><BR> | |
| 16 | −<A HREF="manual.html#_ALERT"><TT>_ALERT</TT></A><BR> | |
| 17 | −<A HREF="manual.html#_ERRORMESSAGE"><TT>_ERRORMESSAGE</TT></A><BR> | |
| 18 | −<A HREF="manual.html#_INPUT"><TT>_INPUT</TT></A><BR> | |
| 19 | −<A HREF="manual.html#_OUTPUT"><TT>_OUTPUT</TT></A><BR> | |
| 20 | −<A HREF="manual.html#_PROMPT"><TT>_PROMPT</TT></A><BR> | |
| 21 | −<A HREF="manual.html#_STDERR"><TT>_STDERR</TT></A><BR> | |
| 22 | −<A HREF="manual.html#_STDIN"><TT>_STDIN</TT></A><BR> | |
| 23 | −<A HREF="manual.html#_STDOUT"><TT>_STDOUT</TT></A><BR> | |
| 24 | − | |
| 25 | − <P> | |
| 26 | − | |
| 27 | −<A HREF="manual.html#abs"><TT>abs</TT></A><BR> | |
| 28 | −<A HREF="manual.html#acceptable index">acceptable index</A><BR> | |
| 29 | −<A HREF="manual.html#acos"><TT>acos</TT></A><BR> | |
| 30 | −<A HREF="manual.html#add event">``add'' event</A><BR> | |
| 31 | −<A HREF="manual.html#Adjustment">adjustment</A><BR> | |
| 32 | −<A HREF="manual.html#alert"><TT>alert</TT></A><BR> | |
| 33 | −<A HREF="manual.html#and">and</A><BR> | |
| 34 | −<A HREF="manual.html#appendto"><TT>appendto</TT></A><BR> | |
| 35 | −<A HREF="manual.html#arg"><TT>arg</TT></A><BR> | |
| 36 | −<A HREF="manual.html#arguments">arguments</A><BR> | |
| 37 | −<A HREF="manual.html#arithmetic operators">arithmetic operators</A><BR> | |
| 38 | −<A HREF="manual.html#arrays">arrays</A><BR> | |
| 39 | −<A HREF="manual.html#asin"><TT>asin</TT></A><BR> | |
| 40 | −<A HREF="manual.html#assert"><TT>assert</TT></A><BR> | |
| 41 | −<A HREF="manual.html#Assignment">assignment</A><BR> | |
| 42 | −<A HREF="manual.html#associative arrays">associative arrays</A><BR> | |
| 43 | −<A HREF="manual.html#atan"><TT>atan</TT></A><BR> | |
| 44 | −<A HREF="manual.html#atan2"><TT>atan2</TT></A><BR> | |
| 45 | − | |
| 46 | − <P> | |
| 47 | − | |
| 48 | −<A HREF="manual.html#Basic Expressions">basic expressions</A><BR> | |
| 49 | −<A HREF="manual.html#basic types">basic types</A><BR> | |
| 50 | −<A HREF="manual.html#block">block</A><BR> | |
| 51 | −<A HREF="manual.html#break statement">break statement</A><BR> | |
| 52 | − | |
| 53 | − <P> | |
| 54 | − | |
| 55 | −<A HREF="manual.html#C API">C API</A><BR> | |
| 56 | −....... <A HREF="manual.html#LUA_ANYTAG"><TT>LUA_ANYTAG</TT></A><BR> | |
| 57 | −....... <A HREF="manual.html#lua_baselibopen"><TT>lua_baselibopen</TT></A><BR> | |
| 58 | −....... <A HREF="manual.html#lua_call"><TT>lua_call</TT></A><BR> | |
| 59 | −....... <A HREF="manual.html#lua_CFunction"><TT>lua_CFunction</TT></A><BR> | |
| 60 | −....... <A HREF="manual.html#lua_close"><TT>lua_close</TT></A><BR> | |
| 61 | −....... <A HREF="manual.html#lua_concat"><TT>lua_concat</TT></A><BR> | |
| 62 | −....... <A HREF="manual.html#lua_copytagmethods"><TT>lua_copytagmethods</TT></A><BR> | |
| 63 | −....... <A HREF="manual.html#lua_dblibopen"><TT>lua_dblibopen</TT></A><BR> | |
| 64 | −....... <A HREF="manual.html#lua_Debug"><TT>lua_Debug</TT></A><BR> | |
| 65 | −....... <A HREF="manual.html#lua_dobuffer"><TT>lua_dobuffer</TT></A><BR> | |
| 66 | −....... <A HREF="manual.html#lua_dofile"><TT>lua_dofile</TT></A><BR> | |
| 67 | −....... <A HREF="manual.html#lua_dostring"><TT>lua_dostring</TT></A><BR> | |
| 68 | −....... <A HREF="manual.html#lua_equal"><TT>lua_equal</TT></A><BR> | |
| 69 | −....... <A HREF="manual.html#LUA_ERRERR"><TT>LUA_ERRERR</TT></A><BR> | |
| 70 | −....... <A HREF="manual.html#LUA_ERRFILE"><TT>LUA_ERRFILE</TT></A><BR> | |
| 71 | −....... <A HREF="manual.html#LUA_ERRMEM"><TT>LUA_ERRMEM</TT></A><BR> | |
| 72 | −....... <A HREF="manual.html#lua_error"><TT>lua_error</TT></A><BR> | |
| 73 | −....... <A HREF="manual.html#LUA_ERRRUN"><TT>LUA_ERRRUN</TT></A><BR> | |
| 74 | −....... <A HREF="manual.html#LUA_ERRSYNTAX"><TT>LUA_ERRSYNTAX</TT></A><BR> | |
| 75 | −....... <A HREF="manual.html#lua_getgccount"><TT>lua_getgccount</TT></A><BR> | |
| 76 | −....... <A HREF="manual.html#lua_getgcthreshold"><TT>lua_getgcthreshold</TT></A><BR> | |
| 77 | −....... <A HREF="manual.html#lua_getglobal"><TT>lua_getglobal</TT></A><BR> | |
| 78 | −....... <A HREF="manual.html#lua_getglobals"><TT>lua_getglobals</TT></A><BR> | |
| 79 | −....... <A HREF="manual.html#lua_getinfo"><TT>lua_getinfo</TT></A><BR> | |
| 80 | −....... <A HREF="manual.html#lua_getlocal"><TT>lua_getlocal</TT></A><BR> | |
| 81 | −....... <A HREF="manual.html#lua_getn"><TT>lua_getn</TT></A><BR> | |
| 82 | −....... <A HREF="manual.html#lua_getref"><TT>lua_getref</TT></A><BR> | |
| 83 | −....... <A HREF="manual.html#lua_getregistry"><TT>lua_getregistry</TT></A><BR> | |
| 84 | −....... <A HREF="manual.html#lua_getstack"><TT>lua_getstack</TT></A><BR> | |
| 85 | −....... <A HREF="manual.html#lua_gettable"><TT>lua_gettable</TT></A><BR> | |
| 86 | −....... <A HREF="manual.html#lua_gettagmethod"><TT>lua_gettagmethod</TT></A><BR> | |
| 87 | −....... <A HREF="manual.html#lua_gettop"><TT>lua_gettop</TT></A><BR> | |
| 88 | −....... <A HREF="manual.html#lua_Hook"><TT>lua_Hook</TT></A><BR> | |
| 89 | −....... <A HREF="manual.html#lua_insert"><TT>lua_insert</TT></A><BR> | |
| 90 | −....... <A HREF="manual.html#lua_iolibopen"><TT>lua_iolibopen</TT></A><BR> | |
| 91 | −....... <A HREF="manual.html#lua_iscfunction"><TT>lua_iscfunction</TT></A><BR> | |
| 92 | −....... <A HREF="manual.html#lua_isfunction"><TT>lua_isfunction</TT></A><BR> | |
| 93 | −....... <A HREF="manual.html#lua_isnil"><TT>lua_isnil</TT></A><BR> | |
| 94 | −....... <A HREF="manual.html#lua_isnumber"><TT>lua_isnumber</TT></A><BR> | |
| 95 | −....... <A HREF="manual.html#lua_isstring"><TT>lua_isstring</TT></A><BR> | |
| 96 | −....... <A HREF="manual.html#lua_istable"><TT>lua_istable</TT></A><BR> | |
| 97 | −....... <A HREF="manual.html#lua_isuserdata"><TT>lua_isuserdata</TT></A><BR> | |
| 98 | −....... <A HREF="manual.html#lua_lessthan"><TT>lua_lessthan</TT></A><BR> | |
| 99 | −....... <A HREF="manual.html#lua_mathlibopen"><TT>lua_mathlibopen</TT></A><BR> | |
| 100 | −....... <A HREF="manual.html#LUA_MINSTACK"><TT>LUA_MINSTACK</TT></A><BR> | |
| 101 | −....... <A HREF="manual.html#LUA_MULTRET"><TT>LUA_MULTRET</TT></A><BR> | |
| 102 | −....... <A HREF="manual.html#lua_newtable"><TT>lua_newtable</TT></A><BR> | |
| 103 | −....... <A HREF="manual.html#lua_newtag"><TT>lua_newtag</TT></A><BR> | |
| 104 | −....... <A HREF="manual.html#lua_next"><TT>lua_next</TT></A><BR> | |
| 105 | −....... <A HREF="manual.html#LUA_NOREF"><TT>LUA_NOREF</TT></A><BR> | |
| 106 | −....... <A HREF="manual.html#lua_open"><TT>lua_open</TT></A><BR> | |
| 107 | −....... <A HREF="manual.html#lua_pushcclosure"><TT>lua_pushcclosure</TT></A><BR> | |
| 108 | −....... <A HREF="manual.html#lua_pushcfunction"><TT>lua_pushcfunction</TT></A><BR> | |
| 109 | −....... <A HREF="manual.html#lua_pushlstring"><TT>lua_pushlstring</TT></A><BR> | |
| 110 | −....... <A HREF="manual.html#lua_pushnil"><TT>lua_pushnil</TT></A><BR> | |
| 111 | −....... <A HREF="manual.html#lua_pushnumber"><TT>lua_pushnumber</TT></A><BR> | |
| 112 | −....... <A HREF="manual.html#lua_pushstring"><TT>lua_pushstring</TT></A><BR> | |
| 113 | −....... <A HREF="manual.html#lua_pushuserdata"><TT>lua_pushuserdata</TT></A><BR> | |
| 114 | −....... <A HREF="manual.html#lua_pushusertag"><TT>lua_pushusertag</TT></A><BR> | |
| 115 | −....... <A HREF="manual.html#lua_pushvalue"><TT>lua_pushvalue</TT></A><BR> | |
| 116 | −....... <A HREF="manual.html#lua_rawcall"><TT>lua_rawcall</TT></A><BR> | |
| 117 | −....... <A HREF="manual.html#lua_rawget"><TT>lua_rawget</TT></A><BR> | |
| 118 | −....... <A HREF="manual.html#lua_rawgeti"><TT>lua_rawgeti</TT></A><BR> | |
| 119 | −....... <A HREF="manual.html#lua_rawset"><TT>lua_rawset</TT></A><BR> | |
| 120 | −....... <A HREF="manual.html#lua_rawseti"><TT>lua_rawseti</TT></A><BR> | |
| 121 | −....... <A HREF="manual.html#lua_ref"><TT>lua_ref</TT></A><BR> | |
| 122 | −....... <A HREF="manual.html#LUA_REFNIL"><TT>LUA_REFNIL</TT></A><BR> | |
| 123 | −....... <A HREF="manual.html#LUA_REFREGISTRY"><TT>LUA_REFREGISTRY</TT></A><BR> | |
| 124 | −....... <A HREF="manual.html#lua_register"><TT>lua_register</TT></A><BR> | |
| 125 | −....... <A HREF="manual.html#lua_remove"><TT>lua_remove</TT></A><BR> | |
| 126 | −....... <A HREF="manual.html#lua_setcallhook"><TT>lua_setcallhook</TT></A><BR> | |
| 127 | −....... <A HREF="manual.html#lua_setgcthreshold"><TT>lua_setgcthreshold</TT></A><BR> | |
| 128 | −....... <A HREF="manual.html#lua_setglobal"><TT>lua_setglobal</TT></A><BR> | |
| 129 | −....... <A HREF="manual.html#lua_setglobals"><TT>lua_setglobals</TT></A><BR> | |
| 130 | −....... <A HREF="manual.html#lua_setlinehook"><TT>lua_setlinehook</TT></A><BR> | |
| 131 | −....... <A HREF="manual.html#lua_setlocal"><TT>lua_setlocal</TT></A><BR> | |
| 132 | −....... <A HREF="manual.html#lua_settable"><TT>lua_settable</TT></A><BR> | |
| 133 | −....... <A HREF="manual.html#lua_settag"><TT>lua_settag</TT></A><BR> | |
| 134 | −....... <A HREF="manual.html#lua_settagmethod"><TT>lua_settagmethod</TT></A><BR> | |
| 135 | −....... <A HREF="manual.html#lua_settop"><TT>lua_settop</TT></A><BR> | |
| 136 | −....... <A HREF="manual.html#lua_stackspace"><TT>lua_stackspace</TT></A><BR> | |
| 137 | −....... <A HREF="manual.html#lua_State"><TT>lua_State</TT></A><BR> | |
| 138 | −....... <A HREF="manual.html#lua_strlen"><TT>lua_strlen</TT></A><BR> | |
| 139 | −....... <A HREF="manual.html#lua_strlibopen"><TT>lua_strlibopen</TT></A><BR> | |
| 140 | −....... <A HREF="manual.html#lua_tag"><TT>lua_tag</TT></A><BR> | |
| 141 | −....... <A HREF="manual.html#lua_tocfunction"><TT>lua_tocfunction</TT></A><BR> | |
| 142 | −....... <A HREF="manual.html#lua_tonumber"><TT>lua_tonumber</TT></A><BR> | |
| 143 | −....... <A HREF="manual.html#lua_tostring"><TT>lua_tostring</TT></A><BR> | |
| 144 | −....... <A HREF="manual.html#lua_touserdata"><TT>lua_touserdata</TT></A><BR> | |
| 145 | −....... <A HREF="manual.html#lua_type"><TT>lua_type</TT></A><BR> | |
| 146 | −....... <A HREF="manual.html#lua_typename"><TT>lua_typename</TT></A><BR> | |
| 147 | −....... <A HREF="manual.html#lua_unref"><TT>lua_unref</TT></A><BR> | |
| 148 | −<A HREF="manual.html#C closure">C closure</A><BR> | |
| 149 | −<A HREF="manual.html#C pointers">C pointers</A><BR> | |
| 150 | −<A HREF="manual.html#call"><TT>call</TT></A><BR> | |
| 151 | −<A HREF="manual.html#captures">captures</A><BR> | |
| 152 | −<A HREF="manual.html#ceil"><TT>ceil</TT></A><BR> | |
| 153 | −<A HREF="manual.html#character class">character class</A><BR> | |
| 154 | −<A HREF="manual.html#chunk">chunk</A><BR> | |
| 155 | −<A HREF="manual.html#clock"><TT>clock</TT></A><BR> | |
| 156 | −<A HREF="manual.html#closefile"><TT>closefile</TT></A><BR> | |
| 157 | −<A HREF="manual.html#closing a file">closing a file</A><BR> | |
| 158 | −<A HREF="manual.html#Coercion">coercion</A><BR> | |
| 159 | −<A HREF="manual.html#collectgarbage"><TT>collectgarbage</TT></A><BR> | |
| 160 | −<A HREF="manual.html#Comments">comments</A><BR> | |
| 161 | −<A HREF="manual.html#concatenation">concatenation</A><BR> | |
| 162 | −<A HREF="manual.html#concatenation event">``concatenation'' event</A><BR> | |
| 163 | −<A HREF="manual.html#condition expression">condition expression</A><BR> | |
| 164 | −<A HREF="manual.html#constructors">constructors</A><BR> | |
| 165 | −<A HREF="manual.html#copytagmethods"><TT>copytagmethods</TT></A><BR> | |
| 166 | −<A HREF="manual.html#cos"><TT>cos</TT></A><BR> | |
| 167 | − | |
| 168 | − <P> | |
| 169 | − | |
| 170 | −<A HREF="manual.html#date"><TT>date</TT></A><BR> | |
| 171 | −<A HREF="manual.html#def"><TT>def</TT></A><BR> | |
| 172 | −<A HREF="manual.html#div event">``div'' event</A><BR> | |
| 173 | −<A HREF="manual.html#dofile"><TT>dofile</TT></A><BR> | |
| 174 | −<A HREF="manual.html#dostring"><TT>dostring</TT></A><BR> | |
| 175 | − | |
| 176 | − <P> | |
| 177 | − | |
| 178 | −<A HREF="manual.html#eight-bit clean">eight-bit clean</A><BR> | |
| 179 | −<A HREF="manual.html#error"><TT>error</TT></A><BR> | |
| 180 | −<A HREF="manual.html#event">event</A><BR> | |
| 181 | −<A HREF="manual.html#execute"><TT>execute</TT></A><BR> | |
| 182 | −<A HREF="manual.html#exit"><TT>exit</TT></A><BR> | |
| 183 | −<A HREF="manual.html#exp"><TT>exp</TT></A><BR> | |
| 184 | −<A HREF="manual.html#exponentiation">exponentiation</A><BR> | |
| 185 | −<A HREF="manual.html#Expressions">expressions</A><BR> | |
| 186 | − | |
| 187 | − <P> | |
| 188 | − | |
| 189 | −<A HREF="manual.html#file handles">file handles</A><BR> | |
| 190 | −<A HREF="manual.html#floor"><TT>floor</TT></A><BR> | |
| 191 | −<A HREF="manual.html#flush"><TT>flush</TT></A><BR> | |
| 192 | −<A HREF="manual.html#for statement">for statement</A><BR> | |
| 193 | −<A HREF="manual.html#foreach"><TT>foreach</TT></A><BR> | |
| 194 | −<A HREF="manual.html#foreachi"><TT>foreachi</TT></A><BR> | |
| 195 | −<A HREF="manual.html#format"><TT>format</TT></A><BR> | |
| 196 | −<A HREF="manual.html#frexp"><TT>frexp</TT></A><BR> | |
| 197 | −<A HREF="manual.html#function">function</A><BR> | |
| 198 | −<A HREF="manual.html#function call">function call</A><BR> | |
| 199 | −<A HREF="manual.html#Function Definitions">function definitions</A><BR> | |
| 200 | −<A HREF="manual.html#function event">``function'' event</A><BR> | |
| 201 | − | |
| 202 | − <P> | |
| 203 | − | |
| 204 | −<A HREF="manual.html#gc event">``gc'' event</A><BR> | |
| 205 | −<A HREF="manual.html#getargs"><TT>getargs</TT></A><BR> | |
| 206 | −<A HREF="manual.html#getenv"><TT>getenv</TT></A><BR> | |
| 207 | −<A HREF="manual.html#getglobal"><TT>getglobal</TT></A><BR> | |
| 208 | −<A HREF="manual.html#getglobal event">``getglobal'' event</A><BR> | |
| 209 | −<A HREF="manual.html#getinfo"><TT>getinfo</TT></A><BR> | |
| 210 | −<A HREF="manual.html#getlocal"><TT>getlocal</TT></A><BR> | |
| 211 | −<A HREF="manual.html#getn"><TT>getn</TT></A><BR> | |
| 212 | −<A HREF="manual.html#gettable event">``gettable'' event</A><BR> | |
| 213 | −<A HREF="manual.html#gettagmethod"><TT>gettagmethod</TT></A><BR> | |
| 214 | −<A HREF="manual.html#global environment">global environment</A><BR> | |
| 215 | −<A HREF="manual.html#Global variables">global variables</A><BR> | |
| 216 | −<A HREF="manual.html#globals"><TT>globals</TT></A><BR> | |
| 217 | −<A HREF="manual.html#grammar">grammar</A><BR> | |
| 218 | −....... <A HREF="manual.html#args">args</A><BR> | |
| 219 | −....... <A HREF="manual.html#binop">binop</A><BR> | |
| 220 | −....... <A HREF="manual.html#block">block</A><BR> | |
| 221 | −....... <A HREF="manual.html#chunk">chunk</A><BR> | |
| 222 | −....... <A HREF="manual.html#declist">declist</A><BR> | |
| 223 | −....... <A HREF="manual.html#exp">exp</A><BR> | |
| 224 | −....... <A HREF="manual.html#exp1">exp1</A><BR> | |
| 225 | −....... <A HREF="manual.html#explist1">explist1</A><BR> | |
| 226 | −....... <A HREF="manual.html#ffield">ffield</A><BR> | |
| 227 | −....... <A HREF="manual.html#ffieldlist">ffieldlist</A><BR> | |
| 228 | −....... <A HREF="manual.html#ffieldlist1">ffieldlist1</A><BR> | |
| 229 | −....... <A HREF="manual.html#fieldlist">fieldlist</A><BR> | |
| 230 | −....... <A HREF="manual.html#funcname">funcname</A><BR> | |
| 231 | −....... <A HREF="manual.html#function">function</A><BR> | |
| 232 | −....... <A HREF="manual.html#functioncall">functioncall</A><BR> | |
| 233 | −....... <A HREF="manual.html#init">init</A><BR> | |
| 234 | −....... <A HREF="manual.html#lfieldlist">lfieldlist</A><BR> | |
| 235 | −....... <A HREF="manual.html#lfieldlist1">lfieldlist1</A><BR> | |
| 236 | −....... <A HREF="manual.html#parlist1">parlist1</A><BR> | |
| 237 | −....... <A HREF="manual.html#stat">stat</A><BR> | |
| 238 | −....... <A HREF="manual.html#tableconstructor">tableconstructor</A><BR> | |
| 239 | −....... <A HREF="manual.html#unop">unop</A><BR> | |
| 240 | −....... <A HREF="manual.html#upvalue">upvalue</A><BR> | |
| 241 | −....... <A HREF="manual.html#var">var</A><BR> | |
| 242 | −....... <A HREF="manual.html#varlist1">varlist1</A><BR> | |
| 243 | −....... <A HREF="manual.html#varorfunc">varorfunc</A><BR> | |
| 244 | −<A HREF="manual.html#gsub"><TT>gsub</TT></A><BR> | |
| 245 | − | |
| 246 | − <P> | |
| 247 | − | |
| 248 | −<A HREF="manual.html#Identifiers">identifiers</A><BR> | |
| 249 | −<A HREF="manual.html#if-then-else statement">if-then-else statement</A><BR> | |
| 250 | −<A HREF="manual.html#index event">``index'' event</A><BR> | |
| 251 | − | |
| 252 | − <P> | |
| 253 | − | |
| 254 | −<A HREF="manual.html#ldexp"><TT>ldexp</TT></A><BR> | |
| 255 | −<A HREF="manual.html#Literal strings">literal strings</A><BR> | |
| 256 | −<A HREF="manual.html#Local variables">local variables</A><BR> | |
| 257 | −<A HREF="manual.html#log"><TT>log</TT></A><BR> | |
| 258 | −<A HREF="manual.html#log10"><TT>log10</TT></A><BR> | |
| 259 | −<A HREF="manual.html#logical operators">logical operators</A><BR> | |
| 260 | −<A HREF="manual.html#lt event">``lt'' event</A><BR> | |
| 261 | −<A HREF="manual.html#Lua Stand-alone">Lua stand-alone</A><BR> | |
| 262 | −<A HREF="manual.html#luac"><TT>luac</TT></A><BR> | |
| 263 | − | |
| 264 | − <P> | |
| 265 | − | |
| 266 | −<A HREF="manual.html#max"><TT>max</TT></A><BR> | |
| 267 | −<A HREF="manual.html#methods">methods</A><BR> | |
| 268 | −<A HREF="manual.html#min"><TT>min</TT></A><BR> | |
| 269 | −<A HREF="manual.html#mod"><TT>mod</TT></A><BR> | |
| 270 | −<A HREF="manual.html#mul event">``mul'' event</A><BR> | |
| 271 | −<A HREF="manual.html#multiple assignment">multiple assignment</A><BR> | |
| 272 | − | |
| 273 | − <P> | |
| 274 | − | |
| 275 | −<A HREF="manual.html#newtag"><TT>newtag</TT></A><BR> | |
| 276 | −<A HREF="manual.html#next"><TT>next</TT></A><BR> | |
| 277 | −<A HREF="manual.html#nil">nil</A><BR> | |
| 278 | −<A HREF="manual.html#not">not</A><BR> | |
| 279 | −<A HREF="manual.html#number">number</A><BR> | |
| 280 | −<A HREF="manual.html#Numerical constants">numerical constants</A><BR> | |
| 281 | − | |
| 282 | − <P> | |
| 283 | − | |
| 284 | −<A HREF="manual.html#openfile"><TT>openfile</TT></A><BR> | |
| 285 | −<A HREF="manual.html#Operator precedence">operator precedence</A><BR> | |
| 286 | −<A HREF="manual.html#or">or</A><BR> | |
| 287 | − | |
| 288 | − <P> | |
| 289 | − | |
| 290 | −<A HREF="manual.html#pattern">pattern</A><BR> | |
| 291 | −<A HREF="manual.html#pattern item">pattern item</A><BR> | |
| 292 | −<A HREF="manual.html#PI"><TT>PI</TT></A><BR> | |
| 293 | −<A HREF="manual.html#piped input">piped input</A><BR> | |
| 294 | −<A HREF="manual.html#popen"><TT>popen</TT></A><BR> | |
| 295 | −<A HREF="manual.html#pow event">``pow'' event</A><BR> | |
| 296 | −<A HREF="manual.html#pre-compilation">pre-compilation</A><BR> | |
| 297 | −<A HREF="manual.html#print"><TT>print</TT></A><BR> | |
| 298 | −<A HREF="manual.html#protected calls">protected calls</A><BR> | |
| 299 | − | |
| 300 | − <P> | |
| 301 | − | |
| 302 | −<A HREF="manual.html#rad"><TT>rad</TT></A><BR> | |
| 303 | −<A HREF="manual.html#random"><TT>random</TT></A><BR> | |
| 304 | −<A HREF="manual.html#randomseed"><TT>randomseed</TT></A><BR> | |
| 305 | −<A HREF="manual.html#rawget"><TT>rawget</TT></A><BR> | |
| 306 | −<A HREF="manual.html#rawset"><TT>rawset</TT></A><BR> | |
| 307 | −<A HREF="manual.html#read"><TT>read</TT></A><BR> | |
| 308 | −<A HREF="manual.html#readfrom"><TT>readfrom</TT></A><BR> | |
| 309 | −<A HREF="manual.html#records">records</A><BR> | |
| 310 | −<A HREF="manual.html#reference">reference</A><BR> | |
| 311 | −<A HREF="manual.html#relational operators">relational operators</A><BR> | |
| 312 | −<A HREF="manual.html#remove"><TT>remove</TT></A><BR> | |
| 313 | −<A HREF="manual.html#rename"><TT>rename</TT></A><BR> | |
| 314 | −<A HREF="manual.html#repeat-until statement">repeat-until statement</A><BR> | |
| 315 | −<A HREF="manual.html#reserved words">reserved words</A><BR> | |
| 316 | −<A HREF="manual.html#return statement">return statement</A><BR> | |
| 317 | − | |
| 318 | − <P> | |
| 319 | − | |
| 320 | −<A HREF="manual.html#seek"><TT>seek</TT></A><BR> | |
| 321 | −<A HREF="manual.html#self"><TT>self</TT></A><BR> | |
| 322 | −<A HREF="manual.html#setcallhook"><TT>setcallhook</TT></A><BR> | |
| 323 | −<A HREF="manual.html#setglobal"><TT>setglobal</TT></A><BR> | |
| 324 | −<A HREF="manual.html#setglobal event">``setglobal'' event</A><BR> | |
| 325 | −<A HREF="manual.html#setlinehook"><TT>setlinehook</TT></A><BR> | |
| 326 | −<A HREF="manual.html#setlocal"><TT>setlocal</TT></A><BR> | |
| 327 | −<A HREF="manual.html#setlocale"><TT>setlocale</TT></A><BR> | |
| 328 | −<A HREF="manual.html#settable event">``settable'' event</A><BR> | |
| 329 | −<A HREF="manual.html#settag"><TT>settag</TT></A><BR> | |
| 330 | −<A HREF="manual.html#settagmethod"><TT>settagmethod</TT></A><BR> | |
| 331 | −<A HREF="manual.html#short-cut evaluation">short-cut evaluation</A><BR> | |
| 332 | −<A HREF="manual.html#sin"><TT>sin</TT></A><BR> | |
| 333 | −<A HREF="manual.html#sort"><TT>sort</TT></A><BR> | |
| 334 | −<A HREF="manual.html#sqrt"><TT>sqrt</TT></A><BR> | |
| 335 | −<A HREF="manual.html#stack index">stack index</A><BR> | |
| 336 | −<A HREF="manual.html#state">state</A><BR> | |
| 337 | −<A HREF="manual.html#statements">statements</A><BR> | |
| 338 | −<A HREF="manual.html#stderr"><TT>stderr</TT></A><BR> | |
| 339 | −<A HREF="manual.html#strbyte"><TT>strbyte</TT></A><BR> | |
| 340 | −<A HREF="manual.html#strchar"><TT>strchar</TT></A><BR> | |
| 341 | −<A HREF="manual.html#strfind"><TT>strfind</TT></A><BR> | |
| 342 | −<A HREF="manual.html#string">string</A><BR> | |
| 343 | −<A HREF="manual.html#strlen"><TT>strlen</TT></A><BR> | |
| 344 | −<A HREF="manual.html#strlower"><TT>strlower</TT></A><BR> | |
| 345 | −<A HREF="manual.html#strrep"><TT>strrep</TT></A><BR> | |
| 346 | −<A HREF="manual.html#strsub"><TT>strsub</TT></A><BR> | |
| 347 | −<A HREF="manual.html#strupper"><TT>strupper</TT></A><BR> | |
| 348 | −<A HREF="manual.html#sub event">``sub'' event</A><BR> | |
| 349 | − | |
| 350 | − <P> | |
| 351 | − | |
| 352 | −<A HREF="manual.html#table">table</A><BR> | |
| 353 | −<A HREF="manual.html#tag">tag</A><BR> | |
| 354 | −<A HREF="manual.html#tag"><TT>tag</TT></A><BR> | |
| 355 | −<A HREF="manual.html#tag method">tag method</A><BR> | |
| 356 | −....... <A HREF="manual.html#add">add</A><BR> | |
| 357 | −....... <A HREF="manual.html#concatenation">concatenation</A><BR> | |
| 358 | −....... <A HREF="manual.html#div">div</A><BR> | |
| 359 | −....... <A HREF="manual.html#function">function</A><BR> | |
| 360 | −....... <A HREF="manual.html#gc">gc</A><BR> | |
| 361 | −....... <A HREF="manual.html#getglobal">getglobal</A><BR> | |
| 362 | −....... <A HREF="manual.html#gettable">gettable</A><BR> | |
| 363 | −....... <A HREF="manual.html#index">index</A><BR> | |
| 364 | −....... <A HREF="manual.html#lt">lt</A><BR> | |
| 365 | −....... <A HREF="manual.html#mul">mul</A><BR> | |
| 366 | −....... <A HREF="manual.html#pow">pow</A><BR> | |
| 367 | −....... <A HREF="manual.html#setglobal">setglobal</A><BR> | |
| 368 | −....... <A HREF="manual.html#settable">settable</A><BR> | |
| 369 | −....... <A HREF="manual.html#sub">sub</A><BR> | |
| 370 | −....... <A HREF="manual.html#unm">unm</A><BR> | |
| 371 | −<A HREF="manual.html#tan"><TT>tan</TT></A><BR> | |
| 372 | −<A HREF="manual.html#tinsert"><TT>tinsert</TT></A><BR> | |
| 373 | −<A HREF="manual.html#tmpname"><TT>tmpname</TT></A><BR> | |
| 374 | −<A HREF="manual.html#tokens">tokens</A><BR> | |
| 375 | −<A HREF="manual.html#tonumber"><TT>tonumber</TT></A><BR> | |
| 376 | −<A HREF="manual.html#tostring"><TT>tostring</TT></A><BR> | |
| 377 | −<A HREF="manual.html#tremove"><TT>tremove</TT></A><BR> | |
| 378 | −<A HREF="manual.html#type"><TT>type</TT></A><BR> | |
| 379 | −<A HREF="manual.html#Types and Tags">types and tags</A><BR> | |
| 380 | − | |
| 381 | − <P> | |
| 382 | − | |
| 383 | −<A HREF="manual.html#unm event">``unm'' event</A><BR> | |
| 384 | −<A HREF="manual.html#upvalues">upvalues</A><BR> | |
| 385 | −<A HREF="manual.html#userdata">userdata</A><BR> | |
| 386 | − | |
| 387 | − <P> | |
| 388 | − | |
| 389 | −<A HREF="manual.html#valid index">valid index</A><BR> | |
| 390 | −<A HREF="manual.html#vararg function">vararg function</A><BR> | |
| 391 | −<A HREF="manual.html#version 3.2">version 3.2</A><BR> | |
| 392 | −<A HREF="manual.html#visibility">visibility</A><BR> | |
| 393 | − | |
| 394 | − <P> | |
| 395 | − | |
| 396 | −<A HREF="manual.html#while-do statement">while-do statement</A><BR> | |
| 397 | −<A HREF="manual.html#write"><TT>write</TT></A><BR> | |
| 398 | −<A HREF="manual.html#writeto"><TT>writeto</TT></A><BR> | |
| 399 | − | |
| 400 | − <P> | |
| 401 | − | |
| 402 | − | |
| 403 | −<HR> | |
| 404 | −<SMALL> | |
| 405 | −Last update: | |
| 406 | −Mon Nov 6 17:35:51 EDT 2000 | |
| 407 | −by <A HREF="http://www.tecgraf.puc-rio.br/~lhf/">lhf</A>. | |
| 408 | −</SMALL> | |
| 409 | − | |
| 410 | −</BODY> | |
| 411 | −</HTML> | |
| @@ -1,93 +0,0 @@ | ||
| 1 | −<HTML> | |
| 2 | −<HEAD> | |
| 3 | −<TITLE>Lua: reference manual - contents</TITLE> | |
| 4 | −</HEAD> | |
| 5 | − | |
| 6 | −<BODY BGCOLOR="#FFFFFF"> | |
| 7 | − | |
| 8 | −<HR> | |
| 9 | −<H1> | |
| 10 | −<IMG SRC="logo.gif" ALT="Lua" ALIGN="bottom"> | |
| 11 | −Reference manual | |
| 12 | −</H1> | |
| 13 | − | |
| 14 | −<A HREF="manual.html"> | |
| 15 | −Reference Manual of the Programming Language | |
| 16 | −<A HREF="http://www.tecgraf.puc-rio.br/lua/">Lua</A> | |
| 17 | −4.0</A> | |
| 18 | −[ | |
| 19 | −<A HREF="manual.html">top</A> | |
| 20 | −| | |
| 21 | −<A HREF="idx.html">index</A> | |
| 22 | −| | |
| 23 | −<A HREF="ftp://ftp.tecgraf.puc-rio.br/pub/lua/refman.ps.gz">ps</A> | |
| 24 | −| | |
| 25 | −<A HREF="ftp://ftp.tecgraf.puc-rio.br/pub/lua/refman.pdf">pdf</A> | |
| 26 | −| | |
| 27 | −<A HREF="old/">old versions</A> | |
| 28 | −] | |
| 29 | −<P> | |
| 30 | −<A NAME="contents"></A> | |
| 31 | −<UL> | |
| 32 | −<LI><A HREF="manual.html#1.">1 - Introduction</A> | |
| 33 | −<LI><A HREF="manual.html#2.">2 - Environment and Chunks</A> | |
| 34 | −<LI><A HREF="manual.html#3.">3 - Types and Tags</A> | |
| 35 | −<LI><A HREF="manual.html#4.">4 - The Language</A> | |
| 36 | − <UL> | |
| 37 | − <LI><A HREF="manual.html#4.1">4.1 - Lexical Conventions</A> | |
| 38 | − <LI><A HREF="manual.html#4.2">4.2 - Coercion</A> | |
| 39 | − <LI><A HREF="manual.html#4.3">4.3 - Adjustment</A> | |
| 40 | − <LI><A HREF="manual.html#4.4">4.4 - Statements</A> | |
| 41 | − <LI><A HREF="manual.html#4.5">4.5 - Expressions</A> | |
| 42 | − <LI><A HREF="manual.html#4.6">4.6 - Visibility and Upvalues</A> | |
| 43 | − <LI><A HREF="manual.html#4.7">4.7 - Error Handling</A> | |
| 44 | − <LI><A HREF="manual.html#4.8">4.8 - Tag Methods</A> | |
| 45 | − </UL> | |
| 46 | −<LI><A HREF="manual.html#5.">5 - The Application Program Interface</A> | |
| 47 | − <UL> | |
| 48 | − <LI><A HREF="manual.html#5.1">5.1 - States</A> | |
| 49 | − <LI><A HREF="manual.html#5.2">5.2 - The Stack and Indices</A> | |
| 50 | − <LI><A HREF="manual.html#5.3">5.3 - Stack Manipulation</A> | |
| 51 | − <LI><A HREF="manual.html#5.4">5.4 - Querying the Stack</A> | |
| 52 | − <LI><A HREF="manual.html#5.5">5.5 - Pushing values onto the Stack</A> | |
| 53 | − <LI><A HREF="manual.html#5.6">5.6 - Garbage Collection</A> | |
| 54 | − <LI><A HREF="manual.html#5.7">5.7 - Userdata and Tags</A> | |
| 55 | − <LI><A HREF="manual.html#5.8">5.8 - Executing Lua Code</A> | |
| 56 | − <LI><A HREF="manual.html#5.9">5.9 - Manipulating Global Variables in Lua</A> | |
| 57 | − <LI><A HREF="manual.html#5.10">5.10 - Manipulating Tables in Lua</A> | |
| 58 | − <LI><A HREF="manual.html#5.11">5.11 - Using Tables as Arrays</A> | |
| 59 | − <LI><A HREF="manual.html#5.12">5.12 - Calling Lua Functions</A> | |
| 60 | − <LI><A HREF="manual.html#5.13">5.13 - Defining C Functions</A> | |
| 61 | − <LI><A HREF="manual.html#5.14">5.14 - References to Lua Objects</A> | |
| 62 | − </UL> | |
| 63 | −<LI><A HREF="manual.html#6.">6 - Standard Libraries</A> | |
| 64 | − <UL> | |
| 65 | − <LI><A HREF="manual.html#6.1">6.1 - Basic Functions</A> | |
| 66 | − <LI><A HREF="manual.html#6.2">6.2 - String Manipulation</A> | |
| 67 | − <LI><A HREF="manual.html#6.3">6.3 - Mathematical Functions</A> | |
| 68 | − <LI><A HREF="manual.html#6.4">6.4 - I/O Facilities</A> | |
| 69 | − <LI><A HREF="manual.html#6.5">6.5 - System Facilities</A> | |
| 70 | − </UL> | |
| 71 | −<LI><A HREF="manual.html#7.">7 - The Debug Interface</A> | |
| 72 | − <UL> | |
| 73 | − <LI><A HREF="manual.html#7.1">7.1 - Stack and Function Information</A> | |
| 74 | − <LI><A HREF="manual.html#7.2">7.2 - Manipulating Local Variables</A> | |
| 75 | − <LI><A HREF="manual.html#7.3">7.3 - Hooks</A> | |
| 76 | − <LI><A HREF="manual.html#7.4">7.4 - The Reflexive Debug Interface</A> | |
| 77 | − </UL> | |
| 78 | −<LI><A HREF="manual.html#8.">8 - Lua Stand-alone</A> | |
| 79 | −<LI><A HREF="manual.html#Acknowledgments">Acknowledgments</A> | |
| 80 | −<LI><A HREF="manual.html#Incompatibilities">Incompatibilities with Previous Versions</A> | |
| 81 | −<LI><A HREF="manual.html#BNF">The Complete Syntax of Lua</A> | |
| 82 | −<LI><A HREF="idx.html">Index</A> | |
| 83 | −</UL> | |
| 84 | − | |
| 85 | −<HR> | |
| 86 | −<SMALL> | |
| 87 | −Last update: | |
| 88 | −Mon Nov 6 17:36:08 EDT 2000 | |
| 89 | −by <A HREF="http://www.tecgraf.puc-rio.br/~lhf/">lhf</A>. | |
| 90 | −</SMALL> | |
| 91 | − | |
| 92 | −</BODY> | |
| 93 | −</HTML> | |
Binary file not shown.
| @@ -1,137 +1,161 @@ | ||
| 1 | −.\" lua.man,v 1.3 2000/09/04 21:41:28 lhf Exp | |
| 2 | −.TH LUA 1 "2000/09/04 21:41:28" | |
| 1 | +.\" lua.man,v 1.8 2003/04/02 00:05:20 lhf Exp | |
| 2 | +.TH LUA 1 "2003/04/02 00:05:20" | |
| 3 | 3 | .SH NAME |
| 4 | 4 | lua \- Lua interpreter |
| 5 | 5 | .SH SYNOPSIS |
| 6 | 6 | .B lua |
| 7 | 7 | [ |
| 8 | −.I arguments | |
| 8 | +.I options | |
| 9 | +] | |
| 10 | +[ | |
| 11 | +.I script | |
| 12 | +[ | |
| 13 | +.I args | |
| 14 | +] | |
| 9 | 15 | ] |
| 10 | 16 | .SH DESCRIPTION |
| 11 | 17 | .B lua |
| 12 | 18 | is the stand-alone Lua interpreter. |
| 13 | 19 | It loads and executes Lua programs, |
| 14 | 20 | either in textual source form or |
| 15 | −in precompiled binary form, | |
| 16 | −as output by | |
| 21 | +in precompiled binary form. | |
| 22 | +(Precompiled binaries are output by | |
| 17 | 23 | .BR luac , |
| 18 | −the Lua compiler. | |
| 24 | +the Lua compiler.) | |
| 19 | 25 | .B lua |
| 20 | 26 | can be used as a batch interpreter and also interactively. |
| 21 | 27 | .LP |
| 22 | −The | |
| 23 | −.I arguments | |
| 24 | −can be options, assignments, or filenames, | |
| 25 | −and are processed in order, | |
| 26 | −from left to right. | |
| 28 | +The given | |
| 29 | +.I options | |
| 30 | +(see below) | |
| 31 | +are executed and then | |
| 32 | +the Lua program in file | |
| 33 | +.I script | |
| 34 | +is loaded and executed. | |
| 35 | +The given | |
| 36 | +.I args | |
| 37 | +are available to | |
| 38 | +.I script | |
| 39 | +as strings in a global table named | |
| 40 | +.BR arg . | |
| 41 | +If these arguments contain spaces or other characters special to the shell, | |
| 42 | +then they should be quoted | |
| 43 | +(but note that the quotes will be removed by the shell). | |
| 44 | +The arguments in | |
| 45 | +.B arg | |
| 46 | +start at 0, | |
| 47 | +which contains the string | |
| 48 | +.RI ` script '. | |
| 49 | +The index of the last argument is stored in | |
| 50 | +.BR "arg.n" . | |
| 51 | +The arguments given in the command line before | |
| 52 | +.IR script , | |
| 53 | +including the name of the interpreter, | |
| 54 | +are available in negative indices in | |
| 55 | +.BR arg . | |
| 56 | +.LP | |
| 57 | +At the very start, | |
| 58 | +before even handling the command line, | |
| 59 | +.B lua | |
| 60 | +executes the contents of the environment variable | |
| 61 | +.BR LUA_INIT , | |
| 62 | +if it is defined. | |
| 63 | +If the value of | |
| 64 | +.B LUA_INIT | |
| 65 | +is of the form | |
| 66 | +.RI `@ filename ', | |
| 67 | +then | |
| 68 | +.I filename | |
| 69 | +is executed. | |
| 70 | +Otherwise, the string is assumed to be a Lua statement and is executed. | |
| 27 | 71 | .LP |
| 28 | 72 | Options start with |
| 29 | 73 | .B \- |
| 30 | 74 | and are described below. |
| 31 | −.LP | |
| 32 | −An assignment is an argument of the form | |
| 33 | −.BR a=b , | |
| 34 | −which assigns the string | |
| 35 | −.RB ` b ' | |
| 36 | −to the global variable | |
| 37 | −.BR a . | |
| 38 | −Note that no quotes are needed around the string if it does not contain spaces | |
| 39 | −or other characters special to the shell. | |
| 40 | −This is for convenience only. | |
| 41 | −(In general, | |
| 42 | −you should be careful when using quotes and spaces on the command line | |
| 43 | −because they are usually handled by the shell.) | |
| 44 | −.LP | |
| 45 | −If the argument is neither an option nor an assignment, | |
| 46 | −then it is assumed to be a filename, | |
| 47 | −which is then loaded and executed. | |
| 75 | +You can use | |
| 76 | +.B "\--" | |
| 77 | +to signal the end of options. | |
| 48 | 78 | .LP |
| 49 | 79 | If no arguments are given, |
| 50 | 80 | then |
| 51 | 81 | .B "\-v \-i" |
| 52 | 82 | is assumed when the standard input is a terminal; |
| 53 | 83 | otherwise, |
| 54 | −.B \- | |
| 84 | +.B "\-" | |
| 55 | 85 | is assumed. |
| 86 | +.LP | |
| 87 | +In interactive mode, | |
| 88 | +.B lua | |
| 89 | +prompts the user, | |
| 90 | +reads lines from the standard input, | |
| 91 | +and executes them as they are read. | |
| 92 | +If a line does not contain a complete statement, | |
| 93 | +then a secondary prompt is displayed and | |
| 94 | +lines are read until a complete statement is formed or | |
| 95 | +a syntax error is found. | |
| 96 | +So, one way to interrupt the reading of an incomplete statement is | |
| 97 | +to force a syntax error: | |
| 98 | +adding a | |
| 99 | +.B `;' | |
| 100 | +in the middle of a statement is a sure way of forcing a syntax error | |
| 101 | +(except inside multiline strings and comments; these must be closed explicitly). | |
| 102 | +If a line starts with | |
| 103 | +.BR `=' , | |
| 104 | +then | |
| 105 | +.B lua | |
| 106 | +displays the values of all the expressions in the remainder of the | |
| 107 | +line. The expressions must be separated by commas. | |
| 108 | +The primary prompt is the value of the global variable | |
| 109 | +.BR _PROMPT , | |
| 110 | +if this value is a string; | |
| 111 | +otherwise, the default prompt is used. | |
| 112 | +Similarly, the secondary prompt is the value of the global variable | |
| 113 | +.BR _PROMPT2 . | |
| 114 | +So, | |
| 115 | +to change the prompts, | |
| 116 | +set the corresponding variable to a string of your choice. | |
| 117 | +You can do that after calling the interpreter | |
| 118 | +or on the command line with | |
| 119 | +.BR "_PROMPT" "=\'lua: \'" , | |
| 120 | +for example. | |
| 121 | +(Note the need for quotes, because the string contains a space.) | |
| 122 | +The default prompts are ``> '' and ``>> ''. | |
| 56 | 123 | .SH OPTIONS |
| 57 | 124 | .TP |
| 58 | 125 | .B \- |
| 59 | −load the standard input as a file, | |
| 126 | +load and execute the standard input as a file, | |
| 60 | 127 | that is, |
| 61 | 128 | not interactively, |
| 62 | 129 | even when the standard input is a terminal. |
| 63 | 130 | .TP |
| 64 | −.B \-c | |
| 65 | −close Lua before exiting. | |
| 66 | −.TP | |
| 67 | 131 | .BI \-e " stat" |
| 68 | 132 | execute statement |
| 69 | 133 | .IR stat . |
| 70 | −You will need to quote | |
| 134 | +You need to quote | |
| 71 | 135 | .I stat |
| 72 | −if it contains spaces or quotes. | |
| 73 | −.TP | |
| 74 | −.BI \-f " file" | |
| 75 | −collect all remaining arguments as strings into a global table named | |
| 76 | −.B arg | |
| 77 | −and then execute | |
| 78 | −.IR file . | |
| 79 | −The arguments in | |
| 80 | −.B arg | |
| 81 | −start at 0, | |
| 82 | −which contains the string | |
| 83 | −.RI ` file '. | |
| 84 | −The index of the last argument is stored in | |
| 85 | −.BR "arg.n" . | |
| 136 | +if it contains spaces, quotes, | |
| 137 | +or other characters special to the shell. | |
| 86 | 138 | .TP |
| 87 | 139 | .B \-i |
| 88 | −enter interactive mode, | |
| 89 | −displaying a prompt. | |
| 90 | −In this mode, | |
| 91 | −.B lua | |
| 92 | −reads lines from the standard input and executes them as they are read. | |
| 93 | −Each line must contain a complete statement. | |
| 94 | −To span a statement across several lines, end each line with a backslash | |
| 95 | −.BR `\e' . | |
| 96 | −The prompt shown is the value of the global variable | |
| 97 | −.BR _PROMPT , | |
| 98 | −if this value is a string. | |
| 99 | −So, | |
| 100 | −to change the prompt, | |
| 101 | −set | |
| 102 | −.B _PROMPT | |
| 103 | −to a string of your choice. | |
| 104 | −You can do that after calling the interpreter | |
| 105 | −or on the command line with | |
| 106 | −.BR "_PROMPT=\'lua: \'" , | |
| 107 | −for example. | |
| 108 | −(Note the need for quotes, because the string contains a space.) | |
| 109 | −The default prompt is ``> ''. | |
| 110 | −.TP | |
| 111 | −.B \-q | |
| 112 | −enter interactive mode, | |
| 113 | −but without displaying a prompt. | |
| 140 | +enter interactive mode after | |
| 141 | +.I script | |
| 142 | +is executed. | |
| 114 | 143 | .TP |
| 115 | −.BI \-s n | |
| 116 | −set the stack size to | |
| 117 | −.IB n . | |
| 118 | −If present, | |
| 119 | −this must be the first option. | |
| 120 | −Note that | |
| 121 | −.I n | |
| 122 | −is in the same argument as | |
| 123 | −.BR -s . | |
| 124 | −For example, | |
| 125 | −to specify a stack size of 2000, | |
| 126 | −use | |
| 127 | −.BR -s2000 . | |
| 144 | +.BI \-l " file" | |
| 145 | +call | |
| 146 | +.BI require( file ) | |
| 147 | +before executing | |
| 148 | +.IR script. | |
| 149 | +Typically used to load libraries | |
| 150 | +(hence the letter | |
| 151 | +.IR l ). | |
| 128 | 152 | .TP |
| 129 | 153 | .B \-v |
| 130 | −print version information. | |
| 154 | +show version information. | |
| 131 | 155 | .SH "SEE ALSO" |
| 132 | 156 | .BR luac (1) |
| 133 | 157 | .br |
| 134 | −http://www.tecgraf.puc-rio.br/lua/ | |
| 158 | +http://www.lua.org/ | |
| 135 | 159 | .SH DIAGNOSTICS |
| 136 | 160 | Error messages should be self explanatory. |
| 137 | 161 | .SH AUTHORS |
| @@ -1,4 +1,4 @@ | ||
| 1 | −<!-- lua.man,v 1.3 2000/09/04 21:41:28 lhf Exp --> | |
| 1 | +<!-- lua.man,v 1.8 2003/04/02 00:05:20 lhf Exp --> | |
| 2 | 2 | <HTML> |
| 3 | 3 | <HEAD> |
| 4 | 4 | <TITLE>LUA man page</TITLE> |
| @@ -11,133 +11,157 @@ lua - Lua interpreter · 6 unmodified lines | ||
| 11 | 11 | <H1>SYNOPSIS</H1> |
| 12 | 12 | <B>lua</B> |
| 13 | 13 | [ |
| 14 | −<I>arguments</I> | |
| 14 | +<I>options</I> | |
| 15 | +] | |
| 16 | +[ | |
| 17 | +<I>script</I> | |
| 18 | +[ | |
| 19 | +<I>args</I> | |
| 20 | +] | |
| 15 | 21 | ] |
| 16 | 22 | <H1>DESCRIPTION</H1> |
| 17 | 23 | <B>lua</B> |
| 18 | 24 | is the stand-alone Lua interpreter. |
| 19 | 25 | It loads and executes Lua programs, |
| 20 | 26 | either in textual source form or |
| 21 | −in precompiled binary form, | |
| 22 | −as output by | |
| 27 | +in precompiled binary form. | |
| 28 | +(Precompiled binaries are output by | |
| 23 | 29 | <B>luac</B>, |
| 24 | −the Lua compiler. | |
| 30 | +the Lua compiler.) | |
| 25 | 31 | <B>lua</B> |
| 26 | 32 | can be used as a batch interpreter and also interactively. |
| 27 | 33 | <P> |
| 28 | −The | |
| 29 | −<I>arguments</I> | |
| 30 | −can be options, assignments, or filenames, | |
| 31 | −and are processed in order, | |
| 32 | −from left to right. | |
| 34 | +The given | |
| 35 | +<I>options</I> | |
| 36 | +(see below) | |
| 37 | +are executed and then | |
| 38 | +the Lua program in file | |
| 39 | +<I>script</I> | |
| 40 | +is loaded and executed. | |
| 41 | +The given | |
| 42 | +<I>args</I> | |
| 43 | +are available to | |
| 44 | +<I>script</I> | |
| 45 | +as strings in a global table named | |
| 46 | +<B>arg</B>. | |
| 47 | +If these arguments contain spaces or other characters special to the shell, | |
| 48 | +then they should be quoted | |
| 49 | +(but note that the quotes will be removed by the shell). | |
| 50 | +The arguments in | |
| 51 | +<B>arg</B> | |
| 52 | +start at 0, | |
| 53 | +which contains the string | |
| 54 | +`<I>script</I>'. | |
| 55 | +The index of the last argument is stored in | |
| 56 | +<B>"arg.n"</B>. | |
| 57 | +The arguments given in the command line before | |
| 58 | +<I>script</I>, | |
| 59 | +including the name of the interpreter, | |
| 60 | +are available in negative indices in | |
| 61 | +<B>arg</B>. | |
| 62 | +<P> | |
| 63 | +At the very start, | |
| 64 | +before even handling the command line, | |
| 65 | +<B>lua</B> | |
| 66 | +executes the contents of the environment variable | |
| 67 | +<B>LUA_INIT</B>, | |
| 68 | +if it is defined. | |
| 69 | +If the value of | |
| 70 | +<B>LUA_INIT</B> | |
| 71 | +is of the form | |
| 72 | +`@<I>filename</I>', | |
| 73 | +then | |
| 74 | +<I>filename</I> | |
| 75 | +is executed. | |
| 76 | +Otherwise, the string is assumed to be a Lua statement and is executed. | |
| 33 | 77 | <P> |
| 34 | 78 | Options start with |
| 35 | 79 | <B>-</B> |
| 36 | 80 | and are described below. |
| 37 | −<P> | |
| 38 | −An assignment is an argument of the form | |
| 39 | −<B>a=b</B>, | |
| 40 | −which assigns the string | |
| 41 | −.RB ` b ' | |
| 42 | −to the global variable | |
| 43 | −<B>a</B>. | |
| 44 | −Note that no quotes are needed around the string if it does not contain spaces | |
| 45 | −or other characters special to the shell. | |
| 46 | −This is for convenience only. | |
| 47 | −(In general, | |
| 48 | −you should be careful when using quotes and spaces on the command line | |
| 49 | −because they are usually handled by the shell.) | |
| 50 | −<P> | |
| 51 | −If the argument is neither an option nor an assignment, | |
| 52 | −then it is assumed to be a filename, | |
| 53 | −which is then loaded and executed. | |
| 81 | +You can use | |
| 82 | +<B>"--"</B> | |
| 83 | +to signal the end of options. | |
| 54 | 84 | <P> |
| 55 | 85 | If no arguments are given, |
| 56 | 86 | then |
| 57 | 87 | <B>"-v -i"</B> |
| 58 | 88 | is assumed when the standard input is a terminal; |
| 59 | 89 | otherwise, |
| 60 | −<B>-</B> | |
| 90 | +<B>"-"</B> | |
| 61 | 91 | is assumed. |
| 92 | +<P> | |
| 93 | +In interactive mode, | |
| 94 | +<B>lua</B> | |
| 95 | +prompts the user, | |
| 96 | +reads lines from the standard input, | |
| 97 | +and executes them as they are read. | |
| 98 | +If a line does not contain a complete statement, | |
| 99 | +then a secondary prompt is displayed and | |
| 100 | +lines are read until a complete statement is formed or | |
| 101 | +a syntax error is found. | |
| 102 | +So, one way to interrupt the reading of an incomplete statement is | |
| 103 | +to force a syntax error: | |
| 104 | +adding a | |
| 105 | +<B>`;' </B> | |
| 106 | +in the middle of a statement is a sure way of forcing a syntax error | |
| 107 | +(except inside multiline strings and comments; these must be closed explicitly). | |
| 108 | +If a line starts with | |
| 109 | +<B>`='</B>, | |
| 110 | +then | |
| 111 | +<B>lua</B> | |
| 112 | +displays the values of all the expressions in the remainder of the | |
| 113 | +line. The expressions must be separated by commas. | |
| 114 | +The primary prompt is the value of the global variable | |
| 115 | +<B>_PROMPT</B>, | |
| 116 | +if this value is a string; | |
| 117 | +otherwise, the default prompt is used. | |
| 118 | +Similarly, the secondary prompt is the value of the global variable | |
| 119 | +<B>_PROMPT2</B>. | |
| 120 | +So, | |
| 121 | +to change the prompts, | |
| 122 | +set the corresponding variable to a string of your choice. | |
| 123 | +You can do that after calling the interpreter | |
| 124 | +or on the command line with | |
| 125 | +<B>"_PROMPT" "=\'lua: \'"</B>, | |
| 126 | +for example. | |
| 127 | +(Note the need for quotes, because the string contains a space.) | |
| 128 | +The default prompts are ``> '' and ``>> ''. | |
| 62 | 129 | <H1>OPTIONS</H1> |
| 63 | 130 | <P> |
| 64 | 131 | <B>-</B> |
| 65 | −load the standard input as a file, | |
| 132 | +load and execute the standard input as a file, | |
| 66 | 133 | that is, |
| 67 | 134 | not interactively, |
| 68 | 135 | even when the standard input is a terminal. |
| 69 | 136 | <P> |
| 70 | −<B>-c</B> | |
| 71 | −close Lua before exiting. | |
| 72 | −<P> | |
| 73 | 137 | <B>-e "</B><I>stat"</I> |
| 74 | 138 | execute statement |
| 75 | 139 | <I>stat</I>. |
| 76 | −You will need to quote | |
| 140 | +You need to quote | |
| 77 | 141 | <I>stat </I> |
| 78 | −if it contains spaces or quotes. | |
| 79 | −<P> | |
| 80 | −<B>-f "</B><I>file"</I> | |
| 81 | −collect all remaining arguments as strings into a global table named | |
| 82 | −<B>arg</B> | |
| 83 | −and then execute | |
| 84 | −<I>file</I>. | |
| 85 | −The arguments in | |
| 86 | −<B>arg</B> | |
| 87 | −start at 0, | |
| 88 | −which contains the string | |
| 89 | −.RI ` file '. | |
| 90 | −The index of the last argument is stored in | |
| 91 | −<B>"arg.n"</B>. | |
| 142 | +if it contains spaces, quotes, | |
| 143 | +or other characters special to the shell. | |
| 92 | 144 | <P> |
| 93 | 145 | <B>-i</B> |
| 94 | −enter interactive mode, | |
| 95 | −displaying a prompt. | |
| 96 | −In this mode, | |
| 97 | −<B>lua</B> | |
| 98 | −reads lines from the standard input and executes them as they are read. | |
| 99 | −Each line must contain a complete statement. | |
| 100 | −To span a statement across several lines, end each line with a backslash | |
| 101 | −<B>`\e'</B>. | |
| 102 | −The prompt shown is the value of the global variable | |
| 103 | −<B>_PROMPT</B>, | |
| 104 | −if this value is a string. | |
| 105 | −So, | |
| 106 | −to change the prompt, | |
| 107 | −set | |
| 108 | −<B>_PROMPT</B> | |
| 109 | −to a string of your choice. | |
| 110 | −You can do that after calling the interpreter | |
| 111 | −or on the command line with | |
| 112 | −<B>"_PROMPT=\'lua: \'"</B>, | |
| 113 | −for example. | |
| 114 | −(Note the need for quotes, because the string contains a space.) | |
| 115 | −The default prompt is ``> ''. | |
| 116 | −<P> | |
| 117 | −<B>-q</B> | |
| 118 | −enter interactive mode, | |
| 119 | −but without displaying a prompt. | |
| 146 | +enter interactive mode after | |
| 147 | +<I>script</I> | |
| 148 | +is executed. | |
| 120 | 149 | <P> |
| 121 | −<B>-s</B><I>n</I> | |
| 122 | −set the stack size to | |
| 123 | −.IB n . | |
| 124 | −If present, | |
| 125 | −this must be the first option. | |
| 126 | −Note that | |
| 127 | −<I>n</I> | |
| 128 | −is in the same argument as | |
| 129 | −<B>-s</B>. | |
| 130 | −For example, | |
| 131 | −to specify a stack size of 2000, | |
| 132 | −use | |
| 133 | −<B>-s2000</B>. | |
| 150 | +<B>-l "</B><I>file"</I> | |
| 151 | +call | |
| 152 | +<B>require( file</B><I>)</I> | |
| 153 | +before executing | |
| 154 | +<I></I>script. | |
| 155 | +Typically used to load libraries | |
| 156 | +(hence the letter | |
| 157 | +<I>l</I>). | |
| 134 | 158 | <P> |
| 135 | 159 | <B>-v</B> |
| 136 | −print version information. | |
| 160 | +show version information. | |
| 137 | 161 | <H1>SEE ALSO</H1> |
| 138 | 162 | <B>luac</B>(1) |
| 139 | 163 | <BR> |
| 140 | −<A HREF="http://www.tecgraf.puc-rio.br/lua/">http://www.tecgraf.puc-rio.br/lua/</A> | |
| 164 | +<A HREF="http://www.lua.org/">http://www.lua.org/</A> | |
| 141 | 165 | <H1>DIAGNOSTICS</H1> |
| 142 | 166 | Error messages should be self explanatory. |
| 143 | 167 | <H1>AUTHORS</H1> |
| @@ -145,7 +169,7 @@ R. Ierusalimschy, · 1 unmodified line | ||
| 145 | 169 | L. H. de Figueiredo, |
| 146 | 170 | and |
| 147 | 171 | W. Celes |
| 148 | −(<A HREF="mailto:lua@tecgraf.puc-rio.br">lua@tecgraf.puc-rio.br</A>) | |
| 172 | +(<A HREF="mailto:lua-NO-SPAM-THANKS@tecgraf.puc-rio.br">lua AT tecgraf.puc-rio.br</A>) | |
| 149 | 173 | <!-- EOF --> |
| 150 | 174 | </BODY> |
| 151 | 175 | </HTML> |
| @@ -1,5 +1,5 @@ | ||
| 1 | −.\" luac.man,v 1.20 2000/10/06 15:11:21 lhf Exp | |
| 2 | −.TH LUAC 1 "2000/10/06 15:11:21" | |
| 1 | +.\" luac.man,v 1.25 2002/12/13 11:45:12 lhf Exp | |
| 2 | +.TH LUAC 1 "2002/12/13 11:45:12" | |
| 3 | 3 | .SH NAME |
| 4 | 4 | luac \- Lua compiler |
| 5 | 5 | .SH SYNOPSIS |
| @@ -13,17 +13,13 @@ luac \- Lua compiler · 7 unmodified lines | ||
| 13 | 13 | .B luac |
| 14 | 14 | is the Lua compiler. |
| 15 | 15 | It translates programs written in the Lua programming language |
| 16 | −into binary files that can be loaded and executed with | |
| 17 | −.B lua_dofile | |
| 18 | −in C or with | |
| 19 | −.B dofile | |
| 20 | −in Lua. | |
| 16 | +into binary files that can be latter loaded and executed. | |
| 21 | 17 | .LP |
| 22 | 18 | The main advantages of precompiling chunks are: |
| 23 | 19 | faster loading, |
| 24 | 20 | protecting source code from user changes, |
| 25 | 21 | and |
| 26 | −off-line syntax error detection. | |
| 22 | +off-line syntax checking. | |
| 27 | 23 | .LP |
| 28 | 24 | Pre-compiling does not imply faster execution |
| 29 | 25 | because in Lua chunks are always compiled into bytecodes before being executed. |
| @@ -46,9 +42,10 @@ are portable to all architectures with the same word size. · 16 unmodified lines | ||
| 46 | 42 | This means that |
| 47 | 43 | binary files created on a 32-bit platform (such as Intel) |
| 48 | 44 | can be read without change in another 32-bit platform (such as Sparc), |
| 49 | −even if the byte order (``endianess'') is different. | |
| 45 | +even if the byte order (``endianness'') is different. | |
| 50 | 46 | On the other hand, |
| 51 | −binary files created on a 16-bit platform cannot be read in a 32-bit platform. | |
| 47 | +binary files created on a 16-bit platform cannot be read in a 32-bit platform, | |
| 48 | +nor vice-versa. | |
| 52 | 49 | .LP |
| 53 | 50 | In the command line, |
| 54 | 51 | you can mix |
| @@ -60,15 +57,17 @@ into a single precompiled chunk. · 5 unmodified lines | ||
| 60 | 57 | .LP |
| 61 | 58 | You can use |
| 62 | 59 | .B "\-" |
| 63 | −to indicate | |
| 64 | −.I stdin | |
| 65 | −as a source file. | |
| 60 | +to indicate the standard input as a source file | |
| 61 | +and | |
| 62 | +.B "\--" | |
| 63 | +to signal the end of options | |
| 64 | +(that is, | |
| 65 | +all remaining arguments will be treated as files even if they start with | |
| 66 | +.BR "\-" ). | |
| 66 | 67 | .LP |
| 67 | 68 | The internal format of the binary files produced by |
| 68 | 69 | .B luac |
| 69 | −may change when a new version of Lua is released. | |
| 70 | −We try to maintain compatibility even for binary files, | |
| 71 | −but it is not always possible. | |
| 70 | +is likely to change when a new version of Lua is released. | |
| 72 | 71 | So, |
| 73 | 72 | save the source files of all Lua programs that you precompile. |
| 74 | 73 | .LP |
| @@ -89,26 +88,16 @@ output to · 14 unmodified lines | ||
| 89 | 88 | .IR file , |
| 90 | 89 | instead of the default |
| 91 | 90 | .BR luac.out . |
| 92 | −The output file can be a source file because | |
| 91 | +The output file may be a source file because | |
| 93 | 92 | all files are loaded before the output file is written. |
| 93 | +Be careful not to overwrite precious files. | |
| 94 | 94 | .TP |
| 95 | 95 | .B \-p |
| 96 | 96 | load files but do not generate any output file. |
| 97 | −Used mainly for syntax checking or testing precompiled chunks: | |
| 97 | +Used mainly for syntax checking and for testing precompiled chunks: | |
| 98 | 98 | corrupted files will probably generate errors when loaded. |
| 99 | −For a thourough integrity test, | |
| 100 | −use | |
| 101 | −.BR \-t . | |
| 102 | −.TP | |
| 103 | −.B \-s | |
| 104 | −strip debug information before writing the output file. | |
| 105 | −This saves some space in very large chunks, | |
| 106 | −but if errors occur when running these chunks, | |
| 107 | −then the error messages might not contain the full information they usually do. | |
| 108 | −.TP | |
| 109 | −.B \-t | |
| 110 | −perform a thourough integrity test of precompiled chunks. | |
| 111 | −Code that passes this test is completely safe, | |
| 99 | +Lua always performs a thorough integrity test on precompiled chunks. | |
| 100 | +Bytecode that passes this test is completely safe, | |
| 112 | 101 | in the sense that it will not break the interpreter. |
| 113 | 102 | However, |
| 114 | 103 | there is no guarantee that such code does anything sensible. |
| @@ -118,9 +107,17 @@ If no files are given, then · 3 unmodified lines | ||
| 118 | 107 | loads |
| 119 | 108 | .B luac.out |
| 120 | 109 | and tests its contents. |
| 110 | +No messages are displayed if the file passes the integrity test. | |
| 111 | +.TP | |
| 112 | +.B \-s | |
| 113 | +strip debug information before writing the output file. | |
| 114 | +This saves some space in very large chunks, | |
| 115 | +but if errors occur when running these chunks, | |
| 116 | +then the error messages may not contain the full information they usually do | |
| 117 | +(line numbers and names of locals are lost). | |
| 121 | 118 | .TP |
| 122 | 119 | .B \-v |
| 123 | −print version information. | |
| 120 | +show version information. | |
| 124 | 121 | .SH FILES |
| 125 | 122 | .TP 15 |
| 126 | 123 | .B luac.out |
| @@ -128,7 +125,7 @@ default output file · 1 unmodified line | ||
| 128 | 125 | .SH "SEE ALSO" |
| 129 | 126 | .BR lua (1) |
| 130 | 127 | .br |
| 131 | −http://www.tecgraf.puc-rio.br/lua/ | |
| 128 | +http://www.lua.org/ | |
| 132 | 129 | .SH DIAGNOSTICS |
| 133 | 130 | Error messages should be self explanatory. |
| 134 | 131 | .SH AUTHORS |
| @@ -1,4 +1,4 @@ | ||
| 1 | −<!-- luac.man,v 1.20 2000/10/06 15:11:21 lhf Exp --> | |
| 1 | +<!-- luac.man,v 1.25 2002/12/13 11:45:12 lhf Exp --> | |
| 2 | 2 | <HTML> |
| 3 | 3 | <HEAD> |
| 4 | 4 | <TITLE>LUAC man page</TITLE> |
| @@ -19,17 +19,13 @@ luac - Lua compiler · 14 unmodified lines | ||
| 19 | 19 | <B>luac</B> |
| 20 | 20 | is the Lua compiler. |
| 21 | 21 | It translates programs written in the Lua programming language |
| 22 | −into binary files that can be loaded and executed with | |
| 23 | −<B>lua_dofile</B> | |
| 24 | −in C or with | |
| 25 | −<B>dofile</B> | |
| 26 | −in Lua. | |
| 22 | +into binary files that can be latter loaded and executed. | |
| 27 | 23 | <P> |
| 28 | 24 | The main advantages of precompiling chunks are: |
| 29 | 25 | faster loading, |
| 30 | 26 | protecting source code from user changes, |
| 31 | 27 | and |
| 32 | −off-line syntax error detection. | |
| 28 | +off-line syntax checking. | |
| 33 | 29 | <P> |
| 34 | 30 | Pre-compiling does not imply faster execution |
| 35 | 31 | because in Lua chunks are always compiled into bytecodes before being executed. |
| @@ -52,9 +48,10 @@ are portable to all architectures with the same word size. · 16 unmodified lines | ||
| 52 | 48 | This means that |
| 53 | 49 | binary files created on a 32-bit platform (such as Intel) |
| 54 | 50 | can be read without change in another 32-bit platform (such as Sparc), |
| 55 | −even if the byte order (``endianess'') is different. | |
| 51 | +even if the byte order (``endianness'') is different. | |
| 56 | 52 | On the other hand, |
| 57 | −binary files created on a 16-bit platform cannot be read in a 32-bit platform. | |
| 53 | +binary files created on a 16-bit platform cannot be read in a 32-bit platform, | |
| 54 | +nor vice-versa. | |
| 58 | 55 | <P> |
| 59 | 56 | In the command line, |
| 60 | 57 | you can mix |
| @@ -66,15 +63,17 @@ into a single precompiled chunk. · 5 unmodified lines | ||
| 66 | 63 | <P> |
| 67 | 64 | You can use |
| 68 | 65 | <B>"-"</B> |
| 69 | −to indicate | |
| 70 | −<I>stdin</I> | |
| 71 | −as a source file. | |
| 66 | +to indicate the standard input as a source file | |
| 67 | +and | |
| 68 | +<B>"--"</B> | |
| 69 | +to signal the end of options | |
| 70 | +(that is, | |
| 71 | +all remaining arguments will be treated as files even if they start with | |
| 72 | +<B>"-"</B>). | |
| 72 | 73 | <P> |
| 73 | 74 | The internal format of the binary files produced by |
| 74 | 75 | <B>luac</B> |
| 75 | −may change when a new version of Lua is released. | |
| 76 | −We try to maintain compatibility even for binary files, | |
| 77 | −but it is not always possible. | |
| 76 | +is likely to change when a new version of Lua is released. | |
| 78 | 77 | So, |
| 79 | 78 | save the source files of all Lua programs that you precompile. |
| 80 | 79 | <P> |
| @@ -95,26 +94,16 @@ output to · 14 unmodified lines | ||
| 95 | 94 | <I>file</I>, |
| 96 | 95 | instead of the default |
| 97 | 96 | <B>luac.out</B>. |
| 98 | −The output file can be a source file because | |
| 97 | +The output file may be a source file because | |
| 99 | 98 | all files are loaded before the output file is written. |
| 99 | +Be careful not to overwrite precious files. | |
| 100 | 100 | <P> |
| 101 | 101 | <B>-p</B> |
| 102 | 102 | load files but do not generate any output file. |
| 103 | −Used mainly for syntax checking or testing precompiled chunks: | |
| 103 | +Used mainly for syntax checking and for testing precompiled chunks: | |
| 104 | 104 | corrupted files will probably generate errors when loaded. |
| 105 | −For a thourough integrity test, | |
| 106 | −use | |
| 107 | −<B>-t</B>. | |
| 108 | −<P> | |
| 109 | −<B>-s</B> | |
| 110 | −strip debug information before writing the output file. | |
| 111 | −This saves some space in very large chunks, | |
| 112 | −but if errors occur when running these chunks, | |
| 113 | −then the error messages might not contain the full information they usually do. | |
| 114 | −<P> | |
| 115 | −<B>-t</B> | |
| 116 | −perform a thourough integrity test of precompiled chunks. | |
| 117 | −Code that passes this test is completely safe, | |
| 105 | +Lua always performs a thorough integrity test on precompiled chunks. | |
| 106 | +Bytecode that passes this test is completely safe, | |
| 118 | 107 | in the sense that it will not break the interpreter. |
| 119 | 108 | However, |
| 120 | 109 | there is no guarantee that such code does anything sensible. |
| @@ -124,9 +113,17 @@ If no files are given, then · 3 unmodified lines | ||
| 124 | 113 | loads |
| 125 | 114 | <B>luac.out</B> |
| 126 | 115 | and tests its contents. |
| 116 | +No messages are displayed if the file passes the integrity test. | |
| 117 | +<P> | |
| 118 | +<B>-s</B> | |
| 119 | +strip debug information before writing the output file. | |
| 120 | +This saves some space in very large chunks, | |
| 121 | +but if errors occur when running these chunks, | |
| 122 | +then the error messages may not contain the full information they usually do | |
| 123 | +(line numbers and names of locals are lost). | |
| 127 | 124 | <P> |
| 128 | 125 | <B>-v</B> |
| 129 | −print version information. | |
| 126 | +show version information. | |
| 130 | 127 | <H1>FILES</H1> |
| 131 | 128 | <P> |
| 132 | 129 | <B>luac.out</B> |
| @@ -134,14 +131,14 @@ default output file · 1 unmodified line | ||
| 134 | 131 | <H1>SEE ALSO</H1> |
| 135 | 132 | <B>lua</B>(1) |
| 136 | 133 | <BR> |
| 137 | −<A HREF="http://www.tecgraf.puc-rio.br/lua/">http://www.tecgraf.puc-rio.br/lua/</A> | |
| 134 | +<A HREF="http://www.lua.org/">http://www.lua.org/</A> | |
| 138 | 135 | <H1>DIAGNOSTICS</H1> |
| 139 | 136 | Error messages should be self explanatory. |
| 140 | 137 | <H1>AUTHORS</H1> |
| 141 | 138 | L. H. de Figueiredo, |
| 142 | 139 | R. Ierusalimschy and |
| 143 | 140 | W. Celes |
| 144 | −(<A HREF="mailto:lua@tecgraf.puc-rio.br">lua@tecgraf.puc-rio.br</A>) | |
| 141 | +(<A HREF="mailto:lua-NO-SPAM-THANKS@tecgraf.puc-rio.br">lua AT tecgraf.puc-rio.br</A>) | |
| 145 | 142 | <!-- EOF --> |
| 146 | 143 | </BODY> |
| 147 | 144 | </HTML> |
| @@ -1,948 +1,1025 @@ | ||
| 1 | −<HTML> | |
| 2 | −<HEAD> | |
| 3 | −<TITLE>Lua: reference manual 4.0</TITLE> | |
| 4 | −</HEAD> | |
| 5 | − | |
| 6 | −<BODY BGCOLOR="#FFFFFF"> | |
| 7 | − | |
| 8 | −<HR> | |
| 9 | −<H1> | |
| 10 | −<IMG SRC="logo.gif" ALT="Lua" ALIGN="bottom"> | |
| 11 | −Reference Manual of the Programming Language | |
| 12 | −<A HREF="http://www.tecgraf.puc-rio.br/lua/">Lua</A> | |
| 13 | −4.0 | |
| 14 | −</H1> | |
| 15 | − | |
| 16 | −<!-- $Id: manual.tex,v 1.45 2000/10/31 18:20:01 roberto Exp roberto $ --> | |
| 17 | −<P> | |
| 18 | −<P> | |
| 1 | +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> | |
| 2 | +<html> | |
| 3 | + | |
| 4 | +<head> | |
| 5 | +<title>Lua 5.0 Reference Manual</title> | |
| 6 | +</head> | |
| 7 | + | |
| 8 | +<body BGCOLOR="#FFFFFF"> | |
| 9 | + | |
| 10 | +<hr> | |
| 11 | +<h1> | |
| 12 | +<a HREF="http://www.lua.org/home.html"> | |
| 13 | +<img SRC="logo.gif" ALT="[Lua logo]" BORDER=0> | |
| 14 | +</a> | |
| 15 | +Lua 5.0 Reference Manual | |
| 16 | +</h1> | |
| 17 | + | |
| 18 | +by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes | |
| 19 | +<p> | |
| 20 | +<small> | |
| 21 | +<a HREF="http://www.lua.org/copyright.html">Copyright</a> | |
| 22 | +© 2003 TeCGraf, PUC-Rio. All rights reserved. | |
| 23 | +</small> | |
| 24 | +<hr> | |
| 25 | + | |
| 26 | +<p> | |
| 27 | +<p> | |
| 19 | 28 | <!-- ====================================================================== --> |
| 20 | −<HR> | |
| 21 | −<A NAME="1."></A> | |
| 22 | −<H1>1 - Introduction</H1> | |
| 23 | −<P> | |
| 24 | −Lua is an extension programming language designed to support | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | +<h1>1 - Introduction</h1> | |
| 33 | + | |
| 34 | +<p>Lua is an extension programming language designed to support | |
| 25 | 35 | general procedural programming with data description |
| 26 | 36 | facilities. |
| 37 | +It also offers good suport for object-oriented programming, | |
| 38 | +functional programming, and data-driven programming. | |
| 27 | 39 | Lua is intended to be used as a powerful, light-weight |
| 28 | 40 | configuration language for any program that needs one. |
| 29 | −<P> | |
| 30 | −Lua is implemented as a library, written in C. | |
| 31 | −Being an extension language, Lua has no notion of a ``main'' program: | |
| 32 | −it only works <EM>embedded</EM> in a host client, | |
| 33 | −called the <EM>embedding</EM> program. | |
| 34 | −This host program can invoke functions to execute a piece of | |
| 35 | −code in Lua, can write and read Lua variables, | |
| 41 | +Lua is implemented as a library, written in <em>clean</em> C | |
| 42 | +(that is, in the common subset of ANSI C and C++). | |
| 43 | + | |
| 44 | +<p>Being an extension language, Lua has no notion of a "main" program: | |
| 45 | +it only works <em>embedded</em> in a host client, | |
| 46 | +called the <em>embedding program</em> or simply the <em>host</em>. | |
| 47 | +This host program can invoke functions to execute a piece of Lua code, | |
| 48 | +can write and read Lua variables, | |
| 36 | 49 | and can register C functions to be called by Lua code. |
| 37 | 50 | Through the use of C functions, Lua can be augmented to cope with |
| 38 | 51 | a wide range of different domains, |
| 39 | 52 | thus creating customized programming languages sharing a syntactical framework. |
| 40 | −<P> | |
| 41 | −Lua is free-distribution software, | |
| 53 | + | |
| 54 | +<p>The Lua distribuition includes a stand-alone embedding program, | |
| 55 | +<code>lua</code>, that uses the Lua library to offer a complete Lua interpreter. | |
| 56 | + | |
| 57 | +<p>Lua is free software, | |
| 42 | 58 | and is provided as usual with no guarantees, |
| 43 | 59 | as stated in its copyright notice. |
| 44 | 60 | The implementation described in this manual is available |
| 45 | −at the following URL's: | |
| 46 | −<PRE> | |
| 47 | − <A HREF="http://www.tecgraf.puc-rio.br/lua/">http://www.tecgraf.puc-rio.br/lua/</A> | |
| 48 | − <A HREF="ftp://ftp.tecgraf.puc-rio.br/pub/lua/">ftp://ftp.tecgraf.puc-rio.br/pub/lua/</A> | |
| 49 | −</PRE> | |
| 50 | −<P> | |
| 51 | −Like any other reference manual, | |
| 61 | +at Lua's official web site, <code>www.lua.org</code>. | |
| 62 | + | |
| 63 | +<p>Like any other reference manual, | |
| 52 | 64 | this document is dry in places. |
| 53 | 65 | For a discussion of the decisions behind the design of Lua, |
| 54 | 66 | see the papers below, |
| 55 | −which are available at the web site above. | |
| 56 | −<UL> | |
| 57 | −<LI> | |
| 67 | +which are available at Lua's web site. | |
| 68 | +<ul> | |
| 69 | +<li> | |
| 58 | 70 | R. Ierusalimschy, L. H. de Figueiredo, and W. Celes. |
| 59 | −Lua-an extensible extension language. | |
| 60 | −<EM>Software: Practice & Experience</EM> <B>26</B> #6 (1996) 635--652. | |
| 61 | −<LI> | |
| 71 | +Lua---an extensible extension language. | |
| 72 | +<em>Software: Practice & Experience</em> <b>26</b> #6 (1996) 635-652. | |
| 73 | +<li> | |
| 62 | 74 | L. H. de Figueiredo, R. Ierusalimschy, and W. Celes. |
| 63 | 75 | The design and implementation of a language for extending applications. |
| 64 | −<EM>Proceedings of XXI Brazilian Seminar on Software and Hardware</EM> (1994) 273--283. | |
| 65 | −<LI> | |
| 76 | +<em>Proceedings of XXI Brazilian Seminar on Software and Hardware</em> (1994) 273-283. | |
| 77 | +<li> | |
| 66 | 78 | L. H. de Figueiredo, R. Ierusalimschy, and W. Celes. |
| 67 | 79 | Lua: an extensible embedded language. |
| 68 | −<EM>Dr. Dobb's Journal</EM> <B>21</B> #12 (Dec 1996) 26--33. | |
| 69 | −</UL> | |
| 70 | −<P> | |
| 71 | −<!-- ====================================================================== --> | |
| 72 | −<HR> | |
| 73 | −<A NAME="2."></A> | |
| 74 | −<H1>2 - Environment and Chunks</H1> | |
| 75 | −<P> | |
| 76 | −All statements in Lua are executed in a <A NAME="global environment"><EM>global environment</EM></A>. | |
| 77 | −This environment is initialized with a call from the embedding program to | |
| 78 | −<CODE>lua_open</CODE> and | |
| 79 | −persists until a call to <CODE>lua_close</CODE>, | |
| 80 | −or the end of the embedding program. | |
| 81 | −If necessary, | |
| 82 | −the host programmer can create multiple independent global | |
| 83 | −environments, and freely switch between them (see Section <A HREF="#mangstate">5.1</A>). | |
| 84 | −<P> | |
| 85 | −The global environment can be manipulated by Lua code or | |
| 86 | −by the embedding program, | |
| 87 | −which can read and write global variables | |
| 88 | −using API functions from the library that implements Lua. | |
| 89 | −<P> | |
| 90 | −<A NAME="Global variables">Global variables</A> in Lua do not need to be declared. | |
| 91 | −Any variable is assumed to be global unless explicitly declared local | |
| 92 | −(see Section <A HREF="#localvar">4.4.6</A>). | |
| 93 | −Before the first assignment, the value of a global variable is <B>nil</B> | |
| 94 | −(this default can be changed; see Section <A HREF="#tag-method">4.8</A>). | |
| 95 | −A table is used to keep all global names and values | |
| 96 | −(tables are explained in Section <A HREF="#TypesSec">3</A>). | |
| 97 | −<P> | |
| 98 | −The unit of execution of Lua is called a <A NAME="chunk"><EM>chunk</EM></A>. | |
| 99 | −A chunk is simply a sequence of statements, | |
| 100 | −which are executed sequentially. | |
| 101 | −Each statement can be optionally followed by a semicolon: | |
| 102 | −<PRE> | |
| 103 | − chunk ::= {stat [`<B>;</B>']} | |
| 104 | −</PRE> | |
| 105 | −Statements are described in Section <A HREF="#stats">4.4</A>. | |
| 106 | −(The notation above is the usual extended BNF, | |
| 80 | +<em>Dr. Dobb's Journal</em> <b>21</b> #12 (Dec 1996) 26-33. | |
| 81 | +<li> | |
| 82 | +R. Ierusalimschy, L. H. de Figueiredo, and W. Celes. | |
| 83 | +The evolution of an extension language: a history of Lua, | |
| 84 | +<em>Proceedings of V Brazilian Symposium on Programming Languages</em> (2001) B-14-B-28. | |
| 85 | +</ul> | |
| 86 | + | |
| 87 | +<p>Lua means "moon" in Portuguese and is pronounced LOO-ah. | |
| 88 | + | |
| 89 | +<p> | |
| 90 | +<a name="language"><h1>2 - The Language</h1></a> | |
| 91 | + | |
| 92 | +<p>This section describes the lexis, the syntax, and the semantics of Lua. | |
| 93 | +In other words, | |
| 94 | +this section describes | |
| 95 | +which tokens are valid, | |
| 96 | +how they can be combined, | |
| 97 | +and what their combinations mean. | |
| 98 | + | |
| 99 | +<p>The language constructs will be explained using the usual extended BNF, | |
| 107 | 100 | in which |
| 108 | −{<EM>a</EM>} means 0 or more <EM>a</EM>'s, | |
| 109 | −[<EM>a</EM>] means an optional <EM>a</EM>, and | |
| 110 | −(<EM>a</EM>)+ means one or more <EM>a</EM>'s. | |
| 111 | −The complete syntax of Lua is given in <A HREF="BNF">BNF</A>). | |
| 112 | −<P> | |
| 113 | −A chunk may be stored in a file or in a string inside the host program. | |
| 114 | −When a chunk is executed, first it is pre-compiled into bytecodes for | |
| 115 | −a virtual machine, and then the statements are executed in sequential order, | |
| 116 | −by simulating the virtual machine. | |
| 117 | −All modifications a chunk effects on the global environment persist | |
| 118 | −after the chunk ends. | |
| 119 | −<P> | |
| 120 | −Chunks may also be pre-compiled into binary form and stored in files; | |
| 121 | −see program <A NAME="luac"><TT><A HREF="luac.html">luac</A></TT></A> for details. | |
| 122 | −Text files with chunks and their binary pre-compiled forms | |
| 123 | −are interchangeable. | |
| 124 | −Lua automatically detects the file type and acts accordingly. | |
| 125 | −<A NAME="pre-compilation"></A> | |
| 126 | −<P> | |
| 127 | −<A NAME="TypesSec"></A> | |
| 128 | −<!-- ====================================================================== --> | |
| 129 | −<HR> | |
| 130 | −<A NAME="3."></A> | |
| 131 | −<H1>3 - Types and Tags</H1> | |
| 132 | −<P> | |
| 133 | −Lua is a <EM>dynamically typed language</EM>. | |
| 134 | −This means that | |
| 135 | −variables do not have types; only values do. | |
| 136 | −Therefore, there are no type definitions in the language. | |
| 137 | −All values carry their own type. | |
| 138 | −Besides a type, all values also have a <A NAME="tag"><EM>tag</EM></A>. | |
| 139 | −<P> | |
| 140 | −There are six <A NAME="basic types">basic types</A> in Lua: <A NAME="nil"><EM>nil</EM></A>, <A NAME="number"><EM>number</EM></A>, | |
| 141 | −<A NAME="string"><EM>string</EM></A>, <A NAME="function"><EM>function</EM></A>, <A NAME="userdata"><EM>userdata</EM></A>, and <A NAME="table"><EM>table</EM></A>. | |
| 142 | −<EM>Nil</EM> is the type of the value <B>nil</B>, | |
| 143 | −whose main property is to be different from any other value. | |
| 144 | −<EM>Number</EM> represents real (double-precision floating-point) numbers, | |
| 145 | −while <EM>string</EM> has the usual meaning. | |
| 146 | −<A NAME="eight-bit clean"></A> | |
| 147 | −Lua is 8-bit clean, | |
| 148 | −and so strings may contain any 8-bit character, | |
| 149 | −including embedded zeros (<CODE>'\0'</CODE>) (see Section <A HREF="#lexical">4.1</A>). | |
| 150 | −The <CODE>type</CODE> function returns a string describing the type | |
| 151 | −of a given value (see Section <A HREF="#pdf-type">6.1</A>). | |
| 152 | −<P> | |
| 153 | −Functions are considered <EM>first-class values</EM> in Lua. | |
| 154 | −This means that functions can be stored in variables, | |
| 155 | −passed as arguments to other functions, and returned as results. | |
| 156 | −Lua can call (and manipulate) functions written in Lua and | |
| 157 | −functions written in C. | |
| 158 | −The two kinds of functions can be distinguished by their tags: | |
| 159 | −all Lua functions have the same tag, | |
| 160 | −and all C functions have the same tag, | |
| 161 | −which is different from the tag of Lua functions. | |
| 162 | −The <CODE>tag</CODE> function returns the tag | |
| 163 | −of a given value (see Section <A HREF="#pdf-tag">6.1</A>). | |
| 164 | −<P> | |
| 165 | −The type <EM>userdata</EM> is provided to allow | |
| 166 | −arbitrary <A NAME="C pointers">C pointers</A> to be stored in Lua variables. | |
| 167 | −This type corresponds to a <CODE>void*</CODE> | |
| 168 | −and has no pre-defined operations in Lua, | |
| 169 | −except assignment and equality test. | |
| 170 | −However, by using <EM>tag methods</EM>, | |
| 171 | −the programmer can define operations for <EM>userdata</EM> values | |
| 172 | −(see Section <A HREF="#tag-method">4.8</A>). | |
| 173 | −<P> | |
| 174 | −The type <EM>table</EM> implements <A NAME="associative arrays">associative arrays</A>, | |
| 175 | −that is, <A NAME="arrays">arrays</A> that can be indexed not only with numbers, | |
| 176 | −but with any value (except <B>nil</B>). | |
| 177 | −Therefore, this type may be used not only to represent ordinary arrays, | |
| 178 | −but also symbol tables, sets, records, graphs, trees, etc. | |
| 179 | −Tables are the main data structuring mechanism in Lua. | |
| 180 | −To represent <A NAME="records">records</A>, Lua uses the field name as an index. | |
| 181 | −The language supports this representation by | |
| 182 | −providing <CODE>a.name</CODE> as syntactic sugar for <CODE>a["name"]</CODE>. | |
| 183 | −Tables may also carry <EM>methods</EM>: | |
| 184 | −Because functions are first class values, | |
| 185 | −table fields may contain functions. | |
| 186 | −The form <CODE>t:f(x)</CODE> is syntactic sugar for <CODE>t.f(t,x)</CODE>, | |
| 187 | −which calls the method <CODE>f</CODE> from the table <CODE>t</CODE> passing | |
| 188 | −the table itself as the first parameter (see Section <A HREF="#func-def">4.5.9</A>). | |
| 189 | −<P> | |
| 190 | −Note that tables are <EM>objects</EM>, and not values. | |
| 191 | −Variables do not contain tables, only <EM>references</EM> to them. | |
| 192 | −Assignment, parameter passing, and returns always manipulate references | |
| 193 | −to tables, and do not imply any kind of copy. | |
| 194 | −Moreover, tables must be explicitly created before used | |
| 195 | −(see Section <A HREF="#tableconstructor">4.5.7</A>). | |
| 196 | −<P> | |
| 197 | −Each of the types <EM>nil</EM>, <EM>number</EM>, and <EM>string</EM> has a different tag. | |
| 198 | −All values of each of these types have the same pre-defined tag. | |
| 199 | −As explained above, | |
| 200 | −values of type <EM>function</EM> can have two different tags, | |
| 201 | −depending on whether they are Lua functions or C functions. | |
| 202 | −Finally, | |
| 203 | −values of type <EM>userdata</EM> and <EM>table</EM> can have variable tags, | |
| 204 | −assigned by the programmer (see Section <A HREF="#tag-method">4.8</A>). | |
| 205 | −The <CODE>tag</CODE> function returns the tag of a given value. | |
| 206 | −User tags are created with the function <CODE>newtag</CODE>. | |
| 207 | −The <CODE>settag</CODE> function | |
| 208 | −is used to change the tag of a table (see Section <A HREF="#pdf-newtag">6.1</A>). | |
| 209 | −The tag of userdata values can only be set from C (see Section <A HREF="#C-tags">5.7</A>). | |
| 210 | −Tags are mainly used to select <EM>tag methods</EM> when | |
| 211 | −some events occur. | |
| 212 | −Tag methods are the main mechanism for extending the | |
| 213 | −semantics of Lua (see Section <A HREF="#tag-method">4.8</A>). | |
| 214 | −<P> | |
| 215 | −<!-- ====================================================================== --> | |
| 216 | −<HR> | |
| 217 | −<A NAME="4."></A> | |
| 218 | −<H1>4 - The Language</H1> | |
| 219 | −<P> | |
| 220 | −This section describes the lexis, the syntax, and the semantics of Lua. | |
| 221 | −<P> | |
| 222 | −<P> | |
| 223 | −<A NAME="lexical"></A> | |
| 224 | −<A NAME="4.1"></A> | |
| 225 | −<H2>4.1 - Lexical Conventions</H2> | |
| 226 | −<P> | |
| 227 | −<A NAME="Identifiers"><EM>Identifiers</EM></A> in Lua can be any string of letters, | |
| 101 | +{<em>a</em>} means 0 or more <em>a</em>'s, and | |
| 102 | +[<em>a</em>] means an optional <em>a</em>. | |
| 103 | +Non-terminals are shown in <em>italics</em>, | |
| 104 | +keywords are shown in <b>bold</b>, | |
| 105 | +and other terminal symbols are shown in <code>typewriter</code> font, | |
| 106 | +enclosed in single quotes. | |
| 107 | + | |
| 108 | +<p><a name="lexical"><h2>2.1 - Lexical Conventions</h2></a> | |
| 109 | + | |
| 110 | +<p><em>Identifiers</em> in Lua can be any string of letters, | |
| 228 | 111 | digits, and underscores, |
| 229 | 112 | not beginning with a digit. |
| 230 | −This coincides with the definition of identifiers in most languages, | |
| 231 | −except that | |
| 232 | −the definition of letter depends on the current locale: | |
| 233 | −Any character considered alphabetic by the current locale | |
| 234 | −can be used in an identifier. | |
| 235 | −The following words are <EM>reserved</EM>, and cannot be used as identifiers: | |
| 236 | −<A NAME="reserved words"></A> | |
| 113 | +This coincides with the definition of identifiers in most languages. | |
| 114 | +(The definition of letter depends on the current locale: | |
| 115 | +any character considered alphabetic by the current locale | |
| 116 | +can be used in an identifier.) | |
| 117 | + | |
| 118 | +<p>The following <em>keywords</em> are reserved | |
| 119 | +and cannot be used as identifiers: | |
| 120 | + | |
| 237 | 121 | <PRE> |
| 238 | 122 | and break do else elseif |
| 239 | − end for function if in | |
| 240 | − local nil not or repeat | |
| 241 | − return then until while | |
| 242 | −</PRE> | |
| 243 | −<P> | |
| 244 | −Lua is a case-sensitive language: | |
| 245 | −<TT>and</TT> is a reserved word, but <TT>And</TT> and <TT>�nd</TT> | |
| 246 | −(if the locale permits) are two different, valid identifiers. | |
| 247 | −As a convention, identifiers starting with underscore followed by | |
| 248 | −uppercase letters (such as <CODE>_INPUT</CODE>) | |
| 249 | −are reserved for internal variables. | |
| 250 | −<P> | |
| 251 | −The following strings denote other <A NAME="tokens">tokens</A>: | |
| 252 | −<PRE> | |
| 253 | − ~= <= >= < > == = + - * / | |
| 254 | − ( ) { } [ ] ; , . .. ... | |
| 255 | −</PRE> | |
| 256 | −<P> | |
| 257 | −<A NAME="Literal strings"><EM>Literal strings</EM></A> | |
| 123 | + end false for function if | |
| 124 | + in local nil not or | |
| 125 | + repeat return then true until | |
| 126 | + while | |
| 127 | +</PRE> | |
| 128 | + | |
| 129 | +<p>Lua is a case-sensitive language: | |
| 130 | +<code>and</code> is a reserved word, but <code>And</code> and <code>AND</code> | |
| 131 | +are two different, valid identifiers. | |
| 132 | +As a convention, identifiers starting with an underscore followed by | |
| 133 | +uppercase letters (such as <code>_VERSION</code>) | |
| 134 | +are reserved for internal variables used by Lua. | |
| 135 | + | |
| 136 | +<p>The following strings denote other tokens: | |
| 137 | +<PRE> | |
| 138 | + + - * / ^ = | |
| 139 | + ~= <= >= < > == | |
| 140 | + ( ) { } [ ] | |
| 141 | + ; : , . .. ... | |
| 142 | +</PRE> | |
| 143 | + | |
| 144 | +<p><em>Literal strings</em> | |
| 258 | 145 | can be delimited by matching single or double quotes, |
| 259 | −and can contain the C-like escape sequences | |
| 260 | −`<CODE>\a</CODE>' (bell), | |
| 261 | −`<CODE>\b</CODE>' (backspace), | |
| 262 | −`<CODE>\f</CODE>' (form feed), | |
| 263 | −`<CODE>\n</CODE>' (newline), | |
| 264 | −`<CODE>\r</CODE>' (carriage return), | |
| 265 | −`<CODE>\t</CODE>' (horizontal tab), | |
| 266 | −`<CODE>\v</CODE>' (vertical tab), | |
| 267 | −`<CODE>\\</CODE>' (backslash), | |
| 268 | −`<CODE>\"</CODE>' (double quote), | |
| 269 | −`<CODE>\'</CODE>' (single quote), | |
| 270 | −and `<CODE>\</CODE><EM>newline</EM>' (that is, a backslash followed by a real newline, | |
| 271 | −which results in a newline in the string). | |
| 272 | −A character in a string may also be specified by its numerical value, | |
| 273 | −through the escape sequence `<CODE>\</CODE><EM>ddd</EM>', | |
| 274 | −where <EM>ddd</EM> is a sequence of up to three <EM>decimal</EM> digits. | |
| 146 | +and can contain the following C-like escape sequences: | |
| 147 | +<ul> | |
| 148 | +<li><b><code>\a</code></b> --- bell | |
| 149 | +<li><b><code>\b</code></b> --- backspace | |
| 150 | +<li><b><code>\f</code></b> --- form feed | |
| 151 | +<li><b><code>\n</code></b> --- newline | |
| 152 | +<li><b><code>\r</code></b> --- carriage return | |
| 153 | +<li><b><code>\t</code></b> --- horizontal tab | |
| 154 | +<li><b><code>\v</code></b> --- vertical tab | |
| 155 | +<li><b><code>\\</code></b> --- backslash | |
| 156 | +<li><b><code>\"</code></b> --- quotation mark | |
| 157 | +<li><b><code>\'</code></b> --- apostrophe | |
| 158 | +<li><b><code>\[</code></b> --- left square bracket | |
| 159 | +<li><b><code>\]</code></b> --- right square bracket | |
| 160 | +</ul> | |
| 161 | +Moreover, a `<code>\</code><em>newline</em>´ | |
| 162 | +(that is, a backslash followed by a real newline) | |
| 163 | +results in a newline in the string. | |
| 164 | +A character in a string may also be specified by its numerical value | |
| 165 | +using the escape sequence `<code>\</code><em>ddd</em>´, | |
| 166 | +where <em>ddd</em> is a sequence of up to three decimal digits. | |
| 275 | 167 | Strings in Lua may contain any 8-bit value, including embedded zeros, |
| 276 | −which can be specified as `<CODE>\000</CODE>'. | |
| 277 | −<P> | |
| 278 | −Literal strings can also be delimited by matching <CODE>[[</CODE> ... <CODE>]]</CODE>. | |
| 168 | +which can be specified as `<code>\0</code>´. | |
| 169 | + | |
| 170 | +<p>Literal strings can also be delimited by matching double square brackets | |
| 171 | +<code>[[</code> · · · <code>]]</code>. | |
| 279 | 172 | Literals in this bracketed form may run for several lines, |
| 280 | −may contain nested <CODE>[[</CODE> ... <CODE>]]</CODE> pairs, | |
| 281 | −and do not interpret escape sequences. | |
| 282 | −This form is specially convenient for | |
| 283 | −writing strings that contain program pieces or | |
| 284 | −other quoted strings. | |
| 285 | −As an example, in a system using ASCII, | |
| 286 | −the following three literals are equivalent: | |
| 287 | −<PRE> | |
| 288 | − 1) "alo\n123\"" | |
| 289 | − 2) '\97lo\10\04923"' | |
| 290 | − 3) [[alo | |
| 173 | +may contain nested <code>[[</code> · · · <code>]]</code> pairs, | |
| 174 | +and do not interpret any escape sequences. | |
| 175 | +For convenience, | |
| 176 | +when the opening `<code>[[</code>´ is immediately followed by a newline, | |
| 177 | +the newline is not included in the string. | |
| 178 | +As an example, in a system using ASCII | |
| 179 | +(in which `<code>a</code>´ is coded as 97, | |
| 180 | +newline is coded as 10, and `<code>1</code>´ is coded as 49), | |
| 181 | +the four literals below denote the same string: | |
| 182 | +<PRE> | |
| 183 | + (1) "alo\n123\"" | |
| 184 | + (2) '\97lo\10\04923"' | |
| 185 | + (3) [[alo | |
| 186 | + 123"]] | |
| 187 | + (4) [[ | |
| 188 | + alo | |
| 291 | 189 | 123"]] |
| 292 | 190 | </PRE> |
| 293 | −<P> | |
| 294 | −<A NAME="Comments"><EM>Comments</EM></A> start anywhere outside a string with a | |
| 295 | −double hyphen (<CODE>--</CODE>) and run until the end of the line. | |
| 296 | −Moreover, | |
| 297 | −the first line of a chunk is skipped if it starts with <CODE>#</CODE>. | |
| 298 | −This facility allows the use of Lua as a script interpreter | |
| 299 | −in Unix systems (see Section <A HREF="#lua-sa">8</A>). | |
| 300 | −<P> | |
| 301 | −<A NAME="Numerical constants"><EM>Numerical constants</EM></A> may be written with an optional decimal part | |
| 191 | + | |
| 192 | +<p><em>Numerical constants</em> may be written with an optional decimal part | |
| 302 | 193 | and an optional decimal exponent. |
| 303 | 194 | Examples of valid numerical constants are |
| 304 | 195 | <PRE> |
| 305 | 196 | 3 3.0 3.1416 314.16e-2 0.31416E1 |
| 306 | 197 | </PRE> |
| 307 | −<P> | |
| 308 | −<A NAME="coercion"></A> | |
| 309 | −<A NAME="4.2"></A> | |
| 310 | −<H2>4.2 - Coercion</H2> | |
| 311 | −<P> | |
| 312 | −Lua provides some automatic conversions between values at run time. | |
| 198 | + | |
| 199 | +<p><em>Comments</em> start anywhere outside a string with a | |
| 200 | +double hyphen (<code>--</code>). | |
| 201 | +If the text immediately after <code>--</code> is different from <code>[[</code>, | |
| 202 | +the comment is a <em>short comment</em>, | |
| 203 | +which runs until the end of the line. | |
| 204 | +Otherwise, it is a <em>long comment</em>, | |
| 205 | +which runs until the corresponding <code>]]</code>. | |
| 206 | +Long comments may run for several lines | |
| 207 | +and may contain nested <code>[[</code> · · · <code>]]</code> pairs. | |
| 208 | + | |
| 209 | +<p>For convenience, | |
| 210 | +the first line of a chunk is skipped if it starts with <code>#</code>. | |
| 211 | +This facility allows the use of Lua as a script interpreter | |
| 212 | +in Unix systems (see <a href="#lua-sa">6</a>). | |
| 213 | + | |
| 214 | +<p><a name="TypesSec"><h2>2.2 - Values and Types</h2></a> | |
| 215 | + | |
| 216 | +<p>Lua is a <em>dynamically typed language</em>. | |
| 217 | +That means that | |
| 218 | +variables do not have types; only values do. | |
| 219 | +There are no type definitions in the language. | |
| 220 | +All values carry their own type. | |
| 221 | + | |
| 222 | +<p>There are eight basic types in Lua: | |
| 223 | +<em>nil</em>, <em>boolean</em>, <em>number</em>, | |
| 224 | +<em>string</em>, <em>function</em>, <em>userdata</em>, <em>thread</em>, and <em>table</em>. | |
| 225 | +<em>Nil</em> is the type of the value <B>nil</B>, | |
| 226 | +whose main property is to be different from any other value; | |
| 227 | +usually it represents the absence of a useful value. | |
| 228 | +<em>Boolean</em> is the type of the values <B>false</B> and <B>true</B>. | |
| 229 | +In Lua, both <B>nil</B> and <B>false</B> make a condition false; | |
| 230 | +any other value makes it true. | |
| 231 | +<em>Number</em> represents real (double-precision floating-point) numbers. | |
| 232 | +(It is easy to build Lua interpreters that use other | |
| 233 | +internal representations for numbers, | |
| 234 | +such as single-precision float or long integers.) | |
| 235 | +<em>String</em> represents arrays of characters. | |
| 236 | + | |
| 237 | +Lua is 8-bit clean: | |
| 238 | +Strings may contain any 8-bit character, | |
| 239 | +including embedded zeros (<code>'\0'</code>) (see <a href="#lexical">2.1</a>). | |
| 240 | + | |
| 241 | +<p>Functions are <em>first-class values</em> in Lua. | |
| 242 | +That means that functions can be stored in variables, | |
| 243 | +passed as arguments to other functions, and returned as results. | |
| 244 | +Lua can call (and manipulate) functions written in Lua and | |
| 245 | +functions written in C | |
| 246 | +(see <a href="#functioncall">2.5.7</a>). | |
| 247 | + | |
| 248 | +<p>The type <em>userdata</em> is provided to allow arbitrary C data to | |
| 249 | +be stored in Lua variables. | |
| 250 | +This type corresponds to a block of raw memory | |
| 251 | +and has no pre-defined operations in Lua, | |
| 252 | +except assignment and identity test. | |
| 253 | +However, by using <em>metatables</em>, | |
| 254 | +the programmer can define operations for userdata values | |
| 255 | +(see <a href="#metatable">2.8</a>). | |
| 256 | +Userdata values cannot be created or modified in Lua, | |
| 257 | +only through the C API. | |
| 258 | +This guarantees the integrity of data owned by the host program. | |
| 259 | + | |
| 260 | +<p>The type <em>thread</em> represents independent threads of execution | |
| 261 | +and it is used to implement coroutines. | |
| 262 | + | |
| 263 | +<p>The type <em>table</em> implements associative arrays, | |
| 264 | +that is, arrays that can be indexed not only with numbers, | |
| 265 | +but with any value (except <B>nil</B>). | |
| 266 | +Moreover, | |
| 267 | +tables can be <em>heterogeneous</em>, | |
| 268 | +that is, they can contain values of all types (except <B>nil</B>). | |
| 269 | +Tables are the sole data structuring mechanism in Lua; | |
| 270 | +they may be used to represent ordinary arrays, | |
| 271 | +symbol tables, sets, records, graphs, trees, etc. | |
| 272 | +To represent records, Lua uses the field name as an index. | |
| 273 | +The language supports this representation by | |
| 274 | +providing <code>a.name</code> as syntactic sugar for <code>a["name"]</code>. | |
| 275 | +There are several convenient ways to create tables in Lua | |
| 276 | +(see <a href="#tableconstructor">2.5.6</a>). | |
| 277 | + | |
| 278 | +<p>Like indices, | |
| 279 | +the value of a table field can be of any type (except <B>nil</B>). | |
| 280 | +In particular, | |
| 281 | +because functions are first class values, | |
| 282 | +table fields may contain functions. | |
| 283 | +Thus tables may also carry <em>methods</em> (see <a href="#func-def">2.5.8</a>). | |
| 284 | + | |
| 285 | +<p>Tables, functions, and userdata values are <em>objects</em>: | |
| 286 | +variables do not actually <em>contain</em> these values, | |
| 287 | +only <em>references</em> to them. | |
| 288 | +Assignment, parameter passing, and function returns | |
| 289 | +always manipulate references to such values; | |
| 290 | +these operations do not imply any kind of copy. | |
| 291 | + | |
| 292 | +<p>The library function <code>type</code> returns a string describing the type | |
| 293 | +of a given value (see <a href="#pdf-type">5.1</a>). | |
| 294 | + | |
| 295 | +<p><a name="coercion"><h3>2.2.1 - Coercion</h3></a> | |
| 296 | + | |
| 297 | +<p>Lua provides automatic conversion between | |
| 298 | +string and number values at run time. | |
| 313 | 299 | Any arithmetic operation applied to a string tries to convert |
| 314 | 300 | that string to a number, following the usual rules. |
| 315 | −Conversely, whenever a number is used when a string is expected, | |
| 316 | −that number is converted to a string, in a reasonable format. | |
| 317 | −The format is chosen so that | |
| 318 | −a conversion from number to string then back to number | |
| 319 | −reproduces the original number <EM>exactly</EM>. | |
| 320 | −Thus, | |
| 321 | −the conversion does not necessarily produces nice-looking text for some numbers. | |
| 301 | +Conversely, whenever a number is used where a string is expected, | |
| 302 | +the number is converted to a string, in a reasonable format. | |
| 322 | 303 | For complete control of how numbers are converted to strings, |
| 323 | −use the <CODE>format</CODE> function (see Section <A HREF="#format">6.2</A>). | |
| 324 | −<P> | |
| 325 | −<P> | |
| 326 | −<A NAME="adjust"></A> | |
| 327 | −<A NAME="4.3"></A> | |
| 328 | −<H2>4.3 - Adjustment</H2> | |
| 329 | −<P> | |
| 330 | −Functions in Lua can return many values. | |
| 331 | −Because there are no type declarations, | |
| 332 | −when a function is called | |
| 333 | −the system does not know how many values the function will return, | |
| 334 | −or how many parameters it needs. | |
| 335 | −Therefore, sometimes, a list of values must be <EM>adjusted</EM>, at run time, | |
| 336 | −to a given length. | |
| 337 | −If there are more values than are needed, | |
| 338 | −then the excess values are thrown away. | |
| 339 | −If there are less values than are needed, | |
| 340 | −then the list is extended with as many <B>nil</B>'s as needed. | |
| 341 | −This adjustment occurs in multiple assignments (see Section <A HREF="#assignment">4.4.2</A>) | |
| 342 | −and in function calls (see Section <A HREF="#functioncall">4.5.8</A>). | |
| 343 | −<P> | |
| 344 | −<P> | |
| 345 | −<A NAME="stats"></A> | |
| 346 | −<A NAME="4.4"></A> | |
| 347 | −<H2>4.4 - Statements</H2> | |
| 348 | −<P> | |
| 349 | −Lua supports an almost conventional set of <A NAME="statements">statements</A>, | |
| 350 | −similar to those in Pascal or C. | |
| 351 | −The conventional commands include | |
| 352 | −assignment, control structures, and procedure calls. | |
| 353 | −Non-conventional commands include table constructors | |
| 354 | −(see Section <A HREF="#tableconstructor">4.5.7</A>) | |
| 355 | −and local variable declarations (see Section <A HREF="#localvar">4.4.6</A>). | |
| 356 | −<P> | |
| 357 | −<H3>4.4.1 - Blocks</H3> | |
| 358 | −A <A NAME="block">block</A> is a list of statements; | |
| 359 | −syntactically, a block is equal to a chunk: | |
| 360 | −<PRE> | |
| 361 | − block ::= chunk | |
| 362 | −</PRE> | |
| 363 | −<P> | |
| 364 | −A block may be explicitly delimited: | |
| 304 | +use the <code>format</code> function from the string library (see <a href="#format">5.3</a>). | |
| 305 | + | |
| 306 | +<p><a name="variables"><h2>2.3 - Variables</h2></a> | |
| 307 | + | |
| 308 | +<p>Variables are places that store values. | |
| 309 | + | |
| 310 | +There are three kinds of variables in Lua: | |
| 311 | +global variables, local variables, and table fields. | |
| 312 | + | |
| 313 | +<p>A single name can denote a global variable or a local variable | |
| 314 | +(or a formal parameter of a function, | |
| 315 | +which is a particular form of local variable): | |
| 316 | +<pre> | |
| 317 | + var ::= Name | |
| 318 | +</pre> | |
| 319 | +Variables are assumed to be global unless explicitly declared local | |
| 320 | +(see <a href="#localvar">2.4.7</a>). | |
| 321 | +Local variables are <em>lexically scoped</em>: | |
| 322 | +Local variables can be freely accessed by functions | |
| 323 | +defined inside their scope (see <a href="#visibility">2.6</a>). | |
| 324 | + | |
| 325 | +<p>Before the first assignment to a variable, its value is <B>nil</B>. | |
| 326 | + | |
| 327 | +<p>Square brackets are used to index a table: | |
| 328 | +<pre> | |
| 329 | + var ::= prefixexp `<b>[</b>´ exp `<b>]</b>´ | |
| 330 | +</pre> | |
| 331 | +The first expression (<em>prefixexp</em>)should result in a table value; | |
| 332 | +the second expression (<em>exp</em>) | |
| 333 | +identifies a specific entry inside that table. | |
| 334 | +The expression denoting the table to be indexed has a restricted syntax; | |
| 335 | +see <a href="#expressions">2.5</a> for details. | |
| 336 | + | |
| 337 | +<p>The syntax <code>var.NAME</code> is just syntactic sugar for | |
| 338 | +<code>var["NAME"]</code>: | |
| 339 | +<pre> | |
| 340 | + var ::= prefixexp `<b>.</b>´ Name | |
| 341 | +</pre> | |
| 342 | + | |
| 343 | +<p>The meaning of accesses to global variables | |
| 344 | +and table fields can be changed via metatables. | |
| 345 | +An access to an indexed variable <code>t[i]</code> is equivalent to | |
| 346 | +a call <code>gettable_event(t,i)</code>. | |
| 347 | +(See <a href="#metatable">2.8</a> for a complete description of the | |
| 348 | +<code>gettable_event</code> function. | |
| 349 | +This function is not defined or callable in Lua. | |
| 350 | +We use it here only for explanatory purposes.) | |
| 351 | + | |
| 352 | +<p>All global variables live as fields in ordinary Lua tables, | |
| 353 | +called <em>environment tables</em> or simply <em>environments</em>. | |
| 354 | +Functions written in C and exported to Lua (<em>C functions</em>) | |
| 355 | +all share a common <em>global environment</em>. | |
| 356 | +Each function written in Lua (a <em>Lua function</em>) | |
| 357 | +has its own reference to an environment, | |
| 358 | +so that all global variables in that function | |
| 359 | +will refer to that environment table. | |
| 360 | +When a function is created, | |
| 361 | +it inherits the environment from the function that created it. | |
| 362 | +To change or get the environment table of a Lua function, | |
| 363 | +you call <code>setfenv</code> or <code>getfenv</code> (see <a href="#setfenv">5.1</a>). | |
| 364 | + | |
| 365 | +<p>An access to a global variable <code>x</code> | |
| 366 | +is equivalent to <code>_env.x</code>, | |
| 367 | +which in turn is equivalent to | |
| 365 | 368 | <PRE> |
| 366 | − stat ::= <B>do</B> block <B>end</B> | |
| 369 | + gettable_event(_env, "x") | |
| 367 | 370 | </PRE> |
| 371 | +where <code>_env</code> is the environment of the running function. | |
| 372 | +(The <code>_env</code> variable is not defined in Lua. | |
| 373 | +We use it here only for explanatory purposes.) | |
| 374 | + | |
| 375 | +<p><a name="stats"><h2>2.4 - Statements</h2></a> | |
| 376 | + | |
| 377 | +<p>Lua supports an almost conventional set of statements, | |
| 378 | +similar to those in Pascal or C. | |
| 379 | +This set includes | |
| 380 | +assignment, control structures, procedure calls, | |
| 381 | +table constructors, and variable declarations. | |
| 382 | + | |
| 383 | +<p><a name="chunks"><h3>2.4.1 - Chunks</h3></a> | |
| 384 | + | |
| 385 | +<p>The unit of execution of Lua is called a <em>chunk</em>. | |
| 386 | +A chunk is simply a sequence of statements, | |
| 387 | +which are executed sequentially. | |
| 388 | +Each statement can be optionally followed by a semicolon: | |
| 389 | +<pre> | |
| 390 | + chunk ::= {stat [`<b>;</b>´]} | |
| 391 | +</pre> | |
| 392 | + | |
| 393 | +<p>Lua handles a chunk as the body of an anonymous function (see <a href="#func-def">2.5.8</a>). | |
| 394 | +As such, chunks can define local variables and return values. | |
| 395 | + | |
| 396 | +<p>A chunk may be stored in a file or in a string inside the host program. | |
| 397 | +When a chunk is executed, first it is pre-compiled into opcodes for | |
| 398 | +a virtual machine, | |
| 399 | +and then the compiled code is executed | |
| 400 | +by an interpreter for the virtual machine. | |
| 401 | + | |
| 402 | +<p>Chunks may also be pre-compiled into binary form; | |
| 403 | +see program <code>luac</code> for details. | |
| 404 | +Programs in source and compiled forms are interchangeable; | |
| 405 | +Lua automatically detects the file type and acts accordingly. | |
| 406 | + | |
| 407 | + | |
| 408 | +<p><h3>2.4.2 - Blocks</h3> | |
| 409 | +A block is a list of statements; | |
| 410 | +syntactically, a block is equal to a chunk: | |
| 411 | +<pre> | |
| 412 | + block ::= chunk | |
| 413 | +</pre> | |
| 414 | + | |
| 415 | +<p>A block may be explicitly delimited to produce a single statement: | |
| 416 | +<pre> | |
| 417 | + stat ::= <b>do</b> block <b>end</b> | |
| 418 | +</pre> | |
| 368 | 419 | Explicit blocks are useful |
| 369 | −to control the scope of local variables (see Section <A HREF="#localvar">4.4.6</A>). | |
| 420 | +to control the scope of variable declarations. | |
| 370 | 421 | Explicit blocks are also sometimes used to |
| 371 | −add a <B>return</B> or <B>break</B> statement in the middle | |
| 372 | −of another block (see Section <A HREF="#control">4.4.3</A>). | |
| 373 | −<P> | |
| 374 | −<A NAME="assignment"></A> | |
| 375 | −<H3>4.4.2 - <A NAME="Assignment</H3>">Assignment</H3></A> | |
| 376 | −Lua allows <A NAME="multiple assignment">multiple assignment</A>. | |
| 422 | +add a <b>return</b> or <b>break</b> statement in the middle | |
| 423 | +of another block (see <a href="#control">2.4.4</a>). | |
| 424 | + | |
| 425 | + | |
| 426 | +<p><a name="assignment"><h3>2.4.3 - Assignment</h3></a> | |
| 427 | + | |
| 428 | +<p>Lua allows multiple assignment. | |
| 377 | 429 | Therefore, the syntax for assignment |
| 378 | 430 | defines a list of variables on the left side |
| 379 | 431 | and a list of expressions on the right side. |
| 380 | 432 | The elements in both lists are separated by commas: |
| 381 | −<PRE> | |
| 382 | − stat ::= varlist1 `<B>=</B>' explist1 | |
| 383 | − varlist1 ::= var {`<B>,</B>' var} | |
| 384 | −</PRE> | |
| 385 | −This statement first evaluates all values on the right side | |
| 386 | −and eventual indices on the left side, | |
| 387 | −and then makes the assignments. | |
| 388 | −So, the code | |
| 433 | +<pre> | |
| 434 | + stat ::= varlist1 `<b>=</b>´ explist1 | |
| 435 | + varlist1 ::= var {`<b>,</b>´ var} | |
| 436 | + explist1 ::= exp {`<b>,</b>´ exp} | |
| 437 | +</pre> | |
| 438 | +Expressions are discussed in <a href="#expressions">2.5</a>. | |
| 439 | + | |
| 440 | +<p>Before the assignment, | |
| 441 | +the list of values is <em>adjusted</em> to the length of | |
| 442 | +the list of variables. | |
| 443 | +If there are more values than needed, | |
| 444 | +the excess values are thrown away. | |
| 445 | +If there are fewer values than needed, | |
| 446 | +the list is extended with as many <B>nil</B>'s as needed. | |
| 447 | +If the list of expressions ends with a function call, | |
| 448 | +then all values returned by that function call enter in the list of values, | |
| 449 | +before the adjustment | |
| 450 | +(except when the call is enclosed in parentheses; see <a href="#expressions">2.5</a>). | |
| 451 | + | |
| 452 | +<p>The assignment statement first evaluates all its expressions | |
| 453 | +and only then are the assignments performed. | |
| 454 | +Thus the code | |
| 389 | 455 | <PRE> |
| 390 | 456 | i = 3 |
| 391 | − i, a[i] = 4, 20 | |
| 457 | + i, a[i] = i+1, 20 | |
| 392 | 458 | </PRE> |
| 393 | −sets <CODE>a[3]</CODE> to 20, but does not affect <CODE>a[4]</CODE> | |
| 394 | −because the <CODE>i</CODE> in <CODE>a[i]</CODE> is evaluated | |
| 395 | −before it is assigned <CODE>4</CODE>. | |
| 396 | −<P> | |
| 397 | −Multiple assignment can be used to exchange two values, as in | |
| 459 | +sets <code>a[3]</code> to 20, without affecting <code>a[4]</code> | |
| 460 | +because the <code>i</code> in <code>a[i]</code> is evaluated (to 3) | |
| 461 | +before it is assigned 4. | |
| 462 | +Similarly, the line | |
| 398 | 463 | <PRE> |
| 399 | 464 | x, y = y, x |
| 400 | 465 | </PRE> |
| 401 | −<P> | |
| 402 | −The two lists in a multiple assignment may have different lengths. | |
| 403 | −Before the assignment, the list of values is adjusted to | |
| 404 | −the length of the list of variables (see Section <A HREF="#adjust">4.3</A>). | |
| 405 | −<P> | |
| 406 | −A single name can denote a global variable, a local variable, | |
| 407 | −or a formal parameter: | |
| 408 | −<PRE> | |
| 409 | − var ::= name | |
| 410 | −</PRE> | |
| 411 | −<P> | |
| 412 | −Square brackets are used to index a table: | |
| 413 | −<PRE> | |
| 414 | − var ::= varorfunc `<B>[</B>' exp1 `<B>]</B>' | |
| 415 | − varorfunc ::= var | functioncall | |
| 416 | −</PRE> | |
| 417 | −The <EM>varorfunc</EM> should result in a table value, | |
| 418 | −from where the field indexed by the expression <EM>exp1</EM> | |
| 419 | −value gets the assigned value. | |
| 420 | −<P> | |
| 421 | −The syntax <CODE>var.NAME</CODE> is just syntactic sugar for | |
| 422 | −<CODE>var["NAME"]</CODE>: | |
| 423 | −<PRE> | |
| 424 | − var ::= varorfunc `<B>.</B>' name | |
| 425 | −</PRE> | |
| 426 | −<P> | |
| 427 | −The meaning of assignments and evaluations of global variables and | |
| 428 | −indexed variables can be changed by tag methods (see Section <A HREF="#tag-method">4.8</A>). | |
| 429 | −Actually, | |
| 430 | −an assignment <CODE>x = val</CODE>, where <CODE>x</CODE> is a global variable, | |
| 431 | −is equivalent to a call <CODE>setglobal("x", val)</CODE> and | |
| 432 | −an assignment <CODE>t[i] = val</CODE> is equivalent to | |
| 433 | −<CODE>settable_event(t,i,val)</CODE>. | |
| 434 | −See Section <A HREF="#tag-method">4.8</A> for a complete description of these functions | |
| 435 | −(<CODE>setglobal</CODE> is in the basic library; | |
| 436 | −<TT>settable_event</TT> is used for explanatory purposes only). | |
| 437 | −<P> | |
| 438 | −<A NAME="control"></A> | |
| 439 | −<H3>4.4.3 - Control Structures</H3> | |
| 440 | −The control structures | |
| 441 | −<B>if</B>, <B>while</B>, and <B>repeat</B> have the usual meaning and | |
| 442 | −familiar syntax | |
| 443 | −<A NAME="while-do statement"></A> | |
| 444 | −<A NAME="repeat-until statement"></A> | |
| 445 | −<A NAME="if-then-else statement"></A> | |
| 446 | −<PRE> | |
| 447 | − stat ::= <B>while</B> exp1 <B>do</B> block <B>end</B> | |
| 448 | − stat ::= <B>repeat</B> block <B>until</B> exp1 | |
| 449 | − stat ::= <B>if</B> exp1 <B>then</B> block {<B>elseif</B> exp1 <B>then</B> block} [<B>else</B> block] <B>end</B> | |
| 450 | −</PRE> | |
| 451 | −The <A NAME="condition expression">condition expression</A> <EM>exp1</EM> of a control structure may return any value. | |
| 452 | −All values different from <B>nil</B> are considered true; | |
| 453 | −only <B>nil</B> is considered false. | |
| 454 | −<P> | |
| 455 | −The <B>return</B> statement is used to return values | |
| 456 | −from a function or from a chunk. | |
| 457 | −<A NAME="return"></A> | |
| 466 | +exchanges the values of <code>x</code> and <code>y</code>. | |
| 458 | 467 | |
| 459 | −<A NAME="return statement"></A> | |
| 460 | −Because functions or chunks may return more than one value, | |
| 461 | −the syntax for the <B>return</B> statement is | |
| 462 | −<PRE> | |
| 463 | − stat ::= <B>return</B> [explist1] | |
| 464 | −</PRE> | |
| 465 | −<P> | |
| 466 | −The <B>break</B> statement can be used to terminate the execution of a loop, | |
| 467 | −skipping to the next statement after the loop: | |
| 468 | −<A NAME="break statement"></A> | |
| 468 | +<p>The meaning of assignments to global variables | |
| 469 | +and table fields can be changed via metatables. | |
| 470 | +An assignment to an indexed variable <code>t[i] = val</code> is equivalent to | |
| 471 | +<code>settable_event(t,i,val)</code>. | |
| 472 | +(See <a href="#metatable">2.8</a> for a complete description of the | |
| 473 | +<code>settable_event</code> function. | |
| 474 | +This function is not defined or callable in Lua. | |
| 475 | +We use it here only for explanatory purposes.) | |
| 476 | + | |
| 477 | +<p>An assignment to a global variable <code>x = val</code> | |
| 478 | +is equivalent to the assignment | |
| 479 | +<code>_env.x = val</code>, | |
| 480 | +which in turn is equivalent to | |
| 469 | 481 | <PRE> |
| 470 | − stat ::= <B>break</B> | |
| 482 | + settable_event(_env, "x", val) | |
| 471 | 483 | </PRE> |
| 472 | −A <B>break</B> ends the innermost enclosing loop | |
| 473 | −(<B>while</B>, <B>repeat</B>, or <B>for</B>). | |
| 474 | −<P> | |
| 475 | −For syntactic reasons, <B>return</B> and <B>break</B> | |
| 476 | −statements can only be written as the <EM>last</EM> statements of a block. | |
| 477 | −If it is really necessary to <B>return</B> or <B>break</B> in the | |
| 484 | +where <code>_env</code> is the environment of the running function. | |
| 485 | +(The <code>_env</code> variable is not defined in Lua. | |
| 486 | +We use it here only for explanatory purposes.) | |
| 487 | + | |
| 488 | +<p><a name="control"><h3>2.4.4 - Control Structures</h3></a> | |
| 489 | +The control structures | |
| 490 | +<b>if</b>, <b>while</b>, and <b>repeat</b> have the usual meaning and | |
| 491 | +familiar syntax: | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | +<pre> | |
| 496 | + stat ::= <b>while</b> exp <b>do</b> block <b>end</b> | |
| 497 | + stat ::= <b>repeat</b> block <b>until</b> exp | |
| 498 | + stat ::= <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b> | |
| 499 | +</pre> | |
| 500 | +Lua also has a <b>for</b> statement, in two flavors (see <a href="#for">2.4.5</a>). | |
| 501 | + | |
| 502 | +<p>The condition expression <em>exp</em> of a | |
| 503 | +control structure may return any value. | |
| 504 | +Both <B>false</B> and <B>nil</B> are considered false. | |
| 505 | +All values different from <B>nil</B> and <B>false</B> are considered true | |
| 506 | +(in particular, the number 0 and the empty string are also true). | |
| 507 | + | |
| 508 | +<p>The <b>return</b> statement is used to return values | |
| 509 | +from a function or from a chunk. | |
| 510 | + | |
| 511 | +Functions and chunks may return more than one value, | |
| 512 | +so the syntax for the <b>return</b> statement is | |
| 513 | +<pre> | |
| 514 | + stat ::= <b>return</b> [explist1] | |
| 515 | +</pre> | |
| 516 | + | |
| 517 | +<p>The <b>break</b> statement can be used to terminate the execution of a | |
| 518 | +<b>while</b>, <b>repeat</b>, or <b>for</b> loop, | |
| 519 | +skiping to the next statement after the loop: | |
| 520 | + | |
| 521 | +<pre> | |
| 522 | + stat ::= <b>break</b> | |
| 523 | +</pre> | |
| 524 | +A <b>break</b> ends the innermost enclosing loop. | |
| 525 | + | |
| 526 | +<p>For syntactic reasons, <b>return</b> and <b>break</b> | |
| 527 | +statements can only be written as the <em>last</em> statement of a block. | |
| 528 | +If it is really necessary to <b>return</b> or <b>break</b> in the | |
| 478 | 529 | middle of a block, |
| 479 | −an explicit inner block can used, | |
| 480 | −as in the idiom `<CODE>do return end</CODE>', | |
| 481 | −because now <B>return</B> is last statement in the inner block. | |
| 482 | −<P> | |
| 483 | −<A NAME="for"></A> | |
| 484 | −<H3>4.4.4 - For Statement</H3> <A NAME="for statement"></A> | |
| 485 | −<P> | |
| 486 | −The <B>for</B> statement has two forms, | |
| 487 | −one for numbers and one for tables. | |
| 488 | −The numerical <B>for</B> loop has the following syntax: | |
| 489 | −<PRE> | |
| 490 | − stat ::= <B>for</B> name `<B>=</B>' exp1 `<B>,</B>' exp1 [`<B>,</B>' exp1] <B>do</B> block <B>end</B> | |
| 491 | −</PRE> | |
| 492 | −A <B>for</B> statement like | |
| 530 | +then an explicit inner block can be used, | |
| 531 | +as in the idioms | |
| 532 | +`<code>do return end</code>´ and | |
| 533 | +`<code>do break end</code>´, | |
| 534 | +because now <b>return</b> and <b>break</b> are the last statements in | |
| 535 | +their (inner) blocks. | |
| 536 | +In practice, | |
| 537 | +those idioms are only used during debugging. | |
| 538 | + | |
| 539 | +<p><a name="for"><h3>2.4.5 - For Statement</h3></a> | |
| 540 | + | |
| 541 | +<p>The <b>for</b> statement has two forms: | |
| 542 | +one numeric and one generic. | |
| 543 | + | |
| 544 | + | |
| 545 | +<p>The numeric <b>for</b> loop repeats a block of code while a | |
| 546 | +control variable runs through an arithmetic progression. | |
| 547 | +It has the following syntax: | |
| 548 | +<pre> | |
| 549 | + stat ::= <b>for</b> Name `<b>=</b>´ exp `<b>,</b>´ exp [`<b>,</b>´ exp] <b>do</b> block <b>end</b> | |
| 550 | +</pre> | |
| 551 | +The <em>block</em> is repeated for <em>name</em> starting at the value of | |
| 552 | +the first <em>exp</em>, until it passes the second <em>exp</em> by steps of the | |
| 553 | +third <em>exp</em>. | |
| 554 | +More precisely, a <b>for</b> statement like | |
| 493 | 555 | <PRE> |
| 494 | − for var = e1 ,e2, e3 do block end | |
| 556 | + for var = e1, e2, e3 do block end | |
| 495 | 557 | </PRE> |
| 496 | 558 | is equivalent to the code: |
| 497 | 559 | <PRE> |
| 498 | 560 | do |
| 499 | 561 | local var, _limit, _step = tonumber(e1), tonumber(e2), tonumber(e3) |
| 500 | 562 | if not (var and _limit and _step) then error() end |
| 501 | − while (_step>0 and var<=_limit) or (_step<=0 and var>=_limit) do | |
| 563 | + while (_step>0 and var<=_limit) or (_step<=0 and var>=_limit) do | |
| 502 | 564 | block |
| 503 | − var = var+_step | |
| 565 | + var = var + _step | |
| 504 | 566 | end |
| 505 | 567 | end |
| 506 | 568 | </PRE> |
| 507 | 569 | Note the following: |
| 508 | −<UL><LI>sep=0pt | |
| 509 | −<LI><CODE>_limit</CODE> and <CODE>_step</CODE> are invisible variables. | |
| 570 | +<ul> | |
| 571 | +<li> All three control expressions are evaluated only once, | |
| 572 | +before the loop starts. | |
| 573 | +They must all result in numbers. | |
| 574 | +<li> <code>_limit</code> and <code>_step</code> are invisible variables. | |
| 510 | 575 | The names are here for explanatory purposes only. |
| 511 | −<LI>The behavior is <EM>undefined</EM> if you assign to <CODE>var</CODE> inside | |
| 576 | +<li> The behavior is <em>undefined</em> if you assign to <code>var</code> inside | |
| 512 | 577 | the block. |
| 513 | −<LI>If the third expression (the step) is absent, then a step of 1 is used. | |
| 514 | −<LI>Both the limit and the step are evaluated only once, | |
| 515 | −before the loop starts. | |
| 516 | −<LI>The variable <CODE>var</CODE> is local to the statement; | |
| 517 | −you cannot use its value after the <B>for</B> ends. | |
| 518 | −<LI>You can use <B>break</B> to exit a <B>for</B>. | |
| 519 | −If you need the value of the index, | |
| 520 | −assign it to another variable before breaking. | |
| 521 | −</UL> | |
| 522 | −<P> | |
| 523 | −The table <B>for</B> statement traverses all pairs | |
| 524 | −(index,value) of a given table. | |
| 525 | −It has the following syntax: | |
| 526 | −<PRE> | |
| 527 | − stat ::= <B>for</B> name `<B>,</B>' name <B>in</B> exp1 <B>do</B> block <B>end</B> | |
| 528 | −</PRE> | |
| 529 | −A <B>for</B> statement like | |
| 530 | −<PRE> | |
| 531 | − for index, value in exp do block end | |
| 578 | +<li> If the third expression (the step) is absent, then a step of 1 is used. | |
| 579 | +<li> You can use <b>break</b> to exit a <b>for</b> loop. | |
| 580 | +<li> The loop variable <code>var</code> is local to the statement; | |
| 581 | +you cannot use its value after the <b>for</b> ends or is broken. | |
| 582 | +If you need the value of the loop variable <code>var</code>, | |
| 583 | +then assign it to another variable before breaking or exiting the loop. | |
| 584 | +</ul> | |
| 585 | + | |
| 586 | +<p>The generic <b>for</b> statement works over functions, | |
| 587 | +called <em>iterators</em>. | |
| 588 | +For each iteration, it calls its iterator function to produce a new value, | |
| 589 | +stopping when the new value is <B>nil</B>. | |
| 590 | +The generic <b>for</b> loop has the following syntax: | |
| 591 | +<pre> | |
| 592 | + stat ::= <b>for</b> Name {`<b>,</b>´ Name} <b>in</b> explist1 <b>do</b> block <b>end</b> | |
| 593 | +</pre> | |
| 594 | +A <b>for</b> statement like | |
| 595 | +<PRE> | |
| 596 | + for var_1, ..., var_n in explist do block end | |
| 532 | 597 | </PRE> |
| 533 | 598 | is equivalent to the code: |
| 534 | 599 | <PRE> |
| 535 | 600 | do |
| 536 | − local _t = exp | |
| 537 | − local index, value = next(t, nil) | |
| 538 | − while index do | |
| 601 | + local _f, _s, var_1 = explist | |
| 602 | + local var_2, ... , var_n | |
| 603 | + while true do | |
| 604 | + var_1, ..., var_n = _f(_s, var_1) | |
| 605 | + if var_1 == nil then break end | |
| 539 | 606 | block |
| 540 | − index, value = next(t, index) | |
| 541 | 607 | end |
| 542 | 608 | end |
| 543 | 609 | </PRE> |
| 544 | 610 | Note the following: |
| 545 | −<UL><LI>sep=0pt | |
| 546 | −<LI><CODE>_t</CODE> is an invisible variable. | |
| 547 | −The name is here for explanatory purposes only. | |
| 548 | −<LI>The behavior is <EM>undefined</EM> if you assign to <CODE>index</CODE> inside | |
| 549 | −the block. | |
| 550 | −<LI>The behavior is <EM>undefined</EM> if you change | |
| 551 | −the table <CODE>_t</CODE> during the traversal. | |
| 552 | −<LI>The variables <CODE>index</CODE> and <CODE>value</CODE> are local to the statement; | |
| 553 | −you cannot use their values after the <B>for</B> ends. | |
| 554 | −<LI>You can use <B>break</B> to exit a <B>for</B>. | |
| 555 | −If you need the value of <CODE>index</CODE> or <CODE>value</CODE>, | |
| 556 | −assign them to other variables before breaking. | |
| 557 | −<LI>The order that table elements are traversed is undefined, | |
| 558 | −<EM>even for numerical indices</EM>. | |
| 559 | −If you want to traverse indices in numerical order, | |
| 560 | −use a numerical <B>for</B>. | |
| 561 | −</UL> | |
| 562 | −<P> | |
| 563 | −<P> | |
| 564 | −<A NAME="funcstat"></A> | |
| 565 | −<H3>4.4.5 - Function Calls as Statements</H3> | |
| 566 | −Because of possible side-effects, | |
| 611 | +<ul> | |
| 612 | +<li> <code>explist</code> is evaluated only once. | |
| 613 | +Its results are an <em>iterator</em> function, | |
| 614 | +a <em>state</em>, and an initial value for the first <em>iterator variable</em>. | |
| 615 | +<li> <code>_f</code> and <code>_s</code> are invisible variables. | |
| 616 | +The names are here for explanatory purposes only. | |
| 617 | +<li> The behavior is <em>undefined</em> if you assign to | |
| 618 | +<code>var_1</code> inside the block. | |
| 619 | +<li> You can use <b>break</b> to exit a <b>for</b> loop. | |
| 620 | +<li> The loop variables <code>var_i</code> are local to the statement; | |
| 621 | +you cannot use their values after the <b>for</b> ends. | |
| 622 | +If you need these values, | |
| 623 | +then assign them to other variables before breaking or exiting the loop. | |
| 624 | +</ul> | |
| 625 | + | |
| 626 | +<p><a name="funcstat"><h3>2.4.6 - Function Calls as Statements</h3></a> | |
| 627 | +To allow possible side-effects, | |
| 567 | 628 | function calls can be executed as statements: |
| 568 | −<PRE> | |
| 569 | − stat ::= functioncall | |
| 570 | −</PRE> | |
| 629 | +<pre> | |
| 630 | + stat ::= functioncall | |
| 631 | +</pre> | |
| 571 | 632 | In this case, all returned values are thrown away. |
| 572 | −Function calls are explained in Section <A HREF="#functioncall">4.5.8</A>. | |
| 573 | −<P> | |
| 574 | −<A NAME="localvar"></A> | |
| 575 | −<H3>4.4.6 - Local Declarations</H3> | |
| 576 | −<A NAME="Local variables">Local variables</A> may be declared anywhere inside a block. | |
| 633 | +Function calls are explained in <a href="#functioncall">2.5.7</a>. | |
| 634 | + | |
| 635 | +<p><a name="localvar"><h3>2.4.7 - Local Declarations</h3></a> | |
| 636 | +Local variables may be declared anywhere inside a block. | |
| 577 | 637 | The declaration may include an initial assignment: |
| 578 | −<PRE> | |
| 579 | − stat ::= <B>local</B> declist [init] | |
| 580 | − declist ::= name {`<B>,</B>' name} | |
| 581 | − init ::= `<B>=</B>' explist1 | |
| 582 | −</PRE> | |
| 638 | +<pre> | |
| 639 | + stat ::= <b>local</b> namelist [`<b>=</b>´ explist1] | |
| 640 | + namelist ::= Name {`<b>,</b>´ Name} | |
| 641 | +</pre> | |
| 583 | 642 | If present, an initial assignment has the same semantics |
| 584 | −of a multiple assignment. | |
| 643 | +of a multiple assignment (see <a href="#assignment">2.4.3</a>). | |
| 585 | 644 | Otherwise, all variables are initialized with <B>nil</B>. |
| 586 | −<P> | |
| 587 | −A chunk is also a block, | |
| 588 | −and so local variables can be declared outside any explicit block. | |
| 589 | −<P> | |
| 590 | −The scope of local variables begins <EM>after</EM> | |
| 591 | −the declaration and lasts until the end of the block. | |
| 592 | −Thus, the code | |
| 593 | −<CODE>local print=print</CODE> | |
| 594 | −creates a local variable called <CODE>print</CODE> whose | |
| 595 | −initial value is that of the <EM>global</EM> variable of the same name. | |
| 596 | −<P> | |
| 597 | −<P> | |
| 598 | −<A NAME="4.5"></A> | |
| 599 | −<H2>4.5 - Expressions</H2> | |
| 600 | −<P> | |
| 601 | −<H3>4.5.1 - <A NAME="Basic Expressions</H3>">Basic Expressions</H3></A> | |
| 602 | −The basic expressions in Lua are | |
| 603 | −<PRE> | |
| 604 | − exp ::= `<B>(</B>' exp `<B>)</B>' | |
| 605 | − exp ::= <B>nil</B> | |
| 606 | − exp ::= number | |
| 607 | − exp ::= literal | |
| 608 | − exp ::= var | |
| 609 | − exp ::= upvalue | |
| 610 | − exp ::= function | |
| 611 | − exp ::= functioncall | |
| 612 | − exp ::= tableconstructor | |
| 613 | −</PRE> | |
| 614 | −<P> | |
| 615 | −Numbers (numerical constants) and | |
| 616 | −literal strings are explained in Section <A HREF="#lexical">4.1</A>; | |
| 617 | −variables are explained in Section <A HREF="#assignment">4.4.2</A>; | |
| 618 | −upvalues are explained in Section <A HREF="#upvalue">4.6</A>; | |
| 619 | −function definitions are explained in Section <A HREF="#func-def">4.5.9</A>; | |
| 620 | −function calls are explained in Section <A HREF="#functioncall">4.5.8</A>. | |
| 621 | −Table constructors are explained in Section <A HREF="#tableconstructor">4.5.7</A>. | |
| 622 | −<P> | |
| 623 | −An access to a global variable <CODE>x</CODE> is equivalent to a | |
| 624 | −call <CODE>getglobal("x")</CODE> and | |
| 625 | −an access to an indexed variable <CODE>t[i]</CODE> is equivalent to | |
| 626 | −a call <CODE>gettable_event(t,i)</CODE>. | |
| 627 | −See Section <A HREF="#tag-method">4.8</A> for a description of these functions | |
| 628 | −(<CODE>getglobal</CODE> is in the basic library; | |
| 629 | −<TT>gettable_event</TT> is used for explanatory purposes only). | |
| 630 | −<P> | |
| 631 | −The non-terminal <EM>exp1</EM> is used to indicate that the values | |
| 632 | −returned by an expression must be adjusted to one single value: | |
| 633 | −<PRE> | |
| 634 | − exp1 ::= exp | |
| 635 | −</PRE> | |
| 636 | −<P> | |
| 637 | −<H3>4.5.2 - Arithmetic Operators</H3> | |
| 638 | −Lua supports the usual <A NAME="arithmetic operators">arithmetic operators</A>: | |
| 639 | −the binary <CODE>+</CODE> (addition), | |
| 640 | −<CODE>-</CODE> (subtraction), <CODE>*</CODE> (multiplication), | |
| 641 | −<CODE>/</CODE> (division), and <CODE>^</CODE> (exponentiation); | |
| 642 | −and unary <CODE>-</CODE> (negation). | |
| 645 | + | |
| 646 | +<p>A chunk is also a block (see <a href="#chunks">2.4.1</a>), | |
| 647 | +so local variables can be declared in a chunk outside any explicit block. | |
| 648 | +Such local variables die when the chunk ends. | |
| 649 | + | |
| 650 | +<p>The visibility rules for local variables are explained in <a href="#visibility">2.6</a>. | |
| 651 | + | |
| 652 | +<p><a name="expressions"><h2>2.5 - Expressions</h2></a> | |
| 653 | + | |
| 654 | +<p> | |
| 655 | +The basic expressions in Lua are the following: | |
| 656 | +<pre> | |
| 657 | + exp ::= prefixexp | |
| 658 | + exp ::= <b>nil</b> | <b>false</b> | <b>true</b> | |
| 659 | + exp ::= Number | |
| 660 | + exp ::= Literal | |
| 661 | + exp ::= function | |
| 662 | + exp ::= tableconstructor | |
| 663 | + prefixexp ::= var | functioncall | `<b>(</b>´ exp `<b>)</b>´ | |
| 664 | +</pre> | |
| 665 | + | |
| 666 | +<p>Numbers and literal strings are explained in <a href="#lexical">2.1</a>; | |
| 667 | +variables are explained in <a href="#variables">2.3</a>; | |
| 668 | +function definitions are explained in <a href="#func-def">2.5.8</a>; | |
| 669 | +function calls are explained in <a href="#functioncall">2.5.7</a>; | |
| 670 | +table constructors are explained in <a href="#tableconstructor">2.5.6</a>. | |
| 671 | + | |
| 672 | + | |
| 673 | +<p>An expression enclosed in parentheses always results in only one value. | |
| 674 | +Thus, | |
| 675 | +<code>(f(x,y,z))</code> is always a single value, | |
| 676 | +even if <code>f</code> returns several values. | |
| 677 | +(The value of <code>(f(x,y,z))</code> is the first value returned by <code>f</code> | |
| 678 | +or <B>nil</B> if <code>f</code> does not return any values.) | |
| 679 | + | |
| 680 | +<p>Expressions can also be built with arithmetic operators, relational operators, | |
| 681 | +and logical operators, all of which are explained below. | |
| 682 | + | |
| 683 | +<p><h3>2.5.1 - Arithmetic Operators</h3> | |
| 684 | +Lua supports the usual arithmetic operators: | |
| 685 | +the binary <code>+</code> (addition), | |
| 686 | +<code>-</code> (subtraction), <code>*</code> (multiplication), | |
| 687 | +<code>/</code> (division), and <code>^</code> (exponentiation); | |
| 688 | +and unary <code>-</code> (negation). | |
| 643 | 689 | If the operands are numbers, or strings that can be converted to |
| 644 | −numbers (according to the rules given in Section <A HREF="#coercion">4.2</A>), | |
| 690 | +numbers (see <a href="#coercion">2.2.1</a>), | |
| 645 | 691 | then all operations except exponentiation have the usual meaning. |
| 646 | −Otherwise, an appropriate tag method is called (see Section <A HREF="#tag-method">4.8</A>). | |
| 647 | −An exponentiation always calls a tag method. | |
| 648 | −The standard mathematical library redefines this method for numbers, | |
| 649 | −giving the expected meaning to <A NAME="exponentiation">exponentiation</A> | |
| 650 | −(see Section <A HREF="#mathlib">6.3</A>). | |
| 651 | −<P> | |
| 652 | −<H3>4.5.3 - Relational Operators</H3> | |
| 653 | −The <A NAME="relational operators">relational operators</A> in Lua are | |
| 654 | −<PRE> | |
| 655 | − == ~= < > <= >= | |
| 656 | −</PRE> | |
| 657 | −These operators return <B>nil</B> as false and a value different from <B>nil</B> as true. | |
| 658 | −<P> | |
| 659 | −Equality (<CODE>==</CODE>) first compares the tags of its operands. | |
| 660 | −If they are different, then the result is <B>nil</B>. | |
| 661 | −Otherwise, their values are compared. | |
| 692 | +Exponentiation calls a global function <code>__pow</code>; | |
| 693 | +otherwise, an appropriate metamethod is called (see <a href="#metatable">2.8</a>). | |
| 694 | +The standard mathematical library defines function <code>__pow</code>, | |
| 695 | +giving the expected meaning to exponentiation | |
| 696 | +(see <a href="#mathlib">5.5</a>). | |
| 697 | + | |
| 698 | +<p><a name="rel-ops"><h3>2.5.2 - Relational Operators</h3></a> | |
| 699 | +The relational operators in Lua are | |
| 700 | +<PRE> | |
| 701 | + == ~= < > <= >= | |
| 702 | +</PRE> | |
| 703 | +These operators always result in <B>false</B> or <B>true</B>. | |
| 704 | + | |
| 705 | +<p>Equality (<code>==</code>) first compares the type of its operands. | |
| 706 | +If the types are different, then the result is <B>false</B>. | |
| 707 | +Otherwise, the values of the operands are compared. | |
| 662 | 708 | Numbers and strings are compared in the usual way. |
| 663 | −Tables, userdata, and functions are compared by reference, | |
| 664 | −that is, two tables are considered equal only if they are the <EM>same</EM> table. | |
| 665 | −The operator <CODE>~=</CODE> is exactly the negation of equality (<CODE>==</CODE>). | |
| 666 | −<P> | |
| 667 | −The conversion rules of Section <A HREF="#coercion">4.2</A> | |
| 668 | −<EM>do not</EM> apply to equality comparisons. | |
| 669 | −Thus, <CODE>"0"==0</CODE> evaluates to <EM>false</EM>, | |
| 670 | −and <CODE>t[0]</CODE> and <CODE>t["0"]</CODE> denote different | |
| 709 | +Objects (tables, userdata, threads, and functions) | |
| 710 | +are compared by <em>reference</em>: | |
| 711 | +Two objects are considered equal only if they are the <em>same</em> object. | |
| 712 | +Every time you create a new object (a table, userdata, or function), | |
| 713 | +this new object is different from any previously existing object. | |
| 714 | + | |
| 715 | +<p>You can change the way that Lua compares tables and userdata | |
| 716 | +using the "eq" metamethod (see <a href="#metatable">2.8</a>). | |
| 717 | + | |
| 718 | +<p>The conversion rules of <a href="#coercion">2.2.1</a> | |
| 719 | +<em>do not</em> apply to equality comparisons. | |
| 720 | +Thus, <code>"0"==0</code> evaluates to <B>false</B>, | |
| 721 | +and <code>t[0]</code> and <code>t["0"]</code> denote different | |
| 671 | 722 | entries in a table. |
| 672 | −<P> | |
| 673 | −The order operators work as follows. | |
| 723 | + | |
| 724 | + | |
| 725 | +<p>The operator <code>~=</code> is exactly the negation of equality (<code>==</code>). | |
| 726 | + | |
| 727 | +<p>The order operators work as follows. | |
| 674 | 728 | If both arguments are numbers, then they are compared as such. |
| 675 | 729 | Otherwise, if both arguments are strings, |
| 676 | −then their values are compared using lexicographical order. | |
| 677 | −Otherwise, the ``lt'' tag method is called (see Section <A HREF="#tag-method">4.8</A>). | |
| 678 | −<P> | |
| 679 | −<H3>4.5.4 - Logical Operators</H3> | |
| 680 | −The <A NAME="logical operators">logical operators</A> in Lua are | |
| 681 | −<A NAME="and"></A><A NAME="or"></A><A NAME="not"></A> | |
| 730 | +then their values are compared according to the current locale. | |
| 731 | +Otherwise, Lua tries to call the "lt" or the "le" | |
| 732 | +metamethod (see <a href="#metatable">2.8</a>). | |
| 733 | + | |
| 734 | +<p><h3>2.5.3 - Logical Operators</h3> | |
| 735 | +The logical operators in Lua are | |
| 736 | + | |
| 682 | 737 | <PRE> |
| 683 | 738 | and or not |
| 684 | 739 | </PRE> |
| 685 | −Like the control structures, all logical operators | |
| 686 | −consider <B>nil</B> as false and anything else as true. | |
| 687 | −<P> | |
| 688 | −The conjunction operator <CODE>and</CODE> returns <B>nil</B> if its first argument is <B>nil</B>; | |
| 689 | −otherwise, it returns its second argument. | |
| 690 | −The disjunction operator <CODE>or</CODE> returns its first argument | |
| 691 | −if it is different from <B>nil</B>; | |
| 692 | −otherwise, it returns its second argument. | |
| 693 | −Both <CODE>and</CODE> and <CODE>or</CODE> use <A NAME="short-cut evaluation">short-cut evaluation</A>, | |
| 740 | +Like the control structures (see <a href="#control">2.4.4</a>), | |
| 741 | +all logical operators consider both <B>false</B> and <B>nil</B> as false | |
| 742 | +and anything else as true. | |
| 743 | + | |
| 744 | + | |
| 745 | +<p>The operator <b>not</b> always return <B>false</B> or <B>true</B>. | |
| 746 | + | |
| 747 | +<p>The conjunction operator <b>and</b> returns its first argument | |
| 748 | +if this value is <B>false</B> or <B>nil</B>; | |
| 749 | +otherwise, <b>and</b> returns its second argument. | |
| 750 | +The disjunction operator <b>or</b> returns its first argument | |
| 751 | +if this value is different from <B>nil</B> and <B>false</B>; | |
| 752 | +otherwise, <b>or</b> returns its second argument. | |
| 753 | +Both <b>and</b> and <b>or</b> use short-cut evaluation, | |
| 694 | 754 | that is, |
| 695 | 755 | the second operand is evaluated only if necessary. |
| 696 | −<P> | |
| 697 | −There are two useful Lua idioms that use logical operators. | |
| 698 | −The first idiom is | |
| 699 | −<PRE> | |
| 700 | − x = x or v | |
| 701 | −</PRE> | |
| 702 | −which is equivalent to | |
| 703 | −<PRE> | |
| 704 | − if x == nil then x = v end | |
| 705 | −</PRE> | |
| 706 | −This idiom sets <CODE>x</CODE> to a default value <CODE>v</CODE> when <CODE>x</CODE> is not set. | |
| 707 | −<P> | |
| 708 | −The second idiom is | |
| 709 | −<PRE> | |
| 710 | − x = a and b or c | |
| 711 | −</PRE> | |
| 712 | −which should be read as <CODE>x = (a and b) or c</CODE>. | |
| 713 | −This idiom is equivalent to | |
| 756 | +For example, | |
| 714 | 757 | <PRE> |
| 715 | − if a then x = b else x = c end | |
| 758 | + 10 or error() -> 10 | |
| 759 | + nil or "a" -> "a" | |
| 760 | + nil and 10 -> nil | |
| 761 | + false and error() -> false | |
| 762 | + false and nil -> false | |
| 763 | + false or nil -> nil | |
| 764 | + 10 and 20 -> 20 | |
| 716 | 765 | </PRE> |
| 717 | −provided that <CODE>b</CODE> is not <B>nil</B>. | |
| 718 | −<P> | |
| 719 | −<A NAME="concat"></A> | |
| 720 | −<H3>4.5.5 - Concatenation</H3> | |
| 721 | −The string <A NAME="concatenation">concatenation</A> operator in Lua is | |
| 722 | −denoted by two dots (`<A NAME=".."><TT>..</TT></A>'). | |
| 766 | + | |
| 767 | +<p><a name="concat"><h3>2.5.4 - Concatenation</h3></a> | |
| 768 | +The string concatenation operator in Lua is | |
| 769 | +denoted by two dots (`<code>..</code>´). | |
| 723 | 770 | If both operands are strings or numbers, then they are converted to |
| 724 | −strings according to the rules in Section <A HREF="#coercion">4.2</A>. | |
| 725 | −Otherwise, the ``concat'' tag method is called (see Section <A HREF="#tag-method">4.8</A>). | |
| 726 | −<P> | |
| 727 | −<H3>4.5.6 - Precedence</H3> | |
| 728 | −<A NAME="Operator precedence">Operator precedence</A> in Lua follows the table below, | |
| 729 | −from the lower to the higher priority: | |
| 730 | −<PRE> | |
| 731 | − and or | |
| 732 | − < > <= >= ~= == | |
| 771 | +strings according to the rules mentioned in <a href="#coercion">2.2.1</a>. | |
| 772 | +Otherwise, the "concat" metamethod is called (see <a href="#metatable">2.8</a>). | |
| 773 | + | |
| 774 | +<p><h3>2.5.5 - Precedence</h3> | |
| 775 | +Operator precedence in Lua follows the table below, | |
| 776 | +from lower to higher priority: | |
| 777 | +<PRE> | |
| 778 | + or | |
| 779 | + and | |
| 780 | + < > <= >= ~= == | |
| 733 | 781 | .. |
| 734 | 782 | + - |
| 735 | 783 | * / |
| 736 | 784 | not - (unary) |
| 737 | 785 | ^ |
| 738 | 786 | </PRE> |
| 739 | −All binary operators are left associative, | |
| 740 | −except for <CODE>^</CODE> (exponentiation), | |
| 741 | −which is right associative. | |
| 742 | −The pre-compiler may rearrange the order of evaluation of | |
| 743 | −associative operators (such as <CODE>..</CODE> or <CODE>+</CODE>), | |
| 744 | −as long as these optimizations do not change normal results. | |
| 745 | −However, these optimizations may change some results | |
| 746 | −if you define non-associative | |
| 747 | −tag methods for these operators. | |
| 748 | −<P> | |
| 749 | −<A NAME="tableconstructor"></A> | |
| 750 | −<H3>4.5.7 - Table Constructors</H3> | |
| 751 | −Table <A NAME="constructors">constructors</A> are expressions that create tables; | |
| 752 | −every time a constructor is evaluated, a new table is created. | |
| 787 | +As usual, you can use parentheses to change the precedences of an expression. | |
| 788 | +The concatenation (`<code>..</code>´) and exponentiation (`<code>^</code>´) | |
| 789 | +operators are right associative. | |
| 790 | +All other binary operators are left associative. | |
| 791 | + | |
| 792 | +<p><a name="tableconstructor"><h3>2.5.6 - Table Constructors</h3></a> | |
| 793 | +Table constructors are expressions that create tables. | |
| 794 | +Every time a constructor is evaluated, a new table is created. | |
| 753 | 795 | Constructors can be used to create empty tables, |
| 754 | 796 | or to create a table and initialize some of its fields. |
| 755 | 797 | The general syntax for constructors is |
| 756 | −<PRE> | |
| 757 | − tableconstructor ::= `<B>{</B>' fieldlist `<B>}</B>' | |
| 758 | − fieldlist ::= lfieldlist | ffieldlist | lfieldlist `<B>;</B>' ffieldlist | ffieldlist `<B>;</B>' lfieldlist | |
| 759 | − lfieldlist ::= [lfieldlist1] | |
| 760 | − ffieldlist ::= [ffieldlist1] | |
| 761 | −</PRE> | |
| 762 | −<P> | |
| 763 | −The form <EM>lfieldlist1</EM> is used to initialize lists: | |
| 764 | −<PRE> | |
| 765 | − lfieldlist1 ::= exp {`<B>,</B>' exp} [`<B>,</B>'] | |
| 766 | −</PRE> | |
| 767 | −The expressions in the list are assigned to consecutive numerical indices, | |
| 768 | −starting with 1. | |
| 769 | −For example, | |
| 770 | −<PRE> | |
| 771 | − a = {"v1", "v2", 34} | |
| 772 | −</PRE> | |
| 773 | −is equivalent to | |
| 774 | −<PRE> | |
| 775 | − do | |
| 776 | − local temp = {} | |
| 777 | − temp[1] = "v1" | |
| 778 | − temp[2] = "v2" | |
| 779 | − temp[3] = 34 | |
| 780 | − a = temp | |
| 781 | − end | |
| 782 | −</PRE> | |
| 783 | −<P> | |
| 784 | −The form <EM>ffieldlist1</EM> initializes other fields in a table: | |
| 785 | −<PRE> | |
| 786 | − ffieldlist1 ::= ffield {`<B>,</B>' ffield} [`<B>,</B>'] | |
| 787 | − ffield ::= `<B>[</B>' exp `<B>]</B>' `<B>=</B>' exp | name `<B>=</B>' exp | |
| 788 | −</PRE> | |
| 798 | +<pre> | |
| 799 | + tableconstructor ::= `<b>{</b>´ [fieldlist] `<b>}</b>´ | |
| 800 | + fieldlist ::= field {fieldsep field} [fieldsep] | |
| 801 | + field ::= `<b>[</b>´ exp `<b>]</b>´ `<b>=</b>´ exp | Name `<b>=</b>´ exp | exp | |
| 802 | + fieldsep ::= `<b>,</b>´ | `<b>;</b>´ | |
| 803 | +</pre> | |
| 804 | + | |
| 805 | +<p>Each field of the form <code>[exp1] = exp2</code> adds to the new table an entry | |
| 806 | +with key <code>exp1</code> and value <code>exp2</code>. | |
| 807 | +A field of the form <code>name = exp</code> is equivalent to | |
| 808 | +<code>["name"] = exp</code>. | |
| 809 | +Finally, fields of the form <code>exp</code> are equivalent to | |
| 810 | +<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers, | |
| 811 | +starting with 1. | |
| 812 | +Fields in the other formats do not affect this counting. | |
| 789 | 813 | For example, |
| 790 | 814 | <PRE> |
| 791 | − a = {[f(k)] = g(y), x = 1, y = 3, [0] = b+c} | |
| 815 | + a = {[f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45} | |
| 792 | 816 | </PRE> |
| 793 | 817 | is equivalent to |
| 794 | 818 | <PRE> |
| 795 | 819 | do |
| 796 | 820 | local temp = {} |
| 797 | − temp[f(k)] = g(y) | |
| 798 | − temp.x = 1 -- or temp["x"] = 1 | |
| 799 | − temp.y = 3 -- or temp["y"] = 3 | |
| 800 | − temp[0] = b+c | |
| 821 | + temp[f(1)] = g | |
| 822 | + temp[1] = "x" -- 1st exp | |
| 823 | + temp[2] = "y" -- 2nd exp | |
| 824 | + temp.x = 1 -- temp["x"] = 1 | |
| 825 | + temp[3] = f(x) -- 3rd exp | |
| 826 | + temp[30] = 23 | |
| 827 | + temp[4] = 45 -- 4th exp | |
| 801 | 828 | a = temp |
| 802 | 829 | end |
| 803 | 830 | </PRE> |
| 804 | −An expression like <CODE>{x = 1, y = 4}</CODE> is | |
| 805 | −in fact syntactic sugar for <CODE>{["x"] = 1, ["y"] = 4}</CODE>. | |
| 806 | −<P> | |
| 807 | −Both forms may have an optional trailing comma, | |
| 808 | −and can be used in the same constructor separated by | |
| 809 | −a semi-colon. | |
| 810 | −For example, all forms below are correct. | |
| 811 | −<PRE> | |
| 812 | − x = {;} | |
| 813 | − x = {"a", "b",} | |
| 814 | − x = {type="list"; "a", "b"} | |
| 815 | − x = {f(0), f(1), f(2),; n=3,} | |
| 816 | −</PRE> | |
| 817 | −<P> | |
| 818 | −<A NAME="functioncall"></A> | |
| 819 | −<H3>4.5.8 - Function Calls</H3> | |
| 820 | −A <A NAME="function call">function call</A> in Lua has the following syntax: | |
| 821 | −<PRE> | |
| 822 | − functioncall ::= varorfunc args | |
| 823 | −</PRE> | |
| 824 | −First, <EM>varorfunc</EM> is evaluated. | |
| 825 | −If its value has type <EM>function</EM>, | |
| 826 | −then this function is called, | |
| 831 | + | |
| 832 | +<p>If the last field in the list has the form <code>exp</code> | |
| 833 | +and the expression is a function call, | |
| 834 | +then all values returned by the call enter the list consecutively | |
| 835 | +(see <a href="#functioncall">2.5.7</a>). | |
| 836 | +To avoid this, | |
| 837 | +enclose the function call in parentheses (see <a href="#expressions">2.5</a>). | |
| 838 | + | |
| 839 | +<p>The field list may have an optional trailing separator, | |
| 840 | +as a convenience for machine-generated code. | |
| 841 | + | |
| 842 | +<p><a name="functioncall"><h3>2.5.7 - Function Calls</h3></a> | |
| 843 | +A function call in Lua has the following syntax: | |
| 844 | +<pre> | |
| 845 | + functioncall ::= prefixexp args | |
| 846 | +</pre> | |
| 847 | +In a function call, | |
| 848 | +first <em>prefixexp</em> and <em>args</em> are evaluated. | |
| 849 | +If the value of <em>prefixexp</em> has type <em>function</em>, | |
| 850 | +then that function is called | |
| 827 | 851 | with the given arguments. |
| 828 | −Otherwise, the ``function'' tag method is called, | |
| 829 | −having as first parameter the value of <EM>varorfunc</EM>, | |
| 830 | −and then the original call arguments | |
| 831 | −(see Section <A HREF="#tag-method">4.8</A>). | |
| 832 | −<P> | |
| 833 | −The form | |
| 834 | −<PRE> | |
| 835 | − functioncall ::= varorfunc `<B>:</B>' name args | |
| 836 | −</PRE> | |
| 837 | −can be used to call ``methods''. | |
| 838 | −A call <CODE>v:name(...)</CODE> | |
| 839 | −is syntactic sugar for <CODE>v.name(v, ...)</CODE>, | |
| 840 | −except that <CODE>v</CODE> is evaluated only once. | |
| 841 | −<P> | |
| 842 | −Arguments have the following syntax: | |
| 843 | −<PRE> | |
| 844 | − args ::= `<B>(</B>' [explist1] `<B>)</B>' | |
| 845 | − args ::= tableconstructor | |
| 846 | − args ::= literal | |
| 847 | − explist1 ::= {exp1 `<B>,</B>'} exp | |
| 848 | −</PRE> | |
| 852 | +Otherwise, its "call" metamethod is called, | |
| 853 | +having as first parameter the value of <em>prefixexp</em>, | |
| 854 | +followed by the original call arguments | |
| 855 | +(see <a href="#metatable">2.8</a>). | |
| 856 | + | |
| 857 | +<p>The form | |
| 858 | +<pre> | |
| 859 | + functioncall ::= prefixexp `<b>:</b>´ Name args | |
| 860 | +</pre> | |
| 861 | +can be used to call "methods". | |
| 862 | +A call <code>v:name(...)</code> | |
| 863 | +is syntactic sugar for <code>v.name(v,...)</code>, | |
| 864 | +except that <code>v</code> is evaluated only once. | |
| 865 | + | |
| 866 | +<p>Arguments have the following syntax: | |
| 867 | +<pre> | |
| 868 | + args ::= `<b>(</b>´ [explist1] `<b>)</b>´ | |
| 869 | + args ::= tableconstructor | |
| 870 | + args ::= Literal | |
| 871 | +</pre> | |
| 849 | 872 | All argument expressions are evaluated before the call. |
| 850 | −A call of the form <CODE>f{...}</CODE> is syntactic sugar for | |
| 851 | −<CODE>f({...})</CODE>, that is, | |
| 873 | +A call of the form <code>f{...}</code> is syntactic sugar for | |
| 874 | +<code>f({...})</code>, that is, | |
| 852 | 875 | the argument list is a single new table. |
| 853 | −A call of the form <CODE>f'...'</CODE> | |
| 854 | −(or <CODE>f"..."</CODE> or <CODE>f[[...]]</CODE>) is syntactic sugar for | |
| 855 | −<CODE>f('...')</CODE>, that is, | |
| 876 | +A call of the form <code>f'...'</code> | |
| 877 | +(or <code>f"..."</code> or <code>f[[...]]</code>) is syntactic sugar for | |
| 878 | +<code>f('...')</code>, that is, | |
| 856 | 879 | the argument list is a single literal string. |
| 857 | −<P> | |
| 858 | −Because a function can return any number of results | |
| 859 | −(see Section <A HREF="#return">4.4.3</A>), | |
| 860 | −the number of results must be adjusted before they are used (see Section <A HREF="#adjust">4.3</A>). | |
| 861 | −If the function is called as a statement (see Section <A HREF="#funcstat">4.4.5</A>), | |
| 862 | −then its return list is adjusted to 0, | |
| 880 | + | |
| 881 | +<p>Because a function can return any number of results | |
| 882 | +(see <a href="#control">2.4.4</a>), | |
| 883 | +the number of results must be adjusted before they are used. | |
| 884 | +If the function is called as a statement (see <a href="#funcstat">2.4.6</a>), | |
| 885 | +then its return list is adjusted to zero elements, | |
| 863 | 886 | thus discarding all returned values. |
| 864 | −If the function is called in a place that needs a single value | |
| 865 | −(syntactically denoted by the non-terminal <EM>exp1</EM>), | |
| 866 | −then its return list is adjusted to 1, | |
| 867 | −thus discarding all returned values but the first one. | |
| 868 | −If the function is called in a place that can hold many values | |
| 869 | −(syntactically denoted by the non-terminal <EM>exp</EM>), | |
| 870 | −then no adjustment is made. | |
| 871 | −The only places that can hold many values | |
| 872 | −is the last (or the only) expression in an assignment, | |
| 873 | −in an argument list, or in the <B>return</B> statement. | |
| 874 | −Here are some examples: | |
| 887 | +If the function is called inside another expression | |
| 888 | +or in the middle of a list of expressions, | |
| 889 | +then its return list is adjusted to one element, | |
| 890 | +thus discarding all returned values except the first one. | |
| 891 | +If the function is called as the last element of a list of expressions, | |
| 892 | +then no adjustment is made | |
| 893 | +(unless the call is enclosed in parentheses). | |
| 894 | + | |
| 895 | +<p>Here are some examples: | |
| 875 | 896 | <PRE> |
| 876 | 897 | f() -- adjusted to 0 results |
| 877 | 898 | g(f(), x) -- f() is adjusted to 1 result |
| 878 | 899 | g(x, f()) -- g gets x plus all values returned by f() |
| 879 | 900 | a,b,c = f(), x -- f() is adjusted to 1 result (and c gets nil) |
| 880 | − a,b,c = x, f() -- f() is adjusted to 2 | |
| 881 | − a,b,c = f() -- f() is adjusted to 3 | |
| 901 | + a,b,c = x, f() -- f() is adjusted to 2 results | |
| 902 | + a,b,c = f() -- f() is adjusted to 3 results | |
| 882 | 903 | return f() -- returns all values returned by f() |
| 883 | − return x,y,f() -- returns a, b, and all values returned by f() | |
| 904 | + return x,y,f() -- returns x, y, and all values returned by f() | |
| 905 | + {f()} -- creates a list with all values returned by f() | |
| 906 | + {f(), nil} -- f() is adjusted to 1 result | |
| 884 | 907 | </PRE> |
| 885 | −<P> | |
| 886 | −<A NAME="func-def"></A> | |
| 887 | −<H3>4.5.9 - <A NAME="Function Definitions</H3>">Function Definitions</H3></A> | |
| 888 | −<P> | |
| 889 | −The syntax for function definition is | |
| 908 | + | |
| 909 | +<p>If you enclose a function call in parentheses, | |
| 910 | +then it is adjusted to return exactly one value: | |
| 890 | 911 | <PRE> |
| 891 | − function ::= <B>function</B> `<B>(</B>' [parlist1] `<B>)</B>' block <B>end</B> | |
| 892 | − stat ::= <B>function</B> funcname `<B>(</B>' [parlist1] `<B>)</B>' block <B>end</B> | |
| 893 | − funcname ::= name | name `<B>.</B>' name | name `<B>:</B>' name | |
| 912 | + return x,y,(f()) -- returns x, y, and the first value from f() | |
| 913 | + {(f())} -- creates a table with exactly one element | |
| 914 | +</PRE> | |
| 915 | + | |
| 916 | +<p>As an exception to the free-format syntax of Lua, | |
| 917 | +you cannot put a line break before the `<code>(</code>´ in a function call. | |
| 918 | +That restriction avoids some ambiguities in the language. | |
| 919 | +If you write | |
| 920 | +<PRE> | |
| 921 | + a = f | |
| 922 | + (g).x(a) | |
| 923 | +</PRE> | |
| 924 | +Lua would read that as <code>a = f(g).x(a)</code>. | |
| 925 | +So, if you want two statements, you must add a semi-colon between them. | |
| 926 | +If you actually want to call <code>f</code>, | |
| 927 | +you must remove the line break before <code>(g)</code>. | |
| 928 | + | |
| 929 | +<p>A call of the form <code>return</code> <em>functioncall</em> is called | |
| 930 | +a <em>tail call</em>. | |
| 931 | +Lua implements <em>proper tail calls</em> | |
| 932 | +(or <em>proper tail recursion</em>): | |
| 933 | +In a tail call, | |
| 934 | +the called function reuses the stack entry of the calling function. | |
| 935 | +Therefore, there is no limit on the number of nested tail calls that | |
| 936 | +a program can execute. | |
| 937 | +However, a tail call erases any debug information about the | |
| 938 | +calling function. | |
| 939 | +Note that a tail call only happens with a particular syntax, | |
| 940 | +where the <b>return</b> has one single function call as argument; | |
| 941 | +this syntax makes the calling function returns exactly | |
| 942 | +the returns of the called function. | |
| 943 | +So, all the following examples are not tails calls: | |
| 944 | +<PRE> | |
| 945 | + return (f(x)) -- results adjusted to 1 | |
| 946 | + return 2 * f(x) | |
| 947 | + return x, f(x) -- adicional results | |
| 948 | + f(x); return -- results discarded | |
| 949 | + return x or f(x) -- results adjusted to 1 | |
| 894 | 950 | </PRE> |
| 951 | + | |
| 952 | +<p><a name="func-def"><h3>2.5.8 - Function Definitions</h3></a> | |
| 953 | + | |
| 954 | +<p>The syntax for function definition is | |
| 955 | +<pre> | |
| 956 | + function ::= <b>function</b> funcbody | |
| 957 | + funcbody ::= `<b>(</b>´ [parlist1] `<b>)</b>´ block <b>end</b> | |
| 958 | +</pre> | |
| 959 | + | |
| 960 | +<p>The following syntactic sugar simplifies function definitions: | |
| 961 | +<pre> | |
| 962 | + stat ::= <b>function</b> funcname funcbody | |
| 963 | + stat ::= <b>local</b> <b>function</b> Name funcbody | |
| 964 | + funcname ::= Name {`<b>.</b>´ Name} [`<b>:</b>´ Name] | |
| 965 | +</pre> | |
| 895 | 966 | The statement |
| 896 | 967 | <PRE> |
| 897 | 968 | function f () ... end |
| 898 | 969 | </PRE> |
| 899 | −is just syntactic sugar for | |
| 970 | +translates to | |
| 900 | 971 | <PRE> |
| 901 | 972 | f = function () ... end |
| 902 | 973 | </PRE> |
| 903 | −and the statement | |
| 974 | +The statement | |
| 975 | +<PRE> | |
| 976 | + function t.a.b.c.f () ... end | |
| 977 | +</PRE> | |
| 978 | +translates to | |
| 904 | 979 | <PRE> |
| 905 | − function v.f () ... end | |
| 980 | + t.a.b.c.f = function () ... end | |
| 906 | 981 | </PRE> |
| 907 | −is syntactic sugar for | |
| 982 | +The statement | |
| 908 | 983 | <PRE> |
| 909 | − v.f = function () ... end | |
| 984 | + local function f () ... end | |
| 910 | 985 | </PRE> |
| 911 | −<P> | |
| 912 | −A function definition is an executable expression, | |
| 913 | −whose value has type <EM>function</EM>. | |
| 986 | +translates to | |
| 987 | +<PRE> | |
| 988 | + local f; f = function () ... end | |
| 989 | +</PRE> | |
| 990 | + | |
| 991 | +<p>A function definition is an executable expression, | |
| 992 | +whose value has type <em>function</em>. | |
| 914 | 993 | When Lua pre-compiles a chunk, |
| 915 | 994 | all its function bodies are pre-compiled too. |
| 916 | 995 | Then, whenever Lua executes the function definition, |
| 917 | −its upvalues are fixed (see Section <A HREF="#upvalue">4.6</A>), | |
| 918 | −and the function is <EM>instantiated</EM> (or <EM>closed</EM>). | |
| 919 | −This function instance (or <EM>closure</EM>) | |
| 996 | +the function is <em>instantiated</em> (or <em>closed</em>). | |
| 997 | +This function instance (or <em>closure</em>) | |
| 920 | 998 | is the final value of the expression. |
| 921 | 999 | Different instances of the same function |
| 922 | −may have different upvalues. | |
| 923 | −<P> | |
| 924 | −Parameters act as local variables, | |
| 925 | −initialized with the argument values: | |
| 926 | −<PRE> | |
| 927 | − parlist1 ::= `<B>...</B>' | |
| 928 | − parlist1 ::= name {`<B>,</B>' name} [`<B>,</B>' `<B>...</B>'] | |
| 929 | −</PRE> | |
| 930 | −<A NAME="vararg"></A> | |
| 1000 | +may refer to different external local variables | |
| 1001 | +and may have different environment tables. | |
| 931 | 1002 | |
| 1003 | +<p>Parameters act as local variables that are | |
| 1004 | +initialized with the argument values: | |
| 1005 | +<pre> | |
| 1006 | + parlist1 ::= namelist [`<b>,</b>´ `<b>...</b>´] | |
| 1007 | + parlist1 ::= `<b>...</b>´ | |
| 1008 | +</pre> | |
| 932 | 1009 | When a function is called, |
| 933 | −the list of <A NAME="arguments">arguments</A> is adjusted to | |
| 934 | −the length of the list of parameters (see Section <A HREF="#adjust">4.3</A>), | |
| 935 | −unless the function is a <A NAME="vararg function"><EM>vararg function</EM></A>, | |
| 1010 | +the list of arguments is adjusted to | |
| 1011 | +the length of the list of parameters, | |
| 1012 | +unless the function is a variadic or <em>vararg function</em>, | |
| 936 | 1013 | which is |
| 937 | −indicated by three dots (`<CODE>...</CODE>') at the end of its parameter list. | |
| 1014 | +indicated by three dots (`<code>...</code>´) at the end of its parameter list. | |
| 938 | 1015 | A vararg function does not adjust its argument list; |
| 939 | 1016 | instead, it collects all extra arguments into an implicit parameter, |
| 940 | −called <A NAME="arg"><TT>arg</TT></A>. | |
| 941 | −The value of <CODE>arg</CODE> is a table, | |
| 942 | −with a field <CODE>n</CODE> whose value is the number of extra arguments, | |
| 943 | −and the extra arguments at positions 1, 2, ..., <CODE>n</CODE>. | |
| 944 | −<P> | |
| 945 | −As an example, consider the following definitions: | |
| 1017 | +called <code>arg</code>. | |
| 1018 | +The value of <a name="vararg"><code>arg</code></a> is a table, | |
| 1019 | +with a field <code>n</code> that holds the number of extra arguments | |
| 1020 | +and with the extra arguments at positions 1, 2, ..., <code>n</code>. | |
| 1021 | + | |
| 1022 | +<p>As an example, consider the following definitions: | |
| 946 | 1023 | <PRE> |
| 947 | 1024 | function f(a, b) end |
| 948 | 1025 | function g(a, b, ...) end |
| @@ -951,1200 +1028,1428 @@ As an example, consider the following definitions: · 2 unmodified lines | ||
| 951 | 1028 | Then, we have the following mapping from arguments to parameters: |
| 952 | 1029 | <PRE> |
| 953 | 1030 | CALL PARAMETERS |
| 954 | −<P> | |
| 1031 | + | |
| 955 | 1032 | f(3) a=3, b=nil |
| 956 | 1033 | f(3, 4) a=3, b=4 |
| 957 | 1034 | f(3, 4, 5) a=3, b=4 |
| 958 | 1035 | f(r(), 10) a=1, b=10 |
| 959 | 1036 | f(r()) a=1, b=2 |
| 960 | −<P> | |
| 1037 | + | |
| 961 | 1038 | g(3) a=3, b=nil, arg={n=0} |
| 962 | − g(3, 4) a=3, b=4, arg={n=0} | |
| 963 | − g(3, 4, 5, 8) a=3, b=4, arg={5, 8; n=2} | |
| 964 | − g(5, r()) a=5, b=1, arg={2, 3; n=2} | |
| 1039 | + g(3, 4) a=3, b=4, arg={n=0} | |
| 1040 | + g(3, 4, 5, 8) a=3, b=4, arg={5, 8; n=2} | |
| 1041 | + g(5, r()) a=5, b=1, arg={2, 3; n=2} | |
| 965 | 1042 | </PRE> |
| 966 | −<P> | |
| 967 | −Results are returned using the <B>return</B> statement (see Section <A HREF="#return">4.4.3</A>). | |
| 1043 | + | |
| 1044 | +<p>Results are returned using the <b>return</b> statement (see <a href="#control">2.4.4</a>). | |
| 968 | 1045 | If control reaches the end of a function |
| 969 | −without encountering a <B>return</B> statement, | |
| 1046 | +without encountering a <b>return</b> statement, | |
| 970 | 1047 | then the function returns with no results. |
| 971 | −<P> | |
| 972 | −The syntax | |
| 1048 | + | |
| 1049 | +<p>The <em>colon</em> syntax | |
| 1050 | +is used for defining <em>methods</em>, | |
| 1051 | +that is, functions that have an implicit extra parameter <code>self</code>. | |
| 1052 | +Thus, the statement | |
| 973 | 1053 | <PRE> |
| 974 | − funcname ::= name `<B>:</B>' name | |
| 1054 | + function t.a.b.c:f (...) ... end | |
| 975 | 1055 | </PRE> |
| 976 | −is used for defining <A NAME="methods"><EM>methods</EM></A>, | |
| 977 | −that is, functions that have an implicit extra parameter <A NAME="self"><TT>self</TT></A>. | |
| 978 | −<P> | |
| 979 | −The statement | |
| 1056 | +is syntactic sugar for | |
| 980 | 1057 | <PRE> |
| 981 | − function v:f (...) ... end | |
| 982 | −</PRE> | |
| 983 | −is just syntactic sugar for | |
| 984 | −<PRE> | |
| 985 | − v.f = function (self, ...) ... end | |
| 986 | −</PRE> | |
| 987 | −Note that the function gets an extra formal parameter called <CODE>self</CODE>. | |
| 988 | −<P> | |
| 989 | −<P> | |
| 990 | −<A NAME="upvalue"></A> | |
| 991 | −<A NAME="4.6"></A> | |
| 992 | −<H2>4.6 - Visibility and Upvalues</H2> | |
| 993 | −<A NAME="visibility"></A><A NAME="upvalues"></A> | |
| 994 | −<P> | |
| 995 | −A function body may refer to its own local variables | |
| 996 | −(which include its parameters) and to global variables, | |
| 997 | −as long as they are not <EM>shadowed</EM> by local | |
| 998 | −variables with the same name from enclosing functions. | |
| 999 | −A function <EM>cannot</EM> access a local | |
| 1000 | −variable from an enclosing function, | |
| 1001 | −since such variables may no longer exist when the function is called. | |
| 1002 | −However, a function may access the <EM>value</EM> of a local variable | |
| 1003 | −from an enclosing function, using <EM>upvalues</EM>, | |
| 1004 | −whose syntax is | |
| 1005 | −<PRE> | |
| 1006 | − upvalue ::= `<B>%</B>' name | |
| 1007 | −</PRE> | |
| 1008 | −<P> | |
| 1009 | −An upvalue is somewhat similar to a variable expression, | |
| 1010 | −but whose value is <EM>frozen</EM> when the function wherein it | |
| 1011 | −appears is instantiated. | |
| 1012 | −The name used in an upvalue may be the name of any variable visible | |
| 1013 | −at the point where the function is defined, | |
| 1014 | −that is, | |
| 1015 | −global variables and local variables | |
| 1016 | −from the <EM>immediately enclosing</EM> function. | |
| 1017 | −Note that when the upvalue is a table, | |
| 1018 | −only the <EM>reference</EM> to that table | |
| 1019 | −(which is the value of the upvalue) is frozen; | |
| 1020 | −the table contents can be changed at will. | |
| 1021 | −Using table values as upvalues is a technique for having | |
| 1022 | −writable but private state attached to functions. | |
| 1023 | −<P> | |
| 1024 | −Here are some examples: | |
| 1025 | −<PRE> | |
| 1026 | − a,b,c = 1,2,3 -- global variables | |
| 1027 | − local d | |
| 1028 | − function f (x) | |
| 1029 | − local b = {} -- x and b are local to f; b shadows the global b | |
| 1030 | − local g = function (a) | |
| 1031 | − local y -- a and y are local to g | |
| 1032 | − p = a -- OK, access local `a' | |
| 1033 | − p = c -- OK, access global `c' | |
| 1034 | − p = b -- ERROR: cannot access a variable in outer scope | |
| 1035 | − p = %b -- OK, access frozen value of `b' (local to `f') | |
| 1036 | − %b = 3 -- ERROR: cannot change an upvalue | |
| 1037 | − %b.x = 3 -- OK, change the table contents | |
| 1038 | − p = %c -- OK, access frozen value of global `c' | |
| 1039 | − p = %y -- ERROR: `y' is not visible where `g' is defined | |
| 1040 | − p = %d -- ERROR: `d' is not visible where `g' is defined | |
| 1041 | − end -- g | |
| 1042 | − end -- f | |
| 1043 | −</PRE> | |
| 1044 | −<P> | |
| 1045 | −<P> | |
| 1046 | −<A NAME="error"></A> | |
| 1047 | −<A NAME="4.7"></A> | |
| 1048 | −<H2>4.7 - Error Handling</H2> | |
| 1049 | −<P> | |
| 1050 | −Because Lua is an extension language, | |
| 1058 | + t.a.b.c.f = function (self, ...) ... end | |
| 1059 | +</PRE> | |
| 1060 | + | |
| 1061 | +<p><a name="visibility"><h2>2.6 - Visibility Rules</h2></a> | |
| 1062 | + | |
| 1063 | + | |
| 1064 | +<p>Lua is a lexically scoped language. | |
| 1065 | +The scope of variables begins at the first statement <em>after</em> | |
| 1066 | +their declaration and lasts until the end of the innermost block that | |
| 1067 | +includes the declaration. | |
| 1068 | +For instance: | |
| 1069 | +<PRE> | |
| 1070 | + x = 10 -- global variable | |
| 1071 | + do -- new block | |
| 1072 | + local x = x -- new `x', with value 10 | |
| 1073 | + print(x) --> 10 | |
| 1074 | + x = x+1 | |
| 1075 | + do -- another block | |
| 1076 | + local x = x+1 -- another `x' | |
| 1077 | + print(x) --> 12 | |
| 1078 | + end | |
| 1079 | + print(x) --> 11 | |
| 1080 | + end | |
| 1081 | + print(x) --> 10 (the global one) | |
| 1082 | +</PRE> | |
| 1083 | +Notice that, in a declaration like <code>local x = x</code>, | |
| 1084 | +the new <code>x</code> being declared is not in scope yet, | |
| 1085 | +and so the second <code>x</code> refers to the outside variable. | |
| 1086 | + | |
| 1087 | +<p>Because of the lexical scoping rules, | |
| 1088 | +local variables can be freely accessed by functions | |
| 1089 | +defined inside their scope. | |
| 1090 | +For instance: | |
| 1091 | +<PRE> | |
| 1092 | + local counter = 0 | |
| 1093 | + function inc (x) | |
| 1094 | + counter = counter + x | |
| 1095 | + return counter | |
| 1096 | + end | |
| 1097 | +</PRE> | |
| 1098 | +A local variable used by an inner function is called | |
| 1099 | +an <em>upvalue</em>, or <em>external local variable</em>, | |
| 1100 | +inside the inner function. | |
| 1101 | + | |
| 1102 | +<p>Notice that each execution of a <b>local</b> statement | |
| 1103 | +defines new local variables. | |
| 1104 | +Consider the following example: | |
| 1105 | +<PRE> | |
| 1106 | + a = {} | |
| 1107 | + local x = 20 | |
| 1108 | + for i=1,10 do | |
| 1109 | + local y = 0 | |
| 1110 | + a[i] = function () y=y+1; return x+y end | |
| 1111 | + end | |
| 1112 | +</PRE> | |
| 1113 | +The loop creates ten closures | |
| 1114 | +(that is, ten instances of the anonymous function). | |
| 1115 | +Each of these closures uses a different <code>y</code> variable, | |
| 1116 | +while all of them share the same <code>x</code>. | |
| 1117 | + | |
| 1118 | +<p><a name="error"><h2>2.7 - Error Handling</h2></a> | |
| 1119 | + | |
| 1120 | +<p>Because Lua is an extension language, | |
| 1051 | 1121 | all Lua actions start from C code in the host program |
| 1052 | −calling a function from the Lua library. | |
| 1122 | +calling a function from the Lua library (see <a href="#lua_pcall">3.15</a>). | |
| 1053 | 1123 | Whenever an error occurs during Lua compilation or execution, |
| 1054 | −the function <CODE>_ERRORMESSAGE</CODE> is called <A NAME="_ERRORMESSAGE"></A> | |
| 1055 | −(provided it is different from <B>nil</B>), | |
| 1056 | −and then the corresponding function from the library | |
| 1057 | −(<CODE>lua_dofile</CODE>, <CODE>lua_dostring</CODE>, | |
| 1058 | −<CODE>lua_dobuffer</CODE>, or <CODE>lua_call</CODE>) | |
| 1059 | −is terminated, returning an error condition. | |
| 1060 | −<P> | |
| 1061 | −Memory allocation errors are an exception to the previous rule. | |
| 1062 | −When memory allocation fails, Lua may not be able to execute the | |
| 1063 | −<CODE>_ERRORMESSAGE</CODE> function. | |
| 1064 | −So, for this kind of error, Lua does not call | |
| 1065 | −the <CODE>_ERRORMESSAGE</CODE> function; | |
| 1066 | −instead, the corresponding function from the library | |
| 1067 | −returns immediately with a special error code (<CODE>LUA_ERRMEM</CODE>). | |
| 1068 | −This and other error codes are defined in <CODE>lua.h</CODE>; | |
| 1069 | −Section <A HREF="#luado">5.8</A>. | |
| 1070 | −<P> | |
| 1071 | −The only argument to <CODE>_ERRORMESSAGE</CODE> is a string | |
| 1072 | −describing the error. | |
| 1073 | −The default definition for | |
| 1074 | −this function calls <CODE>_ALERT</CODE>, <A NAME="_ALERT"></A> | |
| 1075 | −which prints the message to <CODE>stderr</CODE> (see Section <A HREF="#alert">6.1</A>). | |
| 1076 | −The standard I/O library redefines <CODE>_ERRORMESSAGE</CODE> | |
| 1077 | −and uses the debug facilities (see Section <A HREF="#debugI">7</A>) | |
| 1078 | −to print some extra information, | |
| 1079 | −such as a call stack traceback. | |
| 1080 | −<P> | |
| 1081 | −Lua code can explicitly generate an error by calling the | |
| 1082 | −function <CODE>error</CODE> (see Section <A HREF="#pdf-error">6.1</A>). | |
| 1083 | −Lua code can ``catch'' an error using the function | |
| 1084 | −<CODE>call</CODE> (see Section <A HREF="#pdf-call">6.1</A>). | |
| 1085 | −<P> | |
| 1086 | −<P> | |
| 1087 | −<A NAME="tag-method"></A> | |
| 1088 | −<A NAME="4.8"></A> | |
| 1089 | −<H2>4.8 - Tag Methods</H2> | |
| 1090 | −<P> | |
| 1091 | −Lua provides a powerful mechanism to extend its semantics, | |
| 1092 | −called <EM>tag methods</EM>. | |
| 1093 | −A tag method is a programmer-defined function | |
| 1094 | −that is called at specific key points during the execution of a Lua program, | |
| 1095 | −allowing the programmer to change the standard Lua behavior at these points. | |
| 1096 | −Each of these points is called an <A NAME="event"><EM>event</EM></A>. | |
| 1097 | −<P> | |
| 1098 | −The tag method called for any specific event is selected | |
| 1099 | −according to the tag of the values involved | |
| 1100 | −in the event (see Section <A HREF="#TypesSec">3</A>). | |
| 1101 | −The function <A NAME="settagmethod"><TT>settagmethod</TT></A> changes the tag method | |
| 1102 | −associated with a given pair <EM>(tag, event)</EM>. | |
| 1103 | −Its first parameter is the tag, the second parameter is the event name | |
| 1104 | −(a string; see below), | |
| 1105 | −and the third parameter is the new method (a function), | |
| 1106 | −or <B>nil</B> to restore the default behavior for the pair. | |
| 1107 | −The <CODE>settagmethod</CODE> function returns the previous tag method for that pair. | |
| 1108 | −A companion function <A NAME="gettagmethod"><TT>gettagmethod</TT></A> | |
| 1109 | −receives a tag and an event name and returns the | |
| 1110 | −current method associated with the pair. | |
| 1111 | −<P> | |
| 1112 | −Tag methods are called in the following events, | |
| 1113 | −identified by the given names. | |
| 1114 | −The semantics of tag methods is better explained by a Lua function | |
| 1115 | −describing the behavior of the interpreter at each event. | |
| 1116 | −This function not only shows when a tag method is called, | |
| 1117 | −but also its arguments, its results, and the default behavior. | |
| 1118 | −The code shown here is only <EM>illustrative</EM>; | |
| 1119 | −the real behavior is hard coded in the interpreter, | |
| 1120 | −and it is much more efficient than this simulation. | |
| 1121 | −All functions used in these descriptions | |
| 1122 | −(<CODE>rawget</CODE>, <CODE>tonumber</CODE>, <CODE>call</CODE>, etc.) | |
| 1123 | −are described in Section <A HREF="#predefined">6.1</A>. | |
| 1124 | −<P> | |
| 1125 | −<DL> | |
| 1126 | −<P> | |
| 1127 | −<DT><B>``add'':</B><DD><A NAME="add event"></A> | |
| 1128 | −called when a <CODE>+</CODE> operation is applied to non-numerical operands. | |
| 1129 | −<P> | |
| 1130 | −The function <CODE>getbinmethod</CODE> below defines how Lua chooses a tag method | |
| 1131 | −for a binary operation. | |
| 1132 | −First, Lua tries the first operand. | |
| 1133 | −If its tag does not define a tag method for the operation, | |
| 1134 | −then Lua tries the second operand. | |
| 1135 | −If it also fails, then it gets a tag method from tag 0. | |
| 1124 | +control returns to C, | |
| 1125 | +which can take appropriate measures | |
| 1126 | +(such as print an error message). | |
| 1127 | + | |
| 1128 | +<p>Lua code can explicitly generate an error by calling the | |
| 1129 | +<code>error</code> function (see <a href="#pdf-error">5.1</a>). | |
| 1130 | +If you need to catch errors in Lua, | |
| 1131 | +you can use the <code>pcall</code> function (see <a href="#pdf-pcall">5.1</a>). | |
| 1132 | + | |
| 1133 | +<p><a name="metatable"><h2>2.8 - Metatables</h2></a> | |
| 1134 | + | |
| 1135 | +<p>Every table and userdata object in Lua may have a <em>metatable</em>. | |
| 1136 | +This <em>metatable</em> is an ordinary Lua table | |
| 1137 | +that defines the behavior of the original table and userdata | |
| 1138 | +under certain special operations. | |
| 1139 | +You can change several aspects of the behavior | |
| 1140 | +of an object by setting specific fields in its metatable. | |
| 1141 | +For instance, when an object is the operand of an addition, | |
| 1142 | +Lua checks for a function in the field <code>"__add"</code> in its metatable. | |
| 1143 | +If it finds one, | |
| 1144 | +Lua calls that function to perform the addition. | |
| 1145 | + | |
| 1146 | +<p>We call the keys in a metatable <em>events</em> | |
| 1147 | +and the values <em>metamethods</em>. | |
| 1148 | +In the previous example, the event is <code>"add"</code> | |
| 1149 | +and the metamethod is the function that performs the addition. | |
| 1150 | + | |
| 1151 | +<p>You can query and change the metatable of an object | |
| 1152 | +through the <code>set/getmetatable</code> | |
| 1153 | +functions (see <a href="#pdf-getmetatable">5.1</a>). | |
| 1154 | + | |
| 1155 | +<p>A metatable may control how an object behaves in arithmetic operations, | |
| 1156 | +order comparisons, concatenation, and indexing. | |
| 1157 | +A metatable can also define a function to be called when a userdata | |
| 1158 | +is garbage collected. | |
| 1159 | +For each of those operations Lua associates a specific key | |
| 1160 | +called an <em>event</em>. | |
| 1161 | +When Lua performs one of those operations over a table or a userdata, | |
| 1162 | +it checks whether that object has a metatable with the corresponding event. | |
| 1163 | +If so, the value associated with that key (the <em>metamethod</em>) | |
| 1164 | +controls how Lua will perform the operation. | |
| 1165 | + | |
| 1166 | +<p>Metatables control the operations listed next. | |
| 1167 | +Each operation is identified by its corresponding name. | |
| 1168 | +The key for each operation is a string with its name prefixed by | |
| 1169 | +two underscores; | |
| 1170 | +for instance, the key for operation "add" is the | |
| 1171 | +string <code>"__add"</code>. | |
| 1172 | +The semantics of these operations is better explained by a Lua function | |
| 1173 | +describing how the interpreter executes that operation. | |
| 1174 | + | |
| 1175 | +<p>The code shown here in Lua is only illustrative; | |
| 1176 | +the real behavior is hard coded in the interpreter | |
| 1177 | +and it is much more efficient than this simulation. | |
| 1178 | +All functions used in these descriptions | |
| 1179 | +(<code>rawget</code>, <code>tonumber</code>, etc.) | |
| 1180 | +are described in <a href="#predefined">5.1</a>. | |
| 1181 | +In particular, to retrieve the metamethod of a given object, | |
| 1182 | +we use the expression | |
| 1136 | 1183 | <PRE> |
| 1137 | − function getbinmethod (op1, op2, event) | |
| 1138 | − return gettagmethod(tag(op1), event) or | |
| 1139 | − gettagmethod(tag(op2), event) or | |
| 1140 | − gettagmethod(0, event) | |
| 1141 | − end | |
| 1142 | −</PRE> | |
| 1143 | −Using this function, | |
| 1144 | −the tag method for the ``add'' event is | |
| 1145 | −<PRE> | |
| 1146 | − function add_event (op1, op2) | |
| 1147 | − local o1, o2 = tonumber(op1), tonumber(op2) | |
| 1148 | − if o1 and o2 then -- both operands are numeric | |
| 1149 | − return o1+o2 -- '+' here is the primitive 'add' | |
| 1150 | − else -- at least one of the operands is not numeric | |
| 1151 | − local tm = getbinmethod(op1, op2, "add") | |
| 1152 | − if tm then | |
| 1153 | − -- call the method with both operands and an extra | |
| 1154 | − -- argument with the event name | |
| 1155 | − return tm(op1, op2, "add") | |
| 1156 | − else -- no tag method available: default behavior | |
| 1157 | − error("unexpected type at arithmetic operation") | |
| 1158 | − end | |
| 1159 | − end | |
| 1160 | − end | |
| 1184 | + metatable(obj)[event] | |
| 1161 | 1185 | </PRE> |
| 1162 | −<P> | |
| 1163 | −<DT><B>``sub'':</B><DD><A NAME="sub event"></A> | |
| 1164 | −called when a <CODE>-</CODE> operation is applied to non-numerical operands. | |
| 1165 | −Behavior similar to the ``add'' event. | |
| 1166 | −<P> | |
| 1167 | −<DT><B>``mul'':</B><DD><A NAME="mul event"></A> | |
| 1168 | −called when a <CODE>*</CODE> operation is applied to non-numerical operands. | |
| 1169 | −Behavior similar to the ``add'' event. | |
| 1170 | −<P> | |
| 1171 | −<DT><B>``div'':</B><DD><A NAME="div event"></A> | |
| 1172 | −called when a <CODE>/</CODE> operation is applied to non-numerical operands. | |
| 1173 | −Behavior similar to the ``add'' event. | |
| 1174 | −<P> | |
| 1175 | −<DT><B>``pow'':</B><DD><A NAME="pow event"></A> | |
| 1176 | −called when a <CODE>^</CODE> operation (exponentiation) is applied, | |
| 1177 | −even for numerical operands. | |
| 1178 | −<PRE> | |
| 1179 | − function pow_event (op1, op2) | |
| 1180 | − local tm = getbinmethod(op1, op2, "pow") | |
| 1181 | − if tm then | |
| 1182 | − -- call the method with both operands and an extra | |
| 1183 | − -- argument with the event name | |
| 1184 | − return tm(op1, op2, "pow") | |
| 1185 | − else -- no tag method available: default behavior | |
| 1186 | − error("unexpected type at arithmetic operation") | |
| 1187 | − end | |
| 1188 | − end | |
| 1186 | +This should be read as | |
| 1187 | +<PRE> | |
| 1188 | + rawget(metatable(obj) or {}, event) | |
| 1189 | 1189 | </PRE> |
| 1190 | −<P> | |
| 1191 | −<DT><B>``unm'':</B><DD><A NAME="unm event"></A> | |
| 1192 | −called when a unary <CODE>-</CODE> operation is applied to a non-numerical operand. | |
| 1193 | −<PRE> | |
| 1194 | − function unm_event (op) | |
| 1195 | − local o = tonumber(op) | |
| 1196 | − if o then -- operand is numeric | |
| 1197 | − return -o -- '-' here is the primitive 'unm' | |
| 1198 | − else -- the operand is not numeric. | |
| 1199 | − -- Try to get a tag method from the operand; | |
| 1200 | − -- if it does not have one, try a "global" one (tag 0) | |
| 1201 | − local tm = gettagmethod(tag(op), "unm") or | |
| 1202 | − gettagmethod(0, "unm") | |
| 1203 | − if tm then | |
| 1204 | − -- call the method with the operand, nil, and an extra | |
| 1205 | − -- argument with the event name | |
| 1206 | − return tm(op, nil, "unm") | |
| 1207 | − else -- no tag method available: default behavior | |
| 1208 | − error("unexpected type at arithmetic operation") | |
| 1209 | − end | |
| 1210 | − end | |
| 1211 | − end | |
| 1190 | +That is, the access to a metamethod does not invoke other metamethods, | |
| 1191 | +and the access to objects with no metatables does not fail | |
| 1192 | +(it simply results in <B>nil</B>). | |
| 1193 | + | |
| 1194 | +<p><ul> | |
| 1195 | + | |
| 1196 | +<p><li><b>"add":</b> | |
| 1197 | +the <code>+</code> operation. | |
| 1198 | + | |
| 1199 | +<p>The function <code>getbinhandler</code> below defines how Lua chooses a handler | |
| 1200 | +for a binary operation. | |
| 1201 | +First, Lua tries the first operand. | |
| 1202 | +If its type does not define a handler for the operation, | |
| 1203 | +then Lua tries the second operand. | |
| 1204 | +<PRE> | |
| 1205 | + function getbinhandler (op1, op2, event) | |
| 1206 | + return metatable(op1)[event] or metatable(op2)[event] | |
| 1207 | + end | |
| 1208 | +</PRE> | |
| 1209 | +Using that function, | |
| 1210 | +the behavior of the <code>op1 + op2</code> is | |
| 1211 | +<PRE> | |
| 1212 | + function add_event (op1, op2) | |
| 1213 | + local o1, o2 = tonumber(op1), tonumber(op2) | |
| 1214 | + if o1 and o2 then -- both operands are numeric? | |
| 1215 | + return o1 + o2 -- `+' here is the primitive `add' | |
| 1216 | + else -- at least one of the operands is not numeric | |
| 1217 | + local h = getbinhandler(op1, op2, "__add") | |
| 1218 | + if h then | |
| 1219 | + -- call the handler with both operands | |
| 1220 | + return h(op1, op2) | |
| 1221 | + else -- no handler available: default behavior | |
| 1222 | + error("...") | |
| 1223 | + end | |
| 1224 | + end | |
| 1225 | + end | |
| 1212 | 1226 | </PRE> |
| 1213 | −<P> | |
| 1214 | −<DT><B>``lt'':</B><DD><A NAME="lt event"></A> | |
| 1215 | −called when an order operation is applied to non-numerical | |
| 1216 | −or non-string operands. | |
| 1217 | −It corresponds to the <CODE><</CODE> operator. | |
| 1218 | −<PRE> | |
| 1219 | − function lt_event (op1, op2) | |
| 1220 | − if type(op1) == "number" and type(op2) == "number" then | |
| 1221 | − return op1 < op2 -- numeric comparison | |
| 1222 | − elseif type(op1) == "string" and type(op2) == "string" then | |
| 1223 | − return op1 < op2 -- lexicographic comparison | |
| 1224 | − else | |
| 1225 | − local tm = getbinmethod(op1, op2, "lt") | |
| 1226 | − if tm then | |
| 1227 | − return tm(op1, op2, "lt") | |
| 1228 | − else | |
| 1229 | − error("unexpected type at comparison"); | |
| 1230 | − end | |
| 1231 | − end | |
| 1232 | − end | |
| 1227 | + | |
| 1228 | +<p><li><b>"sub":</b> | |
| 1229 | +the <code>-</code> operation. | |
| 1230 | +Behavior similar to the "add" operation. | |
| 1231 | + | |
| 1232 | +<p><li><b>"mul":</b> | |
| 1233 | +the <code>*</code> operation. | |
| 1234 | +Behavior similar to the "add" operation. | |
| 1235 | + | |
| 1236 | +<p><li><b>"div":</b> | |
| 1237 | +the <code>/</code> operation. | |
| 1238 | +Behavior similar to the "add" operation. | |
| 1239 | + | |
| 1240 | +<p><li><b>"pow":</b> | |
| 1241 | +the <code>^</code> (exponentiation) operation. | |
| 1242 | +<PRE> | |
| 1243 | + function pow_event (op1, op2) | |
| 1244 | + local o1, o2 = tonumber(op1), tonumber(op2) | |
| 1245 | + if o1 and o2 then -- both operands are numeric? | |
| 1246 | + return __pow(o1, o2) -- call global `__pow' | |
| 1247 | + else -- at least one of the operands is not numeric | |
| 1248 | + local h = getbinhandler(op1, op2, "__pow") | |
| 1249 | + if h then | |
| 1250 | + -- call the handler with both operands | |
| 1251 | + return h(op1, op2) | |
| 1252 | + else -- no handler available: default behavior | |
| 1253 | + error("...") | |
| 1254 | + end | |
| 1255 | + end | |
| 1256 | + end | |
| 1233 | 1257 | </PRE> |
| 1234 | −The other order operators use this tag method according to the | |
| 1235 | −usual equivalences: | |
| 1236 | −<PRE> | |
| 1237 | − a>b <=> b<a | |
| 1238 | − a<=b <=> not (b<a) | |
| 1239 | − a>=b <=> not (a<b) | |
| 1240 | −</PRE> | |
| 1241 | −<P> | |
| 1242 | −<DT><B>``concat'':</B><DD><A NAME="concatenation event"></A> | |
| 1243 | −called when a concatenation is applied to non-string operands. | |
| 1244 | −<PRE> | |
| 1245 | − function concat_event (op1, op2) | |
| 1246 | − if (type(op1) == "string" or type(op1) == "number") and | |
| 1247 | − (type(op2) == "string" or type(op2) == "number") then | |
| 1248 | − return op1..op2 -- primitive string concatenation | |
| 1249 | − else | |
| 1250 | − local tm = getbinmethod(op1, op2, "concat") | |
| 1251 | − if tm then | |
| 1252 | − return tm(op1, op2, "concat") | |
| 1253 | − else | |
| 1254 | − error("unexpected type for concatenation") | |
| 1255 | − end | |
| 1256 | − end | |
| 1257 | − end | |
| 1258 | + | |
| 1259 | +<p><li><b>"unm":</b> | |
| 1260 | +the unary <code>-</code> operation. | |
| 1261 | +<PRE> | |
| 1262 | + function unm_event (op) | |
| 1263 | + local o = tonumber(op) | |
| 1264 | + if o then -- operand is numeric? | |
| 1265 | + return -o -- `-' here is the primitive `unm' | |
| 1266 | + else -- the operand is not numeric. | |
| 1267 | + -- Try to get a handler from the operand | |
| 1268 | + local h = metatable(op).__unm | |
| 1269 | + if h then | |
| 1270 | + -- call the handler with the operand and nil | |
| 1271 | + return h(op, nil) | |
| 1272 | + else -- no handler available: default behavior | |
| 1273 | + error("...") | |
| 1274 | + end | |
| 1275 | + end | |
| 1276 | + end | |
| 1258 | 1277 | </PRE> |
| 1259 | −<P> | |
| 1260 | −<DT><B>``index'':</B><DD><A NAME="index event"></A> | |
| 1261 | −called when Lua tries to retrieve the value of an index | |
| 1262 | −not present in a table. | |
| 1263 | −See the ``gettable'' event for its semantics. | |
| 1264 | −<P> | |
| 1265 | −<DT><B>``getglobal'':</B><DD><A NAME="getglobal event"></A> | |
| 1266 | −called whenever Lua needs the value of a global variable. | |
| 1267 | −This method can only be set for <B>nil</B> and for tags | |
| 1268 | −created by <CODE>newtag</CODE>. | |
| 1269 | −Note that | |
| 1270 | −the tag is that of the <EM>current value</EM> of the global variable. | |
| 1271 | −<PRE> | |
| 1272 | − function getglobal (varname) | |
| 1273 | − -- access the table of globals | |
| 1274 | − local value = rawget(globals(), varname) | |
| 1275 | − local tm = gettagmethod(tag(value), "getglobal") | |
| 1276 | − if not tm then | |
| 1277 | − return value | |
| 1278 | − else | |
| 1279 | − return tm(varname, value) | |
| 1280 | − end | |
| 1281 | − end | |
| 1278 | + | |
| 1279 | +<p><li><b>"concat":</b> | |
| 1280 | +the <code>..</code> (concatenation) operation. | |
| 1281 | +<PRE> | |
| 1282 | + function concat_event (op1, op2) | |
| 1283 | + if (type(op1) == "string" or type(op1) == "number") and | |
| 1284 | + (type(op2) == "string" or type(op2) == "number") then | |
| 1285 | + return op1 .. op2 -- primitive string concatenation | |
| 1286 | + else | |
| 1287 | + local h = getbinhandler(op1, op2, "__concat") | |
| 1288 | + if h then | |
| 1289 | + return h(op1, op2) | |
| 1290 | + else | |
| 1291 | + error("...") | |
| 1292 | + end | |
| 1293 | + end | |
| 1294 | + end | |
| 1282 | 1295 | </PRE> |
| 1283 | −The function <CODE>getglobal</CODE> is defined in the basic library (see Section <A HREF="#predefined">6.1</A>). | |
| 1284 | −<P> | |
| 1285 | −<DT><B>``setglobal'':</B><DD><A NAME="setglobal event"></A> | |
| 1286 | −called whenever Lua assigns to a global variable. | |
| 1287 | −This method cannot be set for numbers, strings, and tables and | |
| 1288 | −userdata with the default tag. | |
| 1289 | −<PRE> | |
| 1290 | − function setglobal (varname, newvalue) | |
| 1291 | − local oldvalue = rawget(globals(), varname) | |
| 1292 | − local tm = gettagmethod(tag(oldvalue), "setglobal") | |
| 1293 | − if not tm then | |
| 1294 | − rawset(globals(), varname, newvalue) | |
| 1295 | − else | |
| 1296 | − tm(varname, oldvalue, newvalue) | |
| 1297 | − end | |
| 1296 | + | |
| 1297 | +<p><li><b>"eq":</b> | |
| 1298 | +the <code>==</code> operation. | |
| 1299 | +The function <code>getcomphandler</code> defines how Lua chooses a metamethod | |
| 1300 | +for comparison operators. | |
| 1301 | +A metamethod only is selected when both objects | |
| 1302 | +being compared have the same type | |
| 1303 | +and the same metamethod for the selected operation. | |
| 1304 | +<PRE> | |
| 1305 | + function getcomphandler (op1, op2, event) | |
| 1306 | + if type(op1) ~= type(op2) then return nil end | |
| 1307 | + local mm1 = metatable(op1)[event] | |
| 1308 | + local mm2 = metatable(op2)[event] | |
| 1309 | + if mm1 == mm2 then return mm1 else return nil end | |
| 1310 | + end | |
| 1311 | +</PRE> | |
| 1312 | +The "eq" event is defined as follows: | |
| 1313 | +<PRE> | |
| 1314 | + function eq_event (op1, op2) | |
| 1315 | + if type(op1) ~= type(op2) then -- diferent types? | |
| 1316 | + return false -- different objects | |
| 1317 | + end | |
| 1318 | + if op1 == op2 then -- primitive equal? | |
| 1319 | + return true -- objects are equal | |
| 1320 | + end | |
| 1321 | + -- try metamethod | |
| 1322 | + local h = getcomphandler(op1, op2, "__eq") | |
| 1323 | + if h then | |
| 1324 | + return h(op1, op2) | |
| 1325 | + else | |
| 1326 | + return false | |
| 1327 | + end | |
| 1328 | + end | |
| 1329 | +</PRE> | |
| 1330 | +<code>a ~= b</code> is equivalent to <code>not (a == b)</code>. | |
| 1331 | + | |
| 1332 | +<p><li><b>"lt":</b> | |
| 1333 | +the <code><</code> operation. | |
| 1334 | +<PRE> | |
| 1335 | + function lt_event (op1, op2) | |
| 1336 | + if type(op1) == "number" and type(op2) == "number" then | |
| 1337 | + return op1 < op2 -- numeric comparison | |
| 1338 | + elseif type(op1) == "string" and type(op2) == "string" then | |
| 1339 | + return op1 < op2 -- lexicographic comparison | |
| 1340 | + else | |
| 1341 | + local h = getcomphandler(op1, op2, "__lt") | |
| 1342 | + if h then | |
| 1343 | + return h(op1, op2) | |
| 1344 | + else | |
| 1345 | + error("..."); | |
| 1346 | + end | |
| 1347 | + end | |
| 1348 | + end | |
| 1349 | +</PRE> | |
| 1350 | +<code>a > b</code> is equivalent to <code>b < a</code>. | |
| 1351 | + | |
| 1352 | +<p><li><b>"le":</b> | |
| 1353 | +the <code><=</code> operation. | |
| 1354 | +<PRE> | |
| 1355 | + function le_event (op1, op2) | |
| 1356 | + if type(op1) == "number" and type(op2) == "number" then | |
| 1357 | + return op1 <= op2 -- numeric comparison | |
| 1358 | + elseif type(op1) == "string" and type(op2) == "string" then | |
| 1359 | + return op1 <= op2 -- lexicographic comparison | |
| 1360 | + else | |
| 1361 | + local h = getcomphandler(op1, op2, "__le") | |
| 1362 | + if h then | |
| 1363 | + return h(op1, op2) | |
| 1364 | + else | |
| 1365 | + h = getcomphandler(op1, op2, "__lt") | |
| 1366 | + if h then | |
| 1367 | + return not h(op2, op1) | |
| 1368 | + else | |
| 1369 | + error("..."); | |
| 1298 | 1370 | end |
| 1371 | + end | |
| 1372 | + end | |
| 1373 | + end | |
| 1374 | +</PRE> | |
| 1375 | +<code>a >= b</code> is equivalent to <code>b <= a</code>. | |
| 1376 | +Note that, in the absence of a "le" metamethod, | |
| 1377 | +Lua tries the "lt", assuming that <code>a <= b</code> is | |
| 1378 | +equivalent to <code>not (b < a)</code>. | |
| 1379 | + | |
| 1380 | +<p><li><b>"index":</b> | |
| 1381 | +The indexing access <code>table[key]</code>. | |
| 1382 | +<PRE> | |
| 1383 | + function gettable_event (table, key) | |
| 1384 | + local h | |
| 1385 | + if type(table) == "table" then | |
| 1386 | + local v = rawget(table, key) | |
| 1387 | + if v ~= nil then return v end | |
| 1388 | + h = metatable(table).__index | |
| 1389 | + if h == nil then return nil end | |
| 1390 | + else | |
| 1391 | + h = metatable(table).__index | |
| 1392 | + if h == nil then | |
| 1393 | + error("..."); | |
| 1394 | + end | |
| 1395 | + end | |
| 1396 | + if type(h) == "function" then | |
| 1397 | + return h(table, key) -- call the handler | |
| 1398 | + else return h[key] -- or repeat operation on it | |
| 1399 | + end | |
| 1299 | 1400 | </PRE> |
| 1300 | −The function <CODE>setglobal</CODE> is defined in the basic library (see Section <A HREF="#predefined">6.1</A>). | |
| 1301 | −<P> | |
| 1302 | −<DT><B>``gettable'':</B><DD><A NAME="gettable event"></A> | |
| 1303 | −called whenever Lua accesses an indexed variable. | |
| 1304 | −This method cannot be set for tables with the default tag. | |
| 1305 | −<PRE> | |
| 1306 | − function gettable_event (table, index) | |
| 1307 | − local tm = gettagmethod(tag(table), "gettable") | |
| 1308 | − if tm then | |
| 1309 | − return tm(table, index) | |
| 1310 | − elseif type(table) ~= "table" then | |
| 1311 | − error("indexed expression not a table"); | |
| 1312 | − else | |
| 1313 | − local v = rawget(table, index) | |
| 1314 | − tm = gettagmethod(tag(table), "index") | |
| 1315 | − if v == nil and tm then | |
| 1316 | − return tm(table, index) | |
| 1317 | − else | |
| 1318 | − return v | |
| 1319 | − end | |
| 1320 | − end | |
| 1321 | − end | |
| 1401 | + | |
| 1402 | +<p><li><b>"newindex":</b> | |
| 1403 | +The indexing assignment <code>table[key] = value</code>. | |
| 1404 | +<PRE> | |
| 1405 | + function settable_event (table, key, value) | |
| 1406 | + local h | |
| 1407 | + if type(table) == "table" then | |
| 1408 | + local v = rawget(table, key) | |
| 1409 | + if v ~= nil then rawset(table, key, value); return end | |
| 1410 | + h = metatable(table).__newindex | |
| 1411 | + if h == nil then rawset(table, key, value); return end | |
| 1412 | + else | |
| 1413 | + h = metatable(table).__newindex | |
| 1414 | + if h == nil then | |
| 1415 | + error("..."); | |
| 1416 | + end | |
| 1417 | + end | |
| 1418 | + if type(h) == "function" then | |
| 1419 | + return h(table, key,value) -- call the handler | |
| 1420 | + else h[key] = value -- or repeat operation on it | |
| 1421 | + end | |
| 1322 | 1422 | </PRE> |
| 1323 | −<P> | |
| 1324 | −<DT><B>``settable'':</B><DD><A NAME="settable event"></A> | |
| 1325 | −called when Lua assigns to an indexed variable. | |
| 1326 | −This method cannot be set for tables with the default tag. | |
| 1327 | −<PRE> | |
| 1328 | − function settable_event (table, index, value) | |
| 1329 | − local tm = gettagmethod(tag(table), "settable") | |
| 1330 | − if tm then | |
| 1331 | − tm(table, index, value) | |
| 1332 | − elseif type(table) ~= "table" then | |
| 1333 | − error("indexed expression not a table") | |
| 1334 | − else | |
| 1335 | − rawset(table, index, value) | |
| 1336 | − end | |
| 1337 | − end | |
| 1423 | + | |
| 1424 | +<p><li><b>"call":</b> | |
| 1425 | +called when Lua calls a value. | |
| 1426 | +<PRE> | |
| 1427 | + function function_event (func, ...) | |
| 1428 | + if type(func) == "function" then | |
| 1429 | + return func(unpack(arg)) -- primitive call | |
| 1430 | + else | |
| 1431 | + local h = metatable(func).__call | |
| 1432 | + if h then | |
| 1433 | + return h(func, unpack(arg)) | |
| 1434 | + else | |
| 1435 | + error("...") | |
| 1436 | + end | |
| 1437 | + end | |
| 1438 | + end | |
| 1338 | 1439 | </PRE> |
| 1339 | −<P> | |
| 1340 | −<DT><B>``function'':</B><DD><A NAME="function event"></A> | |
| 1341 | −called when Lua tries to call a non-function value. | |
| 1342 | −<PRE> | |
| 1343 | − function function_event (func, ...) | |
| 1344 | − if type(func) == "function" then | |
| 1345 | − return call(func, arg) | |
| 1346 | − else | |
| 1347 | − local tm = gettagmethod(tag(func), "function") | |
| 1348 | − if tm then | |
| 1349 | − for i=arg.n,1,-1 do | |
| 1350 | − arg[i+1] = arg[i] | |
| 1351 | − end | |
| 1352 | − arg.n = arg.n+1 | |
| 1353 | − arg[1] = func | |
| 1354 | − return call(tm, arg) | |
| 1355 | − else | |
| 1356 | − error("call expression not a function") | |
| 1357 | − end | |
| 1358 | − end | |
| 1359 | − end | |
| 1440 | + | |
| 1441 | +<p></ul> | |
| 1442 | + | |
| 1443 | +<p><a name="GC"><h2>2.9 - Garbage Collection</h2></a> | |
| 1444 | + | |
| 1445 | +<p>Lua does automatic memory management. | |
| 1446 | +That means that | |
| 1447 | +you do not have to worry about allocating memory for new objects | |
| 1448 | +and freeing it when the objects are no longer needed. | |
| 1449 | +Lua manages memory automatically by running | |
| 1450 | +a <em>garbage collector</em> from time to time | |
| 1451 | +to collect all <em>dead objects</em> | |
| 1452 | +(that is, those objects that are no longer accessible from Lua). | |
| 1453 | +All objects in Lua are subject to automatic management: | |
| 1454 | +tables, userdata, functions, threads, and strings. | |
| 1455 | + | |
| 1456 | +<p>Lua uses two numbers to control its garbage-collection cycles. | |
| 1457 | +One number counts how many bytes of dynamic memory Lua is using; | |
| 1458 | +the other is a threshold. | |
| 1459 | +When the number of bytes crosses the threshold, | |
| 1460 | +Lua runs the garbage collector, | |
| 1461 | +which reclaims the memory of all dead objects. | |
| 1462 | +The byte counter is adjusted, | |
| 1463 | +and then the threshold is reset to twice the new value of the byte counter. | |
| 1464 | + | |
| 1465 | +<p>Through the C API, you can query those numbers | |
| 1466 | +and change the threshold (see <a href="#GC-API">3.7</a>). | |
| 1467 | +Setting the threshold to zero actually forces an immediate | |
| 1468 | +garbage-collection cycle, | |
| 1469 | +while setting it to a huge number effectively stops the garbage collector. | |
| 1470 | +Using Lua code you have a more limited control over garbage-collection cycles, | |
| 1471 | +through the <code>gcinfo</code> and <code>collectgarbage</code> functions | |
| 1472 | +(see <a href="#predefined">5.1</a>). | |
| 1473 | + | |
| 1474 | +<p><h3>2.9.1 - Garbage-Collection Metamethods</h3> | |
| 1475 | + | |
| 1476 | +<p>Using the C API, | |
| 1477 | +you can set garbage-collector metamethods for userdata (see <a href="#metatable">2.8</a>). | |
| 1478 | +These metamethods are also called <em>finalizers</em>. | |
| 1479 | +Finalizers allow you to coordinate Lua's garbage collection | |
| 1480 | +with external resource management | |
| 1481 | +(such as closing files, network or database connections, | |
| 1482 | +or freeing your own memory). | |
| 1483 | + | |
| 1484 | +<p>Free userdata with a field <code>__gc</code> in their metatables are not | |
| 1485 | +collected immediately by the garbage collector. | |
| 1486 | +Instead, Lua puts them in a list. | |
| 1487 | +After the collection, | |
| 1488 | +Lua does the equivalent of the following function | |
| 1489 | +for each userdata in that list: | |
| 1490 | +<PRE> | |
| 1491 | + function gc_event (udata) | |
| 1492 | + local h = metatable(udata).__gc | |
| 1493 | + if h then | |
| 1494 | + h(udata) | |
| 1495 | + end | |
| 1496 | + end | |
| 1360 | 1497 | </PRE> |
| 1361 | −<P> | |
| 1362 | −<DT><B>``gc'':</B><DD><A NAME="gc event"></A> | |
| 1363 | −called when Lua is ``garbage collecting'' a userdata. | |
| 1364 | −This tag method can be set only from C, | |
| 1365 | −and cannot be set for a userdata with the default tag. | |
| 1366 | −For each userdata to be collected, | |
| 1367 | −Lua does the equivalent of the following function: | |
| 1368 | −<PRE> | |
| 1369 | − function gc_event (obj) | |
| 1370 | − local tm = gettagmethod(tag(obj), "gc") | |
| 1371 | − if tm then | |
| 1372 | − tm(obj) | |
| 1373 | − end | |
| 1374 | − end | |
| 1498 | + | |
| 1499 | +<p>At the end of each garbage-collection cycle, | |
| 1500 | +the finalizers for userdata are called in <em>reverse</em> | |
| 1501 | +order of their creation, | |
| 1502 | +among those collected in that cycle. | |
| 1503 | +That is, the first finalizer to be called is the one associated | |
| 1504 | +with the userdata created last in the program. | |
| 1505 | + | |
| 1506 | +<p><a name="weak-table"><h3>2.9.2 - Weak Tables</h3></a> | |
| 1507 | + | |
| 1508 | +<p>A <em>weak table</em> is a table whose elements are | |
| 1509 | +<em>weak references</em>. | |
| 1510 | +A weak reference is ignored by the garbage collector. | |
| 1511 | +In other words, | |
| 1512 | +if the only references to an object are weak references, | |
| 1513 | +then the garbage collector will collect that object. | |
| 1514 | + | |
| 1515 | +<p>A weak table can have weak keys, weak values, or both. | |
| 1516 | +A table with weak keys allows the collection of its keys, | |
| 1517 | +but prevents the collection of its values. | |
| 1518 | +A table with both weak keys and weak values allows the collection of | |
| 1519 | +both keys and values. | |
| 1520 | +In any case, if either the key or the value is collected, | |
| 1521 | +the whole pair is removed from the table. | |
| 1522 | +The weakness of a table is controlled by the value of the | |
| 1523 | +<code>__mode</code> field of its metatable. | |
| 1524 | +If the <code>__mode</code> field is a string containing the character `<code>k</code>´, | |
| 1525 | +the keys in the table are weak. | |
| 1526 | +If <code>__mode</code> contains `<code>v</code>´, | |
| 1527 | +the values in the table are weak. | |
| 1528 | + | |
| 1529 | +<p>After you use a table as a metatable, | |
| 1530 | +you should not change the value of its field <code>__mode</code>. | |
| 1531 | +Otherwise, the weak behavior of the tables controlled by this | |
| 1532 | +metatable is undefined. | |
| 1533 | + | |
| 1534 | +<p><a name="coroutine"><h2>2.10 - Coroutines</h2></a> | |
| 1535 | + | |
| 1536 | +<p>Lua supports coroutines, | |
| 1537 | +also called <em>semi-coroutines</em> | |
| 1538 | +or <em>collaborative multithreading</em>. | |
| 1539 | +A coroutine in Lua represents an independent thread of execution. | |
| 1540 | +Unlike threads in multithread systems, however, | |
| 1541 | +a coroutine only suspends its execution by explicitly calling | |
| 1542 | +a yield function. | |
| 1543 | + | |
| 1544 | +<p>You create a coroutine with a call to <code>coroutine.create</code>. | |
| 1545 | +Its sole argument is a function | |
| 1546 | +that is the main function of the coroutine. | |
| 1547 | +The <code>create</code> function only creates a new coroutine and | |
| 1548 | +returns a handle to it (an object of type <em>thread</em>); | |
| 1549 | +it does not start the coroutine execution. | |
| 1550 | + | |
| 1551 | +<p>When you first call <code>coroutine.resume</code>, | |
| 1552 | +passing as argument the thread returned by <code>coroutine.create</code>, | |
| 1553 | +the coroutine starts its execution, | |
| 1554 | +at the first line of its main function. | |
| 1555 | +Extra arguments passed to <code>coroutine.resume</code> are given as | |
| 1556 | +parameters for the coroutine main function. | |
| 1557 | +After the coroutine starts running, | |
| 1558 | +it runs until it terminates or <em>yields</em>. | |
| 1559 | + | |
| 1560 | +<p>A coroutine can terminate its execution in two ways: | |
| 1561 | +Normally, when its main function returns | |
| 1562 | +(explicitly or implicitly, after the last instruction); | |
| 1563 | +and abnormally, if there is an unprotected error. | |
| 1564 | +In the first case, <code>coroutine.resume</code> returns <B>true</B>, | |
| 1565 | +plus any values returned by the coroutine main function. | |
| 1566 | +In case of errors, <code>coroutine.resume</code> returns <B>false</B> | |
| 1567 | +plus an error message. | |
| 1568 | + | |
| 1569 | +<p>A coroutine yields by calling <code>coroutine.yield</code>. | |
| 1570 | +When a coroutine yields, | |
| 1571 | +the corresponding <code>coroutine.resume</code> returns immediately, | |
| 1572 | +even if the yield happens inside nested function calls | |
| 1573 | +(that is, not in the main function, | |
| 1574 | +but in a function directly or indirectly called by the main function). | |
| 1575 | +In the case of a yield, <code>coroutine.resume</code> also returns <B>true</B>, | |
| 1576 | +plus any values passed to <code>coroutine.yield</code>. | |
| 1577 | +The next time you resume the same coroutine, | |
| 1578 | +it continues its execution from the point where it yielded, | |
| 1579 | +with the call to <code>coroutine.yield</code> returning any extra | |
| 1580 | +arguments passed to <code>coroutine.resume</code>. | |
| 1581 | + | |
| 1582 | +<p>The <code>coroutine.wrap</code> function creates a coroutine | |
| 1583 | +like <code>coroutine.create</code>, | |
| 1584 | +but instead of returning the coroutine itself, | |
| 1585 | +it returns a function that, when called, resumes the coroutine. | |
| 1586 | +Any arguments passed to that function | |
| 1587 | +go as extra arguments to resume. | |
| 1588 | +The function returns all the values returned by resume, | |
| 1589 | +except the first one (the boolean error code). | |
| 1590 | +Unlike <code>coroutine.resume</code>, | |
| 1591 | +this function does not catch errors; | |
| 1592 | +any error is propagated to the caller. | |
| 1593 | + | |
| 1594 | +<p>As an example, | |
| 1595 | +consider the next code: | |
| 1596 | +<PRE> | |
| 1597 | +function foo1 (a) | |
| 1598 | + print("foo", a) | |
| 1599 | + return coroutine.yield(2*a) | |
| 1600 | +end | |
| 1601 | + | |
| 1602 | +co = coroutine.create(function (a,b) | |
| 1603 | + print("co-body", a, b) | |
| 1604 | + local r = foo1(a+1) | |
| 1605 | + print("co-body", r) | |
| 1606 | + local r, s = coroutine.yield(a+b, a-b) | |
| 1607 | + print("co-body", r, s) | |
| 1608 | + return b, "end" | |
| 1609 | +end) | |
| 1610 | + | |
| 1611 | +a, b = coroutine.resume(co, 1, 10) | |
| 1612 | +print("main", a, b) | |
| 1613 | +a, b, c = coroutine.resume(co, "r") | |
| 1614 | +print("main", a, b, c) | |
| 1615 | +a, b, c = coroutine.resume(co, "x", "y") | |
| 1616 | +print("main", a, b, c) | |
| 1617 | +a, b = coroutine.resume(co, "x", "y") | |
| 1618 | +print("main", a, b) | |
| 1619 | +</PRE> | |
| 1620 | +When you run it, it produces the following output: | |
| 1621 | +<PRE> | |
| 1622 | +co-body 1 10 | |
| 1623 | +foo 2 | |
| 1624 | +main true 4 | |
| 1625 | +co-body r | |
| 1626 | +main true 11 -9 | |
| 1627 | +co-body x y | |
| 1628 | +main true 10 end | |
| 1629 | +main false cannot resume dead coroutine | |
| 1375 | 1630 | </PRE> |
| 1376 | −In a garbage-collection cycle, | |
| 1377 | −the tag methods for userdata are called in <EM>reverse</EM> order of tag creation, | |
| 1378 | −that is, the first tag methods to be called are those associated | |
| 1379 | −with the last tag created in the program. | |
| 1380 | −Moreover, at the end of the cycle, | |
| 1381 | −Lua does the equivalent of the call <CODE>gc_event(nil)</CODE>. | |
| 1382 | −<P> | |
| 1383 | −</DL> | |
| 1384 | −<P> | |
| 1385 | −<P> | |
| 1386 | −<P> | |
| 1387 | −<P> | |
| 1388 | −<!-- ====================================================================== --> | |
| 1389 | −<HR> | |
| 1390 | −<A NAME="5."></A> | |
| 1391 | −<H1>5 - The Application Program Interface</H1> | |
| 1392 | −<A NAME="C API"></A> | |
| 1393 | −This section describes the API for Lua, that is, | |
| 1631 | + | |
| 1632 | +<p> | |
| 1633 | +<a name="API"><h1>3 - The Application Program Interface</h1></a> | |
| 1634 | + | |
| 1635 | + | |
| 1636 | +<p>This section describes the C API for Lua, that is, | |
| 1394 | 1637 | the set of C functions available to the host program to communicate |
| 1395 | 1638 | with Lua. |
| 1396 | 1639 | All API functions and related types and constants |
| 1397 | −are declared in the header file <CODE>lua.h</CODE>. | |
| 1398 | −<P> | |
| 1399 | −Even when we use the term ``function'', | |
| 1400 | −any facility in the API may be provided as a <EM>macro</EM> instead. | |
| 1401 | −All such macros use each of its arguments exactly once, | |
| 1640 | +are declared in the header file <code>lua.h</code>. | |
| 1641 | + | |
| 1642 | +<p>Even when we use the term "function", | |
| 1643 | +any facility in the API may be provided as a <em>macro</em> instead. | |
| 1644 | +All such macros use each of its arguments exactly once | |
| 1645 | +(except for the first argument, which is always a Lua state), | |
| 1402 | 1646 | and so do not generate hidden side-effects. |
| 1403 | −<P> | |
| 1404 | −<P> | |
| 1405 | −<A NAME="mangstate"></A> | |
| 1406 | −<A NAME="5.1"></A> | |
| 1407 | −<H2>5.1 - States</H2> | |
| 1408 | −<P> | |
| 1409 | −The Lua library is fully reentrant: | |
| 1410 | −it does not have any global variables. | |
| 1411 | −<A NAME="state"></A> | |
| 1647 | + | |
| 1648 | +<p><a name="mangstate"><h2>3.1 - States</h2></a> | |
| 1649 | + | |
| 1650 | +<p>The Lua library is fully reentrant: | |
| 1651 | +it has no global variables. | |
| 1652 | + | |
| 1412 | 1653 | The whole state of the Lua interpreter |
| 1413 | −(global variables, stack, tag methods, etc.) | |
| 1414 | −is stored in a dynamically allocated structure of type <CODE>lua_State</CODE>; <A NAME="lua_State"></A> | |
| 1415 | −this state must be passed as the first argument to | |
| 1416 | −every function in the library (except <CODE>lua_open</CODE> below). | |
| 1417 | −<P> | |
| 1418 | −Before calling any API function, | |
| 1419 | −you must create a state by calling | |
| 1420 | −<A NAME="lua_open"></A> | |
| 1421 | −<PRE> | |
| 1422 | − lua_State *lua_open (int stacksize); | |
| 1423 | −</PRE> | |
| 1424 | −The sole argument to this function is the stack size for the interpreter. | |
| 1425 | −(Each function call needs one stack position for each argument, local variable, | |
| 1426 | −and temporary value, plus one position for book-keeping. | |
| 1427 | −The stack must also have some 20 extra positions available. | |
| 1428 | −For very small implementations, without recursive functions, | |
| 1429 | −a stack size of 100 should be enough.) | |
| 1430 | −If <CODE>stacksize</CODE> is zero, | |
| 1431 | −then a default size of 1024 is used. | |
| 1432 | −<P> | |
| 1433 | −To release a state created with <CODE>lua_open</CODE>, call | |
| 1434 | −<A NAME="lua_close"></A> | |
| 1654 | +(global variables, stack, etc.) | |
| 1655 | +is stored in a dynamically allocated structure of type <code>lua_State</code>. | |
| 1656 | + | |
| 1657 | +A pointer to this state must be passed as the first argument to | |
| 1658 | +every function in the library, except to <code>lua_open</code>, | |
| 1659 | +which creates a Lua state from scratch. | |
| 1660 | + | |
| 1661 | +<p>Before calling any API function, | |
| 1662 | +you must create a state by calling <code>lua_open</code>: | |
| 1663 | +<PRE> | |
| 1664 | + lua_State *lua_open (void); | |
| 1665 | +</PRE> | |
| 1666 | + | |
| 1667 | + | |
| 1668 | +<p>To release a state created with <code>lua_open</code>, call <code>lua_close</code>: | |
| 1435 | 1669 | <PRE> |
| 1436 | 1670 | void lua_close (lua_State *L); |
| 1437 | 1671 | </PRE> |
| 1438 | −This function destroys all objects in the given Lua environment | |
| 1439 | −(calling the corresponding garbage-collection tag methods, if any) | |
| 1672 | + | |
| 1673 | +This function destroys all objects in the given Lua state | |
| 1674 | +(calling the corresponding garbage-collection metamethods, if any) | |
| 1440 | 1675 | and frees all dynamic memory used by that state. |
| 1441 | −Usually, you do not need to call this function, | |
| 1442 | −because all resources are naturally released when your program ends. | |
| 1676 | +On several platforms, you may not need to call this function, | |
| 1677 | +because all resources are naturally released when the host program ends. | |
| 1443 | 1678 | On the other hand, |
| 1444 | −long-running programs - | |
| 1445 | −like a daemon or a web server - | |
| 1679 | +long-running programs, | |
| 1680 | +such as a daemon or a web server, | |
| 1446 | 1681 | might need to release states as soon as they are not needed, |
| 1447 | −to avoid growing too big. | |
| 1448 | −<P> | |
| 1449 | −With the exception of <CODE>lua_open</CODE>, | |
| 1450 | −all functions in the Lua API need a state as their first argument. | |
| 1451 | −<P> | |
| 1452 | −<P> | |
| 1453 | −<A NAME="5.2"></A> | |
| 1454 | −<H2>5.2 - The Stack and Indices</H2> | |
| 1455 | −<P> | |
| 1456 | −Lua uses a <EM>stack</EM> to pass values to and from C. | |
| 1682 | +to avoid growing too large. | |
| 1683 | + | |
| 1684 | +<p><h2>3.2 - The Stack and Indices</h2> | |
| 1685 | + | |
| 1686 | +<p>Lua uses a <em>virtual stack</em> to pass values to and from C. | |
| 1457 | 1687 | Each element in this stack represents a Lua value |
| 1458 | −(nil, number, string, etc.). | |
| 1459 | −<P> | |
| 1460 | −For convenience, | |
| 1688 | +(<B>nil</B>, number, string, etc.). | |
| 1689 | + | |
| 1690 | +<p>Whenever Lua calls C, the called function gets a new stack, | |
| 1691 | +which is independent of previous stacks and of stacks of | |
| 1692 | +C functions that are still active. | |
| 1693 | +That stack initially contains any arguments to the C function, | |
| 1694 | +and it is where the C function pushes its results (see <a href="#LuacallC">3.16</a>) | |
| 1695 | +to be returned to the caller. | |
| 1696 | + | |
| 1697 | +<p>For convenience, | |
| 1461 | 1698 | most query operations in the API do not follow a strict stack discipline. |
| 1462 | −Instead, they can refer to any element in the stack by using an <EM>index</EM>: | |
| 1463 | −A positive index represents an <EM>absolute</EM> stack position | |
| 1464 | −(starting at 1, not 0 as in C); | |
| 1465 | −a negative index represents an <EM>offset</EM> from the top of the stack. | |
| 1466 | −More specifically, if the stack has <EM>n</EM> elements, | |
| 1467 | −index 1 represents the first element | |
| 1468 | −(that is, the first element pushed onto the stack), | |
| 1699 | +Instead, they can refer to any element in the stack by using an <em>index</em>: | |
| 1700 | +A positive index represents an <em>absolute</em> stack position | |
| 1701 | +(starting at 1); | |
| 1702 | +a negative index represents an <em>offset</em> from the top of the stack. | |
| 1703 | +More specifically, if the stack has <em>n</em> elements, | |
| 1704 | +then index 1 represents the first element | |
| 1705 | +(that is, the element that was pushed onto the stack first) | |
| 1469 | 1706 | and |
| 1470 | −index <EM>n</EM> represents the last element; | |
| 1471 | −index <I>-1</I> also represents the last element | |
| 1472 | −(that is, the element at the top), | |
| 1473 | −and index <I>-n</I> represents the first element. | |
| 1474 | −We say that an index is <EM>valid</EM> | |
| 1475 | −if it lays between 1 and the stack top | |
| 1476 | −(that is, if <CODE>1 <= abs(index) <= top</CODE>). | |
| 1477 | −<A NAME="stack index"></A> <A NAME="valid index"></A> | |
| 1478 | −<P> | |
| 1479 | −At any time, you can get the index of the top element by calling | |
| 1480 | −<A NAME="lua_gettop"></A> | |
| 1707 | +index <em>n</em> represents the last element; | |
| 1708 | +index <em>-1</em> also represents the last element | |
| 1709 | +(that is, the element at the top) | |
| 1710 | +and index <em>-n</em> represents the first element. | |
| 1711 | +We say that an index is <em>valid</em> | |
| 1712 | +if it lies between 1 and the stack top | |
| 1713 | +(that is, if <code>1 <= abs(index) <= top</code>). | |
| 1714 | + | |
| 1715 | + | |
| 1716 | +<p>At any time, you can get the index of the top element by calling | |
| 1717 | +<code>lua_gettop</code>: | |
| 1481 | 1718 | <PRE> |
| 1482 | 1719 | int lua_gettop (lua_State *L); |
| 1483 | 1720 | </PRE> |
| 1484 | 1721 | Because indices start at 1, |
| 1485 | −the result of <CODE>lua_gettop</CODE> is equal to the number of elements in the stack | |
| 1722 | +the result of <code>lua_gettop</code> is equal to the number of elements in the stack | |
| 1486 | 1723 | (and so 0 means an empty stack). |
| 1487 | −<P> | |
| 1488 | −When you interact with Lua API, | |
| 1489 | −<EM>you are responsible for controlling stack overflow</EM>. | |
| 1490 | −The function <A NAME="lua_stackspace"></A> | |
| 1491 | −<PRE> | |
| 1492 | − int lua_stackspace (lua_State *L); | |
| 1493 | −</PRE> | |
| 1494 | −returns the number of stack positions still available. | |
| 1495 | −Whenever Lua calls C, <A NAME="LUA_MINSTACK"></A> | |
| 1496 | −it ensures that | |
| 1497 | −at least <CODE>LUA_MINSTACK</CODE> positions are still available. | |
| 1498 | −<CODE>LUA_MINSTACK</CODE> is defined in <CODE>lua.h</CODE> and is at least 16, | |
| 1499 | −and so you have to worry about stack space only | |
| 1500 | −when your code has loops pushing elements onto the stack. | |
| 1501 | −<P> | |
| 1502 | −Most query functions accept as indices any value inside the | |
| 1503 | −available stack space. | |
| 1504 | −Such indices are called <EM>acceptable indices</EM>. | |
| 1505 | −More formally, we can define an <A NAME="acceptable index"><EM>acceptable index</EM></A> | |
| 1506 | −as | |
| 1507 | −<PRE> | |
| 1508 | − (index < 0 && abs(index) <= top) || (index > 0 && index <= top + stackspace) | |
| 1509 | −</PRE> | |
| 1510 | −Note that 0 is not an acceptable index. | |
| 1511 | −<P> | |
| 1512 | −<A NAME="5.3"></A> | |
| 1513 | −<H2>5.3 - Stack Manipulation</H2> | |
| 1724 | + | |
| 1725 | +<p>When you interact with Lua API, | |
| 1726 | +<em>you are responsible for controlling stack overflow</em>. | |
| 1727 | +The function | |
| 1728 | +<PRE> | |
| 1729 | + int lua_checkstack (lua_State *L, int extra); | |
| 1730 | +</PRE> | |
| 1731 | + | |
| 1732 | +grows the stack size to <code>top + extra</code> elements; | |
| 1733 | +it returns false if it cannot grow the stack to that size. | |
| 1734 | +This function never shrinks the stack; | |
| 1735 | +if the stack is already larger than the new size, | |
| 1736 | +it is left unchanged. | |
| 1737 | + | |
| 1738 | +<p>Whenever Lua calls C, | |
| 1739 | +it ensures that at least <code>LUA_MINSTACK</code> positions are available. | |
| 1740 | +<code>LUA_MINSTACK</code> is defined in <code>lua.h</code> as 20, | |
| 1741 | +so that usually you do not have to worry about stack space | |
| 1742 | +unless your code has loops pushing elements onto the stack. | |
| 1743 | + | |
| 1744 | +<p>Most query functions accept as indices any value inside the | |
| 1745 | +available stack space, that is, indices up to the maximum stack size | |
| 1746 | +you have set through <code>lua_checkstack</code>. | |
| 1747 | +Such indices are called <em>acceptable indices</em>. | |
| 1748 | +More formally, we define an <em>acceptable index</em> | |
| 1749 | +as follows: | |
| 1750 | +<PRE> | |
| 1751 | + (index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace) | |
| 1752 | +</PRE> | |
| 1753 | +Note that 0 is never an acceptable index. | |
| 1754 | + | |
| 1755 | +<p>Unless otherwise noted, | |
| 1756 | +any function that accepts valid indices can also be called with | |
| 1757 | +<em>pseudo-indices</em>, | |
| 1758 | +which represent some Lua values that are accessible to the C code | |
| 1759 | +but are not in the stack. | |
| 1760 | +Pseudo-indices are used to access the global environment, | |
| 1761 | +the registry, and the upvalues of a C function (see <a href="#c-closure">3.17</a>). | |
| 1762 | + | |
| 1763 | +<p><h2>3.3 - Stack Manipulation</h2> | |
| 1514 | 1764 | The API offers the following functions for basic stack manipulation: |
| 1515 | −<A NAME="lua_settop"></A><A NAME="lua_pushvalue"></A> | |
| 1516 | −<A NAME="lua_remove"></A><A NAME="lua_insert"></A> | |
| 1517 | 1765 | <PRE> |
| 1518 | 1766 | void lua_settop (lua_State *L, int index); |
| 1519 | 1767 | void lua_pushvalue (lua_State *L, int index); |
| 1520 | 1768 | void lua_remove (lua_State *L, int index); |
| 1521 | 1769 | void lua_insert (lua_State *L, int index); |
| 1770 | + void lua_replace (lua_State *L, int index); | |
| 1522 | 1771 | </PRE> |
| 1523 | −<P> | |
| 1524 | −<CODE>lua_settop</CODE> accepts any acceptable index, | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
| 1775 | +<p><code>lua_settop</code> accepts any acceptable index, | |
| 1525 | 1776 | or 0, |
| 1526 | 1777 | and sets the stack top to that index. |
| 1527 | 1778 | If the new top is larger than the old one, |
| 1528 | 1779 | then the new elements are filled with <B>nil</B>. |
| 1529 | −If <CODE>index</CODE> is 0, then all stack elements are removed. | |
| 1530 | −A useful macro defined in the API is | |
| 1780 | +If <code>index</code> is 0, then all stack elements are removed. | |
| 1781 | +A useful macro defined in the <code>lua.h</code> is | |
| 1531 | 1782 | <PRE> |
| 1532 | − #define lua_pop(L,n) lua_settop(L, -(n)-1) | |
| 1783 | + #define lua_pop(L,n) lua_settop(L, -(n)-1) | |
| 1533 | 1784 | </PRE> |
| 1534 | −which pops <CODE>n</CODE> elements from the stack. | |
| 1535 | −<P> | |
| 1536 | −<CODE>lua_pushvalue</CODE> pushes onto the stack a <EM>copy</EM> of the element | |
| 1785 | + | |
| 1786 | +which pops <code>n</code> elements from the stack. | |
| 1787 | + | |
| 1788 | +<p><code>lua_pushvalue</code> pushes onto the stack a copy of the element | |
| 1537 | 1789 | at the given index. |
| 1538 | −<CODE>lua_remove</CODE> removes the element at the given position, | |
| 1539 | −shifting down the elements on top of that position to fill in the gap. | |
| 1540 | −<CODE>lua_insert</CODE> moves the top element into the given position, | |
| 1541 | −shifting up the elements on top of that position to open space. | |
| 1542 | −These functions accept only valid indices. | |
| 1543 | −As an example, if the stack starts as <CODE>10 20 30 40 50</CODE> | |
| 1544 | −(from bottom to top), | |
| 1790 | +<code>lua_remove</code> removes the element at the given position, | |
| 1791 | +shifting down the elements above that position to fill the gap. | |
| 1792 | +<code>lua_insert</code> moves the top element into the given position, | |
| 1793 | +shifting up the elements above that position to open space. | |
| 1794 | +<code>lua_replace</code> moves the top element into the given position, | |
| 1795 | +without shifting any element (therefore replacing the value at | |
| 1796 | +the given position). | |
| 1797 | +All these functions accept only valid indices. | |
| 1798 | +(You cannot call <code>lua_remove</code> or <code>lua_insert</code> with | |
| 1799 | +pseudo-indices, as they do not represent a stack position.) | |
| 1800 | + | |
| 1801 | +<p>As an example, if the stack starts as <code>10 20 30 40 50*</code> | |
| 1802 | +(from bottom to top; the `<code>*</code>´ marks the top), | |
| 1545 | 1803 | then |
| 1546 | 1804 | <PRE> |
| 1547 | − lua_pushvalue(L, 3) --> 10 20 30 40 50 30 | |
| 1548 | − lua_pushvalue(L, -1) --> 10 20 30 40 50 30 30 | |
| 1549 | − lua_remove(L, -3) --> 10 20 30 40 30 30 | |
| 1550 | − lua_remove(L, 6) --> 10 20 30 40 30 | |
| 1551 | − lua_insert(L, 1) --> 30 10 20 30 40 | |
| 1552 | − lua_insert(L, -1) --> 30 10 20 30 40 (no effect) | |
| 1553 | − lua_settop(L, -3) --> 30 10 20 | |
| 1554 | − lua_settop(L, 6) --> 30 10 20 nil nil nil | |
| 1555 | −</PRE> | |
| 1556 | −<P> | |
| 1557 | −<P> | |
| 1558 | −<A NAME="5.4"></A> | |
| 1559 | −<H2>5.4 - Querying the Stack</H2> | |
| 1560 | −<P> | |
| 1561 | −To check the type of a stack element, | |
| 1805 | + lua_pushvalue(L, 3) --> 10 20 30 40 50 30* | |
| 1806 | + lua_pushvalue(L, -1) --> 10 20 30 40 50 30 30* | |
| 1807 | + lua_remove(L, -3) --> 10 20 30 40 30 30* | |
| 1808 | + lua_remove(L, 6) --> 10 20 30 40 30* | |
| 1809 | + lua_insert(L, 1) --> 30 10 20 30 40* | |
| 1810 | + lua_insert(L, -1) --> 30 10 20 30 40* (no effect) | |
| 1811 | + lua_replace(L, 2) --> 30 40 20 30* | |
| 1812 | + lua_settop(L, -3) --> 30 40* | |
| 1813 | + lua_settop(L, 6) --> 30 40 nil nil nil nil* | |
| 1814 | +</PRE> | |
| 1815 | + | |
| 1816 | +<p><h2>3.4 - Querying the Stack</h2> | |
| 1817 | + | |
| 1818 | +<p>To check the type of a stack element, | |
| 1562 | 1819 | the following functions are available: |
| 1563 | −<A NAME="lua_type"></A><A NAME="lua_tag"></A> | |
| 1564 | −<A NAME="lua_isnil"></A><A NAME="lua_isnumber"></A><A NAME="lua_isstring"></A> | |
| 1565 | −<A NAME="lua_istable"></A> | |
| 1566 | −<A NAME="lua_isfunction"></A><A NAME="lua_iscfunction"></A><A NAME="lua_isuserdata"></A> | |
| 1567 | −<PRE> | |
| 1568 | − int lua_type (lua_State *L, int index); | |
| 1569 | − int lua_tag (lua_State *L, int index); | |
| 1570 | − int lua_isnil (lua_State *L, int index); | |
| 1571 | − int lua_isnumber (lua_State *L, int index); | |
| 1572 | − int lua_isstring (lua_State *L, int index); | |
| 1573 | − int lua_istable (lua_State *L, int index); | |
| 1574 | − int lua_isfunction (lua_State *L, int index); | |
| 1575 | − int lua_iscfunction (lua_State *L, int index); | |
| 1576 | − int lua_isuserdata (lua_State *L, int index); | |
| 1820 | +<PRE> | |
| 1821 | + int lua_type (lua_State *L, int index); | |
| 1822 | + int lua_isnil (lua_State *L, int index); | |
| 1823 | + int lua_isboolean (lua_State *L, int index); | |
| 1824 | + int lua_isnumber (lua_State *L, int index); | |
| 1825 | + int lua_isstring (lua_State *L, int index); | |
| 1826 | + int lua_istable (lua_State *L, int index); | |
| 1827 | + int lua_isfunction (lua_State *L, int index); | |
| 1828 | + int lua_iscfunction (lua_State *L, int index); | |
| 1829 | + int lua_isuserdata (lua_State *L, int index); | |
| 1830 | + int lua_islightuserdata (lua_State *L, int index); | |
| 1577 | 1831 | </PRE> |
| 1832 | + | |
| 1833 | + | |
| 1834 | + | |
| 1835 | + | |
| 1836 | + | |
| 1578 | 1837 | These functions can be called with any acceptable index. |
| 1579 | −<P> | |
| 1580 | −<CODE>lua_type</CODE> returns one of the following constants, | |
| 1581 | −according to the type of the given object: | |
| 1582 | −<CODE>LUA_TNIL</CODE>, | |
| 1583 | −<CODE>LUA_TNUMBER</CODE>, | |
| 1584 | −<CODE>LUA_TSTRING</CODE>, | |
| 1585 | −<CODE>LUA_TTABLE</CODE>, | |
| 1586 | −<CODE>LUA_TFUNCTION</CODE>, | |
| 1587 | −<CODE>LUA_TUSERDATA</CODE>. | |
| 1588 | −If the index is non-valid | |
| 1589 | −(that is, if that stack position is ``empty''), | |
| 1590 | −then <CODE>lua_type</CODE> returns <CODE>LUA_TNONE</CODE>. | |
| 1591 | −These constants can be converted to strings with | |
| 1592 | −<A NAME="lua_typename"></A> | |
| 1593 | −<PRE> | |
| 1594 | − const char *lua_typename (lua_State *L, int t); | |
| 1595 | −</PRE> | |
| 1596 | −where <CODE>t</CODE> is a type returned by <CODE>lua_type</CODE>. | |
| 1597 | −The strings returned by <CODE>lua_typename</CODE> are | |
| 1598 | −<CODE>"nil"</CODE>, <CODE>"number"</CODE>, <CODE>"string"</CODE>, <CODE>"table"</CODE>, | |
| 1599 | −<CODE>"function"</CODE>, <CODE>"userdata"</CODE>, and <CODE>"no value"</CODE>, | |
| 1600 | −<P> | |
| 1601 | −<CODE>lua_tag</CODE> returns the tag of a value, | |
| 1602 | −or <CODE>LUA_NOTAG</CODE> for a non-valid index. | |
| 1603 | −<P> | |
| 1604 | −The <CODE>lua_is*</CODE> functions return 1 if the object is compatible | |
| 1838 | + | |
| 1839 | +<p><code>lua_type</code> returns the type of a value in the stack, | |
| 1840 | +or <code>LUA_TNONE</code> for a non-valid index | |
| 1841 | +(that is, if that stack position is "empty"). | |
| 1842 | +The types returned by <code>lua_type</code> are coded by the following constants | |
| 1843 | +defined in <code>lua.h</code>: | |
| 1844 | +<code>LUA_TNIL</code>, | |
| 1845 | +<code>LUA_TNUMBER</code>, | |
| 1846 | +<code>LUA_TBOOLEAN</code>, | |
| 1847 | +<code>LUA_TSTRING</code>, | |
| 1848 | +<code>LUA_TTABLE</code>, | |
| 1849 | +<code>LUA_TFUNCTION</code>, | |
| 1850 | +<code>LUA_TUSERDATA</code>, | |
| 1851 | +<code>LUA_TTHREAD</code>, | |
| 1852 | +<code>LUA_TLIGHTUSERDATA</code>. | |
| 1853 | +The following function translates these constants to strings: | |
| 1854 | +<PRE> | |
| 1855 | + const char *lua_typename (lua_State *L, int type); | |
| 1856 | +</PRE> | |
| 1857 | + | |
| 1858 | + | |
| 1859 | +<p>The <code>lua_is*</code> functions return 1 if the object is compatible | |
| 1605 | 1860 | with the given type, and 0 otherwise. |
| 1861 | +<code>lua_isboolean</code> is an exception to this rule: | |
| 1862 | +It succeeds only for boolean values | |
| 1863 | +(otherwise it would be useless, | |
| 1864 | +as any value has a boolean value). | |
| 1606 | 1865 | They always return 0 for a non-valid index. |
| 1607 | −<CODE>lua_isnumber</CODE> accepts numbers and numerical strings, | |
| 1608 | −<CODE>lua_isstring</CODE> accepts strings and numbers (see Section <A HREF="#coercion">4.2</A>), | |
| 1609 | −and <CODE>lua_isfunction</CODE> accepts both Lua functions and C functions. | |
| 1866 | +<code>lua_isnumber</code> accepts numbers and numerical strings; | |
| 1867 | +<code>lua_isstring</code> accepts strings and numbers (see <a href="#coercion">2.2.1</a>); | |
| 1868 | +<code>lua_isfunction</code> accepts both Lua functions and C functions; | |
| 1869 | +and <code>lua_isuserdata</code> accepts both full and light userdata. | |
| 1610 | 1870 | To distinguish between Lua functions and C functions, |
| 1611 | −you should use <CODE>lua_iscfunction</CODE>. | |
| 1871 | +you can use <code>lua_iscfunction</code>. | |
| 1872 | +To distinguish between full and light userdata, | |
| 1873 | +you can use <code>lua_islightuserdata</code>. | |
| 1612 | 1874 | To distinguish between numbers and numerical strings, |
| 1613 | −you can use <CODE>lua_type</CODE>. | |
| 1614 | −<P> | |
| 1615 | −The API also has functions to compare two values in the stack: | |
| 1616 | −<A NAME="lua_equal"></A> | |
| 1617 | −<A NAME="lua_lessthan"></A> | |
| 1875 | +you can use <code>lua_type</code>. | |
| 1876 | + | |
| 1877 | +<p>The API also contains functions to compare two values in the stack: | |
| 1618 | 1878 | <PRE> |
| 1619 | 1879 | int lua_equal (lua_State *L, int index1, int index2); |
| 1880 | + int lua_rawequal (lua_State *L, int index1, int index2); | |
| 1620 | 1881 | int lua_lessthan (lua_State *L, int index1, int index2); |
| 1621 | 1882 | </PRE> |
| 1622 | −These functions are equivalent to their counterparts in Lua. | |
| 1623 | −Specifically, <CODE>lua_lessthan</CODE> is equivalent to the <CODE>lt_event</CODE> | |
| 1624 | −described in Section <A HREF="#tag-method">4.8</A>. | |
| 1625 | −Both functions return 0 if any of the indices are non-valid. | |
| 1626 | −<P> | |
| 1627 | −To translate a value in the stack to a specific C type, | |
| 1883 | + | |
| 1884 | +<code>lua_equal</code> and <code>lua_lessthan</code> | |
| 1885 | +are equivalent to their counterparts in Lua (see <a href="#rel-ops">2.5.2</a>). | |
| 1886 | +<code>lua_rawequal</code> compares the values for primitive equality, | |
| 1887 | +without metamethods. | |
| 1888 | +These functions return 0 (false) if any of the indices are non-valid. | |
| 1889 | + | |
| 1890 | +<p><a name="lua-to"><h2>3.5 - Getting Values from the Stack</h2></a> | |
| 1891 | + | |
| 1892 | +<p>To translate a value in the stack to a specific C type, | |
| 1628 | 1893 | you can use the following conversion functions: |
| 1629 | −<A NAME="lua_tonumber"></A><A NAME="lua_tostring"></A><A NAME="lua_strlen"></A> | |
| 1630 | −<A NAME="lua_tocfunction"></A><A NAME="lua_touserdata"></A> | |
| 1631 | 1894 | <PRE> |
| 1632 | − double lua_tonumber (lua_State *L, int index); | |
| 1895 | + int lua_toboolean (lua_State *L, int index); | |
| 1896 | + lua_Number lua_tonumber (lua_State *L, int index); | |
| 1633 | 1897 | const char *lua_tostring (lua_State *L, int index); |
| 1634 | 1898 | size_t lua_strlen (lua_State *L, int index); |
| 1635 | 1899 | lua_CFunction lua_tocfunction (lua_State *L, int index); |
| 1636 | 1900 | void *lua_touserdata (lua_State *L, int index); |
| 1901 | + lua_State *lua_tothread (lua_State *L, int index); | |
| 1902 | + void *lua_topointer (lua_State *L, int index); | |
| 1637 | 1903 | </PRE> |
| 1904 | + | |
| 1905 | + | |
| 1906 | + | |
| 1638 | 1907 | These functions can be called with any acceptable index. |
| 1639 | 1908 | When called with a non-valid index, |
| 1640 | 1909 | they act as if the given value had an incorrect type. |
| 1641 | −<P> | |
| 1642 | −<CODE>lua_tonumber</CODE> converts the value at the given index | |
| 1643 | −to a floating-point number. | |
| 1644 | −This value must be a number or a string convertible to number | |
| 1645 | −(see Section <A HREF="#coercion">4.2</A>); otherwise, <CODE>lua_tonumber</CODE> returns 0. | |
| 1646 | −<P> | |
| 1647 | −<CODE>lua_tostring</CODE> converts a Lua value to a string | |
| 1648 | −(<CODE>const char*</CODE>). | |
| 1649 | −This value must be a string or a number; | |
| 1650 | −otherwise, the function returns <CODE>NULL</CODE>. | |
| 1651 | −This function returns a pointer to a string inside the Lua environment. | |
| 1652 | −Those strings always have a zero (<CODE>'\0'</CODE>) after their last character (as in C), | |
| 1653 | −but may contain other zeros in their body. | |
| 1910 | + | |
| 1911 | +<p><code>lua_toboolean</code> converts the Lua value at the given index | |
| 1912 | +to a C "boolean" value (0 or 1). | |
| 1913 | +Like all tests in Lua, <code>lua_toboolean</code> returns 1 for any Lua value | |
| 1914 | +different from <B>false</B> and <B>nil</B>; | |
| 1915 | +otherwise it returns 0. | |
| 1916 | +It also returns 0 when called with a non-valid index. | |
| 1917 | +(If you want to accept only real boolean values, | |
| 1918 | +use <code>lua_isboolean</code> to test the type of the value.) | |
| 1919 | + | |
| 1920 | +<p><code>lua_tonumber</code> converts the Lua value at the given index | |
| 1921 | +to a number (by default, <code>lua_Number</code> is <code>double</code>). | |
| 1922 | + | |
| 1923 | +The Lua value must be a number or a string convertible to number | |
| 1924 | +(see <a href="#coercion">2.2.1</a>); otherwise, <code>lua_tonumber</code> returns 0. | |
| 1925 | + | |
| 1926 | +<p><code>lua_tostring</code> converts the Lua value at the given index to a string | |
| 1927 | +(<code>const char*</code>). | |
| 1928 | +The Lua value must be a string or a number; | |
| 1929 | +otherwise, the function returns <code>NULL</code>. | |
| 1930 | +If the value is a number, | |
| 1931 | +then <code>lua_tostring</code> also | |
| 1932 | +<em>changes the actual value in the stack to a string</em>. | |
| 1933 | +(This change confuses <code>lua_next</code> | |
| 1934 | +when <code>lua_tostring</code> is applied to keys.) | |
| 1935 | +<code>lua_tostring</code> returns a fully aligned pointer | |
| 1936 | +to a string inside the Lua state. | |
| 1937 | +This string always has a zero (<code>'\0'</code>) | |
| 1938 | +after its last character (as in C), | |
| 1939 | +but may contain other zeros in its body. | |
| 1654 | 1940 | If you do not know whether a string may contain zeros, |
| 1655 | −you should use <CODE>lua_strlen</CODE> to get its actual length. | |
| 1941 | +you can use <code>lua_strlen</code> to get its actual length. | |
| 1656 | 1942 | Because Lua has garbage collection, |
| 1657 | −there is no guarantee that the pointer returned by <CODE>lua_tostring</CODE> | |
| 1658 | −will be valid after the respective value is removed from the stack. | |
| 1659 | −<P> | |
| 1660 | −<CODE>lua_tocfunction</CODE> converts a value in the stack to a C function. | |
| 1943 | +there is no guarantee that the pointer returned by <code>lua_tostring</code> | |
| 1944 | +will be valid after the corresponding value is removed from the stack. | |
| 1945 | +If you need the string after the current function returns, | |
| 1946 | +then you should duplicate it or put it into the registry (see <a href="#registry">3.18</a>). | |
| 1947 | + | |
| 1948 | +<p><code>lua_tocfunction</code> converts a value in the stack to a C function. | |
| 1661 | 1949 | This value must be a C function; |
| 1662 | −otherwise, <CODE>lua_tocfunction</CODE> returns <CODE>NULL</CODE>. | |
| 1663 | −The type <CODE>lua_CFunction</CODE> is explained in Section <A HREF="#LuacallC">5.13</A>. | |
| 1664 | −<P> | |
| 1665 | −<CODE>lua_touserdata</CODE> converts a value to <CODE>void*</CODE>. | |
| 1666 | −This value must have type <EM>userdata</EM>; | |
| 1667 | −otherwise, <CODE>lua_touserdata</CODE> returns <CODE>NULL</CODE>. | |
| 1668 | −<P> | |
| 1669 | −<P> | |
| 1670 | −<P> | |
| 1671 | −<A NAME="5.5"></A> | |
| 1672 | −<H2>5.5 - Pushing values onto the Stack</H2> | |
| 1673 | −<P> | |
| 1674 | −The API has the following functions to | |
| 1950 | +otherwise, <code>lua_tocfunction</code> returns <code>NULL</code>. | |
| 1951 | +The type <code>lua_CFunction</code> is explained in <a href="#LuacallC">3.16</a>. | |
| 1952 | + | |
| 1953 | +<p><code>lua_tothread</code> converts a value in the stack to a Lua thread | |
| 1954 | +(represented as <code>lua_State *</code>). | |
| 1955 | +This value must be a thread; | |
| 1956 | +otherwise, <code>lua_tothread</code> returns <code>NULL</code>. | |
| 1957 | + | |
| 1958 | +<p><code>lua_topointer</code> converts a value in the stack to a generic | |
| 1959 | +C pointer (<code>void *</code>). | |
| 1960 | +The value may be a userdata, a table, a thread, or a function; | |
| 1961 | +otherwise, <code>lua_topointer</code> returns <code>NULL</code>. | |
| 1962 | +Lua ensures that different objects of the | |
| 1963 | +same type return different pointers. | |
| 1964 | +There is no direct way to convert the pointer back to its original value. | |
| 1965 | +Typically this function is used for debug information. | |
| 1966 | + | |
| 1967 | +<p><code>lua_touserdata</code> is explained in <a href="#userdata">3.8</a>. | |
| 1968 | + | |
| 1969 | +<p><a name="pushing"><h2>3.6 - Pushing Values onto the Stack</h2></a> | |
| 1970 | + | |
| 1971 | +<p>The API has the following functions to | |
| 1675 | 1972 | push C values onto the stack: |
| 1676 | −<A NAME="lua_pushnumber"></A><A NAME="lua_pushlstring"></A><A NAME="lua_pushstring"></A> | |
| 1677 | −<A NAME="lua_pushcfunction"></A><A NAME="lua_pushusertag"></A> | |
| 1678 | −<A NAME="pushing"></A> | |
| 1679 | −<A NAME="lua_pushnil"></A><A NAME="lua_pushuserdata"></A> | |
| 1680 | −<PRE> | |
| 1681 | − void lua_pushnumber (lua_State *L, double n); | |
| 1682 | − void lua_pushlstring (lua_State *L, const char *s, size_t len); | |
| 1683 | − void lua_pushstring (lua_State *L, const char *s); | |
| 1684 | − void lua_pushusertag (lua_State *L, void *u, int tag); | |
| 1685 | − void lua_pushnil (lua_State *L); | |
| 1686 | − void lua_pushcfunction (lua_State *L, lua_CFunction f); | |
| 1973 | +<PRE> | |
| 1974 | + void lua_pushboolean (lua_State *L, int b); | |
| 1975 | + void lua_pushnumber (lua_State *L, lua_Number n); | |
| 1976 | + void lua_pushlstring (lua_State *L, const char *s, size_t len); | |
| 1977 | + void lua_pushstring (lua_State *L, const char *s); | |
| 1978 | + void lua_pushnil (lua_State *L); | |
| 1979 | + void lua_pushcfunction (lua_State *L, lua_CFunction f); | |
| 1980 | + void lua_pushlightuserdata (lua_State *L, void *p); | |
| 1687 | 1981 | </PRE> |
| 1982 | + | |
| 1983 | +<p> | |
| 1984 | + | |
| 1985 | + | |
| 1688 | 1986 | These functions receive a C value, |
| 1689 | 1987 | convert it to a corresponding Lua value, |
| 1690 | 1988 | and push the result onto the stack. |
| 1691 | −In particular, <CODE>lua_pushlstring</CODE> and <CODE>lua_pushstring</CODE> | |
| 1692 | −make an <EM>internal copy</EM> of the given string. | |
| 1693 | −<CODE>lua_pushstring</CODE> can only be used to push proper C strings | |
| 1989 | +In particular, <code>lua_pushlstring</code> and <code>lua_pushstring</code> | |
| 1990 | +make an internal copy of the given string. | |
| 1991 | +<code>lua_pushstring</code> can only be used to push proper C strings | |
| 1694 | 1992 | (that is, strings that end with a zero and do not contain embedded zeros); |
| 1695 | −otherwise you should use the more general <CODE>lua_pushlstring</CODE>, | |
| 1993 | +otherwise, you should use the more general <code>lua_pushlstring</code>, | |
| 1696 | 1994 | which accepts an explicit size. |
| 1697 | −<P> | |
| 1698 | −<P> | |
| 1699 | −<A NAME="GC"></A> | |
| 1700 | −<A NAME="5.6"></A> | |
| 1701 | −<H2>5.6 - Garbage Collection</H2> | |
| 1702 | −<P> | |
| 1703 | −Lua uses two numbers to control its garbage collection. | |
| 1704 | −One number counts how many bytes of dynamic memory Lua is using, | |
| 1705 | −and the other is a threshold. | |
| 1706 | −(This internal byte counter kept by Lua is not completely acurate; | |
| 1707 | −it is just a lower bound, usually within 10% of the correct value.) | |
| 1708 | −When the number of bytes crosses the threshold, | |
| 1709 | −Lua runs a garbage-collection cycle, | |
| 1710 | −which reclaims the memory of all ``dead'' objects | |
| 1711 | −(that is, objects no longer accessible from Lua). | |
| 1712 | −The byte counter is corrected, | |
| 1713 | −and then the threshold is reset to twice the value of the byte counter. | |
| 1714 | −<P> | |
| 1715 | −You can access the current values of these two numbers through the | |
| 1995 | + | |
| 1996 | +<p>You can also push "formatted" strings: | |
| 1997 | +<PRE> | |
| 1998 | + const char *lua_pushfstring (lua_State *L, const char *fmt, ...); | |
| 1999 | + const char *lua_pushvfstring (lua_State *L, const char *fmt, | |
| 2000 | + va_list argp); | |
| 2001 | +</PRE> | |
| 2002 | + | |
| 2003 | +These functions push onto the stack a formatted string | |
| 2004 | +and return a pointer to that string. | |
| 2005 | +They are similar to <code>sprintf</code> and <code>vsprintf</code>, | |
| 2006 | +but with some important differences: | |
| 2007 | +<ul> | |
| 2008 | +<li> You do not have to allocate the space for the result: | |
| 2009 | +The result is a Lua string and Lua takes care of memory allocation | |
| 2010 | +(and deallocation, through garbage collection). | |
| 2011 | +<li> The conversion specifiers are quite restricted. | |
| 2012 | +There are no flags, widths, or precisions. | |
| 2013 | +The conversion specifiers can be simply | |
| 2014 | +`<code>%%</code>´ (inserts a `<code>%</code>´ in the string), | |
| 2015 | +`<code>%s</code>´ (inserts a zero-terminated string, with no size restrictions), | |
| 2016 | +`<code>%f</code>´ (inserts a <code>lua_Number</code>), | |
| 2017 | +`<code>%d</code>´ (inserts an <code>int</code>), and | |
| 2018 | +`<code>%c</code>´ (inserts an <code>int</code> as a character). | |
| 2019 | +</ul> | |
| 2020 | + | |
| 2021 | +<p>The function | |
| 2022 | +<PRE> | |
| 2023 | + void lua_concat (lua_State *L, int n); | |
| 2024 | +</PRE> | |
| 2025 | + | |
| 2026 | +concatenates the <code>n</code> values at the top of the stack, | |
| 2027 | +pops them, and leaves the result at the top. | |
| 2028 | +If <code>n</code> is 1, the result is that single string | |
| 2029 | +(that is, the function does nothing); | |
| 2030 | +if <code>n</code> is 0, the result is the empty string. | |
| 2031 | +Concatenation is done following the usual semantics of Lua | |
| 2032 | +(see <a href="#concat">2.5.4</a>). | |
| 2033 | + | |
| 2034 | +<p><a name="GC-API"><h2>3.7 - Controlling Garbage Collection</h2></a> | |
| 2035 | + | |
| 2036 | +<p>Lua uses two numbers to control its garbage collection: | |
| 2037 | +the <em>count</em> and the <em>threshold</em> (see <a href="#GC">2.9</a>). | |
| 2038 | +The first counts the amount of memory in use by Lua; | |
| 2039 | +when the count reaches the threshold, | |
| 2040 | +Lua runs its garbage collector. | |
| 2041 | +After the collection, the count is updated | |
| 2042 | +and the threshold is set to twice the count value. | |
| 2043 | + | |
| 2044 | +<p>You can access the current values of these two numbers through the | |
| 1716 | 2045 | following functions: |
| 1717 | −<A NAME="lua_getgcthreshold"></A> <A NAME="lua_getgccount"></A> | |
| 1718 | 2046 | <PRE> |
| 1719 | 2047 | int lua_getgccount (lua_State *L); |
| 1720 | 2048 | int lua_getgcthreshold (lua_State *L); |
| 1721 | 2049 | </PRE> |
| 2050 | + | |
| 1722 | 2051 | Both return their respective values in Kbytes. |
| 1723 | 2052 | You can change the threshold value with |
| 1724 | −<A NAME="lua_setgcthreshold"></A> | |
| 1725 | 2053 | <PRE> |
| 1726 | 2054 | void lua_setgcthreshold (lua_State *L, int newthreshold); |
| 1727 | 2055 | </PRE> |
| 1728 | −Again, the <CODE>newthreshold</CODE> value is given in Kbytes. | |
| 2056 | + | |
| 2057 | +Again, the <code>newthreshold</code> value is given in Kbytes. | |
| 1729 | 2058 | When you call this function, |
| 1730 | 2059 | Lua sets the new threshold and checks it against the byte counter. |
| 1731 | −If the new threshold is smaller than the byte counter, | |
| 1732 | −then Lua immediately runs the garbage collector; | |
| 1733 | −after the collection, | |
| 2060 | +If the new threshold is less than the byte counter, | |
| 2061 | +then Lua immediately runs the garbage collector. | |
| 2062 | +In particular | |
| 2063 | +<code>lua_setgcthreshold(L,0)</code> forces a garbage collection. | |
| 2064 | +After the collection, | |
| 1734 | 2065 | a new threshold is set according to the previous rule. |
| 1735 | −<P> | |
| 1736 | −If you want to change the adaptative behavior of the garbage collector, | |
| 1737 | −you can use the garbage-collection tag method for <B>nil</B> | |
| 1738 | −to set your own threshold | |
| 1739 | −(the tag method is called after Lua resets the threshold). | |
| 1740 | −<P> | |
| 1741 | −<P> | |
| 1742 | −<A NAME="C-tags"></A> | |
| 1743 | −<A NAME="5.7"></A> | |
| 1744 | −<H2>5.7 - Userdata and Tags</H2> | |
| 1745 | −<P> | |
| 1746 | −Because userdata are objects, | |
| 1747 | −the function <CODE>lua_pushusertag</CODE> may create a new userdata. | |
| 1748 | −If Lua has a userdata with the given value (<CODE>void*</CODE>) and tag, | |
| 1749 | −then that userdata is pushed. | |
| 1750 | −Otherwise, a new userdata is created, with the given value and tag. | |
| 1751 | −If this function is called with | |
| 1752 | −<CODE>tag</CODE> equal to <CODE>LUA_ANYTAG</CODE><A NAME="LUA_ANYTAG"></A>, | |
| 1753 | −then Lua will try to find any userdata with the given value, | |
| 1754 | −regardless of its tag. | |
| 1755 | −If there is no userdata with that value, then a new one is created, | |
| 1756 | −with tag equal to 0. | |
| 1757 | −<P> | |
| 1758 | −Userdata can have different tags, | |
| 1759 | −whose semantics are only known to the host program. | |
| 1760 | −Tags are created with the function | |
| 1761 | −<A NAME="lua_newtag"></A> | |
| 1762 | −<PRE> | |
| 1763 | − int lua_newtag (lua_State *L); | |
| 1764 | −</PRE> | |
| 1765 | −The function <CODE>lua_settag</CODE> changes the tag of | |
| 1766 | −the object on top of the stack (without popping it): | |
| 1767 | −<A NAME="lua_settag"></A> | |
| 1768 | −<PRE> | |
| 1769 | − void lua_settag (lua_State *L, int tag); | |
| 1770 | −</PRE> | |
| 1771 | −The object must be a userdata or a table; | |
| 1772 | −the given <CODE>tag</CODE> must be a value created with <CODE>lua_newtag</CODE>. | |
| 1773 | −<P> | |
| 1774 | −<A NAME="luado"></A> | |
| 1775 | −<A NAME="5.8"></A> | |
| 1776 | −<H2>5.8 - Executing Lua Code</H2> | |
| 1777 | −A host program can execute Lua chunks written in a file or in a string | |
| 1778 | −by using the following functions: | |
| 1779 | −<A NAME="lua_dofile"></A><A NAME="lua_dostring"></A><A NAME="lua_dobuffer"></A> | |
| 1780 | −<PRE> | |
| 1781 | − int lua_dofile (lua_State *L, const char *filename); | |
| 1782 | − int lua_dostring (lua_State *L, const char *string); | |
| 1783 | − int lua_dobuffer (lua_State *L, const char *buff, | |
| 1784 | − size_t size, const char *name); | |
| 1785 | −</PRE> | |
| 1786 | −These functions return | |
| 1787 | −0 in case of success, or one of the following error codes if they fail: | |
| 1788 | −<UL> | |
| 1789 | −<LI><A NAME="LUA_ERRRUN"><TT>LUA_ERRRUN</TT></A> - | |
| 1790 | −error while running the chunk. | |
| 1791 | −<LI><A NAME="LUA_ERRSYNTAX"><TT>LUA_ERRSYNTAX</TT></A> - | |
| 2066 | + | |
| 2067 | +<p><a name="userdata"><h2>3.8 - Userdata</h2></a> | |
| 2068 | + | |
| 2069 | +<p>Userdata represents C values in Lua. | |
| 2070 | +Lua supports two types of userdata: | |
| 2071 | +<em>full userdata</em> and <em>light userdata</em>. | |
| 2072 | + | |
| 2073 | +<p>A full userdata represents a block of memory. | |
| 2074 | +It is an object (like a table): | |
| 2075 | +You must create it, it can have its own metatable, | |
| 2076 | +and you can detect when it is being collected. | |
| 2077 | +A full userdata is only equal to itself (under raw equality). | |
| 2078 | + | |
| 2079 | +<p>A light userdata represents a pointer. | |
| 2080 | +It is a value (like a number): | |
| 2081 | +You do not create it, it has no metatables, | |
| 2082 | +it is not collected (as it was never created). | |
| 2083 | +A light userdata is equal to "any" | |
| 2084 | +light userdata with the same C address. | |
| 2085 | + | |
| 2086 | +<p>In Lua code, there is no way to test whether a userdata is full or light; | |
| 2087 | +both have type <code>userdata</code>. | |
| 2088 | +In C code, <code>lua_type</code> returns <code>LUA_TUSERDATA</code> for full userdata, | |
| 2089 | +and <code>LUA_TLIGHTUSERDATA</code> for light userdata. | |
| 2090 | + | |
| 2091 | +<p>You can create a new full userdata with the following function: | |
| 2092 | +<PRE> | |
| 2093 | + void *lua_newuserdata (lua_State *L, size_t size); | |
| 2094 | +</PRE> | |
| 2095 | + | |
| 2096 | +This function allocates a new block of memory with the given size, | |
| 2097 | +pushes on the stack a new userdata with the block address, | |
| 2098 | +and returns this address. | |
| 2099 | + | |
| 2100 | +<p>To push a light userdata into the stack you use | |
| 2101 | +<code>lua_pushlightuserdata</code> (see <a href="#pushing">3.6</a>). | |
| 2102 | + | |
| 2103 | +<p><code>lua_touserdata</code> (see <a href="#lua-to">3.5</a>) retrieves the value of a userdata. | |
| 2104 | +When applied on a full userdata, it returns the address of its block; | |
| 2105 | +when applied on a light userdata, it returns its pointer; | |
| 2106 | +when applied on a non-userdata value, it returns <code>NULL</code>. | |
| 2107 | + | |
| 2108 | +<p>When Lua collects a full userdata, | |
| 2109 | +it calls the userdata's <code>gc</code> metamethod, if any, | |
| 2110 | +and then it frees the userdata's corresponding memory. | |
| 2111 | + | |
| 2112 | +<p><h2>3.9 - Metatables</h2> | |
| 2113 | + | |
| 2114 | +<p>The following functions allow you to manipulate the metatables | |
| 2115 | +of an object: | |
| 2116 | +<PRE> | |
| 2117 | + int lua_getmetatable (lua_State *L, int index); | |
| 2118 | + int lua_setmetatable (lua_State *L, int index); | |
| 2119 | +</PRE> | |
| 2120 | + | |
| 2121 | +<code>lua_getmetatable</code> pushes on the stack the metatable of a given object. | |
| 2122 | +If the index is not valid, | |
| 2123 | +or if the object does not have a metatable, | |
| 2124 | +<code>lua_getmetatable</code> returns 0 and pushes nothing on the stack. | |
| 2125 | + | |
| 2126 | +<p><code>lua_setmetatable</code> pops a table from the stack and | |
| 2127 | +sets it as the new metatable for the given object. | |
| 2128 | +<code>lua_setmetatable</code> returns 0 when it cannot | |
| 2129 | +set the metatable of the given object | |
| 2130 | +(that is, when the object is neither a userdata nor a table); | |
| 2131 | +even then it pops the table from the stack. | |
| 2132 | + | |
| 2133 | +<p><h2>3.10 - Loading Lua Chunks</h2> | |
| 2134 | + | |
| 2135 | +<p>You can load a Lua chunk with <code>lua_load</code>: | |
| 2136 | +<PRE> | |
| 2137 | + typedef const char * (*lua_Chunkreader) | |
| 2138 | + (lua_State *L, void *data, size_t *size); | |
| 2139 | + | |
| 2140 | + int lua_load (lua_State *L, lua_Chunkreader reader, void *data, | |
| 2141 | + const char *chunkname); | |
| 2142 | +</PRE> | |
| 2143 | + | |
| 2144 | +The return values of <code>lua_load</code> are: | |
| 2145 | +<ul> | |
| 2146 | +<li> 0 --- no errors; | |
| 2147 | +<li> <code>LUA_ERRSYNTAX</code> --- | |
| 1792 | 2148 | syntax error during pre-compilation. |
| 1793 | −<LI><A NAME="LUA_ERRMEM"><TT>LUA_ERRMEM</TT></A> - | |
| 2149 | +<li> <code>LUA_ERRMEM</code> --- | |
| 1794 | 2150 | memory allocation error. |
| 1795 | −For such errors, Lua does not call <CODE>_ERRORMESSAGE</CODE> (see Section <A HREF="#error">4.7</A>). | |
| 1796 | −<LI><A NAME="LUA_ERRERR"><TT>LUA_ERRERR</TT></A> - | |
| 1797 | −error while running <CODE>_ERRORMESSAGE</CODE>. | |
| 1798 | −For such errors, Lua does not call <CODE>_ERRORMESSAGE</CODE> again, to avoid loops. | |
| 1799 | −<LI><A NAME="LUA_ERRFILE"><TT>LUA_ERRFILE</TT></A> - | |
| 1800 | −error opening the file (only for <CODE>lua_dofile</CODE>). | |
| 1801 | −In this case, | |
| 1802 | −you may want to | |
| 1803 | −check <CODE>errno</CODE>, | |
| 1804 | −call <CODE>strerror</CODE>, | |
| 1805 | −or call <CODE>perror</CODE> to tell the user what went wrong. | |
| 1806 | −</UL> | |
| 1807 | −These constants are defined in <CODE>lua.h</CODE>. | |
| 1808 | −<P> | |
| 1809 | −When called with argument <CODE>NULL</CODE>, | |
| 1810 | −<CODE>lua_dofile</CODE> executes the <CODE>stdin</CODE> stream. | |
| 1811 | −<CODE>lua_dofile</CODE> and <CODE>lua_dobuffer</CODE> | |
| 1812 | −are both able to execute pre-compiled chunks. | |
| 1813 | −They automatically detect whether the chunk is text or binary, | |
| 1814 | −and load it accordingly (see program <A NAME="luac"><TT><A HREF="luac.html">luac</A></TT></A>). | |
| 1815 | −<CODE>lua_dostring</CODE> executes only source code, | |
| 1816 | −given in textual form. | |
| 1817 | −<P> | |
| 1818 | −The third parameter to <CODE>lua_dobuffer</CODE> | |
| 1819 | −is the ``name of the chunk'', | |
| 1820 | −which is used in error messages and debug information. | |
| 1821 | −If <CODE>name</CODE> is <CODE>NULL</CODE>, | |
| 1822 | −then Lua gives a default name to the chunk. | |
| 1823 | −<P> | |
| 1824 | −These functions push onto the stack | |
| 1825 | −any values eventually returned by the chunk. | |
| 1826 | −A chunk may return any number of values; | |
| 1827 | −Lua takes care that these values fit into the stack space, | |
| 1828 | −but after the call the responsibility is back to you. | |
| 1829 | −If you need to push other elements after calling any of these functions, | |
| 1830 | −and you want to ``play safe'', | |
| 1831 | −you must either check the stack space | |
| 1832 | −with <CODE>lua_stackspace</CODE> | |
| 1833 | −or remove the returned elements | |
| 1834 | −from the stack (if you do not need them). | |
| 1835 | −For instance, the following code | |
| 1836 | −loads a chunk in a file and discards all results returned by this chunk, | |
| 1837 | −leaving the stack as it was before the call: | |
| 1838 | −<PRE> | |
| 1839 | − { | |
| 1840 | − int oldtop = lua_gettop(L); | |
| 1841 | − lua_dofile(L, filename); | |
| 1842 | − lua_settop(L, oldtop); | |
| 1843 | − } | |
| 1844 | −</PRE> | |
| 1845 | −<P> | |
| 1846 | −<P> | |
| 1847 | −<A NAME="5.9"></A> | |
| 1848 | −<H2>5.9 - Manipulating Global Variables in Lua</H2> | |
| 1849 | −<P> | |
| 1850 | −To read the value of a global Lua variable, | |
| 1851 | −you call | |
| 1852 | −<A NAME="lua_getglobal"></A> | |
| 1853 | −<PRE> | |
| 1854 | − void lua_getglobal (lua_State *L, const char *varname); | |
| 1855 | −</PRE> | |
| 1856 | −which pushes onto the stack the value of the given variable. | |
| 1857 | −As in Lua, this function may trigger a tag method | |
| 1858 | −for the ``getglobal'' event (see Section <A HREF="#tag-method">4.8</A>). | |
| 1859 | −To read the real value of a global variable, | |
| 1860 | −without invoking any tag method, | |
| 1861 | −use <CODE>lua_rawget</CODE> over the table of globals | |
| 1862 | −(see below). | |
| 1863 | −<P> | |
| 1864 | −To store a value in a global variable, | |
| 1865 | −you call | |
| 1866 | −<A NAME="lua_setglobal"></A> | |
| 1867 | −<PRE> | |
| 1868 | − void lua_setglobal (lua_State *L, const char *varname); | |
| 1869 | −</PRE> | |
| 1870 | −which pops from the stack the value to be stored in the given variable. | |
| 1871 | −As in Lua, this function may trigger a tag method | |
| 1872 | −for the ``setglobal'' event (see Section <A HREF="#tag-method">4.8</A>). | |
| 1873 | −To set the real value of a global variable, | |
| 1874 | −without invoking any tag method, | |
| 1875 | −use <CODE>lua_rawset</CODE> over the table of globals | |
| 1876 | −(see below). | |
| 1877 | −<P> | |
| 1878 | −All global variables are kept in an ordinary Lua table. | |
| 1879 | −You can get this table calling | |
| 1880 | −<A NAME="lua_getglobals"></A> | |
| 1881 | −<PRE> | |
| 1882 | − void lua_getglobals (lua_State *L); | |
| 1883 | −</PRE> | |
| 1884 | −which pushes the current table of globals onto the stack. | |
| 1885 | −To set another table as the table of globals, | |
| 1886 | −you call | |
| 1887 | −<A NAME="lua_setglobals"></A> | |
| 1888 | −<PRE> | |
| 1889 | − void lua_setglobals (lua_State *L); | |
| 1890 | −</PRE> | |
| 1891 | −The table to be used is popped from the stack. | |
| 1892 | −<P> | |
| 1893 | −<A NAME="5.10"></A> | |
| 1894 | −<H2>5.10 - Manipulating Tables in Lua</H2> | |
| 1895 | −Lua tables can also be manipulated through the API. | |
| 1896 | −<P> | |
| 1897 | −To read the value of in a table, | |
| 1898 | −the table must reside somewhere in the stack. | |
| 1899 | −With this set, | |
| 1900 | −you call | |
| 1901 | −<A NAME="lua_gettable"></A> | |
| 2151 | +</ul> | |
| 2152 | +If there are no errors, | |
| 2153 | +<code>lua_load</code> pushes the compiled chunk as a Lua | |
| 2154 | +function on top of the stack. | |
| 2155 | +Otherwise, it pushes an error message. | |
| 2156 | + | |
| 2157 | +<p><code>lua_load</code> automatically detects whether the chunk is text or binary, | |
| 2158 | +and loads it accordingly (see program <code>luac</code>). | |
| 2159 | + | |
| 2160 | +<p><code>lua_load</code> uses an user-supplied <em>reader</em> function to read the chunk. | |
| 2161 | +Everytime it needs another piece of the chunk, | |
| 2162 | +it calls the reader, | |
| 2163 | +passing along its <code>data</code> parameter. | |
| 2164 | +The reader must return a pointer to a block of memory | |
| 2165 | +with a new piece of the chunk | |
| 2166 | +and set <code>size</code> to the block size. | |
| 2167 | +To signal the end of the chunk, the reader returns <code>NULL</code>. | |
| 2168 | +The reader function may return pieces of any size greater than zero. | |
| 2169 | + | |
| 2170 | +<p>In the current implementation, | |
| 2171 | +the reader function cannot call any Lua function; | |
| 2172 | +to ensure that, it always receives <code>NULL</code> as the Lua state. | |
| 2173 | + | |
| 2174 | +<p>The <em>chunkname</em> is used for error messages | |
| 2175 | +and debug information (see <a href="#debugI">4</a>). | |
| 2176 | + | |
| 2177 | +<p>See the auxiliary library (<code>lauxlib.c</code>) | |
| 2178 | +for examples of how to use <code>lua_load</code> | |
| 2179 | +and for some ready-to-use functions to load chunks | |
| 2180 | +from files and strings. | |
| 2181 | + | |
| 2182 | +<p><h2>3.11 - Manipulating Tables</h2> | |
| 2183 | + | |
| 2184 | +<p>Tables are created by calling | |
| 2185 | +the function | |
| 2186 | +<PRE> | |
| 2187 | + void lua_newtable (lua_State *L); | |
| 2188 | +</PRE> | |
| 2189 | + | |
| 2190 | +This function creates a new, empty table and pushes it onto the stack. | |
| 2191 | + | |
| 2192 | +<p>To read a value from a table that resides somewhere in the stack, | |
| 2193 | +call | |
| 1902 | 2194 | <PRE> |
| 1903 | 2195 | void lua_gettable (lua_State *L, int index); |
| 1904 | 2196 | </PRE> |
| 1905 | −where <CODE>index</CODE> refers to the table. | |
| 1906 | −<CODE>lua_gettable</CODE> pops a key from the stack, | |
| 2197 | + | |
| 2198 | +where <code>index</code> points to the table. | |
| 2199 | +<code>lua_gettable</code> pops a key from the stack | |
| 1907 | 2200 | and returns (on the stack) the contents of the table at that key. |
| 1908 | −As in Lua, this operation may trigger a tag method | |
| 1909 | −for the ``gettable'' event. | |
| 2201 | +The table is left where it was in the stack. | |
| 2202 | +As in Lua, this function may trigger a metamethod | |
| 2203 | +for the "index" event (see <a href="#metatable">2.8</a>). | |
| 1910 | 2204 | To get the real value of any table key, |
| 1911 | −without invoking any tag method, | |
| 1912 | −use the <EM>raw</EM> version: | |
| 1913 | −<A NAME="lua_rawget"></A> | |
| 2205 | +without invoking any metamethod, | |
| 2206 | +use the <em>raw</em> version: | |
| 1914 | 2207 | <PRE> |
| 1915 | 2208 | void lua_rawget (lua_State *L, int index); |
| 1916 | 2209 | </PRE> |
| 1917 | −<P> | |
| 1918 | −To store a value into a table that resides somewhere in the stack, | |
| 1919 | −you push the key and the value onto the stack | |
| 1920 | −(in this order), | |
| 1921 | −and then call | |
| 1922 | −<A NAME="lua_settable"></A> | |
| 2210 | + | |
| 2211 | + | |
| 2212 | +<p>To store a value into a table that resides somewhere in the stack, | |
| 2213 | +you push the key and then the value onto the stack, | |
| 2214 | +and call | |
| 1923 | 2215 | <PRE> |
| 1924 | 2216 | void lua_settable (lua_State *L, int index); |
| 1925 | 2217 | </PRE> |
| 1926 | −where <CODE>index</CODE> refers to the table. | |
| 1927 | −<CODE>lua_settable</CODE> pops from the stack both the key and the value. | |
| 1928 | −As in Lua, this operation may trigger a tag method | |
| 1929 | −for the ``settable'' event. | |
| 2218 | + | |
| 2219 | +where <code>index</code> points to the table. | |
| 2220 | +<code>lua_settable</code> pops from the stack both the key and the value. | |
| 2221 | +The table is left where it was in the stack. | |
| 2222 | +As in Lua, this operation may trigger a metamethod | |
| 2223 | +for the "settable" or "newindex" events. | |
| 1930 | 2224 | To set the real value of any table index, |
| 1931 | −without invoking any tag method, | |
| 1932 | −use the <EM>raw</EM> version: | |
| 1933 | −<A NAME="lua_rawset"></A> | |
| 2225 | +without invoking any metamethod, | |
| 2226 | +use the <em>raw</em> version: | |
| 1934 | 2227 | <PRE> |
| 1935 | 2228 | void lua_rawset (lua_State *L, int index); |
| 1936 | 2229 | </PRE> |
| 1937 | −<P> | |
| 1938 | −Finally, the function | |
| 1939 | −<A NAME="lua_newtable"></A> | |
| 2230 | + | |
| 2231 | + | |
| 2232 | +<p>You can traverse a table with the function | |
| 2233 | +<PRE> | |
| 2234 | + int lua_next (lua_State *L, int index); | |
| 2235 | +</PRE> | |
| 2236 | + | |
| 2237 | +where <code>index</code> points to the table to be traversed. | |
| 2238 | +The function pops a key from the stack, | |
| 2239 | +and pushes a key-value pair from the table | |
| 2240 | +(the "next" pair after the given key). | |
| 2241 | +If there are no more elements, then <code>lua_next</code> returns 0 | |
| 2242 | +(and pushes nothing). | |
| 2243 | +Use a <B>nil</B> key to signal the start of a traversal. | |
| 2244 | + | |
| 2245 | +<p>A typical traversal looks like this: | |
| 1940 | 2246 | <PRE> |
| 1941 | − void lua_newtable (lua_State *L); | |
| 2247 | + /* table is in the stack at index `t' */ | |
| 2248 | + lua_pushnil(L); /* first key */ | |
| 2249 | + while (lua_next(L, t) != 0) { | |
| 2250 | + /* `key' is at index -2 and `value' at index -1 */ | |
| 2251 | + printf("%s - %s\n", | |
| 2252 | + lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); | |
| 2253 | + lua_pop(L, 1); /* removes `value'; keeps `key' for next iteration */ | |
| 2254 | + } | |
| 1942 | 2255 | </PRE> |
| 1943 | −creates a new, empty table and pushes it onto the stack. | |
| 1944 | −<P> | |
| 1945 | −<A NAME="5.11"></A> | |
| 1946 | −<H2>5.11 - Using Tables as Arrays</H2> | |
| 2256 | + | |
| 2257 | +<p>While traversing a table, | |
| 2258 | +do not call <code>lua_tostring</code> directly on a key, | |
| 2259 | +unless you know that the key is actually a string. | |
| 2260 | +Recall that <code>lua_tostring</code> <em>changes</em> the value at the given index; | |
| 2261 | +this confuses the next call to <code>lua_next</code>. | |
| 2262 | + | |
| 2263 | +<p><a name="globals"><h2>3.12 - Manipulating Environments</h2></a> | |
| 2264 | + | |
| 2265 | +<p>All global variables are kept in ordinary Lua tables, | |
| 2266 | +called environments. | |
| 2267 | +The initial environment is called the global environment. | |
| 2268 | +This table is always at pseudo-index <code>LUA_GLOBALSINDEX</code>. | |
| 2269 | + | |
| 2270 | +<p>To access and change the value of global variables, | |
| 2271 | +you can use regular table operations over an environment table. | |
| 2272 | +For instance, to access the value of a global variable, do | |
| 2273 | +<PRE> | |
| 2274 | + lua_pushstring(L, varname); | |
| 2275 | + lua_gettable(L, LUA_GLOBALSINDEX); | |
| 2276 | +</PRE> | |
| 2277 | + | |
| 2278 | +<p>You can change the global environment of a Lua thread using <code>lua_replace</code>. | |
| 2279 | + | |
| 2280 | +<p>The following functions get and set the environment of Lua functions: | |
| 2281 | +<PRE> | |
| 2282 | + void lua_getfenv (lua_State *L, int index); | |
| 2283 | + int lua_setfenv (lua_State *L, int index); | |
| 2284 | +</PRE> | |
| 2285 | + | |
| 2286 | +<code>lua_getfenv</code> pushes on the stack the environment table of | |
| 2287 | +the function at index <code>index</code> in the stack. | |
| 2288 | +If the function is a C function, | |
| 2289 | +<code>lua_getfenv</code> pushes the global environment. | |
| 2290 | +<code>lua_setfenv</code> pops a table from the stack and sets it as | |
| 2291 | +the new environment for the function at index <code>index</code> in the stack. | |
| 2292 | +If the object at the given index is not a Lua function, | |
| 2293 | +<code>lua_setfenv</code> returns 0. | |
| 2294 | + | |
| 2295 | +<p><h2>3.13 - Using Tables as Arrays</h2> | |
| 1947 | 2296 | The API has functions that help to use Lua tables as arrays, |
| 1948 | 2297 | that is, |
| 1949 | 2298 | tables indexed by numbers only: |
| 1950 | −<A NAME="lua_rawgeti"></A> | |
| 1951 | −<A NAME="lua_rawseti"></A> | |
| 1952 | −<A NAME="lua_getn"></A> | |
| 1953 | 2299 | <PRE> |
| 1954 | 2300 | void lua_rawgeti (lua_State *L, int index, int n); |
| 1955 | 2301 | void lua_rawseti (lua_State *L, int index, int n); |
| 1956 | − int lua_getn (lua_State *L, int index); | |
| 1957 | −</PRE> | |
| 1958 | −<P> | |
| 1959 | −<CODE>lua_rawgeti</CODE> gets the value of the <EM>n</EM>-th element of the table | |
| 1960 | −at stack position <CODE>index</CODE>. | |
| 1961 | −<P> | |
| 1962 | −<CODE>lua_rawseti</CODE> sets the value of the <EM>n</EM>-th element of the table | |
| 1963 | −at stack position <CODE>index</CODE> to the value at the top of the stack. | |
| 1964 | −<P> | |
| 1965 | −<CODE>lua_getn</CODE> returns the number of elements in the table | |
| 1966 | −at stack position <CODE>index</CODE>. | |
| 1967 | −This number is the value of the table field <CODE>n</CODE>, | |
| 1968 | −if it has a numeric value, | |
| 1969 | −or | |
| 1970 | −the largest numerical index with a non-nil value in the table. | |
| 1971 | −<P> | |
| 1972 | −<A NAME="5.12"></A> | |
| 1973 | −<H2>5.12 - Calling Lua Functions</H2> | |
| 1974 | −<P> | |
| 1975 | −Functions defined in Lua | |
| 1976 | −(and C functions registered in Lua) | |
| 2302 | +</PRE> | |
| 2303 | + | |
| 2304 | + | |
| 2305 | + | |
| 2306 | +<p><code>lua_rawgeti</code> pushes the value of the <em>n</em>-th element of the table | |
| 2307 | +at stack position <code>index</code>. | |
| 2308 | +<code>lua_rawseti</code> sets the value of the <em>n</em>-th element of the table | |
| 2309 | +at stack position <code>index</code> to the value at the top of the stack, | |
| 2310 | +removing this value from the stack. | |
| 2311 | + | |
| 2312 | +<p><h2>3.14 - Calling Functions</h2> | |
| 2313 | + | |
| 2314 | +<p>Functions defined in Lua | |
| 2315 | +and C functions registered in Lua | |
| 1977 | 2316 | can be called from the host program. |
| 1978 | 2317 | This is done using the following protocol: |
| 1979 | 2318 | First, the function to be called is pushed onto the stack; |
| 1980 | 2319 | then, the arguments to the function are pushed |
| 1981 | −(see Section <A HREF="#pushing">5.5</A>) in <EM>direct order</EM>, that is, the first argument is pushed first. | |
| 2320 | +in <em>direct order</em>, that is, the first argument is pushed first. | |
| 1982 | 2321 | Finally, the function is called using |
| 1983 | −<A NAME="lua_call"></A> | |
| 1984 | −<PRE> | |
| 1985 | − int lua_call (lua_State *L, int nargs, int nresults); | |
| 1986 | −</PRE> | |
| 1987 | −This function returns the same error codes as <CODE>lua_dostring</CODE> and | |
| 1988 | −friends (see Section <A HREF="#luado">5.8</A>). | |
| 1989 | −If you want to propagate the error, | |
| 1990 | −instead of returning an error code, | |
| 1991 | −use | |
| 1992 | −<A NAME="lua_rawcall"></A> | |
| 1993 | 2322 | <PRE> |
| 1994 | − void lua_rawcall (lua_State *L, int nargs, int nresults); | |
| 2323 | + void lua_call (lua_State *L, int nargs, int nresults); | |
| 1995 | 2324 | </PRE> |
| 1996 | −<P> | |
| 1997 | −In both functions, | |
| 1998 | −<CODE>nargs</CODE> is the number of arguments that you pushed onto the stack. | |
| 2325 | + | |
| 2326 | +<code>nargs</code> is the number of arguments that you pushed onto the stack. | |
| 1999 | 2327 | All arguments and the function value are popped from the stack, |
| 2000 | 2328 | and the function results are pushed. |
| 2001 | −The number of results are adjusted (see Section <A HREF="#adjust">4.3</A>) to <CODE>nresults</CODE>, | |
| 2002 | −unless <CODE>nresults</CODE> is <A NAME="LUA_MULTRET"><TT>LUA_MULTRET</TT></A>. | |
| 2003 | −In that case, <EM>all</EM> results from the function are pushed. | |
| 2004 | −The function results are pushed in direct order | |
| 2329 | +The number of results are adjusted to <code>nresults</code>, | |
| 2330 | +unless <code>nresults</code> is <code>LUA_MULTRET</code>. | |
| 2331 | +In that case, <em>all</em> results from the function are pushed. | |
| 2332 | +Lua takes care that the returned values fit into the stack space. | |
| 2333 | +The function results are pushed onto the stack in direct order | |
| 2005 | 2334 | (the first result is pushed first), |
| 2006 | 2335 | so that after the call the last result is on the top. |
| 2007 | −<P> | |
| 2008 | −The following example shows how the host program may do the | |
| 2009 | −equivalent to the Lua code: | |
| 2336 | + | |
| 2337 | +<p>The following example shows how the host program may do the | |
| 2338 | +equivalent to this Lua code: | |
| 2010 | 2339 | <PRE> |
| 2011 | − a,b = f("how", t.x, 4) | |
| 2340 | + a = f("how", t.x, 14) | |
| 2012 | 2341 | </PRE> |
| 2013 | 2342 | Here it is in C: |
| 2014 | 2343 | <PRE> |
| 2015 | − lua_getglobal(L, "t"); /* global `t' (for later use) */ | |
| 2016 | − lua_getglobal(L, "f"); /* function to be called */ | |
| 2344 | + lua_pushstring(L, "t"); | |
| 2345 | + lua_gettable(L, LUA_GLOBALSINDEX); /* global `t' (for later use) */ | |
| 2346 | + lua_pushstring(L, "a"); /* var name */ | |
| 2347 | + lua_pushstring(L, "f"); /* function name */ | |
| 2348 | + lua_gettable(L, LUA_GLOBALSINDEX); /* function to be called */ | |
| 2017 | 2349 | lua_pushstring(L, "how"); /* 1st argument */ |
| 2018 | − lua_pushstring(L, "x"); /* push the string `x' */ | |
| 2019 | − lua_gettable(L, -4); /* push result of t.x (2nd arg) */ | |
| 2020 | − lua_pushnumber(L, 4); /* 3rd argument */ | |
| 2021 | − lua_call(L, 3, 2); /* call function with 3 arguments and 2 results */ | |
| 2022 | − lua_setglobal(L, "b"); /* set global variable `b' */ | |
| 2023 | − lua_setglobal(L, "a"); /* set global variable `a' */ | |
| 2350 | + lua_pushstring(L, "x"); /* push the string "x" */ | |
| 2351 | + lua_gettable(L, -5); /* push result of t.x (2nd arg) */ | |
| 2352 | + lua_pushnumber(L, 14); /* 3rd argument */ | |
| 2353 | + lua_call(L, 3, 1); /* call function with 3 arguments and 1 result */ | |
| 2354 | + lua_settable(L, LUA_GLOBALSINDEX); /* set global variable `a' */ | |
| 2024 | 2355 | lua_pop(L, 1); /* remove `t' from the stack */ |
| 2025 | 2356 | </PRE> |
| 2026 | −Notice that the code above is ``balanced'': | |
| 2027 | −at its end ,the stack is back to its original configuration. | |
| 2357 | +Note that the code above is "balanced": | |
| 2358 | +at its end, the stack is back to its original configuration. | |
| 2028 | 2359 | This is considered good programming practice. |
| 2029 | −<P> | |
| 2030 | −<P> | |
| 2031 | −<P> | |
| 2032 | −Some special Lua functions have their own C interfaces. | |
| 2033 | −The host program can generate a Lua error calling the function | |
| 2034 | −<A NAME="lua_error"></A> | |
| 2035 | −<PRE> | |
| 2036 | − void lua_error (lua_State *L, const char *message); | |
| 2037 | −</PRE> | |
| 2038 | −This function never returns. | |
| 2039 | −If <CODE>lua_error</CODE> is called from a C function that has been called from Lua, | |
| 2040 | −then the corresponding Lua execution terminates, | |
| 2041 | −as if an error had occurred inside Lua code. | |
| 2042 | −Otherwise, the whole host program terminates with a call to | |
| 2043 | −<CODE>exit(EXIT_FAILURE)</CODE>. | |
| 2044 | −Before terminating execution, | |
| 2045 | −the <CODE>message</CODE> is passed to the error handler function, | |
| 2046 | −<CODE>_ERRORMESSAGE</CODE> (see Section <A HREF="#error">4.7</A>). | |
| 2047 | −If <CODE>message</CODE> is <CODE>NULL</CODE>, | |
| 2048 | −then <CODE>_ERRORMESSAGE</CODE> is not called. | |
| 2049 | −<P> | |
| 2050 | −<P> | |
| 2051 | −Tag methods can be changed with <A NAME="lua_settagmethod"></A> | |
| 2052 | −<PRE> | |
| 2053 | − void lua_settagmethod (lua_State *L, int tag, const char *event); | |
| 2054 | −</PRE> | |
| 2055 | −The second parameter is the tag, | |
| 2056 | −and the third is the event name (see Section <A HREF="#tag-method">4.8</A>); | |
| 2057 | −the new method is popped from the stack. | |
| 2058 | −To get the current value of a tag method, | |
| 2059 | −use the function <A NAME="lua_gettagmethod"></A> | |
| 2060 | −<PRE> | |
| 2061 | − void lua_gettagmethod (lua_State *L, int tag, const char *event); | |
| 2062 | −</PRE> | |
| 2063 | −<P> | |
| 2064 | −It is also possible to copy all tag methods from one tag | |
| 2065 | −to another: <A NAME="lua_copytagmethods"></A> | |
| 2066 | −<PRE> | |
| 2067 | − int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); | |
| 2068 | −</PRE> | |
| 2069 | −This function returns <CODE>tagto</CODE>. | |
| 2070 | −<P> | |
| 2071 | −<P> | |
| 2072 | −You can traverse a table with the function <A NAME="lua_next"></A> | |
| 2073 | −<PRE> | |
| 2074 | − int lua_next (lua_State *L, int index); | |
| 2075 | −</PRE> | |
| 2076 | −where <CODE>index</CODE> refers to the table to be traversed. | |
| 2077 | −The function pops a key from the stack, | |
| 2078 | −and pushes a key-value pair from the table | |
| 2079 | −(the ``next'' pair after the given key). | |
| 2080 | −If there are no more elements, then the function returns 0 | |
| 2081 | −(and pushes nothing). | |
| 2082 | −A typical traversal looks like this: | |
| 2083 | −<PRE> | |
| 2084 | − /* table is in the stack at index `t' */ | |
| 2085 | − lua_pushnil(L); /* first key */ | |
| 2086 | − while (lua_next(L, t) != 0) { | |
| 2087 | − /* `key' is at index -2 and `value' at index -1 */ | |
| 2088 | − printf("%s - %s\n", | |
| 2089 | − lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); | |
| 2090 | − lua_pop(L, 1); /* removes `value'; keeps `index' for next iteration */ | |
| 2091 | − } | |
| 2092 | −</PRE> | |
| 2093 | −<P> | |
| 2094 | −The function <A NAME="lua_concat"></A> | |
| 2095 | −<PRE> | |
| 2096 | − void lua_concat (lua_State *L, int n); | |
| 2097 | −</PRE> | |
| 2098 | −concatenates the <CODE>n</CODE> values at the top of the stack, | |
| 2099 | −pops them, and leaves the result at the top; | |
| 2100 | −<CODE>n</CODE> must be at least 2. | |
| 2101 | −Concatenation is done following the usual semantics of Lua | |
| 2102 | −(see Section <A HREF="#concat">4.5.5</A>). | |
| 2103 | −<P> | |
| 2104 | −<P> | |
| 2105 | −<A NAME="LuacallC"></A> | |
| 2106 | −<A NAME="5.13"></A> | |
| 2107 | −<H2>5.13 - Defining C Functions</H2> | |
| 2108 | −To register a C function to Lua, | |
| 2109 | −there is the following convenience macro: | |
| 2110 | −<A NAME="lua_register"></A> | |
| 2111 | −<PRE> | |
| 2112 | − #define lua_register(L, n, f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) | |
| 2113 | − /* const char *n; */ | |
| 2114 | − /* lua_CFunction f; */ | |
| 2115 | −</PRE> | |
| 2116 | −which receives the name the function will have in Lua, | |
| 2117 | −and a pointer to the function. | |
| 2118 | −This pointer must have type <CODE>lua_CFunction</CODE>, | |
| 2119 | −which is defined as | |
| 2120 | −<A NAME="lua_CFunction"></A> | |
| 2360 | + | |
| 2361 | +<p>(We did this example using only the raw functions provided by Lua's API, | |
| 2362 | +to show all the details. | |
| 2363 | +Usually programmers define and use several macros and auxiliary functions | |
| 2364 | +that provide higher level access to Lua. | |
| 2365 | +See the source code of the standard libraries for examples.) | |
| 2366 | + | |
| 2367 | +<p><a name="lua_pcall"><h2>3.15 - Protected Calls</h2></a> | |
| 2368 | + | |
| 2369 | +<p>When you call a function with <code>lua_call</code>, | |
| 2370 | +any error inside the called function is propagated upwards | |
| 2371 | +(with a <code>longjmp</code>). | |
| 2372 | +If you need to handle errors, | |
| 2373 | +then you should use <code>lua_pcall</code>: | |
| 2374 | +<PRE> | |
| 2375 | + int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); | |
| 2376 | +</PRE> | |
| 2377 | +Both <code>nargs</code> and <code>nresults</code> have the same meaning as | |
| 2378 | +in <code>lua_call</code>. | |
| 2379 | +If there are no errors during the call, | |
| 2380 | +<code>lua_pcall</code> behaves exactly like <code>lua_call</code>. | |
| 2381 | +However, if there is any error, | |
| 2382 | +<code>lua_pcall</code> catches it, | |
| 2383 | +pushes a single value at the stack (the error message), | |
| 2384 | +and returns an error code. | |
| 2385 | +Like <code>lua_call</code>, | |
| 2386 | +<code>lua_pcall</code> always removes the function | |
| 2387 | +and its arguments from the stack. | |
| 2388 | + | |
| 2389 | +<p>If <code>errfunc</code> is 0, | |
| 2390 | +then the error message returned is exactly the original error message. | |
| 2391 | +Otherwise, <code>errfunc</code> gives the stack index for an | |
| 2392 | +<em>error handler function</em>. | |
| 2393 | +(In the current implementation, that index cannot be a pseudo-index.) | |
| 2394 | +In case of runtime errors, | |
| 2395 | +that function will be called with the error message | |
| 2396 | +and its return value will be the message returned by <code>lua_pcall</code>. | |
| 2397 | + | |
| 2398 | +<p>Typically, the error handler function is used to add more debug | |
| 2399 | +information to the error message, such as a stack traceback. | |
| 2400 | +Such information cannot be gathered after the return of <code>lua_pcall</code>, | |
| 2401 | +since by then the stack has unwound. | |
| 2402 | + | |
| 2403 | +<p>The <code>lua_pcall</code> function returns 0 in case of success | |
| 2404 | +or one of the following error codes | |
| 2405 | +(defined in <code>lua.h</code>): | |
| 2406 | +<ul> | |
| 2407 | +<li> <code>LUA_ERRRUN</code> --- a runtime error. | |
| 2408 | +<li> <code>LUA_ERRMEM</code> --- memory allocation error. | |
| 2409 | +For such errors, Lua does not call the error handler function. | |
| 2410 | +<li> <code>LUA_ERRERR</code> --- | |
| 2411 | +error while running the error handler function. | |
| 2412 | +</ul> | |
| 2413 | + | |
| 2414 | +<p><a name="LuacallC"><h2>3.16 - Defining C Functions</h2></a> | |
| 2415 | + | |
| 2416 | +<p>Lua can be extended with functions written in C. | |
| 2417 | +These functions must be of type <code>lua_CFunction</code>, | |
| 2418 | +which is defined as | |
| 2121 | 2419 | <PRE> |
| 2122 | 2420 | typedef int (*lua_CFunction) (lua_State *L); |
| 2123 | 2421 | </PRE> |
| 2124 | −that is, a pointer to a function with integer result and a single argument, | |
| 2125 | −a Lua environment. | |
| 2126 | −<P> | |
| 2127 | −In order to communicate properly with Lua, | |
| 2422 | + | |
| 2423 | +A C function receives a Lua state and returns an integer, | |
| 2424 | +the number of values it wants to return to Lua. | |
| 2425 | + | |
| 2426 | +<p>In order to communicate properly with Lua, | |
| 2128 | 2427 | a C function must follow the following protocol, |
| 2129 | 2428 | which defines the way parameters and results are passed: |
| 2130 | −A C function receives its arguments from Lua in the stack, | |
| 2429 | +A C function receives its arguments from Lua in its stack | |
| 2131 | 2430 | in direct order (the first argument is pushed first). |
| 2431 | +So, when the function starts, | |
| 2432 | +its first argument (if any) is at index 1. | |
| 2132 | 2433 | To return values to Lua, a C function just pushes them onto the stack, |
| 2133 | 2434 | in direct order (the first result is pushed first), |
| 2134 | 2435 | and returns the number of results. |
| 2436 | +Any other value in the stack below the results will be properly | |
| 2437 | +discharged by Lua. | |
| 2135 | 2438 | Like a Lua function, a C function called by Lua can also return |
| 2136 | 2439 | many results. |
| 2137 | −<P> | |
| 2138 | −As an example, the following function receives a variable number | |
| 2440 | + | |
| 2441 | +<p>As an example, the following function receives a variable number | |
| 2139 | 2442 | of numerical arguments and returns their average and sum: |
| 2140 | 2443 | <PRE> |
| 2141 | 2444 | static int foo (lua_State *L) { |
| 2142 | 2445 | int n = lua_gettop(L); /* number of arguments */ |
| 2143 | − double sum = 0; | |
| 2446 | + lua_Number sum = 0; | |
| 2144 | 2447 | int i; |
| 2145 | − for (i = 1; i <= n; i++) { | |
| 2146 | − if (!lua_isnumber(L, i)) | |
| 2147 | − lua_error(L, "incorrect argument to function `average'"); | |
| 2448 | + for (i = 1; i <= n; i++) { | |
| 2449 | + if (!lua_isnumber(L, i)) { | |
| 2450 | + lua_pushstring(L, "incorrect argument to function `average'"); | |
| 2451 | + lua_error(L); | |
| 2452 | + } | |
| 2148 | 2453 | sum += lua_tonumber(L, i); |
| 2149 | 2454 | } |
| 2150 | 2455 | lua_pushnumber(L, sum/n); /* first result */ |
| @@ -2152,1648 +2457,2157 @@ of numerical arguments and returns their average and sum: · 1 unmodified line | ||
| 2152 | 2457 | return 2; /* number of results */ |
| 2153 | 2458 | } |
| 2154 | 2459 | </PRE> |
| 2155 | −This function may be registered in Lua as `<CODE>average</CODE>' by calling | |
| 2460 | + | |
| 2461 | +<p>To register a C function to Lua, | |
| 2462 | +there is the following convenience macro: | |
| 2463 | +<PRE> | |
| 2464 | + #define lua_register(L,n,f) \ | |
| 2465 | + (lua_pushstring(L, n), \ | |
| 2466 | + lua_pushcfunction(L, f), \ | |
| 2467 | + lua_settable(L, LUA_GLOBALSINDEX)) | |
| 2468 | + /* lua_State *L; */ | |
| 2469 | + /* const char *n; */ | |
| 2470 | + /* lua_CFunction f; */ | |
| 2471 | +</PRE> | |
| 2472 | + | |
| 2473 | +which receives the name the function will have in Lua | |
| 2474 | +and a pointer to the function. | |
| 2475 | +Thus, | |
| 2476 | +the C function <code>foo</code> above may be registered in Lua as | |
| 2477 | +<code>average</code> by calling | |
| 2156 | 2478 | <PRE> |
| 2157 | 2479 | lua_register(L, "average", foo); |
| 2158 | 2480 | </PRE> |
| 2159 | −<P> | |
| 2160 | −<P> | |
| 2161 | −When a C function is created, | |
| 2162 | −it is possible to associate some <EM>upvalues</EM> to it | |
| 2163 | −(see Section <A HREF="#upvalue">4.6</A>), | |
| 2164 | −thus creating a <A NAME="C closure"><EM>C closure</EM></A>; | |
| 2165 | −these values are passed to the function whenever it is called, | |
| 2166 | −as ordinary arguments. | |
| 2167 | −To associate upvalues to a C function, | |
| 2168 | −first these values should be pushed onto the stack. | |
| 2169 | −Then the function <A NAME="lua_pushcclosure"></A> | |
| 2481 | + | |
| 2482 | +<p><a name="c-closure"><h2>3.17 - Defining C Closures</h2></a> | |
| 2483 | + | |
| 2484 | +<p>When a C function is created, | |
| 2485 | +it is possible to associate some values with it, | |
| 2486 | +thus creating a <em>C closure</em>; | |
| 2487 | +these values are then accessible to the function whenever it is called. | |
| 2488 | +To associate values with a C function, | |
| 2489 | +first these values should be pushed onto the stack | |
| 2490 | +(when there are multiple values, the first value is pushed first). | |
| 2491 | +Then the function | |
| 2170 | 2492 | <PRE> |
| 2171 | 2493 | void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); |
| 2172 | 2494 | </PRE> |
| 2495 | + | |
| 2173 | 2496 | is used to push the C function onto the stack, |
| 2174 | −with the argument <CODE>n</CODE> telling how many upvalues should be | |
| 2497 | +with the argument <code>n</code> telling how many values should be | |
| 2175 | 2498 | associated with the function |
| 2176 | −(these upvalues are popped from the stack); | |
| 2177 | −in fact, the macro <CODE>lua_pushcfunction</CODE> is defined as | |
| 2178 | −<CODE>lua_pushcclosure</CODE> with <CODE>n</CODE> set to 0. | |
| 2179 | −Then, whenever the C function is called, | |
| 2180 | −these upvalues are inserted as the <EM>last</EM> arguments to the function, | |
| 2181 | −after the actual arguments provided in the call. | |
| 2182 | −This makes it easy to get the upvalues without knowing how many arguments | |
| 2183 | −the function received (recall that functions in Lua can receive any number of | |
| 2184 | −arguments): The <EM>i</EM>-th upvalue is in the stack at index <I>i-(n+1)</I>, | |
| 2185 | −where <EM>n</EM> is the number of upvalues. | |
| 2186 | −<P> | |
| 2187 | −For more examples of C functions and closures, see files | |
| 2188 | −<CODE>lbaselib.c</CODE>, <CODE>liolib.c</CODE>, <CODE>lmathlib.c</CODE>, and <CODE>lstrlib.c</CODE> | |
| 2189 | −in the official Lua distribution. | |
| 2190 | −<P> | |
| 2191 | −<A NAME="5.14"></A> | |
| 2192 | −<H2>5.14 - References to Lua Objects</H2> | |
| 2193 | −<P> | |
| 2194 | −If the C code needs to keep a Lua value | |
| 2195 | −outside the life span of a C function, | |
| 2196 | −then it must create a <A NAME="reference"><EM>reference</EM></A> to the value. | |
| 2197 | −The functions to manipulate references are the following: | |
| 2198 | −<A NAME="lua_ref"></A><A NAME="lua_getref"></A> | |
| 2199 | −<A NAME="lua_unref"></A> | |
| 2200 | −<PRE> | |
| 2201 | − int lua_ref (lua_State *L, int lock); | |
| 2202 | − int lua_getref (lua_State *L, int ref); | |
| 2203 | − void lua_unref (lua_State *L, int ref); | |
| 2204 | −</PRE> | |
| 2205 | −<P> | |
| 2206 | −<CODE>lua_ref</CODE> pops a value from | |
| 2207 | −the stack, creates a reference to it, | |
| 2208 | −and returns this reference. | |
| 2209 | −For a <B>nil</B> value, | |
| 2210 | −the reference is always <CODE>LUA_REFNIL</CODE>.<A NAME="LUA_REFNIL"></A> | |
| 2211 | −(<CODE>lua.h</CODE> also defines a constant <CODE>LUA_NOREF</CODE> <A NAME="LUA_NOREF"></A> | |
| 2212 | −that | |
| 2213 | −is different from any valid reference.) | |
| 2214 | −If <CODE>lock</CODE> is not zero, then the object is <EM>locked</EM>: | |
| 2215 | −this means the object will not be garbage collected. | |
| 2216 | −<EM>Unlocked references may be garbage collected</EM>. | |
| 2217 | −<P> | |
| 2218 | −Whenever the referenced object is needed in C, | |
| 2219 | −a call to <CODE>lua_getref</CODE> | |
| 2220 | −pushes that object onto the stack; | |
| 2221 | −if the object has been collected, | |
| 2222 | −<CODE>lua_getref</CODE> returns 0 (and does not push anything). | |
| 2223 | −<P> | |
| 2224 | −When a reference is no longer needed, | |
| 2225 | −it should be released with a call to <CODE>lua_unref</CODE>. | |
| 2226 | −<P> | |
| 2227 | −<P> | |
| 2228 | −<h3>Registry</h3> | |
| 2229 | −<P> | |
| 2230 | −When Lua starts, it registers a table at position | |
| 2231 | −<A NAME="LUA_REFREGISTRY"><TT>LUA_REFREGISTRY</TT></A>. | |
| 2232 | −It can be accessed through the macro<A NAME="lua_getregistry"></A> | |
| 2233 | −<PRE> | |
| 2234 | − #define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) | |
| 2235 | −</PRE> | |
| 2236 | −This table can be used by C libraries as a general registry mechanism. | |
| 2499 | +(<code>lua_pushcclosure</code> also pops these values from the stack); | |
| 2500 | +in fact, the macro <code>lua_pushcfunction</code> is defined as | |
| 2501 | +<code>lua_pushcclosure</code> with <code>n</code> set to 0. | |
| 2502 | + | |
| 2503 | +<p>Then, whenever the C function is called, | |
| 2504 | +those values are located at specific pseudo-indices. | |
| 2505 | +Those pseudo-indices are produced by a macro <code>lua_upvalueindex</code>. | |
| 2506 | +The first value associated with a function is at position | |
| 2507 | +<code>lua_upvalueindex(1)</code>, and so on. | |
| 2508 | +Any access to <code>lua_upvalueindex(<em>n</em>)</code>, | |
| 2509 | +where <em>n</em> is greater than the number of upvalues of the | |
| 2510 | +current function, | |
| 2511 | +produces an acceptable (but invalid) index. | |
| 2512 | + | |
| 2513 | +<p>For examples of C functions and closures, | |
| 2514 | +see the standard libraries in the official Lua distribution | |
| 2515 | +(<code>src/lib/*.c</code>). | |
| 2516 | + | |
| 2517 | +<p><a name="registry"><h2>3.18 - Registry</h2></a> | |
| 2518 | + | |
| 2519 | +<p>Lua provides a registry, | |
| 2520 | +a pre-defined table that can be used by any C code to | |
| 2521 | +store whatever Lua value it needs to store, | |
| 2522 | +specially if the C code needs to keep that Lua value | |
| 2523 | +outside the life span of a C function. | |
| 2524 | +This table is always located at pseudo-index | |
| 2525 | +<code>LUA_REGISTRYINDEX</code>. | |
| 2237 | 2526 | Any C library can store data into this table, |
| 2238 | −as long as it chooses a key different from other libraries. | |
| 2239 | −<P> | |
| 2240 | −<P> | |
| 2241 | −<!-- ====================================================================== --> | |
| 2242 | −<HR> | |
| 2243 | −<A NAME="6."></A> | |
| 2244 | −<H1>6 - Standard Libraries</H1> | |
| 2245 | −<P> | |
| 2246 | −The standard libraries provide useful functions | |
| 2247 | −that are implemented directly through the standard API. | |
| 2248 | −Therefore, they are not necessary to the language, | |
| 2249 | −and are provided as separate C modules. | |
| 2250 | −Currently, Lua has the following standard libraries: | |
| 2251 | −<UL> | |
| 2252 | −<LI>basic library; | |
| 2253 | −<LI>string manipulation; | |
| 2254 | −<LI>mathematical functions (sin, log, etc); | |
| 2255 | −<LI>input and output (plus some system facilities). | |
| 2256 | −</UL> | |
| 2257 | −To have access to these libraries, | |
| 2258 | −the C host program must call the functions | |
| 2259 | −<CODE>lua_baselibopen</CODE>, | |
| 2260 | −<CODE>lua_strlibopen</CODE>, <CODE>lua_mathlibopen</CODE>, | |
| 2261 | −and <CODE>lua_iolibopen</CODE>, which are declared in <CODE>lualib.h</CODE>. | |
| 2262 | −<A NAME="lua_baselibopen"></A> | |
| 2263 | −<A NAME="lua_strlibopen"></A> | |
| 2264 | −<A NAME="lua_mathlibopen"></A> | |
| 2265 | −<A NAME="lua_iolibopen"></A> | |
| 2266 | −<P> | |
| 2267 | −<A NAME="predefined"></A> | |
| 2268 | −<A NAME="6.1"></A> | |
| 2269 | −<H2>6.1 - Basic Functions</H2> | |
| 2270 | −<P> | |
| 2271 | −The basic library provides some core functions to Lua. | |
| 2272 | −Therefore, if you do not include this library in your application, | |
| 2273 | −you should check carefully whether you need to provide some alternative | |
| 2274 | −implementation for some facilities. | |
| 2275 | −(For instance, | |
| 2276 | −without function <CODE>_ERRORMESSAGE</CODE>, | |
| 2277 | −Lua is unable to show error messages.) | |
| 2278 | −<P> | |
| 2279 | −<A NAME="alert"></A> | |
| 2280 | −<h3> <TT>_ALERT (message)</TT></h3><A NAME="alert"></A> | |
| 2281 | −Prints its only string argument to <A NAME="stderr"><TT>stderr</TT></A>. | |
| 2282 | −All error messages in Lua are printed through the function stored | |
| 2283 | −in the <CODE>_ALERT</CODE> global variable | |
| 2284 | −(see Section <A HREF="#error">4.7</A>). | |
| 2285 | −Therefore, a program may assign another function to this variable | |
| 2286 | −to change the way such messages are shown | |
| 2287 | −(for instance, for systems without <CODE>stderr</CODE>). | |
| 2288 | −<P> | |
| 2289 | −<h3> <TT>assert (v [, message])</TT></h3><A NAME="assert"></A> | |
| 2290 | −Issues an <EM>``assertion failed!''</EM> error | |
| 2291 | −when its argument <CODE>v</CODE> is <B>nil</B>. | |
| 2292 | −This function is equivalent to the following Lua function: | |
| 2293 | −<PRE> | |
| 2294 | − function assert (v, m) | |
| 2295 | − if not v then | |
| 2296 | − m = m or "" | |
| 2297 | − error("assertion failed! " .. m) | |
| 2298 | − end | |
| 2299 | − end | |
| 2300 | −</PRE> | |
| 2301 | −<P> | |
| 2302 | −<h3> <TT>call (func, arg [, mode [, errhandler]])</TT></h3><A NAME="call"></A> | |
| 2303 | −<A NAME="pdf-call"></A> | |
| 2304 | − | |
| 2305 | −Calls function <CODE>func</CODE> with | |
| 2306 | −the arguments given by the table <CODE>arg</CODE>. | |
| 2307 | −The call is equivalent to | |
| 2308 | −<PRE> | |
| 2309 | − func(arg[1], arg[2], ..., arg[n]) | |
| 2310 | −</PRE> | |
| 2311 | −where <CODE>n</CODE> is the result of <CODE>getn(arg)</CODE> (see Section <A HREF="#getn">6.1</A>). | |
| 2312 | −All results from <CODE>func</CODE> are simply returned by <CODE>call</CODE>. | |
| 2313 | −<P> | |
| 2314 | −By default, | |
| 2315 | −if an error occurs during the call to <CODE>func</CODE>, | |
| 2316 | −the error is propagated. | |
| 2317 | −If the string <CODE>mode</CODE> contains <CODE>"x"</CODE>, | |
| 2318 | −then the call is <EM>protected</EM>.<A NAME="protected calls"></A> | |
| 2319 | −In this mode, function <CODE>call</CODE> does not propagate an error, | |
| 2320 | −regardless of what happens during the call. | |
| 2321 | −Instead, it returns <B>nil</B> to signal the error | |
| 2322 | −(besides calling the appropriated error handler). | |
| 2323 | −<P> | |
| 2324 | −If <CODE>errhandler</CODE> is provided, | |
| 2325 | −the error function <CODE>_ERRORMESSAGE</CODE> is temporarily set to <CODE>errhandler</CODE>, | |
| 2326 | −while <CODE>func</CODE> runs. | |
| 2327 | −In particular, if <CODE>errhandler</CODE> is <B>nil</B>, | |
| 2328 | −no error messages will be issued during the execution of the called function. | |
| 2329 | −<P> | |
| 2330 | −<h3> <TT>collectgarbage ([limit])</TT></h3><A NAME="collectgarbage"></A> | |
| 2331 | −<P> | |
| 2332 | −Sets the garbage-collection threshold for the given limit | |
| 2333 | −(in Kbytes), and checks it against the byte counter. | |
| 2334 | −If the new threshold is smaller than the byte counter, | |
| 2335 | −then Lua immediately runs the garbage collector (see Section <A HREF="#GC">5.6</A>). | |
| 2336 | −If <CODE>limit</CODE> is absent, it defaults to zero | |
| 2337 | −(thus forcing a garbage-collection cycle). | |
| 2338 | −<P> | |
| 2339 | −<h3> <TT>copytagmethods (tagto, tagfrom)</TT></h3> | |
| 2340 | −<A NAME="copytagmethods"></A> | |
| 2341 | −Copies all tag methods from one tag to another; | |
| 2342 | −returns <CODE>tagto</CODE>. | |
| 2343 | −<P> | |
| 2344 | −<h3> <TT>dofile (filename)</TT></h3><A NAME="dofile"></A> | |
| 2345 | −Receives a file name, | |
| 2346 | −opens the named file, and executes its contents as a Lua chunk, | |
| 2347 | −or as pre-compiled chunks. | |
| 2348 | −When called without arguments, | |
| 2349 | −<CODE>dofile</CODE> executes the contents of the standard input (<CODE>stdin</CODE>). | |
| 2350 | −If there is any error executing the file, | |
| 2351 | −then <CODE>dofile</CODE> returns <B>nil</B>. | |
| 2352 | −Otherwise, it returns the values returned by the chunk, | |
| 2353 | −or a non-<B>nil</B> value if the chunk returns no values. | |
| 2354 | −It issues an error when called with a non-string argument. | |
| 2355 | −<P> | |
| 2356 | −<h3> <TT>dostring (string [, chunkname])</TT></h3><A NAME="dostring"></A> | |
| 2357 | −Executes a given string as a Lua chunk. | |
| 2358 | −If there is any error executing the string, | |
| 2359 | −then <CODE>dostring</CODE> returns <B>nil</B>. | |
| 2360 | −Otherwise, it returns the values returned by the chunk, | |
| 2361 | −or a non-<B>nil</B> value if the chunk returns no values. | |
| 2362 | −The optional parameter <CODE>chunkname</CODE> | |
| 2363 | −is the ``name of the chunk'', | |
| 2364 | −used in error messages and debug information. | |
| 2365 | −<P> | |
| 2366 | −<A NAME="pdf-error"></A> | |
| 2367 | −<h3> <TT>error (message)</TT></h3><A NAME="error"></A> | |
| 2368 | −Calls the error handler (see Section <A HREF="#error">4.7</A>) and then terminates | |
| 2369 | −the last protected function called | |
| 2370 | −(in C: <CODE>lua_dofile</CODE>, <CODE>lua_dostring</CODE>, | |
| 2371 | −<CODE>lua_dobuffer</CODE>, or <CODE>lua_callfunction</CODE>; | |
| 2372 | −in Lua: <CODE>dofile</CODE>, <CODE>dostring</CODE>, or <CODE>call</CODE> in protected mode). | |
| 2373 | −If <CODE>message</CODE> is <B>nil</B>, then the error handler is not called. | |
| 2374 | −Function <CODE>error</CODE> never returns. | |
| 2375 | −<P> | |
| 2376 | −<h3> <TT>foreach (table, func)</TT></h3><A NAME="foreach"></A> | |
| 2377 | −Executes the given <CODE>func</CODE> over all elements of <CODE>table</CODE>. | |
| 2378 | −For each element, the function is called with the index and | |
| 2379 | −respective value as arguments. | |
| 2380 | −If the function returns any non-<B>nil</B> value, | |
| 2381 | −then the loop is broken, and this value is returned | |
| 2382 | −as the final value of <CODE>foreach</CODE>. | |
| 2383 | −This function could be defined in Lua: | |
| 2527 | +as long as it chooses keys different from other libraries. | |
| 2528 | +Typically, you should use as key a string containing your library name | |
| 2529 | +or a light userdata with the address of a C object in your code. | |
| 2530 | + | |
| 2531 | +<p>The integer keys in the registry are used by the reference mechanism, | |
| 2532 | +implemented by the auxiliary library, | |
| 2533 | +and therefore should not be used by other purposes. | |
| 2534 | + | |
| 2535 | +<p><h2>3.19 - Error Handling in C</h2> | |
| 2536 | + | |
| 2537 | +<p>Internally, Lua uses the C <code>longjmp</code> facility to handle errors. | |
| 2538 | +When Lua faces any error | |
| 2539 | +(such as memory allocation errors, type errors, syntax errors) | |
| 2540 | +it <em>raises</em> an error, that is, it does a long jump. | |
| 2541 | +A <em>protected environment</em> uses <code>setjmp</code> | |
| 2542 | +to set a recover point, | |
| 2543 | +and any error jumps to the most recent active recover point. | |
| 2544 | + | |
| 2545 | +<p>If an error happens outside any protected environment, | |
| 2546 | +Lua calls a <em>panic function</em>, | |
| 2547 | +and then calls <code>exit(EXIT_FAILURE)</code>. | |
| 2548 | +You can change the panic function with | |
| 2384 | 2549 | <PRE> |
| 2385 | − function foreach (t, f) | |
| 2386 | − for i, v in t do | |
| 2387 | − local res = f(i, v) | |
| 2388 | − if res then return res end | |
| 2389 | − end | |
| 2390 | − end | |
| 2550 | + lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); | |
| 2391 | 2551 | </PRE> |
| 2392 | −<P> | |
| 2393 | −The behavior of <CODE>foreach</CODE> is <EM>undefined</EM> if you change | |
| 2394 | −the table <CODE>t</CODE> during the traversal. | |
| 2395 | −<P> | |
| 2396 | −<P> | |
| 2397 | −<h3> <TT>foreachi (table, func)</TT></h3><A NAME="foreachi"></A> | |
| 2398 | −Executes the given <CODE>func</CODE> over the | |
| 2399 | −numerical indices of <CODE>table</CODE>. | |
| 2400 | −For each index, the function is called with the index and | |
| 2401 | −respective value as arguments. | |
| 2402 | −Indices are visited in sequential order, | |
| 2403 | −from 1 to <CODE>n</CODE>, | |
| 2404 | −where <CODE>n</CODE> is the result of <CODE>getn(table)</CODE> (see Section <A HREF="#getn">6.1</A>). | |
| 2405 | −If the function returns any non-<B>nil</B> value, | |
| 2406 | −then the loop is broken, and this value is returned | |
| 2407 | −as the final value of <CODE>foreachi</CODE>. | |
| 2408 | −This function could be defined in Lua: | |
| 2552 | +Your new panic function may avoid the application exit by | |
| 2553 | +never returning (e.g. doing a long jump). | |
| 2554 | +Nevertheless, the corresponding Lua will not be consistent; | |
| 2555 | +the only safe operation with it is to close it. | |
| 2556 | + | |
| 2557 | +<p>Almost any function in the API may raise an error, | |
| 2558 | +for instance due to a memory allocation error. | |
| 2559 | +The following functions run in protected mode | |
| 2560 | +(that is, they create a protected environment to run), | |
| 2561 | +so they never raise an error: | |
| 2562 | +<code>lua_open</code>, <code>lua_close</code>, <code>lua_load</code>, | |
| 2563 | +and <code>lua_pcall</code>. | |
| 2564 | + | |
| 2565 | +<p>There is yet another function that runs a given C function in protected mode: | |
| 2409 | 2566 | <PRE> |
| 2410 | − function foreachi (t, f) | |
| 2411 | − for i=1,getn(t) do | |
| 2412 | − local res = f(i, t[i]) | |
| 2413 | − if res then return res end | |
| 2414 | − end | |
| 2415 | − end | |
| 2567 | + int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); | |
| 2416 | 2568 | </PRE> |
| 2417 | −<P> | |
| 2418 | −<P> | |
| 2419 | −<h3> <TT>getglobal (name)</TT></h3><A NAME="getglobal"></A> | |
| 2420 | −Gets the value of a global variable, | |
| 2421 | −or calls a tag method for ``getglobal''. | |
| 2422 | −Its full semantics is explained in Section <A HREF="#tag-method">4.8</A>. | |
| 2423 | −The string <CODE>name</CODE> does not need to be a | |
| 2424 | −syntactically valid variable name. | |
| 2425 | −<P> | |
| 2426 | −<A NAME="getn"></A> | |
| 2427 | −<h3> <TT>getn (table)</TT></h3><A NAME="getn"></A> | |
| 2428 | −Returns the ``size'' of a table, when seen as a list. | |
| 2429 | −If the table has an <CODE>n</CODE> field with a numeric value, | |
| 2430 | −this value is the ``size'' of the table. | |
| 2431 | −Otherwise, the ``size'' is the largest numerical index with a non-nil | |
| 2432 | −value in the table. | |
| 2433 | −This function could be defined in Lua: | |
| 2434 | −<PRE> | |
| 2435 | − function getn (t) | |
| 2436 | − if type(t.n) == "number" then return t.n end | |
| 2437 | − local max = 0 | |
| 2438 | − for i, _ in t do | |
| 2439 | − if type(i) == "number" and i>max then max=i end | |
| 2440 | − end | |
| 2441 | − return max | |
| 2442 | − end | |
| 2569 | + | |
| 2570 | +<code>lua_cpcall</code> calls <code>func</code> in protected mode. | |
| 2571 | +<code>func</code> starts with only one element in its stack, | |
| 2572 | +a light userdata containing <code>ud</code>. | |
| 2573 | +In case of errors, | |
| 2574 | +<code>lua_cpcall</code> returns the same error codes as <code>lua_pcall</code> | |
| 2575 | +(see <a href="#lua_pcall">3.15</a>), | |
| 2576 | +plus the error object on the top of the stack; | |
| 2577 | +otherwise, it returns zero, and does not change the stack. | |
| 2578 | +Any value returned by <code>func</code> is dicarded. | |
| 2579 | + | |
| 2580 | +<p>C code can generate a Lua error calling the function | |
| 2581 | +<PRE> | |
| 2582 | + void lua_error (lua_State *L); | |
| 2443 | 2583 | </PRE> |
| 2444 | −<P> | |
| 2445 | −<h3> <TT>gettagmethod (tag, event)</TT></h3> | |
| 2446 | −<A NAME="gettagmethod"></A> | |
| 2447 | −Returns the current tag method | |
| 2448 | −for a given pair <EM>(tag, event)</EM>. | |
| 2449 | −This function cannot be used to get a tag method for the ``gc'' event. | |
| 2450 | −(Such tag methods can only be manipulated by C code.) | |
| 2451 | −<P> | |
| 2452 | −<h3> <TT>globals ([table])</TT></h3><A NAME="globals"></A> | |
| 2453 | −Returns the current table of globals. | |
| 2454 | −If the argument <CODE>table</CODE> is given, | |
| 2455 | −then it also sets this table as the table of globals. | |
| 2456 | −<P> | |
| 2457 | −<A NAME="pdf-newtag"></A> | |
| 2458 | −<h3> <TT>newtag ()</TT></h3><A NAME="newtag"></A> | |
| 2459 | −Returns a new tag. | |
| 2460 | −<P> | |
| 2461 | −<h3> <TT>next (table, [index])</TT></h3><A NAME="next"></A> | |
| 2462 | −Allows a program to traverse all fields of a table. | |
| 2463 | −Its first argument is a table and its second argument | |
| 2464 | −is an index in this table. | |
| 2465 | −<CODE>next</CODE> returns the next index of the table and the | |
| 2466 | −value associated with the index. | |
| 2467 | −When called with <B>nil</B> as its second argument, | |
| 2468 | −<CODE>next</CODE> returns the first index | |
| 2469 | −of the table and its associated value. | |
| 2470 | −When called with the last index, | |
| 2471 | −or with <B>nil</B> in an empty table, | |
| 2472 | −<CODE>next</CODE> returns <B>nil</B>. | |
| 2473 | −If the second argument is absent, then it is interpreted as <B>nil</B>. | |
| 2474 | −<P> | |
| 2475 | −Lua has no declaration of fields; | |
| 2476 | −semantically, there is no difference between a | |
| 2477 | −field not present in a table or a field with value <B>nil</B>. | |
| 2478 | −Therefore, <CODE>next</CODE> only considers fields with non-<B>nil</B> values. | |
| 2479 | −The order in which the indices are enumerated is not specified, | |
| 2480 | −<EM>even for numeric indices</EM> | |
| 2481 | −(to traverse a table in numeric order, | |
| 2482 | −use a numerical <B>for</B> or the function <CODE>foreachi</CODE>). | |
| 2483 | −<P> | |
| 2484 | −The behavior of <CODE>next</CODE> is <EM>undefined</EM> if you change | |
| 2485 | −the table during the traversal. | |
| 2486 | −<P> | |
| 2487 | −<h3> <TT>print (e1, e2, ...)</TT></h3><A NAME="print"></A> | |
| 2488 | −Receives any number of arguments, | |
| 2489 | −and prints their values using the strings returned by <CODE>tostring</CODE>. | |
| 2490 | −This function is not intended for formatted output, | |
| 2491 | −but only as a quick way to show a value, | |
| 2492 | −for instance for debugging. | |
| 2493 | −See Section <A HREF="#libio">6.4</A> for functions for formatted output. | |
| 2494 | −<P> | |
| 2495 | −<h3> <TT>rawget (table, index)</TT></h3><A NAME="rawget"></A> | |
| 2496 | −Gets the real value of <CODE>table[index]</CODE>, | |
| 2497 | −without invoking any tag method. | |
| 2498 | −<CODE>table</CODE> must be a table, | |
| 2499 | −and <CODE>index</CODE> is any value different from <B>nil</B>. | |
| 2500 | −<P> | |
| 2501 | −<h3> <TT>rawset (table, index, value)</TT></h3><A NAME="rawset"></A> | |
| 2502 | −Sets the real value of <CODE>table[index]</CODE> to <CODE>value</CODE>, | |
| 2503 | −without invoking any tag method. | |
| 2504 | −<CODE>table</CODE> must be a table, | |
| 2505 | −<CODE>index</CODE> is any value different from <B>nil</B>, | |
| 2506 | −and <CODE>value</CODE> is any Lua value. | |
| 2507 | −<P> | |
| 2508 | −<h3> <TT>setglobal (name, value)</TT></h3><A NAME="setglobal"></A> | |
| 2509 | −Sets the named global variable to the given value, | |
| 2510 | −or calls a tag method for ``setglobal''. | |
| 2511 | −Its full semantics is explained in Section <A HREF="#tag-method">4.8</A>. | |
| 2512 | −The string <CODE>name</CODE> does not need to be a | |
| 2513 | −syntactically valid variable name. | |
| 2514 | −<P> | |
| 2515 | −<h3> <TT>settag (t, tag)</TT></h3><A NAME="settag"></A> | |
| 2516 | −Sets the tag of a given table (see Section <A HREF="#TypesSec">3</A>). | |
| 2517 | −<CODE>tag</CODE> must be a value created with <CODE>newtag</CODE> | |
| 2518 | −(see Section <A HREF="#pdf-newtag">6.1</A>). | |
| 2519 | −<CODE>settag</CODE> returns the value of its first argument (the table). | |
| 2520 | −For the safety of host programs, | |
| 2521 | −it is impossible to change the tag of a userdata from Lua. | |
| 2522 | −<P> | |
| 2523 | −<h3> <TT>settagmethod (tag, event, newmethod)</TT></h3> | |
| 2524 | −<A NAME="settagmethod"></A> | |
| 2525 | −Sets a new tag method to the given pair <EM>(tag, event)</EM> and | |
| 2526 | −returns the old method. | |
| 2527 | −If <CODE>newmethod</CODE> is <B>nil</B>, | |
| 2528 | −then <CODE>settagmethod</CODE> restores the default behavior for the given event. | |
| 2529 | −This function cannot be used to set a tag method for the ``gc'' event. | |
| 2530 | −(Such tag methods can only be manipulated by C code.) | |
| 2531 | −<P> | |
| 2532 | −<h3> <TT>sort (table [, comp])</TT></h3><A NAME="sort"></A> | |
| 2533 | −Sorts table elements in a given order, <EM>in-place</EM>, | |
| 2534 | −from <CODE>table[1]</CODE> to <CODE>table[n]</CODE>, | |
| 2535 | −where <CODE>n</CODE> is the result of <CODE>getn(table)</CODE> (see Section <A HREF="#getn">6.1</A>). | |
| 2536 | −If <CODE>comp</CODE> is given, | |
| 2537 | −then it must be a function that receives two table elements, | |
| 2538 | −and returns true (that is, a value different from <B>nil</B>) | |
| 2539 | −when the first is less than the second | |
| 2540 | −(so that <CODE>not comp(a[i+1], a[i])</CODE> will be true after the sort). | |
| 2541 | −If <CODE>comp</CODE> is not given, | |
| 2542 | −then the standard Lua operator <CODE><</CODE> is used instead. | |
| 2543 | −<P> | |
| 2544 | −The sort algorithm is <EM>not</EM> stable | |
| 2545 | −(that is, elements considered equal by the given order | |
| 2546 | −may have their relative positions changed by the sort). | |
| 2547 | −<P> | |
| 2548 | −<A NAME="pdf-tag"></A> | |
| 2549 | −<h3> <TT>tag (v)</TT></h3><A NAME="tag"></A> | |
| 2550 | −Allows Lua programs to test the tag of a value (see Section <A HREF="#TypesSec">3</A>). | |
| 2551 | −It receives one argument, and returns its tag (a number). | |
| 2552 | −<P> | |
| 2553 | −<h3> <TT>tonumber (e [, base])</TT></h3><A NAME="tonumber"></A> | |
| 2554 | −Tries to convert its argument to a number. | |
| 2555 | −If the argument is already a number or a string convertible | |
| 2556 | −to a number, then <CODE>tonumber</CODE> returns that number; | |
| 2557 | −otherwise, it returns <B>nil</B>. | |
| 2558 | −<P> | |
| 2559 | −An optional argument specifies the base to interpret the numeral. | |
| 2560 | −The base may be any integer between 2 and 36, inclusive. | |
| 2561 | −In bases above 10, the letter `A' (either upper or lower case) | |
| 2562 | −represents 10, `B' represents 11, and so forth, with `Z' representing 35. | |
| 2563 | −In base 10 (the default), the number may have a decimal part, | |
| 2564 | −as well as an optional exponent part (see Section <A HREF="#coercion">4.2</A>). | |
| 2565 | −In other bases, only unsigned integers are accepted. | |
| 2566 | −<P> | |
| 2567 | −<h3> <TT>tostring (e)</TT></h3><A NAME="tostring"></A> | |
| 2568 | −Receives an argument of any type and | |
| 2569 | −converts it to a string in a reasonable format. | |
| 2570 | −For complete control of how numbers are converted, | |
| 2571 | −use function <CODE>format</CODE>. | |
| 2572 | −<P> | |
| 2573 | −<P> | |
| 2574 | −<P> | |
| 2575 | −<h3> <TT>tinsert (table [, pos] , value)</TT></h3><A NAME="tinsert"></A> | |
| 2576 | −<P> | |
| 2577 | −Inserts element <CODE>value</CODE> at table position <CODE>pos</CODE>, | |
| 2578 | −shifting other elements to open space, if necessary. | |
| 2579 | −The default value for <CODE>pos</CODE> is <CODE>n+1</CODE>, | |
| 2580 | −where <CODE>n</CODE> is the result of <CODE>getn(table)</CODE> (see Section <A HREF="#getn">6.1</A>), | |
| 2581 | −so that a call <CODE>tinsert(t,x)</CODE> inserts <CODE>x</CODE> at the end | |
| 2582 | −of table <CODE>t</CODE>. | |
| 2583 | −This function also sets or increments the field <CODE>n</CODE> of the table | |
| 2584 | −to <CODE>n+1</CODE>. | |
| 2585 | −This function is equivalent to the following Lua function, | |
| 2586 | −except that the table accesses are all <EM>raw</EM> | |
| 2587 | −(that is, without tag methods): | |
| 2588 | −<PRE> | |
| 2589 | − function tinsert (t, ...) | |
| 2590 | − local pos, value | |
| 2591 | − local n = getn(t) | |
| 2592 | − if arg.n == 1 then | |
| 2593 | − pos, value = n+1, arg[1] | |
| 2594 | − else | |
| 2595 | − pos, value = arg[1], arg[2] | |
| 2596 | − end | |
| 2597 | − t.n = n+1; | |
| 2598 | − for i=n,pos,-1 do | |
| 2599 | − t[i+1] = t[i] | |
| 2600 | − end | |
| 2601 | − t[pos] = value | |
| 2602 | − end | |
| 2584 | + | |
| 2585 | +The error message (which actually can be any type of object) | |
| 2586 | +must be on the stack top. | |
| 2587 | +This function does a long jump, | |
| 2588 | +and therefore never returns. | |
| 2589 | + | |
| 2590 | +<p><h2>3.20 - Threads</h2> | |
| 2591 | + | |
| 2592 | +<p>Lua offers partial support for multiple threads of execution. | |
| 2593 | +If you have a C library that offers multi-threading, | |
| 2594 | +then Lua can cooperate with it to implement the equivalent facility in Lua. | |
| 2595 | +Also, Lua implements its own coroutine system on top of threads. | |
| 2596 | +The following function creates a new thread in Lua: | |
| 2597 | +<PRE> | |
| 2598 | + lua_State *lua_newthread (lua_State *L); | |
| 2603 | 2599 | </PRE> |
| 2604 | −<P> | |
| 2605 | −<h3> <TT>tremove (table [, pos])</TT></h3><A NAME="tremove"></A> | |
| 2606 | −<P> | |
| 2607 | −Removes from <CODE>table</CODE> the element at position <CODE>pos</CODE>, | |
| 2608 | −shifting other elements to close the space, if necessary. | |
| 2609 | −Returns the value of the removed element. | |
| 2610 | −The default value for <CODE>pos</CODE> is <CODE>n</CODE>, | |
| 2611 | −where <CODE>n</CODE> is the result of <CODE>getn(table)</CODE> (see Section <A HREF="#getn">6.1</A>), | |
| 2612 | −so that a call <CODE>tremove(t)</CODE> removes the last element | |
| 2613 | −of table <CODE>t</CODE>. | |
| 2614 | −This function also sets or decrements the field <CODE>n</CODE> of the table | |
| 2615 | −to <CODE>n-1</CODE>. | |
| 2616 | −<P> | |
| 2617 | −This function is equivalent to the following Lua function, | |
| 2618 | −except that the table accesses are all <EM>raw</EM> | |
| 2619 | −(that is, without tag methods): | |
| 2620 | −<PRE> | |
| 2621 | − function tremove (t, pos) | |
| 2622 | − local n = getn(t) | |
| 2623 | − if n<=0 then return end | |
| 2624 | − pos = pos or n | |
| 2625 | − local value = t[pos] | |
| 2626 | − for i=pos,n-1 do | |
| 2627 | − t[i] = t[i+1] | |
| 2628 | − end | |
| 2629 | − t[n] = nil | |
| 2630 | − t.n = n-1 | |
| 2631 | − return value | |
| 2632 | − end | |
| 2600 | + | |
| 2601 | +This function pushes the thread on the stack and returns a pointer to | |
| 2602 | +a <code>lua_State</code> that represents this new thread. | |
| 2603 | +The new state returned by this function shares with the original state | |
| 2604 | +all global objects (such as tables), | |
| 2605 | +but has an independent run-time stack. | |
| 2606 | + | |
| 2607 | +<p>Each thread has an independent global environment table. | |
| 2608 | +When you create a thread, this table is the same as that of the given state, | |
| 2609 | +but you can change each one independently. | |
| 2610 | + | |
| 2611 | +<p>You destroy threads with <code>lua_closethread</code>: | |
| 2612 | +<PRE> | |
| 2613 | + void lua_closethread (lua_State *L, lua_State *thread); | |
| 2633 | 2614 | </PRE> |
| 2634 | −<P> | |
| 2635 | −<A NAME="pdf-type"></A> | |
| 2636 | −<h3> <TT>type (v)</TT></h3><A NAME="type"></A> | |
| 2637 | −Allows Lua programs to test the type of a value. | |
| 2638 | −It receives one argument, and returns its type, coded as a string. | |
| 2639 | −The possible results of this function are | |
| 2640 | −<CODE>"nil"</CODE> (a string, not the value <B>nil</B>), | |
| 2641 | −<CODE>"number"</CODE>, | |
| 2642 | −<CODE>"string"</CODE>, | |
| 2643 | −<CODE>"table"</CODE>, | |
| 2644 | −<CODE>"function"</CODE>, | |
| 2645 | −and <CODE>"userdata"</CODE>. | |
| 2646 | −<P> | |
| 2647 | −<P> | |
| 2648 | −<A NAME="6.2"></A> | |
| 2649 | −<H2>6.2 - String Manipulation</H2> | |
| 2650 | −This library provides generic functions for string manipulation, | |
| 2651 | −such as finding and extracting substrings and pattern matching. | |
| 2652 | −When indexing a string in Lua, the first character is at position 1 | |
| 2653 | −(not at 0, as in C). | |
| 2654 | −Also, | |
| 2655 | −indices are allowed to be negative and are intepreted as indexing backwards, | |
| 2656 | −from the end of the string. Thus, the last character is at position <I>-1</I>, | |
| 2657 | −and so on. | |
| 2658 | −<P> | |
| 2659 | −<h3> <TT>strbyte (s [, i])</TT></h3><A NAME="strbyte"></A> | |
| 2660 | −Returns the internal numerical code of the <EM>i</EM>-th character of <CODE>s</CODE>. | |
| 2661 | −If <CODE>i</CODE> is absent, then it is assumed to be 1. | |
| 2662 | −<CODE>i</CODE> may be negative. | |
| 2663 | −<P> | |
| 2664 | −Numerical codes are not necessarily portable across platforms. | |
| 2665 | −<P> | |
| 2666 | −<h3> <TT>strchar (i1, i2, ...)</TT></h3><A NAME="strchar"></A> | |
| 2667 | −Receives 0 or more integers. | |
| 2668 | −Returns a string with length equal to the number of arguments, | |
| 2669 | −wherein each character has the internal numerical code equal | |
| 2670 | −to its correspondent argument. | |
| 2671 | −<P> | |
| 2672 | −Numerical codes are not necessarily portable across platforms. | |
| 2673 | −<P> | |
| 2674 | −<h3> <TT>strfind (s, pattern [, init [, plain]])</TT></h3> | |
| 2675 | −<A NAME="strfind"></A> | |
| 2676 | −Looks for the first <EM>match</EM> of | |
| 2677 | −<CODE>pattern</CODE> in <CODE>s</CODE>. | |
| 2678 | −If it finds one, then <CODE>strfind</CODE> returns the indices of <CODE>s</CODE> | |
| 2679 | −where this occurrence starts and ends; | |
| 2680 | −otherwise, it returns <B>nil</B>. | |
| 2681 | −If the pattern specifies captures (see <CODE>gsub</CODE> below), | |
| 2682 | −the captured strings are returned as extra results. | |
| 2683 | −A third, optional numerical argument <CODE>init</CODE> specifies | |
| 2684 | −where to start the search; | |
| 2685 | −its default value is 1, and may be negative. | |
| 2686 | −A value of 1 as a fourth, optional argument <CODE>plain</CODE> | |
| 2687 | −turns off the pattern matching facilities, | |
| 2688 | −so the function does a plain ``find substring'' operation, | |
| 2689 | −with no characters in <CODE>pattern</CODE> being considered ``magic''. | |
| 2690 | −Note that if <CODE>plain</CODE> is given, then <CODE>init</CODE> must be given too. | |
| 2691 | −<P> | |
| 2692 | −<h3> <TT>strlen (s)</TT></h3><A NAME="strlen"></A> | |
| 2693 | −Receives a string and returns its length. | |
| 2694 | −The empty string <CODE>""</CODE> has length 0. | |
| 2695 | −Embedded zeros are counted, | |
| 2696 | −and so <CODE>"a\000b\000c"</CODE> has length 5. | |
| 2697 | −<P> | |
| 2698 | −<h3> <TT>strlower (s)</TT></h3><A NAME="strlower"></A> | |
| 2699 | −Receives a string and returns a copy of that string with all | |
| 2700 | −upper case letters changed to lower case. | |
| 2701 | −All other characters are left unchanged. | |
| 2702 | −The definition of what is an upper-case | |
| 2703 | −letter depends on the current locale. | |
| 2704 | −<P> | |
| 2705 | −<h3> <TT>strrep (s, n)</TT></h3><A NAME="strrep"></A> | |
| 2706 | −Returns a string that is the concatenation of <CODE>n</CODE> copies of | |
| 2707 | −the string <CODE>s</CODE>. | |
| 2708 | −<P> | |
| 2709 | −<h3> <TT>strsub (s, i [, j])</TT></h3><A NAME="strsub"></A> | |
| 2710 | −Returns another string, which is a substring of <CODE>s</CODE>, | |
| 2711 | −starting at <CODE>i</CODE> and running until <CODE>j</CODE>; | |
| 2712 | −<CODE>i</CODE> and <CODE>j</CODE> may be negative, | |
| 2713 | −If <CODE>j</CODE> is absent, then it is assumed to be equal to <I>-1</I> | |
| 2714 | −(which is the same as the string length). | |
| 2715 | −In particular, | |
| 2716 | −the call <CODE>strsub(s,1,j)</CODE> returns a prefix of <CODE>s</CODE> | |
| 2717 | −with length <CODE>j</CODE>, | |
| 2718 | −and the call <CODE>strsub(s, -i)</CODE> returns a suffix of <CODE>s</CODE> | |
| 2719 | −with length <CODE>i</CODE>. | |
| 2720 | −<P> | |
| 2721 | −<h3> <TT>strupper (s)</TT></h3><A NAME="strupper"></A> | |
| 2722 | −Receives a string and returns a copy of that string with all | |
| 2723 | −lower case letters changed to upper case. | |
| 2724 | −All other characters are left unchanged. | |
| 2725 | −The definition of what is a lower case | |
| 2726 | −letter depends on the current locale. | |
| 2727 | −<P> | |
| 2728 | −<h3> <TT>format (formatstring, e1, e2, ...)</TT></h3><A NAME="format"></A> | |
| 2729 | −<A NAME="format"></A> | |
| 2615 | +You cannot close the sole (or last) thread of a state. | |
| 2616 | +Instead, you must close the state itself. | |
| 2730 | 2617 | |
| 2731 | −Returns a formatted version of its variable number of arguments | |
| 2732 | −following the description given in its first argument (which must be a string). | |
| 2733 | −The format string follows the same rules as the <CODE>printf</CODE> family of | |
2983 more lines aren’t shown here.
| @@ -7,29 +7,28 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | <HR> |
| 9 | 9 | <H1> |
| 10 | −<IMG SRC="logo.gif" ALT="Lua" ALIGN="bottom"> | |
| 10 | +<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A> | |
| 11 | 11 | Documentation |
| 12 | 12 | </H1> |
| 13 | 13 | |
| 14 | 14 | <UL> |
| 15 | −<LI><A HREF="http://www.tecgraf.puc-rio.br/lua/">Official web site</A> | |
| 16 | −<LI><A HREF="index.html">Reference manual</A> | |
| 15 | +<LI><A HREF="http://www.lua.org/">Official web site</A> | |
| 16 | +<LI><A HREF="manual.html">Reference manual</A> | |
| 17 | 17 | <LI><A HREF="lua.html">lua man page</A> |
| 18 | 18 | <LI><A HREF="luac.html">luac man page</A> |
| 19 | 19 | <LI><A HREF="../README">lua/README</A> |
| 20 | +<LI><A HREF="../src/README">lua/src/README</A> | |
| 20 | 21 | <LI><A HREF="../src/lib/README">lua/src/lib/README</A> |
| 21 | 22 | <LI><A HREF="../src/lua/README">lua/src/lua/README</A> |
| 22 | 23 | <LI><A HREF="../src/luac/README">lua/src/luac/README</A> |
| 23 | 24 | <LI><A HREF="../etc/README">lua/etc/README</A> |
| 24 | 25 | <LI><A HREF="../test/README">lua/test/README</A> |
| 25 | −<LI><A HREF="../test/examples/www/README">lua/test/examples/www/README</A> | |
| 26 | 26 | </UL> |
| 27 | 27 | |
| 28 | 28 | <HR> |
| 29 | 29 | <SMALL> |
| 30 | 30 | Last update: |
| 31 | −Mon Nov 6 19:13:31 EDT 2000 | |
| 32 | −by <A HREF="http://www.tecgraf.puc-rio.br/~lhf/">lhf</A>. | |
| 31 | +Tue Apr 1 14:35:18 EST 2003 | |
| 33 | 32 | </SMALL> |
| 34 | 33 | |
| 35 | 34 | </BODY> |
| @@ -0,0 +1 @@ | ||
| 1 | +/home/n/lhf/lib/vi/c | |
| @@ -1,16 +1,14 @@ | ||
| 1 | −# makefile for etc | |
| 1 | +# makefile for Lua etc | |
| 2 | 2 | |
| 3 | 3 | LUA= .. |
| 4 | 4 | |
| 5 | 5 | include $(LUA)/config |
| 6 | 6 | |
| 7 | 7 | LIBLUA=$(LIB)/liblua.a |
| 8 | −ALL= bin2c min trace lua.def | |
| 8 | +ALL= bin2c min trace noparser luab | |
| 9 | 9 | |
| 10 | −x: | |
| 11 | − @echo 'choose a target:' all $(ALL) | |
| 12 | − | |
| 13 | −all: $(ALL) | |
| 10 | +all: | |
| 11 | + @echo 'choose a target:' $(ALL) | |
| 14 | 12 | |
| 15 | 13 | bin2c: bin2c.c |
| 16 | 14 | $(CC) $(CFLAGS) -o $@ $@.c |
| @@ -19,20 +17,26 @@ min: min.c $(LIBLUA) · 2 unmodified lines | ||
| 19 | 17 | $(CC) $(CFLAGS) -o $@ $@.c -L$(LIB) -llua |
| 20 | 18 | |
| 21 | 19 | trace: trace.c $(LIBLUA) |
| 22 | − $(CC) $(CFLAGS) -o $@ $@.c -L$(LIB) -llua -llualib -lm | |
| 20 | + $(CC) -g $(CFLAGS) -o $@ $@.c -L$(LIB) -llua -llualib $(EXTRA_LIBS) | |
| 23 | 21 | |
| 24 | −def: lua.def | |
| 22 | +noparser: noparser.c | |
| 23 | + $(CC) $(CFLAGS) -I$(LUA)/src -o $@.o -c $@.c | |
| 25 | 24 | |
| 26 | −lua.def: $(INC)/lua.h | |
| 27 | − $(BIN)/lua def.lua < $(INC)/lua.h > $@ | |
| 28 | − # cat $(INC)/l*.h | $(BIN)/lua def.lua > $@ | |
| 25 | +luab: noparser $(LIBLUA) | |
| 26 | + cc -o $@ noparser.o $(LUA)/src/lua/lua.o -L$(LIB) -llua -llualib $(EXTRA_LIBS) | |
| 27 | + $(BIN)/luac $(LUA)/test/hello.lua | |
| 28 | + $@ luac.out | |
| 29 | + -$@ -e'a=1' | |
| 29 | 30 | |
| 30 | −stdcall: | |
| 31 | − mkdir -p Stdcall | |
| 32 | − grep -l _API $(LUA)/src/*.[ch] $(LUA)/src/*/*.[ch] | xargs -n1 -i echo $(BIN)/lua stdcall.lua '<{}' '>Stdcall/{}' | |
| 31 | +flat: | |
| 32 | + cd ..; mkdir flat; mv include/*.h src/*.[ch] src/*/*.[ch] flat | |
| 33 | 33 | |
| 34 | 34 | $(LIBLUA): |
| 35 | 35 | cd ../src; $(MAKE) |
| 36 | 36 | |
| 37 | 37 | clean: |
| 38 | − rm -f $(ALL) | |
| 38 | + rm -f $(ALL) a.out core *.o luac.out | |
| 39 | + | |
| 40 | +luser_tests.h: RCS/ltests.h,v | |
| 41 | + co -q -M ltests.h | |
| 42 | + mv -f ltests.h $@ | |
| @@ -1,43 +1,54 @@ | ||
| 1 | −This directory contains some code that might be useful. | |
| 1 | +This directory contains some useful files and code. | |
| 2 | +Unlike the code in ../src, everything here is in the public domain. | |
| 2 | 3 | |
| 3 | 4 | bin2c.c |
| 4 | − This program converts files to byte arrays that are automatically | |
| 5 | − run with lua_dobuffer. This allows C programs to include all necessary | |
| 6 | − Lua code, even in precompiled form. Even if the code is included in | |
| 7 | − source form, bin2c is useful because it avoids the hassle of having to | |
| 8 | − quote special characters in C strings. | |
| 9 | − Example of usage: Run bin2c file1 file2 ... > init.h. Then, in your C | |
| 10 | − program, just do #include "init.h" anywhere in the *body* of a | |
| 5 | + This program converts files to byte arrays that are automatically run | |
| 6 | + with lua_dobuffer. This allows C programs to include all necessary Lua | |
| 7 | + code, even in precompiled form. Even if the code is included in source | |
| 8 | + form, bin2c is useful because it avoids the hassle of having to quote | |
| 9 | + special characters in C strings. | |
| 10 | + Example of usage: Run bin2c file1 file2 ... > init.h. Then, in your | |
| 11 | + C program, just do #include "init.h" anywhere in the *body* of a | |
| 11 | 12 | function. This will be equivalent to calling |
| 12 | 13 | lua_dofile(L,"file1"); lua_dofile(L,"file2"); ... |
| 13 | 14 | Note that the Lua state is called "L". If you use a different name, |
| 14 | − say "mystate", just #define L mystate before #include "init.h". | |
| 15 | + say "mystate", just #define L mystate before you #include "init.h". | |
| 15 | 16 | |
| 16 | −def.lua | |
| 17 | − A Lua script for creating .DEF for Windows DLLs. | |
| 18 | − Just do "make def" to create lua.def. | |
| 17 | +compat.lua | |
| 18 | + A compatibility module for Lua 4.0 functions. | |
| 19 | 19 | |
| 20 | −min.c | |
| 21 | − A minimal Lua interpreter. | |
| 20 | +doall.lua | |
| 21 | + Emulate the command line behaviour of Lua 4.0 | |
| 22 | 22 | |
| 23 | 23 | lua.ico |
| 24 | 24 | A Lua icon for Windows. |
| 25 | − It was drawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>. | |
| 25 | + Drawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>. | |
| 26 | + | |
| 27 | +lua.magic | |
| 28 | + Data for teaching file(1) about Lua precompiled chunks. | |
| 26 | 29 | |
| 27 | 30 | lua.xpm |
| 28 | 31 | The same icon as lua.ico, but in XPM format. |
| 29 | 32 | It was converted with ImageMagick by Andy Tai <andy@exp.com>. |
| 30 | 33 | |
| 31 | −lua.magic | |
| 32 | − Data for teaching file(1) about Lua precompiled chunks. | |
| 34 | +luser_number.h | |
| 35 | + Number type configuration for Lua core. | |
| 36 | + | |
| 37 | +luser_tests.h | |
| 38 | + Self-test configuration for Lua core. | |
| 39 | + | |
| 40 | +min.c | |
| 41 | + A minimal Lua interpreter. | |
| 42 | + Good for learning and for starting your own. | |
| 33 | 43 | |
| 34 | −stdcall.lua | |
| 35 | − A Lua script for changing the calling convention to __stdcall. | |
| 36 | − Do "make stdcall" and new modules will be created in stdcall/. | |
| 44 | +noparser.c | |
| 45 | + Linking with noparser.o avoids loading the parsing modules in lualib.a. | |
| 46 | + Do "make luab" to build a sample Lua intepreter that does not parse | |
| 47 | + Lua programs, only loads precompiled programs. | |
| 37 | 48 | |
| 38 | −setfallback.lua | |
| 39 | − A Lua implementation of fallbacks on top of tag methods. | |
| 40 | − You only need this module if you have Lua code that uses setfallback. | |
| 49 | +saconfig.c | |
| 50 | + Configuration for Lua interpreter. | |
| 41 | 51 | |
| 42 | 52 | trace.c |
| 43 | − A simple execution tracer. An example of how to use the debugging hooks. | |
| 53 | + A simple execution tracer. | |
| 54 | + An example of how to use the debug hooks in C. | |
| @@ -1,34 +1,30 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * bin2c.c |
| 3 | −* convert binary files to byte arrays | |
| 3 | +* convert files to byte arrays for automatic loading with lua_dobuffer | |
| 4 | 4 | * Luiz Henrique de Figueiredo (lhf@tecgraf.puc-rio.br) |
| 5 | −* 11 Sep 2000 22:37:14 | |
| 5 | +* 02 Apr 2003 20:44:31 | |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <ctype.h> |
| 9 | 9 | #include <stdio.h> |
| 10 | 10 | #include <stdlib.h> |
| 11 | 11 | |
| 12 | −void dump(FILE* f, int n) | |
| 12 | +static void dump(FILE* f, int n) | |
| 13 | 13 | { |
| 14 | − printf("static unsigned char B%d[]={\n",n); | |
| 14 | + printf("static const unsigned char B%d[]={\n",n); | |
| 15 | 15 | for (n=1;;n++) |
| 16 | 16 | { |
| 17 | 17 | int c=getc(f); |
| 18 | 18 | if (c==EOF) break; |
| 19 | −#if 0 | |
| 20 | − printf("0x%02x,",c); | |
| 21 | −#else | |
| 22 | 19 | printf("%3u,",c); |
| 23 | −#endif | |
| 24 | 20 | if (n==20) { putchar('\n'); n=0; } |
| 25 | 21 | } |
| 26 | 22 | printf("\n};\n\n"); |
| 27 | 23 | } |
| 28 | 24 | |
| 29 | −void fdump(char* fn, int n) | |
| 25 | +static void fdump(const char* fn, int n) | |
| 30 | 26 | { |
| 31 | − FILE* f= (fn==NULL) ? stdin : fopen(fn,"rb"); /* must open in binary mode */ | |
| 27 | + FILE* f= fopen(fn,"rb"); /* must open in binary mode */ | |
| 32 | 28 | if (f==NULL) |
| 33 | 29 | { |
| 34 | 30 | fprintf(stderr,"bin2c: cannot open "); |
| @@ -37,15 +33,15 @@ void fdump(char* fn, int n) · 2 unmodified lines | ||
| 37 | 33 | } |
| 38 | 34 | else |
| 39 | 35 | { |
| 40 | − if (fn!=NULL) printf("/* %s */\n",fn); | |
| 36 | + printf("/* %s */\n",fn); | |
| 41 | 37 | dump(f,n); |
| 42 | 38 | fclose(f); |
| 43 | 39 | } |
| 44 | 40 | } |
| 45 | 41 | |
| 46 | −void emit(char* fn, int n) | |
| 42 | +static void emit(const char* fn, int n) | |
| 47 | 43 | { |
| 48 | − printf(" lua_dobuffer(L,B%d,sizeof(B%d),\"%s\");\n",n,n,fn); | |
| 44 | + printf(" lua_dobuffer(L,(const char*)B%d,sizeof(B%d),\"%s\");\n",n,n,fn); | |
| 49 | 45 | } |
| 50 | 46 | |
| 51 | 47 | int main(int argc, char* argv[]) |
| @@ -55,7 +51,7 @@ int main(int argc, char* argv[]) · 3 unmodified lines | ||
| 55 | 51 | if (argc<2) |
| 56 | 52 | { |
| 57 | 53 | dump(stdin,0); |
| 58 | − emit("(stdin)",0); | |
| 54 | + emit("=stdin",0); | |
| 59 | 55 | } |
| 60 | 56 | else |
| 61 | 57 | { |
| @@ -0,0 +1,192 @@ | ||
| 1 | +------------------------------------------------------------------- | |
| 2 | +-- Real globals | |
| 3 | +-- _ALERT | |
| 4 | +-- _ERRORMESSAGE | |
| 5 | +-- _VERSION | |
| 6 | +-- _G | |
| 7 | +-- assert | |
| 8 | +-- error | |
| 9 | +-- metatable | |
| 10 | +-- next | |
| 11 | ||
| 12 | +-- require | |
| 13 | +-- tonumber | |
| 14 | +-- tostring | |
| 15 | +-- type | |
| 16 | +-- unpack | |
| 17 | + | |
| 18 | +------------------------------------------------------------------- | |
| 19 | +-- collectgarbage | |
| 20 | +-- gcinfo | |
| 21 | + | |
| 22 | +-- globals | |
| 23 | + | |
| 24 | +-- call -> protect(f, err) | |
| 25 | +-- loadfile | |
| 26 | +-- loadstring | |
| 27 | + | |
| 28 | +-- rawget | |
| 29 | +-- rawset | |
| 30 | + | |
| 31 | +-- getargs = Main.getargs ?? | |
| 32 | + | |
| 33 | + | |
| 34 | +function do_ (f, err) | |
| 35 | + if not f then print(err); return end | |
| 36 | + local a,b = pcall(f) | |
| 37 | + if not a then print(b); return nil | |
| 38 | + else return b or true | |
| 39 | + end | |
| 40 | +end | |
| 41 | + | |
| 42 | +function dostring(s) return do_(loadstring(s)) end | |
| 43 | +-- function dofile(s) return do_(loadfile(s)) end | |
| 44 | + | |
| 45 | +------------------------------------------------------------------- | |
| 46 | +-- Table library | |
| 47 | +local tab = table | |
| 48 | +foreach = tab.foreach | |
| 49 | +foreachi = tab.foreachi | |
| 50 | +getn = tab.getn | |
| 51 | +tinsert = tab.insert | |
| 52 | +tremove = tab.remove | |
| 53 | +sort = tab.sort | |
| 54 | + | |
| 55 | +------------------------------------------------------------------- | |
| 56 | +-- Debug library | |
| 57 | +local dbg = debug | |
| 58 | +getinfo = dbg.getinfo | |
| 59 | +getlocal = dbg.getlocal | |
| 60 | +setcallhook = function () error"`setcallhook' is deprecated" end | |
| 61 | +setlinehook = function () error"`setlinehook' is deprecated" end | |
| 62 | +setlocal = dbg.setlocal | |
| 63 | + | |
| 64 | +------------------------------------------------------------------- | |
| 65 | +-- math library | |
| 66 | +local math = math | |
| 67 | +abs = math.abs | |
| 68 | +acos = function (x) return math.deg(math.acos(x)) end | |
| 69 | +asin = function (x) return math.deg(math.asin(x)) end | |
| 70 | +atan = function (x) return math.deg(math.atan(x)) end | |
| 71 | +atan2 = function (x,y) return math.deg(math.atan2(x,y)) end | |
| 72 | +ceil = math.ceil | |
| 73 | +cos = function (x) return math.cos(math.rad(x)) end | |
| 74 | +deg = math.deg | |
| 75 | +exp = math.exp | |
| 76 | +floor = math.floor | |
| 77 | +frexp = math.frexp | |
| 78 | +ldexp = math.ldexp | |
| 79 | +log = math.log | |
| 80 | +log10 = math.log10 | |
| 81 | +max = math.max | |
| 82 | +min = math.min | |
| 83 | +mod = math.mod | |
| 84 | +PI = math.pi | |
| 85 | +--??? pow = math.pow | |
| 86 | +rad = math.rad | |
| 87 | +random = math.random | |
| 88 | +randomseed = math.randomseed | |
| 89 | +sin = function (x) return math.sin(math.rad(x)) end | |
| 90 | +sqrt = math.sqrt | |
| 91 | +tan = function (x) return math.tan(math.rad(x)) end | |
| 92 | + | |
| 93 | +------------------------------------------------------------------- | |
| 94 | +-- string library | |
| 95 | +local str = string | |
| 96 | +strbyte = str.byte | |
| 97 | +strchar = str.char | |
| 98 | +strfind = str.find | |
| 99 | +format = str.format | |
| 100 | +gsub = str.gsub | |
| 101 | +strlen = str.len | |
| 102 | +strlower = str.lower | |
| 103 | +strrep = str.rep | |
| 104 | +strsub = str.sub | |
| 105 | +strupper = str.upper | |
| 106 | + | |
| 107 | +------------------------------------------------------------------- | |
| 108 | +-- os library | |
| 109 | +clock = os.clock | |
| 110 | +date = os.date | |
| 111 | +difftime = os.difftime | |
| 112 | +execute = os.execute --? | |
| 113 | +exit = os.exit | |
| 114 | +getenv = os.getenv | |
| 115 | +remove = os.remove | |
| 116 | +rename = os.rename | |
| 117 | +setlocale = os.setlocale | |
| 118 | +time = os.time | |
| 119 | +tmpname = os.tmpname | |
| 120 | + | |
| 121 | +------------------------------------------------------------------- | |
| 122 | +-- compatibility only | |
| 123 | +getglobal = function (n) return _G[n] end | |
| 124 | +setglobal = function (n,v) _G[n] = v end | |
| 125 | + | |
| 126 | +------------------------------------------------------------------- | |
| 127 | + | |
| 128 | +local io, tab = io, table | |
| 129 | + | |
| 130 | +-- IO library (files) | |
| 131 | +_STDIN = io.stdin | |
| 132 | +_STDERR = io.stderr | |
| 133 | +_STDOUT = io.stdout | |
| 134 | +_INPUT = io.stdin | |
| 135 | +_OUTPUT = io.stdout | |
| 136 | +seek = io.stdin.seek -- sick ;-) | |
| 137 | +tmpfile = io.tmpfile | |
| 138 | +closefile = io.close | |
| 139 | +openfile = io.open | |
| 140 | + | |
| 141 | +function flush (f) | |
| 142 | + if f then f:flush() | |
| 143 | + else _OUTPUT:flush() | |
| 144 | + end | |
| 145 | +end | |
| 146 | + | |
| 147 | +function readfrom (name) | |
| 148 | + if name == nil then | |
| 149 | + local f, err, cod = io.close(_INPUT) | |
| 150 | + _INPUT = io.stdin | |
| 151 | + return f, err, cod | |
| 152 | + else | |
| 153 | + local f, err, cod = io.open(name, "r") | |
| 154 | + _INPUT = f or _INPUT | |
| 155 | + return f, err, cod | |
| 156 | + end | |
| 157 | +end | |
| 158 | + | |
| 159 | +function writeto (name) | |
| 160 | + if name == nil then | |
| 161 | + local f, err, cod = io.close(_OUTPUT) | |
| 162 | + _OUTPUT = io.stdout | |
| 163 | + return f, err, cod | |
| 164 | + else | |
| 165 | + local f, err, cod = io.open(name, "w") | |
| 166 | + _OUTPUT = f or _OUTPUT | |
| 167 | + return f, err, cod | |
| 168 | + end | |
| 169 | +end | |
| 170 | + | |
| 171 | +function appendto (name) | |
| 172 | + local f, err, cod = io.open(name, "a") | |
| 173 | + _OUTPUT = f or _OUTPUT | |
| 174 | + return f, err, cod | |
| 175 | +end | |
| 176 | + | |
| 177 | +function read (...) | |
| 178 | + local f = _INPUT | |
| 179 | + if type(arg[1]) == 'userdata' then | |
| 180 | + f = tab.remove(arg, 1) | |
| 181 | + end | |
| 182 | + return f:read(unpack(arg)) | |
| 183 | +end | |
| 184 | + | |
| 185 | +function write (...) | |
| 186 | + local f = _OUTPUT | |
| 187 | + if type(arg[1]) == 'userdata' then | |
| 188 | + f = tab.remove(arg, 1) | |
| 189 | + end | |
| 190 | + return f:write(unpack(arg)) | |
| 191 | +end | |
| 192 | + | |
| @@ -1,9 +0,0 @@ | ||
| 1 | −-- def.lua | |
| 2 | −-- make .DEF file from lua.h | |
| 3 | −-- usage: lua def.lua <lua.h >lua.def | |
| 4 | − | |
| 5 | −T=read"*a" | |
| 6 | −write("LIBRARY LUA\nVERSION ") | |
| 7 | −gsub(T,"LUA_VERSION.-(%d+%.%d+)",write) | |
| 8 | −write("\nEXPORTS\n") | |
| 9 | −gsub(T,"(lua_%w+)%s+%(",function (f) write(" ",f,"\n") end) | |
| @@ -0,0 +1,6 @@ | ||
| 1 | +-- emulate the command line behaviour of Lua 4.0 | |
| 2 | +-- usage: lua doall.lua f1.lua f2.lua f3.lua ... | |
| 3 | + | |
| 4 | +for i=1,table.getn(arg) do | |
| 5 | + dofile(arg[i]) | |
| 6 | +end | |
| @@ -1,10 +1,12 @@ | ||
| 1 | 1 | |
| 2 | −# Lua precompiled files | |
| 2 | +# Lua precompiled files. Versions 2.3 and 4.1 were never officially released. | |
| 3 | 3 | 0 string \33Lua precompiled chunk for Lua |
| 4 | −>4 byte 0x23 2.3 | |
| 4 | +>4 byte 0x23 2.3* | |
| 5 | 5 | >4 byte 0x24 2.4 |
| 6 | 6 | >4 byte 0x25 2.5 |
| 7 | 7 | >4 byte 0x30 3.0 |
| 8 | 8 | >4 byte 0x31 3.1 |
| 9 | 9 | >4 byte 0x32 3.2 |
| 10 | 10 | >4 byte 0x40 4.0 |
| 11 | +>4 byte 0x41 4.1* | |
| 12 | +>4 byte 0x50 5.0 | |
| @@ -0,0 +1,34 @@ | ||
| 1 | +/* luser_number.h -- number type configuration for Lua core | |
| 2 | +* | |
| 3 | +* #define LUA_USER_H to this file and #define one of USE_* below | |
| 4 | +*/ | |
| 5 | + | |
| 6 | +#ifdef USE_DOUBLE | |
| 7 | +#define LUA_NUMBER double | |
| 8 | +#define LUA_NUMBER_SCAN "%lf" | |
| 9 | +#define LUA_NUMBER_FMT "%.14g" | |
| 10 | +#endif | |
| 11 | + | |
| 12 | +#ifdef USE_FLOAT | |
| 13 | +#define LUA_NUMBER float | |
| 14 | +#define LUA_NUMBER_SCAN "%f" | |
| 15 | +#define LUA_NUMBER_FMT "%.5g" | |
| 16 | +#endif | |
| 17 | + | |
| 18 | +#ifdef USE_LONG | |
| 19 | +#define LUA_NUMBER long | |
| 20 | +#define LUA_NUMBER_SCAN "%ld" | |
| 21 | +#define LUA_NUMBER_FMT "%ld" | |
| 22 | +#define lua_str2number(s,p) strtol((s), (p), 10) | |
| 23 | +#endif | |
| 24 | + | |
| 25 | +#ifdef USE_INT | |
| 26 | +#define LUA_NUMBER int | |
| 27 | +#define LUA_NUMBER_SCAN "%d" | |
| 28 | +#define LUA_NUMBER_FMT "%d" | |
| 29 | +#define lua_str2number(s,p) ((int) strtol((s), (p), 10)) | |
| 30 | +#endif | |
| 31 | + | |
| 32 | +#ifdef USE_FASTROUND | |
| 33 | +#define lua_number2int(i,d) __asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d)) | |
| 34 | +#endif | |
| @@ -0,0 +1,68 @@ | ||
| 1 | +/* | |
| 2 | +** $Id: ltests.h,v 1.20 2002/12/04 17:29:05 roberto Exp $ | |
| 3 | +** Internal Header for Debugging of the Lua Implementation | |
| 4 | +** See Copyright Notice in lua.h | |
| 5 | +*/ | |
| 6 | + | |
| 7 | +#ifndef ltests_h | |
| 8 | +#define ltests_h | |
| 9 | + | |
| 10 | + | |
| 11 | +#include <stdlib.h> | |
| 12 | + | |
| 13 | + | |
| 14 | +#define LUA_DEBUG | |
| 15 | + | |
| 16 | +#define LUA_OPNAMES | |
| 17 | + | |
| 18 | +#undef NDEBUG | |
| 19 | +#include <assert.h> | |
| 20 | +#define lua_assert(c) assert(c) | |
| 21 | +#define check_exp(c,e) (lua_assert(c), (e)) | |
| 22 | +#define api_check(L, o) lua_assert(o) | |
| 23 | + | |
| 24 | + | |
| 25 | +/* to avoid warnings, and to make sure value is really unused */ | |
| 26 | +#define UNUSED(x) (x=0, (void)(x)) | |
| 27 | + | |
| 28 | + | |
| 29 | +/* memory allocator control variables */ | |
| 30 | +extern unsigned long memdebug_numblocks; | |
| 31 | +extern unsigned long memdebug_total; | |
| 32 | +extern unsigned long memdebug_maxmem; | |
| 33 | +extern unsigned long memdebug_memlimit; | |
| 34 | + | |
| 35 | + | |
| 36 | +#define l_realloc(b, os, s) debug_realloc(b, os, s) | |
| 37 | +#define l_free(b, os) debug_realloc(b, os, 0) | |
| 38 | + | |
| 39 | +void *debug_realloc (void *block, size_t oldsize, size_t size); | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | +/* test for lock/unlock */ | |
| 44 | +extern int islocked; | |
| 45 | +#define LUA_USERSTATE int * | |
| 46 | +#define getlock(l) (*(cast(LUA_USERSTATE *, l) - 1)) | |
| 47 | +#define lua_userstateopen(l) if (l != NULL) getlock(l) = &islocked; | |
| 48 | +#define lua_lock(l) lua_assert((*getlock(l))++ == 0) | |
| 49 | +#define lua_unlock(l) lua_assert(--(*getlock(l)) == 0) | |
| 50 | + | |
| 51 | + | |
| 52 | +int luaB_opentests (lua_State *L); | |
| 53 | + | |
| 54 | +#define LUA_EXTRALIBS { "tests", luaB_opentests }, | |
| 55 | + | |
| 56 | + | |
| 57 | +/* real main will be defined at `ltests.c' */ | |
| 58 | +int l_main (int argc, char *argv[]); | |
| 59 | +#define main l_main | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | +/* change some sizes to give some bugs a chance */ | |
| 64 | + | |
| 65 | +#define LUAL_BUFFERSIZE 27 | |
| 66 | +#define MINSTRTABSIZE 2 | |
| 67 | + | |
| 68 | +#endif | |
| @@ -1,13 +1,12 @@ | ||
| 1 | 1 | /* |
| 2 | −* min.c | |
| 3 | −* a minimal Lua interpreter. loads stdin only. | |
| 4 | −* no standard library, only a "print" function. | |
| 2 | +* min.c -- a minimal Lua interpreter | |
| 3 | +* loads stdin only with minimal error handling. | |
| 4 | +* no interaction, and no standard library, only a "print" function. | |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | #include <stdio.h> |
| 8 | 8 | #include "lua.h" |
| 9 | 9 | |
| 10 | −/* a simple "print". based on the code in lbaselib.c */ | |
| 11 | 10 | static int print(lua_State *L) |
| 12 | 11 | { |
| 13 | 12 | int n=lua_gettop(L); |
| @@ -17,6 +16,10 @@ static int print(lua_State *L) · 3 unmodified lines | ||
| 17 | 16 | if (i>1) printf("\t"); |
| 18 | 17 | if (lua_isstring(L,i)) |
| 19 | 18 | printf("%s",lua_tostring(L,i)); |
| 19 | + else if (lua_isnil(L,i)) | |
| 20 | + printf("%s","nil"); | |
| 21 | + else if (lua_isboolean(L,i)) | |
| 22 | + printf("%s",lua_toboolean(L,i) ? "true" : "false"); | |
| 20 | 23 | else |
| 21 | 24 | printf("%s:%p",lua_typename(L,lua_type(L,i)),lua_topointer(L,i)); |
| 22 | 25 | } |
| @@ -24,9 +27,20 @@ static int print(lua_State *L) · 1 unmodified line | ||
| 24 | 27 | return 0; |
| 25 | 28 | } |
| 26 | 29 | |
| 30 | +static const char *getF(lua_State *L, void *ud, size_t *size) | |
| 31 | +{ | |
| 32 | + FILE *f=(FILE *)ud; | |
| 33 | + static char buff[512]; | |
| 34 | + if (feof(f)) return NULL; | |
| 35 | + *size=fread(buff,1,sizeof(buff),f); | |
| 36 | + return (*size>0) ? buff : NULL; | |
| 37 | +} | |
| 38 | + | |
| 27 | 39 | int main(void) |
| 28 | 40 | { |
| 29 | − lua_State *L=lua_open(0); | |
| 41 | + lua_State *L=lua_open(); | |
| 30 | 42 | lua_register(L,"print",print); |
| 31 | − return lua_dofile(L,NULL); | |
| 43 | + if (lua_load(L,getF,stdin,"=stdin") || lua_pcall(L,0,0,0)) | |
| 44 | + fprintf(stderr,"%s\n",lua_tostring(L,-1)); | |
| 45 | + return 0; | |
| 32 | 46 | } |
| @@ -0,0 +1,26 @@ | ||
| 1 | +/* | |
| 2 | +* The code below can be used to make a Lua core that does not contain the | |
| 3 | +* parsing modules (lcode, llex, lparser), which represent 35% of the total core. | |
| 4 | +* You'll only be able to load binary files and strings, precompiled with luac. | |
| 5 | +* (Of course, you'll have to build luac with the original parsing modules!) | |
| 6 | +* | |
| 7 | +* To use this module, simply compile it ("make noparser" does that) and | |
| 8 | +* list its object file before the Lua libraries. The linker should then not | |
| 9 | +* load the parsing modules. To try it, do "make luab". | |
| 10 | +*/ | |
| 11 | + | |
| 12 | +#include "llex.h" | |
| 13 | +#include "lparser.h" | |
| 14 | +#include "lzio.h" | |
| 15 | + | |
| 16 | +void luaX_init (lua_State *L) { | |
| 17 | + UNUSED(L); | |
| 18 | +} | |
| 19 | + | |
| 20 | +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { | |
| 21 | + UNUSED(z); | |
| 22 | + UNUSED(buff); | |
| 23 | + lua_pushstring(L,"parser not loaded"); | |
| 24 | + lua_error(L); | |
| 25 | + return NULL; | |
| 26 | +} | |
| @@ -0,0 +1,87 @@ | ||
| 1 | +/* sa-config.c -- configuration for stand-alone Lua interpreter | |
| 2 | +* | |
| 3 | +* #define LUA_USERCONFIG to this file | |
| 4 | +* | |
| 5 | +* Here are the features that can be customized using #define: | |
| 6 | +* | |
| 7 | +*** Line edit and history: | |
| 8 | +* #define USE_READLINE to use the GNU readline library. | |
| 9 | +* | |
| 10 | +* To use another library for this, use the code below as a start. | |
| 11 | +* Make sure you #define lua_readline and lua_saveline accordingly. | |
| 12 | +* If you do not #define lua_readline, you'll get a version based on fgets | |
| 13 | +* that uses a static buffer of size MAXINPUT. | |
| 14 | +* | |
| 15 | +* | |
| 16 | +*** Static Lua libraries to be loaded at startup: | |
| 17 | +* #define lua_userinit(L) to a Lua function that loads libraries; typically | |
| 18 | +* #define lua_userinit(L) openstdlibs(L);myinit(L) | |
| 19 | +* or | |
| 20 | +* #define lua_userinit(L) myinit(L) | |
| 21 | +* | |
| 22 | +* Another way is to add the prototypes of the init functions here and | |
| 23 | +* #define LUA_EXTRALIBS accordingly. For example, | |
| 24 | +* #define LUA_EXTRALIBS {"mylib","luaopen_mylib"}, | |
| 25 | +* Note the ending comma! | |
| 26 | +* | |
| 27 | +* | |
| 28 | +*** Prompts: | |
| 29 | +* The stand-alone Lua interpreter uses two prompts: PROMPT and PROMPT2. | |
| 30 | +* PROMPT is the primary prompt, shown when the intepreter is ready to receive | |
| 31 | +* a new statement. PROMPT2 is the secondary prompt, shown while a statement | |
| 32 | +* is being entered but is still incomplete. | |
| 33 | +* | |
| 34 | +* | |
| 35 | +*** Program name: | |
| 36 | +* Error messages usually show argv[0] as a program name. In systems that do | |
| 37 | +* not give a valid string as argv[0], error messages show PROGNAME instead. | |
| 38 | +* | |
| 39 | +* | |
| 40 | +*/ | |
| 41 | + | |
| 42 | +#ifdef USE_READLINE | |
| 43 | +/* | |
| 44 | +* This section implements of lua_readline and lua_saveline for lua.c using | |
| 45 | +* the GNU readline and history libraries. It should also work with drop-in | |
| 46 | +* replacements such as editline and libedit (you may have to include | |
| 47 | +* different headers, though). | |
| 48 | +* | |
| 49 | +*/ | |
| 50 | + | |
| 51 | +#define lua_readline myreadline | |
| 52 | +#define lua_saveline mysaveline | |
| 53 | + | |
| 54 | +#include <ctype.h> | |
| 55 | +#include <readline/readline.h> | |
| 56 | +#include <readline/history.h> | |
| 57 | + | |
| 58 | +static int myreadline (lua_State *L, const char *prompt) { | |
| 59 | + char *s=readline(prompt); | |
| 60 | + if (s==NULL) | |
| 61 | + return 0; | |
| 62 | + else { | |
| 63 | + lua_pushstring(L,s); | |
| 64 | + lua_pushliteral(L,"\n"); | |
| 65 | + lua_concat(L,2); | |
| 66 | + free(s); | |
| 67 | + return 1; | |
| 68 | + } | |
| 69 | +} | |
| 70 | + | |
| 71 | +static void mysaveline (lua_State *L, const char *s) { | |
| 72 | + const char *p; | |
| 73 | + for (p=s; isspace(*p); p++) | |
| 74 | + ; | |
| 75 | + if (*p!=0) { | |
| 76 | + size_t n=strlen(s)-1; | |
| 77 | + if (s[n]!='\n') | |
| 78 | + add_history(s); | |
| 79 | + else { | |
| 80 | + lua_pushlstring(L,s,n); | |
| 81 | + s=lua_tostring(L,-1); | |
| 82 | + add_history(s); | |
| 83 | + lua_remove(L,-1); | |
| 84 | + } | |
| 85 | + } | |
| 86 | +} | |
| 87 | +#endif | |
| @@ -1,55 +0,0 @@ | ||
| 1 | −-------------------------------------------------------------- | |
| 2 | −-- Definition of "setfallback" using tag methods | |
| 3 | −-- (for compatibility with old code) | |
| 4 | −-------------------------------------------------------------- | |
| 5 | − | |
| 6 | − | |
| 7 | −-- default fallbacks for each event: | |
| 8 | −local defaults = { | |
| 9 | − gettable = function () error('indexed expression not a table') end, | |
| 10 | − settable = function () error('indexed expression not a table') end, | |
| 11 | − index = function () return nil end, | |
| 12 | − getglobal = function () return nil end, | |
| 13 | − arith = function () error('number expected in arithmetic operation') end, | |
| 14 | − order = function () error('incompatible types in comparison') end, | |
| 15 | − concat = function () error('string expected in concatenation') end, | |
| 16 | − gc = function () return nil end, | |
| 17 | − ['function'] = function () error('called expression not a function') end, | |
| 18 | − error = function (s) write(_STDERR, s, '\n') end, | |
| 19 | −} | |
| 20 | − | |
| 21 | − | |
| 22 | −function setfallback (name, func) | |
| 23 | − | |
| 24 | − -- set the given function as the tag method for all "standard" tags | |
| 25 | − -- (since some combinations may cause errors, use call to avoid messages) | |
| 26 | − local fillvalids = function (n, func) | |
| 27 | − call(settagmethod, {0, n, func}, 'x', nil) | |
| 28 | − call(settagmethod, {tag(0), n, func}, 'x', nil) | |
| 29 | − call(settagmethod, {tag(''), n, func}, 'x', nil) | |
| 30 | − call(settagmethod, {tag{}, n, func}, 'x', nil) | |
| 31 | − call(settagmethod, {tag(function () end), n, func}, 'x', nil) | |
| 32 | − call(settagmethod, {tag(settagmethod), n, func}, 'x', nil) | |
| 33 | − call(settagmethod, {tag(nil), n, func}, 'x', nil) | |
| 34 | − end | |
| 35 | − | |
| 36 | − assert(type(func) == 'function') | |
| 37 | − local oldfunc | |
| 38 | − if name == 'error' then | |
| 39 | − oldfunc = seterrormethod(func) | |
| 40 | − elseif name == 'getglobal' then | |
| 41 | − oldfunc = settagmethod(tag(nil), 'getglobal', func) | |
| 42 | − elseif name == 'arith' then | |
| 43 | − oldfunc = gettagmethod(tag(0), 'pow') | |
| 44 | − foreach({"add", "sub", "mul", "div", "unm", "pow"}, | |
| 45 | − function(_, n) %fillvalids(n, %func) end) | |
| 46 | − elseif name == 'order' then | |
| 47 | − oldfunc = gettagmethod(tag(nil), 'lt') | |
| 48 | − foreach({"lt", "gt", "le", "ge"}, | |
| 49 | − function(_, n) %fillvalids(n, %func) end) | |
| 50 | − else | |
| 51 | − oldfunc = gettagmethod(tag(nil), name) | |
| 52 | − fillvalids(name, func) | |
| 53 | − end | |
| 54 | − return oldfunc or rawgettable(%defaults, name) | |
| 55 | −end | |
| @@ -1,10 +0,0 @@ | ||
| 1 | −-- stdcall.lua | |
| 2 | −-- add __stdcall where appropriate | |
| 3 | −-- usage: lua stdcall.lua <lua.h >s_lua.h | |
| 4 | −-- usage: lua stdcall.lua <lapi.c >s_lapi.c | |
| 5 | − | |
| 6 | −T=read"*a" | |
| 7 | −T=gsub(T,"(lua_%w+%s+%()","__stdcall %1") | |
| 8 | −T=gsub(T,"(%*lua_CFunction)","__stdcall %1") | |
| 9 | − | |
| 10 | −write(T) | |
| @@ -1,56 +1,55 @@ | ||
| 1 | 1 | /* |
| 2 | −* trace.c | |
| 3 | −* a simple execution tracer for Lua | |
| 2 | +* trace.c -- a simple execution tracer for Lua | |
| 4 | 3 | */ |
| 5 | 4 | |
| 6 | 5 | #include <stdio.h> |
| 7 | 6 | #include <string.h> |
| 8 | 7 | #include "lua.h" |
| 9 | 8 | #include "lualib.h" |
| 10 | −#include "luadebug.h" | |
| 9 | +#include "lauxlib.h" | |
| 11 | 10 | |
| 12 | −lua_State *lua_state = NULL; | |
| 13 | −#define L lua_state /* lazy! */ | |
| 14 | − | |
| 15 | −static FILE* LOG; /* output file */ | |
| 11 | +static FILE* LOG; /* log file */ | |
| 16 | 12 | static int I=0; /* indentation level */ |
| 17 | 13 | |
| 18 | −static void linehook(lua_State *L, lua_Debug *ar) | |
| 19 | −{ | |
| 20 | − fprintf(LOG,"%*sdo_line(%d)\t-- %d\n",I,"",ar->currentline,I); | |
| 21 | −} | |
| 22 | − | |
| 23 | −static void callhook(lua_State *L, lua_Debug *ar) | |
| 14 | +static void hook(lua_State *L, lua_Debug *ar) | |
| 24 | 15 | { |
| 25 | − fprintf(LOG,"%*sdo_%s\t-- %p %d\n",I,"",ar->event,ar->_func,I); | |
| 26 | − if (*ar->event=='r') --I; else ++I; | |
| 16 | + const char* s=""; | |
| 17 | + switch (ar->event) | |
| 18 | + { | |
| 19 | + case LUA_HOOKTAILRET: ar->event=LUA_HOOKRET; | |
| 20 | + case LUA_HOOKRET: s="return"; break; | |
| 21 | + case LUA_HOOKCALL: s="call"; break; | |
| 22 | + case LUA_HOOKLINE: s="line"; break; | |
| 23 | + default: break; | |
| 24 | + } | |
| 25 | + fprintf(LOG,"[%d]\t%*s%s\t-- %d\n",I,I,"",s,ar->currentline); | |
| 26 | + if (ar->event==LUA_HOOKCALL) ++I; else if (ar->event==LUA_HOOKRET) --I; | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | −void start_trace(FILE* logfile) | |
| 29 | +static void start_trace(lua_State *L, FILE* logfile) | |
| 30 | 30 | { |
| 31 | − lua_setlinehook(L,linehook); | |
| 32 | − lua_setcallhook(L,callhook); | |
| 31 | + lua_sethook(L,hook,LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 0); | |
| 33 | 32 | LOG=logfile; |
| 34 | 33 | } |
| 35 | 34 | |
| 36 | −void stop_trace(void) | |
| 35 | +static void stop_trace(lua_State *L) | |
| 37 | 36 | { |
| 38 | − lua_setlinehook(L,NULL); | |
| 39 | − lua_setcallhook(L,NULL); | |
| 37 | + lua_sethook(L,NULL,0,0); | |
| 40 | 38 | fclose(LOG); |
| 41 | 39 | } |
| 42 | 40 | |
| 43 | 41 | int main(void) |
| 44 | 42 | { |
| 45 | 43 | int rc; |
| 46 | − L=lua_open(0); | |
| 44 | + lua_State *L=lua_open(); | |
| 47 | 45 | lua_baselibopen(L); |
| 46 | + lua_tablibopen(L); | |
| 48 | 47 | lua_iolibopen(L); |
| 49 | 48 | lua_strlibopen(L); |
| 50 | 49 | lua_mathlibopen(L); |
| 51 | 50 | lua_dblibopen(L); |
| 52 | − start_trace(stderr); | |
| 53 | − rc=lua_dofile(L,0); | |
| 54 | − stop_trace(); | |
| 51 | + start_trace(L,stderr); | |
| 52 | + rc=lua_dofile(L,NULL); | |
| 53 | + stop_trace(L); | |
| 55 | 54 | return rc; |
| 56 | 55 | } |
| @@ -4,7 +4,7 @@ LUA= .. · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | include $(LUA)/config |
| 6 | 6 | |
| 7 | −SRCS= lua.h lualib.h luadebug.h lauxlib.h | |
| 7 | +SRCS= lua.h lualib.h lauxlib.h | |
| 8 | 8 | |
| 9 | 9 | all: |
| 10 | 10 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lauxlib.h,v 1.30 2000/10/30 12:38:50 roberto Exp $ | |
| 2 | +** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -16,29 +16,51 @@ · 10 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | |
| 18 | 18 | #ifndef LUALIB_API |
| 19 | −#define LUALIB_API extern | |
| 19 | +#define LUALIB_API LUA_API | |
| 20 | 20 | #endif |
| 21 | 21 | |
| 22 | 22 | |
| 23 | −struct luaL_reg { | |
| 23 | + | |
| 24 | +typedef struct luaL_reg { | |
| 24 | 25 | const char *name; |
| 25 | 26 | lua_CFunction func; |
| 26 | −}; | |
| 27 | +} luaL_reg; | |
| 28 | + | |
| 29 | + | |
| 30 | +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | |
| 31 | + const luaL_reg *l, int nup); | |
| 32 | +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); | |
| 33 | +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e); | |
| 34 | +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname); | |
| 35 | +LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg); | |
| 36 | +LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l); | |
| 37 | +LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg, | |
| 38 | + const char *def, size_t *l); | |
| 39 | +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg); | |
| 40 | +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def); | |
| 41 | + | |
| 42 | +LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg); | |
| 43 | +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); | |
| 44 | +LUALIB_API void luaL_checkany (lua_State *L, int narg); | |
| 27 | 45 | |
| 46 | +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname); | |
| 47 | +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname); | |
| 48 | +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname); | |
| 28 | 49 | |
| 29 | −LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n); | |
| 30 | −LUALIB_API void luaL_argerror (lua_State *L, int numarg, const char *extramsg); | |
| 31 | −LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg, size_t *len); | |
| 32 | −LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg, const char *def, size_t *len); | |
| 33 | −LUALIB_API double luaL_check_number (lua_State *L, int numArg); | |
| 34 | −LUALIB_API double luaL_opt_number (lua_State *L, int numArg, double def); | |
| 50 | +LUALIB_API void luaL_where (lua_State *L, int lvl); | |
| 51 | +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...); | |
| 35 | 52 | |
| 36 | −LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg); | |
| 37 | −LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); | |
| 38 | −LUALIB_API void luaL_checkany (lua_State *L, int narg); | |
| 53 | +LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); | |
| 54 | + | |
| 55 | +LUALIB_API int luaL_ref (lua_State *L, int t); | |
| 56 | +LUALIB_API void luaL_unref (lua_State *L, int t, int ref); | |
| 57 | + | |
| 58 | +LUALIB_API int luaL_getn (lua_State *L, int t); | |
| 59 | +LUALIB_API void luaL_setn (lua_State *L, int t, int n); | |
| 39 | 60 | |
| 40 | −LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); | |
| 41 | −LUALIB_API int luaL_findstring (const char *name, const char *const list[]); | |
| 61 | +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); | |
| 62 | +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, | |
| 63 | + const char *name); | |
| 42 | 64 | |
| 43 | 65 | |
| 44 | 66 | |
| @@ -48,15 +70,14 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]); · 3 unmodified lines | ||
| 48 | 70 | ** =============================================================== |
| 49 | 71 | */ |
| 50 | 72 | |
| 51 | −#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \ | |
| 73 | +#define luaL_argcheck(L, cond,numarg,extramsg) if (!(cond)) \ | |
| 52 | 74 | luaL_argerror(L, numarg,extramsg) |
| 53 | −#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL)) | |
| 54 | −#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL)) | |
| 55 | −#define luaL_check_int(L,n) ((int)luaL_check_number(L, n)) | |
| 56 | −#define luaL_check_long(L,n) ((long)luaL_check_number(L, n)) | |
| 57 | −#define luaL_opt_int(L,n,d) ((int)luaL_opt_number(L, n,d)) | |
| 58 | −#define luaL_opt_long(L,n,d) ((long)luaL_opt_number(L, n,d)) | |
| 59 | −#define luaL_openl(L,a) luaL_openlib(L, a, (sizeof(a)/sizeof(a[0]))) | |
| 75 | +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) | |
| 76 | +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) | |
| 77 | +#define luaL_checkint(L,n) ((int)luaL_checknumber(L, n)) | |
| 78 | +#define luaL_checklong(L,n) ((long)luaL_checknumber(L, n)) | |
| 79 | +#define luaL_optint(L,n,d) ((int)luaL_optnumber(L, n,(lua_Number)(d))) | |
| 80 | +#define luaL_optlong(L,n,d) ((long)luaL_optnumber(L, n,(lua_Number)(d))) | |
| 60 | 81 | |
| 61 | 82 | |
| 62 | 83 | /* |
| @@ -73,13 +94,13 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]); · 10 unmodified lines | ||
| 73 | 94 | |
| 74 | 95 | typedef struct luaL_Buffer { |
| 75 | 96 | char *p; /* current position in buffer */ |
| 76 | − int level; | |
| 97 | + int lvl; /* number of strings in the stack (level) */ | |
| 77 | 98 | lua_State *L; |
| 78 | 99 | char buffer[LUAL_BUFFERSIZE]; |
| 79 | 100 | } luaL_Buffer; |
| 80 | 101 | |
| 81 | 102 | #define luaL_putchar(B,c) \ |
| 82 | − ((void)((B)->p < &(B)->buffer[LUAL_BUFFERSIZE] || luaL_prepbuffer(B)), \ | |
| 103 | + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ | |
| 83 | 104 | (*(B)->p++ = (char)(c))) |
| 84 | 105 | |
| 85 | 106 | #define luaL_addsize(B,n) ((B)->p += (n)) |
| @@ -95,6 +116,30 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B); · 9 unmodified lines | ||
| 95 | 116 | /* }====================================================== */ |
| 96 | 117 | |
| 97 | 118 | |
| 119 | + | |
| 120 | +/* | |
| 121 | +** Compatibility macros and functions | |
| 122 | +*/ | |
| 123 | + | |
| 124 | +LUALIB_API int lua_dofile (lua_State *L, const char *filename); | |
| 125 | +LUALIB_API int lua_dostring (lua_State *L, const char *str); | |
| 126 | +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz, | |
| 127 | + const char *n); | |
| 128 | + | |
| 129 | + | |
| 130 | +#define luaL_check_lstr luaL_checklstring | |
| 131 | +#define luaL_opt_lstr luaL_optlstring | |
| 132 | +#define luaL_check_number luaL_checknumber | |
| 133 | +#define luaL_opt_number luaL_optnumber | |
| 134 | +#define luaL_arg_check luaL_argcheck | |
| 135 | +#define luaL_check_string luaL_checkstring | |
| 136 | +#define luaL_opt_string luaL_optstring | |
| 137 | +#define luaL_check_int luaL_checkint | |
| 138 | +#define luaL_check_long luaL_checklong | |
| 139 | +#define luaL_opt_int luaL_optint | |
| 140 | +#define luaL_opt_long luaL_optlong | |
| 141 | + | |
| 142 | + | |
| 98 | 143 | #endif |
| 99 | 144 | |
| 100 | 145 | |
| @@ -1,9 +1,8 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lua.h,v 1.79a 2000/10/31 12:44:07 roberto Exp $ | |
| 2 | +** $Id: lua.h,v 1.175 2003/03/18 12:31:39 roberto Exp $ | |
| 3 | 3 | ** Lua - An Extensible Extension Language |
| 4 | −** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil | |
| 5 | −** e-mail: lua@tecgraf.puc-rio.br | |
| 6 | −** www: http://www.tecgraf.puc-rio.br/lua/ | |
| 4 | +** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil | |
| 5 | +** http://www.lua.org mailto:info@lua.org | |
| 7 | 6 | ** See Copyright Notice at the end of this file |
| 8 | 7 | */ |
| 9 | 8 | |
| @@ -11,45 +10,29 @@ · 1 unmodified line | ||
| 11 | 10 | #ifndef lua_h |
| 12 | 11 | #define lua_h |
| 13 | 12 | |
| 14 | − | |
| 15 | −/* definition of `size_t' */ | |
| 13 | +#include <stdarg.h> | |
| 16 | 14 | #include <stddef.h> |
| 17 | 15 | |
| 18 | 16 | |
| 19 | −/* mark for all API functions */ | |
| 20 | −#ifndef LUA_API | |
| 21 | −#define LUA_API extern | |
| 22 | −#endif | |
| 23 | − | |
| 24 | − | |
| 25 | −#define LUA_VERSION "Lua 4.0.1" | |
| 26 | −#define LUA_COPYRIGHT "Copyright (C) 1994-2000 TeCGraf, PUC-Rio" | |
| 27 | −#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" | |
| 17 | +#define LUA_VERSION "Lua 5.0" | |
| 18 | +#define LUA_COPYRIGHT "Copyright (C) 1994-2003 Tecgraf, PUC-Rio" | |
| 19 | +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" | |
| 28 | 20 | |
| 29 | 21 | |
| 30 | −/* name of global variable with error handler */ | |
| 31 | −#define LUA_ERRORMESSAGE "_ERRORMESSAGE" | |
| 32 | − | |
| 33 | − | |
| 34 | −/* pre-defined references */ | |
| 35 | −#define LUA_NOREF (-2) | |
| 36 | −#define LUA_REFNIL (-1) | |
| 37 | −#define LUA_REFREGISTRY 0 | |
| 38 | − | |
| 39 | −/* pre-defined tags */ | |
| 40 | −#define LUA_ANYTAG (-1) | |
| 41 | −#define LUA_NOTAG (-2) | |
| 42 | 22 | |
| 43 | − | |
| 44 | −/* option for multiple returns in lua_call */ | |
| 23 | +/* option for multiple returns in `lua_pcall' and `lua_call' */ | |
| 45 | 24 | #define LUA_MULTRET (-1) |
| 46 | 25 | |
| 47 | 26 | |
| 48 | −/* minimum stack available for a C function */ | |
| 49 | −#define LUA_MINSTACK 20 | |
| 27 | +/* | |
| 28 | +** pseudo-indices | |
| 29 | +*/ | |
| 30 | +#define LUA_REGISTRYINDEX (-10000) | |
| 31 | +#define LUA_GLOBALSINDEX (-10001) | |
| 32 | +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) | |
| 50 | 33 | |
| 51 | 34 | |
| 52 | −/* error codes for lua_do* */ | |
| 35 | +/* error codes for `lua_load' and `lua_pcall' */ | |
| 53 | 36 | #define LUA_ERRRUN 1 |
| 54 | 37 | #define LUA_ERRFILE 2 |
| 55 | 38 | #define LUA_ERRSYNTAX 3 |
| @@ -61,107 +44,164 @@ typedef struct lua_State lua_State; · 5 unmodified lines | ||
| 61 | 44 | |
| 62 | 45 | typedef int (*lua_CFunction) (lua_State *L); |
| 63 | 46 | |
| 47 | + | |
| 48 | +/* | |
| 49 | +** functions that read/write blocks when loading/dumping Lua chunks | |
| 50 | +*/ | |
| 51 | +typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz); | |
| 52 | + | |
| 53 | +typedef int (*lua_Chunkwriter) (lua_State *L, const void* p, | |
| 54 | + size_t sz, void* ud); | |
| 55 | + | |
| 56 | + | |
| 64 | 57 | /* |
| 65 | −** types returned by `lua_type' | |
| 58 | +** basic types | |
| 66 | 59 | */ |
| 67 | 60 | #define LUA_TNONE (-1) |
| 68 | 61 | |
| 69 | −#define LUA_TUSERDATA 0 | |
| 70 | −#define LUA_TNIL 1 | |
| 71 | −#define LUA_TNUMBER 2 | |
| 72 | −#define LUA_TSTRING 3 | |
| 73 | −#define LUA_TTABLE 4 | |
| 74 | −#define LUA_TFUNCTION 5 | |
| 62 | +#define LUA_TNIL 0 | |
| 63 | +#define LUA_TBOOLEAN 1 | |
| 64 | +#define LUA_TLIGHTUSERDATA 2 | |
| 65 | +#define LUA_TNUMBER 3 | |
| 66 | +#define LUA_TSTRING 4 | |
| 67 | +#define LUA_TTABLE 5 | |
| 68 | +#define LUA_TFUNCTION 6 | |
| 69 | +#define LUA_TUSERDATA 7 | |
| 70 | +#define LUA_TTHREAD 8 | |
| 71 | + | |
| 72 | + | |
| 73 | +/* minimum Lua stack available to a C function */ | |
| 74 | +#define LUA_MINSTACK 20 | |
| 75 | 75 | |
| 76 | 76 | |
| 77 | +/* | |
| 78 | +** generic extra include file | |
| 79 | +*/ | |
| 80 | +#ifdef LUA_USER_H | |
| 81 | +#include LUA_USER_H | |
| 82 | +#endif | |
| 83 | + | |
| 84 | + | |
| 85 | +/* type of numbers in Lua */ | |
| 86 | +#ifndef LUA_NUMBER | |
| 87 | +typedef double lua_Number; | |
| 88 | +#else | |
| 89 | +typedef LUA_NUMBER lua_Number; | |
| 90 | +#endif | |
| 91 | + | |
| 92 | + | |
| 93 | +/* mark for all API functions */ | |
| 94 | +#ifndef LUA_API | |
| 95 | +#define LUA_API extern | |
| 96 | +#endif | |
| 97 | + | |
| 77 | 98 | |
| 78 | 99 | /* |
| 79 | 100 | ** state manipulation |
| 80 | 101 | */ |
| 81 | −LUA_API lua_State *lua_open (int stacksize); | |
| 102 | +LUA_API lua_State *lua_open (void); | |
| 82 | 103 | LUA_API void lua_close (lua_State *L); |
| 104 | +LUA_API lua_State *lua_newthread (lua_State *L); | |
| 105 | + | |
| 106 | +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); | |
| 83 | 107 | |
| 84 | 108 | |
| 85 | 109 | /* |
| 86 | 110 | ** basic stack manipulation |
| 87 | 111 | */ |
| 88 | 112 | LUA_API int lua_gettop (lua_State *L); |
| 89 | −LUA_API void lua_settop (lua_State *L, int index); | |
| 90 | −LUA_API void lua_pushvalue (lua_State *L, int index); | |
| 91 | −LUA_API void lua_remove (lua_State *L, int index); | |
| 92 | −LUA_API void lua_insert (lua_State *L, int index); | |
| 93 | −LUA_API int lua_stackspace (lua_State *L); | |
| 113 | +LUA_API void lua_settop (lua_State *L, int idx); | |
| 114 | +LUA_API void lua_pushvalue (lua_State *L, int idx); | |
| 115 | +LUA_API void lua_remove (lua_State *L, int idx); | |
| 116 | +LUA_API void lua_insert (lua_State *L, int idx); | |
| 117 | +LUA_API void lua_replace (lua_State *L, int idx); | |
| 118 | +LUA_API int lua_checkstack (lua_State *L, int sz); | |
| 119 | + | |
| 120 | +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n); | |
| 94 | 121 | |
| 95 | 122 | |
| 96 | 123 | /* |
| 97 | 124 | ** access functions (stack -> C) |
| 98 | 125 | */ |
| 99 | 126 | |
| 100 | −LUA_API int lua_type (lua_State *L, int index); | |
| 101 | −LUA_API const char *lua_typename (lua_State *L, int t); | |
| 102 | −LUA_API int lua_isnumber (lua_State *L, int index); | |
| 103 | −LUA_API int lua_isstring (lua_State *L, int index); | |
| 104 | −LUA_API int lua_iscfunction (lua_State *L, int index); | |
| 105 | −LUA_API int lua_tag (lua_State *L, int index); | |
| 127 | +LUA_API int lua_isnumber (lua_State *L, int idx); | |
| 128 | +LUA_API int lua_isstring (lua_State *L, int idx); | |
| 129 | +LUA_API int lua_iscfunction (lua_State *L, int idx); | |
| 130 | +LUA_API int lua_isuserdata (lua_State *L, int idx); | |
| 131 | +LUA_API int lua_type (lua_State *L, int idx); | |
| 132 | +LUA_API const char *lua_typename (lua_State *L, int tp); | |
| 106 | 133 | |
| 107 | −LUA_API int lua_equal (lua_State *L, int index1, int index2); | |
| 108 | −LUA_API int lua_lessthan (lua_State *L, int index1, int index2); | |
| 134 | +LUA_API int lua_equal (lua_State *L, int idx1, int idx2); | |
| 135 | +LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2); | |
| 136 | +LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2); | |
| 109 | 137 | |
| 110 | −LUA_API double lua_tonumber (lua_State *L, int index); | |
| 111 | −LUA_API const char *lua_tostring (lua_State *L, int index); | |
| 112 | −LUA_API size_t lua_strlen (lua_State *L, int index); | |
| 113 | −LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index); | |
| 114 | −LUA_API void *lua_touserdata (lua_State *L, int index); | |
| 115 | −LUA_API const void *lua_topointer (lua_State *L, int index); | |
| 138 | +LUA_API lua_Number lua_tonumber (lua_State *L, int idx); | |
| 139 | +LUA_API int lua_toboolean (lua_State *L, int idx); | |
| 140 | +LUA_API const char *lua_tostring (lua_State *L, int idx); | |
| 141 | +LUA_API size_t lua_strlen (lua_State *L, int idx); | |
| 142 | +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx); | |
| 143 | +LUA_API void *lua_touserdata (lua_State *L, int idx); | |
| 144 | +LUA_API lua_State *lua_tothread (lua_State *L, int idx); | |
| 145 | +LUA_API const void *lua_topointer (lua_State *L, int idx); | |
| 116 | 146 | |
| 117 | 147 | |
| 118 | 148 | /* |
| 119 | 149 | ** push functions (C -> stack) |
| 120 | 150 | */ |
| 121 | 151 | LUA_API void lua_pushnil (lua_State *L); |
| 122 | −LUA_API void lua_pushnumber (lua_State *L, double n); | |
| 123 | −LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); | |
| 152 | +LUA_API void lua_pushnumber (lua_State *L, lua_Number n); | |
| 153 | +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t l); | |
| 124 | 154 | LUA_API void lua_pushstring (lua_State *L, const char *s); |
| 155 | +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, | |
| 156 | + va_list argp); | |
| 157 | +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...); | |
| 125 | 158 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); |
| 126 | −LUA_API void lua_pushusertag (lua_State *L, void *u, int tag); | |
| 159 | +LUA_API void lua_pushboolean (lua_State *L, int b); | |
| 160 | +LUA_API void lua_pushlightuserdata (lua_State *L, void *p); | |
| 127 | 161 | |
| 128 | 162 | |
| 129 | 163 | /* |
| 130 | 164 | ** get functions (Lua -> stack) |
| 131 | 165 | */ |
| 132 | −LUA_API void lua_getglobal (lua_State *L, const char *name); | |
| 133 | −LUA_API void lua_gettable (lua_State *L, int index); | |
| 134 | −LUA_API void lua_rawget (lua_State *L, int index); | |
| 135 | −LUA_API void lua_rawgeti (lua_State *L, int index, int n); | |
| 136 | −LUA_API void lua_getglobals (lua_State *L); | |
| 137 | −LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); | |
| 138 | −LUA_API int lua_getref (lua_State *L, int ref); | |
| 166 | +LUA_API void lua_gettable (lua_State *L, int idx); | |
| 167 | +LUA_API void lua_rawget (lua_State *L, int idx); | |
| 168 | +LUA_API void lua_rawgeti (lua_State *L, int idx, int n); | |
| 139 | 169 | LUA_API void lua_newtable (lua_State *L); |
| 170 | +LUA_API void *lua_newuserdata (lua_State *L, size_t sz); | |
| 171 | +LUA_API int lua_getmetatable (lua_State *L, int objindex); | |
| 172 | +LUA_API void lua_getfenv (lua_State *L, int idx); | |
| 140 | 173 | |
| 141 | 174 | |
| 142 | 175 | /* |
| 143 | 176 | ** set functions (stack -> Lua) |
| 144 | 177 | */ |
| 145 | −LUA_API void lua_setglobal (lua_State *L, const char *name); | |
| 146 | −LUA_API void lua_settable (lua_State *L, int index); | |
| 147 | −LUA_API void lua_rawset (lua_State *L, int index); | |
| 148 | −LUA_API void lua_rawseti (lua_State *L, int index, int n); | |
| 149 | −LUA_API void lua_setglobals (lua_State *L); | |
| 150 | −LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); | |
| 151 | −LUA_API int lua_ref (lua_State *L, int lock); | |
| 178 | +LUA_API void lua_settable (lua_State *L, int idx); | |
| 179 | +LUA_API void lua_rawset (lua_State *L, int idx); | |
| 180 | +LUA_API void lua_rawseti (lua_State *L, int idx, int n); | |
| 181 | +LUA_API int lua_setmetatable (lua_State *L, int objindex); | |
| 182 | +LUA_API int lua_setfenv (lua_State *L, int idx); | |
| 183 | + | |
| 184 | + | |
| 185 | +/* | |
| 186 | +** `load' and `call' functions (load and run Lua code) | |
| 187 | +*/ | |
| 188 | +LUA_API void lua_call (lua_State *L, int nargs, int nresults); | |
| 189 | +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); | |
| 190 | +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); | |
| 191 | +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt, | |
| 192 | + const char *chunkname); | |
| 193 | + | |
| 194 | +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data); | |
| 152 | 195 | |
| 153 | 196 | |
| 154 | 197 | /* |
| 155 | −** "do" functions (run Lua code) | |
| 198 | +** coroutine functions | |
| 156 | 199 | */ |
| 157 | −LUA_API int lua_call (lua_State *L, int nargs, int nresults); | |
| 158 | −LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults); | |
| 159 | −LUA_API int lua_dofile (lua_State *L, const char *filename); | |
| 160 | −LUA_API int lua_dostring (lua_State *L, const char *str); | |
| 161 | −LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name); | |
| 200 | +LUA_API int lua_yield (lua_State *L, int nresults); | |
| 201 | +LUA_API int lua_resume (lua_State *L, int narg); | |
| 162 | 202 | |
| 163 | 203 | /* |
| 164 | −** Garbage-collection functions | |
| 204 | +** garbage-collection functions | |
| 165 | 205 | */ |
| 166 | 206 | LUA_API int lua_getgcthreshold (lua_State *L); |
| 167 | 207 | LUA_API int lua_getgccount (lua_State *L); |
| @@ -170,20 +210,15 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); · 2 unmodified lines | ||
| 170 | 210 | /* |
| 171 | 211 | ** miscellaneous functions |
| 172 | 212 | */ |
| 173 | −LUA_API int lua_newtag (lua_State *L); | |
| 174 | −LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); | |
| 175 | −LUA_API void lua_settag (lua_State *L, int tag); | |
| 176 | 213 | |
| 177 | −LUA_API void lua_error (lua_State *L, const char *s); | |
| 214 | +LUA_API const char *lua_version (void); | |
| 178 | 215 | |
| 179 | −LUA_API void lua_unref (lua_State *L, int ref); | |
| 216 | +LUA_API int lua_error (lua_State *L); | |
| 180 | 217 | |
| 181 | −LUA_API int lua_next (lua_State *L, int index); | |
| 182 | −LUA_API int lua_getn (lua_State *L, int index); | |
| 218 | +LUA_API int lua_next (lua_State *L, int idx); | |
| 183 | 219 | |
| 184 | 220 | LUA_API void lua_concat (lua_State *L, int n); |
| 185 | 221 | |
| 186 | −LUA_API void *lua_newuserdata (lua_State *L, size_t size); | |
| 187 | 222 | |
| 188 | 223 | |
| 189 | 224 | /* |
| @@ -192,57 +227,165 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size); · 2 unmodified lines | ||
| 192 | 227 | ** =============================================================== |
| 193 | 228 | */ |
| 194 | 229 | |
| 230 | +#define lua_boxpointer(L,u) \ | |
| 231 | + (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u)) | |
| 232 | + | |
| 233 | +#define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i))) | |
| 234 | + | |
| 195 | 235 | #define lua_pop(L,n) lua_settop(L, -(n)-1) |
| 196 | 236 | |
| 197 | −#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) | |
| 198 | −#define lua_pushuserdata(L,u) lua_pushusertag(L, u, 0) | |
| 237 | +#define lua_register(L,n,f) \ | |
| 238 | + (lua_pushstring(L, n), \ | |
| 239 | + lua_pushcfunction(L, f), \ | |
| 240 | + lua_settable(L, LUA_GLOBALSINDEX)) | |
| 241 | + | |
| 199 | 242 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) |
| 200 | −#define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) | |
| 201 | 243 | |
| 202 | 244 | #define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) |
| 203 | 245 | #define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) |
| 204 | −#define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) | |
| 246 | +#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA) | |
| 205 | 247 | #define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) |
| 206 | −#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) | |
| 248 | +#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN) | |
| 249 | +#define lua_isnone(L,n) (lua_type(L,n) == LUA_TNONE) | |
| 250 | +#define lua_isnoneornil(L, n) (lua_type(L,n) <= 0) | |
| 251 | + | |
| 252 | +#define lua_pushliteral(L, s) \ | |
| 253 | + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) | |
| 207 | 254 | |
| 208 | −#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) | |
| 209 | 255 | |
| 256 | + | |
| 257 | +/* | |
| 258 | +** compatibility macros and functions | |
| 259 | +*/ | |
| 260 | + | |
| 261 | + | |
| 262 | +LUA_API int lua_pushupvalues (lua_State *L); | |
| 263 | + | |
| 264 | +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) | |
| 265 | +#define lua_setglobal(L,s) \ | |
| 266 | + (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX)) | |
| 267 | + | |
| 268 | +#define lua_getglobal(L,s) \ | |
| 269 | + (lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX)) | |
| 270 | + | |
| 271 | + | |
| 272 | +/* compatibility with ref system */ | |
| 273 | + | |
| 274 | +/* pre-defined references */ | |
| 275 | +#define LUA_NOREF (-2) | |
| 276 | +#define LUA_REFNIL (-1) | |
| 277 | + | |
| 278 | +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ | |
| 279 | + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) | |
| 280 | + | |
| 281 | +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) | |
| 282 | + | |
| 283 | +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, ref) | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | +/* | |
| 288 | +** {====================================================================== | |
| 289 | +** useful definitions for Lua kernel and libraries | |
| 290 | +** ======================================================================= | |
| 291 | +*/ | |
| 292 | + | |
| 293 | +/* formats for Lua numbers */ | |
| 294 | +#ifndef LUA_NUMBER_SCAN | |
| 295 | +#define LUA_NUMBER_SCAN "%lf" | |
| 210 | 296 | #endif |
| 211 | 297 | |
| 298 | +#ifndef LUA_NUMBER_FMT | |
| 299 | +#define LUA_NUMBER_FMT "%.14g" | |
| 300 | +#endif | |
| 301 | + | |
| 302 | +/* }====================================================================== */ | |
| 303 | + | |
| 304 | + | |
| 305 | +/* | |
| 306 | +** {====================================================================== | |
| 307 | +** Debug API | |
| 308 | +** ======================================================================= | |
| 309 | +*/ | |
| 310 | + | |
| 311 | + | |
| 312 | +/* | |
| 313 | +** Event codes | |
| 314 | +*/ | |
| 315 | +#define LUA_HOOKCALL 0 | |
| 316 | +#define LUA_HOOKRET 1 | |
| 317 | +#define LUA_HOOKLINE 2 | |
| 318 | +#define LUA_HOOKCOUNT 3 | |
| 319 | +#define LUA_HOOKTAILRET 4 | |
| 320 | + | |
| 321 | + | |
| 322 | +/* | |
| 323 | +** Event masks | |
| 324 | +*/ | |
| 325 | +#define LUA_MASKCALL (1 << LUA_HOOKCALL) | |
| 326 | +#define LUA_MASKRET (1 << LUA_HOOKRET) | |
| 327 | +#define LUA_MASKLINE (1 << LUA_HOOKLINE) | |
| 328 | +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) | |
| 329 | + | |
| 330 | +typedef struct lua_Debug lua_Debug; /* activation record */ | |
| 331 | + | |
| 332 | +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); | |
| 333 | + | |
| 334 | + | |
| 335 | +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); | |
| 336 | +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); | |
| 337 | +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); | |
| 338 | +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); | |
| 339 | +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); | |
| 340 | +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); | |
| 341 | + | |
| 342 | +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); | |
| 343 | +LUA_API lua_Hook lua_gethook (lua_State *L); | |
| 344 | +LUA_API int lua_gethookmask (lua_State *L); | |
| 345 | +LUA_API int lua_gethookcount (lua_State *L); | |
| 346 | + | |
| 347 | + | |
| 348 | +#define LUA_IDSIZE 60 | |
| 349 | + | |
| 350 | +struct lua_Debug { | |
| 351 | + int event; | |
| 352 | + const char *name; /* (n) */ | |
| 353 | + const char *namewhat; /* (n) `global', `local', `field', `method' */ | |
| 354 | + const char *what; /* (S) `Lua', `C', `main', `tail' */ | |
| 355 | + const char *source; /* (S) */ | |
| 356 | + int currentline; /* (l) */ | |
| 357 | + int nups; /* (u) number of upvalues */ | |
| 358 | + int linedefined; /* (S) */ | |
| 359 | + char short_src[LUA_IDSIZE]; /* (S) */ | |
| 360 | + /* private part */ | |
| 361 | + int i_ci; /* active function */ | |
| 362 | +}; | |
| 363 | + | |
| 364 | +/* }====================================================================== */ | |
| 212 | 365 | |
| 213 | 366 | |
| 214 | 367 | /****************************************************************************** |
| 215 | −* Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. | |
| 216 | −* | |
| 217 | −* Permission is hereby granted, without written agreement and without license | |
| 218 | −* or royalty fees, to use, copy, modify, and distribute this software and its | |
| 219 | −* documentation for any purpose, including commercial applications, subject to | |
| 368 | +* Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved. | |
| 369 | +* | |
| 370 | +* Permission is hereby granted, free of charge, to any person obtaining | |
| 371 | +* a copy of this software and associated documentation files (the | |
| 372 | +* "Software"), to deal in the Software without restriction, including | |
| 373 | +* without limitation the rights to use, copy, modify, merge, publish, | |
| 374 | +* distribute, sublicense, and/or sell copies of the Software, and to | |
| 375 | +* permit persons to whom the Software is furnished to do so, subject to | |
| 220 | 376 | * the following conditions: |
| 221 | −* | |
| 222 | −* - The above copyright notice and this permission notice shall appear in all | |
| 223 | −* copies or substantial portions of this software. | |
| 224 | −* | |
| 225 | −* - The origin of this software must not be misrepresented; you must not | |
| 226 | −* claim that you wrote the original software. If you use this software in a | |
| 227 | −* product, an acknowledgment in the product documentation would be greatly | |
| 228 | −* appreciated (but it is not required). | |
| 229 | −* | |
| 230 | −* - Altered source versions must be plainly marked as such, and must not be | |
| 231 | −* misrepresented as being the original software. | |
| 232 | −* | |
| 233 | −* The authors specifically disclaim any warranties, including, but not limited | |
| 234 | −* to, the implied warranties of merchantability and fitness for a particular | |
| 235 | −* purpose. The software provided hereunder is on an "as is" basis, and the | |
| 236 | −* authors have no obligation to provide maintenance, support, updates, | |
| 237 | −* enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the | |
| 238 | −* authors be held liable to any party for direct, indirect, special, | |
| 239 | −* incidental, or consequential damages arising out of the use of this software | |
| 240 | −* and its documentation. | |
| 241 | −* | |
| 242 | −* The Lua language and this implementation have been entirely designed and | |
| 243 | −* written by Waldemar Celes Filho, Roberto Ierusalimschy and | |
| 244 | −* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio. | |
| 245 | 377 | * |
| 246 | −* This implementation contains no third-party code. | |
| 378 | +* The above copyright notice and this permission notice shall be | |
| 379 | +* included in all copies or substantial portions of the Software. | |
| 380 | +* | |
| 381 | +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 382 | +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 383 | +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 384 | +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 385 | +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 386 | +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 387 | +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 247 | 388 | ******************************************************************************/ |
| 248 | 389 | |
| 390 | + | |
| 391 | +#endif | |
| @@ -1,46 +0,0 @@ | ||
| 1 | −/* | |
| 2 | −** $Id: luadebug.h,v 1.17 2000/10/30 12:38:50 roberto Exp $ | |
| 3 | −** Debugging API | |
| 4 | −** See Copyright Notice in lua.h | |
| 5 | −*/ | |
| 6 | − | |
| 7 | − | |
| 8 | −#ifndef luadebug_h | |
| 9 | −#define luadebug_h | |
| 10 | − | |
| 11 | − | |
| 12 | −#include "lua.h" | |
| 13 | − | |
| 14 | −typedef struct lua_Debug lua_Debug; /* activation record */ | |
| 15 | −typedef struct lua_Localvar lua_Localvar; | |
| 16 | − | |
| 17 | −typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); | |
| 18 | − | |
| 19 | − | |
| 20 | −LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); | |
| 21 | −LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); | |
| 22 | −LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); | |
| 23 | −LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); | |
| 24 | − | |
| 25 | −LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); | |
| 26 | −LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func); | |
| 27 | − | |
| 28 | − | |
| 29 | −#define LUA_IDSIZE 60 | |
| 30 | − | |
| 31 | −struct lua_Debug { | |
| 32 | − const char *event; /* `call', `return' */ | |
| 33 | − int currentline; /* (l) */ | |
| 34 | − const char *name; /* (n) */ | |
| 35 | − const char *namewhat; /* (n) `global', `tag method', `local', `field' */ | |
| 36 | − int nups; /* (u) number of upvalues */ | |
| 37 | − int linedefined; /* (S) */ | |
| 38 | − const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ | |
| 39 | − const char *source; /* (S) */ | |
| 40 | − char short_src[LUA_IDSIZE]; /* (S) */ | |
| 41 | − /* private part */ | |
| 42 | − struct lua_TObject *_func; /* active function */ | |
| 43 | −}; | |
| 44 | − | |
| 45 | − | |
| 46 | −#endif | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lualib.h,v 1.14 2000/10/27 16:15:53 roberto Exp $ | |
| 2 | +** $Id: lualib.h,v 1.28 2003/03/18 12:24:26 roberto Exp $ | |
| 3 | 3 | ** Lua standard libraries |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -12,23 +12,45 @@ · 6 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | |
| 14 | 14 | #ifndef LUALIB_API |
| 15 | −#define LUALIB_API extern | |
| 15 | +#define LUALIB_API LUA_API | |
| 16 | 16 | #endif |
| 17 | 17 | |
| 18 | 18 | |
| 19 | −#define LUA_ALERT "_ALERT" | |
| 19 | +#define LUA_COLIBNAME "coroutine" | |
| 20 | +LUALIB_API int luaopen_base (lua_State *L); | |
| 20 | 21 | |
| 21 | −LUALIB_API void lua_baselibopen (lua_State *L); | |
| 22 | −LUALIB_API void lua_iolibopen (lua_State *L); | |
| 23 | −LUALIB_API void lua_strlibopen (lua_State *L); | |
| 24 | −LUALIB_API void lua_mathlibopen (lua_State *L); | |
| 25 | −LUALIB_API void lua_dblibopen (lua_State *L); | |
| 22 | +#define LUA_TABLIBNAME "table" | |
| 23 | +LUALIB_API int luaopen_table (lua_State *L); | |
| 26 | 24 | |
| 25 | +#define LUA_IOLIBNAME "io" | |
| 26 | +#define LUA_OSLIBNAME "os" | |
| 27 | +LUALIB_API int luaopen_io (lua_State *L); | |
| 27 | 28 | |
| 29 | +#define LUA_STRLIBNAME "string" | |
| 30 | +LUALIB_API int luaopen_string (lua_State *L); | |
| 28 | 31 | |
| 29 | −/* Auxiliary functions (private) */ | |
| 32 | +#define LUA_MATHLIBNAME "math" | |
| 33 | +LUALIB_API int luaopen_math (lua_State *L); | |
| 30 | 34 | |
| 31 | −const char *luaI_classend (lua_State *L, const char *p); | |
| 32 | −int luaI_singlematch (int c, const char *p, const char *ep); | |
| 35 | +#define LUA_DBLIBNAME "debug" | |
| 36 | +LUALIB_API int luaopen_debug (lua_State *L); | |
| 37 | + | |
| 38 | + | |
| 39 | +LUALIB_API int luaopen_loadlib (lua_State *L); | |
| 40 | + | |
| 41 | + | |
| 42 | +/* to help testing the libraries */ | |
| 43 | +#ifndef lua_assert | |
| 44 | +#define lua_assert(c) /* empty */ | |
| 45 | +#endif | |
| 46 | + | |
| 47 | + | |
| 48 | +/* compatibility code */ | |
| 49 | +#define lua_baselibopen luaopen_base | |
| 50 | +#define lua_tablibopen luaopen_table | |
| 51 | +#define lua_iolibopen luaopen_io | |
| 52 | +#define lua_strlibopen luaopen_string | |
| 53 | +#define lua_mathlibopen luaopen_math | |
| 54 | +#define lua_dblibopen luaopen_debug | |
| 33 | 55 | |
| 34 | 56 | #endif |
| @@ -9,11 +9,13 @@ OBJS= \ · 8 unmodified lines | ||
| 9 | 9 | lcode.o \ |
| 10 | 10 | ldebug.o \ |
| 11 | 11 | ldo.o \ |
| 12 | + ldump.o \ | |
| 12 | 13 | lfunc.o \ |
| 13 | 14 | lgc.o \ |
| 14 | 15 | llex.o \ |
| 15 | 16 | lmem.o \ |
| 16 | 17 | lobject.o \ |
| 18 | + lopcodes.o \ | |
| 17 | 19 | lparser.o \ |
| 18 | 20 | lstate.o \ |
| 19 | 21 | lstring.o \ |
| @@ -29,11 +31,13 @@ SRCS= \ · 9 unmodified lines | ||
| 29 | 31 | lcode.c \ |
| 30 | 32 | ldebug.c \ |
| 31 | 33 | ldo.c \ |
| 34 | + ldump.c \ | |
| 32 | 35 | lfunc.c \ |
| 33 | 36 | lgc.c \ |
| 34 | 37 | llex.c \ |
| 35 | 38 | lmem.c \ |
| 36 | 39 | lobject.c \ |
| 40 | + lopcodes.c \ | |
| 37 | 41 | lparser.c \ |
| 38 | 42 | lstate.c \ |
| 39 | 43 | lstring.c \ |
| @@ -65,9 +69,9 @@ SRCS= \ · 25 unmodified lines | ||
| 65 | 69 | |
| 66 | 70 | T= $(LIB)/liblua.a |
| 67 | 71 | |
| 68 | −all: $T | |
| 72 | +all: $T | |
| 69 | 73 | |
| 70 | −$T: $(OBJS) | |
| 74 | +$T: $(OBJS) | |
| 71 | 75 | $(AR) $@ $(OBJS) |
| 72 | 76 | $(RANLIB) $@ |
| 73 | 77 | |
| @@ -0,0 +1,5 @@ | ||
| 1 | +This is the Lua core. | |
| 2 | + | |
| 3 | +The standard Lua library are in lib/. | |
| 4 | +A sample interpreter is in lua/. | |
| 5 | +A standalone compiler is in luac/. | |
| @@ -1,15 +1,19 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lapi.c,v 1.110a 2000/10/30 12:50:09 roberto Exp $ | |
| 2 | +** $Id: lapi.c,v 1.235 2003/04/07 14:36:08 roberto Exp $ | |
| 3 | 3 | ** Lua API |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | +#include <assert.h> | |
| 8 | 9 | #include <string.h> |
| 9 | 10 | |
| 11 | +#define lapi_c | |
| 12 | + | |
| 10 | 13 | #include "lua.h" |
| 11 | 14 | |
| 12 | 15 | #include "lapi.h" |
| 16 | +#include "ldebug.h" | |
| 13 | 17 | #include "ldo.h" |
| 14 | 18 | #include "lfunc.h" |
| 15 | 19 | #include "lgc.h" |
| @@ -19,43 +23,128 @@ · 3 unmodified lines | ||
| 19 | 23 | #include "lstring.h" |
| 20 | 24 | #include "ltable.h" |
| 21 | 25 | #include "ltm.h" |
| 26 | +#include "lundump.h" | |
| 22 | 27 | #include "lvm.h" |
| 23 | 28 | |
| 24 | 29 | |
| 25 | −const char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" | |
| 26 | − "$Authors: " LUA_AUTHORS " $"; | |
| 30 | +const char lua_ident[] = | |
| 31 | + "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" | |
| 32 | + "$Authors: " LUA_AUTHORS " $\n" | |
| 33 | + "$URL: www.lua.org $\n"; | |
| 34 | + | |
| 27 | 35 | |
| 28 | 36 | |
| 37 | +#ifndef api_check | |
| 38 | +#define api_check(L, o) /*{ assert(o); }*/ | |
| 39 | +#endif | |
| 29 | 40 | |
| 30 | −#define Index(L,i) ((i) >= 0 ? (L->Cbase+((i)-1)) : (L->top+(i))) | |
| 41 | +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) | |
| 31 | 42 | |
| 32 | −#define api_incr_top(L) incr_top | |
| 43 | +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} | |
| 33 | 44 | |
| 34 | 45 | |
| 35 | 46 | |
| 36 | 47 | |
| 37 | −TObject *luaA_index (lua_State *L, int index) { | |
| 38 | − return Index(L, index); | |
| 48 | +static TObject *negindex (lua_State *L, int idx) { | |
| 49 | + if (idx > LUA_REGISTRYINDEX) { | |
| 50 | + api_check(L, idx != 0 && -idx <= L->top - L->base); | |
| 51 | + return L->top+idx; | |
| 52 | + } | |
| 53 | + else switch (idx) { /* pseudo-indices */ | |
| 54 | + case LUA_REGISTRYINDEX: return registry(L); | |
| 55 | + case LUA_GLOBALSINDEX: return gt(L); | |
| 56 | + default: { | |
| 57 | + TObject *func = (L->base - 1); | |
| 58 | + idx = LUA_GLOBALSINDEX - idx; | |
| 59 | + lua_assert(iscfunction(func)); | |
| 60 | + return (idx <= clvalue(func)->c.nupvalues) | |
| 61 | + ? &clvalue(func)->c.upvalue[idx-1] | |
| 62 | + : NULL; | |
| 63 | + } | |
| 64 | + } | |
| 65 | +} | |
| 66 | + | |
| 67 | + | |
| 68 | +static TObject *luaA_index (lua_State *L, int idx) { | |
| 69 | + if (idx > 0) { | |
| 70 | + api_check(L, idx <= L->top - L->base); | |
| 71 | + return L->base + idx - 1; | |
| 72 | + } | |
| 73 | + else { | |
| 74 | + TObject *o = negindex(L, idx); | |
| 75 | + api_check(L, o != NULL); | |
| 76 | + return o; | |
| 77 | + } | |
| 39 | 78 | } |
| 40 | 79 | |
| 41 | 80 | |
| 42 | −static TObject *luaA_indexAcceptable (lua_State *L, int index) { | |
| 43 | − if (index >= 0) { | |
| 44 | − TObject *o = L->Cbase+(index-1); | |
| 81 | +static TObject *luaA_indexAcceptable (lua_State *L, int idx) { | |
| 82 | + if (idx > 0) { | |
| 83 | + TObject *o = L->base+(idx-1); | |
| 84 | + api_check(L, idx <= L->stack_last - L->base); | |
| 45 | 85 | if (o >= L->top) return NULL; |
| 46 | 86 | else return o; |
| 47 | 87 | } |
| 48 | − else return L->top+index; | |
| 88 | + else | |
| 89 | + return negindex(L, idx); | |
| 49 | 90 | } |
| 50 | 91 | |
| 51 | 92 | |
| 52 | 93 | void luaA_pushobject (lua_State *L, const TObject *o) { |
| 53 | − *L->top = *o; | |
| 54 | − incr_top; | |
| 94 | + setobj2s(L->top, o); | |
| 95 | + incr_top(L); | |
| 96 | +} | |
| 97 | + | |
| 98 | + | |
| 99 | +LUA_API int lua_checkstack (lua_State *L, int size) { | |
| 100 | + int res; | |
| 101 | + lua_lock(L); | |
| 102 | + if ((L->top - L->base + size) > LUA_MAXCSTACK) | |
| 103 | + res = 0; /* stack overflow */ | |
| 104 | + else { | |
| 105 | + luaD_checkstack(L, size); | |
| 106 | + if (L->ci->top < L->top + size) | |
| 107 | + L->ci->top = L->top + size; | |
| 108 | + res = 1; | |
| 109 | + } | |
| 110 | + lua_unlock(L); | |
| 111 | + return res; | |
| 55 | 112 | } |
| 56 | 113 | |
| 57 | −LUA_API int lua_stackspace (lua_State *L) { | |
| 58 | − return (L->stack_last - L->top); | |
| 114 | + | |
| 115 | +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |
| 116 | + int i; | |
| 117 | + lua_lock(to); | |
| 118 | + api_checknelems(from, n); | |
| 119 | + from->top -= n; | |
| 120 | + for (i = 0; i < n; i++) { | |
| 121 | + setobj2s(to->top, from->top + i); | |
| 122 | + api_incr_top(to); | |
| 123 | + } | |
| 124 | + lua_unlock(to); | |
| 125 | +} | |
| 126 | + | |
| 127 | + | |
| 128 | +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { | |
| 129 | + lua_CFunction old; | |
| 130 | + lua_lock(L); | |
| 131 | + old = G(L)->panic; | |
| 132 | + G(L)->panic = panicf; | |
| 133 | + lua_unlock(L); | |
| 134 | + return old; | |
| 135 | +} | |
| 136 | + | |
| 137 | + | |
| 138 | +LUA_API lua_State *lua_newthread (lua_State *L) { | |
| 139 | + lua_State *L1; | |
| 140 | + lua_lock(L); | |
| 141 | + luaC_checkGC(L); | |
| 142 | + L1 = luaE_newthread(L); | |
| 143 | + setthvalue(L->top, L1); | |
| 144 | + api_incr_top(L); | |
| 145 | + lua_unlock(L); | |
| 146 | + lua_userstateopen(L1); | |
| 147 | + return L1; | |
| 59 | 148 | } |
| 60 | 149 | |
| 61 | 150 | |
| @@ -66,37 +155,61 @@ LUA_API int lua_stackspace (lua_State *L) { · 4 unmodified lines | ||
| 66 | 155 | |
| 67 | 156 | |
| 68 | 157 | LUA_API int lua_gettop (lua_State *L) { |
| 69 | − return (L->top - L->Cbase); | |
| 158 | + return (L->top - L->base); | |
| 70 | 159 | } |
| 71 | 160 | |
| 72 | 161 | |
| 73 | −LUA_API void lua_settop (lua_State *L, int index) { | |
| 74 | − if (index >= 0) | |
| 75 | − luaD_adjusttop(L, L->Cbase, index); | |
| 76 | − else | |
| 77 | − L->top = L->top+index+1; /* index is negative */ | |
| 162 | +LUA_API void lua_settop (lua_State *L, int idx) { | |
| 163 | + lua_lock(L); | |
| 164 | + if (idx >= 0) { | |
| 165 | + api_check(L, idx <= L->stack_last - L->base); | |
| 166 | + while (L->top < L->base + idx) | |
| 167 | + setnilvalue(L->top++); | |
| 168 | + L->top = L->base + idx; | |
| 169 | + } | |
| 170 | + else { | |
| 171 | + api_check(L, -(idx+1) <= (L->top - L->base)); | |
| 172 | + L->top += idx+1; /* `subtract' index (index is negative) */ | |
| 173 | + } | |
| 174 | + lua_unlock(L); | |
| 78 | 175 | } |
| 79 | 176 | |
| 80 | 177 | |
| 81 | −LUA_API void lua_remove (lua_State *L, int index) { | |
| 82 | − StkId p = luaA_index(L, index); | |
| 83 | − while (++p < L->top) *(p-1) = *p; | |
| 178 | +LUA_API void lua_remove (lua_State *L, int idx) { | |
| 179 | + StkId p; | |
| 180 | + lua_lock(L); | |
| 181 | + p = luaA_index(L, idx); | |
| 182 | + while (++p < L->top) setobjs2s(p-1, p); | |
| 84 | 183 | L->top--; |
| 184 | + lua_unlock(L); | |
| 85 | 185 | } |
| 86 | 186 | |
| 87 | 187 | |
| 88 | −LUA_API void lua_insert (lua_State *L, int index) { | |
| 89 | − StkId p = luaA_index(L, index); | |
| 188 | +LUA_API void lua_insert (lua_State *L, int idx) { | |
| 189 | + StkId p; | |
| 90 | 190 | StkId q; |
| 91 | − for (q = L->top; q>p; q--) | |
| 92 | − *q = *(q-1); | |
| 93 | − *p = *L->top; | |
| 191 | + lua_lock(L); | |
| 192 | + p = luaA_index(L, idx); | |
| 193 | + for (q = L->top; q>p; q--) setobjs2s(q, q-1); | |
| 194 | + setobjs2s(p, L->top); | |
| 195 | + lua_unlock(L); | |
| 94 | 196 | } |
| 95 | 197 | |
| 96 | 198 | |
| 97 | −LUA_API void lua_pushvalue (lua_State *L, int index) { | |
| 98 | − *L->top = *luaA_index(L, index); | |
| 199 | +LUA_API void lua_replace (lua_State *L, int idx) { | |
| 200 | + lua_lock(L); | |
| 201 | + api_checknelems(L, 1); | |
| 202 | + setobj(luaA_index(L, idx), L->top - 1); /* write barrier */ | |
| 203 | + L->top--; | |
| 204 | + lua_unlock(L); | |
| 205 | +} | |
| 206 | + | |
| 207 | + | |
| 208 | +LUA_API void lua_pushvalue (lua_State *L, int idx) { | |
| 209 | + lua_lock(L); | |
| 210 | + setobj2s(L->top, luaA_index(L, idx)); | |
| 99 | 211 | api_incr_top(L); |
| 212 | + lua_unlock(L); | |
| 100 | 213 | } |
| 101 | 214 | |
| 102 | 215 | |
| @@ -106,93 +219,167 @@ LUA_API void lua_pushvalue (lua_State *L, int index) { · 3 unmodified lines | ||
| 106 | 219 | */ |
| 107 | 220 | |
| 108 | 221 | |
| 109 | −LUA_API int lua_type (lua_State *L, int index) { | |
| 110 | − StkId o = luaA_indexAcceptable(L, index); | |
| 222 | +LUA_API int lua_type (lua_State *L, int idx) { | |
| 223 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 111 | 224 | return (o == NULL) ? LUA_TNONE : ttype(o); |
| 112 | 225 | } |
| 113 | 226 | |
| 227 | + | |
| 114 | 228 | LUA_API const char *lua_typename (lua_State *L, int t) { |
| 115 | 229 | UNUSED(L); |
| 116 | − return (t == LUA_TNONE) ? "no value" : luaO_typenames[t]; | |
| 230 | + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; | |
| 117 | 231 | } |
| 118 | 232 | |
| 119 | 233 | |
| 120 | −LUA_API int lua_iscfunction (lua_State *L, int index) { | |
| 121 | − StkId o = luaA_indexAcceptable(L, index); | |
| 234 | +LUA_API int lua_iscfunction (lua_State *L, int idx) { | |
| 235 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 122 | 236 | return (o == NULL) ? 0 : iscfunction(o); |
| 123 | 237 | } |
| 124 | 238 | |
| 125 | −LUA_API int lua_isnumber (lua_State *L, int index) { | |
| 126 | − TObject *o = luaA_indexAcceptable(L, index); | |
| 127 | − return (o == NULL) ? 0 : (tonumber(o) == 0); | |
| 239 | + | |
| 240 | +LUA_API int lua_isnumber (lua_State *L, int idx) { | |
| 241 | + TObject n; | |
| 242 | + const TObject *o = luaA_indexAcceptable(L, idx); | |
| 243 | + return (o != NULL && tonumber(o, &n)); | |
| 128 | 244 | } |
| 129 | 245 | |
| 130 | −LUA_API int lua_isstring (lua_State *L, int index) { | |
| 131 | − int t = lua_type(L, index); | |
| 246 | + | |
| 247 | +LUA_API int lua_isstring (lua_State *L, int idx) { | |
| 248 | + int t = lua_type(L, idx); | |
| 132 | 249 | return (t == LUA_TSTRING || t == LUA_TNUMBER); |
| 133 | 250 | } |
| 134 | 251 | |
| 135 | 252 | |
| 136 | −LUA_API int lua_tag (lua_State *L, int index) { | |
| 137 | − StkId o = luaA_indexAcceptable(L, index); | |
| 138 | − return (o == NULL) ? LUA_NOTAG : luaT_tag(o); | |
| 253 | +LUA_API int lua_isuserdata (lua_State *L, int idx) { | |
| 254 | + const TObject *o = luaA_indexAcceptable(L, idx); | |
| 255 | + return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o))); | |
| 139 | 256 | } |
| 140 | 257 | |
| 141 | −LUA_API int lua_equal (lua_State *L, int index1, int index2) { | |
| 258 | + | |
| 259 | +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { | |
| 142 | 260 | StkId o1 = luaA_indexAcceptable(L, index1); |
| 143 | 261 | StkId o2 = luaA_indexAcceptable(L, index2); |
| 144 | − if (o1 == NULL || o2 == NULL) return 0; /* index out-of-range */ | |
| 145 | − else return luaO_equalObj(o1, o2); | |
| 262 | + return (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ | |
| 263 | + : luaO_rawequalObj(o1, o2); | |
| 264 | +} | |
| 265 | + | |
| 266 | + | |
| 267 | +LUA_API int lua_equal (lua_State *L, int index1, int index2) { | |
| 268 | + StkId o1, o2; | |
| 269 | + int i; | |
| 270 | + lua_lock(L); /* may call tag method */ | |
| 271 | + o1 = luaA_indexAcceptable(L, index1); | |
| 272 | + o2 = luaA_indexAcceptable(L, index2); | |
| 273 | + i = (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ | |
| 274 | + : equalobj(L, o1, o2); | |
| 275 | + lua_unlock(L); | |
| 276 | + return i; | |
| 146 | 277 | } |
| 147 | 278 | |
| 279 | + | |
| 148 | 280 | LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { |
| 149 | − StkId o1 = luaA_indexAcceptable(L, index1); | |
| 150 | − StkId o2 = luaA_indexAcceptable(L, index2); | |
| 151 | − if (o1 == NULL || o2 == NULL) return 0; /* index out-of-range */ | |
| 152 | − else return luaV_lessthan(L, o1, o2, L->top); | |
| 281 | + StkId o1, o2; | |
| 282 | + int i; | |
| 283 | + lua_lock(L); /* may call tag method */ | |
| 284 | + o1 = luaA_indexAcceptable(L, index1); | |
| 285 | + o2 = luaA_indexAcceptable(L, index2); | |
| 286 | + i = (o1 == NULL || o2 == NULL) ? 0 /* index out-of-range */ | |
| 287 | + : luaV_lessthan(L, o1, o2); | |
| 288 | + lua_unlock(L); | |
| 289 | + return i; | |
| 153 | 290 | } |
| 154 | 291 | |
| 155 | 292 | |
| 156 | 293 | |
| 157 | −LUA_API double lua_tonumber (lua_State *L, int index) { | |
| 158 | − StkId o = luaA_indexAcceptable(L, index); | |
| 159 | − return (o == NULL || tonumber(o)) ? 0 : nvalue(o); | |
| 294 | +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { | |
| 295 | + TObject n; | |
| 296 | + const TObject *o = luaA_indexAcceptable(L, idx); | |
| 297 | + if (o != NULL && tonumber(o, &n)) | |
| 298 | + return nvalue(o); | |
| 299 | + else | |
| 300 | + return 0; | |
| 160 | 301 | } |
| 161 | 302 | |
| 162 | −LUA_API const char *lua_tostring (lua_State *L, int index) { | |
| 163 | − StkId o = luaA_indexAcceptable(L, index); | |
| 164 | − return (o == NULL || tostring(L, o)) ? NULL : svalue(o); | |
| 303 | + | |
| 304 | +LUA_API int lua_toboolean (lua_State *L, int idx) { | |
| 305 | + const TObject *o = luaA_indexAcceptable(L, idx); | |
| 306 | + return (o != NULL) && !l_isfalse(o); | |
| 165 | 307 | } |
| 166 | 308 | |
| 167 | −LUA_API size_t lua_strlen (lua_State *L, int index) { | |
| 168 | − StkId o = luaA_indexAcceptable(L, index); | |
| 169 | − return (o == NULL || tostring(L, o)) ? 0 : tsvalue(o)->len; | |
| 309 | + | |
| 310 | +LUA_API const char *lua_tostring (lua_State *L, int idx) { | |
| 311 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 312 | + if (o == NULL) | |
| 313 | + return NULL; | |
| 314 | + else if (ttisstring(o)) | |
| 315 | + return svalue(o); | |
| 316 | + else { | |
| 317 | + const char *s; | |
| 318 | + lua_lock(L); /* `luaV_tostring' may create a new string */ | |
| 319 | + s = (luaV_tostring(L, o) ? svalue(o) : NULL); | |
| 320 | + luaC_checkGC(L); | |
| 321 | + lua_unlock(L); | |
| 322 | + return s; | |
| 323 | + } | |
| 170 | 324 | } |
| 171 | 325 | |
| 172 | −LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) { | |
| 173 | − StkId o = luaA_indexAcceptable(L, index); | |
| 174 | − return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->f.c; | |
| 326 | + | |
| 327 | +LUA_API size_t lua_strlen (lua_State *L, int idx) { | |
| 328 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 329 | + if (o == NULL) | |
| 330 | + return 0; | |
| 331 | + else if (ttisstring(o)) | |
| 332 | + return tsvalue(o)->tsv.len; | |
| 333 | + else { | |
| 334 | + size_t l; | |
| 335 | + lua_lock(L); /* `luaV_tostring' may create a new string */ | |
| 336 | + l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0); | |
| 337 | + lua_unlock(L); | |
| 338 | + return l; | |
| 339 | + } | |
| 175 | 340 | } |
| 176 | 341 | |
| 177 | −LUA_API void *lua_touserdata (lua_State *L, int index) { | |
| 178 | − StkId o = luaA_indexAcceptable(L, index); | |
| 179 | − return (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : | |
| 180 | − tsvalue(o)->u.d.value; | |
| 342 | + | |
| 343 | +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { | |
| 344 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 345 | + return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f; | |
| 181 | 346 | } |
| 182 | 347 | |
| 183 | −LUA_API const void *lua_topointer (lua_State *L, int index) { | |
| 184 | − StkId o = luaA_indexAcceptable(L, index); | |
| 348 | + | |
| 349 | +LUA_API void *lua_touserdata (lua_State *L, int idx) { | |
| 350 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 185 | 351 | if (o == NULL) return NULL; |
| 186 | 352 | switch (ttype(o)) { |
| 187 | − case LUA_TTABLE: | |
| 188 | − return hvalue(o); | |
| 189 | − case LUA_TFUNCTION: | |
| 190 | − return clvalue(o); | |
| 353 | + case LUA_TUSERDATA: return (uvalue(o) + 1); | |
| 354 | + case LUA_TLIGHTUSERDATA: return pvalue(o); | |
| 191 | 355 | default: return NULL; |
| 192 | 356 | } |
| 193 | 357 | } |
| 194 | 358 | |
| 195 | 359 | |
| 360 | +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { | |
| 361 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 362 | + return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o); | |
| 363 | +} | |
| 364 | + | |
| 365 | + | |
| 366 | +LUA_API const void *lua_topointer (lua_State *L, int idx) { | |
| 367 | + StkId o = luaA_indexAcceptable(L, idx); | |
| 368 | + if (o == NULL) return NULL; | |
| 369 | + else { | |
| 370 | + switch (ttype(o)) { | |
| 371 | + case LUA_TTABLE: return hvalue(o); | |
| 372 | + case LUA_TFUNCTION: return clvalue(o); | |
| 373 | + case LUA_TTHREAD: return thvalue(o); | |
| 374 | + case LUA_TUSERDATA: | |
| 375 | + case LUA_TLIGHTUSERDATA: | |
| 376 | + return lua_touserdata(L, idx); | |
| 377 | + default: return NULL; | |
| 378 | + } | |
| 379 | + } | |
| 380 | +} | |
| 381 | + | |
| 382 | + | |
| 196 | 383 | |
| 197 | 384 | /* |
| 198 | 385 | ** push functions (C -> stack) |
| @@ -200,22 +387,27 @@ LUA_API const void *lua_topointer (lua_State *L, int index) { · 1 unmodified line | ||
| 200 | 387 | |
| 201 | 388 | |
| 202 | 389 | LUA_API void lua_pushnil (lua_State *L) { |
| 203 | − ttype(L->top) = LUA_TNIL; | |
| 390 | + lua_lock(L); | |
| 391 | + setnilvalue(L->top); | |
| 204 | 392 | api_incr_top(L); |
| 393 | + lua_unlock(L); | |
| 205 | 394 | } |
| 206 | 395 | |
| 207 | 396 | |
| 208 | −LUA_API void lua_pushnumber (lua_State *L, double n) { | |
| 209 | − nvalue(L->top) = n; | |
| 210 | − ttype(L->top) = LUA_TNUMBER; | |
| 397 | +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { | |
| 398 | + lua_lock(L); | |
| 399 | + setnvalue(L->top, n); | |
| 211 | 400 | api_incr_top(L); |
| 401 | + lua_unlock(L); | |
| 212 | 402 | } |
| 213 | 403 | |
| 214 | 404 | |
| 215 | 405 | LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { |
| 216 | − tsvalue(L->top) = luaS_newlstr(L, s, len); | |
| 217 | − ttype(L->top) = LUA_TSTRING; | |
| 406 | + lua_lock(L); | |
| 407 | + luaC_checkGC(L); | |
| 408 | + setsvalue2s(L->top, luaS_newlstr(L, s, len)); | |
| 218 | 409 | api_incr_top(L); |
| 410 | + lua_unlock(L); | |
| 219 | 411 | } |
| 220 | 412 | |
| 221 | 413 | |
| @@ -227,159 +419,338 @@ LUA_API void lua_pushstring (lua_State *L, const char *s) { · 5 unmodified lines | ||
| 227 | 419 | } |
| 228 | 420 | |
| 229 | 421 | |
| 230 | −LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |
| 231 | − luaV_Cclosure(L, fn, n); | |
| 422 | +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, | |
| 423 | + va_list argp) { | |
| 424 | + const char *ret; | |
| 425 | + lua_lock(L); | |
| 426 | + luaC_checkGC(L); | |
| 427 | + ret = luaO_pushvfstring(L, fmt, argp); | |
| 428 | + lua_unlock(L); | |
| 429 | + return ret; | |
| 232 | 430 | } |
| 233 | 431 | |
| 234 | 432 | |
| 235 | −LUA_API void lua_pushusertag (lua_State *L, void *u, int tag) { | |
| 236 | − /* ORDER LUA_T */ | |
| 237 | − if (!(tag == LUA_ANYTAG || tag == LUA_TUSERDATA || validtag(tag))) | |
| 238 | − luaO_verror(L, "invalid tag for a userdata (%d)", tag); | |
| 239 | − tsvalue(L->top) = luaS_createudata(L, u, tag); | |
| 240 | − ttype(L->top) = LUA_TUSERDATA; | |
| 241 | − api_incr_top(L); | |
| 433 | +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { | |
| 434 | + const char *ret; | |
| 435 | + va_list argp; | |
| 436 | + lua_lock(L); | |
| 437 | + luaC_checkGC(L); | |
| 438 | + va_start(argp, fmt); | |
| 439 | + ret = luaO_pushvfstring(L, fmt, argp); | |
| 440 | + va_end(argp); | |
| 441 | + lua_unlock(L); | |
| 442 | + return ret; | |
| 242 | 443 | } |
| 243 | 444 | |
| 244 | 445 | |
| 245 | − | |
| 246 | −/* | |
| 247 | −** get functions (Lua -> stack) | |
| 248 | −*/ | |
| 446 | +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |
| 447 | + Closure *cl; | |
| 448 | + lua_lock(L); | |
| 449 | + luaC_checkGC(L); | |
| 450 | + api_checknelems(L, n); | |
| 451 | + cl = luaF_newCclosure(L, n); | |
| 452 | + cl->c.f = fn; | |
| 453 | + L->top -= n; | |
| 454 | + while (n--) | |
| 455 | + setobj2n(&cl->c.upvalue[n], L->top+n); | |
| 456 | + setclvalue(L->top, cl); | |
| 457 | + api_incr_top(L); | |
| 458 | + lua_unlock(L); | |
| 459 | +} | |
| 249 | 460 | |
| 250 | 461 | |
| 251 | −LUA_API void lua_getglobal (lua_State *L, const char *name) { | |
| 252 | − StkId top = L->top; | |
| 253 | − *top = *luaV_getglobal(L, luaS_new(L, name)); | |
| 254 | − L->top = top; | |
| 462 | +LUA_API void lua_pushboolean (lua_State *L, int b) { | |
| 463 | + lua_lock(L); | |
| 464 | + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ | |
| 255 | 465 | api_incr_top(L); |
| 466 | + lua_unlock(L); | |
| 256 | 467 | } |
| 257 | 468 | |
| 258 | 469 | |
| 259 | −LUA_API void lua_gettable (lua_State *L, int index) { | |
| 260 | − StkId t = Index(L, index); | |
| 261 | − StkId top = L->top; | |
| 262 | − *(top-1) = *luaV_gettable(L, t); | |
| 263 | − L->top = top; /* tag method may change top */ | |
| 470 | +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { | |
| 471 | + lua_lock(L); | |
| 472 | + setpvalue(L->top, p); | |
| 473 | + api_incr_top(L); | |
| 474 | + lua_unlock(L); | |
| 264 | 475 | } |
| 265 | 476 | |
| 266 | 477 | |
| 267 | −LUA_API void lua_rawget (lua_State *L, int index) { | |
| 268 | − StkId t = Index(L, index); | |
| 269 | − LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); | |
| 270 | − *(L->top - 1) = *luaH_get(L, hvalue(t), L->top - 1); | |
| 271 | −} | |
| 272 | 478 | |
| 479 | +/* | |
| 480 | +** get functions (Lua -> stack) | |
| 481 | +*/ | |
| 273 | 482 | |
| 274 | −LUA_API void lua_rawgeti (lua_State *L, int index, int n) { | |
| 275 | − StkId o = Index(L, index); | |
| 276 | − LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); | |
| 277 | − *L->top = *luaH_getnum(hvalue(o), n); | |
| 278 | − api_incr_top(L); | |
| 483 | + | |
| 484 | +LUA_API void lua_gettable (lua_State *L, int idx) { | |
| 485 | + StkId t; | |
| 486 | + lua_lock(L); | |
| 487 | + t = luaA_index(L, idx); | |
| 488 | + setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0)); | |
| 489 | + lua_unlock(L); | |
| 279 | 490 | } |
| 280 | 491 | |
| 281 | 492 | |
| 282 | −LUA_API void lua_getglobals (lua_State *L) { | |
| 283 | − hvalue(L->top) = L->gt; | |
| 284 | − ttype(L->top) = LUA_TTABLE; | |
| 285 | − api_incr_top(L); | |
| 493 | +LUA_API void lua_rawget (lua_State *L, int idx) { | |
| 494 | + StkId t; | |
| 495 | + lua_lock(L); | |
| 496 | + t = luaA_index(L, idx); | |
| 497 | + api_check(L, ttistable(t)); | |
| 498 | + setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1)); | |
| 499 | + lua_unlock(L); | |
| 286 | 500 | } |
| 287 | 501 | |
| 288 | 502 | |
| 289 | −LUA_API int lua_getref (lua_State *L, int ref) { | |
| 290 | − if (ref == LUA_REFNIL) | |
| 291 | − ttype(L->top) = LUA_TNIL; | |
| 292 | − else if (0 <= ref && ref < L->refSize && | |
| 293 | − (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD)) | |
| 294 | − *L->top = L->refArray[ref].o; | |
| 295 | − else | |
| 296 | − return 0; | |
| 503 | +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { | |
| 504 | + StkId o; | |
| 505 | + lua_lock(L); | |
| 506 | + o = luaA_index(L, idx); | |
| 507 | + api_check(L, ttistable(o)); | |
| 508 | + setobj2s(L->top, luaH_getnum(hvalue(o), n)); | |
| 297 | 509 | api_incr_top(L); |
| 298 | − return 1; | |
| 510 | + lua_unlock(L); | |
| 299 | 511 | } |
| 300 | 512 | |
| 301 | 513 | |
| 302 | 514 | LUA_API void lua_newtable (lua_State *L) { |
| 303 | − hvalue(L->top) = luaH_new(L, 0); | |
| 304 | − ttype(L->top) = LUA_TTABLE; | |
| 515 | + lua_lock(L); | |
| 516 | + luaC_checkGC(L); | |
| 517 | + sethvalue(L->top, luaH_new(L, 0, 0)); | |
| 305 | 518 | api_incr_top(L); |
| 519 | + lua_unlock(L); | |
| 520 | +} | |
| 521 | + | |
| 522 | + | |
| 523 | +LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |
| 524 | + const TObject *obj; | |
| 525 | + Table *mt = NULL; | |
| 526 | + int res; | |
| 527 | + lua_lock(L); | |
| 528 | + obj = luaA_indexAcceptable(L, objindex); | |
| 529 | + if (obj != NULL) { | |
| 530 | + switch (ttype(obj)) { | |
| 531 | + case LUA_TTABLE: | |
| 532 | + mt = hvalue(obj)->metatable; | |
| 533 | + break; | |
| 534 | + case LUA_TUSERDATA: | |
| 535 | + mt = uvalue(obj)->uv.metatable; | |
| 536 | + break; | |
| 537 | + } | |
| 538 | + } | |
| 539 | + if (mt == NULL || mt == hvalue(defaultmeta(L))) | |
| 540 | + res = 0; | |
| 541 | + else { | |
| 542 | + sethvalue(L->top, mt); | |
| 543 | + api_incr_top(L); | |
| 544 | + res = 1; | |
| 545 | + } | |
| 546 | + lua_unlock(L); | |
| 547 | + return res; | |
| 306 | 548 | } |
| 307 | 549 | |
| 308 | 550 | |
| 551 | +LUA_API void lua_getfenv (lua_State *L, int idx) { | |
| 552 | + StkId o; | |
| 553 | + lua_lock(L); | |
| 554 | + o = luaA_index(L, idx); | |
| 555 | + setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); | |
| 556 | + api_incr_top(L); | |
| 557 | + lua_unlock(L); | |
| 558 | +} | |
| 559 | + | |
| 309 | 560 | |
| 310 | 561 | /* |
| 311 | 562 | ** set functions (stack -> Lua) |
| 312 | 563 | */ |
| 313 | 564 | |
| 314 | 565 | |
| 315 | −LUA_API void lua_setglobal (lua_State *L, const char *name) { | |
| 316 | − StkId top = L->top; | |
| 317 | − luaV_setglobal(L, luaS_new(L, name)); | |
| 318 | − L->top = top-1; /* remove element from the top */ | |
| 566 | +LUA_API void lua_settable (lua_State *L, int idx) { | |
| 567 | + StkId t; | |
| 568 | + lua_lock(L); | |
| 569 | + api_checknelems(L, 2); | |
| 570 | + t = luaA_index(L, idx); | |
| 571 | + luaV_settable(L, t, L->top - 2, L->top - 1); | |
| 572 | + L->top -= 2; /* pop index and value */ | |
| 573 | + lua_unlock(L); | |
| 319 | 574 | } |
| 320 | 575 | |
| 321 | 576 | |
| 322 | −LUA_API void lua_settable (lua_State *L, int index) { | |
| 323 | − StkId t = Index(L, index); | |
| 324 | − StkId top = L->top; | |
| 325 | − luaV_settable(L, t, top-2); | |
| 326 | − L->top = top-2; /* pop index and value */ | |
| 577 | +LUA_API void lua_rawset (lua_State *L, int idx) { | |
| 578 | + StkId t; | |
| 579 | + lua_lock(L); | |
| 580 | + api_checknelems(L, 2); | |
| 581 | + t = luaA_index(L, idx); | |
| 582 | + api_check(L, ttistable(t)); | |
| 583 | + setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */ | |
| 584 | + L->top -= 2; | |
| 585 | + lua_unlock(L); | |
| 327 | 586 | } |
| 328 | 587 | |
| 329 | 588 | |
| 330 | −LUA_API void lua_rawset (lua_State *L, int index) { | |
| 331 | − StkId t = Index(L, index); | |
| 332 | − LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); | |
| 333 | − *luaH_set(L, hvalue(t), L->top-2) = *(L->top-1); | |
| 334 | − L->top -= 2; | |
| 589 | +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { | |
| 590 | + StkId o; | |
| 591 | + lua_lock(L); | |
| 592 | + api_checknelems(L, 1); | |
| 593 | + o = luaA_index(L, idx); | |
| 594 | + api_check(L, ttistable(o)); | |
| 595 | + setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */ | |
| 596 | + L->top--; | |
| 597 | + lua_unlock(L); | |
| 335 | 598 | } |
| 336 | 599 | |
| 337 | 600 | |
| 338 | −LUA_API void lua_rawseti (lua_State *L, int index, int n) { | |
| 339 | − StkId o = Index(L, index); | |
| 340 | − LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); | |
| 341 | − *luaH_setint(L, hvalue(o), n) = *(L->top-1); | |
| 601 | +LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |
| 602 | + TObject *obj, *mt; | |
| 603 | + int res = 1; | |
| 604 | + lua_lock(L); | |
| 605 | + api_checknelems(L, 1); | |
| 606 | + obj = luaA_index(L, objindex); | |
| 607 | + mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); | |
| 608 | + api_check(L, ttistable(mt)); | |
| 609 | + switch (ttype(obj)) { | |
| 610 | + case LUA_TTABLE: { | |
| 611 | + hvalue(obj)->metatable = hvalue(mt); /* write barrier */ | |
| 612 | + break; | |
| 613 | + } | |
| 614 | + case LUA_TUSERDATA: { | |
| 615 | + uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */ | |
| 616 | + break; | |
| 617 | + } | |
| 618 | + default: { | |
| 619 | + res = 0; /* cannot set */ | |
| 620 | + break; | |
| 621 | + } | |
| 622 | + } | |
| 342 | 623 | L->top--; |
| 624 | + lua_unlock(L); | |
| 625 | + return res; | |
| 343 | 626 | } |
| 344 | 627 | |
| 345 | 628 | |
| 346 | −LUA_API void lua_setglobals (lua_State *L) { | |
| 347 | − StkId newtable = --L->top; | |
| 348 | − LUA_ASSERT(ttype(newtable) == LUA_TTABLE, "table expected"); | |
| 349 | − L->gt = hvalue(newtable); | |
| 629 | +LUA_API int lua_setfenv (lua_State *L, int idx) { | |
| 630 | + StkId o; | |
| 631 | + int res = 0; | |
| 632 | + lua_lock(L); | |
| 633 | + api_checknelems(L, 1); | |
| 634 | + o = luaA_index(L, idx); | |
| 635 | + L->top--; | |
| 636 | + api_check(L, ttistable(L->top)); | |
| 637 | + if (isLfunction(o)) { | |
| 638 | + res = 1; | |
| 639 | + clvalue(o)->l.g = *(L->top); | |
| 640 | + } | |
| 641 | + lua_unlock(L); | |
| 642 | + return res; | |
| 350 | 643 | } |
| 351 | 644 | |
| 352 | 645 | |
| 353 | −LUA_API int lua_ref (lua_State *L, int lock) { | |
| 354 | − int ref; | |
| 355 | − if (ttype(L->top-1) == LUA_TNIL) | |
| 356 | − ref = LUA_REFNIL; | |
| 357 | − else { | |
| 358 | − if (L->refFree != NONEXT) { /* is there a free place? */ | |
| 359 | − ref = L->refFree; | |
| 360 | − L->refFree = L->refArray[ref].st; | |
| 361 | − } | |
| 362 | − else { /* no more free places */ | |
| 363 | − luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref, | |
| 364 | − "reference table overflow", MAX_INT); | |
| 365 | − L->nblocks += sizeof(struct Ref); | |
| 366 | − ref = L->refSize++; | |
| 367 | − } | |
| 368 | − L->refArray[ref].o = *(L->top-1); | |
| 369 | − L->refArray[ref].st = lock ? LOCK : HOLD; | |
| 370 | − } | |
| 371 | − L->top--; | |
| 372 | − return ref; | |
| 646 | +/* | |
| 647 | +** `load' and `call' functions (run Lua code) | |
| 648 | +*/ | |
| 649 | + | |
| 650 | +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { | |
| 651 | + StkId func; | |
| 652 | + lua_lock(L); | |
| 653 | + api_checknelems(L, nargs+1); | |
| 654 | + func = L->top - (nargs+1); | |
| 655 | + luaD_call(L, func, nresults); | |
| 656 | + lua_unlock(L); | |
| 373 | 657 | } |
| 374 | 658 | |
| 375 | 659 | |
| 660 | + | |
| 376 | 661 | /* |
| 377 | −** "do" functions (run Lua code) | |
| 378 | −** (most of them are in ldo.c) | |
| 662 | +** Execute a protected call. | |
| 379 | 663 | */ |
| 664 | +struct CallS { /* data to `f_call' */ | |
| 665 | + StkId func; | |
| 666 | + int nresults; | |
| 667 | +}; | |
| 668 | + | |
| 380 | 669 | |
| 381 | −LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) { | |
| 382 | − luaD_call(L, L->top-(nargs+1), nresults); | |
| 670 | +static void f_call (lua_State *L, void *ud) { | |
| 671 | + struct CallS *c = cast(struct CallS *, ud); | |
| 672 | + luaD_call(L, c->func, c->nresults); | |
| 673 | +} | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { | |
| 678 | + struct CallS c; | |
| 679 | + int status; | |
| 680 | + ptrdiff_t func; | |
| 681 | + lua_lock(L); | |
| 682 | + func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc)); | |
| 683 | + c.func = L->top - (nargs+1); /* function to be called */ | |
| 684 | + c.nresults = nresults; | |
| 685 | + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); | |
| 686 | + lua_unlock(L); | |
| 687 | + return status; | |
| 688 | +} | |
| 689 | + | |
| 690 | + | |
| 691 | +/* | |
| 692 | +** Execute a protected C call. | |
| 693 | +*/ | |
| 694 | +struct CCallS { /* data to `f_Ccall' */ | |
| 695 | + lua_CFunction func; | |
| 696 | + void *ud; | |
| 697 | +}; | |
| 698 | + | |
| 699 | + | |
| 700 | +static void f_Ccall (lua_State *L, void *ud) { | |
| 701 | + struct CCallS *c = cast(struct CCallS *, ud); | |
| 702 | + Closure *cl; | |
| 703 | + cl = luaF_newCclosure(L, 0); | |
| 704 | + cl->c.f = c->func; | |
| 705 | + setclvalue(L->top, cl); /* push function */ | |
| 706 | + incr_top(L); | |
| 707 | + setpvalue(L->top, c->ud); /* push only argument */ | |
| 708 | + incr_top(L); | |
| 709 | + luaD_call(L, L->top - 2, 0); | |
| 710 | +} | |
| 711 | + | |
| 712 | + | |
| 713 | +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { | |
| 714 | + struct CCallS c; | |
| 715 | + int status; | |
| 716 | + lua_lock(L); | |
| 717 | + c.func = func; | |
| 718 | + c.ud = ud; | |
| 719 | + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); | |
| 720 | + lua_unlock(L); | |
| 721 | + return status; | |
| 722 | +} | |
| 723 | + | |
| 724 | + | |
| 725 | +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data, | |
| 726 | + const char *chunkname) { | |
| 727 | + ZIO z; | |
| 728 | + int status; | |
| 729 | + int c; | |
| 730 | + lua_lock(L); | |
| 731 | + if (!chunkname) chunkname = "?"; | |
| 732 | + luaZ_init(&z, reader, data, chunkname); | |
| 733 | + c = luaZ_lookahead(&z); | |
| 734 | + status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0])); | |
| 735 | + lua_unlock(L); | |
| 736 | + return status; | |
| 737 | +} | |
| 738 | + | |
| 739 | + | |
| 740 | +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) { | |
| 741 | + int status; | |
| 742 | + TObject *o; | |
| 743 | + lua_lock(L); | |
| 744 | + api_checknelems(L, 1); | |
| 745 | + o = L->top - 1; | |
| 746 | + if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) { | |
| 747 | + luaU_dump(L, clvalue(o)->l.p, writer, data); | |
| 748 | + status = 1; | |
| 749 | + } | |
| 750 | + else | |
| 751 | + status = 0; | |
| 752 | + lua_unlock(L); | |
| 753 | + return status; | |
| 383 | 754 | } |
| 384 | 755 | |
| 385 | 756 | |
| @@ -388,23 +759,34 @@ LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) { · 2 unmodified lines | ||
| 388 | 759 | */ |
| 389 | 760 | |
| 390 | 761 | /* GC values are expressed in Kbytes: #bytes/2^10 */ |
| 391 | −#define GCscale(x) ((int)((x)>>10)) | |
| 392 | −#define GCunscale(x) ((unsigned long)(x)<<10) | |
| 762 | +#define GCscalel(x) ((x)>>10) | |
| 763 | +#define GCscale(x) (cast(int, GCscalel(x))) | |
| 764 | +#define GCunscale(x) (cast(lu_mem, x)<<10) | |
| 393 | 765 | |
| 394 | 766 | LUA_API int lua_getgcthreshold (lua_State *L) { |
| 395 | − return GCscale(L->GCthreshold); | |
| 767 | + int threshold; | |
| 768 | + lua_lock(L); | |
| 769 | + threshold = GCscale(G(L)->GCthreshold); | |
| 770 | + lua_unlock(L); | |
| 771 | + return threshold; | |
| 396 | 772 | } |
| 397 | 773 | |
| 398 | 774 | LUA_API int lua_getgccount (lua_State *L) { |
| 399 | − return GCscale(L->nblocks); | |
| 775 | + int count; | |
| 776 | + lua_lock(L); | |
| 777 | + count = GCscale(G(L)->nblocks); | |
| 778 | + lua_unlock(L); | |
| 779 | + return count; | |
| 400 | 780 | } |
| 401 | 781 | |
| 402 | 782 | LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { |
| 403 | − if (newthreshold > GCscale(ULONG_MAX)) | |
| 404 | − L->GCthreshold = ULONG_MAX; | |
| 783 | + lua_lock(L); | |
| 784 | + if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM)) | |
| 785 | + G(L)->GCthreshold = MAX_LUMEM; | |
| 405 | 786 | else |
| 406 | − L->GCthreshold = GCunscale(newthreshold); | |
| 787 | + G(L)->GCthreshold = GCunscale(newthreshold); | |
| 407 | 788 | luaC_checkGC(L); |
| 789 | + lua_unlock(L); | |
| 408 | 790 | } |
| 409 | 791 | |
| 410 | 792 | |
| @@ -412,83 +794,129 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { · 1 unmodified line | ||
| 412 | 794 | ** miscellaneous functions |
| 413 | 795 | */ |
| 414 | 796 | |
| 415 | −LUA_API void lua_settag (lua_State *L, int tag) { | |
| 416 | − luaT_realtag(L, tag); | |
| 417 | − switch (ttype(L->top-1)) { | |
| 418 | − case LUA_TTABLE: | |
| 419 | − hvalue(L->top-1)->htag = tag; | |
| 420 | − break; | |
| 421 | − case LUA_TUSERDATA: | |
| 422 | − tsvalue(L->top-1)->u.d.tag = tag; | |
| 423 | − break; | |
| 424 | − default: | |
| 425 | − luaO_verror(L, "cannot change the tag of a %.20s", | |
| 426 | − luaO_typename(L->top-1)); | |
| 427 | − } | |
| 797 | + | |
| 798 | +LUA_API const char *lua_version (void) { | |
| 799 | + return LUA_VERSION; | |
| 428 | 800 | } |
| 429 | 801 | |
| 430 | 802 | |
| 431 | −LUA_API void lua_unref (lua_State *L, int ref) { | |
| 432 | − if (ref >= 0) { | |
| 433 | − LUA_ASSERT(ref < L->refSize && L->refArray[ref].st < 0, "invalid ref"); | |
| 434 | − L->refArray[ref].st = L->refFree; | |
| 435 | − L->refFree = ref; | |
| 436 | − } | |
| 803 | +LUA_API int lua_error (lua_State *L) { | |
| 804 | + lua_lock(L); | |
| 805 | + api_checknelems(L, 1); | |
| 806 | + luaG_errormsg(L); | |
| 807 | + lua_unlock(L); | |
| 808 | + return 0; /* to avoid warnings */ | |
| 437 | 809 | } |
| 438 | 810 | |
| 439 | 811 | |
| 440 | −LUA_API int lua_next (lua_State *L, int index) { | |
| 441 | − StkId t = luaA_index(L, index); | |
| 442 | − Node *n; | |
| 443 | − LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); | |
| 444 | − n = luaH_next(L, hvalue(t), luaA_index(L, -1)); | |
| 445 | − if (n) { | |
| 446 | − *(L->top-1) = *key(n); | |
| 447 | − *L->top = *val(n); | |
| 812 | +LUA_API int lua_next (lua_State *L, int idx) { | |
| 813 | + StkId t; | |
| 814 | + int more; | |
| 815 | + lua_lock(L); | |
| 816 | + t = luaA_index(L, idx); | |
| 817 | + api_check(L, ttistable(t)); | |
| 818 | + more = luaH_next(L, hvalue(t), L->top - 1); | |
| 819 | + if (more) { | |
| 448 | 820 | api_incr_top(L); |
| 449 | − return 1; | |
| 450 | 821 | } |
| 451 | − else { /* no more elements */ | |
| 822 | + else /* no more elements */ | |
| 452 | 823 | L->top -= 1; /* remove key */ |
| 453 | − return 0; | |
| 824 | + lua_unlock(L); | |
| 825 | + return more; | |
| 826 | +} | |
| 827 | + | |
| 828 | + | |
| 829 | +LUA_API void lua_concat (lua_State *L, int n) { | |
| 830 | + lua_lock(L); | |
| 831 | + luaC_checkGC(L); | |
| 832 | + api_checknelems(L, n); | |
| 833 | + if (n >= 2) { | |
| 834 | + luaV_concat(L, n, L->top - L->base - 1); | |
| 835 | + L->top -= (n-1); | |
| 836 | + } | |
| 837 | + else if (n == 0) { /* push empty string */ | |
| 838 | + setsvalue2s(L->top, luaS_newlstr(L, NULL, 0)); | |
| 839 | + api_incr_top(L); | |
| 840 | + } | |
| 841 | + /* else n == 1; nothing to do */ | |
| 842 | + lua_unlock(L); | |
| 843 | +} | |
| 844 | + | |
| 845 | + | |
| 846 | +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |
| 847 | + Udata *u; | |
| 848 | + lua_lock(L); | |
| 849 | + luaC_checkGC(L); | |
| 850 | + u = luaS_newudata(L, size); | |
| 851 | + setuvalue(L->top, u); | |
| 852 | + api_incr_top(L); | |
| 853 | + lua_unlock(L); | |
| 854 | + return u + 1; | |
| 855 | +} | |
| 856 | + | |
| 857 | + | |
| 858 | +LUA_API int lua_pushupvalues (lua_State *L) { | |
| 859 | + Closure *func; | |
| 860 | + int n, i; | |
| 861 | + lua_lock(L); | |
| 862 | + api_check(L, iscfunction(L->base - 1)); | |
| 863 | + func = clvalue(L->base - 1); | |
| 864 | + n = func->c.nupvalues; | |
| 865 | + luaD_checkstack(L, n + LUA_MINSTACK); | |
| 866 | + for (i=0; i<n; i++) { | |
| 867 | + setobj2s(L->top, &func->c.upvalue[i]); | |
| 868 | + L->top++; | |
| 454 | 869 | } |
| 870 | + lua_unlock(L); | |
| 871 | + return n; | |
| 455 | 872 | } |
| 456 | 873 | |
| 457 | 874 | |
| 458 | −LUA_API int lua_getn (lua_State *L, int index) { | |
| 459 | − Hash *h = hvalue(luaA_index(L, index)); | |
| 460 | − const TObject *value = luaH_getstr(h, luaS_new(L, "n")); /* value = h.n */ | |
| 461 | − if (ttype(value) == LUA_TNUMBER) | |
| 462 | − return (int)nvalue(value); | |
| 875 | +static const char *aux_upvalue (lua_State *L, int funcindex, int n, | |
| 876 | + TObject **val) { | |
| 877 | + Closure *f; | |
| 878 | + StkId fi = luaA_index(L, funcindex); | |
| 879 | + if (!ttisfunction(fi)) return NULL; | |
| 880 | + f = clvalue(fi); | |
| 881 | + if (f->c.isC) { | |
| 882 | + if (n > f->c.nupvalues) return NULL; | |
| 883 | + *val = &f->c.upvalue[n-1]; | |
| 884 | + return ""; | |
| 885 | + } | |
| 463 | 886 | else { |
| 464 | − Number max = 0; | |
| 465 | − int i = h->size; | |
| 466 | − Node *n = h->node; | |
| 467 | − while (i--) { | |
| 468 | − if (ttype(key(n)) == LUA_TNUMBER && | |
| 469 | − ttype(val(n)) != LUA_TNIL && | |
| 470 | − nvalue(key(n)) > max) | |
| 471 | − max = nvalue(key(n)); | |
| 472 | − n++; | |
| 473 | − } | |
| 474 | − return (int)max; | |
| 887 | + Proto *p = f->l.p; | |
| 888 | + if (n > p->sizeupvalues) return NULL; | |
| 889 | + *val = f->l.upvals[n-1]->v; | |
| 890 | + return getstr(p->upvalues[n-1]); | |
| 475 | 891 | } |
| 476 | 892 | } |
| 477 | 893 | |
| 478 | 894 | |
| 479 | −LUA_API void lua_concat (lua_State *L, int n) { | |
| 480 | − StkId top = L->top; | |
| 481 | − luaV_strconc(L, n, top); | |
| 482 | − L->top = top-(n-1); | |
| 483 | − luaC_checkGC(L); | |
| 895 | +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |
| 896 | + const char *name; | |
| 897 | + TObject *val; | |
| 898 | + lua_lock(L); | |
| 899 | + name = aux_upvalue(L, funcindex, n, &val); | |
| 900 | + if (name) { | |
| 901 | + setobj2s(L->top, val); | |
| 902 | + api_incr_top(L); | |
| 903 | + } | |
| 904 | + lua_unlock(L); | |
| 905 | + return name; | |
| 484 | 906 | } |
| 485 | 907 | |
| 486 | 908 | |
| 487 | −LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |
| 488 | − TString *ts = luaS_newudata(L, (size==0) ? 1 : size, NULL); | |
| 489 | − tsvalue(L->top) = ts; | |
| 490 | − ttype(L->top) = LUA_TUSERDATA; | |
| 491 | − api_incr_top(L); | |
| 492 | − return ts->u.d.value; | |
| 909 | +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | |
| 910 | + const char *name; | |
| 911 | + TObject *val; | |
| 912 | + lua_lock(L); | |
| 913 | + api_checknelems(L, 1); | |
| 914 | + name = aux_upvalue(L, funcindex, n, &val); | |
| 915 | + if (name) { | |
| 916 | + L->top--; | |
| 917 | + setobj(val, L->top); /* write barrier */ | |
| 918 | + } | |
| 919 | + lua_unlock(L); | |
| 920 | + return name; | |
| 493 | 921 | } |
| 494 | 922 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lapi.h,v 1.20 2000/08/31 14:08:27 roberto Exp $ | |
| 2 | +** $Id: lapi.h,v 1.21 2002/03/04 21:29:41 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions from Lua API |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -11,7 +11,6 @@ · 5 unmodified lines | ||
| 11 | 11 | #include "lobject.h" |
| 12 | 12 | |
| 13 | 13 | |
| 14 | −TObject *luaA_index (lua_State *L, int index); | |
| 15 | 14 | void luaA_pushobject (lua_State *L, const TObject *o); |
| 16 | 15 | |
| 17 | 16 | #endif |
| @@ -1,66 +1,84 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.c,v 1.51 2000/09/29 12:42:13 roberto Exp $ | |
| 2 | +** $Id: lcode.c,v 1.117 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | −#include "stdlib.h" | |
| 8 | +#include <stdlib.h> | |
| 9 | + | |
| 10 | +#define lcode_c | |
| 9 | 11 | |
| 10 | 12 | #include "lua.h" |
| 11 | 13 | |
| 12 | 14 | #include "lcode.h" |
| 15 | +#include "ldebug.h" | |
| 13 | 16 | #include "ldo.h" |
| 14 | 17 | #include "llex.h" |
| 15 | 18 | #include "lmem.h" |
| 16 | 19 | #include "lobject.h" |
| 17 | 20 | #include "lopcodes.h" |
| 18 | 21 | #include "lparser.h" |
| 22 | +#include "ltable.h" | |
| 19 | 23 | |
| 20 | 24 | |
| 21 | −void luaK_error (LexState *ls, const char *msg) { | |
| 22 | − luaX_error(ls, msg, ls->t.token); | |
| 23 | −} | |
| 25 | +#define hasjumps(e) ((e)->t != (e)->f) | |
| 24 | 26 | |
| 25 | 27 | |
| 26 | −/* | |
| 27 | −** Returns the the previous instruction, for optimizations. | |
| 28 | −** If there is a jump target between this and the current instruction, | |
| 29 | −** returns a dummy instruction to avoid wrong optimizations. | |
| 30 | −*/ | |
| 31 | −static Instruction previous_instruction (FuncState *fs) { | |
| 32 | − if (fs->pc > fs->lasttarget) /* no jumps to current position? */ | |
| 33 | − return fs->f->code[fs->pc-1]; /* returns previous instruction */ | |
| 34 | − else | |
| 35 | − return CREATE_0(OP_END); /* no optimizations after an `END' */ | |
| 28 | +void luaK_nil (FuncState *fs, int from, int n) { | |
| 29 | + Instruction *previous; | |
| 30 | + if (fs->pc > fs->lasttarget && /* no jumps to current position? */ | |
| 31 | + GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { | |
| 32 | + int pfrom = GETARG_A(*previous); | |
| 33 | + int pto = GETARG_B(*previous); | |
| 34 | + if (pfrom <= from && from <= pto+1) { /* can connect both? */ | |
| 35 | + if (from+n-1 > pto) | |
| 36 | + SETARG_B(*previous, from+n-1); | |
| 37 | + return; | |
| 38 | + } | |
| 39 | + } | |
| 40 | + luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | |
| 36 | 41 | } |
| 37 | 42 | |
| 38 | 43 | |
| 39 | 44 | int luaK_jump (FuncState *fs) { |
| 40 | − int j = luaK_code1(fs, OP_JMP, NO_JUMP); | |
| 41 | − if (j == fs->lasttarget) { /* possible jumps to this jump? */ | |
| 42 | − luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | |
| 43 | − fs->jlt = NO_JUMP; | |
| 44 | − } | |
| 45 | + int jpc = fs->jpc; /* save list of jumps to here */ | |
| 46 | + int j; | |
| 47 | + fs->jpc = NO_JUMP; | |
| 48 | + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); | |
| 49 | + luaK_concat(fs, &j, jpc); /* keep them on hold */ | |
| 45 | 50 | return j; |
| 46 | 51 | } |
| 47 | 52 | |
| 48 | 53 | |
| 54 | +static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { | |
| 55 | + luaK_codeABC(fs, op, A, B, C); | |
| 56 | + return luaK_jump(fs); | |
| 57 | +} | |
| 58 | + | |
| 59 | + | |
| 49 | 60 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
| 50 | 61 | Instruction *jmp = &fs->f->code[pc]; |
| 51 | − if (dest == NO_JUMP) | |
| 52 | − SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ | |
| 53 | − else { /* jump is relative to position following jump instruction */ | |
| 54 | − int offset = dest-(pc+1); | |
| 55 | − if (abs(offset) > MAXARG_S) | |
| 56 | − luaK_error(fs->ls, "control structure too long"); | |
| 57 | − SETARG_S(*jmp, offset); | |
| 58 | − } | |
| 62 | + int offset = dest-(pc+1); | |
| 63 | + lua_assert(dest != NO_JUMP); | |
| 64 | + if (abs(offset) > MAXARG_sBx) | |
| 65 | + luaX_syntaxerror(fs->ls, "control structure too long"); | |
| 66 | + SETARG_sBx(*jmp, offset); | |
| 67 | +} | |
| 68 | + | |
| 69 | + | |
| 70 | +/* | |
| 71 | +** returns current `pc' and marks it as a jump target (to avoid wrong | |
| 72 | +** optimizations with consecutive instructions not in the same basic block). | |
| 73 | +*/ | |
| 74 | +int luaK_getlabel (FuncState *fs) { | |
| 75 | + fs->lasttarget = fs->pc; | |
| 76 | + return fs->pc; | |
| 59 | 77 | } |
| 60 | 78 | |
| 61 | 79 | |
| 62 | 80 | static int luaK_getjump (FuncState *fs, int pc) { |
| 63 | − int offset = GETARG_S(fs->f->code[pc]); | |
| 81 | + int offset = GETARG_sBx(fs->f->code[pc]); | |
| 64 | 82 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
| 65 | 83 | return NO_JUMP; /* end of list */ |
| 66 | 84 | else |
| @@ -68,634 +86,629 @@ static int luaK_getjump (FuncState *fs, int pc) { · 1 unmodified line | ||
| 68 | 86 | } |
| 69 | 87 | |
| 70 | 88 | |
| 89 | +static Instruction *getjumpcontrol (FuncState *fs, int pc) { | |
| 90 | + Instruction *pi = &fs->f->code[pc]; | |
| 91 | + if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT)) | |
| 92 | + return pi-1; | |
| 93 | + else | |
| 94 | + return pi; | |
| 95 | +} | |
| 96 | + | |
| 97 | + | |
| 71 | 98 | /* |
| 72 | −** returns current `pc' and marks it as a jump target (to avoid wrong | |
| 73 | −** optimizations with consecutive instructions not in the same basic block). | |
| 74 | −** discharge list of jumps to last target. | |
| 99 | +** check whether list has any jump that do not produce a value | |
| 100 | +** (or produce an inverted value) | |
| 75 | 101 | */ |
| 76 | −int luaK_getlabel (FuncState *fs) { | |
| 77 | − if (fs->pc != fs->lasttarget) { | |
| 78 | − int lasttarget = fs->lasttarget; | |
| 79 | − fs->lasttarget = fs->pc; | |
| 80 | − luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ | |
| 81 | − fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ | |
| 102 | +static int need_value (FuncState *fs, int list, int cond) { | |
| 103 | + for (; list != NO_JUMP; list = luaK_getjump(fs, list)) { | |
| 104 | + Instruction i = *getjumpcontrol(fs, list); | |
| 105 | + if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; | |
| 82 | 106 | } |
| 83 | − return fs->pc; | |
| 107 | + return 0; /* not found */ | |
| 84 | 108 | } |
| 85 | 109 | |
| 86 | 110 | |
| 87 | −void luaK_deltastack (FuncState *fs, int delta) { | |
| 88 | − fs->stacklevel += delta; | |
| 89 | − if (fs->stacklevel > fs->f->maxstacksize) { | |
| 90 | − if (fs->stacklevel > MAXSTACK) | |
| 91 | − luaK_error(fs->ls, "function or expression too complex"); | |
| 92 | − fs->f->maxstacksize = fs->stacklevel; | |
| 93 | − } | |
| 111 | +static void patchtestreg (Instruction *i, int reg) { | |
| 112 | + if (reg == NO_REG) reg = GETARG_B(*i); | |
| 113 | + SETARG_A(*i, reg); | |
| 94 | 114 | } |
| 95 | 115 | |
| 96 | 116 | |
| 97 | −void luaK_kstr (LexState *ls, int c) { | |
| 98 | − luaK_code1(ls->fs, OP_PUSHSTRING, c); | |
| 117 | +static void luaK_patchlistaux (FuncState *fs, int list, | |
| 118 | + int ttarget, int treg, int ftarget, int freg, int dtarget) { | |
| 119 | + while (list != NO_JUMP) { | |
| 120 | + int next = luaK_getjump(fs, list); | |
| 121 | + Instruction *i = getjumpcontrol(fs, list); | |
| 122 | + if (GET_OPCODE(*i) != OP_TEST) { | |
| 123 | + lua_assert(dtarget != NO_JUMP); | |
| 124 | + luaK_fixjump(fs, list, dtarget); /* jump to default target */ | |
| 125 | + } | |
| 126 | + else { | |
| 127 | + if (GETARG_C(*i)) { | |
| 128 | + lua_assert(ttarget != NO_JUMP); | |
| 129 | + patchtestreg(i, treg); | |
| 130 | + luaK_fixjump(fs, list, ttarget); | |
| 131 | + } | |
| 132 | + else { | |
| 133 | + lua_assert(ftarget != NO_JUMP); | |
| 134 | + patchtestreg(i, freg); | |
| 135 | + luaK_fixjump(fs, list, ftarget); | |
| 136 | + } | |
| 137 | + } | |
| 138 | + list = next; | |
| 139 | + } | |
| 99 | 140 | } |
| 100 | 141 | |
| 101 | 142 | |
| 102 | −static int number_constant (FuncState *fs, Number r) { | |
| 103 | − /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ | |
| 104 | − Proto *f = fs->f; | |
| 105 | − int c = f->nknum; | |
| 106 | − int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; | |
| 107 | − while (--c >= lim) | |
| 108 | − if (f->knum[c] == r) return c; | |
| 109 | − /* not found; create a new entry */ | |
| 110 | − luaM_growvector(fs->L, f->knum, f->nknum, 1, Number, | |
| 111 | − "constant table overflow", MAXARG_U); | |
| 112 | − c = f->nknum++; | |
| 113 | − f->knum[c] = r; | |
| 114 | − return c; | |
| 115 | −} | |
| 116 | − | |
| 117 | − | |
| 118 | −void luaK_number (FuncState *fs, Number f) { | |
| 119 | − if (f <= (Number)MAXARG_S && (Number)(int)f == f) | |
| 120 | − luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ | |
| 121 | − else | |
| 122 | − luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); | |
| 143 | +static void luaK_dischargejpc (FuncState *fs) { | |
| 144 | + luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); | |
| 145 | + fs->jpc = NO_JUMP; | |
| 123 | 146 | } |
| 124 | 147 | |
| 125 | 148 | |
| 126 | −void luaK_adjuststack (FuncState *fs, int n) { | |
| 127 | − if (n > 0) | |
| 128 | − luaK_code1(fs, OP_POP, n); | |
| 129 | − else | |
| 130 | − luaK_code1(fs, OP_PUSHNIL, -n); | |
| 149 | +void luaK_patchlist (FuncState *fs, int list, int target) { | |
| 150 | + if (target == fs->pc) | |
| 151 | + luaK_patchtohere(fs, list); | |
| 152 | + else { | |
| 153 | + lua_assert(target < fs->pc); | |
| 154 | + luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); | |
| 155 | + } | |
| 131 | 156 | } |
| 132 | 157 | |
| 133 | 158 | |
| 134 | −int luaK_lastisopen (FuncState *fs) { | |
| 135 | − /* check whether last instruction is an open function call */ | |
| 136 | − Instruction i = previous_instruction(fs); | |
| 137 | − if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) | |
| 138 | − return 1; | |
| 139 | − else return 0; | |
| 159 | +void luaK_patchtohere (FuncState *fs, int list) { | |
| 160 | + luaK_getlabel(fs); | |
| 161 | + luaK_concat(fs, &fs->jpc, list); | |
| 140 | 162 | } |
| 141 | 163 | |
| 142 | 164 | |
| 143 | −void luaK_setcallreturns (FuncState *fs, int nresults) { | |
| 144 | − if (luaK_lastisopen(fs)) { /* expression is an open function call? */ | |
| 145 | − SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ | |
| 146 | − luaK_deltastack(fs, nresults); /* push results */ | |
| 165 | +void luaK_concat (FuncState *fs, int *l1, int l2) { | |
| 166 | + if (l2 == NO_JUMP) return; | |
| 167 | + else if (*l1 == NO_JUMP) | |
| 168 | + *l1 = l2; | |
| 169 | + else { | |
| 170 | + int list = *l1; | |
| 171 | + int next; | |
| 172 | + while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | |
| 173 | + list = next; | |
| 174 | + luaK_fixjump(fs, list, l2); | |
| 147 | 175 | } |
| 148 | 176 | } |
| 149 | 177 | |
| 150 | 178 | |
| 151 | −static int discharge (FuncState *fs, expdesc *var) { | |
| 152 | − switch (var->k) { | |
| 153 | − case VLOCAL: | |
| 154 | − luaK_code1(fs, OP_GETLOCAL, var->u.index); | |
| 155 | − break; | |
| 156 | − case VGLOBAL: | |
| 157 | − luaK_code1(fs, OP_GETGLOBAL, var->u.index); | |
| 158 | − break; | |
| 159 | − case VINDEXED: | |
| 160 | − luaK_code0(fs, OP_GETTABLE); | |
| 161 | − break; | |
| 162 | − case VEXP: | |
| 163 | − return 0; /* nothing to do */ | |
| 179 | +void luaK_checkstack (FuncState *fs, int n) { | |
| 180 | + int newstack = fs->freereg + n; | |
| 181 | + if (newstack > fs->f->maxstacksize) { | |
| 182 | + if (newstack >= MAXSTACK) | |
| 183 | + luaX_syntaxerror(fs->ls, "function or expression too complex"); | |
| 184 | + fs->f->maxstacksize = cast(lu_byte, newstack); | |
| 164 | 185 | } |
| 165 | − var->k = VEXP; | |
| 166 | − var->u.l.t = var->u.l.f = NO_JUMP; | |
| 167 | − return 1; | |
| 168 | 186 | } |
| 169 | 187 | |
| 170 | 188 | |
| 171 | −static void discharge1 (FuncState *fs, expdesc *var) { | |
| 172 | − discharge(fs, var); | |
| 173 | − /* if it has jumps then it is already discharged */ | |
| 174 | − if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | |
| 175 | − luaK_setcallreturns(fs, 1); /* call must return 1 value */ | |
| 189 | +void luaK_reserveregs (FuncState *fs, int n) { | |
| 190 | + luaK_checkstack(fs, n); | |
| 191 | + fs->freereg += n; | |
| 176 | 192 | } |
| 177 | 193 | |
| 178 | 194 | |
| 179 | −void luaK_storevar (LexState *ls, const expdesc *var) { | |
| 180 | − FuncState *fs = ls->fs; | |
| 181 | − switch (var->k) { | |
| 182 | − case VLOCAL: | |
| 183 | − luaK_code1(fs, OP_SETLOCAL, var->u.index); | |
| 184 | − break; | |
| 185 | − case VGLOBAL: | |
| 186 | − luaK_code1(fs, OP_SETGLOBAL, var->u.index); | |
| 187 | − break; | |
| 188 | − case VINDEXED: /* table is at top-3; pop 3 elements after operation */ | |
| 189 | − luaK_code2(fs, OP_SETTABLE, 3, 3); | |
| 190 | − break; | |
| 191 | − default: | |
| 192 | − LUA_INTERNALERROR("invalid var kind to store"); | |
| 195 | +static void freereg (FuncState *fs, int reg) { | |
| 196 | + if (reg >= fs->nactvar && reg < MAXSTACK) { | |
| 197 | + fs->freereg--; | |
| 198 | + lua_assert(reg == fs->freereg); | |
| 193 | 199 | } |
| 194 | 200 | } |
| 195 | 201 | |
| 196 | 202 | |
| 197 | −static OpCode invertjump (OpCode op) { | |
| 198 | − switch (op) { | |
| 199 | − case OP_JMPNE: return OP_JMPEQ; | |
| 200 | − case OP_JMPEQ: return OP_JMPNE; | |
| 201 | − case OP_JMPLT: return OP_JMPGE; | |
| 202 | − case OP_JMPLE: return OP_JMPGT; | |
| 203 | − case OP_JMPGT: return OP_JMPLE; | |
| 204 | − case OP_JMPGE: return OP_JMPLT; | |
| 205 | − case OP_JMPT: case OP_JMPONT: return OP_JMPF; | |
| 206 | − case OP_JMPF: case OP_JMPONF: return OP_JMPT; | |
| 207 | − default: | |
| 208 | − LUA_INTERNALERROR("invalid jump instruction"); | |
| 209 | − return OP_END; /* to avoid warnings */ | |
| 210 | − } | |
| 203 | +static void freeexp (FuncState *fs, expdesc *e) { | |
| 204 | + if (e->k == VNONRELOC) | |
| 205 | + freereg(fs, e->info); | |
| 211 | 206 | } |
| 212 | 207 | |
| 213 | 208 | |
| 214 | −static void luaK_patchlistaux (FuncState *fs, int list, int target, | |
| 215 | − OpCode special, int special_target) { | |
| 216 | − Instruction *code = fs->f->code; | |
| 217 | − while (list != NO_JUMP) { | |
| 218 | − int next = luaK_getjump(fs, list); | |
| 219 | − Instruction *i = &code[list]; | |
| 220 | − OpCode op = GET_OPCODE(*i); | |
| 221 | − if (op == special) /* this `op' already has a value */ | |
| 222 | − luaK_fixjump(fs, list, special_target); | |
| 223 | − else { | |
| 224 | − luaK_fixjump(fs, list, target); /* do the patch */ | |
| 225 | − if (op == OP_JMPONT) /* remove eventual values */ | |
| 226 | − SET_OPCODE(*i, OP_JMPT); | |
| 227 | − else if (op == OP_JMPONF) | |
| 228 | − SET_OPCODE(*i, OP_JMPF); | |
| 229 | − } | |
| 230 | − list = next; | |
| 209 | +static int addk (FuncState *fs, TObject *k, TObject *v) { | |
| 210 | + const TObject *idx = luaH_get(fs->h, k); | |
| 211 | + if (ttisnumber(idx)) { | |
| 212 | + lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v)); | |
| 213 | + return cast(int, nvalue(idx)); | |
| 214 | + } | |
| 215 | + else { /* constant not found; create a new entry */ | |
| 216 | + Proto *f = fs->f; | |
| 217 | + luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, | |
| 218 | + MAXARG_Bx, "constant table overflow"); | |
| 219 | + setobj2n(&f->k[fs->nk], v); | |
| 220 | + setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk)); | |
| 221 | + return fs->nk++; | |
| 231 | 222 | } |
| 232 | 223 | } |
| 233 | 224 | |
| 234 | 225 | |
| 235 | −void luaK_patchlist (FuncState *fs, int list, int target) { | |
| 236 | − if (target == fs->lasttarget) /* same target that list `jlt'? */ | |
| 237 | − luaK_concat(fs, &fs->jlt, list); /* delay fixing */ | |
| 238 | − else | |
| 239 | − luaK_patchlistaux(fs, list, target, OP_END, 0); | |
| 226 | +int luaK_stringK (FuncState *fs, TString *s) { | |
| 227 | + TObject o; | |
| 228 | + setsvalue(&o, s); | |
| 229 | + return addk(fs, &o, &o); | |
| 240 | 230 | } |
| 241 | 231 | |
| 242 | 232 | |
| 243 | −static int need_value (FuncState *fs, int list, OpCode hasvalue) { | |
| 244 | − /* check whether list has a jump without a value */ | |
| 245 | − for (; list != NO_JUMP; list = luaK_getjump(fs, list)) | |
| 246 | − if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; | |
| 247 | − return 0; /* not found */ | |
| 233 | +int luaK_numberK (FuncState *fs, lua_Number r) { | |
| 234 | + TObject o; | |
| 235 | + setnvalue(&o, r); | |
| 236 | + return addk(fs, &o, &o); | |
| 248 | 237 | } |
| 249 | 238 | |
| 250 | 239 | |
| 251 | −void luaK_concat (FuncState *fs, int *l1, int l2) { | |
| 252 | − if (*l1 == NO_JUMP) | |
| 253 | − *l1 = l2; | |
| 254 | − else { | |
| 255 | − int list = *l1; | |
| 256 | − for (;;) { /* traverse `l1' */ | |
| 257 | − int next = luaK_getjump(fs, list); | |
| 258 | − if (next == NO_JUMP) { /* end of list? */ | |
| 259 | − luaK_fixjump(fs, list, l2); | |
| 260 | − return; | |
| 261 | − } | |
| 262 | − list = next; | |
| 263 | − } | |
| 264 | − } | |
| 240 | +static int nil_constant (FuncState *fs) { | |
| 241 | + TObject k, v; | |
| 242 | + setnilvalue(&v); | |
| 243 | + sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */ | |
| 244 | + return addk(fs, &k, &v); | |
| 265 | 245 | } |
| 266 | 246 | |
| 267 | 247 | |
| 268 | −static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | |
| 269 | − int prevpos; /* position of last instruction */ | |
| 270 | − Instruction *previous; | |
| 271 | − int *golist, *exitlist; | |
| 272 | − if (!invert) { | |
| 273 | − golist = &v->u.l.f; /* go if false */ | |
| 274 | − exitlist = &v->u.l.t; /* exit if true */ | |
| 275 | − } | |
| 276 | − else { | |
| 277 | − golist = &v->u.l.t; /* go if true */ | |
| 278 | − exitlist = &v->u.l.f; /* exit if false */ | |
| 279 | − } | |
| 280 | − discharge1(fs, v); | |
| 281 | − prevpos = fs->pc-1; | |
| 282 | − previous = &fs->f->code[prevpos]; | |
| 283 | − LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here"); | |
| 284 | − if (!ISJUMP(GET_OPCODE(*previous))) | |
| 285 | − prevpos = luaK_code1(fs, jump, NO_JUMP); | |
| 286 | − else { /* last instruction is already a jump */ | |
| 287 | − if (invert) | |
| 288 | − SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | |
| 248 | +void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { | |
| 249 | + if (e->k == VCALL) { /* expression is an open function call? */ | |
| 250 | + SETARG_C(getcode(fs, e), nresults+1); | |
| 251 | + if (nresults == 1) { /* `regular' expression? */ | |
| 252 | + e->k = VNONRELOC; | |
| 253 | + e->info = GETARG_A(getcode(fs, e)); | |
| 254 | + } | |
| 289 | 255 | } |
| 290 | − luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ | |
| 291 | − luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | |
| 292 | − *golist = NO_JUMP; | |
| 293 | 256 | } |
| 294 | 257 | |
| 295 | 258 | |
| 296 | −void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { | |
| 297 | − luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); | |
| 259 | +void luaK_dischargevars (FuncState *fs, expdesc *e) { | |
| 260 | + switch (e->k) { | |
| 261 | + case VLOCAL: { | |
| 262 | + e->k = VNONRELOC; | |
| 263 | + break; | |
| 264 | + } | |
| 265 | + case VUPVAL: { | |
| 266 | + e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); | |
| 267 | + e->k = VRELOCABLE; | |
| 268 | + break; | |
| 269 | + } | |
| 270 | + case VGLOBAL: { | |
| 271 | + e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); | |
| 272 | + e->k = VRELOCABLE; | |
| 273 | + break; | |
| 274 | + } | |
| 275 | + case VINDEXED: { | |
| 276 | + freereg(fs, e->aux); | |
| 277 | + freereg(fs, e->info); | |
| 278 | + e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); | |
| 279 | + e->k = VRELOCABLE; | |
| 280 | + break; | |
| 281 | + } | |
| 282 | + case VCALL: { | |
| 283 | + luaK_setcallreturns(fs, e, 1); | |
| 284 | + break; | |
| 285 | + } | |
| 286 | + default: break; /* there is one value available (somewhere) */ | |
| 287 | + } | |
| 298 | 288 | } |
| 299 | 289 | |
| 300 | 290 | |
| 301 | −static void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) { | |
| 302 | − luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT); | |
| 291 | +static int code_label (FuncState *fs, int A, int b, int jump) { | |
| 292 | + luaK_getlabel(fs); /* those instructions may be jump targets */ | |
| 293 | + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); | |
| 303 | 294 | } |
| 304 | 295 | |
| 305 | 296 | |
| 306 | −static int code_label (FuncState *fs, OpCode op, int arg) { | |
| 307 | − luaK_getlabel(fs); /* those instructions may be jump targets */ | |
| 308 | − return luaK_code1(fs, op, arg); | |
| 309 | −} | |
| 310 | − | |
| 311 | − | |
| 312 | −void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | |
| 313 | − FuncState *fs = ls->fs; | |
| 314 | − if (!discharge(fs, v)) { /* `v' is an expression? */ | |
| 315 | − OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); | |
| 316 | − if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { | |
| 317 | − /* expression has no jumps */ | |
| 318 | − if (onlyone) | |
| 319 | − luaK_setcallreturns(fs, 1); /* call must return 1 value */ | |
| 320 | − } | |
| 321 | − else { /* expression has jumps */ | |
| 322 | − int final; /* position after whole expression */ | |
| 323 | − int j = NO_JUMP; /* eventual jump over values */ | |
| 324 | − int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | |
| 325 | − int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | |
| 326 | − if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) | |
| 327 | − || need_value(fs, v->u.l.t, OP_JMPONT)) { | |
| 328 | − /* expression needs values */ | |
| 329 | − if (ISJUMP(previous)) | |
| 330 | − luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ | |
| 331 | − else { | |
| 332 | − j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ | |
| 333 | − /* correct stack for compiler and symbolic execution */ | |
| 334 | − luaK_adjuststack(fs, 1); | |
| 335 | − } | |
| 336 | − p_nil = code_label(fs, OP_PUSHNILJMP, 0); | |
| 337 | − p_1 = code_label(fs, OP_PUSHINT, 1); | |
| 338 | − luaK_patchlist(fs, j, luaK_getlabel(fs)); | |
| 339 | − } | |
| 340 | − final = luaK_getlabel(fs); | |
| 341 | − luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | |
| 342 | − luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | |
| 343 | − v->u.l.f = v->u.l.t = NO_JUMP; | |
| 297 | +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |
| 298 | + luaK_dischargevars(fs, e); | |
| 299 | + switch (e->k) { | |
| 300 | + case VNIL: { | |
| 301 | + luaK_nil(fs, reg, 1); | |
| 302 | + break; | |
| 303 | + } | |
| 304 | + case VFALSE: case VTRUE: { | |
| 305 | + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); | |
| 306 | + break; | |
| 307 | + } | |
| 308 | + case VK: { | |
| 309 | + luaK_codeABx(fs, OP_LOADK, reg, e->info); | |
| 310 | + break; | |
| 311 | + } | |
| 312 | + case VRELOCABLE: { | |
| 313 | + Instruction *pc = &getcode(fs, e); | |
| 314 | + SETARG_A(*pc, reg); | |
| 315 | + break; | |
| 316 | + } | |
| 317 | + case VNONRELOC: { | |
| 318 | + if (reg != e->info) | |
| 319 | + luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); | |
| 320 | + break; | |
| 321 | + } | |
| 322 | + default: { | |
| 323 | + lua_assert(e->k == VVOID || e->k == VJMP); | |
| 324 | + return; /* nothing to do... */ | |
| 344 | 325 | } |
| 345 | 326 | } |
| 327 | + e->info = reg; | |
| 328 | + e->k = VNONRELOC; | |
| 346 | 329 | } |
| 347 | 330 | |
| 348 | 331 | |
| 349 | −void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { | |
| 350 | − FuncState *fs = ls->fs; | |
| 351 | − if (op == OPR_MINUS) { | |
| 352 | − luaK_tostack(ls, v, 1); | |
| 353 | − luaK_code0(fs, OP_MINUS); | |
| 332 | +static void discharge2anyreg (FuncState *fs, expdesc *e) { | |
| 333 | + if (e->k != VNONRELOC) { | |
| 334 | + luaK_reserveregs(fs, 1); | |
| 335 | + discharge2reg(fs, e, fs->freereg-1); | |
| 354 | 336 | } |
| 355 | − else { /* op == NOT */ | |
| 356 | − Instruction *previous; | |
| 357 | − discharge1(fs, v); | |
| 358 | − previous = &fs->f->code[fs->pc-1]; | |
| 359 | − if (ISJUMP(GET_OPCODE(*previous))) | |
| 360 | − SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | |
| 361 | − else | |
| 362 | − luaK_code0(fs, OP_NOT); | |
| 363 | − /* interchange true and false lists */ | |
| 364 | − { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | |
| 337 | +} | |
| 338 | + | |
| 339 | + | |
| 340 | +static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { | |
| 341 | + discharge2reg(fs, e, reg); | |
| 342 | + if (e->k == VJMP) | |
| 343 | + luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */ | |
| 344 | + if (hasjumps(e)) { | |
| 345 | + int final; /* position after whole expression */ | |
| 346 | + int p_f = NO_JUMP; /* position of an eventual LOAD false */ | |
| 347 | + int p_t = NO_JUMP; /* position of an eventual LOAD true */ | |
| 348 | + if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { | |
| 349 | + int fj = NO_JUMP; /* first jump (over LOAD ops.) */ | |
| 350 | + if (e->k != VJMP) | |
| 351 | + fj = luaK_jump(fs); | |
| 352 | + p_f = code_label(fs, reg, 0, 1); | |
| 353 | + p_t = code_label(fs, reg, 1, 0); | |
| 354 | + luaK_patchtohere(fs, fj); | |
| 355 | + } | |
| 356 | + final = luaK_getlabel(fs); | |
| 357 | + luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); | |
| 358 | + luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); | |
| 365 | 359 | } |
| 360 | + e->f = e->t = NO_JUMP; | |
| 361 | + e->info = reg; | |
| 362 | + e->k = VNONRELOC; | |
| 366 | 363 | } |
| 367 | 364 | |
| 368 | 365 | |
| 369 | −void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { | |
| 370 | − FuncState *fs = ls->fs; | |
| 371 | − switch (op) { | |
| 372 | − case OPR_AND: | |
| 373 | − luaK_goiftrue(fs, v, 1); | |
| 374 | − break; | |
| 375 | − case OPR_OR: | |
| 376 | − luaK_goiffalse(fs, v, 1); | |
| 377 | − break; | |
| 378 | − default: | |
| 379 | − luaK_tostack(ls, v, 1); /* all other binary operators need a value */ | |
| 366 | +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | |
| 367 | + luaK_dischargevars(fs, e); | |
| 368 | + freeexp(fs, e); | |
| 369 | + luaK_reserveregs(fs, 1); | |
| 370 | + luaK_exp2reg(fs, e, fs->freereg - 1); | |
| 371 | +} | |
| 372 | + | |
| 373 | + | |
| 374 | +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |
| 375 | + luaK_dischargevars(fs, e); | |
| 376 | + if (e->k == VNONRELOC) { | |
| 377 | + if (!hasjumps(e)) return e->info; /* exp is already in a register */ | |
| 378 | + if (e->info >= fs->nactvar) { /* reg. is not a local? */ | |
| 379 | + luaK_exp2reg(fs, e, e->info); /* put value on it */ | |
| 380 | + return e->info; | |
| 381 | + } | |
| 380 | 382 | } |
| 383 | + luaK_exp2nextreg(fs, e); /* default */ | |
| 384 | + return e->info; | |
| 381 | 385 | } |
| 382 | 386 | |
| 383 | 387 | |
| 388 | +void luaK_exp2val (FuncState *fs, expdesc *e) { | |
| 389 | + if (hasjumps(e)) | |
| 390 | + luaK_exp2anyreg(fs, e); | |
| 391 | + else | |
| 392 | + luaK_dischargevars(fs, e); | |
| 393 | +} | |
| 384 | 394 | |
| 385 | −static const struct { | |
| 386 | − OpCode opcode; /* opcode for each binary operator */ | |
| 387 | − int arg; /* default argument for the opcode */ | |
| 388 | −} codes[] = { /* ORDER OPR */ | |
| 389 | − {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, | |
| 390 | − {OP_POW, 0}, {OP_CONCAT, 2}, | |
| 391 | − {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, | |
| 392 | − {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, | |
| 393 | − {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} | |
| 394 | −}; | |
| 395 | 395 | |
| 396 | +int luaK_exp2RK (FuncState *fs, expdesc *e) { | |
| 397 | + luaK_exp2val(fs, e); | |
| 398 | + switch (e->k) { | |
| 399 | + case VNIL: { | |
| 400 | + if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */ | |
| 401 | + e->info = nil_constant(fs); | |
| 402 | + e->k = VK; | |
| 403 | + return e->info + MAXSTACK; | |
| 404 | + } | |
| 405 | + else break; | |
| 406 | + } | |
| 407 | + case VK: { | |
| 408 | + if (e->info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */ | |
| 409 | + return e->info + MAXSTACK; | |
| 410 | + else break; | |
| 411 | + } | |
| 412 | + default: break; | |
| 413 | + } | |
| 414 | + /* not a constant in the right range: put it in a register */ | |
| 415 | + return luaK_exp2anyreg(fs, e); | |
| 416 | +} | |
| 396 | 417 | |
| 397 | −void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { | |
| 398 | − FuncState *fs = ls->fs; | |
| 399 | − switch (op) { | |
| 400 | − case OPR_AND: { | |
| 401 | − LUA_ASSERT(v1->u.l.t == NO_JUMP, "list must be closed"); | |
| 402 | − discharge1(fs, v2); | |
| 403 | − v1->u.l.t = v2->u.l.t; | |
| 404 | − luaK_concat(fs, &v1->u.l.f, v2->u.l.f); | |
| 418 | + | |
| 419 | +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |
| 420 | + switch (var->k) { | |
| 421 | + case VLOCAL: { | |
| 422 | + freeexp(fs, exp); | |
| 423 | + luaK_exp2reg(fs, exp, var->info); | |
| 424 | + return; | |
| 425 | + } | |
| 426 | + case VUPVAL: { | |
| 427 | + int e = luaK_exp2anyreg(fs, exp); | |
| 428 | + luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); | |
| 405 | 429 | break; |
| 406 | 430 | } |
| 407 | − case OPR_OR: { | |
| 408 | − LUA_ASSERT(v1->u.l.f == NO_JUMP, "list must be closed"); | |
| 409 | − discharge1(fs, v2); | |
| 410 | − v1->u.l.f = v2->u.l.f; | |
| 411 | − luaK_concat(fs, &v1->u.l.t, v2->u.l.t); | |
| 431 | + case VGLOBAL: { | |
| 432 | + int e = luaK_exp2anyreg(fs, exp); | |
| 433 | + luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); | |
| 434 | + break; | |
| 435 | + } | |
| 436 | + case VINDEXED: { | |
| 437 | + int e = luaK_exp2RK(fs, exp); | |
| 438 | + luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); | |
| 412 | 439 | break; |
| 413 | 440 | } |
| 414 | 441 | default: { |
| 415 | − luaK_tostack(ls, v2, 1); /* `v2' must be a value */ | |
| 416 | − luaK_code1(fs, codes[op].opcode, codes[op].arg); | |
| 442 | + lua_assert(0); /* invalid var kind to store */ | |
| 443 | + break; | |
| 417 | 444 | } |
| 418 | 445 | } |
| 446 | + freeexp(fs, exp); | |
| 419 | 447 | } |
| 420 | 448 | |
| 421 | 449 | |
| 422 | −static void codelineinfo (FuncState *fs) { | |
| 423 | − Proto *f = fs->f; | |
| 424 | − LexState *ls = fs->ls; | |
| 425 | − if (ls->lastline > fs->lastline) { | |
| 426 | − luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int, | |
| 427 | − "line info overflow", MAX_INT); | |
| 428 | − if (ls->lastline > fs->lastline+1) | |
| 429 | − f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | |
| 430 | − f->lineinfo[f->nlineinfo++] = fs->pc; | |
| 431 | − fs->lastline = ls->lastline; | |
| 432 | − } | |
| 450 | +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |
| 451 | + int func; | |
| 452 | + luaK_exp2anyreg(fs, e); | |
| 453 | + freeexp(fs, e); | |
| 454 | + func = fs->freereg; | |
| 455 | + luaK_reserveregs(fs, 2); | |
| 456 | + luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); | |
| 457 | + freeexp(fs, key); | |
| 458 | + e->info = func; | |
| 459 | + e->k = VNONRELOC; | |
| 433 | 460 | } |
| 434 | 461 | |
| 435 | 462 | |
| 436 | −int luaK_code0 (FuncState *fs, OpCode o) { | |
| 437 | − return luaK_code2(fs, o, 0, 0); | |
| 463 | +static void invertjump (FuncState *fs, expdesc *e) { | |
| 464 | + Instruction *pc = getjumpcontrol(fs, e->info); | |
| 465 | + lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) && | |
| 466 | + GET_OPCODE(*pc) != OP_TEST); | |
| 467 | + SETARG_A(*pc, !(GETARG_A(*pc))); | |
| 438 | 468 | } |
| 439 | 469 | |
| 440 | 470 | |
| 441 | −int luaK_code1 (FuncState *fs, OpCode o, int arg1) { | |
| 442 | − return luaK_code2(fs, o, arg1, 0); | |
| 471 | +static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |
| 472 | + if (e->k == VRELOCABLE) { | |
| 473 | + Instruction ie = getcode(fs, e); | |
| 474 | + if (GET_OPCODE(ie) == OP_NOT) { | |
| 475 | + fs->pc--; /* remove previous OP_NOT */ | |
| 476 | + return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); | |
| 477 | + } | |
| 478 | + /* else go through */ | |
| 479 | + } | |
| 480 | + discharge2anyreg(fs, e); | |
| 481 | + freeexp(fs, e); | |
| 482 | + return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond); | |
| 443 | 483 | } |
| 444 | 484 | |
| 445 | 485 | |
| 446 | −int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |
| 447 | − Instruction i = previous_instruction(fs); | |
| 448 | − int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop; | |
| 449 | − int optm = 0; /* 1 when there is an optimization */ | |
| 450 | − switch (o) { | |
| 451 | − case OP_CLOSURE: { | |
| 452 | − delta = -arg2+1; | |
| 486 | +void luaK_goiftrue (FuncState *fs, expdesc *e) { | |
| 487 | + int pc; /* pc of last jump */ | |
| 488 | + luaK_dischargevars(fs, e); | |
| 489 | + switch (e->k) { | |
| 490 | + case VK: case VTRUE: { | |
| 491 | + pc = NO_JUMP; /* always true; do nothing */ | |
| 453 | 492 | break; |
| 454 | 493 | } |
| 455 | − case OP_SETTABLE: { | |
| 456 | − delta = -arg2; | |
| 494 | + case VFALSE: { | |
| 495 | + pc = luaK_jump(fs); /* always jump */ | |
| 457 | 496 | break; |
| 458 | 497 | } |
| 459 | − case OP_SETLIST: { | |
| 460 | − if (arg2 == 0) return NO_JUMP; /* nothing to do */ | |
| 461 | − delta = -arg2; | |
| 498 | + case VJMP: { | |
| 499 | + invertjump(fs, e); | |
| 500 | + pc = e->info; | |
| 462 | 501 | break; |
| 463 | 502 | } |
| 464 | − case OP_SETMAP: { | |
| 465 | − if (arg1 == 0) return NO_JUMP; /* nothing to do */ | |
| 466 | − delta = -2*arg1; | |
| 503 | + default: { | |
| 504 | + pc = jumponcond(fs, e, 0); | |
| 467 | 505 | break; |
| 468 | 506 | } |
| 469 | − case OP_RETURN: { | |
| 470 | − if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { | |
| 471 | − SET_OPCODE(i, OP_TAILCALL); | |
| 472 | − SETARG_B(i, arg1); | |
| 473 | − optm = 1; | |
| 474 | − } | |
| 507 | + } | |
| 508 | + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ | |
| 509 | +} | |
| 510 | + | |
| 511 | + | |
| 512 | +void luaK_goiffalse (FuncState *fs, expdesc *e) { | |
| 513 | + int pc; /* pc of last jump */ | |
| 514 | + luaK_dischargevars(fs, e); | |
| 515 | + switch (e->k) { | |
| 516 | + case VNIL: case VFALSE: { | |
| 517 | + pc = NO_JUMP; /* always false; do nothing */ | |
| 475 | 518 | break; |
| 476 | 519 | } |
| 477 | − case OP_PUSHNIL: { | |
| 478 | − if (arg1 == 0) return NO_JUMP; /* nothing to do */ | |
| 479 | − delta = arg1; | |
| 480 | − switch(GET_OPCODE(i)) { | |
| 481 | − case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; | |
| 482 | − default: break; | |
| 483 | − } | |
| 520 | + case VTRUE: { | |
| 521 | + pc = luaK_jump(fs); /* always jump */ | |
| 484 | 522 | break; |
| 485 | 523 | } |
| 486 | − case OP_POP: { | |
| 487 | − if (arg1 == 0) return NO_JUMP; /* nothing to do */ | |
| 488 | − delta = -arg1; | |
| 489 | − switch(GET_OPCODE(i)) { | |
| 490 | − case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; | |
| 491 | − default: break; | |
| 492 | − } | |
| 524 | + case VJMP: { | |
| 525 | + pc = e->info; | |
| 493 | 526 | break; |
| 494 | 527 | } |
| 495 | − case OP_GETTABLE: { | |
| 496 | − switch(GET_OPCODE(i)) { | |
| 497 | − case OP_PUSHSTRING: /* `t.x' */ | |
| 498 | − SET_OPCODE(i, OP_GETDOTTED); | |
| 499 | − optm = 1; | |
| 500 | − break; | |
| 501 | − case OP_GETLOCAL: /* `t[i]' */ | |
| 502 | − SET_OPCODE(i, OP_GETINDEXED); | |
| 503 | − optm = 1; | |
| 504 | − break; | |
| 505 | − default: break; | |
| 506 | − } | |
| 528 | + default: { | |
| 529 | + pc = jumponcond(fs, e, 1); | |
| 507 | 530 | break; |
| 508 | 531 | } |
| 509 | − case OP_ADD: { | |
| 510 | − switch(GET_OPCODE(i)) { | |
| 511 | − case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ | |
| 512 | − default: break; | |
| 513 | − } | |
| 532 | + } | |
| 533 | + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ | |
| 534 | +} | |
| 535 | + | |
| 536 | + | |
| 537 | +static void codenot (FuncState *fs, expdesc *e) { | |
| 538 | + luaK_dischargevars(fs, e); | |
| 539 | + switch (e->k) { | |
| 540 | + case VNIL: case VFALSE: { | |
| 541 | + e->k = VTRUE; | |
| 514 | 542 | break; |
| 515 | 543 | } |
| 516 | − case OP_SUB: { | |
| 517 | − switch(GET_OPCODE(i)) { | |
| 518 | − case OP_PUSHINT: /* `a-k' */ | |
| 519 | − i = CREATE_S(OP_ADDI, -GETARG_S(i)); | |
| 520 | − optm = 1; | |
| 521 | − break; | |
| 522 | − default: break; | |
| 523 | − } | |
| 544 | + case VK: case VTRUE: { | |
| 545 | + e->k = VFALSE; | |
| 524 | 546 | break; |
| 525 | 547 | } |
| 526 | − case OP_CONCAT: { | |
| 527 | − delta = -arg1+1; | |
| 528 | − switch(GET_OPCODE(i)) { | |
| 529 | − case OP_CONCAT: /* `a..b..c' */ | |
| 530 | − SETARG_U(i, GETARG_U(i)+1); | |
| 531 | − optm = 1; | |
| 532 | − break; | |
| 533 | − default: break; | |
| 534 | − } | |
| 548 | + case VJMP: { | |
| 549 | + invertjump(fs, e); | |
| 535 | 550 | break; |
| 536 | 551 | } |
| 537 | − case OP_MINUS: { | |
| 538 | − switch(GET_OPCODE(i)) { | |
| 539 | − case OP_PUSHINT: /* `-k' */ | |
| 540 | − SETARG_S(i, -GETARG_S(i)); | |
| 541 | − optm = 1; | |
| 542 | − break; | |
| 543 | − case OP_PUSHNUM: /* `-k' */ | |
| 544 | − SET_OPCODE(i, OP_PUSHNEGNUM); | |
| 545 | − optm = 1; | |
| 546 | − break; | |
| 547 | − default: break; | |
| 548 | − } | |
| 552 | + case VRELOCABLE: | |
| 553 | + case VNONRELOC: { | |
| 554 | + discharge2anyreg(fs, e); | |
| 555 | + freeexp(fs, e); | |
| 556 | + e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); | |
| 557 | + e->k = VRELOCABLE; | |
| 549 | 558 | break; |
| 550 | 559 | } |
| 551 | − case OP_JMPNE: { | |
| 552 | − if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ | |
| 553 | − i = CREATE_S(OP_JMPT, NO_JUMP); | |
| 554 | − optm = 1; | |
| 555 | − } | |
| 560 | + default: { | |
| 561 | + lua_assert(0); /* cannot happen */ | |
| 556 | 562 | break; |
| 557 | 563 | } |
| 558 | − case OP_JMPEQ: { | |
| 559 | − if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ | |
| 560 | − i = CREATE_0(OP_NOT); | |
| 561 | − delta = -1; /* just undo effect of previous PUSHNIL */ | |
| 562 | − optm = 1; | |
| 563 | − } | |
| 564 | − break; | |
| 564 | + } | |
| 565 | + /* interchange true and false lists */ | |
| 566 | + { int temp = e->f; e->f = e->t; e->t = temp; } | |
| 567 | +} | |
| 568 | + | |
| 569 | + | |
| 570 | +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | |
| 571 | + t->aux = luaK_exp2RK(fs, k); | |
| 572 | + t->k = VINDEXED; | |
| 573 | +} | |
| 574 | + | |
| 575 | + | |
| 576 | +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | |
| 577 | + if (op == OPR_MINUS) { | |
| 578 | + luaK_exp2val(fs, e); | |
| 579 | + if (e->k == VK && ttisnumber(&fs->f->k[e->info])) | |
| 580 | + e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info])); | |
| 581 | + else { | |
| 582 | + luaK_exp2anyreg(fs, e); | |
| 583 | + freeexp(fs, e); | |
| 584 | + e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0); | |
| 585 | + e->k = VRELOCABLE; | |
| 565 | 586 | } |
| 566 | − case OP_JMPT: | |
| 567 | − case OP_JMPONT: { | |
| 568 | − switch (GET_OPCODE(i)) { | |
| 569 | − case OP_NOT: { | |
| 570 | − i = CREATE_S(OP_JMPF, NO_JUMP); | |
| 571 | − optm = 1; | |
| 572 | − break; | |
| 573 | − } | |
| 574 | − case OP_PUSHINT: { | |
| 575 | − if (o == OP_JMPT) { /* JMPONT must keep original integer value */ | |
| 576 | − i = CREATE_S(OP_JMP, NO_JUMP); | |
| 577 | − optm = 1; | |
| 578 | − } | |
| 579 | − break; | |
| 580 | − } | |
| 581 | − case OP_PUSHNIL: { | |
| 582 | − if (GETARG_U(i) == 1) { | |
| 583 | − fs->pc--; /* erase previous instruction */ | |
| 584 | − luaK_deltastack(fs, -1); /* correct stack */ | |
| 585 | − return NO_JUMP; | |
| 586 | − } | |
| 587 | − break; | |
| 588 | − } | |
| 589 | − default: break; | |
| 590 | − } | |
| 587 | + } | |
| 588 | + else /* op == NOT */ | |
| 589 | + codenot(fs, e); | |
| 590 | +} | |
| 591 | + | |
| 592 | + | |
| 593 | +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |
| 594 | + switch (op) { | |
| 595 | + case OPR_AND: { | |
| 596 | + luaK_goiftrue(fs, v); | |
| 597 | + luaK_patchtohere(fs, v->t); | |
| 598 | + v->t = NO_JUMP; | |
| 591 | 599 | break; |
| 592 | 600 | } |
| 593 | − case OP_JMPF: | |
| 594 | − case OP_JMPONF: { | |
| 595 | − switch (GET_OPCODE(i)) { | |
| 596 | − case OP_NOT: { | |
| 597 | − i = CREATE_S(OP_JMPT, NO_JUMP); | |
| 598 | − optm = 1; | |
| 599 | − break; | |
| 600 | − } | |
| 601 | − case OP_PUSHINT: { /* `while 1 do ...' */ | |
| 602 | − fs->pc--; /* erase previous instruction */ | |
| 603 | − luaK_deltastack(fs, -1); /* correct stack */ | |
| 604 | − return NO_JUMP; | |
| 605 | − } | |
| 606 | − case OP_PUSHNIL: { /* `repeat ... until nil' */ | |
| 607 | − if (GETARG_U(i) == 1) { | |
| 608 | − i = CREATE_S(OP_JMP, NO_JUMP); | |
| 609 | − optm = 1; | |
| 610 | − } | |
| 611 | − break; | |
| 612 | − } | |
| 613 | − default: break; | |
| 614 | − } | |
| 601 | + case OPR_OR: { | |
| 602 | + luaK_goiffalse(fs, v); | |
| 603 | + luaK_patchtohere(fs, v->f); | |
| 604 | + v->f = NO_JUMP; | |
| 615 | 605 | break; |
| 616 | 606 | } |
| 617 | − case OP_GETDOTTED: | |
| 618 | − case OP_GETINDEXED: | |
| 619 | − case OP_TAILCALL: | |
| 620 | − case OP_ADDI: { | |
| 621 | − LUA_INTERNALERROR("instruction used only for optimizations"); | |
| 607 | + case OPR_CONCAT: { | |
| 608 | + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ | |
| 622 | 609 | break; |
| 623 | 610 | } |
| 624 | 611 | default: { |
| 625 | − LUA_ASSERT(delta != VD, "invalid delta"); | |
| 612 | + luaK_exp2RK(fs, v); | |
| 626 | 613 | break; |
| 627 | 614 | } |
| 628 | 615 | } |
| 629 | − luaK_deltastack(fs, delta); | |
| 630 | − if (optm) { /* optimize: put instruction in place of last one */ | |
| 631 | − fs->f->code[fs->pc-1] = i; /* change previous instruction */ | |
| 632 | − return fs->pc-1; /* do not generate new instruction */ | |
| 616 | +} | |
| 617 | + | |
| 618 | + | |
| 619 | +static void codebinop (FuncState *fs, expdesc *res, BinOpr op, | |
| 620 | + int o1, int o2) { | |
| 621 | + if (op <= OPR_POW) { /* arithmetic operator? */ | |
| 622 | + OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */ | |
| 623 | + res->info = luaK_codeABC(fs, opc, 0, o1, o2); | |
| 624 | + res->k = VRELOCABLE; | |
| 633 | 625 | } |
| 634 | − /* else build new instruction */ | |
| 635 | − switch ((enum Mode)luaK_opproperties[o].mode) { | |
| 636 | − case iO: i = CREATE_0(o); break; | |
| 637 | − case iU: i = CREATE_U(o, arg1); break; | |
| 638 | − case iS: i = CREATE_S(o, arg1); break; | |
| 639 | − case iAB: i = CREATE_AB(o, arg1, arg2); break; | |
| 626 | + else { /* test operator */ | |
| 627 | + static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE}; | |
| 628 | + int cond = 1; | |
| 629 | + if (op >= OPR_GT) { /* `>' or `>='? */ | |
| 630 | + int temp; /* exchange args and replace by `<' or `<=' */ | |
| 631 | + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | |
| 632 | + } | |
| 633 | + else if (op == OPR_NE) cond = 0; | |
| 634 | + res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2); | |
| 635 | + res->k = VJMP; | |
| 640 | 636 | } |
| 641 | − codelineinfo(fs); | |
| 637 | +} | |
| 638 | + | |
| 639 | + | |
| 640 | +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | |
| 641 | + switch (op) { | |
| 642 | + case OPR_AND: { | |
| 643 | + lua_assert(e1->t == NO_JUMP); /* list must be closed */ | |
| 644 | + luaK_dischargevars(fs, e2); | |
| 645 | + luaK_concat(fs, &e1->f, e2->f); | |
| 646 | + e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; | |
| 647 | + break; | |
| 648 | + } | |
| 649 | + case OPR_OR: { | |
| 650 | + lua_assert(e1->f == NO_JUMP); /* list must be closed */ | |
| 651 | + luaK_dischargevars(fs, e2); | |
| 652 | + luaK_concat(fs, &e1->t, e2->t); | |
| 653 | + e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; | |
| 654 | + break; | |
| 655 | + } | |
| 656 | + case OPR_CONCAT: { | |
| 657 | + luaK_exp2val(fs, e2); | |
| 658 | + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | |
| 659 | + lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); | |
| 660 | + freeexp(fs, e1); | |
| 661 | + SETARG_B(getcode(fs, e2), e1->info); | |
| 662 | + e1->k = e2->k; e1->info = e2->info; | |
| 663 | + } | |
| 664 | + else { | |
| 665 | + luaK_exp2nextreg(fs, e2); | |
| 666 | + freeexp(fs, e2); | |
| 667 | + freeexp(fs, e1); | |
| 668 | + e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info); | |
| 669 | + e1->k = VRELOCABLE; | |
| 670 | + } | |
| 671 | + break; | |
| 672 | + } | |
| 673 | + default: { | |
| 674 | + int o1 = luaK_exp2RK(fs, e1); | |
| 675 | + int o2 = luaK_exp2RK(fs, e2); | |
| 676 | + freeexp(fs, e2); | |
| 677 | + freeexp(fs, e1); | |
| 678 | + codebinop(fs, e1, op, o1, o2); | |
| 679 | + } | |
| 680 | + } | |
| 681 | +} | |
| 682 | + | |
| 683 | + | |
| 684 | +void luaK_fixline (FuncState *fs, int line) { | |
| 685 | + fs->f->lineinfo[fs->pc - 1] = line; | |
| 686 | +} | |
| 687 | + | |
| 688 | + | |
| 689 | +int luaK_code (FuncState *fs, Instruction i, int line) { | |
| 690 | + Proto *f = fs->f; | |
| 691 | + luaK_dischargejpc(fs); /* `pc' will change */ | |
| 642 | 692 | /* put new instruction in code array */ |
| 643 | − luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, | |
| 644 | − "code size overflow", MAX_INT); | |
| 645 | − fs->f->code[fs->pc] = i; | |
| 693 | + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | |
| 694 | + MAX_INT, "code size overflow"); | |
| 695 | + f->code[fs->pc] = i; | |
| 696 | + /* save corresponding line information */ | |
| 697 | + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | |
| 698 | + MAX_INT, "code size overflow"); | |
| 699 | + f->lineinfo[fs->pc] = line; | |
| 646 | 700 | return fs->pc++; |
| 647 | 701 | } |
| 648 | 702 | |
| 649 | 703 | |
| 650 | −const struct OpProperties luaK_opproperties[NUM_OPCODES] = { | |
| 651 | − {iO, 0, 0}, /* OP_END */ | |
| 652 | − {iU, 0, 0}, /* OP_RETURN */ | |
| 653 | − {iAB, 0, 0}, /* OP_CALL */ | |
| 654 | − {iAB, 0, 0}, /* OP_TAILCALL */ | |
| 655 | − {iU, VD, 0}, /* OP_PUSHNIL */ | |
| 656 | − {iU, VD, 0}, /* OP_POP */ | |
| 657 | − {iS, 1, 0}, /* OP_PUSHINT */ | |
| 658 | − {iU, 1, 0}, /* OP_PUSHSTRING */ | |
| 659 | − {iU, 1, 0}, /* OP_PUSHNUM */ | |
| 660 | − {iU, 1, 0}, /* OP_PUSHNEGNUM */ | |
| 661 | − {iU, 1, 0}, /* OP_PUSHUPVALUE */ | |
| 662 | − {iU, 1, 0}, /* OP_GETLOCAL */ | |
| 663 | − {iU, 1, 0}, /* OP_GETGLOBAL */ | |
| 664 | − {iO, 1, 2}, /* OP_GETTABLE */ | |
| 665 | − {iU, 1, 1}, /* OP_GETDOTTED */ | |
| 666 | − {iU, 1, 1}, /* OP_GETINDEXED */ | |
| 667 | − {iU, 2, 1}, /* OP_PUSHSELF */ | |
| 668 | − {iU, 1, 0}, /* OP_CREATETABLE */ | |
| 669 | − {iU, 0, 1}, /* OP_SETLOCAL */ | |
| 670 | − {iU, 0, 1}, /* OP_SETGLOBAL */ | |
| 671 | − {iAB, VD, 0}, /* OP_SETTABLE */ | |
| 672 | − {iAB, VD, 0}, /* OP_SETLIST */ | |
| 673 | − {iU, VD, 0}, /* OP_SETMAP */ | |
| 674 | − {iO, 1, 2}, /* OP_ADD */ | |
| 675 | − {iS, 1, 1}, /* OP_ADDI */ | |
| 676 | − {iO, 1, 2}, /* OP_SUB */ | |
| 677 | − {iO, 1, 2}, /* OP_MULT */ | |
| 678 | − {iO, 1, 2}, /* OP_DIV */ | |
| 679 | − {iO, 1, 2}, /* OP_POW */ | |
| 680 | − {iU, VD, 0}, /* OP_CONCAT */ | |
| 681 | − {iO, 1, 1}, /* OP_MINUS */ | |
| 682 | − {iO, 1, 1}, /* OP_NOT */ | |
| 683 | − {iS, 0, 2}, /* OP_JMPNE */ | |
| 684 | − {iS, 0, 2}, /* OP_JMPEQ */ | |
| 685 | − {iS, 0, 2}, /* OP_JMPLT */ | |
| 686 | − {iS, 0, 2}, /* OP_JMPLE */ | |
| 687 | − {iS, 0, 2}, /* OP_JMPGT */ | |
| 688 | − {iS, 0, 2}, /* OP_JMPGE */ | |
| 689 | − {iS, 0, 1}, /* OP_JMPT */ | |
| 690 | − {iS, 0, 1}, /* OP_JMPF */ | |
| 691 | − {iS, 0, 1}, /* OP_JMPONT */ | |
| 692 | − {iS, 0, 1}, /* OP_JMPONF */ | |
| 693 | − {iS, 0, 0}, /* OP_JMP */ | |
| 694 | − {iO, 0, 0}, /* OP_PUSHNILJMP */ | |
| 695 | − {iS, 0, 0}, /* OP_FORPREP */ | |
| 696 | − {iS, 0, 3}, /* OP_FORLOOP */ | |
| 697 | − {iS, 2, 0}, /* OP_LFORPREP */ | |
| 698 | − {iS, 0, 3}, /* OP_LFORLOOP */ | |
| 699 | − {iAB, VD, 0} /* OP_CLOSURE */ | |
| 700 | −}; | |
| 704 | +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | |
| 705 | + lua_assert(getOpMode(o) == iABC); | |
| 706 | + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); | |
| 707 | +} | |
| 708 | + | |
| 709 | + | |
| 710 | +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | |
| 711 | + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | |
| 712 | + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); | |
| 713 | +} | |
| 701 | 714 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.h,v 1.16 2000/08/09 14:49:13 roberto Exp $ | |
| 2 | +** $Id: lcode.h,v 1.38 2002/12/11 12:34:22 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -26,45 +26,49 @@ · 20 unmodified lines | ||
| 26 | 26 | typedef enum BinOpr { |
| 27 | 27 | OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW, |
| 28 | 28 | OPR_CONCAT, |
| 29 | − OPR_NE, OPR_EQ, OPR_LT, OPR_LE, OPR_GT, OPR_GE, | |
| 29 | + OPR_NE, OPR_EQ, | |
| 30 | + OPR_LT, OPR_LE, OPR_GT, OPR_GE, | |
| 30 | 31 | OPR_AND, OPR_OR, |
| 31 | 32 | OPR_NOBINOPR |
| 32 | 33 | } BinOpr; |
| 33 | 34 | |
| 34 | −typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; | |
| 35 | − | |
| 35 | +#define binopistest(op) ((op) >= OPR_NE) | |
| 36 | 36 | |
| 37 | −enum Mode {iO, iU, iS, iAB}; /* instruction format */ | |
| 37 | +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; | |
| 38 | 38 | |
| 39 | −#define VD 100 /* flag for variable delta */ | |
| 40 | 39 | |
| 41 | −extern const struct OpProperties { | |
| 42 | − char mode; | |
| 43 | − unsigned char push; | |
| 44 | − unsigned char pop; | |
| 45 | −} luaK_opproperties[]; | |
| 40 | +#define getcode(fs,e) ((fs)->f->code[(e)->info]) | |
| 46 | 41 | |
| 42 | +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) | |
| 47 | 43 | |
| 48 | −void luaK_error (LexState *ls, const char *msg); | |
| 49 | −int luaK_code0 (FuncState *fs, OpCode o); | |
| 50 | −int luaK_code1 (FuncState *fs, OpCode o, int arg1); | |
| 51 | −int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2); | |
| 44 | +int luaK_code (FuncState *fs, Instruction i, int line); | |
| 45 | +int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); | |
| 46 | +int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); | |
| 47 | +void luaK_fixline (FuncState *fs, int line); | |
| 48 | +void luaK_nil (FuncState *fs, int from, int n); | |
| 49 | +void luaK_reserveregs (FuncState *fs, int n); | |
| 50 | +void luaK_checkstack (FuncState *fs, int n); | |
| 51 | +int luaK_stringK (FuncState *fs, TString *s); | |
| 52 | +int luaK_numberK (FuncState *fs, lua_Number r); | |
| 53 | +void luaK_dischargevars (FuncState *fs, expdesc *e); | |
| 54 | +int luaK_exp2anyreg (FuncState *fs, expdesc *e); | |
| 55 | +void luaK_exp2nextreg (FuncState *fs, expdesc *e); | |
| 56 | +void luaK_exp2val (FuncState *fs, expdesc *e); | |
| 57 | +int luaK_exp2RK (FuncState *fs, expdesc *e); | |
| 58 | +void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | |
| 59 | +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | |
| 60 | +void luaK_goiftrue (FuncState *fs, expdesc *e); | |
| 61 | +void luaK_goiffalse (FuncState *fs, expdesc *e); | |
| 62 | +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | |
| 63 | +void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); | |
| 52 | 64 | int luaK_jump (FuncState *fs); |
| 53 | 65 | void luaK_patchlist (FuncState *fs, int list, int target); |
| 66 | +void luaK_patchtohere (FuncState *fs, int list); | |
| 54 | 67 | void luaK_concat (FuncState *fs, int *l1, int l2); |
| 55 | −void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); | |
| 56 | 68 | int luaK_getlabel (FuncState *fs); |
| 57 | −void luaK_deltastack (FuncState *fs, int delta); | |
| 58 | −void luaK_kstr (LexState *ls, int c); | |
| 59 | −void luaK_number (FuncState *fs, Number f); | |
| 60 | −void luaK_adjuststack (FuncState *fs, int n); | |
| 61 | −int luaK_lastisopen (FuncState *fs); | |
| 62 | −void luaK_setcallreturns (FuncState *fs, int nresults); | |
| 63 | −void luaK_tostack (LexState *ls, expdesc *v, int onlyone); | |
| 64 | −void luaK_storevar (LexState *ls, const expdesc *var); | |
| 65 | −void luaK_prefix (LexState *ls, UnOpr op, expdesc *v); | |
| 66 | −void luaK_infix (LexState *ls, BinOpr op, expdesc *v); | |
| 67 | −void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2); | |
| 69 | +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); | |
| 70 | +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); | |
| 71 | +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); | |
| 68 | 72 | |
| 69 | 73 | |
| 70 | 74 | #endif |
| @@ -1,11 +1,14 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldebug.c,v 1.50 2000/10/30 12:38:50 roberto Exp $ | |
| 2 | +** $Id: ldebug.c,v 1.150 2003/03/19 21:24:04 roberto Exp $ | |
| 3 | 3 | ** Debug Interface |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | #include <stdlib.h> |
| 9 | +#include <string.h> | |
| 10 | + | |
| 11 | +#define ldebug_c | |
| 9 | 12 | |
| 10 | 13 | #include "lua.h" |
| 11 | 14 | |
| @@ -20,447 +23,563 @@ · 8 unmodified lines | ||
| 20 | 23 | #include "lstring.h" |
| 21 | 24 | #include "ltable.h" |
| 22 | 25 | #include "ltm.h" |
| 23 | −#include "luadebug.h" | |
| 26 | +#include "lvm.h" | |
| 24 | 27 | |
| 25 | 28 | |
| 26 | 29 | |
| 27 | −static const char *getfuncname (lua_State *L, StkId f, const char **name); | |
| 30 | +static const char *getfuncname (CallInfo *ci, const char **name); | |
| 28 | 31 | |
| 29 | 32 | |
| 30 | −static void setnormalized (TObject *d, const TObject *s) { | |
| 31 | − if (ttype(s) == LUA_TMARK) { | |
| 32 | − clvalue(d) = infovalue(s)->func; | |
| 33 | − ttype(d) = LUA_TFUNCTION; | |
| 34 | − } | |
| 35 | − else *d = *s; | |
| 36 | −} | |
| 33 | +#define isLua(ci) (!((ci)->state & CI_C)) | |
| 37 | 34 | |
| 38 | 35 | |
| 39 | −static int isLmark (StkId o) { | |
| 40 | − return (o && ttype(o) == LUA_TMARK && !infovalue(o)->func->isC); | |
| 36 | +static int currentpc (CallInfo *ci) { | |
| 37 | + if (!isLua(ci)) return -1; /* function is not a Lua function? */ | |
| 38 | + if (ci->state & CI_HASFRAME) /* function has a frame? */ | |
| 39 | + ci->u.l.savedpc = *ci->u.l.pc; /* use `pc' from there */ | |
| 40 | + /* function's pc is saved */ | |
| 41 | + return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); | |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | |
| 44 | −LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) { | |
| 45 | − lua_Hook oldhook = L->callhook; | |
| 46 | − L->callhook = func; | |
| 47 | − return oldhook; | |
| 45 | +static int currentline (CallInfo *ci) { | |
| 46 | + int pc = currentpc(ci); | |
| 47 | + if (pc < 0) | |
| 48 | + return -1; /* only active lua functions have current-line information */ | |
| 49 | + else | |
| 50 | + return getline(ci_func(ci)->l.p, pc); | |
| 48 | 51 | } |
| 49 | 52 | |
| 50 | 53 | |
| 51 | −LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) { | |
| 52 | − lua_Hook oldhook = L->linehook; | |
| 53 | − L->linehook = func; | |
| 54 | − return oldhook; | |
| 54 | +void luaG_inithooks (lua_State *L) { | |
| 55 | + CallInfo *ci; | |
| 56 | + for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */ | |
| 57 | + currentpc(ci); | |
| 58 | + L->hookinit = 1; | |
| 55 | 59 | } |
| 56 | 60 | |
| 57 | 61 | |
| 58 | −static StkId aux_stackedfunction (lua_State *L, int level, StkId top) { | |
| 59 | − int i; | |
| 60 | − for (i = (top-1) - L->stack; i>=0; i--) { | |
| 61 | − if (is_T_MARK(L->stack[i].ttype)) { | |
| 62 | − if (level == 0) | |
| 63 | − return L->stack+i; | |
| 64 | − level--; | |
| 65 | − } | |
| 62 | +/* | |
| 63 | +** this function can be called asynchronous (e.g. during a signal) | |
| 64 | +*/ | |
| 65 | +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |
| 66 | + if (func == NULL || mask == 0) { /* turn off hooks? */ | |
| 67 | + mask = 0; | |
| 68 | + func = NULL; | |
| 66 | 69 | } |
| 67 | − return NULL; | |
| 70 | + L->hook = func; | |
| 71 | + L->basehookcount = count; | |
| 72 | + resethookcount(L); | |
| 73 | + L->hookmask = cast(lu_byte, mask); | |
| 74 | + L->hookinit = 0; | |
| 75 | + return 1; | |
| 68 | 76 | } |
| 69 | 77 | |
| 70 | 78 | |
| 71 | −LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | |
| 72 | − StkId f = aux_stackedfunction(L, level, L->top); | |
| 73 | − if (f == NULL) return 0; /* there is no such level */ | |
| 74 | − else { | |
| 75 | − ar->_func = f; | |
| 76 | − return 1; | |
| 77 | − } | |
| 79 | +LUA_API lua_Hook lua_gethook (lua_State *L) { | |
| 80 | + return L->hook; | |
| 78 | 81 | } |
| 79 | 82 | |
| 80 | 83 | |
| 81 | −static int nups (StkId f) { | |
| 82 | − switch (ttype(f)) { | |
| 83 | − case LUA_TFUNCTION: | |
| 84 | − return clvalue(f)->nupvalues; | |
| 85 | − case LUA_TMARK: | |
| 86 | − return infovalue(f)->func->nupvalues; | |
| 87 | − default: | |
| 88 | − return 0; | |
| 89 | − } | |
| 84 | +LUA_API int lua_gethookmask (lua_State *L) { | |
| 85 | + return L->hookmask; | |
| 90 | 86 | } |
| 91 | 87 | |
| 92 | 88 | |
| 93 | −int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { | |
| 94 | − int refi; | |
| 95 | − if (lineinfo == NULL || pc == -1) | |
| 96 | − return -1; /* no line info or function is not active */ | |
| 97 | − refi = prefi ? *prefi : 0; | |
| 98 | − if (lineinfo[refi] < 0) | |
| 99 | − refline += -lineinfo[refi++]; | |
| 100 | − LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); | |
| 101 | − while (lineinfo[refi] > pc) { | |
| 102 | − refline--; | |
| 103 | − refi--; | |
| 104 | − if (lineinfo[refi] < 0) | |
| 105 | − refline -= -lineinfo[refi--]; | |
| 106 | − LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); | |
| 107 | − } | |
| 108 | − for (;;) { | |
| 109 | − int nextline = refline + 1; | |
| 110 | − int nextref = refi + 1; | |
| 111 | − if (lineinfo[nextref] < 0) | |
| 112 | − nextline += -lineinfo[nextref++]; | |
| 113 | − LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info"); | |
| 114 | − if (lineinfo[nextref] > pc) | |
| 115 | − break; | |
| 116 | − refline = nextline; | |
| 117 | − refi = nextref; | |
| 118 | − } | |
| 119 | − if (prefi) *prefi = refi; | |
| 120 | − return refline; | |
| 89 | +LUA_API int lua_gethookcount (lua_State *L) { | |
| 90 | + return L->basehookcount; | |
| 121 | 91 | } |
| 122 | 92 | |
| 123 | 93 | |
| 124 | −static int currentpc (StkId f) { | |
| 125 | − CallInfo *ci = infovalue(f); | |
| 126 | − LUA_ASSERT(isLmark(f), "function has no pc"); | |
| 127 | − if (ci->pc) | |
| 128 | − return (*ci->pc - ci->func->f.l->code) - 1; | |
| 129 | − else | |
| 130 | − return -1; /* function is not active */ | |
| 131 | −} | |
| 132 | − | |
| 133 | − | |
| 134 | −static int currentline (StkId f) { | |
| 135 | − if (!isLmark(f)) | |
| 136 | − return -1; /* only active lua functions have current-line information */ | |
| 94 | +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | |
| 95 | + int status; | |
| 96 | + CallInfo *ci; | |
| 97 | + lua_lock(L); | |
| 98 | + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { | |
| 99 | + level--; | |
| 100 | + if (!(ci->state & CI_C)) /* Lua function? */ | |
| 101 | + level -= ci->u.l.tailcalls; /* skip lost tail calls */ | |
| 102 | + } | |
| 103 | + if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ | |
| 104 | + else if (level < 0) { /* level is of a lost tail call */ | |
| 105 | + status = 1; | |
| 106 | + ar->i_ci = 0; | |
| 107 | + } | |
| 137 | 108 | else { |
| 138 | − CallInfo *ci = infovalue(f); | |
| 139 | − int *lineinfo = ci->func->f.l->lineinfo; | |
| 140 | − return luaG_getline(lineinfo, currentpc(f), 1, NULL); | |
| 109 | + status = 1; | |
| 110 | + ar->i_ci = ci - L->base_ci; | |
| 141 | 111 | } |
| 112 | + lua_unlock(L); | |
| 113 | + return status; | |
| 142 | 114 | } |
| 143 | 115 | |
| 144 | 116 | |
| 145 | − | |
| 146 | −static Proto *getluaproto (StkId f) { | |
| 147 | − return (isLmark(f) ? infovalue(f)->func->f.l : NULL); | |
| 117 | +static Proto *getluaproto (CallInfo *ci) { | |
| 118 | + return (isLua(ci) ? ci_func(ci)->l.p : NULL); | |
| 148 | 119 | } |
| 149 | 120 | |
| 150 | 121 | |
| 151 | 122 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { |
| 152 | 123 | const char *name; |
| 153 | − StkId f = ar->_func; | |
| 154 | − Proto *fp = getluaproto(f); | |
| 155 | − if (!fp) return NULL; /* `f' is not a Lua function? */ | |
| 156 | − name = luaF_getlocalname(fp, n, currentpc(f)); | |
| 157 | − if (!name) return NULL; | |
| 158 | − luaA_pushobject(L, (f+1)+(n-1)); /* push value */ | |
| 124 | + CallInfo *ci; | |
| 125 | + Proto *fp; | |
| 126 | + lua_lock(L); | |
| 127 | + name = NULL; | |
| 128 | + ci = L->base_ci + ar->i_ci; | |
| 129 | + fp = getluaproto(ci); | |
| 130 | + if (fp) { /* is a Lua function? */ | |
| 131 | + name = luaF_getlocalname(fp, n, currentpc(ci)); | |
| 132 | + if (name) | |
| 133 | + luaA_pushobject(L, ci->base+(n-1)); /* push value */ | |
| 134 | + } | |
| 135 | + lua_unlock(L); | |
| 159 | 136 | return name; |
| 160 | 137 | } |
| 161 | 138 | |
| 162 | 139 | |
| 163 | 140 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { |
| 164 | 141 | const char *name; |
| 165 | − StkId f = ar->_func; | |
| 166 | − Proto *fp = getluaproto(f); | |
| 142 | + CallInfo *ci; | |
| 143 | + Proto *fp; | |
| 144 | + lua_lock(L); | |
| 145 | + name = NULL; | |
| 146 | + ci = L->base_ci + ar->i_ci; | |
| 147 | + fp = getluaproto(ci); | |
| 167 | 148 | L->top--; /* pop new value */ |
| 168 | − if (!fp) return NULL; /* `f' is not a Lua function? */ | |
| 169 | − name = luaF_getlocalname(fp, n, currentpc(f)); | |
| 170 | − if (!name || name[0] == '(') return NULL; /* `(' starts private locals */ | |
| 171 | − *((f+1)+(n-1)) = *L->top; | |
| 149 | + if (fp) { /* is a Lua function? */ | |
| 150 | + name = luaF_getlocalname(fp, n, currentpc(ci)); | |
| 151 | + if (!name || name[0] == '(') /* `(' starts private locals */ | |
| 152 | + name = NULL; | |
| 153 | + else | |
| 154 | + setobjs2s(ci->base+(n-1), L->top); | |
| 155 | + } | |
| 156 | + lua_unlock(L); | |
| 172 | 157 | return name; |
| 173 | 158 | } |
| 174 | 159 | |
| 175 | 160 | |
| 176 | −static void infoLproto (lua_Debug *ar, Proto *f) { | |
| 177 | − ar->source = f->source->str; | |
| 178 | − ar->linedefined = f->lineDefined; | |
| 179 | − ar->what = "Lua"; | |
| 180 | −} | |
| 181 | − | |
| 182 | − | |
| 183 | −static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { | |
| 184 | − Closure *cl = NULL; | |
| 185 | − switch (ttype(func)) { | |
| 186 | − case LUA_TFUNCTION: | |
| 187 | − cl = clvalue(func); | |
| 188 | − break; | |
| 189 | − case LUA_TMARK: | |
| 190 | − cl = infovalue(func)->func; | |
| 191 | − break; | |
| 192 | − default: | |
| 193 | − lua_error(L, "value for `lua_getinfo' is not a function"); | |
| 194 | − } | |
| 195 | − if (cl->isC) { | |
| 196 | − ar->source = "=C"; | |
| 161 | +static void funcinfo (lua_Debug *ar, StkId func) { | |
| 162 | + Closure *cl = clvalue(func); | |
| 163 | + if (cl->c.isC) { | |
| 164 | + ar->source = "=[C]"; | |
| 197 | 165 | ar->linedefined = -1; |
| 198 | 166 | ar->what = "C"; |
| 199 | 167 | } |
| 200 | − else | |
| 201 | − infoLproto(ar, cl->f.l); | |
| 202 | − luaO_chunkid(ar->short_src, ar->source, sizeof(ar->short_src)); | |
| 203 | − if (ar->linedefined == 0) | |
| 204 | − ar->what = "main"; | |
| 205 | −} | |
| 206 | − | |
| 207 | − | |
| 208 | −static const char *travtagmethods (lua_State *L, const TObject *o) { | |
| 209 | − if (ttype(o) == LUA_TFUNCTION) { | |
| 210 | − int e; | |
| 211 | − for (e=0; e<TM_N; e++) { | |
| 212 | − int t; | |
| 213 | − for (t=0; t<=L->last_tag; t++) | |
| 214 | − if (clvalue(o) == luaT_gettm(L, t, e)) | |
| 215 | − return luaT_eventname[e]; | |
| 216 | − } | |
| 168 | + else { | |
| 169 | + ar->source = getstr(cl->l.p->source); | |
| 170 | + ar->linedefined = cl->l.p->lineDefined; | |
| 171 | + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; | |
| 217 | 172 | } |
| 218 | − return NULL; | |
| 173 | + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | |
| 219 | 174 | } |
| 220 | 175 | |
| 221 | 176 | |
| 222 | 177 | static const char *travglobals (lua_State *L, const TObject *o) { |
| 223 | − Hash *g = L->gt; | |
| 224 | − int i; | |
| 225 | − for (i=0; i<g->size; i++) { | |
| 226 | − if (luaO_equalObj(o, val(node(g, i))) && | |
| 227 | − ttype(key(node(g, i))) == LUA_TSTRING) | |
| 228 | − return tsvalue(key(node(g, i)))->str; | |
| 178 | + Table *g = hvalue(gt(L)); | |
| 179 | + int i = sizenode(g); | |
| 180 | + while (i--) { | |
| 181 | + Node *n = gnode(g, i); | |
| 182 | + if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n))) | |
| 183 | + return getstr(tsvalue(gkey(n))); | |
| 229 | 184 | } |
| 230 | 185 | return NULL; |
| 231 | 186 | } |
| 232 | 187 | |
| 233 | 188 | |
| 234 | −static void getname (lua_State *L, StkId f, lua_Debug *ar) { | |
| 235 | − TObject o; | |
| 236 | − setnormalized(&o, f); | |
| 237 | − /* try to find a name for given function */ | |
| 238 | − if ((ar->name = travglobals(L, &o)) != NULL) | |
| 239 | − ar->namewhat = "global"; | |
| 240 | − /* not found: try tag methods */ | |
| 241 | − else if ((ar->name = travtagmethods(L, &o)) != NULL) | |
| 242 | − ar->namewhat = "tag-method"; | |
| 243 | − else ar->namewhat = ""; /* not found at all */ | |
| 189 | +static void info_tailcall (lua_State *L, lua_Debug *ar) { | |
| 190 | + ar->name = ar->namewhat = ""; | |
| 191 | + ar->what = "tail"; | |
| 192 | + ar->linedefined = ar->currentline = -1; | |
| 193 | + ar->source = "=(tail call)"; | |
| 194 | + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | |
| 195 | + ar->nups = 0; | |
| 196 | + setnilvalue(L->top); | |
| 244 | 197 | } |
| 245 | 198 | |
| 246 | 199 | |
| 247 | −LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |
| 248 | − StkId func; | |
| 249 | − int isactive = (*what != '>'); | |
| 250 | − if (isactive) | |
| 251 | − func = ar->_func; | |
| 252 | − else { | |
| 253 | − what++; /* skip the '>' */ | |
| 254 | − func = L->top - 1; | |
| 255 | − } | |
| 200 | +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |
| 201 | + StkId f, CallInfo *ci) { | |
| 202 | + int status = 1; | |
| 256 | 203 | for (; *what; what++) { |
| 257 | 204 | switch (*what) { |
| 258 | 205 | case 'S': { |
| 259 | − funcinfo(L, ar, func); | |
| 206 | + funcinfo(ar, f); | |
| 260 | 207 | break; |
| 261 | 208 | } |
| 262 | 209 | case 'l': { |
| 263 | − ar->currentline = currentline(func); | |
| 210 | + ar->currentline = (ci) ? currentline(ci) : -1; | |
| 264 | 211 | break; |
| 265 | 212 | } |
| 266 | 213 | case 'u': { |
| 267 | − ar->nups = nups(func); | |
| 214 | + ar->nups = clvalue(f)->c.nupvalues; | |
| 268 | 215 | break; |
| 269 | 216 | } |
| 270 | 217 | case 'n': { |
| 271 | − ar->namewhat = (isactive) ? getfuncname(L, func, &ar->name) : NULL; | |
| 272 | − if (ar->namewhat == NULL) | |
| 273 | − getname(L, func, ar); | |
| 218 | + ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL; | |
| 219 | + if (ar->namewhat == NULL) { | |
| 220 | + /* try to find a global name */ | |
| 221 | + if ((ar->name = travglobals(L, f)) != NULL) | |
| 222 | + ar->namewhat = "global"; | |
| 223 | + else ar->namewhat = ""; /* not found */ | |
| 224 | + } | |
| 274 | 225 | break; |
| 275 | 226 | } |
| 276 | 227 | case 'f': { |
| 277 | − setnormalized(L->top, func); | |
| 278 | − incr_top; /* push function */ | |
| 228 | + setobj2s(L->top, f); | |
| 279 | 229 | break; |
| 280 | 230 | } |
| 281 | − default: return 0; /* invalid option */ | |
| 231 | + default: status = 0; /* invalid option */ | |
| 282 | 232 | } |
| 283 | 233 | } |
| 284 | − if (!isactive) L->top--; /* pop function */ | |
| 285 | − return 1; | |
| 234 | + return status; | |
| 235 | +} | |
| 236 | + | |
| 237 | + | |
| 238 | +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |
| 239 | + int status = 1; | |
| 240 | + lua_lock(L); | |
| 241 | + if (*what == '>') { | |
| 242 | + StkId f = L->top - 1; | |
| 243 | + if (!ttisfunction(f)) | |
| 244 | + luaG_runerror(L, "value for `lua_getinfo' is not a function"); | |
| 245 | + status = auxgetinfo(L, what + 1, ar, f, NULL); | |
| 246 | + L->top--; /* pop function */ | |
| 247 | + } | |
| 248 | + else if (ar->i_ci != 0) { /* no tail call? */ | |
| 249 | + CallInfo *ci = L->base_ci + ar->i_ci; | |
| 250 | + lua_assert(ttisfunction(ci->base - 1)); | |
| 251 | + status = auxgetinfo(L, what, ar, ci->base - 1, ci); | |
| 252 | + } | |
| 253 | + else | |
| 254 | + info_tailcall(L, ar); | |
| 255 | + if (strchr(what, 'f')) incr_top(L); | |
| 256 | + lua_unlock(L); | |
| 257 | + return status; | |
| 286 | 258 | } |
| 287 | 259 | |
| 288 | 260 | |
| 289 | 261 | /* |
| 290 | 262 | ** {====================================================== |
| 291 | −** Symbolic Execution | |
| 263 | +** Symbolic Execution and code checker | |
| 292 | 264 | ** ======================================================= |
| 293 | 265 | */ |
| 294 | 266 | |
| 267 | +#define check(x) if (!(x)) return 0; | |
| 268 | + | |
| 269 | +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) | |
| 270 | + | |
| 271 | +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) | |
| 272 | + | |
| 273 | + | |
| 295 | 274 | |
| 296 | −static int pushpc (int *stack, int pc, int top, int n) { | |
| 297 | − while (n--) | |
| 298 | − stack[top++] = pc-1; | |
| 299 | − return top; | |
| 275 | +static int precheck (const Proto *pt) { | |
| 276 | + check(pt->maxstacksize <= MAXSTACK); | |
| 277 | + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); | |
| 278 | + lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize); | |
| 279 | + check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); | |
| 280 | + return 1; | |
| 300 | 281 | } |
| 301 | 282 | |
| 302 | 283 | |
| 303 | −static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { | |
| 304 | − int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ | |
| 305 | − const Instruction *code = pt->code; | |
| 306 | − int top = pt->numparams; | |
| 307 | − int pc = 0; | |
| 308 | − if (pt->is_vararg) /* varargs? */ | |
| 309 | − top++; /* `arg' */ | |
| 310 | − while (pc < lastpc) { | |
| 311 | − const Instruction i = code[pc++]; | |
| 312 | − LUA_ASSERT(0 <= top && top <= pt->maxstacksize, "wrong stack"); | |
| 313 | − switch (GET_OPCODE(i)) { | |
| 314 | − case OP_RETURN: { | |
| 315 | − LUA_ASSERT(top >= GETARG_U(i), "wrong stack"); | |
| 316 | − top = GETARG_U(i); | |
| 284 | +static int checkopenop (const Proto *pt, int pc) { | |
| 285 | + Instruction i = pt->code[pc+1]; | |
| 286 | + switch (GET_OPCODE(i)) { | |
| 287 | + case OP_CALL: | |
| 288 | + case OP_TAILCALL: | |
| 289 | + case OP_RETURN: { | |
| 290 | + check(GETARG_B(i) == 0); | |
| 291 | + return 1; | |
| 292 | + } | |
| 293 | + case OP_SETLISTO: return 1; | |
| 294 | + default: return 0; /* invalid instruction after an open call */ | |
| 295 | + } | |
| 296 | +} | |
| 297 | + | |
| 298 | + | |
| 299 | +static int checkRK (const Proto *pt, int r) { | |
| 300 | + return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek)); | |
| 301 | +} | |
| 302 | + | |
| 303 | + | |
| 304 | +static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |
| 305 | + int pc; | |
| 306 | + int last; /* stores position of last instruction that changed `reg' */ | |
| 307 | + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ | |
| 308 | + check(precheck(pt)); | |
| 309 | + for (pc = 0; pc < lastpc; pc++) { | |
| 310 | + const Instruction i = pt->code[pc]; | |
| 311 | + OpCode op = GET_OPCODE(i); | |
| 312 | + int a = GETARG_A(i); | |
| 313 | + int b = 0; | |
| 314 | + int c = 0; | |
| 315 | + checkreg(pt, a); | |
| 316 | + switch (getOpMode(op)) { | |
| 317 | + case iABC: { | |
| 318 | + b = GETARG_B(i); | |
| 319 | + c = GETARG_C(i); | |
| 320 | + if (testOpMode(op, OpModeBreg)) { | |
| 321 | + checkreg(pt, b); | |
| 322 | + } | |
| 323 | + else if (testOpMode(op, OpModeBrk)) | |
| 324 | + check(checkRK(pt, b)); | |
| 325 | + if (testOpMode(op, OpModeCrk)) | |
| 326 | + check(checkRK(pt, c)); | |
| 317 | 327 | break; |
| 318 | 328 | } |
| 319 | − case OP_TAILCALL: { | |
| 320 | − LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); | |
| 321 | − top = GETARG_B(i); | |
| 329 | + case iABx: { | |
| 330 | + b = GETARG_Bx(i); | |
| 331 | + if (testOpMode(op, OpModeK)) check(b < pt->sizek); | |
| 332 | + break; | |
| 333 | + } | |
| 334 | + case iAsBx: { | |
| 335 | + b = GETARG_sBx(i); | |
| 322 | 336 | break; |
| 323 | 337 | } |
| 324 | − case OP_CALL: { | |
| 325 | − int nresults = GETARG_B(i); | |
| 326 | − if (nresults == MULT_RET) nresults = 1; | |
| 327 | − LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); | |
| 328 | − top = pushpc(stack, pc, GETARG_A(i), nresults); | |
| 338 | + } | |
| 339 | + if (testOpMode(op, OpModesetA)) { | |
| 340 | + if (a == reg) last = pc; /* change register `a' */ | |
| 341 | + } | |
| 342 | + if (testOpMode(op, OpModeT)) { | |
| 343 | + check(pc+2 < pt->sizecode); /* check skip */ | |
| 344 | + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); | |
| 345 | + } | |
| 346 | + switch (op) { | |
| 347 | + case OP_LOADBOOL: { | |
| 348 | + check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ | |
| 329 | 349 | break; |
| 330 | 350 | } |
| 331 | − case OP_PUSHNIL: { | |
| 332 | − top = pushpc(stack, pc, top, GETARG_U(i)); | |
| 351 | + case OP_LOADNIL: { | |
| 352 | + if (a <= reg && reg <= b) | |
| 353 | + last = pc; /* set registers from `a' to `b' */ | |
| 333 | 354 | break; |
| 334 | 355 | } |
| 335 | − case OP_POP: { | |
| 336 | − top -= GETARG_U(i); | |
| 356 | + case OP_GETUPVAL: | |
| 357 | + case OP_SETUPVAL: { | |
| 358 | + check(b < pt->nups); | |
| 337 | 359 | break; |
| 338 | 360 | } |
| 339 | − case OP_SETTABLE: | |
| 340 | − case OP_SETLIST: { | |
| 341 | − top -= GETARG_B(i); | |
| 361 | + case OP_GETGLOBAL: | |
| 362 | + case OP_SETGLOBAL: { | |
| 363 | + check(ttisstring(&pt->k[b])); | |
| 342 | 364 | break; |
| 343 | 365 | } |
| 344 | − case OP_SETMAP: { | |
| 345 | − top -= 2*GETARG_U(i); | |
| 366 | + case OP_SELF: { | |
| 367 | + checkreg(pt, a+1); | |
| 368 | + if (reg == a+1) last = pc; | |
| 346 | 369 | break; |
| 347 | 370 | } |
| 348 | 371 | case OP_CONCAT: { |
| 349 | − top -= GETARG_U(i); | |
| 350 | − stack[top++] = pc-1; | |
| 372 | + /* `c' is a register, and at least two operands */ | |
| 373 | + check(c < MAXSTACK && b < c); | |
| 351 | 374 | break; |
| 352 | 375 | } |
| 353 | − case OP_CLOSURE: { | |
| 354 | − top -= GETARG_B(i); | |
| 355 | − stack[top++] = pc-1; | |
| 376 | + case OP_TFORLOOP: | |
| 377 | + checkreg(pt, a+c+5); | |
| 378 | + if (reg >= a) last = pc; /* affect all registers above base */ | |
| 379 | + /* go through */ | |
| 380 | + case OP_FORLOOP: | |
| 381 | + checkreg(pt, a+2); | |
| 382 | + /* go through */ | |
| 383 | + case OP_JMP: { | |
| 384 | + int dest = pc+1+b; | |
| 385 | + check(0 <= dest && dest < pt->sizecode); | |
| 386 | + /* not full check and jump is forward and do not skip `lastpc'? */ | |
| 387 | + if (reg != NO_REG && pc < dest && dest <= lastpc) | |
| 388 | + pc += b; /* do the jump */ | |
| 356 | 389 | break; |
| 357 | 390 | } |
| 358 | − case OP_JMPONT: | |
| 359 | − case OP_JMPONF: { | |
| 360 | − int newpc = pc + GETARG_S(i); | |
| 361 | − /* jump is forward and do not skip `lastpc'? */ | |
| 362 | − if (pc < newpc && newpc <= lastpc) { | |
| 363 | − stack[top-1] = pc-1; /* value comes from `and'/`or' */ | |
| 364 | − pc = newpc; /* do the jump */ | |
| 391 | + case OP_CALL: | |
| 392 | + case OP_TAILCALL: { | |
| 393 | + if (b != 0) { | |
| 394 | + checkreg(pt, a+b-1); | |
| 365 | 395 | } |
| 366 | − else | |
| 367 | − top--; /* do not jump; pop value */ | |
| 396 | + c--; /* c = num. returns */ | |
| 397 | + if (c == LUA_MULTRET) { | |
| 398 | + check(checkopenop(pt, pc)); | |
| 399 | + } | |
| 400 | + else if (c != 0) | |
| 401 | + checkreg(pt, a+c-1); | |
| 402 | + if (reg >= a) last = pc; /* affect all registers above base */ | |
| 368 | 403 | break; |
| 369 | 404 | } |
| 370 | − default: { | |
| 371 | − OpCode op = GET_OPCODE(i); | |
| 372 | − LUA_ASSERT(luaK_opproperties[op].push != VD, | |
| 373 | − "invalid opcode for default"); | |
| 374 | − top -= luaK_opproperties[op].pop; | |
| 375 | − LUA_ASSERT(top >= 0, "wrong stack"); | |
| 376 | − top = pushpc(stack, pc, top, luaK_opproperties[op].push); | |
| 405 | + case OP_RETURN: { | |
| 406 | + b--; /* b = num. returns */ | |
| 407 | + if (b > 0) checkreg(pt, a+b-1); | |
| 408 | + break; | |
| 409 | + } | |
| 410 | + case OP_SETLIST: { | |
| 411 | + checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1); | |
| 412 | + break; | |
| 413 | + } | |
| 414 | + case OP_CLOSURE: { | |
| 415 | + int nup; | |
| 416 | + check(b < pt->sizep); | |
| 417 | + nup = pt->p[b]->nups; | |
| 418 | + check(pc + nup < pt->sizecode); | |
| 419 | + for (; nup>0; nup--) { | |
| 420 | + OpCode op1 = GET_OPCODE(pt->code[pc+nup]); | |
| 421 | + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); | |
| 422 | + } | |
| 423 | + break; | |
| 377 | 424 | } |
| 425 | + default: break; | |
| 378 | 426 | } |
| 379 | 427 | } |
| 380 | − return code[stack[stackpos]]; | |
| 428 | + return pt->code[last]; | |
| 381 | 429 | } |
| 382 | 430 | |
| 431 | +#undef check | |
| 432 | +#undef checkjump | |
| 433 | +#undef checkreg | |
| 383 | 434 | |
| 384 | −static const char *getobjname (lua_State *L, StkId obj, const char **name) { | |
| 385 | − StkId func = aux_stackedfunction(L, 0, obj); | |
| 386 | − if (!isLmark(func)) | |
| 387 | − return NULL; /* not an active Lua function */ | |
| 388 | − else { | |
| 389 | − Proto *p = infovalue(func)->func->f.l; | |
| 390 | − int pc = currentpc(func); | |
| 391 | − int stackpos = obj - (func+1); /* func+1 == function base */ | |
| 392 | − Instruction i = luaG_symbexec(p, pc, stackpos); | |
| 393 | − LUA_ASSERT(pc != -1, "function must be active"); | |
| 435 | +/* }====================================================== */ | |
| 436 | + | |
| 437 | + | |
| 438 | +int luaG_checkcode (const Proto *pt) { | |
| 439 | + return luaG_symbexec(pt, pt->sizecode, NO_REG); | |
| 440 | +} | |
| 441 | + | |
| 442 | + | |
| 443 | +static const char *kname (Proto *p, int c) { | |
| 444 | + c = c - MAXSTACK; | |
| 445 | + if (c >= 0 && ttisstring(&p->k[c])) | |
| 446 | + return svalue(&p->k[c]); | |
| 447 | + else | |
| 448 | + return "?"; | |
| 449 | +} | |
| 450 | + | |
| 451 | + | |
| 452 | +static const char *getobjname (CallInfo *ci, int stackpos, const char **name) { | |
| 453 | + if (isLua(ci)) { /* a Lua function? */ | |
| 454 | + Proto *p = ci_func(ci)->l.p; | |
| 455 | + int pc = currentpc(ci); | |
| 456 | + Instruction i; | |
| 457 | + *name = luaF_getlocalname(p, stackpos+1, pc); | |
| 458 | + if (*name) /* is a local? */ | |
| 459 | + return "local"; | |
| 460 | + i = luaG_symbexec(p, pc, stackpos); /* try symbolic execution */ | |
| 461 | + lua_assert(pc != -1); | |
| 394 | 462 | switch (GET_OPCODE(i)) { |
| 395 | 463 | case OP_GETGLOBAL: { |
| 396 | − *name = p->kstr[GETARG_U(i)]->str; | |
| 464 | + int g = GETARG_Bx(i); /* global index */ | |
| 465 | + lua_assert(ttisstring(&p->k[g])); | |
| 466 | + *name = svalue(&p->k[g]); | |
| 397 | 467 | return "global"; |
| 398 | 468 | } |
| 399 | − case OP_GETLOCAL: { | |
| 400 | − *name = luaF_getlocalname(p, GETARG_U(i)+1, pc); | |
| 401 | − LUA_ASSERT(*name, "local must exist"); | |
| 402 | − return "local"; | |
| 469 | + case OP_MOVE: { | |
| 470 | + int a = GETARG_A(i); | |
| 471 | + int b = GETARG_B(i); /* move from `b' to `a' */ | |
| 472 | + if (b < a) | |
| 473 | + return getobjname(ci, b, name); /* get name for `b' */ | |
| 474 | + break; | |
| 403 | 475 | } |
| 404 | − case OP_PUSHSELF: | |
| 405 | − case OP_GETDOTTED: { | |
| 406 | − *name = p->kstr[GETARG_U(i)]->str; | |
| 476 | + case OP_GETTABLE: { | |
| 477 | + int k = GETARG_C(i); /* key index */ | |
| 478 | + *name = kname(p, k); | |
| 407 | 479 | return "field"; |
| 408 | 480 | } |
| 409 | − default: | |
| 410 | − return NULL; /* no useful name found */ | |
| 481 | + case OP_SELF: { | |
| 482 | + int k = GETARG_C(i); /* key index */ | |
| 483 | + *name = kname(p, k); | |
| 484 | + return "method"; | |
| 485 | + } | |
| 486 | + default: break; | |
| 411 | 487 | } |
| 412 | 488 | } |
| 489 | + return NULL; /* no useful name found */ | |
| 413 | 490 | } |
| 414 | 491 | |
| 415 | 492 | |
| 416 | −static const char *getfuncname (lua_State *L, StkId f, const char **name) { | |
| 417 | − StkId func = aux_stackedfunction(L, 0, f); /* calling function */ | |
| 418 | − if (!isLmark(func)) | |
| 419 | − return NULL; /* not an active Lua function */ | |
| 420 | − else { | |
| 421 | − Proto *p = infovalue(func)->func->f.l; | |
| 422 | − int pc = currentpc(func); | |
| 423 | − Instruction i; | |
| 424 | − if (pc == -1) return NULL; /* function is not activated */ | |
| 425 | − i = p->code[pc]; | |
| 426 | − switch (GET_OPCODE(i)) { | |
| 427 | − case OP_CALL: case OP_TAILCALL: | |
| 428 | − return getobjname(L, (func+1)+GETARG_A(i), name); | |
| 429 | − default: | |
| 430 | − return NULL; /* no useful name found */ | |
| 431 | − } | |
| 432 | − } | |
| 493 | +static const char *getfuncname (CallInfo *ci, const char **name) { | |
| 494 | + Instruction i; | |
| 495 | + if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1)) | |
| 496 | + return NULL; /* calling function is not Lua (or is unknown) */ | |
| 497 | + ci--; /* calling function */ | |
| 498 | + i = ci_func(ci)->l.p->code[currentpc(ci)]; | |
| 499 | + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL) | |
| 500 | + return getobjname(ci, GETARG_A(i), name); | |
| 501 | + else | |
| 502 | + return NULL; /* no useful name can be found */ | |
| 433 | 503 | } |
| 434 | 504 | |
| 435 | 505 | |
| 436 | −/* }====================================================== */ | |
| 506 | +/* only ANSI way to check whether a pointer points to an array */ | |
| 507 | +static int isinstack (CallInfo *ci, const TObject *o) { | |
| 508 | + StkId p; | |
| 509 | + for (p = ci->base; p < ci->top; p++) | |
| 510 | + if (o == p) return 1; | |
| 511 | + return 0; | |
| 512 | +} | |
| 437 | 513 | |
| 438 | 514 | |
| 439 | −void luaG_typeerror (lua_State *L, StkId o, const char *op) { | |
| 440 | − const char *name; | |
| 441 | − const char *kind = getobjname(L, o, &name); | |
| 442 | − const char *t = luaO_typename(o); | |
| 515 | +void luaG_typeerror (lua_State *L, const TObject *o, const char *op) { | |
| 516 | + const char *name = NULL; | |
| 517 | + const char *t = luaT_typenames[ttype(o)]; | |
| 518 | + const char *kind = (isinstack(L->ci, o)) ? | |
| 519 | + getobjname(L->ci, o - L->base, &name) : NULL; | |
| 443 | 520 | if (kind) |
| 444 | − luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", | |
| 521 | + luaG_runerror(L, "attempt to %s %s `%s' (a %s value)", | |
| 445 | 522 | op, kind, name, t); |
| 446 | 523 | else |
| 447 | − luaO_verror(L, "attempt to %.30s a %.10s value", op, t); | |
| 524 | + luaG_runerror(L, "attempt to %s a %s value", op, t); | |
| 525 | +} | |
| 526 | + | |
| 527 | + | |
| 528 | +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { | |
| 529 | + if (ttisstring(p1)) p1 = p2; | |
| 530 | + lua_assert(!ttisstring(p1)); | |
| 531 | + luaG_typeerror(L, p1, "concatenate"); | |
| 448 | 532 | } |
| 449 | 533 | |
| 450 | 534 | |
| 451 | −void luaG_binerror (lua_State *L, StkId p1, int t, const char *op) { | |
| 452 | − if (ttype(p1) == t) p1++; | |
| 453 | − LUA_ASSERT(ttype(p1) != t, "must be an error"); | |
| 454 | − luaG_typeerror(L, p1, op); | |
| 535 | +void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) { | |
| 536 | + TObject temp; | |
| 537 | + if (luaV_tonumber(p1, &temp) == NULL) | |
| 538 | + p2 = p1; /* first operand is wrong */ | |
| 539 | + luaG_typeerror(L, p2, "perform arithmetic on"); | |
| 455 | 540 | } |
| 456 | 541 | |
| 457 | 542 | |
| 458 | −void luaG_ordererror (lua_State *L, StkId top) { | |
| 459 | − const char *t1 = luaO_typename(top-2); | |
| 460 | − const char *t2 = luaO_typename(top-1); | |
| 543 | +int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { | |
| 544 | + const char *t1 = luaT_typenames[ttype(p1)]; | |
| 545 | + const char *t2 = luaT_typenames[ttype(p2)]; | |
| 461 | 546 | if (t1[2] == t2[2]) |
| 462 | − luaO_verror(L, "attempt to compare two %.10s values", t1); | |
| 547 | + luaG_runerror(L, "attempt to compare two %s values", t1); | |
| 463 | 548 | else |
| 464 | − luaO_verror(L, "attempt to compare %.10s with %.10s", t1, t2); | |
| 549 | + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); | |
| 550 | + return 0; | |
| 551 | +} | |
| 552 | + | |
| 553 | + | |
| 554 | +static void addinfo (lua_State *L, const char *msg) { | |
| 555 | + CallInfo *ci = L->ci; | |
| 556 | + if (isLua(ci)) { /* is Lua code? */ | |
| 557 | + char buff[LUA_IDSIZE]; /* add file:line information */ | |
| 558 | + int line = currentline(ci); | |
| 559 | + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); | |
| 560 | + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); | |
| 561 | + } | |
| 562 | +} | |
| 563 | + | |
| 564 | + | |
| 565 | +void luaG_errormsg (lua_State *L) { | |
| 566 | + if (L->errfunc != 0) { /* is there an error handling function? */ | |
| 567 | + StkId errfunc = restorestack(L, L->errfunc); | |
| 568 | + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); | |
| 569 | + setobjs2s(L->top, L->top - 1); /* move argument */ | |
| 570 | + setobjs2s(L->top - 1, errfunc); /* push function */ | |
| 571 | + incr_top(L); | |
| 572 | + luaD_call(L, L->top - 2, 1); /* call it */ | |
| 573 | + } | |
| 574 | + luaD_throw(L, LUA_ERRRUN); | |
| 575 | +} | |
| 576 | + | |
| 577 | + | |
| 578 | +void luaG_runerror (lua_State *L, const char *fmt, ...) { | |
| 579 | + va_list argp; | |
| 580 | + va_start(argp, fmt); | |
| 581 | + addinfo(L, luaO_pushvfstring(L, fmt, argp)); | |
| 582 | + va_end(argp); | |
| 583 | + luaG_errormsg(L); | |
| 465 | 584 | } |
| 466 | 585 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldebug.h,v 1.7 2000/10/05 12:14:08 roberto Exp $ | |
| 2 | +** $Id: ldebug.h,v 1.32 2002/11/18 11:01:55 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions from Debug Interface module |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -9,13 +9,23 @@ · 3 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | #include "lstate.h" |
| 12 | −#include "luadebug.h" | |
| 13 | 12 | |
| 14 | 13 | |
| 15 | −void luaG_typeerror (lua_State *L, StkId o, const char *op); | |
| 16 | −void luaG_binerror (lua_State *L, StkId p1, int t, const char *op); | |
| 17 | −int luaG_getline (int *lineinfo, int pc, int refline, int *refi); | |
| 18 | −void luaG_ordererror (lua_State *L, StkId top); | |
| 14 | +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) | |
| 15 | + | |
| 16 | +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) | |
| 17 | + | |
| 18 | +#define resethookcount(L) (L->hookcount = L->basehookcount) | |
| 19 | + | |
| 20 | + | |
| 21 | +void luaG_inithooks (lua_State *L); | |
| 22 | +void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); | |
| 23 | +void luaG_concaterror (lua_State *L, StkId p1, StkId p2); | |
| 24 | +void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2); | |
| 25 | +int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); | |
| 26 | +void luaG_runerror (lua_State *L, const char *fmt, ...); | |
| 27 | +void luaG_errormsg (lua_State *L); | |
| 28 | +int luaG_checkcode (const Proto *pt); | |
| 19 | 29 | |
| 20 | 30 | |
| 21 | 31 | #endif |
| @@ -1,22 +1,25 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldo.c,v 1.109a 2000/10/30 12:38:50 roberto Exp $ | |
| 2 | +** $Id: ldo.c,v 1.217 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Stack and Call structure of Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | #include <setjmp.h> |
| 9 | −#include <stdio.h> | |
| 10 | 9 | #include <stdlib.h> |
| 11 | 10 | #include <string.h> |
| 12 | 11 | |
| 12 | +#define ldo_c | |
| 13 | + | |
| 13 | 14 | #include "lua.h" |
| 14 | 15 | |
| 15 | 16 | #include "ldebug.h" |
| 16 | 17 | #include "ldo.h" |
| 18 | +#include "lfunc.h" | |
| 17 | 19 | #include "lgc.h" |
| 18 | 20 | #include "lmem.h" |
| 19 | 21 | #include "lobject.h" |
| 22 | +#include "lopcodes.h" | |
| 20 | 23 | #include "lparser.h" |
| 21 | 24 | #include "lstate.h" |
| 22 | 25 | #include "lstring.h" |
| @@ -27,362 +30,429 @@ · 4 unmodified lines | ||
| 27 | 30 | #include "lzio.h" |
| 28 | 31 | |
| 29 | 32 | |
| 30 | −/* space to handle stack overflow errors */ | |
| 31 | −#define EXTRA_STACK (2*LUA_MINSTACK) | |
| 32 | 33 | |
| 33 | 34 | |
| 34 | −void luaD_init (lua_State *L, int stacksize) { | |
| 35 | − L->stack = luaM_newvector(L, stacksize+EXTRA_STACK, TObject); | |
| 36 | − L->nblocks += stacksize*sizeof(TObject); | |
| 37 | − L->stack_last = L->stack+(stacksize-1); | |
| 38 | − L->stacksize = stacksize; | |
| 39 | − L->Cbase = L->top = L->stack; | |
| 40 | −} | |
| 35 | +/* | |
| 36 | +** {====================================================== | |
| 37 | +** Error-recovery functions (based on long jumps) | |
| 38 | +** ======================================================= | |
| 39 | +*/ | |
| 41 | 40 | |
| 42 | 41 | |
| 43 | −void luaD_checkstack (lua_State *L, int n) { | |
| 44 | − if (L->stack_last - L->top <= n) { /* stack overflow? */ | |
| 45 | − if (L->stack_last-L->stack > (L->stacksize-1)) { | |
| 46 | − /* overflow while handling overflow */ | |
| 47 | − luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ | |
| 42 | +/* chain list of long jump buffers */ | |
| 43 | +struct lua_longjmp { | |
| 44 | + struct lua_longjmp *previous; | |
| 45 | + jmp_buf b; | |
| 46 | + volatile int status; /* error code */ | |
| 47 | +}; | |
| 48 | + | |
| 49 | + | |
| 50 | +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |
| 51 | + switch (errcode) { | |
| 52 | + case LUA_ERRMEM: { | |
| 53 | + setsvalue2s(oldtop, luaS_new(L, MEMERRMSG)); | |
| 54 | + break; | |
| 55 | + } | |
| 56 | + case LUA_ERRERR: { | |
| 57 | + setsvalue2s(oldtop, luaS_new(L, "error in error handling")); | |
| 58 | + break; | |
| 48 | 59 | } |
| 49 | − else { | |
| 50 | − L->stack_last += EXTRA_STACK; /* to be used by error message */ | |
| 51 | − lua_error(L, "stack overflow"); | |
| 60 | + case LUA_ERRSYNTAX: | |
| 61 | + case LUA_ERRRUN: { | |
| 62 | + setobjs2s(oldtop, L->top - 1); /* error message on current top */ | |
| 63 | + break; | |
| 52 | 64 | } |
| 53 | 65 | } |
| 66 | + L->top = oldtop + 1; | |
| 67 | +} | |
| 68 | + | |
| 69 | + | |
| 70 | +void luaD_throw (lua_State *L, int errcode) { | |
| 71 | + if (L->errorJmp) { | |
| 72 | + L->errorJmp->status = errcode; | |
| 73 | + longjmp(L->errorJmp->b, 1); | |
| 74 | + } | |
| 75 | + else { | |
| 76 | + G(L)->panic(L); | |
| 77 | + exit(EXIT_FAILURE); | |
| 78 | + } | |
| 79 | +} | |
| 80 | + | |
| 81 | + | |
| 82 | +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |
| 83 | + struct lua_longjmp lj; | |
| 84 | + lj.status = 0; | |
| 85 | + lj.previous = L->errorJmp; /* chain new error handler */ | |
| 86 | + L->errorJmp = &lj; | |
| 87 | + if (setjmp(lj.b) == 0) | |
| 88 | + (*f)(L, ud); | |
| 89 | + L->errorJmp = lj.previous; /* restore old error handler */ | |
| 90 | + return lj.status; | |
| 54 | 91 | } |
| 55 | 92 | |
| 56 | 93 | |
| 57 | 94 | static void restore_stack_limit (lua_State *L) { |
| 58 | − if (L->top - L->stack < L->stacksize - 1) | |
| 59 | − L->stack_last = L->stack + (L->stacksize-1); | |
| 95 | + L->stack_last = L->stack+L->stacksize-1; | |
| 96 | + if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */ | |
| 97 | + int inuse = (L->ci - L->base_ci); | |
| 98 | + if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */ | |
| 99 | + luaD_reallocCI(L, LUA_MAXCALLS); | |
| 100 | + } | |
| 60 | 101 | } |
| 61 | 102 | |
| 103 | +/* }====================================================== */ | |
| 62 | 104 | |
| 63 | −/* | |
| 64 | −** Adjust stack. Set top to base+extra, pushing NILs if needed. | |
| 65 | −** (we cannot add base+extra unless we are sure it fits in the stack; | |
| 66 | −** otherwise the result of such operation on pointers is undefined) | |
| 67 | −*/ | |
| 68 | −void luaD_adjusttop (lua_State *L, StkId base, int extra) { | |
| 69 | − int diff = extra-(L->top-base); | |
| 70 | − if (diff <= 0) | |
| 71 | − L->top = base+extra; | |
| 72 | − else { | |
| 73 | − luaD_checkstack(L, diff); | |
| 74 | − while (diff--) | |
| 75 | − ttype(L->top++) = LUA_TNIL; | |
| 105 | + | |
| 106 | +static void correctstack (lua_State *L, TObject *oldstack) { | |
| 107 | + CallInfo *ci; | |
| 108 | + GCObject *up; | |
| 109 | + L->top = (L->top - oldstack) + L->stack; | |
| 110 | + for (up = L->openupval; up != NULL; up = up->gch.next) | |
| 111 | + gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack; | |
| 112 | + for (ci = L->base_ci; ci <= L->ci; ci++) { | |
| 113 | + ci->top = (ci->top - oldstack) + L->stack; | |
| 114 | + ci->base = (ci->base - oldstack) + L->stack; | |
| 76 | 115 | } |
| 116 | + L->base = L->ci->base; | |
| 77 | 117 | } |
| 78 | 118 | |
| 79 | 119 | |
| 80 | −/* | |
| 81 | −** Open a hole inside the stack at `pos' | |
| 82 | −*/ | |
| 83 | −static void luaD_openstack (lua_State *L, StkId pos) { | |
| 84 | − int i = L->top-pos; | |
| 85 | − while (i--) pos[i+1] = pos[i]; | |
| 86 | − incr_top; | |
| 120 | +void luaD_reallocstack (lua_State *L, int newsize) { | |
| 121 | + TObject *oldstack = L->stack; | |
| 122 | + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject); | |
| 123 | + L->stacksize = newsize; | |
| 124 | + L->stack_last = L->stack+newsize-1-EXTRA_STACK; | |
| 125 | + correctstack(L, oldstack); | |
| 87 | 126 | } |
| 88 | 127 | |
| 89 | 128 | |
| 90 | −static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { | |
| 91 | − StkId old_Cbase = L->Cbase; | |
| 92 | − StkId old_top = L->Cbase = L->top; | |
| 93 | − luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | |
| 94 | − L->allowhooks = 0; /* cannot call hooks inside a hook */ | |
| 95 | − (*hook)(L, ar); | |
| 96 | − LUA_ASSERT(L->allowhooks == 0, "invalid allow"); | |
| 97 | − L->allowhooks = 1; | |
| 98 | − L->top = old_top; | |
| 99 | − L->Cbase = old_Cbase; | |
| 129 | +void luaD_reallocCI (lua_State *L, int newsize) { | |
| 130 | + CallInfo *oldci = L->base_ci; | |
| 131 | + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); | |
| 132 | + L->size_ci = cast(unsigned short, newsize); | |
| 133 | + L->ci = (L->ci - oldci) + L->base_ci; | |
| 134 | + L->end_ci = L->base_ci + L->size_ci; | |
| 100 | 135 | } |
| 101 | 136 | |
| 102 | 137 | |
| 103 | −void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook) { | |
| 104 | − if (L->allowhooks) { | |
| 105 | − lua_Debug ar; | |
| 106 | − ar._func = func; | |
| 107 | − ar.event = "line"; | |
| 108 | − ar.currentline = line; | |
| 109 | − dohook(L, &ar, linehook); | |
| 138 | +void luaD_growstack (lua_State *L, int n) { | |
| 139 | + if (n <= L->stacksize) /* double size is enough? */ | |
| 140 | + luaD_reallocstack(L, 2*L->stacksize); | |
| 141 | + else | |
| 142 | + luaD_reallocstack(L, L->stacksize + n + EXTRA_STACK); | |
| 143 | +} | |
| 144 | + | |
| 145 | + | |
| 146 | +static void luaD_growCI (lua_State *L) { | |
| 147 | + if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ | |
| 148 | + luaD_throw(L, LUA_ERRERR); | |
| 149 | + else { | |
| 150 | + luaD_reallocCI(L, 2*L->size_ci); | |
| 151 | + if (L->size_ci > LUA_MAXCALLS) | |
| 152 | + luaG_runerror(L, "stack overflow"); | |
| 110 | 153 | } |
| 111 | 154 | } |
| 112 | 155 | |
| 113 | 156 | |
| 114 | −static void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, | |
| 115 | − const char *event) { | |
| 116 | − if (L->allowhooks) { | |
| 157 | +void luaD_callhook (lua_State *L, int event, int line) { | |
| 158 | + lua_Hook hook = L->hook; | |
| 159 | + if (hook && L->allowhook) { | |
| 160 | + ptrdiff_t top = savestack(L, L->top); | |
| 161 | + ptrdiff_t ci_top = savestack(L, L->ci->top); | |
| 117 | 162 | lua_Debug ar; |
| 118 | − ar._func = func; | |
| 119 | 163 | ar.event = event; |
| 120 | − infovalue(func)->pc = NULL; /* function is not active */ | |
| 121 | − dohook(L, &ar, callhook); | |
| 164 | + ar.currentline = line; | |
| 165 | + if (event == LUA_HOOKTAILRET) | |
| 166 | + ar.i_ci = 0; /* tail call; no debug information about it */ | |
| 167 | + else | |
| 168 | + ar.i_ci = L->ci - L->base_ci; | |
| 169 | + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | |
| 170 | + L->ci->top = L->top + LUA_MINSTACK; | |
| 171 | + L->allowhook = 0; /* cannot call hooks inside a hook */ | |
| 172 | + lua_unlock(L); | |
| 173 | + (*hook)(L, &ar); | |
| 174 | + lua_lock(L); | |
| 175 | + lua_assert(!L->allowhook); | |
| 176 | + L->allowhook = 1; | |
| 177 | + L->ci->top = restorestack(L, ci_top); | |
| 178 | + L->top = restorestack(L, top); | |
| 122 | 179 | } |
| 123 | 180 | } |
| 124 | 181 | |
| 125 | 182 | |
| 126 | −static StkId callCclosure (lua_State *L, const struct Closure *cl, StkId base) { | |
| 127 | − int nup = cl->nupvalues; /* number of upvalues */ | |
| 128 | − StkId old_Cbase = L->Cbase; | |
| 129 | − int n; | |
| 130 | − L->Cbase = base; /* new base for C function */ | |
| 131 | − luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */ | |
| 132 | − for (n=0; n<nup; n++) /* copy upvalues as extra arguments */ | |
| 133 | − *(L->top++) = cl->upvalue[n]; | |
| 134 | − n = (*cl->f.c)(L); /* do the actual call */ | |
| 135 | − L->Cbase = old_Cbase; /* restore old C base */ | |
| 136 | − return L->top - n; /* return index of first result */ | |
| 183 | +static void adjust_varargs (lua_State *L, int nfixargs, StkId base) { | |
| 184 | + int i; | |
| 185 | + Table *htab; | |
| 186 | + TObject nname; | |
| 187 | + int actual = L->top - base; /* actual number of arguments */ | |
| 188 | + if (actual < nfixargs) { | |
| 189 | + luaD_checkstack(L, nfixargs - actual); | |
| 190 | + for (; actual < nfixargs; ++actual) | |
| 191 | + setnilvalue(L->top++); | |
| 192 | + } | |
| 193 | + actual -= nfixargs; /* number of extra arguments */ | |
| 194 | + htab = luaH_new(L, actual, 1); /* create `arg' table */ | |
| 195 | + for (i=0; i<actual; i++) /* put extra arguments into `arg' table */ | |
| 196 | + setobj2n(luaH_setnum(L, htab, i+1), L->top - actual + i); | |
| 197 | + /* store counter in field `n' */ | |
| 198 | + setsvalue(&nname, luaS_newliteral(L, "n")); | |
| 199 | + setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual)); | |
| 200 | + L->top -= actual; /* remove extra elements from the stack */ | |
| 201 | + sethvalue(L->top, htab); | |
| 202 | + incr_top(L); | |
| 137 | 203 | } |
| 138 | 204 | |
| 139 | 205 | |
| 140 | −void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults) { | |
| 141 | − StkId base = L->top - nParams; | |
| 142 | − luaD_openstack(L, base); | |
| 143 | − clvalue(base) = f; | |
| 144 | − ttype(base) = LUA_TFUNCTION; | |
| 145 | − luaD_call(L, base, nResults); | |
| 206 | +static StkId tryfuncTM (lua_State *L, StkId func) { | |
| 207 | + const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); | |
| 208 | + StkId p; | |
| 209 | + ptrdiff_t funcr = savestack(L, func); | |
| 210 | + if (!ttisfunction(tm)) | |
| 211 | + luaG_typeerror(L, func, "call"); | |
| 212 | + /* Open a hole inside the stack at `func' */ | |
| 213 | + for (p = L->top; p > func; p--) setobjs2s(p, p-1); | |
| 214 | + incr_top(L); | |
| 215 | + func = restorestack(L, funcr); /* previous call may change stack */ | |
| 216 | + setobj2s(func, tm); /* tag method is the new function to be called */ | |
| 217 | + return func; | |
| 146 | 218 | } |
| 147 | 219 | |
| 148 | 220 | |
| 149 | −/* | |
| 150 | −** Call a function (C or Lua). The function to be called is at *func. | |
| 151 | −** The arguments are on the stack, right after the function. | |
| 152 | −** When returns, the results are on the stack, starting at the original | |
| 153 | −** function position. | |
| 154 | −** The number of results is nResults, unless nResults=LUA_MULTRET. | |
| 155 | −*/ | |
| 156 | −void luaD_call (lua_State *L, StkId func, int nResults) { | |
| 157 | − lua_Hook callhook; | |
| 158 | − StkId firstResult; | |
| 159 | − CallInfo ci; | |
| 160 | − Closure *cl; | |
| 161 | − if (ttype(func) != LUA_TFUNCTION) { | |
| 162 | − /* `func' is not a function; check the `function' tag method */ | |
| 163 | − Closure *tm = luaT_gettmbyObj(L, func, TM_FUNCTION); | |
| 164 | − if (tm == NULL) | |
| 165 | − luaG_typeerror(L, func, "call"); | |
| 166 | − luaD_openstack(L, func); | |
| 167 | − clvalue(func) = tm; /* tag method is the new function to be called */ | |
| 168 | − ttype(func) = LUA_TFUNCTION; | |
| 221 | +StkId luaD_precall (lua_State *L, StkId func) { | |
| 222 | + LClosure *cl; | |
| 223 | + ptrdiff_t funcr = savestack(L, func); | |
| 224 | + if (!ttisfunction(func)) /* `func' is not a function? */ | |
| 225 | + func = tryfuncTM(L, func); /* check the `function' tag method */ | |
| 226 | + if (L->ci + 1 == L->end_ci) luaD_growCI(L); | |
| 227 | + else condhardstacktests(luaD_reallocCI(L, L->size_ci)); | |
| 228 | + cl = &clvalue(func)->l; | |
| 229 | + if (!cl->isC) { /* Lua function? prepare its call */ | |
| 230 | + CallInfo *ci; | |
| 231 | + Proto *p = cl->p; | |
| 232 | + if (p->is_vararg) /* varargs? */ | |
| 233 | + adjust_varargs(L, p->numparams, func+1); | |
| 234 | + luaD_checkstack(L, p->maxstacksize); | |
| 235 | + ci = ++L->ci; /* now `enter' new function */ | |
| 236 | + L->base = L->ci->base = restorestack(L, funcr) + 1; | |
| 237 | + ci->top = L->base + p->maxstacksize; | |
| 238 | + ci->u.l.savedpc = p->code; /* starting point */ | |
| 239 | + ci->u.l.tailcalls = 0; | |
| 240 | + ci->state = CI_SAVEDPC; | |
| 241 | + while (L->top < ci->top) | |
| 242 | + setnilvalue(L->top++); | |
| 243 | + L->top = ci->top; | |
| 244 | + return NULL; | |
| 169 | 245 | } |
| 170 | − cl = clvalue(func); | |
| 171 | − ci.func = cl; | |
| 172 | − infovalue(func) = &ci; | |
| 173 | − ttype(func) = LUA_TMARK; | |
| 174 | − callhook = L->callhook; | |
| 175 | − if (callhook) | |
| 176 | − luaD_callHook(L, func, callhook, "call"); | |
| 177 | − firstResult = (cl->isC ? callCclosure(L, cl, func+1) : | |
| 178 | − luaV_execute(L, cl, func+1)); | |
| 179 | − if (callhook) /* same hook that was active at entry */ | |
| 180 | − luaD_callHook(L, func, callhook, "return"); | |
| 181 | − LUA_ASSERT(ttype(func) == LUA_TMARK, "invalid tag"); | |
| 182 | − /* move results to `func' (to erase parameters and function) */ | |
| 183 | − if (nResults == LUA_MULTRET) { | |
| 184 | − while (firstResult < L->top) /* copy all results */ | |
| 185 | − *func++ = *firstResult++; | |
| 186 | − L->top = func; | |
| 246 | + else { /* if is a C function, call it */ | |
| 247 | + CallInfo *ci; | |
| 248 | + int n; | |
| 249 | + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | |
| 250 | + ci = ++L->ci; /* now `enter' new function */ | |
| 251 | + L->base = L->ci->base = restorestack(L, funcr) + 1; | |
| 252 | + ci->top = L->top + LUA_MINSTACK; | |
| 253 | + ci->state = CI_C; /* a C function */ | |
| 254 | + if (L->hookmask & LUA_MASKCALL) | |
| 255 | + luaD_callhook(L, LUA_HOOKCALL, -1); | |
| 256 | + lua_unlock(L); | |
| 257 | +#ifdef LUA_COMPATUPVALUES | |
| 258 | + lua_pushupvalues(L); | |
| 259 | +#endif | |
| 260 | + n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */ | |
| 261 | + lua_lock(L); | |
| 262 | + return L->top - n; | |
| 187 | 263 | } |
| 188 | − else { /* copy at most `nResults' */ | |
| 189 | − for (; nResults > 0 && firstResult < L->top; nResults--) | |
| 190 | − *func++ = *firstResult++; | |
| 191 | − L->top = func; | |
| 192 | − for (; nResults > 0; nResults--) { /* if there are not enough results */ | |
| 193 | − ttype(L->top) = LUA_TNIL; /* adjust the stack */ | |
| 194 | − incr_top; /* must check stack space */ | |
| 195 | − } | |
| 196 | − } | |
| 197 | − luaC_checkGC(L); | |
| 198 | 264 | } |
| 199 | 265 | |
| 200 | 266 | |
| 201 | −/* | |
| 202 | −** Execute a protected call. | |
| 203 | −*/ | |
| 204 | −struct CallS { /* data to `f_call' */ | |
| 205 | − StkId func; | |
| 206 | − int nresults; | |
| 207 | −}; | |
| 208 | − | |
| 209 | −static void f_call (lua_State *L, void *ud) { | |
| 210 | − struct CallS *c = (struct CallS *)ud; | |
| 211 | − luaD_call(L, c->func, c->nresults); | |
| 267 | +static StkId callrethooks (lua_State *L, StkId firstResult) { | |
| 268 | + ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | |
| 269 | + luaD_callhook(L, LUA_HOOKRET, -1); | |
| 270 | + if (!(L->ci->state & CI_C)) { /* Lua function? */ | |
| 271 | + while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ | |
| 272 | + luaD_callhook(L, LUA_HOOKTAILRET, -1); | |
| 273 | + } | |
| 274 | + return restorestack(L, fr); | |
| 212 | 275 | } |
| 213 | 276 | |
| 214 | 277 | |
| 215 | −LUA_API int lua_call (lua_State *L, int nargs, int nresults) { | |
| 216 | − StkId func = L->top - (nargs+1); /* function to be called */ | |
| 217 | − struct CallS c; | |
| 218 | − int status; | |
| 219 | − c.func = func; c.nresults = nresults; | |
| 220 | − status = luaD_runprotected(L, f_call, &c); | |
| 221 | − if (status != 0) /* an error occurred? */ | |
| 222 | − L->top = func; /* remove parameters from the stack */ | |
| 223 | − return status; | |
| 278 | +void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | |
| 279 | + StkId res; | |
| 280 | + if (L->hookmask & LUA_MASKRET) | |
| 281 | + firstResult = callrethooks(L, firstResult); | |
| 282 | + res = L->base - 1; /* res == final position of 1st result */ | |
| 283 | + L->ci--; | |
| 284 | + L->base = L->ci->base; /* restore base */ | |
| 285 | + /* move results to correct place */ | |
| 286 | + while (wanted != 0 && firstResult < L->top) { | |
| 287 | + setobjs2s(res++, firstResult++); | |
| 288 | + wanted--; | |
| 289 | + } | |
| 290 | + while (wanted-- > 0) | |
| 291 | + setnilvalue(res++); | |
| 292 | + L->top = res; | |
| 224 | 293 | } |
| 225 | 294 | |
| 226 | 295 | |
| 227 | 296 | /* |
| 228 | −** Execute a protected parser. | |
| 229 | −*/ | |
| 230 | −struct ParserS { /* data to `f_parser' */ | |
| 231 | − ZIO *z; | |
| 232 | − int bin; | |
| 233 | −}; | |
| 234 | − | |
| 235 | −static void f_parser (lua_State *L, void *ud) { | |
| 236 | − struct ParserS *p = (struct ParserS *)ud; | |
| 237 | − Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); | |
| 238 | − luaV_Lclosure(L, tf, 0); | |
| 297 | +** Call a function (C or Lua). The function to be called is at *func. | |
| 298 | +** The arguments are on the stack, right after the function. | |
| 299 | +** When returns, all the results are on the stack, starting at the original | |
| 300 | +** function position. | |
| 301 | +*/ | |
| 302 | +void luaD_call (lua_State *L, StkId func, int nResults) { | |
| 303 | + StkId firstResult; | |
| 304 | + lua_assert(!(L->ci->state & CI_CALLING)); | |
| 305 | + if (++L->nCcalls >= LUA_MAXCCALLS) { | |
| 306 | + if (L->nCcalls == LUA_MAXCCALLS) | |
| 307 | + luaG_runerror(L, "C stack overflow"); | |
| 308 | + else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) | |
| 309 | + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | |
| 310 | + } | |
| 311 | + firstResult = luaD_precall(L, func); | |
| 312 | + if (firstResult == NULL) /* is a Lua function? */ | |
| 313 | + firstResult = luaV_execute(L); /* call it */ | |
| 314 | + luaD_poscall(L, nResults, firstResult); | |
| 315 | + L->nCcalls--; | |
| 316 | + luaC_checkGC(L); | |
| 239 | 317 | } |
| 240 | 318 | |
| 241 | 319 | |
| 242 | −static int protectedparser (lua_State *L, ZIO *z, int bin) { | |
| 243 | − struct ParserS p; | |
| 244 | − unsigned long old_blocks; | |
| 245 | − int status; | |
| 246 | − p.z = z; p.bin = bin; | |
| 247 | − /* before parsing, give a (good) chance to GC */ | |
| 248 | − if (L->nblocks/8 >= L->GCthreshold/10) | |
| 249 | − luaC_collectgarbage(L); | |
| 250 | − old_blocks = L->nblocks; | |
| 251 | − status = luaD_runprotected(L, f_parser, &p); | |
| 252 | − if (status == 0) { | |
| 253 | − /* add new memory to threshold (as it probably will stay) */ | |
| 254 | − L->GCthreshold += (L->nblocks - old_blocks); | |
| 320 | +static void resume (lua_State *L, void *ud) { | |
| 321 | + StkId firstResult; | |
| 322 | + int nargs = *cast(int *, ud); | |
| 323 | + CallInfo *ci = L->ci; | |
| 324 | + if (ci == L->base_ci) { /* no activation record? */ | |
| 325 | + if (nargs >= L->top - L->base) | |
| 326 | + luaG_runerror(L, "cannot resume dead coroutine"); | |
| 327 | + luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | |
| 255 | 328 | } |
| 256 | − else if (status == LUA_ERRRUN) /* an error occurred: correct error code */ | |
| 257 | − status = LUA_ERRSYNTAX; | |
| 258 | − return status; | |
| 329 | + else if (ci->state & CI_YIELD) { /* inside a yield? */ | |
| 330 | + if (ci->state & CI_C) { /* `common' yield? */ | |
| 331 | + /* finish interrupted execution of `OP_CALL' */ | |
| 332 | + int nresults; | |
| 333 | + lua_assert((ci-1)->state & CI_SAVEDPC); | |
| 334 | + lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | |
| 335 | + GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | |
| 336 | + nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | |
| 337 | + luaD_poscall(L, nresults, L->top - nargs); /* complete it */ | |
| 338 | + if (nresults >= 0) L->top = L->ci->top; | |
| 339 | + } | |
| 340 | + else { /* yielded inside a hook: just continue its execution */ | |
| 341 | + ci->state &= ~CI_YIELD; | |
| 342 | + } | |
| 343 | + } | |
| 344 | + else | |
| 345 | + luaG_runerror(L, "cannot resume non-suspended coroutine"); | |
| 346 | + firstResult = luaV_execute(L); | |
| 347 | + if (firstResult != NULL) /* return? */ | |
| 348 | + luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ | |
| 259 | 349 | } |
| 260 | 350 | |
| 261 | 351 | |
| 262 | −static int parse_file (lua_State *L, const char *filename) { | |
| 263 | − ZIO z; | |
| 352 | +LUA_API int lua_resume (lua_State *L, int nargs) { | |
| 264 | 353 | int status; |
| 265 | − int bin; /* flag for file mode */ | |
| 266 | − int c; /* look ahead char */ | |
| 267 | − FILE *f = (filename == NULL) ? stdin : fopen(filename, "r"); | |
| 268 | − if (f == NULL) return LUA_ERRFILE; /* unable to open file */ | |
| 269 | − c = fgetc(f); | |
| 270 | − ungetc(c, f); | |
| 271 | − bin = (c == ID_CHUNK); | |
| 272 | − if (bin && f != stdin) { | |
| 273 | − f = freopen(filename, "rb", f); /* set binary mode */ | |
| 274 | − if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ | |
| 354 | + lu_byte old_allowhooks; | |
| 355 | + lua_lock(L); | |
| 356 | + old_allowhooks = L->allowhook; | |
| 357 | + lua_assert(L->errfunc == 0 && L->nCcalls == 0); | |
| 358 | + status = luaD_rawrunprotected(L, resume, &nargs); | |
| 359 | + if (status != 0) { /* error? */ | |
| 360 | + L->ci = L->base_ci; /* go back to initial level */ | |
| 361 | + L->base = L->ci->base; | |
| 362 | + L->nCcalls = 0; | |
| 363 | + luaF_close(L, L->base); /* close eventual pending closures */ | |
| 364 | + seterrorobj(L, status, L->base); | |
| 365 | + L->allowhook = old_allowhooks; | |
| 366 | + restore_stack_limit(L); | |
| 275 | 367 | } |
| 276 | − lua_pushstring(L, "@"); | |
| 277 | − lua_pushstring(L, (filename == NULL) ? "(stdin)" : filename); | |
| 278 | − lua_concat(L, 2); | |
| 279 | − c = lua_gettop(L); | |
| 280 | − filename = lua_tostring(L, c); /* filename = '@'..filename */ | |
| 281 | − luaZ_Fopen(&z, f, filename); | |
| 282 | − status = protectedparser(L, &z, bin); | |
| 283 | − lua_remove(L, c); /* remove `filename' from the stack */ | |
| 284 | − if (f != stdin) | |
| 285 | − fclose(f); | |
| 286 | − return status; | |
| 287 | −} | |
| 288 | − | |
| 289 | − | |
| 290 | −LUA_API int lua_dofile (lua_State *L, const char *filename) { | |
| 291 | − int status = parse_file(L, filename); | |
| 292 | − if (status == 0) /* parse OK? */ | |
| 293 | − status = lua_call(L, 0, LUA_MULTRET); /* call main */ | |
| 368 | + lua_unlock(L); | |
| 294 | 369 | return status; |
| 295 | 370 | } |
| 296 | 371 | |
| 297 | 372 | |
| 298 | −static int parse_buffer (lua_State *L, const char *buff, size_t size, | |
| 299 | − const char *name) { | |
| 300 | − ZIO z; | |
| 301 | − if (!name) name = "?"; | |
| 302 | − luaZ_mopen(&z, buff, size, name); | |
| 303 | − return protectedparser(L, &z, buff[0]==ID_CHUNK); | |
| 373 | +LUA_API int lua_yield (lua_State *L, int nresults) { | |
| 374 | + CallInfo *ci; | |
| 375 | + lua_lock(L); | |
| 376 | + ci = L->ci; | |
| 377 | + if (L->nCcalls > 0) | |
| 378 | + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); | |
| 379 | + if (ci->state & CI_C) { /* usual yield */ | |
| 380 | + if ((ci-1)->state & CI_C) | |
| 381 | + luaG_runerror(L, "cannot yield a C function"); | |
| 382 | + if (L->top - nresults > L->base) { /* is there garbage in the stack? */ | |
| 383 | + int i; | |
| 384 | + for (i=0; i<nresults; i++) /* move down results */ | |
| 385 | + setobjs2s(L->base + i, L->top - nresults + i); | |
| 386 | + L->top = L->base + nresults; | |
| 387 | + } | |
| 388 | + } /* else it's an yield inside a hook: nothing to do */ | |
| 389 | + ci->state |= CI_YIELD; | |
| 390 | + lua_unlock(L); | |
| 391 | + return -1; | |
| 304 | 392 | } |
| 305 | 393 | |
| 306 | 394 | |
| 307 | −LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name) { | |
| 308 | − int status = parse_buffer(L, buff, size, name); | |
| 309 | − if (status == 0) /* parse OK? */ | |
| 310 | − status = lua_call(L, 0, LUA_MULTRET); /* call main */ | |
| 395 | +int luaD_pcall (lua_State *L, Pfunc func, void *u, | |
| 396 | + ptrdiff_t old_top, ptrdiff_t ef) { | |
| 397 | + int status; | |
| 398 | + unsigned short oldnCcalls = L->nCcalls; | |
| 399 | + ptrdiff_t old_ci = saveci(L, L->ci); | |
| 400 | + lu_byte old_allowhooks = L->allowhook; | |
| 401 | + ptrdiff_t old_errfunc = L->errfunc; | |
| 402 | + L->errfunc = ef; | |
| 403 | + status = luaD_rawrunprotected(L, func, u); | |
| 404 | + if (status != 0) { /* an error occurred? */ | |
| 405 | + StkId oldtop = restorestack(L, old_top); | |
| 406 | + luaF_close(L, oldtop); /* close eventual pending closures */ | |
| 407 | + seterrorobj(L, status, oldtop); | |
| 408 | + L->nCcalls = oldnCcalls; | |
| 409 | + L->ci = restoreci(L, old_ci); | |
| 410 | + L->base = L->ci->base; | |
| 411 | + L->allowhook = old_allowhooks; | |
| 412 | + restore_stack_limit(L); | |
| 413 | + } | |
| 414 | + L->errfunc = old_errfunc; | |
| 311 | 415 | return status; |
| 312 | 416 | } |
| 313 | 417 | |
| 314 | 418 | |
| 315 | −LUA_API int lua_dostring (lua_State *L, const char *str) { | |
| 316 | − return lua_dobuffer(L, str, strlen(str), str); | |
| 317 | −} | |
| 318 | − | |
| 319 | 419 | |
| 320 | 420 | /* |
| 321 | −** {====================================================== | |
| 322 | −** Error-recover functions (based on long jumps) | |
| 323 | −** ======================================================= | |
| 421 | +** Execute a protected parser. | |
| 324 | 422 | */ |
| 325 | − | |
| 326 | −/* chain list of long jump buffers */ | |
| 327 | −struct lua_longjmp { | |
| 328 | − jmp_buf b; | |
| 329 | − struct lua_longjmp *previous; | |
| 330 | − volatile int status; /* error code */ | |
| 423 | +struct SParser { /* data to `f_parser' */ | |
| 424 | + ZIO *z; | |
| 425 | + Mbuffer buff; /* buffer to be used by the scanner */ | |
| 426 | + int bin; | |
| 331 | 427 | }; |
| 332 | 428 | |
| 333 | − | |
| 334 | −static void message (lua_State *L, const char *s) { | |
| 335 | − const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | |
| 336 | − if (ttype(em) == LUA_TFUNCTION) { | |
| 337 | − *L->top = *em; | |
| 338 | − incr_top; | |
| 339 | − lua_pushstring(L, s); | |
| 340 | − luaD_call(L, L->top-2, 0); | |
| 341 | − } | |
| 342 | −} | |
| 343 | − | |
| 344 | − | |
| 345 | −/* | |
| 346 | −** Reports an error, and jumps up to the available recovery label | |
| 347 | −*/ | |
| 348 | −LUA_API void lua_error (lua_State *L, const char *s) { | |
| 349 | − if (s) message(L, s); | |
| 350 | − luaD_breakrun(L, LUA_ERRRUN); | |
| 351 | −} | |
| 352 | − | |
| 353 | − | |
| 354 | −void luaD_breakrun (lua_State *L, int errcode) { | |
| 355 | − if (L->errorJmp) { | |
| 356 | − L->errorJmp->status = errcode; | |
| 357 | − longjmp(L->errorJmp->b, 1); | |
| 358 | − } | |
| 359 | − else { | |
| 360 | − if (errcode != LUA_ERRMEM) | |
| 361 | − message(L, "unable to recover; exiting\n"); | |
| 362 | − exit(EXIT_FAILURE); | |
| 363 | − } | |
| 429 | +static void f_parser (lua_State *L, void *ud) { | |
| 430 | + struct SParser *p; | |
| 431 | + Proto *tf; | |
| 432 | + Closure *cl; | |
| 433 | + luaC_checkGC(L); | |
| 434 | + p = cast(struct SParser *, ud); | |
| 435 | + tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff); | |
| 436 | + cl = luaF_newLclosure(L, 0, gt(L)); | |
| 437 | + cl->l.p = tf; | |
| 438 | + setclvalue(L->top, cl); | |
| 439 | + incr_top(L); | |
| 364 | 440 | } |
| 365 | 441 | |
| 366 | 442 | |
| 367 | −int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | |
| 368 | − StkId oldCbase = L->Cbase; | |
| 369 | − StkId oldtop = L->top; | |
| 370 | − struct lua_longjmp lj; | |
| 371 | − int allowhooks = L->allowhooks; | |
| 372 | − lj.status = 0; | |
| 373 | − lj.previous = L->errorJmp; /* chain new error handler */ | |
| 374 | − L->errorJmp = &lj; | |
| 375 | − if (setjmp(lj.b) == 0) | |
| 376 | − (*f)(L, ud); | |
| 377 | − else { /* an error occurred: restore the state */ | |
| 378 | − L->allowhooks = allowhooks; | |
| 379 | − L->Cbase = oldCbase; | |
| 380 | − L->top = oldtop; | |
| 381 | − restore_stack_limit(L); | |
| 443 | +int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { | |
| 444 | + struct SParser p; | |
| 445 | + int status; | |
| 446 | + ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */ | |
| 447 | + p.z = z; p.bin = bin; | |
| 448 | + luaZ_initbuffer(L, &p.buff); | |
| 449 | + status = luaD_rawrunprotected(L, f_parser, &p); | |
| 450 | + luaZ_freebuffer(L, &p.buff); | |
| 451 | + if (status != 0) { /* error? */ | |
| 452 | + StkId oldtop = restorestack(L, oldtopr); | |
| 453 | + seterrorobj(L, status, oldtop); | |
| 382 | 454 | } |
| 383 | − L->errorJmp = lj.previous; /* restore old error handler */ | |
| 384 | − return lj.status; | |
| 455 | + return status; | |
| 385 | 456 | } |
| 386 | 457 | |
| 387 | −/* }====================================================== */ | |
| 388 | 458 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldo.h,v 1.28 2000/10/06 12:45:25 roberto Exp $ | |
| 2 | +** $Id: ldo.h,v 1.56 2002/12/04 17:29:32 roberto Exp $ | |
| 3 | 3 | ** Stack and Call structure of Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -10,24 +10,51 @@ · 4 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include "lobject.h" |
| 12 | 12 | #include "lstate.h" |
| 13 | +#include "lzio.h" | |
| 13 | 14 | |
| 14 | 15 | |
| 15 | 16 | /* |
| 16 | −** macro to increment stack top. | |
| 17 | −** There must be always an empty slot at the L->stack.top | |
| 18 | −*/ | |
| 19 | −#define incr_top {if (L->top == L->stack_last) luaD_checkstack(L, 1); L->top++;} | |
| 17 | +** macro to control inclusion of some hard tests on stack reallocation | |
| 18 | +*/ | |
| 19 | +#ifndef HARDSTACKTESTS | |
| 20 | +#define condhardstacktests(x) { /* empty */ } | |
| 21 | +#else | |
| 22 | +#define condhardstacktests(x) x | |
| 23 | +#endif | |
| 20 | 24 | |
| 21 | 25 | |
| 22 | −void luaD_init (lua_State *L, int stacksize); | |
| 23 | −void luaD_adjusttop (lua_State *L, StkId base, int extra); | |
| 24 | −void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); | |
| 25 | −void luaD_call (lua_State *L, StkId func, int nResults); | |
| 26 | −void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults); | |
| 27 | −void luaD_checkstack (lua_State *L, int n); | |
| 26 | +#define luaD_checkstack(L,n) \ | |
| 27 | + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \ | |
| 28 | + luaD_growstack(L, n); \ | |
| 29 | + else condhardstacktests(luaD_reallocstack(L, L->stacksize)); | |
| 30 | + | |
| 31 | + | |
| 32 | +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} | |
| 28 | 33 | |
| 29 | −void luaD_breakrun (lua_State *L, int errcode); | |
| 30 | −int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); | |
| 34 | +#define savestack(L,p) ((char *)(p) - (char *)L->stack) | |
| 35 | +#define restorestack(L,n) ((TObject *)((char *)L->stack + (n))) | |
| 36 | + | |
| 37 | +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) | |
| 38 | +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) | |
| 39 | + | |
| 40 | + | |
| 41 | +/* type of protected functions, to be ran by `runprotected' */ | |
| 42 | +typedef void (*Pfunc) (lua_State *L, void *ud); | |
| 43 | + | |
| 44 | +void luaD_resetprotection (lua_State *L); | |
| 45 | +int luaD_protectedparser (lua_State *L, ZIO *z, int bin); | |
| 46 | +void luaD_callhook (lua_State *L, int event, int line); | |
| 47 | +StkId luaD_precall (lua_State *L, StkId func); | |
| 48 | +void luaD_call (lua_State *L, StkId func, int nResults); | |
| 49 | +int luaD_pcall (lua_State *L, Pfunc func, void *u, | |
| 50 | + ptrdiff_t oldtop, ptrdiff_t ef); | |
| 51 | +void luaD_poscall (lua_State *L, int wanted, StkId firstResult); | |
| 52 | +void luaD_reallocCI (lua_State *L, int newsize); | |
| 53 | +void luaD_reallocstack (lua_State *L, int newsize); | |
| 54 | +void luaD_growstack (lua_State *L, int n); | |
| 55 | + | |
| 56 | +void luaD_throw (lua_State *L, int errcode); | |
| 57 | +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); | |
| 31 | 58 | |
| 32 | 59 | |
| 33 | 60 | #endif |
| @@ -0,0 +1,170 @@ | ||
| 1 | +/* | |
| 2 | +** $Id: ldump.c,v 1.4 2003/02/11 23:52:12 lhf Exp $ | |
| 3 | +** save bytecodes | |
| 4 | +** See Copyright Notice in lua.h | |
| 5 | +*/ | |
| 6 | + | |
| 7 | +#include <stddef.h> | |
| 8 | + | |
| 9 | +#define ldump_c | |
| 10 | + | |
| 11 | +#include "lua.h" | |
| 12 | + | |
| 13 | +#include "lobject.h" | |
| 14 | +#include "lopcodes.h" | |
| 15 | +#include "lstate.h" | |
| 16 | +#include "lundump.h" | |
| 17 | + | |
| 18 | +#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D) | |
| 19 | +#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D) | |
| 20 | + | |
| 21 | +typedef struct { | |
| 22 | + lua_State* L; | |
| 23 | + lua_Chunkwriter write; | |
| 24 | + void* data; | |
| 25 | +} DumpState; | |
| 26 | + | |
| 27 | +static void DumpBlock(const void* b, size_t size, DumpState* D) | |
| 28 | +{ | |
| 29 | + lua_unlock(D->L); | |
| 30 | + (*D->write)(D->L,b,size,D->data); | |
| 31 | + lua_lock(D->L); | |
| 32 | +} | |
| 33 | + | |
| 34 | +static void DumpByte(int y, DumpState* D) | |
| 35 | +{ | |
| 36 | + char x=(char)y; | |
| 37 | + DumpBlock(&x,sizeof(x),D); | |
| 38 | +} | |
| 39 | + | |
| 40 | +static void DumpInt(int x, DumpState* D) | |
| 41 | +{ | |
| 42 | + DumpBlock(&x,sizeof(x),D); | |
| 43 | +} | |
| 44 | + | |
| 45 | +static void DumpSize(size_t x, DumpState* D) | |
| 46 | +{ | |
| 47 | + DumpBlock(&x,sizeof(x),D); | |
| 48 | +} | |
| 49 | + | |
| 50 | +static void DumpNumber(lua_Number x, DumpState* D) | |
| 51 | +{ | |
| 52 | + DumpBlock(&x,sizeof(x),D); | |
| 53 | +} | |
| 54 | + | |
| 55 | +static void DumpString(TString* s, DumpState* D) | |
| 56 | +{ | |
| 57 | + if (s==NULL || getstr(s)==NULL) | |
| 58 | + DumpSize(0,D); | |
| 59 | + else | |
| 60 | + { | |
| 61 | + size_t size=s->tsv.len+1; /* include trailing '\0' */ | |
| 62 | + DumpSize(size,D); | |
| 63 | + DumpBlock(getstr(s),size,D); | |
| 64 | + } | |
| 65 | +} | |
| 66 | + | |
| 67 | +static void DumpCode(const Proto* f, DumpState* D) | |
| 68 | +{ | |
| 69 | + DumpInt(f->sizecode,D); | |
| 70 | + DumpVector(f->code,f->sizecode,sizeof(*f->code),D); | |
| 71 | +} | |
| 72 | + | |
| 73 | +static void DumpLocals(const Proto* f, DumpState* D) | |
| 74 | +{ | |
| 75 | + int i,n=f->sizelocvars; | |
| 76 | + DumpInt(n,D); | |
| 77 | + for (i=0; i<n; i++) | |
| 78 | + { | |
| 79 | + DumpString(f->locvars[i].varname,D); | |
| 80 | + DumpInt(f->locvars[i].startpc,D); | |
| 81 | + DumpInt(f->locvars[i].endpc,D); | |
| 82 | + } | |
| 83 | +} | |
| 84 | + | |
| 85 | +static void DumpLines(const Proto* f, DumpState* D) | |
| 86 | +{ | |
| 87 | + DumpInt(f->sizelineinfo,D); | |
| 88 | + DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D); | |
| 89 | +} | |
| 90 | + | |
| 91 | +static void DumpUpvalues(const Proto* f, DumpState* D) | |
| 92 | +{ | |
| 93 | + int i,n=f->sizeupvalues; | |
| 94 | + DumpInt(n,D); | |
| 95 | + for (i=0; i<n; i++) DumpString(f->upvalues[i],D); | |
| 96 | +} | |
| 97 | + | |
| 98 | +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); | |
| 99 | + | |
| 100 | +static void DumpConstants(const Proto* f, DumpState* D) | |
| 101 | +{ | |
| 102 | + int i,n; | |
| 103 | + DumpInt(n=f->sizek,D); | |
| 104 | + for (i=0; i<n; i++) | |
| 105 | + { | |
| 106 | + const TObject* o=&f->k[i]; | |
| 107 | + DumpByte(ttype(o),D); | |
| 108 | + switch (ttype(o)) | |
| 109 | + { | |
| 110 | + case LUA_TNUMBER: | |
| 111 | + DumpNumber(nvalue(o),D); | |
| 112 | + break; | |
| 113 | + case LUA_TSTRING: | |
| 114 | + DumpString(tsvalue(o),D); | |
| 115 | + break; | |
| 116 | + case LUA_TNIL: | |
| 117 | + break; | |
| 118 | + default: | |
| 119 | + lua_assert(0); /* cannot happen */ | |
| 120 | + break; | |
| 121 | + } | |
| 122 | + } | |
| 123 | + DumpInt(n=f->sizep,D); | |
| 124 | + for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); | |
| 125 | +} | |
| 126 | + | |
| 127 | +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) | |
| 128 | +{ | |
| 129 | + DumpString((f->source==p) ? NULL : f->source,D); | |
| 130 | + DumpInt(f->lineDefined,D); | |
| 131 | + DumpByte(f->nups,D); | |
| 132 | + DumpByte(f->numparams,D); | |
| 133 | + DumpByte(f->is_vararg,D); | |
| 134 | + DumpByte(f->maxstacksize,D); | |
| 135 | + DumpLines(f,D); | |
| 136 | + DumpLocals(f,D); | |
| 137 | + DumpUpvalues(f,D); | |
| 138 | + DumpConstants(f,D); | |
| 139 | + DumpCode(f,D); | |
| 140 | +} | |
| 141 | + | |
| 142 | +static void DumpHeader(DumpState* D) | |
| 143 | +{ | |
| 144 | + DumpLiteral(LUA_SIGNATURE,D); | |
| 145 | + DumpByte(VERSION,D); | |
| 146 | + DumpByte(luaU_endianness(),D); | |
| 147 | + DumpByte(sizeof(int),D); | |
| 148 | + DumpByte(sizeof(size_t),D); | |
| 149 | + DumpByte(sizeof(Instruction),D); | |
| 150 | + DumpByte(SIZE_OP,D); | |
| 151 | + DumpByte(SIZE_A,D); | |
| 152 | + DumpByte(SIZE_B,D); | |
| 153 | + DumpByte(SIZE_C,D); | |
| 154 | + DumpByte(sizeof(lua_Number),D); | |
| 155 | + DumpNumber(TEST_NUMBER,D); | |
| 156 | +} | |
| 157 | + | |
| 158 | +/* | |
| 159 | +** dump function as precompiled chunk | |
| 160 | +*/ | |
| 161 | +void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data) | |
| 162 | +{ | |
| 163 | + DumpState D; | |
| 164 | + D.L=L; | |
| 165 | + D.write=w; | |
| 166 | + D.data=data; | |
| 167 | + DumpHeader(&D); | |
| 168 | + DumpFunction(Main,NULL,&D); | |
| 169 | +} | |
| 170 | + | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lfunc.c,v 1.34 2000/10/30 12:20:29 roberto Exp $ | |
| 2 | +** $Id: lfunc.c,v 1.67 2003/03/18 12:50:04 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -7,87 +7,113 @@ · 1 unmodified line | ||
| 7 | 7 | |
| 8 | 8 | #include <stdlib.h> |
| 9 | 9 | |
| 10 | +#define lfunc_c | |
| 11 | + | |
| 10 | 12 | #include "lua.h" |
| 11 | 13 | |
| 12 | 14 | #include "lfunc.h" |
| 15 | +#include "lgc.h" | |
| 13 | 16 | #include "lmem.h" |
| 17 | +#include "lobject.h" | |
| 14 | 18 | #include "lstate.h" |
| 15 | 19 | |
| 16 | 20 | |
| 17 | −#define sizeclosure(n) ((int)sizeof(Closure) + (int)sizeof(TObject)*((n)-1)) | |
| 21 | +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ | |
| 22 | + cast(int, sizeof(TObject)*((n)-1))) | |
| 23 | + | |
| 24 | +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ | |
| 25 | + cast(int, sizeof(TObject *)*((n)-1))) | |
| 26 | + | |
| 18 | 27 | |
| 19 | 28 | |
| 20 | −Closure *luaF_newclosure (lua_State *L, int nelems) { | |
| 21 | − int size = sizeclosure(nelems); | |
| 22 | − Closure *c = (Closure *)luaM_malloc(L, size); | |
| 23 | − c->next = L->rootcl; | |
| 24 | − L->rootcl = c; | |
| 25 | − c->mark = c; | |
| 26 | − c->nupvalues = nelems; | |
| 27 | − L->nblocks += size; | |
| 29 | +Closure *luaF_newCclosure (lua_State *L, int nelems) { | |
| 30 | + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); | |
| 31 | + luaC_link(L, valtogco(c), LUA_TFUNCTION); | |
| 32 | + c->c.isC = 1; | |
| 33 | + c->c.nupvalues = cast(lu_byte, nelems); | |
| 28 | 34 | return c; |
| 29 | 35 | } |
| 30 | 36 | |
| 31 | 37 | |
| 38 | +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) { | |
| 39 | + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); | |
| 40 | + luaC_link(L, valtogco(c), LUA_TFUNCTION); | |
| 41 | + c->l.isC = 0; | |
| 42 | + c->l.g = *e; | |
| 43 | + c->l.nupvalues = cast(lu_byte, nelems); | |
| 44 | + return c; | |
| 45 | +} | |
| 46 | + | |
| 47 | + | |
| 48 | +UpVal *luaF_findupval (lua_State *L, StkId level) { | |
| 49 | + GCObject **pp = &L->openupval; | |
| 50 | + UpVal *p; | |
| 51 | + UpVal *v; | |
| 52 | + while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { | |
| 53 | + if (p->v == level) return p; | |
| 54 | + pp = &p->next; | |
| 55 | + } | |
| 56 | + v = luaM_new(L, UpVal); /* not found: create a new one */ | |
| 57 | + v->tt = LUA_TUPVAL; | |
| 58 | + v->marked = 1; /* open upvalues should not be collected */ | |
| 59 | + v->v = level; /* current value lives in the stack */ | |
| 60 | + v->next = *pp; /* chain it in the proper position */ | |
| 61 | + *pp = valtogco(v); | |
| 62 | + return v; | |
| 63 | +} | |
| 64 | + | |
| 65 | + | |
| 66 | +void luaF_close (lua_State *L, StkId level) { | |
| 67 | + UpVal *p; | |
| 68 | + while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) { | |
| 69 | + setobj(&p->value, p->v); /* save current value (write barrier) */ | |
| 70 | + p->v = &p->value; /* now current value lives here */ | |
| 71 | + L->openupval = p->next; /* remove from `open' list */ | |
| 72 | + luaC_link(L, valtogco(p), LUA_TUPVAL); | |
| 73 | + } | |
| 74 | +} | |
| 75 | + | |
| 76 | + | |
| 32 | 77 | Proto *luaF_newproto (lua_State *L) { |
| 33 | 78 | Proto *f = luaM_new(L, Proto); |
| 34 | − f->knum = NULL; | |
| 35 | − f->nknum = 0; | |
| 36 | − f->kstr = NULL; | |
| 37 | − f->nkstr = 0; | |
| 38 | − f->kproto = NULL; | |
| 39 | − f->nkproto = 0; | |
| 79 | + luaC_link(L, valtogco(f), LUA_TPROTO); | |
| 80 | + f->k = NULL; | |
| 81 | + f->sizek = 0; | |
| 82 | + f->p = NULL; | |
| 83 | + f->sizep = 0; | |
| 40 | 84 | f->code = NULL; |
| 41 | − f->ncode = 0; | |
| 85 | + f->sizecode = 0; | |
| 86 | + f->sizelineinfo = 0; | |
| 87 | + f->sizeupvalues = 0; | |
| 88 | + f->nups = 0; | |
| 89 | + f->upvalues = NULL; | |
| 42 | 90 | f->numparams = 0; |
| 43 | 91 | f->is_vararg = 0; |
| 44 | 92 | f->maxstacksize = 0; |
| 45 | − f->marked = 0; | |
| 46 | 93 | f->lineinfo = NULL; |
| 47 | − f->nlineinfo = 0; | |
| 48 | − f->nlocvars = 0; | |
| 94 | + f->sizelocvars = 0; | |
| 49 | 95 | f->locvars = NULL; |
| 50 | 96 | f->lineDefined = 0; |
| 51 | 97 | f->source = NULL; |
| 52 | − f->next = L->rootproto; /* chain in list of protos */ | |
| 53 | − L->rootproto = f; | |
| 54 | 98 | return f; |
| 55 | 99 | } |
| 56 | 100 | |
| 57 | 101 | |
| 58 | −static size_t protosize (Proto *f) { | |
| 59 | − return sizeof(Proto) | |
| 60 | − + f->nknum*sizeof(Number) | |
| 61 | − + f->nkstr*sizeof(TString *) | |
| 62 | − + f->nkproto*sizeof(Proto *) | |
| 63 | − + f->ncode*sizeof(Instruction) | |
| 64 | − + f->nlocvars*sizeof(struct LocVar) | |
| 65 | − + f->nlineinfo*sizeof(int); | |
| 66 | −} | |
| 67 | − | |
| 68 | − | |
| 69 | −void luaF_protook (lua_State *L, Proto *f, int pc) { | |
| 70 | − f->ncode = pc; /* signal that proto was properly created */ | |
| 71 | − L->nblocks += protosize(f); | |
| 72 | −} | |
| 73 | − | |
| 74 | − | |
| 75 | 102 | void luaF_freeproto (lua_State *L, Proto *f) { |
| 76 | − if (f->ncode > 0) /* function was properly created? */ | |
| 77 | − L->nblocks -= protosize(f); | |
| 78 | − luaM_free(L, f->code); | |
| 79 | − luaM_free(L, f->locvars); | |
| 80 | − luaM_free(L, f->kstr); | |
| 81 | − luaM_free(L, f->knum); | |
| 82 | − luaM_free(L, f->kproto); | |
| 83 | − luaM_free(L, f->lineinfo); | |
| 84 | − luaM_free(L, f); | |
| 103 | + luaM_freearray(L, f->code, f->sizecode, Instruction); | |
| 104 | + luaM_freearray(L, f->p, f->sizep, Proto *); | |
| 105 | + luaM_freearray(L, f->k, f->sizek, TObject); | |
| 106 | + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | |
| 107 | + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); | |
| 108 | + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); | |
| 109 | + luaM_freelem(L, f); | |
| 85 | 110 | } |
| 86 | 111 | |
| 87 | 112 | |
| 88 | 113 | void luaF_freeclosure (lua_State *L, Closure *c) { |
| 89 | − L->nblocks -= sizeclosure(c->nupvalues); | |
| 90 | − luaM_free(L, c); | |
| 114 | + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : | |
| 115 | + sizeLclosure(c->l.nupvalues); | |
| 116 | + luaM_free(L, c, size); | |
| 91 | 117 | } |
| 92 | 118 | |
| 93 | 119 | |
| @@ -97,11 +123,11 @@ void luaF_freeclosure (lua_State *L, Closure *c) { · 3 unmodified lines | ||
| 97 | 123 | */ |
| 98 | 124 | const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { |
| 99 | 125 | int i; |
| 100 | − for (i = 0; i<f->nlocvars && f->locvars[i].startpc <= pc; i++) { | |
| 126 | + for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { | |
| 101 | 127 | if (pc < f->locvars[i].endpc) { /* is variable active? */ |
| 102 | 128 | local_number--; |
| 103 | 129 | if (local_number == 0) |
| 104 | − return f->locvars[i].varname->str; | |
| 130 | + return getstr(f->locvars[i].varname); | |
| 105 | 131 | } |
| 106 | 132 | } |
| 107 | 133 | return NULL; /* not found */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lfunc.h,v 1.13 2000/09/29 12:42:13 roberto Exp $ | |
| 2 | +** $Id: lfunc.h,v 1.21 2003/03/18 12:50:04 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -11,10 +11,11 @@ · 5 unmodified lines | ||
| 11 | 11 | #include "lobject.h" |
| 12 | 12 | |
| 13 | 13 | |
| 14 | − | |
| 15 | 14 | Proto *luaF_newproto (lua_State *L); |
| 16 | −void luaF_protook (lua_State *L, Proto *f, int pc); | |
| 17 | −Closure *luaF_newclosure (lua_State *L, int nelems); | |
| 15 | +Closure *luaF_newCclosure (lua_State *L, int nelems); | |
| 16 | +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e); | |
| 17 | +UpVal *luaF_findupval (lua_State *L, StkId level); | |
| 18 | +void luaF_close (lua_State *L, StkId level); | |
| 18 | 19 | void luaF_freeproto (lua_State *L, Proto *f); |
| 19 | 20 | void luaF_freeclosure (lua_State *L, Closure *c); |
| 20 | 21 | |
| @@ -1,11 +1,16 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lgc.c,v 1.72+ 2000/10/26 12:47:05 roberto Exp $ | |
| 2 | +** $Id: lgc.c,v 1.171 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Garbage Collector |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | +#include <string.h> | |
| 8 | + | |
| 9 | +#define lgc_c | |
| 10 | + | |
| 7 | 11 | #include "lua.h" |
| 8 | 12 | |
| 13 | +#include "ldebug.h" | |
| 9 | 14 | #include "ldo.h" |
| 10 | 15 | #include "lfunc.h" |
| 11 | 16 | #include "lgc.h" |
| @@ -18,336 +23,471 @@ · 6 unmodified lines | ||
| 18 | 23 | |
| 19 | 24 | |
| 20 | 25 | typedef struct GCState { |
| 21 | − Hash *tmark; /* list of marked tables to be visited */ | |
| 22 | − Closure *cmark; /* list of marked closures to be visited */ | |
| 26 | + GCObject *tmark; /* list of marked objects to be traversed */ | |
| 27 | + GCObject *wk; /* list of traversed key-weak tables (to be cleared) */ | |
| 28 | + GCObject *wv; /* list of traversed value-weak tables */ | |
| 29 | + GCObject *wkv; /* list of traversed key-value weak tables */ | |
| 30 | + global_State *g; | |
| 23 | 31 | } GCState; |
| 24 | 32 | |
| 25 | 33 | |
| 34 | +/* | |
| 35 | +** some userful bit tricks | |
| 36 | +*/ | |
| 37 | +#define setbit(x,b) ((x) |= (1<<(b))) | |
| 38 | +#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b)))) | |
| 39 | +#define testbit(x,b) ((x) & (1<<(b))) | |
| 26 | 40 | |
| 27 | −static void markobject (GCState *st, TObject *o); | |
| 41 | +#define unmark(x) resetbit((x)->gch.marked, 0) | |
| 42 | +#define ismarked(x) ((x)->gch.marked & ((1<<4)|1)) | |
| 28 | 43 | |
| 44 | +#define stringmark(s) setbit((s)->tsv.marked, 0) | |
| 29 | 45 | |
| 30 | −/* mark a string; marks larger than 1 cannot be changed */ | |
| 31 | −#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} | |
| 32 | 46 | |
| 47 | +#define isfinalized(u) (!testbit((u)->uv.marked, 1)) | |
| 48 | +#define markfinalized(u) resetbit((u)->uv.marked, 1) | |
| 33 | 49 | |
| 34 | 50 | |
| 35 | −static void protomark (Proto *f) { | |
| 36 | − if (!f->marked) { | |
| 37 | − int i; | |
| 38 | − f->marked = 1; | |
| 39 | − strmark(f->source); | |
| 40 | − for (i=0; i<f->nkstr; i++) | |
| 41 | − strmark(f->kstr[i]); | |
| 42 | − for (i=0; i<f->nkproto; i++) | |
| 43 | − protomark(f->kproto[i]); | |
| 44 | − for (i=0; i<f->nlocvars; i++) /* mark local-variable names */ | |
| 45 | − strmark(f->locvars[i].varname); | |
| 46 | − } | |
| 47 | −} | |
| 51 | +#define KEYWEAKBIT 1 | |
| 52 | +#define VALUEWEAKBIT 2 | |
| 53 | +#define KEYWEAK (1<<KEYWEAKBIT) | |
| 54 | +#define VALUEWEAK (1<<VALUEWEAKBIT) | |
| 48 | 55 | |
| 49 | 56 | |
| 50 | −static void markstack (lua_State *L, GCState *st) { | |
| 51 | − StkId o; | |
| 52 | − for (o=L->stack; o<L->top; o++) | |
| 53 | − markobject(st, o); | |
| 54 | −} | |
| 55 | 57 | |
| 58 | +#define markobject(st,o) { checkconsistency(o); \ | |
| 59 | + if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); } | |
| 56 | 60 | |
| 57 | −static void marklock (lua_State *L, GCState *st) { | |
| 58 | − int i; | |
| 59 | − for (i=0; i<L->refSize; i++) { | |
| 60 | − if (L->refArray[i].st == LOCK) | |
| 61 | − markobject(st, &L->refArray[i].o); | |
| 61 | +#define condmarkobject(st,o,c) { checkconsistency(o); \ | |
| 62 | + if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \ | |
| 63 | + reallymarkobject(st,gcvalue(o)); } | |
| 64 | + | |
| 65 | +#define markvalue(st,t) { if (!ismarked(valtogco(t))) \ | |
| 66 | + reallymarkobject(st, valtogco(t)); } | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | +static void reallymarkobject (GCState *st, GCObject *o) { | |
| 71 | + lua_assert(!ismarked(o)); | |
| 72 | + setbit(o->gch.marked, 0); /* mark object */ | |
| 73 | + switch (o->gch.tt) { | |
| 74 | + case LUA_TUSERDATA: { | |
| 75 | + markvalue(st, gcotou(o)->uv.metatable); | |
| 76 | + break; | |
| 77 | + } | |
| 78 | + case LUA_TFUNCTION: { | |
| 79 | + gcotocl(o)->c.gclist = st->tmark; | |
| 80 | + st->tmark = o; | |
| 81 | + break; | |
| 82 | + } | |
| 83 | + case LUA_TTABLE: { | |
| 84 | + gcotoh(o)->gclist = st->tmark; | |
| 85 | + st->tmark = o; | |
| 86 | + break; | |
| 87 | + } | |
| 88 | + case LUA_TTHREAD: { | |
| 89 | + gcototh(o)->gclist = st->tmark; | |
| 90 | + st->tmark = o; | |
| 91 | + break; | |
| 92 | + } | |
| 93 | + case LUA_TPROTO: { | |
| 94 | + gcotop(o)->gclist = st->tmark; | |
| 95 | + st->tmark = o; | |
| 96 | + break; | |
| 97 | + } | |
| 98 | + default: lua_assert(o->gch.tt == LUA_TSTRING); | |
| 62 | 99 | } |
| 63 | 100 | } |
| 64 | 101 | |
| 65 | 102 | |
| 66 | −static void markclosure (GCState *st, Closure *cl) { | |
| 67 | − if (!ismarked(cl)) { | |
| 68 | − if (!cl->isC) | |
| 69 | − protomark(cl->f.l); | |
| 70 | − cl->mark = st->cmark; /* chain it for later traversal */ | |
| 71 | − st->cmark = cl; | |
| 103 | +static void marktmu (GCState *st) { | |
| 104 | + GCObject *u; | |
| 105 | + for (u = st->g->tmudata; u; u = u->gch.next) { | |
| 106 | + unmark(u); /* may be marked, if left from previous GC */ | |
| 107 | + reallymarkobject(st, u); | |
| 72 | 108 | } |
| 73 | 109 | } |
| 74 | 110 | |
| 75 | 111 | |
| 76 | −static void marktagmethods (lua_State *L, GCState *st) { | |
| 77 | − int e; | |
| 78 | − for (e=0; e<TM_N; e++) { | |
| 79 | − int t; | |
| 80 | − for (t=0; t<=L->last_tag; t++) { | |
| 81 | − Closure *cl = luaT_gettm(L, t, e); | |
| 82 | − if (cl) markclosure(st, cl); | |
| 112 | +/* move `dead' udata that need finalization to list `tmudata' */ | |
| 113 | +void luaC_separateudata (lua_State *L) { | |
| 114 | + GCObject **p = &G(L)->rootudata; | |
| 115 | + GCObject *curr; | |
| 116 | + GCObject *collected = NULL; /* to collect udata with gc event */ | |
| 117 | + GCObject **lastcollected = &collected; | |
| 118 | + while ((curr = *p) != NULL) { | |
| 119 | + lua_assert(curr->gch.tt == LUA_TUSERDATA); | |
| 120 | + if (ismarked(curr) || isfinalized(gcotou(curr))) | |
| 121 | + p = &curr->gch.next; /* don't bother with them */ | |
| 122 | + | |
| 123 | + else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { | |
| 124 | + markfinalized(gcotou(curr)); /* don't need finalization */ | |
| 125 | + p = &curr->gch.next; | |
| 126 | + } | |
| 127 | + else { /* must call its gc method */ | |
| 128 | + *p = curr->gch.next; | |
| 129 | + curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ | |
| 130 | + *lastcollected = curr; | |
| 131 | + lastcollected = &curr->gch.next; | |
| 83 | 132 | } |
| 84 | 133 | } |
| 134 | + /* insert collected udata with gc event into `tmudata' list */ | |
| 135 | + *lastcollected = G(L)->tmudata; | |
| 136 | + G(L)->tmudata = collected; | |
| 85 | 137 | } |
| 86 | 138 | |
| 87 | 139 | |
| 88 | −static void markobject (GCState *st, TObject *o) { | |
| 89 | − switch (ttype(o)) { | |
| 90 | − case LUA_TUSERDATA: case LUA_TSTRING: | |
| 91 | − strmark(tsvalue(o)); | |
| 92 | − break; | |
| 93 | − case LUA_TMARK: | |
| 94 | − markclosure(st, infovalue(o)->func); | |
| 95 | − break; | |
| 96 | − case LUA_TFUNCTION: | |
| 97 | − markclosure(st, clvalue(o)); | |
| 98 | − break; | |
| 99 | − case LUA_TTABLE: { | |
| 100 | − if (!ismarked(hvalue(o))) { | |
| 101 | − hvalue(o)->mark = st->tmark; /* chain it in list of marked */ | |
| 102 | − st->tmark = hvalue(o); | |
| 103 | − } | |
| 104 | − break; | |
| 105 | − } | |
| 106 | − default: break; /* numbers, etc */ | |
| 107 | − } | |
| 140 | +static void removekey (Node *n) { | |
| 141 | + setnilvalue(gval(n)); /* remove corresponding value ... */ | |
| 142 | + if (iscollectable(gkey(n))) | |
| 143 | + setttype(gkey(n), LUA_TNONE); /* dead key; remove it */ | |
| 108 | 144 | } |
| 109 | 145 | |
| 110 | 146 | |
| 111 | −static void markall (lua_State *L) { | |
| 112 | − GCState st; | |
| 113 | − st.cmark = NULL; | |
| 114 | − st.tmark = L->gt; /* put table of globals in mark list */ | |
| 115 | − L->gt->mark = NULL; | |
| 116 | − marktagmethods(L, &st); /* mark tag methods */ | |
| 117 | − markstack(L, &st); /* mark stack objects */ | |
| 118 | − marklock(L, &st); /* mark locked objects */ | |
| 119 | − for (;;) { /* mark tables and closures */ | |
| 120 | − if (st.cmark) { | |
| 121 | − int i; | |
| 122 | − Closure *f = st.cmark; /* get first closure from list */ | |
| 123 | − st.cmark = f->mark; /* remove it from list */ | |
| 124 | − for (i=0; i<f->nupvalues; i++) /* mark its upvalues */ | |
| 125 | − markobject(&st, &f->upvalue[i]); | |
| 147 | +static void traversetable (GCState *st, Table *h) { | |
| 148 | + int i; | |
| 149 | + int weakkey = 0; | |
| 150 | + int weakvalue = 0; | |
| 151 | + const TObject *mode; | |
| 152 | + markvalue(st, h->metatable); | |
| 153 | + lua_assert(h->lsizenode || h->node == st->g->dummynode); | |
| 154 | + mode = gfasttm(st->g, h->metatable, TM_MODE); | |
| 155 | + if (mode && ttisstring(mode)) { /* is there a weak mode? */ | |
| 156 | + weakkey = (strchr(svalue(mode), 'k') != NULL); | |
| 157 | + weakvalue = (strchr(svalue(mode), 'v') != NULL); | |
| 158 | + if (weakkey || weakvalue) { /* is really weak? */ | |
| 159 | + GCObject **weaklist; | |
| 160 | + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ | |
| 161 | + h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) | | |
| 162 | + (weakvalue << VALUEWEAKBIT)); | |
| 163 | + weaklist = (weakkey && weakvalue) ? &st->wkv : | |
| 164 | + (weakkey) ? &st->wk : | |
| 165 | + &st->wv; | |
| 166 | + h->gclist = *weaklist; /* must be cleared after GC, ... */ | |
| 167 | + *weaklist = valtogco(h); /* ... so put in the appropriate list */ | |
| 126 | 168 | } |
| 127 | − else if (st.tmark) { | |
| 128 | − int i; | |
| 129 | − Hash *h = st.tmark; /* get first table from list */ | |
| 130 | − st.tmark = h->mark; /* remove it from list */ | |
| 131 | − for (i=0; i<h->size; i++) { | |
| 132 | − Node *n = node(h, i); | |
| 133 | − if (ttype(key(n)) != LUA_TNIL) { | |
| 134 | − if (ttype(val(n)) == LUA_TNIL) | |
| 135 | − luaH_remove(h, key(n)); /* dead element; try to remove it */ | |
| 136 | − markobject(&st, &n->key); | |
| 137 | − markobject(&st, &n->val); | |
| 138 | − } | |
| 139 | − } | |
| 169 | + } | |
| 170 | + if (!weakvalue) { | |
| 171 | + i = h->sizearray; | |
| 172 | + while (i--) | |
| 173 | + markobject(st, &h->array[i]); | |
| 174 | + } | |
| 175 | + i = sizenode(h); | |
| 176 | + while (i--) { | |
| 177 | + Node *n = gnode(h, i); | |
| 178 | + if (!ttisnil(gval(n))) { | |
| 179 | + lua_assert(!ttisnil(gkey(n))); | |
| 180 | + condmarkobject(st, gkey(n), !weakkey); | |
| 181 | + condmarkobject(st, gval(n), !weakvalue); | |
| 140 | 182 | } |
| 141 | − else break; /* nothing else to mark */ | |
| 142 | 183 | } |
| 143 | 184 | } |
| 144 | 185 | |
| 145 | 186 | |
| 146 | −static int hasmark (const TObject *o) { | |
| 147 | − /* valid only for locked objects */ | |
| 148 | − switch (o->ttype) { | |
| 149 | − case LUA_TSTRING: case LUA_TUSERDATA: | |
| 150 | − return tsvalue(o)->marked; | |
| 151 | − case LUA_TTABLE: | |
| 152 | − return ismarked(hvalue(o)); | |
| 153 | − case LUA_TFUNCTION: | |
| 154 | − return ismarked(clvalue(o)); | |
| 155 | − default: /* number */ | |
| 156 | − return 1; | |
| 187 | +static void traverseproto (GCState *st, Proto *f) { | |
| 188 | + int i; | |
| 189 | + stringmark(f->source); | |
| 190 | + for (i=0; i<f->sizek; i++) { /* mark literal strings */ | |
| 191 | + if (ttisstring(f->k+i)) | |
| 192 | + stringmark(tsvalue(f->k+i)); | |
| 157 | 193 | } |
| 194 | + for (i=0; i<f->sizeupvalues; i++) /* mark upvalue names */ | |
| 195 | + stringmark(f->upvalues[i]); | |
| 196 | + for (i=0; i<f->sizep; i++) /* mark nested protos */ | |
| 197 | + markvalue(st, f->p[i]); | |
| 198 | + for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ | |
| 199 | + stringmark(f->locvars[i].varname); | |
| 200 | + lua_assert(luaG_checkcode(f)); | |
| 158 | 201 | } |
| 159 | 202 | |
| 160 | 203 | |
| 161 | −/* macro for internal debugging; check if a link of free refs is valid */ | |
| 162 | −#define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n)) | |
| 163 | 204 | |
| 164 | −static void invalidaterefs (lua_State *L) { | |
| 165 | − int n = L->refSize; | |
| 166 | − int i; | |
| 167 | − for (i=0; i<n; i++) { | |
| 168 | − struct Ref *r = &L->refArray[i]; | |
| 169 | − if (r->st == HOLD && !hasmark(&r->o)) | |
| 170 | − r->st = COLLECTED; | |
| 171 | − LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) || | |
| 172 | − (r->st == HOLD && hasmark(&r->o)) || | |
| 173 | − r->st == COLLECTED || | |
| 174 | − r->st == NONEXT || | |
| 175 | − (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), | |
| 176 | − "inconsistent ref table"); | |
| 205 | +static void traverseclosure (GCState *st, Closure *cl) { | |
| 206 | + if (cl->c.isC) { | |
| 207 | + int i; | |
| 208 | + for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ | |
| 209 | + markobject(st, &cl->c.upvalue[i]); | |
| 210 | + } | |
| 211 | + else { | |
| 212 | + int i; | |
| 213 | + lua_assert(cl->l.nupvalues == cl->l.p->nups); | |
| 214 | + markvalue(st, hvalue(&cl->l.g)); | |
| 215 | + markvalue(st, cl->l.p); | |
| 216 | + for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ | |
| 217 | + UpVal *u = cl->l.upvals[i]; | |
| 218 | + if (!u->marked) { | |
| 219 | + markobject(st, &u->value); | |
| 220 | + u->marked = 1; | |
| 221 | + } | |
| 222 | + } | |
| 177 | 223 | } |
| 178 | − LUA_ASSERT(VALIDLINK(L, L->refFree, n), "inconsistent ref table"); | |
| 179 | 224 | } |
| 180 | 225 | |
| 181 | 226 | |
| 227 | +static void checkstacksizes (lua_State *L, StkId max) { | |
| 228 | + int used = L->ci - L->base_ci; /* number of `ci' in use */ | |
| 229 | + if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | |
| 230 | + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | |
| 231 | + else condhardstacktests(luaD_reallocCI(L, L->size_ci)); | |
| 232 | + used = max - L->stack; /* part of stack in use */ | |
| 233 | + if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) | |
| 234 | + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | |
| 235 | + else condhardstacktests(luaD_reallocstack(L, L->stacksize)); | |
| 236 | +} | |
| 182 | 237 | |
| 183 | −static void collectproto (lua_State *L) { | |
| 184 | − Proto **p = &L->rootproto; | |
| 185 | − Proto *next; | |
| 186 | − while ((next = *p) != NULL) { | |
| 187 | − if (next->marked) { | |
| 188 | − next->marked = 0; | |
| 189 | − p = &next->next; | |
| 190 | − } | |
| 191 | − else { | |
| 192 | − *p = next->next; | |
| 193 | − luaF_freeproto(L, next); | |
| 194 | − } | |
| 238 | + | |
| 239 | +static void traversestack (GCState *st, lua_State *L1) { | |
| 240 | + StkId o, lim; | |
| 241 | + CallInfo *ci; | |
| 242 | + markobject(st, gt(L1)); | |
| 243 | + lim = L1->top; | |
| 244 | + for (ci = L1->base_ci; ci <= L1->ci; ci++) { | |
| 245 | + lua_assert(ci->top <= L1->stack_last); | |
| 246 | + lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC)); | |
| 247 | + if (!(ci->state & CI_C) && lim < ci->top) | |
| 248 | + lim = ci->top; | |
| 195 | 249 | } |
| 250 | + for (o = L1->stack; o < L1->top; o++) | |
| 251 | + markobject(st, o); | |
| 252 | + for (; o <= lim; o++) | |
| 253 | + setnilvalue(o); | |
| 254 | + checkstacksizes(L1, lim); | |
| 196 | 255 | } |
| 197 | 256 | |
| 198 | 257 | |
| 199 | −static void collectclosure (lua_State *L) { | |
| 200 | − Closure **p = &L->rootcl; | |
| 201 | − Closure *next; | |
| 202 | − while ((next = *p) != NULL) { | |
| 203 | − if (ismarked(next)) { | |
| 204 | − next->mark = next; /* unmark */ | |
| 205 | − p = &next->next; | |
| 258 | +static void propagatemarks (GCState *st) { | |
| 259 | + while (st->tmark) { /* traverse marked objects */ | |
| 260 | + switch (st->tmark->gch.tt) { | |
| 261 | + case LUA_TTABLE: { | |
| 262 | + Table *h = gcotoh(st->tmark); | |
| 263 | + st->tmark = h->gclist; | |
| 264 | + traversetable(st, h); | |
| 265 | + break; | |
| 266 | + } | |
| 267 | + case LUA_TFUNCTION: { | |
| 268 | + Closure *cl = gcotocl(st->tmark); | |
| 269 | + st->tmark = cl->c.gclist; | |
| 270 | + traverseclosure(st, cl); | |
| 271 | + break; | |
| 272 | + } | |
| 273 | + case LUA_TTHREAD: { | |
| 274 | + lua_State *th = gcototh(st->tmark); | |
| 275 | + st->tmark = th->gclist; | |
| 276 | + traversestack(st, th); | |
| 277 | + break; | |
| 278 | + } | |
| 279 | + case LUA_TPROTO: { | |
| 280 | + Proto *p = gcotop(st->tmark); | |
| 281 | + st->tmark = p->gclist; | |
| 282 | + traverseproto(st, p); | |
| 283 | + break; | |
| 284 | + } | |
| 285 | + default: lua_assert(0); | |
| 206 | 286 | } |
| 207 | − else { | |
| 208 | − *p = next->next; | |
| 209 | − luaF_freeclosure(L, next); | |
| 287 | + } | |
| 288 | +} | |
| 289 | + | |
| 290 | + | |
| 291 | +static int valismarked (const TObject *o) { | |
| 292 | + if (ttisstring(o)) | |
| 293 | + stringmark(tsvalue(o)); /* strings are `values', so are never weak */ | |
| 294 | + return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0); | |
| 295 | +} | |
| 296 | + | |
| 297 | + | |
| 298 | +/* | |
| 299 | +** clear collected keys from weaktables | |
| 300 | +*/ | |
| 301 | +static void cleartablekeys (GCObject *l) { | |
| 302 | + while (l) { | |
| 303 | + Table *h = gcotoh(l); | |
| 304 | + int i = sizenode(h); | |
| 305 | + lua_assert(h->marked & KEYWEAK); | |
| 306 | + while (i--) { | |
| 307 | + Node *n = gnode(h, i); | |
| 308 | + if (!valismarked(gkey(n))) /* key was collected? */ | |
| 309 | + removekey(n); /* remove entry from table */ | |
| 210 | 310 | } |
| 311 | + l = h->gclist; | |
| 211 | 312 | } |
| 212 | 313 | } |
| 213 | 314 | |
| 214 | 315 | |
| 215 | −static void collecttable (lua_State *L) { | |
| 216 | − Hash **p = &L->roottable; | |
| 217 | − Hash *next; | |
| 218 | − while ((next = *p) != NULL) { | |
| 219 | − if (ismarked(next)) { | |
| 220 | − next->mark = next; /* unmark */ | |
| 221 | − p = &next->next; | |
| 316 | +/* | |
| 317 | +** clear collected values from weaktables | |
| 318 | +*/ | |
| 319 | +static void cleartablevalues (GCObject *l) { | |
| 320 | + while (l) { | |
| 321 | + Table *h = gcotoh(l); | |
| 322 | + int i = h->sizearray; | |
| 323 | + lua_assert(h->marked & VALUEWEAK); | |
| 324 | + while (i--) { | |
| 325 | + TObject *o = &h->array[i]; | |
| 326 | + if (!valismarked(o)) /* value was collected? */ | |
| 327 | + setnilvalue(o); /* remove value */ | |
| 222 | 328 | } |
| 223 | − else { | |
| 224 | − *p = next->next; | |
| 225 | − luaH_free(L, next); | |
| 329 | + i = sizenode(h); | |
| 330 | + while (i--) { | |
| 331 | + Node *n = gnode(h, i); | |
| 332 | + if (!valismarked(gval(n))) /* value was collected? */ | |
| 333 | + removekey(n); /* remove entry from table */ | |
| 226 | 334 | } |
| 335 | + l = h->gclist; | |
| 227 | 336 | } |
| 228 | 337 | } |
| 229 | 338 | |
| 230 | 339 | |
| 231 | −static void checktab (lua_State *L, stringtable *tb) { | |
| 232 | − if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) | |
| 233 | − luaS_resize(L, tb, tb->size/2); /* table is too big */ | |
| 340 | +static void freeobj (lua_State *L, GCObject *o) { | |
| 341 | + switch (o->gch.tt) { | |
| 342 | + case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break; | |
| 343 | + case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break; | |
| 344 | + case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break; | |
| 345 | + case LUA_TTABLE: luaH_free(L, gcotoh(o)); break; | |
| 346 | + case LUA_TTHREAD: { | |
| 347 | + lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread); | |
| 348 | + luaE_freethread(L, gcototh(o)); | |
| 349 | + break; | |
| 350 | + } | |
| 351 | + case LUA_TSTRING: { | |
| 352 | + luaM_free(L, o, sizestring(gcotots(o)->tsv.len)); | |
| 353 | + break; | |
| 354 | + } | |
| 355 | + case LUA_TUSERDATA: { | |
| 356 | + luaM_free(L, o, sizeudata(gcotou(o)->uv.len)); | |
| 357 | + break; | |
| 358 | + } | |
| 359 | + default: lua_assert(0); | |
| 360 | + } | |
| 234 | 361 | } |
| 235 | 362 | |
| 236 | 363 | |
| 237 | −static void collectstrings (lua_State *L, int all) { | |
| 238 | − int i; | |
| 239 | − for (i=0; i<L->strt.size; i++) { /* for each list */ | |
| 240 | − TString **p = &L->strt.hash[i]; | |
| 241 | − TString *next; | |
| 242 | − while ((next = *p) != NULL) { | |
| 243 | − if (next->marked && !all) { /* preserve? */ | |
| 244 | − if (next->marked < FIXMARK) /* does not change FIXMARKs */ | |
| 245 | − next->marked = 0; | |
| 246 | − p = &next->nexthash; | |
| 247 | − } | |
| 248 | − else { /* collect */ | |
| 249 | − *p = next->nexthash; | |
| 250 | − L->strt.nuse--; | |
| 251 | − L->nblocks -= sizestring(next->len); | |
| 252 | − luaM_free(L, next); | |
| 253 | − } | |
| 364 | +static int sweeplist (lua_State *L, GCObject **p, int limit) { | |
| 365 | + GCObject *curr; | |
| 366 | + int count = 0; /* number of collected items */ | |
| 367 | + while ((curr = *p) != NULL) { | |
| 368 | + if (curr->gch.marked > limit) { | |
| 369 | + unmark(curr); | |
| 370 | + p = &curr->gch.next; | |
| 371 | + } | |
| 372 | + else { | |
| 373 | + count++; | |
| 374 | + *p = curr->gch.next; | |
| 375 | + freeobj(L, curr); | |
| 254 | 376 | } |
| 255 | 377 | } |
| 256 | − checktab(L, &L->strt); | |
| 378 | + return count; | |
| 257 | 379 | } |
| 258 | 380 | |
| 259 | 381 | |
| 260 | −static void collectudata (lua_State *L, int all) { | |
| 382 | +static void sweepstrings (lua_State *L, int all) { | |
| 261 | 383 | int i; |
| 262 | − for (i=0; i<L->udt.size; i++) { /* for each list */ | |
| 263 | − TString **p = &L->udt.hash[i]; | |
| 264 | − TString *next; | |
| 265 | − while ((next = *p) != NULL) { | |
| 266 | − LUA_ASSERT(next->marked <= 1, "udata cannot be fixed"); | |
| 267 | − if (next->marked && !all) { /* preserve? */ | |
| 268 | − next->marked = 0; | |
| 269 | − p = &next->nexthash; | |
| 270 | − } | |
| 271 | − else { /* collect */ | |
| 272 | − int tag = next->u.d.tag; | |
| 273 | − *p = next->nexthash; | |
| 274 | − next->nexthash = L->TMtable[tag].collected; /* chain udata */ | |
| 275 | − L->TMtable[tag].collected = next; | |
| 276 | − L->nblocks -= sizestring(next->len); | |
| 277 | − L->udt.nuse--; | |
| 278 | − } | |
| 279 | − } | |
| 384 | + for (i=0; i<G(L)->strt.size; i++) { /* for each list */ | |
| 385 | + G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all); | |
| 280 | 386 | } |
| 281 | − checktab(L, &L->udt); | |
| 282 | 387 | } |
| 283 | 388 | |
| 284 | 389 | |
| 285 | −#define MINBUFFER 256 | |
| 286 | −static void checkMbuffer (lua_State *L) { | |
| 287 | − if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */ | |
| 288 | − size_t newsize = L->Mbuffsize/2; /* still larger than MINBUFFER */ | |
| 289 | − L->nblocks += (newsize - L->Mbuffsize)*sizeof(char); | |
| 290 | − L->Mbuffsize = newsize; | |
| 291 | − luaM_reallocvector(L, L->Mbuffer, newsize, char); | |
| 390 | +static void checkSizes (lua_State *L) { | |
| 391 | + /* check size of string hash */ | |
| 392 | + if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) && | |
| 393 | + G(L)->strt.size > MINSTRTABSIZE*2) | |
| 394 | + luaS_resize(L, G(L)->strt.size/2); /* table is too big */ | |
| 395 | + /* check size of buffer */ | |
| 396 | + if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ | |
| 397 | + size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2; | |
| 398 | + luaZ_resizebuffer(L, &G(L)->buff, newsize); | |
| 292 | 399 | } |
| 400 | + G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ | |
| 293 | 401 | } |
| 294 | 402 | |
| 295 | 403 | |
| 296 | −static void callgcTM (lua_State *L, const TObject *o) { | |
| 297 | − Closure *tm = luaT_gettmbyObj(L, o, TM_GC); | |
| 404 | +static void do1gcTM (lua_State *L, Udata *udata) { | |
| 405 | + const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC); | |
| 298 | 406 | if (tm != NULL) { |
| 299 | − int oldah = L->allowhooks; | |
| 300 | − L->allowhooks = 0; /* stop debug hooks during GC tag methods */ | |
| 301 | − luaD_checkstack(L, 2); | |
| 302 | − clvalue(L->top) = tm; | |
| 303 | − ttype(L->top) = LUA_TFUNCTION; | |
| 304 | − *(L->top+1) = *o; | |
| 407 | + setobj2s(L->top, tm); | |
| 408 | + setuvalue(L->top+1, udata); | |
| 305 | 409 | L->top += 2; |
| 306 | − luaD_call(L, L->top-2, 0); | |
| 307 | − L->allowhooks = oldah; /* restore hooks */ | |
| 410 | + luaD_call(L, L->top - 2, 0); | |
| 308 | 411 | } |
| 309 | 412 | } |
| 310 | 413 | |
| 311 | 414 | |
| 312 | −static void callgcTMudata (lua_State *L) { | |
| 313 | − int tag; | |
| 314 | − TObject o; | |
| 315 | − ttype(&o) = LUA_TUSERDATA; | |
| 316 | − L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */ | |
| 317 | − for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */ | |
| 318 | − TString *udata; | |
| 319 | − while ((udata = L->TMtable[tag].collected) != NULL) { | |
| 320 | − L->TMtable[tag].collected = udata->nexthash; /* remove it from list */ | |
| 321 | − tsvalue(&o) = udata; | |
| 322 | − callgcTM(L, &o); | |
| 323 | − luaM_free(L, udata); | |
| 324 | − } | |
| 415 | +void luaC_callGCTM (lua_State *L) { | |
| 416 | + lu_byte oldah = L->allowhook; | |
| 417 | + L->allowhook = 0; /* stop debug hooks during GC tag methods */ | |
| 418 | + L->top++; /* reserve space to keep udata while runs its gc method */ | |
| 419 | + while (G(L)->tmudata != NULL) { | |
| 420 | + GCObject *o = G(L)->tmudata; | |
| 421 | + Udata *udata = gcotou(o); | |
| 422 | + G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */ | |
| 423 | + udata->uv.next = G(L)->rootudata; /* return it to `root' list */ | |
| 424 | + G(L)->rootudata = o; | |
| 425 | + setuvalue(L->top - 1, udata); /* keep a reference to it */ | |
| 426 | + unmark(o); | |
| 427 | + markfinalized(udata); | |
| 428 | + do1gcTM(L, udata); | |
| 325 | 429 | } |
| 430 | + L->top--; | |
| 431 | + L->allowhook = oldah; /* restore hooks */ | |
| 326 | 432 | } |
| 327 | 433 | |
| 328 | 434 | |
| 329 | −void luaC_collect (lua_State *L, int all) { | |
| 330 | − collectudata(L, all); | |
| 331 | − callgcTMudata(L); | |
| 332 | − collectstrings(L, all); | |
| 333 | − collecttable(L); | |
| 334 | − collectproto(L); | |
| 335 | − collectclosure(L); | |
| 435 | +void luaC_sweep (lua_State *L, int all) { | |
| 436 | + if (all) all = 256; /* larger than any mark */ | |
| 437 | + sweeplist(L, &G(L)->rootudata, all); | |
| 438 | + sweepstrings(L, all); | |
| 439 | + sweeplist(L, &G(L)->rootgc, all); | |
| 440 | +} | |
| 441 | + | |
| 442 | + | |
| 443 | +/* mark root set */ | |
| 444 | +static void markroot (GCState *st, lua_State *L) { | |
| 445 | + global_State *g = st->g; | |
| 446 | + markobject(st, defaultmeta(L)); | |
| 447 | + markobject(st, registry(L)); | |
| 448 | + traversestack(st, g->mainthread); | |
| 449 | + if (L != g->mainthread) /* another thread is running? */ | |
| 450 | + markvalue(st, L); /* cannot collect it */ | |
| 451 | +} | |
| 452 | + | |
| 453 | + | |
| 454 | +static void mark (lua_State *L) { | |
| 455 | + GCState st; | |
| 456 | + GCObject *wkv; | |
| 457 | + st.g = G(L); | |
| 458 | + st.tmark = NULL; | |
| 459 | + st.wkv = st.wk = st.wv = NULL; | |
| 460 | + markroot(&st, L); | |
| 461 | + propagatemarks(&st); /* mark all reachable objects */ | |
| 462 | + cleartablevalues(st.wkv); | |
| 463 | + cleartablevalues(st.wv); | |
| 464 | + wkv = st.wkv; /* keys must be cleared after preserving udata */ | |
| 465 | + st.wkv = NULL; | |
| 466 | + st.wv = NULL; | |
| 467 | + luaC_separateudata(L); /* separate userdata to be preserved */ | |
| 468 | + marktmu(&st); /* mark `preserved' userdata */ | |
| 469 | + propagatemarks(&st); /* remark, to propagate `preserveness' */ | |
| 470 | + cleartablekeys(wkv); | |
| 471 | + /* `propagatemarks' may resuscitate some weak tables; clear them too */ | |
| 472 | + cleartablekeys(st.wk); | |
| 473 | + cleartablevalues(st.wv); | |
| 474 | + cleartablekeys(st.wkv); | |
| 475 | + cleartablevalues(st.wkv); | |
| 336 | 476 | } |
| 337 | 477 | |
| 338 | 478 | |
| 339 | 479 | void luaC_collectgarbage (lua_State *L) { |
| 340 | − markall(L); | |
| 341 | − invalidaterefs(L); /* check unlocked references */ | |
| 342 | − luaC_collect(L, 0); | |
| 343 | − checkMbuffer(L); | |
| 344 | − L->GCthreshold = 2*L->nblocks; /* set new threshold */ | |
| 345 | − callgcTM(L, &luaO_nilobject); | |
| 480 | + mark(L); | |
| 481 | + luaC_sweep(L, 0); | |
| 482 | + checkSizes(L); | |
| 483 | + luaC_callGCTM(L); | |
| 346 | 484 | } |
| 347 | 485 | |
| 348 | 486 | |
| 349 | −void luaC_checkGC (lua_State *L) { | |
| 350 | − if (L->nblocks >= L->GCthreshold) | |
| 351 | − luaC_collectgarbage(L); | |
| 487 | +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { | |
| 488 | + o->gch.next = G(L)->rootgc; | |
| 489 | + G(L)->rootgc = o; | |
| 490 | + o->gch.marked = 0; | |
| 491 | + o->gch.tt = tt; | |
| 352 | 492 | } |
| 353 | 493 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lgc.h,v 1.9 2001/02/02 16:23:20 roberto Exp $ | |
| 2 | +** $Id: lgc.h,v 1.19 2003/02/28 19:45:15 roberto Exp $ | |
| 3 | 3 | ** Garbage Collector |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -11,9 +11,15 @@ · 5 unmodified lines | ||
| 11 | 11 | #include "lobject.h" |
| 12 | 12 | |
| 13 | 13 | |
| 14 | −void luaC_collect (lua_State *L, int all); | |
| 14 | +#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \ | |
| 15 | + if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); } | |
| 16 | + | |
| 17 | + | |
| 18 | +void luaC_separateudata (lua_State *L); | |
| 19 | +void luaC_callGCTM (lua_State *L); | |
| 20 | +void luaC_sweep (lua_State *L, int all); | |
| 15 | 21 | void luaC_collectgarbage (lua_State *L); |
| 16 | −void luaC_checkGC (lua_State *L); | |
| 22 | +void luaC_link (lua_State *L, GCObject *o, lu_byte tt); | |
| 17 | 23 | |
| 18 | 24 | |
| 19 | 25 | #endif |
| @@ -4,17 +4,16 @@ LUA= ../.. · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | include $(LUA)/config |
| 6 | 6 | |
| 7 | −# actually only used in liolib.c | |
| 8 | −EXTRA_DEFS= $(POPEN) | |
| 7 | +EXTRA_DEFS= $(POPEN) $(TMPNAM) $(DEGREES) $(LOADLIB) | |
| 9 | 8 | |
| 10 | −OBJS= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o lstrlib.o | |
| 11 | −SRCS= lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c lstrlib.c | |
| 9 | +OBJS= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o ltablib.o lstrlib.o loadlib.o | |
| 10 | +SRCS= lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c ltablib.c lstrlib.c loadlib.c | |
| 12 | 11 | |
| 13 | 12 | T= $(LIB)/liblualib.a |
| 14 | 13 | |
| 15 | −all: $T | |
| 14 | +all: $T | |
| 16 | 15 | |
| 17 | −$T: $(OBJS) | |
| 16 | +$T: $(OBJS) | |
| 18 | 17 | $(AR) $@ $(OBJS) |
| 19 | 18 | $(RANLIB) $@ |
| 20 | 19 | |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | This is the standard Lua library. |
| 2 | −It is implemented entirely on top of the official Lua API as declared in lua.h, | |
| 3 | −using lauxlib.c, which contains several useful functions for writing libraries. | |
| 4 | −We encourage developers to use lauxlib.c in their own libraries. | |
| 2 | + | |
| 5 | 3 | The code of the standard library can be read as an example of how to export |
| 6 | −C functions to Lua. | |
| 4 | +C functions to Lua. The easiest library to read is lmathlib.c. | |
| 5 | + | |
| 6 | +The library is implemented entirely on top of the official Lua API as declared | |
| 7 | +in lua.h, using lauxlib.c, which contains several useful functions for writing | |
| 8 | +libraries. We encourage developers to use lauxlib.c in their own libraries. | |
| @@ -1,25 +1,101 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lauxlib.c,v 1.43 2000/10/30 13:07:48 roberto Exp $ | |
| 2 | +** $Id: lauxlib.c,v 1.100 2003/04/07 14:35:00 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | +#include <ctype.h> | |
| 9 | +#include <errno.h> | |
| 8 | 10 | #include <stdarg.h> |
| 9 | 11 | #include <stdio.h> |
| 10 | 12 | #include <string.h> |
| 11 | 13 | |
| 14 | + | |
| 12 | 15 | /* This file uses only the official API of Lua. |
| 13 | 16 | ** Any function declared here could be written as an application function. |
| 14 | −** With care, these functions can be used by other libraries. | |
| 15 | 17 | */ |
| 16 | 18 | |
| 19 | +#define lauxlib_c | |
| 20 | + | |
| 17 | 21 | #include "lua.h" |
| 18 | 22 | |
| 19 | 23 | #include "lauxlib.h" |
| 20 | −#include "luadebug.h" | |
| 21 | 24 | |
| 22 | 25 | |
| 26 | +/* number of prereserved references (for internal use) */ | |
| 27 | +#define RESERVED_REFS 2 | |
| 28 | + | |
| 29 | +/* reserved references */ | |
| 30 | +#define FREELIST_REF 1 /* free list of references */ | |
| 31 | +#define ARRAYSIZE_REF 2 /* array sizes */ | |
| 32 | + | |
| 33 | + | |
| 34 | +/* convert a stack index to positive */ | |
| 35 | +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ | |
| 36 | + lua_gettop(L) + (i) + 1) | |
| 37 | + | |
| 38 | + | |
| 39 | +/* | |
| 40 | +** {====================================================== | |
| 41 | +** Error-report functions | |
| 42 | +** ======================================================= | |
| 43 | +*/ | |
| 44 | + | |
| 45 | + | |
| 46 | +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | |
| 47 | + lua_Debug ar; | |
| 48 | + lua_getstack(L, 0, &ar); | |
| 49 | + lua_getinfo(L, "n", &ar); | |
| 50 | + if (strcmp(ar.namewhat, "method") == 0) { | |
| 51 | + narg--; /* do not count `self' */ | |
| 52 | + if (narg == 0) /* error is in the self argument itself? */ | |
| 53 | + return luaL_error(L, "calling `%s' on bad self (%s)", ar.name, extramsg); | |
| 54 | + } | |
| 55 | + if (ar.name == NULL) | |
| 56 | + ar.name = "?"; | |
| 57 | + return luaL_error(L, "bad argument #%d to `%s' (%s)", | |
| 58 | + narg, ar.name, extramsg); | |
| 59 | +} | |
| 60 | + | |
| 61 | + | |
| 62 | +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { | |
| 63 | + const char *msg = lua_pushfstring(L, "%s expected, got %s", | |
| 64 | + tname, lua_typename(L, lua_type(L,narg))); | |
| 65 | + return luaL_argerror(L, narg, msg); | |
| 66 | +} | |
| 67 | + | |
| 68 | + | |
| 69 | +static void tag_error (lua_State *L, int narg, int tag) { | |
| 70 | + luaL_typerror(L, narg, lua_typename(L, tag)); | |
| 71 | +} | |
| 72 | + | |
| 73 | + | |
| 74 | +LUALIB_API void luaL_where (lua_State *L, int level) { | |
| 75 | + lua_Debug ar; | |
| 76 | + if (lua_getstack(L, level, &ar)) { /* check function at level */ | |
| 77 | + lua_getinfo(L, "Snl", &ar); /* get info about it */ | |
| 78 | + if (ar.currentline > 0) { /* is there info? */ | |
| 79 | + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); | |
| 80 | + return; | |
| 81 | + } | |
| 82 | + } | |
| 83 | + lua_pushliteral(L, ""); /* else, no information available... */ | |
| 84 | +} | |
| 85 | + | |
| 86 | + | |
| 87 | +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { | |
| 88 | + va_list argp; | |
| 89 | + va_start(argp, fmt); | |
| 90 | + luaL_where(L, 1); | |
| 91 | + lua_pushvfstring(L, fmt, argp); | |
| 92 | + va_end(argp); | |
| 93 | + lua_concat(L, 2); | |
| 94 | + return lua_error(L); | |
| 95 | +} | |
| 96 | + | |
| 97 | +/* }====================================================== */ | |
| 98 | + | |
| 23 | 99 | |
| 24 | 100 | LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { |
| 25 | 101 | int i; |
| @@ -29,34 +105,55 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { · 3 unmodified lines | ||
| 29 | 105 | return -1; /* name not found */ |
| 30 | 106 | } |
| 31 | 107 | |
| 32 | −LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) { | |
| 33 | − lua_Debug ar; | |
| 34 | − lua_getstack(L, 0, &ar); | |
| 35 | − lua_getinfo(L, "n", &ar); | |
| 36 | − if (ar.name == NULL) | |
| 37 | − ar.name = "?"; | |
| 38 | − luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)", | |
| 39 | − narg, ar.name, extramsg); | |
| 108 | + | |
| 109 | +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { | |
| 110 | + lua_pushstring(L, tname); | |
| 111 | + lua_rawget(L, LUA_REGISTRYINDEX); /* get registry.name */ | |
| 112 | + if (!lua_isnil(L, -1)) /* name already in use? */ | |
| 113 | + return 0; /* leave previous value on top, but return 0 */ | |
| 114 | + lua_pop(L, 1); | |
| 115 | + lua_newtable(L); /* create metatable */ | |
| 116 | + lua_pushstring(L, tname); | |
| 117 | + lua_pushvalue(L, -2); | |
| 118 | + lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */ | |
| 119 | + lua_pushvalue(L, -1); | |
| 120 | + lua_pushstring(L, tname); | |
| 121 | + lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */ | |
| 122 | + return 1; | |
| 40 | 123 | } |
| 41 | 124 | |
| 42 | 125 | |
| 43 | −static void type_error (lua_State *L, int narg, int t) { | |
| 44 | − char buff[50]; | |
| 45 | − sprintf(buff, "%.8s expected, got %.8s", lua_typename(L, t), | |
| 46 | − lua_typename(L, lua_type(L, narg))); | |
| 47 | − luaL_argerror(L, narg, buff); | |
| 126 | +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) { | |
| 127 | + lua_pushstring(L, tname); | |
| 128 | + lua_rawget(L, LUA_REGISTRYINDEX); | |
| 129 | +} | |
| 130 | + | |
| 131 | + | |
| 132 | +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { | |
| 133 | + const char *tn; | |
| 134 | + if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */ | |
| 135 | + lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */ | |
| 136 | + tn = lua_tostring(L, -1); | |
| 137 | + if (tn && (strcmp(tn, tname) == 0)) { | |
| 138 | + lua_pop(L, 1); | |
| 139 | + return lua_touserdata(L, ud); | |
| 140 | + } | |
| 141 | + else { | |
| 142 | + lua_pop(L, 1); | |
| 143 | + return NULL; | |
| 144 | + } | |
| 48 | 145 | } |
| 49 | 146 | |
| 50 | 147 | |
| 51 | 148 | LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { |
| 52 | − if (space > lua_stackspace(L)) | |
| 53 | − luaL_verror(L, "stack overflow (%.30s)", mes); | |
| 149 | + if (!lua_checkstack(L, space)) | |
| 150 | + luaL_error(L, "stack overflow (%s)", mes); | |
| 54 | 151 | } |
| 55 | 152 | |
| 56 | 153 | |
| 57 | −LUALIB_API void luaL_checktype(lua_State *L, int narg, int t) { | |
| 154 | +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { | |
| 58 | 155 | if (lua_type(L, narg) != t) |
| 59 | − type_error(L, narg, t); | |
| 156 | + tag_error(L, narg, t); | |
| 60 | 157 | } |
| 61 | 158 | |
| 62 | 159 | |
| @@ -66,55 +163,164 @@ LUALIB_API void luaL_checkany (lua_State *L, int narg) { · 3 unmodified lines | ||
| 66 | 163 | } |
| 67 | 164 | |
| 68 | 165 | |
| 69 | −LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) { | |
| 166 | +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { | |
| 70 | 167 | const char *s = lua_tostring(L, narg); |
| 71 | − if (!s) type_error(L, narg, LUA_TSTRING); | |
| 168 | + if (!s) tag_error(L, narg, LUA_TSTRING); | |
| 72 | 169 | if (len) *len = lua_strlen(L, narg); |
| 73 | 170 | return s; |
| 74 | 171 | } |
| 75 | 172 | |
| 76 | 173 | |
| 77 | −LUALIB_API const char *luaL_opt_lstr (lua_State *L, int narg, const char *def, size_t *len) { | |
| 78 | − if (lua_isnull(L, narg)) { | |
| 174 | +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, | |
| 175 | + const char *def, size_t *len) { | |
| 176 | + if (lua_isnoneornil(L, narg)) { | |
| 79 | 177 | if (len) |
| 80 | 178 | *len = (def ? strlen(def) : 0); |
| 81 | 179 | return def; |
| 82 | 180 | } |
| 83 | − else return luaL_check_lstr(L, narg, len); | |
| 181 | + else return luaL_checklstring(L, narg, len); | |
| 84 | 182 | } |
| 85 | 183 | |
| 86 | 184 | |
| 87 | −LUALIB_API double luaL_check_number (lua_State *L, int narg) { | |
| 88 | − double d = lua_tonumber(L, narg); | |
| 185 | +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { | |
| 186 | + lua_Number d = lua_tonumber(L, narg); | |
| 89 | 187 | if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ |
| 90 | − type_error(L, narg, LUA_TNUMBER); | |
| 188 | + tag_error(L, narg, LUA_TNUMBER); | |
| 91 | 189 | return d; |
| 92 | 190 | } |
| 93 | 191 | |
| 94 | 192 | |
| 95 | −LUALIB_API double luaL_opt_number (lua_State *L, int narg, double def) { | |
| 96 | − if (lua_isnull(L, narg)) return def; | |
| 97 | − else return luaL_check_number(L, narg); | |
| 193 | +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { | |
| 194 | + if (lua_isnoneornil(L, narg)) return def; | |
| 195 | + else return luaL_checknumber(L, narg); | |
| 98 | 196 | } |
| 99 | 197 | |
| 100 | 198 | |
| 101 | −LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n) { | |
| 102 | − int i; | |
| 103 | − for (i=0; i<n; i++) | |
| 104 | − lua_register(L, l[i].name, l[i].func); | |
| 199 | +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { | |
| 200 | + if (!lua_getmetatable(L, obj)) /* no metatable? */ | |
| 201 | + return 0; | |
| 202 | + lua_pushstring(L, event); | |
| 203 | + lua_rawget(L, -2); | |
| 204 | + if (lua_isnil(L, -1)) { | |
| 205 | + lua_pop(L, 2); /* remove metatable and metafield */ | |
| 206 | + return 0; | |
| 207 | + } | |
| 208 | + else { | |
| 209 | + lua_remove(L, -2); /* remove only metatable */ | |
| 210 | + return 1; | |
| 211 | + } | |
| 105 | 212 | } |
| 106 | 213 | |
| 107 | 214 | |
| 108 | −LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...) { | |
| 109 | − char buff[500]; | |
| 110 | − va_list argp; | |
| 111 | − va_start(argp, fmt); | |
| 112 | − vsprintf(buff, fmt, argp); | |
| 113 | − va_end(argp); | |
| 114 | − lua_error(L, buff); | |
| 215 | +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { | |
| 216 | + obj = abs_index(L, obj); | |
| 217 | + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ | |
| 218 | + return 0; | |
| 219 | + lua_pushvalue(L, obj); | |
| 220 | + lua_call(L, 1, 1); | |
| 221 | + return 1; | |
| 115 | 222 | } |
| 116 | 223 | |
| 117 | 224 | |
| 225 | +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | |
| 226 | + const luaL_reg *l, int nup) { | |
| 227 | + if (libname) { | |
| 228 | + lua_pushstring(L, libname); | |
| 229 | + lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */ | |
| 230 | + if (lua_isnil(L, -1)) { /* no? */ | |
| 231 | + lua_pop(L, 1); | |
| 232 | + lua_newtable(L); /* create it */ | |
| 233 | + lua_pushstring(L, libname); | |
| 234 | + lua_pushvalue(L, -2); | |
| 235 | + lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */ | |
| 236 | + } | |
| 237 | + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ | |
| 238 | + } | |
| 239 | + for (; l->name; l++) { | |
| 240 | + int i; | |
| 241 | + lua_pushstring(L, l->name); | |
| 242 | + for (i=0; i<nup; i++) /* copy upvalues to the top */ | |
| 243 | + lua_pushvalue(L, -(nup+1)); | |
| 244 | + lua_pushcclosure(L, l->func, nup); | |
| 245 | + lua_settable(L, -(nup+3)); | |
| 246 | + } | |
| 247 | + lua_pop(L, nup); /* remove upvalues */ | |
| 248 | +} | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | +/* | |
| 253 | +** {====================================================== | |
| 254 | +** getn-setn: size for arrays | |
| 255 | +** ======================================================= | |
| 256 | +*/ | |
| 257 | + | |
| 258 | +static int checkint (lua_State *L, int topop) { | |
| 259 | + int n = (int)lua_tonumber(L, -1); | |
| 260 | + if (n == 0 && !lua_isnumber(L, -1)) n = -1; | |
| 261 | + lua_pop(L, topop); | |
| 262 | + return n; | |
| 263 | +} | |
| 264 | + | |
| 265 | + | |
| 266 | +static void getsizes (lua_State *L) { | |
| 267 | + lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); | |
| 268 | + if (lua_isnil(L, -1)) { /* no `size' table? */ | |
| 269 | + lua_pop(L, 1); /* remove nil */ | |
| 270 | + lua_newtable(L); /* create it */ | |
| 271 | + lua_pushvalue(L, -1); /* `size' will be its own metatable */ | |
| 272 | + lua_setmetatable(L, -2); | |
| 273 | + lua_pushliteral(L, "__mode"); | |
| 274 | + lua_pushliteral(L, "k"); | |
| 275 | + lua_rawset(L, -3); /* metatable(N).__mode = "k" */ | |
| 276 | + lua_pushvalue(L, -1); | |
| 277 | + lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ | |
| 278 | + } | |
| 279 | +} | |
| 280 | + | |
| 281 | + | |
| 282 | +void luaL_setn (lua_State *L, int t, int n) { | |
| 283 | + t = abs_index(L, t); | |
| 284 | + lua_pushliteral(L, "n"); | |
| 285 | + lua_rawget(L, t); | |
| 286 | + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ | |
| 287 | + lua_pushliteral(L, "n"); /* use it */ | |
| 288 | + lua_pushnumber(L, (lua_Number)n); | |
| 289 | + lua_rawset(L, t); | |
| 290 | + } | |
| 291 | + else { /* use `sizes' */ | |
| 292 | + getsizes(L); | |
| 293 | + lua_pushvalue(L, t); | |
| 294 | + lua_pushnumber(L, (lua_Number)n); | |
| 295 | + lua_rawset(L, -3); /* sizes[t] = n */ | |
| 296 | + lua_pop(L, 1); /* remove `sizes' */ | |
| 297 | + } | |
| 298 | +} | |
| 299 | + | |
| 300 | + | |
| 301 | +int luaL_getn (lua_State *L, int t) { | |
| 302 | + int n; | |
| 303 | + t = abs_index(L, t); | |
| 304 | + lua_pushliteral(L, "n"); /* try t.n */ | |
| 305 | + lua_rawget(L, t); | |
| 306 | + if ((n = checkint(L, 1)) >= 0) return n; | |
| 307 | + getsizes(L); /* else try sizes[t] */ | |
| 308 | + lua_pushvalue(L, t); | |
| 309 | + lua_rawget(L, -2); | |
| 310 | + if ((n = checkint(L, 2)) >= 0) return n; | |
| 311 | + for (n = 1; ; n++) { /* else must count elements */ | |
| 312 | + lua_rawgeti(L, t, n); | |
| 313 | + if (lua_isnil(L, -1)) break; | |
| 314 | + lua_pop(L, 1); | |
| 315 | + } | |
| 316 | + lua_pop(L, 1); | |
| 317 | + return n - 1; | |
| 318 | +} | |
| 319 | + | |
| 320 | +/* }====================================================== */ | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 118 | 324 | /* |
| 119 | 325 | ** {====================================================== |
| 120 | 326 | ** Generic Buffer manipulation |
| @@ -122,7 +328,6 @@ LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...) { · 1 unmodified line | ||
| 122 | 328 | */ |
| 123 | 329 | |
| 124 | 330 | |
| 125 | −#define buffempty(B) ((B)->p == (B)->buffer) | |
| 126 | 331 | #define bufflen(B) ((B)->p - (B)->buffer) |
| 127 | 332 | #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) |
| 128 | 333 | |
| @@ -135,29 +340,27 @@ static int emptybuffer (luaL_Buffer *B) { · 6 unmodified lines | ||
| 135 | 340 | else { |
| 136 | 341 | lua_pushlstring(B->L, B->buffer, l); |
| 137 | 342 | B->p = B->buffer; |
| 138 | − B->level++; | |
| 343 | + B->lvl++; | |
| 139 | 344 | return 1; |
| 140 | 345 | } |
| 141 | 346 | } |
| 142 | 347 | |
| 143 | 348 | |
| 144 | 349 | static void adjuststack (luaL_Buffer *B) { |
| 145 | − if (B->level > 1) { | |
| 350 | + if (B->lvl > 1) { | |
| 146 | 351 | lua_State *L = B->L; |
| 147 | 352 | int toget = 1; /* number of levels to concat */ |
| 148 | 353 | size_t toplen = lua_strlen(L, -1); |
| 149 | 354 | do { |
| 150 | 355 | size_t l = lua_strlen(L, -(toget+1)); |
| 151 | − if (B->level - toget + 1 >= LIMIT || toplen > l) { | |
| 356 | + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { | |
| 152 | 357 | toplen += l; |
| 153 | 358 | toget++; |
| 154 | 359 | } |
| 155 | 360 | else break; |
| 156 | − } while (toget < B->level); | |
| 157 | − if (toget >= 2) { | |
| 158 | − lua_concat(L, toget); | |
| 159 | − B->level = B->level - toget + 1; | |
| 160 | − } | |
| 361 | + } while (toget < B->lvl); | |
| 362 | + lua_concat(L, toget); | |
| 363 | + B->lvl = B->lvl - toget + 1; | |
| 161 | 364 | } |
| 162 | 365 | } |
| 163 | 366 | |
| @@ -182,11 +385,8 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { · 18 unmodified lines | ||
| 182 | 385 | |
| 183 | 386 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { |
| 184 | 387 | emptybuffer(B); |
| 185 | − if (B->level == 0) | |
| 186 | − lua_pushlstring(B->L, NULL, 0); | |
| 187 | − else if (B->level > 1) | |
| 188 | − lua_concat(B->L, B->level); | |
| 189 | − B->level = 1; | |
| 388 | + lua_concat(B->L, B->lvl); | |
| 389 | + B->lvl = 1; | |
| 190 | 390 | } |
| 191 | 391 | |
| 192 | 392 | |
| @@ -201,7 +401,7 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) { · 8 unmodified lines | ||
| 201 | 401 | else { |
| 202 | 402 | if (emptybuffer(B)) |
| 203 | 403 | lua_insert(L, -2); /* put buffer before new value */ |
| 204 | − B->level++; /* add new value into B stack */ | |
| 404 | + B->lvl++; /* add new value into B stack */ | |
| 205 | 405 | adjuststack(B); |
| 206 | 406 | } |
| 207 | 407 | } |
| @@ -210,7 +410,182 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) { · 2 unmodified lines | ||
| 210 | 410 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { |
| 211 | 411 | B->L = L; |
| 212 | 412 | B->p = B->buffer; |
| 213 | − B->level = 0; | |
| 413 | + B->lvl = 0; | |
| 414 | +} | |
| 415 | + | |
| 416 | +/* }====================================================== */ | |
| 417 | + | |
| 418 | + | |
| 419 | +LUALIB_API int luaL_ref (lua_State *L, int t) { | |
| 420 | + int ref; | |
| 421 | + t = abs_index(L, t); | |
| 422 | + if (lua_isnil(L, -1)) { | |
| 423 | + lua_pop(L, 1); /* remove from stack */ | |
| 424 | + return LUA_REFNIL; /* `nil' has a unique fixed reference */ | |
| 425 | + } | |
| 426 | + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ | |
| 427 | + ref = (int)lua_tonumber(L, -1); /* ref = t[FREELIST_REF] */ | |
| 428 | + lua_pop(L, 1); /* remove it from stack */ | |
| 429 | + if (ref != 0) { /* any free element? */ | |
| 430 | + lua_rawgeti(L, t, ref); /* remove it from list */ | |
| 431 | + lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ | |
| 432 | + } | |
| 433 | + else { /* no free elements */ | |
| 434 | + ref = luaL_getn(L, t); | |
| 435 | + if (ref < RESERVED_REFS) | |
| 436 | + ref = RESERVED_REFS; /* skip reserved references */ | |
| 437 | + ref++; /* create new reference */ | |
| 438 | + luaL_setn(L, t, ref); | |
| 439 | + } | |
| 440 | + lua_rawseti(L, t, ref); | |
| 441 | + return ref; | |
| 442 | +} | |
| 443 | + | |
| 444 | + | |
| 445 | +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | |
| 446 | + if (ref >= 0) { | |
| 447 | + t = abs_index(L, t); | |
| 448 | + lua_rawgeti(L, t, FREELIST_REF); | |
| 449 | + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ | |
| 450 | + lua_pushnumber(L, (lua_Number)ref); | |
| 451 | + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ | |
| 452 | + } | |
| 453 | +} | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | +/* | |
| 458 | +** {====================================================== | |
| 459 | +** Load functions | |
| 460 | +** ======================================================= | |
| 461 | +*/ | |
| 462 | + | |
| 463 | +typedef struct LoadF { | |
| 464 | + FILE *f; | |
| 465 | + char buff[LUAL_BUFFERSIZE]; | |
| 466 | +} LoadF; | |
| 467 | + | |
| 468 | + | |
| 469 | +static const char *getF (lua_State *L, void *ud, size_t *size) { | |
| 470 | + LoadF *lf = (LoadF *)ud; | |
| 471 | + (void)L; | |
| 472 | + if (feof(lf->f)) return NULL; | |
| 473 | + *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f); | |
| 474 | + return (*size > 0) ? lf->buff : NULL; | |
| 475 | +} | |
| 476 | + | |
| 477 | + | |
| 478 | +static int errfile (lua_State *L, int fnameindex) { | |
| 479 | + const char *filename = lua_tostring(L, fnameindex) + 1; | |
| 480 | + lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno)); | |
| 481 | + lua_remove(L, fnameindex); | |
| 482 | + return LUA_ERRFILE; | |
| 483 | +} | |
| 484 | + | |
| 485 | + | |
| 486 | +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { | |
| 487 | + LoadF lf; | |
| 488 | + int status, readstatus; | |
| 489 | + int c; | |
| 490 | + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ | |
| 491 | + if (filename == NULL) { | |
| 492 | + lua_pushliteral(L, "=stdin"); | |
| 493 | + lf.f = stdin; | |
| 494 | + } | |
| 495 | + else { | |
| 496 | + lua_pushfstring(L, "@%s", filename); | |
| 497 | + lf.f = fopen(filename, "r"); | |
| 498 | + } | |
| 499 | + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */ | |
| 500 | + c = ungetc(getc(lf.f), lf.f); | |
| 501 | + if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ | |
| 502 | + fclose(lf.f); | |
| 503 | + lf.f = fopen(filename, "rb"); /* reopen in binary mode */ | |
| 504 | + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */ | |
| 505 | + } | |
| 506 | + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); | |
| 507 | + readstatus = ferror(lf.f); | |
| 508 | + if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */ | |
| 509 | + if (readstatus) { | |
| 510 | + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ | |
| 511 | + return errfile(L, fnameindex); | |
| 512 | + } | |
| 513 | + lua_remove(L, fnameindex); | |
| 514 | + return status; | |
| 515 | +} | |
| 516 | + | |
| 517 | + | |
| 518 | +typedef struct LoadS { | |
| 519 | + const char *s; | |
| 520 | + size_t size; | |
| 521 | +} LoadS; | |
| 522 | + | |
| 523 | + | |
| 524 | +static const char *getS (lua_State *L, void *ud, size_t *size) { | |
| 525 | + LoadS *ls = (LoadS *)ud; | |
| 526 | + (void)L; | |
| 527 | + if (ls->size == 0) return NULL; | |
| 528 | + *size = ls->size; | |
| 529 | + ls->size = 0; | |
| 530 | + return ls->s; | |
| 531 | +} | |
| 532 | + | |
| 533 | + | |
| 534 | +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, | |
| 535 | + const char *name) { | |
| 536 | + LoadS ls; | |
| 537 | + ls.s = buff; | |
| 538 | + ls.size = size; | |
| 539 | + return lua_load(L, getS, &ls, name); | |
| 540 | +} | |
| 541 | + | |
| 542 | +/* }====================================================== */ | |
| 543 | + | |
| 544 | + | |
| 545 | +/* | |
| 546 | +** {====================================================== | |
| 547 | +** compatibility code | |
| 548 | +** ======================================================= | |
| 549 | +*/ | |
| 550 | + | |
| 551 | + | |
| 552 | +static void callalert (lua_State *L, int status) { | |
| 553 | + if (status != 0) { | |
| 554 | + lua_getglobal(L, "_ALERT"); | |
| 555 | + if (lua_isfunction(L, -1)) { | |
| 556 | + lua_insert(L, -2); | |
| 557 | + lua_call(L, 1, 0); | |
| 558 | + } | |
| 559 | + else { /* no _ALERT function; print it on stderr */ | |
| 560 | + fprintf(stderr, "%s\n", lua_tostring(L, -2)); | |
| 561 | + lua_pop(L, 2); /* remove error message and _ALERT */ | |
| 562 | + } | |
| 563 | + } | |
| 564 | +} | |
| 565 | + | |
| 566 | + | |
| 567 | +static int aux_do (lua_State *L, int status) { | |
| 568 | + if (status == 0) { /* parse OK? */ | |
| 569 | + status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */ | |
| 570 | + } | |
| 571 | + callalert(L, status); | |
| 572 | + return status; | |
| 573 | +} | |
| 574 | + | |
| 575 | + | |
| 576 | +LUALIB_API int lua_dofile (lua_State *L, const char *filename) { | |
| 577 | + return aux_do(L, luaL_loadfile(L, filename)); | |
| 578 | +} | |
| 579 | + | |
| 580 | + | |
| 581 | +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, | |
| 582 | + const char *name) { | |
| 583 | + return aux_do(L, luaL_loadbuffer(L, buff, size, name)); | |
| 584 | +} | |
| 585 | + | |
| 586 | + | |
| 587 | +LUALIB_API int lua_dostring (lua_State *L, const char *str) { | |
| 588 | + return lua_dobuffer(L, str, strlen(str), str); | |
| 214 | 589 | } |
| 215 | 590 | |
| 216 | 591 | /* }====================================================== */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lbaselib.c,v 1.17a 2000/11/06 13:45:18 roberto Exp $ | |
| 2 | +** $Id: lbaselib.c,v 1.130 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Basic library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -11,51 +11,15 @@ · 5 unmodified lines | ||
| 11 | 11 | #include <stdlib.h> |
| 12 | 12 | #include <string.h> |
| 13 | 13 | |
| 14 | +#define lbaselib_c | |
| 15 | + | |
| 14 | 16 | #include "lua.h" |
| 15 | 17 | |
| 16 | 18 | #include "lauxlib.h" |
| 17 | −#include "luadebug.h" | |
| 18 | 19 | #include "lualib.h" |
| 19 | 20 | |
| 20 | 21 | |
| 21 | 22 | |
| 22 | −/* | |
| 23 | −** If your system does not support `stderr', redefine this function, or | |
| 24 | −** redefine _ERRORMESSAGE so that it won't need _ALERT. | |
| 25 | −*/ | |
| 26 | −static int luaB__ALERT (lua_State *L) { | |
| 27 | − fputs(luaL_check_string(L, 1), stderr); | |
| 28 | − return 0; | |
| 29 | −} | |
| 30 | − | |
| 31 | − | |
| 32 | −/* | |
| 33 | −** Basic implementation of _ERRORMESSAGE. | |
| 34 | −** The library `liolib' redefines _ERRORMESSAGE for better error information. | |
| 35 | −*/ | |
| 36 | −static int luaB__ERRORMESSAGE (lua_State *L) { | |
| 37 | − luaL_checktype(L, 1, LUA_TSTRING); | |
| 38 | − lua_getglobal(L, LUA_ALERT); | |
| 39 | − if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ | |
| 40 | − lua_Debug ar; | |
| 41 | − lua_pushstring(L, "error: "); | |
| 42 | − lua_pushvalue(L, 1); | |
| 43 | − if (lua_getstack(L, 1, &ar)) { | |
| 44 | − lua_getinfo(L, "Sl", &ar); | |
| 45 | − if (ar.source && ar.currentline > 0) { | |
| 46 | − char buff[100]; | |
| 47 | − sprintf(buff, "\n <%.70s: line %d>", ar.short_src, ar.currentline); | |
| 48 | − lua_pushstring(L, buff); | |
| 49 | − lua_concat(L, 2); | |
| 50 | − } | |
| 51 | − } | |
| 52 | − lua_pushstring(L, "\n"); | |
| 53 | − lua_concat(L, 3); | |
| 54 | − lua_rawcall(L, 1, 0); | |
| 55 | − } | |
| 56 | − return 0; | |
| 57 | −} | |
| 58 | − | |
| 59 | 23 | |
| 60 | 24 | /* |
| 61 | 25 | ** If your system does not support `stdout', you can just remove this function. |
| @@ -71,10 +35,10 @@ static int luaB_print (lua_State *L) { · 9 unmodified lines | ||
| 71 | 35 | const char *s; |
| 72 | 36 | lua_pushvalue(L, -1); /* function to be called */ |
| 73 | 37 | lua_pushvalue(L, i); /* value to print */ |
| 74 | − lua_rawcall(L, 1, 1); | |
| 38 | + lua_call(L, 1, 1); | |
| 75 | 39 | s = lua_tostring(L, -1); /* get result */ |
| 76 | 40 | if (s == NULL) |
| 77 | − lua_error(L, "`tostring' must return a string to `print'"); | |
| 41 | + return luaL_error(L, "`tostring' must return a string to `print'"); | |
| 78 | 42 | if (i>1) fputs("\t", stdout); |
| 79 | 43 | fputs(s, stdout); |
| 80 | 44 | lua_pop(L, 1); /* pop result */ |
| @@ -85,7 +49,7 @@ static int luaB_print (lua_State *L) { · 4 unmodified lines | ||
| 85 | 49 | |
| 86 | 50 | |
| 87 | 51 | static int luaB_tonumber (lua_State *L) { |
| 88 | − int base = luaL_opt_int(L, 2, 10); | |
| 52 | + int base = luaL_optint(L, 2, 10); | |
| 89 | 53 | if (base == 10) { /* standard conversion */ |
| 90 | 54 | luaL_checkany(L, 1); |
| 91 | 55 | if (lua_isnumber(L, 1)) { |
| @@ -94,15 +58,15 @@ static int luaB_tonumber (lua_State *L) { · 2 unmodified lines | ||
| 94 | 58 | } |
| 95 | 59 | } |
| 96 | 60 | else { |
| 97 | − const char *s1 = luaL_check_string(L, 1); | |
| 61 | + const char *s1 = luaL_checkstring(L, 1); | |
| 98 | 62 | char *s2; |
| 99 | 63 | unsigned long n; |
| 100 | − luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range"); | |
| 64 | + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | |
| 101 | 65 | n = strtoul(s1, &s2, base); |
| 102 | 66 | if (s1 != s2) { /* at least one valid digit? */ |
| 103 | − while (isspace((unsigned char)*s2)) s2++; /* skip trailing spaces */ | |
| 67 | + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ | |
| 104 | 68 | if (*s2 == '\0') { /* no invalid trailing characters? */ |
| 105 | − lua_pushnumber(L, n); | |
| 69 | + lua_pushnumber(L, (lua_Number)n); | |
| 106 | 70 | return 1; |
| 107 | 71 | } |
| 108 | 72 | } |
| @@ -113,55 +77,99 @@ static int luaB_tonumber (lua_State *L) { · 4 unmodified lines | ||
| 113 | 77 | |
| 114 | 78 | |
| 115 | 79 | static int luaB_error (lua_State *L) { |
| 116 | − lua_error(L, luaL_opt_string(L, 1, NULL)); | |
| 117 | − return 0; /* to avoid warnings */ | |
| 80 | + int level = luaL_optint(L, 2, 1); | |
| 81 | + luaL_checkany(L, 1); | |
| 82 | + if (!lua_isstring(L, 1) || level == 0) | |
| 83 | + lua_pushvalue(L, 1); /* propagate error message without changes */ | |
| 84 | + else { /* add extra information */ | |
| 85 | + luaL_where(L, level); | |
| 86 | + lua_pushvalue(L, 1); | |
| 87 | + lua_concat(L, 2); | |
| 88 | + } | |
| 89 | + return lua_error(L); | |
| 118 | 90 | } |
| 119 | 91 | |
| 120 | −static int luaB_setglobal (lua_State *L) { | |
| 121 | − luaL_checkany(L, 2); | |
| 122 | − lua_setglobal(L, luaL_check_string(L, 1)); | |
| 123 | − return 0; | |
| 92 | + | |
| 93 | +static int luaB_getmetatable (lua_State *L) { | |
| 94 | + luaL_checkany(L, 1); | |
| 95 | + if (!lua_getmetatable(L, 1)) { | |
| 96 | + lua_pushnil(L); | |
| 97 | + return 1; /* no metatable */ | |
| 98 | + } | |
| 99 | + luaL_getmetafield(L, 1, "__metatable"); | |
| 100 | + return 1; /* returns either __metatable field (if present) or metatable */ | |
| 124 | 101 | } |
| 125 | 102 | |
| 126 | −static int luaB_getglobal (lua_State *L) { | |
| 127 | − lua_getglobal(L, luaL_check_string(L, 1)); | |
| 103 | + | |
| 104 | +static int luaB_setmetatable (lua_State *L) { | |
| 105 | + int t = lua_type(L, 2); | |
| 106 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 107 | + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, | |
| 108 | + "nil or table expected"); | |
| 109 | + if (luaL_getmetafield(L, 1, "__metatable")) | |
| 110 | + luaL_error(L, "cannot change a protected metatable"); | |
| 111 | + lua_settop(L, 2); | |
| 112 | + lua_setmetatable(L, 1); | |
| 128 | 113 | return 1; |
| 129 | 114 | } |
| 130 | 115 | |
| 131 | −static int luaB_tag (lua_State *L) { | |
| 132 | − luaL_checkany(L, 1); | |
| 133 | − lua_pushnumber(L, lua_tag(L, 1)); | |
| 134 | − return 1; | |
| 116 | + | |
| 117 | +static void getfunc (lua_State *L) { | |
| 118 | + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); | |
| 119 | + else { | |
| 120 | + lua_Debug ar; | |
| 121 | + int level = luaL_optint(L, 1, 1); | |
| 122 | + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); | |
| 123 | + if (lua_getstack(L, level, &ar) == 0) | |
| 124 | + luaL_argerror(L, 1, "invalid level"); | |
| 125 | + lua_getinfo(L, "f", &ar); | |
| 126 | + if (lua_isnil(L, -1)) | |
| 127 | + luaL_error(L, "no function environment for tail call at level %d", | |
| 128 | + level); | |
| 129 | + } | |
| 135 | 130 | } |
| 136 | 131 | |
| 137 | −static int luaB_settag (lua_State *L) { | |
| 138 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 139 | − lua_pushvalue(L, 1); /* push table */ | |
| 140 | − lua_settag(L, luaL_check_int(L, 2)); | |
| 141 | − return 1; /* return table */ | |
| 132 | + | |
| 133 | +static int aux_getfenv (lua_State *L) { | |
| 134 | + lua_getfenv(L, -1); | |
| 135 | + lua_pushliteral(L, "__fenv"); | |
| 136 | + lua_rawget(L, -2); | |
| 137 | + return !lua_isnil(L, -1); | |
| 142 | 138 | } |
| 143 | 139 | |
| 144 | −static int luaB_newtag (lua_State *L) { | |
| 145 | − lua_pushnumber(L, lua_newtag(L)); | |
| 140 | + | |
| 141 | +static int luaB_getfenv (lua_State *L) { | |
| 142 | + getfunc(L); | |
| 143 | + if (!aux_getfenv(L)) /* __fenv not defined? */ | |
| 144 | + lua_pop(L, 1); /* remove it, to return real environment */ | |
| 146 | 145 | return 1; |
| 147 | 146 | } |
| 148 | 147 | |
| 149 | −static int luaB_copytagmethods (lua_State *L) { | |
| 150 | − lua_pushnumber(L, lua_copytagmethods(L, luaL_check_int(L, 1), | |
| 151 | − luaL_check_int(L, 2))); | |
| 152 | − return 1; | |
| 148 | + | |
| 149 | +static int luaB_setfenv (lua_State *L) { | |
| 150 | + luaL_checktype(L, 2, LUA_TTABLE); | |
| 151 | + getfunc(L); | |
| 152 | + if (aux_getfenv(L)) /* __fenv defined? */ | |
| 153 | + luaL_error(L, "`setfenv' cannot change a protected environment"); | |
| 154 | + else | |
| 155 | + lua_pop(L, 2); /* remove __fenv and real environment table */ | |
| 156 | + lua_pushvalue(L, 2); | |
| 157 | + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) | |
| 158 | + lua_replace(L, LUA_GLOBALSINDEX); | |
| 159 | + else if (lua_setfenv(L, -2) == 0) | |
| 160 | + luaL_error(L, "`setfenv' cannot change environment of given function"); | |
| 161 | + return 0; | |
| 153 | 162 | } |
| 154 | 163 | |
| 155 | −static int luaB_globals (lua_State *L) { | |
| 156 | − lua_getglobals(L); /* value to be returned */ | |
| 157 | − if (!lua_isnull(L, 1)) { | |
| 158 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 159 | − lua_pushvalue(L, 1); /* new table of globals */ | |
| 160 | − lua_setglobals(L); | |
| 161 | − } | |
| 164 | + | |
| 165 | +static int luaB_rawequal (lua_State *L) { | |
| 166 | + luaL_checkany(L, 1); | |
| 167 | + luaL_checkany(L, 2); | |
| 168 | + lua_pushboolean(L, lua_rawequal(L, 1, 2)); | |
| 162 | 169 | return 1; |
| 163 | 170 | } |
| 164 | 171 | |
| 172 | + | |
| 165 | 173 | static int luaB_rawget (lua_State *L) { |
| 166 | 174 | luaL_checktype(L, 1, LUA_TTABLE); |
| 167 | 175 | luaL_checkany(L, 2); |
| @@ -177,39 +185,16 @@ static int luaB_rawset (lua_State *L) { · 9 unmodified lines | ||
| 177 | 185 | return 1; |
| 178 | 186 | } |
| 179 | 187 | |
| 180 | −static int luaB_settagmethod (lua_State *L) { | |
| 181 | − int tag = luaL_check_int(L, 1); | |
| 182 | − const char *event = luaL_check_string(L, 2); | |
| 183 | − luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, | |
| 184 | − "function or nil expected"); | |
| 185 | − if (strcmp(event, "gc") == 0) | |
| 186 | − lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua"); | |
| 187 | − lua_gettagmethod(L, tag, event); | |
| 188 | − lua_pushvalue(L, 3); | |
| 189 | − lua_settagmethod(L, tag, event); | |
| 190 | − return 1; | |
| 191 | −} | |
| 192 | − | |
| 193 | − | |
| 194 | −static int luaB_gettagmethod (lua_State *L) { | |
| 195 | − int tag = luaL_check_int(L, 1); | |
| 196 | − const char *event = luaL_check_string(L, 2); | |
| 197 | − if (strcmp(event, "gc") == 0) | |
| 198 | − lua_error(L, "deprecated use: cannot get the `gc' tag method from Lua"); | |
| 199 | − lua_gettagmethod(L, tag, event); | |
| 200 | − return 1; | |
| 201 | −} | |
| 202 | − | |
| 203 | 188 | |
| 204 | 189 | static int luaB_gcinfo (lua_State *L) { |
| 205 | − lua_pushnumber(L, lua_getgccount(L)); | |
| 206 | − lua_pushnumber(L, lua_getgcthreshold(L)); | |
| 190 | + lua_pushnumber(L, (lua_Number)lua_getgccount(L)); | |
| 191 | + lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L)); | |
| 207 | 192 | return 2; |
| 208 | 193 | } |
| 209 | 194 | |
| 210 | 195 | |
| 211 | 196 | static int luaB_collectgarbage (lua_State *L) { |
| 212 | − lua_setgcthreshold(L, luaL_opt_int(L, 1, 0)); | |
| 197 | + lua_setgcthreshold(L, luaL_optint(L, 1, 0)); | |
| 213 | 198 | return 0; |
| 214 | 199 | } |
| 215 | 200 | |
| @@ -233,83 +218,116 @@ static int luaB_next (lua_State *L) { · 17 unmodified lines | ||
| 233 | 218 | } |
| 234 | 219 | |
| 235 | 220 | |
| 236 | −static int passresults (lua_State *L, int status, int oldtop) { | |
| 237 | − static const char *const errornames[] = | |
| 238 | − {"ok", "run-time error", "file error", "syntax error", | |
| 239 | − "memory error", "error in error handling"}; | |
| 240 | − if (status == 0) { | |
| 241 | − int nresults = lua_gettop(L) - oldtop; | |
| 242 | − if (nresults > 0) | |
| 243 | − return nresults; /* results are already on the stack */ | |
| 244 | − else { | |
| 245 | − lua_pushuserdata(L, NULL); /* at least one result to signal no errors */ | |
| 246 | − return 1; | |
| 247 | − } | |
| 221 | +static int luaB_pairs (lua_State *L) { | |
| 222 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 223 | + lua_pushliteral(L, "next"); | |
| 224 | + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ | |
| 225 | + lua_pushvalue(L, 1); /* state, */ | |
| 226 | + lua_pushnil(L); /* and initial value */ | |
| 227 | + return 3; | |
| 228 | +} | |
| 229 | + | |
| 230 | + | |
| 231 | +static int luaB_ipairs (lua_State *L) { | |
| 232 | + lua_Number i = lua_tonumber(L, 2); | |
| 233 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 234 | + if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */ | |
| 235 | + lua_pushliteral(L, "ipairs"); | |
| 236 | + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ | |
| 237 | + lua_pushvalue(L, 1); /* state, */ | |
| 238 | + lua_pushnumber(L, 0); /* and initial value */ | |
| 239 | + return 3; | |
| 240 | + } | |
| 241 | + else { /* `for' step */ | |
| 242 | + i++; /* next value */ | |
| 243 | + lua_pushnumber(L, i); | |
| 244 | + lua_rawgeti(L, 1, (int)i); | |
| 245 | + return (lua_isnil(L, -1)) ? 0 : 2; | |
| 248 | 246 | } |
| 249 | − else { /* error */ | |
| 247 | +} | |
| 248 | + | |
| 249 | + | |
| 250 | +static int load_aux (lua_State *L, int status) { | |
| 251 | + if (status == 0) /* OK? */ | |
| 252 | + return 1; | |
| 253 | + else { | |
| 250 | 254 | lua_pushnil(L); |
| 251 | − lua_pushstring(L, errornames[status]); /* error code */ | |
| 252 | − return 2; | |
| 255 | + lua_insert(L, -2); /* put before error message */ | |
| 256 | + return 2; /* return nil plus error message */ | |
| 253 | 257 | } |
| 254 | 258 | } |
| 255 | 259 | |
| 256 | −static int luaB_dostring (lua_State *L) { | |
| 257 | − int oldtop = lua_gettop(L); | |
| 260 | + | |
| 261 | +static int luaB_loadstring (lua_State *L) { | |
| 258 | 262 | size_t l; |
| 259 | − const char *s = luaL_check_lstr(L, 1, &l); | |
| 260 | − if (*s == '\33') /* binary files start with ESC... */ | |
| 261 | − lua_error(L, "`dostring' cannot run pre-compiled code"); | |
| 262 | − return passresults(L, lua_dobuffer(L, s, l, luaL_opt_string(L, 2, s)), oldtop); | |
| 263 | + const char *s = luaL_checklstring(L, 1, &l); | |
| 264 | + const char *chunkname = luaL_optstring(L, 2, s); | |
| 265 | + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); | |
| 266 | +} | |
| 267 | + | |
| 268 | + | |
| 269 | +static int luaB_loadfile (lua_State *L) { | |
| 270 | + const char *fname = luaL_optstring(L, 1, NULL); | |
| 271 | + return load_aux(L, luaL_loadfile(L, fname)); | |
| 263 | 272 | } |
| 264 | 273 | |
| 265 | 274 | |
| 266 | 275 | static int luaB_dofile (lua_State *L) { |
| 267 | − int oldtop = lua_gettop(L); | |
| 268 | − const char *fname = luaL_opt_string(L, 1, NULL); | |
| 269 | − return passresults(L, lua_dofile(L, fname), oldtop); | |
| 276 | + const char *fname = luaL_optstring(L, 1, NULL); | |
| 277 | + int status = luaL_loadfile(L, fname); | |
| 278 | + if (status != 0) lua_error(L); | |
| 279 | + lua_call(L, 0, LUA_MULTRET); | |
| 280 | + return lua_gettop(L) - 1; | |
| 270 | 281 | } |
| 271 | 282 | |
| 272 | 283 | |
| 273 | −static int luaB_call (lua_State *L) { | |
| 274 | − int oldtop; | |
| 275 | − const char *options = luaL_opt_string(L, 3, ""); | |
| 276 | − int err = 0; /* index of old error method */ | |
| 277 | − int i, status; | |
| 278 | − int n; | |
| 279 | − luaL_checktype(L, 2, LUA_TTABLE); | |
| 280 | − n = lua_getn(L, 2); | |
| 281 | − if (!lua_isnull(L, 4)) { /* set new error method */ | |
| 282 | − lua_getglobal(L, LUA_ERRORMESSAGE); | |
| 283 | − err = lua_gettop(L); /* get index */ | |
| 284 | − lua_pushvalue(L, 4); | |
| 285 | − lua_setglobal(L, LUA_ERRORMESSAGE); | |
| 286 | − } | |
| 287 | − oldtop = lua_gettop(L); /* top before function-call preparation */ | |
| 288 | − /* push function */ | |
| 289 | − lua_pushvalue(L, 1); | |
| 290 | − luaL_checkstack(L, n, "too many arguments"); | |
| 291 | − for (i=0; i<n; i++) /* push arg[1...n] */ | |
| 292 | − lua_rawgeti(L, 2, i+1); | |
| 293 | − status = lua_call(L, n, LUA_MULTRET); | |
| 294 | − if (err != 0) { /* restore old error method */ | |
| 295 | − lua_pushvalue(L, err); | |
| 296 | − lua_setglobal(L, LUA_ERRORMESSAGE); | |
| 297 | − } | |
| 298 | − if (status != 0) { /* error in call? */ | |
| 299 | − if (strchr(options, 'x')) | |
| 300 | − lua_pushnil(L); /* return nil to signal the error */ | |
| 301 | − else | |
| 302 | − lua_error(L, NULL); /* propagate error without additional messages */ | |
| 303 | − return 1; | |
| 304 | − } | |
| 305 | − if (strchr(options, 'p')) /* pack results? */ | |
| 306 | − lua_error(L, "deprecated option `p' in `call'"); | |
| 307 | − return lua_gettop(L) - oldtop; /* results are already on the stack */ | |
| 284 | +static int luaB_assert (lua_State *L) { | |
| 285 | + luaL_checkany(L, 1); | |
| 286 | + if (!lua_toboolean(L, 1)) | |
| 287 | + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); | |
| 288 | + lua_settop(L, 1); | |
| 289 | + return 1; | |
| 290 | +} | |
| 291 | + | |
| 292 | + | |
| 293 | +static int luaB_unpack (lua_State *L) { | |
| 294 | + int n, i; | |
| 295 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 296 | + n = luaL_getn(L, 1); | |
| 297 | + luaL_checkstack(L, n, "table too big to unpack"); | |
| 298 | + for (i=1; i<=n; i++) /* push arg[1...n] */ | |
| 299 | + lua_rawgeti(L, 1, i); | |
| 300 | + return n; | |
| 301 | +} | |
| 302 | + | |
| 303 | + | |
| 304 | +static int luaB_pcall (lua_State *L) { | |
| 305 | + int status; | |
| 306 | + luaL_checkany(L, 1); | |
| 307 | + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); | |
| 308 | + lua_pushboolean(L, (status == 0)); | |
| 309 | + lua_insert(L, 1); | |
| 310 | + return lua_gettop(L); /* return status + all results */ | |
| 311 | +} | |
| 312 | + | |
| 313 | + | |
| 314 | +static int luaB_xpcall (lua_State *L) { | |
| 315 | + int status; | |
| 316 | + luaL_checkany(L, 2); | |
| 317 | + lua_settop(L, 2); | |
| 318 | + lua_insert(L, 1); /* put error function under function to be called */ | |
| 319 | + status = lua_pcall(L, 0, LUA_MULTRET, 1); | |
| 320 | + lua_pushboolean(L, (status == 0)); | |
| 321 | + lua_replace(L, 1); | |
| 322 | + return lua_gettop(L); /* return status + all results */ | |
| 308 | 323 | } |
| 309 | 324 | |
| 310 | 325 | |
| 311 | 326 | static int luaB_tostring (lua_State *L) { |
| 312 | 327 | char buff[64]; |
| 328 | + luaL_checkany(L, 1); | |
| 329 | + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ | |
| 330 | + return 1; /* use its value */ | |
| 313 | 331 | switch (lua_type(L, 1)) { |
| 314 | 332 | case LUA_TNUMBER: |
| 315 | 333 | lua_pushstring(L, lua_tostring(L, 1)); |
| @@ -317,6 +335,9 @@ static int luaB_tostring (lua_State *L) { · 1 unmodified line | ||
| 317 | 335 | case LUA_TSTRING: |
| 318 | 336 | lua_pushvalue(L, 1); |
| 319 | 337 | return 1; |
| 338 | + case LUA_TBOOLEAN: | |
| 339 | + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); | |
| 340 | + return 1; | |
| 320 | 341 | case LUA_TTABLE: |
| 321 | 342 | sprintf(buff, "table: %p", lua_topointer(L, 1)); |
| 322 | 343 | break; |
| @@ -324,328 +345,330 @@ static int luaB_tostring (lua_State *L) { · 1 unmodified line | ||
| 324 | 345 | sprintf(buff, "function: %p", lua_topointer(L, 1)); |
| 325 | 346 | break; |
| 326 | 347 | case LUA_TUSERDATA: |
| 327 | − sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), lua_touserdata(L, 1)); | |
| 348 | + case LUA_TLIGHTUSERDATA: | |
| 349 | + sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); | |
| 350 | + break; | |
| 351 | + case LUA_TTHREAD: | |
| 352 | + sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); | |
| 328 | 353 | break; |
| 329 | 354 | case LUA_TNIL: |
| 330 | − lua_pushstring(L, "nil"); | |
| 355 | + lua_pushliteral(L, "nil"); | |
| 331 | 356 | return 1; |
| 332 | − default: | |
| 333 | − luaL_argerror(L, 1, "value expected"); | |
| 334 | 357 | } |
| 335 | 358 | lua_pushstring(L, buff); |
| 336 | 359 | return 1; |
| 337 | 360 | } |
| 338 | 361 | |
| 339 | 362 | |
| 340 | −static int luaB_foreachi (lua_State *L) { | |
| 341 | − int n, i; | |
| 342 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 343 | − luaL_checktype(L, 2, LUA_TFUNCTION); | |
| 344 | − n = lua_getn(L, 1); | |
| 345 | − for (i=1; i<=n; i++) { | |
| 346 | − lua_pushvalue(L, 2); /* function */ | |
| 347 | − lua_pushnumber(L, i); /* 1st argument */ | |
| 348 | − lua_rawgeti(L, 1, i); /* 2nd argument */ | |
| 349 | − lua_rawcall(L, 2, 1); | |
| 350 | − if (!lua_isnil(L, -1)) | |
| 351 | − return 1; | |
| 352 | − lua_pop(L, 1); /* remove nil result */ | |
| 363 | +static int luaB_newproxy (lua_State *L) { | |
| 364 | + lua_settop(L, 1); | |
| 365 | + lua_newuserdata(L, 0); /* create proxy */ | |
| 366 | + if (lua_toboolean(L, 1) == 0) | |
| 367 | + return 1; /* no metatable */ | |
| 368 | + else if (lua_isboolean(L, 1)) { | |
| 369 | + lua_newtable(L); /* create a new metatable `m' ... */ | |
| 370 | + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ | |
| 371 | + lua_pushboolean(L, 1); | |
| 372 | + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ | |
| 353 | 373 | } |
| 354 | − return 0; | |
| 355 | −} | |
| 356 | − | |
| 357 | − | |
| 358 | −static int luaB_foreach (lua_State *L) { | |
| 359 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 360 | − luaL_checktype(L, 2, LUA_TFUNCTION); | |
| 361 | − lua_pushnil(L); /* first index */ | |
| 362 | − for (;;) { | |
| 363 | − if (lua_next(L, 1) == 0) | |
| 364 | − return 0; | |
| 365 | − lua_pushvalue(L, 2); /* function */ | |
| 366 | − lua_pushvalue(L, -3); /* key */ | |
| 367 | − lua_pushvalue(L, -3); /* value */ | |
| 368 | − lua_rawcall(L, 2, 1); | |
| 369 | − if (!lua_isnil(L, -1)) | |
| 370 | − return 1; | |
| 371 | − lua_pop(L, 2); /* remove value and result */ | |
| 374 | + else { | |
| 375 | + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ | |
| 376 | + if (lua_getmetatable(L, 1)) { | |
| 377 | + lua_rawget(L, lua_upvalueindex(1)); | |
| 378 | + validproxy = lua_toboolean(L, -1); | |
| 379 | + lua_pop(L, 1); /* remove value */ | |
| 380 | + } | |
| 381 | + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); | |
| 382 | + lua_getmetatable(L, 1); /* metatable is valid; get it */ | |
| 372 | 383 | } |
| 373 | −} | |
| 374 | − | |
| 375 | − | |
| 376 | −static int luaB_assert (lua_State *L) { | |
| 377 | − luaL_checkany(L, 1); | |
| 378 | − if (lua_isnil(L, 1)) | |
| 379 | − luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, "")); | |
| 380 | − return 0; | |
| 381 | −} | |
| 382 | − | |
| 383 | − | |
| 384 | −static int luaB_getn (lua_State *L) { | |
| 385 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 386 | − lua_pushnumber(L, lua_getn(L, 1)); | |
| 384 | + lua_setmetatable(L, 2); | |
| 387 | 385 | return 1; |
| 388 | 386 | } |
| 389 | 387 | |
| 390 | 388 | |
| 391 | −static int luaB_tinsert (lua_State *L) { | |
| 392 | − int v = lua_gettop(L); /* last argument: to be inserted */ | |
| 393 | − int n, pos; | |
| 394 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 395 | − n = lua_getn(L, 1); | |
| 396 | − if (v == 2) /* called with only 2 arguments */ | |
| 397 | − pos = n+1; | |
| 398 | − else | |
| 399 | − pos = luaL_check_int(L, 2); /* 2nd argument is the position */ | |
| 400 | − lua_pushstring(L, "n"); | |
| 401 | − lua_pushnumber(L, n+1); | |
| 402 | − lua_rawset(L, 1); /* t.n = n+1 */ | |
| 403 | − for (; n>=pos; n--) { | |
| 404 | − lua_rawgeti(L, 1, n); | |
| 405 | − lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ | |
| 406 | − } | |
| 407 | − lua_pushvalue(L, v); | |
| 408 | − lua_rawseti(L, 1, pos); /* t[pos] = v */ | |
| 409 | − return 0; | |
| 410 | −} | |
| 411 | − | |
| 389 | +/* | |
| 390 | +** {====================================================== | |
| 391 | +** `require' function | |
| 392 | +** ======================================================= | |
| 393 | +*/ | |
| 412 | 394 | |
| 413 | −static int luaB_tremove (lua_State *L) { | |
| 414 | − int pos, n; | |
| 415 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 416 | − n = lua_getn(L, 1); | |
| 417 | − pos = luaL_opt_int(L, 2, n); | |
| 418 | − if (n <= 0) return 0; /* table is "empty" */ | |
| 419 | − lua_rawgeti(L, 1, pos); /* result = t[pos] */ | |
| 420 | − for ( ;pos<n; pos++) { | |
| 421 | − lua_rawgeti(L, 1, pos+1); | |
| 422 | − lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */ | |
| 423 | − } | |
| 424 | − lua_pushstring(L, "n"); | |
| 425 | − lua_pushnumber(L, n-1); | |
| 426 | − lua_rawset(L, 1); /* t.n = n-1 */ | |
| 427 | − lua_pushnil(L); | |
| 428 | − lua_rawseti(L, 1, n); /* t[n] = nil */ | |
| 429 | − return 1; | |
| 430 | −} | |
| 431 | 395 | |
| 396 | +/* name of global that holds table with loaded packages */ | |
| 397 | +#define REQTAB "_LOADED" | |
| 432 | 398 | |
| 399 | +/* name of global that holds the search path for packages */ | |
| 400 | +#define LUA_PATH "LUA_PATH" | |
| 433 | 401 | |
| 402 | +#ifndef LUA_PATH_SEP | |
| 403 | +#define LUA_PATH_SEP ';' | |
| 404 | +#endif | |
| 434 | 405 | |
| 435 | −/* | |
| 436 | −** {====================================================== | |
| 437 | −** Quicksort | |
| 438 | −** (based on `Algorithms in MODULA-3', Robert Sedgewick; | |
| 439 | −** Addison-Wesley, 1993.) | |
| 440 | −*/ | |
| 406 | +#ifndef LUA_PATH_MARK | |
| 407 | +#define LUA_PATH_MARK '?' | |
| 408 | +#endif | |
| 441 | 409 | |
| 410 | +#ifndef LUA_PATH_DEFAULT | |
| 411 | +#define LUA_PATH_DEFAULT "?;?.lua" | |
| 412 | +#endif | |
| 442 | 413 | |
| 443 | −static void set2 (lua_State *L, int i, int j) { | |
| 444 | − lua_rawseti(L, 1, i); | |
| 445 | − lua_rawseti(L, 1, j); | |
| 446 | −} | |
| 447 | 414 | |
| 448 | −static int sort_comp (lua_State *L, int a, int b) { | |
| 449 | − /* WARNING: the caller (auxsort) must ensure stack space */ | |
| 450 | − if (!lua_isnil(L, 2)) { /* function? */ | |
| 451 | − int res; | |
| 452 | − lua_pushvalue(L, 2); | |
| 453 | − lua_pushvalue(L, a-1); /* -1 to compensate function */ | |
| 454 | − lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ | |
| 455 | − lua_rawcall(L, 2, 1); | |
| 456 | − res = !lua_isnil(L, -1); | |
| 457 | − lua_pop(L, 1); | |
| 458 | − return res; | |
| 415 | +static const char *getpath (lua_State *L) { | |
| 416 | + const char *path; | |
| 417 | + lua_getglobal(L, LUA_PATH); /* try global variable */ | |
| 418 | + path = lua_tostring(L, -1); | |
| 419 | + lua_pop(L, 1); | |
| 420 | + if (path) return path; | |
| 421 | + path = getenv(LUA_PATH); /* else try environment variable */ | |
| 422 | + if (path) return path; | |
| 423 | + return LUA_PATH_DEFAULT; /* else use default */ | |
| 424 | +} | |
| 425 | + | |
| 426 | + | |
| 427 | +static const char *pushnextpath (lua_State *L, const char *path) { | |
| 428 | + const char *l; | |
| 429 | + if (*path == '\0') return NULL; /* no more paths */ | |
| 430 | + if (*path == LUA_PATH_SEP) path++; /* skip separator */ | |
| 431 | + l = strchr(path, LUA_PATH_SEP); /* find next separator */ | |
| 432 | + if (l == NULL) l = path+strlen(path); | |
| 433 | + lua_pushlstring(L, path, l - path); /* directory name */ | |
| 434 | + return l; | |
| 435 | +} | |
| 436 | + | |
| 437 | + | |
| 438 | +static void pushcomposename (lua_State *L) { | |
| 439 | + const char *path = lua_tostring(L, -1); | |
| 440 | + const char *wild; | |
| 441 | + int n = 1; | |
| 442 | + while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) { | |
| 443 | + /* is there stack space for prefix, name, and eventual last sufix? */ | |
| 444 | + luaL_checkstack(L, 3, "too many marks in a path component"); | |
| 445 | + lua_pushlstring(L, path, wild - path); /* push prefix */ | |
| 446 | + lua_pushvalue(L, 1); /* push package name (in place of MARK) */ | |
| 447 | + path = wild + 1; /* continue after MARK */ | |
| 448 | + n += 2; | |
| 459 | 449 | } |
| 460 | − else /* a < b? */ | |
| 461 | − return lua_lessthan(L, a, b); | |
| 462 | −} | |
| 463 | − | |
| 464 | −static void auxsort (lua_State *L, int l, int u) { | |
| 465 | − while (l < u) { /* for tail recursion */ | |
| 466 | − int i, j; | |
| 467 | − /* sort elements a[l], a[(l+u)/2] and a[u] */ | |
| 468 | − lua_rawgeti(L, 1, l); | |
| 469 | − lua_rawgeti(L, 1, u); | |
| 470 | − if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ | |
| 471 | − set2(L, l, u); /* swap a[l] - a[u] */ | |
| 472 | − else | |
| 473 | − lua_pop(L, 2); | |
| 474 | − if (u-l == 1) break; /* only 2 elements */ | |
| 475 | − i = (l+u)/2; | |
| 476 | − lua_rawgeti(L, 1, i); | |
| 477 | − lua_rawgeti(L, 1, l); | |
| 478 | − if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ | |
| 479 | − set2(L, i, l); | |
| 480 | − else { | |
| 481 | − lua_pop(L, 1); /* remove a[l] */ | |
| 482 | − lua_rawgeti(L, 1, u); | |
| 483 | − if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ | |
| 484 | − set2(L, i, u); | |
| 485 | − else | |
| 486 | − lua_pop(L, 2); | |
| 450 | + lua_pushstring(L, path); /* push last sufix (`n' already includes this) */ | |
| 451 | + lua_concat(L, n); | |
| 452 | +} | |
| 453 | + | |
| 454 | + | |
| 455 | +static int luaB_require (lua_State *L) { | |
| 456 | + const char *path; | |
| 457 | + int status = LUA_ERRFILE; /* not found (yet) */ | |
| 458 | + luaL_checkstring(L, 1); | |
| 459 | + lua_settop(L, 1); | |
| 460 | + lua_getglobal(L, REQTAB); | |
| 461 | + if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table"); | |
| 462 | + path = getpath(L); | |
| 463 | + lua_pushvalue(L, 1); /* check package's name in book-keeping table */ | |
| 464 | + lua_rawget(L, 2); | |
| 465 | + if (lua_toboolean(L, -1)) /* is it there? */ | |
| 466 | + return 1; /* package is already loaded; return its result */ | |
| 467 | + else { /* must load it */ | |
| 468 | + while (status == LUA_ERRFILE) { | |
| 469 | + lua_settop(L, 3); /* reset stack position */ | |
| 470 | + if ((path = pushnextpath(L, path)) == NULL) break; | |
| 471 | + pushcomposename(L); | |
| 472 | + status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ | |
| 487 | 473 | } |
| 488 | − if (u-l == 2) break; /* only 3 elements */ | |
| 489 | − lua_rawgeti(L, 1, i); /* Pivot */ | |
| 490 | − lua_pushvalue(L, -1); | |
| 491 | − lua_rawgeti(L, 1, u-1); | |
| 492 | − set2(L, i, u-1); | |
| 493 | − /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ | |
| 494 | − i = l; j = u-1; | |
| 495 | − for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | |
| 496 | − /* repeat ++i until a[i] >= P */ | |
| 497 | − while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { | |
| 498 | − if (i>u) lua_error(L, "invalid order function for sorting"); | |
| 499 | − lua_pop(L, 1); /* remove a[i] */ | |
| 500 | − } | |
| 501 | − /* repeat --j until a[j] <= P */ | |
| 502 | − while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { | |
| 503 | − if (j<l) lua_error(L, "invalid order function for sorting"); | |
| 504 | − lua_pop(L, 1); /* remove a[j] */ | |
| 505 | − } | |
| 506 | − if (j<i) { | |
| 507 | − lua_pop(L, 3); /* pop pivot, a[i], a[j] */ | |
| 508 | − break; | |
| 474 | + } | |
| 475 | + switch (status) { | |
| 476 | + case 0: { | |
| 477 | + lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */ | |
| 478 | + lua_insert(L, -2); /* put it below function */ | |
| 479 | + lua_pushvalue(L, 1); | |
| 480 | + lua_setglobal(L, "_REQUIREDNAME"); /* set new name */ | |
| 481 | + lua_call(L, 0, 1); /* run loaded module */ | |
| 482 | + lua_insert(L, -2); /* put result below previous name */ | |
| 483 | + lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */ | |
| 484 | + if (lua_isnil(L, -1)) { /* no/nil return? */ | |
| 485 | + lua_pushboolean(L, 1); | |
| 486 | + lua_replace(L, -2); /* replace to true */ | |
| 509 | 487 | } |
| 510 | − set2(L, i, j); | |
| 488 | + lua_pushvalue(L, 1); | |
| 489 | + lua_pushvalue(L, -2); | |
| 490 | + lua_rawset(L, 2); /* mark it as loaded */ | |
| 491 | + return 1; /* return value */ | |
| 511 | 492 | } |
| 512 | − lua_rawgeti(L, 1, u-1); | |
| 513 | − lua_rawgeti(L, 1, i); | |
| 514 | − set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | |
| 515 | − /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ | |
| 516 | − /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ | |
| 517 | − if (i-l < u-i) { | |
| 518 | − j=l; i=i-1; l=i+2; | |
| 493 | + case LUA_ERRFILE: { /* file not found */ | |
| 494 | + return luaL_error(L, "could not load package `%s' from path `%s'", | |
| 495 | + lua_tostring(L, 1), getpath(L)); | |
| 519 | 496 | } |
| 520 | − else { | |
| 521 | − j=i+1; i=u; u=j-2; | |
| 497 | + default: { | |
| 498 | + return luaL_error(L, "error loading package `%s' (%s)", | |
| 499 | + lua_tostring(L, 1), lua_tostring(L, -1)); | |
| 522 | 500 | } |
| 523 | − auxsort(L, j, i); /* call recursively the smaller one */ | |
| 524 | − } /* repeat the routine for the larger one */ | |
| 525 | −} | |
| 526 | − | |
| 527 | −static int luaB_sort (lua_State *L) { | |
| 528 | − int n; | |
| 529 | − luaL_checktype(L, 1, LUA_TTABLE); | |
| 530 | − n = lua_getn(L, 1); | |
| 531 | − if (!lua_isnull(L, 2)) /* is there a 2nd argument? */ | |
| 532 | − luaL_checktype(L, 2, LUA_TFUNCTION); | |
| 533 | − lua_settop(L, 2); /* make sure there is two arguments */ | |
| 534 | − auxsort(L, 1, n); | |
| 535 | − return 0; | |
| 501 | + } | |
| 536 | 502 | } |
| 537 | 503 | |
| 538 | 504 | /* }====================================================== */ |
| 539 | 505 | |
| 540 | 506 | |
| 507 | +static const luaL_reg base_funcs[] = { | |
| 508 | + {"error", luaB_error}, | |
| 509 | + {"getmetatable", luaB_getmetatable}, | |
| 510 | + {"setmetatable", luaB_setmetatable}, | |
| 511 | + {"getfenv", luaB_getfenv}, | |
| 512 | + {"setfenv", luaB_setfenv}, | |
| 513 | + {"next", luaB_next}, | |
| 514 | + {"ipairs", luaB_ipairs}, | |
| 515 | + {"pairs", luaB_pairs}, | |
| 516 | + {"print", luaB_print}, | |
| 517 | + {"tonumber", luaB_tonumber}, | |
| 518 | + {"tostring", luaB_tostring}, | |
| 519 | + {"type", luaB_type}, | |
| 520 | + {"assert", luaB_assert}, | |
| 521 | + {"unpack", luaB_unpack}, | |
| 522 | + {"rawequal", luaB_rawequal}, | |
| 523 | + {"rawget", luaB_rawget}, | |
| 524 | + {"rawset", luaB_rawset}, | |
| 525 | + {"pcall", luaB_pcall}, | |
| 526 | + {"xpcall", luaB_xpcall}, | |
| 527 | + {"collectgarbage", luaB_collectgarbage}, | |
| 528 | + {"gcinfo", luaB_gcinfo}, | |
| 529 | + {"loadfile", luaB_loadfile}, | |
| 530 | + {"dofile", luaB_dofile}, | |
| 531 | + {"loadstring", luaB_loadstring}, | |
| 532 | + {"require", luaB_require}, | |
| 533 | + {NULL, NULL} | |
| 534 | +}; | |
| 535 | + | |
| 541 | 536 | |
| 542 | 537 | /* |
| 543 | 538 | ** {====================================================== |
| 544 | −** Deprecated functions to manipulate global environment. | |
| 539 | +** Coroutine library | |
| 545 | 540 | ** ======================================================= |
| 546 | 541 | */ |
| 547 | 542 | |
| 543 | +static int auxresume (lua_State *L, lua_State *co, int narg) { | |
| 544 | + int status; | |
| 545 | + if (!lua_checkstack(co, narg)) | |
| 546 | + luaL_error(L, "too many arguments to resume"); | |
| 547 | + lua_xmove(L, co, narg); | |
| 548 | + status = lua_resume(co, narg); | |
| 549 | + if (status == 0) { | |
| 550 | + int nres = lua_gettop(co); | |
| 551 | + if (!lua_checkstack(L, nres)) | |
| 552 | + luaL_error(L, "too many results to resume"); | |
| 553 | + lua_xmove(co, L, nres); /* move yielded values */ | |
| 554 | + return nres; | |
| 555 | + } | |
| 556 | + else { | |
| 557 | + lua_xmove(co, L, 1); /* move error message */ | |
| 558 | + return -1; /* error flag */ | |
| 559 | + } | |
| 560 | +} | |
| 548 | 561 | |
| 549 | −#define num_deprecated 4 | |
| 550 | − | |
| 551 | −static const struct luaL_reg deprecated_names [num_deprecated] = { | |
| 552 | − {"foreachvar", luaB_foreach}, | |
| 553 | − {"nextvar", luaB_next}, | |
| 554 | − {"rawgetglobal", luaB_rawget}, | |
| 555 | − {"rawsetglobal", luaB_rawset} | |
| 556 | −}; | |
| 557 | 562 | |
| 563 | +static int luaB_coresume (lua_State *L) { | |
| 564 | + lua_State *co = lua_tothread(L, 1); | |
| 565 | + int r; | |
| 566 | + luaL_argcheck(L, co, 1, "coroutine expected"); | |
| 567 | + r = auxresume(L, co, lua_gettop(L) - 1); | |
| 568 | + if (r < 0) { | |
| 569 | + lua_pushboolean(L, 0); | |
| 570 | + lua_insert(L, -2); | |
| 571 | + return 2; /* return false + error message */ | |
| 572 | + } | |
| 573 | + else { | |
| 574 | + lua_pushboolean(L, 1); | |
| 575 | + lua_insert(L, -(r + 1)); | |
| 576 | + return r + 1; /* return true + `resume' returns */ | |
| 577 | + } | |
| 578 | +} | |
| 558 | 579 | |
| 559 | −#ifdef LUA_DEPRECATEDFUNCS | |
| 560 | 580 | |
| 561 | −/* | |
| 562 | −** call corresponding function inserting `globals' as first argument | |
| 563 | −*/ | |
| 564 | −static int deprecated_func (lua_State *L) { | |
| 565 | − lua_insert(L, 1); /* upvalue is the function to be called */ | |
| 566 | − lua_getglobals(L); | |
| 567 | − lua_insert(L, 2); /* table of globals is 1o argument */ | |
| 568 | − lua_rawcall(L, lua_gettop(L)-1, LUA_MULTRET); | |
| 569 | − return lua_gettop(L); /* return all results */ | |
| 581 | +static int luaB_auxwrap (lua_State *L) { | |
| 582 | + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); | |
| 583 | + int r = auxresume(L, co, lua_gettop(L)); | |
| 584 | + if (r < 0) { | |
| 585 | + if (lua_isstring(L, -1)) { /* error object is a string? */ | |
| 586 | + luaL_where(L, 1); /* add extra info */ | |
| 587 | + lua_insert(L, -2); | |
| 588 | + lua_concat(L, 2); | |
| 589 | + } | |
| 590 | + lua_error(L); /* propagate error */ | |
| 591 | + } | |
| 592 | + return r; | |
| 570 | 593 | } |
| 571 | 594 | |
| 572 | 595 | |
| 573 | −static void deprecated_funcs (lua_State *L) { | |
| 574 | − int i; | |
| 575 | − for (i=0; i<num_deprecated; i++) { | |
| 576 | − lua_pushcfunction(L, deprecated_names[i].func); | |
| 577 | − lua_pushcclosure(L, deprecated_func, 1); | |
| 578 | − lua_setglobal(L, deprecated_names[i].name); | |
| 579 | − } | |
| 596 | +static int luaB_cocreate (lua_State *L) { | |
| 597 | + lua_State *NL = lua_newthread(L); | |
| 598 | + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, | |
| 599 | + "Lua function expected"); | |
| 600 | + lua_pushvalue(L, 1); /* move function to top */ | |
| 601 | + lua_xmove(L, NL, 1); /* move function from L to NL */ | |
| 602 | + return 1; | |
| 580 | 603 | } |
| 581 | 604 | |
| 582 | 605 | |
| 583 | −#else | |
| 606 | +static int luaB_cowrap (lua_State *L) { | |
| 607 | + luaB_cocreate(L); | |
| 608 | + lua_pushcclosure(L, luaB_auxwrap, 1); | |
| 609 | + return 1; | |
| 610 | +} | |
| 584 | 611 | |
| 585 | −/* | |
| 586 | −** gives an explicit error in any attempt to call a deprecated function | |
| 587 | −*/ | |
| 588 | −static int deprecated_func (lua_State *L) { | |
| 589 | − luaL_verror(L, "function `%.20s' is deprecated", lua_tostring(L, -1)); | |
| 590 | − return 0; /* to avoid warnings */ | |
| 612 | + | |
| 613 | +static int luaB_yield (lua_State *L) { | |
| 614 | + return lua_yield(L, lua_gettop(L)); | |
| 591 | 615 | } |
| 592 | 616 | |
| 593 | 617 | |
| 594 | −static void deprecated_funcs (lua_State *L) { | |
| 595 | − int i; | |
| 596 | − for (i=0; i<num_deprecated; i++) { | |
| 597 | − lua_pushstring(L, deprecated_names[i].name); | |
| 598 | − lua_pushcclosure(L, deprecated_func, 1); | |
| 599 | − lua_setglobal(L, deprecated_names[i].name); | |
| 618 | +static int luaB_costatus (lua_State *L) { | |
| 619 | + lua_State *co = lua_tothread(L, 1); | |
| 620 | + luaL_argcheck(L, co, 1, "coroutine expected"); | |
| 621 | + if (L == co) lua_pushliteral(L, "running"); | |
| 622 | + else { | |
| 623 | + lua_Debug ar; | |
| 624 | + if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0) | |
| 625 | + lua_pushliteral(L, "dead"); | |
| 626 | + else | |
| 627 | + lua_pushliteral(L, "suspended"); | |
| 600 | 628 | } |
| 629 | + return 1; | |
| 601 | 630 | } |
| 602 | 631 | |
| 603 | −#endif | |
| 604 | − | |
| 605 | −/* }====================================================== */ | |
| 606 | 632 | |
| 607 | −static const struct luaL_reg base_funcs[] = { | |
| 608 | − {LUA_ALERT, luaB__ALERT}, | |
| 609 | − {LUA_ERRORMESSAGE, luaB__ERRORMESSAGE}, | |
| 610 | − {"call", luaB_call}, | |
| 611 | − {"collectgarbage", luaB_collectgarbage}, | |
| 612 | − {"copytagmethods", luaB_copytagmethods}, | |
| 613 | − {"dofile", luaB_dofile}, | |
| 614 | − {"dostring", luaB_dostring}, | |
| 615 | − {"error", luaB_error}, | |
| 616 | − {"foreach", luaB_foreach}, | |
| 617 | − {"foreachi", luaB_foreachi}, | |
| 618 | − {"gcinfo", luaB_gcinfo}, | |
| 619 | − {"getglobal", luaB_getglobal}, | |
| 620 | − {"gettagmethod", luaB_gettagmethod}, | |
| 621 | − {"globals", luaB_globals}, | |
| 622 | − {"newtag", luaB_newtag}, | |
| 623 | − {"next", luaB_next}, | |
| 624 | − {"print", luaB_print}, | |
| 625 | − {"rawget", luaB_rawget}, | |
| 626 | − {"rawset", luaB_rawset}, | |
| 627 | − {"rawgettable", luaB_rawget}, /* for compatibility */ | |
| 628 | − {"rawsettable", luaB_rawset}, /* for compatibility */ | |
| 629 | − {"setglobal", luaB_setglobal}, | |
| 630 | − {"settag", luaB_settag}, | |
| 631 | − {"settagmethod", luaB_settagmethod}, | |
| 632 | − {"tag", luaB_tag}, | |
| 633 | − {"tonumber", luaB_tonumber}, | |
| 634 | − {"tostring", luaB_tostring}, | |
| 635 | − {"type", luaB_type}, | |
| 636 | − {"assert", luaB_assert}, | |
| 637 | − {"getn", luaB_getn}, | |
| 638 | − {"sort", luaB_sort}, | |
| 639 | − {"tinsert", luaB_tinsert}, | |
| 640 | − {"tremove", luaB_tremove} | |
| 633 | +static const luaL_reg co_funcs[] = { | |
| 634 | + {"create", luaB_cocreate}, | |
| 635 | + {"wrap", luaB_cowrap}, | |
| 636 | + {"resume", luaB_coresume}, | |
| 637 | + {"yield", luaB_yield}, | |
| 638 | + {"status", luaB_costatus}, | |
| 639 | + {NULL, NULL} | |
| 641 | 640 | }; |
| 642 | 641 | |
| 642 | +/* }====================================================== */ | |
| 643 | + | |
| 643 | 644 | |
| 644 | 645 | |
| 645 | −LUALIB_API void lua_baselibopen (lua_State *L) { | |
| 646 | − luaL_openl(L, base_funcs); | |
| 647 | − lua_pushstring(L, LUA_VERSION); | |
| 648 | − lua_setglobal(L, "_VERSION"); | |
| 649 | − deprecated_funcs(L); | |
| 646 | +static void base_open (lua_State *L) { | |
| 647 | + lua_pushliteral(L, "_G"); | |
| 648 | + lua_pushvalue(L, LUA_GLOBALSINDEX); | |
| 649 | + luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */ | |
| 650 | + lua_pushliteral(L, "_VERSION"); | |
| 651 | + lua_pushliteral(L, LUA_VERSION); | |
| 652 | + lua_rawset(L, -3); /* set global _VERSION */ | |
| 653 | + /* `newproxy' needs a weaktable as upvalue */ | |
| 654 | + lua_pushliteral(L, "newproxy"); | |
| 655 | + lua_newtable(L); /* new table `w' */ | |
| 656 | + lua_pushvalue(L, -1); /* `w' will be its own metatable */ | |
| 657 | + lua_setmetatable(L, -2); | |
| 658 | + lua_pushliteral(L, "__mode"); | |
| 659 | + lua_pushliteral(L, "k"); | |
| 660 | + lua_rawset(L, -3); /* metatable(w).__mode = "k" */ | |
| 661 | + lua_pushcclosure(L, luaB_newproxy, 1); | |
| 662 | + lua_rawset(L, -3); /* set global `newproxy' */ | |
| 663 | + lua_rawset(L, -1); /* set global _G */ | |
| 664 | +} | |
| 665 | + | |
| 666 | + | |
| 667 | +LUALIB_API int luaopen_base (lua_State *L) { | |
| 668 | + base_open(L); | |
| 669 | + luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); | |
| 670 | + lua_newtable(L); | |
| 671 | + lua_setglobal(L, REQTAB); | |
| 672 | + return 0; | |
| 650 | 673 | } |
| 651 | 674 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldblib.c,v 1.29 2000/11/06 17:58:38 roberto Exp $ | |
| 2 | +** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Interface from Lua to its debug API |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -9,10 +9,11 @@ · 3 unmodified lines | ||
| 9 | 9 | #include <stdlib.h> |
| 10 | 10 | #include <string.h> |
| 11 | 11 | |
| 12 | +#define ldblib_c | |
| 13 | + | |
| 12 | 14 | #include "lua.h" |
| 13 | 15 | |
| 14 | 16 | #include "lauxlib.h" |
| 15 | −#include "luadebug.h" | |
| 16 | 17 | #include "lualib.h" |
| 17 | 18 | |
| 18 | 19 | |
| @@ -20,43 +21,41 @@ · 1 unmodified line | ||
| 20 | 21 | static void settabss (lua_State *L, const char *i, const char *v) { |
| 21 | 22 | lua_pushstring(L, i); |
| 22 | 23 | lua_pushstring(L, v); |
| 23 | − lua_settable(L, -3); | |
| 24 | + lua_rawset(L, -3); | |
| 24 | 25 | } |
| 25 | 26 | |
| 26 | 27 | |
| 27 | 28 | static void settabsi (lua_State *L, const char *i, int v) { |
| 28 | 29 | lua_pushstring(L, i); |
| 29 | − lua_pushnumber(L, v); | |
| 30 | − lua_settable(L, -3); | |
| 30 | + lua_pushnumber(L, (lua_Number)v); | |
| 31 | + lua_rawset(L, -3); | |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | 34 | |
| 34 | 35 | static int getinfo (lua_State *L) { |
| 35 | 36 | lua_Debug ar; |
| 36 | − const char *options = luaL_opt_string(L, 2, "flnSu"); | |
| 37 | − char buff[20]; | |
| 37 | + const char *options = luaL_optstring(L, 2, "flnSu"); | |
| 38 | 38 | if (lua_isnumber(L, 1)) { |
| 39 | − if (!lua_getstack(L, (int)lua_tonumber(L, 1), &ar)) { | |
| 39 | + if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { | |
| 40 | 40 | lua_pushnil(L); /* level out of range */ |
| 41 | 41 | return 1; |
| 42 | 42 | } |
| 43 | 43 | } |
| 44 | 44 | else if (lua_isfunction(L, 1)) { |
| 45 | + lua_pushfstring(L, ">%s", options); | |
| 46 | + options = lua_tostring(L, -1); | |
| 45 | 47 | lua_pushvalue(L, 1); |
| 46 | − sprintf(buff, ">%.10s", options); | |
| 47 | − options = buff; | |
| 48 | 48 | } |
| 49 | 49 | else |
| 50 | − luaL_argerror(L, 1, "function or level expected"); | |
| 50 | + return luaL_argerror(L, 1, "function or level expected"); | |
| 51 | 51 | if (!lua_getinfo(L, options, &ar)) |
| 52 | − luaL_argerror(L, 2, "invalid option"); | |
| 52 | + return luaL_argerror(L, 2, "invalid option"); | |
| 53 | 53 | lua_newtable(L); |
| 54 | 54 | for (; *options; options++) { |
| 55 | 55 | switch (*options) { |
| 56 | 56 | case 'S': |
| 57 | 57 | settabss(L, "source", ar.source); |
| 58 | − if (ar.source) | |
| 59 | − settabss(L, "short_src", ar.short_src); | |
| 58 | + settabss(L, "short_src", ar.short_src); | |
| 60 | 59 | settabsi(L, "linedefined", ar.linedefined); |
| 61 | 60 | settabss(L, "what", ar.what); |
| 62 | 61 | break; |
| @@ -71,9 +70,9 @@ static int getinfo (lua_State *L) { · 8 unmodified lines | ||
| 71 | 70 | settabss(L, "namewhat", ar.namewhat); |
| 72 | 71 | break; |
| 73 | 72 | case 'f': |
| 74 | − lua_pushstring(L, "func"); | |
| 73 | + lua_pushliteral(L, "func"); | |
| 75 | 74 | lua_pushvalue(L, -3); |
| 76 | − lua_settable(L, -3); | |
| 75 | + lua_rawset(L, -3); | |
| 77 | 76 | break; |
| 78 | 77 | } |
| 79 | 78 | } |
| @@ -84,9 +83,9 @@ static int getinfo (lua_State *L) { · 4 unmodified lines | ||
| 84 | 83 | static int getlocal (lua_State *L) { |
| 85 | 84 | lua_Debug ar; |
| 86 | 85 | const char *name; |
| 87 | − if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ | |
| 88 | − luaL_argerror(L, 1, "level out of range"); | |
| 89 | − name = lua_getlocal(L, &ar, luaL_check_int(L, 2)); | |
| 86 | + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ | |
| 87 | + return luaL_argerror(L, 1, "level out of range"); | |
| 88 | + name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); | |
| 90 | 89 | if (name) { |
| 91 | 90 | lua_pushstring(L, name); |
| 92 | 91 | lua_pushvalue(L, -2); |
| @@ -101,88 +100,200 @@ static int getlocal (lua_State *L) { · 8 unmodified lines | ||
| 101 | 100 | |
| 102 | 101 | static int setlocal (lua_State *L) { |
| 103 | 102 | lua_Debug ar; |
| 104 | − if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ | |
| 105 | − luaL_argerror(L, 1, "level out of range"); | |
| 103 | + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ | |
| 104 | + return luaL_argerror(L, 1, "level out of range"); | |
| 106 | 105 | luaL_checkany(L, 3); |
| 107 | − lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2))); | |
| 106 | + lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2))); | |
| 108 | 107 | return 1; |
| 109 | 108 | } |
| 110 | 109 | |
| 111 | 110 | |
| 111 | +static int auxupvalue (lua_State *L, int get) { | |
| 112 | + const char *name; | |
| 113 | + int n = luaL_checkint(L, 2); | |
| 114 | + luaL_checktype(L, 1, LUA_TFUNCTION); | |
| 115 | + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ | |
| 116 | + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); | |
| 117 | + if (name == NULL) return 0; | |
| 118 | + lua_pushstring(L, name); | |
| 119 | + lua_insert(L, -(get+1)); | |
| 120 | + return get + 1; | |
| 121 | +} | |
| 122 | + | |
| 123 | + | |
| 124 | +static int getupvalue (lua_State *L) { | |
| 125 | + return auxupvalue(L, 1); | |
| 126 | +} | |
| 127 | + | |
| 128 | + | |
| 129 | +static int setupvalue (lua_State *L) { | |
| 130 | + luaL_checkany(L, 3); | |
| 131 | + return auxupvalue(L, 0); | |
| 132 | +} | |
| 133 | + | |
| 134 | + | |
| 112 | 135 | |
| 113 | −/* dummy variables (to define unique addresses) */ | |
| 114 | −static char key1, key2; | |
| 115 | −#define KEY_CALLHOOK (&key1) | |
| 116 | −#define KEY_LINEHOOK (&key2) | |
| 136 | +static const char KEY_HOOK = 'h'; | |
| 117 | 137 | |
| 118 | 138 | |
| 119 | −static void hookf (lua_State *L, void *key) { | |
| 120 | − lua_getregistry(L); | |
| 121 | − lua_pushuserdata(L, key); | |
| 122 | − lua_gettable(L, -2); | |
| 139 | +static void hookf (lua_State *L, lua_Debug *ar) { | |
| 140 | + static const char *const hooknames[] = | |
| 141 | + {"call", "return", "line", "count", "tail return"}; | |
| 142 | + lua_pushlightuserdata(L, (void *)&KEY_HOOK); | |
| 143 | + lua_rawget(L, LUA_REGISTRYINDEX); | |
| 123 | 144 | if (lua_isfunction(L, -1)) { |
| 124 | − lua_pushvalue(L, 1); | |
| 125 | − lua_rawcall(L, 1, 0); | |
| 145 | + lua_pushstring(L, hooknames[(int)ar->event]); | |
| 146 | + if (ar->currentline >= 0) | |
| 147 | + lua_pushnumber(L, (lua_Number)ar->currentline); | |
| 148 | + else lua_pushnil(L); | |
| 149 | + lua_assert(lua_getinfo(L, "lS", ar)); | |
| 150 | + lua_call(L, 2, 0); | |
| 126 | 151 | } |
| 127 | 152 | else |
| 128 | 153 | lua_pop(L, 1); /* pop result from gettable */ |
| 129 | − lua_pop(L, 1); /* pop table */ | |
| 130 | 154 | } |
| 131 | 155 | |
| 132 | 156 | |
| 133 | −static void callf (lua_State *L, lua_Debug *ar) { | |
| 134 | − lua_pushstring(L, ar->event); | |
| 135 | − hookf(L, KEY_CALLHOOK); | |
| 157 | +static int makemask (const char *smask, int count) { | |
| 158 | + int mask = 0; | |
| 159 | + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; | |
| 160 | + if (strchr(smask, 'r')) mask |= LUA_MASKRET; | |
| 161 | + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; | |
| 162 | + if (count > 0) mask |= LUA_MASKCOUNT; | |
| 163 | + return mask; | |
| 136 | 164 | } |
| 137 | 165 | |
| 138 | 166 | |
| 139 | −static void linef (lua_State *L, lua_Debug *ar) { | |
| 140 | − lua_pushnumber(L, ar->currentline); | |
| 141 | − hookf(L, KEY_LINEHOOK); | |
| 167 | +static char *unmakemask (int mask, char *smask) { | |
| 168 | + int i = 0; | |
| 169 | + if (mask & LUA_MASKCALL) smask[i++] = 'c'; | |
| 170 | + if (mask & LUA_MASKRET) smask[i++] = 'r'; | |
| 171 | + if (mask & LUA_MASKLINE) smask[i++] = 'l'; | |
| 172 | + smask[i] = '\0'; | |
| 173 | + return smask; | |
| 142 | 174 | } |
| 143 | 175 | |
| 144 | 176 | |
| 145 | −static void sethook (lua_State *L, void *key, lua_Hook hook, | |
| 146 | − lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) { | |
| 147 | − lua_settop(L, 1); | |
| 148 | − if (lua_isnil(L, 1)) | |
| 149 | − (*sethookf)(L, NULL); | |
| 150 | − else if (lua_isfunction(L, 1)) | |
| 151 | − (*sethookf)(L, hook); | |
| 152 | − else | |
| 153 | − luaL_argerror(L, 1, "function expected"); | |
| 154 | − lua_getregistry(L); | |
| 155 | − lua_pushuserdata(L, key); | |
| 156 | − lua_pushvalue(L, -1); /* dup key */ | |
| 157 | − lua_gettable(L, -3); /* get old value */ | |
| 158 | − lua_pushvalue(L, -2); /* key (again) */ | |
| 177 | +static int sethook (lua_State *L) { | |
| 178 | + if (lua_isnoneornil(L, 1)) { | |
| 179 | + lua_settop(L, 1); | |
| 180 | + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ | |
| 181 | + } | |
| 182 | + else { | |
| 183 | + const char *smask = luaL_checkstring(L, 2); | |
| 184 | + int count = luaL_optint(L, 3, 0); | |
| 185 | + luaL_checktype(L, 1, LUA_TFUNCTION); | |
| 186 | + lua_sethook(L, hookf, makemask(smask, count), count); | |
| 187 | + } | |
| 188 | + lua_pushlightuserdata(L, (void *)&KEY_HOOK); | |
| 159 | 189 | lua_pushvalue(L, 1); |
| 160 | − lua_settable(L, -5); /* set new value */ | |
| 190 | + lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ | |
| 191 | + return 0; | |
| 161 | 192 | } |
| 162 | 193 | |
| 163 | 194 | |
| 164 | −static int setcallhook (lua_State *L) { | |
| 165 | − sethook(L, KEY_CALLHOOK, callf, lua_setcallhook); | |
| 166 | − return 1; | |
| 195 | +static int gethook (lua_State *L) { | |
| 196 | + char buff[5]; | |
| 197 | + int mask = lua_gethookmask(L); | |
| 198 | + lua_Hook hook = lua_gethook(L); | |
| 199 | + if (hook != NULL && hook != hookf) /* external hook? */ | |
| 200 | + lua_pushliteral(L, "external hook"); | |
| 201 | + else { | |
| 202 | + lua_pushlightuserdata(L, (void *)&KEY_HOOK); | |
| 203 | + lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ | |
| 204 | + } | |
| 205 | + lua_pushstring(L, unmakemask(mask, buff)); | |
| 206 | + lua_pushnumber(L, (lua_Number)lua_gethookcount(L)); | |
| 207 | + return 3; | |
| 208 | +} | |
| 209 | + | |
| 210 | + | |
| 211 | +static int debug (lua_State *L) { | |
| 212 | + for (;;) { | |
| 213 | + char buffer[250]; | |
| 214 | + fputs("lua_debug> ", stderr); | |
| 215 | + if (fgets(buffer, sizeof(buffer), stdin) == 0 || | |
| 216 | + strcmp(buffer, "cont\n") == 0) | |
| 217 | + return 0; | |
| 218 | + lua_dostring(L, buffer); | |
| 219 | + lua_settop(L, 0); /* remove eventual returns */ | |
| 220 | + } | |
| 167 | 221 | } |
| 168 | 222 | |
| 169 | 223 | |
| 170 | −static int setlinehook (lua_State *L) { | |
| 171 | − sethook(L, KEY_LINEHOOK, linef, lua_setlinehook); | |
| 224 | +#define LEVELS1 12 /* size of the first part of the stack */ | |
| 225 | +#define LEVELS2 10 /* size of the second part of the stack */ | |
| 226 | + | |
| 227 | +static int errorfb (lua_State *L) { | |
| 228 | + int level = 1; /* skip level 0 (it's this function) */ | |
| 229 | + int firstpart = 1; /* still before eventual `...' */ | |
| 230 | + lua_Debug ar; | |
| 231 | + if (lua_gettop(L) == 0) | |
| 232 | + lua_pushliteral(L, ""); | |
| 233 | + else if (!lua_isstring(L, 1)) return 1; /* no string message */ | |
| 234 | + else lua_pushliteral(L, "\n"); | |
| 235 | + lua_pushliteral(L, "stack traceback:"); | |
| 236 | + while (lua_getstack(L, level++, &ar)) { | |
| 237 | + if (level > LEVELS1 && firstpart) { | |
| 238 | + /* no more than `LEVELS2' more levels? */ | |
| 239 | + if (!lua_getstack(L, level+LEVELS2, &ar)) | |
| 240 | + level--; /* keep going */ | |
| 241 | + else { | |
| 242 | + lua_pushliteral(L, "\n\t..."); /* too many levels */ | |
| 243 | + while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ | |
| 244 | + level++; | |
| 245 | + } | |
| 246 | + firstpart = 0; | |
| 247 | + continue; | |
| 248 | + } | |
| 249 | + lua_pushliteral(L, "\n\t"); | |
| 250 | + lua_getinfo(L, "Snl", &ar); | |
| 251 | + lua_pushfstring(L, "%s:", ar.short_src); | |
| 252 | + if (ar.currentline > 0) | |
| 253 | + lua_pushfstring(L, "%d:", ar.currentline); | |
| 254 | + switch (*ar.namewhat) { | |
| 255 | + case 'g': /* global */ | |
| 256 | + case 'l': /* local */ | |
| 257 | + case 'f': /* field */ | |
| 258 | + case 'm': /* method */ | |
| 259 | + lua_pushfstring(L, " in function `%s'", ar.name); | |
| 260 | + break; | |
| 261 | + default: { | |
| 262 | + if (*ar.what == 'm') /* main? */ | |
| 263 | + lua_pushfstring(L, " in main chunk"); | |
| 264 | + else if (*ar.what == 'C' || *ar.what == 't') | |
| 265 | + lua_pushliteral(L, " ?"); /* C function or tail call */ | |
| 266 | + else | |
| 267 | + lua_pushfstring(L, " in function <%s:%d>", | |
| 268 | + ar.short_src, ar.linedefined); | |
| 269 | + } | |
| 270 | + } | |
| 271 | + lua_concat(L, lua_gettop(L)); | |
| 272 | + } | |
| 273 | + lua_concat(L, lua_gettop(L)); | |
| 172 | 274 | return 1; |
| 173 | 275 | } |
| 174 | 276 | |
| 175 | 277 | |
| 176 | −static const struct luaL_reg dblib[] = { | |
| 278 | +static const luaL_reg dblib[] = { | |
| 177 | 279 | {"getlocal", getlocal}, |
| 178 | 280 | {"getinfo", getinfo}, |
| 179 | − {"setcallhook", setcallhook}, | |
| 180 | − {"setlinehook", setlinehook}, | |
| 181 | − {"setlocal", setlocal} | |
| 281 | + {"gethook", gethook}, | |
| 282 | + {"getupvalue", getupvalue}, | |
| 283 | + {"sethook", sethook}, | |
| 284 | + {"setlocal", setlocal}, | |
| 285 | + {"setupvalue", setupvalue}, | |
| 286 | + {"debug", debug}, | |
| 287 | + {"traceback", errorfb}, | |
| 288 | + {NULL, NULL} | |
| 182 | 289 | }; |
| 183 | 290 | |
| 184 | 291 | |
| 185 | −LUALIB_API void lua_dblibopen (lua_State *L) { | |
| 186 | − luaL_openl(L, dblib); | |
| 292 | +LUALIB_API int luaopen_debug (lua_State *L) { | |
| 293 | + luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); | |
| 294 | + lua_pushliteral(L, "_TRACEBACK"); | |
| 295 | + lua_pushcfunction(L, errorfb); | |
| 296 | + lua_settable(L, LUA_GLOBALSINDEX); | |
| 297 | + return 1; | |
| 187 | 298 | } |
| 188 | 299 | |
| @@ -1,302 +1,309 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: liolib.c,v 1.91 2000/10/31 13:10:24 roberto Exp $ | |
| 2 | +** $Id: liolib.c,v 2.39 2003/03/19 21:16:12 roberto Exp $ | |
| 3 | 3 | ** Standard I/O (and system) library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | −#include <ctype.h> | |
| 8 | +#include <errno.h> | |
| 9 | +#include <locale.h> | |
| 9 | 10 | #include <stdio.h> |
| 10 | 11 | #include <stdlib.h> |
| 11 | 12 | #include <string.h> |
| 12 | 13 | #include <time.h> |
| 13 | 14 | |
| 15 | +#define liolib_c | |
| 16 | + | |
| 14 | 17 | #include "lua.h" |
| 15 | 18 | |
| 16 | 19 | #include "lauxlib.h" |
| 17 | −#include "luadebug.h" | |
| 18 | 20 | #include "lualib.h" |
| 19 | 21 | |
| 20 | 22 | |
| 21 | −#ifndef OLD_ANSI | |
| 22 | −#include <errno.h> | |
| 23 | −#include <locale.h> | |
| 24 | −#define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s)) | |
| 25 | −#define free(b) if (b) (free)(b) | |
| 23 | + | |
| 24 | +/* | |
| 25 | +** by default, gcc does not get `tmpname' | |
| 26 | +*/ | |
| 27 | +#ifndef USE_TMPNAME | |
| 28 | +#ifdef __GNUC__ | |
| 29 | +#define USE_TMPNAME 0 | |
| 26 | 30 | #else |
| 27 | −/* no support for locale and for strerror: fake them */ | |
| 28 | −#define setlocale(a,b) ((void)a, strcmp((b),"C")==0?"C":NULL) | |
| 29 | −#define LC_ALL 0 | |
| 30 | −#define LC_COLLATE 0 | |
| 31 | −#define LC_CTYPE 0 | |
| 32 | −#define LC_MONETARY 0 | |
| 33 | −#define LC_NUMERIC 0 | |
| 34 | −#define LC_TIME 0 | |
| 35 | −#define strerror(e) "generic I/O error" | |
| 36 | −#define errno (-1) | |
| 31 | +#define USE_TMPNAME 1 | |
| 32 | +#endif | |
| 37 | 33 | #endif |
| 38 | 34 | |
| 39 | 35 | |
| 36 | +/* | |
| 37 | +** by default, posix systems get `popen' | |
| 38 | +*/ | |
| 39 | +#ifndef USE_POPEN | |
| 40 | +#ifdef _POSIX_C_SOURCE | |
| 41 | +#if _POSIX_C_SOURCE >= 2 | |
| 42 | +#define USE_POPEN 1 | |
| 43 | +#endif | |
| 44 | +#endif | |
| 45 | +#endif | |
| 40 | 46 | |
| 41 | −#ifdef POPEN | |
| 42 | −/* FILE *popen(); | |
| 43 | −int pclose(); */ | |
| 44 | −#define CLOSEFILE(L, f) ((pclose(f) == -1) ? fclose(f) : 0) | |
| 45 | −#else | |
| 46 | −/* no support for popen */ | |
| 47 | −#define popen(x,y) NULL /* that is, popen always fails */ | |
| 48 | −#define CLOSEFILE(L, f) (fclose(f)) | |
| 47 | +#ifndef USE_POPEN | |
| 48 | +#define USE_POPEN 0 | |
| 49 | 49 | #endif |
| 50 | 50 | |
| 51 | 51 | |
| 52 | −#define INFILE 0 | |
| 53 | −#define OUTFILE 1 | |
| 54 | 52 | |
| 55 | −typedef struct IOCtrl { | |
| 56 | − int ref[2]; /* ref for strings _INPUT/_OUTPUT */ | |
| 57 | − int iotag; /* tag for file handles */ | |
| 58 | − int closedtag; /* tag for closed handles */ | |
| 59 | −} IOCtrl; | |
| 53 | + | |
| 54 | +/* | |
| 55 | +** {====================================================== | |
| 56 | +** FILE Operations | |
| 57 | +** ======================================================= | |
| 58 | +*/ | |
| 59 | + | |
| 60 | + | |
| 61 | +#if !USE_POPEN | |
| 62 | +#define pclose(f) (-1) | |
| 63 | +#endif | |
| 60 | 64 | |
| 61 | 65 | |
| 66 | +#define FILEHANDLE "FILE*" | |
| 62 | 67 | |
| 63 | −static const char *const filenames[] = {"_INPUT", "_OUTPUT"}; | |
| 68 | +#define IO_INPUT "_input" | |
| 69 | +#define IO_OUTPUT "_output" | |
| 64 | 70 | |
| 65 | 71 | |
| 66 | −static int pushresult (lua_State *L, int i) { | |
| 72 | +static int pushresult (lua_State *L, int i, const char *filename) { | |
| 67 | 73 | if (i) { |
| 68 | − lua_pushuserdata(L, NULL); | |
| 74 | + lua_pushboolean(L, 1); | |
| 69 | 75 | return 1; |
| 70 | 76 | } |
| 71 | 77 | else { |
| 72 | 78 | lua_pushnil(L); |
| 73 | − lua_pushstring(L, strerror(errno)); | |
| 79 | + if (filename) | |
| 80 | + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); | |
| 81 | + else | |
| 82 | + lua_pushfstring(L, "%s", strerror(errno)); | |
| 74 | 83 | lua_pushnumber(L, errno); |
| 75 | − return 3;; | |
| 76 | − } | |
| 77 | −} | |
| 78 | − | |
| 79 | − | |
| 80 | −/* | |
| 81 | −** {====================================================== | |
| 82 | −** FILE Operations | |
| 83 | −** ======================================================= | |
| 84 | −*/ | |
| 85 | − | |
| 86 | − | |
| 87 | −static FILE *gethandle (lua_State *L, IOCtrl *ctrl, int f) { | |
| 88 | − void *p = lua_touserdata(L, f); | |
| 89 | − if (p != NULL) { /* is `f' a userdata ? */ | |
| 90 | − int ftag = lua_tag(L, f); | |
| 91 | − if (ftag == ctrl->iotag) /* does it have the correct tag? */ | |
| 92 | − return (FILE *)p; | |
| 93 | − else if (ftag == ctrl->closedtag) | |
| 94 | − lua_error(L, "cannot access a closed file"); | |
| 95 | − /* else go through */ | |
| 84 | + return 3; | |
| 96 | 85 | } |
| 97 | − return NULL; | |
| 98 | 86 | } |
| 99 | 87 | |
| 100 | 88 | |
| 101 | −static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) { | |
| 102 | − FILE *f = gethandle(L, ctrl, arg); | |
| 103 | − luaL_arg_check(L, f, arg, "invalid file handle"); | |
| 89 | +static FILE **topfile (lua_State *L, int findex) { | |
| 90 | + FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE); | |
| 91 | + if (f == NULL) luaL_argerror(L, findex, "bad file"); | |
| 104 | 92 | return f; |
| 105 | 93 | } |
| 106 | 94 | |
| 107 | 95 | |
| 108 | −static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) { | |
| 109 | − FILE *f; | |
| 110 | − lua_getglobals(L); | |
| 111 | − lua_getref(L, ctrl->ref[inout]); | |
| 112 | − lua_rawget(L, -2); | |
| 113 | − f = gethandle(L, ctrl, -1); | |
| 114 | − if (f == NULL) | |
| 115 | − luaL_verror(L, "global variable `%.10s' is not a file handle", | |
| 116 | − filenames[inout]); | |
| 117 | − return f; | |
| 96 | +static int io_type (lua_State *L) { | |
| 97 | + FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE); | |
| 98 | + if (f == NULL) lua_pushnil(L); | |
| 99 | + else if (*f == NULL) | |
| 100 | + lua_pushliteral(L, "closed file"); | |
| 101 | + else | |
| 102 | + lua_pushliteral(L, "file"); | |
| 103 | + return 1; | |
| 118 | 104 | } |
| 119 | 105 | |
| 120 | 106 | |
| 121 | −static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f, | |
| 122 | − const char *name) { | |
| 123 | − lua_pushusertag(L, f, ctrl->iotag); | |
| 124 | − lua_setglobal(L, name); | |
| 107 | +static FILE *tofile (lua_State *L, int findex) { | |
| 108 | + FILE **f = topfile(L, findex); | |
| 109 | + if (*f == NULL) | |
| 110 | + luaL_error(L, "attempt to use a closed file"); | |
| 111 | + return *f; | |
| 125 | 112 | } |
| 126 | 113 | |
| 127 | 114 | |
| 128 | −#define setfile(L,ctrl,f,inout) (setfilebyname(L,ctrl,f,filenames[inout])) | |
| 129 | 115 | |
| 116 | +/* | |
| 117 | +** When creating file handles, always creates a `closed' file handle | |
| 118 | +** before opening the actual file; so, if there is a memory error, the | |
| 119 | +** file is not left opened. | |
| 120 | +*/ | |
| 121 | +static FILE **newfile (lua_State *L) { | |
| 122 | + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); | |
| 123 | + *pf = NULL; /* file handle is currently `closed' */ | |
| 124 | + luaL_getmetatable(L, FILEHANDLE); | |
| 125 | + lua_setmetatable(L, -2); | |
| 126 | + return pf; | |
| 127 | +} | |
| 130 | 128 | |
| 131 | −static int setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { | |
| 132 | − if (f == NULL) | |
| 133 | − return pushresult(L, 0); | |
| 134 | − else { | |
| 135 | − setfile(L, ctrl, f, inout); | |
| 136 | − lua_pushusertag(L, f, ctrl->iotag); | |
| 137 | − return 1; | |
| 129 | + | |
| 130 | +/* | |
| 131 | +** assumes that top of the stack is the `io' library, and next is | |
| 132 | +** the `io' metatable | |
| 133 | +*/ | |
| 134 | +static void registerfile (lua_State *L, FILE *f, const char *name, | |
| 135 | + const char *impname) { | |
| 136 | + lua_pushstring(L, name); | |
| 137 | + *newfile(L) = f; | |
| 138 | + if (impname) { | |
| 139 | + lua_pushstring(L, impname); | |
| 140 | + lua_pushvalue(L, -2); | |
| 141 | + lua_settable(L, -6); /* metatable[impname] = file */ | |
| 138 | 142 | } |
| 143 | + lua_settable(L, -3); /* io[name] = file */ | |
| 139 | 144 | } |
| 140 | 145 | |
| 141 | 146 | |
| 142 | −static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) { | |
| 147 | +static int aux_close (lua_State *L) { | |
| 148 | + FILE *f = tofile(L, 1); | |
| 143 | 149 | if (f == stdin || f == stdout || f == stderr) |
| 144 | − return 1; | |
| 150 | + return 0; /* file cannot be closed */ | |
| 145 | 151 | else { |
| 146 | − lua_pushusertag(L, f, ctrl->iotag); | |
| 147 | − lua_settag(L, ctrl->closedtag); | |
| 148 | − return (CLOSEFILE(L, f) == 0); | |
| 152 | + int ok = (pclose(f) != -1) || (fclose(f) == 0); | |
| 153 | + if (ok) | |
| 154 | + *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ | |
| 155 | + return ok; | |
| 149 | 156 | } |
| 150 | 157 | } |
| 151 | 158 | |
| 152 | 159 | |
| 153 | 160 | static int io_close (lua_State *L) { |
| 154 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 155 | − lua_pop(L, 1); /* remove upvalue */ | |
| 156 | − return pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 1))); | |
| 161 | + if (lua_isnone(L, 1)) { | |
| 162 | + lua_pushstring(L, IO_OUTPUT); | |
| 163 | + lua_rawget(L, lua_upvalueindex(1)); | |
| 164 | + } | |
| 165 | + return pushresult(L, aux_close(L), NULL); | |
| 157 | 166 | } |
| 158 | 167 | |
| 159 | 168 | |
| 160 | −static int file_collect (lua_State *L) { | |
| 161 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 162 | − FILE *f = getnonullfile(L, ctrl, 1); | |
| 163 | − if (f != stdin && f != stdout && f != stderr) | |
| 164 | − CLOSEFILE(L, f); | |
| 169 | +static int io_gc (lua_State *L) { | |
| 170 | + FILE **f = topfile(L, 1); | |
| 171 | + if (*f != NULL) /* ignore closed files */ | |
| 172 | + aux_close(L); | |
| 165 | 173 | return 0; |
| 166 | 174 | } |
| 167 | 175 | |
| 168 | 176 | |
| 169 | −static int io_open (lua_State *L) { | |
| 170 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 171 | − FILE *f; | |
| 172 | − lua_pop(L, 1); /* remove upvalue */ | |
| 173 | − f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); | |
| 174 | − if (f) { | |
| 175 | − lua_pushusertag(L, f, ctrl->iotag); | |
| 176 | − return 1; | |
| 177 | − } | |
| 177 | +static int io_tostring (lua_State *L) { | |
| 178 | + char buff[32]; | |
| 179 | + FILE **f = topfile(L, 1); | |
| 180 | + if (*f == NULL) | |
| 181 | + strcpy(buff, "closed"); | |
| 178 | 182 | else |
| 179 | − return pushresult(L, 0); | |
| 183 | + sprintf(buff, "%p", lua_touserdata(L, 1)); | |
| 184 | + lua_pushfstring(L, "file (%s)", buff); | |
| 185 | + return 1; | |
| 180 | 186 | } |
| 181 | 187 | |
| 182 | 188 | |
| 189 | +static int io_open (lua_State *L) { | |
| 190 | + const char *filename = luaL_checkstring(L, 1); | |
| 191 | + const char *mode = luaL_optstring(L, 2, "r"); | |
| 192 | + FILE **pf = newfile(L); | |
| 193 | + *pf = fopen(filename, mode); | |
| 194 | + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; | |
| 195 | +} | |
| 183 | 196 | |
| 184 | −static int io_fromto (lua_State *L, int inout, const char *mode) { | |
| 185 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 186 | − FILE *current; | |
| 187 | − lua_pop(L, 1); /* remove upvalue */ | |
| 188 | − if (lua_isnull(L, 1)) { | |
| 189 | − closefile(L, ctrl, getfilebyref(L, ctrl, inout)); | |
| 190 | − current = (inout == 0) ? stdin : stdout; | |
| 191 | − } | |
| 192 | − else if (lua_tag(L, 1) == ctrl->iotag) /* deprecated option */ | |
| 193 | − current = (FILE *)lua_touserdata(L, 1); | |
| 194 | − else { | |
| 195 | − const char *s = luaL_check_string(L, 1); | |
| 196 | − current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode); | |
| 197 | − } | |
| 198 | − return setreturn(L, ctrl, current, inout); | |
| 197 | + | |
| 198 | +static int io_popen (lua_State *L) { | |
| 199 | +#if !USE_POPEN | |
| 200 | + luaL_error(L, "`popen' not supported"); | |
| 201 | + return 0; | |
| 202 | +#else | |
| 203 | + const char *filename = luaL_checkstring(L, 1); | |
| 204 | + const char *mode = luaL_optstring(L, 2, "r"); | |
| 205 | + FILE **pf = newfile(L); | |
| 206 | + *pf = popen(filename, mode); | |
| 207 | + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; | |
| 208 | +#endif | |
| 199 | 209 | } |
| 200 | 210 | |
| 201 | 211 | |
| 202 | −static int io_readfrom (lua_State *L) { | |
| 203 | − return io_fromto(L, INFILE, "r"); | |
| 212 | +static int io_tmpfile (lua_State *L) { | |
| 213 | + FILE **pf = newfile(L); | |
| 214 | + *pf = tmpfile(); | |
| 215 | + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; | |
| 204 | 216 | } |
| 205 | 217 | |
| 206 | 218 | |
| 207 | −static int io_writeto (lua_State *L) { | |
| 208 | − return io_fromto(L, OUTFILE, "w"); | |
| 219 | +static FILE *getiofile (lua_State *L, const char *name) { | |
| 220 | + lua_pushstring(L, name); | |
| 221 | + lua_rawget(L, lua_upvalueindex(1)); | |
| 222 | + return tofile(L, -1); | |
| 209 | 223 | } |
| 210 | 224 | |
| 211 | 225 | |
| 212 | −static int io_appendto (lua_State *L) { | |
| 213 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 214 | − FILE *current; | |
| 215 | − lua_pop(L, 1); /* remove upvalue */ | |
| 216 | − current = fopen(luaL_check_string(L, 1), "a"); | |
| 217 | − return setreturn(L, ctrl, current, OUTFILE); | |
| 226 | +static int g_iofile (lua_State *L, const char *name, const char *mode) { | |
| 227 | + if (!lua_isnoneornil(L, 1)) { | |
| 228 | + const char *filename = lua_tostring(L, 1); | |
| 229 | + lua_pushstring(L, name); | |
| 230 | + if (filename) { | |
| 231 | + FILE **pf = newfile(L); | |
| 232 | + *pf = fopen(filename, mode); | |
| 233 | + if (*pf == NULL) { | |
| 234 | + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); | |
| 235 | + luaL_argerror(L, 1, lua_tostring(L, -1)); | |
| 236 | + } | |
| 237 | + } | |
| 238 | + else { | |
| 239 | + tofile(L, 1); /* check that it's a valid file handle */ | |
| 240 | + lua_pushvalue(L, 1); | |
| 241 | + } | |
| 242 | + lua_rawset(L, lua_upvalueindex(1)); | |
| 243 | + } | |
| 244 | + /* return current value */ | |
| 245 | + lua_pushstring(L, name); | |
| 246 | + lua_rawget(L, lua_upvalueindex(1)); | |
| 247 | + return 1; | |
| 218 | 248 | } |
| 219 | 249 | |
| 220 | 250 | |
| 251 | +static int io_input (lua_State *L) { | |
| 252 | + return g_iofile(L, IO_INPUT, "r"); | |
| 253 | +} | |
| 221 | 254 | |
| 222 | −/* | |
| 223 | −** {====================================================== | |
| 224 | −** READ | |
| 225 | −** ======================================================= | |
| 226 | −*/ | |
| 227 | 255 | |
| 256 | +static int io_output (lua_State *L) { | |
| 257 | + return g_iofile(L, IO_OUTPUT, "w"); | |
| 258 | +} | |
| 228 | 259 | |
| 229 | 260 | |
| 230 | −#ifdef LUA_COMPAT_READPATTERN | |
| 261 | +static int io_readline (lua_State *L); | |
| 231 | 262 | |
| 232 | −/* | |
| 233 | −** We cannot lookahead without need, because this can lock stdin. | |
| 234 | −** This flag signals when we need to read a next char. | |
| 235 | −*/ | |
| 236 | −#define NEED_OTHER (EOF-1) /* just some flag different from EOF */ | |
| 237 | 263 | |
| 264 | +static void aux_lines (lua_State *L, int idx, int close) { | |
| 265 | + lua_pushliteral(L, FILEHANDLE); | |
| 266 | + lua_rawget(L, LUA_REGISTRYINDEX); | |
| 267 | + lua_pushvalue(L, idx); | |
| 268 | + lua_pushboolean(L, close); /* close/not close file when finished */ | |
| 269 | + lua_pushcclosure(L, io_readline, 3); | |
| 270 | +} | |
| 238 | 271 | |
| 239 | −static int read_pattern (lua_State *L, FILE *f, const char *p) { | |
| 240 | − int inskip = 0; /* {skip} level */ | |
| 241 | − int c = NEED_OTHER; | |
| 242 | − luaL_Buffer b; | |
| 243 | − luaL_buffinit(L, &b); | |
| 244 | − while (*p != '\0') { | |
| 245 | − switch (*p) { | |
| 246 | − case '{': | |
| 247 | − inskip++; | |
| 248 | − p++; | |
| 249 | − continue; | |
| 250 | − case '}': | |
| 251 | − if (!inskip) lua_error(L, "unbalanced braces in read pattern"); | |
| 252 | − inskip--; | |
| 253 | − p++; | |
| 254 | − continue; | |
| 255 | − default: { | |
| 256 | − const char *ep = luaI_classend(L, p); /* get what is next */ | |
| 257 | − int m; /* match result */ | |
| 258 | − if (c == NEED_OTHER) c = getc(f); | |
| 259 | − m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); | |
| 260 | − if (m) { | |
| 261 | − if (!inskip) luaL_putchar(&b, c); | |
| 262 | − c = NEED_OTHER; | |
| 263 | − } | |
| 264 | − switch (*ep) { | |
| 265 | − case '+': /* repetition (1 or more) */ | |
| 266 | − if (!m) goto break_while; /* pattern fails? */ | |
| 267 | − /* else go through */ | |
| 268 | − case '*': /* repetition (0 or more) */ | |
| 269 | − while (m) { /* reads the same item until it fails */ | |
| 270 | − c = getc(f); | |
| 271 | − m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); | |
| 272 | − if (m && !inskip) luaL_putchar(&b, c); | |
| 273 | − } | |
| 274 | − /* go through to continue reading the pattern */ | |
| 275 | − case '?': /* optional */ | |
| 276 | − p = ep+1; /* continues reading the pattern */ | |
| 277 | − continue; | |
| 278 | − default: | |
| 279 | − if (!m) goto break_while; /* pattern fails? */ | |
| 280 | − p = ep; /* else continues reading the pattern */ | |
| 281 | − } | |
| 282 | − } | |
| 283 | − } | |
| 284 | − } break_while: | |
| 285 | − if (c != NEED_OTHER) ungetc(c, f); | |
| 286 | − luaL_pushresult(&b); /* close buffer */ | |
| 287 | − return (*p == '\0'); | |
| 272 | + | |
| 273 | +static int f_lines (lua_State *L) { | |
| 274 | + tofile(L, 1); /* check that it's a valid file handle */ | |
| 275 | + aux_lines(L, 1, 0); | |
| 276 | + return 1; | |
| 288 | 277 | } |
| 289 | 278 | |
| 290 | −#else | |
| 291 | 279 | |
| 292 | −#define read_pattern(L, f, p) (lua_error(L, "read patterns are deprecated"), 0) | |
| 280 | +static int io_lines (lua_State *L) { | |
| 281 | + if (lua_isnoneornil(L, 1)) { /* no arguments? */ | |
| 282 | + lua_pushstring(L, IO_INPUT); | |
| 283 | + lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */ | |
| 284 | + return f_lines(L); | |
| 285 | + } | |
| 286 | + else { | |
| 287 | + const char *filename = luaL_checkstring(L, 1); | |
| 288 | + FILE **pf = newfile(L); | |
| 289 | + *pf = fopen(filename, "r"); | |
| 290 | + luaL_argcheck(L, *pf, 1, strerror(errno)); | |
| 291 | + aux_lines(L, lua_gettop(L), 1); | |
| 292 | + return 1; | |
| 293 | + } | |
| 294 | +} | |
| 295 | + | |
| 293 | 296 | |
| 294 | −#endif | |
| 297 | +/* | |
| 298 | +** {====================================================== | |
| 299 | +** READ | |
| 300 | +** ======================================================= | |
| 301 | +*/ | |
| 295 | 302 | |
| 296 | 303 | |
| 297 | 304 | static int read_number (lua_State *L, FILE *f) { |
| 298 | − double d; | |
| 299 | − if (fscanf(f, "%lf", &d) == 1) { | |
| 305 | + lua_Number d; | |
| 306 | + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { | |
| 300 | 307 | lua_pushnumber(L, d); |
| 301 | 308 | return 1; |
| 302 | 309 | } |
| @@ -304,175 +311,167 @@ static int read_number (lua_State *L, FILE *f) { · 1 unmodified line | ||
| 304 | 311 | } |
| 305 | 312 | |
| 306 | 313 | |
| 307 | −static int read_word (lua_State *L, FILE *f) { | |
| 308 | − int c; | |
| 309 | − luaL_Buffer b; | |
| 310 | − luaL_buffinit(L, &b); | |
| 311 | − do { c = fgetc(f); } while (isspace(c)); /* skip spaces */ | |
| 312 | − while (c != EOF && !isspace(c)) { | |
| 313 | − luaL_putchar(&b, c); | |
| 314 | − c = fgetc(f); | |
| 315 | − } | |
| 314 | +static int test_eof (lua_State *L, FILE *f) { | |
| 315 | + int c = getc(f); | |
| 316 | 316 | ungetc(c, f); |
| 317 | − luaL_pushresult(&b); /* close buffer */ | |
| 318 | − return (lua_strlen(L, -1) > 0); | |
| 317 | + lua_pushlstring(L, NULL, 0); | |
| 318 | + return (c != EOF); | |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | |
| 322 | 322 | static int read_line (lua_State *L, FILE *f) { |
| 323 | − int n = 0; | |
| 324 | 323 | luaL_Buffer b; |
| 325 | 324 | luaL_buffinit(L, &b); |
| 326 | 325 | for (;;) { |
| 326 | + size_t l; | |
| 327 | 327 | char *p = luaL_prepbuffer(&b); |
| 328 | − if (!fgets(p, LUAL_BUFFERSIZE, f)) /* read fails? */ | |
| 329 | − break; | |
| 330 | − n = strlen(p); | |
| 331 | − if (p[n-1] != '\n') | |
| 332 | − luaL_addsize(&b, n); | |
| 333 | − else { | |
| 334 | − luaL_addsize(&b, n-1); /* do not add the `\n' */ | |
| 335 | − break; | |
| 328 | + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ | |
| 329 | + luaL_pushresult(&b); /* close buffer */ | |
| 330 | + return (lua_strlen(L, -1) > 0); /* check whether read something */ | |
| 336 | 331 | } |
| 337 | − } | |
| 338 | − luaL_pushresult(&b); /* close buffer */ | |
| 339 | − return (n > 0); /* read something? */ | |
| 340 | −} | |
| 341 | − | |
| 342 | − | |
| 343 | −static void read_file (lua_State *L, FILE *f) { | |
| 344 | − size_t len = 0; | |
| 345 | − size_t size = BUFSIZ; | |
| 346 | − char *buffer = NULL; | |
| 347 | − for (;;) { | |
| 348 | − char *newbuffer = (char *)realloc(buffer, size); | |
| 349 | − if (newbuffer == NULL) { | |
| 350 | − free(buffer); | |
| 351 | − lua_error(L, "not enough memory to read a file"); | |
| 332 | + l = strlen(p); | |
| 333 | + if (p[l-1] != '\n') | |
| 334 | + luaL_addsize(&b, l); | |
| 335 | + else { | |
| 336 | + luaL_addsize(&b, l - 1); /* do not include `eol' */ | |
| 337 | + luaL_pushresult(&b); /* close buffer */ | |
| 338 | + return 1; /* read at least an `eol' */ | |
| 352 | 339 | } |
| 353 | − buffer = newbuffer; | |
| 354 | − len += fread(buffer+len, sizeof(char), size-len, f); | |
| 355 | − if (len < size) break; /* did not read all it could */ | |
| 356 | − size *= 2; | |
| 357 | 340 | } |
| 358 | − lua_pushlstring(L, buffer, len); | |
| 359 | − free(buffer); | |
| 360 | 341 | } |
| 361 | 342 | |
| 362 | 343 | |
| 363 | 344 | static int read_chars (lua_State *L, FILE *f, size_t n) { |
| 364 | − char *buffer; | |
| 365 | − size_t n1; | |
| 366 | − char statbuff[BUFSIZ]; | |
| 367 | − if (n <= BUFSIZ) | |
| 368 | − buffer = statbuff; | |
| 369 | − else { | |
| 370 | − buffer = (char *)malloc(n); | |
| 371 | − if (buffer == NULL) | |
| 372 | − lua_error(L, "not enough memory to read a file"); | |
| 373 | − } | |
| 374 | − n1 = fread(buffer, sizeof(char), n, f); | |
| 375 | − lua_pushlstring(L, buffer, n1); | |
| 376 | − if (buffer != statbuff) free(buffer); | |
| 377 | − return (n1 > 0 || n == 0); | |
| 345 | + size_t rlen; /* how much to read */ | |
| 346 | + size_t nr; /* number of chars actually read */ | |
| 347 | + luaL_Buffer b; | |
| 348 | + luaL_buffinit(L, &b); | |
| 349 | + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ | |
| 350 | + do { | |
| 351 | + char *p = luaL_prepbuffer(&b); | |
| 352 | + if (rlen > n) rlen = n; /* cannot read more than asked */ | |
| 353 | + nr = fread(p, sizeof(char), rlen, f); | |
| 354 | + luaL_addsize(&b, nr); | |
| 355 | + n -= nr; /* still have to read `n' chars */ | |
| 356 | + } while (n > 0 && nr == rlen); /* until end of count or eof */ | |
| 357 | + luaL_pushresult(&b); /* close buffer */ | |
| 358 | + return (n == 0 || lua_strlen(L, -1) > 0); | |
| 378 | 359 | } |
| 379 | 360 | |
| 380 | 361 | |
| 381 | −static int io_read (lua_State *L) { | |
| 382 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 383 | − int lastarg = lua_gettop(L) - 1; | |
| 384 | − int firstarg = 1; | |
| 385 | − FILE *f = gethandle(L, ctrl, firstarg); | |
| 362 | +static int g_read (lua_State *L, FILE *f, int first) { | |
| 363 | + int nargs = lua_gettop(L) - 1; | |
| 364 | + int success; | |
| 386 | 365 | int n; |
| 387 | − if (f) firstarg++; | |
| 388 | − else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */ | |
| 389 | − lua_pop(L, 1); | |
| 390 | − if (firstarg > lastarg) { /* no arguments? */ | |
| 391 | − lua_settop(L, 0); /* erase upvalue and other eventual garbage */ | |
| 392 | − firstarg = lastarg = 1; /* correct indices */ | |
| 393 | − lua_pushstring(L, "*l"); /* push default argument */ | |
| 366 | + if (nargs == 0) { /* no arguments? */ | |
| 367 | + success = read_line(L, f); | |
| 368 | + n = first+1; /* to return 1 result */ | |
| 394 | 369 | } |
| 395 | − else /* ensure stack space for all results and for auxlib's buffer */ | |
| 396 | − luaL_checkstack(L, lastarg-firstarg+1+LUA_MINSTACK, "too many arguments"); | |
| 397 | − for (n = firstarg; n<=lastarg; n++) { | |
| 398 | − int success; | |
| 399 | − if (lua_isnumber(L, n)) | |
| 400 | − success = read_chars(L, f, (size_t)lua_tonumber(L, n)); | |
| 401 | − else { | |
| 402 | − const char *p = luaL_check_string(L, n); | |
| 403 | − if (p[0] != '*') | |
| 404 | − success = read_pattern(L, f, p); /* deprecated! */ | |
| 370 | + else { /* ensure stack space for all results and for auxlib's buffer */ | |
| 371 | + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); | |
| 372 | + success = 1; | |
| 373 | + for (n = first; nargs-- && success; n++) { | |
| 374 | + if (lua_type(L, n) == LUA_TNUMBER) { | |
| 375 | + size_t l = (size_t)lua_tonumber(L, n); | |
| 376 | + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); | |
| 377 | + } | |
| 405 | 378 | else { |
| 379 | + const char *p = lua_tostring(L, n); | |
| 380 | + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); | |
| 406 | 381 | switch (p[1]) { |
| 407 | 382 | case 'n': /* number */ |
| 408 | − if (!read_number(L, f)) goto endloop; /* read fails */ | |
| 409 | − continue; /* number is already pushed; avoid the "pushstring" */ | |
| 383 | + success = read_number(L, f); | |
| 384 | + break; | |
| 410 | 385 | case 'l': /* line */ |
| 411 | 386 | success = read_line(L, f); |
| 412 | 387 | break; |
| 413 | 388 | case 'a': /* file */ |
| 414 | − read_file(L, f); | |
| 389 | + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ | |
| 415 | 390 | success = 1; /* always success */ |
| 416 | 391 | break; |
| 417 | 392 | case 'w': /* word */ |
| 418 | − success = read_word(L, f); | |
| 419 | − break; | |
| 393 | + return luaL_error(L, "obsolete option `*w' to `read'"); | |
| 420 | 394 | default: |
| 421 | − luaL_argerror(L, n, "invalid format"); | |
| 422 | − success = 0; /* to avoid warnings */ | |
| 395 | + return luaL_argerror(L, n, "invalid format"); | |
| 423 | 396 | } |
| 424 | 397 | } |
| 425 | 398 | } |
| 426 | − if (!success) { | |
| 427 | − lua_pop(L, 1); /* remove last result */ | |
| 428 | − break; /* read fails */ | |
| 399 | + } | |
| 400 | + if (!success) { | |
| 401 | + lua_pop(L, 1); /* remove last result */ | |
| 402 | + lua_pushnil(L); /* push nil instead */ | |
| 403 | + } | |
| 404 | + return n - first; | |
| 405 | +} | |
| 406 | + | |
| 407 | + | |
| 408 | +static int io_read (lua_State *L) { | |
| 409 | + return g_read(L, getiofile(L, IO_INPUT), 1); | |
| 410 | +} | |
| 411 | + | |
| 412 | + | |
| 413 | +static int f_read (lua_State *L) { | |
| 414 | + return g_read(L, tofile(L, 1), 2); | |
| 415 | +} | |
| 416 | + | |
| 417 | + | |
| 418 | +static int io_readline (lua_State *L) { | |
| 419 | + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2)); | |
| 420 | + if (f == NULL) /* file is already closed? */ | |
| 421 | + luaL_error(L, "file is already closed"); | |
| 422 | + if (read_line(L, f)) return 1; | |
| 423 | + else { /* EOF */ | |
| 424 | + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ | |
| 425 | + lua_settop(L, 0); | |
| 426 | + lua_pushvalue(L, lua_upvalueindex(2)); | |
| 427 | + aux_close(L); /* close it */ | |
| 429 | 428 | } |
| 430 | − } endloop: | |
| 431 | − return n - firstarg; | |
| 429 | + return 0; | |
| 430 | + } | |
| 432 | 431 | } |
| 433 | 432 | |
| 434 | 433 | /* }====================================================== */ |
| 435 | 434 | |
| 436 | 435 | |
| 437 | −static int io_write (lua_State *L) { | |
| 438 | − int lastarg = lua_gettop(L) - 1; | |
| 439 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 440 | − int arg = 1; | |
| 436 | +static int g_write (lua_State *L, FILE *f, int arg) { | |
| 437 | + int nargs = lua_gettop(L) - 1; | |
| 441 | 438 | int status = 1; |
| 442 | − FILE *f = gethandle(L, ctrl, arg); | |
| 443 | − if (f) arg++; | |
| 444 | − else f = getfilebyref(L, ctrl, OUTFILE); /* get _OUTPUT */ | |
| 445 | − for (; arg <= lastarg; arg++) { | |
| 446 | − if (lua_type(L, arg) == LUA_TNUMBER) { /* LUA_NUMBER */ | |
| 439 | + for (; nargs--; arg++) { | |
| 440 | + if (lua_type(L, arg) == LUA_TNUMBER) { | |
| 447 | 441 | /* optimization: could be done exactly as for strings */ |
| 448 | − status = status && fprintf(f, "%.16g", lua_tonumber(L, arg)) > 0; | |
| 442 | + status = status && | |
| 443 | + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; | |
| 449 | 444 | } |
| 450 | 445 | else { |
| 451 | 446 | size_t l; |
| 452 | − const char *s = luaL_check_lstr(L, arg, &l); | |
| 447 | + const char *s = luaL_checklstring(L, arg, &l); | |
| 453 | 448 | status = status && (fwrite(s, sizeof(char), l, f) == l); |
| 454 | 449 | } |
| 455 | 450 | } |
| 456 | − pushresult(L, status); | |
| 457 | − return 1; | |
| 451 | + return pushresult(L, status, NULL); | |
| 452 | +} | |
| 453 | + | |
| 454 | + | |
| 455 | +static int io_write (lua_State *L) { | |
| 456 | + return g_write(L, getiofile(L, IO_OUTPUT), 1); | |
| 458 | 457 | } |
| 459 | 458 | |
| 460 | 459 | |
| 461 | −static int io_seek (lua_State *L) { | |
| 460 | +static int f_write (lua_State *L) { | |
| 461 | + return g_write(L, tofile(L, 1), 2); | |
| 462 | +} | |
| 463 | + | |
| 464 | + | |
| 465 | +static int f_seek (lua_State *L) { | |
| 462 | 466 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; |
| 463 | 467 | static const char *const modenames[] = {"set", "cur", "end", NULL}; |
| 464 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 465 | − FILE *f; | |
| 466 | − int op; | |
| 467 | − long offset; | |
| 468 | − lua_pop(L, 1); /* remove upvalue */ | |
| 469 | − f = getnonullfile(L, ctrl, 1); | |
| 470 | − op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames); | |
| 471 | − offset = luaL_opt_long(L, 3, 0); | |
| 472 | − luaL_arg_check(L, op != -1, 2, "invalid mode"); | |
| 468 | + FILE *f = tofile(L, 1); | |
| 469 | + int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames); | |
| 470 | + long offset = luaL_optlong(L, 3, 0); | |
| 471 | + luaL_argcheck(L, op != -1, 2, "invalid mode"); | |
| 473 | 472 | op = fseek(f, offset, mode[op]); |
| 474 | 473 | if (op) |
| 475 | − return pushresult(L, 0); /* error */ | |
| 474 | + return pushresult(L, 0, NULL); /* error */ | |
| 476 | 475 | else { |
| 477 | 476 | lua_pushnumber(L, ftell(f)); |
| 478 | 477 | return 1; |
| @@ -481,12 +480,51 @@ static int io_seek (lua_State *L) { · 2 unmodified lines | ||
| 481 | 480 | |
| 482 | 481 | |
| 483 | 482 | static int io_flush (lua_State *L) { |
| 484 | − IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); | |
| 485 | − FILE *f; | |
| 486 | − lua_pop(L, 1); /* remove upvalue */ | |
| 487 | − f = gethandle(L, ctrl, 1); | |
| 488 | − luaL_arg_check(L, f || lua_isnull(L, 1), 1, "invalid file handle"); | |
| 489 | − return pushresult(L, fflush(f) == 0); | |
| 483 | + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); | |
| 484 | +} | |
| 485 | + | |
| 486 | + | |
| 487 | +static int f_flush (lua_State *L) { | |
| 488 | + return pushresult(L, fflush(tofile(L, 1)) == 0, NULL); | |
| 489 | +} | |
| 490 | + | |
| 491 | + | |
| 492 | +static const luaL_reg iolib[] = { | |
| 493 | + {"input", io_input}, | |
| 494 | + {"output", io_output}, | |
| 495 | + {"lines", io_lines}, | |
| 496 | + {"close", io_close}, | |
| 497 | + {"flush", io_flush}, | |
| 498 | + {"open", io_open}, | |
| 499 | + {"popen", io_popen}, | |
| 500 | + {"read", io_read}, | |
| 501 | + {"tmpfile", io_tmpfile}, | |
| 502 | + {"type", io_type}, | |
| 503 | + {"write", io_write}, | |
| 504 | + {NULL, NULL} | |
| 505 | +}; | |
| 506 | + | |
| 507 | + | |
| 508 | +static const luaL_reg flib[] = { | |
| 509 | + {"flush", f_flush}, | |
| 510 | + {"read", f_read}, | |
| 511 | + {"lines", f_lines}, | |
| 512 | + {"seek", f_seek}, | |
| 513 | + {"write", f_write}, | |
| 514 | + {"close", io_close}, | |
| 515 | + {"__gc", io_gc}, | |
| 516 | + {"__tostring", io_tostring}, | |
| 517 | + {NULL, NULL} | |
| 518 | +}; | |
| 519 | + | |
| 520 | + | |
| 521 | +static void createmeta (lua_State *L) { | |
| 522 | + luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */ | |
| 523 | + /* file methods */ | |
| 524 | + lua_pushliteral(L, "__index"); | |
| 525 | + lua_pushvalue(L, -2); /* push metatable */ | |
| 526 | + lua_rawset(L, -3); /* metatable.__index = metatable */ | |
| 527 | + luaL_openlib(L, NULL, flib, 0); | |
| 490 | 528 | } |
| 491 | 529 | |
| 492 | 530 | /* }====================================================== */ |
| @@ -499,220 +537,214 @@ static int io_flush (lua_State *L) { · 6 unmodified lines | ||
| 499 | 537 | */ |
| 500 | 538 | |
| 501 | 539 | static int io_execute (lua_State *L) { |
| 502 | − lua_pushnumber(L, system(luaL_check_string(L, 1))); | |
| 540 | + lua_pushnumber(L, system(luaL_checkstring(L, 1))); | |
| 503 | 541 | return 1; |
| 504 | 542 | } |
| 505 | 543 | |
| 506 | 544 | |
| 507 | 545 | static int io_remove (lua_State *L) { |
| 508 | − return pushresult(L, remove(luaL_check_string(L, 1)) == 0); | |
| 546 | + const char *filename = luaL_checkstring(L, 1); | |
| 547 | + return pushresult(L, remove(filename) == 0, filename); | |
| 509 | 548 | } |
| 510 | 549 | |
| 511 | 550 | |
| 512 | 551 | static int io_rename (lua_State *L) { |
| 513 | − return pushresult(L, rename(luaL_check_string(L, 1), | |
| 514 | − luaL_check_string(L, 2)) == 0); | |
| 552 | + const char *fromname = luaL_checkstring(L, 1); | |
| 553 | + const char *toname = luaL_checkstring(L, 2); | |
| 554 | + return pushresult(L, rename(fromname, toname) == 0, fromname); | |
| 515 | 555 | } |
| 516 | 556 | |
| 517 | 557 | |
| 518 | 558 | static int io_tmpname (lua_State *L) { |
| 519 | − lua_pushstring(L, tmpnam(NULL)); | |
| 559 | +#if !USE_TMPNAME | |
| 560 | + luaL_error(L, "`tmpname' not supported"); | |
| 561 | + return 0; | |
| 562 | +#else | |
| 563 | + char buff[L_tmpnam]; | |
| 564 | + if (tmpnam(buff) != buff) | |
| 565 | + return luaL_error(L, "unable to generate a unique filename in `tmpname'"); | |
| 566 | + lua_pushstring(L, buff); | |
| 520 | 567 | return 1; |
| 568 | +#endif | |
| 521 | 569 | } |
| 522 | 570 | |
| 523 | 571 | |
| 524 | − | |
| 525 | 572 | static int io_getenv (lua_State *L) { |
| 526 | − lua_pushstring(L, getenv(luaL_check_string(L, 1))); /* if NULL push nil */ | |
| 573 | + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ | |
| 527 | 574 | return 1; |
| 528 | 575 | } |
| 529 | 576 | |
| 530 | 577 | |
| 531 | 578 | static int io_clock (lua_State *L) { |
| 532 | − lua_pushnumber(L, ((double)clock())/CLOCKS_PER_SEC); | |
| 579 | + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); | |
| 533 | 580 | return 1; |
| 534 | 581 | } |
| 535 | 582 | |
| 536 | 583 | |
| 584 | +/* | |
| 585 | +** {====================================================== | |
| 586 | +** Time/Date operations | |
| 587 | +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, | |
| 588 | +** wday=%w+1, yday=%j, isdst=? } | |
| 589 | +** ======================================================= | |
| 590 | +*/ | |
| 591 | + | |
| 592 | +static void setfield (lua_State *L, const char *key, int value) { | |
| 593 | + lua_pushstring(L, key); | |
| 594 | + lua_pushnumber(L, value); | |
| 595 | + lua_rawset(L, -3); | |
| 596 | +} | |
| 597 | + | |
| 598 | +static void setboolfield (lua_State *L, const char *key, int value) { | |
| 599 | + lua_pushstring(L, key); | |
| 600 | + lua_pushboolean(L, value); | |
| 601 | + lua_rawset(L, -3); | |
| 602 | +} | |
| 603 | + | |
| 604 | +static int getboolfield (lua_State *L, const char *key) { | |
| 605 | + int res; | |
| 606 | + lua_pushstring(L, key); | |
| 607 | + lua_gettable(L, -2); | |
| 608 | + res = lua_toboolean(L, -1); | |
| 609 | + lua_pop(L, 1); | |
| 610 | + return res; | |
| 611 | +} | |
| 612 | + | |
| 613 | + | |
| 614 | +static int getfield (lua_State *L, const char *key, int d) { | |
| 615 | + int res; | |
| 616 | + lua_pushstring(L, key); | |
| 617 | + lua_gettable(L, -2); | |
| 618 | + if (lua_isnumber(L, -1)) | |
| 619 | + res = (int)(lua_tonumber(L, -1)); | |
| 620 | + else { | |
| 621 | + if (d == -2) | |
| 622 | + return luaL_error(L, "field `%s' missing in date table", key); | |
| 623 | + res = d; | |
| 624 | + } | |
| 625 | + lua_pop(L, 1); | |
| 626 | + return res; | |
| 627 | +} | |
| 628 | + | |
| 629 | + | |
| 537 | 630 | static int io_date (lua_State *L) { |
| 538 | − char b[256]; | |
| 539 | − const char *s = luaL_opt_string(L, 1, "%c"); | |
| 631 | + const char *s = luaL_optstring(L, 1, "%c"); | |
| 632 | + time_t t = (time_t)(luaL_optnumber(L, 2, -1)); | |
| 540 | 633 | struct tm *stm; |
| 541 | − time_t t; | |
| 542 | − time(&t); stm = localtime(&t); | |
| 543 | − if (strftime(b, sizeof(b), s, stm)) | |
| 544 | − lua_pushstring(L, b); | |
| 634 | + if (t == (time_t)(-1)) /* no time given? */ | |
| 635 | + t = time(NULL); /* use current time */ | |
| 636 | + if (*s == '!') { /* UTC? */ | |
| 637 | + stm = gmtime(&t); | |
| 638 | + s++; /* skip `!' */ | |
| 639 | + } | |
| 545 | 640 | else |
| 546 | − lua_error(L, "invalid `date' format"); | |
| 641 | + stm = localtime(&t); | |
| 642 | + if (stm == NULL) /* invalid date? */ | |
| 643 | + lua_pushnil(L); | |
| 644 | + else if (strcmp(s, "*t") == 0) { | |
| 645 | + lua_newtable(L); | |
| 646 | + setfield(L, "sec", stm->tm_sec); | |
| 647 | + setfield(L, "min", stm->tm_min); | |
| 648 | + setfield(L, "hour", stm->tm_hour); | |
| 649 | + setfield(L, "day", stm->tm_mday); | |
| 650 | + setfield(L, "month", stm->tm_mon+1); | |
| 651 | + setfield(L, "year", stm->tm_year+1900); | |
| 652 | + setfield(L, "wday", stm->tm_wday+1); | |
| 653 | + setfield(L, "yday", stm->tm_yday+1); | |
| 654 | + setboolfield(L, "isdst", stm->tm_isdst); | |
| 655 | + } | |
| 656 | + else { | |
| 657 | + char b[256]; | |
| 658 | + if (strftime(b, sizeof(b), s, stm)) | |
| 659 | + lua_pushstring(L, b); | |
| 660 | + else | |
| 661 | + return luaL_error(L, "`date' format too long"); | |
| 662 | + } | |
| 547 | 663 | return 1; |
| 548 | 664 | } |
| 549 | 665 | |
| 550 | 666 | |
| 551 | −static int setloc (lua_State *L) { | |
| 552 | − static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, | |
| 553 | − LC_NUMERIC, LC_TIME}; | |
| 554 | − static const char *const catnames[] = {"all", "collate", "ctype", "monetary", | |
| 555 | − "numeric", "time", NULL}; | |
| 556 | − int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames); | |
| 557 | − luaL_arg_check(L, op != -1, 2, "invalid option"); | |
| 558 | − lua_pushstring(L, setlocale(cat[op], luaL_check_string(L, 1))); | |
| 667 | +static int io_time (lua_State *L) { | |
| 668 | + if (lua_isnoneornil(L, 1)) /* called without args? */ | |
| 669 | + lua_pushnumber(L, time(NULL)); /* return current time */ | |
| 670 | + else { | |
| 671 | + time_t t; | |
| 672 | + struct tm ts; | |
| 673 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 674 | + lua_settop(L, 1); /* make sure table is at the top */ | |
| 675 | + ts.tm_sec = getfield(L, "sec", 0); | |
| 676 | + ts.tm_min = getfield(L, "min", 0); | |
| 677 | + ts.tm_hour = getfield(L, "hour", 12); | |
| 678 | + ts.tm_mday = getfield(L, "day", -2); | |
| 679 | + ts.tm_mon = getfield(L, "month", -2) - 1; | |
| 680 | + ts.tm_year = getfield(L, "year", -2) - 1900; | |
| 681 | + ts.tm_isdst = getboolfield(L, "isdst"); | |
| 682 | + t = mktime(&ts); | |
| 683 | + if (t == (time_t)(-1)) | |
| 684 | + lua_pushnil(L); | |
| 685 | + else | |
| 686 | + lua_pushnumber(L, t); | |
| 687 | + } | |
| 559 | 688 | return 1; |
| 560 | 689 | } |
| 561 | 690 | |
| 562 | 691 | |
| 563 | −static int io_exit (lua_State *L) { | |
| 564 | − exit(luaL_opt_int(L, 1, EXIT_SUCCESS)); | |
| 565 | − return 0; /* to avoid warnings */ | |
| 692 | +static int io_difftime (lua_State *L) { | |
| 693 | + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), | |
| 694 | + (time_t)(luaL_optnumber(L, 2, 0)))); | |
| 695 | + return 1; | |
| 566 | 696 | } |
| 567 | 697 | |
| 568 | 698 | /* }====================================================== */ |
| 569 | 699 | |
| 570 | 700 | |
| 571 | − | |
| 572 | −static int io_debug (lua_State *L) { | |
| 573 | − for (;;) { | |
| 574 | − char buffer[250]; | |
| 575 | − fprintf(stderr, "lua_debug> "); | |
| 576 | − if (fgets(buffer, sizeof(buffer), stdin) == 0 || | |
| 577 | − strcmp(buffer, "cont\n") == 0) | |
| 578 | − return 0; | |
| 579 | − lua_dostring(L, buffer); | |
| 580 | − lua_settop(L, 0); /* remove eventual returns */ | |
| 581 | − } | |
| 701 | +static int io_setloc (lua_State *L) { | |
| 702 | + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, | |
| 703 | + LC_NUMERIC, LC_TIME}; | |
| 704 | + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", | |
| 705 | + "numeric", "time", NULL}; | |
| 706 | + const char *l = lua_tostring(L, 1); | |
| 707 | + int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames); | |
| 708 | + luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected"); | |
| 709 | + luaL_argcheck(L, op != -1, 2, "invalid option"); | |
| 710 | + lua_pushstring(L, setlocale(cat[op], l)); | |
| 711 | + return 1; | |
| 582 | 712 | } |
| 583 | 713 | |
| 584 | 714 | |
| 585 | −#define LEVELS1 12 /* size of the first part of the stack */ | |
| 586 | −#define LEVELS2 10 /* size of the second part of the stack */ | |
| 587 | − | |
| 588 | −static int errorfb (lua_State *L) { | |
| 589 | − int level = 1; /* skip level 0 (it's this function) */ | |
| 590 | − int firstpart = 1; /* still before eventual `...' */ | |
| 591 | − lua_Debug ar; | |
| 592 | − luaL_Buffer b; | |
| 593 | − luaL_buffinit(L, &b); | |
| 594 | − luaL_addstring(&b, "error: "); | |
| 595 | − luaL_addstring(&b, luaL_check_string(L, 1)); | |
| 596 | − luaL_addstring(&b, "\n"); | |
| 597 | − while (lua_getstack(L, level++, &ar)) { | |
| 598 | − char buff[120]; /* enough to fit following `sprintf's */ | |
| 599 | − if (level == 2) | |
| 600 | − luaL_addstring(&b, "stack traceback:\n"); | |
| 601 | − else if (level > LEVELS1 && firstpart) { | |
| 602 | − /* no more than `LEVELS2' more levels? */ | |
| 603 | − if (!lua_getstack(L, level+LEVELS2, &ar)) | |
| 604 | − level--; /* keep going */ | |
| 605 | − else { | |
| 606 | − luaL_addstring(&b, " ...\n"); /* too many levels */ | |
| 607 | − while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ | |
| 608 | − level++; | |
| 609 | − } | |
| 610 | − firstpart = 0; | |
| 611 | − continue; | |
| 612 | − } | |
| 613 | − sprintf(buff, "%4d: ", level-1); | |
| 614 | − luaL_addstring(&b, buff); | |
| 615 | − lua_getinfo(L, "Snl", &ar); | |
| 616 | − switch (*ar.namewhat) { | |
| 617 | − case 'g': case 'l': /* global, local */ | |
| 618 | − sprintf(buff, "function `%.50s'", ar.name); | |
| 619 | − break; | |
| 620 | − case 'f': /* field */ | |
| 621 | − sprintf(buff, "method `%.50s'", ar.name); | |
| 622 | − break; | |
| 623 | − case 't': /* tag method */ | |
| 624 | − sprintf(buff, "`%.50s' tag method", ar.name); | |
| 625 | − break; | |
| 626 | − default: { | |
| 627 | − if (*ar.what == 'm') /* main? */ | |
| 628 | − sprintf(buff, "main of %.70s", ar.short_src); | |
| 629 | − else if (*ar.what == 'C') /* C function? */ | |
| 630 | − sprintf(buff, "%.70s", ar.short_src); | |
| 631 | − else | |
| 632 | − sprintf(buff, "function <%d:%.70s>", ar.linedefined, ar.short_src); | |
| 633 | − ar.source = NULL; /* do not print source again */ | |
| 634 | − } | |
| 635 | − } | |
| 636 | − luaL_addstring(&b, buff); | |
| 637 | − if (ar.currentline > 0) { | |
| 638 | − sprintf(buff, " at line %d", ar.currentline); | |
| 639 | − luaL_addstring(&b, buff); | |
| 640 | − } | |
| 641 | − if (ar.source) { | |
| 642 | − sprintf(buff, " [%.70s]", ar.short_src); | |
| 643 | − luaL_addstring(&b, buff); | |
| 644 | − } | |
| 645 | − luaL_addstring(&b, "\n"); | |
| 646 | − } | |
| 647 | − luaL_pushresult(&b); | |
| 648 | − lua_getglobal(L, LUA_ALERT); | |
| 649 | − if (lua_isfunction(L, -1)) { /* avoid loop if _ALERT is not defined */ | |
| 650 | − lua_pushvalue(L, -2); /* error message */ | |
| 651 | − lua_rawcall(L, 1, 0); | |
| 652 | − } | |
| 653 | − return 0; | |
| 715 | +static int io_exit (lua_State *L) { | |
| 716 | + exit(luaL_optint(L, 1, EXIT_SUCCESS)); | |
| 717 | + return 0; /* to avoid warnings */ | |
| 654 | 718 | } |
| 655 | 719 | |
| 656 | − | |
| 657 | − | |
| 658 | −static const struct luaL_reg iolib[] = { | |
| 659 | − {LUA_ERRORMESSAGE, errorfb}, | |
| 720 | +static const luaL_reg syslib[] = { | |
| 660 | 721 | {"clock", io_clock}, |
| 661 | − {"date", io_date}, | |
| 662 | − {"debug", io_debug}, | |
| 663 | − {"execute", io_execute}, | |
| 664 | − {"exit", io_exit}, | |
| 665 | − {"getenv", io_getenv}, | |
| 666 | − {"remove", io_remove}, | |
| 667 | − {"rename", io_rename}, | |
| 668 | − {"setlocale", setloc}, | |
| 669 | − {"tmpname", io_tmpname} | |
| 722 | + {"date", io_date}, | |
| 723 | + {"difftime", io_difftime}, | |
| 724 | + {"execute", io_execute}, | |
| 725 | + {"exit", io_exit}, | |
| 726 | + {"getenv", io_getenv}, | |
| 727 | + {"remove", io_remove}, | |
| 728 | + {"rename", io_rename}, | |
| 729 | + {"setlocale", io_setloc}, | |
| 730 | + {"time", io_time}, | |
| 731 | + {"tmpname", io_tmpname}, | |
| 732 | + {NULL, NULL} | |
| 670 | 733 | }; |
| 671 | 734 | |
| 735 | +/* }====================================================== */ | |
| 672 | 736 | |
| 673 | −static const struct luaL_reg iolibtag[] = { | |
| 674 | − {"appendto", io_appendto}, | |
| 675 | − {"closefile", io_close}, | |
| 676 | − {"flush", io_flush}, | |
| 677 | − {"openfile", io_open}, | |
| 678 | − {"read", io_read}, | |
| 679 | − {"readfrom", io_readfrom}, | |
| 680 | − {"seek", io_seek}, | |
| 681 | − {"write", io_write}, | |
| 682 | − {"writeto", io_writeto} | |
| 683 | −}; | |
| 684 | 737 | |
| 685 | 738 | |
| 686 | −static void openwithcontrol (lua_State *L) { | |
| 687 | − IOCtrl *ctrl = (IOCtrl *)lua_newuserdata(L, sizeof(IOCtrl)); | |
| 688 | − unsigned int i; | |
| 689 | − ctrl->iotag = lua_newtag(L); | |
| 690 | − ctrl->closedtag = lua_newtag(L); | |
| 691 | − for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) { | |
| 692 | − /* put `ctrl' as upvalue for these functions */ | |
| 693 | − lua_pushvalue(L, -1); | |
| 694 | − lua_pushcclosure(L, iolibtag[i].func, 1); | |
| 695 | − lua_setglobal(L, iolibtag[i].name); | |
| 696 | − } | |
| 697 | − /* create references to variable names */ | |
| 698 | − lua_pushstring(L, filenames[INFILE]); | |
| 699 | − ctrl->ref[INFILE] = lua_ref(L, 1); | |
| 700 | − lua_pushstring(L, filenames[OUTFILE]); | |
| 701 | − ctrl->ref[OUTFILE] = lua_ref(L, 1); | |
| 702 | − /* predefined file handles */ | |
| 703 | − setfile(L, ctrl, stdin, INFILE); | |
| 704 | − setfile(L, ctrl, stdout, OUTFILE); | |
| 705 | − setfilebyname(L, ctrl, stdin, "_STDIN"); | |
| 706 | − setfilebyname(L, ctrl, stdout, "_STDOUT"); | |
| 707 | − setfilebyname(L, ctrl, stderr, "_STDERR"); | |
| 708 | − /* close files when collected */ | |
| 709 | − lua_pushcclosure(L, file_collect, 1); /* pops `ctrl' from stack */ | |
| 710 | − lua_settagmethod(L, ctrl->iotag, "gc"); | |
| 711 | −} | |
| 712 | − | |
| 713 | − | |
| 714 | −LUALIB_API void lua_iolibopen (lua_State *L) { | |
| 715 | − luaL_openl(L, iolib); | |
| 716 | − openwithcontrol(L); | |
| 739 | +LUALIB_API int luaopen_io (lua_State *L) { | |
| 740 | + luaL_openlib(L, LUA_OSLIBNAME, syslib, 0); | |
| 741 | + createmeta(L); | |
| 742 | + lua_pushvalue(L, -1); | |
| 743 | + luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); | |
| 744 | + /* put predefined file handles into `io' table */ | |
| 745 | + registerfile(L, stdin, "stdin", IO_INPUT); | |
| 746 | + registerfile(L, stdout, "stdout", IO_OUTPUT); | |
| 747 | + registerfile(L, stderr, "stderr", NULL); | |
| 748 | + return 1; | |
| 717 | 749 | } |
| 718 | 750 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lmathlib.c,v 1.32 2000/10/31 13:10:24 roberto Exp $ | |
| 2 | +** $Id: lmathlib.c,v 1.56 2003/03/11 12:30:37 roberto Exp $ | |
| 3 | 3 | ** Standard mathematical library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -8,6 +8,8 @@ · 2 unmodified lines | ||
| 8 | 8 | #include <stdlib.h> |
| 9 | 9 | #include <math.h> |
| 10 | 10 | |
| 11 | +#define lmathlib_c | |
| 12 | + | |
| 11 | 13 | #include "lua.h" |
| 12 | 14 | |
| 13 | 15 | #include "lauxlib.h" |
| @@ -21,117 +23,117 @@ · 7 unmodified lines | ||
| 21 | 23 | |
| 22 | 24 | |
| 23 | 25 | /* |
| 24 | −** If you want Lua to operate in radians (instead of degrees), | |
| 25 | −** define RADIANS | |
| 26 | +** If you want Lua to operate in degrees (instead of radians), | |
| 27 | +** define USE_DEGREES | |
| 26 | 28 | */ |
| 27 | −#ifdef RADIANS | |
| 28 | −#define FROMRAD(a) (a) | |
| 29 | −#define TORAD(a) (a) | |
| 30 | −#else | |
| 29 | +#ifdef USE_DEGREES | |
| 31 | 30 | #define FROMRAD(a) ((a)/RADIANS_PER_DEGREE) |
| 32 | 31 | #define TORAD(a) ((a)*RADIANS_PER_DEGREE) |
| 32 | +#else | |
| 33 | +#define FROMRAD(a) (a) | |
| 34 | +#define TORAD(a) (a) | |
| 33 | 35 | #endif |
| 34 | 36 | |
| 35 | 37 | |
| 36 | 38 | static int math_abs (lua_State *L) { |
| 37 | − lua_pushnumber(L, fabs(luaL_check_number(L, 1))); | |
| 39 | + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); | |
| 38 | 40 | return 1; |
| 39 | 41 | } |
| 40 | 42 | |
| 41 | 43 | static int math_sin (lua_State *L) { |
| 42 | − lua_pushnumber(L, sin(TORAD(luaL_check_number(L, 1)))); | |
| 44 | + lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1)))); | |
| 43 | 45 | return 1; |
| 44 | 46 | } |
| 45 | 47 | |
| 46 | 48 | static int math_cos (lua_State *L) { |
| 47 | − lua_pushnumber(L, cos(TORAD(luaL_check_number(L, 1)))); | |
| 49 | + lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1)))); | |
| 48 | 50 | return 1; |
| 49 | 51 | } |
| 50 | 52 | |
| 51 | 53 | static int math_tan (lua_State *L) { |
| 52 | − lua_pushnumber(L, tan(TORAD(luaL_check_number(L, 1)))); | |
| 54 | + lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1)))); | |
| 53 | 55 | return 1; |
| 54 | 56 | } |
| 55 | 57 | |
| 56 | 58 | static int math_asin (lua_State *L) { |
| 57 | − lua_pushnumber(L, FROMRAD(asin(luaL_check_number(L, 1)))); | |
| 59 | + lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1)))); | |
| 58 | 60 | return 1; |
| 59 | 61 | } |
| 60 | 62 | |
| 61 | 63 | static int math_acos (lua_State *L) { |
| 62 | − lua_pushnumber(L, FROMRAD(acos(luaL_check_number(L, 1)))); | |
| 64 | + lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1)))); | |
| 63 | 65 | return 1; |
| 64 | 66 | } |
| 65 | 67 | |
| 66 | 68 | static int math_atan (lua_State *L) { |
| 67 | − lua_pushnumber(L, FROMRAD(atan(luaL_check_number(L, 1)))); | |
| 69 | + lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1)))); | |
| 68 | 70 | return 1; |
| 69 | 71 | } |
| 70 | 72 | |
| 71 | 73 | static int math_atan2 (lua_State *L) { |
| 72 | − lua_pushnumber(L, FROMRAD(atan2(luaL_check_number(L, 1), luaL_check_number(L, 2)))); | |
| 74 | + lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)))); | |
| 73 | 75 | return 1; |
| 74 | 76 | } |
| 75 | 77 | |
| 76 | 78 | static int math_ceil (lua_State *L) { |
| 77 | − lua_pushnumber(L, ceil(luaL_check_number(L, 1))); | |
| 79 | + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); | |
| 78 | 80 | return 1; |
| 79 | 81 | } |
| 80 | 82 | |
| 81 | 83 | static int math_floor (lua_State *L) { |
| 82 | − lua_pushnumber(L, floor(luaL_check_number(L, 1))); | |
| 84 | + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); | |
| 83 | 85 | return 1; |
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | static int math_mod (lua_State *L) { |
| 87 | − lua_pushnumber(L, fmod(luaL_check_number(L, 1), luaL_check_number(L, 2))); | |
| 89 | + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | |
| 88 | 90 | return 1; |
| 89 | 91 | } |
| 90 | 92 | |
| 91 | 93 | static int math_sqrt (lua_State *L) { |
| 92 | − lua_pushnumber(L, sqrt(luaL_check_number(L, 1))); | |
| 94 | + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); | |
| 93 | 95 | return 1; |
| 94 | 96 | } |
| 95 | 97 | |
| 96 | 98 | static int math_pow (lua_State *L) { |
| 97 | − lua_pushnumber(L, pow(luaL_check_number(L, 1), luaL_check_number(L, 2))); | |
| 99 | + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | |
| 98 | 100 | return 1; |
| 99 | 101 | } |
| 100 | 102 | |
| 101 | 103 | static int math_log (lua_State *L) { |
| 102 | − lua_pushnumber(L, log(luaL_check_number(L, 1))); | |
| 104 | + lua_pushnumber(L, log(luaL_checknumber(L, 1))); | |
| 103 | 105 | return 1; |
| 104 | 106 | } |
| 105 | 107 | |
| 106 | 108 | static int math_log10 (lua_State *L) { |
| 107 | − lua_pushnumber(L, log10(luaL_check_number(L, 1))); | |
| 109 | + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); | |
| 108 | 110 | return 1; |
| 109 | 111 | } |
| 110 | 112 | |
| 111 | 113 | static int math_exp (lua_State *L) { |
| 112 | − lua_pushnumber(L, exp(luaL_check_number(L, 1))); | |
| 114 | + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); | |
| 113 | 115 | return 1; |
| 114 | 116 | } |
| 115 | 117 | |
| 116 | 118 | static int math_deg (lua_State *L) { |
| 117 | − lua_pushnumber(L, luaL_check_number(L, 1)/RADIANS_PER_DEGREE); | |
| 119 | + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); | |
| 118 | 120 | return 1; |
| 119 | 121 | } |
| 120 | 122 | |
| 121 | 123 | static int math_rad (lua_State *L) { |
| 122 | − lua_pushnumber(L, luaL_check_number(L, 1)*RADIANS_PER_DEGREE); | |
| 124 | + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); | |
| 123 | 125 | return 1; |
| 124 | 126 | } |
| 125 | 127 | |
| 126 | 128 | static int math_frexp (lua_State *L) { |
| 127 | 129 | int e; |
| 128 | − lua_pushnumber(L, frexp(luaL_check_number(L, 1), &e)); | |
| 130 | + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); | |
| 129 | 131 | lua_pushnumber(L, e); |
| 130 | 132 | return 2; |
| 131 | 133 | } |
| 132 | 134 | |
| 133 | 135 | static int math_ldexp (lua_State *L) { |
| 134 | − lua_pushnumber(L, ldexp(luaL_check_number(L, 1), luaL_check_int(L, 2))); | |
| 136 | + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); | |
| 135 | 137 | return 1; |
| 136 | 138 | } |
| 137 | 139 | |
| @@ -139,10 +141,10 @@ static int math_ldexp (lua_State *L) { · 1 unmodified line | ||
| 139 | 141 | |
| 140 | 142 | static int math_min (lua_State *L) { |
| 141 | 143 | int n = lua_gettop(L); /* number of arguments */ |
| 142 | − double dmin = luaL_check_number(L, 1); | |
| 144 | + lua_Number dmin = luaL_checknumber(L, 1); | |
| 143 | 145 | int i; |
| 144 | 146 | for (i=2; i<=n; i++) { |
| 145 | − double d = luaL_check_number(L, i); | |
| 147 | + lua_Number d = luaL_checknumber(L, i); | |
| 146 | 148 | if (d < dmin) |
| 147 | 149 | dmin = d; |
| 148 | 150 | } |
| @@ -153,10 +155,10 @@ static int math_min (lua_State *L) { · 4 unmodified lines | ||
| 153 | 155 | |
| 154 | 156 | static int math_max (lua_State *L) { |
| 155 | 157 | int n = lua_gettop(L); /* number of arguments */ |
| 156 | − double dmax = luaL_check_number(L, 1); | |
| 158 | + lua_Number dmax = luaL_checknumber(L, 1); | |
| 157 | 159 | int i; |
| 158 | 160 | for (i=2; i<=n; i++) { |
| 159 | − double d = luaL_check_number(L, i); | |
| 161 | + lua_Number d = luaL_checknumber(L, i); | |
| 160 | 162 | if (d > dmax) |
| 161 | 163 | dmax = d; |
| 162 | 164 | } |
| @@ -166,73 +168,79 @@ static int math_max (lua_State *L) { · 3 unmodified lines | ||
| 166 | 168 | |
| 167 | 169 | |
| 168 | 170 | static int math_random (lua_State *L) { |
| 169 | − /* the '%' avoids the (rare) case of r==1, and is needed also because on | |
| 170 | − some systems (SunOS!) "rand()" may return a value larger than RAND_MAX */ | |
| 171 | − double r = (double)(rand()%RAND_MAX) / (double)RAND_MAX; | |
| 171 | + /* the `%' avoids the (rare) case of r==1, and is needed also because on | |
| 172 | + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ | |
| 173 | + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; | |
| 172 | 174 | switch (lua_gettop(L)) { /* check number of arguments */ |
| 173 | 175 | case 0: { /* no arguments */ |
| 174 | 176 | lua_pushnumber(L, r); /* Number between 0 and 1 */ |
| 175 | 177 | break; |
| 176 | 178 | } |
| 177 | 179 | case 1: { /* only upper limit */ |
| 178 | − int u = luaL_check_int(L, 1); | |
| 179 | − luaL_arg_check(L, 1<=u, 1, "interval is empty"); | |
| 180 | − lua_pushnumber(L, (int)(r*u)+1); /* integer between 1 and `u' */ | |
| 180 | + int u = luaL_checkint(L, 1); | |
| 181 | + luaL_argcheck(L, 1<=u, 1, "interval is empty"); | |
| 182 | + lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */ | |
| 181 | 183 | break; |
| 182 | 184 | } |
| 183 | 185 | case 2: { /* lower and upper limits */ |
| 184 | − int l = luaL_check_int(L, 1); | |
| 185 | − int u = luaL_check_int(L, 2); | |
| 186 | − luaL_arg_check(L, l<=u, 2, "interval is empty"); | |
| 187 | − lua_pushnumber(L, (int)(r*(u-l+1))+l); /* integer between `l' and `u' */ | |
| 186 | + int l = luaL_checkint(L, 1); | |
| 187 | + int u = luaL_checkint(L, 2); | |
| 188 | + luaL_argcheck(L, l<=u, 2, "interval is empty"); | |
| 189 | + lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */ | |
| 188 | 190 | break; |
| 189 | 191 | } |
| 190 | − default: lua_error(L, "wrong number of arguments"); | |
| 192 | + default: return luaL_error(L, "wrong number of arguments"); | |
| 191 | 193 | } |
| 192 | 194 | return 1; |
| 193 | 195 | } |
| 194 | 196 | |
| 195 | 197 | |
| 196 | 198 | static int math_randomseed (lua_State *L) { |
| 197 | − srand(luaL_check_int(L, 1)); | |
| 199 | + srand(luaL_checkint(L, 1)); | |
| 198 | 200 | return 0; |
| 199 | 201 | } |
| 200 | 202 | |
| 201 | 203 | |
| 202 | −static const struct luaL_reg mathlib[] = { | |
| 203 | −{"abs", math_abs}, | |
| 204 | −{"sin", math_sin}, | |
| 205 | −{"cos", math_cos}, | |
| 206 | −{"tan", math_tan}, | |
| 207 | −{"asin", math_asin}, | |
| 208 | −{"acos", math_acos}, | |
| 209 | −{"atan", math_atan}, | |
| 210 | −{"atan2", math_atan2}, | |
| 211 | −{"ceil", math_ceil}, | |
| 212 | −{"floor", math_floor}, | |
| 213 | −{"mod", math_mod}, | |
| 214 | −{"frexp", math_frexp}, | |
| 215 | −{"ldexp", math_ldexp}, | |
| 216 | −{"sqrt", math_sqrt}, | |
| 217 | −{"min", math_min}, | |
| 218 | −{"max", math_max}, | |
| 219 | −{"log", math_log}, | |
| 220 | −{"log10", math_log10}, | |
| 221 | −{"exp", math_exp}, | |
| 222 | −{"deg", math_deg}, | |
| 223 | −{"rad", math_rad}, | |
| 224 | −{"random", math_random}, | |
| 225 | −{"randomseed", math_randomseed} | |
| 204 | +static const luaL_reg mathlib[] = { | |
| 205 | + {"abs", math_abs}, | |
| 206 | + {"sin", math_sin}, | |
| 207 | + {"cos", math_cos}, | |
| 208 | + {"tan", math_tan}, | |
| 209 | + {"asin", math_asin}, | |
| 210 | + {"acos", math_acos}, | |
| 211 | + {"atan", math_atan}, | |
| 212 | + {"atan2", math_atan2}, | |
| 213 | + {"ceil", math_ceil}, | |
| 214 | + {"floor", math_floor}, | |
| 215 | + {"mod", math_mod}, | |
| 216 | + {"frexp", math_frexp}, | |
| 217 | + {"ldexp", math_ldexp}, | |
| 218 | + {"sqrt", math_sqrt}, | |
| 219 | + {"min", math_min}, | |
| 220 | + {"max", math_max}, | |
| 221 | + {"log", math_log}, | |
| 222 | + {"log10", math_log10}, | |
| 223 | + {"exp", math_exp}, | |
| 224 | + {"deg", math_deg}, | |
| 225 | + {"pow", math_pow}, | |
| 226 | + {"rad", math_rad}, | |
| 227 | + {"random", math_random}, | |
| 228 | + {"randomseed", math_randomseed}, | |
| 229 | + {NULL, NULL} | |
| 226 | 230 | }; |
| 227 | 231 | |
| 232 | + | |
| 228 | 233 | /* |
| 229 | 234 | ** Open math library |
| 230 | 235 | */ |
| 231 | −LUALIB_API void lua_mathlibopen (lua_State *L) { | |
| 232 | − luaL_openl(L, mathlib); | |
| 233 | − lua_pushcfunction(L, math_pow); | |
| 234 | − lua_settagmethod(L, LUA_TNUMBER, "pow"); | |
| 236 | +LUALIB_API int luaopen_math (lua_State *L) { | |
| 237 | + luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); | |
| 238 | + lua_pushliteral(L, "pi"); | |
| 235 | 239 | lua_pushnumber(L, PI); |
| 236 | − lua_setglobal(L, "PI"); | |
| 240 | + lua_settable(L, -3); | |
| 241 | + lua_pushliteral(L, "__pow"); | |
| 242 | + lua_pushcfunction(L, math_pow); | |
| 243 | + lua_settable(L, LUA_GLOBALSINDEX); | |
| 244 | + return 1; | |
| 237 | 245 | } |
| 238 | 246 | |
| @@ -0,0 +1,205 @@ | ||
| 1 | +/* | |
| 2 | +** $Id: loadlib.c,v 1.4 2003/04/07 20:11:53 roberto Exp $ | |
| 3 | +** Dynamic library loader for Lua | |
| 4 | +** See Copyright Notice in lua.h | |
| 5 | +* | |
| 6 | +* This Lua library exports a single function, called loadlib, which is | |
| 7 | +* called from Lua as loadlib(lib,init), where lib is the full name of the | |
| 8 | +* library to be loaded (including the complete path) and init is the name | |
| 9 | +* of a function to be called after the library is loaded. Typically, this | |
| 10 | +* function will register other functions, thus making the complete library | |
| 11 | +* available to Lua. The init function is *not* automatically called by | |
| 12 | +* loadlib. Instead, loadlib returns the init function as a Lua function | |
| 13 | +* that the client can call when it thinks is appropriate. In the case of | |
| 14 | +* errors, loadlib returns nil and two strings describing the error. | |
| 15 | +* The first string is supplied by the operating system; it should be | |
| 16 | +* informative and useful for error messages. The second string is "open", | |
| 17 | +* "init", or "absent" to identify the error and is meant to be used for | |
| 18 | +* making decisions without having to look into the first string (whose | |
| 19 | +* format is system-dependent). | |
| 20 | +* | |
| 21 | +* This module contains an implementation of loadlib for Unix systems that | |
| 22 | +* have dlfcn, an implementation for Windows, and a stub for other systems. | |
| 23 | +* See the list at the end of this file for some links to available | |
| 24 | +* implementations of dlfcn and interfaces to other native dynamic loaders | |
| 25 | +* on top of which loadlib could be implemented. | |
| 26 | +* | |
| 27 | +*/ | |
| 28 | + | |
| 29 | +#include "lua.h" | |
| 30 | +#include "lauxlib.h" | |
| 31 | +#include "lualib.h" | |
| 32 | + | |
| 33 | + | |
| 34 | +#undef LOADLIB | |
| 35 | + | |
| 36 | + | |
| 37 | +#ifdef USE_DLOPEN | |
| 38 | +#define LOADLIB | |
| 39 | +/* | |
| 40 | +* This is an implementation of loadlib based on the dlfcn interface. | |
| 41 | +* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, | |
| 42 | +* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least | |
| 43 | +* as an emulation layer on top of native functions. | |
| 44 | +*/ | |
| 45 | + | |
| 46 | +#include <dlfcn.h> | |
| 47 | + | |
| 48 | +static int loadlib(lua_State *L) | |
| 49 | +{ | |
| 50 | + const char *path=luaL_checkstring(L,1); | |
| 51 | + const char *init=luaL_checkstring(L,2); | |
| 52 | + void *lib=dlopen(path,RTLD_NOW); | |
| 53 | + if (lib!=NULL) | |
| 54 | + { | |
| 55 | + lua_CFunction f=(lua_CFunction) dlsym(lib,init); | |
| 56 | + if (f!=NULL) | |
| 57 | + { | |
| 58 | + lua_pushlightuserdata(L,lib); | |
| 59 | + lua_pushcclosure(L,f,1); | |
| 60 | + return 1; | |
| 61 | + } | |
| 62 | + } | |
| 63 | + /* else return appropriate error messages */ | |
| 64 | + lua_pushnil(L); | |
| 65 | + lua_pushstring(L,dlerror()); | |
| 66 | + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); | |
| 67 | + if (lib!=NULL) dlclose(lib); | |
| 68 | + return 3; | |
| 69 | +} | |
| 70 | + | |
| 71 | +#endif | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | +/* | |
| 76 | +** In Windows, default is to use dll; otherwise, default is not to use dll | |
| 77 | +*/ | |
| 78 | +#ifndef USE_DLL | |
| 79 | +#ifdef _WIN32 | |
| 80 | +#define USE_DLL 1 | |
| 81 | +#else | |
| 82 | +#define USE_DLL 0 | |
| 83 | +#endif | |
| 84 | +#endif | |
| 85 | + | |
| 86 | + | |
| 87 | +#if USE_DLL | |
| 88 | +#define LOADLIB | |
| 89 | +/* | |
| 90 | +* This is an implementation of loadlib for Windows using native functions. | |
| 91 | +*/ | |
| 92 | + | |
| 93 | +#include <windows.h> | |
| 94 | + | |
| 95 | +static void pusherror(lua_State *L) | |
| 96 | +{ | |
| 97 | + int error=GetLastError(); | |
| 98 | + char buffer[128]; | |
| 99 | + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, | |
| 100 | + 0, error, 0, buffer, sizeof(buffer), 0)) | |
| 101 | + lua_pushstring(L,buffer); | |
| 102 | + else | |
| 103 | + lua_pushfstring(L,"system error %d\n",error); | |
| 104 | +} | |
| 105 | + | |
| 106 | +static int loadlib(lua_State *L) | |
| 107 | +{ | |
| 108 | + const char *path=luaL_checkstring(L,1); | |
| 109 | + const char *init=luaL_checkstring(L,2); | |
| 110 | + HINSTANCE lib=LoadLibrary(path); | |
| 111 | + if (lib!=NULL) | |
| 112 | + { | |
| 113 | + lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); | |
| 114 | + if (f!=NULL) | |
| 115 | + { | |
| 116 | + lua_pushlightuserdata(L,lib); | |
| 117 | + lua_pushcclosure(L,f,1); | |
| 118 | + return 1; | |
| 119 | + } | |
| 120 | + } | |
| 121 | + lua_pushnil(L); | |
| 122 | + pusherror(L); | |
| 123 | + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); | |
| 124 | + if (lib!=NULL) FreeLibrary(lib); | |
| 125 | + return 3; | |
| 126 | +} | |
| 127 | + | |
| 128 | +#endif | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | +#ifndef LOADLIB | |
| 133 | +/* Fallback for other systems */ | |
| 134 | + | |
| 135 | +/* | |
| 136 | +** Those systems support dlopen, so they should have defined USE_DLOPEN. | |
| 137 | +** The default (no)implementation gives them a special error message. | |
| 138 | +*/ | |
| 139 | +#ifdef linux | |
| 140 | +#define LOADLIB | |
| 141 | +#endif | |
| 142 | + | |
| 143 | +#ifdef sun | |
| 144 | +#define LOADLIB | |
| 145 | +#endif | |
| 146 | + | |
| 147 | +#ifdef sgi | |
| 148 | +#define LOADLIB | |
| 149 | +#endif | |
| 150 | + | |
| 151 | +#ifdef BSD | |
| 152 | +#define LOADLIB | |
| 153 | +#endif | |
| 154 | + | |
| 155 | +#ifdef _WIN32 | |
| 156 | +#define LOADLIB | |
| 157 | +#endif | |
| 158 | + | |
| 159 | +#ifdef LOADLIB | |
| 160 | +#undef LOADLIB | |
| 161 | +#define LOADLIB "`loadlib' not installed (check your Lua configuration)" | |
| 162 | +#else | |
| 163 | +#define LOADLIB "`loadlib' not supported" | |
| 164 | +#endif | |
| 165 | + | |
| 166 | +static int loadlib(lua_State *L) | |
| 167 | +{ | |
| 168 | + lua_pushnil(L); | |
| 169 | + lua_pushliteral(L,LOADLIB); | |
| 170 | + lua_pushliteral(L,"absent"); | |
| 171 | + return 3; | |
| 172 | +} | |
| 173 | +#endif | |
| 174 | + | |
| 175 | +LUALIB_API int luaopen_loadlib (lua_State *L) | |
| 176 | +{ | |
| 177 | + lua_register(L,"loadlib",loadlib); | |
| 178 | + return 0; | |
| 179 | +} | |
| 180 | + | |
| 181 | +/* | |
| 182 | +* Here are some links to available implementations of dlfcn and | |
| 183 | +* interfaces to other native dynamic loaders on top of which loadlib | |
| 184 | +* could be implemented. Please send contributions and corrections to us. | |
| 185 | +* | |
| 186 | +* AIX | |
| 187 | +* Starting with AIX 4.2, dlfcn is included in the base OS. | |
| 188 | +* There is also an emulation package available. | |
| 189 | +* http://www.faqs.org/faqs/aix-faq/part4/section-21.html | |
| 190 | +* | |
| 191 | +* HPUX | |
| 192 | +* HPUX 11 has dlfcn. For HPUX 10 use shl_*. | |
| 193 | +* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html | |
| 194 | +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html | |
| 195 | +* | |
| 196 | +* Macintosh, Windows | |
| 197 | +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html | |
| 198 | +* | |
| 199 | +* Mac OS X/Darwin | |
| 200 | +* http://www.opendarwin.org/projects/dlcompat/ | |
| 201 | +* | |
| 202 | +* GLIB has wrapper code for BeOS, OS2, Unix and Windows | |
| 203 | +* http://cvs.gnome.org/lxr/source/glib/gmodule/ | |
| 204 | +* | |
| 205 | +*/ | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lstrlib.c,v 1.56 2000/10/27 16:15:53 roberto Exp $ | |
| 2 | +** $Id: lstrlib.c,v 1.98 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | 3 | ** Standard library for string operations and pattern-matching |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -11,37 +11,47 @@ · 5 unmodified lines | ||
| 11 | 11 | #include <stdlib.h> |
| 12 | 12 | #include <string.h> |
| 13 | 13 | |
| 14 | +#define lstrlib_c | |
| 15 | + | |
| 14 | 16 | #include "lua.h" |
| 15 | 17 | |
| 16 | 18 | #include "lauxlib.h" |
| 17 | 19 | #include "lualib.h" |
| 18 | 20 | |
| 19 | 21 | |
| 22 | +/* macro to `unsign' a character */ | |
| 23 | +#ifndef uchar | |
| 24 | +#define uchar(c) ((unsigned char)(c)) | |
| 25 | +#endif | |
| 26 | + | |
| 27 | + | |
| 28 | +typedef long sint32; /* a signed version for size_t */ | |
| 29 | + | |
| 20 | 30 | |
| 21 | 31 | static int str_len (lua_State *L) { |
| 22 | 32 | size_t l; |
| 23 | − luaL_check_lstr(L, 1, &l); | |
| 24 | − lua_pushnumber(L, l); | |
| 33 | + luaL_checklstring(L, 1, &l); | |
| 34 | + lua_pushnumber(L, (lua_Number)l); | |
| 25 | 35 | return 1; |
| 26 | 36 | } |
| 27 | 37 | |
| 28 | 38 | |
| 29 | −static long posrelat (long pos, size_t len) { | |
| 39 | +static sint32 posrelat (sint32 pos, size_t len) { | |
| 30 | 40 | /* relative string position: negative means back from end */ |
| 31 | − return (pos>=0) ? pos : (long)len+pos+1; | |
| 41 | + return (pos>=0) ? pos : (sint32)len+pos+1; | |
| 32 | 42 | } |
| 33 | 43 | |
| 34 | 44 | |
| 35 | 45 | static int str_sub (lua_State *L) { |
| 36 | 46 | size_t l; |
| 37 | − const char *s = luaL_check_lstr(L, 1, &l); | |
| 38 | − long start = posrelat(luaL_check_long(L, 2), l); | |
| 39 | − long end = posrelat(luaL_opt_long(L, 3, -1), l); | |
| 47 | + const char *s = luaL_checklstring(L, 1, &l); | |
| 48 | + sint32 start = posrelat(luaL_checklong(L, 2), l); | |
| 49 | + sint32 end = posrelat(luaL_optlong(L, 3, -1), l); | |
| 40 | 50 | if (start < 1) start = 1; |
| 41 | − if (end > (long)l) end = l; | |
| 51 | + if (end > (sint32)l) end = (sint32)l; | |
| 42 | 52 | if (start <= end) |
| 43 | 53 | lua_pushlstring(L, s+start-1, end-start+1); |
| 44 | − else lua_pushstring(L, ""); | |
| 54 | + else lua_pushliteral(L, ""); | |
| 45 | 55 | return 1; |
| 46 | 56 | } |
| 47 | 57 | |
| @@ -50,10 +60,10 @@ static int str_lower (lua_State *L) { · 2 unmodified lines | ||
| 50 | 60 | size_t l; |
| 51 | 61 | size_t i; |
| 52 | 62 | luaL_Buffer b; |
| 53 | − const char *s = luaL_check_lstr(L, 1, &l); | |
| 63 | + const char *s = luaL_checklstring(L, 1, &l); | |
| 54 | 64 | luaL_buffinit(L, &b); |
| 55 | 65 | for (i=0; i<l; i++) |
| 56 | − luaL_putchar(&b, tolower((unsigned char)(s[i]))); | |
| 66 | + luaL_putchar(&b, tolower(uchar(s[i]))); | |
| 57 | 67 | luaL_pushresult(&b); |
| 58 | 68 | return 1; |
| 59 | 69 | } |
| @@ -63,10 +73,10 @@ static int str_upper (lua_State *L) { · 3 unmodified lines | ||
| 63 | 73 | size_t l; |
| 64 | 74 | size_t i; |
| 65 | 75 | luaL_Buffer b; |
| 66 | − const char *s = luaL_check_lstr(L, 1, &l); | |
| 76 | + const char *s = luaL_checklstring(L, 1, &l); | |
| 67 | 77 | luaL_buffinit(L, &b); |
| 68 | 78 | for (i=0; i<l; i++) |
| 69 | − luaL_putchar(&b, toupper((unsigned char)(s[i]))); | |
| 79 | + luaL_putchar(&b, toupper(uchar(s[i]))); | |
| 70 | 80 | luaL_pushresult(&b); |
| 71 | 81 | return 1; |
| 72 | 82 | } |
| @@ -74,8 +84,8 @@ static int str_upper (lua_State *L) { · 1 unmodified line | ||
| 74 | 84 | static int str_rep (lua_State *L) { |
| 75 | 85 | size_t l; |
| 76 | 86 | luaL_Buffer b; |
| 77 | − const char *s = luaL_check_lstr(L, 1, &l); | |
| 78 | − int n = luaL_check_int(L, 2); | |
| 87 | + const char *s = luaL_checklstring(L, 1, &l); | |
| 88 | + int n = luaL_checkint(L, 2); | |
| 79 | 89 | luaL_buffinit(L, &b); |
| 80 | 90 | while (n-- > 0) |
| 81 | 91 | luaL_addlstring(&b, s, l); |
| @@ -86,10 +96,11 @@ static int str_rep (lua_State *L) { · 4 unmodified lines | ||
| 86 | 96 | |
| 87 | 97 | static int str_byte (lua_State *L) { |
| 88 | 98 | size_t l; |
| 89 | − const char *s = luaL_check_lstr(L, 1, &l); | |
| 90 | − long pos = posrelat(luaL_opt_long(L, 2, 1), l); | |
| 91 | − luaL_arg_check(L, 0<pos && (size_t)pos<=l, 2, "out of range"); | |
| 92 | − lua_pushnumber(L, (unsigned char)s[pos-1]); | |
| 99 | + const char *s = luaL_checklstring(L, 1, &l); | |
| 100 | + sint32 pos = posrelat(luaL_optlong(L, 2, 1), l); | |
| 101 | + if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */ | |
| 102 | + return 0; /* no answer */ | |
| 103 | + lua_pushnumber(L, uchar(s[pos-1])); | |
| 93 | 104 | return 1; |
| 94 | 105 | } |
| 95 | 106 | |
| @@ -100,15 +111,33 @@ static int str_char (lua_State *L) { · 4 unmodified lines | ||
| 100 | 111 | luaL_Buffer b; |
| 101 | 112 | luaL_buffinit(L, &b); |
| 102 | 113 | for (i=1; i<=n; i++) { |
| 103 | − int c = luaL_check_int(L, i); | |
| 104 | − luaL_arg_check(L, (unsigned char)c == c, i, "invalid value"); | |
| 105 | − luaL_putchar(&b, (unsigned char)c); | |
| 114 | + int c = luaL_checkint(L, i); | |
| 115 | + luaL_argcheck(L, uchar(c) == c, i, "invalid value"); | |
| 116 | + luaL_putchar(&b, uchar(c)); | |
| 106 | 117 | } |
| 107 | 118 | luaL_pushresult(&b); |
| 108 | 119 | return 1; |
| 109 | 120 | } |
| 110 | 121 | |
| 111 | 122 | |
| 123 | +static int writer (lua_State *L, const void* b, size_t size, void* B) { | |
| 124 | + (void)L; | |
| 125 | + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); | |
| 126 | + return 1; | |
| 127 | +} | |
| 128 | + | |
| 129 | + | |
| 130 | +static int str_dump (lua_State *L) { | |
| 131 | + luaL_Buffer b; | |
| 132 | + luaL_checktype(L, 1, LUA_TFUNCTION); | |
| 133 | + luaL_buffinit(L,&b); | |
| 134 | + if (!lua_dump(L, writer, &b)) | |
| 135 | + luaL_error(L, "unable to dump given function"); | |
| 136 | + luaL_pushresult(&b); | |
| 137 | + return 1; | |
| 138 | +} | |
| 139 | + | |
| 140 | + | |
| 112 | 141 | |
| 113 | 142 | /* |
| 114 | 143 | ** {====================================================== |
| @@ -121,51 +150,61 @@ static int str_char (lua_State *L) { · 6 unmodified lines | ||
| 121 | 150 | #endif |
| 122 | 151 | |
| 123 | 152 | |
| 124 | −struct Capture { | |
| 125 | − const char *src_end; /* end ('\0') of source string */ | |
| 153 | +#define CAP_UNFINISHED (-1) | |
| 154 | +#define CAP_POSITION (-2) | |
| 155 | + | |
| 156 | +typedef struct MatchState { | |
| 157 | + const char *src_init; /* init of source string */ | |
| 158 | + const char *src_end; /* end (`\0') of source string */ | |
| 159 | + lua_State *L; | |
| 126 | 160 | int level; /* total number of captures (finished or unfinished) */ |
| 127 | 161 | struct { |
| 128 | 162 | const char *init; |
| 129 | − long len; /* -1 signals unfinished capture */ | |
| 163 | + sint32 len; | |
| 130 | 164 | } capture[MAX_CAPTURES]; |
| 131 | −}; | |
| 165 | +} MatchState; | |
| 132 | 166 | |
| 133 | 167 | |
| 134 | 168 | #define ESC '%' |
| 135 | 169 | #define SPECIALS "^$*+?.([%-" |
| 136 | 170 | |
| 137 | 171 | |
| 138 | −static int check_capture (lua_State *L, int l, struct Capture *cap) { | |
| 172 | +static int check_capture (MatchState *ms, int l) { | |
| 139 | 173 | l -= '1'; |
| 140 | − if (!(0 <= l && l < cap->level && cap->capture[l].len != -1)) | |
| 141 | − lua_error(L, "invalid capture index"); | |
| 174 | + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) | |
| 175 | + return luaL_error(ms->L, "invalid capture index"); | |
| 142 | 176 | return l; |
| 143 | 177 | } |
| 144 | 178 | |
| 145 | 179 | |
| 146 | −static int capture_to_close (lua_State *L, struct Capture *cap) { | |
| 147 | − int level = cap->level; | |
| 180 | +static int capture_to_close (MatchState *ms) { | |
| 181 | + int level = ms->level; | |
| 148 | 182 | for (level--; level>=0; level--) |
| 149 | − if (cap->capture[level].len == -1) return level; | |
| 150 | − lua_error(L, "invalid pattern capture"); | |
| 151 | − return 0; /* to avoid warnings */ | |
| 183 | + if (ms->capture[level].len == CAP_UNFINISHED) return level; | |
| 184 | + return luaL_error(ms->L, "invalid pattern capture"); | |
| 152 | 185 | } |
| 153 | 186 | |
| 154 | 187 | |
| 155 | −const char *luaI_classend (lua_State *L, const char *p) { | |
| 188 | +static const char *luaI_classend (MatchState *ms, const char *p) { | |
| 156 | 189 | switch (*p++) { |
| 157 | − case ESC: | |
| 158 | − if (*p == '\0') lua_error(L, "malformed pattern (ends with `%')"); | |
| 190 | + case ESC: { | |
| 191 | + if (*p == '\0') | |
| 192 | + luaL_error(ms->L, "malformed pattern (ends with `%')"); | |
| 159 | 193 | return p+1; |
| 160 | − case '[': | |
| 194 | + } | |
| 195 | + case '[': { | |
| 161 | 196 | if (*p == '^') p++; |
| 162 | − do { /* look for a ']' */ | |
| 163 | − if (*p == '\0') lua_error(L, "malformed pattern (missing `]')"); | |
| 164 | − if (*(p++) == ESC && *p != '\0') p++; /* skip escapes (e.g. '%]') */ | |
| 197 | + do { /* look for a `]' */ | |
| 198 | + if (*p == '\0') | |
| 199 | + luaL_error(ms->L, "malformed pattern (missing `]')"); | |
| 200 | + if (*(p++) == ESC && *p != '\0') | |
| 201 | + p++; /* skip escapes (e.g. `%]') */ | |
| 165 | 202 | } while (*p != ']'); |
| 166 | 203 | return p+1; |
| 167 | − default: | |
| 204 | + } | |
| 205 | + default: { | |
| 168 | 206 | return p; |
| 207 | + } | |
| 169 | 208 | } |
| 170 | 209 | } |
| 171 | 210 | |
| @@ -182,66 +221,59 @@ static int match_class (int c, int cl) { · 10 unmodified lines | ||
| 182 | 221 | case 'u' : res = isupper(c); break; |
| 183 | 222 | case 'w' : res = isalnum(c); break; |
| 184 | 223 | case 'x' : res = isxdigit(c); break; |
| 185 | − case 'z' : res = (c == '\0'); break; | |
| 224 | + case 'z' : res = (c == 0); break; | |
| 186 | 225 | default: return (cl == c); |
| 187 | 226 | } |
| 188 | 227 | return (islower(cl) ? res : !res); |
| 189 | 228 | } |
| 190 | 229 | |
| 191 | 230 | |
| 192 | − | |
| 193 | −static int matchbracketclass (int c, const char *p, const char *endclass) { | |
| 231 | +static int matchbracketclass (int c, const char *p, const char *ec) { | |
| 194 | 232 | int sig = 1; |
| 195 | 233 | if (*(p+1) == '^') { |
| 196 | 234 | sig = 0; |
| 197 | − p++; /* skip the '^' */ | |
| 235 | + p++; /* skip the `^' */ | |
| 198 | 236 | } |
| 199 | − while (++p < endclass) { | |
| 237 | + while (++p < ec) { | |
| 200 | 238 | if (*p == ESC) { |
| 201 | 239 | p++; |
| 202 | − if (match_class(c, (unsigned char)*p)) | |
| 240 | + if (match_class(c, *p)) | |
| 203 | 241 | return sig; |
| 204 | 242 | } |
| 205 | − else if ((*(p+1) == '-') && (p+2 < endclass)) { | |
| 243 | + else if ((*(p+1) == '-') && (p+2 < ec)) { | |
| 206 | 244 | p+=2; |
| 207 | − if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p) | |
| 245 | + if (uchar(*(p-2)) <= c && c <= uchar(*p)) | |
| 208 | 246 | return sig; |
| 209 | 247 | } |
| 210 | − else if ((int)(unsigned char)*p == c) return sig; | |
| 248 | + else if (uchar(*p) == c) return sig; | |
| 211 | 249 | } |
| 212 | 250 | return !sig; |
| 213 | 251 | } |
| 214 | 252 | |
| 215 | 253 | |
| 216 | − | |
| 217 | −int luaI_singlematch (int c, const char *p, const char *ep) { | |
| 254 | +static int luaI_singlematch (int c, const char *p, const char *ep) { | |
| 218 | 255 | switch (*p) { |
| 219 | − case '.': /* matches any char */ | |
| 220 | − return 1; | |
| 221 | − case ESC: | |
| 222 | − return match_class(c, (unsigned char)*(p+1)); | |
| 223 | − case '[': | |
| 224 | − return matchbracketclass(c, p, ep-1); | |
| 225 | − default: | |
| 226 | − return ((unsigned char)*p == c); | |
| 256 | + case '.': return 1; /* matches any char */ | |
| 257 | + case ESC: return match_class(c, *(p+1)); | |
| 258 | + case '[': return matchbracketclass(c, p, ep-1); | |
| 259 | + default: return (uchar(*p) == c); | |
| 227 | 260 | } |
| 228 | 261 | } |
| 229 | 262 | |
| 230 | 263 | |
| 231 | −static const char *match (lua_State *L, const char *s, const char *p, | |
| 232 | − struct Capture *cap); | |
| 264 | +static const char *match (MatchState *ms, const char *s, const char *p); | |
| 233 | 265 | |
| 234 | 266 | |
| 235 | −static const char *matchbalance (lua_State *L, const char *s, const char *p, | |
| 236 | − struct Capture *cap) { | |
| 267 | +static const char *matchbalance (MatchState *ms, const char *s, | |
| 268 | + const char *p) { | |
| 237 | 269 | if (*p == 0 || *(p+1) == 0) |
| 238 | − lua_error(L, "unbalanced pattern"); | |
| 270 | + luaL_error(ms->L, "unbalanced pattern"); | |
| 239 | 271 | if (*s != *p) return NULL; |
| 240 | 272 | else { |
| 241 | 273 | int b = *p; |
| 242 | 274 | int e = *(p+1); |
| 243 | 275 | int cont = 1; |
| 244 | − while (++s < cap->src_end) { | |
| 276 | + while (++s < ms->src_end) { | |
| 245 | 277 | if (*s == e) { |
| 246 | 278 | if (--cont == 0) return s+1; |
| 247 | 279 | } |
| @@ -252,14 +284,14 @@ static const char *matchbalance (lua_State *L, const char *s, const char *p, · 4 unmodified lines | ||
| 252 | 284 | } |
| 253 | 285 | |
| 254 | 286 | |
| 255 | −static const char *max_expand (lua_State *L, const char *s, const char *p, | |
| 256 | − const char *ep, struct Capture *cap) { | |
| 257 | − long i = 0; /* counts maximum expand for item */ | |
| 258 | − while ((s+i)<cap->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep)) | |
| 287 | +static const char *max_expand (MatchState *ms, const char *s, | |
| 288 | + const char *p, const char *ep) { | |
| 289 | + sint32 i = 0; /* counts maximum expand for item */ | |
| 290 | + while ((s+i)<ms->src_end && luaI_singlematch(uchar(*(s+i)), p, ep)) | |
| 259 | 291 | i++; |
| 260 | 292 | /* keeps trying to match with the maximum repetitions */ |
| 261 | 293 | while (i>=0) { |
| 262 | − const char *res = match(L, (s+i), ep+1, cap); | |
| 294 | + const char *res = match(ms, (s+i), ep+1); | |
| 263 | 295 | if (res) return res; |
| 264 | 296 | i--; /* else didn't match; reduce 1 repetition to try again */ |
| 265 | 297 | } |
| @@ -267,100 +299,126 @@ static const char *max_expand (lua_State *L, const char *s, const char *p, · 1 unmodified line | ||
| 267 | 299 | } |
| 268 | 300 | |
| 269 | 301 | |
| 270 | −static const char *min_expand (lua_State *L, const char *s, const char *p, | |
| 271 | − const char *ep, struct Capture *cap) { | |
| 302 | +static const char *min_expand (MatchState *ms, const char *s, | |
| 303 | + const char *p, const char *ep) { | |
| 272 | 304 | for (;;) { |
| 273 | − const char *res = match(L, s, ep+1, cap); | |
| 305 | + const char *res = match(ms, s, ep+1); | |
| 274 | 306 | if (res != NULL) |
| 275 | 307 | return res; |
| 276 | − else if (s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep)) | |
| 308 | + else if (s<ms->src_end && luaI_singlematch(uchar(*s), p, ep)) | |
| 277 | 309 | s++; /* try with one more repetition */ |
| 278 | 310 | else return NULL; |
| 279 | 311 | } |
| 280 | 312 | } |
| 281 | 313 | |
| 282 | 314 | |
| 283 | −static const char *start_capture (lua_State *L, const char *s, const char *p, | |
| 284 | − struct Capture *cap) { | |
| 315 | +static const char *start_capture (MatchState *ms, const char *s, | |
| 316 | + const char *p, int what) { | |
| 285 | 317 | const char *res; |
| 286 | − int level = cap->level; | |
| 287 | − if (level >= MAX_CAPTURES) lua_error(L, "too many captures"); | |
| 288 | − cap->capture[level].init = s; | |
| 289 | − cap->capture[level].len = -1; | |
| 290 | − cap->level = level+1; | |
| 291 | − if ((res=match(L, s, p+1, cap)) == NULL) /* match failed? */ | |
| 292 | − cap->level--; /* undo capture */ | |
| 318 | + int level = ms->level; | |
| 319 | + if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures"); | |
| 320 | + ms->capture[level].init = s; | |
| 321 | + ms->capture[level].len = what; | |
| 322 | + ms->level = level+1; | |
| 323 | + if ((res=match(ms, s, p)) == NULL) /* match failed? */ | |
| 324 | + ms->level--; /* undo capture */ | |
| 293 | 325 | return res; |
| 294 | 326 | } |
| 295 | 327 | |
| 296 | 328 | |
| 297 | −static const char *end_capture (lua_State *L, const char *s, const char *p, | |
| 298 | − struct Capture *cap) { | |
| 299 | − int l = capture_to_close(L, cap); | |
| 329 | +static const char *end_capture (MatchState *ms, const char *s, | |
| 330 | + const char *p) { | |
| 331 | + int l = capture_to_close(ms); | |
| 300 | 332 | const char *res; |
| 301 | − cap->capture[l].len = s - cap->capture[l].init; /* close capture */ | |
| 302 | − if ((res = match(L, s, p+1, cap)) == NULL) /* match failed? */ | |
| 303 | − cap->capture[l].len = -1; /* undo capture */ | |
| 333 | + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ | |
| 334 | + if ((res = match(ms, s, p)) == NULL) /* match failed? */ | |
| 335 | + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ | |
| 304 | 336 | return res; |
| 305 | 337 | } |
| 306 | 338 | |
| 307 | 339 | |
| 308 | −static const char *match_capture (lua_State *L, const char *s, int level, | |
| 309 | − struct Capture *cap) { | |
| 310 | − int l = check_capture(L, level, cap); | |
| 311 | − size_t len = cap->capture[l].len; | |
| 312 | − if ((size_t)(cap->src_end-s) >= len && | |
| 313 | − memcmp(cap->capture[l].init, s, len) == 0) | |
| 340 | +static const char *match_capture (MatchState *ms, const char *s, int l) { | |
| 341 | + size_t len; | |
| 342 | + l = check_capture(ms, l); | |
| 343 | + len = ms->capture[l].len; | |
| 344 | + if ((size_t)(ms->src_end-s) >= len && | |
| 345 | + memcmp(ms->capture[l].init, s, len) == 0) | |
| 314 | 346 | return s+len; |
| 315 | 347 | else return NULL; |
| 316 | 348 | } |
| 317 | 349 | |
| 318 | 350 | |
| 319 | −static const char *match (lua_State *L, const char *s, const char *p, | |
| 320 | − struct Capture *cap) { | |
| 351 | +static const char *match (MatchState *ms, const char *s, const char *p) { | |
| 321 | 352 | init: /* using goto's to optimize tail recursion */ |
| 322 | 353 | switch (*p) { |
| 323 | − case '(': /* start capture */ | |
| 324 | − return start_capture(L, s, p, cap); | |
| 325 | − case ')': /* end capture */ | |
| 326 | − return end_capture(L, s, p, cap); | |
| 327 | − case ESC: /* may be %[0-9] or %b */ | |
| 328 | − if (isdigit((unsigned char)(*(p+1)))) { /* capture? */ | |
| 329 | − s = match_capture(L, s, *(p+1), cap); | |
| 330 | − if (s == NULL) return NULL; | |
| 331 | − p+=2; goto init; /* else return match(L, s, p+2, cap) */ | |
| 332 | − } | |
| 333 | − else if (*(p+1) == 'b') { /* balanced string? */ | |
| 334 | − s = matchbalance(L, s, p+2, cap); | |
| 335 | − if (s == NULL) return NULL; | |
| 336 | − p+=4; goto init; /* else return match(L, s, p+4, cap); */ | |
| 354 | + case '(': { /* start capture */ | |
| 355 | + if (*(p+1) == ')') /* position capture? */ | |
| 356 | + return start_capture(ms, s, p+2, CAP_POSITION); | |
| 357 | + else | |
| 358 | + return start_capture(ms, s, p+1, CAP_UNFINISHED); | |
| 359 | + } | |
| 360 | + case ')': { /* end capture */ | |
| 361 | + return end_capture(ms, s, p+1); | |
| 362 | + } | |
| 363 | + case ESC: { | |
| 364 | + switch (*(p+1)) { | |
| 365 | + case 'b': { /* balanced string? */ | |
| 366 | + s = matchbalance(ms, s, p+2); | |
| 367 | + if (s == NULL) return NULL; | |
| 368 | + p+=4; goto init; /* else return match(ms, s, p+4); */ | |
| 369 | + } | |
| 370 | + case 'f': { /* frontier? */ | |
| 371 | + const char *ep; char previous; | |
| 372 | + p += 2; | |
| 373 | + if (*p != '[') | |
| 374 | + luaL_error(ms->L, "missing `[' after `%%f' in pattern"); | |
| 375 | + ep = luaI_classend(ms, p); /* points to what is next */ | |
| 376 | + previous = (s == ms->src_init) ? '\0' : *(s-1); | |
| 377 | + if (matchbracketclass(uchar(previous), p, ep-1) || | |
| 378 | + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; | |
| 379 | + p=ep; goto init; /* else return match(ms, s, ep); */ | |
| 380 | + } | |
| 381 | + default: { | |
| 382 | + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ | |
| 383 | + s = match_capture(ms, s, *(p+1)); | |
| 384 | + if (s == NULL) return NULL; | |
| 385 | + p+=2; goto init; /* else return match(ms, s, p+2) */ | |
| 386 | + } | |
| 387 | + goto dflt; /* case default */ | |
| 388 | + } | |
| 337 | 389 | } |
| 338 | − else goto dflt; /* case default */ | |
| 339 | − case '\0': /* end of pattern */ | |
| 390 | + } | |
| 391 | + case '\0': { /* end of pattern */ | |
| 340 | 392 | return s; /* match succeeded */ |
| 341 | − case '$': | |
| 342 | − if (*(p+1) == '\0') /* is the '$' the last char in pattern? */ | |
| 343 | − return (s == cap->src_end) ? s : NULL; /* check end of string */ | |
| 393 | + } | |
| 394 | + case '$': { | |
| 395 | + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ | |
| 396 | + return (s == ms->src_end) ? s : NULL; /* check end of string */ | |
| 344 | 397 | else goto dflt; |
| 398 | + } | |
| 345 | 399 | default: dflt: { /* it is a pattern item */ |
| 346 | − const char *ep = luaI_classend(L, p); /* points to what is next */ | |
| 347 | − int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep); | |
| 400 | + const char *ep = luaI_classend(ms, p); /* points to what is next */ | |
| 401 | + int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep); | |
| 348 | 402 | switch (*ep) { |
| 349 | 403 | case '?': { /* optional */ |
| 350 | 404 | const char *res; |
| 351 | − if (m && ((res=match(L, s+1, ep+1, cap)) != NULL)) | |
| 405 | + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) | |
| 352 | 406 | return res; |
| 353 | − p=ep+1; goto init; /* else return match(L, s, ep+1, cap); */ | |
| 407 | + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ | |
| 408 | + } | |
| 409 | + case '*': { /* 0 or more repetitions */ | |
| 410 | + return max_expand(ms, s, p, ep); | |
| 411 | + } | |
| 412 | + case '+': { /* 1 or more repetitions */ | |
| 413 | + return (m ? max_expand(ms, s+1, p, ep) : NULL); | |
| 414 | + } | |
| 415 | + case '-': { /* 0 or more repetitions (minimum) */ | |
| 416 | + return min_expand(ms, s, p, ep); | |
| 354 | 417 | } |
| 355 | − case '*': /* 0 or more repetitions */ | |
| 356 | − return max_expand(L, s, p, ep, cap); | |
| 357 | − case '+': /* 1 or more repetitions */ | |
| 358 | − return (m ? max_expand(L, s+1, p, ep, cap) : NULL); | |
| 359 | − case '-': /* 0 or more repetitions (minimum) */ | |
| 360 | − return min_expand(L, s, p, ep, cap); | |
| 361 | − default: | |
| 418 | + default: { | |
| 362 | 419 | if (!m) return NULL; |
| 363 | − s++; p=ep; goto init; /* else return match(L, s+1, ep, cap); */ | |
| 420 | + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ | |
| 421 | + } | |
| 364 | 422 | } |
| 365 | 423 | } |
| 366 | 424 | } |
| @@ -369,7 +427,7 @@ static const char *match (lua_State *L, const char *s, const char *p, · 2 unmodified lines | ||
| 369 | 427 | |
| 370 | 428 | |
| 371 | 429 | static const char *lmemfind (const char *s1, size_t l1, |
| 372 | − const char *s2, size_t l2) { | |
| 430 | + const char *s2, size_t l2) { | |
| 373 | 431 | if (l2 == 0) return s1; /* empty strings are everywhere */ |
| 374 | 432 | else if (l2 > l1) return NULL; /* avoids a negative `l1' */ |
| 375 | 433 | else { |
| @@ -390,54 +448,109 @@ static const char *lmemfind (const char *s1, size_t l1, · 14 unmodified lines | ||
| 390 | 448 | } |
| 391 | 449 | |
| 392 | 450 | |
| 393 | −static int push_captures (lua_State *L, struct Capture *cap) { | |
| 451 | +static void push_onecapture (MatchState *ms, int i) { | |
| 452 | + int l = ms->capture[i].len; | |
| 453 | + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); | |
| 454 | + if (l == CAP_POSITION) | |
| 455 | + lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1)); | |
| 456 | + else | |
| 457 | + lua_pushlstring(ms->L, ms->capture[i].init, l); | |
| 458 | +} | |
| 459 | + | |
| 460 | + | |
| 461 | +static int push_captures (MatchState *ms, const char *s, const char *e) { | |
| 394 | 462 | int i; |
| 395 | − luaL_checkstack(L, cap->level, "too many captures"); | |
| 396 | − for (i=0; i<cap->level; i++) { | |
| 397 | − int l = cap->capture[i].len; | |
| 398 | − if (l == -1) lua_error(L, "unfinished capture"); | |
| 399 | − lua_pushlstring(L, cap->capture[i].init, l); | |
| 463 | + luaL_checkstack(ms->L, ms->level, "too many captures"); | |
| 464 | + if (ms->level == 0 && s) { /* no explicit captures? */ | |
| 465 | + lua_pushlstring(ms->L, s, e-s); /* return whole match */ | |
| 466 | + return 1; | |
| 467 | + } | |
| 468 | + else { /* return all captures */ | |
| 469 | + for (i=0; i<ms->level; i++) | |
| 470 | + push_onecapture(ms, i); | |
| 471 | + return ms->level; /* number of strings pushed */ | |
| 400 | 472 | } |
| 401 | − return cap->level; /* number of strings pushed */ | |
| 402 | 473 | } |
| 403 | 474 | |
| 404 | 475 | |
| 405 | 476 | static int str_find (lua_State *L) { |
| 406 | 477 | size_t l1, l2; |
| 407 | − const char *s = luaL_check_lstr(L, 1, &l1); | |
| 408 | − const char *p = luaL_check_lstr(L, 2, &l2); | |
| 409 | − long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1; | |
| 410 | − struct Capture cap; | |
| 411 | − luaL_arg_check(L, 0 <= init && (size_t)init <= l1, 3, "out of range"); | |
| 412 | − if (lua_gettop(L) > 3 || /* extra argument? */ | |
| 478 | + const char *s = luaL_checklstring(L, 1, &l1); | |
| 479 | + const char *p = luaL_checklstring(L, 2, &l2); | |
| 480 | + sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; | |
| 481 | + if (init < 0) init = 0; | |
| 482 | + else if ((size_t)(init) > l1) init = (sint32)l1; | |
| 483 | + if (lua_toboolean(L, 4) || /* explicit request? */ | |
| 413 | 484 | strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ |
| 485 | + /* do a plain search */ | |
| 414 | 486 | const char *s2 = lmemfind(s+init, l1-init, p, l2); |
| 415 | 487 | if (s2) { |
| 416 | − lua_pushnumber(L, s2-s+1); | |
| 417 | − lua_pushnumber(L, s2-s+l2); | |
| 488 | + lua_pushnumber(L, (lua_Number)(s2-s+1)); | |
| 489 | + lua_pushnumber(L, (lua_Number)(s2-s+l2)); | |
| 418 | 490 | return 2; |
| 419 | 491 | } |
| 420 | 492 | } |
| 421 | 493 | else { |
| 494 | + MatchState ms; | |
| 422 | 495 | int anchor = (*p == '^') ? (p++, 1) : 0; |
| 423 | 496 | const char *s1=s+init; |
| 424 | − cap.src_end = s+l1; | |
| 497 | + ms.L = L; | |
| 498 | + ms.src_init = s; | |
| 499 | + ms.src_end = s+l1; | |
| 425 | 500 | do { |
| 426 | 501 | const char *res; |
| 427 | − cap.level = 0; | |
| 428 | − if ((res=match(L, s1, p, &cap)) != NULL) { | |
| 429 | − lua_pushnumber(L, s1-s+1); /* start */ | |
| 430 | − lua_pushnumber(L, res-s); /* end */ | |
| 431 | − return push_captures(L, &cap) + 2; | |
| 502 | + ms.level = 0; | |
| 503 | + if ((res=match(&ms, s1, p)) != NULL) { | |
| 504 | + lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */ | |
| 505 | + lua_pushnumber(L, (lua_Number)(res-s)); /* end */ | |
| 506 | + return push_captures(&ms, NULL, 0) + 2; | |
| 432 | 507 | } |
| 433 | − } while (s1++<cap.src_end && !anchor); | |
| 508 | + } while (s1++<ms.src_end && !anchor); | |
| 434 | 509 | } |
| 435 | 510 | lua_pushnil(L); /* not found */ |
| 436 | 511 | return 1; |
| 437 | 512 | } |
| 438 | 513 | |
| 439 | 514 | |
| 440 | −static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) { | |
| 515 | +static int gfind_aux (lua_State *L) { | |
| 516 | + MatchState ms; | |
| 517 | + const char *s = lua_tostring(L, lua_upvalueindex(1)); | |
| 518 | + size_t ls = lua_strlen(L, lua_upvalueindex(1)); | |
| 519 | + const char *p = lua_tostring(L, lua_upvalueindex(2)); | |
| 520 | + const char *src; | |
| 521 | + ms.L = L; | |
| 522 | + ms.src_init = s; | |
| 523 | + ms.src_end = s+ls; | |
| 524 | + for (src = s + (size_t)lua_tonumber(L, lua_upvalueindex(3)); | |
| 525 | + src <= ms.src_end; | |
| 526 | + src++) { | |
| 527 | + const char *e; | |
| 528 | + ms.level = 0; | |
| 529 | + if ((e = match(&ms, src, p)) != NULL) { | |
| 530 | + int newstart = e-s; | |
| 531 | + if (e == src) newstart++; /* empty match? go at least one position */ | |
| 532 | + lua_pushnumber(L, (lua_Number)newstart); | |
| 533 | + lua_replace(L, lua_upvalueindex(3)); | |
| 534 | + return push_captures(&ms, src, e); | |
| 535 | + } | |
| 536 | + } | |
| 537 | + return 0; /* not found */ | |
| 538 | +} | |
| 539 | + | |
| 540 | + | |
| 541 | +static int gfind (lua_State *L) { | |
| 542 | + luaL_checkstring(L, 1); | |
| 543 | + luaL_checkstring(L, 2); | |
| 544 | + lua_settop(L, 2); | |
| 545 | + lua_pushnumber(L, 0); | |
| 546 | + lua_pushcclosure(L, gfind_aux, 3); | |
| 547 | + return 1; | |
| 548 | +} | |
| 549 | + | |
| 550 | + | |
| 551 | +static void add_s (MatchState *ms, luaL_Buffer *b, | |
| 552 | + const char *s, const char *e) { | |
| 553 | + lua_State *L = ms->L; | |
| 441 | 554 | if (lua_isstring(L, 3)) { |
| 442 | 555 | const char *news = lua_tostring(L, 3); |
| 443 | 556 | size_t l = lua_strlen(L, 3); |
| @@ -447,11 +560,12 @@ static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) { · 3 unmodified lines | ||
| 447 | 560 | luaL_putchar(b, news[i]); |
| 448 | 561 | else { |
| 449 | 562 | i++; /* skip ESC */ |
| 450 | − if (!isdigit((unsigned char)news[i])) | |
| 563 | + if (!isdigit(uchar(news[i]))) | |
| 451 | 564 | luaL_putchar(b, news[i]); |
| 452 | 565 | else { |
| 453 | − int level = check_capture(L, news[i], cap); | |
| 454 | − luaL_addlstring(b, cap->capture[level].init, cap->capture[level].len); | |
| 566 | + int level = check_capture(ms, news[i]); | |
| 567 | + push_onecapture(ms, level); | |
| 568 | + luaL_addvalue(b); /* add capture to accumulated result */ | |
| 455 | 569 | } |
| 456 | 570 | } |
| 457 | 571 | } |
| @@ -459,8 +573,8 @@ static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) { · 1 unmodified line | ||
| 459 | 573 | else { /* is a function */ |
| 460 | 574 | int n; |
| 461 | 575 | lua_pushvalue(L, 3); |
| 462 | − n = push_captures(L, cap); | |
| 463 | − lua_rawcall(L, n, 1); | |
| 576 | + n = push_captures(ms, s, e); | |
| 577 | + lua_call(L, n, 1); | |
| 464 | 578 | if (lua_isstring(L, -1)) |
| 465 | 579 | luaL_addvalue(b); /* add return to accumulated result */ |
| 466 | 580 | else |
| @@ -471,124 +585,155 @@ static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) { · 4 unmodified lines | ||
| 471 | 585 | |
| 472 | 586 | static int str_gsub (lua_State *L) { |
| 473 | 587 | size_t srcl; |
| 474 | − const char *src = luaL_check_lstr(L, 1, &srcl); | |
| 475 | − const char *p = luaL_check_string(L, 2); | |
| 476 | − int max_s = luaL_opt_int(L, 4, srcl+1); | |
| 588 | + const char *src = luaL_checklstring(L, 1, &srcl); | |
| 589 | + const char *p = luaL_checkstring(L, 2); | |
| 590 | + int max_s = luaL_optint(L, 4, srcl+1); | |
| 477 | 591 | int anchor = (*p == '^') ? (p++, 1) : 0; |
| 478 | 592 | int n = 0; |
| 479 | − struct Capture cap; | |
| 593 | + MatchState ms; | |
| 480 | 594 | luaL_Buffer b; |
| 481 | − luaL_arg_check(L, | |
| 595 | + luaL_argcheck(L, | |
| 482 | 596 | lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), |
| 483 | 597 | 3, "string or function expected"); |
| 484 | 598 | luaL_buffinit(L, &b); |
| 485 | − cap.src_end = src+srcl; | |
| 599 | + ms.L = L; | |
| 600 | + ms.src_init = src; | |
| 601 | + ms.src_end = src+srcl; | |
| 486 | 602 | while (n < max_s) { |
| 487 | 603 | const char *e; |
| 488 | − cap.level = 0; | |
| 489 | − e = match(L, src, p, &cap); | |
| 604 | + ms.level = 0; | |
| 605 | + e = match(&ms, src, p); | |
| 490 | 606 | if (e) { |
| 491 | 607 | n++; |
| 492 | − add_s(L, &b, &cap); | |
| 608 | + add_s(&ms, &b, src, e); | |
| 493 | 609 | } |
| 494 | 610 | if (e && e>src) /* non empty match? */ |
| 495 | 611 | src = e; /* skip it */ |
| 496 | − else if (src < cap.src_end) | |
| 612 | + else if (src < ms.src_end) | |
| 497 | 613 | luaL_putchar(&b, *src++); |
| 498 | 614 | else break; |
| 499 | 615 | if (anchor) break; |
| 500 | 616 | } |
| 501 | − luaL_addlstring(&b, src, cap.src_end-src); | |
| 617 | + luaL_addlstring(&b, src, ms.src_end-src); | |
| 502 | 618 | luaL_pushresult(&b); |
| 503 | − lua_pushnumber(L, n); /* number of substitutions */ | |
| 619 | + lua_pushnumber(L, (lua_Number)n); /* number of substitutions */ | |
| 504 | 620 | return 2; |
| 505 | 621 | } |
| 506 | 622 | |
| 507 | 623 | /* }====================================================== */ |
| 508 | 624 | |
| 509 | 625 | |
| 626 | +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ | |
| 627 | +#define MAX_ITEM 512 | |
| 628 | +/* maximum size of each format specification (such as '%-099.99d') */ | |
| 629 | +#define MAX_FORMAT 20 | |
| 630 | + | |
| 631 | + | |
| 510 | 632 | static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { |
| 511 | 633 | size_t l; |
| 512 | − const char *s = luaL_check_lstr(L, arg, &l); | |
| 634 | + const char *s = luaL_checklstring(L, arg, &l); | |
| 513 | 635 | luaL_putchar(b, '"'); |
| 514 | 636 | while (l--) { |
| 515 | 637 | switch (*s) { |
| 516 | − case '"': case '\\': case '\n': | |
| 638 | + case '"': case '\\': case '\n': { | |
| 517 | 639 | luaL_putchar(b, '\\'); |
| 518 | 640 | luaL_putchar(b, *s); |
| 519 | 641 | break; |
| 520 | − case '\0': luaL_addlstring(b, "\\000", 4); break; | |
| 521 | − default: luaL_putchar(b, *s); | |
| 642 | + } | |
| 643 | + case '\0': { | |
| 644 | + luaL_addlstring(b, "\\000", 4); | |
| 645 | + break; | |
| 646 | + } | |
| 647 | + default: { | |
| 648 | + luaL_putchar(b, *s); | |
| 649 | + break; | |
| 650 | + } | |
| 522 | 651 | } |
| 523 | 652 | s++; |
| 524 | 653 | } |
| 525 | 654 | luaL_putchar(b, '"'); |
| 526 | 655 | } |
| 527 | 656 | |
| 528 | −/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ | |
| 529 | −#define MAX_ITEM 512 | |
| 530 | −/* maximum size of each format specification (such as '%-099.99d') */ | |
| 531 | −#define MAX_FORMAT 20 | |
| 657 | + | |
| 658 | +static const char *scanformat (lua_State *L, const char *strfrmt, | |
| 659 | + char *form, int *hasprecision) { | |
| 660 | + const char *p = strfrmt; | |
| 661 | + while (strchr("-+ #0", *p)) p++; /* skip flags */ | |
| 662 | + if (isdigit(uchar(*p))) p++; /* skip width */ | |
| 663 | + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ | |
| 664 | + if (*p == '.') { | |
| 665 | + p++; | |
| 666 | + *hasprecision = 1; | |
| 667 | + if (isdigit(uchar(*p))) p++; /* skip precision */ | |
| 668 | + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ | |
| 669 | + } | |
| 670 | + if (isdigit(uchar(*p))) | |
| 671 | + luaL_error(L, "invalid format (width or precision too long)"); | |
| 672 | + if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ | |
| 673 | + luaL_error(L, "invalid format (too long)"); | |
| 674 | + form[0] = '%'; | |
| 675 | + strncpy(form+1, strfrmt, p-strfrmt+1); | |
| 676 | + form[p-strfrmt+2] = 0; | |
| 677 | + return p; | |
| 678 | +} | |
| 679 | + | |
| 532 | 680 | |
| 533 | 681 | static int str_format (lua_State *L) { |
| 534 | 682 | int arg = 1; |
| 535 | − const char *strfrmt = luaL_check_string(L, arg); | |
| 683 | + size_t sfl; | |
| 684 | + const char *strfrmt = luaL_checklstring(L, arg, &sfl); | |
| 685 | + const char *strfrmt_end = strfrmt+sfl; | |
| 536 | 686 | luaL_Buffer b; |
| 537 | 687 | luaL_buffinit(L, &b); |
| 538 | − while (*strfrmt) { | |
| 688 | + while (strfrmt < strfrmt_end) { | |
| 539 | 689 | if (*strfrmt != '%') |
| 540 | 690 | luaL_putchar(&b, *strfrmt++); |
| 541 | 691 | else if (*++strfrmt == '%') |
| 542 | 692 | luaL_putchar(&b, *strfrmt++); /* %% */ |
| 543 | 693 | else { /* format item */ |
| 544 | − struct Capture cap; | |
| 545 | − char form[MAX_FORMAT]; /* to store the format ('%...') */ | |
| 694 | + char form[MAX_FORMAT]; /* to store the format (`%...') */ | |
| 546 | 695 | char buff[MAX_ITEM]; /* to store the formatted item */ |
| 547 | − const char *initf = strfrmt; | |
| 548 | − form[0] = '%'; | |
| 549 | − if (isdigit((unsigned char)*initf) && *(initf+1) == '$') { | |
| 550 | − arg = *initf - '0'; | |
| 551 | − initf += 2; /* skip the 'n$' */ | |
| 552 | − } | |
| 696 | + int hasprecision = 0; | |
| 697 | + if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$') | |
| 698 | + return luaL_error(L, "obsolete option (d$) to `format'"); | |
| 553 | 699 | arg++; |
| 554 | − cap.src_end = strfrmt+strlen(strfrmt)+1; | |
| 555 | − cap.level = 0; | |
| 556 | − strfrmt = match(L, initf, "[-+ #0]*(%d*)%.?(%d*)", &cap); | |
| 557 | − if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */ | |
| 558 | − strfrmt-initf > MAX_FORMAT-2) | |
| 559 | − lua_error(L, "invalid format (width or precision too long)"); | |
| 560 | − strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ | |
| 561 | − form[strfrmt-initf+2] = 0; | |
| 700 | + strfrmt = scanformat(L, strfrmt, form, &hasprecision); | |
| 562 | 701 | switch (*strfrmt++) { |
| 563 | − case 'c': case 'd': case 'i': | |
| 564 | − sprintf(buff, form, luaL_check_int(L, arg)); | |
| 702 | + case 'c': case 'd': case 'i': { | |
| 703 | + sprintf(buff, form, luaL_checkint(L, arg)); | |
| 565 | 704 | break; |
| 566 | − case 'o': case 'u': case 'x': case 'X': | |
| 567 | − sprintf(buff, form, (unsigned int)luaL_check_number(L, arg)); | |
| 705 | + } | |
| 706 | + case 'o': case 'u': case 'x': case 'X': { | |
| 707 | + sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); | |
| 568 | 708 | break; |
| 569 | − case 'e': case 'E': case 'f': case 'g': case 'G': | |
| 570 | − sprintf(buff, form, luaL_check_number(L, arg)); | |
| 709 | + } | |
| 710 | + case 'e': case 'E': case 'f': | |
| 711 | + case 'g': case 'G': { | |
| 712 | + sprintf(buff, form, luaL_checknumber(L, arg)); | |
| 571 | 713 | break; |
| 572 | − case 'q': | |
| 714 | + } | |
| 715 | + case 'q': { | |
| 573 | 716 | luaI_addquoted(L, &b, arg); |
| 574 | − continue; /* skip the "addsize" at the end */ | |
| 717 | + continue; /* skip the `addsize' at the end */ | |
| 718 | + } | |
| 575 | 719 | case 's': { |
| 576 | 720 | size_t l; |
| 577 | − const char *s = luaL_check_lstr(L, arg, &l); | |
| 578 | − if (cap.capture[1].len == 0 && l >= 100) { | |
| 721 | + const char *s = luaL_checklstring(L, arg, &l); | |
| 722 | + if (!hasprecision && l >= 100) { | |
| 579 | 723 | /* no precision and string is too long to be formatted; |
| 580 | 724 | keep original string */ |
| 581 | 725 | lua_pushvalue(L, arg); |
| 582 | 726 | luaL_addvalue(&b); |
| 583 | − continue; /* skip the "addsize" at the end */ | |
| 727 | + continue; /* skip the `addsize' at the end */ | |
| 584 | 728 | } |
| 585 | 729 | else { |
| 586 | 730 | sprintf(buff, form, s); |
| 587 | 731 | break; |
| 588 | 732 | } |
| 589 | 733 | } |
| 590 | − default: /* also treat cases 'pnLlh' */ | |
| 591 | − lua_error(L, "invalid option in `format'"); | |
| 734 | + default: { /* also treat cases `pnLlh' */ | |
| 735 | + return luaL_error(L, "invalid option to `format'"); | |
| 736 | + } | |
| 592 | 737 | } |
| 593 | 738 | luaL_addlstring(&b, buff, strlen(buff)); |
| 594 | 739 | } |
| @@ -598,24 +743,28 @@ static int str_format (lua_State *L) { · 3 unmodified lines | ||
| 598 | 743 | } |
| 599 | 744 | |
| 600 | 745 | |
| 601 | −static const struct luaL_reg strlib[] = { | |
| 602 | −{"strlen", str_len}, | |
| 603 | −{"strsub", str_sub}, | |
| 604 | −{"strlower", str_lower}, | |
| 605 | −{"strupper", str_upper}, | |
| 606 | −{"strchar", str_char}, | |
| 607 | −{"strrep", str_rep}, | |
| 608 | −{"ascii", str_byte}, /* for compatibility with 3.0 and earlier */ | |
| 609 | −{"strbyte", str_byte}, | |
| 610 | −{"format", str_format}, | |
| 611 | −{"strfind", str_find}, | |
| 612 | −{"gsub", str_gsub} | |
| 746 | +static const luaL_reg strlib[] = { | |
| 747 | + {"len", str_len}, | |
| 748 | + {"sub", str_sub}, | |
| 749 | + {"lower", str_lower}, | |
| 750 | + {"upper", str_upper}, | |
| 751 | + {"char", str_char}, | |
| 752 | + {"rep", str_rep}, | |
| 753 | + {"byte", str_byte}, | |
| 754 | + {"format", str_format}, | |
| 755 | + {"dump", str_dump}, | |
| 756 | + {"find", str_find}, | |
| 757 | + {"gfind", gfind}, | |
| 758 | + {"gsub", str_gsub}, | |
| 759 | + {NULL, NULL} | |
| 613 | 760 | }; |
| 614 | 761 | |
| 615 | 762 | |
| 616 | 763 | /* |
| 617 | 764 | ** Open string library |
| 618 | 765 | */ |
| 619 | −LUALIB_API void lua_strlibopen (lua_State *L) { | |
| 620 | − luaL_openl(L, strlib); | |
| 766 | +LUALIB_API int luaopen_string (lua_State *L) { | |
| 767 | + luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); | |
| 768 | + return 1; | |
| 621 | 769 | } |
| 770 | + | |
| @@ -0,0 +1,250 @@ | ||
| 1 | +/* | |
| 2 | +** $Id: ltablib.c,v 1.21 2003/04/03 13:35:34 roberto Exp $ | |
| 3 | +** Library for Table Manipulation | |
| 4 | +** See Copyright Notice in lua.h | |
| 5 | +*/ | |
| 6 | + | |
| 7 | + | |
| 8 | +#include <stddef.h> | |
| 9 | + | |
| 10 | +#define ltablib_c | |
| 11 | + | |
| 12 | +#include "lua.h" | |
| 13 | + | |
| 14 | +#include "lauxlib.h" | |
| 15 | +#include "lualib.h" | |
| 16 | + | |
| 17 | + | |
| 18 | +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) | |
| 19 | + | |
| 20 | + | |
| 21 | +static int luaB_foreachi (lua_State *L) { | |
| 22 | + int i; | |
| 23 | + int n = aux_getn(L, 1); | |
| 24 | + luaL_checktype(L, 2, LUA_TFUNCTION); | |
| 25 | + for (i=1; i<=n; i++) { | |
| 26 | + lua_pushvalue(L, 2); /* function */ | |
| 27 | + lua_pushnumber(L, (lua_Number)i); /* 1st argument */ | |
| 28 | + lua_rawgeti(L, 1, i); /* 2nd argument */ | |
| 29 | + lua_call(L, 2, 1); | |
| 30 | + if (!lua_isnil(L, -1)) | |
| 31 | + return 1; | |
| 32 | + lua_pop(L, 1); /* remove nil result */ | |
| 33 | + } | |
| 34 | + return 0; | |
| 35 | +} | |
| 36 | + | |
| 37 | + | |
| 38 | +static int luaB_foreach (lua_State *L) { | |
| 39 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 40 | + luaL_checktype(L, 2, LUA_TFUNCTION); | |
| 41 | + lua_pushnil(L); /* first key */ | |
| 42 | + for (;;) { | |
| 43 | + if (lua_next(L, 1) == 0) | |
| 44 | + return 0; | |
| 45 | + lua_pushvalue(L, 2); /* function */ | |
| 46 | + lua_pushvalue(L, -3); /* key */ | |
| 47 | + lua_pushvalue(L, -3); /* value */ | |
| 48 | + lua_call(L, 2, 1); | |
| 49 | + if (!lua_isnil(L, -1)) | |
| 50 | + return 1; | |
| 51 | + lua_pop(L, 2); /* remove value and result */ | |
| 52 | + } | |
| 53 | +} | |
| 54 | + | |
| 55 | + | |
| 56 | +static int luaB_getn (lua_State *L) { | |
| 57 | + lua_pushnumber(L, (lua_Number)aux_getn(L, 1)); | |
| 58 | + return 1; | |
| 59 | +} | |
| 60 | + | |
| 61 | + | |
| 62 | +static int luaB_setn (lua_State *L) { | |
| 63 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 64 | + luaL_setn(L, 1, luaL_checkint(L, 2)); | |
| 65 | + return 0; | |
| 66 | +} | |
| 67 | + | |
| 68 | + | |
| 69 | +static int luaB_tinsert (lua_State *L) { | |
| 70 | + int v = lua_gettop(L); /* number of arguments */ | |
| 71 | + int n = aux_getn(L, 1) + 1; | |
| 72 | + int pos; /* where to insert new element */ | |
| 73 | + if (v == 2) /* called with only 2 arguments */ | |
| 74 | + pos = n; /* insert new element at the end */ | |
| 75 | + else { | |
| 76 | + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ | |
| 77 | + if (pos > n) n = pos; /* `grow' array if necessary */ | |
| 78 | + v = 3; /* function may be called with more than 3 args */ | |
| 79 | + } | |
| 80 | + luaL_setn(L, 1, n); /* new size */ | |
| 81 | + while (--n >= pos) { /* move up elements */ | |
| 82 | + lua_rawgeti(L, 1, n); | |
| 83 | + lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ | |
| 84 | + } | |
| 85 | + lua_pushvalue(L, v); | |
| 86 | + lua_rawseti(L, 1, pos); /* t[pos] = v */ | |
| 87 | + return 0; | |
| 88 | +} | |
| 89 | + | |
| 90 | + | |
| 91 | +static int luaB_tremove (lua_State *L) { | |
| 92 | + int n = aux_getn(L, 1); | |
| 93 | + int pos = luaL_optint(L, 2, n); | |
| 94 | + if (n <= 0) return 0; /* table is `empty' */ | |
| 95 | + luaL_setn(L, 1, n-1); /* t.n = n-1 */ | |
| 96 | + lua_rawgeti(L, 1, pos); /* result = t[pos] */ | |
| 97 | + for ( ;pos<n; pos++) { | |
| 98 | + lua_rawgeti(L, 1, pos+1); | |
| 99 | + lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ | |
| 100 | + } | |
| 101 | + lua_pushnil(L); | |
| 102 | + lua_rawseti(L, 1, n); /* t[n] = nil */ | |
| 103 | + return 1; | |
| 104 | +} | |
| 105 | + | |
| 106 | + | |
| 107 | +static int str_concat (lua_State *L) { | |
| 108 | + luaL_Buffer b; | |
| 109 | + size_t lsep; | |
| 110 | + const char *sep = luaL_optlstring(L, 2, "", &lsep); | |
| 111 | + int i = luaL_optint(L, 3, 1); | |
| 112 | + int n = luaL_optint(L, 4, 0); | |
| 113 | + luaL_checktype(L, 1, LUA_TTABLE); | |
| 114 | + if (n == 0) n = luaL_getn(L, 1); | |
| 115 | + luaL_buffinit(L, &b); | |
| 116 | + for (; i <= n; i++) { | |
| 117 | + lua_rawgeti(L, 1, i); | |
| 118 | + luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings"); | |
| 119 | + luaL_addvalue(&b); | |
| 120 | + if (i != n) | |
| 121 | + luaL_addlstring(&b, sep, lsep); | |
| 122 | + } | |
| 123 | + luaL_pushresult(&b); | |
| 124 | + return 1; | |
| 125 | +} | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | +/* | |
| 130 | +** {====================================================== | |
| 131 | +** Quicksort | |
| 132 | +** (based on `Algorithms in MODULA-3', Robert Sedgewick; | |
| 133 | +** Addison-Wesley, 1993.) | |
| 134 | +*/ | |
| 135 | + | |
| 136 | + | |
| 137 | +static void set2 (lua_State *L, int i, int j) { | |
| 138 | + lua_rawseti(L, 1, i); | |
| 139 | + lua_rawseti(L, 1, j); | |
| 140 | +} | |
| 141 | + | |
| 142 | +static int sort_comp (lua_State *L, int a, int b) { | |
| 143 | + if (!lua_isnil(L, 2)) { /* function? */ | |
| 144 | + int res; | |
| 145 | + lua_pushvalue(L, 2); | |
| 146 | + lua_pushvalue(L, a-1); /* -1 to compensate function */ | |
| 147 | + lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ | |
| 148 | + lua_call(L, 2, 1); | |
| 149 | + res = lua_toboolean(L, -1); | |
| 150 | + lua_pop(L, 1); | |
| 151 | + return res; | |
| 152 | + } | |
| 153 | + else /* a < b? */ | |
| 154 | + return lua_lessthan(L, a, b); | |
| 155 | +} | |
| 156 | + | |
| 157 | +static void auxsort (lua_State *L, int l, int u) { | |
| 158 | + while (l < u) { /* for tail recursion */ | |
| 159 | + int i, j; | |
| 160 | + /* sort elements a[l], a[(l+u)/2] and a[u] */ | |
| 161 | + lua_rawgeti(L, 1, l); | |
| 162 | + lua_rawgeti(L, 1, u); | |
| 163 | + if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ | |
| 164 | + set2(L, l, u); /* swap a[l] - a[u] */ | |
| 165 | + else | |
| 166 | + lua_pop(L, 2); | |
| 167 | + if (u-l == 1) break; /* only 2 elements */ | |
| 168 | + i = (l+u)/2; | |
| 169 | + lua_rawgeti(L, 1, i); | |
| 170 | + lua_rawgeti(L, 1, l); | |
| 171 | + if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ | |
| 172 | + set2(L, i, l); | |
| 173 | + else { | |
| 174 | + lua_pop(L, 1); /* remove a[l] */ | |
| 175 | + lua_rawgeti(L, 1, u); | |
| 176 | + if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ | |
| 177 | + set2(L, i, u); | |
| 178 | + else | |
| 179 | + lua_pop(L, 2); | |
| 180 | + } | |
| 181 | + if (u-l == 2) break; /* only 3 elements */ | |
| 182 | + lua_rawgeti(L, 1, i); /* Pivot */ | |
| 183 | + lua_pushvalue(L, -1); | |
| 184 | + lua_rawgeti(L, 1, u-1); | |
| 185 | + set2(L, i, u-1); | |
| 186 | + /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ | |
| 187 | + i = l; j = u-1; | |
| 188 | + for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | |
| 189 | + /* repeat ++i until a[i] >= P */ | |
| 190 | + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { | |
| 191 | + if (i>u) luaL_error(L, "invalid order function for sorting"); | |
| 192 | + lua_pop(L, 1); /* remove a[i] */ | |
| 193 | + } | |
| 194 | + /* repeat --j until a[j] <= P */ | |
| 195 | + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { | |
| 196 | + if (j<l) luaL_error(L, "invalid order function for sorting"); | |
| 197 | + lua_pop(L, 1); /* remove a[j] */ | |
| 198 | + } | |
| 199 | + if (j<i) { | |
| 200 | + lua_pop(L, 3); /* pop pivot, a[i], a[j] */ | |
| 201 | + break; | |
| 202 | + } | |
| 203 | + set2(L, i, j); | |
| 204 | + } | |
| 205 | + lua_rawgeti(L, 1, u-1); | |
| 206 | + lua_rawgeti(L, 1, i); | |
| 207 | + set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | |
| 208 | + /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ | |
| 209 | + /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ | |
| 210 | + if (i-l < u-i) { | |
| 211 | + j=l; i=i-1; l=i+2; | |
| 212 | + } | |
| 213 | + else { | |
| 214 | + j=i+1; i=u; u=j-2; | |
| 215 | + } | |
| 216 | + auxsort(L, j, i); /* call recursively the smaller one */ | |
| 217 | + } /* repeat the routine for the larger one */ | |
| 218 | +} | |
| 219 | + | |
| 220 | +static int luaB_sort (lua_State *L) { | |
| 221 | + int n = aux_getn(L, 1); | |
| 222 | + luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ | |
| 223 | + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ | |
| 224 | + luaL_checktype(L, 2, LUA_TFUNCTION); | |
| 225 | + lua_settop(L, 2); /* make sure there is two arguments */ | |
| 226 | + auxsort(L, 1, n); | |
| 227 | + return 0; | |
| 228 | +} | |
| 229 | + | |
| 230 | +/* }====================================================== */ | |
| 231 | + | |
| 232 | + | |
| 233 | +static const luaL_reg tab_funcs[] = { | |
| 234 | + {"concat", str_concat}, | |
| 235 | + {"foreach", luaB_foreach}, | |
| 236 | + {"foreachi", luaB_foreachi}, | |
| 237 | + {"getn", luaB_getn}, | |
| 238 | + {"setn", luaB_setn}, | |
| 239 | + {"sort", luaB_sort}, | |
| 240 | + {"insert", luaB_tinsert}, | |
| 241 | + {"remove", luaB_tremove}, | |
| 242 | + {NULL, NULL} | |
| 243 | +}; | |
| 244 | + | |
| 245 | + | |
| 246 | +LUALIB_API int luaopen_table (lua_State *L) { | |
| 247 | + luaL_openlib(L, LUA_TABLIBNAME, tab_funcs, 0); | |
| 248 | + return 1; | |
| 249 | +} | |
| 250 | + | |
| @@ -1,24 +1,23 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: llex.c,v 1.72 2000/10/20 16:39:03 roberto Exp $ | |
| 2 | +** $Id: llex.c,v 1.119 2003/03/24 12:39:34 roberto Exp $ | |
| 3 | 3 | ** Lexical Analyzer |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | #include <ctype.h> |
| 9 | −#include <stdio.h> | |
| 10 | 9 | #include <string.h> |
| 11 | 10 | |
| 11 | +#define llex_c | |
| 12 | + | |
| 12 | 13 | #include "lua.h" |
| 13 | 14 | |
| 15 | +#include "ldo.h" | |
| 14 | 16 | #include "llex.h" |
| 15 | −#include "lmem.h" | |
| 16 | 17 | #include "lobject.h" |
| 17 | 18 | #include "lparser.h" |
| 18 | 19 | #include "lstate.h" |
| 19 | 20 | #include "lstring.h" |
| 20 | −#include "ltable.h" | |
| 21 | −#include "luadebug.h" | |
| 22 | 21 | #include "lzio.h" |
| 23 | 22 | |
| 24 | 23 | |
| @@ -29,16 +28,22 @@ · 4 unmodified lines | ||
| 29 | 28 | |
| 30 | 29 | /* ORDER RESERVED */ |
| 31 | 30 | static const char *const token2string [] = { |
| 32 | − "and", "break", "do", "else", "elseif", "end", "for", | |
| 33 | − "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", | |
| 34 | − "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", "<eof>"}; | |
| 31 | + "and", "break", "do", "else", "elseif", | |
| 32 | + "end", "false", "for", "function", "if", | |
| 33 | + "in", "local", "nil", "not", "or", "repeat", | |
| 34 | + "return", "then", "true", "until", "while", "*name", | |
| 35 | + "..", "...", "==", ">=", "<=", "~=", | |
| 36 | + "*number", "*string", "<eof>" | |
| 37 | +}; | |
| 35 | 38 | |
| 36 | 39 | |
| 37 | 40 | void luaX_init (lua_State *L) { |
| 38 | 41 | int i; |
| 39 | 42 | for (i=0; i<NUM_RESERVED; i++) { |
| 40 | 43 | TString *ts = luaS_new(L, token2string[i]); |
| 41 | − ts->marked = (unsigned char)(RESERVEDMARK+i); /* reserved word */ | |
| 44 | + luaS_fix(ts); /* reserved words are never collected */ | |
| 45 | + lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN); | |
| 46 | + ts->tsv.reserved = cast(lu_byte, i+1); /* reserved word */ | |
| 42 | 47 | } |
| 43 | 48 | } |
| 44 | 49 | |
| @@ -48,50 +53,64 @@ void luaX_init (lua_State *L) { · 3 unmodified lines | ||
| 48 | 53 | |
| 49 | 54 | void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { |
| 50 | 55 | if (val > limit) { |
| 51 | − char buff[100]; | |
| 52 | − sprintf(buff, "too many %.50s (limit=%d)", msg, limit); | |
| 53 | − luaX_error(ls, buff, ls->t.token); | |
| 56 | + msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit); | |
| 57 | + luaX_syntaxerror(ls, msg); | |
| 54 | 58 | } |
| 55 | 59 | } |
| 56 | 60 | |
| 57 | 61 | |
| 58 | −void luaX_syntaxerror (LexState *ls, const char *s, const char *token) { | |
| 62 | +void luaX_errorline (LexState *ls, const char *s, const char *token, int line) { | |
| 63 | + lua_State *L = ls->L; | |
| 59 | 64 | char buff[MAXSRC]; |
| 60 | − luaO_chunkid(buff, ls->source->str, sizeof(buff)); | |
| 61 | − luaO_verror(ls->L, "%.99s;\n last token read: `%.30s' at line %d in %.80s", | |
| 62 | − s, token, ls->linenumber, buff); | |
| 65 | + luaO_chunkid(buff, getstr(ls->source), MAXSRC); | |
| 66 | + luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token); | |
| 67 | + luaD_throw(L, LUA_ERRSYNTAX); | |
| 63 | 68 | } |
| 64 | 69 | |
| 65 | 70 | |
| 66 | −void luaX_error (LexState *ls, const char *s, int token) { | |
| 67 | − char buff[TOKEN_LEN]; | |
| 68 | − luaX_token2str(token, buff); | |
| 69 | − if (buff[0] == '\0') | |
| 70 | − luaX_syntaxerror(ls, s, ls->L->Mbuffer); | |
| 71 | − else | |
| 72 | − luaX_syntaxerror(ls, s, buff); | |
| 71 | +static void luaX_error (LexState *ls, const char *s, const char *token) { | |
| 72 | + luaX_errorline(ls, s, token, ls->linenumber); | |
| 73 | +} | |
| 74 | + | |
| 75 | + | |
| 76 | +void luaX_syntaxerror (LexState *ls, const char *msg) { | |
| 77 | + const char *lasttoken; | |
| 78 | + switch (ls->t.token) { | |
| 79 | + case TK_NAME: | |
| 80 | + lasttoken = getstr(ls->t.seminfo.ts); | |
| 81 | + break; | |
| 82 | + case TK_STRING: | |
| 83 | + case TK_NUMBER: | |
| 84 | + lasttoken = luaZ_buffer(ls->buff); | |
| 85 | + break; | |
| 86 | + default: | |
| 87 | + lasttoken = luaX_token2str(ls, ls->t.token); | |
| 88 | + break; | |
| 89 | + } | |
| 90 | + luaX_error(ls, msg, lasttoken); | |
| 73 | 91 | } |
| 74 | 92 | |
| 75 | 93 | |
| 76 | −void luaX_token2str (int token, char *s) { | |
| 77 | − if (token < 256) { | |
| 78 | − s[0] = (char)token; | |
| 79 | − s[1] = '\0'; | |
| 94 | +const char *luaX_token2str (LexState *ls, int token) { | |
| 95 | + if (token < FIRST_RESERVED) { | |
| 96 | + lua_assert(token == (unsigned char)token); | |
| 97 | + return luaO_pushfstring(ls->L, "%c", token); | |
| 80 | 98 | } |
| 81 | 99 | else |
| 82 | − strcpy(s, token2string[token-FIRST_RESERVED]); | |
| 100 | + return token2string[token-FIRST_RESERVED]; | |
| 83 | 101 | } |
| 84 | 102 | |
| 85 | 103 | |
| 86 | −static void luaX_invalidchar (LexState *ls, int c) { | |
| 87 | − char buff[8]; | |
| 88 | − sprintf(buff, "0x%02X", c); | |
| 89 | − luaX_syntaxerror(ls, "invalid control char", buff); | |
| 104 | +static void luaX_lexerror (LexState *ls, const char *s, int token) { | |
| 105 | + if (token == TK_EOS) | |
| 106 | + luaX_error(ls, s, luaX_token2str(ls, token)); | |
| 107 | + else | |
| 108 | + luaX_error(ls, s, luaZ_buffer(ls->buff)); | |
| 90 | 109 | } |
| 91 | 110 | |
| 92 | 111 | |
| 93 | 112 | static void inclinenumber (LexState *LS) { |
| 94 | − next(LS); /* skip '\n' */ | |
| 113 | + next(LS); /* skip `\n' */ | |
| 95 | 114 | ++LS->linenumber; |
| 96 | 115 | luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk"); |
| 97 | 116 | } |
| @@ -122,159 +141,173 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) { · 24 unmodified lines | ||
| 122 | 141 | */ |
| 123 | 142 | |
| 124 | 143 | |
| 125 | −/* use Mbuffer to store names, literal strings and numbers */ | |
| 144 | +/* use buffer to store names, literal strings and numbers */ | |
| 145 | + | |
| 146 | +/* extra space to allocate when growing buffer */ | |
| 147 | +#define EXTRABUFF 32 | |
| 148 | + | |
| 149 | +/* maximum number of chars that can be read without checking buffer size */ | |
| 150 | +#define MAXNOCHECK 5 | |
| 126 | 151 | |
| 127 | −#define EXTRABUFF 128 | |
| 128 | −#define checkbuffer(L, n, len) if ((len)+(n) > L->Mbuffsize) \ | |
| 129 | − luaO_openspace(L, (len)+(n)+EXTRABUFF) | |
| 152 | +#define checkbuffer(LS, len) \ | |
| 153 | + if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \ | |
| 154 | + luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF) | |
| 130 | 155 | |
| 131 | −#define save(L, c, l) (L->Mbuffer[l++] = (char)c) | |
| 132 | −#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS)) | |
| 156 | +#define save(LS, c, l) \ | |
| 157 | + (luaZ_buffer((LS)->buff)[l++] = cast(char, c)) | |
| 158 | +#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS)) | |
| 133 | 159 | |
| 134 | 160 | |
| 135 | −static const char *readname (LexState *LS) { | |
| 136 | − lua_State *L = LS->L; | |
| 161 | +static size_t readname (LexState *LS) { | |
| 137 | 162 | size_t l = 0; |
| 138 | − checkbuffer(L, 10, l); | |
| 163 | + checkbuffer(LS, l); | |
| 139 | 164 | do { |
| 140 | − checkbuffer(L, 10, l); | |
| 141 | − save_and_next(L, LS, l); | |
| 165 | + checkbuffer(LS, l); | |
| 166 | + save_and_next(LS, l); | |
| 142 | 167 | } while (isalnum(LS->current) || LS->current == '_'); |
| 143 | − save(L, '\0', l); | |
| 144 | − return L->Mbuffer; | |
| 168 | + save(LS, '\0', l); | |
| 169 | + return l-1; | |
| 145 | 170 | } |
| 146 | 171 | |
| 147 | 172 | |
| 148 | 173 | /* LUA_NUMBER */ |
| 149 | −static void read_number (LexState *LS, int comma, SemInfo *seminfo) { | |
| 150 | − lua_State *L = LS->L; | |
| 174 | +static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) { | |
| 151 | 175 | size_t l = 0; |
| 152 | − checkbuffer(L, 10, l); | |
| 153 | − if (comma) save(L, '.', l); | |
| 176 | + checkbuffer(LS, l); | |
| 177 | + if (comma) save(LS, '.', l); | |
| 154 | 178 | while (isdigit(LS->current)) { |
| 155 | − checkbuffer(L, 10, l); | |
| 156 | − save_and_next(L, LS, l); | |
| 179 | + checkbuffer(LS, l); | |
| 180 | + save_and_next(LS, l); | |
| 157 | 181 | } |
| 158 | 182 | if (LS->current == '.') { |
| 159 | − save_and_next(L, LS, l); | |
| 183 | + save_and_next(LS, l); | |
| 160 | 184 | if (LS->current == '.') { |
| 161 | − save_and_next(L, LS, l); | |
| 162 | − save(L, '\0', l); | |
| 163 | − luaX_error(LS, "ambiguous syntax" | |
| 164 | − " (decimal point x string concatenation)", TK_NUMBER); | |
| 185 | + save_and_next(LS, l); | |
| 186 | + save(LS, '\0', l); | |
| 187 | + luaX_lexerror(LS, | |
| 188 | + "ambiguous syntax (decimal point x string concatenation)", | |
| 189 | + TK_NUMBER); | |
| 165 | 190 | } |
| 166 | 191 | } |
| 167 | 192 | while (isdigit(LS->current)) { |
| 168 | − checkbuffer(L, 10, l); | |
| 169 | − save_and_next(L, LS, l); | |
| 193 | + checkbuffer(LS, l); | |
| 194 | + save_and_next(LS, l); | |
| 170 | 195 | } |
| 171 | 196 | if (LS->current == 'e' || LS->current == 'E') { |
| 172 | − save_and_next(L, LS, l); /* read 'E' */ | |
| 197 | + save_and_next(LS, l); /* read `E' */ | |
| 173 | 198 | if (LS->current == '+' || LS->current == '-') |
| 174 | − save_and_next(L, LS, l); /* optional exponent sign */ | |
| 199 | + save_and_next(LS, l); /* optional exponent sign */ | |
| 175 | 200 | while (isdigit(LS->current)) { |
| 176 | − checkbuffer(L, 10, l); | |
| 177 | − save_and_next(L, LS, l); | |
| 201 | + checkbuffer(LS, l); | |
| 202 | + save_and_next(LS, l); | |
| 178 | 203 | } |
| 179 | 204 | } |
| 180 | − save(L, '\0', l); | |
| 181 | − if (!luaO_str2d(L->Mbuffer, &seminfo->r)) | |
| 182 | − luaX_error(LS, "malformed number", TK_NUMBER); | |
| 205 | + save(LS, '\0', l); | |
| 206 | + if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r)) | |
| 207 | + luaX_lexerror(LS, "malformed number", TK_NUMBER); | |
| 183 | 208 | } |
| 184 | 209 | |
| 185 | 210 | |
| 186 | 211 | static void read_long_string (LexState *LS, SemInfo *seminfo) { |
| 187 | − lua_State *L = LS->L; | |
| 188 | 212 | int cont = 0; |
| 189 | 213 | size_t l = 0; |
| 190 | − checkbuffer(L, 10, l); | |
| 191 | − save(L, '[', l); /* save first '[' */ | |
| 192 | − save_and_next(L, LS, l); /* pass the second '[' */ | |
| 214 | + checkbuffer(LS, l); | |
| 215 | + save(LS, '[', l); /* save first `[' */ | |
| 216 | + save_and_next(LS, l); /* pass the second `[' */ | |
| 217 | + if (LS->current == '\n') /* string starts with a newline? */ | |
| 218 | + inclinenumber(LS); /* skip it */ | |
| 193 | 219 | for (;;) { |
| 194 | − checkbuffer(L, 10, l); | |
| 220 | + checkbuffer(LS, l); | |
| 195 | 221 | switch (LS->current) { |
| 196 | 222 | case EOZ: |
| 197 | − save(L, '\0', l); | |
| 198 | − luaX_error(LS, "unfinished long string", TK_STRING); | |
| 223 | + save(LS, '\0', l); | |
| 224 | + luaX_lexerror(LS, (seminfo) ? "unfinished long string" : | |
| 225 | + "unfinished long comment", TK_EOS); | |
| 199 | 226 | break; /* to avoid warnings */ |
| 200 | 227 | case '[': |
| 201 | − save_and_next(L, LS, l); | |
| 228 | + save_and_next(LS, l); | |
| 202 | 229 | if (LS->current == '[') { |
| 203 | 230 | cont++; |
| 204 | − save_and_next(L, LS, l); | |
| 231 | + save_and_next(LS, l); | |
| 205 | 232 | } |
| 206 | 233 | continue; |
| 207 | 234 | case ']': |
| 208 | − save_and_next(L, LS, l); | |
| 235 | + save_and_next(LS, l); | |
| 209 | 236 | if (LS->current == ']') { |
| 210 | 237 | if (cont == 0) goto endloop; |
| 211 | 238 | cont--; |
| 212 | − save_and_next(L, LS, l); | |
| 239 | + save_and_next(LS, l); | |
| 213 | 240 | } |
| 214 | 241 | continue; |
| 215 | 242 | case '\n': |
| 216 | − save(L, '\n', l); | |
| 243 | + save(LS, '\n', l); | |
| 217 | 244 | inclinenumber(LS); |
| 245 | + if (!seminfo) l = 0; /* reset buffer to avoid wasting space */ | |
| 218 | 246 | continue; |
| 219 | 247 | default: |
| 220 | − save_and_next(L, LS, l); | |
| 248 | + save_and_next(LS, l); | |
| 221 | 249 | } |
| 222 | 250 | } endloop: |
| 223 | − save_and_next(L, LS, l); /* skip the second ']' */ | |
| 224 | − save(L, '\0', l); | |
| 225 | − seminfo->ts = luaS_newlstr(L, L->Mbuffer+2, l-5); | |
| 251 | + save_and_next(LS, l); /* skip the second `]' */ | |
| 252 | + save(LS, '\0', l); | |
| 253 | + if (seminfo) | |
| 254 | + seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5); | |
| 226 | 255 | } |
| 227 | 256 | |
| 228 | 257 | |
| 229 | 258 | static void read_string (LexState *LS, int del, SemInfo *seminfo) { |
| 230 | − lua_State *L = LS->L; | |
| 231 | 259 | size_t l = 0; |
| 232 | − checkbuffer(L, 10, l); | |
| 233 | − save_and_next(L, LS, l); | |
| 260 | + checkbuffer(LS, l); | |
| 261 | + save_and_next(LS, l); | |
| 234 | 262 | while (LS->current != del) { |
| 235 | − checkbuffer(L, 10, l); | |
| 263 | + checkbuffer(LS, l); | |
| 236 | 264 | switch (LS->current) { |
| 237 | − case EOZ: case '\n': | |
| 238 | − save(L, '\0', l); | |
| 239 | − luaX_error(LS, "unfinished string", TK_STRING); | |
| 265 | + case EOZ: | |
| 266 | + save(LS, '\0', l); | |
| 267 | + luaX_lexerror(LS, "unfinished string", TK_EOS); | |
| 268 | + break; /* to avoid warnings */ | |
| 269 | + case '\n': | |
| 270 | + save(LS, '\0', l); | |
| 271 | + luaX_lexerror(LS, "unfinished string", TK_STRING); | |
| 240 | 272 | break; /* to avoid warnings */ |
| 241 | 273 | case '\\': |
| 242 | − next(LS); /* do not save the '\' */ | |
| 274 | + next(LS); /* do not save the `\' */ | |
| 243 | 275 | switch (LS->current) { |
| 244 | − case 'a': save(L, '\a', l); next(LS); break; | |
| 245 | − case 'b': save(L, '\b', l); next(LS); break; | |
| 246 | − case 'f': save(L, '\f', l); next(LS); break; | |
| 247 | − case 'n': save(L, '\n', l); next(LS); break; | |
| 248 | − case 'r': save(L, '\r', l); next(LS); break; | |
| 249 | − case 't': save(L, '\t', l); next(LS); break; | |
| 250 | − case 'v': save(L, '\v', l); next(LS); break; | |
| 251 | − case '\n': save(L, '\n', l); inclinenumber(LS); break; | |
| 252 | − case '0': case '1': case '2': case '3': case '4': | |
| 253 | − case '5': case '6': case '7': case '8': case '9': { | |
| 254 | − int c = 0; | |
| 255 | − int i = 0; | |
| 256 | − do { | |
| 257 | − c = 10*c + (LS->current-'0'); | |
| 258 | − next(LS); | |
| 259 | − } while (++i<3 && isdigit(LS->current)); | |
| 260 | − if (c != (unsigned char)c) { | |
| 261 | − save(L, '\0', l); | |
| 262 | − luaX_error(LS, "escape sequence too large", TK_STRING); | |
| 276 | + case 'a': save(LS, '\a', l); next(LS); break; | |
| 277 | + case 'b': save(LS, '\b', l); next(LS); break; | |
| 278 | + case 'f': save(LS, '\f', l); next(LS); break; | |
| 279 | + case 'n': save(LS, '\n', l); next(LS); break; | |
| 280 | + case 'r': save(LS, '\r', l); next(LS); break; | |
| 281 | + case 't': save(LS, '\t', l); next(LS); break; | |
| 282 | + case 'v': save(LS, '\v', l); next(LS); break; | |
| 283 | + case '\n': save(LS, '\n', l); inclinenumber(LS); break; | |
| 284 | + case EOZ: break; /* will raise an error next loop */ | |
| 285 | + default: { | |
| 286 | + if (!isdigit(LS->current)) | |
| 287 | + save_and_next(LS, l); /* handles \\, \", \', and \? */ | |
| 288 | + else { /* \xxx */ | |
| 289 | + int c = 0; | |
| 290 | + int i = 0; | |
| 291 | + do { | |
| 292 | + c = 10*c + (LS->current-'0'); | |
| 293 | + next(LS); | |
| 294 | + } while (++i<3 && isdigit(LS->current)); | |
| 295 | + if (c > UCHAR_MAX) { | |
| 296 | + save(LS, '\0', l); | |
| 297 | + luaX_lexerror(LS, "escape sequence too large", TK_STRING); | |
| 298 | + } | |
| 299 | + save(LS, c, l); | |
| 263 | 300 | } |
| 264 | − save(L, c, l); | |
| 265 | − break; | |
| 266 | 301 | } |
| 267 | − default: /* handles \\, \", \', and \? */ | |
| 268 | − save_and_next(L, LS, l); | |
| 269 | 302 | } |
| 270 | 303 | break; |
| 271 | 304 | default: |
| 272 | − save_and_next(L, LS, l); | |
| 305 | + save_and_next(LS, l); | |
| 273 | 306 | } |
| 274 | 307 | } |
| 275 | − save_and_next(L, LS, l); /* skip delimiter */ | |
| 276 | − save(L, '\0', l); | |
| 277 | − seminfo->ts = luaS_newlstr(L, L->Mbuffer+1, l-3); | |
| 308 | + save_and_next(LS, l); /* skip delimiter */ | |
| 309 | + save(LS, '\0', l); | |
| 310 | + seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3); | |
| 278 | 311 | } |
| 279 | 312 | |
| 280 | 313 | |
| @@ -282,58 +315,56 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) { · 1 unmodified line | ||
| 282 | 315 | for (;;) { |
| 283 | 316 | switch (LS->current) { |
| 284 | 317 | |
| 285 | − case ' ': case '\t': case '\r': /* `\r' to avoid problems with DOS */ | |
| 286 | − next(LS); | |
| 287 | − continue; | |
| 288 | − | |
| 289 | − case '\n': | |
| 318 | + case '\n': { | |
| 290 | 319 | inclinenumber(LS); |
| 291 | 320 | continue; |
| 292 | − | |
| 293 | − case '$': | |
| 294 | − luaX_error(LS, "unexpected `$' (pragmas are no longer supported)", '$'); | |
| 295 | − break; | |
| 296 | − | |
| 297 | − case '-': | |
| 321 | + } | |
| 322 | + case '-': { | |
| 298 | 323 | next(LS); |
| 299 | 324 | if (LS->current != '-') return '-'; |
| 300 | − do { next(LS); } while (LS->current != '\n' && LS->current != EOZ); | |
| 325 | + /* else is a comment */ | |
| 326 | + next(LS); | |
| 327 | + if (LS->current == '[' && (next(LS), LS->current == '[')) | |
| 328 | + read_long_string(LS, NULL); /* long comment */ | |
| 329 | + else /* short comment */ | |
| 330 | + while (LS->current != '\n' && LS->current != EOZ) | |
| 331 | + next(LS); | |
| 301 | 332 | continue; |
| 302 | − | |
| 303 | − case '[': | |
| 333 | + } | |
| 334 | + case '[': { | |
| 304 | 335 | next(LS); |
| 305 | 336 | if (LS->current != '[') return '['; |
| 306 | 337 | else { |
| 307 | 338 | read_long_string(LS, seminfo); |
| 308 | 339 | return TK_STRING; |
| 309 | 340 | } |
| 310 | − | |
| 311 | − case '=': | |
| 341 | + } | |
| 342 | + case '=': { | |
| 312 | 343 | next(LS); |
| 313 | 344 | if (LS->current != '=') return '='; |
| 314 | 345 | else { next(LS); return TK_EQ; } |
| 315 | − | |
| 316 | − case '<': | |
| 346 | + } | |
| 347 | + case '<': { | |
| 317 | 348 | next(LS); |
| 318 | 349 | if (LS->current != '=') return '<'; |
| 319 | 350 | else { next(LS); return TK_LE; } |
| 320 | − | |
| 321 | − case '>': | |
| 351 | + } | |
| 352 | + case '>': { | |
| 322 | 353 | next(LS); |
| 323 | 354 | if (LS->current != '=') return '>'; |
| 324 | 355 | else { next(LS); return TK_GE; } |
| 325 | − | |
| 326 | − case '~': | |
| 356 | + } | |
| 357 | + case '~': { | |
| 327 | 358 | next(LS); |
| 328 | 359 | if (LS->current != '=') return '~'; |
| 329 | 360 | else { next(LS); return TK_NE; } |
| 330 | − | |
| 361 | + } | |
| 331 | 362 | case '"': |
| 332 | − case '\'': | |
| 363 | + case '\'': { | |
| 333 | 364 | read_string(LS, LS->current, seminfo); |
| 334 | 365 | return TK_STRING; |
| 335 | − | |
| 336 | − case '.': | |
| 366 | + } | |
| 367 | + case '.': { | |
| 337 | 368 | next(LS); |
| 338 | 369 | if (LS->current == '.') { |
| 339 | 370 | next(LS); |
| @@ -345,36 +376,42 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) { · 5 unmodified lines | ||
| 345 | 376 | } |
| 346 | 377 | else if (!isdigit(LS->current)) return '.'; |
| 347 | 378 | else { |
| 348 | − read_number(LS, 1, seminfo); | |
| 379 | + read_numeral(LS, 1, seminfo); | |
| 349 | 380 | return TK_NUMBER; |
| 350 | 381 | } |
| 351 | − | |
| 352 | − case '0': case '1': case '2': case '3': case '4': | |
| 353 | − case '5': case '6': case '7': case '8': case '9': | |
| 354 | − read_number(LS, 0, seminfo); | |
| 355 | − return TK_NUMBER; | |
| 356 | − | |
| 357 | − case EOZ: | |
| 382 | + } | |
| 383 | + case EOZ: { | |
| 358 | 384 | return TK_EOS; |
| 359 | − | |
| 360 | − case '_': goto tname; | |
| 361 | − | |
| 362 | − default: | |
| 363 | − if (!isalpha(LS->current)) { | |
| 364 | − int c = LS->current; | |
| 365 | − if (iscntrl(c)) | |
| 366 | − luaX_invalidchar(LS, c); | |
| 385 | + } | |
| 386 | + default: { | |
| 387 | + if (isspace(LS->current)) { | |
| 367 | 388 | next(LS); |
| 368 | − return c; | |
| 389 | + continue; | |
| 390 | + } | |
| 391 | + else if (isdigit(LS->current)) { | |
| 392 | + read_numeral(LS, 0, seminfo); | |
| 393 | + return TK_NUMBER; | |
| 369 | 394 | } |
| 370 | − tname: { /* identifier or reserved word */ | |
| 371 | − TString *ts = luaS_new(LS->L, readname(LS)); | |
| 372 | − if (ts->marked >= RESERVEDMARK) /* reserved word? */ | |
| 373 | − return ts->marked-RESERVEDMARK+FIRST_RESERVED; | |
| 395 | + else if (isalpha(LS->current) || LS->current == '_') { | |
| 396 | + /* identifier or reserved word */ | |
| 397 | + size_t l = readname(LS); | |
| 398 | + TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l); | |
| 399 | + if (ts->tsv.reserved > 0) /* reserved word? */ | |
| 400 | + return ts->tsv.reserved - 1 + FIRST_RESERVED; | |
| 374 | 401 | seminfo->ts = ts; |
| 375 | 402 | return TK_NAME; |
| 376 | 403 | } |
| 404 | + else { | |
| 405 | + int c = LS->current; | |
| 406 | + if (iscntrl(c)) | |
| 407 | + luaX_error(LS, "invalid control char", | |
| 408 | + luaO_pushfstring(LS->L, "char(%d)", c)); | |
| 409 | + next(LS); | |
| 410 | + return c; /* single-char tokens (+ - / ...) */ | |
| 411 | + } | |
| 412 | + } | |
| 377 | 413 | } |
| 378 | 414 | } |
| 379 | 415 | } |
| 380 | 416 | |
| 417 | +#undef next | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: llex.h,v 1.31 2000/09/27 17:41:58 roberto Exp $ | |
| 2 | +** $Id: llex.h,v 1.47 2003/02/28 17:19:47 roberto Exp $ | |
| 3 | 3 | ** Lexical Analyzer |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -13,8 +13,8 @@ · 7 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #define FIRST_RESERVED 257 |
| 15 | 15 | |
| 16 | −/* maximum length of a reserved word (+1 for final 0) */ | |
| 17 | −#define TOKEN_LEN 15 | |
| 16 | +/* maximum length of a reserved word */ | |
| 17 | +#define TOKEN_LEN (sizeof("function")/sizeof(char)) | |
| 18 | 18 | |
| 19 | 19 | |
| 20 | 20 | /* |
| @@ -24,19 +24,20 @@ · 3 unmodified lines | ||
| 24 | 24 | enum RESERVED { |
| 25 | 25 | /* terminal symbols denoted by reserved words */ |
| 26 | 26 | TK_AND = FIRST_RESERVED, TK_BREAK, |
| 27 | − TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FOR, TK_FUNCTION, TK_IF, TK_LOCAL, | |
| 28 | − TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, | |
| 27 | + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, | |
| 28 | + TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, | |
| 29 | + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, | |
| 29 | 30 | /* other terminal symbols */ |
| 30 | 31 | TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, |
| 31 | 32 | TK_STRING, TK_EOS |
| 32 | 33 | }; |
| 33 | 34 | |
| 34 | 35 | /* number of reserved words */ |
| 35 | −#define NUM_RESERVED ((int)(TK_WHILE-FIRST_RESERVED+1)) | |
| 36 | +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) | |
| 36 | 37 | |
| 37 | 38 | |
| 38 | 39 | typedef union { |
| 39 | − Number r; | |
| 40 | + lua_Number r; | |
| 40 | 41 | TString *ts; |
| 41 | 42 | } SemInfo; /* semantics information */ |
| 42 | 43 | |
| @@ -48,15 +49,17 @@ typedef struct Token { · 5 unmodified lines | ||
| 48 | 49 | |
| 49 | 50 | |
| 50 | 51 | typedef struct LexState { |
| 51 | − int current; /* current character */ | |
| 52 | + int current; /* current character (charint) */ | |
| 53 | + int linenumber; /* input line counter */ | |
| 54 | + int lastline; /* line of last token `consumed' */ | |
| 52 | 55 | Token t; /* current token */ |
| 53 | 56 | Token lookahead; /* look ahead token */ |
| 54 | 57 | struct FuncState *fs; /* `FuncState' is private to the parser */ |
| 55 | 58 | struct lua_State *L; |
| 56 | − struct zio *z; /* input stream */ | |
| 57 | − int linenumber; /* input line counter */ | |
| 58 | − int lastline; /* line of last token `consumed' */ | |
| 59 | + ZIO *z; /* input stream */ | |
| 60 | + Mbuffer *buff; /* buffer for tokens */ | |
| 59 | 61 | TString *source; /* current source name */ |
| 62 | + int nestlevel; /* level of nested non-terminals */ | |
| 60 | 63 | } LexState; |
| 61 | 64 | |
| 62 | 65 | |
| @@ -64,9 +67,9 @@ void luaX_init (lua_State *L); · 1 unmodified line | ||
| 64 | 67 | void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); |
| 65 | 68 | int luaX_lex (LexState *LS, SemInfo *seminfo); |
| 66 | 69 | void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); |
| 67 | −void luaX_syntaxerror (LexState *ls, const char *s, const char *token); | |
| 68 | −void luaX_error (LexState *ls, const char *s, int token); | |
| 69 | −void luaX_token2str (int token, char *s); | |
| 70 | +void luaX_syntaxerror (LexState *ls, const char *s); | |
| 71 | +void luaX_errorline (LexState *ls, const char *s, const char *token, int line); | |
| 72 | +const char *luaX_token2str (LexState *ls, int token); | |
| 70 | 73 | |
| 71 | 74 | |
| 72 | 75 | #endif |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /* |
267 more lines aren’t shown here.
This diff is large: its 203 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 442 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 324 lines aren’t shown here.
This diff is large: its 1808 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 294 lines aren’t shown here.
This diff is large: its 236 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 694 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 1017 lines aren’t shown here.
This diff is large: its 202 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 652 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 310 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 259 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 420 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 1280 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 193 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 182 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.