Compare commits

...

723 Commits
v2.2 ... v3.2

Author SHA1 Message Date
Roberto Ierusalimschy
16024861bd new format for numbers in precompiled code (as strings) 1999-07-08 09:43:23 -03:00
Roberto Ierusalimschy
3f43aaa23f new RedHat defines PI :-( 1999-07-07 14:54:08 -03:00
Roberto Ierusalimschy
3b4c831ca9 some systems do not reset signal handlers when a signal happens 1999-07-02 15:22:38 -03:00
Roberto Ierusalimschy
3fdab3981b no more automatic setlocale. 1999-06-24 16:42:02 -03:00
Roberto Ierusalimschy
88b65da4d7 simplifications. 1999-06-23 10:48:39 -03:00
Roberto Ierusalimschy
521b38532a better interfaces for luaD_calln (x luaD_call) 1999-06-22 17:37:23 -03:00
Roberto Ierusalimschy
36b6fe8d17 better treatment for arbitrary limits 1999-06-17 14:04:03 -03:00
Roberto Ierusalimschy
d4dce57f5c cannot assign to unlimited variables, because it causes overflow in
the number of returns of a function.
1999-06-16 10:35:01 -03:00
Roberto Ierusalimschy
5c19ed2a13 bigger limit for number of local variables and upvalues 1999-06-16 10:22:04 -03:00
Roberto Ierusalimschy
5caf7f4a33 tremove erases its previous last element (to avoid locking potential
garbagge).
1999-05-27 17:21:03 -03:00
Roberto Ierusalimschy
3b533ea7c7 foreach, foreachi, foreachvar points to function in stack when stack
can be reallocated.
1999-05-24 14:53:49 -03:00
Roberto Ierusalimschy
995775e1cb tighter control on the stack when debugging 1999-05-24 14:53:03 -03:00
Roberto Ierusalimschy
abfc885079 when debugging, move and erase old blocks to realloc. 1999-05-24 14:51:05 -03:00
Roberto Ierusalimschy
613b60c156 detail 1999-05-21 16:54:06 -03:00
Roberto Ierusalimschy
cdd0fe9946 some C compilers cannot initialize a local struct 1999-05-21 16:41:49 -03:00
Roberto Ierusalimschy
bc8619342a better control of stack size (only for DEBUG). 1999-05-21 14:23:15 -03:00
Roberto Ierusalimschy
48326500d0 longer marks when controling memory leaks 1999-05-20 17:43:06 -03:00
Roberto Ierusalimschy
c8d219798a lhf 1999-05-17 11:12:01 -03:00
Roberto Ierusalimschy
34695d4f4a details (message text) 1999-05-14 09:24:20 -03:00
Roberto Ierusalimschy
924bbe020b bigger limits 1999-05-14 09:24:04 -03:00
Roberto Ierusalimschy
3aa500b524 new pattern item '+' 1999-05-11 17:46:28 -03:00
Roberto Ierusalimschy
f1861ee210 no more beta 1999-05-11 17:29:19 -03:00
Roberto Ierusalimschy
705eae9fe4 there is no need for a size for Cblocks 1999-05-11 17:08:20 -03:00
Roberto Ierusalimschy
6eb1399a1c array Cblocks should grow dynamically 1999-05-11 11:19:32 -03:00
Roberto Ierusalimschy
c390f73e3b block must always have a power-of-2 size (even at the limit) 1999-05-11 11:18:40 -03:00
Roberto Ierusalimschy
73308c7605 warnings by clinio 1999-05-10 10:54:01 -03:00
Roberto Ierusalimschy
288fa05602 opcodes with LONGARG do not use byte variants. 1999-05-06 11:41:41 -03:00
Roberto Ierusalimschy
7808ea3a5f new implementation for '*' in patterns + new option '+' 1999-05-05 16:23:11 -03:00
Roberto Ierusalimschy
732741b62f cannot use (i=i+1) 1999-05-05 16:21:57 -03:00
Roberto Ierusalimschy
cc0f635ef7 '$' at end of pattern was matching regular '$', too. 1999-04-30 11:12:05 -03:00
Roberto Ierusalimschy
e64dbc390a new version is beta. 1999-04-15 09:33:19 -03:00
Roberto Ierusalimschy
a0fd8d1787 manual for 3.2 beta should be the same one that for 3.2. 1999-04-14 17:47:12 -03:00
Roberto Ierusalimschy
d9d04a9274 "read_pattern" could lock when reading a lookahead from stdin. 1999-04-14 17:40:32 -03:00
Roberto Ierusalimschy
b4ad600b93 numbers are stored in ascii format for better portability and simplicity 1999-04-13 17:16:37 -03:00
Roberto Ierusalimschy
cb7f027380 IMtable must be initialized (and IMtable_size is not needed any more) due
to new way to handle growing vectors (previous modification).
1999-04-13 16:30:51 -03:00
Roberto Ierusalimschy
0bbd96bd5f details. 1999-04-13 16:28:49 -03:00
Roberto Ierusalimschy
4eb67aa710 changes from lhf. 1999-04-07 13:40:04 -03:00
Roberto Ierusalimschy
0133610315 format for function prototypes. 1999-04-07 12:37:02 -03:00
Roberto Ierusalimschy
de04533dc0 better the old way, using upvalues to keep iotag. 1999-04-05 16:47:05 -03:00
Roberto Ierusalimschy
7c9aee64c2 new version by lhf. 1999-03-30 17:29:34 -03:00
Roberto Ierusalimschy
e0ff4e5d22 first version about Lua debug library. 1999-03-29 11:21:37 -03:00
Roberto Ierusalimschy
bf7f85d609 GC of files is tricky when Lua is being closed... 1999-03-26 10:48:26 -03:00
Roberto Ierusalimschy
a775a2d81a check first whether function is global. 1999-03-26 10:14:00 -03:00
Roberto Ierusalimschy
e9aa98d594 do not generate SETLINE after main (it will be after last line) 1999-03-25 18:06:57 -03:00
Roberto Ierusalimschy
3e9c6a8a24 details 1999-03-25 18:05:05 -03:00
Roberto Ierusalimschy
1f4e2ba7b2 more precise debug information about local variables 1999-03-23 16:58:37 -03:00
Roberto Ierusalimschy
d6ff06751a new functions openfile and closefile;
new way to keep file handle tags.
1999-03-16 17:07:54 -03:00
Roberto Ierusalimschy
7a11c7f8e4 details 1999-03-16 13:43:27 -03:00
Roberto Ierusalimschy
c454dc7bdd no more if expressions. 1999-03-11 16:00:12 -03:00
Roberto Ierusalimschy
82ad0d5770 details 1999-03-11 15:59:19 -03:00
Roberto Ierusalimschy
256d1bea08 missing #include 1999-03-10 11:23:07 -03:00
Roberto Ierusalimschy
f2d35bdc78 format for file source is independent of "ldo". 1999-03-10 11:19:41 -03:00
Roberto Ierusalimschy
2679461637 no more assignment expressions (they don't fit in Lua...) 1999-03-10 11:09:45 -03:00
Roberto Ierusalimschy
0870a2d1d8 new opcode TAILCALL 1999-03-05 18:16:07 -03:00
Roberto Ierusalimschy
78edc241e9 details about debug info. 1999-03-05 17:45:01 -03:00
Roberto Ierusalimschy
e907c711c0 "feof" may be a macro. 1999-03-05 10:15:50 -03:00
Roberto Ierusalimschy
5a8bb00df4 storing chunk "sources" instead of "filenames". 1999-03-04 18:23:39 -03:00
Roberto Ierusalimschy
677188de8a details. 1999-03-04 18:15:50 -03:00
Roberto Ierusalimschy
6233d21c9d file stream cannot call fread after EOF. 1999-03-04 11:50:26 -03:00
Roberto Ierusalimschy
ab8ea5c38a warnings 1999-03-01 17:22:16 -03:00
Roberto Ierusalimschy
ae9fd122fa vector do not need to grow until MINSIZE 1999-03-01 14:49:13 -03:00
Roberto Ierusalimschy
da18ec5d54 warnings... 1999-03-01 14:49:04 -03:00
Roberto Ierusalimschy
038848eccd better control of vector when DEBUGing 1999-02-26 12:50:10 -03:00
Roberto Ierusalimschy
b678e465a1 warnings in Solaris 1999-02-26 12:49:53 -03:00
Roberto Ierusalimschy
72d675aba7 macros "growvector" and "reallocvector" more compact 1999-02-26 12:48:55 -03:00
Roberto Ierusalimschy
ba57f7d946 details 1999-02-26 12:48:30 -03:00
Roberto Ierusalimschy
e63b542c9b comments 1999-02-26 12:19:54 -03:00
Roberto Ierusalimschy
6a853fcb8b details (from lhf) 1999-02-25 18:07:26 -03:00
Roberto Ierusalimschy
31bea2190b small correction 1999-02-25 16:20:40 -03:00
Roberto Ierusalimschy
4b954e9b2e details (from lhf) 1999-02-25 16:13:56 -03:00
Roberto Ierusalimschy
055823c04d "L->Mbuffbase" is better kept as offset instead of pointer 1999-02-25 12:17:01 -03:00
Roberto Ierusalimschy
26d1e21c89 new way to handle "growing" vectors 1999-02-25 12:16:26 -03:00
Roberto Ierusalimschy
24a2c08145 details 1999-02-24 18:31:03 -03:00
Roberto Ierusalimschy
9d7bae0b6a better instrumentation for internal debugging 1999-02-24 14:55:51 -03:00
Roberto Ierusalimschy
082aded149 warnings 1999-02-24 12:37:19 -03:00
Roberto Ierusalimschy
aa9c75c06e no more EXTRALIBS (and new dependencies) 1999-02-23 12:01:29 -03:00
Roberto Ierusalimschy
f04c83e075 new function "lua_next" (+ new implementation for "next") 1999-02-23 11:57:28 -03:00
Roberto Ierusalimschy
c364e9f97e LONGARGW (for completeness). 1999-02-23 10:38:38 -03:00
Roberto Ierusalimschy
e3a02e6a9c comments 1999-02-22 16:23:36 -03:00
Roberto Ierusalimschy
d5feffdb60 new function lua_nextvar 1999-02-22 16:13:12 -03:00
Roberto Ierusalimschy
bb5627f3a4 better control over calls to _ALERT and _ERRORMESSAGE (to avoid error
loops)
1999-02-22 11:17:24 -03:00
Roberto Ierusalimschy
21107d7c2c debug state is restored after a dofile/dostring 1999-02-22 10:51:44 -03:00
Roberto Ierusalimschy
b5cd7d426f details 1999-02-19 15:33:35 -02:00
Roberto Ierusalimschy
bf6d2ccf92 details 1999-02-12 17:23:02 -02:00
Roberto Ierusalimschy
b82ff713e3 new name for opcode 1999-02-09 16:01:55 -02:00
Roberto Ierusalimschy
77113ee02f new year for Copyright. 1999-02-09 13:59:22 -02:00
Roberto Ierusalimschy
ad6c7b0dd4 small corrections in opcodes. 1999-02-09 13:59:10 -02:00
Roberto Ierusalimschy
8b2d97d187 assignment expression may be multiple 1999-02-08 16:54:19 -02:00
Roberto Ierusalimschy
fb1cf6ab2d clearer way to set tables. 1999-02-08 15:07:59 -02:00
Roberto Ierusalimschy
19ca2087de another (silly) debuging function. 1999-02-08 14:29:35 -02:00
Roberto Ierusalimschy
7bdbd833b5 userdata and strings are kept in separate stringtables 1999-02-08 14:28:48 -02:00
Roberto Ierusalimschy
b22baf386d Lua cannot have static variables. 1999-02-05 13:22:43 -02:00
Roberto Ierusalimschy
8fdd06ba3c lots of new stuff from 3.2 1999-02-05 10:15:07 -02:00
Roberto Ierusalimschy
028ec00ab9 details 1999-02-05 09:22:58 -02:00
Roberto Ierusalimschy
1dcf1c9cbd format "%s" may break limit of "sprintf" on some machines. 1999-02-04 17:29:51 -02:00
Roberto Ierusalimschy
76179a1014 compile option EXTRALIB for builtin functions that can be written in Lua. 1999-02-04 17:12:35 -02:00
Roberto Ierusalimschy
bdfab46c22 "errorim" now is _ERRORMESSAGE. 1999-02-04 16:59:31 -02:00
Roberto Ierusalimschy
5687949560 "lua_debug", "lua_callhook" and "lua_linehook" must be inside "lua_state". 1999-02-04 15:47:59 -02:00
Roberto Ierusalimschy
19de5b2205 new dependencies 1999-02-04 14:37:41 -02:00
Roberto Ierusalimschy
cbc58af260 new opcode for "long" arguments (3 bytes) 1999-02-04 14:36:16 -02:00
Roberto Ierusalimschy
80001ab0eb getlocal cannot return the local itself, since lua_isstring and
lua_isnumber can modify it.
1999-02-03 14:42:42 -02:00
Roberto Ierusalimschy
ae29ab9858 only parser uses MAX_WORD 1999-02-03 11:53:48 -02:00
Roberto Ierusalimschy
27407fc1f5 new syntax: assignment expressions + better order for opcodes 1999-02-02 17:41:17 -02:00
Roberto Ierusalimschy
1a17da2ff9 opcodes with builtin parameters are too complicated for very little extra
performance.
1999-02-02 15:57:49 -02:00
Roberto Ierusalimschy
50248e440a "if" expression leaves only one of its expressions on the stack 1999-02-02 11:47:31 -02:00
Roberto Ierusalimschy
0f0079f394 "if" expressions. 1999-02-01 16:52:05 -02:00
Roberto Ierusalimschy
68267ed878 negative numerals do not need a MINUSOPeration; go directly to contant
table.
1999-01-29 11:48:58 -02:00
Roberto Ierusalimschy
fd25d4ad85 no need to define functions for macros... 1999-01-26 13:38:01 -02:00
Roberto Ierusalimschy
2431534f10 details 1999-01-26 09:50:58 -02:00
Roberto Ierusalimschy
fd7d0774e5 luaH_set does the set and protect its value; luaH_move can then be a
macro.
New algorithm for double hashing (does not use "%").
1999-01-25 15:41:19 -02:00
Roberto Ierusalimschy
57ffc3f009 luaH_set does the set, and protects its value, so luaH_move can be a
macro.
1999-01-25 15:40:10 -02:00
Roberto Ierusalimschy
4a13f513f8 luaH_set does the set! 1999-01-25 15:39:28 -02:00
Roberto Ierusalimschy
13ad46b67d uses the same double hashing that is used for tables 1999-01-25 15:38:04 -02:00
Roberto Ierusalimschy
1b45e967b4 table entries with ref=null always have val=null too. 1999-01-25 10:30:11 -02:00
Roberto Ierusalimschy
933bead92e small optimizations(?) 1999-01-22 16:47:23 -02:00
Roberto Ierusalimschy
3314f49ec4 C cannot initialize a struct. 1999-01-22 16:46:11 -02:00
Roberto Ierusalimschy
bc930aa5ff "free" usually handles NULL; handle non ANSI case separately. 1999-01-22 16:08:57 -02:00
Roberto Ierusalimschy
67b44c9493 local names are all in the constant pool, so they do not need to be
marked in GC.
1999-01-22 16:08:03 -02:00
Roberto Ierusalimschy
758a381644 "realloc" usually implements "malloc"; handle non ANSI case separately. 1999-01-22 15:28:00 -02:00
Roberto Ierusalimschy
eec31aaca5 <string.h> is needed because of "memcpy". 1999-01-21 16:38:39 -02:00
Roberto Ierusalimschy
595738f6fe small optimizations 1999-01-20 18:22:06 -02:00
Roberto Ierusalimschy
b5eb4f3126 small optimization in getglobal 1999-01-15 11:14:24 -02:00
Roberto Ierusalimschy
3fecf187ff names... 1999-01-15 11:11:57 -02:00
Roberto Ierusalimschy
54840fb256 new functions to manipulate C global variables 1999-01-15 11:11:22 -02:00
Roberto Ierusalimschy
e87fddf1ad GC can be called during parsing, if needed. 1999-01-15 09:38:33 -02:00
Roberto Ierusalimschy
dea400bc1d "getstack" returns func, too. 1999-01-15 09:36:28 -02:00
Roberto Ierusalimschy
fb663f768d "%.16g" already formats integers as integers, so we do not need an
alternative "%ld" convertion in "tostring".
1999-01-13 17:09:04 -02:00
Roberto Ierusalimschy
e03767b3eb details (comments) 1999-01-13 17:08:37 -02:00
Roberto Ierusalimschy
8396027516 better precision when converting numbers to strings. 1999-01-12 16:38:35 -02:00
Roberto Ierusalimschy
e24f7fd2d2 details 1999-01-11 18:23:54 -02:00
Roberto Ierusalimschy
8081f39dab header missing. 1999-01-11 16:57:35 -02:00
Roberto Ierusalimschy
3cc4ca821e initialization module (to load libraries) 1999-01-08 14:49:32 -02:00
Roberto Ierusalimschy
01772cefa5 new library for debbuging 1999-01-08 14:47:44 -02:00
Roberto Ierusalimschy
dc90d4bce3 when handling signals (^C), deep old hook values. 1999-01-06 11:12:41 -02:00
Roberto Ierusalimschy
f5bc671030 "goto" for tail recursion changed to "while" 1999-01-04 15:34:49 -02:00
Roberto Ierusalimschy
d7294c6de8 double hashing for string tables. 1999-01-04 11:37:29 -02:00
Roberto Ierusalimschy
63a752f961 small improvements. 1999-01-04 11:37:07 -02:00
Roberto Ierusalimschy
03d38b66fd new sort algorithm. 1999-01-04 10:55:09 -02:00
Roberto Ierusalimschy
b9c9ccfbb4 function "move" for tables is better implemented with some "inside
information".
1999-01-04 10:54:33 -02:00
Roberto Ierusalimschy
b94110a68f bug: "format" does not check size of format item (such as "%00000...00000d"). 1999-01-04 10:53:24 -02:00
Roberto Ierusalimschy
8278468041 comments 1999-01-04 10:41:12 -02:00
Roberto Ierusalimschy
4fbb2531b3 don´t need the "+1", the "%" is enough to garantee r<1. 1998-12-30 19:23:26 -02:00
Roberto Ierusalimschy
59f8e6fb77 details ("settable") 1998-12-30 15:26:49 -02:00
Roberto Ierusalimschy
05d89b5c05 new option for function "random": random(a,b) returns a<=x<=b 1998-12-30 15:22:17 -02:00
Roberto Ierusalimschy
fe5c41fb8a new functions "tinsert" and "tremove" 1998-12-30 11:16:50 -02:00
Roberto Ierusalimschy
9a45543841 tables are better manipulated via "Hash *" instead of "TObject" or
"lua_Object".
1998-12-30 11:14:46 -02:00
Roberto Ierusalimschy
766e67ef3b to avoid warnings about "typecast" (Visual C++) 1998-12-28 11:44:54 -02:00
Roberto Ierusalimschy
4c94d8cc2c new function "luaO_str2d" to convert strings to numbers, because
old "lex" algorithm had aproximation errors, but strtod (and atof
and scanf) are too slow.
1998-12-27 18:25:20 -02:00
Roberto Ierusalimschy
d2de2d5eda format for double is always "%g", do not need #defines 1998-12-27 18:23:22 -02:00
Roberto Ierusalimschy
96a7695275 reorder and rename of most functions, for better documentation. 1998-12-27 18:22:36 -02:00
Roberto Ierusalimschy
63166c0ca0 new implementation of function "read", with predifined options. 1998-12-27 18:21:28 -02:00
Roberto Ierusalimschy
a881abfd1e "strtod" is cleaner than "scanf" for this job. 1998-12-24 12:57:23 -02:00
Roberto Ierusalimschy
d3ac7075a2 better error message 1998-12-23 12:06:57 -02:00
Roberto Ierusalimschy
0c9080c7a9 "tonumber" goes crazy with negative numbers in other bases (not 10),
because "strtol" returns long, not unsigned long.
1998-12-18 11:26:43 -02:00
Roberto Ierusalimschy
b8fcb7b151 details 1998-12-15 13:21:09 -02:00
Roberto Ierusalimschy
5d6de9075d "print" uses fputs instead of printf (easier to reimplement). 1998-12-15 12:59:59 -02:00
Roberto Ierusalimschy
21cff3015a details (for regularity) 1998-12-15 12:59:43 -02:00
Roberto Ierusalimschy
5ca2709ba0 small warnings 1998-12-03 13:45:15 -02:00
Roberto Ierusalimschy
bb1cb7b9f1 NUMBER_FMT also may be predefined in makefile 1998-12-01 17:09:47 -02:00
Roberto Ierusalimschy
c64f36ab2b better behavior for "strsub" when indices are out-of-range 1998-12-01 16:41:25 -02:00
Roberto Ierusalimschy
e4830ddce3 new option "mode" in "readfrom", "writeto" and "appendto" (for
binary files).
1998-11-20 13:41:43 -02:00
Roberto Ierusalimschy
758e330d6e new functions "getn" and "foreachi" 1998-11-13 14:48:48 -02:00
Roberto Ierusalimschy
8e3bd752bb small optimization in "sort" + new functions "getn" and "foreachi" 1998-11-13 14:39:18 -02:00
Roberto Ierusalimschy
a84bca67fc bug: gsub/strfind do not check whether captures are properly finished. 1998-11-10 17:38:12 -02:00
Roberto Ierusalimschy
4ccfb2f9bc "_TRIGMODE" was still being declared. 1998-09-08 16:25:35 -03:00
Roberto Ierusalimschy
ce9609296c function "luaL_argerror" prints wrong argument number (from a user's point
of view) when functions have upvalues.
1998-09-07 15:59:59 -03:00
Roberto Ierusalimschy
b1450721be new function "lua_nups" (number of upvalues). 1998-09-07 15:59:59 -03:00
Roberto Ierusalimschy
b04294d3d8 details. 1998-08-30 17:25:24 -03:00
Roberto Ierusalimschy
22c2704842 "lua_state" is already declared in lua.h, which is included here. 1998-08-30 15:28:58 -03:00
Roberto Ierusalimschy
ee22af5ced new functions "seek" and "flush". 1998-08-24 17:14:56 -03:00
Roberto Ierusalimschy
cc117253c8 new implementation for error handling: on error, function _ERRORMESSAGE
is called, which in turn calls _ALERT to write a message to stderr.
1998-08-21 14:43:44 -03:00
Roberto Ierusalimschy
8e226e6a09 small bug: nuse may change when table is rehashed;
3/2 is a good fraction for hash limit (instead of 0.7, using floats)
1998-08-11 13:38:34 -03:00
Roberto Ierusalimschy
1d420c2c11 better error message for code too long (old one was misleading when the
problem was SETLINE after 64k lines...)
1998-08-11 10:28:05 -03:00
Roberto Ierusalimschy
5378331f2d hash tables may shrink if use rate is too small. 1998-08-10 18:36:32 -03:00
Roberto Ierusalimschy
894a264671 new hash function. 1998-07-27 14:06:17 -03:00
Roberto Ierusalimschy
e1a127245d details ("luaX_token2str" doesn't need LexState) 1998-07-24 15:02:38 -03:00
Roberto Ierusalimschy
afb5ef72e1 new function "sort" + many small changes 1998-07-12 13:16:43 -03:00
Roberto Ierusalimschy
1d8edd347d small changes to use new auxiliar functions 1998-07-12 13:16:02 -03:00
Roberto Ierusalimschy
41d9ea948c auxiliar functions "luaH_setint" & "luaH_getint". 1998-07-12 13:15:19 -03:00
Roberto Ierusalimschy
ee912e5a7f auxiliar function "luaD_calln". 1998-07-12 13:14:34 -03:00
Roberto Ierusalimschy
ad446a0eb0 "%q" can handle strings with '\0'. 1998-07-12 13:13:45 -03:00
Roberto Ierusalimschy
176cb39feb macro encapsulates de "-". 1998-07-12 13:11:55 -03:00
Roberto Ierusalimschy
64ad009fb2 "fileName" cannot be NULL 1998-07-12 13:10:38 -03:00
Roberto Ierusalimschy
dcb1a08906 "exp" changed to "exp0" to avoid problems with math.h. 1998-07-06 19:07:51 -03:00
Roberto Ierusalimschy
1788501eed double constant used in integer expression 1998-07-06 19:04:58 -03:00
Roberto Ierusalimschy
bee1a5aeb2 spelling 1998-07-01 11:21:57 -03:00
Roberto Ierusalimschy
994aba062b when debuging, blocks must be kept in double allignment. 1998-06-29 19:03:06 -03:00
Roberto Ierusalimschy
e869d17eb1 functions should return explicit "nil"s. 1998-06-29 15:24:06 -03:00
Roberto Ierusalimschy
9a0221ef58 detail 1998-06-29 15:09:28 -03:00
Roberto Ierusalimschy
07008b5d45 details (by lhf) 1998-06-25 13:48:44 -03:00
Roberto Ierusalimschy
8f31eda649 details in comments 1998-06-25 11:37:00 -03:00
Roberto Ierusalimschy
da94130160 stupid bug (in syntax print "hello") 1998-06-24 11:48:15 -03:00
Roberto Ierusalimschy
468fbdbde7 details 1998-06-24 10:33:00 -03:00
Roberto Ierusalimschy
eb45f8b631 details (dependencies) 1998-06-19 15:52:27 -03:00
Roberto Ierusalimschy
df0df08bc5 "dostring" accepts chunk name. 1998-06-19 15:47:06 -03:00
Roberto Ierusalimschy
9618aaf07d small corrections in comments 1998-06-19 13:14:09 -03:00
Roberto Ierusalimschy
bec9bc4154 sugestions by lhf 1998-06-18 14:36:27 -03:00
Roberto Ierusalimschy
955a811aa1 category for "setlocale" is given by name 1998-06-18 14:04:28 -03:00
Roberto Ierusalimschy
c9902be294 "findname" moved from lobject.c to lauxlib.c (so libraries may use it). 1998-06-18 13:57:03 -03:00
Roberto Ierusalimschy
112c9d53ab new version by lhf 1998-06-18 13:52:04 -03:00
Roberto Ierusalimschy
0789451458 details 1998-06-18 13:51:53 -03:00
Roberto Ierusalimschy
d97af0de26 "lua_dobuffer" gets an extra argument, with the chunk name 1998-06-15 18:34:14 -03:00
Roberto Ierusalimschy
1917149fdd details. 1998-06-11 15:21:37 -03:00
Roberto Ierusalimschy
0845e73b6a new copyright notice 1998-06-06 18:05:52 -03:00
Roberto Ierusalimschy
7dfa952091 no more error for '\x' (with "invalid" x) 1998-06-06 17:44:05 -03:00
Roberto Ierusalimschy
02134b4a87 name: lua_pushCclosure -> lua_pushcclosure. 1998-06-05 19:17:44 -03:00
Roberto Ierusalimschy
bdb1db4d37 "read" more efficient when reading lines and whole files ('.*') 1998-06-02 18:20:54 -03:00
Roberto Ierusalimschy
02a6891939 API for functions to manipulate global state. 1998-06-02 17:37:04 -03:00
Roberto Ierusalimschy
741c6f5006 'dobuffer' addpoted. 1998-05-31 19:22:00 -03:00
Roberto Ierusalimschy
6152973f9c new names for 'ascii' ('strbyte') and 'int2str' ('strchar') 1998-05-31 19:20:45 -03:00
Roberto Ierusalimschy
243a808067 'print' now calls 'tostring' 1998-05-31 19:19:35 -03:00
Roberto Ierusalimschy
62c36a6056 better error message when '^' is not defined. 1998-05-31 19:18:24 -03:00
Roberto Ierusalimschy
74719afc33 new functions "frexp" and "ldexp" 1998-05-27 16:09:39 -03:00
Roberto Ierusalimschy
7e59a8901d NEW LL(1) PARSER 1998-05-27 10:08:34 -03:00
Roberto Ierusalimschy
abc6eac404 new function "clock" 1998-05-20 19:21:35 -03:00
Roberto Ierusalimschy
054e0b888a number type in Lua changed for double (by default). 1998-05-18 19:26:03 -03:00
Roberto Ierusalimschy
da252eeff7 arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int. 1998-05-18 19:21:55 -03:00
Roberto Ierusalimschy
9890bedaab details (format for html) 1998-04-02 13:09:16 -03:00
Roberto Ierusalimschy
0a0c9593b8 many small corrections; strings with '\0' 1998-03-30 15:17:55 -03:00
Roberto Ierusalimschy
d470792517 words are stored in hi-lo order (easier to print) 1998-03-30 10:57:23 -03:00
Roberto Ierusalimschy
439236773b changes by lhf 1998-03-26 11:50:19 -03:00
Roberto Ierusalimschy
2a2b64d6ac opcode "CLOSURE" gets the prototipe (instead of a previous pushconstant) 1998-03-25 15:52:29 -03:00
Roberto Ierusalimschy
daa937c043 pattern-matching support for '\0'. 1998-03-24 17:14:25 -03:00
Roberto Ierusalimschy
21455162b5 details (and new escape sequences: \a, \b, ...) 1998-03-20 11:18:18 -03:00
Roberto Ierusalimschy
99cc4b20f2 details 1998-03-11 10:59:50 -03:00
Roberto Ierusalimschy
0969a971cd better use of "ASSERT". 1998-03-09 18:49:52 -03:00
Roberto Ierusalimschy
be6d215f67 BUG: gsub('a', '(b?)%1*' ...) loops (because the capture is empty). 1998-03-09 15:28:08 -03:00
Roberto Ierusalimschy
e74817f8aa correct way to handle string delimiters 1998-03-09 14:22:49 -03:00
Roberto Ierusalimschy
043c2ac258 new names for "lua_pushlstr" and "lua_getstrlen" 1998-03-06 15:47:42 -03:00
Roberto Ierusalimschy
88a2023c32 support for strings with '\0' 1998-03-06 13:54:42 -03:00
Roberto Ierusalimschy
5ef1989c4b "settag" returns its first argument. 1998-02-12 17:27:10 -02:00
Roberto Ierusalimschy
f380d627f8 usefull macros also available as functions 1998-02-12 17:23:32 -02:00
Roberto Ierusalimschy
aafa106d10 implementation of numerical escape sequences in strings ("\12");
better error messages for wrong tokens
1998-02-11 18:56:46 -02:00
Roberto Ierusalimschy
29b7b8e52c better error messages for wrong tokens 1998-02-11 18:56:46 -02:00
Roberto Ierusalimschy
a9dd2c6717 interrupts lua loops with "^C" (via signals) 1998-02-11 18:56:05 -02:00
Roberto Ierusalimschy
aee3f97acb put back quotes (") when string in dostring ends with a \n 1998-01-29 13:59:35 -02:00
Roberto Ierusalimschy
46968b8ffa "volatile is the only reliable way to ensure that a local variable
retains the value it had at the time of the call to longjmp"
1998-01-28 15:47:05 -02:00
Roberto Ierusalimschy
6cdf0d8768 tables can become full of "emptys" slots, and keep growing without limits. 1998-01-28 14:50:33 -02:00
Roberto Ierusalimschy
07ff251a17 details in "dostring" identification 1998-01-27 19:21:27 -02:00
Roberto Ierusalimschy
b3b7cf7335 BUG: "lua_getstring" may create a new string, so should check GC 1998-01-27 17:13:45 -02:00
Roberto Ierusalimschy
8622dc18bf bug: format size limits with little problems 1998-01-27 17:11:36 -02:00
Roberto Ierusalimschy
d22e2644dd wrong line number (+1) in error report when file starts with "#..." 1998-01-19 18:18:02 -02:00
Roberto Ierusalimschy
f529a22ca5 BUG: wrong line number (+1) in error report when file starts with "#..." 1998-01-19 18:18:02 -02:00
Roberto Ierusalimschy
783ba75129 needs "stdlib.h" (calls "exit") 1998-01-19 17:49:49 -02:00
Roberto Ierusalimschy
d49e4dd752 MAX_WORD should not be bigger than MAX_INT 1998-01-19 17:49:22 -02:00
Roberto Ierusalimschy
981fddea02 module to load bytecodes from files. 1998-01-14 13:49:01 -02:00
Roberto Ierusalimschy
81b953f27e details 1998-01-14 11:49:44 -02:00
Roberto Ierusalimschy
b9acf4b4af "strcoll" may not exist in ond ansi machines 1998-01-14 11:49:15 -02:00
Roberto Ierusalimschy
44ace0aefd we don't need a type "Word". 1998-01-14 11:48:28 -02:00
Roberto Ierusalimschy
5981161360 small optimizations (?) 1998-01-13 16:06:27 -02:00
Roberto Ierusalimschy
763c64be9b details 1998-01-13 13:42:43 -02:00
Roberto Ierusalimschy
f0dffaa209 new way to hanlde arg information 1998-01-12 11:35:37 -02:00
Roberto Ierusalimschy
77a6836fef we don't need a type "Word". 1998-01-12 11:00:51 -02:00
Roberto Ierusalimschy
9f043e8017 luaL_arg_check now is inlined 1998-01-09 13:09:53 -02:00
Roberto Ierusalimschy
6ac047afc4 details 1998-01-09 12:57:43 -02:00
Roberto Ierusalimschy
0e1058cfdd small optimizations in switch order 1998-01-09 12:44:55 -02:00
Roberto Ierusalimschy
26679b1a48 back to upavalues as extra arguments for C closures; this way it's
trivial to make currying.
1998-01-07 14:26:48 -02:00
Roberto Ierusalimschy
e04c2b9aa8 details 1998-01-06 17:17:31 -02:00
Roberto Ierusalimschy
0c031dcc8b details 1998-01-05 15:12:54 -02:00
Roberto Ierusalimschy
c332c4e927 reference manual of the Lua language 1998-01-02 16:34:00 -02:00
Roberto Ierusalimschy
964c503a63 LUA_COMPAT2.5 may use #ifdef instead of #if 1998-01-02 15:46:32 -02:00
Roberto Ierusalimschy
90d87e3a78 details 1997-12-30 17:15:52 -02:00
Roberto Ierusalimschy
f76bca23ef variants for "ARGS". 1997-12-30 17:08:23 -02:00
Roberto Ierusalimschy
a5fd7d722c opctional "base" in "tonumber" convertion. 1997-12-30 15:57:45 -02:00
Roberto Ierusalimschy
4e0bf95622 variant opcodes for PUSHSELF 1997-12-29 15:35:46 -02:00
Roberto Ierusalimschy
498a934abf new syntax possibilities: f(x).x, etc; on the other hand,
"function ... (x)" now is more restricted.
1997-12-29 15:28:45 -02:00
Roberto Ierusalimschy
ce53872684 new syntax: f´s´ for f(´s´). 1997-12-28 20:48:15 -02:00
Roberto Ierusalimschy
da96eb2cce some details related to OLD_ANSI 1997-12-26 16:38:16 -02:00
Roberto Ierusalimschy
fada8efd01 "rand()", in SunOS, may return values bigger than "RAND_MAX"... 1997-12-26 16:36:31 -02:00
Roberto Ierusalimschy
d916487d7c auxlib split in two parts (lauxlib and lbuffer) 1997-12-23 17:24:36 -02:00
Roberto Ierusalimschy
1bf762ba38 Generic buffer facilities for Lua (and libraries) 1997-12-23 17:24:36 -02:00
Roberto Ierusalimschy
541e722360 details 1997-12-23 17:24:19 -02:00
Roberto Ierusalimschy
807ba6301c error method *always* gets a string (otherwise it is not called at all) 1997-12-23 10:50:49 -02:00
Roberto Ierusalimschy
03f3f9e707 "zio" now keeps its "name". 1997-12-22 18:57:18 -02:00
Roberto Ierusalimschy
a78eecee48 details (aborts with invalid arguments) 1997-12-22 18:03:50 -02:00
Roberto Ierusalimschy
43461d267f help message 1997-12-22 16:05:23 -02:00
Roberto Ierusalimschy
fae0b52825 small bugs in error report 1997-12-22 15:52:20 -02:00
Roberto Ierusalimschy
22439a7511 new syntax for constructors (a={n=3;1,2,3}). 1997-12-22 15:24:11 -02:00
Roberto Ierusalimschy
7ecc3ce827 new command line options 1997-12-19 16:34:23 -02:00
Roberto Ierusalimschy
4e91384e14 sorting the includes... 1997-12-18 17:11:43 -02:00
Roberto Ierusalimschy
de79e7fc58 back to "lua_upvalue"... (seems better choice) 1997-12-18 16:32:39 -02:00
Roberto Ierusalimschy
8b5b42563c "lua_dobuffer" (is not official, but its there...) 1997-12-17 18:57:20 -02:00
Roberto Ierusalimschy
502343b402 new scheme for buffers, centralized in auxlib. 1997-12-17 18:48:58 -02:00
Roberto Ierusalimschy
82d09fbf0d new structure for closures, without static variables. 1997-12-15 15:58:49 -02:00
Roberto Ierusalimschy
9be85d1648 new year 1997-12-15 15:47:55 -02:00
Roberto Ierusalimschy
45e533599f optimization: closures without upvalues don't need to be closures 1997-12-15 14:17:20 -02:00
Roberto Ierusalimschy
94144a7821 otimization: closures without upvalues don't need to be closures 1997-12-15 14:17:20 -02:00
Roberto Ierusalimschy
4daae2165d new API function and built-in "lua_copytagmethods" 1997-12-11 15:21:11 -02:00
Roberto Ierusalimschy
cdd261f332 new option "-q" (quiet), and multi-line commands (ending with '\') 1997-12-11 15:00:21 -02:00
Roberto Ierusalimschy
034f16892e better treatment of MARKs and DEBUG cases. 1997-12-11 12:48:46 -02:00
Roberto Ierusalimschy
c759520bc8 safer way to put #defines in error messages... 1997-12-09 14:01:08 -02:00
Roberto Ierusalimschy
80b3d28f4a details (mainly error messages) 1997-12-09 11:50:08 -02:00
Roberto Ierusalimschy
69d97712ec arguments "var=value" doesn't need quotes for value 1997-12-03 17:57:54 -02:00
Roberto Ierusalimschy
5d89dad9b8 bug log 1997-12-02 10:46:15 -02:00
Roberto Ierusalimschy
525a91fed3 BUG: "lastline" was not reset on function entry, so debug information
started only in the 2nd line of a function.
1997-12-02 10:43:54 -02:00
Roberto Ierusalimschy
868d16dee0 comments 1997-12-02 10:43:44 -02:00
Roberto Ierusalimschy
3393fd7f25 first version of "lua_close" 1997-12-01 18:31:25 -02:00
Roberto Ierusalimschy
00c122cc29 other distribution of memory debug information. 1997-12-01 18:30:44 -02:00
Roberto Ierusalimschy
03160920cf store "functofind" in stack top, so doesn't need this field in
global state.
1997-11-28 14:56:05 -02:00
Roberto Ierusalimschy
b42cc6a4d2 no more protected global variables; using upvalues to store tags. 1997-11-28 10:40:37 -02:00
Roberto Ierusalimschy
a6ad644bf2 no more protected global variables 1997-11-28 10:39:45 -02:00
Roberto Ierusalimschy
39fd5bb9b0 details 1997-11-28 10:39:22 -02:00
Roberto Ierusalimschy
5482992dec other access method for C upvalues (as arguments) 1997-11-27 16:25:14 -02:00
Roberto Ierusalimschy
024528e0c2 global variables starting with '.' are protected in Lua (temporarily at
least...)
1997-11-27 13:59:44 -02:00
Roberto Ierusalimschy
ef37c87e93 no more 'globalbag' 1997-11-27 13:59:25 -02:00
Roberto Ierusalimschy
9e029f98b9 details 1997-11-26 18:44:52 -02:00
Roberto Ierusalimschy
e962330df9 "stacklimit" is not necessary. 1997-11-26 18:28:22 -02:00
Roberto Ierusalimschy
b291e50006 extra argument for "assert" 1997-11-26 17:40:27 -02:00
Roberto Ierusalimschy
9ae0c082a3 small details by lint. 1997-11-26 16:53:45 -02:00
Roberto Ierusalimschy
accd7bc253 small modifications (format, small optimizations, etc) 1997-11-21 17:00:46 -02:00
Roberto Ierusalimschy
6153200bc2 make sure there is no mem problems, using %.ns instead of %s for luaV_error. 1997-11-19 16:16:33 -02:00
Roberto Ierusalimschy
2e7595522d allows '\r' at the end of pragmas, so one can mix Windows and Unix files 1997-11-19 15:35:47 -02:00
Roberto Ierusalimschy
b79ffdc4ce global state for Lua interpreter 1997-11-19 15:31:19 -02:00
Roberto Ierusalimschy
592a3f289b first implementation of centralized global state. 1997-11-19 15:29:23 -02:00
Roberto Ierusalimschy
9cdeb275e7 details 1997-11-10 15:47:01 -02:00
Roberto Ierusalimschy
c957b270d2 "call" now handles errors (instead of "dostring") 1997-11-07 16:19:13 -02:00
Roberto Ierusalimschy
92791b9dd6 small details 1997-11-07 13:09:49 -02:00
Roberto Ierusalimschy
45cad43c3f "lua_open": now lua has an explicit open operation. 1997-11-04 13:27:53 -02:00
Roberto Ierusalimschy
dad5a01fb0 trigonometric mode stored in a Lua global variable. 1997-11-03 19:11:44 -02:00
Roberto Ierusalimschy
66713181c1 no need of "emergency error"... 1997-11-03 19:00:23 -02:00
Roberto Ierusalimschy
7135803cc8 "global" version of a nil object. 1997-11-03 18:45:23 -02:00
Roberto Ierusalimschy
b7567b6673 "read" & "write" may receive a file handler as first argument 1997-10-30 18:29:09 -02:00
Roberto Ierusalimschy
f8c95fa9e8 new "block" syntax (DO ... END) 1997-10-30 16:47:19 -02:00
Roberto Ierusalimschy
9c965d0ffb more precise error messages for compiler limits. 1997-10-28 15:26:53 -02:00
Roberto Ierusalimschy
6103dca8ee small bug. 1997-10-27 14:14:37 -02:00
Roberto Ierusalimschy
18cd7adac6 optimization to handle <a.x> (new opcode). 1997-10-24 16:40:29 -02:00
Roberto Ierusalimschy
41223a01ec definition of "PI" and modes for angles. 1997-10-24 15:44:22 -02:00
Roberto Ierusalimschy
e78cf96c97 first version of Cclosures. 1997-10-24 15:17:24 -02:00
Roberto Ierusalimschy
0cb3843956 "foreach" and "foreachvar" more robust (to survive GCs), and with
termination test.
1997-10-23 14:28:48 -02:00
Roberto Ierusalimschy
907368ead5 GC now considers an "estimate" of object size, instead of just the number
of objects.
1997-10-23 14:26:37 -02:00
Roberto Ierusalimschy
81489beea1 functions may use many upvalues, to keep global values. 1997-10-18 14:46:39 -02:00
Roberto Ierusalimschy
ac30aad09b new functions "foreach" and "foreachvar" 1997-10-18 14:33:36 -02:00
Roberto Ierusalimschy
2c89651fc6 macro "val" should live together with macro "ref". 1997-10-18 14:29:15 -02:00
Roberto Ierusalimschy
3a89c973ff details 1997-10-16 19:14:47 -02:00
Roberto Ierusalimschy
52d5e8032c better identification of types which are tags 1997-10-16 18:07:40 -02:00
Roberto Ierusalimschy
19c178fa14 new (smaller) prompt 1997-10-16 16:35:59 -02:00
Roberto Ierusalimschy
45ccb0e881 "nupvalues" is kept in Closure, not in prototype (as a preparation
for C closures...)
1997-10-16 08:59:34 -02:00
Roberto Ierusalimschy
4be18fa889 details 1997-10-15 18:16:00 -02:00
Roberto Ierusalimschy
7c261a13b5 more uniform treatment to opcode variants. 1997-10-13 20:12:04 -02:00
Roberto Ierusalimschy
2bb94d9e22 using bison instead of yacc; lparser.c renamed to lstx.c (to
avoid confusion with lparser.h...)
1997-10-13 20:10:45 -02:00
Roberto Ierusalimschy
a3235ad270 prompt for interactive mode 1997-10-06 12:51:32 -02:00
Roberto Ierusalimschy
f6a9cc9a67 jumps are relative to next instruction 1997-10-06 12:51:11 -02:00
Roberto Ierusalimschy
28d47a0aaa all jumps have byte variants; WHILE optimization 1997-10-01 17:05:34 -03:00
Roberto Ierusalimschy
eb617df2d8 better way to traverse GCnode lists. 1997-09-26 13:46:20 -03:00
Roberto Ierusalimschy
a580480b07 new implementation for globals: Global value is stored in TaggedString 1997-09-26 12:02:26 -03:00
Roberto Ierusalimschy
0dd6d1080e new opcode variants. 1997-09-24 16:43:11 -03:00
Roberto Ierusalimschy
3c820d622e better control over closed files 1997-09-23 11:12:44 -03:00
Roberto Ierusalimschy
d6c867ea50 better way to cope with opcode variants 1997-09-22 17:53:20 -03:00
Roberto Ierusalimschy
2079cfe8fa new way to code globals, using const table instead of putting global
index inside the opcode.
1997-09-19 18:17:52 -03:00
Roberto Ierusalimschy
dfe03c7abe small optimizations (bit scrubbing) 1997-09-19 15:40:32 -03:00
Roberto Ierusalimschy
8cd67ac676 Syntax analizer and code generator 1997-09-16 16:33:21 -03:00
Roberto Ierusalimschy
9828893f7e Makefile 1997-09-16 16:33:21 -03:00
Roberto Ierusalimschy
6990da0057 Lua virtual machine 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
d985dc0629 Opcodes for Lua virtual machine 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
451124005b Standard I/O (and system) library 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
2f1fa3d427 Type definitions for Lua objects 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
189d64409b Garbage Collector 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
60cc473bcf Lexical Analizer 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
43a2ee6ea1 Stack and Call structure of Lua 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
4b91e9cde6 Tag methods 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
26c5f56ad1 Built-in functions 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
daa858ef27 String table (keep all strings handled by Lua) 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
ea169d2083 auxiliar functions from Lua API 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
c31aa863ac Auxiliar functions for building Lua libraries 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
ff08b0f406 Lua Function structures 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
c1801e623f Some generic functions over Lua objects 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
a404f6e0e6 Lua tables (hash) 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
2d2440a753 Lua stand-alone interpreter 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
0c4ed2b3dc main header file 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
b945fae40e Lua standard mathematical library 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
dadba4d6ed Interface to Memory Manager 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
d600a6b5b3 a generic input stream interface 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
75ac0d2172 Standard library for strings and pattern-matching 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
9f3785a2f3 Lua standard libraries 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
84e92e0976 Debuging API 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
b8a049abed Global variables 1997-09-16 16:25:59 -03:00
Roberto Ierusalimschy
e18f681333 very small corrections... 1997-09-16 16:01:10 -03:00
Roberto Ierusalimschy
dd1aa28390 small optimization in opcodes for "and" and "or" 1997-08-04 16:15:05 -03:00
Roberto Ierusalimschy
abbf14cd32 small optimizations; try to find previous use when coding a real constant. 1997-07-31 17:46:59 -03:00
Roberto Ierusalimschy
e8292f076d new dependencies 1997-07-31 17:45:25 -03:00
Roberto Ierusalimschy
3037dccaf6 prime numbers spread better. 1997-07-31 17:44:46 -03:00
Roberto Ierusalimschy
a7793468aa correct support for changing real to double (optional) 1997-07-31 16:37:37 -03:00
Roberto Ierusalimschy
caa987faad "random" accepts an 'n' to return between 1 and 'n'. 1997-07-30 19:15:18 -03:00
Roberto Ierusalimschy
0892f0e5b7 BIG CHANGE: functions have their own "constant table". 1997-07-30 19:00:50 -03:00
Roberto Ierusalimschy
1d7857bc63 free(b) is equivalent to realloc(b, 0) 1997-07-30 15:29:08 -03:00
Roberto Ierusalimschy
72a1d81b51 bug: lua_getlocal breaks when called with a CFunction. 1997-07-29 18:11:10 -03:00
Roberto Ierusalimschy
2c580a0afb new way to handle global state during compilation. 1997-07-29 17:38:45 -03:00
Roberto Ierusalimschy
05e8b0ae80 new opcode, ENDCODE, to signal end of code vector. 1997-07-29 17:38:06 -03:00
Roberto Ierusalimschy
16dd77e8d9 unused field "size" in struct TFunc. 1997-07-29 16:44:02 -03:00
Roberto Ierusalimschy
0600f968c3 BUG: LUA_COMPAT2_5 written wrong... 1997-07-29 10:35:06 -03:00
Roberto Ierusalimschy
971b1d557d bug log. Most of the log is done automatically by RCS, and not in
the file itself :-)
1997-07-29 10:34:15 -03:00
Roberto Ierusalimschy
11d97c34d5 skipping of '#' in first line is done by lex.c. 1997-07-29 10:33:15 -03:00
Roberto Ierusalimschy
66be42549e BUG: files starting with '#' get wrong line numbers 1997-07-07 18:05:51 -03:00
Roberto Ierusalimschy
067db30d71 "next" & "nextvar" check if argument is a result of previous calls 1997-07-07 13:44:26 -03:00
Roberto Ierusalimschy
da4dbe65b2 new functionality for "format": "%d$...". 1997-07-04 19:35:38 -03:00
Roberto Ierusalimschy
4321fde2a7 error inside an error method could break the stack. 1997-07-04 11:55:37 -03:00
Roberto Ierusalimschy
8f3df1d471 small details. 1997-07-02 15:50:18 -03:00
Roberto Ierusalimschy
1a17211707 auxliar support for "locale" (to avoid portability problems) 1997-07-02 15:45:09 -03:00
Roberto Ierusalimschy
d56e3a6481 "locale" support + better uniformity in formating 1997-07-02 14:09:48 -03:00
Roberto Ierusalimschy
7820a47184 LOCALE support 1997-07-01 16:32:41 -03:00
Roberto Ierusalimschy
88b185ada1 more uniform source (more macros...) 1997-07-01 14:41:34 -03:00
Roberto Ierusalimschy
ef3c45d523 for security reasons, one cannot change the tag of a udata
from Lua.
1997-06-27 19:38:49 -03:00
Roberto Ierusalimschy
20a48a818f a file handle must be a userdata. 1997-06-27 19:38:49 -03:00
Roberto Ierusalimschy
c9e6ed1d9f small corrections. 1997-06-27 15:39:34 -03:00
Roberto Ierusalimschy
56fdab67d8 believe it or not, this makes a difference... 1997-06-26 18:40:57 -03:00
Roberto Ierusalimschy
3a98c8670d new name for _VERSION (standard of _UPPERCASES for pre-defined
global variable)
1997-06-26 17:47:43 -03:00
Roberto Ierusalimschy
da585783e3 new method to handle current files, with global variables
_INPUT and _OUTPUT.
1997-06-26 17:39:10 -03:00
Roberto Ierusalimschy
e81f184164 new #define LUA_COMPAT2_5 to select "compatibility mode". 1997-06-23 15:27:53 -03:00
Roberto Ierusalimschy
3e43275308 incompatibilities with 2.5 + restrictions on tag methods 1997-06-20 16:28:16 -03:00
Roberto Ierusalimschy
f97307b548 zio should not care about how a user creates a FILE (pipe, socket, popen,
etc).
1997-06-20 16:25:54 -03:00
Roberto Ierusalimschy
6402bfb1f8 better error message for dostring (2nd argument) 1997-06-20 16:19:09 -03:00
Roberto Ierusalimschy
27b6bbdcf3 "testC" inactive (active only for tests) 1997-06-19 15:55:40 -03:00
Roberto Ierusalimschy
5a198de3c1 new prefix luaZ 1997-06-19 15:55:28 -03:00
Roberto Ierusalimschy
c5d7ba7347 dostring has an optional error method argument 1997-06-19 15:49:40 -03:00
Roberto Ierusalimschy
f84c2ebc4a dostring has an optional error method argument;
counter for gsub only when there is a table (to keep full compatibility)
1997-06-19 15:49:40 -03:00
Roberto Ierusalimschy
c8897f2b08 counter for gsub only when there is a table (to keep full compatibility) 1997-06-19 15:49:40 -03:00
Roberto Ierusalimschy
6bb2cac3db setparsedfile is extern; luaz_... changed to luaZ_... 1997-06-19 15:04:34 -03:00
Roberto Ierusalimschy
88f020b626 new interface to "lua_seterrormethod" and "lua_settagmethod", to
allow the use of Lua functions too.
1997-06-19 15:03:04 -03:00
Roberto Ierusalimschy
a38f093f05 luaI_initTFunc initializes fileName. 1997-06-19 14:46:12 -03:00
Roberto Ierusalimschy
b6adfdd01b gsub aborts if error occurs. 1997-06-19 14:45:28 -03:00
Roberto Ierusalimschy
b90b4bbd3a macros don't need prototypes. 1997-06-18 18:39:56 -03:00
Roberto Ierusalimschy
f6d95140ae using old version functions. 1997-06-18 18:20:45 -03:00
Roberto Ierusalimschy
eca17b24ea #if wraps compatibility issue 1997-06-18 18:20:45 -03:00
Roberto Ierusalimschy
6b61582e47 do not use $...$ to italic. 1997-06-18 18:11:53 -03:00
Roberto Ierusalimschy
60bdc370d9 new functions lua_doFILE and lua_dobuffer to help users... 1997-06-18 17:35:49 -03:00
Roberto Ierusalimschy
b9e31f73ee exported functions follow "lua" prefix rule. 1997-06-18 17:30:52 -03:00
Roberto Ierusalimschy
ea98620d98 new arguments for gsub 1997-06-18 17:15:47 -03:00
Roberto Ierusalimschy
6b78040840 lhf corrections + new gsub 1997-06-18 17:14:52 -03:00
Roberto Ierusalimschy
e931c7c0f6 error message always shows file names. 1997-06-18 14:33:30 -03:00
Roberto Ierusalimschy
70160320b1 first version for Lua 3.0 (with tag methods, etc) 1997-06-17 15:45:16 -03:00
Roberto Ierusalimschy
bfbf56f15a extra parameter for "call" is "pack" or "plain". 1997-06-17 15:44:31 -03:00
Roberto Ierusalimschy
732ef82c72 "luaI_undump1" cannot be static; luac uses it. 1997-06-17 15:19:17 -03:00
Roberto Ierusalimschy
2a1da64872 "lua_getobjname" must return "tag-method" and not "fallback". 1997-06-17 15:09:31 -03:00
Roberto Ierusalimschy
3c5d71cf77 "nil" may have fallbacks too. 1997-06-17 14:27:07 -03:00
Roberto Ierusalimschy
1848bcc15b "strsub" accepts negative indices (count from the end of the string). 1997-06-16 17:29:59 -03:00
Roberto Ierusalimschy
4d2de484f6 "lua_seterrormethod" should return the previous handler. 1997-06-16 16:48:18 -03:00
Roberto Ierusalimschy
312f78d925 default error method is not nil (nil does nothing). 1997-06-16 15:43:19 -03:00
Roberto Ierusalimschy
e4b69d6c9c "order" and "concat" operations choose tag methods the same way that
"arith" operations do (first the first parameter, etc).
1997-06-16 15:42:32 -03:00
Roberto Ierusalimschy
c9a2dfeb2c using "zio" for parsing Lua code. 1997-06-16 13:50:22 -03:00
Roberto Ierusalimschy
9fe5be3acf library for uniform buffered input. 1997-06-16 13:50:22 -03:00
Roberto Ierusalimschy
611680af08 functions "lua_settagmethod" and similars should be safe too. 1997-06-12 15:27:29 -03:00
Roberto Ierusalimschy
cb1d8f0fa0 missing small dependency. 1997-06-11 15:57:00 -03:00
Roberto Ierusalimschy
33f4fef410 BUG: did not handle properly pragmas $endinput/$debug inside a $if. 1997-06-11 15:56:02 -03:00
Roberto Ierusalimschy
e77534c08f small 'improvement' 1997-06-11 11:24:40 -03:00
Roberto Ierusalimschy
a22b54bbb6 format more uniform, to facilitate filters .tex->.html 1997-06-09 15:16:33 -03:00
Roberto Ierusalimschy
414ebe8ce1 power method (^) acts only in numbers. 1997-06-09 14:30:10 -03:00
Roberto Ierusalimschy
33ace03b5a udata is just void * again, so there is no point for function "getbyte". 1997-06-09 14:29:45 -03:00
Roberto Ierusalimschy
085181a08a new function "testC", to help debug the API. 1997-06-09 14:29:16 -03:00
Roberto Ierusalimschy
dd22ea4da5 new implementation for udata (again they are just void *);
new implementation for the API: most operations now do not disturb
structures lua2C and C2lua.
1997-06-09 14:28:14 -03:00
Roberto Ierusalimschy
5fdcfeb353 new lua_Objects are created below the C2lua stack, so most API functions
don't need to adjust stack.
1997-06-06 17:54:40 -03:00
Roberto Ierusalimschy
d68d8287aa new lua_Objects are created below the C2lua stack, so most API functions
don't need to adjust stack. So lua_getref does not change the stack,
and lua_pushref can use it as a macro.
1997-06-06 17:54:40 -03:00
Roberto Ierusalimschy
e1249970c2 new API function to force garbage collection. 1997-05-26 11:42:51 -03:00
Roberto Ierusalimschy
9d6f4e48a6 unused declaration. 1997-05-26 11:42:36 -03:00
Roberto Ierusalimschy
b546a042e8 another (better?) implementation for "pushsubscript". 1997-05-26 11:23:55 -03:00
Roberto Ierusalimschy
bd9e68cfcd new implementation of gc: "Pre-collect" garbage in temporary lists and
then call fallbacks.
1997-05-14 15:38:29 -03:00
Roberto Ierusalimschy
9747f3c87a double hashing + tables do not grow if there are empty slots 1997-05-08 17:43:30 -03:00
Roberto Ierusalimschy
12d9731a49 bug: string table must be initialized. 1997-05-05 17:21:23 -03:00
Roberto Ierusalimschy
4aade854bb correction of name (and "iternal" was wrong, any way). 1997-04-30 16:55:47 -03:00
Roberto Ierusalimschy
369dd65318 small optimization in the access to i.m. table. 1997-04-24 19:59:57 -03:00
Roberto Ierusalimschy
209602ac31 BUG: input file must be closed just after parser. 1997-04-15 14:32:47 -03:00
Roberto Ierusalimschy
6251d889ca missing definition of "lua_storesubscript", for compatibility 1997-04-15 13:52:20 -03:00
Roberto Ierusalimschy
faec0b0824 new pragma "$endinput" 1997-04-14 16:08:09 -03:00
Roberto Ierusalimschy
64d93e7cf9 global variables (in $if) may have '_'. 1997-04-14 12:30:29 -03:00
Roberto Ierusalimschy
d73c5bcfe7 function name is only needed *if* there is an error. 1997-04-14 12:30:03 -03:00
Luiz Henrique de Figueiredo
e78c1c54aa mem.h is now luamem.h
removed warn
added support for new opcodes (VARARGS, STOREMAP)
better error messages with luaL_verror
1997-04-14 09:12:40 -03:00
Luiz Henrique de Figueiredo
42049b42f1 fix comment in VERSION 1997-04-14 09:12:40 -03:00
Roberto Ierusalimschy
a8cd072c76 nested "$if's", "$else", and "$if" constants (nil & 1). 1997-04-12 12:01:49 -03:00
Roberto Ierusalimschy
83e9897cf0 correction on comments about opcodes. 1997-04-11 18:34:53 -03:00
Roberto Ierusalimschy
f93704728f one cannot "create" a userdata. 1997-04-08 12:41:44 -03:00
Roberto Ierusalimschy
c9e3d32182 first implementation of "$if";
new function "findstring" (useful in good places)
1997-04-07 11:48:53 -03:00
Roberto Ierusalimschy
00050b8a6b detail: local names 1997-04-06 11:17:06 -03:00
Roberto Ierusalimschy
19a1e19ae1 detail: better way to put a "..." in message. 1997-04-06 11:14:27 -03:00
Roberto Ierusalimschy
3a9516ffc8 luaL check functions do not need the function name (it can be
accessed via luadebug interface).
1997-04-06 11:08:08 -03:00
Roberto Ierusalimschy
42fa305649 better error messages;
better names for some API functions.
1997-04-04 19:24:51 -03:00
Roberto Ierusalimschy
9319735744 using new lib auxlib. 1997-04-04 12:35:37 -03:00
Roberto Ierusalimschy
1ea6e8064c "setintmethod" returns old method (to be coerent with seterrormethod).
BUG: wrong pointer arithmetic (index out of range when comparing).
obs: version 4 is due to internal methods.
1997-04-03 15:27:06 -03:00
Roberto Ierusalimschy
c1746340c3 obs: version 4 is due to internal methods.
(some small details in comments)
1997-04-03 15:26:08 -03:00
Roberto Ierusalimschy
d0339e7b72 "setintmethod" returns old method (to be coerent with seterrormethod).
obs: version 2 is due to internal methods.
1997-04-03 15:24:23 -03:00
Roberto Ierusalimschy
075b7918c3 new function "getintmethod" 1997-04-02 20:04:12 -03:00
Roberto Ierusalimschy
7c99149a76 "tostring" gives an overview of a userdata. 1997-04-02 19:53:35 -03:00
Roberto Ierusalimschy
27d95f1880 "newtag" does not need a type name. 1997-04-02 19:52:42 -03:00
Roberto Ierusalimschy
f0d523887d lua_getuserdata must return NULL if object is not userdata 1997-04-02 14:44:18 -03:00
Roberto Ierusalimschy
f29fbf2bf6 lua_getuserdata must return NULL if object is not userdata;
small BUG: wrong error message for a=b[1] (b not a table)
1997-04-02 14:44:18 -03:00
Roberto Ierusalimschy
4355e1afcd "getbyte" returns userdata size when called without second parameter. 1997-04-02 14:44:18 -03:00
Roberto Ierusalimschy
cae1eff901 small "bugs" detected by Purify: cannot read "next" after 0. 1997-04-01 18:23:20 -03:00
Roberto Ierusalimschy
f83bc86e51 small "bugs" detected by Purify: some blocks may be smaller than
sizeof(int).
1997-04-01 18:23:20 -03:00
Roberto Ierusalimschy
59744f0311 "storeglobal" changed to "setglobal" 1997-04-01 16:02:43 -03:00
Roberto Ierusalimschy
bb2e2bec18 new lua function "tag" 1997-04-01 14:31:42 -03:00
Roberto Ierusalimschy
efaaf99c42 first version of "setglobal" and "getglobal" internal methods. 1997-03-31 17:59:09 -03:00
Roberto Ierusalimschy
f8a571ee35 some new options for warnings and optimizations. 1997-03-31 17:58:42 -03:00
Roberto Ierusalimschy
397e32399b update of ".h" dependencies 1997-03-31 11:23:49 -03:00
Roberto Ierusalimschy
373363cb69 new name for old "mem.h" (conflicts with some compiler libraries) 1997-03-31 11:19:01 -03:00
Roberto Ierusalimschy
ad5574c4c9 "Object" renamed to "TObject" (Tagged Object), to avoid conflicts with
pre-defined names in some C compilers.
1997-03-31 11:02:58 -03:00
Roberto Ierusalimschy
264f8c5e7b new (internal?) functions to manipulate userdata 1997-03-26 19:23:15 -03:00
Roberto Ierusalimschy
9e9e2ea287 BUG: must mark userdata in garbage collection. 1997-03-26 19:22:41 -03:00
Roberto Ierusalimschy
03d917f229 some corrections, improvements; 1997-03-24 14:13:22 -03:00
Roberto Ierusalimschy
c3488f5115 must call "gc" i.m. for nil after all others. 1997-03-21 18:39:57 -03:00
Roberto Ierusalimschy
6fef372fb8 mathlib now uses i.m. for "pow" operator. 1997-03-21 15:37:28 -03:00
Roberto Ierusalimschy
052a1cc46c files now have proper tags. 1997-03-20 17:36:58 -03:00
Roberto Ierusalimschy
ae067dcddd BUG: lua_newtag can be called before luaI_IMtable is initialized. 1997-03-20 17:36:19 -03:00
Roberto Ierusalimschy
5d60470508 i.m. "arith" and "order" splited for different operations 1997-03-20 16:20:43 -03:00
Roberto Ierusalimschy
88d7ffb0d0 luaI_type moved to fallback.c 1997-03-20 16:20:23 -03:00
Roberto Ierusalimschy
47527d2d3c setmethods should return old methods. 1997-03-19 18:12:34 -03:00
Roberto Ierusalimschy
1444d28476 first full implementation of internal methods 1997-03-19 16:41:10 -03:00
Roberto Ierusalimschy
2de803c250 new header 'auxlib.h' + new function luaL_verror 1997-03-18 12:30:50 -03:00
Roberto Ierusalimschy
fa08b42dd8 new header for auxiliar functions. 1997-03-18 12:30:50 -03:00
Roberto Ierusalimschy
eea734aa88 new module 'auxlib' centralizes functions to get/check parameters. 1997-03-17 14:02:29 -03:00
Roberto Ierusalimschy
b6d91e24e2 "tag" changed to "ttype" (since now tag has other meaning) 1997-03-11 15:44:28 -03:00
Roberto Ierusalimschy
a82ab0852e new explanation about communication between Lua and C. 1997-03-06 19:19:08 -03:00
Roberto Ierusalimschy
b8af9c56c9 new form for constructors: {[exp] = exp, ...} 1997-03-06 14:30:55 -03:00
Roberto Ierusalimschy
c3c0b52a1f atualization of #include dependencies. 1997-03-05 10:37:04 -03:00
Roberto Ierusalimschy
ec422ec7d0 skips can be nested (why not?). 1997-03-05 10:32:41 -03:00
Roberto Ierusalimschy
a8a15ff1bd "mem.c.debug" incorporated (with "#if"). 1997-03-03 16:55:38 -03:00
Roberto Ierusalimschy
131d66efd2 first step in implementing internal methods. 1997-02-26 14:38:41 -03:00
Roberto Ierusalimschy
bbf1b3060a small correction. 1997-02-26 14:07:57 -03:00
Roberto Ierusalimschy
8b7f271ea2 new pattern item ".-";
empty patterns may be used in gsub.
1997-02-21 12:21:34 -03:00
Roberto Ierusalimschy
bc323435ee new facilities for pattern matching (%b and .-);
explanations about  next-nextvar.
1997-02-21 12:19:37 -03:00
Roberto Ierusalimschy
6769f34817 lua_Type is private (preparation for tags) 1997-02-20 12:51:14 -03:00
Roberto Ierusalimschy
0b110f7922 small syntax error (yacc does not complain, but bison does). 1997-02-13 14:18:39 -02:00
Roberto Ierusalimschy
205ee1ec84 userdata can handle arbitrary binary data;
user tag is stored with data;
1997-02-11 09:40:01 -02:00
Roberto Ierusalimschy
b48847c5fa BUG: "inclinenumber" cannot use public buffer, since it could change
the buffer pointer (luaY_lex and read_long_string have local
pointers to it).
1997-02-07 11:49:46 -02:00
Roberto Ierusalimschy
1143bf9286 better check when converting from float to int, to avoid overflow
(on some machines it may result in run-time error)
1997-01-31 12:27:11 -02:00
Roberto Ierusalimschy
d9ecc13545 lhf revisions/sugestions 1997-01-23 14:17:53 -02:00
Roberto Ierusalimschy
f00d692445 small correction to avoid "wrong" default action 1997-01-15 14:11:37 -02:00
Roberto Ierusalimschy
d8b0bbb2ad BUG: pointer arithmetic does not have to work when pointing outside
an array.
1996-11-22 11:08:28 -02:00
Roberto Ierusalimschy
1f4ee4a4d2 ANSI ctype only works for unsigned chars (or EOF) 1996-11-22 11:08:02 -02:00
Roberto Ierusalimschy
6a9efa8b8e useless include. 1996-11-22 11:07:20 -02:00
Roberto Ierusalimschy
65459e7938 small BUG: pragma deletes 0 at end of yytext, so a syntax error just after
it may have a wrong token in message.
1996-11-21 12:44:04 -02:00
Roberto Ierusalimschy
42359b8b13 new version 1996-11-20 11:49:32 -02:00
Roberto Ierusalimschy
169870e37d BUG: ISO chars are negative, ISO ints are not. 1996-11-20 11:47:59 -02:00
Roberto Ierusalimschy
78e454d864 BUG: ISO chars are negative, ISO ints are not.
new "balanced" pattern.
1996-11-20 11:47:59 -02:00
Roberto Ierusalimschy
dbfe28e199 correction in inheritance code in C 1996-11-18 12:27:42 -02:00
Roberto Ierusalimschy
d59c52753f undump needs file in binary mode 1996-11-18 11:48:44 -02:00
Roberto Ierusalimschy
62e1a4c84d BUG: problems with negative indexes 1996-11-18 11:48:44 -02:00
Luiz Henrique de Figueiredo
81411e8913 headers includes sizeof(Word) not sizeof(int) 1996-11-18 09:18:29 -02:00
Luiz Henrique de Figueiredo
62aa717f7e stdlib.h for exit
blocks are void*
1996-11-16 18:14:23 -02:00
Roberto Ierusalimschy
a5614eae3c spelling corrections. 1996-11-14 15:45:37 -02:00
Luiz Henrique de Figueiredo
536bae5871 corrected version test (0x23 not 23) 1996-11-14 13:00:32 -02:00
Luiz Henrique de Figueiredo
679eddf296 1996-11-14 11:33:15 -02:00
Luiz Henrique de Figueiredo
d991def36c added 3 new bytes to header (sizeof's) 1996-11-14 09:44:34 -02:00
Luiz Henrique de Figueiredo
8b195533d2 new header version 1996-11-14 09:44:34 -02:00
Roberto Ierusalimschy
3ccdd57c26 new version 1996-11-12 14:00:16 -02:00
Roberto Ierusalimschy
a103455dda better format for error messages. 1996-11-08 17:08:30 -02:00
Roberto Ierusalimschy
60242e1930 error message for syntax "1..2";
syntax error function is in "lex.c" (it has the token)
1996-11-08 10:49:35 -02:00
Roberto Ierusalimschy
a0e9bfbb48 syntax error function is in "lex.c" (it has the token) 1996-11-08 10:49:35 -02:00
Roberto Ierusalimschy
2f19e0ba16 SunOS is not ANSI about the return value of "sprintf". 1996-11-07 18:26:19 -02:00
Roberto Ierusalimschy
ab7fdcbbed corrected copyright notice 1996-11-07 18:26:08 -02:00
Luiz Henrique de Figueiredo
48cf1de356 replaced unions by memcpy 1996-11-07 12:13:28 -02:00
Luiz Henrique de Figueiredo
8d50122af0 replaced unions by memcpy 1996-11-07 11:59:51 -02:00
Roberto Ierusalimschy
fd379b38f7 new flag for STRERROR; libs now are called lib... 1996-11-06 18:48:03 -02:00
Roberto Ierusalimschy
aa4d865077 anna's comments 1996-11-06 18:26:56 -02:00
Roberto Ierusalimschy
3e94febfc1 pragmas should not be recognized inside literal strings. 1996-11-06 18:24:29 -02:00
Roberto Ierusalimschy
243b3a1a47 i/o functions return an error message 1996-11-01 16:02:53 -02:00
Roberto Ierusalimschy
389e808c60 although an ANSI function, some systems do not offer "strerror" 1996-11-01 15:54:41 -02:00
Roberto Ierusalimschy
450465c4d4 new parameters for "read" and "write". BIG CHANGE. 1996-11-01 15:03:36 -02:00
Roberto Ierusalimschy
2f44cc9f4d new pattern matching facilities; new version of i/o lib;
other small corrections.
1996-11-01 15:02:10 -02:00
Roberto Ierusalimschy
d106f3f43c pre-defined variable _VERSION_ 1996-11-01 10:47:45 -02:00
Roberto Ierusalimschy
bf3091d94f new version number 1996-11-01 10:46:59 -02:00
Roberto Ierusalimschy
4dbf7285a8 small omission corrected ("s_tsvalue") 1996-11-01 10:46:59 -02:00
Roberto Ierusalimschy
a1e41e3a12 small corrections in error messages 1996-10-31 18:18:05 -02:00
Roberto Ierusalimschy
9d0044ce53 "strfind" has an extra parameter to turn off all special characteres. 1996-10-31 15:26:04 -02:00
Roberto Ierusalimschy
37bf74efb7 some compilers do not accept "stdin"/"stdout" as constants. 1996-10-16 18:22:34 -02:00
Roberto Ierusalimschy
8c37d3b9d6 documentation of opcode meanings (thanks to lhf) 1996-09-26 18:08:41 -03:00
Roberto Ierusalimschy
0af581f0bf new way to handle pragmas (at the lexical level, instead of parsing). 1996-09-25 18:52:00 -03:00
Roberto Ierusalimschy
2a506ea9d2 lua_linenumber is initialized in lex.c 1996-09-25 09:57:22 -03:00
Roberto Ierusalimschy
e5ec547eb3 "call" returns separate results, instead of a table. 1996-09-24 18:46:44 -03:00
Roberto Ierusalimschy
6d383202dc "dofile" and "dostring" may return values. 1996-09-24 14:30:28 -03:00
Roberto Ierusalimschy
7b8166d7b3 a chunk may end with a return. 1996-09-24 14:29:50 -03:00
Roberto Ierusalimschy
3636bbad3a new function "strrep" 1996-09-20 15:20:44 -03:00
Roberto Ierusalimschy
82f9f3e552 better structure to control stack interface lua-C.
beginblock-endblock keeps better control over stack
1996-09-20 09:51:16 -03:00
Roberto Ierusalimschy
c96ad1c945 "strmap" replaced by "strupper" and "strlower" (that's what people will
use, anyway).
"gsub" aceppts a function to give the replacement string.
1996-09-16 15:02:40 -03:00
Roberto Ierusalimschy
5b9fbfa006 "dostring" now stores the prefix of its string, to improve error messages. 1996-09-11 18:53:02 -03:00
Roberto Ierusalimschy
f0cc2d5506 BUG: a program ending in a comment without EOL made lex loops forever. 1996-09-09 11:11:11 -03:00
Roberto Ierusalimschy
d289ac81d3 functions may have tags CMARK and MARK, too. 1996-09-02 18:57:51 -03:00
Roberto Ierusalimschy
15791f93fe lhf's corrections. 1996-08-28 17:46:26 -03:00
Roberto Ierusalimschy
d763b69740 skip first line of a lua file if it starts with a '#' (to allow shell
scripts).
1996-08-15 15:40:55 -03:00
Roberto Ierusalimschy
36dd1af92d "[^]]" must mean "not ]". 1996-08-09 10:14:11 -03:00
Roberto Ierusalimschy
25b6dae7c0 singlematch and item_end are used by "read", in iolib. 1996-08-05 17:55:24 -03:00
Roberto Ierusalimschy
1630c2533a Pattern-Matching!
plus several other changes...
1996-08-01 11:55:33 -03:00
Roberto Ierusalimschy
1d373d77de more functions exported. 1996-08-01 11:55:33 -03:00
Roberto Ierusalimschy
f025b0d160 "pushnil" is not needed (default return is nil). 1996-08-01 11:55:33 -03:00
Roberto Ierusalimschy
cc02b4729b new mod implementation (more portable). 1996-08-01 11:55:33 -03:00
Roberto Ierusalimschy
2bb3830fc1 "memcpy" is defined in "string.h". 1996-07-24 15:01:52 -03:00
Roberto Ierusalimschy
7a38bdd4b3 "exit" is defined in "stdlib". 1996-07-24 14:55:57 -03:00
Roberto Ierusalimschy
7614b17e85 very small corrections 1996-07-24 11:38:12 -03:00
Roberto Ierusalimschy
6dfdb76538 C functions don't need to "pushnil" to return nil value (this is
the default value).
1996-07-12 17:00:26 -03:00
Roberto Ierusalimschy
9a3c51cff1 new name for POSIX flag (this one turns on some posix stuff in standard
header files).
1996-07-06 17:20:35 -03:00
Roberto Ierusalimschy
6336d2f9e1 flag for direct execution is "-e"; argument with an "=" goes to
direct execution, independently of flags.
1996-07-05 17:55:43 -03:00
Roberto Ierusalimschy
ec6677e551 when "block" is computed, "nentity" == "block". So the change is only
a simpler way to write the same expression.
1996-06-18 18:12:23 -03:00
Roberto Ierusalimschy
20cbca699a "lua_dofile" has a more informative return code. 1996-06-18 17:08:40 -03:00
Roberto Ierusalimschy
3211a9648a "lua_dofile" returns different error codes if it could not open the file 1996-06-10 16:36:24 -03:00
Roberto Ierusalimschy
0baa915343 new option "-x" to execute a string given as argument. 1996-06-10 16:35:46 -03:00
Roberto Ierusalimschy
5cddb264d4 lexical analiser may use luaI_buffer, instead of waste space with
a separate buffer.
1996-05-30 11:04:07 -03:00
Roberto Ierusalimschy
9863223fbf first version of vararg facility (plus new function "call"). 1996-05-28 18:07:32 -03:00
Roberto Ierusalimschy
9a1948e67d small correction. 1996-05-27 11:06:58 -03:00
Roberto Ierusalimschy
f9deeac632 "luaI_malloc(s)" is just a macro to "luaI_realloc(NULL, s)". 1996-05-24 11:31:10 -03:00
Roberto Ierusalimschy
29f0021837 variables which contain string lengths must be long (if they also may
be negative) or size_t.
1996-05-22 18:59:07 -03:00
Roberto Ierusalimschy
7acddb871d memory manager for old versions of Lua. It should be in RCS since
the beginning.
1996-05-06 18:37:28 -03:00
Roberto Ierusalimschy
a7ca46405d unused "#include". 1996-05-06 13:59:00 -03:00
Roberto Ierusalimschy
0e2297afaa update of dependencies from "#include"s. 1996-05-06 11:38:40 -03:00
Roberto Ierusalimschy
0a1891f6a0 new version. 1996-05-06 11:32:59 -03:00
Roberto Ierusalimschy
1936a9e53b tables may grow bigger than words. 1996-05-06 11:30:27 -03:00
Roberto Ierusalimschy
820ec63bdf as strings are no more duplicated, "nextvar" can use "pushstring". 1996-05-06 11:29:35 -03:00
Roberto Ierusalimschy
01ea523b80 small corrections. 1996-05-03 17:10:59 -03:00
Roberto Ierusalimschy
88cf0836fc "isatty" is POSIX, but not ANSI. 1996-05-03 14:27:03 -03:00
Roberto Ierusalimschy
3ec9ee0d0f new function "luaI_openlib" to help open libs. 1996-04-30 18:13:55 -03:00
Roberto Ierusalimschy
21c9ebf4a9 new algotithm to adjust garbage collection: it tries to adapt gc calls
so that it collects half of the total objects when it is called.
1996-04-29 15:53:53 -03:00
Roberto Ierusalimschy
4fb77c4308 no more "lua_Reference"; new return value for "append";
documentation of "exit" (it was not in the manual).
1996-04-29 15:50:08 -03:00
Roberto Ierusalimschy
bced00ab9e lua_Reference is int, so say so. 1996-04-25 11:10:00 -03:00
Roberto Ierusalimschy
25116a3065 "malloc.h" is not ansi. 1996-04-25 11:01:27 -03:00
Roberto Ierusalimschy
eadbb9cff4 "stat" is not ansi. 1996-04-23 09:43:07 -03:00
Roberto Ierusalimschy
42b947296b "fileno" is not ansi. 1996-04-23 09:43:07 -03:00
Roberto Ierusalimschy
f37e65d1cb "exit" has an optional parameter of status. 1996-04-22 16:28:37 -03:00
Roberto Ierusalimschy
0ef5cf2289 lock mechanism seperseded by the REFERENCE mechanism. 1996-04-22 15:00:37 -03:00
Roberto Ierusalimschy
fed9408ab5 page size "letter". 1996-04-01 11:36:35 -03:00
Roberto Ierusalimschy
ce23901f04 smaller limit to stack size (otherwise C stack can finish first) 1996-03-22 16:12:15 -03:00
Roberto Ierusalimschy
df1ee1fb1c small "abstraction" 1996-03-22 14:57:24 -03:00
Roberto Ierusalimschy
f1d0276684 small bug in strfind. 1996-03-21 19:18:08 -03:00
Roberto Ierusalimschy
7ecc2ea597 new version 1996-03-21 18:30:29 -03:00
Roberto Ierusalimschy
7a35f23c16 a simplification about memory error messages. 1996-03-21 15:55:02 -03:00
Roberto Ierusalimschy
9284742a11 better control when growing arrays. 1996-03-21 13:33:47 -03:00
Roberto Ierusalimschy
9704ff4cb1 hook variables are global, no more "lua_set...hook" functions. 1996-03-20 15:44:02 -03:00
Roberto Ierusalimschy
e3c0ce9a69 dofile accepts pre-compiled chunks.
lua_is... do coercion.
small correction: = versus ==.
1996-03-19 19:39:07 -03:00
Roberto Ierusalimschy
85b76bcc01 functions "lua_is..." consider coercions.
small change when calling call hook.
1996-03-19 19:28:37 -03:00
Roberto Ierusalimschy
a275d9a25b functions "lua_is..." consider coercions. 1996-03-19 19:28:37 -03:00
Roberto Ierusalimschy
7e0be1fbde unused "#include" 1996-03-19 13:50:24 -03:00
Roberto Ierusalimschy
54ba642cc3 new module "undump.o" 1996-03-15 15:22:09 -03:00
Roberto Ierusalimschy
8826eb7918 small correction 1996-03-15 15:21:58 -03:00
Roberto Ierusalimschy
e701a86385 "openfile" now returns the file 1996-03-15 10:13:13 -03:00
Roberto Ierusalimschy
3e1f731826 integration with undump (execution of pre-compiled chuncks) 1996-03-15 10:13:13 -03:00
Roberto Ierusalimschy
f86c1367db new functions "rename" and "tmpname".
new option 'q' for function "format".
new example, about vararg.
1996-03-14 14:45:01 -03:00
Luiz Henrique de Figueiredo
58fd8aa851 added cast instead of union [lazy?] 1996-03-14 14:31:15 -03:00
Roberto Ierusalimschy
3226ac2da8 "lua_ntable" and "lua_nconstant" are public (undump.c uses them). 1996-03-14 12:57:19 -03:00
Roberto Ierusalimschy
3e9daa7416 creation of strings must call garbage collector. 1996-03-14 12:56:26 -03:00
Roberto Ierusalimschy
7236df875a new function "luaI_buffer". 1996-03-14 12:55:49 -03:00
Roberto Ierusalimschy
675e608325 new functions "rename" and "tmpname". 1996-03-14 12:55:18 -03:00
Roberto Ierusalimschy
1dc0e82aeb "freefunc" now is public. 1996-03-14 12:54:20 -03:00
Roberto Ierusalimschy
c2eb02aaf6 both "write" and "format" need "addquoted". 1996-03-14 12:53:09 -03:00
Roberto Ierusalimschy
2fee7e42c9 new option 'q' in function "format". 1996-03-14 12:52:35 -03:00
Roberto Ierusalimschy
281db390e8 no more "ugly" programs.
no more comments with '#'.
1996-03-14 12:17:28 -03:00
Luiz Henrique de Figueiredo
df8cf53cc9 removed tf->marked=0; 1996-03-12 17:00:40 -03:00
Roberto Ierusalimschy
40306b10db small corrections. 1996-03-12 12:56:03 -03:00
Luiz Henrique de Figueiredo
5eff5d3eac moved some includes from undump.h
LoadString now uses luaI_buffer
added LoadNewString
needs tf->marked=0
luaI_undump now returns int and aborts if luaI_dorun fails
1996-03-11 19:01:46 -03:00
Luiz Henrique de Figueiredo
8ad8426c43 moved some includes to undump.c
luaI_undump now returns int
1996-03-11 18:59:41 -03:00
Luiz Henrique de Figueiredo
3cab7cd025 undump.c is now a module
panic is now lua_error
 included swap.c
 tries float permutation earlier
 new functions: luaI_undump1 and luaI_undump
1996-03-08 18:44:12 -03:00
Luiz Henrique de Figueiredo
bb26efbbec definitions for lua decompiler
undump is now a module
1996-03-08 18:43:21 -03:00
Roberto Ierusalimschy
5c0e5fd36d details. 1996-03-08 09:04:04 -03:00
Roberto Ierusalimschy
621322a305 "PrintCode" now is defined in luac. 1996-03-08 09:02:37 -03:00
Luiz Henrique de Figueiredo
e33a3b8e0d now loads size as two words 1996-03-06 18:40:10 -03:00
Luiz Henrique de Figueiredo
9a6cccb08c removed support for local vars 1996-03-06 13:01:08 -03:00
Roberto Ierusalimschy
b58225e93b unused declaration removed. 1996-03-06 10:11:23 -03:00
Luiz Henrique de Figueiredo
852b919465 now swaps bytes (but need to make it more robust) 1996-03-05 22:41:18 -03:00
Roberto Ierusalimschy
ef94999647 parse.o was included twice in lua.a 1996-03-05 12:57:53 -03:00
Roberto Ierusalimschy
6f30fa98d8 small change to avoid error on "lua_pushstring(NULL)". 1996-03-04 11:46:35 -03:00
Roberto Ierusalimschy
74102bd716 small corrections. 1996-03-04 10:29:10 -03:00
Roberto Ierusalimschy
8d82aa821a small correction (about types) 1996-03-01 13:54:00 -03:00
Luiz Henrique de Figueiredo
cec1ffb80b uses ID_* constants
simplified signature checking
loads local vars
1996-03-01 00:43:50 -03:00
Luiz Henrique de Figueiredo
870967ca77 headers for Main and others are different 1996-02-28 20:10:46 -03:00
Roberto Ierusalimschy
66fc0f554a using double to read numbers. 1996-02-26 19:35:51 -03:00
Roberto Ierusalimschy
d6e4c29733 fixed strings (not collectable) don't need to be inserted in the constant table. 1996-02-26 18:00:27 -03:00
Luiz Henrique de Figueiredo
3e42969979 main always reads "luac.out" 1996-02-26 16:44:17 -03:00
Roberto Ierusalimschy
712ac505e0 small correction 1996-02-26 14:07:49 -03:00
Roberto Ierusalimschy
f935d3397e check if jump is bigger than 2^16. 1996-02-26 14:07:20 -03:00
Roberto Ierusalimschy
30dd3a2dbc small changes (preparing for new module of pre-compilation) 1996-02-26 14:06:39 -03:00
Luiz Henrique de Figueiredo
b04f88d581 functions now linked into a list headed by main 1996-02-24 13:44:28 -03:00
Luiz Henrique de Figueiredo
b3c10c8c41 fix to PUSHFUNCTION now correctly at tf->marked 1996-02-24 00:46:57 -03:00
Luiz Henrique de Figueiredo
5c1bd89a1c added fix to PUSHFUNCTION and support for main function 1996-02-23 19:00:26 -03:00
Luiz Henrique de Figueiredo
15f3ab09eb load bytecodes from files 1996-02-23 16:04:38 -03:00
Roberto Ierusalimschy
c7e834f424 function "write_quoted" rewritten more clearly. 1996-02-22 17:56:33 -03:00
Roberto Ierusalimschy
8c1a9899d4 functions "luaI_free" and "luaI_realloc" (or macro "growvector") may be
called with NULL.
1996-02-22 17:34:33 -03:00
Roberto Ierusalimschy
05caf09a36 list of incompatibilities with version 2.2.
new macro \Version.
1996-02-16 10:12:12 -03:00
Roberto Ierusalimschy
168a865e60 more appropriate error message for "date" 1996-02-16 10:10:14 -03:00
Roberto Ierusalimschy
15c17c24fa small improvements 1996-02-14 16:11:09 -03:00
Roberto Ierusalimschy
45cf24485d useless #include. 1996-02-14 15:25:04 -03:00
Roberto Ierusalimschy
c56e2b2e30 new version 1996-02-14 10:40:26 -03:00
Roberto Ierusalimschy
d1608c597e reserved words are stored in main string table; "marked" field is
used to indicate its type.
Table initializations centralized by "tree.c".
1996-02-14 10:35:51 -03:00
Roberto Ierusalimschy
0f4903a5d7 new header "lex.h". 1996-02-13 14:30:39 -03:00
Roberto Ierusalimschy
772f25d3dd new header for lex.c 1996-02-13 14:30:39 -03:00
Roberto Ierusalimschy
f1a1eda7c5 old trick in "strsub" does not work with new hash table for strings. 1996-02-12 15:34:44 -03:00
Roberto Ierusalimschy
41259bff31 BIG CHANGE: new data structure for constants, strings and globals, using
an array of hash tables for all them.
1996-02-12 15:32:40 -03:00
Roberto Ierusalimschy
afaa98a666 no more "lua_pushliteral". 1996-02-12 15:32:09 -03:00
Roberto Ierusalimschy
73be918285 a backslash followed by a newline allows the newline to go into
a string.
1996-02-09 17:35:23 -02:00
Roberto Ierusalimschy
ca412214cb new function "date", replaces old "date" and "time". 1996-02-09 17:02:30 -02:00
Roberto Ierusalimschy
801722825d "lua_check_number" accepts strings convertible to numbers. 1996-02-09 17:00:23 -02:00
Roberto Ierusalimschy
3abc25fa54 new functions "random" and "randomseed". 1996-02-09 15:21:27 -02:00
Roberto Ierusalimschy
f4d67761f1 new section describing the debug interface. 1996-02-09 14:37:58 -02:00
Roberto Ierusalimschy
369c5fe3c0 lock mechanism more robust; nil is pseudo-locked under index -1. 1996-02-08 17:08:34 -02:00
Roberto Ierusalimschy
7918c6cf11 small bug 1996-02-08 16:14:17 -02:00
Roberto Ierusalimschy
826d70fcba new type lua_Function for activation records 1996-02-08 15:03:20 -02:00
Roberto Ierusalimschy
bbb23048e3 correction of dependencies (include's). 1996-02-07 16:14:38 -02:00
Roberto Ierusalimschy
5a3a1fe458 debug interface functions to manipulated local variables:
"lua_getlocal" and "lua_setlocal".
1996-02-07 16:10:27 -02:00
Roberto Ierusalimschy
56fb06b6f5 "lua_debug" now is exported through debug interface (luadebug.h) 1996-02-07 12:14:40 -02:00
Roberto Ierusalimschy
995a9f7188 no more "Bool" type 1996-02-07 12:13:17 -02:00
Roberto Ierusalimschy
a0ef046ef1 elimination of unused declarations (left from old modifications) 1996-02-06 14:18:21 -02:00
Roberto Ierusalimschy
5fa51fc426 new option "q" in function "write", to write literal strings. 1996-02-05 19:32:19 -02:00
Roberto Ierusalimschy
15057aa0a4 new examples showing data structures and object-oriented programming.
generic improvements and corrections.
1996-02-05 12:52:47 -02:00
Roberto Ierusalimschy
1431b52e76 improve of compiling error messages. 1996-02-05 11:26:01 -02:00
Roberto Ierusalimschy
98fe770cab small bug 1996-02-04 14:59:12 -02:00
Roberto Ierusalimschy
43382ce5a2 new fallback "getglobal". 1996-01-30 13:25:23 -02:00
Roberto Ierusalimschy
abfebf1e21 new example showing how to build modules. 1996-01-30 13:24:49 -02:00
Roberto Ierusalimschy
b1c02c7f00 new fallback "getglobal".
modifications to generate an index (not automatically yet).
1996-01-30 10:55:10 -02:00
Roberto Ierusalimschy
84df3ac267 new functions "tostring", "assert", and "format". 1996-01-29 15:08:23 -02:00
Roberto Ierusalimschy
55a70c9719 "read('s')" was "eating" delimiter. 1996-01-29 14:40:09 -02:00
Roberto Ierusalimschy
0d50b87aa4 lua_table now has references to global variable names (TreeNode's). 1996-01-26 16:03:19 -02:00
Roberto Ierusalimschy
19290a8e92 "dofile" issues an error when called with non string arguments, and
runs stdin when called without arguments.
1996-01-26 14:52:47 -02:00
Roberto Ierusalimschy
d845963349 "setglobal" and "getglobal" moved to inout.c, as it concentrates pre-defined
library.
new function "assert".
1996-01-26 12:05:28 -02:00
Roberto Ierusalimschy
8dae4657a1 "setglobal" and "getglobal" moved to inout.c, as it concentrates pre-defined
library.
1996-01-26 12:04:32 -02:00
Roberto Ierusalimschy
ca7be1cfeb elimination of function "int2str", as it can be replaced by "format('%c', .)" 1996-01-26 10:11:28 -02:00
Roberto Ierusalimschy
445872a6e2 "dofile" does not issue a warning when unable to open the file,
but only returns an error code.
1996-01-23 16:43:07 -02:00
Roberto Ierusalimschy
3681d025ac new function "assert" 1996-01-23 16:39:45 -02:00
Roberto Ierusalimschy
2998049f51 local variable stack needs only the name of the variable (TreeNode);
this way is simpler and faster than old way.
1996-01-23 15:50:29 -02:00
Roberto Ierusalimschy
24ccc7c038 correction of some order dependencies in debug code. 1996-01-22 16:39:37 -02:00
Roberto Ierusalimschy
be48c4d91e add_char now is global.
time returns week-day.
1996-01-22 15:46:55 -02:00
Roberto Ierusalimschy
a19f9056f3 new function "tostring". 1996-01-22 15:40:00 -02:00
Roberto Ierusalimschy
5b71ab780c add_char now is global.
new function format.
1996-01-22 15:38:57 -02:00
Roberto Ierusalimschy
481bafd581 add_char now is global. 1996-01-22 15:38:57 -02:00
Roberto Ierusalimschy
e74b250d71 memory overflow tries a garbage collection; if it fails then exit the
program.
1996-01-22 12:15:13 -02:00
Roberto Ierusalimschy
cd54c95ee1 bug: "read" with format MUST read given number of chars (if file ends
before that reports an error, returning nil).
"readuntil" can be called with nil or no parameters to read until EOF.
1996-01-12 15:00:30 -02:00
Roberto Ierusalimschy
bf006eeaf5 "getobjectname" got a "lua_" prefix. 1996-01-09 18:23:19 -02:00
Roberto Ierusalimschy
b2afc410fa hooks for line change and function calls; first version. 1996-01-09 18:22:44 -02:00
Roberto Ierusalimschy
19cfa32393 correction of dependencies from "luadebug.h". 1996-01-09 18:22:08 -02:00
Roberto Ierusalimschy
27ae8432b6 names generated by yacc (starting with "yy") are changed to start with
"luaY_", to avoid name clashes with hosts using yacc.
1995-12-21 14:14:04 -02:00
Roberto Ierusalimschy
415ee250b5 bug: luaI_findconstantbyname may change the value of lua_constant. 1995-12-18 14:47:29 -02:00
73 changed files with 12108 additions and 6622 deletions

104
bugs Normal file
View File

@@ -0,0 +1,104 @@
** lua.stx / llex.c
Tue Dec 2 10:45:48 EDT 1997
>> BUG: "lastline" was not reset on function entry, so debug information
>> started only in the 2nd line of a function.
--- Version 3.1 alpha
** lua.c
Thu Jan 15 14:34:58 EDT 1998
>> must include "stdlib.h" (for "exit()").
** lbuiltin.c / lobject.h
Thu Jan 15 14:34:58 EDT 1998
>> MAX_WORD may be bigger than MAX_INT
(by lhf)
** llex.c
Mon Jan 19 18:17:18 EDT 1998
>> wrong line number (+1) in error report when file starts with "#..."
** lstrlib.c
Tue Jan 27 15:27:49 EDT 1998
>> formats like "%020d" were considered too big (3 digits); moreover,
>> some sistems limit printf to at most 500 chars, so we can limit sizes
>> to 2 digits (99).
** lapi.c
Tue Jan 27 17:12:36 EDT 1998
>> "lua_getstring" may create a new string, so should check GC
** lstring.c / ltable.c
Wed Jan 28 14:48:12 EDT 1998
>> tables can become full of "empty" slots, and keep growing without limits.
** lstrlib.c
Mon Mar 9 15:26:09 EST 1998
>> gsub('a', '(b?)%1*' ...) loops (because the capture is empty).
** lstrlib.c
Mon May 18 19:20:00 EST 1998
>> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int.
--- Version 3.1
** liolib.c / lauxlib.c
Mon Sep 7 15:57:02 EST 1998
>> function "luaL_argerror" prints wrong argument number (from a user's point
of view) when functions have upvalues.
** lstrlib.c
Tue Nov 10 17:29:36 EDT 1998
>> gsub/strfind do not check whether captures are properly finished.
(by roberto/tomas)
** lbuiltin.c
Fri Dec 18 11:22:55 EDT 1998
>> "tonumber" goes crazy with negative numbers in other bases (not 10),
because "strtol" returns long, not unsigned long.
(by Visual C++)
** lstrlib.c
Mon Jan 4 10:41:40 EDT 1999
>> "format" does not check size of format item (such as "%00000...00000d").
** lapi.c
Wed Feb 3 14:40:21 EDT 1999
>> getlocal cannot return the local itself, since lua_isstring and
lua_isnumber can modify it.
** lstrlib.c
Thu Feb 4 17:08:50 EDT 1999
>> format "%s" may break limit of "sprintf" on some machines.
(by Marcelo Sales)
** lzio.c
Thu Mar 4 11:49:37 EST 1999
>> file stream cannot call fread after EOF.
(by lhf)
--- Version 3.2 (beta)
** lstrlib.c
Fri Apr 30 11:10:20 EST 1999
>> '$' at end of pattern was matching regular '$', too.
(by anna; since 2.5)
** lbuiltin.c
Fri May 21 17:15:11 EST 1999
>> foreach, foreachi, foreachvar points to function in stack when stack
can be reallocated.
(by tomas; since 3.2 beta)
** lparser.c
Wed Jun 16 10:32:46 EST 1999
>> cannot assign to unlimited variables, because it causes overflow in
the number of returns of a function.
(since 3.1)

View File

@@ -1,177 +0,0 @@
/*
** fallback.c
** TecCGraf - PUC-Rio
*/
char *rcs_fallback="$Id: fallback.c,v 1.16 1995/10/17 11:52:38 roberto Exp roberto $";
#include <stdio.h>
#include <string.h>
#include "mem.h"
#include "fallback.h"
#include "opcode.h"
#include "lua.h"
static void errorFB (void);
static void indexFB (void);
static void gettableFB (void);
static void arithFB (void);
static void concatFB (void);
static void orderFB (void);
static void GDFB (void);
static void funcFB (void);
/*
** Warning: This list must be in the same order as the #define's
*/
struct FB luaI_fallBacks[] = {
{"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0},
{"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1},
{"gettable", {LUA_T_CFUNCTION, {gettableFB}}, 2, 1},
{"arith", {LUA_T_CFUNCTION, {arithFB}}, 3, 1},
{"order", {LUA_T_CFUNCTION, {orderFB}}, 3, 1},
{"concat", {LUA_T_CFUNCTION, {concatFB}}, 2, 1},
{"settable", {LUA_T_CFUNCTION, {gettableFB}}, 3, 0},
{"gc", {LUA_T_CFUNCTION, {GDFB}}, 1, 0},
{"function", {LUA_T_CFUNCTION, {funcFB}}, -1, -1}
/* no fixed number of params or results */
};
#define N_FB (sizeof(luaI_fallBacks)/sizeof(struct FB))
void luaI_setfallback (void)
{
int i;
char *name = lua_getstring(lua_getparam(1));
lua_Object func = lua_getparam(2);
if (name == NULL || !(lua_isfunction(func) || lua_iscfunction(func)))
lua_error("incorrect argument to function `setfallback'");
for (i=0; i<N_FB; i++)
{
if (strcmp(luaI_fallBacks[i].kind, name) == 0)
{
luaI_pushobject(&luaI_fallBacks[i].function);
luaI_fallBacks[i].function = *luaI_Address(func);
return;
}
}
/* name not found */
lua_error("incorrect argument to function `setfallback'");
}
static void errorFB (void)
{
lua_Object o = lua_getparam(1);
if (lua_isstring(o))
fprintf (stderr, "lua: %s\n", lua_getstring(o));
else
fprintf(stderr, "lua: unknown error\n");
}
static void indexFB (void)
{
lua_pushnil();
}
static void gettableFB (void)
{
lua_error("indexed expression not a table");
}
static void arithFB (void)
{
lua_error("unexpected type at conversion to number");
}
static void concatFB (void)
{
lua_error("unexpected type at conversion to string");
}
static void orderFB (void)
{
lua_error("unexpected type at comparison");
}
static void GDFB (void) { }
static void funcFB (void)
{
lua_error("call expression not a function");
}
/*
** Lock routines
*/
static Object *lockArray = NULL;
static Word lockSize = 0;
int luaI_lock (Object *object)
{
Word i;
Word oldSize;
if (tag(object) == LUA_T_NIL)
return -1;
for (i=0; i<lockSize; i++)
if (tag(&lockArray[i]) == LUA_T_NIL)
{
lockArray[i] = *object;
return i;
}
/* no more empty spaces */
oldSize = lockSize;
if (lockArray == NULL)
{
lockSize = 10;
lockArray = newvector(lockSize, Object);
}
else
{
lockSize = 3*oldSize/2 + 5;
lockArray = growvector(lockArray, lockSize, Object);
}
for (i=oldSize; i<lockSize; i++)
tag(&lockArray[i]) = LUA_T_NIL;
lockArray[oldSize] = *object;
return oldSize;
}
void lua_unlock (int ref)
{
tag(&lockArray[ref]) = LUA_T_NIL;
}
Object *luaI_getlocked (int ref)
{
return &lockArray[ref];
}
void luaI_travlock (int (*fn)(Object *))
{
Word i;
for (i=0; i<lockSize; i++)
fn(&lockArray[i]);
}
char *luaI_travfallbacks (int (*fn)(Object *))
{
Word i;
for (i=0; i<N_FB; i++)
if (fn(&luaI_fallBacks[i].function))
return luaI_fallBacks[i].kind;
return NULL;
}

View File

@@ -1,34 +0,0 @@
/*
** $Id: fallback.h,v 1.9 1995/10/09 13:14:29 roberto Exp roberto $
*/
#ifndef fallback_h
#define fallback_h
#include "opcode.h"
extern struct FB {
char *kind;
Object function;
int nParams;
int nResults;
} luaI_fallBacks[];
#define FB_ERROR 0
#define FB_INDEX 1
#define FB_GETTABLE 2
#define FB_ARITH 3
#define FB_ORDER 4
#define FB_CONCAT 5
#define FB_SETTABLE 6
#define FB_GC 7
#define FB_FUNCTION 8
void luaI_setfallback (void);
int luaI_lock (Object *object);
Object *luaI_getlocked (int ref);
void luaI_travlock (int (*fn)(Object *));
char *luaI_travfallbacks (int (*fn)(Object *));
#endif

79
func.c
View File

@@ -1,79 +0,0 @@
#include <stdio.h>
#include "luadebug.h"
#include "table.h"
#include "mem.h"
#include "func.h"
#include "opcode.h"
static TFunc *function_root = NULL;
/*
** Insert function in list for GC
*/
void luaI_insertfunction (TFunc *f)
{
lua_pack();
f->next = function_root;
function_root = f;
f->marked = 0;
}
/*
** Free function
*/
static void freefunc (TFunc *f)
{
luaI_free (f->code);
luaI_free (f);
}
/*
** Garbage collection function.
** This function traverse the function list freeing unindexed functions
*/
Long luaI_funccollector (void)
{
TFunc *curr = function_root;
TFunc *prev = NULL;
Long counter = 0;
while (curr)
{
TFunc *next = curr->next;
if (!curr->marked)
{
if (prev == NULL)
function_root = next;
else
prev->next = next;
freefunc (curr);
++counter;
}
else
{
curr->marked = 0;
prev = curr;
}
curr = next;
}
return counter;
}
void lua_funcinfo (lua_Object func, char **filename, int *linedefined)
{
Object *f = luaI_Address(func);
if (f->tag == LUA_T_MARK || f->tag == LUA_T_FUNCTION)
{
*filename = f->value.tf->fileName;
*linedefined = f->value.tf->lineDefined;
}
else if (f->tag == LUA_T_CMARK || f->tag == LUA_T_CFUNCTION)
{
*filename = "(C)";
*linedefined = -1;
}
}

24
func.h
View File

@@ -1,24 +0,0 @@
#ifndef func_h
#define func_h
#include "types.h"
#include "lua.h"
/*
** Header para funcoes.
*/
typedef struct TFunc
{
struct TFunc *next;
char marked;
int size;
Byte *code;
int lineDefined;
char *fileName;
} TFunc;
Long luaI_funccollector (void);
void luaI_insertfunction (TFunc *f);
#endif

335
hash.c
View File

@@ -1,335 +0,0 @@
/*
** hash.c
** hash manager for lua
*/
char *rcs_hash="$Id: hash.c,v 2.25 1995/05/02 18:43:03 roberto Exp $";
#include <string.h>
#include "mem.h"
#include "opcode.h"
#include "hash.h"
#include "table.h"
#include "lua.h"
#define streq(s1,s2) (s1 == s2 || (*(s1) == *(s2) && strcmp(s1,s2)==0))
#define nhash(t) ((t)->nhash)
#define nuse(t) ((t)->nuse)
#define markarray(t) ((t)->mark)
#define nodevector(t) ((t)->node)
#define node(t,i) (&(t)->node[i])
#define ref(n) (&(n)->ref)
#define val(n) (&(n)->val)
#define REHASH_LIMIT 0.70 /* avoid more than this % full */
static Hash *listhead = NULL;
/* hash dimensions values */
static Word dimensions[] =
{3, 5, 7, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421,
12853, 25717, 51437, 65521, 0}; /* 65521 == last prime < MAX_WORD */
static Word redimension (Word nhash)
{
Word i;
for (i=0; dimensions[i]!=0; i++)
{
if (dimensions[i] > nhash)
return dimensions[i];
}
lua_error("table overflow");
return 0; /* to avoid warnings */
}
static Word hashindex (Hash *t, Object *ref) /* hash function */
{
switch (tag(ref))
{
case LUA_T_NIL:
lua_error ("unexpected type to index table");
return -1; /* UNREACHEABLE */
case LUA_T_NUMBER:
return (((Word)nvalue(ref))%nhash(t));
case LUA_T_STRING:
{
unsigned long h = tsvalue(ref)->hash;
if (h == 0)
{
char *name = svalue(ref);
while (*name)
h = ((h<<5)-h)^(unsigned char)*(name++);
tsvalue(ref)->hash = h;
}
return (Word)h%nhash(t); /* make it a valid index */
}
case LUA_T_FUNCTION:
return (((IntPoint)ref->value.tf)%nhash(t));
case LUA_T_CFUNCTION:
return (((IntPoint)fvalue(ref))%nhash(t));
case LUA_T_ARRAY:
return (((IntPoint)avalue(ref))%nhash(t));
default: /* user data */
return (((IntPoint)uvalue(ref))%nhash(t));
}
}
Bool lua_equalObj (Object *t1, Object *t2)
{
if (tag(t1) != tag(t2)) return 0;
switch (tag(t1))
{
case LUA_T_NIL: return 1;
case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2);
case LUA_T_STRING: return streq(svalue(t1), svalue(t2));
case LUA_T_ARRAY: return avalue(t1) == avalue(t2);
case LUA_T_FUNCTION: return t1->value.tf == t2->value.tf;
case LUA_T_CFUNCTION: return fvalue(t1) == fvalue(t2);
default: return uvalue(t1) == uvalue(t2);
}
}
static Word present (Hash *t, Object *ref)
{
Word h = hashindex(t, ref);
while (tag(ref(node(t, h))) != LUA_T_NIL)
{
if (lua_equalObj(ref, ref(node(t, h))))
return h;
h = (h+1) % nhash(t);
}
return h;
}
/*
** Alloc a vector node
*/
static Node *hashnodecreate (Word nhash)
{
Word i;
Node *v = newvector (nhash, Node);
for (i=0; i<nhash; i++)
tag(ref(&v[i])) = LUA_T_NIL;
return v;
}
/*
** Create a new hash. Return the hash pointer or NULL on error.
*/
static Hash *hashcreate (Word nhash)
{
Hash *t = new(Hash);
nhash = redimension((Word)((float)nhash/REHASH_LIMIT));
nodevector(t) = hashnodecreate(nhash);
nhash(t) = nhash;
nuse(t) = 0;
markarray(t) = 0;
return t;
}
/*
** Delete a hash
*/
static void hashdelete (Hash *t)
{
luaI_free (nodevector(t));
luaI_free(t);
}
/*
** Mark a hash and check its elements
*/
void lua_hashmark (Hash *h)
{
if (markarray(h) == 0)
{
Word i;
markarray(h) = 1;
for (i=0; i<nhash(h); i++)
{
Node *n = node(h,i);
if (tag(ref(n)) != LUA_T_NIL)
{
lua_markobject(&n->ref);
lua_markobject(&n->val);
}
}
}
}
static void call_fallbacks (void)
{
Hash *curr_array;
Object t;
tag(&t) = LUA_T_ARRAY;
for (curr_array = listhead; curr_array; curr_array = curr_array->next)
if (markarray(curr_array) != 1)
{
avalue(&t) = curr_array;
luaI_gcFB(&t);
}
tag(&t) = LUA_T_NIL;
luaI_gcFB(&t); /* end of list */
}
/*
** Garbage collection to arrays
** Delete all unmarked arrays.
*/
Long lua_hashcollector (void)
{
Hash *curr_array = listhead, *prev = NULL;
Long counter = 0;
call_fallbacks();
while (curr_array != NULL)
{
Hash *next = curr_array->next;
if (markarray(curr_array) != 1)
{
if (prev == NULL) listhead = next;
else prev->next = next;
hashdelete(curr_array);
++counter;
}
else
{
markarray(curr_array) = 0;
prev = curr_array;
}
curr_array = next;
}
return counter;
}
/*
** Create a new array
** This function inserts the new array in the array list. It also
** executes garbage collection if the number of arrays created
** exceed a pre-defined range.
*/
Hash *lua_createarray (Word nhash)
{
Hash *array;
lua_pack();
array = hashcreate(nhash);
array->next = listhead;
listhead = array;
return array;
}
/*
** Re-hash
*/
static void rehash (Hash *t)
{
Word i;
Word nold = nhash(t);
Node *vold = nodevector(t);
nhash(t) = redimension(nhash(t));
nodevector(t) = hashnodecreate(nhash(t));
for (i=0; i<nold; i++)
{
Node *n = vold+i;
if (tag(ref(n)) != LUA_T_NIL && tag(val(n)) != LUA_T_NIL)
*node(t, present(t, ref(n))) = *n; /* copy old node to new hahs */
}
luaI_free(vold);
}
/*
** If the hash node is present, return its pointer, otherwise return
** null.
*/
Object *lua_hashget (Hash *t, Object *ref)
{
Word h = present(t, ref);
if (tag(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h));
else return NULL;
}
/*
** If the hash node is present, return its pointer, otherwise create a new
** node for the given reference and also return its pointer.
*/
Object *lua_hashdefine (Hash *t, Object *ref)
{
Word h;
Node *n;
h = present(t, ref);
n = node(t, h);
if (tag(ref(n)) == LUA_T_NIL)
{
nuse(t)++;
if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT)
{
rehash(t);
h = present(t, ref);
n = node(t, h);
}
*ref(n) = *ref;
tag(val(n)) = LUA_T_NIL;
}
return (val(n));
}
/*
** Internal function to manipulate arrays.
** Given an array object and a reference value, return the next element
** in the hash.
** This function pushs the element value and its reference to the stack.
*/
static void hashnext (Hash *t, Word i)
{
if (i >= nhash(t))
{
lua_pushnil(); lua_pushnil();
return;
}
while (tag(ref(node(t,i))) == LUA_T_NIL || tag(val(node(t,i))) == LUA_T_NIL)
{
if (++i >= nhash(t))
{
lua_pushnil(); lua_pushnil();
return;
}
}
luaI_pushobject(ref(node(t,i)));
luaI_pushobject(val(node(t,i)));
}
void lua_next (void)
{
Hash *t;
lua_Object o = lua_getparam(1);
lua_Object r = lua_getparam(2);
if (o == LUA_NOOBJECT || r == LUA_NOOBJECT)
lua_error ("too few arguments to function `next'");
if (lua_getparam(3) != LUA_NOOBJECT)
lua_error ("too many arguments to function `next'");
if (!lua_istable(o))
lua_error ("first argument of function `next' is not a table");
t = avalue(luaI_Address(o));
if (lua_isnil(r))
{
hashnext(t, 0);
}
else
{
Word h = present (t, luaI_Address(r));
hashnext(t, h+1);
}
}

37
hash.h
View File

@@ -1,37 +0,0 @@
/*
** hash.h
** hash manager for lua
** Luiz Henrique de Figueiredo - 17 Aug 90
** $Id: hash.h,v 2.7 1994/12/20 21:20:36 roberto Exp roberto $
*/
#ifndef hash_h
#define hash_h
#include "types.h"
typedef struct node
{
Object ref;
Object val;
} Node;
typedef struct Hash
{
struct Hash *next;
char mark;
Word nhash;
Word nuse;
Node *node;
} Hash;
Bool lua_equalObj (Object *t1, Object *t2);
Hash *lua_createarray (Word nhash);
void lua_hashmark (Hash *h);
Long lua_hashcollector (void);
Object *lua_hashget (Hash *t, Object *ref);
Object *lua_hashdefine (Hash *t, Object *ref);
void lua_next (void);
#endif

220
inout.c
View File

@@ -1,220 +0,0 @@
/*
** inout.c
** Provide function to realise the input/output function and debugger
** facilities.
** Also provides some predefined lua functions.
*/
char *rcs_inout="$Id: inout.c,v 2.24 1995/10/23 13:54:11 roberto Exp roberto $";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mem.h"
#include "opcode.h"
#include "hash.h"
#include "inout.h"
#include "table.h"
#include "tree.h"
#include "lua.h"
#ifndef MAXFUNCSTACK
#define MAXFUNCSTACK 100
#endif
#define MAXMESSAGE MAXFUNCSTACK*80
/* Exported variables */
Word lua_linenumber;
Bool lua_debug = 0;
char *lua_parsedfile;
static FILE *fp;
static char *st;
/*
** Function to get the next character from the input file
*/
static int fileinput (void)
{
return fgetc (fp);
}
/*
** Function to get the next character from the input string
*/
static int stringinput (void)
{
return *st++;
}
/*
** Function to open a file to be input unit.
** Return 0 on success or error message on error.
*/
char *lua_openfile (char *fn)
{
lua_setinput (fileinput);
if (fn == NULL)
{
fp = stdin;
fn = "(stdin)";
}
else
fp = fopen (fn, "r");
if (fp == NULL)
{
static char buff[255];
sprintf(buff, "unable to open file `%.200s'", fn);
return buff;
}
lua_linenumber = 1;
lua_parsedfile = lua_constcreate(fn)->ts.str;
return NULL;
}
/*
** Function to close an opened file
*/
void lua_closefile (void)
{
if (fp != NULL && fp != stdin)
{
fclose (fp);
fp = NULL;
}
}
/*
** Function to open a string to be input unit
*/
void lua_openstring (char *s)
{
lua_setinput (stringinput);
st = s;
lua_linenumber = 1;
lua_parsedfile = lua_constcreate("(string)")->ts.str;
}
/*
** Function to close an opened string
*/
void lua_closestring (void)
{
}
/*
** Internal function: do a string
*/
void lua_internaldostring (void)
{
lua_Object obj = lua_getparam (1);
if (lua_isstring(obj) && !lua_dostring(lua_getstring(obj)))
lua_pushnumber(1);
else
lua_pushnil();
}
/*
** Internal function: do a file
*/
void lua_internaldofile (void)
{
lua_Object obj = lua_getparam (1);
if (lua_isstring(obj) && !lua_dofile(lua_getstring(obj)))
lua_pushnumber(1);
else
lua_pushnil();
}
/*
** Internal function: print object values
*/
void lua_print (void)
{
int i=1;
lua_Object obj;
while ((obj=lua_getparam (i++)) != LUA_NOOBJECT)
{
if (lua_isnumber(obj)) printf("%g\n",lua_getnumber(obj));
else if (lua_isstring(obj)) printf("%s\n",lua_getstring(obj));
else if (lua_isfunction(obj)) printf("function: %p\n",(luaI_Address(obj))->value.tf);
else if (lua_iscfunction(obj)) printf("cfunction: %p\n",lua_getcfunction(obj)
);
else if (lua_isuserdata(obj)) printf("userdata: %p\n",lua_getuserdata(obj));
else if (lua_istable(obj)) printf("table: %p\n",avalue(luaI_Address(obj)));
else if (lua_isnil(obj)) printf("nil\n");
else printf("invalid value to print\n");
}
}
/*
** Internal function: return an object type.
*/
void luaI_type (void)
{
lua_Object o = lua_getparam(1);
int t;
if (o == LUA_NOOBJECT)
lua_error("no parameter to function 'type'");
t = lua_type(o);
switch (t)
{
case LUA_T_NIL :
lua_pushliteral("nil");
break;
case LUA_T_NUMBER :
lua_pushliteral("number");
break;
case LUA_T_STRING :
lua_pushliteral("string");
break;
case LUA_T_ARRAY :
lua_pushliteral("table");
break;
case LUA_T_FUNCTION :
case LUA_T_CFUNCTION :
lua_pushliteral("function");
break;
default :
lua_pushliteral("userdata");
break;
}
lua_pushnumber(t);
}
/*
** Internal function: convert an object to a number
*/
void lua_obj2number (void)
{
lua_Object o = lua_getparam(1);
if (lua_isnumber(o))
lua_pushobject(o);
else if (lua_isstring(o))
{
char c;
float f;
if (sscanf(lua_getstring(o),"%f %c",&f,&c) == 1)
lua_pushnumber(f);
else
lua_pushnil();
}
else
lua_pushnil();
}
void luaI_error (void)
{
char *s = lua_getstring(lua_getparam(1));
if (s == NULL) s = "(no message)";
lua_error(s);
}

29
inout.h
View File

@@ -1,29 +0,0 @@
/*
** $Id: inout.h,v 1.9 1995/05/16 17:23:58 roberto Exp roberto $
*/
#ifndef inout_h
#define inout_h
#include "types.h"
extern Word lua_linenumber;
extern Bool lua_debug;
extern Word lua_debugline;
extern char *lua_parsedfile;
char *lua_openfile (char *fn);
void lua_closefile (void);
void lua_openstring (char *s);
void lua_closestring (void);
void lua_internaldofile (void);
void lua_internaldostring (void);
void lua_print (void);
void luaI_type (void);
void lua_obj2number (void);
void luaI_error (void);
#endif

622
iolib.c
View File

@@ -1,622 +0,0 @@
/*
** iolib.c
** Input/output library to LUA
*/
char *rcs_iolib="$Id: iolib.c,v 1.28 1995/11/10 17:55:48 roberto Exp roberto $";
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include "lua.h"
#include "luadebug.h"
#include "lualib.h"
static FILE *in=stdin, *out=stdout;
#ifdef POPEN
FILE *popen();
int pclose();
#else
#define popen(x,y) NULL /* that is, popen always fails */
#define pclose(x) (-1)
#endif
static void closeread (void)
{
if (in != stdin)
{
if (pclose(in) == -1)
fclose(in);
in = stdin;
}
}
static void closewrite (void)
{
if (out != stdout)
{
if (pclose(out) == -1)
fclose(out);
out = stdout;
}
}
/*
** Open a file to read.
** LUA interface:
** status = readfrom (filename)
** where:
** status = 1 -> success
** status = nil -> error
*/
static void io_readfrom (void)
{
if (lua_getparam (1) == LUA_NOOBJECT)
{ /* restore standart input */
closeread();
lua_pushnumber (1);
}
else
{
char *s = lua_check_string(1, "readfrom");
FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
if (fp == NULL)
lua_pushnil();
else
{
closeread();
in = fp;
lua_pushnumber (1);
}
}
}
/*
** Open a file to write.
** LUA interface:
** status = writeto (filename)
** where:
** status = 1 -> success
** status = nil -> error
*/
static void io_writeto (void)
{
if (lua_getparam (1) == LUA_NOOBJECT) /* restore standart output */
{
closewrite();
lua_pushnumber (1);
}
else
{
char *s = lua_check_string(1, "writeto");
FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w");
if (fp == NULL)
lua_pushnil();
else
{
closewrite();
out = fp;
lua_pushnumber (1);
}
}
}
/*
** Open a file to write appended.
** LUA interface:
** status = appendto (filename)
** where:
** status = 2 -> success (already exist)
** status = 1 -> success (new file)
** status = nil -> error
*/
static void io_appendto (void)
{
char *s = lua_check_string(1, "appendto");
struct stat st;
int r = (stat(s, &st) == -1) ? 1 : 2;
FILE *fp = fopen (s, "a");
if (fp == NULL)
lua_pushnil();
else
{
if (out != stdout) fclose (out);
out = fp;
lua_pushnumber (r);
}
}
static char getformat (char *f, int *just, int *m, int *n)
{
int t;
switch (*f++)
{
case 's': case 'S':
t = 's';
break;
case 'f': case 'F': case 'g': case 'G': case 'e': case 'E':
t = 'f';
break;
case 'i': case 'I':
t = 'i';
break;
default:
t = 0; /* to avoid compiler warnings */
lua_arg_error("read/write (format)");
}
*just = (*f == '<' || *f == '>' || *f == '|') ? *f++ : '>';
if (isdigit(*f))
{
*m = 0;
while (isdigit(*f))
*m = *m*10 + (*f++ - '0');
}
else
*m = -1;
if (*f == '.')
{
f++; /* skip point */
*n = 0;
while (isdigit(*f))
*n = *n*10 + (*f++ - '0');
}
else
*n = -1;
return t;
}
static char *add_char (int c)
{
static char *buff = NULL;
static int max = 0;
static int n = 0;
if (n >= max)
{
if (max == 0)
{
max = 100;
buff = (char *)malloc(max);
}
else
{
max *= 2;
buff = (char *)realloc(buff, max);
}
if (buff == NULL)
lua_error("memory overflow");
}
buff[n++] = c;
if (c == 0)
n = 0; /* prepare for next string */
return buff;
}
/*
** Read a variable. On error put nil on stack.
** LUA interface:
** variable = read ([format])
**
** O formato pode ter um dos seguintes especificadores:
**
** s ou S -> para string
** f ou F, g ou G, e ou E -> para reais
** i ou I -> para inteiros
**
** Estes especificadores podem vir seguidos de numero que representa
** o numero de campos a serem lidos.
*/
static int read_until_char (int del)
{
int c;
while((c = fgetc(in)) != EOF && c != del)
add_char(c);
return c;
}
static int read_until_blank (void)
{
int c;
while((c = fgetc(in)) != EOF && !isspace(c))
add_char(c);
return c;
}
static void read_m (int m)
{
int c;
while (m-- && (c = fgetc(in)) != EOF)
add_char(c);
}
static void read_free (void)
{
int c;
while (isspace(c=fgetc(in)))
;
if (c == EOF)
{
lua_pushnil();
return;
}
if (c == '\"' || c == '\'')
{ /* string */
c = read_until_char(c);
if (c == EOF)
{
add_char(0); /* to be ready for next time */
lua_pushnil();
}
else
lua_pushstring(add_char(0));
}
else
{
double d;
char dummy;
char *s;
add_char(c);
read_until_blank();
s = add_char(0);
if (sscanf(s, "%lf %c", &d, &dummy) == 1)
lua_pushnumber(d);
else
lua_pushstring(s);
}
}
static void io_read (void)
{
lua_Object o = lua_getparam (1);
if (o == LUA_NOOBJECT) /* free format */
read_free();
else /* formatted */
{
int m, dummy1, dummy2;
switch (getformat(lua_check_string(1, "read"), &dummy1, &m, &dummy2))
{
case 's':
if (m < 0)
read_until_blank();
else
read_m(m);
lua_pushstring(add_char(0));
break;
case 'i': /* can read as float, since it makes no difference to Lua */
case 'f':
{
double d;
int result;
if (m < 0)
result = fscanf(in, "%lf", &d);
else
{
read_m(m);
result = sscanf(add_char(0), "%lf", &d);
}
if (result == 1)
lua_pushnumber(d);
else
lua_pushnil();
break;
}
}
}
}
/*
** Read characters until a given one. The delimiter is not read.
*/
static void io_readuntil (void)
{
int del = *lua_check_string(1, "readuntil");
int c = read_until_char(del);
if (c != EOF) ungetc(c,in);
lua_pushstring(add_char(0));
}
/*
** Write a variable. On error put 0 on stack, otherwise put 1.
** LUA interface:
** status = write (variable [,format])
**
** O formato pode ter um dos seguintes especificadores:
**
** s ou S -> para string
** f ou F, g ou G, e ou E -> para reais
** i ou I -> para inteiros
**
** Estes especificadores podem vir seguidos de:
**
** [?][m][.n]
**
** onde:
** ? -> indica justificacao
** < = esquerda
** | = centro
** > = direita (default)
** m -> numero maximo de campos (se exceder estoura)
** n -> indica precisao para
** reais -> numero de casas decimais
** inteiros -> numero minimo de digitos
** string -> nao se aplica
*/
static int write_fill (int n, int c)
{
while (n--)
if (fputc(c, out) == EOF)
return 0;
return 1;
}
static int write_string (char *s, int just, int m)
{
int status;
int l = strlen(s);
int pre; /* number of blanks before string */
if (m < 0) m = l;
else if (l > m)
{
write_fill(m, '*');
return 0;
}
pre = (just == '<') ? 0 : (just == '>') ? m-l : (m-l)/2;
status = write_fill(pre, ' ');
status = status && fprintf(out, "%s", s) >= 0;
status = status && write_fill(m-(l+pre), ' ');
return status;
}
static int write_float (int just, int m, int n)
{
char buffer[100];
lua_Object p = lua_getparam(1);
float number;
if (!lua_isnumber(p)) return 0;
number = lua_getnumber(p);
if (n >= 0)
sprintf(buffer, "%.*f", n, number);
else
sprintf(buffer, "%g", number);
return write_string(buffer, just, m);
}
static int write_int (int just, int m, int n)
{
char buffer[100];
lua_Object p = lua_getparam(1);
int number;
if (!lua_isnumber(p)) return 0;
number = (int)lua_getnumber(p);
if (n >= 0)
sprintf(buffer, "%.*d", n, number);
else
sprintf(buffer, "%d", number);
return write_string(buffer, just, m);
}
static void io_write (void)
{
int status = 0;
if (lua_getparam (2) == LUA_NOOBJECT) /* free format */
{
lua_Object o1 = lua_getparam(1);
if (lua_isnumber(o1))
status = fprintf (out, "%g", lua_getnumber(o1)) >= 0;
else if (lua_isstring(o1))
status = fprintf (out, "%s", lua_getstring(o1)) >= 0;
}
else /* formated */
{
int just, m, n;
switch (getformat (lua_check_string(2, "write"), &just, &m, &n))
{
case 's':
{
lua_Object p = lua_getparam(1);
if (lua_isstring(p))
status = write_string(lua_getstring(p), just, m);
else
status = 0;
break;
}
case 'f':
status = write_float(just, m, n);
break;
case 'i':
status = write_int(just, m, n);
break;
}
}
if (status)
lua_pushnumber(status);
else
lua_pushnil();
}
/*
** Execute a executable program using "system".
** Return the result of execution.
*/
static void io_execute (void)
{
lua_pushnumber(system(lua_check_string(1, "execute")));
}
/*
** Remove a file. On error return nil.
*/
static void io_remove (void)
{
if (remove(lua_check_string(1, "remove")) == 0)
lua_pushnumber (1);
else
lua_pushnil();
}
/*
** To get a environment variables
*/
static void io_getenv (void)
{
char *env = getenv(lua_check_string(1, "getenv"));
if (env == NULL) lua_pushnil();
else lua_pushstring(env);
}
/*
** Return time: hour, min, sec
*/
static void io_time (void)
{
time_t t;
struct tm *s;
time(&t);
s = localtime(&t);
lua_pushnumber(s->tm_hour);
lua_pushnumber(s->tm_min);
lua_pushnumber(s->tm_sec);
}
/*
** Return date: dd, mm, yyyy
*/
static void io_date (void)
{
time_t t;
struct tm *s;
time(&t);
s = localtime(&t);
lua_pushnumber(s->tm_mday);
lua_pushnumber(s->tm_mon+1);
lua_pushnumber(s->tm_year+1900);
}
/*
** Beep
*/
static void io_beep (void)
{
printf("\a");
}
/*
** To exit
*/
static void io_exit (void)
{
lua_Object o = lua_getparam(1);
if (lua_isstring(o))
fprintf(stderr, "%s\n", lua_getstring(o));
exit(1);
}
/*
** To debug a lua program. Start a dialog with the user, interpreting
lua commands until an 'cont'.
*/
static void io_debug (void)
{
while (1)
{
char buffer[250];
fprintf(stderr, "lua_debug> ");
if (gets(buffer) == 0) return;
if (strcmp(buffer, "cont") == 0) return;
lua_dostring(buffer);
}
}
void lua_printstack (FILE *f)
{
int level = 0;
lua_Object func;
fprintf(f, "Active Stack:\n");
while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT)
{
char *name;
int currentline;
fprintf(f, "\t");
switch (*getobjname(func, &name))
{
case 'g':
fprintf(f, "function %s", name);
break;
case 'f':
fprintf(f, "fallback %s", name);
break;
default:
{
char *filename;
int linedefined;
lua_funcinfo(func, &filename, &linedefined);
if (linedefined == 0)
fprintf(f, "main of %s", filename);
else if (linedefined < 0)
fprintf(f, "%s", filename);
else
fprintf(f, "function (%s:%d)", filename, linedefined);
}
}
if ((currentline = lua_currentline(func)) > 0)
fprintf(f, " at line %d", currentline);
fprintf(f, "\n");
}
}
static void errorfb (void)
{
lua_Object o = lua_getparam(1);
char *s = lua_isstring(o) ? lua_getstring(o) : "(no messsage)";
fprintf(stderr, "lua: %s\n", s);
lua_printstack(stderr);
}
/*
** Open io library
*/
void iolib_open (void)
{
lua_register ("readfrom", io_readfrom);
lua_register ("writeto", io_writeto);
lua_register ("appendto", io_appendto);
lua_register ("read", io_read);
lua_register ("readuntil",io_readuntil);
lua_register ("write", io_write);
lua_register ("execute", io_execute);
lua_register ("remove", io_remove);
lua_register ("getenv", io_getenv);
lua_register ("time", io_time);
lua_register ("date", io_date);
lua_register ("beep", io_beep);
lua_register ("exit", io_exit);
lua_register ("debug", io_debug);
lua_register ("print_stack", errorfb);
lua_setfallback("error", errorfb);
}

693
lapi.c Normal file
View File

@@ -0,0 +1,693 @@
/*
** $Id: lapi.c,v 1.46 1999/06/17 17:04:03 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#include <string.h>
#include "lapi.h"
#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lua.h"
#include "luadebug.h"
#include "lvm.h"
char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
"$Authors: " LUA_AUTHORS " $";
TObject *luaA_Address (lua_Object o) {
return (o != LUA_NOOBJECT) ? Address(o) : NULL;
}
static lua_Type normalized_type (TObject *o)
{
int t = ttype(o);
switch (t) {
case LUA_T_PMARK:
return LUA_T_PROTO;
case LUA_T_CMARK:
return LUA_T_CPROTO;
case LUA_T_CLMARK:
return LUA_T_CLOSURE;
default:
return t;
}
}
static void set_normalized (TObject *d, TObject *s)
{
d->value = s->value;
d->ttype = normalized_type(s);
}
static TObject *luaA_protovalue (TObject *o)
{
return (normalized_type(o) == LUA_T_CLOSURE) ? protovalue(o) : o;
}
void luaA_packresults (void)
{
luaV_pack(L->Cstack.lua2C, L->Cstack.num, L->stack.top);
incr_top;
}
int luaA_passresults (void) {
L->Cstack.base = L->Cstack.lua2C; /* position of first result */
return L->Cstack.num;
}
static void checkCparams (int nParams)
{
if (L->stack.top-L->stack.stack < L->Cstack.base+nParams)
lua_error("API error - wrong number of arguments in C2lua stack");
}
static lua_Object put_luaObject (TObject *o) {
luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
L->stack.stack[L->Cstack.base++] = *o;
return L->Cstack.base; /* this is +1 real position (see Ref) */
}
static lua_Object put_luaObjectonTop (void) {
luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
L->stack.stack[L->Cstack.base++] = *(--L->stack.top);
return L->Cstack.base; /* this is +1 real position (see Ref) */
}
static void top2LC (int n) {
/* Put the 'n' elements on the top as the Lua2C contents */
L->Cstack.base = (L->stack.top-L->stack.stack); /* new base */
L->Cstack.lua2C = L->Cstack.base-n; /* position of the new results */
L->Cstack.num = n; /* number of results */
}
lua_Object lua_pop (void) {
checkCparams(1);
return put_luaObjectonTop();
}
/*
** Get a parameter, returning the object handle or LUA_NOOBJECT on error.
** 'number' must be 1 to get the first parameter.
*/
lua_Object lua_lua2C (int number)
{
if (number <= 0 || number > L->Cstack.num) return LUA_NOOBJECT;
/* Ref(L->stack.stack+(L->Cstack.lua2C+number-1)) ==
L->stack.stack+(L->Cstack.lua2C+number-1)-L->stack.stack+1 == */
return L->Cstack.lua2C+number;
}
int lua_callfunction (lua_Object function)
{
if (function == LUA_NOOBJECT)
return 1;
else {
luaD_openstack((L->stack.top-L->stack.stack)-L->Cstack.base);
set_normalized(L->stack.stack+L->Cstack.base, Address(function));
return luaD_protectedrun();
}
}
lua_Object lua_gettagmethod (int tag, char *event)
{
return put_luaObject(luaT_gettagmethod(tag, event));
}
lua_Object lua_settagmethod (int tag, char *event)
{
checkCparams(1);
luaT_settagmethod(tag, event, L->stack.top-1);
return put_luaObjectonTop();
}
lua_Object lua_seterrormethod (void) {
lua_Object temp;
checkCparams(1);
temp = lua_getglobal("_ERRORMESSAGE");
lua_setglobal("_ERRORMESSAGE");
return temp;
}
lua_Object lua_gettable (void)
{
checkCparams(2);
luaV_gettable();
return put_luaObjectonTop();
}
lua_Object lua_rawgettable (void) {
checkCparams(2);
if (ttype(L->stack.top-2) != LUA_T_ARRAY)
lua_error("indexed expression not a table in rawgettable");
*(L->stack.top-2) = *luaH_get(avalue(L->stack.top-2), L->stack.top-1);
--L->stack.top;
return put_luaObjectonTop();
}
void lua_settable (void) {
checkCparams(3);
luaV_settable(L->stack.top-3);
L->stack.top -= 2; /* pop table and index */
}
void lua_rawsettable (void) {
checkCparams(3);
luaV_rawsettable(L->stack.top-3);
}
lua_Object lua_createtable (void)
{
TObject o;
luaC_checkGC();
avalue(&o) = luaH_new(0);
ttype(&o) = LUA_T_ARRAY;
return put_luaObject(&o);
}
lua_Object lua_getglobal (char *name)
{
luaD_checkstack(2); /* may need that to call T.M. */
luaV_getglobal(luaS_new(name));
return put_luaObjectonTop();
}
lua_Object lua_rawgetglobal (char *name)
{
TaggedString *ts = luaS_new(name);
return put_luaObject(&ts->u.s.globalval);
}
void lua_setglobal (char *name)
{
checkCparams(1);
luaD_checkstack(2); /* may need that to call T.M. */
luaV_setglobal(luaS_new(name));
}
void lua_rawsetglobal (char *name)
{
TaggedString *ts = luaS_new(name);
checkCparams(1);
luaS_rawsetglobal(ts, --L->stack.top);
}
int lua_isnil (lua_Object o)
{
return (o!= LUA_NOOBJECT) && (ttype(Address(o)) == LUA_T_NIL);
}
int lua_istable (lua_Object o)
{
return (o!= LUA_NOOBJECT) && (ttype(Address(o)) == LUA_T_ARRAY);
}
int lua_isuserdata (lua_Object o)
{
return (o!= LUA_NOOBJECT) && (ttype(Address(o)) == LUA_T_USERDATA);
}
int lua_iscfunction (lua_Object o)
{
return (lua_tag(o) == LUA_T_CPROTO);
}
int lua_isnumber (lua_Object o)
{
return (o!= LUA_NOOBJECT) && (tonumber(Address(o)) == 0);
}
int lua_isstring (lua_Object o)
{
int t = lua_tag(o);
return (t == LUA_T_STRING) || (t == LUA_T_NUMBER);
}
int lua_isfunction (lua_Object o)
{
int t = lua_tag(o);
return (t == LUA_T_PROTO) || (t == LUA_T_CPROTO);
}
double lua_getnumber (lua_Object object)
{
if (object == LUA_NOOBJECT) return 0.0;
if (tonumber(Address(object))) return 0.0;
else return (nvalue(Address(object)));
}
char *lua_getstring (lua_Object object)
{
luaC_checkGC(); /* "tostring" may create a new string */
if (object == LUA_NOOBJECT || tostring(Address(object)))
return NULL;
else return (svalue(Address(object)));
}
long lua_strlen (lua_Object object)
{
luaC_checkGC(); /* "tostring" may create a new string */
if (object == LUA_NOOBJECT || tostring(Address(object)))
return 0L;
else return (tsvalue(Address(object))->u.s.len);
}
void *lua_getuserdata (lua_Object object)
{
if (object == LUA_NOOBJECT || ttype(Address(object)) != LUA_T_USERDATA)
return NULL;
else return tsvalue(Address(object))->u.d.v;
}
lua_CFunction lua_getcfunction (lua_Object object)
{
if (!lua_iscfunction(object))
return NULL;
else return fvalue(luaA_protovalue(Address(object)));
}
void lua_pushnil (void)
{
ttype(L->stack.top) = LUA_T_NIL;
incr_top;
}
void lua_pushnumber (double n)
{
ttype(L->stack.top) = LUA_T_NUMBER;
nvalue(L->stack.top) = n;
incr_top;
}
void lua_pushlstring (char *s, long len)
{
tsvalue(L->stack.top) = luaS_newlstr(s, len);
ttype(L->stack.top) = LUA_T_STRING;
incr_top;
luaC_checkGC();
}
void lua_pushstring (char *s)
{
if (s == NULL)
lua_pushnil();
else
lua_pushlstring(s, strlen(s));
}
void lua_pushcclosure (lua_CFunction fn, int n)
{
if (fn == NULL)
lua_error("API error - attempt to push a NULL Cfunction");
checkCparams(n);
ttype(L->stack.top) = LUA_T_CPROTO;
fvalue(L->stack.top) = fn;
incr_top;
luaV_closure(n);
luaC_checkGC();
}
void lua_pushusertag (void *u, int tag)
{
if (tag < 0 && tag != LUA_ANYTAG)
luaT_realtag(tag); /* error if tag is not valid */
tsvalue(L->stack.top) = luaS_createudata(u, tag);
ttype(L->stack.top) = LUA_T_USERDATA;
incr_top;
luaC_checkGC();
}
void luaA_pushobject (TObject *o)
{
*L->stack.top = *o;
incr_top;
}
void lua_pushobject (lua_Object o) {
if (o == LUA_NOOBJECT)
lua_error("API error - attempt to push a NOOBJECT");
set_normalized(L->stack.top, Address(o));
incr_top;
}
int lua_tag (lua_Object lo)
{
if (lo == LUA_NOOBJECT)
return LUA_T_NIL;
else {
TObject *o = Address(lo);
int t;
switch (t = ttype(o)) {
case LUA_T_USERDATA:
return o->value.ts->u.d.tag;
case LUA_T_ARRAY:
return o->value.a->htag;
case LUA_T_PMARK:
return LUA_T_PROTO;
case LUA_T_CMARK:
return LUA_T_CPROTO;
case LUA_T_CLOSURE: case LUA_T_CLMARK:
return o->value.cl->consts[0].ttype;
#ifdef DEBUG
case LUA_T_LINE:
LUA_INTERNALERROR("invalid type");
#endif
default:
return t;
}
}
}
void lua_settag (int tag)
{
checkCparams(1);
luaT_realtag(tag);
switch (ttype(L->stack.top-1)) {
case LUA_T_ARRAY:
(L->stack.top-1)->value.a->htag = tag;
break;
case LUA_T_USERDATA:
(L->stack.top-1)->value.ts->u.d.tag = tag;
break;
default:
luaL_verror("cannot change the tag of a %.20s",
luaO_typename(L->stack.top-1));
}
L->stack.top--;
}
TaggedString *luaA_nextvar (TaggedString *g) {
if (g == NULL)
g = (TaggedString *)L->rootglobal.next; /* first variable */
else {
/* check whether name is in global var list */
luaL_arg_check((GCnode *)g != g->head.next, 1, "variable name expected");
g = (TaggedString *)g->head.next; /* get next */
}
while (g && g->u.s.globalval.ttype == LUA_T_NIL) /* skip globals with nil */
g = (TaggedString *)g->head.next;
if (g) {
ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g;
incr_top;
luaA_pushobject(&g->u.s.globalval);
}
return g;
}
char *lua_nextvar (char *varname) {
TaggedString *g = (varname == NULL) ? NULL : luaS_new(varname);
g = luaA_nextvar(g);
if (g) {
top2LC(2);
return g->str;
}
else {
top2LC(0);
return NULL;
}
}
int luaA_next (Hash *t, int i) {
int tsize = nhash(t);
for (; i<tsize; i++) {
Node *n = node(t, i);
if (ttype(val(n)) != LUA_T_NIL) {
luaA_pushobject(ref(n));
luaA_pushobject(val(n));
return i+1; /* index to be used next time */
}
}
return 0; /* no more elements */
}
int lua_next (lua_Object o, int i) {
TObject *t = Address(o);
if (ttype(t) != LUA_T_ARRAY)
lua_error("API error - object is not a table in `lua_next'");
i = luaA_next(avalue(t), i);
top2LC((i==0) ? 0 : 2);
return i;
}
/*
** {======================================================
** To manipulate some state information
** =======================================================
*/
lua_State *lua_setstate (lua_State *st) {
lua_State *old = lua_state;
lua_state = st;
return old;
}
lua_LHFunction lua_setlinehook (lua_LHFunction func) {
lua_LHFunction old = L->linehook;
L->linehook = func;
return old;
}
lua_CHFunction lua_setcallhook (lua_CHFunction func) {
lua_CHFunction old = L->callhook;
L->callhook = func;
return old;
}
int lua_setdebug (int debug) {
int old = L->debug;
L->debug = debug;
return old;
}
/* }====================================================== */
/*
** {======================================================
** Debug interface
** =======================================================
*/
lua_Function lua_stackedfunction (int level)
{
StkId i;
for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) {
int t = L->stack.stack[i].ttype;
if (t == LUA_T_CLMARK || t == LUA_T_PMARK || t == LUA_T_CMARK)
if (level-- == 0)
return Ref(L->stack.stack+i);
}
return LUA_NOOBJECT;
}
int lua_nups (lua_Function func) {
TObject *o = luaA_Address(func);
return (!o || normalized_type(o) != LUA_T_CLOSURE) ? 0 : o->value.cl->nelems;
}
int lua_currentline (lua_Function func)
{
TObject *f = Address(func);
return (f+1 < L->stack.top && (f+1)->ttype == LUA_T_LINE) ?
(f+1)->value.i : -1;
}
lua_Object lua_getlocal (lua_Function func, int local_number, char **name) {
/* check whether func is a Lua function */
if (lua_tag(func) != LUA_T_PROTO)
return LUA_NOOBJECT;
else {
TObject *f = Address(func);
TProtoFunc *fp = luaA_protovalue(f)->value.tf;
*name = luaF_getlocalname(fp, local_number, lua_currentline(func));
if (*name) {
/* if "*name", there must be a LUA_T_LINE */
/* therefore, f+2 points to function base */
return put_luaObject((f+2)+(local_number-1));
}
else
return LUA_NOOBJECT;
}
}
int lua_setlocal (lua_Function func, int local_number)
{
/* check whether func is a Lua function */
if (lua_tag(func) != LUA_T_PROTO)
return 0;
else {
TObject *f = Address(func);
TProtoFunc *fp = luaA_protovalue(f)->value.tf;
char *name = luaF_getlocalname(fp, local_number, lua_currentline(func));
checkCparams(1);
--L->stack.top;
if (name) {
/* if "name", there must be a LUA_T_LINE */
/* therefore, f+2 points to function base */
*((f+2)+(local_number-1)) = *L->stack.top;
return 1;
}
else
return 0;
}
}
void lua_funcinfo (lua_Object func, char **source, int *linedefined) {
if (!lua_isfunction(func))
lua_error("API error - `funcinfo' called with a non-function value");
else {
TObject *f = luaA_protovalue(Address(func));
if (normalized_type(f) == LUA_T_PROTO) {
*source = tfvalue(f)->source->str;
*linedefined = tfvalue(f)->lineDefined;
}
else {
*source = "(C)";
*linedefined = -1;
}
}
}
static int checkfunc (TObject *o)
{
return luaO_equalObj(o, L->stack.top);
}
char *lua_getobjname (lua_Object o, char **name)
{ /* try to find a name for given function */
set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc" */
if ((*name = luaS_travsymbol(checkfunc)) != NULL)
return "global";
else if ((*name = luaT_travtagmethods(checkfunc)) != NULL)
return "tag-method";
else return "";
}
/* }====================================================== */
/*
** {======================================================
** BLOCK mechanism
** =======================================================
*/
#ifndef MAX_C_BLOCKS
#define MAX_C_BLOCKS 1000 /* arbitrary limit */
#endif
void lua_beginblock (void) {
luaM_growvector(L->Cblocks, L->numCblocks, 1, struct C_Lua_Stack,
"too many nested blocks", MAX_C_BLOCKS);
L->Cblocks[L->numCblocks] = L->Cstack;
L->numCblocks++;
}
void lua_endblock (void) {
--L->numCblocks;
L->Cstack = L->Cblocks[L->numCblocks];
luaD_adjusttop(L->Cstack.base);
}
int lua_ref (int lock) {
int ref;
checkCparams(1);
ref = luaC_ref(L->stack.top-1, lock);
L->stack.top--;
return ref;
}
lua_Object lua_getref (int ref) {
TObject *o = luaC_getref(ref);
return (o ? put_luaObject(o) : LUA_NOOBJECT);
}
/* }====================================================== */
#ifdef LUA_COMPAT2_5
/*
** API: set a function as a fallback
*/
static void do_unprotectedrun (lua_CFunction f, int nParams, int nResults) {
luaD_openstack(nParams);
(L->stack.top-nParams)->ttype = LUA_T_CPROTO;
(L->stack.top-nParams)->value.f = f;
luaD_calln(nParams, nResults);
}
lua_Object lua_setfallback (char *name, lua_CFunction fallback) {
lua_pushstring(name);
lua_pushcfunction(fallback);
do_unprotectedrun(luaT_setfallback, 2, 1);
return put_luaObjectonTop();
}
#endif

22
lapi.h Normal file
View File

@@ -0,0 +1,22 @@
/*
** $Id: lapi.h,v 1.3 1999/02/22 19:13:12 roberto Exp roberto $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "lua.h"
#include "lobject.h"
TObject *luaA_Address (lua_Object o);
void luaA_pushobject (TObject *o);
void luaA_packresults (void);
int luaA_passresults (void);
TaggedString *luaA_nextvar (TaggedString *g);
int luaA_next (Hash *t, int i);
#endif

133
lauxlib.c Normal file
View File

@@ -0,0 +1,133 @@
/*
** $Id: lauxlib.c,v 1.16 1999/03/10 14:19:41 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
/* Please Notice: This file uses only the official API of Lua
** Any function declared here could be written as an application function.
** With care, these functions can be used by other libraries.
*/
#include "lauxlib.h"
#include "lua.h"
#include "luadebug.h"
int luaL_findstring (char *name, char *list[]) {
int i;
for (i=0; list[i]; i++)
if (strcmp(list[i], name) == 0)
return i;
return -1; /* name not found */
}
void luaL_argerror (int numarg, char *extramsg) {
lua_Function f = lua_stackedfunction(0);
char *funcname;
lua_getobjname(f, &funcname);
numarg -= lua_nups(f);
if (funcname == NULL)
funcname = "?";
if (extramsg == NULL)
luaL_verror("bad argument #%d to function `%.50s'", numarg, funcname);
else
luaL_verror("bad argument #%d to function `%.50s' (%.100s)",
numarg, funcname, extramsg);
}
char *luaL_check_lstr (int numArg, long *len)
{
lua_Object o = lua_getparam(numArg);
luaL_arg_check(lua_isstring(o), numArg, "string expected");
if (len) *len = lua_strlen(o);
return lua_getstring(o);
}
char *luaL_opt_lstr (int numArg, char *def, long *len)
{
return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
luaL_check_lstr(numArg, len);
}
double luaL_check_number (int numArg)
{
lua_Object o = lua_getparam(numArg);
luaL_arg_check(lua_isnumber(o), numArg, "number expected");
return lua_getnumber(o);
}
double luaL_opt_number (int numArg, double def)
{
return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
luaL_check_number(numArg);
}
lua_Object luaL_tablearg (int arg)
{
lua_Object o = lua_getparam(arg);
luaL_arg_check(lua_istable(o), arg, "table expected");
return o;
}
lua_Object luaL_functionarg (int arg)
{
lua_Object o = lua_getparam(arg);
luaL_arg_check(lua_isfunction(o), arg, "function expected");
return o;
}
lua_Object luaL_nonnullarg (int numArg)
{
lua_Object o = lua_getparam(numArg);
luaL_arg_check(o != LUA_NOOBJECT, numArg, "value expected");
return o;
}
void luaL_openlib (struct luaL_reg *l, int n)
{
int i;
lua_open(); /* make sure lua is already open */
for (i=0; i<n; i++)
lua_register(l[i].name, l[i].func);
}
void luaL_verror (char *fmt, ...)
{
char buff[500];
va_list argp;
va_start(argp, fmt);
vsprintf(buff, fmt, argp);
va_end(argp);
lua_error(buff);
}
void luaL_chunkid (char *out, char *source, int len) {
len -= 13; /* 13 = strlen("string ''...\0") */
if (*source == '@')
sprintf(out, "file `%.*s'", len, source+1);
else if (*source == '(')
strcpy(out, "(C code)");
else {
char *b = strchr(source , '\n'); /* stop string at first new line */
int lim = (b && (b-source)<len) ? b-source : len;
sprintf(out, "string `%.*s'", lim, source);
strcpy(out+lim+(13-5), "...'"); /* 5 = strlen("...'\0") */
}
}
void luaL_filesource (char *out, char *filename, int len) {
if (filename == NULL) filename = "(stdin)";
sprintf(out, "@%.*s", len-2, filename); /* -2 for '@' and '\0' */
}

53
lauxlib.h Normal file
View File

@@ -0,0 +1,53 @@
/*
** $Id: lauxlib.h,v 1.11 1999/03/04 21:17:26 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef auxlib_h
#define auxlib_h
#include "lua.h"
struct luaL_reg {
char *name;
lua_CFunction func;
};
#define luaL_arg_check(cond,numarg,extramsg) if (!(cond)) \
luaL_argerror(numarg,extramsg)
void luaL_openlib (struct luaL_reg *l, int n);
void luaL_argerror (int numarg, char *extramsg);
#define luaL_check_string(n) (luaL_check_lstr((n), NULL))
char *luaL_check_lstr (int numArg, long *len);
#define luaL_opt_string(n, d) (luaL_opt_lstr((n), (d), NULL))
char *luaL_opt_lstr (int numArg, char *def, long *len);
double luaL_check_number (int numArg);
#define luaL_check_int(n) ((int)luaL_check_number(n))
#define luaL_check_long(n) ((long)luaL_check_number(n))
double luaL_opt_number (int numArg, double def);
#define luaL_opt_int(n,d) ((int)luaL_opt_number(n,d))
#define luaL_opt_long(n,d) ((long)luaL_opt_number(n,d))
lua_Object luaL_functionarg (int arg);
lua_Object luaL_tablearg (int arg);
lua_Object luaL_nonnullarg (int numArg);
void luaL_verror (char *fmt, ...);
char *luaL_openspace (int size);
void luaL_resetbuffer (void);
void luaL_addchar (int c);
int luaL_getsize (void);
void luaL_addsize (int n);
int luaL_newbuffer (int size);
void luaL_oldbuffer (int old);
char *luaL_buffer (void);
int luaL_findstring (char *name, char *list[]);
void luaL_chunkid (char *out, char *source, int len);
void luaL_filesource (char *out, char *filename, int len);
#endif

75
lbuffer.c Normal file
View File

@@ -0,0 +1,75 @@
/*
** $Id: lbuffer.c,v 1.8 1999/02/25 19:20:40 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include "lauxlib.h"
#include "lmem.h"
#include "lstate.h"
/*-------------------------------------------------------
** Auxiliary buffer
-------------------------------------------------------*/
#define EXTRABUFF 32
#define openspace(size) if (L->Mbuffnext+(size) > L->Mbuffsize) Openspace(size)
static void Openspace (int size) {
lua_State *l = L; /* to optimize */
size += EXTRABUFF;
l->Mbuffsize = l->Mbuffnext+size;
luaM_growvector(l->Mbuffer, l->Mbuffnext, size, char, arrEM, MAX_INT);
}
char *luaL_openspace (int size) {
openspace(size);
return L->Mbuffer+L->Mbuffnext;
}
void luaL_addchar (int c) {
openspace(1);
L->Mbuffer[L->Mbuffnext++] = (char)c;
}
void luaL_resetbuffer (void) {
L->Mbuffnext = L->Mbuffbase;
}
void luaL_addsize (int n) {
L->Mbuffnext += n;
}
int luaL_getsize (void) {
return L->Mbuffnext-L->Mbuffbase;
}
int luaL_newbuffer (int size) {
int old = L->Mbuffbase;
openspace(size);
L->Mbuffbase = L->Mbuffnext;
return old;
}
void luaL_oldbuffer (int old) {
L->Mbuffnext = L->Mbuffbase;
L->Mbuffbase = old;
}
char *luaL_buffer (void) {
return L->Mbuffer+L->Mbuffbase;
}

736
lbuiltin.c Normal file
View File

@@ -0,0 +1,736 @@
/*
** $Id: lbuiltin.c,v 1.58 1999/05/27 20:21:03 roberto Exp roberto $
** Built-in functions
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lapi.h"
#include "lauxlib.h"
#include "lbuiltin.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lua.h"
#include "lundump.h"
#include "lvm.h"
/*
** {======================================================
** Auxiliary functions
** =======================================================
*/
static void pushtagstring (TaggedString *s) {
TObject o;
o.ttype = LUA_T_STRING;
o.value.ts = s;
luaA_pushobject(&o);
}
static real getsize (Hash *h) {
real max = 0;
int i;
for (i = 0; i<nhash(h); i++) {
Node *n = h->node+i;
if (ttype(ref(n)) == LUA_T_NUMBER &&
ttype(val(n)) != LUA_T_NIL &&
nvalue(ref(n)) > max)
max = nvalue(ref(n));
}
return max;
}
static real getnarg (Hash *a) {
TObject index;
TObject *value;
/* value = table.n */
ttype(&index) = LUA_T_STRING;
tsvalue(&index) = luaS_new("n");
value = luaH_get(a, &index);
return (ttype(value) == LUA_T_NUMBER) ? nvalue(value) : getsize(a);
}
static Hash *gethash (int arg) {
return avalue(luaA_Address(luaL_tablearg(arg)));
}
/* }====================================================== */
/*
** {======================================================
** Functions that use only the official API
** =======================================================
*/
/*
** If your system does not support "stderr", redefine this function, or
** redefine _ERRORMESSAGE so that it won't need _ALERT.
*/
static void luaB_alert (void) {
fputs(luaL_check_string(1), stderr);
}
/*
** Standard implementation of _ERRORMESSAGE.
** The library "iolib" redefines _ERRORMESSAGE for better error information.
*/
static void error_message (void) {
lua_Object al = lua_rawgetglobal("_ALERT");
if (lua_isfunction(al)) { /* avoid error loop if _ALERT is not defined */
char buff[600];
sprintf(buff, "lua error: %.500s\n", luaL_check_string(1));
lua_pushstring(buff);
lua_callfunction(al);
}
}
/*
** If your system does not support "stdout", just remove this function.
** If you need, you can define your own "print" function, following this
** model but changing "fputs" to put the strings at a proper place
** (a console window or a log file, for instance).
*/
#ifndef MAXPRINT
#define MAXPRINT 40 /* arbitrary limit */
#endif
static void luaB_print (void) {
lua_Object args[MAXPRINT];
lua_Object obj;
int n = 0;
int i;
while ((obj = lua_getparam(n+1)) != LUA_NOOBJECT) {
luaL_arg_check(n < MAXPRINT, n+1, "too many arguments");
args[n++] = obj;
}
for (i=0; i<n; i++) {
lua_pushobject(args[i]);
if (lua_call("tostring"))
lua_error("error in `tostring' called by `print'");
obj = lua_getresult(1);
if (!lua_isstring(obj))
lua_error("`tostring' must return a string to `print'");
if (i>0) fputs("\t", stdout);
fputs(lua_getstring(obj), stdout);
}
fputs("\n", stdout);
}
static void luaB_tonumber (void) {
int base = luaL_opt_int(2, 10);
if (base == 10) { /* standard conversion */
lua_Object o = lua_getparam(1);
if (lua_isnumber(o)) lua_pushnumber(lua_getnumber(o));
else lua_pushnil(); /* not a number */
}
else {
char *s = luaL_check_string(1);
long n;
luaL_arg_check(0 <= base && base <= 36, 2, "base out of range");
n = strtol(s, &s, base);
while (isspace((unsigned char)*s)) s++; /* skip trailing spaces */
if (*s) lua_pushnil(); /* invalid format: return nil */
else lua_pushnumber(n);
}
}
static void luaB_error (void) {
lua_error(lua_getstring(lua_getparam(1)));
}
static void luaB_setglobal (void) {
char *n = luaL_check_string(1);
lua_Object value = luaL_nonnullarg(2);
lua_pushobject(value);
lua_setglobal(n);
lua_pushobject(value); /* return given value */
}
static void luaB_rawsetglobal (void) {
char *n = luaL_check_string(1);
lua_Object value = luaL_nonnullarg(2);
lua_pushobject(value);
lua_rawsetglobal(n);
lua_pushobject(value); /* return given value */
}
static void luaB_getglobal (void) {
lua_pushobject(lua_getglobal(luaL_check_string(1)));
}
static void luaB_rawgetglobal (void) {
lua_pushobject(lua_rawgetglobal(luaL_check_string(1)));
}
static void luaB_luatag (void) {
lua_pushnumber(lua_tag(lua_getparam(1)));
}
static void luaB_settag (void) {
lua_Object o = luaL_tablearg(1);
lua_pushobject(o);
lua_settag(luaL_check_int(2));
lua_pushobject(o); /* return first argument */
}
static void luaB_newtag (void) {
lua_pushnumber(lua_newtag());
}
static void luaB_copytagmethods (void) {
lua_pushnumber(lua_copytagmethods(luaL_check_int(1),
luaL_check_int(2)));
}
static void luaB_rawgettable (void) {
lua_pushobject(luaL_nonnullarg(1));
lua_pushobject(luaL_nonnullarg(2));
lua_pushobject(lua_rawgettable());
}
static void luaB_rawsettable (void) {
lua_pushobject(luaL_nonnullarg(1));
lua_pushobject(luaL_nonnullarg(2));
lua_pushobject(luaL_nonnullarg(3));
lua_rawsettable();
}
static void luaB_settagmethod (void) {
lua_Object nf = luaL_nonnullarg(3);
lua_pushobject(nf);
lua_pushobject(lua_settagmethod(luaL_check_int(1), luaL_check_string(2)));
}
static void luaB_gettagmethod (void) {
lua_pushobject(lua_gettagmethod(luaL_check_int(1), luaL_check_string(2)));
}
static void luaB_seterrormethod (void) {
lua_Object nf = luaL_functionarg(1);
lua_pushobject(nf);
lua_pushobject(lua_seterrormethod());
}
static void luaB_collectgarbage (void) {
lua_pushnumber(lua_collectgarbage(luaL_opt_int(1, 0)));
}
/* }====================================================== */
/*
** {======================================================
** Functions that could use only the official API but
** do not, for efficiency.
** =======================================================
*/
static void luaB_dostring (void) {
long l;
char *s = luaL_check_lstr(1, &l);
if (*s == ID_CHUNK)
lua_error("`dostring' cannot run pre-compiled code");
if (lua_dobuffer(s, l, luaL_opt_string(2, s)) == 0)
if (luaA_passresults() == 0)
lua_pushuserdata(NULL); /* at least one result to signal no errors */
}
static void luaB_dofile (void) {
char *fname = luaL_opt_string(1, NULL);
if (lua_dofile(fname) == 0)
if (luaA_passresults() == 0)
lua_pushuserdata(NULL); /* at least one result to signal no errors */
}
static void luaB_call (void) {
lua_Object f = luaL_nonnullarg(1);
Hash *arg = gethash(2);
char *options = luaL_opt_string(3, "");
lua_Object err = lua_getparam(4);
int narg = (int)getnarg(arg);
int i, status;
if (err != LUA_NOOBJECT) { /* set new error method */
lua_pushobject(err);
err = lua_seterrormethod();
}
/* push arg[1...n] */
luaD_checkstack(narg);
for (i=0; i<narg; i++)
*(L->stack.top++) = *luaH_getint(arg, i+1);
status = lua_callfunction(f);
if (err != LUA_NOOBJECT) { /* restore old error method */
lua_pushobject(err);
lua_seterrormethod();
}
if (status != 0) { /* error in call? */
if (strchr(options, 'x')) {
lua_pushnil();
return; /* return nil to signal the error */
}
else
lua_error(NULL);
}
else { /* no errors */
if (strchr(options, 'p'))
luaA_packresults();
else
luaA_passresults();
}
}
static void luaB_nextvar (void) {
TObject *o = luaA_Address(luaL_nonnullarg(1));
TaggedString *g;
if (ttype(o) == LUA_T_NIL)
g = NULL;
else {
luaL_arg_check(ttype(o) == LUA_T_STRING, 1, "variable name expected");
g = tsvalue(o);
}
if (!luaA_nextvar(g))
lua_pushnil();
}
static void luaB_next (void) {
Hash *a = gethash(1);
TObject *k = luaA_Address(luaL_nonnullarg(2));
int i = (ttype(k) == LUA_T_NIL) ? 0 : luaH_pos(a, k)+1;
if (luaA_next(a, i) == 0)
lua_pushnil();
}
static void luaB_tostring (void) {
lua_Object obj = lua_getparam(1);
TObject *o = luaA_Address(obj);
char buff[64];
switch (ttype(o)) {
case LUA_T_NUMBER:
lua_pushstring(lua_getstring(obj));
return;
case LUA_T_STRING:
lua_pushobject(obj);
return;
case LUA_T_ARRAY:
sprintf(buff, "table: %p", (void *)o->value.a);
break;
case LUA_T_CLOSURE:
sprintf(buff, "function: %p", (void *)o->value.cl);
break;
case LUA_T_PROTO:
sprintf(buff, "function: %p", (void *)o->value.tf);
break;
case LUA_T_CPROTO:
sprintf(buff, "function: %p", (void *)o->value.f);
break;
case LUA_T_USERDATA:
sprintf(buff, "userdata: %p", o->value.ts->u.d.v);
break;
case LUA_T_NIL:
lua_pushstring("nil");
return;
default:
LUA_INTERNALERROR("invalid type");
}
lua_pushstring(buff);
}
static void luaB_type (void) {
lua_Object o = luaL_nonnullarg(1);
lua_pushstring(luaO_typename(luaA_Address(o)));
lua_pushnumber(lua_tag(o));
}
/* }====================================================== */
/*
** {======================================================
** "Extra" functions
** These functions can be written in Lua, so you can
** delete them if you need a tiny Lua implementation.
** If you delete them, remove their entries in array
** "builtin_funcs".
** =======================================================
*/
static void luaB_assert (void) {
lua_Object p = lua_getparam(1);
if (p == LUA_NOOBJECT || lua_isnil(p))
luaL_verror("assertion failed! %.100s", luaL_opt_string(2, ""));
}
static void luaB_foreachi (void) {
Hash *t = gethash(1);
int i;
int n = (int)getnarg(t);
TObject f;
/* 'f' cannot be a pointer to TObject, because it is on the stack, and the
stack may be reallocated by the call. Moreover, some C compilers do not
initialize structs, so we must do the assignment after the declaration */
f = *luaA_Address(luaL_functionarg(2));
luaD_checkstack(3); /* for f, ref, and val */
for (i=1; i<=n; i++) {
*(L->stack.top++) = f;
ttype(L->stack.top) = LUA_T_NUMBER; nvalue(L->stack.top++) = i;
*(L->stack.top++) = *luaH_getint(t, i);
luaD_calln(2, 1);
if (ttype(L->stack.top-1) != LUA_T_NIL)
return;
L->stack.top--;
}
}
static void luaB_foreach (void) {
Hash *a = gethash(1);
int i;
TObject f; /* see comment in 'foreachi' */
f = *luaA_Address(luaL_functionarg(2));
luaD_checkstack(3); /* for f, ref, and val */
for (i=0; i<a->nhash; i++) {
Node *nd = &(a->node[i]);
if (ttype(val(nd)) != LUA_T_NIL) {
*(L->stack.top++) = f;
*(L->stack.top++) = *ref(nd);
*(L->stack.top++) = *val(nd);
luaD_calln(2, 1);
if (ttype(L->stack.top-1) != LUA_T_NIL)
return;
L->stack.top--; /* remove result */
}
}
}
static void luaB_foreachvar (void) {
GCnode *g;
TObject f; /* see comment in 'foreachi' */
f = *luaA_Address(luaL_functionarg(1));
luaD_checkstack(4); /* for extra var name, f, var name, and globalval */
for (g = L->rootglobal.next; g; g = g->next) {
TaggedString *s = (TaggedString *)g;
if (s->u.s.globalval.ttype != LUA_T_NIL) {
pushtagstring(s); /* keep (extra) s on stack to avoid GC */
*(L->stack.top++) = f;
pushtagstring(s);
*(L->stack.top++) = s->u.s.globalval;
luaD_calln(2, 1);
if (ttype(L->stack.top-1) != LUA_T_NIL) {
L->stack.top--;
*(L->stack.top-1) = *L->stack.top; /* remove extra s */
return;
}
L->stack.top-=2; /* remove result and extra s */
}
}
}
static void luaB_getn (void) {
lua_pushnumber(getnarg(gethash(1)));
}
static void luaB_tinsert (void) {
Hash *a = gethash(1);
lua_Object v = lua_getparam(3);
int n = (int)getnarg(a);
int pos;
if (v != LUA_NOOBJECT)
pos = luaL_check_int(2);
else { /* called with only 2 arguments */
v = luaL_nonnullarg(2);
pos = n+1;
}
luaV_setn(a, n+1); /* a.n = n+1 */
for ( ;n>=pos; n--)
luaH_move(a, n, n+1); /* a[n+1] = a[n] */
luaH_setint(a, pos, luaA_Address(v)); /* a[pos] = v */
}
static void luaB_tremove (void) {
Hash *a = gethash(1);
int n = (int)getnarg(a);
int pos = luaL_opt_int(2, n);
if (n <= 0) return; /* table is "empty" */
luaA_pushobject(luaH_getint(a, pos)); /* result = a[pos] */
for ( ;pos<n; pos++)
luaH_move(a, pos+1, pos); /* a[pos] = a[pos+1] */
luaV_setn(a, n-1); /* a.n = n-1 */
luaH_setint(a, n, &luaO_nilobject); /* a[n] = nil */
}
/* {
** Quicksort
*/
static void swap (Hash *a, int i, int j) {
TObject temp;
temp = *luaH_getint(a, i);
luaH_move(a, j, i);
luaH_setint(a, j, &temp);
}
static int sort_comp (lua_Object f, TObject *a, TObject *b) {
/* notice: the caller (auxsort) must check stack space */
if (f != LUA_NOOBJECT) {
*(L->stack.top) = *luaA_Address(f);
*(L->stack.top+1) = *a;
*(L->stack.top+2) = *b;
L->stack.top += 3;
luaD_calln(2, 1);
}
else { /* a < b? */
*(L->stack.top) = *a;
*(L->stack.top+1) = *b;
L->stack.top += 2;
luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
}
return ttype(--(L->stack.top)) != LUA_T_NIL;
}
static void auxsort (Hash *a, int l, int u, lua_Object f) {
while (l < u) { /* for tail recursion */
TObject *P;
int i, j;
/* sort elements a[l], a[(l+u)/2] and a[u] */
if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[l]>a[u]? */
swap(a, l, u);
if (u-l == 1) break; /* only 2 elements */
i = (l+u)/2;
P = luaH_getint(a, i);
if (sort_comp(f, P, luaH_getint(a, l))) /* a[l]>a[i]? */
swap(a, l, i);
else if (sort_comp(f, luaH_getint(a, u), P)) /* a[i]>a[u]? */
swap(a, i, u);
if (u-l == 2) break; /* only 3 elements */
P = L->stack.top++;
*P = *luaH_getint(a, i); /* save pivot on stack (for GC) */
swap(a, i, u-1); /* put median element as pivot (a[u-1]) */
/* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */
i = l; j = u-1;
for (;;) {
/* invariant: a[l..i] <= P <= a[j..u] */
while (sort_comp(f, luaH_getint(a, ++i), P)) /* stop when a[i] >= P */
if (i>u) lua_error("invalid order function for sorting");
while (sort_comp(f, P, luaH_getint(a, --j))) /* stop when a[j] <= P */
if (j<l) lua_error("invalid order function for sorting");
if (j<i) break;
swap(a, i, j);
}
swap(a, u-1, i); /* swap pivot (a[u-1]) with a[i] */
L->stack.top--; /* remove pivot from stack */
/* a[l..i-1] <= a[i] == P <= a[i+1..u] */
/* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */
if (i-l < u-i) {
j=l; i=i-1; l=i+2;
}
else {
j=i+1; i=u; u=j-2;
}
auxsort(a, j, i, f); /* call recursively the smaller one */
} /* repeat the routine for the larger one */
}
static void luaB_sort (void) {
lua_Object t = lua_getparam(1);
Hash *a = gethash(1);
int n = (int)getnarg(a);
lua_Object func = lua_getparam(2);
luaL_arg_check(func == LUA_NOOBJECT || lua_isfunction(func), 2,
"function expected");
luaD_checkstack(4); /* for Pivot, f, a, b (sort_comp) */
auxsort(a, 1, n, func);
lua_pushobject(t);
}
/* }}===================================================== */
/*
** ====================================================== */
#ifdef DEBUG
/*
** {======================================================
** some DEBUG functions
** =======================================================
*/
static void mem_query (void) {
lua_pushnumber(totalmem);
lua_pushnumber(numblocks);
}
static void query_strings (void) {
lua_pushnumber(L->string_root[luaL_check_int(1)].nuse);
}
static void countlist (void) {
char *s = luaL_check_string(1);
GCnode *l = (s[0]=='t') ? L->roottable.next : (s[0]=='c') ? L->rootcl.next :
(s[0]=='p') ? L->rootproto.next : L->rootglobal.next;
int i=0;
while (l) {
i++;
l = l->next;
}
lua_pushnumber(i);
}
static void testC (void) {
#define getnum(s) ((*s++) - '0')
#define getname(s) (nome[0] = *s++, nome)
static int locks[10];
lua_Object reg[10];
char nome[2];
char *s = luaL_check_string(1);
nome[1] = 0;
for (;;) {
switch (*s++) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
lua_pushnumber(*(s-1) - '0');
break;
case 'c': reg[getnum(s)] = lua_createtable(); break;
case 'C': { lua_CFunction f = lua_getcfunction(lua_getglobal(getname(s)));
lua_pushcclosure(f, getnum(s));
break;
}
case 'P': reg[getnum(s)] = lua_pop(); break;
case 'g': { int n=getnum(s); reg[n]=lua_getglobal(getname(s)); break; }
case 'G': { int n = getnum(s);
reg[n] = lua_rawgetglobal(getname(s));
break;
}
case 'l': locks[getnum(s)] = lua_ref(1); break;
case 'L': locks[getnum(s)] = lua_ref(0); break;
case 'r': { int n=getnum(s); reg[n]=lua_getref(locks[getnum(s)]); break; }
case 'u': lua_unref(locks[getnum(s)]); break;
case 'p': { int n = getnum(s); reg[n] = lua_getparam(getnum(s)); break; }
case '=': lua_setglobal(getname(s)); break;
case 's': lua_pushstring(getname(s)); break;
case 'o': lua_pushobject(reg[getnum(s)]); break;
case 'f': lua_call(getname(s)); break;
case 'i': reg[getnum(s)] = lua_gettable(); break;
case 'I': reg[getnum(s)] = lua_rawgettable(); break;
case 't': lua_settable(); break;
case 'T': lua_rawsettable(); break;
case 'N' : lua_pushstring(lua_nextvar(lua_getstring(reg[getnum(s)])));
break;
case 'n' : { int n=getnum(s);
n=lua_next(reg[n], (int)lua_getnumber(reg[getnum(s)]));
lua_pushnumber(n); break;
}
default: luaL_verror("unknown command in `testC': %c", *(s-1));
}
if (*s == 0) return;
if (*s++ != ' ') lua_error("missing ` ' between commands in `testC'");
}
}
/* }====================================================== */
#endif
static struct luaL_reg builtin_funcs[] = {
#ifdef LUA_COMPAT2_5
{"setfallback", luaT_setfallback},
#endif
#ifdef DEBUG
{"testC", testC},
{"totalmem", mem_query},
{"count", countlist},
{"querystr", query_strings},
#endif
{"_ALERT", luaB_alert},
{"_ERRORMESSAGE", error_message},
{"call", luaB_call},
{"collectgarbage", luaB_collectgarbage},
{"copytagmethods", luaB_copytagmethods},
{"dofile", luaB_dofile},
{"dostring", luaB_dostring},
{"error", luaB_error},
{"getglobal", luaB_getglobal},
{"gettagmethod", luaB_gettagmethod},
{"newtag", luaB_newtag},
{"next", luaB_next},
{"nextvar", luaB_nextvar},
{"print", luaB_print},
{"rawgetglobal", luaB_rawgetglobal},
{"rawgettable", luaB_rawgettable},
{"rawsetglobal", luaB_rawsetglobal},
{"rawsettable", luaB_rawsettable},
{"seterrormethod", luaB_seterrormethod},
{"setglobal", luaB_setglobal},
{"settag", luaB_settag},
{"settagmethod", luaB_settagmethod},
{"tag", luaB_luatag},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
/* "Extra" functions */
{"assert", luaB_assert},
{"foreach", luaB_foreach},
{"foreachi", luaB_foreachi},
{"foreachvar", luaB_foreachvar},
{"getn", luaB_getn},
{"sort", luaB_sort},
{"tinsert", luaB_tinsert},
{"tremove", luaB_tremove}
};
#define INTFUNCSIZE (sizeof(builtin_funcs)/sizeof(builtin_funcs[0]))
void luaB_predefine (void) {
/* pre-register mem error messages, to avoid loop when error arises */
luaS_newfixedstring(tableEM);
luaS_newfixedstring(memEM);
luaL_openlib(builtin_funcs, (sizeof(builtin_funcs)/sizeof(builtin_funcs[0])));
lua_pushstring(LUA_VERSION);
lua_setglobal("_VERSION");
}

14
lbuiltin.h Normal file
View File

@@ -0,0 +1,14 @@
/*
** $Id: $
** Built-in functions
** See Copyright Notice in lua.h
*/
#ifndef lbuiltin_h
#define lbuiltin_h
void luaB_predefine (void);
#endif

217
ldblib.c Normal file
View File

@@ -0,0 +1,217 @@
/*
** $Id: ldblib.c,v 1.4 1999/02/04 17:47:59 roberto Exp roberto $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#include <string.h>
#include "lauxlib.h"
#include "lua.h"
#include "luadebug.h"
#include "lualib.h"
static void settabss (lua_Object t, char *i, char *v) {
lua_pushobject(t);
lua_pushstring(i);
lua_pushstring(v);
lua_settable();
}
static void settabsi (lua_Object t, char *i, int v) {
lua_pushobject(t);
lua_pushstring(i);
lua_pushnumber(v);
lua_settable();
}
static lua_Object getfuncinfo (lua_Object func) {
lua_Object result = lua_createtable();
char *str;
int line;
lua_funcinfo(func, &str, &line);
if (line == -1) /* C function? */
settabss(result, "kind", "C");
else if (line == 0) { /* "main"? */
settabss(result, "kind", "chunk");
settabss(result, "source", str);
}
else { /* Lua function */
settabss(result, "kind", "Lua");
settabsi(result, "def_line", line);
settabss(result, "source", str);
}
if (line != 0) { /* is it not a "main"? */
char *kind = lua_getobjname(func, &str);
if (*kind) {
settabss(result, "name", str);
settabss(result, "where", kind);
}
}
return result;
}
static void getstack (void) {
lua_Object func = lua_stackedfunction(luaL_check_int(1));
if (func == LUA_NOOBJECT) /* level out of range? */
return;
else {
lua_Object result = getfuncinfo(func);
int currline = lua_currentline(func);
if (currline > 0)
settabsi(result, "current", currline);
lua_pushobject(result);
lua_pushstring("func");
lua_pushobject(func);
lua_settable(); /* result.func = func */
lua_pushobject(result);
}
}
static void funcinfo (void) {
lua_pushobject(getfuncinfo(luaL_functionarg(1)));
}
static int findlocal (lua_Object func, int arg) {
lua_Object v = lua_getparam(arg);
if (lua_isnumber(v))
return (int)lua_getnumber(v);
else {
char *name = luaL_check_string(arg);
int i = 0;
int result = -1;
char *vname;
while (lua_getlocal(func, ++i, &vname) != LUA_NOOBJECT) {
if (strcmp(name, vname) == 0)
result = i; /* keep looping to get the last var with this name */
}
if (result == -1)
luaL_verror("no local variable `%.50s' at given level", name);
return result;
}
}
static void getlocal (void) {
lua_Object func = lua_stackedfunction(luaL_check_int(1));
lua_Object val;
char *name;
if (func == LUA_NOOBJECT) /* level out of range? */
return; /* return nil */
else if (lua_getparam(2) != LUA_NOOBJECT) { /* 2nd argument? */
if ((val = lua_getlocal(func, findlocal(func, 2), &name)) != LUA_NOOBJECT) {
lua_pushobject(val);
lua_pushstring(name);
}
/* else return nil */
}
else { /* collect all locals in a table */
lua_Object result = lua_createtable();
int i;
for (i=1; ;i++) {
if ((val = lua_getlocal(func, i, &name)) == LUA_NOOBJECT)
break;
lua_pushobject(result);
lua_pushstring(name);
lua_pushobject(val);
lua_settable(); /* result[name] = value */
}
lua_pushobject(result);
}
}
static void setlocal (void) {
lua_Object func = lua_stackedfunction(luaL_check_int(1));
int numvar;
luaL_arg_check(func != LUA_NOOBJECT, 1, "level out of range");
numvar = findlocal(func, 2);
lua_pushobject(luaL_nonnullarg(3));
if (!lua_setlocal(func, numvar))
lua_error("no such local variable");
}
static int linehook = -1; /* Lua reference to line hook function */
static int callhook = -1; /* Lua reference to call hook function */
static void dohook (int ref) {
lua_LHFunction oldlinehook = lua_setlinehook(NULL);
lua_CHFunction oldcallhook = lua_setcallhook(NULL);
lua_callfunction(lua_getref(ref));
lua_setlinehook(oldlinehook);
lua_setcallhook(oldcallhook);
}
static void linef (int line) {
lua_pushnumber(line);
dohook(linehook);
}
static void callf (lua_Function func, char *file, int line) {
if (func != LUA_NOOBJECT) {
lua_pushobject(func);
lua_pushstring(file);
lua_pushnumber(line);
}
dohook(callhook);
}
static void setcallhook (void) {
lua_Object f = lua_getparam(1);
lua_unref(callhook);
if (f == LUA_NOOBJECT) {
callhook = -1;
lua_setcallhook(NULL);
}
else {
lua_pushobject(f);
callhook = lua_ref(1);
lua_setcallhook(callf);
}
}
static void setlinehook (void) {
lua_Object f = lua_getparam(1);
lua_unref(linehook);
if (f == LUA_NOOBJECT) {
linehook = -1;
lua_setlinehook(NULL);
}
else {
lua_pushobject(f);
linehook = lua_ref(1);
lua_setlinehook(linef);
}
}
static struct luaL_reg dblib[] = {
{"funcinfo", funcinfo},
{"getlocal", getlocal},
{"getstack", getstack},
{"setcallhook", setcallhook},
{"setlinehook", setlinehook},
{"setlocal", setlocal}
};
void lua_dblibopen (void) {
luaL_openlib(dblib, (sizeof(dblib)/sizeof(dblib[0])));
}

385
ldo.c Normal file
View File

@@ -0,0 +1,385 @@
/*
** $Id: ldo.c,v 1.44 1999/06/17 17:04:03 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "ltm.h"
#include "lua.h"
#include "luadebug.h"
#include "lundump.h"
#include "lvm.h"
#include "lzio.h"
#ifndef STACK_LIMIT
#define STACK_LIMIT 6000 /* arbitrary limit */
#endif
#define STACK_UNIT 128
#ifdef DEBUG
#undef STACK_UNIT
#define STACK_UNIT 2
#endif
void luaD_init (void) {
L->stack.stack = luaM_newvector(STACK_UNIT, TObject);
L->stack.top = L->stack.stack;
L->stack.last = L->stack.stack+(STACK_UNIT-1);
}
void luaD_checkstack (int n) {
struct Stack *S = &L->stack;
if (S->last-S->top <= n) {
StkId top = S->top-S->stack;
int stacksize = (S->last-S->stack)+STACK_UNIT+n;
luaM_reallocvector(S->stack, stacksize, TObject);
S->last = S->stack+(stacksize-1);
S->top = S->stack + top;
if (stacksize >= STACK_LIMIT) { /* stack overflow? */
if (lua_stackedfunction(100) == LUA_NOOBJECT) /* 100 funcs on stack? */
lua_error("Lua2C - C2Lua overflow"); /* doesn't look like a rec. loop */
else
lua_error("stack size overflow");
}
}
}
/*
** Adjust stack. Set top to the given value, pushing NILs if needed.
*/
void luaD_adjusttop (StkId newtop) {
int diff = newtop-(L->stack.top-L->stack.stack);
if (diff <= 0)
L->stack.top += diff;
else {
luaD_checkstack(diff);
while (diff--)
ttype(L->stack.top++) = LUA_T_NIL;
}
}
/*
** Open a hole below "nelems" from the L->stack.top.
*/
void luaD_openstack (int nelems) {
luaO_memup(L->stack.top-nelems+1, L->stack.top-nelems,
nelems*sizeof(TObject));
incr_top;
}
void luaD_lineHook (int line) {
struct C_Lua_Stack oldCLS = L->Cstack;
StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack;
L->Cstack.num = 0;
(*L->linehook)(line);
L->stack.top = L->stack.stack+old_top;
L->Cstack = oldCLS;
}
void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn) {
struct C_Lua_Stack oldCLS = L->Cstack;
StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack;
L->Cstack.num = 0;
if (isreturn)
(*L->callhook)(LUA_NOOBJECT, "(return)", 0);
else {
TObject *f = L->stack.stack+base-1;
if (tf)
(*L->callhook)(Ref(f), tf->source->str, tf->lineDefined);
else
(*L->callhook)(Ref(f), "(C)", -1);
}
L->stack.top = L->stack.stack+old_top;
L->Cstack = oldCLS;
}
/*
** Call a C function.
** Cstack.num is the number of arguments; Cstack.lua2C points to the
** first argument. Returns an index to the first result from C.
*/
static StkId callC (lua_CFunction f, StkId base) {
struct C_Lua_Stack *cls = &L->Cstack;
struct C_Lua_Stack oldCLS = *cls;
StkId firstResult;
int numarg = (L->stack.top-L->stack.stack) - base;
cls->num = numarg;
cls->lua2C = base;
cls->base = base+numarg; /* == top-stack */
if (L->callhook)
luaD_callHook(base, NULL, 0);
(*f)(); /* do the actual call */
if (L->callhook) /* func may have changed callhook */
luaD_callHook(base, NULL, 1);
firstResult = cls->base;
*cls = oldCLS;
return firstResult;
}
static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base) {
TObject *pbase;
int nup = cl->nelems; /* number of upvalues */
luaD_checkstack(nup);
pbase = L->stack.stack+base; /* care: previous call may change this */
/* open space for upvalues as extra arguments */
luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject));
/* copy upvalues into stack */
memcpy(pbase, cl->consts+1, nup*sizeof(TObject));
L->stack.top += nup;
return callC(f, base);
}
void luaD_callTM (TObject *f, int nParams, int nResults) {
luaD_openstack(nParams);
*(L->stack.top-nParams-1) = *f;
luaD_calln(nParams, nResults);
}
/*
** Call a function (C or Lua). The parameters must be on the stack,
** between [top-nArgs,top). The function to be called is right below the
** arguments.
** When returns, the results are on the stack, between [top-nArgs-1,top).
** The number of results is nResults, unless nResults=MULT_RET.
*/
void luaD_calln (int nArgs, int nResults) {
struct Stack *S = &L->stack; /* to optimize */
StkId base = (S->top-S->stack)-nArgs;
TObject *func = S->stack+base-1;
StkId firstResult;
int i;
switch (ttype(func)) {
case LUA_T_CPROTO:
ttype(func) = LUA_T_CMARK;
firstResult = callC(fvalue(func), base);
break;
case LUA_T_PROTO:
ttype(func) = LUA_T_PMARK;
firstResult = luaV_execute(NULL, tfvalue(func), base);
break;
case LUA_T_CLOSURE: {
Closure *c = clvalue(func);
TObject *proto = &(c->consts[0]);
ttype(func) = LUA_T_CLMARK;
firstResult = (ttype(proto) == LUA_T_CPROTO) ?
callCclosure(c, fvalue(proto), base) :
luaV_execute(c, tfvalue(proto), base);
break;
}
default: { /* func is not a function */
/* Check the tag method for invalid functions */
TObject *im = luaT_getimbyObj(func, IM_FUNCTION);
if (ttype(im) == LUA_T_NIL)
lua_error("call expression not a function");
luaD_callTM(im, (S->top-S->stack)-(base-1), nResults);
return;
}
}
/* adjust the number of results */
if (nResults == MULT_RET)
nResults = (S->top-S->stack)-firstResult;
else
luaD_adjusttop(firstResult+nResults);
/* move results to base-1 (to erase parameters and function) */
base--;
for (i=0; i<nResults; i++)
*(S->stack+base+i) = *(S->stack+firstResult+i);
S->top -= firstResult-base;
}
/*
** Traverse all objects on L->stack.stack
*/
void luaD_travstack (int (*fn)(TObject *))
{
StkId i;
for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--)
fn(L->stack.stack+i);
}
static void message (char *s) {
TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval);
if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO ||
ttype(em) == LUA_T_CLOSURE) {
*L->stack.top = *em;
incr_top;
lua_pushstring(s);
luaD_calln(1, 0);
}
}
/*
** Reports an error, and jumps up to the available recover label
*/
void lua_error (char *s) {
if (s) message(s);
if (L->errorJmp)
longjmp(L->errorJmp->b, 1);
else {
message("exit(1). Unable to recover.\n");
exit(1);
}
}
/*
** Execute a protected call. Assumes that function is at L->Cstack.base and
** parameters are on top of it. Leave nResults on the stack.
*/
int luaD_protectedrun (void) {
volatile struct C_Lua_Stack oldCLS = L->Cstack;
struct lua_longjmp myErrorJmp;
volatile int status;
struct lua_longjmp *volatile oldErr = L->errorJmp;
L->errorJmp = &myErrorJmp;
if (setjmp(myErrorJmp.b) == 0) {
StkId base = L->Cstack.base;
luaD_calln((L->stack.top-L->stack.stack)-base-1, MULT_RET);
L->Cstack.lua2C = base; /* position of the new results */
L->Cstack.num = (L->stack.top-L->stack.stack) - base;
L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */
status = 0;
}
else { /* an error occurred: restore L->Cstack and L->stack.top */
L->Cstack = oldCLS;
L->stack.top = L->stack.stack+L->Cstack.base;
status = 1;
}
L->errorJmp = oldErr;
return status;
}
/*
** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load
*/
static int protectedparser (ZIO *z, int bin) {
volatile struct C_Lua_Stack oldCLS = L->Cstack;
struct lua_longjmp myErrorJmp;
volatile int status;
TProtoFunc *volatile tf;
struct lua_longjmp *volatile oldErr = L->errorJmp;
L->errorJmp = &myErrorJmp;
if (setjmp(myErrorJmp.b) == 0) {
tf = bin ? luaU_undump1(z) : luaY_parser(z);
status = 0;
}
else { /* an error occurred: restore L->Cstack and L->stack.top */
L->Cstack = oldCLS;
L->stack.top = L->stack.stack+L->Cstack.base;
tf = NULL;
status = 1;
}
L->errorJmp = oldErr;
if (status) return 1; /* error code */
if (tf == NULL) return 2; /* 'natural' end */
luaD_adjusttop(L->Cstack.base+1); /* one slot for the pseudo-function */
L->stack.stack[L->Cstack.base].ttype = LUA_T_PROTO;
L->stack.stack[L->Cstack.base].value.tf = tf;
luaV_closure(0);
return 0;
}
static int do_main (ZIO *z, int bin) {
int status;
int debug = L->debug; /* save debug status */
do {
long old_blocks = (luaC_checkGC(), L->nblocks);
status = protectedparser(z, bin);
if (status == 1) return 1; /* error */
else if (status == 2) return 0; /* 'natural' end */
else {
unsigned long newelems2 = 2*(L->nblocks-old_blocks);
L->GCthreshold += newelems2;
status = luaD_protectedrun();
L->GCthreshold -= newelems2;
}
} while (bin && status == 0);
L->debug = debug; /* restore debug status */
return status;
}
void luaD_gcIM (TObject *o)
{
TObject *im = luaT_getimbyObj(o, IM_GC);
if (ttype(im) != LUA_T_NIL) {
*L->stack.top = *o;
incr_top;
luaD_callTM(im, 1, 0);
}
}
#define MAXFILENAME 260 /* maximum part of a file name kept */
int lua_dofile (char *filename) {
ZIO z;
int status;
int c;
int bin;
char source[MAXFILENAME];
FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
if (f == NULL)
return 2;
c = fgetc(f);
ungetc(c, f);
bin = (c == ID_CHUNK);
if (bin)
f = freopen(filename, "rb", f); /* set binary mode */
luaL_filesource(source, filename, sizeof(source));
luaZ_Fopen(&z, f, source);
status = do_main(&z, bin);
if (f != stdin)
fclose(f);
return status;
}
int lua_dostring (char *str) {
return lua_dobuffer(str, strlen(str), str);
}
int lua_dobuffer (char *buff, int size, char *name) {
ZIO z;
if (!name) name = "?";
luaZ_mopen(&z, buff, size, name);
return do_main(&z, buff[0]==ID_CHUNK);
}

46
ldo.h Normal file
View File

@@ -0,0 +1,46 @@
/*
** $Id: ldo.h,v 1.5 1998/07/12 16:14:34 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#ifndef ldo_h
#define ldo_h
#include "lobject.h"
#include "lstate.h"
#define MULT_RET 255
/*
** macro to increment stack top.
** There must be always an empty slot at the L->stack.top
*/
#define incr_top { if (L->stack.top >= L->stack.last) luaD_checkstack(1); \
L->stack.top++; }
/* macros to convert from lua_Object to (TObject *) and back */
#define Address(lo) ((lo)+L->stack.stack-1)
#define Ref(st) ((st)-L->stack.stack+1)
void luaD_init (void);
void luaD_adjusttop (StkId newtop);
void luaD_openstack (int nelems);
void luaD_lineHook (int line);
void luaD_callHook (StkId base, TProtoFunc *tf, int isreturn);
void luaD_calln (int nArgs, int nResults);
void luaD_callTM (TObject *f, int nParams, int nResults);
int luaD_protectedrun (void);
void luaD_gcIM (TObject *o);
void luaD_travstack (int (*fn)(TObject *));
void luaD_checkstack (int n);
#endif

357
lex.c
View File

@@ -1,357 +0,0 @@
char *rcs_lex = "$Id: lex.c,v 2.20 1995/10/25 13:05:51 roberto Exp roberto $";
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mem.h"
#include "tree.h"
#include "table.h"
#include "opcode.h"
#include "inout.h"
#include "parser.h"
#include "ugly.h"
#define MINBUFF 260
#define lua_strcmp(a,b) (a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b)))
#define next() { current = input(); }
#define save(x) { *yytextLast++ = (x); }
#define save_and_next() { save(current); next(); }
static int current;
static char *yytext = NULL;
static int textsize = 0;
static char *yytextLast;
static Input input;
void lua_setinput (Input fn)
{
current = ' ';
input = fn;
if (yytext == NULL)
{
textsize = MINBUFF;
yytext = newvector(textsize, char);
}
}
char *lua_lasttext (void)
{
*yytextLast = 0;
return yytext;
}
/* The reserved words must be listed in lexicographic order */
static struct
{
char *name;
int token;
} reserved [] = {
{"and", AND},
{"do", DO},
{"else", ELSE},
{"elseif", ELSEIF},
{"end", END},
{"function", FUNCTION},
{"if", IF},
{"local", LOCAL},
{"nil", NIL},
{"not", NOT},
{"or", OR},
{"repeat", REPEAT},
{"return", RETURN},
{"then", THEN},
{"until", UNTIL},
{"while", WHILE} };
#define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0]))
static int findReserved (char *name)
{
int l = 0;
int h = RESERVEDSIZE - 1;
while (l <= h)
{
int m = (l+h)/2;
int comp = lua_strcmp(name, reserved[m].name);
if (comp < 0)
h = m-1;
else if (comp == 0)
return reserved[m].token;
else
l = m+1;
}
return 0;
}
static void growtext (void)
{
int size = yytextLast - yytext;
textsize *= 2;
yytext = growvector(yytext, textsize, char);
yytextLast = yytext + size;
}
static int read_long_string (void)
{
int cont = 0;
int spaceleft = textsize - (yytextLast - yytext);
while (1)
{
if (spaceleft <= 2) /* may read more than 1 char in one cicle */
{
growtext();
spaceleft = textsize - (yytextLast - yytext);
}
switch (current)
{
case EOF:
case 0:
return WRONGTOKEN;
case '[':
save_and_next(); spaceleft--;
if (current == '[')
{
cont++;
save_and_next(); spaceleft--;
}
continue;
case ']':
save_and_next(); spaceleft--;
if (current == ']')
{
if (cont == 0) return STRING;
cont--;
save_and_next(); spaceleft--;
}
continue;
case '\n':
lua_linenumber++; /* goes through */
default:
save_and_next(); spaceleft--;
}
}
}
int yylex (void)
{
float a;
static int linelasttoken = 0;
if (lua_debug)
luaI_codedebugline(linelasttoken);
linelasttoken = lua_linenumber;
while (1)
{
yytextLast = yytext;
#if 0
fprintf(stderr,"'%c' %d\n",current,current);
#endif
switch (current)
{
case EOF:
case 0:
return 0;
case '\n': linelasttoken = ++lua_linenumber;
case ' ':
case '\r': /* CR: to avoid problems with DOS/Windows */
case '\t':
next();
continue;
case '$':
next();
while (isalnum(current) || current == '_')
save_and_next();
*yytextLast = 0;
if (lua_strcmp(yytext, "debug") == 0)
{
yylval.vInt = 1;
return DEBUG;
}
else if (lua_strcmp(yytext, "nodebug") == 0)
{
yylval.vInt = 0;
return DEBUG;
}
return WRONGTOKEN;
case '-':
save_and_next();
if (current != '-') return '-'; /* else goes through */
case '#':
do { next(); } while (current != '\n' && current != 0);
continue;
case '[':
save_and_next();
if (current != '[') return '[';
else
{
save_and_next(); /* pass the second '[' */
if (read_long_string() == WRONGTOKEN)
return WRONGTOKEN;
save_and_next(); /* pass the second ']' */
*(yytextLast-2) = 0; /* erases ']]' */
yylval.vWord = luaI_findconstantbyname(yytext+2);
return STRING;
}
case '=':
save_and_next();
if (current != '=') return '=';
else { save_and_next(); return EQ; }
case '<':
save_and_next();
if (current != '=') return '<';
else { save_and_next(); return LE; }
case '>':
save_and_next();
if (current != '=') return '>';
else { save_and_next(); return GE; }
case '~':
save_and_next();
if (current != '=') return '~';
else { save_and_next(); return NE; }
case '"':
case '\'':
{
int del = current;
int spaceleft = textsize - (yytextLast - yytext);
next(); /* skip the delimiter */
while (current != del)
{
if (spaceleft <= 2) /* may read more than 1 char in one cicle */
{
growtext();
spaceleft = textsize - (yytextLast - yytext);
}
spaceleft--;
switch (current)
{
case EOF:
case 0:
case '\n':
return WRONGTOKEN;
case '\\':
next(); /* do not save the '\' */
switch (current)
{
case 'n': save('\n'); next(); break;
case 't': save('\t'); next(); break;
case 'r': save('\r'); next(); break;
default : save(current); next(); break;
}
break;
default:
save_and_next();
}
}
next(); /* skip the delimiter */
*yytextLast = 0;
yylval.vWord = luaI_findconstantbyname(yytext);
return STRING;
}
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
case '_':
{
Word res;
do { save_and_next(); } while (isalnum(current) || current == '_');
*yytextLast = 0;
res = findReserved(yytext);
if (res) return res;
yylval.pNode = lua_constcreate(yytext);
return NAME;
}
case '.':
save_and_next();
if (current == '.')
{
save_and_next();
return CONC;
}
else if (!isdigit(current)) return '.';
/* current is a digit: goes through to number */
a=0.0;
goto fraction;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
a=0.0;
do { a=10*a+current-'0'; save_and_next(); } while (isdigit(current));
if (current == '.') save_and_next();
fraction:
{ float da=0.1;
while (isdigit(current))
{a+=(current-'0')*da; da/=10.0; save_and_next()};
if (current == 'e' || current == 'E')
{
int e=0;
int neg;
float ea;
save_and_next();
neg=(current=='-');
if (current == '+' || current == '-') save_and_next();
if (!isdigit(current)) return WRONGTOKEN;
do { e=10*e+current-'0'; save_and_next(); } while (isdigit(current));
for (ea=neg?0.1:10.0; e>0; e>>=1)
{
if (e & 1) a*=ea;
ea*=ea;
}
}
yylval.vFloat = a;
return NUMBER;
}
case U_and: case U_do: case U_else: case U_elseif: case U_end:
case U_function: case U_if: case U_local: case U_nil: case U_not:
case U_or: case U_repeat: case U_return: case U_then:
case U_until: case U_while:
{
int old = current;
next();
return reserved[old-U_and].token;
}
case U_eq: next(); return EQ;
case U_le: next(); return LE;
case U_ge: next(); return GE;
case U_ne: next(); return NE;
case U_sc: next(); return CONC;
default: /* also end of file */
{
save_and_next();
return yytext[0];
}
}
}
}

98
lfunc.c Normal file
View File

@@ -0,0 +1,98 @@
/*
** $Id: lfunc.c,v 1.9 1998/06/19 16:14:09 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#include "lfunc.h"
#include "lmem.h"
#include "lstate.h"
#define gcsizeproto(p) 5 /* approximate "weight" for a prototype */
#define gcsizeclosure(c) 1 /* approximate "weight" for a closure */
Closure *luaF_newclosure (int nelems)
{
Closure *c = (Closure *)luaM_malloc(sizeof(Closure)+nelems*sizeof(TObject));
luaO_insertlist(&(L->rootcl), (GCnode *)c);
L->nblocks += gcsizeclosure(c);
c->nelems = nelems;
return c;
}
TProtoFunc *luaF_newproto (void)
{
TProtoFunc *f = luaM_new(TProtoFunc);
f->code = NULL;
f->lineDefined = 0;
f->source = NULL;
f->consts = NULL;
f->nconsts = 0;
f->locvars = NULL;
luaO_insertlist(&(L->rootproto), (GCnode *)f);
L->nblocks += gcsizeproto(f);
return f;
}
static void freefunc (TProtoFunc *f)
{
luaM_free(f->code);
luaM_free(f->locvars);
luaM_free(f->consts);
luaM_free(f);
}
void luaF_freeproto (TProtoFunc *l)
{
while (l) {
TProtoFunc *next = (TProtoFunc *)l->head.next;
L->nblocks -= gcsizeproto(l);
freefunc(l);
l = next;
}
}
void luaF_freeclosure (Closure *l)
{
while (l) {
Closure *next = (Closure *)l->head.next;
L->nblocks -= gcsizeclosure(l);
luaM_free(l);
l = next;
}
}
/*
** Look for n-th local variable at line "line" in function "func".
** Returns NULL if not found.
*/
char *luaF_getlocalname (TProtoFunc *func, int local_number, int line)
{
int count = 0;
char *varname = NULL;
LocVar *lv = func->locvars;
if (lv == NULL)
return NULL;
for (; lv->line != -1 && lv->line < line; lv++) {
if (lv->varname) { /* register */
if (++count == local_number)
varname = lv->varname->str;
}
else /* unregister */
if (--count < local_number)
varname = NULL;
}
return varname;
}

23
lfunc.h Normal file
View File

@@ -0,0 +1,23 @@
/*
** $Id: lfunc.h,v 1.4 1997/11/19 17:29:23 roberto Exp roberto $
** Lua Function structures
** See Copyright Notice in lua.h
*/
#ifndef lfunc_h
#define lfunc_h
#include "lobject.h"
TProtoFunc *luaF_newproto (void);
Closure *luaF_newclosure (int nelems);
void luaF_freeproto (TProtoFunc *l);
void luaF_freeclosure (Closure *l);
char *luaF_getlocalname (TProtoFunc *func, int local_number, int line);
#endif

275
lgc.c Normal file
View File

@@ -0,0 +1,275 @@
/*
** $Id: lgc.c,v 1.22 1999/02/26 15:48:55 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lua.h"
static int markobject (TObject *o);
/*
** =======================================================
** REF mechanism
** =======================================================
*/
int luaC_ref (TObject *o, int lock) {
int ref;
if (ttype(o) == LUA_T_NIL)
ref = -1; /* special ref for nil */
else {
for (ref=0; ref<L->refSize; ref++)
if (L->refArray[ref].status == FREE)
break;
if (ref == L->refSize) { /* no more empty spaces? */
luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT);
L->refSize++;
}
L->refArray[ref].o = *o;
L->refArray[ref].status = lock ? LOCK : HOLD;
}
return ref;
}
void lua_unref (int ref)
{
if (ref >= 0 && ref < L->refSize)
L->refArray[ref].status = FREE;
}
TObject* luaC_getref (int ref)
{
if (ref == -1)
return &luaO_nilobject;
if (ref >= 0 && ref < L->refSize &&
(L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD))
return &L->refArray[ref].o;
else
return NULL;
}
static void travlock (void)
{
int i;
for (i=0; i<L->refSize; i++)
if (L->refArray[i].status == LOCK)
markobject(&L->refArray[i].o);
}
static int ismarked (TObject *o)
{
/* valid only for locked objects */
switch (o->ttype) {
case LUA_T_STRING: case LUA_T_USERDATA:
return o->value.ts->head.marked;
case LUA_T_ARRAY:
return o->value.a->head.marked;
case LUA_T_CLOSURE:
return o->value.cl->head.marked;
case LUA_T_PROTO:
return o->value.tf->head.marked;
#ifdef DEBUG
case LUA_T_LINE: case LUA_T_CLMARK:
case LUA_T_CMARK: case LUA_T_PMARK:
LUA_INTERNALERROR("invalid type");
#endif
default: /* nil, number or cproto */
return 1;
}
}
static void invalidaterefs (void)
{
int i;
for (i=0; i<L->refSize; i++)
if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o))
L->refArray[i].status = COLLECTED;
}
void luaC_hashcallIM (Hash *l)
{
TObject t;
ttype(&t) = LUA_T_ARRAY;
for (; l; l=(Hash *)l->head.next) {
avalue(&t) = l;
luaD_gcIM(&t);
}
}
void luaC_strcallIM (TaggedString *l)
{
TObject o;
ttype(&o) = LUA_T_USERDATA;
for (; l; l=(TaggedString *)l->head.next)
if (l->constindex == -1) { /* is userdata? */
tsvalue(&o) = l;
luaD_gcIM(&o);
}
}
static GCnode *listcollect (GCnode *l)
{
GCnode *frees = NULL;
while (l) {
GCnode *next = l->next;
l->marked = 0;
while (next && !next->marked) {
l->next = next->next;
next->next = frees;
frees = next;
next = l->next;
}
l = next;
}
return frees;
}
static void strmark (TaggedString *s)
{
if (!s->head.marked)
s->head.marked = 1;
}
static void protomark (TProtoFunc *f) {
if (!f->head.marked) {
int i;
f->head.marked = 1;
strmark(f->source);
for (i=0; i<f->nconsts; i++)
markobject(&f->consts[i]);
}
}
static void closuremark (Closure *f)
{
if (!f->head.marked) {
int i;
f->head.marked = 1;
for (i=f->nelems; i>=0; i--)
markobject(&f->consts[i]);
}
}
static void hashmark (Hash *h)
{
if (!h->head.marked) {
int i;
h->head.marked = 1;
for (i=0; i<nhash(h); i++) {
Node *n = node(h,i);
if (ttype(ref(n)) != LUA_T_NIL) {
markobject(&n->ref);
markobject(&n->val);
}
}
}
}
static void globalmark (void)
{
TaggedString *g;
for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next){
LUA_ASSERT(g->constindex >= 0, "userdata in global list");
if (g->u.s.globalval.ttype != LUA_T_NIL) {
markobject(&g->u.s.globalval);
strmark(g); /* cannot collect non nil global variables */
}
}
}
static int markobject (TObject *o)
{
switch (ttype(o)) {
case LUA_T_USERDATA: case LUA_T_STRING:
strmark(tsvalue(o));
break;
case LUA_T_ARRAY:
hashmark(avalue(o));
break;
case LUA_T_CLOSURE: case LUA_T_CLMARK:
closuremark(o->value.cl);
break;
case LUA_T_PROTO: case LUA_T_PMARK:
protomark(o->value.tf);
break;
default: break; /* numbers, cprotos, etc */
}
return 0;
}
static void markall (void)
{
luaD_travstack(markobject); /* mark stack objects */
globalmark(); /* mark global variable values and names */
travlock(); /* mark locked objects */
luaT_travtagmethods(markobject); /* mark fallbacks */
}
long lua_collectgarbage (long limit)
{
unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */
Hash *freetable;
TaggedString *freestr;
TProtoFunc *freefunc;
Closure *freeclos;
markall();
invalidaterefs();
freestr = luaS_collector();
freetable = (Hash *)listcollect(&(L->roottable));
freefunc = (TProtoFunc *)listcollect(&(L->rootproto));
freeclos = (Closure *)listcollect(&(L->rootcl));
L->GCthreshold *= 4; /* to avoid GC during GC */
luaC_hashcallIM(freetable); /* GC tag methods for tables */
luaC_strcallIM(freestr); /* GC tag methods for userdata */
luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */
luaH_free(freetable);
luaS_free(freestr);
luaF_freeproto(freefunc);
luaF_freeclosure(freeclos);
recovered = recovered-L->nblocks;
L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
return recovered;
}
void luaC_checkGC (void)
{
if (L->nblocks >= L->GCthreshold)
lua_collectgarbage(0);
}

21
lgc.h Normal file
View File

@@ -0,0 +1,21 @@
/*
** $Id: lgc.h,v 1.3 1997/11/19 17:29:23 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#ifndef lgc_h
#define lgc_h
#include "lobject.h"
void luaC_checkGC (void);
TObject* luaC_getref (int ref);
int luaC_ref (TObject *o, int lock);
void luaC_hashcallIM (Hash *l);
void luaC_strcallIM (TaggedString *l);
#endif

17
linit.c Normal file
View File

@@ -0,0 +1,17 @@
/*
** $Id: linit.c,v 1.1 1999/01/08 16:47:44 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/
#include "lua.h"
#include "lualib.h"
void lua_userinit (void) {
lua_iolibopen();
lua_strlibopen();
lua_mathlibopen();
lua_dblibopen();
}

583
liolib.c Normal file
View File

@@ -0,0 +1,583 @@
/*
** $Id: liolib.c,v 1.40 1999/05/14 12:24:04 roberto Exp roberto $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lauxlib.h"
#include "lua.h"
#include "luadebug.h"
#include "lualib.h"
#ifndef OLD_ANSI
#include <locale.h>
#else
/* no support for locale and for strerror: fake them */
#define setlocale(a,b) 0
#define LC_ALL 0
#define LC_COLLATE 0
#define LC_CTYPE 0
#define LC_MONETARY 0
#define LC_NUMERIC 0
#define LC_TIME 0
#define strerror(e) "(no error message provided by operating system)"
#endif
#define IOTAG 1
#define FIRSTARG 2 /* 1st is upvalue */
#define CLOSEDTAG(tag) ((tag)-1) /* assume that CLOSEDTAG = iotag-1 */
#define FINPUT "_INPUT"
#define FOUTPUT "_OUTPUT"
#ifdef POPEN
FILE *popen();
int pclose();
#define CLOSEFILE(f) {if (pclose(f) == -1) fclose(f);}
#else
/* no support for popen */
#define popen(x,y) NULL /* that is, popen always fails */
#define CLOSEFILE(f) {fclose(f);}
#endif
static void pushresult (int i) {
if (i)
lua_pushuserdata(NULL);
else {
lua_pushnil();
lua_pushstring(strerror(errno));
lua_pushnumber(errno);
}
}
/*
** {======================================================
** FILE Operations
** =======================================================
*/
static int gettag (void) {
return (int)lua_getnumber(lua_getparam(IOTAG));
}
static int ishandle (lua_Object f) {
if (lua_isuserdata(f)) {
int tag = gettag();
if (lua_tag(f) == CLOSEDTAG(tag))
lua_error("cannot access a closed file");
return lua_tag(f) == tag;
}
else return 0;
}
static FILE *getfilebyname (char *name) {
lua_Object f = lua_getglobal(name);
if (!ishandle(f))
luaL_verror("global variable `%.50s' is not a file handle", name);
return lua_getuserdata(f);
}
static FILE *getfile (int arg) {
lua_Object f = lua_getparam(arg);
return (ishandle(f)) ? lua_getuserdata(f) : NULL;
}
static FILE *getnonullfile (int arg) {
FILE *f = getfile(arg);
luaL_arg_check(f, arg, "invalid file handle");
return f;
}
static FILE *getfileparam (char *name, int *arg) {
FILE *f = getfile(*arg);
if (f) {
(*arg)++;
return f;
}
else
return getfilebyname(name);
}
static void closefile (FILE *f) {
if (f != stdin && f != stdout) {
int tag = gettag();
CLOSEFILE(f);
lua_pushusertag(f, tag);
lua_settag(CLOSEDTAG(tag));
}
}
static void io_close (void) {
closefile(getnonullfile(FIRSTARG));
}
static void gc_close (void) {
FILE *f = getnonullfile(FIRSTARG);
if (f != stdin && f != stdout && f != stderr) {
CLOSEFILE(f);
}
}
static void io_open (void) {
FILE *f = fopen(luaL_check_string(FIRSTARG), luaL_check_string(FIRSTARG+1));
if (f) lua_pushusertag(f, gettag());
else pushresult(0);
}
static void setfile (FILE *f, char *name, int tag) {
lua_pushusertag(f, tag);
lua_setglobal(name);
}
static void setreturn (FILE *f, char *name) {
if (f == NULL)
pushresult(0);
else {
int tag = gettag();
setfile(f, name, tag);
lua_pushusertag(f, tag);
}
}
static void io_readfrom (void) {
FILE *current;
lua_Object f = lua_getparam(FIRSTARG);
if (f == LUA_NOOBJECT) {
closefile(getfilebyname(FINPUT));
current = stdin;
}
else if (lua_tag(f) == gettag()) /* deprecated option */
current = lua_getuserdata(f);
else {
char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
}
setreturn(current, FINPUT);
}
static void io_writeto (void) {
FILE *current;
lua_Object f = lua_getparam(FIRSTARG);
if (f == LUA_NOOBJECT) {
closefile(getfilebyname(FOUTPUT));
current = stdout;
}
else if (lua_tag(f) == gettag()) /* deprecated option */
current = lua_getuserdata(f);
else {
char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1,"w") : fopen(s, "w");
}
setreturn(current, FOUTPUT);
}
static void io_appendto (void) {
FILE *current = fopen(luaL_check_string(FIRSTARG), "a");
setreturn(current, FOUTPUT);
}
/*
** {======================================================
** READ
** =======================================================
*/
/*
** We cannot lookahead without need, because this can lock stdin.
** This flag signals when we need to read a next char.
*/
#define NEED_OTHER (EOF-1) /* just some flag different from EOF */
static int read_pattern (FILE *f, char *p) {
int inskip = 0; /* {skip} level */
int c = NEED_OTHER;
while (*p != '\0') {
switch (*p) {
case '{':
inskip++;
p++;
continue;
case '}':
if (!inskip) lua_error("unbalanced braces in read pattern");
inskip--;
p++;
continue;
default: {
char *ep = luaI_classend(p); /* get what is next */
int m; /* match result */
if (c == NEED_OTHER) c = getc(f);
m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
if (m) {
if (!inskip) luaL_addchar(c);
c = NEED_OTHER;
}
switch (*ep) {
case '+': /* repetition (1 or more) */
if (!m) goto break_while; /* pattern fails? */
/* else go through */
case '*': /* repetition (0 or more) */
while (m) { /* reads the same item until it fails */
c = getc(f);
m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
if (m && !inskip) luaL_addchar(c);
}
/* go through to continue reading the pattern */
case '?': /* optional */
p = ep+1; /* continues reading the pattern */
continue;
default:
if (!m) goto break_while; /* pattern fails? */
p = ep; /* else continues reading the pattern */
}
}
}
} break_while:
if (c != NEED_OTHER) ungetc(c, f);
return (*p == '\0');
}
static int read_number (FILE *f) {
double d;
if (fscanf(f, "%lf", &d) == 1) {
lua_pushnumber(d);
return 1;
}
else return 0; /* read fails */
}
#define HUNK_LINE 1024
#define HUNK_FILE BUFSIZ
static int read_line (FILE *f) {
/* equivalent to: return read_pattern(f, "[^\n]*{\n}"); */
int n;
char *b;
do {
b = luaL_openspace(HUNK_LINE);
if (!fgets(b, HUNK_LINE, f)) return 0; /* read fails */
n = strlen(b);
luaL_addsize(n);
} while (b[n-1] != '\n');
luaL_addsize(-1); /* remove '\n' */
return 1;
}
static void read_file (FILE *f) {
/* equivalent to: return read_pattern(f, ".*"); */
int n;
do {
char *b = luaL_openspace(HUNK_FILE);
n = fread(b, sizeof(char), HUNK_FILE, f);
luaL_addsize(n);
} while (n==HUNK_FILE);
}
static void io_read (void) {
static char *options[] = {"*n", "*l", "*a", ".*", "*w", NULL};
int arg = FIRSTARG;
FILE *f = getfileparam(FINPUT, &arg);
char *p = luaL_opt_string(arg++, "*l");
do { /* repeat for each part */
long l;
int success;
luaL_resetbuffer();
switch (luaL_findstring(p, options)) {
case 0: /* number */
if (!read_number(f)) return; /* read fails */
continue; /* number is already pushed; avoid the "pushstring" */
case 1: /* line */
success = read_line(f);
break;
case 2: case 3: /* file */
read_file(f);
success = 1; /* always success */
break;
case 4: /* word */
success = read_pattern(f, "{%s*}%S+");
break;
default:
success = read_pattern(f, p);
}
l = luaL_getsize();
if (!success && l==0) return; /* read fails */
lua_pushlstring(luaL_buffer(), l);
} while ((p = luaL_opt_string(arg++, NULL)) != NULL);
}
/* }====================================================== */
static void io_write (void) {
int arg = FIRSTARG;
FILE *f = getfileparam(FOUTPUT, &arg);
int status = 1;
char *s;
long l;
while ((s = luaL_opt_lstr(arg++, NULL, &l)) != NULL)
status = status && ((long)fwrite(s, 1, l, f) == l);
pushresult(status);
}
static void io_seek (void) {
static int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static char *modenames[] = {"set", "cur", "end", NULL};
FILE *f = getnonullfile(FIRSTARG);
int op = luaL_findstring(luaL_opt_string(FIRSTARG+1, "cur"), modenames);
long offset = luaL_opt_long(FIRSTARG+2, 0);
luaL_arg_check(op != -1, FIRSTARG+1, "invalid mode");
op = fseek(f, offset, mode[op]);
if (op)
pushresult(0); /* error */
else
lua_pushnumber(ftell(f));
}
static void io_flush (void) {
FILE *f = getfile(FIRSTARG);
luaL_arg_check(f || lua_getparam(FIRSTARG) == LUA_NOOBJECT, FIRSTARG,
"invalid file handle");
pushresult(fflush(f) == 0);
}
/* }====================================================== */
/*
** {======================================================
** Other O.S. Operations
** =======================================================
*/
static void io_execute (void) {
lua_pushnumber(system(luaL_check_string(1)));
}
static void io_remove (void) {
pushresult(remove(luaL_check_string(1)) == 0);
}
static void io_rename (void) {
pushresult(rename(luaL_check_string(1),
luaL_check_string(2)) == 0);
}
static void io_tmpname (void) {
lua_pushstring(tmpnam(NULL));
}
static void io_getenv (void) {
lua_pushstring(getenv(luaL_check_string(1))); /* if NULL push nil */
}
static void io_clock (void) {
lua_pushnumber(((double)clock())/CLOCKS_PER_SEC);
}
static void io_date (void) {
char b[256];
char *s = luaL_opt_string(1, "%c");
struct tm *tm;
time_t t;
time(&t); tm = localtime(&t);
if (strftime(b,sizeof(b),s,tm))
lua_pushstring(b);
else
lua_error("invalid `date' format");
}
static void setloc (void) {
static int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC,
LC_TIME};
static char *catnames[] = {"all", "collate", "ctype", "monetary",
"numeric", "time", NULL};
int op = luaL_findstring(luaL_opt_string(2, "all"), catnames);
luaL_arg_check(op != -1, 2, "invalid option");
lua_pushstring(setlocale(cat[op], luaL_check_string(1)));
}
static void io_exit (void) {
lua_Object o = lua_getparam(1);
exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1);
}
/* }====================================================== */
static void io_debug (void) {
for (;;) {
char buffer[250];
fprintf(stderr, "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return;
lua_dostring(buffer);
}
}
#define MESSAGESIZE 150
#define MAXMESSAGE (MESSAGESIZE*10)
#define MAXSRC 60
static void errorfb (void) {
char buff[MAXMESSAGE];
int level = 1; /* skip level 0 (it's this function) */
lua_Object func;
sprintf(buff, "lua error: %.200s\n", lua_getstring(lua_getparam(1)));
while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) {
char *name;
int currentline;
char *chunkname;
char buffchunk[MAXSRC];
int linedefined;
lua_funcinfo(func, &chunkname, &linedefined);
luaL_chunkid(buffchunk, chunkname, sizeof(buffchunk));
if (level == 2) strcat(buff, "Active Stack:\n");
strcat(buff, " ");
if (strlen(buff) > MAXMESSAGE-MESSAGESIZE) {
strcat(buff, "...\n");
break; /* buffer is full */
}
switch (*lua_getobjname(func, &name)) {
case 'g':
sprintf(buff+strlen(buff), "function `%.50s'", name);
break;
case 't':
sprintf(buff+strlen(buff), "`%.50s' tag method", name);
break;
default: {
if (linedefined == 0)
sprintf(buff+strlen(buff), "main of %.70s", buffchunk);
else if (linedefined < 0)
sprintf(buff+strlen(buff), "%.70s", buffchunk);
else
sprintf(buff+strlen(buff), "function <%d:%.70s>",
linedefined, buffchunk);
chunkname = NULL;
}
}
if ((currentline = lua_currentline(func)) > 0)
sprintf(buff+strlen(buff), " at line %d", currentline);
if (chunkname)
sprintf(buff+strlen(buff), " [%.70s]", buffchunk);
strcat(buff, "\n");
}
func = lua_rawgetglobal("_ALERT");
if (lua_isfunction(func)) { /* avoid error loop if _ALERT is not defined */
lua_pushstring(buff);
lua_callfunction(func);
}
}
static struct luaL_reg iolib[] = {
{"_ERRORMESSAGE", errorfb},
{"clock", io_clock},
{"date", io_date},
{"debug", io_debug},
{"execute", io_execute},
{"exit", io_exit},
{"getenv", io_getenv},
{"remove", io_remove},
{"rename", io_rename},
{"setlocale", setloc},
{"tmpname", io_tmpname}
};
static struct luaL_reg iolibtag[] = {
{"appendto", io_appendto},
{"closefile", io_close},
{"flush", io_flush},
{"openfile", io_open},
{"read", io_read},
{"readfrom", io_readfrom},
{"seek", io_seek},
{"write", io_write},
{"writeto", io_writeto}
};
static void openwithtags (void) {
int i;
int iotag = lua_newtag();
lua_newtag(); /* alloc CLOSEDTAG: assume that CLOSEDTAG = iotag-1 */
for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) {
/* put iotag as upvalue for these functions */
lua_pushnumber(iotag);
lua_pushcclosure(iolibtag[i].func, 1);
lua_setglobal(iolibtag[i].name);
}
/* predefined file handles */
setfile(stdin, FINPUT, iotag);
setfile(stdout, FOUTPUT, iotag);
setfile(stdin, "_STDIN", iotag);
setfile(stdout, "_STDOUT", iotag);
setfile(stderr, "_STDERR", iotag);
/* close file when collected */
lua_pushnumber(iotag);
lua_pushcclosure(gc_close, 1);
lua_settagmethod(iotag, "gc");
}
void lua_iolibopen (void) {
/* register lib functions */
luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
openwithtags();
}

437
llex.c Normal file
View File

@@ -0,0 +1,437 @@
/*
** $Id: llex.c,v 1.35 1999/05/14 12:24:04 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <string.h>
#include "lauxlib.h"
#include "llex.h"
#include "lmem.h"
#include "lobject.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "luadebug.h"
#include "lzio.h"
#define next(LS) (LS->current = zgetc(LS->lex_z))
#define save(c) luaL_addchar(c)
#define save_and_next(LS) (save(LS->current), next(LS))
char *reserved [] = {"and", "do", "else", "elseif", "end", "function",
"if", "local", "nil", "not", "or", "repeat", "return", "then",
"until", "while"};
void luaX_init (void) {
int i;
for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) {
TaggedString *ts = luaS_new(reserved[i]);
ts->head.marked = FIRST_RESERVED+i; /* reserved word (always > 255) */
}
}
#define MAXSRC 80
void luaX_syntaxerror (LexState *ls, char *s, char *token) {
char buff[MAXSRC];
luaL_chunkid(buff, zname(ls->lex_z), sizeof(buff));
if (token[0] == '\0')
token = "<eof>";
luaL_verror("%.100s;\n last token read: `%.50s' at line %d in %.80s",
s, token, ls->linenumber, buff);
}
void luaX_error (LexState *ls, char *s) {
save('\0');
luaX_syntaxerror(ls, s, luaL_buffer());
}
void luaX_token2str (int token, char *s) {
if (token < 255) {
s[0] = (char)token;
s[1] = '\0';
}
else
strcpy(s, reserved[token-FIRST_RESERVED]);
}
static void luaX_invalidchar (LexState *ls, int c) {
char buff[8];
sprintf(buff, "0x%02X", c);
luaX_syntaxerror(ls, "invalid control char", buff);
}
static void firstline (LexState *LS)
{
int c = zgetc(LS->lex_z);
if (c == '#')
while ((c=zgetc(LS->lex_z)) != '\n' && c != EOZ) /* skip first line */;
zungetc(LS->lex_z);
}
void luaX_setinput (LexState *LS, ZIO *z)
{
LS->current = '\n';
LS->linenumber = 0;
LS->iflevel = 0;
LS->ifstate[0].skip = 0;
LS->ifstate[0].elsepart = 1; /* to avoid a free $else */
LS->lex_z = z;
LS->fs = NULL;
firstline(LS);
luaL_resetbuffer();
}
/*
** =======================================================
** PRAGMAS
** =======================================================
*/
#ifndef PRAGMASIZE
#define PRAGMASIZE 80 /* arbitrary limit */
#endif
static void skipspace (LexState *LS) {
while (LS->current == ' ' || LS->current == '\t' || LS->current == '\r')
next(LS);
}
static int checkcond (LexState *LS, char *buff) {
static char *opts[] = {"nil", "1", NULL};
int i = luaL_findstring(buff, opts);
if (i >= 0) return i;
else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
return luaS_globaldefined(buff);
else {
luaX_syntaxerror(LS, "invalid $if condition", buff);
return 0; /* to avoid warnings */
}
}
static void readname (LexState *LS, char *buff) {
int i = 0;
skipspace(LS);
while (isalnum(LS->current) || LS->current == '_') {
if (i >= PRAGMASIZE) {
buff[PRAGMASIZE] = 0;
luaX_syntaxerror(LS, "pragma too long", buff);
}
buff[i++] = (char)LS->current;
next(LS);
}
buff[i] = 0;
}
static void inclinenumber (LexState *LS);
static void ifskip (LexState *LS) {
while (LS->ifstate[LS->iflevel].skip) {
if (LS->current == '\n')
inclinenumber(LS);
else if (LS->current == EOZ)
luaX_error(LS, "input ends inside a $if");
else next(LS);
}
}
static void inclinenumber (LexState *LS) {
static char *pragmas [] =
{"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
next(LS); /* skip '\n' */
++LS->linenumber;
if (LS->current == '$') { /* is a pragma? */
char buff[PRAGMASIZE+1];
int ifnot = 0;
int skip = LS->ifstate[LS->iflevel].skip;
next(LS); /* skip $ */
readname(LS, buff);
switch (luaL_findstring(buff, pragmas)) {
case 0: /* debug */
if (!skip) L->debug = 1;
break;
case 1: /* nodebug */
if (!skip) L->debug = 0;
break;
case 2: /* endinput */
if (!skip) {
LS->current = EOZ;
LS->iflevel = 0; /* to allow $endinput inside a $if */
}
break;
case 3: /* end */
if (LS->iflevel-- == 0)
luaX_syntaxerror(LS, "unmatched $end", "$end");
break;
case 4: /* ifnot */
ifnot = 1;
/* go through */
case 5: /* if */
if (LS->iflevel == MAX_IFS-1)
luaX_syntaxerror(LS, "too many nested $ifs", "$if");
readname(LS, buff);
LS->iflevel++;
LS->ifstate[LS->iflevel].elsepart = 0;
LS->ifstate[LS->iflevel].condition = checkcond(LS, buff) ? !ifnot : ifnot;
LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition;
break;
case 6: /* else */
if (LS->ifstate[LS->iflevel].elsepart)
luaX_syntaxerror(LS, "unmatched $else", "$else");
LS->ifstate[LS->iflevel].elsepart = 1;
LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip ||
LS->ifstate[LS->iflevel].condition;
break;
default:
luaX_syntaxerror(LS, "unknown pragma", buff);
}
skipspace(LS);
if (LS->current == '\n') /* pragma must end with a '\n' ... */
inclinenumber(LS);
else if (LS->current != EOZ) /* or eof */
luaX_syntaxerror(LS, "invalid pragma format", buff);
ifskip(LS);
}
}
/*
** =======================================================
** LEXICAL ANALIZER
** =======================================================
*/
static int read_long_string (LexState *LS) {
int cont = 0;
for (;;) {
switch (LS->current) {
case EOZ:
luaX_error(LS, "unfinished long string");
return EOS; /* to avoid warnings */
case '[':
save_and_next(LS);
if (LS->current == '[') {
cont++;
save_and_next(LS);
}
continue;
case ']':
save_and_next(LS);
if (LS->current == ']') {
if (cont == 0) goto endloop;
cont--;
save_and_next(LS);
}
continue;
case '\n':
save('\n');
inclinenumber(LS);
continue;
default:
save_and_next(LS);
}
} endloop:
save_and_next(LS); /* skip the second ']' */
LS->seminfo.ts = luaS_newlstr(L->Mbuffer+(L->Mbuffbase+2),
L->Mbuffnext-L->Mbuffbase-4);
return STRING;
}
int luaX_lex (LexState *LS) {
luaL_resetbuffer();
for (;;) {
switch (LS->current) {
case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
next(LS);
continue;
case '\n':
inclinenumber(LS);
continue;
case '-':
save_and_next(LS);
if (LS->current != '-') return '-';
do { next(LS); } while (LS->current != '\n' && LS->current != EOZ);
luaL_resetbuffer();
continue;
case '[':
save_and_next(LS);
if (LS->current != '[') return '[';
else {
save_and_next(LS); /* pass the second '[' */
return read_long_string(LS);
}
case '=':
save_and_next(LS);
if (LS->current != '=') return '=';
else { save_and_next(LS); return EQ; }
case '<':
save_and_next(LS);
if (LS->current != '=') return '<';
else { save_and_next(LS); return LE; }
case '>':
save_and_next(LS);
if (LS->current != '=') return '>';
else { save_and_next(LS); return GE; }
case '~':
save_and_next(LS);
if (LS->current != '=') return '~';
else { save_and_next(LS); return NE; }
case '"':
case '\'': {
int del = LS->current;
save_and_next(LS);
while (LS->current != del) {
switch (LS->current) {
case EOZ:
case '\n':
luaX_error(LS, "unfinished string");
return EOS; /* to avoid warnings */
case '\\':
next(LS); /* do not save the '\' */
switch (LS->current) {
case 'a': save('\a'); next(LS); break;
case 'b': save('\b'); next(LS); break;
case 'f': save('\f'); next(LS); break;
case 'n': save('\n'); next(LS); break;
case 'r': save('\r'); next(LS); break;
case 't': save('\t'); next(LS); break;
case 'v': save('\v'); next(LS); break;
case '\n': save('\n'); inclinenumber(LS); break;
default : {
if (isdigit(LS->current)) {
int c = 0;
int i = 0;
do {
c = 10*c + (LS->current-'0');
next(LS);
} while (++i<3 && isdigit(LS->current));
if (c != (unsigned char)c)
luaX_error(LS, "escape sequence too large");
save(c);
}
else { /* handles \, ", ', and ? */
save(LS->current);
next(LS);
}
break;
}
}
break;
default:
save_and_next(LS);
}
}
save_and_next(LS); /* skip delimiter */
LS->seminfo.ts = luaS_newlstr(L->Mbuffer+(L->Mbuffbase+1),
L->Mbuffnext-L->Mbuffbase-2);
return STRING;
}
case '.':
save_and_next(LS);
if (LS->current == '.')
{
save_and_next(LS);
if (LS->current == '.')
{
save_and_next(LS);
return DOTS; /* ... */
}
else return CONC; /* .. */
}
else if (!isdigit(LS->current)) return '.';
goto fraction; /* LS->current is a digit: goes through to number */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
do {
save_and_next(LS);
} while (isdigit(LS->current));
if (LS->current == '.') {
save_and_next(LS);
if (LS->current == '.') {
save('.');
luaX_error(LS,
"ambiguous syntax (decimal point x string concatenation)");
}
}
fraction:
while (isdigit(LS->current))
save_and_next(LS);
if (toupper(LS->current) == 'E') {
save_and_next(LS); /* read 'E' */
save_and_next(LS); /* read '+', '-' or first digit */
while (isdigit(LS->current))
save_and_next(LS);
}
save('\0');
LS->seminfo.r = luaO_str2d(L->Mbuffer+L->Mbuffbase);
if (LS->seminfo.r < 0)
luaX_error(LS, "invalid numeric format");
return NUMBER;
case EOZ:
if (LS->iflevel > 0)
luaX_error(LS, "input ends inside a $if");
return EOS;
default:
if (LS->current != '_' && !isalpha(LS->current)) {
int c = LS->current;
if (iscntrl(c))
luaX_invalidchar(LS, c);
save_and_next(LS);
return c;
}
else { /* identifier or reserved word */
TaggedString *ts;
do {
save_and_next(LS);
} while (isalnum(LS->current) || LS->current == '_');
save('\0');
ts = luaS_new(L->Mbuffer+L->Mbuffbase);
if (ts->head.marked >= FIRST_RESERVED)
return ts->head.marked; /* reserved word */
LS->seminfo.ts = ts;
return NAME;
}
}
}
}

64
llex.h Normal file
View File

@@ -0,0 +1,64 @@
/*
** $Id: llex.h,v 1.11 1999/02/25 19:13:56 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#ifndef llex_h
#define llex_h
#include "lobject.h"
#include "lzio.h"
#define FIRST_RESERVED 260
/* maximum length of a reserved word (+1 for terminal 0) */
#define TOKEN_LEN 15
enum RESERVED {
/* terminal symbols denoted by reserved words */
AND = FIRST_RESERVED,
DO, ELSE, ELSEIF, END, FUNCTION, IF, LOCAL, NIL, NOT, OR,
REPEAT, RETURN, THEN, UNTIL, WHILE,
/* other terminal symbols */
NAME, CONC, DOTS, EQ, GE, LE, NE, NUMBER, STRING, EOS};
#ifndef MAX_IFS
#define MAX_IFS 5 /* arbitrary limit */
#endif
/* "ifstate" keeps the state of each nested $if the lexical is dealing with. */
struct ifState {
int elsepart; /* true if it's in the $else part */
int condition; /* true if $if condition is true */
int skip; /* true if part must be skipped */
};
typedef struct LexState {
int current; /* look ahead character */
int token; /* look ahead token */
struct FuncState *fs; /* 'FuncState' is private for the parser */
union {
real r;
TaggedString *ts;
} seminfo; /* semantics information */
struct zio *lex_z; /* input stream */
int linenumber; /* input line counter */
int iflevel; /* level of nested $if's (for lexical analysis) */
struct ifState ifstate[MAX_IFS];
} LexState;
void luaX_init (void);
void luaX_setinput (LexState *LS, ZIO *z);
int luaX_lex (LexState *LS);
void luaX_syntaxerror (LexState *ls, char *s, char *token);
void luaX_error (LexState *ls, char *s);
void luaX_token2str (int token, char *s);
#endif

203
lmathlib.c Normal file
View File

@@ -0,0 +1,203 @@
/*
** $Id: lmathlib.c,v 1.16 1999/02/19 17:33:35 roberto Exp roberto $
** Lua standard mathematical library
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#include <math.h>
#include "lauxlib.h"
#include "lua.h"
#include "lualib.h"
#undef PI
#define PI (3.14159265358979323846)
#define RADIANS_PER_DEGREE (PI/180.0)
/*
** If you want Lua to operate in radians (instead of degrees),
** define RADIANS
*/
#ifdef RADIANS
#define FROMRAD(a) (a)
#define TORAD(a) (a)
#else
#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE)
#define TORAD(a) ((a)*RADIANS_PER_DEGREE)
#endif
static void math_abs (void) {
lua_pushnumber(fabs(luaL_check_number(1)));
}
static void math_sin (void) {
lua_pushnumber(sin(TORAD(luaL_check_number(1))));
}
static void math_cos (void) {
lua_pushnumber(cos(TORAD(luaL_check_number(1))));
}
static void math_tan (void) {
lua_pushnumber(tan(TORAD(luaL_check_number(1))));
}
static void math_asin (void) {
lua_pushnumber(FROMRAD(asin(luaL_check_number(1))));
}
static void math_acos (void) {
lua_pushnumber(FROMRAD(acos(luaL_check_number(1))));
}
static void math_atan (void) {
lua_pushnumber(FROMRAD(atan(luaL_check_number(1))));
}
static void math_atan2 (void) {
lua_pushnumber(FROMRAD(atan2(luaL_check_number(1), luaL_check_number(2))));
}
static void math_ceil (void) {
lua_pushnumber(ceil(luaL_check_number(1)));
}
static void math_floor (void) {
lua_pushnumber(floor(luaL_check_number(1)));
}
static void math_mod (void) {
lua_pushnumber(fmod(luaL_check_number(1), luaL_check_number(2)));
}
static void math_sqrt (void) {
lua_pushnumber(sqrt(luaL_check_number(1)));
}
static void math_pow (void) {
lua_pushnumber(pow(luaL_check_number(1), luaL_check_number(2)));
}
static void math_log (void) {
lua_pushnumber(log(luaL_check_number(1)));
}
static void math_log10 (void) {
lua_pushnumber(log10(luaL_check_number(1)));
}
static void math_exp (void) {
lua_pushnumber(exp(luaL_check_number(1)));
}
static void math_deg (void) {
lua_pushnumber(luaL_check_number(1)/RADIANS_PER_DEGREE);
}
static void math_rad (void) {
lua_pushnumber(luaL_check_number(1)*RADIANS_PER_DEGREE);
}
static void math_frexp (void) {
int e;
lua_pushnumber(frexp(luaL_check_number(1), &e));
lua_pushnumber(e);
}
static void math_ldexp (void) {
lua_pushnumber(ldexp(luaL_check_number(1), luaL_check_int(2)));
}
static void math_min (void) {
int i = 1;
double dmin = luaL_check_number(i);
while (lua_getparam(++i) != LUA_NOOBJECT) {
double d = luaL_check_number(i);
if (d < dmin)
dmin = d;
}
lua_pushnumber(dmin);
}
static void math_max (void) {
int i = 1;
double dmax = luaL_check_number(i);
while (lua_getparam(++i) != LUA_NOOBJECT) {
double d = luaL_check_number(i);
if (d > dmax)
dmax = d;
}
lua_pushnumber(dmax);
}
static void math_random (void) {
/* the '%' avoids the (rare) case of r==1, and is needed also because on
some systems (SunOS!) "rand()" may return a value bigger than RAND_MAX */
double r = (double)(rand()%RAND_MAX) / (double)RAND_MAX;
int l = luaL_opt_int(1, 0);
if (l == 0)
lua_pushnumber(r);
else {
int u = luaL_opt_int(2, 0);
if (u == 0) {
u = l;
l = 1;
}
luaL_arg_check(l<=u, 1, "interval is empty");
lua_pushnumber((int)(r*(u-l+1))+l);
}
}
static void math_randomseed (void) {
srand(luaL_check_int(1));
}
static struct luaL_reg mathlib[] = {
{"abs", math_abs},
{"sin", math_sin},
{"cos", math_cos},
{"tan", math_tan},
{"asin", math_asin},
{"acos", math_acos},
{"atan", math_atan},
{"atan2", math_atan2},
{"ceil", math_ceil},
{"floor", math_floor},
{"mod", math_mod},
{"frexp", math_frexp},
{"ldexp", math_ldexp},
{"sqrt", math_sqrt},
{"min", math_min},
{"max", math_max},
{"log", math_log},
{"log10", math_log10},
{"exp", math_exp},
{"deg", math_deg},
{"rad", math_rad},
{"random", math_random},
{"randomseed", math_randomseed}
};
/*
** Open math library
*/
void lua_mathlibopen (void) {
luaL_openlib(mathlib, (sizeof(mathlib)/sizeof(mathlib[0])));
lua_pushcfunction(math_pow);
lua_pushnumber(0); /* to get its tag */
lua_settagmethod(lua_tag(lua_pop()), "pow");
lua_pushnumber(PI); lua_setglobal("PI");
}

140
lmem.c Normal file
View File

@@ -0,0 +1,140 @@
/*
** $Id: lmem.c,v 1.16 1999/05/20 20:43:06 roberto Exp roberto $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#include "lmem.h"
#include "lstate.h"
#include "lua.h"
/*
** real ANSI systems do not need these tests;
** but some systems (Sun OS) are not that ANSI...
*/
#ifdef OLD_ANSI
#define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s))
#define free(b) if (b) (free)(b)
#endif
#define MINSIZE 8 /* minimum size for "growing" vectors */
static unsigned long power2 (unsigned long n) {
unsigned long p = MINSIZE;
while (p<=n) p<<=1;
return p;
}
void *luaM_growaux (void *block, unsigned long nelems, int inc, int size,
char *errormsg, unsigned long limit) {
unsigned long newn = nelems+inc;
if (newn >= limit) lua_error(errormsg);
if ((newn ^ nelems) <= nelems || /* still the same power of 2 limit? */
(nelems > 0 && newn < MINSIZE)) /* or block already is MINSIZE? */
return block; /* do not need to reallocate */
else /* it crossed a power of 2 boundary; grow to next power */
return luaM_realloc(block, power2(newn)*size);
}
#ifndef DEBUG
/*
** generic allocation routine.
*/
void *luaM_realloc (void *block, unsigned long size) {
size_t s = (size_t)size;
if (s != size)
lua_error("memory allocation error: block too big");
if (size == 0) {
free(block); /* block may be NULL, that is OK for free */
return NULL;
}
block = realloc(block, s);
if (block == NULL)
lua_error(memEM);
return block;
}
#else
/* DEBUG */
#include <string.h>
#define HEADER (sizeof(double))
#define MARKSIZE 16
#define MARK 55
#define blocksize(b) ((unsigned long *)((char *)(b) - HEADER))
unsigned long numblocks = 0;
unsigned long totalmem = 0;
static void *checkblock (void *block) {
if (block == NULL)
return NULL;
else {
unsigned long *b = blocksize(block);
unsigned long size = *b;
int i;
for (i=0;i<MARKSIZE;i++)
LUA_ASSERT(*(((char *)b)+HEADER+size+i) == MARK+i, "corrupted block");
numblocks--;
totalmem -= size;
return b;
}
}
static void freeblock (void *block) {
if (block)
memset(block, -1, *blocksize(block)); /* erase block */
free(checkblock(block));
}
void *luaM_realloc (void *block, unsigned long size) {
unsigned long realsize = HEADER+size+MARKSIZE;
if (realsize != (size_t)realsize)
lua_error("memory allocation error: block too big");
if (size == 0) {
freeblock(block);
return NULL;
}
else {
char *newblock = malloc(realsize);
int i;
if (block) {
unsigned long oldsize = *blocksize(block);
if (oldsize > size) oldsize = size;
memcpy(newblock+HEADER, block, oldsize);
freeblock(block); /* erase (and check) old copy */
}
if (newblock == NULL)
lua_error(memEM);
totalmem += size;
numblocks++;
*(unsigned long *)newblock = size;
for (i=0;i<MARKSIZE;i++)
*(newblock+HEADER+size+i) = MARK+i;
return newblock+HEADER;
}
}
#endif

41
lmem.h Normal file
View File

@@ -0,0 +1,41 @@
/*
** $Id: lmem.h,v 1.7 1999/02/25 15:16:26 roberto Exp roberto $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#ifndef lmem_h
#define lmem_h
#include <stdlib.h>
/* memory error messages */
#define codeEM "code size overflow"
#define constantEM "constant table overflow"
#define refEM "reference table overflow"
#define tableEM "table overflow"
#define memEM "not enough memory"
#define arrEM "internal array bigger than `int' limit"
void *luaM_realloc (void *oldblock, unsigned long size);
void *luaM_growaux (void *block, unsigned long nelems, int inc, int size,
char *errormsg, unsigned long limit);
#define luaM_free(b) luaM_realloc((b), 0)
#define luaM_malloc(t) luaM_realloc(NULL, (t))
#define luaM_new(t) ((t *)luaM_malloc(sizeof(t)))
#define luaM_newvector(n,t) ((t *)luaM_malloc((n)*sizeof(t)))
#define luaM_growvector(v,nelems,inc,t,e,l) \
((v)=(t *)luaM_growaux(v,nelems,inc,sizeof(t),e,l))
#define luaM_reallocvector(v,n,t) ((v)=(t *)luaM_realloc(v,(n)*sizeof(t)))
#ifdef DEBUG
extern unsigned long numblocks;
extern unsigned long totalmem;
#endif
#endif

129
lobject.c Normal file
View File

@@ -0,0 +1,129 @@
/*
** $Id: lobject.c,v 1.18 1999/02/26 15:48:30 roberto Exp roberto $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdlib.h>
#include "lobject.h"
#include "lua.h"
char *luaO_typenames[] = { /* ORDER LUA_T */
"userdata", "number", "string", "table", "function", "function",
"nil", "function", "mark", "mark", "mark", "line", NULL
};
TObject luaO_nilobject = {LUA_T_NIL, {NULL}};
/* hash dimensions values */
static long dimensions[] =
{5L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
1644817L, 3289613L, 6579211L, 13158023L, MAX_INT};
int luaO_redimension (int oldsize)
{
int i;
for (i=0; dimensions[i]<MAX_INT; i++) {
if (dimensions[i] > oldsize)
return dimensions[i];
}
lua_error("tableEM");
return 0; /* to avoid warnings */
}
int luaO_equalval (TObject *t1, TObject *t2) {
switch (ttype(t1)) {
case LUA_T_NIL: return 1;
case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2);
case LUA_T_STRING: case LUA_T_USERDATA: return svalue(t1) == svalue(t2);
case LUA_T_ARRAY: return avalue(t1) == avalue(t2);
case LUA_T_PROTO: return tfvalue(t1) == tfvalue(t2);
case LUA_T_CPROTO: return fvalue(t1) == fvalue(t2);
case LUA_T_CLOSURE: return t1->value.cl == t2->value.cl;
default:
LUA_INTERNALERROR("invalid type");
return 0; /* UNREACHABLE */
}
}
void luaO_insertlist (GCnode *root, GCnode *node)
{
node->next = root->next;
root->next = node;
node->marked = 0;
}
#ifdef OLD_ANSI
void luaO_memup (void *dest, void *src, int size) {
while (size--)
((char *)dest)[size]=((char *)src)[size];
}
void luaO_memdown (void *dest, void *src, int size) {
int i;
for (i=0; i<size; i++)
((char *)dest)[i]=((char *)src)[i];
}
#endif
static double expten (unsigned int e) {
double exp = 10.0;
double res = 1.0;
for (; e; e>>=1) {
if (e & 1) res *= exp;
exp *= exp;
}
return res;
}
double luaO_str2d (char *s) { /* LUA_NUMBER */
double a = 0.0;
int point = 0;
while (isdigit((unsigned char)*s)) {
a = 10.0*a + (*(s++)-'0');
}
if (*s == '.') {
s++;
while (isdigit((unsigned char)*s)) {
a = 10.0*a + (*(s++)-'0');
point++;
}
}
if (toupper((unsigned char)*s) == 'E') {
int e = 0;
int sig = 1;
s++;
if (*s == '-') {
s++;
sig = -1;
}
else if (*s == '+') s++;
if (!isdigit((unsigned char)*s)) return -1; /* no digit in the exponent? */
do {
e = 10*e + (*(s++)-'0');
} while (isdigit((unsigned char)*s));
point -= sig*e;
}
while (isspace((unsigned char)*s)) s++;
if (*s != '\0') return -1; /* invalid trailing characters? */
if (point > 0)
a /= expten(point);
else if (point < 0)
a *= expten(-point);
return a;
}

204
lobject.h Normal file
View File

@@ -0,0 +1,204 @@
/*
** $Id: lobject.h,v 1.27 1999/03/04 21:17:26 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
#ifndef lobject_h
#define lobject_h
#include <limits.h>
#include "lua.h"
#ifdef DEBUG
#include "lauxlib.h"
#define LUA_INTERNALERROR(s) \
luaL_verror("INTERNAL ERROR - %s [%s:%d]",(s),__FILE__,__LINE__)
#define LUA_ASSERT(c,s) { if (!(c)) LUA_INTERNALERROR(s); }
#else
#define LUA_INTERNALERROR(s) /* empty */
#define LUA_ASSERT(c,s) /* empty */
#endif
/*
** "real" is the type "number" of Lua
** GREP LUA_NUMBER to change that
*/
#ifndef LUA_NUM_TYPE
#define LUA_NUM_TYPE double
#endif
typedef LUA_NUM_TYPE real;
#define Byte lua_Byte /* some systems have Byte as a predefined type */
typedef unsigned char Byte; /* unsigned 8 bits */
#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
typedef unsigned int IntPoint; /* unsigned with same size as a pointer (for hashing) */
/*
** Lua TYPES
** WARNING: if you change the order of this enumeration,
** grep "ORDER LUA_T"
*/
typedef enum {
LUA_T_USERDATA = 0, /* tag default for userdata */
LUA_T_NUMBER = -1, /* fixed tag for numbers */
LUA_T_STRING = -2, /* fixed tag for strings */
LUA_T_ARRAY = -3, /* tag default for tables (or arrays) */
LUA_T_PROTO = -4, /* fixed tag for functions */
LUA_T_CPROTO = -5, /* fixed tag for Cfunctions */
LUA_T_NIL = -6, /* last "pre-defined" tag */
LUA_T_CLOSURE = -7,
LUA_T_CLMARK = -8, /* mark for closures */
LUA_T_PMARK = -9, /* mark for Lua prototypes */
LUA_T_CMARK = -10, /* mark for C prototypes */
LUA_T_LINE = -11
} lua_Type;
#define NUM_TAGS 7
typedef union {
lua_CFunction f; /* LUA_T_CPROTO, LUA_T_CMARK */
real n; /* LUA_T_NUMBER */
struct TaggedString *ts; /* LUA_T_STRING, LUA_T_USERDATA */
struct TProtoFunc *tf; /* LUA_T_PROTO, LUA_T_PMARK */
struct Closure *cl; /* LUA_T_CLOSURE, LUA_T_CLMARK */
struct Hash *a; /* LUA_T_ARRAY */
int i; /* LUA_T_LINE */
} Value;
typedef struct TObject {
lua_Type ttype;
Value value;
} TObject;
/*
** generic header for garbage collector lists
*/
typedef struct GCnode {
struct GCnode *next;
int marked;
} GCnode;
/*
** String headers for string table
*/
typedef struct TaggedString {
GCnode head;
unsigned long hash;
int constindex; /* hint to reuse constants (= -1 if this is a userdata) */
union {
struct {
TObject globalval;
long len; /* if this is a string, here is its length */
} s;
struct {
int tag;
void *v; /* if this is a userdata, here is its value */
} d;
} u;
char str[1]; /* \0 byte already reserved */
} TaggedString;
/*
** Function Prototypes
*/
typedef struct TProtoFunc {
GCnode head;
struct TObject *consts;
int nconsts;
Byte *code; /* ends with opcode ENDCODE */
int lineDefined;
TaggedString *source;
struct LocVar *locvars; /* ends with line = -1 */
} TProtoFunc;
typedef struct LocVar {
TaggedString *varname; /* NULL signals end of scope */
int line;
} LocVar;
/* Macros to access structure members */
#define ttype(o) ((o)->ttype)
#define nvalue(o) ((o)->value.n)
#define svalue(o) ((o)->value.ts->str)
#define tsvalue(o) ((o)->value.ts)
#define clvalue(o) ((o)->value.cl)
#define avalue(o) ((o)->value.a)
#define fvalue(o) ((o)->value.f)
#define tfvalue(o) ((o)->value.tf)
#define protovalue(o) ((o)->value.cl->consts)
/*
** Closures
*/
typedef struct Closure {
GCnode head;
int nelems; /* not included the first one (always the prototype) */
TObject consts[1]; /* at least one for prototype */
} Closure;
typedef struct node {
TObject ref;
TObject val;
} Node;
typedef struct Hash {
GCnode head;
Node *node;
int nhash;
int nuse;
int htag;
} Hash;
extern char *luaO_typenames[];
#define luaO_typename(o) luaO_typenames[-ttype(o)]
extern TObject luaO_nilobject;
#define luaO_equalObj(t1,t2) ((ttype(t1) != ttype(t2)) ? 0 \
: luaO_equalval(t1,t2))
int luaO_equalval (TObject *t1, TObject *t2);
int luaO_redimension (int oldsize);
void luaO_insertlist (GCnode *root, GCnode *node);
double luaO_str2d (char *s);
#ifdef OLD_ANSI
void luaO_memup (void *dest, void *src, int size);
void luaO_memdown (void *dest, void *src, int size);
#else
#include <string.h>
#define luaO_memup(d,s,n) memmove(d,s,n)
#define luaO_memdown(d,s,n) memmove(d,s,n)
#endif
#endif

138
lopcodes.h Normal file
View File

@@ -0,0 +1,138 @@
/*
** $Id: lopcodes.h,v 1.32 1999/03/10 14:09:45 roberto Exp roberto $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
#ifndef lopcodes_h
#define lopcodes_h
/*
** NOTICE: variants of the same opcode must be consecutive: First, those
** with word parameter, then with byte parameter.
*/
typedef enum {
/* name parm before after side effect
-----------------------------------------------------------------------------*/
ENDCODE,/* - - (return) */
RETCODE,/* b - (return) */
CALL,/* b c v_c...v_1 f r_b...r_1 f(v1,...,v_c) */
TAILCALL,/* b c v_c...v_1 f (return) f(v1,...,v_c) */
PUSHNIL,/* b - nil_0...nil_b */
POP,/* b a_b...a_1 - */
PUSHNUMBERW,/* w - (float)w */
PUSHNUMBER,/* b - (float)b */
PUSHNUMBERNEGW,/* w - (float)-w */
PUSHNUMBERNEG,/* b - (float)-b */
PUSHCONSTANTW,/*w - CNST[w] */
PUSHCONSTANT,/* b - CNST[b] */
PUSHUPVALUE,/* b - Closure[b] */
PUSHLOCAL,/* b - LOC[b] */
GETGLOBALW,/* w - VAR[CNST[w]] */
GETGLOBAL,/* b - VAR[CNST[b]] */
GETTABLE,/* - i t t[i] */
GETDOTTEDW,/* w t t[CNST[w]] */
GETDOTTED,/* b t t[CNST[b]] */
PUSHSELFW,/* w t t t[CNST[w]] */
PUSHSELF,/* b t t t[CNST[b]] */
CREATEARRAYW,/* w - newarray(size = w) */
CREATEARRAY,/* b - newarray(size = b) */
SETLOCAL,/* b x - LOC[b]=x */
SETGLOBALW,/* w x - VAR[CNST[w]]=x */
SETGLOBAL,/* b x - VAR[CNST[b]]=x */
SETTABLEPOP,/* - v i t - t[i]=v */
SETTABLE,/* b v a_b...a_1 i t a_b...a_1 i t t[i]=v */
SETLISTW,/* w c v_c...v_1 t t t[i+w*FPF]=v_i */
SETLIST,/* b c v_c...v_1 t t t[i+b*FPF]=v_i */
SETMAP,/* b v_b k_b ...v_0 k_0 t t t[k_i]=v_i */
NEQOP,/* - y x (x~=y)? 1 : nil */
EQOP,/* - y x (x==y)? 1 : nil */
LTOP,/* - y x (x<y)? 1 : nil */
LEOP,/* - y x (x<y)? 1 : nil */
GTOP,/* - y x (x>y)? 1 : nil */
GEOP,/* - y x (x>=y)? 1 : nil */
ADDOP,/* - y x x+y */
SUBOP,/* - y x x-y */
MULTOP,/* - y x x*y */
DIVOP,/* - y x x/y */
POWOP,/* - y x x^y */
CONCOP,/* - y x x..y */
MINUSOP,/* - x -x */
NOTOP,/* - x (x==nil)? 1 : nil */
ONTJMPW,/* w x (x!=nil)? x : - (x!=nil)? PC+=w */
ONTJMP,/* b x (x!=nil)? x : - (x!=nil)? PC+=b */
ONFJMPW,/* w x (x==nil)? x : - (x==nil)? PC+=w */
ONFJMP,/* b x (x==nil)? x : - (x==nil)? PC+=b */
JMPW,/* w - - PC+=w */
JMP,/* b - - PC+=b */
IFFJMPW,/* w x - (x==nil)? PC+=w */
IFFJMP,/* b x - (x==nil)? PC+=b */
IFTUPJMPW,/* w x - (x!=nil)? PC-=w */
IFTUPJMP,/* b x - (x!=nil)? PC-=b */
IFFUPJMPW,/* w x - (x==nil)? PC-=w */
IFFUPJMP,/* b x - (x==nil)? PC-=b */
CLOSUREW,/* w c v_c...v_1 closure(CNST[w], v_c...v_1) */
CLOSURE,/* b c v_c...v_1 closure(CNST[b], v_c...v_1) */
SETLINEW,/* w - - LINE=w */
SETLINE,/* b - - LINE=b */
LONGARGW,/* w (add w*(1<<16) to arg of next instruction) */
LONGARG,/* b (add b*(1<<16) to arg of next instruction) */
CHECKSTACK /* b (assert #temporaries == b; only for internal debuging!) */
} OpCode;
#define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */
#define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) */
#define ZEROVARARG 128
/* maximum value of an arg of 3 bytes; must fit in an "int" */
#if MAX_INT < (1<<24)
#define MAX_ARG MAX_INT
#else
#define MAX_ARG ((1<<24)-1)
#endif
/* maximum value of a word of 2 bytes; cannot be bigger than MAX_ARG */
#if MAX_ARG < (1<<16)
#define MAX_WORD MAX_ARG
#else
#define MAX_WORD ((1<<16)-1)
#endif
/* maximum value of a byte */
#define MAX_BYTE ((1<<8)-1)
#endif

1391
lparser.c Normal file

File diff suppressed because it is too large Load Diff

20
lparser.h Normal file
View File

@@ -0,0 +1,20 @@
/*
** $Id: lparser.h,v 1.2 1997/12/22 20:57:18 roberto Exp roberto $
** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h
*/
#ifndef lparser_h
#define lparser_h
#include "lobject.h"
#include "lzio.h"
void luaY_codedebugline (int line);
TProtoFunc *luaY_parser (ZIO *z);
void luaY_error (char *s);
void luaY_syntaxerror (char *s, char *token);
#endif

86
lstate.c Normal file
View File

@@ -0,0 +1,86 @@
/*
** $Id: lstate.c,v 1.11 1999/05/11 14:19:32 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
#include "lbuiltin.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "llex.h"
#include "lmem.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
lua_State *lua_state = NULL;
void lua_open (void)
{
if (lua_state) return;
lua_state = luaM_new(lua_State);
L->Cstack.base = 0;
L->Cstack.lua2C = 0;
L->Cstack.num = 0;
L->errorJmp = NULL;
L->Mbuffer = NULL;
L->Mbuffbase = 0;
L->Mbuffsize = 0;
L->Mbuffnext = 0;
L->Cblocks = NULL;
L->numCblocks = 0;
L->debug = 0;
L->callhook = NULL;
L->linehook = NULL;
L->rootproto.next = NULL;
L->rootproto.marked = 0;
L->rootcl.next = NULL;
L->rootcl.marked = 0;
L->rootglobal.next = NULL;
L->rootglobal.marked = 0;
L->roottable.next = NULL;
L->roottable.marked = 0;
L->IMtable = NULL;
L->refArray = NULL;
L->refSize = 0;
L->GCthreshold = GARBAGE_BLOCK;
L->nblocks = 0;
luaD_init();
luaS_init();
luaX_init();
luaT_init();
luaB_predefine();
}
void lua_close (void)
{
TaggedString *alludata = luaS_collectudata();
L->GCthreshold = MAX_INT; /* to avoid GC during GC */
luaC_hashcallIM((Hash *)L->roottable.next); /* GC t.methods for tables */
luaC_strcallIM(alludata); /* GC tag methods for userdata */
luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */
luaH_free((Hash *)L->roottable.next);
luaF_freeproto((TProtoFunc *)L->rootproto.next);
luaF_freeclosure((Closure *)L->rootcl.next);
luaS_free(alludata);
luaS_freeall();
luaM_free(L->stack.stack);
luaM_free(L->IMtable);
luaM_free(L->refArray);
luaM_free(L->Mbuffer);
luaM_free(L->Cblocks);
luaM_free(L);
L = NULL;
#ifdef DEBUG
printf("total de blocos: %ld\n", numblocks);
printf("total de memoria: %ld\n", totalmem);
#endif
}

94
lstate.h Normal file
View File

@@ -0,0 +1,94 @@
/*
** $Id: lstate.h,v 1.18 1999/05/11 14:19:32 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
#ifndef lstate_h
#define lstate_h
#include <setjmp.h>
#include "lobject.h"
#include "lua.h"
#include "luadebug.h"
#define GARBAGE_BLOCK 150
typedef int StkId; /* index to stack elements */
/*
** "jmp_buf" may be an array, so it is better to make sure it has an
** address (and not that it *is* an address...)
*/
struct lua_longjmp {
jmp_buf b;
};
struct Stack {
TObject *top;
TObject *stack;
TObject *last;
};
struct C_Lua_Stack {
StkId base; /* when Lua calls C or C calls Lua, points to */
/* the first slot after the last parameter. */
StkId lua2C; /* points to first element of "array" lua2C */
int num; /* size of "array" lua2C */
};
typedef struct stringtable {
int size;
int nuse; /* number of elements (including EMPTYs) */
TaggedString **hash;
} stringtable;
enum Status {LOCK, HOLD, FREE, COLLECTED};
struct ref {
TObject o;
enum Status status;
};
struct lua_State {
/* thread-specific state */
struct Stack stack; /* Lua stack */
struct C_Lua_Stack Cstack; /* C2lua struct */
struct lua_longjmp *errorJmp; /* current error recover point */
char *Mbuffer; /* global buffer */
int Mbuffbase; /* current first position of Mbuffer */
int Mbuffsize; /* size of Mbuffer */
int Mbuffnext; /* next position to fill in Mbuffer */
struct C_Lua_Stack *Cblocks;
int numCblocks; /* number of nested Cblocks */
int debug;
lua_CHFunction callhook;
lua_LHFunction linehook;
/* global state */
GCnode rootproto; /* list of all prototypes */
GCnode rootcl; /* list of all closures */
GCnode roottable; /* list of all tables */
GCnode rootglobal; /* list of strings with global values */
stringtable *string_root; /* array of hash tables for strings and udata */
struct IM *IMtable; /* table for tag methods */
int last_tag; /* last used tag in IMtable */
struct ref *refArray; /* locked objects */
int refSize; /* size of refArray */
unsigned long GCthreshold;
unsigned long nblocks; /* number of 'blocks' currently allocated */
};
#define L lua_state
#endif

298
lstring.c Normal file
View File

@@ -0,0 +1,298 @@
/*
** $Id: lstring.c,v 1.18 1999/02/08 16:28:48 roberto Exp roberto $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
#include <string.h>
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "lua.h"
#define NUM_HASHSTR 31
#define NUM_HASHUDATA 31
#define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA)
#define gcsizestring(l) (1+(l/64)) /* "weight" for a string with length 'l' */
static TaggedString EMPTY = {{NULL, 2}, 0L, 0,
{{{LUA_T_NIL, {NULL}}, 0L}}, {0}};
void luaS_init (void) {
int i;
L->string_root = luaM_newvector(NUM_HASHS, stringtable);
for (i=0; i<NUM_HASHS; i++) {
L->string_root[i].size = 0;
L->string_root[i].nuse = 0;
L->string_root[i].hash = NULL;
}
}
static unsigned long hash_s (char *s, long l) {
unsigned long h = 0; /* seed */
while (l--)
h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++));
return h;
}
static int newsize (stringtable *tb) {
int size = tb->size;
int realuse = 0;
int i;
/* count how many entries are really in use */
for (i=0; i<size; i++)
if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY)
realuse++;
return luaO_redimension((realuse+1)*2); /* +1 is the new element */
}
static void grow (stringtable *tb) {
int ns = newsize(tb);
TaggedString **newhash = luaM_newvector(ns, TaggedString *);
int i;
for (i=0; i<ns; i++)
newhash[i] = NULL;
/* rehash */
tb->nuse = 0;
for (i=0; i<tb->size; i++) {
if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) {
unsigned long h = tb->hash[i]->hash;
int h1 = h%ns;
while (newhash[h1]) {
h1 += (h&(ns-2)) + 1; /* double hashing */
if (h1 >= ns) h1 -= ns;
}
newhash[h1] = tb->hash[i];
tb->nuse++;
}
}
luaM_free(tb->hash);
tb->size = ns;
tb->hash = newhash;
}
static TaggedString *newone_s (char *str, long l, unsigned long h) {
TaggedString *ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l);
memcpy(ts->str, str, l);
ts->str[l] = 0; /* ending 0 */
ts->u.s.globalval.ttype = LUA_T_NIL; /* initialize global value */
ts->u.s.len = l;
ts->constindex = 0;
L->nblocks += gcsizestring(l);
ts->head.marked = 0;
ts->head.next = (GCnode *)ts; /* signal it is in no list */
ts->hash = h;
return ts;
}
static TaggedString *newone_u (char *buff, int tag, unsigned long h) {
TaggedString *ts = luaM_new(TaggedString);
ts->u.d.v = buff;
ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
ts->constindex = -1; /* tag -> this is a userdata */
L->nblocks++;
ts->head.marked = 0;
ts->head.next = (GCnode *)ts; /* signal it is in no list */
ts->hash = h;
return ts;
}
static TaggedString *insert_s (char *str, long l, stringtable *tb) {
TaggedString *ts;
unsigned long h = hash_s(str, l);
int size = tb->size;
int j = -1;
int h1;
if ((long)tb->nuse*3 >= (long)size*2) {
grow(tb);
size = tb->size;
}
h1 = h%size;
while ((ts = tb->hash[h1]) != NULL) {
if (ts == &EMPTY)
j = h1;
else if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0))
return ts;
h1 += (h&(size-2)) + 1; /* double hashing */
if (h1 >= size) h1 -= size;
}
/* not found */
if (j != -1) /* is there an EMPTY space? */
h1 = j;
else
tb->nuse++;
ts = tb->hash[h1] = newone_s(str, l, h);
return ts;
}
static TaggedString *insert_u (void *buff, int tag, stringtable *tb) {
TaggedString *ts;
unsigned long h = (unsigned long)buff;
int size = tb->size;
int j = -1;
int h1;
if ((long)tb->nuse*3 >= (long)size*2) {
grow(tb);
size = tb->size;
}
h1 = h%size;
while ((ts = tb->hash[h1]) != NULL) {
if (ts == &EMPTY)
j = h1;
else if ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v)
return ts;
h1 += (h&(size-2)) + 1; /* double hashing */
if (h1 >= size) h1 -= size;
}
/* not found */
if (j != -1) /* is there an EMPTY space? */
h1 = j;
else
tb->nuse++;
ts = tb->hash[h1] = newone_u(buff, tag, h);
return ts;
}
TaggedString *luaS_createudata (void *udata, int tag) {
int t = ((unsigned)udata%NUM_HASHUDATA)+NUM_HASHSTR;
return insert_u(udata, tag, &L->string_root[t]);
}
TaggedString *luaS_newlstr (char *str, long l) {
int t = (l==0) ? 0 : ((int)((unsigned char)str[0]*l))%NUM_HASHSTR;
return insert_s(str, l, &L->string_root[t]);
}
TaggedString *luaS_new (char *str) {
return luaS_newlstr(str, strlen(str));
}
TaggedString *luaS_newfixedstring (char *str) {
TaggedString *ts = luaS_new(str);
if (ts->head.marked == 0)
ts->head.marked = 2; /* avoid GC */
return ts;
}
void luaS_free (TaggedString *l) {
while (l) {
TaggedString *next = (TaggedString *)l->head.next;
L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len);
luaM_free(l);
l = next;
}
}
/*
** Garbage collection functions.
*/
static void remove_from_list (GCnode *l) {
while (l) {
GCnode *next = l->next;
while (next && !next->marked)
next = l->next = next->next;
l = next;
}
}
TaggedString *luaS_collector (void) {
TaggedString *frees = NULL;
int i;
remove_from_list(&(L->rootglobal));
for (i=0; i<NUM_HASHS; i++) {
stringtable *tb = &L->string_root[i];
int j;
for (j=0; j<tb->size; j++) {
TaggedString *t = tb->hash[j];
if (t == NULL) continue;
if (t->head.marked == 1)
t->head.marked = 0;
else if (!t->head.marked) {
t->head.next = (GCnode *)frees;
frees = t;
tb->hash[j] = &EMPTY;
}
}
}
return frees;
}
TaggedString *luaS_collectudata (void) {
TaggedString *frees = NULL;
int i;
L->rootglobal.next = NULL; /* empty list of globals */
for (i=NUM_HASHSTR; i<NUM_HASHS; i++) {
stringtable *tb = &L->string_root[i];
int j;
for (j=0; j<tb->size; j++) {
TaggedString *t = tb->hash[j];
if (t == NULL || t == &EMPTY)
continue;
LUA_ASSERT(t->constindex == -1, "must be userdata");
t->head.next = (GCnode *)frees;
frees = t;
tb->hash[j] = &EMPTY;
}
}
return frees;
}
void luaS_freeall (void) {
int i;
for (i=0; i<NUM_HASHS; i++) {
stringtable *tb = &L->string_root[i];
int j;
for (j=0; j<tb->size; j++) {
TaggedString *t = tb->hash[j];
if (t == &EMPTY) continue;
luaM_free(t);
}
luaM_free(tb->hash);
}
luaM_free(L->string_root);
}
void luaS_rawsetglobal (TaggedString *ts, TObject *newval) {
ts->u.s.globalval = *newval;
if (ts->head.next == (GCnode *)ts) { /* is not in list? */
ts->head.next = L->rootglobal.next;
L->rootglobal.next = (GCnode *)ts;
}
}
char *luaS_travsymbol (int (*fn)(TObject *)) {
TaggedString *g;
for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next)
if (fn(&g->u.s.globalval))
return g->str;
return NULL;
}
int luaS_globaldefined (char *name) {
TaggedString *ts = luaS_new(name);
return ts->u.s.globalval.ttype != LUA_T_NIL;
}

28
lstring.h Normal file
View File

@@ -0,0 +1,28 @@
/*
** $Id: lstring.h,v 1.6 1997/12/01 20:31:25 roberto Exp roberto $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
#ifndef lstring_h
#define lstring_h
#include "lobject.h"
void luaS_init (void);
TaggedString *luaS_createudata (void *udata, int tag);
TaggedString *luaS_collector (void);
void luaS_free (TaggedString *l);
TaggedString *luaS_newlstr (char *str, long l);
TaggedString *luaS_new (char *str);
TaggedString *luaS_newfixedstring (char *str);
void luaS_rawsetglobal (TaggedString *ts, TObject *newval);
char *luaS_travsymbol (int (*fn)(TObject *));
int luaS_globaldefined (char *name);
TaggedString *luaS_collectudata (void);
void luaS_freeall (void);
#endif

594
lstrlib.c Normal file
View File

@@ -0,0 +1,594 @@
/*
** $Id: lstrlib.c,v 1.31 1999/05/14 12:24:04 roberto Exp roberto $
** Standard library for strings and pattern-matching
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lauxlib.h"
#include "lua.h"
#include "lualib.h"
static void addnchar (char *s, int n)
{
char *b = luaL_openspace(n);
memcpy(b, s, n);
luaL_addsize(n);
}
static void str_len (void)
{
long l;
luaL_check_lstr(1, &l);
lua_pushnumber(l);
}
static void closeandpush (void) {
lua_pushlstring(luaL_buffer(), luaL_getsize());
}
static long posrelat (long pos, long len) {
/* relative string position: negative means back from end */
return (pos>=0) ? pos : len+pos+1;
}
static void str_sub (void) {
long l;
char *s = luaL_check_lstr(1, &l);
long start = posrelat(luaL_check_long(2), l);
long end = posrelat(luaL_opt_long(3, -1), l);
if (start < 1) start = 1;
if (end > l) end = l;
if (start <= end)
lua_pushlstring(s+start-1, end-start+1);
else lua_pushstring("");
}
static void str_lower (void) {
long l;
int i;
char *s = luaL_check_lstr(1, &l);
luaL_resetbuffer();
for (i=0; i<l; i++)
luaL_addchar(tolower((unsigned char)(s[i])));
closeandpush();
}
static void str_upper (void) {
long l;
int i;
char *s = luaL_check_lstr(1, &l);
luaL_resetbuffer();
for (i=0; i<l; i++)
luaL_addchar(toupper((unsigned char)(s[i])));
closeandpush();
}
static void str_rep (void)
{
long l;
char *s = luaL_check_lstr(1, &l);
int n = luaL_check_int(2);
luaL_resetbuffer();
while (n-- > 0)
addnchar(s, l);
closeandpush();
}
static void str_byte (void) {
long l;
char *s = luaL_check_lstr(1, &l);
long pos = posrelat(luaL_opt_long(2, 1), l);
luaL_arg_check(0<pos && pos<=l, 2, "out of range");
lua_pushnumber((unsigned char)s[pos-1]);
}
static void str_char (void) {
int i = 0;
luaL_resetbuffer();
while (lua_getparam(++i) != LUA_NOOBJECT) {
double c = luaL_check_number(i);
luaL_arg_check((unsigned char)c == c, i, "invalid value");
luaL_addchar((unsigned char)c);
}
closeandpush();
}
/*
** {======================================================
** PATTERN MATCHING
** =======================================================
*/
#ifndef MAX_CAPT
#define MAX_CAPT 32 /* arbitrary limit */
#endif
struct Capture {
char *src_end; /* end ('\0') of source string */
int level; /* total number of captures (finished or unfinished) */
struct {
char *init;
int len; /* -1 signals unfinished capture */
} capture[MAX_CAPT];
};
#define ESC '%'
#define SPECIALS "^$*+?.([%-"
static void push_captures (struct Capture *cap) {
int i;
for (i=0; i<cap->level; i++) {
int l = cap->capture[i].len;
if (l == -1) lua_error("unfinished capture");
lua_pushlstring(cap->capture[i].init, l);
}
}
static int check_cap (int l, struct Capture *cap) {
l -= '1';
if (!(0 <= l && l < cap->level && cap->capture[l].len != -1))
lua_error("invalid capture index");
return l;
}
static int capture_to_close (struct Capture *cap) {
int level = cap->level;
for (level--; level>=0; level--)
if (cap->capture[level].len == -1) return level;
lua_error("invalid pattern capture");
return 0; /* to avoid warnings */
}
char *luaI_classend (char *p) {
switch (*p++) {
case ESC:
if (*p == '\0')
luaL_verror("incorrect pattern (ends with `%c')", ESC);
return p+1;
case '[':
if (*p == '^') p++;
if (*p == ']') p++;
p = strchr(p, ']');
if (!p) lua_error("incorrect pattern (missing `]')");
return p+1;
default:
return p;
}
}
static int matchclass (int c, int cl) {
int res;
switch (tolower(cl)) {
case 'a' : res = isalpha(c); break;
case 'c' : res = iscntrl(c); break;
case 'd' : res = isdigit(c); break;
case 'l' : res = islower(c); break;
case 'p' : res = ispunct(c); break;
case 's' : res = isspace(c); break;
case 'u' : res = isupper(c); break;
case 'w' : res = isalnum(c); break;
case 'x' : res = isxdigit(c); break;
case 'z' : res = (c == '\0'); break;
default: return (cl == c);
}
return (islower(cl) ? res : !res);
}
static int matchbracketclass (int c, char *p, char *end) {
int sig = 1;
if (*(p+1) == '^') {
sig = 0;
p++; /* skip the '^' */
}
while (++p < end) {
if (*p == ESC) {
p++;
if ((p < end) && matchclass(c, (unsigned char)*p))
return sig;
}
else if ((*(p+1) == '-') && (p+2 < end)) {
p+=2;
if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p)
return sig;
}
else if ((unsigned char)*p == c) return sig;
}
return !sig;
}
int luaI_singlematch (int c, char *p, char *ep) {
switch (*p) {
case '.': /* matches any char */
return 1;
case ESC:
return matchclass(c, (unsigned char)*(p+1));
case '[':
return matchbracketclass(c, p, ep-1);
default:
return ((unsigned char)*p == c);
}
}
static char *match (char *s, char *p, struct Capture *cap);
static char *matchbalance (char *s, char *p, struct Capture *cap) {
if (*p == 0 || *(p+1) == 0)
lua_error("unbalanced pattern");
if (*s != *p) return NULL;
else {
int b = *p;
int e = *(p+1);
int cont = 1;
while (++s < cap->src_end) {
if (*s == e) {
if (--cont == 0) return s+1;
}
else if (*s == b) cont++;
}
}
return NULL; /* string ends out of balance */
}
static char *max_expand (char *s, char *p, char *ep, struct Capture *cap) {
int i = 0; /* counts maximum expand for item */
while ((s+i)<cap->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep))
i++;
/* keeps trying to match mith the maximum repetitions */
while (i>=0) {
char *res = match((s+i), ep+1, cap);
if (res) return res;
i--; /* else didn't match; reduce 1 repetition to try again */
}
return NULL;
}
static char *min_expand (char *s, char *p, char *ep, struct Capture *cap) {
for (;;) {
char *res = match(s, ep+1, cap);
if (res != NULL)
return res;
else if (s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep))
s++; /* try with one more repetition */
else return NULL;
}
}
static char *start_capt (char *s, char *p, struct Capture *cap) {
char *res;
int level = cap->level;
if (level >= MAX_CAPT) lua_error("too many captures");
cap->capture[level].init = s;
cap->capture[level].len = -1;
cap->level = level+1;
if ((res=match(s, p+1, cap)) == NULL) /* match failed? */
cap->level--; /* undo capture */
return res;
}
static char *end_capt (char *s, char *p, struct Capture *cap) {
int l = capture_to_close(cap);
char *res;
cap->capture[l].len = s - cap->capture[l].init; /* close capture */
if ((res = match(s, p+1, cap)) == NULL) /* match failed? */
cap->capture[l].len = -1; /* undo capture */
return res;
}
static char *match_capture (char *s, int level, struct Capture *cap) {
int l = check_cap(level, cap);
int len = cap->capture[l].len;
if (cap->src_end-s >= len &&
memcmp(cap->capture[l].init, s, len) == 0)
return s+len;
else return NULL;
}
static char *match (char *s, char *p, struct Capture *cap) {
init: /* using goto's to optimize tail recursion */
switch (*p) {
case '(': /* start capture */
return start_capt(s, p, cap);
case ')': /* end capture */
return end_capt(s, p, cap);
case ESC: /* may be %[0-9] or %b */
if (isdigit((unsigned char)(*(p+1)))) { /* capture? */
s = match_capture(s, *(p+1), cap);
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(p+2, s, cap) */
}
else if (*(p+1) == 'b') { /* balanced string? */
s = matchbalance(s, p+2, cap);
if (s == NULL) return NULL;
p+=4; goto init; /* else return match(p+4, s, cap); */
}
else goto dflt; /* case default */
case '\0': /* end of pattern */
return s; /* match succeeded */
case '$':
if (*(p+1) == '\0') /* is the '$' the last char in pattern? */
return (s == cap->src_end) ? s : NULL; /* check end of string */
else goto dflt;
default: dflt: { /* it is a pattern item */
char *ep = luaI_classend(p); /* points to what is next */
int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep);
switch (*ep) {
case '?': { /* optional */
char *res;
if (m && ((res=match(s+1, ep+1, cap)) != NULL))
return res;
p=ep+1; goto init; /* else return match(s, ep+1, cap); */
}
case '*': /* 0 or more repetitions */
return max_expand(s, p, ep, cap);
case '+': /* 1 or more repetitions */
return (m ? max_expand(s+1, p, ep, cap) : NULL);
case '-': /* 0 or more repetitions (minimum) */
return min_expand(s, p, ep, cap);
default:
if (!m) return NULL;
s++; p=ep; goto init; /* else return match(s+1, ep, cap); */
}
}
}
}
static void str_find (void) {
long l;
char *s = luaL_check_lstr(1, &l);
char *p = luaL_check_string(2);
long init = posrelat(luaL_opt_long(3, 1), l) - 1;
struct Capture cap;
luaL_arg_check(0 <= init && init <= l, 3, "out of range");
if (lua_getparam(4) != LUA_NOOBJECT ||
strpbrk(p, SPECIALS) == NULL) { /* no special characters? */
char *s2 = strstr(s+init, p);
if (s2) {
lua_pushnumber(s2-s+1);
lua_pushnumber(s2-s+strlen(p));
return;
}
}
else {
int anchor = (*p == '^') ? (p++, 1) : 0;
char *s1=s+init;
cap.src_end = s+l;
do {
char *res;
cap.level = 0;
if ((res=match(s1, p, &cap)) != NULL) {
lua_pushnumber(s1-s+1); /* start */
lua_pushnumber(res-s); /* end */
push_captures(&cap);
return;
}
} while (s1++<cap.src_end && !anchor);
}
lua_pushnil(); /* if arrives here, it didn't find */
}
static void add_s (lua_Object newp, struct Capture *cap) {
if (lua_isstring(newp)) {
char *news = lua_getstring(newp);
int l = lua_strlen(newp);
int i;
for (i=0; i<l; i++) {
if (news[i] != ESC)
luaL_addchar(news[i]);
else {
i++; /* skip ESC */
if (!isdigit((unsigned char)news[i]))
luaL_addchar(news[i]);
else {
int level = check_cap(news[i], cap);
addnchar(cap->capture[level].init, cap->capture[level].len);
}
}
}
}
else { /* is a function */
lua_Object res;
int status;
int oldbuff;
lua_beginblock();
push_captures(cap);
/* function may use buffer, so save it and create a new one */
oldbuff = luaL_newbuffer(0);
status = lua_callfunction(newp);
/* restore old buffer */
luaL_oldbuffer(oldbuff);
if (status != 0) {
lua_endblock();
lua_error(NULL);
}
res = lua_getresult(1);
if (lua_isstring(res))
addnchar(lua_getstring(res), lua_strlen(res));
lua_endblock();
}
}
static void str_gsub (void) {
long srcl;
char *src = luaL_check_lstr(1, &srcl);
char *p = luaL_check_string(2);
lua_Object newp = lua_getparam(3);
int max_s = luaL_opt_int(4, srcl+1);
int anchor = (*p == '^') ? (p++, 1) : 0;
int n = 0;
struct Capture cap;
luaL_arg_check(lua_isstring(newp) || lua_isfunction(newp), 3,
"string or function expected");
luaL_resetbuffer();
cap.src_end = src+srcl;
while (n < max_s) {
char *e;
cap.level = 0;
e = match(src, p, &cap);
if (e) {
n++;
add_s(newp, &cap);
}
if (e && e>src) /* non empty match? */
src = e; /* skip it */
else if (src < cap.src_end)
luaL_addchar(*src++);
else break;
if (anchor) break;
}
addnchar(src, cap.src_end-src);
closeandpush();
lua_pushnumber(n); /* number of substitutions */
}
/* }====================================================== */
static void luaI_addquoted (int arg) {
long l;
char *s = luaL_check_lstr(arg, &l);
luaL_addchar('"');
while (l--) {
switch (*s) {
case '"': case '\\': case '\n':
luaL_addchar('\\');
luaL_addchar(*s);
break;
case '\0': addnchar("\\000", 4); break;
default: luaL_addchar(*s);
}
s++;
}
luaL_addchar('"');
}
/* maximum size of each format specification (such as '%-099.99d') */
#define MAX_FORMAT 20 /* arbitrary limit */
static void str_format (void) {
int arg = 1;
char *strfrmt = luaL_check_string(arg);
luaL_resetbuffer();
while (*strfrmt) {
if (*strfrmt != '%')
luaL_addchar(*strfrmt++);
else if (*++strfrmt == '%')
luaL_addchar(*strfrmt++); /* %% */
else { /* format item */
struct Capture cap;
char form[MAX_FORMAT]; /* to store the format ('%...') */
char *buff; /* to store the formatted item */
char *initf = strfrmt;
form[0] = '%';
if (isdigit((unsigned char)*initf) && *(initf+1) == '$') {
arg = *initf - '0';
initf += 2; /* skip the 'n$' */
}
arg++;
cap.src_end = strfrmt+strlen(strfrmt)+1;
cap.level = 0;
strfrmt = match(initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */
strfrmt-initf > MAX_FORMAT-2)
lua_error("invalid format (width or precision too long)");
strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */
form[strfrmt-initf+2] = 0;
buff = luaL_openspace(512); /* 512 > soid luaI_addquot99.99f', -1e308) */
switch (*strfrmt++) {
case 'c': case 'd': case 'i':
sprintf(buff, form, luaL_check_int(arg));
break;
case 'o': case 'u': case 'x': case 'X':
sprintf(buff, form, (unsigned int)luaL_check_number(arg));
break;
case 'e': case 'E': case 'f': case 'g': case 'G':
sprintf(buff, form, luaL_check_number(arg));
break;
case 'q':
luaI_addquoted(arg);
continue; /* skip the "addsize" at the end */
case 's': {
long l;
char *s = luaL_check_lstr(arg, &l);
if (cap.capture[1].len == 0 && l >= 100) {
/* no precision and string is too big to be formatted;
keep original string */
addnchar(s, l);
continue; /* skip the "addsize" at the end */
}
else {
sprintf(buff, form, s);
break;
}
}
default: /* also treat cases 'pnLlh' */
lua_error("invalid option in `format'");
}
luaL_addsize(strlen(buff));
}
}
closeandpush(); /* push the result */
}
static struct luaL_reg strlib[] = {
{"strlen", str_len},
{"strsub", str_sub},
{"strlower", str_lower},
{"strupper", str_upper},
{"strchar", str_char},
{"strrep", str_rep},
{"ascii", str_byte}, /* for compatibility with 3.0 and earlier */
{"strbyte", str_byte},
{"format", str_format},
{"strfind", str_find},
{"gsub", str_gsub}
};
/*
** Open string library
*/
void strlib_open (void)
{
luaL_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0])));
}

177
ltable.c Normal file
View File

@@ -0,0 +1,177 @@
/*
** $Id: ltable.c,v 1.21 1999/02/23 14:57:28 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#include "lauxlib.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "ltable.h"
#include "lua.h"
#define gcsize(n) (1+(n/16))
#define nuse(t) ((t)->nuse)
#define nodevector(t) ((t)->node)
#define TagDefault LUA_T_ARRAY;
static long int hashindex (TObject *ref) {
long int h;
switch (ttype(ref)) {
case LUA_T_NUMBER:
h = (long int)nvalue(ref);
break;
case LUA_T_STRING: case LUA_T_USERDATA:
h = (IntPoint)tsvalue(ref);
break;
case LUA_T_ARRAY:
h = (IntPoint)avalue(ref);
break;
case LUA_T_PROTO:
h = (IntPoint)tfvalue(ref);
break;
case LUA_T_CPROTO:
h = (IntPoint)fvalue(ref);
break;
case LUA_T_CLOSURE:
h = (IntPoint)clvalue(ref);
break;
default:
lua_error("unexpected type to index table");
h = 0; /* to avoid warnings */
}
return (h >= 0 ? h : -(h+1));
}
Node *luaH_present (Hash *t, TObject *key) {
int tsize = nhash(t);
long int h = hashindex(key);
int h1 = h%tsize;
Node *n = node(t, h1);
/* keep looking until an entry with "ref" equal to key or nil */
while ((ttype(ref(n)) == ttype(key)) ? !luaO_equalval(key, ref(n))
: ttype(ref(n)) != LUA_T_NIL) {
h1 += (h&(tsize-2)) + 1; /* double hashing */
if (h1 >= tsize) h1 -= tsize;
n = node(t, h1);
}
return n;
}
void luaH_free (Hash *frees) {
while (frees) {
Hash *next = (Hash *)frees->head.next;
L->nblocks -= gcsize(frees->nhash);
luaM_free(nodevector(frees));
luaM_free(frees);
frees = next;
}
}
static Node *hashnodecreate (int nhash) {
Node *v = luaM_newvector(nhash, Node);
int i;
for (i=0; i<nhash; i++)
ttype(ref(&v[i])) = ttype(val(&v[i])) = LUA_T_NIL;
return v;
}
Hash *luaH_new (int nhash) {
Hash *t = luaM_new(Hash);
nhash = luaO_redimension(nhash*3/2);
nodevector(t) = hashnodecreate(nhash);
nhash(t) = nhash;
nuse(t) = 0;
t->htag = TagDefault;
luaO_insertlist(&(L->roottable), (GCnode *)t);
L->nblocks += gcsize(nhash);
return t;
}
static int newsize (Hash *t) {
Node *v = t->node;
int size = nhash(t);
int realuse = 0;
int i;
for (i=0; i<size; i++) {
if (ttype(val(v+i)) != LUA_T_NIL)
realuse++;
}
return luaO_redimension((realuse+1)*2); /* +1 is the new element */
}
static void rehash (Hash *t) {
int nold = nhash(t);
Node *vold = nodevector(t);
int nnew = newsize(t);
int i;
nodevector(t) = hashnodecreate(nnew);
nhash(t) = nnew;
nuse(t) = 0;
for (i=0; i<nold; i++) {
Node *n = vold+i;
if (ttype(val(n)) != LUA_T_NIL) {
*luaH_present(t, ref(n)) = *n; /* copy old node to new hash */
nuse(t)++;
}
}
L->nblocks += gcsize(nnew)-gcsize(nold);
luaM_free(vold);
}
void luaH_set (Hash *t, TObject *ref, TObject *val) {
Node *n = luaH_present(t, ref);
if (ttype(ref(n)) != LUA_T_NIL)
*val(n) = *val;
else {
TObject buff;
buff = *val; /* rehash may invalidate this address */
if ((long)nuse(t)*3L > (long)nhash(t)*2L) {
rehash(t);
n = luaH_present(t, ref);
}
nuse(t)++;
*ref(n) = *ref;
*val(n) = buff;
}
}
int luaH_pos (Hash *t, TObject *r) {
Node *n = luaH_present(t, r);
luaL_arg_check(ttype(val(n)) != LUA_T_NIL, 2, "key not found");
return n-(t->node);
}
void luaH_setint (Hash *t, int ref, TObject *val) {
TObject index;
ttype(&index) = LUA_T_NUMBER;
nvalue(&index) = ref;
luaH_set(t, &index, val);
}
TObject *luaH_getint (Hash *t, int ref) {
TObject index;
ttype(&index) = LUA_T_NUMBER;
nvalue(&index) = ref;
return luaH_get(t, &index);
}

30
ltable.h Normal file
View File

@@ -0,0 +1,30 @@
/*
** $Id: ltable.h,v 1.10 1999/01/25 17:40:10 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
#ifndef ltable_h
#define ltable_h
#include "lobject.h"
#define node(t,i) (&(t)->node[i])
#define ref(n) (&(n)->ref)
#define val(n) (&(n)->val)
#define nhash(t) ((t)->nhash)
#define luaH_get(t,ref) (val(luaH_present((t), (ref))))
#define luaH_move(t,from,to) (luaH_setint(t, to, luaH_getint(t, from)))
Hash *luaH_new (int nhash);
void luaH_free (Hash *frees);
Node *luaH_present (Hash *t, TObject *key);
void luaH_set (Hash *t, TObject *ref, TObject *val);
int luaH_pos (Hash *t, TObject *r);
void luaH_setint (Hash *t, int ref, TObject *val);
TObject *luaH_getint (Hash *t, int ref);
#endif

248
ltm.c Normal file
View File

@@ -0,0 +1,248 @@
/*
** $Id: ltm.c,v 1.24 1999/02/26 15:48:55 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include <string.h>
#include "lauxlib.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "ltm.h"
char *luaT_eventname[] = { /* ORDER IM */
"gettable", "settable", "index", "getglobal", "setglobal", "add",
"sub", "mul", "div", "pow", "unm", "lt", "le", "gt", "ge",
"concat", "gc", "function", NULL
};
static int luaI_checkevent (char *name, char *list[]) {
int e = luaL_findstring(name, list);
if (e < 0)
luaL_verror("`%.50s' is not a valid event name", name);
return e;
}
/* events in LUA_T_NIL are all allowed, since this is used as a
* 'placeholder' for "default" fallbacks
*/
static char luaT_validevents[NUM_TAGS][IM_N] = { /* ORDER LUA_T, ORDER IM */
{1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */
{1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */
{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_PROTO */
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CPROTO */
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */
};
static int luaT_validevent (int t, int e) { /* ORDER LUA_T */
return (t < LUA_T_NIL) ? 1 : luaT_validevents[-t][e];
}
static void init_entry (int tag) {
int i;
for (i=0; i<IM_N; i++)
ttype(luaT_getim(tag, i)) = LUA_T_NIL;
}
void luaT_init (void) {
int t;
L->last_tag = -(NUM_TAGS-1);
luaM_growvector(L->IMtable, 0, NUM_TAGS, struct IM, arrEM, MAX_INT);
for (t=L->last_tag; t<=0; t++)
init_entry(t);
}
int lua_newtag (void) {
--L->last_tag;
luaM_growvector(L->IMtable, -(L->last_tag), 1, struct IM, arrEM, MAX_INT);
init_entry(L->last_tag);
return L->last_tag;
}
static void checktag (int tag) {
if (!(L->last_tag <= tag && tag <= 0))
luaL_verror("%d is not a valid tag", tag);
}
void luaT_realtag (int tag) {
if (!(L->last_tag <= tag && tag < LUA_T_NIL))
luaL_verror("tag %d was not created by `newtag'", tag);
}
int lua_copytagmethods (int tagto, int tagfrom) {
int e;
checktag(tagto);
checktag(tagfrom);
for (e=0; e<IM_N; e++) {
if (luaT_validevent(tagto, e))
*luaT_getim(tagto, e) = *luaT_getim(tagfrom, e);
}
return tagto;
}
int luaT_effectivetag (TObject *o) {
int t;
switch (t = ttype(o)) {
case LUA_T_ARRAY:
return o->value.a->htag;
case LUA_T_USERDATA: {
int tag = o->value.ts->u.d.tag;
return (tag >= 0) ? LUA_T_USERDATA : tag;
}
case LUA_T_CLOSURE:
return o->value.cl->consts[0].ttype;
#ifdef DEBUG
case LUA_T_PMARK: case LUA_T_CMARK:
case LUA_T_CLMARK: case LUA_T_LINE:
LUA_INTERNALERROR("invalid type");
#endif
default:
return t;
}
}
TObject *luaT_gettagmethod (int t, char *event) {
int e = luaI_checkevent(event, luaT_eventname);
checktag(t);
if (luaT_validevent(t, e))
return luaT_getim(t,e);
else
return &luaO_nilobject;
}
void luaT_settagmethod (int t, char *event, TObject *func) {
TObject temp;
int e = luaI_checkevent(event, luaT_eventname);
checktag(t);
if (!luaT_validevent(t, e))
luaL_verror("cannot change tag method `%.20s' for type `%.20s'%.20s",
luaT_eventname[e], luaO_typenames[-t],
(t == LUA_T_ARRAY || t == LUA_T_USERDATA) ? " with default tag"
: "");
temp = *func;
*func = *luaT_getim(t,e);
*luaT_getim(t, e) = temp;
}
char *luaT_travtagmethods (int (*fn)(TObject *)) { /* ORDER IM */
int e;
for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) {
int t;
for (t=0; t>=L->last_tag; t--)
if (fn(luaT_getim(t,e)))
return luaT_eventname[e];
}
return NULL;
}
/*
* ===================================================================
* compatibility with old fallback system
*/
#ifdef LUA_COMPAT2_5
#include "lapi.h"
#include "lstring.h"
static void errorFB (void)
{
lua_Object o = lua_getparam(1);
if (lua_isstring(o))
fprintf(stderr, "lua: %s\n", lua_getstring(o));
else
fprintf(stderr, "lua: unknown error\n");
}
static void nilFB (void) { }
static void typeFB (void) {
lua_error("unexpected type");
}
static void fillvalids (IMS e, TObject *func) {
int t;
for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++)
if (luaT_validevent(t, e))
*luaT_getim(t, e) = *func;
}
void luaT_setfallback (void) {
static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL};
TObject oldfunc;
lua_CFunction replace;
char *name = luaL_check_string(1);
lua_Object func = lua_getparam(2);
luaL_arg_check(lua_isfunction(func), 2, "function expected");
switch (luaL_findstring(name, oldnames)) {
case 0: { /* old error fallback */
TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval);
oldfunc = *em;
*em = *luaA_Address(func);
replace = errorFB;
break;
}
case 1: /* old getglobal fallback */
oldfunc = *luaT_getim(LUA_T_NIL, IM_GETGLOBAL);
*luaT_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaA_Address(func);
replace = nilFB;
break;
case 2: { /* old arith fallback */
int i;
oldfunc = *luaT_getim(LUA_T_NUMBER, IM_POW);
for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */
fillvalids(i, luaA_Address(func));
replace = typeFB;
break;
}
case 3: { /* old order fallback */
int i;
oldfunc = *luaT_getim(LUA_T_NIL, IM_LT);
for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */
fillvalids(i, luaA_Address(func));
replace = typeFB;
break;
}
default: {
int e;
if ((e = luaL_findstring(name, luaT_eventname)) >= 0) {
oldfunc = *luaT_getim(LUA_T_NIL, e);
fillvalids(e, luaA_Address(func));
replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB;
}
else {
luaL_verror("`%.50s' is not a valid fallback name", name);
replace = NULL; /* to avoid warnings */
}
}
}
if (oldfunc.ttype != LUA_T_NIL)
luaA_pushobject(&oldfunc);
else
lua_pushcfunction(replace);
}
#endif

62
ltm.h Normal file
View File

@@ -0,0 +1,62 @@
/*
** $Id: ltm.h,v 1.4 1997/11/26 18:53:45 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
#ifndef ltm_h
#define ltm_h
#include "lobject.h"
#include "lstate.h"
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER IM"
*/
typedef enum {
IM_GETTABLE = 0,
IM_SETTABLE,
IM_INDEX,
IM_GETGLOBAL,
IM_SETGLOBAL,
IM_ADD,
IM_SUB,
IM_MUL,
IM_DIV,
IM_POW,
IM_UNM,
IM_LT,
IM_LE,
IM_GT,
IM_GE,
IM_CONCAT,
IM_GC,
IM_FUNCTION
} IMS;
#define IM_N 18
struct IM {
TObject int_method[IM_N];
};
#define luaT_getim(tag,event) (&L->IMtable[-(tag)].int_method[event])
#define luaT_getimbyObj(o,e) (luaT_getim(luaT_effectivetag(o),(e)))
extern char *luaT_eventname[];
void luaT_init (void);
void luaT_realtag (int tag);
int luaT_effectivetag (TObject *o);
void luaT_settagmethod (int t, char *event, TObject *func);
TObject *luaT_gettagmethod (int t, char *event);
char *luaT_travtagmethods (int (*fn)(TObject *));
void luaT_setfallback (void); /* only if LUA_COMPAT2_5 */
#endif

232
lua.c
View File

@@ -1,92 +1,188 @@
/*
** lua.c
** Linguagem para Usuarios de Aplicacao
** $Id: lua.c,v 1.20 1999/06/24 19:42:02 roberto Exp roberto $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
char *rcs_lua="$Id: lua.c,v 1.6 1995/10/23 13:54:11 roberto Exp roberto $";
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "luadebug.h"
#include "lualib.h"
static int lua_argc;
static char **lua_argv;
/*
** although this function is POSIX, there is no standard header file that
** defines it
*/
int isatty (int fd);
#ifdef _POSIX_SOURCE
#include <unistd.h>
#else
#define isatty(x) (x==0) /* assume stdin is a tty */
#endif
/*
%F Allow Lua code to access argv strings.
%i Receive from Lua the argument number (starting with 1).
%o Return to Lua the argument, or nil if it does not exist.
*/
static void lua_getargv (void)
{
lua_Object lo = lua_getparam(1);
if (!lua_isnumber(lo))
lua_pushnil();
else
{
int n = (int)lua_getnumber(lo);
if (n < 1 || n > lua_argc) lua_pushnil();
else lua_pushstring(lua_argv[n]);
}
typedef void (*handler)(int); /* type for signal actions */
static void laction (int i);
static lua_LHFunction old_linehook = NULL;
static lua_CHFunction old_callhook = NULL;
static handler lreset (void) {
return signal(SIGINT, laction);
}
static void manual_input (void)
{
if (isatty(fileno(stdin)))
{
char buffer[250];
while (gets(buffer) != 0)
lua_dostring(buffer);
static void lstop (void) {
lua_setlinehook(old_linehook);
lua_setcallhook(old_callhook);
lreset();
lua_error("interrupted!");
}
static void laction (int i) {
signal(SIGINT, SIG_DFL); /* if another SIGINT happens before lstop,
terminate process (default action) */
old_linehook = lua_setlinehook((lua_LHFunction)lstop);
old_callhook = lua_setcallhook((lua_CHFunction)lstop);
}
static int ldo (int (*f)(char *), char *name) {
int res;
handler h = lreset();
res = f(name); /* dostring | dofile */
signal(SIGINT, h); /* restore old action */
return res;
}
static void print_message (void) {
fprintf(stderr,
"Lua: command line options:\n"
" -v print version information\n"
" -d turn debug on\n"
" -e stat dostring `stat'\n"
" -q interactive mode without prompt\n"
" -i interactive mode with prompt\n"
" - executes stdin as a file\n"
" a=b sets global `a' with string `b'\n"
" name dofile `name'\n\n");
}
static void assign (char *arg) {
if (strlen(arg) >= 500)
fprintf(stderr, "lua: shell argument too long");
else {
char buffer[500];
char *eq = strchr(arg, '=');
lua_pushstring(eq+1);
strncpy(buffer, arg, eq-arg);
buffer[eq-arg] = 0;
lua_setglobal(buffer);
}
else
lua_dofile(NULL); /* executes stdin as a file */
}
static void manual_input (int prompt) {
int cont = 1;
while (cont) {
char buffer[BUFSIZ];
int i = 0;
lua_beginblock();
if (prompt)
printf("%s", lua_getstring(lua_getglobal("_PROMPT")));
for(;;) {
int c = getchar();
if (c == EOF) {
cont = 0;
break;
}
else if (c == '\n') {
if (i>0 && buffer[i-1] == '\\')
buffer[i-1] = '\n';
else break;
}
else if (i >= BUFSIZ-1) {
fprintf(stderr, "lua: argument line too long\n");
break;
}
else buffer[i++] = (char)c;
}
buffer[i] = '\0';
ldo(lua_dostring, buffer);
lua_endblock();
}
printf("\n");
}
int main (int argc, char *argv[])
{
int i;
int result = 0;
iolib_open ();
strlib_open ();
mathlib_open ();
lua_register("argv", lua_getargv);
if (argc < 2)
manual_input();
else
{
for (i=1; i<argc; i++)
if (strcmp(argv[i], "--") == 0)
{
lua_argc = argc-i-1;
lua_argv = argv+i;
break;
}
for (i=1; i<argc; i++)
{
if (strcmp(argv[i], "--") == 0)
break;
else if (strcmp(argv[i], "-") == 0)
manual_input();
else if (strcmp(argv[i], "-v") == 0)
printf("%s %s\n(written by %s)\n\n",
LUA_VERSION, LUA_COPYRIGHT, LUA_AUTHORS);
else
result = lua_dofile (argv[i]);
int i;
lua_open();
lua_pushstring("> "); lua_setglobal("_PROMPT");
lua_userinit();
if (argc < 2) { /* no arguments? */
if (isatty(0)) {
printf("%s %s\n", LUA_VERSION, LUA_COPYRIGHT);
manual_input(1);
}
else
ldo(lua_dofile, NULL); /* executes stdin as a file */
}
}
return result;
else for (i=1; i<argc; i++) {
if (argv[i][0] == '-') { /* option? */
switch (argv[i][1]) {
case 0:
ldo(lua_dofile, NULL); /* executes stdin as a file */
break;
case 'i':
manual_input(1);
break;
case 'q':
manual_input(0);
break;
case 'd':
lua_setdebug(1);
break;
case 'v':
printf("%s %s\n(written by %s)\n\n",
LUA_VERSION, LUA_COPYRIGHT, LUA_AUTHORS);
break;
case 'e':
i++;
if (ldo(lua_dostring, argv[i]) != 0) {
fprintf(stderr, "lua: error running argument `%s'\n", argv[i]);
return 1;
}
break;
default:
print_message();
exit(1);
}
}
else if (strchr(argv[i], '='))
assign(argv[i]);
else {
int result = ldo(lua_dofile, argv[i]);
if (result) {
if (result == 2) {
fprintf(stderr, "lua: cannot execute file ");
perror(argv[i]);
}
exit(1);
}
}
}
#ifdef DEBUG
lua_close();
#endif
return 0;
}

215
lua.h
View File

@@ -1,108 +1,193 @@
/*
** LUA - Linguagem para Usuarios de Aplicacao
** Grupo de Tecnologia em Computacao Grafica
** TeCGraf - PUC-Rio
** $Id: lua.h,v 3.20 1995/10/31 16:41:53 roberto Exp roberto $
** $Id: lua.h,v 1.31 1999/04/15 12:33:19 roberto Exp roberto $
** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: lua@tecgraf.puc-rio.br
** www: http://www.tecgraf.puc-rio.br/lua/
** See Copyright Notice at the end of this file
*/
#ifndef lua_h
#define lua_h
#define LUA_VERSION "Lua 2.2"
#define LUA_COPYRIGHT "Copyright (C) 1994, 1995 TeCGraf"
#define LUA_VERSION "Lua 3.2"
#define LUA_COPYRIGHT "Copyright (C) 1994-1999 TeCGraf, PUC-Rio"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo"
/* Private Part */
typedef enum
{
LUA_T_NIL = -1,
LUA_T_NUMBER = -2,
LUA_T_STRING = -3,
LUA_T_ARRAY = -4,
LUA_T_FUNCTION = -5,
LUA_T_CFUNCTION= -6,
LUA_T_MARK = -7,
LUA_T_CMARK = -8,
LUA_T_LINE = -9,
LUA_T_USERDATA = 0
} lua_Type;
/* Public Part */
#define LUA_NOOBJECT 0
#define LUA_ANYTAG (-1)
typedef struct lua_State lua_State;
extern lua_State *lua_state;
typedef void (*lua_CFunction) (void);
typedef unsigned int lua_Object;
lua_Object lua_setfallback (char *name, lua_CFunction fallback);
void lua_open (void);
void lua_close (void);
lua_State *lua_setstate (lua_State *st);
lua_Object lua_settagmethod (int tag, char *event); /* In: new method */
lua_Object lua_gettagmethod (int tag, char *event);
int lua_newtag (void);
int lua_copytagmethods (int tagto, int tagfrom);
void lua_settag (int tag); /* In: object */
void lua_error (char *s);
int lua_dofile (char *filename);
int lua_dostring (char *string);
int lua_callfunction (lua_Object function);
int lua_call (char *funcname);
int lua_dofile (char *filename); /* Out: returns */
int lua_dostring (char *string); /* Out: returns */
int lua_dobuffer (char *buff, int size, char *name);
/* Out: returns */
int lua_callfunction (lua_Object f);
/* In: parameters; Out: returns */
void lua_beginblock (void);
void lua_endblock (void);
lua_Object lua_getparam (int number);
#define lua_getresult(_) lua_getparam(_)
lua_Object lua_lua2C (int number);
#define lua_getparam(_) lua_lua2C(_)
#define lua_getresult(_) lua_lua2C(_)
float lua_getnumber (lua_Object object);
int lua_isnil (lua_Object object);
int lua_istable (lua_Object object);
int lua_isuserdata (lua_Object object);
int lua_iscfunction (lua_Object object);
int lua_isnumber (lua_Object object);
int lua_isstring (lua_Object object);
int lua_isfunction (lua_Object object);
double lua_getnumber (lua_Object object);
char *lua_getstring (lua_Object object);
long lua_strlen (lua_Object object);
lua_CFunction lua_getcfunction (lua_Object object);
void *lua_getuserdata (lua_Object object);
void *lua_getuserdata (lua_Object object);
void lua_pushnil (void);
void lua_pushnumber (float n);
void lua_pushnumber (double n);
void lua_pushlstring (char *s, long len);
void lua_pushstring (char *s);
void lua_pushliteral (char *s);
void lua_pushcfunction (lua_CFunction fn);
void lua_pushusertag (void *u, int tag);
void lua_pushcclosure (lua_CFunction fn, int n);
void lua_pushusertag (void *u, int tag);
void lua_pushobject (lua_Object object);
lua_Object lua_pop (void);
lua_Object lua_getglobal (char *name);
void lua_storeglobal (char *name);
lua_Object lua_rawgetglobal (char *name);
void lua_setglobal (char *name); /* In: value */
void lua_rawsetglobal (char *name); /* In: value */
void lua_storesubscript (void);
lua_Object lua_getsubscript (void);
void lua_settable (void); /* In: table, index, value */
void lua_rawsettable (void); /* In: table, index, value */
lua_Object lua_gettable (void); /* In: table, index */
lua_Object lua_rawgettable (void); /* In: table, index */
int lua_type (lua_Object object);
int lua_tag (lua_Object object);
int lua_lock (void);
lua_Object lua_getlocked (int ref);
void lua_pushlocked (int ref);
void lua_unlock (int ref);
char *lua_nextvar (char *varname); /* Out: value */
int lua_next (lua_Object o, int i);
/* Out: ref, value */
int lua_ref (int lock); /* In: value */
lua_Object lua_getref (int ref);
void lua_unref (int ref);
lua_Object lua_createtable (void);
/* some useful macros */
#define lua_lockobject(o) (lua_pushobject(o), lua_lock())
#define lua_register(n,f) (lua_pushcfunction(f), lua_storeglobal(n))
#define lua_pushuserdata(u) lua_pushusertag(u, LUA_T_USERDATA)
#define lua_isnil(_) (lua_type(_)==LUA_T_NIL)
#define lua_isnumber(_) (lua_type(_)==LUA_T_NUMBER)
#define lua_isstring(_) (lua_type(_)==LUA_T_STRING)
#define lua_istable(_) (lua_type(_)==LUA_T_ARRAY)
#define lua_isfunction(_) (lua_type(_)==LUA_T_FUNCTION)
#define lua_iscfunction(_) (lua_type(_)==LUA_T_CFUNCTION)
#define lua_isuserdata(_) (lua_type(_)>=LUA_T_USERDATA)
long lua_collectgarbage (long limit);
/* for lua 1.1 compatibility. Avoid using these macros */
/* =============================================================== */
/* some useful macros/functions */
#define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_getsubscript())
#define lua_getfield(o,f) (lua_pushobject(o), lua_pushliteral(f), lua_getsubscript())
#define lua_call(name) lua_callfunction(lua_getglobal(name))
#define lua_pushref(ref) lua_pushobject(lua_getref(ref))
#define lua_refobject(o,l) (lua_pushobject(o), lua_ref(l))
#define lua_register(n,f) (lua_pushcfunction(f), lua_setglobal(n))
#define lua_pushuserdata(u) lua_pushusertag(u, 0)
#define lua_pushcfunction(f) lua_pushcclosure(f, 0)
#define lua_clonetag(t) lua_copytagmethods(lua_newtag(), (t))
lua_Object lua_seterrormethod (void); /* In: new method */
/* ==========================================================================
** for compatibility with old versions. Avoid using these macros/functions
** If your program does need any of these, define LUA_COMPAT2_5
*/
#ifdef LUA_COMPAT2_5
lua_Object lua_setfallback (char *event, lua_CFunction fallback);
#define lua_storeglobal lua_setglobal
#define lua_type lua_tag
#define lua_lockobject(o) lua_refobject(o,1)
#define lua_lock() lua_ref(1)
#define lua_getlocked lua_getref
#define lua_pushlocked lua_pushref
#define lua_unlock lua_unref
#define lua_pushliteral(o) lua_pushstring(o)
#define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_gettable())
#define lua_getfield(o,f) (lua_pushobject(o), lua_pushstring(f), lua_gettable())
#define lua_copystring(o) (strdup(lua_getstring(o)))
#define lua_getsubscript lua_gettable
#define lua_storesubscript lua_settable
#endif
#endif
/******************************************************************************
* Copyright (c) 1994-1999 TeCGraf, PUC-Rio. All rights reserved.
*
* Permission is hereby granted, without written agreement and without license
* or royalty fees, to use, copy, modify, and distribute this software and its
* documentation for any purpose, including commercial applications, subject to
* the following conditions:
*
* - The above copyright notice and this permission notice shall appear in all
* copies or substantial portions of this software.
*
* - The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be greatly
* appreciated (but it is not required).
*
* - Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* The authors specifically disclaim any warranties, including, but not limited
* to, the implied warranties of merchantability and fitness for a particular
* purpose. The software provided hereunder is on an "as is" basis, and the
* authors have no obligation to provide maintenance, support, updates,
* enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the
* authors be held liable to any party for direct, indirect, special,
* incidental, or consequential damages arising out of the use of this software
* and its documentation.
*
* The Lua language and this implementation have been entirely designed and
* written by Waldemar Celes Filho, Roberto Ierusalimschy and
* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio.
*
* This implementation contains no third-party code.
******************************************************************************/

1014
lua.stx

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,34 @@
/*
** LUA - Linguagem para Usuarios de Aplicacao
** Grupo de Tecnologia em Computacao Grafica
** TeCGraf - PUC-Rio
** $Id: luadebug.h,v 1.1 1995/10/17 14:12:45 roberto Exp roberto $
** $Id: luadebug.h,v 1.5 1999/02/04 17:47:59 roberto Exp roberto $
** Debugging API
** See Copyright Notice in lua.h
*/
#ifndef luadebug_h
#define luadebug_h
#include "lua.h"
lua_Object lua_stackedfunction(int level);
void lua_funcinfo (lua_Object func, char **filename, int *linedefined);
int lua_currentline (lua_Object func);
char *getobjname (lua_Object o, char **name);
typedef lua_Object lua_Function;
typedef void (*lua_LHFunction) (int line);
typedef void (*lua_CHFunction) (lua_Function func, char *file, int line);
lua_Function lua_stackedfunction (int level);
void lua_funcinfo (lua_Object func, char **source, int *linedefined);
int lua_currentline (lua_Function func);
char *lua_getobjname (lua_Object o, char **name);
lua_Object lua_getlocal (lua_Function func, int local_number, char **name);
int lua_setlocal (lua_Function func, int local_number);
int lua_nups (lua_Function func);
lua_LHFunction lua_setlinehook (lua_LHFunction func);
lua_CHFunction lua_setcallhook (lua_CHFunction func);
int lua_setdebug (int debug);
#endif

View File

@@ -1,22 +1,36 @@
/*
** Libraries to be used in LUA programs
** Grupo de Tecnologia em Computacao Grafica
** TeCGraf - PUC-Rio
** $Id: lualib.h,v 1.3 1994/12/13 15:59:16 roberto Exp roberto $
** $Id: lualib.h,v 1.5 1999/01/08 16:47:44 roberto Exp roberto $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
#ifndef lualib_h
#define lualib_h
void iolib_open (void);
void strlib_open (void);
void mathlib_open (void);
#include "lua.h"
void lua_iolibopen (void);
void lua_strlibopen (void);
void lua_mathlibopen (void);
void lua_dblibopen (void);
/* auxiliar functions (private) */
void lua_arg_error(char *funcname);
char *lua_check_string (int numArg, char *funcname);
float lua_check_number (int numArg, char *funcname);
void lua_userinit (void);
/* To keep compatibility with old versions */
#define iolib_open lua_iolibopen
#define strlib_open lua_strlibopen
#define mathlib_open lua_mathlibopen
/* Auxiliary functions (private) */
char *luaI_classend (char *p);
int luaI_singlematch (int c, char *p, char *ep);
#endif

View File

@@ -1,44 +0,0 @@
/*
** mem.c
** TecCGraf - PUC-Rio
*/
char *rcs_mem = "$Id: mem.c,v 1.4 1995/01/13 22:11:12 roberto Exp roberto $";
#include <stdlib.h>
#include <string.h>
#include "mem.h"
#include "lua.h"
void luaI_free (void *block)
{
*((int *)block) = -1; /* to catch errors */
free(block);
}
void *luaI_malloc (unsigned long size)
{
void *block = malloc((size_t)size);
if (block == NULL)
lua_error("not enough memory");
return block;
}
void *luaI_realloc (void *oldblock, unsigned long size)
{
void *block = realloc(oldblock, (size_t)size);
if (block == NULL)
lua_error("not enough memory");
return block;
}
char *luaI_strdup (char *str)
{
char *newstr = luaI_malloc(strlen(str)+1);
strcpy(newstr, str);
return newstr;
}

View File

@@ -1,25 +0,0 @@
/*
** mem.c
** memory manager for lua
** $Id: mem.h,v 1.1 1994/11/16 17:38:08 roberto Stab roberto $
*/
#ifndef mem_h
#define mem_h
#ifndef NULL
#define NULL 0
#endif
void luaI_free (void *block);
void *luaI_malloc (unsigned long size);
void *luaI_realloc (void *oldblock, unsigned long size);
char *luaI_strdup (char *str);
#define new(s) ((s *)luaI_malloc(sizeof(s)))
#define newvector(n,s) ((s *)luaI_malloc((n)*sizeof(s)))
#define growvector(old,n,s) ((s *)luaI_realloc(old,(n)*sizeof(s)))
#endif

239
lundump.c Normal file
View File

@@ -0,0 +1,239 @@
/*
** $Id: lundump.c,v 1.21 1999/07/02 19:34:26 lhf Exp $
** load bytecodes from files
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include <string.h>
#include "lauxlib.h"
#include "lfunc.h"
#include "lmem.h"
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"
#define LoadBlock(b,size,Z) ezread(Z,b,size)
static void unexpectedEOZ (ZIO* Z)
{
luaL_verror("unexpected end of file in %s",zname(Z));
}
static int ezgetc (ZIO* Z)
{
int c=zgetc(Z);
if (c==EOZ) unexpectedEOZ(Z);
return c;
}
static void ezread (ZIO* Z, void* b, int n)
{
int r=zread(Z,b,n);
if (r!=0) unexpectedEOZ(Z);
}
static unsigned int LoadWord (ZIO* Z)
{
unsigned int hi=ezgetc(Z);
unsigned int lo=ezgetc(Z);
return (hi<<8)|lo;
}
static unsigned long LoadLong (ZIO* Z)
{
unsigned long hi=LoadWord(Z);
unsigned long lo=LoadWord(Z);
return (hi<<16)|lo;
}
/*
* convert number from text
*/
double luaU_str2d (char* b, char* where)
{
int negative=(b[0]=='-');
double x=luaO_str2d(b+negative);
if (x<0) luaL_verror("cannot convert number '%s' in %s",b,where);
return negative ? -x : x;
}
static real LoadNumber (ZIO* Z, int native)
{
real x;
if (native)
{
LoadBlock(&x,sizeof(x),Z);
return x;
}
else
{
char b[256];
int size=ezgetc(Z);
LoadBlock(b,size,Z);
b[size]=0;
return luaU_str2d(b,zname(Z));
}
}
static int LoadInt (ZIO* Z, char* message)
{
unsigned long l=LoadLong(Z);
unsigned int i=l;
if (i!=l) luaL_verror(message,l,zname(Z));
return i;
}
#define PAD 5 /* two word operands plus opcode */
static Byte* LoadCode (ZIO* Z)
{
int size=LoadInt(Z,"code too long (%ld bytes) in %s");
Byte* b=luaM_malloc(size+PAD);
LoadBlock(b,size,Z);
if (b[size-1]!=ENDCODE) luaL_verror("bad code in %s",zname(Z));
memset(b+size,ENDCODE,PAD); /* pad code for safety */
return b;
}
static TaggedString* LoadTString (ZIO* Z)
{
long size=LoadLong(Z);
if (size==0)
return NULL;
else
{
char* s=luaL_openspace(size);
LoadBlock(s,size,Z);
return luaS_newlstr(s,size-1);
}
}
static void LoadLocals (TProtoFunc* tf, ZIO* Z)
{
int i,n=LoadInt(Z,"too many locals (%ld) in %s");
if (n==0) return;
tf->locvars=luaM_newvector(n+1,LocVar);
for (i=0; i<n; i++)
{
tf->locvars[i].line=LoadInt(Z,"too many lines (%ld) in %s");
tf->locvars[i].varname=LoadTString(Z);
}
tf->locvars[i].line=-1; /* flag end of vector */
tf->locvars[i].varname=NULL;
}
static TProtoFunc* LoadFunction (ZIO* Z, int native);
static void LoadConstants (TProtoFunc* tf, ZIO* Z, int native)
{
int i,n=LoadInt(Z,"too many constants (%ld) in %s");
tf->nconsts=n;
if (n==0) return;
tf->consts=luaM_newvector(n,TObject);
for (i=0; i<n; i++)
{
TObject* o=tf->consts+i;
ttype(o)=-ezgetc(Z); /* ttype(o) is negative - ORDER LUA_T */
switch (ttype(o))
{
case LUA_T_NUMBER:
nvalue(o)=LoadNumber(Z,native);
break;
case LUA_T_STRING:
tsvalue(o)=LoadTString(Z);
break;
case LUA_T_PROTO:
tfvalue(o)=LoadFunction(Z,native);
break;
case LUA_T_NIL:
break;
default: /* cannot happen */
luaU_badconstant("load",i,o,tf);
break;
}
}
}
static TProtoFunc* LoadFunction (ZIO* Z, int native)
{
TProtoFunc* tf=luaF_newproto();
tf->lineDefined=LoadInt(Z,"lineDefined too large (%ld) in %s");
tf->source=LoadTString(Z);
if (tf->source==NULL) tf->source=luaS_new(zname(Z));
tf->code=LoadCode(Z);
LoadLocals(tf,Z);
LoadConstants(tf,Z,native);
return tf;
}
static void LoadSignature (ZIO* Z)
{
char* s=SIGNATURE;
while (*s!=0 && ezgetc(Z)==*s)
++s;
if (*s!=0) luaL_verror("bad signature in %s",zname(Z));
}
static int LoadHeader (ZIO* Z)
{
int version,sizeofR;
int native;
LoadSignature(Z);
version=ezgetc(Z);
if (version>VERSION)
luaL_verror(
"%s too new: version=0x%02x; expected at most 0x%02x",
zname(Z),version,VERSION);
if (version<VERSION0) /* check last major change */
luaL_verror(
"%s too old: version=0x%02x; expected at least 0x%02x",
zname(Z),version,VERSION0);
sizeofR=ezgetc(Z);
native=(sizeofR!=0);
if (native) /* test number representation */
{
if (sizeofR!=sizeof(real))
luaL_verror("unknown number size in %s: read %d; expected %d",
zname(Z),sizeofR,sizeof(real));
else
{
real tf=TEST_NUMBER;
real f=LoadNumber(Z,native);
if ((long)f!=(long)tf)
luaL_verror("unknown number format in %s: "
"read " NUMBER_FMT "; expected " NUMBER_FMT,
zname(Z),f,tf);
}
}
return native;
}
static TProtoFunc* LoadChunk (ZIO* Z)
{
return LoadFunction(Z,LoadHeader(Z));
}
/*
** load one chunk from a file or buffer
** return main if ok and NULL at EOF
*/
TProtoFunc* luaU_undump1 (ZIO* Z)
{
int c=zgetc(Z);
if (c==ID_CHUNK)
return LoadChunk(Z);
else if (c!=EOZ)
luaL_verror("%s is not a Lua binary file",zname(Z));
return NULL;
}
/*
* handle constants that cannot happen
*/
void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf)
{
int t=ttype(o);
char* name= (t>0 || t<LUA_T_LINE) ? "?" : luaO_typenames[-t];
luaL_verror("cannot %s constant #%d: type=%d [%s]" IN,s,i,t,name,INLOC);
}

39
lundump.h Normal file
View File

@@ -0,0 +1,39 @@
/*
** $Id: lundump.h,v 1.15 1999/07/02 19:34:26 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
#ifndef lundump_h
#define lundump_h
#include "lobject.h"
#include "lzio.h"
TProtoFunc* luaU_undump1 (ZIO* Z); /* load one chunk */
void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf);
/* handle cases that cannot happen */
double luaU_str2d (char* b, char* where);
/* convert number from text */
/* definitions for headers of binary files */
#define VERSION 0x32 /* last format change was in 3.2 */
#define VERSION0 0x32 /* last major change was in 3.2 */
#define ID_CHUNK 27 /* binary files start with ESC... */
#define SIGNATURE "Lua" /* ...followed by this signature */
/* formats for error messages */
#define SOURCE "<%s:%d>"
#define IN " in %p " SOURCE
#define INLOC tf,tf->source->str,tf->lineDefined
/* format for numbers in listings and error messages */
#ifndef NUMBER_FMT
#define NUMBER_FMT "%.16g" /* LUA_NUMBER */
#endif
/* a multiple of PI for testing native format */
/* multiplying by 1E8 gives non-trivial integer values */
#define TEST_NUMBER 3.14159265358979323846E8
#endif

635
lvm.c Normal file
View File

@@ -0,0 +1,635 @@
/*
** $Id: lvm.c,v 1.57 1999/05/21 19:41:49 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "luadebug.h"
#include "lvm.h"
#ifdef OLD_ANSI
#define strcoll(a,b) strcmp(a,b)
#endif
#define highbyte(x) ((x)<<8)
/* Extra stack size to run a function: LUA_T_LINE(1), TM calls(2), ... */
#define EXTRA_STACK 5
static TaggedString *strconc (TaggedString *l, TaggedString *r) {
long nl = l->u.s.len;
long nr = r->u.s.len;
char *buffer = luaL_openspace(nl+nr);
memcpy(buffer, l->str, nl);
memcpy(buffer+nl, r->str, nr);
return luaS_newlstr(buffer, nl+nr);
}
int luaV_tonumber (TObject *obj) { /* LUA_NUMBER */
if (ttype(obj) != LUA_T_STRING)
return 1;
else {
double t;
char *e = svalue(obj);
int sig = 1;
while (isspace((unsigned char)*e)) e++;
if (*e == '-') {
e++;
sig = -1;
}
else if (*e == '+') e++;
/* no digit before or after decimal point? */
if (!isdigit((unsigned char)*e) && !isdigit((unsigned char)*(e+1)))
return 2;
t = luaO_str2d(e);
if (t<0) return 2;
nvalue(obj) = (real)t*sig;
ttype(obj) = LUA_T_NUMBER;
return 0;
}
}
int luaV_tostring (TObject *obj) { /* LUA_NUMBER */
if (ttype(obj) != LUA_T_NUMBER)
return 1;
else {
char s[32]; /* 16 digits, signal, point and \0 (+ some extra...) */
sprintf(s, "%.16g", (double)nvalue(obj));
tsvalue(obj) = luaS_new(s);
ttype(obj) = LUA_T_STRING;
return 0;
}
}
void luaV_setn (Hash *t, int val) {
TObject index, value;
ttype(&index) = LUA_T_STRING; tsvalue(&index) = luaS_new("n");
ttype(&value) = LUA_T_NUMBER; nvalue(&value) = val;
luaH_set(t, &index, &value);
}
void luaV_closure (int nelems) {
if (nelems > 0) {
struct Stack *S = &L->stack;
Closure *c = luaF_newclosure(nelems);
c->consts[0] = *(S->top-1);
memcpy(&c->consts[1], S->top-(nelems+1), nelems*sizeof(TObject));
S->top -= nelems;
ttype(S->top-1) = LUA_T_CLOSURE;
(S->top-1)->value.cl = c;
}
}
/*
** Function to index a table.
** Receives the table at top-2 and the index at top-1.
*/
void luaV_gettable (void) {
TObject *table = L->stack.top-2;
TObject *im;
if (ttype(table) != LUA_T_ARRAY) { /* not a table, get gettable method */
im = luaT_getimbyObj(table, IM_GETTABLE);
if (ttype(im) == LUA_T_NIL)
lua_error("indexed expression not a table");
}
else { /* object is a table... */
int tg = table->value.a->htag;
im = luaT_getim(tg, IM_GETTABLE);
if (ttype(im) == LUA_T_NIL) { /* and does not have a "gettable" method */
TObject *h = luaH_get(avalue(table), table+1);
if (ttype(h) == LUA_T_NIL &&
(ttype(im=luaT_getim(tg, IM_INDEX)) != LUA_T_NIL)) {
/* result is nil and there is an "index" tag method */
luaD_callTM(im, 2, 1); /* calls it */
}
else {
L->stack.top--;
*table = *h; /* "push" result into table position */
}
return;
}
/* else it has a "gettable" method, go through to next command */
}
/* object is not a table, or it has a "gettable" method */
luaD_callTM(im, 2, 1);
}
/*
** Receives table at *t, index at *(t+1) and value at top.
*/
void luaV_settable (TObject *t) {
struct Stack *S = &L->stack;
TObject *im;
if (ttype(t) != LUA_T_ARRAY) { /* not a table, get "settable" method */
im = luaT_getimbyObj(t, IM_SETTABLE);
if (ttype(im) == LUA_T_NIL)
lua_error("indexed expression not a table");
}
else { /* object is a table... */
im = luaT_getim(avalue(t)->htag, IM_SETTABLE);
if (ttype(im) == LUA_T_NIL) { /* and does not have a "settable" method */
luaH_set(avalue(t), t+1, S->top-1);
S->top--; /* pop value */
return;
}
/* else it has a "settable" method, go through to next command */
}
/* object is not a table, or it has a "settable" method */
/* prepare arguments and call the tag method */
*(S->top+1) = *(L->stack.top-1);
*(S->top) = *(t+1);
*(S->top-1) = *t;
S->top += 2; /* WARNING: caller must assure stack space */
luaD_callTM(im, 3, 0);
}
void luaV_rawsettable (TObject *t) {
if (ttype(t) != LUA_T_ARRAY)
lua_error("indexed expression not a table");
else {
struct Stack *S = &L->stack;
luaH_set(avalue(t), t+1, S->top-1);
S->top -= 3;
}
}
void luaV_getglobal (TaggedString *ts) {
/* WARNING: caller must assure stack space */
/* only userdata, tables and nil can have getglobal tag methods */
static char valid_getglobals[] = {1, 0, 0, 1, 0, 0, 1, 0}; /* ORDER LUA_T */
TObject *value = &ts->u.s.globalval;
if (valid_getglobals[-ttype(value)]) {
TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL);
if (ttype(im) != LUA_T_NIL) { /* is there a tag method? */
struct Stack *S = &L->stack;
ttype(S->top) = LUA_T_STRING;
tsvalue(S->top) = ts;
S->top++;
*S->top++ = *value;
luaD_callTM(im, 2, 1);
return;
}
/* else no tag method: go through to default behavior */
}
*L->stack.top++ = *value; /* default behavior */
}
void luaV_setglobal (TaggedString *ts) {
TObject *oldvalue = &ts->u.s.globalval;
TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
if (ttype(im) == LUA_T_NIL) /* is there a tag method? */
luaS_rawsetglobal(ts, --L->stack.top);
else {
/* WARNING: caller must assure stack space */
struct Stack *S = &L->stack;
TObject newvalue;
newvalue = *(S->top-1);
ttype(S->top-1) = LUA_T_STRING;
tsvalue(S->top-1) = ts;
*S->top++ = *oldvalue;
*S->top++ = newvalue;
luaD_callTM(im, 3, 0);
}
}
static void call_binTM (IMS event, char *msg)
{
TObject *im = luaT_getimbyObj(L->stack.top-2, event);/* try first operand */
if (ttype(im) == LUA_T_NIL) {
im = luaT_getimbyObj(L->stack.top-1, event); /* try second operand */
if (ttype(im) == LUA_T_NIL) {
im = luaT_getim(0, event); /* try a 'global' i.m. */
if (ttype(im) == LUA_T_NIL)
lua_error(msg);
}
}
lua_pushstring(luaT_eventname[event]);
luaD_callTM(im, 3, 1);
}
static void call_arith (IMS event)
{
call_binTM(event, "unexpected type in arithmetic operation");
}
static int luaV_strcomp (char *l, long ll, char *r, long lr)
{
for (;;) {
long temp = strcoll(l, r);
if (temp != 0) return temp;
/* strings are equal up to a '\0' */
temp = strlen(l); /* index of first '\0' in both strings */
if (temp == ll) /* l is finished? */
return (temp == lr) ? 0 : -1; /* l is equal or smaller than r */
else if (temp == lr) /* r is finished? */
return 1; /* l is greater than r (because l is not finished) */
/* both strings longer than temp; go on comparing (after the '\0') */
temp++;
l += temp; ll -= temp; r += temp; lr -= temp;
}
}
void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal,
lua_Type ttype_great, IMS op) {
struct Stack *S = &L->stack;
TObject *l = S->top-2;
TObject *r = S->top-1;
real result;
if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER)
result = nvalue(l)-nvalue(r);
else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING)
result = luaV_strcomp(svalue(l), tsvalue(l)->u.s.len,
svalue(r), tsvalue(r)->u.s.len);
else {
call_binTM(op, "unexpected type in comparison");
return;
}
S->top--;
nvalue(S->top-1) = 1;
ttype(S->top-1) = (result < 0) ? ttype_less :
(result == 0) ? ttype_equal : ttype_great;
}
void luaV_pack (StkId firstel, int nvararg, TObject *tab) {
TObject *firstelem = L->stack.stack+firstel;
int i;
Hash *htab;
if (nvararg < 0) nvararg = 0;
htab = avalue(tab) = luaH_new(nvararg+1); /* +1 for field 'n' */
ttype(tab) = LUA_T_ARRAY;
for (i=0; i<nvararg; i++)
luaH_setint(htab, i+1, firstelem+i);
luaV_setn(htab, nvararg); /* store counter in field "n" */
}
static void adjust_varargs (StkId first_extra_arg)
{
TObject arg;
luaV_pack(first_extra_arg,
(L->stack.top-L->stack.stack)-first_extra_arg, &arg);
luaD_adjusttop(first_extra_arg);
*L->stack.top++ = arg;
}
/*
** Execute the given opcode, until a RET. Parameters are between
** [stack+base,top). Returns n such that the the results are between
** [stack+n,top).
*/
StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
struct Stack *S = &L->stack; /* to optimize */
register Byte *pc = tf->code;
TObject *consts = tf->consts;
if (L->callhook)
luaD_callHook(base, tf, 0);
luaD_checkstack((*pc++)+EXTRA_STACK);
if (*pc < ZEROVARARG)
luaD_adjusttop(base+*(pc++));
else { /* varargs */
luaC_checkGC();
adjust_varargs(base+(*pc++)-ZEROVARARG);
}
for (;;) {
register int aux = 0;
switchentry:
switch ((OpCode)*pc++) {
case ENDCODE:
S->top = S->stack + base;
goto ret;
case RETCODE:
base += *pc++;
goto ret;
case CALL: aux = *pc++;
luaD_calln(*pc++, aux);
break;
case TAILCALL: aux = *pc++;
luaD_calln(*pc++, MULT_RET);
base += aux;
goto ret;
case PUSHNIL: aux = *pc++;
do {
ttype(S->top++) = LUA_T_NIL;
} while (aux--);
break;
case POP: aux = *pc++;
S->top -= aux;
break;
case PUSHNUMBERW: aux += highbyte(*pc++);
case PUSHNUMBER: aux += *pc++;
ttype(S->top) = LUA_T_NUMBER;
nvalue(S->top) = aux;
S->top++;
break;
case PUSHNUMBERNEGW: aux += highbyte(*pc++);
case PUSHNUMBERNEG: aux += *pc++;
ttype(S->top) = LUA_T_NUMBER;
nvalue(S->top) = -aux;
S->top++;
break;
case PUSHCONSTANTW: aux += highbyte(*pc++);
case PUSHCONSTANT: aux += *pc++;
*S->top++ = consts[aux];
break;
case PUSHUPVALUE: aux = *pc++;
*S->top++ = cl->consts[aux+1];
break;
case PUSHLOCAL: aux = *pc++;
*S->top++ = *((S->stack+base) + aux);
break;
case GETGLOBALW: aux += highbyte(*pc++);
case GETGLOBAL: aux += *pc++;
luaV_getglobal(tsvalue(&consts[aux]));
break;
case GETTABLE:
luaV_gettable();
break;
case GETDOTTEDW: aux += highbyte(*pc++);
case GETDOTTED: aux += *pc++;
*S->top++ = consts[aux];
luaV_gettable();
break;
case PUSHSELFW: aux += highbyte(*pc++);
case PUSHSELF: aux += *pc++; {
TObject receiver;
receiver = *(S->top-1);
*S->top++ = consts[aux];
luaV_gettable();
*S->top++ = receiver;
break;
}
case CREATEARRAYW: aux += highbyte(*pc++);
case CREATEARRAY: aux += *pc++;
luaC_checkGC();
avalue(S->top) = luaH_new(aux);
ttype(S->top) = LUA_T_ARRAY;
S->top++;
break;
case SETLOCAL: aux = *pc++;
*((S->stack+base) + aux) = *(--S->top);
break;
case SETGLOBALW: aux += highbyte(*pc++);
case SETGLOBAL: aux += *pc++;
luaV_setglobal(tsvalue(&consts[aux]));
break;
case SETTABLEPOP:
luaV_settable(S->top-3);
S->top -= 2; /* pop table and index */
break;
case SETTABLE:
luaV_settable(S->top-3-(*pc++));
break;
case SETLISTW: aux += highbyte(*pc++);
case SETLIST: aux += *pc++; {
int n = *(pc++);
Hash *arr = avalue(S->top-n-1);
aux *= LFIELDS_PER_FLUSH;
for (; n; n--)
luaH_setint(arr, n+aux, --S->top);
break;
}
case SETMAP: aux = *pc++; {
Hash *arr = avalue(S->top-(2*aux)-3);
do {
luaH_set(arr, S->top-2, S->top-1);
S->top-=2;
} while (aux--);
break;
}
case NEQOP: aux = 1;
case EQOP: {
int res = luaO_equalObj(S->top-2, S->top-1);
if (aux) res = !res;
S->top--;
ttype(S->top-1) = res ? LUA_T_NUMBER : LUA_T_NIL;
nvalue(S->top-1) = 1;
break;
}
case LTOP:
luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
break;
case LEOP:
luaV_comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE);
break;
case GTOP:
luaV_comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT);
break;
case GEOP:
luaV_comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE);
break;
case ADDOP: {
TObject *l = S->top-2;
TObject *r = S->top-1;
if (tonumber(r) || tonumber(l))
call_arith(IM_ADD);
else {
nvalue(l) += nvalue(r);
--S->top;
}
break;
}
case SUBOP: {
TObject *l = S->top-2;
TObject *r = S->top-1;
if (tonumber(r) || tonumber(l))
call_arith(IM_SUB);
else {
nvalue(l) -= nvalue(r);
--S->top;
}
break;
}
case MULTOP: {
TObject *l = S->top-2;
TObject *r = S->top-1;
if (tonumber(r) || tonumber(l))
call_arith(IM_MUL);
else {
nvalue(l) *= nvalue(r);
--S->top;
}
break;
}
case DIVOP: {
TObject *l = S->top-2;
TObject *r = S->top-1;
if (tonumber(r) || tonumber(l))
call_arith(IM_DIV);
else {
nvalue(l) /= nvalue(r);
--S->top;
}
break;
}
case POWOP:
call_binTM(IM_POW, "undefined operation");
break;
case CONCOP: {
TObject *l = S->top-2;
TObject *r = S->top-1;
if (tostring(l) || tostring(r))
call_binTM(IM_CONCAT, "unexpected type for concatenation");
else {
tsvalue(l) = strconc(tsvalue(l), tsvalue(r));
--S->top;
}
luaC_checkGC();
break;
}
case MINUSOP:
if (tonumber(S->top-1)) {
ttype(S->top) = LUA_T_NIL;
S->top++;
call_arith(IM_UNM);
}
else
nvalue(S->top-1) = - nvalue(S->top-1);
break;
case NOTOP:
ttype(S->top-1) =
(ttype(S->top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL;
nvalue(S->top-1) = 1;
break;
case ONTJMPW: aux += highbyte(*pc++);
case ONTJMP: aux += *pc++;
if (ttype(S->top-1) != LUA_T_NIL) pc += aux;
else S->top--;
break;
case ONFJMPW: aux += highbyte(*pc++);
case ONFJMP: aux += *pc++;
if (ttype(S->top-1) == LUA_T_NIL) pc += aux;
else S->top--;
break;
case JMPW: aux += highbyte(*pc++);
case JMP: aux += *pc++;
pc += aux;
break;
case IFFJMPW: aux += highbyte(*pc++);
case IFFJMP: aux += *pc++;
if (ttype(--S->top) == LUA_T_NIL) pc += aux;
break;
case IFTUPJMPW: aux += highbyte(*pc++);
case IFTUPJMP: aux += *pc++;
if (ttype(--S->top) != LUA_T_NIL) pc -= aux;
break;
case IFFUPJMPW: aux += highbyte(*pc++);
case IFFUPJMP: aux += *pc++;
if (ttype(--S->top) == LUA_T_NIL) pc -= aux;
break;
case CLOSUREW: aux += highbyte(*pc++);
case CLOSURE: aux += *pc++;
*S->top++ = consts[aux];
luaV_closure(*pc++);
luaC_checkGC();
break;
case SETLINEW: aux += highbyte(*pc++);
case SETLINE: aux += *pc++;
if ((S->stack+base-1)->ttype != LUA_T_LINE) {
/* open space for LINE value */
luaD_openstack((S->top-S->stack)-base);
base++;
(S->stack+base-1)->ttype = LUA_T_LINE;
}
(S->stack+base-1)->value.i = aux;
if (L->linehook)
luaD_lineHook(aux);
break;
case LONGARGW: aux += highbyte(*pc++);
case LONGARG: aux += *pc++;
aux = highbyte(highbyte(aux));
goto switchentry; /* do not reset "aux" */
case CHECKSTACK: aux = *pc++;
LUA_ASSERT((S->top-S->stack)-base == aux && S->last >= S->top,
"wrong stack size");
break;
}
} ret:
if (L->callhook)
luaD_callHook(0, NULL, 1);
return base;
}

34
lvm.h Normal file
View File

@@ -0,0 +1,34 @@
/*
** $Id: lvm.h,v 1.7 1998/12/30 17:26:49 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
#ifndef lvm_h
#define lvm_h
#include "ldo.h"
#include "lobject.h"
#include "ltm.h"
#define tonumber(o) ((ttype(o) != LUA_T_NUMBER) && (luaV_tonumber(o) != 0))
#define tostring(o) ((ttype(o) != LUA_T_STRING) && (luaV_tostring(o) != 0))
void luaV_pack (StkId firstel, int nvararg, TObject *tab);
int luaV_tonumber (TObject *obj);
int luaV_tostring (TObject *obj);
void luaV_setn (Hash *t, int val);
void luaV_gettable (void);
void luaV_settable (TObject *t);
void luaV_rawsettable (TObject *t);
void luaV_getglobal (TaggedString *ts);
void luaV_setglobal (TaggedString *ts);
StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base);
void luaV_closure (int nelems);
void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal,
lua_Type ttype_great, IMS op);
#endif

84
lzio.c Normal file
View File

@@ -0,0 +1,84 @@
/*
** $Id: lzio.c,v 1.6 1999/03/04 14:49:18 roberto Exp roberto $
** a generic input stream interface
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include <string.h>
#include "lzio.h"
/* ----------------------------------------------------- memory buffers --- */
static int zmfilbuf (ZIO* z) {
return EOZ;
}
ZIO* zmopen (ZIO* z, char* b, int size, char *name)
{
if (b==NULL) return NULL;
z->n=size;
z->p= (unsigned char *)b;
z->filbuf=zmfilbuf;
z->u=NULL;
z->name=name;
return z;
}
/* ------------------------------------------------------------ strings --- */
ZIO* zsopen (ZIO* z, char* s, char *name)
{
if (s==NULL) return NULL;
return zmopen(z,s,strlen(s),name);
}
/* -------------------------------------------------------------- FILEs --- */
static int zffilbuf (ZIO* z) {
int n;
if (feof((FILE *)z->u)) return EOZ;
n=fread(z->buffer,1,ZBSIZE,z->u);
if (n==0) return EOZ;
z->n=n-1;
z->p=z->buffer;
return *(z->p++);
}
ZIO* zFopen (ZIO* z, FILE* f, char *name)
{
if (f==NULL) return NULL;
z->n=0;
z->p=z->buffer;
z->filbuf=zffilbuf;
z->u=f;
z->name=name;
return z;
}
/* --------------------------------------------------------------- read --- */
int zread (ZIO *z, void *b, int n) {
while (n) {
int m;
if (z->n == 0) {
if (z->filbuf(z) == EOZ)
return n; /* return number of missing bytes */
zungetc(z); /* put result from 'filbuf' in the buffer */
}
m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
memcpy(b, z->p, m);
z->n -= m;
z->p += m;
b = (char *)b + m;
n -= m;
}
return 0;
}

50
lzio.h Normal file
View File

@@ -0,0 +1,50 @@
/*
** $Id: lzio.h,v 1.3 1997/12/22 20:57:18 roberto Exp roberto $
** Buffered streams
** See Copyright Notice in lua.h
*/
#ifndef lzio_h
#define lzio_h
#include <stdio.h>
/* For Lua only */
#define zFopen luaZ_Fopen
#define zsopen luaZ_sopen
#define zmopen luaZ_mopen
#define zread luaZ_read
#define EOZ (-1) /* end of stream */
typedef struct zio ZIO;
ZIO* zFopen (ZIO* z, FILE* f, char *name); /* open FILEs */
ZIO* zsopen (ZIO* z, char* s, char *name); /* string */
ZIO* zmopen (ZIO* z, char* b, int size, char *name); /* memory */
int zread (ZIO* z, void* b, int n); /* read next n bytes */
#define zgetc(z) (--(z)->n>=0 ? ((int)*(z)->p++): (z)->filbuf(z))
#define zungetc(z) (++(z)->n,--(z)->p)
#define zname(z) ((z)->name)
/* --------- Private Part ------------------ */
#define ZBSIZE 256 /* buffer size */
struct zio {
int n; /* bytes still unread */
unsigned char* p; /* current position in buffer */
int (*filbuf)(ZIO* z);
void* u; /* additional data */
char *name;
unsigned char buffer[ZBSIZE]; /* buffer */
};
#endif

160
makefile
View File

@@ -1,46 +1,82 @@
# $Id: makefile,v 1.15 1995/10/17 18:16:58 roberto Exp roberto $
#
## $Id: makefile,v 1.18 1999/02/23 15:01:29 roberto Exp roberto $
## Makefile
## See Copyright Notice in lua.h
#
#configuration
#CONFIGURATION
# define (undefine) POPEN if your system (does not) support piped I/O
CONFIG = -DPOPEN
#
# define (undefine) _POSIX_SOURCE if your system is (not) POSIX compliant
#
# define (undefine) OLD_ANSI if your system does NOT have some new ANSI
# facilities (e.g. strerror, locale.h, memmove). SunOS does not comply;
# so, add "-DOLD_ANSI" on SunOS
#
# define LUA_COMPAT2_5 if yous system does need to be compatible with
# version 2.5 (or older)
#
# define LUA_NUM_TYPE if you need numbers to be different from double
# (for instance, -DLUA_NUM_TYPE=float)
#
CONFIG = -DPOPEN -D_POSIX_SOURCE
#CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG
# Compilation parameters
CC = gcc
CFLAGS = $(CONFIG) -I/usr/5include -Wall -Wmissing-prototypes -Wshadow -ansi -O2
CWARNS = -Wall -Wmissing-prototypes -Wshadow -pedantic -Wpointer-arith -Wcast-align -Waggregate-return
CFLAGS = $(CONFIG) $(CWARNS) -ansi -O2
# To make early versions
CO_OPTIONS =
#CC = acc
#CFLAGS = -fast -I/usr/5include
AR = ar
ARFLAGS = rvl
# Aplication modules
LUAOBJS = \
parser.o \
lex.o \
opcode.o \
hash.o \
table.o \
inout.o \
tree.o \
fallback.o \
mem.o \
func.o
lapi.o \
lauxlib.o \
lbuffer.o \
lbuiltin.o \
ldo.o \
lfunc.o \
lgc.o \
llex.o \
lmem.o \
lobject.o \
lparser.o \
lstate.o \
lstring.o \
ltable.o \
ltm.o \
lvm.o \
lundump.o \
lzio.o
LIBOBJS = \
iolib.o \
mathlib.o \
strlib.o
liolib.o \
lmathlib.o \
lstrlib.o \
ldblib.o \
linit.o
lua : lua.o lua.a lualib.a
$(CC) $(CFLAGS) -o $@ lua.o lua.a lualib.a -lm
lua : lua.o liblua.a liblualib.a
$(CC) $(CFLAGS) -o $@ lua.o -L. -llua -llualib -lm
lua.a : parser.o $(LUAOBJS)
liblua.a : $(LUAOBJS)
$(AR) $(ARFLAGS) $@ $?
ranlib lua.a
ranlib $@
lualib.a : $(LIBOBJS)
liblualib.a : $(LIBOBJS)
$(AR) $(ARFLAGS) $@ $?
ranlib $@
@@ -48,35 +84,57 @@ liblua.so.1.0 : lua.o
ld -o liblua.so.1.0 $(LUAOBJS)
parser.c : lua.stx
yacc++ -d lua.stx ; mv -f y.tab.c parser.c ; mv -f y.tab.h parser.h
clear :
rcsclean
rm -f *.o
rm -f parser.c parser.h
co lua.h lualib.h luadebug.h
% : RCS/%,v
co $@
rm -f
co $(CO_OPTIONS) lua.h lualib.h luadebug.h
fallback.o : fallback.c mem.h fallback.h opcode.h lua.h types.h tree.h func.h
func.o : func.c table.h tree.h types.h opcode.h lua.h func.h mem.h
hash.o : hash.c mem.h opcode.h lua.h types.h tree.h func.h hash.h table.h
inout.o : inout.c mem.h opcode.h lua.h types.h tree.h func.h hash.h inout.h \
table.h
iolib.o : iolib.c lua.h lualib.h luadebug.h
lex.o : lex.c mem.h tree.h types.h table.h opcode.h lua.h func.h inout.h parser.h \
ugly.h
lua.o : lua.c lua.h lualib.h
mathlib.o : mathlib.c lualib.h lua.h
mem.o : mem.c mem.h lua.h
opcode.o : opcode.c mem.h opcode.h lua.h types.h tree.h func.h hash.h inout.h \
table.h fallback.h luadebug.h
parser.o : parser.c mem.h opcode.h lua.h types.h tree.h func.h hash.h inout.h \
table.h
strlib.o : strlib.c lua.h lualib.h
table.o : table.c mem.h opcode.h lua.h types.h tree.h func.h hash.h table.h \
inout.h fallback.h
tree.o : tree.c mem.h lua.h tree.h types.h table.h opcode.h func.h
%.h : RCS/%.h,v
co $(CO_OPTIONS) $@
%.c : RCS/%.c,v
co $(CO_OPTIONS) $@
lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h \
luadebug.h lfunc.h lgc.h lmem.h lstring.h ltable.h ltm.h lvm.h
lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h
lbuffer.o: lbuffer.c lauxlib.h lua.h lmem.h lstate.h lobject.h \
luadebug.h
lbuiltin.o: lbuiltin.c lapi.h lua.h lobject.h lauxlib.h lbuiltin.h \
ldo.h lstate.h luadebug.h lfunc.h lmem.h lstring.h ltable.h ltm.h \
lundump.h lzio.h lvm.h
ldblib.o: ldblib.c lauxlib.h lua.h luadebug.h lualib.h
ldo.o: ldo.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \
lmem.h lparser.h lzio.h lstring.h ltm.h lundump.h lvm.h
lfunc.o: lfunc.c lfunc.h lobject.h lua.h lmem.h lstate.h luadebug.h
lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h luadebug.h lfunc.h lgc.h \
lmem.h lstring.h ltable.h ltm.h
linit.o: linit.c lua.h lualib.h
liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h
llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \
lparser.h lstate.h luadebug.h lstring.h
lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h
lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h luadebug.h
lobject.o: lobject.c lobject.h lua.h
lparser.o: lparser.c lauxlib.h lua.h ldo.h lobject.h lstate.h \
luadebug.h lfunc.h llex.h lzio.h lmem.h lopcodes.h lparser.h \
lstring.h
lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h \
luadebug.h lfunc.h lgc.h llex.h lzio.h lmem.h lstring.h ltable.h \
ltm.h
lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h luadebug.h \
lstring.h
lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h
ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h \
luadebug.h ltable.h
ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h luadebug.h \
ltm.h
lua.o: lua.c lua.h luadebug.h lualib.h
lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \
lstring.h lundump.h lzio.h
lvm.o: lvm.c lauxlib.h lua.h ldo.h lobject.h lstate.h luadebug.h \
lfunc.h lgc.h lmem.h lopcodes.h lstring.h ltable.h ltm.h lvm.h
lzio.o: lzio.c lzio.h

3803
manual.tex

File diff suppressed because it is too large Load Diff

212
mathlib.c
View File

@@ -1,212 +0,0 @@
/*
** mathlib.c
** Mathematics library to LUA
*/
char *rcs_mathlib="$Id: mathlib.c,v 1.12 1995/10/09 12:48:38 roberto Exp roberto $";
#include <stdio.h> /* NULL */
#include <math.h>
#include "lualib.h"
#include "lua.h"
#ifndef PI
#define PI 3.14159265358979323846
#endif
#define TODEGREE(a) ((a)*180.0/PI)
#define TORAD(a) ((a)*PI/180.0)
static void math_abs (void)
{
double d = lua_check_number(1, "abs");
if (d < 0) d = -d;
lua_pushnumber (d);
}
static void math_sin (void)
{
double d = lua_check_number(1, "sin");
lua_pushnumber (sin(TORAD(d)));
}
static void math_cos (void)
{
double d = lua_check_number(1, "cos");
lua_pushnumber (cos(TORAD(d)));
}
static void math_tan (void)
{
double d = lua_check_number(1, "tan");
lua_pushnumber (tan(TORAD(d)));
}
static void math_asin (void)
{
double d = lua_check_number(1, "asin");
lua_pushnumber (TODEGREE(asin(d)));
}
static void math_acos (void)
{
double d = lua_check_number(1, "acos");
lua_pushnumber (TODEGREE(acos(d)));
}
static void math_atan (void)
{
double d = lua_check_number(1, "atan");
lua_pushnumber (TODEGREE(atan(d)));
}
static void math_atan2 (void)
{
double d1 = lua_check_number(1, "atan2");
double d2 = lua_check_number(2, "atan2");
lua_pushnumber (TODEGREE(atan2(d1, d2)));
}
static void math_ceil (void)
{
double d = lua_check_number(1, "ceil");
lua_pushnumber (ceil(d));
}
static void math_floor (void)
{
double d = lua_check_number(1, "floor");
lua_pushnumber (floor(d));
}
static void math_mod (void)
{
int d1 = (int)lua_check_number(1, "mod");
int d2 = (int)lua_check_number(2, "mod");
lua_pushnumber (d1%d2);
}
static void math_sqrt (void)
{
double d = lua_check_number(1, "sqrt");
lua_pushnumber (sqrt(d));
}
static int old_pow;
static void math_pow (void)
{
lua_Object o1 = lua_getparam (1);
lua_Object o2 = lua_getparam (2);
lua_Object op = lua_getparam(3);
if (!lua_isnumber(o1) || !lua_isnumber(o2) || *(lua_getstring(op)) != 'p')
{
lua_Object old = lua_getlocked(old_pow);
lua_pushobject(o1);
lua_pushobject(o2);
lua_pushobject(op);
if (lua_callfunction(old) != 0)
lua_error(NULL);
}
else
{
double d1 = lua_getnumber(o1);
double d2 = lua_getnumber(o2);
lua_pushnumber (pow(d1,d2));
}
}
static void math_min (void)
{
int i=1;
double dmin = lua_check_number(i, "min");
while (lua_getparam(++i) != LUA_NOOBJECT)
{
double d = lua_check_number(i, "min");
if (d < dmin) dmin = d;
}
lua_pushnumber (dmin);
}
static void math_max (void)
{
int i=1;
double dmax = lua_check_number(i, "max");
while (lua_getparam(++i) != LUA_NOOBJECT)
{
double d = lua_check_number(i, "max");
if (d > dmax) dmax = d;
}
lua_pushnumber (dmax);
}
static void math_log (void)
{
double d = lua_check_number(1, "log");
lua_pushnumber (log(d));
}
static void math_log10 (void)
{
double d = lua_check_number(1, "log10");
lua_pushnumber (log10(d));
}
static void math_exp (void)
{
double d = lua_check_number(1, "exp");
lua_pushnumber (exp(d));
}
static void math_deg (void)
{
float d = lua_check_number(1, "deg");
lua_pushnumber (d*180./PI);
}
static void math_rad (void)
{
float d = lua_check_number(1, "rad");
lua_pushnumber (d/180.*PI);
}
/*
** Open math library
*/
void mathlib_open (void)
{
lua_register ("abs", math_abs);
lua_register ("sin", math_sin);
lua_register ("cos", math_cos);
lua_register ("tan", math_tan);
lua_register ("asin", math_asin);
lua_register ("acos", math_acos);
lua_register ("atan", math_atan);
lua_register ("atan2", math_atan2);
lua_register ("ceil", math_ceil);
lua_register ("floor", math_floor);
lua_register ("mod", math_mod);
lua_register ("sqrt", math_sqrt);
lua_register ("min", math_min);
lua_register ("max", math_max);
lua_register ("log", math_log);
lua_register ("log10", math_log10);
lua_register ("exp", math_exp);
lua_register ("deg", math_deg);
lua_register ("rad", math_rad);
old_pow = lua_lockobject(lua_setfallback("arith", math_pow));
}

View File

@@ -1,13 +0,0 @@
/*
** Math library to LUA
** TeCGraf - PUC-Rio
** $Id: $
*/
#ifndef strlib_h
void mathlib_open (void);
#endif

1172
opcode.c

File diff suppressed because it is too large Load Diff

157
opcode.h
View File

@@ -1,157 +0,0 @@
/*
** TeCGraf - PUC-Rio
** $Id: opcode.h,v 3.13 1995/10/17 11:58:41 roberto Exp roberto $
*/
#ifndef opcode_h
#define opcode_h
#include "lua.h"
#include "types.h"
#include "tree.h"
#include "func.h"
#ifndef real
#define real float
#endif
#define FIELDS_PER_FLUSH 40
typedef enum
{
PUSHNIL,
PUSH0, PUSH1, PUSH2,
PUSHBYTE,
PUSHWORD,
PUSHFLOAT,
PUSHSTRING,
PUSHFUNCTION,
PUSHLOCAL0, PUSHLOCAL1, PUSHLOCAL2, PUSHLOCAL3, PUSHLOCAL4,
PUSHLOCAL5, PUSHLOCAL6, PUSHLOCAL7, PUSHLOCAL8, PUSHLOCAL9,
PUSHLOCAL,
PUSHGLOBAL,
PUSHINDEXED,
PUSHSELF,
STORELOCAL0, STORELOCAL1, STORELOCAL2, STORELOCAL3, STORELOCAL4,
STORELOCAL5, STORELOCAL6, STORELOCAL7, STORELOCAL8, STORELOCAL9,
STORELOCAL,
STOREGLOBAL,
STOREINDEXED0,
STOREINDEXED,
STORELIST0,
STORELIST,
STORERECORD,
ADJUST0,
ADJUST,
CREATEARRAY,
EQOP,
LTOP,
LEOP,
GTOP,
GEOP,
ADDOP,
SUBOP,
MULTOP,
DIVOP,
POWOP,
CONCOP,
MINUSOP,
NOTOP,
ONTJMP,
ONFJMP,
JMP,
UPJMP,
IFFJMP,
IFFUPJMP,
POP,
CALLFUNC,
RETCODE0,
RETCODE,
SETLINE
} OpCode;
#define MULT_RET 255
typedef void (*Cfunction) (void);
typedef int (*Input) (void);
typedef union
{
Cfunction f;
real n;
TaggedString *ts;
TFunc *tf;
struct Hash *a;
void *u;
int i;
} Value;
typedef struct Object
{
lua_Type tag;
Value value;
} Object;
typedef struct
{
Object object;
} Symbol;
/* Macros to access structure members */
#define tag(o) ((o)->tag)
#define nvalue(o) ((o)->value.n)
#define svalue(o) ((o)->value.ts->str)
#define tsvalue(o) ((o)->value.ts)
#define avalue(o) ((o)->value.a)
#define fvalue(o) ((o)->value.f)
#define uvalue(o) ((o)->value.u)
/* Macros to access symbol table */
#define s_object(i) (lua_table[i].object)
#define s_tag(i) (tag(&s_object(i)))
#define s_nvalue(i) (nvalue(&s_object(i)))
#define s_svalue(i) (svalue(&s_object(i)))
#define s_avalue(i) (avalue(&s_object(i)))
#define s_fvalue(i) (fvalue(&s_object(i)))
#define s_uvalue(i) (uvalue(&s_object(i)))
typedef union
{
struct {char c1; char c2;} m;
Word w;
} CodeWord;
#define get_word(code,pc) {code.m.c1 = *pc++; code.m.c2 = *pc++;}
typedef union
{
struct {char c1; char c2; char c3; char c4;} m;
float f;
} CodeFloat;
#define get_float(code,pc) {code.m.c1 = *pc++; code.m.c2 = *pc++;\
code.m.c3 = *pc++; code.m.c4 = *pc++;}
typedef union
{
struct {char c1; char c2; char c3; char c4;} m;
TFunc *tf;
} CodeCode;
#define get_code(code,pc) {code.m.c1 = *pc++; code.m.c2 = *pc++;\
code.m.c3 = *pc++; code.m.c4 = *pc++;}
/* Exported functions */
char *lua_strdup (char *l);
void lua_setinput (Input fn); /* from "lex.c" module */
char *lua_lasttext (void); /* from "lex.c" module */
int yylex (void); /* from "lex.c" module */
void lua_parse (TFunc *tf); /* from "lua.stx" module */
void luaI_codedebugline (int line); /* from "lua.stx" module */
void lua_travstack (int (*fn)(Object *));
Object *luaI_Address (lua_Object o);
void luaI_pushobject (Object *o);
void luaI_gcFB (Object *o);
#endif

192
strlib.c
View File

@@ -1,192 +0,0 @@
/*
** strlib.c
** String library to LUA
*/
char *rcs_strlib="$Id: strlib.c,v 1.13 1995/10/09 12:49:21 roberto Exp roberto $";
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "lua.h"
#include "lualib.h"
void lua_arg_error(char *funcname)
{
char buff[100];
sprintf(buff, "incorrect arguments to function `%s'", funcname);
lua_error(buff);
}
char *lua_check_string (int numArg, char *funcname)
{
lua_Object o = lua_getparam(numArg);
if (!(lua_isstring(o) || lua_isnumber(o)))
lua_arg_error(funcname);
return lua_getstring(o);
}
float lua_check_number (int numArg, char *funcname)
{
lua_Object o = lua_getparam(numArg);
if (!lua_isnumber(o))
lua_arg_error(funcname);
return lua_getnumber(o);
}
static char *newstring (char *s)
{
char *ns = (char *)malloc(strlen(s)+1);
if (ns == 0)
lua_error("not enough memory for new string");
strcpy(ns, s);
return ns;
}
/*
** Return the position of the first caracter of a substring into a string
** LUA interface:
** n = strfind (string, substring, init, end)
*/
static void str_find (void)
{
char *s1 = lua_check_string(1, "strfind");
char *s2 = lua_check_string(2, "strfind");
int init = (lua_getparam(3) == LUA_NOOBJECT) ? 0 :
(int)lua_check_number(3, "strfind")-1;
char *f = strstr(s1+init,s2);
if (f != NULL)
{
int pos = f-s1+1;
if (lua_getparam (4) == LUA_NOOBJECT)
lua_pushnumber (pos);
else if ((int)lua_check_number(4, "strfind") >= pos+strlen(s2)-1)
lua_pushnumber (pos);
else
lua_pushnil();
}
else
lua_pushnil();
}
/*
** Return the string length
** LUA interface:
** n = strlen (string)
*/
static void str_len (void)
{
char *s = lua_check_string(1, "strlen");
lua_pushnumber(strlen(s));
}
/*
** Return the substring of a string, from start to end
** LUA interface:
** substring = strsub (string, start, end)
*/
static void str_sub (void)
{
char *s = lua_check_string(1, "strsub");
int start = (int)lua_check_number(2, "strsub");
int end = (lua_getparam(3) == LUA_NOOBJECT) ? strlen(s) :
(int)lua_check_number(3, "strsub");
if (end < start || start < 1 || end > strlen(s))
lua_pushliteral("");
else
{
char temp = s[end];
s[end] = 0;
lua_pushstring (&s[start-1]);
s[end] = temp;
}
}
/*
** Convert a string according to given function.
*/
typedef int (*strfunc)(int s);
static void str_apply (strfunc f, char *funcname)
{
char *s, *c;
c = s = newstring(lua_check_string(1, funcname));
while (*c != 0)
{
*c = f(*c);
c++;
}
lua_pushstring(s);
free(s);
}
/*
** Convert a string to lower case.
** LUA interface:
** lowercase = strlower (string)
*/
static void str_lower (void)
{
str_apply(tolower, "strlower");
}
/*
** Convert a string to upper case.
** LUA interface:
** uppercase = strupper (string)
*/
static void str_upper (void)
{
str_apply(toupper, "strupper");
}
/*
** get ascii value of a character in a string
*/
static void str_ascii (void)
{
char *s = lua_check_string(1, "ascii");
lua_Object o2 = lua_getparam(2);
int pos;
pos = (o2 == LUA_NOOBJECT) ? 0 : (int)lua_check_number(2, "ascii")-1;
if (pos<0 || pos>=strlen(s))
lua_arg_error("ascii");
lua_pushnumber(s[pos]);
}
/*
** converts one or more integers to chars in a string
*/
#define maxparams 50
static void str_int2str (void)
{
char s[maxparams+1];
int i = 0;
while (lua_getparam(++i) != LUA_NOOBJECT)
{
if (i > maxparams)
lua_error("too many parameters to function `int2str'");
s[i-1] = (int)lua_check_number(i, "int2str");
}
s[i-1] = 0;
lua_pushstring(s);
}
/*
** Open string library
*/
void strlib_open (void)
{
lua_register ("strfind", str_find);
lua_register ("strlen", str_len);
lua_register ("strsub", str_sub);
lua_register ("strlower", str_lower);
lua_register ("strupper", str_upper);
lua_register ("ascii", str_ascii);
lua_register ("int2str", str_int2str);
}

View File

@@ -1,13 +0,0 @@
/*
** String library to LUA
** TeCGraf - PUC-Rio
** $Id: $
*/
#ifndef strlib_h
void strlib_open (void);
#endif

282
table.c
View File

@@ -1,282 +0,0 @@
/*
** table.c
** Module to control static tables
*/
char *rcs_table="$Id: table.c,v 2.37 1995/10/26 14:21:56 roberto Exp roberto $";
/*#include <string.h>*/
#include "mem.h"
#include "opcode.h"
#include "tree.h"
#include "hash.h"
#include "table.h"
#include "inout.h"
#include "lua.h"
#include "fallback.h"
#include "luadebug.h"
#define BUFFER_BLOCK 256
Symbol *lua_table = NULL;
static Word lua_ntable = 0;
static Long lua_maxsymbol = 0;
TaggedString **lua_constant = NULL;
static Word lua_nconstant = 0;
static Long lua_maxconstant = 0;
#define GARBAGE_BLOCK 1024
#define MIN_GARBAGE_BLOCK (GARBAGE_BLOCK/2)
static void lua_nextvar (void);
static void setglobal (void);
static void getglobal (void);
/*
** Initialise symbol table with internal functions
*/
static void lua_initsymbol (void)
{
Word n;
lua_maxsymbol = BUFFER_BLOCK;
lua_table = newvector(lua_maxsymbol, Symbol);
n = luaI_findsymbolbyname("next");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_next;
n = luaI_findsymbolbyname("dofile");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_internaldofile;
n = luaI_findsymbolbyname("setglobal");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = setglobal;
n = luaI_findsymbolbyname("getglobal");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = getglobal;
n = luaI_findsymbolbyname("nextvar");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_nextvar;
n = luaI_findsymbolbyname("type");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = luaI_type;
n = luaI_findsymbolbyname("tonumber");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_obj2number;
n = luaI_findsymbolbyname("print");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_print;
n = luaI_findsymbolbyname("dostring");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = lua_internaldostring;
n = luaI_findsymbolbyname("setfallback");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = luaI_setfallback;
n = luaI_findsymbolbyname("error");
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = luaI_error;
}
/*
** Initialise constant table with pre-defined constants
*/
void lua_initconstant (void)
{
lua_maxconstant = BUFFER_BLOCK;
lua_constant = newvector(lua_maxconstant, TaggedString *);
}
/*
** Given a name, search it at symbol table and return its index. If not
** found, allocate it.
*/
Word luaI_findsymbol (TreeNode *t)
{
if (lua_table == NULL)
lua_initsymbol();
if (t->varindex == NOT_USED)
{
if (lua_ntable == lua_maxsymbol)
{
if (lua_maxsymbol >= MAX_WORD)
lua_error("symbol table overflow");
lua_maxsymbol *= 2;
if (lua_maxsymbol >= MAX_WORD)
lua_maxsymbol = MAX_WORD;
lua_table = growvector(lua_table, lua_maxsymbol, Symbol);
}
t->varindex = lua_ntable;
s_tag(lua_ntable) = LUA_T_NIL;
lua_ntable++;
}
return t->varindex;
}
Word luaI_findsymbolbyname (char *name)
{
return luaI_findsymbol(lua_constcreate(name));
}
/*
** Given a tree node, check it is has a correspondent constant index. If not,
** allocate it.
*/
Word luaI_findconstant (TreeNode *t)
{
if (lua_constant == NULL)
lua_initconstant();
if (t->constindex == NOT_USED)
{
if (lua_nconstant == lua_maxconstant)
{
if (lua_maxconstant >= MAX_WORD)
lua_error("constant table overflow");
lua_maxconstant *= 2;
if (lua_maxconstant >= MAX_WORD)
lua_maxconstant = MAX_WORD;
lua_constant = growvector(lua_constant, lua_maxconstant, TaggedString *);
}
t->constindex = lua_nconstant;
lua_constant[lua_nconstant] = &(t->ts);
lua_nconstant++;
}
return t->constindex;
}
Word luaI_findconstantbyname (char *name)
{
return luaI_findconstant(lua_constcreate(name));
}
/*
** Traverse symbol table objects
*/
static char *lua_travsymbol (int (*fn)(Object *))
{
Word i;
for (i=0; i<lua_ntable; i++)
if (fn(&s_object(i)))
return luaI_nodebysymbol(i)->ts.str;
return NULL;
}
/*
** Mark an object if it is a string or a unmarked array.
*/
int lua_markobject (Object *o)
{
if (tag(o) == LUA_T_STRING && !tsvalue(o)->marked)
tsvalue(o)->marked = 1;
else if (tag(o) == LUA_T_ARRAY)
lua_hashmark (avalue(o));
else if ((o->tag == LUA_T_FUNCTION || o->tag == LUA_T_MARK)
&& !o->value.tf->marked)
o->value.tf->marked = 1;
return 0;
}
/*
** Garbage collection.
** Delete all unused strings and arrays.
*/
void lua_pack (void)
{
static Long block = GARBAGE_BLOCK; /* when garbage collector will be called */
static Long nentity = 0; /* counter of new entities (strings and arrays) */
Long recovered = 0;
if (nentity++ < block) return;
lua_travstack(lua_markobject); /* mark stack objects */
lua_travsymbol(lua_markobject); /* mark symbol table objects */
luaI_travlock(lua_markobject); /* mark locked objects */
luaI_travfallbacks(lua_markobject); /* mark fallbacks */
recovered += lua_strcollector();
recovered += lua_hashcollector();
recovered += luaI_funccollector();
nentity = 0; /* reset counter */
block=(16*block-7*recovered)/12; /* adapt block size */
if (block < MIN_GARBAGE_BLOCK) block = MIN_GARBAGE_BLOCK;
}
/*
** Internal function: return next global variable
*/
static void lua_nextvar (void)
{
Word next;
lua_Object o = lua_getparam(1);
if (o == LUA_NOOBJECT)
lua_error("too few arguments to function `nextvar'");
if (lua_getparam(2) != LUA_NOOBJECT)
lua_error("too many arguments to function `nextvar'");
if (lua_isnil(o))
next = 0;
else if (!lua_isstring(o))
{
lua_error("incorrect argument to function `nextvar'");
return; /* to avoid warnings */
}
else
next = luaI_findsymbolbyname(lua_getstring(o)) + 1;
while (next < lua_ntable && s_tag(next) == LUA_T_NIL) next++;
if (next >= lua_ntable)
{
lua_pushnil();
lua_pushnil();
}
else
{
TreeNode *t = luaI_nodebysymbol(next);
Object name;
tag(&name) = LUA_T_STRING;
tsvalue(&name) = &(t->ts);
luaI_pushobject(&name);
luaI_pushobject(&s_object(next));
}
}
static void setglobal (void)
{
lua_Object name = lua_getparam(1);
lua_Object value = lua_getparam(2);
if (!lua_isstring(name))
lua_error("incorrect argument to function `setglobal'");
lua_pushobject(value);
lua_storeglobal(lua_getstring(name));
}
static void getglobal (void)
{
lua_Object name = lua_getparam(1);
if (!lua_isstring(name))
lua_error("incorrect argument to function `getglobal'");
lua_pushobject(lua_getglobal(lua_getstring(name)));
}
static Object *functofind;
static int checkfunc (Object *o)
{
if (o->tag == LUA_T_FUNCTION)
return
((functofind->tag == LUA_T_FUNCTION || functofind->tag == LUA_T_MARK)
&& (functofind->value.tf == o->value.tf));
if (o->tag == LUA_T_CFUNCTION)
return
((functofind->tag == LUA_T_CFUNCTION || functofind->tag == LUA_T_CMARK)
&& (functofind->value.f == o->value.f));
return 0;
}
char *getobjname (lua_Object o, char **name)
{ /* try to find a name for given function */
functofind = luaI_Address(o);
if ((*name = luaI_travfallbacks(checkfunc)) != NULL)
return "fallback";
else if ((*name = lua_travsymbol(checkfunc)) != NULL)
return "global";
else return "";
}

29
table.h
View File

@@ -1,29 +0,0 @@
/*
** Module to control static tables
** TeCGraf - PUC-Rio
** $Id: table.h,v 2.12 1995/10/17 11:58:41 roberto Exp roberto $
*/
#ifndef table_h
#define table_h
#include "tree.h"
#include "opcode.h"
extern Symbol *lua_table;
extern TaggedString **lua_constant;
extern char *lua_file[];
extern int lua_nfile;
void lua_initconstant (void);
Word luaI_findsymbolbyname (char *name);
Word luaI_findsymbol (TreeNode *t);
Word luaI_findconstant (TreeNode *t);
Word luaI_findconstantbyname (char *name);
int lua_markobject (Object *o);
void lua_pack (void);
#endif

123
tree.c
View File

@@ -1,123 +0,0 @@
/*
** tree.c
** TecCGraf - PUC-Rio
*/
char *rcs_tree="$Id: tree.c,v 1.13 1995/01/12 14:19:04 roberto Exp roberto $";
#include <string.h>
#include "mem.h"
#include "lua.h"
#include "tree.h"
#include "table.h"
#define lua_strcmp(a,b) (a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b)))
typedef struct StringNode {
struct StringNode *next;
TaggedString ts;
} StringNode;
static StringNode *string_root = NULL;
static TreeNode *constant_root = NULL;
/*
** Insert a new constant/variable at the tree.
*/
static TreeNode *tree_create (TreeNode **node, char *str)
{
if (*node == NULL)
{
*node = (TreeNode *) luaI_malloc(sizeof(TreeNode)+strlen(str));
(*node)->left = (*node)->right = NULL;
strcpy((*node)->ts.str, str);
(*node)->ts.marked = 0;
(*node)->ts.hash = 0;
(*node)->varindex = (*node)->constindex = NOT_USED;
return *node;
}
else
{
int c = lua_strcmp(str, (*node)->ts.str);
if (c < 0)
return tree_create(&(*node)->left, str);
else if (c > 0)
return tree_create(&(*node)->right, str);
else
return *node;
}
}
TaggedString *lua_createstring (char *str)
{
StringNode *newString;
if (str == NULL) return NULL;
lua_pack();
newString = (StringNode *)luaI_malloc(sizeof(StringNode)+strlen(str));
newString->ts.marked = 0;
newString->ts.hash = 0;
strcpy(newString->ts.str, str);
newString->next = string_root;
string_root = newString;
return &(newString->ts);
}
TreeNode *lua_constcreate (char *str)
{
return tree_create(&constant_root, str);
}
/*
** Garbage collection function.
** This function traverse the string list freeing unindexed strings
*/
Long lua_strcollector (void)
{
StringNode *curr = string_root, *prev = NULL;
Long counter = 0;
while (curr)
{
StringNode *next = curr->next;
if (!curr->ts.marked)
{
if (prev == NULL) string_root = next;
else prev->next = next;
luaI_free(curr);
++counter;
}
else
{
curr->ts.marked = 0;
prev = curr;
}
curr = next;
}
return counter;
}
/*
** Traverse the constant tree looking for a specific symbol number
*/
static TreeNode *nodebysymbol (TreeNode *root, Word symbol)
{
TreeNode *t;
if (root == NULL) return NULL;
if (root->varindex == symbol) return root;
t = nodebysymbol(root->left, symbol);
if (t) return t;
return nodebysymbol(root->right, symbol);
}
TreeNode *luaI_nodebysymbol (Word symbol)
{
return nodebysymbol(constant_root, symbol);
}

37
tree.h
View File

@@ -1,37 +0,0 @@
/*
** tree.h
** TecCGraf - PUC-Rio
** $Id: tree.h,v 1.9 1995/01/12 14:19:04 roberto Exp roberto $
*/
#ifndef tree_h
#define tree_h
#include "types.h"
#define NOT_USED 0xFFFE
typedef struct TaggedString
{
unsigned long hash; /* 0 if not initialized */
char marked; /* for garbage collection */
char str[1]; /* \0 byte already reserved */
} TaggedString;
typedef struct TreeNode
{
struct TreeNode *right;
struct TreeNode *left;
unsigned short varindex; /* != NOT_USED if this is a symbol */
unsigned short constindex; /* != NOT_USED if this is a constant */
TaggedString ts;
} TreeNode;
TaggedString *lua_createstring (char *str);
TreeNode *lua_constcreate (char *str);
Long lua_strcollector (void);
TreeNode *luaI_nodebysymbol (Word symbol);
#endif

31
types.h
View File

@@ -1,31 +0,0 @@
/*
** TeCGraf - PUC-Rio
** $Id: types.h,v 1.2 1994/12/27 20:41:47 celes Exp roberto $
*/
#ifndef types_h
#define types_h
#include <limits.h>
#ifndef real
#define real float
#endif
typedef int Bool; /* boolean values */
#define Byte lua_Byte /* some systems have Byte as a predefined type */
typedef unsigned char Byte; /* unsigned 8 bits */
#define Word lua_Word /* some systems have Word as a predefined type */
typedef unsigned short Word; /* unsigned 16 bits */
#define MAX_WORD (USHRT_MAX-2) /* maximum value of a word (-2 for safety) */
#define MAX_INT (INT_MAX-2) /* maximum value of a int (-2 for safety) */
#define Long lua_Long /* some systems have Long as a predefined type */
typedef signed long Long; /* 32 bits */
typedef unsigned int IntPoint; /* unsigned with same size as a pointer (for hashing) */
#endif

36
ugly.h
View File

@@ -1,36 +0,0 @@
/*
** ugly.h
** TecCGraf - PUC-Rio
** $Id: $
*/
#ifndef ugly_h
#define ugly_h
/* This enum must have the same order of the array 'reserved' in lex.c */
enum {
U_and=128,
U_do,
U_else,
U_elseif,
U_end,
U_function,
U_if,
U_local,
U_nil,
U_not,
U_or,
U_repeat,
U_return,
U_then,
U_until,
U_while,
U_eq = '='+128,
U_le = '<'+128,
U_ge = '>'+128,
U_ne = '~'+128,
U_sc = '.'+128
};
#endif