Compare commits

..

134 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
30 changed files with 3725 additions and 2864 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,130 +3,37 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_fallback="$Id: fallback.c,v 1.24 1996/04/22 18:00:37 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 "table.h"
#include "tree.h"
#include "hash.h"
static void errorFB (void);
static void indexFB (void);
static void gettableFB (void);
static void arithFB (void);
static void concatFB (void);
static void orderFB (void);
static void GDFB (void);
static void funcFB (void);
/* -------------------------------------------
/*
** Warning: This list must be in the same order as the #define's
*/
struct FB luaI_fallBacks[] = {
{"error", {LUA_T_CFUNCTION, {errorFB}}, 1, 0},
{"index", {LUA_T_CFUNCTION, {indexFB}}, 2, 1},
{"gettable", {LUA_T_CFUNCTION, {gettableFB}}, 2, 1},
{"arith", {LUA_T_CFUNCTION, {arithFB}}, 3, 1},
{"order", {LUA_T_CFUNCTION, {orderFB}}, 3, 1},
{"concat", {LUA_T_CFUNCTION, {concatFB}}, 2, 1},
{"settable", {LUA_T_CFUNCTION, {gettableFB}}, 3, 0},
{"gc", {LUA_T_CFUNCTION, {GDFB}}, 1, 0},
{"function", {LUA_T_CFUNCTION, {funcFB}}, -1, -1},
/* no fixed number of params or results */
{"getglobal", {LUA_T_CFUNCTION, {indexFB}}, 1, 1}
/* same default behavior of index FB */
};
#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_error("incorrect argument to function `setfallback'");
for (i=0; i<N_FB; i++)
{
if (strcmp(luaI_fallBacks[i].kind, name) == 0)
{
luaI_pushobject(&luaI_fallBacks[i].function);
luaI_fallBacks[i].function = *luaI_Address(func);
return;
}
}
/* name not found */
lua_error("incorrect argument to function `setfallback'");
}
static void errorFB (void)
{
lua_Object o = lua_getparam(1);
if (lua_isstring(o))
fprintf (stderr, "lua: %s\n", lua_getstring(o));
else
fprintf(stderr, "lua: unknown error\n");
}
static void indexFB (void)
{
lua_pushnil();
}
static void gettableFB (void)
{
lua_error("indexed expression not a table");
}
static void arithFB (void)
{
lua_error("unexpected type at conversion to number");
}
static void concatFB (void)
{
lua_error("unexpected type at conversion to string");
}
static void orderFB (void)
{
lua_error("unexpected type at comparison");
}
static void GDFB (void) { }
static void funcFB (void)
{
lua_error("call expression not a function");
}
/*
** Reference routines ** Reference routines
*/ */
static struct ref { static struct ref {
Object o; TObject o;
enum {LOCK, HOLD, FREE, COLLECTED} status; enum {LOCK, HOLD, FREE, COLLECTED} status;
} *refArray = NULL; } *refArray = NULL;
static int refSize = 0; static int refSize = 0;
int luaI_ref (Object *object, int lock) int luaI_ref (TObject *object, int lock)
{ {
int i; int i;
int oldSize; int oldSize;
if (tag(object) == LUA_T_NIL) if (ttype(object) == LUA_T_NIL)
return -1; /* special ref for nil */ return -1; /* special ref for nil */
for (i=0; i<refSize; i++) for (i=0; i<refSize; i++)
if (refArray[i].status == FREE) if (refArray[i].status == FREE)
@@ -151,9 +58,9 @@ void lua_unref (int ref)
} }
Object *luaI_getref (int ref) TObject *luaI_getref (int ref)
{ {
static Object nul = {LUA_T_NIL, {0}}; static TObject nul = {LUA_T_NIL, {0}};
if (ref == -1) if (ref == -1)
return &nul; return &nul;
if (ref >= 0 && ref < refSize && if (ref >= 0 && ref < refSize &&
@@ -164,7 +71,7 @@ Object *luaI_getref (int ref)
} }
void luaI_travlock (int (*fn)(Object *)) void luaI_travlock (int (*fn)(TObject *))
{ {
int i; int i;
for (i=0; i<refSize; i++) for (i=0; i<refSize; i++)
@@ -181,11 +88,274 @@ void luaI_invalidaterefs (void)
refArray[i].status = COLLECTED; refArray[i].status = COLLECTED;
} }
char *luaI_travfallbacks (int (*fn)(Object *))
/* -------------------------------------------
* 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; int i;
for (i=0; i<N_FB; i++) for (i=0; i<IM_N; i++)
if (fn(&luaI_fallBacks[i].function)) luaI_IMtable[-tag].int_method[i].ttype = LUA_T_NIL;
return luaI_fallBacks[i].kind; }
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; return NULL;
} }
/*
* ===================================================================
* compatibility with old fallback system
*/
static void errorFB (void)
{
lua_Object o = lua_getparam(1);
if (lua_isstring(o))
fprintf (stderr, "lua: %s\n", lua_getstring(o));
else
fprintf(stderr, "lua: unknown error\n");
}
static void nilFB (void) { }
static void typeFB (void)
{
lua_error("unexpected type");
}
static void fillvalids (IMS e, TObject *func)
{
int t;
for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++)
if (validevent(t, e))
luaI_IMtable[-t].int_method[e] = *func;
}
void luaI_setfallback (void)
{
static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL};
TObject oldfunc;
lua_CFunction replace;
char *name = luaL_check_string(1);
lua_Object func = lua_getparam(2);
luaI_initfallbacks();
luaL_arg_check(lua_isfunction(func), 2, "function expected");
switch (luaI_findstring(name, oldnames)) {
case 0: /* old error fallback */
oldfunc = errorim;
errorim = *luaI_Address(func);
replace = errorFB;
break;
case 1: /* old getglobal fallback */
oldfunc = luaI_IMtable[-LUA_T_NIL].int_method[IM_GETGLOBAL];
luaI_IMtable[-LUA_T_NIL].int_method[IM_GETGLOBAL] = *luaI_Address(func);
replace = nilFB;
break;
case 2: { /* old arith fallback */
int i;
oldfunc = luaI_IMtable[-LUA_T_USERDATA].int_method[IM_POW];
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 */
}
}
}
if (oldfunc.ttype != LUA_T_NIL)
luaI_pushobject(&oldfunc);
else
lua_pushcfunction(replace);
}

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: fallback.h,v 1.12 1996/04/22 18:00:37 roberto Exp roberto $ ** $Id: fallback.h,v 1.21 1997/04/02 23:04:12 roberto Exp roberto $
*/ */
#ifndef fallback_h #ifndef fallback_h
@@ -8,30 +8,53 @@
#include "lua.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
#define FB_GETGLOBAL 9
void luaI_setfallback (void); void luaI_setfallback (void);
int luaI_ref (Object *object, int lock); int luaI_ref (TObject *object, int lock);
Object *luaI_getref (int ref); TObject *luaI_getref (int ref);
void luaI_travlock (int (*fn)(Object *)); void luaI_travlock (int (*fn)(TObject *));
void luaI_invalidaterefs (void); void luaI_invalidaterefs (void);
char *luaI_travfallbacks (int (*fn)(Object *)); 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

10
func.c
View File

@@ -1,8 +1,8 @@
#include <stdlib.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"
@@ -83,13 +83,13 @@ 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;

106
hash.c
View File

@@ -3,14 +3,15 @@
** hash manager for lua ** hash manager for lua
*/ */
char *rcs_hash="$Id: hash.c,v 2.29 1996/02/14 18:25:04 roberto Exp roberto $"; char *rcs_hash="$Id: hash.c,v 2.40 1997/04/04 15:35:37 roberto Exp roberto $";
#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 nhash(t) ((t)->nhash) #define nhash(t) ((t)->nhash)
@@ -24,6 +25,8 @@ char *rcs_hash="$Id: hash.c,v 2.29 1996/02/14 18:25:04 roberto Exp roberto $";
#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;
@@ -46,47 +49,49 @@ int luaI_redimension (int nhash)
return 0; /* to avoid warnings */ return 0; /* to avoid warnings */
} }
static int 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 (((int)nvalue(ref))%nhash(t)); case LUA_T_FUNCTION:
case LUA_T_STRING: h = (IntPoint)ref->value.tf; break;
return (int)((tsvalue(ref)->hash)%nhash(t)); /* make it a valid index */ case LUA_T_CFUNCTION:
case LUA_T_FUNCTION: h = (IntPoint)fvalue(ref); break;
return (((IntPoint)ref->value.tf)%nhash(t)); case LUA_T_ARRAY:
case LUA_T_CFUNCTION: h = (IntPoint)avalue(ref); break;
return (((IntPoint)fvalue(ref))%nhash(t)); default:
case LUA_T_ARRAY: lua_error ("unexpected type to index table");
return (((IntPoint)avalue(ref))%nhash(t)); h = 0; /* UNREACHEABLE */
default: /* user data */ }
return (((IntPoint)uvalue(ref))%nhash(t)); if (h < 0) h = -h;
} return h%nhash(t); /* make it a valid index */
} }
int 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 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 int present (Hash *t, Object *ref) static int present (Hash *t, TObject *ref)
{ {
int 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;
@@ -104,7 +109,7 @@ static Node *hashnodecreate (int nhash)
int 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;
} }
@@ -119,6 +124,7 @@ static Hash *hashcreate (int 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;
} }
@@ -144,7 +150,7 @@ void lua_hashmark (Hash *h)
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);
@@ -154,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 */
} }
@@ -178,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;
@@ -230,7 +233,7 @@ static void rehash (Hash *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);
@@ -240,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)
{ {
int 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;
} }
@@ -252,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)
{ {
int 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)
@@ -268,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));
} }
@@ -283,17 +286,12 @@ Object *lua_hashdefine (Hash *t, Object *ref)
static void hashnext (Hash *t, int 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)));
@@ -304,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))
{ {

30
hash.h
View File

@@ -1,7 +1,7 @@
/* /*
** hash.h ** hash.h
** hash manager for lua ** hash manager for lua
** $Id: hash.h,v 2.11 1996/03/08 12:04:04 roberto Exp roberto $ ** $Id: hash.h,v 2.14 1997/03/19 19:41:10 roberto Exp roberto $
*/ */
#ifndef hash_h #ifndef hash_h
@@ -10,29 +10,29 @@
#include "types.h" #include "types.h"
#include "opcode.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;
Node *node; int nhash;
int nhash; int nuse;
int nuse; int htag;
char mark; char mark;
} Hash; } Hash;
int lua_equalObj (Object *t1, Object *t2); int lua_equalObj (TObject *t1, TObject *t2);
int luaI_redimension (int nhash); int luaI_redimension (int nhash);
Hash *lua_createarray (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

311
inout.c
View File

@@ -5,17 +5,22 @@
** Also provides some predefined lua functions. ** Also provides some predefined lua functions.
*/ */
char *rcs_inout="$Id: inout.c,v 2.35 1996/03/19 16:50:24 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 <string.h>
#include "auxlib.h"
#include "lex.h" #include "lex.h"
#include "opcode.h" #include "opcode.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 "mem.h" #include "hash.h"
#include "luamem.h"
#include "fallback.h"
#include "luamem.h"
/* Exported variables */ /* Exported variables */
@@ -23,6 +28,12 @@ Word lua_linenumber;
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;
@@ -31,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;
} }
/* /*
@@ -58,7 +70,6 @@ FILE *lua_openfile (char *fn)
fp = fopen (fn, "r"); fp = fopen (fn, "r");
if (fp == NULL) if (fp == NULL)
return NULL; return NULL;
lua_linenumber = 1;
lua_parsedfile = luaI_createfixedstring(fn)->str; lua_parsedfile = luaI_createfixedstring(fn)->str;
return fp; return fp;
} }
@@ -78,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 = luaI_createfixedstring("(string)")->str; sprintf(buff, "(dostring) >> %.20s%s", s,
(strlen(s) > SIZE_PREF) ? "..." : "");
lua_parsedfile = luaI_createfixedstring(buff)->str;
} }
/* /*
@@ -94,69 +108,67 @@ 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);
char *fname = NULL; if (lua_dofile(fname) == 0)
if (lua_isstring(obj)) if (passresults() == 0)
fname = lua_getstring(obj); lua_pushuserdata(NULL); /* at least one result to signal no errors */
else if (obj != LUA_NOOBJECT)
lua_error("invalid argument to function `dofile'");
/* else fname = NULL */
if (!lua_dofile(fname))
lua_pushnumber(1);
else
lua_pushnil();
} }
static char *tostring (lua_Object obj) static char *tostring (lua_Object obj)
{ {
char *buff = luaI_buffer(20); TObject *o = luaI_Address(obj);
if (lua_isstring(obj)) /* get strings and numbers */ switch (ttype(o)) {
return lua_getstring(obj); case LUA_T_NUMBER: case LUA_T_STRING:
else switch(lua_type(obj)) return lua_getstring(obj);
{ case LUA_T_ARRAY: case LUA_T_FUNCTION:
case LUA_T_FUNCTION: case LUA_T_CFUNCTION: case LUA_T_NIL:
sprintf(buff, "function: %p", (luaI_Address(obj))->value.tf); return luaI_typenames[-ttype(o)];
break; case LUA_T_USERDATA: {
case LUA_T_CFUNCTION: char *buff = luaI_buffer(100);
sprintf(buff, "cfunction: %p", lua_getcfunction(obj)); int size = o->value.ts->size;
break; int i;
case LUA_T_ARRAY: strcpy(buff, "userdata: ");
sprintf(buff, "table: %p", avalue(luaI_Address(obj))); if (size > 10) size = 10;
break; for (i=0; i<size; i++)
case LUA_T_NIL: sprintf(buff+strlen(buff), "%.2X",
sprintf(buff, "nil"); (int)(unsigned char)o->value.ts->str[i]);
break; return buff;
default: }
sprintf(buff, "userdata: %p", lua_getuserdata(obj)); default: return "<unknown object>";
break;
} }
return buff;
} }
void luaI_tostring (void) static void luaI_tostring (void)
{ {
lua_pushstring(tostring(lua_getparam(1))); lua_pushstring(tostring(lua_getparam(1)));
} }
void luaI_print (void) static void luaI_print (void)
{ {
int i = 1; int i = 1;
lua_Object obj; lua_Object obj;
@@ -164,83 +176,192 @@ void luaI_print (void)
printf("%s\n", tostring(obj)); printf("%s\n", tostring(obj));
} }
/* static void luaI_type (void)
** Internal function: return an object type.
*/
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_pushnumber(lua_getnumber(o)); lua_pushnumber(lua_getnumber(o));
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);
} }
void luaI_assert (void) static void luaI_assert (void)
{ {
lua_Object p = lua_getparam(1); lua_Object p = lua_getparam(1);
if (p == LUA_NOOBJECT || lua_isnil(p)) if (p == LUA_NOOBJECT || lua_isnil(p))
lua_error("assertion failed!"); lua_error("assertion failed!");
} }
void luaI_setglobal (void) static void luaI_setglobal (void)
{ {
lua_Object name = lua_getparam(1);
lua_Object value = lua_getparam(2); lua_Object value = lua_getparam(2);
if (!lua_isstring(name)) luaL_arg_check(value != LUA_NOOBJECT, 2, NULL);
lua_error("incorrect argument to function `setglobal'");
lua_pushobject(value); lua_pushobject(value);
lua_storeglobal(lua_getstring(name)); lua_setglobal(luaL_check_string(1));
lua_pushobject(value); /* return given value */ lua_pushobject(value); /* return given value */
} }
void luaI_getglobal (void) static void luaI_rawsetglobal (void)
{ {
lua_Object name = lua_getparam(1); lua_Object value = lua_getparam(2);
if (!lua_isstring(name)) luaL_arg_check(value != LUA_NOOBJECT, 2, NULL);
lua_error("incorrect argument to function `getglobal'"); lua_pushobject(value);
lua_pushobject(lua_getglobal(lua_getstring(name))); 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.14 1996/03/15 13:13:13 roberto Exp roberto $ ** $Id: inout.h,v 1.16 1996/05/28 21:07:32 roberto Exp roberto $
*/ */
@@ -19,15 +19,6 @@ 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 luaI_tostring (void);
void luaI_print (void);
void luaI_type (void);
void lua_obj2number (void);
void luaI_error (void);
void luaI_assert (void);
void luaI_setglobal (void);
void luaI_getglobal (void);
#endif #endif

662
iolib.c
View File

@@ -1,22 +1,18 @@
/*
** iolib.c
** Input/output library to LUA
*/
char *rcs_iolib="$Id: iolib.c,v 1.43 1996/04/30 21:13:55 roberto Exp roberto $";
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.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
@@ -31,515 +27,209 @@ int pclose();
static void pushresult (int i) static void pushresult (int i)
{ {
if (i) if (i)
lua_pushnumber (1); lua_pushuserdata(NULL);
else else {
lua_pushnil(); lua_pushnil();
} #ifndef NOSTRERROR
lua_pushstring(strerror(errno));
static void closeread (void) #else
{ lua_pushstring("O.S. unable to define the error");
if (in != stdin) #endif
{
if (pclose(in) == -1)
fclose(in);
in = stdin;
} }
} }
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 = 1 -> success
** 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);
FILE *fp = fopen (s, "a"); FILE *fp = fopen (s, "a");
if (fp == NULL) if (fp != NULL) {
lua_pushnil(); lua_outfile = fp;
else lua_pushusertag(lua_outfile, lua_tagio);
{
if (out != stdout) fclose (out);
out = fp;
lua_pushnumber(1);
}
}
static char getformat (char *f, int *just, int *m, int *n)
{
int t;
switch (*f++)
{
case 'q': case 'Q':
case 's': case 'S':
case 'i': case 'I':
t = tolower(*(f-1));
break;
case 'f': case 'F': case 'g': case 'G': case 'e': case 'E':
t = 'f';
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;
} }
/* #define NEED_OTHER (EOF-1) /* just some flag different from EOF */
** 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)
luaI_addchar(c);
return c;
}
static void read_until_blank (void)
{
int c;
while((c = fgetc(in)) != EOF && !isspace(c))
luaI_addchar(c);
if (c != EOF) ungetc(c,in);
}
static void read_m (int m)
{
int c;
while (m-- && (c = fgetc(in)) != EOF)
luaI_addchar(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)
lua_pushnil();
else
lua_pushstring(luaI_addchar(0));
}
else
{
double d;
char dummy;
char *s;
luaI_addchar(c);
read_until_blank();
s = luaI_addchar(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;
luaI_addchar(0); /* initialize buffer */ char *p = luaL_opt_string(1, "[^\n]*{\n}");
if (o == LUA_NOOBJECT) /* free format */ int inskip = 0; /* to control {skips} */
read_free(); int c = NEED_OTHER;
else /* formatted */ luaI_emptybuff();
{ while (*p) {
int m, dummy1, dummy2; if (*p == '{') {
switch (getformat(lua_check_string(1, "read"), &dummy1, &m, &dummy2)) inskip++;
{ p++;
case 's':
{
char *s;
if (m < 0)
read_until_blank();
else
read_m(m);
s = luaI_addchar(0);
if ((m >= 0 && strlen(s) == m) || (m < 0 && strlen(s) > 0))
lua_pushstring(s);
else
lua_pushnil();
break;
}
case 'i': /* can read as float, since it makes no difference to Lua */
case 'f':
{
double d;
int result;
if (m < 0)
result = fscanf(in, "%lf", &d);
else
{
read_m(m);
result = sscanf(luaI_addchar(0), "%lf", &d);
}
if (result == 1)
lua_pushnumber(d);
else
lua_pushnil();
break;
}
default:
lua_arg_error("read (format)");
} }
} else if (*p == '}') {
} if (inskip == 0)
lua_error("unbalanced braces in read pattern");
inskip--;
/* p++;
** Read characters until a given one. The delimiter is not read. }
*/ else {
static void io_readuntil (void) char *ep = luaL_item_end(p); /* get what is next */
{ int m; /* match result */
int del, c; if (c == NEED_OTHER) c = getc(lua_infile);
lua_Object p = lua_getparam(1); m = (c == EOF) ? 0 : luaL_singlematch((char)c, p);
luaI_addchar(0); /* initialize buffer */ if (m) {
if (p == LUA_NOOBJECT || lua_isnil(p)) if (inskip == 0) luaI_addchar(c);
del = EOF; c = NEED_OTHER;
else }
del = *lua_check_string(1, "readuntil"); switch (*ep) {
c = read_until_char(del); case '*': /* repetition */
if (c != EOF) ungetc(c,in); if (!m) p = ep+1; /* else stay in (repeat) the same item */
lua_pushstring(luaI_addchar(0)); break;
} case '?': /* optional */
p = ep+1; /* continues reading the pattern */
break;
/* default:
** Write a variable. On error put 0 on stack, otherwise put 1. if (m) p = ep; /* continues reading the pattern */
** LUA interface: else
** status = write (variable [,format]) goto break_while; /* pattern fails */
** }
** O formato pode ter um dos seguintes especificadores: }
** } break_while:
** s ou S -> para string if (c >= 0) /* not EOF nor NEED_OTHER? */
** f ou F, g ou G, e ou E -> para reais ungetc(c, lua_infile);
** i ou I -> para inteiros buff = luaI_addchar(0);
** if (*buff != 0 || *p == 0) /* read something or did not fail? */
** Estes especificadores podem vir seguidos de: lua_pushstring(buff);
**
** [?][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_quoted (int just, int m)
{
luaI_addchar(0);
luaI_addquoted(lua_check_string(1, "write"));
return write_string(luaI_addchar(0), just, m);
}
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)
int t = lua_type(o1); status = status && (fputs(s, lua_outfile) != EOF);
if (t == LUA_T_NUMBER) pushresult(status);
status = fprintf (out, "%g", lua_getnumber(o1)) >= 0;
else if (t == LUA_T_STRING)
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 'q':
status = write_quoted(just, m);
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)
{ {
pushresult(remove(lua_check_string(1, "remove")) == 0); pushresult(remove(luaL_check_string(1)) == 0);
} }
static void io_rename (void) static void io_rename (void)
{ {
char *f1 = lua_check_string(1, "rename"); pushresult(rename(luaL_check_string(1),
char *f2 = lua_check_string(2, "rename"); luaL_check_string(2)) == 0);
pushresult(rename(f1, f2) == 0);
} }
static void io_tmpname (void) static void io_tmpname (void)
{ {
lua_pushstring(tmpnam(NULL)); lua_pushstring(tmpnam(NULL));
} }
static void io_errorno (void)
{
/* lua_pushstring(strerror(errno));*/
}
/*
** To get a environment variable
*/
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 */
lua_pushstring(env); /* if NULL push nil */
} }
/*
** Return user formatted time stamp
*/
static void io_date (void) static void io_date (void)
{ {
time_t t; time_t t;
struct tm *tm; struct tm *tm;
char *s; char *s = luaL_opt_string(1, "%c");
char b[BUFSIZ]; char b[BUFSIZ];
if (lua_getparam(1) == LUA_NOOBJECT) time(&t); tm = localtime(&t);
s = "%c"; if (strftime(b,sizeof(b),s,tm))
else lua_pushstring(b);
s = lua_check_string(1, "date"); else
time(&t); tm = localtime(&t); lua_error("invalid `date' format");
if (strftime(b,sizeof(b),s,tm))
lua_pushstring(b);
else
lua_error("invalid `date' format");
} }
/*
** To exit
*/
static void io_exit (void) static void io_exit (void)
{ {
lua_Object o = lua_getparam(1); lua_Object o = lua_getparam(1);
int code = lua_isnumber(o) ? (int)lua_getnumber(o) : 1; exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1);
exit(code);
} }
/*
** 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 (fgets(buffer, sizeof(buffer), stdin) == 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);
} }
} }
@@ -547,24 +237,20 @@ static void io_debug (void)
static 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 (*lua_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, "`%s' fallback", 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);
@@ -585,34 +271,78 @@ static 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);
} }
static struct lua_reg iolib[] = { /* --------------------------------------------
* functions to manipulate userdata
*/
static void getbyte (void)
{
lua_Object ud = lua_getparam(1);
int i = luaL_opt_number(2, -1);
luaL_arg_check(lua_isuserdata(ud), 1, "userdata expected");
if (i == -1)
lua_pushnumber(lua_getbindatasize(ud));
else {
i--;
if (0 <= i && i < lua_getbindatasize(ud))
lua_pushnumber(*(((char *)lua_getbindata(ud))+i));
else
lua_pushnil();
}
}
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}, {"readfrom", io_readfrom},
{"writeto", io_writeto}, {"writeto", io_writeto},
{"appendto", io_appendto}, {"appendto", io_appendto},
{"read", io_read}, {"read", io_read},
{"readuntil",io_readuntil},
{"write", io_write}, {"write", io_write},
{"execute", io_execute}, {"execute", io_execute},
{"remove", io_remove}, {"remove", io_remove},
{"rename", io_rename}, {"rename", io_rename},
{"tmpname", io_tmpname}, {"tmpname", io_tmpname},
{"ioerror", io_errorno},
{"getenv", io_getenv}, {"getenv", io_getenv},
{"date", io_date}, {"date", io_date},
{"exit", io_exit}, {"exit", io_exit},
{"debug", io_debug}, {"debug", io_debug},
{"getbyte", getbyte},
{"userdata", newuserdata},
{"print_stack", errorfb} {"print_stack", errorfb}
}; };
void iolib_open (void) void iolib_open (void)
{ {
luaI_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); lua_tagio = lua_newtag();
lua_setfallback("error", errorfb); lua_infile=stdin; lua_outfile=stdout;
luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
lua_seterrormethod(errorfb);
} }

375
lex.c
View File

@@ -1,10 +1,11 @@
char *rcs_lex = "$Id: lex.c,v 2.31 1996/03/19 16:50:24 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 <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 "lex.h" #include "lex.h"
@@ -12,34 +13,56 @@ char *rcs_lex = "$Id: lex.c,v 2.31 1996/03/19 16:50:24 roberto Exp roberto $";
#include "luadebug.h" #include "luadebug.h"
#include "parser.h" #include "parser.h"
#define MINBUFF 260 #define MINBUFF 250
#define next() { current = input(); } #define next() (current = input())
#define save(x) { *yytextLast++ = (x); } #define save(x) (yytext[tokensize++] = (x))
#define save_and_next() { save(current); next(); } #define save_and_next() (save(current), next())
static int current;
static char *yytext = NULL;
static int textsize = 0;
static char *yytextLast;
static Input input; static int current; /* look ahead character */
static Input input; /* input function */
#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 */
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));
} }
@@ -80,94 +103,183 @@ void luaI_addReserved (void)
} }
static void growtext (void) /*
** Pragma handling
*/
#define PRAGMASIZE 20
static void skipspace (void)
{ {
int size = yytextLast - yytext; while (current == ' ' || current == '\t') next();
textsize = growvector(&yytext, textsize, char, lexEM, MAX_WORD);
yytextLast = yytext + size;
} }
static int read_long_string (void) static int checkcond (char *buff)
{ {
int cont = 0; if (strcmp(buff, "nil") == 0)
int spaceleft = textsize - (yytextLast - yytext); return 0;
while (1) else if (strcmp(buff, "1") == 0)
{ return 1;
if (spaceleft <= 2) /* may read more than 1 char in one cicle */ else if (isalpha((unsigned char)buff[0]))
{ return luaI_globaldefined(buff);
growtext(); else {
spaceleft = textsize - (yytextLast - yytext); luaI_auxsynterrbf("invalid $if condition", buff);
} return 0; /* to avoid warnings */
switch (current)
{
case EOF:
case 0:
return WRONGTOKEN;
case '[':
save_and_next(); spaceleft--;
if (current == '[')
{
cont++;
save_and_next(); spaceleft--;
}
continue;
case ']':
save_and_next(); spaceleft--;
if (current == ']')
{
if (cont == 0) return STRING;
cont--;
save_and_next(); spaceleft--;
}
continue;
case '\n':
lua_linenumber++; /* goes through */
default:
save_and_next(); spaceleft--;
}
} }
} }
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 tokensize = 2; /* '[[' already stored */
while (1)
{
if (buffsize-tokensize <= 2) /* may read more than 1 char in one cicle */
yytext = luaI_buffer(buffsize *= 2);
switch (current)
{
case 0:
save(0);
return WRONGTOKEN;
case '[':
save_and_next();
if (current == '[')
{
cont++;
save_and_next();
}
continue;
case ']':
save_and_next();
if (current == ']')
{
if (cont == 0) goto endloop;
cont--;
save_and_next();
}
continue;
case '\n':
save('\n');
inclinenumber();
continue;
default:
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 luaY_lex (void)
{ {
double 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;
switch (current) switch (current)
{ {
case EOF: case '\n':
case 0: inclinenumber();
return 0; linelasttoken = lua_linenumber;
case '\n': linelasttoken = ++lua_linenumber;
case ' ':
case '\r': /* CR: to avoid problems with DOS/Windows */
case '\t':
next();
continue; continue;
case '$': case ' ': case '\t': case '\r': /* CR: to avoid problems with DOS */
next(); next();
while (isalnum(current) || current == '_') continue;
save_and_next();
*yytextLast = 0;
if (strcmp(yytext, "debug") == 0)
{
luaY_lval.vInt = 1;
return DEBUG;
}
else if (strcmp(yytext, "nodebug") == 0)
{
luaY_lval.vInt = 0;
return DEBUG;
}
return WRONGTOKEN;
case '-': case '-':
save_and_next(); save_and_next();
@@ -181,12 +293,7 @@ int luaY_lex (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 ']]' */
luaY_lval.vWord = luaI_findconstantbyname(yytext+2);
return STRING;
} }
case '=': case '=':
@@ -213,21 +320,16 @@ int luaY_lex (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 '\' */
@@ -236,17 +338,19 @@ int luaY_lex (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;
case '\n': lua_linenumber++; /* goes through */ case '\n': save('\n'); inclinenumber(); break;
default : save(current); next(); 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);
luaY_lval.vWord = luaI_findconstantbyname(yytext); luaY_lval.vWord = luaI_findconstantbyname(yytext+1);
tokensize--;
save(del); save(0); /* restore delimiter */
return STRING; return STRING;
} }
@@ -265,8 +369,10 @@ int luaY_lex (void)
case '_': case '_':
{ {
TaggedString *ts; TaggedString *ts;
do { save_and_next(); } while (isalnum(current) || current == '_'); do {
*yytextLast = 0; save_and_next();
} while (isalnum((unsigned char)current) || current == '_');
save(0);
ts = lua_createstring(yytext); ts = lua_createstring(yytext);
if (ts->marked > 2) if (ts->marked > 2)
return ts->marked; /* reserved word */ return ts->marked; /* reserved word */
@@ -280,9 +386,14 @@ int luaY_lex (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;
@@ -290,12 +401,24 @@ int luaY_lex (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.0*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();
} while (isdigit((unsigned char)current));
if (current == '.') {
save_and_next();
if (current == '.')
luaI_syntaxerror(
"ambiguous syntax (decimal point x string concatenation)");
}
fraction:
{ double da=0.1; { double da=0.1;
while (isdigit(current)) while (isdigit((unsigned char)current))
{a+=(current-'0')*da; da/=10.0; save_and_next()}; {
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;
@@ -304,8 +427,12 @@ fraction:
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.0*e+(current-'0'); save_and_next(); } while (isdigit(current)); save(0); return WRONGTOKEN; }
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) for (ea=neg?0.1:10.0; e>0; e>>=1)
{ {
if (e & 1) a*=ea; if (e & 1) a*=ea;
@@ -313,14 +440,20 @@ fraction:
} }
} }
luaY_lval.vFloat = a; luaY_lval.vFloat = a;
save(0);
return NUMBER; return NUMBER;
} }
default: /* also end of file */ case 0:
{ save(0);
if (iflevel > 0)
luaI_syntaxerror("missing $endif");
return 0;
default:
save_and_next(); save_and_next();
return yytext[0]; return yytext[0];
}
} }
} }
} }

4
lex.h
View File

@@ -1,7 +1,7 @@
/* /*
** lex.h ** lex.h
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
** $Id: lex.h,v 1.1 1996/02/13 17:30:39 roberto Exp roberto $ ** $Id: lex.h,v 1.2 1996/02/14 13:35:51 roberto Exp roberto $
*/ */
#ifndef lex_h #ifndef lex_h
@@ -11,7 +11,7 @@
typedef int (*Input) (void); typedef int (*Input) (void);
void lua_setinput (Input fn); void lua_setinput (Input fn);
char *lua_lasttext (void); void luaI_syntaxerror (char *s);
int luaY_lex (void); int luaY_lex (void);
void luaI_addReserved (void); void luaI_addReserved (void);

107
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.9 1996/04/23 12:43:07 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,45 +11,23 @@ char *rcs_lua="$Id: lua.c,v 1.9 1996/04/23 12:43:07 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 #ifdef _POSIX_SOURCE
/* #include <unistd.h>
** although this function is POSIX, there is no standard header file that
** defines it
*/
int isatty (int fd);
#else #else
#define isatty(x) (x==0) /* assume stdin is a tty */ #define isatty(x) (x==0) /* assume stdin is a tty */
#endif #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(0)) if (isatty(0)) {
{ char buffer[250];
char buffer[250]; while (fgets(buffer, sizeof(buffer), stdin) != 0) {
while (fgets(buffer, sizeof(buffer), stdin) != 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 */
@@ -58,43 +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)
{ printf("%s %s\n(written by %s)\n\n",
result = lua_dofile (argv[i]); LUA_VERSION, LUA_COPYRIGHT, LUA_AUTHORS);
if (result) else if ((strcmp(argv[i], "-e") == 0 && i++) || strchr(argv[i], '=')) {
fprintf(stderr, "lua: error trying to run file %s\n", 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;
} }

97
lua.h
View File

@@ -1,61 +1,50 @@
/* /*
** 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.27 1996/04/25 14:10:00 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.4" #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(_)
#define lua_isnil(_) (lua_type(_)==LUA_T_NIL) int lua_isnil (lua_Object object);
#define lua_istable(_) (lua_type(_)==LUA_T_ARRAY) int lua_istable (lua_Object object);
#define lua_isuserdata(_) (lua_type(_)>=LUA_T_USERDATA) int lua_isuserdata (lua_Object object);
#define lua_iscfunction(_) (lua_type(_)==LUA_T_CFUNCTION) int lua_iscfunction (lua_Object object);
int lua_isnumber (lua_Object object); int lua_isnumber (lua_Object object);
int lua_isstring (lua_Object object); int lua_isstring (lua_Object object);
int lua_isfunction (lua_Object object); int lua_isfunction (lua_Object object);
@@ -63,25 +52,31 @@ 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_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_ref (int lock); int lua_ref (int lock); /* In: value */
lua_Object lua_getref (int ref); lua_Object lua_getref (int ref);
void lua_pushref (int ref); void lua_pushref (int ref);
void lua_unref (int ref); void lua_unref (int ref);
@@ -89,16 +84,25 @@ void lua_unref (int ref);
lua_Object lua_createtable (void); lua_Object lua_createtable (void);
/* =============================================================== */
/* some useful macros */ /* some useful macros */
#define lua_refobject(o,l) (lua_pushobject(o), lua_ref(l)) #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)
/* for compatibility with old versions. Avoid using these macros */ /* =============================================================== */
/* for compatibility with old versions. Avoid using these macros/functions */
lua_Object lua_setfallback (char *event, lua_CFunction fallback);
#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_lockobject(o) lua_refobject(o,1)
#define lua_lock() lua_ref(1) #define lua_lock() lua_ref(1)
@@ -108,9 +112,10 @@ lua_Object lua_createtable (void);
#define lua_pushliteral(o) lua_pushstring(o) #define lua_pushliteral(o) lua_pushstring(o)
#define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_getsubscript()) #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_getsubscript()) #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

168
lua.stx
View File

@@ -1,12 +1,13 @@
%{ %{
char *rcs_luastx = "$Id: lua.stx,v 3.35 1996/03/08 12:02:37 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 "luadebug.h" #include "luadebug.h"
#include "mem.h" #include "luamem.h"
#include "lex.h" #include "lex.h"
#include "opcode.h" #include "opcode.h"
#include "hash.h" #include "hash.h"
@@ -49,8 +50,6 @@ 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; int lua_debug = 0;
@@ -58,76 +57,55 @@ int lua_debug = 0;
static void yyerror (char *s) static void yyerror (char *s)
{ {
char msg[256]; luaI_syntaxerror(s);
char *token = lua_lasttext(); }
if (token[0] == 0)
token = "<eof>"; static void check_space (int i)
sprintf (msg,"%s; last token read: \"%s\" at line %d in file `%s'", {
s, token, lua_linenumber, lua_parsedfile); if (pc+i>maxcurr-1) /* 1 byte free to code HALT of main code */
lua_error (msg); 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);
maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT);
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, int n) static void code_word_at (Byte *p, int n)
{ {
CodeWord code; Word w = n;
if ((Word)n != n) if (w != n)
yyerror("block too big"); yyerror("block too big");
code.w = (Word)n; memcpy(p, &w, sizeof(Word));
*p++ = code.m.c1;
*p++ = code.m.c2;
}
static void push_field (Word name)
{
if (nfields < MAXFIELDS)
fields[nfields++] = name;
else
yyerror ("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)
@@ -170,11 +148,22 @@ static void add_varbuffer (Long var)
yyerror ("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)
{ {
@@ -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 */
@@ -418,7 +420,7 @@ void lua_parse (TFunc *tf)
TaggedString *pTStr; TaggedString *pTStr;
} }
%start functionlist %start chunk
%token WRONGTOKEN %token WRONGTOKEN
%token NIL %token NIL
@@ -426,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 <pTStr> 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
@@ -440,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
@@ -455,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
{ {
@@ -476,8 +475,7 @@ 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_createfixedstring("self")); add_localvar(luaI_createfixedstring("self"));
@@ -539,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);
@@ -580,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); }
; ;
@@ -603,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; }
@@ -674,14 +672,23 @@ 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 { add_localvar($1); } parlist1 : par { $$ = $1; }
| parlist1 ',' NAME { add_localvar($3); } | parlist1 ',' par
{
if ($1)
lua_error("invalid parameter list");
$$ = $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); }
semicolonpart semicolonpart
@@ -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,9 +759,8 @@ var : singlevar { $$ = $1; }
} }
| varexp '.' NAME | varexp '.' NAME
{ {
code_byte(PUSHSTRING); code_constant($3);
code_word(luaI_findconstant($3)); $$ = 0; /* indexed variable */
$$ = 0; /* indexed variable */
} }
; ;
@@ -782,7 +789,4 @@ decinit : /* empty */ { $$ = 0; }
| '=' exprlist1 { $$ = $2; } | '=' exprlist1 { $$ = $2; }
; ;
setdebug : DEBUG { lua_debug = $1; }
;
%% %%

View File

@@ -2,7 +2,7 @@
** 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.7 1996/03/14 15:53:09 roberto Exp roberto $ ** $Id: lualib.h,v 1.12 1997/03/18 15:30:50 roberto Exp roberto $
*/ */
#ifndef lualib_h #ifndef lualib_h
@@ -15,19 +15,15 @@ void strlib_open (void);
void mathlib_open (void); void mathlib_open (void);
/* auxiliar functions (private) */ /* auxiliar functions (private) */
struct lua_reg {
char *name;
lua_CFunction func;
};
void luaI_openlib (struct lua_reg *l, int n);
void lua_arg_error(char *funcname);
char *lua_check_string (int numArg, char *funcname);
double lua_check_number (int numArg, char *funcname);
char *luaI_addchar (int c); char *luaI_addchar (int c);
void luaI_emptybuff (void);
void luaI_addquoted (char *s); void luaI_addquoted (char *s);
char *luaL_item_end (char *p);
int luaL_singlematch (int c, char *p);
#endif #endif

126
luamem.c
View File

@@ -3,42 +3,37 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_mem = "$Id: mem.c,v 1.11 1996/03/21 18:54:29 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 "mem.h" #include "luamem.h"
#include "lua.h" #include "lua.h"
#define mem_error() lua_error(memEM) #define DEBUG 0
#if !DEBUG
void luaI_free (void *block) void luaI_free (void *block)
{ {
if (block) if (block)
{ {
*((int *)block) = -1; /* to catch errors */ *((char *)block) = -1; /* to catch errors */
free(block); free(block);
} }
} }
void *luaI_malloc (unsigned long size)
{
void *block = malloc((size_t)size);
if (block == NULL)
mem_error();
return block;
}
void *luaI_realloc (void *oldblock, unsigned long size) void *luaI_realloc (void *oldblock, unsigned long size)
{ {
void *block = oldblock ? realloc(oldblock, (size_t)size) : void *block;
malloc((size_t)size); 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)
mem_error(); lua_error(memEM);
return block; return block;
} }
@@ -52,7 +47,7 @@ int luaI_growvector (void **block, unsigned long nelems, int size,
if (nelems > limit) if (nelems > limit)
nelems = limit; nelems = limit;
*block = luaI_realloc(*block, nelems*size); *block = luaI_realloc(*block, nelems*size);
return (int) nelems; return (int)nelems;
} }
@@ -65,3 +60,100 @@ void* luaI_buffer (unsigned long size)
return buffer; 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,11 +1,11 @@
/* /*
** mem.c ** mem.c
** memory manager for lua ** memory manager for lua
** $Id: mem.h,v 1.6 1996/03/21 18:54:29 roberto Exp 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
@@ -24,12 +24,12 @@
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); void *luaI_buffer (unsigned long size);
int luaI_growvector (void **block, unsigned long nelems, int size, int luaI_growvector (void **block, unsigned long nelems, int size,
char *errormsg, unsigned long limit); char *errormsg, unsigned long limit);
#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,e,l) \ #define growvector(old,n,s,e,l) \

View File

@@ -1,13 +1,16 @@
# $Id: makefile,v 1.25 1996/05/06 14:38:40 roberto Exp $ # $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
# define (undefine) POSIX if your system is (not) POSIX compliant # define (undefine) _POSIX_SOURCE if your system is (not) POSIX compliant
CONFIG = -DPOPEN -DPOSIX #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
@@ -15,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 \
@@ -25,9 +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 undump.o \
auxlib.o
LIBOBJS = \ LIBOBJS = \
iolib.o \ iolib.o \
@@ -35,28 +40,28 @@ 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 : $(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 y.tab.c y.tab.h : lua.stx
# yacc++ -d lua.stx yacc -d lua.stx
#parser.c : y.tab.c parser.c : y.tab.c
# sed -e 's/yy/luaY_/g' -e 's/malloc\.h/stdlib\.h/g' y.tab.c > parser.c sed -e 's/yy/luaY_/g' -e 's/malloc\.h/stdlib\.h/g' y.tab.c > parser.c
#parser.h : y.tab.h parser.h : y.tab.h
# sed -e 's/yy/luaY_/g' y.tab.h > parser.h sed -e 's/yy/luaY_/g' y.tab.h > parser.h
clear : clear :
rcsclean rcsclean
@@ -65,28 +70,36 @@ clear :
co lua.h lualib.h luadebug.h co lua.h lualib.h luadebug.h
#% : RCS/%,v %.h : RCS/%.h,v
# co $@ co $@
%.c : RCS/%.c,v
co $@
fallback.o : fallback.c mem.h fallback.h lua.h opcode.h types.h tree.h func.h \ auxlib.o: auxlib.c lua.h auxlib.h
table.h fallback.o: fallback.c auxlib.h lua.h luamem.h fallback.h opcode.h \
func.o : func.c luadebug.h lua.h table.h tree.h types.h opcode.h func.h mem.h types.h tree.h func.h table.h hash.h
hash.o : hash.c mem.h opcode.h lua.h types.h tree.h func.h hash.h table.h func.o: func.c luadebug.h lua.h table.h tree.h types.h opcode.h func.h \
inout.o : inout.c lex.h opcode.h lua.h types.h tree.h func.h inout.h table.h \ luamem.h
mem.h hash.o: hash.c luamem.h opcode.h lua.h types.h tree.h func.h hash.h \
iolib.o : iolib.c lua.h luadebug.h lualib.h table.h auxlib.h
lex.o : lex.c mem.h tree.h types.h table.h opcode.h lua.h func.h lex.h inout.h \ inout.o: inout.c auxlib.h lua.h lex.h opcode.h types.h tree.h func.h \
luadebug.h parser.h inout.h table.h hash.h luamem.h fallback.h
lua.o : lua.c lua.h lualib.h iolib.o: iolib.c lua.h auxlib.h luadebug.h lualib.h
mathlib.o : mathlib.c lualib.h lua.h lex.o: lex.c auxlib.h lua.h luamem.h tree.h types.h table.h opcode.h \
mem.o : mem.c mem.h lua.h table.h tree.h types.h opcode.h func.h func.h lex.h inout.h luadebug.h parser.h
opcode.o : opcode.c luadebug.h lua.h mem.h opcode.h types.h tree.h func.h hash.h \ lua.o: lua.c lua.h lualib.h
inout.h table.h fallback.h undump.h luamem.o: luamem.c luamem.h lua.h
parser.o : parser.c luadebug.h lua.h mem.h lex.h opcode.h types.h tree.h func.h \ mathlib.o: mathlib.c lualib.h lua.h auxlib.h
hash.h inout.h table.h opcode.o: opcode.c luadebug.h lua.h luamem.h opcode.h types.h tree.h \
strlib.o : strlib.c lua.h lualib.h func.h hash.h inout.h table.h fallback.h undump.h auxlib.h
table.o : table.c mem.h opcode.h lua.h types.h tree.h func.h hash.h table.h \ parser.o: parser.c luadebug.h lua.h luamem.h lex.h opcode.h types.h \
inout.h fallback.h luadebug.h tree.h func.h hash.h inout.h table.h
tree.o : tree.c mem.h lua.h tree.h types.h lex.h hash.h opcode.h func.h table.h strlib.o: strlib.c lua.h auxlib.h lualib.h
undump.o : undump.c opcode.h lua.h types.h tree.h func.h mem.h table.h undump.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

1799
manual.tex

File diff suppressed because it is too large Load Diff

View File

@@ -3,12 +3,13 @@
** Mathematics library to LUA ** Mathematics library to LUA
*/ */
char *rcs_mathlib="$Id: mathlib.c,v 1.16 1996/04/25 14:10:00 roberto Exp roberto $"; char *rcs_mathlib="$Id: mathlib.c,v 1.22 1997/04/04 22:24:51 roberto Exp roberto $";
#include <stdlib.h> #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.16 1996/04/25 14:10:00 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_getref(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,33 +139,33 @@ 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);
} }
@@ -191,11 +176,11 @@ static void math_random (void)
static void math_randomseed (void) static void math_randomseed (void)
{ {
srand(lua_check_number(1, "randomseed")); srand(luaL_check_number(1));
} }
static struct lua_reg mathlib[] = { static struct luaL_reg mathlib[] = {
{"abs", math_abs}, {"abs", math_abs},
{"sin", math_sin}, {"sin", math_sin},
{"cos", math_cos}, {"cos", math_cos},
@@ -224,7 +209,7 @@ static struct lua_reg mathlib[] = {
*/ */
void mathlib_open (void) void mathlib_open (void)
{ {
luaI_openlib(mathlib, (sizeof(mathlib)/sizeof(mathlib[0]))); luaL_openlib(mathlib, (sizeof(mathlib)/sizeof(mathlib[0])));
old_pow = lua_refobject(lua_setfallback("arith", math_pow), 1); lua_settagmethod(0, "pow", math_pow);
} }

932
opcode.c

File diff suppressed because it is too large Load Diff

195
opcode.h
View File

@@ -1,6 +1,6 @@
/* /*
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: opcode.h,v 3.19 1996/03/06 13:11:23 roberto Exp $ ** $Id: opcode.h,v 3.32 1997/04/04 22:24:51 roberto Exp roberto $
*/ */
#ifndef opcode_h #ifndef opcode_h
@@ -14,60 +14,106 @@
#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 typedef enum
{ {
PUSHNIL, LUA_T_NIL = -9,
PUSH0, PUSH1, PUSH2, LUA_T_NUMBER = -8,
PUSHBYTE, LUA_T_STRING = -7,
PUSHWORD, LUA_T_ARRAY = -6, /* array==table */
PUSHFLOAT, LUA_T_FUNCTION = -5,
PUSHSTRING, LUA_T_CFUNCTION= -4,
PUSHFUNCTION, LUA_T_MARK = -3,
PUSHLOCAL0, PUSHLOCAL1, PUSHLOCAL2, PUSHLOCAL3, PUSHLOCAL4, LUA_T_CMARK = -2,
PUSHLOCAL5, PUSHLOCAL6, PUSHLOCAL7, PUSHLOCAL8, PUSHLOCAL9, LUA_T_LINE = -1,
PUSHLOCAL, LUA_T_USERDATA = 0
PUSHGLOBAL, } lua_Type;
PUSHINDEXED,
PUSHSELF, #define NUM_TYPES 10
STORELOCAL0, STORELOCAL1, STORELOCAL2, STORELOCAL3, STORELOCAL4,
STORELOCAL5, STORELOCAL6, STORELOCAL7, STORELOCAL8, STORELOCAL9,
STORELOCAL, extern char *luaI_typenames[];
STOREGLOBAL,
STOREINDEXED0, typedef enum {
STOREINDEXED, /* name parm before after side effect
STORELIST0, -----------------------------------------------------------------------------*/
STORELIST,
STORERECORD, PUSHNIL,/* - nil */
ADJUST0, PUSH0,/* - 0.0 */
ADJUST, PUSH1,/* - 1.0 */
CREATEARRAY, PUSH2,/* - 2.0 */
EQOP, PUSHBYTE,/* b - (float)b */
LTOP, PUSHWORD,/* w - (float)w */
LEOP, PUSHFLOAT,/* f - f */
GTOP, PUSHSTRING,/* w - STR[w] */
GEOP, PUSHFUNCTION,/* p - FUN(p) */
ADDOP, PUSHLOCAL0,/* - LOC[0] */
SUBOP, PUSHLOCAL1,/* - LOC[1] */
MULTOP, PUSHLOCAL2,/* - LOC[2] */
DIVOP, PUSHLOCAL3,/* - LOC[3] */
POWOP, PUSHLOCAL4,/* - LOC[4] */
CONCOP, PUSHLOCAL5,/* - LOC[5] */
MINUSOP, PUSHLOCAL6,/* - LOC[6] */
NOTOP, PUSHLOCAL7,/* - LOC[7] */
ONTJMP, PUSHLOCAL8,/* - LOC[8] */
ONFJMP, PUSHLOCAL9,/* - LOC[9] */
JMP, PUSHLOCAL,/* b - LOC[b] */
UPJMP, PUSHGLOBAL,/* w - VAR[w] */
IFFJMP, PUSHINDEXED,/* i t t[i] */
IFFUPJMP, PUSHSELF,/* w t t t[STR[w]] */
POP, STORELOCAL0,/* x - LOC[0]=x */
CALLFUNC, STORELOCAL1,/* x - LOC[1]=x */
RETCODE0, STORELOCAL2,/* x - LOC[2]=x */
RETCODE, STORELOCAL3,/* x - LOC[3]=x */
SETLINE STORELOCAL4,/* x - LOC[4]=x */
STORELOCAL5,/* x - LOC[5]=x */
STORELOCAL6,/* x - LOC[6]=x */
STORELOCAL7,/* x - LOC[7]=x */
STORELOCAL8,/* x - LOC[8]=x */
STORELOCAL9,/* x - LOC[9]=x */
STORELOCAL,/* b x - LOC[b]=x */
STOREGLOBAL,/* w x - VAR[w]=x */
STOREINDEXED0,/* v i t - t[i]=v */
STOREINDEXED,/* b v a_b...a_1 i t a_b...a_1 i t t[i]=v */
STORELIST0,/* b v_b...v_1 t - t[i]=v_i */
STORELIST,/* b c v_b...v_1 t - t[i+c*FPF]=v_i */
STORERECORD,/* b
w_b...w_1 v_b...v_1 t - t[STR[w_i]]=v_i */
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
@@ -78,66 +124,47 @@ typedef union
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;
/* 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 {Byte c1; Byte 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 {Byte c1; Byte c2; Byte c3; Byte 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 {Byte c1; Byte c2; Byte c3; Byte 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 */
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); int luaI_dorun (TFunc *tf);
#endif #endif

589
strlib.c
View File

@@ -3,156 +3,150 @@
** String library to LUA ** String library to LUA
*/ */
char *rcs_strlib="$Id: strlib.c,v 1.22 1996/03/22 17:57:24 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>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <limits.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)) return buff+lbuffer.size;
lua_arg_error(funcname);
return lua_getstring(o);
}
double lua_check_number (int numArg, char *funcname)
{
lua_Object o = lua_getparam(numArg);
if (!lua_isnumber(o))
lua_arg_error(funcname);
return lua_getnumber(o);
}
static int lua_opt_number (int numArg, int def, char *funcname)
{
return (lua_getparam(numArg) == LUA_NOOBJECT) ? def :
(int)lua_check_number(numArg, funcname);
} }
char *luaI_addchar (int c) char *luaI_addchar (int c)
{ {
static char *buff = NULL; if (lbuffer.size >= lbuffer.max)
static int max = 0; strbuffer(lbuffer.max == 0 ? 100 : lbuffer.max*2);
static int n = 0; lbuffer.b[lbuffer.size++] = c;
if (n >= max) return lbuffer.b;
{
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;
} }
void luaI_emptybuff (void)
{
lbuffer.size = 0; /* prepare for next string */
}
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_opt_number(3, 1, "strfind") - 1; lua_Object t = lua_createtable();
char *f = (init>=0 && init<=strlen(s1)) ? strstr(s1+init,s2) : NULL; int i = 1;
if (f != NULL) /* As strtok changes s1, and s1 is "constant", make a copy of it */
{ s1 = strcpy(strbuffer(strlen(s1+1)), s1);
int pos = f-s1+1; while ((s1 = strtok(s1, del)) != NULL) {
if (lua_opt_number(4, INT_MAX, "strfind") >= pos+strlen(s2)-1) lua_pushobject(t);
lua_pushnumber (pos); lua_pushnumber(i++);
else lua_pushstring(s1);
lua_pushnil(); lua_settable();
} s1 = NULL; /* prepare for next strtok */
else }
lua_pushnil(); lua_pushobject(t);
lua_pushnumber(i-1); /* total number of tokens */
} }
/* /*
** 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_opt_number(3, strlen(s), "strsub"); long end = (long)luaL_opt_number(3, strlen(s));
if (end < start || start < 1 || end > strlen(s)) if (1 <= start && start <= end && end <= strlen(s)) {
lua_pushliteral(""); luaI_emptybuff();
else addnchar(s+start-1, end-start+1);
{ lua_pushstring(luaI_addchar(0));
luaI_addchar(0); }
while (start <= end) else lua_pushliteral("");
luaI_addchar(s[start++ - 1]);
lua_pushstring (luaI_addchar(0));
}
} }
/* /*
** 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)
{ {
char *s = lua_check_string(1, "strlower"); char *s;
luaI_addchar(0); luaI_emptybuff();
while (*s) for (s = luaL_check_string(1); *s; s++)
luaI_addchar(tolower(*s++)); luaI_addchar(tolower((unsigned char)*s));
lua_pushstring(luaI_addchar(0)); 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)
{ {
char *s = lua_check_string(1, "strupper"); char *s;
luaI_addchar(0); luaI_emptybuff();
while (*s) for (s = luaL_check_string(1); *s; s++)
luaI_addchar(toupper(*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)); lua_pushstring(luaI_addchar(0));
} }
@@ -161,109 +155,386 @@ 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);
int pos = lua_opt_number(2, 1, "ascii") - 1; long pos = (long)luaL_opt_number(2, 1) - 1;
if (pos<0 || pos>=strlen(s)) luaL_arg_check(0<=pos && pos<strlen(s), 2, "out of range");
lua_arg_error("ascii"); lua_pushnumber((unsigned char)s[pos]);
lua_pushnumber(s[pos]);
} }
/* pattern matching */
#define ESC '%'
#define SPECIALS "^$*?.([%-"
static char *bracket_end (char *p)
{
return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+1, ']');
}
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) void luaI_addquoted (char *s)
{ {
luaI_addchar('"'); luaI_addchar('"');
for (; *s; s++) for (; *s; s++) {
{ if (strchr("\"\\\n", *s))
if (*s == '"' || *s == '\\' || *s == '\n')
luaI_addchar('\\'); luaI_addchar('\\');
luaI_addchar(*s); luaI_addchar(*s);
} }
luaI_addchar('"'); luaI_addchar('"');
} }
#define MAX_CONVERTION 2000 #define MAX_FORMAT 200
#define MAX_FORMAT 50
static void str_format (void) static void str_format (void)
{ {
int arg = 1; int arg = 1;
char *strfrmt = lua_check_string(arg++, "format"); char *strfrmt = luaL_check_string(arg++);
luaI_addchar(0); /* initialize */ luaI_emptybuff(); /* initialize */
while (*strfrmt) while (*strfrmt) {
{
if (*strfrmt != '%') if (*strfrmt != '%')
luaI_addchar(*strfrmt++); luaI_addchar(*strfrmt++);
else if (*++strfrmt == '%') else if (*++strfrmt == '%')
luaI_addchar(*strfrmt++); /* %% */ luaI_addchar(*strfrmt++); /* %% */
else else { /* format item */
{ /* format item */
char form[MAX_FORMAT]; /* store the format ('%...') */ char form[MAX_FORMAT]; /* store the format ('%...') */
char buff[MAX_CONVERTION]; /* store the formated value */ char *buff;
int size = 0; char *initf = strfrmt-1; /* -1 to include % */
int i = 0; strfrmt = match(strfrmt, "[-+ #]*(%d*)%.?(%d*)", 0);
form[i++] = '%'; if (capture[0].len > 3 || capture[1].len > 3) /* < 1000? */
form[i] = *strfrmt++; lua_error("invalid format (width or precision too long)");
while (!isalpha(form[i])) strncpy(form, initf, strfrmt-initf+1); /* +1 to include convertion */
{ form[strfrmt-initf+1] = 0;
if (isdigit(form[i])) buff = openspace(1000); /* to store the formated value */
{ switch (*strfrmt++) {
size = size*10 + form[i]-'0';
if (size >= MAX_CONVERTION)
lua_error("format size/precision too long in function `format'");
}
else if (form[i] == '.')
size = 0; /* re-start */
if (++i >= MAX_FORMAT)
lua_error("bad format in function `format'");
form[i] = *strfrmt++;
}
form[i+1] = 0; /* ends string */
switch (form[i])
{
case 'q': case 'q':
luaI_addquoted(lua_check_string(arg++, "format")); luaI_addquoted(luaL_check_string(arg++));
buff[0] = '\0'; /* addchar already done */ continue;
break; case 's': {
case 's': char *s = luaL_check_string(arg++);
{ buff = openspace(strlen(s));
char *s = lua_check_string(arg++, "format");
if (strlen(s) >= MAX_CONVERTION)
lua_error("string argument too long in function `format'");
sprintf(buff, form, s); sprintf(buff, form, s);
break; break;
} }
case 'c': case 'd': case 'i': case 'o': case 'c': case 'd': case 'i': case 'o':
case 'u': case 'x': case 'X': case 'u': case 'x': case 'X':
sprintf(buff, form, (int)lua_check_number(arg++, "format")); sprintf(buff, form, (int)luaL_check_number(arg++));
break; break;
case 'e': case 'E': case 'f': case 'g': case 'e': case 'E': case 'f': case 'g':
sprintf(buff, form, lua_check_number(arg++, "format")); sprintf(buff, form, luaL_check_number(arg++));
break; break;
default: /* also treat cases 'pnLlh' */ default: /* also treat cases 'pnLlh' */
lua_error("invalid format option in function `format'"); lua_error("invalid format option in function `format'");
} }
for (i=0; buff[i]; i++) /* move formated value to result */ lbuffer.size += strlen(buff);
luaI_addchar(buff[i]);
} }
} }
lua_pushstring(luaI_addchar(0)); /* push the result */ lua_pushstring(luaI_addchar(0)); /* push the result */
} }
void luaI_openlib (struct lua_reg *l, int n) static struct luaL_reg strlib[] = {
{ {"strtok", str_tok},
int i;
for (i=0; i<n; i++)
lua_register(l[i].name, l[i].func);
}
static struct lua_reg strlib[] = {
{"strfind", str_find},
{"strlen", str_len}, {"strlen", str_len},
{"strsub", str_sub}, {"strsub", str_sub},
{"strset", str_set},
{"strlower", str_lower}, {"strlower", str_lower},
{"strupper", str_upper}, {"strupper", str_upper},
{"strrep", str_rep},
{"ascii", str_ascii}, {"ascii", str_ascii},
{"format", str_format} {"format", str_format},
{"strfind", str_find},
{"gsub", str_gsub}
}; };
@@ -272,5 +543,5 @@ static struct lua_reg strlib[] = {
*/ */
void strlib_open (void) void strlib_open (void)
{ {
luaI_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0]))); luaL_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0])));
} }

127
table.c
View File

@@ -3,9 +3,10 @@
** Module to control static tables ** Module to control static tables
*/ */
char *rcs_table="$Id: table.c,v 2.53 1996/04/29 18:53:53 roberto Exp roberto $"; char *rcs_table="$Id: table.c,v 2.67 1997/04/06 14:08:08 roberto Exp roberto $";
#include "mem.h" #include "luamem.h"
#include "auxlib.h"
#include "opcode.h" #include "opcode.h"
#include "tree.h" #include "tree.h"
#include "hash.h" #include "hash.h"
@@ -29,43 +30,12 @@ static Long lua_maxconstant = 0;
#define GARBAGE_BLOCK 50 #define GARBAGE_BLOCK 50
static void lua_nextvar (void);
/*
** Internal functions
*/
static struct {
char *name;
lua_CFunction func;
} int_funcs[] = {
{"assert", luaI_assert},
{"dofile", lua_internaldofile},
{"dostring", lua_internaldostring},
{"error", luaI_error},
{"getglobal", luaI_getglobal},
{"next", lua_next},
{"nextvar", lua_nextvar},
{"print", luaI_print},
{"setfallback", luaI_setfallback},
{"setglobal", luaI_setglobal},
{"tonumber", lua_obj2number},
{"tostring", luaI_tostring},
{"type", luaI_type}
};
#define INTFUNCSIZE (sizeof(int_funcs)/sizeof(int_funcs[0]))
void luaI_initsymbol (void) void luaI_initsymbol (void)
{ {
int i;
lua_maxsymbol = BUFFER_BLOCK; lua_maxsymbol = BUFFER_BLOCK;
lua_table = newvector(lua_maxsymbol, Symbol); lua_table = newvector(lua_maxsymbol, Symbol);
for (i=0; i<INTFUNCSIZE; i++) luaI_predefine();
{
Word n = luaI_findsymbolbyname(int_funcs[i].name);
s_tag(n) = LUA_T_CFUNCTION; s_fvalue(n) = int_funcs[i].func;
}
} }
@@ -95,7 +65,7 @@ Word luaI_findsymbol (TaggedString *t)
symbolEM, MAX_WORD); symbolEM, MAX_WORD);
t->varindex = lua_ntable; t->varindex = lua_ntable;
lua_table[lua_ntable].varname = t; lua_table[lua_ntable].varname = t;
s_tag(lua_ntable) = LUA_T_NIL; s_ttype(lua_ntable) = LUA_T_NIL;
lua_ntable++; lua_ntable++;
} }
return t->varindex; return t->varindex;
@@ -141,10 +111,16 @@ TaggedString *luaI_createfixedstring (char *name)
} }
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++)
@@ -157,13 +133,14 @@ 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 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;
@@ -172,9 +149,9 @@ int lua_markobject (Object *o)
/* /*
* returns 0 if the object is going to be (garbage) collected * returns 0 if the object is going to be (garbage) collected
*/ */
int luaI_ismarked (Object *o) int luaI_ismarked (TObject *o)
{ {
switch (o->tag) switch (o->ttype)
{ {
case LUA_T_STRING: case LUA_T_STRING:
return o->value.ts->marked; return o->value.ts->marked;
@@ -188,6 +165,13 @@ int luaI_ismarked (Object *o)
} }
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.
@@ -199,6 +183,9 @@ Long luaI_collectgarbage (void)
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(); luaI_invalidaterefs();
recovered += lua_strcollector(); recovered += lua_strcollector();
recovered += lua_hashcollector(); recovered += lua_hashcollector();
@@ -213,7 +200,7 @@ void lua_pack (void)
unsigned long recovered = 0; unsigned long recovered = 0;
if (nentity++ < block) return; if (nentity++ < block) return;
recovered = luaI_collectgarbage(); recovered = luaI_collectgarbage();
block = block*2*(1.0 - (float)recovered/nentity); block = 2*(block-recovered);
nentity -= recovered; nentity -= recovered;
} }
@@ -221,48 +208,34 @@ void lua_pack (void)
/* /*
** 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
{
lua_pushstring(lua_table[next].varname->str);
luaI_pushobject(&s_object(next));
}
} }
static Object *functofind; static TObject *functofind;
static int checkfunc (Object *o) static int checkfunc (TObject *o)
{ {
if (o->tag == LUA_T_FUNCTION) if (o->ttype == 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;
} }

10
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.20 1996/03/14 15:57:19 roberto Exp roberto $ ** $Id: table.h,v 2.23 1997/03/31 14:02:58 roberto Exp roberto $
*/ */
#ifndef table_h #ifndef table_h
@@ -12,7 +12,7 @@
typedef struct typedef struct
{ {
Object object; TObject object;
TaggedString *varname; TaggedString *varname;
} Symbol; } Symbol;
@@ -28,9 +28,11 @@ Word luaI_findsymbolbyname (char *name);
Word luaI_findsymbol (TaggedString *t); Word luaI_findsymbol (TaggedString *t);
Word luaI_findconstant (TaggedString *t); Word luaI_findconstant (TaggedString *t);
Word luaI_findconstantbyname (char *name); Word luaI_findconstantbyname (char *name);
int luaI_globaldefined (char *name);
void luaI_nextvar (void);
TaggedString *luaI_createfixedstring (char *str); TaggedString *luaI_createfixedstring (char *str);
int lua_markobject (Object *o); int lua_markobject (TObject *o);
int luaI_ismarked (Object *o); int luaI_ismarked (TObject *o);
Long luaI_collectgarbage (void); Long luaI_collectgarbage (void);
void lua_pack (void); void lua_pack (void);

59
tree.c
View File

@@ -3,17 +3,18 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_tree="$Id: tree.c,v 1.19 1996/02/22 20:34:33 roberto Exp $"; 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 "lex.h"
#include "hash.h" #include "hash.h"
#include "table.h" #include "table.h"
#include "fallback.h"
#define NUM_HASHS 64 #define NUM_HASHS 64
@@ -28,14 +29,14 @@ static int initialized = 0;
static stringtable string_root[NUM_HASHS]; static stringtable string_root[NUM_HASHS];
static TaggedString EMPTY = {NOT_USED, NOT_USED, 0, 2, {0}}; static TaggedString EMPTY = {LUA_T_STRING, 0, NOT_USED, NOT_USED, 0, 2, {0}};
static unsigned long hash (char *str) static unsigned long hash (char *buff, long size)
{ {
unsigned long h = 0; unsigned long h = 0;
while (*str) while (size--)
h = ((h<<5)-h)^(unsigned char)*(str++); h = ((h<<5)-h)^(unsigned char)*(buff++);
return h; return h;
} }
@@ -45,6 +46,7 @@ static void initialize (void)
luaI_addReserved(); luaI_addReserved();
luaI_initsymbol(); luaI_initsymbol();
luaI_initconstant(); luaI_initconstant();
luaI_initfallbacks();
} }
@@ -71,10 +73,10 @@ static void grow (stringtable *tb)
tb->hash = newhash; tb->hash = newhash;
} }
static TaggedString *insert (char *str, stringtable *tb) static TaggedString *insert (char *buff, long size, int tag, stringtable *tb)
{ {
TaggedString *ts; TaggedString *ts;
unsigned long h = hash(str); unsigned long h = hash(buff, size);
int i; int i;
int j = -1; int j = -1;
if ((Long)tb->nuse*3 >= (Long)tb->size*2) if ((Long)tb->nuse*3 >= (Long)tb->size*2)
@@ -84,12 +86,13 @@ static TaggedString *insert (char *str, stringtable *tb)
grow(tb); grow(tb);
} }
i = h%tb->size; i = h%tb->size;
while (tb->hash[i]) while ((ts = tb->hash[i]) != NULL)
{ {
if (tb->hash[i] == &EMPTY) if (ts == &EMPTY)
j = i; j = i;
else if (strcmp(str, tb->hash[i]->str) == 0) else if (ts->size == size && ts->tag == tag &&
return tb->hash[i]; memcmp(buff, ts->str, size) == 0)
return ts;
i = (i+1)%tb->size; i = (i+1)%tb->size;
} }
/* not found */ /* not found */
@@ -98,17 +101,43 @@ static TaggedString *insert (char *str, stringtable *tb)
i = j; i = j;
else else
tb->nuse++; tb->nuse++;
ts = tb->hash[i] = (TaggedString *)luaI_malloc(sizeof(TaggedString)+strlen(str)); ts = tb->hash[i] = (TaggedString *)luaI_malloc(sizeof(TaggedString)+size-1);
strcpy(ts->str, str); memcpy(ts->str, buff, size);
ts->tag = tag;
ts->size = size;
ts->marked = 0; ts->marked = 0;
ts->hash = h; ts->hash = h;
ts->varindex = ts->constindex = NOT_USED; ts->varindex = ts->constindex = NOT_USED;
return ts; 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) TaggedString *lua_createstring (char *str)
{ {
return insert(str, &string_root[(unsigned)str[0]%NUM_HASHS]); return luaI_createuserdata(str, strlen(str)+1, LUA_T_STRING);
}
void luaI_strcallIM (void)
{
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);
}
}
}
} }

8
tree.h
View File

@@ -1,7 +1,7 @@
/* /*
** tree.h ** tree.h
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
** $Id: tree.h,v 1.13 1996/02/14 13:35:51 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,15 +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 varindex; /* != NOT_USED if this is a symbol */
Word constindex; /* != NOT_USED if this is a constant */ Word constindex; /* != NOT_USED if this is a constant */
unsigned long hash; /* 0 if not initialized */ unsigned long hash; /* 0 if not initialized */
int marked; /* for garbage collection; never collect (nor change) if > 1 */ 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;
TaggedString *lua_createstring (char *str); TaggedString *lua_createstring (char *str);
TaggedString *luaI_createuserdata (char *buff, long size, int tag);
Long lua_strcollector (void); Long lua_strcollector (void);
void luaI_strcallIM (void);
#endif #endif

View File

@@ -3,12 +3,13 @@
** load bytecodes from files ** load bytecodes from files
*/ */
char* rcs_undump="$Id: undump.c,v 1.13 1996/03/12 20:00:40 lhf Exp lhf $"; char* rcs_undump="$Id: undump.c,v 1.21 1996/11/18 11:18:29 lhf Exp lhf $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "auxlib.h"
#include "opcode.h" #include "opcode.h"
#include "mem.h" #include "luamem.h"
#include "table.h" #include "table.h"
#include "undump.h" #include "undump.h"
@@ -17,19 +18,12 @@ static int swapfloat=0;
static TFunc* Main=NULL; /* functions in a chunk */ static TFunc* Main=NULL; /* functions in a chunk */
static TFunc* lastF=NULL; static TFunc* lastF=NULL;
static void warn(char* s) /* TODO: remove */
{
#if 0
fprintf(stderr,"undump: %s\n",s);
#endif
}
static void FixCode(Byte* code, Byte* end) /* swap words */ static void FixCode(Byte* code, Byte* end) /* swap words */
{ {
Byte* p; Byte* p;
for (p=code; p!=end;) for (p=code; p!=end;)
{ {
OpCode op=(OpCode)*p; int op=*p;
switch (op) switch (op)
{ {
case PUSHNIL: case PUSHNIL:
@@ -83,6 +77,8 @@ static void FixCode(Byte* code, Byte* end) /* swap words */
case STORELIST0: case STORELIST0:
case ADJUST: case ADJUST:
case RETCODE: case RETCODE:
case VARARGS:
case STOREMAP:
p+=2; p+=2;
break; break;
case STORELIST: case STORELIST:
@@ -90,7 +86,7 @@ static void FixCode(Byte* code, Byte* end) /* swap words */
p+=3; p+=3;
break; break;
case PUSHFUNCTION: case PUSHFUNCTION:
p+=5; p+=5; /* TODO: use sizeof(TFunc*) or old? */
break; break;
case PUSHWORD: case PUSHWORD:
case PUSHSELF: case PUSHSELF:
@@ -111,7 +107,7 @@ static void FixCode(Byte* code, Byte* end) /* swap words */
p+=3; p+=3;
break; break;
} }
case PUSHFLOAT: case PUSHFLOAT: /* assumes sizeof(float)==4 */
{ {
Byte t; Byte t;
t=p[1]; p[1]=p[4]; p[4]=t; t=p[1]; p[1]=p[4]; p[4]=t;
@@ -132,7 +128,8 @@ static void FixCode(Byte* code, Byte* end) /* swap words */
break; break;
} }
default: default:
lua_error("corrupt binary file"); luaL_verror("corrupt binary file: bad opcode %d at %d\n",
op,(int)(p-code));
break; break;
} }
} }
@@ -142,13 +139,11 @@ static void Unthread(Byte* code, int i, int v)
{ {
while (i!=0) while (i!=0)
{ {
CodeWord c; Word w;
Byte* p=code+i; Byte* p=code+i;
get_word(c,p); memcpy(&w,p,sizeof(w));
i=c.w; i=w; w=v;
c.w=v; memcpy(p,&w,sizeof(w));
p[-2]=c.m.c1;
p[-1]=c.m.c2;
} }
} }
@@ -158,7 +153,7 @@ static int LoadWord(FILE* D)
fread(&w,sizeof(w),1,D); fread(&w,sizeof(w),1,D);
if (swapword) if (swapword)
{ {
Byte* p=(Byte*)&w; /* TODO: need union? */ Byte* p=(Byte*)&w;
Byte t; Byte t;
t=p[0]; p[0]=p[1]; p[1]=t; t=p[0]; p[0]=p[1]; p[1]=t;
} }
@@ -174,9 +169,9 @@ static int LoadSize(FILE* D)
return s; return s;
} }
static char* LoadBlock(int size, FILE* D) static void* LoadBlock(int size, FILE* D)
{ {
char* b=luaI_malloc(size); void* b=luaI_malloc(size);
fread(b,size,1,D); fread(b,size,1,D);
return b; return b;
} }
@@ -208,13 +203,9 @@ static void LoadFunction(FILE* D)
} }
else /* fix PUSHFUNCTION */ else /* fix PUSHFUNCTION */
{ {
CodeCode c;
Byte* p;
tf->marked=LoadWord(D); tf->marked=LoadWord(D);
tf->fileName=Main->fileName; tf->fileName=Main->fileName;
p=Main->code+tf->marked; memcpy(Main->code+tf->marked,&tf,sizeof(tf));
c.tf=tf;
*p++=c.m.c1; *p++=c.m.c2; *p++=c.m.c3; *p++=c.m.c4;
lastF=lastF->next=tf; lastF=lastF->next=tf;
} }
tf->code=LoadBlock(tf->size,D); tf->code=LoadBlock(tf->size,D);
@@ -249,33 +240,49 @@ static void LoadSignature(FILE* D)
char* s=SIGNATURE; char* s=SIGNATURE;
while (*s!=0 && getc(D)==*s) while (*s!=0 && getc(D)==*s)
++s; ++s;
if (*s!=0) lua_error("bad signature"); if (*s!=0) lua_error("cannot load binary file: bad signature");
} }
static void LoadHeader(FILE* D) /* TODO: error handling */ static void LoadHeader(FILE* D)
{ {
Word w,tw=TEST_WORD; Word w,tw=TEST_WORD;
float f,tf=TEST_FLOAT; float f,tf=TEST_FLOAT;
int version;
LoadSignature(D); LoadSignature(D);
getc(D); /* skip version */ 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 */ fread(&w,sizeof(w),1,D); /* test word */
if (w!=tw) if (w!=tw)
{ {
swapword=1; swapword=1;
warn("different byte order");
} }
fread(&f,sizeof(f),1,D); /* test float */ fread(&f,sizeof(f),1,D); /* test float */
if (f!=tf) if (f!=tf)
{ {
Byte* p=(Byte*)&f; /* TODO: need union? */ Byte* p=(Byte*)&f;
Byte t; Byte t;
swapfloat=1; swapfloat=1;
t=p[0]; p[0]=p[3]; p[3]=t; t=p[0]; p[0]=p[3]; p[3]=t;
t=p[1]; p[1]=p[2]; p[2]=t; t=p[1]; p[1]=p[2]; p[2]=t;
if (f!=tf) /* TODO: try another perm? */ if (f!=tf) /* TODO: try another perm? */
lua_error("different float representation"); lua_error("cannot load binary file: unknown float representation");
else
warn("different byte order in floats");
} }
} }

View File

@@ -1,7 +1,7 @@
/* /*
** undump.h ** undump.h
** definitions for lua decompiler ** definitions for lua decompiler
** $Id: undump.h,v 1.1 1996/03/08 21:43:21 lhf Exp lhf $ ** $Id: undump.h,v 1.3 1996/11/14 11:44:34 lhf Exp lhf $
*/ */
#include "func.h" #include "func.h"
@@ -15,7 +15,7 @@
#define ID_VAR 'V' #define ID_VAR 'V'
#define ID_STR 'S' #define ID_STR 'S'
#define SIGNATURE "Lua" #define SIGNATURE "Lua"
#define VERSION 0x23 /* 2.3 */ #define VERSION 0x25 /* last format change was in 2.5 */
#define TEST_WORD 0x1234 /* a word for testing byte ordering */ #define TEST_WORD 0x1234 /* a word for testing byte ordering */
#define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */ #define TEST_FLOAT 0.123456789e-23 /* a float for testing representation */