summaryrefslogtreecommitdiff
path: root/src/lobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lobject.c')
-rw-r--r--src/lobject.c126
1 files changed, 88 insertions, 38 deletions
diff --git a/src/lobject.c b/src/lobject.c
index edb0efeb..41bde947 100644
--- a/src/lobject.c
+++ b/src/lobject.c
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.c,v 2.67 2013/06/25 18:58:32 roberto Exp $
+** $Id: lobject.c,v 2.76 2014/03/21 13:52:33 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -77,22 +77,30 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
case LUA_OPSUB:return intop(-, v1, v2);
case LUA_OPMUL:return intop(*, v1, v2);
case LUA_OPMOD: return luaV_mod(L, v1, v2);
- case LUA_OPPOW: return luaV_pow(v1, v2);
- case LUA_OPUNM: return -v1;
+ case LUA_OPPOW: return luaV_pow(L, v1, v2);
+ case LUA_OPIDIV: return luaV_div(L, v1, v2);
+ case LUA_OPBAND: return intop(&, v1, v2);
+ case LUA_OPBOR: return intop(|, v1, v2);
+ case LUA_OPBXOR: return intop(^, v1, v2);
+ case LUA_OPSHL: return luaV_shiftl(v1, v2);
+ case LUA_OPSHR: return luaV_shiftl(v1, -v2);
+ case LUA_OPUNM: return intop(-, 0, v1);
+ case LUA_OPBNOT: return intop(^, cast_integer(-1), v1);
default: lua_assert(0); return 0;
}
}
-static lua_Number numarith (int op, lua_Number v1, lua_Number v2) {
+static lua_Number numarith (lua_State *L, int op, lua_Number v1,
+ lua_Number v2) {
switch (op) {
- case LUA_OPADD: return luai_numadd(NULL, v1, v2);
- case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
- case LUA_OPMUL: return luai_nummul(NULL, v1, v2);
- case LUA_OPDIV: return luai_numdiv(NULL, v1, v2);
- case LUA_OPMOD: return luai_nummod(NULL, v1, v2);
- case LUA_OPPOW: return luai_numpow(NULL, v1, v2);
- case LUA_OPUNM: return luai_numunm(NULL, v1);
+ case LUA_OPADD: return luai_numadd(L, v1, v2);
+ case LUA_OPSUB: return luai_numsub(L, v1, v2);
+ case LUA_OPMUL: return luai_nummul(L, v1, v2);
+ case LUA_OPDIV: return luai_numdiv(L, v1, v2);
+ case LUA_OPMOD: return luai_nummod(L, v1, v2);
+ case LUA_OPPOW: return luai_numpow(L, v1, v2);
+ case LUA_OPUNM: return luai_numunm(L, v1);
default: lua_assert(0); return 0;
}
}
@@ -100,29 +108,40 @@ static lua_Number numarith (int op, lua_Number v1, lua_Number v2) {
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
TValue *res) {
- if (op == LUA_OPIDIV) { /* operates only on integers */
- lua_Integer i1; lua_Integer i2;
- if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
- setivalue(res, luaV_div(L, i1, i2));
- return;
+ switch (op) {
+ case LUA_OPIDIV: case LUA_OPBAND: case LUA_OPBOR:
+ case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR:
+ case LUA_OPBNOT: { /* operates only on integers */
+ lua_Integer i1; lua_Integer i2;
+ if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
+ setivalue(res, intarith(L, op, i1, i2));
+ return;
+ }
+ else break; /* go to the end */
}
- /* else go to the end */
- }
- else { /* other operations */
- lua_Number n1; lua_Number n2;
- if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV &&
- (op != LUA_OPPOW || ivalue(p2) >= 0)) {
- setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
- return;
+ case LUA_OPDIV: { /* operates only on floats */
+ lua_Number n1; lua_Number n2;
+ if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+ setnvalue(res, numarith(L, op, n1, n2));
+ return;
+ }
+ else break; /* go to the end */
}
- else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
- setnvalue(res, numarith(op, n1, n2));
- return;
+ default: { /* other operations */
+ lua_Number n1; lua_Number n2;
+ if (ttisinteger(p1) && ttisinteger(p2)) {
+ setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
+ return;
+ }
+ else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+ setnvalue(res, numarith(L, op, n1, n2));
+ return;
+ }
+ else break; /* go to the end */
}
- /* else go to the end */
}
- /* could not perform raw operation; try metmethod */
- lua_assert(L != NULL); /* cannot fail when folding (compile time) */
+ /* could not perform raw operation; try metamethod */
+ lua_assert(L != NULL); /* should not fail when folding (compile time) */
luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD));
}
@@ -141,22 +160,26 @@ static int isneg (const char **s) {
/*
+** {======================================================
** 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.
+** =======================================================
*/
-#if defined(LUA_USE_STRTODHEX)
+#if !defined(lua_strx2number) /* { */
+
+#if defined(LUA_USE_C99) /* { */
+
#define lua_strx2number(s,p) lua_str2number(s,p)
-#endif
+#else /* }{ */
-#if !defined(lua_strx2number)
+/* Lua's implementation for 'lua_strx2number' */
#include <math.h>
-
/* maximum number of significant digits to read (to avoid overflows
even with single floats) */
#define MAXSIGDIG 30
@@ -219,7 +242,11 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
return l_mathop(ldexp)(r, e);
}
-#endif
+#endif /* } */
+
+#endif /* } */
+
+/* }====================================================== */
int luaO_str2d (const char *s, size_t len, lua_Number *result) {
@@ -260,19 +287,36 @@ int luaO_str2int (const char *s, size_t len, lua_Integer *result) {
while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */
if (empty || s != ends) return 0; /* something wrong in the numeral */
else {
- if (neg) *result = -cast(lua_Integer, a);
- else *result = cast(lua_Integer, a);
+ *result = cast_integer((neg) ? 0u - a : a);
return 1;
}
}
+int luaO_utf8esc (char *buff, unsigned int x) {
+ int n = 1; /* number of bytes put in buffer (backwards) */
+ if (x < 0x80) /* ascii? */
+ buff[UTF8BUFFSZ - 1] = x;
+ else { /* need continuation bytes */
+ unsigned int mfb = 0x3f; /* maximum that fits in first byte */
+ do {
+ buff[UTF8BUFFSZ - (n++)] = 0x80 | (x & 0x3f); /* add continuation byte */
+ 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] = (~mfb << 1) | x; /* add first byte */
+ }
+ return n;
+}
+
+
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 '%L' and '%U' */
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 0;
for (;;) {
@@ -311,6 +355,12 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
pushstr(L, buff, l);
break;
}
+ case 'U': {
+ char buff[UTF8BUFFSZ];
+ int l = luaO_utf8esc(buff, va_arg(argp, int));
+ pushstr(L, buff + UTF8BUFFSZ - l, l);
+ break;
+ }
case '%': {
pushstr(L, "%", 1);
break;