aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-10-02 17:31:17 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-10-02 17:31:17 -0300
commitb97fb932ece7872a8d1dd6c0a2c88f3ce33e9741 (patch)
treed9e60044a35ad3fdf761f28506be08205081ebd7
parentc7cf92e6f318823406e40ad6016e5ccb4e041c72 (diff)
downloadlua-b97fb932ece7872a8d1dd6c0a2c88f3ce33e9741.tar.gz
lua-b97fb932ece7872a8d1dd6c0a2c88f3ce33e9741.tar.bz2
lua-b97fb932ece7872a8d1dd6c0a2c88f3ce33e9741.zip
Lua kernel does not use malloc/free functions.
-rw-r--r--lauxlib.c19
-rw-r--r--lauxlib.h4
-rw-r--r--lmem.c65
-rw-r--r--lstate.c51
-rw-r--r--lstate.h4
-rw-r--r--ltests.c47
-rw-r--r--ltests.h20
-rw-r--r--lua.h11
8 files changed, 116 insertions, 105 deletions
diff --git a/lauxlib.c b/lauxlib.c
index 60e28646..b90bf458 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.102 2003/05/16 18:59:08 roberto Exp roberto $ 2** $Id: lauxlib.c,v 1.103 2003/10/01 16:50:53 roberto Exp roberto $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -9,6 +9,7 @@
9#include <errno.h> 9#include <errno.h>
10#include <stdarg.h> 10#include <stdarg.h>
11#include <stdio.h> 11#include <stdio.h>
12#include <stdlib.h>
12#include <string.h> 13#include <string.h>
13 14
14 15
@@ -558,6 +559,22 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
558/* }====================================================== */ 559/* }====================================================== */
559 560
560 561
562static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
563 (void)ud;
564 if (nsize == 0) {
565 free(ptr);
566 return NULL;
567 }
568 else
569 return realloc(ptr, nsize);
570}
571
572
573LUALIB_API lua_State *luaL_newstate (void) {
574 return lua_newstate(l_alloc, NULL);
575}
576
577
561/* 578/*
562** {====================================================== 579** {======================================================
563** compatibility code 580** compatibility code
diff --git a/lauxlib.h b/lauxlib.h
index 25f3c441..a04c55e7 100644
--- a/lauxlib.h
+++ b/lauxlib.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.h,v 1.59 2003/03/18 12:25:32 roberto Exp roberto $ 2** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp roberto $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -62,6 +62,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename);
62LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, 62LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz,
63 const char *name); 63 const char *name);
64 64
65LUALIB_API lua_State *(luaL_newstate) (void);
66
65 67
66 68
67/* 69/*
diff --git a/lmem.c b/lmem.c
index 8b89b764..39e19647 100644
--- a/lmem.c
+++ b/lmem.c
@@ -1,11 +1,11 @@
1/* 1/*
2** $Id: lmem.c,v 1.60 2002/11/21 14:14:42 roberto Exp roberto $ 2** $Id: lmem.c,v 1.61 2002/12/04 17:38:31 roberto Exp roberto $
3** Interface to Memory Manager 3** Interface to Memory Manager
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
6 6
7 7
8#include <stdlib.h> 8#include <stddef.h>
9 9
10#define lmem_c 10#define lmem_c
11 11
@@ -20,21 +20,23 @@
20 20
21 21
22/* 22/*
23** definition for realloc function. It must assure that l_realloc(NULL, 23** About the realloc function:
24** 0, x) allocates a new block (ANSI C assures that). (`os' is the old 24** void * realloc (void *ud, void *ptr, size_t osize, size_t nsize);
25** block size; some allocators may use that.) 25** (`osize' is the old size, `nsize' is the new size)
26**
27** Lua ensures that (ptr == NULL) iff (osize == 0).
28**
29** * realloc(ud, NULL, 0, x) creates a new block of size `x'
30**
31** * realloc(ud, p, x, 0) frees the block `p'
32** (in this specific case, realloc must return NULL).
33** particularly, realloc(ud, NULL, 0, 0) does nothing
34** (which is equivalent to free(NULL) in ANSI C)
35**
36** realloc returns NULL if it cannot create or reallocate the area
37** (any reallocation to an equal or smaller size cannot fail!)
26*/ 38*/
27#ifndef l_realloc
28#define l_realloc(b,os,s) realloc(b,s)
29#endif
30 39
31/*
32** definition for free function. (`os' is the old block size; some
33** allocators may use that.)
34*/
35#ifndef l_free
36#define l_free(b,os) free(b)
37#endif
38 40
39 41
40#define MINSIZEARRAY 4 42#define MINSIZEARRAY 4
@@ -62,30 +64,17 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
62/* 64/*
63** generic allocation routine. 65** generic allocation routine.
64*/ 66*/
65void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) { 67void *luaM_realloc (lua_State *L, void *block, lu_mem osize, lu_mem nsize) {
66 lua_assert((oldsize == 0) == (block == NULL)); 68 global_State *g = G(L);
67 if (size == 0) { 69 lua_assert((osize == 0) == (block == NULL));
68 if (block != NULL) { 70 if (nsize >= MAX_SIZET)
69 l_free(block, oldsize);
70 block = NULL;
71 }
72 else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */
73 }
74 else if (size >= MAX_SIZET)
75 luaG_runerror(L, "memory allocation error: block too big"); 71 luaG_runerror(L, "memory allocation error: block too big");
76 else { 72 block = (*g->realloc)(g->ud, block, osize, nsize);
77 block = l_realloc(block, oldsize, size); 73 if (block == NULL && nsize > 0)
78 if (block == NULL) { 74 luaD_throw(L, LUA_ERRMEM);
79 if (L) 75 lua_assert((nsize == 0) == (block == NULL));
80 luaD_throw(L, LUA_ERRMEM); 76 g->nblocks -= osize;
81 else return NULL; /* error before creating state! */ 77 g->nblocks += nsize;
82 }
83 }
84 if (L) {
85 lua_assert(G(L) != NULL && G(L)->nblocks > 0);
86 G(L)->nblocks -= oldsize;
87 G(L)->nblocks += size;
88 }
89 return block; 78 return block;
90} 79}
91 80
diff --git a/lstate.c b/lstate.c
index dd80a7e1..12acb3eb 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,11 +1,11 @@
1/* 1/*
2** $Id: lstate.c,v 1.125 2003/07/16 20:51:47 roberto Exp roberto $ 2** $Id: lstate.c,v 1.126 2003/09/04 20:19:07 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
6 6
7 7
8#include <stdlib.h> 8#include <stddef.h>
9 9
10#define lstate_c 10#define lstate_c
11 11
@@ -34,6 +34,11 @@ union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
34#endif 34#endif
35 35
36 36
37#define state_size(x) (sizeof(x) + EXTRASPACE)
38#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + EXTRASPACE))
39#define fromstate(l) (cast(lu_byte *, (l)) - EXTRASPACE)
40
41
37/* 42/*
38** Main thread combines a thread state and the global state 43** Main thread combines a thread state and the global state
39*/ 44*/
@@ -44,23 +49,6 @@ typedef struct LG {
44 49
45 50
46 51
47
48static lua_State *mallocstate (lua_State *L, size_t size) {
49 lu_byte *block = (lu_byte *)luaM_malloc(L, size + EXTRASPACE);
50 if (block == NULL) return NULL;
51 else {
52 block += EXTRASPACE;
53 return cast(lua_State *, block);
54 }
55}
56
57
58static void freestate (lua_State *L, lua_State *L1, size_t size) {
59 luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
60 size + EXTRASPACE);
61}
62
63
64static void stack_init (lua_State *L1, lua_State *L) { 52static void stack_init (lua_State *L1, lua_State *L) {
65 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject); 53 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
66 L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; 54 L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
@@ -122,20 +110,21 @@ static void preinit_state (lua_State *L) {
122 110
123 111
124static void close_state (lua_State *L) { 112static void close_state (lua_State *L) {
113 global_State *g = G(L);
125 luaF_close(L, L->stack); /* close all upvalues for this thread */ 114 luaF_close(L, L->stack); /* close all upvalues for this thread */
126 luaC_sweep(L, 1); /* collect all elements */ 115 luaC_sweep(L, 1); /* collect all elements */
127 lua_assert(G(L)->rootgc == NULL); 116 lua_assert(g->rootgc == NULL);
128 lua_assert(G(L)->rootudata == NULL); 117 lua_assert(g->rootudata == NULL);
129 luaS_freeall(L); 118 luaS_freeall(L);
130 luaZ_freebuffer(L, &G(L)->buff); 119 luaZ_freebuffer(L, &g->buff);
131 freestack(L, L); 120 freestack(L, L);
132 lua_assert(G(L)->nblocks == sizeof(LG)); 121 lua_assert(g->nblocks == sizeof(LG));
133 freestate(NULL, L, sizeof(LG)); 122 (*g->realloc)(g->ud, fromstate(L), state_size(LG), 0);
134} 123}
135 124
136 125
137lua_State *luaE_newthread (lua_State *L) { 126lua_State *luaE_newthread (lua_State *L) {
138 lua_State *L1 = mallocstate(L, sizeof(lua_State)); 127 lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
139 luaC_link(L, valtogco(L1), LUA_TTHREAD); 128 luaC_link(L, valtogco(L1), LUA_TTHREAD);
140 preinit_state(L1); 129 preinit_state(L1);
141 L1->l_G = L->l_G; 130 L1->l_G = L->l_G;
@@ -149,20 +138,24 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
149 luaF_close(L1, L1->stack); /* close all upvalues for this thread */ 138 luaF_close(L1, L1->stack); /* close all upvalues for this thread */
150 lua_assert(L1->openupval == NULL); 139 lua_assert(L1->openupval == NULL);
151 freestack(L, L1); 140 freestack(L, L1);
152 freestate(L, L1, sizeof(lua_State)); 141 luaM_free(L, fromstate(L1), state_size(lua_State));
153} 142}
154 143
155 144
156LUA_API lua_State *lua_open (void) { 145LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
157 lua_State *L = mallocstate(NULL, sizeof(LG)); 146 lua_State *L;
158 global_State *g; 147 global_State *g;
159 if (L == NULL) return NULL; 148 void *l = (*f)(ud, NULL, 0, state_size(LG));
149 if (l == NULL) return NULL;
150 L = tostate(l);
160 g = &((LG *)L)->g; 151 g = &((LG *)L)->g;
161 L->tt = LUA_TTHREAD; 152 L->tt = LUA_TTHREAD;
162 L->marked = 0; 153 L->marked = 0;
163 L->next = L->gclist = NULL; 154 L->next = L->gclist = NULL;
164 preinit_state(L); 155 preinit_state(L);
165 L->l_G = g; 156 L->l_G = g;
157 g->realloc = f;
158 g->ud = ud;
166 g->mainthread = L; 159 g->mainthread = L;
167 g->GCthreshold = 0; /* mark it as unfinished state */ 160 g->GCthreshold = 0; /* mark it as unfinished state */
168 g->strt.size = 0; 161 g->strt.size = 0;
diff --git a/lstate.h b/lstate.h
index 009ea790..94e9bbfa 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 1.110 2003/04/28 19:26:16 roberto Exp roberto $ 2** $Id: lstate.h,v 1.111 2003/07/16 20:49:02 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -101,6 +101,8 @@ typedef struct global_State {
101 GCObject *rootgc; /* list of (almost) all collectable objects */ 101 GCObject *rootgc; /* list of (almost) all collectable objects */
102 GCObject *rootudata; /* (separated) list of all userdata */ 102 GCObject *rootudata; /* (separated) list of all userdata */
103 GCObject *tmudata; /* list of userdata to be GC */ 103 GCObject *tmudata; /* list of userdata to be GC */
104 lua_Alloc realloc; /* function to reallocate memory */
105 void *ud; /* auxiliary data to `realloc' */
104 Mbuffer buff; /* temporary buffer for string concatentation */ 106 Mbuffer buff; /* temporary buffer for string concatentation */
105 lu_mem GCthreshold; 107 lu_mem GCthreshold;
106 lu_mem nblocks; /* number of `bytes' currently allocated */ 108 lu_mem nblocks; /* number of `bytes' currently allocated */
diff --git a/ltests.c b/ltests.c
index a659d3af..2c0f5869 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.162 2003/07/09 12:08:43 roberto Exp roberto $ 2** $Id: ltests.c,v 1.163 2003/07/29 19:26:34 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -80,10 +80,8 @@ static void setnameval (lua_State *L, const char *name, int val) {
80#define fillmem(mem,size) /* empty */ 80#define fillmem(mem,size) /* empty */
81#endif 81#endif
82 82
83unsigned long memdebug_numblocks = 0; 83
84unsigned long memdebug_total = 0; 84Memcontrol memcontrol = {0L, 0L, 0L, ULONG_MAX};
85unsigned long memdebug_maxmem = 0;
86unsigned long memdebug_memlimit = ULONG_MAX;
87 85
88 86
89static void *checkblock (void *block, size_t size) { 87static void *checkblock (void *block, size_t size) {
@@ -95,27 +93,26 @@ static void *checkblock (void *block, size_t size) {
95} 93}
96 94
97 95
98static void freeblock (void *block, size_t size) { 96static void freeblock (Memcontrol *mc, void *block, size_t size) {
99 if (block) { 97 if (block) {
100 lua_assert(checkblocksize(block, size)); 98 lua_assert(checkblocksize(block, size));
101 block = checkblock(block, size); 99 block = checkblock(block, size);
102 fillmem(block, size+HEADER+MARKSIZE); /* erase block */ 100 fillmem(block, size+HEADER+MARKSIZE); /* erase block */
103 free(block); /* free original block */ 101 free(block); /* free original block */
104 memdebug_numblocks--; 102 mc->numblocks--;
105 memdebug_total -= size; 103 mc->total -= size;
106 } 104 }
107} 105}
108 106
109 107
110void *debug_realloc (void *block, size_t oldsize, size_t size) { 108void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
109 Memcontrol *mc = cast(Memcontrol *, ud);
111 lua_assert(oldsize == 0 || checkblocksize(block, oldsize)); 110 lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
112 /* ISO does not specify what realloc(NULL, 0) does */
113 lua_assert(block != NULL || size > 0);
114 if (size == 0) { 111 if (size == 0) {
115 freeblock(block, oldsize); 112 freeblock(mc, block, oldsize);
116 return NULL; 113 return NULL;
117 } 114 }
118 else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit) 115 else if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
119 return NULL; /* to test memory allocation errors */ 116 return NULL; /* to test memory allocation errors */
120 else { 117 else {
121 void *newblock; 118 void *newblock;
@@ -127,14 +124,14 @@ void *debug_realloc (void *block, size_t oldsize, size_t size) {
127 if (newblock == NULL) return NULL; 124 if (newblock == NULL) return NULL;
128 if (block) { 125 if (block) {
129 memcpy(cast(char *, newblock)+HEADER, block, commonsize); 126 memcpy(cast(char *, newblock)+HEADER, block, commonsize);
130 freeblock(block, oldsize); /* erase (and check) old copy */ 127 freeblock(mc, block, oldsize); /* erase (and check) old copy */
131 } 128 }
132 /* initialize new part of the block with something `weird' */ 129 /* initialize new part of the block with something `weird' */
133 fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize); 130 fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
134 memdebug_total += size; 131 mc->total += size;
135 if (memdebug_total > memdebug_maxmem) 132 if (mc->total > mc->maxmem)
136 memdebug_maxmem = memdebug_total; 133 mc->maxmem = mc->total;
137 memdebug_numblocks++; 134 mc->numblocks++;
138 setsize(newblock, size); 135 setsize(newblock, size);
139 for (i=0;i<MARKSIZE;i++) 136 for (i=0;i<MARKSIZE;i++)
140 *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i); 137 *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
@@ -260,13 +257,13 @@ static int setgcthreshold (lua_State *L) {
260 257
261static int mem_query (lua_State *L) { 258static int mem_query (lua_State *L) {
262 if (lua_isnone(L, 1)) { 259 if (lua_isnone(L, 1)) {
263 lua_pushintegral(L, memdebug_total); 260 lua_pushintegral(L, memcontrol.total);
264 lua_pushintegral(L, memdebug_numblocks); 261 lua_pushintegral(L, memcontrol.numblocks);
265 lua_pushintegral(L, memdebug_maxmem); 262 lua_pushintegral(L, memcontrol.maxmem);
266 return 3; 263 return 3;
267 } 264 }
268 else { 265 else {
269 memdebug_memlimit = luaL_checkint(L, 1); 266 memcontrol.memlimit = luaL_checkint(L, 1);
270 return 0; 267 return 0;
271 } 268 }
272} 269}
@@ -830,8 +827,8 @@ static const struct luaL_reg tests_funcs[] = {
830static void fim (void) { 827static void fim (void) {
831 if (!islocked) 828 if (!islocked)
832 lua_close(lua_state); 829 lua_close(lua_state);
833 lua_assert(memdebug_numblocks == 0); 830 lua_assert(memcontrol.numblocks == 0);
834 lua_assert(memdebug_total == 0); 831 lua_assert(memcontrol.total == 0);
835} 832}
836 833
837 834
@@ -856,7 +853,7 @@ int luaB_opentests (lua_State *L) {
856int main (int argc, char *argv[]) { 853int main (int argc, char *argv[]) {
857 char *limit = getenv("MEMLIMIT"); 854 char *limit = getenv("MEMLIMIT");
858 if (limit) 855 if (limit)
859 memdebug_memlimit = strtoul(limit, NULL, 10); 856 memcontrol.memlimit = strtoul(limit, NULL, 10);
860 l_main(argc, argv); 857 l_main(argc, argv);
861 return 0; 858 return 0;
862} 859}
diff --git a/ltests.h b/ltests.h
index 44242781..0eb64bcf 100644
--- a/ltests.h
+++ b/ltests.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.h,v 1.19 2002/11/19 17:42:32 roberto Exp roberto $ 2** $Id: ltests.h,v 1.20 2002/12/04 17:29:05 roberto Exp roberto $
3** Internal Header for Debugging of the Lua Implementation 3** Internal Header for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -27,16 +27,20 @@
27 27
28 28
29/* memory allocator control variables */ 29/* memory allocator control variables */
30extern unsigned long memdebug_numblocks; 30typedef struct Memcontrol {
31extern unsigned long memdebug_total; 31 unsigned long numblocks;
32extern unsigned long memdebug_maxmem; 32 unsigned long total;
33extern unsigned long memdebug_memlimit; 33 unsigned long maxmem;
34 unsigned long memlimit;
35} Memcontrol;
34 36
37extern Memcontrol memcontrol;
35 38
36#define l_realloc(b, os, s) debug_realloc(b, os, s) 39void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
37#define l_free(b, os) debug_realloc(b, os, 0)
38 40
39void *debug_realloc (void *block, size_t oldsize, size_t size); 41#ifdef lua_c
42#define luaL_newstate() lua_newstate(debug_realloc, &memcontrol)
43#endif
40 44
41 45
42 46
diff --git a/lua.h b/lua.h
index 8285c555..abea10af 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.177 2003/05/15 12:20:04 roberto Exp roberto $ 2** $Id: lua.h,v 1.178 2003/07/07 13:30:57 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil 4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
5** http://www.lua.org mailto:info@lua.org 5** http://www.lua.org mailto:info@lua.org
@@ -57,6 +57,12 @@ typedef int (*lua_Chunkwriter) (lua_State *L, const void* p,
57 57
58 58
59/* 59/*
60** prototype for memory-allocation functions
61*/
62typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
63
64
65/*
60** basic types 66** basic types
61*/ 67*/
62#define LUA_TNONE (-1) 68#define LUA_TNONE (-1)
@@ -101,7 +107,7 @@ typedef LUA_NUMBER lua_Number;
101/* 107/*
102** state manipulation 108** state manipulation
103*/ 109*/
104LUA_API lua_State *lua_open (void); 110LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud);
105LUA_API void lua_close (lua_State *L); 111LUA_API void lua_close (lua_State *L);
106LUA_API lua_State *lua_newthread (lua_State *L); 112LUA_API lua_State *lua_newthread (lua_State *L);
107 113
@@ -261,6 +267,7 @@ LUA_API void lua_concat (lua_State *L, int n);
261** compatibility macros and functions 267** compatibility macros and functions
262*/ 268*/
263 269
270#define lua_open() luaL_newstate()
264 271
265#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) 272#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
266#define lua_setglobal(L,s) \ 273#define lua_setglobal(L,s) \