浏览代码

configuration for NaN trick big-endian + macro 'luai_checknum' to
ensure numbers comming from C are not "improper" (some kinds of
signaling NaNs)

Roberto Ierusalimschy 14 年之前
父节点
当前提交
fd80e63468
共有 3 个文件被更改,包括 50 次插入7 次删除
  1. 3 1
      lapi.c
  2. 19 2
      lobject.h
  3. 28 4
      luaconf.h

+ 3 - 1
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.147 2011/05/31 18:27:56 roberto Exp roberto $
+** $Id: lapi.c,v 2.148 2011/06/02 19:31:40 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -463,6 +463,8 @@ LUA_API void lua_pushnil (lua_State *L) {
 LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
   lua_lock(L);
   setnvalue(L->top, n);
+  luai_checknum(L, L->top,
+    luaG_runerror(L, "C API - attempt to push a signaling NaN"));
   api_incr_top(L);
   lua_unlock(L);
 }

+ 19 - 2
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.58 2011/06/07 19:02:33 roberto Exp roberto $
+** $Id: lobject.h,v 2.59 2011/06/09 18:21:25 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -262,7 +262,7 @@ typedef struct lua_TValue TValue;
 ** =======================================================
 */
 
-#if defined(LUA_NANTRICK)
+#if defined(LUA_NANTRICKLE) || defined(LUA_NANTRICKBE)
 
 /*
 ** numbers are represented in the 'd_' field. All other values have the
@@ -270,11 +270,20 @@ typedef struct lua_TValue TValue;
 ** a "signaled NaN", which is never generated by regular operations by
 ** the CPU (nor by 'strtod')
 */
+#if !defined(NNMARK)
 #define NNMARK		0x7FF7A500
+#endif
 
 #undef TValuefields
+#if defined(LUA_NANTRICKLE)
+/* little endian */
 #define TValuefields  \
 	union { struct { Value v_; int tt_; } i; double d_; } u
+#else
+/* big endian */
+#define TValuefields  \
+	union { struct { int tt_; Value v_; } i; double d_; } u
+#endif
 
 #undef numfield
 #define numfield	/* no such field; numbers are the entire struct */
@@ -322,6 +331,14 @@ typedef struct lua_TValue TValue;
 	(ttisnumber(o1) ? ttisnumber(o2) : ((o1)->u.i.tt_ == (o2)->u.i.tt_))
 
 
+
+#define luai_checknum(L,o,c)	{ if (!ttisnumber(o)) c; }
+
+
+#else
+
+#define luai_checknum(L,o,c)	{ /* empty */ }
+
 #endif
 /* }====================================================== */
 

+ 28 - 4
luaconf.h

@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.157 2011/04/29 13:56:28 roberto Exp roberto $
+** $Id: luaconf.h,v 1.158 2011/05/26 16:09:40 roberto Exp roberto $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */
@@ -465,11 +465,11 @@
 
 /*
 @@ LUA_IEEEENDIAN is the endianness of doubles in your machine
-@@ (0 for little endian, 1 for big endian); if not defined, Lua will
-@@ check it dynamically.
+** (0 for little endian, 1 for big endian); if not defined, Lua will
+** check it dynamically.
 */
 /* check for known architectures */
-#if defined(__i386__) || defined(__i386) || defined(i386) || \
+#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
     defined (__x86_64)
 #define LUA_IEEEENDIAN	0
 #elif defined(__POWERPC__) || defined(__ppc__)
@@ -485,6 +485,30 @@
 /* }================================================================== */
 
 
+/*
+@@ LUA_NANTRICKLE/LUA_NANTRICKBE controls the use of a trick to pack all
+** types into a single double value, using NaN values to represent
+** non-number values. The trick only works on 32-bit machines (ints and
+** pointers are 32-bit values) with numbers represented as IEEE 754-2008
+** doubles with conventional endianess (12345678 or 87654321), in CPUs
+** that do not produce signaling NaN values (all NaNs are quiet).
+*/
+#if defined(LUA_CORE)		/* { */
+
+#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI)	/* { */
+
+/* little-endian architectures that satisfy those conditions */
+#if defined(__i386__) || defined(__i386) || defined(__X86__)
+
+#define LUA_NANTRICKLE
+
+#endif
+
+#endif							/* } */
+
+#endif			/* } */
+
+
 
 
 /* =================================================================== */