From 237969724f54eeefee057ae382237c8db54af44e Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 5 Apr 2002 15:54:31 -0300
Subject: [PATCH] support for `light' userdata + simpler support for `boxed'
 udata

---
 lapi.c     | 44 ++++++++++++++++++++------------------------
 lbaselib.c | 11 ++++++-----
 lgc.c      |  5 +++--
 liolib.c   |  8 ++++----
 lobject.c  |  6 ++++--
 lobject.h  | 17 ++++++++---------
 lstring.c  |  3 +--
 ltable.c   |  6 ++++--
 ltests.c   | 10 +++++-----
 ltm.c      |  5 +++--
 lua.c      |  4 ++--
 lua.h      | 16 +++++++++++-----
 12 files changed, 71 insertions(+), 64 deletions(-)

diff --git a/lapi.c b/lapi.c
index ae96ef86..9edc043f 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.181 2002/03/27 12:49:53 roberto Exp roberto $
+** $Id: lapi.c,v 1.182 2002/04/02 20:43:18 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -278,7 +278,12 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) {
 
 LUA_API void *lua_touserdata (lua_State *L, int index) {
   StkId o = luaA_indexAcceptable(L, index);
-  return (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : uvalue(o)->uv.value;
+  if (o == NULL) return NULL;
+  switch (ttype(o)) {
+    case LUA_TUSERDATA: return (uvalue(o) + 1);
+    case LUA_TUDATAVAL: return pvalue(o);
+    default: return NULL;
+  }
 }
 
 
@@ -356,6 +361,14 @@ LUA_API void lua_pushboolean (lua_State *L, int b) {
 }
 
 
+LUA_API void lua_pushudataval (lua_State *L, void *p) {
+  lua_lock(L);
+  setpvalue(L->top, p);
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
 
 /*
 ** get functions (Lua -> stack)
@@ -472,7 +485,7 @@ LUA_API void lua_setmetatable (lua_State *L, int objindex) {
   StkId obj, mt;
   lua_lock(L);
   api_checknelems(L, 1);
-  obj = luaA_indexAcceptable(L, objindex);
+  obj = luaA_index(L, objindex);
   mt = --L->top;
   if (ttype(mt) == LUA_TNIL)
     mt = defaultmeta(L);
@@ -649,31 +662,14 @@ LUA_API void lua_concat (lua_State *L, int n) {
 }
 
 
-static Udata *pushnewudata (lua_State *L, size_t size) {
-  Udata *u = luaS_newudata(L, size);
-  setuvalue(L->top, u);
-  api_incr_top(L);
-  return uvalue(L->top-1);
-}
-
-
 LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
   Udata *u;
-  void *p;
   lua_lock(L);
-  u = pushnewudata(L, size);
-  p = u->uv.value;
-  lua_unlock(L);
-  return p;
-}
-
-
-LUA_API void lua_newuserdatabox (lua_State *L, void *p) {
-  Udata *u;
-  lua_lock(L);
-  u = pushnewudata(L, 0);
-  u->uv.value = p;
+  u = luaS_newudata(L, size);
+  setuvalue(L->top, u);
+  api_incr_top(L);
   lua_unlock(L);
+  return u + 1;
 }
 
 
diff --git a/lbaselib.c b/lbaselib.c
index dae741b3..b8d0bacb 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.62 2002/03/27 15:30:41 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.63 2002/04/02 20:42:20 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -206,7 +206,7 @@ static int passresults (lua_State *L, int status, int oldtop) {
     if (nresults > 0)
       return nresults;  /* results are already on the stack */
     else {
-      lua_newuserdatabox(L, NULL); /* at least one result to signal no errors */
+      lua_pushboolean(L, 1); /* at least one result to signal no errors */
       return 1;
     }
   }
@@ -383,6 +383,7 @@ static int luaB_tostring (lua_State *L) {
       sprintf(buff, "function: %p", lua_topointer(L, 1));
       break;
     case LUA_TUSERDATA:
+    case LUA_TUDATAVAL:
       sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
       break;
     case LUA_TNIL:
@@ -439,7 +440,7 @@ static void base_open (lua_State *L) {
 
 
 static int luaB_resume (lua_State *L) {
-  lua_State *co = (lua_State *)lua_touserdata(L, lua_upvalueindex(1));
+  lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1));
   if (lua_resume(L, co) != 0)
     lua_error(L, "error running co-routine");
   return lua_gettop(L);
@@ -448,7 +449,7 @@ static int luaB_resume (lua_State *L) {
 
 
 static int gc_coroutine (lua_State *L) {
-  lua_State *co = (lua_State *)lua_touserdata(L, 1);
+  lua_State *co = (lua_State *)lua_getfrombox(L, 1);
   lua_closethread(L, co);
   return 0;
 }
@@ -471,7 +472,7 @@ static int luaB_coroutine (lua_State *L) {
     lua_unref(L, ref);
   }
   lua_cobegin(NL, n-1);
-  lua_newuserdatabox(L, NL);
+  lua_newpointerbox(L, NL);
   lua_pushliteral(L, "Coroutine");
   lua_rawget(L, LUA_REGISTRYINDEX);
   lua_setmetatable(L, -2);
diff --git a/lgc.c b/lgc.c
index b08657bd..f1d00e09 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.132 2002/03/20 18:54:29 roberto Exp roberto $
+** $Id: lgc.c,v 1.133 2002/03/26 18:55:50 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -46,7 +46,8 @@ typedef struct GCState {
 
 
 #define ismarkable(o)	(!((1 << ttype(o)) & \
-	((1 << LUA_TNIL) | (1 << LUA_TNUMBER) | (1 << LUA_TBOOLEAN))))
+	((1 << LUA_TNIL)     | (1 << LUA_TNUMBER) | \
+	 (1 << LUA_TBOOLEAN) | (1 << LUA_TUDATAVAL))))
 
 static void reallymarkobject (GCState *st, TObject *o);
 
diff --git a/liolib.c b/liolib.c
index 71e7ca46..4260534d 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 1.133 2002/03/27 15:30:41 roberto Exp roberto $
+** $Id: liolib.c,v 2.1 2002/04/04 20:24:56 roberto Exp roberto $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -54,11 +54,11 @@ static int pushresult (lua_State *L, int i) {
 
 
 static FILE *tofile (lua_State *L, int findex) {
-  FILE *f = (FILE *)lua_touserdata(L, findex);
+  FILE **f = (FILE **)lua_touserdata(L, findex);
   if (f && lua_getmetatable(L, findex) &&
       lua_equal(L, -1, lua_upvalueindex(1))) {
     lua_pop(L, 1);
-    return f;
+    return *f;
   }
   luaL_argerror(L, findex, "bad file");
   return NULL;  /* to avoid warnings */
@@ -66,7 +66,7 @@ static FILE *tofile (lua_State *L, int findex) {
 
 
 static void newfile (lua_State *L, FILE *f) {
-  lua_newuserdatabox(L, f);
+  lua_newpointerbox(L, f);
   lua_pushliteral(L, FILEHANDLE);
   lua_rawget(L, LUA_REGISTRYINDEX);
   lua_setmetatable(L, -2);
diff --git a/lobject.c b/lobject.c
index d44e041d..41b193cf 100644
--- a/lobject.c
+++ b/lobject.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
+** $Id: lobject.c,v 1.75 2002/02/07 17:25:12 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -59,7 +59,9 @@ int luaO_equalObj (const TObject *t1, const TObject *t2) {
       return 1;
     case LUA_TBOOLEAN:
       return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
-    default:  /* all other types are equal if pointers are equal */
+    case LUA_TUDATAVAL:
+      return pvalue(t1) == pvalue(t2);
+    default:  /* other types are equal if struct pointers are equal */
       return tsvalue(t1) == tsvalue(t2);
   }
 }
diff --git a/lobject.h b/lobject.h
index dca2531a..a7286927 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.127 2002/03/18 18:16:16 roberto Exp roberto $
+** $Id: lobject.h,v 1.128 2002/03/25 17:47:14 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -13,15 +13,15 @@
 
 
 /* tags for values visible from Lua */
-#define NUM_TAGS	6
+#define NUM_TAGS	LUA_TFUNCTION
 
 
 typedef union {
+  void *p;
   union TString *ts;
   union Udata *u;
   union Closure *cl;
   struct Table *h;
-  struct lua_TObject *v;
   lua_Number n;
   int b;
 } Value;
@@ -35,12 +35,12 @@ typedef struct lua_TObject {
 
 /* Macros to access values */
 #define ttype(o)        ((o)->tt)
+#define pvalue(o)	((o)->value.p)
 #define nvalue(o)       ((o)->value.n)
 #define tsvalue(o)      ((o)->value.ts)
 #define uvalue(o)      ((o)->value.u)
 #define clvalue(o)      ((o)->value.cl)
 #define hvalue(o)       ((o)->value.h)
-#define vvalue(o)	((o)->value.v)
 #define bvalue(o)	((o)->value.b)
 
 #define l_isfalse(o)	(ttype(o) == LUA_TNIL || \
@@ -52,6 +52,9 @@ typedef struct lua_TObject {
 
 #define chgnvalue(obj,x)	((obj)->value.n=(x))
 
+#define setpvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TUDATAVAL; i_o->value.p=(x); }
+
 #define setbvalue(obj,x) \
   { TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); }
 
@@ -69,9 +72,6 @@ typedef struct lua_TObject {
 
 #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
 
-#define setupvalue(obj,x,t) \
-  { TObject *i_o=(obj); i_o->tt=(t); i_o->value.v=(x); }
-
 #define setobj(obj1,obj2) \
   { TObject *o1=(obj1); const TObject *o2=(obj2); \
     o1->tt=o2->tt; o1->value = o2->value; }
@@ -106,9 +106,8 @@ typedef union Udata {
   union L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
   struct {
     struct Table *metatable;
-    void *value;
     union Udata *next;  /* chain for list of all udata */
-    size_t len;  /* least bit reserved for gc mark */
+    size_t len;  /* least 2 bits reserved for gc mark */
   } uv;
 } Udata;
 
diff --git a/lstring.c b/lstring.c
index a1ec6b80..fa19309c 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.72 2002/02/08 22:41:09 roberto Exp roberto $
+** $Id: lstring.c,v 1.73 2002/03/20 18:37:13 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -89,7 +89,6 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
   u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
   u->uv.len = s;
   u->uv.metatable = hvalue(defaultmeta(L));
-  u->uv.value = u + 1;
   /* chain it on udata list */
   u->uv.next = G(L)->rootudata;
   G(L)->rootudata = u;
diff --git a/ltable.c b/ltable.c
index d0feafef..c71179d1 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.101 2002/02/14 21:41:08 roberto Exp roberto $
+** $Id: ltable.c,v 1.102 2002/03/18 18:18:35 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -73,7 +73,9 @@ Node *luaH_mainposition (const Table *t, const TObject *key) {
       return hashstr(t, tsvalue(key));
     case LUA_TBOOLEAN:
       return hashboolean(t, bvalue(key));
-    default:  /* all other types are hashed as (void *) */
+    case LUA_TUDATAVAL:
+      return hashpointer(t, pvalue(key));
+    default:  /* other types are hashed as (struct *) */
       return hashpointer(t, tsvalue(key));
   }
 }
diff --git a/ltests.c b/ltests.c
index b21ffc62..4893b312 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.114 2002/03/25 17:47:14 roberto Exp roberto $
+** $Id: ltests.c,v 1.115 2002/04/02 20:43:08 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -368,14 +368,14 @@ static int newuserdata (lua_State *L) {
   return 1;
 }
 
-static int newuserdatabox (lua_State *L) {
-  lua_newuserdatabox(L, cast(void *, luaL_check_int(L, 1)));
+
+static int pushuserdata (lua_State *L) {
+  lua_pushudataval(L, cast(void *, luaL_check_int(L, 1)));
   return 1;
 }
 
 
 static int udataval (lua_State *L) {
-  luaL_check_type(L, 1, LUA_TUSERDATA);
   lua_pushnumber(L, cast(int, lua_touserdata(L, 1)));
   return 1;
 }
@@ -662,7 +662,7 @@ static const struct luaL_reg tests_funcs[] = {
   {"s2d", s2d},
   {"metatable", metatable},
   {"newuserdata", newuserdata},
-  {"newuserdatabox", newuserdatabox},
+  {"pushuserdata", pushuserdata},
   {"udataval", udataval},
   {"doonnewstack", doonnewstack},
   {"newstate", newstate},
diff --git a/ltm.c b/ltm.c
index e53f49cb..5a4c72ac 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 1.87 2002/02/14 21:40:29 roberto Exp roberto $
+** $Id: ltm.c,v 1.88 2002/03/18 20:24:14 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -19,7 +19,8 @@
 
 
 const char *const luaT_typenames[] = {
-  "nil", "number", "string", "boolean", "table", "userdata", "function"
+  "nil", "number", "string", "boolean", "table",
+  "userdata", "userdata", "function"
 };
 
 
diff --git a/lua.c b/lua.c
index 58c4d28a..d9d8a4f0 100644
--- a/lua.c
+++ b/lua.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.79 2002/03/27 18:00:13 roberto Exp roberto $
+** $Id: lua.c,v 1.80 2002/04/01 14:42:33 roberto Exp roberto $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -334,7 +334,7 @@ static int handle_argv (char *argv[], int *toclose) {
 
 
 static void register_getargs (char *argv[]) {
-  lua_newuserdatabox(L, argv);
+  lua_pushudataval(L, argv);
   lua_pushcclosure(L, l_getargs, 1);
   lua_setglobal(L, "getargs");
 }
diff --git a/lua.h b/lua.h
index 6bfe8b0f..73e60082 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.124 2002/03/27 12:49:53 roberto Exp roberto $
+** $Id: lua.h,v 1.125 2002/03/27 15:30:41 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
 ** e-mail: info@lua.org
@@ -17,8 +17,8 @@
 
 
 
-#define LUA_VERSION	"Lua 4.1 (beta)"
-#define LUA_COPYRIGHT	"Copyright (C) 1994-2001 TeCGraf, PUC-Rio"
+#define LUA_VERSION	"Lua 5.0 (alpha)"
+#define LUA_COPYRIGHT	"Copyright (C) 1994-2002 TeCGraf, PUC-Rio"
 #define LUA_AUTHORS 	"W. Celes, R. Ierusalimschy & L. H. de Figueiredo"
 
 
@@ -63,7 +63,8 @@ typedef int (*lua_CFunction) (lua_State *L);
 #define LUA_TBOOLEAN	3
 #define LUA_TTABLE	4
 #define LUA_TUSERDATA	5
-#define LUA_TFUNCTION	6
+#define LUA_TUDATAVAL	6
+#define LUA_TFUNCTION	7
 
 
 /* minimum Lua stack available to a C function */
@@ -143,6 +144,7 @@ LUA_API void  lua_pushlstring (lua_State *L, const char *s, size_t len);
 LUA_API void  lua_pushstring (lua_State *L, const char *s);
 LUA_API void  lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
 LUA_API void  lua_pushboolean (lua_State *L, int b);
+LUA_API void  lua_pushudataval (lua_State *L, void *p);
 
 
 /*
@@ -204,7 +206,6 @@ LUA_API int   lua_getn (lua_State *L, int index);
 LUA_API void  lua_concat (lua_State *L, int n);
 
 LUA_API void *lua_newuserdata (lua_State *L, size_t size);
-LUA_API void  lua_newuserdatabox (lua_State *L, void *u);
 
 
 
@@ -214,6 +215,11 @@ LUA_API void  lua_newuserdatabox (lua_State *L, void *u);
 ** ===============================================================
 */
 
+#define lua_newpointerbox(L,u) \
+	(*(void **)(lua_newuserdata(L, sizeof(void *))) = (u))
+
+#define lua_getfrombox(L,i)	(*(void **)(lua_touserdata(L, i)))
+
 #define lua_pop(L,n)		lua_settop(L, -(n)-1)
 
 #define lua_register(L,n,f) \