diff -urN lua-5.0.2.orig/src/lcode.c lua-5.0.2/src/lcode.c --- lua-5.0.2.orig/src/lcode.c 2003年04月03日 08:35:34.000000000 -0500 +++ lua-5.0.2/src/lcode.c 2004年06月21日 19:12:54.000000000 -0400 @@ -585,6 +585,17 @@ e->k = VRELOCABLE; } } + else if (op == OPR_BNOT) { + luaK_exp2val(fs, e); + if (e->k == VK && ttisnumber(&fs->f->k[e->info])) + e->info = luaK_numberK(fs, ~ (long) nvalue(&fs->f->k[e->info])); + else { + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + e->info = luaK_codeABC(fs, OP_BNOT, 0, e->info, 0); + e->k = VRELOCABLE; + } + } else /* op == NOT */ codenot(fs, e); } @@ -623,6 +634,11 @@ res->info = luaK_codeABC(fs, opc, 0, o1, o2); res->k = VRELOCABLE; } + else if ((op>= OPR_BAND) && (op <= OPR_BXOR)) { + OpCode opc = cast(OpCode, (op - OPR_BAND) + OP_BAND); /* ORDER OP */ + res->info = luaK_codeABC(fs, opc, 0, o1, o2); + res->k = VRELOCABLE; + } else { /* test operator */ static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE}; int cond = 1; diff -urN lua-5.0.2.orig/src/lcode.h lua-5.0.2/src/lcode.h --- lua-5.0.2.orig/src/lcode.h 2002年12月11日 07:34:22.000000000 -0500 +++ lua-5.0.2/src/lcode.h 2004年06月21日 19:05:05.000000000 -0400 @@ -29,12 +29,13 @@ OPR_NE, OPR_EQ, OPR_LT, OPR_LE, OPR_GT, OPR_GE, OPR_AND, OPR_OR, + OPR_BAND, OPR_BOR, OPR_BXOR, OPR_NOBINOPR } BinOpr; #define binopistest(op) ((op)>= OPR_NE) -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_BNOT, OPR_NOUNOPR } UnOpr; #define getcode(fs,e) ((fs)->f->code[(e)->info]) diff -urN lua-5.0.2.orig/src/llex.c lua-5.0.2/src/llex.c --- lua-5.0.2.orig/src/llex.c 2003年03月24日 07:39:34.000000000 -0500 +++ lua-5.0.2/src/llex.c 2004年06月21日 12:28:34.000000000 -0400 @@ -171,10 +171,35 @@ /* LUA_NUMBER */ -static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) { +static int hexval(char c) +{ + if ((c>= '0') && (c <= '9')) return c - '0'; + if ((c>= 'a') && (c <= 'f')) return 10 + c - 'a'; + if ((c>= 'A') && (c <= 'F')) return 10 + c - 'A'; + return 0; +} + +static void read_hexadecimal (LexState *LS, char xchar, SemInfo *seminfo) { + size_t l = 0; + checkbuffer(LS, l); + save(LS, '0', l); + checkbuffer(LS, l); + save(LS, xchar, l); + next(LS); + while (isxdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + save(LS, '0円', l); + + if (!luaO_str2x(luaZ_buffer(LS->buff), &seminfo->r)) + luaX_lexerror(LS, "malformed hexadecimal number", TK_NUMBER); +} /* read_hexadecimal */ + +static void read_numeral (LexState *LS, char pushchar, SemInfo *seminfo) { size_t l = 0; checkbuffer(LS, l); - if (comma) save(LS, '.', l); + if (pushchar) save(LS, pushchar, l); while (isdigit(LS->current)) { checkbuffer(LS, l); save_and_next(LS, l); @@ -207,7 +232,6 @@ luaX_lexerror(LS, "malformed number", TK_NUMBER); } - static void read_long_string (LexState *LS, SemInfo *seminfo) { int cont = 0; size_t l = 0; @@ -281,6 +305,22 @@ case 't': save(LS, '\t', l); next(LS); break; case 'v': save(LS, '\v', l); next(LS); break; case '\n': save(LS, '\n', l); inclinenumber(LS); break; + case 'x': case 'X': { + int c = 0; + next(LS); + if (!isxdigit(LS->current)) { + save(LS, '0円', l); + luaX_lexerror(LS, "no hex digits given in hex escape sequence", TK_STRING); + } + c = hexval(LS->current); + next(LS); + if (isxdigit(LS->current)) { + c = 16*c + hexval(LS->current); + next(LS); + } + save(LS, c, l); + break; + } case EOZ: break; /* will raise an error next loop */ default: { if (!isdigit(LS->current)) @@ -298,13 +338,14 @@ } save(LS, c, l); } - } - } + } /* default '\\' case - check for decimal digits, etc. */ + } /* switch on character after '\\' */ break; default: save_and_next(LS, l); } } + save_and_next(LS, l); /* skip delimiter */ save(LS, '0円', l); seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3); @@ -376,13 +417,24 @@ } else if (!isdigit(LS->current)) return '.'; else { - read_numeral(LS, 1, seminfo); + read_numeral(LS, '.', seminfo); return TK_NUMBER; } } case EOZ: { return TK_EOS; } + case '0': { + next(LS); + if ((LS->current == 'x') || (LS->current == 'X')) { + read_hexadecimal(LS, LS->current, seminfo); + return TK_NUMBER; + } + else { + read_numeral(LS, '0', seminfo); + return TK_NUMBER; + } + } default: { if (isspace(LS->current)) { next(LS); diff -urN lua-5.0.2.orig/src/lobject.c lua-5.0.2/src/lobject.c --- lua-5.0.2.orig/src/lobject.c 2003年04月03日 08:35:34.000000000 -0500 +++ lua-5.0.2/src/lobject.c 2004年06月21日 12:28:34.000000000 -0400 @@ -100,6 +100,17 @@ } +int luaO_str2x (const char *s, lua_Number *result) { + char *endptr; + lua_Number res = (lua_Number) strtol(s, &endptr, 16); + if (endptr == s) return 0; /* no conversion */ + while (isspace((unsigned char)(*endptr))) endptr++; + if (*endptr != '0円') return 0; /* invalid trailing characters? */ + *result = res; + return 1; +} + + static void pushstr (lua_State *L, const char *str) { setsvalue2s(L->top, luaS_new(L, str)); diff -urN lua-5.0.2.orig/src/lobject.h lua-5.0.2/src/lobject.h --- lua-5.0.2.orig/src/lobject.h 2003年03月18日 07:50:04.000000000 -0500 +++ lua-5.0.2/src/lobject.h 2004年06月21日 12:28:34.000000000 -0400 @@ -327,6 +327,7 @@ int luaO_rawequalObj (const TObject *t1, const TObject *t2); int luaO_str2d (const char *s, lua_Number *result); +int luaO_str2x (const char *s, lua_Number *result); const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); diff -urN lua-5.0.2.orig/src/lopcodes.c lua-5.0.2/src/lopcodes.c --- lua-5.0.2.orig/src/lopcodes.c 2002年12月04日 12:38:31.000000000 -0500 +++ lua-5.0.2/src/lopcodes.c 2004年06月21日 13:05:30.000000000 -0400 @@ -51,7 +51,11 @@ "SETLIST", "SETLISTO", "CLOSE", - "CLOSURE" + "CLOSURE", + "BITNOT", + "BITAND", + "BITOR", + "BITXOR", }; #endif @@ -98,5 +102,9 @@ ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLISTO */ ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CLOSE */ ,opmode(0, 0, 0, 0, 1, 0, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_BNOT */ + ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_BAND */ + ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_BOR */ + ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_BXOR */ }; diff -urN lua-5.0.2.orig/src/lopcodes.h lua-5.0.2/src/lopcodes.h --- lua-5.0.2.orig/src/lopcodes.h 2002年08月21日 14:56:09.000000000 -0400 +++ lua-5.0.2/src/lopcodes.h 2004年06月21日 18:27:46.000000000 -0400 @@ -182,11 +182,17 @@ OP_SETLISTO,/* A Bx */ OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ -OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + +OP_BNOT, /* A B R(A) := bitwise-complement R(B) */ +OP_BAND, /* A B C R(A) := R(B) bitwise-and R(C) */ +OP_BOR, /* A B C R(A) := R(B) bitwise-or R(C) */ +OP_BXOR /* A B C R(A) := R(B) bitwise-xor R(C) */ + } OpCode; -#define NUM_OPCODES (cast(int, OP_CLOSURE+1)) +#define NUM_OPCODES (cast(int, OP_BXOR+1)) diff -urN lua-5.0.2.orig/src/lparser.c lua-5.0.2/src/lparser.c --- lua-5.0.2.orig/src/lparser.c 2003年11月25日 07:30:13.000000000 -0500 +++ lua-5.0.2/src/lparser.c 2004年06月21日 19:04:08.000000000 -0400 @@ -752,6 +752,7 @@ switch (op) { case TK_NOT: return OPR_NOT; case '-': return OPR_MINUS; + case '#': return OPR_BNOT; default: return OPR_NOUNOPR; } } @@ -773,6 +774,9 @@ case TK_GE: return OPR_GE; case TK_AND: return OPR_AND; case TK_OR: return OPR_OR; + case '&': return OPR_BAND; + case '|': return OPR_BOR; + case '#': return OPR_BXOR; default: return OPR_NOBINOPR; } } @@ -786,7 +790,8 @@ {10, 9}, {5, 4}, /* power and concat (right associative) */ {3, 3}, {3, 3}, /* equality */ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ - {2, 2}, {1, 1} /* logical (and/or) */ + {2, 2}, {1, 1}, /* logical (and/or) */ + {6, 6}, {6, 6}, {6, 6} /* bit-wise (band/bor/bxor) */ }; #define UNARY_PRIORITY 8 /* priority for unary operators */ diff -urN lua-5.0.2.orig/src/lvm.c lua-5.0.2/src/lvm.c --- lua-5.0.2.orig/src/lvm.c 2004年03月03日 19:50:13.000000000 -0500 +++ lua-5.0.2/src/lvm.c 2004年06月21日 19:27:37.000000000 -0400 @@ -774,7 +774,39 @@ luaC_checkGC(L); break; } - } + + case OP_BNOT: { + const TObject *rb = RKB(i); + if (ttisnumber(rb)) { + setnvalue(ra, ~ (long) nvalue(rb)); + } + break; + } + case OP_BAND: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, (long) nvalue(rb) & (long) nvalue(rc)); + } + break; + } + case OP_BOR: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, (long) nvalue(rb) | (long) nvalue(rc)); + } + break; + } + case OP_BXOR: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, (long) nvalue(rb) ^ (long) nvalue(rc)); + } + break; + } + } /* switch */ } }