Compare commits

...

221 Commits

Author SHA1 Message Date
Roberto Ierusalimschy
762c737037 last changes by lhf 2003-04-10 14:39:41 -03:00
Roberto Ierusalimschy
de57dc2653 new scheme to control `loadlib' configuration (default for dlopen
implementation is not to include it)
2003-04-07 17:11:53 -03:00
Roberto Ierusalimschy
d1df829f8d lua_getmetatable must accept any acceptable index 2003-04-07 11:36:08 -03:00
Roberto Ierusalimschy
2ad947fe03 new test options for luaL_getn/setn 2003-04-07 11:35:00 -03:00
Roberto Ierusalimschy
f0cc013afa luaL_getn/setn must operate correctly over negative indices 2003-04-07 11:35:00 -03:00
Roberto Ierusalimschy
0d88545b82 warnings from several compilers (mainly typecasts when lua_Number is float) 2003-04-03 10:35:34 -03:00
Roberto Ierusalimschy
f84c5a5fc6 avoid conflicts in (re)definition of `isatty' 2003-04-03 10:34:42 -03:00
Roberto Ierusalimschy
05d35d8f3c comments 2003-04-02 10:09:14 -03:00
Roberto Ierusalimschy
3a6230ef7c error-message format 2003-04-01 14:52:31 -03:00
Roberto Ierusalimschy
a424a112b5 clearance of debuging code (left by mistake) 2003-03-31 10:00:25 -03:00
Roberto Ierusalimschy
b858161fbc new hash method for lua_Number (double) (due to a performance problem) 2003-03-24 11:18:42 -03:00
Roberto Ierusalimschy
80bac182db do not mix --help' with --' 2003-03-24 09:40:01 -03:00
Roberto Ierusalimschy
30a411ab3c chars from zio are always unsigned 2003-03-24 09:39:34 -03:00
Roberto Ierusalimschy
5bb5a1831d details 2003-03-20 17:26:33 -03:00
Roberto Ierusalimschy
b518d14071 bug: zio mixes a 255 as first char in a buffer with EOZ 2003-03-20 13:00:56 -03:00
Roberto Ierusalimschy
15dbb53461 towards 5.0 final 2003-03-19 18:27:30 -03:00
Roberto Ierusalimschy
abc304f9da avoid name colision (for alllua.c) 2003-03-19 18:24:04 -03:00
Roberto Ierusalimschy
1a553f9199 better error messages 2003-03-19 18:16:12 -03:00
Roberto Ierusalimschy
0ca225d33a better error message 2003-03-19 18:15:18 -03:00
Roberto Ierusalimschy
70e2b7ab86 name changes to avoid name collision between macros and variables 2003-03-19 18:14:53 -03:00
Roberto Ierusalimschy
5a144e891a __globals' -> __fenv' 2003-03-19 18:14:34 -03:00
Roberto Ierusalimschy
b12776f29c `luaL_getmetafield' was leaving extra value on the stack 2003-03-18 15:48:31 -03:00
Roberto Ierusalimschy
ab9e062928 name changes to avoid name collision between macros and variables 2003-03-18 09:50:04 -03:00
Roberto Ierusalimschy
81cdbabf09 detail (change place of a prototype) 2003-03-18 09:31:39 -03:00
Roberto Ierusalimschy
40cfb0691e new auxiliary functions for `type' manipulation 2003-03-18 09:25:32 -03:00
Roberto Ierusalimschy
9b7af7e45b tests for Windows version 2003-03-18 09:25:01 -03:00
Roberto Ierusalimschy
2e66248f8a unused argument 2003-03-18 09:24:38 -03:00
Roberto Ierusalimschy
79db75101e detail 2003-03-18 09:24:26 -03:00
Roberto Ierusalimschy
b0c40e2405 first version of `loadlib' 2003-03-17 10:04:58 -03:00
Roberto Ierusalimschy
4734e2de05 `loadlib' now an official library 2003-03-17 10:01:48 -03:00
Roberto Ierusalimschy
7ea180af6e detail 2003-03-14 16:08:11 -03:00
Roberto Ierusalimschy
05d567d52e io.input'/io.output' always return current file 2003-03-14 16:00:16 -03:00
Roberto Ierusalimschy
d8a3a00d84 `string.find' also accepts out-of-range indices 2003-03-14 15:59:53 -03:00
Roberto Ierusalimschy
c9ea94ec92 out-of-bound upvalues (in C) are acceptable indices 2003-03-14 15:59:21 -03:00
Roberto Ierusalimschy
fa4b4c1100 loadstring/loadfile use global environment + setfenv(0) changes
global environment
2003-03-11 15:17:43 -03:00
Roberto Ierusalimschy
4039bf457d ^ operator is defined by global `__pow' 2003-03-11 09:30:37 -03:00
Roberto Ierusalimschy
034de1fe73 new names for functions that open C libraries 2003-03-11 09:24:34 -03:00
Roberto Ierusalimschy
430d6db928 LUA_PATH components may have multiple interrogation marks 2003-03-11 09:08:13 -03:00
Roberto Ierusalimschy
7c3857cded comments 2003-03-07 10:21:31 -03:00
Roberto Ierusalimschy
8ce6f0b418 avoid including system headers after program headers 2003-03-06 16:37:42 -03:00
Roberto Ierusalimschy
572bddc0b0 LUA_USETMPNAME -> USE_TMPNAME 2003-03-06 16:36:44 -03:00
Roberto Ierusalimschy
3684f67771 details (text of an error message) 2003-03-06 16:36:16 -03:00
Roberto Ierusalimschy
69dd9461e5 bug: GC metamethod calls could mess C/Lua stack syncronization 2003-02-28 16:45:15 -03:00
Roberto Ierusalimschy
6b6bc532a4 better error message for (deprecated) "%global" 2003-02-28 14:19:47 -03:00
Roberto Ierusalimschy
ea16ee41a8 no more attempt to optimize GC when parsing new modules (too complex) 2003-02-28 12:42:08 -03:00
Roberto Ierusalimschy
60d11ec316 by default, gcc does not get tmpname 2003-02-27 09:39:05 -03:00
Roberto Ierusalimschy
e1a424e8a3 avoid the identifier index' (clashes with BSD index' function) 2003-02-27 09:33:07 -03:00
Roberto Ierusalimschy
59ce42dbd5 detail 2003-02-27 09:32:30 -03:00
Roberto Ierusalimschy
92f6e0c1bf no-nonsense debug information about tail calls 2003-02-27 08:52:30 -03:00
Roberto Ierusalimschy
5cd99b82b7 set/getenvtable' -> set/getfenv' 2003-02-24 13:54:20 -03:00
Roberto Ierusalimschy
07e210e655 `require' returns value returned by package 2003-02-24 13:50:41 -03:00
Roberto Ierusalimschy
feb724c122 ULONG_MAX>>10 may not fit into an int (old bug) 2003-02-21 16:00:14 -03:00
Roberto Ierusalimschy
67f9a2a98f details 2003-02-20 17:12:39 -03:00
Roberto Ierusalimschy
c4f9c887fc expressions too complex for an ARM compiler... 2003-02-19 07:28:58 -03:00
Roberto Ierusalimschy
9866fb0ef1 set/getglobals' -> set/getenvtable' 2003-02-18 13:13:15 -03:00
Roberto Ierusalimschy
60c83ded30 small optimization for sizes of array constructors 2003-02-18 13:02:56 -03:00
Roberto Ierusalimschy
07948c3181 restore _REQUIREDNAME after requiring a file 2003-02-18 13:02:13 -03:00
Roberto Ierusalimschy
dce9a49a08 final version 2003-02-18 13:01:57 -03:00
Roberto Ierusalimschy
15db58a2f5 create arg table with correct size 2003-02-13 14:08:47 -02:00
Roberto Ierusalimschy
d6826dbc80 simpler way to count uses 2003-02-13 14:08:32 -02:00
Roberto Ierusalimschy
e75a6ae9ee `defaultmeta' is always empty, but registry needs some space for
names and numbers (references)
2003-02-13 14:07:57 -02:00
Roberto Ierusalimschy
2866fb2dd0 reset _REQUIREDNAME after loading module 2003-02-13 14:07:37 -02:00
Roberto Ierusalimschy
4b6f436d67 unpack' uses getn' to get table size 2003-02-12 07:11:01 -02:00
Roberto Ierusalimschy
8f105d6b59 string.byte returns nil if index is out-of-range 2003-02-12 07:10:41 -02:00
Roberto Ierusalimschy
2fef8c772b auxiliary function to check userdata with types 2003-02-11 13:32:31 -02:00
Roberto Ierusalimschy
7285fa393b use C names for C types 2003-02-11 13:31:50 -02:00
Roberto Ierusalimschy
5085f09ce5 small optimizations 2003-02-11 13:24:52 -02:00
Roberto Ierusalimschy
d674626392 compatibility with '%' syntax is optional 2003-02-11 08:49:53 -02:00
Roberto Ierusalimschy
7a40cdbda0 different variables for number of upvalues and size of upvalue array
(makes code clearer)
2003-02-11 08:46:24 -02:00
Roberto Ierusalimschy
3cdeacbbfb reference system also uses getn/setn (plus small corrections) 2003-02-11 07:44:38 -02:00
Roberto Ierusalimschy
6f207b15fb resist errors in finalizers during lua_close 2003-02-10 15:32:50 -02:00
Roberto Ierusalimschy
3184314bf3 warning 2003-02-10 15:31:13 -02:00
Roberto Ierusalimschy
7964f7cbbd more complete information for coroutine errors 2003-02-10 08:21:31 -02:00
Roberto Ierusalimschy
383a6e88f9 argv[0] may be NULL 2003-01-29 11:23:45 -02:00
Roberto Ierusalimschy
871166d7db test for panic function 2003-01-29 08:27:53 -02:00
Roberto Ierusalimschy
592cf2334e "panic" cannot happen in lua.c, with lua_cpcall +
argv[0] may be empty
2003-01-29 08:27:07 -02:00
Roberto Ierusalimschy
0175f8d5d1 dump/undump of upvalue names 2003-01-27 13:52:57 -02:00
Roberto Ierusalimschy
e79bf02f33 correct semantics for comparison metamethods (they are only valid
when both operands have the same metamethod).
2003-01-27 13:12:52 -02:00
Roberto Ierusalimschy
41ed3c4771 getn/setn in C moved to lauxlib 2003-01-27 11:46:16 -02:00
Roberto Ierusalimschy
635b7c707d details 2003-01-27 11:00:43 -02:00
Roberto Ierusalimschy
83f0d6ef1a DEPRECATED (new manual uses an independent format instead of LaTeX) 2003-01-24 14:38:18 -02:00
Roberto Ierusalimschy
3088ebd95b last changes before leaving Latex 2003-01-24 07:14:54 -02:00
Roberto Ierusalimschy
797d964df9 detail 2003-01-23 09:34:18 -02:00
Roberto Ierusalimschy
e44e579dc1 bug: luaD_protectedparser must protect its garbage collection too 2003-01-23 09:31:38 -02:00
Roberto Ierusalimschy
a153cafd8d starting translation to new format (@comand{...}). 2003-01-22 14:29:38 -02:00
Roberto Ierusalimschy
3b5158f2a1 corrections from Asko Kauppi 2003-01-21 15:45:11 -02:00
Roberto Ierusalimschy
60a8b94fd0 corrections/suggestions by Ed Ferguson 2003-01-20 09:03:05 -02:00
Roberto Ierusalimschy
c499442e5f compatibility macros must be available by default 2003-01-17 13:28:09 -02:00
Roberto Ierusalimschy
9a5bab82ff use the more modern _POSIX_C_SOURCE instead of older _POSIX_SOURCE 2003-01-17 13:27:28 -02:00
Roberto Ierusalimschy
32fd039bb5 `openlib' functions return new module 2002-12-20 08:26:33 -02:00
Roberto Ierusalimschy
75f73172c4 bug: `resume' was checking the wrong value for stack overflow 2002-12-20 07:55:56 -02:00
Roberto Ierusalimschy
754c630754 details 2002-12-19 11:21:08 -02:00
Roberto Ierusalimschy
dd8edecae1 new functions to manipulate upvales (get/setupvalue) 2002-12-19 09:11:55 -02:00
Roberto Ierusalimschy
28021c5c66 better explanation (+ example) for coroutines 2002-12-11 11:43:15 -02:00
Roberto Ierusalimschy
73517e86b0 OP_TFORLOOP uses extra stack space 2002-12-11 10:34:22 -02:00
Roberto Ierusalimschy
9e8face8d8 must move call results in the last iteration, too 2002-12-11 10:34:22 -02:00
Roberto Ierusalimschy
64864f094b new options for debugging Lua (HARDSTACKTESTS & EXTERNMEMCHECK) 2002-12-06 15:20:45 -02:00
Roberto Ierusalimschy
9bd3fc1039 TFORLOOP makes a call that affects all values above it on the stack 2002-12-06 15:15:35 -02:00
Roberto Ierusalimschy
cc4a22ebe2 bug: scope of generic for variables is not sound 2002-12-06 15:09:00 -02:00
Roberto Ierusalimschy
acf62ddfbe "load*" creates chunk with same global table than caller 2002-12-06 15:05:15 -02:00
Roberto Ierusalimschy
04f95ce879 hook counts are integers now 2002-12-05 15:50:10 -02:00
Roberto Ierusalimschy
27c6b4d422 each .c file defines its own name 2002-12-04 15:38:31 -02:00
Roberto Ierusalimschy
0bb8eb5151 new function `lua_cpcall' 2002-12-04 15:29:32 -02:00
Roberto Ierusalimschy
38da8c0d7d new facilities to test memory overflow in main.c 2002-12-04 15:29:05 -02:00
Roberto Ierusalimschy
76de732745 avoid non-raw accesses to globals when variable may not exist 2002-12-04 13:38:25 -02:00
Roberto Ierusalimschy
90d7892007 new function `io.type' 2002-12-04 13:27:17 -02:00
Roberto Ierusalimschy
041cb96992 small bug: `write' must return three values in case of errors 2002-12-04 13:17:36 -02:00
Roberto Ierusalimschy
c75c3cfd19 avoid names `str...' (may conflict with string.h) 2002-12-02 10:06:10 -02:00
Roberto Ierusalimschy
24471525d7 details 2002-12-02 10:06:10 -02:00
Roberto Ierusalimschy
1f55dbc699 details 2002-11-26 10:53:29 -02:00
Roberto Ierusalimschy
c194a46bc5 detail 2002-11-26 06:59:48 -02:00
Roberto Ierusalimschy
8954bdc706 new `coroutine.status' function 2002-11-26 06:45:36 -02:00
Roberto Ierusalimschy
5a228bb1d8 new function `lua_version' 2002-11-25 15:50:14 -02:00
Roberto Ierusalimschy
5f698f8b6f simpler interface to hooks + use of `int' to count hooks 2002-11-25 15:47:13 -02:00
Roberto Ierusalimschy
9b1c586b2f renaming stringdump' -> string.dump' 2002-11-25 15:33:33 -02:00
Roberto Ierusalimschy
d9340154ac `__tostring' for files + small bug (could do invalid read inside
a userdata when it was not a file)
2002-11-25 13:05:39 -02:00
Roberto Ierusalimschy
e47baca75a warnings from Visual C++ 2002-11-25 10:38:47 -02:00
Roberto Ierusalimschy
b8a680c114 resets hook count even in case of errors 2002-11-25 09:20:29 -02:00
Roberto Ierusalimschy
709b27b456 ULONG_MAX>>10 may not fit into an int 2002-11-25 09:16:48 -02:00
Roberto Ierusalimschy
dbc5451bea comments 2002-11-22 16:01:46 -02:00
Roberto Ierusalimschy
2d2d45976c separated control over C recursion level 2002-11-22 15:16:52 -02:00
Roberto Ierusalimschy
0050d983fc make more clear "primitive" recursive definitions 2002-11-22 14:42:53 -02:00
Roberto Ierusalimschy
04b143ddf9 avoid C stack overflow during parsing 2002-11-22 14:35:20 -02:00
Roberto Ierusalimschy
007f229568 detail 2002-11-22 11:59:04 -02:00
Roberto Ierusalimschy
84488c5670 small bug: previous call may change `base' 2002-11-21 15:19:42 -02:00
Roberto Ierusalimschy
5142e630bf new macro `condhardstacktests' to control hard stack tests 2002-11-21 15:19:11 -02:00
Roberto Ierusalimschy
010bbd9d9c simpler definition for incr_top 2002-11-21 14:46:16 -02:00
Roberto Ierusalimschy
be00cd2a6b easier way to keep `base' correct 2002-11-21 13:46:44 -02:00
Roberto Ierusalimschy
2e4e888de0 Lua functions must have a frame or a saved pc. 2002-11-21 13:46:20 -02:00
Roberto Ierusalimschy
ddc144e4d2 keep L->ci->base in L->base for faster access 2002-11-21 13:16:04 -02:00
Roberto Ierusalimschy
b48c6e7680 no problem keeping some dead meat while doing collection 2002-11-21 12:18:01 -02:00
Roberto Ierusalimschy
aff97fffc4 C functions cannot increase its top without filling the stack 2002-11-21 12:17:15 -02:00
Roberto Ierusalimschy
1648674653 must check GC every time it can create new objects 2002-11-21 12:16:52 -02:00
Roberto Ierusalimschy
d404f0c276 global_State must be deallocated (and so allocated) with NULL also
(otherwise it trys to decrement inside itself after its own free)
2002-11-21 12:14:42 -02:00
Roberto Ierusalimschy
48e42261ac details 2002-11-19 15:42:32 -02:00
Roberto Ierusalimschy
be762f38bd better organization of "malloc responsabilities" 2002-11-19 12:12:13 -02:00
Roberto Ierusalimschy
c8a79057f7 option -l does a require', instead of dofile' 2002-11-19 11:49:43 -02:00
Roberto Ierusalimschy
642af82e81 small bugs (state could keep its CI_HASFRAME attribute after returning) 2002-11-19 06:50:56 -02:00
Roberto Ierusalimschy
636c629e56 new assertions 2002-11-18 16:45:38 -02:00
Roberto Ierusalimschy
96ba5d0bc2 include file name in error messages 2002-11-18 14:53:19 -02:00
Roberto Ierusalimschy
f0185f7628 support for tests of yield inside hooks + better support for tests
with valgrind and other memory checkers
2002-11-18 13:24:27 -02:00
Roberto Ierusalimschy
9bab2cf55d support for yield inside hooks 2002-11-18 13:24:11 -02:00
Roberto Ierusalimschy
c4ae00a3d1 details 2002-11-18 13:23:43 -02:00
Roberto Ierusalimschy
f4d3bc52f4 towards 5.0 beta 2002-11-18 12:39:34 -02:00
Roberto Ierusalimschy
18765d900e messages 2002-11-18 09:20:01 -02:00
Roberto Ierusalimschy
43013b39cc new representation for hooks (to allow asynchronous calls to sethook) 2002-11-18 09:01:55 -02:00
Roberto Ierusalimschy
94912d99fc details 2002-11-14 14:59:16 -02:00
Roberto Ierusalimschy
b40c9f7a3c better code to signal write barriers 2002-11-14 14:16:21 -02:00
Roberto Ierusalimschy
41fd639cab documentation for write barriers 2002-11-14 14:15:53 -02:00
Roberto Ierusalimschy
a845a46cc8 C function may leave garbage on the stack (besides return values) 2002-11-14 13:42:05 -02:00
Roberto Ierusalimschy
097edd3884 better names for auxiliar functions 2002-11-14 13:41:38 -02:00
Roberto Ierusalimschy
5c5d9b2703 back to `__mode' metafield to specify weakness 2002-11-14 10:01:35 -02:00
Roberto Ierusalimschy
43d1a6af12 detail 2002-11-14 09:51:23 -02:00
Roberto Ierusalimschy
3010eb0536 all objects with several children (tables, closures, stacks, prototypes)
go to `gray' queue
2002-11-13 09:49:19 -02:00
Roberto Ierusalimschy
2f91f95d94 better control over GCObjects 2002-11-13 09:32:26 -02:00
Roberto Ierusalimschy
42dd080a2e details 2002-11-12 12:34:18 -02:00
Roberto Ierusalimschy
9957f7d598 better way to open libraries 2002-11-11 11:28:06 -02:00
Roberto Ierusalimschy
ac27b7a842 avoid traversing extra elements when cleaning weak tables 2002-11-11 09:52:43 -02:00
Roberto Ierusalimschy
81e142fc14 detail (`key' is always on stack) 2002-11-07 14:03:33 -02:00
Roberto Ierusalimschy
63633c5b5f better name for `lua_movethread' 2002-11-07 13:39:23 -02:00
Roberto Ierusalimschy
dff9be4224 new macros to distinguish different types of object moves (for future GC
evolution).
2002-11-07 13:37:10 -02:00
Roberto Ierusalimschy
118347d8c3 new API for coroutines 2002-11-06 17:08:00 -02:00
Roberto Ierusalimschy
6820da5096 detail 2002-11-04 10:31:44 -02:00
Roberto Ierusalimschy
c3eb4675b9 new module, ldump.c 2002-10-25 18:38:17 -03:00
Roberto Ierusalimschy
7e0f880bc5 C++ demands cast from void to specific types 2002-10-25 18:36:54 -03:00
Roberto Ierusalimschy
118e9cd843 new facility for dumping chunks 2002-10-25 18:31:28 -03:00
Roberto Ierusalimschy
de00d0d0ad module for dumping chunks 2002-10-25 18:31:28 -03:00
Roberto Ierusalimschy
1713b64065 Writer type must be public (so, in lua.h) 2002-10-25 18:30:49 -03:00
Roberto Ierusalimschy
671dc6eec2 new version (from lhf) 2002-10-25 18:30:41 -03:00
Roberto Ierusalimschy
e356a43dc0 C needs "union" (unlike C++) 2002-10-25 18:30:00 -03:00
Roberto Ierusalimschy
f36038e42a assertion must be always valid (not only in debug mode) 2002-10-25 18:29:20 -03:00
Roberto Ierusalimschy
96e15b8501 threads now are real Lua objects, subject to garbage collection 2002-10-25 17:05:28 -03:00
Roberto Ierusalimschy
0fd91b1b08 optional limits for table.concat 2002-10-23 16:08:23 -03:00
Roberto Ierusalimschy
a2b353e044 details 2002-10-23 16:08:13 -03:00
Roberto Ierusalimschy
92a2ef9dca field `__globals' protect global tables 2002-10-22 16:41:08 -03:00
Roberto Ierusalimschy
4fb9110a6e tests for compatibility functions lua_dostring/lua_dofile 2002-10-22 15:07:55 -03:00
Roberto Ierusalimschy
11886dc7b0 print error on stderr when _ALERT is not defined 2002-10-22 15:07:55 -03:00
Roberto Ierusalimschy
81bc5711a8 only one instance of registry and default metatable per global state 2002-10-22 14:58:14 -03:00
Roberto Ierusalimschy
6a77a6b73f avoid too much precision when printing numbers 2002-10-22 14:21:25 -03:00
Roberto Ierusalimschy
84e0b1bc97 small changes in type configuration facilities 2002-10-22 14:18:28 -03:00
Roberto Ierusalimschy
6823a2f57f better tokens for error messages 2002-10-22 13:45:52 -03:00
Roberto Ierusalimschy
313b2fe902 detail 2002-10-21 17:43:38 -03:00
Roberto Ierusalimschy
425e5813b0 free prototype in (more or less) the same order it is created by
`undump'
2002-10-21 17:41:46 -03:00
Roberto Ierusalimschy
6505503b49 do not pretend that file is closed when close fails 2002-10-21 17:41:24 -03:00
Roberto Ierusalimschy
ec748fcb0a correct handling of opened files in presence of memory allocation
errors
2002-10-16 17:41:35 -03:00
Roberto Ierusalimschy
c196348717 in case of memory allocation errors, sizecode and sizelineinfo can
be different
2002-10-16 17:40:58 -03:00
Roberto Ierusalimschy
669129a6d8 io.lines() iterate over the standard input file 2002-10-11 17:40:32 -03:00
Roberto Ierusalimschy
46b063ef59 `undump' also uses private buffer 2002-10-09 10:42:01 -03:00
Roberto Ierusalimschy
e1d5153a33 details 2002-10-09 10:00:08 -03:00
Roberto Ierusalimschy
b3d0682fb9 use of different buffers for scanner and concatenation 2002-10-08 15:46:08 -03:00
Roberto Ierusalimschy
02afc892d5 new ANSI C does not assure that realloc(p,0) == free(p) 2002-10-08 15:45:07 -03:00
Roberto Ierusalimschy
fa2f1ec7ba to avoid `strerror', define itself to something else;
nil has a special, fixed reference
2002-10-04 11:31:40 -03:00
Roberto Ierusalimschy
829befcc41 small optimization for object comparison 2002-10-04 11:31:03 -03:00
Roberto Ierusalimschy
d477e4ffd6 detail 2002-10-04 11:30:31 -03:00
Roberto Ierusalimschy
ce09af1e25 easier to define api_check' using assert' 2002-09-20 14:01:24 -03:00
Roberto Ierusalimschy
98d0b79613 EXIT_SUCCESS may be different from 0 2002-09-20 10:32:56 -03:00
Roberto Ierusalimschy
e8f35fc4ff unification of __index & __gettable (and __newindex & __settable) 2002-09-19 17:12:47 -03:00
Roberto Ierusalimschy
6fb0fd5063 avoid `reclearing' weak tables 2002-09-19 16:54:22 -03:00
Roberto Ierusalimschy
565e6d74e1 state's buffer is used only for chars 2002-09-19 10:03:53 -03:00
Roberto Ierusalimschy
f6bc7884be new generators for reading a file line by line 2002-09-17 17:35:54 -03:00
Roberto Ierusalimschy
32a5d96dfc `setmetatable' cannot change protected objects 2002-09-16 16:49:45 -03:00
Roberto Ierusalimschy
8dae071f42 details 2002-09-16 16:18:01 -03:00
Roberto Ierusalimschy
afe1305b1a avoid luaS_resize (which may need extra memory) during `main' activities 2002-09-05 16:57:40 -03:00
Roberto Ierusalimschy
728fa167d2 cannot raise memory error when realloc to smaller block 2002-09-05 16:57:08 -03:00
Roberto Ierusalimschy
1bdde38bd2 no more newlines at the end of error messages 2002-09-05 16:45:42 -03:00
Roberto Ierusalimschy
b2bc3b44b6 no more reserved word "global" 2002-09-03 08:57:38 -03:00
Roberto Ierusalimschy
7c0ccdfd61 avoid the use of "enum" in the API, as they do not have a fixed representation 2002-09-02 17:00:41 -03:00
Roberto Ierusalimschy
4964e7c8a0 details 2002-09-02 16:54:49 -03:00
Roberto Ierusalimschy
2c670baf24 avoid the use of "obvious" names in header files to avoid conflicts 2002-08-30 17:00:59 -03:00
Roberto Ierusalimschy
fdafd4f4a8 new structure for collectable objects, sharing a common header 2002-08-30 16:09:21 -03:00
Roberto Ierusalimschy
beeff4ccaf GC metamethod stored in a weak metatable being collected together with
userdata may not be cleared properly
2002-08-30 16:08:30 -03:00
Roberto Ierusalimschy
12c4e48506 `frontier' patterns 2002-08-23 16:45:24 -03:00
Roberto Ierusalimschy
c78aaa9a70 better line number for function definitions 2002-08-22 16:51:08 -03:00
Roberto Ierusalimschy
4d7a554921 style for switch statements 2002-08-21 16:39:31 -03:00
Roberto Ierusalimschy
fbc23d0245 details 2002-08-21 15:56:33 -03:00
Roberto Ierusalimschy
81a8845e4f detail 2002-08-21 11:57:48 -03:00
Roberto Ierusalimschy
6c283b2f4f new simetric format for ABC instructions, to avoid exchanging operands
for `commutative' operators
2002-08-20 17:03:05 -03:00
Roberto Ierusalimschy
576bded513 details 2002-08-16 17:02:13 -03:00
Roberto Ierusalimschy
ecc7769de2 names... 2002-08-16 17:00:28 -03:00
Roberto Ierusalimschy
da19c436cc cleaning the stage for generational collection 2002-08-16 11:45:55 -03:00
Roberto Ierusalimschy
0039feb9da warning from Visual C 2002-08-16 11:45:18 -03:00
53 changed files with 4122 additions and 6937 deletions

48
bugs
View File

@@ -286,3 +286,51 @@ Wed Jun 19 13:31:49 EST 2002
>> (in function `parse_file')
(by Alex Bilyk; since 4.0)
=================================================================
--- Version 5.0 alpha
** lgc.c
Fri Aug 30 13:49:14 EST 2002
>> GC metamethod stored in a weak metatable being collected together with
>> userdata may not be cleared properly
(by Roberto; since 5.0a)
** lapi.c
Thu Nov 21 11:00:00 EST 2002
>> ULONG_MAX>>10 may not fit into an int
(by Jeff Petkau; since 4.0)
** lparser.c
Fri Dec 6 17:06:40 UTC 2002
>> scope of generic for variables is not sound
(by Gavin Wraith; since 5.0a)
=================================================================
--- Version 5.0 beta
** lbaselib.c
Fri Dec 20 09:53:19 UTC 2002
>> `resume' was checking the wrong value for stack overflow
(by Maik Zimmermann; since 5.0b)
** ldo.c
Thu Jan 23 11:29:06 UTC 2003
>> error during garbage collection in luaD_protectedparser is not being
>> protected
(by Benoit Germain; since 5.0a)
** ldo.c (and others)
Fri Feb 28 14:20:33 EST 2003
>> GC metamethod calls could mess C/Lua stack syncronization
(by Roberto; since 5.0b)
** lzio.h/zlio.c
Thu Mar 20 11:40:12 EST 2003
>> zio mixes a 255 as first char in a buffer with EOZ
(by lhf; since 5.0a)

445
lapi.c
View File

@@ -1,12 +1,15 @@
/*
** $Id: lapi.c,v 1.210 2002/08/07 14:24:24 roberto Exp roberto $
** $Id: lapi.c,v 1.234 2003/04/03 13:35:34 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
#include <assert.h>
#include <string.h>
#define lapi_c
#include "lua.h"
#include "lapi.h"
@@ -32,54 +35,63 @@ const char lua_ident[] =
#ifndef api_check
#define api_check(L, o) ((void)1)
#define api_check(L, o) /*{ assert(o); }*/
#endif
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->ci->base))
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
#define api_incr_top(L) (api_check(L, L->top<L->ci->top), L->top++)
#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
static TObject *negindex (lua_State *L, int index) {
if (index > LUA_REGISTRYINDEX) {
api_check(L, index != 0 && -index <= L->top - L->ci->base);
return L->top+index;
static TObject *negindex (lua_State *L, int idx) {
if (idx > LUA_REGISTRYINDEX) {
api_check(L, idx != 0 && -idx <= L->top - L->base);
return L->top+idx;
}
else switch (index) { /* pseudo-indices */
else switch (idx) { /* pseudo-indices */
case LUA_REGISTRYINDEX: return registry(L);
case LUA_GLOBALSINDEX: return gt(L);
default: {
TObject *func = (L->ci->base - 1);
index = LUA_GLOBALSINDEX - index;
api_check(L, iscfunction(func) && index <= clvalue(func)->c.nupvalues);
return &clvalue(func)->c.upvalue[index-1];
TObject *func = (L->base - 1);
idx = LUA_GLOBALSINDEX - idx;
lua_assert(iscfunction(func));
return (idx <= clvalue(func)->c.nupvalues)
? &clvalue(func)->c.upvalue[idx-1]
: NULL;
}
}
}
#define luaA_index(L, index) \
( (index > 0) ? \
(api_check(L, index <= L->top - L->ci->base), L->ci->base+index-1) : \
negindex(L, index))
static TObject *luaA_index (lua_State *L, int idx) {
if (idx > 0) {
api_check(L, idx <= L->top - L->base);
return L->base + idx - 1;
}
else {
TObject *o = negindex(L, idx);
api_check(L, o != NULL);
return o;
}
}
static TObject *luaA_indexAcceptable (lua_State *L, int index) {
if (index > 0) {
TObject *o = L->ci->base+(index-1);
api_check(L, index <= L->stack_last - L->ci->base);
static TObject *luaA_indexAcceptable (lua_State *L, int idx) {
if (idx > 0) {
TObject *o = L->base+(idx-1);
api_check(L, idx <= L->stack_last - L->base);
if (o >= L->top) return NULL;
else return o;
}
else
return negindex(L, index);
return negindex(L, idx);
}
void luaA_pushobject (lua_State *L, const TObject *o) {
setobj(L->top, o);
setobj2s(L->top, o);
incr_top(L);
}
@@ -87,7 +99,7 @@ void luaA_pushobject (lua_State *L, const TObject *o) {
LUA_API int lua_checkstack (lua_State *L, int size) {
int res;
lua_lock(L);
if ((L->top - L->ci->base + size) > LUA_MAXCSTACK)
if ((L->top - L->base + size) > LUA_MAXCSTACK)
res = 0; /* stack overflow */
else {
luaD_checkstack(L, size);
@@ -100,6 +112,19 @@ LUA_API int lua_checkstack (lua_State *L, int size) {
}
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
int i;
lua_lock(to);
api_checknelems(from, n);
from->top -= n;
for (i = 0; i < n; i++) {
setobj2s(to->top, from->top + i);
api_incr_top(to);
}
lua_unlock(to);
}
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
lua_CFunction old;
lua_lock(L);
@@ -110,65 +135,79 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
}
LUA_API lua_State *lua_newthread (lua_State *L) {
lua_State *L1;
lua_lock(L);
luaC_checkGC(L);
L1 = luaE_newthread(L);
setthvalue(L->top, L1);
api_incr_top(L);
lua_unlock(L);
lua_userstateopen(L1);
return L1;
}
/*
** basic stack manipulation
*/
LUA_API int lua_gettop (lua_State *L) {
return (L->top - L->ci->base);
return (L->top - L->base);
}
LUA_API void lua_settop (lua_State *L, int index) {
LUA_API void lua_settop (lua_State *L, int idx) {
lua_lock(L);
if (index >= 0) {
api_check(L, index <= L->stack_last - L->ci->base);
while (L->top < L->ci->base + index)
if (idx >= 0) {
api_check(L, idx <= L->stack_last - L->base);
while (L->top < L->base + idx)
setnilvalue(L->top++);
L->top = L->ci->base + index;
L->top = L->base + idx;
}
else {
api_check(L, -(index+1) <= (L->top - L->ci->base));
L->top += index+1; /* `subtract' index (index is negative) */
api_check(L, -(idx+1) <= (L->top - L->base));
L->top += idx+1; /* `subtract' index (index is negative) */
}
lua_unlock(L);
}
LUA_API void lua_remove (lua_State *L, int index) {
LUA_API void lua_remove (lua_State *L, int idx) {
StkId p;
lua_lock(L);
p = luaA_index(L, index);
while (++p < L->top) setobj(p-1, p);
p = luaA_index(L, idx);
while (++p < L->top) setobjs2s(p-1, p);
L->top--;
lua_unlock(L);
}
LUA_API void lua_insert (lua_State *L, int index) {
LUA_API void lua_insert (lua_State *L, int idx) {
StkId p;
StkId q;
lua_lock(L);
p = luaA_index(L, index);
for (q = L->top; q>p; q--) setobj(q, q-1);
setobj(p, L->top);
p = luaA_index(L, idx);
for (q = L->top; q>p; q--) setobjs2s(q, q-1);
setobjs2s(p, L->top);
lua_unlock(L);
}
LUA_API void lua_replace (lua_State *L, int index) {
LUA_API void lua_replace (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 1);
setobj(luaA_index(L, index), L->top - 1);
setobj(luaA_index(L, idx), L->top - 1); /* write barrier */
L->top--;
lua_unlock(L);
}
LUA_API void lua_pushvalue (lua_State *L, int index) {
LUA_API void lua_pushvalue (lua_State *L, int idx) {
lua_lock(L);
setobj(L->top, luaA_index(L, index));
setobj2s(L->top, luaA_index(L, idx));
api_incr_top(L);
lua_unlock(L);
}
@@ -180,8 +219,8 @@ LUA_API void lua_pushvalue (lua_State *L, int index) {
*/
LUA_API int lua_type (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API int lua_type (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
return (o == NULL) ? LUA_TNONE : ttype(o);
}
@@ -192,25 +231,31 @@ LUA_API const char *lua_typename (lua_State *L, int t) {
}
LUA_API int lua_iscfunction (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API int lua_iscfunction (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
return (o == NULL) ? 0 : iscfunction(o);
}
LUA_API int lua_isnumber (lua_State *L, int index) {
LUA_API int lua_isnumber (lua_State *L, int idx) {
TObject n;
const TObject *o = luaA_indexAcceptable(L, index);
const TObject *o = luaA_indexAcceptable(L, idx);
return (o != NULL && tonumber(o, &n));
}
LUA_API int lua_isstring (lua_State *L, int index) {
int t = lua_type(L, index);
LUA_API int lua_isstring (lua_State *L, int idx) {
int t = lua_type(L, idx);
return (t == LUA_TSTRING || t == LUA_TNUMBER);
}
LUA_API int lua_isuserdata (lua_State *L, int idx) {
const TObject *o = luaA_indexAcceptable(L, idx);
return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
}
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
StkId o1 = luaA_indexAcceptable(L, index1);
StkId o2 = luaA_indexAcceptable(L, index2);
@@ -246,9 +291,9 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
LUA_API lua_Number lua_tonumber (lua_State *L, int index) {
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
TObject n;
const TObject *o = luaA_indexAcceptable(L, index);
const TObject *o = luaA_indexAcceptable(L, idx);
if (o != NULL && tonumber(o, &n))
return nvalue(o);
else
@@ -256,14 +301,14 @@ LUA_API lua_Number lua_tonumber (lua_State *L, int index) {
}
LUA_API int lua_toboolean (lua_State *L, int index) {
const TObject *o = luaA_indexAcceptable(L, index);
LUA_API int lua_toboolean (lua_State *L, int idx) {
const TObject *o = luaA_indexAcceptable(L, idx);
return (o != NULL) && !l_isfalse(o);
}
LUA_API const char *lua_tostring (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API const char *lua_tostring (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
if (o == NULL)
return NULL;
else if (ttisstring(o))
@@ -272,14 +317,15 @@ LUA_API const char *lua_tostring (lua_State *L, int index) {
const char *s;
lua_lock(L); /* `luaV_tostring' may create a new string */
s = (luaV_tostring(L, o) ? svalue(o) : NULL);
luaC_checkGC(L);
lua_unlock(L);
return s;
}
}
LUA_API size_t lua_strlen (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API size_t lua_strlen (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
if (o == NULL)
return 0;
else if (ttisstring(o))
@@ -294,14 +340,14 @@ LUA_API size_t lua_strlen (lua_State *L, int index) {
}
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
}
LUA_API void *lua_touserdata (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API void *lua_touserdata (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
if (o == NULL) return NULL;
switch (ttype(o)) {
case LUA_TUSERDATA: return (uvalue(o) + 1);
@@ -311,16 +357,23 @@ LUA_API void *lua_touserdata (lua_State *L, int index) {
}
LUA_API const void *lua_topointer (lua_State *L, int index) {
StkId o = luaA_indexAcceptable(L, index);
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
}
LUA_API const void *lua_topointer (lua_State *L, int idx) {
StkId o = luaA_indexAcceptable(L, idx);
if (o == NULL) return NULL;
else {
switch (ttype(o)) {
case LUA_TTABLE: return hvalue(o);
case LUA_TFUNCTION: return clvalue(o);
case LUA_TTHREAD: return thvalue(o);
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
return lua_touserdata(L, index);
return lua_touserdata(L, idx);
default: return NULL;
}
}
@@ -351,7 +404,8 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
lua_lock(L);
setsvalue(L->top, luaS_newlstr(L, s, len));
luaC_checkGC(L);
setsvalue2s(L->top, luaS_newlstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
@@ -369,6 +423,7 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
va_list argp) {
const char *ret;
lua_lock(L);
luaC_checkGC(L);
ret = luaO_pushvfstring(L, fmt, argp);
lua_unlock(L);
return ret;
@@ -379,6 +434,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
const char *ret;
va_list argp;
lua_lock(L);
luaC_checkGC(L);
va_start(argp, fmt);
ret = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
@@ -390,12 +446,13 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
Closure *cl;
lua_lock(L);
luaC_checkGC(L);
api_checknelems(L, n);
cl = luaF_newCclosure(L, n);
cl->c.f = fn;
L->top -= n;
while (n--)
setobj(&cl->c.upvalue[n], L->top+n);
setobj2n(&cl->c.upvalue[n], L->top+n);
setclvalue(L->top, cl);
api_incr_top(L);
lua_unlock(L);
@@ -424,33 +481,31 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
*/
LUA_API void lua_gettable (lua_State *L, int index) {
LUA_API void lua_gettable (lua_State *L, int idx) {
StkId t;
const TObject *v;
lua_lock(L);
t = luaA_index(L, index);
v = luaV_gettable(L, t, L->top-1, 0);
setobj(L->top - 1, v);
t = luaA_index(L, idx);
setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
lua_unlock(L);
}
LUA_API void lua_rawget (lua_State *L, int index) {
LUA_API void lua_rawget (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = luaA_index(L, index);
t = luaA_index(L, idx);
api_check(L, ttistable(t));
setobj(L->top - 1, luaH_get(hvalue(t), L->top - 1));
setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
}
LUA_API void lua_rawgeti (lua_State *L, int index, int n) {
LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
StkId o;
lua_lock(L);
o = luaA_index(L, index);
o = luaA_index(L, idx);
api_check(L, ttistable(o));
setobj(L->top, luaH_getnum(hvalue(o), n));
setobj2s(L->top, luaH_getnum(hvalue(o), n));
api_incr_top(L);
lua_unlock(L);
}
@@ -458,43 +513,30 @@ LUA_API void lua_rawgeti (lua_State *L, int index, int n) {
LUA_API void lua_newtable (lua_State *L) {
lua_lock(L);
luaC_checkGC(L);
sethvalue(L->top, luaH_new(L, 0, 0));
api_incr_top(L);
lua_unlock(L);
}
LUA_API const char *lua_getmode (lua_State *L, int index) {
static const char *const modes[] = {"", "k", "v", "kv"};
int mode = 0;
TObject *t;
lua_lock(L);
t = luaA_index(L, index);
api_check(L, ttistable(t));
if (hvalue(t)->mode & WEAKKEY) mode += 1;
if (hvalue(t)->mode & WEAKVALUE) mode += 2;
lua_unlock(L);
return modes[mode];
}
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
StkId obj;
Table *mt;
const TObject *obj;
Table *mt = NULL;
int res;
lua_lock(L);
obj = luaA_indexAcceptable(L, objindex);
switch (ttype(obj)) {
case LUA_TTABLE:
mt = hvalue(obj)->metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(obj)->uv.metatable;
break;
default:
mt = hvalue(defaultmeta(L));
if (obj != NULL) {
switch (ttype(obj)) {
case LUA_TTABLE:
mt = hvalue(obj)->metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(obj)->uv.metatable;
break;
}
}
if (mt == hvalue(defaultmeta(L)))
if (mt == NULL || mt == hvalue(defaultmeta(L)))
res = 0;
else {
sethvalue(L->top, mt);
@@ -506,11 +548,11 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
}
LUA_API void lua_getglobals (lua_State *L, int index) {
LUA_API void lua_getfenv (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = luaA_index(L, index);
setobj(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
o = luaA_index(L, idx);
setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
api_incr_top(L);
lua_unlock(L);
}
@@ -521,52 +563,41 @@ LUA_API void lua_getglobals (lua_State *L, int index) {
*/
LUA_API void lua_settable (lua_State *L, int index) {
LUA_API void lua_settable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
t = luaA_index(L, index);
t = luaA_index(L, idx);
luaV_settable(L, t, L->top - 2, L->top - 1);
L->top -= 2; /* pop index and value */
lua_unlock(L);
}
LUA_API void lua_rawset (lua_State *L, int index) {
LUA_API void lua_rawset (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
t = luaA_index(L, index);
t = luaA_index(L, idx);
api_check(L, ttistable(t));
setobj(luaH_set(L, hvalue(t), L->top-2), L->top-1);
setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */
L->top -= 2;
lua_unlock(L);
}
LUA_API void lua_rawseti (lua_State *L, int index, int n) {
LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
StkId o;
lua_lock(L);
api_checknelems(L, 1);
o = luaA_index(L, index);
o = luaA_index(L, idx);
api_check(L, ttistable(o));
setobj(luaH_setnum(L, hvalue(o), n), L->top-1);
setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */
L->top--;
lua_unlock(L);
}
LUA_API void lua_setmode (lua_State *L, int index, const char *mode) {
TObject *t;
lua_lock(L);
t = luaA_index(L, index);
api_check(L, ttistable(t));
hvalue(t)->mode &= ~(WEAKKEY | WEAKVALUE); /* clear bits */
if (strchr(mode, 'k')) hvalue(t)->mode |= WEAKKEY;
if (strchr(mode, 'v')) hvalue(t)->mode |= WEAKVALUE;
lua_unlock(L);
}
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
TObject *obj, *mt;
int res = 1;
@@ -577,11 +608,11 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
api_check(L, ttistable(mt));
switch (ttype(obj)) {
case LUA_TTABLE: {
hvalue(obj)->metatable = hvalue(mt);
hvalue(obj)->metatable = hvalue(mt); /* write barrier */
break;
}
case LUA_TUSERDATA: {
uvalue(obj)->uv.metatable = hvalue(mt);
uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */
break;
}
default: {
@@ -595,12 +626,12 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
}
LUA_API int lua_setglobals (lua_State *L, int index) {
LUA_API int lua_setfenv (lua_State *L, int idx) {
StkId o;
int res = 0;
lua_lock(L);
api_checknelems(L, 1);
o = luaA_index(L, index);
o = luaA_index(L, idx);
L->top--;
api_check(L, ttistable(L->top));
if (isLfunction(o)) {
@@ -626,12 +657,66 @@ LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
}
/*
** Execute a protected call.
*/
struct CallS { /* data to `f_call' */
StkId func;
int nresults;
};
static void f_call (lua_State *L, void *ud) {
struct CallS *c = cast(struct CallS *, ud);
luaD_call(L, c->func, c->nresults);
}
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
struct CallS c;
int status;
ptrdiff_t func;
lua_lock(L);
func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
status = luaD_pcall(L, nargs, nresults, func);
c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
lua_unlock(L);
return status;
}
/*
** Execute a protected C call.
*/
struct CCallS { /* data to `f_Ccall' */
lua_CFunction func;
void *ud;
};
static void f_Ccall (lua_State *L, void *ud) {
struct CCallS *c = cast(struct CCallS *, ud);
Closure *cl;
cl = luaF_newCclosure(L, 0);
cl->c.f = c->func;
setclvalue(L->top, cl); /* push function */
incr_top(L);
setpvalue(L->top, c->ud); /* push only argument */
incr_top(L);
luaD_call(L, L->top - 2, 0);
}
LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
struct CCallS c;
int status;
lua_lock(L);
c.func = func;
c.ud = ud;
status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
lua_unlock(L);
return status;
}
@@ -652,13 +737,31 @@ LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
}
LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
int status;
TObject *o;
lua_lock(L);
api_checknelems(L, 1);
o = L->top - 1;
if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
luaU_dump(L, clvalue(o)->l.p, writer, data);
status = 1;
}
else
status = 0;
lua_unlock(L);
return status;
}
/*
** Garbage-collection functions
*/
/* GC values are expressed in Kbytes: #bytes/2^10 */
#define GCscale(x) (cast(int, (x)>>10))
#define GCunscale(x) (cast(lu_mem, (x)<<10))
#define GCscalel(x) ((x)>>10)
#define GCscale(x) (cast(int, GCscalel(x)))
#define GCunscale(x) (cast(lu_mem, x)<<10)
LUA_API int lua_getgcthreshold (lua_State *L) {
int threshold;
@@ -678,8 +781,8 @@ LUA_API int lua_getgccount (lua_State *L) {
LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
lua_lock(L);
if (newthreshold > GCscale(ULONG_MAX))
G(L)->GCthreshold = ULONG_MAX;
if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
G(L)->GCthreshold = MAX_LUMEM;
else
G(L)->GCthreshold = GCunscale(newthreshold);
luaC_checkGC(L);
@@ -692,6 +795,11 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
*/
LUA_API const char *lua_version (void) {
return LUA_VERSION;
}
LUA_API int lua_error (lua_State *L) {
lua_lock(L);
api_checknelems(L, 1);
@@ -701,11 +809,11 @@ LUA_API int lua_error (lua_State *L) {
}
LUA_API int lua_next (lua_State *L, int index) {
LUA_API int lua_next (lua_State *L, int idx) {
StkId t;
int more;
lua_lock(L);
t = luaA_index(L, index);
t = luaA_index(L, idx);
api_check(L, ttistable(t));
more = luaH_next(L, hvalue(t), L->top - 1);
if (more) {
@@ -720,14 +828,14 @@ LUA_API int lua_next (lua_State *L, int index) {
LUA_API void lua_concat (lua_State *L, int n) {
lua_lock(L);
luaC_checkGC(L);
api_checknelems(L, n);
if (n >= 2) {
luaV_concat(L, n, L->top - L->ci->base - 1);
luaV_concat(L, n, L->top - L->base - 1);
L->top -= (n-1);
luaC_checkGC(L);
}
else if (n == 0) { /* push empty string */
setsvalue(L->top, luaS_newlstr(L, NULL, 0));
setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
api_incr_top(L);
}
/* else n == 1; nothing to do */
@@ -738,6 +846,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
Udata *u;
lua_lock(L);
luaC_checkGC(L);
u = luaS_newudata(L, size);
setuvalue(L->top, u);
api_incr_top(L);
@@ -750,12 +859,12 @@ LUA_API int lua_pushupvalues (lua_State *L) {
Closure *func;
int n, i;
lua_lock(L);
api_check(L, iscfunction(L->ci->base - 1));
func = clvalue(L->ci->base - 1);
api_check(L, iscfunction(L->base - 1));
func = clvalue(L->base - 1);
n = func->c.nupvalues;
luaD_checkstack(L, n + LUA_MINSTACK);
for (i=0; i<n; i++) {
setobj(L->top, &func->c.upvalue[i]);
setobj2s(L->top, &func->c.upvalue[i]);
L->top++;
}
lua_unlock(L);
@@ -763,3 +872,51 @@ LUA_API int lua_pushupvalues (lua_State *L) {
}
static const char *aux_upvalue (lua_State *L, int funcindex, int n,
TObject **val) {
Closure *f;
StkId fi = luaA_index(L, funcindex);
if (!ttisfunction(fi)) return NULL;
f = clvalue(fi);
if (f->c.isC) {
if (n > f->c.nupvalues) return NULL;
*val = &f->c.upvalue[n-1];
return "";
}
else {
Proto *p = f->l.p;
if (n > p->sizeupvalues) return NULL;
*val = f->l.upvals[n-1]->v;
return getstr(p->upvalues[n-1]);
}
}
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
const char *name;
TObject *val;
lua_lock(L);
name = aux_upvalue(L, funcindex, n, &val);
if (name) {
setobj2s(L->top, val);
api_incr_top(L);
}
lua_unlock(L);
return name;
}
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
const char *name;
TObject *val;
lua_lock(L);
api_checknelems(L, 1);
name = aux_upvalue(L, funcindex, n, &val);
if (name) {
L->top--;
setobj(val, L->top); /* write barrier */
}
lua_unlock(L);
return name;
}

297
lauxlib.c
View File

@@ -1,30 +1,41 @@
/*
** $Id: lauxlib.c,v 1.82 2002/08/06 18:01:50 roberto Exp roberto $
** $Id: lauxlib.c,v 1.99 2003/04/03 13:35:34 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#ifndef lua_filerror
#include <errno.h>
#define lua_fileerror (strerror(errno))
#endif
/* This file uses only the official API of Lua.
** Any function declared here could be written as an application function.
*/
#define lauxlib_c
#include "lua.h"
#include "lauxlib.h"
/* number of prereserved references (for internal use) */
#define RESERVED_REFS 2
/* reserved references */
#define FREELIST_REF 1 /* free list of references */
#define ARRAYSIZE_REF 2 /* array sizes */
/* convert a stack index to positive */
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
lua_gettop(L) + (i) + 1)
/*
** {======================================================
** Error-report functions
@@ -39,9 +50,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
if (strcmp(ar.namewhat, "method") == 0) {
narg--; /* do not count `self' */
if (narg == 0) /* error is in the self argument itself? */
return luaL_error(L,
"calling %s on bad self (perhaps using `:' instead of `.')",
ar.name);
return luaL_error(L, "calling `%s' on bad self (%s)", ar.name, extramsg);
}
if (ar.name == NULL)
ar.name = "?";
@@ -81,8 +90,7 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
va_end(argp);
lua_pushliteral(L, "\n");
lua_concat(L, 3);
lua_concat(L, 2);
return lua_error(L);
}
@@ -98,25 +106,64 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
}
LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) {
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
lua_pushstring(L, tname);
lua_rawget(L, LUA_REGISTRYINDEX); /* get registry.name */
if (!lua_isnil(L, -1)) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
lua_newtable(L); /* create metatable */
lua_pushstring(L, tname);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */
lua_pushvalue(L, -1);
lua_pushstring(L, tname);
lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */
return 1;
}
LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) {
lua_pushstring(L, tname);
lua_rawget(L, LUA_REGISTRYINDEX);
}
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
const char *tn;
if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */
lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */
tn = lua_tostring(L, -1);
if (tn && (strcmp(tn, tname) == 0)) {
lua_pop(L, 1);
return lua_touserdata(L, ud);
}
else {
lua_pop(L, 1);
return NULL;
}
}
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
if (!lua_checkstack(L, space))
luaL_error(L, "stack overflow (%s)", mes);
}
LUALIB_API void luaL_check_type (lua_State *L, int narg, int t) {
LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
if (lua_type(L, narg) != t)
tag_error(L, narg, t);
}
LUALIB_API void luaL_check_any (lua_State *L, int narg) {
LUALIB_API void luaL_checkany (lua_State *L, int narg) {
if (lua_type(L, narg) == LUA_TNONE)
luaL_argerror(L, narg, "value expected");
}
LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) {
LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
const char *s = lua_tostring(L, narg);
if (!s) tag_error(L, narg, LUA_TSTRING);
if (len) *len = lua_strlen(L, narg);
@@ -124,17 +171,18 @@ LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) {
}
LUALIB_API const char *luaL_opt_lstr (lua_State *L, int narg, const char *def, size_t *len) {
LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
const char *def, size_t *len) {
if (lua_isnoneornil(L, narg)) {
if (len)
*len = (def ? strlen(def) : 0);
return def;
}
else return luaL_check_lstr(L, narg, len);
else return luaL_checklstring(L, narg, len);
}
LUALIB_API lua_Number luaL_check_number (lua_State *L, int narg) {
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
lua_Number d = lua_tonumber(L, narg);
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
tag_error(L, narg, LUA_TNUMBER);
@@ -142,13 +190,13 @@ LUALIB_API lua_Number luaL_check_number (lua_State *L, int narg) {
}
LUALIB_API lua_Number luaL_opt_number (lua_State *L, int narg, lua_Number def) {
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
if (lua_isnoneornil(L, narg)) return def;
else return luaL_check_number(L, narg);
else return luaL_checknumber(L, narg);
}
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
if (!lua_getmetatable(L, obj)) /* no metatable? */
return 0;
lua_pushstring(L, event);
@@ -157,13 +205,37 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
lua_pop(L, 2); /* remove metatable and metafield */
return 0;
}
else {
lua_remove(L, -2); /* remove only metatable */
return 1;
}
}
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
obj = abs_index(L, obj);
if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
return 0;
lua_pushvalue(L, obj);
lua_call(L, 1, 1);
return 1;
}
LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup) {
LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup) {
if (libname) {
lua_pushstring(L, libname);
lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */
if (lua_isnil(L, -1)) { /* no? */
lua_pop(L, 1);
lua_newtable(L); /* create it */
lua_pushstring(L, libname);
lua_pushvalue(L, -2);
lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */
}
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
}
for (; l->name; l++) {
int i;
lua_pushstring(L, l->name);
@@ -172,21 +244,82 @@ LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup) {
lua_pushcclosure(L, l->func, nup);
lua_settable(L, -(nup+3));
}
lua_pop(L, nup);
lua_pop(L, nup); /* remove upvalues */
}
LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup) {
lua_pushstring(L, libname);
lua_insert(L, -(nup+1));
lua_newtable(L);
lua_insert(L, -(nup+1));
luaL_openlib(L, l, nup);
lua_settable(L, LUA_GLOBALSINDEX);
/*
** {======================================================
** getn-setn: size for arrays
** =======================================================
*/
static int checkint (lua_State *L, int topop) {
int n = (int)lua_tonumber(L, -1);
if (n == 0 && !lua_isnumber(L, -1)) n = -1;
lua_pop(L, topop);
return n;
}
static void getsizes (lua_State *L) {
lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);
if (lua_isnil(L, -1)) { /* no `size' table? */
lua_pop(L, 1); /* remove nil */
lua_newtable(L); /* create it */
lua_pushvalue(L, -1); /* `size' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushliteral(L, "__mode");
lua_pushliteral(L, "k");
lua_rawset(L, -3); /* metatable(N).__mode = "k" */
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */
}
}
void luaL_setn (lua_State *L, int t, int n) {
t = abs_index(L, t);
lua_pushliteral(L, "n");
lua_rawget(L, t);
if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
lua_pushliteral(L, "n"); /* use it */
lua_pushnumber(L, (lua_Number)n);
lua_rawset(L, t);
}
else { /* use `sizes' */
getsizes(L);
lua_pushvalue(L, t);
lua_pushnumber(L, (lua_Number)n);
lua_rawset(L, -3); /* sizes[t] = n */
lua_pop(L, 1); /* remove `sizes' */
}
}
int luaL_getn (lua_State *L, int t) {
int n;
t = abs_index(L, t);
lua_pushliteral(L, "n"); /* try t.n */
lua_rawget(L, t);
if ((n = checkint(L, 1)) >= 0) return n;
getsizes(L); /* else try sizes[t] */
lua_pushvalue(L, t);
lua_rawget(L, -2);
if ((n = checkint(L, 2)) >= 0) return n;
for (n = 1; ; n++) { /* else must count elements */
lua_rawgeti(L, t, n);
if (lua_isnil(L, -1)) break;
lua_pop(L, 1);
}
lua_pop(L, 1);
return n - 1;
}
/* }====================================================== */
/*
** {======================================================
@@ -195,7 +328,6 @@ LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
*/
#define buffempty(B) ((B)->p == (B)->buffer)
#define bufflen(B) ((B)->p - (B)->buffer)
#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
@@ -208,27 +340,27 @@ static int emptybuffer (luaL_Buffer *B) {
else {
lua_pushlstring(B->L, B->buffer, l);
B->p = B->buffer;
B->level++;
B->lvl++;
return 1;
}
}
static void adjuststack (luaL_Buffer *B) {
if (B->level > 1) {
if (B->lvl > 1) {
lua_State *L = B->L;
int toget = 1; /* number of levels to concat */
size_t toplen = lua_strlen(L, -1);
do {
size_t l = lua_strlen(L, -(toget+1));
if (B->level - toget + 1 >= LIMIT || toplen > l) {
if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
toplen += l;
toget++;
}
else break;
} while (toget < B->level);
} while (toget < B->lvl);
lua_concat(L, toget);
B->level = B->level - toget + 1;
B->lvl = B->lvl - toget + 1;
}
}
@@ -253,8 +385,8 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
emptybuffer(B);
lua_concat(B->L, B->level);
B->level = 1;
lua_concat(B->L, B->lvl);
B->lvl = 1;
}
@@ -269,7 +401,7 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
else {
if (emptybuffer(B))
lua_insert(L, -2); /* put buffer before new value */
B->level++; /* add new value into B stack */
B->lvl++; /* add new value into B stack */
adjuststack(B);
}
}
@@ -278,7 +410,7 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
B->L = L;
B->p = B->buffer;
B->level = 0;
B->lvl = 0;
}
/* }====================================================== */
@@ -286,21 +418,24 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
LUALIB_API int luaL_ref (lua_State *L, int t) {
int ref;
lua_rawgeti(L, t, 0); /* get first free element */
ref = (int)lua_tonumber(L, -1); /* ref = t[0] */
t = abs_index(L, t);
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* remove from stack */
return LUA_REFNIL; /* `nil' has a unique fixed reference */
}
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
ref = (int)lua_tonumber(L, -1); /* ref = t[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, t, ref); /* remove it from list */
lua_rawseti(L, t, 0); /* (that is, t[0] = t[ref]) */
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
}
else { /* no free elements */
lua_pushliteral(L, "n");
lua_pushvalue(L, -1);
lua_rawget(L, t); /* get t.n */
ref = (int)lua_tonumber(L, -1) + 1; /* ref = t.n + 1 */
lua_pop(L, 1); /* pop t.n */
lua_pushnumber(L, ref);
lua_rawset(L, t); /* t.n = t.n + 1 */
ref = luaL_getn(L, t);
if (ref < RESERVED_REFS)
ref = RESERVED_REFS; /* skip reserved references */
ref++; /* create new reference */
luaL_setn(L, t, ref);
}
lua_rawseti(L, t, ref);
return ref;
@@ -309,10 +444,11 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
if (ref >= 0) {
lua_rawgeti(L, t, 0);
lua_rawseti(L, t, ref); /* t[ref] = t[0] */
lua_pushnumber(L, ref);
lua_rawseti(L, t, 0); /* t[0] = ref */
t = abs_index(L, t);
lua_rawgeti(L, t, FREELIST_REF);
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
lua_pushnumber(L, (lua_Number)ref);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
@@ -339,38 +475,42 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
}
static int errfile (lua_State *L, const char *filename) {
if (filename == NULL) filename = "stdin";
lua_pushfstring(L, "cannot read %s: %s", filename, lua_fileerror);
static int errfile (lua_State *L, int fnameindex) {
const char *filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno));
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
LoadF lf;
int status;
int status, readstatus;
int c;
int old_top = lua_gettop(L);
lf.f = (filename == NULL) ? stdin : fopen(filename, "r");
if (lf.f == NULL) return errfile(L, filename); /* unable to open file */
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
if (filename == NULL) {
lua_pushliteral(L, "=stdin");
lf.f = stdin;
}
else {
lua_pushfstring(L, "@%s", filename);
lf.f = fopen(filename, "r");
}
if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */
c = ungetc(getc(lf.f), lf.f);
if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */
fclose(lf.f);
lf.f = fopen(filename, "rb"); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, filename); /* unable to reopen file */
if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */
}
if (filename == NULL)
lua_pushliteral(L, "=stdin");
else
lua_pushfstring(L, "@%s", filename);
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
lua_remove(L, old_top+1); /* remove filename from stack */
if (ferror(lf.f)) {
lua_settop(L, old_top); /* ignore results from `lua_load' */
return errfile(L, filename);
readstatus = ferror(lf.f);
if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) {
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
return errfile(L, fnameindex);
}
if (lf.f != stdin)
fclose(lf.f);
lua_remove(L, fnameindex);
return status;
}
@@ -412,9 +552,14 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
static void callalert (lua_State *L, int status) {
if (status != 0) {
lua_getglobal(L, "_ALERT");
lua_insert(L, -2);
lua_call(L, 1, 0);
lua_pop(L, 1);
if (lua_isfunction(L, -1)) {
lua_insert(L, -2);
lua_call(L, 1, 0);
}
else { /* no _ALERT function; print it on stderr */
fprintf(stderr, "%s\n", lua_tostring(L, -2));
lua_pop(L, 2); /* remove error message and _ALERT */
}
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lauxlib.h,v 1.51 2002/07/01 19:23:58 roberto Exp roberto $
** $Id: lauxlib.h,v 1.59 2003/03/18 12:25:32 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -16,7 +16,7 @@
#ifndef LUALIB_API
#define LUALIB_API extern
#define LUALIB_API LUA_API
#endif
@@ -27,34 +27,39 @@ typedef struct luaL_reg {
} luaL_reg;
LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup);
LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup);
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event);
LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup);
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e);
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e);
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname);
LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg);
LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg,
size_t *len);
LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg,
const char *def, size_t *len);
LUALIB_API lua_Number luaL_check_number (lua_State *L, int numArg);
LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def);
LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l);
LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg,
const char *def, size_t *l);
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg);
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def);
LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg);
LUALIB_API void luaL_check_type (lua_State *L, int narg, int t);
LUALIB_API void luaL_check_any (lua_State *L, int narg);
LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg);
LUALIB_API void luaL_checktype (lua_State *L, int narg, int t);
LUALIB_API void luaL_checkany (lua_State *L, int narg);
LUALIB_API void luaL_where (lua_State *L, int level);
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname);
LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname);
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname);
LUALIB_API void luaL_where (lua_State *L, int lvl);
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...);
LUALIB_API int luaL_findstring (const char *name,
const char *const list[]);
LUALIB_API int luaL_findstring (const char *st, const char *const lst[]);
LUALIB_API int luaL_ref (lua_State *L, int t);
LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
LUALIB_API int luaL_getn (lua_State *L, int t);
LUALIB_API void luaL_setn (lua_State *L, int t, int n);
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename);
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz,
const char *name);
@@ -65,14 +70,14 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
** ===============================================================
*/
#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \
#define luaL_argcheck(L, cond,numarg,extramsg) if (!(cond)) \
luaL_argerror(L, numarg,extramsg)
#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL))
#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL))
#define luaL_check_int(L,n) ((int)luaL_check_number(L, n))
#define luaL_check_long(L,n) ((long)luaL_check_number(L, n))
#define luaL_opt_int(L,n,d) ((int)luaL_opt_number(L, n,d))
#define luaL_opt_long(L,n,d) ((long)luaL_opt_number(L, n,d))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_checkint(L,n) ((int)luaL_checknumber(L, n))
#define luaL_checklong(L,n) ((long)luaL_checknumber(L, n))
#define luaL_optint(L,n,d) ((int)luaL_optnumber(L, n,(lua_Number)(d)))
#define luaL_optlong(L,n,d) ((long)luaL_optnumber(L, n,(lua_Number)(d)))
/*
@@ -89,7 +94,7 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
typedef struct luaL_Buffer {
char *p; /* current position in buffer */
int level;
int lvl; /* number of strings in the stack (level) */
lua_State *L;
char buffer[LUAL_BUFFERSIZE];
} luaL_Buffer;
@@ -113,16 +118,26 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B);
/*
** Compatibility macros
** Compatibility macros and functions
*/
#define luaL_checktype luaL_check_type
#define luaL_checkany luaL_check_any
LUALIB_API int lua_dofile (lua_State *L, const char *filename);
LUALIB_API int lua_dostring (lua_State *L, const char *str);
LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
const char *name);
LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz,
const char *n);
#define luaL_check_lstr luaL_checklstring
#define luaL_opt_lstr luaL_optlstring
#define luaL_check_number luaL_checknumber
#define luaL_opt_number luaL_optnumber
#define luaL_arg_check luaL_argcheck
#define luaL_check_string luaL_checkstring
#define luaL_opt_string luaL_optstring
#define luaL_check_int luaL_checkint
#define luaL_check_long luaL_checklong
#define luaL_opt_int luaL_optint
#define luaL_opt_long luaL_optlong
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lbaselib.c,v 1.96 2002/08/06 18:54:18 roberto Exp roberto $
** $Id: lbaselib.c,v 1.129 2003/03/19 21:14:34 roberto Exp roberto $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <string.h>
#define lbaselib_c
#include "lua.h"
#include "lauxlib.h"
@@ -47,24 +49,24 @@ static int luaB_print (lua_State *L) {
static int luaB_tonumber (lua_State *L) {
int base = luaL_opt_int(L, 2, 10);
int base = luaL_optint(L, 2, 10);
if (base == 10) { /* standard conversion */
luaL_check_any(L, 1);
luaL_checkany(L, 1);
if (lua_isnumber(L, 1)) {
lua_pushnumber(L, lua_tonumber(L, 1));
return 1;
}
}
else {
const char *s1 = luaL_check_string(L, 1);
const char *s1 = luaL_checkstring(L, 1);
char *s2;
unsigned long n;
luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range");
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
n = strtoul(s1, &s2, base);
if (s1 != s2) { /* at least one valid digit? */
while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
if (*s2 == '\0') { /* no invalid trailing characters? */
lua_pushnumber(L, n);
lua_pushnumber(L, (lua_Number)n);
return 1;
}
}
@@ -75,57 +77,37 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) {
int level = luaL_opt_int(L, 2, 1);
luaL_check_any(L, 1);
int level = luaL_optint(L, 2, 1);
luaL_checkany(L, 1);
if (!lua_isstring(L, 1) || level == 0)
lua_pushvalue(L, 1); /* propagate error mesage without changes */
lua_pushvalue(L, 1); /* propagate error message without changes */
else { /* add extra information */
luaL_where(L, level);
lua_pushvalue(L, 1);
lua_pushliteral(L, "\n");
lua_concat(L, 3);
lua_concat(L, 2);
}
return lua_error(L);
}
static int luaB_getmode (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_pushstring(L, lua_getmode(L, 1));
return 1;
}
static int luaB_setmode (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_setmode(L, 1, luaL_check_string(L, 2));
lua_settop(L, 1);
return 1;
}
static int luaB_getmetatable (lua_State *L) {
luaL_check_any(L, 1);
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L);
return 1; /* no metatable */
}
else {
lua_pushliteral(L, "__metatable");
lua_rawget(L, -2);
if (lua_isnil(L, -1))
lua_pop(L, 1);
/* otherwise returns metatable.__metatable */
}
return 1;
luaL_getmetafield(L, 1, "__metatable");
return 1; /* returns either __metatable field (if present) or metatable */
}
static int luaB_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_check_type(L, 1, LUA_TTABLE);
luaL_arg_check(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
luaL_checktype(L, 1, LUA_TTABLE);
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
if (luaL_getmetafield(L, 1, "__metatable"))
luaL_error(L, "cannot change a protected metatable");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
@@ -136,78 +118,96 @@ static void getfunc (lua_State *L) {
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
else {
lua_Debug ar;
int level = luaL_opt_int(L, 1, 1);
luaL_arg_check(L, level >= 0, 1, "level must be non-negative");
int level = luaL_optint(L, 1, 1);
luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
if (lua_getstack(L, level, &ar) == 0)
luaL_argerror(L, 1, "invalid level");
lua_getinfo(L, "f", &ar);
if (lua_isnil(L, -1))
luaL_error(L, "no function environment for tail call at level %d",
level);
}
}
static int luaB_getglobals (lua_State *L) {
static int aux_getfenv (lua_State *L) {
lua_getfenv(L, -1);
lua_pushliteral(L, "__fenv");
lua_rawget(L, -2);
return !lua_isnil(L, -1);
}
static int luaB_getfenv (lua_State *L) {
getfunc(L);
lua_getglobals(L, -1);
if (!aux_getfenv(L)) /* __fenv not defined? */
lua_pop(L, 1); /* remove it, to return real environment */
return 1;
}
static int luaB_setglobals (lua_State *L) {
luaL_check_type(L, 2, LUA_TTABLE);
static int luaB_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
getfunc(L);
if (aux_getfenv(L)) /* __fenv defined? */
luaL_error(L, "`setfenv' cannot change a protected environment");
else
lua_pop(L, 2); /* remove __fenv and real environment table */
lua_pushvalue(L, 2);
if (lua_setglobals(L, -2) == 0)
luaL_error(L, "cannot change global table of given function");
if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0)
lua_replace(L, LUA_GLOBALSINDEX);
else if (lua_setfenv(L, -2) == 0)
luaL_error(L, "`setfenv' cannot change environment of given function");
return 0;
}
static int luaB_rawequal (lua_State *L) {
luaL_check_any(L, 1);
luaL_check_any(L, 2);
luaL_checkany(L, 1);
luaL_checkany(L, 2);
lua_pushboolean(L, lua_rawequal(L, 1, 2));
return 1;
}
static int luaB_rawget (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
luaL_check_any(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
lua_rawget(L, 1);
return 1;
}
static int luaB_rawset (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
luaL_check_any(L, 2);
luaL_check_any(L, 3);
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
luaL_checkany(L, 3);
lua_rawset(L, 1);
return 1;
}
static int luaB_gcinfo (lua_State *L) {
lua_pushnumber(L, lua_getgccount(L));
lua_pushnumber(L, lua_getgcthreshold(L));
lua_pushnumber(L, (lua_Number)lua_getgccount(L));
lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L));
return 2;
}
static int luaB_collectgarbage (lua_State *L) {
lua_setgcthreshold(L, luaL_opt_int(L, 1, 0));
lua_setgcthreshold(L, luaL_optint(L, 1, 0));
return 0;
}
static int luaB_type (lua_State *L) {
luaL_check_any(L, 1);
luaL_checkany(L, 1);
lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
return 1;
}
static int luaB_next (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
if (lua_next(L, 1))
return 2;
@@ -219,8 +219,9 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_getglobal(L, "next"); /* return generator, */
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushliteral(L, "next");
lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
return 3;
@@ -229,9 +230,10 @@ static int luaB_pairs (lua_State *L) {
static int luaB_ipairs (lua_State *L) {
lua_Number i = lua_tonumber(L, 2);
luaL_check_type(L, 1, LUA_TTABLE);
if (i == 0 && lua_isnull(L, 2)) { /* `for' start? */
lua_getglobal(L, "ipairs"); /* return generator, */
luaL_checktype(L, 1, LUA_TTABLE);
if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */
lua_pushliteral(L, "ipairs");
lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnumber(L, 0); /* and initial value */
return 3;
@@ -245,32 +247,33 @@ static int luaB_ipairs (lua_State *L) {
}
static int passresults (lua_State *L, int status) {
if (status == 0) return 1;
static int load_aux (lua_State *L, int status) {
if (status == 0) /* OK? */
return 1;
else {
lua_pushnil(L);
lua_insert(L, -2);
return 2;
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
}
}
static int luaB_loadstring (lua_State *L) {
size_t l;
const char *s = luaL_check_lstr(L, 1, &l);
const char *chunkname = luaL_opt_string(L, 2, s);
return passresults(L, luaL_loadbuffer(L, s, l, chunkname));
const char *s = luaL_checklstring(L, 1, &l);
const char *chunkname = luaL_optstring(L, 2, s);
return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
}
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_opt_string(L, 1, NULL);
return passresults(L, luaL_loadfile(L, fname));
const char *fname = luaL_optstring(L, 1, NULL);
return load_aux(L, luaL_loadfile(L, fname));
}
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_opt_string(L, 1, NULL);
const char *fname = luaL_optstring(L, 1, NULL);
int status = luaL_loadfile(L, fname);
if (status != 0) lua_error(L);
lua_call(L, 0, LUA_MULTRET);
@@ -279,9 +282,9 @@ static int luaB_dofile (lua_State *L) {
static int luaB_assert (lua_State *L) {
luaL_check_any(L, 1);
luaL_checkany(L, 1);
if (!lua_toboolean(L, 1))
return luaL_error(L, "%s", luaL_opt_string(L, 2, "assertion failed!"));
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
lua_settop(L, 1);
return 1;
}
@@ -289,27 +292,18 @@ static int luaB_assert (lua_State *L) {
static int luaB_unpack (lua_State *L) {
int n, i;
luaL_check_type(L, 1, LUA_TTABLE);
lua_pushliteral(L, "n");
lua_rawget(L, 1);
n = (lua_isnumber(L, -1)) ? (int)lua_tonumber(L, -1) : -1;
for (i=0; i<n || n==-1; i++) { /* push arg[1...n] */
luaL_check_stack(L, LUA_MINSTACK, "table too big to unpack");
lua_rawgeti(L, 1, i+1);
if (n == -1) { /* no explicit limit? */
if (lua_isnil(L, -1)) { /* stop at first `nil' element */
lua_pop(L, 1); /* remove `nil' */
break;
}
}
}
return i;
luaL_checktype(L, 1, LUA_TTABLE);
n = luaL_getn(L, 1);
luaL_checkstack(L, n, "table too big to unpack");
for (i=1; i<=n; i++) /* push arg[1...n] */
lua_rawgeti(L, 1, i);
return n;
}
static int luaB_pcall (lua_State *L) {
int status;
luaL_check_any(L, 1);
luaL_checkany(L, 1);
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
lua_pushboolean(L, (status == 0));
lua_insert(L, 1);
@@ -319,7 +313,7 @@ static int luaB_pcall (lua_State *L) {
static int luaB_xpcall (lua_State *L) {
int status;
luaL_check_any(L, 2);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_insert(L, 1); /* put error function under function to be called */
status = lua_pcall(L, 0, LUA_MULTRET, 1);
@@ -354,6 +348,9 @@ static int luaB_tostring (lua_State *L) {
case LUA_TLIGHTUSERDATA:
sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
break;
case LUA_TTHREAD:
sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
return 1;
@@ -381,7 +378,7 @@ static int luaB_newproxy (lua_State *L) {
validproxy = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove value */
}
luaL_arg_check(L, validproxy, 1, "boolean/proxy expected");
luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
lua_getmetatable(L, 1); /* metatable is valid; get it */
}
lua_setmetatable(L, 2);
@@ -406,6 +403,10 @@ static int luaB_newproxy (lua_State *L) {
#define LUA_PATH_SEP ';'
#endif
#ifndef LUA_PATH_MARK
#define LUA_PATH_MARK '?'
#endif
#ifndef LUA_PATH_DEFAULT
#define LUA_PATH_DEFAULT "?;?.lua"
#endif
@@ -425,7 +426,7 @@ static const char *getpath (lua_State *L) {
static const char *pushnextpath (lua_State *L, const char *path) {
const char *l;
if (*path == '\0') return NULL; /* no more pathes */
if (*path == '\0') return NULL; /* no more paths */
if (*path == LUA_PATH_SEP) path++; /* skip separator */
l = strchr(path, LUA_PATH_SEP); /* find next separator */
if (l == NULL) l = path+strlen(path);
@@ -436,29 +437,33 @@ static const char *pushnextpath (lua_State *L, const char *path) {
static void pushcomposename (lua_State *L) {
const char *path = lua_tostring(L, -1);
const char *wild = strchr(path, '?');
if (wild == NULL) return; /* no wild char; path is the file name */
lua_pushlstring(L, path, wild - path);
lua_pushvalue(L, 1); /* package name */
lua_pushstring(L, wild + 1);
lua_concat(L, 3);
const char *wild;
int n = 1;
while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
/* is there stack space for prefix, name, and eventual last sufix? */
luaL_checkstack(L, 3, "too many marks in a path component");
lua_pushlstring(L, path, wild - path); /* push prefix */
lua_pushvalue(L, 1); /* push package name (in place of MARK) */
path = wild + 1; /* continue after MARK */
n += 2;
}
lua_pushstring(L, path); /* push last sufix (`n' already includes this) */
lua_concat(L, n);
}
static int luaB_require (lua_State *L) {
const char *path;
int status = LUA_ERRFILE; /* not found (yet) */
luaL_check_string(L, 1);
luaL_checkstring(L, 1);
lua_settop(L, 1);
lua_pushvalue(L, 1);
lua_setglobal(L, "_REQUIREDNAME");
lua_getglobal(L, REQTAB);
if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
path = getpath(L);
lua_pushvalue(L, 1); /* check package's name in book-keeping table */
lua_rawget(L, 2);
if (!lua_isnil(L, -1)) /* is it there? */
return 0; /* package is already loaded */
if (lua_toboolean(L, -1)) /* is it there? */
return 1; /* package is already loaded; return its result */
else { /* must load it */
while (status == LUA_ERRFILE) {
lua_settop(L, 3); /* reset stack position */
@@ -469,18 +474,29 @@ static int luaB_require (lua_State *L) {
}
switch (status) {
case 0: {
lua_call(L, 0, 0); /* run loaded module */
lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */
lua_insert(L, -2); /* put it below function */
lua_pushvalue(L, 1);
lua_pushboolean(L, 1);
lua_setglobal(L, "_REQUIREDNAME"); /* set new name */
lua_call(L, 0, 1); /* run loaded module */
lua_insert(L, -2); /* put result below previous name */
lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */
if (lua_isnil(L, -1)) { /* no/nil return? */
lua_pushboolean(L, 1);
lua_replace(L, -2); /* replace to true */
}
lua_pushvalue(L, 1);
lua_pushvalue(L, -2);
lua_rawset(L, 2); /* mark it as loaded */
return 0;
return 1; /* return value */
}
case LUA_ERRFILE: { /* file not found */
return luaL_error(L, "could not load package `%s' from path `%s'",
lua_tostring(L, 1), getpath(L));
}
default: {
return luaL_error(L, "error loading package\n%s", lua_tostring(L, -1));
return luaL_error(L, "error loading package `%s' (%s)",
lua_tostring(L, 1), lua_tostring(L, -1));
}
}
}
@@ -492,10 +508,8 @@ static const luaL_reg base_funcs[] = {
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
{"setmetatable", luaB_setmetatable},
{"getglobals", luaB_getglobals},
{"setglobals", luaB_setglobals},
{"getmode", luaB_getmode},
{"setmode", luaB_setmode},
{"getfenv", luaB_getfenv},
{"setfenv", luaB_setfenv},
{"next", luaB_next},
{"ipairs", luaB_ipairs},
{"pairs", luaB_pairs},
@@ -526,48 +540,72 @@ static const luaL_reg base_funcs[] = {
** =======================================================
*/
static int luaB_resume (lua_State *L) {
lua_State *co = (lua_State *)lua_unboxpointer(L, lua_upvalueindex(1));
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status;
lua_settop(L, 0);
status = lua_resume(L, co);
if (status != 0)
return lua_error(L);
return lua_gettop(L);
}
static int gc_coroutine (lua_State *L) {
lua_State *co = (lua_State *)lua_unboxpointer(L, 1);
lua_closethread(L, co);
return 0;
}
static int luaB_coroutine (lua_State *L) {
lua_State *NL;
int ref;
int i;
int n = lua_gettop(L);
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
"Lua function expected");
NL = lua_newthread(L);
if (NL == NULL) return luaL_error(L, "unable to create new thread");
/* move function and arguments from L to NL */
for (i=0; i<n; i++) {
ref = lua_ref(L, 1);
lua_getref(NL, ref);
lua_insert(NL, 1);
lua_unref(L, ref);
if (!lua_checkstack(co, narg))
luaL_error(L, "too many arguments to resume");
lua_xmove(L, co, narg);
status = lua_resume(co, narg);
if (status == 0) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres))
luaL_error(L, "too many results to resume");
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
lua_cobegin(NL, n-1);
lua_boxpointer(L, NL);
lua_pushliteral(L, "Coroutine");
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
lua_pushcclosure(L, luaB_resume, 1);
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int luaB_coresume (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
int r;
luaL_argcheck(L, co, 1, "coroutine expected");
r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + `resume' returns */
}
}
static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L));
if (r < 0) {
if (lua_isstring(L, -1)) { /* error object is a string? */
luaL_where(L, 1); /* add extra info */
lua_insert(L, -2);
lua_concat(L, 2);
}
lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL = lua_newthread(L);
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
"Lua function expected");
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
@@ -576,24 +614,31 @@ static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
static int luaB_costatus (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argcheck(L, co, 1, "coroutine expected");
if (L == co) lua_pushliteral(L, "running");
else {
lua_Debug ar;
if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0)
lua_pushliteral(L, "dead");
else
lua_pushliteral(L, "suspended");
}
return 1;
}
static const luaL_reg co_funcs[] = {
{"create", luaB_coroutine},
{"create", luaB_cocreate},
{"wrap", luaB_cowrap},
{"resume", luaB_coresume},
{"yield", luaB_yield},
{"status", luaB_costatus},
{NULL, NULL}
};
static void co_open (lua_State *L) {
luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0);
/* create metatable for coroutines */
lua_pushliteral(L, "Coroutine");
lua_newtable(L);
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, gc_coroutine);
lua_rawset(L, -3);
lua_rawset(L, LUA_REGISTRYINDEX);
}
/* }====================================================== */
@@ -601,23 +646,27 @@ static void co_open (lua_State *L) {
static void base_open (lua_State *L) {
lua_pushliteral(L, "_G");
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_openlib(L, base_funcs, 0); /* open lib into global table */
luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */
lua_pushliteral(L, "_VERSION");
lua_pushliteral(L, LUA_VERSION);
lua_rawset(L, -3); /* set global _VERSION */
/* `newproxy' needs a weaktable as upvalue */
lua_pushliteral(L, "newproxy");
lua_newtable(L); /* new table `w' */
lua_setmode(L, -1, "k");
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushliteral(L, "__mode");
lua_pushliteral(L, "k");
lua_rawset(L, -3); /* metatable(w).__mode = "k" */
lua_pushcclosure(L, luaB_newproxy, 1);
lua_rawset(L, -3); /* set global `newproxy' */
lua_rawset(L, -1); /* set global _G */
}
LUALIB_API int lua_baselibopen (lua_State *L) {
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
co_open(L);
luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
lua_newtable(L);
lua_setglobal(L, REQTAB);
return 0;

114
lcode.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 1.108 2002/06/13 13:39:55 roberto Exp $
** $Id: lcode.c,v 1.116 2003/02/27 12:33:07 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,8 @@
#include <stdlib.h>
#define lcode_c
#include "lua.h"
#include "lcode.h"
@@ -100,14 +102,14 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) {
static int need_value (FuncState *fs, int list, int cond) {
for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
Instruction i = *getjumpcontrol(fs, list);
if (GET_OPCODE(i) != OP_TEST || GETARG_B(i) != cond) return 1;
if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1;
}
return 0; /* not found */
}
static void patchtestreg (Instruction *i, int reg) {
if (reg == NO_REG) reg = GETARG_C(*i);
if (reg == NO_REG) reg = GETARG_B(*i);
SETARG_A(*i, reg);
}
@@ -122,7 +124,7 @@ static void luaK_patchlistaux (FuncState *fs, int list,
luaK_fixjump(fs, list, dtarget); /* jump to default target */
}
else {
if (GETARG_B(*i)) {
if (GETARG_C(*i)) {
lua_assert(ttarget != NO_JUMP);
patchtestreg(i, treg);
luaK_fixjump(fs, list, ttarget);
@@ -174,7 +176,7 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
}
static void luaK_checkstack (FuncState *fs, int n) {
void luaK_checkstack (FuncState *fs, int n) {
int newstack = fs->freereg + n;
if (newstack > fs->f->maxstacksize) {
if (newstack >= MAXSTACK)
@@ -205,17 +207,17 @@ static void freeexp (FuncState *fs, expdesc *e) {
static int addk (FuncState *fs, TObject *k, TObject *v) {
const TObject *index = luaH_get(fs->h, k);
if (ttisnumber(index)) {
lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(index))], v));
return cast(int, nvalue(index));
const TObject *idx = luaH_get(fs->h, k);
if (ttisnumber(idx)) {
lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v));
return cast(int, nvalue(idx));
}
else { /* constant not found; create a new entry */
Proto *f = fs->f;
luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
MAXARG_Bx, "constant table overflow");
setobj(&f->k[fs->nk], v);
setnvalue(luaH_set(fs->L, fs->h, k), fs->nk);
setobj2n(&f->k[fs->nk], v);
setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk));
return fs->nk++;
}
}
@@ -409,7 +411,7 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
}
default: break;
}
/* not a constant in the right range: put in a register */
/* not a constant in the right range: put it in a register */
return luaK_exp2anyreg(fs, e);
}
@@ -432,8 +434,8 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
break;
}
case VINDEXED: {
int e = luaK_exp2anyreg(fs, exp);
luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux);
int e = luaK_exp2RK(fs, exp);
luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
break;
}
default: {
@@ -460,8 +462,9 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
static void invertjump (FuncState *fs, expdesc *e) {
Instruction *pc = getjumpcontrol(fs, e->info);
lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT));
SETARG_B(*pc, !(GETARG_B(*pc)));
lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
GET_OPCODE(*pc) != OP_TEST);
SETARG_A(*pc, !(GETARG_A(*pc)));
}
@@ -470,13 +473,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
Instruction ie = getcode(fs, e);
if (GET_OPCODE(ie) == OP_NOT) {
fs->pc--; /* remove previous OP_NOT */
return luaK_condjump(fs, OP_TEST, NO_REG, !cond ,GETARG_B(ie));
return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond);
}
/* else go through */
}
discharge2anyreg(fs, e);
freeexp(fs, e);
return luaK_condjump(fs, OP_TEST, NO_REG, cond, e->info);
return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond);
}
@@ -605,11 +608,6 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
break;
}
case OPR_SUB: case OPR_DIV: case OPR_POW: {
/* non-comutative operators */
luaK_exp2anyreg(fs, v); /* first operand must be a register */
break;
}
default: {
luaK_exp2RK(fs, v);
break;
@@ -619,40 +617,22 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
int o1, int o2, int ic) {
switch (op) {
case OPR_SUB:
case OPR_DIV:
case OPR_POW:
lua_assert(!ic);
/* go through */
case OPR_ADD:
case OPR_MULT: { /* ORDER OPR */
OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD);
res->info = luaK_codeABC(fs, opc, 0, o1, o2);
res->k = VRELOCABLE;
break;
int o1, int o2) {
if (op <= OPR_POW) { /* arithmetic operator? */
OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */
res->info = luaK_codeABC(fs, opc, 0, o1, o2);
res->k = VRELOCABLE;
}
else { /* test operator */
static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE};
int cond = 1;
if (op >= OPR_GT) { /* `>' or `>='? */
int temp; /* exchange args and replace by `<' or `<=' */
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
}
case OPR_NE:
case OPR_EQ: {
res->info = luaK_condjump(fs, OP_EQ, o1, (op == OPR_EQ), o2);
res->k = VJMP;
break;
}
case OPR_LT:
case OPR_LE:
case OPR_GT:
case OPR_GE: { /* ORDER OPR */
OpCode opc;
int i = op - OPR_LT;
if (ic) /* operands were interchanged? */
i = (i+2)&3; /* correct operator */
opc = cast(OpCode, i + OP_LT);
res->info = luaK_condjump(fs, opc, o1, 1, o2);
res->k = VJMP;
break;
}
default: lua_assert(0);
else if (op == OPR_NE) cond = 0;
res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2);
res->k = VJMP;
}
}
@@ -691,21 +671,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
break;
}
default: {
int o1, o2;
int ic; /* interchange flag */
if (e1->k != VK) { /* not a constant operator? */
o1 = e1->info;
o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */
ic = 0;
}
else { /* interchange operands */
o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */
o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */
ic = 1;
}
int o1 = luaK_exp2RK(fs, e1);
int o2 = luaK_exp2RK(fs, e2);
freeexp(fs, e2);
freeexp(fs, e1);
codebinop(fs, e1, op, o1, o2, ic);
codebinop(fs, e1, op, o1, o2);
}
}
}
@@ -718,14 +688,14 @@ void luaK_fixline (FuncState *fs, int line) {
int luaK_code (FuncState *fs, Instruction i, int line) {
Proto *f = fs->f;
int oldsize = f->sizecode;
luaK_dischargejpc(fs); /* `pc' will change */
/* put new instruction in code array */
luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
MAX_INT, "code size overflow");
f->code[fs->pc] = i;
if (f->sizecode != oldsize)
luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int);
/* save corresponding line information */
luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
MAX_INT, "code size overflow");
f->lineinfo[fs->pc] = line;
return fs->pc++;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lcode.h,v 1.36 2002/05/13 13:07:48 roberto Exp roberto $
** $Id: lcode.h,v 1.37 2002/06/12 19:16:00 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -47,6 +47,7 @@ int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
void luaK_fixline (FuncState *fs, int line);
void luaK_nil (FuncState *fs, int from, int n);
void luaK_reserveregs (FuncState *fs, int n);
void luaK_checkstack (FuncState *fs, int n);
int luaK_stringK (FuncState *fs, TString *s);
int luaK_numberK (FuncState *fs, lua_Number r);
void luaK_dischargevars (FuncState *fs, expdesc *e);

101
ldblib.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldblib.c,v 1.66 2002/08/06 18:01:50 roberto Exp roberto $
** $Id: ldblib.c,v 1.79 2003/03/11 12:24:34 roberto Exp roberto $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,8 @@
#include <stdlib.h>
#include <string.h>
#define ldblib_c
#include "lua.h"
#include "lauxlib.h"
@@ -25,14 +27,14 @@ static void settabss (lua_State *L, const char *i, const char *v) {
static void settabsi (lua_State *L, const char *i, int v) {
lua_pushstring(L, i);
lua_pushnumber(L, v);
lua_pushnumber(L, (lua_Number)v);
lua_rawset(L, -3);
}
static int getinfo (lua_State *L) {
lua_Debug ar;
const char *options = luaL_opt_string(L, 2, "flnSu");
const char *options = luaL_optstring(L, 2, "flnSu");
if (lua_isnumber(L, 1)) {
if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
lua_pushnil(L); /* level out of range */
@@ -81,9 +83,9 @@ static int getinfo (lua_State *L) {
static int getlocal (lua_State *L) {
lua_Debug ar;
const char *name;
if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */
if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
return luaL_argerror(L, 1, "level out of range");
name = lua_getlocal(L, &ar, luaL_check_int(L, 2));
name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
if (name) {
lua_pushstring(L, name);
lua_pushvalue(L, -2);
@@ -98,25 +100,51 @@ static int getlocal (lua_State *L) {
static int setlocal (lua_State *L) {
lua_Debug ar;
if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */
if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
return luaL_argerror(L, 1, "level out of range");
luaL_check_any(L, 3);
lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2)));
luaL_checkany(L, 3);
lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
return 1;
}
static int auxupvalue (lua_State *L, int get) {
const char *name;
int n = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TFUNCTION);
if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == NULL) return 0;
lua_pushstring(L, name);
lua_insert(L, -(get+1));
return get + 1;
}
static int getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
static int setupvalue (lua_State *L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
static const char KEY_HOOK = 'h';
static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] = {"call", "return", "line", "count"};
static const char *const hooknames[] =
{"call", "return", "line", "count", "tail return"};
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0) lua_pushnumber(L, ar->currentline);
if (ar->currentline >= 0)
lua_pushnumber(L, (lua_Number)ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
@@ -126,16 +154,17 @@ static void hookf (lua_State *L, lua_Debug *ar) {
}
static unsigned long makemask (const char *smask, int count) {
unsigned long mask = 0;
static int makemask (const char *smask, int count) {
int mask = 0;
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
return mask | LUA_MASKCOUNT(count);
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
}
static char *unmakemask (unsigned long mask, char *smask) {
static char *unmakemask (int mask, char *smask) {
int i = 0;
if (mask & LUA_MASKCALL) smask[i++] = 'c';
if (mask & LUA_MASKRET) smask[i++] = 'r';
@@ -148,14 +177,13 @@ static char *unmakemask (unsigned long mask, char *smask) {
static int sethook (lua_State *L) {
if (lua_isnoneornil(L, 1)) {
lua_settop(L, 1);
lua_sethook(L, NULL, 0); /* turn off hooks */
lua_sethook(L, NULL, 0, 0); /* turn off hooks */
}
else {
const char *smask = luaL_check_string(L, 2);
lua_Number count = luaL_opt_number(L, 3, 0);
luaL_check_type(L, 1, LUA_TFUNCTION);
luaL_arg_check(L, count <= LUA_MAXCOUNT, 2, "count too large (>= 2^24)");
lua_sethook(L, hookf, makemask(smask, count));
const char *smask = luaL_checkstring(L, 2);
int count = luaL_optint(L, 3, 0);
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_sethook(L, hookf, makemask(smask, count), count);
}
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_pushvalue(L, 1);
@@ -166,11 +194,16 @@ static int sethook (lua_State *L) {
static int gethook (lua_State *L) {
char buff[5];
unsigned long mask = lua_gethookmask(L);
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
int mask = lua_gethookmask(L);
lua_Hook hook = lua_gethook(L);
if (hook != NULL && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
}
lua_pushstring(L, unmakemask(mask, buff));
lua_pushnumber(L, lua_getmaskcount(mask));
lua_pushnumber(L, (lua_Number)lua_gethookcount(L));
return 3;
}
@@ -198,21 +231,22 @@ static int errorfb (lua_State *L) {
if (lua_gettop(L) == 0)
lua_pushliteral(L, "");
else if (!lua_isstring(L, 1)) return 1; /* no string message */
lua_pushliteral(L, "stack traceback:\n");
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
if (!lua_getstack(L, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\t...\n"); /* too many levels */
lua_pushliteral(L, "\n\t..."); /* too many levels */
while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\t");
lua_pushliteral(L, "\n\t");
lua_getinfo(L, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
@@ -227,14 +261,13 @@ static int errorfb (lua_State *L) {
default: {
if (*ar.what == 'm') /* main? */
lua_pushfstring(L, " in main chunk");
else if (*ar.what == 'C') /* C function? */
lua_pushfstring(L, "%s", ar.short_src);
else if (*ar.what == 'C' || *ar.what == 't')
lua_pushliteral(L, " ?"); /* C function or tail call */
else
lua_pushfstring(L, " in function <%s:%d>",
ar.short_src, ar.linedefined);
}
}
lua_pushliteral(L, "\n");
lua_concat(L, lua_gettop(L));
}
lua_concat(L, lua_gettop(L));
@@ -246,19 +279,21 @@ static const luaL_reg dblib[] = {
{"getlocal", getlocal},
{"getinfo", getinfo},
{"gethook", gethook},
{"getupvalue", getupvalue},
{"sethook", sethook},
{"setlocal", setlocal},
{"setupvalue", setupvalue},
{"debug", debug},
{"traceback", errorfb},
{NULL, NULL}
};
LUALIB_API int lua_dblibopen (lua_State *L) {
luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0);
LUALIB_API int luaopen_debug (lua_State *L) {
luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
lua_pushliteral(L, "_TRACEBACK");
lua_pushcfunction(L, errorfb);
lua_settable(L, LUA_GLOBALSINDEX);
return 0;
return 1;
}

227
ldebug.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 1.131 2002/08/08 20:08:41 roberto Exp roberto $
** $Id: ldebug.c,v 1.149 2003/03/18 12:50:04 roberto Exp roberto $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,8 @@
#include <stdlib.h>
#include <string.h>
#define ldebug_c
#include "lua.h"
#include "lapi.h"
@@ -49,20 +51,27 @@ static int currentline (CallInfo *ci) {
}
LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask) {
int allow;
void luaG_inithooks (lua_State *L) {
CallInfo *ci;
lua_lock(L);
allow = allowhook(L);
if (func == NULL) mask = 0;
else if (mask == 0) func = NULL;
L->hook = func;
L->hookmask = mask;
setallowhook(L, allow);
resethookcount(L);
for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */
currentpc(ci);
lua_unlock(L);
L->hookinit = 1;
}
/*
** this function can be called asynchronous (e.g. during a signal)
*/
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
if (func == NULL || mask == 0) { /* turn off hooks? */
mask = 0;
func = NULL;
}
L->hook = func;
L->basehookcount = count;
resethookcount(L);
L->hookmask = cast(lu_byte, mask);
L->hookinit = 0;
return 1;
}
@@ -72,18 +81,33 @@ LUA_API lua_Hook lua_gethook (lua_State *L) {
}
LUA_API unsigned long lua_gethookmask (lua_State *L) {
LUA_API int lua_gethookmask (lua_State *L) {
return L->hookmask;
}
LUA_API int lua_gethookcount (lua_State *L) {
return L->basehookcount;
}
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status;
CallInfo *ci;
lua_lock(L);
if (L->ci - L->base_ci <= level) status = 0; /* there is no such level */
else {
ar->i_ci = (L->ci - L->base_ci) - level;
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
level--;
if (!(ci->state & CI_C)) /* Lua function? */
level -= ci->u.l.tailcalls; /* skip lost tail calls */
}
if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */
else if (level < 0) { /* level is of a lost tail call */
status = 1;
ar->i_ci = 0;
}
else {
status = 1;
ar->i_ci = ci - L->base_ci;
}
lua_unlock(L);
return status;
@@ -127,38 +151,26 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
if (!name || name[0] == '(') /* `(' starts private locals */
name = NULL;
else
setobj(ci->base+(n-1), L->top);
setobjs2s(ci->base+(n-1), L->top);
}
lua_unlock(L);
return name;
}
static void infoLproto (lua_Debug *ar, Proto *f) {
ar->source = getstr(f->source);
ar->linedefined = f->lineDefined;
ar->what = "Lua";
}
static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) {
Closure *cl;
if (ttisfunction(func))
cl = clvalue(func);
else {
luaG_runerror(L, "value for `lua_getinfo' is not a function");
cl = NULL; /* to avoid warnings */
}
static void funcinfo (lua_Debug *ar, StkId func) {
Closure *cl = clvalue(func);
if (cl->c.isC) {
ar->source = "=[C]";
ar->linedefined = -1;
ar->what = "C";
}
else
infoLproto(ar, cl->l.p);
else {
ar->source = getstr(cl->l.p->source);
ar->linedefined = cl->l.p->lineDefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
if (ar->linedefined == 0)
ar->what = "main";
}
@@ -166,41 +178,32 @@ static const char *travglobals (lua_State *L, const TObject *o) {
Table *g = hvalue(gt(L));
int i = sizenode(g);
while (i--) {
Node *n = node(g, i);
if (luaO_rawequalObj(o, val(n)) && ttisstring(key(n)))
return getstr(tsvalue(key(n)));
Node *n = gnode(g, i);
if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n)))
return getstr(tsvalue(gkey(n)));
}
return NULL;
}
static void getname (lua_State *L, const TObject *f, lua_Debug *ar) {
/* try to find a name for given function */
if ((ar->name = travglobals(L, f)) != NULL)
ar->namewhat = "global";
else ar->namewhat = ""; /* not found */
static void info_tailcall (lua_State *L, lua_Debug *ar) {
ar->name = ar->namewhat = "";
ar->what = "tail";
ar->linedefined = ar->currentline = -1;
ar->source = "=(tail call)";
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
ar->nups = 0;
setnilvalue(L->top);
}
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
StkId f;
CallInfo *ci;
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
StkId f, CallInfo *ci) {
int status = 1;
lua_lock(L);
if (*what != '>') { /* function is active? */
ci = L->base_ci + ar->i_ci;
f = ci->base - 1;
}
else {
what++; /* skip the `>' */
ci = NULL;
f = L->top - 1;
}
for (; *what; what++) {
switch (*what) {
case 'S': {
funcinfo(L, ar, f);
funcinfo(ar, f);
break;
}
case 'l': {
@@ -208,25 +211,48 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
break;
}
case 'u': {
ar->nups = (ttisfunction(f)) ? clvalue(f)->c.nupvalues : 0;
ar->nups = clvalue(f)->c.nupvalues;
break;
}
case 'n': {
ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL;
if (ar->namewhat == NULL)
getname(L, f, ar);
if (ar->namewhat == NULL) {
/* try to find a global name */
if ((ar->name = travglobals(L, f)) != NULL)
ar->namewhat = "global";
else ar->namewhat = ""; /* not found */
}
break;
}
case 'f': {
setobj(L->top, f);
status = 2;
setobj2s(L->top, f);
break;
}
default: status = 0; /* invalid option */
}
}
if (!ci) L->top--; /* pop function */
if (status == 2) incr_top(L);
return status;
}
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
int status = 1;
lua_lock(L);
if (*what == '>') {
StkId f = L->top - 1;
if (!ttisfunction(f))
luaG_runerror(L, "value for `lua_getinfo' is not a function");
status = auxgetinfo(L, what + 1, ar, f, NULL);
L->top--; /* pop function */
}
else if (ar->i_ci != 0) { /* no tail call? */
CallInfo *ci = L->base_ci + ar->i_ci;
lua_assert(ttisfunction(ci->base - 1));
status = auxgetinfo(L, what, ar, ci->base - 1, ci);
}
else
info_tailcall(L, ar);
if (strchr(what, 'f')) incr_top(L);
lua_unlock(L);
return status;
}
@@ -248,6 +274,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
static int precheck (const Proto *pt) {
check(pt->maxstacksize <= MAXSTACK);
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize);
check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
return 1;
@@ -269,6 +296,11 @@ static int checkopenop (const Proto *pt, int pc) {
}
static int checkRK (const Proto *pt, int r) {
return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek));
}
static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
int pc;
int last; /* stores position of last instruction that changed `reg' */
@@ -285,11 +317,13 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
case iABC: {
b = GETARG_B(i);
c = GETARG_C(i);
if (testOpMode(op, OpModeBreg))
if (testOpMode(op, OpModeBreg)) {
checkreg(pt, b);
if (testOpMode(op, OpModeCreg))
check(c < pt->maxstacksize ||
(c >= MAXSTACK && c-MAXSTACK < pt->sizek));
}
else if (testOpMode(op, OpModeBrk))
check(checkRK(pt, b));
if (testOpMode(op, OpModeCrk))
check(checkRK(pt, c));
break;
}
case iABx: {
@@ -321,7 +355,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
}
case OP_GETUPVAL:
case OP_SETUPVAL: {
check(b < pt->nupvalues);
check(b < pt->nups);
break;
}
case OP_GETGLOBAL:
@@ -340,7 +374,8 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
break;
}
case OP_TFORLOOP:
checkreg(pt, a+2+c);
checkreg(pt, a+c+5);
if (reg >= a) last = pc; /* affect all registers above base */
/* go through */
case OP_FORLOOP:
checkreg(pt, a+2);
@@ -379,7 +414,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
case OP_CLOSURE: {
int nup;
check(b < pt->sizep);
nup = pt->p[b]->nupvalues;
nup = pt->p[b]->nups;
check(pc + nup < pt->sizecode);
for (; nup>0; nup--) {
OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
@@ -426,8 +461,9 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
lua_assert(pc != -1);
switch (GET_OPCODE(i)) {
case OP_GETGLOBAL: {
lua_assert(ttisstring(&p->k[GETARG_Bx(i)]));
*name = svalue(&p->k[GETARG_Bx(i)]);
int g = GETARG_Bx(i); /* global index */
lua_assert(ttisstring(&p->k[g]));
*name = svalue(&p->k[g]);
return "global";
}
case OP_MOVE: {
@@ -438,11 +474,13 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
break;
}
case OP_GETTABLE: {
*name = kname(p, GETARG_C(i));
int k = GETARG_C(i); /* key index */
*name = kname(p, k);
return "field";
}
case OP_SELF: {
*name = kname(p, GETARG_C(i));
int k = GETARG_C(i); /* key index */
*name = kname(p, k);
return "method";
}
default: break;
@@ -452,18 +490,16 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
}
static Instruction getcurrentinstr (CallInfo *ci) {
return (!isLua(ci)) ? (Instruction)(-1) :
ci_func(ci)->l.p->code[currentpc(ci)];
}
static const char *getfuncname (CallInfo *ci, const char **name) {
Instruction i;
if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1))
return NULL; /* calling function is not Lua (or is unknown) */
ci--; /* calling function */
i = getcurrentinstr(ci);
return (GET_OPCODE(i) == OP_CALL ? getobjname(ci, GETARG_A(i), name)
: NULL); /* no useful name found */
i = ci_func(ci)->l.p->code[currentpc(ci)];
if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL)
return getobjname(ci, GETARG_A(i), name);
else
return NULL; /* no useful name can be found */
}
@@ -480,7 +516,7 @@ void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
const char *name = NULL;
const char *t = luaT_typenames[ttype(o)];
const char *kind = (isinstack(L->ci, o)) ?
getobjname(L->ci, o - L->ci->base, &name) : NULL;
getobjname(L->ci, o - L->base, &name) : NULL;
if (kind)
luaG_runerror(L, "attempt to %s %s `%s' (a %s value)",
op, kind, name, t);
@@ -492,11 +528,11 @@ void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
if (ttisstring(p1)) p1 = p2;
lua_assert(!ttisstring(p1));
luaG_typeerror(L, p1, "concat");
luaG_typeerror(L, p1, "concatenate");
}
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2) {
void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) {
TObject temp;
if (luaV_tonumber(p1, &temp) == NULL)
p2 = p1; /* first operand is wrong */
@@ -517,14 +553,11 @@ int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
static void addinfo (lua_State *L, const char *msg) {
CallInfo *ci = L->ci;
if (!isLua(ci)) { /* no Lua code? */
luaO_pushfstring(L, "%s\n", msg); /* no extra info; just add '\n' */
}
else { /* add file:line information */
char buff[LUA_IDSIZE];
if (isLua(ci)) { /* is Lua code? */
char buff[LUA_IDSIZE]; /* add file:line information */
int line = currentline(ci);
luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
luaO_pushfstring(L, "%s:%d: %s\n", buff, line, msg);
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
}
}
@@ -533,8 +566,8 @@ void luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
setobj(L->top, L->top - 1); /* move argument */
setobj(L->top - 1, errfunc); /* push function */
setobjs2s(L->top, L->top - 1); /* move argument */
setobjs2s(L->top - 1, errfunc); /* push function */
incr_top(L);
luaD_call(L, L->top - 2, 1); /* call it */
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldebug.h,v 1.29 2002/08/08 20:08:41 roberto Exp roberto $
** $Id: ldebug.h,v 1.31 2002/08/20 20:03:05 roberto Exp roberto $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -15,15 +15,13 @@
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
#define resethookcount(L) (L->hookcount = lua_getmaskcount(L->hookmask))
#define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond))
#define allowhook(L) ((L->hookmask) & 1)
#define resethookcount(L) (L->hookcount = L->basehookcount)
void luaG_inithooks (lua_State *L);
void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2);
void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2);
int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2);
void luaG_runerror (lua_State *L, const char *fmt, ...);
void luaG_errormsg (lua_State *L);

281
ldo.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 1.191 2002/08/07 19:22:39 roberto Exp roberto $
** $Id: ldo.c,v 1.216 2003/02/28 19:45:15 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,8 @@
#include <stdlib.h>
#include <string.h>
#define ldo_c
#include "lua.h"
#include "ldebug.h"
@@ -29,6 +31,7 @@
/*
** {======================================================
** Error-recovery functions (based on long jumps)
@@ -44,22 +47,23 @@ struct lua_longjmp {
};
static void seterrorobj (lua_State *L, int errcode) {
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: {
setsvalue(L->top, luaS_new(L, MEMERRMSG));
setsvalue2s(oldtop, luaS_new(L, MEMERRMSG));
break;
}
case LUA_ERRERR: {
setsvalue(L->top, luaS_new(L, "error in error handling"));
setsvalue2s(oldtop, luaS_new(L, "error in error handling"));
break;
}
case LUA_ERRSYNTAX:
case LUA_ERRRUN: {
return; /* error message already on top */
setobjs2s(oldtop, L->top - 1); /* error message on current top */
break;
}
}
L->top++;
L->top = oldtop + 1;
}
@@ -101,16 +105,15 @@ static void restore_stack_limit (lua_State *L) {
static void correctstack (lua_State *L, TObject *oldstack) {
CallInfo *ci;
UpVal *up;
GCObject *up;
L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->next)
up->v = (up->v - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->gch.next)
gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack;
for (ci = L->base_ci; ci <= L->ci; ci++) {
ci->base = (ci->base - oldstack) + L->stack;
ci->top = (ci->top - oldstack) + L->stack;
if (ci->state & CI_HASFRAME) /* Lua function with active frame? */
*ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */
ci->base = (ci->base - oldstack) + L->stack;
}
L->base = L->ci->base;
}
@@ -126,7 +129,7 @@ void luaD_reallocstack (lua_State *L, int newsize) {
void luaD_reallocCI (lua_State *L, int newsize) {
CallInfo *oldci = L->base_ci;
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
L->size_ci = newsize;
L->size_ci = cast(unsigned short, newsize);
L->ci = (L->ci - oldci) + L->base_ci;
L->end_ci = L->base_ci + L->size_ci;
}
@@ -151,23 +154,26 @@ static void luaD_growCI (lua_State *L) {
}
void luaD_callhook (lua_State *L, lua_Hookevent event, int line) {
void luaD_callhook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook;
if (hook && allowhook(L)) {
if (hook && L->allowhook) {
ptrdiff_t top = savestack(L, L->top);
ptrdiff_t ci_top = savestack(L, L->ci->top);
lua_Debug ar;
ar.event = event;
ar.currentline = line;
ar.i_ci = L->ci - L->base_ci;
if (event == LUA_HOOKTAILRET)
ar.i_ci = 0; /* tail call; no debug information about it */
else
ar.i_ci = L->ci - L->base_ci;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
L->ci->top = L->top + LUA_MINSTACK;
setallowhook(L, 0); /* cannot call hooks inside a hook */
L->allowhook = 0; /* cannot call hooks inside a hook */
lua_unlock(L);
(*hook)(L, &ar);
lua_lock(L);
lua_assert(!allowhook(L));
setallowhook(L, 1);
lua_assert(!L->allowhook);
L->allowhook = 1;
L->ci->top = restorestack(L, ci_top);
L->top = restorestack(L, top);
}
@@ -185,12 +191,12 @@ static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
setnilvalue(L->top++);
}
actual -= nfixargs; /* number of extra arguments */
htab = luaH_new(L, 0, 0); /* create `arg' table */
htab = luaH_new(L, actual, 1); /* create `arg' table */
for (i=0; i<actual; i++) /* put extra arguments into `arg' table */
setobj(luaH_setnum(L, htab, i+1), L->top - actual + i);
setobj2n(luaH_setnum(L, htab, i+1), L->top - actual + i);
/* store counter in field `n' */
setsvalue(&nname, luaS_newliteral(L, "n"));
setnvalue(luaH_set(L, htab, &nname), actual);
setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual));
L->top -= actual; /* remove extra elements from the stack */
sethvalue(L->top, htab);
incr_top(L);
@@ -204,10 +210,10 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
if (!ttisfunction(tm))
luaG_typeerror(L, func, "call");
/* Open a hole inside the stack at `func' */
for (p = L->top; p > func; p--) setobj(p, p-1);
for (p = L->top; p > func; p--) setobjs2s(p, p-1);
incr_top(L);
func = restorestack(L, funcr); /* previous call may change stack */
setobj(func, tm); /* tag method is the new function to be called */
setobj2s(func, tm); /* tag method is the new function to be called */
return func;
}
@@ -218,6 +224,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
if (!ttisfunction(func)) /* `func' is not a function? */
func = tryfuncTM(L, func); /* check the `function' tag method */
if (L->ci + 1 == L->end_ci) luaD_growCI(L);
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
cl = &clvalue(func)->l;
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
@@ -226,9 +233,10 @@ StkId luaD_precall (lua_State *L, StkId func) {
adjust_varargs(L, p->numparams, func+1);
luaD_checkstack(L, p->maxstacksize);
ci = ++L->ci; /* now `enter' new function */
ci->base = restorestack(L, funcr) + 1;
ci->top = ci->base + p->maxstacksize;
L->base = L->ci->base = restorestack(L, funcr) + 1;
ci->top = L->base + p->maxstacksize;
ci->u.l.savedpc = p->code; /* starting point */
ci->u.l.tailcalls = 0;
ci->state = CI_SAVEDPC;
while (L->top < ci->top)
setnilvalue(L->top++);
@@ -240,42 +248,48 @@ StkId luaD_precall (lua_State *L, StkId func) {
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci = ++L->ci; /* now `enter' new function */
ci->base = restorestack(L, funcr) + 1;
L->base = L->ci->base = restorestack(L, funcr) + 1;
ci->top = L->top + LUA_MINSTACK;
ci->state = CI_C; /* a C function */
if (L->hookmask & LUA_MASKCALL) {
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
ci = L->ci; /* previous call may realocate `ci' */
}
lua_unlock(L);
#ifdef LUA_COMPATUPVALUES
lua_pushupvalues(L);
#endif
n = (*clvalue(ci->base-1)->c.f)(L); /* do the actual call */
n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */
lua_lock(L);
return L->top - n;
}
}
static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
if (!(L->ci->state & CI_C)) { /* Lua function? */
while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
}
void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
StkId res;
if (L->hookmask & LUA_MASKRET) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
firstResult = restorestack(L, fr);
}
res = L->ci->base - 1; /* res == final position of 1st result */
if (L->hookmask & LUA_MASKRET)
firstResult = callrethooks(L, firstResult);
res = L->base - 1; /* res == final position of 1st result */
L->ci--;
L->base = L->ci->base; /* restore base */
/* move results to correct place */
while (wanted != 0 && firstResult < L->top) {
setobj(res++, firstResult++);
setobjs2s(res++, firstResult++);
wanted--;
}
while (wanted-- > 0)
setnilvalue(res++);
L->top = res;
luaC_checkGC(L);
}
@@ -286,73 +300,70 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
** function position.
*/
void luaD_call (lua_State *L, StkId func, int nResults) {
StkId firstResult = luaD_precall(L, func);
if (firstResult == NULL) { /* is a Lua function? */
StkId firstResult;
lua_assert(!(L->ci->state & CI_CALLING));
if (++L->nCcalls >= LUA_MAXCCALLS) {
if (L->nCcalls == LUA_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
firstResult = luaD_precall(L, func);
if (firstResult == NULL) /* is a Lua function? */
firstResult = luaV_execute(L); /* call it */
if (firstResult == NULL) {
luaD_poscall(L, 0, L->top);
luaG_runerror(L, "attempt to yield across tag-method/C-call boundary");
}
}
luaD_poscall(L, nResults, firstResult);
}
LUA_API void lua_cobegin (lua_State *L, int nargs) {
lua_lock(L);
luaD_precall(L, L->top - (nargs+1));
lua_unlock(L);
}
static void move_results (lua_State *L, TObject *from, TObject *to) {
while (from < to) {
setobj(L->top, from);
from++;
incr_top(L);
}
L->nCcalls--;
luaC_checkGC(L);
}
static void resume (lua_State *L, void *ud) {
StkId firstResult;
int nargs = *cast(int *, ud);
CallInfo *ci = L->ci;
if (ci->state & CI_C) { /* not first time (i.e. inside a yield)? */
/* finish interrupted execution of `OP_CALL' */
int nresults;
lua_assert((ci-1)->state & CI_SAVEDPC);
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
luaD_poscall(L, nresults, L->top); /* complete it */
if (nresults >= 0) L->top = L->ci->top;
if (ci == L->base_ci) { /* no activation record? */
if (nargs >= L->top - L->base)
luaG_runerror(L, "cannot resume dead coroutine");
luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
}
else if (ci->state & CI_YIELD) { /* inside a yield? */
if (ci->state & CI_C) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */
int nresults;
lua_assert((ci-1)->state & CI_SAVEDPC);
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
luaD_poscall(L, nresults, L->top - nargs); /* complete it */
if (nresults >= 0) L->top = L->ci->top;
}
else { /* yielded inside a hook: just continue its execution */
ci->state &= ~CI_YIELD;
}
}
else
luaG_runerror(L, "cannot resume non-suspended coroutine");
firstResult = luaV_execute(L);
if (firstResult == NULL) /* yield? */
*cast(int *, ud) = L->ci->u.c.yield_results;
else { /* return */
*cast(int *, ud) = L->top - firstResult;
if (firstResult != NULL) /* return? */
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
}
}
LUA_API int lua_resume (lua_State *L, lua_State *co) {
CallInfo *ci;
int numres;
LUA_API int lua_resume (lua_State *L, int nargs) {
int status;
lu_byte old_allowhooks;
lua_lock(L);
ci = co->ci;
if (ci == co->base_ci) /* no activation record? ?? */
luaG_runerror(L, "cannot resume dead thread");
if (co->errorJmp != NULL) /* ?? */
luaG_runerror(L, "cannot resume active thread");
status = luaD_rawrunprotected(co, resume, &numres);
if (status == 0)
move_results(L, co->top - numres, co->top);
else {
setobj(L->top++, co->top - 1); /* move error message to other stack */
co->ci = co->base_ci; /* `kill' thread */
old_allowhooks = L->allowhook;
lua_assert(L->errfunc == 0 && L->nCcalls == 0);
status = luaD_rawrunprotected(L, resume, &nargs);
if (status != 0) { /* error? */
L->ci = L->base_ci; /* go back to initial level */
L->base = L->ci->base;
L->nCcalls = 0;
luaF_close(L, L->base); /* close eventual pending closures */
seterrorobj(L, status, L->base);
L->allowhook = old_allowhooks;
restore_stack_limit(L);
}
lua_unlock(L);
return status;
@@ -363,51 +374,41 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
CallInfo *ci;
lua_lock(L);
ci = L->ci;
if ((ci-1)->state & CI_C)
luaG_runerror(L, "cannot yield a C function");
lua_assert(ci->state & CI_C); /* current function is not Lua */
ci->u.c.yield_results = nresults;
if (L->nCcalls > 0)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
if (ci->state & CI_C) { /* usual yield */
if ((ci-1)->state & CI_C)
luaG_runerror(L, "cannot yield a C function");
if (L->top - nresults > L->base) { /* is there garbage in the stack? */
int i;
for (i=0; i<nresults; i++) /* move down results */
setobjs2s(L->base + i, L->top - nresults + i);
L->top = L->base + nresults;
}
} /* else it's an yield inside a hook: nothing to do */
ci->state |= CI_YIELD;
lua_unlock(L);
return -1;
}
/*
** Execute a protected call.
*/
struct CallS { /* data to `f_call' */
StkId func;
int nresults;
};
static void f_call (lua_State *L, void *ud) {
struct CallS *c = cast(struct CallS *, ud);
luaD_call(L, c->func, c->nresults);
}
int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
struct CallS c;
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
ptrdiff_t old_top = savestack(L, L->top);
unsigned short oldnCcalls = L->nCcalls;
ptrdiff_t old_ci = saveci(L, L->ci);
int old_allowhooks = allowhook(L);
lu_byte old_allowhooks = L->allowhook;
ptrdiff_t old_errfunc = L->errfunc;
L->errfunc = errfunc;
c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
status = luaD_rawrunprotected(L, &f_call, &c);
L->errfunc = ef;
status = luaD_rawrunprotected(L, func, u);
if (status != 0) { /* an error occurred? */
StkId err; /* error msg. position */
seterrorobj(L, status);
err = L->top - 1;
/* remove parameters and func from the stack */
L->top = restorestack(L, old_top) - (nargs+1);
setobj(L->top++, err); /* copy error message to corrected top */
luaF_close(L, L->top); /* close eventual pending closures */
StkId oldtop = restorestack(L, old_top);
luaF_close(L, oldtop); /* close eventual pending closures */
seterrorobj(L, status, oldtop);
L->nCcalls = oldnCcalls;
L->ci = restoreci(L, old_ci);
setallowhook(L, old_allowhooks);
L->base = L->ci->base;
L->allowhook = old_allowhooks;
restore_stack_limit(L);
}
L->errfunc = old_errfunc;
@@ -415,18 +416,24 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
}
/*
** Execute a protected parser.
*/
struct SParser { /* data to `f_parser' */
ZIO *z;
Mbuffer buff; /* buffer to be used by the scanner */
int bin;
};
static void f_parser (lua_State *L, void *ud) {
struct SParser *p = cast(struct SParser *, ud);
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
Closure *cl = luaF_newLclosure(L, 0, gt(L));
struct SParser *p;
Proto *tf;
Closure *cl;
luaC_checkGC(L);
p = cast(struct SParser *, ud);
tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff);
cl = luaF_newLclosure(L, 0, gt(L));
cl->l.p = tf;
setclvalue(L->top, cl);
incr_top(L);
@@ -435,25 +442,15 @@ static void f_parser (lua_State *L, void *ud) {
int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
struct SParser p;
lu_mem old_blocks;
int status;
ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
p.z = z; p.bin = bin;
/* before parsing, give a (good) chance to GC */
if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
luaC_collectgarbage(L);
old_blocks = G(L)->nblocks;
luaZ_initbuffer(L, &p.buff);
status = luaD_rawrunprotected(L, f_parser, &p);
if (status == 0) {
/* add new memory to threshold (as it probably will stay) */
lua_assert(G(L)->nblocks >= old_blocks);
G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
}
else { /* error */
luaZ_freebuffer(L, &p.buff);
if (status != 0) { /* error? */
StkId oldtop = restorestack(L, oldtopr);
seterrorobj(L, status);
setobj(oldtop, L->top - 1); /* copy error message to old top */
L->top = oldtop+1;
seterrorobj(L, status, oldtop);
}
return status;
}

26
ldo.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 1.50 2002/08/06 15:32:22 roberto Exp roberto $
** $Id: ldo.h,v 1.55 2002/11/21 17:41:25 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -14,15 +14,22 @@
/*
** macro to increment stack top.
** There must be always an empty slot at the L->stack.top
*/
#define incr_top(L) \
{if (L->top >= L->stack_last) luaD_growstack(L, 1); L->top++;}
** macro to control inclusion of some hard tests on stack reallocation
*/
#ifndef HARDSTACKTESTS
#define condhardstacktests(x) { /* empty */ }
#else
#define condhardstacktests(x) x
#endif
#define luaD_checkstack(L,n) \
if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \
luaD_growstack(L, n)
luaD_growstack(L, n); \
else condhardstacktests(luaD_reallocstack(L, L->stacksize));
#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
#define restorestack(L,n) ((TObject *)((char *)L->stack + (n)))
@@ -36,10 +43,11 @@ typedef void (*Pfunc) (lua_State *L, void *ud);
void luaD_resetprotection (lua_State *L);
int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
void luaD_callhook (lua_State *L, int event, int line);
StkId luaD_precall (lua_State *L, StkId func);
void luaD_call (lua_State *L, StkId func, int nResults);
int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc);
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
void luaD_poscall (lua_State *L, int wanted, StkId firstResult);
void luaD_reallocCI (lua_State *L, int newsize);
void luaD_reallocstack (lua_State *L, int newsize);

170
ldump.c Normal file
View File

@@ -0,0 +1,170 @@
/*
** $Id: ldump.c,v 1.4 2003/02/11 23:52:12 lhf Exp $
** save bytecodes
** See Copyright Notice in lua.h
*/
#include <stddef.h>
#define ldump_c
#include "lua.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lundump.h"
#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D)
#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D)
typedef struct {
lua_State* L;
lua_Chunkwriter write;
void* data;
} DumpState;
static void DumpBlock(const void* b, size_t size, DumpState* D)
{
lua_unlock(D->L);
(*D->write)(D->L,b,size,D->data);
lua_lock(D->L);
}
static void DumpByte(int y, DumpState* D)
{
char x=(char)y;
DumpBlock(&x,sizeof(x),D);
}
static void DumpInt(int x, DumpState* D)
{
DumpBlock(&x,sizeof(x),D);
}
static void DumpSize(size_t x, DumpState* D)
{
DumpBlock(&x,sizeof(x),D);
}
static void DumpNumber(lua_Number x, DumpState* D)
{
DumpBlock(&x,sizeof(x),D);
}
static void DumpString(TString* s, DumpState* D)
{
if (s==NULL || getstr(s)==NULL)
DumpSize(0,D);
else
{
size_t size=s->tsv.len+1; /* include trailing '\0' */
DumpSize(size,D);
DumpBlock(getstr(s),size,D);
}
}
static void DumpCode(const Proto* f, DumpState* D)
{
DumpInt(f->sizecode,D);
DumpVector(f->code,f->sizecode,sizeof(*f->code),D);
}
static void DumpLocals(const Proto* f, DumpState* D)
{
int i,n=f->sizelocvars;
DumpInt(n,D);
for (i=0; i<n; i++)
{
DumpString(f->locvars[i].varname,D);
DumpInt(f->locvars[i].startpc,D);
DumpInt(f->locvars[i].endpc,D);
}
}
static void DumpLines(const Proto* f, DumpState* D)
{
DumpInt(f->sizelineinfo,D);
DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D);
}
static void DumpUpvalues(const Proto* f, DumpState* D)
{
int i,n=f->sizeupvalues;
DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
}
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
static void DumpConstants(const Proto* f, DumpState* D)
{
int i,n;
DumpInt(n=f->sizek,D);
for (i=0; i<n; i++)
{
const TObject* o=&f->k[i];
DumpByte(ttype(o),D);
switch (ttype(o))
{
case LUA_TNUMBER:
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
DumpString(tsvalue(o),D);
break;
case LUA_TNIL:
break;
default:
lua_assert(0); /* cannot happen */
break;
}
}
DumpInt(n=f->sizep,D);
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
}
static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
{
DumpString((f->source==p) ? NULL : f->source,D);
DumpInt(f->lineDefined,D);
DumpByte(f->nups,D);
DumpByte(f->numparams,D);
DumpByte(f->is_vararg,D);
DumpByte(f->maxstacksize,D);
DumpLines(f,D);
DumpLocals(f,D);
DumpUpvalues(f,D);
DumpConstants(f,D);
DumpCode(f,D);
}
static void DumpHeader(DumpState* D)
{
DumpLiteral(LUA_SIGNATURE,D);
DumpByte(VERSION,D);
DumpByte(luaU_endianness(),D);
DumpByte(sizeof(int),D);
DumpByte(sizeof(size_t),D);
DumpByte(sizeof(Instruction),D);
DumpByte(SIZE_OP,D);
DumpByte(SIZE_A,D);
DumpByte(SIZE_B,D);
DumpByte(SIZE_C,D);
DumpByte(sizeof(lua_Number),D);
DumpNumber(TEST_NUMBER,D);
}
/*
** dump function as precompiled chunk
*/
void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data)
{
DumpState D;
D.L=L;
D.write=w;
D.data=data;
DumpHeader(&D);
DumpFunction(Main,NULL,&D);
}

58
lfunc.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lfunc.c,v 1.56 2002/05/02 13:06:20 roberto Exp roberto $
** $Id: lfunc.c,v 1.66 2003/02/11 10:46:24 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -7,9 +7,12 @@
#include <stdlib.h>
#define lfunc_c
#include "lua.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
@@ -25,85 +28,84 @@
Closure *luaF_newCclosure (lua_State *L, int nelems) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
luaC_link(L, valtogco(c), LUA_TFUNCTION);
c->c.isC = 1;
c->c.next = G(L)->rootcl;
G(L)->rootcl = c;
c->c.marked = 0;
c->c.nupvalues = cast(lu_byte, nelems);
return c;
}
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt) {
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
luaC_link(L, valtogco(c), LUA_TFUNCTION);
c->l.isC = 0;
c->c.next = G(L)->rootcl;
G(L)->rootcl = c;
c->l.marked = 0;
c->l.g = *gt;
c->l.g = *e;
c->l.nupvalues = cast(lu_byte, nelems);
return c;
}
UpVal *luaF_findupval (lua_State *L, StkId level) {
UpVal **pp = &L->openupval;
GCObject **pp = &L->openupval;
UpVal *p;
while ((p = *pp) != NULL && p->v >= level) {
UpVal *v;
while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
if (p->v == level) return p;
pp = &p->next;
}
p = luaM_new(L, UpVal); /* not found: create a new one */
p->v = level; /* current value lives in the stack */
p->next = *pp; /* chain it in the proper position */
*pp = p;
return p;
v = luaM_new(L, UpVal); /* not found: create a new one */
v->tt = LUA_TUPVAL;
v->marked = 1; /* open upvalues should not be collected */
v->v = level; /* current value lives in the stack */
v->next = *pp; /* chain it in the proper position */
*pp = valtogco(v);
return v;
}
void luaF_close (lua_State *L, StkId level) {
UpVal *p;
while ((p = L->openupval) != NULL && p->v >= level) {
setobj(&p->value, p->v); /* save current value */
while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) {
setobj(&p->value, p->v); /* save current value (write barrier) */
p->v = &p->value; /* now current value lives here */
L->openupval = p->next; /* remove from `open' list */
p->next = G(L)->rootupval; /* chain in `closed' list */
G(L)->rootupval = p;
luaC_link(L, valtogco(p), LUA_TUPVAL);
}
}
Proto *luaF_newproto (lua_State *L) {
Proto *f = luaM_new(L, Proto);
luaC_link(L, valtogco(f), LUA_TPROTO);
f->k = NULL;
f->sizek = 0;
f->p = NULL;
f->sizep = 0;
f->code = NULL;
f->sizecode = 0;
f->nupvalues = 0;
f->sizelineinfo = 0;
f->sizeupvalues = 0;
f->nups = 0;
f->upvalues = NULL;
f->numparams = 0;
f->is_vararg = 0;
f->maxstacksize = 0;
f->marked = 0;
f->lineinfo = NULL;
f->sizelocvars = 0;
f->locvars = NULL;
f->lineDefined = 0;
f->source = NULL;
f->next = G(L)->rootproto; /* chain in list of protos */
G(L)->rootproto = f;
return f;
}
void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
if (f->lineinfo)
luaM_freearray(L, f->lineinfo, f->sizecode, int);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->k, f->sizek, TObject);
luaM_freearray(L, f->p, f->sizep, Proto *);
luaM_freearray(L, f->k, f->sizek, TObject);
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
luaM_freelem(L, f);
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lfunc.h,v 1.19 2001/11/29 20:22:22 roberto Exp roberto $
** $Id: lfunc.h,v 1.20 2002/06/20 20:41:46 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -13,7 +13,7 @@
Proto *luaF_newproto (lua_State *L);
Closure *luaF_newCclosure (lua_State *L, int nelems);
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt);
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e);
UpVal *luaF_findupval (lua_State *L, StkId level);
void luaF_close (lua_State *L, StkId level);
void luaF_freeproto (lua_State *L, Proto *f);

681
lgc.c
View File

@@ -1,11 +1,13 @@
/*
** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $
** $Id: lgc.c,v 1.170 2003/03/18 12:50:04 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#include <string.h>
#define lgc_c
#include "lua.h"
#include "ldebug.h"
@@ -21,183 +23,112 @@
typedef struct GCState {
Table *tmark; /* list of marked tables to be visited */
Table *toclear; /* list of visited weak tables (to be cleared after GC) */
lua_State *L;
GCObject *tmark; /* list of marked objects to be traversed */
GCObject *wk; /* list of traversed key-weak tables (to be cleared) */
GCObject *wv; /* list of traversed value-weak tables */
GCObject *wkv; /* list of traversed key-value weak tables */
global_State *g;
} GCState;
/* mark a string; marks larger than 1 cannot be changed */
#define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;}
/*
** some userful bit tricks
*/
#define setbit(x,b) ((x) |= (1<<(b)))
#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b))))
#define testbit(x,b) ((x) & (1<<(b)))
#define unmark(x) resetbit((x)->gch.marked, 0)
#define ismarked(x) ((x)->gch.marked & ((1<<4)|1))
#define stringmark(s) setbit((s)->tsv.marked, 0)
/* unmarked tables are represented by pointing `mark' to themselves */
#define ismarked(x) ((x)->mark != (x))
#define isfinalized(u) (!testbit((u)->uv.marked, 1))
#define markfinalized(u) resetbit((u)->uv.marked, 1)
#define KEYWEAKBIT 1
#define VALUEWEAKBIT 2
#define KEYWEAK (1<<KEYWEAKBIT)
#define VALUEWEAK (1<<VALUEWEAKBIT)
/* mark tricks for userdata */
#define isudmarked(u) (u->uv.len & 1)
#define markud(u) (u->uv.len |= 1)
#define unmarkud(u) (u->uv.len &= (~(size_t)1))
#define markobject(st,o) { checkconsistency(o); \
if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); }
#define isfinalized(u) (u->uv.len & 2)
#define markfinalized(u) (u->uv.len |= 2)
#define condmarkobject(st,o,c) { checkconsistency(o); \
if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \
reallymarkobject(st,gcvalue(o)); }
/* mark tricks for upvalues (assume that open upvalues are always marked) */
#define isupvalmarked(uv) ((uv)->v != &(uv)->value)
#define markvalue(st,t) { if (!ismarked(valtogco(t))) \
reallymarkobject(st, valtogco(t)); }
#define ismarkable(o) (!((1 << ttype(o)) & \
((1 << LUA_TNIL) | (1 << LUA_TNUMBER) | \
(1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA))))
static void reallymarkobject (GCState *st, TObject *o);
#define markobject(st,o) if (ismarkable(o)) reallymarkobject(st,o)
static void protomark (Proto *f) {
if (!f->marked) {
int i;
f->marked = 1;
strmark(f->source);
for (i=0; i<f->sizek; i++) {
if (ttisstring(f->k+i))
strmark(tsvalue(f->k+i));
}
for (i=0; i<f->sizep; i++)
protomark(f->p[i]);
for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
strmark(f->locvars[i].varname);
}
lua_assert(luaG_checkcode(f));
}
static void marktable (GCState *st, Table *h) {
if (!ismarked(h)) {
h->mark = st->tmark; /* chain it for later traversal */
st->tmark = h;
}
}
static void markclosure (GCState *st, Closure *cl) {
if (!cl->c.marked) {
cl->c.marked = 1;
if (cl->c.isC) {
int i;
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
markobject(st, &cl->c.upvalue[i]);
}
else {
int i;
lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
marktable(st, hvalue(&cl->l.g));
protomark(cl->l.p);
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
UpVal *u = cl->l.upvals[i];
if (!isupvalmarked(u)) {
markobject(st, &u->value);
u->v = NULL; /* mark it! */
}
}
}
}
}
static void markudata (GCState *st, Udata *u) {
markud(u);
marktable(st, u->uv.metatable);
}
static void reallymarkobject (GCState *st, TObject *o) {
switch (ttype(o)) {
case LUA_TSTRING:
strmark(tsvalue(o));
static void reallymarkobject (GCState *st, GCObject *o) {
lua_assert(!ismarked(o));
setbit(o->gch.marked, 0); /* mark object */
switch (o->gch.tt) {
case LUA_TUSERDATA: {
markvalue(st, gcotou(o)->uv.metatable);
break;
case LUA_TUSERDATA:
if (!isudmarked(uvalue(o)))
markudata(st, uvalue(o));
break;
case LUA_TFUNCTION:
markclosure(st, clvalue(o));
}
case LUA_TFUNCTION: {
gcotocl(o)->c.gclist = st->tmark;
st->tmark = o;
break;
}
case LUA_TTABLE: {
marktable(st, hvalue(o));
gcotoh(o)->gclist = st->tmark;
st->tmark = o;
break;
}
default: lua_assert(0); /* should not be called with other types */
case LUA_TTHREAD: {
gcototh(o)->gclist = st->tmark;
st->tmark = o;
break;
}
case LUA_TPROTO: {
gcotop(o)->gclist = st->tmark;
st->tmark = o;
break;
}
default: lua_assert(o->gch.tt == LUA_TSTRING);
}
}
static void checkstacksizes (lua_State *L, StkId max) {
int used = L->ci - L->base_ci; /* number of `ci' in use */
if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
used = max - L->stack; /* part of stack in use */
if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
}
static void markstacks (GCState *st) {
lua_State *L1 = st->L;
do { /* for each thread */
StkId o, lim;
CallInfo *ci;
if (ttisnil(defaultmeta(L1))) { /* incomplete state? */
lua_assert(L1 != st->L);
L1 = L1->next;
luaE_closethread(st->L, L1->previous); /* collect it */
continue;
}
markobject(st, defaultmeta(L1));
markobject(st, gt(L1));
markobject(st, registry(L1));
for (o=L1->stack; o<L1->top; o++)
markobject(st, o);
lim = o;
for (ci = L1->base_ci; ci <= L1->ci; ci++) {
lua_assert(ci->top <= L1->stack_last);
if (lim < ci->top) lim = ci->top;
}
for (; o<=lim; o++) setnilvalue(o);
checkstacksizes(L1, lim);
lua_assert(L1->previous->next == L1 && L1->next->previous == L1);
L1 = L1->next;
} while (L1 != st->L);
}
static void marktmu (GCState *st) {
Udata *u;
for (u = G(st->L)->tmudata; u; u = u->uv.next)
markudata(st, u);
GCObject *u;
for (u = st->g->tmudata; u; u = u->gch.next) {
unmark(u); /* may be marked, if left from previous GC */
reallymarkobject(st, u);
}
}
/* move `dead' udata that need finalization to list `tmudata' */
static void separateudata (lua_State *L) {
Udata **p = &G(L)->rootudata;
Udata *curr;
Udata *collected = NULL; /* to collect udata with gc event */
Udata **lastcollected = &collected;
void luaC_separateudata (lua_State *L) {
GCObject **p = &G(L)->rootudata;
GCObject *curr;
GCObject *collected = NULL; /* to collect udata with gc event */
GCObject **lastcollected = &collected;
while ((curr = *p) != NULL) {
if (isudmarked(curr) || isfinalized(curr) ||
(fasttm(L, curr->uv.metatable, TM_GC) == NULL))
p = &curr->uv.next;
lua_assert(curr->gch.tt == LUA_TUSERDATA);
if (ismarked(curr) || isfinalized(gcotou(curr)))
p = &curr->gch.next; /* don't bother with them */
else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) {
markfinalized(gcotou(curr)); /* don't need finalization */
p = &curr->gch.next;
}
else { /* must call its gc method */
*p = curr->uv.next;
curr->uv.next = NULL; /* link `curr' at the end of `collected' list */
*p = curr->gch.next;
curr->gch.next = NULL; /* link `curr' at the end of `collected' list */
*lastcollected = curr;
lastcollected = &curr->uv.next;
lastcollected = &curr->gch.next;
}
}
/* insert collected udata with gc event into `tmudata' list */
@@ -207,9 +138,9 @@ static void separateudata (lua_State *L) {
static void removekey (Node *n) {
setnilvalue(val(n)); /* remove corresponding value ... */
if (ismarkable(key(n)))
setttype(key(n), LUA_TNONE); /* dead key; remove it */
setnilvalue(gval(n)); /* remove corresponding value ... */
if (iscollectable(gkey(n)))
setttype(gkey(n), LUA_TNONE); /* dead key; remove it */
}
@@ -217,72 +148,167 @@ static void traversetable (GCState *st, Table *h) {
int i;
int weakkey = 0;
int weakvalue = 0;
marktable(st, h->metatable);
lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
weakkey = h->mode & WEAKKEY;
weakvalue = h->mode & WEAKVALUE;
h->mark = st->toclear; /* must be cleared after GC, ... */
st->toclear = h; /* ... so put in the appropriate list */
const TObject *mode;
markvalue(st, h->metatable);
lua_assert(h->lsizenode || h->node == st->g->dummynode);
mode = gfasttm(st->g, h->metatable, TM_MODE);
if (mode && ttisstring(mode)) { /* is there a weak mode? */
weakkey = (strchr(svalue(mode), 'k') != NULL);
weakvalue = (strchr(svalue(mode), 'v') != NULL);
if (weakkey || weakvalue) { /* is really weak? */
GCObject **weaklist;
h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) |
(weakvalue << VALUEWEAKBIT));
weaklist = (weakkey && weakvalue) ? &st->wkv :
(weakkey) ? &st->wk :
&st->wv;
h->gclist = *weaklist; /* must be cleared after GC, ... */
*weaklist = valtogco(h); /* ... so put in the appropriate list */
}
}
if (!weakvalue) {
i = sizearray(h);
i = h->sizearray;
while (i--)
markobject(st, &h->array[i]);
}
i = sizenode(h);
while (i--) {
Node *n = node(h, i);
if (!ttisnil(val(n))) {
lua_assert(!ttisnil(key(n)));
if (!weakkey) markobject(st, key(n));
if (!weakvalue) markobject(st, val(n));
Node *n = gnode(h, i);
if (!ttisnil(gval(n))) {
lua_assert(!ttisnil(gkey(n)));
condmarkobject(st, gkey(n), !weakkey);
condmarkobject(st, gval(n), !weakvalue);
}
}
}
static void propagatemarks (GCState *st) {
while (st->tmark) { /* traverse marked tables */
Table *h = st->tmark; /* get first table from list */
st->tmark = h->mark; /* remove it from list */
traversetable(st, h);
static void traverseproto (GCState *st, Proto *f) {
int i;
stringmark(f->source);
for (i=0; i<f->sizek; i++) { /* mark literal strings */
if (ttisstring(f->k+i))
stringmark(tsvalue(f->k+i));
}
for (i=0; i<f->sizeupvalues; i++) /* mark upvalue names */
stringmark(f->upvalues[i]);
for (i=0; i<f->sizep; i++) /* mark nested protos */
markvalue(st, f->p[i]);
for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
stringmark(f->locvars[i].varname);
lua_assert(luaG_checkcode(f));
}
static void traverseclosure (GCState *st, Closure *cl) {
if (cl->c.isC) {
int i;
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
markobject(st, &cl->c.upvalue[i]);
}
else {
int i;
lua_assert(cl->l.nupvalues == cl->l.p->nups);
markvalue(st, hvalue(&cl->l.g));
markvalue(st, cl->l.p);
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
UpVal *u = cl->l.upvals[i];
if (!u->marked) {
markobject(st, &u->value);
u->marked = 1;
}
}
}
}
static int hasmark (const TObject *o) {
switch (ttype(o)) {
case LUA_TUSERDATA:
return isudmarked(uvalue(o));
case LUA_TTABLE:
return ismarked(hvalue(o));
case LUA_TFUNCTION:
return clvalue(o)->c.marked;
case LUA_TSTRING:
strmark(tsvalue(o)); /* strings are `values', so are never weak */
/* go through */
default: /* number, nil, boolean, udataval */
return 1;
static void checkstacksizes (lua_State *L, StkId max) {
int used = L->ci - L->base_ci; /* number of `ci' in use */
if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
used = max - L->stack; /* part of stack in use */
if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
else condhardstacktests(luaD_reallocstack(L, L->stacksize));
}
static void traversestack (GCState *st, lua_State *L1) {
StkId o, lim;
CallInfo *ci;
markobject(st, gt(L1));
lim = L1->top;
for (ci = L1->base_ci; ci <= L1->ci; ci++) {
lua_assert(ci->top <= L1->stack_last);
lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC));
if (!(ci->state & CI_C) && lim < ci->top)
lim = ci->top;
}
for (o = L1->stack; o < L1->top; o++)
markobject(st, o);
for (; o <= lim; o++)
setnilvalue(o);
checkstacksizes(L1, lim);
}
static void propagatemarks (GCState *st) {
while (st->tmark) { /* traverse marked objects */
switch (st->tmark->gch.tt) {
case LUA_TTABLE: {
Table *h = gcotoh(st->tmark);
st->tmark = h->gclist;
traversetable(st, h);
break;
}
case LUA_TFUNCTION: {
Closure *cl = gcotocl(st->tmark);
st->tmark = cl->c.gclist;
traverseclosure(st, cl);
break;
}
case LUA_TTHREAD: {
lua_State *th = gcototh(st->tmark);
st->tmark = th->gclist;
traversestack(st, th);
break;
}
case LUA_TPROTO: {
Proto *p = gcotop(st->tmark);
st->tmark = p->gclist;
traverseproto(st, p);
break;
}
default: lua_assert(0);
}
}
}
static int valismarked (const TObject *o) {
if (ttisstring(o))
stringmark(tsvalue(o)); /* strings are `values', so are never weak */
return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0);
}
/*
** clear collected keys from weaktables
*/
static void cleartablekeys (GCState *st) {
Table *h;
for (h = st->toclear; h; h = h->mark) {
lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
int i = sizenode(h);
while (i--) {
Node *n = node(h, i);
if (!hasmark(key(n))) /* key was collected? */
removekey(n); /* remove entry from table */
}
static void cleartablekeys (GCObject *l) {
while (l) {
Table *h = gcotoh(l);
int i = sizenode(h);
lua_assert(h->marked & KEYWEAK);
while (i--) {
Node *n = gnode(h, i);
if (!valismarked(gkey(n))) /* key was collected? */
removekey(n); /* remove entry from table */
}
l = h->gclist;
}
}
@@ -290,148 +316,95 @@ static void cleartablekeys (GCState *st) {
/*
** clear collected values from weaktables
*/
static void cleartablevalues (GCState *st) {
Table *h;
for (h = st->toclear; h; h = h->mark) {
if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
int i = sizearray(h);
while (i--) {
TObject *o = &h->array[i];
if (!hasmark(o)) /* value was collected? */
setnilvalue(o); /* remove value */
}
i = sizenode(h);
while (i--) {
Node *n = node(h, i);
if (!hasmark(val(n))) /* value was collected? */
removekey(n); /* remove entry from table */
}
static void cleartablevalues (GCObject *l) {
while (l) {
Table *h = gcotoh(l);
int i = h->sizearray;
lua_assert(h->marked & VALUEWEAK);
while (i--) {
TObject *o = &h->array[i];
if (!valismarked(o)) /* value was collected? */
setnilvalue(o); /* remove value */
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
if (!valismarked(gval(n))) /* value was collected? */
removekey(n); /* remove entry from table */
}
l = h->gclist;
}
}
static void collectproto (lua_State *L) {
Proto **p = &G(L)->rootproto;
Proto *curr;
static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) {
case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break;
case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break;
case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break;
case LUA_TTABLE: luaH_free(L, gcotoh(o)); break;
case LUA_TTHREAD: {
lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread);
luaE_freethread(L, gcototh(o));
break;
}
case LUA_TSTRING: {
luaM_free(L, o, sizestring(gcotots(o)->tsv.len));
break;
}
case LUA_TUSERDATA: {
luaM_free(L, o, sizeudata(gcotou(o)->uv.len));
break;
}
default: lua_assert(0);
}
}
static int sweeplist (lua_State *L, GCObject **p, int limit) {
GCObject *curr;
int count = 0; /* number of collected items */
while ((curr = *p) != NULL) {
if (curr->marked) {
curr->marked = 0;
p = &curr->next;
if (curr->gch.marked > limit) {
unmark(curr);
p = &curr->gch.next;
}
else {
*p = curr->next;
luaF_freeproto(L, curr);
count++;
*p = curr->gch.next;
freeobj(L, curr);
}
}
return count;
}
static void collectclosures (lua_State *L) {
Closure **p = &G(L)->rootcl;
Closure *curr;
while ((curr = *p) != NULL) {
if (curr->c.marked) {
curr->c.marked = 0;
p = &curr->c.next;
}
else {
*p = curr->c.next;
luaF_freeclosure(L, curr);
}
}
}
static void collectupval (lua_State *L) {
UpVal **v = &G(L)->rootupval;
UpVal *curr;
while ((curr = *v) != NULL) {
if (isupvalmarked(curr)) {
lua_assert(curr->v == NULL);
curr->v = &curr->value; /* unmark */
v = &curr->next; /* next */
}
else {
*v = curr->next; /* next */
luaM_freelem(L, curr);
}
}
}
static void collecttable (lua_State *L) {
Table **p = &G(L)->roottable;
Table *curr;
while ((curr = *p) != NULL) {
if (ismarked(curr)) {
curr->mark = curr; /* unmark */
p = &curr->next;
}
else {
*p = curr->next;
luaH_free(L, curr);
}
}
}
static void collectudata (lua_State *L) {
Udata **p = &G(L)->rootudata;
Udata *curr;
while ((curr = *p) != NULL) {
if (isudmarked(curr)) {
unmarkud(curr);
p = &curr->uv.next;
}
else {
*p = curr->uv.next;
luaM_free(L, curr, sizeudata(curr->uv.len & (~(size_t)3)));
}
}
}
static void collectstrings (lua_State *L, int all) {
static void sweepstrings (lua_State *L, int all) {
int i;
for (i=0; i<G(L)->strt.size; i++) { /* for each list */
TString **p = &G(L)->strt.hash[i];
TString *curr;
while ((curr = *p) != NULL) {
if (curr->tsv.marked && !all) { /* preserve? */
if (curr->tsv.marked < FIXMARK) /* does not change FIXMARKs */
curr->tsv.marked = 0;
p = &curr->tsv.nexthash;
}
else { /* collect */
*p = curr->tsv.nexthash;
G(L)->strt.nuse--;
luaM_free(L, curr, sizestring(curr->tsv.len));
}
}
G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all);
}
}
static void checkSizes (lua_State *L) {
/* check size of string hash */
if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
G(L)->strt.size > MINSTRTABSIZE*2)
luaS_resize(L, G(L)->strt.size/2); /* table is too big */
}
#define MINBUFFER 256
static void checkMbuffer (lua_State *L) {
if (G(L)->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */
size_t newsize = G(L)->Mbuffsize/2; /* still larger than MINBUFFER */
luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, newsize, char);
G(L)->Mbuffsize = newsize;
/* check size of buffer */
if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
luaZ_resizebuffer(L, &G(L)->buff, newsize);
}
G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
}
static void do1gcTM (lua_State *L, Udata *udata) {
const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC);
if (tm != NULL) {
setobj(L->top, tm);
setobj2s(L->top, tm);
setuvalue(L->top+1, udata);
L->top += 2;
luaD_call(L, L->top - 2, 0);
@@ -439,56 +412,82 @@ static void do1gcTM (lua_State *L, Udata *udata) {
}
static void callGCTM (lua_State *L) {
int oldah = allowhook(L);
setallowhook(L, 0); /* stop debug hooks during GC tag methods */
void luaC_callGCTM (lua_State *L) {
lu_byte oldah = L->allowhook;
L->allowhook = 0; /* stop debug hooks during GC tag methods */
L->top++; /* reserve space to keep udata while runs its gc method */
while (G(L)->tmudata != NULL) {
Udata *udata = G(L)->tmudata;
GCObject *o = G(L)->tmudata;
Udata *udata = gcotou(o);
G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */
udata->uv.next = G(L)->rootudata; /* return it to `root' list */
G(L)->rootudata = udata;
G(L)->rootudata = o;
setuvalue(L->top - 1, udata); /* keep a reference to it */
unmarkud(udata);
unmark(o);
markfinalized(udata);
do1gcTM(L, udata);
}
L->top--;
setallowhook(L, oldah); /* restore hooks */
L->allowhook = oldah; /* restore hooks */
}
void luaC_callallgcTM (lua_State *L) {
separateudata(L);
callGCTM(L); /* call their GC tag methods */
void luaC_sweep (lua_State *L, int all) {
if (all) all = 256; /* larger than any mark */
sweeplist(L, &G(L)->rootudata, all);
sweepstrings(L, all);
sweeplist(L, &G(L)->rootgc, all);
}
void luaC_collect (lua_State *L, int all) {
collectudata(L);
collectstrings(L, all);
collecttable(L);
collectproto(L);
collectupval(L);
collectclosures(L);
/* mark root set */
static void markroot (GCState *st, lua_State *L) {
global_State *g = st->g;
markobject(st, defaultmeta(L));
markobject(st, registry(L));
traversestack(st, g->mainthread);
if (L != g->mainthread) /* another thread is running? */
markvalue(st, L); /* cannot collect it */
}
static void mark (lua_State *L) {
GCState st;
GCObject *wkv;
st.g = G(L);
st.tmark = NULL;
st.wkv = st.wk = st.wv = NULL;
markroot(&st, L);
propagatemarks(&st); /* mark all reachable objects */
cleartablevalues(st.wkv);
cleartablevalues(st.wv);
wkv = st.wkv; /* keys must be cleared after preserving udata */
st.wkv = NULL;
st.wv = NULL;
luaC_separateudata(L); /* separate userdata to be preserved */
marktmu(&st); /* mark `preserved' userdata */
propagatemarks(&st); /* remark, to propagate `preserveness' */
cleartablekeys(wkv);
/* `propagatemarks' may resuscitate some weak tables; clear them too */
cleartablekeys(st.wk);
cleartablevalues(st.wv);
cleartablekeys(st.wkv);
cleartablevalues(st.wkv);
}
void luaC_collectgarbage (lua_State *L) {
GCState st;
st.L = L;
st.tmark = NULL;
st.toclear = NULL;
markstacks(&st); /* mark all stacks */
propagatemarks(&st); /* mark all reachable objects */
cleartablevalues(&st);
separateudata(L); /* separate userdata to be preserved */
marktmu(&st); /* mark `preserved' userdata */
propagatemarks(&st); /* remark */
cleartablekeys(&st);
luaC_collect(L, 0);
checkMbuffer(L);
G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
callGCTM(L);
mark(L);
luaC_sweep(L, 0);
checkSizes(L);
luaC_callGCTM(L);
}
void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
o->gch.next = G(L)->rootgc;
G(L)->rootgc = o;
o->gch.marked = 0;
o->gch.tt = tt;
}

12
lgc.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
** $Id: lgc.h,v 1.18 2003/02/10 17:32:50 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -11,13 +11,15 @@
#include "lobject.h"
#define luaC_checkGC(L) if (G(L)->nblocks >= G(L)->GCthreshold) \
luaC_collectgarbage(L)
#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \
if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); }
void luaC_callallgcTM (lua_State *L);
void luaC_collect (lua_State *L, int all);
void luaC_separateudata (lua_State *L);
void luaC_callGCTM (lua_State *L);
void luaC_sweep (lua_State *L, int all);
void luaC_collectgarbage (lua_State *L);
void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
#endif

350
liolib.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: liolib.c,v 2.14 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: liolib.c,v 2.38 2003/03/18 12:25:32 roberto Exp roberto $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -12,6 +12,8 @@
#include <string.h>
#include <time.h>
#define liolib_c
#include "lua.h"
#include "lauxlib.h"
@@ -19,6 +21,36 @@
/*
** by default, gcc does not get `tmpname'
*/
#ifndef USE_TMPNAME
#ifdef __GNUC__
#define USE_TMPNAME 0
#else
#define USE_TMPNAME 1
#endif
#endif
/*
** by default, posix systems get `popen'
*/
#ifndef USE_POPEN
#ifdef _POSIX_C_SOURCE
#if _POSIX_C_SOURCE >= 2
#define USE_POPEN 1
#endif
#endif
#endif
#ifndef USE_POPEN
#define USE_POPEN 0
#endif
/*
** {======================================================
** FILE Operations
@@ -26,149 +58,193 @@
*/
#ifndef POPEN
#if !USE_POPEN
#define pclose(f) (-1)
#endif
#define FILEHANDLE "FileHandle"
#define CLOSEDFILEHANDLE "ClosedFileHandle"
#define FILEHANDLE "FILE*"
#define IO_INPUT "_input"
#define IO_OUTPUT "_output"
static int pushresult (lua_State *L, int i) {
static int pushresult (lua_State *L, int i, const char *filename) {
if (i) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
else
lua_pushfstring(L, "%s", strerror(errno));
lua_pushnumber(L, errno);
return 3;
}
}
static FILE **topfile (lua_State *L, int findex) {
FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE);
if (f == NULL) luaL_argerror(L, findex, "bad file");
return f;
}
static int io_type (lua_State *L) {
FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE);
if (f == NULL) lua_pushnil(L);
else if (*f == NULL)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
return 1;
}
static FILE *tofile (lua_State *L, int findex) {
FILE **f = (FILE **)lua_touserdata(L, findex);
if (f && lua_getmetatable(L, findex) &&
lua_rawequal(L, -1, lua_upvalueindex(1))) {
lua_pop(L, 1);
return *f;
}
if (findex > 0)
luaL_argerror(L, findex, "bad file");
return NULL;
FILE **f = topfile(L, findex);
if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
return *f;
}
static void newfile (lua_State *L, FILE *f) {
lua_boxpointer(L, f);
lua_pushliteral(L, FILEHANDLE);
lua_rawget(L, LUA_REGISTRYINDEX);
/*
** When creating file handles, always creates a `closed' file handle
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
*/
static FILE **newfile (lua_State *L) {
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
*pf = NULL; /* file handle is currently `closed' */
luaL_getmetatable(L, FILEHANDLE);
lua_setmetatable(L, -2);
return pf;
}
/*
** assumes that top of the stack is the `io' library, and next is
** the `io' metatable
*/
static void registerfile (lua_State *L, FILE *f, const char *name,
const char *impname) {
lua_pushstring(L, name);
newfile(L, f);
*newfile(L) = f;
if (impname) {
lua_pushstring(L, impname);
lua_pushvalue(L, -2);
lua_settable(L, -6);
lua_settable(L, -6); /* metatable[impname] = file */
}
lua_settable(L, -3);
lua_settable(L, -3); /* io[name] = file */
}
static int setnewfile (lua_State *L, FILE *f) {
if (f == NULL)
return pushresult(L, 0);
static int aux_close (lua_State *L) {
FILE *f = tofile(L, 1);
if (f == stdin || f == stdout || f == stderr)
return 0; /* file cannot be closed */
else {
newfile(L, f);
return 1;
int ok = (pclose(f) != -1) || (fclose(f) == 0);
if (ok)
*(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */
return ok;
}
}
static int io_close (lua_State *L) {
FILE *f;
int status = 1;
if (lua_isnone(L, 1)) {
lua_pushstring(L, IO_OUTPUT);
lua_rawget(L, lua_upvalueindex(1));
}
f = tofile(L, 1);
if (f != stdin && f != stdout && f != stderr) {
lua_settop(L, 1); /* make sure file is on top */
lua_pushliteral(L, CLOSEDFILEHANDLE);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, 1);
status = (pclose(f) != -1) || (fclose(f) == 0);
}
return pushresult(L, status);
return pushresult(L, aux_close(L), NULL);
}
static int io_gc (lua_State *L) {
FILE **f = topfile(L, 1);
if (*f != NULL) /* ignore closed files */
aux_close(L);
return 0;
}
static int io_tostring (lua_State *L) {
char buff[32];
FILE **f = topfile(L, 1);
if (*f == NULL)
strcpy(buff, "closed");
else
sprintf(buff, "%p", lua_touserdata(L, 1));
lua_pushfstring(L, "file (%s)", buff);
return 1;
}
static int io_open (lua_State *L) {
FILE *f = fopen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r"));
return setnewfile(L, f);
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
}
static int io_popen (lua_State *L) {
#ifndef POPEN
#if !USE_POPEN
luaL_error(L, "`popen' not supported");
return 0;
#else
FILE *f = popen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r"));
return setnewfile(L, f);
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
FILE **pf = newfile(L);
*pf = popen(filename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
#endif
}
static int io_tmpfile (lua_State *L) {
return setnewfile(L, tmpfile());
FILE **pf = newfile(L);
*pf = tmpfile();
return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
}
static FILE *getiofile (lua_State *L, const char *name) {
FILE *f;
lua_pushstring(L, name);
lua_rawget(L, lua_upvalueindex(1));
f = tofile(L, -1);
if (f == NULL)
luaL_error(L, "%s is closed", name);
return f;
return tofile(L, -1);
}
static int g_iofile (lua_State *L, const char *name, const char *mode) {
if (lua_isnoneornil(L, 1)) {
lua_pushstring(L, name);
lua_rawget(L, lua_upvalueindex(1));
return 1;
}
else {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
lua_pushstring(L, name);
if (filename) {
FILE *f = fopen(filename, mode);
luaL_arg_check(L, f, 1, strerror(errno));
newfile(L, f);
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
if (*pf == NULL) {
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
luaL_argerror(L, 1, lua_tostring(L, -1));
}
}
else {
tofile(L, 1); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
lua_rawset(L, lua_upvalueindex(1));
return 0;
}
/* return current value */
lua_pushstring(L, name);
lua_rawget(L, lua_upvalueindex(1));
return 1;
}
@@ -182,6 +258,42 @@ static int io_output (lua_State *L) {
}
static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int idx, int close) {
lua_pushliteral(L, FILEHANDLE);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushvalue(L, idx);
lua_pushboolean(L, close); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 3);
}
static int f_lines (lua_State *L) {
tofile(L, 1); /* check that it's a valid file handle */
aux_lines(L, 1, 0);
return 1;
}
static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */
lua_pushstring(L, IO_INPUT);
lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */
return f_lines(L);
}
else {
const char *filename = luaL_checkstring(L, 1);
FILE **pf = newfile(L);
*pf = fopen(filename, "r");
luaL_argcheck(L, *pf, 1, strerror(errno));
aux_lines(L, lua_gettop(L), 1);
return 1;
}
}
/*
** {======================================================
** READ
@@ -256,7 +368,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
n = first+1; /* to return 1 result */
}
else { /* ensure stack space for all results and for auxlib's buffer */
luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments");
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
@@ -265,8 +377,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
}
else {
const char *p = lua_tostring(L, n);
if (!p || p[0] != '*')
return luaL_error(L, "invalid `read' option");
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
switch (p[1]) {
case 'n': /* number */
success = read_number(L, f);
@@ -279,7 +390,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
success = 1; /* always success */
break;
case 'w': /* word */
return luaL_error(L, "obsolete option `*w'");
return luaL_error(L, "obsolete option `*w' to `read'");
default:
return luaL_argerror(L, n, "invalid format");
}
@@ -303,6 +414,22 @@ static int f_read (lua_State *L) {
return g_read(L, tofile(L, 1), 2);
}
static int io_readline (lua_State *L) {
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
if (f == NULL) /* file is already closed? */
luaL_error(L, "file is already closed");
if (read_line(L, f)) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(2));
aux_close(L); /* close it */
}
return 0;
}
}
/* }====================================================== */
@@ -317,12 +444,11 @@ static int g_write (lua_State *L, FILE *f, int arg) {
}
else {
size_t l;
const char *s = luaL_check_lstr(L, arg, &l);
const char *s = luaL_checklstring(L, arg, &l);
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
pushresult(L, status);
return 1;
return pushresult(L, status, NULL);
}
@@ -340,12 +466,12 @@ static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L, 1);
int op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames);
long offset = luaL_opt_long(L, 3, 0);
luaL_arg_check(L, op != -1, 2, "invalid mode");
int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
long offset = luaL_optlong(L, 3, 0);
luaL_argcheck(L, op != -1, 2, "invalid mode");
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0); /* error */
return pushresult(L, 0, NULL); /* error */
else {
lua_pushnumber(L, ftell(f));
return 1;
@@ -354,24 +480,26 @@ static int f_seek (lua_State *L) {
static int io_flush (lua_State *L) {
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0);
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
return pushresult(L, fflush(tofile(L, 1)) == 0);
return pushresult(L, fflush(tofile(L, 1)) == 0, NULL);
}
static const luaL_reg iolib[] = {
{"input", io_input},
{"output", io_output},
{"lines", io_lines},
{"close", io_close},
{"flush", io_flush},
{"open", io_open},
{"popen", io_popen},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
{"write", io_write},
{NULL, NULL}
};
@@ -380,33 +508,23 @@ static const luaL_reg iolib[] = {
static const luaL_reg flib[] = {
{"flush", f_flush},
{"read", f_read},
{"lines", f_lines},
{"seek", f_seek},
{"write", f_write},
{"close", io_close},
{"__gc", io_gc},
{"__tostring", io_tostring},
{NULL, NULL}
};
static void createmeta (lua_State *L) {
lua_pushliteral(L, FILEHANDLE); /* S: FH */
lua_newtable(L); /* S: mt FH */
/* close files when collected */
lua_pushliteral(L, "__gc"); /* S: `gc' mt FH */
lua_pushvalue(L, -2); /* S: mt `gc' mt FH */
lua_pushcclosure(L, io_close, 1); /* S: close `gc' mt FH */
lua_rawset(L, -3); /* S: mt FH */
luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */
/* file methods */
lua_pushliteral(L, "__gettable"); /* S: `gettable' mt FH */
lua_pushvalue(L, -2); /* S: mt `gettable' mt FH */
lua_rawset(L, -3); /* S: mt FH */
lua_pushvalue(L, -1); /* S: mt mt FH */
luaL_openlib(L, flib, 1); /* S: mt FH */
/* put new metatable into registry */
lua_rawset(L, LUA_REGISTRYINDEX); /* S: empty */
/* meta table for CLOSEDFILEHANDLE */
lua_pushliteral(L, CLOSEDFILEHANDLE);
lua_newtable(L);
lua_rawset(L, LUA_REGISTRYINDEX);
lua_pushliteral(L, "__index");
lua_pushvalue(L, -2); /* push metatable */
lua_rawset(L, -3); /* metatable.__index = metatable */
luaL_openlib(L, NULL, flib, 0);
}
/* }====================================================== */
@@ -419,33 +537,40 @@ static void createmeta (lua_State *L) {
*/
static int io_execute (lua_State *L) {
lua_pushnumber(L, system(luaL_check_string(L, 1)));
lua_pushnumber(L, system(luaL_checkstring(L, 1)));
return 1;
}
static int io_remove (lua_State *L) {
return pushresult(L, remove(luaL_check_string(L, 1)) == 0);
const char *filename = luaL_checkstring(L, 1);
return pushresult(L, remove(filename) == 0, filename);
}
static int io_rename (lua_State *L) {
return pushresult(L, rename(luaL_check_string(L, 1),
luaL_check_string(L, 2)) == 0);
const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2);
return pushresult(L, rename(fromname, toname) == 0, fromname);
}
static int io_tmpname (lua_State *L) {
#if !USE_TMPNAME
luaL_error(L, "`tmpname' not supported");
return 0;
#else
char buff[L_tmpnam];
if (tmpnam(buff) != buff)
return luaL_error(L, "unable to generate a unique filename");
return luaL_error(L, "unable to generate a unique filename in `tmpname'");
lua_pushstring(L, buff);
return 1;
#endif
}
static int io_getenv (lua_State *L) {
lua_pushstring(L, getenv(luaL_check_string(L, 1))); /* if NULL push nil */
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
return 1;
}
@@ -503,8 +628,8 @@ static int getfield (lua_State *L, const char *key, int d) {
static int io_date (lua_State *L) {
const char *s = luaL_opt_string(L, 1, "%c");
time_t t = (time_t)(luaL_opt_number(L, 2, -1));
const char *s = luaL_optstring(L, 1, "%c");
time_t t = (time_t)(luaL_optnumber(L, 2, -1));
struct tm *stm;
if (t == (time_t)(-1)) /* no time given? */
t = time(NULL); /* use current time */
@@ -545,7 +670,7 @@ static int io_time (lua_State *L) {
else {
time_t t;
struct tm ts;
luaL_check_type(L, 1, LUA_TTABLE);
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); /* make sure table is at the top */
ts.tm_sec = getfield(L, "sec", 0);
ts.tm_min = getfield(L, "min", 0);
@@ -565,8 +690,8 @@ static int io_time (lua_State *L) {
static int io_difftime (lua_State *L) {
lua_pushnumber(L, difftime((time_t)(luaL_check_number(L, 1)),
(time_t)(luaL_opt_number(L, 2, 0))));
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
(time_t)(luaL_optnumber(L, 2, 0))));
return 1;
}
@@ -579,16 +704,16 @@ static int io_setloc (lua_State *L) {
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
"numeric", "time", NULL};
const char *l = lua_tostring(L, 1);
int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames);
luaL_arg_check(L, l || lua_isnoneornil(L, 1), 1, "string expected");
luaL_arg_check(L, op != -1, 2, "invalid option");
int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames);
luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected");
luaL_argcheck(L, op != -1, 2, "invalid option");
lua_pushstring(L, setlocale(cat[op], l));
return 1;
}
static int io_exit (lua_State *L) {
exit(luaL_opt_int(L, 1, EXIT_SUCCESS));
exit(luaL_optint(L, 1, EXIT_SUCCESS));
return 0; /* to avoid warnings */
}
@@ -611,20 +736,15 @@ static const luaL_reg syslib[] = {
LUALIB_API int lua_iolibopen (lua_State *L) {
LUALIB_API int luaopen_io (lua_State *L) {
luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
createmeta(L);
luaL_opennamedlib(L, LUA_OSLIBNAME, syslib, 0);
lua_pushliteral(L, FILEHANDLE); /* S: FH */
lua_rawget(L, LUA_REGISTRYINDEX); /* S: mt */
lua_pushvalue(L, -1); /* S: mt mt */
luaL_opennamedlib(L, LUA_IOLIBNAME, iolib, 1); /* S: mt */
lua_pushliteral(L, LUA_IOLIBNAME); /* S: `io' mt */
lua_gettable(L, LUA_GLOBALSINDEX); /* S: io mt */
lua_pushvalue(L, -1);
luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
/* put predefined file handles into `io' table */
registerfile(L, stdin, "stdin", IO_INPUT);
registerfile(L, stdout, "stdout", IO_OUTPUT);
registerfile(L, stderr, "stderr", NULL);
lua_pop(L, 2); /* S: empty */
return 0;
return 1;
}

164
llex.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: llex.c,v 1.107 2002/07/08 18:14:36 roberto Exp roberto $
** $Id: llex.c,v 1.118 2003/02/28 17:19:47 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,8 @@
#include <ctype.h>
#include <string.h>
#define llex_c
#include "lua.h"
#include "ldo.h"
@@ -27,7 +29,7 @@
/* ORDER RESERVED */
static const char *const token2string [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "global", "if",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while", "*name",
"..", "...", "==", ">=", "<=", "~=",
@@ -39,8 +41,9 @@ void luaX_init (lua_State *L) {
int i;
for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, token2string[i]);
luaS_fix(ts); /* reserved words are never collected */
lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN);
ts->tsv.marked = cast(unsigned short, RESERVEDMARK+i); /* reserved word */
ts->tsv.reserved = cast(lu_byte, i+1); /* reserved word */
}
}
@@ -56,26 +59,29 @@ void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) {
}
static void luaX_error (LexState *ls, const char *s, const char *token) {
void luaX_errorline (LexState *ls, const char *s, const char *token, int line) {
lua_State *L = ls->L;
char buff[MAXSRC];
luaO_chunkid(buff, getstr(ls->source), MAXSRC);
luaO_pushfstring(L, "%s:%d: %s near `%s'\n", buff, ls->linenumber, s, token);
luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token);
luaD_throw(L, LUA_ERRSYNTAX);
}
static void luaX_error (LexState *ls, const char *s, const char *token) {
luaX_errorline(ls, s, token, ls->linenumber);
}
void luaX_syntaxerror (LexState *ls, const char *msg) {
const char *lasttoken;
switch (ls->t.token) {
case TK_NAME:
lasttoken = luaO_pushfstring(ls->L, "%s", getstr(ls->t.seminfo.ts));
lasttoken = getstr(ls->t.seminfo.ts);
break;
case TK_STRING:
lasttoken = luaO_pushfstring(ls->L, "\"%s\"", getstr(ls->t.seminfo.ts));
break;
case TK_NUMBER:
lasttoken = luaO_pushfstring(ls->L, "%f", ls->t.seminfo.r);
lasttoken = luaZ_buffer(ls->buff);
break;
default:
lasttoken = luaX_token2str(ls, ls->t.token);
@@ -87,7 +93,7 @@ void luaX_syntaxerror (LexState *ls, const char *msg) {
const char *luaX_token2str (LexState *ls, int token) {
if (token < FIRST_RESERVED) {
lua_assert(token == (char)token);
lua_assert(token == (unsigned char)token);
return luaO_pushfstring(ls->L, "%c", token);
}
else
@@ -99,7 +105,7 @@ static void luaX_lexerror (LexState *ls, const char *s, int token) {
if (token == TK_EOS)
luaX_error(ls, s, luaX_token2str(ls, token));
else
luaX_error(ls, s, cast(char *, G(ls->L)->Mbuffer));
luaX_error(ls, s, luaZ_buffer(ls->buff));
}
@@ -135,148 +141,150 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
*/
/* use Mbuffer to store names, literal strings and numbers */
/* use buffer to store names, literal strings and numbers */
#define EXTRABUFF 128
#define checkbuffer(L, len) \
if (((len)+10)*sizeof(char) > G(L)->Mbuffsize) \
luaO_openspace(L, (len)+EXTRABUFF, char)
/* extra space to allocate when growing buffer */
#define EXTRABUFF 32
#define save(L, c, l) (cast(char *, G(L)->Mbuffer)[l++] = cast(char, c))
#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS))
/* maximum number of chars that can be read without checking buffer size */
#define MAXNOCHECK 5
#define checkbuffer(LS, len) \
if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
#define save(LS, c, l) \
(luaZ_buffer((LS)->buff)[l++] = cast(char, c))
#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS))
static size_t readname (LexState *LS) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
checkbuffer(LS, l);
do {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
} while (isalnum(LS->current) || LS->current == '_');
save(L, '\0', l);
save(LS, '\0', l);
return l-1;
}
/* LUA_NUMBER */
static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
if (comma) save(L, '.', l);
checkbuffer(LS, l);
if (comma) save(LS, '.', l);
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
}
if (LS->current == '.') {
save_and_next(L, LS, l);
save_and_next(LS, l);
if (LS->current == '.') {
save_and_next(L, LS, l);
save(L, '\0', l);
save_and_next(LS, l);
save(LS, '\0', l);
luaX_lexerror(LS,
"ambiguous syntax (decimal point x string concatenation)",
TK_NUMBER);
}
}
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
}
if (LS->current == 'e' || LS->current == 'E') {
save_and_next(L, LS, l); /* read `E' */
save_and_next(LS, l); /* read `E' */
if (LS->current == '+' || LS->current == '-')
save_and_next(L, LS, l); /* optional exponent sign */
save_and_next(LS, l); /* optional exponent sign */
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
}
}
save(L, '\0', l);
if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
save(LS, '\0', l);
if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r))
luaX_lexerror(LS, "malformed number", TK_NUMBER);
}
static void read_long_string (LexState *LS, SemInfo *seminfo) {
lua_State *L = LS->L;
int cont = 0;
size_t l = 0;
checkbuffer(L, l);
save(L, '[', l); /* save first `[' */
save_and_next(L, LS, l); /* pass the second `[' */
checkbuffer(LS, l);
save(LS, '[', l); /* save first `[' */
save_and_next(LS, l); /* pass the second `[' */
if (LS->current == '\n') /* string starts with a newline? */
inclinenumber(LS); /* skip it */
for (;;) {
checkbuffer(L, l);
checkbuffer(LS, l);
switch (LS->current) {
case EOZ:
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS);
break; /* to avoid warnings */
case '[':
save_and_next(L, LS, l);
save_and_next(LS, l);
if (LS->current == '[') {
cont++;
save_and_next(L, LS, l);
save_and_next(LS, l);
}
continue;
case ']':
save_and_next(L, LS, l);
save_and_next(LS, l);
if (LS->current == ']') {
if (cont == 0) goto endloop;
cont--;
save_and_next(L, LS, l);
save_and_next(LS, l);
}
continue;
case '\n':
save(L, '\n', l);
save(LS, '\n', l);
inclinenumber(LS);
if (!seminfo) l = 0; /* reset buffer to avoid wasting space */
continue;
default:
save_and_next(L, LS, l);
save_and_next(LS, l);
}
} endloop:
save_and_next(L, LS, l); /* skip the second `]' */
save(L, '\0', l);
save_and_next(LS, l); /* skip the second `]' */
save(LS, '\0', l);
if (seminfo)
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+2, l-5);
seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
}
static void read_string (LexState *LS, int del, SemInfo *seminfo) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
while (LS->current != del) {
checkbuffer(L, l);
checkbuffer(LS, l);
switch (LS->current) {
case EOZ:
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_EOS);
break; /* to avoid warnings */
case '\n':
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_STRING);
break; /* to avoid warnings */
case '\\':
next(LS); /* do not save the `\' */
switch (LS->current) {
case 'a': save(L, '\a', l); next(LS); break;
case 'b': save(L, '\b', l); next(LS); break;
case 'f': save(L, '\f', l); next(LS); break;
case 'n': save(L, '\n', l); next(LS); break;
case 'r': save(L, '\r', l); next(LS); break;
case 't': save(L, '\t', l); next(LS); break;
case 'v': save(L, '\v', l); next(LS); break;
case '\n': save(L, '\n', l); inclinenumber(LS); break;
case 'a': save(LS, '\a', l); next(LS); break;
case 'b': save(LS, '\b', l); next(LS); break;
case 'f': save(LS, '\f', l); next(LS); break;
case 'n': save(LS, '\n', l); next(LS); break;
case 'r': save(LS, '\r', l); next(LS); break;
case 't': save(LS, '\t', l); next(LS); break;
case 'v': save(LS, '\v', l); next(LS); break;
case '\n': save(LS, '\n', l); inclinenumber(LS); break;
case EOZ: break; /* will raise an error next loop */
default: {
if (!isdigit(LS->current))
save_and_next(L, LS, l); /* handles \\, \", \', and \? */
save_and_next(LS, l); /* handles \\, \", \', and \? */
else { /* \xxx */
int c = 0;
int i = 0;
@@ -285,21 +293,21 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
next(LS);
} while (++i<3 && isdigit(LS->current));
if (c > UCHAR_MAX) {
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, "escape sequence too large", TK_STRING);
}
save(L, c, l);
save(LS, c, l);
}
}
}
break;
default:
save_and_next(L, LS, l);
save_and_next(LS, l);
}
}
save_and_next(L, LS, l); /* skip delimiter */
save(L, '\0', l);
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+1, l-3);
save_and_next(LS, l); /* skip delimiter */
save(LS, '\0', l);
seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
}
@@ -387,9 +395,9 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
else if (isalpha(LS->current) || LS->current == '_') {
/* identifier or reserved word */
size_t l = readname(LS);
TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
if (ts->tsv.marked >= RESERVEDMARK) /* reserved word? */
return ts->tsv.marked-RESERVEDMARK+FIRST_RESERVED;
TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
if (ts->tsv.reserved > 0) /* reserved word? */
return ts->tsv.reserved - 1 + FIRST_RESERVED;
seminfo->ts = ts;
return TK_NAME;
}

9
llex.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: llex.h,v 1.42 2002/02/08 22:42:41 roberto Exp roberto $
** $Id: llex.h,v 1.46 2002/11/22 16:35:20 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -25,7 +25,7 @@ enum RESERVED {
/* terminal symbols denoted by reserved words */
TK_AND = FIRST_RESERVED, TK_BREAK,
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
TK_GLOBAL, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
@@ -56,8 +56,10 @@ typedef struct LexState {
Token lookahead; /* look ahead token */
struct FuncState *fs; /* `FuncState' is private to the parser */
struct lua_State *L;
struct zio *z; /* input stream */
ZIO *z; /* input stream */
Mbuffer *buff; /* buffer for tokens */
TString *source; /* current source name */
int nestlevel; /* level of nested non-terminals */
} LexState;
@@ -66,6 +68,7 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source);
int luaX_lex (LexState *LS, SemInfo *seminfo);
void luaX_checklimit (LexState *ls, int val, int limit, const char *msg);
void luaX_syntaxerror (LexState *ls, const char *s);
void luaX_errorline (LexState *ls, const char *s, const char *token, int line);
const char *luaX_token2str (LexState *ls, int token);

View File

@@ -1,5 +1,5 @@
/*
** $Id: llimits.h,v 1.44 2002/06/13 13:45:31 roberto Exp roberto $
** $Id: llimits.h,v 1.51 2002/11/25 17:47:13 roberto Exp roberto $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -49,15 +49,13 @@ typedef int ls_hash;
/* it should be at least as large as size_t */
typedef unsigned long lu_mem;
#define MAX_LUMEM ULONG_MAX
/* an integer big enough to count the number of strings in use */
typedef long ls_nstr;
/* an integer big enough to count the number of steps when calling a
** `count' hook */
typedef long ls_count;
/* chars used as small naturals (so that `char' is reserved for characteres) */
/* chars used as small naturals (so that `char' is reserved for characters) */
typedef unsigned char lu_byte;
@@ -77,9 +75,18 @@ typedef unsigned char lu_byte;
/* type to ensure maximum alignment */
#ifndef LUSER_ALIGNMENT_T
#define LUSER_ALIGNMENT_T double
typedef union { double u; void *s; long l; } L_Umaxalign;
#else
typedef LUSER_ALIGNMENT_T L_Umaxalign;
#endif
/* result of `usual argument conversion' over lua_Number */
#ifndef LUA_UACNUMBER
typedef double l_uacNumber;
#else
typedef LUA_UACNUMBER l_uacNumber;
#endif
union L_Umaxalign { LUSER_ALIGNMENT_T u; void *s; long l; };
#ifndef lua_assert
@@ -110,12 +117,22 @@ union L_Umaxalign { LUSER_ALIGNMENT_T u; void *s; long l; };
typedef unsigned long Instruction;
/* maximum depth for calls */
/* maximum depth for calls (unsigned short) */
#ifndef LUA_MAXCALLS
#define LUA_MAXCALLS 4096
#endif
/*
** maximum depth for C calls (unsigned short): Not too big, or may
** overflow the C stack...
*/
#ifndef LUA_MAXCCALLS
#define LUA_MAXCCALLS 200
#endif
/* maximum size for the C stack */
#ifndef LUA_MAXCSTACK
#define LUA_MAXCSTACK 2048
@@ -150,4 +167,19 @@ typedef unsigned long Instruction;
#endif
/* minimum size for string buffer */
#ifndef LUA_MINBUFFER
#define LUA_MINBUFFER 32
#endif
/*
** maximum number of syntactical nested non-terminals: Not too big,
** or may overflow the C stack...
*/
#ifndef LUA_MAXPARSERLEVEL
#define LUA_MAXPARSERLEVEL 200
#endif
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lmathlib.c,v 1.50 2002/08/14 20:07:43 roberto Exp roberto $
** $Id: lmathlib.c,v 1.55 2003/03/11 12:24:34 roberto Exp roberto $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,8 @@
#include <stdlib.h>
#include <math.h>
#define lmathlib_c
#include "lua.h"
#include "lauxlib.h"
@@ -34,104 +36,104 @@
static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_check_number(L, 1)));
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
return 1;
}
static int math_sin (lua_State *L) {
lua_pushnumber(L, sin(TORAD(luaL_check_number(L, 1))));
lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1))));
return 1;
}
static int math_cos (lua_State *L) {
lua_pushnumber(L, cos(TORAD(luaL_check_number(L, 1))));
lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1))));
return 1;
}
static int math_tan (lua_State *L) {
lua_pushnumber(L, tan(TORAD(luaL_check_number(L, 1))));
lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1))));
return 1;
}
static int math_asin (lua_State *L) {
lua_pushnumber(L, FROMRAD(asin(luaL_check_number(L, 1))));
lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1))));
return 1;
}
static int math_acos (lua_State *L) {
lua_pushnumber(L, FROMRAD(acos(luaL_check_number(L, 1))));
lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1))));
return 1;
}
static int math_atan (lua_State *L) {
lua_pushnumber(L, FROMRAD(atan(luaL_check_number(L, 1))));
lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1))));
return 1;
}
static int math_atan2 (lua_State *L) {
lua_pushnumber(L, FROMRAD(atan2(luaL_check_number(L, 1), luaL_check_number(L, 2))));
lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))));
return 1;
}
static int math_ceil (lua_State *L) {
lua_pushnumber(L, ceil(luaL_check_number(L, 1)));
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
return 1;
}
static int math_floor (lua_State *L) {
lua_pushnumber(L, floor(luaL_check_number(L, 1)));
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
return 1;
}
static int math_mod (lua_State *L) {
lua_pushnumber(L, fmod(luaL_check_number(L, 1), luaL_check_number(L, 2)));
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
static int math_sqrt (lua_State *L) {
lua_pushnumber(L, sqrt(luaL_check_number(L, 1)));
lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
return 1;
}
static int math_pow (lua_State *L) {
lua_pushnumber(L, pow(luaL_check_number(L, 1), luaL_check_number(L, 2)));
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
static int math_log (lua_State *L) {
lua_pushnumber(L, log(luaL_check_number(L, 1)));
lua_pushnumber(L, log(luaL_checknumber(L, 1)));
return 1;
}
static int math_log10 (lua_State *L) {
lua_pushnumber(L, log10(luaL_check_number(L, 1)));
lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
return 1;
}
static int math_exp (lua_State *L) {
lua_pushnumber(L, exp(luaL_check_number(L, 1)));
lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
return 1;
}
static int math_deg (lua_State *L) {
lua_pushnumber(L, luaL_check_number(L, 1)/RADIANS_PER_DEGREE);
lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
return 1;
}
static int math_rad (lua_State *L) {
lua_pushnumber(L, luaL_check_number(L, 1)*RADIANS_PER_DEGREE);
lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
return 1;
}
static int math_frexp (lua_State *L) {
int e;
lua_pushnumber(L, frexp(luaL_check_number(L, 1), &e));
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
lua_pushnumber(L, e);
return 2;
}
static int math_ldexp (lua_State *L) {
lua_pushnumber(L, ldexp(luaL_check_number(L, 1), luaL_check_int(L, 2)));
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
return 1;
}
@@ -139,10 +141,10 @@ static int math_ldexp (lua_State *L) {
static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number dmin = luaL_check_number(L, 1);
lua_Number dmin = luaL_checknumber(L, 1);
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_check_number(L, i);
lua_Number d = luaL_checknumber(L, i);
if (d < dmin)
dmin = d;
}
@@ -153,10 +155,10 @@ static int math_min (lua_State *L) {
static int math_max (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number dmax = luaL_check_number(L, 1);
lua_Number dmax = luaL_checknumber(L, 1);
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_check_number(L, i);
lua_Number d = luaL_checknumber(L, i);
if (d > dmax)
dmax = d;
}
@@ -175,15 +177,15 @@ static int math_random (lua_State *L) {
break;
}
case 1: { /* only upper limit */
int u = luaL_check_int(L, 1);
luaL_arg_check(L, 1<=u, 1, "interval is empty");
int u = luaL_checkint(L, 1);
luaL_argcheck(L, 1<=u, 1, "interval is empty");
lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */
break;
}
case 2: { /* lower and upper limits */
int l = luaL_check_int(L, 1);
int u = luaL_check_int(L, 2);
luaL_arg_check(L, l<=u, 2, "interval is empty");
int l = luaL_checkint(L, 1);
int u = luaL_checkint(L, 2);
luaL_argcheck(L, l<=u, 2, "interval is empty");
lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */
break;
}
@@ -194,7 +196,7 @@ static int math_random (lua_State *L) {
static int math_randomseed (lua_State *L) {
srand(luaL_check_int(L, 1));
srand(luaL_checkint(L, 1));
return 0;
}
@@ -231,17 +233,14 @@ static const luaL_reg mathlib[] = {
/*
** Open math library
*/
LUALIB_API int lua_mathlibopen (lua_State *L) {
lua_pushliteral(L, LUA_MATHLIBNAME);
lua_newtable(L);
luaL_openlib(L, mathlib, 0);
LUALIB_API int luaopen_math (lua_State *L) {
luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0);
lua_pushliteral(L, "pi");
lua_pushnumber(L, PI);
lua_settable(L, -3);
lua_settable(L, LUA_GLOBALSINDEX);
lua_pushliteral(L, "__pow");
lua_pushcfunction(L, math_pow);
lua_settable(L, LUA_REGISTRYINDEX);
return 0;
lua_settable(L, LUA_GLOBALSINDEX);
return 1;
}

26
lmem.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lmem.c,v 1.56 2002/06/11 16:23:47 roberto Exp roberto $
** $Id: lmem.c,v 1.60 2002/11/21 14:14:42 roberto Exp roberto $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,8 @@
#include <stdlib.h>
#define lmem_c
#include "lua.h"
#include "ldebug.h"
@@ -18,15 +20,22 @@
/*
** definition for realloc function. It must assure that
** l_realloc(block, x, 0) frees the block, and l_realloc(NULL, 0, x)
** allocates a new block (ANSI C assures that).
** (`os' is the old block size; some allocators may use that.)
** definition for realloc function. It must assure that l_realloc(NULL,
** 0, x) allocates a new block (ANSI C assures that). (`os' is the old
** block size; some allocators may use that.)
*/
#ifndef l_realloc
#define l_realloc(b,os,s) realloc(b,s)
#endif
/*
** definition for free function. (`os' is the old block size; some
** allocators may use that.)
*/
#ifndef l_free
#define l_free(b,os) free(b)
#endif
#define MINSIZEARRAY 4
@@ -54,11 +63,13 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
** generic allocation routine.
*/
void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
lua_assert((oldsize == 0) == (block == NULL));
if (size == 0) {
if (block != NULL) {
l_realloc(block, oldsize, size);
l_free(block, oldsize);
block = NULL;
}
else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */
}
else if (size >= MAX_SIZET)
luaG_runerror(L, "memory allocation error: block too big");
@@ -70,7 +81,8 @@ void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
else return NULL; /* error before creating state! */
}
}
if (L && G(L)) {
if (L) {
lua_assert(G(L) != NULL && G(L)->nblocks > 0);
G(L)->nblocks -= oldsize;
G(L)->nblocks += size;
}

205
loadlib.c Normal file
View File

@@ -0,0 +1,205 @@
/*
** $Id: loadlib.c,v 1.3 2003/04/02 13:09:14 roberto Exp roberto $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
*
* This Lua library exports a single function, called loadlib, which is
* called from Lua as loadlib(lib,init), where lib is the full name of the
* library to be loaded (including the complete path) and init is the name
* of a function to be called after the library is loaded. Typically, this
* function will register other functions, thus making the complete library
* available to Lua. The init function is *not* automatically called by
* loadlib. Instead, loadlib returns the init function as a Lua function
* that the client can call when it thinks is appropriate. In the case of
* errors, loadlib returns nil and two strings describing the error.
* The first string is supplied by the operating system; it should be
* informative and useful for error messages. The second string is "open",
* "init", or "absent" to identify the error and is meant to be used for
* making decisions without having to look into the first string (whose
* format is system-dependent).
*
* This module contains an implementation of loadlib for Unix systems that
* have dlfcn, an implementation for Windows, and a stub for other systems.
* See the list at the end of this file for some links to available
* implementations of dlfcn and interfaces to other native dynamic loaders
* on top of which loadlib could be implemented.
*
*/
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#undef LOADLIB
#ifdef USE_DLOPEN
#define LOADLIB
/*
* This is an implementation of loadlib based on the dlfcn interface.
* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
* as an emulation layer on top of native functions.
*/
#include <dlfcn.h>
static int loadlib(lua_State *L)
{
const char *path=luaL_checkstring(L,1);
const char *init=luaL_checkstring(L,2);
void *lib=dlopen(path,RTLD_NOW);
if (lib!=NULL)
{
lua_CFunction f=(lua_CFunction) dlsym(lib,init);
if (f!=NULL)
{
lua_pushlightuserdata(L,lib);
lua_pushcclosure(L,f,1);
return 1;
}
}
/* else return appropriate error messages */
lua_pushnil(L);
lua_pushstring(L,dlerror());
lua_pushstring(L,(lib!=NULL) ? "init" : "open");
if (lib!=NULL) dlclose(lib);
return 3;
}
#endif
/*
** In Windows, default is to use dll; otherwise, default is not to use dll
*/
#ifndef USE_DLL
#ifdef _WIN32
#define USE_DLL 1
#else
#define USE_DLL 0
#endif
#endif
#if USE_DLL
#define LOADLIB
/*
* This is an implementation of loadlib for Windows using native functions.
*/
#include <windows.h>
static void pusherror(lua_State *L)
{
int error=GetLastError();
char buffer[128];
if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
0, error, 0, buffer, sizeof(buffer), 0))
lua_pushstring(L,buffer);
else
lua_pushfstring(L,"system error %d\n",error);
}
static int loadlib(lua_State *L)
{
const char *path=luaL_checkstring(L,1);
const char *init=luaL_checkstring(L,2);
HINSTANCE lib=LoadLibrary(path);
if (lib!=NULL)
{
lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init);
if (f!=NULL)
{
lua_pushlightuserdata(L,lib);
lua_pushcclosure(L,f,1);
return 1;
}
}
lua_pushnil(L);
pusherror(L);
lua_pushstring(L,(lib!=NULL) ? "init" : "open");
if (lib!=NULL) FreeLibrary(lib);
return 3;
}
#endif
#ifndef LOADLIB
/* Fallback for other systems */
/*
** Those systems support dlopen, so they should have defined USE_DLOPEN.
** The default (no)implementation gives them a special error message.
*/
#ifdef linux
#define LOADLIB
#endif
#ifdef sun
#define LOADLIB
#endif
#ifdef sgi
#define LOADLIB
#endif
#ifdef BSD
#define LOADLIB
#endif
#ifdef _WIN32
#define LOADLIB
#endif
#ifdef LOADLIB
#undef LOADLIB
#define LOADLIB "`loadlib' not installed (check your Lua configuration)"
#else
#define LOADLIB "`loadlib' not supported"
#endif
static int loadlib(lua_State *L)
{
lua_pushnil(L);
lua_pushliteral(L,LOADLIB);
lua_pushliteral(L,"absent");
return 3;
}
#endif
LUALIB_API int luaopen_loadlib (lua_State *L)
{
lua_register(L,"loadlib",loadlib);
return 0;
}
/*
* Here are some links to available implementations of dlfcn and
* interfaces to other native dynamic loaders on top of which loadlib
* could be implemented. Please send contributions and corrections to us.
*
* AIX
* Starting with AIX 4.2, dlfcn is included in the base OS.
* There is also an emulation package available.
* http://www.faqs.org/faqs/aix-faq/part4/section-21.html
*
* HPUX
* HPUX 11 has dlfcn. For HPUX 10 use shl_*.
* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html
* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
*
* Macintosh, Windows
* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
*
* Mac OS X/Darwin
* http://www.opendarwin.org/projects/dlcompat/
*
* GLIB has wrapper code for BeOS, OS2, Unix and Windows
* http://cvs.gnome.org/lxr/source/glib/gmodule/
*
*/

View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.c,v 1.85 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: lobject.c,v 1.96 2003/02/18 16:02:56 roberto Exp roberto $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,8 @@
#include <stdlib.h>
#include <string.h>
#define lobject_c
#include "lua.h"
#include "ldo.h"
@@ -28,6 +30,20 @@
const TObject luaO_nilobject = {LUA_TNIL, {NULL}};
/*
** converts an integer to a "floating point byte", represented as
** (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm)
*/
int luaO_int2fb (unsigned int x) {
int m = 0; /* mantissa */
while (x >= (1<<3)) {
x = (x+1) >> 1;
m++;
}
return (m << 3) | cast(int, x);
}
int luaO_log2 (unsigned int x) {
static const lu_byte log_8[255] = {
0,
@@ -57,35 +73,19 @@ int luaO_log2 (unsigned int x) {
int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
if (ttype(t1) != ttype(t2)) return 0;
switch (ttype(t1)) {
case LUA_TNUMBER:
return nvalue(t1) == nvalue(t2);
else switch (ttype(t1)) {
case LUA_TNIL:
return 1;
case LUA_TSTRING:
return tsvalue(t1) == tsvalue(t2);
case LUA_TNUMBER:
return nvalue(t1) == nvalue(t2);
case LUA_TBOOLEAN:
return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA:
return uvalue(t1) == uvalue(t2);
case LUA_TTABLE:
return hvalue(t1) == hvalue(t2);
case LUA_TFUNCTION:
return clvalue(t1) == clvalue(t2);
default:
lua_assert(iscollectable(t1));
return gcvalue(t1) == gcvalue(t2);
}
lua_assert(0);
return 0; /* to avoid warnings */
}
void *luaO_openspaceaux (lua_State *L, size_t n) {
if (n > G(L)->Mbuffsize) {
G(L)->Mbuffer = luaM_realloc(L, G(L)->Mbuffer, G(L)->Mbuffsize, n);
G(L)->Mbuffsize = n;
}
return G(L)->Mbuffer;
}
@@ -102,7 +102,7 @@ int luaO_str2d (const char *s, lua_Number *result) {
static void pushstr (lua_State *L, const char *str) {
setsvalue(L->top, luaS_new(L, str));
setsvalue2s(L->top, luaS_new(L, str));
incr_top(L);
}
@@ -114,7 +114,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
setsvalue(L->top, luaS_newlstr(L, fmt, e-fmt));
setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
switch (*(e+1)) {
case 's':
@@ -128,11 +128,11 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
break;
}
case 'd':
setnvalue(L->top, va_arg(argp, int));
setnvalue(L->top, cast(lua_Number, va_arg(argp, int)));
incr_top(L);
break;
case 'f':
setnvalue(L->top, va_arg(argp, lua_Number));
setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber)));
incr_top(L);
break;
case '%':
@@ -144,7 +144,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
fmt = e+2;
}
pushstr(L, fmt);
luaV_concat(L, n+1, L->top - L->ci->base - 1);
luaV_concat(L, n+1, L->top - L->base - 1);
L->top -= n;
return svalue(L->top - 1);
}

163
lobject.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $
** $Id: lobject.h,v 1.158 2003/02/18 16:02:56 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -13,20 +13,53 @@
/* tags for values visible from Lua */
#define NUM_TAGS LUA_TFUNCTION
#define NUM_TAGS LUA_TTHREAD
/*
** Extra tags for non-values
*/
#define LUA_TPROTO (NUM_TAGS+1)
#define LUA_TUPVAL (NUM_TAGS+2)
/*
** Union of all collectable objects
*/
typedef union GCObject GCObject;
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
/*
** Common header in struct form
*/
typedef struct GCheader {
CommonHeader;
} GCheader;
/*
** Union of all Lua values
*/
typedef union {
GCObject *gc;
void *p;
union TString *ts;
union Udata *u;
union Closure *cl;
struct Table *h;
lua_Number n;
int b;
} Value;
/*
** Lua values (or `tagged objects')
*/
typedef struct lua_TObject {
int tt;
Value value;
@@ -41,17 +74,20 @@ typedef struct lua_TObject {
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
/* Macros to access values */
#define ttype(o) ((o)->tt)
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
#define tsvalue(o) check_exp(ttisstring(o), (o)->value.ts)
#define uvalue(o) check_exp(ttisuserdata(o), (o)->value.u)
#define clvalue(o) check_exp(ttisfunction(o), (o)->value.cl)
#define hvalue(o) check_exp(ttistable(o), (o)->value.h)
#define tsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
#define uvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
@@ -69,26 +105,70 @@ typedef struct lua_TObject {
{ TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); }
#define setsvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TSTRING; i_o->value.ts=(x); }
{ TObject *i_o=(obj); i_o->tt=LUA_TSTRING; \
i_o->value.gc=cast(GCObject *, (x)); \
lua_assert(i_o->value.gc->gch.tt == LUA_TSTRING); }
#define setuvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; i_o->value.u=(x); }
{ TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; \
i_o->value.gc=cast(GCObject *, (x)); \
lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); }
#define setthvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \
i_o->value.gc=cast(GCObject *, (x)); \
lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); }
#define setclvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; i_o->value.cl=(x); }
{ TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \
i_o->value.gc=cast(GCObject *, (x)); \
lua_assert(i_o->value.gc->gch.tt == LUA_TFUNCTION); }
#define sethvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TTABLE; i_o->value.h=(x); }
{ TObject *i_o=(obj); i_o->tt=LUA_TTABLE; \
i_o->value.gc=cast(GCObject *, (x)); \
lua_assert(i_o->value.gc->gch.tt == LUA_TTABLE); }
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
/*
** for internal debug only
*/
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
#define setobj(obj1,obj2) \
{ const TObject *o2=(obj2); TObject *o1=(obj1); \
checkconsistency(o2); \
o1->tt=o2->tt; o1->value = o2->value; }
/*
** different types of sets, according to destination
*/
/* from stack to (same) stack */
#define setobjs2s setobj
/* to stack (not from same stack) */
#define setobj2s setobj
#define setsvalue2s setsvalue
/* from table to same table */
#define setobjt2t setobj
/* to table */
#define setobj2t setobj
/* to new object */
#define setobj2n setobj
#define setsvalue2n setsvalue
#define setttype(obj, tt) (ttype(obj) = (tt))
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
typedef TObject *StkId; /* index to stack elements */
@@ -97,12 +177,12 @@ typedef TObject *StkId; /* index to stack elements */
** String headers for string table
*/
typedef union TString {
union L_Umaxalign dummy; /* ensures maximum alignment for strings */
L_Umaxalign dummy; /* ensures maximum alignment for strings */
struct {
CommonHeader;
lu_byte reserved;
lu_hash hash;
size_t len;
int marked;
union TString *nexthash; /* chain for hash table */
} tsv;
} TString;
@@ -113,11 +193,11 @@ typedef union TString {
typedef union Udata {
union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct {
CommonHeader;
struct Table *metatable;
union Udata *next; /* chain for list of all udata */
size_t len; /* least 2 bits reserved for gc mark */
size_t len;
} uv;
} Udata;
@@ -128,23 +208,26 @@ typedef union Udata {
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
TObject *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
struct Proto *next;
int *lineinfo; /* map from opcodes to source lines */
struct LocVar *locvars; /* information about local variables */
TString **upvalues; /* upvalue names */
TString *source;
int sizeupvalues;
int sizek; /* size of `k' */
int sizecode;
int sizelineinfo;
int sizep; /* size of `p' */
int sizelocvars;
int lineDefined;
lu_byte nupvalues;
GCObject *gclist;
lu_byte nups; /* number of upvalues */
lu_byte numparams;
lu_byte is_vararg;
lu_byte maxstacksize;
lu_byte marked;
} Proto;
@@ -161,8 +244,8 @@ typedef struct LocVar {
*/
typedef struct UpVal {
CommonHeader;
TObject *v; /* points to stack or to its own value */
struct UpVal *next;
TObject value; /* the value (when closed) */
} UpVal;
@@ -171,21 +254,18 @@ typedef struct UpVal {
** Closures
*/
#define ClosureHeader \
CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist
typedef struct CClosure {
lu_byte isC; /* 0 for Lua functions, 1 for C functions */
lu_byte nupvalues;
lu_byte marked;
union Closure *next;
ClosureHeader;
lua_CFunction f;
TObject upvalue[1];
} CClosure;
typedef struct LClosure {
lu_byte isC;
lu_byte nupvalues;
lu_byte marked;
union Closure *next; /* first four fields must be equal to CClosure!! */
ClosureHeader;
struct Proto *p;
TObject g; /* global table for this closure */
UpVal *upvals[1];
@@ -214,21 +294,17 @@ typedef struct Node {
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable;
TObject *array; /* array part */
Node *node;
Node *firstfree; /* this position is free; all positions after it are full */
struct Table *next;
struct Table *mark; /* marked tables (point to itself when not marked) */
GCObject *gclist;
int sizearray; /* size of `array' array */
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
lu_byte mode;
} Table;
/* bit masks for `mode' */
#define WEAKKEY 1
#define WEAKVALUE 2
/*
@@ -240,17 +316,14 @@ typedef struct Table {
#define twoto(x) (1<<(x))
#define sizenode(t) (twoto((t)->lsizenode))
#define sizearray(t) ((t)->sizearray)
extern const TObject luaO_nilobject;
int luaO_log2 (unsigned int x);
#define luaO_openspace(L,n,t) cast(t *, luaO_openspaceaux(L,(n)*sizeof(t)))
void *luaO_openspaceaux (lua_State *L, size_t n);
int luaO_int2fb (unsigned int x);
#define fb2int(x) (((x) & 7) << ((x) >> 3))
int luaO_rawequalObj (const TObject *t1, const TObject *t2);
int luaO_str2d (const char *s, lua_Number *result);

View File

@@ -1,11 +1,13 @@
/*
** $Id: lopcodes.c,v 1.19 2002/05/13 13:09:00 roberto Exp roberto $
** $Id: lopcodes.c,v 1.21 2002/08/20 20:03:05 roberto Exp roberto $
** extracted automatically from lopcodes.h by mkprint.lua
** DO NOT EDIT
** See Copyright Notice in lua.h
*/
#define lopcodes_c
#include "lua.h"
#include "lobject.h"
@@ -39,8 +41,6 @@ const char *const luaP_opnames[] = {
"EQ",
"LT",
"LE",
"GT",
"GE",
"TEST",
"CALL",
"TAILCALL",
@@ -56,49 +56,47 @@ const char *const luaP_opnames[] = {
#endif
#define opmode(t,x,b,c,sa,k,m) (((t)<<OpModeT) | \
((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
#define opmode(t,b,bk,ck,sa,k,m) (((t)<<OpModeT) | \
((b)<<OpModeBreg) | ((bk)<<OpModeBrk) | ((ck)<<OpModeCrk) | \
((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* T _ B C sA K mode opcode */
opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */
,opmode(0,0,0,0, 1,1,iABx) /* OP_LOADK */
,opmode(0,0,0,0, 1,0,iABC) /* OP_LOADBOOL */
,opmode(0,0,1,0, 1,0,iABC) /* OP_LOADNIL */
,opmode(0,0,0,0, 1,0,iABC) /* OP_GETUPVAL */
,opmode(0,0,0,0, 1,1,iABx) /* OP_GETGLOBAL */
,opmode(0,0,1,1, 1,0,iABC) /* OP_GETTABLE */
,opmode(0,0,0,0, 0,1,iABx) /* OP_SETGLOBAL */
,opmode(0,0,0,0, 0,0,iABC) /* OP_SETUPVAL */
,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */
,opmode(0,0,0,0, 1,0,iABC) /* OP_NEWTABLE */
,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */
,opmode(0,0,1,1, 1,0,iABC) /* OP_ADD */
,opmode(0,0,1,1, 1,0,iABC) /* OP_SUB */
,opmode(0,0,1,1, 1,0,iABC) /* OP_MUL */
,opmode(0,0,1,1, 1,0,iABC) /* OP_DIV */
,opmode(0,0,1,1, 1,0,iABC) /* OP_POW */
,opmode(0,0,1,0, 1,0,iABC) /* OP_UNM */
,opmode(0,0,1,0, 1,0,iABC) /* OP_NOT */
,opmode(0,0,1,1, 1,0,iABC) /* OP_CONCAT */
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_JMP */
,opmode(1,0,0,1, 0,0,iABC) /* OP_EQ */
,opmode(1,0,0,1, 0,0,iABC) /* OP_LT */
,opmode(1,0,0,1, 0,0,iABC) /* OP_LE */
,opmode(1,0,0,1, 0,0,iABC) /* OP_GT */
,opmode(1,0,0,1, 0,0,iABC) /* OP_GE */
,opmode(1,0,0,1, 1,0,iABC) /* OP_TEST */
,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */
,opmode(0,0,0,0, 0,0,iABC) /* OP_TAILCALL */
,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_FORLOOP */
,opmode(1,0,0,0, 0,0,iABC) /* OP_TFORLOOP */
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_TFORPREP */
,opmode(0,0,0,0, 0,0,iABx) /* OP_SETLIST */
,opmode(0,0,0,0, 0,0,iABx) /* OP_SETLISTO */
,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */
,opmode(0,0,0,0, 1,0,iABx) /* OP_CLOSURE */
/* T B Bk Ck sA K mode opcode */
opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_MOVE */
,opmode(0, 0, 0, 0, 1, 1, iABx) /* OP_LOADK */
,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_LOADBOOL */
,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_LOADNIL */
,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_GETUPVAL */
,opmode(0, 0, 0, 0, 1, 1, iABx) /* OP_GETGLOBAL */
,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_GETTABLE */
,opmode(0, 0, 0, 0, 0, 1, iABx) /* OP_SETGLOBAL */
,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */
,opmode(0, 0, 1, 1, 0, 0, iABC) /* OP_SETTABLE */
,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_NEWTABLE */
,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_SELF */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_ADD */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_SUB */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_MUL */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_DIV */
,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_POW */
,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_UNM */
,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_NOT */
,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_CONCAT */
,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_JMP */
,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_EQ */
,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_LT */
,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_LE */
,opmode(1, 1, 0, 0, 1, 0, iABC) /* OP_TEST */
,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CALL */
,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_TAILCALL */
,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_RETURN */
,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORLOOP */
,opmode(1, 0, 0, 0, 0, 0, iABC) /* OP_TFORLOOP */
,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_TFORPREP */
,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLIST */
,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLISTO */
,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CLOSE */
,opmode(0, 0, 0, 0, 1, 0, iABx) /* OP_CLOSURE */
};

View File

@@ -1,5 +1,5 @@
/*
** $Id: lopcodes.h,v 1.99 2002/06/12 14:51:31 roberto Exp $
** $Id: lopcodes.h,v 1.101 2002/08/20 20:03:05 roberto Exp roberto $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -14,9 +14,9 @@
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
`A' : 8 bits (25-32)
`B' : 8 bits (17-24)
`C' : 10 bits (7-16)
`A' : 8 bits
`B' : 9 bits
`C' : 9 bits
`Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx
@@ -34,8 +34,8 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
/*
** size and position of opcode arguments.
*/
#define SIZE_C 10
#define SIZE_B 8
#define SIZE_C 9
#define SIZE_B 9
#define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_A 8
@@ -112,16 +112,20 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
/*
** invalid registers that fits in 8 bits
** invalid register that fits in 8 bits
*/
#define NO_REG MAXARG_A
#define NO_REG1 (NO_REG+1)
/*
** R(x) - register
** Kst(x) - constant (in constant table)
** R/K(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
** RK(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
*/
/*
** grep "ORDER OP" if you change these enums
*/
typedef enum {
@@ -135,21 +139,21 @@ OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
OP_ADD,/* A B C R(A) := R(B) + R/K(C) */
OP_SUB,/* A B C R(A) := R(B) - R/K(C) */
OP_MUL,/* A B C R(A) := R(B) * R/K(C) */
OP_DIV,/* A B C R(A) := R(B) / R/K(C) */
OP_POW,/* A B C R(A) := R(B) ^ R/K(C) */
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
OP_NOT,/* A B R(A) := not R(B) */
@@ -157,13 +161,11 @@ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
OP_JMP,/* sBx PC += sBx */
OP_EQ,/* A B C if ((R(A) == R/K(C)) ~= B) then pc++ */
OP_LT,/* A B C if ((R(A) < R/K(C)) ~= B) then pc++ */
OP_LE,/* A B C if ((R(A) <= R/K(C)) ~= B) then pc++ */
OP_GT,/* A B C if ((R(A) > R/K(C)) ~= B) then pc++ */
OP_GE,/* A B C if ((R(A) >= R/K(C)) ~= B) then pc++ */
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
OP_TEST,/* A B C if (R(C) <=> B) then R(A) := R(C) else pc++ */
OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
@@ -207,12 +209,15 @@ OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
*/
enum OpModeMask {
OpModeBreg = 2, /* B is a register */
OpModeCreg, /* C is a register/constant */
OpModeBrk, /* B is a register/constant */
OpModeCrk, /* C is a register/constant */
OpModesetA, /* instruction set register A */
OpModeK, /* Bx is a constant */
OpModeT /* operator is a test */
};
extern const lu_byte luaP_opmodes[NUM_OPCODES];
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))

340
lparser.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 1.190 2002/07/04 18:23:42 roberto Exp $
** $Id: lparser.c,v 1.207 2003/02/28 17:19:47 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,8 @@
#include <string.h>
#define lparser_c
#include "lua.h"
#include "lcode.h"
@@ -26,6 +28,10 @@
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \
luaX_syntaxerror(ls, "too many syntax levels");
#define leavelevel(ls) ((ls)->nestlevel--)
/*
** nodes for block list (list of active blocks)
@@ -43,9 +49,7 @@ typedef struct BlockCnt {
/*
** prototypes for recursive non-terminal functions
*/
static void body (LexState *ls, expdesc *v, int needself, int line);
static void chunk (LexState *ls);
static void constructor (LexState *ls, expdesc *v);
static void expr (LexState *ls, expdesc *v);
@@ -175,16 +179,22 @@ static void create_local (LexState *ls, const char *name) {
}
static int indexupvalue (FuncState *fs, expdesc *v) {
static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
int i;
for (i=0; i<fs->f->nupvalues; i++) {
if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info)
Proto *f = fs->f;
for (i=0; i<f->nups; i++) {
if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) {
lua_assert(fs->f->upvalues[i] == name);
return i;
}
}
/* new one */
luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, "upvalues");
fs->upvalues[fs->f->nupvalues] = *v;
return fs->f->nupvalues++;
luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues");
luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues,
TString *, MAX_INT, "");
fs->f->upvalues[f->nups] = name;
fs->upvalues[f->nups] = *v;
return f->nups++;
}
@@ -222,7 +232,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
var->info = luaK_stringK(fs, n); /* info points to global name */
}
else { /* LOCAL or UPVAL */
var->info = indexupvalue(fs, var);
var->info = indexupvalue(fs, n, var);
var->k = VUPVAL; /* upvalue in this level */
}
}
@@ -230,8 +240,10 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
}
static void singlevar (LexState *ls, expdesc *var, int base) {
singlevaraux(ls->fs, str_checkname(ls), var, base);
static TString *singlevar (LexState *ls, expdesc *var, int base) {
TString *varname = str_checkname(ls);
singlevaraux(ls->fs, varname, var, base);
return varname;
}
@@ -298,9 +310,9 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
MAXARG_Bx, "constant table overflow");
f->p[fs->np++] = func->f;
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
for (i=0; i<func->f->nupvalues; i++) {
luaK_exp2nextreg(fs, &func->upvalues[i]);
fs->freereg--; /* CLOSURE will use these values */
for (i=0; i<func->f->nups; i++) {
OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
}
}
@@ -322,11 +334,8 @@ static void open_func (LexState *ls, FuncState *fs) {
fs->nlocvars = 0;
fs->nactvar = 0;
fs->bl = NULL;
f->code = NULL;
f->source = ls->source;
f->maxstacksize = 1; /* register 0 is always valid */
f->numparams = 0; /* default for main chunk */
f->is_vararg = 0; /* default for main chunk */
f->maxstacksize = 2; /* registers 0/1 are always valid */
}
@@ -336,27 +345,29 @@ static void close_func (LexState *ls) {
Proto *f = fs->f;
removevars(ls, 0);
luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */
lua_assert(G(L)->roottable == fs->h);
G(L)->roottable = fs->h->next;
luaH_free(L, fs->h);
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
luaM_reallocvector(L, f->lineinfo, f->sizecode, fs->pc, int);
f->sizecode = fs->pc;
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
f->sizelineinfo = fs->pc;
luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject);
f->sizek = fs->nk;
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
f->sizep = fs->np;
luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
f->sizelocvars = fs->nlocvars;
luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
f->sizeupvalues = f->nups;
lua_assert(luaG_checkcode(f));
lua_assert(fs->bl == NULL);
ls->fs = fs->prev;
}
Proto *luaY_parser (lua_State *L, ZIO *z) {
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
struct LexState lexstate;
struct FuncState funcstate;
lexstate.buff = buff;
lexstate.nestlevel = 0;
luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
open_func(&lexstate, &funcstate);
next(&lexstate); /* read first token */
@@ -364,7 +375,8 @@ Proto *luaY_parser (lua_State *L, ZIO *z) {
check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
close_func(&lexstate);
lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nupvalues == 0);
lua_assert(funcstate.f->nups == 0);
lua_assert(lexstate.nestlevel == 0);
return funcstate.f;
}
@@ -395,69 +407,6 @@ static void luaY_index (LexState *ls, expdesc *v) {
}
static int explist1 (LexState *ls, expdesc *v) {
/* explist1 -> expr { `,' expr } */
int n = 1; /* at least one expression */
expr(ls, v);
while (testnext(ls, ',')) {
luaK_exp2nextreg(ls->fs, v);
expr(ls, v);
n++;
}
return n;
}
static void funcargs (LexState *ls, expdesc *f) {
FuncState *fs = ls->fs;
expdesc args;
int base, nparams;
int line = ls->linenumber;
switch (ls->t.token) {
case '(': { /* funcargs -> `(' [ explist1 ] `)' */
if (line != ls->lastline)
luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
next(ls);
if (ls->t.token == ')') /* arg list is empty? */
args.k = VVOID;
else {
explist1(ls, &args);
luaK_setcallreturns(fs, &args, LUA_MULTRET);
}
check_match(ls, ')', '(', line);
break;
}
case '{': { /* funcargs -> constructor */
constructor(ls, &args);
break;
}
case TK_STRING: { /* funcargs -> STRING */
codestring(ls, &args, ls->t.seminfo.ts);
next(ls); /* must use `seminfo' before `next' */
break;
}
default: {
luaX_syntaxerror(ls, "function arguments expected");
return;
}
}
lua_assert(f->k == VNONRELOC);
base = f->info; /* base register for call */
if (args.k == VCALL)
nparams = LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
luaK_exp2nextreg(fs, &args); /* close last argument */
nparams = fs->freereg - (base+1);
}
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
fs->f->lineinfo[f->info] = line;
fs->freereg = base+1; /* call remove function and arguments and leaves
(unless changed) one result */
}
/*
** {======================================================================
** Rules for Constructors
@@ -489,8 +438,8 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
check(ls, '=');
luaK_exp2RK(fs, &key);
expr(ls, &val);
luaK_exp2anyreg(fs, &val);
luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key));
luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key),
luaK_exp2RK(fs, &val));
fs->freereg = reg; /* free registers */
}
@@ -568,16 +517,111 @@ static void constructor (LexState *ls, expdesc *t) {
} while (testnext(ls, ',') || testnext(ls, ';'));
check_match(ls, '}', '{', line);
lastlistfield(fs, &cc);
if (cc.na > 0)
SETARG_B(fs->f->code[pc], luaO_log2(cc.na-1)+2); /* set initial table size */
SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */
}
/* }====================================================================== */
static void parlist (LexState *ls) {
/* parlist -> [ param { `,' param } ] */
int nparams = 0;
int dots = 0;
if (ls->t.token != ')') { /* is `parlist' not empty? */
do {
switch (ls->t.token) {
case TK_DOTS: dots = 1; next(ls); break;
case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break;
default: luaX_syntaxerror(ls, "<name> or `...' expected");
}
} while (!dots && testnext(ls, ','));
}
code_params(ls, nparams, dots);
}
static void body (LexState *ls, expdesc *e, int needself, int line) {
/* body -> `(' parlist `)' chunk END */
FuncState new_fs;
open_func(ls, &new_fs);
new_fs.f->lineDefined = line;
check(ls, '(');
if (needself)
create_local(ls, "self");
parlist(ls);
check(ls, ')');
chunk(ls);
check_match(ls, TK_END, TK_FUNCTION, line);
close_func(ls);
pushclosure(ls, &new_fs, e);
}
static int explist1 (LexState *ls, expdesc *v) {
/* explist1 -> expr { `,' expr } */
int n = 1; /* at least one expression */
expr(ls, v);
while (testnext(ls, ',')) {
luaK_exp2nextreg(ls->fs, v);
expr(ls, v);
n++;
}
return n;
}
static void funcargs (LexState *ls, expdesc *f) {
FuncState *fs = ls->fs;
expdesc args;
int base, nparams;
int line = ls->linenumber;
switch (ls->t.token) {
case '(': { /* funcargs -> `(' [ explist1 ] `)' */
if (line != ls->lastline)
luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
next(ls);
if (ls->t.token == ')') /* arg list is empty? */
args.k = VVOID;
else {
explist1(ls, &args);
luaK_setcallreturns(fs, &args, LUA_MULTRET);
}
check_match(ls, ')', '(', line);
break;
}
case '{': { /* funcargs -> constructor */
constructor(ls, &args);
break;
}
case TK_STRING: { /* funcargs -> STRING */
codestring(ls, &args, ls->t.seminfo.ts);
next(ls); /* must use `seminfo' before `next' */
break;
}
default: {
luaX_syntaxerror(ls, "function arguments expected");
return;
}
}
lua_assert(f->k == VNONRELOC);
base = f->info; /* base register for call */
if (args.k == VCALL)
nparams = LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
luaK_exp2nextreg(fs, &args); /* close last argument */
nparams = fs->freereg - (base+1);
}
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
luaK_fixline(fs, line);
fs->freereg = base+1; /* call remove function and arguments and leaves
(unless changed) one result */
}
/*
** {======================================================================
@@ -601,12 +645,18 @@ static void prefixexp (LexState *ls, expdesc *v) {
singlevar(ls, v, 1);
return;
}
#ifdef LUA_COMPATUPSYNTAX
case '%': { /* for compatibility only */
TString *varname;
int line = ls->linenumber;
next(ls); /* skip `%' */
singlevar(ls, v, 1);
check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete");
varname = singlevar(ls, v, 1);
if (v->k != VUPVAL)
luaX_errorline(ls, "global upvalues are obsolete",
getstr(varname), line);
return;
}
#endif
default: {
luaX_syntaxerror(ls, "unexpected symbol");
return;
@@ -698,8 +748,6 @@ static void simpleexp (LexState *ls, expdesc *v) {
}
static UnOpr getunopr (int op) {
switch (op) {
case TK_NOT: return OPR_NOT;
@@ -735,7 +783,7 @@ static const struct {
lu_byte right; /* right priority */
} priority[] = { /* ORDER OPR */
{6, 6}, {6, 6}, {7, 7}, {7, 7}, /* arithmetic */
{10, 9}, {5, 4}, /* power and concat (right associative) */
{10, 9}, {5, 4}, /* power and concat (right associative) */
{3, 3}, {3, 3}, /* equality */
{3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
{2, 2}, {1, 1} /* logical (and/or) */
@@ -750,7 +798,9 @@ static const struct {
*/
static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
BinOpr op;
UnOpr uop = getunopr(ls->t.token);
UnOpr uop;
enterlevel(ls);
uop = getunopr(ls->t.token);
if (uop != OPR_NOUNOPR) {
next(ls);
subexpr(ls, v, UNARY_PRIORITY);
@@ -769,6 +819,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
luaK_posfix(ls->fs, op, v, &v2);
op = nextop;
}
leavelevel(ls);
return op; /* return first untreated operator */
}
@@ -780,6 +831,7 @@ static void expr (LexState *ls, expdesc *v) {
/* }==================================================================== */
/*
** {======================================================================
** Rules for Statements
@@ -909,7 +961,7 @@ static void cond (LexState *ls, expdesc *v) {
static void whilestat (LexState *ls, int line) {
/* whilestat -> WHILE cond DO block END */
Instruction codeexp[MAXEXPWHILE + EXTRAEXP];
int lineexp = 0;
int lineexp;
int i;
int sizeexp;
FuncState *fs = ls->fs;
@@ -974,10 +1026,27 @@ static int exp1 (LexState *ls) {
}
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
BlockCnt bl;
FuncState *fs = ls->fs;
int prep, endfor;
adjustlocalvars(ls, nvars); /* scope for all variables */
check(ls, TK_DO);
enterblock(fs, &bl, 1); /* loop block */
prep = luaK_getlabel(fs);
block(ls);
luaK_patchtohere(fs, prep-1);
endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);
leaveblock(fs);
}
static void fornum (LexState *ls, TString *varname, int line) {
/* fornum -> NAME = exp1,exp1[,exp1] DO body */
FuncState *fs = ls->fs;
int prep, endfor;
int base = fs->freereg;
new_localvar(ls, varname, 0);
new_localvarstr(ls, "(for limit)", 1);
@@ -992,16 +1061,9 @@ static void fornum (LexState *ls, TString *varname, int line) {
luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
luaK_reserveregs(fs, 1);
}
adjustlocalvars(ls, 3); /* scope for control variables */
luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
luaK_jump(fs);
prep = luaK_getlabel(fs);
check(ls, TK_DO);
block(ls);
luaK_patchtohere(fs, prep-1);
endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
luaK_patchlist(fs, endfor, prep);
forbody(ls, base, line, 3, 1);
}
@@ -1009,9 +1071,8 @@ static void forlist (LexState *ls, TString *indexname) {
/* forlist -> NAME {,NAME} IN explist1 DO body */
FuncState *fs = ls->fs;
expdesc e;
int line;
int nvars = 0;
int prep;
int line;
int base = fs->freereg;
new_localvarstr(ls, "(for generator)", nvars++);
new_localvarstr(ls, "(for state)", nvars++);
@@ -1020,18 +1081,10 @@ static void forlist (LexState *ls, TString *indexname) {
new_localvar(ls, str_checkname(ls), nvars++);
check(ls, TK_IN);
line = ls->linenumber;
adjust_assign(ls, 3, explist1(ls, &e), &e);
luaK_reserveregs(fs, nvars - 3); /* registers for other variables */
adjust_assign(ls, nvars, explist1(ls, &e), &e);
luaK_checkstack(fs, 3); /* extra space to call generator */
luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);
adjustlocalvars(ls, nvars); /* scope for all variables */
check(ls, TK_DO);
prep = luaK_getlabel(fs);
block(ls);
luaK_patchtohere(fs, prep-1);
removevars(fs->ls, fs->nactvar - nvars); /* deactivate locals for next op. */
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
luaK_patchlist(fs, luaK_jump(fs), prep);
forbody(ls, base, line, nvars, 0);
}
@@ -1040,7 +1093,7 @@ static void forstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
TString *varname;
BlockCnt bl;
enterblock(fs, &bl, 1);
enterblock(fs, &bl, 0); /* block to control variable scope */
next(ls); /* skip `for' */
varname = str_checkname(ls); /* first variable name */
switch (ls->t.token) {
@@ -1137,6 +1190,7 @@ static void funcstat (LexState *ls, int line) {
needself = funcname(ls, &v);
body(ls, &b, needself, line);
luaK_storevar(ls->fs, &v, &b);
luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
}
@@ -1259,51 +1313,17 @@ static int statement (LexState *ls) {
}
static void parlist (LexState *ls) {
/* parlist -> [ param { `,' param } ] */
int nparams = 0;
int dots = 0;
if (ls->t.token != ')') { /* is `parlist' not empty? */
do {
switch (ls->t.token) {
case TK_DOTS: dots = 1; next(ls); break;
case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break;
default: luaX_syntaxerror(ls, "<name> or `...' expected");
}
} while (!dots && testnext(ls, ','));
}
code_params(ls, nparams, dots);
}
static void body (LexState *ls, expdesc *e, int needself, int line) {
/* body -> `(' parlist `)' chunk END */
FuncState new_fs;
open_func(ls, &new_fs);
new_fs.f->lineDefined = line;
check(ls, '(');
if (needself)
create_local(ls, "self");
parlist(ls);
check(ls, ')');
chunk(ls);
check_match(ls, TK_END, TK_FUNCTION, line);
close_func(ls);
pushclosure(ls, &new_fs, e);
}
/* }====================================================================== */
static void chunk (LexState *ls) {
/* chunk -> { stat [`;'] } */
int islast = 0;
enterlevel(ls);
while (!islast && !block_follow(ls->t.token)) {
islast = statement(ls);
testnext(ls, ';');
lua_assert(ls->fs->freereg >= ls->fs->nactvar);
ls->fs->freereg = ls->fs->nactvar; /* free registers */
}
leavelevel(ls);
}
/* }====================================================================== */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
** $Id: lparser.h,v 1.46 2002/12/19 11:11:55 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -65,7 +65,7 @@ typedef struct FuncState {
} FuncState;
Proto *luaY_parser (lua_State *L, ZIO *z);
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
#endif

228
lstate.c
View File

@@ -1,10 +1,14 @@
/*
** $Id: lstate.c,v 1.102 2002/08/06 15:32:22 roberto Exp roberto $
** $Id: lstate.c,v 1.122 2003/03/18 12:50:04 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#define lstate_c
#include "lua.h"
#include "ldebug.h"
@@ -19,13 +23,20 @@
#include "ltm.h"
/*
** macro to allow the inclusion of user information in Lua state
*/
#ifndef LUA_USERSTATE
#define EXTRASPACE 0
#else
union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
#define EXTRASPACE (sizeof(union UEXTRASPACE))
#endif
static void close_state (lua_State *L);
/*
** you can change this function through the official API
** you can change this function through the official API:
** call `lua_setpanicf'
*/
static int default_panic (lua_State *L) {
@@ -34,19 +45,41 @@ static int default_panic (lua_State *L) {
}
static void stack_init (lua_State *L, lua_State *OL) {
L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
L->top = L->stack;
L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
L->ci = L->base_ci;
L->ci->state = CI_C; /* not a Lua function */
setnilvalue(L->top++); /* `function' entry for this `ci' */
L->ci->base = L->top;
L->ci->top = L->top + LUA_MINSTACK;
L->size_ci = BASIC_CI_SIZE;
L->end_ci = L->base_ci + L->size_ci;
static lua_State *mallocstate (lua_State *L) {
lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE);
if (block == NULL) return NULL;
else {
block += EXTRASPACE;
return cast(lua_State *, block);
}
}
static void freestate (lua_State *L, lua_State *L1) {
luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
sizeof(lua_State) + EXTRASPACE);
}
static void stack_init (lua_State *L1, lua_State *L) {
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
L1->top = L1->stack;
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
L1->ci = L1->base_ci;
L1->ci->state = CI_C; /* not a Lua function */
setnilvalue(L1->top++); /* `function' entry for this `ci' */
L1->base = L1->ci->base = L1->top;
L1->ci->top = L1->top + LUA_MINSTACK;
L1->size_ci = BASIC_CI_SIZE;
L1->end_ci = L1->base_ci + L1->size_ci;
}
static void freestack (lua_State *L, lua_State *L1) {
luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
luaM_freearray(L, L1->stack, L1->stacksize, TObject);
}
@@ -54,38 +87,39 @@ static void stack_init (lua_State *L, lua_State *OL) {
** open parts that may cause memory-allocation errors
*/
static void f_luaopen (lua_State *L, void *ud) {
UNUSED(ud);
/* create a new global state */
L->l_G = luaM_new(L, global_State);
G(L)->GCthreshold = 0; /* mark it as unfinished state */
G(L)->strt.size = 0;
G(L)->strt.nuse = 0;
G(L)->strt.hash = NULL;
G(L)->Mbuffer = NULL;
G(L)->Mbuffsize = 0;
G(L)->panic = &default_panic;
G(L)->rootproto = NULL;
G(L)->rootcl = NULL;
G(L)->roottable = NULL;
G(L)->rootupval = NULL;
G(L)->rootudata = NULL;
G(L)->tmudata = NULL;
setnilvalue(key(G(L)->dummynode));
setnilvalue(val(G(L)->dummynode));
G(L)->dummynode->next = NULL;
G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
global_State *g = luaM_new(NULL, global_State);
UNUSED(ud);
if (g == NULL) luaD_throw(L, LUA_ERRMEM);
L->l_G = g;
g->mainthread = L;
g->GCthreshold = 0; /* mark it as unfinished state */
g->strt.size = 0;
g->strt.nuse = 0;
g->strt.hash = NULL;
setnilvalue(defaultmeta(L));
setnilvalue(registry(L));
luaZ_initbuffer(L, &g->buff);
g->panic = default_panic;
g->rootgc = NULL;
g->rootudata = NULL;
g->tmudata = NULL;
setnilvalue(gkey(g->dummynode));
setnilvalue(gval(g->dummynode));
g->dummynode->next = NULL;
g->nblocks = sizeof(lua_State) + sizeof(global_State);
stack_init(L, L); /* init stack */
/* create default meta table with a dummy table, and then close the loop */
sethvalue(defaultmeta(L), NULL);
sethvalue(defaultmeta(L), luaH_new(L, 0, 4));
defaultmeta(L)->tt = LUA_TTABLE;
sethvalue(defaultmeta(L), luaH_new(L, 0, 0));
hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L));
sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */
sethvalue(registry(L), luaH_new(L, 0, 0)); /* registry */
sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaT_init(L);
luaX_init(L);
luaS_fix(luaS_newliteral(L, MEMERRMSG));
G(L)->GCthreshold = 4*G(L)->nblocks;
g->GCthreshold = 4*G(L)->nblocks;
}
@@ -94,46 +128,64 @@ static void preinit_state (lua_State *L) {
L->stacksize = 0;
L->errorJmp = NULL;
L->hook = NULL;
L->hookmask = 0;
setallowhook(L, 1);
L->hookmask = L->hookinit = 0;
L->basehookcount = 0;
L->allowhook = 1;
resethookcount(L);
L->openupval = NULL;
L->size_ci = 0;
L->nCcalls = 0;
L->base_ci = L->ci = NULL;
L->errfunc = 0;
setnilvalue(defaultmeta(L));
setnilvalue(gt(L));
setnilvalue(registry(L));
}
LUA_API lua_State *lua_newthread (lua_State *OL) {
lua_State *L;
lua_lock(OL);
L = luaM_new(OL, lua_State);
preinit_state(L);
L->l_G = OL->l_G;
OL->next->previous = L; /* insert L into linked list */
L->next = OL->next;
OL->next = L;
L->previous = OL;
stack_init(L, OL); /* init stack */
setobj(defaultmeta(L), defaultmeta(OL)); /* share default meta table */
setobj(gt(L), gt(OL)); /* share table of globals */
setobj(registry(L), registry(OL)); /* share registry */
lua_unlock(OL);
lua_userstateopen(L);
return L;
static void close_state (lua_State *L) {
luaF_close(L, L->stack); /* close all upvalues for this thread */
if (G(L)) { /* close global state */
luaC_sweep(L, 1); /* collect all elements */
lua_assert(G(L)->rootgc == NULL);
lua_assert(G(L)->rootudata == NULL);
luaS_freeall(L);
luaZ_freebuffer(L, &G(L)->buff);
}
freestack(L, L);
if (G(L)) {
lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State));
luaM_freelem(NULL, G(L));
}
freestate(NULL, L);
}
lua_State *luaE_newthread (lua_State *L) {
lua_State *L1 = mallocstate(L);
luaC_link(L, valtogco(L1), LUA_TTHREAD);
preinit_state(L1);
L1->l_G = L->l_G;
stack_init(L1, L); /* init stack */
setobj2n(gt(L1), gt(L)); /* share table of globals */
return L1;
}
void luaE_freethread (lua_State *L, lua_State *L1) {
luaF_close(L1, L1->stack); /* close all upvalues for this thread */
lua_assert(L1->openupval == NULL);
freestack(L, L1);
freestate(L, L1);
}
LUA_API lua_State *lua_open (void) {
lua_State *L;
L = luaM_new(NULL, lua_State);
lua_State *L = mallocstate(NULL);
if (L) { /* allocation OK? */
L->tt = LUA_TTHREAD;
L->marked = 0;
L->next = L->gclist = NULL;
preinit_state(L);
L->l_G = NULL;
L->next = L->previous = L;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
/* memory allocation error: free partial state */
close_state(L);
@@ -145,48 +197,24 @@ LUA_API lua_State *lua_open (void) {
}
void luaE_closethread (lua_State *OL, lua_State *L) {
luaF_close(L, L->stack); /* close all upvalues for this thread */
lua_assert(L->openupval == NULL);
L->previous->next = L->next;
L->next->previous = L->previous;
luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
luaM_freearray(OL, L->stack, L->stacksize, TObject);
luaM_freelem(OL, L);
}
static void close_state (lua_State *L) {
luaF_close(L, L->stack); /* close all upvalues for this thread */
if (G(L)) { /* close global state */
luaC_collect(L, 1); /* collect all elements */
lua_assert(G(L)->rootproto == NULL);
lua_assert(G(L)->rootudata == NULL);
lua_assert(G(L)->rootcl == NULL);
lua_assert(G(L)->rootupval == NULL);
lua_assert(G(L)->roottable == NULL);
luaS_freeall(L);
luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
luaM_freelem(NULL, L->l_G);
}
luaE_closethread(NULL, L);
}
LUA_API void lua_closethread (lua_State *L, lua_State *thread) {
lua_lock(L);
if (L == thread) luaG_runerror(L, "cannot close only thread of a state");
luaE_closethread(L, thread);
lua_unlock(L);
static void callallgcTM (lua_State *L, void *ud) {
UNUSED(ud);
luaC_callGCTM(L); /* call GC metamethods for all udata */
}
LUA_API void lua_close (lua_State *L) {
lua_lock(L);
luaC_callallgcTM(L); /* call GC tag methods for all udata */
L = G(L)->mainthread; /* only the main thread can be closed */
luaF_close(L, L->stack); /* close all upvalues for this thread */
luaC_separateudata(L); /* separate udata that have GC metamethods */
L->errfunc = 0; /* no error function during GC metamethods */
do { /* repeat until no more errors */
L->ci = L->base_ci;
L->base = L->top = L->ci->base;
L->nCcalls = 0;
} while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
lua_assert(G(L)->tmudata == NULL);
while (L->next != L) /* then, close all other threads */
luaE_closethread(L, L->next);
close_state(L);
}

113
lstate.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 1.93 2002/08/07 19:22:39 roberto Exp roberto $
** $Id: lstate.h,v 1.108 2002/11/25 17:47:13 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -11,15 +11,16 @@
#include "lobject.h"
#include "ltm.h"
#include "lzio.h"
/*
** macros for thread syncronization inside Lua core machine:
** all accesses to the global state and to global objects are syncronized.
** macros for thread synchronization inside Lua core machine:
** all accesses to the global state and to global objects are synchronized.
** Because threads can read the stack of other threads
** (when running garbage collection),
** a thread must also syncronize any write-access to its own stack.
** Unsyncronized accesses are allowed only when reading its own stack,
** a thread must also synchronize any write-access to its own stack.
** Unsynchronized accesses are allowed only when reading its own stack,
** or when reading immutable fields from global objects
** (such as string values and udata values).
*/
@@ -31,12 +32,6 @@
#define lua_unlock(L) ((void) 0)
#endif
/*
** macro to allow the inclusion of user information in Lua state
*/
#ifndef LUA_USERSTATE
#define LUA_USERSTATE
#endif
#ifndef lua_userstateopen
#define lua_userstateopen(l)
@@ -47,21 +42,14 @@
struct lua_longjmp; /* defined in ldo.c */
/*
** array of `global' objects
*/
#define NUMGLOBS 3
/* default meta table (both for tables and udata) */
#define defaultmeta(L) (L->globs)
#define defaultmeta(L) (&G(L)->_defaultmeta)
/* table of globals */
#define gt(L) (L->globs + 1)
#define gt(L) (&L->_gt)
/* registry */
#define registry(L) (L->globs + 2)
#define registry(L) (&G(L)->_registry)
/* extra stack space to handle TM calls and some other extras */
@@ -75,7 +63,7 @@ struct lua_longjmp; /* defined in ldo.c */
typedef struct stringtable {
TString **hash;
GCObject **hash;
ls_nstr nuse; /* number of elements */
int size;
} stringtable;
@@ -92,10 +80,10 @@ typedef struct CallInfo {
struct { /* for Lua functions */
const Instruction *savedpc;
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
StkId *pb; /* points to `base' variable in `luaV_execute' */
int tailcalls; /* number of tail calls lost under this entry */
} l;
struct { /* for C functions */
int yield_results;
int dummy; /* just to avoid an empty struct */
} c;
} u;
} CallInfo;
@@ -104,13 +92,14 @@ typedef struct CallInfo {
/*
** bit fields for `CallInfo.state'
*/
#define CI_C 1 /* 1 if function is a C function */
#define CI_C (1<<0) /* 1 if function is a C function */
/* 1 if (Lua) function has an active `luaV_execute' running it */
#define CI_HASFRAME 2
#define CI_HASFRAME (1<<1)
/* 1 if Lua function is calling another Lua function (and therefore its
`pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */
#define CI_CALLING 4
#define CI_SAVEDPC 8 /* 1 if `savedpc' is updated */
#define CI_CALLING (1<<2)
#define CI_SAVEDPC (1<<3) /* 1 if `savedpc' is updated */
#define CI_YIELD (1<<4) /* 1 if thread is suspended */
#define ci_func(ci) (clvalue((ci)->base - 1))
@@ -121,17 +110,16 @@ typedef struct CallInfo {
*/
typedef struct global_State {
stringtable strt; /* hash table for strings */
Proto *rootproto; /* list of all prototypes */
Closure *rootcl; /* list of all closures */
Table *roottable; /* list of all tables */
UpVal *rootupval; /* list of closed up values */
Udata *rootudata; /* list of all userdata */
Udata *tmudata; /* list of userdata to be GC */
void *Mbuffer; /* global buffer */
size_t Mbuffsize; /* size of Mbuffer */
GCObject *rootgc; /* list of (almost) all collectable objects */
GCObject *rootudata; /* (separated) list of all userdata */
GCObject *tmudata; /* list of userdata to be GC */
Mbuffer buff; /* temporary buffer for string concatentation */
lu_mem GCthreshold;
lu_mem nblocks; /* number of `bytes' currently allocated */
lua_CFunction panic; /* to be called in unprotected errors */
TObject _registry;
TObject _defaultmeta;
struct lua_State *mainthread;
Node dummynode[1]; /* common node array for all empty tables */
TString *tmname[TM_N]; /* array with tag-method names */
} global_State;
@@ -141,8 +129,9 @@ typedef struct global_State {
** `per thread' state
*/
struct lua_State {
LUA_USERSTATE
CommonHeader;
StkId top; /* first free slot in the stack */
StkId base; /* base of current function */
global_State *l_G;
CallInfo *ci; /* call info for current function */
StkId stack_last; /* last free slot in the stack */
@@ -150,23 +139,57 @@ struct lua_State {
int stacksize;
CallInfo *end_ci; /* points after end of ci array*/
CallInfo *base_ci; /* array of CallInfo's */
int size_ci; /* size of array `base_ci' */
unsigned long hookmask;
ls_count hookcount;
unsigned short size_ci; /* size of array `base_ci' */
unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask;
lu_byte allowhook;
lu_byte hookinit;
int basehookcount;
int hookcount;
lua_Hook hook;
UpVal *openupval; /* list of open upvalues in this stack */
TObject _gt; /* table of globals */
GCObject *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */
ptrdiff_t errfunc; /* current error handling function (stack index) */
lua_State *next; /* circular double linked list of states */
lua_State *previous;
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
};
#define G(L) (L->l_G)
void luaE_closethread (lua_State *OL, lua_State *L);
/*
** Union of all collectable objects
*/
union GCObject {
GCheader gch;
union TString ts;
union Udata u;
union Closure cl;
struct Table h;
struct Proto p;
struct UpVal uv;
struct lua_State th; /* thread */
};
/* macros to convert a GCObject into a specific value */
#define gcotots(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
#define gcotou(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
#define gcotocl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
#define gcotoh(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gcotop(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gcotouv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define ngcotouv(o) \
check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define gcototh(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
/* macro to convert any value into a GCObject */
#define valtogco(v) (cast(GCObject *, (v)))
lua_State *luaE_newthread (lua_State *L);
void luaE_freethread (lua_State *L, lua_State *L1);
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstring.c,v 1.73 2002/03/20 18:37:13 roberto Exp roberto $
** $Id: lstring.c,v 1.77 2002/11/13 11:32:26 roberto Exp roberto $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,8 @@
#include <string.h>
#define lstring_c
#include "lua.h"
#include "lmem.h"
@@ -23,19 +25,19 @@ void luaS_freeall (lua_State *L) {
void luaS_resize (lua_State *L, int newsize) {
TString **newhash = luaM_newvector(L, newsize, TString *);
GCObject **newhash = luaM_newvector(L, newsize, GCObject *);
stringtable *tb = &G(L)->strt;
int i;
for (i=0; i<newsize; i++) newhash[i] = NULL;
/* rehash */
for (i=0; i<tb->size; i++) {
TString *p = tb->hash[i];
GCObject *p = tb->hash[i];
while (p) { /* for each node in the list */
TString *next = p->tsv.nexthash; /* save next */
lu_hash h = p->tsv.hash;
GCObject *next = p->gch.next; /* save next */
lu_hash h = gcotots(p)->tsv.hash;
int h1 = lmod(h, newsize); /* new position */
lua_assert(cast(int, h%newsize) == lmod(h, newsize));
p->tsv.nexthash = newhash[h1]; /* chain it in new position */
p->gch.next = newhash[h1]; /* chain it */
newhash[h1] = p;
p = next;
}
@@ -49,16 +51,17 @@ void luaS_resize (lua_State *L, int newsize) {
static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
TString *ts = cast(TString *, luaM_malloc(L, sizestring(l)));
stringtable *tb;
ts->tsv.nexthash = NULL;
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.marked = 0;
ts->tsv.tt = LUA_TSTRING;
ts->tsv.reserved = 0;
memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */
tb = &G(L)->strt;
h = lmod(h, tb->size);
ts->tsv.nexthash = tb->hash[h]; /* chain new entry */
tb->hash[h] = ts;
ts->tsv.next = tb->hash[h]; /* chain new entry */
tb->hash[h] = valtogco(ts);
tb->nuse++;
if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
@@ -67,15 +70,16 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
TString *ts;
GCObject *o;
lu_hash h = (lu_hash)l; /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=l; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1]));
for (ts = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
ts != NULL;
ts = ts->tsv.nexthash) {
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL;
o = o->gch.next) {
TString *ts = gcotots(o);
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0))
return ts;
}
@@ -85,13 +89,14 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
Udata *luaS_newudata (lua_State *L, size_t s) {
Udata *u;
s = (s+3) & (~(size_t)3); /* make sure size is multiple of 4 */
u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
u->uv.marked = (1<<1); /* is not finalized */
u->uv.tt = LUA_TUSERDATA;
u->uv.len = s;
u->uv.metatable = hvalue(defaultmeta(L));
/* chain it on udata list */
u->uv.next = G(L)->rootudata;
G(L)->rootudata = u;
G(L)->rootudata = valtogco(u);
return u;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstring.h,v 1.35 2001/11/28 20:13:13 roberto Exp roberto $
** $Id: lstring.h,v 1.36 2002/04/30 13:01:48 roberto Exp roberto $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -13,14 +13,6 @@
/*
** any TString with mark>=FIXMARK is never collected.
** Marks>=RESERVEDMARK are used to identify reserved words.
*/
#define FIXMARK 2
#define RESERVEDMARK 3
#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \
(cast(lu_mem, l)+1)*sizeof(char))
@@ -30,7 +22,7 @@
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1))
#define luaS_fix(s) ((s)->tsv.marked = FIXMARK)
#define luaS_fix(s) ((s)->tsv.marked |= (1<<4))
void luaS_resize (lua_State *L, int newsize);
Udata *luaS_newudata (lua_State *L, size_t s);

224
lstrlib.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lstrlib.c,v 1.86 2002/06/25 19:16:44 roberto Exp roberto $
** $Id: lstrlib.c,v 1.97 2003/03/19 21:16:12 roberto Exp roberto $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <string.h>
#define lstrlib_c
#include "lua.h"
#include "lauxlib.h"
@@ -28,8 +30,8 @@ typedef long sint32; /* a signed version for size_t */
static int str_len (lua_State *L) {
size_t l;
luaL_check_lstr(L, 1, &l);
lua_pushnumber(L, l);
luaL_checklstring(L, 1, &l);
lua_pushnumber(L, (lua_Number)l);
return 1;
}
@@ -42,11 +44,11 @@ static sint32 posrelat (sint32 pos, size_t len) {
static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_check_lstr(L, 1, &l);
sint32 start = posrelat(luaL_check_long(L, 2), l);
sint32 end = posrelat(luaL_opt_long(L, 3, -1), l);
const char *s = luaL_checklstring(L, 1, &l);
sint32 start = posrelat(luaL_checklong(L, 2), l);
sint32 end = posrelat(luaL_optlong(L, 3, -1), l);
if (start < 1) start = 1;
if (end > (sint32)l) end = l;
if (end > (sint32)l) end = (sint32)l;
if (start <= end)
lua_pushlstring(L, s+start-1, end-start+1);
else lua_pushliteral(L, "");
@@ -58,7 +60,7 @@ static int str_lower (lua_State *L) {
size_t l;
size_t i;
luaL_Buffer b;
const char *s = luaL_check_lstr(L, 1, &l);
const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b);
for (i=0; i<l; i++)
luaL_putchar(&b, tolower(uchar(s[i])));
@@ -71,7 +73,7 @@ static int str_upper (lua_State *L) {
size_t l;
size_t i;
luaL_Buffer b;
const char *s = luaL_check_lstr(L, 1, &l);
const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b);
for (i=0; i<l; i++)
luaL_putchar(&b, toupper(uchar(s[i])));
@@ -82,8 +84,8 @@ static int str_upper (lua_State *L) {
static int str_rep (lua_State *L) {
size_t l;
luaL_Buffer b;
const char *s = luaL_check_lstr(L, 1, &l);
int n = luaL_check_int(L, 2);
const char *s = luaL_checklstring(L, 1, &l);
int n = luaL_checkint(L, 2);
luaL_buffinit(L, &b);
while (n-- > 0)
luaL_addlstring(&b, s, l);
@@ -94,9 +96,10 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_check_lstr(L, 1, &l);
sint32 pos = posrelat(luaL_opt_long(L, 2, 1), l);
luaL_arg_check(L, 0 < pos && (size_t)(pos) <= l, 2, "out of range");
const char *s = luaL_checklstring(L, 1, &l);
sint32 pos = posrelat(luaL_optlong(L, 2, 1), l);
if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */
return 0; /* no answer */
lua_pushnumber(L, uchar(s[pos-1]));
return 1;
}
@@ -108,8 +111,8 @@ static int str_char (lua_State *L) {
luaL_Buffer b;
luaL_buffinit(L, &b);
for (i=1; i<=n; i++) {
int c = luaL_check_int(L, i);
luaL_arg_check(L, uchar(c) == c, i, "invalid value");
int c = luaL_checkint(L, i);
luaL_argcheck(L, uchar(c) == c, i, "invalid value");
luaL_putchar(&b, uchar(c));
}
luaL_pushresult(&b);
@@ -117,6 +120,24 @@ static int str_char (lua_State *L) {
}
static int writer (lua_State *L, const void* b, size_t size, void* B) {
(void)L;
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
return 1;
}
static int str_dump (lua_State *L) {
luaL_Buffer b;
luaL_checktype(L, 1, LUA_TFUNCTION);
luaL_buffinit(L,&b);
if (!lua_dump(L, writer, &b))
luaL_error(L, "unable to dump given function");
luaL_pushresult(&b);
return 1;
}
/*
** {======================================================
@@ -166,11 +187,12 @@ static int capture_to_close (MatchState *ms) {
static const char *luaI_classend (MatchState *ms, const char *p) {
switch (*p++) {
case ESC:
case ESC: {
if (*p == '\0')
luaL_error(ms->L, "malformed pattern (ends with `%')");
return p+1;
case '[':
}
case '[': {
if (*p == '^') p++;
do { /* look for a `]' */
if (*p == '\0')
@@ -179,8 +201,10 @@ static const char *luaI_classend (MatchState *ms, const char *p) {
p++; /* skip escapes (e.g. `%]') */
} while (*p != ']');
return p+1;
default:
}
default: {
return p;
}
}
}
@@ -229,14 +253,10 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
static int luaI_singlematch (int c, const char *p, const char *ep) {
switch (*p) {
case '.': /* matches any char */
return 1;
case ESC:
return match_class(c, *(p+1));
case '[':
return matchbracketclass(c, p, ep-1);
default:
return (uchar(*p) == c);
case '.': return 1; /* matches any char */
case ESC: return match_class(c, *(p+1));
case '[': return matchbracketclass(c, p, ep-1);
default: return (uchar(*p) == c);
}
}
@@ -331,31 +351,51 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
static const char *match (MatchState *ms, const char *s, const char *p) {
init: /* using goto's to optimize tail recursion */
switch (*p) {
case '(': /* start capture */
case '(': { /* start capture */
if (*(p+1) == ')') /* position capture? */
return start_capture(ms, s, p+2, CAP_POSITION);
else
return start_capture(ms, s, p+1, CAP_UNFINISHED);
case ')': /* end capture */
}
case ')': { /* end capture */
return end_capture(ms, s, p+1);
case ESC: /* may be %[0-9] or %b */
if (isdigit(uchar(*(p+1)))) { /* capture? */
s = match_capture(ms, s, *(p+1));
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(ms, s, p+2) */
}
case ESC: {
switch (*(p+1)) {
case 'b': { /* balanced string? */
s = matchbalance(ms, s, p+2);
if (s == NULL) return NULL;
p+=4; goto init; /* else return match(ms, s, p+4); */
}
case 'f': { /* frontier? */
const char *ep; char previous;
p += 2;
if (*p != '[')
luaL_error(ms->L, "missing `[' after `%%f' in pattern");
ep = luaI_classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s-1);
if (matchbracketclass(uchar(previous), p, ep-1) ||
!matchbracketclass(uchar(*s), p, ep-1)) return NULL;
p=ep; goto init; /* else return match(ms, s, ep); */
}
default: {
if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
s = match_capture(ms, s, *(p+1));
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(ms, s, p+2) */
}
goto dflt; /* case default */
}
}
else if (*(p+1) == 'b') { /* balanced string? */
s = matchbalance(ms, s, p+2);
if (s == NULL) return NULL;
p+=4; goto init; /* else return match(ms, s, p+4); */
}
else goto dflt; /* case default */
case '\0': /* end of pattern */
}
case '\0': { /* end of pattern */
return s; /* match succeeded */
case '$':
}
case '$': {
if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
return (s == ms->src_end) ? s : NULL; /* check end of string */
else goto dflt;
}
default: dflt: { /* it is a pattern item */
const char *ep = luaI_classend(ms, p); /* points to what is next */
int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep);
@@ -366,15 +406,19 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
return res;
p=ep+1; goto init; /* else return match(ms, s, ep+1); */
}
case '*': /* 0 or more repetitions */
case '*': { /* 0 or more repetitions */
return max_expand(ms, s, p, ep);
case '+': /* 1 or more repetitions */
}
case '+': { /* 1 or more repetitions */
return (m ? max_expand(ms, s+1, p, ep) : NULL);
case '-': /* 0 or more repetitions (minimum) */
}
case '-': { /* 0 or more repetitions (minimum) */
return min_expand(ms, s, p, ep);
default:
}
default: {
if (!m) return NULL;
s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
}
}
}
}
@@ -408,7 +452,7 @@ static void push_onecapture (MatchState *ms, int i) {
int l = ms->capture[i].len;
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
if (l == CAP_POSITION)
lua_pushnumber(ms->L, ms->capture[i].init - ms->src_init + 1);
lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1));
else
lua_pushlstring(ms->L, ms->capture[i].init, l);
}
@@ -416,7 +460,7 @@ static void push_onecapture (MatchState *ms, int i) {
static int push_captures (MatchState *ms, const char *s, const char *e) {
int i;
luaL_check_stack(ms->L, ms->level, "too many captures");
luaL_checkstack(ms->L, ms->level, "too many captures");
if (ms->level == 0 && s) { /* no explicit captures? */
lua_pushlstring(ms->L, s, e-s); /* return whole match */
return 1;
@@ -431,17 +475,18 @@ static int push_captures (MatchState *ms, const char *s, const char *e) {
static int str_find (lua_State *L) {
size_t l1, l2;
const char *s = luaL_check_lstr(L, 1, &l1);
const char *p = luaL_check_lstr(L, 2, &l2);
sint32 init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1;
luaL_arg_check(L, 0 <= init && (size_t)(init) <= l1, 3, "out of range");
const char *s = luaL_checklstring(L, 1, &l1);
const char *p = luaL_checklstring(L, 2, &l2);
sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1;
if (init < 0) init = 0;
else if ((size_t)(init) > l1) init = (sint32)l1;
if (lua_toboolean(L, 4) || /* explicit request? */
strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */
/* do a plain search */
const char *s2 = lmemfind(s+init, l1-init, p, l2);
if (s2) {
lua_pushnumber(L, s2-s+1);
lua_pushnumber(L, s2-s+l2);
lua_pushnumber(L, (lua_Number)(s2-s+1));
lua_pushnumber(L, (lua_Number)(s2-s+l2));
return 2;
}
}
@@ -456,8 +501,8 @@ static int str_find (lua_State *L) {
const char *res;
ms.level = 0;
if ((res=match(&ms, s1, p)) != NULL) {
lua_pushnumber(L, s1-s+1); /* start */
lua_pushnumber(L, res-s); /* end */
lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */
lua_pushnumber(L, (lua_Number)(res-s)); /* end */
return push_captures(&ms, NULL, 0) + 2;
}
} while (s1++<ms.src_end && !anchor);
@@ -484,7 +529,7 @@ static int gfind_aux (lua_State *L) {
if ((e = match(&ms, src, p)) != NULL) {
int newstart = e-s;
if (e == src) newstart++; /* empty match? go at least one position */
lua_pushnumber(L, newstart);
lua_pushnumber(L, (lua_Number)newstart);
lua_replace(L, lua_upvalueindex(3));
return push_captures(&ms, src, e);
}
@@ -494,8 +539,8 @@ static int gfind_aux (lua_State *L) {
static int gfind (lua_State *L) {
luaL_check_string(L, 1);
luaL_check_string(L, 2);
luaL_checkstring(L, 1);
luaL_checkstring(L, 2);
lua_settop(L, 2);
lua_pushnumber(L, 0);
lua_pushcclosure(L, gfind_aux, 3);
@@ -540,14 +585,14 @@ static void add_s (MatchState *ms, luaL_Buffer *b,
static int str_gsub (lua_State *L) {
size_t srcl;
const char *src = luaL_check_lstr(L, 1, &srcl);
const char *p = luaL_check_string(L, 2);
int max_s = luaL_opt_int(L, 4, srcl+1);
const char *src = luaL_checklstring(L, 1, &srcl);
const char *p = luaL_checkstring(L, 2);
int max_s = luaL_optint(L, 4, srcl+1);
int anchor = (*p == '^') ? (p++, 1) : 0;
int n = 0;
MatchState ms;
luaL_Buffer b;
luaL_arg_check(L,
luaL_argcheck(L,
lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
3, "string or function expected");
luaL_buffinit(L, &b);
@@ -571,7 +616,7 @@ static int str_gsub (lua_State *L) {
}
luaL_addlstring(&b, src, ms.src_end-src);
luaL_pushresult(&b);
lua_pushnumber(L, n); /* number of substitutions */
lua_pushnumber(L, (lua_Number)n); /* number of substitutions */
return 2;
}
@@ -586,16 +631,23 @@ static int str_gsub (lua_State *L) {
static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
size_t l;
const char *s = luaL_check_lstr(L, arg, &l);
const char *s = luaL_checklstring(L, arg, &l);
luaL_putchar(b, '"');
while (l--) {
switch (*s) {
case '"': case '\\': case '\n':
case '"': case '\\': case '\n': {
luaL_putchar(b, '\\');
luaL_putchar(b, *s);
break;
case '\0': luaL_addlstring(b, "\\000", 4); break;
default: luaL_putchar(b, *s);
}
case '\0': {
luaL_addlstring(b, "\\000", 4);
break;
}
default: {
luaL_putchar(b, *s);
break;
}
}
s++;
}
@@ -629,7 +681,7 @@ static const char *scanformat (lua_State *L, const char *strfrmt,
static int str_format (lua_State *L) {
int arg = 1;
size_t sfl;
const char *strfrmt = luaL_check_lstr(L, arg, &sfl);
const char *strfrmt = luaL_checklstring(L, arg, &sfl);
const char *strfrmt_end = strfrmt+sfl;
luaL_Buffer b;
luaL_buffinit(L, &b);
@@ -643,26 +695,30 @@ static int str_format (lua_State *L) {
char buff[MAX_ITEM]; /* to store the formatted item */
int hasprecision = 0;
if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$')
return luaL_error(L, "obsolete `format' option (d$)");
return luaL_error(L, "obsolete option (d$) to `format'");
arg++;
strfrmt = scanformat(L, strfrmt, form, &hasprecision);
switch (*strfrmt++) {
case 'c': case 'd': case 'i':
sprintf(buff, form, luaL_check_int(L, arg));
case 'c': case 'd': case 'i': {
sprintf(buff, form, luaL_checkint(L, arg));
break;
case 'o': case 'u': case 'x': case 'X':
sprintf(buff, form, (unsigned int)(luaL_check_number(L, arg)));
}
case 'o': case 'u': case 'x': case 'X': {
sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg)));
break;
}
case 'e': case 'E': case 'f':
case 'g': case 'G':
sprintf(buff, form, luaL_check_number(L, arg));
case 'g': case 'G': {
sprintf(buff, form, luaL_checknumber(L, arg));
break;
case 'q':
}
case 'q': {
luaI_addquoted(L, &b, arg);
continue; /* skip the `addsize' at the end */
}
case 's': {
size_t l;
const char *s = luaL_check_lstr(L, arg, &l);
const char *s = luaL_checklstring(L, arg, &l);
if (!hasprecision && l >= 100) {
/* no precision and string is too long to be formatted;
keep original string */
@@ -675,8 +731,9 @@ static int str_format (lua_State *L) {
break;
}
}
default: /* also treat cases `pnLlh' */
return luaL_error(L, "invalid option in `format'");
default: { /* also treat cases `pnLlh' */
return luaL_error(L, "invalid option to `format'");
}
}
luaL_addlstring(&b, buff, strlen(buff));
}
@@ -695,6 +752,7 @@ static const luaL_reg strlib[] = {
{"rep", str_rep},
{"byte", str_byte},
{"format", str_format},
{"dump", str_dump},
{"find", str_find},
{"gfind", gfind},
{"gsub", str_gsub},
@@ -705,8 +763,8 @@ static const luaL_reg strlib[] = {
/*
** Open string library
*/
LUALIB_API int lua_strlibopen (lua_State *L) {
luaL_opennamedlib(L, LUA_STRLIBNAME, strlib, 0);
return 0;
LUALIB_API int luaopen_string (lua_State *L) {
luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
return 1;
}

168
ltable.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltable.c,v 1.115 2002/08/05 14:45:32 roberto Exp roberto $
** $Id: ltable.c,v 1.131 2003/03/24 14:18:42 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -21,12 +21,15 @@
** performance penalties.
*/
#include <string.h>
#define ltable_c
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
@@ -52,17 +55,41 @@
#endif
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
#define hashboolean(t,p) hashpow2(t, p)
#define hashnum(t,n) \
(node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t))))
#define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t))))
#define hashboolean(t,p) (node(t, lmod(p, sizenode(t))))
/*
** avoid modulus by power of 2 for pointers, as they tend to have many
** 2 factors.
** for some types, it is better to avoid modulus by power of 2, as
** they tend to have many 2 factors.
*/
#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1))))
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
#define hashpointer(t,p) hashmod(t, IntPoint(p))
/*
** number of ints inside a lua_Number
*/
#define numints cast(int, sizeof(lua_Number)/sizeof(int))
/*
** hash for lua_Numbers
*/
static Node *hashnum (const Table *t, lua_Number n) {
unsigned int a[numints];
int i;
n += 1; /* normalize number (avoid -0) */
lua_assert(sizeof(a) <= sizeof(n));
memcpy(a, &n, sizeof(a));
for (i = 1; i < numints; i++) a[0] += a[i];
return hashmod(t, cast(lu_hash, a[0]));
}
/*
@@ -71,26 +98,17 @@
*/
Node *luaH_mainposition (const Table *t, const TObject *key) {
switch (ttype(key)) {
case LUA_TNUMBER: {
int ikey;
lua_number2int(ikey, nvalue(key));
return hashnum(t, ikey);
}
case LUA_TNUMBER:
return hashnum(t, nvalue(key));
case LUA_TSTRING:
return hashstr(t, tsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
return hashpointer(t, pvalue(key));
case LUA_TUSERDATA:
return hashpointer(t, uvalue(key));
case LUA_TFUNCTION:
return hashpointer(t, clvalue(key));
case LUA_TTABLE:
return hashpointer(t, hvalue(key));
default:
return hashpointer(t, gcvalue(key));
}
lua_assert(0);
return 0; /* to avoid warnings */
}
@@ -114,7 +132,7 @@ static int arrayindex (const TObject *key) {
** elements in the array part, then elements in the hash part. The
** beginning and end of a traversal are signalled by -1.
*/
static int luaH_index (lua_State *L, Table *t, const TObject *key) {
static int luaH_index (lua_State *L, Table *t, StkId key) {
int i;
if (ttisnil(key)) return -1; /* first iteration */
i = arrayindex(key);
@@ -126,25 +144,25 @@ static int luaH_index (lua_State *L, Table *t, const TObject *key) {
if (v == &luaO_nilobject)
luaG_runerror(L, "invalid key for `next'");
i = cast(int, (cast(const lu_byte *, v) -
cast(const lu_byte *, val(node(t, 0)))) / sizeof(Node));
cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node));
return i + t->sizearray; /* hash elements are numbered after array ones */
}
}
int luaH_next (lua_State *L, Table *t, TObject *key) {
int luaH_next (lua_State *L, Table *t, StkId key) {
int i = luaH_index(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
setnvalue(key, i+1);
setobj(key+1, &t->array[i]);
setnvalue(key, cast(lua_Number, i+1));
setobj2s(key+1, &t->array[i]);
return 1;
}
}
for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
if (!ttisnil(val(node(t, i)))) { /* a non-nil value? */
setobj(key, key(node(t, i)));
setobj(key+1, val(node(t, i)));
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
setobj2s(key, gkey(gnode(t, i)));
setobj2s(key+1, gval(gnode(t, i)));
return 1;
}
}
@@ -164,7 +182,7 @@ static void computesizes (int nums[], int ntotal, int *narray, int *nhash) {
int a = nums[0]; /* number of elements smaller than 2^i */
int na = a; /* number of elements to go to array part */
int n = (na == 0) ? -1 : 0; /* (log of) optimal size for array part */
for (i = 1; i <= MAXBITS && *narray >= twoto(i-1); i++) {
for (i = 1; a < *narray && *narray >= twoto(i-1); i++) {
if (nums[i] > 0) {
a += nums[i];
if (a >= twoto(i-1)) { /* more than half elements in use? */
@@ -182,27 +200,31 @@ static void computesizes (int nums[], int ntotal, int *narray, int *nhash) {
static void numuse (const Table *t, int *narray, int *nhash) {
int nums[MAXBITS+1];
int i;
int i, lg;
int totaluse = 0;
for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* init `nums' */
/* count elements in array part */
i = luaO_log2(t->sizearray) + 1; /* number of `slices' */
while (i--) { /* for each slice [2^(i-1) to 2^i) */
int to = twoto(i);
int from = to/2;
if (to > t->sizearray) to = t->sizearray;
for (; from < to; from++)
if (!ttisnil(&t->array[from])) {
nums[i]++;
for (i=0, lg=0; lg<=MAXBITS; lg++) { /* for each slice [2^(lg-1) to 2^lg) */
int ttlg = twoto(lg); /* 2^lg */
if (ttlg > t->sizearray) {
ttlg = t->sizearray;
if (i >= ttlg) break;
}
nums[lg] = 0;
for (; i<ttlg; i++) {
if (!ttisnil(&t->array[i])) {
nums[lg]++;
totaluse++;
}
}
}
for (; lg<=MAXBITS; lg++) nums[lg] = 0; /* reset other counts */
*narray = totaluse; /* all previous uses were in array part */
/* count elements in hash part */
i = sizenode(t);
while (i--) {
if (!ttisnil(val(&t->node[i]))) {
int k = arrayindex(key(&t->node[i]));
Node *n = &t->node[i];
if (!ttisnil(gval(n))) {
int k = arrayindex(gkey(n));
if (k >= 0) { /* is `key' an appropriate array index? */
nums[luaO_log2(k-1)+1]++; /* count as such */
(*narray)++;
@@ -230,20 +252,20 @@ static void setnodevector (lua_State *L, Table *t, int lsize) {
luaG_runerror(L, "table overflow");
if (lsize == 0) { /* no elements to hash part? */
t->node = G(L)->dummynode; /* use common `dummynode' */
lua_assert(ttisnil(key(t->node))); /* assert invariants: */
lua_assert(ttisnil(val(t->node)));
lua_assert(ttisnil(gkey(t->node))); /* assert invariants: */
lua_assert(ttisnil(gval(t->node)));
lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */
}
else {
t->node = luaM_newvector(L, size, Node);
for (i=0; i<size; i++) {
t->node[i].next = NULL;
setnilvalue(key(node(t, i)));
setnilvalue(val(node(t, i)));
setnilvalue(gkey(gnode(t, i)));
setnilvalue(gval(gnode(t, i)));
}
}
t->lsizenode = cast(lu_byte, lsize);
t->firstfree = node(t, size-1); /* first free position to be used */
t->firstfree = gnode(t, size-1); /* first free position to be used */
}
@@ -259,8 +281,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
lua_assert(t->node == G(L)->dummynode);
temp[0] = t->node[0]; /* copy it to `temp' */
nold = temp;
setnilvalue(key(G(L)->dummynode)); /* restate invariant */
setnilvalue(val(G(L)->dummynode));
setnilvalue(gkey(G(L)->dummynode)); /* restate invariant */
setnilvalue(gval(G(L)->dummynode));
lua_assert(G(L)->dummynode->next == NULL);
}
if (nasize > oldasize) /* array part must grow? */
@@ -273,7 +295,7 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
/* re-insert elements from vanishing slice */
for (i=nasize; i<oldasize; i++) {
if (!ttisnil(&t->array[i]))
setobj(luaH_setnum(L, t, i+1), &t->array[i]);
setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
}
/* shrink array */
luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
@@ -281,8 +303,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
/* re-insert elements in hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--) {
Node *old = nold+i;
if (!ttisnil(val(old)))
setobj(luaH_set(L, t, key(old)), val(old));
if (!ttisnil(gval(old)))
setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
}
if (oldhsize)
luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
@@ -304,12 +326,9 @@ static void rehash (lua_State *L, Table *t) {
Table *luaH_new (lua_State *L, int narray, int lnhash) {
Table *t = luaM_new(L, Table);
luaC_link(L, valtogco(t), LUA_TTABLE);
t->metatable = hvalue(defaultmeta(L));
t->next = G(L)->roottable;
G(L)->roottable = t;
t->mark = t;
t->flags = cast(lu_byte, ~0);
t->mode = 0;
/* temporary values (kept only if some malloc fails) */
t->array = NULL;
t->sizearray = 0;
@@ -335,7 +354,7 @@ void luaH_free (lua_State *L, Table *t) {
** (because gc can call `remove' during a table traversal)
*/
void luaH_remove (Table *t, Node *e) {
Node *mp = luaH_mainposition(t, key(e));
Node *mp = luaH_mainposition(t, gkey(e));
if (e != mp) { /* element not in its main position? */
while (mp->next != e) mp = mp->next; /* find previous */
mp->next = e->next; /* remove `e' from its list */
@@ -343,8 +362,8 @@ void luaH_remove (Table *t, Node *e) {
else {
if (e->next != NULL) ??
}
lua_assert(ttisnil(val(node)));
setnilvalue(key(e)); /* clear node `e' */
lua_assert(ttisnil(gval(node)));
setnilvalue(gkey(e)); /* clear node `e' */
e->next = NULL;
}
#endif
@@ -360,8 +379,8 @@ void luaH_remove (Table *t, Node *e) {
static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
TObject *val;
Node *mp = luaH_mainposition(t, key);
if (!ttisnil(val(mp))) { /* main position is not free? */
Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */
if (!ttisnil(gval(mp))) { /* main position is not free? */
Node *othern = luaH_mainposition(t, gkey(mp)); /* `mp' of colliding node */
Node *n = t->firstfree; /* get a free place */
if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */
@@ -369,7 +388,7 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
othern->next = n; /* redo the chain with `n' in place of `mp' */
*n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
mp->next = NULL; /* now `mp' is free */
setnilvalue(val(mp));
setnilvalue(gval(mp));
}
else { /* colliding node is in its own main position */
/* new node will go into free position */
@@ -378,16 +397,16 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
mp = n;
}
}
setobj(key(mp), key);
lua_assert(ttisnil(val(mp)));
setobj2t(gkey(mp), key); /* write barrier */
lua_assert(ttisnil(gval(mp)));
for (;;) { /* correct `firstfree' */
if (ttisnil(key(t->firstfree)))
return val(mp); /* OK; table still has a free place */
if (ttisnil(gkey(t->firstfree)))
return gval(mp); /* OK; table still has a free place */
else if (t->firstfree == t->node) break; /* cannot decrement from here */
else (t->firstfree)--;
}
/* no more free places; must create one */
setbvalue(val(mp), 0); /* avoid new key being removed */
setbvalue(gval(mp), 0); /* avoid new key being removed */
rehash(L, t); /* grow table */
val = cast(TObject *, luaH_get(t, key)); /* get new position */
lua_assert(ttisboolean(val));
@@ -404,7 +423,7 @@ static const TObject *luaH_getany (Table *t, const TObject *key) {
else {
Node *n = luaH_mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(key(n), key)) return val(n); /* that's it */
if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */
else n = n->next;
} while (n);
return &luaO_nilobject;
@@ -419,10 +438,11 @@ const TObject *luaH_getnum (Table *t, int key) {
if (1 <= key && key <= t->sizearray)
return &t->array[key-1];
else {
Node *n = hashnum(t, key);
lua_Number nk = cast(lua_Number, key);
Node *n = hashnum(t, nk);
do { /* check whether `key' is somewhere in the chain */
if (ttisnumber(key(n)) && nvalue(key(n)) == (lua_Number)key)
return val(n); /* that's it */
if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk)
return gval(n); /* that's it */
else n = n->next;
} while (n);
return &luaO_nilobject;
@@ -436,8 +456,8 @@ const TObject *luaH_getnum (Table *t, int key) {
const TObject *luaH_getstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
do { /* check whether `key' is somewhere in the chain */
if (ttisstring(key(n)) && tsvalue(key(n)) == key)
return val(n); /* that's it */
if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key)
return gval(n); /* that's it */
else n = n->next;
} while (n);
return &luaO_nilobject;
@@ -482,7 +502,7 @@ TObject *luaH_setnum (lua_State *L, Table *t, int key) {
return cast(TObject *, p);
else {
TObject k;
setnvalue(&k, key);
setnvalue(&k, cast(lua_Number, key));
return newkey(L, t, &k);
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltable.h,v 1.41 2002/03/11 12:45:00 roberto Exp roberto $
** $Id: ltable.h,v 1.43 2002/11/07 16:03:33 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -10,9 +10,9 @@
#include "lobject.h"
#define node(t,i) (&(t)->node[i])
#define key(n) (&(n)->i_key)
#define val(n) (&(n)->i_val)
#define gnode(t,i) (&(t)->node[i])
#define gkey(n) (&(n)->i_key)
#define gval(n) (&(n)->i_val)
const TObject *luaH_getnum (Table *t, int key);
@@ -22,7 +22,7 @@ const TObject *luaH_get (Table *t, const TObject *key);
TObject *luaH_set (lua_State *L, Table *t, const TObject *key);
Table *luaH_new (lua_State *L, int narray, int lnhash);
void luaH_free (lua_State *L, Table *t);
int luaH_next (lua_State *L, Table *t, TObject *key);
int luaH_next (lua_State *L, Table *t, StkId key);
/* exported only for debugging */
Node *luaH_mainposition (const Table *t, const TObject *key);

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltablib.c,v 1.11 2002/08/06 17:06:56 roberto Exp roberto $
** $Id: ltablib.c,v 1.20 2003/03/11 12:24:34 roberto Exp roberto $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@@ -7,67 +7,24 @@
#include <stddef.h>
#define ltablib_c
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int checkint (lua_State *L) {
int n = (int)lua_tonumber(L, -1);
if (n == 0 && !lua_isnumber(L, -1)) n = -1;
lua_pop(L, 1);
return n;
}
static void aux_setn (lua_State *L, int t, int n) {
lua_pushliteral(L, "n");
lua_rawget(L, t);
if (checkint(L) >= 0) {
lua_pushliteral(L, "n"); /* use it */
lua_pushnumber(L, n);
lua_rawset(L, t);
}
else { /* use N */
lua_pushvalue(L, t);
lua_pushnumber(L, n);
lua_rawset(L, lua_upvalueindex(1)); /* N[t] = n */
}
}
static int aux_getn (lua_State *L, int t) {
int n;
luaL_check_type(L, t, LUA_TTABLE);
lua_pushliteral(L, "n"); /* try t.n */
lua_rawget(L, t);
if ((n = checkint(L)) >= 0) return n;
lua_pushvalue(L, t); /* try N[t] */
lua_rawget(L, lua_upvalueindex(1));
if ((n = checkint(L)) >= 0) return n;
else { /* must count elements */
n = 0;
for (;;) {
lua_rawgeti(L, t, ++n);
if (lua_isnil(L, -1)) break;
lua_pop(L, 1);
}
lua_pop(L, 1);
aux_setn(L, t, n - 1);
return n - 1;
}
}
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
static int luaB_foreachi (lua_State *L) {
int i;
int n = aux_getn(L, 1);
luaL_check_type(L, 2, LUA_TFUNCTION);
luaL_checktype(L, 2, LUA_TFUNCTION);
for (i=1; i<=n; i++) {
lua_pushvalue(L, 2); /* function */
lua_pushnumber(L, i); /* 1st argument */
lua_pushnumber(L, (lua_Number)i); /* 1st argument */
lua_rawgeti(L, 1, i); /* 2nd argument */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
@@ -79,8 +36,8 @@ static int luaB_foreachi (lua_State *L) {
static int luaB_foreach (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
luaL_check_type(L, 2, LUA_TFUNCTION);
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_pushnil(L); /* first key */
for (;;) {
if (lua_next(L, 1) == 0)
@@ -97,14 +54,14 @@ static int luaB_foreach (lua_State *L) {
static int luaB_getn (lua_State *L) {
lua_pushnumber(L, aux_getn(L, 1));
lua_pushnumber(L, (lua_Number)aux_getn(L, 1));
return 1;
}
static int luaB_setn (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
aux_setn(L, 1, luaL_check_int(L, 2));
luaL_checktype(L, 1, LUA_TTABLE);
luaL_setn(L, 1, luaL_checkint(L, 2));
return 0;
}
@@ -116,11 +73,11 @@ static int luaB_tinsert (lua_State *L) {
if (v == 2) /* called with only 2 arguments */
pos = n; /* insert new element at the end */
else {
pos = luaL_check_int(L, 2); /* 2nd argument is the position */
pos = luaL_checkint(L, 2); /* 2nd argument is the position */
if (pos > n) n = pos; /* `grow' array if necessary */
v = 3; /* function may be called with more than 3 args */
}
aux_setn(L, 1, n); /* new size */
luaL_setn(L, 1, n); /* new size */
while (--n >= pos) { /* move up elements */
lua_rawgeti(L, 1, n);
lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
@@ -133,9 +90,9 @@ static int luaB_tinsert (lua_State *L) {
static int luaB_tremove (lua_State *L) {
int n = aux_getn(L, 1);
int pos = luaL_opt_int(L, 2, n);
int pos = luaL_optint(L, 2, n);
if (n <= 0) return 0; /* table is `empty' */
aux_setn(L, 1, n-1); /* t.n = n-1 */
luaL_setn(L, 1, n-1); /* t.n = n-1 */
lua_rawgeti(L, 1, pos); /* result = t[pos] */
for ( ;pos<n; pos++) {
lua_rawgeti(L, 1, pos+1);
@@ -149,15 +106,16 @@ static int luaB_tremove (lua_State *L) {
static int str_concat (lua_State *L) {
luaL_Buffer b;
int n = aux_getn(L, 1);
size_t lsep;
const char *sep = luaL_opt_lstr(L, 2, "", &lsep);
int i;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
int i = luaL_optint(L, 3, 1);
int n = luaL_optint(L, 4, 0);
luaL_checktype(L, 1, LUA_TTABLE);
if (n == 0) n = luaL_getn(L, 1);
luaL_buffinit(L, &b);
for (i=1; i<=n; i++) {
for (; i <= n; i++) {
lua_rawgeti(L, 1, i);
luaL_arg_check(L, lua_isstring(L, -1), 1,
"table contains non-strings");
luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
luaL_addvalue(&b);
if (i != n)
luaL_addlstring(&b, sep, lsep);
@@ -261,9 +219,9 @@ static void auxsort (lua_State *L, int l, int u) {
static int luaB_sort (lua_State *L) {
int n = aux_getn(L, 1);
luaL_check_stack(L, 40, ""); /* assume array is smaller than 2^40 */
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_check_type(L, 2, LUA_TFUNCTION);
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_settop(L, 2); /* make sure there is two arguments */
auxsort(L, 1, n);
return 0;
@@ -285,10 +243,8 @@ static const luaL_reg tab_funcs[] = {
};
LUALIB_API int lua_tablibopen (lua_State *L) {
lua_newtable(L); /* create N (table to store num. elements in tables) */
lua_setmode(L, -1, "k"); /* make it a weak table */
luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1);
return 0;
LUALIB_API int luaopen_table (lua_State *L) {
luaL_openlib(L, LUA_TABLIBNAME, tab_funcs, 0);
return 1;
}

368
ltests.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltests.c,v 1.132 2002/08/06 15:32:22 roberto Exp roberto $
** $Id: ltests.c,v 1.157 2003/04/03 13:35:34 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#define ltests_c
#include "lua.h"
@@ -35,17 +36,20 @@
#ifdef LUA_DEBUG
#define lua_pushintegral(L,i) lua_pushnumber(L, cast(lua_Number, (i)))
static lua_State *lua_state = NULL;
int islocked = 0;
#define index(L,k) (L->ci->base+(k) - 1)
#define func_at(L,k) (L->ci->base+(k) - 1)
static void setnameval (lua_State *L, const char *name, int val) {
lua_pushstring(L, name);
lua_pushnumber(L, val);
lua_pushintegral(L, val);
lua_settable(L, -3);
}
@@ -56,15 +60,25 @@ static void setnameval (lua_State *L, const char *name, int val) {
** =======================================================================
*/
/* ensures maximum alignment for HEADER */
#define HEADER (sizeof(union L_Umaxalign))
#define MARKSIZE 32
#define MARK 0x55 /* 01010101 (a nice pattern) */
#define blocksize(b) (cast(size_t *, b) - HEADER/sizeof(size_t))
#ifndef EXTERNMEMCHECK
/* full memory check */
#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
#define MARKSIZE 16 /* size of marks after each block */
#define blockhead(b) (cast(char *, b) - HEADER)
#define setsize(newblock, size) (*cast(size_t *, newblock) = size)
#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
#define fillmem(mem,size) memset(mem, -MARK, size)
#else
/* external memory check: don't do it twice */
#define HEADER 0
#define MARKSIZE 0
#define blockhead(b) (b)
#define setsize(newblock, size) /* empty */
#define checkblocksize(b,size) (1)
#define fillmem(mem,size) /* empty */
#endif
unsigned long memdebug_numblocks = 0;
unsigned long memdebug_total = 0;
@@ -72,9 +86,8 @@ unsigned long memdebug_maxmem = 0;
unsigned long memdebug_memlimit = ULONG_MAX;
static void *checkblock (void *block) {
size_t *b = blocksize(block);
size_t size = *b;
static void *checkblock (void *block, size_t size) {
void *b = blockhead(block);
int i;
for (i=0;i<MARKSIZE;i++)
lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
@@ -82,11 +95,11 @@ static void *checkblock (void *block) {
}
static void freeblock (void *block) {
static void freeblock (void *block, size_t size) {
if (block) {
size_t size = *blocksize(block);
block = checkblock(block);
memset(block, -1, size+HEADER+MARKSIZE); /* erase block */
lua_assert(checkblocksize(block, size));
block = checkblock(block, size);
fillmem(block, size+HEADER+MARKSIZE); /* erase block */
free(block); /* free original block */
memdebug_numblocks--;
memdebug_total -= size;
@@ -95,35 +108,34 @@ static void freeblock (void *block) {
void *debug_realloc (void *block, size_t oldsize, size_t size) {
lua_assert((oldsize == 0) == (block == NULL));
lua_assert(oldsize == 0 || oldsize == *blocksize(block));
lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
/* ISO does not specify what realloc(NULL, 0) does */
lua_assert(block != NULL || size > 0);
if (size == 0) {
freeblock(block);
freeblock(block, oldsize);
return NULL;
}
else if (memdebug_total+size-oldsize > memdebug_memlimit)
else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit)
return NULL; /* to test memory allocation errors */
else {
void *newblock;
int i;
size_t realsize = HEADER+size+MARKSIZE;
size_t commonsize = (oldsize < size) ? oldsize : size;
if (realsize < size) return NULL; /* overflow! */
newblock = malloc(realsize); /* alloc a new block */
if (newblock == NULL) return NULL;
if (oldsize > size) oldsize = size;
if (block) {
memcpy(cast(char *, newblock)+HEADER, block, oldsize);
freeblock(block); /* erase (and check) old copy */
memcpy(cast(char *, newblock)+HEADER, block, commonsize);
freeblock(block, oldsize); /* erase (and check) old copy */
}
/* initialize new part of the block with something `weird' */
memset(cast(char *, newblock)+HEADER+oldsize, -MARK, size-oldsize);
fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
memdebug_total += size;
if (memdebug_total > memdebug_maxmem)
memdebug_maxmem = memdebug_total;
memdebug_numblocks++;
*cast(size_t *, newblock) = size;
setsize(newblock, size);
for (i=0;i<MARKSIZE;i++)
*(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
return cast(char *, newblock)+HEADER;
@@ -179,15 +191,15 @@ void luaI_printcode (Proto *pt, int size) {
static int listcode (lua_State *L) {
int pc;
Proto *p;
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
p = clvalue(index(L, 1))->l.p;
p = clvalue(func_at(L, 1))->l.p;
lua_newtable(L);
setnameval(L, "maxstack", p->maxstacksize);
setnameval(L, "numparams", p->numparams);
for (pc=0; pc<p->sizecode; pc++) {
char buff[100];
lua_pushnumber(L, pc+1);
lua_pushintegral(L, pc+1);
lua_pushstring(L, buildop(p, pc, buff));
lua_settable(L, -3);
}
@@ -198,12 +210,12 @@ static int listcode (lua_State *L) {
static int listk (lua_State *L) {
Proto *p;
int i;
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
p = clvalue(index(L, 1))->l.p;
p = clvalue(func_at(L, 1))->l.p;
lua_newtable(L);
for (i=0; i<p->sizek; i++) {
lua_pushnumber(L, i+1);
lua_pushintegral(L, i+1);
luaA_pushobject(L, p->k+i);
lua_settable(L, -3);
}
@@ -213,12 +225,12 @@ static int listk (lua_State *L) {
static int listlocals (lua_State *L) {
Proto *p;
int pc = luaL_check_int(L, 2) - 1;
int pc = luaL_checkint(L, 2) - 1;
int i = 0;
const char *name;
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
p = clvalue(index(L, 1))->l.p;
p = clvalue(func_at(L, 1))->l.p;
while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
lua_pushstring(L, name);
return i-1;
@@ -243,13 +255,13 @@ static int get_limits (lua_State *L) {
static int mem_query (lua_State *L) {
if (lua_isnone(L, 1)) {
lua_pushnumber(L, memdebug_total);
lua_pushnumber(L, memdebug_numblocks);
lua_pushnumber(L, memdebug_maxmem);
lua_pushintegral(L, memdebug_total);
lua_pushintegral(L, memdebug_numblocks);
lua_pushintegral(L, memdebug_maxmem);
return 3;
}
else {
memdebug_memlimit = luaL_check_int(L, 1);
memdebug_memlimit = luaL_checkint(L, 1);
return 0;
}
}
@@ -257,15 +269,15 @@ static int mem_query (lua_State *L) {
static int hash_query (lua_State *L) {
if (lua_isnone(L, 2)) {
luaL_arg_check(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
lua_pushnumber(L, tsvalue(index(L, 1))->tsv.hash);
luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
lua_pushintegral(L, tsvalue(func_at(L, 1))->tsv.hash);
}
else {
TObject *o = index(L, 1);
TObject *o = func_at(L, 1);
Table *t;
luaL_check_type(L, 2, LUA_TTABLE);
t = hvalue(index(L, 2));
lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
luaL_checktype(L, 2, LUA_TTABLE);
t = hvalue(func_at(L, 2));
lua_pushintegral(L, luaH_mainposition(t, o) - t->node);
}
return 1;
}
@@ -273,41 +285,41 @@ static int hash_query (lua_State *L) {
static int stacklevel (lua_State *L) {
unsigned long a = 0;
lua_pushnumber(L, (int)(L->top - L->stack));
lua_pushnumber(L, (int)(L->stack_last - L->stack));
lua_pushnumber(L, (int)(L->ci - L->base_ci));
lua_pushnumber(L, (int)(L->end_ci - L->base_ci));
lua_pushnumber(L, (unsigned long)&a);
lua_pushintegral(L, (int)(L->top - L->stack));
lua_pushintegral(L, (int)(L->stack_last - L->stack));
lua_pushintegral(L, (int)(L->ci - L->base_ci));
lua_pushintegral(L, (int)(L->end_ci - L->base_ci));
lua_pushintegral(L, (unsigned long)&a);
return 5;
}
static int table_query (lua_State *L) {
const Table *t;
int i = luaL_opt_int(L, 2, -1);
luaL_check_type(L, 1, LUA_TTABLE);
t = hvalue(index(L, 1));
int i = luaL_optint(L, 2, -1);
luaL_checktype(L, 1, LUA_TTABLE);
t = hvalue(func_at(L, 1));
if (i == -1) {
lua_pushnumber(L, t->sizearray);
lua_pushnumber(L, sizenode(t));
lua_pushnumber(L, t->firstfree - t->node);
lua_pushintegral(L, t->sizearray);
lua_pushintegral(L, sizenode(t));
lua_pushintegral(L, t->firstfree - t->node);
}
else if (i < t->sizearray) {
lua_pushnumber(L, i);
lua_pushintegral(L, i);
luaA_pushobject(L, &t->array[i]);
lua_pushnil(L);
}
else if ((i -= t->sizearray) < sizenode(t)) {
if (!ttisnil(val(node(t, i))) ||
ttisnil(key(node(t, i))) ||
ttisnumber(key(node(t, i)))) {
luaA_pushobject(L, key(node(t, i)));
if (!ttisnil(gval(gnode(t, i))) ||
ttisnil(gkey(gnode(t, i))) ||
ttisnumber(gkey(gnode(t, i)))) {
luaA_pushobject(L, gkey(gnode(t, i)));
}
else
lua_pushstring(L, "<undef>");
luaA_pushobject(L, val(&t->node[i]));
luaA_pushobject(L, gval(gnode(t, i)));
if (t->node[i].next)
lua_pushnumber(L, t->node[i].next - t->node);
lua_pushintegral(L, t->node[i].next - t->node);
else
lua_pushnil(L);
}
@@ -317,17 +329,17 @@ static int table_query (lua_State *L) {
static int string_query (lua_State *L) {
stringtable *tb = &G(L)->strt;
int s = luaL_opt_int(L, 2, 0) - 1;
int s = luaL_optint(L, 2, 0) - 1;
if (s==-1) {
lua_pushnumber(L ,tb->nuse);
lua_pushnumber(L ,tb->size);
lua_pushintegral(L ,tb->nuse);
lua_pushintegral(L ,tb->size);
return 2;
}
else if (s < tb->size) {
TString *ts;
GCObject *ts;
int n = 0;
for (ts = tb->hash[s]; ts; ts = ts->tsv.nexthash) {
setsvalue(L->top, ts);
for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
setsvalue2s(L->top, gcotots(ts));
incr_top(L);
n++;
}
@@ -339,44 +351,62 @@ static int string_query (lua_State *L) {
static int tref (lua_State *L) {
int level = lua_gettop(L);
int lock = luaL_opt_int(L, 2, 1);
luaL_check_any(L, 1);
int lock = luaL_optint(L, 2, 1);
luaL_checkany(L, 1);
lua_pushvalue(L, 1);
lua_pushnumber(L, lua_ref(L, lock));
lua_pushintegral(L, lua_ref(L, lock));
assert(lua_gettop(L) == level+1); /* +1 for result */
return 1;
}
static int getref (lua_State *L) {
int level = lua_gettop(L);
lua_getref(L, luaL_check_int(L, 1));
lua_getref(L, luaL_checkint(L, 1));
assert(lua_gettop(L) == level+1);
return 1;
}
static int unref (lua_State *L) {
int level = lua_gettop(L);
lua_unref(L, luaL_check_int(L, 1));
lua_unref(L, luaL_checkint(L, 1));
assert(lua_gettop(L) == level);
return 0;
}
static int metatable (lua_State *L) {
luaL_check_any(L, 1);
luaL_checkany(L, 1);
if (lua_isnone(L, 2)) {
if (lua_getmetatable(L, 1) == 0)
lua_pushnil(L);
}
else {
lua_settop(L, 2);
luaL_check_type(L, 2, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE);
lua_setmetatable(L, 1);
}
return 1;
}
static int upvalue (lua_State *L) {
int n = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TFUNCTION);
if (lua_isnone(L, 3)) {
const char *name = lua_getupvalue(L, 1, n);
if (name == NULL) return 0;
lua_pushstring(L, name);
return 2;
}
else {
const char *name = lua_setupvalue(L, 1, n);
lua_pushstring(L, name);
return 1;
}
}
static int newuserdata (lua_State *L) {
size_t size = luaL_check_int(L, 1);
size_t size = luaL_checkint(L, 1);
char *p = cast(char *, lua_newuserdata(L, size));
while (size--) *p++ = '\0';
return 1;
@@ -384,13 +414,13 @@ static int newuserdata (lua_State *L) {
static int pushuserdata (lua_State *L) {
lua_pushlightuserdata(L, cast(void *, luaL_check_int(L, 1)));
lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
return 1;
}
static int udataval (lua_State *L) {
lua_pushnumber(L, cast(int, lua_touserdata(L, 1)));
lua_pushintegral(L, cast(int, lua_touserdata(L, 1)));
return 1;
}
@@ -398,23 +428,22 @@ static int udataval (lua_State *L) {
static int doonnewstack (lua_State *L) {
lua_State *L1 = lua_newthread(L);
size_t l;
const char *s = luaL_check_lstr(L, 1, &l);
const char *s = luaL_checklstring(L, 1, &l);
int status = luaL_loadbuffer(L1, s, l, s);
if (status == 0)
status = lua_pcall(L1, 0, 0, 0);
lua_pushnumber(L, status);
lua_closethread(L, L1);
lua_pushintegral(L, status);
return 1;
}
static int s2d (lua_State *L) {
lua_pushnumber(L, *cast(const double *, luaL_check_string(L, 1)));
lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
return 1;
}
static int d2s (lua_State *L) {
double d = luaL_check_number(L, 1);
double d = luaL_checknumber(L, 1);
lua_pushlstring(L, cast(char *, &d), sizeof(d));
return 1;
}
@@ -423,35 +452,43 @@ static int d2s (lua_State *L) {
static int newstate (lua_State *L) {
lua_State *L1 = lua_open();
if (L1) {
*cast(int **, L1) = &islocked; /* initialize the lock */
lua_pushnumber(L, (unsigned long)L1);
lua_userstateopen(L1); /* init lock */
lua_pushintegral(L, (unsigned long)L1);
}
else
lua_pushnil(L);
return 1;
}
static int loadlib (lua_State *L) {
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_check_number(L, 1)));
lua_register(L1, "mathlibopen", lua_mathlibopen);
lua_register(L1, "strlibopen", lua_strlibopen);
lua_register(L1, "iolibopen", lua_iolibopen);
lua_register(L1, "dblibopen", lua_dblibopen);
lua_register(L1, "baselibopen", lua_baselibopen);
static const luaL_reg libs[] = {
{"mathlibopen", luaopen_math},
{"strlibopen", luaopen_string},
{"iolibopen", luaopen_io},
{"tablibopen", luaopen_table},
{"dblibopen", luaopen_debug},
{"baselibopen", luaopen_base},
{NULL, NULL}
};
lua_State *L1 = cast(lua_State *,
cast(unsigned long, luaL_checknumber(L, 1)));
lua_pushvalue(L1, LUA_GLOBALSINDEX);
luaL_openlib(L1, NULL, libs, 0);
return 0;
}
static int closestate (lua_State *L) {
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_check_number(L, 1)));
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
lua_close(L1);
lua_unlock(L); /* close cannot unlock that */
return 0;
}
static int doremote (lua_State *L) {
lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_check_number(L, 1)));
lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
size_t lcode;
const char *code = luaL_check_lstr(L, 2, &lcode);
const char *code = luaL_checklstring(L, 2, &lcode);
int status;
lua_settop(L1, 0);
status = luaL_loadbuffer(L1, code, lcode, code);
@@ -459,8 +496,9 @@ static int doremote (lua_State *L) {
status = lua_pcall(L1, 0, LUA_MULTRET, 0);
if (status != 0) {
lua_pushnil(L);
lua_pushnumber(L, status);
return 2;
lua_pushintegral(L, status);
lua_pushstring(L, lua_tostring(L1, -1));
return 3;
}
else {
int i = 0;
@@ -473,10 +511,28 @@ static int doremote (lua_State *L) {
static int log2_aux (lua_State *L) {
lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1)));
lua_pushintegral(L, luaO_log2(luaL_checkint(L, 1)));
return 1;
}
static int int2fb_aux (lua_State *L) {
int b = luaO_int2fb(luaL_checkint(L, 1));
lua_pushintegral(L, b);
lua_pushintegral(L, fb2int(b));
return 2;
}
static int test_do (lua_State *L) {
const char *p = luaL_checkstring(L, 1);
if (*p == '@')
lua_dofile(L, p+1);
else
lua_dostring(L, p);
return lua_gettop(L);
}
/*
** {======================================================
@@ -527,36 +583,36 @@ static const char *getname_aux (char *buff, const char **pc) {
static int testC (lua_State *L) {
char buff[30];
const char *pc = luaL_check_string(L, 1);
const char *pc = luaL_checkstring(L, 1);
for (;;) {
const char *inst = getname;
if EQ("") return 0;
else if EQ("isnumber") {
lua_pushnumber(L, lua_isnumber(L, getnum));
lua_pushintegral(L, lua_isnumber(L, getnum));
}
else if EQ("isstring") {
lua_pushnumber(L, lua_isstring(L, getnum));
lua_pushintegral(L, lua_isstring(L, getnum));
}
else if EQ("istable") {
lua_pushnumber(L, lua_istable(L, getnum));
lua_pushintegral(L, lua_istable(L, getnum));
}
else if EQ("iscfunction") {
lua_pushnumber(L, lua_iscfunction(L, getnum));
lua_pushintegral(L, lua_iscfunction(L, getnum));
}
else if EQ("isfunction") {
lua_pushnumber(L, lua_isfunction(L, getnum));
lua_pushintegral(L, lua_isfunction(L, getnum));
}
else if EQ("isuserdata") {
lua_pushnumber(L, lua_isuserdata(L, getnum));
lua_pushintegral(L, lua_isuserdata(L, getnum));
}
else if EQ("isudataval") {
lua_pushnumber(L, lua_islightuserdata(L, getnum));
lua_pushintegral(L, lua_islightuserdata(L, getnum));
}
else if EQ("isnil") {
lua_pushnumber(L, lua_isnil(L, getnum));
lua_pushintegral(L, lua_isnil(L, getnum));
}
else if EQ("isnull") {
lua_pushnumber(L, lua_isnone(L, getnum));
lua_pushintegral(L, lua_isnone(L, getnum));
}
else if EQ("tonumber") {
lua_pushnumber(L, lua_tonumber(L, getnum));
@@ -565,11 +621,8 @@ static int testC (lua_State *L) {
const char *s = lua_tostring(L, getnum);
lua_pushstring(L, s);
}
else if EQ("tonumber") {
lua_pushnumber(L, lua_tonumber(L, getnum));
}
else if EQ("strlen") {
lua_pushnumber(L, lua_strlen(L, getnum));
lua_pushintegral(L, lua_strlen(L, getnum));
}
else if EQ("tocfunction") {
lua_pushcfunction(L, lua_tocfunction(L, getnum));
@@ -578,7 +631,7 @@ static int testC (lua_State *L) {
return getnum;
}
else if EQ("gettop") {
lua_pushnumber(L, lua_gettop(L));
lua_pushintegral(L, lua_gettop(L));
}
else if EQ("settop") {
lua_settop(L, getnum);
@@ -587,7 +640,7 @@ static int testC (lua_State *L) {
lua_pop(L, getnum);
}
else if EQ("pushnum") {
lua_pushnumber(L, getnum);
lua_pushintegral(L, getnum);
}
else if EQ("pushnil") {
lua_pushnil(L);
@@ -596,7 +649,7 @@ static int testC (lua_State *L) {
lua_pushboolean(L, getnum);
}
else if EQ("tobool") {
lua_pushnumber(L, lua_toboolean(L, getnum));
lua_pushintegral(L, lua_toboolean(L, getnum));
}
else if EQ("pushvalue") {
lua_pushvalue(L, getnum);
@@ -648,11 +701,11 @@ static int testC (lua_State *L) {
}
else if EQ("loadstring") {
size_t sl;
const char *s = luaL_check_lstr(L, getnum, &sl);
const char *s = luaL_checklstring(L, getnum, &sl);
luaL_loadbuffer(L, s, sl, s);
}
else if EQ("loadfile") {
luaL_loadfile(L, luaL_check_string(L, getnum));
luaL_loadfile(L, luaL_checkstring(L, getnum));
}
else if EQ("setmetatable") {
lua_setmetatable(L, getnum);
@@ -664,6 +717,16 @@ static int testC (lua_State *L) {
else if EQ("type") {
lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
}
else if EQ("getn") {
int i = getnum;
lua_pushintegral(L, luaL_getn(L, i));
}
else if EQ("setn") {
int i = getnum;
int n = cast(int, lua_tonumber(L, -1));
luaL_setn(L, i, n);
lua_pop(L, 1);
}
else luaL_error(L, "unknown instruction %s", buff);
}
return 0;
@@ -672,6 +735,50 @@ static int testC (lua_State *L) {
/* }====================================================== */
/*
** {======================================================
** tests for yield inside hooks
** =======================================================
*/
static void yieldf (lua_State *L, lua_Debug *ar) {
lua_yield(L, 0);
}
static int setyhook (lua_State *L) {
if (lua_isnoneornil(L, 1))
lua_sethook(L, NULL, 0, 0); /* turn off hooks */
else {
const char *smask = luaL_checkstring(L, 1);
int count = luaL_optint(L, 2, 0);
int mask = 0;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
if (count > 0) mask |= LUA_MASKCOUNT;
lua_sethook(L, yieldf, mask, count);
}
return 0;
}
static int coresume (lua_State *L) {
int status;
lua_State *co = lua_tothread(L, 1);
luaL_argcheck(L, co, 1, "coroutine expected");
status = lua_resume(co, 0);
if (status != 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
return 1;
}
}
/* }====================================================== */
static const struct luaL_reg tests_funcs[] = {
{"hash", hash_query},
@@ -683,6 +790,7 @@ static const struct luaL_reg tests_funcs[] = {
{"stacklevel", stacklevel},
{"querystr", string_query},
{"querytab", table_query},
{"doit", test_do},
{"testC", testC},
{"ref", tref},
{"getref", getref},
@@ -690,6 +798,7 @@ static const struct luaL_reg tests_funcs[] = {
{"d2s", d2s},
{"s2d", s2d},
{"metatable", metatable},
{"upvalue", upvalue},
{"newuserdata", newuserdata},
{"pushuserdata", pushuserdata},
{"udataval", udataval},
@@ -698,7 +807,10 @@ static const struct luaL_reg tests_funcs[] = {
{"closestate", closestate},
{"doremote", doremote},
{"log2", log2_aux},
{"int2fb", int2fb_aux},
{"totalmem", mem_query},
{"resume", coresume},
{"setyhook", setyhook},
{NULL, NULL}
};
@@ -711,12 +823,30 @@ static void fim (void) {
}
static int l_panic (lua_State *L) {
UNUSED(L);
fprintf(stderr, "unable to recover; exiting\n");
return 0;
}
int luaB_opentests (lua_State *L) {
*cast(int **, L) = &islocked; /* init lock */
lua_atpanic(L, l_panic);
lua_userstateopen(L); /* init lock */
lua_state = L; /* keep first state to be opened */
luaL_opennamedlib(L, "T", tests_funcs, 0);
luaL_openlib(L, "T", tests_funcs, 0);
atexit(fim);
return 0;
}
#undef main
int main (int argc, char *argv[]) {
char *limit = getenv("MEMLIMIT");
if (limit)
memdebug_memlimit = strtoul(limit, NULL, 10);
l_main(argc, argv);
return 0;
}
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltests.h,v 1.14 2002/06/13 13:45:31 roberto Exp roberto $
** $Id: ltests.h,v 1.19 2002/11/19 17:42:32 roberto Exp roberto $
** Internal Header for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -34,6 +34,7 @@ extern unsigned long memdebug_memlimit;
#define l_realloc(b, os, s) debug_realloc(b, os, s)
#define l_free(b, os) debug_realloc(b, os, 0)
void *debug_realloc (void *block, size_t oldsize, size_t size);
@@ -41,15 +42,21 @@ void *debug_realloc (void *block, size_t oldsize, size_t size);
/* test for lock/unlock */
extern int islocked;
#define LUA_USERSTATE int *lock;
#define lua_userstateopen(l) if (l != NULL) *cast(int **, l) = &islocked;
#define lua_lock(L) lua_assert((**cast(int **, L))++ == 0)
#define lua_unlock(L) lua_assert(--(**cast(int **, L)) == 0)
#define LUA_USERSTATE int *
#define getlock(l) (*(cast(LUA_USERSTATE *, l) - 1))
#define lua_userstateopen(l) if (l != NULL) getlock(l) = &islocked;
#define lua_lock(l) lua_assert((*getlock(l))++ == 0)
#define lua_unlock(l) lua_assert(--(*getlock(l)) == 0)
int luaB_opentests (lua_State *L);
#define lua_userinit(L) (luaB_opentests(L) + openstdlibs(L))
#define LUA_EXTRALIBS { "tests", luaB_opentests },
/* real main will be defined at `ltests.c' */
int l_main (int argc, char *argv[]);
#define main l_main

13
ltm.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltm.c,v 1.99 2002/08/05 14:09:06 roberto Exp roberto $
** $Id: ltm.c,v 1.105 2002/12/04 17:38:31 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,8 @@
#include <string.h>
#define ltm_c
#include "lua.h"
#include "lobject.h"
@@ -18,16 +20,15 @@
const char *const luaT_typenames[] = {
"nil", "number", "string", "boolean", "table",
"function", "userdata", "userdata"
"nil", "boolean", "userdata", "number",
"string", "table", "function", "userdata", "thread"
};
void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex",
"__gc", "__eq",
"__gettable", "__settable",
"__gc", "__mode", "__eq",
"__add", "__sub", "__mul", "__div",
"__pow", "__unm", "__lt", "__le",
"__concat", "__call"
@@ -48,7 +49,7 @@ const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
const TObject *tm = luaH_getstr(events, ename);
lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= (1u<<event); /* cache this fact */
events->flags |= cast(lu_byte, 1u<<event); /* cache this fact */
return NULL;
}
else return tm;

11
ltm.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltm.h,v 1.38 2002/07/01 17:06:58 roberto Exp roberto $
** $Id: ltm.h,v 1.40 2002/09/19 20:12:47 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -19,9 +19,8 @@ typedef enum {
TM_INDEX,
TM_NEWINDEX,
TM_GC,
TM_MODE,
TM_EQ, /* last tag method with `fast' access */
TM_GETTABLE,
TM_SETTABLE,
TM_ADD,
TM_SUB,
TM_MUL,
@@ -37,8 +36,10 @@ typedef enum {
#define fasttm(l,et,e) \
(((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, G(l)->tmname[e]))
#define gfasttm(g,et,e) \
(((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
#define fasttm(l,et,e) gfasttm(G(l), et, e)
const TObject *luaT_gettm (Table *events, TMS event, TString *ename);

199
lua.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.c,v 1.102 2002/08/12 17:23:12 roberto Exp roberto $
** $Id: lua.c,v 1.121 2003/03/24 12:40:01 roberto Exp roberto $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <string.h>
#define lua_c
#include "lua.h"
#include "lauxlib.h"
@@ -24,10 +26,14 @@
#endif
#ifdef _POSIX_SOURCE
/*
** definition of `isatty'
*/
#ifdef _POSIX_C_SOURCE
#include <unistd.h>
#define stdin_is_tty() isatty(0)
#else
static int isatty (int x) { return x==0; } /* assume stdin is a tty */
#define stdin_is_tty() 1 /* assume stdin is a tty */
#endif
@@ -41,24 +47,44 @@ static int isatty (int x) { return x==0; } /* assume stdin is a tty */
#define PROMPT2 ">> "
#endif
#ifndef PROGNAME
#define PROGNAME "lua"
#endif
#ifndef lua_userinit
#define lua_userinit(L) openstdlibs(L)
#endif
#ifndef LUA_EXTRALIBS
#define LUA_EXTRALIBS /* empty */
#endif
static lua_State *L = NULL;
static const char *progname;
static const char *progname = PROGNAME;
static lua_Hook old_hook = NULL;
static unsigned long old_mask = 0;
static const luaL_reg lualibs[] = {
{"base", luaopen_base},
{"table", luaopen_table},
{"io", luaopen_io},
{"string", luaopen_string},
{"math", luaopen_math},
{"debug", luaopen_debug},
{"loadlib", luaopen_loadlib},
/* add your libraries here */
LUA_EXTRALIBS
{NULL, NULL}
};
static void lstop (lua_State *l, lua_Debug *ar) {
(void)ar; /* unused arg. */
lua_sethook(l, old_hook, old_mask);
lua_sethook(l, NULL, 0, 0);
luaL_error(l, "interrupted!");
}
@@ -66,36 +92,31 @@ static void lstop (lua_State *l, lua_Debug *ar) {
static void laction (int i) {
signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
terminate process (default action) */
old_hook = lua_gethook(L);
old_mask = lua_gethookmask(L);
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT(1));
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
static void print_usage (void) {
fprintf(stderr,
"usage: %s [options] [prog [args]].\n"
"usage: %s [options] [script [args]].\n"
"Available options are:\n"
" - execute stdin as a file\n"
" -e stat execute string `stat'\n"
" -i enter interactive mode after executing `prog'\n"
" -l name execute file `name'\n"
" -v print version information\n"
" -i enter interactive mode after executing `script'\n"
" -l name load and run library `name'\n"
" -v show version information\n"
" -- stop handling options\n" ,
progname);
}
static void l_message (const char *pname, const char *msg) {
size_t l = strlen(msg);
if (pname) fprintf(stderr, "%s: ", pname);
fprintf(stderr, "%s", msg);
if (l > 0 && msg[l-1] != '\n') /* does not end with newline? */
fprintf(stderr, "\n"); /* add a newline */
fprintf(stderr, "%s\n", msg);
}
static void report (int status) {
static int report (int status) {
const char *msg;
if (status) {
msg = lua_tostring(L, -1);
@@ -103,28 +124,21 @@ static void report (int status) {
l_message(progname, msg);
lua_pop(L, 1);
}
}
static int lcall (int clear) {
int status;
int top = lua_gettop(L);
lua_getglobal(L, "_TRACEBACK"); /* get traceback function */
lua_insert(L, top); /* put it under chunk */
signal(SIGINT, laction);
status = lua_pcall(L, 0, LUA_MULTRET, -2);
signal(SIGINT, SIG_DFL);
lua_remove(L, top); /* remove traceback function */
if (status == 0 && clear)
lua_settop(L, top); /* remove eventual results */
return status;
}
static int l_panic (lua_State *l) {
(void)l;
l_message(progname, "unable to recover; exiting");
return 0;
static int lcall (int narg, int clear) {
int status;
int base = lua_gettop(L) - narg; /* function index */
lua_pushliteral(L, "_TRACEBACK");
lua_rawget(L, LUA_GLOBALSINDEX); /* get traceback function */
lua_insert(L, base); /* put it under chunk and args */
signal(SIGINT, laction);
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
signal(SIGINT, SIG_DFL);
lua_remove(L, base); /* remove traceback function */
return status;
}
@@ -149,9 +163,8 @@ static void getargs (char *argv[], int n) {
static int docall (int status) {
if (status == 0) status = lcall(1);
report(status);
return status;
if (status == 0) status = lcall(0, 1);
return report(status);
}
@@ -165,6 +178,20 @@ static int dostring (const char *s, const char *name) {
}
static int load_file (const char *name) {
lua_pushliteral(L, "require");
lua_rawget(L, LUA_GLOBALSINDEX);
if (!lua_isfunction(L, -1)) { /* no `require' defined? */
lua_pop(L, 1);
return file_input(name);
}
else {
lua_pushstring(L, name);
return report(lcall(1, 1));
}
}
/*
** this macro can be used by some `history' system to save lines
** read in manual input
@@ -206,7 +233,8 @@ static int readline (lua_State *l, const char *prompt) {
static const char *get_prompt (int firstline) {
const char *p = NULL;
lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2");
lua_rawget(L, LUA_GLOBALSINDEX);
p = lua_tostring(L, -1);
if (p == NULL) p = (firstline ? PROMPT : PROMPT2);
lua_pop(L, 1); /* remove global */
@@ -252,13 +280,14 @@ static void manual_input (void) {
const char *oldprogname = progname;
progname = NULL;
while ((status = load_string()) != -1) {
if (status == 0) status = lcall(0);
if (status == 0) status = lcall(0, 0);
report(status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
l_message(progname, "error calling `print'");
l_message(progname, lua_pushfstring(L, "error calling `print' (%s)",
lua_tostring(L, -1)));
}
}
lua_settop(L, 0); /* clear stack */
@@ -269,7 +298,7 @@ static void manual_input (void) {
static int handle_argv (char *argv[], int *interactive) {
if (argv[1] == NULL) { /* no more arguments? */
if (isatty(0)) {
if (stdin_is_tty()) {
print_version();
manual_input();
}
@@ -282,6 +311,10 @@ static int handle_argv (char *argv[], int *interactive) {
if (argv[i][0] != '-') break; /* not an option? */
switch (argv[i][1]) { /* option */
case '-': { /* `--' */
if (argv[i][2] != '\0') {
print_usage();
return 1;
}
i++; /* skip this argument */
goto endloop; /* stop handling arguments */
}
@@ -302,10 +335,10 @@ static int handle_argv (char *argv[], int *interactive) {
if (*chunk == '\0') chunk = argv[++i];
if (chunk == NULL) {
print_usage();
return EXIT_FAILURE;
return 1;
}
if (dostring(chunk, "=<command line>") != 0)
return EXIT_FAILURE;
return 1;
break;
}
case 'l': {
@@ -313,10 +346,10 @@ static int handle_argv (char *argv[], int *interactive) {
if (*filename == '\0') filename = argv[++i];
if (filename == NULL) {
print_usage();
return EXIT_FAILURE;
return 1;
}
if (file_input(filename))
return EXIT_FAILURE; /* stop if file fails */
if (load_file(filename))
return 1; /* stop if file fails */
break;
}
case 'c': {
@@ -329,31 +362,27 @@ static int handle_argv (char *argv[], int *interactive) {
}
default: {
print_usage();
return EXIT_FAILURE;
return 1;
}
}
} endloop:
if (argv[i] != NULL) {
const char *filename = argv[i];
getargs(argv, i); /* collect remaining arguments */
getargs(argv, i); /* collect arguments */
lua_setglobal(L, "arg");
return file_input(filename); /* stop scanning arguments */
}
}
return EXIT_SUCCESS;
return 0;
}
static int openstdlibs (lua_State *l) {
int res = 0;
res += lua_baselibopen(l);
res += lua_tablibopen(l);
res += lua_iolibopen(l);
res += lua_strlibopen(l);
res += lua_mathlibopen(l);
res += lua_dblibopen(l);
/* add your libraries here */
return res;
static void openstdlibs (lua_State *l) {
const luaL_reg *lib = lualibs;
for (; lib->func; lib++) {
lib->func(l); /* open library */
lua_settop(l, 0); /* discard any results */
}
}
@@ -367,19 +396,43 @@ static int handle_luainit (void) {
}
int main (int argc, char *argv[]) {
struct Smain {
int argc;
char **argv;
int status;
};
static int pmain (lua_State *l) {
struct Smain *s = (struct Smain *)lua_touserdata(l, 1);
int status;
int interactive = 0;
(void)argc; /* to avoid warnings */
progname = argv[0];
L = lua_open(); /* create state */
lua_atpanic(L, l_panic);
lua_pop(L, lua_userinit(L)); /* open libraries, discard any results */
if (s->argv[0] && s->argv[0][0]) progname = s->argv[0];
L = l;
lua_userinit(l); /* open libraries */
status = handle_luainit();
if (status != 0) return status;
status = handle_argv(argv, &interactive);
if (status == 0 && interactive) manual_input();
lua_close(L);
return status;
if (status == 0) {
status = handle_argv(s->argv, &interactive);
if (status == 0 && interactive) manual_input();
}
s->status = status;
return 0;
}
int main (int argc, char *argv[]) {
int status;
struct Smain s;
lua_State *l = lua_open(); /* create state */
if (l == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
s.argc = argc;
s.argv = argv;
status = lua_cpcall(l, &pmain, &s);
report(status);
lua_close(l);
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}

171
lua.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.153 2002/08/06 18:54:18 roberto Exp roberto $
** $Id: lua.h,v 1.174 2003/02/27 11:52:30 roberto Exp roberto $
** Lua - An Extensible Extension Language
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
** http://www.lua.org mailto:info@lua.org
@@ -10,18 +10,13 @@
#ifndef lua_h
#define lua_h
/* definition of `va_list' */
#include <stdarg.h>
/* definition of `size_t' */
#include <stddef.h>
#define LUA_VERSION "Lua 5.0 (alpha)"
#define LUA_COPYRIGHT "Copyright (C) 1994-2002 Tecgraf, PUC-Rio"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo"
#define LUA_VERSION "Lua 5.0"
#define LUA_COPYRIGHT "Copyright (C) 1994-2003 Tecgraf, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
@@ -43,7 +38,6 @@
#define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4
#define LUA_ERRERR 5
#define LUA_ERRTHROW 6
typedef struct lua_State lua_State;
@@ -52,9 +46,12 @@ typedef int (*lua_CFunction) (lua_State *L);
/*
** functions that read blocks when loading Lua chunk
** functions that read/write blocks when loading/dumping Lua chunks
*/
typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz);
typedef int (*lua_Chunkwriter) (lua_State *L, const void* p,
size_t sz, void* ud);
/*
@@ -63,13 +60,14 @@ typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TNUMBER 1
#define LUA_TSTRING 2
#define LUA_TBOOLEAN 3
#define LUA_TTABLE 4
#define LUA_TFUNCTION 5
#define LUA_TUSERDATA 6
#define LUA_TLIGHTUSERDATA 7
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
/* minimum Lua stack available to a C function */
@@ -84,11 +82,12 @@ typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
#endif
/* type of Numbers in Lua */
/* type of numbers in Lua */
#ifndef LUA_NUMBER
#define LUA_NUMBER double
#endif
typedef double lua_Number;
#else
typedef LUA_NUMBER lua_Number;
#endif
/* mark for all API functions */
@@ -103,7 +102,6 @@ typedef LUA_NUMBER lua_Number;
LUA_API lua_State *lua_open (void);
LUA_API void lua_close (lua_State *L);
LUA_API lua_State *lua_newthread (lua_State *L);
LUA_API void lua_closethread (lua_State *L, lua_State *thread);
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
@@ -112,35 +110,39 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
** basic stack manipulation
*/
LUA_API int lua_gettop (lua_State *L);
LUA_API void lua_settop (lua_State *L, int index);
LUA_API void lua_pushvalue (lua_State *L, int index);
LUA_API void lua_remove (lua_State *L, int index);
LUA_API void lua_insert (lua_State *L, int index);
LUA_API void lua_replace (lua_State *L, int index);
LUA_API int lua_checkstack (lua_State *L, int size);
LUA_API void lua_settop (lua_State *L, int idx);
LUA_API void lua_pushvalue (lua_State *L, int idx);
LUA_API void lua_remove (lua_State *L, int idx);
LUA_API void lua_insert (lua_State *L, int idx);
LUA_API void lua_replace (lua_State *L, int idx);
LUA_API int lua_checkstack (lua_State *L, int sz);
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n);
/*
** access functions (stack -> C)
*/
LUA_API int lua_isnumber (lua_State *L, int index);
LUA_API int lua_isstring (lua_State *L, int index);
LUA_API int lua_iscfunction (lua_State *L, int index);
LUA_API int lua_type (lua_State *L, int index);
LUA_API const char *lua_typename (lua_State *L, int type);
LUA_API int lua_isnumber (lua_State *L, int idx);
LUA_API int lua_isstring (lua_State *L, int idx);
LUA_API int lua_iscfunction (lua_State *L, int idx);
LUA_API int lua_isuserdata (lua_State *L, int idx);
LUA_API int lua_type (lua_State *L, int idx);
LUA_API const char *lua_typename (lua_State *L, int tp);
LUA_API int lua_equal (lua_State *L, int index1, int index2);
LUA_API int lua_rawequal (lua_State *L, int index1, int index2);
LUA_API int lua_lessthan (lua_State *L, int index1, int index2);
LUA_API int lua_equal (lua_State *L, int idx1, int idx2);
LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2);
LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2);
LUA_API lua_Number lua_tonumber (lua_State *L, int index);
LUA_API int lua_toboolean (lua_State *L, int index);
LUA_API const char *lua_tostring (lua_State *L, int index);
LUA_API size_t lua_strlen (lua_State *L, int index);
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index);
LUA_API void *lua_touserdata (lua_State *L, int index);
LUA_API const void *lua_topointer (lua_State *L, int index);
LUA_API lua_Number lua_tonumber (lua_State *L, int idx);
LUA_API int lua_toboolean (lua_State *L, int idx);
LUA_API const char *lua_tostring (lua_State *L, int idx);
LUA_API size_t lua_strlen (lua_State *L, int idx);
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx);
LUA_API void *lua_touserdata (lua_State *L, int idx);
LUA_API lua_State *lua_tothread (lua_State *L, int idx);
LUA_API const void *lua_topointer (lua_State *L, int idx);
/*
@@ -148,7 +150,7 @@ LUA_API const void *lua_topointer (lua_State *L, int index);
*/
LUA_API void lua_pushnil (lua_State *L);
LUA_API void lua_pushnumber (lua_State *L, lua_Number n);
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len);
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t l);
LUA_API void lua_pushstring (lua_State *L, const char *s);
LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
@@ -161,24 +163,23 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p);
/*
** get functions (Lua -> stack)
*/
LUA_API void lua_gettable (lua_State *L, int index);
LUA_API void lua_rawget (lua_State *L, int index);
LUA_API void lua_rawgeti (lua_State *L, int index, int n);
LUA_API void lua_gettable (lua_State *L, int idx);
LUA_API void lua_rawget (lua_State *L, int idx);
LUA_API void lua_rawgeti (lua_State *L, int idx, int n);
LUA_API void lua_newtable (lua_State *L);
LUA_API void *lua_newuserdata (lua_State *L, size_t sz);
LUA_API int lua_getmetatable (lua_State *L, int objindex);
LUA_API const char *lua_getmode (lua_State *L, int index);
LUA_API void lua_getglobals (lua_State *L, int index);
LUA_API void lua_getfenv (lua_State *L, int idx);
/*
** set functions (stack -> Lua)
*/
LUA_API void lua_settable (lua_State *L, int index);
LUA_API void lua_rawset (lua_State *L, int index);
LUA_API void lua_rawseti (lua_State *L, int index, int n);
LUA_API void lua_setmode (lua_State *L, int index, const char *mode);
LUA_API void lua_settable (lua_State *L, int idx);
LUA_API void lua_rawset (lua_State *L, int idx);
LUA_API void lua_rawseti (lua_State *L, int idx, int n);
LUA_API int lua_setmetatable (lua_State *L, int objindex);
LUA_API int lua_setglobals (lua_State *L, int index);
LUA_API int lua_setfenv (lua_State *L, int idx);
/*
@@ -186,19 +187,21 @@ LUA_API int lua_setglobals (lua_State *L, int index);
*/
LUA_API void lua_call (lua_State *L, int nargs, int nresults);
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt,
const char *chunkname);
LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data);
/*
** coroutine functions
*/
LUA_API void lua_cobegin (lua_State *L, int nargs);
LUA_API int lua_yield (lua_State *L, int nresults);
LUA_API int lua_resume (lua_State *L, lua_State *co);
LUA_API int lua_resume (lua_State *L, int narg);
/*
** Garbage-collection functions
** garbage-collection functions
*/
LUA_API int lua_getgcthreshold (lua_State *L);
LUA_API int lua_getgccount (lua_State *L);
@@ -208,14 +211,14 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold);
** miscellaneous functions
*/
LUA_API const char *lua_version (void);
LUA_API int lua_error (lua_State *L);
LUA_API int lua_next (lua_State *L, int index);
LUA_API int lua_next (lua_State *L, int idx);
LUA_API void lua_concat (lua_State *L, int n);
LUA_API void *lua_newuserdata (lua_State *L, size_t size);
/*
@@ -240,7 +243,6 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size);
#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE)
#define lua_isuserdata(L,n) (lua_type(L,n) >= LUA_TUSERDATA)
#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN)
@@ -266,8 +268,6 @@ LUA_API int lua_pushupvalues (lua_State *L);
#define lua_getglobal(L,s) \
(lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX))
#define lua_isnull lua_isnone
/* compatibility with ref system */
@@ -296,7 +296,7 @@ LUA_API int lua_pushupvalues (lua_State *L);
#endif
#ifndef LUA_NUMBER_FMT
#define LUA_NUMBER_FMT "%.16g"
#define LUA_NUMBER_FMT "%.14g"
#endif
/* }====================================================================== */
@@ -308,18 +308,24 @@ LUA_API int lua_pushupvalues (lua_State *L);
** =======================================================================
*/
typedef enum lua_Hookevent {
LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKLINE, LUA_HOOKCOUNT
} lua_Hookevent;
/*
** Event codes
*/
#define LUA_HOOKCALL 0
#define LUA_HOOKRET 1
#define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILRET 4
#define LUA_MASKCALL (2 << LUA_HOOKCALL)
#define LUA_MASKRET (2 << LUA_HOOKRET)
#define LUA_MASKLINE (2 << LUA_HOOKLINE)
#define LUA_MASKCOUNT(count) ((unsigned long)(count) << 8)
#define lua_getmaskcount(mask) ((mask) >> 8)
#define LUA_MAXCOUNT ((1<<24) - 1)
/*
** Event masks
*/
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
#define LUA_MASKRET (1 << LUA_HOOKRET)
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
typedef struct lua_Debug lua_Debug; /* activation record */
@@ -330,19 +336,22 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask);
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook lua_gethook (lua_State *L);
LUA_API unsigned long lua_gethookmask (lua_State *L);
LUA_API int lua_gethookmask (lua_State *L);
LUA_API int lua_gethookcount (lua_State *L);
#define LUA_IDSIZE 60
struct lua_Debug {
lua_Hookevent event;
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) `global', `local', `field', `method' */
const char *what; /* (S) `Lua' function, `C' function, Lua `main' */
const char *what; /* (S) `Lua', `C', `main', `tail' */
const char *source; /* (S) */
int currentline; /* (l) */
int nups; /* (u) number of upvalues */
@@ -356,7 +365,7 @@ struct lua_Debug {
/******************************************************************************
* Copyright (C) 2002 Tecgraf, PUC-Rio. All rights reserved.
* Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

View File

@@ -1,5 +1,5 @@
/*
** $Id: lualib.h,v 1.24 2002/06/18 17:42:52 roberto Exp roberto $
** $Id: lualib.h,v 1.27 2003/03/17 13:04:58 roberto Exp roberto $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
@@ -12,28 +12,31 @@
#ifndef LUALIB_API
#define LUALIB_API extern
#define LUALIB_API LUA_API
#endif
#define LUA_COLIBNAME "coroutine"
LUALIB_API int lua_baselibopen (lua_State *L);
LUALIB_API int luaopen_base (lua_State *L);
#define LUA_TABLIBNAME "table"
LUALIB_API int lua_tablibopen (lua_State *L);
LUALIB_API int luaopen_table (lua_State *L);
#define LUA_IOLIBNAME "io"
#define LUA_OSLIBNAME "os"
LUALIB_API int lua_iolibopen (lua_State *L);
LUALIB_API int luaopen_io (lua_State *L);
#define LUA_STRLIBNAME "string"
LUALIB_API int lua_strlibopen (lua_State *L);
LUALIB_API int luaopen_string (lua_State *L);
#define LUA_MATHLIBNAME "math"
LUALIB_API int lua_mathlibopen (lua_State *L);
LUALIB_API int luaopen_math (lua_State *L);
#define LUA_DBLIBNAME "debug"
LUALIB_API int lua_dblibopen (lua_State *L);
LUALIB_API int luaopen_debug (lua_State *L);
LUALIB_API int luaopen_loadlib (lua_State *L);
/* to help testing the libraries */
@@ -41,4 +44,13 @@ LUALIB_API int lua_dblibopen (lua_State *L);
#define lua_assert(c) /* empty */
#endif
/* compatibility code */
#define lua_baselibopen luaopen_base
#define lua_tablibopen luaopen_table
#define lua_iolibopen luaopen_io
#define lua_strlibopen luaopen_string
#define lua_mathlibopen luaopen_math
#define lua_dblibopen luaopen_debug
#endif

View File

@@ -1,9 +1,11 @@
/*
** $Id: lundump.c,v 1.43 2002/08/07 00:36:03 lhf Exp $
** $Id: lundump.c,v 1.49 2003/04/07 20:34:20 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
#define lundump_c
#include "lua.h"
#include "ldebug.h"
@@ -19,6 +21,7 @@
typedef struct {
lua_State* L;
ZIO* Z;
Mbuffer* b;
int swap;
const char* name;
} LoadState;
@@ -45,7 +48,7 @@ static void LoadBlock (LoadState* S, void* b, size_t size)
{
if (S->swap)
{
char *p=(char*) b+size-1;
char* p=(char*) b+size-1;
int n=size;
while (n--) *p--=(char)ezgetc(S);
}
@@ -57,10 +60,10 @@ static void LoadVector (LoadState* S, void* b, int m, size_t size)
{
if (S->swap)
{
char *q=(char*) b;
char* q=(char*) b;
while (m--)
{
char *p=q+size-1;
char* p=q+size-1;
int n=size;
while (n--) *p--=(char)ezgetc(S);
q+=size;
@@ -99,9 +102,9 @@ static TString* LoadString (LoadState* S)
return NULL;
else
{
char* s=luaO_openspace(S->L,size,char);
char* s=luaZ_openspace(S->L,S->b,size);
ezread(S,s,size);
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
}
}
@@ -129,10 +132,22 @@ static void LoadLocals (LoadState* S, Proto* f)
static void LoadLines (LoadState* S, Proto* f)
{
int n;
int size=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,size,int);
f->sizelineinfo=size;
LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
}
static void LoadUpvalues (LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,n,int);
LoadVector(S,f->lineinfo,n,sizeof(*f->lineinfo));
if (n!=0 && n!=f->nups)
luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d",
S->name,n,f->nups);
f->upvalues=luaM_newvector(S->L,n,TString*);
f->sizeupvalues=n;
for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
}
static Proto* LoadFunction (LoadState* S, TString* p);
@@ -153,7 +168,7 @@ static void LoadConstants (LoadState* S, Proto* f)
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
setsvalue(o,LoadString(S));
setsvalue2n(o,LoadString(S));
break;
case LUA_TNIL:
setnilvalue(o);
@@ -174,12 +189,13 @@ static Proto* LoadFunction (LoadState* S, TString* p)
Proto* f=luaF_newproto(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->lineDefined=LoadInt(S);
f->nupvalues=LoadByte(S);
f->nups=LoadByte(S);
f->numparams=LoadByte(S);
f->is_vararg=LoadByte(S);
f->maxstacksize=LoadByte(S);
LoadLocals(S,f);
LoadLines(S,f);
LoadLocals(S,f);
LoadUpvalues(S,f);
LoadConstants(S,f);
LoadCode(S,f);
#ifndef TRUST_BINARIES
@@ -210,14 +226,14 @@ static void TestSize (LoadState* S, int s, const char* what)
static void LoadHeader (LoadState* S)
{
int version;
lua_Number x=0,tx=TEST_NUMBER;
lua_Number x,tx=TEST_NUMBER;
LoadSignature(S);
version=LoadByte(S);
if (version>VERSION)
luaG_runerror(S->L,"%s too new: "
"read version %d.%d; expected at most %d.%d",
S->name,V(version),V(VERSION));
if (version<VERSION0) /* check last major change */
if (version<VERSION0) /* check last major change */
luaG_runerror(S->L,"%s too old: "
"read version %d.%d; expected at least %d.%d",
S->name,V(version),V(VERSION0));
@@ -232,8 +248,7 @@ static void LoadHeader (LoadState* S)
TESTSIZE(sizeof(lua_Number), "number");
x=LoadNumber(S);
if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */
luaG_runerror(S->L,"unknown number format in %s: read %f; expected %f",
S->name,x,tx);
luaG_runerror(S->L,"unknown number format in %s",S->name);
}
static Proto* LoadChunk (LoadState* S)
@@ -243,12 +258,11 @@ static Proto* LoadChunk (LoadState* S)
}
/*
** load one chunk from a file or buffer
** load precompiled chunk
*/
Proto* luaU_undump (lua_State* L, ZIO* Z)
Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
{
LoadState S;
Proto* f;
const char* s=zname(Z);
if (*s=='@' || *s=='=')
S.name=s+1;
@@ -258,10 +272,8 @@ Proto* luaU_undump (lua_State* L, ZIO* Z)
S.name=s;
S.L=L;
S.Z=Z;
f=LoadChunk(&S);
if (zgetc(Z)!=EOZ)
luaG_runerror(L,"%s apparently contains more than one chunk",S.name);
return f;
S.b=buff;
return LoadChunk(&S);
}
/*

View File

@@ -1,5 +1,5 @@
/*
** $Id: lundump.h,v 1.26 2002/08/07 00:36:03 lhf Exp $
** $Id: lundump.h,v 1.30 2003/04/07 20:34:20 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -10,27 +10,25 @@
#include "lobject.h"
#include "lzio.h"
typedef int (*Writer)(const void* p, size_t size, void* u);
/* load one chunk; from lundump.c */
Proto* luaU_undump (lua_State* L, ZIO* Z);
Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff);
/* find byte order; from lundump.c */
int luaU_endianness (void);
/* dump one chunk; from dump.c */
void luaU_dump (const Proto* Main, Writer w, void* data);
/* dump one chunk; from ldump.c */
void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data);
/* print one chunk; from print.c */
void luaU_print (const Proto* Main);
/* definitions for headers of binary files */
#define LUA_SIGNATURE "\033Lua" /* binary files start with <esc>Lua */
#define LUA_SIGNATURE "\033Lua" /* binary files start with "<esc>Lua" */
#define VERSION 0x50 /* last format change was in 5.0 */
#define VERSION0 0x50 /* last major change was in 5.0 */
/* a multiple of PI for testing native format */
/* multiplying by 1E8 gives non-trivial integer values */
#define TEST_NUMBER 3.14159265358979323846E8
/* multiplying by 1E7 gives non-trivial integer values */
#define TEST_NUMBER ((lua_Number)3.14159265358979323846E7)
#endif

315
lvm.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 1.251 2002/08/07 19:22:39 roberto Exp roberto $
** $Id: lvm.c,v 1.283 2003/03/31 13:00:25 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,11 @@
#include <stdlib.h>
#include <string.h>
/* needed only when `lua_number2str' uses `sprintf' */
#include <stdio.h>
#define lvm_c
#include "lua.h"
#include "ldebug.h"
@@ -27,7 +32,6 @@
/* function to convert a lua_Number to a string */
#ifndef lua_number2str
#include <stdio.h>
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#endif
@@ -36,15 +40,6 @@
#define MAXTAGLOOP 100
static void luaV_checkGC (lua_State *L, StkId top) {
if (G(L)->nblocks >= G(L)->GCthreshold) {
L->top = top; /* limit for active registers */
luaC_collectgarbage(L);
L->top = L->ci->top; /* restore old top position */
}
}
const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
lua_Number num;
if (ttisnumber(obj)) return obj;
@@ -57,24 +52,24 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
}
int luaV_tostring (lua_State *L, TObject *obj) {
int luaV_tostring (lua_State *L, StkId obj) {
if (!ttisnumber(obj))
return 0;
else {
char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
lua_number2str(s, nvalue(obj));
setsvalue(obj, luaS_new(L, s));
setsvalue2s(obj, luaS_new(L, s));
return 1;
}
}
static void traceexec (lua_State *L) {
unsigned long mask = L->hookmask;
lu_byte mask = L->hookmask;
if (mask > LUA_MASKLINE) { /* instruction-hook set? */
if (L->hookcount == 0) {
luaD_callhook(L, LUA_HOOKCOUNT, -1);
resethookcount(L);
luaD_callhook(L, LUA_HOOKCOUNT, -1);
return;
}
}
@@ -82,6 +77,10 @@ static void traceexec (lua_State *L) {
CallInfo *ci = L->ci;
Proto *p = ci_func(ci)->l.p;
int newline = getline(p, pcRel(*ci->u.l.pc, p));
if (!L->hookinit) {
luaG_inithooks(L);
return;
}
lua_assert(ci->state & CI_HASFRAME);
if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */
ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */
@@ -98,9 +97,9 @@ static void traceexec (lua_State *L) {
static void callTMres (lua_State *L, const TObject *f,
const TObject *p1, const TObject *p2) {
setobj(L->top, f); /* push function */
setobj(L->top+1, p1); /* 1st argument */
setobj(L->top+2, p2); /* 2nd argument */
setobj2s(L->top, f); /* push function */
setobj2s(L->top+1, p1); /* 1st argument */
setobj2s(L->top+2, p2); /* 2nd argument */
luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */
L->top += 3;
luaD_call(L, L->top - 3, 1);
@@ -111,10 +110,10 @@ static void callTMres (lua_State *L, const TObject *f,
static void callTM (lua_State *L, const TObject *f,
const TObject *p1, const TObject *p2, const TObject *p3) {
setobj(L->top, f); /* push function */
setobj(L->top+1, p1); /* 1st argument */
setobj(L->top+2, p2); /* 2nd argument */
setobj(L->top+3, p3); /* 3th argument */
setobj2s(L->top, f); /* push function */
setobj2s(L->top+1, p1); /* 1st argument */
setobj2s(L->top+2, p2); /* 2nd argument */
setobj2s(L->top+3, p3); /* 3th argument */
luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */
L->top += 4;
luaD_call(L, L->top - 4, 0);
@@ -134,7 +133,7 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
TObject *key, int loop) {
const TObject *tm = luaT_gettmbyobj(L, t, TM_GETTABLE);
const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
if (ttisnil(tm))
luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) {
@@ -176,12 +175,12 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
setobj(oldval, val);
setobj2t(oldval, val); /* write barrier */
return;
}
/* else will try the tag method */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)))
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) {
callTM(L, tm, t, key, val);
@@ -194,7 +193,7 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
TObject *res, TMS event) {
StkId res, TMS event) {
ptrdiff_t result = savestack(L, res);
const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
if (ttisnil(tm))
@@ -202,11 +201,38 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
if (!ttisfunction(tm)) return 0;
callTMres(L, tm, p1, p2);
res = restorestack(L, result); /* previous call may change stack */
setobj(res, L->top);
setobjs2s(res, L->top);
return 1;
}
static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
TMS event) {
const TObject *tm1 = fasttm(L, mt1, event);
const TObject *tm2;
if (tm1 == NULL) return NULL; /* no metamethod */
if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
tm2 = fasttm(L, mt2, event);
if (tm2 == NULL) return NULL; /* no metamethod */
if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */
return tm1;
return NULL;
}
static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,
TMS event) {
const TObject *tm1 = luaT_gettmbyobj(L, p1, event);
const TObject *tm2;
if (ttisnil(tm1)) return -1; /* no metamethod? */
tm2 = luaT_gettmbyobj(L, p2, event);
if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
return -1;
callTMres(L, tm1, p1, p2);
return !l_isfalse(L->top);
}
static int luaV_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = ls->tsv.len;
@@ -230,56 +256,57 @@ static int luaV_strcmp (const TString *ls, const TString *rs) {
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
int res;
if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r);
else if (ttisnumber(l))
return nvalue(l) < nvalue(r);
else if (ttisstring(l))
return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
else if (call_binTM(L, l, r, L->top, TM_LT))
return !l_isfalse(L->top);
else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
return res;
return luaG_ordererror(L, l, r);
}
static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
int res;
if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r);
else if (ttisnumber(l))
return nvalue(l) <= nvalue(r);
else if (ttisstring(l))
return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
else if (call_binTM(L, l, r, L->top, TM_LE)) /* first try `le' */
return !l_isfalse(L->top);
else if (call_binTM(L, r, l, L->top, TM_LT)) /* else try `lt' */
return l_isfalse(L->top);
else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
return res;
else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
return !res;
return luaG_ordererror(L, l, r);
}
int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
const TObject *tm = NULL;
const TObject *tm;
lua_assert(ttype(t1) == ttype(t2));
switch (ttype(t1)) {
case LUA_TNIL: return 1;
case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
case LUA_TSTRING: return tsvalue(t1) == tsvalue(t2);
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
case LUA_TFUNCTION: return clvalue(t1) == clvalue(t2);
case LUA_TUSERDATA:
case LUA_TUSERDATA: {
if (uvalue(t1) == uvalue(t2)) return 1;
else if ((tm = fasttm(L, uvalue(t1)->uv.metatable, TM_EQ)) == NULL &&
(tm = fasttm(L, uvalue(t2)->uv.metatable, TM_EQ)) == NULL)
return 0; /* no TM */
else break; /* will try TM */
case LUA_TTABLE:
tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,
TM_EQ);
break; /* will try TM */
}
case LUA_TTABLE: {
if (hvalue(t1) == hvalue(t2)) return 1;
else if ((tm = fasttm(L, hvalue(t1)->metatable, TM_EQ)) == NULL &&
(tm = fasttm(L, hvalue(t2)->metatable, TM_EQ)) == NULL)
return 0; /* no TM */
else break; /* will try TM */
tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
default: return gcvalue(t1) == gcvalue(t2);
}
if (tm == NULL) return 0; /* no TM? */
callTMres(L, tm, t1, t2); /* call TM */
return !l_isfalse(L->top);
}
@@ -287,7 +314,7 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
void luaV_concat (lua_State *L, int total, int last) {
do {
StkId top = L->ci->base + last + 1;
StkId top = L->base + last + 1;
int n = 2; /* number of elements handled in this pass (at least 2) */
if (!tostring(L, top-2) || !tostring(L, top-1)) {
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
@@ -303,14 +330,14 @@ void luaV_concat (lua_State *L, int total, int last) {
n++;
}
if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
buffer = luaO_openspace(L, tl, char);
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
for (i=n; i>0; i--) { /* concat all strings */
size_t l = tsvalue(top-i)->tsv.len;
memcpy(buffer+tl, svalue(top-i), l);
tl += l;
}
setsvalue(top-n, luaS_newlstr(L, buffer, tl));
setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
}
total -= n-1; /* got `n' strings to create 1 new */
last -= n-1;
@@ -318,7 +345,8 @@ void luaV_concat (lua_State *L, int total, int last) {
}
static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
static void Arith (lua_State *L, StkId ra,
const TObject *rb, const TObject *rc, TMS op) {
TObject tempb, tempc;
const TObject *b, *c;
if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
@@ -329,14 +357,13 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
case TM_POW: {
const TObject *f = luaH_getstr(hvalue(registry(L)),
G(L)->tmname[TM_POW]);
const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
ptrdiff_t res = savestack(L, ra);
if (!ttisfunction(f))
luaG_runerror(L, "`pow' (for `^' operator) is not a function");
luaG_runerror(L, "`__pow' (`^' operator) is not a function");
callTMres(L, f, b, c);
ra = restorestack(L, res); /* previous call may change stack */
setobj(ra, L->top);
setobjs2s(ra, L->top);
break;
}
default: lua_assert(0); break;
@@ -355,11 +382,12 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
#define runtime_check(L, c) { if (!(c)) return 0; }
#define RA(i) (base+GETARG_A(i))
/* to be used after possible stack reallocation */
#define XRA(i) (L->base+GETARG_A(i))
#define RB(i) (base+GETARG_B(i))
#define RKB(i) ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
#define RC(i) (base+GETARG_C(i))
#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? \
base+GETARG_C(i) : \
k+GETARG_C(i)-MAXSTACK)
#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
#define KBx(i) (k+GETARG_Bx(i))
@@ -367,42 +395,49 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
StkId luaV_execute (lua_State *L) {
StkId base;
LClosure *cl;
TObject *k;
const Instruction *pc;
callentry: /* entry point when calling new functions */
L->ci->u.l.pb = &base;
L->ci->u.l.pc = &pc;
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
retentry: /* entry point when returning to old functions */
lua_assert(L->ci->state & CI_SAVEDPC);
lua_assert(L->ci->state == CI_SAVEDPC ||
L->ci->state == (CI_SAVEDPC | CI_CALLING));
L->ci->state = CI_HASFRAME; /* activate frame */
pc = L->ci->u.l.savedpc;
base = L->ci->base;
cl = &clvalue(base - 1)->l;
cl = &clvalue(L->base - 1)->l;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
StkId ra;
if (L->hookmask >= LUA_MASKLINE &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
StkId base, ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
traceexec(L);
if (L->ci->state & CI_YIELD) { /* did hook yield? */
L->ci->u.l.savedpc = pc - 1;
L->ci->state = CI_YIELD | CI_SAVEDPC;
return NULL;
}
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
base = L->base;
ra = RA(i);
lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
lua_assert(L->ci->state & CI_HASFRAME);
lua_assert(base == L->ci->base);
lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
lua_assert(L->top == L->ci->top ||
GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
switch (GET_OPCODE(i)) {
case OP_MOVE: {
setobj(ra, RB(i));
setobjs2s(ra, RB(i));
break;
}
case OP_LOADK: {
setobj(ra, KBx(i));
setobj2s(ra, KBx(i));
break;
}
case OP_LOADBOOL: {
@@ -419,17 +454,17 @@ StkId luaV_execute (lua_State *L) {
}
case OP_GETUPVAL: {
int b = GETARG_B(i);
setobj(ra, cl->upvals[b]->v);
setobj2s(ra, cl->upvals[b]->v);
break;
}
case OP_GETGLOBAL: {
StkId rb = KBx(i);
TObject *rb = KBx(i);
const TObject *v;
lua_assert(ttisstring(rb) && ttistable(&cl->g));
v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
if (!ttisnil(v)) { setobj(ra, v); }
if (!ttisnil(v)) { setobj2s(ra, v); }
else
setobj(RA(i), luaV_index(L, &cl->g, rb, 0));
setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
break;
}
case OP_GETTABLE: {
@@ -437,12 +472,12 @@ StkId luaV_execute (lua_State *L) {
TObject *rc = RKC(i);
if (ttistable(rb)) {
const TObject *v = luaH_get(hvalue(rb), rc);
if (!ttisnil(v)) { setobj(ra, v); }
if (!ttisnil(v)) { setobj2s(ra, v); }
else
setobj(RA(i), luaV_index(L, rb, rc, 0));
setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
}
else
setobj(RA(i), luaV_getnotable(L, rb, rc, 0));
setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
break;
}
case OP_SETGLOBAL: {
@@ -452,38 +487,38 @@ StkId luaV_execute (lua_State *L) {
}
case OP_SETUPVAL: {
int b = GETARG_B(i);
setobj(cl->upvals[b]->v, ra);
setobj(cl->upvals[b]->v, ra); /* write barrier */
break;
}
case OP_SETTABLE: {
luaV_settable(L, RB(i), RKC(i), ra);
luaV_settable(L, ra, RKB(i), RKC(i));
break;
}
case OP_NEWTABLE: {
int b = GETARG_B(i);
if (b > 0) b = twoto(b-1);
b = fb2int(b);
sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
luaV_checkGC(L, ra+1);
luaC_checkGC(L);
break;
}
case OP_SELF: {
StkId rb = RB(i);
TObject *rc = RKC(i);
runtime_check(L, ttisstring(rc));
setobj(ra+1, rb);
setobjs2s(ra+1, rb);
if (ttistable(rb)) {
const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
if (!ttisnil(v)) { setobj(ra, v); }
if (!ttisnil(v)) { setobj2s(ra, v); }
else
setobj(RA(i), luaV_index(L, rb, rc, 0));
setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
}
else
setobj(RA(i), luaV_getnotable(L, rb, rc, 0));
setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
break;
}
case OP_ADD: {
StkId rb = RB(i);
StkId rc = RKC(i);
TObject *rb = RKB(i);
TObject *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) + nvalue(rc));
}
@@ -492,8 +527,8 @@ StkId luaV_execute (lua_State *L) {
break;
}
case OP_SUB: {
StkId rb = RB(i);
StkId rc = RKC(i);
TObject *rb = RKB(i);
TObject *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) - nvalue(rc));
}
@@ -502,8 +537,8 @@ StkId luaV_execute (lua_State *L) {
break;
}
case OP_MUL: {
StkId rb = RB(i);
StkId rc = RKC(i);
TObject *rb = RKB(i);
TObject *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) * nvalue(rc));
}
@@ -512,8 +547,8 @@ StkId luaV_execute (lua_State *L) {
break;
}
case OP_DIV: {
StkId rb = RB(i);
StkId rc = RKC(i);
TObject *rb = RKB(i);
TObject *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) / nvalue(rc));
}
@@ -522,7 +557,7 @@ StkId luaV_execute (lua_State *L) {
break;
}
case OP_POW: {
Arith(L, ra, RB(i), RKC(i), TM_POW);
Arith(L, ra, RKB(i), RKC(i), TM_POW);
break;
}
case OP_UNM: {
@@ -547,44 +582,35 @@ StkId luaV_execute (lua_State *L) {
int b = GETARG_B(i);
int c = GETARG_C(i);
luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */
setobj(RA(i), base+b);
luaV_checkGC(L, base+c+1);
base = L->base;
setobjs2s(RA(i), base+b);
luaC_checkGC(L);
break;
}
case OP_JMP: {
dojump(pc, GETARG_sBx(i));
break;
}
case OP_EQ: { /* skip next instruction if test fails */
if (equalobj(L, ra, RKC(i)) != GETARG_B(i)) pc++;
case OP_EQ: {
if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
else dojump(pc, GETARG_sBx(*pc) + 1);
break;
}
case OP_LT: {
if (luaV_lessthan(L, ra, RKC(i)) != GETARG_B(i)) pc++;
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
else dojump(pc, GETARG_sBx(*pc) + 1);
break;
}
case OP_LE: {
if (luaV_lessequal(L, ra, RKC(i)) != GETARG_B(i)) pc++;
else dojump(pc, GETARG_sBx(*pc) + 1);
break;
}
case OP_GT: {
if (luaV_lessthan(L, RKC(i), ra) != GETARG_B(i)) pc++;
else dojump(pc, GETARG_sBx(*pc) + 1);
break;
}
case OP_GE: {
if (luaV_lessequal(L, RKC(i), ra) != GETARG_B(i)) pc++;
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
else dojump(pc, GETARG_sBx(*pc) + 1);
break;
}
case OP_TEST: {
StkId rc = RKC(i);
if (l_isfalse(rc) == GETARG_B(i)) pc++;
TObject *rb = RB(i);
if (l_isfalse(rb) == GETARG_C(i)) pc++;
else {
setobj(ra, rc);
setobjs2s(ra, rb);
dojump(pc, GETARG_sBx(*pc) + 1);
}
break;
@@ -599,6 +625,7 @@ StkId luaV_execute (lua_State *L) {
firstResult = luaD_precall(L, ra);
if (firstResult) {
if (firstResult > L->top) { /* yield? */
lua_assert(L->ci->state == (CI_C | CI_YIELD));
(L->ci - 1)->u.l.savedpc = pc;
(L->ci - 1)->state = CI_SAVEDPC;
return NULL;
@@ -614,22 +641,25 @@ StkId luaV_execute (lua_State *L) {
}
else { /* tail call: put new frame in place of previous one */
int aux;
StkId ra1 = RA(i); /* `luaD_precall' may change the stack */
base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
ra = RA(i);
if (L->openupval) luaF_close(L, base);
for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */
setobj(base+aux-1, ra1+aux);
for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
setobjs2s(base+aux-1, ra+aux);
(L->ci - 1)->top = L->top = base+aux; /* correct top */
lua_assert(L->ci->state & CI_SAVEDPC);
(L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
(L->ci - 1)->u.l.tailcalls++; /* one more call lost */
(L->ci - 1)->state = CI_SAVEDPC;
L->ci--; /* remove previous frame */
L->ci--; /* remove new frame */
L->base = L->ci->base;
}
goto callentry;
}
break;
}
case OP_RETURN: {
CallInfo *ci = L->ci - 1;
CallInfo *ci = L->ci - 1; /* previous function frame */
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
lua_assert(L->ci->state & CI_HASFRAME);
@@ -637,12 +667,15 @@ StkId luaV_execute (lua_State *L) {
L->ci->state = CI_SAVEDPC; /* deactivate current function */
L->ci->u.l.savedpc = pc;
/* previous function was running `here'? */
if (!(ci->state & CI_CALLING))
if (!(ci->state & CI_CALLING)) {
lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
return ra; /* no: return */
else { /* yes: continue its execution (go through) */
}
else { /* yes: continue its execution */
int nresults;
lua_assert(ttisfunction(ci->base - 1));
lua_assert(ci->state & CI_SAVEDPC);
lua_assert(ci->u.l.pc == &pc &&
ttisfunction(ci->base - 1) &&
(ci->state & CI_SAVEDPC));
lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
luaD_poscall(L, nresults, ra);
@@ -651,7 +684,7 @@ StkId luaV_execute (lua_State *L) {
}
}
case OP_FORLOOP: {
lua_Number step, index, limit;
lua_Number step, idx, limit;
const TObject *plimit = ra+1;
const TObject *pstep = ra+2;
if (!ttisnumber(ra))
@@ -661,29 +694,39 @@ StkId luaV_execute (lua_State *L) {
if (!tonumber(pstep, ra+2))
luaG_runerror(L, "`for' step must be a number");
step = nvalue(pstep);
index = nvalue(ra) + step; /* increment index */
idx = nvalue(ra) + step; /* increment index */
limit = nvalue(plimit);
if (step > 0 ? index <= limit : index >= limit) {
if (step > 0 ? idx <= limit : idx >= limit) {
dojump(pc, GETARG_sBx(i)); /* jump back */
chgnvalue(ra, index); /* update index */
chgnvalue(ra, idx); /* update index */
}
break;
}
case OP_TFORLOOP: {
setobj(ra+4, ra+2);
setobj(ra+3, ra+1);
setobj(ra+2, ra);
L->top = ra+5;
luaD_call(L, ra+2, GETARG_C(i) + 1);
int nvar = GETARG_C(i) + 1;
StkId cb = ra + nvar + 2; /* call base */
setobjs2s(cb, ra);
setobjs2s(cb+1, ra+1);
setobjs2s(cb+2, ra+2);
L->top = cb+3; /* func. + 2 args (state and index) */
luaD_call(L, cb, nvar);
L->top = L->ci->top;
if (ttisnil(RA(i)+2)) pc++; /* skip jump (break loop) */
else dojump(pc, GETARG_sBx(*pc) + 1); /* else jump back */
ra = XRA(i) + 2; /* final position of first result */
cb = ra + nvar;
do { /* move results to proper positions */
nvar--;
setobjs2s(ra+nvar, cb+nvar);
} while (nvar > 0);
if (ttisnil(ra)) /* break loop? */
pc++; /* skip jump (break loop) */
else
dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */
break;
}
case OP_TFORPREP: { /* for compatibility only */
if (ttistable(ra)) {
setobj(ra+1, ra);
setobj(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
setobjs2s(ra+1, ra);
setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
}
dojump(pc, GETARG_sBx(i));
break;
@@ -704,7 +747,7 @@ StkId luaV_execute (lua_State *L) {
}
bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */
for (; n > 0; n--)
setobj(luaH_setnum(L, h, bc+n), ra+n);
setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */
break;
}
case OP_CLOSE: {
@@ -716,7 +759,7 @@ StkId luaV_execute (lua_State *L) {
Closure *ncl;
int nup, j;
p = cl->p->p[GETARG_Bx(i)];
nup = p->nupvalues;
nup = p->nups;
ncl = luaF_newLclosure(L, nup, &cl->g);
ncl->l.p = p;
for (j=0; j<nup; j++, pc++) {
@@ -728,7 +771,7 @@ StkId luaV_execute (lua_State *L) {
}
}
setclvalue(ra, ncl);
luaV_checkGC(L, L->top);
luaC_checkGC(L);
break;
}
}

4
lvm.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.h,v 1.45 2002/08/05 17:36:24 roberto Exp roberto $
** $Id: lvm.h,v 1.46 2002/08/07 19:22:39 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -25,7 +25,7 @@
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
const TObject *luaV_tonumber (const TObject *obj, TObject *n);
int luaV_tostring (lua_State *L, TObject *obj);
int luaV_tostring (lua_State *L, StkId obj);
const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
int loop);
void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val);

21
lzio.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lzio.c,v 1.20 2002/08/05 18:45:02 roberto Exp roberto $
** $Id: lzio.c,v 1.23 2002/12/04 17:38:31 roberto Exp roberto $
** a generic input stream interface
** See Copyright Notice in lua.h
*/
@@ -7,20 +7,22 @@
#include <string.h>
#define lzio_c
#include "lua.h"
#include "llimits.h"
#include "lmem.h"
#include "lzio.h"
int luaZ_fill (ZIO *z) {
size_t size;
const char *buff = z->reader(NULL, z->data, &size);
if (buff == NULL || size == 0) return EOZ;
z->n = size - 1;
z->p = buff;
return *(z->p++);
return char2int(*(z->p++));
}
@@ -31,7 +33,7 @@ int luaZ_lookahead (ZIO *z) {
z->n++;
z->p--;
}
return *z->p;
return char2int(*z->p);
}
@@ -66,3 +68,14 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
return 0;
}
/* ------------------------------------------------------------------------ */
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
if (n > buff->buffsize) {
if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
buff->buffsize = n;
}
return buff->buffer;
}

34
lzio.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lzio.h,v 1.12 2002/06/06 12:40:22 roberto Exp roberto $
** $Id: lzio.h,v 1.14 2002/10/08 18:46:08 roberto Exp roberto $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -13,11 +13,12 @@
#define EOZ (-1) /* end of stream */
typedef struct zio ZIO;
typedef struct Zio ZIO;
#define zgetc(z) (((z)->n--)>0 ? \
cast(int, cast(unsigned char, *(z)->p++)) : \
luaZ_fill(z))
#define char2int(c) cast(int, cast(unsigned char, (c)))
#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
#define zname(z) ((z)->name)
@@ -26,9 +27,30 @@ size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
int luaZ_lookahead (ZIO *z);
typedef struct Mbuffer {
char *buffer;
size_t buffsize;
} Mbuffer;
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
#define luaZ_sizebuffer(buff) ((buff)->buffsize)
#define luaZ_buffer(buff) ((buff)->buffer)
#define luaZ_resizebuffer(L, buff, size) \
(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
(buff)->buffsize = size)
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
/* --------- Private Part ------------------ */
struct zio {
struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Chunkreader reader;

View File

@@ -1,5 +1,5 @@
#
## $Id: makefile,v 1.35 2002/03/18 18:18:35 roberto Exp roberto $
## $Id: makefile,v 1.40 2003/03/19 21:27:30 roberto Exp roberto $
## Makefile
## See Copyright Notice in lua.h
#
@@ -7,22 +7,14 @@
#CONFIGURATION
# define (undefine) POPEN if your system (does not) support piped I/O
#
# define (undefine) _POSIX_SOURCE if your system is (not) POSIX compliant
#
# define LUA_NUM_TYPE if you need numbers to be different from double
# (for instance, -DLUA_NUM_TYPE=float)
# you may need to adapat the code, too.
# -DEXTERNMEMCHECK -DHARDSTACKTESTS
# DEBUG = -g -DLUA_USER_H='"ltests.h"'
OPTIMIZE = -O2 \
-D'lua_number2int(i,d)=__asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d))' \
-fomit-frame-pointer
-D'lua_number2int(i,d)=__asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d))' \
# -fomit-frame-pointer
CONFIG = -D_POSIX_SOURCE -DPOPEN $(DEBUG) $(OPTIMIZE)
CONFIG = $(DEBUG) $(OPTIMIZE) -DLUA_COMPATUPSYNTAX -DUSE_TMPNAME -DUSE_DLOPEN
# Compilation parameters
@@ -39,7 +31,7 @@ CWARNS = -Wall -pedantic \
# -Wtraditional \
# -Wcast-qual
CFLAGS = $(CONFIG) $(CWARNS) -ansi
CFLAGS = $(CONFIG) $(CWARNS) # -ansi
# To make early versions
@@ -68,6 +60,7 @@ LUAOBJS = \
llex.o \
lopcodes.o \
lundump.o \
ldump.o \
lzio.o \
ldebug.o \
ltests.o
@@ -79,11 +72,12 @@ LIBOBJS = \
lmathlib.o \
liolib.o \
lstrlib.o \
ldblib.o
ldblib.o \
loadlib.o
lua : lua.o liblua.a liblualib.a
$(CC) $(CFLAGS) -o $@ lua.o -L. -llua -llualib -lm
$(CC) $(CFLAGS) -o $@ lua.o -Wl,-E -L. -llua -llualib -lm -ldl
liblua.a : $(LUAOBJS)
$(AR) $(ARFLAGS) $@ $?
@@ -109,52 +103,54 @@ clear :
co $(CO_OPTIONS) $@
lapi.o: lapi.c lua.h lapi.h lobject.h llimits.h ldebug.h lstate.h \
ltm.h ldo.h lzio.h lfunc.h lgc.h lmem.h lstring.h ltable.h lundump.h \
lvm.h
lapi.o: lapi.c lua.h lapi.h lobject.h llimits.h ldebug.h lstate.h ltm.h \
lzio.h ldo.h lfunc.h lgc.h lmem.h lstring.h ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lua.h lauxlib.h
lbaselib.o: lbaselib.c lua.h lauxlib.h lualib.h
lcode.o: lcode.c lua.h lcode.h llex.h lobject.h llimits.h lzio.h \
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lmem.h
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lmem.h
ldblib.o: ldblib.c lua.h lauxlib.h lualib.h
ldebug.o: ldebug.c lua.h lapi.h lobject.h llimits.h lcode.h llex.h \
lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h \
lfunc.h lstring.h lvm.h
ldo.o: ldo.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lfunc.h lgc.h lmem.h lopcodes.h lparser.h ltable.h lstring.h \
lundump.h lvm.h
lfunc.o: lfunc.c lua.h lfunc.h lobject.h llimits.h lmem.h lstate.h \
ltm.h
lgc.o: lgc.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lfunc.h lgc.h lmem.h lstring.h ltable.h
ldebug.o: ldebug.c lua.h lapi.h lobject.h llimits.h lcode.h llex.h lzio.h \
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \
lstring.h lvm.h
ldo.o: ldo.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
ldo.h lfunc.h lgc.h lmem.h lopcodes.h lparser.h ltable.h lstring.h \
lundump.h lvm.h
ldump.o: ldump.c lua.h lobject.h llimits.h lopcodes.h lstate.h ltm.h \
lzio.h lundump.h
lfunc.o: lfunc.c lua.h lfunc.h lobject.h llimits.h lgc.h lmem.h lstate.h \
ltm.h lzio.h
lgc.o: lgc.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
ldo.h lfunc.h lgc.h lmem.h lstring.h ltable.h
liolib.o: liolib.c lua.h lauxlib.h lualib.h
llex.o: llex.c lua.h ldo.h lobject.h llimits.h lstate.h ltm.h lzio.h \
llex.h lparser.h ltable.h lstring.h
llex.h lparser.h ltable.h lstring.h
lmathlib.o: lmathlib.c lua.h lauxlib.h lualib.h
lmem.o: lmem.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lmem.h
lmem.o: lmem.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
ldo.h lmem.h
lobject.o: lobject.c lua.h ldo.h lobject.h llimits.h lstate.h ltm.h \
lzio.h lmem.h lstring.h lvm.h
lzio.h lmem.h lstring.h lvm.h
loadlib.o: loadlib.c lua.h lauxlib.h lualib.h
lopcodes.o: lopcodes.c lua.h lobject.h llimits.h lopcodes.h
lparser.o: lparser.c lua.h lcode.h llex.h lobject.h llimits.h lzio.h \
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h lfunc.h lmem.h \
lstring.h
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h lfunc.h lmem.h \
lstring.h
lstate.o: lstate.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
ldo.h lzio.h lfunc.h lgc.h llex.h lmem.h lstring.h ltable.h
lzio.h ldo.h lfunc.h lgc.h llex.h lmem.h lstring.h ltable.h
lstring.o: lstring.c lua.h lmem.h llimits.h lobject.h lstate.h ltm.h \
lstring.h
lzio.h lstring.h
lstrlib.o: lstrlib.c lua.h lauxlib.h lualib.h
ltable.o: ltable.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
ldo.h lzio.h lmem.h ltable.h
lzio.h ldo.h lgc.h lmem.h ltable.h
ltablib.o: ltablib.c lua.h lauxlib.h lualib.h
ltests.o: ltests.c lua.h lapi.h lobject.h llimits.h lauxlib.h lcode.h \
llex.h lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lmem.h lstring.h lualib.h
ltm.o: ltm.c lua.h lobject.h llimits.h lstate.h ltm.h lstring.h \
ltable.h
llex.h lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lmem.h lstring.h lualib.h
ltm.o: ltm.c lua.h lobject.h llimits.h lstate.h ltm.h lzio.h lstring.h \
ltable.h
lua.o: lua.c lua.h lauxlib.h lualib.h
lundump.o: lundump.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
lfunc.h lmem.h lopcodes.h lstring.h lundump.h lzio.h
lvm.o: lvm.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
lzio.o: lzio.c lua.h llimits.h lzio.h
lzio.h lfunc.h lmem.h lopcodes.h lstring.h lundump.h
lvm.o: lvm.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
lzio.o: lzio.c lua.h llimits.h lmem.h lzio.h

4298
manual.tex

File diff suppressed because it is too large Load Diff