diff options
Diffstat (limited to 'src/lobject.c')
| -rw-r--r-- | src/lobject.c | 126 |
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; |
