From 69eb64403a608cd00ba76d9bb655fd5e54f49aa9 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 5 Sep 2012 13:56:56 +0000 Subject: [PATCH] Lua 5.2 compatibility fixes. --- src/core/org/luaj/vm2/compiler/FuncState.java | 48 ++++--- src/core/org/luaj/vm2/compiler/LexState.java | 117 ++++++++++++------ 2 files changed, 103 insertions(+), 62 deletions(-) diff --git a/src/core/org/luaj/vm2/compiler/FuncState.java b/src/core/org/luaj/vm2/compiler/FuncState.java index 0f30252a..7678fd06 100644 --- a/src/core/org/luaj/vm2/compiler/FuncState.java +++ b/src/core/org/luaj/vm2/compiler/FuncState.java @@ -279,23 +279,25 @@ public class FuncState extends LuaC { // ============================================================= void nil(int from, int n) { - if (pc > 0 && GET_OPCODE(f.code[pc - 1]) == OP_LOADNIL) { - final int code_prev = f.code[pc - 1]; - int l = from + n - 1; /* last register to set nil */ - int pfrom = GETARG_A(code_prev); - int pl = pfrom + GETARG_B(code_prev); - if ((pfrom <= from && from <= pl + 1) - || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) - from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) - l = pl; /* l = max(l, pl) */ - InstructionPtr previous = new InstructionPtr(this.f.code, this.pc - 1); - SETARG_A(previous, from); - SETARG_B(previous, l - from); - return; - } - } /* else go through */ + int l = from + n - 1; /* last register to set nil */ + if (this.pc > this.lasttarget && pc > 0) { /* no jumps to current position? */ + final int previous_code = f.code[pc - 1]; + if (GET_OPCODE(previous_code) == OP_LOADNIL) { + int pfrom = GETARG_A(previous_code); + int pl = pfrom + GETARG_B(previous_code); + if ((pfrom <= from && from <= pl + 1) + || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) + from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) + l = pl; /* l = max(l, pl) */ + InstructionPtr previous = new InstructionPtr(this.f.code, this.pc - 1); + SETARG_A(previous, from); + SETARG_B(previous, l - from); + return; + } + } /* else go through */ + } this.codeABC(OP_LOADNIL, from, n - 1, 0); } @@ -801,19 +803,15 @@ public class FuncState extends LuaC { int pc; /* pc of last jump */ this.dischargevars(e); switch (e.k) { + case LexState.VJMP: { + pc = e.u.info; + break; + } case LexState.VNIL: case LexState.VFALSE: { pc = LexState.NO_JUMP; /* always false; do nothing */ break; } - case LexState.VTRUE: { - pc = this.jump(); /* always jump */ - break; - } - case LexState.VJMP: { - pc = e.u.info; - break; - } default: { pc = this.jumponcond(e, 1); break; diff --git a/src/core/org/luaj/vm2/compiler/LexState.java b/src/core/org/luaj/vm2/compiler/LexState.java index b5113826..ba2f9240 100644 --- a/src/core/org/luaj/vm2/compiler/LexState.java +++ b/src/core/org/luaj/vm2/compiler/LexState.java @@ -194,7 +194,7 @@ public class LexState { private boolean isxdigit(int c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') - || (c >= 'F' && c <= 'F'); + || (c >= 'A' && c <= 'F'); } private boolean isspace(int c) { @@ -351,47 +351,65 @@ public class LexState { p[n] = to; } - boolean str2d(String str, SemInfo seminfo) { - double d; - str = str.trim(); // TODO: get rid of this - if ( str.startsWith("0x") ) { - d = Long.parseLong(str.substring(2), 16); + LuaValue strx2number(String str, SemInfo seminfo) { + char[] c = str.toCharArray(); + int s = 0; + while ( s < c.length && isspace(c[s])) + ++s; + // Check for negative sign + boolean neg = false; + if (s < c.length && c[s] == '-') { + neg = true; + ++s; } + /* Check for "0x" */ + if (s + 2 >= c.length ) + return LuaValue.ZERO; + if (c[s++] != '0') + return LuaValue.ZERO; + if (c[s] != 'x' && c[s] != 'X') + return LuaValue.ZERO; + ++s; + + // read integer part. + long m = 0; + int e = 0; + while (s < c.length && isxdigit(c[s])) + m = (m << 4) + hexvalue(c[s++]); + if (s < c.length && c[s] == '.') { + ++s; // skip dot + while (s < c.length && isxdigit(c[s])) { + m = (m << 4) + hexvalue(c[s++]); + e -= 4; // Each fractional part shifts right by 2^4 + } + } + if (s < c.length && (c[s] == 'p' || c[s] == 'P')) { + ++s; + int exp1 = 0; + boolean neg1 = false; + if (s < c.length && c[s] == '-') { + neg1 = true; + ++s; + } + while (s < c.length && isdigit(c[s])) + exp1 = exp1 * 10 + c[s++] - '0'; + if (neg1) + exp1 = -exp1; + e += exp1; + } + return e == 0 ? LuaValue.valueOf(m): LuaValue.valueOf(m * Math.pow(2.0, e)); + } + + boolean str2d(String str, SemInfo seminfo) { + if (str.indexOf('n')>=0 || str.indexOf('N')>=0) + seminfo.r = LuaValue.ZERO; + else if (str.indexOf('x')>=0 || str.indexOf('X')>=0) + seminfo.r = strx2number(str, seminfo); else - d = Double.parseDouble(str); - seminfo.r = LuaValue.valueOf(d); + seminfo.r = LuaValue.valueOf(Double.parseDouble(str.trim())); return true; } - // - // TODO: reexamine this source and see if it should be ported differently - // - // static void trydecpoint (LexState *ls, SemInfo *seminfo) { - // /* format error: try to update decimal point separator */ - // struct lconv *cv = localeconv(); - // char old = this.decpoint; - // this.decpoint = (cv ? cv->decimal_point[0] : '.'); - // buffreplace(ls, old, this.decpoint); /* try updated decimal separator */ - // if (!luaO_str2d(luaZ_buffer(this.buff), &seminfo->r)) { - // /* format error with correct decimal point: no more options */ - // buffreplace(ls, this.decpoint, '.'); /* undo change (for error message) */ - // luaX_lexerror(ls, "malformed number", TK_NUMBER); - // } - // } - // - /* - void trydecpoint(String str, SemInfo seminfo) { - NumberFormat nf = NumberFormat.getInstance(); - try { - Number n = nf.parse(str); - double d = n.doubleValue(); - seminfo.r = new LDouble(d); - } catch (ParseException e) { - lexerror("malformed number", TK_NUMBER); - } - } - */ - void read_numeral(SemInfo seminfo) { String expo = "Ee"; int first = current; @@ -478,6 +496,20 @@ public class LexState { seminfo.ts = newstring(buff, 2 + sep, nbuff - 2 * (2 + sep)); } + int hexvalue(int c) { + return c <= '9'? c - '0': c <= 'F'? c + 10 - 'A': c + 10 - 'a'; + } + + int readhexaesc() { + nextChar(); + int c1 = current; + nextChar(); + int c2 = current; + if (!isxdigit(c1) || !isxdigit(c2)) + lexerror("hexadecimal digit expected 'x"+((char)c1)+((char)c2), TK_STRING); + return (hexvalue(c1) << 4) + hexvalue(c2); + } + void read_string(int del, SemInfo seminfo) { save_and_next(); while (current != del) { @@ -514,6 +546,9 @@ public class LexState { case 'v': /* vertical tab */ c = '\u000B'; break; + case 'x': + c = readhexaesc(); + break; case '\n': /* go through */ case '\r': save('\n'); @@ -521,6 +556,14 @@ public class LexState { continue; case EOZ: continue; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + nextChar(); /* skip the 'z' */ + while (isspace(current)) { + if (currIsNewline()) inclinenumber(); + else nextChar(); + } + continue; + } default: { if (!isdigit(current)) save_and_next(); /* handles \\, \", \', and \? */