aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-20 13:52:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-20 13:52:50 -0300
commitca6fe7449a74efde6f959605dbe77acf3e64ca0b (patch)
treea6190e813ff712f7db750d4ecd3afd3ac9c0dbab
parent1afd5a152dc8b3a304236dc4e07bca38ea5eb53a (diff)
downloadlua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.tar.gz
lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.tar.bz2
lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.zip
userdata can have multiple user values
-rw-r--r--lapi.c35
-rw-r--r--ldblib.c13
-rw-r--r--lgc.c33
-rw-r--r--lobject.h60
-rw-r--r--lstring.c13
-rw-r--r--lstring.h7
-rw-r--r--ltests.c25
-rw-r--r--lua.h15
8 files changed, 121 insertions, 80 deletions
diff --git a/lapi.c b/lapi.c
index 1ec649b0..78ae7e0b 100644
--- a/lapi.c
+++ b/lapi.c
@@ -10,6 +10,7 @@
10#include "lprefix.h" 10#include "lprefix.h"
11 11
12 12
13#include <limits.h>
13#include <stdarg.h> 14#include <stdarg.h>
14#include <string.h> 15#include <string.h>
15 16
@@ -733,15 +734,23 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
733} 734}
734 735
735 736
736LUA_API int lua_getuservalue (lua_State *L, int idx) { 737LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) {
737 TValue *o; 738 TValue *o;
739 int t;
738 lua_lock(L); 740 lua_lock(L);
739 o = index2value(L, idx); 741 o = index2value(L, idx);
740 api_check(L, ttisfulluserdata(o), "full userdata expected"); 742 api_check(L, ttisfulluserdata(o), "full userdata expected");
741 getuservalue(L, uvalue(o), s2v(L->top)); 743 if (n <= 0 || n > uvalue(o)->nuvalue) {
744 setnilvalue(s2v(L->top));
745 t = LUA_TNONE;
746 }
747 else {
748 setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv);
749 t = ttnov(s2v(L->top));
750 }
742 api_incr_top(L); 751 api_incr_top(L);
743 lua_unlock(L); 752 lua_unlock(L);
744 return ttnov(s2v(L->top - 1)); 753 return t;
745} 754}
746 755
747 756
@@ -903,16 +912,23 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
903} 912}
904 913
905 914
906LUA_API void lua_setuservalue (lua_State *L, int idx) { 915LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) {
907 TValue *o; 916 TValue *o;
917 int res;
908 lua_lock(L); 918 lua_lock(L);
909 api_checknelems(L, 1); 919 api_checknelems(L, 1);
910 o = index2value(L, idx); 920 o = index2value(L, idx);
911 api_check(L, ttisfulluserdata(o), "full userdata expected"); 921 api_check(L, ttisfulluserdata(o), "full userdata expected");
912 setuservalue(L, uvalue(o), s2v(L->top - 1)); 922 if (!(0 < n && n <= uvalue(o)->nuvalue))
913 luaC_barrier(L, gcvalue(o), s2v(L->top - 1)); 923 res = 0;
914 L->top--; 924 else {
925 setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1));
926 luaC_barrierback(L, gcvalue(o), s2v(L->top - 1));
927 L->top--;
928 res = 1;
929 }
915 lua_unlock(L); 930 lua_unlock(L);
931 return res;
916} 932}
917 933
918 934
@@ -1231,10 +1247,11 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
1231} 1247}
1232 1248
1233 1249
1234LUA_API void *lua_newuserdata (lua_State *L, size_t size) { 1250LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) {
1235 Udata *u; 1251 Udata *u;
1236 lua_lock(L); 1252 lua_lock(L);
1237 u = luaS_newudata(L, size); 1253 api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value");
1254 u = luaS_newudata(L, size, nuvalue);
1238 setuvalue(L, s2v(L->top), u); 1255 setuvalue(L, s2v(L->top), u);
1239 api_incr_top(L); 1256 api_incr_top(L);
1240 luaC_checkGC(L); 1257 luaC_checkGC(L);
diff --git a/ldblib.c b/ldblib.c
index c1e26e0d..32da9697 100644
--- a/ldblib.c
+++ b/ldblib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp roberto $ 2** $Id: ldblib.c,v 1.152 2018/02/17 19:29:29 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*/
@@ -64,19 +64,24 @@ static int db_setmetatable (lua_State *L) {
64 64
65 65
66static int db_getuservalue (lua_State *L) { 66static int db_getuservalue (lua_State *L) {
67 int n = luaL_optinteger(L, 2, 1);
67 if (lua_type(L, 1) != LUA_TUSERDATA) 68 if (lua_type(L, 1) != LUA_TUSERDATA)
68 lua_pushnil(L); 69 lua_pushnil(L);
69 else 70 else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
70 lua_getuservalue(L, 1); 71 lua_pushboolean(L, 1);
72 return 2;
73 }
71 return 1; 74 return 1;
72} 75}
73 76
74 77
75static int db_setuservalue (lua_State *L) { 78static int db_setuservalue (lua_State *L) {
79 int n = luaL_optinteger(L, 3, 1);
76 luaL_checktype(L, 1, LUA_TUSERDATA); 80 luaL_checktype(L, 1, LUA_TUSERDATA);
77 luaL_checkany(L, 2); 81 luaL_checkany(L, 2);
78 lua_settop(L, 2); 82 lua_settop(L, 2);
79 lua_setuservalue(L, 1); 83 if (!lua_setiuservalue(L, 1, n))
84 lua_pushnil(L);
80 return 1; 85 return 1;
81} 86}
82 87
diff --git a/lgc.c b/lgc.c
index 77ccae0a..3421bd8a 100644
--- a/lgc.c
+++ b/lgc.c
@@ -113,6 +113,7 @@ static lu_mem atomic (lua_State *L);
113static GCObject **getgclist (GCObject *o) { 113static GCObject **getgclist (GCObject *o) {
114 switch (o->tt) { 114 switch (o->tt) {
115 case LUA_TTABLE: return &gco2t(o)->gclist; 115 case LUA_TTABLE: return &gco2t(o)->gclist;
116 case LUA_TUSERDATA: return &gco2u(o)->gclist;
116 case LUA_TLCL: return &gco2lcl(o)->gclist; 117 case LUA_TLCL: return &gco2lcl(o)->gclist;
117 case LUA_TCCL: return &gco2ccl(o)->gclist; 118 case LUA_TCCL: return &gco2ccl(o)->gclist;
118 case LUA_TTHREAD: return &gco2th(o)->gclist; 119 case LUA_TTHREAD: return &gco2th(o)->gclist;
@@ -269,7 +270,6 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
269** to avoid barriers, as their values will be revisited by the thread.) 270** to avoid barriers, as their values will be revisited by the thread.)
270*/ 271*/
271static void reallymarkobject (global_State *g, GCObject *o) { 272static void reallymarkobject (global_State *g, GCObject *o) {
272 reentry:
273 white2gray(o); 273 white2gray(o);
274 switch (o->tt) { 274 switch (o->tt) {
275 case LUA_TSHRSTR: 275 case LUA_TSHRSTR:
@@ -277,17 +277,6 @@ static void reallymarkobject (global_State *g, GCObject *o) {
277 gray2black(o); 277 gray2black(o);
278 break; 278 break;
279 } 279 }
280 case LUA_TUSERDATA: {
281 TValue uvalue;
282 markobjectN(g, gco2u(o)->metatable); /* mark its metatable */
283 gray2black(o);
284 getuservalue(g->mainthread, gco2u(o), &uvalue);
285 if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */
286 o = gcvalue(&uvalue);
287 goto reentry;
288 }
289 break;
290 }
291 case LUA_TUPVAL: { 280 case LUA_TUPVAL: {
292 UpVal *uv = gco2upv(o); 281 UpVal *uv = gco2upv(o);
293 if (!upisopen(uv)) /* open upvalues are kept gray */ 282 if (!upisopen(uv)) /* open upvalues are kept gray */
@@ -296,7 +285,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
296 break; 285 break;
297 } 286 }
298 case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: 287 case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE:
299 case LUA_TTHREAD: case LUA_TPROTO: { 288 case LUA_TUSERDATA: case LUA_TTHREAD: case LUA_TPROTO: {
300 linkobjgclist(o, g->gray); 289 linkobjgclist(o, g->gray);
301 break; 290 break;
302 } 291 }
@@ -602,6 +591,15 @@ static int traversethread (global_State *g, lua_State *th) {
602} 591}
603 592
604 593
594static int traverseudata (global_State *g, Udata *u) {
595 int i;
596 markobjectN(g, u->metatable); /* mark its metatable */
597 for (i = 0; i < u->nuvalue; i++)
598 markvalue(g, &u->uv[i].uv);
599 return 1 + u->nuvalue;
600}
601
602
605/* 603/*
606** traverse one gray object, turning it to black (except for threads, 604** traverse one gray object, turning it to black (except for threads,
607** which are always gray). 605** which are always gray).
@@ -612,6 +610,7 @@ static lu_mem propagatemark (global_State *g) {
612 g->gray = *getgclist(o); /* remove from 'gray' list */ 610 g->gray = *getgclist(o); /* remove from 'gray' list */
613 switch (o->tt) { 611 switch (o->tt) {
614 case LUA_TTABLE: return traversetable(g, gco2t(o)); 612 case LUA_TTABLE: return traversetable(g, gco2t(o));
613 case LUA_TUSERDATA: return traverseudata(g, gco2u(o));
615 case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); 614 case LUA_TLCL: return traverseLclosure(g, gco2lcl(o));
616 case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); 615 case LUA_TCCL: return traverseCclosure(g, gco2ccl(o));
617 case LUA_TPROTO: return traverseproto(g, gco2p(o)); 616 case LUA_TPROTO: return traverseproto(g, gco2p(o));
@@ -742,9 +741,11 @@ static void freeobj (lua_State *L, GCObject *o) {
742 case LUA_TTHREAD: 741 case LUA_TTHREAD:
743 luaE_freethread(L, gco2th(o)); 742 luaE_freethread(L, gco2th(o));
744 break; 743 break;
745 case LUA_TUSERDATA: 744 case LUA_TUSERDATA: {
746 luaM_freemem(L, o, sizeudata(gco2u(o))); 745 Udata *u = gco2u(o);
746 luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
747 break; 747 break;
748 }
748 case LUA_TSHRSTR: 749 case LUA_TSHRSTR:
749 luaS_remove(L, gco2ts(o)); /* remove it from hash table */ 750 luaS_remove(L, gco2ts(o)); /* remove it from hash table */
750 luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); 751 luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
@@ -1065,7 +1066,7 @@ static GCObject **correctgraylist (GCObject **p) {
1065 GCObject *curr; 1066 GCObject *curr;
1066 while ((curr = *p) != NULL) { 1067 while ((curr = *p) != NULL) {
1067 switch (curr->tt) { 1068 switch (curr->tt) {
1068 case LUA_TTABLE: { 1069 case LUA_TTABLE: case LUA_TUSERDATA: {
1069 GCObject **next = getgclist(curr); 1070 GCObject **next = getgclist(curr);
1070 if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ 1071 if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */
1071 lua_assert(isgray(curr)); 1072 lua_assert(isgray(curr));
diff --git a/lobject.h b/lobject.h
index 01bd39fa..03396f11 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.132 2018/01/28 12:07:53 roberto Exp roberto $ 2** $Id: lobject.h,v 2.133 2018/01/28 15:13:26 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*/
@@ -365,47 +365,53 @@ typedef union UTString {
365 365
366 366
367/* 367/*
368** Header for userdata; memory area follows the end of this structure 368** {==================================================================
369** (aligned according to 'UUdata'; see next). 369** Userdata
370** ===================================================================
371*/
372
373/* Ensures that addresses after this type are always fully aligned. */
374typedef union UValue {
375 TValue uv;
376 LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */
377} UValue;
378
379
380/*
381** Header for userdata; memory area follows the end of this structure.
370*/ 382*/
371typedef struct Udata { 383typedef struct Udata {
372 CommonHeader; 384 CommonHeader;
373 lu_byte ttuv_; /* user value's tag */ 385 unsigned short nuvalue; /* number of user values */
374 struct Table *metatable;
375 size_t len; /* number of bytes */ 386 size_t len; /* number of bytes */
376 union Value user_; /* user value */ 387 struct Table *metatable;
388 GCObject *gclist;
389 UValue uv[1]; /* user values */
377} Udata; 390} Udata;
378 391
379 392
380/* 393/* computes the offset of the memory area of a userdata */
381** Ensures that address after this type is always fully aligned. 394#define udatamemoffset(nuv) (sizeof(Udata) + (sizeof(UValue) * ((nuv) - 1)))
382*/
383typedef union UUdata {
384 LUAI_MAXALIGN; /* ensures maximum alignment for 'local' udata */
385 Udata uv;
386} UUdata;
387
388 395
389/* 396/*
390** Get the address of memory block inside 'Udata'. 397** Get the address of the memory block inside 'Udata'.
391** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
392*/ 398*/
393#define getudatamem(u) \ 399#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue))
394 check_exp(sizeof((u)->ttuv_), (cast_charp(u) + sizeof(UUdata)))
395 400
396#define setuservalue(L,u,o) \ 401/* computes the size of a userdata */
397 { const TValue *io=(o); Udata *iu = (u); \ 402#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb))
398 iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
399 checkliveness(L,io); }
400 403
404/* }================================================================== */
401 405
402#define getuservalue(L,u,o) \
403 { TValue *io=(o); const Udata *iu = (u); \
404 io->value_ = iu->user_; settt_(io, iu->ttuv_); \
405 checkliveness(L,io); }
406 406
407 407
408/* 408/*
409** {==================================================================
410** Prototypes
411** ===================================================================
412*/
413
414/*
409** Description of an upvalue for function prototypes 415** Description of an upvalue for function prototypes
410*/ 416*/
411typedef struct Upvaldesc { 417typedef struct Upvaldesc {
@@ -471,6 +477,8 @@ typedef struct Proto {
471 GCObject *gclist; 477 GCObject *gclist;
472} Proto; 478} Proto;
473 479
480/* }================================================================== */
481
474 482
475 483
476/* 484/*
diff --git a/lstring.c b/lstring.c
index fbc3e02d..29a08212 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.c,v 2.63 2018/01/28 15:13:26 roberto Exp roberto $ 2** $Id: lstring.c,v 2.64 2018/02/15 18:06:24 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*/
@@ -265,16 +265,19 @@ TString *luaS_new (lua_State *L, const char *str) {
265} 265}
266 266
267 267
268Udata *luaS_newudata (lua_State *L, size_t s) { 268Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
269 Udata *u; 269 Udata *u;
270 int i;
270 GCObject *o; 271 GCObject *o;
271 if (s > MAX_SIZE - sizeof(Udata)) 272 if (s > MAX_SIZE - udatamemoffset(nuvalue))
272 luaM_toobig(L); 273 luaM_toobig(L);
273 o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); 274 o = luaC_newobj(L, LUA_TUSERDATA, sizeudata(nuvalue, s));
274 u = gco2u(o); 275 u = gco2u(o);
275 u->len = s; 276 u->len = s;
277 u->nuvalue = nuvalue;
276 u->metatable = NULL; 278 u->metatable = NULL;
277 setuservalue(L, u, luaO_nilobject); 279 for (i = 0; i < nuvalue; i++)
280 setnilvalue(&u->uv[i].uv);
278 return u; 281 return u;
279} 282}
280 283
diff --git a/lstring.h b/lstring.h
index a994fe1e..2be5a3ff 100644
--- a/lstring.h
+++ b/lstring.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.h,v 1.62 2017/07/27 13:50:16 roberto Exp roberto $ 2** $Id: lstring.h,v 1.63 2017/11/23 19:29:04 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*/
@@ -21,9 +21,6 @@
21 21
22#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) 22#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char))
23 23
24#define sizeludata(l) (sizeof(union UUdata) + (l))
25#define sizeudata(u) sizeludata((u)->len)
26
27#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ 24#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
28 (sizeof(s)/sizeof(char))-1)) 25 (sizeof(s)/sizeof(char))-1))
29 26
@@ -47,7 +44,7 @@ LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
47LUAI_FUNC void luaS_clearcache (global_State *g); 44LUAI_FUNC void luaS_clearcache (global_State *g);
48LUAI_FUNC void luaS_init (lua_State *L); 45LUAI_FUNC void luaS_init (lua_State *L);
49LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); 46LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
50LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); 47LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue);
51LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 48LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
52LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); 49LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
53LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); 50LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
diff --git a/ltests.c b/ltests.c
index 24753d5f..97d1abd4 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.239 2018/01/09 11:24:12 roberto Exp roberto $ 2** $Id: ltests.c,v 2.240 2018/01/28 15:13:26 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*/
@@ -265,6 +265,15 @@ static void checktable (global_State *g, Table *h) {
265} 265}
266 266
267 267
268static void checkudata (global_State *g, Udata *u) {
269 int i;
270 GCObject *hgc = obj2gco(u);
271 checkobjref(g, hgc, u->metatable);
272 for (i = 0; i < u->nuvalue; i++)
273 checkvalref(g, hgc, &u->uv[i].uv);
274}
275
276
268/* 277/*
269** All marks are conditional because a GC may happen while the 278** All marks are conditional because a GC may happen while the
270** prototype is still being created 279** prototype is still being created
@@ -287,7 +296,6 @@ static void checkproto (global_State *g, Proto *f) {
287} 296}
288 297
289 298
290
291static void checkCclosure (global_State *g, CClosure *cl) { 299static void checkCclosure (global_State *g, CClosure *cl) {
292 GCObject *clgc = obj2gco(cl); 300 GCObject *clgc = obj2gco(cl);
293 int i; 301 int i;
@@ -344,11 +352,7 @@ static void checkstack (global_State *g, lua_State *L1) {
344static void checkrefs (global_State *g, GCObject *o) { 352static void checkrefs (global_State *g, GCObject *o) {
345 switch (o->tt) { 353 switch (o->tt) {
346 case LUA_TUSERDATA: { 354 case LUA_TUSERDATA: {
347 TValue uservalue; 355 checkudata(g, gco2u(o));
348 Table *mt = gco2u(o)->metatable;
349 checkobjref(g, o, mt);
350 getuservalue(g->mainthread, gco2u(o), &uservalue);
351 checkvalref(g, o, &uservalue);
352 break; 356 break;
353 } 357 }
354 case LUA_TUPVAL: { 358 case LUA_TUPVAL: {
@@ -728,7 +732,7 @@ static int gc_color (lua_State *L) {
728 GCObject *obj = gcvalue(o); 732 GCObject *obj = gcvalue(o);
729 lua_pushstring(L, isdead(G(L), obj) ? "dead" : 733 lua_pushstring(L, isdead(G(L), obj) ? "dead" :
730 iswhite(obj) ? "white" : 734 iswhite(obj) ? "white" :
731 isblack(obj) ? "black" : "grey"); 735 isblack(obj) ? "black" : "gray");
732 } 736 }
733 return 1; 737 return 1;
734} 738}
@@ -919,8 +923,9 @@ static int upvalue (lua_State *L) {
919 923
920 924
921static int newuserdata (lua_State *L) { 925static int newuserdata (lua_State *L) {
922 size_t size = cast_sizet(luaL_checkinteger(L, 1)); 926 size_t size = cast_sizet(luaL_optinteger(L, 1, 0));
923 char *p = cast_charp(lua_newuserdata(L, size)); 927 int nuv = luaL_optinteger(L, 2, 0);
928 char *p = cast_charp(lua_newuserdatauv(L, size, nuv));
924 while (size--) *p++ = '\0'; 929 while (size--) *p++ = '\0';
925 return 1; 930 return 1;
926} 931}
diff --git a/lua.h b/lua.h
index d6277b4e..8fb2ccbe 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.339 2017/11/07 13:25:26 roberto Exp roberto $ 2** $Id: lua.h,v 1.340 2018/02/17 19:29:29 roberto Exp roberto $
3** Lua - A Scripting Language 3** Lua - A Scripting Language
4** Lua.org, PUC-Rio, Brazil (http://www.lua.org) 4** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
5** See Copyright Notice at the end of this file 5** See Copyright Notice at the end of this file
@@ -247,9 +247,9 @@ LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
247LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); 247LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
248 248
249LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); 249LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
250LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); 250LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
251LUA_API int (lua_getmetatable) (lua_State *L, int objindex); 251LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
252LUA_API int (lua_getuservalue) (lua_State *L, int idx); 252LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
253 253
254 254
255/* 255/*
@@ -263,7 +263,7 @@ LUA_API void (lua_rawset) (lua_State *L, int idx);
263LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); 263LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
264LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); 264LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
265LUA_API int (lua_setmetatable) (lua_State *L, int objindex); 265LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
266LUA_API void (lua_setuservalue) (lua_State *L, int idx); 266LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n);
267 267
268 268
269/* 269/*
@@ -380,7 +380,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
380 380
381/* 381/*
382** {============================================================== 382** {==============================================================
383** compatibility macros for unsigned conversions 383** compatibility macros
384** =============================================================== 384** ===============================================================
385*/ 385*/
386#if defined(LUA_COMPAT_APIINTCASTS) 386#if defined(LUA_COMPAT_APIINTCASTS)
@@ -390,6 +390,11 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
390#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) 390#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
391 391
392#endif 392#endif
393
394#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
395#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1)
396#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1)
397
393/* }============================================================== */ 398/* }============================================================== */
394 399
395/* 400/*