+
+/* maximum number of significant digits to read (to avoid overflows
+ even with single floats) */
+#define MAXSIGDIG 30
/*
** convert an hexadecimal numeric string to a number, following
** C99 specification for 'strtod'
*/
static lua_Number lua_strx2number (const char *s, char **endptr) {
- lua_Number r = 0.0;
- int e = 0, i = 0;
- int neg = 0; /* 1 if number is negative */
+ lua_Number r = 0.0; /* result (accumulator) */
+ int sigdig = 0; /* number of significant digits */
+ int nosigdig = 0; /* number of non-significant digits */
+ int e = 0; /* exponent correction */
+ int neg; /* 1 if number is negative */
+ int dot = 0; /* true after seen a dot */
*endptr = cast(char *, s); /* nothing is valid yet */
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check signal */
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
return 0.0; /* invalid format (no '0x') */
- s += 2; /* skip '0x' */
- r = readhexa(&s, r, &i); /* read integer part */
- if (*s == '.') {
- s++; /* skip dot */
- r = readhexa(&s, r, &e); /* read fractional part */
+ for (s += 2; ; s++) { /* skip '0x' and read numeral */
+ if (*s == '.') {
+ if (dot) break; /* second dot? stop loop */
+ else dot = 1;
+ }
+ else if (lisxdigit(cast_uchar(*s))) {
+ if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
+ nosigdig++;
+ else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
+ r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
+ else e++; /* too many digits; ignore, but still count for exponent */
+ if (dot) e--; /* decimal digit? correct exponent */
+ }
+ else break; /* neither a dot nor a digit */
}
- if (i == 0 && e == 0)
- return 0.0; /* invalid format (no digit) */
- e *= -4; /* each fractional digit divides value by 2^-4 */
+ if (nosigdig + sigdig == 0) /* no digits? */
+ return 0.0; /* invalid format */
*endptr = cast(char *, s); /* valid up to here */
+ e *= 4; /* each digit multiplies/divides value by 2^4 */
if (*s == 'p' || *s == 'P') { /* exponent part? */
- int exp1 = 0;
- int neg1;
+ int exp1 = 0; /* exponent value */
+ int neg1; /* exponent signal */
s++; /* skip 'p' */
neg1 = isneg(&s); /* signal */
if (!lisdigit(cast_uchar(*s)))
- goto ret; /* must have at least one digit */
+ return 0.0; /* invalid; must have at least one digit */
while (lisdigit(cast_uchar(*s))) /* read exponent */
exp1 = exp1 * 10 + *(s++) - '0';
if (neg1) exp1 = -exp1;
e += exp1;
+ *endptr = cast(char *, s); /* valid up to here */
}
- *endptr = cast(char *, s); /* valid up to here */
- ret:
if (neg) r = -r;
return l_mathop(ldexp)(r, e);
}
#endif
+/* }====================================================== */
-int luaO_str2d (const char *s, size_t len, lua_Number *result) {
+static const char *l_str2d (const char *s, lua_Number *result) {
char *endptr;
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
- return 0;
- else if (strpbrk(s, "xX")) /* hexa? */
+ return NULL;
+ else if (strpbrk(s, "xX")) /* hex? */
*result = lua_strx2number(s, &endptr);
else
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* nothing recognized */
while (lisspace(cast_uchar(*endptr))) endptr++;
- return (endptr == s + len); /* OK if no trailing characters */
+ return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
}
+static const char *l_str2int (const char *s, lua_Integer *result) {
+ lua_Unsigned a = 0;
+ int empty = 1;
+ int neg;
+ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
+ neg = isneg(&s);
+ if (s[0] == '0' &&
+ (s[1] == 'x' || s[1] == 'X')) { /* hex? */
+ s += 2; /* skip '0x' */
+ for (; lisxdigit(cast_uchar(*s)); s++) {
+ a = a * 16 + luaO_hexavalue(*s);
+ empty = 0;
+ }
+ }
+ else { /* decimal */
+ for (; lisdigit(cast_uchar(*s)); s++) {
+ a = a * 10 + *s - '0';
+ empty = 0;
+ }
+ }
+ while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */
+ if (empty || *s != '\0') return NULL; /* something wrong in the numeral */
+ else {
+ *result = l_castU2S((neg) ? 0u - a : a);
+ return s;
+ }
+}
+
+
+size_t luaO_str2num (const char *s, TValue *o) {
+ lua_Integer i; lua_Number n;
+ const char *e;
+ if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */
+ setivalue(o, i);
+ }
+ else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */
+ setfltvalue(o, n);
+ }
+ else
+ return 0; /* conversion failed */
+ return (e - s + 1); /* success; return string size */
+}
+
+
+int luaO_utf8esc (char *buff, unsigned long x) {
+ int n = 1; /* number of bytes put in buffer (backwards) */
+ lua_assert(x <= 0x10FFFF);
+ if (x < 0x80) /* ascii? */
+ buff[UTF8BUFFSZ - 1] = cast(char, x);
+ else { /* need continuation bytes */
+ unsigned int mfb = 0x3f; /* maximum that fits in first byte */
+ do { /* add continuation bytes */
+ buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f));
+ x >>= 6; /* remove added bits */
+ mfb >>= 1; /* now there is one less bit available in first byte */
+ } while (x > mfb); /* still needs continuation byte? */
+ buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */
+ }
+ return n;
+}
+
+
+/* maximum length of the conversion of a number to a string */
+#define MAXNUMBER2STR 50
+
+
+/*
+** Convert a number object to a string
+*/
+void luaO_tostring (lua_State *L, StkId obj) {
+ char buff[MAXNUMBER2STR];
+ size_t len;
+ lua_assert(ttisnumber(obj));
+ if (ttisinteger(obj))
+ len = lua_integer2str(buff, ivalue(obj));
+ else {
+ len = lua_number2str(buff, fltvalue(obj));
+#if !defined(LUA_COMPAT_FLOATSTRING)
+ if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
+ buff[len++] = '.';
+ buff[len++] = '0'; /* adds '.0' to result */
+ }
+#endif
+ }
+ setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
+}
+
static void pushstr (lua_State *L, const char *str, size_t l) {
setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
}
-/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
+/* this function handles only '%d', '%c', '%f', '%p', and '%s'
+ conventional formats, plus Lua-specific '%I' and '%U' */
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 0;
for (;;) {
@@ -191,33 +360,47 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
break;
}
case 'c': {
- char buff;
- buff = cast(char, va_arg(argp, int));
- pushstr(L, &buff, 1);
+ char buff = cast(char, va_arg(argp, int));
+ if (lisprint(cast_uchar(buff)))
+ pushstr(L, &buff, 1);
+ else /* non-printable character; print its code */
+ luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
break;
}
case 'd': {
- setnvalue(L->top++, cast_num(va_arg(argp, int)));
+ setivalue(L->top++, va_arg(argp, int));
+ luaO_tostring(L, L->top - 1);
+ break;
+ }
+ case 'I': {
+ setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
+ luaO_tostring(L, L->top - 1);
break;
}
case 'f': {
- setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
+ setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
+ luaO_tostring(L, L->top - 1);
break;
}
case 'p': {
- char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
int l = sprintf(buff, "%p", va_arg(argp, void *));
pushstr(L, buff, l);
break;
}
+ case 'U': {
+ char buff[UTF8BUFFSZ];
+ int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
+ pushstr(L, buff + UTF8BUFFSZ - l, l);
+ break;
+ }
case '%': {
pushstr(L, "%", 1);
break;
}
default: {
- luaG_runerror(L,
- "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
- *(e + 1));
+ luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'",
+ *(e + 1));
}
}
n += 2;
diff --git a/luaxx/lobject.h b/luaxx/lobject.h
index 3a630b94..d7d0ebf3 100644
--- a/luaxx/lobject.h
+++ b/luaxx/lobject.h
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.h,v 2.71.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -20,13 +20,12 @@
** Extra tags for non-values
*/
#define LUA_TPROTO LUA_NUMTAGS
-#define LUA_TUPVAL (LUA_NUMTAGS+1)
-#define LUA_TDEADKEY (LUA_NUMTAGS+2)
+#define LUA_TDEADKEY (LUA_NUMTAGS+1)
/*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
*/
-#define LUA_TOTALTAGS (LUA_TUPVAL+2)
+#define LUA_TOTALTAGS (LUA_TPROTO + 2)
/*
@@ -57,6 +56,11 @@
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
+/* Variant tags for numbers */
+#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */
+#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */
+
+
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)
@@ -65,9 +69,9 @@
/*
-** Union of all collectable objects
+** Common type for all collectable objects
*/
-typedef union GCObject GCObject;
+typedef struct GCObject GCObject;
/*
@@ -78,11 +82,11 @@ typedef union GCObject GCObject;
/*
-** Common header in struct form
+** Common type has only the common header
*/
-typedef struct GCheader {
+struct GCObject {
CommonHeader;
-} GCheader;
+};
@@ -92,8 +96,6 @@ typedef struct GCheader {
typedef union Value Value;
-#define numfield lua_Number n; /* numbers */
-
/*
@@ -111,7 +113,6 @@ typedef struct lua_TValue TValue;
#define val_(o) ((o)->value_)
-#define num_(o) (val_(o).n)
/* raw type tag of a TValue */
@@ -124,13 +125,15 @@ typedef struct lua_TValue TValue;
#define ttype(o) (rttype(o) & 0x3F)
/* type tag of a TValue with no variants (bits 0-3) */
-#define ttypenv(o) (novariant(rttype(o)))
+#define ttnov(o) (novariant(rttype(o)))
/* Macros to test type */
#define checktag(o,t) (rttype(o) == (t))
-#define checktype(o,t) (ttypenv(o) == (t))
-#define ttisnumber(o) checktag((o), LUA_TNUMBER)
+#define checktype(o,t) (ttnov(o) == (t))
+#define ttisnumber(o) checktype((o), LUA_TNUMBER)
+#define ttisfloat(o) checktag((o), LUA_TNUMFLT)
+#define ttisinteger(o) checktag((o), LUA_TNUMINT)
#define ttisnil(o) checktag((o), LUA_TNIL)
#define ttisboolean(o) checktag((o), LUA_TBOOLEAN)
#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
@@ -143,27 +146,27 @@ typedef struct lua_TValue TValue;
#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL))
#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL))
#define ttislcf(o) checktag((o), LUA_TLCF)
-#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA))
+#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
-#define ttisequal(o1,o2) (rttype(o1) == rttype(o2))
/* Macros to access values */
-#define nvalue(o) check_exp(ttisnumber(o), num_(o))
+#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
+#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
+#define nvalue(o) check_exp(ttisnumber(o), \
+ (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
-#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts)
-#define tsvalue(o) (&rawtsvalue(o)->tsv)
-#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u)
-#define uvalue(o) (&rawuvalue(o)->uv)
-#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl)
-#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l)
-#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c)
+#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc))
+#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
+#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
+#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
+#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
-#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h)
+#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
-#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th)
+#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
/* a dead value may get the 'gc' field, but cannot access its contents */
#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
@@ -174,7 +177,7 @@ typedef struct lua_TValue TValue;
/* Macros for internal tests */
-#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt)
+#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt)
#define checkliveness(g,obj) \
lua_longassert(!iscollectable(obj) || \
@@ -184,8 +187,11 @@ typedef struct lua_TValue TValue;
/* Macros to set values */
#define settt_(o,t) ((o)->tt_=(t))
-#define setnvalue(obj,x) \
- { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); }
+#define setfltvalue(obj,x) \
+ { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
+
+#define setivalue(obj,x) \
+ { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
@@ -199,38 +205,37 @@ typedef struct lua_TValue TValue;
{ TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); }
#define setgcovalue(L,obj,x) \
- { TValue *io=(obj); GCObject *i_g=(x); \
- val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); }
+ { TValue *io = (obj); GCObject *i_g=(x); \
+ val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
#define setsvalue(L,obj,x) \
- { TValue *io=(obj); \
- TString *x_ = (x); \
- val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \
+ { TValue *io = (obj); TString *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
checkliveness(G(L),io); }
#define setuvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \
+ { TValue *io = (obj); Udata *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
checkliveness(G(L),io); }
#define setthvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \
+ { TValue *io = (obj); lua_State *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
checkliveness(G(L),io); }
#define setclLvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \
+ { TValue *io = (obj); LClosure *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
checkliveness(G(L),io); }
#define setclCvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \
+ { TValue *io = (obj); CClosure *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
checkliveness(G(L),io); }
#define sethvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
+ { TValue *io = (obj); Table *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(G(L),io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
@@ -238,9 +243,8 @@ typedef struct lua_TValue TValue;
#define setobj(L,obj1,obj2) \
- { const TValue *io2=(obj2); TValue *io1=(obj1); \
- io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
- checkliveness(G(L),io1); }
+ { TValue *io1=(obj1); *io1 = *(obj2); \
+ (void)L; checkliveness(G(L),io1); }
/*
@@ -263,119 +267,6 @@ typedef struct lua_TValue TValue;
#define setsvalue2n setsvalue
-/* check whether a number is valid (useful only for NaN trick) */
-#define luai_checknum(L,o,c) { /* empty */ }
-
-
-/*
-** {======================================================
-** NaN Trick
-** =======================================================
-*/
-#if defined(LUA_NANTRICK)
-
-/*
-** numbers are represented in the 'd_' field. All other values have the
-** value (NNMARK | tag) in 'tt__'. A number with such pattern would be
-** a "signaled NaN", which is never generated by regular operations by
-** the CPU (nor by 'strtod')
-*/
-
-/* allows for external implementation for part of the trick */
-#if !defined(NNMARK) /* { */
-
-
-#if !defined(LUA_IEEEENDIAN)
-#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN'
-#endif
-
-
-#define NNMARK 0x7FF7A500
-#define NNMASK 0x7FFFFF00
-
-#undef TValuefields
-#undef NILCONSTANT
-
-#if (LUA_IEEEENDIAN == 0) /* { */
-
-/* little endian */
-#define TValuefields \
- union { struct { Value v__; int tt__; } i; double d__; } u
-#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}}
-/* field-access macros */
-#define v_(o) ((o)->u.i.v__)
-#define d_(o) ((o)->u.d__)
-#define tt_(o) ((o)->u.i.tt__)
-
-#else /* }{ */
-
-/* big endian */
-#define TValuefields \
- union { struct { int tt__; Value v__; } i; double d__; } u
-#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}}
-/* field-access macros */
-#define v_(o) ((o)->u.i.v__)
-#define d_(o) ((o)->u.d__)
-#define tt_(o) ((o)->u.i.tt__)
-
-#endif /* } */
-
-#endif /* } */
-
-
-/* correspondence with standard representation */
-#undef val_
-#define val_(o) v_(o)
-#undef num_
-#define num_(o) d_(o)
-
-
-#undef numfield
-#define numfield /* no such field; numbers are the entire struct */
-
-/* basic check to distinguish numbers from non-numbers */
-#undef ttisnumber
-#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK)
-
-#define tag2tt(t) (NNMARK | (t))
-
-#undef rttype
-#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff)
-
-#undef settt_
-#define settt_(o,t) (tt_(o) = tag2tt(t))
-
-#undef setnvalue
-#define setnvalue(obj,x) \
- { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); }
-
-#undef setobj
-#define setobj(L,obj1,obj2) \
- { const TValue *o2_=(obj2); TValue *o1_=(obj1); \
- o1_->u = o2_->u; \
- checkliveness(G(L),o1_); }
-
-
-/*
-** these redefinitions are not mandatory, but these forms are more efficient
-*/
-
-#undef checktag
-#undef checktype
-#define checktag(o,t) (tt_(o) == tag2tt(t))
-#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS))
-
-#undef ttisequal
-#define ttisequal(o1,o2) \
- (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
-
-
-#undef luai_checknum
-#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; }
-
-#endif
-/* }====================================================== */
-
/*
@@ -390,7 +281,8 @@ union Value {
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
- numfield /* numbers */
+ lua_Integer i; /* integer numbers */
+ lua_Number n; /* float numbers */
};
@@ -406,39 +298,78 @@ typedef TValue *StkId; /* index to stack elements */
/*
** Header for string value; string bytes follow the end of this structure
+** (aligned according to 'UTString'; see next).
*/
-typedef union TString {
- L_Umaxalign dummy; /* ensures maximum alignment for strings */
- struct {
- CommonHeader;
- lu_byte extra; /* reserved words for short strings; "has hash" for longs */
- unsigned int hash;
- size_t len; /* number of characters in string */
- } tsv;
+typedef struct TString {
+ CommonHeader;
+ lu_byte extra; /* reserved words for short strings; "has hash" for longs */
+ unsigned int hash;
+ size_t len; /* number of characters in string */
+ struct TString *hnext; /* linked list for hash table */
} TString;
-/* get the actual string (array of bytes) from a TString */
-#define getstr(ts) cast(const char *, (ts) + 1)
+/*
+** Ensures that address after this type is always fully aligned.
+*/
+typedef union UTString {
+ L_Umaxalign dummy; /* ensures maximum alignment for strings */
+ TString tsv;
+} UTString;
+
+
+/*
+** Get the actual string (array of bytes) from a 'TString'.
+** (Access to 'extra' ensures that value is really a 'TString'.)
+*/
+#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString))
+#define getstr(ts) \
+ check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts)))
/* get the actual string (array of bytes) from a Lua value */
-#define svalue(o) getstr(rawtsvalue(o))
+#define svalue(o) getstr(tsvalue(o))
/*
** Header for userdata; memory area follows the end of this structure
+** (aligned according to 'UUdata'; see next).
*/
-typedef union Udata {
- L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
- struct {
- CommonHeader;
- struct Table *metatable;
- struct Table *env;
- size_t len; /* number of bytes */
- } uv;
+typedef struct Udata {
+ CommonHeader;
+ lu_byte ttuv_; /* user value's tag */
+ struct Table *metatable;
+ size_t len; /* number of bytes */
+ union Value user_; /* user value */
} Udata;
+/*
+** Ensures that address after this type is always fully aligned.
+*/
+typedef union UUdata {
+ L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */
+ Udata uv;
+} UUdata;
+
+
+/*
+** Get the address of memory block inside 'Udata'.
+** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
+*/
+#define getudatamem(u) \
+ check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata)))
+
+#define setuservalue(L,u,o) \
+ { const TValue *io=(o); Udata *iu = (u); \
+ iu->user_ = io->value_; iu->ttuv_ = io->tt_; \
+ checkliveness(G(L),io); }
+
+
+#define getuservalue(L,u,o) \
+ { TValue *io=(o); const Udata *iu = (u); \
+ io->value_ = iu->user_; io->tt_ = iu->ttuv_; \
+ checkliveness(G(L),io); }
+
/*
** Description of an upvalue for function prototypes
@@ -466,26 +397,26 @@ typedef struct LocVar {
*/
typedef struct Proto {
CommonHeader;
+ lu_byte numparams; /* number of fixed parameters */
+ lu_byte is_vararg;
+ lu_byte maxstacksize; /* maximum stack used by this function */
+ int sizeupvalues; /* size of 'upvalues' */
+ int sizek; /* size of 'k' */
+ int sizecode;
+ int sizelineinfo;
+ int sizep; /* size of 'p' */
+ int sizelocvars;
+ int linedefined;
+ int lastlinedefined;
TValue *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines (debug information) */
LocVar *locvars; /* information about local variables (debug information) */
Upvaldesc *upvalues; /* upvalue information */
- union Closure *cache; /* last created closure with this prototype */
+ struct LClosure *cache; /* last created closure with this prototype */
TString *source; /* used for debug information */
- int sizeupvalues; /* size of 'upvalues' */
- int sizek; /* size of `k' */
- int sizecode;
- int sizelineinfo;
- int sizep; /* size of `p' */
- int sizelocvars;
- int linedefined;
- int lastlinedefined;
GCObject *gclist;
- lu_byte numparams; /* number of fixed parameters */
- lu_byte is_vararg;
- lu_byte maxstacksize; /* maximum stack used by this function */
} Proto;
@@ -493,17 +424,7 @@ typedef struct Proto {
/*
** Lua Upvalues
*/
-typedef struct UpVal {
- CommonHeader;
- TValue *v; /* points to stack or to its own value */
- union {
- TValue value; /* the value (when closed) */
- struct { /* double linked list (when open) */
- struct UpVal *prev;
- struct UpVal *next;
- } l;
- } u;
-} UpVal;
+typedef struct UpVal UpVal;
/*
@@ -545,12 +466,19 @@ typedef union Closure {
typedef union TKey {
struct {
TValuefields;
- struct Node *next; /* for chaining */
+ int next; /* for chaining (offset for next node) */
} nk;
TValue tvk;
} TKey;
+/* copy a value into a key without messing up field 'next' */
+#define setnodekey(L,key,obj) \
+ { TKey *k_=(key); const TValue *io_=(obj); \
+ k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
+ (void)L; checkliveness(G(L),io_); }
+
+
typedef struct Node {
TValue i_val;
TKey i_key;
@@ -560,19 +488,19 @@ typedef struct Node {
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<
#include "lopcodes.h"
@@ -31,10 +34,17 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"ADD",
"SUB",
"MUL",
- "DIV",
"MOD",
"POW",
+ "DIV",
+ "IDIV",
+ "BAND",
+ "BOR",
+ "BXOR",
+ "SHL",
+ "SHR",
"UNM",
+ "BNOT",
"NOT",
"LEN",
"CONCAT",
@@ -79,10 +89,17 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
- ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
diff --git a/luaxx/lopcodes.h b/luaxx/lopcodes.h
index 51f57915..864b8e4b 100644
--- a/luaxx/lopcodes.h
+++ b/luaxx/lopcodes.h
@@ -1,5 +1,5 @@
/*
-** $Id: lopcodes.h,v 1.142.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lopcodes.h,v 1.148 2014/10/25 11:50:46 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -14,12 +14,12 @@
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
- `A' : 8 bits
- `B' : 9 bits
- `C' : 9 bits
+ 'A' : 8 bits
+ 'B' : 9 bits
+ 'C' : 9 bits
'Ax' : 26 bits ('A', 'B', and 'C' together)
- `Bx' : 18 bits (`B' and `C' together)
- `sBx' : signed Bx
+ 'Bx' : 18 bits ('B' and 'C' together)
+ 'sBx' : signed Bx
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
@@ -58,7 +58,7 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
*/
#if SIZE_Bx < LUAI_BITSINT-1
#define MAXARG_Bx ((1<>1) /* `sBx' is signed */
+#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
#else
#define MAXARG_Bx MAX_INT
#define MAXARG_sBx MAX_INT
@@ -76,10 +76,10 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
#define MAXARG_C ((1<> RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
+OP_BNOT,/* A B R(A) := ~R(B) */
OP_NOT,/* A B R(A) := not R(B) */
OP_LEN,/* A B R(A) := length of R(B) */
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
-OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */
+OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
@@ -231,16 +238,16 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
/*===========================================================================
Notes:
- (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then `top' is
+ (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
set to last_result+1, so next open instruction (OP_CALL, OP_RETURN,
- OP_SETLIST) may use `top'.
+ OP_SETLIST) may use 'top'.
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
- (*) In OP_RETURN, if (B == 0) then return up to `top'.
+ (*) In OP_RETURN, if (B == 0) then return up to 'top'.
- (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next
+ (*) In OP_SETLIST, if (B == 0) then B = 'top'; if (C == 0) then next
'instruction' is EXTRAARG(real C).
(*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
@@ -248,7 +255,7 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
(*) For comparisons, A specifies what condition the test should accept
(true or false).
- (*) All `skips' (pc++) assume that next instruction is a jump.
+ (*) All 'skips' (pc++) assume that next instruction is a jump.
===========================================================================*/
diff --git a/luaxx/loslib.c b/luaxx/loslib.c
index 21c48616..6d14c73f 100644
--- a/luaxx/loslib.c
+++ b/luaxx/loslib.c
@@ -1,9 +1,14 @@
/*
-** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: loslib.c,v 1.54 2014/12/26 14:46:07 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
+#define loslib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
#include
#include
@@ -11,69 +16,96 @@
#include
#include
-#define loslib_c
-#define LUA_LIB
-
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
+#if !defined(LUA_STRFTIMEOPTIONS) /* { */
/*
** list of valid conversion specifiers for the 'strftime' function
*/
-#if !defined(LUA_STRFTIMEOPTIONS)
-#if !defined(LUA_USE_POSIX)
+#if defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
-#else
+#else /* C99 specification */
#define LUA_STRFTIMEOPTIONS \
- { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
- "", "E", "cCxXyY", \
+ { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
+ "E", "cCxXyY", \
"O", "deHImMSuUVwWy" }
#endif
-#endif
+#endif /* } */
+
+
+
+#if !defined(l_time_t) /* { */
+/*
+** type to represent time_t in Lua
+*/
+#define l_timet lua_Integer
+#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
+#define l_checktime(L,a) ((time_t)luaL_checkinteger(L,a))
+#endif /* } */
+
+#if !defined(lua_tmpnam) /* { */
/*
** By default, Lua uses tmpnam except when POSIX is available, where it
** uses mkstemp.
*/
-#if defined(LUA_USE_MKSTEMP)
+
+#if defined(LUA_USE_POSIX) /* { */
+
#include
+
#define LUA_TMPNAMBUFSIZE 32
+
+#if !defined(LUA_TMPNAMTEMPLATE)
+#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
+#endif
+
#define lua_tmpnam(b,e) { \
- strcpy(b, "/tmp/lua_XXXXXX"); \
+ strcpy(b, LUA_TMPNAMTEMPLATE); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
-#elif !defined(lua_tmpnam)
+#else /* }{ */
+/* ISO C definitions */
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
-#endif
+#endif /* } */
+
+#endif /* } */
+
+#if !defined(l_gmtime) /* { */
/*
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
-#if defined(LUA_USE_GMTIME_R)
+
+#if defined(LUA_USE_POSIX) /* { */
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
-#elif !defined(l_gmtime)
+#else /* }{ */
-#define l_gmtime(t,r) ((void)r, gmtime(t))
-#define l_localtime(t,r) ((void)r, localtime(t))
+/* ISO C definitions */
+#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
+#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
-#endif
+#endif /* } */
+
+#endif /* } */
@@ -153,8 +185,7 @@ static void setboolfield (lua_State *L, const char *key, int value) {
static int getboolfield (lua_State *L, const char *key) {
int res;
- lua_getfield(L, -1, key);
- res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
lua_pop(L, 1);
return res;
}
@@ -166,7 +197,7 @@ static int getfield (lua_State *L, const char *key, int d) {
res = (int)lua_tointegerx(L, -1, &isnum);
if (!isnum) {
if (d < 0)
- return luaL_error(L, "field " LUA_QS " missing in date table", key);
+ return luaL_error(L, "field '%s' missing in date table", key);
res = d;
}
lua_pop(L, 1);
@@ -200,11 +231,11 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) {
static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c");
- time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
+ time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
struct tm tmr, *stm;
if (*s == '!') { /* UTC? */
stm = l_gmtime(&t, &tmr);
- s++; /* skip `!' */
+ s++; /* skip '!' */
}
else
stm = l_localtime(&t, &tmr);
@@ -261,17 +292,19 @@ static int os_time (lua_State *L) {
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
}
- if (t == (time_t)(-1))
+ if (t != (time_t)(l_timet)t)
+ luaL_error(L, "time result cannot be represented in this Lua instalation");
+ else if (t == (time_t)(-1))
lua_pushnil(L);
else
- lua_pushnumber(L, (lua_Number)t);
+ l_pushtime(L, t);
return 1;
}
static int os_difftime (lua_State *L) {
- lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
- (time_t)(luaL_optnumber(L, 2, 0))));
+ double res = difftime((l_checktime(L, 1)), (l_checktime(L, 2)));
+ lua_pushnumber(L, (lua_Number)res);
return 1;
}
@@ -295,7 +328,7 @@ static int os_exit (lua_State *L) {
if (lua_isboolean(L, 1))
status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
else
- status = luaL_optint(L, 1, EXIT_SUCCESS);
+ status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS);
if (lua_toboolean(L, 2))
lua_close(L);
if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
diff --git a/luaxx/lparser.c b/luaxx/lparser.c
index 9e1a9ca2..9a54dfc9 100644
--- a/luaxx/lparser.c
+++ b/luaxx/lparser.c
@@ -1,15 +1,17 @@
/*
-** $Id: lparser.c,v 2.130.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lparser.c,v 2.147 2014/12/27 20:31:43 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
-
-#include
-
#define lparser_c
#define LUA_CORE
+#include "lprefix.h"
+
+
+#include
+
#include "lua.h"
#include "lcode.h"
@@ -35,17 +37,21 @@
#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
+/* because all strings are unified by the scanner, the parser
+ can use pointer equality for string equality */
+#define eqstr(a,b) ((a) == (b))
+
/*
** nodes for block list (list of active blocks)
*/
typedef struct BlockCnt {
struct BlockCnt *previous; /* chain */
- short firstlabel; /* index of first label in this block */
- short firstgoto; /* index of first pending goto in this block */
+ int firstlabel; /* index of first label in this block */
+ int firstgoto; /* index of first pending goto in this block */
lu_byte nactvar; /* # active locals outside the block */
lu_byte upval; /* true if some variable in the block is an upvalue */
- lu_byte isloop; /* true if `block' is a loop */
+ lu_byte isloop; /* true if 'block' is a loop */
} BlockCnt;
@@ -57,19 +63,9 @@ static void statement (LexState *ls);
static void expr (LexState *ls, expdesc *v);
-static void anchor_token (LexState *ls) {
- /* last token from outer function must be EOS */
- lua_assert(ls->fs != NULL || ls->t.token == TK_EOS);
- if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
- TString *ts = ls->t.seminfo.ts;
- luaX_newstring(ls, getstr(ts), ts->tsv.len);
- }
-}
-
-
/* semantic error */
static l_noret semerror (LexState *ls, const char *msg) {
- ls->t.token = 0; /* remove 'near to' from final message */
+ ls->t.token = 0; /* remove "near " from final message */
luaX_syntaxerror(ls, msg);
}
@@ -222,7 +218,7 @@ static int searchupvalue (FuncState *fs, TString *name) {
int i;
Upvaldesc *up = fs->f->upvalues;
for (i = 0; i < fs->nups; i++) {
- if (luaS_eqstr(up[i].name, name)) return i;
+ if (eqstr(up[i].name, name)) return i;
}
return -1; /* not found */
}
@@ -246,7 +242,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
static int searchvar (FuncState *fs, TString *n) {
int i;
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
- if (luaS_eqstr(n, getlocvar(fs, i)->varname))
+ if (eqstr(n, getlocvar(fs, i)->varname))
return i;
}
return -1; /* not found */
@@ -342,11 +338,11 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
FuncState *fs = ls->fs;
Labellist *gl = &ls->dyd->gt;
Labeldesc *gt = &gl->arr[g];
- lua_assert(luaS_eqstr(gt->name, label->name));
+ lua_assert(eqstr(gt->name, label->name));
if (gt->nactvar < label->nactvar) {
TString *vname = getlocvar(fs, gt->nactvar)->varname;
const char *msg = luaO_pushfstring(ls->L,
- " at line %d jumps into the scope of local " LUA_QS,
+ " at line %d jumps into the scope of local '%s'",
getstr(gt->name), gt->line, getstr(vname));
semerror(ls, msg);
}
@@ -369,7 +365,7 @@ static int findlabel (LexState *ls, int g) {
/* check labels in current block for a match */
for (i = bl->firstlabel; i < dyd->label.n; i++) {
Labeldesc *lb = &dyd->label.arr[i];
- if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */
+ if (eqstr(lb->name, gt->name)) { /* correct label? */
if (gt->nactvar > lb->nactvar &&
(bl->upval || dyd->label.n > bl->firstlabel))
luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
@@ -390,7 +386,7 @@ static int newlabelentry (LexState *ls, Labellist *l, TString *name,
l->arr[n].line = line;
l->arr[n].nactvar = ls->fs->nactvar;
l->arr[n].pc = pc;
- l->n++;
+ l->n = n + 1;
return n;
}
@@ -403,7 +399,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
Labellist *gl = &ls->dyd->gt;
int i = ls->fs->bl->firstgoto;
while (i < gl->n) {
- if (luaS_eqstr(gl->arr[i].name, lb->name))
+ if (eqstr(gl->arr[i].name, lb->name))
closegoto(ls, i, lb);
else
i++;
@@ -412,7 +408,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
/*
-** "export" pending gotos to outer level, to check them against
+** export pending gotos to outer level, to check them against
** outer labels; if the block being exited has upvalues, and
** the goto exits the scope of any variable (which can be the
** upvalue), close those variables being exited.
@@ -448,7 +444,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
/*
-** create a label named "break" to resolve break statements
+** create a label named 'break' to resolve break statements
*/
static void breaklabel (LexState *ls) {
TString *n = luaS_new(ls->L, "break");
@@ -463,7 +459,7 @@ static void breaklabel (LexState *ls) {
static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
const char *msg = isreserved(gt->name)
? "<%s> at line %d not inside a loop"
- : "no visible label " LUA_QS " for at line %d";
+ : "no visible label '%s' for at line %d";
msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
semerror(ls, msg);
}
@@ -525,7 +521,6 @@ static void codeclosure (LexState *ls, expdesc *v) {
static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
- lua_State *L = ls->L;
Proto *f;
fs->prev = ls->fs; /* linked list of funcstates */
fs->ls = ls;
@@ -544,10 +539,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
f = fs->f;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
- fs->h = luaH_new(L);
- /* anchor table of constants (to avoid being collected) */
- sethvalue2s(L, L->top, fs->h);
- incr_top(L);
enterblock(fs, bl, 0);
}
@@ -572,9 +563,6 @@ static void close_func (LexState *ls) {
f->sizeupvalues = fs->nups;
lua_assert(fs->bl == NULL);
ls->fs = fs->prev;
- /* last token read was anchored in defunct function; must re-anchor it */
- anchor_token(ls);
- L->top--; /* pop table of constants */
luaC_checkGC(L);
}
@@ -588,7 +576,7 @@ static void close_func (LexState *ls) {
/*
** check whether current token is in the follow set of a block.
** 'until' closes syntactical blocks, but do not close scope,
-** so it handled in separate.
+** so it is handled in separate.
*/
static int block_follow (LexState *ls, int withuntil) {
switch (ls->t.token) {
@@ -602,7 +590,7 @@ static int block_follow (LexState *ls, int withuntil) {
static void statlist (LexState *ls) {
- /* statlist -> { stat [`;'] } */
+ /* statlist -> { stat [';'] } */
while (!block_follow(ls, 1)) {
if (ls->t.token == TK_RETURN) {
statement(ls);
@@ -643,14 +631,14 @@ static void yindex (LexState *ls, expdesc *v) {
struct ConsControl {
expdesc v; /* last list item read */
expdesc *t; /* table descriptor */
- int nh; /* total number of `record' elements */
+ int nh; /* total number of 'record' elements */
int na; /* total number of array elements */
int tostore; /* number of array elements pending to be stored */
};
static void recfield (LexState *ls, struct ConsControl *cc) {
- /* recfield -> (NAME | `['exp1`]') = exp1 */
+ /* recfield -> (NAME | '['exp1']') = exp1 */
FuncState *fs = ls->fs;
int reg = ls->fs->freereg;
expdesc key, val;
@@ -757,12 +745,12 @@ static void constructor (LexState *ls, expdesc *t) {
static void parlist (LexState *ls) {
- /* parlist -> [ param { `,' param } ] */
+ /* parlist -> [ param { ',' param } ] */
FuncState *fs = ls->fs;
Proto *f = fs->f;
int nparams = 0;
f->is_vararg = 0;
- if (ls->t.token != ')') { /* is `parlist' not empty? */
+ if (ls->t.token != ')') { /* is 'parlist' not empty? */
do {
switch (ls->t.token) {
case TK_NAME: { /* param -> NAME */
@@ -770,12 +758,12 @@ static void parlist (LexState *ls) {
nparams++;
break;
}
- case TK_DOTS: { /* param -> `...' */
+ case TK_DOTS: { /* param -> '...' */
luaX_next(ls);
f->is_vararg = 1;
break;
}
- default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected");
+ default: luaX_syntaxerror(ls, " or '...' expected");
}
} while (!f->is_vararg && testnext(ls, ','));
}
@@ -786,7 +774,7 @@ static void parlist (LexState *ls) {
static void body (LexState *ls, expdesc *e, int ismethod, int line) {
- /* body -> `(' parlist `)' block END */
+ /* body -> '(' parlist ')' block END */
FuncState new_fs;
BlockCnt bl;
new_fs.f = addprototype(ls);
@@ -808,7 +796,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
static int explist (LexState *ls, expdesc *v) {
- /* explist -> expr { `,' expr } */
+ /* explist -> expr { ',' expr } */
int n = 1; /* at least one expression */
expr(ls, v);
while (testnext(ls, ',')) {
@@ -825,7 +813,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
expdesc args;
int base, nparams;
switch (ls->t.token) {
- case '(': { /* funcargs -> `(' [ explist ] `)' */
+ case '(': { /* funcargs -> '(' [ explist ] ')' */
luaX_next(ls);
if (ls->t.token == ')') /* arg list is empty? */
args.k = VVOID;
@@ -842,7 +830,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
}
case TK_STRING: { /* funcargs -> STRING */
codestring(ls, &args, ls->t.seminfo.ts);
- luaX_next(ls); /* must use `seminfo' before `next' */
+ luaX_next(ls); /* must use 'seminfo' before 'next' */
break;
}
default: {
@@ -908,14 +896,14 @@ static void suffixedexp (LexState *ls, expdesc *v) {
fieldsel(ls, v);
break;
}
- case '[': { /* `[' exp1 `]' */
+ case '[': { /* '[' exp1 ']' */
expdesc key;
luaK_exp2anyregup(fs, v);
yindex(ls, &key);
luaK_indexed(fs, v, &key);
break;
}
- case ':': { /* `:' NAME funcargs */
+ case ':': { /* ':' NAME funcargs */
expdesc key;
luaX_next(ls);
checkname(ls, &key);
@@ -935,14 +923,19 @@ static void suffixedexp (LexState *ls, expdesc *v) {
static void simpleexp (LexState *ls, expdesc *v) {
- /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
+ /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... |
constructor | FUNCTION body | suffixedexp */
switch (ls->t.token) {
- case TK_NUMBER: {
- init_exp(v, VKNUM, 0);
+ case TK_FLT: {
+ init_exp(v, VKFLT, 0);
v->u.nval = ls->t.seminfo.r;
break;
}
+ case TK_INT: {
+ init_exp(v, VKINT, 0);
+ v->u.ival = ls->t.seminfo.i;
+ break;
+ }
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
break;
@@ -962,7 +955,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
case TK_DOTS: { /* vararg */
FuncState *fs = ls->fs;
check_condition(ls, fs->f->is_vararg,
- "cannot use " LUA_QL("...") " outside a vararg function");
+ "cannot use '...' outside a vararg function");
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
@@ -988,6 +981,7 @@ static UnOpr getunopr (int op) {
switch (op) {
case TK_NOT: return OPR_NOT;
case '-': return OPR_MINUS;
+ case '~': return OPR_BNOT;
case '#': return OPR_LEN;
default: return OPR_NOUNOPR;
}
@@ -999,9 +993,15 @@ static BinOpr getbinopr (int op) {
case '+': return OPR_ADD;
case '-': return OPR_SUB;
case '*': return OPR_MUL;
- case '/': return OPR_DIV;
case '%': return OPR_MOD;
case '^': return OPR_POW;
+ case '/': return OPR_DIV;
+ case TK_IDIV: return OPR_IDIV;
+ case '&': return OPR_BAND;
+ case '|': return OPR_BOR;
+ case '~': return OPR_BXOR;
+ case TK_SHL: return OPR_SHL;
+ case TK_SHR: return OPR_SHR;
case TK_CONCAT: return OPR_CONCAT;
case TK_NE: return OPR_NE;
case TK_EQ: return OPR_EQ;
@@ -1020,19 +1020,24 @@ static const struct {
lu_byte left; /* left priority for each binary operator */
lu_byte right; /* right priority */
} priority[] = { /* ORDER OPR */
- {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */
- {10, 9}, {5, 4}, /* ^, .. (right associative) */
- {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */
- {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */
- {2, 2}, {1, 1} /* and, or */
+ {10, 10}, {10, 10}, /* '+' '-' */
+ {11, 11}, {11, 11}, /* '*' '%' */
+ {14, 13}, /* '^' (right associative) */
+ {11, 11}, {11, 11}, /* '/' '//' */
+ {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */
+ {7, 7}, {7, 7}, /* '<<' '>>' */
+ {9, 8}, /* '..' (right associative) */
+ {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */
+ {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */
+ {2, 2}, {1, 1} /* and, or */
};
-#define UNARY_PRIORITY 8 /* priority for unary operators */
+#define UNARY_PRIORITY 12 /* priority for unary operators */
/*
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
-** where `binop' is any binary operator with a priority higher than `limit'
+** where 'binop' is any binary operator with a priority higher than 'limit'
*/
static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
BinOpr op;
@@ -1046,7 +1051,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
luaK_prefix(ls->fs, uop, v, line);
}
else simpleexp(ls, v);
- /* expand while operators have priorities higher than `limit' */
+ /* expand while operators have priorities higher than 'limit' */
op = getbinopr(ls->t.token);
while (op != OPR_NOBINOPR && priority[op].left > limit) {
expdesc v2;
@@ -1146,7 +1151,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
"C levels");
assignment(ls, &nv, nvars+1);
}
- else { /* assignment -> `=' explist */
+ else { /* assignment -> '=' explist */
int nexps;
checknext(ls, '=');
nexps = explist(ls, &e);
@@ -1170,7 +1175,7 @@ static int cond (LexState *ls) {
/* cond -> exp */
expdesc v;
expr(ls, &v); /* read condition */
- if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */
luaK_goiftrue(ls->fs, &v);
return v.f;
}
@@ -1195,9 +1200,9 @@ static void gotostat (LexState *ls, int pc) {
static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
int i;
for (i = fs->bl->firstlabel; i < ll->n; i++) {
- if (luaS_eqstr(label, ll->arr[i].name)) {
+ if (eqstr(label, ll->arr[i].name)) {
const char *msg = luaO_pushfstring(fs->ls->L,
- "label " LUA_QS " already defined on line %d",
+ "label '%s' already defined on line %d",
getstr(label), ll->arr[i].line);
semerror(fs->ls, msg);
}
@@ -1321,7 +1326,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
if (testnext(ls, ','))
exp1(ls); /* optional step */
else { /* default step = 1 */
- luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1));
+ luaK_codek(fs, fs->freereg, luaK_intK(fs, 1));
luaK_reserveregs(fs, 1);
}
forbody(ls, base, line, 1, 1);
@@ -1359,15 +1364,15 @@ static void forstat (LexState *ls, int line) {
TString *varname;
BlockCnt bl;
enterblock(fs, &bl, 1); /* scope for loop and control variables */
- luaX_next(ls); /* skip `for' */
+ luaX_next(ls); /* skip 'for' */
varname = str_checkname(ls); /* first variable name */
switch (ls->t.token) {
case '=': fornum(ls, varname, line); break;
case ',': case TK_IN: forlist(ls, varname); break;
- default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
+ default: luaX_syntaxerror(ls, "'=' or 'in' expected");
}
check_match(ls, TK_END, TK_FOR, line);
- leaveblock(fs); /* loop scope (`break' jumps to this point) */
+ leaveblock(fs); /* loop scope ('break' jumps to this point) */
}
@@ -1397,7 +1402,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
enterblock(fs, &bl, 0);
jf = v.f;
}
- statlist(ls); /* `then' part */
+ statlist(ls); /* 'then' part */
leaveblock(fs);
if (ls->t.token == TK_ELSE ||
ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */
@@ -1414,7 +1419,7 @@ static void ifstat (LexState *ls, int line) {
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */
if (testnext(ls, TK_ELSE))
- block(ls); /* `else' part */
+ block(ls); /* 'else' part */
check_match(ls, TK_END, TK_IF, line);
luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */
}
@@ -1432,7 +1437,7 @@ static void localfunc (LexState *ls) {
static void localstat (LexState *ls) {
- /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */
+ /* stat -> LOCAL NAME {',' NAME} ['=' explist] */
int nvars = 0;
int nexps;
expdesc e;
@@ -1452,7 +1457,7 @@ static void localstat (LexState *ls) {
static int funcname (LexState *ls, expdesc *v) {
- /* funcname -> NAME {fieldsel} [`:' NAME] */
+ /* funcname -> NAME {fieldsel} [':' NAME] */
int ismethod = 0;
singlevar(ls, v);
while (ls->t.token == '.')
@@ -1473,7 +1478,7 @@ static void funcstat (LexState *ls, int line) {
ismethod = funcname(ls, &v);
body(ls, &b, ismethod, line);
luaK_storevar(ls->fs, &v, &b);
- luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
+ luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
}
@@ -1515,8 +1520,8 @@ static void retstat (LexState *ls) {
if (nret == 1) /* only one single value? */
first = luaK_exp2anyreg(fs, &e);
else {
- luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
- first = fs->nactvar; /* return all `active' values */
+ luaK_exp2nextreg(fs, &e); /* values must go to the stack */
+ first = fs->nactvar; /* return all active values */
lua_assert(nret == fs->freereg - first);
}
}
@@ -1615,16 +1620,19 @@ static void mainfunc (LexState *ls, FuncState *fs) {
}
-Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar) {
+LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar) {
LexState lexstate;
FuncState funcstate;
- Closure *cl = luaF_newLclosure(L, 1); /* create main closure */
- /* anchor closure (to avoid being collected) */
- setclLvalue(L, L->top, cl);
+ LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */
+ setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */
+ incr_top(L);
+ lexstate.h = luaH_new(L); /* create table for scanner */
+ sethvalue(L, L->top, lexstate.h); /* anchor it */
incr_top(L);
- funcstate.f = cl->l.p = luaF_newproto(L);
+ funcstate.f = cl->p = luaF_newproto(L);
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
+ lua_assert(iswhite(funcstate.f)); /* do not need barrier here */
lexstate.buff = buff;
lexstate.dyd = dyd;
dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
@@ -1633,6 +1641,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
/* all scopes should be correctly finished */
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
- return cl; /* it's on the stack too */
+ L->top--; /* remove scanner's table */
+ return cl; /* closure is on the stack, too */
}
diff --git a/luaxx/lparser.h b/luaxx/lparser.h
index 0346e3c4..62c50cac 100644
--- a/luaxx/lparser.h
+++ b/luaxx/lparser.h
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lparser.h,v 1.74 2014/10/25 11:50:46 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -21,8 +21,9 @@ typedef enum {
VNIL,
VTRUE,
VFALSE,
- VK, /* info = index of constant in `k' */
- VKNUM, /* nval = numerical value */
+ VK, /* info = index of constant in 'k' */
+ VKFLT, /* nval = numerical float value */
+ VKINT, /* nval = numerical integer value */
VNONRELOC, /* info = result register */
VLOCAL, /* info = local register */
VUPVAL, /* info = index of upvalue in 'upvalues' */
@@ -46,10 +47,11 @@ typedef struct expdesc {
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind;
int info; /* for generic use */
- lua_Number nval; /* for VKNUM */
+ lua_Number nval; /* for VKFLT */
+ lua_Integer ival; /* for VKINT */
} u;
- int t; /* patch list of `exit when true' */
- int f; /* patch list of `exit when false' */
+ int t; /* patch list of 'exit when true' */
+ int f; /* patch list of 'exit when false' */
} expdesc;
@@ -95,15 +97,14 @@ struct BlockCnt; /* defined in lparser.c */
/* state needed to generate code for a given function */
typedef struct FuncState {
Proto *f; /* current function header */
- Table *h; /* table to find (and reuse) elements in `k' */
struct FuncState *prev; /* enclosing function */
struct LexState *ls; /* lexical state */
struct BlockCnt *bl; /* chain of current blocks */
- int pc; /* next position to code (equivalent to `ncode') */
+ int pc; /* next position to code (equivalent to 'ncode') */
int lasttarget; /* 'label' of last 'jump label' */
- int jpc; /* list of pending jumps to `pc' */
- int nk; /* number of elements in `k' */
- int np; /* number of elements in `p' */
+ int jpc; /* list of pending jumps to 'pc' */
+ int nk; /* number of elements in 'k' */
+ int np; /* number of elements in 'p' */
int firstlocal; /* index of first local var (in Dyndata array) */
short nlocvars; /* number of elements in 'f->locvars' */
lu_byte nactvar; /* number of active local variables */
@@ -112,8 +113,8 @@ typedef struct FuncState {
} FuncState;
-LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar);
+LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar);
#endif
diff --git a/luaxx/lprefix.h b/luaxx/lprefix.h
new file mode 100644
index 00000000..02daa837
--- /dev/null
+++ b/luaxx/lprefix.h
@@ -0,0 +1,45 @@
+/*
+** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
+** Definitions for Lua code that must come before any other header file
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lprefix_h
+#define lprefix_h
+
+
+/*
+** Allows POSIX/XSI stuff
+*/
+#if !defined(LUA_USE_C89) /* { */
+
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE 600
+#elif _XOPEN_SOURCE == 0
+#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */
+#endif
+
+/*
+** Allows manipulation of large files in gcc and some other compilers
+*/
+#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
+#define _LARGEFILE_SOURCE 1
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#endif /* } */
+
+
+/*
+** Windows stuff
+*/
+#if defined(_WIN32) /* { */
+
+#if !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */
+#endif
+
+#endif /* } */
+
+#endif
+
diff --git a/luaxx/lstate.c b/luaxx/lstate.c
index c7f2672b..ff6b02d3 100644
--- a/luaxx/lstate.c
+++ b/luaxx/lstate.c
@@ -1,16 +1,18 @@
/*
-** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $
+** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
+#define lstate_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
#include
#include
-#define lstate_c
-#define LUA_CORE
-
#include "lua.h"
#include "lapi.h"
@@ -30,10 +32,6 @@
#define LUAI_GCPAUSE 200 /* 200% */
#endif
-#if !defined(LUAI_GCMAJOR)
-#define LUAI_GCMAJOR 200 /* 200% */
-#endif
-
#if !defined(LUAI_GCMUL)
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
#endif
@@ -57,9 +55,7 @@
** thread state + extra space
*/
typedef struct LX {
-#if defined(LUAI_EXTRASPACE)
- char buff[LUAI_EXTRASPACE];
-#endif
+ lu_byte extra_[LUA_EXTRASPACE];
lua_State l;
} LX;
@@ -78,9 +74,8 @@ typedef struct LG {
/*
-** Compute an initial seed as random as possible. In ANSI, rely on
-** Address Space Layout Randomization (if present) to increase
-** randomness..
+** Compute an initial seed as random as possible. Rely on Address Space
+** Layout Randomization (if present) to increase randomness..
*/
#define addbuff(b,p,e) \
{ size_t t = cast(size_t, e); \
@@ -119,6 +114,9 @@ CallInfo *luaE_extendCI (lua_State *L) {
}
+/*
+** free all CallInfo structures not in use by a thread
+*/
void luaE_freeCI (lua_State *L) {
CallInfo *ci = L->ci;
CallInfo *next = ci->next;
@@ -130,6 +128,22 @@ void luaE_freeCI (lua_State *L) {
}
+/*
+** free half of the CallInfo structures not in use by a thread
+*/
+void luaE_shrinkCI (lua_State *L) {
+ CallInfo *ci = L->ci;
+ while (ci->next != NULL) { /* while there is 'next' */
+ CallInfo *next2 = ci->next->next; /* next's next */
+ if (next2 == NULL) break;
+ luaM_free(L, ci->next); /* remove next */
+ ci->next = next2; /* remove 'next' from the list */
+ next2->previous = ci;
+ ci = next2;
+ }
+}
+
+
static void stack_init (lua_State *L1, lua_State *L) {
int i; CallInfo *ci;
/* initialize stack array */
@@ -163,22 +177,23 @@ static void freestack (lua_State *L) {
** Create registry table and its predefined values
*/
static void init_registry (lua_State *L, global_State *g) {
- TValue mt;
+ TValue temp;
/* create registry */
Table *registry = luaH_new(L);
sethvalue(L, &g->l_registry, registry);
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
/* registry[LUA_RIDX_MAINTHREAD] = L */
- setthvalue(L, &mt, L);
- luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
+ setthvalue(L, &temp, L); /* temp = L */
+ luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
/* registry[LUA_RIDX_GLOBALS] = table of globals */
- sethvalue(L, &mt, luaH_new(L));
- luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
+ sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */
+ luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
}
/*
-** open parts of the state that may cause memory-allocation errors
+** open parts of the state that may cause memory-allocation errors.
+** ('g->version' != NULL flags that the state was completely build)
*/
static void f_luaopen (lua_State *L, void *ud) {
global_State *g = G(L);
@@ -190,7 +205,7 @@ static void f_luaopen (lua_State *L, void *ud) {
luaX_init(L);
/* pre-create memory-error message */
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
- luaS_fix(g->memerrmsg); /* it should never be collected */
+ luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
g->gcrunning = 1; /* allow gc */
g->version = lua_version(NULL);
luai_userstateopen(L);
@@ -198,14 +213,15 @@ static void f_luaopen (lua_State *L, void *ud) {
/*
-** preinitialize a state with consistent values without allocating
+** preinitialize a thread with consistent values without allocating
** any memory (to avoid errors)
*/
-static void preinit_state (lua_State *L, global_State *g) {
+static void preinit_thread (lua_State *L, global_State *g) {
G(L) = g;
L->stack = NULL;
L->ci = NULL;
L->stacksize = 0;
+ L->twups = L; /* thread has no upvalues */
L->errorJmp = NULL;
L->nCcalls = 0;
L->hook = NULL;
@@ -235,17 +251,28 @@ static void close_state (lua_State *L) {
LUA_API lua_State *lua_newthread (lua_State *L) {
+ global_State *g = G(L);
lua_State *L1;
lua_lock(L);
luaC_checkGC(L);
- L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th;
+ /* create new thread */
+ L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
+ L1->marked = luaC_white(g);
+ L1->tt = LUA_TTHREAD;
+ /* link it on list 'allgc' */
+ L1->next = g->allgc;
+ g->allgc = obj2gco(L1);
+ /* anchor it on L stack */
setthvalue(L, L->top, L1);
api_incr_top(L);
- preinit_state(L1, G(L));
+ preinit_thread(L1, g);
L1->hookmask = L->hookmask;
L1->basehookcount = L->basehookcount;
L1->hook = L->hook;
resethookcount(L1);
+ /* initialize L1 extra space */
+ memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
+ LUA_EXTRASPACE);
luai_userstatethread(L, L1);
stack_init(L1, L); /* init stack */
lua_unlock(L);
@@ -273,36 +300,32 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g = &l->g;
L->next = NULL;
L->tt = LUA_TTHREAD;
- g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+ g->currentwhite = bitmask(WHITE0BIT);
L->marked = luaC_white(g);
- g->gckind = KGC_NORMAL;
- preinit_state(L, g);
+ preinit_thread(L, g);
g->frealloc = f;
g->ud = ud;
g->mainthread = L;
g->seed = makeseed(L);
- g->uvhead.u.l.prev = &g->uvhead;
- g->uvhead.u.l.next = &g->uvhead;
g->gcrunning = 0; /* no GC while building state */
g->GCestimate = 0;
- g->strt.size = 0;
- g->strt.nuse = 0;
+ g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL;
setnilvalue(&g->l_registry);
luaZ_initbuffer(L, &g->buff);
g->panic = NULL;
g->version = NULL;
g->gcstate = GCSpause;
- g->allgc = NULL;
- g->finobj = NULL;
- g->tobefnz = NULL;
- g->sweepgc = g->sweepfin = NULL;
+ g->gckind = KGC_NORMAL;
+ g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
+ g->sweepgc = NULL;
g->gray = g->grayagain = NULL;
g->weak = g->ephemeron = g->allweak = NULL;
+ g->twups = NULL;
g->totalbytes = sizeof(LG);
g->GCdebt = 0;
+ g->gcfinnum = 0;
g->gcpause = LUAI_GCPAUSE;
- g->gcmajorinc = LUAI_GCMAJOR;
g->gcstepmul = LUAI_GCMUL;
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
diff --git a/luaxx/lstate.h b/luaxx/lstate.h
index daffd9aa..81e12c40 100644
--- a/luaxx/lstate.h
+++ b/luaxx/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstate.h,v 2.119 2014/10/30 18:53:28 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -16,25 +16,16 @@
/*
-** Some notes about garbage-collected objects: All objects in Lua must
-** be kept somehow accessible until being freed.
+** Some notes about garbage-collected objects: All objects in Lua must
+** be kept somehow accessible until being freed, so all objects always
+** belong to one (and only one) of these lists, using field 'next' of
+** the 'CommonHeader' for the link:
**
-** Lua keeps most objects linked in list g->allgc. The link uses field
-** 'next' of the CommonHeader.
-**
-** Strings are kept in several lists headed by the array g->strt.hash.
-**
-** Open upvalues are not subject to independent garbage collection. They
-** are collected together with their respective threads. Lua keeps a
-** double-linked list with all open upvalues (g->uvhead) so that it can
-** mark objects referred by them. (They are always gray, so they must
-** be remarked in the atomic step. Usually their contents would be marked
-** when traversing the respective threads, but the thread may already be
-** dead, while the upvalue is still accessible through closures.)
-**
-** Objects with finalizers are kept in the list g->finobj.
-**
-** The list g->tobefnz links all objects being finalized.
+** 'allgc': all objects not marked for finalization;
+** 'finobj': all objects marked for finalization;
+** 'tobefnz': all objects ready to be finalized;
+** 'fixedgc': all objects that are not to be collected (currently
+** only small strings, such as reserved words).
*/
@@ -53,65 +44,70 @@ struct lua_longjmp; /* defined in ldo.c */
/* kinds of Garbage Collection */
#define KGC_NORMAL 0
#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */
-#define KGC_GEN 2 /* generational collection */
typedef struct stringtable {
- GCObject **hash;
- lu_int32 nuse; /* number of elements */
+ TString **hash;
+ int nuse; /* number of elements */
int size;
} stringtable;
/*
-** information about a call
+** Information about a call.
+** When a thread yields, 'func' is adjusted to pretend that the
+** top function has only the yielded values in its stack; in that
+** case, the actual 'func' value is saved in field 'extra'.
+** When a function calls another with a continuation, 'extra' keeps
+** the function index so that, in case of errors, the continuation
+** function can be called with the correct top.
*/
typedef struct CallInfo {
StkId func; /* function index in the stack */
StkId top; /* top for this function */
struct CallInfo *previous, *next; /* dynamic call link */
- short nresults; /* expected number of results from this function */
- lu_byte callstatus;
- ptrdiff_t extra;
union {
struct { /* only for Lua functions */
StkId base; /* base for this function */
const Instruction *savedpc;
} l;
struct { /* only for C functions */
- int ctx; /* context info. in case of yields */
- lua_CFunction k; /* continuation in case of yields */
+ lua_KFunction k; /* continuation in case of yields */
ptrdiff_t old_errfunc;
- lu_byte old_allowhook;
- lu_byte status;
+ lua_KContext ctx; /* context info. in case of yields */
} c;
} u;
+ ptrdiff_t extra;
+ short nresults; /* expected number of results from this function */
+ lu_byte callstatus;
} CallInfo;
/*
** Bits in CallInfo status
*/
-#define CIST_LUA (1<<0) /* call is running a Lua function */
-#define CIST_HOOKED (1<<1) /* call is running a debug hook */
-#define CIST_REENTRY (1<<2) /* call is running on same invocation of
+#define CIST_OAH (1<<0) /* original value of 'allowhook' */
+#define CIST_LUA (1<<1) /* call is running a Lua function */
+#define CIST_HOOKED (1<<2) /* call is running a debug hook */
+#define CIST_REENTRY (1<<3) /* call is running on same invocation of
luaV_execute of previous call */
-#define CIST_YIELDED (1<<3) /* call reentered after suspension */
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
-#define CIST_STAT (1<<5) /* call has an error status (pcall) */
-#define CIST_TAIL (1<<6) /* call was tail called */
-#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */
-
+#define CIST_TAIL (1<<5) /* call was tail called */
+#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
#define isLua(ci) ((ci)->callstatus & CIST_LUA)
+/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
+#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v))
+#define getoah(st) ((st) & CIST_OAH)
+
/*
-** `global state', shared by all threads of this state
+** 'global state', shared by all threads of this state
*/
typedef struct global_State {
lua_Alloc frealloc; /* function to reallocate memory */
- void *ud; /* auxiliary data to `frealloc' */
+ void *ud; /* auxiliary data to 'frealloc' */
lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem GCmemtrav; /* memory traversed by the GC */
@@ -123,22 +119,21 @@ typedef struct global_State {
lu_byte gcstate; /* state of garbage collector */
lu_byte gckind; /* kind of GC running */
lu_byte gcrunning; /* true if GC is running */
- int sweepstrgc; /* position of sweep in `strt' */
GCObject *allgc; /* list of all collectable objects */
+ GCObject **sweepgc; /* current position of sweep in list */
GCObject *finobj; /* list of collectable objects with finalizers */
- GCObject **sweepgc; /* current position of sweep in list 'allgc' */
- GCObject **sweepfin; /* current position of sweep in list 'finobj' */
GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of tables with weak values */
GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
GCObject *allweak; /* list of all-weak tables */
GCObject *tobefnz; /* list of userdata to be GC */
- UpVal uvhead; /* head of double-linked list of all open upvalues */
+ GCObject *fixedgc; /* list of objects not to be collected */
+ struct lua_State *twups; /* list of threads with open upvalues */
Mbuffer buff; /* temporary buffer for string concatenation */
+ unsigned int gcfinnum; /* number of finalizers to call in each GC step */
int gcpause; /* size of pause between successive GCs */
- int gcmajorinc; /* pause between major collections (only in gen. mode) */
- int gcstepmul; /* GC `granularity' */
+ int gcstepmul; /* GC 'granularity' */
lua_CFunction panic; /* to be called in unprotected errors */
struct lua_State *mainthread;
const lua_Number *version; /* pointer to version number */
@@ -149,7 +144,7 @@ typedef struct global_State {
/*
-** `per thread' state
+** 'per thread' state
*/
struct lua_State {
CommonHeader;
@@ -160,19 +155,20 @@ struct lua_State {
const Instruction *oldpc; /* last pc traced */
StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */
+ UpVal *openupval; /* list of open upvalues in this stack */
+ GCObject *gclist;
+ struct lua_State *twups; /* list of threads with open upvalues */
+ struct lua_longjmp *errorJmp; /* current error recover point */
+ CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
+ lua_Hook hook;
+ ptrdiff_t errfunc; /* current error handling function (stack index) */
int stacksize;
+ int basehookcount;
+ int hookcount;
unsigned short nny; /* number of non-yieldable calls in stack */
unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask;
lu_byte allowhook;
- int basehookcount;
- int hookcount;
- lua_Hook hook;
- GCObject *openupval; /* list of open upvalues in this stack */
- GCObject *gclist;
- struct lua_longjmp *errorJmp; /* current error recover point */
- ptrdiff_t errfunc; /* current error handling function (stack index) */
- CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
};
@@ -180,39 +176,37 @@ struct lua_State {
/*
-** Union of all collectable objects
+** Union of all collectable objects (only for conversions)
*/
-union GCObject {
- GCheader gch; /* common header */
- union TString ts;
- union Udata u;
+union GCUnion {
+ GCObject gc; /* common header */
+ struct TString ts;
+ struct Udata u;
union Closure cl;
struct Table h;
struct Proto p;
- struct UpVal uv;
struct lua_State th; /* thread */
};
-#define gch(o) (&(o)->gch)
+#define cast_u(o) cast(union GCUnion *, (o))
/* macros to convert a GCObject into a specific value */
-#define rawgco2ts(o) \
- check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts))
-#define gco2ts(o) (&rawgco2ts(o)->tsv)
-#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
-#define gco2u(o) (&rawgco2u(o)->uv)
-#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l))
-#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c))
+#define gco2ts(o) \
+ check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
+#define gco2u(o) check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u))
+#define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l))
+#define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c))
#define gco2cl(o) \
- check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl))
-#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
-#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
-#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
-#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+ check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
+#define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h))
+#define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p))
+#define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th))
+
-/* macro to convert any Lua object into a GCObject */
-#define obj2gco(v) (cast(GCObject *, (v)))
+/* macro to convert a Lua object into a GCObject */
+#define obj2gco(v) \
+ check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc)))
/* actual number of total bytes allocated */
@@ -222,6 +216,7 @@ LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
LUAI_FUNC void luaE_freeCI (lua_State *L);
+LUAI_FUNC void luaE_shrinkCI (lua_State *L);
#endif
diff --git a/luaxx/lstring.c b/luaxx/lstring.c
index af96c89c..2947113c 100644
--- a/luaxx/lstring.c
+++ b/luaxx/lstring.c
@@ -1,23 +1,28 @@
/*
-** $Id: lstring.c,v 2.26.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
-
-#include
-
#define lstring_c
#define LUA_CORE
+#include "lprefix.h"
+
+
+#include
+
#include "lua.h"
+#include "ldebug.h"
+#include "ldo.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
+
/*
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
** compute its hash
@@ -31,23 +36,14 @@
** equality for long strings
*/
int luaS_eqlngstr (TString *a, TString *b) {
- size_t len = a->tsv.len;
- lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR);
+ size_t len = a->len;
+ lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
return (a == b) || /* same instance or... */
- ((len == b->tsv.len) && /* equal length and ... */
+ ((len == b->len) && /* equal length and ... */
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
}
-/*
-** equality for strings
-*/
-int luaS_eqstr (TString *a, TString *b) {
- return (a->tsv.tt == b->tsv.tt) &&
- (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b));
-}
-
-
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
unsigned int h = seed ^ cast(unsigned int, l);
size_t l1;
@@ -64,66 +60,59 @@ unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
void luaS_resize (lua_State *L, int newsize) {
int i;
stringtable *tb = &G(L)->strt;
- /* cannot resize while GC is traversing strings */
- luaC_runtilstate(L, ~bitmask(GCSsweepstring));
- if (newsize > tb->size) {
- luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
- for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL;
+ if (newsize > tb->size) { /* grow table if needed */
+ luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
+ for (i = tb->size; i < newsize; i++)
+ tb->hash[i] = NULL;
}
- /* rehash */
- for (i=0; isize; i++) {
- GCObject *p = tb->hash[i];
+ for (i = 0; i < tb->size; i++) { /* rehash */
+ TString *p = tb->hash[i];
tb->hash[i] = NULL;
while (p) { /* for each node in the list */
- GCObject *next = gch(p)->next; /* save next */
- unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */
- gch(p)->next = tb->hash[h]; /* chain it */
+ TString *hnext = p->hnext; /* save next */
+ unsigned int h = lmod(p->hash, newsize); /* new position */
+ p->hnext = tb->hash[h]; /* chain it */
tb->hash[h] = p;
- resetoldbit(p); /* see MOVE OLD rule */
- p = next;
+ p = hnext;
}
}
- if (newsize < tb->size) {
- /* shrinking slice must be empty */
+ if (newsize < tb->size) { /* shrink table if needed */
+ /* vanishing slice should be empty */
lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL);
- luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
+ luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
}
tb->size = newsize;
}
+
/*
** creates a new string object
*/
static TString *createstrobj (lua_State *L, const char *str, size_t l,
- int tag, unsigned int h, GCObject **list) {
+ int tag, unsigned int h) {
TString *ts;
+ GCObject *o;
size_t totalsize; /* total size of TString object */
- totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
- ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts;
- ts->tsv.len = l;
- ts->tsv.hash = h;
- ts->tsv.extra = 0;
- memcpy(ts+1, str, l*sizeof(char));
- ((char *)(ts+1))[l] = '\0'; /* ending 0 */
+ totalsize = sizelstring(l);
+ o = luaC_newobj(L, tag, totalsize);
+ ts = gco2ts(o);
+ ts->len = l;
+ ts->hash = h;
+ ts->extra = 0;
+ memcpy(getaddrstr(ts), str, l * sizeof(char));
+ getaddrstr(ts)[l] = '\0'; /* ending 0 */
return ts;
}
-/*
-** creates a new short string, inserting it into string table
-*/
-static TString *newshrstr (lua_State *L, const char *str, size_t l,
- unsigned int h) {
- GCObject **list; /* (pointer to) list where it will be inserted */
+void luaS_remove (lua_State *L, TString *ts) {
stringtable *tb = &G(L)->strt;
- TString *s;
- if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
- luaS_resize(L, tb->size*2); /* too crowded */
- list = &tb->hash[lmod(h, tb->size)];
- s = createstrobj(L, str, l, LUA_TSHRSTR, h, list);
- tb->nuse++;
- return s;
+ TString **p = &tb->hash[lmod(ts->hash, tb->size)];
+ while (*p != ts) /* find previous element */
+ p = &(*p)->hnext;
+ *p = (*p)->hnext; /* remove element from its list */
+ tb->nuse--;
}
@@ -131,22 +120,28 @@ static TString *newshrstr (lua_State *L, const char *str, size_t l,
** checks whether short string exists and reuses it or creates a new one
*/
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
- GCObject *o;
+ TString *ts;
global_State *g = G(L);
unsigned int h = luaS_hash(str, l, g->seed);
- for (o = g->strt.hash[lmod(h, g->strt.size)];
- o != NULL;
- o = gch(o)->next) {
- TString *ts = rawgco2ts(o);
- if (h == ts->tsv.hash &&
- l == ts->tsv.len &&
+ TString **list = &g->strt.hash[lmod(h, g->strt.size)];
+ for (ts = *list; ts != NULL; ts = ts->hnext) {
+ if (l == ts->len &&
(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
- if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */
- changewhite(o); /* resurrect it */
+ /* found! */
+ if (isdead(g, ts)) /* dead (but not collected yet)? */
+ changewhite(ts); /* resurrect it */
return ts;
}
}
- return newshrstr(L, str, l, h); /* not found; create a new string */
+ if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) {
+ luaS_resize(L, g->strt.size * 2);
+ list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
+ }
+ ts = createstrobj(L, str, l, LUA_TSHRSTR, h);
+ ts->hnext = *list;
+ *list = ts;
+ g->strt.nuse++;
+ return ts;
}
@@ -157,9 +152,9 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
if (l <= LUAI_MAXSHORTLEN) /* short string? */
return internshrstr(L, str, l);
else {
- if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+ if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
luaM_toobig(L);
- return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL);
+ return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
}
}
@@ -172,14 +167,16 @@ TString *luaS_new (lua_State *L, const char *str) {
}
-Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
+Udata *luaS_newudata (lua_State *L, size_t s) {
Udata *u;
- if (s > MAX_SIZET - sizeof(Udata))
+ GCObject *o;
+ if (s > MAX_SIZE - sizeof(Udata))
luaM_toobig(L);
- u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u;
- u->uv.len = s;
- u->uv.metatable = NULL;
- u->uv.env = e;
+ o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s));
+ u = gco2u(o);
+ u->len = s;
+ u->metatable = NULL;
+ setuservalue(L, u, luaO_nilobject);
return u;
}
diff --git a/luaxx/lstring.h b/luaxx/lstring.h
index 260e7f16..d3f04caf 100644
--- a/luaxx/lstring.h
+++ b/luaxx/lstring.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -12,33 +12,33 @@
#include "lstate.h"
-#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
+#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char))
+#define sizestring(s) sizelstring((s)->len)
-#define sizeudata(u) (sizeof(union Udata)+(u)->len)
+#define sizeludata(l) (sizeof(union UUdata) + (l))
+#define sizeudata(u) sizeludata((u)->len)
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1))
-#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
-
/*
** test whether a string is a reserved word
*/
-#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0)
+#define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0)
/*
** equality for short strings, which are always internalized
*/
-#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b))
+#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b))
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
-LUAI_FUNC int luaS_eqstr (TString *a, TString *b);
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
-LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
diff --git a/luaxx/lstrlib.c b/luaxx/lstrlib.c
index 9261fd22..a650b768 100644
--- a/luaxx/lstrlib.c
+++ b/luaxx/lstrlib.c
@@ -1,19 +1,22 @@
/*
-** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
#include
+#include
#include
#include
#include
#include
-#define lstrlib_c
-#define LUA_LIB
-
#include "lua.h"
#include "lauxlib.h"
@@ -29,10 +32,19 @@
#endif
-/* macro to `unsign' a character */
+/* macro to 'unsign' a character */
#define uchar(c) ((unsigned char)(c))
+/*
+** Some sizes are better limited to fit in 'int', but must also fit in
+** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
+*/
+#define MAXSIZE \
+ (sizeof(size_t) < sizeof(int) ? (~(size_t)0) : (size_t)(INT_MAX))
+
+
+
static int str_len (lua_State *L) {
size_t l;
@@ -43,22 +55,22 @@ static int str_len (lua_State *L) {
/* translate a relative string position: negative means back from end */
-static size_t posrelat (ptrdiff_t pos, size_t len) {
- if (pos >= 0) return (size_t)pos;
+static lua_Integer posrelat (lua_Integer pos, size_t len) {
+ if (pos >= 0) return pos;
else if (0u - (size_t)pos > len) return 0;
- else return len - ((size_t)-pos) + 1;
+ else return (lua_Integer)len + pos + 1;
}
static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- size_t start = posrelat(luaL_checkinteger(L, 2), l);
- size_t end = posrelat(luaL_optinteger(L, 3, -1), l);
+ lua_Integer start = posrelat(luaL_checkinteger(L, 2), l);
+ lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1;
- if (end > l) end = l;
+ if (end > (lua_Integer)l) end = l;
if (start <= end)
- lua_pushlstring(L, s + start - 1, end - start + 1);
+ lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1));
else lua_pushliteral(L, "");
return 1;
}
@@ -102,25 +114,23 @@ static int str_upper (lua_State *L) {
}
-/* reasonable limit to avoid arithmetic overflow */
-#define MAXSIZE ((~(size_t)0) >> 1)
-
static int str_rep (lua_State *L) {
size_t l, lsep;
const char *s = luaL_checklstring(L, 1, &l);
- int n = luaL_checkint(L, 2);
+ lua_Integer n = luaL_checkinteger(L, 2);
const char *sep = luaL_optlstring(L, 3, "", &lsep);
if (n <= 0) lua_pushliteral(L, "");
- else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */
+ else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */
return luaL_error(L, "resulting string too large");
else {
- size_t totallen = n * l + (n - 1) * lsep;
+ size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
luaL_Buffer b;
char *p = luaL_buffinitsize(L, &b, totallen);
while (n-- > 1) { /* first n-1 copies (followed by separator) */
memcpy(p, s, l * sizeof(char)); p += l;
- if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */
- memcpy(p, sep, lsep * sizeof(char)); p += lsep;
+ if (lsep > 0) { /* empty 'memcpy' is not that cheap */
+ memcpy(p, sep, lsep * sizeof(char));
+ p += lsep;
}
}
memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
@@ -133,14 +143,14 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- size_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
- size_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l);
int n, i;
if (posi < 1) posi = 1;
- if (pose > l) pose = l;
+ if (pose > (lua_Integer)l) pose = l;
if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1);
- if (posi + n <= pose) /* (size_t -> int) overflow? */
+ if (posi + n <= pose) /* arithmetic overflow? */
return luaL_error(L, "string slice too long");
luaL_checkstack(L, n, "string slice too long");
for (i=0; ip_end)
- luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+ luaL_error(ms->L, "malformed pattern (ends with '%%')");
return p+1;
}
case '[': {
if (*p == '^') p++;
- do { /* look for a `]' */
+ do { /* look for a ']' */
if (p == ms->p_end)
- luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ luaL_error(ms->L, "malformed pattern (missing ']')");
if (*(p++) == L_ESC && p < ms->p_end)
- p++; /* skip escapes (e.g. `%]') */
+ p++; /* skip escapes (e.g. '%]') */
} while (*p != ']');
return p+1;
}
@@ -287,7 +298,7 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
int sig = 1;
if (*(p+1) == '^') {
sig = 0;
- p++; /* skip the `^' */
+ p++; /* skip the '^' */
}
while (++p < ec) {
if (*p == L_ESC) {
@@ -325,8 +336,7 @@ static int singlematch (MatchState *ms, const char *s, const char *p,
static const char *matchbalance (MatchState *ms, const char *s,
const char *p) {
if (p >= ms->p_end - 1)
- luaL_error(ms->L, "malformed pattern "
- "(missing arguments to " LUA_QL("%%b") ")");
+ luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
if (*s != *p) return NULL;
else {
int b = *p;
@@ -425,7 +435,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
break;
}
case '$': {
- if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */
+ if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */
goto dflt; /* no; go to default */
s = (s == ms->src_end) ? s : NULL; /* check end of string */
break;
@@ -443,8 +453,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
const char *ep; char previous;
p += 2;
if (*p != '[')
- luaL_error(ms->L, "missing " LUA_QL("[") " after "
- LUA_QL("%%f") " in pattern");
+ luaL_error(ms->L, "missing '[' after '%%f' in pattern");
ep = classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s - 1);
if (!matchbracketclass(uchar(previous), p, ep - 1) &&
@@ -514,16 +523,16 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
static const char *lmemfind (const char *s1, size_t l1,
const char *s2, size_t l2) {
if (l2 == 0) return s1; /* empty strings are everywhere */
- else if (l2 > l1) return NULL; /* avoids a negative `l1' */
+ else if (l2 > l1) return NULL; /* avoids a negative 'l1' */
else {
- const char *init; /* to search for a `*s2' inside `s1' */
- l2--; /* 1st char will be checked by `memchr' */
- l1 = l1-l2; /* `s2' cannot be found after that */
+ const char *init; /* to search for a '*s2' inside 's1' */
+ l2--; /* 1st char will be checked by 'memchr' */
+ l1 = l1-l2; /* 's2' cannot be found after that */
while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
init++; /* 1st char is already checked */
if (memcmp(init, s2+1, l2) == 0)
return init-1;
- else { /* correct `l1' and `s1' to try again */
+ else { /* correct 'l1' and 's1' to try again */
l1 -= init-s1;
s1 = init;
}
@@ -539,7 +548,7 @@ static void push_onecapture (MatchState *ms, int i, const char *s,
if (i == 0) /* ms->level == 0, too */
lua_pushlstring(ms->L, s, e - s); /* add whole match */
else
- luaL_error(ms->L, "invalid capture index");
+ luaL_error(ms->L, "invalid capture index %%%d", i + 1);
}
else {
ptrdiff_t l = ms->capture[i].len;
@@ -578,16 +587,16 @@ static int str_find_aux (lua_State *L, int find) {
size_t ls, lp;
const char *s = luaL_checklstring(L, 1, &ls);
const char *p = luaL_checklstring(L, 2, &lp);
- size_t init = posrelat(luaL_optinteger(L, 3, 1), ls);
+ lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls);
if (init < 1) init = 1;
- else if (init > ls + 1) { /* start after string's end? */
+ else if (init > (lua_Integer)ls + 1) { /* start after string's end? */
lua_pushnil(L); /* cannot find anything */
return 1;
}
/* explicit request or no special characters? */
if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
/* do a plain search */
- const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp);
+ const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
if (s2) {
lua_pushinteger(L, s2 - s + 1);
lua_pushinteger(L, s2 - s + lp);
@@ -678,7 +687,8 @@ static int gmatch (lua_State *L) {
static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
const char *e) {
size_t l, i;
- const char *news = lua_tolstring(ms->L, 3, &l);
+ lua_State *L = ms->L;
+ const char *news = lua_tolstring(L, 3, &l);
for (i = 0; i < l; i++) {
if (news[i] != L_ESC)
luaL_addchar(b, news[i]);
@@ -686,14 +696,15 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
i++; /* skip ESC */
if (!isdigit(uchar(news[i]))) {
if (news[i] != L_ESC)
- luaL_error(ms->L, "invalid use of " LUA_QL("%c")
- " in replacement string", L_ESC);
+ luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
luaL_addchar(b, news[i]);
}
else if (news[i] == '0')
luaL_addlstring(b, s, e - s);
else {
push_onecapture(ms, news[i] - '1', s, e);
+ luaL_tolstring(L, -1, NULL); /* if number, convert it to string */
+ lua_remove(L, -2); /* remove original value */
luaL_addvalue(b); /* add capture to accumulated result */
}
}
@@ -737,9 +748,9 @@ static int str_gsub (lua_State *L) {
const char *src = luaL_checklstring(L, 1, &srcl);
const char *p = luaL_checklstring(L, 2, &lp);
int tr = lua_type(L, 3);
- size_t max_s = luaL_optinteger(L, 4, srcl+1);
+ lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1);
int anchor = (*p == '^');
- size_t n = 0;
+ lua_Integer n = 0;
MatchState ms;
luaL_Buffer b;
luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
@@ -786,48 +797,17 @@ static int str_gsub (lua_State *L) {
** =======================================================
*/
-/*
-** LUA_INTFRMLEN is the length modifier for integer conversions in
-** 'string.format'; LUA_INTFRM_T is the integer type corresponding to
-** the previous length
-*/
-#if !defined(LUA_INTFRMLEN) /* { */
-#if defined(LUA_USE_LONGLONG)
-
-#define LUA_INTFRMLEN "ll"
-#define LUA_INTFRM_T long long
-
-#else
-
-#define LUA_INTFRMLEN "l"
-#define LUA_INTFRM_T long
-
-#endif
-#endif /* } */
-
-
-/*
-** LUA_FLTFRMLEN is the length modifier for float conversions in
-** 'string.format'; LUA_FLTFRM_T is the float type corresponding to
-** the previous length
-*/
-#if !defined(LUA_FLTFRMLEN)
-
-#define LUA_FLTFRMLEN ""
-#define LUA_FLTFRM_T double
-
-#endif
-
-
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM 512
+
/* valid flags in a format specification */
#define FLAGS "-+ #0"
+
/*
-** maximum size of each format specification (such as '%-099.99d')
-** (+10 accounts for %99.99x plus margin of error)
+** maximum size of each format specification (such as "%-099.99d")
+** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error)
*/
-#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+#define MAX_FORMAT (sizeof(FLAGS) + 2 + 10)
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
@@ -903,7 +883,7 @@ static int str_format (lua_State *L) {
else if (*++strfrmt == L_ESC)
luaL_addchar(&b, *strfrmt++); /* %% */
else { /* format item */
- char form[MAX_FORMAT]; /* to store the format (`%...') */
+ char form[MAX_FORMAT]; /* to store the format ('%...') */
char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
int nb = 0; /* number of bytes in added item */
if (++arg > top)
@@ -911,36 +891,23 @@ static int str_format (lua_State *L) {
strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) {
case 'c': {
- nb = sprintf(buff, form, luaL_checkint(L, arg));
- break;
- }
- case 'd': case 'i': {
- lua_Number n = luaL_checknumber(L, arg);
- LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
- lua_Number diff = n - (lua_Number)ni;
- luaL_argcheck(L, -1 < diff && diff < 1, arg,
- "not a number in proper range");
- addlenmod(form, LUA_INTFRMLEN);
- nb = sprintf(buff, form, ni);
+ nb = sprintf(buff, form, (int)luaL_checkinteger(L, arg));
break;
}
+ case 'd': case 'i':
case 'o': case 'u': case 'x': case 'X': {
- lua_Number n = luaL_checknumber(L, arg);
- unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
- lua_Number diff = n - (lua_Number)ni;
- luaL_argcheck(L, -1 < diff && diff < 1, arg,
- "not a non-negative number in proper range");
- addlenmod(form, LUA_INTFRMLEN);
- nb = sprintf(buff, form, ni);
+ lua_Integer n = luaL_checkinteger(L, arg);
+ addlenmod(form, LUA_INTEGER_FRMLEN);
+ nb = sprintf(buff, form, n);
break;
}
- case 'e': case 'E': case 'f':
#if defined(LUA_USE_AFORMAT)
case 'a': case 'A':
#endif
+ case 'e': case 'E': case 'f':
case 'g': case 'G': {
- addlenmod(form, LUA_FLTFRMLEN);
- nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg));
+ addlenmod(form, LUA_NUMBER_FRMLEN);
+ nb = sprintf(buff, form, luaL_checknumber(L, arg));
break;
}
case 'q': {
@@ -962,9 +929,9 @@ static int str_format (lua_State *L) {
break;
}
}
- default: { /* also treat cases `pnLlh' */
- return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
- LUA_QL("format"), *(strfrmt - 1));
+ default: { /* also treat cases 'pnLlh' */
+ return luaL_error(L, "invalid option '%%%c' to 'format'",
+ *(strfrmt - 1));
}
}
luaL_addsize(&b, nb);
@@ -977,6 +944,447 @@ static int str_format (lua_State *L) {
/* }====================================================== */
+/*
+** {======================================================
+** PACK/UNPACK
+** =======================================================
+*/
+
+
+/* value used for padding */
+#if !defined(LUA_PACKPADBYTE)
+#define LUA_PACKPADBYTE 0x00
+#endif
+
+/* maximum size for the binary representation of an integer */
+#define MAXINTSIZE 16
+
+/* number of bits in a character */
+#define NB CHAR_BIT
+
+/* mask for one character (NB 1's) */
+#define MC ((1 << NB) - 1)
+
+/* size of a lua_Integer */
+#define SZINT ((int)sizeof(lua_Integer))
+
+
+/* dummy union to get native endianness */
+static const union {
+ int dummy;
+ char little; /* true iff machine is little endian */
+} nativeendian = {1};
+
+
+/* dummy structure to get native alignment requirements */
+struct cD {
+ char c;
+ union { double d; void *p; lua_Integer i; lua_Number n; } u;
+};
+
+#define MAXALIGN (offsetof(struct cD, u))
+
+
+/*
+** Union for serializing floats
+*/
+typedef union Ftypes {
+ float f;
+ double d;
+ lua_Number n;
+ char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
+} Ftypes;
+
+
+/*
+** information to pack/unpack stuff
+*/
+typedef struct Header {
+ lua_State *L;
+ int islittle;
+ int maxalign;
+} Header;
+
+
+/*
+** options for pack/unpack
+*/
+typedef enum KOption {
+ Kint, /* signed integers */
+ Kuint, /* unsigned integers */
+ Kfloat, /* floating-point numbers */
+ Kchar, /* fixed-length strings */
+ Kstring, /* strings with prefixed length */
+ Kzstr, /* zero-terminated strings */
+ Kpadding, /* padding */
+ Kpaddalign, /* padding for alignment */
+ Knop /* no-op (configuration or spaces) */
+} KOption;
+
+
+/*
+** Read an integer numeral from string 'fmt' or return 'df' if
+** there is no numeral
+*/
+static int digit (int c) { return '0' <= c && c <= '9'; }
+
+static int getnum (const char **fmt, int df) {
+ if (!digit(**fmt)) /* no number? */
+ return df; /* return default value */
+ else {
+ int a = 0;
+ do {
+ a = a*10 + (*((*fmt)++) - '0');
+ } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
+ return a;
+ }
+}
+
+
+/*
+** Read an integer numeral and raises an error if it is larger
+** than the maximum size for integers.
+*/
+static int getnumlimit (Header *h, const char **fmt, int df) {
+ int sz = getnum(fmt, df);
+ if (sz > MAXINTSIZE || sz <= 0)
+ luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
+ sz, MAXINTSIZE);
+ return sz;
+}
+
+
+/*
+** Initialize Header
+*/
+static void initheader (lua_State *L, Header *h) {
+ h->L = L;
+ h->islittle = nativeendian.little;
+ h->maxalign = 1;
+}
+
+
+/*
+** Read and classify next option. 'size' is filled with option's size.
+*/
+static KOption getoption (Header *h, const char **fmt, int *size) {
+ int opt = *((*fmt)++);
+ *size = 0; /* default */
+ switch (opt) {
+ case 'b': *size = sizeof(char); return Kint;
+ case 'B': *size = sizeof(char); return Kuint;
+ case 'h': *size = sizeof(short); return Kint;
+ case 'H': *size = sizeof(short); return Kuint;
+ case 'l': *size = sizeof(long); return Kint;
+ case 'L': *size = sizeof(long); return Kuint;
+ case 'j': *size = sizeof(lua_Integer); return Kint;
+ case 'J': *size = sizeof(lua_Integer); return Kuint;
+ case 'T': *size = sizeof(size_t); return Kuint;
+ case 'f': *size = sizeof(float); return Kfloat;
+ case 'd': *size = sizeof(double); return Kfloat;
+ case 'n': *size = sizeof(lua_Number); return Kfloat;
+ case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
+ case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
+ case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
+ case 'c':
+ *size = getnum(fmt, -1);
+ if (*size == -1)
+ luaL_error(h->L, "missing size for format option 'c'");
+ return Kchar;
+ case 'z': return Kzstr;
+ case 'x': *size = 1; return Kpadding;
+ case 'X': return Kpaddalign;
+ case ' ': break;
+ case '<': h->islittle = 1; break;
+ case '>': h->islittle = 0; break;
+ case '=': h->islittle = nativeendian.little; break;
+ case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
+ default: luaL_error(h->L, "invalid format option '%c'", opt);
+ }
+ return Knop;
+}
+
+
+/*
+** Read, classify, and fill other details about the next option.
+** 'psize' is filled with option's size, 'notoalign' with its
+** alignment requirements.
+** Local variable 'size' gets the size to be aligned. (Kpadal option
+** always gets its full alignment, other options are limited by
+** the maximum alignment ('maxalign'). Kchar option needs no alignment
+** despite its size.
+*/
+static KOption getdetails (Header *h, size_t totalsize,
+ const char **fmt, int *psize, int *ntoalign) {
+ KOption opt = getoption(h, fmt, psize);
+ int align = *psize; /* usually, alignment follows size */
+ if (opt == Kpaddalign) { /* 'X' gets alignment from following option */
+ if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
+ luaL_argerror(h->L, 1, "invalid next option for option 'X'");
+ }
+ if (align <= 1 || opt == Kchar) /* need no alignment? */
+ *ntoalign = 0;
+ else {
+ if (align > h->maxalign) /* enforce maximum alignment */
+ align = h->maxalign;
+ if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */
+ luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
+ *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
+ }
+ return opt;
+}
+
+
+/*
+** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
+** The final 'if' handles the case when 'size' is larger than
+** the size of a Lua integer, correcting the extra sign-extension
+** bytes if necessary (by default they would be zeros).
+*/
+static void packint (luaL_Buffer *b, lua_Unsigned n,
+ int islittle, int size, int neg) {
+ char *buff = luaL_prepbuffsize(b, size);
+ int i;
+ buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */
+ for (i = 1; i < size; i++) {
+ n >>= NB;
+ buff[islittle ? i : size - 1 - i] = (char)(n & MC);
+ }
+ if (neg && size > SZINT) { /* negative number need sign extension? */
+ for (i = SZINT; i < size; i++) /* correct extra bytes */
+ buff[islittle ? i : size - 1 - i] = (char)MC;
+ }
+ luaL_addsize(b, size); /* add result to buffer */
+}
+
+
+/*
+** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
+** given 'islittle' is different from native endianness.
+*/
+static void copywithendian (volatile char *dest, volatile const char *src,
+ int size, int islittle) {
+ if (islittle == nativeendian.little) {
+ while (size-- != 0)
+ *(dest++) = *(src++);
+ }
+ else {
+ dest += size - 1;
+ while (size-- != 0)
+ *(dest--) = *(src++);
+ }
+}
+
+
+static int str_pack (lua_State *L) {
+ luaL_Buffer b;
+ Header h;
+ const char *fmt = luaL_checkstring(L, 1); /* format string */
+ int arg = 1; /* current argument to pack */
+ size_t totalsize = 0; /* accumulate total size of result */
+ initheader(L, &h);
+ lua_pushnil(L); /* mark to separate arguments from string buffer */
+ luaL_buffinit(L, &b);
+ while (*fmt != '\0') {
+ int size, ntoalign;
+ KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+ totalsize += ntoalign + size;
+ while (ntoalign-- > 0)
+ luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */
+ arg++;
+ switch (opt) {
+ case Kint: { /* signed integers */
+ lua_Integer n = luaL_checkinteger(L, arg);
+ if (size < SZINT) { /* need overflow check? */
+ lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
+ luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
+ }
+ packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0));
+ break;
+ }
+ case Kuint: { /* unsigned integers */
+ lua_Integer n = luaL_checkinteger(L, arg);
+ if (size < SZINT) /* need overflow check? */
+ luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
+ arg, "unsigned overflow");
+ packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
+ break;
+ }
+ case Kfloat: { /* floating-point options */
+ volatile Ftypes u;
+ char *buff = luaL_prepbuffsize(&b, size);
+ lua_Number n = luaL_checknumber(L, arg); /* get argument */
+ if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
+ else if (size == sizeof(u.d)) u.d = (double)n;
+ else u.n = n;
+ /* move 'u' to final result, correcting endianness if needed */
+ copywithendian(buff, u.buff, size, h.islittle);
+ luaL_addsize(&b, size);
+ break;
+ }
+ case Kchar: { /* fixed-size string */
+ size_t len;
+ const char *s = luaL_checklstring(L, arg, &len);
+ luaL_argcheck(L, len == (size_t)size, arg, "wrong length");
+ luaL_addlstring(&b, s, size);
+ break;
+ }
+ case Kstring: { /* strings with length count */
+ size_t len;
+ const char *s = luaL_checklstring(L, arg, &len);
+ luaL_argcheck(L, size >= (int)sizeof(size_t) ||
+ len < ((size_t)1 << (size * NB)),
+ arg, "string length does not fit in given size");
+ packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */
+ luaL_addlstring(&b, s, len);
+ totalsize += len;
+ break;
+ }
+ case Kzstr: { /* zero-terminated string */
+ size_t len;
+ const char *s = luaL_checklstring(L, arg, &len);
+ luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
+ luaL_addlstring(&b, s, len);
+ luaL_addchar(&b, '\0'); /* add zero at the end */
+ totalsize += len + 1;
+ break;
+ }
+ case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* go through */
+ case Kpaddalign: case Knop:
+ arg--; /* undo increment */
+ break;
+ }
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_packsize (lua_State *L) {
+ Header h;
+ const char *fmt = luaL_checkstring(L, 1); /* format string */
+ size_t totalsize = 0; /* accumulate total size of result */
+ initheader(L, &h);
+ while (*fmt != '\0') {
+ int size, ntoalign;
+ KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+ size += ntoalign; /* total space used by option */
+ luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
+ "format result too large");
+ totalsize += size;
+ switch (opt) {
+ case Kstring: /* strings with length count */
+ case Kzstr: /* zero-terminated string */
+ luaL_argerror(L, 1, "variable-length format");
+ break;
+ default: break;
+ }
+ }
+ lua_pushinteger(L, (lua_Integer)totalsize);
+ return 1;
+}
+
+
+/*
+** Unpack an integer with 'size' bytes and 'islittle' endianness.
+** If size is smaller than the size of a Lua integer and integer
+** is signed, must do sign extension (propagating the sign to the
+** higher bits); if size is larger than the size of a Lua integer,
+** it must check the unread bytes to see whether they do not cause an
+** overflow.
+*/
+static lua_Integer unpackint (lua_State *L, const char *str,
+ int islittle, int size, int issigned) {
+ lua_Unsigned res = 0;
+ int i;
+ int limit = (size <= SZINT) ? size : SZINT;
+ for (i = limit - 1; i >= 0; i--) {
+ res <<= NB;
+ res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
+ }
+ if (size < SZINT) { /* real size smaller than lua_Integer? */
+ if (issigned) { /* needs sign extension? */
+ lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
+ res = ((res ^ mask) - mask); /* do sign extension */
+ }
+ }
+ else if (size > SZINT) { /* must check unread bytes */
+ int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
+ for (i = limit; i < size; i++) {
+ if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
+ luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
+ }
+ }
+ return (lua_Integer)res;
+}
+
+
+static int str_unpack (lua_State *L) {
+ Header h;
+ const char *fmt = luaL_checkstring(L, 1);
+ size_t ld;
+ const char *data = luaL_checklstring(L, 2, &ld);
+ size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
+ int n = 0; /* number of results */
+ luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
+ initheader(L, &h);
+ while (*fmt != '\0') {
+ int size, ntoalign;
+ KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
+ if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
+ luaL_argerror(L, 2, "data string too short");
+ pos += ntoalign; /* skip alignment */
+ /* stack space for item + next position */
+ luaL_checkstack(L, 2, "too many results");
+ n++;
+ switch (opt) {
+ case Kint:
+ case Kuint: {
+ lua_Integer res = unpackint(L, data + pos, h.islittle, size,
+ (opt == Kint));
+ lua_pushinteger(L, res);
+ break;
+ }
+ case Kfloat: {
+ volatile Ftypes u;
+ lua_Number num;
+ copywithendian(u.buff, data + pos, size, h.islittle);
+ if (size == sizeof(u.f)) num = (lua_Number)u.f;
+ else if (size == sizeof(u.d)) num = (lua_Number)u.d;
+ else num = u.n;
+ lua_pushnumber(L, num);
+ break;
+ }
+ case Kchar: {
+ lua_pushlstring(L, data + pos, size);
+ break;
+ }
+ case Kstring: {
+ size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
+ luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
+ lua_pushlstring(L, data + pos + size, len);
+ pos += len; /* skip string */
+ break;
+ }
+ case Kzstr: {
+ size_t len = (int)strlen(data + pos);
+ lua_pushlstring(L, data + pos, len);
+ pos += len + 1; /* skip string plus final '\0' */
+ break;
+ }
+ case Kpaddalign: case Kpadding: case Knop:
+ n--; /* undo increment */
+ break;
+ }
+ pos += size;
+ }
+ lua_pushinteger(L, pos + 1); /* next position */
+ return n + 1;
+}
+
+/* }====================================================== */
+
+
static const luaL_Reg strlib[] = {
{"byte", str_byte},
{"char", str_char},
@@ -992,6 +1400,9 @@ static const luaL_Reg strlib[] = {
{"reverse", str_reverse},
{"sub", str_sub},
{"upper", str_upper},
+ {"pack", str_pack},
+ {"packsize", str_packsize},
+ {"unpack", str_unpack},
{NULL, NULL}
};
diff --git a/luaxx/ltable.c b/luaxx/ltable.c
index 5d76f97e..38be0051 100644
--- a/luaxx/ltable.c
+++ b/luaxx/ltable.c
@@ -1,27 +1,32 @@
/*
-** $Id: ltable.c,v 2.72.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
+#define ltable_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
/*
** Implementation of tables (aka arrays, objects, or hash tables).
** Tables keep its elements in two parts: an array part and a hash part.
** Non-negative integer keys are all candidates to be kept in the array
-** part. The actual size of the array is the largest `n' such that at
+** part. The actual size of the array is the largest 'n' such that at
** least half the slots between 0 and n are in use.
** Hash uses a mix of chained scatter table with Brent's variation.
** A main invariant of these tables is that, if an element is not
-** in its main position (i.e. the `original' position that its hash gives
+** in its main position (i.e. the 'original' position that its hash gives
** to it), then the colliding element is in its own main position.
** Hence even when the load factor reaches 100%, performance remains good.
*/
+#include
+#include
#include
-
-#define ltable_c
-#define LUA_CORE
+#include
#include "lua.h"
@@ -37,21 +42,26 @@
/*
-** max size of array part is 2^MAXBITS
+** Maximum size of array part (MAXASIZE) is 2^MAXABITS. MAXABITS is
+** the largest integer such that MAXASIZE fits in an unsigned int.
*/
-#if LUAI_BITSINT >= 32
-#define MAXBITS 30
-#else
-#define MAXBITS (LUAI_BITSINT-2)
-#endif
+#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1)
+#define MAXASIZE (1u << MAXABITS)
-#define MAXASIZE (1 << MAXBITS)
+/*
+** Maximum size of hash part is 2^MAXHBITS. MAXHBITS is the largest
+** integer such that 2^MAXHBITS fits in a signed int. (Note that the
+** maximum number of elements in a table, 2^MAXABITS + 2^MAXHBITS, still
+** fits comfortably in an unsigned int.)
+*/
+#define MAXHBITS (MAXABITS - 1)
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
-#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+#define hashstr(t,str) hashpow2(t, (str)->hash)
#define hashboolean(t,p) hashpow2(t, p)
+#define hashint(t,i) hashpow2(t, i)
/*
@@ -61,7 +71,7 @@
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
-#define hashpointer(t,p) hashmod(t, IntPoint(p))
+#define hashpointer(t,p) hashmod(t, point2int(p))
#define dummynode (&dummynode_)
@@ -70,16 +80,28 @@
static const Node dummynode_ = {
{NILCONSTANT}, /* value */
- {{NILCONSTANT, NULL}} /* key */
+ {{NILCONSTANT, 0}} /* key */
};
/*
-** hash for lua_Numbers
+** Checks whether a float has a value representable as a lua_Integer
+** (and does the conversion if so)
+*/
+static int numisinteger (lua_Number x, lua_Integer *p) {
+ if ((x) == l_floor(x)) /* integral value? */
+ return lua_numbertointeger(x, p); /* try as an integer */
+ else return 0;
+}
+
+
+/*
+** hash for floating-point numbers
*/
-static Node *hashnum (const Table *t, lua_Number n) {
+static Node *hashfloat (const Table *t, lua_Number n) {
int i;
- luai_hashnum(i, n);
+ n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP);
+ i += cast_int(n);
if (i < 0) {
if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
i = 0; /* handle INT_MIN */
@@ -91,23 +113,25 @@ static Node *hashnum (const Table *t, lua_Number n) {
/*
-** returns the `main' position of an element in a table (that is, the index
+** returns the 'main' position of an element in a table (that is, the index
** of its hash value)
*/
static Node *mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) {
- case LUA_TNUMBER:
- return hashnum(t, nvalue(key));
+ case LUA_TNUMINT:
+ return hashint(t, ivalue(key));
+ case LUA_TNUMFLT:
+ return hashfloat(t, fltvalue(key));
+ case LUA_TSHRSTR:
+ return hashstr(t, tsvalue(key));
case LUA_TLNGSTR: {
- TString *s = rawtsvalue(key);
- if (s->tsv.extra == 0) { /* no hash? */
- s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash);
- s->tsv.extra = 1; /* now it has its hash */
+ TString *s = tsvalue(key);
+ if (s->extra == 0) { /* no hash? */
+ s->hash = luaS_hash(getstr(s), s->len, s->hash);
+ s->extra = 1; /* now it has its hash */
}
- return hashstr(t, rawtsvalue(key));
+ return hashstr(t, tsvalue(key));
}
- case LUA_TSHRSTR:
- return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
@@ -121,61 +145,61 @@ static Node *mainposition (const Table *t, const TValue *key) {
/*
-** returns the index for `key' if `key' is an appropriate key to live in
-** the array part of the table, -1 otherwise.
+** returns the index for 'key' if 'key' is an appropriate key to live in
+** the array part of the table, 0 otherwise.
*/
-static int arrayindex (const TValue *key) {
- if (ttisnumber(key)) {
- lua_Number n = nvalue(key);
- int k;
- lua_number2int(k, n);
- if (luai_numeq(cast_num(k), n))
- return k;
+static unsigned int arrayindex (const TValue *key) {
+ if (ttisinteger(key)) {
+ lua_Integer k = ivalue(key);
+ if (0 < k && (lua_Unsigned)k <= MAXASIZE)
+ return cast(unsigned int, k); /* 'key' is an appropriate array index */
}
- return -1; /* `key' did not match some condition */
+ return 0; /* 'key' did not match some condition */
}
/*
-** returns the index of a `key' for table traversals. First goes all
+** returns the index of a 'key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The
-** beginning of a traversal is signaled by -1.
+** beginning of a traversal is signaled by 0.
*/
-static int findindex (lua_State *L, Table *t, StkId key) {
- int i;
- if (ttisnil(key)) return -1; /* first iteration */
+static unsigned int findindex (lua_State *L, Table *t, StkId key) {
+ unsigned int i;
+ if (ttisnil(key)) return 0; /* first iteration */
i = arrayindex(key);
- if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
- return i-1; /* yes; that's the index (corrected to C) */
+ if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */
+ return i; /* yes; that's the index */
else {
+ int nx;
Node *n = mainposition(t, key);
- for (;;) { /* check whether `key' is somewhere in the chain */
- /* key may be dead already, but it is ok to use it in `next' */
+ for (;;) { /* check whether 'key' is somewhere in the chain */
+ /* key may be dead already, but it is ok to use it in 'next' */
if (luaV_rawequalobj(gkey(n), key) ||
(ttisdeadkey(gkey(n)) && iscollectable(key) &&
deadvalue(gkey(n)) == gcvalue(key))) {
i = cast_int(n - gnode(t, 0)); /* key index in hash table */
/* hash elements are numbered after array ones */
- return i + t->sizearray;
+ return (i + 1) + t->sizearray;
}
- else n = gnext(n);
- if (n == NULL)
- luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
+ nx = gnext(n);
+ if (nx == 0)
+ luaG_runerror(L, "invalid key to 'next'"); /* key not found */
+ else n += nx;
}
}
}
int luaH_next (lua_State *L, Table *t, StkId key) {
- int i = findindex(L, t, key); /* find original element */
- for (i++; i < t->sizearray; i++) { /* try first array part */
+ unsigned int i = findindex(L, t, key); /* find original element */
+ for (; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
- setnvalue(key, cast_num(i+1));
+ setivalue(key, i + 1);
setobj2s(L, key+1, &t->array[i]);
return 1;
}
}
- for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
+ for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
setobj2s(L, key, gkey(gnode(t, i)));
setobj2s(L, key+1, gval(gnode(t, i)));
@@ -192,19 +216,24 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
** ==============================================================
*/
-
-static int computesizes (int nums[], int *narray) {
+/*
+** Compute the optimal size for the array part of table 't'. 'nums' is a
+** "count array" where 'nums[i]' is the number of integers in the table
+** between 2^(i - 1) + 1 and 2^i. Put in '*narray' the optimal size, and
+** return the number of elements that will go to that part.
+*/
+static unsigned int computesizes (unsigned int nums[], unsigned int *narray) {
int i;
- int twotoi; /* 2^i */
- int a = 0; /* number of elements smaller than 2^i */
- int na = 0; /* number of elements to go to array part */
- int n = 0; /* optimal size for array part */
+ unsigned int twotoi; /* 2^i */
+ unsigned int a = 0; /* number of elements smaller than 2^i */
+ unsigned int na = 0; /* number of elements to go to array part */
+ unsigned int n = 0; /* optimal size for array part */
for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
if (nums[i] > 0) {
a += nums[i];
if (a > twotoi/2) { /* more than half elements present? */
n = twotoi; /* optimal size (till now) */
- na = a; /* all elements smaller than n will go to array part */
+ na = a; /* all elements up to 'n' will go to array part */
}
}
if (a == *narray) break; /* all elements already counted */
@@ -215,9 +244,9 @@ static int computesizes (int nums[], int *narray) {
}
-static int countint (const TValue *key, int *nums) {
- int k = arrayindex(key);
- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
+static int countint (const TValue *key, unsigned int *nums) {
+ unsigned int k = arrayindex(key);
+ if (k != 0) { /* is 'key' an appropriate array index? */
nums[luaO_ceillog2(k)]++; /* count as such */
return 1;
}
@@ -226,20 +255,21 @@ static int countint (const TValue *key, int *nums) {
}
-static int numusearray (const Table *t, int *nums) {
+static unsigned int numusearray (const Table *t, unsigned int *nums) {
int lg;
- int ttlg; /* 2^lg */
- int ause = 0; /* summation of `nums' */
- int i = 1; /* count to traverse all array keys */
- for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
- int lc = 0; /* counter */
- int lim = ttlg;
+ unsigned int ttlg; /* 2^lg */
+ unsigned int ause = 0; /* summation of 'nums' */
+ unsigned int i = 1; /* count to traverse all array keys */
+ /* traverse each slice */
+ for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) {
+ unsigned int lc = 0; /* counter */
+ unsigned int lim = ttlg;
if (lim > t->sizearray) {
lim = t->sizearray; /* adjust upper limit */
if (i > lim)
break; /* no more elements to count */
}
- /* count elements in range (2^(lg-1), 2^lg] */
+ /* count elements in range (2^(lg - 1), 2^lg] */
for (; i <= lim; i++) {
if (!ttisnil(&t->array[i-1]))
lc++;
@@ -251,9 +281,10 @@ static int numusearray (const Table *t, int *nums) {
}
-static int numusehash (const Table *t, int *nums, int *pnasize) {
+static int numusehash (const Table *t, unsigned int *nums,
+ unsigned int *pnasize) {
int totaluse = 0; /* total number of elements */
- int ause = 0; /* summation of `nums' */
+ int ause = 0; /* elements added to 'nums' (can go to array part) */
int i = sizenode(t);
while (i--) {
Node *n = &t->node[i];
@@ -267,8 +298,8 @@ static int numusehash (const Table *t, int *nums, int *pnasize) {
}
-static void setarrayvector (lua_State *L, Table *t, int size) {
- int i;
+static void setarrayvector (lua_State *L, Table *t, unsigned int size) {
+ unsigned int i;
luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
for (i=t->sizearray; iarray[i]);
@@ -276,23 +307,23 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
}
-static void setnodevector (lua_State *L, Table *t, int size) {
+static void setnodevector (lua_State *L, Table *t, unsigned int size) {
int lsize;
if (size == 0) { /* no elements to hash part? */
- t->node = cast(Node *, dummynode); /* use common `dummynode' */
+ t->node = cast(Node *, dummynode); /* use common 'dummynode' */
lsize = 0;
}
else {
int i;
lsize = luaO_ceillog2(size);
- if (lsize > MAXBITS)
+ if (lsize > MAXHBITS)
luaG_runerror(L, "table overflow");
size = twoto(lsize);
t->node = luaM_newvector(L, size, Node);
- for (i=0; isizearray;
+void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
+ unsigned int nhsize) {
+ unsigned int i;
+ int j;
+ unsigned int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
Node *nold = t->node; /* save old hash ... */
if (nasize > oldasize) /* array part must grow? */
@@ -321,8 +354,8 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
}
/* re-insert elements from hash part */
- for (i = twoto(oldhsize) - 1; i >= 0; i--) {
- Node *old = nold+i;
+ for (j = twoto(oldhsize) - 1; j >= 0; j--) {
+ Node *old = nold + j;
if (!ttisnil(gval(old))) {
/* doesn't need barrier/invalidate cache, as entry was
already present in the table */
@@ -334,18 +367,20 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
}
-void luaH_resizearray (lua_State *L, Table *t, int nasize) {
+void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
int nsize = isdummy(t->node) ? 0 : sizenode(t);
luaH_resize(L, t, nasize, nsize);
}
-
+/*
+** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
+*/
static void rehash (lua_State *L, Table *t, const TValue *ek) {
- int nasize, na;
- int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */
+ unsigned int nasize, na;
+ unsigned int nums[MAXABITS + 1];
int i;
int totaluse;
- for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
+ for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */
nasize = numusearray(t, nums); /* count keys in array part */
totaluse = nasize; /* all those keys are integer keys */
totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
@@ -366,7 +401,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
Table *luaH_new (lua_State *L) {
- Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h;
+ GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table));
+ Table *t = gco2t(o);
t->metatable = NULL;
t->flags = cast_byte(~0);
t->array = NULL;
@@ -404,37 +440,52 @@ static Node *getfreepos (Table *t) {
*/
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp;
+ TValue aux;
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
- else if (ttisnumber(key) && luai_numisnan(L, nvalue(key)))
- luaG_runerror(L, "table index is NaN");
+ else if (ttisfloat(key)) {
+ lua_Number n = fltvalue(key);
+ lua_Integer k;
+ if (luai_numisnan(n))
+ luaG_runerror(L, "table index is NaN");
+ if (numisinteger(n, &k)) { /* index is int? */
+ setivalue(&aux, k);
+ key = &aux; /* insert it as an integer */
+ }
+ }
mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
Node *othern;
- Node *n = getfreepos(t); /* get a free place */
- if (n == NULL) { /* cannot find a free place? */
+ Node *f = getfreepos(t); /* get a free place */
+ if (f == NULL) { /* cannot find a free place? */
rehash(L, t, key); /* grow table */
- /* whatever called 'newkey' take care of TM cache and GC barrier */
+ /* whatever called 'newkey' takes care of TM cache and GC barrier */
return luaH_set(L, t, key); /* insert key into grown table */
}
- lua_assert(!isdummy(n));
+ lua_assert(!isdummy(f));
othern = mainposition(t, gkey(mp));
if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */
- while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
- gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
- *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
- gnext(mp) = NULL; /* now `mp' is free */
+ while (othern + gnext(othern) != mp) /* find previous */
+ othern += gnext(othern);
+ gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */
+ *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+ if (gnext(mp) != 0) {
+ gnext(f) += cast_int(mp - f); /* correct 'next' */
+ gnext(mp) = 0; /* now 'mp' is free */
+ }
setnilvalue(gval(mp));
}
else { /* colliding node is in its own main position */
/* new node will go into free position */
- gnext(n) = gnext(mp); /* chain new position */
- gnext(mp) = n;
- mp = n;
+ if (gnext(mp) != 0)
+ gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */
+ else lua_assert(gnext(f) == 0);
+ gnext(mp) = cast_int(f - mp);
+ mp = f;
}
}
- setobj2t(L, gkey(mp), key);
- luaC_barrierback(L, obj2gco(t), key);
+ setnodekey(L, &mp->i_key, key);
+ luaC_barrierback(L, t, key);
lua_assert(ttisnil(gval(mp)));
return gval(mp);
}
@@ -443,18 +494,21 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
/*
** search function for integers
*/
-const TValue *luaH_getint (Table *t, int key) {
+const TValue *luaH_getint (Table *t, lua_Integer key) {
/* (1 <= key && key <= t->sizearray) */
- if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
- return &t->array[key-1];
+ if (l_castS2U(key - 1) < t->sizearray)
+ return &t->array[key - 1];
else {
- lua_Number nk = cast_num(key);
- Node *n = hashnum(t, nk);
- do { /* check whether `key' is somewhere in the chain */
- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
+ Node *n = hashint(t, key);
+ for (;;) { /* check whether 'key' is somewhere in the chain */
+ if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
return gval(n); /* that's it */
- else n = gnext(n);
- } while (n);
+ else {
+ int nx = gnext(n);
+ if (nx == 0) break;
+ n += nx;
+ }
+ };
return luaO_nilobject;
}
}
@@ -465,12 +519,17 @@ const TValue *luaH_getint (Table *t, int key) {
*/
const TValue *luaH_getstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
- lua_assert(key->tsv.tt == LUA_TSHRSTR);
- do { /* check whether `key' is somewhere in the chain */
- if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key))
+ lua_assert(key->tt == LUA_TSHRSTR);
+ for (;;) { /* check whether 'key' is somewhere in the chain */
+ const TValue *k = gkey(n);
+ if (ttisshrstring(k) && eqshrstr(tsvalue(k), key))
return gval(n); /* that's it */
- else n = gnext(n);
- } while (n);
+ else {
+ int nx = gnext(n);
+ if (nx == 0) break;
+ n += nx;
+ }
+ };
return luaO_nilobject;
}
@@ -480,23 +539,26 @@ const TValue *luaH_getstr (Table *t, TString *key) {
*/
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
- case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key));
+ case LUA_TSHRSTR: return luaH_getstr(t, tsvalue(key));
+ case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
case LUA_TNIL: return luaO_nilobject;
- case LUA_TNUMBER: {
- int k;
- lua_Number n = nvalue(key);
- lua_number2int(k, n);
- if (luai_numeq(cast_num(k), n)) /* index is int? */
+ case LUA_TNUMFLT: {
+ lua_Integer k;
+ if (numisinteger(fltvalue(key), &k)) /* index is int? */
return luaH_getint(t, k); /* use specialized version */
/* else go through */
}
default: {
Node *n = mainposition(t, key);
- do { /* check whether `key' is somewhere in the chain */
+ for (;;) { /* check whether 'key' is somewhere in the chain */
if (luaV_rawequalobj(gkey(n), key))
return gval(n); /* that's it */
- else n = gnext(n);
- } while (n);
+ else {
+ int nx = gnext(n);
+ if (nx == 0) break;
+ n += nx;
+ }
+ };
return luaO_nilobject;
}
}
@@ -515,14 +577,14 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
}
-void luaH_setint (lua_State *L, Table *t, int key, TValue *value) {
+void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
const TValue *p = luaH_getint(t, key);
TValue *cell;
if (p != luaO_nilobject)
cell = cast(TValue *, p);
else {
TValue k;
- setnvalue(&k, cast_num(key));
+ setivalue(&k, key);
cell = luaH_newkey(L, t, &k);
}
setobj2t(L, cell, value);
@@ -532,16 +594,16 @@ void luaH_setint (lua_State *L, Table *t, int key, TValue *value) {
static int unbound_search (Table *t, unsigned int j) {
unsigned int i = j; /* i is zero or a present index */
j++;
- /* find `i' and `j' such that i is present and j is not */
+ /* find 'i' and 'j' such that i is present and j is not */
while (!ttisnil(luaH_getint(t, j))) {
i = j;
- j *= 2;
- if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */
/* table was built with bad purposes: resort to linear search */
i = 1;
while (!ttisnil(luaH_getint(t, i))) i++;
return i - 1;
}
+ j *= 2;
}
/* now do a binary search between them */
while (j - i > 1) {
@@ -554,7 +616,7 @@ static int unbound_search (Table *t, unsigned int j) {
/*
-** Try to find a boundary in table `t'. A `boundary' is an integer index
+** Try to find a boundary in table 't'. A 'boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
int luaH_getn (Table *t) {
diff --git a/luaxx/ltable.h b/luaxx/ltable.h
index d69449b2..53d25511 100644
--- a/luaxx/ltable.h
+++ b/luaxx/ltable.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 roberto Exp $
+** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -11,26 +11,34 @@
#define gnode(t,i) (&(t)->node[i])
-#define gkey(n) (&(n)->i_key.tvk)
#define gval(n) (&(n)->i_val)
#define gnext(n) ((n)->i_key.nk.next)
+
+/* 'const' to avoid wrong writings that can mess up field 'next' */
+#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk))
+
+#define wgkey(n) (&(n)->i_key.nk)
+
#define invalidateTMcache(t) ((t)->flags = 0)
+
/* returns the key, given the value of a table entry */
#define keyfromval(v) \
(gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
-LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
-LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value);
+LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
+LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
+ TValue *value);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC Table *luaH_new (lua_State *L);
-LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize);
-LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
+LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
+ unsigned int nhsize);
+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
LUAI_FUNC int luaH_getn (Table *t);
diff --git a/luaxx/ltablib.c b/luaxx/ltablib.c
index 6001224e..8f78afb7 100644
--- a/luaxx/ltablib.c
+++ b/luaxx/ltablib.c
@@ -1,23 +1,58 @@
/*
-** $Id: ltablib.c,v 1.65.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
-
-#include
-
#define ltablib_c
#define LUA_LIB
+#include "lprefix.h"
+
+
+#include
+#include
+
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
-#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
+/*
+** Structure with table-access functions
+*/
+typedef struct {
+ int (*geti) (lua_State *L, int idx, lua_Integer n);
+ void (*seti) (lua_State *L, int idx, lua_Integer n);
+} TabA;
+
+
+/*
+** Check that 'arg' has a table and set access functions in 'ta' to raw
+** or non-raw according to the presence of corresponding metamethods.
+*/
+static void checktab (lua_State *L, int arg, TabA *ta) {
+ ta->geti = NULL; ta->seti = NULL;
+ if (lua_getmetatable(L, arg)) {
+ lua_pushliteral(L, "__index"); /* 'index' metamethod */
+ if (lua_rawget(L, -2) != LUA_TNIL)
+ ta->geti = lua_geti;
+ lua_pushliteral(L, "__newindex"); /* 'newindex' metamethod */
+ if (lua_rawget(L, -3) != LUA_TNIL)
+ ta->seti = lua_seti;
+ lua_pop(L, 3); /* pop metatable plus both metamethods */
+ }
+ if (ta->geti == NULL || ta->seti == NULL) {
+ luaL_checktype(L, arg, LUA_TTABLE); /* must be table for raw methods */
+ if (ta->geti == NULL) ta->geti = lua_rawgeti;
+ if (ta->seti == NULL) ta->seti = lua_rawseti;
+ }
+}
+
+
+#define aux_getn(L,n,ta) (checktab(L, n, ta), luaL_len(L, n))
#if defined(LUA_COMPAT_MAXN)
@@ -39,72 +74,110 @@ static int maxn (lua_State *L) {
static int tinsert (lua_State *L) {
- int e = aux_getn(L, 1) + 1; /* first empty element */
- int pos; /* where to insert new element */
+ TabA ta;
+ lua_Integer e = aux_getn(L, 1, &ta) + 1; /* first empty element */
+ lua_Integer pos; /* where to insert new element */
switch (lua_gettop(L)) {
case 2: { /* called with only 2 arguments */
pos = e; /* insert new element at the end */
break;
}
case 3: {
- int i;
- pos = luaL_checkint(L, 2); /* 2nd argument is the position */
+ lua_Integer i;
+ pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
for (i = e; i > pos; i--) { /* move up elements */
- lua_rawgeti(L, 1, i-1);
- lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
+ (*ta.geti)(L, 1, i - 1);
+ (*ta.seti)(L, 1, i); /* t[i] = t[i - 1] */
}
break;
}
default: {
- return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
+ return luaL_error(L, "wrong number of arguments to 'insert'");
}
}
- lua_rawseti(L, 1, pos); /* t[pos] = v */
+ (*ta.seti)(L, 1, pos); /* t[pos] = v */
return 0;
}
static int tremove (lua_State *L) {
- int size = aux_getn(L, 1);
- int pos = luaL_optint(L, 2, size);
+ TabA ta;
+ lua_Integer size = aux_getn(L, 1, &ta);
+ lua_Integer pos = luaL_optinteger(L, 2, size);
if (pos != size) /* validate 'pos' if given */
luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
- lua_rawgeti(L, 1, pos); /* result = t[pos] */
+ (*ta.geti)(L, 1, pos); /* result = t[pos] */
for ( ; pos < size; pos++) {
- lua_rawgeti(L, 1, pos+1);
- lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
+ (*ta.geti)(L, 1, pos + 1);
+ (*ta.seti)(L, 1, pos); /* t[pos] = t[pos + 1] */
}
lua_pushnil(L);
- lua_rawseti(L, 1, pos); /* t[pos] = nil */
+ (*ta.seti)(L, 1, pos); /* t[pos] = nil */
+ return 1;
+}
+
+
+static int tmove (lua_State *L) {
+ TabA ta;
+ lua_Integer f = luaL_checkinteger(L, 2);
+ lua_Integer e = luaL_checkinteger(L, 3);
+ lua_Integer t = luaL_checkinteger(L, 4);
+ int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
+ /* the following restriction avoids several problems with overflows */
+ luaL_argcheck(L, f > 0, 2, "initial position must be positive");
+ if (e >= f) { /* otherwise, nothing to move */
+ lua_Integer n, i;
+ ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL)
+ ? (luaL_checktype(L, 1, LUA_TTABLE), lua_rawgeti)
+ : lua_geti;
+ ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL)
+ ? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti)
+ : lua_seti;
+ n = e - f + 1; /* number of elements to move */
+ if (t > f) {
+ for (i = n - 1; i >= 0; i--) {
+ (*ta.geti)(L, 1, f + i);
+ (*ta.seti)(L, tt, t + i);
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ (*ta.geti)(L, 1, f + i);
+ (*ta.seti)(L, tt, t + i);
+ }
+ }
+ }
+ lua_pushvalue(L, tt); /* return "to table" */
return 1;
}
-static void addfield (lua_State *L, luaL_Buffer *b, int i) {
- lua_rawgeti(L, 1, i);
+static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) {
+ (*ta->geti)(L, 1, i);
if (!lua_isstring(L, -1))
- luaL_error(L, "invalid value (%s) at index %d in table for "
- LUA_QL("concat"), luaL_typename(L, -1), i);
+ luaL_error(L, "invalid value (%s) at index %d in table for 'concat'",
+ luaL_typename(L, -1), i);
luaL_addvalue(b);
}
static int tconcat (lua_State *L) {
+ TabA ta;
luaL_Buffer b;
size_t lsep;
- int i, last;
+ lua_Integer i, last;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
- luaL_checktype(L, 1, LUA_TTABLE);
- i = luaL_optint(L, 3, 1);
- last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
+ checktab(L, 1, &ta);
+ i = luaL_optinteger(L, 3, 1);
+ last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1));
luaL_buffinit(L, &b);
for (; i < last; i++) {
- addfield(L, &b, i);
+ addfield(L, &b, &ta, i);
luaL_addlstring(&b, sep, lsep);
}
if (i == last) /* add last value (if interval was not empty) */
- addfield(L, &b, i);
+ addfield(L, &b, &ta, i);
luaL_pushresult(&b);
return 1;
}
@@ -117,35 +190,34 @@ static int tconcat (lua_State *L) {
*/
static int pack (lua_State *L) {
+ int i;
int n = lua_gettop(L); /* number of elements to pack */
lua_createtable(L, n, 1); /* create result table */
+ lua_insert(L, 1); /* put it at index 1 */
+ for (i = n; i >= 1; i--) /* assign elements */
+ lua_rawseti(L, 1, i);
lua_pushinteger(L, n);
- lua_setfield(L, -2, "n"); /* t.n = number of elements */
- if (n > 0) { /* at least one element? */
- int i;
- lua_pushvalue(L, 1);
- lua_rawseti(L, -2, 1); /* insert first element */
- lua_replace(L, 1); /* move table into index 1 */
- for (i = n; i >= 2; i--) /* assign other elements */
- lua_rawseti(L, 1, i);
- }
+ lua_setfield(L, 1, "n"); /* t.n = number of elements */
return 1; /* return table */
}
static int unpack (lua_State *L) {
- int i, e, n;
- luaL_checktype(L, 1, LUA_TTABLE);
- i = luaL_optint(L, 2, 1);
- e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
+ TabA ta;
+ lua_Integer i, e;
+ lua_Unsigned n;
+ checktab(L, 1, &ta);
+ i = luaL_optinteger(L, 2, 1);
+ e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
if (i > e) return 0; /* empty range */
- n = e - i + 1; /* number of elements */
- if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
+ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
+ if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n)))
return luaL_error(L, "too many results to unpack");
- lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
- while (i++ < e) /* push arg[i + 1...e] */
- lua_rawgeti(L, 1, i);
- return n;
+ do { /* must have at least one element */
+ (*ta.geti)(L, 1, i); /* push arg[i..e] */
+ } while (i++ < e);
+
+ return (int)n;
}
/* }====================================================== */
@@ -155,15 +227,15 @@ static int unpack (lua_State *L) {
/*
** {======================================================
** Quicksort
-** (based on `Algorithms in MODULA-3', Robert Sedgewick;
+** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
** Addison-Wesley, 1993.)
** =======================================================
*/
-static void set2 (lua_State *L, int i, int j) {
- lua_rawseti(L, 1, i);
- lua_rawseti(L, 1, j);
+static void set2 (lua_State *L, TabA *ta, int i, int j) {
+ (*ta->seti)(L, 1, i);
+ (*ta->seti)(L, 1, j);
}
static int sort_comp (lua_State *L, int a, int b) {
@@ -171,7 +243,7 @@ static int sort_comp (lua_State *L, int a, int b) {
int res;
lua_pushvalue(L, 2);
lua_pushvalue(L, a-1); /* -1 to compensate function */
- lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
+ lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */
lua_call(L, 2, 1);
res = lua_toboolean(L, -1);
lua_pop(L, 1);
@@ -181,45 +253,45 @@ static int sort_comp (lua_State *L, int a, int b) {
return lua_compare(L, a, b, LUA_OPLT);
}
-static void auxsort (lua_State *L, int l, int u) {
+static void auxsort (lua_State *L, TabA *ta, int l, int u) {
while (l < u) { /* for tail recursion */
int i, j;
/* sort elements a[l], a[(l+u)/2] and a[u] */
- lua_rawgeti(L, 1, l);
- lua_rawgeti(L, 1, u);
+ (*ta->geti)(L, 1, l);
+ (*ta->geti)(L, 1, u);
if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
- set2(L, l, u); /* swap a[l] - a[u] */
+ set2(L, ta, l, u); /* swap a[l] - a[u] */
else
lua_pop(L, 2);
if (u-l == 1) break; /* only 2 elements */
i = (l+u)/2;
- lua_rawgeti(L, 1, i);
- lua_rawgeti(L, 1, l);
+ (*ta->geti)(L, 1, i);
+ (*ta->geti)(L, 1, l);
if (sort_comp(L, -2, -1)) /* a[i]geti)(L, 1, u);
if (sort_comp(L, -1, -2)) /* a[u]geti)(L, 1, i); /* Pivot */
lua_pushvalue(L, -1);
- lua_rawgeti(L, 1, u-1);
- set2(L, i, u-1);
+ (*ta->geti)(L, 1, u-1);
+ set2(L, ta, i, u-1);
/* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
i = l; j = u-1;
for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
/* repeat ++i until a[i] >= P */
- while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
+ while ((*ta->geti)(L, 1, ++i), sort_comp(L, -1, -2)) {
if (i>=u) luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[i] */
}
/* repeat --j until a[j] <= P */
- while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
+ while ((*ta->geti)(L, 1, --j), sort_comp(L, -3, -1)) {
if (j<=l) luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[j] */
}
@@ -227,11 +299,11 @@ static void auxsort (lua_State *L, int l, int u) {
lua_pop(L, 3); /* pop pivot, a[i], a[j] */
break;
}
- set2(L, i, j);
+ set2(L, ta, i, j);
}
- lua_rawgeti(L, 1, u-1);
- lua_rawgeti(L, 1, i);
- set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
+ (*ta->geti)(L, 1, u-1);
+ (*ta->geti)(L, 1, i);
+ set2(L, ta, u-1, i); /* swap pivot (a[u-1]) with a[i] */
/* a[l..i-1] <= a[i] == P <= a[i+1..u] */
/* adjust so that smaller half is in [j..i] and larger one in [l..u] */
if (i-l < u-i) {
@@ -240,17 +312,18 @@ static void auxsort (lua_State *L, int l, int u) {
else {
j=i+1; i=u; u=j-2;
}
- auxsort(L, j, i); /* call recursively the smaller one */
+ auxsort(L, ta, j, i); /* call recursively the smaller one */
} /* repeat the routine for the larger one */
}
static int sort (lua_State *L) {
- int n = aux_getn(L, 1);
- luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
+ TabA ta;
+ int n = (int)aux_getn(L, 1, &ta);
+ luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION);
- lua_settop(L, 2); /* make sure there is two arguments */
- auxsort(L, 1, n);
+ lua_settop(L, 2); /* make sure there are two arguments */
+ auxsort(L, &ta, 1, n);
return 0;
}
@@ -266,6 +339,7 @@ static const luaL_Reg tab_funcs[] = {
{"pack", pack},
{"unpack", unpack},
{"remove", tremove},
+ {"move", tmove},
{"sort", sort},
{NULL, NULL}
};
diff --git a/luaxx/ltm.c b/luaxx/ltm.c
index 69b4ed77..25b46b17 100644
--- a/luaxx/ltm.c
+++ b/luaxx/ltm.c
@@ -1,22 +1,27 @@
/*
-** $Id: ltm.c,v 2.14.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltm.c,v 2.33 2014/11/21 12:15:57 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
-
-#include
-
#define ltm_c
#define LUA_CORE
+#include "lprefix.h"
+
+
+#include
+
#include "lua.h"
+#include "ldebug.h"
+#include "ldo.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
+#include "lvm.h"
static const char udatatypename[] = "userdata";
@@ -25,7 +30,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
"no value",
"nil", "boolean", udatatypename, "number",
"string", "table", "function", udatatypename, "thread",
- "proto", "upval" /* these last two cases are used for tests only */
+ "proto" /* this last case is used for tests only */
};
@@ -33,14 +38,16 @@ void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex",
"__gc", "__mode", "__len", "__eq",
- "__add", "__sub", "__mul", "__div", "__mod",
- "__pow", "__unm", "__lt", "__le",
+ "__add", "__sub", "__mul", "__mod", "__pow",
+ "__div", "__idiv",
+ "__band", "__bor", "__bxor", "__shl", "__shr",
+ "__unm", "__bnot", "__lt", "__le",
"__concat", "__call"
};
int i;
for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]);
- luaS_fix(G(L)->tmname[i]); /* never collect these names */
+ luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */
}
}
@@ -62,7 +69,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
Table *mt;
- switch (ttypenv(o)) {
+ switch (ttnov(o)) {
case LUA_TTABLE:
mt = hvalue(o)->metatable;
break;
@@ -70,8 +77,67 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
mt = uvalue(o)->metatable;
break;
default:
- mt = G(L)->mt[ttypenv(o)];
+ mt = G(L)->mt[ttnov(o)];
}
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}
+
+void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, TValue *p3, int hasres) {
+ ptrdiff_t result = savestack(L, p3);
+ setobj2s(L, L->top++, f); /* push function (assume EXTRA_STACK) */
+ setobj2s(L, L->top++, p1); /* 1st argument */
+ setobj2s(L, L->top++, p2); /* 2nd argument */
+ if (!hasres) /* no result? 'p3' is third argument */
+ setobj2s(L, L->top++, p3); /* 3rd argument */
+ /* metamethod may yield only when called from Lua code */
+ luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
+ if (hasres) { /* if has result, move it to its place */
+ p3 = restorestack(L, result);
+ setobjs2s(L, p3, --L->top);
+ }
+}
+
+
+int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ if (ttisnil(tm))
+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
+ if (ttisnil(tm)) return 0;
+ luaT_callTM(L, tm, p1, p2, res, 1);
+ return 1;
+}
+
+
+void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ if (!luaT_callbinTM(L, p1, p2, res, event)) {
+ switch (event) {
+ case TM_CONCAT:
+ luaG_concaterror(L, p1, p2);
+ case TM_BAND: case TM_BOR: case TM_BXOR:
+ case TM_SHL: case TM_SHR: case TM_BNOT: {
+ lua_Number dummy;
+ if (tonumber(p1, &dummy) && tonumber(p2, &dummy))
+ luaG_tointerror(L, p1, p2);
+ else
+ luaG_opinterror(L, p1, p2, "perform bitwise operation on");
+ /* else go through */
+ }
+ default:
+ luaG_opinterror(L, p1, p2, "perform arithmetic on");
+ }
+ }
+}
+
+
+int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
+ TMS event) {
+ if (!luaT_callbinTM(L, p1, p2, L->top, event))
+ return -1; /* no metamethod */
+ else
+ return !l_isfalse(L->top);
+}
+
diff --git a/luaxx/ltm.h b/luaxx/ltm.h
index 7f89c841..180179ce 100644
--- a/luaxx/ltm.h
+++ b/luaxx/ltm.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltm.h,v 2.21 2014/10/25 11:50:46 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -13,7 +13,7 @@
/*
* WARNING: if you change the order of this enumeration,
-* grep "ORDER TM"
+* grep "ORDER TM" and "ORDER OP"
*/
typedef enum {
TM_INDEX,
@@ -21,14 +21,21 @@ typedef enum {
TM_GC,
TM_MODE,
TM_LEN,
- TM_EQ, /* last tag method with `fast' access */
+ TM_EQ, /* last tag method with fast access */
TM_ADD,
TM_SUB,
TM_MUL,
- TM_DIV,
TM_MOD,
TM_POW,
+ TM_DIV,
+ TM_IDIV,
+ TM_BAND,
+ TM_BOR,
+ TM_BXOR,
+ TM_SHL,
+ TM_SHR,
TM_UNM,
+ TM_BNOT,
TM_LT,
TM_LE,
TM_CONCAT,
@@ -44,7 +51,7 @@ typedef enum {
#define fasttm(l,et,e) gfasttm(G(l), et, e)
#define ttypename(x) luaT_typenames_[(x) + 1]
-#define objtypename(x) ttypename(ttypenv(x))
+#define objtypename(x) ttypename(ttnov(x))
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
@@ -54,4 +61,15 @@ LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
TMS event);
LUAI_FUNC void luaT_init (lua_State *L);
+LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, TValue *p3, int hasres);
+LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event);
+LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event);
+LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
+ const TValue *p2, TMS event);
+
+
+
#endif
diff --git a/luaxx/lu8w.c b/luaxx/lu8w.c
index 39fc8153..e31bda18 100644
--- a/luaxx/lu8w.c
+++ b/luaxx/lu8w.c
@@ -2,6 +2,8 @@
UTF-8 Wrapper for Windows
*/
+#include "lprefix.h"
+
#include
#include
#include
diff --git a/luaxx/lu8w.h b/luaxx/lu8w.h
index 11209c70..eaad1014 100644
--- a/luaxx/lu8w.h
+++ b/luaxx/lu8w.h
@@ -51,7 +51,7 @@ int u8rename(const char *oldfname, const char *newfname);
#define system u8system
#define remove u8remove
#define rename u8rename
-#endif /* LUA_CORE or LUA_LIB or lua_c or luac_c */
+#endif /* LUA_U8W or LUA_CORE or LUA_LIB or lua_c or luac_c */
#endif /* not lu8w_c */
#endif /* U8W_H */
diff --git a/luaxx/lua.h b/luaxx/lua.h
index 149a2c37..09a4ccaf 100644
--- a/luaxx/lua.h
+++ b/luaxx/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.285.1.2 2013/11/11 12:09:16 roberto Exp $
+** $Id: lua.h,v 1.325 2014/12/26 17:24:27 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@@ -17,18 +17,18 @@
#define LUA_VERSION_MAJOR "5"
-#define LUA_VERSION_MINOR "2"
-#define LUA_VERSION_NUM 502
-#define LUA_VERSION_RELEASE "3"
+#define LUA_VERSION_MINOR "3"
+#define LUA_VERSION_NUM 503
+#define LUA_VERSION_RELEASE "0"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
-#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio"
+#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
/* mark for precompiled code ('Lua') */
-#define LUA_SIGNATURE "\033Lua"
+#define LUA_SIGNATURE "\x1bLua"
/* option for multiple returns in 'lua_pcall' and 'lua_call' */
#define LUA_MULTRET (-1)
@@ -53,22 +53,6 @@
typedef struct lua_State lua_State;
-typedef int (*lua_CFunction) (lua_State *L);
-
-
-/*
-** functions that read/write blocks when loading/dumping Lua chunks
-*/
-typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
-
-typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
-
-
-/*
-** prototype for memory-allocation functions
-*/
-typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
-
/*
** basic types
@@ -109,6 +93,34 @@ typedef LUA_INTEGER lua_Integer;
/* unsigned integer type */
typedef LUA_UNSIGNED lua_Unsigned;
+/* type for continuation-function contexts */
+typedef LUA_KCONTEXT lua_KContext;
+
+
+/*
+** Type for C functions registered with Lua
+*/
+typedef int (*lua_CFunction) (lua_State *L);
+
+/*
+** Type for continuation functions
+*/
+typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);
+
+
+/*
+** Type for functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud);
+
+
+/*
+** Type for memory-allocation functions
+*/
+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
+
/*
@@ -145,11 +157,9 @@ LUA_API int (lua_absindex) (lua_State *L, int idx);
LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
-LUA_API void (lua_remove) (lua_State *L, int idx);
-LUA_API void (lua_insert) (lua_State *L, int idx);
-LUA_API void (lua_replace) (lua_State *L, int idx);
+LUA_API void (lua_rotate) (lua_State *L, int idx, int n);
LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
-LUA_API int (lua_checkstack) (lua_State *L, int sz);
+LUA_API int (lua_checkstack) (lua_State *L, int n);
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
@@ -161,13 +171,13 @@ LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int (lua_isinteger) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp);
LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum);
-LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum);
LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_rawlen) (lua_State *L, int idx);
@@ -181,13 +191,20 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx);
** Comparison and arithmetic functions
*/
-#define LUA_OPADD 0 /* ORDER TM */
+#define LUA_OPADD 0 /* ORDER TM, ORDER OP */
#define LUA_OPSUB 1
#define LUA_OPMUL 2
-#define LUA_OPDIV 3
-#define LUA_OPMOD 4
-#define LUA_OPPOW 5
-#define LUA_OPUNM 6
+#define LUA_OPMOD 3
+#define LUA_OPPOW 4
+#define LUA_OPDIV 5
+#define LUA_OPIDIV 6
+#define LUA_OPBAND 7
+#define LUA_OPBOR 8
+#define LUA_OPBXOR 9
+#define LUA_OPSHL 10
+#define LUA_OPSHR 11
+#define LUA_OPUNM 12
+#define LUA_OPBNOT 13
LUA_API void (lua_arith) (lua_State *L, int op);
@@ -205,8 +222,7 @@ LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op);
LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
-LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n);
-LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l);
+LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
@@ -220,26 +236,29 @@ LUA_API int (lua_pushthread) (lua_State *L);
/*
** get functions (Lua -> stack)
*/
-LUA_API void (lua_getglobal) (lua_State *L, const char *var);
-LUA_API void (lua_gettable) (lua_State *L, int idx);
-LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
-LUA_API void (lua_rawget) (lua_State *L, int idx);
-LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
-LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p);
+LUA_API int (lua_getglobal) (lua_State *L, const char *name);
+LUA_API int (lua_gettable) (lua_State *L, int idx);
+LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
+LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
+LUA_API int (lua_rawget) (lua_State *L, int idx);
+LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
+LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
+
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
-LUA_API void (lua_getuservalue) (lua_State *L, int idx);
+LUA_API int (lua_getuservalue) (lua_State *L, int idx);
/*
** set functions (stack -> Lua)
*/
-LUA_API void (lua_setglobal) (lua_State *L, const char *var);
+LUA_API void (lua_setglobal) (lua_State *L, const char *name);
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawset) (lua_State *L, int idx);
-LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API void (lua_setuservalue) (lua_State *L, int idx);
@@ -248,31 +267,31 @@ LUA_API void (lua_setuservalue) (lua_State *L, int idx);
/*
** 'load' and 'call' functions (load and run Lua code)
*/
-LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
- lua_CFunction k);
+LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults,
+ lua_KContext ctx, lua_KFunction k);
#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
-LUA_API int (lua_getctx) (lua_State *L, int *ctx);
-
LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
- int ctx, lua_CFunction k);
+ lua_KContext ctx, lua_KFunction k);
#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
- const char *chunkname,
- const char *mode);
+ const char *chunkname, const char *mode);
-LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
/*
** coroutine functions
*/
-LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx,
- lua_CFunction k);
+LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
+ lua_KFunction k);
+LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg);
+LUA_API int (lua_status) (lua_State *L);
+LUA_API int (lua_isyieldable) (lua_State *L);
+
#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
-LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg);
-LUA_API int (lua_status) (lua_State *L);
+
/*
** garbage-collection function and options
@@ -286,10 +305,7 @@ LUA_API int (lua_status) (lua_State *L);
#define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
-#define LUA_GCSETMAJORINC 8
#define LUA_GCISRUNNING 9
-#define LUA_GCGEN 10
-#define LUA_GCINC 11
LUA_API int (lua_gc) (lua_State *L, int what, int data);
@@ -305,20 +321,23 @@ LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API void (lua_len) (lua_State *L, int idx);
+LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s);
+
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
/*
-** ===============================================================
+** {==============================================================
** some useful macros
** ===============================================================
*/
-#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL)
-#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL)
-#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL)
+#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
+
+#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL)
+#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL)
#define lua_pop(L,n) lua_settop(L, -(n)-1)
@@ -346,6 +365,28 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
+#define lua_insert(L,idx) lua_rotate(L, (idx), 1)
+
+#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
+
+#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
+
+/* }============================================================== */
+
+
+/*
+** {==============================================================
+** compatibility macros for unsigned conversions
+** ===============================================================
+*/
+#if defined(LUA_COMPAT_APIINTCASTS)
+
+#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
+#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is))
+#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
+
+#endif
+/* }============================================================== */
/*
** {======================================================================
@@ -390,7 +431,7 @@ LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n);
LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
-LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook (lua_gethook) (lua_State *L);
LUA_API int (lua_gethookmask) (lua_State *L);
LUA_API int (lua_gethookcount) (lua_State *L);
@@ -418,7 +459,7 @@ struct lua_Debug {
/******************************************************************************
-* Copyright (C) 1994-2013 Lua.org, PUC-Rio.
+* Copyright (C) 1994-2015 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
diff --git a/luaxx/luaconf.h b/luaxx/luaconf.h
index c6e3a3cb..333459c7 100644
--- a/luaxx/luaconf.h
+++ b/luaxx/luaconf.h
@@ -1,112 +1,187 @@
/*
-** $Id: luaconf.h,v 1.176.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: luaconf.h,v 1.238 2014/12/29 13:27:55 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
-#ifndef lconfig_h
-#define lconfig_h
+#ifndef luaconf_h
+#define luaconf_h
#include
#include
-#include "lu8w.h"
/*
-** ==================================================================
+** ===================================================================
** Search for "@@" to find all configurable definitions.
** ===================================================================
*/
/*
-@@ LUA_ANSI controls the use of non-ansi features.
-** CHANGE it (define it) if you want Lua to avoid the use of any
-** non-ansi feature or library.
+** {====================================================================
+** System Configuration: macros to adapt (if needed) Lua to some
+** particular platform, for instance compiling it with 32-bit numbers or
+** restricting it to C89.
+** =====================================================================
*/
-#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__)
-#define LUA_ANSI
-#endif
+/*
+@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You
+** can also define LUA_32BITS in the make file, but changing here you
+** ensure that all software connected to Lua will be compiled with the
+** same configuration.
+*/
+/* #define LUA_32BITS */
-#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE)
-#define LUA_WIN /* enable goodies for regular Windows platforms */
-#endif
-#if defined(LUA_WIN)
-#define LUA_DL_DLL
-#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
+/*
+@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
+** Define it if you want Lua to avoid the use of a few C99 features
+** or Windows-specific features on Windows.
+*/
+/* #define LUA_USE_C89 */
+
+
+/*
+** By default, Lua on Windows use (some) specific Windows features
+*/
+#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE)
+#define LUA_USE_WINDOWS /* enable goodies for regular Windows */
#endif
+#if defined(LUA_USE_WINDOWS)
+#define LUA_DL_DLL /* enable support for DLL */
+#define LUA_USE_C89 /* broadly, Windows is C89 */
+#endif
+
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
-#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */
-#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
-#define LUA_USE_LONGLONG /* assume support for long long */
#endif
+
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
-#define LUA_USE_DLOPEN /* does not need -ldl */
+#define LUA_USE_DLOPEN /* MacOS does not need -ldl */
#define LUA_USE_READLINE /* needs an extra library: -lreadline */
-#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */
-#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
-#define LUA_USE_LONGLONG /* assume support for long long */
#endif
+/*
+@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
+** C89 ('long' and 'double'); Windows always has '__int64', so it does
+** not need to use this case.
+*/
+#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
+#define LUA_C89_NUMBERS
+#endif
+
+
+
+/*
+@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'.
+*/
+/* avoid undefined shifts */
+#if ((INT_MAX >> 15) >> 15) >= 1
+#define LUAI_BITSINT 32
+#else
+/* 'int' always must have at least 16 bits */
+#define LUAI_BITSINT 16
+#endif
+
+
+/*
+@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines the type for
+** Lua integers.
+@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines
+** the type for Lua floats.
+** Lua should work fine with any mix of these options (if supported
+** by your C compiler). The usual configurations are 64-bit integers
+** and 'double' (the default), 32-bit integers and 'float' (for
+** restricted platforms), and 'long'/'double' (for C compilers not
+** compliant with C99, which may not have support for 'long long').
+*/
+#if defined(LUA_32BITS) /* { */
/*
-@@ LUA_USE_POSIX includes all functionality listed as X/Open System
-@* Interfaces Extension (XSI).
-** CHANGE it (define it) if your system is XSI compatible.
+** 32-bit integers and 'float'
*/
-#if defined(LUA_USE_POSIX)
-#define LUA_USE_MKSTEMP
-#define LUA_USE_ISATTY
-#define LUA_USE_POPEN
-#define LUA_USE_ULONGJMP
-#define LUA_USE_GMTIME_R
+#if LUAI_BITSINT >= 32 /* use 'int' if big enough */
+#define LUA_INT_INT
+#else /* otherwise use 'long' */
+#define LUA_INT_LONG
#endif
+#define LUA_REAL_FLOAT
+
+#elif defined(LUA_C89_NUMBERS) /* }{ */
+/*
+** largest types available for C89 ('long' and 'double')
+*/
+#define LUA_INT_LONG
+#define LUA_REAL_DOUBLE
+
+#else /* }{ */
+/*
+** default configuration for 64-bit Lua ('long long' and 'double')
+*/
+#define LUA_INT_LONGLONG
+#define LUA_REAL_DOUBLE
+
+#endif /* } */
+
+/* }================================================================== */
+
+/*
+** {==================================================================
+** Configuration for Paths.
+** ===================================================================
+*/
+
/*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
-@* Lua libraries.
+** Lua libraries.
@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
-@* C libraries.
+** C libraries.
** CHANGE them if your machine has a non-conventional directory
** hierarchy or if you want to install your libraries in
** non-conventional directories.
*/
-#if defined(_WIN32) /* { */
+#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
+#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
- LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua"
+ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
+ LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
+ ".\\?.lua;" ".\\?\\init.lua"
#define LUA_CPATH_DEFAULT \
- LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll"
+ LUA_CDIR"?.dll;" \
+ LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
+ LUA_CDIR"loadall.dll;" ".\\?.dll"
#else /* }{ */
-#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/"
#define LUA_ROOT "/usr/local/"
-#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR
-#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR
+#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
+#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
- LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua"
+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
+ "./?.lua;" "./?/init.lua"
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
#endif /* } */
@@ -123,14 +198,14 @@
#define LUA_DIRSEP "/"
#endif
+/* }================================================================== */
+
/*
-@@ LUA_ENV is the name of the variable that holds the current
-@@ environment, used to access global names.
-** CHANGE it if you do not like this name.
+** {==================================================================
+** Marks for exported symbols in the C code
+** ===================================================================
*/
-#define LUA_ENV "_ENV"
-
/*
@@ LUA_API is a mark for all core API functions.
@@ -163,10 +238,10 @@
/*
@@ LUAI_FUNC is a mark for all extern functions that are not to be
-@* exported to outside modules.
+** exported to outside modules.
@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables
-@* that are not to be exported to outside modules (LUAI_DDEF for
-@* definitions and LUAI_DDEC for declarations).
+** that are not to be exported to outside modules (LUAI_DDEF for
+** definitions and LUAI_DDEC for declarations).
** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library. Not all elf targets support
@@ -178,78 +253,66 @@
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
-#define LUAI_DDEC LUAI_FUNC
-#define LUAI_DDEF /* empty */
-
#else /* }{ */
#define LUAI_FUNC extern
-#define LUAI_DDEC extern
-#define LUAI_DDEF /* empty */
#endif /* } */
+#define LUAI_DDEC LUAI_FUNC
+#define LUAI_DDEF /* empty */
+
+/* }================================================================== */
/*
-@@ LUA_QL describes how error messages quote program elements.
-** CHANGE it if you want a different appearance.
+** {==================================================================
+** Compatibility with previous versions
+** ===================================================================
*/
-#define LUA_QL(x) "'" x "'"
-#define LUA_QS LUA_QL("%s")
-
/*
-@@ LUA_IDSIZE gives the maximum size for the description of the source
-@* of a function in debug information.
-** CHANGE it if you want a different size.
+@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2.
+@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1.
+** You can define it to get all options, or change specific options
+** to fit your specific needs.
*/
-#define LUA_IDSIZE 60
-
+#if defined(LUA_COMPAT_5_2) /* { */
/*
-@@ luai_writestring/luai_writeline define how 'print' prints its results.
-** They are only used in libraries and the stand-alone program. (The #if
-** avoids including 'stdio.h' everywhere.)
+@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
+** functions in the mathematical library.
*/
-#if defined(LUA_LIB) || defined(lua_c)
-#include
-#ifdef U8W_H
-#define luai_writestring(s,l) fprintf(stdout, "%s", s)
-#else
-#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
-#endif
-#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout))
-#endif
+#define LUA_COMPAT_MATHLIB
/*
-@@ luai_writestringerror defines how to print error messages.
-** (A format string with one argument is enough for Lua...)
+@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'.
*/
-#define luai_writestringerror(s,p) \
- (fprintf(stderr, (s), (p)), fflush(stderr))
-
+#define LUA_COMPAT_BITLIB
/*
-@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
-** strings that are internalized. (Cannot be smaller than reserved words
-** or tags for metamethods, as these strings must be internalized;
-** #("function") = 8, #("__newindex") = 10.)
+@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod.
*/
-#define LUAI_MAXSHORTLEN 40
-
-
+#define LUA_COMPAT_IPAIRS
/*
-** {==================================================================
-** Compatibility with previous versions
-** ===================================================================
+@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
+** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
+** luaL_checkint, luaL_checklong, etc.)
*/
+#define LUA_COMPAT_APIINTCASTS
+
/*
-@@ LUA_COMPAT_ALL controls all compatibility options.
-** You can define it to get all options, or change specific options
-** to fit your specific needs.
+@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
+@@ a float mark ('.0').
+** This macro is not on by default even in compatibility mode,
+** because this is not really an incompatibility.
*/
-#if defined(LUA_COMPAT_ALL) /* { */
+/* #define LUA_COMPAT_FLOATSTRING */
+
+#endif /* } */
+
+
+#if defined(LUA_COMPAT_5_1) /* { */
/*
@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
@@ -315,131 +378,119 @@
/*
-@@ LUAI_BITSINT defines the number of bits in an int.
-** CHANGE here if Lua cannot automatically detect the number of bits of
-** your machine. Probably you do not need to change this.
+** {==================================================================
+** Configuration for Numbers.
+** Change these definitions if no predefined LUA_REAL_* / LUA_INT_*
+** satisfy your needs.
+** ===================================================================
*/
-/* avoid overflows in comparison */
-#if INT_MAX-20 < 32760 /* { */
-#define LUAI_BITSINT 16
-#elif INT_MAX > 2147483640L /* }{ */
-/* int has at least 32 bits */
-#define LUAI_BITSINT 32
-#else /* }{ */
-#error "you must define LUA_BITSINT with number of bits in an integer"
-#endif /* } */
-
/*
-@@ LUA_INT32 is an signed integer with exactly 32 bits.
-@@ LUAI_UMEM is an unsigned integer big enough to count the total
-@* memory used by Lua.
-@@ LUAI_MEM is a signed integer big enough to count the total memory
-@* used by Lua.
-** CHANGE here if for some weird reason the default definitions are not
-** good enough for your machine. Probably you do not need to change
-** this.
+@@ LUA_NUMBER is the floating-point type used by Lua.
+**
+@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+@@ over a floating number.
+**
+@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
+@@ LUA_NUMBER_FMT is the format for writing floats.
+@@ lua_number2str converts a float to a string.
+**
+@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
+**
+@@ lua_str2number converts a decimal numeric string to a number.
*/
-#if LUAI_BITSINT >= 32 /* { */
-#define LUA_INT32 int
-#define LUAI_UMEM size_t
-#define LUAI_MEM ptrdiff_t
-#else /* }{ */
-/* 16-bit ints */
-#define LUA_INT32 long
-#define LUAI_UMEM unsigned long
-#define LUAI_MEM long
-#endif /* } */
+#if defined(LUA_REAL_FLOAT) /* { single float */
-/*
-@@ LUAI_MAXSTACK limits the size of the Lua stack.
-** CHANGE it if you need a different limit. This limit is arbitrary;
-** its only purpose is to stop Lua to consume unlimited stack
-** space (and to reserve some numbers for pseudo-indices).
-*/
-#if LUAI_BITSINT >= 32
-#define LUAI_MAXSTACK 1000000
-#else
-#define LUAI_MAXSTACK 15000
-#endif
+#define LUA_NUMBER float
-/* reserve some space for error handling */
-#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
+#define LUAI_UACNUMBER double
+#define LUA_NUMBER_FRMLEN ""
+#define LUA_NUMBER_FMT "%.7g"
+#define l_mathop(op) op##f
+#define lua_str2number(s,p) strtof((s), (p))
-/*
-@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
-** CHANGE it if it uses too much C-stack space.
-*/
-#define LUAL_BUFFERSIZE BUFSIZ
+#elif defined(LUA_REAL_LONGDOUBLE) /* }{ long double */
+#define LUA_NUMBER long double
+#define LUAI_UACNUMBER long double
-/*
-** {==================================================================
-@@ LUA_NUMBER is the type of numbers in Lua.
-** CHANGE the following definitions only if you want to build Lua
-** with a number type different from double. You may also need to
-** change lua_number2int & lua_number2integer.
-** ===================================================================
-*/
+#define LUA_NUMBER_FRMLEN "L"
+#define LUA_NUMBER_FMT "%.19Lg"
+
+#define l_mathop(op) op##l
+
+#define lua_str2number(s,p) strtold((s), (p))
+
+#elif defined(LUA_REAL_DOUBLE) /* }{ double */
-#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double
-/*
-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
-@* over a number.
-*/
#define LUAI_UACNUMBER double
-
-/*
-@@ LUA_NUMBER_SCAN is the format for reading numbers.
-@@ LUA_NUMBER_FMT is the format for writing numbers.
-@@ lua_number2str converts a number to a string.
-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
-*/
-#define LUA_NUMBER_SCAN "%lf"
+#define LUA_NUMBER_FRMLEN ""
#define LUA_NUMBER_FMT "%.14g"
-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+#define l_mathop(op) op
-/*
-@@ l_mathop allows the addition of an 'l' or 'f' to all math operations
-*/
-#define l_mathop(x) (x)
+#define lua_str2number(s,p) strtod((s), (p))
+
+#else /* }{ */
+
+#error "numeric real type not defined"
+
+#endif /* } */
+
+
+#define l_floor(x) (l_mathop(floor)(x))
+
+#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
/*
-@@ lua_str2number converts a decimal numeric string to a number.
-@@ lua_strx2number converts an hexadecimal numeric string to a number.
-** In C99, 'strtod' does both conversions. C89, however, has no function
-** to convert floating hexadecimal strings to numbers. For these
-** systems, you can leave 'lua_strx2number' undefined and Lua will
-** provide its own implementation.
+@@ lua_numbertointeger converts a float number to an integer, or
+** returns 0 if float is not within the range of a lua_Integer.
+** (The range comparisons are tricky because of rounding. The tests
+** here assume a two-complement representation, where MININTEGER always
+** has an exact representation as a float; MAXINTEGER may not have one,
+** and therefore its conversion to float may have an ill-defined value.)
*/
-#define lua_str2number(s,p) strtod((s), (p))
-
-#if defined(LUA_USE_STRTODHEX)
-#define lua_strx2number(s,p) strtod((s), (p))
-#endif
+#define lua_numbertointeger(n,p) \
+ ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
+ (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
+ (*(p) = (LUA_INTEGER)(n), 1))
/*
@@ The luai_num* macros define the primitive operations over numbers.
+** They should work for any size of floating numbers.
*/
/* the following operations need the math library */
#if defined(lobject_c) || defined(lvm_c)
#include
-#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b))
-#define luai_numpow(L,a,b) (l_mathop(pow)(a,b))
+
+/* floor division (defined as 'floor(a/b)') */
+#define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)(luai_numdiv(L,a,b)))
+
+/*
+** module: defined as 'a - floor(a/b)*b'; the previous definition gives
+** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the
+** result of 'a - trunc(a/b)*b', and therefore must be corrected when
+** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
+** non-integer negative result, which is equivalent to the test below
+*/
+#define luai_nummod(L,a,b,m) \
+ { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
+
+/* exponentiation */
+#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
+
#endif
/* these are quite standard operations */
@@ -450,97 +501,223 @@
#define luai_numdiv(L,a,b) ((a)/(b))
#define luai_numunm(L,a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
-#define luai_numlt(L,a,b) ((a)<(b))
-#define luai_numle(L,a,b) ((a)<=(b))
-#define luai_numisnan(L,a) (!luai_numeq((a), (a)))
+#define luai_numlt(a,b) ((a)<(b))
+#define luai_numle(a,b) ((a)<=(b))
+#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
+/*
+@@ LUA_INTEGER is the integer type used by Lua.
+**
+@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
+**
+@@ LUAI_UACINT is the result of an 'usual argument conversion'
+@@ over a lUA_INTEGER.
+@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
+@@ LUA_INTEGER_FMT is the format for writing integers.
+@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
+@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
+@@ lua_integer2str converts an integer to a string.
+*/
+
+
+/* The following definitions are good for most cases here */
+
+#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
+#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n))
+
+#define LUAI_UACINT LUA_INTEGER
/*
-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
-** machines, ptrdiff_t gives a good choice between int or long.)
+** use LUAI_UACINT here to avoid problems with promotions (which
+** can turn a comparison between unsigneds into a signed comparison)
*/
-#define LUA_INTEGER ptrdiff_t
+#define LUA_UNSIGNED unsigned LUAI_UACINT
+
+
+/* now the variable definitions */
+
+#if defined(LUA_INT_INT) /* { int */
+
+#define LUA_INTEGER int
+#define LUA_INTEGER_FRMLEN ""
+
+#define LUA_MAXINTEGER INT_MAX
+#define LUA_MININTEGER INT_MIN
+
+#elif defined(LUA_INT_LONG) /* }{ long */
+
+#define LUA_INTEGER long
+#define LUA_INTEGER_FRMLEN "l"
+
+#define LUA_MAXINTEGER LONG_MAX
+#define LUA_MININTEGER LONG_MIN
+
+#elif defined(LUA_INT_LONGLONG) /* }{ long long */
+
+#if defined(LLONG_MAX) /* { */
+/* use ISO C99 stuff */
+
+#define LUA_INTEGER long long
+#define LUA_INTEGER_FRMLEN "ll"
+
+#define LUA_MAXINTEGER LLONG_MAX
+#define LUA_MININTEGER LLONG_MIN
+
+#elif defined(LUA_USE_WINDOWS) /* }{ */
+/* in Windows, can use specific Windows types */
+
+#define LUA_INTEGER __int64
+#define LUA_INTEGER_FRMLEN "I64"
+
+#define LUA_MAXINTEGER _I64_MAX
+#define LUA_MININTEGER _I64_MIN
+
+#else /* }{ */
+
+#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
+ or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
+
+#endif /* } */
+
+#else /* }{ */
+
+#error "numeric integer type not defined"
+
+#endif /* } */
+
+/* }================================================================== */
+
/*
-@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned.
-** It must have at least 32 bits.
+** {==================================================================
+** Dependencies with C99
+** ===================================================================
*/
-#define LUA_UNSIGNED unsigned LUA_INT32
+/*
+@@ lua_strx2number converts an hexadecimal numeric string to a number.
+** In C99, 'strtod' does both conversions. Otherwise, you can
+** leave 'lua_strx2number' undefined and Lua will provide its own
+** implementation.
+*/
+#if !defined(LUA_USE_C89)
+#define lua_strx2number(s,p) lua_str2number(s,p)
+#endif
/*
-** Some tricks with doubles
+@@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format'
+** Enable it if the C function 'printf' supports these specifiers.
+** (C99 demands it and Windows also supports it.)
*/
+#if !defined(LUA_USE_C89) || defined(LUA_USE_WINDOWS)
+#define LUA_USE_AFORMAT
+#endif
+
-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
/*
-** The next definitions activate some tricks to speed up the
-** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
-**
-@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a
-** DirectX idiosyncrasy.
-**
-@@ LUA_IEEE754TRICK uses a trick that should work on any machine
-** using IEEE754 with a 32-bit integer type.
-**
-@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be
-** defined when LUA_INTEGER is a 32-bit integer.
-**
-@@ 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 for LUA_IEEE754TRICK (but not for LUA_NANTRICK).
-**
-@@ LUA_NANTRICK 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).
+** 'strtof' and 'opf' variants for math functions are not valid in
+** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the
+** availability of these variants. ('math.h' is already included in
+** all files that use these macros.)
*/
+#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF))
+#undef l_mathop /* variants not available */
+#undef lua_str2number
+#define l_mathop(op) (lua_Number)op /* no variant */
+#define lua_str2number(s,p) ((lua_Number)strtod((s), (p)))
+#endif
-/* Microsoft compiler on a Pentium (32 bit) ? */
-#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
-#define LUA_MSASMTRICK
-#define LUA_IEEEENDIAN 0
-#define LUA_NANTRICK
+/*
+@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation
+** functions. It must be a numerical type; Lua will use 'intptr_t' if
+** available, otherwise it will use 'ptrdiff_t' (the nearest thing to
+** 'intptr_t' in C89)
+*/
+#define LUA_KCONTEXT ptrdiff_t
+#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
+ __STDC_VERSION__ >= 199901L
+#include
+#if defined (INTPTR_MAX) /* even in C99 this type is optional */
+#undef LUA_KCONTEXT
+#define LUA_KCONTEXT intptr_t
+#endif
+#endif
-/* pentium 32 bits? */
-#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */
+/* }================================================================== */
-#define LUA_IEEE754TRICK
-#define LUA_IEEELL
-#define LUA_IEEEENDIAN 0
-#define LUA_NANTRICK
-/* pentium 64 bits? */
-#elif defined(__x86_64) /* }{ */
+/*
+** {==================================================================
+** Macros that affect the API and must be stable (that is, must be the
+** same when you compile Lua and when you compile code that links to
+** Lua). You probably do not want/need to change them.
+** =====================================================================
+*/
-#define LUA_IEEE754TRICK
-#define LUA_IEEEENDIAN 0
+/*
+@@ LUAI_MAXSTACK limits the size of the Lua stack.
+** CHANGE it if you need a different limit. This limit is arbitrary;
+** its only purpose is to stop Lua from consuming unlimited stack
+** space (and to reserve some numbers for pseudo-indices).
+*/
+#if LUAI_BITSINT >= 32
+#define LUAI_MAXSTACK 1000000
+#else
+#define LUAI_MAXSTACK 15000
+#endif
-#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */
+/* reserve some space for error handling */
+#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
-#define LUA_IEEE754TRICK
-#define LUA_IEEEENDIAN 1
-#else /* }{ */
+/*
+@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
+** a Lua state with very fast access.
+** CHANGE it if you need a different size.
+*/
+#define LUA_EXTRASPACE (sizeof(void *))
-/* assume IEEE754 and a 32-bit integer type */
-#define LUA_IEEE754TRICK
-#endif /* } */
+/*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@@ of a function in debug information.
+** CHANGE it if you want a different size.
+*/
+#define LUA_IDSIZE 60
+
+
+/*
+@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
+** strings that are internalized. (Cannot be smaller than reserved words
+** or tags for metamethods, as these strings must be internalized;
+** #("function") = 8, #("__newindex") = 10.)
+*/
+#define LUAI_MAXSHORTLEN 40
-#endif /* } */
+
+/*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+** CHANGE it if it uses too much C-stack space.
+*/
+#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
/* }================================================================== */
+/*
+@@ LUA_QL describes how error messages quote program elements.
+** Lua does not use these macros anymore; they are here for
+** compatibility only.
+*/
+#define LUA_QL(x) "'" x "'"
+#define LUA_QS LUA_QL("%s")
+
+
/* =================================================================== */
@@ -551,6 +728,8 @@
*/
+#include "lu8w.h"
+
#endif
diff --git a/luaxx/lualib.h b/luaxx/lualib.h
index da82005c..5165c0fb 100644
--- a/luaxx/lualib.h
+++ b/luaxx/lualib.h
@@ -1,5 +1,5 @@
/*
-** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
@@ -29,6 +29,9 @@ LUAMOD_API int (luaopen_os) (lua_State *L);
#define LUA_STRLIBNAME "string"
LUAMOD_API int (luaopen_string) (lua_State *L);
+#define LUA_UTF8LIBNAME "utf8"
+LUAMOD_API int (luaopen_utf8) (lua_State *L);
+
#define LUA_BITLIBNAME "bit32"
LUAMOD_API int (luaopen_bit32) (lua_State *L);
diff --git a/luaxx/luaxx.vcxproj b/luaxx/luaxx.vcxproj
index 0256da9a..97713dee 100644
--- a/luaxx/luaxx.vcxproj
+++ b/luaxx/luaxx.vcxproj
@@ -68,25 +68,25 @@
true
- lua52
+ lua53
$(SolutionDir)$(Platform)\$(Configuration)\
$(Platform)\$(Configuration)\
true
- lua52
+ lua53
$(SolutionDir)$(Platform)\$(Configuration)\
$(Platform)\$(Configuration)\
false
- lua52
+ lua53
$(SolutionDir)$(Platform)\$(Configuration)\
$(Platform)\$(Configuration)\
false
- lua52
+ lua53
$(SolutionDir)$(Platform)\$(Configuration)\
$(Platform)\$(Configuration)\
@@ -95,7 +95,7 @@
Use
Level3
Disabled
- LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ LUA_BUILD_AS_DLL;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
stdafx.h
@@ -109,7 +109,7 @@
Use
Level3
Disabled
- LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ LUA_BUILD_AS_DLL;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
stdafx.h
@@ -125,7 +125,7 @@
MaxSpeed
true
true
- LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ LUA_BUILD_AS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
stdafx.h
@@ -142,7 +142,7 @@
MaxSpeed
true
true
- LUA_BUILD_AS_DLL;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ LUA_BUILD_AS_DLL;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
stdafx.h
@@ -167,6 +167,7 @@
+
@@ -213,6 +214,7 @@
+
diff --git a/luaxx/luaxx.vcxproj.filters b/luaxx/luaxx.vcxproj.filters
index 15ede838..a21ddf81 100644
--- a/luaxx/luaxx.vcxproj.filters
+++ b/luaxx/luaxx.vcxproj.filters
@@ -60,6 +60,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -194,6 +197,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/luaxx/lundump.c b/luaxx/lundump.c
index 4163cb5d..510f3258 100644
--- a/luaxx/lundump.c
+++ b/luaxx/lundump.c
@@ -1,14 +1,17 @@
/*
-** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lundump.c,v 2.41 2014/11/02 19:19:04 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
-#include
-
#define lundump_c
#define LUA_CORE
+#include "lprefix.h"
+
+
+#include
+
#include "lua.h"
#include "ldebug.h"
@@ -20,239 +23,255 @@
#include "lundump.h"
#include "lzio.h"
+
+#if !defined(luai_verifycode)
+#define luai_verifycode(L,b,f) /* empty */
+#endif
+
+
typedef struct {
- lua_State* L;
- ZIO* Z;
- Mbuffer* b;
- const char* name;
+ lua_State *L;
+ ZIO *Z;
+ Mbuffer *b;
+ const char *name;
} LoadState;
-static l_noret error(LoadState* S, const char* why)
-{
- luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
- luaD_throw(S->L,LUA_ERRSYNTAX);
+
+static l_noret error(LoadState *S, const char *why) {
+ luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
+ luaD_throw(S->L, LUA_ERRSYNTAX);
}
-#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
-#define LoadByte(S) (lu_byte)LoadChar(S)
-#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
-#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
-#if !defined(luai_verifycode)
-#define luai_verifycode(L,b,f) /* empty */
-#endif
+/*
+** All high-level loads go through LoadVector; you can change it to
+** adapt to the endianness of the input
+*/
+#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0]))
+
+static void LoadBlock (LoadState *S, void *b, size_t size) {
+ if (luaZ_read(S->Z, b, size) != 0)
+ error(S, "truncated");
+}
+
+
+#define LoadVar(S,x) LoadVector(S,&x,1)
+
+
+static lu_byte LoadByte (LoadState *S) {
+ lu_byte x;
+ LoadVar(S, x);
+ return x;
+}
+
+
+static int LoadInt (LoadState *S) {
+ int x;
+ LoadVar(S, x);
+ return x;
+}
+
-static void LoadBlock(LoadState* S, void* b, size_t size)
-{
- if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated");
+static lua_Number LoadNumber (LoadState *S) {
+ lua_Number x;
+ LoadVar(S, x);
+ return x;
}
-static int LoadChar(LoadState* S)
-{
- char x;
- LoadVar(S,x);
- return x;
+
+static lua_Integer LoadInteger (LoadState *S) {
+ lua_Integer x;
+ LoadVar(S, x);
+ return x;
}
-static int LoadInt(LoadState* S)
-{
- int x;
- LoadVar(S,x);
- if (x<0) error(S,"corrupted");
- return x;
+
+static TString *LoadString (LoadState *S) {
+ size_t size = LoadByte(S);
+ if (size == 0xFF)
+ LoadVar(S, size);
+ if (size == 0)
+ return NULL;
+ else {
+ char *s = luaZ_openspace(S->L, S->b, --size);
+ LoadVector(S, s, size);
+ return luaS_newlstr(S->L, s, size);
+ }
}
-static lua_Number LoadNumber(LoadState* S)
-{
- lua_Number x;
- LoadVar(S,x);
- return x;
+
+static void LoadCode (LoadState *S, Proto *f) {
+ int n = LoadInt(S);
+ f->code = luaM_newvector(S->L, n, Instruction);
+ f->sizecode = n;
+ LoadVector(S, f->code, n);
}
-static TString* LoadString(LoadState* S)
-{
- size_t size;
- LoadVar(S,size);
- if (size==0)
- return NULL;
- else
- {
- char* s=luaZ_openspace(S->L,S->b,size);
- LoadBlock(S,s,size*sizeof(char));
- return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
- }
+
+static void LoadFunction(LoadState *S, Proto *f, TString *psource);
+
+
+static void LoadConstants (LoadState *S, Proto *f) {
+ int i;
+ int n = LoadInt(S);
+ f->k = luaM_newvector(S->L, n, TValue);
+ f->sizek = n;
+ for (i = 0; i < n; i++)
+ setnilvalue(&f->k[i]);
+ for (i = 0; i < n; i++) {
+ TValue *o = &f->k[i];
+ int t = LoadByte(S);
+ switch (t) {
+ case LUA_TNIL:
+ setnilvalue(o);
+ break;
+ case LUA_TBOOLEAN:
+ setbvalue(o, LoadByte(S));
+ break;
+ case LUA_TNUMFLT:
+ setfltvalue(o, LoadNumber(S));
+ break;
+ case LUA_TNUMINT:
+ setivalue(o, LoadInteger(S));
+ break;
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
+ setsvalue2n(S->L, o, LoadString(S));
+ break;
+ default:
+ lua_assert(0);
+ }
+ }
}
-static void LoadCode(LoadState* S, Proto* f)
-{
- int n=LoadInt(S);
- f->code=luaM_newvector(S->L,n,Instruction);
- f->sizecode=n;
- LoadVector(S,f->code,n,sizeof(Instruction));
+
+static void LoadProtos (LoadState *S, Proto *f) {
+ int i;
+ int n = LoadInt(S);
+ f->p = luaM_newvector(S->L, n, Proto *);
+ f->sizep = n;
+ for (i = 0; i < n; i++)
+ f->p[i] = NULL;
+ for (i = 0; i < n; i++) {
+ f->p[i] = luaF_newproto(S->L);
+ LoadFunction(S, f->p[i], f->source);
+ }
}
-static void LoadFunction(LoadState* S, Proto* f);
-
-static void LoadConstants(LoadState* S, Proto* f)
-{
- int i,n;
- n=LoadInt(S);
- f->k=luaM_newvector(S->L,n,TValue);
- f->sizek=n;
- for (i=0; ik[i]);
- for (i=0; ik[i];
- int t=LoadChar(S);
- switch (t)
- {
- case LUA_TNIL:
- setnilvalue(o);
- break;
- case LUA_TBOOLEAN:
- setbvalue(o,LoadChar(S));
- break;
- case LUA_TNUMBER:
- setnvalue(o,LoadNumber(S));
- break;
- case LUA_TSTRING:
- setsvalue2n(S->L,o,LoadString(S));
- break;
- default: lua_assert(0);
+
+static void LoadUpvalues (LoadState *S, Proto *f) {
+ int i, n;
+ n = LoadInt(S);
+ f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
+ f->sizeupvalues = n;
+ for (i = 0; i < n; i++)
+ f->upvalues[i].name = NULL;
+ for (i = 0; i < n; i++) {
+ f->upvalues[i].instack = LoadByte(S);
+ f->upvalues[i].idx = LoadByte(S);
}
- }
- n=LoadInt(S);
- f->p=luaM_newvector(S->L,n,Proto*);
- f->sizep=n;
- for (i=0; ip[i]=NULL;
- for (i=0; ip[i]=luaF_newproto(S->L);
- LoadFunction(S,f->p[i]);
- }
}
-static void LoadUpvalues(LoadState* S, Proto* f)
-{
- int i,n;
- n=LoadInt(S);
- f->upvalues=luaM_newvector(S->L,n,Upvaldesc);
- f->sizeupvalues=n;
- for (i=0; iupvalues[i].name=NULL;
- for (i=0; iupvalues[i].instack=LoadByte(S);
- f->upvalues[i].idx=LoadByte(S);
- }
+
+static void LoadDebug (LoadState *S, Proto *f) {
+ int i, n;
+ n = LoadInt(S);
+ f->lineinfo = luaM_newvector(S->L, n, int);
+ f->sizelineinfo = n;
+ LoadVector(S, f->lineinfo, n);
+ n = LoadInt(S);
+ f->locvars = luaM_newvector(S->L, n, LocVar);
+ f->sizelocvars = n;
+ for (i = 0; i < n; i++)
+ f->locvars[i].varname = NULL;
+ for (i = 0; i < n; i++) {
+ f->locvars[i].varname = LoadString(S);
+ f->locvars[i].startpc = LoadInt(S);
+ f->locvars[i].endpc = LoadInt(S);
+ }
+ n = LoadInt(S);
+ for (i = 0; i < n; i++)
+ f->upvalues[i].name = LoadString(S);
}
-static void LoadDebug(LoadState* S, Proto* f)
-{
- int i,n;
- f->source=LoadString(S);
- n=LoadInt(S);
- f->lineinfo=luaM_newvector(S->L,n,int);
- f->sizelineinfo=n;
- LoadVector(S,f->lineinfo,n,sizeof(int));
- n=LoadInt(S);
- f->locvars=luaM_newvector(S->L,n,LocVar);
- f->sizelocvars=n;
- for (i=0; ilocvars[i].varname=NULL;
- for (i=0; ilocvars[i].varname=LoadString(S);
- f->locvars[i].startpc=LoadInt(S);
- f->locvars[i].endpc=LoadInt(S);
- }
- n=LoadInt(S);
- for (i=0; iupvalues[i].name=LoadString(S);
+
+static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
+ f->source = LoadString(S);
+ if (f->source == NULL) /* no source in dump? */
+ f->source = psource; /* reuse parent's source */
+ f->linedefined = LoadInt(S);
+ f->lastlinedefined = LoadInt(S);
+ f->numparams = LoadByte(S);
+ f->is_vararg = LoadByte(S);
+ f->maxstacksize = LoadByte(S);
+ LoadCode(S, f);
+ LoadConstants(S, f);
+ LoadUpvalues(S, f);
+ LoadProtos(S, f);
+ LoadDebug(S, f);
}
-static void LoadFunction(LoadState* S, Proto* f)
-{
- f->linedefined=LoadInt(S);
- f->lastlinedefined=LoadInt(S);
- f->numparams=LoadByte(S);
- f->is_vararg=LoadByte(S);
- f->maxstacksize=LoadByte(S);
- LoadCode(S,f);
- LoadConstants(S,f);
- LoadUpvalues(S,f);
- LoadDebug(S,f);
+
+static void checkliteral (LoadState *S, const char *s, const char *msg) {
+ char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
+ size_t len = strlen(s);
+ LoadVector(S, buff, len);
+ if (memcmp(s, buff, len) != 0)
+ error(S, msg);
}
-/* the code below must be consistent with the code in luaU_header */
-#define N0 LUAC_HEADERSIZE
-#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char))
-#define N2 N1+2
-#define N3 N2+6
-
-static void LoadHeader(LoadState* S)
-{
- lu_byte h[LUAC_HEADERSIZE];
- lu_byte s[LUAC_HEADERSIZE];
- luaU_header(h);
- memcpy(s,h,sizeof(char)); /* first char already read */
- LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char));
- if (memcmp(h,s,N0)==0) return;
- if (memcmp(h,s,N1)!=0) error(S,"not a");
- if (memcmp(h,s,N2)!=0) error(S,"version mismatch in");
- if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted");
+
+static void fchecksize (LoadState *S, size_t size, const char *tname) {
+ if (LoadByte(S) != size)
+ error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
}
-/*
-** load precompiled chunk
-*/
-Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
-{
- LoadState S;
- Closure* cl;
- if (*name=='@' || *name=='=')
- S.name=name+1;
- else if (*name==LUA_SIGNATURE[0])
- S.name="binary string";
- else
- S.name=name;
- S.L=L;
- S.Z=Z;
- S.b=buff;
- LoadHeader(&S);
- cl=luaF_newLclosure(L,1);
- setclLvalue(L,L->top,cl); incr_top(L);
- cl->l.p=luaF_newproto(L);
- LoadFunction(&S,cl->l.p);
- if (cl->l.p->sizeupvalues != 1)
- {
- Proto* p=cl->l.p;
- cl=luaF_newLclosure(L,cl->l.p->sizeupvalues);
- cl->l.p=p;
- setclLvalue(L,L->top-1,cl);
- }
- luai_verifycode(L,buff,cl->l.p);
- return cl;
+
+#define checksize(S,t) fchecksize(S,sizeof(t),#t)
+
+static void checkHeader (LoadState *S) {
+ checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */
+ if (LoadByte(S) != LUAC_VERSION)
+ error(S, "version mismatch in");
+ if (LoadByte(S) != LUAC_FORMAT)
+ error(S, "format mismatch in");
+ checkliteral(S, LUAC_DATA, "corrupted");
+ checksize(S, int);
+ checksize(S, size_t);
+ checksize(S, Instruction);
+ checksize(S, lua_Integer);
+ checksize(S, lua_Number);
+ if (LoadInteger(S) != LUAC_INT)
+ error(S, "endianness mismatch in");
+ if (LoadNumber(S) != LUAC_NUM)
+ error(S, "float format mismatch in");
}
-#define MYINT(s) (s[0]-'0')
-#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)
-#define FORMAT 0 /* this is the official format */
/*
-* make header for precompiled chunks
-* if you change the code below be sure to update LoadHeader and FORMAT above
-* and LUAC_HEADERSIZE in lundump.h
+** load precompiled chunk
*/
-void luaU_header (lu_byte* h)
-{
- int x=1;
- memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char));
- h+=sizeof(LUA_SIGNATURE)-sizeof(char);
- *h++=cast_byte(VERSION);
- *h++=cast_byte(FORMAT);
- *h++=cast_byte(*(char*)&x); /* endianness */
- *h++=cast_byte(sizeof(int));
- *h++=cast_byte(sizeof(size_t));
- *h++=cast_byte(sizeof(Instruction));
- *h++=cast_byte(sizeof(lua_Number));
- *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */
- memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char));
+LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
+ const char *name) {
+ LoadState S;
+ LClosure *cl;
+ if (*name == '@' || *name == '=')
+ S.name = name + 1;
+ else if (*name == LUA_SIGNATURE[0])
+ S.name = "binary string";
+ else
+ S.name = name;
+ S.L = L;
+ S.Z = Z;
+ S.b = buff;
+ checkHeader(&S);
+ cl = luaF_newLclosure(L, LoadByte(&S));
+ setclLvalue(L, L->top, cl);
+ incr_top(L);
+ cl->p = luaF_newproto(L);
+ LoadFunction(&S, cl->p, NULL);
+ lua_assert(cl->nupvalues == cl->p->sizeupvalues);
+ luai_verifycode(L, buff, cl->p);
+ return cl;
}
+
diff --git a/luaxx/lundump.h b/luaxx/lundump.h
index 5255db25..ef43d512 100644
--- a/luaxx/lundump.h
+++ b/luaxx/lundump.h
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -7,22 +7,27 @@
#ifndef lundump_h
#define lundump_h
+#include "llimits.h"
#include "lobject.h"
#include "lzio.h"
-/* load one chunk; from lundump.c */
-LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
-/* make header; from lundump.c */
-LUAI_FUNC void luaU_header (lu_byte* h);
+/* data to catch conversion errors */
+#define LUAC_DATA "\x19\x93\r\n\x1a\n"
-/* dump one chunk; from ldump.c */
-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+#define LUAC_INT 0x5678
+#define LUAC_NUM cast_num(370.5)
-/* data to catch conversion errors */
-#define LUAC_TAIL "\x19\x93\r\n\x1a\n"
+#define MYINT(s) (s[0]-'0')
+#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
+#define LUAC_FORMAT 0 /* this is the official format */
-/* size in bytes of header of binary files */
-#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char))
+/* load one chunk; from lundump.c */
+LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff,
+ const char* name);
+
+/* dump one chunk; from ldump.c */
+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
+ void* data, int strip);
#endif
diff --git a/luaxx/lutf8lib.c b/luaxx/lutf8lib.c
new file mode 100644
index 00000000..be4f087f
--- /dev/null
+++ b/luaxx/lutf8lib.c
@@ -0,0 +1,255 @@
+/*
+** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $
+** Standard library for UTF-8 manipulation
+** See Copyright Notice in lua.h
+*/
+
+#define lutf8lib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
+
+#include
+#include
+#include
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+#define MAXUNICODE 0x10FFFF
+
+#define iscont(p) ((*(p) & 0xC0) == 0x80)
+
+
+/* from strlib */
+/* translate a relative string position: negative means back from end */
+static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
+ if (pos >= 0) return pos;
+ else if (0u - (size_t)pos > len) return 0;
+ else return (lua_Integer)len + pos + 1;
+}
+
+
+/*
+** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
+*/
+static const char *utf8_decode (const char *o, int *val) {
+ static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
+ const unsigned char *s = (const unsigned char *)o;
+ unsigned int c = s[0];
+ unsigned int res = 0; /* final result */
+ if (c < 0x80) /* ascii? */
+ res = c;
+ else {
+ int count = 0; /* to count number of continuation bytes */
+ while (c & 0x40) { /* still have continuation bytes? */
+ int cc = s[++count]; /* read next byte */
+ if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
+ return NULL; /* invalid byte sequence */
+ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
+ c <<= 1; /* to test next bit */
+ }
+ res |= ((c & 0x7F) << (count * 5)); /* add first byte */
+ if (count > 3 || res > MAXUNICODE || res <= limits[count])
+ return NULL; /* invalid byte sequence */
+ s += count; /* skip continuation bytes read */
+ }
+ if (val) *val = res;
+ return (const char *)s + 1; /* +1 to include first byte */
+}
+
+
+/*
+** utf8len(s [, i [, j]]) --> number of characters that start in the
+** range [i,j], or nil + current position if 's' is not well formed in
+** that interval
+*/
+static int utflen (lua_State *L) {
+ int n = 0;
+ size_t len;
+ const char *s = luaL_checklstring(L, 1, &len);
+ lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+ lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
+ luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
+ "initial position out of string");
+ luaL_argcheck(L, --posj < (lua_Integer)len, 3,
+ "final position out of string");
+ while (posi <= posj) {
+ const char *s1 = utf8_decode(s + posi, NULL);
+ if (s1 == NULL) { /* conversion error? */
+ lua_pushnil(L); /* return nil ... */
+ lua_pushinteger(L, posi + 1); /* ... and current position */
+ return 2;
+ }
+ posi = s1 - s;
+ n++;
+ }
+ lua_pushinteger(L, n);
+ return 1;
+}
+
+
+/*
+** codepoint(s, [i, [j]]) -> returns codepoints for all characters
+** that start in the range [i,j]
+*/
+static int codepoint (lua_State *L) {
+ size_t len;
+ const char *s = luaL_checklstring(L, 1, &len);
+ lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+ lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
+ int n;
+ const char *se;
+ luaL_argcheck(L, posi >= 1, 2, "out of range");
+ luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
+ if (posi > pose) return 0; /* empty interval; return no values */
+ n = (int)(pose - posi + 1);
+ if (posi + n <= pose) /* (lua_Integer -> int) overflow? */
+ return luaL_error(L, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
+ n = 0;
+ se = s + pose;
+ for (s += posi - 1; s < se;) {
+ int code;
+ s = utf8_decode(s, &code);
+ if (s == NULL)
+ return luaL_error(L, "invalid UTF-8 code");
+ lua_pushinteger(L, code);
+ n++;
+ }
+ return n;
+}
+
+
+static void pushutfchar (lua_State *L, int arg) {
+ lua_Integer code = luaL_checkinteger(L, arg);
+ luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
+ lua_pushfstring(L, "%U", (long)code);
+}
+
+
+/*
+** utfchar(n1, n2, ...) -> char(n1)..char(n2)...
+*/
+static int utfchar (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ if (n == 1) /* optimize common case of single char */
+ pushutfchar(L, 1);
+ else {
+ int i;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (i = 1; i <= n; i++) {
+ pushutfchar(L, i);
+ luaL_addvalue(&b);
+ }
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+
+/*
+** offset(s, n, [i]) -> index where n-th character counting from
+** position 'i' starts; 0 means character at 'i'.
+*/
+static int byteoffset (lua_State *L) {
+ size_t len;
+ const char *s = luaL_checklstring(L, 1, &len);
+ lua_Integer n = luaL_checkinteger(L, 2);
+ lua_Integer posi = (n >= 0) ? 1 : len + 1;
+ posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
+ luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
+ "position out of range");
+ if (n == 0) {
+ /* find beginning of current byte sequence */
+ while (posi > 0 && iscont(s + posi)) posi--;
+ }
+ else {
+ if (iscont(s + posi))
+ luaL_error(L, "initial position is a continuation byte");
+ if (n < 0) {
+ while (n < 0 && posi > 0) { /* move back */
+ do { /* find beginning of previous character */
+ posi--;
+ } while (posi > 0 && iscont(s + posi));
+ n++;
+ }
+ }
+ else {
+ n--; /* do not move for 1st character */
+ while (n > 0 && posi < (lua_Integer)len) {
+ do { /* find beginning of next character */
+ posi++;
+ } while (iscont(s + posi)); /* (cannot pass final '\0') */
+ n--;
+ }
+ }
+ }
+ if (n == 0) /* did it find given character? */
+ lua_pushinteger(L, posi + 1);
+ else /* no such character */
+ lua_pushnil(L);
+ return 1;
+}
+
+
+static int iter_aux (lua_State *L) {
+ size_t len;
+ const char *s = luaL_checklstring(L, 1, &len);
+ lua_Integer n = lua_tointeger(L, 2) - 1;
+ if (n < 0) /* first iteration? */
+ n = 0; /* start from here */
+ else if (n < (lua_Integer)len) {
+ n++; /* skip current byte */
+ while (iscont(s + n)) n++; /* and its continuations */
+ }
+ if (n >= (lua_Integer)len)
+ return 0; /* no more codepoints */
+ else {
+ int code;
+ const char *next = utf8_decode(s + n, &code);
+ if (next == NULL || iscont(next))
+ return luaL_error(L, "invalid UTF-8 code");
+ lua_pushinteger(L, n + 1);
+ lua_pushinteger(L, code);
+ return 2;
+ }
+}
+
+
+static int iter_codes (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_pushcfunction(L, iter_aux);
+ lua_pushvalue(L, 1);
+ lua_pushinteger(L, 0);
+ return 3;
+}
+
+
+/* pattern to match a single UTF-8 character */
+#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
+
+
+static struct luaL_Reg funcs[] = {
+ {"offset", byteoffset},
+ {"codepoint", codepoint},
+ {"char", utfchar},
+ {"len", utflen},
+ {"codes", iter_codes},
+ /* placeholders */
+ {"charpattern", NULL},
+ {NULL, NULL}
+};
+
+
+LUAMOD_API int luaopen_utf8 (lua_State *L) {
+ luaL_newlib(L, funcs);
+ lua_pushliteral(L, UTF8PATT);
+ lua_setfield(L, -2, "charpattern");
+ return 1;
+}
+
diff --git a/luaxx/lvm.c b/luaxx/lvm.c
index 141b9fd1..2ac1b02d 100644
--- a/luaxx/lvm.c
+++ b/luaxx/lvm.c
@@ -1,17 +1,20 @@
/*
-** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
+#define lvm_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
+#include
#include
#include
#include
-#define lvm_c
-#define LUA_CORE
-
#include "lua.h"
#include "ldebug.h"
@@ -27,121 +30,176 @@
#include "lvm.h"
+/*
+** You can define LUA_FLOORN2I if you want to convert floats to integers
+** by flooring them (instead of raising an error if they are not
+** integral values)
+*/
+#if !defined(LUA_FLOORN2I)
+#define LUA_FLOORN2I 0
+#endif
+
/* limit for table tag-method chains (to avoid loops) */
-#define MAXTAGLOOP 100
+#define MAXTAGLOOP 2000
-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
- lua_Number num;
- if (ttisnumber(obj)) return obj;
- if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
- setnvalue(n, num);
- return n;
+/*
+** Similar to 'tonumber', but does not attempt to convert strings and
+** ensure correct precision (no extra bits). Used in comparisons.
+*/
+static int tofloat (const TValue *obj, lua_Number *n) {
+ if (ttisfloat(obj)) *n = fltvalue(obj);
+ else if (ttisinteger(obj)) {
+ volatile lua_Number x = cast_num(ivalue(obj)); /* avoid extra precision */
+ *n = x;
}
- else
- return NULL;
+ else {
+ *n = 0; /* to avoid warnings */
+ return 0;
+ }
+ return 1;
}
-int luaV_tostring (lua_State *L, StkId obj) {
- if (!ttisnumber(obj))
- return 0;
- else {
- char s[LUAI_MAXNUMBER2STR];
- lua_Number n = nvalue(obj);
- int l = lua_number2str(s, n);
- setsvalue2s(L, obj, luaS_newlstr(L, s, l));
+/*
+** Try to convert a value to a float. The float case is already handled
+** by the macro 'tonumber'.
+*/
+int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
+ TValue v;
+ if (ttisinteger(obj)) {
+ *n = cast_num(ivalue(obj));
return 1;
}
+ else if (cvt2num(obj) && /* string convertible to number? */
+ luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
+ *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
+ return 1;
+ }
+ else
+ return 0; /* conversion failed */
}
-static void traceexec (lua_State *L) {
- CallInfo *ci = L->ci;
- lu_byte mask = L->hookmask;
- int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
- if (counthook)
- resethookcount(L); /* reset count */
- if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
- ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
- return; /* do not call hook again (VM yielded, so it did not move) */
+/*
+** try to convert a value to an integer, rounding according to 'mode':
+** mode == 0: accepts only integral values
+** mode == 1: takes the floor of the number
+** mode == 2: takes the ceil of the number
+*/
+static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
+ TValue v;
+ again:
+ if (ttisfloat(obj)) {
+ lua_Number n = fltvalue(obj);
+ lua_Number f = l_floor(n);
+ if (n != f) { /* not an integral value? */
+ if (mode == 0) return 0; /* fails if mode demands integral value */
+ else if (mode > 1) /* needs ceil? */
+ f += 1; /* convert floor to ceil (remember: n != f) */
+ }
+ return lua_numbertointeger(f, p);
}
- if (counthook)
- luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
- if (mask & LUA_MASKLINE) {
- Proto *p = ci_func(ci)->p;
- int npc = pcRel(ci->u.l.savedpc, p);
- int newline = getfuncline(p, npc);
- if (npc == 0 || /* call linehook when enter a new function, */
- ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */
- newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */
- luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
+ else if (ttisinteger(obj)) {
+ *p = ivalue(obj);
+ return 1;
}
- L->oldpc = ci->u.l.savedpc;
- if (L->status == LUA_YIELD) { /* did hook yield? */
- if (counthook)
- L->hookcount = 1; /* undo decrement to zero */
- ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
- ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
- ci->func = L->top - 1; /* protect stack below results */
- luaD_throw(L, LUA_YIELD);
+ else if (cvt2num(obj) &&
+ luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
+ obj = &v;
+ goto again; /* convert result from 'luaO_str2num' to an integer */
}
+ return 0; /* conversion failed */
}
-static void callTM (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, TValue *p3, int hasres) {
- ptrdiff_t result = savestack(L, p3);
- setobj2s(L, L->top++, f); /* push function */
- setobj2s(L, L->top++, p1); /* 1st argument */
- setobj2s(L, L->top++, p2); /* 2nd argument */
- if (!hasres) /* no result? 'p3' is third argument */
- setobj2s(L, L->top++, p3); /* 3rd argument */
- /* metamethod may yield only when called from Lua code */
- luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
- if (hasres) { /* if has result, move it to its place */
- p3 = restorestack(L, result);
- setobjs2s(L, p3, --L->top);
+/*
+** try to convert a value to an integer
+*/
+int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
+ return tointeger_aux(obj, p, LUA_FLOORN2I);
+}
+
+
+/*
+** Try to convert a 'for' limit to an integer, preserving the
+** semantics of the loop.
+** (The following explanation assumes a non-negative step; it is valid
+** for negative steps mutatis mutandis.)
+** If the limit can be converted to an integer, rounding down, that is
+** it.
+** Otherwise, check whether the limit can be converted to a number. If
+** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
+** which means no limit. If the number is too negative, the loop
+** should not run, because any initial integer value is larger than the
+** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects
+** the extreme case when the initial value is LUA_MININTEGER, in which
+** case the LUA_MININTEGER limit would still run the loop once.
+*/
+static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
+ int *stopnow) {
+ *stopnow = 0; /* usually, let loops run */
+ if (!tointeger_aux(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */
+ lua_Number n; /* try to convert to float */
+ if (!tonumber(obj, &n)) /* cannot convert to float? */
+ return 0; /* not a number */
+ if (n > 0) { /* if true, float is larger than max integer */
+ *p = LUA_MAXINTEGER;
+ if (step < 0) *stopnow = 1;
+ }
+ else { /* float is smaller than min integer */
+ *p = LUA_MININTEGER;
+ if (step >= 0) *stopnow = 1;
+ }
}
+ return 1;
}
+/*
+** Main function for table access (invoking metamethods if needed).
+** Compute 'val = t[key]'
+*/
void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
- int loop;
+ int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
- if (ttistable(t)) { /* `t' is a table? */
+ if (ttistable(t)) { /* 't' is a table? */
Table *h = hvalue(t);
const TValue *res = luaH_get(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is not nil? */
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
- setobj2s(L, val, res);
+ setobj2s(L, val, res); /* result is the raw get */
return;
}
- /* else will try the tag method */
+ /* else will try metamethod */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
- luaG_typeerror(L, t, "index");
- if (ttisfunction(tm)) {
- callTM(L, tm, t, key, val, 1);
+ luaG_typeerror(L, t, "index"); /* no metamethod */
+ if (ttisfunction(tm)) { /* metamethod is a function */
+ luaT_callTM(L, tm, t, key, val, 1);
return;
}
- t = tm; /* else repeat with 'tm' */
+ t = tm; /* else repeat access over 'tm' */
}
- luaG_runerror(L, "loop in gettable");
+ luaG_runerror(L, "gettable chain too long; possible loop");
}
+/*
+** Main function for table assignment (invoking metamethods if needed).
+** Compute 't[key] = val'
+*/
void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
- int loop;
+ int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
- if (ttistable(t)) { /* `t' is a table? */
+ if (ttistable(t)) { /* 't' is a table? */
Table *h = hvalue(t);
TValue *oldval = cast(TValue *, luaH_get(h, key));
/* if previous value is not nil, there must be a previous entry
- in the table; moreover, a metamethod has no relevance */
+ in the table; a metamethod has no relevance */
if (!ttisnil(oldval) ||
/* previous value is nil; must check the metamethod */
((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
@@ -153,7 +211,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
/* no metamethod and (now) there is an entry with given key */
setobj2t(L, oldval, val); /* assign new value to that entry */
invalidateTMcache(h);
- luaC_barrierback(L, obj2gco(h), val);
+ luaC_barrierback(L, h, val);
return;
}
/* else will try the metamethod */
@@ -161,66 +219,40 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
else /* not a table; check metamethod */
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index");
- /* there is a metamethod */
+ /* try the metamethod */
if (ttisfunction(tm)) {
- callTM(L, tm, t, key, val, 0);
+ luaT_callTM(L, tm, t, key, val, 0);
return;
}
- t = tm; /* else repeat with 'tm' */
+ t = tm; /* else repeat assignment over 'tm' */
}
- luaG_runerror(L, "loop in settable");
-}
-
-
-static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
- if (ttisnil(tm))
- tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
- if (ttisnil(tm)) return 0;
- callTM(L, tm, p1, p2, res, 1);
- return 1;
-}
-
-
-static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
- TMS event) {
- const TValue *tm1 = fasttm(L, mt1, event);
- const TValue *tm2;
- if (tm1 == NULL) return NULL; /* no metamethod */
- if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
- tm2 = fasttm(L, mt2, event);
- if (tm2 == NULL) return NULL; /* no metamethod */
- if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */
- return tm1;
- return NULL;
-}
-
-
-static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
- TMS event) {
- if (!call_binTM(L, p1, p2, L->top, event))
- return -1; /* no metamethod */
- else
- return !l_isfalse(L->top);
+ luaG_runerror(L, "settable chain too long; possible loop");
}
+/*
+** Compare two strings 'ls' x 'rs', returning an integer smaller-equal-
+** -larger than zero if 'ls' is smaller-equal-larger than 'rs'.
+** The code is a little tricky because it allows '\0' in the strings
+** and it uses 'strcoll' (to respect locales) for each segments
+** of the strings.
+*/
static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
- size_t ll = ls->tsv.len;
+ size_t ll = ls->len;
const char *r = getstr(rs);
- size_t lr = rs->tsv.len;
- for (;;) {
+ size_t lr = rs->len;
+ for (;;) { /* for each segment */
int temp = strcoll(l, r);
- if (temp != 0) return temp;
- else { /* strings are equal up to a `\0' */
- size_t len = strlen(l); /* index of first `\0' in both strings */
- if (len == lr) /* r is finished? */
- return (len == ll) ? 0 : 1;
- else if (len == ll) /* l is finished? */
- return -1; /* l is smaller than r (because r is not finished) */
- /* both strings longer than `len'; go on comparing (after the `\0') */
+ if (temp != 0) /* not equal? */
+ return temp; /* done */
+ else { /* strings are equal up to a '\0' */
+ size_t len = strlen(l); /* index of first '\0' in both strings */
+ if (len == lr) /* 'rs' is finished? */
+ return (len == ll) ? 0 : 1; /* check 'ls' */
+ else if (len == ll) /* 'ls' is finished? */
+ return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */
+ /* both strings longer than 'len'; go on comparing after the '\0' */
len++;
l += len; ll -= len; r += len; lr -= len;
}
@@ -228,79 +260,113 @@ static int l_strcmp (const TString *ls, const TString *rs) {
}
+/*
+** Main operation less than; return 'l < r'.
+*/
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
- if (ttisnumber(l) && ttisnumber(r))
- return luai_numlt(L, nvalue(l), nvalue(r));
- else if (ttisstring(l) && ttisstring(r))
- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
- else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)
- luaG_ordererror(L, l, r);
+ lua_Number nl, nr;
+ if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
+ return (ivalue(l) < ivalue(r));
+ else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
+ return luai_numlt(nl, nr);
+ else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
+ return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
+ else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
+ luaG_ordererror(L, l, r); /* error */
return res;
}
+/*
+** Main operation less than or equal to; return 'l <= r'.
+*/
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
- if (ttisnumber(l) && ttisnumber(r))
- return luai_numle(L, nvalue(l), nvalue(r));
- else if (ttisstring(l) && ttisstring(r))
- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
- else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */
+ lua_Number nl, nr;
+ if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
+ return (ivalue(l) <= ivalue(r));
+ else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
+ return luai_numle(nl, nr);
+ else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
+ return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
+ else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */
return res;
- else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */
+ else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */
luaG_ordererror(L, l, r);
return !res;
}
/*
-** equality of Lua values. L == NULL means raw equality (no metamethods)
+** Main operation for equality of Lua values; return 't1 == t2'.
+** L == NULL means raw equality (no metamethods)
*/
-int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {
+int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
const TValue *tm;
- lua_assert(ttisequal(t1, t2));
+ if (ttype(t1) != ttype(t2)) { /* not the same variant? */
+ if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
+ return 0; /* only numbers can be equal with different variants */
+ else { /* two numbers with different variants */
+ lua_Number n1, n2; /* compare them as floats */
+ lua_assert(ttisnumber(t1) && ttisnumber(t2));
+ cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2));
+ return luai_numeq(n1, n2);
+ }
+ }
+ /* values have same type and same variant */
switch (ttype(t1)) {
case LUA_TNIL: return 1;
- case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2));
+ case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
case LUA_TLCF: return fvalue(t1) == fvalue(t2);
- case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
- case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
+ case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
+ case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
case LUA_TUSERDATA: {
if (uvalue(t1) == uvalue(t2)) return 1;
else if (L == NULL) return 0;
- tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
+ tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
+ if (tm == NULL)
+ tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
case LUA_TTABLE: {
if (hvalue(t1) == hvalue(t2)) return 1;
else if (L == NULL) return 0;
- tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+ tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
+ if (tm == NULL)
+ tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
default:
- lua_assert(iscollectable(t1));
return gcvalue(t1) == gcvalue(t2);
}
- if (tm == NULL) return 0; /* no TM? */
- callTM(L, tm, t1, t2, L->top, 1); /* call TM */
+ if (tm == NULL) /* no TM? */
+ return 0; /* objects are different */
+ luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */
return !l_isfalse(L->top);
}
+/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */
+#define tostring(L,o) \
+ (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
+
+/*
+** Main operation for concatenation: concat 'total' values in the stack,
+** from 'L->top - total' up to 'L->top - 1'.
+*/
void luaV_concat (lua_State *L, int total) {
lua_assert(total >= 2);
do {
StkId top = L->top;
int n = 2; /* number of elements handled in this pass (at least 2) */
- if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
- if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
- luaG_concaterror(L, top-2, top-1);
- }
+ if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
+ luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
else if (tsvalue(top-1)->len == 0) /* second operand is empty? */
- (void)tostring(L, top - 2); /* result is first operand */
+ cast_void(tostring(L, top - 2)); /* result is first operand */
else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
setobjs2s(L, top - 2, top - 1); /* result is second op. */
}
@@ -312,19 +378,19 @@ void luaV_concat (lua_State *L, int total) {
/* collect total length */
for (i = 1; i < total && tostring(L, top-i-1); i++) {
size_t l = tsvalue(top-i-1)->len;
- if (l >= (MAX_SIZET/sizeof(char)) - tl)
+ if (l >= (MAX_SIZE/sizeof(char)) - tl)
luaG_runerror(L, "string length overflow");
tl += l;
}
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
n = i;
- do { /* concat all strings */
+ do { /* copy all strings to buffer */
size_t l = tsvalue(top-i)->len;
memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
tl += l;
} while (--i > 0);
- setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */
}
total -= n-1; /* got 'n' strings to create 1 new */
L->top -= n-1; /* popped 'n' strings and pushed one */
@@ -332,18 +398,21 @@ void luaV_concat (lua_State *L, int total) {
}
+/*
+** Main operation 'ra' = #rb'.
+*/
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
const TValue *tm;
- switch (ttypenv(rb)) {
+ switch (ttnov(rb)) {
case LUA_TTABLE: {
Table *h = hvalue(rb);
tm = fasttm(L, h->metatable, TM_LEN);
if (tm) break; /* metamethod? break switch to call it */
- setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */
+ setivalue(ra, luaH_getn(h)); /* else primitive len */
return;
}
case LUA_TSTRING: {
- setnvalue(ra, cast_num(tsvalue(rb)->len));
+ setivalue(ra, tsvalue(rb)->len);
return;
}
default: { /* try metamethod */
@@ -353,21 +422,66 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
break;
}
}
- callTM(L, tm, rb, rb, ra, 1);
+ luaT_callTM(L, tm, rb, rb, ra, 1);
+}
+
+
+/*
+** Integer division; return 'm // n', that is, floor(m/n).
+** C division truncates its result (rounds towards zero).
+** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
+** otherwise 'floor(q) == trunc(q) - 1'.
+*/
+lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
+ if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
+ if (n == 0)
+ luaG_runerror(L, "attempt to divide by zero");
+ return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
+ }
+ else {
+ lua_Integer q = m / n; /* perform C division */
+ if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */
+ q -= 1; /* correct result for different rounding */
+ return q;
+ }
}
-void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
- const TValue *rc, TMS op) {
- TValue tempb, tempc;
- const TValue *b, *c;
- if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
- (c = luaV_tonumber(rc, &tempc)) != NULL) {
- lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));
- setnvalue(ra, res);
+/*
+** Integer modulus; return 'm % n'. (Assume that C '%' with
+** negative operands follows C99 behavior. See previous comment
+** about luaV_div.)
+*/
+lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
+ if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
+ if (n == 0)
+ luaG_runerror(L, "attempt to perform 'n%%0'");
+ return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
+ }
+ else {
+ lua_Integer r = m % n;
+ if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */
+ r += n; /* correct result for different rounding */
+ return r;
+ }
+}
+
+
+/* number of bits in an integer */
+#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
+
+/*
+** Shift left operation. (Shift right just negates 'y'.)
+*/
+lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
+ if (y < 0) { /* shift right? */
+ if (y <= -NBITS) return 0;
+ else return intop(>>, x, -y);
+ }
+ else { /* shift left */
+ if (y >= NBITS) return 0;
+ else return intop(<<, x, y);
}
- else if (!call_binTM(L, rb, rc, ra, op))
- luaG_aritherror(L, rb, rc);
}
@@ -376,15 +490,15 @@ void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
** whether there is a cached closure with the same upvalues needed by
** new closure to be created.
*/
-static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
- Closure *c = p->cache;
+static LClosure *getcached (Proto *p, UpVal **encup, StkId base) {
+ LClosure *c = p->cache;
if (c != NULL) { /* is there a cached closure? */
int nup = p->sizeupvalues;
Upvaldesc *uv = p->upvalues;
int i;
for (i = 0; i < nup; i++) { /* check whether it has right upvalues */
TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;
- if (c->l.upvals[i]->v != v)
+ if (c->upvals[i]->v != v)
return NULL; /* wrong upvalue; cannot reuse closure */
}
}
@@ -394,26 +508,28 @@ static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
/*
** create a new Lua closure, push it in the stack, and initialize
-** its upvalues. Note that the call to 'luaC_barrierproto' must come
-** before the assignment to 'p->cache', as the function needs the
-** original value of that field.
+** its upvalues. Note that the closure is not cached if prototype is
+** already black (which means that 'cache' was already cleared by the
+** GC).
*/
static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
StkId ra) {
int nup = p->sizeupvalues;
Upvaldesc *uv = p->upvalues;
int i;
- Closure *ncl = luaF_newLclosure(L, nup);
- ncl->l.p = p;
+ LClosure *ncl = luaF_newLclosure(L, nup);
+ ncl->p = p;
setclLvalue(L, ra, ncl); /* anchor new closure in stack */
for (i = 0; i < nup; i++) { /* fill in its upvalues */
if (uv[i].instack) /* upvalue refers to local variable? */
- ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
+ ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx);
else /* get upvalue from enclosing function */
- ncl->l.upvals[i] = encup[uv[i].idx];
+ ncl->upvals[i] = encup[uv[i].idx];
+ ncl->upvals[i]->refcount++;
+ /* new closure is white, so we do not need a barrier here */
}
- luaC_barrierproto(L, p, ncl);
- p->cache = ncl; /* save it on cache for reuse */
+ if (!isblack(p)) /* cache will not break GC invariant? */
+ p->cache = ncl; /* save it on cache for reuse */
}
@@ -426,8 +542,10 @@ void luaV_finishOp (lua_State *L) {
Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
OpCode op = GET_OPCODE(inst);
switch (op) { /* finish its execution */
- case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
- case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
+ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV:
+ case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
+ case OP_MOD: case OP_POW:
+ case OP_UNM: case OP_BNOT: case OP_LEN:
case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
setobjs2s(L, base + GETARG_A(inst), --L->top);
break;
@@ -446,7 +564,7 @@ void luaV_finishOp (lua_State *L) {
break;
}
case OP_CONCAT: {
- StkId top = L->top - 1; /* top when 'call_binTM' was called */
+ StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */
int b = GETARG_B(inst); /* first element to concatenate */
int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */
setobj2s(L, top - 2, top); /* put TM result in proper position */
@@ -477,8 +595,16 @@ void luaV_finishOp (lua_State *L) {
+
+/*
+** {==================================================================
+** Function 'luaV_execute': main interpreter loop
+** ===================================================================
+*/
+
+
/*
-** some macros for common tasks in `luaV_execute'
+** some macros for common tasks in 'luaV_execute'
*/
#if !defined luai_runtimecheck
@@ -517,19 +643,9 @@ void luaV_finishOp (lua_State *L) {
luai_threadyield(L); )
-#define arith_op(op,tm) { \
- TValue *rb = RKB(i); \
- TValue *rc = RKC(i); \
- if (ttisnumber(rb) && ttisnumber(rc)) { \
- lua_Number nb = nvalue(rb), nc = nvalue(rc); \
- setnvalue(ra, op(L, nb, nc)); \
- } \
- else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
-
-
#define vmdispatch(o) switch(o)
-#define vmcase(l,b) case l: {b} break;
-#define vmcasenb(l,b) case l: {b} /* nb = no break */
+#define vmcase(l) case l:
+#define vmbreak break
void luaV_execute (lua_State *L) {
CallInfo *ci = L->ci;
@@ -547,60 +663,71 @@ void luaV_execute (lua_State *L) {
StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
- Protect(traceexec(L));
+ Protect(luaG_traceexec(L));
}
- /* WARNING: several calls may realloc the stack and invalidate `ra' */
+ /* WARNING: several calls may realloc the stack and invalidate 'ra' */
ra = RA(i);
lua_assert(base == ci->u.l.base);
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
vmdispatch (GET_OPCODE(i)) {
- vmcase(OP_MOVE,
+ vmcase(OP_MOVE) {
setobjs2s(L, ra, RB(i));
- )
- vmcase(OP_LOADK,
+ vmbreak;
+ }
+ vmcase(OP_LOADK) {
TValue *rb = k + GETARG_Bx(i);
setobj2s(L, ra, rb);
- )
- vmcase(OP_LOADKX,
+ vmbreak;
+ }
+ vmcase(OP_LOADKX) {
TValue *rb;
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
rb = k + GETARG_Ax(*ci->u.l.savedpc++);
setobj2s(L, ra, rb);
- )
- vmcase(OP_LOADBOOL,
+ vmbreak;
+ }
+ vmcase(OP_LOADBOOL) {
setbvalue(ra, GETARG_B(i));
if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */
- )
- vmcase(OP_LOADNIL,
+ vmbreak;
+ }
+ vmcase(OP_LOADNIL) {
int b = GETARG_B(i);
do {
setnilvalue(ra++);
} while (b--);
- )
- vmcase(OP_GETUPVAL,
+ vmbreak;
+ }
+ vmcase(OP_GETUPVAL) {
int b = GETARG_B(i);
setobj2s(L, ra, cl->upvals[b]->v);
- )
- vmcase(OP_GETTABUP,
+ vmbreak;
+ }
+ vmcase(OP_GETTABUP) {
int b = GETARG_B(i);
Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
- )
- vmcase(OP_GETTABLE,
+ vmbreak;
+ }
+ vmcase(OP_GETTABLE) {
Protect(luaV_gettable(L, RB(i), RKC(i), ra));
- )
- vmcase(OP_SETTABUP,
+ vmbreak;
+ }
+ vmcase(OP_SETTABUP) {
int a = GETARG_A(i);
Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
- )
- vmcase(OP_SETUPVAL,
+ vmbreak;
+ }
+ vmcase(OP_SETUPVAL) {
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
- luaC_barrier(L, uv, ra);
- )
- vmcase(OP_SETTABLE,
+ luaC_upvalbarrier(L, uv);
+ vmbreak;
+ }
+ vmcase(OP_SETTABLE) {
Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
- )
- vmcase(OP_NEWTABLE,
+ vmbreak;
+ }
+ vmcase(OP_NEWTABLE) {
int b = GETARG_B(i);
int c = GETARG_C(i);
Table *t = luaH_new(L);
@@ -608,49 +735,193 @@ void luaV_execute (lua_State *L) {
if (b != 0 || c != 0)
luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
checkGC(L, ra + 1);
- )
- vmcase(OP_SELF,
+ vmbreak;
+ }
+ vmcase(OP_SELF) {
StkId rb = RB(i);
setobjs2s(L, ra+1, rb);
Protect(luaV_gettable(L, rb, RKC(i), ra));
- )
- vmcase(OP_ADD,
- arith_op(luai_numadd, TM_ADD);
- )
- vmcase(OP_SUB,
- arith_op(luai_numsub, TM_SUB);
- )
- vmcase(OP_MUL,
- arith_op(luai_nummul, TM_MUL);
- )
- vmcase(OP_DIV,
- arith_op(luai_numdiv, TM_DIV);
- )
- vmcase(OP_MOD,
- arith_op(luai_nummod, TM_MOD);
- )
- vmcase(OP_POW,
- arith_op(luai_numpow, TM_POW);
- )
- vmcase(OP_UNM,
+ vmbreak;
+ }
+ vmcase(OP_ADD) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (ttisinteger(rb) && ttisinteger(rc)) {
+ lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+ setivalue(ra, intop(+, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_numadd(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
+ vmbreak;
+ }
+ vmcase(OP_SUB) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (ttisinteger(rb) && ttisinteger(rc)) {
+ lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+ setivalue(ra, intop(-, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_numsub(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); }
+ vmbreak;
+ }
+ vmcase(OP_MUL) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (ttisinteger(rb) && ttisinteger(rc)) {
+ lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+ setivalue(ra, intop(*, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_nummul(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); }
+ vmbreak;
+ }
+ vmcase(OP_DIV) { /* float division (always with floats) */
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_numdiv(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); }
+ vmbreak;
+ }
+ vmcase(OP_BAND) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Integer ib; lua_Integer ic;
+ if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+ setivalue(ra, intop(&, ib, ic));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); }
+ vmbreak;
+ }
+ vmcase(OP_BOR) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Integer ib; lua_Integer ic;
+ if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+ setivalue(ra, intop(|, ib, ic));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); }
+ vmbreak;
+ }
+ vmcase(OP_BXOR) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Integer ib; lua_Integer ic;
+ if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+ setivalue(ra, intop(^, ib, ic));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); }
+ vmbreak;
+ }
+ vmcase(OP_SHL) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Integer ib; lua_Integer ic;
+ if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+ setivalue(ra, luaV_shiftl(ib, ic));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); }
+ vmbreak;
+ }
+ vmcase(OP_SHR) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Integer ib; lua_Integer ic;
+ if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+ setivalue(ra, luaV_shiftl(ib, -ic));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); }
+ vmbreak;
+ }
+ vmcase(OP_MOD) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (ttisinteger(rb) && ttisinteger(rc)) {
+ lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+ setivalue(ra, luaV_mod(L, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ lua_Number m;
+ luai_nummod(L, nb, nc, m);
+ setfltvalue(ra, m);
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); }
+ vmbreak;
+ }
+ vmcase(OP_IDIV) { /* floor division */
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (ttisinteger(rb) && ttisinteger(rc)) {
+ lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+ setivalue(ra, luaV_div(L, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_numidiv(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
+ vmbreak;
+ }
+ vmcase(OP_POW) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_numpow(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
+ vmbreak;
+ }
+ vmcase(OP_UNM) {
+ TValue *rb = RB(i);
+ lua_Number nb;
+ if (ttisinteger(rb)) {
+ lua_Integer ib = ivalue(rb);
+ setivalue(ra, intop(-, 0, ib));
+ }
+ else if (tonumber(rb, &nb)) {
+ setfltvalue(ra, luai_numunm(L, nb));
+ }
+ else {
+ Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
+ }
+ vmbreak;
+ }
+ vmcase(OP_BNOT) {
TValue *rb = RB(i);
- if (ttisnumber(rb)) {
- lua_Number nb = nvalue(rb);
- setnvalue(ra, luai_numunm(L, nb));
+ lua_Integer ib;
+ if (tointeger(rb, &ib)) {
+ setivalue(ra, intop(^, ~l_castS2U(0), ib));
}
else {
- Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
+ Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT));
}
- )
- vmcase(OP_NOT,
+ vmbreak;
+ }
+ vmcase(OP_NOT) {
TValue *rb = RB(i);
int res = l_isfalse(rb); /* next assignment may change this value */
setbvalue(ra, res);
- )
- vmcase(OP_LEN,
+ vmbreak;
+ }
+ vmcase(OP_LEN) {
Protect(luaV_objlen(L, ra, RB(i)));
- )
- vmcase(OP_CONCAT,
+ vmbreak;
+ }
+ vmcase(OP_CONCAT) {
int b = GETARG_B(i);
int c = GETARG_C(i);
StkId rb;
@@ -661,43 +932,49 @@ void luaV_execute (lua_State *L) {
setobjs2s(L, ra, rb);
checkGC(L, (ra >= rb ? ra + 1 : rb));
L->top = ci->top; /* restore top */
- )
- vmcase(OP_JMP,
+ vmbreak;
+ }
+ vmcase(OP_JMP) {
dojump(ci, i, 0);
- )
- vmcase(OP_EQ,
+ vmbreak;
+ }
+ vmcase(OP_EQ) {
TValue *rb = RKB(i);
TValue *rc = RKC(i);
Protect(
- if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))
+ if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
)
- )
- vmcase(OP_LT,
+ vmbreak;
+ }
+ vmcase(OP_LT) {
Protect(
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
)
- )
- vmcase(OP_LE,
+ vmbreak;
+ }
+ vmcase(OP_LE) {
Protect(
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
)
- )
- vmcase(OP_TEST,
+ vmbreak;
+ }
+ vmcase(OP_TEST) {
if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
ci->u.l.savedpc++;
else
donextjump(ci);
- )
- vmcase(OP_TESTSET,
+ vmbreak;
+ }
+ vmcase(OP_TESTSET) {
TValue *rb = RB(i);
if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
ci->u.l.savedpc++;
@@ -705,8 +982,9 @@ void luaV_execute (lua_State *L) {
setobjs2s(L, ra, rb);
donextjump(ci);
}
- )
- vmcase(OP_CALL,
+ vmbreak;
+ }
+ vmcase(OP_CALL) {
int b = GETARG_B(i);
int nresults = GETARG_C(i) - 1;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
@@ -719,8 +997,9 @@ void luaV_execute (lua_State *L) {
ci->callstatus |= CIST_REENTRY;
goto newframe; /* restart luaV_execute over new Lua function */
}
- )
- vmcase(OP_TAILCALL,
+ vmbreak;
+ }
+ vmcase(OP_TAILCALL) {
int b = GETARG_B(i);
if (b != 0) L->top = ra+b; /* else previous instruction set top */
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
@@ -748,8 +1027,9 @@ void luaV_execute (lua_State *L) {
lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
goto newframe; /* restart luaV_execute over new Lua function */
}
- )
- vmcasenb(OP_RETURN,
+ vmbreak;
+ }
+ vmcase(OP_RETURN) {
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
if (cl->p->sizep > 0) luaF_close(L, base);
@@ -763,32 +1043,60 @@ void luaV_execute (lua_State *L) {
lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
goto newframe; /* restart luaV_execute over new Lua function */
}
- )
- vmcase(OP_FORLOOP,
- lua_Number step = nvalue(ra+2);
- lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
- lua_Number limit = nvalue(ra+1);
- if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
- : luai_numle(L, limit, idx)) {
- ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- setnvalue(ra, idx); /* update internal index... */
- setnvalue(ra+3, idx); /* ...and external index */
- }
- )
- vmcase(OP_FORPREP,
- const TValue *init = ra;
- const TValue *plimit = ra+1;
- const TValue *pstep = ra+2;
- if (!tonumber(init, ra))
- luaG_runerror(L, LUA_QL("for") " initial value must be a number");
- else if (!tonumber(plimit, ra+1))
- luaG_runerror(L, LUA_QL("for") " limit must be a number");
- else if (!tonumber(pstep, ra+2))
- luaG_runerror(L, LUA_QL("for") " step must be a number");
- setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
+ }
+ vmcase(OP_FORLOOP) {
+ if (ttisinteger(ra)) { /* integer loop? */
+ lua_Integer step = ivalue(ra + 2);
+ lua_Integer idx = ivalue(ra) + step; /* increment index */
+ lua_Integer limit = ivalue(ra + 1);
+ if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
+ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
+ setivalue(ra, idx); /* update internal index... */
+ setivalue(ra + 3, idx); /* ...and external index */
+ }
+ }
+ else { /* floating loop */
+ lua_Number step = fltvalue(ra + 2);
+ lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
+ lua_Number limit = fltvalue(ra + 1);
+ if (luai_numlt(0, step) ? luai_numle(idx, limit)
+ : luai_numle(limit, idx)) {
+ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
+ setfltvalue(ra, idx); /* update internal index... */
+ setfltvalue(ra + 3, idx); /* ...and external index */
+ }
+ }
+ vmbreak;
+ }
+ vmcase(OP_FORPREP) {
+ TValue *init = ra;
+ TValue *plimit = ra + 1;
+ TValue *pstep = ra + 2;
+ lua_Integer ilimit;
+ int stopnow;
+ if (ttisinteger(init) && ttisinteger(pstep) &&
+ forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
+ /* all values are integer */
+ lua_Integer initv = (stopnow ? 0 : ivalue(init));
+ setivalue(plimit, ilimit);
+ setivalue(init, initv - ivalue(pstep));
+ }
+ else { /* try making all values floats */
+ lua_Number ninit; lua_Number nlimit; lua_Number nstep;
+ if (!tonumber(plimit, &nlimit))
+ luaG_runerror(L, "'for' limit must be a number");
+ setfltvalue(plimit, nlimit);
+ if (!tonumber(pstep, &nstep))
+ luaG_runerror(L, "'for' step must be a number");
+ setfltvalue(pstep, nstep);
+ if (!tonumber(init, &ninit))
+ luaG_runerror(L, "'for' initial value must be a number");
+ setfltvalue(init, luai_numsub(L, ninit, nstep));
+ }
ci->u.l.savedpc += GETARG_sBx(i);
- )
- vmcasenb(OP_TFORCALL,
+ vmbreak;
+ }
+ vmcase(OP_TFORCALL) {
StkId cb = ra + 3; /* call base */
setobjs2s(L, cb+2, ra+2);
setobjs2s(L, cb+1, ra+1);
@@ -800,18 +1108,19 @@ void luaV_execute (lua_State *L) {
ra = RA(i);
lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
goto l_tforloop;
- )
- vmcase(OP_TFORLOOP,
+ }
+ vmcase(OP_TFORLOOP) {
l_tforloop:
if (!ttisnil(ra + 1)) { /* continue loop? */
setobjs2s(L, ra, ra + 1); /* save control variable */
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
}
- )
- vmcase(OP_SETLIST,
+ vmbreak;
+ }
+ vmcase(OP_SETLIST) {
int n = GETARG_B(i);
int c = GETARG_C(i);
- int last;
+ unsigned int last;
Table *h;
if (n == 0) n = cast_int(L->top - ra) - 1;
if (c == 0) {
@@ -826,20 +1135,22 @@ void luaV_execute (lua_State *L) {
for (; n > 0; n--) {
TValue *val = ra+n;
luaH_setint(L, h, last--, val);
- luaC_barrierback(L, obj2gco(h), val);
+ luaC_barrierback(L, h, val);
}
L->top = ci->top; /* correct top (in case of previous open call) */
- )
- vmcase(OP_CLOSURE,
+ vmbreak;
+ }
+ vmcase(OP_CLOSURE) {
Proto *p = cl->p->p[GETARG_Bx(i)];
- Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */
+ LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */
if (ncl == NULL) /* no match? */
pushclosure(L, p, cl->upvals, base, ra); /* create a new one */
else
setclLvalue(L, ra, ncl); /* push cashed closure */
checkGC(L, ra + 1);
- )
- vmcase(OP_VARARG,
+ vmbreak;
+ }
+ vmcase(OP_VARARG) {
int b = GETARG_B(i) - 1;
int j;
int n = cast_int(base - ci->func) - cl->p->numparams - 1;
@@ -857,11 +1168,15 @@ void luaV_execute (lua_State *L) {
setnilvalue(ra + j);
}
}
- )
- vmcase(OP_EXTRAARG,
+ vmbreak;
+ }
+ vmcase(OP_EXTRAARG) {
lua_assert(0);
- )
+ vmbreak;
+ }
}
}
}
+/* }================================================================== */
+
diff --git a/luaxx/lvm.h b/luaxx/lvm.h
index 5380270d..5c5e18c3 100644
--- a/luaxx/lvm.h
+++ b/luaxx/lvm.h
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -13,23 +13,36 @@
#include "ltm.h"
-#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
+#if !defined(LUA_NOCVTN2S)
+#define cvt2str(o) ttisnumber(o)
+#else
+#define cvt2str(o) 0 /* no conversion from numbers to strings */
+#endif
+
+
+#if !defined(LUA_NOCVTS2N)
+#define cvt2num(o) ttisstring(o)
+#else
+#define cvt2num(o) 0 /* no conversion from strings to numbers */
+#endif
-#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
-#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2))
+#define tonumber(o,n) \
+ (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
-#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2)
+#define tointeger(o,i) \
+ (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i))
+#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
-/* not to called directly */
-LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2);
+#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
+LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
-LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
-LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
+LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
+LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p);
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val);
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
@@ -37,8 +50,9 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total);
-LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
- const TValue *rc, TMS op);
+LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
#endif
diff --git a/luaxx/lzio.c b/luaxx/lzio.c
index 20efea98..46493920 100644
--- a/luaxx/lzio.c
+++ b/luaxx/lzio.c
@@ -1,15 +1,17 @@
/*
-** $Id: lzio.c,v 1.35.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/
-
-#include
-
#define lzio_c
#define LUA_CORE
+#include "lprefix.h"
+
+
+#include
+
#include "lua.h"
#include "llimits.h"
diff --git a/luaxx/lzio.h b/luaxx/lzio.h
index 441f7479..b2e56bcd 100644
--- a/luaxx/lzio.h
+++ b/luaxx/lzio.h
@@ -1,5 +1,5 @@
/*
-** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -32,11 +32,13 @@ typedef struct Mbuffer {
#define luaZ_sizebuffer(buff) ((buff)->buffsize)
#define luaZ_bufflen(buff) ((buff)->n)
+#define luaZ_buffremove(buff,i) ((buff)->n -= (i))
#define luaZ_resetbuffer(buff) ((buff)->n = 0)
#define luaZ_resizebuffer(L, buff, size) \
- (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+ ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \
+ (buff)->buffsize, size), \
(buff)->buffsize = size)
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
@@ -45,7 +47,7 @@ typedef struct Mbuffer {
LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data);
-LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
+LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */
@@ -55,7 +57,7 @@ struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Reader reader; /* reader function */
- void* data; /* additional data */
+ void *data; /* additional data */
lua_State *L; /* Lua state (for reader) */
};
diff --git a/luaxx/stdafx.h b/luaxx/stdafx.h
index 44af8f2a..ba97c916 100644
--- a/luaxx/stdafx.h
+++ b/luaxx/stdafx.h
@@ -1,6 +1,8 @@
#pragma once
+#include "lprefix.h"
+
#include
#include
#include