Update lua to 5.2 and fix obvious breakage due to obsolete api.

develop
Alexander Gavrilov 2012-03-31 12:11:43 +04:00
parent 10b610669f
commit 9384f0c842
69 changed files with 8679 additions and 6040 deletions

@ -17,10 +17,10 @@ IF(UNIX)
ENDIF() ENDIF()
SET (HDR_LIBLUA SET (HDR_LIBLUA
include/bit.h
include/lapi.h include/lapi.h
include/lauxlib.h include/lauxlib.h
include/lcode.h include/lcode.h
include/lctype.h
include/ldebug.h include/ldebug.h
include/ldo.h include/ldo.h
include/lfunc.h include/lfunc.h
@ -50,7 +50,10 @@ SET (SRC_LIBLUA
src/lapi.c src/lapi.c
src/lauxlib.c src/lauxlib.c
src/lbaselib.c src/lbaselib.c
src/lbitlib.c
src/lcode.c src/lcode.c
src/lcorolib.c
src/lctype.c
src/ldblib.c src/ldblib.c
src/ldebug.c src/ldebug.c
src/ldo.c src/ldo.c
@ -76,7 +79,6 @@ src/ltm.c
src/lundump.c src/lundump.c
src/lvm.c src/lvm.c
src/lzio.c src/lzio.c
src/bit.c
) )
# compile with C++ compiler # compile with C++ compiler
set_source_files_properties(${SRC_LIBLUA} PROPERTIES LANGUAGE CXX) set_source_files_properties(${SRC_LIBLUA} PROPERTIES LANGUAGE CXX)

@ -1,4 +1,4 @@
README for Lua 5.1 README for Lua 5.2
See INSTALL for installation instructions. See INSTALL for installation instructions.
See HISTORY for a summary of changes since the last released version. See HISTORY for a summary of changes since the last released version.

@ -1,17 +0,0 @@
#ifndef BIT_H
#define BIT_H
#define LUA_BITOP_VERSION "1.0.1"
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#ifdef __cplusplus
extern "C" {
#endif
LUALIB_API int luaopen_bit(lua_State *L);
#ifdef __cplusplus
}
#endif
#endif // BIT_H

@ -1,5 +1,5 @@
/* /*
** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lapi.h,v 2.7 2009/11/27 15:37:59 roberto Exp $
** Auxiliary functions from Lua API ** Auxiliary functions from Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -8,9 +8,17 @@
#define lapi_h #define lapi_h
#include "lobject.h" #include "llimits.h"
#include "lstate.h"
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
#define adjustresults(L,nres) \
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")
LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $
** Auxiliary functions for building Lua libraries ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -15,18 +15,6 @@
#include "lua.h" #include "lua.h"
#if defined(LUA_COMPAT_GETN)
LUALIB_API int (luaL_getn) (lua_State *L, int t);
LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
#else
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
#define luaL_setn(L,i,j) ((void)0) /* no op! */
#endif
#if defined(LUA_COMPAT_OPENLIB)
#define luaI_openlib luaL_openlib
#endif
/* extra error code for `luaL_load' */ /* extra error code for `luaL_load' */
#define LUA_ERRFILE (LUA_ERRERR+1) #define LUA_ERRFILE (LUA_ERRERR+1)
@ -38,14 +26,12 @@ typedef struct luaL_Reg {
} luaL_Reg; } luaL_Reg;
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver);
#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM)
LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
const luaL_Reg *l);
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
size_t *l); size_t *l);
@ -57,12 +43,17 @@ LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
lua_Integer def); lua_Integer def);
LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg);
LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg,
lua_Unsigned def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int narg); LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl); LUALIB_API void (luaL_where) (lua_State *L, int lvl);
@ -71,25 +62,41 @@ LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
const char *const lst[]); const char *const lst[]);
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
/* pre-defined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
LUALIB_API int (luaL_ref) (lua_State *L, int t); LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *mode);
const char *name);
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void); LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API int (luaL_len) (lua_State *L, int idx);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r); const char *r);
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
const char *fname, int szhint);
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
/* /*
** =============================================================== ** ===============================================================
@ -97,6 +104,12 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
** =============================================================== ** ===============================================================
*/ */
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#define luaL_argcheck(L, cond,numarg,extramsg) \ #define luaL_argcheck(L, cond,numarg,extramsg) \
((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
@ -118,56 +131,81 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/* /*
** {====================================================== ** {======================================================
** Generic Buffer manipulation ** Generic Buffer manipulation
** ======================================================= ** =======================================================
*/ */
typedef struct luaL_Buffer { typedef struct luaL_Buffer {
char *p; /* current position in buffer */ char *b; /* buffer address */
int lvl; /* number of strings in the stack (level) */ size_t size; /* buffer size */
size_t n; /* number of characters in buffer */
lua_State *L; lua_State *L;
char buffer[LUAL_BUFFERSIZE]; char initb[LUAL_BUFFERSIZE]; /* initial buffer */
} luaL_Buffer; } luaL_Buffer;
#define luaL_addchar(B,c) \
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
(*(B)->p++ = (char)(c)))
/* compatibility only */ #define luaL_addchar(B,c) \
#define luaL_putchar(B,c) luaL_addchar(B,c) ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
((B)->b[(B)->n++] = (c)))
#define luaL_addsize(B,n) ((B)->p += (n)) #define luaL_addsize(B,s) ((B)->n += (s))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
/* }====================================================== */ /* }====================================================== */
/* compatibility with ref system */
/* pre-defined references */ /*
#define LUA_NOREF (-2) ** {======================================================
#define LUA_REFNIL (-1) ** File handles for IO library
** =======================================================
*/
/*
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
** initial structure 'luaL_Stream' (it may contain other fields
** after that initial structure).
*/
#define LUA_FILEHANDLE "FILE*"
typedef struct luaL_Stream {
FILE *f; /* stream (NULL for incompletely created streams) */
lua_CFunction closef; /* to close stream (NULL for closed streams) */
} luaL_Stream;
/* }====================================================== */
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) /* compatibility with old module system */
#if defined(LUA_COMPAT_MODULE)
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
int sizehint);
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
#endif
#define luaL_reg luaL_Reg
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -21,13 +21,13 @@
/* /*
** grep "ORDER OPR" if you change these enums ** grep "ORDER OPR" if you change these enums (ORDER OP)
*/ */
typedef enum BinOpr { typedef enum BinOpr {
OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
OPR_CONCAT, OPR_CONCAT,
OPR_NE, OPR_EQ, OPR_EQ, OPR_LT, OPR_LE,
OPR_LT, OPR_LE, OPR_GT, OPR_GE, OPR_NE, OPR_GT, OPR_GE,
OPR_AND, OPR_OR, OPR_AND, OPR_OR,
OPR_NOBINOPR OPR_NOBINOPR
} BinOpr; } BinOpr;
@ -36,14 +36,17 @@ typedef enum BinOpr {
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) #define getcode(fs,e) ((fs)->f->code[(e)->u.info])
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line); LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
@ -52,12 +55,14 @@ LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
@ -65,11 +70,13 @@ LUAI_FUNC int luaK_jump (FuncState *fs);
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level);
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
LUAI_FUNC int luaK_getlabel (FuncState *fs); LUAI_FUNC int luaK_getlabel (FuncState *fs);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
expdesc *v2, int line);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);

@ -0,0 +1,95 @@
/*
** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#ifndef lctype_h
#define lctype_h
#include "lua.h"
/*
** WARNING: the functions defined here do not necessarily correspond
** to the similar functions in the standard C ctype.h. They are
** optimized for the specific needs of Lua
*/
#if !defined(LUA_USE_CTYPE)
#if 'A' == 65 && '0' == 48
/* ASCII case: can use its own tables; faster and fixed */
#define LUA_USE_CTYPE 0
#else
/* must use standard C ctype */
#define LUA_USE_CTYPE 1
#endif
#endif
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
#include "llimits.h"
#define ALPHABIT 0
#define DIGITBIT 1
#define PRINTBIT 2
#define SPACEBIT 3
#define XDIGITBIT 4
#define MASK(B) (1 << (B))
/*
** add 1 to char to allow index -1 (EOZ)
*/
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
/*
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
*/
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
#define lisspace(c) testprop(c, MASK(SPACEBIT))
#define lisprint(c) testprop(c, MASK(PRINTBIT))
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
/*
** this 'ltolower' only works for alphabetic characters
*/
#define ltolower(c) ((c) | ('A' ^ 'a'))
/* two more entries for 0 and -1 (EOZ) */
LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2];
#else /* }{ */
/*
** use standard C ctypes
*/
#include <ctype.h>
#define lislalpha(c) (isalpha(c) || (c) == '_')
#define lislalnum(c) (isalnum(c) || (c) == '_')
#define lisdigit(c) (isdigit(c))
#define lisspace(c) (isspace(c))
#define lisprint(c) (isprint(c))
#define lisxdigit(c) (isxdigit(c))
#define ltolower(c) (tolower(c))
#endif /* } */
#endif

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $
** Auxiliary functions from Debug Interface module ** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,21 +13,22 @@
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) #define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
#define resethookcount(L) (L->hookcount = L->basehookcount) #define resethookcount(L) (L->hookcount = L->basehookcount)
/* Active Lua function (given call info) */
#define ci_func(ci) (clLvalue((ci)->func))
LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,
const char *opname); LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); const char *opname);
LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2);
const TValue *p2); LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1,
LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2);
const TValue *p2); LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); const TValue *p2);
LUAI_FUNC void luaG_errormsg (lua_State *L); LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC int luaG_checkcode (const Proto *pt); LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
LUAI_FUNC int luaG_checkopenop (Instruction i);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,45 +13,34 @@
#include "lzio.h" #include "lzio.h"
#define luaD_checkstack(L,n) \ #define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \
if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ luaD_growstack(L, n); else condmovestack(L);
luaD_growstack(L, n); \
else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
#define incr_top(L) {luaD_checkstack(L,1); L->top++;} #define incr_top(L) {L->top++; luaD_checkstack(L,0);}
#define savestack(L,p) ((char *)(p) - (char *)L->stack) #define savestack(L,p) ((char *)(p) - (char *)L->stack)
#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) #define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
/* results from luaD_precall */
#define PCRLUA 0 /* initiated a call to a Lua function */
#define PCRC 1 /* did a call to a C function */
#define PCRYIELD 2 /* C funtion yielded */
/* type of protected functions, to be ran by `runprotected' */ /* type of protected functions, to be ran by `runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud); typedef void (*Pfunc) (lua_State *L, void *ud);
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); const char *mode);
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
int allowyield);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef); ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_growstack (lua_State *L, int n);
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
LUAI_FUNC void luaD_throw (lua_State *L, int errcode); LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lfunc.h,v 2.6 2010/06/04 13:06:15 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures ** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -19,8 +19,8 @@
LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, Proto *p);
LUAI_FUNC UpVal *luaF_newupval (lua_State *L); LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_close (lua_State *L, StkId level); LUAI_FUNC void luaF_close (lua_State *L, StkId level);

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lgc.h,v 2.52 2011/10/03 17:54:25 roberto Exp $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -9,65 +9,89 @@
#include "lobject.h" #include "lobject.h"
#include "lstate.h"
/*
** Collectable objects may have one of three colors: white, which
** means the object is not marked; gray, which means the
** object is marked, but its references may be not marked; and
** black, which means that the object and all its references are marked.
** The main invariant of the garbage collector, while marking objects,
** is that a black object can never point to a white one. Moreover,
** any gray object must be in a "gray list" (gray, grayagain, weak,
** allweak, ephemeron) so that it can be visited again before finishing
** the collection cycle. These lists have no meaning when the invariant
** is not being enforced (e.g., sweep phase).
*/
/* /*
** Possible states of the Garbage Collector ** Possible states of the Garbage Collector
*/ */
#define GCSpause 0 #define GCSpropagate 0
#define GCSpropagate 1 #define GCSatomic 1
#define GCSsweepstring 2 #define GCSsweepstring 2
#define GCSsweep 3 #define GCSsweepudata 3
#define GCSfinalize 4 #define GCSsweep 4
#define GCSpause 5
#define issweepphase(g) \
(GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
#define isgenerational(g) ((g)->gckind == KGC_GEN)
/* /*
** some userful bit tricks ** macro to tell when main invariant (white objects cannot point to black
** ones) must be kept. During a non-generational collection, the sweep
** phase may break the invariant, as objects turned white may point to
** still-black objects. The invariant is restored when sweep ends and
** all objects are white again. During a generational collection, the
** invariant must be kept all times.
*/ */
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) #define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic)
#define setbits(x,m) ((x) |= (m))
#define testbits(x,m) ((x) & (m))
#define bitmask(b) (1<<(b))
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
#define l_setbit(x,b) setbits(x, bitmask(b))
#define resetbit(x,b) resetbits(x, bitmask(b))
#define testbit(x,b) testbits(x, bitmask(b))
#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
/* /*
** Layout for bit use in `marked' field: ** some useful bit tricks
** bit 0 - object is white (type 0)
** bit 1 - object is white (type 1)
** bit 2 - object is black
** bit 3 - for userdata: has been finalized
** bit 3 - for tables: has weak keys
** bit 4 - for tables: has weak values
** bit 5 - object is fixed (should not be collected)
** bit 6 - object is "super" fixed (only the main thread)
*/ */
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
#define setbits(x,m) ((x) |= (m))
#define testbits(x,m) ((x) & (m))
#define bitmask(b) (1<<(b))
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
#define l_setbit(x,b) setbits(x, bitmask(b))
#define resetbit(x,b) resetbits(x, bitmask(b))
#define testbit(x,b) testbits(x, bitmask(b))
/* Layout for bit use in `marked' field: */
#define WHITE0BIT 0 /* object is white (type 0) */
#define WHITE1BIT 1 /* object is white (type 1) */
#define BLACKBIT 2 /* object is black */
#define FINALIZEDBIT 3 /* object has been separated for finalization */
#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */
#define FIXEDBIT 5 /* object is fixed (should not be collected) */
#define OLDBIT 6 /* object is old (only in generational mode) */
/* bit 7 is currently used by tests (luaL_checkmemory) */
#define WHITE0BIT 0
#define WHITE1BIT 1
#define BLACKBIT 2
#define FINALIZEDBIT 3
#define KEYWEAKBIT 3
#define VALUEWEAKBIT 4
#define FIXEDBIT 5
#define SFIXEDBIT 6
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define iswhite(x) testbits((x)->gch.marked, WHITEBITS)
#define isblack(x) testbit((x)->gch.marked, BLACKBIT) #define isblack(x) testbit((x)->gch.marked, BLACKBIT)
#define isgray(x) (!isblack(x) && !iswhite(x)) #define isgray(x) /* neither white nor black */ \
(!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
#define isold(x) testbit((x)->gch.marked, OLDBIT)
/* MOVE OLD rule: whenever an object is moved to the beginning of
a GC list, its old bit must be cleared */
#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT)
#define otherwhite(g) (g->currentwhite ^ WHITEBITS) #define otherwhite(g) (g->currentwhite ^ WHITEBITS)
#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow)))
#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked)
#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) #define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
@ -77,34 +101,39 @@
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
#define luaC_checkGC(L) { \ #define luaC_condGC(L,c) \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);}
if (G(L)->totalbytes >= G(L)->GCthreshold) \ #define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);)
luaC_step(L); }
#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
luaC_barrierf(L,obj2gco(p),gcvalue(v)); } luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ #define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
luaC_barrierback(L,t); } luaC_barrierback_(L,p); }
#define luaC_objbarrier(L,p,o) \ #define luaC_objbarrier(L,p,o) \
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
luaC_barrierf(L,obj2gco(p),obj2gco(o)); } luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
#define luaC_objbarriert(L,t,o) \ #define luaC_objbarrierback(L,p,o) \
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); }
LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); #define luaC_barrierproto(L,p,c) \
LUAI_FUNC void luaC_callGCTM (lua_State *L); { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); }
LUAI_FUNC void luaC_freeall (lua_State *L);
LUAI_FUNC void luaC_step (lua_State *L);
LUAI_FUNC void luaC_fullgc (lua_State *L);
LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
LUAI_FUNC void luaC_step (lua_State *L);
LUAI_FUNC void luaC_forcestep (lua_State *L);
LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz,
GCObject **list, int offset);
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv);
LUAI_FUNC void luaC_changemode (lua_State *L, int mode);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,8 +13,6 @@
#define FIRST_RESERVED 257 #define FIRST_RESERVED 257
/* maximum length of a reserved word */
#define TOKEN_LEN (sizeof("function")/sizeof(char))
/* /*
@ -25,21 +23,17 @@ enum RESERVED {
/* terminal symbols denoted by reserved words */ /* terminal symbols denoted by reserved words */
TK_AND = FIRST_RESERVED, TK_BREAK, TK_AND = FIRST_RESERVED, TK_BREAK,
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */ /* other terminal symbols */
TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS,
TK_NAME, TK_STRING, TK_EOS TK_NUMBER, TK_NAME, TK_STRING
}; };
/* number of reserved words */ /* number of reserved words */
#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
/* array with token `names' */
LUAI_DATA const char *const luaX_tokens [];
typedef union { typedef union {
lua_Number r; lua_Number r;
TString *ts; TString *ts;
@ -52,29 +46,32 @@ typedef struct Token {
} Token; } Token;
/* state of the lexer plus state of the parser when shared by all
functions */
typedef struct LexState { typedef struct LexState {
int current; /* current character (charint) */ int current; /* current character (charint) */
int linenumber; /* input line counter */ int linenumber; /* input line counter */
int lastline; /* line of last token `consumed' */ int lastline; /* line of last token `consumed' */
Token t; /* current token */ Token t; /* current token */
Token lookahead; /* look ahead token */ Token lookahead; /* look ahead token */
struct FuncState *fs; /* `FuncState' is private to the parser */ struct FuncState *fs; /* current function (parser) */
struct lua_State *L; struct lua_State *L;
ZIO *z; /* input stream */ ZIO *z; /* input stream */
Mbuffer *buff; /* buffer for tokens */ Mbuffer *buff; /* buffer for tokens */
struct Dyndata *dyd; /* dynamic structures used by the parser */
TString *source; /* current source name */ TString *source; /* current source name */
TString *envn; /* environment variable name */
char decpoint; /* locale decimal point */ char decpoint; /* locale decimal point */
} LexState; } LexState;
LUAI_FUNC void luaX_init (lua_State *L); LUAI_FUNC void luaX_init (lua_State *L);
LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
TString *source); TString *source, int firstchar);
LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
LUAI_FUNC void luaX_next (LexState *ls); LUAI_FUNC void luaX_next (LexState *ls);
LUAI_FUNC void luaX_lookahead (LexState *ls); LUAI_FUNC int luaX_lookahead (LexState *ls);
LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s);
LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);
LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);

@ -1,5 +1,5 @@
/* /*
** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: llimits.h,v 1.95 2011/12/06 16:58:36 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions ** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -15,7 +15,7 @@
#include "lua.h" #include "lua.h"
typedef LUAI_UINT32 lu_int32; typedef unsigned LUA_INT32 lu_int32;
typedef LUAI_UMEM lu_mem; typedef LUAI_UMEM lu_mem;
@ -44,6 +44,10 @@ typedef unsigned char lu_byte;
/* type to ensure maximum alignment */ /* type to ensure maximum alignment */
#if !defined(LUAI_USER_ALIGNMENT_T)
#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }
#endif
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
@ -52,35 +56,74 @@ typedef LUAI_UACNUMBER l_uacNumber;
/* internal assertions for in-house debugging */ /* internal assertions for in-house debugging */
#ifdef lua_assert #if defined(lua_assert)
#define check_exp(c,e) (lua_assert(c), (e)) #define check_exp(c,e) (lua_assert(c), (e))
#define api_check(l,e) lua_assert(e) /* to avoid problems with conditions too long */
#define lua_longassert(c) { if (!(c)) lua_assert(0); }
#else #else
#define lua_assert(c) ((void)0) #define lua_assert(c) ((void)0)
#define check_exp(c,e) (e) #define check_exp(c,e) (e)
#define api_check luai_apicheck #define lua_longassert(c) ((void)0)
#endif
/*
** assertion for checking API calls
*/
#if !defined(luai_apicheck)
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(L,e) assert(e)
#else
#define luai_apicheck(L,e) lua_assert(e)
#endif #endif
#endif
#ifndef UNUSED #define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x)) /* to avoid warnings */ #define UNUSED(x) ((void)(x)) /* to avoid warnings */
#endif #endif
#ifndef cast
#define cast(t, exp) ((t)(exp)) #define cast(t, exp) ((t)(exp))
#endif
#define cast_byte(i) cast(lu_byte, (i)) #define cast_byte(i) cast(lu_byte, (i))
#define cast_num(i) cast(lua_Number, (i)) #define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i)) #define cast_int(i) cast(int, (i))
#define cast_uchar(i) cast(unsigned char, (i))
/*
** non-return type
*/
#if defined(__GNUC__)
#define l_noret void __attribute__((noreturn))
#elif defined(_MSC_VER)
#define l_noret void __declspec(noreturn)
#else
#define l_noret void
#endif
/*
** maximum depth for nested C calls and syntactical nested non-terminals
** in a program. (Value must fit in an unsigned short int.)
*/
#if !defined(LUAI_MAXCCALLS)
#define LUAI_MAXCCALLS 200
#endif
/*
** maximum number of upvalues in a closure (both C and Lua). (Value
** must fit in an unsigned char.)
*/
#define MAXUPVAL UCHAR_MAX
/* /*
** type for virtual-machine instructions ** type for virtual-machine instructions
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
@ -95,34 +138,165 @@ typedef lu_int32 Instruction;
/* minimum size for the string table (must be power of 2) */ /* minimum size for the string table (must be power of 2) */
#ifndef MINSTRTABSIZE #if !defined(MINSTRTABSIZE)
#define MINSTRTABSIZE 32 #define MINSTRTABSIZE 32
#endif #endif
/* minimum size for string buffer */ /* minimum size for string buffer */
#ifndef LUA_MINBUFFER #if !defined(LUA_MINBUFFER)
#define LUA_MINBUFFER 32 #define LUA_MINBUFFER 32
#endif #endif
#ifndef lua_lock #if !defined(lua_lock)
#define lua_lock(L) ((void) 0) #define lua_lock(L) ((void) 0)
#define lua_unlock(L) ((void) 0) #define lua_unlock(L) ((void) 0)
#endif #endif
#ifndef luai_threadyield #if !defined(luai_threadyield)
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
#endif #endif
/*
** these macros allow user-specific actions on threads when you defined
** LUAI_EXTRASPACE and need to do something extra when a thread is
** created/deleted/resumed/yielded.
*/
#if !defined(luai_userstateopen)
#define luai_userstateopen(L) ((void)L)
#endif
#if !defined(luai_userstateclose)
#define luai_userstateclose(L) ((void)L)
#endif
#if !defined(luai_userstatethread)
#define luai_userstatethread(L,L1) ((void)L)
#endif
#if !defined(luai_userstatefree)
#define luai_userstatefree(L,L1) ((void)L)
#endif
#if !defined(luai_userstateresume)
#define luai_userstateresume(L,n) ((void)L)
#endif
#if !defined(luai_userstateyield)
#define luai_userstateyield(L,n) ((void)L)
#endif
/*
** lua_number2int is a macro to convert lua_Number to int.
** lua_number2integer is a macro to convert lua_Number to lua_Integer.
** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned.
** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number.
** luai_hashnum is a macro to hash a lua_Number value into an integer.
** The hash must be deterministic and give reasonable values for
** both small and large values (outside the range of integers).
*/
#if defined(MS_ASMTRICK) /* { */
/* trick with Microsoft assembler for X86 */
#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i}
#define lua_number2integer(i,n) lua_number2int(i, n)
#define lua_number2unsigned(i,n) \
{__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;}
#elif defined(LUA_IEEE754TRICK) /* }{ */
/* the next trick should work on any machine using IEEE754 with
a 32-bit integer type */
union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
#if !defined(LUA_IEEEENDIAN) /* { */
#define LUAI_EXTRAIEEE \
static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)};
#define LUA_IEEEENDIAN (ieeeendian.l_p[1] == 33)
#else
#define LUAI_EXTRAIEEE /* empty */
#endif /* } */
#define lua_number2int32(i,n,t) \
{ LUAI_EXTRAIEEE \
volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \
(i) = (t)u.l_p[LUA_IEEEENDIAN]; }
#define luai_hashnum(i,n) \
{ volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \
(i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */
#define lua_number2int(i,n) lua_number2int32(i, n, int)
#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer)
#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned)
#endif /* } */
/* the following definitions always work, but may be slow */
#if !defined(lua_number2int)
#define lua_number2int(i,n) ((i)=(int)(n))
#endif
#if !defined(lua_number2integer)
#define lua_number2integer(i,n) ((i)=(lua_Integer)(n))
#endif
#if !defined(lua_number2unsigned) /* { */
/* the following definition assures proper modulo behavior */
#if defined(LUA_NUMBER_DOUBLE)
#include <math.h>
#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1)
#define lua_number2unsigned(i,n) \
((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED))
#else
#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n))
#endif
#endif /* } */
#if !defined(lua_unsigned2number)
/* on several machines, coercion from unsigned to double is slow,
so it may be worth to avoid */
#define lua_unsigned2number(u) \
(((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u))
#endif
#if defined(ltable_c) && !defined(luai_hashnum)
#include <float.h>
#include <math.h>
#define luai_hashnum(i,n) { int e; \
n = frexp(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \
lua_number2int(i, n); i += e; }
#endif
/* /*
** macro to control inclusion of some hard tests on stack reallocation ** macro to control inclusion of some hard tests on stack reallocation
*/ */
#ifndef HARDSTACKTESTS #if !defined(HARDSTACKTESTS)
#define condhardstacktests(x) ((void)0) #define condmovestack(L) ((void)0)
#else
/* realloc stack keeping its size */
#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize)
#endif
#if !defined(HARDMEMTESTS)
#define condchangemem(L) condmovestack(L)
#else #else
#define condhardstacktests(x) x #define condchangemem(L) \
((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1)))
#endif #endif
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lmem.h,v 1.38 2011/12/02 13:26:54 roberto Exp $
** Interface to Memory Manager ** Interface to Memory Manager
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,23 +13,23 @@
#include "llimits.h" #include "llimits.h"
#include "lua.h" #include "lua.h"
#define MEMERRMSG "not enough memory"
#define luaM_reallocv(L,b,on,n,e) \ #define luaM_reallocv(L,b,on,n,e) \
((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ ((cast(size_t, (n)+1) > MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \
luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ (luaM_toobig(L), (void *)0) : \
luaM_toobig(L)) luaM_realloc_(L, (b), (on)*(e), (n)*(e)))
#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)
#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) #define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0]))
#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) #define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s))
#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t)))
#define luaM_newvector(L,n,t) \ #define luaM_newvector(L,n,t) \
cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))
#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s))
#define luaM_growvector(L,v,nelems,size,t,limit,e) \ #define luaM_growvector(L,v,nelems,size,t,limit,e) \
if ((nelems)+1 > (size)) \ if ((nelems)+1 > (size)) \
((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
@ -37,13 +37,14 @@
#define luaM_reallocvector(L, v,oldn,n,t) \ #define luaM_reallocvector(L, v,oldn,n,t) \
((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
LUAI_FUNC l_noret luaM_toobig (lua_State *L);
/* not to be called directly */
LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
size_t size); size_t size);
LUAI_FUNC void *luaM_toobig (lua_State *L);
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
size_t size_elem, int limit, size_t size_elem, int limit,
const char *errormsg); const char *what);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ ** $Id: lobject.h,v 2.64 2011/10/31 17:48:22 roberto Exp $
** Type definitions for Lua objects ** Type definitions for Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -16,18 +16,44 @@
#include "lua.h" #include "lua.h"
/* tags for values visible from Lua */ /*
#define LAST_TAG LUA_TTHREAD ** Extra tags for non-values
*/
#define LUA_TPROTO LUA_NUMTAGS
#define LUA_TUPVAL (LUA_NUMTAGS+1)
#define LUA_TDEADKEY (LUA_NUMTAGS+2)
#define NUM_TAGS (LAST_TAG+1) /*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
*/
#define LUA_TOTALTAGS (LUA_TUPVAL+2)
/* /*
** Extra tags for non-values ** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* value)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/ */
#define LUA_TPROTO (LAST_TAG+1)
#define LUA_TUPVAL (LAST_TAG+2) /*
#define LUA_TDEADKEY (LAST_TAG+3) ** LUA_TFUNCTION variants:
** 0 - Lua function
** 1 - light C function
** 2 - regular C function (closure)
*/
/* Variant tags for functions */
#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */
#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */
#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)
/* mark a tag as collectable */
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
/* /*
@ -52,120 +78,166 @@ typedef struct GCheader {
/* /*
** Union of all Lua values ** Union of all Lua values
*/ */
typedef union { typedef union Value Value;
GCObject *gc;
void *p;
lua_Number n; #define numfield lua_Number n; /* numbers */
int b;
} Value;
/* /*
** Tagged Values ** Tagged Values. This is the basic representation of values in Lua,
** an actual value plus a tag with its type.
*/ */
#define TValuefields Value value; int tt #define TValuefields Value value_; int tt_
typedef struct lua_TValue TValue;
/* macro defining a nil value */
#define NILCONSTANT {NULL}, LUA_TNIL
#define val_(o) ((o)->value_)
#define num_(o) (val_(o).n)
typedef struct lua_TValue {
TValuefields; /* raw type tag of a TValue */
} TValue; #define rttype(o) ((o)->tt_)
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define ttype(o) (rttype(o) & 0x3F)
/* type tag of a TValue with no variants (bits 0-3) */
#define ttypenv(o) (rttype(o) & 0x0F)
/* Macros to test type */ /* Macros to test type */
#define ttisnil(o) (ttype(o) == LUA_TNIL) #define checktag(o,t) (rttype(o) == (t))
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) #define ttisnumber(o) checktag((o), LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING) #define ttisnil(o) checktag((o), LUA_TNIL)
#define ttistable(o) (ttype(o) == LUA_TTABLE) #define ttisboolean(o) checktag((o), LUA_TBOOLEAN)
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) #define ttisstring(o) checktag((o), ctb(LUA_TSTRING))
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) #define ttistable(o) checktag((o), ctb(LUA_TTABLE))
#define ttisthread(o) (ttype(o) == LUA_TTHREAD) #define ttisfunction(o) (ttypenv(o) == LUA_TFUNCTION)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) #define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION)
#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL))
#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL))
#define ttislcf(o) checktag((o), LUA_TLCF)
#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
#define ttisequal(o1,o2) (rttype(o1) == rttype(o2))
/* Macros to access values */ /* Macros to access values */
#define ttype(o) ((o)->tt) #define nvalue(o) check_exp(ttisnumber(o), num_(o))
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts)
#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
#define tsvalue(o) (&rawtsvalue(o)->tsv) #define tsvalue(o) (&rawtsvalue(o)->tsv)
#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) #define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u)
#define uvalue(o) (&rawuvalue(o)->uv) #define uvalue(o) (&rawuvalue(o)->uv)
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) #define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl)
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) #define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l)
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) #define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c)
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) #define fvalue(o) check_exp(ttislcf(o), val_(o).f)
#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h)
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th)
/* a dead value may get the 'gc' field, but cannot access its contents */
#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
/*
** for internal debug only #define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)
*/
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) /* Macros for internal tests */
#define righttt(obj) (ttypenv(obj) == gcvalue(obj)->gch.tt)
#define checkliveness(g,obj) \ #define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \ lua_longassert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) (righttt(obj) && !isdead(g,gcvalue(obj))))
/* Macros to set values */ /* Macros to set values */
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define settt_(o,t) ((o)->tt_=(t))
#define setnvalue(obj,x) \ #define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); }
#define changenvalue(o,x) check_exp(ttisnumber(o), num_(o)=(x))
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
#define setfvalue(obj,x) \
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); }
#define setpvalue(obj,x) \ #define setpvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); }
#define setbvalue(obj,x) \ #define setbvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); }
#define setgcovalue(L,obj,x) \
{ TValue *io=(obj); GCObject *i_g=(x); \
val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); }
#define setsvalue(L,obj,x) \ #define setsvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { TValue *io=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TSTRING)); \
checkliveness(G(L),i_o); } checkliveness(G(L),io); }
#define setuvalue(L,obj,x) \ #define setuvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { TValue *io=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \
checkliveness(G(L),i_o); } checkliveness(G(L),io); }
#define setthvalue(L,obj,x) \ #define setthvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { TValue *io=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \
checkliveness(G(L),i_o); } checkliveness(G(L),io); }
#define setclvalue(L,obj,x) \ #define setclLvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { TValue *io=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \
checkliveness(G(L),i_o); } checkliveness(G(L),io); }
#define setclCvalue(L,obj,x) \
{ TValue *io=(obj); \
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \
checkliveness(G(L),io); }
#define sethvalue(L,obj,x) \ #define sethvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { TValue *io=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(G(L),i_o); } checkliveness(G(L),io); }
#define setptvalue(L,obj,x) \ #define setptvalue(L,obj,x) \
{ TValue *i_o=(obj); \ { TValue *io=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TPROTO)); \
checkliveness(G(L),i_o); } checkliveness(G(L),io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
#define setobj(L,obj1,obj2) \ #define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \ { const TValue *io2=(obj2); TValue *io1=(obj1); \
o1->value = o2->value; o1->tt=o2->tt; \ io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
checkliveness(G(L),o1); } checkliveness(G(L),io1); }
/* /*
** different types of sets, according to destination ** different types of assignments, according to destination
*/ */
/* from stack to (same) stack */ /* from stack to (same) stack */
@ -183,18 +255,147 @@ typedef struct lua_TValue {
#define setobj2n setobj #define setobj2n setobj
#define setsvalue2n setsvalue #define setsvalue2n setsvalue
#define setttype(obj, tt) (ttype(obj) = (tt))
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
/*
** {======================================================
** NaN Trick
** =======================================================
*/
#if defined(LUA_NANTRICK) \
|| defined(LUA_NANTRICK_LE) \
|| defined(LUA_NANTRICK_BE)
/*
** numbers are represented in the 'd_' field. All other values have the
** value (NNMARK | tag) in 'tt__'. A number with such pattern would be
** a "signaled NaN", which is never generated by regular operations by
** the CPU (nor by 'strtod')
*/
#if !defined(NNMARK)
#define NNMARK 0x7FF7A500
#define NNMASK 0x7FFFFF00
#endif
#undef TValuefields
#undef NILCONSTANT
#if defined(LUA_NANTRICK_LE)
/* little endian */
#define TValuefields \
union { struct { Value v__; int tt__; } i; double d__; } u
#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}}
/* field-access macros */
#define v_(o) ((o)->u.i.v__)
#define d_(o) ((o)->u.d__)
#define tt_(o) ((o)->u.i.tt__)
#elif defined(LUA_NANTRICK_BE)
/* big endian */
#define TValuefields \
union { struct { int tt__; Value v__; } i; double d__; } u
#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}}
/* field-access macros */
#define v_(o) ((o)->u.i.v__)
#define d_(o) ((o)->u.d__)
#define tt_(o) ((o)->u.i.tt__)
#elif !defined(TValuefields)
#error option 'LUA_NANTRICK' needs declaration for 'TValuefields'
#endif
/* correspondence with standard representation */
#undef val_
#define val_(o) v_(o)
#undef num_
#define num_(o) d_(o)
#undef numfield
#define numfield /* no such field; numbers are the entire struct */
/* basic check to distinguish numbers from non-numbers */
#undef ttisnumber
#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK)
#define tag2tt(t) (NNMARK | (t))
#undef rttype
#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff)
#undef settt_
#define settt_(o,t) (tt_(o) = tag2tt(t))
#undef setnvalue
#define setnvalue(obj,x) \
{ TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); }
#undef setobj
#define setobj(L,obj1,obj2) \
{ const TValue *o2_=(obj2); TValue *o1_=(obj1); \
o1_->u = o2_->u; \
checkliveness(G(L),o1_); }
/*
** these redefinitions are not mandatory, but these forms are more efficient
*/
#undef checktag
#define checktag(o,t) (tt_(o) == tag2tt(t))
#undef ttisequal
#define ttisequal(o1,o2) \
(ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; }
#else
#define luai_checknum(L,o,c) { /* empty */ }
#endif
/* }====================================================== */
/*
** {======================================================
** types and prototypes
** =======================================================
*/
union Value {
GCObject *gc; /* collectable objects */
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
numfield /* numbers */
};
struct lua_TValue {
TValuefields;
};
typedef TValue *StkId; /* index to stack elements */ typedef TValue *StkId; /* index to stack elements */
/* /*
** String headers for string table ** Header for string value; string bytes follow the end of this structure
*/ */
typedef union TString { typedef union TString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */ L_Umaxalign dummy; /* ensures maximum alignment for strings */
@ -202,28 +403,53 @@ typedef union TString {
CommonHeader; CommonHeader;
lu_byte reserved; lu_byte reserved;
unsigned int hash; unsigned int hash;
size_t len; size_t len; /* number of characters in string */
} tsv; } tsv;
} TString; } TString;
/* get the actual string (array of bytes) from a TString */
#define getstr(ts) cast(const char *, (ts) + 1) #define getstr(ts) cast(const char *, (ts) + 1)
#define svalue(o) getstr(rawtsvalue(o))
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(rawtsvalue(o))
/*
** Header for userdata; memory area follows the end of this structure
*/
typedef union Udata { typedef union Udata {
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct { struct {
CommonHeader; CommonHeader;
struct Table *metatable; struct Table *metatable;
struct Table *env; struct Table *env;
size_t len; size_t len; /* number of bytes */
} uv; } uv;
} Udata; } Udata;
/*
** Description of an upvalue for function prototypes
*/
typedef struct Upvaldesc {
TString *name; /* upvalue name (for debug information) */
lu_byte instack; /* whether it is in stack */
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
} Upvaldesc;
/*
** Description of a local variable for function prototypes
** (used for debug information)
*/
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
} LocVar;
/* /*
** Function Prototypes ** Function Prototypes
@ -233,11 +459,12 @@ typedef struct Proto {
TValue *k; /* constants used by the function */ TValue *k; /* constants used by the function */
Instruction *code; Instruction *code;
struct Proto **p; /* functions defined inside the function */ struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines */ int *lineinfo; /* map from opcodes to source lines (debug information) */
struct LocVar *locvars; /* information about local variables */ LocVar *locvars; /* information about local variables (debug information) */
TString **upvalues; /* upvalue names */ Upvaldesc *upvalues; /* upvalue information */
TString *source; union Closure *cache; /* last created closure with this prototype */
int sizeupvalues; TString *source; /* used for debug information */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of `k' */ int sizek; /* size of `k' */
int sizecode; int sizecode;
int sizelineinfo; int sizelineinfo;
@ -246,31 +473,16 @@ typedef struct Proto {
int linedefined; int linedefined;
int lastlinedefined; int lastlinedefined;
GCObject *gclist; GCObject *gclist;
lu_byte nups; /* number of upvalues */ lu_byte numparams; /* number of fixed parameters */
lu_byte numparams;
lu_byte is_vararg; lu_byte is_vararg;
lu_byte maxstacksize; lu_byte maxstacksize; /* maximum stack used by this function */
} Proto; } Proto;
/* masks for new-style vararg */
#define VARARG_HASARG 1
#define VARARG_ISVARARG 2
#define VARARG_NEEDSARG 4
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
} LocVar;
/* /*
** Upvalues ** Lua Upvalues
*/ */
typedef struct UpVal { typedef struct UpVal {
CommonHeader; CommonHeader;
TValue *v; /* points to stack or to its own value */ TValue *v; /* points to stack or to its own value */
@ -289,20 +501,19 @@ typedef struct UpVal {
*/ */
#define ClosureHeader \ #define ClosureHeader \
CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist
struct Table *env
typedef struct CClosure { typedef struct CClosure {
ClosureHeader; ClosureHeader;
lua_CFunction f; lua_CFunction f;
TValue upvalue[1]; TValue upvalue[1]; /* list of upvalues */
} CClosure; } CClosure;
typedef struct LClosure { typedef struct LClosure {
ClosureHeader; ClosureHeader;
struct Proto *p; struct Proto *p;
UpVal *upvals[1]; UpVal *upvals[1]; /* list of upvalues */
} LClosure; } LClosure;
@ -312,8 +523,9 @@ typedef union Closure {
} Closure; } Closure;
#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) #define isLfunction(o) ttisLclosure(o)
#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
#define getproto(o) (clLvalue(o)->p)
/* /*
@ -337,7 +549,7 @@ typedef struct Node {
typedef struct Table { typedef struct Table {
CommonHeader; CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */ lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable; struct Table *metatable;
TValue *array; /* array part */ TValue *array; /* array part */
@ -360,17 +572,21 @@ typedef struct Table {
#define sizenode(t) (twoto((t)->lsizenode)) #define sizenode(t) (twoto((t)->lsizenode))
/*
** (address of) a fixed nil value
*/
#define luaO_nilobject (&luaO_nilobject_) #define luaO_nilobject (&luaO_nilobject_)
LUAI_DATA const TValue luaO_nilobject_;
#define ceillog2(x) (luaO_log2((x)-1) + 1) LUAI_DDEC const TValue luaO_nilobject_;
LUAI_FUNC int luaO_log2 (unsigned int x);
LUAI_FUNC int luaO_int2fb (unsigned int x); LUAI_FUNC int luaO_int2fb (unsigned int x);
LUAI_FUNC int luaO_fb2int (int x); LUAI_FUNC int luaO_fb2int (int x);
LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2);
LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result);
LUAI_FUNC int luaO_hexavalue (int c);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp); va_list argp);
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);

@ -1,5 +1,5 @@
/* /*
** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $
** Opcodes for Lua virtual machine ** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -17,6 +17,7 @@
`A' : 8 bits `A' : 8 bits
`B' : 9 bits `B' : 9 bits
`C' : 9 bits `C' : 9 bits
'Ax' : 26 bits ('A', 'B', and 'C' together)
`Bx' : 18 bits (`B' and `C' together) `Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx `sBx' : signed Bx
@ -28,7 +29,7 @@
===========================================================================*/ ===========================================================================*/
enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
/* /*
@ -38,6 +39,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
#define SIZE_B 9 #define SIZE_B 9
#define SIZE_Bx (SIZE_C + SIZE_B) #define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_A 8 #define SIZE_A 8
#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A)
#define SIZE_OP 6 #define SIZE_OP 6
@ -46,6 +48,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
#define POS_C (POS_A + SIZE_A) #define POS_C (POS_A + SIZE_A)
#define POS_B (POS_C + SIZE_C) #define POS_B (POS_C + SIZE_C)
#define POS_Bx POS_C #define POS_Bx POS_C
#define POS_Ax POS_A
/* /*
@ -61,6 +64,12 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
#define MAXARG_sBx MAX_INT #define MAXARG_sBx MAX_INT
#endif #endif
#if SIZE_Ax < LUAI_BITSINT-1
#define MAXARG_Ax ((1<<SIZE_Ax)-1)
#else
#define MAXARG_Ax MAX_INT
#endif
#define MAXARG_A ((1<<SIZE_A)-1) #define MAXARG_A ((1<<SIZE_A)-1)
#define MAXARG_B ((1<<SIZE_B)-1) #define MAXARG_B ((1<<SIZE_B)-1)
@ -68,7 +77,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
/* creates a mask with `n' 1 bits at position `p' */ /* creates a mask with `n' 1 bits at position `p' */
#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p) #define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p))
/* creates a mask with `n' 0 bits at position `p' */ /* creates a mask with `n' 0 bits at position `p' */
#define MASK0(n,p) (~MASK1(n,p)) #define MASK0(n,p) (~MASK1(n,p))
@ -81,21 +90,24 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0))) #define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0)))
#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) ((cast(Instruction, v)<<pos)&MASK1(size,pos))))
#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0))) #define GETARG_A(i) getarg(i, POS_A, SIZE_A)
#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0))) #define GETARG_B(i) getarg(i, POS_B, SIZE_B)
#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ #define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0))) #define GETARG_C(i) getarg(i, POS_C, SIZE_C)
#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ #define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
#define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx)
#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
#define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax)
#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax)
#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) #define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) #define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
@ -110,6 +122,9 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
| (cast(Instruction, a)<<POS_A) \ | (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, bc)<<POS_Bx)) | (cast(Instruction, bc)<<POS_Bx))
#define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_Ax))
/* /*
** Macros to operate RK indices ** Macros to operate RK indices
@ -153,14 +168,15 @@ name args description
------------------------------------------------------------------------*/ ------------------------------------------------------------------------*/
OP_MOVE,/* A B R(A) := R(B) */ OP_MOVE,/* A B R(A) := R(B) */
OP_LOADK,/* A Bx R(A) := Kst(Bx) */ OP_LOADK,/* A Bx R(A) := Kst(Bx) */
OP_LOADKX,/* A R(A) := Kst(extra arg) */
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
OP_GETUPVAL,/* A B R(A) := UpValue[B] */ OP_GETUPVAL,/* A B R(A) := UpValue[B] */
OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */ OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */ OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */
OP_SETUPVAL,/* A B UpValue[B] := R(A) */ OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
@ -180,14 +196,13 @@ OP_LEN,/* A B R(A) := length of R(B) */
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
OP_JMP,/* sBx pc+=sBx */ OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
@ -197,39 +212,44 @@ OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */
OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
} OpCode; } OpCode;
#define NUM_OPCODES (cast(int, OP_VARARG) + 1) #define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1)
/*=========================================================================== /*===========================================================================
Notes: Notes:
(*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then `top' is
and can be 0: OP_CALL then sets `top' to last_result+1, so set to last_result+1, so next open instruction (OP_CALL, OP_RETURN,
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. OP_SETLIST) may use `top'.
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0). set top (like in OP_CALL with C == 0).
(*) In OP_RETURN, if (B == 0) then return up to `top' (*) In OP_RETURN, if (B == 0) then return up to `top'.
(*) In OP_SETLIST, if (B == 0) then B = `top'; (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next
if (C == 0) then next `instruction' is real C 'instruction' is EXTRAARG(real C).
(*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
(*) For comparisons, A specifies what condition the test should accept (*) For comparisons, A specifies what condition the test should accept
(true or false). (true or false).
(*) All `skips' (pc++) assume that next instruction is a jump.
(*) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/ ===========================================================================*/
@ -239,8 +259,8 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
** bits 2-3: C arg mode ** bits 2-3: C arg mode
** bits 4-5: B arg mode ** bits 4-5: B arg mode
** bit 6: instruction set register A ** bit 6: instruction set register A
** bit 7: operator is a test ** bit 7: operator is a test (next instruction must be a jump)
*/ */
enum OpArgMask { enum OpArgMask {
OpArgN, /* argument is not used */ OpArgN, /* argument is not used */
@ -249,7 +269,7 @@ enum OpArgMask {
OpArgK /* argument is a constant or register/constant */ OpArgK /* argument is a constant or register/constant */
}; };
LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
@ -258,7 +278,7 @@ LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) #define testTMode(m) (luaP_opmodes[m] & (1 << 7))
LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
/* number of list items to accumulate before a SETLIST instruction */ /* number of list items to accumulate before a SETLIST instruction */

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lparser.h,v 1.69 2011/07/27 18:09:01 roberto Exp $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -23,34 +23,72 @@ typedef enum {
VFALSE, VFALSE,
VK, /* info = index of constant in `k' */ VK, /* info = index of constant in `k' */
VKNUM, /* nval = numerical value */ VKNUM, /* nval = numerical value */
VNONRELOC, /* info = result register */
VLOCAL, /* info = local register */ VLOCAL, /* info = local register */
VUPVAL, /* info = index of upvalue in `upvalues' */ VUPVAL, /* info = index of upvalue in 'upvalues' */
VGLOBAL, /* info = index of table; aux = index of global name in `k' */ VINDEXED, /* t = table register/upvalue; idx = index R/K */
VINDEXED, /* info = table register; aux = index register (or `k') */
VJMP, /* info = instruction pc */ VJMP, /* info = instruction pc */
VRELOCABLE, /* info = instruction pc */ VRELOCABLE, /* info = instruction pc */
VNONRELOC, /* info = result register */
VCALL, /* info = instruction pc */ VCALL, /* info = instruction pc */
VVARARG /* info = instruction pc */ VVARARG /* info = instruction pc */
} expkind; } expkind;
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED)
#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
typedef struct expdesc { typedef struct expdesc {
expkind k; expkind k;
union { union {
struct { int info, aux; } s; struct { /* for indexed variables (VINDEXED) */
lua_Number nval; short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind;
int info; /* for generic use */
lua_Number nval; /* for VKNUM */
} u; } u;
int t; /* patch list of `exit when true' */ int t; /* patch list of `exit when true' */
int f; /* patch list of `exit when false' */ int f; /* patch list of `exit when false' */
} expdesc; } expdesc;
typedef struct upvaldesc { /* description of active local variable */
lu_byte k; typedef struct Vardesc {
lu_byte info; short idx; /* variable index in stack */
} upvaldesc; } Vardesc;
/* description of pending goto statements and label statements */
typedef struct Labeldesc {
TString *name; /* label identifier */
int pc; /* position in code */
int line; /* line where it appeared */
lu_byte nactvar; /* local level where it appears in current block */
} Labeldesc;
/* list of labels or gotos */
typedef struct Labellist {
Labeldesc *arr; /* array */
int n; /* number of entries in use */
int size; /* array size */
} Labellist;
/* dynamic structures used by the parser */
typedef struct Dyndata {
struct { /* list of active local variables */
Vardesc *arr;
int n;
int size;
} actvar;
Labellist gt; /* list of pending gotos */
Labellist label; /* list of active labels */
} Dyndata;
/* control of blocks */
struct BlockCnt; /* defined in lparser.c */ struct BlockCnt; /* defined in lparser.c */
@ -60,23 +98,22 @@ typedef struct FuncState {
Table *h; /* table to find (and reuse) elements in `k' */ Table *h; /* table to find (and reuse) elements in `k' */
struct FuncState *prev; /* enclosing function */ struct FuncState *prev; /* enclosing function */
struct LexState *ls; /* lexical state */ struct LexState *ls; /* lexical state */
struct lua_State *L; /* copy of the Lua state */
struct BlockCnt *bl; /* chain of current blocks */ struct BlockCnt *bl; /* chain of current blocks */
int pc; /* next position to code (equivalent to `ncode') */ int pc; /* next position to code (equivalent to `ncode') */
int lasttarget; /* `pc' of last `jump target' */ int lasttarget; /* 'label' of last 'jump label' */
int jpc; /* list of pending jumps to `pc' */ int jpc; /* list of pending jumps to `pc' */
int freereg; /* first free register */
int nk; /* number of elements in `k' */ int nk; /* number of elements in `k' */
int np; /* number of elements in `p' */ int np; /* number of elements in `p' */
short nlocvars; /* number of elements in `locvars' */ int firstlocal; /* index of first local var (in Dyndata array) */
short nlocvars; /* number of elements in 'f->locvars' */
lu_byte nactvar; /* number of active local variables */ lu_byte nactvar; /* number of active local variables */
upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ lu_byte nups; /* number of upvalues */
unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ lu_byte freereg; /* first free register */
} FuncState; } FuncState;
LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
const char *name); Dyndata *dyd, const char *name, int firstchar);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ ** $Id: lstate.h,v 2.74 2011/09/30 12:45:07 roberto Exp $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -14,26 +14,47 @@
#include "lzio.h" #include "lzio.h"
/*
struct lua_longjmp; /* defined in ldo.c */ ** Some notes about garbage-collected objects: All objects in Lua must
** be kept somehow accessible until being freed.
**
** Lua keeps most objects linked in list g->allgc. The link uses field
** 'next' of the CommonHeader.
**
** Strings are kept in several lists headed by the array g->strt.hash.
**
** Open upvalues are not subject to independent garbage collection. They
** are collected together with their respective threads. Lua keeps a
** double-linked list with all open upvalues (g->uvhead) so that it can
** mark objects referred by them. (They are always gray, so they must
** be remarked in the atomic step. Usually their contents would be marked
** when traversing the respective threads, but the thread may already be
** dead, while the upvalue is still accessible through closures.)
**
** Objects with finalizers are kept in the list g->finobj.
**
** The list g->tobefnz links all objects being finalized.
*/
/* table of globals */
#define gt(L) (&L->l_gt)
/* registry */ struct lua_longjmp; /* defined in ldo.c */
#define registry(L) (&G(L)->l_registry)
/* extra stack space to handle TM calls and some other extras */ /* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5 #define EXTRA_STACK 5
#define BASIC_CI_SIZE 8
#define BASIC_STACK_SIZE (2*LUA_MINSTACK) #define BASIC_STACK_SIZE (2*LUA_MINSTACK)
/* kinds of Garbage Collection */
#define KGC_NORMAL 0
#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */
#define KGC_GEN 2 /* generational collection */
typedef struct stringtable { typedef struct stringtable {
GCObject **hash; GCObject **hash;
@ -43,54 +64,83 @@ typedef struct stringtable {
/* /*
** informations about a call ** information about a call
*/ */
typedef struct CallInfo { typedef struct CallInfo {
StkId base; /* base for this function */
StkId func; /* function index in the stack */ StkId func; /* function index in the stack */
StkId top; /* top for this function */ StkId top; /* top for this function */
const Instruction *savedpc; struct CallInfo *previous, *next; /* dynamic call link */
int nresults; /* expected number of results from this function */ short nresults; /* expected number of results from this function */
int tailcalls; /* number of tail calls lost under this entry */ lu_byte callstatus;
union {
struct { /* only for Lua functions */
StkId base; /* base for this function */
const Instruction *savedpc;
} l;
struct { /* only for C functions */
int ctx; /* context info. in case of yields */
lua_CFunction k; /* continuation in case of yields */
ptrdiff_t old_errfunc;
ptrdiff_t extra;
lu_byte old_allowhook;
lu_byte status;
} c;
} u;
} CallInfo; } CallInfo;
/*
** Bits in CallInfo status
*/
#define CIST_LUA (1<<0) /* call is running a Lua function */
#define CIST_HOOKED (1<<1) /* call is running a debug hook */
#define CIST_REENTRY (1<<2) /* call is running on same invocation of
luaV_execute of previous call */
#define CIST_YIELDED (1<<3) /* call reentered after suspension */
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
#define CIST_STAT (1<<5) /* call has an error status (pcall) */
#define CIST_TAIL (1<<6) /* call was tail called */
#define curr_func(L) (clvalue(L->ci->func)) #define isLua(ci) ((ci)->callstatus & CIST_LUA)
#define ci_func(ci) (clvalue((ci)->func))
#define f_isLua(ci) (!ci_func(ci)->c.isC)
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
/* /*
** `global state', shared by all threads of this state ** `global state', shared by all threads of this state
*/ */
typedef struct global_State { typedef struct global_State {
stringtable strt; /* hash table for strings */
lua_Alloc frealloc; /* function to reallocate memory */ lua_Alloc frealloc; /* function to reallocate memory */
void *ud; /* auxiliary data to `frealloc' */ void *ud; /* auxiliary data to `frealloc' */
lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem lastmajormem; /* memory in use after last major collection */
stringtable strt; /* hash table for strings */
TValue l_registry;
lu_byte currentwhite; lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */ lu_byte gcstate; /* state of garbage collector */
lu_byte gckind; /* kind of GC running */
lu_byte gcrunning; /* true if GC is running */
int sweepstrgc; /* position of sweep in `strt' */ int sweepstrgc; /* position of sweep in `strt' */
GCObject *rootgc; /* list of all collectable objects */ GCObject *allgc; /* list of all collectable objects */
GCObject **sweepgc; /* position of sweep in `rootgc' */ GCObject *finobj; /* list of collectable objects with finalizers */
GCObject **sweepgc; /* current position of sweep */
GCObject *gray; /* list of gray objects */ GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */ GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of weak tables (to be cleared) */ GCObject *weak; /* list of tables with weak values */
GCObject *tmudata; /* last element of list of userdata to be GC */ GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
Mbuffer buff; /* temporary buffer for string concatentation */ GCObject *allweak; /* list of all-weak tables */
lu_mem GCthreshold; GCObject *tobefnz; /* list of userdata to be GC */
lu_mem totalbytes; /* number of bytes currently allocated */ UpVal uvhead; /* head of double-linked list of all open upvalues */
lu_mem estimate; /* an estimate of number of bytes actually in use */ Mbuffer buff; /* temporary buffer for string concatenation */
lu_mem gcdept; /* how much GC is `behind schedule' */
int gcpause; /* size of pause between successive GCs */ int gcpause; /* size of pause between successive GCs */
int gcmajorinc; /* how much to wait for a major GC (only in gen. mode) */
int gcstepmul; /* GC `granularity' */ int gcstepmul; /* GC `granularity' */
lua_CFunction panic; /* to be called in unprotected errors */ lua_CFunction panic; /* to be called in unprotected errors */
TValue l_registry;
struct lua_State *mainthread; struct lua_State *mainthread;
UpVal uvhead; /* head of double-linked list of all open upvalues */ const lua_Number *version; /* pointer to version number */
struct Table *mt[NUM_TAGS]; /* metatables for basic types */ TString *memerrmsg; /* memory-error message */
TString *tmname[TM_N]; /* array with tag-method names */ TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
} global_State; } global_State;
@ -101,29 +151,24 @@ struct lua_State {
CommonHeader; CommonHeader;
lu_byte status; lu_byte status;
StkId top; /* first free slot in the stack */ StkId top; /* first free slot in the stack */
StkId base; /* base of current function */
global_State *l_G; global_State *l_G;
CallInfo *ci; /* call info for current function */ CallInfo *ci; /* call info for current function */
const Instruction *savedpc; /* `savedpc' of current function */ const Instruction *oldpc; /* last pc traced */
StkId stack_last; /* last free slot in the stack */ StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */ StkId stack; /* stack base */
CallInfo *end_ci; /* points after end of ci array*/
CallInfo *base_ci; /* array of CallInfo's */
int stacksize; int stacksize;
int size_ci; /* size of array `base_ci' */ unsigned short nny; /* number of non-yieldable calls in stack */
unsigned short nCcalls; /* number of nested C calls */ unsigned short nCcalls; /* number of nested C calls */
unsigned short baseCcalls; /* nested C calls when resuming coroutine */
lu_byte hookmask; lu_byte hookmask;
lu_byte allowhook; lu_byte allowhook;
int basehookcount; int basehookcount;
int hookcount; int hookcount;
lua_Hook hook; lua_Hook hook;
TValue l_gt; /* table of globals */
TValue env; /* temporary place for environments */
GCObject *openupval; /* list of open upvalues in this stack */ GCObject *openupval; /* list of open upvalues in this stack */
GCObject *gclist; GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */ struct lua_longjmp *errorJmp; /* current error recover point */
ptrdiff_t errfunc; /* current error handling function (stack index) */ ptrdiff_t errfunc; /* current error handling function (stack index) */
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
}; };
@ -134,7 +179,7 @@ struct lua_State {
** Union of all collectable objects ** Union of all collectable objects
*/ */
union GCObject { union GCObject {
GCheader gch; GCheader gch; /* common header */
union TString ts; union TString ts;
union Udata u; union Udata u;
union Closure cl; union Closure cl;
@ -145,25 +190,31 @@ union GCObject {
}; };
#define gch(o) (&(o)->gch)
/* macros to convert a GCObject into a specific value */ /* macros to convert a GCObject into a specific value */
#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
#define gco2ts(o) (&rawgco2ts(o)->tsv) #define gco2ts(o) (&rawgco2ts(o)->tsv)
#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
#define gco2u(o) (&rawgco2u(o)->uv) #define gco2u(o) (&rawgco2u(o)->uv)
#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) #define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) #define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define ngcotouv(o) \
check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
/* macro to convert any Lua object into a GCObject */ /* macro to convert any Lua object into a GCObject */
#define obj2gco(v) (cast(GCObject *, (v))) #define obj2gco(v) (cast(GCObject *, (v)))
LUAI_FUNC lua_State *luaE_newthread (lua_State *L); /* actual number of total bytes allocated */
#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt)
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
LUAI_FUNC void luaE_freeCI (lua_State *L);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lstring.h,v 1.46 2010/04/05 16:26:37 roberto Exp $
** String table (keep all strings handled by Lua) ** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -7,7 +7,6 @@
#ifndef lstring_h #ifndef lstring_h
#define lstring_h #define lstring_h
#include "lgc.h" #include "lgc.h"
#include "lobject.h" #include "lobject.h"
#include "lstate.h" #include "lstate.h"
@ -17,15 +16,22 @@
#define sizeudata(u) (sizeof(union Udata)+(u)->len) #define sizeudata(u) (sizeof(union Udata)+(u)->len)
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1)) (sizeof(s)/sizeof(char))-1))
#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
/*
** as all string are internalized, string equality becomes
** pointer equality
*/
#define eqstr(a,b) ((a) == (b))
LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -11,20 +11,21 @@
#define gnode(t,i) (&(t)->node[i]) #define gnode(t,i) (&(t)->node[i])
#define gkey(n) (&(n)->i_key.nk) #define gkey(n) (&(n)->i_key.tvk)
#define gval(n) (&(n)->i_val) #define gval(n) (&(n)->i_val)
#define gnext(n) ((n)->i_key.nk.next) #define gnext(n) ((n)->i_key.nk.next)
#define key2tval(n) (&(n)->i_key.tvk) #define invalidateTMcache(t) ((t)->flags = 0)
LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); LUAI_FUNC Table *luaH_new (lua_State *L);
LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize);
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
LUAI_FUNC void luaH_free (lua_State *L, Table *t); LUAI_FUNC void luaH_free (lua_State *L, Table *t);
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);

@ -1,5 +1,5 @@
/* /*
** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -20,6 +20,7 @@ typedef enum {
TM_NEWINDEX, TM_NEWINDEX,
TM_GC, TM_GC,
TM_MODE, TM_MODE,
TM_LEN,
TM_EQ, /* last tag method with `fast' access */ TM_EQ, /* last tag method with `fast' access */
TM_ADD, TM_ADD,
TM_SUB, TM_SUB,
@ -28,7 +29,6 @@ typedef enum {
TM_MOD, TM_MOD,
TM_POW, TM_POW,
TM_UNM, TM_UNM,
TM_LEN,
TM_LT, TM_LT,
TM_LE, TM_LE,
TM_CONCAT, TM_CONCAT,
@ -43,7 +43,10 @@ typedef enum {
#define fasttm(l,et,e) gfasttm(G(l), et, e) #define fasttm(l,et,e) gfasttm(G(l), et, e)
LUAI_DATA const char *const luaT_typenames[]; #define ttypename(x) luaT_typenames_[(x) + 1]
#define objtypename(x) ttypename(ttypenv(x))
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);

@ -1,6 +1,6 @@
/* /*
** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ** $Id: lua.h,v 1.282 2011/11/29 15:55:08 roberto Exp $
** Lua - An Extensible Extension Language ** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file ** See Copyright Notice at the end of this file
*/ */
@ -16,35 +16,39 @@
#include "luaconf.h" #include "luaconf.h"
#define LUA_VERSION "Lua 5.1" #define LUA_VERSION_MAJOR "5"
#define LUA_RELEASE "Lua 5.1.4" #define LUA_VERSION_MINOR "2"
#define LUA_VERSION_NUM 501 #define LUA_VERSION_NUM 502
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" #define LUA_VERSION_RELEASE "0"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2011 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
/* mark for precompiled code (`<esc>Lua') */
#define LUA_SIGNATURE "\033Lua"
/* option for multiple returns in `lua_pcall' and `lua_call' */ /* mark for precompiled code ('<esc>Lua') */
#define LUA_SIGNATURE "\033Lua"
/* option for multiple returns in 'lua_pcall' and 'lua_call' */
#define LUA_MULTRET (-1) #define LUA_MULTRET (-1)
/* /*
** pseudo-indices ** pseudo-indices
*/ */
#define LUA_REGISTRYINDEX (-10000) #define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX
#define LUA_ENVIRONINDEX (-10001) #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
#define LUA_GLOBALSINDEX (-10002)
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
/* thread status; 0 is OK */ /* thread status */
#define LUA_OK 0
#define LUA_YIELD 1 #define LUA_YIELD 1
#define LUA_ERRRUN 2 #define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3 #define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4 #define LUA_ERRMEM 4
#define LUA_ERRERR 5 #define LUA_ERRGCMM 5
#define LUA_ERRERR 6
typedef struct lua_State lua_State; typedef struct lua_State lua_State;
@ -81,18 +85,18 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
#define LUA_TUSERDATA 7 #define LUA_TUSERDATA 7
#define LUA_TTHREAD 8 #define LUA_TTHREAD 8
#define LUA_NUMTAGS 9
/* minimum Lua stack available to a C function */ /* minimum Lua stack available to a C function */
#define LUA_MINSTACK 20 #define LUA_MINSTACK 20
/* /* predefined values in the registry */
** generic extra include file #define LUA_RIDX_MAINTHREAD 1
*/ #define LUA_RIDX_GLOBALS 2
#if defined(LUA_USER_H) #define LUA_RIDX_LAST LUA_RIDX_GLOBALS
#include LUA_USER_H
#endif
/* type of numbers in Lua */ /* type of numbers in Lua */
@ -102,6 +106,18 @@ typedef LUA_NUMBER lua_Number;
/* type for integer functions */ /* type for integer functions */
typedef LUA_INTEGER lua_Integer; typedef LUA_INTEGER lua_Integer;
/* unsigned integer type */
typedef LUA_UNSIGNED lua_Unsigned;
/*
** generic extra include file
*/
#if defined(LUA_USER_H)
#include LUA_USER_H
#endif
/* /*
@ -114,15 +130,20 @@ LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
LUA_API const lua_Number *(lua_version) (lua_State *L);
/* /*
** basic stack manipulation ** basic stack manipulation
*/ */
LUA_API int (lua_absindex) (lua_State *L, int idx);
LUA_API int (lua_gettop) (lua_State *L); LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx); LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx); LUA_API void (lua_pushvalue) (lua_State *L, int idx);
LUA_API void (lua_remove) (lua_State *L, int idx); LUA_API void (lua_remove) (lua_State *L, int idx);
LUA_API void (lua_insert) (lua_State *L, int idx); LUA_API void (lua_insert) (lua_State *L, int idx);
LUA_API void (lua_replace) (lua_State *L, int idx); LUA_API void (lua_replace) (lua_State *L, int idx);
LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
LUA_API int (lua_checkstack) (lua_State *L, int sz); LUA_API int (lua_checkstack) (lua_State *L, int sz);
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
@ -139,29 +160,49 @@ LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx); LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp); LUA_API const char *(lua_typename) (lua_State *L, int tp);
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum);
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum);
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
LUA_API int (lua_toboolean) (lua_State *L, int idx); LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_objlen) (lua_State *L, int idx); LUA_API size_t (lua_rawlen) (lua_State *L, int idx);
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API void *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
LUA_API const void *(lua_topointer) (lua_State *L, int idx); LUA_API const void *(lua_topointer) (lua_State *L, int idx);
/*
** Comparison and arithmetic functions
*/
#define LUA_OPADD 0 /* ORDER TM */
#define LUA_OPSUB 1
#define LUA_OPMUL 2
#define LUA_OPDIV 3
#define LUA_OPMOD 4
#define LUA_OPPOW 5
#define LUA_OPUNM 6
LUA_API void (lua_arith) (lua_State *L, int op);
#define LUA_OPEQ 0
#define LUA_OPLT 1
#define LUA_OPLE 2
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op);
/* /*
** push functions (C -> stack) ** push functions (C -> stack)
*/ */
LUA_API void (lua_pushnil) (lua_State *L); LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n);
LUA_API void (lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp); va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
@ -174,35 +215,47 @@ LUA_API int (lua_pushthread) (lua_State *L);
/* /*
** get functions (Lua -> stack) ** get functions (Lua -> stack)
*/ */
LUA_API void (lua_getglobal) (lua_State *L, const char *var);
LUA_API void (lua_gettable) (lua_State *L, int idx); LUA_API void (lua_gettable) (lua_State *L, int idx);
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawget) (lua_State *L, int idx); LUA_API void (lua_rawget) (lua_State *L, int idx);
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p);
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex); LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
LUA_API void (lua_getfenv) (lua_State *L, int idx); LUA_API void (lua_getuservalue) (lua_State *L, int idx);
/* /*
** set functions (stack -> Lua) ** set functions (stack -> Lua)
*/ */
LUA_API void (lua_setglobal) (lua_State *L, const char *var);
LUA_API void (lua_settable) (lua_State *L, int idx); LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawset) (lua_State *L, int idx); LUA_API void (lua_rawset) (lua_State *L, int idx);
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex); LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API int (lua_setfenv) (lua_State *L, int idx); LUA_API void (lua_setuservalue) (lua_State *L, int idx);
/* /*
** `load' and `call' functions (load and run Lua code) ** 'load' and 'call' functions (load and run Lua code)
*/ */
LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); lua_CFunction k);
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
LUA_API int (lua_getctx) (lua_State *L, int *ctx);
LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
int ctx, lua_CFunction k);
#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname); const char *chunkname,
const char *mode);
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
@ -210,8 +263,10 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
/* /*
** coroutine functions ** coroutine functions
*/ */
LUA_API int (lua_yield) (lua_State *L, int nresults); LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx,
LUA_API int (lua_resume) (lua_State *L, int narg); lua_CFunction k);
#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg);
LUA_API int (lua_status) (lua_State *L); LUA_API int (lua_status) (lua_State *L);
/* /*
@ -226,6 +281,10 @@ LUA_API int (lua_status) (lua_State *L);
#define LUA_GCSTEP 5 #define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6 #define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7 #define LUA_GCSETSTEPMUL 7
#define LUA_GCSETMAJORINC 8
#define LUA_GCISRUNNING 9
#define LUA_GCGEN 10
#define LUA_GCINC 11
LUA_API int (lua_gc) (lua_State *L, int what, int data); LUA_API int (lua_gc) (lua_State *L, int what, int data);
@ -239,18 +298,23 @@ LUA_API int (lua_error) (lua_State *L);
LUA_API int (lua_next) (lua_State *L, int idx); LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n); LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API void (lua_len) (lua_State *L, int idx);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
/* /*
** =============================================================== ** ===============================================================
** some useful macros ** some useful macros
** =============================================================== ** ===============================================================
*/ */
#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL)
#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL)
#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL)
#define lua_pop(L,n) lua_settop(L, -(n)-1) #define lua_pop(L,n) lua_settop(L, -(n)-1)
#define lua_newtable(L) lua_createtable(L, 0, 0) #define lua_newtable(L) lua_createtable(L, 0, 0)
@ -259,8 +323,6 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
#define lua_strlen(L,i) lua_objlen(L, (i))
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
@ -273,31 +335,13 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
#define lua_pushliteral(L, s) \ #define lua_pushliteral(L, s) \
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) #define lua_pushglobaltable(L) \
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) #define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
/*
** compatibility macros and functions
*/
#define lua_open() luaL_newstate()
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
#define lua_Chunkreader lua_Reader
#define lua_Chunkwriter lua_Writer
/* hack */
LUA_API void lua_setlevel (lua_State *from, lua_State *to);
/* /*
** {====================================================================== ** {======================================================================
** Debug API ** Debug API
@ -312,7 +356,7 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to);
#define LUA_HOOKRET 1 #define LUA_HOOKRET 1
#define LUA_HOOKLINE 2 #define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3 #define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILRET 4 #define LUA_HOOKTAILCALL 4
/* /*
@ -326,43 +370,50 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to);
typedef struct lua_Debug lua_Debug; /* activation record */ typedef struct lua_Debug lua_Debug; /* activation record */
/* Functions to be called by the debuger in specific events */ /* Functions to be called by the debugger in specific events */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar);
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n);
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n);
LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n);
LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook lua_gethook (lua_State *L); LUA_API lua_Hook (lua_gethook) (lua_State *L);
LUA_API int lua_gethookmask (lua_State *L); LUA_API int (lua_gethookmask) (lua_State *L);
LUA_API int lua_gethookcount (lua_State *L); LUA_API int (lua_gethookcount) (lua_State *L);
struct lua_Debug { struct lua_Debug {
int event; int event;
const char *name; /* (n) */ const char *name; /* (n) */
const char *namewhat; /* (n) `global', `local', `field', `method' */ const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */
const char *what; /* (S) `Lua', `C', `main', `tail' */ const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */
const char *source; /* (S) */ const char *source; /* (S) */
int currentline; /* (l) */ int currentline; /* (l) */
int nups; /* (u) number of upvalues */
int linedefined; /* (S) */ int linedefined; /* (S) */
int lastlinedefined; /* (S) */ int lastlinedefined; /* (S) */
unsigned char nups; /* (u) number of upvalues */
unsigned char nparams;/* (u) number of parameters */
char isvararg; /* (u) */
char istailcall; /* (t) */
char short_src[LUA_IDSIZE]; /* (S) */ char short_src[LUA_IDSIZE]; /* (S) */
/* private part */ /* private part */
int i_ci; /* active function */ struct CallInfo *i_ci; /* active function */
}; };
/* }====================================================================== */ /* }====================================================================== */
/****************************************************************************** /******************************************************************************
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. * Copyright (C) 1994-2011 Lua.org, PUC-Rio. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

@ -1,5 +1,5 @@
/* /*
** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ ** $Id: luaconf.h,v 1.170 2011/12/06 16:58:36 roberto Exp $
** Configuration file for Lua ** Configuration file for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -24,30 +24,44 @@
** CHANGE it (define it) if you want Lua to avoid the use of any ** CHANGE it (define it) if you want Lua to avoid the use of any
** non-ansi feature or library. ** non-ansi feature or library.
*/ */
#if defined(__STRICT_ANSI__) #if !defined(LUA_ANSI) && defined(__STRICT_ANSI__)
#define LUA_ANSI #define LUA_ANSI
#endif #endif
#if !defined(LUA_ANSI) && defined(_WIN32) #if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE)
#define LUA_WIN #define LUA_WIN /* enable goodies for regular Windows platforms */
#endif #endif
#if defined(LUA_WIN)
#define LUA_DL_DLL
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#endif
#if defined(LUA_USE_LINUX) #if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX #define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ #define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */ #define LUA_USE_READLINE /* needs some extra libraries */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#define LUA_USE_LONGLONG /* assume support for long long */
#endif #endif
#if defined(LUA_USE_MACOSX) #if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX #define LUA_USE_POSIX
#define LUA_DL_DYLD /* does not need extra library */ #define LUA_USE_DLOPEN /* does not need -ldl */
#define LUA_USE_READLINE /* needs an extra library: -lreadline */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#define LUA_USE_LONGLONG /* assume support for long long */
#endif #endif
/* /*
@@ LUA_USE_POSIX includes all functionallity listed as X/Open System @@ LUA_USE_POSIX includes all functionality listed as X/Open System
@* Interfaces Extension (XSI). @* Interfaces Extension (XSI).
** CHANGE it (define it) if your system is XSI compatible. ** CHANGE it (define it) if your system is XSI compatible.
*/ */
@ -56,20 +70,10 @@
#define LUA_USE_ISATTY #define LUA_USE_ISATTY
#define LUA_USE_POPEN #define LUA_USE_POPEN
#define LUA_USE_ULONGJMP #define LUA_USE_ULONGJMP
#define LUA_USE_GMTIME_R
#endif #endif
/*
@@ LUA_PATH and LUA_CPATH are the names of the environment variables that
@* Lua check to set its paths.
@@ LUA_INIT is the name of the environment variable that Lua
@* checks for initialization code.
** CHANGE them if you want different names.
*/
#define LUA_PATH "LUA_PATH"
#define LUA_CPATH "LUA_CPATH"
#define LUA_INIT "LUA_INIT"
/* /*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
@ -80,7 +84,7 @@
** hierarchy or if you want to install your libraries in ** hierarchy or if you want to install your libraries in
** non-conventional directories. ** non-conventional directories.
*/ */
#if defined(_WIN32) #if defined(_WIN32) /* { */
/* /*
** In Windows, any exclamation mark ('!') in the path is replaced by the ** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process. ** path of the directory of the executable file of the current process.
@ -88,21 +92,23 @@
#define LUA_LDIR "!\\lua\\" #define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\" #define LUA_CDIR "!\\"
#define LUA_PATH_DEFAULT \ #define LUA_PATH_DEFAULT \
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua"
#define LUA_CPATH_DEFAULT \ #define LUA_CPATH_DEFAULT \
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll"
#else #else /* }{ */
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/"
#define LUA_ROOT "/usr/local/" #define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/5.1/" #define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR
#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" #define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR
#define LUA_PATH_DEFAULT \ #define LUA_PATH_DEFAULT \
"./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua"
#define LUA_CPATH_DEFAULT \ #define LUA_CPATH_DEFAULT \
"./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
#endif #endif /* } */
/* /*
@ -118,88 +124,71 @@
/* /*
@@ LUA_PATHSEP is the character that separates templates in a path. @@ LUA_ENV is the name of the variable that holds the current
@@ LUA_PATH_MARK is the string that marks the substitution points in a @@ environment, used to access global names.
@* template. ** CHANGE it if you do not like this name.
@@ LUA_EXECDIR in a Windows path is replaced by the executable's
@* directory.
@@ LUA_IGMARK is a mark to ignore all before it when bulding the
@* luaopen_ function name.
** CHANGE them if for some reason your system cannot use those
** characters. (E.g., if one of those characters is a common character
** in file/directory names.) Probably you do not need to change them.
*/
#define LUA_PATHSEP ";"
#define LUA_PATH_MARK "?"
#define LUA_EXECDIR "!"
#define LUA_IGMARK "-"
/*
@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
** machines, ptrdiff_t gives a good choice between int or long.)
*/ */
#define LUA_INTEGER ptrdiff_t #define LUA_ENV "_ENV"
/* /*
@@ LUA_API is a mark for all core API functions. @@ LUA_API is a mark for all core API functions.
@@ LUALIB_API is a mark for all standard library functions. @@ LUALIB_API is a mark for all auxiliary library functions.
@@ LUAMOD_API is a mark for all standard library opening functions.
** CHANGE them if you need to define those functions in some special way. ** CHANGE them if you need to define those functions in some special way.
** For instance, if you want to create one Windows DLL with the core and ** For instance, if you want to create one Windows DLL with the core and
** the libraries, you may want to use the following definition (define ** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it). ** LUA_BUILD_AS_DLL to get it).
*/ */
#ifdef __cplusplus #if defined(LUA_BUILD_AS_DLL) /* { */
#define LUA_API_EXTERN extern
#else #if defined(_MSC_VER)
#define LUA_API_EXTERN extern #if defined(LUA_CORE) || defined(LUA_LIB) /* { */
#endif #define LUA_API __declspec(dllexport)
#if defined(LUA_BUILD_AS_DLL) #else /* }{ */
#if defined(_MSC_VER) #define LUA_API __declspec(dllimport)
#if defined(LUA_CORE) || defined(LUA_LIB) #endif /* } */
#define LUA_API LUA_API_EXTERN __declspec(dllexport)
#else
#define LUA_API LUA_API_EXTERN __declspec(dllimport)
#endif
#else
#define LUA_API LUA_API_EXTERN __attribute__ ((visibility("default")))
#endif
#else #else
#ifdef __cplusplus #define LUA_API __attribute__ ((visibility("default")))
#define LUA_API extern "C"
#else
#define LUA_API extern
#endif
#endif #endif
#else /* }{ */
#define LUA_API extern
#endif /* } */
/* more often than not the libs go together with the core */ /* more often than not the libs go together with the core */
#define LUALIB_API LUA_API #define LUALIB_API LUA_API
#define LUAMOD_API LUALIB_API
/* /*
@@ LUAI_FUNC is a mark for all extern functions that are not to be @@ LUAI_FUNC is a mark for all extern functions that are not to be
@* exported to outside modules. @* exported to outside modules.
@@ LUAI_DATA is a mark for all extern (const) variables that are not to @@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables
@* be exported to outside modules. @* that are not to be exported to outside modules (LUAI_DDEF for
@* definitions and LUAI_DDEC for declarations).
** CHANGE them if you need to mark them in some special way. Elf/gcc ** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access ** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library. ** when Lua is compiled as a shared library. Not all elf targets support
*/ ** this attribute. Unfortunately, gcc does not offer a way to check
#if defined(luaall_c) ** whether the target offers that support, and those without support
#define LUAI_FUNC static ** give a warning about it. To avoid these warnings, change to the
#define LUAI_DATA /* empty */ ** default definition.
*/
#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) defined(__ELF__) /* { */
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern #define LUAI_FUNC __attribute__((visibility("hidden"))) extern
#define LUAI_DATA LUAI_FUNC #define LUAI_DDEC LUAI_FUNC
#define LUAI_DDEF /* empty */
#else #else /* }{ */
#define LUAI_FUNC extern #define LUAI_FUNC extern
#define LUAI_DATA extern #define LUAI_DDEC extern
#endif #define LUAI_DDEF /* empty */
#endif /* } */
@ -220,175 +209,101 @@
/* /*
** {================================================================== @@ luai_writestring/luai_writeline define how 'print' prints its results.
** Stand-alone configuration ** They are only used in libraries and the stand-alone program. (The #if
** =================================================================== ** avoids including 'stdio.h' everywhere.)
*/
#if defined(lua_c) || defined(luaall_c)
/*
@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
@* is, whether we're running lua interactively).
** CHANGE it if you have a better definition for non-POSIX/non-Windows
** systems.
*/ */
#if defined(LUA_USE_ISATTY) #if defined(LUA_LIB) || defined(lua_c)
#include <unistd.h>
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#include <stdio.h> #include <stdio.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin)) #define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
#else #define luai_writeline() (luai_writestring("\n", 1), fflush(stdout))
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
#endif #endif
/* /*
@@ LUA_PROMPT is the default prompt used by stand-alone Lua. @@ luai_writestringerror defines how to print error messages.
@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. ** (A format string with one argument is enough for Lua...)
** CHANGE them if you want different prompts. (You can also change the
** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
*/ */
#define LUA_PROMPT "> " #define luai_writestringerror(s,p) \
#define LUA_PROMPT2 ">> " (fprintf(stderr, (s), (p)), fflush(stderr))
/*
@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
** CHANGE it if your stand-alone interpreter has a different name and
** your system is not able to detect that name automatically.
*/
#define LUA_PROGNAME "lua"
/*
@@ LUA_MAXINPUT is the maximum length for an input line in the
@* stand-alone interpreter.
** CHANGE it if you need longer lines.
*/
#define LUA_MAXINPUT 512
/* /*
@@ lua_readline defines how to show a prompt and then read a line from ** {==================================================================
@* the standard input. ** Compatibility with previous versions
@@ lua_saveline defines how to "save" a read line in a "history". ** ===================================================================
@@ lua_freeline defines how to free a line read by lua_readline.
** CHANGE them if you want to improve this functionality (e.g., by using
** GNU readline and history facilities).
*/ */
#if defined(LUA_USE_READLINE)
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */
#define lua_freeline(L,b) ((void)L, free(b))
#else
#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif
#endif
/* }================================================================== */
/* /*
@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles @@ LUA_COMPAT_ALL controls all compatibility options.
@* as a percentage. ** You can define it to get all options, or change specific options
** CHANGE it if you want the GC to run faster or slower (higher values ** to fit your specific needs.
** mean larger pauses which mean slower collection.) You can also change
** this value dynamically.
*/ */
#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ #if defined(LUA_COMPAT_ALL) /* { */
/* /*
@@ LUAI_GCMUL defines the default speed of garbage collection relative to @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
@* memory allocation as a percentage. ** You can replace it with 'table.unpack'.
** CHANGE it if you want to change the granularity of the garbage
** collection. (Higher values mean coarser collections. 0 represents
** infinity, where each step performs a full collection.) You can also
** change this value dynamically.
*/ */
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ #define LUA_COMPAT_UNPACK
/* /*
@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. @@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'.
** CHANGE it (define it) if you want exact compatibility with the ** You can replace it with 'package.searchers'.
** behavior of setn/getn in Lua 5.0.
*/ */
#undef LUA_COMPAT_GETN #define LUA_COMPAT_LOADERS
/* /*
@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. @@ macro 'lua_cpcall' emulates deprecated function lua_cpcall.
** CHANGE it to undefined as soon as you do not need a global 'loadlib' ** You can call your C function directly (with light C functions).
** function (the function is still available as 'package.loadlib').
*/ */
#undef LUA_COMPAT_LOADLIB #define lua_cpcall(L,f,u) \
(lua_pushcfunction(L, (f)), \
lua_pushlightuserdata(L,(u)), \
lua_pcall(L,1,0,0))
/*
@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.
** CHANGE it to undefined as soon as your programs use only '...' to
** access vararg parameters (instead of the old 'arg' table).
*/
#define LUA_COMPAT_VARARG
/* /*
@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. @@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library.
** CHANGE it to undefined as soon as your programs use 'math.fmod' or ** You can rewrite 'log10(x)' as 'log(x, 10)'.
** the new '%' operator instead of 'math.mod'.
*/ */
#define LUA_COMPAT_MOD #define LUA_COMPAT_LOG10
/* /*
@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting @@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base
@* facility. ** library. You can rewrite 'loadstring(s)' as 'load(s)'.
** CHANGE it to 2 if you want the old behaviour, or undefine it to turn
** off the advisory error when nesting [[...]].
*/ */
#define LUA_COMPAT_LSTR 1 #define LUA_COMPAT_LOADSTRING
/* /*
@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. @@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library.
** CHANGE it to undefined as soon as you rename 'string.gfind' to
** 'string.gmatch'.
*/ */
#define LUA_COMPAT_GFIND #define LUA_COMPAT_MAXN
/* /*
@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' @@ The following macros supply trivial compatibility for some
@* behavior. ** changes in the API. The macros themselves document how to
** CHANGE it to undefined as soon as you replace to 'luaL_register' ** change your code to avoid using them.
** your uses of 'luaL_openlib'
*/ */
#define LUA_COMPAT_OPENLIB #define lua_strlen(L,i) lua_rawlen(L, (i))
#define lua_objlen(L,i) lua_rawlen(L, (i))
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
/* /*
@@ luai_apicheck is the assert macro used by the Lua-C API. @@ LUA_COMPAT_MODULE controls compatibility with previous
** CHANGE luai_apicheck if you want Lua to perform some checks in the ** module functions 'module' (Lua) and 'luaL_register' (C).
** parameters it gets from API calls. This may slow down the interpreter
** a bit, but may be quite useful when debugging C code that interfaces
** with Lua. A useful redefinition is to use assert.h.
*/ */
#if defined(LUA_USE_APICHECK) #define LUA_COMPAT_MODULE
#include <assert.h>
#define luai_apicheck(L,o) { (void)L; assert(o); } #endif /* } */
#else
#define luai_apicheck(L,o) { (void)L; } /* }================================================================== */
#endif
/* /*
@ -397,107 +312,62 @@
** your machine. Probably you do not need to change this. ** your machine. Probably you do not need to change this.
*/ */
/* avoid overflows in comparison */ /* avoid overflows in comparison */
#if INT_MAX-20 < 32760 #if INT_MAX-20 < 32760 /* { */
#define LUAI_BITSINT 16 #define LUAI_BITSINT 16
#elif INT_MAX > 2147483640L #elif INT_MAX > 2147483640L /* }{ */
/* int has at least 32 bits */ /* int has at least 32 bits */
#define LUAI_BITSINT 32 #define LUAI_BITSINT 32
#else #else /* }{ */
#error "you must define LUA_BITSINT with number of bits in an integer" #error "you must define LUA_BITSINT with number of bits in an integer"
#endif #endif /* } */
/* /*
@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. @@ LUA_INT32 is an signed integer with exactly 32 bits.
@@ LUAI_INT32 is an signed integer with at least 32 bits.
@@ LUAI_UMEM is an unsigned integer big enough to count the total @@ LUAI_UMEM is an unsigned integer big enough to count the total
@* memory used by Lua. @* memory used by Lua.
@@ LUAI_MEM is a signed integer big enough to count the total memory @@ LUAI_MEM is a signed integer big enough to count the total memory
@* used by Lua. @* used by Lua.
** CHANGE here if for some weird reason the default definitions are not ** CHANGE here if for some weird reason the default definitions are not
** good enough for your machine. (The definitions in the 'else' ** good enough for your machine. Probably you do not need to change
** part always works, but may waste space on machines with 64-bit ** this.
** longs.) Probably you do not need to change this.
*/ */
#if LUAI_BITSINT >= 32 #if LUAI_BITSINT >= 32 /* { */
#define LUAI_UINT32 unsigned int #define LUA_INT32 int
#define LUAI_INT32 int
#define LUAI_MAXINT32 INT_MAX
#define LUAI_UMEM size_t #define LUAI_UMEM size_t
#define LUAI_MEM ptrdiff_t #define LUAI_MEM ptrdiff_t
#else #else /* }{ */
/* 16-bit ints */ /* 16-bit ints */
#define LUAI_UINT32 unsigned long #define LUA_INT32 long
#define LUAI_INT32 long
#define LUAI_MAXINT32 LONG_MAX
#define LUAI_UMEM unsigned long #define LUAI_UMEM unsigned long
#define LUAI_MEM long #define LUAI_MEM long
#endif #endif /* } */
/* /*
@@ LUAI_MAXCALLS limits the number of nested calls. @@ LUAI_MAXSTACK limits the size of the Lua stack.
** CHANGE it if you need really deep recursive calls. This limit is ** CHANGE it if you need a different limit. This limit is arbitrary;
** arbitrary; its only purpose is to stop infinite recursion before ** its only purpose is to stop Lua to consume unlimited stack
** exhausting memory. ** space (and to reserve some numbers for pseudo-indices).
*/
#define LUAI_MAXCALLS 20000
/*
@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
@* can use.
** CHANGE it if you need lots of (Lua) stack space for your C
** functions. This limit is arbitrary; its only purpose is to stop C
** functions to consume unlimited stack space. (must be smaller than
** -LUA_REGISTRYINDEX)
*/
#define LUAI_MAXCSTACK 8000
/*
** {==================================================================
** CHANGE (to smaller values) the following definitions if your system
** has a small C stack. (Or you may want to change them to larger
** values if your system has a large C stack and these limits are
** too rigid for you.) Some of these constants control the size of
** stack-allocated arrays used by the compiler or the interpreter, while
** others limit the maximum number of recursive calls that the compiler
** or the interpreter can perform. Values too large may cause a C stack
** overflow for some forms of deep constructs.
** ===================================================================
*/ */
#if LUAI_BITSINT >= 32
#define LUAI_MAXSTACK 1000000
#else
#define LUAI_MAXSTACK 15000
#endif
/* reserve some space for error handling */
#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
/*
@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and
@* syntactical nested non-terminals in a program.
*/
#define LUAI_MAXCCALLS 200
/*
@@ LUAI_MAXVARS is the maximum number of local variables per function
@* (must be smaller than 250).
*/
#define LUAI_MAXVARS 200
/*
@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
@* (must be smaller than 250).
*/
#define LUAI_MAXUPVALUES 60
/* /*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
** CHANGE it if it uses too much C-stack space.
*/ */
#define LUAL_BUFFERSIZE BUFSIZ #define LUAL_BUFFERSIZE BUFSIZ
/* }================================================================== */
@ -525,241 +395,128 @@
@@ LUA_NUMBER_FMT is the format for writing numbers. @@ LUA_NUMBER_FMT is the format for writing numbers.
@@ lua_number2str converts a number to a string. @@ lua_number2str converts a number to a string.
@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
@@ lua_str2number converts a string to a number.
*/ */
#define LUA_NUMBER_SCAN "%lf" #define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g" #define LUA_NUMBER_FMT "%.14g"
#ifdef WIN32 //More specifically MSVC, but did not work, either way only MSVC is used in windows build
#define lua_number2str(s,n) sprintf_s((s),32, LUA_NUMBER_FMT, (n))
#else
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#endif
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
#define lua_str2number(s,p) strtod((s), (p))
/* /*
@@ The luai_num* macros define the primitive operations over numbers. @@ lua_str2number converts a decimal numeric string to a number.
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' do both conversions. C89, however, has no function
** to convert floating hexadecimal strings to numbers. For these
** systems, you can leave 'lua_strx2number' undefined and Lua will
** provide its own implementation.
*/ */
#if defined(LUA_CORE) #define lua_str2number(s,p) strtod((s), (p))
#include <math.h>
#define luai_numadd(a,b) ((a)+(b)) #if defined(LUA_USE_STRTODHEX)
#define luai_numsub(a,b) ((a)-(b)) #define lua_strx2number(s,p) strtod((s), (p))
#define luai_nummul(a,b) ((a)*(b))
#define luai_numdiv(a,b) ((a)/(b))
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
#define luai_numpow(a,b) (pow(a,b))
#define luai_numunm(a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif #endif
/* /*
@@ lua_number2int is a macro to convert lua_Number to int. @@ The luai_num* macros define the primitive operations over numbers.
@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
** CHANGE them if you know a faster way to convert a lua_Number to
** int (with any rounding method and without throwing errors) in your
** system. In Pentium machines, a naive typecast from double to int
** in C is extremely slow, so any alternative is worth trying.
*/ */
/* On a Pentium, resort to a trick */ /* the following operations need the math library */
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ #if defined(lobject_c) || defined(lvm_c)
(defined(__i386) || defined (_M_IX86) || defined(__i386__)) #include <math.h>
#define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b))
/* On a Microsoft compiler, use assembler */ #define luai_numpow(L,a,b) (pow(a,b))
#if defined(_MSC_VER)
#define lua_number2int(i,d) __asm fld d __asm fistp i
#define lua_number2integer(i,n) lua_number2int(i, n)
/* the next trick should work on any Pentium, but sometimes clashes
with a DirectX idiosyncrasy */
#else
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) \
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n) lua_number2int(i, n)
#endif #endif
/* these are quite standard operations */
/* this option always works, but may be slow */ #if defined(LUA_CORE)
#else #define luai_numadd(L,a,b) ((a)+(b))
#define lua_number2int(i,d) ((i)=(int)(d)) #define luai_numsub(L,a,b) ((a)-(b))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) #define luai_nummul(L,a,b) ((a)*(b))
#define luai_numdiv(L,a,b) ((a)/(b))
#define luai_numunm(L,a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(L,a,b) ((a)<(b))
#define luai_numle(L,a,b) ((a)<=(b))
#define luai_numisnan(L,a) (!luai_numeq((a), (a)))
#endif #endif
/* }================================================================== */
/* /*
@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
** CHANGE it if your system requires alignments larger than double. (For ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
** instance, if your system supports long doubles and they must be ** machines, ptrdiff_t gives a good choice between int or long.)
** aligned in 16-byte boundaries, then you should add long double in the
** union.) Probably you do not need to change this.
*/ */
#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } #define LUA_INTEGER ptrdiff_t
/* /*
@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. @@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned.
** CHANGE them if you prefer to use longjmp/setjmp even with C++ ** It must have at least 32 bits.
** or if want/don't to use _longjmp/_setjmp instead of regular
** longjmp/setjmp. By default, Lua handles errors with exceptions when
** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
** and with longjmp/setjmp otherwise.
*/ */
#if defined(__cplusplus) #define LUA_UNSIGNED unsigned LUA_INT32
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
#define LUAI_TRY(L,c,a) try { a } catch(...) \
{ if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int /* dummy variable */
#elif defined(LUA_USE_ULONGJMP)
/* in Unix, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#else
/* default handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#endif
/*
@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern
@* can do during pattern-matching.
** CHANGE it if you need more captures. This limit is arbitrary.
*/
#define LUA_MAXCAPTURES 32
#if defined(LUA_CORE) /* { */
/* #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
@@ lua_tmpnam is the function that the OS library uses to create a
@* temporary name.
@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.
** CHANGE them if you have an alternative to tmpnam (which is considered
** insecure) or if you want the original tmpnam anyway. By default, Lua
** uses tmpnam except when POSIX is available, where it uses mkstemp.
*/
#if defined(loslib_c) || defined(luaall_c)
#if defined(LUA_USE_MKSTEMP) /* On a Microsoft compiler on a Pentium, use assembler to avoid clashes
#include <unistd.h> with a DirectX idiosyncrasy */
#define LUA_TMPNAMBUFSIZE 32 #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
#define lua_tmpnam(b,e) { \
strcpy(b, "/tmp/lua_XXXXXX"); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
#else #define MS_ASMTRICK
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif
#endif #else /* }{ */
/* the next definition uses a trick that should work on any machine
using IEEE754 with a 32-bit integer type */
#define LUA_IEEE754TRICK
/* /*
@@ lua_popen spawns a new process connected to the current one through @@ LUA_IEEEENDIAN is the endianness of doubles in your machine
@* the file streams. ** (0 for little endian, 1 for big endian); if not defined, Lua will
** CHANGE it if you have a way to implement it in your system. ** check it dynamically.
*/ */
#if defined(LUA_USE_POPEN) /* check for known architectures */
#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) defined (__x86_64)
#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) #define LUA_IEEEENDIAN 0
#elif defined(__POWERPC__) || defined(__ppc__)
#elif defined(LUA_WIN) #define LUA_IEEEENDIAN 1
#define lua_popen(L,c,m) ((void)L, _popen(c,m))
#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
#else
#define lua_popen(L,c,m) ((void)((void)c, m), \
luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
#define lua_pclose(L,file) ((void)((void)L, file), 0)
#endif
/*
@@ LUA_DL_* define which dynamic-library system Lua should use.
** CHANGE here if Lua has problems choosing the appropriate
** dynamic-library system for your platform (either Windows' DLL, Mac's
** dyld, or Unix's dlopen). If your system is some kind of Unix, there
** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for
** it. To use dlopen you also need to adapt the src/Makefile (probably
** adding -ldl to the linker options), so Lua does not select it
** automatically. (When you change the makefile to add -ldl, you must
** also add -DLUA_USE_DLOPEN.)
** If you do not want any kind of dynamic library, undefine all these
** options.
** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
*/
#if defined(LUA_USE_DLOPEN)
#define LUA_DL_DLOPEN
#endif
#if defined(LUA_WIN)
#define LUA_DL_DLL
#endif #endif
#endif /* } */
/* #endif /* } */
@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
@* (the data goes just *before* the lua_State pointer).
** CHANGE (define) this if you really need that. This value must be
** a multiple of the maximum alignment required for your machine.
*/
#define LUAI_EXTRASPACE 0
#endif /* } */
/* /* }================================================================== */
@@ luai_userstate* allow user-specific actions on threads.
** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
** extra when a thread is created/deleted/resumed/yielded.
*/
#define luai_userstateopen(L) ((void)L)
#define luai_userstateclose(L) ((void)L)
#define luai_userstatethread(L,L1) ((void)L)
#define luai_userstatefree(L) ((void)L)
#define luai_userstateresume(L,n) ((void)L)
#define luai_userstateyield(L,n) ((void)L)
/* /*
@@ LUA_INTFRMLEN is the length modifier for integer conversions @@ LUA_NANTRICK_LE/LUA_NANTRICK_BE controls the use of a trick to
@* in 'string.format'. ** pack all types into a single double value, using NaN values to
@@ LUA_INTFRM_T is the integer type correspoding to the previous length ** represent non-number values. The trick only works on 32-bit machines
@* modifier. ** (ints and pointers are 32-bit values) with numbers represented as
** CHANGE them if your system supports long long or does not support long. ** IEEE 754-2008 doubles with conventional endianess (12345678 or
** 87654321), in CPUs that do not produce signaling NaN values (all NaNs
** are quiet).
*/ */
#if defined(LUA_CORE) && \
defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
#if defined(LUA_USELONGLONG) /* little-endian architectures that satisfy those conditions */
#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
defined(_M_IX86)
#define LUA_INTFRMLEN "ll" #define LUA_NANTRICK_LE
#define LUA_INTFRM_T long long
#else #endif
#define LUA_INTFRMLEN "l" #endif /* } */
#define LUA_INTFRM_T long
#endif

@ -1,5 +1,5 @@
/* /*
** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $
** Lua standard libraries ** Lua standard libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -11,41 +11,43 @@
#include "lua.h" #include "lua.h"
/* Key to file-handle type */
#define LUA_FILEHANDLE "FILE*"
LUAMOD_API int (luaopen_base) (lua_State *L);
#define LUA_COLIBNAME "coroutine" #define LUA_COLIBNAME "coroutine"
LUALIB_API int (luaopen_base) (lua_State *L); LUAMOD_API int (luaopen_coroutine) (lua_State *L);
#define LUA_TABLIBNAME "table" #define LUA_TABLIBNAME "table"
LUALIB_API int (luaopen_table) (lua_State *L); LUAMOD_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io" #define LUA_IOLIBNAME "io"
LUALIB_API int (luaopen_io) (lua_State *L); LUAMOD_API int (luaopen_io) (lua_State *L);
#define LUA_OSLIBNAME "os" #define LUA_OSLIBNAME "os"
LUALIB_API int (luaopen_os) (lua_State *L); LUAMOD_API int (luaopen_os) (lua_State *L);
#define LUA_STRLIBNAME "string" #define LUA_STRLIBNAME "string"
LUALIB_API int (luaopen_string) (lua_State *L); LUAMOD_API int (luaopen_string) (lua_State *L);
#define LUA_BITLIBNAME "bit32"
LUAMOD_API int (luaopen_bit32) (lua_State *L);
#define LUA_MATHLIBNAME "math" #define LUA_MATHLIBNAME "math"
LUALIB_API int (luaopen_math) (lua_State *L); LUAMOD_API int (luaopen_math) (lua_State *L);
#define LUA_DBLIBNAME "debug" #define LUA_DBLIBNAME "debug"
LUALIB_API int (luaopen_debug) (lua_State *L); LUAMOD_API int (luaopen_debug) (lua_State *L);
#define LUA_LOADLIBNAME "package" #define LUA_LOADLIBNAME "package"
LUALIB_API int (luaopen_package) (lua_State *L); LUAMOD_API int (luaopen_package) (lua_State *L);
/* open all previous libraries */ /* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L); LUALIB_API void (luaL_openlibs) (lua_State *L);
#ifndef lua_assert #if !defined(lua_assert)
#define lua_assert(x) ((void)0) #define lua_assert(x) ((void)0)
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lundump.h,v 1.44 2011/05/06 13:35:17 lhf Exp $
** load precompiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -14,23 +14,15 @@
LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
/* make header; from lundump.c */ /* make header; from lundump.c */
LUAI_FUNC void luaU_header (char* h); LUAI_FUNC void luaU_header (lu_byte* h);
/* dump one chunk; from ldump.c */ /* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
#ifdef luac_c /* data to catch conversion errors */
/* print one chunk; from print.c */ #define LUAC_TAIL "\x19\x93\r\n\x1a\n"
LUAI_FUNC void luaU_print (const Proto* f, int full);
#endif
/* for header of binary files -- this is Lua 5.1 */
#define LUAC_VERSION 0x51
/* for header of binary files -- this is the official format */
#define LUAC_FORMAT 0
/* size of header of binary files */ /* size in bytes of header of binary files */
#define LUAC_HEADERSIZE 12 #define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char))
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,24 +13,33 @@
#include "ltm.h" #include "ltm.h"
#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ #define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
(((o) = luaV_tonumber(o,n)) != NULL))
#define equalobj(L,o1,o2) \ #define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2))
(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
#define luaV_rawequalobj(t1,t2) \
(ttisequal(t1,t2) && luaV_equalobj_(NULL,t1,t2))
/* not to called directly */
LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2);
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val); StkId val);
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
StkId val); StkId val);
LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total);
LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
const TValue *rc, TMS op);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $
** Buffered streams ** Buffered streams
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -17,9 +17,8 @@
typedef struct Zio ZIO; typedef struct Zio ZIO;
#define char2int(c) cast(int, cast(unsigned char, (c))) #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z))
#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
typedef struct Mbuffer { typedef struct Mbuffer {
char *buffer; char *buffer;
@ -47,7 +46,6 @@ LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data); void *data);
LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
LUAI_FUNC int luaZ_lookahead (ZIO *z);
@ -56,7 +54,7 @@ LUAI_FUNC int luaZ_lookahead (ZIO *z);
struct Zio { struct Zio {
size_t n; /* bytes still unread */ size_t n; /* bytes still unread */
const char *p; /* current position in buffer */ const char *p; /* current position in buffer */
lua_Reader reader; lua_Reader reader; /* reader function */
void* data; /* additional data */ void* data; /* additional data */
lua_State *L; /* Lua state (for reader) */ lua_State *L; /* Lua state (for reader) */
}; };

@ -1,181 +0,0 @@
/*
** Lua BitOp -- a bit operations library for Lua 5.1.
** http://bitop.luajit.org/
**
** Copyright (C) 2008-2009 Mike Pall. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
*/
#include "bit.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
typedef int32_t SBits;
typedef uint32_t UBits;
typedef union {
lua_Number n;
#ifdef LUA_NUMBER_DOUBLE
uint64_t b;
#else
UBits b;
#endif
} BitNum;
/* Convert argument to bit type. */
static UBits barg(lua_State *L, int idx)
{
BitNum bn;
UBits b;
bn.n = lua_tonumber(L, idx);
#if defined(LUA_NUMBER_DOUBLE)
bn.n += 6755399441055744.0; /* 2^52+2^51 */
#ifdef SWAPPED_DOUBLE
b = (UBits)(bn.b >> 32);
#else
b = (UBits)bn.b;
#endif
#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \
defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \
defined(LUA_NUMBER_LLONG)
if (sizeof(UBits) == sizeof(lua_Number))
b = bn.b;
else
b = (UBits)(SBits)bn.n;
#elif defined(LUA_NUMBER_FLOAT)
#error "A 'float' lua_Number type is incompatible with this library"
#else
#error "Unknown number type, check LUA_NUMBER_* in luaconf.h"
#endif
if (b == 0 && !lua_isnumber(L, idx))
luaL_typerror(L, idx, "number");
return b;
}
/* Return bit type. */
#define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1;
static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) }
static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }
#define BIT_OP(func, opr) \
static int func(lua_State *L) { int i; UBits b = barg(L, 1); \
for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) }
BIT_OP(bit_band, &=)
BIT_OP(bit_bor, |=)
BIT_OP(bit_bxor, ^=)
#define bshl(b, n) (b << n)
#define bshr(b, n) (b >> n)
#define bsar(b, n) ((SBits)b >> n)
#define brol(b, n) ((b << n) | (b >> (32-n)))
#define bror(b, n) ((b << (32-n)) | (b >> n))
#define BIT_SH(func, fn) \
static int func(lua_State *L) { \
UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) }
BIT_SH(bit_lshift, bshl)
BIT_SH(bit_rshift, bshr)
BIT_SH(bit_arshift, bsar)
BIT_SH(bit_rol, brol)
BIT_SH(bit_ror, bror)
static int bit_bswap(lua_State *L)
{
UBits b = barg(L, 1);
b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24);
BRET(b)
}
static int bit_tohex(lua_State *L)
{
UBits b = barg(L, 1);
SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2);
const char *hexdigits = "0123456789abcdef";
char buf[8];
int i;
if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
if (n > 8) n = 8;
for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }
lua_pushlstring(L, buf, (size_t)n);
return 1;
}
static const struct luaL_Reg bit_funcs[] = {
{ "tobit", bit_tobit },
{ "bnot", bit_bnot },
{ "band", bit_band },
{ "bor", bit_bor },
{ "bxor", bit_bxor },
{ "lshift", bit_lshift },
{ "rshift", bit_rshift },
{ "arshift", bit_arshift },
{ "rol", bit_rol },
{ "ror", bit_ror },
{ "bswap", bit_bswap },
{ "tohex", bit_tohex },
{ NULL, NULL }
};
/* Signed right-shifts are implementation-defined per C89/C99.
** But the de facto standard are arithmetic right-shifts on two's
** complement CPUs. This behaviour is required here, so test for it.
*/
#define BAD_SAR (bsar(-8, 2) != (SBits)-2)
LUALIB_API int luaopen_bit(lua_State *L)
{
UBits b;
lua_pushnumber(L, (lua_Number)1437217655L);
b = barg(L, -1);
if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */
const char *msg = "compiled with incompatible luaconf.h";
#ifdef LUA_NUMBER_DOUBLE
#ifdef _WIN32
if (b == (UBits)1610612736L)
msg = "use D3DCREATE_FPU_PRESERVE with DirectX";
#endif
if (b == (UBits)1127743488L)
msg = "not compiled with SWAPPED_DOUBLE";
#endif
if (BAD_SAR)
msg = "arithmetic right-shift broken";
luaL_error(L, "bit library self-test failed (%s)", msg);
}
luaL_register(L, "bit", bit_funcs);
return 1;
}
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/* /*
** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ ** $Id: lbaselib.c,v 1.273 2011/11/30 13:03:24 roberto Exp $
** Basic library ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -20,60 +20,68 @@
#include "lualib.h" #include "lualib.h"
/*
** If your system does not support `stdout', you can just remove this function.
** If you need, you can define your own `print' function, following this
** model but changing `fputs' to put the strings at a proper place
** (a console window or a log file, for instance).
*/
static int luaB_print (lua_State *L) { static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */ int n = lua_gettop(L); /* number of arguments */
int i; int i;
lua_getglobal(L, "tostring"); lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) { for (i=1; i<=n; i++) {
const char *s; const char *s;
size_t l;
lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */ lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1); lua_call(L, 1, 1);
s = lua_tostring(L, -1); /* get result */ s = lua_tolstring(L, -1, &l); /* get result */
if (s == NULL) if (s == NULL)
return luaL_error(L, LUA_QL("tostring") " must return a string to " return luaL_error(L,
LUA_QL("print")); LUA_QL("tostring") " must return a string to " LUA_QL("print"));
if (i>1) fputs("\t", stdout); if (i>1) luai_writestring("\t", 1);
fputs(s, stdout); luai_writestring(s, l);
lua_pop(L, 1); /* pop result */ lua_pop(L, 1); /* pop result */
} }
fputs("\n", stdout); luai_writeline();
return 0; return 0;
} }
#define SPACECHARS " \f\n\r\t\v"
static int luaB_tonumber (lua_State *L) { static int luaB_tonumber (lua_State *L) {
int base = luaL_optint(L, 2, 10); if (lua_isnoneornil(L, 2)) { /* standard conversion */
if (base == 10) { /* standard conversion */ int isnum;
luaL_checkany(L, 1); lua_Number n = lua_tonumberx(L, 1, &isnum);
if (lua_isnumber(L, 1)) { if (isnum) {
lua_pushnumber(L, lua_tonumber(L, 1)); lua_pushnumber(L, n);
return 1; return 1;
} } /* else not a number; must be something */
luaL_checkany(L, 1);
} }
else { else {
const char *s1 = luaL_checkstring(L, 1); size_t l;
char *s2; const char *s = luaL_checklstring(L, 1, &l);
unsigned long n; const char *e = s + l; /* end point for 's' */
int base = luaL_checkint(L, 2);
int neg = 0;
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
n = strtoul(s1, &s2, base); s += strspn(s, SPACECHARS); /* skip initial spaces */
if (s1 != s2) { /* at least one valid digit? */ if (*s == '-') { s++; neg = 1; } /* handle signal */
while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ else if (*s == '+') s++;
if (*s2 == '\0') { /* no invalid trailing characters? */ if (isalnum((unsigned char)*s)) {
lua_pushnumber(L, (lua_Number)n); lua_Number n = 0;
do {
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
: toupper((unsigned char)*s) - 'A' + 10;
if (digit >= base) break; /* invalid numeral; force a fail */
n = n * (lua_Number)base + (lua_Number)digit;
s++;
} while (isalnum((unsigned char)*s));
s += strspn(s, SPACECHARS); /* skip trailing spaces */
if (s == e) { /* no invalid trailing characters? */
lua_pushnumber(L, (neg) ? -n : n);
return 1; return 1;
} } /* else not a number */
} } /* else not a number */
} }
lua_pushnil(L); /* else not a number */ lua_pushnil(L); /* not a number */
return 1; return 1;
} }
@ -107,57 +115,13 @@ static int luaB_setmetatable (lua_State *L) {
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected"); "nil or table expected");
if (luaL_getmetafield(L, 1, "__metatable")) if (luaL_getmetafield(L, 1, "__metatable"))
luaL_error(L, "cannot change a protected metatable"); return luaL_error(L, "cannot change a protected metatable");
lua_settop(L, 2); lua_settop(L, 2);
lua_setmetatable(L, 1); lua_setmetatable(L, 1);
return 1; return 1;
} }
static void getfunc (lua_State *L, int opt) {
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
else {
lua_Debug ar;
int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
if (lua_getstack(L, level, &ar) == 0)
luaL_argerror(L, 1, "invalid level");
lua_getinfo(L, "f", &ar);
if (lua_isnil(L, -1))
luaL_error(L, "no function environment for tail call at level %d",
level);
}
}
static int luaB_getfenv (lua_State *L) {
getfunc(L, 1);
if (lua_iscfunction(L, -1)) /* is a C function? */
lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
else
lua_getfenv(L, -1);
return 1;
}
static int luaB_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
getfunc(L, 0);
lua_pushvalue(L, 2);
if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
/* change environment of current thread */
lua_pushthread(L);
lua_insert(L, -2);
lua_setfenv(L, -2);
return 0;
}
else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
luaL_error(L,
LUA_QL("setfenv") " cannot change environment of given object");
return 1;
}
static int luaB_rawequal (lua_State *L) { static int luaB_rawequal (lua_State *L) {
luaL_checkany(L, 1); luaL_checkany(L, 1);
luaL_checkany(L, 2); luaL_checkany(L, 2);
@ -166,6 +130,15 @@ static int luaB_rawequal (lua_State *L) {
} }
static int luaB_rawlen (lua_State *L) {
int t = lua_type(L, 1);
luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
"table or string expected");
lua_pushinteger(L, lua_rawlen(L, 1));
return 1;
}
static int luaB_rawget (lua_State *L) { static int luaB_rawget (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2); luaL_checkany(L, 2);
@ -184,32 +157,29 @@ static int luaB_rawset (lua_State *L) {
} }
static int luaB_gcinfo (lua_State *L) {
lua_pushinteger(L, lua_getgccount(L));
return 1;
}
static int luaB_collectgarbage (lua_State *L) { static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect", static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul", NULL}; "count", "step", "setpause", "setstepmul",
"setmajorinc", "isrunning", "generational", "incremental", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
int o = luaL_checkoption(L, 1, "collect", opts); LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
int ex = luaL_optint(L, 2, 0); int ex = luaL_optint(L, 2, 0);
int res = lua_gc(L, optsnum[o], ex); int res = lua_gc(L, o, ex);
switch (optsnum[o]) { switch (o) {
case LUA_GCCOUNT: { case LUA_GCCOUNT: {
int b = lua_gc(L, LUA_GCCOUNTB, 0); int b = lua_gc(L, LUA_GCCOUNTB, 0);
lua_pushnumber(L, res + ((lua_Number)b/1024)); lua_pushnumber(L, res + ((lua_Number)b/1024));
return 1; lua_pushinteger(L, b);
return 2;
} }
case LUA_GCSTEP: { case LUA_GCSTEP: case LUA_GCISRUNNING: {
lua_pushboolean(L, res); lua_pushboolean(L, res);
return 1; return 1;
} }
default: { default: {
lua_pushnumber(L, res); lua_pushinteger(L, res);
return 1; return 1;
} }
} }
@ -223,6 +193,23 @@ static int luaB_type (lua_State *L) {
} }
static int pairsmeta (lua_State *L, const char *method, int iszero,
lua_CFunction iter) {
if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */
luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */
lua_pushcfunction(L, iter); /* will return generator, */
lua_pushvalue(L, 1); /* state, */
if (iszero) lua_pushinteger(L, 0); /* and initial value */
else lua_pushnil(L);
}
else {
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
lua_call(L, 1, 3); /* get 3 values from metamethod */
}
return 3;
}
static int luaB_next (lua_State *L) { static int luaB_next (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 2); /* create a 2nd argument if there isn't one */ lua_settop(L, 2); /* create a 2nd argument if there isn't one */
@ -236,18 +223,7 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) { static int luaB_pairs (lua_State *L) {
luaL_checkany(L, 1); return pairsmeta(L, "__pairs", 0, luaB_next);
if (luaL_getmetafield(L, 1, "__pairs")) {
lua_pushvalue(L, 1);
lua_call(L, 1, 3);
}
else {
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
}
return 3;
} }
@ -257,28 +233,17 @@ static int ipairsaux (lua_State *L) {
i++; /* next value */ i++; /* next value */
lua_pushinteger(L, i); lua_pushinteger(L, i);
lua_rawgeti(L, 1, i); lua_rawgeti(L, 1, i);
return (lua_isnil(L, -1)) ? 0 : 2; return (lua_isnil(L, -1)) ? 1 : 2;
} }
static int luaB_ipairs (lua_State *L) { static int luaB_ipairs (lua_State *L) {
luaL_checkany(L, 1); return pairsmeta(L, "__ipairs", 1, ipairsaux);
if (luaL_getmetafield(L, 1, "__ipairs")) {
lua_pushvalue(L, 1);
lua_call(L, 1, 3);
}
else {
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushinteger(L, 0); /* and initial value */
}
return 3;
} }
static int load_aux (lua_State *L, int status) { static int load_aux (lua_State *L, int status) {
if (status == 0) /* OK? */ if (status == LUA_OK)
return 1; return 1;
else { else {
lua_pushnil(L); lua_pushnil(L);
@ -288,20 +253,34 @@ static int load_aux (lua_State *L, int status) {
} }
static int luaB_loadstring (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
const char *chunkname = luaL_optstring(L, 2, s);
return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
}
static int luaB_loadfile (lua_State *L) { static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL); const char *fname = luaL_optstring(L, 1, NULL);
return load_aux(L, luaL_loadfile(L, fname)); const char *mode = luaL_optstring(L, 2, NULL);
int env = !lua_isnone(L, 3); /* 'env' parameter? */
int status = luaL_loadfilex(L, fname, mode);
if (status == LUA_OK && env) { /* 'env' parameter? */
lua_pushvalue(L, 3);
lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
}
return load_aux(L, status);
} }
/*
** {======================================================
** Generic Read function
** =======================================================
*/
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/* /*
** Reader for generic `load' function: `lua_load' uses the ** Reader for generic `load' function: `lua_load' uses the
** stack for internal stuff, so the reader cannot change the ** stack for internal stuff, so the reader cannot change the
@ -309,7 +288,7 @@ static int luaB_loadfile (lua_State *L) {
** reserved slot inside the stack. ** reserved slot inside the stack.
*/ */
static const char *generic_reader (lua_State *L, void *ud, size_t *size) { static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)ud; /* to avoid warnings */ (void)(ud); /* not used */
luaL_checkstack(L, 2, "too many nested functions"); luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */ lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */ lua_call(L, 0, 1); /* call it */
@ -317,58 +296,60 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
*size = 0; *size = 0;
return NULL; return NULL;
} }
else if (lua_isstring(L, -1)) { else if (!lua_isstring(L, -1))
lua_replace(L, 3); /* save string in a reserved stack slot */ luaL_error(L, "reader function must return a string");
return lua_tolstring(L, 3, size); lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
} return lua_tolstring(L, RESERVEDSLOT, size);
else luaL_error(L, "reader function must return a string");
return NULL; /* to avoid warnings */
} }
static int luaB_load (lua_State *L) { static int luaB_load (lua_State *L) {
int status; int status;
const char *cname = luaL_optstring(L, 2, "=(load)"); size_t l;
luaL_checktype(L, 1, LUA_TFUNCTION); int top = lua_gettop(L);
lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ const char *s = lua_tolstring(L, 1, &l);
status = lua_load(L, generic_reader, NULL, cname); const char *mode = luaL_optstring(L, 3, "bt");
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = luaL_loadbufferx(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = lua_load(L, generic_reader, NULL, chunkname, mode);
}
if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */
lua_pushvalue(L, 4); /* environment for loaded function */
lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */
}
return load_aux(L, status); return load_aux(L, status);
} }
/* }====================================================== */
static int dofilecont (lua_State *L) {
return lua_gettop(L) - 1;
}
static int luaB_dofile (lua_State *L) { static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL); const char *fname = luaL_optstring(L, 1, NULL);
int n = lua_gettop(L); lua_settop(L, 1);
if (luaL_loadfile(L, fname) != 0) lua_error(L); if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L);
lua_call(L, 0, LUA_MULTRET); lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
return lua_gettop(L) - n; return dofilecont(L);
} }
static int luaB_assert (lua_State *L) { static int luaB_assert (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_toboolean(L, 1)) if (!lua_toboolean(L, 1))
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
return lua_gettop(L); return lua_gettop(L);
} }
static int luaB_unpack (lua_State *L) {
int i, e, n;
luaL_checktype(L, 1, LUA_TTABLE);
i = luaL_optint(L, 2, 1);
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
if (i > e) return 0; /* empty range */
n = e - i + 1; /* number of elements */
if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
return luaL_error(L, "too many results to unpack");
lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
while (i++ < e) /* push arg[i + 1...e] */
lua_rawgeti(L, 1, i);
return n;
}
static int luaB_select (lua_State *L) { static int luaB_select (lua_State *L) {
int n = lua_gettop(L); int n = lua_gettop(L);
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
@ -385,75 +366,50 @@ static int luaB_select (lua_State *L) {
} }
static int finishpcall (lua_State *L, int status) {
if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */
lua_settop(L, 0); /* create space for return values */
lua_pushboolean(L, 0);
lua_pushstring(L, "stack overflow");
return 2; /* return false, msg */
}
lua_pushboolean(L, status); /* first result (status) */
lua_replace(L, 1); /* put first result in first slot */
return lua_gettop(L);
}
static int pcallcont (lua_State *L) {
int status = lua_getctx(L, NULL);
return finishpcall(L, (status == LUA_YIELD));
}
static int luaB_pcall (lua_State *L) { static int luaB_pcall (lua_State *L) {
int status; int status;
luaL_checkany(L, 1); luaL_checkany(L, 1);
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); lua_pushnil(L);
lua_pushboolean(L, (status == 0)); lua_insert(L, 1); /* create space for status result */
lua_insert(L, 1); status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
return lua_gettop(L); /* return status + all results */ return finishpcall(L, (status == LUA_OK));
} }
static int luaB_xpcall (lua_State *L) { static int luaB_xpcall (lua_State *L) {
int status; int status;
luaL_checkany(L, 2); int n = lua_gettop(L);
lua_settop(L, 2); luaL_argcheck(L, n >= 2, 2, "value expected");
lua_insert(L, 1); /* put error function under function to be called */ lua_pushvalue(L, 1); /* exchange function... */
status = lua_pcall(L, 0, LUA_MULTRET, 1); lua_copy(L, 2, 1); /* ...and error handler */
lua_pushboolean(L, (status == 0)); lua_replace(L, 2);
lua_replace(L, 1); status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont);
return lua_gettop(L); /* return status + all results */ return finishpcall(L, (status == LUA_OK));
} }
static int luaB_tostring (lua_State *L) { static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1); luaL_checkany(L, 1);
if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ luaL_tolstring(L, 1, NULL);
return 1; /* use its value */
switch (lua_type(L, 1)) {
case LUA_TNUMBER:
lua_pushstring(L, lua_tostring(L, 1));
break;
case LUA_TSTRING:
lua_pushvalue(L, 1);
break;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
break;
default:
lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
break;
}
return 1;
}
static int luaB_newproxy (lua_State *L) {
lua_settop(L, 1);
lua_newuserdata(L, 0); /* create proxy */
if (lua_toboolean(L, 1) == 0)
return 1; /* no metatable */
else if (lua_isboolean(L, 1)) {
lua_newtable(L); /* create a new metatable `m' ... */
lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
lua_pushboolean(L, 1);
lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
}
else {
int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
if (lua_getmetatable(L, 1)) {
lua_rawget(L, lua_upvalueindex(1));
validproxy = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove value */
}
luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
lua_getmetatable(L, 1); /* metatable is valid; get it */
}
lua_setmetatable(L, 2);
return 1; return 1;
} }
@ -463,205 +419,40 @@ static const luaL_Reg base_funcs[] = {
{"collectgarbage", luaB_collectgarbage}, {"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile}, {"dofile", luaB_dofile},
{"error", luaB_error}, {"error", luaB_error},
{"gcinfo", luaB_gcinfo},
{"getfenv", luaB_getfenv},
{"getmetatable", luaB_getmetatable}, {"getmetatable", luaB_getmetatable},
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile}, {"loadfile", luaB_loadfile},
{"load", luaB_load}, {"load", luaB_load},
{"loadstring", luaB_loadstring}, #if defined(LUA_COMPAT_LOADSTRING)
{"loadstring", luaB_load},
#endif
{"next", luaB_next}, {"next", luaB_next},
{"pairs", luaB_pairs},
{"pcall", luaB_pcall}, {"pcall", luaB_pcall},
{"print", luaB_print}, {"print", luaB_print},
{"rawequal", luaB_rawequal}, {"rawequal", luaB_rawequal},
{"rawlen", luaB_rawlen},
{"rawget", luaB_rawget}, {"rawget", luaB_rawget},
{"rawset", luaB_rawset}, {"rawset", luaB_rawset},
{"select", luaB_select}, {"select", luaB_select},
{"setfenv", luaB_setfenv},
{"setmetatable", luaB_setmetatable}, {"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber}, {"tonumber", luaB_tonumber},
{"tostring", luaB_tostring}, {"tostring", luaB_tostring},
{"type", luaB_type}, {"type", luaB_type},
{"unpack", luaB_unpack},
{"xpcall", luaB_xpcall}, {"xpcall", luaB_xpcall},
{NULL, NULL} {NULL, NULL}
}; };
/* LUAMOD_API int luaopen_base (lua_State *L) {
** {======================================================
** Coroutine library
** =======================================================
*/
#define CO_RUN 0 /* running */
#define CO_SUS 1 /* suspended */
#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */
#define CO_DEAD 3
static const char *const statnames[] =
{"running", "suspended", "normal", "dead"};
static int costatus (lua_State *L, lua_State *co) {
if (L == co) return CO_RUN;
switch (lua_status(co)) {
case LUA_YIELD:
return CO_SUS;
case 0: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
return CO_NOR; /* it is running */
else if (lua_gettop(co) == 0)
return CO_DEAD;
else
return CO_SUS; /* initial state */
}
default: /* some error occured */
return CO_DEAD;
}
}
static int luaB_costatus (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argcheck(L, co, 1, "coroutine expected");
lua_pushstring(L, statnames[costatus(L, co)]);
return 1;
}
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status = costatus(L, co);
if (!lua_checkstack(co, narg))
luaL_error(L, "too many arguments to resume");
if (status != CO_SUS) {
lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
return -1; /* error flag */
}
lua_xmove(L, co, narg);
lua_setlevel(L, co);
status = lua_resume(co, narg);
if (status == 0 || status == LUA_YIELD) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres + 1))
luaL_error(L, "too many results to resume");
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int luaB_coresume (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
int r;
luaL_argcheck(L, co, 1, "coroutine expected");
r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + `resume' returns */
}
}
static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L));
if (r < 0) {
if (lua_isstring(L, -1)) { /* error object is a string? */
luaL_where(L, 1); /* add extra info */
lua_insert(L, -2);
lua_concat(L, 2);
}
lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL = lua_newthread(L);
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
"Lua function expected");
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
static int luaB_corunning (lua_State *L) {
if (lua_pushthread(L))
lua_pushnil(L); /* main thread is not a coroutine */
return 1;
}
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{NULL, NULL}
};
/* }====================================================== */
static void auxopen (lua_State *L, const char *name,
lua_CFunction f, lua_CFunction u) {
lua_pushcfunction(L, u);
lua_pushcclosure(L, f, 1);
lua_setfield(L, -2, name);
}
static void base_open (lua_State *L) {
/* set global _G */ /* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushglobaltable(L);
lua_setglobal(L, "_G"); lua_pushglobaltable(L);
lua_setfield(L, -2, "_G");
/* open lib into global table */ /* open lib into global table */
luaL_register(L, "_G", base_funcs); luaL_setfuncs(L, base_funcs, 0);
lua_pushliteral(L, LUA_VERSION); lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */ lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */
/* `ipairs' and `pairs' need auxliliary functions as upvalues */ return 1;
auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next);
/* `newproxy' needs a weaktable as upvalue */
lua_createtable(L, 0, 1); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1);
lua_setglobal(L, "newproxy"); /* set global `newproxy' */
}
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
} }

@ -0,0 +1,209 @@
/*
** $Id: lbitlib.c,v 1.16 2011/06/20 16:35:23 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
#define lbitlib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/* number of bits to consider in a number */
#if !defined(LUA_NBITS)
#define LUA_NBITS 32
#endif
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
/* macro to trim extra bits */
#define trim(x) ((x) & ALLONES)
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
typedef lua_Unsigned b_uint;
static b_uint andaux (lua_State *L) {
int i, n = lua_gettop(L);
b_uint r = ~(b_uint)0;
for (i = 1; i <= n; i++)
r &= luaL_checkunsigned(L, i);
return trim(r);
}
static int b_and (lua_State *L) {
b_uint r = andaux(L);
lua_pushunsigned(L, r);
return 1;
}
static int b_test (lua_State *L) {
b_uint r = andaux(L);
lua_pushboolean(L, r != 0);
return 1;
}
static int b_or (lua_State *L) {
int i, n = lua_gettop(L);
b_uint r = 0;
for (i = 1; i <= n; i++)
r |= luaL_checkunsigned(L, i);
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_xor (lua_State *L) {
int i, n = lua_gettop(L);
b_uint r = 0;
for (i = 1; i <= n; i++)
r ^= luaL_checkunsigned(L, i);
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_not (lua_State *L) {
b_uint r = ~luaL_checkunsigned(L, 1);
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_shift (lua_State *L, b_uint r, int i) {
if (i < 0) { /* shift right? */
i = -i;
r = trim(r);
if (i >= LUA_NBITS) r = 0;
else r >>= i;
}
else { /* shift left */
if (i >= LUA_NBITS) r = 0;
else r <<= i;
r = trim(r);
}
lua_pushunsigned(L, r);
return 1;
}
static int b_lshift (lua_State *L) {
return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
}
static int b_rshift (lua_State *L) {
return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
}
static int b_arshift (lua_State *L) {
b_uint r = luaL_checkunsigned(L, 1);
int i = luaL_checkint(L, 2);
if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
return b_shift(L, r, -i);
else { /* arithmetic shift for 'negative' number */
if (i >= LUA_NBITS) r = ALLONES;
else
r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */
lua_pushunsigned(L, r);
return 1;
}
}
static int b_rot (lua_State *L, int i) {
b_uint r = luaL_checkunsigned(L, 1);
i &= (LUA_NBITS - 1); /* i = i % NBITS */
r = trim(r);
r = (r << i) | (r >> (LUA_NBITS - i));
lua_pushunsigned(L, trim(r));
return 1;
}
static int b_lrot (lua_State *L) {
return b_rot(L, luaL_checkint(L, 2));
}
static int b_rrot (lua_State *L) {
return b_rot(L, -luaL_checkint(L, 2));
}
/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid
*/
static int fieldargs (lua_State *L, int farg, int *width) {
int f = luaL_checkint(L, farg);
int w = luaL_optint(L, farg + 1, 1);
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
if (f + w > LUA_NBITS)
luaL_error(L, "trying to access non-existent bits");
*width = w;
return f;
}
static int b_extract (lua_State *L) {
int w;
b_uint r = luaL_checkunsigned(L, 1);
int f = fieldargs(L, 2, &w);
r = (r >> f) & mask(w);
lua_pushunsigned(L, r);
return 1;
}
static int b_replace (lua_State *L) {
int w;
b_uint r = luaL_checkunsigned(L, 1);
b_uint v = luaL_checkunsigned(L, 2);
int f = fieldargs(L, 3, &w);
int m = mask(w);
v &= m; /* erase bits outside given width */
r = (r & ~(m << f)) | (v << f);
lua_pushunsigned(L, r);
return 1;
}
static const luaL_Reg bitlib[] = {
{"arshift", b_arshift},
{"band", b_and},
{"bnot", b_not},
{"bor", b_or},
{"bxor", b_xor},
{"btest", b_test},
{"extract", b_extract},
{"lrotate", b_lrot},
{"lshift", b_lshift},
{"replace", b_replace},
{"rrotate", b_rrot},
{"rshift", b_rshift},
{NULL, NULL}
};
LUAMOD_API int luaopen_bit32 (lua_State *L) {
luaL_newlib(L, bitlib);
return 1;
}

@ -1,5 +1,5 @@
/* /*
** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ ** $Id: lcode.c,v 2.60 2011/08/30 16:26:41 roberto Exp $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -21,7 +21,9 @@
#include "lobject.h" #include "lobject.h"
#include "lopcodes.h" #include "lopcodes.h"
#include "lparser.h" #include "lparser.h"
#include "lstring.h"
#include "ltable.h" #include "ltable.h"
#include "lvm.h"
#define hasjumps(e) ((e)->t != (e)->f) #define hasjumps(e) ((e)->t != (e)->f)
@ -34,25 +36,23 @@ static int isnumeral(expdesc *e) {
void luaK_nil (FuncState *fs, int from, int n) { void luaK_nil (FuncState *fs, int from, int n) {
Instruction *previous; Instruction *previous;
int l = from + n - 1; /* last register to set nil */
if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
if (fs->pc == 0) { /* function start? */ previous = &fs->f->code[fs->pc-1];
if (from >= fs->nactvar) if (GET_OPCODE(*previous) == OP_LOADNIL) {
return; /* positions are already clean */ int pfrom = GETARG_A(*previous);
} int pl = pfrom + GETARG_B(*previous);
else { if ((pfrom <= from && from <= pl + 1) ||
previous = &fs->f->code[fs->pc-1]; (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */
if (GET_OPCODE(*previous) == OP_LOADNIL) { if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */
int pfrom = GETARG_A(*previous); if (pl > l) l = pl; /* l = max(l, pl) */
int pto = GETARG_B(*previous); SETARG_A(*previous, from);
if (pfrom <= from && from <= pto+1) { /* can connect both? */ SETARG_B(*previous, l - from);
if (from+n-1 > pto) return;
SETARG_B(*previous, from+n-1);
return;
}
} }
} } /* else go through */
} }
luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */
} }
@ -176,6 +176,19 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
} }
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) {
level++; /* argument is +1 to reserve 0 as non-op */
while (list != NO_JUMP) {
int next = getjump(fs, list);
lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
(GETARG_A(fs->f->code[list]) == 0 ||
GETARG_A(fs->f->code[list]) >= level));
SETARG_A(fs->f->code[list], level);
list = next;
}
}
void luaK_patchtohere (FuncState *fs, int list) { void luaK_patchtohere (FuncState *fs, int list) {
luaK_getlabel(fs); luaK_getlabel(fs);
luaK_concat(fs, &fs->jpc, list); luaK_concat(fs, &fs->jpc, list);
@ -196,6 +209,55 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
} }
static int luaK_code (FuncState *fs, Instruction i) {
Proto *f = fs->f;
dischargejpc(fs); /* `pc' will change */
/* put new instruction in code array */
luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
MAX_INT, "opcodes");
f->code[fs->pc] = i;
/* save corresponding line information */
luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
MAX_INT, "opcodes");
f->lineinfo[fs->pc] = fs->ls->lastline;
return fs->pc++;
}
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
lua_assert(getOpMode(o) == iABC);
lua_assert(getBMode(o) != OpArgN || b == 0);
lua_assert(getCMode(o) != OpArgN || c == 0);
lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
return luaK_code(fs, CREATE_ABC(o, a, b, c));
}
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
lua_assert(getCMode(o) == OpArgN);
lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
return luaK_code(fs, CREATE_ABx(o, a, bc));
}
static int codeextraarg (FuncState *fs, int a) {
lua_assert(a <= MAXARG_Ax);
return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
}
int luaK_codek (FuncState *fs, int reg, int k) {
if (k <= MAXARG_Bx)
return luaK_codeABx(fs, OP_LOADK, reg, k);
else {
int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
codeextraarg(fs, k);
return p;
}
}
void luaK_checkstack (FuncState *fs, int n) { void luaK_checkstack (FuncState *fs, int n) {
int newstack = fs->freereg + n; int newstack = fs->freereg + n;
if (newstack > fs->f->maxstacksize) { if (newstack > fs->f->maxstacksize) {
@ -222,42 +284,60 @@ static void freereg (FuncState *fs, int reg) {
static void freeexp (FuncState *fs, expdesc *e) { static void freeexp (FuncState *fs, expdesc *e) {
if (e->k == VNONRELOC) if (e->k == VNONRELOC)
freereg(fs, e->u.s.info); freereg(fs, e->u.info);
} }
static int addk (FuncState *fs, TValue *k, TValue *v) { static int addk (FuncState *fs, TValue *key, TValue *v) {
lua_State *L = fs->L; lua_State *L = fs->ls->L;
TValue *idx = luaH_set(L, fs->h, k); TValue *idx = luaH_set(L, fs->h, key);
Proto *f = fs->f; Proto *f = fs->f;
int oldsize = f->sizek; int k, oldsize;
if (ttisnumber(idx)) { if (ttisnumber(idx)) {
lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); lua_Number n = nvalue(idx);
return cast_int(nvalue(idx)); lua_number2int(k, n);
} if (luaV_rawequalobj(&f->k[k], v))
else { /* constant not found; create a new entry */ return k;
setnvalue(idx, cast_num(fs->nk)); /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0");
luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, go through and create a new entry for this value */
MAXARG_Bx, "constant table overflow");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
setobj(L, &f->k[fs->nk], v);
luaC_barrier(L, f, v);
return fs->nk++;
} }
/* constant not found; create a new entry */
oldsize = f->sizek;
k = fs->nk;
/* numerical value does not need GC barrier;
table has no metatable, so it does not need to invalidate cache */
setnvalue(idx, cast_num(k));
luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
setobj(L, &f->k[k], v);
fs->nk++;
luaC_barrier(L, f, v);
return k;
} }
int luaK_stringK (FuncState *fs, TString *s) { int luaK_stringK (FuncState *fs, TString *s) {
TValue o; TValue o;
setsvalue(fs->L, &o, s); setsvalue(fs->ls->L, &o, s);
return addk(fs, &o, &o); return addk(fs, &o, &o);
} }
int luaK_numberK (FuncState *fs, lua_Number r) { int luaK_numberK (FuncState *fs, lua_Number r) {
int n;
lua_State *L = fs->ls->L;
TValue o; TValue o;
setnvalue(&o, r); setnvalue(&o, r);
return addk(fs, &o, &o); if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */
/* use raw representation as key to avoid numeric problems */
setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r)));
incr_top(L);
n = addk(fs, L->top - 1, &o);
L->top--;
}
else
n = addk(fs, &o, &o); /* regular case */
return n;
} }
@ -272,7 +352,7 @@ static int nilK (FuncState *fs) {
TValue k, v; TValue k, v;
setnilvalue(&v); setnilvalue(&v);
/* cannot use nil as key; instead use table itself to represent nil */ /* cannot use nil as key; instead use table itself to represent nil */
sethvalue(fs->L, &k, fs->h); sethvalue(fs->ls->L, &k, fs->h);
return addk(fs, &k, &v); return addk(fs, &k, &v);
} }
@ -292,7 +372,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
void luaK_setoneret (FuncState *fs, expdesc *e) { void luaK_setoneret (FuncState *fs, expdesc *e) {
if (e->k == VCALL) { /* expression is an open function call? */ if (e->k == VCALL) { /* expression is an open function call? */
e->k = VNONRELOC; e->k = VNONRELOC;
e->u.s.info = GETARG_A(getcode(fs, e)); e->u.info = GETARG_A(getcode(fs, e));
} }
else if (e->k == VVARARG) { else if (e->k == VVARARG) {
SETARG_B(getcode(fs, e), 2); SETARG_B(getcode(fs, e), 2);
@ -308,19 +388,18 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
break; break;
} }
case VUPVAL: { case VUPVAL: {
e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
e->k = VRELOCABLE;
break;
}
case VGLOBAL: {
e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
case VINDEXED: { case VINDEXED: {
freereg(fs, e->u.s.aux); OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */
freereg(fs, e->u.s.info); freereg(fs, e->u.ind.idx);
e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */
freereg(fs, e->u.ind.t);
op = OP_GETTABLE;
}
e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
@ -352,11 +431,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
break; break;
} }
case VK: { case VK: {
luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); luaK_codek(fs, reg, e->u.info);
break; break;
} }
case VKNUM: { case VKNUM: {
luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval));
break; break;
} }
case VRELOCABLE: { case VRELOCABLE: {
@ -365,8 +444,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
break; break;
} }
case VNONRELOC: { case VNONRELOC: {
if (reg != e->u.s.info) if (reg != e->u.info)
luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
break; break;
} }
default: { default: {
@ -374,7 +453,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
return; /* nothing to do... */ return; /* nothing to do... */
} }
} }
e->u.s.info = reg; e->u.info = reg;
e->k = VNONRELOC; e->k = VNONRELOC;
} }
@ -390,7 +469,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) {
static void exp2reg (FuncState *fs, expdesc *e, int reg) { static void exp2reg (FuncState *fs, expdesc *e, int reg) {
discharge2reg(fs, e, reg); discharge2reg(fs, e, reg);
if (e->k == VJMP) if (e->k == VJMP)
luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */
if (hasjumps(e)) { if (hasjumps(e)) {
int final; /* position after whole expression */ int final; /* position after whole expression */
int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_f = NO_JUMP; /* position of an eventual LOAD false */
@ -406,7 +485,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
patchlistaux(fs, e->t, final, reg, p_t); patchlistaux(fs, e->t, final, reg, p_t);
} }
e->f = e->t = NO_JUMP; e->f = e->t = NO_JUMP;
e->u.s.info = reg; e->u.info = reg;
e->k = VNONRELOC; e->k = VNONRELOC;
} }
@ -422,14 +501,20 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
int luaK_exp2anyreg (FuncState *fs, expdesc *e) { int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
if (e->k == VNONRELOC) { if (e->k == VNONRELOC) {
if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ if (!hasjumps(e)) return e->u.info; /* exp is already in a register */
if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ if (e->u.info >= fs->nactvar) { /* reg. is not a local? */
exp2reg(fs, e, e->u.s.info); /* put value on it */ exp2reg(fs, e, e->u.info); /* put value on it */
return e->u.s.info; return e->u.info;
} }
} }
luaK_exp2nextreg(fs, e); /* default */ luaK_exp2nextreg(fs, e); /* default */
return e->u.s.info; return e->u.info;
}
void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
if (e->k != VUPVAL || hasjumps(e))
luaK_exp2anyreg(fs, e);
} }
@ -444,22 +529,24 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
int luaK_exp2RK (FuncState *fs, expdesc *e) { int luaK_exp2RK (FuncState *fs, expdesc *e) {
luaK_exp2val(fs, e); luaK_exp2val(fs, e);
switch (e->k) { switch (e->k) {
case VKNUM:
case VTRUE: case VTRUE:
case VFALSE: case VFALSE:
case VNIL: { case VNIL: {
if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */
e->u.s.info = (e->k == VNIL) ? nilK(fs) : e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE));
(e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
boolK(fs, (e->k == VTRUE));
e->k = VK; e->k = VK;
return RKASK(e->u.s.info); return RKASK(e->u.info);
} }
else break; else break;
} }
case VKNUM: {
e->u.info = luaK_numberK(fs, e->u.nval);
e->k = VK;
/* go through */
}
case VK: { case VK: {
if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */
return RKASK(e->u.s.info); return RKASK(e->u.info);
else break; else break;
} }
default: break; default: break;
@ -473,22 +560,18 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
switch (var->k) { switch (var->k) {
case VLOCAL: { case VLOCAL: {
freeexp(fs, ex); freeexp(fs, ex);
exp2reg(fs, ex, var->u.s.info); exp2reg(fs, ex, var->u.info);
return; return;
} }
case VUPVAL: { case VUPVAL: {
int e = luaK_exp2anyreg(fs, ex); int e = luaK_exp2anyreg(fs, ex);
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
break;
}
case VGLOBAL: {
int e = luaK_exp2anyreg(fs, ex);
luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
break; break;
} }
case VINDEXED: { case VINDEXED: {
OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
int e = luaK_exp2RK(fs, ex); int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
break; break;
} }
default: { default: {
@ -501,20 +584,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
int func; int ereg;
luaK_exp2anyreg(fs, e); luaK_exp2anyreg(fs, e);
ereg = e->u.info; /* register where 'e' was placed */
freeexp(fs, e); freeexp(fs, e);
func = fs->freereg; e->u.info = fs->freereg; /* base register for op_self */
luaK_reserveregs(fs, 2);
luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
freeexp(fs, key);
e->u.s.info = func;
e->k = VNONRELOC; e->k = VNONRELOC;
luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
freeexp(fs, key);
} }
static void invertjump (FuncState *fs, expdesc *e) { static void invertjump (FuncState *fs, expdesc *e) {
Instruction *pc = getjumpcontrol(fs, e->u.s.info); Instruction *pc = getjumpcontrol(fs, e->u.info);
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
GET_OPCODE(*pc) != OP_TEST); GET_OPCODE(*pc) != OP_TEST);
SETARG_A(*pc, !(GETARG_A(*pc))); SETARG_A(*pc, !(GETARG_A(*pc)));
@ -532,7 +615,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
} }
discharge2anyreg(fs, e); discharge2anyreg(fs, e);
freeexp(fs, e); freeexp(fs, e);
return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond);
} }
@ -540,17 +623,13 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
int pc; /* pc of last jump */ int pc; /* pc of last jump */
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
switch (e->k) { switch (e->k) {
case VK: case VKNUM: case VTRUE: {
pc = NO_JUMP; /* always true; do nothing */
break;
}
case VFALSE: {
pc = luaK_jump(fs); /* always jump */
break;
}
case VJMP: { case VJMP: {
invertjump(fs, e); invertjump(fs, e);
pc = e->u.s.info; pc = e->u.info;
break;
}
case VK: case VKNUM: case VTRUE: {
pc = NO_JUMP; /* always true; do nothing */
break; break;
} }
default: { default: {
@ -564,20 +643,16 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
} }
static void luaK_goiffalse (FuncState *fs, expdesc *e) { void luaK_goiffalse (FuncState *fs, expdesc *e) {
int pc; /* pc of last jump */ int pc; /* pc of last jump */
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
switch (e->k) { switch (e->k) {
case VNIL: case VFALSE: { case VJMP: {
pc = NO_JUMP; /* always false; do nothing */ pc = e->u.info;
break;
}
case VTRUE: {
pc = luaK_jump(fs); /* always jump */
break; break;
} }
case VJMP: { case VNIL: case VFALSE: {
pc = e->u.s.info; pc = NO_JUMP; /* always false; do nothing */
break; break;
} }
default: { default: {
@ -610,7 +685,7 @@ static void codenot (FuncState *fs, expdesc *e) {
case VNONRELOC: { case VNONRELOC: {
discharge2anyreg(fs, e); discharge2anyreg(fs, e);
freeexp(fs, e); freeexp(fs, e);
e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
@ -627,38 +702,28 @@ static void codenot (FuncState *fs, expdesc *e) {
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
t->u.s.aux = luaK_exp2RK(fs, k); lua_assert(!hasjumps(t));
t->u.ind.t = t->u.info;
t->u.ind.idx = luaK_exp2RK(fs, k);
t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
: check_exp(vkisinreg(t->k), VLOCAL);
t->k = VINDEXED; t->k = VINDEXED;
} }
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
lua_Number v1, v2, r; lua_Number r;
if (!isnumeral(e1) || !isnumeral(e2)) return 0; if (!isnumeral(e1) || !isnumeral(e2)) return 0;
v1 = e1->u.nval; if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0)
v2 = e2->u.nval; return 0; /* do not attempt to divide by 0 */
switch (op) { r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval);
case OP_ADD: r = luai_numadd(v1, v2); break;
case OP_SUB: r = luai_numsub(v1, v2); break;
case OP_MUL: r = luai_nummul(v1, v2); break;
case OP_DIV:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_numdiv(v1, v2); break;
case OP_MOD:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_nummod(v1, v2); break;
case OP_POW: r = luai_numpow(v1, v2); break;
case OP_UNM: r = luai_numunm(v1); break;
case OP_LEN: return 0; /* no constant folding for 'len' */
default: lua_assert(0); r = 0; break;
}
if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
e1->u.nval = r; e1->u.nval = r;
return 1; return 1;
} }
static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { static void codearith (FuncState *fs, OpCode op,
expdesc *e1, expdesc *e2, int line) {
if (constfolding(op, e1, e2)) if (constfolding(op, e1, e2))
return; return;
else { else {
@ -672,8 +737,9 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
freeexp(fs, e2); freeexp(fs, e2);
freeexp(fs, e1); freeexp(fs, e1);
} }
e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);
e1->k = VRELOCABLE; e1->k = VRELOCABLE;
luaK_fixline(fs, line);
} }
} }
@ -689,25 +755,28 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
cond = 1; cond = 1;
} }
e1->u.s.info = condjump(fs, op, cond, o1, o2); e1->u.info = condjump(fs, op, cond, o1, o2);
e1->k = VJMP; e1->k = VJMP;
} }
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
expdesc e2; expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
switch (op) { switch (op) {
case OPR_MINUS: { case OPR_MINUS: {
if (!isnumeral(e)) if (isnumeral(e)) /* minus constant? */
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */
codearith(fs, OP_UNM, e, &e2); else {
luaK_exp2anyreg(fs, e);
codearith(fs, OP_UNM, e, &e2, line);
}
break; break;
} }
case OPR_NOT: codenot(fs, e); break; case OPR_NOT: codenot(fs, e); break;
case OPR_LEN: { case OPR_LEN: {
luaK_exp2anyreg(fs, e); /* cannot operate on constants */ luaK_exp2anyreg(fs, e); /* cannot operate on constants */
codearith(fs, OP_LEN, e, &e2); codearith(fs, OP_LEN, e, &e2, line);
break; break;
} }
default: lua_assert(0); default: lua_assert(0);
@ -742,7 +811,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
} }
void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { void luaK_posfix (FuncState *fs, BinOpr op,
expdesc *e1, expdesc *e2, int line) {
switch (op) { switch (op) {
case OPR_AND: { case OPR_AND: {
lua_assert(e1->t == NO_JUMP); /* list must be closed */ lua_assert(e1->t == NO_JUMP); /* list must be closed */
@ -761,29 +831,30 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
case OPR_CONCAT: { case OPR_CONCAT: {
luaK_exp2val(fs, e2); luaK_exp2val(fs, e2);
if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
freeexp(fs, e1); freeexp(fs, e1);
SETARG_B(getcode(fs, e2), e1->u.s.info); SETARG_B(getcode(fs, e2), e1->u.info);
e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; e1->k = VRELOCABLE; e1->u.info = e2->u.info;
} }
else { else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
codearith(fs, OP_CONCAT, e1, e2); codearith(fs, OP_CONCAT, e1, e2, line);
} }
break; break;
} }
case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; case OPR_MOD: case OPR_POW: {
case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; break;
case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; }
case OPR_POW: codearith(fs, OP_POW, e1, e2); break; case OPR_EQ: case OPR_LT: case OPR_LE: {
case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; break;
case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; }
case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; case OPR_NE: case OPR_GT: case OPR_GE: {
case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; break;
}
default: lua_assert(0); default: lua_assert(0);
} }
} }
@ -794,46 +865,18 @@ void luaK_fixline (FuncState *fs, int line) {
} }
static int luaK_code (FuncState *fs, Instruction i, int line) {
Proto *f = fs->f;
dischargejpc(fs); /* `pc' will change */
/* put new instruction in code array */
luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
MAX_INT, "code size overflow");
f->code[fs->pc] = i;
/* save corresponding line information */
luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
MAX_INT, "code size overflow");
f->lineinfo[fs->pc] = line;
return fs->pc++;
}
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
lua_assert(getOpMode(o) == iABC);
lua_assert(getBMode(o) != OpArgN || b == 0);
lua_assert(getCMode(o) != OpArgN || c == 0);
return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
}
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
lua_assert(getCMode(o) == OpArgN);
return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
}
void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
int b = (tostore == LUA_MULTRET) ? 0 : tostore; int b = (tostore == LUA_MULTRET) ? 0 : tostore;
lua_assert(tostore != 0); lua_assert(tostore != 0);
if (c <= MAXARG_C) if (c <= MAXARG_C)
luaK_codeABC(fs, OP_SETLIST, base, b, c); luaK_codeABC(fs, OP_SETLIST, base, b, c);
else { else if (c <= MAXARG_Ax) {
luaK_codeABC(fs, OP_SETLIST, base, b, 0); luaK_codeABC(fs, OP_SETLIST, base, b, 0);
luaK_code(fs, cast(Instruction, c), fs->ls->lastline); codeextraarg(fs, c);
} }
else
luaX_syntaxerror(fs->ls, "constructor too long");
fs->freereg = base + 1; /* free registers with list values */ fs->freereg = base + 1; /* free registers with list values */
} }

@ -0,0 +1,154 @@
/*
** $Id: lcorolib.c,v 1.3 2011/08/23 17:24:34 roberto Exp $
** Coroutine Library
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#define lcorolib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status;
if (!lua_checkstack(co, narg)) {
lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
lua_pushliteral(L, "cannot resume dead coroutine");
return -1; /* error flag */
}
lua_xmove(L, co, narg);
status = lua_resume(co, L, narg);
if (status == LUA_OK || status == LUA_YIELD) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres + 1)) {
lua_pop(co, nres); /* remove results anyway */
lua_pushliteral(L, "too many results to resume");
return -1; /* error flag */
}
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int luaB_coresume (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
int r;
luaL_argcheck(L, co, 1, "coroutine expected");
r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + `resume' returns */
}
}
static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L));
if (r < 0) {
if (lua_isstring(L, -1)) { /* error object is a string? */
luaL_where(L, 1); /* add extra info */
lua_insert(L, -2);
lua_concat(L, 2);
}
lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL = lua_newthread(L);
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
static int luaB_costatus (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argcheck(L, co, 1, "coroutine expected");
if (L == co) lua_pushliteral(L, "running");
else {
switch (lua_status(co)) {
case LUA_YIELD:
lua_pushliteral(L, "suspended");
break;
case LUA_OK: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
lua_pushliteral(L, "normal"); /* it is running */
else if (lua_gettop(co) == 0)
lua_pushliteral(L, "dead");
else
lua_pushliteral(L, "suspended"); /* initial state */
break;
}
default: /* some error occurred */
lua_pushliteral(L, "dead");
break;
}
}
return 1;
}
static int luaB_corunning (lua_State *L) {
int ismain = lua_pushthread(L);
lua_pushboolean(L, ismain);
return 2;
}
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{NULL, NULL}
};
LUAMOD_API int luaopen_coroutine (lua_State *L) {
luaL_newlib(L, co_funcs);
return 1;
}

@ -0,0 +1,52 @@
/*
** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#define lctype_c
#define LUA_CORE
#include "lctype.h"
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
0x00, /* EOZ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif /* } */

@ -1,5 +1,5 @@
/* /*
** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ ** $Id: ldblib.c,v 1.131 2011/10/24 14:54:05 roberto Exp $
** Interface from Lua to its debug API ** Interface from Lua to its debug API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -18,6 +18,9 @@
#include "lualib.h" #include "lualib.h"
#define HOOKKEY "_HKEY"
static int db_getregistry (lua_State *L) { static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX); lua_pushvalue(L, LUA_REGISTRYINDEX);
@ -39,23 +42,28 @@ static int db_setmetatable (lua_State *L) {
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected"); "nil or table expected");
lua_settop(L, 2); lua_settop(L, 2);
lua_pushboolean(L, lua_setmetatable(L, 1)); lua_setmetatable(L, 1);
return 1; return 1; /* return 1st argument */
} }
static int db_getfenv (lua_State *L) { static int db_getuservalue (lua_State *L) {
lua_getfenv(L, 1); if (lua_type(L, 1) != LUA_TUSERDATA)
lua_pushnil(L);
else
lua_getuservalue(L, 1);
return 1; return 1;
} }
static int db_setfenv (lua_State *L) { static int db_setuservalue (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE); if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)
luaL_argerror(L, 1, "full userdata expected, got light userdata");
luaL_checktype(L, 1, LUA_TUSERDATA);
if (!lua_isnoneornil(L, 2))
luaL_checktype(L, 2, LUA_TTABLE);
lua_settop(L, 2); lua_settop(L, 2);
if (lua_setfenv(L, 1) == 0) lua_setuservalue(L, 1);
luaL_error(L, LUA_QL("setfenv")
" cannot change environment of given object");
return 1; return 1;
} }
@ -72,6 +80,12 @@ static void settabsi (lua_State *L, const char *i, int v) {
} }
static void settabsb (lua_State *L, const char *i, int v) {
lua_pushboolean(L, v);
lua_setfield(L, -2, i);
}
static lua_State *getthread (lua_State *L, int *arg) { static lua_State *getthread (lua_State *L, int *arg) {
if (lua_isthread(L, 1)) { if (lua_isthread(L, 1)) {
*arg = 1; *arg = 1;
@ -99,7 +113,7 @@ static int db_getinfo (lua_State *L) {
lua_Debug ar; lua_Debug ar;
int arg; int arg;
lua_State *L1 = getthread(L, &arg); lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg+2, "flnSu"); const char *options = luaL_optstring(L, arg+2, "flnStu");
if (lua_isnumber(L, arg+1)) { if (lua_isnumber(L, arg+1)) {
if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
lua_pushnil(L); /* level out of range */ lua_pushnil(L); /* level out of range */
@ -126,38 +140,51 @@ static int db_getinfo (lua_State *L) {
} }
if (strchr(options, 'l')) if (strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline); settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u')) if (strchr(options, 'u')) {
settabsi(L, "nups", ar.nups); settabsi(L, "nups", ar.nups);
settabsi(L, "nparams", ar.nparams);
settabsb(L, "isvararg", ar.isvararg);
}
if (strchr(options, 'n')) { if (strchr(options, 'n')) {
settabss(L, "name", ar.name); settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat); settabss(L, "namewhat", ar.namewhat);
} }
if (strchr(options, 't'))
settabsb(L, "istailcall", ar.istailcall);
if (strchr(options, 'L')) if (strchr(options, 'L'))
treatstackoption(L, L1, "activelines"); treatstackoption(L, L1, "activelines");
if (strchr(options, 'f')) if (strchr(options, 'f'))
treatstackoption(L, L1, "func"); treatstackoption(L, L1, "func");
return 1; /* return table */ return 1; /* return table */
} }
static int db_getlocal (lua_State *L) { static int db_getlocal (lua_State *L) {
int arg; int arg;
lua_State *L1 = getthread(L, &arg); lua_State *L1 = getthread(L, &arg);
lua_Debug ar; lua_Debug ar;
const char *name; const char *name;
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ int nvar = luaL_checkint(L, arg+2); /* local-variable index */
return luaL_argerror(L, arg+1, "level out of range"); if (lua_isfunction(L, arg + 1)) { /* function argument? */
name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); lua_pushvalue(L, arg + 1); /* push function */
if (name) { lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
lua_xmove(L1, L, 1);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
}
else {
lua_pushnil(L);
return 1; return 1;
} }
else { /* stack-level argument */
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
name = lua_getlocal(L1, &ar, nvar);
if (name) {
lua_xmove(L1, L, 1); /* push local value */
lua_pushstring(L, name); /* push name */
lua_pushvalue(L, -2); /* re-order */
return 2;
}
else {
lua_pushnil(L); /* no name (nor value) */
return 1;
}
}
} }
@ -179,7 +206,6 @@ static int auxupvalue (lua_State *L, int get) {
const char *name; const char *name;
int n = luaL_checkint(L, 2); int n = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TFUNCTION); luaL_checktype(L, 1, LUA_TFUNCTION);
if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == NULL) return 0; if (name == NULL) return 0;
lua_pushstring(L, name); lua_pushstring(L, name);
@ -199,17 +225,42 @@ static int db_setupvalue (lua_State *L) {
} }
static int checkupval (lua_State *L, int argf, int argnup) {
lua_Debug ar;
int nup = luaL_checkint(L, argnup);
luaL_checktype(L, argf, LUA_TFUNCTION);
lua_pushvalue(L, argf);
lua_getinfo(L, ">u", &ar);
luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
return nup;
}
static const char KEY_HOOK = 'h';
static int db_upvalueid (lua_State *L) {
int n = checkupval(L, 1, 2);
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
return 1;
}
static int db_upvaluejoin (lua_State *L) {
int n1 = checkupval(L, 1, 2);
int n2 = checkupval(L, 3, 4);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
return 0;
}
#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY);
static void hookf (lua_State *L, lua_Debug *ar) { static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] = static const char *const hooknames[] =
{"call", "return", "line", "count", "tail return"}; {"call", "return", "line", "count", "tail call"};
lua_pushlightuserdata(L, (void *)&KEY_HOOK); gethooktable(L);
lua_rawget(L, LUA_REGISTRYINDEX); lua_rawgetp(L, -1, L);
lua_pushlightuserdata(L, L);
lua_rawget(L, -2);
if (lua_isfunction(L, -1)) { if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]); lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0) if (ar->currentline >= 0)
@ -241,19 +292,6 @@ static char *unmakemask (int mask, char *smask) {
} }
static void gethooktable (lua_State *L) {
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
lua_createtable(L, 0, 1);
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
}
static int db_sethook (lua_State *L) { static int db_sethook (lua_State *L) {
int arg, mask, count; int arg, mask, count;
lua_Hook func; lua_Hook func;
@ -269,9 +307,8 @@ static int db_sethook (lua_State *L) {
func = hookf; mask = makemask(smask, count); func = hookf; mask = makemask(smask, count);
} }
gethooktable(L); gethooktable(L);
lua_pushlightuserdata(L, L1);
lua_pushvalue(L, arg+1); lua_pushvalue(L, arg+1);
lua_rawset(L, -3); /* set new hook */ lua_rawsetp(L, -2, L1); /* set new hook */
lua_pop(L, 1); /* remove hook table */ lua_pop(L, 1); /* remove hook table */
lua_sethook(L1, func, mask, count); /* set hooks */ lua_sethook(L1, func, mask, count); /* set hooks */
return 0; return 0;
@ -288,8 +325,7 @@ static int db_gethook (lua_State *L) {
lua_pushliteral(L, "external hook"); lua_pushliteral(L, "external hook");
else { else {
gethooktable(L); gethooktable(L);
lua_pushlightuserdata(L, L1); lua_rawgetp(L, -1, L1); /* get hook */
lua_rawget(L, -2); /* get hook */
lua_remove(L, -2); /* remove hook table */ lua_remove(L, -2); /* remove hook table */
} }
lua_pushstring(L, unmakemask(mask, buff)); lua_pushstring(L, unmakemask(mask, buff));
@ -301,97 +337,55 @@ static int db_gethook (lua_State *L) {
static int db_debug (lua_State *L) { static int db_debug (lua_State *L) {
for (;;) { for (;;) {
char buffer[250]; char buffer[250];
fputs("lua_debug> ", stderr); luai_writestringerror("%s", "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == 0 || if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0) strcmp(buffer, "cont\n") == 0)
return 0; return 0;
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0)) { lua_pcall(L, 0, 0, 0))
fputs(lua_tostring(L, -1), stderr); luai_writestringerror("%s\n", lua_tostring(L, -1));
fputs("\n", stderr);
}
lua_settop(L, 0); /* remove eventual returns */ lua_settop(L, 0); /* remove eventual returns */
} }
} }
#define LEVELS1 12 /* size of the first part of the stack */ static int db_traceback (lua_State *L) {
#define LEVELS2 10 /* size of the second part of the stack */
static int db_errorfb (lua_State *L) {
int level;
int firstpart = 1; /* still before eventual `...' */
int arg; int arg;
lua_State *L1 = getthread(L, &arg); lua_State *L1 = getthread(L, &arg);
lua_Debug ar; const char *msg = lua_tostring(L, arg + 1);
if (lua_isnumber(L, arg+2)) { if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
level = (int)lua_tointeger(L, arg+2); lua_pushvalue(L, arg + 1); /* return it untouched */
lua_pop(L, 1); else {
} int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
else luaL_traceback(L, L1, msg, level);
level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
if (lua_gettop(L) == arg)
lua_pushliteral(L, "");
else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L1, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
if (!lua_getstack(L1, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\n\t..."); /* too many levels */
while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n\t");
lua_getinfo(L1, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
if (*ar.namewhat != '\0') /* is there a name? */
lua_pushfstring(L, " in function " LUA_QS, ar.name);
else {
if (*ar.what == 'm') /* main? */
lua_pushfstring(L, " in main chunk");
else if (*ar.what == 'C' || *ar.what == 't')
lua_pushliteral(L, " ?"); /* C function or tail call */
else
lua_pushfstring(L, " in function <%s:%d>",
ar.short_src, ar.linedefined);
}
lua_concat(L, lua_gettop(L) - arg);
} }
lua_concat(L, lua_gettop(L) - arg);
return 1; return 1;
} }
static const luaL_Reg dblib[] = { static const luaL_Reg dblib[] = {
{"debug", db_debug}, {"debug", db_debug},
{"getfenv", db_getfenv}, {"getuservalue", db_getuservalue},
{"gethook", db_gethook}, {"gethook", db_gethook},
{"getinfo", db_getinfo}, {"getinfo", db_getinfo},
{"getlocal", db_getlocal}, {"getlocal", db_getlocal},
{"getregistry", db_getregistry}, {"getregistry", db_getregistry},
{"getmetatable", db_getmetatable}, {"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue}, {"getupvalue", db_getupvalue},
{"setfenv", db_setfenv}, {"upvaluejoin", db_upvaluejoin},
{"upvalueid", db_upvalueid},
{"setuservalue", db_setuservalue},
{"sethook", db_sethook}, {"sethook", db_sethook},
{"setlocal", db_setlocal}, {"setlocal", db_setlocal},
{"setmetatable", db_setmetatable}, {"setmetatable", db_setmetatable},
{"setupvalue", db_setupvalue}, {"setupvalue", db_setupvalue},
{"traceback", db_errorfb}, {"traceback", db_traceback},
{NULL, NULL} {NULL, NULL}
}; };
LUALIB_API int luaopen_debug (lua_State *L) { LUAMOD_API int luaopen_debug (lua_State *L) {
luaL_register(L, LUA_DBLIBNAME, dblib); luaL_newlib(L, dblib);
return 1; return 1;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ ** $Id: ldebug.c,v 2.88 2011/11/30 12:43:51 roberto Exp $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -33,20 +33,14 @@
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
static int currentpc (lua_State *L, CallInfo *ci) { static int currentpc (CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */ lua_assert(isLua(ci));
if (ci == L->ci) return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
ci->savedpc = L->savedpc;
return pcRel(ci->savedpc, ci_func(ci)->l.p);
} }
static int currentline (lua_State *L, CallInfo *ci) { static int currentline (CallInfo *ci) {
int pc = currentpc(L, ci); return getfuncline(ci_func(ci)->p, currentpc(ci));
if (pc < 0)
return -1; /* only active lua functions have current-line information */
else
return getline(ci_func(ci)->l.p, pc);
} }
@ -58,6 +52,8 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
mask = 0; mask = 0;
func = NULL; func = NULL;
} }
if (isLua(L->ci))
L->oldpc = L->ci->u.l.savedpc;
L->hook = func; L->hook = func;
L->basehookcount = count; L->basehookcount = count;
resethookcount(L); resethookcount(L);
@ -84,19 +80,13 @@ LUA_API int lua_gethookcount (lua_State *L) {
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status; int status;
CallInfo *ci; CallInfo *ci;
if (level < 0) return 0; /* invalid (negative) level */
lua_lock(L); lua_lock(L);
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
level--; level--;
if (f_isLua(ci)) /* Lua function? */ if (level == 0 && ci != &L->base_ci) { /* level found? */
level -= ci->tailcalls; /* skip lost tail calls */
}
if (level == 0 && ci > L->base_ci) { /* level found? */
status = 1;
ar->i_ci = cast_int(ci - L->base_ci);
}
else if (level < 0) { /* level is of a lost tail call? */
status = 1; status = 1;
ar->i_ci = 0; ar->i_ci = ci;
} }
else status = 0; /* no such level */ else status = 0; /* no such level */
lua_unlock(L); lua_unlock(L);
@ -104,43 +94,78 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
} }
static Proto *getluaproto (CallInfo *ci) { static const char *upvalname (Proto *p, int uv) {
return (isLua(ci) ? ci_func(ci)->l.p : NULL); TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
if (s == NULL) return "?";
else return getstr(s);
} }
static const char *findlocal (lua_State *L, CallInfo *ci, int n) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
const char *name; int nparams = clLvalue(ci->func)->p->numparams;
Proto *fp = getluaproto(ci); if (n >= ci->u.l.base - ci->func - nparams)
if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) return NULL; /* no such vararg */
return name; /* is a local variable in a Lua function */
else { else {
StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; *pos = ci->func + nparams + n;
if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ return "(*vararg)"; /* generic name for any vararg */
return "(*temporary)"; }
}
static const char *findlocal (lua_State *L, CallInfo *ci, int n,
StkId *pos) {
const char *name = NULL;
StkId base;
if (isLua(ci)) {
if (n < 0) /* access to vararg values? */
return findvararg(ci, -n, pos);
else {
base = ci->u.l.base;
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
}
}
else
base = ci->func + 1;
if (name == NULL) { /* no 'standard' name? */
StkId limit = (ci == L->ci) ? L->top : ci->next->func;
if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */
name = "(*temporary)"; /* generic name for any valid slot */
else else
return NULL; return NULL; /* no name */
} }
*pos = base + (n - 1);
return name;
} }
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
CallInfo *ci = L->base_ci + ar->i_ci; const char *name;
const char *name = findlocal(L, ci, n);
lua_lock(L); lua_lock(L);
if (name) if (ar == NULL) { /* information about non-active function? */
luaA_pushobject(L, ci->base + (n - 1)); if (!isLfunction(L->top - 1)) /* not a Lua function? */
name = NULL;
else /* consider live variables at function start (parameters) */
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
}
else { /* active function; get information through 'ar' */
StkId pos = 0; /* to avoid warnings */
name = findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobj2s(L, L->top, pos);
api_incr_top(L);
}
}
lua_unlock(L); lua_unlock(L);
return name; return name;
} }
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
CallInfo *ci = L->base_ci + ar->i_ci; StkId pos = 0; /* to avoid warnings */
const char *name = findlocal(L, ci, n); const char *name = findlocal(L, ar->i_ci, n, &pos);
lua_lock(L); lua_lock(L);
if (name) if (name)
setobjs2s(L, ci->base + (n - 1), L->top - 1); setobjs2s(L, pos, L->top - 1);
L->top--; /* pop value */ L->top--; /* pop value */
lua_unlock(L); lua_unlock(L);
return name; return name;
@ -148,55 +173,45 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
static void funcinfo (lua_Debug *ar, Closure *cl) { static void funcinfo (lua_Debug *ar, Closure *cl) {
if (cl->c.isC) { if (cl == NULL || cl->c.isC) {
ar->source = "=[C]"; ar->source = "=[C]";
ar->linedefined = -1; ar->linedefined = -1;
ar->lastlinedefined = -1; ar->lastlinedefined = -1;
ar->what = "C"; ar->what = "C";
} }
else { else {
ar->source = getstr(cl->l.p->source); Proto *p = cl->l.p;
ar->linedefined = cl->l.p->linedefined; ar->source = p->source ? getstr(p->source) : "=?";
ar->lastlinedefined = cl->l.p->lastlinedefined; ar->linedefined = p->linedefined;
ar->lastlinedefined = p->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua"; ar->what = (ar->linedefined == 0) ? "main" : "Lua";
} }
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
} }
static void info_tailcall (lua_Debug *ar) {
ar->name = ar->namewhat = "";
ar->what = "tail";
ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
ar->source = "=(tail call)";
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
ar->nups = 0;
}
static void collectvalidlines (lua_State *L, Closure *f) { static void collectvalidlines (lua_State *L, Closure *f) {
if (f == NULL || f->c.isC) { if (f == NULL || f->c.isC) {
setnilvalue(L->top); setnilvalue(L->top);
incr_top(L);
} }
else { else {
Table *t = luaH_new(L, 0, 0);
int *lineinfo = f->l.p->lineinfo;
int i; int i;
for (i=0; i<f->l.p->sizelineinfo; i++) TValue v;
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); int *lineinfo = f->l.p->lineinfo;
sethvalue(L, L->top, t); Table *t = luaH_new(L); /* new table to store active lines */
sethvalue(L, L->top, t); /* push it on stack */
incr_top(L);
setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */
for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */
luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */
} }
incr_top(L);
} }
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
Closure *f, CallInfo *ci) { Closure *f, CallInfo *ci) {
int status = 1; int status = 1;
if (f == NULL) {
info_tailcall(ar);
return status;
}
for (; *what; what++) { for (; *what; what++) {
switch (*what) { switch (*what) {
case 'S': { case 'S': {
@ -204,15 +219,31 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
break; break;
} }
case 'l': { case 'l': {
ar->currentline = (ci) ? currentline(L, ci) : -1; ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1;
break; break;
} }
case 'u': { case 'u': {
ar->nups = f->c.nupvalues; ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
if (f == NULL || f->c.isC) {
ar->isvararg = 1;
ar->nparams = 0;
}
else {
ar->isvararg = f->l.p->is_vararg;
ar->nparams = f->l.p->numparams;
}
break;
}
case 't': {
ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
break; break;
} }
case 'n': { case 'n': {
ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; /* calling function is a known Lua function? */
if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
ar->namewhat = getfuncname(L, ci->previous, &ar->name);
else
ar->namewhat = NULL;
if (ar->namewhat == NULL) { if (ar->namewhat == NULL) {
ar->namewhat = ""; /* not found */ ar->namewhat = ""; /* not found */
ar->name = NULL; ar->name = NULL;
@ -231,29 +262,30 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
int status; int status;
Closure *f = NULL; Closure *cl;
CallInfo *ci = NULL; CallInfo *ci;
StkId func;
lua_lock(L); lua_lock(L);
if (*what == '>') { if (*what == '>') {
StkId func = L->top - 1; ci = NULL;
luai_apicheck(L, ttisfunction(func)); func = L->top - 1;
api_check(L, ttisfunction(func), "function expected");
what++; /* skip the '>' */ what++; /* skip the '>' */
f = clvalue(func);
L->top--; /* pop function */ L->top--; /* pop function */
} }
else if (ar->i_ci != 0) { /* no tail call? */ else {
ci = L->base_ci + ar->i_ci; ci = ar->i_ci;
func = ci->func;
lua_assert(ttisfunction(ci->func)); lua_assert(ttisfunction(ci->func));
f = clvalue(ci->func);
} }
status = auxgetinfo(L, what, ar, f, ci); cl = ttisclosure(func) ? clvalue(func) : NULL;
status = auxgetinfo(L, what, ar, cl, ci);
if (strchr(what, 'f')) { if (strchr(what, 'f')) {
if (f == NULL) setnilvalue(L->top); setobjs2s(L, L->top, func);
else setclvalue(L, L->top, f);
incr_top(L); incr_top(L);
} }
if (strchr(what, 'L')) if (strchr(what, 'L'))
collectvalidlines(L, f); collectvalidlines(L, cl);
lua_unlock(L); lua_unlock(L);
return status; return status;
} }
@ -261,315 +293,218 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
/* /*
** {====================================================== ** {======================================================
** Symbolic Execution and code checker ** Symbolic Execution
** ======================================================= ** =======================================================
*/ */
#define check(x) if (!(x)) return 0; static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name);
#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode)
#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize)
static int precheck (const Proto *pt) {
check(pt->maxstacksize <= MAXSTACK);
check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
check(!(pt->is_vararg & VARARG_NEEDSARG) ||
(pt->is_vararg & VARARG_HASARG));
check(pt->sizeupvalues <= pt->nups);
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
return 1;
}
#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) /*
** find a "name" for the RK value 'c'
int luaG_checkopenop (Instruction i) { */
switch (GET_OPCODE(i)) { static void kname (Proto *p, int pc, int c, const char **name) {
case OP_CALL: if (ISK(c)) { /* is 'c' a constant? */
case OP_TAILCALL: TValue *kvalue = &p->k[INDEXK(c)];
case OP_RETURN: if (ttisstring(kvalue)) { /* literal constant? */
case OP_SETLIST: { *name = svalue(kvalue); /* it is its own name */
check(GETARG_B(i) == 0); return;
return 1;
} }
default: return 0; /* invalid instruction after an open call */ /* else no reasonable name found */
} }
} else { /* 'c' is a register */
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
if (what && *what == 'c') { /* found a constant name? */
static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { return; /* 'name' already filled */
switch (mode) { }
case OpArgN: check(r == 0); break; /* else no reasonable name found */
case OpArgU: break;
case OpArgR: checkreg(pt, r); break;
case OpArgK:
check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
break;
} }
return 1; *name = "?"; /* no reasonable name found */
} }
static Instruction symbexec (const Proto *pt, int lastpc, int reg) { /*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
static int findsetreg (Proto *p, int lastpc, int reg) {
int pc; int pc;
int last; /* stores position of last instruction that changed `reg' */ int setreg = -1; /* keep last instruction that changed 'reg' */
last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
check(precheck(pt));
for (pc = 0; pc < lastpc; pc++) { for (pc = 0; pc < lastpc; pc++) {
Instruction i = pt->code[pc]; Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i); OpCode op = GET_OPCODE(i);
int a = GETARG_A(i); int a = GETARG_A(i);
int b = 0;
int c = 0;
check(op < NUM_OPCODES);
checkreg(pt, a);
switch (getOpMode(op)) {
case iABC: {
b = GETARG_B(i);
c = GETARG_C(i);
check(checkArgMode(pt, b, getBMode(op)));
check(checkArgMode(pt, c, getCMode(op)));
break;
}
case iABx: {
b = GETARG_Bx(i);
if (getBMode(op) == OpArgK) check(b < pt->sizek);
break;
}
case iAsBx: {
b = GETARG_sBx(i);
if (getBMode(op) == OpArgR) {
int dest = pc+1+b;
check(0 <= dest && dest < pt->sizecode);
if (dest > 0) {
int j;
/* check that it does not jump to a setlist count; this
is tricky, because the count from a previous setlist may
have the same value of an invalid setlist; so, we must
go all the way back to the first of them (if any) */
for (j = 0; j < dest; j++) {
Instruction d = pt->code[dest-1-j];
if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
}
/* if 'j' is even, previous value is not a setlist (even if
it looks like one) */
check((j&1) == 0);
}
}
break;
}
}
if (testAMode(op)) {
if (a == reg) last = pc; /* change register `a' */
}
if (testTMode(op)) {
check(pc+2 < pt->sizecode); /* check skip */
check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
}
switch (op) { switch (op) {
case OP_LOADBOOL: {
if (c == 1) { /* does it jump? */
check(pc+2 < pt->sizecode); /* check its jump */
check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
GETARG_C(pt->code[pc+1]) != 0);
}
break;
}
case OP_LOADNIL: { case OP_LOADNIL: {
if (a <= reg && reg <= b) int b = GETARG_B(i);
last = pc; /* set registers from `a' to `b' */ if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
break; setreg = pc;
}
case OP_GETUPVAL:
case OP_SETUPVAL: {
check(b < pt->nups);
break;
}
case OP_GETGLOBAL:
case OP_SETGLOBAL: {
check(ttisstring(&pt->k[b]));
break; break;
} }
case OP_SELF: { case OP_TFORCALL: {
checkreg(pt, a+1); if (reg >= a + 2) setreg = pc; /* affect all regs above its base */
if (reg == a+1) last = pc;
break;
}
case OP_CONCAT: {
check(b < c); /* at least two operands */
break;
}
case OP_TFORLOOP: {
check(c >= 1); /* at least one result (control variable) */
checkreg(pt, a+2+c); /* space for results */
if (reg >= a+2) last = pc; /* affect all regs above its base */
break;
}
case OP_FORLOOP:
case OP_FORPREP:
checkreg(pt, a+3);
/* go through */
case OP_JMP: {
int dest = pc+1+b;
/* not full check and jump is forward and do not skip `lastpc'? */
if (reg != NO_REG && pc < dest && dest <= lastpc)
pc += b; /* do the jump */
break; break;
} }
case OP_CALL: case OP_CALL:
case OP_TAILCALL: { case OP_TAILCALL: {
if (b != 0) { if (reg >= a) setreg = pc; /* affect all registers above base */
checkreg(pt, a+b-1);
}
c--; /* c = num. returns */
if (c == LUA_MULTRET) {
check(checkopenop(pt, pc));
}
else if (c != 0)
checkreg(pt, a+c-1);
if (reg >= a) last = pc; /* affect all registers above base */
break; break;
} }
case OP_RETURN: { case OP_JMP: {
b--; /* b = num. returns */ int b = GETARG_sBx(i);
if (b > 0) checkreg(pt, a+b-1); int dest = pc + 1 + b;
/* jump is forward and do not skip `lastpc'? */
if (pc < dest && dest <= lastpc)
pc += b; /* do the jump */
break; break;
} }
case OP_SETLIST: { case OP_TEST: {
if (b > 0) checkreg(pt, a + b); if (reg == a) setreg = pc; /* jumped code can change 'a' */
if (c == 0) {
pc++;
check(pc < pt->sizecode - 1);
}
break; break;
} }
case OP_CLOSURE: { default:
int nup, j; if (testAMode(op) && reg == a) /* any instruction that set A */
check(b < pt->sizep); setreg = pc;
nup = pt->p[b]->nups;
check(pc + nup < pt->sizecode);
for (j = 1; j <= nup; j++) {
OpCode op1 = GET_OPCODE(pt->code[pc + j]);
check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
}
if (reg != NO_REG) /* tracing? */
pc += nup; /* do not 'execute' these pseudo-instructions */
break; break;
}
case OP_VARARG: {
check((pt->is_vararg & VARARG_ISVARARG) &&
!(pt->is_vararg & VARARG_NEEDSARG));
b--;
if (b == LUA_MULTRET) check(checkopenop(pt, pc));
checkreg(pt, a+b-1);
break;
}
default: break;
} }
} }
return pt->code[last]; return setreg;
}
#undef check
#undef checkjump
#undef checkreg
/* }====================================================== */
int luaG_checkcode (const Proto *pt) {
return (symbexec(pt, pt->sizecode, NO_REG) != 0);
}
static const char *kname (Proto *p, int c) {
if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
return svalue(&p->k[INDEXK(c)]);
else
return "?";
} }
static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name) { const char **name) {
if (isLua(ci)) { /* a Lua function? */ int pc;
Proto *p = ci_func(ci)->l.p; *name = luaF_getlocalname(p, reg + 1, lastpc);
int pc = currentpc(L, ci); if (*name) /* is a local? */
Instruction i; return "local";
*name = luaF_getlocalname(p, stackpos+1, pc); /* else try symbolic execution */
if (*name) /* is a local? */ pc = findsetreg(p, lastpc, reg);
return "local"; if (pc != -1) { /* could find instruction? */
i = symbexec(p, pc, stackpos); /* try symbolic execution */ Instruction i = p->code[pc];
lua_assert(pc != -1); OpCode op = GET_OPCODE(i);
switch (GET_OPCODE(i)) { switch (op) {
case OP_GETGLOBAL: {
int g = GETARG_Bx(i); /* global index */
lua_assert(ttisstring(&p->k[g]));
*name = svalue(&p->k[g]);
return "global";
}
case OP_MOVE: { case OP_MOVE: {
int a = GETARG_A(i); int b = GETARG_B(i); /* move from 'b' to 'a' */
int b = GETARG_B(i); /* move from `b' to `a' */ if (b < GETARG_A(i))
if (b < a) return getobjname(p, pc, b, name); /* get name for 'b' */
return getobjname(L, ci, b, name); /* get name for `b' */
break; break;
} }
case OP_GETTABUP:
case OP_GETTABLE: { case OP_GETTABLE: {
int k = GETARG_C(i); /* key index */ int k = GETARG_C(i); /* key index */
*name = kname(p, k); int t = GETARG_B(i); /* table index */
return "field"; const char *vn = (op == OP_GETTABLE) /* name of indexed variable */
? luaF_getlocalname(p, t + 1, pc)
: upvalname(p, t);
kname(p, pc, k, name);
return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
} }
case OP_GETUPVAL: { case OP_GETUPVAL: {
int u = GETARG_B(i); /* upvalue index */ *name = upvalname(p, GETARG_B(i));
*name = p->upvalues ? getstr(p->upvalues[u]) : "?";
return "upvalue"; return "upvalue";
} }
case OP_LOADK:
case OP_LOADKX: {
int b = (op == OP_LOADK) ? GETARG_Bx(i)
: GETARG_Ax(p->code[pc + 1]);
if (ttisstring(&p->k[b])) {
*name = svalue(&p->k[b]);
return "constant";
}
break;
}
case OP_SELF: { case OP_SELF: {
int k = GETARG_C(i); /* key index */ int k = GETARG_C(i); /* key index */
*name = kname(p, k); kname(p, pc, k, name);
return "method"; return "method";
} }
default: break; default: break; /* go through to return NULL */
} }
} }
return NULL; /* no useful name found */ return NULL; /* could not find reasonable name */
} }
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
Instruction i; TMS tm;
if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) Proto *p = ci_func(ci)->p; /* calling function */
return NULL; /* calling function is not Lua (or is unknown) */ int pc = currentpc(ci); /* calling instruction index */
ci--; /* calling function */ Instruction i = p->code[pc]; /* calling instruction */
i = ci_func(ci)->l.p->code[currentpc(L, ci)]; switch (GET_OPCODE(i)) {
if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || case OP_CALL:
GET_OPCODE(i) == OP_TFORLOOP) case OP_TAILCALL: /* get function name */
return getobjname(L, ci, GETARG_A(i), name); return getobjname(p, pc, GETARG_A(i), name);
else case OP_TFORCALL: { /* for iterator */
return NULL; /* no useful name can be found */ *name = "for iterator";
return "for iterator";
}
/* all other instructions can call only through metamethods */
case OP_SELF:
case OP_GETTABUP:
case OP_GETTABLE: tm = TM_INDEX; break;
case OP_SETTABUP:
case OP_SETTABLE: tm = TM_NEWINDEX; break;
case OP_EQ: tm = TM_EQ; break;
case OP_ADD: tm = TM_ADD; break;
case OP_SUB: tm = TM_SUB; break;
case OP_MUL: tm = TM_MUL; break;
case OP_DIV: tm = TM_DIV; break;
case OP_MOD: tm = TM_MOD; break;
case OP_POW: tm = TM_POW; break;
case OP_UNM: tm = TM_UNM; break;
case OP_LEN: tm = TM_LEN; break;
case OP_LT: tm = TM_LT; break;
case OP_LE: tm = TM_LE; break;
case OP_CONCAT: tm = TM_CONCAT; break;
default:
return NULL; /* else no useful name can be found */
}
*name = getstr(G(L)->tmname[tm]);
return "metamethod";
} }
/* }====================================================== */
/* only ANSI way to check whether a pointer points to an array */ /*
** only ANSI way to check whether a pointer points to an array
** (used only for error messages, so efficiency is not a big concern)
*/
static int isinstack (CallInfo *ci, const TValue *o) { static int isinstack (CallInfo *ci, const TValue *o) {
StkId p; StkId p;
for (p = ci->base; p < ci->top; p++) for (p = ci->u.l.base; p < ci->top; p++)
if (o == p) return 1; if (o == p) return 1;
return 0; return 0;
} }
void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { static const char *getupvalname (CallInfo *ci, const TValue *o,
const char **name) {
LClosure *c = ci_func(ci);
int i;
for (i = 0; i < c->nupvalues; i++) {
if (c->upvals[i]->v == o) {
*name = upvalname(c->p, i);
return "upvalue";
}
}
return NULL;
}
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
CallInfo *ci = L->ci;
const char *name = NULL; const char *name = NULL;
const char *t = luaT_typenames[ttype(o)]; const char *t = objtypename(o);
const char *kind = (isinstack(L->ci, o)) ? const char *kind = NULL;
getobjname(L, L->ci, cast_int(o - L->base), &name) : if (isLua(ci)) {
NULL; kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
if (!kind && isinstack(ci, o)) /* no? try a register */
kind = getobjname(ci_func(ci)->p, currentpc(ci),
cast_int(o - ci->u.l.base), &name);
}
if (kind) if (kind)
luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
op, kind, name, t); op, kind, name, t);
@ -578,14 +513,14 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
} }
void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
lua_assert(!ttisstring(p1) && !ttisnumber(p1)); lua_assert(!ttisstring(p1) && !ttisnumber(p2));
luaG_typeerror(L, p1, "concatenate"); luaG_typeerror(L, p1, "concatenate");
} }
void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
TValue temp; TValue temp;
if (luaV_tonumber(p1, &temp) == NULL) if (luaV_tonumber(p1, &temp) == NULL)
p2 = p1; /* first operand is wrong */ p2 = p1; /* first operand is wrong */
@ -593,14 +528,13 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
} }
int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = luaT_typenames[ttype(p1)]; const char *t1 = objtypename(p1);
const char *t2 = luaT_typenames[ttype(p2)]; const char *t2 = objtypename(p2);
if (t1[2] == t2[2]) if (t1 == t2)
luaG_runerror(L, "attempt to compare two %s values", t1); luaG_runerror(L, "attempt to compare two %s values", t1);
else else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2); luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
return 0;
} }
@ -608,27 +542,32 @@ static void addinfo (lua_State *L, const char *msg) {
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
if (isLua(ci)) { /* is Lua code? */ if (isLua(ci)) { /* is Lua code? */
char buff[LUA_IDSIZE]; /* add file:line information */ char buff[LUA_IDSIZE]; /* add file:line information */
int line = currentline(L, ci); int line = currentline(ci);
luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); TString *src = ci_func(ci)->p->source;
if (src)
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
else { /* no source available; use "?" instead */
buff[0] = '?'; buff[1] = '\0';
}
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
} }
} }
void luaG_errormsg (lua_State *L) { l_noret luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */ if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc); StkId errfunc = restorestack(L, L->errfunc);
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
setobjs2s(L, L->top, L->top - 1); /* move argument */ setobjs2s(L, L->top, L->top - 1); /* move argument */
setobjs2s(L, L->top - 1, errfunc); /* push function */ setobjs2s(L, L->top - 1, errfunc); /* push function */
incr_top(L); incr_top(L);
luaD_call(L, L->top - 2, 1); /* call it */ luaD_call(L, L->top - 2, 1, 0); /* call it */
} }
luaD_throw(L, LUA_ERRRUN); luaD_throw(L, LUA_ERRRUN);
} }
void luaG_runerror (lua_State *L, const char *fmt, ...) { l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
va_list argp; va_list argp;
va_start(argp, fmt); va_start(argp, fmt);
addinfo(L, luaO_pushvfstring(L, fmt, argp)); addinfo(L, luaO_pushvfstring(L, fmt, argp));

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ ** $Id: ldo.c,v 2.102 2011/11/29 15:55:08 roberto Exp $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -14,6 +14,7 @@
#include "lua.h" #include "lua.h"
#include "lapi.h"
#include "ldebug.h" #include "ldebug.h"
#include "ldo.h" #include "ldo.h"
#include "lfunc.h" #include "lfunc.h"
@ -39,6 +40,38 @@
** ======================================================= ** =======================================================
*/ */
/*
** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
** default, Lua handles errors with exceptions when compiling as
** C++ code, with _longjmp/_setjmp when asked to use them, and with
** longjmp/setjmp otherwise.
*/
#if !defined(LUAI_THROW)
#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP)
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
#define LUAI_TRY(L,c,a) \
try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int /* dummy variable */
#elif defined(LUA_USE_ULONGJMP)
/* in Unix, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#else
/* default handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#endif
#endif
/* chain list of long jump buffers */ /* chain list of long jump buffers */
struct lua_longjmp { struct lua_longjmp {
@ -48,18 +81,17 @@ struct lua_longjmp {
}; };
void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) { switch (errcode) {
case LUA_ERRMEM: { case LUA_ERRMEM: { /* memory error? */
setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
break; break;
} }
case LUA_ERRERR: { case LUA_ERRERR: {
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break; break;
} }
case LUA_ERRSYNTAX: default: {
case LUA_ERRRUN: {
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
break; break;
} }
@ -68,55 +100,39 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
} }
static void restore_stack_limit (lua_State *L) { l_noret luaD_throw (lua_State *L, int errcode) {
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); if (L->errorJmp) { /* thread has an error handler? */
if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ L->errorJmp->status = errcode; /* set status */
int inuse = cast_int(L->ci - L->base_ci); LUAI_THROW(L, L->errorJmp); /* jump to it */
if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
luaD_reallocCI(L, LUAI_MAXCALLS);
} }
} else { /* thread has no error handler */
L->status = cast_byte(errcode); /* mark it as dead */
if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */
static void resetstack (lua_State *L, int status) { setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */
L->ci = L->base_ci; luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */
L->base = L->ci->base; }
luaF_close(L, L->base); /* close eventual pending closures */ else { /* no handler at all; abort */
luaD_seterrorobj(L, status, L->base); if (G(L)->panic) { /* panic function? */
L->nCcalls = L->baseCcalls; lua_unlock(L);
L->allowhook = 1; G(L)->panic(L); /* call it (last chance to jump out) */
restore_stack_limit(L); }
L->errfunc = 0; abort();
L->errorJmp = NULL;
}
void luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) {
L->errorJmp->status = errcode;
LUAI_THROW(L, L->errorJmp);
}
else {
L->status = cast_byte(errcode);
if (G(L)->panic) {
resetstack(L, errcode);
lua_unlock(L);
G(L)->panic(L);
} }
exit(EXIT_FAILURE);
} }
} }
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
unsigned short oldnCcalls = L->nCcalls;
struct lua_longjmp lj; struct lua_longjmp lj;
lj.status = 0; lj.status = LUA_OK;
lj.previous = L->errorJmp; /* chain new error handler */ lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj; L->errorJmp = &lj;
LUAI_TRY(L, &lj, LUAI_TRY(L, &lj,
(*f)(L, ud); (*f)(L, ud);
); );
L->errorJmp = lj.previous; /* restore old error handler */ L->errorJmp = lj.previous; /* restore old error handler */
L->nCcalls = oldnCcalls;
return lj.status; return lj.status;
} }
@ -129,112 +145,126 @@ static void correctstack (lua_State *L, TValue *oldstack) {
L->top = (L->top - oldstack) + L->stack; L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->gch.next) for (up = L->openupval; up != NULL; up = up->gch.next)
gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
for (ci = L->base_ci; ci <= L->ci; ci++) { for (ci = L->ci; ci != NULL; ci = ci->previous) {
ci->top = (ci->top - oldstack) + L->stack; ci->top = (ci->top - oldstack) + L->stack;
ci->base = (ci->base - oldstack) + L->stack;
ci->func = (ci->func - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack;
if (isLua(ci))
ci->u.l.base = (ci->u.l.base - oldstack) + L->stack;
} }
L->base = (L->base - oldstack) + L->stack;
} }
/* some space for error handling */
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
void luaD_reallocstack (lua_State *L, int newsize) { void luaD_reallocstack (lua_State *L, int newsize) {
TValue *oldstack = L->stack; TValue *oldstack = L->stack;
int realsize = newsize + 1 + EXTRA_STACK; int lim = L->stacksize;
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
L->stacksize = realsize; luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
L->stack_last = L->stack+newsize; for (; lim < newsize; lim++)
setnilvalue(L->stack + lim); /* erase new segment */
L->stacksize = newsize;
L->stack_last = L->stack + newsize - EXTRA_STACK;
correctstack(L, oldstack); correctstack(L, oldstack);
} }
void luaD_reallocCI (lua_State *L, int newsize) { void luaD_growstack (lua_State *L, int n) {
CallInfo *oldci = L->base_ci; int size = L->stacksize;
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); if (size > LUAI_MAXSTACK) /* error after extra size? */
L->size_ci = newsize; luaD_throw(L, LUA_ERRERR);
L->ci = (L->ci - oldci) + L->base_ci; else {
L->end_ci = L->base_ci + L->size_ci - 1; int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
int newsize = 2 * size;
if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
if (newsize < needed) newsize = needed;
if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
luaD_reallocstack(L, ERRORSTACKSIZE);
luaG_runerror(L, "stack overflow");
}
else
luaD_reallocstack(L, newsize);
}
} }
void luaD_growstack (lua_State *L, int n) { static int stackinuse (lua_State *L) {
if (n <= L->stacksize) /* double size is enough? */ CallInfo *ci;
luaD_reallocstack(L, 2*L->stacksize); StkId lim = L->top;
else for (ci = L->ci; ci != NULL; ci = ci->previous) {
luaD_reallocstack(L, L->stacksize + n); lua_assert(ci->top <= L->stack_last);
if (lim < ci->top) lim = ci->top;
}
return cast_int(lim - L->stack) + 1; /* part of stack in use */
} }
static CallInfo *growCI (lua_State *L) { void luaD_shrinkstack (lua_State *L) {
if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ int inuse = stackinuse(L);
luaD_throw(L, LUA_ERRERR); int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
else { if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
luaD_reallocCI(L, 2*L->size_ci); if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */
if (L->size_ci > LUAI_MAXCALLS) goodsize >= L->stacksize) /* would grow instead of shrink? */
luaG_runerror(L, "stack overflow"); condmovestack(L); /* don't change stack (change only for debugging) */
} else
return ++L->ci; luaD_reallocstack(L, goodsize); /* shrink it */
} }
void luaD_callhook (lua_State *L, int event, int line) { void luaD_hook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook; lua_Hook hook = L->hook;
if (hook && L->allowhook) { if (hook && L->allowhook) {
CallInfo *ci = L->ci;
ptrdiff_t top = savestack(L, L->top); ptrdiff_t top = savestack(L, L->top);
ptrdiff_t ci_top = savestack(L, L->ci->top); ptrdiff_t ci_top = savestack(L, ci->top);
lua_Debug ar; lua_Debug ar;
ar.event = event; ar.event = event;
ar.currentline = line; ar.currentline = line;
if (event == LUA_HOOKTAILRET) ar.i_ci = ci;
ar.i_ci = 0; /* tail call; no debug information about it */
else
ar.i_ci = cast_int(L->ci - L->base_ci);
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
L->ci->top = L->top + LUA_MINSTACK; ci->top = L->top + LUA_MINSTACK;
lua_assert(L->ci->top <= L->stack_last); lua_assert(ci->top <= L->stack_last);
L->allowhook = 0; /* cannot call hooks inside a hook */ L->allowhook = 0; /* cannot call hooks inside a hook */
ci->callstatus |= CIST_HOOKED;
lua_unlock(L); lua_unlock(L);
(*hook)(L, &ar); (*hook)(L, &ar);
lua_lock(L); lua_lock(L);
lua_assert(!L->allowhook); lua_assert(!L->allowhook);
L->allowhook = 1; L->allowhook = 1;
L->ci->top = restorestack(L, ci_top); ci->top = restorestack(L, ci_top);
L->top = restorestack(L, top); L->top = restorestack(L, top);
ci->callstatus &= ~CIST_HOOKED;
} }
} }
static void callhook (lua_State *L, CallInfo *ci) {
int hook = LUA_HOOKCALL;
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
if (isLua(ci->previous) &&
GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
ci->callstatus |= CIST_TAIL;
hook = LUA_HOOKTAILCALL;
}
luaD_hook(L, hook, -1);
ci->u.l.savedpc--; /* correct 'pc' */
}
static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
int i; int i;
int nfixargs = p->numparams; int nfixargs = p->numparams;
Table *htab = NULL;
StkId base, fixed; StkId base, fixed;
for (; actual < nfixargs; ++actual) lua_assert(actual >= nfixargs);
setnilvalue(L->top++);
#if defined(LUA_COMPAT_VARARG)
if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
int nvar = actual - nfixargs; /* number of extra arguments */
lua_assert(p->is_vararg & VARARG_HASARG);
luaC_checkGC(L);
htab = luaH_new(L, nvar, 1); /* create `arg' table */
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
/* store counter in field `n' */
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
}
#endif
/* move fixed parameters to final position */ /* move fixed parameters to final position */
fixed = L->top - actual; /* first fixed argument */ fixed = L->top - actual; /* first fixed argument */
base = L->top; /* final position of first argument */ base = L->top; /* final position of first argument */
for (i=0; i<nfixargs; i++) { for (i=0; i<nfixargs; i++) {
setobjs2s(L, L->top++, fixed+i); setobjs2s(L, L->top++, fixed + i);
setnilvalue(fixed+i); setnilvalue(fixed + i);
}
/* add `arg' parameter */
if (htab) {
sethvalue(L, L->top++, htab);
lua_assert(iswhite(obj2gco(htab)));
} }
return base; return base;
} }
@ -256,100 +286,85 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
#define inc_ci(L) \ #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
((L->ci == L->end_ci) ? growCI(L) : \
(condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
/*
** returns true if function has been executed (C function)
*/
int luaD_precall (lua_State *L, StkId func, int nresults) { int luaD_precall (lua_State *L, StkId func, int nresults) {
LClosure *cl; lua_CFunction f;
ptrdiff_t funcr; CallInfo *ci;
if (!ttisfunction(func)) /* `func' is not a function? */ int n; /* number of arguments (Lua) or returns (C) */
func = tryfuncTM(L, func); /* check the `function' tag method */ ptrdiff_t funcr = savestack(L, func);
funcr = savestack(L, func); switch (ttype(func)) {
cl = &clvalue(func)->l; case LUA_TLCF: /* light C function */
L->ci->savedpc = L->savedpc; f = fvalue(func);
if (!cl->isC) { /* Lua function? prepare its call */ goto Cfunc;
CallInfo *ci; case LUA_TCCL: { /* C closure */
StkId st, base; f = clCvalue(func)->f;
Proto *p = cl->p; Cfunc:
luaD_checkstack(L, p->maxstacksize); luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
func = restorestack(L, funcr); ci = next_ci(L); /* now 'enter' new function */
if (!p->is_vararg) { /* no varargs? */ ci->nresults = nresults;
base = func + 1; ci->func = restorestack(L, funcr);
if (L->top > base + p->numparams) ci->top = L->top + LUA_MINSTACK;
L->top = base + p->numparams; lua_assert(ci->top <= L->stack_last);
} ci->callstatus = 0;
else { /* vararg function */ if (L->hookmask & LUA_MASKCALL)
int nargs = cast_int(L->top - func) - 1; luaD_hook(L, LUA_HOOKCALL, -1);
base = adjust_varargs(L, p, nargs); lua_unlock(L);
func = restorestack(L, funcr); /* previous call may change the stack */ n = (*f)(L); /* do the actual call */
lua_lock(L);
api_checknelems(L, n);
luaD_poscall(L, L->top - n);
return 1;
} }
ci = inc_ci(L); /* now `enter' new function */ case LUA_TLCL: { /* Lua function: prepare its call */
ci->func = func; StkId base;
L->base = ci->base = base; Proto *p = clLvalue(func)->p;
ci->top = L->base + p->maxstacksize; luaD_checkstack(L, p->maxstacksize);
lua_assert(ci->top <= L->stack_last); func = restorestack(L, funcr);
L->savedpc = p->code; /* starting point */ n = cast_int(L->top - func) - 1; /* number of real arguments */
ci->tailcalls = 0; for (; n < p->numparams; n++)
ci->nresults = nresults; setnilvalue(L->top++); /* complete missing arguments */
for (st = L->top; st < ci->top; st++) base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n);
setnilvalue(st); ci = next_ci(L); /* now 'enter' new function */
L->top = ci->top; ci->nresults = nresults;
if (L->hookmask & LUA_MASKCALL) { ci->func = func;
L->savedpc++; /* hooks assume 'pc' is already incremented */ ci->u.l.base = base;
luaD_callhook(L, LUA_HOOKCALL, -1); ci->top = base + p->maxstacksize;
L->savedpc--; /* correct 'pc' */ lua_assert(ci->top <= L->stack_last);
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = CIST_LUA;
L->top = ci->top;
if (L->hookmask & LUA_MASKCALL)
callhook(L, ci);
return 0;
} }
return PCRLUA; default: { /* not a function */
} func = tryfuncTM(L, func); /* retry with 'function' tag method */
else { /* if is a C function, call it */ return luaD_precall(L, func, nresults); /* now it must be a function */
CallInfo *ci;
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci = inc_ci(L); /* now `enter' new function */
ci->func = restorestack(L, funcr);
L->base = ci->base = ci->func + 1;
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
ci->nresults = nresults;
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
n = (*curr_func(L)->c.f)(L); /* do the actual call */
lua_lock(L);
if (n < 0) /* yielding? */
return PCRYIELD;
else {
luaD_poscall(L, L->top - n);
return PCRC;
} }
} }
} }
static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
if (f_isLua(L->ci)) { /* Lua function? */
while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
}
int luaD_poscall (lua_State *L, StkId firstResult) { int luaD_poscall (lua_State *L, StkId firstResult) {
StkId res; StkId res;
int wanted, i; int wanted, i;
CallInfo *ci; CallInfo *ci = L->ci;
if (L->hookmask & LUA_MASKRET) if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
firstResult = callrethooks(L, firstResult); if (L->hookmask & LUA_MASKRET) {
ci = L->ci--; ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
luaD_hook(L, LUA_HOOKRET, -1);
firstResult = restorestack(L, fr);
}
L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
}
res = ci->func; /* res == final position of 1st result */ res = ci->func; /* res == final position of 1st result */
wanted = ci->nresults; wanted = ci->nresults;
L->base = (ci - 1)->base; /* restore base */ L->ci = ci = ci->previous; /* back to caller */
L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
/* move results to correct place */ /* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--) for (i = wanted; i != 0 && firstResult < L->top; i--)
setobjs2s(L, res++, firstResult++); setobjs2s(L, res++, firstResult++);
@ -365,112 +380,223 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
** The arguments are on the stack, right after the function. ** The arguments are on the stack, right after the function.
** When returns, all the results are on the stack, starting at the original ** When returns, all the results are on the stack, starting at the original
** function position. ** function position.
*/ */
void luaD_call (lua_State *L, StkId func, int nResults) { void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
if (++L->nCcalls >= LUAI_MAXCCALLS) { if (++L->nCcalls >= LUAI_MAXCCALLS) {
if (L->nCcalls == LUAI_MAXCCALLS) if (L->nCcalls == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow"); luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
} }
if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ if (!allowyield) L->nny++;
luaV_execute(L, 1); /* call it */ if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
luaV_execute(L); /* call it */
if (!allowyield) L->nny--;
L->nCcalls--; L->nCcalls--;
luaC_checkGC(L); luaC_checkGC(L);
} }
static void resume (lua_State *L, void *ud) { static void finishCcall (lua_State *L) {
StkId firstArg = cast(StkId, ud);
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
if (L->status == 0) { /* start coroutine? */ int n;
lua_assert(ci == L->base_ci && firstArg > L->base); lua_assert(ci->u.c.k != NULL); /* must have a continuation */
if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) lua_assert(L->nny == 0);
return; /* finish 'luaD_call' */
} L->nCcalls--;
else { /* resuming from previous yield */ /* finish 'lua_callk' */
lua_assert(L->status == LUA_YIELD); adjustresults(L, ci->nresults);
L->status = 0; /* call continuation function */
if (!f_isLua(ci)) { /* `common' yield? */ if (!(ci->callstatus & CIST_STAT)) /* no call status? */
/* finish interrupted execution of `OP_CALL' */ ci->u.c.status = LUA_YIELD; /* 'default' status */
lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || lua_assert(ci->u.c.status != LUA_OK);
GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
if (luaD_poscall(L, firstArg)) /* complete it... */ lua_unlock(L);
L->top = L->ci->top; /* and correct top if not multiple results */ n = (*ci->u.c.k)(L);
lua_lock(L);
api_checknelems(L, n);
/* finish 'luaD_precall' */
luaD_poscall(L, L->top - n);
}
static void unroll (lua_State *L, void *ud) {
UNUSED(ud);
for (;;) {
if (L->ci == &L->base_ci) /* stack is empty? */
return; /* coroutine finished normally */
if (!isLua(L->ci)) /* C function? */
finishCcall(L);
else { /* Lua function */
luaV_finishOp(L); /* finish interrupted instruction */
luaV_execute(L); /* execute down to higher C 'boundary' */
} }
else /* yielded inside a hook: just continue its execution */
L->base = L->ci->base;
} }
luaV_execute(L, cast_int(L->ci - L->base_ci));
} }
static int resume_error (lua_State *L, const char *msg) { /*
L->top = L->ci->base; ** check whether thread has a suspended protected call
setsvalue2s(L, L->top, luaS_new(L, msg)); */
static CallInfo *findpcall (lua_State *L) {
CallInfo *ci;
for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
if (ci->callstatus & CIST_YPCALL)
return ci;
}
return NULL; /* no pending pcall */
}
static int recover (lua_State *L, int status) {
StkId oldtop;
CallInfo *ci = findpcall(L);
if (ci == NULL) return 0; /* no recovery point */
/* "finish" luaD_pcall */
oldtop = restorestack(L, ci->u.c.extra);
luaF_close(L, oldtop);
seterrorobj(L, status, oldtop);
L->ci = ci;
L->allowhook = ci->u.c.old_allowhook;
L->nny = 0; /* should be zero to be yieldable */
luaD_shrinkstack(L);
L->errfunc = ci->u.c.old_errfunc;
ci->callstatus |= CIST_STAT; /* call has error status */
ci->u.c.status = status; /* (here it is) */
return 1; /* continue running the coroutine */
}
/*
** signal an error in the call to 'resume', not in the execution of the
** coroutine itself. (Such errors should not be handled by any coroutine
** error handler and should not kill the coroutine.)
*/
static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
L->top = firstArg; /* remove args from the stack */
setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
incr_top(L); incr_top(L);
lua_unlock(L); luaD_throw(L, -1); /* jump back to 'lua_resume' */
return LUA_ERRRUN;
} }
LUA_API int lua_resume (lua_State *L, int nargs) { /*
** do the work for 'lua_resume' in protected mode
*/
static void resume (lua_State *L, void *ud) {
StkId firstArg = cast(StkId, ud);
CallInfo *ci = L->ci;
if (L->nCcalls >= LUAI_MAXCCALLS)
resume_error(L, "C stack overflow", firstArg);
if (L->status == LUA_OK) { /* may be starting a coroutine */
if (ci != &L->base_ci) /* not in base level? */
resume_error(L, "cannot resume non-suspended coroutine", firstArg);
/* coroutine is in base level; start running it */
if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
luaV_execute(L); /* call it */
}
else if (L->status != LUA_YIELD)
resume_error(L, "cannot resume dead coroutine", firstArg);
else { /* resuming from previous yield */
L->status = LUA_OK;
if (isLua(ci)) /* yielded inside a hook? */
luaV_execute(L); /* just continue running Lua code */
else { /* 'common' yield */
ci->func = restorestack(L, ci->u.c.extra);
if (ci->u.c.k != NULL) { /* does it have a continuation? */
int n;
ci->u.c.status = LUA_YIELD; /* 'default' status */
ci->callstatus |= CIST_YIELDED;
lua_unlock(L);
n = (*ci->u.c.k)(L); /* call continuation */
lua_lock(L);
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
L->nCcalls--; /* finish 'luaD_call' */
luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
}
unroll(L, NULL);
}
}
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
int status; int status;
lua_lock(L); lua_lock(L);
if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
return resume_error(L, "cannot resume non-suspended coroutine");
if (L->nCcalls >= LUAI_MAXCCALLS)
return resume_error(L, "C stack overflow");
luai_userstateresume(L, nargs); luai_userstateresume(L, nargs);
lua_assert(L->errfunc == 0); L->nCcalls = (from) ? from->nCcalls + 1 : 1;
L->baseCcalls = ++L->nCcalls; L->nny = 0; /* allow yields */
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, L->top - nargs); status = luaD_rawrunprotected(L, resume, L->top - nargs);
if (status != 0) { /* error? */ if (status == -1) /* error calling 'lua_resume'? */
L->status = cast_byte(status); /* mark thread as `dead' */ status = LUA_ERRRUN;
luaD_seterrorobj(L, status, L->top); else { /* yield or regular error */
L->ci->top = L->top; while (status != LUA_OK && status != LUA_YIELD) { /* error? */
} if (recover(L, status)) /* recover point? */
else { status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */
lua_assert(L->nCcalls == L->baseCcalls); else { /* unrecoverable error */
status = L->status; L->status = cast_byte(status); /* mark thread as `dead' */
seterrorobj(L, status, L->top);
L->ci->top = L->top;
break;
}
}
lua_assert(status == L->status);
} }
--L->nCcalls; L->nny = 1; /* do not allow yields */
L->nCcalls--;
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
lua_unlock(L); lua_unlock(L);
return status; return status;
} }
LUA_API int lua_yield (lua_State *L, int nresults) { LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
CallInfo *ci = L->ci;
luai_userstateyield(L, nresults); luai_userstateyield(L, nresults);
lua_lock(L); lua_lock(L);
if (L->nCcalls > L->baseCcalls) api_checknelems(L, nresults);
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); if (L->nny > 0) {
L->base = L->top - nresults; /* protect stack slots below */ if (L != G(L)->mainthread)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
else
luaG_runerror(L, "attempt to yield from outside a coroutine");
}
L->status = LUA_YIELD; L->status = LUA_YIELD;
if (isLua(ci)) { /* inside a hook? */
api_check(L, k == NULL, "hooks cannot continue after yielding");
}
else {
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
ci->u.c.ctx = ctx; /* save context */
ci->u.c.extra = savestack(L, ci->func); /* save current 'func' */
ci->func = L->top - nresults - 1; /* protect stack below results */
luaD_throw(L, LUA_YIELD);
}
lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
lua_unlock(L); lua_unlock(L);
return -1; return 0; /* return to 'luaD_hook' */
} }
int luaD_pcall (lua_State *L, Pfunc func, void *u, int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) { ptrdiff_t old_top, ptrdiff_t ef) {
int status; int status;
unsigned short oldnCcalls = L->nCcalls; CallInfo *old_ci = L->ci;
ptrdiff_t old_ci = saveci(L, L->ci);
lu_byte old_allowhooks = L->allowhook; lu_byte old_allowhooks = L->allowhook;
unsigned short old_nny = L->nny;
ptrdiff_t old_errfunc = L->errfunc; ptrdiff_t old_errfunc = L->errfunc;
L->errfunc = ef; L->errfunc = ef;
status = luaD_rawrunprotected(L, func, u); status = luaD_rawrunprotected(L, func, u);
if (status != 0) { /* an error occurred? */ if (status != LUA_OK) { /* an error occurred? */
StkId oldtop = restorestack(L, old_top); StkId oldtop = restorestack(L, old_top);
luaF_close(L, oldtop); /* close eventual pending closures */ luaF_close(L, oldtop); /* close possible pending closures */
luaD_seterrorobj(L, status, oldtop); seterrorobj(L, status, oldtop);
L->nCcalls = oldnCcalls; L->ci = old_ci;
L->ci = restoreci(L, old_ci);
L->base = L->ci->base;
L->savedpc = L->ci->savedpc;
L->allowhook = old_allowhooks; L->allowhook = old_allowhooks;
restore_stack_limit(L); L->nny = old_nny;
luaD_shrinkstack(L);
} }
L->errfunc = old_errfunc; L->errfunc = old_errfunc;
return status; return status;
@ -483,35 +609,61 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
*/ */
struct SParser { /* data to `f_parser' */ struct SParser { /* data to `f_parser' */
ZIO *z; ZIO *z;
Mbuffer buff; /* buffer to be used by the scanner */ Mbuffer buff; /* dynamic structure used by the scanner */
Dyndata dyd; /* dynamic structures used by the parser */
const char *mode;
const char *name; const char *name;
}; };
static void checkmode (lua_State *L, const char *mode, const char *x) {
if (mode && strchr(mode, x[0]) == NULL) {
luaO_pushfstring(L,
"attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
luaD_throw(L, LUA_ERRSYNTAX);
}
}
static void f_parser (lua_State *L, void *ud) { static void f_parser (lua_State *L, void *ud) {
int i; int i;
Proto *tf; Proto *tf;
Closure *cl; Closure *cl;
struct SParser *p = cast(struct SParser *, ud); struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z); int c = zgetc(p->z); /* read first character */
luaC_checkGC(L); if (c == LUA_SIGNATURE[0]) {
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, checkmode(L, p->mode, "binary");
&p->buff, p->name); tf = luaU_undump(L, p->z, &p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); }
cl->l.p = tf; else {
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ checkmode(L, p->mode, "text");
cl->l.upvals[i] = luaF_newupval(L); tf = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
setclvalue(L, L->top, cl); }
setptvalue2s(L, L->top, tf);
incr_top(L); incr_top(L);
cl = luaF_newLclosure(L, tf);
setclLvalue(L, L->top - 1, cl);
for (i = 0; i < tf->sizeupvalues; i++) /* initialize upvalues */
cl->l.upvals[i] = luaF_newupval(L);
} }
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode) {
struct SParser p; struct SParser p;
int status; int status;
p.z = z; p.name = name; L->nny++; /* cannot yield during parsing */
p.z = z; p.name = name; p.mode = mode;
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff); luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff); luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
L->nny--;
return status; return status;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: ldump.c,v 1.19 2011/11/23 17:48:18 lhf Exp $
** save precompiled Lua chunks ** save precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -24,7 +24,7 @@ typedef struct {
} DumpState; } DumpState;
#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) #define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) #define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
static void DumpBlock(const void* b, size_t size, DumpState* D) static void DumpBlock(const void* b, size_t size, DumpState* D)
{ {
@ -60,7 +60,7 @@ static void DumpVector(const void* b, int n, size_t size, DumpState* D)
static void DumpString(const TString* s, DumpState* D) static void DumpString(const TString* s, DumpState* D)
{ {
if (s==NULL || getstr(s)==NULL) if (s==NULL)
{ {
size_t size=0; size_t size=0;
DumpVar(size,D); DumpVar(size,D);
@ -69,13 +69,13 @@ static void DumpString(const TString* s, DumpState* D)
{ {
size_t size=s->tsv.len+1; /* include trailing '\0' */ size_t size=s->tsv.len+1; /* include trailing '\0' */
DumpVar(size,D); DumpVar(size,D);
DumpBlock(getstr(s),size,D); DumpBlock(getstr(s),size*sizeof(char),D);
} }
} }
#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) #define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
static void DumpFunction(const Proto* f, const TString* p, DumpState* D); static void DumpFunction(const Proto* f, DumpState* D);
static void DumpConstants(const Proto* f, DumpState* D) static void DumpConstants(const Proto* f, DumpState* D)
{ {
@ -98,19 +98,28 @@ static void DumpConstants(const Proto* f, DumpState* D)
case LUA_TSTRING: case LUA_TSTRING:
DumpString(rawtsvalue(o),D); DumpString(rawtsvalue(o),D);
break; break;
default:
lua_assert(0); /* cannot happen */
break;
} }
} }
n=f->sizep; n=f->sizep;
DumpInt(n,D); DumpInt(n,D);
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); for (i=0; i<n; i++) DumpFunction(f->p[i],D);
}
static void DumpUpvalues(const Proto* f, DumpState* D)
{
int i,n=f->sizeupvalues;
DumpInt(n,D);
for (i=0; i<n; i++)
{
DumpChar(f->upvalues[i].instack,D);
DumpChar(f->upvalues[i].idx,D);
}
} }
static void DumpDebug(const Proto* f, DumpState* D) static void DumpDebug(const Proto* f, DumpState* D)
{ {
int i,n; int i,n;
DumpString((D->strip) ? NULL : f->source,D);
n= (D->strip) ? 0 : f->sizelineinfo; n= (D->strip) ? 0 : f->sizelineinfo;
DumpVector(f->lineinfo,n,sizeof(int),D); DumpVector(f->lineinfo,n,sizeof(int),D);
n= (D->strip) ? 0 : f->sizelocvars; n= (D->strip) ? 0 : f->sizelocvars;
@ -123,26 +132,25 @@ static void DumpDebug(const Proto* f, DumpState* D)
} }
n= (D->strip) ? 0 : f->sizeupvalues; n= (D->strip) ? 0 : f->sizeupvalues;
DumpInt(n,D); DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f->upvalues[i],D); for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D);
} }
static void DumpFunction(const Proto* f, const TString* p, DumpState* D) static void DumpFunction(const Proto* f, DumpState* D)
{ {
DumpString((f->source==p || D->strip) ? NULL : f->source,D);
DumpInt(f->linedefined,D); DumpInt(f->linedefined,D);
DumpInt(f->lastlinedefined,D); DumpInt(f->lastlinedefined,D);
DumpChar(f->nups,D);
DumpChar(f->numparams,D); DumpChar(f->numparams,D);
DumpChar(f->is_vararg,D); DumpChar(f->is_vararg,D);
DumpChar(f->maxstacksize,D); DumpChar(f->maxstacksize,D);
DumpCode(f,D); DumpCode(f,D);
DumpConstants(f,D); DumpConstants(f,D);
DumpUpvalues(f,D);
DumpDebug(f,D); DumpDebug(f,D);
} }
static void DumpHeader(DumpState* D) static void DumpHeader(DumpState* D)
{ {
char h[LUAC_HEADERSIZE]; lu_byte h[LUAC_HEADERSIZE];
luaU_header(h); luaU_header(h);
DumpBlock(h,LUAC_HEADERSIZE,D); DumpBlock(h,LUAC_HEADERSIZE,D);
} }
@ -159,6 +167,6 @@ int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip
D.strip=strip; D.strip=strip;
D.status=0; D.status=0;
DumpHeader(&D); DumpHeader(&D);
DumpFunction(f,NULL,&D); DumpFunction(f,&D);
return D.status; return D.status;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ ** $Id: lfunc.c,v 2.27 2010/06/30 14:11:17 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures ** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -20,30 +20,27 @@
Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { Closure *luaF_newCclosure (lua_State *L, int n) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeCclosure(n), NULL, 0)->cl;
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->c.isC = 1; c->c.isC = 1;
c->c.env = e; c->c.nupvalues = cast_byte(n);
c->c.nupvalues = cast_byte(nelems);
return c; return c;
} }
Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { Closure *luaF_newLclosure (lua_State *L, Proto *p) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); int n = p->sizeupvalues;
luaC_link(L, obj2gco(c), LUA_TFUNCTION); Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeLclosure(n), NULL, 0)->cl;
c->l.isC = 0; c->l.isC = 0;
c->l.env = e; c->l.p = p;
c->l.nupvalues = cast_byte(nelems); c->l.nupvalues = cast_byte(n);
while (nelems--) c->l.upvals[nelems] = NULL; while (n--) c->l.upvals[n] = NULL;
return c; return c;
} }
UpVal *luaF_newupval (lua_State *L) { UpVal *luaF_newupval (lua_State *L) {
UpVal *uv = luaM_new(L, UpVal); UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv;
luaC_link(L, obj2gco(uv), LUA_TUPVAL);
uv->v = &uv->u.value; uv->v = &uv->u.value;
setnilvalue(uv->v); setnilvalue(uv->v);
return uv; return uv;
@ -55,21 +52,20 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
GCObject **pp = &L->openupval; GCObject **pp = &L->openupval;
UpVal *p; UpVal *p;
UpVal *uv; UpVal *uv;
while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
GCObject *o = obj2gco(p);
lua_assert(p->v != &p->u.value); lua_assert(p->v != &p->u.value);
if (p->v == level) { /* found a corresponding upvalue? */ if (p->v == level) { /* found a corresponding upvalue? */
if (isdead(g, obj2gco(p))) /* is it dead? */ if (isdead(g, o)) /* is it dead? */
changewhite(obj2gco(p)); /* ressurect it */ changewhite(o); /* resurrect it */
return p; return p;
} }
resetoldbit(o); /* may create a newer upval after this one */
pp = &p->next; pp = &p->next;
} }
uv = luaM_new(L, UpVal); /* not found: create a new one */ /* not found: create a new one */
uv->tt = LUA_TUPVAL; uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv;
uv->marked = luaC_white(g);
uv->v = level; /* current value lives in the stack */ uv->v = level; /* current value lives in the stack */
uv->next = *pp; /* chain it in the proper position */
*pp = obj2gco(uv);
uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
uv->u.l.next = g->uvhead.u.l.next; uv->u.l.next = g->uvhead.u.l.next;
uv->u.l.next->u.l.prev = uv; uv->u.l.next->u.l.prev = uv;
@ -96,41 +92,42 @@ void luaF_freeupval (lua_State *L, UpVal *uv) {
void luaF_close (lua_State *L, StkId level) { void luaF_close (lua_State *L, StkId level) {
UpVal *uv; UpVal *uv;
global_State *g = G(L); global_State *g = G(L);
while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) {
GCObject *o = obj2gco(uv); GCObject *o = obj2gco(uv);
lua_assert(!isblack(o) && uv->v != &uv->u.value); lua_assert(!isblack(o) && uv->v != &uv->u.value);
L->openupval = uv->next; /* remove from `open' list */ L->openupval = uv->next; /* remove from `open' list */
if (isdead(g, o)) if (isdead(g, o))
luaF_freeupval(L, uv); /* free upvalue */ luaF_freeupval(L, uv); /* free upvalue */
else { else {
unlinkupval(uv); unlinkupval(uv); /* remove upvalue from 'uvhead' list */
setobj(L, &uv->u.value, uv->v); setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
uv->v = &uv->u.value; /* now current value lives here */ uv->v = &uv->u.value; /* now current value lives here */
luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */
g->allgc = o;
luaC_checkupvalcolor(g, uv);
} }
} }
} }
Proto *luaF_newproto (lua_State *L) { Proto *luaF_newproto (lua_State *L) {
Proto *f = luaM_new(L, Proto); Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p;
luaC_link(L, obj2gco(f), LUA_TPROTO);
f->k = NULL; f->k = NULL;
f->sizek = 0; f->sizek = 0;
f->p = NULL; f->p = NULL;
f->sizep = 0; f->sizep = 0;
f->code = NULL; f->code = NULL;
f->cache = NULL;
f->sizecode = 0; f->sizecode = 0;
f->lineinfo = NULL;
f->sizelineinfo = 0; f->sizelineinfo = 0;
f->sizeupvalues = 0;
f->nups = 0;
f->upvalues = NULL; f->upvalues = NULL;
f->sizeupvalues = 0;
f->numparams = 0; f->numparams = 0;
f->is_vararg = 0; f->is_vararg = 0;
f->maxstacksize = 0; f->maxstacksize = 0;
f->lineinfo = NULL;
f->sizelocvars = 0;
f->locvars = NULL; f->locvars = NULL;
f->sizelocvars = 0;
f->linedefined = 0; f->linedefined = 0;
f->lastlinedefined = 0; f->lastlinedefined = 0;
f->source = NULL; f->source = NULL;
@ -139,12 +136,12 @@ Proto *luaF_newproto (lua_State *L) {
void luaF_freeproto (lua_State *L, Proto *f) { void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->code, f->sizecode, Instruction); luaM_freearray(L, f->code, f->sizecode);
luaM_freearray(L, f->p, f->sizep, Proto *); luaM_freearray(L, f->p, f->sizep);
luaM_freearray(L, f->k, f->sizek, TValue); luaM_freearray(L, f->k, f->sizek);
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); luaM_freearray(L, f->lineinfo, f->sizelineinfo);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); luaM_freearray(L, f->locvars, f->sizelocvars);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); luaM_freearray(L, f->upvalues, f->sizeupvalues);
luaM_free(L, f); luaM_free(L, f);
} }

File diff suppressed because it is too large Load Diff

@ -1,10 +1,18 @@
/* /*
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $
** Initialization of libraries for lua.c ** Initialization of libraries for lua.c and other clients
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
/*
** If you embed Lua in your program and need to open the standard
** libraries, call luaL_openlibs in your program. If you need a
** different set of libraries, copy this file to your project and edit
** it to suit your needs.
*/
#define linit_c #define linit_c
#define LUA_LIB #define LUA_LIB
@ -12,28 +20,48 @@
#include "lualib.h" #include "lualib.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "bit.h"
static const luaL_Reg lualibs[] = {
{"", luaopen_base}, /*
** these libs are loaded by lua.c and are readily available to any Lua
** program
*/
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package}, {LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table}, {LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io}, {LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os}, {LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string}, {LUA_STRLIBNAME, luaopen_string},
{LUA_BITLIBNAME, luaopen_bit32},
{LUA_MATHLIBNAME, luaopen_math}, {LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug}, {LUA_DBLIBNAME, luaopen_debug},
{"bit",luaopen_bit}, {NULL, NULL}
};
/*
** these libs are preloaded and must be required before used
*/
static const luaL_Reg preloadedlibs[] = {
{NULL, NULL} {NULL, NULL}
}; };
LUALIB_API void luaL_openlibs (lua_State *L) { LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib = lualibs; const luaL_Reg *lib;
for (; lib->func; lib++) { /* call open functions from 'loadedlibs' and set results to global table */
for (lib = loadedlibs; lib->func; lib++) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1); /* remove lib */
}
/* add open functions from 'preloadedlibs' into 'package.preload' table */
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
for (lib = preloadedlibs; lib->func; lib++) {
lua_pushcfunction(L, lib->func); lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name); lua_setfield(L, -2, lib->name);
lua_call(L, 1, 0);
} }
lua_pop(L, 1); /* remove _PRELOAD table */
} }

@ -1,10 +1,20 @@
/* /*
** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ ** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $
** Standard I/O (and system) library ** Standard I/O (and system) library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
/*
** POSIX idiosyncrasy!
** This definition must come before the inclusion of 'stdio.h'; it
** should not affect non-POSIX systems
*/
#if !defined(_FILE_OFFSET_BITS)
#define _FILE_OFFSET_BITS 64
#endif
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -20,48 +30,95 @@
#define IO_INPUT 1 /*
#define IO_OUTPUT 2 ** {======================================================
** lua_popen spawns a new process connected to the current
** one through the file streams.
** =======================================================
*/
#if !defined(lua_popen) /* { */
#if defined(LUA_USE_POPEN) /* { */
static const char *const fnames[] = {"input", "output"}; #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
#define lua_pclose(L,file) ((void)L, pclose(file))
#elif defined(LUA_WIN) /* }{ */
static int pushresult (lua_State *L, int i, const char *filename) { #define lua_popen(L,c,m) ((void)L, _popen(c,m))
int en = errno; /* calls to Lua API may change this value */ #define lua_pclose(L,file) ((void)L, _pclose(file))
if (i) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
}
static void fileerror (lua_State *L, int arg, const char *filename) { #else /* }{ */
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
luaL_argerror(L, arg, lua_tostring(L, -1)); #define lua_popen(L,c,m) ((void)((void)c, m), \
} luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
#define lua_pclose(L,file) ((void)((void)L, file), -1)
#endif /* } */
#endif /* } */
/* }====================================================== */
/*
** {======================================================
** lua_fseek/lua_ftell: configuration for longer offsets
** =======================================================
*/
#if !defined(lua_fseek) /* { */
#if defined(LUA_USE_POSIX)
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
&& defined(_MSC_VER) && (_MSC_VER >= 1400)
/* Windows (but not DDK) and Visual C++ 2005 or higher */
#define l_fseek(f,o,w) _fseeki64(f,o,w)
#define l_ftell(f) _ftelli64(f)
#define l_seeknum __int64
#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) #else
#define l_fseek(f,o,w) fseek(f,o,w)
#define l_ftell(f) ftell(f)
#define l_seeknum long
#endif
#endif /* } */
/* }====================================================== */
#define IO_PREFIX "_IO_"
#define IO_INPUT (IO_PREFIX "input")
#define IO_OUTPUT (IO_PREFIX "output")
typedef luaL_Stream LStream;
#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
#define isclosed(p) ((p)->closef == NULL)
static int io_type (lua_State *L) { static int io_type (lua_State *L) {
void *ud; LStream *p;
luaL_checkany(L, 1); luaL_checkany(L, 1);
ud = lua_touserdata(L, 1); p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); if (p == NULL)
if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
lua_pushnil(L); /* not a file */ lua_pushnil(L); /* not a file */
else if (*((FILE **)ud) == NULL) else if (isclosed(p))
lua_pushliteral(L, "closed file"); lua_pushliteral(L, "closed file");
else else
lua_pushliteral(L, "file"); lua_pushliteral(L, "file");
@ -69,47 +126,59 @@ static int io_type (lua_State *L) {
} }
static int f_tostring (lua_State *L) {
LStream *p = tolstream(L);
if (isclosed(p))
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%p)", p->f);
return 1;
}
static FILE *tofile (lua_State *L) { static FILE *tofile (lua_State *L) {
FILE **f = tofilep(L); LStream *p = tolstream(L);
if (*f == NULL) if (isclosed(p))
luaL_error(L, "attempt to use a closed file"); luaL_error(L, "attempt to use a closed file");
return *f; lua_assert(p->f);
return p->f;
} }
/* /*
** When creating file handles, always creates a `closed' file handle ** When creating file handles, always creates a `closed' file handle
** before opening the actual file; so, if there is a memory error, the ** before opening the actual file; so, if there is a memory error, the
** file is not left opened. ** file is not left opened.
*/ */
static FILE **newfile (lua_State *L) { static LStream *newprefile (lua_State *L) {
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
*pf = NULL; /* file handle is currently `closed' */ p->closef = NULL; /* mark file handle as 'closed' */
luaL_getmetatable(L, LUA_FILEHANDLE); luaL_setmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2); return p;
return pf;
} }
/* static int aux_close (lua_State *L) {
** function to (not) close the standard files stdin, stdout, and stderr LStream *p = tolstream(L);
*/ lua_CFunction cf = p->closef;
static int io_noclose (lua_State *L) { p->closef = NULL; /* mark stream as closed */
lua_pushnil(L); return (*cf)(L); /* close it */
lua_pushliteral(L, "cannot close standard file");
return 2;
} }
/* static int io_close (lua_State *L) {
** function to close 'popen' files if (lua_isnone(L, 1)) /* no argument? */
*/ lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
static int io_pclose (lua_State *L) { tofile(L); /* make sure argument is an open stream */
FILE **p = tofilep(L); return aux_close(L);
int ok = lua_pclose(L, *p); }
*p = NULL;
return pushresult(L, ok, NULL);
static int f_gc (lua_State *L) {
LStream *p = tolstream(L);
if (!isclosed(p) && p->f != NULL)
aux_close(L); /* ignore closed and incompletely open files */
return 0;
} }
@ -117,103 +186,94 @@ static int io_pclose (lua_State *L) {
** function to close regular files ** function to close regular files
*/ */
static int io_fclose (lua_State *L) { static int io_fclose (lua_State *L) {
FILE **p = tofilep(L); LStream *p = tolstream(L);
int ok = (fclose(*p) == 0); int res = fclose(p->f);
*p = NULL; return luaL_fileresult(L, (res == 0), NULL);
return pushresult(L, ok, NULL);
}
static int aux_close (lua_State *L) {
lua_getfenv(L, 1);
lua_getfield(L, -1, "__close");
return (lua_tocfunction(L, -1))(L);
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1))
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
tofile(L); /* make sure argument is a file */
return aux_close(L);
} }
static int io_gc (lua_State *L) { static LStream *newfile (lua_State *L) {
FILE *f = *tofilep(L); LStream *p = newprefile(L);
/* ignore closed files */ p->f = NULL;
if (f != NULL) p->closef = &io_fclose;
aux_close(L); return p;
return 0;
} }
static int io_tostring (lua_State *L) { static void opencheck (lua_State *L, const char *fname, const char *mode) {
FILE *f = *tofilep(L); LStream *p = newfile(L);
if (f == NULL) p->f = fopen(fname, mode);
lua_pushliteral(L, "file (closed)"); if (p->f == NULL)
else luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
lua_pushfstring(L, "file (%p)", f);
return 1;
} }
static int io_open (lua_State *L) { static int io_open (lua_State *L) {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r"); const char *mode = luaL_optstring(L, 2, "r");
FILE **pf = newfile(L); LStream *p = newfile(L);
*pf = fopen(filename, mode); int i = 0;
return (*pf == NULL) ? pushresult(L, 0, filename) : 1; /* check whether 'mode' matches '[rwa]%+?b?' */
if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL &&
(mode[i] != '+' || ++i) && /* skip if char is '+' */
(mode[i] != 'b' || ++i) && /* skip if char is 'b' */
(mode[i] == '\0')))
return luaL_error(L, "invalid mode " LUA_QS
" (should match " LUA_QL("[rwa]%%+?b?") ")", mode);
p->f = fopen(filename, mode);
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
} }
/* /*
** this function has a separated environment, which defines the ** function to close 'popen' files
** correct __close for 'popen' files
*/ */
static int io_pclose (lua_State *L) {
LStream *p = tolstream(L);
return luaL_execresult(L, lua_pclose(L, p->f));
}
static int io_popen (lua_State *L) { static int io_popen (lua_State *L) {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r"); const char *mode = luaL_optstring(L, 2, "r");
FILE **pf = newfile(L); LStream *p = newprefile(L);
*pf = lua_popen(L, filename, mode); p->f = lua_popen(L, filename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1; p->closef = &io_pclose;
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
} }
static int io_tmpfile (lua_State *L) { static int io_tmpfile (lua_State *L) {
FILE **pf = newfile(L); LStream *p = newfile(L);
*pf = tmpfile(); p->f = tmpfile();
return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
} }
static FILE *getiofile (lua_State *L, int findex) { static FILE *getiofile (lua_State *L, const char *findex) {
FILE *f; LStream *p;
lua_rawgeti(L, LUA_ENVIRONINDEX, findex); lua_getfield(L, LUA_REGISTRYINDEX, findex);
f = *(FILE **)lua_touserdata(L, -1); p = (LStream *)lua_touserdata(L, -1);
if (f == NULL) if (isclosed(p))
luaL_error(L, "standard %s file is closed", fnames[findex - 1]); luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
return f; return p->f;
} }
static int g_iofile (lua_State *L, int f, const char *mode) { static int g_iofile (lua_State *L, const char *f, const char *mode) {
if (!lua_isnoneornil(L, 1)) { if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1); const char *filename = lua_tostring(L, 1);
if (filename) { if (filename)
FILE **pf = newfile(L); opencheck(L, filename, mode);
*pf = fopen(filename, mode);
if (*pf == NULL)
fileerror(L, 1, filename);
}
else { else {
tofile(L); /* check that it's a valid file handle */ tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
} }
lua_rawseti(L, LUA_ENVIRONINDEX, f); lua_setfield(L, LUA_REGISTRYINDEX, f);
} }
/* return current value */ /* return current value */
lua_rawgeti(L, LUA_ENVIRONINDEX, f); lua_getfield(L, LUA_REGISTRYINDEX, f);
return 1; return 1;
} }
@ -231,35 +291,43 @@ static int io_output (lua_State *L) {
static int io_readline (lua_State *L); static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int idx, int toclose) { static void aux_lines (lua_State *L, int toclose) {
lua_pushvalue(L, idx); int i;
int n = lua_gettop(L) - 1; /* number of arguments to read */
/* ensure that arguments will fit here and into 'io_readline' stack */
luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
lua_pushvalue(L, 1); /* file handle */
lua_pushinteger(L, n); /* number of arguments to read */
lua_pushboolean(L, toclose); /* close/not close file when finished */ lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 2); for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */
lua_pushcclosure(L, io_readline, 3 + n);
} }
static int f_lines (lua_State *L) { static int f_lines (lua_State *L) {
tofile(L); /* check that it's a valid file handle */ tofile(L); /* check that it's a valid file handle */
aux_lines(L, 1, 0); aux_lines(L, 0);
return 1; return 1;
} }
static int io_lines (lua_State *L) { static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */ int toclose;
/* will iterate over default input */ if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); if (lua_isnil(L, 1)) { /* no file name? */
return f_lines(L); lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
lua_replace(L, 1); /* put it at index 1 */
tofile(L); /* check that it's a valid file handle */
toclose = 0; /* do not close it after iteration */
} }
else { else { /* open a new file */
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
FILE **pf = newfile(L); opencheck(L, filename, "r");
*pf = fopen(filename, "r"); lua_replace(L, 1); /* put file at index 1 */
if (*pf == NULL) toclose = 1; /* close it after iteration */
fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
} }
aux_lines(L, toclose);
return 1;
} }
@ -276,7 +344,10 @@ static int read_number (lua_State *L, FILE *f) {
lua_pushnumber(L, d); lua_pushnumber(L, d);
return 1; return 1;
} }
else return 0; /* read fails */ else {
lua_pushnil(L); /* "result" to be removed */
return 0; /* read fails */
}
} }
@ -288,7 +359,7 @@ static int test_eof (lua_State *L, FILE *f) {
} }
static int read_line (lua_State *L, FILE *f) { static int read_line (lua_State *L, FILE *f, int chop) {
luaL_Buffer b; luaL_Buffer b;
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
for (;;) { for (;;) {
@ -296,13 +367,13 @@ static int read_line (lua_State *L, FILE *f) {
char *p = luaL_prepbuffer(&b); char *p = luaL_prepbuffer(&b);
if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
luaL_pushresult(&b); /* close buffer */ luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */ return (lua_rawlen(L, -1) > 0); /* check whether read something */
} }
l = strlen(p); l = strlen(p);
if (l == 0 || p[l-1] != '\n') if (l == 0 || p[l-1] != '\n')
luaL_addsize(&b, l); luaL_addsize(&b, l);
else { else {
luaL_addsize(&b, l - 1); /* do not include `eol' */ luaL_addsize(&b, l - chop); /* chop 'eol' if needed */
luaL_pushresult(&b); /* close buffer */ luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */ return 1; /* read at least an `eol' */
} }
@ -310,21 +381,34 @@ static int read_line (lua_State *L, FILE *f) {
} }
#define MAX_SIZE_T (~(size_t)0)
static void read_all (lua_State *L, FILE *f) {
size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */
luaL_Buffer b;
luaL_buffinit(L, &b);
for (;;) {
char *p = luaL_prepbuffsize(&b, rlen);
size_t nr = fread(p, sizeof(char), rlen, f);
luaL_addsize(&b, nr);
if (nr < rlen) break; /* eof? */
else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */
rlen *= 2; /* double buffer size at each iteration */
}
luaL_pushresult(&b); /* close buffer */
}
static int read_chars (lua_State *L, FILE *f, size_t n) { static int read_chars (lua_State *L, FILE *f, size_t n) {
size_t rlen; /* how much to read */
size_t nr; /* number of chars actually read */ size_t nr; /* number of chars actually read */
char *p;
luaL_Buffer b; luaL_Buffer b;
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
do { nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
char *p = luaL_prepbuffer(&b); luaL_addsize(&b, nr);
if (rlen > n) rlen = n; /* cannot read more than asked */
nr = fread(p, sizeof(char), rlen, f);
luaL_addsize(&b, nr);
n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */
luaL_pushresult(&b); /* close buffer */ luaL_pushresult(&b); /* close buffer */
return (n == 0 || lua_objlen(L, -1) > 0); return (nr > 0); /* true iff read something */
} }
@ -334,7 +418,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
int n; int n;
clearerr(f); clearerr(f);
if (nargs == 0) { /* no arguments? */ if (nargs == 0) { /* no arguments? */
success = read_line(L, f); success = read_line(L, f, 1);
n = first+1; /* to return 1 result */ n = first+1; /* to return 1 result */
} }
else { /* ensure stack space for all results and for auxlib's buffer */ else { /* ensure stack space for all results and for auxlib's buffer */
@ -353,10 +437,13 @@ static int g_read (lua_State *L, FILE *f, int first) {
success = read_number(L, f); success = read_number(L, f);
break; break;
case 'l': /* line */ case 'l': /* line */
success = read_line(L, f); success = read_line(L, f, 1);
break;
case 'L': /* line with end-of-line */
success = read_line(L, f, 0);
break; break;
case 'a': /* file */ case 'a': /* file */
read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ read_all(L, f); /* read entire file */
success = 1; /* always success */ success = 1; /* always success */
break; break;
default: default:
@ -366,7 +453,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
} }
} }
if (ferror(f)) if (ferror(f))
return pushresult(L, 0, NULL); return luaL_fileresult(L, 0, NULL);
if (!success) { if (!success) {
lua_pop(L, 1); /* remove last result */ lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */ lua_pushnil(L); /* push nil instead */
@ -386,16 +473,24 @@ static int f_read (lua_State *L) {
static int io_readline (lua_State *L) { static int io_readline (lua_State *L) {
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
int sucess; int i;
if (f == NULL) /* file is already closed? */ int n = (int)lua_tointeger(L, lua_upvalueindex(2));
luaL_error(L, "file is already closed"); if (isclosed(p)) /* file is already closed? */
sucess = read_line(L, f); return luaL_error(L, "file is already closed");
if (ferror(f)) lua_settop(L , 1);
return luaL_error(L, "%s", strerror(errno)); for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
if (sucess) return 1; lua_pushvalue(L, lua_upvalueindex(3 + i));
else { /* EOF */ n = g_read(L, p->f, 2); /* 'n' is number of results */
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ lua_assert(n > 0); /* should return at least a nil */
if (!lua_isnil(L, -n)) /* read at least one value? */
return n; /* return them */
else { /* first result is nil: EOF or error */
if (n > 1) { /* is there error information? */
/* 2nd result is error message */
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
}
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
lua_settop(L, 0); lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(1)); lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */ aux_close(L); /* close it */
@ -408,7 +503,7 @@ static int io_readline (lua_State *L) {
static int g_write (lua_State *L, FILE *f, int arg) { static int g_write (lua_State *L, FILE *f, int arg) {
int nargs = lua_gettop(L) - 1; int nargs = lua_gettop(L) - arg;
int status = 1; int status = 1;
for (; nargs--; arg++) { for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) { if (lua_type(L, arg) == LUA_TNUMBER) {
@ -422,7 +517,8 @@ static int g_write (lua_State *L, FILE *f, int arg) {
status = status && (fwrite(s, sizeof(char), l, f) == l); status = status && (fwrite(s, sizeof(char), l, f) == l);
} }
} }
return pushresult(L, status, NULL); if (status) return 1; /* file handle already on stack top */
else return luaL_fileresult(L, status, NULL);
} }
@ -432,7 +528,9 @@ static int io_write (lua_State *L) {
static int f_write (lua_State *L) { static int f_write (lua_State *L) {
return g_write(L, tofile(L), 2); FILE *f = tofile(L);
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
return g_write(L, f, 2);
} }
@ -441,12 +539,15 @@ static int f_seek (lua_State *L) {
static const char *const modenames[] = {"set", "cur", "end", NULL}; static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L); FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames); int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0); lua_Number p3 = luaL_optnumber(L, 3, 0);
op = fseek(f, offset, mode[op]); l_seeknum offset = (l_seeknum)p3;
luaL_argcheck(L, (lua_Number)offset == p3, 3,
"not an integer in proper range");
op = l_fseek(f, offset, mode[op]);
if (op) if (op)
return pushresult(L, 0, NULL); /* error */ return luaL_fileresult(L, 0, NULL); /* error */
else { else {
lua_pushinteger(L, ftell(f)); lua_pushnumber(L, (lua_Number)l_ftell(f));
return 1; return 1;
} }
} }
@ -459,21 +560,24 @@ static int f_setvbuf (lua_State *L) {
int op = luaL_checkoption(L, 2, NULL, modenames); int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], sz); int res = setvbuf(f, NULL, mode[op], sz);
return pushresult(L, res == 0, NULL); return luaL_fileresult(L, res == 0, NULL);
} }
static int io_flush (lua_State *L) { static int io_flush (lua_State *L) {
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
} }
static int f_flush (lua_State *L) { static int f_flush (lua_State *L) {
return pushresult(L, fflush(tofile(L)) == 0, NULL); return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
} }
/*
** functions for 'io' library
*/
static const luaL_Reg iolib[] = { static const luaL_Reg iolib[] = {
{"close", io_close}, {"close", io_close},
{"flush", io_flush}, {"flush", io_flush},
@ -490,6 +594,9 @@ static const luaL_Reg iolib[] = {
}; };
/*
** methods for file handles
*/
static const luaL_Reg flib[] = { static const luaL_Reg flib[] = {
{"close", io_close}, {"close", io_close},
{"flush", f_flush}, {"flush", f_flush},
@ -498,8 +605,8 @@ static const luaL_Reg flib[] = {
{"seek", f_seek}, {"seek", f_seek},
{"setvbuf", f_setvbuf}, {"setvbuf", f_setvbuf},
{"write", f_write}, {"write", f_write},
{"__gc", io_gc}, {"__gc", f_gc},
{"__tostring", io_tostring}, {"__tostring", f_tostring},
{NULL, NULL} {NULL, NULL}
}; };
@ -508,46 +615,43 @@ static void createmeta (lua_State *L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */ lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_register(L, NULL, flib); /* file methods */ luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
lua_pop(L, 1); /* pop new metatable */
} }
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { /*
*newfile(L) = f; ** function to (not) close the standard files stdin, stdout, and stderr
if (k > 0) { */
lua_pushvalue(L, -1); static int io_noclose (lua_State *L) {
lua_rawseti(L, LUA_ENVIRONINDEX, k); LStream *p = tolstream(L);
} p->closef = &io_noclose; /* keep file opened */
lua_pushvalue(L, -2); /* copy environment */ lua_pushnil(L);
lua_setfenv(L, -2); /* set it */ lua_pushliteral(L, "cannot close standard file");
lua_setfield(L, -3, fname); return 2;
} }
static void newfenv (lua_State *L, lua_CFunction cls) { static void createstdfile (lua_State *L, FILE *f, const char *k,
lua_createtable(L, 0, 1); const char *fname) {
lua_pushcfunction(L, cls); LStream *p = newprefile(L);
lua_setfield(L, -2, "__close"); p->f = f;
p->closef = &io_noclose;
if (k != NULL) {
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
}
lua_setfield(L, -2, fname); /* add file to module */
} }
LUALIB_API int luaopen_io (lua_State *L) { LUAMOD_API int luaopen_io (lua_State *L) {
luaL_newlib(L, iolib); /* new module */
createmeta(L); createmeta(L);
/* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
newfenv(L, io_fclose);
lua_replace(L, LUA_ENVIRONINDEX);
/* open library */
luaL_register(L, LUA_IOLIBNAME, iolib);
/* create (and set) default files */ /* create (and set) default files */
newfenv(L, io_noclose); /* close function for default files */
createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, 0, "stderr"); createstdfile(L, stderr, NULL, "stderr");
lua_pop(L, 1); /* pop environment for default files */
lua_getfield(L, -1, "popen");
newfenv(L, io_pclose); /* create environment for 'popen' */
lua_setfenv(L, -2); /* set fenv for 'popen' */
lua_pop(L, 1); /* pop 'popen' */
return 1; return 1;
} }

@ -1,11 +1,10 @@
/* /*
** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: llex.c,v 2.59 2011/11/30 12:43:51 roberto Exp $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <ctype.h>
#include <locale.h> #include <locale.h>
#include <string.h> #include <string.h>
@ -14,6 +13,7 @@
#include "lua.h" #include "lua.h"
#include "lctype.h"
#include "ldo.h" #include "ldo.h"
#include "llex.h" #include "llex.h"
#include "lobject.h" #include "lobject.h"
@ -29,35 +29,36 @@
#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
/* ORDER RESERVED */ /* ORDER RESERVED */
const char *const luaX_tokens [] = { static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif", "and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if", "end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat", "in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while", "return", "then", "true", "until", "while",
"..", "...", "==", ">=", "<=", "~=", "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
"<number>", "<name>", "<string>", "<eof>", "<number>", "<name>", "<string>"
NULL
}; };
#define save_and_next(ls) (save(ls, ls->current), next(ls)) #define save_and_next(ls) (save(ls, ls->current), next(ls))
static l_noret lexerror (LexState *ls, const char *msg, int token);
static void save (LexState *ls, int c) { static void save (LexState *ls, int c) {
Mbuffer *b = ls->buff; Mbuffer *b = ls->buff;
if (b->n + 1 > b->buffsize) { if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
size_t newsize; size_t newsize;
if (b->buffsize >= MAX_SIZET/2) if (luaZ_sizebuffer(b) >= MAX_SIZET/2)
luaX_lexerror(ls, "lexical element too long", 0); lexerror(ls, "lexical element too long", 0);
newsize = b->buffsize * 2; newsize = luaZ_sizebuffer(b) * 2;
luaZ_resizebuffer(ls->L, b, newsize); luaZ_resizebuffer(ls->L, b, newsize);
} }
b->buffer[b->n++] = cast(char, c); b->buffer[luaZ_bufflen(b)++] = cast(char, c);
} }
@ -66,23 +67,24 @@ void luaX_init (lua_State *L) {
for (i=0; i<NUM_RESERVED; i++) { for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, luaX_tokens[i]); TString *ts = luaS_new(L, luaX_tokens[i]);
luaS_fix(ts); /* reserved words are never collected */ luaS_fix(ts); /* reserved words are never collected */
lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
ts->tsv.reserved = cast_byte(i+1); /* reserved word */ ts->tsv.reserved = cast_byte(i+1); /* reserved word */
} }
} }
#define MAXSRC 80
const char *luaX_token2str (LexState *ls, int token) { const char *luaX_token2str (LexState *ls, int token) {
if (token < FIRST_RESERVED) { if (token < FIRST_RESERVED) {
lua_assert(token == cast(unsigned char, token)); lua_assert(token == cast(unsigned char, token));
return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) :
luaO_pushfstring(ls->L, "%c", token); luaO_pushfstring(ls->L, "char(%d)", token);
}
else {
const char *s = luaX_tokens[token - FIRST_RESERVED];
if (token < TK_EOS)
return luaO_pushfstring(ls->L, LUA_QS, s);
else
return s;
} }
else
return luaX_tokens[token-FIRST_RESERVED];
} }
@ -92,38 +94,54 @@ static const char *txtToken (LexState *ls, int token) {
case TK_STRING: case TK_STRING:
case TK_NUMBER: case TK_NUMBER:
save(ls, '\0'); save(ls, '\0');
return luaZ_buffer(ls->buff); return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff));
default: default:
return luaX_token2str(ls, token); return luaX_token2str(ls, token);
} }
} }
void luaX_lexerror (LexState *ls, const char *msg, int token) { static l_noret lexerror (LexState *ls, const char *msg, int token) {
char buff[MAXSRC]; char buff[LUA_IDSIZE];
luaO_chunkid(buff, getstr(ls->source), MAXSRC); luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE);
msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
if (token) if (token)
luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
luaD_throw(ls->L, LUA_ERRSYNTAX); luaD_throw(ls->L, LUA_ERRSYNTAX);
} }
void luaX_syntaxerror (LexState *ls, const char *msg) { l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
luaX_lexerror(ls, msg, ls->t.token); lexerror(ls, msg, ls->t.token);
} }
/*
** creates a new string and anchors it in function's table so that
** it will not be collected until the end of the function's compilation
** (by that time it should be anchored in function's prototype)
*/
TString *luaX_newstring (LexState *ls, const char *str, size_t l) { TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
lua_State *L = ls->L; lua_State *L = ls->L;
TString *ts = luaS_newlstr(L, str, l); TValue *o; /* entry for `str' */
TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ TString *ts = luaS_newlstr(L, str, l); /* create new string */
if (ttisnil(o)) setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */
setbvalue(o, 1); /* make sure `str' will not be collected */ o = luaH_set(L, ls->fs->h, L->top - 1);
if (ttisnil(o)) { /* not in use yet? (see 'addK') */
/* boolean value does not need GC barrier;
table has no metatable, so it does not need to invalidate cache */
setbvalue(o, 1); /* t[string] = true */
luaC_checkGC(L);
}
L->top--; /* remove string from stack */
return ts; return ts;
} }
/*
** increment line number and skips newline sequence (any of
** \n, \r, \n\r, or \r\n)
*/
static void inclinenumber (LexState *ls) { static void inclinenumber (LexState *ls) {
int old = ls->current; int old = ls->current;
lua_assert(currIsNewline(ls)); lua_assert(currIsNewline(ls));
@ -135,17 +153,20 @@ static void inclinenumber (LexState *ls) {
} }
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
int firstchar) {
ls->decpoint = '.'; ls->decpoint = '.';
ls->L = L; ls->L = L;
ls->current = firstchar;
ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->lookahead.token = TK_EOS; /* no look-ahead token */
ls->z = z; ls->z = z;
ls->fs = NULL; ls->fs = NULL;
ls->linenumber = 1; ls->linenumber = 1;
ls->lastline = 1; ls->lastline = 1;
ls->source = source; ls->source = source;
ls->envn = luaS_new(L, LUA_ENV); /* create env name */
luaS_fix(ls->envn); /* never collect this name */
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
next(ls); /* read first char */
} }
@ -159,13 +180,16 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
static int check_next (LexState *ls, const char *set) { static int check_next (LexState *ls, const char *set) {
if (!strchr(set, ls->current)) if (ls->current == '\0' || !strchr(set, ls->current))
return 0; return 0;
save_and_next(ls); save_and_next(ls);
return 1; return 1;
} }
/*
** change all characters 'from' in buffer to 'to'
*/
static void buffreplace (LexState *ls, char from, char to) { static void buffreplace (LexState *ls, char from, char to) {
size_t n = luaZ_bufflen(ls->buff); size_t n = luaZ_bufflen(ls->buff);
char *p = luaZ_buffer(ls->buff); char *p = luaZ_buffer(ls->buff);
@ -174,37 +198,48 @@ static void buffreplace (LexState *ls, char from, char to) {
} }
#if !defined(getlocaledecpoint)
#define getlocaledecpoint() (localeconv()->decimal_point[0])
#endif
#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e)
/*
** in case of format error, try to change decimal point separator to
** the one defined in the current locale and check again
*/
static void trydecpoint (LexState *ls, SemInfo *seminfo) { static void trydecpoint (LexState *ls, SemInfo *seminfo) {
/* format error: try to update decimal point separator */
struct lconv *cv = localeconv();
char old = ls->decpoint; char old = ls->decpoint;
ls->decpoint = (cv ? cv->decimal_point[0] : '.'); ls->decpoint = getlocaledecpoint();
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { if (!buff2d(ls->buff, &seminfo->r)) {
/* format error with correct decimal point: no more options */ /* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
luaX_lexerror(ls, "malformed number", TK_NUMBER); lexerror(ls, "malformed number", TK_NUMBER);
} }
} }
/* LUA_NUMBER */ /* LUA_NUMBER */
static void read_numeral (LexState *ls, SemInfo *seminfo) { static void read_numeral (LexState *ls, SemInfo *seminfo) {
lua_assert(isdigit(ls->current)); lua_assert(lisdigit(ls->current));
do { do {
save_and_next(ls); save_and_next(ls);
} while (isdigit(ls->current) || ls->current == '.'); if (check_next(ls, "EePp")) /* exponent part? */
if (check_next(ls, "Ee")) /* `E'? */ check_next(ls, "+-"); /* optional exponent sign */
check_next(ls, "+-"); /* optional exponent sign */ } while (lislalnum(ls->current) || ls->current == '.');
while (isalnum(ls->current) || ls->current == '_')
save_and_next(ls);
save(ls, '\0'); save(ls, '\0');
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ if (!buff2d(ls->buff, &seminfo->r)) /* format error? */
trydecpoint(ls, seminfo); /* try to update decimal point separator */ trydecpoint(ls, seminfo); /* try to update decimal point separator */
} }
/*
** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
** -1 if sequence is malformed
*/
static int skip_sep (LexState *ls) { static int skip_sep (LexState *ls) {
int count = 0; int count = 0;
int s = ls->current; int s = ls->current;
@ -219,43 +254,23 @@ static int skip_sep (LexState *ls) {
static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
int cont = 0;
(void)(cont); /* avoid warnings when `cont' is not used */
save_and_next(ls); /* skip 2nd `[' */ save_and_next(ls); /* skip 2nd `[' */
if (currIsNewline(ls)) /* string starts with a newline? */ if (currIsNewline(ls)) /* string starts with a newline? */
inclinenumber(ls); /* skip it */ inclinenumber(ls); /* skip it */
for (;;) { for (;;) {
switch (ls->current) { switch (ls->current) {
case EOZ: case EOZ:
luaX_lexerror(ls, (seminfo) ? "unfinished long string" : lexerror(ls, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS); "unfinished long comment", TK_EOS);
break; /* to avoid warnings */ break; /* to avoid warnings */
#if defined(LUA_COMPAT_LSTR)
case '[': {
if (skip_sep(ls) == sep) {
save_and_next(ls); /* skip 2nd `[' */
cont++;
#if LUA_COMPAT_LSTR == 1
if (sep == 0)
luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
#endif
}
break;
}
#endif
case ']': { case ']': {
if (skip_sep(ls) == sep) { if (skip_sep(ls) == sep) {
save_and_next(ls); /* skip 2nd `]' */ save_and_next(ls); /* skip 2nd `]' */
#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
cont--;
if (sep == 0 && cont >= 0) break;
#endif
goto endloop; goto endloop;
} }
break; break;
} }
case '\n': case '\n': case '\r': {
case '\r': {
save(ls, '\n'); save(ls, '\n');
inclinenumber(ls); inclinenumber(ls);
if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
@ -273,51 +288,91 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
} }
static void escerror (LexState *ls, int *c, int n, const char *msg) {
int i;
luaZ_resetbuffer(ls->buff); /* prepare error message */
save(ls, '\\');
for (i = 0; i < n && c[i] != EOZ; i++)
save(ls, c[i]);
lexerror(ls, msg, TK_STRING);
}
static int readhexaesc (LexState *ls) {
int c[3], i; /* keep input for error message */
int r = 0; /* result accumulator */
c[0] = 'x'; /* for error message */
for (i = 1; i < 3; i++) { /* read two hexa digits */
c[i] = next(ls);
if (!lisxdigit(c[i]))
escerror(ls, c, i + 1, "hexadecimal digit expected");
r = (r << 4) + luaO_hexavalue(c[i]);
}
return r;
}
static int readdecesc (LexState *ls) {
int c[3], i;
int r = 0; /* result accumulator */
for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */
c[i] = ls->current;
r = 10*r + c[i] - '0';
next(ls);
}
if (r > UCHAR_MAX)
escerror(ls, c, i, "decimal escape too large");
return r;
}
static void read_string (LexState *ls, int del, SemInfo *seminfo) { static void read_string (LexState *ls, int del, SemInfo *seminfo) {
save_and_next(ls); save_and_next(ls); /* keep delimiter (for error messages) */
while (ls->current != del) { while (ls->current != del) {
switch (ls->current) { switch (ls->current) {
case EOZ: case EOZ:
luaX_lexerror(ls, "unfinished string", TK_EOS); lexerror(ls, "unfinished string", TK_EOS);
continue; /* to avoid warnings */ break; /* to avoid warnings */
case '\n': case '\n':
case '\r': case '\r':
luaX_lexerror(ls, "unfinished string", TK_STRING); lexerror(ls, "unfinished string", TK_STRING);
continue; /* to avoid warnings */ break; /* to avoid warnings */
case '\\': { case '\\': { /* escape sequences */
int c; int c; /* final character to be saved */
next(ls); /* do not save the `\' */ next(ls); /* do not save the `\' */
switch (ls->current) { switch (ls->current) {
case 'a': c = '\a'; break; case 'a': c = '\a'; goto read_save;
case 'b': c = '\b'; break; case 'b': c = '\b'; goto read_save;
case 'f': c = '\f'; break; case 'f': c = '\f'; goto read_save;
case 'n': c = '\n'; break; case 'n': c = '\n'; goto read_save;
case 'r': c = '\r'; break; case 'r': c = '\r'; goto read_save;
case 't': c = '\t'; break; case 't': c = '\t'; goto read_save;
case 'v': c = '\v'; break; case 'v': c = '\v'; goto read_save;
case '\n': /* go through */ case 'x': c = readhexaesc(ls); goto read_save;
case '\r': save(ls, '\n'); inclinenumber(ls); continue; case '\n': case '\r':
case EOZ: continue; /* will raise an error next loop */ inclinenumber(ls); c = '\n'; goto only_save;
default: { case '\\': case '\"': case '\'':
if (!isdigit(ls->current)) c = ls->current; goto read_save;
save_and_next(ls); /* handles \\, \", \', and \? */ case EOZ: goto no_save; /* will raise an error next loop */
else { /* \xxx */ case 'z': { /* zap following span of spaces */
int i = 0; next(ls); /* skip the 'z' */
c = 0; while (lisspace(ls->current)) {
do { if (currIsNewline(ls)) inclinenumber(ls);
c = 10*c + (ls->current-'0'); else next(ls);
next(ls);
} while (++i<3 && isdigit(ls->current));
if (c > UCHAR_MAX)
luaX_lexerror(ls, "escape sequence too large", TK_STRING);
save(ls, c);
} }
continue; goto no_save;
}
default: {
if (!lisdigit(ls->current))
escerror(ls, &ls->current, 1, "invalid escape sequence");
/* digital escape \ddd */
c = readdecesc(ls);
goto only_save;
} }
} }
save(ls, c); read_save: next(ls); /* read next character */
next(ls); only_save: save(ls, c); /* save 'c' */
continue; no_save: break;
} }
default: default:
save_and_next(ls); save_and_next(ls);
@ -333,38 +388,41 @@ static int llex (LexState *ls, SemInfo *seminfo) {
luaZ_resetbuffer(ls->buff); luaZ_resetbuffer(ls->buff);
for (;;) { for (;;) {
switch (ls->current) { switch (ls->current) {
case '\n': case '\n': case '\r': { /* line breaks */
case '\r': {
inclinenumber(ls); inclinenumber(ls);
continue; break;
} }
case '-': { case ' ': case '\f': case '\t': case '\v': { /* spaces */
next(ls);
break;
}
case '-': { /* '-' or '--' (comment) */
next(ls); next(ls);
if (ls->current != '-') return '-'; if (ls->current != '-') return '-';
/* else is a comment */ /* else is a comment */
next(ls); next(ls);
if (ls->current == '[') { if (ls->current == '[') { /* long comment? */
int sep = skip_sep(ls); int sep = skip_sep(ls);
luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */
if (sep >= 0) { if (sep >= 0) {
read_long_string(ls, NULL, sep); /* long comment */ read_long_string(ls, NULL, sep); /* skip long comment */
luaZ_resetbuffer(ls->buff); luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */
continue; break;
} }
} }
/* else short comment */ /* else short comment */
while (!currIsNewline(ls) && ls->current != EOZ) while (!currIsNewline(ls) && ls->current != EOZ)
next(ls); next(ls); /* skip until end of line (or end of file) */
continue; break;
} }
case '[': { case '[': { /* long string or simply '[' */
int sep = skip_sep(ls); int sep = skip_sep(ls);
if (sep >= 0) { if (sep >= 0) {
read_long_string(ls, seminfo, sep); read_long_string(ls, seminfo, sep);
return TK_STRING; return TK_STRING;
} }
else if (sep == -1) return '['; else if (sep == -1) return '[';
else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); else lexerror(ls, "invalid long string delimiter", TK_STRING);
} }
case '=': { case '=': {
next(ls); next(ls);
@ -386,56 +444,52 @@ static int llex (LexState *ls, SemInfo *seminfo) {
if (ls->current != '=') return '~'; if (ls->current != '=') return '~';
else { next(ls); return TK_NE; } else { next(ls); return TK_NE; }
} }
case '"': case ':': {
case '\'': { next(ls);
if (ls->current != ':') return ':';
else { next(ls); return TK_DBCOLON; }
}
case '"': case '\'': { /* short literal strings */
read_string(ls, ls->current, seminfo); read_string(ls, ls->current, seminfo);
return TK_STRING; return TK_STRING;
} }
case '.': { case '.': { /* '.', '..', '...', or number */
save_and_next(ls); save_and_next(ls);
if (check_next(ls, ".")) { if (check_next(ls, ".")) {
if (check_next(ls, ".")) if (check_next(ls, "."))
return TK_DOTS; /* ... */ return TK_DOTS; /* '...' */
else return TK_CONCAT; /* .. */ else return TK_CONCAT; /* '..' */
}
else if (!isdigit(ls->current)) return '.';
else {
read_numeral(ls, seminfo);
return TK_NUMBER;
} }
else if (!lisdigit(ls->current)) return '.';
/* else go through */
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
read_numeral(ls, seminfo);
return TK_NUMBER;
} }
case EOZ: { case EOZ: {
return TK_EOS; return TK_EOS;
} }
default: { default: {
if (isspace(ls->current)) { if (lislalpha(ls->current)) { /* identifier or reserved word? */
lua_assert(!currIsNewline(ls));
next(ls);
continue;
}
else if (isdigit(ls->current)) {
read_numeral(ls, seminfo);
return TK_NUMBER;
}
else if (isalpha(ls->current) || ls->current == '_') {
/* identifier or reserved word */
TString *ts; TString *ts;
do { do {
save_and_next(ls); save_and_next(ls);
} while (isalnum(ls->current) || ls->current == '_'); } while (lislalnum(ls->current));
ts = luaX_newstring(ls, luaZ_buffer(ls->buff), ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff)); luaZ_bufflen(ls->buff));
seminfo->ts = ts;
if (ts->tsv.reserved > 0) /* reserved word? */ if (ts->tsv.reserved > 0) /* reserved word? */
return ts->tsv.reserved - 1 + FIRST_RESERVED; return ts->tsv.reserved - 1 + FIRST_RESERVED;
else { else {
seminfo->ts = ts;
return TK_NAME; return TK_NAME;
} }
} }
else { else { /* single-char tokens (+ - / ...) */
int c = ls->current; int c = ls->current;
next(ls); next(ls);
return c; /* single-char tokens (+ - / ...) */ return c;
} }
} }
} }
@ -454,8 +508,9 @@ void luaX_next (LexState *ls) {
} }
void luaX_lookahead (LexState *ls) { int luaX_lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS); lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
return ls->lookahead.token;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lmathlib.c,v 1.80 2011/07/05 12:49:35 roberto Exp $
** Standard mathematical library ** Standard mathematical library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -22,107 +22,127 @@
#define RADIANS_PER_DEGREE (PI/180.0) #define RADIANS_PER_DEGREE (PI/180.0)
/* macro 'l_tg' allows the addition of an 'l' or 'f' to all math operations */
#if !defined(l_tg)
#define l_tg(x) (x)
#endif
static int math_abs (lua_State *L) { static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(fabs)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_sin (lua_State *L) { static int math_sin (lua_State *L) {
lua_pushnumber(L, sin(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(sin)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_sinh (lua_State *L) { static int math_sinh (lua_State *L) {
lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(sinh)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_cos (lua_State *L) { static int math_cos (lua_State *L) {
lua_pushnumber(L, cos(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(cos)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_cosh (lua_State *L) { static int math_cosh (lua_State *L) {
lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(cosh)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_tan (lua_State *L) { static int math_tan (lua_State *L) {
lua_pushnumber(L, tan(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(tan)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_tanh (lua_State *L) { static int math_tanh (lua_State *L) {
lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(tanh)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_asin (lua_State *L) { static int math_asin (lua_State *L) {
lua_pushnumber(L, asin(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(asin)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_acos (lua_State *L) { static int math_acos (lua_State *L) {
lua_pushnumber(L, acos(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(acos)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_atan (lua_State *L) { static int math_atan (lua_State *L) {
lua_pushnumber(L, atan(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(atan)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_atan2 (lua_State *L) { static int math_atan2 (lua_State *L) {
lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); lua_pushnumber(L, l_tg(atan2)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
return 1; return 1;
} }
static int math_ceil (lua_State *L) { static int math_ceil (lua_State *L) {
lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(ceil)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_floor (lua_State *L) { static int math_floor (lua_State *L) {
lua_pushnumber(L, floor(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(floor)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_fmod (lua_State *L) { static int math_fmod (lua_State *L) {
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); lua_pushnumber(L, l_tg(fmod)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
return 1; return 1;
} }
static int math_modf (lua_State *L) { static int math_modf (lua_State *L) {
double ip; lua_Number ip;
double fp = modf(luaL_checknumber(L, 1), &ip); lua_Number fp = l_tg(modf)(luaL_checknumber(L, 1), &ip);
lua_pushnumber(L, ip); lua_pushnumber(L, ip);
lua_pushnumber(L, fp); lua_pushnumber(L, fp);
return 2; return 2;
} }
static int math_sqrt (lua_State *L) { static int math_sqrt (lua_State *L) {
lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(sqrt)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
static int math_pow (lua_State *L) { static int math_pow (lua_State *L) {
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); lua_pushnumber(L, l_tg(pow)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
return 1; return 1;
} }
static int math_log (lua_State *L) { static int math_log (lua_State *L) {
lua_pushnumber(L, log(luaL_checknumber(L, 1))); lua_Number x = luaL_checknumber(L, 1);
lua_Number res;
if (lua_isnoneornil(L, 2))
res = l_tg(log)(x);
else {
lua_Number base = luaL_checknumber(L, 2);
if (base == 10.0) res = l_tg(log10)(x);
else res = l_tg(log)(x)/l_tg(log)(base);
}
lua_pushnumber(L, res);
return 1; return 1;
} }
#if defined(LUA_COMPAT_LOG10)
static int math_log10 (lua_State *L) { static int math_log10 (lua_State *L) {
lua_pushnumber(L, log10(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(log10)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
#endif
static int math_exp (lua_State *L) { static int math_exp (lua_State *L) {
lua_pushnumber(L, exp(luaL_checknumber(L, 1))); lua_pushnumber(L, l_tg(exp)(luaL_checknumber(L, 1)));
return 1; return 1;
} }
@ -138,13 +158,14 @@ static int math_rad (lua_State *L) {
static int math_frexp (lua_State *L) { static int math_frexp (lua_State *L) {
int e; int e;
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); lua_pushnumber(L, l_tg(frexp)(luaL_checknumber(L, 1), &e));
lua_pushinteger(L, e); lua_pushinteger(L, e);
return 2; return 2;
} }
static int math_ldexp (lua_State *L) { static int math_ldexp (lua_State *L) {
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); lua_pushnumber(L, l_tg(ldexp)(luaL_checknumber(L, 1),
luaL_checkint(L, 2)));
return 1; return 1;
} }
@ -188,16 +209,16 @@ static int math_random (lua_State *L) {
break; break;
} }
case 1: { /* only upper limit */ case 1: { /* only upper limit */
int u = luaL_checkint(L, 1); lua_Number u = luaL_checknumber(L, 1);
luaL_argcheck(L, 1<=u, 1, "interval is empty"); luaL_argcheck(L, 1.0 <= u, 1, "interval is empty");
lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ lua_pushnumber(L, l_tg(floor)(r*u) + 1.0); /* int in [1, u] */
break; break;
} }
case 2: { /* lower and upper limits */ case 2: { /* lower and upper limits */
int l = luaL_checkint(L, 1); lua_Number l = luaL_checknumber(L, 1);
int u = luaL_checkint(L, 2); lua_Number u = luaL_checknumber(L, 2);
luaL_argcheck(L, l<=u, 2, "interval is empty"); luaL_argcheck(L, l <= u, 2, "interval is empty");
lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ lua_pushnumber(L, l_tg(floor)(r*(u-l+1)) + l); /* int in [l, u] */
break; break;
} }
default: return luaL_error(L, "wrong number of arguments"); default: return luaL_error(L, "wrong number of arguments");
@ -207,7 +228,8 @@ static int math_random (lua_State *L) {
static int math_randomseed (lua_State *L) { static int math_randomseed (lua_State *L) {
srand(luaL_checkint(L, 1)); srand(luaL_checkunsigned(L, 1));
(void)rand(); /* discard first value to avoid undesirable correlations */
return 0; return 0;
} }
@ -227,7 +249,9 @@ static const luaL_Reg mathlib[] = {
{"fmod", math_fmod}, {"fmod", math_fmod},
{"frexp", math_frexp}, {"frexp", math_frexp},
{"ldexp", math_ldexp}, {"ldexp", math_ldexp},
#if defined(LUA_COMPAT_LOG10)
{"log10", math_log10}, {"log10", math_log10},
#endif
{"log", math_log}, {"log", math_log},
{"max", math_max}, {"max", math_max},
{"min", math_min}, {"min", math_min},
@ -248,16 +272,12 @@ static const luaL_Reg mathlib[] = {
/* /*
** Open math library ** Open math library
*/ */
LUALIB_API int luaopen_math (lua_State *L) { LUAMOD_API int luaopen_math (lua_State *L) {
luaL_register(L, LUA_MATHLIBNAME, mathlib); luaL_newlib(L, mathlib);
lua_pushnumber(L, PI); lua_pushnumber(L, PI);
lua_setfield(L, -2, "pi"); lua_setfield(L, -2, "pi");
lua_pushnumber(L, HUGE_VAL); lua_pushnumber(L, HUGE_VAL);
lua_setfield(L, -2, "huge"); lua_setfield(L, -2, "huge");
#if defined(LUA_COMPAT_MOD)
lua_getfield(L, -1, "fmod");
lua_setfield(L, -2, "mod");
#endif
return 1; return 1;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lmem.c,v 1.83 2011/11/30 12:42:49 roberto Exp $
** Interface to Memory Manager ** Interface to Memory Manager
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -14,6 +14,7 @@
#include "ldebug.h" #include "ldebug.h"
#include "ldo.h" #include "ldo.h"
#include "lgc.h"
#include "lmem.h" #include "lmem.h"
#include "lobject.h" #include "lobject.h"
#include "lstate.h" #include "lstate.h"
@ -25,12 +26,11 @@
** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
** (`osize' is the old size, `nsize' is the new size) ** (`osize' is the old size, `nsize' is the new size)
** **
** Lua ensures that (ptr == NULL) iff (osize == 0). ** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no
** ** matter 'x').
** * frealloc(ud, NULL, 0, x) creates a new block of size `x'
** **
** * frealloc(ud, p, x, 0) frees the block `p' ** * frealloc(ud, p, x, 0) frees the block `p'
** (in this specific case, frealloc must return NULL). ** (in this specific case, frealloc must return NULL);
** particularly, frealloc(ud, NULL, 0, 0) does nothing ** particularly, frealloc(ud, NULL, 0, 0) does nothing
** (which is equivalent to free(NULL) in ANSI C) ** (which is equivalent to free(NULL) in ANSI C)
** **
@ -44,12 +44,12 @@
void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
int limit, const char *errormsg) { int limit, const char *what) {
void *newblock; void *newblock;
int newsize; int newsize;
if (*size >= limit/2) { /* cannot double it? */ if (*size >= limit/2) { /* cannot double it? */
if (*size >= limit) /* cannot grow even a little? */ if (*size >= limit) /* cannot grow even a little? */
luaG_runerror(L, errormsg); luaG_runerror(L, "too many %s (limit is %d)", what, limit);
newsize = limit; /* still have at least one free place */ newsize = limit; /* still have at least one free place */
} }
else { else {
@ -63,9 +63,8 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
} }
void *luaM_toobig (lua_State *L) { l_noret luaM_toobig (lua_State *L) {
luaG_runerror(L, "memory allocation error: block too big"); luaG_runerror(L, "memory allocation error: block too big");
return NULL; /* to avoid warnings */
} }
@ -74,13 +73,43 @@ void *luaM_toobig (lua_State *L) {
** generic allocation routine. ** generic allocation routine.
*/ */
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
void *newblock;
global_State *g = G(L); global_State *g = G(L);
lua_assert((osize == 0) == (block == NULL)); size_t realosize = (block) ? osize : 0;
block = (*g->frealloc)(g->ud, block, osize, nsize); lua_assert((realosize == 0) == (block == NULL));
if (block == NULL && nsize > 0) #if defined(HARDMEMTESTS)
luaD_throw(L, LUA_ERRMEM); if (nsize > realosize && g->gcrunning)
lua_assert((nsize == 0) == (block == NULL)); luaC_fullgc(L, 1); /* force a GC whenever possible */
g->totalbytes = (g->totalbytes - osize) + nsize; #endif
return block; newblock = (*g->frealloc)(g->ud, block, osize, nsize);
if (newblock == NULL && nsize > 0) {
api_check(L, nsize > realosize,
"realloc cannot fail when shrinking a block");
if (g->gcrunning) {
luaC_fullgc(L, 1); /* try to free some memory... */
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
}
if (newblock == NULL)
luaD_throw(L, LUA_ERRMEM);
}
lua_assert((nsize == 0) == (newblock == NULL));
g->GCdebt = (g->GCdebt + nsize) - realosize;
#if defined(TRACEMEM)
{ /* auxiliary patch to monitor garbage collection.
** To plot, gnuplot with following command:
** plot TRACEMEM using 1:2 with lines, TRACEMEM using 1:3 with lines
*/
static unsigned long total = 0; /* our "time" */
static FILE *f = NULL; /* output file */
total++; /* "time" always grows */
if ((total % 200) == 0) {
if (f == NULL) f = fopen(TRACEMEM, "w");
fprintf(f, "%lu %u %d %d\n", total,
gettotalbytes(g), g->GCdebt, g->gcstate * 10000);
}
}
#endif
return newblock;
} }

@ -1,14 +1,22 @@
/* /*
** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ ** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp $
** Dynamic library loader for Lua ** Dynamic library loader for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
** **
** This module contains an implementation of loadlib for Unix systems ** This module contains an implementation of loadlib for Unix systems
** that have dlfcn, an implementation for Darwin (Mac OS X), an ** that have dlfcn, an implementation for Windows, and a stub for other
** implementation for Windows, and a stub for other systems. ** systems.
*/ */
/*
** if needed, includes windows header before everything else
*/
#if defined(_WIN32)
#include <windows.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -22,6 +30,61 @@
#include "lualib.h" #include "lualib.h"
/*
** LUA_PATH and LUA_CPATH are the names of the environment
** variables that Lua check to set its paths.
*/
#if !defined(LUA_PATH)
#define LUA_PATH "LUA_PATH"
#endif
#if !defined(LUA_CPATH)
#define LUA_CPATH "LUA_CPATH"
#endif
#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX
#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX
/*
** LUA_PATH_SEP is the character that separates templates in a path.
** LUA_PATH_MARK is the string that marks the substitution points in a
** template.
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
** directory.
** LUA_IGMARK is a mark to ignore all before it when building the
** luaopen_ function name.
*/
#if !defined (LUA_PATH_SEP)
#define LUA_PATH_SEP ";"
#endif
#if !defined (LUA_PATH_MARK)
#define LUA_PATH_MARK "?"
#endif
#if !defined (LUA_EXEC_DIR)
#define LUA_EXEC_DIR "!"
#endif
#if !defined (LUA_IGMARK)
#define LUA_IGMARK "-"
#endif
/*
** LUA_CSUBSEP is the character that replaces dots in submodule names
** when searching for a C loader.
** LUA_LSUBSEP is the character that replaces dots in submodule names
** when searching for a Lua loader.
*/
#if !defined(LUA_CSUBSEP)
#define LUA_CSUBSEP LUA_DIRSEP
#endif
#if !defined(LUA_LSUBSEP)
#define LUA_LSUBSEP LUA_DIRSEP
#endif
/* prefix for open functions in C libraries */ /* prefix for open functions in C libraries */
#define LUA_POF "luaopen_" #define LUA_POF "luaopen_"
@ -42,13 +105,16 @@
#define setprogdir(L) ((void)0) #define setprogdir(L) ((void)0)
/*
** system-dependent functions
*/
static void ll_unloadlib (void *lib); static void ll_unloadlib (void *lib);
static void *ll_load (lua_State *L, const char *path); static void *ll_load (lua_State *L, const char *path, int seeglb);
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
#if defined(LUA_DL_DLOPEN) #if defined(LUA_USE_DLOPEN)
/* /*
** {======================================================================== ** {========================================================================
** This is an implementation of loadlib based on the dlfcn interface. ** This is an implementation of loadlib based on the dlfcn interface.
@ -65,8 +131,8 @@ static void ll_unloadlib (void *lib) {
} }
static void *ll_load (lua_State *L, const char *path) { static void *ll_load (lua_State *L, const char *path, int seeglb) {
void *lib = dlopen(path, RTLD_NOW); void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
if (lib == NULL) lua_pushstring(L, dlerror()); if (lib == NULL) lua_pushstring(L, dlerror());
return lib; return lib;
} }
@ -89,10 +155,15 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
** ======================================================================= ** =======================================================================
*/ */
#include <windows.h> #undef setprogdir
/*
** optional flags for LoadLibraryEx
*/
#if !defined(LUA_LLE_FLAGS)
#define LUA_LLE_FLAGS 0
#endif
#undef setprogdir
static void setprogdir (lua_State *L) { static void setprogdir (lua_State *L) {
char buff[MAX_PATH + 1]; char buff[MAX_PATH + 1];
@ -103,7 +174,7 @@ static void setprogdir (lua_State *L) {
luaL_error(L, "unable to get ModuleFileName"); luaL_error(L, "unable to get ModuleFileName");
else { else {
*lb = '\0'; *lb = '\0';
luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
lua_remove(L, -2); /* remove original string */ lua_remove(L, -2); /* remove original string */
} }
} }
@ -113,26 +184,27 @@ static void pusherror (lua_State *L) {
int error = GetLastError(); int error = GetLastError();
char buffer[128]; char buffer[128];
if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error, 0, buffer, sizeof(buffer), NULL)) NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
lua_pushstring(L, buffer); lua_pushstring(L, buffer);
else else
lua_pushfstring(L, "system error %d\n", error); lua_pushfstring(L, "system error %d\n", error);
} }
static void ll_unloadlib (void *lib) { static void ll_unloadlib (void *lib) {
FreeLibrary((HINSTANCE)lib); FreeLibrary((HMODULE)lib);
} }
static void *ll_load (lua_State *L, const char *path) { static void *ll_load (lua_State *L, const char *path, int seeglb) {
HINSTANCE lib = LoadLibraryA(path); HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
(void)(seeglb); /* not used: symbols are 'global' by default */
if (lib == NULL) pusherror(L); if (lib == NULL) pusherror(L);
return lib; return lib;
} }
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
if (f == NULL) pusherror(L); if (f == NULL) pusherror(L);
return f; return f;
} }
@ -140,88 +212,6 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
/* }====================================================== */ /* }====================================================== */
#elif defined(LUA_DL_DYLD)
/*
** {======================================================================
** Native Mac OS X / Darwin Implementation
** =======================================================================
*/
#include <mach-o/dyld.h>
/* Mac appends a `_' before C function names */
#undef POF
#define POF "_" LUA_POF
static void pusherror (lua_State *L) {
const char *err_str;
const char *err_file;
NSLinkEditErrors err;
int err_num;
NSLinkEditError(&err, &err_num, &err_file, &err_str);
lua_pushstring(L, err_str);
}
static const char *errorfromcode (NSObjectFileImageReturnCode ret) {
switch (ret) {
case NSObjectFileImageInappropriateFile:
return "file is not a bundle";
case NSObjectFileImageArch:
return "library is for wrong CPU type";
case NSObjectFileImageFormat:
return "bad format";
case NSObjectFileImageAccess:
return "cannot access file";
case NSObjectFileImageFailure:
default:
return "unable to load library";
}
}
static void ll_unloadlib (void *lib) {
NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
}
static void *ll_load (lua_State *L, const char *path) {
NSObjectFileImage img;
NSObjectFileImageReturnCode ret;
/* this would be a rare case, but prevents crashing if it happens */
if(!_dyld_present()) {
lua_pushliteral(L, "dyld not present");
return NULL;
}
ret = NSCreateObjectFileImageFromFile(path, &img);
if (ret == NSObjectFileImageSuccess) {
NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |
NSLINKMODULE_OPTION_RETURN_ON_ERROR);
NSDestroyObjectFileImage(img);
if (mod == NULL) pusherror(L);
return mod;
}
lua_pushstring(L, errorfromcode(ret));
return NULL;
}
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);
if (nss == NULL) {
lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
return NULL;
}
return (lua_CFunction)NSAddressOfSymbol(nss);
}
/* }====================================================== */
#else #else
/* /*
** {====================================================== ** {======================================================
@ -237,19 +227,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
static void ll_unloadlib (void *lib) { static void ll_unloadlib (void *lib) {
(void)lib; /* to avoid warnings */ (void)(lib); /* not used */
} }
static void *ll_load (lua_State *L, const char *path) { static void *ll_load (lua_State *L, const char *path, int seeglb) {
(void)path; /* to avoid warnings */ (void)(path); (void)(seeglb); /* not used */
lua_pushliteral(L, DLMSG); lua_pushliteral(L, DLMSG);
return NULL; return NULL;
} }
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
(void)lib; (void)sym; /* to avoid warnings */ (void)(lib); (void)(sym); /* not used */
lua_pushliteral(L, DLMSG); lua_pushliteral(L, DLMSG);
return NULL; return NULL;
} }
@ -266,11 +256,10 @@ static void **ll_register (lua_State *L, const char *path) {
if (!lua_isnil(L, -1)) /* is there an entry? */ if (!lua_isnil(L, -1)) /* is there an entry? */
plib = (void **)lua_touserdata(L, -1); plib = (void **)lua_touserdata(L, -1);
else { /* no entry yet; create one */ else { /* no entry yet; create one */
lua_pop(L, 1); lua_pop(L, 1); /* remove result from gettable */
plib = (void **)lua_newuserdata(L, sizeof(const void *)); plib = (void **)lua_newuserdata(L, sizeof(const void *));
*plib = NULL; *plib = NULL;
luaL_getmetatable(L, "_LOADLIB"); luaL_setmetatable(L, "_LOADLIB");
lua_setmetatable(L, -2);
lua_pushfstring(L, "%s%s", LIBPREFIX, path); lua_pushfstring(L, "%s%s", LIBPREFIX, path);
lua_pushvalue(L, -2); lua_pushvalue(L, -2);
lua_settable(L, LUA_REGISTRYINDEX); lua_settable(L, LUA_REGISTRYINDEX);
@ -293,15 +282,18 @@ static int gctm (lua_State *L) {
static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
void **reg = ll_register(L, path); void **reg = ll_register(L, path);
if (*reg == NULL) *reg = ll_load(L, path); if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
if (*reg == NULL) if (*reg == NULL) return ERRLIB; /* unable to load library */
return ERRLIB; /* unable to load library */ if (*sym == '*') { /* loading only library (no function)? */
lua_pushboolean(L, 1); /* return 'true' */
return 0; /* no errors */
}
else { else {
lua_CFunction f = ll_sym(L, *reg, sym); lua_CFunction f = ll_sym(L, *reg, sym);
if (f == NULL) if (f == NULL)
return ERRFUNC; /* unable to find function */ return ERRFUNC; /* unable to find function */
lua_pushcfunction(L, f); lua_pushcfunction(L, f); /* else create new function */
return 0; /* return function */ return 0; /* no errors */
} }
} }
@ -339,104 +331,137 @@ static int readable (const char *filename) {
static const char *pushnexttemplate (lua_State *L, const char *path) { static const char *pushnexttemplate (lua_State *L, const char *path) {
const char *l; const char *l;
while (*path == *LUA_PATHSEP) path++; /* skip separators */ while (*path == *LUA_PATH_SEP) path++; /* skip separators */
if (*path == '\0') return NULL; /* no more templates */ if (*path == '\0') return NULL; /* no more templates */
l = strchr(path, *LUA_PATHSEP); /* find next separator */ l = strchr(path, *LUA_PATH_SEP); /* find next separator */
if (l == NULL) l = path + strlen(path); if (l == NULL) l = path + strlen(path);
lua_pushlstring(L, path, l - path); /* template */ lua_pushlstring(L, path, l - path); /* template */
return l; return l;
} }
static const char *findfile (lua_State *L, const char *name, static const char *searchpath (lua_State *L, const char *name,
const char *pname) { const char *path,
const char *path; const char *sep,
name = luaL_gsub(L, name, ".", LUA_DIRSEP); const char *dirsep) {
lua_getfield(L, LUA_ENVIRONINDEX, pname); luaL_Buffer msg; /* to build error message */
path = lua_tostring(L, -1); luaL_buffinit(L, &msg);
if (path == NULL) if (*sep != '\0') /* non-empty separator? */
luaL_error(L, LUA_QL("package.%s") " must be a string", pname); name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
lua_pushliteral(L, ""); /* error accumulator */
while ((path = pushnexttemplate(L, path)) != NULL) { while ((path = pushnexttemplate(L, path)) != NULL) {
const char *filename; const char *filename = luaL_gsub(L, lua_tostring(L, -1),
filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); LUA_PATH_MARK, name);
lua_remove(L, -2); /* remove path template */ lua_remove(L, -2); /* remove path template */
if (readable(filename)) /* does file exist and is readable? */ if (readable(filename)) /* does file exist and is readable? */
return filename; /* return that file name */ return filename; /* return that file name */
lua_pushfstring(L, "\n\tno file " LUA_QS, filename); lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
lua_remove(L, -2); /* remove file name */ lua_remove(L, -2); /* remove file name */
lua_concat(L, 2); /* add entry to possible error message */ luaL_addvalue(&msg); /* concatenate error msg. entry */
} }
luaL_pushresult(&msg); /* create error message */
return NULL; /* not found */ return NULL; /* not found */
} }
static void loaderror (lua_State *L, const char *filename) { static int ll_searchpath (lua_State *L) {
luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", const char *f = searchpath(L, luaL_checkstring(L, 1),
lua_tostring(L, 1), filename, lua_tostring(L, -1)); luaL_checkstring(L, 2),
luaL_optstring(L, 3, "."),
luaL_optstring(L, 4, LUA_DIRSEP));
if (f != NULL) return 1;
else { /* error message is on top of the stack */
lua_pushnil(L);
lua_insert(L, -2);
return 2; /* return nil + error message */
}
} }
static int loader_Lua (lua_State *L) { static const char *findfile (lua_State *L, const char *name,
const char *pname,
const char *dirsep) {
const char *path;
lua_getfield(L, lua_upvalueindex(1), pname);
path = lua_tostring(L, -1);
if (path == NULL)
luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
return searchpath(L, name, path, ".", dirsep);
}
static int checkload (lua_State *L, int stat, const char *filename) {
if (stat) { /* module loaded successfully? */
lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2; /* return open function and file name */
}
else
return luaL_error(L, "error loading module " LUA_QS
" from file " LUA_QS ":\n\t%s",
lua_tostring(L, 1), filename, lua_tostring(L, -1));
}
static int searcher_Lua (lua_State *L) {
const char *filename; const char *filename;
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path"); filename = findfile(L, name, "path", LUA_LSUBSEP);
if (filename == NULL) return 1; /* library not found in this path */ if (filename == NULL) return 1; /* module not found in this path */
if (luaL_loadfile(L, filename) != 0) return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
loaderror(L, filename);
return 1; /* library loaded successfully */
} }
static const char *mkfuncname (lua_State *L, const char *modname) { static int loadfunc (lua_State *L, const char *filename, const char *modname) {
const char *funcname; const char *funcname;
const char *mark = strchr(modname, *LUA_IGMARK); const char *mark;
if (mark) modname = mark + 1; modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); mark = strchr(modname, *LUA_IGMARK);
funcname = lua_pushfstring(L, POF"%s", funcname); if (mark) {
lua_remove(L, -2); /* remove 'gsub' result */ int stat;
return funcname; funcname = lua_pushlstring(L, modname, mark - modname);
funcname = lua_pushfstring(L, POF"%s", funcname);
stat = ll_loadfunc(L, filename, funcname);
if (stat != ERRFUNC) return stat;
modname = mark + 1; /* else go ahead and try old-style name */
}
funcname = lua_pushfstring(L, POF"%s", modname);
return ll_loadfunc(L, filename, funcname);
} }
static int loader_C (lua_State *L) { static int searcher_C (lua_State *L) {
const char *funcname;
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
const char *filename = findfile(L, name, "cpath"); const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
if (filename == NULL) return 1; /* library not found in this path */ if (filename == NULL) return 1; /* module not found in this path */
funcname = mkfuncname(L, name); return checkload(L, (loadfunc(L, filename, name) == 0), filename);
if (ll_loadfunc(L, filename, funcname) != 0)
loaderror(L, filename);
return 1; /* library loaded successfully */
} }
static int loader_Croot (lua_State *L) { static int searcher_Croot (lua_State *L) {
const char *funcname;
const char *filename; const char *filename;
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
const char *p = strchr(name, '.'); const char *p = strchr(name, '.');
int stat; int stat;
if (p == NULL) return 0; /* is root */ if (p == NULL) return 0; /* is root */
lua_pushlstring(L, name, p - name); lua_pushlstring(L, name, p - name);
filename = findfile(L, lua_tostring(L, -1), "cpath"); filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
if (filename == NULL) return 1; /* root not found */ if (filename == NULL) return 1; /* root not found */
funcname = mkfuncname(L, name); if ((stat = loadfunc(L, filename, name)) != 0) {
if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { if (stat != ERRFUNC)
if (stat != ERRFUNC) loaderror(L, filename); /* real error */ return checkload(L, 0, filename); /* real error */
lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, else { /* open function not found */
name, filename); lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
return 1; /* function not found */ name, filename);
return 1;
}
} }
return 1; lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2;
} }
static int loader_preload (lua_State *L) { static int searcher_preload (lua_State *L) {
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
lua_getfield(L, LUA_ENVIRONINDEX, "preload"); lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
if (!lua_istable(L, -1))
luaL_error(L, LUA_QL("package.preload") " must be a table");
lua_getfield(L, -1, name); lua_getfield(L, -1, name);
if (lua_isnil(L, -1)) /* not found? */ if (lua_isnil(L, -1)) /* not found? */
lua_pushfstring(L, "\n\tno field package.preload['%s']", name); lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
@ -444,48 +469,53 @@ static int loader_preload (lua_State *L) {
} }
static const int sentinel_ = 0; static void findloader (lua_State *L, const char *name) {
#define sentinel ((void *)&sentinel_) int i;
luaL_Buffer msg; /* to build error message */
luaL_buffinit(L, &msg);
lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */
if (!lua_istable(L, 3))
luaL_error(L, LUA_QL("package.searchers") " must be a table");
/* iterate over available seachers to find a loader */
for (i = 1; ; i++) {
lua_rawgeti(L, 3, i); /* get a seacher */
if (lua_isnil(L, -1)) { /* no more searchers? */
lua_pop(L, 1); /* remove nil */
luaL_pushresult(&msg); /* create error message */
luaL_error(L, "module " LUA_QS " not found:%s",
name, lua_tostring(L, -1));
}
lua_pushstring(L, name);
lua_call(L, 1, 2); /* call it */
if (lua_isfunction(L, -2)) /* did it find a loader? */
return; /* module loader found */
else if (lua_isstring(L, -2)) { /* searcher returned error message? */
lua_pop(L, 1); /* remove extra return */
luaL_addvalue(&msg); /* concatenate error message */
}
else
lua_pop(L, 2); /* remove both returns */
}
}
static int ll_require (lua_State *L) { static int ll_require (lua_State *L) {
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
int i;
lua_settop(L, 1); /* _LOADED table will be at index 2 */ lua_settop(L, 1); /* _LOADED table will be at index 2 */
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
lua_getfield(L, 2, name); lua_getfield(L, 2, name); /* _LOADED[name] */
if (lua_toboolean(L, -1)) { /* is it there? */ if (lua_toboolean(L, -1)) /* is it there? */
if (lua_touserdata(L, -1) == sentinel) /* check loops */
luaL_error(L, "loop or previous error loading module " LUA_QS, name);
return 1; /* package is already loaded */ return 1; /* package is already loaded */
} /* else must load package */
/* else must load it; iterate over available loaders */ lua_pop(L, 1); /* remove 'getfield' result */
lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); findloader(L, name);
if (!lua_istable(L, -1)) lua_pushstring(L, name); /* pass name as argument to module loader */
luaL_error(L, LUA_QL("package.loaders") " must be a table"); lua_insert(L, -2); /* name is 1st argument (before search data) */
lua_pushliteral(L, ""); /* error message accumulator */ lua_call(L, 2, 1); /* run loader to load module */
for (i=1; ; i++) {
lua_rawgeti(L, -2, i); /* get a loader */
if (lua_isnil(L, -1))
luaL_error(L, "module " LUA_QS " not found:%s",
name, lua_tostring(L, -2));
lua_pushstring(L, name);
lua_call(L, 1, 1); /* call it */
if (lua_isfunction(L, -1)) /* did it find module? */
break; /* module loaded successfully */
else if (lua_isstring(L, -1)) /* loader returned error message? */
lua_concat(L, 2); /* accumulate it */
else
lua_pop(L, 1);
}
lua_pushlightuserdata(L, sentinel);
lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
lua_pushstring(L, name); /* pass name as argument to module */
lua_call(L, 1, 1); /* run loaded module */
if (!lua_isnil(L, -1)) /* non-nil return? */ if (!lua_isnil(L, -1)) /* non-nil return? */
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
lua_getfield(L, 2, name); lua_getfield(L, 2, name);
if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ if (lua_isnil(L, -1)) { /* module did not set a value? */
lua_pushboolean(L, 1); /* use true as result */ lua_pushboolean(L, 1); /* use true as result */
lua_pushvalue(L, -1); /* extra copy to be returned */ lua_pushvalue(L, -1); /* extra copy to be returned */
lua_setfield(L, 2, name); /* _LOADED[name] = true */ lua_setfield(L, 2, name); /* _LOADED[name] = true */
@ -502,26 +532,31 @@ static int ll_require (lua_State *L) {
** 'module' function ** 'module' function
** ======================================================= ** =======================================================
*/ */
#if defined(LUA_COMPAT_MODULE)
static void setfenv (lua_State *L) { /*
** changes the environment variable of calling function
*/
static void set_env (lua_State *L) {
lua_Debug ar; lua_Debug ar;
if (lua_getstack(L, 1, &ar) == 0 || if (lua_getstack(L, 1, &ar) == 0 ||
lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
lua_iscfunction(L, -1)) lua_iscfunction(L, -1))
luaL_error(L, LUA_QL("module") " not called from a Lua function"); luaL_error(L, LUA_QL("module") " not called from a Lua function");
lua_pushvalue(L, -2); lua_pushvalue(L, -2); /* copy new environment table to top */
lua_setfenv(L, -2); lua_setupvalue(L, -2, 1);
lua_pop(L, 1); lua_pop(L, 1); /* remove function */
} }
static void dooptions (lua_State *L, int n) { static void dooptions (lua_State *L, int n) {
int i; int i;
for (i = 2; i <= n; i++) { for (i = 2; i <= n; i++) {
lua_pushvalue(L, i); /* get option (a function) */ if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */
lua_pushvalue(L, -2); /* module */ lua_pushvalue(L, i); /* get option (a function) */
lua_call(L, 1, 0); lua_pushvalue(L, -2); /* module */
lua_call(L, 1, 0);
}
} }
} }
@ -543,17 +578,8 @@ static void modinit (lua_State *L, const char *modname) {
static int ll_module (lua_State *L) { static int ll_module (lua_State *L) {
const char *modname = luaL_checkstring(L, 1); const char *modname = luaL_checkstring(L, 1);
int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ int lastarg = lua_gettop(L); /* last parameter */
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); luaL_pushmodule(L, modname, 1); /* get/create module table */
lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
if (!lua_istable(L, -1)) { /* not found? */
lua_pop(L, 1); /* remove previous result */
/* try global variable (and create one if it does not exist) */
if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
return luaL_error(L, "name conflict for module " LUA_QS, modname);
lua_pushvalue(L, -1);
lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
}
/* check whether table already has a _NAME field */ /* check whether table already has a _NAME field */
lua_getfield(L, -1, "_NAME"); lua_getfield(L, -1, "_NAME");
if (!lua_isnil(L, -1)) /* is table an initialized module? */ if (!lua_isnil(L, -1)) /* is table an initialized module? */
@ -563,9 +589,9 @@ static int ll_module (lua_State *L) {
modinit(L, modname); modinit(L, modname);
} }
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
setfenv(L); set_env(L);
dooptions(L, loaded - 1); dooptions(L, lastarg);
return 0; return 1;
} }
@ -576,12 +602,12 @@ static int ll_seeall (lua_State *L) {
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setmetatable(L, 1); lua_setmetatable(L, 1);
} }
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushglobaltable(L);
lua_setfield(L, -2, "__index"); /* mt.__index = _G */ lua_setfield(L, -2, "__index"); /* mt.__index = _G */
return 0; return 0;
} }
#endif
/* }====================================================== */ /* }====================================================== */
@ -589,15 +615,30 @@ static int ll_seeall (lua_State *L) {
/* auxiliary mark (for internal use) */ /* auxiliary mark (for internal use) */
#define AUXMARK "\1" #define AUXMARK "\1"
static void setpath (lua_State *L, const char *fieldname, const char *envname,
const char *def) { /*
const char *path = getenv(envname); ** return registry.LUA_NOENV as a boolean
*/
static int noenv (lua_State *L) {
int b;
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
b = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove value */
return b;
}
static void setpath (lua_State *L, const char *fieldname, const char *envname1,
const char *envname2, const char *def) {
const char *path = getenv(envname1);
if (path == NULL) /* no environment variable? */ if (path == NULL) /* no environment variable? */
path = getenv(envname2); /* try alternative name */
if (path == NULL || noenv(L)) /* no environment variable? */
lua_pushstring(L, def); /* use default */ lua_pushstring(L, def); /* use default */
else { else {
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
LUA_PATHSEP AUXMARK LUA_PATHSEP); LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
luaL_gsub(L, path, AUXMARK, def); luaL_gsub(L, path, AUXMARK, def);
lua_remove(L, -2); lua_remove(L, -2);
} }
@ -608,59 +649,66 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname,
static const luaL_Reg pk_funcs[] = { static const luaL_Reg pk_funcs[] = {
{"loadlib", ll_loadlib}, {"loadlib", ll_loadlib},
{"searchpath", ll_searchpath},
#if defined(LUA_COMPAT_MODULE)
{"seeall", ll_seeall}, {"seeall", ll_seeall},
#endif
{NULL, NULL} {NULL, NULL}
}; };
static const luaL_Reg ll_funcs[] = { static const luaL_Reg ll_funcs[] = {
#if defined(LUA_COMPAT_MODULE)
{"module", ll_module}, {"module", ll_module},
#endif
{"require", ll_require}, {"require", ll_require},
{NULL, NULL} {NULL, NULL}
}; };
static const lua_CFunction loaders[] = static const lua_CFunction searchers[] =
{loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
LUALIB_API int luaopen_package (lua_State *L) { LUAMOD_API int luaopen_package (lua_State *L) {
int i; int i;
/* create new type _LOADLIB */ /* create new type _LOADLIB */
luaL_newmetatable(L, "_LOADLIB"); luaL_newmetatable(L, "_LOADLIB");
lua_pushcfunction(L, gctm); lua_pushcfunction(L, gctm);
lua_setfield(L, -2, "__gc"); lua_setfield(L, -2, "__gc");
/* create `package' table */ /* create `package' table */
luaL_register(L, LUA_LOADLIBNAME, pk_funcs); luaL_newlib(L, pk_funcs);
#if defined(LUA_COMPAT_LOADLIB) /* create 'searchers' table */
lua_getfield(L, -1, "loadlib"); lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); /* fill it with pre-defined searchers */
#endif for (i=0; searchers[i] != NULL; i++) {
lua_pushvalue(L, -1); lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
lua_replace(L, LUA_ENVIRONINDEX); lua_pushcclosure(L, searchers[i], 1);
/* create `loaders' table */
lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);
/* fill it with pre-defined loaders */
for (i=0; loaders[i] != NULL; i++) {
lua_pushcfunction(L, loaders[i]);
lua_rawseti(L, -2, i+1); lua_rawseti(L, -2, i+1);
} }
lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ #if defined(LUA_COMPAT_LOADERS)
setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ lua_pushvalue(L, -1); /* make a copy of 'searchers' table */
setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */
#endif
lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */
/* set field 'path' */
setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
/* set field 'cpath' */
setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
/* store config information */ /* store config information */
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
LUA_EXECDIR "\n" LUA_IGMARK); LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
lua_setfield(L, -2, "config"); lua_setfield(L, -2, "config");
/* set field `loaded' */ /* set field `loaded' */
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
lua_setfield(L, -2, "loaded"); lua_setfield(L, -2, "loaded");
/* set field `preload' */ /* set field `preload' */
lua_newtable(L); luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
lua_setfield(L, -2, "preload"); lua_setfield(L, -2, "preload");
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushglobaltable(L);
luaL_register(L, NULL, ll_funcs); /* open lib into global table */ lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
lua_pop(L, 1); luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
lua_pop(L, 1); /* pop global table */
return 1; /* return 'package' table */ return 1; /* return 'package' table */
} }

@ -1,10 +1,9 @@
/* /*
** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lobject.c,v 2.55 2011/11/30 19:30:16 roberto Exp $
** Some generic functions over Lua objects ** Some generic functions over Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -15,6 +14,8 @@
#include "lua.h" #include "lua.h"
#include "lctype.h"
#include "ldebug.h"
#include "ldo.h" #include "ldo.h"
#include "lmem.h" #include "lmem.h"
#include "lobject.h" #include "lobject.h"
@ -24,7 +25,7 @@
const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
/* /*
@ -33,25 +34,25 @@ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
** eeeee != 0 and (xxx) otherwise. ** eeeee != 0 and (xxx) otherwise.
*/ */
int luaO_int2fb (unsigned int x) { int luaO_int2fb (unsigned int x) {
int e = 0; /* expoent */ int e = 0; /* exponent */
while (x >= 16) { if (x < 8) return x;
while (x >= 0x10) {
x = (x+1) >> 1; x = (x+1) >> 1;
e++; e++;
} }
if (x < 8) return x; return ((e+1) << 3) | (cast_int(x) - 8);
else return ((e+1) << 3) | (cast_int(x) - 8);
} }
/* converts back */ /* converts back */
int luaO_fb2int (int x) { int luaO_fb2int (int x) {
int e = (x >> 3) & 31; int e = (x >> 3) & 0x1f;
if (e == 0) return x; if (e == 0) return x;
else return ((x & 7)+8) << (e - 1); else return ((x & 7) + 8) << (e - 1);
} }
int luaO_log2 (unsigned int x) { int luaO_ceillog2 (unsigned int x) {
static const lu_byte log_2[256] = { static const lu_byte log_2[256] = {
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
@ -62,55 +63,122 @@ int luaO_log2 (unsigned int x) {
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
}; };
int l = -1; int l = 0;
x--;
while (x >= 256) { l += 8; x >>= 8; } while (x >= 256) { l += 8; x >>= 8; }
return l + log_2[x]; return l + log_2[x];
}
lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) {
switch (op) {
case LUA_OPADD: return luai_numadd(NULL, v1, v2);
case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
case LUA_OPMUL: return luai_nummul(NULL, v1, v2);
case LUA_OPDIV: return luai_numdiv(NULL, v1, v2);
case LUA_OPMOD: return luai_nummod(NULL, v1, v2);
case LUA_OPPOW: return luai_numpow(NULL, v1, v2);
case LUA_OPUNM: return luai_numunm(NULL, v1);
default: lua_assert(0); return 0;
}
}
int luaO_hexavalue (int c) {
if (lisdigit(c)) return c - '0';
else return ltolower(c) - 'a' + 10;
}
#if !defined(lua_strx2number)
#include <math.h>
static int isneg (const char **s) {
if (**s == '-') { (*s)++; return 1; }
else if (**s == '+') (*s)++;
return 0;
}
static lua_Number readhexa (const char **s, lua_Number r, int *count) {
for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */
r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(**s)));
(*count)++;
}
return r;
} }
int luaO_rawequalObj (const TValue *t1, const TValue *t2) { /*
if (ttype(t1) != ttype(t2)) return 0; ** convert an hexadecimal numeric string to a number, following
else switch (ttype(t1)) { ** C99 specification for 'strtod'
case LUA_TNIL: */
return 1; static lua_Number lua_strx2number (const char *s, char **endptr) {
case LUA_TNUMBER: lua_Number r = 0.0;
return luai_numeq(nvalue(t1), nvalue(t2)); int e = 0, i = 0;
case LUA_TBOOLEAN: int neg = 0; /* 1 if number is negative */
return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ *endptr = cast(char *, s); /* nothing is valid yet */
case LUA_TLIGHTUSERDATA: while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
return pvalue(t1) == pvalue(t2); neg = isneg(&s); /* check signal */
default: if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
lua_assert(iscollectable(t1)); return 0.0; /* invalid format (no '0x') */
return gcvalue(t1) == gcvalue(t2); s += 2; /* skip '0x' */
r = readhexa(&s, r, &i); /* read integer part */
if (*s == '.') {
s++; /* skip dot */
r = readhexa(&s, r, &e); /* read fractional part */
} }
if (i == 0 && e == 0)
return 0.0; /* invalid format (no digit) */
e *= -4; /* each fractional digit divides value by 2^-4 */
*endptr = cast(char *, s); /* valid up to here */
if (*s == 'p' || *s == 'P') { /* exponent part? */
int exp1 = 0;
int neg1;
s++; /* skip 'p' */
neg1 = isneg(&s); /* signal */
if (!lisdigit(cast_uchar(*s)))
goto ret; /* must have at least one digit */
while (lisdigit(cast_uchar(*s))) /* read exponent */
exp1 = exp1 * 10 + *(s++) - '0';
if (neg1) exp1 = -exp1;
e += exp1;
}
*endptr = cast(char *, s); /* valid up to here */
ret:
if (neg) r = -r;
return ldexp(r, e);
} }
#endif
int luaO_str2d (const char *s, lua_Number *result) { int luaO_str2d (const char *s, size_t len, lua_Number *result) {
char *endptr; char *endptr;
*result = lua_str2number(s, &endptr); if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
if (endptr == s) return 0; /* conversion failed */ return 0;
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ else if (strpbrk(s, "xX")) /* hexa? */
*result = cast_num(strtoul(s, &endptr, 16)); *result = lua_strx2number(s, &endptr);
if (*endptr == '\0') return 1; /* most common case */ else
while (isspace(cast(unsigned char, *endptr))) endptr++; *result = lua_str2number(s, &endptr);
if (*endptr != '\0') return 0; /* invalid trailing characters? */ if (endptr == s) return 0; /* nothing recognized */
return 1; while (lisspace(cast_uchar(*endptr))) endptr++;
return (endptr == s + len); /* OK if no trailing characters */
} }
static void pushstr (lua_State *L, const char *str) { static void pushstr (lua_State *L, const char *str, size_t l) {
setsvalue2s(L, L->top, luaS_new(L, str)); setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
incr_top(L); incr_top(L);
} }
/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 1; int n = 0;
pushstr(L, "");
for (;;) { for (;;) {
const char *e = strchr(fmt, '%'); const char *e = strchr(fmt, '%');
if (e == NULL) break; if (e == NULL) break;
@ -120,14 +188,13 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
case 's': { case 's': {
const char *s = va_arg(argp, char *); const char *s = va_arg(argp, char *);
if (s == NULL) s = "(null)"; if (s == NULL) s = "(null)";
pushstr(L, s); pushstr(L, s, strlen(s));
break; break;
} }
case 'c': { case 'c': {
char buff[2]; char buff;
buff[0] = cast(char, va_arg(argp, int)); buff = cast(char, va_arg(argp, int));
buff[1] = '\0'; pushstr(L, &buff, 1);
pushstr(L, buff);
break; break;
} }
case 'd': { case 'd': {
@ -142,29 +209,25 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
} }
case 'p': { case 'p': {
char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
sprintf(buff, "%p", va_arg(argp, void *)); int l = sprintf(buff, "%p", va_arg(argp, void *));
pushstr(L, buff); pushstr(L, buff, l);
break; break;
} }
case '%': { case '%': {
pushstr(L, "%"); pushstr(L, "%", 1);
break; break;
} }
default: { default: {
char buff[3]; luaG_runerror(L,
buff[0] = '%'; "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
buff[1] = *(e+1); *(e + 1));
buff[2] = '\0';
pushstr(L, buff);
break;
} }
} }
n += 2; n += 2;
fmt = e+2; fmt = e+2;
} }
pushstr(L, fmt); pushstr(L, fmt, strlen(fmt));
luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); if (n > 0) luaV_concat(L, n + 1);
L->top -= n;
return svalue(L->top - 1); return svalue(L->top - 1);
} }
@ -179,36 +242,48 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
} }
/* number of chars of a literal string without the ending \0 */
#define LL(x) (sizeof(x)/sizeof(char) - 1)
#define RETS "..."
#define PRE "[string \""
#define POS "\"]"
#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
void luaO_chunkid (char *out, const char *source, size_t bufflen) { void luaO_chunkid (char *out, const char *source, size_t bufflen) {
if (*source == '=') { size_t l = strlen(source);
strncpy(out, source+1, bufflen); /* remove first char */ if (*source == '=') { /* 'literal' source */
out[bufflen-1] = '\0'; /* ensures null termination */ if (l <= bufflen) /* small enough? */
memcpy(out, source + 1, l * sizeof(char));
else { /* truncate it */
addstr(out, source + 1, bufflen - 1);
*out = '\0';
}
} }
else { /* out = "source", or "...source" */ else if (*source == '@') { /* file name */
if (*source == '@') { if (l <= bufflen) /* small enough? */
size_t l; memcpy(out, source + 1, l * sizeof(char));
source++; /* skip the `@' */ else { /* add '...' before rest of name */
bufflen -= sizeof(" '...' "); addstr(out, RETS, LL(RETS));
l = strlen(source); bufflen -= LL(RETS);
strcpy(out, ""); memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
if (l > bufflen) {
source += (l-bufflen); /* get last part of file name */
strcat(out, "...");
}
strcat(out, source);
} }
else { /* out = [string "string"] */ }
size_t len = strcspn(source, "\n\r"); /* stop at first newline */ else { /* string; format as [string "source"] */
bufflen -= sizeof(" [string \"...\"] "); const char *nl = strchr(source, '\n'); /* find first new line (if any) */
if (len > bufflen) len = bufflen; addstr(out, PRE, LL(PRE)); /* add prefix */
strcpy(out, "[string \""); bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
if (source[len] != '\0') { /* must truncate? */ if (l < bufflen && nl == NULL) { /* small one-line source? */
strncat(out, source, len); addstr(out, source, l); /* keep it */
strcat(out, "...");
}
else
strcat(out, source);
strcat(out, "\"]");
} }
else {
if (nl != NULL) l = nl - source; /* stop at first newline */
if (l > bufflen) l = bufflen;
addstr(out, source, l);
addstr(out, RETS, LL(RETS));
}
memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
} }
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lopcodes.c,v 1.48 2011/04/19 16:22:13 roberto Exp $
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,15 +13,16 @@
/* ORDER OP */ /* ORDER OP */
const char *const luaP_opnames[NUM_OPCODES+1] = { LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"MOVE", "MOVE",
"LOADK", "LOADK",
"LOADKX",
"LOADBOOL", "LOADBOOL",
"LOADNIL", "LOADNIL",
"GETUPVAL", "GETUPVAL",
"GETGLOBAL", "GETTABUP",
"GETTABLE", "GETTABLE",
"SETGLOBAL", "SETTABUP",
"SETUPVAL", "SETUPVAL",
"SETTABLE", "SETTABLE",
"NEWTABLE", "NEWTABLE",
@ -47,27 +48,29 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
"RETURN", "RETURN",
"FORLOOP", "FORLOOP",
"FORPREP", "FORPREP",
"TFORCALL",
"TFORLOOP", "TFORLOOP",
"SETLIST", "SETLIST",
"CLOSE",
"CLOSURE", "CLOSURE",
"VARARG", "VARARG",
"EXTRAARG",
NULL NULL
}; };
#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
const lu_byte luaP_opmodes[NUM_OPCODES] = { LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* T A B C mode opcode */ /* T A B C mode opcode */
opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
@ -86,17 +89,18 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */
,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */
,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */
,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */
}; };

@ -1,5 +1,5 @@
/* /*
** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ ** $Id: loslib.c,v 1.38 2011/11/30 12:35:05 roberto Exp $
** Standard Operating System library ** Standard Operating System library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -20,37 +20,84 @@
#include "lualib.h" #include "lualib.h"
static int os_pushresult (lua_State *L, int i, const char *filename) { /*
int en = errno; /* calls to Lua API may change this value */ ** list of valid conversion specifiers for the 'strftime' function
if (i) { */
lua_pushboolean(L, 1); #if !defined(LUA_STRFTIMEOPTIONS)
return 1;
} #if !defined(LUA_USE_POSIX)
else { #define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
lua_pushnil(L); #else
lua_pushfstring(L, "%s: %s", filename, strerror(en)); #define LUA_STRFTIMEOPTIONS { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
lua_pushinteger(L, en); "E", "cCxXyY", \
return 3; "O", "deHImMSuUVwWy" }
} #endif
}
#endif
/*
** By default, Lua uses tmpnam except when POSIX is available, where it
** uses mkstemp.
*/
#if defined(LUA_USE_MKSTEMP)
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
#define lua_tmpnam(b,e) { \
strcpy(b, "/tmp/lua_XXXXXX"); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
#elif !defined(lua_tmpnam)
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif
/*
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
#if defined(LUA_USE_GMTIME_R)
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
#elif !defined(l_gmtime)
#define l_gmtime(t,r) ((void)r, gmtime(t))
#define l_localtime(t,r) ((void)r, localtime(t))
#endif
static int os_execute (lua_State *L) { static int os_execute (lua_State *L) {
lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); const char *cmd = luaL_optstring(L, 1, NULL);
return 1; int stat = system(cmd);
if (cmd != NULL)
return luaL_execresult(L, stat);
else {
lua_pushboolean(L, stat); /* true if there is a shell */
return 1;
}
} }
static int os_remove (lua_State *L) { static int os_remove (lua_State *L) {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
return os_pushresult(L, remove(filename) == 0, filename); return luaL_fileresult(L, remove(filename) == 0, filename);
} }
static int os_rename (lua_State *L) { static int os_rename (lua_State *L) {
const char *fromname = luaL_checkstring(L, 1); const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2); const char *toname = luaL_checkstring(L, 2);
return os_pushresult(L, rename(fromname, toname) == 0, fromname); return luaL_fileresult(L, rename(fromname, toname) == 0, fromname);
} }
@ -107,11 +154,10 @@ static int getboolfield (lua_State *L, const char *key) {
static int getfield (lua_State *L, const char *key, int d) { static int getfield (lua_State *L, const char *key, int d) {
int res; int res, isnum;
lua_getfield(L, -1, key); lua_getfield(L, -1, key);
if (lua_isnumber(L, -1)) res = (int)lua_tointegerx(L, -1, &isnum);
res = (int)lua_tointeger(L, -1); if (!isnum) {
else {
if (d < 0) if (d < 0)
return luaL_error(L, "field " LUA_QS " missing in date table", key); return luaL_error(L, "field " LUA_QS " missing in date table", key);
res = d; res = d;
@ -121,16 +167,40 @@ static int getfield (lua_State *L, const char *key, int d) {
} }
static const char *checkoption (lua_State *L, const char *conv, char *buff) {
static const char *const options[] = LUA_STRFTIMEOPTIONS;
unsigned int i;
for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {
if (*conv != '\0' && strchr(options[i], *conv) != NULL) {
buff[1] = *conv;
if (*options[i + 1] == '\0') { /* one-char conversion specifier? */
buff[2] = '\0'; /* end buffer */
return conv + 1;
}
else if (*(conv + 1) != '\0' &&
strchr(options[i + 1], *(conv + 1)) != NULL) {
buff[2] = *(conv + 1); /* valid two-char conversion specifier */
buff[3] = '\0'; /* end buffer */
return conv + 2;
}
}
}
luaL_argerror(L, 1,
lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
return conv; /* to avoid warnings */
}
static int os_date (lua_State *L) { static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c"); const char *s = luaL_optstring(L, 1, "%c");
time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
struct tm *stm; struct tm tmr, *stm;
if (*s == '!') { /* UTC? */ if (*s == '!') { /* UTC? */
stm = gmtime(&t); stm = l_gmtime(&t, &tmr);
s++; /* skip `!' */ s++; /* skip `!' */
} }
else else
stm = localtime(&t); stm = l_localtime(&t, &tmr);
if (stm == NULL) /* invalid date? */ if (stm == NULL) /* invalid date? */
lua_pushnil(L); lua_pushnil(L);
else if (strcmp(s, "*t") == 0) { else if (strcmp(s, "*t") == 0) {
@ -146,17 +216,17 @@ static int os_date (lua_State *L) {
setboolfield(L, "isdst", stm->tm_isdst); setboolfield(L, "isdst", stm->tm_isdst);
} }
else { else {
char cc[3]; char cc[4];
luaL_Buffer b; luaL_Buffer b;
cc[0] = '%'; cc[2] = '\0'; cc[0] = '%';
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
for (; *s; s++) { while (*s) {
if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ if (*s != '%') /* no conversion specifier? */
luaL_addchar(&b, *s); luaL_addchar(&b, *s++);
else { else {
size_t reslen; size_t reslen;
char buff[200]; /* should be big enough for any conversion result */ char buff[200]; /* should be big enough for any conversion result */
cc[1] = *(++s); s = checkoption(L, s + 1, cc);
reslen = strftime(buff, sizeof(buff), cc, stm); reslen = strftime(buff, sizeof(buff), cc, stm);
luaL_addlstring(&b, buff, reslen); luaL_addlstring(&b, buff, reslen);
} }
@ -214,9 +284,18 @@ static int os_setlocale (lua_State *L) {
static int os_exit (lua_State *L) { static int os_exit (lua_State *L) {
exit(luaL_optint(L, 1, EXIT_SUCCESS)); int status;
if (lua_isboolean(L, 1))
status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
else
status = luaL_optint(L, 1, EXIT_SUCCESS);
if (lua_toboolean(L, 2))
lua_close(L);
if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
return 0;
} }
static const luaL_Reg syslib[] = { static const luaL_Reg syslib[] = {
{"clock", os_clock}, {"clock", os_clock},
{"date", os_date}, {"date", os_date},
@ -236,8 +315,8 @@ static const luaL_Reg syslib[] = {
LUALIB_API int luaopen_os (lua_State *L) { LUAMOD_API int luaopen_os (lua_State *L) {
luaL_register(L, LUA_OSLIBNAME, syslib); luaL_newlib(L, syslib);
return 1; return 1;
} }

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ ** $Id: lstate.c,v 2.92 2011/10/03 17:54:25 roberto Exp $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -12,6 +12,7 @@
#include "lua.h" #include "lua.h"
#include "lapi.h"
#include "ldebug.h" #include "ldebug.h"
#include "ldo.h" #include "ldo.h"
#include "lfunc.h" #include "lfunc.h"
@ -24,119 +25,203 @@
#include "ltm.h" #include "ltm.h"
#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) #if !defined(LUAI_GCPAUSE)
#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) #define LUAI_GCPAUSE 200 /* 200% */
#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) #endif
#if !defined(LUAI_GCMAJOR)
#define LUAI_GCMAJOR 200 /* 200% */
#endif
#if !defined(LUAI_GCMUL)
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
#endif
#define MEMERRMSG "not enough memory"
/*
** thread state + extra space
*/
typedef struct LX {
#if defined(LUAI_EXTRASPACE)
char buff[LUAI_EXTRASPACE];
#endif
lua_State l;
} LX;
/* /*
** Main thread combines a thread state and the global state ** Main thread combines a thread state and the global state
*/ */
typedef struct LG { typedef struct LG {
lua_State l; LX l;
global_State g; global_State g;
} LG; } LG;
#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
/*
** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
** invariant
*/
void luaE_setdebt (global_State *g, l_mem debt) {
g->totalbytes -= (debt - g->GCdebt);
g->GCdebt = debt;
}
CallInfo *luaE_extendCI (lua_State *L) {
CallInfo *ci = luaM_new(L, CallInfo);
lua_assert(L->ci->next == NULL);
L->ci->next = ci;
ci->previous = L->ci;
ci->next = NULL;
return ci;
}
void luaE_freeCI (lua_State *L) {
CallInfo *ci = L->ci;
CallInfo *next = ci->next;
ci->next = NULL;
while ((ci = next) != NULL) {
next = ci->next;
luaM_free(L, ci);
}
}
static void stack_init (lua_State *L1, lua_State *L) { static void stack_init (lua_State *L1, lua_State *L) {
/* initialize CallInfo array */ int i; CallInfo *ci;
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
L1->ci = L1->base_ci;
L1->size_ci = BASIC_CI_SIZE;
L1->end_ci = L1->base_ci + L1->size_ci - 1;
/* initialize stack array */ /* initialize stack array */
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue);
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; L1->stacksize = BASIC_STACK_SIZE;
for (i = 0; i < BASIC_STACK_SIZE; i++)
setnilvalue(L1->stack + i); /* erase new stack */
L1->top = L1->stack; L1->top = L1->stack;
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
/* initialize first ci */ /* initialize first ci */
L1->ci->func = L1->top; ci = &L1->base_ci;
setnilvalue(L1->top++); /* `function' entry for this `ci' */ ci->next = ci->previous = NULL;
L1->base = L1->ci->base = L1->top; ci->callstatus = 0;
L1->ci->top = L1->top + LUA_MINSTACK; ci->func = L1->top;
setnilvalue(L1->top++); /* 'function' entry for this 'ci' */
ci->top = L1->top + LUA_MINSTACK;
L1->ci = ci;
}
static void freestack (lua_State *L) {
if (L->stack == NULL)
return; /* stack not completely built yet */
L->ci = &L->base_ci; /* free the entire 'ci' list */
luaE_freeCI(L);
luaM_freearray(L, L->stack, L->stacksize); /* free stack array */
} }
static void freestack (lua_State *L, lua_State *L1) { /*
luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); ** Create registry table and its predefined values
luaM_freearray(L, L1->stack, L1->stacksize, TValue); */
static void init_registry (lua_State *L, global_State *g) {
TValue mt;
/* create registry */
Table *registry = luaH_new(L);
sethvalue(L, &g->l_registry, registry);
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
/* registry[LUA_RIDX_MAINTHREAD] = L */
setthvalue(L, &mt, L);
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
/* registry[LUA_RIDX_GLOBALS] = table of globals */
sethvalue(L, &mt, luaH_new(L));
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
} }
/* /*
** open parts that may cause memory-allocation errors ** open parts of the state that may cause memory-allocation errors
*/ */
static void f_luaopen (lua_State *L, void *ud) { static void f_luaopen (lua_State *L, void *ud) {
global_State *g = G(L); global_State *g = G(L);
UNUSED(ud); UNUSED(ud);
stack_init(L, L); /* init stack */ stack_init(L, L); /* init stack */
sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ init_registry(L, g);
sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaT_init(L); luaT_init(L);
luaX_init(L); luaX_init(L);
luaS_fix(luaS_newliteral(L, MEMERRMSG)); /* pre-create memory-error message */
g->GCthreshold = 4*g->totalbytes; g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaS_fix(g->memerrmsg); /* it should never be collected */
g->gcrunning = 1; /* allow gc */
} }
/*
** preinitialize a state with consistent values without allocating
** any memory (to avoid errors)
*/
static void preinit_state (lua_State *L, global_State *g) { static void preinit_state (lua_State *L, global_State *g) {
G(L) = g; G(L) = g;
L->stack = NULL; L->stack = NULL;
L->ci = NULL;
L->stacksize = 0; L->stacksize = 0;
L->errorJmp = NULL; L->errorJmp = NULL;
L->nCcalls = 0;
L->hook = NULL; L->hook = NULL;
L->hookmask = 0; L->hookmask = 0;
L->basehookcount = 0; L->basehookcount = 0;
L->allowhook = 1; L->allowhook = 1;
resethookcount(L); resethookcount(L);
L->openupval = NULL; L->openupval = NULL;
L->size_ci = 0; L->nny = 1;
L->nCcalls = L->baseCcalls = 0; L->status = LUA_OK;
L->status = 0;
L->base_ci = L->ci = NULL;
L->savedpc = NULL;
L->errfunc = 0; L->errfunc = 0;
setnilvalue(gt(L));
} }
static void close_state (lua_State *L) { static void close_state (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */ luaF_close(L, L->stack); /* close all upvalues for this thread */
luaC_freeall(L); /* collect all objects */ luaC_freeallobjects(L); /* collect all objects */
lua_assert(g->rootgc == obj2gco(L)); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
lua_assert(g->strt.nuse == 0);
luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
luaZ_freebuffer(L, &g->buff); luaZ_freebuffer(L, &g->buff);
freestack(L, L); freestack(L);
lua_assert(g->totalbytes == sizeof(LG)); lua_assert(gettotalbytes(g) == sizeof(LG));
(*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
} }
lua_State *luaE_newthread (lua_State *L) { LUA_API lua_State *lua_newthread (lua_State *L) {
lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); lua_State *L1;
luaC_link(L, obj2gco(L1), LUA_TTHREAD); lua_lock(L);
luaC_checkGC(L);
L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th;
setthvalue(L, L->top, L1);
api_incr_top(L);
preinit_state(L1, G(L)); preinit_state(L1, G(L));
stack_init(L1, L); /* init stack */
setobj2n(L, gt(L1), gt(L)); /* share table of globals */
L1->hookmask = L->hookmask; L1->hookmask = L->hookmask;
L1->basehookcount = L->basehookcount; L1->basehookcount = L->basehookcount;
L1->hook = L->hook; L1->hook = L->hook;
resethookcount(L1); resethookcount(L1);
lua_assert(iswhite(obj2gco(L1))); luai_userstatethread(L, L1);
stack_init(L1, L); /* init stack */
lua_unlock(L);
return L1; return L1;
} }
void luaE_freethread (lua_State *L, lua_State *L1) { void luaE_freethread (lua_State *L, lua_State *L1) {
LX *l = fromstate(L1);
luaF_close(L1, L1->stack); /* close all upvalues for this thread */ luaF_close(L1, L1->stack); /* close all upvalues for this thread */
lua_assert(L1->openupval == NULL); lua_assert(L1->openupval == NULL);
luai_userstatefree(L1); luai_userstatefree(L, L1);
freestack(L, L1); freestack(L1);
luaM_freemem(L, fromstate(L1), state_size(lua_State)); luaM_free(L, l);
} }
@ -144,42 +229,43 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
int i; int i;
lua_State *L; lua_State *L;
global_State *g; global_State *g;
void *l = (*f)(ud, NULL, 0, state_size(LG)); LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
if (l == NULL) return NULL; if (l == NULL) return NULL;
L = tostate(l); L = &l->l.l;
g = &((LG *)L)->g; g = &l->g;
L->next = NULL; L->next = NULL;
L->tt = LUA_TTHREAD; L->tt = LUA_TTHREAD;
g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
L->marked = luaC_white(g); L->marked = luaC_white(g);
set2bits(L->marked, FIXEDBIT, SFIXEDBIT); g->gckind = KGC_NORMAL;
preinit_state(L, g); preinit_state(L, g);
g->frealloc = f; g->frealloc = f;
g->ud = ud; g->ud = ud;
g->mainthread = L; g->mainthread = L;
g->uvhead.u.l.prev = &g->uvhead; g->uvhead.u.l.prev = &g->uvhead;
g->uvhead.u.l.next = &g->uvhead; g->uvhead.u.l.next = &g->uvhead;
g->GCthreshold = 0; /* mark it as unfinished state */ g->gcrunning = 0; /* no GC while building state */
g->lastmajormem = 0;
g->strt.size = 0; g->strt.size = 0;
g->strt.nuse = 0; g->strt.nuse = 0;
g->strt.hash = NULL; g->strt.hash = NULL;
setnilvalue(registry(L)); setnilvalue(&g->l_registry);
luaZ_initbuffer(L, &g->buff); luaZ_initbuffer(L, &g->buff);
g->panic = NULL; g->panic = NULL;
g->version = lua_version(NULL);
g->gcstate = GCSpause; g->gcstate = GCSpause;
g->rootgc = obj2gco(L); g->allgc = NULL;
g->sweepstrgc = 0; g->finobj = NULL;
g->sweepgc = &g->rootgc; g->tobefnz = NULL;
g->gray = NULL; g->gray = g->grayagain = NULL;
g->grayagain = NULL; g->weak = g->ephemeron = g->allweak = NULL;
g->weak = NULL;
g->tmudata = NULL;
g->totalbytes = sizeof(LG); g->totalbytes = sizeof(LG);
g->GCdebt = 0;
g->gcpause = LUAI_GCPAUSE; g->gcpause = LUAI_GCPAUSE;
g->gcmajorinc = LUAI_GCMAJOR;
g->gcstepmul = LUAI_GCMUL; g->gcstepmul = LUAI_GCMUL;
g->gcdept = 0; for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
/* memory allocation error: free partial state */ /* memory allocation error: free partial state */
close_state(L); close_state(L);
L = NULL; L = NULL;
@ -190,25 +276,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
} }
static void callallgcTM (lua_State *L, void *ud) {
UNUSED(ud);
luaC_callGCTM(L); /* call GC metamethods for all udata */
}
LUA_API void lua_close (lua_State *L) { LUA_API void lua_close (lua_State *L) {
L = G(L)->mainthread; /* only the main thread can be closed */ L = G(L)->mainthread; /* only the main thread can be closed */
lua_lock(L); lua_lock(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
L->errfunc = 0; /* no error function during GC metamethods */
do { /* repeat until no more errors */
L->ci = L->base_ci;
L->base = L->top = L->ci->base;
L->nCcalls = L->baseCcalls = 0;
} while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
lua_assert(G(L)->tmudata == NULL);
luai_userstateclose(L); luai_userstateclose(L);
close_state(L); close_state(L);
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lstring.c,v 2.19 2011/05/03 16:01:57 roberto Exp $
** String table (keeps all strings handled by Lua) ** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -20,54 +20,55 @@
void luaS_resize (lua_State *L, int newsize) { void luaS_resize (lua_State *L, int newsize) {
GCObject **newhash;
stringtable *tb;
int i; int i;
if (G(L)->gcstate == GCSsweepstring) stringtable *tb = &G(L)->strt;
return; /* cannot resize during GC traverse */ /* cannot resize while GC is traversing strings */
newhash = luaM_newvector(L, newsize, GCObject *); luaC_runtilstate(L, ~bitmask(GCSsweepstring));
tb = &G(L)->strt; if (newsize > tb->size) {
for (i=0; i<newsize; i++) newhash[i] = NULL; luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL;
}
/* rehash */ /* rehash */
for (i=0; i<tb->size; i++) { for (i=0; i<tb->size; i++) {
GCObject *p = tb->hash[i]; GCObject *p = tb->hash[i];
tb->hash[i] = NULL;
while (p) { /* for each node in the list */ while (p) { /* for each node in the list */
GCObject *next = p->gch.next; /* save next */ GCObject *next = gch(p)->next; /* save next */
unsigned int h = gco2ts(p)->hash; unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */
int h1 = lmod(h, newsize); /* new position */ gch(p)->next = tb->hash[h]; /* chain it */
lua_assert(cast_int(h%newsize) == lmod(h, newsize)); tb->hash[h] = p;
p->gch.next = newhash[h1]; /* chain it */ resetoldbit(p); /* see MOVE OLD rule */
newhash[h1] = p;
p = next; p = next;
} }
} }
luaM_freearray(L, tb->hash, tb->size, TString *); if (newsize < tb->size) {
/* shrinking slice must be empty */
lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL);
luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
}
tb->size = newsize; tb->size = newsize;
tb->hash = newhash;
} }
static TString *newlstr (lua_State *L, const char *str, size_t l, static TString *newlstr (lua_State *L, const char *str, size_t l,
unsigned int h) { unsigned int h) {
size_t totalsize; /* total size of TString object */
GCObject **list; /* (pointer to) list where it will be inserted */
TString *ts; TString *ts;
stringtable *tb; stringtable *tb = &G(L)->strt;
if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
luaM_toobig(L); luaM_toobig(L);
ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
list = &tb->hash[lmod(h, tb->size)];
ts = &luaC_newobj(L, LUA_TSTRING, totalsize, list, 0)->ts;
ts->tsv.len = l; ts->tsv.len = l;
ts->tsv.hash = h; ts->tsv.hash = h;
ts->tsv.marked = luaC_white(G(L));
ts->tsv.tt = LUA_TSTRING;
ts->tsv.reserved = 0; ts->tsv.reserved = 0;
memcpy(ts+1, str, l*sizeof(char)); memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
tb = &G(L)->strt;
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
tb->hash[h] = obj2gco(ts);
tb->nuse++; tb->nuse++;
if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
return ts; return ts;
} }
@ -81,15 +82,22 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL; o != NULL;
o = o->gch.next) { o = gch(o)->next) {
TString *ts = rawgco2ts(o); TString *ts = rawgco2ts(o);
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { if (h == ts->tsv.hash &&
/* string may be dead */ ts->tsv.len == l &&
if (isdead(G(L), o)) changewhite(o); (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */
changewhite(o); /* resurrect it */
return ts; return ts;
} }
} }
return newlstr(L, str, l, h); /* not found */ return newlstr(L, str, l, h); /* not found; create a new string */
}
TString *luaS_new (lua_State *L, const char *str) {
return luaS_newlstr(L, str, strlen(str));
} }
@ -97,15 +105,10 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
Udata *u; Udata *u;
if (s > MAX_SIZET - sizeof(Udata)) if (s > MAX_SIZET - sizeof(Udata))
luaM_toobig(L); luaM_toobig(L);
u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u;
u->uv.marked = luaC_white(G(L)); /* is not finalized */
u->uv.tt = LUA_TUSERDATA;
u->uv.len = s; u->uv.len = s;
u->uv.metatable = NULL; u->uv.metatable = NULL;
u->uv.env = e; u->uv.env = e;
/* chain it on udata list (after main thread) */
u->uv.next = G(L)->mainthread->next;
G(L)->mainthread->next = obj2gco(u);
return u; return u;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ** $Id: lstrlib.c,v 1.173 2011/11/30 18:24:56 roberto Exp $
** Standard library for string operations and pattern-matching ** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -20,6 +20,15 @@
#include "lualib.h" #include "lualib.h"
/*
** maximum number of captures that a pattern can do during
** pattern-matching. This limit is arbitrary.
*/
#if !defined(LUA_MAXCAPTURES)
#define LUA_MAXCAPTURES 32
#endif
/* macro to `unsign' a character */ /* macro to `unsign' a character */
#define uchar(c) ((unsigned char)(c)) #define uchar(c) ((unsigned char)(c))
@ -28,39 +37,41 @@
static int str_len (lua_State *L) { static int str_len (lua_State *L) {
size_t l; size_t l;
luaL_checklstring(L, 1, &l); luaL_checklstring(L, 1, &l);
lua_pushinteger(L, l); lua_pushinteger(L, (lua_Integer)l);
return 1; return 1;
} }
static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { /* translate a relative string position: negative means back from end */
/* relative string position: negative means back from end */ static size_t posrelat (ptrdiff_t pos, size_t len) {
if (pos < 0) pos += (ptrdiff_t)len + 1; if (pos >= 0) return (size_t)pos;
return (pos >= 0) ? pos : 0; else if (0u - (size_t)pos > len) return 0;
else return len - ((size_t)-pos) + 1;
} }
static int str_sub (lua_State *L) { static int str_sub (lua_State *L) {
size_t l; size_t l;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); size_t start = posrelat(luaL_checkinteger(L, 2), l);
ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); size_t end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1; if (start < 1) start = 1;
if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; if (end > l) end = l;
if (start <= end) if (start <= end)
lua_pushlstring(L, s+start-1, end-start+1); lua_pushlstring(L, s + start - 1, end - start + 1);
else lua_pushliteral(L, ""); else lua_pushliteral(L, "");
return 1; return 1;
} }
static int str_reverse (lua_State *L) { static int str_reverse (lua_State *L) {
size_t l; size_t l, i;
luaL_Buffer b; luaL_Buffer b;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b); char *p = luaL_buffinitsize(L, &b, l);
while (l--) luaL_addchar(&b, s[l]); for (i = 0; i < l; i++)
luaL_pushresult(&b); p[i] = s[l - i - 1];
luaL_pushresultsize(&b, l);
return 1; return 1;
} }
@ -70,10 +81,10 @@ static int str_lower (lua_State *L) {
size_t i; size_t i;
luaL_Buffer b; luaL_Buffer b;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b); char *p = luaL_buffinitsize(L, &b, l);
for (i=0; i<l; i++) for (i=0; i<l; i++)
luaL_addchar(&b, tolower(uchar(s[i]))); p[i] = tolower(uchar(s[i]));
luaL_pushresult(&b); luaL_pushresultsize(&b, l);
return 1; return 1;
} }
@ -83,22 +94,36 @@ static int str_upper (lua_State *L) {
size_t i; size_t i;
luaL_Buffer b; luaL_Buffer b;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b); char *p = luaL_buffinitsize(L, &b, l);
for (i=0; i<l; i++) for (i=0; i<l; i++)
luaL_addchar(&b, toupper(uchar(s[i]))); p[i] = toupper(uchar(s[i]));
luaL_pushresult(&b); luaL_pushresultsize(&b, l);
return 1; return 1;
} }
/* reasonable limit to avoid arithmetic overflow */
#define MAXSIZE ((~(size_t)0) >> 1)
static int str_rep (lua_State *L) { static int str_rep (lua_State *L) {
size_t l; size_t l, lsep;
luaL_Buffer b;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
int n = luaL_checkint(L, 2); int n = luaL_checkint(L, 2);
luaL_buffinit(L, &b); const char *sep = luaL_optlstring(L, 3, "", &lsep);
while (n-- > 0) if (n <= 0) lua_pushliteral(L, "");
luaL_addlstring(&b, s, l); else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */
luaL_pushresult(&b); return luaL_error(L, "resulting string too large");
else {
size_t totallen = n * l + (n - 1) * lsep;
luaL_Buffer b;
char *p = luaL_buffinitsize(L, &b, totallen);
while (n-- > 1) { /* first n-1 copies (followed by separator) */
memcpy(p, s, l * sizeof(char)); p += l;
memcpy(p, sep, lsep * sizeof(char)); p += lsep;
}
memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
luaL_pushresultsize(&b, totallen);
}
return 1; return 1;
} }
@ -106,15 +131,15 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) { static int str_byte (lua_State *L) {
size_t l; size_t l;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); size_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); size_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
int n, i; int n, i;
if (posi <= 0) posi = 1; if (posi < 1) posi = 1;
if ((size_t)pose > l) pose = l; if (pose > l) pose = l;
if (posi > pose) return 0; /* empty interval; return no values */ if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1); n = (int)(pose - posi + 1);
if (posi + n <= pose) /* overflow? */ if (posi + n <= pose) /* (size_t -> int) overflow? */
luaL_error(L, "string slice too long"); return luaL_error(L, "string slice too long");
luaL_checkstack(L, n, "string slice too long"); luaL_checkstack(L, n, "string slice too long");
for (i=0; i<n; i++) for (i=0; i<n; i++)
lua_pushinteger(L, uchar(s[posi+i-1])); lua_pushinteger(L, uchar(s[posi+i-1]));
@ -126,13 +151,13 @@ static int str_char (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */ int n = lua_gettop(L); /* number of arguments */
int i; int i;
luaL_Buffer b; luaL_Buffer b;
luaL_buffinit(L, &b); char *p = luaL_buffinitsize(L, &b, n);
for (i=1; i<=n; i++) { for (i=1; i<=n; i++) {
int c = luaL_checkint(L, i); int c = luaL_checkint(L, i);
luaL_argcheck(L, uchar(c) == c, i, "invalid value"); luaL_argcheck(L, uchar(c) == c, i, "value out of range");
luaL_addchar(&b, uchar(c)); p[i - 1] = uchar(c);
} }
luaL_pushresult(&b); luaL_pushresultsize(&b, n);
return 1; return 1;
} }
@ -150,7 +175,7 @@ static int str_dump (lua_State *L) {
lua_settop(L, 1); lua_settop(L, 1);
luaL_buffinit(L,&b); luaL_buffinit(L,&b);
if (lua_dump(L, writer, &b) != 0) if (lua_dump(L, writer, &b) != 0)
luaL_error(L, "unable to dump given function"); return luaL_error(L, "unable to dump given function");
luaL_pushresult(&b); luaL_pushresult(&b);
return 1; return 1;
} }
@ -169,7 +194,8 @@ static int str_dump (lua_State *L) {
typedef struct MatchState { typedef struct MatchState {
const char *src_init; /* init of source string */ const char *src_init; /* init of source string */
const char *src_end; /* end (`\0') of source string */ const char *src_end; /* end ('\0') of source string */
const char *p_end; /* end ('\0') of pattern */
lua_State *L; lua_State *L;
int level; /* total number of captures (finished or unfinished) */ int level; /* total number of captures (finished or unfinished) */
struct { struct {
@ -186,7 +212,7 @@ typedef struct MatchState {
static int check_capture (MatchState *ms, int l) { static int check_capture (MatchState *ms, int l) {
l -= '1'; l -= '1';
if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
return luaL_error(ms->L, "invalid capture index"); return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
return l; return l;
} }
@ -202,16 +228,16 @@ static int capture_to_close (MatchState *ms) {
static const char *classend (MatchState *ms, const char *p) { static const char *classend (MatchState *ms, const char *p) {
switch (*p++) { switch (*p++) {
case L_ESC: { case L_ESC: {
if (*p == '\0') if (p == ms->p_end)
luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
return p+1; return p+1;
} }
case '[': { case '[': {
if (*p == '^') p++; if (*p == '^') p++;
do { /* look for a `]' */ do { /* look for a `]' */
if (*p == '\0') if (p == ms->p_end)
luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
if (*(p++) == L_ESC && *p != '\0') if (*(p++) == L_ESC && p < ms->p_end)
p++; /* skip escapes (e.g. `%]') */ p++; /* skip escapes (e.g. `%]') */
} while (*p != ']'); } while (*p != ']');
return p+1; return p+1;
@ -229,13 +255,14 @@ static int match_class (int c, int cl) {
case 'a' : res = isalpha(c); break; case 'a' : res = isalpha(c); break;
case 'c' : res = iscntrl(c); break; case 'c' : res = iscntrl(c); break;
case 'd' : res = isdigit(c); break; case 'd' : res = isdigit(c); break;
case 'g' : res = isgraph(c); break;
case 'l' : res = islower(c); break; case 'l' : res = islower(c); break;
case 'p' : res = ispunct(c); break; case 'p' : res = ispunct(c); break;
case 's' : res = isspace(c); break; case 's' : res = isspace(c); break;
case 'u' : res = isupper(c); break; case 'u' : res = isupper(c); break;
case 'w' : res = isalnum(c); break; case 'w' : res = isalnum(c); break;
case 'x' : res = isxdigit(c); break; case 'x' : res = isxdigit(c); break;
case 'z' : res = (c == 0); break; case 'z' : res = (c == 0); break; /* deprecated option */
default: return (cl == c); default: return (cl == c);
} }
return (islower(cl) ? res : !res); return (islower(cl) ? res : !res);
@ -280,8 +307,9 @@ static const char *match (MatchState *ms, const char *s, const char *p);
static const char *matchbalance (MatchState *ms, const char *s, static const char *matchbalance (MatchState *ms, const char *s,
const char *p) { const char *p) {
if (*p == 0 || *(p+1) == 0) if (p >= ms->p_end - 1)
luaL_error(ms->L, "unbalanced pattern"); luaL_error(ms->L, "malformed pattern "
"(missing arguments to " LUA_QL("%%b") ")");
if (*s != *p) return NULL; if (*s != *p) return NULL;
else { else {
int b = *p; int b = *p;
@ -364,6 +392,8 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
static const char *match (MatchState *ms, const char *s, const char *p) { static const char *match (MatchState *ms, const char *s, const char *p) {
init: /* using goto's to optimize tail recursion */ init: /* using goto's to optimize tail recursion */
if (p == ms->p_end) /* end of pattern? */
return s; /* match succeeded */
switch (*p) { switch (*p) {
case '(': { /* start capture */ case '(': { /* start capture */
if (*(p+1) == ')') /* position capture? */ if (*(p+1) == ')') /* position capture? */
@ -374,7 +404,12 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
case ')': { /* end capture */ case ')': { /* end capture */
return end_capture(ms, s, p+1); return end_capture(ms, s, p+1);
} }
case L_ESC: { case '$': {
if ((p+1) == ms->p_end) /* is the `$' the last char in pattern? */
return (s == ms->src_end) ? s : NULL; /* check end of string */
else goto dflt;
}
case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
switch (*(p+1)) { switch (*(p+1)) {
case 'b': { /* balanced string? */ case 'b': { /* balanced string? */
s = matchbalance(ms, s, p+2); s = matchbalance(ms, s, p+2);
@ -393,27 +428,19 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
!matchbracketclass(uchar(*s), p, ep-1)) return NULL; !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
p=ep; goto init; /* else return match(ms, s, ep); */ p=ep; goto init; /* else return match(ms, s, ep); */
} }
default: { case '0': case '1': case '2': case '3':
if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ case '4': case '5': case '6': case '7':
s = match_capture(ms, s, uchar(*(p+1))); case '8': case '9': { /* capture results (%0-%9)? */
if (s == NULL) return NULL; s = match_capture(ms, s, uchar(*(p+1)));
p+=2; goto init; /* else return match(ms, s, p+2) */ if (s == NULL) return NULL;
} p+=2; goto init; /* else return match(ms, s, p+2) */
goto dflt; /* case default */
} }
default: goto dflt;
} }
} }
case '\0': { /* end of pattern */ default: dflt: { /* pattern class plus optional suffix */
return s; /* match succeeded */
}
case '$': {
if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
return (s == ms->src_end) ? s : NULL; /* check end of string */
else goto dflt;
}
default: dflt: { /* it is a pattern item */
const char *ep = classend(ms, p); /* points to what is next */ const char *ep = classend(ms, p); /* points to what is next */
int m = s<ms->src_end && singlematch(uchar(*s), p, ep); int m = s < ms->src_end && singlematch(uchar(*s), p, ep);
switch (*ep) { switch (*ep) {
case '?': { /* optional */ case '?': { /* optional */
const char *res; const char *res;
@ -492,37 +519,56 @@ static int push_captures (MatchState *ms, const char *s, const char *e) {
} }
/* check whether pattern has no special characters */
static int nospecials (const char *p, size_t l) {
size_t upto = 0;
do {
if (strpbrk(p + upto, SPECIALS))
return 0; /* pattern has a special character */
upto += strlen(p + upto) + 1; /* may have more after \0 */
} while (upto <= l);
return 1; /* no special chars found */
}
static int str_find_aux (lua_State *L, int find) { static int str_find_aux (lua_State *L, int find) {
size_t l1, l2; size_t ls, lp;
const char *s = luaL_checklstring(L, 1, &l1); const char *s = luaL_checklstring(L, 1, &ls);
const char *p = luaL_checklstring(L, 2, &l2); const char *p = luaL_checklstring(L, 2, &lp);
ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; size_t init = posrelat(luaL_optinteger(L, 3, 1), ls);
if (init < 0) init = 0; if (init < 1) init = 1;
else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; else if (init > ls + 1) { /* start after string's end? */
if (find && (lua_toboolean(L, 4) || /* explicit request? */ lua_pushnil(L); /* cannot find anything */
strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ return 1;
}
/* explicit request or no special characters? */
if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
/* do a plain search */ /* do a plain search */
const char *s2 = lmemfind(s+init, l1-init, p, l2); const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp);
if (s2) { if (s2) {
lua_pushinteger(L, s2-s+1); lua_pushinteger(L, s2 - s + 1);
lua_pushinteger(L, s2-s+l2); lua_pushinteger(L, s2 - s + lp);
return 2; return 2;
} }
} }
else { else {
MatchState ms; MatchState ms;
int anchor = (*p == '^') ? (p++, 1) : 0; const char *s1 = s + init - 1;
const char *s1=s+init; int anchor = (*p == '^');
if (anchor) {
p++; lp--; /* skip anchor character */
}
ms.L = L; ms.L = L;
ms.src_init = s; ms.src_init = s;
ms.src_end = s+l1; ms.src_end = s + ls;
ms.p_end = p + lp;
do { do {
const char *res; const char *res;
ms.level = 0; ms.level = 0;
if ((res=match(&ms, s1, p)) != NULL) { if ((res=match(&ms, s1, p)) != NULL) {
if (find) { if (find) {
lua_pushinteger(L, s1-s+1); /* start */ lua_pushinteger(L, s1 - s + 1); /* start */
lua_pushinteger(L, res-s); /* end */ lua_pushinteger(L, res - s); /* end */
return push_captures(&ms, NULL, 0) + 2; return push_captures(&ms, NULL, 0) + 2;
} }
else else
@ -547,13 +593,14 @@ static int str_match (lua_State *L) {
static int gmatch_aux (lua_State *L) { static int gmatch_aux (lua_State *L) {
MatchState ms; MatchState ms;
size_t ls; size_t ls, lp;
const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
const char *p = lua_tostring(L, lua_upvalueindex(2)); const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
const char *src; const char *src;
ms.L = L; ms.L = L;
ms.src_init = s; ms.src_init = s;
ms.src_end = s+ls; ms.src_end = s+ls;
ms.p_end = p + lp;
for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
src <= ms.src_end; src <= ms.src_end;
src++) { src++) {
@ -581,12 +628,6 @@ static int gmatch (lua_State *L) {
} }
static int gfind_nodef (lua_State *L) {
return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
LUA_QL("string.gmatch"));
}
static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
const char *e) { const char *e) {
size_t l, i; size_t l, i;
@ -596,8 +637,12 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
luaL_addchar(b, news[i]); luaL_addchar(b, news[i]);
else { else {
i++; /* skip ESC */ i++; /* skip ESC */
if (!isdigit(uchar(news[i]))) if (!isdigit(uchar(news[i]))) {
if (news[i] != L_ESC)
luaL_error(ms->L, "invalid use of " LUA_QL("%c")
" in replacement string", L_ESC);
luaL_addchar(b, news[i]); luaL_addchar(b, news[i]);
}
else if (news[i] == '0') else if (news[i] == '0')
luaL_addlstring(b, s, e - s); luaL_addlstring(b, s, e - s);
else { else {
@ -610,14 +655,9 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
const char *e) { const char *e, int tr) {
lua_State *L = ms->L; lua_State *L = ms->L;
switch (lua_type(L, 3)) { switch (tr) {
case LUA_TNUMBER:
case LUA_TSTRING: {
add_s(ms, b, s, e);
return;
}
case LUA_TFUNCTION: { case LUA_TFUNCTION: {
int n; int n;
lua_pushvalue(L, 3); lua_pushvalue(L, 3);
@ -630,41 +670,49 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
lua_gettable(L, 3); lua_gettable(L, 3);
break; break;
} }
default: { /* LUA_TNUMBER or LUA_TSTRING */
add_s(ms, b, s, e);
return;
}
} }
if (!lua_toboolean(L, -1)) { /* nil or false? */ if (!lua_toboolean(L, -1)) { /* nil or false? */
lua_pop(L, 1); lua_pop(L, 1);
lua_pushlstring(L, s, e - s); /* keep original text */ lua_pushlstring(L, s, e - s); /* keep original text */
} }
else if (!lua_isstring(L, -1)) else if (!lua_isstring(L, -1))
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
luaL_addvalue(b); /* add result to accumulator */ luaL_addvalue(b); /* add result to accumulator */
} }
static int str_gsub (lua_State *L) { static int str_gsub (lua_State *L) {
size_t srcl; size_t srcl, lp;
const char *src = luaL_checklstring(L, 1, &srcl); const char *src = luaL_checklstring(L, 1, &srcl);
const char *p = luaL_checkstring(L, 2); const char *p = luaL_checklstring(L, 2, &lp);
int tr = lua_type(L, 3); int tr = lua_type(L, 3);
int max_s = luaL_optint(L, 4, srcl+1); size_t max_s = luaL_optinteger(L, 4, srcl+1);
int anchor = (*p == '^') ? (p++, 1) : 0; int anchor = (*p == '^');
int n = 0; size_t n = 0;
MatchState ms; MatchState ms;
luaL_Buffer b; luaL_Buffer b;
luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
"string/function/table expected"); "string/function/table expected");
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
if (anchor) {
p++; lp--; /* skip anchor character */
}
ms.L = L; ms.L = L;
ms.src_init = src; ms.src_init = src;
ms.src_end = src+srcl; ms.src_end = src+srcl;
ms.p_end = p + lp;
while (n < max_s) { while (n < max_s) {
const char *e; const char *e;
ms.level = 0; ms.level = 0;
e = match(&ms, src, p); e = match(&ms, src, p);
if (e) { if (e) {
n++; n++;
add_value(&ms, &b, src, e); add_value(&ms, &b, src, e, tr);
} }
if (e && e>src) /* non empty match? */ if (e && e>src) /* non empty match? */
src = e; /* skip it */ src = e; /* skip it */
@ -682,6 +730,49 @@ static int str_gsub (lua_State *L) {
/* }====================================================== */ /* }====================================================== */
/*
** {======================================================
** STRING FORMAT
** =======================================================
*/
/*
** LUA_INTFRMLEN is the length modifier for integer conversions in
** 'string.format'; LUA_INTFRM_T is the integer type corresponding to
** the previous length
*/
#if !defined(LUA_INTFRMLEN) /* { */
#if defined(LUA_USE_LONGLONG)
#define LUA_INTFRMLEN "ll"
#define LUA_INTFRM_T long long
#else
#define LUA_INTFRMLEN "l"
#define LUA_INTFRM_T long
#endif
#endif /* } */
#define MAX_UINTFRM ((lua_Number)(~(unsigned LUA_INTFRM_T)0))
#define MAX_INTFRM ((lua_Number)((~(unsigned LUA_INTFRM_T)0)/2))
#define MIN_INTFRM (-(lua_Number)((~(unsigned LUA_INTFRM_T)0)/2) - 1)
/*
** LUA_FLTFRMLEN is the length modifier for float conversions in
** 'string.format'; LUA_FLTFRM_T is the float type corresponding to
** the previous length
*/
#if !defined(LUA_FLTFRMLEN)
#define LUA_FLTFRMLEN ""
#define LUA_FLTFRM_T double
#endif
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM 512 #define MAX_ITEM 512
/* valid flags in a format specification */ /* valid flags in a format specification */
@ -698,25 +789,20 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
const char *s = luaL_checklstring(L, arg, &l); const char *s = luaL_checklstring(L, arg, &l);
luaL_addchar(b, '"'); luaL_addchar(b, '"');
while (l--) { while (l--) {
switch (*s) { if (*s == '"' || *s == '\\' || *s == '\n') {
case '"': case '\\': case '\n': { luaL_addchar(b, '\\');
luaL_addchar(b, '\\'); luaL_addchar(b, *s);
luaL_addchar(b, *s);
break;
}
case '\r': {
luaL_addlstring(b, "\\r", 2);
break;
}
case '\0': {
luaL_addlstring(b, "\\000", 4);
break;
}
default: {
luaL_addchar(b, *s);
break;
}
} }
else if (*s == '\0' || iscntrl(uchar(*s))) {
char buff[10];
if (!isdigit(uchar(*(s+1))))
sprintf(buff, "\\%d", (int)uchar(*s));
else
sprintf(buff, "\\%03d", (int)uchar(*s));
luaL_addstring(b, buff);
}
else
luaL_addchar(b, *s);
s++; s++;
} }
luaL_addchar(b, '"'); luaL_addchar(b, '"');
@ -725,7 +811,7 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
const char *p = strfrmt; const char *p = strfrmt;
while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char))
luaL_error(L, "invalid format (repeated flags)"); luaL_error(L, "invalid format (repeated flags)");
if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* skip width */
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
@ -737,23 +823,28 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
if (isdigit(uchar(*p))) if (isdigit(uchar(*p)))
luaL_error(L, "invalid format (width or precision too long)"); luaL_error(L, "invalid format (width or precision too long)");
*(form++) = '%'; *(form++) = '%';
strncpy(form, strfrmt, p - strfrmt + 1); memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char));
form += p - strfrmt + 1; form += p - strfrmt + 1;
*form = '\0'; *form = '\0';
return p; return p;
} }
static void addintlen (char *form) { /*
** add length modifier into formats
*/
static void addlenmod (char *form, const char *lenmod) {
size_t l = strlen(form); size_t l = strlen(form);
size_t lm = strlen(lenmod);
char spec = form[l - 1]; char spec = form[l - 1];
strcpy(form + l - 1, LUA_INTFRMLEN); strcpy(form + l - 1, lenmod);
form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; form[l + lm - 1] = spec;
form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; form[l + lm] = '\0';
} }
static int str_format (lua_State *L) { static int str_format (lua_State *L) {
int top = lua_gettop(L);
int arg = 1; int arg = 1;
size_t sfl; size_t sfl;
const char *strfrmt = luaL_checklstring(L, arg, &sfl); const char *strfrmt = luaL_checklstring(L, arg, &sfl);
@ -767,45 +858,57 @@ static int str_format (lua_State *L) {
luaL_addchar(&b, *strfrmt++); /* %% */ luaL_addchar(&b, *strfrmt++); /* %% */
else { /* format item */ else { /* format item */
char form[MAX_FORMAT]; /* to store the format (`%...') */ char form[MAX_FORMAT]; /* to store the format (`%...') */
char buff[MAX_ITEM]; /* to store the formatted item */ char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
arg++; int nb = 0; /* number of bytes in added item */
if (++arg > top)
luaL_argerror(L, arg, "no value");
strfrmt = scanformat(L, strfrmt, form); strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) { switch (*strfrmt++) {
case 'c': { case 'c': {
sprintf(buff, form, (int)luaL_checknumber(L, arg)); nb = sprintf(buff, form, luaL_checkint(L, arg));
break; break;
} }
case 'd': case 'i': { case 'd': case 'i': {
addintlen(form); lua_Number n = luaL_checknumber(L, arg);
sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); luaL_argcheck(L, (MIN_INTFRM - 1) < n && n < (MAX_INTFRM + 1), arg,
"not a number in proper range");
addlenmod(form, LUA_INTFRMLEN);
nb = sprintf(buff, form, (LUA_INTFRM_T)n);
break; break;
} }
case 'o': case 'u': case 'x': case 'X': { case 'o': case 'u': case 'x': case 'X': {
addintlen(form); lua_Number n = luaL_checknumber(L, arg);
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); luaL_argcheck(L, 0 <= n && n < (MAX_UINTFRM + 1), arg,
"not a non-negative number in proper range");
addlenmod(form, LUA_INTFRMLEN);
nb = sprintf(buff, form, (unsigned LUA_INTFRM_T)n);
break; break;
} }
case 'e': case 'E': case 'f': case 'e': case 'E': case 'f':
#if defined(LUA_USE_AFORMAT)
case 'a': case 'A':
#endif
case 'g': case 'G': { case 'g': case 'G': {
sprintf(buff, form, (double)luaL_checknumber(L, arg)); addlenmod(form, LUA_FLTFRMLEN);
nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg));
break; break;
} }
case 'q': { case 'q': {
addquoted(L, &b, arg); addquoted(L, &b, arg);
continue; /* skip the 'addsize' at the end */ break;
} }
case 's': { case 's': {
size_t l; size_t l;
const char *s = luaL_checklstring(L, arg, &l); const char *s = luaL_tolstring(L, arg, &l);
if (!strchr(form, '.') && l >= 100) { if (!strchr(form, '.') && l >= 100) {
/* no precision and string is too long to be formatted; /* no precision and string is too long to be formatted;
keep original string */ keep original string */
lua_pushvalue(L, arg);
luaL_addvalue(&b); luaL_addvalue(&b);
continue; /* skip the `addsize' at the end */ break;
} }
else { else {
sprintf(buff, form, s); nb = sprintf(buff, form, s);
lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
break; break;
} }
} }
@ -814,13 +917,15 @@ static int str_format (lua_State *L) {
LUA_QL("format"), *(strfrmt - 1)); LUA_QL("format"), *(strfrmt - 1));
} }
} }
luaL_addlstring(&b, buff, strlen(buff)); luaL_addsize(&b, nb);
} }
} }
luaL_pushresult(&b); luaL_pushresult(&b);
return 1; return 1;
} }
/* }====================================================== */
static const luaL_Reg strlib[] = { static const luaL_Reg strlib[] = {
{"byte", str_byte}, {"byte", str_byte},
@ -828,7 +933,6 @@ static const luaL_Reg strlib[] = {
{"dump", str_dump}, {"dump", str_dump},
{"find", str_find}, {"find", str_find},
{"format", str_format}, {"format", str_format},
{"gfind", gfind_nodef},
{"gmatch", gmatch}, {"gmatch", gmatch},
{"gsub", str_gsub}, {"gsub", str_gsub},
{"len", str_len}, {"len", str_len},
@ -843,13 +947,13 @@ static const luaL_Reg strlib[] = {
static void createmetatable (lua_State *L) { static void createmetatable (lua_State *L) {
lua_createtable(L, 0, 1); /* create metatable for strings */ lua_createtable(L, 0, 1); /* table to be metatable for strings */
lua_pushliteral(L, ""); /* dummy string */ lua_pushliteral(L, ""); /* dummy string */
lua_pushvalue(L, -2); lua_pushvalue(L, -2); /* copy table */
lua_setmetatable(L, -2); /* set string metatable */ lua_setmetatable(L, -2); /* set table as metatable for strings */
lua_pop(L, 1); /* pop dummy string */ lua_pop(L, 1); /* pop dummy string */
lua_pushvalue(L, -2); /* string library... */ lua_pushvalue(L, -2); /* get string library */
lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ lua_setfield(L, -2, "__index"); /* metatable.__index = string */
lua_pop(L, 1); /* pop metatable */ lua_pop(L, 1); /* pop metatable */
} }
@ -857,12 +961,8 @@ static void createmetatable (lua_State *L) {
/* /*
** Open string library ** Open string library
*/ */
LUALIB_API int luaopen_string (lua_State *L) { LUAMOD_API int luaopen_string (lua_State *L) {
luaL_register(L, LUA_STRLIBNAME, strlib); luaL_newlib(L, strlib);
#if defined(LUA_COMPAT_GFIND)
lua_getfield(L, -1, "gmatch");
lua_setfield(L, -2, "gfind");
#endif
createmetatable(L); createmetatable(L);
return 1; return 1;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ ** $Id: ltable.c,v 2.67 2011/11/30 12:41:45 roberto Exp $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -18,7 +18,6 @@
** Hence even when the load factor reaches 100%, performance remains good. ** Hence even when the load factor reaches 100%, performance remains good.
*/ */
#include <math.h>
#include <string.h> #include <string.h>
#define ltable_c #define ltable_c
@ -32,14 +31,16 @@
#include "lmem.h" #include "lmem.h"
#include "lobject.h" #include "lobject.h"
#include "lstate.h" #include "lstate.h"
#include "lstring.h"
#include "ltable.h" #include "ltable.h"
#include "lvm.h"
/* /*
** max size of array part is 2^MAXBITS ** max size of array part is 2^MAXBITS
*/ */
#if LUAI_BITSINT > 26 #if LUAI_BITSINT >= 32
#define MAXBITS 26 #define MAXBITS 30
#else #else
#define MAXBITS (LUAI_BITSINT-2) #define MAXBITS (LUAI_BITSINT-2)
#endif #endif
@ -48,7 +49,7 @@
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) #define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
#define hashboolean(t,p) hashpow2(t, p) #define hashboolean(t,p) hashpow2(t, p)
@ -63,18 +64,13 @@
#define hashpointer(t,p) hashmod(t, IntPoint(p)) #define hashpointer(t,p) hashmod(t, IntPoint(p))
/*
** number of ints inside a lua_Number
*/
#define numints cast_int(sizeof(lua_Number)/sizeof(int))
#define dummynode (&dummynode_) #define dummynode (&dummynode_)
#define isdummy(n) ((n) == dummynode)
static const Node dummynode_ = { static const Node dummynode_ = {
{{NULL}, LUA_TNIL}, /* value */ {NILCONSTANT}, /* value */
{{{NULL}, LUA_TNIL, NULL}} /* key */ {{NILCONSTANT, NULL}} /* key */
}; };
@ -82,13 +78,14 @@ static const Node dummynode_ = {
** hash for lua_Numbers ** hash for lua_Numbers
*/ */
static Node *hashnum (const Table *t, lua_Number n) { static Node *hashnum (const Table *t, lua_Number n) {
unsigned int a[numints];
int i; int i;
if (luai_numeq(n, 0)) /* avoid problems with -0 */ luai_hashnum(i, n);
return gnode(t, 0); if (i < 0) {
memcpy(a, &n, sizeof(a)); if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
for (i = 1; i < numints; i++) a[0] += a[i]; i = 0; /* handle INT_MIN */
return hashmod(t, a[0]); i = -i; /* must be a positive value */
}
return hashmod(t, i);
} }
@ -107,6 +104,8 @@ static Node *mainposition (const Table *t, const TValue *key) {
return hashboolean(t, bvalue(key)); return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
return hashpointer(t, pvalue(key)); return hashpointer(t, pvalue(key));
case LUA_TLCF:
return hashpointer(t, fvalue(key));
default: default:
return hashpointer(t, gcvalue(key)); return hashpointer(t, gcvalue(key));
} }
@ -132,7 +131,7 @@ static int arrayindex (const TValue *key) {
/* /*
** returns the index of a `key' for table traversals. First goes all ** returns the index of a `key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The ** elements in the array part, then elements in the hash part. The
** beginning of a traversal is signalled by -1. ** beginning of a traversal is signaled by -1.
*/ */
static int findindex (lua_State *L, Table *t, StkId key) { static int findindex (lua_State *L, Table *t, StkId key) {
int i; int i;
@ -142,19 +141,19 @@ static int findindex (lua_State *L, Table *t, StkId key) {
return i-1; /* yes; that's the index (corrected to C) */ return i-1; /* yes; that's the index (corrected to C) */
else { else {
Node *n = mainposition(t, key); Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */ for (;;) { /* check whether `key' is somewhere in the chain */
/* key may be dead already, but it is ok to use it in `next' */ /* key may be dead already, but it is ok to use it in `next' */
if (luaO_rawequalObj(key2tval(n), key) || if (luaV_rawequalobj(gkey(n), key) ||
(ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && (ttisdeadkey(gkey(n)) && iscollectable(key) &&
gcvalue(gkey(n)) == gcvalue(key))) { deadvalue(gkey(n)) == gcvalue(key))) {
i = cast_int(n - gnode(t, 0)); /* key index in hash table */ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
/* hash elements are numbered after array ones */ /* hash elements are numbered after array ones */
return i + t->sizearray; return i + t->sizearray;
} }
else n = gnext(n); else n = gnext(n);
} while (n); if (n == NULL)
luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
return 0; /* to avoid warnings */ }
} }
} }
@ -170,7 +169,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
} }
for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
setobj2s(L, key, key2tval(gnode(t, i))); setobj2s(L, key, gkey(gnode(t, i)));
setobj2s(L, key+1, gval(gnode(t, i))); setobj2s(L, key+1, gval(gnode(t, i)));
return 1; return 1;
} }
@ -211,7 +210,7 @@ static int computesizes (int nums[], int *narray) {
static int countint (const TValue *key, int *nums) { static int countint (const TValue *key, int *nums) {
int k = arrayindex(key); int k = arrayindex(key);
if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
nums[ceillog2(k)]++; /* count as such */ nums[luaO_ceillog2(k)]++; /* count as such */
return 1; return 1;
} }
else else
@ -251,7 +250,7 @@ static int numusehash (const Table *t, int *nums, int *pnasize) {
while (i--) { while (i--) {
Node *n = &t->node[i]; Node *n = &t->node[i];
if (!ttisnil(gval(n))) { if (!ttisnil(gval(n))) {
ause += countint(key2tval(n), nums); ause += countint(gkey(n), nums);
totaluse++; totaluse++;
} }
} }
@ -277,7 +276,7 @@ static void setnodevector (lua_State *L, Table *t, int size) {
} }
else { else {
int i; int i;
lsize = ceillog2(size); lsize = luaO_ceillog2(size);
if (lsize > MAXBITS) if (lsize > MAXBITS)
luaG_runerror(L, "table overflow"); luaG_runerror(L, "table overflow");
size = twoto(lsize); size = twoto(lsize);
@ -294,7 +293,7 @@ static void setnodevector (lua_State *L, Table *t, int size) {
} }
static void resize (lua_State *L, Table *t, int nasize, int nhsize) { void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
int i; int i;
int oldasize = t->sizearray; int oldasize = t->sizearray;
int oldhsize = t->lsizenode; int oldhsize = t->lsizenode;
@ -302,13 +301,13 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
if (nasize > oldasize) /* array part must grow? */ if (nasize > oldasize) /* array part must grow? */
setarrayvector(L, t, nasize); setarrayvector(L, t, nasize);
/* create new hash part with appropriate size */ /* create new hash part with appropriate size */
setnodevector(L, t, nhsize); setnodevector(L, t, nhsize);
if (nasize < oldasize) { /* array part must shrink? */ if (nasize < oldasize) { /* array part must shrink? */
t->sizearray = nasize; t->sizearray = nasize;
/* re-insert elements from vanishing slice */ /* re-insert elements from vanishing slice */
for (i=nasize; i<oldasize; i++) { for (i=nasize; i<oldasize; i++) {
if (!ttisnil(&t->array[i])) if (!ttisnil(&t->array[i]))
setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); luaH_setint(L, t, i + 1, &t->array[i]);
} }
/* shrink array */ /* shrink array */
luaM_reallocvector(L, t->array, oldasize, nasize, TValue); luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
@ -316,23 +315,26 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
/* re-insert elements from hash part */ /* re-insert elements from hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--) { for (i = twoto(oldhsize) - 1; i >= 0; i--) {
Node *old = nold+i; Node *old = nold+i;
if (!ttisnil(gval(old))) if (!ttisnil(gval(old))) {
setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); /* doesn't need barrier/invalidate cache, as entry was
already present in the table */
setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old));
}
} }
if (nold != dummynode) if (!isdummy(nold))
luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */
} }
void luaH_resizearray (lua_State *L, Table *t, int nasize) { void luaH_resizearray (lua_State *L, Table *t, int nasize) {
int nsize = (t->node == dummynode) ? 0 : sizenode(t); int nsize = isdummy(t->node) ? 0 : sizenode(t);
resize(L, t, nasize, nsize); luaH_resize(L, t, nasize, nsize);
} }
static void rehash (lua_State *L, Table *t, const TValue *ek) { static void rehash (lua_State *L, Table *t, const TValue *ek) {
int nasize, na; int nasize, na;
int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */
int i; int i;
int totaluse; int totaluse;
for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
@ -345,7 +347,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
/* compute new size for array part */ /* compute new size for array part */
na = computesizes(nums, &nasize); na = computesizes(nums, &nasize);
/* resize the table to new computed sizes */ /* resize the table to new computed sizes */
resize(L, t, nasize, totaluse - na); luaH_resize(L, t, nasize, totaluse - na);
} }
@ -355,32 +357,28 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
*/ */
Table *luaH_new (lua_State *L, int narray, int nhash) { Table *luaH_new (lua_State *L) {
Table *t = luaM_new(L, Table); Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h;
luaC_link(L, obj2gco(t), LUA_TTABLE);
t->metatable = NULL; t->metatable = NULL;
t->flags = cast_byte(~0); t->flags = cast_byte(~0);
/* temporary values (kept only if some malloc fails) */
t->array = NULL; t->array = NULL;
t->sizearray = 0; t->sizearray = 0;
t->lsizenode = 0; setnodevector(L, t, 0);
t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray);
setnodevector(L, t, nhash);
return t; return t;
} }
void luaH_free (lua_State *L, Table *t) { void luaH_free (lua_State *L, Table *t) {
if (t->node != dummynode) if (!isdummy(t->node))
luaM_freearray(L, t->node, sizenode(t), Node); luaM_freearray(L, t->node, cast(size_t, sizenode(t)));
luaM_freearray(L, t->array, t->sizearray, TValue); luaM_freearray(L, t->array, t->sizearray);
luaM_free(L, t); luaM_free(L, t);
} }
static Node *getfreepos (Table *t) { static Node *getfreepos (Table *t) {
while (t->lastfree-- > t->node) { while (t->lastfree > t->node) {
t->lastfree--;
if (ttisnil(gkey(t->lastfree))) if (ttisnil(gkey(t->lastfree)))
return t->lastfree; return t->lastfree;
} }
@ -390,23 +388,28 @@ static Node *getfreepos (Table *t) {
/* /*
** inserts a new key into a hash table; first, check whether key's main ** inserts a new key into a hash table; first, check whether key's main
** position is free. If not, check whether colliding node is in its main ** position is free. If not, check whether colliding node is in its main
** position or not: if it is not, move colliding node to an empty place and ** position or not: if it is not, move colliding node to an empty place and
** put new key in its main position; otherwise (colliding node is in its main ** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position. ** position), new key goes to an empty position.
*/ */
static TValue *newkey (lua_State *L, Table *t, const TValue *key) { TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp = mainposition(t, key); Node *mp;
if (!ttisnil(gval(mp)) || mp == dummynode) { if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisnumber(key) && luai_numisnan(L, nvalue(key)))
luaG_runerror(L, "table index is NaN");
mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
Node *othern; Node *othern;
Node *n = getfreepos(t); /* get a free place */ Node *n = getfreepos(t); /* get a free place */
if (n == NULL) { /* cannot find a free place? */ if (n == NULL) { /* cannot find a free place? */
rehash(L, t, key); /* grow table */ rehash(L, t, key); /* grow table */
return luaH_set(L, t, key); /* re-insert key into grown table */ /* whatever called 'newkey' take care of TM cache and GC barrier */
return luaH_set(L, t, key); /* insert key into grown table */
} }
lua_assert(n != dummynode); lua_assert(!isdummy(n));
othern = mainposition(t, key2tval(mp)); othern = mainposition(t, gkey(mp));
if (othern != mp) { /* is colliding node out of its main position? */ if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */ /* yes; move colliding node into free position */
while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
@ -422,8 +425,8 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
mp = n; mp = n;
} }
} }
gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; setobj2t(L, gkey(mp), key);
luaC_barriert(L, t, key); luaC_barrierback(L, obj2gco(t), key);
lua_assert(ttisnil(gval(mp))); lua_assert(ttisnil(gval(mp)));
return gval(mp); return gval(mp);
} }
@ -432,7 +435,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
/* /*
** search function for integers ** search function for integers
*/ */
const TValue *luaH_getnum (Table *t, int key) { const TValue *luaH_getint (Table *t, int key) {
/* (1 <= key && key <= t->sizearray) */ /* (1 <= key && key <= t->sizearray) */
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
return &t->array[key-1]; return &t->array[key-1];
@ -455,7 +458,7 @@ const TValue *luaH_getnum (Table *t, int key) {
const TValue *luaH_getstr (Table *t, TString *key) { const TValue *luaH_getstr (Table *t, TString *key) {
Node *n = hashstr(t, key); Node *n = hashstr(t, key);
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) if (ttisstring(gkey(n)) && eqstr(rawtsvalue(gkey(n)), key))
return gval(n); /* that's it */ return gval(n); /* that's it */
else n = gnext(n); else n = gnext(n);
} while (n); } while (n);
@ -467,7 +470,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
** main search function ** main search function
*/ */
const TValue *luaH_get (Table *t, const TValue *key) { const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) { switch (ttypenv(key)) {
case LUA_TNIL: return luaO_nilobject; case LUA_TNIL: return luaO_nilobject;
case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNUMBER: { case LUA_TNUMBER: {
@ -475,13 +478,13 @@ const TValue *luaH_get (Table *t, const TValue *key) {
lua_Number n = nvalue(key); lua_Number n = nvalue(key);
lua_number2int(k, n); lua_number2int(k, n);
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
return luaH_getnum(t, k); /* use specialized version */ return luaH_getint(t, k); /* use specialized version */
/* else go through */ /* else go through */
} }
default: { default: {
Node *n = mainposition(t, key); Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(key2tval(n), key)) if (luaV_rawequalobj(gkey(n), key))
return gval(n); /* that's it */ return gval(n); /* that's it */
else n = gnext(n); else n = gnext(n);
} while (n); } while (n);
@ -491,41 +494,29 @@ const TValue *luaH_get (Table *t, const TValue *key) {
} }
/*
** beware: when using this function you probably need to check a GC
** barrier and invalidate the TM cache.
*/
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
const TValue *p = luaH_get(t, key); const TValue *p = luaH_get(t, key);
t->flags = 0;
if (p != luaO_nilobject) if (p != luaO_nilobject)
return cast(TValue *, p); return cast(TValue *, p);
else { else return luaH_newkey(L, t, key);
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
luaG_runerror(L, "table index is NaN");
return newkey(L, t, key);
}
} }
TValue *luaH_setnum (lua_State *L, Table *t, int key) { void luaH_setint (lua_State *L, Table *t, int key, TValue *value) {
const TValue *p = luaH_getnum(t, key); const TValue *p = luaH_getint(t, key);
TValue *cell;
if (p != luaO_nilobject) if (p != luaO_nilobject)
return cast(TValue *, p); cell = cast(TValue *, p);
else { else {
TValue k; TValue k;
setnvalue(&k, cast_num(key)); setnvalue(&k, cast_num(key));
return newkey(L, t, &k); cell = luaH_newkey(L, t, &k);
}
}
TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
const TValue *p = luaH_getstr(t, key);
if (p != luaO_nilobject)
return cast(TValue *, p);
else {
TValue k;
setsvalue(L, &k, key);
return newkey(L, t, &k);
} }
setobj2t(L, cell, value);
} }
@ -533,20 +524,20 @@ static int unbound_search (Table *t, unsigned int j) {
unsigned int i = j; /* i is zero or a present index */ unsigned int i = j; /* i is zero or a present index */
j++; j++;
/* find `i' and `j' such that i is present and j is not */ /* find `i' and `j' such that i is present and j is not */
while (!ttisnil(luaH_getnum(t, j))) { while (!ttisnil(luaH_getint(t, j))) {
i = j; i = j;
j *= 2; j *= 2;
if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
/* table was built with bad purposes: resort to linear search */ /* table was built with bad purposes: resort to linear search */
i = 1; i = 1;
while (!ttisnil(luaH_getnum(t, i))) i++; while (!ttisnil(luaH_getint(t, i))) i++;
return i - 1; return i - 1;
} }
} }
/* now do a binary search between them */ /* now do a binary search between them */
while (j - i > 1) { while (j - i > 1) {
unsigned int m = (i+j)/2; unsigned int m = (i+j)/2;
if (ttisnil(luaH_getnum(t, m))) j = m; if (ttisnil(luaH_getint(t, m))) j = m;
else i = m; else i = m;
} }
return i; return i;
@ -570,7 +561,7 @@ int luaH_getn (Table *t) {
return i; return i;
} }
/* else must find a boundary in hash part */ /* else must find a boundary in hash part */
else if (t->node == dummynode) /* hash part is empty? */ else if (isdummy(t->node)) /* hash part is empty? */
return j; /* that is easy... */ return j; /* that is easy... */
else return unbound_search(t, j); else return unbound_search(t, j);
} }
@ -583,6 +574,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) {
return mainposition(t, key); return mainposition(t, key);
} }
int luaH_isdummy (Node *n) { return n == dummynode; } int luaH_isdummy (Node *n) { return isdummy(n); }
#endif #endif

@ -1,5 +1,5 @@
/* /*
** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ ** $Id: ltablib.c,v 1.63 2011/11/28 17:26:30 roberto Exp $
** Library for Table Manipulation ** Library for Table Manipulation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -16,43 +16,11 @@
#include "lualib.h" #include "lualib.h"
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) #define aux_getn(L,n) \
(luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
static int foreachi (lua_State *L) {
int i;
int n = aux_getn(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
for (i=1; i <= n; i++) {
lua_pushvalue(L, 2); /* function */
lua_pushinteger(L, i); /* 1st argument */
lua_rawgeti(L, 1, i); /* 2nd argument */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
return 1;
lua_pop(L, 1); /* remove nil result */
}
return 0;
}
static int foreach (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_pushnil(L); /* first key */
while (lua_next(L, 1)) {
lua_pushvalue(L, 2); /* function */
lua_pushvalue(L, -3); /* key */
lua_pushvalue(L, -3); /* value */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
return 1;
lua_pop(L, 2); /* remove value and result */
}
return 0;
}
#if defined(LUA_COMPAT_MAXN)
static int maxn (lua_State *L) { static int maxn (lua_State *L) {
lua_Number max = 0; lua_Number max = 0;
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
@ -67,24 +35,7 @@ static int maxn (lua_State *L) {
lua_pushnumber(L, max); lua_pushnumber(L, max);
return 1; return 1;
} }
static int getn (lua_State *L) {
lua_pushinteger(L, aux_getn(L, 1));
return 1;
}
static int setn (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
#ifndef luaL_setn
luaL_setn(L, 1, luaL_checkint(L, 2));
#else
luaL_error(L, LUA_QL("setn") " is obsolete");
#endif #endif
lua_pushvalue(L, 1);
return 1;
}
static int tinsert (lua_State *L) { static int tinsert (lua_State *L) {
@ -109,7 +60,6 @@ static int tinsert (lua_State *L) {
return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
} }
} }
luaL_setn(L, 1, e); /* new size */
lua_rawseti(L, 1, pos); /* t[pos] = v */ lua_rawseti(L, 1, pos); /* t[pos] = v */
return 0; return 0;
} }
@ -119,8 +69,7 @@ static int tremove (lua_State *L) {
int e = aux_getn(L, 1); int e = aux_getn(L, 1);
int pos = luaL_optint(L, 2, e); int pos = luaL_optint(L, 2, e);
if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
return 0; /* nothing to remove */ return 0; /* nothing to remove */
luaL_setn(L, 1, e - 1); /* t.n = n-1 */
lua_rawgeti(L, 1, pos); /* result = t[pos] */ lua_rawgeti(L, 1, pos); /* result = t[pos] */
for ( ;pos<e; pos++) { for ( ;pos<e; pos++) {
lua_rawgeti(L, 1, pos+1); lua_rawgeti(L, 1, pos+1);
@ -137,7 +86,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) {
if (!lua_isstring(L, -1)) if (!lua_isstring(L, -1))
luaL_error(L, "invalid value (%s) at index %d in table for " luaL_error(L, "invalid value (%s) at index %d in table for "
LUA_QL("concat"), luaL_typename(L, -1), i); LUA_QL("concat"), luaL_typename(L, -1), i);
luaL_addvalue(b); luaL_addvalue(b);
} }
@ -148,7 +97,7 @@ static int tconcat (lua_State *L) {
const char *sep = luaL_optlstring(L, 2, "", &lsep); const char *sep = luaL_optlstring(L, 2, "", &lsep);
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
i = luaL_optint(L, 3, 1); i = luaL_optint(L, 3, 1);
last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
for (; i < last; i++) { for (; i < last; i++) {
addfield(L, &b, i); addfield(L, &b, i);
@ -161,12 +110,54 @@ static int tconcat (lua_State *L) {
} }
/*
** {======================================================
** Pack/unpack
** =======================================================
*/
static int pack (lua_State *L) {
int n = lua_gettop(L); /* number of elements to pack */
lua_createtable(L, n, 1); /* create result table */
lua_pushinteger(L, n);
lua_setfield(L, -2, "n"); /* t.n = number of elements */
if (n > 0) { /* at least one element? */
int i;
lua_pushvalue(L, 1);
lua_rawseti(L, -2, 1); /* insert first element */
lua_replace(L, 1); /* move table into index 1 */
for (i = n; i >= 2; i--) /* assign other elements */
lua_rawseti(L, 1, i);
}
return 1; /* return table */
}
static int unpack (lua_State *L) {
int i, e, n;
luaL_checktype(L, 1, LUA_TTABLE);
i = luaL_optint(L, 2, 1);
e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
if (i > e) return 0; /* empty range */
n = e - i + 1; /* number of elements */
if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
return luaL_error(L, "too many results to unpack");
lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
while (i++ < e) /* push arg[i + 1...e] */
lua_rawgeti(L, 1, i);
return n;
}
/* }====================================================== */
/* /*
** {====================================================== ** {======================================================
** Quicksort ** Quicksort
** (based on `Algorithms in MODULA-3', Robert Sedgewick; ** (based on `Algorithms in MODULA-3', Robert Sedgewick;
** Addison-Wesley, 1993.) ** Addison-Wesley, 1993.)
** =======================================================
*/ */
@ -187,7 +178,7 @@ static int sort_comp (lua_State *L, int a, int b) {
return res; return res;
} }
else /* a < b? */ else /* a < b? */
return lua_lessthan(L, a, b); return lua_compare(L, a, b, LUA_OPLT);
} }
static void auxsort (lua_State *L, int l, int u) { static void auxsort (lua_State *L, int l, int u) {
@ -224,12 +215,12 @@ static void auxsort (lua_State *L, int l, int u) {
for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
/* repeat ++i until a[i] >= P */ /* repeat ++i until a[i] >= P */
while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
if (i>u) luaL_error(L, "invalid order function for sorting"); if (i>=u) luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[i] */ lua_pop(L, 1); /* remove a[i] */
} }
/* repeat --j until a[j] <= P */ /* repeat --j until a[j] <= P */
while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
if (j<l) luaL_error(L, "invalid order function for sorting"); if (j<=l) luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[j] */ lua_pop(L, 1); /* remove a[j] */
} }
if (j<i) { if (j<i) {
@ -268,20 +259,25 @@ static int sort (lua_State *L) {
static const luaL_Reg tab_funcs[] = { static const luaL_Reg tab_funcs[] = {
{"concat", tconcat}, {"concat", tconcat},
{"foreach", foreach}, #if defined(LUA_COMPAT_MAXN)
{"foreachi", foreachi},
{"getn", getn},
{"maxn", maxn}, {"maxn", maxn},
#endif
{"insert", tinsert}, {"insert", tinsert},
{"pack", pack},
{"unpack", unpack},
{"remove", tremove}, {"remove", tremove},
{"setn", setn},
{"sort", sort}, {"sort", sort},
{NULL, NULL} {NULL, NULL}
}; };
LUALIB_API int luaopen_table (lua_State *L) { LUAMOD_API int luaopen_table (lua_State *L) {
luaL_register(L, LUA_TABLIBNAME, tab_funcs); luaL_newlib(L, tab_funcs);
#if defined(LUA_COMPAT_UNPACK)
/* _G.unpack = table.unpack */
lua_getfield(L, -1, "unpack");
lua_setglobal(L, "unpack");
#endif
return 1; return 1;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: ltm.c,v 2.14 2011/06/02 19:31:40 roberto Exp $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -19,20 +19,22 @@
#include "ltm.h" #include "ltm.h"
static const char udatatypename[] = "userdata";
const char *const luaT_typenames[] = { LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
"nil", "boolean", "userdata", "number", "no value",
"string", "table", "function", "userdata", "thread", "nil", "boolean", udatatypename, "number",
"proto", "upval" "string", "table", "function", udatatypename, "thread",
"proto", "upval" /* these last two cases are used for tests only */
}; };
void luaT_init (lua_State *L) { void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */ static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex", "__index", "__newindex",
"__gc", "__mode", "__eq", "__gc", "__mode", "__len", "__eq",
"__add", "__sub", "__mul", "__div", "__mod", "__add", "__sub", "__mul", "__div", "__mod",
"__pow", "__unm", "__len", "__lt", "__le", "__pow", "__unm", "__lt", "__le",
"__concat", "__call" "__concat", "__call"
}; };
int i; int i;
@ -60,7 +62,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
Table *mt; Table *mt;
switch (ttype(o)) { switch (ttypenv(o)) {
case LUA_TTABLE: case LUA_TTABLE:
mt = hvalue(o)->metatable; mt = hvalue(o)->metatable;
break; break;
@ -68,7 +70,7 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
mt = uvalue(o)->metatable; mt = uvalue(o)->metatable;
break; break;
default: default:
mt = G(L)->mt[ttype(o)]; mt = G(L)->mt[ttypenv(o)];
} }
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
} }

@ -1,5 +1,5 @@
/* /*
** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $ ** $Id: lua.c,v 1.203 2011/12/12 16:34:03 roberto Exp $
** Lua stand-alone interpreter ** Lua stand-alone interpreter
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -18,6 +18,72 @@
#include "lualib.h" #include "lualib.h"
#if !defined(LUA_PROMPT)
#define LUA_PROMPT "> "
#define LUA_PROMPT2 ">> "
#endif
#if !defined(LUA_PROGNAME)
#define LUA_PROGNAME "lua"
#endif
#if !defined(LUA_MAXINPUT)
#define LUA_MAXINPUT 512
#endif
#if !defined(LUA_INIT)
#define LUA_INIT "LUA_INIT"
#endif
#define LUA_INITVERSION \
LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
/*
** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
** is, whether we're running lua interactively).
*/
#if defined(LUA_USE_ISATTY)
#include <unistd.h>
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#include <stdio.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
#endif
/*
** lua_readline defines how to show a prompt and then read a line from
** the standard input.
** lua_saveline defines how to "save" a read line in a "history".
** lua_freeline defines how to free a line read by lua_readline.
*/
#if defined(LUA_USE_READLINE)
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \
if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */
#define lua_freeline(L,b) ((void)L, free(b))
#elif !defined(lua_readline)
#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif
static lua_State *globalL = NULL; static lua_State *globalL = NULL;
@ -39,77 +105,87 @@ static void laction (int i) {
} }
static void print_usage (void) { static void print_usage (const char *badoption) {
fprintf(stderr, luai_writestringerror("%s: ", progname);
"usage: %s [options] [script [args]].\n" if (badoption[1] == 'e' || badoption[1] == 'l')
luai_writestringerror("'%s' needs argument\n", badoption);
else
luai_writestringerror("unrecognized option '%s'\n", badoption);
luai_writestringerror(
"usage: %s [options] [script [args]]\n"
"Available options are:\n" "Available options are:\n"
" -e stat execute string " LUA_QL("stat") "\n" " -e stat execute string " LUA_QL("stat") "\n"
" -l name require library " LUA_QL("name") "\n"
" -i enter interactive mode after executing " LUA_QL("script") "\n" " -i enter interactive mode after executing " LUA_QL("script") "\n"
" -l name require library " LUA_QL("name") "\n"
" -v show version information\n" " -v show version information\n"
" -E ignore environment variables\n"
" -- stop handling options\n" " -- stop handling options\n"
" - execute stdin and stop handling options\n" " - stop handling options and execute stdin\n"
, ,
progname); progname);
fflush(stderr);
} }
static void l_message (const char *pname, const char *msg) { static void l_message (const char *pname, const char *msg) {
if (pname) fprintf(stderr, "%s: ", pname); if (pname) luai_writestringerror("%s: ", pname);
fprintf(stderr, "%s\n", msg); luai_writestringerror("%s\n", msg);
fflush(stderr);
} }
static int report (lua_State *L, int status) { static int report (lua_State *L, int status) {
if (status && !lua_isnil(L, -1)) { if (status != LUA_OK && !lua_isnil(L, -1)) {
const char *msg = lua_tostring(L, -1); const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)"; if (msg == NULL) msg = "(error object is not a string)";
l_message(progname, msg); l_message(progname, msg);
lua_pop(L, 1); lua_pop(L, 1);
/* force a complete garbage collection in case of errors */
lua_gc(L, LUA_GCCOLLECT, 0);
} }
return status; return status;
} }
static int traceback (lua_State *L) { /* the next function is called unprotected, so it must avoid errors */
if (!lua_isstring(L, 1)) /* 'message' not a string? */ static void finalreport (lua_State *L, int status) {
return 1; /* keep it intact */ if (status != LUA_OK) {
lua_getfield(L, LUA_GLOBALSINDEX, "debug"); const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1)
if (!lua_istable(L, -1)) { : NULL;
if (msg == NULL) msg = "(error object is not a string)";
l_message(progname, msg);
lua_pop(L, 1); lua_pop(L, 1);
return 1;
} }
lua_getfield(L, -1, "traceback"); }
if (!lua_isfunction(L, -1)) {
lua_pop(L, 2);
return 1; static int traceback (lua_State *L) {
const char *msg = lua_tostring(L, 1);
if (msg)
luaL_traceback(L, L, msg, 1);
else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */
if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
lua_pushliteral(L, "(no error message)");
} }
lua_pushvalue(L, 1); /* pass error message */
lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback */
return 1; return 1;
} }
static int docall (lua_State *L, int narg, int clear) { static int docall (lua_State *L, int narg, int nres) {
int status; int status;
int base = lua_gettop(L) - narg; /* function index */ int base = lua_gettop(L) - narg; /* function index */
lua_pushcfunction(L, traceback); /* push traceback function */ lua_pushcfunction(L, traceback); /* push traceback function */
lua_insert(L, base); /* put it under chunk and args */ lua_insert(L, base); /* put it under chunk and args */
globalL = L; /* to be available to 'laction' */
signal(SIGINT, laction); signal(SIGINT, laction);
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); status = lua_pcall(L, narg, nres, base);
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
lua_remove(L, base); /* remove traceback function */ lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection in case of errors */
if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
return status; return status;
} }
static void print_version (void) { static void print_version (void) {
l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT); luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
luai_writeline();
} }
@ -132,40 +208,53 @@ static int getargs (lua_State *L, char **argv, int n) {
static int dofile (lua_State *L, const char *name) { static int dofile (lua_State *L, const char *name) {
int status = luaL_loadfile(L, name) || docall(L, 0, 1); int status = luaL_loadfile(L, name);
if (status == LUA_OK) status = docall(L, 0, 0);
return report(L, status); return report(L, status);
} }
static int dostring (lua_State *L, const char *s, const char *name) { static int dostring (lua_State *L, const char *s, const char *name) {
int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); int status = luaL_loadbuffer(L, s, strlen(s), name);
if (status == LUA_OK) status = docall(L, 0, 0);
return report(L, status); return report(L, status);
} }
static int dolibrary (lua_State *L, const char *name) { static int dolibrary (lua_State *L, const char *name) {
lua_getglobal(L, "require"); int status;
lua_pushglobaltable(L);
lua_getfield(L, -1, "require");
lua_pushstring(L, name); lua_pushstring(L, name);
return report(L, docall(L, 1, 1)); status = docall(L, 1, 1);
if (status == LUA_OK) {
lua_setfield(L, -2, name); /* global[name] = require return */
lua_pop(L, 1); /* remove global table */
}
else
lua_remove(L, -2); /* remove global table (below error msg.) */
return report(L, status);
} }
static const char *get_prompt (lua_State *L, int firstline) { static const char *get_prompt (lua_State *L, int firstline) {
const char *p; const char *p;
lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
p = lua_tostring(L, -1); p = lua_tostring(L, -1);
if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
lua_pop(L, 1); /* remove global */ lua_pop(L, 1); /* remove global */
return p; return p;
} }
/* mark in error messages for incomplete statements */
#define EOFMARK "<eof>"
#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
static int incomplete (lua_State *L, int status) { static int incomplete (lua_State *L, int status) {
if (status == LUA_ERRSYNTAX) { if (status == LUA_ERRSYNTAX) {
size_t lmsg; size_t lmsg;
const char *msg = lua_tolstring(L, -1, &lmsg); const char *msg = lua_tolstring(L, -1, &lmsg);
const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1); if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
if (strstr(msg, LUA_QL("<eof>")) == tp) {
lua_pop(L, 1); lua_pop(L, 1);
return 1; return 1;
} }
@ -199,7 +288,9 @@ static int loadline (lua_State *L) {
if (!pushline(L, 1)) if (!pushline(L, 1))
return -1; /* no input */ return -1; /* no input */
for (;;) { /* repeat until gets a complete line */ for (;;) { /* repeat until gets a complete line */
status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); size_t l;
const char *line = lua_tolstring(L, 1, &l);
status = luaL_loadbuffer(L, line, l, "=stdin");
if (!incomplete(L, status)) break; /* cannot try to add lines? */ if (!incomplete(L, status)) break; /* cannot try to add lines? */
if (!pushline(L, 0)) /* no more input? */ if (!pushline(L, 0)) /* no more input? */
return -1; return -1;
@ -218,20 +309,20 @@ static void dotty (lua_State *L) {
const char *oldprogname = progname; const char *oldprogname = progname;
progname = NULL; progname = NULL;
while ((status = loadline(L)) != -1) { while ((status = loadline(L)) != -1) {
if (status == 0) status = docall(L, 0, 0); if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET);
report(L, status); report(L, status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */
luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
lua_getglobal(L, "print"); lua_getglobal(L, "print");
lua_insert(L, 1); lua_insert(L, 1);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK)
l_message(progname, lua_pushfstring(L, l_message(progname, lua_pushfstring(L,
"error calling " LUA_QL("print") " (%s)", "error calling " LUA_QL("print") " (%s)",
lua_tostring(L, -1))); lua_tostring(L, -1)));
} }
} }
lua_settop(L, 0); /* clear stack */ lua_settop(L, 0); /* clear stack */
fputs("\n", stdout); luai_writeline();
fflush(stdout);
progname = oldprogname; progname = oldprogname;
} }
@ -242,49 +333,63 @@ static int handle_script (lua_State *L, char **argv, int n) {
int narg = getargs(L, argv, n); /* collect arguments */ int narg = getargs(L, argv, n); /* collect arguments */
lua_setglobal(L, "arg"); lua_setglobal(L, "arg");
fname = argv[n]; fname = argv[n];
if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
fname = NULL; /* stdin */ fname = NULL; /* stdin */
status = luaL_loadfile(L, fname); status = luaL_loadfile(L, fname);
lua_insert(L, -(narg+1)); lua_insert(L, -(narg+1));
if (status == 0) if (status == LUA_OK)
status = docall(L, narg, 0); status = docall(L, narg, LUA_MULTRET);
else else
lua_pop(L, narg); lua_pop(L, narg);
return report(L, status); return report(L, status);
} }
/* check that argument has no extra characters at the end */ /* check that argument has no extra characters at the end */
#define notail(x) {if ((x)[2] != '\0') return -1;} #define noextrachars(x) {if ((x)[2] != '\0') return -1;}
/* indices of various argument indicators in array args */
#define has_i 0 /* -i */
#define has_v 1 /* -v */
#define has_e 2 /* -e */
#define has_E 3 /* -E */
#define num_has 4 /* number of 'has_*' */
static int collectargs (char **argv, int *pi, int *pv, int *pe) {
static int collectargs (char **argv, int *args) {
int i; int i;
for (i = 1; argv[i] != NULL; i++) { for (i = 1; argv[i] != NULL; i++) {
if (argv[i][0] != '-') /* not an option? */ if (argv[i][0] != '-') /* not an option? */
return i; return i;
switch (argv[i][1]) { /* option */ switch (argv[i][1]) { /* option */
case '-': case '-':
notail(argv[i]); noextrachars(argv[i]);
return (argv[i+1] != NULL ? i+1 : 0); return (argv[i+1] != NULL ? i+1 : 0);
case '\0': case '\0':
return i; return i;
case 'E':
args[has_E] = 1;
break;
case 'i': case 'i':
notail(argv[i]); noextrachars(argv[i]);
*pi = 1; /* go through */ args[has_i] = 1; /* go through */
case 'v': case 'v':
notail(argv[i]); noextrachars(argv[i]);
*pv = 1; args[has_v] = 1;
break; break;
case 'e': case 'e':
*pe = 1; /* go through */ args[has_e] = 1; /* go through */
case 'l': case 'l': /* both options need an argument */
if (argv[i][2] == '\0') { if (argv[i][2] == '\0') { /* no concatenated argument? */
i++; i++; /* try next 'argv' */
if (argv[i] == NULL) return -1; if (argv[i] == NULL || argv[i][0] == '-')
return -(i - 1); /* no next argument or it is another option */
} }
break; break;
default: return -1; /* invalid option */ default: /* invalid option; return its index... */
return -i; /* ...as a negative value */
} }
} }
return 0; return 0;
@ -294,99 +399,103 @@ static int collectargs (char **argv, int *pi, int *pv, int *pe) {
static int runargs (lua_State *L, char **argv, int n) { static int runargs (lua_State *L, char **argv, int n) {
int i; int i;
for (i = 1; i < n; i++) { for (i = 1; i < n; i++) {
if (argv[i] == NULL) continue;
lua_assert(argv[i][0] == '-'); lua_assert(argv[i][0] == '-');
switch (argv[i][1]) { /* option */ switch (argv[i][1]) { /* option */
case 'e': { case 'e': {
const char *chunk = argv[i] + 2; const char *chunk = argv[i] + 2;
if (*chunk == '\0') chunk = argv[++i]; if (*chunk == '\0') chunk = argv[++i];
lua_assert(chunk != NULL); lua_assert(chunk != NULL);
if (dostring(L, chunk, "=(command line)") != 0) if (dostring(L, chunk, "=(command line)") != LUA_OK)
return 1; return 0;
break; break;
} }
case 'l': { case 'l': {
const char *filename = argv[i] + 2; const char *filename = argv[i] + 2;
if (*filename == '\0') filename = argv[++i]; if (*filename == '\0') filename = argv[++i];
lua_assert(filename != NULL); lua_assert(filename != NULL);
if (dolibrary(L, filename)) if (dolibrary(L, filename) != LUA_OK)
return 1; /* stop if file fails */ return 0; /* stop if file fails */
break; break;
} }
default: break; default: break;
} }
} }
return 0; return 1;
} }
static int handle_luainit (lua_State *L) { static int handle_luainit (lua_State *L) {
const char *init = getenv(LUA_INIT); const char *name = "=" LUA_INITVERSION;
if (init == NULL) return 0; /* status OK */ const char *init = getenv(name + 1);
if (init == NULL) {
name = "=" LUA_INIT;
init = getenv(name + 1); /* try alternative name */
}
if (init == NULL) return LUA_OK;
else if (init[0] == '@') else if (init[0] == '@')
return dofile(L, init+1); return dofile(L, init+1);
else else
return dostring(L, init, "=" LUA_INIT); return dostring(L, init, name);
} }
struct Smain {
int argc;
char **argv;
int status;
};
static int pmain (lua_State *L) { static int pmain (lua_State *L) {
struct Smain *s = (struct Smain *)lua_touserdata(L, 1); int argc = (int)lua_tointeger(L, 1);
char **argv = s->argv; char **argv = (char **)lua_touserdata(L, 2);
int script; int script;
int has_i = 0, has_v = 0, has_e = 0; int args[num_has];
globalL = L; args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0;
if (argv[0] && argv[0][0]) progname = argv[0]; if (argv[0] && argv[0][0]) progname = argv[0];
script = collectargs(argv, args);
if (script < 0) { /* invalid arg? */
print_usage(argv[-script]);
return 0;
}
if (args[has_v]) print_version();
if (args[has_E]) { /* option '-E'? */
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
}
/* open standard libraries */
luaL_checkversion(L);
lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
luaL_openlibs(L); /* open libraries */ luaL_openlibs(L); /* open libraries */
lua_gc(L, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
s->status = handle_luainit(L); if (!args[has_E] && handle_luainit(L) != LUA_OK)
if (s->status != 0) return 0; return 0; /* error running LUA_INIT */
script = collectargs(argv, &has_i, &has_v, &has_e); /* execute arguments -e and -l */
if (script < 0) { /* invalid args? */ if (!runargs(L, argv, (script > 0) ? script : argc)) return 0;
print_usage(); /* execute main script (if there is one) */
s->status = 1; if (script && handle_script(L, argv, script) != LUA_OK) return 0;
return 0; if (args[has_i]) /* -i option? */
}
if (has_v) print_version();
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
if (s->status != 0) return 0;
if (script)
s->status = handle_script(L, argv, script);
if (s->status != 0) return 0;
if (has_i)
dotty(L); dotty(L);
else if (script == 0 && !has_e && !has_v) { else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */
if (lua_stdin_is_tty()) { if (lua_stdin_is_tty()) {
print_version(); print_version();
dotty(L); dotty(L);
} }
else dofile(L, NULL); /* executes stdin as a file */ else dofile(L, NULL); /* executes stdin as a file */
} }
return 0; lua_pushboolean(L, 1); /* signal no errors */
return 1;
} }
int main (int argc, char **argv) { int main (int argc, char **argv) {
int status; int status, result;
struct Smain s; lua_State *L = luaL_newstate(); /* create state */
lua_State *L = lua_open(); /* create state */
if (L == NULL) { if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory"); l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
s.argc = argc; /* call 'pmain' in protected mode */
s.argv = argv; lua_pushcfunction(L, &pmain);
status = lua_cpcall(L, &pmain, &s); lua_pushinteger(L, argc); /* 1st argument */
report(L, status); lua_pushlightuserdata(L, argv); /* 2nd argument */
status = lua_pcall(L, 2, 1, 0);
result = lua_toboolean(L, -1); /* get result */
finalreport(L, status);
lua_close(L); lua_close(L);
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
} }

@ -1,5 +1,5 @@
/* /*
** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ ** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $
** Lua compiler (saves bytecodes to files; also list bytecodes) ** Lua compiler (saves bytecodes to files; also list bytecodes)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -15,16 +15,15 @@
#include "lua.h" #include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h" #include "lobject.h"
#include "lopcodes.h" #include "lstate.h"
#include "lstring.h"
#include "lundump.h" #include "lundump.h"
static void PrintFunction(const Proto* f, int full);
#define luaU_print PrintFunction
#define PROGNAME "luac" /* default program name */ #define PROGNAME "luac" /* default program name */
#define OUTPUT PROGNAME ".out" /* default output file */ #define OUTPUT PROGNAME ".out" /* default output file */
static int listing=0; /* list bytecodes? */ static int listing=0; /* list bytecodes? */
static int dumping=1; /* dump bytecodes? */ static int dumping=1; /* dump bytecodes? */
@ -52,20 +51,20 @@ static void usage(const char* message)
else else
fprintf(stderr,"%s: %s\n",progname,message); fprintf(stderr,"%s: %s\n",progname,message);
fprintf(stderr, fprintf(stderr,
"usage: %s [options] [filenames].\n" "usage: %s [options] [filenames]\n"
"Available options are:\n" "Available options are:\n"
" - process stdin\n" " -l list (use -l -l for full listing)\n"
" -l list\n" " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
" -o name output to file " LUA_QL("name") " (default is \"%s\")\n" " -p parse only\n"
" -p parse only\n" " -s strip debug information\n"
" -s strip debug information\n" " -v show version information\n"
" -v show version information\n" " -- stop handling options\n"
" -- stop handling options\n", " - stop handling options and process stdin\n"
progname,Output); ,progname,Output);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
#define IS(s) (strcmp(argv[i],s)==0) #define IS(s) (strcmp(argv[i],s)==0)
static int doargs(int argc, char* argv[]) static int doargs(int argc, char* argv[])
{ {
@ -89,7 +88,8 @@ static int doargs(int argc, char* argv[])
else if (IS("-o")) /* output file */ else if (IS("-o")) /* output file */
{ {
output=argv[++i]; output=argv[++i];
if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument"); if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
usage(LUA_QL("-o") " needs argument");
if (IS("-")) output=NULL; if (IS("-")) output=NULL;
} }
else if (IS("-p")) /* parse only */ else if (IS("-p")) /* parse only */
@ -108,13 +108,30 @@ static int doargs(int argc, char* argv[])
} }
if (version) if (version)
{ {
printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT); printf("%s\n",LUA_COPYRIGHT);
if (version==argc-1) exit(EXIT_SUCCESS); if (version==argc-1) exit(EXIT_SUCCESS);
} }
return i; return i;
} }
#define toproto(L,i) (clvalue(L->top+(i))->l.p) #define FUNCTION "(function()end)();"
static const char* reader(lua_State *L, void *ud, size_t *size)
{
UNUSED(L);
if ((*(int*)ud)--)
{
*size=sizeof(FUNCTION)-1;
return FUNCTION;
}
else
{
*size=0;
return NULL;
}
}
#define toproto(L,i) getproto(L->top+(i))
static const Proto* combine(lua_State* L, int n) static const Proto* combine(lua_State* L, int n)
{ {
@ -122,24 +139,16 @@ static const Proto* combine(lua_State* L, int n)
return toproto(L,-1); return toproto(L,-1);
else else
{ {
int i,pc; Proto* f;
Proto* f=luaF_newproto(L); int i=n;
setptvalue2s(L,L->top,f); incr_top(L); if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
f->source=luaS_newliteral(L,"=(" PROGNAME ")"); f=toproto(L,-1);
f->maxstacksize=1;
pc=2*n+1;
f->code=luaM_newvector(L,pc,Instruction);
f->sizecode=pc;
f->p=luaM_newvector(L,n,Proto*);
f->sizep=n;
pc=0;
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
f->p[i]=toproto(L,i-n-1); f->p[i]=toproto(L,i-n-1);
f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
} }
f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); f->sizelineinfo=0;
return f; return f;
} }
} }
@ -150,23 +159,17 @@ static int writer(lua_State* L, const void* p, size_t size, void* u)
return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
} }
struct Smain {
int argc;
char** argv;
};
static int pmain(lua_State* L) static int pmain(lua_State* L)
{ {
struct Smain* s = (struct Smain*)lua_touserdata(L, 1); int argc=(int)lua_tointeger(L,1);
int argc=s->argc; char** argv=(char**)lua_touserdata(L,2);
char** argv=s->argv;
const Proto* f; const Proto* f;
int i; int i;
if (!lua_checkstack(L,argc)) fatal("too many input files"); if (!lua_checkstack(L,argc)) fatal("too many input files");
for (i=0; i<argc; i++) for (i=0; i<argc; i++)
{ {
const char* filename=IS("-") ? NULL : argv[i]; const char* filename=IS("-") ? NULL : argv[i];
if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1)); if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1));
} }
f=combine(L,argc); f=combine(L,argc);
if (listing) luaU_print(f,listing>1); if (listing) luaU_print(f,listing>1);
@ -186,15 +189,244 @@ static int pmain(lua_State* L)
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
lua_State* L; lua_State* L;
struct Smain s;
int i=doargs(argc,argv); int i=doargs(argc,argv);
argc-=i; argv+=i; argc-=i; argv+=i;
if (argc<=0) usage("no input files given"); if (argc<=0) usage("no input files given");
L=lua_open(); L=luaL_newstate();
if (L==NULL) fatal("not enough memory for state"); if (L==NULL) fatal("cannot create state: not enough memory");
s.argc=argc; lua_pushcfunction(L,&pmain);
s.argv=argv; lua_pushinteger(L,argc);
if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); lua_pushlightuserdata(L,argv);
if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
lua_close(L); lua_close(L);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/*
** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdio.h>
#define luac_c
#define LUA_CORE
#include "ldebug.h"
#include "lobject.h"
#include "lopcodes.h"
#define VOID(p) ((const void*)(p))
static void PrintString(const TString* ts)
{
const char* s=getstr(ts);
size_t i,n=ts->tsv.len;
printf("%c",'"');
for (i=0; i<n; i++)
{
int c=(int)(unsigned char)s[i];
switch (c)
{
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
case '\a': printf("\\a"); break;
case '\b': printf("\\b"); break;
case '\f': printf("\\f"); break;
case '\n': printf("\\n"); break;
case '\r': printf("\\r"); break;
case '\t': printf("\\t"); break;
case '\v': printf("\\v"); break;
default: if (isprint(c))
printf("%c",c);
else
printf("\\%03d",c);
}
}
printf("%c",'"');
}
static void PrintConstant(const Proto* f, int i)
{
const TValue* o=&f->k[i];
switch (ttype(o))
{
case LUA_TNIL:
printf("nil");
break;
case LUA_TBOOLEAN:
printf(bvalue(o) ? "true" : "false");
break;
case LUA_TNUMBER:
printf(LUA_NUMBER_FMT,nvalue(o));
break;
case LUA_TSTRING:
PrintString(rawtsvalue(o));
break;
default: /* cannot happen */
printf("? type=%d",ttype(o));
break;
}
}
#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
#define MYK(x) (-1-(x))
static void PrintCode(const Proto* f)
{
const Instruction* code=f->code;
int pc,n=f->sizecode;
for (pc=0; pc<n; pc++)
{
Instruction i=code[pc];
OpCode o=GET_OPCODE(i);
int a=GETARG_A(i);
int b=GETARG_B(i);
int c=GETARG_C(i);
int ax=GETARG_Ax(i);
int bx=GETARG_Bx(i);
int sbx=GETARG_sBx(i);
int line=getfuncline(f,pc);
printf("\t%d\t",pc+1);
if (line>0) printf("[%d]\t",line); else printf("[-]\t");
printf("%-9s\t",luaP_opnames[o]);
switch (getOpMode(o))
{
case iABC:
printf("%d",a);
if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b);
if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c);
break;
case iABx:
printf("%d",a);
if (getBMode(o)==OpArgK) printf(" %d",MYK(bx));
if (getBMode(o)==OpArgU) printf(" %d",bx);
break;
case iAsBx:
printf("%d %d",a,sbx);
break;
case iAx:
printf("%d",MYK(ax));
break;
}
switch (o)
{
case OP_LOADK:
printf("\t; "); PrintConstant(f,bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
printf("\t; %s",UPVALNAME(b));
break;
case OP_GETTABUP:
printf("\t; %s",UPVALNAME(b));
if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
break;
case OP_SETTABUP:
printf("\t; %s",UPVALNAME(a));
if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); }
if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
break;
case OP_GETTABLE:
case OP_SELF:
if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
break;
case OP_SETTABLE:
case OP_ADD:
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_POW:
case OP_EQ:
case OP_LT:
case OP_LE:
if (ISK(b) || ISK(c))
{
printf("\t; ");
if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
printf(" ");
if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
}
break;
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
case OP_TFORLOOP:
printf("\t; to %d",sbx+pc+2);
break;
case OP_CLOSURE:
printf("\t; %p",VOID(f->p[bx]));
break;
case OP_SETLIST:
if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c);
break;
case OP_EXTRAARG:
printf("\t; "); PrintConstant(f,ax);
break;
default:
break;
}
printf("\n");
}
}
#define SS(x) ((x==1)?"":"s")
#define S(x) (int)(x),SS(x)
static void PrintHeader(const Proto* f)
{
const char* s=f->source ? getstr(f->source) : "=?";
if (*s=='@' || *s=='=')
s++;
else if (*s==LUA_SIGNATURE[0])
s="(bstring)";
else
s="(string)";
printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
(f->linedefined==0)?"main":"function",s,
f->linedefined,f->lastlinedefined,
S(f->sizecode),VOID(f));
printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
(int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
S(f->maxstacksize),S(f->sizeupvalues));
printf("%d local%s, %d constant%s, %d function%s\n",
S(f->sizelocvars),S(f->sizek),S(f->sizep));
}
static void PrintDebug(const Proto* f)
{
int i,n;
n=f->sizek;
printf("constants (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t",i+1);
PrintConstant(f,i);
printf("\n");
}
n=f->sizelocvars;
printf("locals (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t%s\t%d\t%d\n",
i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
}
n=f->sizeupvalues;
printf("upvalues (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t%s\t%d\t%d\n",
i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
}
}
static void PrintFunction(const Proto* f, int full)
{
int i,n=f->sizep;
PrintHeader(f);
PrintCode(f);
if (full) PrintDebug(f);
for (i=0; i<n; i++) PrintFunction(f->p[i],full);
}

@ -1,5 +1,5 @@
/* /*
** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ ** $Id: lundump.c,v 1.71 2011/12/07 10:39:12 lhf Exp $
** load precompiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -27,28 +27,24 @@ typedef struct {
const char* name; const char* name;
} LoadState; } LoadState;
#ifdef LUAC_TRUST_BINARIES
#define IF(c,s)
#define error(S,s)
#else
#define IF(c,s) if (c) error(S,s)
static void error(LoadState* S, const char* why) static void error(LoadState* S, const char* why)
{ {
luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
luaD_throw(S->L,LUA_ERRSYNTAX); luaD_throw(S->L,LUA_ERRSYNTAX);
} }
#endif
#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
#define LoadByte(S) (lu_byte)LoadChar(S) #define LoadByte(S) (lu_byte)LoadChar(S)
#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
#if !defined(luai_verifycode)
#define luai_verifycode(L,b,f) (f)
#endif
static void LoadBlock(LoadState* S, void* b, size_t size) static void LoadBlock(LoadState* S, void* b, size_t size)
{ {
size_t r=luaZ_read(S->Z,b,size); if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated");
IF (r!=0, "unexpected end");
} }
static int LoadChar(LoadState* S) static int LoadChar(LoadState* S)
@ -62,7 +58,7 @@ static int LoadInt(LoadState* S)
{ {
int x; int x;
LoadVar(S,x); LoadVar(S,x);
IF (x<0, "bad integer"); if (x<0) error(S,"corrupted");
return x; return x;
} }
@ -82,7 +78,7 @@ static TString* LoadString(LoadState* S)
else else
{ {
char* s=luaZ_openspace(S->L,S->b,size); char* s=luaZ_openspace(S->L,S->b,size);
LoadBlock(S,s,size); LoadBlock(S,s,size*sizeof(char));
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
} }
} }
@ -95,7 +91,7 @@ static void LoadCode(LoadState* S, Proto* f)
LoadVector(S,f->code,n,sizeof(Instruction)); LoadVector(S,f->code,n,sizeof(Instruction));
} }
static Proto* LoadFunction(LoadState* S, TString* p); static Proto* LoadFunction(LoadState* S);
static void LoadConstants(LoadState* S, Proto* f) static void LoadConstants(LoadState* S, Proto* f)
{ {
@ -111,10 +107,10 @@ static void LoadConstants(LoadState* S, Proto* f)
switch (t) switch (t)
{ {
case LUA_TNIL: case LUA_TNIL:
setnilvalue(o); setnilvalue(o);
break; break;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
setbvalue(o,LoadChar(S)!=0); setbvalue(o,LoadChar(S));
break; break;
case LUA_TNUMBER: case LUA_TNUMBER:
setnvalue(o,LoadNumber(S)); setnvalue(o,LoadNumber(S));
@ -122,21 +118,33 @@ static void LoadConstants(LoadState* S, Proto* f)
case LUA_TSTRING: case LUA_TSTRING:
setsvalue2n(S->L,o,LoadString(S)); setsvalue2n(S->L,o,LoadString(S));
break; break;
default:
error(S,"bad constant");
break;
} }
} }
n=LoadInt(S); n=LoadInt(S);
f->p=luaM_newvector(S->L,n,Proto*); f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n; f->sizep=n;
for (i=0; i<n; i++) f->p[i]=NULL; for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); for (i=0; i<n; i++) f->p[i]=LoadFunction(S);
}
static void LoadUpvalues(LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->upvalues=luaM_newvector(S->L,n,Upvaldesc);
f->sizeupvalues=n;
for (i=0; i<n; i++) f->upvalues[i].name=NULL;
for (i=0; i<n; i++)
{
f->upvalues[i].instack=LoadByte(S);
f->upvalues[i].idx=LoadByte(S);
}
} }
static void LoadDebug(LoadState* S, Proto* f) static void LoadDebug(LoadState* S, Proto* f)
{ {
int i,n; int i,n;
f->source=LoadString(S);
n=LoadInt(S); n=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,n,int); f->lineinfo=luaM_newvector(S->L,n,int);
f->sizelineinfo=n; f->sizelineinfo=n;
@ -152,41 +160,43 @@ static void LoadDebug(LoadState* S, Proto* f)
f->locvars[i].endpc=LoadInt(S); f->locvars[i].endpc=LoadInt(S);
} }
n=LoadInt(S); n=LoadInt(S);
f->upvalues=luaM_newvector(S->L,n,TString*); for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
f->sizeupvalues=n;
for (i=0; i<n; i++) f->upvalues[i]=NULL;
for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
} }
static Proto* LoadFunction(LoadState* S, TString* p) static Proto* LoadFunction(LoadState* S)
{ {
Proto* f; Proto* f=luaF_newproto(S->L);
if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
f=luaF_newproto(S->L);
setptvalue2s(S->L,S->L->top,f); incr_top(S->L); setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->linedefined=LoadInt(S); f->linedefined=LoadInt(S);
f->lastlinedefined=LoadInt(S); f->lastlinedefined=LoadInt(S);
f->nups=LoadByte(S);
f->numparams=LoadByte(S); f->numparams=LoadByte(S);
f->is_vararg=LoadByte(S); f->is_vararg=LoadByte(S);
f->maxstacksize=LoadByte(S); f->maxstacksize=LoadByte(S);
LoadCode(S,f); LoadCode(S,f);
LoadConstants(S,f); LoadConstants(S,f);
LoadUpvalues(S,f);
LoadDebug(S,f); LoadDebug(S,f);
IF (!luaG_checkcode(f), "bad code");
S->L->top--; S->L->top--;
S->L->nCcalls--;
return f; return f;
} }
/* the code below must be consistent with the code in luaU_header */
#define N0 LUAC_HEADERSIZE
#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char))
#define N2 N1+2
#define N3 N2+6
static void LoadHeader(LoadState* S) static void LoadHeader(LoadState* S)
{ {
char h[LUAC_HEADERSIZE]; lu_byte h[LUAC_HEADERSIZE];
char s[LUAC_HEADERSIZE]; lu_byte s[LUAC_HEADERSIZE];
luaU_header(h); luaU_header(h);
LoadBlock(S,s,LUAC_HEADERSIZE); memcpy(s,h,sizeof(char)); /* first char already read */
IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char));
if (memcmp(h,s,N0)==0) return;
if (memcmp(h,s,N1)!=0) error(S,"not a");
if (memcmp(h,s,N2)!=0) error(S,"version mismatch in");
if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted");
} }
/* /*
@ -205,23 +215,30 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
S.Z=Z; S.Z=Z;
S.b=buff; S.b=buff;
LoadHeader(&S); LoadHeader(&S);
return LoadFunction(&S,luaS_newliteral(L,"=?")); return luai_verifycode(L,buff,LoadFunction(&S));
} }
#define MYINT(s) (s[0]-'0')
#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)
#define FORMAT 0 /* this is the official format */
/* /*
* make header * make header for precompiled chunks
* if you change the code below be sure to update LoadHeader and FORMAT above
* and LUAC_HEADERSIZE in lundump.h
*/ */
void luaU_header (char* h) void luaU_header (lu_byte* h)
{ {
int x=1; int x=1;
memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char));
h+=sizeof(LUA_SIGNATURE)-1; h+=sizeof(LUA_SIGNATURE)-sizeof(char);
*h++=(char)LUAC_VERSION; *h++=cast_byte(VERSION);
*h++=(char)LUAC_FORMAT; *h++=cast_byte(FORMAT);
*h++=(char)*(char*)&x; /* endianness */ *h++=cast_byte(*(char*)&x); /* endianness */
*h++=(char)sizeof(int); *h++=cast_byte(sizeof(int));
*h++=(char)sizeof(size_t); *h++=cast_byte(sizeof(size_t));
*h++=(char)sizeof(Instruction); *h++=cast_byte(sizeof(Instruction));
*h++=(char)sizeof(lua_Number); *h++=cast_byte(sizeof(lua_Number));
*h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */
memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char));
} }

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/* /*
** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lzio.c,v 1.34 2011/07/15 12:35:32 roberto Exp $
** a generic input stream interface ** a generic input stream interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -25,23 +25,11 @@ int luaZ_fill (ZIO *z) {
lua_unlock(L); lua_unlock(L);
buff = z->reader(L, z->data, &size); buff = z->reader(L, z->data, &size);
lua_lock(L); lua_lock(L);
if (buff == NULL || size == 0) return EOZ; if (buff == NULL || size == 0)
z->n = size - 1; return EOZ;
z->n = size - 1; /* discount char being returned */
z->p = buff; z->p = buff;
return char2int(*(z->p++)); return cast_uchar(*(z->p++));
}
int luaZ_lookahead (ZIO *z) {
if (z->n == 0) {
if (luaZ_fill(z) == EOZ)
return EOZ;
else {
z->n++; /* luaZ_fill removed first byte; put back it */
z->p--;
}
}
return char2int(*z->p);
} }
@ -58,8 +46,14 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
size_t luaZ_read (ZIO *z, void *b, size_t n) { size_t luaZ_read (ZIO *z, void *b, size_t n) {
while (n) { while (n) {
size_t m; size_t m;
if (luaZ_lookahead(z) == EOZ) if (z->n == 0) { /* no bytes in buffer? */
return n; /* return number of missing bytes */ if (luaZ_fill(z) == EOZ) /* try to read more */
return n; /* no more input; return number of missing bytes */
else {
z->n++; /* luaZ_fill consumed first byte; put it back */
z->p--;
}
}
m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
memcpy(b, z->p, m); memcpy(b, z->p, m);
z->n -= m; z->n -= m;

@ -1,227 +0,0 @@
/*
** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdio.h>
#define luac_c
#define LUA_CORE
#include "ldebug.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lundump.h"
#define PrintFunction luaU_print
#define Sizeof(x) ((int)sizeof(x))
#define VOID(p) ((const void*)(p))
static void PrintString(const TString* ts)
{
const char* s=getstr(ts);
size_t i,n=ts->tsv.len;
putchar('"');
for (i=0; i<n; i++)
{
int c=s[i];
switch (c)
{
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
case '\a': printf("\\a"); break;
case '\b': printf("\\b"); break;
case '\f': printf("\\f"); break;
case '\n': printf("\\n"); break;
case '\r': printf("\\r"); break;
case '\t': printf("\\t"); break;
case '\v': printf("\\v"); break;
default: if (isprint((unsigned char)c))
putchar(c);
else
printf("\\%03u",(unsigned char)c);
}
}
putchar('"');
}
static void PrintConstant(const Proto* f, int i)
{
const TValue* o=&f->k[i];
switch (ttype(o))
{
case LUA_TNIL:
printf("nil");
break;
case LUA_TBOOLEAN:
printf(bvalue(o) ? "true" : "false");
break;
case LUA_TNUMBER:
printf(LUA_NUMBER_FMT,nvalue(o));
break;
case LUA_TSTRING:
PrintString(rawtsvalue(o));
break;
default: /* cannot happen */
printf("? type=%d",ttype(o));
break;
}
}
static void PrintCode(const Proto* f)
{
const Instruction* code=f->code;
int pc,n=f->sizecode;
for (pc=0; pc<n; pc++)
{
Instruction i=code[pc];
OpCode o=GET_OPCODE(i);
int a=GETARG_A(i);
int b=GETARG_B(i);
int c=GETARG_C(i);
int bx=GETARG_Bx(i);
int sbx=GETARG_sBx(i);
int line=getline(f,pc);
printf("\t%d\t",pc+1);
if (line>0) printf("[%d]\t",line); else printf("[-]\t");
printf("%-9s\t",luaP_opnames[o]);
switch (getOpMode(o))
{
case iABC:
printf("%d",a);
if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
break;
case iABx:
if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
break;
case iAsBx:
if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
break;
}
switch (o)
{
case OP_LOADK:
printf("\t; "); PrintConstant(f,bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
break;
case OP_GETGLOBAL:
case OP_SETGLOBAL:
printf("\t; %s",svalue(&f->k[bx]));
break;
case OP_GETTABLE:
case OP_SELF:
if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
break;
case OP_SETTABLE:
case OP_ADD:
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_POW:
case OP_EQ:
case OP_LT:
case OP_LE:
if (ISK(b) || ISK(c))
{
printf("\t; ");
if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
printf(" ");
if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
}
break;
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
printf("\t; to %d",sbx+pc+2);
break;
case OP_CLOSURE:
printf("\t; %p",VOID(f->p[bx]));
break;
case OP_SETLIST:
if (c==0) printf("\t; %d",(int)code[++pc]);
else printf("\t; %d",c);
break;
default:
break;
}
printf("\n");
}
}
#define SS(x) (x==1)?"":"s"
#define S(x) x,SS(x)
static void PrintHeader(const Proto* f)
{
const char* s=getstr(f->source);
if (*s=='@' || *s=='=')
s++;
else if (*s==LUA_SIGNATURE[0])
s="(bstring)";
else
s="(string)";
printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n",
(f->linedefined==0)?"main":"function",s,
f->linedefined,f->lastlinedefined,
S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
f->numparams,f->is_vararg?"+":"",SS(f->numparams),
S(f->maxstacksize),S(f->nups));
printf("%d local%s, %d constant%s, %d function%s\n",
S(f->sizelocvars),S(f->sizek),S(f->sizep));
}
static void PrintConstants(const Proto* f)
{
int i,n=f->sizek;
printf("constants (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t",i+1);
PrintConstant(f,i);
printf("\n");
}
}
static void PrintLocals(const Proto* f)
{
int i,n=f->sizelocvars;
printf("locals (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
printf("\t%d\t%s\t%d\t%d\n",
i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
}
}
static void PrintUpvalues(const Proto* f)
{
int i,n=f->sizeupvalues;
printf("upvalues (%d) for %p:\n",n,VOID(f));
if (f->upvalues==NULL) return;
for (i=0; i<n; i++)
{
printf("\t%d\t%s\n",i,getstr(f->upvalues[i]));
}
}
void PrintFunction(const Proto* f, int full)
{
int i,n=f->sizep;
PrintHeader(f);
PrintCode(f);
if (full)
{
PrintConstants(f);
PrintLocals(f);
PrintUpvalues(f);
}
for (i=0; i<n; i++) PrintFunction(f->p[i],full);
}

@ -643,7 +643,7 @@ static int meta_struct_next(lua_State *state)
{ {
if (lua_gettop(state) < 2) lua_pushnil(state); if (lua_gettop(state) < 2) lua_pushnil(state);
int len = lua_objlen(state, UPVAL_FIELDTABLE); int len = lua_rawlen(state, UPVAL_FIELDTABLE);
int idx = cur_iter_index(state, len+1, 2, 0); int idx = cur_iter_index(state, len+1, 2, 0);
if (idx == len) if (idx == len)
return 0; return 0;
@ -1053,7 +1053,7 @@ static void IndexFields(lua_State *state, int base, struct_identity *pstruct)
if (!fields) if (!fields)
return; return;
int cnt = lua_objlen(state, base+3); // field iter table int cnt = lua_rawlen(state, base+3); // field iter table
for (int i = 0; fields[i].mode != struct_field_info::END; ++i) for (int i = 0; fields[i].mode != struct_field_info::END; ++i)
{ {

@ -695,7 +695,7 @@ static int meta_assign(lua_State *state)
/* /*
* no assign && nil or missing resize field => 1-based lua array * no assign && nil or missing resize field => 1-based lua array
*/ */
int size = lua_objlen(state, 2); int size = lua_rawlen(state, 2);
lua_pop(state, 1); lua_pop(state, 1);
invoke_resize(state, 1, size); invoke_resize(state, 1, size);
@ -1242,7 +1242,7 @@ static void RenderTypeChildren(lua_State *state, const std::vector<compound_iden
} }
} }
static void DoAttach(lua_State *state) static int DoAttach(lua_State *state)
{ {
int base = lua_gettop(state); int base = lua_gettop(state);
@ -1287,8 +1287,6 @@ static void DoAttach(lua_State *state)
lua_pushcclosure(state, meta_delete, 1); lua_pushcclosure(state, meta_delete, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME);
luaL_register(state, "df", no_functions);
{ {
// Assign df a metatable with read-only contents // Assign df a metatable with read-only contents
lua_newtable(state); lua_newtable(state);
@ -1312,12 +1310,10 @@ static void DoAttach(lua_State *state)
lua_pushlightuserdata(state, NULL); lua_pushlightuserdata(state, NULL);
lua_setglobal(state, "NULL"); lua_setglobal(state, "NULL");
freeze_table(state, true, "df"); freeze_table(state, false, "df");
lua_remove(state, -2);
lua_setmetatable(state, -2);
} }
lua_pop(state, 1); return 1;
} }
/** /**
@ -1327,7 +1323,10 @@ static void DoAttach(lua_State *state)
void DFHack::AttachDFGlobals(lua_State *state) void DFHack::AttachDFGlobals(lua_State *state)
{ {
if (luaL_newmetatable(state, DFHACK_TYPETABLE_NAME)) if (luaL_newmetatable(state, DFHACK_TYPETABLE_NAME))
DoAttach(state); {
luaL_requiref(state, "df", DoAttach, 1);
lua_pop(state, 1);
}
lua_pop(state, 1); lua_pop(state, 1);
} }

@ -31,8 +31,8 @@ namespace lua
//dumps lua function trace, useless unless called from lua. //dumps lua function trace, useless unless called from lua.
string DebugDump(lua::state &L); string DebugDump(lua::state &L);
//register functions, first registers into global scope, second into current table //register functions, first registers into global scope, second into current table
void RegFunctions(lua::state &L,luaL_reg const *arr); void RegFunctions(lua::state &L,luaL_Reg const *arr);
void RegFunctionsLocal(lua::state &L,luaL_reg const *arr); void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr);
} }

@ -139,9 +139,8 @@ public:
// store method table in globals so that // store method table in globals so that
// scripts can add functions written in Lua. // scripts can add functions written in Lua.
lua_pushstring(L, T::className);
lua_pushvalue(L, methods); lua_pushvalue(L, methods);
lua_settable(L, LUA_GLOBALSINDEX); lua_setglobal(L, T::className);
lua_pushliteral(L, "__metatable"); lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methods); lua_pushvalue(L, methods);
@ -212,7 +211,7 @@ public:
userdataType *ud = userdataType *ud =
static_cast<userdataType*>(luaL_checkudata(L, narg, T::className)); //TODO FIX THIs.. static_cast<userdataType*>(luaL_checkudata(L, narg, T::className)); //TODO FIX THIs..
//(lua_touserdata(L, narg));// //(lua_touserdata(L, narg));//
if(!ud) luaL_typerror(L, narg, T::className); if(!ud) luaL_error(L, "Bad argument %d: expected type %s", narg, T::className);
return ud->pT; // pointer to T object return ud->pT; // pointer to T object
} }
protected: protected:

@ -23,7 +23,7 @@ int lua_Ver_Lua(lua_State *L)
} }
static const struct luaL_reg lua_basic_lib [] = static const struct luaL_Reg lua_basic_lib [] =
{ {
{"getluaver", lua_Ver_Lua}, {"getluaver", lua_Ver_Lua},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
@ -34,9 +34,9 @@ void lua::RegBasics(lua::state &L)
RegFunctions(L,lua_basic_lib); RegFunctions(L,lua_basic_lib);
} }
void lua::RegFunctions(lua::state &L,luaL_reg const*arr) void lua::RegFunctions(lua::state &L,luaL_Reg const*arr)
{ {
luaL_reg const *cur=arr; luaL_Reg const *cur=arr;
while(cur->name!=NULL) while(cur->name!=NULL)
{ {
lua_pushcfunction(L, cur->func); lua_pushcfunction(L, cur->func);
@ -45,9 +45,9 @@ void lua::RegFunctions(lua::state &L,luaL_reg const*arr)
cur++; cur++;
} }
} }
void lua::RegFunctionsLocal(lua::state &L,luaL_reg const*arr) void lua::RegFunctionsLocal(lua::state &L,luaL_Reg const*arr)
{ {
luaL_reg const *cur=arr; luaL_Reg const *cur=arr;
while(cur->name!=NULL) while(cur->name!=NULL)
{ {
lua_pushcfunction(L, cur->func); lua_pushcfunction(L, cur->func);

@ -215,7 +215,11 @@ namespace lua
template<> template<>
std::string state::as(std::string default_value, int index) { std::string state::as(std::string default_value, int index) {
if (lua_isstring(L, index)) if (lua_isstring(L, index))
return std::string(lua_tostring(L, index), lua_strlen(L, index)); {
size_t len;
const char *str = lua_tolstring(L, index, &len);
return std::string(str, len);
}
else else
return default_value; return default_value;
} }
@ -674,7 +678,7 @@ namespace lua
* @returns the length of the indicated value * @returns the length of the indicated value
*/ */
size_t state::objlen(int index) { size_t state::objlen(int index) {
return lua_objlen(L, index); return lua_rawlen(L, index);
} }
/** Get the value at index as a bool. /** Get the value at index as a bool.
@ -715,7 +719,11 @@ namespace lua
template<> template<>
state& state::to(std::string& string, int index) { state& state::to(std::string& string, int index) {
if (lua_isstring(L, index)) if (lua_isstring(L, index))
string.replace(0, std::string::npos, lua_tostring(L, index), lua_strlen(L, index)); {
size_t len;
const char *str = lua_tolstring(L, index, &len);
string.replace(0, std::string::npos, str, len);
}
else else
throw bad_conversion("Cannot convert value to string"); throw bad_conversion("Cannot convert value to string");
@ -755,7 +763,11 @@ namespace lua
template<> template<>
std::string state::as(int index) { std::string state::as(int index) {
if (lua_isstring(L, index)) if (lua_isstring(L, index))
return std::string(lua_tostring(L, index), lua_strlen(L, index)); {
size_t len;
const char *str = lua_tolstring(L, index, &len);
return std::string(str, len);
}
else else
throw bad_conversion("Cannot convert value to string"); throw bad_conversion("Cannot convert value to string");
} }