aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c45
-rw-r--r--lbaselib.c10
-rw-r--r--lcode.c6
-rw-r--r--ldblib.c16
-rw-r--r--lgc.c62
-rw-r--r--liolib.c94
-rw-r--r--lobject.h34
-rw-r--r--lstate.c12
-rw-r--r--lstate.h4
-rw-r--r--lstring.c72
-rw-r--r--lstring.h20
-rw-r--r--ltable.c4
-rw-r--r--ltests.c38
-rw-r--r--ltm.c6
-rw-r--r--ltm.h4
-rw-r--r--lua.c4
-rw-r--r--lua.h4
17 files changed, 215 insertions, 220 deletions
diff --git a/lapi.c b/lapi.c
index 36e0aef7..7f4c6e7f 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.141 2001/04/23 16:35:45 roberto Exp roberto $ 2** $Id: lapi.c,v 1.142 2001/06/05 18:17:01 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -284,8 +284,7 @@ LUA_API void *lua_touserdata (lua_State *L, int index) {
284 void *p; 284 void *p;
285 lua_lock(L); 285 lua_lock(L);
286 o = luaA_indexAcceptable(L, index); 286 o = luaA_indexAcceptable(L, index);
287 p = (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : 287 p = (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : uvalue(o)->value;
288 tsvalue(o)->u.d.value;
289 lua_unlock(L); 288 lua_unlock(L);
290 return p; 289 return p;
291} 290}
@@ -360,16 +359,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
360} 359}
361 360
362 361
363LUA_API int lua_pushuserdata (lua_State *L, void *u) {
364 int isnew;
365 lua_lock(L);
366 isnew = luaS_createudata(L, u, L->top);
367 api_incr_top(L);
368 lua_unlock(L);
369 return isnew;
370}
371
372
373 362
374/* 363/*
375** get functions (Lua -> stack) 364** get functions (Lua -> stack)
@@ -673,7 +662,7 @@ LUA_API void lua_settag (lua_State *L, int tag) {
673 hvalue(L->top-1)->htag = tag; 662 hvalue(L->top-1)->htag = tag;
674 break; 663 break;
675 case LUA_TUSERDATA: 664 case LUA_TUSERDATA:
676 tsvalue(L->top-1)->u.d.tag = tag; 665 uvalue(L->top-1)->tag = tag;
677 break; 666 break;
678 default: 667 default:
679 luaO_verror(L, l_s("cannot change the tag of a %.20s"), 668 luaO_verror(L, l_s("cannot change the tag of a %.20s"),
@@ -771,20 +760,34 @@ LUA_API void lua_concat (lua_State *L, int n) {
771} 760}
772 761
773 762
763static Udata *pushnewudata (lua_State *L, size_t size) {
764 Udata *u = luaS_newudata(L, size);
765 setuvalue(L->top, u);
766 api_incr_top(L);
767 return uvalue(L->top-1);
768}
769
770
774LUA_API void *lua_newuserdata (lua_State *L, size_t size) { 771LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
775 TString *ts; 772 Udata *u;
776 void *p; 773 void *p;
777 lua_lock(L); 774 lua_lock(L);
778 if (size == 0) size = 1; 775 u = pushnewudata(L, size);
779 ts = luaS_newudata(L, size, NULL); 776 p = u->value;
780 setuvalue(L->top, ts);
781 api_incr_top(L);
782 p = ts->u.d.value;
783 lua_unlock(L); 777 lua_unlock(L);
784 return p; 778 return p;
785} 779}
786 780
787 781
782LUA_API void lua_newuserdatabox (lua_State *L, void *p) {
783 Udata *u;
784 lua_lock(L);
785 u = pushnewudata(L, 0);
786 u->value = p;
787 lua_unlock(L);
788}
789
790
788LUA_API int lua_getweakmode (lua_State *L, int index) { 791LUA_API int lua_getweakmode (lua_State *L, int index) {
789 StkId t; 792 StkId t;
790 int mode; 793 int mode;
@@ -806,6 +809,7 @@ LUA_API void lua_setweakmode (lua_State *L, int mode) {
806 809
807 810
808 811
812#if 0
809/* 813/*
810** deprecated function 814** deprecated function
811*/ 815*/
@@ -819,3 +823,4 @@ LUA_API void lua_pushusertag (lua_State *L, void *u, int tag) {
819} 823}
820 } 824 }
821} 825}
826#endif
diff --git a/lbaselib.c b/lbaselib.c
index 78fd6795..2c41aae1 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.35 2001/04/23 16:35:45 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.36 2001/06/05 19:41:31 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -170,11 +170,11 @@ static int luaB_settag (lua_State *L) {
170} 170}
171 171
172static int luaB_weakmode (lua_State *L) { 172static int luaB_weakmode (lua_State *L) {
173 const char *mode = luaL_check_string(L, 2); 173 const l_char *mode = luaL_check_string(L, 2);
174 luaL_checktype(L, 1, LUA_TTABLE); 174 luaL_checktype(L, 1, LUA_TTABLE);
175 if (*mode == l_c('?')) { 175 if (*mode == l_c('?')) {
176 char buff[3]; 176 l_char buff[3];
177 char *s = buff; 177 l_char *s = buff;
178 int imode = lua_getweakmode(L, 1); 178 int imode = lua_getweakmode(L, 1);
179 if (imode & LUA_WEAK_KEY) *s++ = 'k'; 179 if (imode & LUA_WEAK_KEY) *s++ = 'k';
180 if (imode & LUA_WEAK_VALUE) *s++ = 'v'; 180 if (imode & LUA_WEAK_VALUE) *s++ = 'v';
@@ -300,7 +300,7 @@ static int passresults (lua_State *L, int status, int oldtop) {
300 if (nresults > 0) 300 if (nresults > 0)
301 return nresults; /* results are already on the stack */ 301 return nresults; /* results are already on the stack */
302 else { 302 else {
303 lua_pushuserdata(L, NULL); /* at least one result to signal no errors */ 303 lua_newuserdatabox(L, NULL); /* at least one result to signal no errors */
304 return 1; 304 return 1;
305 } 305 }
306 } 306 }
diff --git a/lcode.c b/lcode.c
index 2658e602..8c43084e 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 1.68 2001/04/23 16:35:45 roberto Exp roberto $ 2** $Id: lcode.c,v 1.69 2001/06/05 18:17:01 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -226,12 +226,12 @@ static int addk (FuncState *fs, TObject *k) {
226 226
227int luaK_stringk (FuncState *fs, TString *s) { 227int luaK_stringk (FuncState *fs, TString *s) {
228 Proto *f = fs->f; 228 Proto *f = fs->f;
229 int c = s->u.s.constindex; 229 int c = s->constindex;
230 if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) { 230 if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) {
231 TObject o; 231 TObject o;
232 setsvalue(&o, s); 232 setsvalue(&o, s);
233 c = addk(fs, &o); 233 c = addk(fs, &o);
234 s->u.s.constindex = c; /* hint for next time */ 234 s->constindex = c; /* hint for next time */
235 } 235 }
236 return c; 236 return c;
237} 237}
diff --git a/ldblib.c b/ldblib.c
index d5604f51..d3f0bca3 100644
--- a/ldblib.c
+++ b/ldblib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldblib.c,v 1.35 2001/03/07 18:09:25 roberto Exp roberto $ 2** $Id: ldblib.c,v 1.36 2001/03/26 14:31:49 roberto Exp roberto $
3** Interface from Lua to its debug API 3** Interface from Lua to its debug API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -111,15 +111,13 @@ static int setlocal (lua_State *L) {
111 111
112 112
113 113
114/* dummy variables (to define unique addresses) */ 114#define KEY_CALLHOOK l_s("luadblibCallhook")
115static const l_char key1[] = l_s("ab"); 115#define KEY_LINEHOOK l_s("luadblibLinehook")
116#define KEY_CALLHOOK ((void *)key1)
117#define KEY_LINEHOOK ((void *)(key1+1))
118 116
119 117
120static void hookf (lua_State *L, void *key) { 118static void hookf (lua_State *L, const l_char *key) {
121 lua_getregistry(L); 119 lua_getregistry(L);
122 lua_pushuserdata(L, key); 120 lua_pushstring(L, key);
123 lua_gettable(L, -2); 121 lua_gettable(L, -2);
124 if (lua_isfunction(L, -1)) { 122 if (lua_isfunction(L, -1)) {
125 lua_pushvalue(L, -3); /* original argument (below table and function) */ 123 lua_pushvalue(L, -3); /* original argument (below table and function) */
@@ -143,7 +141,7 @@ static void linef (lua_State *L, lua_Debug *ar) {
143} 141}
144 142
145 143
146static void sethook (lua_State *L, void *key, lua_Hook hook, 144static void sethook (lua_State *L, const l_char *key, lua_Hook hook,
147 lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) { 145 lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) {
148 lua_settop(L, 1); 146 lua_settop(L, 1);
149 if (lua_isnil(L, 1)) 147 if (lua_isnil(L, 1))
@@ -153,7 +151,7 @@ static void sethook (lua_State *L, void *key, lua_Hook hook,
153 else 151 else
154 luaL_argerror(L, 1, l_s("function expected")); 152 luaL_argerror(L, 1, l_s("function expected"));
155 lua_getregistry(L); 153 lua_getregistry(L);
156 lua_pushuserdata(L, key); 154 lua_pushstring(L, key);
157 lua_pushvalue(L, -1); /* dup key */ 155 lua_pushvalue(L, -1); /* dup key */
158 lua_gettable(L, -3); /* get old value */ 156 lua_gettable(L, -3); /* get old value */
159 lua_pushvalue(L, -2); /* key (again) */ 157 lua_pushvalue(L, -2); /* key (again) */
diff --git a/lgc.c b/lgc.c
index a82039dd..86b7d092 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.98 2001/06/05 18:17:01 roberto Exp roberto $ 2** $Id: lgc.c,v 1.99 2001/06/05 19:27:32 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -82,9 +82,12 @@ static void marktable (GCState *st, Hash *h) {
82 82
83static void markobject (GCState *st, TObject *o) { 83static void markobject (GCState *st, TObject *o) {
84 switch (ttype(o)) { 84 switch (ttype(o)) {
85 case LUA_TUSERDATA: case LUA_TSTRING: 85 case LUA_TSTRING:
86 strmark(tsvalue(o)); 86 strmark(tsvalue(o));
87 break; 87 break;
88 case LUA_TUSERDATA:
89 uvalue(o)->marked = 1;
90 break;
88 case LUA_TFUNCTION: 91 case LUA_TFUNCTION:
89 markclosure(st, clvalue(o)); 92 markclosure(st, clvalue(o));
90 break; 93 break;
@@ -190,8 +193,10 @@ static void markall (lua_State *L) {
190 193
191static int hasmark (const TObject *o) { 194static int hasmark (const TObject *o) {
192 switch (ttype(o)) { 195 switch (ttype(o)) {
193 case LUA_TSTRING: case LUA_TUSERDATA: 196 case LUA_TSTRING:
194 return tsvalue(o)->marked; 197 return tsvalue(o)->marked;
198 case LUA_TUSERDATA:
199 return uvalue(o)->marked;
195 case LUA_TTABLE: 200 case LUA_TTABLE:
196 return ismarked(hvalue(o)); 201 return ismarked(hvalue(o));
197 case LUA_TFUNCTION: 202 case LUA_TFUNCTION:
@@ -275,9 +280,21 @@ static void collecttable (lua_State *L) {
275} 280}
276 281
277 282
278static void checktab (lua_State *L, stringtable *tb) { 283static void collectudata (lua_State *L) {
279 if (tb->nuse < (ls_nstr)(tb->size/4) && tb->size > MINPOWER2) 284 Udata **p = &G(L)->rootudata;
280 luaS_resize(L, tb, tb->size/2); /* table is too big */ 285 Udata *next;
286 while ((next = *p) != NULL) {
287 if (next->marked) {
288 next->marked = 0; /* unmark */
289 p = &next->next;
290 }
291 else { /* collect */
292 int tag = next->tag;
293 *p = next->next;
294 next->next = G(L)->TMtable[tag].collected; /* chain udata */
295 G(L)->TMtable[tag].collected = next;
296 }
297 }
281} 298}
282 299
283 300
@@ -299,33 +316,12 @@ static void collectstrings (lua_State *L, int all) {
299 } 316 }
300 } 317 }
301 } 318 }
302 checktab(L, &G(L)->strt); 319 if (G(L)->strt.nuse < (ls_nstr)(G(L)->strt.size/4) &&
320 G(L)->strt.size > MINPOWER2)
321 luaS_resize(L, G(L)->strt.size/2); /* table is too big */
303} 322}
304 323
305 324
306static void collectudata (lua_State *L, int all) {
307 int i;
308 for (i=0; i<G(L)->udt.size; i++) { /* for each list */
309 TString **p = &G(L)->udt.hash[i];
310 TString *next;
311 while ((next = *p) != NULL) {
312 lua_assert(next->marked <= 1);
313 if (next->marked && !all) { /* preserve? */
314 next->marked = 0;
315 p = &next->nexthash;
316 }
317 else { /* collect */
318 int tag = next->u.d.tag;
319 *p = next->nexthash;
320 next->nexthash = G(L)->TMtable[tag].collected; /* chain udata */
321 G(L)->TMtable[tag].collected = next;
322 G(L)->udt.nuse--;
323 }
324 }
325 }
326 checktab(L, &G(L)->udt);
327}
328
329 325
330#define MINBUFFER 256 326#define MINBUFFER 256
331static void checkMbuffer (lua_State *L) { 327static void checkMbuffer (lua_State *L) {
@@ -356,10 +352,10 @@ static void callgcTMudata (lua_State *L) {
356 int tag; 352 int tag;
357 G(L)->GCthreshold = 2*G(L)->nblocks; /* avoid GC during tag methods */ 353 G(L)->GCthreshold = 2*G(L)->nblocks; /* avoid GC during tag methods */
358 for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */ 354 for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */
359 TString *udata; 355 Udata *udata;
360 while ((udata = G(L)->TMtable[tag].collected) != NULL) { 356 while ((udata = G(L)->TMtable[tag].collected) != NULL) {
361 TObject obj; 357 TObject obj;
362 G(L)->TMtable[tag].collected = udata->nexthash; /* remove it from list */ 358 G(L)->TMtable[tag].collected = udata->next; /* remove it from list */
363 setuvalue(&obj, udata); 359 setuvalue(&obj, udata);
364 callgcTM(L, &obj); 360 callgcTM(L, &obj);
365 luaM_free(L, udata, sizeudata(udata->len)); 361 luaM_free(L, udata, sizeudata(udata->len));
@@ -370,7 +366,7 @@ static void callgcTMudata (lua_State *L) {
370 366
371void luaC_collect (lua_State *L, int all) { 367void luaC_collect (lua_State *L, int all) {
372 lua_lockgc(L); 368 lua_lockgc(L);
373 collectudata(L, all); 369 collectudata(L);
374 callgcTMudata(L); 370 callgcTMudata(L);
375 collectstrings(L, all); 371 collectstrings(L, all);
376 collecttable(L); 372 collecttable(L);
diff --git a/liolib.c b/liolib.c
index fa9830bf..dda79529 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: liolib.c,v 1.111 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: liolib.c,v 1.112 2001/04/23 16:35:45 roberto Exp roberto $
3** Standard I/O (and system) library 3** Standard I/O (and system) library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -48,15 +48,17 @@ int pclose(); */
48#define OUTFILE 1 48#define OUTFILE 1
49#define NOFILE 2 49#define NOFILE 2
50 50
51#define FILEHANDLE l_s("FileHandle") 51#define FILEHANDLE l_s("FileHandle")
52#define CLOSEDFILEHANDLE l_s("ClosedFileHandle")
52 53
53 54
54static const l_char *const filenames[] = {l_s("_INPUT"), l_s("_OUTPUT")}; 55static const l_char *const filenames[] = {l_s("_INPUT"), l_s("_OUTPUT")};
56static const l_char *const basicfiles[] = {l_s("_STDIN"), l_s("_STDOUT")};
55 57
56 58
57static int pushresult (lua_State *L, int i) { 59static int pushresult (lua_State *L, int i) {
58 if (i) { 60 if (i) {
59 lua_pushuserdata(L, NULL); 61 lua_newuserdatabox(L, NULL);
60 return 1; 62 return 1;
61 } 63 }
62 else { 64 else {
@@ -81,16 +83,15 @@ static int pushresult (lua_State *L, int i) {
81static FILE *getopthandle (lua_State *L, int inout) { 83static FILE *getopthandle (lua_State *L, int inout) {
82 FILE *p = (FILE *)lua_touserdata(L, 1); 84 FILE *p = (FILE *)lua_touserdata(L, 1);
83 if (p != NULL) { /* is it a userdata ? */ 85 if (p != NULL) { /* is it a userdata ? */
84 if (!checkfile(L, 1)) { 86 if (!checkfile(L, 1)) { /* not a valid file handle? */
85 if (strcmp(lua_xtypename(L, 1), l_s("ClosedFileHandle")) == 0) 87 if (strcmp(lua_xtypename(L, 1), CLOSEDFILEHANDLE) == 0)
86 luaL_argerror(L, 1, l_s("file is closed")); 88 luaL_argerror(L, 1, l_s("file is closed"));
87 else 89 else
88 luaL_argerror(L, 1, l_s("(invalid value)")); 90 luaL_argerror(L, 1, l_s("(invalid value)"));
89 } 91 }
90 /* move it to stack top */ 92 lua_pushvalue(L, 1); lua_remove(L, 1); /* move it to stack top */
91 lua_pushvalue(L, 1); lua_remove(L, 1);
92 } 93 }
93 else if (inout != NOFILE) { /* try global value */ 94 else { /* try global value */
94 lua_getglobal(L, filenames[inout]); 95 lua_getglobal(L, filenames[inout]);
95 if (!checkfile(L,-1)) 96 if (!checkfile(L,-1))
96 luaL_verror(L, l_s("global variable `%.10s' is not a valid file handle"), 97 luaL_verror(L, l_s("global variable `%.10s' is not a valid file handle"),
@@ -101,46 +102,50 @@ static FILE *getopthandle (lua_State *L, int inout) {
101} 102}
102 103
103 104
104static void pushfile (lua_State *L, FILE *f) { 105static void newfile (lua_State *L, FILE *f) {
105 lua_pushusertag(L, f, lua_name2tag(L, FILEHANDLE)); 106 lua_newuserdatabox(L, f);
107 lua_settag(L, lua_name2tag(L, FILEHANDLE));
106} 108}
107 109
108 110
109static void setfilebyname (lua_State *L, FILE *f, const l_char *name) { 111static void newfilewithname (lua_State *L, FILE *f, const l_char *name) {
110 pushfile(L, f); 112 newfile(L, f);
111 lua_setglobal(L, name); 113 lua_setglobal(L, name);
112} 114}
113 115
114 116
115#define setfile(L,f,inout) (setfilebyname(L,f,filenames[inout])) 117static int setnewfile (lua_State *L, FILE *f, int inout) {
116
117
118static int setreturn (lua_State *L, FILE *f, int inout) {
119 if (f == NULL) 118 if (f == NULL)
120 return pushresult(L, 0); 119 return pushresult(L, 0);
121 else { 120 else {
122 if (inout != NOFILE) 121 newfile(L, f);
123 setfile(L, f, inout); 122 if (inout != NOFILE) {
124 pushfile(L, f); 123 lua_pushvalue(L, -1);
124 lua_setglobal(L, filenames[inout]);
125 }
125 return 1; 126 return 1;
126 } 127 }
127} 128}
128 129
129 130
130static int closefile (lua_State *L, FILE *f) { 131static void resetfile (lua_State *L, int inout) {
131 if (f == stdin || f == stdout || f == stderr) 132 lua_getglobal(L, basicfiles[inout]);
132 return 1; 133 lua_setglobal(L, filenames[inout]);
133 else {
134 lua_pushuserdata(L, f);
135 lua_settag(L, lua_name2tag(L, l_s("ClosedFileHandle")));
136 return (CLOSEFILE(L, f) == 0);
137 }
138} 134}
139 135
140 136
141static int io_close (lua_State *L) { 137static int io_close (lua_State *L) {
142 FILE *f = (FILE *)luaL_check_userdata(L, 1, FILEHANDLE); 138 FILE *f;
143 return pushresult(L, closefile(L, f)); 139 int status;
140 lua_settop(L, 1);
141 f = luaL_check_userdata(L, 1, FILEHANDLE);
142 if (f == stdin || f == stdout || f == stderr)
143 status = 1;
144 else {
145 lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE));
146 status = (CLOSEFILE(L, f) == 0);
147 }
148 return pushresult(L, status);
144} 149}
145 150
146 151
@@ -154,12 +159,12 @@ static int file_collect (lua_State *L) {
154 159
155static int io_open (lua_State *L) { 160static int io_open (lua_State *L) {
156 FILE *f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); 161 FILE *f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2));
157 return setreturn(L, f, NOFILE); 162 return setnewfile(L, f, NOFILE);
158} 163}
159 164
160 165
161static int io_tmpfile (lua_State *L) { 166static int io_tmpfile (lua_State *L) {
162 return setreturn(L, tmpfile(), NOFILE); 167 return setnewfile(L, tmpfile(), NOFILE);
163} 168}
164 169
165 170
@@ -167,16 +172,15 @@ static int io_tmpfile (lua_State *L) {
167static int io_fromto (lua_State *L, int inout, const l_char *mode) { 172static int io_fromto (lua_State *L, int inout, const l_char *mode) {
168 FILE *current; 173 FILE *current;
169 if (lua_isnull(L, 1)) { 174 if (lua_isnull(L, 1)) {
170 closefile(L, getopthandle(L, inout)); 175 getopthandle(L, inout);
171 current = (inout == 0) ? stdin : stdout; 176 resetfile(L, inout);
177 return io_close(L);
172 } 178 }
173 else if (checkfile(L, 1)) /* deprecated option */
174 current = (FILE *)lua_touserdata(L, 1);
175 else { 179 else {
176 const l_char *s = luaL_check_string(L, 1); 180 const l_char *s = luaL_check_string(L, 1);
177 current = (*s == l_c('|')) ? popen(s+1, mode) : fopen(s, mode); 181 current = (*s == l_c('|')) ? popen(s+1, mode) : fopen(s, mode);
182 return setnewfile(L, current, inout);
178 } 183 }
179 return setreturn(L, current, inout);
180} 184}
181 185
182 186
@@ -192,7 +196,7 @@ static int io_writeto (lua_State *L) {
192 196
193static int io_appendto (lua_State *L) { 197static int io_appendto (lua_State *L) {
194 FILE *current = fopen(luaL_check_string(L, 1), l_s("a")); 198 FILE *current = fopen(luaL_check_string(L, 1), l_s("a"));
195 return setreturn(L, current, OUTFILE); 199 return setnewfile(L, current, OUTFILE);
196} 200}
197 201
198 202
@@ -388,8 +392,8 @@ static int io_seek (lua_State *L) {
388 392
389 393
390static int io_flush (lua_State *L) { 394static int io_flush (lua_State *L) {
391 FILE *f = getopthandle(L, NOFILE); 395 FILE *f = (lua_isnull(L, 1)) ? (FILE *)NULL :
392 luaL_arg_check(L, f || lua_isnull(L, 1), 1, l_s("invalid file handle")); 396 (FILE *)luaL_check_userdata(L, 1, FILEHANDLE);
393 return pushresult(L, fflush(f) == 0); 397 return pushresult(L, fflush(f) == 0);
394} 398}
395 399
@@ -679,14 +683,14 @@ static const luaL_reg iolib[] = {
679 683
680LUALIB_API int lua_iolibopen (lua_State *L) { 684LUALIB_API int lua_iolibopen (lua_State *L) {
681 int iotag = lua_newxtype(L, FILEHANDLE, LUA_TUSERDATA); 685 int iotag = lua_newxtype(L, FILEHANDLE, LUA_TUSERDATA);
682 lua_newxtype(L, l_s("ClosedFileHandle"), LUA_TUSERDATA); 686 lua_newxtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA);
683 luaL_openl(L, iolib); 687 luaL_openl(L, iolib);
684 /* predefined file handles */ 688 /* predefined file handles */
685 setfile(L, stdin, INFILE); 689 newfilewithname(L, stdin, basicfiles[INFILE]);
686 setfile(L, stdout, OUTFILE); 690 newfilewithname(L, stdout, basicfiles[OUTFILE]);
687 setfilebyname(L, stdin, l_s("_STDIN")); 691 newfilewithname(L, stderr, l_s("_STDERR"));
688 setfilebyname(L, stdout, l_s("_STDOUT")); 692 resetfile(L, INFILE);
689 setfilebyname(L, stderr, l_s("_STDERR")); 693 resetfile(L, OUTFILE);
690 /* close files when collected */ 694 /* close files when collected */
691 lua_pushcfunction(L, file_collect); 695 lua_pushcfunction(L, file_collect);
692 lua_settagmethod(L, iotag, l_s("gc")); 696 lua_settagmethod(L, iotag, l_s("gc"));
diff --git a/lobject.h b/lobject.h
index 97f77a97..ebcdbbb7 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.102 2001/04/11 14:42:41 roberto Exp roberto $ 2** $Id: lobject.h,v 1.103 2001/06/05 18:17:01 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -29,6 +29,7 @@
29 29
30typedef union { 30typedef union {
31 struct TString *ts; 31 struct TString *ts;
32 struct Udata *u;
32 struct Closure *cl; 33 struct Closure *cl;
33 struct Hash *h; 34 struct Hash *h;
34 lua_Number n; /* LUA_TNUMBER */ 35 lua_Number n; /* LUA_TNUMBER */
@@ -45,6 +46,7 @@ typedef struct lua_TObject {
45#define ttype(o) ((o)->tt) 46#define ttype(o) ((o)->tt)
46#define nvalue(o) ((o)->value.n) 47#define nvalue(o) ((o)->value.n)
47#define tsvalue(o) ((o)->value.ts) 48#define tsvalue(o) ((o)->value.ts)
49#define uvalue(o) ((o)->value.u)
48#define clvalue(o) ((o)->value.cl) 50#define clvalue(o) ((o)->value.cl)
49#define hvalue(o) ((o)->value.h) 51#define hvalue(o) ((o)->value.h)
50 52
@@ -57,7 +59,7 @@ typedef struct lua_TObject {
57 { TObject *_o=(obj); _o->tt=LUA_TSTRING; _o->value.ts=(x); } 59 { TObject *_o=(obj); _o->tt=LUA_TSTRING; _o->value.ts=(x); }
58 60
59#define setuvalue(obj,x) \ 61#define setuvalue(obj,x) \
60 { TObject *_o=(obj); _o->tt=LUA_TUSERDATA; _o->value.ts=(x); } 62 { TObject *_o=(obj); _o->tt=LUA_TUSERDATA; _o->value.u=(x); }
61 63
62#define setclvalue(obj,x) \ 64#define setclvalue(obj,x) \
63 { TObject *_o=(obj); _o->tt=LUA_TFUNCTION; _o->value.cl=(x); } 65 { TObject *_o=(obj); _o->tt=LUA_TFUNCTION; _o->value.cl=(x); }
@@ -78,38 +80,40 @@ typedef TObject *StkId; /* index to stack elements */
78/* 80/*
79** String headers for string table 81** String headers for string table
80*/ 82*/
81
82typedef struct TString { 83typedef struct TString {
83 union { 84 lu_hash hash;
84 struct { /* for strings */ 85 int constindex; /* hint to reuse constants */
85 lu_hash hash;
86 int constindex; /* hint to reuse constants */
87 } s;
88 struct { /* for userdata */
89 int tag;
90 void *value;
91 } d;
92 } u;
93 size_t len; 86 size_t len;
94 int marked; 87 int marked;
95 struct TString *nexthash; /* chain for hash table */ 88 struct TString *nexthash; /* chain for hash table */
96} TString; 89} TString;
97 90
98 91
92
99/* 93/*
100** type equivalent to TString, but with maximum alignment requirements 94** type equivalent to TString, but with maximum alignment requirements
101*/ 95*/
102union L_UTString { 96union L_UTString {
103 TString ts; 97 TString ts;
104 union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ 98 union L_Umaxalign dummy; /* ensures maximum alignment for strings */
105}; 99};
106 100
107 101
108
109#define getstr(ts) ((l_char *)((union L_UTString *)(ts) + 1)) 102#define getstr(ts) ((l_char *)((union L_UTString *)(ts) + 1))
110#define svalue(o) getstr(tsvalue(o)) 103#define svalue(o) getstr(tsvalue(o))
111 104
112 105
106
107typedef struct Udata {
108 int tag;
109 void *value;
110 size_t len;
111 int marked;
112 struct Udata *next; /* chain for list of all udata */
113} Udata;
114
115
116
113/* 117/*
114** Function Prototypes 118** Function Prototypes
115*/ 119*/
diff --git a/lstate.c b/lstate.c
index 63e15283..194e92c1 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.61 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: lstate.c,v 1.62 2001/04/17 17:35:54 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*/
@@ -49,14 +49,15 @@ static void f_luaopen (lua_State *L, void *ud) {
49 } 49 }
50 else { /* create a new global state */ 50 else { /* create a new global state */
51 L->G = luaM_new(L, global_State); 51 L->G = luaM_new(L, global_State);
52 G(L)->strt.size = G(L)->udt.size = 0; 52 G(L)->strt.size = 0;
53 G(L)->strt.nuse = G(L)->udt.nuse = 0; 53 G(L)->strt.nuse = 0;
54 G(L)->strt.hash = G(L)->udt.hash = NULL; 54 G(L)->strt.hash = NULL;
55 G(L)->Mbuffer = NULL; 55 G(L)->Mbuffer = NULL;
56 G(L)->Mbuffsize = 0; 56 G(L)->Mbuffsize = 0;
57 G(L)->rootproto = NULL; 57 G(L)->rootproto = NULL;
58 G(L)->rootcl = NULL; 58 G(L)->rootcl = NULL;
59 G(L)->roottable = NULL; 59 G(L)->roottable = NULL;
60 G(L)->rootudata = NULL;
60 G(L)->TMtable = NULL; 61 G(L)->TMtable = NULL;
61 G(L)->sizeTM = 0; 62 G(L)->sizeTM = 0;
62 G(L)->ntag = 0; 63 G(L)->ntag = 0;
@@ -67,7 +68,7 @@ static void f_luaopen (lua_State *L, void *ud) {
67 G(L)->registry = luaH_new(L, 0); 68 G(L)->registry = luaH_new(L, 0);
68 G(L)->weakregistry = luaH_new(L, 0); 69 G(L)->weakregistry = luaH_new(L, 0);
69 G(L)->weakregistry->weakmode = LUA_WEAK_VALUE; /* make weakregistry weak */ 70 G(L)->weakregistry->weakmode = LUA_WEAK_VALUE; /* make weakregistry weak */
70 luaS_init(L); 71 luaS_resize(L, MINPOWER2);
71 luaX_init(L); 72 luaX_init(L);
72 luaT_init(L); 73 luaT_init(L);
73 G(L)->GCthreshold = 4*G(L)->nblocks; 74 G(L)->GCthreshold = 4*G(L)->nblocks;
@@ -115,6 +116,7 @@ static void close_state (lua_State *L, lua_State *OL) {
115 lua_assert(G(L)->rootproto == NULL); 116 lua_assert(G(L)->rootproto == NULL);
116 lua_assert(G(L)->rootcl == NULL); 117 lua_assert(G(L)->rootcl == NULL);
117 lua_assert(G(L)->roottable == NULL); 118 lua_assert(G(L)->roottable == NULL);
119 lua_assert(G(L)->rootudata == NULL);
118 luaS_freeall(L); 120 luaS_freeall(L);
119 luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); 121 luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
120 luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char); 122 luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char);
diff --git a/lstate.h b/lstate.h
index 7c0e808d..a1965fb8 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 1.55 2001/03/07 18:09:25 roberto Exp roberto $ 2** $Id: lstate.h,v 1.56 2001/04/17 17:35:54 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*/
@@ -53,8 +53,8 @@ typedef struct global_State {
53 Proto *rootproto; /* list of all prototypes */ 53 Proto *rootproto; /* list of all prototypes */
54 Closure *rootcl; /* list of all closures */ 54 Closure *rootcl; /* list of all closures */
55 Hash *roottable; /* list of all tables */ 55 Hash *roottable; /* list of all tables */
56 Udata *rootudata; /* list of all userdata */
56 stringtable strt; /* hash table for strings */ 57 stringtable strt; /* hash table for strings */
57 stringtable udt; /* hash table for udata */
58 Hash *type2tag; /* hash table from type names to tags */ 58 Hash *type2tag; /* hash table from type names to tags */
59 Hash *registry; /* (strong) registry table */ 59 Hash *registry; /* (strong) registry table */
60 Hash *weakregistry; /* weakregistry table */ 60 Hash *weakregistry; /* weakregistry table */
diff --git a/lstring.c b/lstring.c
index 4318070d..e9d165cc 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.c,v 1.61 2001/02/23 17:17:25 roberto Exp roberto $ 2** $Id: lstring.c,v 1.62 2001/03/26 14:31:49 roberto Exp roberto $
3** String table (keeps all strings handled by Lua) 3** String table (keeps all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -17,22 +17,15 @@
17 17
18 18
19 19
20void luaS_init (lua_State *L) {
21 luaS_resize(L, &G(L)->strt, MINPOWER2);
22 luaS_resize(L, &G(L)->udt, MINPOWER2);
23}
24
25
26void luaS_freeall (lua_State *L) { 20void luaS_freeall (lua_State *L) {
27 lua_assert(G(L)->strt.nuse==0); 21 lua_assert(G(L)->strt.nuse==0);
28 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); 22 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
29 lua_assert(G(L)->udt.nuse==0);
30 luaM_freearray(L, G(L)->udt.hash, G(L)->udt.size, TString *);
31} 23}
32 24
33 25
34void luaS_resize (lua_State *L, stringtable *tb, int newsize) { 26void luaS_resize (lua_State *L, int newsize) {
35 TString **newhash = luaM_newvector(L, newsize, TString *); 27 TString **newhash = luaM_newvector(L, newsize, TString *);
28 stringtable *tb = &G(L)->strt;
36 int i; 29 int i;
37 for (i=0; i<newsize; i++) newhash[i] = NULL; 30 for (i=0; i<newsize; i++) newhash[i] = NULL;
38 /* rehash */ 31 /* rehash */
@@ -40,7 +33,7 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
40 TString *p = tb->hash[i]; 33 TString *p = tb->hash[i];
41 while (p) { /* for each node in the list */ 34 while (p) { /* for each node in the list */
42 TString *next = p->nexthash; /* save next */ 35 TString *next = p->nexthash; /* save next */
43 lu_hash h = (tb == &G(L)->strt) ? p->u.s.hash : IntPoint(p->u.d.value); 36 lu_hash h = p->hash;
44 int h1 = lmod(h, newsize); /* new position */ 37 int h1 = lmod(h, newsize); /* new position */
45 lua_assert((int)(h%newsize) == lmod(h, newsize)); 38 lua_assert((int)(h%newsize) == lmod(h, newsize));
46 p->nexthash = newhash[h1]; /* chain it in new position */ 39 p->nexthash = newhash[h1]; /* chain it in new position */
@@ -54,16 +47,6 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
54} 47}
55 48
56 49
57static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) {
58 ts->nexthash = tb->hash[h]; /* chain new entry */
59 tb->hash[h] = ts;
60 tb->nuse++;
61 if (tb->nuse > (ls_nstr)tb->size && tb->size <= MAX_INT/2) /* too crowded? */
62 luaS_resize(L, tb, tb->size*2);
63}
64
65
66
67TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l) { 50TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l) {
68 TString *ts; 51 TString *ts;
69 lu_hash h = l; /* seed */ 52 lu_hash h = l; /* seed */
@@ -80,39 +63,30 @@ TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l) {
80 ts->marked = 0; 63 ts->marked = 0;
81 ts->nexthash = NULL; 64 ts->nexthash = NULL;
82 ts->len = l; 65 ts->len = l;
83 ts->u.s.hash = h; 66 ts->hash = h;
84 ts->u.s.constindex = 0; 67 ts->constindex = 0;
85 memcpy(getstr(ts), str, l*sizeof(l_char)); 68 memcpy(getstr(ts), str, l*sizeof(l_char));
86 getstr(ts)[l] = 0; /* ending 0 */ 69 getstr(ts)[l] = 0; /* ending 0 */
87 newentry(L, &G(L)->strt, ts, lmod(h, G(L)->strt.size)); /* insert it */ 70 h = lmod(h, G(L)->strt.size);
71 ts->nexthash = G(L)->strt.hash[h]; /* chain new entry */
72 G(L)->strt.hash[h] = ts;
73 G(L)->strt.nuse++;
74 if (G(L)->strt.nuse > (ls_nstr)G(L)->strt.size &&
75 G(L)->strt.size <= MAX_INT/2)
76 luaS_resize(L, G(L)->strt.size*2); /* too crowded */
88 return ts; 77 return ts;
89} 78}
90 79
91 80
92TString *luaS_newudata (lua_State *L, size_t s, void *udata) { 81Udata *luaS_newudata (lua_State *L, size_t s) {
93 TString *ts = (TString *)luaM_malloc(L, sizeudata(s)); 82 Udata *u = (Udata *)luaM_malloc(L, sizeudata(s));
94 ts->marked = 0; 83 u->marked = 0;
95 ts->nexthash = NULL; 84 u->len = s;
96 ts->len = s; 85 u->tag = 0;
97 ts->u.d.tag = 0; 86 u->value = ((union L_UUdata *)(u) + 1);
98 ts->u.d.value = (s > 0) ? getstr(ts) : udata; 87 /* chain it on udata list */
99 /* insert it on table */ 88 u->next = G(L)->rootudata;
100 newentry(L, &G(L)->udt, ts, lmod(IntPoint(ts->u.d.value), G(L)->udt.size)); 89 G(L)->rootudata = u;
101 return ts; 90 return u;
102}
103
104
105int luaS_createudata (lua_State *L, void *udata, TObject *o) {
106 int h1 = lmod(IntPoint(udata), G(L)->udt.size);
107 TString *ts;
108 for (ts = G(L)->udt.hash[h1]; ts; ts = ts->nexthash) {
109 if (udata == ts->u.d.value) {
110 setuvalue(o, ts);
111 return 0;
112 }
113 }
114 /* not found */
115 setuvalue(o, luaS_newudata(L, 0, udata));
116 return 1;
117} 91}
118 92
diff --git a/lstring.h b/lstring.h
index ad6cca52..130b3a81 100644
--- a/lstring.h
+++ b/lstring.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.h,v 1.30 2001/02/20 18:15:33 roberto Exp roberto $ 2** $Id: lstring.h,v 1.31 2001/02/23 17:17:25 roberto Exp roberto $
3** String table (keep all strings handled by Lua) 3** String table (keep all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -14,6 +14,16 @@
14 14
15 15
16/* 16/*
17** type equivalent to Udata, but with maximum alignment requirements
18*/
19union L_UUdata {
20 Udata u;
21 union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
22};
23
24
25
26/*
17** any TString with mark>=FIXMARK is never collected. 27** any TString with mark>=FIXMARK is never collected.
18** Marks>=RESERVEDMARK are used to identify reserved words. 28** Marks>=RESERVEDMARK are used to identify reserved words.
19*/ 29*/
@@ -24,16 +34,14 @@
24#define sizestring(l) ((lu_mem)sizeof(union L_UTString)+ \ 34#define sizestring(l) ((lu_mem)sizeof(union L_UTString)+ \
25 ((lu_mem)(l)+1)*sizeof(l_char)) 35 ((lu_mem)(l)+1)*sizeof(l_char))
26 36
27#define sizeudata(l) ((lu_mem)sizeof(union L_UTString)+(l)) 37#define sizeudata(l) ((lu_mem)sizeof(union L_UUdata)+(l))
28 38
29#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) 39#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
30#define luaS_newliteral(L, s) (luaS_newlstr(L, l_s("") s, \ 40#define luaS_newliteral(L, s) (luaS_newlstr(L, l_s("") s, \
31 (sizeof(s)/sizeof(l_char))-1)) 41 (sizeof(s)/sizeof(l_char))-1))
32 42
33void luaS_init (lua_State *L); 43void luaS_resize (lua_State *L, int newsize);
34void luaS_resize (lua_State *L, stringtable *tb, int newsize); 44Udata *luaS_newudata (lua_State *L, size_t s);
35TString *luaS_newudata (lua_State *L, size_t s, void *udata);
36int luaS_createudata (lua_State *L, void *udata, TObject *o);
37void luaS_freeall (lua_State *L); 45void luaS_freeall (lua_State *L);
38TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l); 46TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l);
39 47
diff --git a/ltable.c b/ltable.c
index c3e4d382..c4a2c789 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 1.78 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: ltable.c,v 1.79 2001/04/11 14:42:41 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -33,7 +33,7 @@
33 33
34 34
35#define hashnum(t,n) (&t->node[lmod((lu_hash)(ls_hash)(n), t->size)]) 35#define hashnum(t,n) (&t->node[lmod((lu_hash)(ls_hash)(n), t->size)])
36#define hashstr(t,str) (&t->node[lmod((str)->u.s.hash, t->size)]) 36#define hashstr(t,str) (&t->node[lmod((str)->hash, t->size)])
37#define hashpointer(t,p) (&t->node[lmod(IntPoint(p), t->size)]) 37#define hashpointer(t,p) (&t->node[lmod(IntPoint(p), t->size)])
38 38
39 39
diff --git a/ltests.c b/ltests.c
index 95d7813d..b666a917 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.80 2001/04/23 16:35:45 roberto Exp roberto $ 2** $Id: ltests.c,v 1.81 2001/06/05 18:17:01 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*/
@@ -290,7 +290,7 @@ static int mem_query (lua_State *L) {
290static int hash_query (lua_State *L) { 290static int hash_query (lua_State *L) {
291 if (lua_isnull(L, 2)) { 291 if (lua_isnull(L, 2)) {
292 luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, l_s("string expected")); 292 luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, l_s("string expected"));
293 lua_pushnumber(L, tsvalue(luaA_index(L, 1))->u.s.hash); 293 lua_pushnumber(L, tsvalue(luaA_index(L, 1))->hash);
294 } 294 }
295 else { 295 else {
296 Hash *t; 296 Hash *t;
@@ -339,8 +339,7 @@ static int table_query (lua_State *L) {
339 339
340 340
341static int string_query (lua_State *L) { 341static int string_query (lua_State *L) {
342 stringtable *tb = (*luaL_check_string(L, 1) == l_c('s')) ? &G(L)->strt : 342 stringtable *tb = &G(L)->strt;
343 &G(L)->udt;
344 int s = luaL_opt_int(L, 2, 0) - 1; 343 int s = luaL_opt_int(L, 2, 0) - 1;
345 if (s==-1) { 344 if (s==-1) {
346 lua_pushnumber(L ,tb->nuse); 345 lua_pushnumber(L ,tb->nuse);
@@ -390,19 +389,22 @@ static int unref (lua_State *L) {
390} 389}
391 390
392static int newuserdata (lua_State *L) { 391static int newuserdata (lua_State *L) {
393 if (lua_isnumber(L, 2)) { 392 size_t size = luaL_check_int(L, 1);
394 int tag = luaL_check_int(L, 2); 393 l_char *p = (l_char *)lua_newuserdata(L, size);
395 int res = lua_pushuserdata(L, (void *)luaL_check_int(L, 1)); 394 while (size--) *p++ = l_c('\0');
396 if (tag) lua_settag(L, tag); 395 return 1;
397 pushbool(L, res); 396}
398 return 2; 397
399 } 398static int newuserdatabox (lua_State *L) {
400 else { 399 lua_newuserdatabox(L, (void *)luaL_check_int(L, 1));
401 size_t size = luaL_check_int(L, 1); 400 return 1;
402 l_char *p = (l_char *)lua_newuserdata(L, size); 401}
403 while (size--) *p++ = l_c('\0'); 402
404 return 1; 403static int settag (lua_State *L) {
405 } 404 luaL_checkany(L, 1);
405 lua_pushvalue(L, 1); /* push value */
406 lua_settag(L, luaL_check_int(L, 2));
407 return 1; /* return value */
406} 408}
407 409
408static int udataval (lua_State *L) { 410static int udataval (lua_State *L) {
@@ -691,6 +693,8 @@ static const struct luaL_reg tests_funcs[] = {
691 {l_s("d2s"), d2s}, 693 {l_s("d2s"), d2s},
692 {l_s("s2d"), s2d}, 694 {l_s("s2d"), s2d},
693 {l_s("newuserdata"), newuserdata}, 695 {l_s("newuserdata"), newuserdata},
696 {l_s("newuserdatabox"), newuserdatabox},
697 {l_s("settag"), settag},
694 {l_s("udataval"), udataval}, 698 {l_s("udataval"), udataval},
695 {l_s("newtag"), newtag}, 699 {l_s("newtag"), newtag},
696 {l_s("doonnewstack"), doonnewstack}, 700 {l_s("doonnewstack"), doonnewstack},
diff --git a/ltm.c b/ltm.c
index b66d3d46..756728cf 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 1.70 2001/03/02 17:27:50 roberto Exp roberto $ 2** $Id: ltm.c,v 1.71 2001/03/26 14:31:49 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -127,7 +127,7 @@ LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) {
127int luaT_tag (const TObject *o) { 127int luaT_tag (const TObject *o) {
128 int t = ttype(o); 128 int t = ttype(o);
129 switch (t) { 129 switch (t) {
130 case LUA_TUSERDATA: return tsvalue(o)->u.d.tag; 130 case LUA_TUSERDATA: return uvalue(o)->tag;
131 case LUA_TTABLE: return hvalue(o)->htag; 131 case LUA_TTABLE: return hvalue(o)->htag;
132 default: return t; 132 default: return t;
133 } 133 }
@@ -140,7 +140,7 @@ const l_char *luaT_typename (global_State *G, const TObject *o) {
140 TString *ts; 140 TString *ts;
141 switch (t) { 141 switch (t) {
142 case LUA_TUSERDATA: 142 case LUA_TUSERDATA:
143 tag = tsvalue(o)->u.d.tag; 143 tag = uvalue(o)->tag;
144 break; 144 break;
145 case LUA_TTABLE: 145 case LUA_TTABLE:
146 tag = hvalue(o)->htag; 146 tag = hvalue(o)->htag;
diff --git a/ltm.h b/ltm.h
index 53572bd2..e233f1ef 100644
--- a/ltm.h
+++ b/ltm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.h,v 1.23 2001/02/09 20:22:29 roberto Exp roberto $ 2** $Id: ltm.h,v 1.24 2001/02/23 17:17:25 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -53,7 +53,7 @@ typedef enum {
53 53
54struct TM { 54struct TM {
55 Closure *method[TM_N]; 55 Closure *method[TM_N];
56 TString *collected; /* list of garbage-collected udata with this tag */ 56 Udata *collected; /* list of garbage-collected udata with this tag */
57 TString *name; /* type name */ 57 TString *name; /* type name */
58 int basictype; 58 int basictype;
59}; 59};
diff --git a/lua.c b/lua.c
index fc2e89b0..34333f6f 100644
--- a/lua.c
+++ b/lua.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.c,v 1.65 2001/03/09 18:05:05 roberto Exp roberto $ 2** $Id: lua.c,v 1.66 2001/03/26 14:31:49 roberto Exp roberto $
3** Lua stand-alone interpreter 3** Lua stand-alone interpreter
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -308,7 +308,7 @@ static void getstacksize (int argc, l_char *argv[], struct Options *opt) {
308 308
309 309
310static void register_getargs (l_char *argv[]) { 310static void register_getargs (l_char *argv[]) {
311 lua_pushuserdata(L, argv); 311 lua_newuserdatabox(L, argv);
312 lua_pushcclosure(L, l_getargs, 1); 312 lua_pushcclosure(L, l_getargs, 1);
313 lua_setglobal(L, l_s("getargs")); 313 lua_setglobal(L, l_s("getargs"));
314} 314}
diff --git a/lua.h b/lua.h
index 6e1254ba..d391ccb0 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.96 2001/04/17 17:35:54 roberto Exp roberto $ 2** $Id: lua.h,v 1.97 2001/04/23 16:35:45 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil 4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
5** e-mail: info@lua.org 5** e-mail: info@lua.org
@@ -150,7 +150,6 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n);
150LUA_API void lua_pushlstring (lua_State *L, const lua_char *s, size_t len); 150LUA_API void lua_pushlstring (lua_State *L, const lua_char *s, size_t len);
151LUA_API void lua_pushstring (lua_State *L, const lua_char *s); 151LUA_API void lua_pushstring (lua_State *L, const lua_char *s);
152LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); 152LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
153LUA_API int lua_pushuserdata (lua_State *L, void *u);
154 153
155 154
156/* 155/*
@@ -218,6 +217,7 @@ LUA_API int lua_getn (lua_State *L, int index);
218LUA_API void lua_concat (lua_State *L, int n); 217LUA_API void lua_concat (lua_State *L, int n);
219 218
220LUA_API void *lua_newuserdata (lua_State *L, size_t size); 219LUA_API void *lua_newuserdata (lua_State *L, size_t size);
220LUA_API void lua_newuserdatabox (lua_State *L, void *u);
221 221
222LUA_API void lua_setweakmode (lua_State *L, int mode); 222LUA_API void lua_setweakmode (lua_State *L, int mode);
223LUA_API int lua_getweakmode (lua_State *L, int index); 223LUA_API int lua_getweakmode (lua_State *L, int index);