Compare commits

..

259 Commits

Author SHA1 Message Date
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
34 changed files with 5078 additions and 3286 deletions

81
auxlib.c Normal file
View File

@@ -0,0 +1,81 @@
char *rcs_auxlib="$Id: auxlib.c,v 1.3 1997/04/06 14:08:08 roberto Exp roberto $";
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "lua.h"
#include "auxlib.h"
#include "luadebug.h"
int luaI_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_arg_check(int cond, int numarg, char *extramsg)
{
char *funcname;
lua_getobjname(lua_stackedfunction(0), &funcname);
if (funcname == NULL)
funcname = "???";
if (!cond) {
if (extramsg == NULL)
luaL_verror("bad argument #%d to function `%s'", numarg, funcname);
else
luaL_verror("bad argument #%d to function `%s' (%s)",
numarg, funcname, extramsg);
}
}
char *luaL_check_string (int numArg)
{
lua_Object o = lua_getparam(numArg);
luaL_arg_check(lua_isstring(o), numArg, "string expected");
return lua_getstring(o);
}
char *luaL_opt_string (int numArg, char *def)
{
return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
luaL_check_string(numArg);
}
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);
}
void luaL_openlib (struct luaL_reg *l, int n)
{
int i;
for (i=0; i<n; i++)
lua_register(l[i].name, l[i].func);
}
void luaL_verror (char *fmt, ...)
{
char buff[1000];
va_list argp;
va_start(argp, fmt);
vsprintf(buff, fmt, argp);
va_end(argp);
lua_error(buff);
}

30
auxlib.h Normal file
View File

@@ -0,0 +1,30 @@
/*
** $Id: auxlib.h,v 1.2 1997/04/06 14:08:08 roberto Exp roberto $
*/
#ifndef auxlib_h
#define auxlib_h
#include "lua.h"
struct luaL_reg {
char *name;
lua_CFunction func;
};
void luaL_openlib (struct luaL_reg *l, int n);
void luaL_arg_check(int cond, int numarg, char *extramsg);
char *luaL_check_string (int numArg);
char *luaL_opt_string (int numArg, char *def);
double luaL_check_number (int numArg);
double luaL_opt_number (int numArg, double def);
void luaL_verror (char *fmt, ...);
/* -- private part (only for Lua modules */
int luaI_findstring (char *name, char *list[]);
#endif

View File

@@ -3,64 +3,278 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_fallback="$Id: fallback.c,v 1.16 1995/10/17 11:52:38 roberto Exp roberto $"; char *rcs_fallback="$Id: fallback.c,v 2.3 1997/04/06 14:08:08 roberto Exp roberto $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "mem.h" #include "auxlib.h"
#include "luamem.h"
#include "fallback.h" #include "fallback.h"
#include "opcode.h" #include "opcode.h"
#include "lua.h" #include "lua.h"
#include "table.h"
#include "tree.h"
#include "hash.h"
static void errorFB (void);
static void indexFB (void); /* -------------------------------------------
static void gettableFB (void); ** Reference routines
static void arithFB (void); */
static void concatFB (void);
static void orderFB (void); static struct ref {
static void GDFB (void); TObject o;
static void funcFB (void); enum {LOCK, HOLD, FREE, COLLECTED} status;
} *refArray = NULL;
static int refSize = 0;
int luaI_ref (TObject *object, int lock)
{
int i;
int oldSize;
if (ttype(object) == LUA_T_NIL)
return -1; /* special ref for nil */
for (i=0; i<refSize; i++)
if (refArray[i].status == FREE)
goto found;
/* no more empty spaces */
oldSize = refSize;
refSize = growvector(&refArray, refSize, struct ref, refEM, MAX_WORD);
for (i=oldSize; i<refSize; i++)
refArray[i].status = FREE;
i = oldSize;
found:
refArray[i].o = *object;
refArray[i].status = lock ? LOCK : HOLD;
return i;
}
void lua_unref (int ref)
{
if (ref >= 0 && ref < refSize)
refArray[ref].status = FREE;
}
TObject *luaI_getref (int ref)
{
static TObject nul = {LUA_T_NIL, {0}};
if (ref == -1)
return &nul;
if (ref >= 0 && ref < refSize &&
(refArray[ref].status == LOCK || refArray[ref].status == HOLD))
return &refArray[ref].o;
else
return NULL;
}
void luaI_travlock (int (*fn)(TObject *))
{
int i;
for (i=0; i<refSize; i++)
if (refArray[i].status == LOCK)
fn(&refArray[i].o);
}
void luaI_invalidaterefs (void)
{
int i;
for (i=0; i<refSize; i++)
if (refArray[i].status == HOLD && !luaI_ismarked(&refArray[i].o))
refArray[i].status = COLLECTED;
}
/* -------------------------------------------
* Internal Methods
*/
char *luaI_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 = luaI_findstring(name, list);
if (e < 0)
luaL_verror("`%s' is not a valid event name", name);
return e;
}
static struct IM {
TObject int_method[IM_N];
} *luaI_IMtable = NULL;
static int IMtable_size = 0;
static int last_tag = LUA_T_NIL; /* ORDER LUA_T */
static char validevents[NUM_TYPES][IM_N] = { /* ORDER LUA_T, ORDER IM */
{1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_USERDATA */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_LINE */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_CMARK */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_MARK */
{1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CFUNCTION */
{1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_FUNCTION */
{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */
{1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */
{1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, /* LUA_T_NUMBER */
{0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0} /* LUA_T_NIL */
};
static int validevent (lua_Type t, int e)
{ /* ORDER LUA_T */
return (t < LUA_T_NIL) ? 1 : validevents[-t][e];
}
static void init_entry (int tag)
{
int i;
for (i=0; i<IM_N; i++)
luaI_IMtable[-tag].int_method[i].ttype = LUA_T_NIL;
}
void luaI_initfallbacks (void)
{
if (luaI_IMtable == NULL) {
int i;
IMtable_size = NUM_TYPES+10;
luaI_IMtable = newvector(IMtable_size, struct IM);
for (i=LUA_T_NIL; i<=LUA_T_USERDATA; i++)
init_entry(i);
}
}
int lua_newtag (void)
{
--last_tag;
if ((-last_tag) >= IMtable_size) {
luaI_initfallbacks();
IMtable_size = growvector(&luaI_IMtable, IMtable_size,
struct IM, memEM, MAX_INT);
}
init_entry(last_tag);
return last_tag;
}
static void checktag (int tag)
{
if (!(last_tag <= tag && tag <= 0))
luaL_verror("%d is not a valid tag", tag);
}
void luaI_realtag (int tag)
{
if (!(last_tag <= tag && tag < LUA_T_NIL))
luaL_verror("tag %d is not result of `newtag'", tag);
}
void luaI_settag (int tag, TObject *o)
{
luaI_realtag(tag);
switch (ttype(o)) {
case LUA_T_ARRAY:
o->value.a->htag = tag;
break;
default:
luaL_verror("cannot change the tag of a %s", luaI_typenames[-ttype(o)]);
}
}
int luaI_tag (TObject *o)
{
lua_Type t = ttype(o);
if (t == LUA_T_USERDATA)
return o->value.ts->tag;
else if (t == LUA_T_ARRAY)
return o->value.a->htag;
else return t;
}
TObject *luaI_getim (int tag, IMS event)
{
if (tag > LUA_T_USERDATA)
tag = LUA_T_USERDATA; /* default for non-registered tags */
return &luaI_IMtable[-tag].int_method[event];
}
void luaI_gettagmethod (void)
{
int t = (int)luaL_check_number(1);
int e = luaI_checkevent(luaL_check_string(2), luaI_eventname);
checktag(t);
if (validevent(t, e))
luaI_pushobject(&luaI_IMtable[-t].int_method[e]);
}
void luaI_settagmethod (void)
{
int t = (int)luaL_check_number(1);
int e = luaI_checkevent(luaL_check_string(2), luaI_eventname);
lua_Object func = lua_getparam(3);
checktag(t);
if (!validevent(t, e))
luaL_verror("cannot change internal method `%s' for tag %d",
luaI_eventname[e], t);
luaL_arg_check(lua_isnil(func) || lua_isfunction(func),
3, "function expected");
luaI_pushobject(&luaI_IMtable[-t].int_method[e]);
luaI_IMtable[-t].int_method[e] = *luaI_Address(func);
}
static TObject errorim = {LUA_T_NIL, {NULL}};
TObject *luaI_geterrorim (void)
{
return &errorim;
}
void luaI_seterrormethod (void)
{
lua_Object func = lua_getparam(1);
luaL_arg_check(lua_isnil(func) || lua_isfunction(func),
1, "function expected");
luaI_pushobject(&errorim);
errorim = *luaI_Address(func);
}
char *luaI_travfallbacks (int (*fn)(TObject *))
{
int e;
if (fn(&errorim))
return "error";
for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */
int t;
for (t=0; t>=last_tag; t--)
if (fn(&luaI_IMtable[-t].int_method[e]))
return luaI_eventname[e];
}
return NULL;
}
/* /*
** Warning: This list must be in the same order as the #define's * ===================================================================
* compatibility with old fallback system
*/ */
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) static void errorFB (void)
@@ -73,105 +287,75 @@ static void errorFB (void)
} }
static void indexFB (void) static void nilFB (void) { }
{
lua_pushnil();
}
static void gettableFB (void) static void typeFB (void)
{ {
lua_error("indexed expression not a table"); lua_error("unexpected type");
}
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) static void fillvalids (IMS e, TObject *func)
{ {
lua_error("unexpected type at comparison"); int t;
for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++)
if (validevent(t, e))
luaI_IMtable[-t].int_method[e] = *func;
} }
static void GDFB (void) { } void luaI_setfallback (void)
static void funcFB (void)
{ {
lua_error("call expression not a function"); 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);
** Lock routines luaI_initfallbacks();
*/ luaL_arg_check(lua_isfunction(func), 2, "function expected");
switch (luaI_findstring(name, oldnames)) {
static Object *lockArray = NULL; case 0: /* old error fallback */
static Word lockSize = 0; oldfunc = errorim;
errorim = *luaI_Address(func);
int luaI_lock (Object *object) replace = errorFB;
{ break;
Word i; case 1: /* old getglobal fallback */
Word oldSize; oldfunc = luaI_IMtable[-LUA_T_NIL].int_method[IM_GETGLOBAL];
if (tag(object) == LUA_T_NIL) luaI_IMtable[-LUA_T_NIL].int_method[IM_GETGLOBAL] = *luaI_Address(func);
return -1; replace = nilFB;
for (i=0; i<lockSize; i++) break;
if (tag(&lockArray[i]) == LUA_T_NIL) case 2: { /* old arith fallback */
{ int i;
lockArray[i] = *object; oldfunc = luaI_IMtable[-LUA_T_USERDATA].int_method[IM_POW];
return i; for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */
fillvalids(i, luaI_Address(func));
replace = typeFB;
break;
}
case 3: { /* old order fallback */
int i;
oldfunc = luaI_IMtable[-LUA_T_USERDATA].int_method[IM_LT];
for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */
fillvalids(i, luaI_Address(func));
replace = typeFB;
break;
}
default: {
int e;
if ((e = luaI_findstring(name, luaI_eventname)) >= 0) {
oldfunc = luaI_IMtable[-LUA_T_USERDATA].int_method[e];
fillvalids(e, luaI_Address(func));
replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB;
}
else {
luaL_verror("`%s' is not a valid fallback name", name);
replace = NULL; /* to avoid warnings */
}
} }
/* no more empty spaces */
oldSize = lockSize;
if (lockArray == NULL)
{
lockSize = 10;
lockArray = newvector(lockSize, Object);
} }
if (oldfunc.ttype != LUA_T_NIL)
luaI_pushobject(&oldfunc);
else else
{ lua_pushcfunction(replace);
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 +1,60 @@
/* /*
** $Id: fallback.h,v 1.9 1995/10/09 13:14:29 roberto Exp roberto $ ** $Id: fallback.h,v 1.21 1997/04/02 23:04:12 roberto Exp roberto $
*/ */
#ifndef fallback_h #ifndef fallback_h
#define fallback_h #define fallback_h
#include "lua.h"
#include "opcode.h" #include "opcode.h"
extern struct FB { /*
char *kind; * WARNING: if you change the order of this enumeration,
Object function; * grep "ORDER IM"
int nParams; */
int nResults; typedef enum {
} luaI_fallBacks[]; 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
extern char *luaI_eventname[];
#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); void luaI_setfallback (void);
int luaI_lock (Object *object); int luaI_ref (TObject *object, int lock);
Object *luaI_getlocked (int ref); TObject *luaI_getref (int ref);
void luaI_travlock (int (*fn)(Object *)); void luaI_travlock (int (*fn)(TObject *));
char *luaI_travfallbacks (int (*fn)(Object *)); void luaI_invalidaterefs (void);
char *luaI_travfallbacks (int (*fn)(TObject *));
void luaI_settag (int tag, TObject *o);
void luaI_realtag (int tag);
TObject *luaI_getim (int tag, IMS event);
#define luaI_getimbyObj(o,e) (luaI_getim(luaI_tag(o),(e)))
TObject *luaI_geterrorim (void);
int luaI_tag (TObject *o);
void luaI_settagmethod (void);
void luaI_gettagmethod (void);
void luaI_seterrormethod (void);
void luaI_initfallbacks (void);
#endif #endif

93
func.c
View File

@@ -1,13 +1,31 @@
#include <stdio.h> #include <string.h>
#include "luadebug.h" #include "luadebug.h"
#include "table.h" #include "table.h"
#include "mem.h" #include "luamem.h"
#include "func.h" #include "func.h"
#include "opcode.h" #include "opcode.h"
static TFunc *function_root = NULL;
static TFunc *function_root = NULL;
static LocVar *currvars = NULL;
static int numcurrvars = 0;
static int maxcurrvars = 0;
/*
** Initialize TFunc struct
*/
void luaI_initTFunc (TFunc *f)
{
f->next = NULL;
f->marked = 0;
f->size = 0;
f->code = NULL;
f->lineDefined = 0;
f->fileName = NULL;
f->locvars = NULL;
}
/* /*
** Insert function in list for GC ** Insert function in list for GC
@@ -24,9 +42,10 @@ void luaI_insertfunction (TFunc *f)
/* /*
** Free function ** Free function
*/ */
static void freefunc (TFunc *f) void luaI_freefunc (TFunc *f)
{ {
luaI_free (f->code); luaI_free (f->code);
luaI_free (f->locvars);
luaI_free (f); luaI_free (f);
} }
@@ -48,7 +67,7 @@ Long luaI_funccollector (void)
function_root = next; function_root = next;
else else
prev->next = next; prev->next = next;
freefunc (curr); luaI_freefunc (curr);
++counter; ++counter;
} }
else else
@@ -64,16 +83,74 @@ Long luaI_funccollector (void)
void lua_funcinfo (lua_Object func, char **filename, int *linedefined) void lua_funcinfo (lua_Object func, char **filename, int *linedefined)
{ {
Object *f = luaI_Address(func); TObject *f = luaI_Address(func);
if (f->tag == LUA_T_MARK || f->tag == LUA_T_FUNCTION) if (f->ttype == LUA_T_MARK || f->ttype == LUA_T_FUNCTION)
{ {
*filename = f->value.tf->fileName; *filename = f->value.tf->fileName;
*linedefined = f->value.tf->lineDefined; *linedefined = f->value.tf->lineDefined;
} }
else if (f->tag == LUA_T_CMARK || f->tag == LUA_T_CFUNCTION) else if (f->ttype == LUA_T_CMARK || f->ttype == LUA_T_CFUNCTION)
{ {
*filename = "(C)"; *filename = "(C)";
*linedefined = -1; *linedefined = -1;
} }
} }
/*
** Stores information to know that variable has been declared in given line
*/
void luaI_registerlocalvar (TaggedString *varname, int line)
{
if (numcurrvars >= maxcurrvars)
maxcurrvars = growvector(&currvars, maxcurrvars, LocVar, "", MAX_WORD);
currvars[numcurrvars].varname = varname;
currvars[numcurrvars].line = line;
numcurrvars++;
}
/*
** Stores information to know that variable has been out of scope in given line
*/
void luaI_unregisterlocalvar (int line)
{
luaI_registerlocalvar(NULL, line);
}
/*
** Copies "currvars" into a new area and store it in function header.
** The values (varname = NULL, line = -1) signal the end of vector.
*/
void luaI_closelocalvars (TFunc *func)
{
func->locvars = newvector (numcurrvars+1, LocVar);
memcpy (func->locvars, currvars, numcurrvars*sizeof(LocVar));
func->locvars[numcurrvars].varname = NULL;
func->locvars[numcurrvars].line = -1;
numcurrvars = 0; /* prepares for next function */
}
/*
** Look for n-esim local variable at line "line" in function "func".
** Returns NULL if not found.
*/
char *luaI_getlocalname (TFunc *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;
}

24
func.h
View File

@@ -1,24 +1,44 @@
/*
** $Id: func.h,v 1.7 1996/03/08 12:04:04 roberto Exp roberto $
*/
#ifndef func_h #ifndef func_h
#define func_h #define func_h
#include "types.h" #include "types.h"
#include "lua.h" #include "lua.h"
#include "tree.h"
typedef struct LocVar
{
TaggedString *varname; /* NULL signals end of scope */
int line;
} LocVar;
/* /*
** Header para funcoes. ** Function Headers
*/ */
typedef struct TFunc typedef struct TFunc
{ {
struct TFunc *next; struct TFunc *next;
char marked; int marked;
int size; int size;
Byte *code; Byte *code;
int lineDefined; int lineDefined;
char *fileName; char *fileName;
LocVar *locvars;
} TFunc; } TFunc;
Long luaI_funccollector (void); Long luaI_funccollector (void);
void luaI_insertfunction (TFunc *f); void luaI_insertfunction (TFunc *f);
void luaI_initTFunc (TFunc *f);
void luaI_freefunc (TFunc *f);
void luaI_registerlocalvar (TaggedString *varname, int line);
void luaI_unregisterlocalvar (int line);
void luaI_closelocalvars (TFunc *func);
char *luaI_getlocalname (TFunc *func, int local_number, int line);
#endif #endif

160
hash.c
View File

@@ -3,17 +3,16 @@
** hash manager for lua ** hash manager for lua
*/ */
char *rcs_hash="$Id: hash.c,v 2.25 1995/05/02 18:43:03 roberto Exp $"; char *rcs_hash="$Id: hash.c,v 2.40 1997/04/04 15:35:37 roberto Exp roberto $";
#include <string.h>
#include "mem.h" #include "luamem.h"
#include "opcode.h" #include "opcode.h"
#include "hash.h" #include "hash.h"
#include "table.h" #include "table.h"
#include "lua.h" #include "lua.h"
#include "auxlib.h"
#define streq(s1,s2) (s1 == s2 || (*(s1) == *(s2) && strcmp(s1,s2)==0))
#define nhash(t) ((t)->nhash) #define nhash(t) ((t)->nhash)
#define nuse(t) ((t)->nuse) #define nuse(t) ((t)->nuse)
@@ -24,22 +23,24 @@ char *rcs_hash="$Id: hash.c,v 2.25 1995/05/02 18:43:03 roberto Exp $";
#define val(n) (&(n)->val) #define val(n) (&(n)->val)
#define REHASH_LIMIT 0.70 /* avoid more than this % full */ #define REHASH_LIMIT 0.70 /* avoid more than this % full */
#define TagDefault LUA_T_ARRAY;
static Hash *listhead = NULL; static Hash *listhead = NULL;
/* hash dimensions values */ /* hash dimensions values */
static Word dimensions[] = static Long dimensions[] =
{3, 5, 7, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, {3L, 5L, 7L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
12853, 25717, 51437, 65521, 0}; /* 65521 == last prime < MAX_WORD */ 12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
1644817L, 3289613L, 6579211L, 13158023L, MAX_INT};
static Word redimension (Word nhash) int luaI_redimension (int nhash)
{ {
Word i; int i;
for (i=0; dimensions[i]!=0; i++) for (i=0; dimensions[i]<MAX_INT; i++)
{ {
if (dimensions[i] > nhash) if (dimensions[i] > nhash)
return dimensions[i]; return dimensions[i];
@@ -48,57 +49,49 @@ static Word redimension (Word nhash)
return 0; /* to avoid warnings */ return 0; /* to avoid warnings */
} }
static Word hashindex (Hash *t, Object *ref) /* hash function */ static int hashindex (Hash *t, TObject *ref) /* hash function */
{ {
switch (tag(ref)) long int h;
{ switch (ttype(ref)) {
case LUA_T_NIL: case LUA_T_NUMBER:
lua_error ("unexpected type to index table"); h = (long int)nvalue(ref); break;
return -1; /* UNREACHEABLE */ case LUA_T_STRING: case LUA_T_USERDATA:
case LUA_T_NUMBER: h = tsvalue(ref)->hash; break;
return (((Word)nvalue(ref))%nhash(t)); case LUA_T_FUNCTION:
case LUA_T_STRING: h = (IntPoint)ref->value.tf; break;
{ case LUA_T_CFUNCTION:
unsigned long h = tsvalue(ref)->hash; h = (IntPoint)fvalue(ref); break;
if (h == 0) case LUA_T_ARRAY:
{ h = (IntPoint)avalue(ref); break;
char *name = svalue(ref); default:
while (*name) lua_error ("unexpected type to index table");
h = ((h<<5)-h)^(unsigned char)*(name++); h = 0; /* UNREACHEABLE */
tsvalue(ref)->hash = h;
}
return (Word)h%nhash(t); /* make it a valid index */
} }
case LUA_T_FUNCTION: if (h < 0) h = -h;
return (((IntPoint)ref->value.tf)%nhash(t)); return h%nhash(t); /* make it a valid index */
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) int lua_equalObj (TObject *t1, TObject *t2)
{ {
if (tag(t1) != tag(t2)) return 0; if (ttype(t1) != ttype(t2)) return 0;
switch (tag(t1)) switch (ttype(t1))
{ {
case LUA_T_NIL: return 1; case LUA_T_NIL: return 1;
case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2); case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2);
case LUA_T_STRING: return streq(svalue(t1), svalue(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_ARRAY: return avalue(t1) == avalue(t2);
case LUA_T_FUNCTION: return t1->value.tf == t2->value.tf; case LUA_T_FUNCTION: return t1->value.tf == t2->value.tf;
case LUA_T_CFUNCTION: return fvalue(t1) == fvalue(t2); case LUA_T_CFUNCTION: return fvalue(t1) == fvalue(t2);
default: return uvalue(t1) == uvalue(t2); default:
lua_error("internal error in `lua_equalObj'");
return 0; /* UNREACHEABLE */
} }
} }
static Word present (Hash *t, Object *ref) static int present (Hash *t, TObject *ref)
{ {
Word h = hashindex(t, ref); int h = hashindex(t, ref);
while (tag(ref(node(t, h))) != LUA_T_NIL) while (ttype(ref(node(t, h))) != LUA_T_NIL)
{ {
if (lua_equalObj(ref, ref(node(t, h)))) if (lua_equalObj(ref, ref(node(t, h))))
return h; return h;
@@ -111,26 +104,27 @@ static Word present (Hash *t, Object *ref)
/* /*
** Alloc a vector node ** Alloc a vector node
*/ */
static Node *hashnodecreate (Word nhash) static Node *hashnodecreate (int nhash)
{ {
Word i; int i;
Node *v = newvector (nhash, Node); Node *v = newvector (nhash, Node);
for (i=0; i<nhash; i++) for (i=0; i<nhash; i++)
tag(ref(&v[i])) = LUA_T_NIL; ttype(ref(&v[i])) = LUA_T_NIL;
return v; return v;
} }
/* /*
** Create a new hash. Return the hash pointer or NULL on error. ** Create a new hash. Return the hash pointer or NULL on error.
*/ */
static Hash *hashcreate (Word nhash) static Hash *hashcreate (int nhash)
{ {
Hash *t = new(Hash); Hash *t = new(Hash);
nhash = redimension((Word)((float)nhash/REHASH_LIMIT)); nhash = luaI_redimension((int)((float)nhash/REHASH_LIMIT));
nodevector(t) = hashnodecreate(nhash); nodevector(t) = hashnodecreate(nhash);
nhash(t) = nhash; nhash(t) = nhash;
nuse(t) = 0; nuse(t) = 0;
markarray(t) = 0; markarray(t) = 0;
t->htag = TagDefault;
return t; return t;
} }
@@ -151,12 +145,12 @@ void lua_hashmark (Hash *h)
{ {
if (markarray(h) == 0) if (markarray(h) == 0)
{ {
Word i; int i;
markarray(h) = 1; markarray(h) = 1;
for (i=0; i<nhash(h); i++) for (i=0; i<nhash(h); i++)
{ {
Node *n = node(h,i); Node *n = node(h,i);
if (tag(ref(n)) != LUA_T_NIL) if (ttype(ref(n)) != LUA_T_NIL)
{ {
lua_markobject(&n->ref); lua_markobject(&n->ref);
lua_markobject(&n->val); lua_markobject(&n->val);
@@ -166,19 +160,17 @@ void lua_hashmark (Hash *h)
} }
static void call_fallbacks (void) void luaI_hashcallIM (void)
{ {
Hash *curr_array; Hash *curr_array;
Object t; TObject t;
tag(&t) = LUA_T_ARRAY; ttype(&t) = LUA_T_ARRAY;
for (curr_array = listhead; curr_array; curr_array = curr_array->next) for (curr_array = listhead; curr_array; curr_array = curr_array->next)
if (markarray(curr_array) != 1) if (markarray(curr_array) != 1)
{ {
avalue(&t) = curr_array; avalue(&t) = curr_array;
luaI_gcFB(&t); luaI_gcIM(&t);
} }
tag(&t) = LUA_T_NIL;
luaI_gcFB(&t); /* end of list */
} }
@@ -190,7 +182,6 @@ Long lua_hashcollector (void)
{ {
Hash *curr_array = listhead, *prev = NULL; Hash *curr_array = listhead, *prev = NULL;
Long counter = 0; Long counter = 0;
call_fallbacks();
while (curr_array != NULL) while (curr_array != NULL)
{ {
Hash *next = curr_array->next; Hash *next = curr_array->next;
@@ -218,7 +209,7 @@ Long lua_hashcollector (void)
** executes garbage collection if the number of arrays created ** executes garbage collection if the number of arrays created
** exceed a pre-defined range. ** exceed a pre-defined range.
*/ */
Hash *lua_createarray (Word nhash) Hash *lua_createarray (int nhash)
{ {
Hash *array; Hash *array;
lua_pack(); lua_pack();
@@ -234,15 +225,15 @@ Hash *lua_createarray (Word nhash)
*/ */
static void rehash (Hash *t) static void rehash (Hash *t)
{ {
Word i; int i;
Word nold = nhash(t); int nold = nhash(t);
Node *vold = nodevector(t); Node *vold = nodevector(t);
nhash(t) = redimension(nhash(t)); nhash(t) = luaI_redimension(nhash(t));
nodevector(t) = hashnodecreate(nhash(t)); nodevector(t) = hashnodecreate(nhash(t));
for (i=0; i<nold; i++) for (i=0; i<nold; i++)
{ {
Node *n = vold+i; Node *n = vold+i;
if (tag(ref(n)) != LUA_T_NIL && tag(val(n)) != LUA_T_NIL) if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) != LUA_T_NIL)
*node(t, present(t, ref(n))) = *n; /* copy old node to new hahs */ *node(t, present(t, ref(n))) = *n; /* copy old node to new hahs */
} }
luaI_free(vold); luaI_free(vold);
@@ -252,10 +243,10 @@ static void rehash (Hash *t)
** If the hash node is present, return its pointer, otherwise return ** If the hash node is present, return its pointer, otherwise return
** null. ** null.
*/ */
Object *lua_hashget (Hash *t, Object *ref) TObject *lua_hashget (Hash *t, TObject *ref)
{ {
Word h = present(t, ref); int h = present(t, ref);
if (tag(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h)); if (ttype(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h));
else return NULL; else return NULL;
} }
@@ -264,13 +255,13 @@ Object *lua_hashget (Hash *t, Object *ref)
** If the hash node is present, return its pointer, otherwise create a new ** If the hash node is present, return its pointer, otherwise create a new
** node for the given reference and also return its pointer. ** node for the given reference and also return its pointer.
*/ */
Object *lua_hashdefine (Hash *t, Object *ref) TObject *lua_hashdefine (Hash *t, TObject *ref)
{ {
Word h; int h;
Node *n; Node *n;
h = present(t, ref); h = present(t, ref);
n = node(t, h); n = node(t, h);
if (tag(ref(n)) == LUA_T_NIL) if (ttype(ref(n)) == LUA_T_NIL)
{ {
nuse(t)++; nuse(t)++;
if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT) if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT)
@@ -280,7 +271,7 @@ Object *lua_hashdefine (Hash *t, Object *ref)
n = node(t, h); n = node(t, h);
} }
*ref(n) = *ref; *ref(n) = *ref;
tag(val(n)) = LUA_T_NIL; ttype(val(n)) = LUA_T_NIL;
} }
return (val(n)); return (val(n));
} }
@@ -292,20 +283,15 @@ Object *lua_hashdefine (Hash *t, Object *ref)
** in the hash. ** in the hash.
** This function pushs the element value and its reference to the stack. ** This function pushs the element value and its reference to the stack.
*/ */
static void hashnext (Hash *t, Word i) static void hashnext (Hash *t, int i)
{ {
if (i >= nhash(t)) if (i >= nhash(t))
{
lua_pushnil(); lua_pushnil();
return; return;
} while (ttype(ref(node(t,i))) == LUA_T_NIL ||
while (tag(ref(node(t,i))) == LUA_T_NIL || tag(val(node(t,i))) == LUA_T_NIL) ttype(val(node(t,i))) == LUA_T_NIL)
{ {
if (++i >= nhash(t)) if (++i >= nhash(t))
{
lua_pushnil(); lua_pushnil();
return; return;
}
} }
luaI_pushobject(ref(node(t,i))); luaI_pushobject(ref(node(t,i)));
luaI_pushobject(val(node(t,i))); luaI_pushobject(val(node(t,i)));
@@ -316,12 +302,8 @@ void lua_next (void)
Hash *t; Hash *t;
lua_Object o = lua_getparam(1); lua_Object o = lua_getparam(1);
lua_Object r = lua_getparam(2); lua_Object r = lua_getparam(2);
if (o == LUA_NOOBJECT || r == LUA_NOOBJECT) luaL_arg_check(lua_istable(o), 1, "table expected");
lua_error ("too few arguments to function `next'"); luaL_arg_check(r != LUA_NOOBJECT, 2, "value expected");
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)); t = avalue(luaI_Address(o));
if (lua_isnil(r)) if (lua_isnil(r))
{ {
@@ -329,7 +311,7 @@ void lua_next (void)
} }
else else
{ {
Word h = present (t, luaI_Address(r)); int h = present (t, luaI_Address(r));
hashnext(t, h+1); hashnext(t, h+1);
} }
} }

35
hash.h
View File

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

353
inout.c
View File

@@ -5,34 +5,35 @@
** Also provides some predefined lua functions. ** Also provides some predefined lua functions.
*/ */
char *rcs_inout="$Id: inout.c,v 2.24 1995/10/23 13:54:11 roberto Exp roberto $"; char *rcs_inout="$Id: inout.c,v 2.56 1997/04/06 14:08:08 roberto Exp roberto $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "mem.h" #include "auxlib.h"
#include "lex.h"
#include "opcode.h" #include "opcode.h"
#include "hash.h"
#include "inout.h" #include "inout.h"
#include "table.h" #include "table.h"
#include "tree.h" #include "tree.h"
#include "lua.h" #include "lua.h"
#include "hash.h"
#include "luamem.h"
#ifndef MAXFUNCSTACK #include "fallback.h"
#define MAXFUNCSTACK 100 #include "luamem.h"
#endif
#define MAXMESSAGE MAXFUNCSTACK*80
/* Exported variables */ /* Exported variables */
Word lua_linenumber; Word lua_linenumber;
Bool lua_debug = 0;
char *lua_parsedfile; char *lua_parsedfile;
char *luaI_typenames[] = { /* ORDER LUA_T */
"userdata", "line", "cmark", "mark", "function",
"function", "table", "string", "number", "nil",
NULL
};
static FILE *fp; static FILE *fp;
static char *st; static char *st;
@@ -41,7 +42,8 @@ static char *st;
*/ */
static int fileinput (void) static int fileinput (void)
{ {
return fgetc (fp); int c = fgetc(fp);
return (c == EOF) ? 0 : c;
} }
/* /*
@@ -54,9 +56,9 @@ static int stringinput (void)
/* /*
** Function to open a file to be input unit. ** Function to open a file to be input unit.
** Return 0 on success or error message on error. ** Return the file.
*/ */
char *lua_openfile (char *fn) FILE *lua_openfile (char *fn)
{ {
lua_setinput (fileinput); lua_setinput (fileinput);
if (fn == NULL) if (fn == NULL)
@@ -67,14 +69,9 @@ char *lua_openfile (char *fn)
else else
fp = fopen (fn, "r"); fp = fopen (fn, "r");
if (fp == NULL) if (fp == NULL)
{ return NULL;
static char buff[255]; lua_parsedfile = luaI_createfixedstring(fn)->str;
sprintf(buff, "unable to open file `%.200s'", fn); return fp;
return buff;
}
lua_linenumber = 1;
lua_parsedfile = lua_constcreate(fn)->ts.str;
return NULL;
} }
/* /*
@@ -92,12 +89,15 @@ void lua_closefile (void)
/* /*
** Function to open a string to be input unit ** Function to open a string to be input unit
*/ */
#define SIZE_PREF 20 /* size of string prefix to appear in error messages */
void lua_openstring (char *s) void lua_openstring (char *s)
{ {
lua_setinput (stringinput); char buff[SIZE_PREF+25];
st = s; lua_setinput(stringinput);
lua_linenumber = 1; st = s;
lua_parsedfile = lua_constcreate("(string)")->ts.str; sprintf(buff, "(dostring) >> %.20s%s", s,
(strlen(s) > SIZE_PREF) ? "..." : "");
lua_parsedfile = luaI_createfixedstring(buff)->str;
} }
/* /*
@@ -107,114 +107,261 @@ void lua_closestring (void)
{ {
} }
static int passresults (void)
{
int arg = 0;
lua_Object obj;
while ((obj = lua_getresult(++arg)) != LUA_NOOBJECT)
lua_pushobject(obj);
return arg-1;
}
/* /*
** Internal function: do a string ** Internal function: do a string
*/ */
void lua_internaldostring (void) static void lua_internaldostring (void)
{ {
lua_Object obj = lua_getparam (1); if (lua_dostring(luaL_check_string(1)) == 0)
if (lua_isstring(obj) && !lua_dostring(lua_getstring(obj))) if (passresults() == 0)
lua_pushnumber(1); lua_pushuserdata(NULL); /* at least one result to signal no errors */
else
lua_pushnil();
} }
/* /*
** Internal function: do a file ** Internal function: do a file
*/ */
void lua_internaldofile (void) static void lua_internaldofile (void)
{ {
lua_Object obj = lua_getparam (1); char *fname = luaL_opt_string(1, NULL);
if (lua_isstring(obj) && !lua_dofile(lua_getstring(obj))) if (lua_dofile(fname) == 0)
lua_pushnumber(1); if (passresults() == 0)
else lua_pushuserdata(NULL); /* at least one result to signal no errors */
lua_pushnil();
} }
/*
** Internal function: print object values static char *tostring (lua_Object obj)
*/
void lua_print (void)
{ {
int i=1; TObject *o = luaI_Address(obj);
lua_Object obj; switch (ttype(o)) {
while ((obj=lua_getparam (i++)) != LUA_NOOBJECT) case LUA_T_NUMBER: case LUA_T_STRING:
{ return lua_getstring(obj);
if (lua_isnumber(obj)) printf("%g\n",lua_getnumber(obj)); case LUA_T_ARRAY: case LUA_T_FUNCTION:
else if (lua_isstring(obj)) printf("%s\n",lua_getstring(obj)); case LUA_T_CFUNCTION: case LUA_T_NIL:
else if (lua_isfunction(obj)) printf("function: %p\n",(luaI_Address(obj))->value.tf); return luaI_typenames[-ttype(o)];
else if (lua_iscfunction(obj)) printf("cfunction: %p\n",lua_getcfunction(obj) case LUA_T_USERDATA: {
); char *buff = luaI_buffer(100);
else if (lua_isuserdata(obj)) printf("userdata: %p\n",lua_getuserdata(obj)); int size = o->value.ts->size;
else if (lua_istable(obj)) printf("table: %p\n",avalue(luaI_Address(obj))); int i;
else if (lua_isnil(obj)) printf("nil\n"); strcpy(buff, "userdata: ");
else printf("invalid value to print\n"); if (size > 10) size = 10;
} for (i=0; i<size; i++)
sprintf(buff+strlen(buff), "%.2X",
(int)(unsigned char)o->value.ts->str[i]);
return buff;
}
default: return "<unknown object>";
}
} }
static void luaI_tostring (void)
{
lua_pushstring(tostring(lua_getparam(1)));
}
/* static void luaI_print (void)
** Internal function: return an object type. {
*/ int i = 1;
void luaI_type (void) lua_Object obj;
while ((obj = lua_getparam(i++)) != LUA_NOOBJECT)
printf("%s\n", tostring(obj));
}
static void luaI_type (void)
{ {
lua_Object o = lua_getparam(1); lua_Object o = lua_getparam(1);
int t; luaL_arg_check(o != LUA_NOOBJECT, 1, "no argument");
if (o == LUA_NOOBJECT) lua_pushstring(luaI_typenames[-ttype(luaI_Address(o))]);
lua_error("no parameter to function 'type'"); lua_pushnumber(lua_tag(o));
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 ** Internal function: convert an object to a number
*/ */
void lua_obj2number (void) static void lua_obj2number (void)
{ {
lua_Object o = lua_getparam(1); lua_Object o = lua_getparam(1);
if (lua_isnumber(o)) if (lua_isnumber(o))
lua_pushobject(o); lua_pushnumber(lua_getnumber(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) static void luaI_error (void)
{ {
char *s = lua_getstring(lua_getparam(1)); char *s = lua_getstring(lua_getparam(1));
if (s == NULL) s = "(no message)"; if (s == NULL) s = "(no message)";
lua_error(s); lua_error(s);
} }
static void luaI_assert (void)
{
lua_Object p = lua_getparam(1);
if (p == LUA_NOOBJECT || lua_isnil(p))
lua_error("assertion failed!");
}
static void luaI_setglobal (void)
{
lua_Object value = lua_getparam(2);
luaL_arg_check(value != LUA_NOOBJECT, 2, NULL);
lua_pushobject(value);
lua_setglobal(luaL_check_string(1));
lua_pushobject(value); /* return given value */
}
static void luaI_rawsetglobal (void)
{
lua_Object value = lua_getparam(2);
luaL_arg_check(value != LUA_NOOBJECT, 2, NULL);
lua_pushobject(value);
lua_rawsetglobal(luaL_check_string(1));
lua_pushobject(value); /* return given value */
}
static void luaI_getglobal (void)
{
lua_pushobject(lua_getglobal(luaL_check_string(1)));
}
static void luaI_rawgetglobal (void)
{
lua_pushobject(lua_rawgetglobal(luaL_check_string(1)));
}
static void luatag (void)
{
lua_pushnumber(lua_tag(lua_getparam(1)));
}
#define MAXPARAMS 256
static void luaI_call (void)
{
lua_Object f = lua_getparam(1);
lua_Object arg = lua_getparam(2);
lua_Object temp, params[MAXPARAMS];
int narg, i;
luaL_arg_check(lua_isfunction(f), 1, "function expected");
luaL_arg_check(lua_istable(arg), 2, "table expected");
/* narg = arg.n */
lua_pushobject(arg);
lua_pushstring("n");
temp = lua_getsubscript();
narg = lua_isnumber(temp) ? lua_getnumber(temp) : MAXPARAMS+1;
/* read arg[1...n] */
for (i=0; i<narg; i++) {
if (i>=MAXPARAMS)
lua_error("argument list too long in function `call'");
lua_pushobject(arg);
lua_pushnumber(i+1);
params[i] = lua_getsubscript();
if (narg == MAXPARAMS+1 && lua_isnil(params[i])) {
narg = i;
break;
}
}
/* push parameters and do the call */
for (i=0; i<narg; i++)
lua_pushobject(params[i]);
if (lua_callfunction(f))
lua_error(NULL);
else
passresults();
}
static void luaIl_settag (void)
{
lua_Object o = lua_getparam(1);
luaL_arg_check(o != LUA_NOOBJECT, 1, NULL);
lua_pushobject(o);
lua_settag(luaL_check_number(2));
}
static void luaIl_newtag (void)
{
lua_pushnumber(lua_newtag());
}
static void rawgettable (void)
{
lua_Object t = lua_getparam(1);
lua_Object i = lua_getparam(2);
luaL_arg_check(t != LUA_NOOBJECT, 1, NULL);
luaL_arg_check(i != LUA_NOOBJECT, 2, NULL);
lua_pushobject(t);
lua_pushobject(i);
lua_pushobject(lua_rawgettable());
}
static void rawsettable (void)
{
lua_Object t = lua_getparam(1);
lua_Object i = lua_getparam(2);
lua_Object v = lua_getparam(3);
luaL_arg_check(t != LUA_NOOBJECT && i != LUA_NOOBJECT && v != LUA_NOOBJECT,
0, NULL);
lua_pushobject(t);
lua_pushobject(i);
lua_pushobject(v);
lua_rawsettable();
}
/*
** Internal functions
*/
static struct {
char *name;
lua_CFunction func;
} int_funcs[] = {
{"assert", luaI_assert},
{"call", luaI_call},
{"dofile", lua_internaldofile},
{"dostring", lua_internaldostring},
{"error", luaI_error},
{"getglobal", luaI_getglobal},
{"newtag", luaIl_newtag},
{"next", lua_next},
{"nextvar", luaI_nextvar},
{"print", luaI_print},
{"rawgetglobal", luaI_rawgetglobal},
{"rawgettable", rawgettable},
{"rawsetglobal", luaI_rawsetglobal},
{"rawsettable", rawsettable},
{"seterrormethod", luaI_seterrormethod},
{"setfallback", luaI_setfallback},
{"setglobal", luaI_setglobal},
{"settagmethod", luaI_settagmethod},
{"gettagmethod", luaI_gettagmethod},
{"settag", luaIl_settag},
{"tonumber", lua_obj2number},
{"tostring", luaI_tostring},
{"tag", luatag},
{"type", luaI_type}
};
#define INTFUNCSIZE (sizeof(int_funcs)/sizeof(int_funcs[0]))
void luaI_predefine (void)
{
int i;
Word n;
for (i=0; i<INTFUNCSIZE; i++) {
n = luaI_findsymbolbyname(int_funcs[i].name);
s_ttype(n) = LUA_T_CFUNCTION; s_fvalue(n) = int_funcs[i].func;
}
n = luaI_findsymbolbyname("_VERSION_");
s_ttype(n) = LUA_T_STRING; s_tsvalue(n) = lua_createstring(LUA_VERSION);
}

13
inout.h
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: inout.h,v 1.9 1995/05/16 17:23:58 roberto Exp roberto $ ** $Id: inout.h,v 1.16 1996/05/28 21:07:32 roberto Exp roberto $
*/ */
@@ -7,23 +7,18 @@
#define inout_h #define inout_h
#include "types.h" #include "types.h"
#include <stdio.h>
extern Word lua_linenumber; extern Word lua_linenumber;
extern Bool lua_debug;
extern Word lua_debugline; extern Word lua_debugline;
extern char *lua_parsedfile; extern char *lua_parsedfile;
char *lua_openfile (char *fn); FILE *lua_openfile (char *fn);
void lua_closefile (void); void lua_closefile (void);
void lua_openstring (char *s); void lua_openstring (char *s);
void lua_closestring (void); void lua_closestring (void);
void lua_internaldofile (void); void luaI_predefine (void);
void lua_internaldostring (void);
void lua_print (void);
void luaI_type (void);
void lua_obj2number (void);
void luaI_error (void);
#endif #endif

726
iolib.c
View File

@@ -1,23 +1,18 @@
/*
** 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 <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include "lua.h" #include "lua.h"
#include "auxlib.h"
#include "luadebug.h" #include "luadebug.h"
#include "lualib.h" #include "lualib.h"
static FILE *in=stdin, *out=stdout;
FILE *lua_infile, *lua_outfile;
int lua_tagio;
#ifdef POPEN #ifdef POPEN
@@ -29,547 +24,233 @@ int pclose();
#endif #endif
static void closeread (void) static void pushresult (int i)
{ {
if (in != stdin) if (i)
{ lua_pushuserdata(NULL);
if (pclose(in) == -1) else {
fclose(in); lua_pushnil();
in = stdin; #ifndef NOSTRERROR
lua_pushstring(strerror(errno));
#else
lua_pushstring("O.S. unable to define the error");
#endif
} }
} }
static void closewrite (void)
static void closefile (FILE *f)
{ {
if (out != stdout) if (f == stdin || f == stdout)
{ return;
if (pclose(out) == -1) if (f == lua_infile)
fclose(out); lua_infile = stdin;
out = stdout; if (f == lua_outfile)
} lua_outfile = stdout;
if (pclose(f) == -1)
fclose(f);
} }
/*
** Open a file to read.
** LUA interface:
** status = readfrom (filename)
** where:
** status = 1 -> success
** status = nil -> error
*/
static void io_readfrom (void) static void io_readfrom (void)
{ {
if (lua_getparam (1) == LUA_NOOBJECT) lua_Object f = lua_getparam(1);
{ /* restore standart input */ if (f == LUA_NOOBJECT)
closeread(); closefile(lua_infile); /* restore standart input */
lua_pushnumber (1); else if (lua_tag(f) == lua_tagio)
} lua_infile = lua_getuserdata(f);
else else {
{ char *s = luaL_check_string(1);
char *s = lua_check_string(1, "readfrom"); FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); if (fp)
if (fp == NULL) lua_infile = fp;
lua_pushnil(); else {
else pushresult(0);
{ return;
closeread(); }
in = fp; }
lua_pushnumber (1); lua_pushusertag(lua_infile, lua_tagio);
}
}
} }
/*
** Open a file to write.
** LUA interface:
** status = writeto (filename)
** where:
** status = 1 -> success
** status = nil -> error
*/
static void io_writeto (void) static void io_writeto (void)
{ {
if (lua_getparam (1) == LUA_NOOBJECT) /* restore standart output */ lua_Object f = lua_getparam(1);
{ if (f == LUA_NOOBJECT)
closewrite(); closefile(lua_outfile); /* restore standart output */
lua_pushnumber (1); else if (lua_tag(f) == lua_tagio)
} lua_outfile = lua_getuserdata(f);
else else {
{ char *s = luaL_check_string(1);
char *s = lua_check_string(1, "writeto"); FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w");
FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); if (fp)
if (fp == NULL) lua_outfile = fp;
lua_pushnil(); else {
else pushresult(0);
{ return;
closewrite(); }
out = fp; }
lua_pushnumber (1); lua_pushusertag(lua_outfile, lua_tagio);
}
}
} }
/*
** 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) static void io_appendto (void)
{ {
char *s = lua_check_string(1, "appendto"); char *s = luaL_check_string(1);
struct stat st; FILE *fp = fopen (s, "a");
int r = (stat(s, &st) == -1) ? 1 : 2; if (fp != NULL) {
FILE *fp = fopen (s, "a"); lua_outfile = fp;
if (fp == NULL) lua_pushusertag(lua_outfile, lua_tagio);
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 else
*m = -1; pushresult(0);
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) #define NEED_OTHER (EOF-1) /* just some flag different from EOF */
{
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) static void io_read (void)
{ {
lua_Object o = lua_getparam (1); char *buff;
if (o == LUA_NOOBJECT) /* free format */ char *p = luaL_opt_string(1, "[^\n]*{\n}");
read_free(); int inskip = 0; /* to control {skips} */
else /* formatted */ int c = NEED_OTHER;
{ luaI_emptybuff();
int m, dummy1, dummy2; while (*p) {
switch (getformat(lua_check_string(1, "read"), &dummy1, &m, &dummy2)) if (*p == '{') {
{ inskip++;
case 's': p++;
if (m < 0) }
read_until_blank(); else if (*p == '}') {
else if (inskip == 0)
read_m(m); lua_error("unbalanced braces in read pattern");
lua_pushstring(add_char(0)); inskip--;
break; p++;
}
case 'i': /* can read as float, since it makes no difference to Lua */ else {
case 'f': char *ep = luaL_item_end(p); /* get what is next */
{ int m; /* match result */
double d; if (c == NEED_OTHER) c = getc(lua_infile);
int result; m = (c == EOF) ? 0 : luaL_singlematch((char)c, p);
if (m < 0) if (m) {
result = fscanf(in, "%lf", &d); if (inskip == 0) luaI_addchar(c);
else c = NEED_OTHER;
{ }
read_m(m); switch (*ep) {
result = sscanf(add_char(0), "%lf", &d); case '*': /* repetition */
} if (!m) p = ep+1; /* else stay in (repeat) the same item */
if (result == 1) break;
lua_pushnumber(d); case '?': /* optional */
else p = ep+1; /* continues reading the pattern */
lua_pushnil(); break;
break; default:
if (m) p = ep; /* continues reading the pattern */
else
goto break_while; /* pattern fails */
} }
} }
} } break_while:
} if (c >= 0) /* not EOF nor NEED_OTHER? */
ungetc(c, lua_infile);
buff = luaI_addchar(0);
/* if (*buff != 0 || *p == 0) /* read something or did not fail? */
** Read characters until a given one. The delimiter is not read. lua_pushstring(buff);
*/
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) static void io_write (void)
{ {
int status = 0; int arg = 1;
if (lua_getparam (2) == LUA_NOOBJECT) /* free format */ int status = 1;
{ char *s;
lua_Object o1 = lua_getparam(1); while ((s = luaL_opt_string(arg++, NULL)) != NULL)
if (lua_isnumber(o1)) status = status && (fputs(s, lua_outfile) != EOF);
status = fprintf (out, "%g", lua_getnumber(o1)) >= 0; pushresult(status);
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) static void io_execute (void)
{ {
lua_pushnumber(system(lua_check_string(1, "execute"))); lua_pushnumber(system(luaL_check_string(1)));
} }
/*
** Remove a file. On error return nil.
*/
static void io_remove (void) static void io_remove (void)
{ {
if (remove(lua_check_string(1, "remove")) == 0) pushresult(remove(luaL_check_string(1)) == 0);
lua_pushnumber (1);
else
lua_pushnil();
} }
/* static void io_rename (void)
** To get a environment variables {
*/ 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) static void io_getenv (void)
{ {
char *env = getenv(lua_check_string(1, "getenv")); lua_pushstring(getenv(luaL_check_string(1))); /* if NULL push nil */
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) static void io_date (void)
{ {
time_t t; time_t t;
struct tm *s; struct tm *tm;
char *s = luaL_opt_string(1, "%c");
time(&t); char b[BUFSIZ];
s = localtime(&t); time(&t); tm = localtime(&t);
lua_pushnumber(s->tm_mday); if (strftime(b,sizeof(b),s,tm))
lua_pushnumber(s->tm_mon+1); lua_pushstring(b);
lua_pushnumber(s->tm_year+1900); else
lua_error("invalid `date' format");
} }
/*
** Beep
*/
static void io_beep (void)
{
printf("\a");
}
/*
** To exit
*/
static void io_exit (void) static void io_exit (void)
{ {
lua_Object o = lua_getparam(1); lua_Object o = lua_getparam(1);
if (lua_isstring(o)) exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1);
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) static void io_debug (void)
{ {
while (1) while (1) {
{
char buffer[250]; char buffer[250];
fprintf(stderr, "lua_debug> "); fprintf(stderr, "lua_debug> ");
if (gets(buffer) == 0) return; if (fgets(buffer, sizeof(buffer), stdin) == 0) return;
if (strcmp(buffer, "cont") == 0) return; if (strcmp(buffer, "cont\n") == 0) return;
lua_dostring(buffer); lua_dostring(buffer);
} }
} }
void lua_printstack (FILE *f) static void lua_printstack (FILE *f)
{ {
int level = 0; int level = 1; /* skip level 0 (it's this function) */
lua_Object func; lua_Object func;
fprintf(f, "Active Stack:\n"); while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) {
while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT)
{
char *name; char *name;
int currentline; int currentline;
fprintf(f, "\t"); fprintf(f, (level==2) ? "Active Stack:\n\t" : "\t");
switch (*getobjname(func, &name)) switch (*lua_getobjname(func, &name)) {
{
case 'g': case 'g':
fprintf(f, "function %s", name); fprintf(f, "function %s", name);
break; break;
case 'f': case 'f':
fprintf(f, "fallback %s", name); fprintf(f, "`%s' iternal method", name);
break; break;
default: default: {
{
char *filename; char *filename;
int linedefined; int linedefined;
lua_funcinfo(func, &filename, &linedefined); lua_funcinfo(func, &filename, &linedefined);
@@ -582,7 +263,7 @@ void lua_printstack (FILE *f)
} }
} }
if ((currentline = lua_currentline(func)) > 0) if ((currentline = lua_currentline(func)) > 0)
fprintf(f, " at line %d", currentline); fprintf(f, " at line %d", currentline);
fprintf(f, "\n"); fprintf(f, "\n");
} }
} }
@@ -590,33 +271,78 @@ void lua_printstack (FILE *f)
static void errorfb (void) static void errorfb (void)
{ {
lua_Object o = lua_getparam(1); fprintf(stderr, "lua: %s\n", lua_getstring(lua_getparam(1)));
char *s = lua_isstring(o) ? lua_getstring(o) : "(no messsage)";
fprintf(stderr, "lua: %s\n", s);
lua_printstack(stderr); lua_printstack(stderr);
} }
/* /* --------------------------------------------
** Open io library * functions to manipulate userdata
*/ */
void iolib_open (void) static void getbyte (void)
{ {
lua_register ("readfrom", io_readfrom); lua_Object ud = lua_getparam(1);
lua_register ("writeto", io_writeto); int i = luaL_opt_number(2, -1);
lua_register ("appendto", io_appendto); luaL_arg_check(lua_isuserdata(ud), 1, "userdata expected");
lua_register ("read", io_read); if (i == -1)
lua_register ("readuntil",io_readuntil); lua_pushnumber(lua_getbindatasize(ud));
lua_register ("write", io_write); else {
lua_register ("execute", io_execute); i--;
lua_register ("remove", io_remove); if (0 <= i && i < lua_getbindatasize(ud))
lua_register ("getenv", io_getenv); lua_pushnumber(*(((char *)lua_getbindata(ud))+i));
lua_register ("time", io_time); else
lua_register ("date", io_date); lua_pushnil();
lua_register ("beep", io_beep); }
lua_register ("exit", io_exit);
lua_register ("debug", io_debug);
lua_register ("print_stack", errorfb);
lua_setfallback("error", errorfb);
} }
static void newuserdata (void)
{
lua_Object t = lua_getparam(1);
int tag = luaL_opt_number(2, 0);
int i;
luaI_emptybuff();
luaL_arg_check(lua_istable(t), 1, "table expected");
for (i=0; ; i++) {
lua_Object o;
lua_beginblock();
lua_pushobject(t);
lua_pushnumber(i+1);
o = lua_rawgettable();
if (lua_isnil(o)) {
lua_endblock();
break;
}
luaL_arg_check(lua_isnumber(o), 1, "table values must be numbers");
luaI_addchar(lua_getnumber(o));
lua_endblock();
}
lua_pushbindata(luaI_addchar(0), i, tag);
}
static struct luaL_reg iolib[] = {
{"readfrom", io_readfrom},
{"writeto", io_writeto},
{"appendto", io_appendto},
{"read", io_read},
{"write", io_write},
{"execute", io_execute},
{"remove", io_remove},
{"rename", io_rename},
{"tmpname", io_tmpname},
{"getenv", io_getenv},
{"date", io_date},
{"exit", io_exit},
{"debug", io_debug},
{"getbyte", getbyte},
{"userdata", newuserdata},
{"print_stack", errorfb}
};
void iolib_open (void)
{
lua_tagio = lua_newtag();
lua_infile=stdin; lua_outfile=stdout;
luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
lua_seterrormethod(errorfb);
}

406
lex.c
View File

@@ -1,53 +1,71 @@
char *rcs_lex = "$Id: lex.c,v 2.20 1995/10/25 13:05:51 roberto Exp roberto $"; char *rcs_lex = "$Id: lex.c,v 2.46 1997/04/07 14:48:53 roberto Exp roberto $";
#include <ctype.h> #include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "mem.h" #include "auxlib.h"
#include "luamem.h"
#include "tree.h" #include "tree.h"
#include "table.h" #include "table.h"
#include "opcode.h" #include "lex.h"
#include "inout.h" #include "inout.h"
#include "luadebug.h"
#include "parser.h" #include "parser.h"
#include "ugly.h"
#define MINBUFF 260 #define MINBUFF 250
#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) (yytext[tokensize++] = (x))
#define save_and_next() (save(current), next())
#define next() { current = input(); }
#define save(x) { *yytextLast++ = (x); }
#define save_and_next() { save(current); next(); }
static int current; static int current; /* look ahead character */
static char *yytext = NULL; static Input input; /* input function */
static int textsize = 0;
static char *yytextLast; #define MAX_IFS 10
/* "ifstate" keeps the state of each nested $if the lexical is
** dealing with. The first bit indicates whether the $if condition
** is false or true. The second bit indicates whether the lexical is
** inside the "then" part (0) or the "else" part (2)
*/
static int ifstate[MAX_IFS]; /* 0 => then part - condition false */
/* 1 => then part - condition true */
/* 2 => else part - condition false */
/* 3 => else part - condition true */
static int iflevel; /* level of nested $if's */
static Input input;
void lua_setinput (Input fn) void lua_setinput (Input fn)
{ {
current = ' '; current = '\n';
lua_linenumber = 0;
iflevel = 0;
input = fn; input = fn;
if (yytext == NULL)
{
textsize = MINBUFF;
yytext = newvector(textsize, char);
}
} }
char *lua_lasttext (void)
static void luaI_auxsyntaxerror (char *s)
{ {
*yytextLast = 0; luaL_verror("%s;\n> at line %d in file %s",
return yytext; s, lua_linenumber, lua_parsedfile);
}
static void luaI_auxsynterrbf (char *s, char *token)
{
if (token[0] == 0)
token = "<eof>";
luaL_verror("%s;\n> last token read: \"%s\" at line %d in file %s",
s, token, lua_linenumber, lua_parsedfile);
}
void luaI_syntaxerror (char *s)
{
luaI_auxsynterrbf(s, luaI_buffer(1));
} }
/* The reserved words must be listed in lexicographic order */
static struct static struct
{ {
char *name; char *name;
@@ -74,122 +92,198 @@ static struct
#define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0])) #define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0]))
static int findReserved (char *name) void luaI_addReserved (void)
{ {
int l = 0; int i;
int h = RESERVEDSIZE - 1; for (i=0; i<RESERVEDSIZE; i++)
while (l <= h)
{ {
int m = (l+h)/2; TaggedString *ts = lua_createstring(reserved[i].name);
int comp = lua_strcmp(name, reserved[m].name); ts->marked = reserved[i].token; /* reserved word (always > 255) */
if (comp < 0)
h = m-1;
else if (comp == 0)
return reserved[m].token;
else
l = m+1;
} }
return 0;
} }
static void growtext (void) /*
** Pragma handling
*/
#define PRAGMASIZE 20
static void skipspace (void)
{ {
int size = yytextLast - yytext; while (current == ' ' || current == '\t') next();
textsize *= 2;
yytext = growvector(yytext, textsize, char);
yytextLast = yytext + size;
} }
static int read_long_string (void) static int checkcond (char *buff)
{
if (strcmp(buff, "nil") == 0)
return 0;
else if (strcmp(buff, "1") == 0)
return 1;
else if (isalpha((unsigned char)buff[0]))
return luaI_globaldefined(buff);
else {
luaI_auxsynterrbf("invalid $if condition", buff);
return 0; /* to avoid warnings */
}
}
static void readname (char *buff)
{
int i = 0;
skipspace();
while (isalnum((unsigned char)current)) {
if (i >= PRAGMASIZE) {
buff[PRAGMASIZE] = 0;
luaI_auxsynterrbf("pragma too long", buff);
}
buff[i++] = current;
next();
}
buff[i] = 0;
}
static void inclinenumber (void);
static void ifskip (int thisiflevel)
{
while (iflevel > thisiflevel &&
(ifstate[thisiflevel] == 0 || ifstate[thisiflevel] == 3)) {
if (current == '\n')
inclinenumber();
else if (current == 0)
luaI_auxsyntaxerror("input ends inside a $if");
else next();
}
}
static void inclinenumber (void)
{
static char *pragmas [] =
{"debug", "nodebug", "end", "ifnot", "if", "else", NULL};
next(); /* skip '\n' */
++lua_linenumber;
if (current == '$') { /* is a pragma? */
char buff[PRAGMASIZE+1];
int ifnot = 0;
next(); /* skip $ */
readname(buff);
switch (luaI_findstring(buff, pragmas)) {
case 0: /* debug */
lua_debug = 1;
break;
case 1: /* nodebug */
lua_debug = 0;
break;
case 2: /* end */
if (--iflevel < 0)
luaI_auxsyntaxerror("unmatched $endif");
break;
case 3: /* ifnot */
ifnot = 1;
/* go through */
case 4: /* if */
if (iflevel == MAX_IFS)
luaI_auxsyntaxerror("too many nested `$ifs'");
readname(buff);
ifstate[iflevel++] = checkcond(buff) ? !ifnot : ifnot;
break;
case 5: /* else */
if (iflevel <= 0 || (ifstate[iflevel-1] & 2))
luaI_auxsyntaxerror("unmatched $else");
ifstate[iflevel-1] = ifstate[iflevel-1] | 2;
break;
default:
luaI_auxsynterrbf("invalid pragma", buff);
}
skipspace();
if (current == '\n') /* pragma must end with a '\n' */
inclinenumber();
else if (current != 0) /* or eof */
luaI_auxsyntaxerror("invalid pragma format");
if (iflevel > 0)
ifskip(iflevel-1);
}
}
static int read_long_string (char *yytext, int buffsize)
{ {
int cont = 0; int cont = 0;
int spaceleft = textsize - (yytextLast - yytext); int tokensize = 2; /* '[[' already stored */
while (1) while (1)
{ {
if (spaceleft <= 2) /* may read more than 1 char in one cicle */ if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
{ yytext = luaI_buffer(buffsize *= 2);
growtext();
spaceleft = textsize - (yytextLast - yytext);
}
switch (current) switch (current)
{ {
case EOF:
case 0: case 0:
save(0);
return WRONGTOKEN; return WRONGTOKEN;
case '[': case '[':
save_and_next(); spaceleft--; save_and_next();
if (current == '[') if (current == '[')
{ {
cont++; cont++;
save_and_next(); spaceleft--; save_and_next();
} }
continue; continue;
case ']': case ']':
save_and_next(); spaceleft--; save_and_next();
if (current == ']') if (current == ']')
{ {
if (cont == 0) return STRING; if (cont == 0) goto endloop;
cont--; cont--;
save_and_next(); spaceleft--; save_and_next();
} }
continue; continue;
case '\n': case '\n':
lua_linenumber++; /* goes through */ save('\n');
inclinenumber();
continue;
default: default:
save_and_next(); spaceleft--; save_and_next();
} }
} } endloop:
save_and_next(); /* pass the second ']' */
yytext[tokensize-2] = 0; /* erases ']]' */
luaY_lval.vWord = luaI_findconstantbyname(yytext+2);
yytext[tokensize-2] = ']'; /* restores ']]' */
save(0);
return STRING;
} }
int luaY_lex (void)
int yylex (void)
{ {
float a;
static int linelasttoken = 0; static int linelasttoken = 0;
double a;
int buffsize = MINBUFF;
char *yytext = luaI_buffer(buffsize);
yytext[1] = yytext[2] = yytext[3] = 0;
if (lua_debug) if (lua_debug)
luaI_codedebugline(linelasttoken); luaI_codedebugline(linelasttoken);
linelasttoken = lua_linenumber; linelasttoken = lua_linenumber;
while (1) while (1)
{ {
yytextLast = yytext; int tokensize = 0;
#if 0
fprintf(stderr,"'%c' %d\n",current,current);
#endif
switch (current) switch (current)
{ {
case EOF: case '\n':
case 0: inclinenumber();
return 0; linelasttoken = lua_linenumber;
case '\n': linelasttoken = ++lua_linenumber; continue;
case ' ':
case '\r': /* CR: to avoid problems with DOS/Windows */ case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
case '\t':
next(); next();
continue; 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 '-': case '-':
save_and_next(); save_and_next();
if (current != '-') return '-'; /* else goes through */ if (current != '-') return '-';
case '#':
do { next(); } while (current != '\n' && current != 0); do { next(); } while (current != '\n' && current != 0);
continue; continue;
@@ -199,12 +293,7 @@ int yylex (void)
else else
{ {
save_and_next(); /* pass the second '[' */ save_and_next(); /* pass the second '[' */
if (read_long_string() == WRONGTOKEN) return read_long_string(yytext, buffsize);
return WRONGTOKEN;
save_and_next(); /* pass the second ']' */
*(yytextLast-2) = 0; /* erases ']]' */
yylval.vWord = luaI_findconstantbyname(yytext+2);
return STRING;
} }
case '=': case '=':
@@ -231,21 +320,16 @@ int yylex (void)
case '\'': case '\'':
{ {
int del = current; int del = current;
int spaceleft = textsize - (yytextLast - yytext); save_and_next();
next(); /* skip the delimiter */
while (current != del) while (current != del)
{ {
if (spaceleft <= 2) /* may read more than 1 char in one cicle */ if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
{ yytext = luaI_buffer(buffsize *= 2);
growtext();
spaceleft = textsize - (yytextLast - yytext);
}
spaceleft--;
switch (current) switch (current)
{ {
case EOF:
case 0: case 0:
case '\n': case '\n':
save(0);
return WRONGTOKEN; return WRONGTOKEN;
case '\\': case '\\':
next(); /* do not save the '\' */ next(); /* do not save the '\' */
@@ -254,16 +338,19 @@ int yylex (void)
case 'n': save('\n'); next(); break; case 'n': save('\n'); next(); break;
case 't': save('\t'); next(); break; case 't': save('\t'); next(); break;
case 'r': save('\r'); next(); break; case 'r': save('\r'); next(); break;
default : save(current); next(); break; case '\n': save('\n'); inclinenumber(); break;
default : save_and_next(); break;
} }
break; break;
default: default:
save_and_next(); save_and_next();
} }
} }
next(); /* skip the delimiter */ next(); /* skip delimiter */
*yytextLast = 0; save(0);
yylval.vWord = luaI_findconstantbyname(yytext); luaY_lval.vWord = luaI_findconstantbyname(yytext+1);
tokensize--;
save(del); save(0); /* restore delimiter */
return STRING; return STRING;
} }
@@ -281,12 +368,16 @@ int yylex (void)
case 'Z': case 'Z':
case '_': case '_':
{ {
Word res; TaggedString *ts;
do { save_and_next(); } while (isalnum(current) || current == '_'); do {
*yytextLast = 0; save_and_next();
res = findReserved(yytext); } while (isalnum((unsigned char)current) || current == '_');
if (res) return res; save(0);
yylval.pNode = lua_constcreate(yytext); ts = lua_createstring(yytext);
if (ts->marked > 2)
return ts->marked; /* reserved word */
luaY_lval.pTStr = ts;
ts->marked = 2; /* avoid GC */
return NAME; return NAME;
} }
@@ -295,9 +386,14 @@ int yylex (void)
if (current == '.') if (current == '.')
{ {
save_and_next(); save_and_next();
return CONC; if (current == '.')
{
save_and_next();
return DOTS; /* ... */
}
else return CONC; /* .. */
} }
else if (!isdigit(current)) return '.'; else if (!isdigit((unsigned char)current)) return '.';
/* current is a digit: goes through to number */ /* current is a digit: goes through to number */
a=0.0; a=0.0;
goto fraction; goto fraction;
@@ -305,53 +401,59 @@ int yylex (void)
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
a=0.0; a=0.0;
do { a=10*a+current-'0'; save_and_next(); } while (isdigit(current)); do {
if (current == '.') save_and_next(); a=10.0*a+(current-'0');
fraction: save_and_next();
{ float da=0.1; } while (isdigit((unsigned char)current));
while (isdigit(current)) if (current == '.') {
{a+=(current-'0')*da; da/=10.0; save_and_next()}; save_and_next();
if (current == '.')
luaI_syntaxerror(
"ambiguous syntax (decimal point x string concatenation)");
}
fraction:
{ double da=0.1;
while (isdigit((unsigned char)current))
{
a+=(current-'0')*da;
da/=10.0;
save_and_next();
}
if (current == 'e' || current == 'E') if (current == 'e' || current == 'E')
{ {
int e=0; int e=0;
int neg; int neg;
float ea; double ea;
save_and_next(); save_and_next();
neg=(current=='-'); neg=(current=='-');
if (current == '+' || current == '-') save_and_next(); if (current == '+' || current == '-') save_and_next();
if (!isdigit(current)) return WRONGTOKEN; if (!isdigit((unsigned char)current)) {
do { e=10*e+current-'0'; save_and_next(); } while (isdigit(current)); save(0); return WRONGTOKEN; }
for (ea=neg?0.1:10.0; e>0; e>>=1) do {
e=10.0*e+(current-'0');
save_and_next();
} while (isdigit((unsigned char)current));
for (ea=neg?0.1:10.0; e>0; e>>=1)
{ {
if (e & 1) a*=ea; if (e & 1) a*=ea;
ea*=ea; ea*=ea;
} }
} }
yylval.vFloat = a; luaY_lval.vFloat = a;
save(0);
return NUMBER; return NUMBER;
} }
case U_and: case U_do: case U_else: case U_elseif: case U_end: case 0:
case U_function: case U_if: case U_local: case U_nil: case U_not: save(0);
case U_or: case U_repeat: case U_return: case U_then: if (iflevel > 0)
case U_until: case U_while: luaI_syntaxerror("missing $endif");
{ return 0;
int old = current;
next();
return reserved[old-U_and].token;
}
case U_eq: next(); return EQ; default:
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(); save_and_next();
return yytext[0]; return yytext[0];
}
} }
} }
} }

19
lex.h Normal file
View File

@@ -0,0 +1,19 @@
/*
** lex.h
** TecCGraf - PUC-Rio
** $Id: lex.h,v 1.2 1996/02/14 13:35:51 roberto Exp roberto $
*/
#ifndef lex_h
#define lex_h
typedef int (*Input) (void);
void lua_setinput (Input fn);
void luaI_syntaxerror (char *s);
int luaY_lex (void);
void luaI_addReserved (void);
#endif

105
lua.c
View File

@@ -3,7 +3,7 @@
** Linguagem para Usuarios de Aplicacao ** Linguagem para Usuarios de Aplicacao
*/ */
char *rcs_lua="$Id: lua.c,v 1.6 1995/10/23 13:54:11 roberto Exp roberto $"; char *rcs_lua="$Id: lua.c,v 1.14 1996/09/24 17:30:28 roberto Exp roberto $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -11,41 +11,23 @@ char *rcs_lua="$Id: lua.c,v 1.6 1995/10/23 13:54:11 roberto Exp roberto $";
#include "lua.h" #include "lua.h"
#include "lualib.h" #include "lualib.h"
static int lua_argc;
static char **lua_argv;
/* #ifdef _POSIX_SOURCE
** although this function is POSIX, there is no standard header file that #include <unistd.h>
** defines it #else
*/ #define isatty(x) (x==0) /* assume stdin is a tty */
int isatty (int fd); #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]);
}
}
static void manual_input (void) static void manual_input (void)
{ {
if (isatty(fileno(stdin))) if (isatty(0)) {
{ char buffer[250];
char buffer[250]; while (fgets(buffer, sizeof(buffer), stdin) != 0) {
while (gets(buffer) != 0) lua_beginblock();
lua_dostring(buffer); lua_dostring(buffer);
lua_endblock();
}
} }
else else
lua_dofile(NULL); /* executes stdin as a file */ lua_dofile(NULL); /* executes stdin as a file */
@@ -54,39 +36,36 @@ static void manual_input (void)
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
int i; int i;
int result = 0; int result = 0;
iolib_open (); iolib_open ();
strlib_open (); strlib_open ();
mathlib_open (); mathlib_open ();
if (argc < 2)
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(); manual_input();
else if (strcmp(argv[i], "-v") == 0) else for (i=1; i<argc; i++) {
printf("%s %s\n(written by %s)\n\n", if (strcmp(argv[i], "-") == 0)
LUA_VERSION, LUA_COPYRIGHT, LUA_AUTHORS); manual_input();
else else if (strcmp(argv[i], "-v") == 0)
result = lua_dofile (argv[i]); printf("%s %s\n(written by %s)\n\n",
LUA_VERSION, LUA_COPYRIGHT, LUA_AUTHORS);
else if ((strcmp(argv[i], "-e") == 0 && i++) || strchr(argv[i], '=')) {
if (lua_dostring(argv[i]) != 0) {
fprintf(stderr, "lua: error running argument `%s'\n", argv[i]);
return 1;
}
}
else {
result = lua_dofile (argv[i]);
if (result) {
if (result == 2) {
fprintf(stderr, "lua: cannot execute file ");
perror(argv[i]);
}
return 1;
}
}
} }
} return result;
return result;
} }

123
lua.h
View File

@@ -1,108 +1,121 @@
/* /*
** LUA - Linguagem para Usuarios de Aplicacao ** LUA - An Extensible Extension Language
** Grupo de Tecnologia em Computacao Grafica ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** TeCGraf - PUC-Rio ** e-mail: lua@tecgraf.puc-rio.br
** $Id: lua.h,v 3.20 1995/10/31 16:41:53 roberto Exp roberto $ ** $Id: lua.h,v 4.1 1997/04/03 18:26:08 roberto Exp roberto $
*/ */
#ifndef lua_h #ifndef lua_h
#define lua_h #define lua_h
#define LUA_VERSION "Lua 2.2" #define LUA_VERSION "Lua 3.0 (alpha)"
#define LUA_COPYRIGHT "Copyright (C) 1994, 1995 TeCGraf" #define LUA_COPYRIGHT "Copyright (C) 1994-1997 TeCGraf"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" #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_NOOBJECT 0
typedef void (*lua_CFunction) (void); typedef void (*lua_CFunction) (void);
typedef unsigned int lua_Object; typedef unsigned int lua_Object;
lua_Object lua_setfallback (char *name, lua_CFunction fallback); void lua_settagmethod (int tag, char *event, lua_CFunction method);
void lua_gettagmethod (int tag, char *event); /* out: method */
void lua_seterrormethod (lua_CFunction method);
int lua_newtag (void);
void lua_settag (int tag); /* In: object */
void lua_error (char *s); void lua_error (char *s);
int lua_dofile (char *filename); int lua_dofile (char *filename); /* Out: returns */
int lua_dostring (char *string); int lua_dostring (char *string); /* Out: returns */
int lua_callfunction (lua_Object function); int lua_callfunction (lua_Object f);
/* In: parameters; Out: returns */
int lua_call (char *funcname); int lua_call (char *funcname);
/* In: parameters; Out: returns */
void lua_beginblock (void); void lua_beginblock (void);
void lua_endblock (void); void lua_endblock (void);
lua_Object lua_getparam (int number); lua_Object lua_lua2C (int number);
#define lua_getresult(_) lua_getparam(_) #define lua_getparam(_) lua_lua2C(_)
#define lua_getresult(_) lua_lua2C(_)
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);
float lua_getnumber (lua_Object object); float lua_getnumber (lua_Object object);
char *lua_getstring (lua_Object object); char *lua_getstring (lua_Object object);
lua_CFunction lua_getcfunction (lua_Object object); lua_CFunction lua_getcfunction (lua_Object object);
void *lua_getuserdata (lua_Object object); void *lua_getbindata (lua_Object object);
int lua_getbindatasize (lua_Object object);
void lua_pushnil (void); void lua_pushnil (void);
void lua_pushnumber (float n); void lua_pushnumber (float n);
void lua_pushstring (char *s); void lua_pushstring (char *s);
void lua_pushliteral (char *s);
void lua_pushcfunction (lua_CFunction fn); void lua_pushcfunction (lua_CFunction fn);
void lua_pushbindata (void *buff, int size, int tag);
void lua_pushusertag (void *u, int tag); void lua_pushusertag (void *u, int tag);
void lua_pushobject (lua_Object object); void lua_pushobject (lua_Object object);
lua_Object lua_getglobal (char *name); 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); void lua_settable (void); /* In: table, index, value */
lua_Object lua_getsubscript (void); 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); int lua_ref (int lock); /* In: value */
void lua_pushlocked (int ref); lua_Object lua_getref (int ref);
void lua_unlock (int ref); void lua_pushref (int ref);
void lua_unref (int ref);
lua_Object lua_createtable (void); lua_Object lua_createtable (void);
/* =============================================================== */
/* some useful macros */ /* some useful macros */
#define lua_lockobject(o) (lua_pushobject(o), lua_lock()) #define lua_refobject(o,l) (lua_pushobject(o), lua_ref(l))
#define lua_register(n,f) (lua_pushcfunction(f), lua_storeglobal(n)) #define lua_register(n,f) (lua_pushcfunction(f), lua_setglobal(n))
#define lua_pushuserdata(u) lua_pushusertag(u, LUA_T_USERDATA) #define lua_pushuserdata(u) lua_pushusertag(u, 0)
#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)
/* for lua 1.1 compatibility. Avoid using these macros */ /* =============================================================== */
/* for compatibility with old versions. Avoid using these macros/functions */
#define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_getsubscript()) lua_Object lua_setfallback (char *event, lua_CFunction fallback);
#define lua_getfield(o,f) (lua_pushobject(o), lua_pushliteral(f), lua_getsubscript())
#define lua_storeglobal(n) lua_setglobal(n)
#define lua_type(o) (lua_tag(o))
void *lua_getuserdata (lua_Object object);
#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_pushliteral(f), lua_gettable())
#define lua_copystring(o) (strdup(lua_getstring(o))) #define lua_copystring(o) (strdup(lua_getstring(o)))
#define lua_getsubscript lua_gettable
#endif #endif

460
lua.stx
View File

@@ -1,12 +1,14 @@
%{ %{
char *rcs_luastx = "$Id: lua.stx,v 3.24 1995/10/26 14:21:56 roberto Exp roberto $"; char *rcs_luastx = "$Id: lua.stx,v 3.45 1997/03/06 17:30:55 roberto Exp roberto $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "mem.h" #include "luadebug.h"
#include "luamem.h"
#include "lex.h"
#include "opcode.h" #include "opcode.h"
#include "hash.h" #include "hash.h"
#include "inout.h" #include "inout.h"
@@ -30,7 +32,7 @@ int yyparse (void);
#endif #endif
static int maxcode; static int maxcode;
static int maxmain; static int maxmain;
static Long maxcurr; /* to allow maxcurr *= 2 without overflow */ static int maxcurr;
static Byte *funcCode = NULL; static Byte *funcCode = NULL;
static Byte **initcode; static Byte **initcode;
static Byte *basepc; static Byte *basepc;
@@ -44,90 +46,66 @@ static Long varbuffer[MAXVAR]; /* variables in an assignment list;
static int nvarbuffer=0; /* number of variables at a list */ static int nvarbuffer=0; /* number of variables at a list */
#define MAXLOCALS 32 #define MAXLOCALS 32
static Word localvar[MAXLOCALS]; /* store local variable names */ static TaggedString *localvar[MAXLOCALS]; /* store local variable names */
static int nlocalvar=0; /* number of local variables */ static int nlocalvar=0; /* number of local variables */
#define MAXFIELDS FIELDS_PER_FLUSH*2 #define MAXFIELDS FIELDS_PER_FLUSH*2
static Word fields[MAXFIELDS]; /* fieldnames to be flushed */
static int nfields=0;
int lua_debug = 0;
/* Internal functions */ /* Internal functions */
static void yyerror (char *s) static void yyerror (char *s)
{ {
static char msg[256]; luaI_syntaxerror(s);
sprintf (msg,"%s near \"%s\" at line %d in file `%s'", }
s, lua_lasttext (), lua_linenumber, lua_parsedfile);
lua_error (msg); static void check_space (int i)
{
if (pc+i>maxcurr-1) /* 1 byte free to code HALT of main code */
maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT);
} }
static void code_byte (Byte c) static void code_byte (Byte c)
{ {
if (pc>maxcurr-2) /* 1 byte free to code HALT of main code */ check_space(1);
{
if (maxcurr >= MAX_INT)
lua_error("code size overflow");
maxcurr *= 2;
if (maxcurr >= MAX_INT)
maxcurr = MAX_INT;
basepc = growvector(basepc, maxcurr, Byte);
}
basepc[pc++] = c; basepc[pc++] = c;
} }
static void code_word (Word n) static void code_word (Word n)
{ {
CodeWord code; check_space(sizeof(Word));
code.w = n; memcpy(basepc+pc, &n, sizeof(Word));
code_byte(code.m.c1); pc += sizeof(Word);
code_byte(code.m.c2);
} }
static void code_float (float n) static void code_float (real n)
{ {
CodeFloat code; check_space(sizeof(real));
code.f = n; memcpy(basepc+pc, &n, sizeof(real));
code_byte(code.m.c1); pc += sizeof(real);
code_byte(code.m.c2);
code_byte(code.m.c3);
code_byte(code.m.c4);
} }
static void code_code (TFunc *tf) static void code_code (TFunc *tf)
{ {
CodeCode code; check_space(sizeof(TFunc *));
code.tf = tf; memcpy(basepc+pc, &tf, sizeof(TFunc *));
code_byte(code.m.c1); pc += sizeof(TFunc *);
code_byte(code.m.c2);
code_byte(code.m.c3);
code_byte(code.m.c4);
} }
static void code_word_at (Byte *p, Word n) static void code_word_at (Byte *p, int n)
{ {
CodeWord code; Word w = n;
code.w = n; if (w != n)
*p++ = code.m.c1; yyerror("block too big");
*p++ = code.m.c2; memcpy(p, &w, sizeof(Word));
}
static void push_field (Word name)
{
if (nfields < MAXFIELDS)
fields[nfields++] = name;
else
lua_error ("too many fields in nested constructors");
} }
static void flush_record (int n) static void flush_record (int n)
{ {
int i;
if (n == 0) return; if (n == 0) return;
code_byte(STORERECORD); code_byte(STOREMAP);
code_byte(n); code_byte(n);
for (i=0; i<n; i++)
code_word(fields[--nfields]);
} }
static void flush_list (int m, int n) static void flush_list (int m, int n)
@@ -142,24 +120,24 @@ static void flush_list (int m, int n)
code_byte(m); code_byte(m);
} }
else else
lua_error ("list constructor too long"); yyerror ("list constructor too long");
code_byte(n); code_byte(n);
} }
static void add_localvar (Word name) static void store_localvar (TaggedString *name, int n)
{
if (nlocalvar < MAXLOCALS)
localvar[nlocalvar++] = name;
else
lua_error ("too many local variables");
}
static void store_localvar (Word name, int n)
{ {
if (nlocalvar+n < MAXLOCALS) if (nlocalvar+n < MAXLOCALS)
localvar[nlocalvar+n] = name; localvar[nlocalvar+n] = name;
else else
lua_error ("too many local variables"); yyerror ("too many local variables");
if (lua_debug)
luaI_registerlocalvar(name, lua_linenumber);
}
static void add_localvar (TaggedString *name)
{
store_localvar(name, 0);
nlocalvar++;
} }
static void add_varbuffer (Long var) static void add_varbuffer (Long var)
@@ -167,14 +145,25 @@ static void add_varbuffer (Long var)
if (nvarbuffer < MAXVAR) if (nvarbuffer < MAXVAR)
varbuffer[nvarbuffer++] = var; varbuffer[nvarbuffer++] = var;
else else
lua_error ("variable buffer overflow"); yyerror ("variable buffer overflow");
}
static void code_string (Word w)
{
code_byte(PUSHSTRING);
code_word(w);
}
static void code_constant (TaggedString *s)
{
code_string(luaI_findconstant(s));
} }
static void code_number (float f) static void code_number (float f)
{ {
Word i = (Word)f; Word i;
if (f == (float)i) /* f has an (short) integer value */ if (f >= 0 && f <= (float)MAX_WORD && (float)(i=(Word)f) == f) {
{ /* f has an (short) integer value */
if (i <= 2) code_byte(PUSH0 + i); if (i <= 2) code_byte(PUSH0 + i);
else if (i <= 255) else if (i <= 255)
{ {
@@ -197,7 +186,7 @@ static void code_number (float f)
/* /*
** Search a local name and if find return its index. If do not find return -1 ** Search a local name and if find return its index. If do not find return -1
*/ */
static int lua_localname (Word n) static int lua_localname (TaggedString *n)
{ {
int i; int i;
for (i=nlocalvar-1; i >= 0; i--) for (i=nlocalvar-1; i >= 0; i--)
@@ -322,6 +311,19 @@ static void adjust_mult_assign (int vars, Long exps, int temps)
lua_codeadjust(temps); lua_codeadjust(temps);
} }
static int close_parlist (int dots)
{
if (!dots)
lua_codeadjust(0);
else
{
code_byte(VARARGS);
code_byte(nlocalvar);
add_localvar(luaI_createfixedstring("arg"));
}
return lua_linenumber;
}
static void storesinglevar (Long v) static void storesinglevar (Long v)
{ {
if (v > 0) /* global var */ if (v > 0) /* global var */
@@ -388,7 +390,6 @@ static void codeIf (Long thenAdd, Long elseAdd)
*/ */
void lua_parse (TFunc *tf) void lua_parse (TFunc *tf)
{ {
lua_debug = 0;
initcode = &(tf->code); initcode = &(tf->code);
*initcode = newvector(CODE_BLOCK, Byte); *initcode = newvector(CODE_BLOCK, Byte);
maincode = 0; maincode = 0;
@@ -416,10 +417,10 @@ void lua_parse (TFunc *tf)
Word vWord; Word vWord;
Long vLong; Long vLong;
TFunc *pFunc; TFunc *pFunc;
TreeNode *pNode; TaggedString *pTStr;
} }
%start functionlist %start chunk
%token WRONGTOKEN %token WRONGTOKEN
%token NIL %token NIL
@@ -427,10 +428,10 @@ void lua_parse (TFunc *tf)
%token RETURN %token RETURN
%token LOCAL %token LOCAL
%token FUNCTION %token FUNCTION
%token DOTS
%token <vFloat> NUMBER %token <vFloat> NUMBER
%token <vWord> STRING %token <vWord> STRING
%token <pNode> NAME %token <pTStr> NAME
%token <vInt> DEBUG
%type <vLong> PrepJump %type <vLong> PrepJump
%type <vLong> exprlist, exprlist1 /* if > 0, points to function return %type <vLong> exprlist, exprlist1 /* if > 0, points to function return
@@ -441,7 +442,7 @@ void lua_parse (TFunc *tf)
%type <vInt> fieldlist, localdeclist, decinit %type <vInt> fieldlist, localdeclist, decinit
%type <vInt> ffieldlist, ffieldlist1, semicolonpart %type <vInt> ffieldlist, ffieldlist1, semicolonpart
%type <vInt> lfieldlist, lfieldlist1 %type <vInt> lfieldlist, lfieldlist1
%type <vInt> parlist %type <vInt> parlist, parlist1, par
%type <vLong> var, singlevar, funcname %type <vLong> var, singlevar, funcname
%type <pFunc> body %type <pFunc> body
@@ -456,15 +457,12 @@ void lua_parse (TFunc *tf)
%% /* beginning of rules section */ %% /* beginning of rules section */
chunk : chunklist ret ;
functionlist : /* empty */ chunklist : /* empty */
| functionlist globalstat | chunklist stat sc
| functionlist function | chunklist function
; ;
globalstat : stat sc
| setdebug
;
function : FUNCTION funcname body function : FUNCTION funcname body
{ {
@@ -477,11 +475,10 @@ function : FUNCTION funcname body
funcname : var { $$ =$1; init_func(); } funcname : var { $$ =$1; init_func(); }
| varexp ':' NAME | varexp ':' NAME
{ {
code_byte(PUSHSTRING); code_constant($3);
code_word(luaI_findconstant($3));
$$ = 0; /* indexed variable */ $$ = 0; /* indexed variable */
init_func(); init_func();
add_localvar(luaI_findsymbolbyname("self")); add_localvar(luaI_createfixedstring("self"));
} }
; ;
@@ -489,11 +486,14 @@ body : '(' parlist ')' block END
{ {
codereturn(); codereturn();
$$ = new(TFunc); $$ = new(TFunc);
luaI_initTFunc($$);
$$->size = pc; $$->size = pc;
$$->code = newvector(pc, Byte); $$->code = newvector(pc, Byte);
$$->fileName = lua_parsedfile; $$->fileName = lua_parsedfile;
$$->lineDefined = $2; $$->lineDefined = $2;
memcpy($$->code, basepc, pc*sizeof(Byte)); memcpy($$->code, basepc, pc*sizeof(Byte));
if (lua_debug)
luaI_closelocalvars($$);
/* save func values */ /* save func values */
funcCode = basepc; maxcode=maxcurr; funcCode = basepc; maxcode=maxcurr;
#if LISTING #if LISTING
@@ -537,7 +537,7 @@ stat : IF expr1 THEN PrepJump block PrepJump elsepart END
lua_codeadjust (0); lua_codeadjust (0);
} }
} }
| functioncall | functioncall {;}
| LOCAL localdeclist decinit | LOCAL localdeclist decinit
{ nlocalvar += $2; { nlocalvar += $2;
adjust_mult_assign($2, $3, 0); adjust_mult_assign($2, $3, 0);
@@ -554,7 +554,11 @@ block : {$<vInt>$ = nlocalvar;} statlist ret
{ {
if (nlocalvar != $<vInt>1) if (nlocalvar != $<vInt>1)
{ {
nlocalvar = $<vInt>1; if (lua_debug)
for (; nlocalvar > $<vInt>1; nlocalvar--)
luaI_unregisterlocalvar(lua_linenumber);
else
nlocalvar = $<vInt>1;
lua_codeadjust (0); lua_codeadjust (0);
} }
} }
@@ -574,6 +578,7 @@ PrepJump : /* empty */
code_byte(0); /* open space */ code_byte(0); /* open space */
code_word (0); code_word (0);
} }
;
expr1 : expr { adjust_functioncall($1, 1); } expr1 : expr { adjust_functioncall($1, 1); }
; ;
@@ -597,9 +602,8 @@ expr : '(' expr ')' { $$ = $2; }
| NUMBER { code_number($1); $$ = 0; } | NUMBER { code_number($1); $$ = 0; }
| STRING | STRING
{ {
code_byte(PUSHSTRING); code_string($1);
code_word($1); $$ = 0;
$$ = 0;
} }
| NIL {code_byte(PUSHNIL); $$ = 0; } | NIL {code_byte(PUSHNIL); $$ = 0; }
| functioncall { $$ = $1; } | functioncall { $$ = $1; }
@@ -668,19 +672,22 @@ exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; }
} }
; ;
parlist : /* empty */ { lua_codeadjust(0); $$ = lua_linenumber; } parlist : /* empty */ { $$ = close_parlist(0); }
| parlist1 { lua_codeadjust(0); $$ = lua_linenumber; } | parlist1 { $$ = close_parlist($1); }
; ;
parlist1 : NAME parlist1 : par { $$ = $1; }
{ | parlist1 ',' par
add_localvar(luaI_findsymbol($1)); {
} if ($1)
| parlist1 ',' NAME lua_error("invalid parameter list");
{ $$ = $3;
add_localvar(luaI_findsymbol($3)); }
}
; ;
par : NAME { add_localvar($1); $$ = 0; }
| DOTS { $$ = 1; }
;
fieldlist : lfieldlist fieldlist : lfieldlist
{ flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); } { flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); }
@@ -712,12 +719,13 @@ ffieldlist1 : ffield {$$=1;}
} }
; ;
ffield : NAME '=' expr1 ffield : ffieldkey '=' expr1
{
push_field(luaI_findconstant($1));
}
; ;
ffieldkey : '[' expr1 ']'
| NAME { code_constant($1); }
;
lfieldlist : /* empty */ { $$ = 0; } lfieldlist : /* empty */ { $$ = 0; }
| lfieldlist1 lastcomma { $$ = $1; } | lfieldlist1 lastcomma { $$ = $1; }
; ;
@@ -751,18 +759,16 @@ var : singlevar { $$ = $1; }
} }
| varexp '.' NAME | varexp '.' NAME
{ {
code_byte(PUSHSTRING); code_constant($3);
code_word(luaI_findconstant($3)); $$ = 0; /* indexed variable */
$$ = 0; /* indexed variable */
} }
; ;
singlevar : NAME singlevar : NAME
{ {
Word s = luaI_findsymbol($1); int local = lua_localname($1);
int local = lua_localname (s);
if (local == -1) /* global var */ if (local == -1) /* global var */
$$ = s + 1; /* return positive value */ $$ = luaI_findsymbol($1)+1; /* return positive value */
else else
$$ = -(local+1); /* return negative value */ $$ = -(local+1); /* return negative value */
} }
@@ -771,10 +777,10 @@ singlevar : NAME
varexp : var { lua_pushvar($1); } varexp : var { lua_pushvar($1); }
; ;
localdeclist : NAME {store_localvar(luaI_findsymbol($1), 0); $$ = 1;} localdeclist : NAME {store_localvar($1, 0); $$ = 1;}
| localdeclist ',' NAME | localdeclist ',' NAME
{ {
store_localvar(luaI_findsymbol($3), $1); store_localvar($3, $1);
$$ = $1+1; $$ = $1+1;
} }
; ;
@@ -783,232 +789,4 @@ decinit : /* empty */ { $$ = 0; }
| '=' exprlist1 { $$ = $2; } | '=' exprlist1 { $$ = $2; }
; ;
setdebug : DEBUG { lua_debug = $1; }
;
%% %%
#if LISTING
static void PrintCode (Byte *code, Byte *end)
{
Byte *p = code;
printf ("\n\nCODE\n");
while (p != end)
{
switch ((OpCode)*p)
{
case PUSHNIL: printf ("%d PUSHNIL\n", (p++)-code); break;
case PUSH0: case PUSH1: case PUSH2:
printf ("%d PUSH%c\n", p-code, *p-PUSH0+'0');
p++;
break;
case PUSHBYTE:
printf ("%d PUSHBYTE %d\n", p-code, *(++p));
p++;
break;
case PUSHWORD:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d PUSHWORD %d\n", n, c.w);
}
break;
case PUSHFLOAT:
{
CodeFloat c;
int n = p-code;
p++;
get_float(c,p);
printf ("%d PUSHFLOAT %f\n", n, c.f);
}
break;
case PUSHSTRING:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d PUSHSTRING %d\n", n, c.w);
}
break;
case PUSHFUNCTION:
{
CodeCode c;
int n = p-code;
p++;
get_code(c,p);
printf ("%d PUSHFUNCTION %p\n", n, c.tf);
}
break;
case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: case PUSHLOCAL3:
case PUSHLOCAL4: case PUSHLOCAL5: case PUSHLOCAL6: case PUSHLOCAL7:
case PUSHLOCAL8: case PUSHLOCAL9:
printf ("%d PUSHLOCAL%c\n", p-code, *p-PUSHLOCAL0+'0');
p++;
break;
case PUSHLOCAL: printf ("%d PUSHLOCAL %d\n", p-code, *(++p));
p++;
break;
case PUSHGLOBAL:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d PUSHGLOBAL %d\n", n, c.w);
}
break;
case PUSHINDEXED: printf ("%d PUSHINDEXED\n", (p++)-code); break;
case STORELOCAL0: case STORELOCAL1: case STORELOCAL2: case STORELOCAL3:
case STORELOCAL4: case STORELOCAL5: case STORELOCAL6: case STORELOCAL7:
case STORELOCAL8: case STORELOCAL9:
printf ("%d STORELOCAL%c\n", p-code, *p-STORELOCAL0+'0');
p++;
break;
case STORELOCAL:
printf ("%d STORELOCAL %d\n", p-code, *(++p));
p++;
break;
case STOREGLOBAL:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d STOREGLOBAL %d\n", n, c.w);
}
break;
case PUSHSELF:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d PUSHSELF %d\n", n, c.w);
}
break;
case STOREINDEXED0: printf ("%d STOREINDEXED0\n", (p++)-code); break;
case STOREINDEXED: printf ("%d STOREINDEXED %d\n", p-code, *(++p));
p++;
break;
case STORELIST0:
printf("%d STORELIST0 %d\n", p-code, *(++p));
p++;
break;
case STORELIST:
printf("%d STORELIST %d %d\n", p-code, *(p+1), *(p+2));
p+=3;
break;
case STORERECORD:
printf("%d STORERECORD %d\n", p-code, *(++p));
p += *p*sizeof(Word) + 1;
break;
case ADJUST0: printf ("%d ADJUST0\n", (p++)-code); break;
case ADJUST:
printf ("%d ADJUST %d\n", p-code, *(++p));
p++;
break;
case CREATEARRAY:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d CREATEARRAY %d\n", n, c.w);
break;
}
case EQOP: printf ("%d EQOP\n", (p++)-code); break;
case LTOP: printf ("%d LTOP\n", (p++)-code); break;
case LEOP: printf ("%d LEOP\n", (p++)-code); break;
case ADDOP: printf ("%d ADDOP\n", (p++)-code); break;
case SUBOP: printf ("%d SUBOP\n", (p++)-code); break;
case MULTOP: printf ("%d MULTOP\n", (p++)-code); break;
case DIVOP: printf ("%d DIVOP\n", (p++)-code); break;
case POWOP: printf ("%d POWOP\n", (p++)-code); break;
case CONCOP: printf ("%d CONCOP\n", (p++)-code); break;
case MINUSOP: printf ("%d MINUSOP\n", (p++)-code); break;
case NOTOP: printf ("%d NOTOP\n", (p++)-code); break;
case ONTJMP:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d ONTJMP %d\n", n, c.w);
}
break;
case ONFJMP:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d ONFJMP %d\n", n, c.w);
}
break;
case JMP:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d JMP %d\n", n, c.w);
}
break;
case UPJMP:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d UPJMP %d\n", n, c.w);
}
break;
case IFFJMP:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d IFFJMP %d\n", n, c.w);
}
break;
case IFFUPJMP:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d IFFUPJMP %d\n", n, c.w);
}
break;
case POP: printf ("%d POP\n", (p++)-code); break;
case CALLFUNC:
printf ("%d CALLFUNC %d %d\n", p-code, *(p+1), *(p+2));
p+=3;
break;
case RETCODE0: printf ("%d RETCODE0\n", (p++)-code); break;
case RETCODE:
printf ("%d RETCODE %d\n", p-code, *(++p));
p++;
break;
case SETLINE:
{
CodeWord c;
int n = p-code;
p++;
get_word(c,p);
printf ("%d SETLINE %d\n", n, c.w);
}
break;
default: printf ("%d Cannot happen: code %d\n", (p++)-code, *(p-1)); break;
}
}
}
#endif

View File

@@ -2,7 +2,7 @@
** LUA - Linguagem para Usuarios de Aplicacao ** LUA - Linguagem para Usuarios de Aplicacao
** Grupo de Tecnologia em Computacao Grafica ** Grupo de Tecnologia em Computacao Grafica
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: luadebug.h,v 1.1 1995/10/17 14:12:45 roberto Exp roberto $ ** $Id: luadebug.h,v 1.5 1996/02/08 17:03:20 roberto Exp roberto $
*/ */
@@ -11,10 +11,21 @@
#include "lua.h" #include "lua.h"
lua_Object lua_stackedfunction(int level); typedef lua_Object lua_Function;
void lua_funcinfo (lua_Object func, char **filename, int *linedefined);
int lua_currentline (lua_Object func);
char *getobjname (lua_Object o, char **name);
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 **filename, 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);
extern lua_LHFunction lua_linehook;
extern lua_CHFunction lua_callhook;
extern int lua_debug;
#endif #endif

View File

@@ -2,21 +2,28 @@
** Libraries to be used in LUA programs ** Libraries to be used in LUA programs
** Grupo de Tecnologia em Computacao Grafica ** Grupo de Tecnologia em Computacao Grafica
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: lualib.h,v 1.3 1994/12/13 15:59:16 roberto Exp roberto $ ** $Id: lualib.h,v 1.12 1997/03/18 15:30:50 roberto Exp roberto $
*/ */
#ifndef lualib_h #ifndef lualib_h
#define lualib_h #define lualib_h
#include "lua.h"
void iolib_open (void); void iolib_open (void);
void strlib_open (void); void strlib_open (void);
void mathlib_open (void); void mathlib_open (void);
/* auxiliar functions (private) */ /* auxiliar functions (private) */
void lua_arg_error(char *funcname);
char *lua_check_string (int numArg, char *funcname); char *luaI_addchar (int c);
float lua_check_number (int numArg, char *funcname); void luaI_emptybuff (void);
void luaI_addquoted (char *s);
char *luaL_item_end (char *p);
int luaL_singlematch (int c, char *p);
#endif #endif

155
luamem.c
View File

@@ -3,42 +3,157 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_mem = "$Id: mem.c,v 1.4 1995/01/13 22:11:12 roberto Exp roberto $"; char *rcs_luamem = "$Id: luamem.c,v 1.15 1997/03/31 14:17:09 roberto Exp roberto $";
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "mem.h" #include "luamem.h"
#include "lua.h" #include "lua.h"
#define DEBUG 0
#if !DEBUG
void luaI_free (void *block) void luaI_free (void *block)
{ {
*((int *)block) = -1; /* to catch errors */ if (block)
free(block); {
} *((char *)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 *luaI_realloc (void *oldblock, unsigned long size)
{ {
void *block = realloc(oldblock, (size_t)size); void *block;
size_t s = (size_t)size;
if (s != size)
lua_error("Allocation Error: Block too big");
block = oldblock ? realloc(oldblock, s) : malloc(s);
if (block == NULL) if (block == NULL)
lua_error("not enough memory"); lua_error(memEM);
return block; return block;
} }
char *luaI_strdup (char *str) int luaI_growvector (void **block, unsigned long nelems, int size,
char *errormsg, unsigned long limit)
{ {
char *newstr = luaI_malloc(strlen(str)+1); if (nelems >= limit)
strcpy(newstr, str); lua_error(errormsg);
return newstr; nelems = (nelems == 0) ? 20 : nelems*2;
if (nelems > limit)
nelems = limit;
*block = luaI_realloc(*block, nelems*size);
return (int)nelems;
} }
void* luaI_buffer (unsigned long size)
{
static unsigned long buffsize = 0;
static char* buffer = NULL;
if (size > buffsize)
buffer = luaI_realloc(buffer, buffsize=size);
return buffer;
}
#else
/* DEBUG */
#include <stdio.h>
# define assert(ex) {if (!(ex)){(void)fprintf(stderr, \
"Assertion failed: file \"%s\", line %d\n", __FILE__, __LINE__);exit(1);}}
#define MARK 55
static unsigned long numblocks = 0;
static unsigned long totalmem = 0;
static void message (void)
{
#define inrange(x,y) ((x) < (((y)*3)/2) && (x) > (((y)*2)/3))
static int count = 0;
static unsigned long lastnumblocks = 0;
static unsigned long lasttotalmem = 0;
if (!inrange(numblocks, lastnumblocks) || !inrange(totalmem, lasttotalmem)
|| count++ >= 5000)
{
fprintf(stderr,"blocks = %lu mem = %luK\n", numblocks, totalmem/1000);
count = 0;
lastnumblocks = numblocks;
lasttotalmem = totalmem;
}
}
void luaI_free (void *block)
{
if (block)
{
unsigned long *b = (unsigned long *)block - 1;
unsigned long size = *b;
assert(*(((char *)b)+size+sizeof(unsigned long)) == MARK);
numblocks--;
totalmem -= size;
free(b);
message();
}
}
void *luaI_realloc (void *oldblock, unsigned long size)
{
unsigned long *block;
unsigned long realsize = sizeof(unsigned long)+size+sizeof(char);
if (realsize != (size_t)realsize)
lua_error("Allocation Error: Block too big");
if (oldblock)
{
unsigned long *b = (unsigned long *)oldblock - 1;
unsigned long oldsize = *b;
assert(*(((char *)b)+oldsize+sizeof(unsigned long)) == MARK);
totalmem -= oldsize;
numblocks--;
block = (unsigned long *)realloc(b, realsize);
}
else
block = (unsigned long *)malloc(realsize);
if (block == NULL)
lua_error("not enough memory");
totalmem += size;
numblocks++;
*block = size;
*(((char *)block)+size+sizeof(unsigned long)) = MARK;
message();
return block+1;
}
int luaI_growvector (void **block, unsigned long nelems, int size,
char *errormsg, unsigned long limit)
{
if (nelems >= limit)
lua_error(errormsg);
nelems = (nelems == 0) ? 20 : nelems*2;
if (nelems > limit)
nelems = limit;
*block = luaI_realloc(*block, nelems*size);
return (int)nelems;
}
void* luaI_buffer (unsigned long size)
{
static unsigned long buffsize = 0;
static char* buffer = NULL;
if (size > buffsize)
buffer = luaI_realloc(buffer, buffsize=size);
return buffer;
}
#endif

View File

@@ -1,25 +1,39 @@
/* /*
** mem.c ** mem.c
** memory manager for lua ** memory manager for lua
** $Id: mem.h,v 1.1 1994/11/16 17:38:08 roberto Stab roberto $ ** $Id: luamem.h,v 1.8 1996/05/24 14:31:10 roberto Exp roberto $
*/ */
#ifndef mem_h #ifndef luamem_h
#define mem_h #define luamem_h
#ifndef NULL #ifndef NULL
#define NULL 0 #define NULL 0
#endif #endif
/* memory error messages */
#define codeEM "code size overflow"
#define symbolEM "symbol table overflow"
#define constantEM "constant table overflow"
#define stackEM "stack size overflow"
#define lexEM "lex buffer overflow"
#define refEM "reference table overflow"
#define tableEM "table overflow"
#define memEM "not enough memory"
void luaI_free (void *block); void luaI_free (void *block);
void *luaI_malloc (unsigned long size);
void *luaI_realloc (void *oldblock, unsigned long size); void *luaI_realloc (void *oldblock, unsigned long size);
void *luaI_buffer (unsigned long size);
int luaI_growvector (void **block, unsigned long nelems, int size,
char *errormsg, unsigned long limit);
char *luaI_strdup (char *str); #define luaI_malloc(s) luaI_realloc(NULL, (s))
#define new(s) ((s *)luaI_malloc(sizeof(s))) #define new(s) ((s *)luaI_malloc(sizeof(s)))
#define newvector(n,s) ((s *)luaI_malloc((n)*sizeof(s))) #define newvector(n,s) ((s *)luaI_malloc((n)*sizeof(s)))
#define growvector(old,n,s) ((s *)luaI_realloc(old,(n)*sizeof(s))) #define growvector(old,n,s,e,l) \
(luaI_growvector((void**)old,n,sizeof(s),e,l))
#endif #endif

View File

@@ -1,12 +1,16 @@
# $Id: makefile,v 1.15 1995/10/17 18:16:58 roberto Exp roberto $ # $Id: makefile,v 1.32 1997/03/31 20:58:42 roberto Exp roberto $
#configuration #configuration
# define (undefine) POPEN if your system (does not) support piped I/O # 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) NOSTRERROR if your system does NOT have function "strerror"
# (although this is ANSI, SunOS does not comply; so, add "-DNOSTRERROR" on SunOS)
CONFIG = -DPOPEN -D_POSIX_SOURCE
# Compilation parameters # Compilation parameters
CC = gcc 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 -fomit-frame-pointer
#CC = acc #CC = acc
#CFLAGS = -fast -I/usr/5include #CFLAGS = -fast -I/usr/5include
@@ -14,6 +18,7 @@ CFLAGS = $(CONFIG) -I/usr/5include -Wall -Wmissing-prototypes -Wshadow -ansi -O2
AR = ar AR = ar
ARFLAGS = rvl ARFLAGS = rvl
# Aplication modules # Aplication modules
LUAOBJS = \ LUAOBJS = \
parser.o \ parser.o \
@@ -24,8 +29,10 @@ LUAOBJS = \
inout.o \ inout.o \
tree.o \ tree.o \
fallback.o \ fallback.o \
mem.o \ luamem.o \
func.o func.o \
undump.o \
auxlib.o
LIBOBJS = \ LIBOBJS = \
iolib.o \ iolib.o \
@@ -33,50 +40,66 @@ LIBOBJS = \
strlib.o strlib.o
lua : lua.o lua.a lualib.a lua : lua.o liblua.a liblualib.a
$(CC) $(CFLAGS) -o $@ lua.o lua.a lualib.a -lm $(CC) $(CFLAGS) -o $@ lua.o -L. -llua -llualib -lm
lua.a : parser.o $(LUAOBJS) liblua.a : $(LUAOBJS)
$(AR) $(ARFLAGS) $@ $? $(AR) $(ARFLAGS) $@ $?
ranlib lua.a ranlib $@
lualib.a : $(LIBOBJS) liblualib.a : $(LIBOBJS)
$(AR) $(ARFLAGS) $@ $? $(AR) $(ARFLAGS) $@ $?
ranlib $@ ranlib $@
liblua.so.1.0 : lua.o liblua.so.1.0 : lua.o
ld -o liblua.so.1.0 $(LUAOBJS) ld -o liblua.so.1.0 $(LUAOBJS)
y.tab.c y.tab.h : lua.stx
yacc -d lua.stx
parser.c : lua.stx parser.c : y.tab.c
yacc++ -d lua.stx ; mv -f y.tab.c parser.c ; mv -f y.tab.h parser.h sed -e 's/yy/luaY_/g' -e 's/malloc\.h/stdlib\.h/g' y.tab.c > parser.c
parser.h : y.tab.h
sed -e 's/yy/luaY_/g' y.tab.h > parser.h
clear : clear :
rcsclean rcsclean
rm -f *.o rm -f *.o
rm -f parser.c parser.h rm -f parser.c parser.h y.tab.c y.tab.h
co lua.h lualib.h luadebug.h co lua.h lualib.h luadebug.h
% : RCS/%,v
%.h : RCS/%.h,v
co $@
%.c : RCS/%.c,v
co $@ co $@
fallback.o : fallback.c mem.h fallback.h opcode.h lua.h types.h tree.h func.h auxlib.o: auxlib.c lua.h auxlib.h
func.o : func.c table.h tree.h types.h opcode.h lua.h func.h mem.h fallback.o: fallback.c auxlib.h lua.h luamem.h fallback.h opcode.h \
hash.o : hash.c mem.h opcode.h lua.h types.h tree.h func.h hash.h table.h types.h tree.h func.h table.h hash.h
inout.o : inout.c mem.h opcode.h lua.h types.h tree.h func.h hash.h inout.h \ func.o: func.c luadebug.h lua.h table.h tree.h types.h opcode.h func.h \
table.h luamem.h
iolib.o : iolib.c lua.h lualib.h luadebug.h hash.o: hash.c luamem.h opcode.h lua.h types.h tree.h func.h hash.h \
lex.o : lex.c mem.h tree.h types.h table.h opcode.h lua.h func.h inout.h parser.h \ table.h auxlib.h
ugly.h inout.o: inout.c auxlib.h lua.h lex.h opcode.h types.h tree.h func.h \
lua.o : lua.c lua.h lualib.h inout.h table.h hash.h luamem.h fallback.h
mathlib.o : mathlib.c lualib.h lua.h iolib.o: iolib.c lua.h auxlib.h luadebug.h lualib.h
mem.o : mem.c mem.h lua.h lex.o: lex.c auxlib.h lua.h luamem.h tree.h types.h table.h opcode.h \
opcode.o : opcode.c mem.h opcode.h lua.h types.h tree.h func.h hash.h inout.h \ func.h lex.h inout.h luadebug.h parser.h
table.h fallback.h luadebug.h lua.o: lua.c lua.h lualib.h
parser.o : parser.c mem.h opcode.h lua.h types.h tree.h func.h hash.h inout.h \ luamem.o: luamem.c luamem.h lua.h
table.h mathlib.o: mathlib.c lualib.h lua.h auxlib.h
strlib.o : strlib.c lua.h lualib.h opcode.o: opcode.c luadebug.h lua.h luamem.h opcode.h types.h tree.h \
table.o : table.c mem.h opcode.h lua.h types.h tree.h func.h hash.h table.h \ func.h hash.h inout.h table.h fallback.h undump.h auxlib.h
inout.h fallback.h parser.o: parser.c luadebug.h lua.h luamem.h lex.h opcode.h types.h \
tree.o : tree.c mem.h lua.h tree.h types.h table.h opcode.h func.h tree.h func.h hash.h inout.h table.h
strlib.o: strlib.c lua.h auxlib.h lualib.h
table.o: table.c luamem.h auxlib.h lua.h opcode.h types.h tree.h \
func.h hash.h table.h inout.h fallback.h luadebug.h
tree.o: tree.c luamem.h lua.h tree.h types.h lex.h hash.h opcode.h \
func.h table.h fallback.h
undump.o: undump.c opcode.h lua.h types.h tree.h func.h luamem.h \
table.h undump.h

1947
manual.tex

File diff suppressed because it is too large Load Diff

133
mathlib.c
View File

@@ -3,12 +3,13 @@
** Mathematics library to LUA ** Mathematics library to LUA
*/ */
char *rcs_mathlib="$Id: mathlib.c,v 1.12 1995/10/09 12:48:38 roberto Exp roberto $"; char *rcs_mathlib="$Id: mathlib.c,v 1.22 1997/04/04 22:24:51 roberto Exp roberto $";
#include <stdio.h> /* NULL */ #include <stdlib.h>
#include <math.h> #include <math.h>
#include "lualib.h" #include "lualib.h"
#include "auxlib.h"
#include "lua.h" #include "lua.h"
#ifndef PI #ifndef PI
@@ -19,7 +20,7 @@ char *rcs_mathlib="$Id: mathlib.c,v 1.12 1995/10/09 12:48:38 roberto Exp roberto
static void math_abs (void) static void math_abs (void)
{ {
double d = lua_check_number(1, "abs"); double d = luaL_check_number(1);
if (d < 0) d = -d; if (d < 0) d = -d;
lua_pushnumber (d); lua_pushnumber (d);
} }
@@ -27,7 +28,7 @@ static void math_abs (void)
static void math_sin (void) static void math_sin (void)
{ {
double d = lua_check_number(1, "sin"); double d = luaL_check_number(1);
lua_pushnumber (sin(TORAD(d))); lua_pushnumber (sin(TORAD(d)));
} }
@@ -35,7 +36,7 @@ static void math_sin (void)
static void math_cos (void) static void math_cos (void)
{ {
double d = lua_check_number(1, "cos"); double d = luaL_check_number(1);
lua_pushnumber (cos(TORAD(d))); lua_pushnumber (cos(TORAD(d)));
} }
@@ -43,98 +44,82 @@ static void math_cos (void)
static void math_tan (void) static void math_tan (void)
{ {
double d = lua_check_number(1, "tan"); double d = luaL_check_number(1);
lua_pushnumber (tan(TORAD(d))); lua_pushnumber (tan(TORAD(d)));
} }
static void math_asin (void) static void math_asin (void)
{ {
double d = lua_check_number(1, "asin"); double d = luaL_check_number(1);
lua_pushnumber (TODEGREE(asin(d))); lua_pushnumber (TODEGREE(asin(d)));
} }
static void math_acos (void) static void math_acos (void)
{ {
double d = lua_check_number(1, "acos"); double d = luaL_check_number(1);
lua_pushnumber (TODEGREE(acos(d))); lua_pushnumber (TODEGREE(acos(d)));
} }
static void math_atan (void) static void math_atan (void)
{ {
double d = lua_check_number(1, "atan"); double d = luaL_check_number(1);
lua_pushnumber (TODEGREE(atan(d))); lua_pushnumber (TODEGREE(atan(d)));
} }
static void math_atan2 (void) static void math_atan2 (void)
{ {
double d1 = lua_check_number(1, "atan2"); double d1 = luaL_check_number(1);
double d2 = lua_check_number(2, "atan2"); double d2 = luaL_check_number(2);
lua_pushnumber (TODEGREE(atan2(d1, d2))); lua_pushnumber (TODEGREE(atan2(d1, d2)));
} }
static void math_ceil (void) static void math_ceil (void)
{ {
double d = lua_check_number(1, "ceil"); double d = luaL_check_number(1);
lua_pushnumber (ceil(d)); lua_pushnumber (ceil(d));
} }
static void math_floor (void) static void math_floor (void)
{ {
double d = lua_check_number(1, "floor"); double d = luaL_check_number(1);
lua_pushnumber (floor(d)); lua_pushnumber (floor(d));
} }
static void math_mod (void) static void math_mod (void)
{ {
int d1 = (int)lua_check_number(1, "mod"); float x = luaL_check_number(1);
int d2 = (int)lua_check_number(2, "mod"); float y = luaL_check_number(2);
lua_pushnumber (d1%d2); lua_pushnumber(fmod(x, y));
} }
static void math_sqrt (void) static void math_sqrt (void)
{ {
double d = lua_check_number(1, "sqrt"); double d = luaL_check_number(1);
lua_pushnumber (sqrt(d)); lua_pushnumber (sqrt(d));
} }
static int old_pow;
static void math_pow (void) static void math_pow (void)
{ {
lua_Object o1 = lua_getparam (1); double d1 = luaL_check_number(1);
lua_Object o2 = lua_getparam (2); double d2 = luaL_check_number(2);
lua_Object op = lua_getparam(3); lua_pushnumber(pow(d1,d2));
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) static void math_min (void)
{ {
int i=1; int i=1;
double dmin = lua_check_number(i, "min"); double dmin = luaL_check_number(i);
while (lua_getparam(++i) != LUA_NOOBJECT) while (lua_getparam(++i) != LUA_NOOBJECT)
{ {
double d = lua_check_number(i, "min"); double d = luaL_check_number(i);
if (d < dmin) dmin = d; if (d < dmin) dmin = d;
} }
lua_pushnumber (dmin); lua_pushnumber (dmin);
@@ -143,10 +128,10 @@ static void math_min (void)
static void math_max (void) static void math_max (void)
{ {
int i=1; int i=1;
double dmax = lua_check_number(i, "max"); double dmax = luaL_check_number(i);
while (lua_getparam(++i) != LUA_NOOBJECT) while (lua_getparam(++i) != LUA_NOOBJECT)
{ {
double d = lua_check_number(i, "max"); double d = luaL_check_number(i);
if (d > dmax) dmax = d; if (d > dmax) dmax = d;
} }
lua_pushnumber (dmax); lua_pushnumber (dmax);
@@ -154,59 +139,77 @@ static void math_max (void)
static void math_log (void) static void math_log (void)
{ {
double d = lua_check_number(1, "log"); double d = luaL_check_number(1);
lua_pushnumber (log(d)); lua_pushnumber (log(d));
} }
static void math_log10 (void) static void math_log10 (void)
{ {
double d = lua_check_number(1, "log10"); double d = luaL_check_number(1);
lua_pushnumber (log10(d)); lua_pushnumber (log10(d));
} }
static void math_exp (void) static void math_exp (void)
{ {
double d = lua_check_number(1, "exp"); double d = luaL_check_number(1);
lua_pushnumber (exp(d)); lua_pushnumber (exp(d));
} }
static void math_deg (void) static void math_deg (void)
{ {
float d = lua_check_number(1, "deg"); float d = luaL_check_number(1);
lua_pushnumber (d*180./PI); lua_pushnumber (d*180./PI);
} }
static void math_rad (void) static void math_rad (void)
{ {
float d = lua_check_number(1, "rad"); float d = luaL_check_number(1);
lua_pushnumber (d/180.*PI); lua_pushnumber (d/180.*PI);
} }
static void math_random (void)
{
lua_pushnumber((double)(rand()%RAND_MAX) / (double)RAND_MAX);
}
static void math_randomseed (void)
{
srand(luaL_check_number(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},
{"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 ** Open math library
*/ */
void mathlib_open (void) void mathlib_open (void)
{ {
lua_register ("abs", math_abs); luaL_openlib(mathlib, (sizeof(mathlib)/sizeof(mathlib[0])));
lua_register ("sin", math_sin); lua_settagmethod(0, "pow", math_pow);
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));
} }

1119
opcode.c

File diff suppressed because it is too large Load Diff

215
opcode.h
View File

@@ -1,6 +1,6 @@
/* /*
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: opcode.h,v 3.13 1995/10/17 11:58:41 roberto Exp roberto $ ** $Id: opcode.h,v 3.32 1997/04/04 22:24:51 roberto Exp roberto $
*/ */
#ifndef opcode_h #ifndef opcode_h
@@ -11,147 +11,160 @@
#include "tree.h" #include "tree.h"
#include "func.h" #include "func.h"
#ifndef real
#define real float
#endif
#define FIELDS_PER_FLUSH 40 #define FIELDS_PER_FLUSH 40
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER LUA_T"
*/
typedef enum
{
LUA_T_NIL = -9,
LUA_T_NUMBER = -8,
LUA_T_STRING = -7,
LUA_T_ARRAY = -6, /* array==table */
LUA_T_FUNCTION = -5,
LUA_T_CFUNCTION= -4,
LUA_T_MARK = -3,
LUA_T_CMARK = -2,
LUA_T_LINE = -1,
LUA_T_USERDATA = 0
} lua_Type;
typedef enum #define NUM_TYPES 10
{
PUSHNIL,
PUSH0, PUSH1, PUSH2, extern char *luaI_typenames[];
PUSHBYTE,
PUSHWORD, typedef enum {
PUSHFLOAT, /* name parm before after side effect
PUSHSTRING, -----------------------------------------------------------------------------*/
PUSHFUNCTION,
PUSHLOCAL0, PUSHLOCAL1, PUSHLOCAL2, PUSHLOCAL3, PUSHLOCAL4, PUSHNIL,/* - nil */
PUSHLOCAL5, PUSHLOCAL6, PUSHLOCAL7, PUSHLOCAL8, PUSHLOCAL9, PUSH0,/* - 0.0 */
PUSHLOCAL, PUSH1,/* - 1.0 */
PUSHGLOBAL, PUSH2,/* - 2.0 */
PUSHINDEXED, PUSHBYTE,/* b - (float)b */
PUSHSELF, PUSHWORD,/* w - (float)w */
STORELOCAL0, STORELOCAL1, STORELOCAL2, STORELOCAL3, STORELOCAL4, PUSHFLOAT,/* f - f */
STORELOCAL5, STORELOCAL6, STORELOCAL7, STORELOCAL8, STORELOCAL9, PUSHSTRING,/* w - STR[w] */
STORELOCAL, PUSHFUNCTION,/* p - FUN(p) */
STOREGLOBAL, PUSHLOCAL0,/* - LOC[0] */
STOREINDEXED0, PUSHLOCAL1,/* - LOC[1] */
STOREINDEXED, PUSHLOCAL2,/* - LOC[2] */
STORELIST0, PUSHLOCAL3,/* - LOC[3] */
STORELIST, PUSHLOCAL4,/* - LOC[4] */
STORERECORD, PUSHLOCAL5,/* - LOC[5] */
ADJUST0, PUSHLOCAL6,/* - LOC[6] */
ADJUST, PUSHLOCAL7,/* - LOC[7] */
CREATEARRAY, PUSHLOCAL8,/* - LOC[8] */
EQOP, PUSHLOCAL9,/* - LOC[9] */
LTOP, PUSHLOCAL,/* b - LOC[b] */
LEOP, PUSHGLOBAL,/* w - VAR[w] */
GTOP, PUSHINDEXED,/* i t t[i] */
GEOP, PUSHSELF,/* w t t t[STR[w]] */
ADDOP, STORELOCAL0,/* x - LOC[0]=x */
SUBOP, STORELOCAL1,/* x - LOC[1]=x */
MULTOP, STORELOCAL2,/* x - LOC[2]=x */
DIVOP, STORELOCAL3,/* x - LOC[3]=x */
POWOP, STORELOCAL4,/* x - LOC[4]=x */
CONCOP, STORELOCAL5,/* x - LOC[5]=x */
MINUSOP, STORELOCAL6,/* x - LOC[6]=x */
NOTOP, STORELOCAL7,/* x - LOC[7]=x */
ONTJMP, STORELOCAL8,/* x - LOC[8]=x */
ONFJMP, STORELOCAL9,/* x - LOC[9]=x */
JMP, STORELOCAL,/* b x - LOC[b]=x */
UPJMP, STOREGLOBAL,/* w x - VAR[w]=x */
IFFJMP, STOREINDEXED0,/* v i t - t[i]=v */
IFFUPJMP, STOREINDEXED,/* b v a_b...a_1 i t a_b...a_1 i t t[i]=v */
POP, STORELIST0,/* b v_b...v_1 t - t[i]=v_i */
CALLFUNC, STORELIST,/* b c v_b...v_1 t - t[i+c*FPF]=v_i */
RETCODE0, STORERECORD,/* b
RETCODE, w_b...w_1 v_b...v_1 t - t[STR[w_i]]=v_i */
SETLINE ADJUST0,/* - - TOP=BASE */
ADJUST,/* b - - TOP=BASE+b */
CREATEARRAY,/* w - newarray(size = w) */
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 */
ONTJMP,/* w x - (x!=nil)? PC+=w */
ONFJMP,/* w x - (x==nil)? PC+=w */
JMP,/* w - - PC+=w */
UPJMP,/* w - - PC-=w */
IFFJMP,/* w x - (x==nil)? PC+=w */
IFFUPJMP,/* w x - (x==nil)? PC-=w */
POP,/* x - */
CALLFUNC,/* b c v_b...v_1 f r_c...r_1 f(v1,...,v_b) */
RETCODE0,
RETCODE,/* b - - */
SETLINE,/* w - - LINE=w */
VARARGS,/* b v_b...v_1 {v_1...v_b;n=b} */
STOREMAP/* b v_b k_b ...v_1 k_1 t - t[k_i]=v_i */
} OpCode; } OpCode;
#define MULT_RET 255 #define MULT_RET 255
typedef void (*Cfunction) (void);
typedef int (*Input) (void);
typedef union typedef union
{ {
Cfunction f; lua_CFunction f;
real n; real n;
TaggedString *ts; TaggedString *ts;
TFunc *tf; TFunc *tf;
struct Hash *a; struct Hash *a;
void *u;
int i; int i;
} Value; } Value;
typedef struct Object typedef struct TObject
{ {
lua_Type tag; lua_Type ttype;
Value value; Value value;
} Object; } TObject;
typedef struct
{
Object object;
} Symbol;
/* Macros to access structure members */ /* Macros to access structure members */
#define tag(o) ((o)->tag) #define ttype(o) ((o)->ttype)
#define nvalue(o) ((o)->value.n) #define nvalue(o) ((o)->value.n)
#define svalue(o) ((o)->value.ts->str) #define svalue(o) ((o)->value.ts->str)
#define tsvalue(o) ((o)->value.ts) #define tsvalue(o) ((o)->value.ts)
#define avalue(o) ((o)->value.a) #define avalue(o) ((o)->value.a)
#define fvalue(o) ((o)->value.f) #define fvalue(o) ((o)->value.f)
#define uvalue(o) ((o)->value.u)
/* Macros to access symbol table */ /* Macros to access symbol table */
#define s_object(i) (lua_table[i].object) #define s_object(i) (lua_table[i].object)
#define s_tag(i) (tag(&s_object(i))) #define s_ttype(i) (ttype(&s_object(i)))
#define s_nvalue(i) (nvalue(&s_object(i))) #define s_nvalue(i) (nvalue(&s_object(i)))
#define s_svalue(i) (svalue(&s_object(i))) #define s_svalue(i) (svalue(&s_object(i)))
#define s_tsvalue(i) (tsvalue(&s_object(i)))
#define s_avalue(i) (avalue(&s_object(i))) #define s_avalue(i) (avalue(&s_object(i)))
#define s_fvalue(i) (fvalue(&s_object(i))) #define s_fvalue(i) (fvalue(&s_object(i)))
#define s_uvalue(i) (uvalue(&s_object(i))) #define s_uvalue(i) (uvalue(&s_object(i)))
typedef union #define get_word(code,pc) {memcpy(&code, pc, sizeof(Word)); pc+=sizeof(Word);}
{ #define get_float(code,pc){memcpy(&code, pc, sizeof(real)); pc+=sizeof(real);}
struct {char c1; char c2;} m; #define get_code(code,pc) {memcpy(&code, pc, sizeof(TFunc *)); \
Word w; pc+=sizeof(TFunc *);}
} 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 */ /* 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 lua_parse (TFunc *tf); /* from "lua.stx" module */
void luaI_codedebugline (int line); /* from "lua.stx" module */ void luaI_codedebugline (int line); /* from "lua.stx" module */
void lua_travstack (int (*fn)(Object *)); void lua_travstack (int (*fn)(TObject *));
Object *luaI_Address (lua_Object o); TObject *luaI_Address (lua_Object o);
void luaI_pushobject (Object *o); void luaI_pushobject (TObject *o);
void luaI_gcFB (Object *o); void luaI_gcIM (TObject *o);
int luaI_dorun (TFunc *tf);
#endif #endif

587
strlib.c
View File

@@ -3,7 +3,7 @@
** String library to LUA ** String library to LUA
*/ */
char *rcs_strlib="$Id: strlib.c,v 1.13 1995/10/09 12:49:21 roberto Exp roberto $"; char *rcs_strlib="$Id: strlib.c,v 1.40 1997/04/06 14:08:08 roberto Exp roberto $";
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@@ -11,138 +11,143 @@ char *rcs_strlib="$Id: strlib.c,v 1.13 1995/10/09 12:49:21 roberto Exp roberto $
#include <ctype.h> #include <ctype.h>
#include "lua.h" #include "lua.h"
#include "auxlib.h"
#include "lualib.h" #include "lualib.h"
void lua_arg_error(char *funcname) struct lbuff {
char *b;
size_t max;
size_t size;
};
static struct lbuff lbuffer = {NULL, 0, 0};
static char *strbuffer (unsigned long size)
{ {
char buff[100]; if (size > lbuffer.max) {
sprintf(buff, "incorrect arguments to function `%s'", funcname); /* ANSI "realloc" doesn't need this test, but some machines (Sun!)
lua_error(buff); don't follow ANSI */
lbuffer.b = (lbuffer.b) ? realloc(lbuffer.b, lbuffer.max=size) :
malloc(lbuffer.max=size);
if (lbuffer.b == NULL)
lua_error("memory overflow");
}
return lbuffer.b;
} }
char *lua_check_string (int numArg, char *funcname) static char *openspace (unsigned long size)
{ {
lua_Object o = lua_getparam(numArg); char *buff = strbuffer(lbuffer.size+size);
if (!(lua_isstring(o) || lua_isnumber(o))) return buff+lbuffer.size;
lua_arg_error(funcname);
return lua_getstring(o);
} }
float lua_check_number (int numArg, char *funcname) char *luaI_addchar (int c)
{ {
lua_Object o = lua_getparam(numArg); if (lbuffer.size >= lbuffer.max)
if (!lua_isnumber(o)) strbuffer(lbuffer.max == 0 ? 100 : lbuffer.max*2);
lua_arg_error(funcname); lbuffer.b[lbuffer.size++] = c;
return lua_getnumber(o); return lbuffer.b;
} }
static char *newstring (char *s) void luaI_emptybuff (void)
{ {
char *ns = (char *)malloc(strlen(s)+1); lbuffer.size = 0; /* prepare for next string */
if (ns == 0)
lua_error("not enough memory for new string");
strcpy(ns, s);
return ns;
} }
static void addnchar (char *s, int n)
{
char *b = openspace(n);
strncpy(b, s, n);
lbuffer.size += n;
}
static void addstr (char *s)
{
addnchar(s, strlen(s));
}
/* /*
** Return the position of the first caracter of a substring into a string ** Interface to strtok
** LUA interface:
** n = strfind (string, substring, init, end)
*/ */
static void str_find (void) static void str_tok (void)
{ {
char *s1 = lua_check_string(1, "strfind"); char *s1 = luaL_check_string(1);
char *s2 = lua_check_string(2, "strfind"); char *del = luaL_check_string(2);
int init = (lua_getparam(3) == LUA_NOOBJECT) ? 0 : lua_Object t = lua_createtable();
(int)lua_check_number(3, "strfind")-1; int i = 1;
char *f = strstr(s1+init,s2); /* As strtok changes s1, and s1 is "constant", make a copy of it */
if (f != NULL) s1 = strcpy(strbuffer(strlen(s1+1)), s1);
{ while ((s1 = strtok(s1, del)) != NULL) {
int pos = f-s1+1; lua_pushobject(t);
if (lua_getparam (4) == LUA_NOOBJECT) lua_pushnumber(i++);
lua_pushnumber (pos); lua_pushstring(s1);
else if ((int)lua_check_number(4, "strfind") >= pos+strlen(s2)-1) lua_settable();
lua_pushnumber (pos); s1 = NULL; /* prepare for next strtok */
else }
lua_pushnil(); lua_pushobject(t);
} lua_pushnumber(i-1); /* total number of tokens */
else
lua_pushnil();
} }
/* /*
** Return the string length ** Return the string length
** LUA interface:
** n = strlen (string)
*/ */
static void str_len (void) static void str_len (void)
{ {
char *s = lua_check_string(1, "strlen"); lua_pushnumber(strlen(luaL_check_string(1)));
lua_pushnumber(strlen(s));
} }
/* /*
** Return the substring of a string, from start to end ** Return the substring of a string
** LUA interface:
** substring = strsub (string, start, end)
*/ */
static void str_sub (void) static void str_sub (void)
{ {
char *s = lua_check_string(1, "strsub"); char *s = luaL_check_string(1);
int start = (int)lua_check_number(2, "strsub"); long start = (long)luaL_check_number(2);
int end = (lua_getparam(3) == LUA_NOOBJECT) ? strlen(s) : long end = (long)luaL_opt_number(3, strlen(s));
(int)lua_check_number(3, "strsub"); if (1 <= start && start <= end && end <= strlen(s)) {
if (end < start || start < 1 || end > strlen(s)) luaI_emptybuff();
lua_pushliteral(""); addnchar(s+start-1, end-start+1);
else lua_pushstring(luaI_addchar(0));
{ }
char temp = s[end]; else lua_pushliteral("");
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. ** Convert a string to lower case.
** LUA interface:
** lowercase = strlower (string)
*/ */
static void str_lower (void) static void str_lower (void)
{ {
str_apply(tolower, "strlower"); char *s;
luaI_emptybuff();
for (s = luaL_check_string(1); *s; s++)
luaI_addchar(tolower((unsigned char)*s));
lua_pushstring(luaI_addchar(0));
} }
/* /*
** Convert a string to upper case. ** Convert a string to upper case.
** LUA interface:
** uppercase = strupper (string)
*/ */
static void str_upper (void) static void str_upper (void)
{ {
str_apply(toupper, "strupper"); char *s;
luaI_emptybuff();
for (s = luaL_check_string(1); *s; s++)
luaI_addchar(toupper((unsigned char)*s));
lua_pushstring(luaI_addchar(0));
}
static void str_rep (void)
{
char *s = luaL_check_string(1);
int n = (int)luaL_check_number(2);
luaI_emptybuff();
while (n-- > 0)
addstr(s);
lua_pushstring(luaI_addchar(0));
} }
/* /*
@@ -150,43 +155,393 @@ static void str_upper (void)
*/ */
static void str_ascii (void) static void str_ascii (void)
{ {
char *s = lua_check_string(1, "ascii"); char *s = luaL_check_string(1);
lua_Object o2 = lua_getparam(2); long pos = (long)luaL_opt_number(2, 1) - 1;
int pos; luaL_arg_check(0<=pos && pos<strlen(s), 2, "out of range");
pos = (o2 == LUA_NOOBJECT) ? 0 : (int)lua_check_number(2, "ascii")-1; lua_pushnumber((unsigned char)s[pos]);
if (pos<0 || pos>=strlen(s))
lua_arg_error("ascii");
lua_pushnumber(s[pos]);
} }
/*
** converts one or more integers to chars in a string /* pattern matching */
*/
#define maxparams 50 #define ESC '%'
static void str_int2str (void) #define SPECIALS "^$*?.([%-"
static char *bracket_end (char *p)
{ {
char s[maxparams+1]; return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+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);
} }
char *luaL_item_end (char *p)
{
switch (*p++) {
case '\0': return p-1;
case ESC:
if (*p == 0) luaL_verror("incorrect pattern (ends with `%c')", ESC);
return p+1;
case '[': {
char *end = bracket_end(p);
if (end == NULL) lua_error("incorrect pattern (missing `]')");
return end+1;
}
default:
return p;
}
}
static int matchclass (int c, int cl)
{
int res;
switch (tolower((unsigned char)cl)) {
case 'a' : res = isalpha((unsigned char)c); break;
case 'c' : res = iscntrl((unsigned char)c); break;
case 'd' : res = isdigit((unsigned char)c); break;
case 'l' : res = islower((unsigned char)c); break;
case 'p' : res = ispunct((unsigned char)c); break;
case 's' : res = isspace((unsigned char)c); break;
case 'u' : res = isupper((unsigned char)c); break;
case 'w' : res = isalnum((unsigned char)c); break;
default: return (cl == c);
}
return (islower((unsigned char)cl) ? res : !res);
}
int luaL_singlematch (int c, char *p)
{
if (c == 0) return 0;
switch (*p) {
case '.': return 1;
case ESC: return matchclass(c, *(p+1));
case '[': {
char *end = bracket_end(p+1);
int sig = *(p+1) == '^' ? (p++, 0) : 1;
while (++p < end) {
if (*p == ESC) {
if (((p+1) < end) && matchclass(c, *++p)) return sig;
}
else if ((*(p+1) == '-') && (p+2 < end)) {
p+=2;
if (*(p-2) <= c && c <= *p) return sig;
}
else if (*p == c) return sig;
}
return !sig;
}
default: return (*p == c);
}
}
#define MAX_CAPT 9
static struct {
char *init;
int len; /* -1 signals unfinished capture */
} capture[MAX_CAPT];
static int num_captures; /* only valid after a sucessful call to match */
static void push_captures (void)
{
int i;
for (i=0; i<num_captures; i++) {
int l = capture[i].len;
char *buff = openspace(l+1);
if (l == -1) lua_error("unfinished capture");
strncpy(buff, capture[i].init, l);
buff[l] = 0;
lua_pushstring(buff);
}
}
static int check_cap (int l, int level)
{
l -= '1';
if (!(0 <= l && l < level && capture[l].len != -1))
lua_error("invalid capture index");
return l;
}
static int capture_to_close (int level)
{
for (level--; level>=0; level--)
if (capture[level].len == -1) return level;
lua_error("invalid pattern capture");
return 0; /* to avoid warnings */
}
static char *matchbalance (char *s, int b, int e)
{
if (*s != b) return NULL;
else {
int cont = 1;
while (*(++s)) {
if (*s == e) {
if (--cont == 0) return s+1;
}
else if (*s == b) cont++;
}
}
return NULL; /* string ends out of balance */
}
static char *match (char *s, char *p, int level)
{
init: /* using goto's to optimize tail recursion */
switch (*p) {
case '(': /* start capture */
if (level >= MAX_CAPT) lua_error("too many captures");
capture[level].init = s;
capture[level].len = -1;
level++; p++; goto init; /* return match(s, p+1, level); */
case ')': { /* end capture */
int l = capture_to_close(level);
char *res;
capture[l].len = s - capture[l].init; /* close capture */
if ((res = match(s, p+1, level)) == NULL) /* match failed? */
capture[l].len = -1; /* undo capture */
return res;
}
case ESC:
if (isdigit((unsigned char)*(p+1))) { /* capture */
int l = check_cap(*(p+1), level);
if (strncmp(capture[l].init, s, capture[l].len) == 0) {
/* return match(p+2, s+capture[l].len, level); */
p+=2; s+=capture[l].len; goto init;
}
else return NULL;
}
else if (*(p+1) == 'b') { /* balanced string */
if (*(p+2) == 0 || *(p+3) == 0)
lua_error("bad balanced pattern specification");
s = matchbalance(s, *(p+2), *(p+3));
if (s == NULL) return NULL;
else { /* return match(p+4, s, level); */
p+=4; goto init;
}
}
else goto dflt;
case '\0': case '$': /* (possibly) end of pattern */
if (*p == 0 || (*(p+1) == 0 && *s == 0)) {
num_captures = level;
return s;
}
else goto dflt;
default: dflt: { /* it is a pattern item */
int m = luaL_singlematch(*s, p);
char *ep = luaL_item_end(p); /* get what is next */
switch (*ep) {
case '*': { /* repetition */
char *res;
if (m && (res = match(s+1, p, level)))
return res;
p=ep+1; goto init; /* else return match(s, ep+1, level); */
}
case '-': { /* repetition */
char *res;
if ((res = match(s, ep+1, level)) != 0)
return res;
else if (m) {
s++;
goto init; /* return match(s+1, p, level); */
}
else
return NULL;
}
case '?': { /* optional */
char *res;
if (m && (res = match(s+1, ep+1, level)))
return res;
p=ep+1; goto init; /* else return match(s, ep+1, level); */
}
default:
if (m) { s++; p=ep; goto init; } /* return match(s+1, ep, level); */
else return NULL;
}
}
}
}
static void str_find (void)
{
char *s = luaL_check_string(1);
char *p = luaL_check_string(2);
long init = (long)luaL_opt_number(3, 1) - 1;
luaL_arg_check(0 <= init && init <= strlen(s), 3, "out of range");
if (lua_getparam(4) != LUA_NOOBJECT ||
strpbrk(p, SPECIALS) == NULL) { /* no special caracters? */
char *s2 = strstr(s+init, p);
if (s2) {
lua_pushnumber(s2-s+1);
lua_pushnumber(s2-s+strlen(p));
}
}
else {
int anchor = (*p == '^') ? (p++, 1) : 0;
char *s1=s+init;
do {
char *res;
if ((res=match(s1, p, 0)) != NULL) {
lua_pushnumber(s1-s+1); /* start */
lua_pushnumber(res-s); /* end */
push_captures();
return;
}
} while (*s1++ && !anchor);
}
}
static void add_s (lua_Object newp)
{
if (lua_isstring(newp)) {
char *news = lua_getstring(newp);
while (*news) {
if (*news != ESC || !isdigit((unsigned char)*++news))
luaI_addchar(*news++);
else {
int l = check_cap(*news++, num_captures);
addnchar(capture[l].init, capture[l].len);
}
}
}
else if (lua_isfunction(newp)) {
lua_Object res;
struct lbuff oldbuff;
lua_beginblock();
push_captures();
/* function may use lbuffer, so save it and create a new one */
oldbuff = lbuffer;
lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0;
lua_callfunction(newp);
/* restore old buffer */
free(lbuffer.b);
lbuffer = oldbuff;
res = lua_getresult(1);
addstr(lua_isstring(res) ? lua_getstring(res) : "");
lua_endblock();
}
else luaL_arg_check(0, 3, NULL);
}
static void str_gsub (void)
{
char *src = luaL_check_string(1);
char *p = luaL_check_string(2);
lua_Object newp = lua_getparam(3);
int max_s = (int)luaL_opt_number(4, strlen(src)+1);
int anchor = (*p == '^') ? (p++, 1) : 0;
int n = 0;
luaI_emptybuff();
while (n < max_s) {
char *e = match(src, p, 0);
if (e) {
add_s(newp);
n++;
}
if (e && e>src) /* non empty match? */
src = e; /* skip it */
else if (*src)
luaI_addchar(*src++);
else break;
if (anchor) break;
}
addstr(src);
lua_pushstring(luaI_addchar(0));
lua_pushnumber(n); /* number of substitutions */
}
static void str_set (void)
{
char *item = luaL_check_string(1);
int i;
luaL_arg_check(*luaL_item_end(item) == 0, 1, "wrong format");
luaI_emptybuff();
for (i=1; i<256; i++) /* 0 cannot be part of a set */
if (luaL_singlematch(i, item))
luaI_addchar(i);
lua_pushstring(luaI_addchar(0));
}
void luaI_addquoted (char *s)
{
luaI_addchar('"');
for (; *s; s++) {
if (strchr("\"\\\n", *s))
luaI_addchar('\\');
luaI_addchar(*s);
}
luaI_addchar('"');
}
#define MAX_FORMAT 200
static void str_format (void)
{
int arg = 1;
char *strfrmt = luaL_check_string(arg++);
luaI_emptybuff(); /* initialize */
while (*strfrmt) {
if (*strfrmt != '%')
luaI_addchar(*strfrmt++);
else if (*++strfrmt == '%')
luaI_addchar(*strfrmt++); /* %% */
else { /* format item */
char form[MAX_FORMAT]; /* store the format ('%...') */
char *buff;
char *initf = strfrmt-1; /* -1 to include % */
strfrmt = match(strfrmt, "[-+ #]*(%d*)%.?(%d*)", 0);
if (capture[0].len > 3 || capture[1].len > 3) /* < 1000? */
lua_error("invalid format (width or precision too long)");
strncpy(form, initf, strfrmt-initf+1); /* +1 to include convertion */
form[strfrmt-initf+1] = 0;
buff = openspace(1000); /* to store the formated value */
switch (*strfrmt++) {
case 'q':
luaI_addquoted(luaL_check_string(arg++));
continue;
case 's': {
char *s = luaL_check_string(arg++);
buff = openspace(strlen(s));
sprintf(buff, form, s);
break;
}
case 'c': case 'd': case 'i': case 'o':
case 'u': case 'x': case 'X':
sprintf(buff, form, (int)luaL_check_number(arg++));
break;
case 'e': case 'E': case 'f': case 'g':
sprintf(buff, form, luaL_check_number(arg++));
break;
default: /* also treat cases 'pnLlh' */
lua_error("invalid format option in function `format'");
}
lbuffer.size += strlen(buff);
}
}
lua_pushstring(luaI_addchar(0)); /* push the result */
}
static struct luaL_reg strlib[] = {
{"strtok", str_tok},
{"strlen", str_len},
{"strsub", str_sub},
{"strset", str_set},
{"strlower", str_lower},
{"strupper", str_upper},
{"strrep", str_rep},
{"ascii", str_ascii},
{"format", str_format},
{"strfind", str_find},
{"gsub", str_gsub}
};
/* /*
** Open string library ** Open string library
*/ */
void strlib_open (void) void strlib_open (void)
{ {
lua_register ("strfind", str_find); luaL_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0])));
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);
} }

250
table.c
View File

@@ -3,11 +3,10 @@
** Module to control static tables ** Module to control static tables
*/ */
char *rcs_table="$Id: table.c,v 2.37 1995/10/26 14:21:56 roberto Exp roberto $"; char *rcs_table="$Id: table.c,v 2.67 1997/04/06 14:08:08 roberto Exp roberto $";
/*#include <string.h>*/ #include "luamem.h"
#include "auxlib.h"
#include "mem.h"
#include "opcode.h" #include "opcode.h"
#include "tree.h" #include "tree.h"
#include "hash.h" #include "hash.h"
@@ -21,61 +20,35 @@ char *rcs_table="$Id: table.c,v 2.37 1995/10/26 14:21:56 roberto Exp roberto $";
#define BUFFER_BLOCK 256 #define BUFFER_BLOCK 256
Symbol *lua_table = NULL; Symbol *lua_table = NULL;
static Word lua_ntable = 0; Word lua_ntable = 0;
static Long lua_maxsymbol = 0; static Long lua_maxsymbol = 0;
TaggedString **lua_constant = NULL; TaggedString **lua_constant = NULL;
static Word lua_nconstant = 0; Word lua_nconstant = 0;
static Long lua_maxconstant = 0; static Long lua_maxconstant = 0;
#define GARBAGE_BLOCK 1024 #define GARBAGE_BLOCK 50
#define MIN_GARBAGE_BLOCK (GARBAGE_BLOCK/2)
static void lua_nextvar (void);
static void setglobal (void);
static void getglobal (void);
/* void luaI_initsymbol (void)
** Initialise symbol table with internal functions
*/
static void lua_initsymbol (void)
{ {
Word n; lua_maxsymbol = BUFFER_BLOCK;
lua_maxsymbol = BUFFER_BLOCK; lua_table = newvector(lua_maxsymbol, Symbol);
lua_table = newvector(lua_maxsymbol, Symbol); luaI_predefine();
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 ** Initialise constant table with pre-defined constants
*/ */
void lua_initconstant (void) void luaI_initconstant (void)
{ {
lua_maxconstant = BUFFER_BLOCK; lua_maxconstant = BUFFER_BLOCK;
lua_constant = newvector(lua_maxconstant, TaggedString *); lua_constant = newvector(lua_maxconstant, TaggedString *);
/* pre-register mem error messages, to avoid loop when error arises */
luaI_findconstantbyname(tableEM);
luaI_findconstantbyname(memEM);
} }
@@ -83,23 +56,16 @@ void lua_initconstant (void)
** Given a name, search it at symbol table and return its index. If not ** Given a name, search it at symbol table and return its index. If not
** found, allocate it. ** found, allocate it.
*/ */
Word luaI_findsymbol (TreeNode *t) Word luaI_findsymbol (TaggedString *t)
{ {
if (lua_table == NULL)
lua_initsymbol();
if (t->varindex == NOT_USED) if (t->varindex == NOT_USED)
{ {
if (lua_ntable == lua_maxsymbol) if (lua_ntable == lua_maxsymbol)
{ lua_maxsymbol = growvector(&lua_table, lua_maxsymbol, Symbol,
if (lua_maxsymbol >= MAX_WORD) symbolEM, 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; t->varindex = lua_ntable;
s_tag(lua_ntable) = LUA_T_NIL; lua_table[lua_ntable].varname = t;
s_ttype(lua_ntable) = LUA_T_NIL;
lua_ntable++; lua_ntable++;
} }
return t->varindex; return t->varindex;
@@ -108,7 +74,7 @@ Word luaI_findsymbol (TreeNode *t)
Word luaI_findsymbolbyname (char *name) Word luaI_findsymbolbyname (char *name)
{ {
return luaI_findsymbol(lua_constcreate(name)); return luaI_findsymbol(luaI_createfixedstring(name));
} }
@@ -116,23 +82,15 @@ Word luaI_findsymbolbyname (char *name)
** Given a tree node, check it is has a correspondent constant index. If not, ** Given a tree node, check it is has a correspondent constant index. If not,
** allocate it. ** allocate it.
*/ */
Word luaI_findconstant (TreeNode *t) Word luaI_findconstant (TaggedString *t)
{ {
if (lua_constant == NULL)
lua_initconstant();
if (t->constindex == NOT_USED) if (t->constindex == NOT_USED)
{ {
if (lua_nconstant == lua_maxconstant) if (lua_nconstant == lua_maxconstant)
{ lua_maxconstant = growvector(&lua_constant, lua_maxconstant, TaggedString *,
if (lua_maxconstant >= MAX_WORD) constantEM, 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; t->constindex = lua_nconstant;
lua_constant[lua_nconstant] = &(t->ts); lua_constant[lua_nconstant] = t;
lua_nconstant++; lua_nconstant++;
} }
return t->constindex; return t->constindex;
@@ -141,19 +99,33 @@ Word luaI_findconstant (TreeNode *t)
Word luaI_findconstantbyname (char *name) Word luaI_findconstantbyname (char *name)
{ {
return luaI_findconstant(lua_constcreate(name)); return luaI_findconstant(luaI_createfixedstring(name));
}
TaggedString *luaI_createfixedstring (char *name)
{
TaggedString *ts = lua_createstring(name);
if (!ts->marked)
ts->marked = 2; /* avoid GC */
return ts;
}
int luaI_globaldefined (char *name)
{
return ttype(&lua_table[luaI_findsymbolbyname(name)].object) != LUA_T_NIL;
} }
/* /*
** Traverse symbol table objects ** Traverse symbol table objects
*/ */
static char *lua_travsymbol (int (*fn)(Object *)) static char *lua_travsymbol (int (*fn)(TObject *))
{ {
Word i; Word i;
for (i=0; i<lua_ntable; i++) for (i=0; i<lua_ntable; i++)
if (fn(&s_object(i))) if (fn(&s_object(i)))
return luaI_nodebysymbol(i)->ts.str; return lua_table[i].varname->str;
return NULL; return NULL;
} }
@@ -161,116 +133,114 @@ static char *lua_travsymbol (int (*fn)(Object *))
/* /*
** Mark an object if it is a string or a unmarked array. ** Mark an object if it is a string or a unmarked array.
*/ */
int lua_markobject (Object *o) int lua_markobject (TObject *o)
{ {/* if already marked, does not change mark value */
if (tag(o) == LUA_T_STRING && !tsvalue(o)->marked) if (ttype(o) == LUA_T_USERDATA ||
(ttype(o) == LUA_T_STRING && !tsvalue(o)->marked))
tsvalue(o)->marked = 1; tsvalue(o)->marked = 1;
else if (tag(o) == LUA_T_ARRAY) else if (ttype(o) == LUA_T_ARRAY)
lua_hashmark (avalue(o)); lua_hashmark (avalue(o));
else if ((o->tag == LUA_T_FUNCTION || o->tag == LUA_T_MARK) else if ((o->ttype == LUA_T_FUNCTION || o->ttype == LUA_T_MARK)
&& !o->value.tf->marked) && !o->value.tf->marked)
o->value.tf->marked = 1; o->value.tf->marked = 1;
return 0; return 0;
} }
/*
* returns 0 if the object is going to be (garbage) collected
*/
int luaI_ismarked (TObject *o)
{
switch (o->ttype)
{
case LUA_T_STRING:
return o->value.ts->marked;
case LUA_T_FUNCTION:
return o->value.tf->marked;
case LUA_T_ARRAY:
return o->value.a->mark;
default: /* nil, number, cfunction, or user data */
return 1;
}
}
static void call_nilIM (void)
{ /* signals end of garbage collection */
TObject t;
ttype(&t) = LUA_T_NIL;
luaI_gcIM(&t); /* end of list */
}
/* /*
** Garbage collection. ** Garbage collection.
** Delete all unused strings and arrays. ** Delete all unused strings and arrays.
*/ */
void lua_pack (void) Long luaI_collectgarbage (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; Long recovered = 0;
if (nentity++ < block) return;
lua_travstack(lua_markobject); /* mark stack objects */ lua_travstack(lua_markobject); /* mark stack objects */
lua_travsymbol(lua_markobject); /* mark symbol table objects */ lua_travsymbol(lua_markobject); /* mark symbol table objects */
luaI_travlock(lua_markobject); /* mark locked objects */ luaI_travlock(lua_markobject); /* mark locked objects */
luaI_travfallbacks(lua_markobject); /* mark fallbacks */ luaI_travfallbacks(lua_markobject); /* mark fallbacks */
luaI_hashcallIM();
luaI_strcallIM();
call_nilIM();
luaI_invalidaterefs();
recovered += lua_strcollector(); recovered += lua_strcollector();
recovered += lua_hashcollector(); recovered += lua_hashcollector();
recovered += luaI_funccollector(); recovered += luaI_funccollector();
nentity = 0; /* reset counter */ return recovered;
block=(16*block-7*recovered)/12; /* adapt block size */ }
if (block < MIN_GARBAGE_BLOCK) block = MIN_GARBAGE_BLOCK;
void lua_pack (void)
{
static unsigned long block = GARBAGE_BLOCK;
static unsigned long nentity = 0; /* total of strings, arrays, etc */
unsigned long recovered = 0;
if (nentity++ < block) return;
recovered = luaI_collectgarbage();
block = 2*(block-recovered);
nentity -= recovered;
} }
/* /*
** Internal function: return next global variable ** Internal function: return next global variable
*/ */
static void lua_nextvar (void) void luaI_nextvar (void)
{ {
Word next; Word next;
lua_Object o = lua_getparam(1); if (lua_isnil(lua_getparam(1)))
if (o == LUA_NOOBJECT) next = 0;
lua_error("too few arguments to function `nextvar'"); else
if (lua_getparam(2) != LUA_NOOBJECT) next = luaI_findsymbolbyname(luaL_check_string(1)) + 1;
lua_error("too many arguments to function `nextvar'"); while (next < lua_ntable && s_ttype(next) == LUA_T_NIL)
if (lua_isnil(o)) next++;
next = 0; if (next < lua_ntable) {
else if (!lua_isstring(o)) lua_pushstring(lua_table[next].varname->str);
{ luaI_pushobject(&s_object(next));
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) static TObject *functofind;
static int checkfunc (TObject *o)
{ {
lua_Object name = lua_getparam(1); if (o->ttype == LUA_T_FUNCTION)
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 return
((functofind->tag == LUA_T_FUNCTION || functofind->tag == LUA_T_MARK) ((functofind->ttype == LUA_T_FUNCTION || functofind->ttype == LUA_T_MARK)
&& (functofind->value.tf == o->value.tf)); && (functofind->value.tf == o->value.tf));
if (o->tag == LUA_T_CFUNCTION) if (o->ttype == LUA_T_CFUNCTION)
return return
((functofind->tag == LUA_T_CFUNCTION || functofind->tag == LUA_T_CMARK) ((functofind->ttype == LUA_T_CFUNCTION ||
&& (functofind->value.f == o->value.f)); functofind->ttype == LUA_T_CMARK) &&
(functofind->value.f == o->value.f));
return 0; return 0;
} }
char *getobjname (lua_Object o, char **name) char *lua_getobjname (lua_Object o, char **name)
{ /* try to find a name for given function */ { /* try to find a name for given function */
functofind = luaI_Address(o); functofind = luaI_Address(o);
if ((*name = luaI_travfallbacks(checkfunc)) != NULL) if ((*name = luaI_travfallbacks(checkfunc)) != NULL)

29
table.h
View File

@@ -1,7 +1,7 @@
/* /*
** Module to control static tables ** Module to control static tables
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: table.h,v 2.12 1995/10/17 11:58:41 roberto Exp roberto $ ** $Id: table.h,v 2.23 1997/03/31 14:02:58 roberto Exp roberto $
*/ */
#ifndef table_h #ifndef table_h
@@ -10,19 +10,30 @@
#include "tree.h" #include "tree.h"
#include "opcode.h" #include "opcode.h"
typedef struct
{
TObject object;
TaggedString *varname;
} Symbol;
extern Symbol *lua_table; extern Symbol *lua_table;
extern Word lua_ntable;
extern TaggedString **lua_constant; extern TaggedString **lua_constant;
extern Word lua_nconstant;
extern char *lua_file[]; void luaI_initsymbol (void);
extern int lua_nfile; void luaI_initconstant (void);
void lua_initconstant (void);
Word luaI_findsymbolbyname (char *name); Word luaI_findsymbolbyname (char *name);
Word luaI_findsymbol (TreeNode *t); Word luaI_findsymbol (TaggedString *t);
Word luaI_findconstant (TreeNode *t); Word luaI_findconstant (TaggedString *t);
Word luaI_findconstantbyname (char *name); Word luaI_findconstantbyname (char *name);
int lua_markobject (Object *o); int luaI_globaldefined (char *name);
void luaI_nextvar (void);
TaggedString *luaI_createfixedstring (char *str);
int lua_markobject (TObject *o);
int luaI_ismarked (TObject *o);
Long luaI_collectgarbage (void);
void lua_pack (void); void lua_pack (void);

213
tree.c
View File

@@ -3,74 +3,141 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_tree="$Id: tree.c,v 1.13 1995/01/12 14:19:04 roberto Exp roberto $"; char *rcs_tree="$Id: tree.c,v 1.23 1997/03/31 14:02:58 roberto Exp roberto $";
#include <string.h> #include <string.h>
#include "mem.h" #include "luamem.h"
#include "lua.h" #include "lua.h"
#include "tree.h" #include "tree.h"
#include "lex.h"
#include "hash.h"
#include "table.h" #include "table.h"
#include "fallback.h"
#define lua_strcmp(a,b) (a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b))) #define NUM_HASHS 64
typedef struct {
int size;
int nuse; /* number of elements (including EMPTYs) */
TaggedString **hash;
} stringtable;
static int initialized = 0;
static stringtable string_root[NUM_HASHS];
static TaggedString EMPTY = {LUA_T_STRING, 0, NOT_USED, NOT_USED, 0, 2, {0}};
typedef struct StringNode { static unsigned long hash (char *buff, long size)
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) unsigned long h = 0;
{ while (size--)
*node = (TreeNode *) luaI_malloc(sizeof(TreeNode)+strlen(str)); h = ((h<<5)-h)^(unsigned char)*(buff++);
(*node)->left = (*node)->right = NULL; return h;
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) static void initialize (void)
{ {
StringNode *newString; initialized = 1;
if (str == NULL) return NULL; luaI_addReserved();
luaI_initsymbol();
luaI_initconstant();
luaI_initfallbacks();
}
static void grow (stringtable *tb)
{
int newsize = luaI_redimension(tb->size);
TaggedString **newhash = newvector(newsize, TaggedString *);
int i;
for (i=0; i<newsize; i++)
newhash[i] = NULL;
/* rehash */
tb->nuse = 0;
for (i=0; i<tb->size; i++)
if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY)
{
int h = tb->hash[i]->hash%newsize;
while (newhash[h])
h = (h+1)%newsize;
newhash[h] = tb->hash[i];
tb->nuse++;
}
luaI_free(tb->hash);
tb->size = newsize;
tb->hash = newhash;
}
static TaggedString *insert (char *buff, long size, int tag, stringtable *tb)
{
TaggedString *ts;
unsigned long h = hash(buff, size);
int i;
int j = -1;
if ((Long)tb->nuse*3 >= (Long)tb->size*2)
{
if (!initialized)
initialize();
grow(tb);
}
i = h%tb->size;
while ((ts = tb->hash[i]) != NULL)
{
if (ts == &EMPTY)
j = i;
else if (ts->size == size && ts->tag == tag &&
memcmp(buff, ts->str, size) == 0)
return ts;
i = (i+1)%tb->size;
}
/* not found */
lua_pack(); lua_pack();
newString = (StringNode *)luaI_malloc(sizeof(StringNode)+strlen(str)); if (j != -1) /* is there an EMPTY space? */
newString->ts.marked = 0; i = j;
newString->ts.hash = 0; else
strcpy(newString->ts.str, str); tb->nuse++;
newString->next = string_root; ts = tb->hash[i] = (TaggedString *)luaI_malloc(sizeof(TaggedString)+size-1);
string_root = newString; memcpy(ts->str, buff, size);
return &(newString->ts); ts->tag = tag;
ts->size = size;
ts->marked = 0;
ts->hash = h;
ts->varindex = ts->constindex = NOT_USED;
return ts;
}
TaggedString *luaI_createuserdata (char *buff, long size, int tag)
{
return insert(buff, size, tag, &string_root[(unsigned)buff[0]%NUM_HASHS]);
}
TaggedString *lua_createstring (char *str)
{
return luaI_createuserdata(str, strlen(str)+1, LUA_T_STRING);
} }
TreeNode *lua_constcreate (char *str) void luaI_strcallIM (void)
{ {
return tree_create(&constant_root, str); int i;
TObject o;
ttype(&o) = LUA_T_USERDATA;
for (i=0; i<NUM_HASHS; i++) {
stringtable *tb = &string_root[i];
int j;
for (j=0; j<tb->size; j++) {
TaggedString *t = tb->hash[j];
if (t != NULL && t->tag != LUA_T_STRING && t->marked == 0) {
tsvalue(&o) = t;
luaI_gcIM(&o);
}
}
}
} }
@@ -80,44 +147,28 @@ TreeNode *lua_constcreate (char *str)
*/ */
Long lua_strcollector (void) Long lua_strcollector (void)
{ {
StringNode *curr = string_root, *prev = NULL;
Long counter = 0; Long counter = 0;
while (curr) int i;
for (i=0; i<NUM_HASHS; i++)
{ {
StringNode *next = curr->next; stringtable *tb = &string_root[i];
if (!curr->ts.marked) int j;
for (j=0; j<tb->size; j++)
{ {
if (prev == NULL) string_root = next; TaggedString *t = tb->hash[j];
else prev->next = next; if (t != NULL && t->marked <= 1)
luaI_free(curr); {
++counter; if (t->marked)
t->marked = 0;
else
{
luaI_free(t);
tb->hash[j] = &EMPTY;
counter++;
}
}
} }
else
{
curr->ts.marked = 0;
prev = curr;
}
curr = next;
} }
return counter; 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);
}

23
tree.h
View File

@@ -1,7 +1,7 @@
/* /*
** tree.h ** tree.h
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
** $Id: tree.h,v 1.9 1995/01/12 14:19:04 roberto Exp roberto $ ** $Id: tree.h,v 1.15 1997/02/11 11:35:05 roberto Exp roberto $
*/ */
#ifndef tree_h #ifndef tree_h
@@ -14,24 +14,19 @@
typedef struct TaggedString typedef struct TaggedString
{ {
int tag; /* if != LUA_T_STRING, this is a userdata */
long size;
Word varindex; /* != NOT_USED if this is a symbol */
Word constindex; /* != NOT_USED if this is a constant */
unsigned long hash; /* 0 if not initialized */ unsigned long hash; /* 0 if not initialized */
char marked; /* for garbage collection */ int marked; /* for garbage collection; never collect (nor change) if > 1 */
char str[1]; /* \0 byte already reserved */ char str[1]; /* \0 byte already reserved; MAY BE NOT 0 TERMINATED!! */
} TaggedString; } 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); TaggedString *lua_createstring (char *str);
TreeNode *lua_constcreate (char *str); TaggedString *luaI_createuserdata (char *buff, long size, int tag);
Long lua_strcollector (void); Long lua_strcollector (void);
TreeNode *luaI_nodebysymbol (Word symbol); void luaI_strcallIM (void);
#endif #endif

View File

@@ -1,6 +1,6 @@
/* /*
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: types.h,v 1.2 1994/12/27 20:41:47 celes Exp roberto $ ** $Id: types.h,v 1.3 1995/02/06 19:32:43 roberto Exp roberto $
*/ */
#ifndef types_h #ifndef types_h
@@ -12,8 +12,6 @@
#define real float #define real float
#endif #endif
typedef int Bool; /* boolean values */
#define Byte lua_Byte /* some systems have Byte as a predefined type */ #define Byte lua_Byte /* some systems have Byte as a predefined type */
typedef unsigned char Byte; /* unsigned 8 bits */ typedef unsigned char Byte; /* unsigned 8 bits */

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

333
undump.c Normal file
View File

@@ -0,0 +1,333 @@
/*
** undump.c
** load bytecodes from files
*/
char* rcs_undump="$Id: undump.c,v 1.21 1996/11/18 11:18:29 lhf Exp lhf $";
#include <stdio.h>
#include <string.h>
#include "auxlib.h"
#include "opcode.h"
#include "luamem.h"
#include "table.h"
#include "undump.h"
static int swapword=0;
static int swapfloat=0;
static TFunc* Main=NULL; /* functions in a chunk */
static TFunc* lastF=NULL;
static void FixCode(Byte* code, Byte* end) /* swap words */
{
Byte* p;
for (p=code; p!=end;)
{
int op=*p;
switch (op)
{
case PUSHNIL:
case PUSH0:
case PUSH1:
case PUSH2:
case PUSHLOCAL0:
case PUSHLOCAL1:
case PUSHLOCAL2:
case PUSHLOCAL3:
case PUSHLOCAL4:
case PUSHLOCAL5:
case PUSHLOCAL6:
case PUSHLOCAL7:
case PUSHLOCAL8:
case PUSHLOCAL9:
case PUSHINDEXED:
case STORELOCAL0:
case STORELOCAL1:
case STORELOCAL2:
case STORELOCAL3:
case STORELOCAL4:
case STORELOCAL5:
case STORELOCAL6:
case STORELOCAL7:
case STORELOCAL8:
case STORELOCAL9:
case STOREINDEXED0:
case ADJUST0:
case EQOP:
case LTOP:
case LEOP:
case GTOP:
case GEOP:
case ADDOP:
case SUBOP:
case MULTOP:
case DIVOP:
case POWOP:
case CONCOP:
case MINUSOP:
case NOTOP:
case POP:
case RETCODE0:
p++;
break;
case PUSHBYTE:
case PUSHLOCAL:
case STORELOCAL:
case STOREINDEXED:
case STORELIST0:
case ADJUST:
case RETCODE:
case VARARGS:
case STOREMAP:
p+=2;
break;
case STORELIST:
case CALLFUNC:
p+=3;
break;
case PUSHFUNCTION:
p+=5; /* TODO: use sizeof(TFunc*) or old? */
break;
case PUSHWORD:
case PUSHSELF:
case CREATEARRAY:
case ONTJMP:
case ONFJMP:
case JMP:
case UPJMP:
case IFFJMP:
case IFFUPJMP:
case SETLINE:
case PUSHSTRING:
case PUSHGLOBAL:
case STOREGLOBAL:
{
Byte t;
t=p[1]; p[1]=p[2]; p[2]=t;
p+=3;
break;
}
case PUSHFLOAT: /* assumes sizeof(float)==4 */
{
Byte t;
t=p[1]; p[1]=p[4]; p[4]=t;
t=p[2]; p[2]=p[3]; p[3]=t;
p+=5;
break;
}
case STORERECORD:
{
int n=*++p;
p++;
while (n--)
{
Byte t;
t=p[0]; p[0]=p[1]; p[1]=t;
p+=2;
}
break;
}
default:
luaL_verror("corrupt binary file: bad opcode %d at %d\n",
op,(int)(p-code));
break;
}
}
}
static void Unthread(Byte* code, int i, int v)
{
while (i!=0)
{
Word w;
Byte* p=code+i;
memcpy(&w,p,sizeof(w));
i=w; w=v;
memcpy(p,&w,sizeof(w));
}
}
static int LoadWord(FILE* D)
{
Word w;
fread(&w,sizeof(w),1,D);
if (swapword)
{
Byte* p=(Byte*)&w;
Byte t;
t=p[0]; p[0]=p[1]; p[1]=t;
}
return w;
}
static int LoadSize(FILE* D)
{
Word hi=LoadWord(D);
Word lo=LoadWord(D);
int s=(hi<<16)|lo;
if ((Word)s != s) lua_error("code too long");
return s;
}
static void* LoadBlock(int size, FILE* D)
{
void* b=luaI_malloc(size);
fread(b,size,1,D);
return b;
}
static char* LoadString(FILE* D)
{
int size=LoadWord(D);
char *b=luaI_buffer(size);
fread(b,size,1,D);
return b;
}
static char* LoadNewString(FILE* D)
{
return LoadBlock(LoadWord(D),D);
}
static void LoadFunction(FILE* D)
{
TFunc* tf=new(TFunc);
tf->next=NULL;
tf->locvars=NULL;
tf->size=LoadSize(D);
tf->lineDefined=LoadWord(D);
if (IsMain(tf)) /* new main */
{
tf->fileName=LoadNewString(D);
Main=lastF=tf;
}
else /* fix PUSHFUNCTION */
{
tf->marked=LoadWord(D);
tf->fileName=Main->fileName;
memcpy(Main->code+tf->marked,&tf,sizeof(tf));
lastF=lastF->next=tf;
}
tf->code=LoadBlock(tf->size,D);
if (swapword || swapfloat) FixCode(tf->code,tf->code+tf->size);
while (1) /* unthread */
{
int c=getc(D);
if (c==ID_VAR) /* global var */
{
int i=LoadWord(D);
char* s=LoadString(D);
int v=luaI_findsymbolbyname(s);
Unthread(tf->code,i,v);
}
else if (c==ID_STR) /* constant string */
{
int i=LoadWord(D);
char* s=LoadString(D);
int v=luaI_findconstantbyname(s);
Unthread(tf->code,i,v);
}
else
{
ungetc(c,D);
break;
}
}
}
static void LoadSignature(FILE* D)
{
char* s=SIGNATURE;
while (*s!=0 && getc(D)==*s)
++s;
if (*s!=0) lua_error("cannot load binary file: bad signature");
}
static void LoadHeader(FILE* D)
{
Word w,tw=TEST_WORD;
float f,tf=TEST_FLOAT;
int version;
LoadSignature(D);
version=getc(D);
if (version>0x23) /* after 2.5 */
{
int oldsizeofW=getc(D);
int oldsizeofF=getc(D);
int oldsizeofP=getc(D);
if (oldsizeofW!=2)
luaL_verror(
"cannot load binary file created on machine with sizeof(Word)=%d; "
"expected 2",oldsizeofW);
if (oldsizeofF!=4)
luaL_verror(
"cannot load binary file created on machine with sizeof(float)=%d; "
"expected 4\nnot an IEEE machine?",oldsizeofF);
if (oldsizeofP!=sizeof(TFunc*)) /* TODO: pack? */
luaL_verror(
"cannot load binary file created on machine with sizeof(TFunc*)=%d; "
"expected %d",oldsizeofP,sizeof(TFunc*));
}
fread(&w,sizeof(w),1,D); /* test word */
if (w!=tw)
{
swapword=1;
}
fread(&f,sizeof(f),1,D); /* test float */
if (f!=tf)
{
Byte* p=(Byte*)&f;
Byte t;
swapfloat=1;
t=p[0]; p[0]=p[3]; p[3]=t;
t=p[1]; p[1]=p[2]; p[2]=t;
if (f!=tf) /* TODO: try another perm? */
lua_error("cannot load binary file: unknown float representation");
}
}
static void LoadChunk(FILE* D)
{
LoadHeader(D);
while (1)
{
int c=getc(D);
if (c==ID_FUN) LoadFunction(D); else { ungetc(c,D); break; }
}
}
/*
** load one chunk from a file.
** return list of functions found, headed by main, or NULL at EOF.
*/
TFunc* luaI_undump1(FILE* D)
{
while (1)
{
int c=getc(D);
if (c==ID_CHUNK)
{
LoadChunk(D);
return Main;
}
else if (c==EOF)
return NULL;
else
lua_error("not a lua binary file");
}
}
/*
** load and run all chunks in a file
*/
int luaI_undump(FILE* D)
{
TFunc* m;
while ((m=luaI_undump1(D)))
{
int status=luaI_dorun(m);
luaI_freefunc(m);
if (status!=0) return status;
}
return 0;
}

23
undump.h Normal file
View File

@@ -0,0 +1,23 @@
/*
** undump.h
** definitions for lua decompiler
** $Id: undump.h,v 1.3 1996/11/14 11:44:34 lhf Exp lhf $
*/
#include "func.h"
#define IsMain(f) (f->lineDefined==0)
/* definitions for chunk headers */
#define ID_CHUNK 27 /* ESC */
#define ID_FUN 'F'
#define ID_VAR 'V'
#define ID_STR 'S'
#define SIGNATURE "Lua"
#define VERSION 0x25 /* last format change was in 2.5 */
#define TEST_WORD 0x1234 /* a word for testing byte ordering */
#define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */
TFunc* luaI_undump1(FILE* D); /* load one chunk */
int luaI_undump(FILE* D); /* load all chunks */