From 03042b7e2367a4a0f233f3aeb96f302c4a53992d Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Mon, 27 Jul 2009 00:23:49 +0000 Subject: [PATCH] Decoding simple files with functions and assignments is now possible --- ASTNode.cpp | 27 +++- ASTNode.h | 80 ++++++++++-- ASTree.cpp | 339 +++++++++++++++++++++++++++++++-------------------- ASTree.h | 12 +- bytecode.cpp | 10 +- module.cpp | 2 +- numeric.h | 2 +- pycdas.cpp | 10 +- pycdc.cpp | 7 +- sequence.h | 10 +- string.cpp | 10 +- string.h | 1 + 12 files changed, 330 insertions(+), 180 deletions(-) diff --git a/ASTNode.cpp b/ASTNode.cpp index 6bd7d1b..c09f50e 100644 --- a/ASTNode.cpp +++ b/ASTNode.cpp @@ -2,6 +2,31 @@ PycRef Node_NULL = (ASTNode*)0; +/* ASTNodeList */ +void ASTNodeList::removeLast() +{ + list_t::iterator it = m_nodes.end(); + --it; + m_nodes.erase(it); +} + +void ASTNodeList::removeFirst() +{ + list_t::iterator it = m_nodes.begin(); + m_nodes.erase(it); +} + + +/* ASTBinary */ +const char* ASTBinary::op_str() const +{ + static const char* s_op_strings[] = { + "**", "*", "/", "%", "+", "-", "<<", ">>", "&", "^", "|" + }; + return s_op_strings[op()]; +} + + /* ASTCompare */ const char* ASTCompare::op_str() const { @@ -9,5 +34,5 @@ const char* ASTCompare::op_str() const "<", "<=", "==", "!=", ">", ">=", "in", "not in", "is", "is not", "", "" }; - return s_cmp_strings[m_op]; + return s_cmp_strings[op()]; } diff --git a/ASTNode.h b/ASTNode.h index 74107fd..0047b5a 100644 --- a/ASTNode.h +++ b/ASTNode.h @@ -10,7 +10,8 @@ class ASTNode { public: enum Type { NODE_INVALID, NODE_LIST, NODE_OBJECT, NODE_UNARY, NODE_BINARY, - NODE_COMPARE, NODE_STORE, NODE_RETURN, NODE_NAME, NODE_DELETE + NODE_COMPARE, NODE_STORE, NODE_RETURN, NODE_NAME, NODE_DELETE, + NODE_FUNCTION, NODE_CLASS, NODE_CALL, NODE_PASS }; ASTNode(int type = NODE_INVALID) : m_refs(0), m_type(type) { } @@ -38,7 +39,10 @@ public: ASTNodeList(list_t nodes) : ASTNode(NODE_LIST), m_nodes(nodes) { } - list_t nodes() const { return m_nodes; } + const list_t& nodes() const { return m_nodes; } + void removeFirst(); + void removeLast(); + void append(PycRef node) { m_nodes.push_back(node); } private: list_t m_nodes; @@ -71,11 +75,22 @@ private: class ASTBinary : public ASTNode { public: - ASTBinary(PycRef left, PycRef right, int type = NODE_BINARY) - : ASTNode(type), m_left(left), m_right(right) { } + enum BinOp { + BIN_POWER, BIN_MULTIPLY, BIN_DIVIDE, BIN_MODULO, BIN_ADD, + BIN_SUBTRACT, BIN_LSHIFT, BIN_RSHIFT, BIN_AND, BIN_XOR, BIN_OR + }; + + ASTBinary(PycRef left, PycRef right, int op, + int type = NODE_BINARY) + : ASTNode(type), m_op(op), m_left(left), m_right(right) { } PycRef left() const { return m_left; } PycRef right() const { return m_right; } + int op() const { return m_op; } + virtual const char* op_str() const; + +protected: + int m_op; private: PycRef m_left; @@ -91,14 +106,10 @@ public: CMP_EXCEPTION, CMP_BAD }; - ASTCompare(PycRef left, PycRef right, CompareOp op) - : ASTBinary(left, right, NODE_COMPARE), m_op(op) { } + ASTCompare(PycRef left, PycRef right, int op) + : ASTBinary(left, right, op, NODE_COMPARE) { } - CompareOp op() const { return m_op; } const char* op_str() const; - -private: - CompareOp m_op; }; @@ -135,7 +146,7 @@ public: ASTName(PycRef name) : ASTNode(NODE_NAME) { m_name.push_back(name); } - name_t name() const { return m_name; } + const name_t& name() const { return m_name; } void add(PycRef name) { m_name.push_back(name); } private: @@ -154,4 +165,51 @@ private: PycRef m_value; }; + +class ASTFunction : public ASTNode { +public: + typedef std::list > defarg_t; + + ASTFunction(PycRef code, defarg_t defArgs) + : ASTNode(NODE_FUNCTION), m_code(code) { } + + PycRef code() const { return m_code; } + const defarg_t& defargs() const { return m_defargs; } + +private: + PycRef m_code; + defarg_t m_defargs; +}; + + +class ASTClass : public ASTNode { +public: + ASTClass(PycRef code) + : ASTNode(NODE_CLASS), m_code(code) { } + + PycRef code() const { return m_code; } + +private: + PycRef m_code; +}; + + +class ASTCall : public ASTNode { +public: + typedef std::list > pparam_t; + typedef std::list, PycRef > > kwparam_t; + + ASTCall(PycRef func, pparam_t pparams, kwparam_t kwparams) + : ASTNode(NODE_CALL), m_func(func), m_pparams(pparams), m_kwparams(kwparams) { } + + PycRef func() const { return m_func; } + const pparam_t& pparams() const { return m_pparams; } + const kwparam_t& kwparams() const { return m_kwparams; } + +private: + PycRef m_func; + pparam_t m_pparams; + kwparam_t m_kwparams; +}; + #endif diff --git a/ASTree.cpp b/ASTree.cpp index 61ecf5a..0663283 100644 --- a/ASTree.cpp +++ b/ASTree.cpp @@ -32,134 +32,115 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) opcode |= opadd; switch (opcode) { - //case Py2k::STOP_CODE: - //case Py2k::POP_TOP: - //case Py2k::ROT_TWO: - //case Py2k::ROT_THREE: - //case Py2k::DUP_TOP: - //case Py2k::ROT_FOUR: - //case Py2k::NOP: - //case Py2k::UNARY_POSITIVE: - //case Py2k::UNARY_NEGATIVE: - //case Py2k::UNARY_NOT: - //case Py2k::UNARY_CONVERT: - //case Py2k::UNARY_INVERT: - //case Py2k::LIST_APPEND: - //case Py2k::BINARY_POWER: - //case Py2k::BINARY_MULTIPLY: - //case Py2k::BINARY_DIVIDE: - //case Py2k::BINARY_MODULO: - //case Py2k::BINARY_ADD: - //case Py2k::BINARY_SUBTRACT: - //case Py2k::BINARY_SUBSCR: - //case Py2k::BINARY_FLOOR_DIVIDE: - //case Py2k::BINARY_TRUE_DIVIDE: - //case Py2k::INPLACE_FLOOR_DIVIDE: - //case Py2k::INPLACE_TRUE_DIVIDE: - //case Py2k::SLICE_0: - //case Py2k::SLICE_1: - //case Py2k::SLICE_2: - //case Py2k::SLICE_3: - //case Py2k::STORE_SLICE_0: - //case Py2k::STORE_SLICE_1: - //case Py2k::STORE_SLICE_2: - //case Py2k::STORE_SLICE_3: - //case Py2k::DELETE_SLICE_0: - //case Py2k::DELETE_SLICE_1: - //case Py2k::DELETE_SLICE_2: - //case Py2k::DELETE_SLICE_3: - //case Py2k::STORE_MAP: - //case Py2k::INPLACE_ADD: - //case Py2k::INPLACE_SUBTRACT: - //case Py2k::INPLACE_MULTIPLY: - //case Py2k::INPLACE_DIVIDE: - //case Py2k::INPLACE_MODULO: - //case Py2k::STORE_SUBSCR: - //case Py2k::DELETE_SUBSCR: - //case Py2k::BINARY_LSHIFT: - //case Py2k::BINARY_RSHIFT: - //case Py2k::BINARY_AND: - //case Py2k::BINARY_XOR: - //case Py2k::BINARY_OR: - //case Py2k::INPLACE_POWER: - //case Py2k::GET_ITER: - //case Py2k::PRINT_EXPR: - //case Py2k::PRINT_ITEM: - //case Py2k::PRINT_NEWLINE: - //case Py2k::PRINT_ITEM_TO: - //case Py2k::PRINT_NEWLINE_TO: - //case Py2k::INPLACE_LSHIFT: - //case Py2k::INPLACE_RSHIFT: - //case Py2k::INPLACE_AND: - //case Py2k::INPLACE_XOR: - //case Py2k::INPLACE_OR: - //case Py2k::BREAK_LOOP: - //case Py2k::WITH_CLEANUP: - //case Py2k::LOAD_LOCALS: - //case Py2k::RETURN_VALUE: - //case Py2k::IMPORT_STAR: - //case Py2k::EXEC_STMT: - //case Py2k::YIELD_VALUE: - //case Py2k::POP_BLOCK: - //case Py2k::END_FINALLY: - //case Py2k::BUILD_CLASS: - case (PY_1000 | Py1k::STORE_NAME): - case (PY_2000 | Py2k::STORE_NAME): - case (PY_3000 | Py3k::STORE_NAME): + case (PY_1000 | Py1k::BINARY_AND): + case (PY_2000 | Py2k::BINARY_AND): + case (PY_3000 | Py3k::BINARY_AND): { - PycRef value = stack.top(); - PycRef name = new ASTName(code->getName(operand)); + PycRef right = stack.top(); stack.pop(); - lines.push_back(new ASTStore(value, name)); + PycRef left = stack.top(); + stack.pop(); + stack.push(new ASTBinary(left, right, ASTBinary::BIN_AND)); + } + break; + case (PY_1000 | Py1k::BUILD_FUNCTION): + { + PycRef code = stack.top(); + stack.pop(); + stack.push(new ASTFunction(code, ASTFunction::defarg_t())); + } + break; + case (PY_1000 | Py1k::CALL_FUNCTION): + case (PY_2000 | Py2k::CALL_FUNCTION): + case (PY_3000 | Py3k::CALL_FUNCTION): + { + int kwparams = (operand & 0xFF00) >> 8; + int pparams = (operand & 0xFF); + ASTCall::kwparam_t kwparamList; + ASTCall::pparam_t pparamList; + for (int i=0; i val = stack.top(); + stack.pop(); + PycRef key = stack.top(); + stack.pop(); + kwparamList.push_front(std::make_pair(key, val)); + } + for (int i=0; i func = stack.top(); + stack.pop(); + stack.push(new ASTCall(func, pparamList, kwparamList)); + } + break; + case (PY_1000 | Py1k::COMPARE_OP): + case (PY_2000 | Py2k::COMPARE_OP): + case (PY_3000 | Py3k::COMPARE_OP): + { + PycRef right = stack.top(); + stack.pop(); + PycRef left = stack.top(); + stack.pop(); + stack.push(new ASTCompare(left, right, operand)); } break; - //case Py2k::DELETE_NAME: - //case Py2k::UNPACK_SEQUENCE: - //case Py2k::FOR_ITER: - //case Py2k::STORE_ATTR: - //case Py2k::DELETE_ATTR: - //case Py2k::STORE_GLOBAL: - //case Py2k::DELETE_GLOBAL: - //case Py2k::DUP_TOPX: case (PY_1000 | Py1k::LOAD_CONST): case (PY_2000 | Py2k::LOAD_CONST): case (PY_3000 | Py3k::LOAD_CONST): stack.push(new ASTObject(code->getConst(operand))); break; - //case Py2k::LOAD_NAME: - //case Py2k::BUILD_TUPLE: - //case Py2k::BUILD_LIST: - //case Py2k::BUILD_MAP: - //case Py2k::LOAD_ATTR: - //case Py2k::COMPARE_OP: - //case Py2k::IMPORT_NAME: - //case Py2k::IMPORT_FROM: - //case Py2k::JUMP_FORWARD: - //case Py2k::JUMP_IF_FALSE: - //case Py2k::JUMP_IF_TRUE: - //case Py2k::JUMP_ABSOLUTE: - //case Py2k::FOR_LOOP: - //case Py2k::LOAD_GLOBAL: - //case Py2k::CONTINUE_LOOP: - //case Py2k::SETUP_LOOP: - //case Py2k::SETUP_EXCEPT: - //case Py2k::SETUP_FINALLY: - //case Py2k::LOAD_FAST: - //case Py2k::STORE_FAST: - //case Py2k::DELETE_FAST: - //case Py2k::SET_LINENO: - //case Py2k::RAISE_VARARGS: - //case Py2k::CALL_FUNCTION: - //case Py2k::MAKE_FUNCTION: - //case Py2k::BUILD_SLICE: - //case Py2k::MAKE_CLOSURE: - //case Py2k::LOAD_CLOSURE: - //case Py2k::LOAD_DEREF: - //case Py2k::STORE_DEREF: - //case Py2k::CALL_FUNCTION_VAR: - //case Py2k::CALL_FUNCTION_KW: - //case Py2k::CALL_FUNCTION_VAR_KW: - //case Py2k::EXTENDED_ARG: + case (PY_1000 | Py1k::LOAD_FAST): + if (mod->minorVer() < 3) + stack.push(new ASTName(code->getName(operand))); + else + stack.push(new ASTName(code->getVarName(operand))); + break; + case (PY_2000 | Py2k::LOAD_FAST): + case (PY_3000 | Py3k::LOAD_FAST): + stack.push(new ASTName(code->getVarName(operand))); + break; + case (PY_1000 | Py1k::LOAD_GLOBAL): + case (PY_2000 | Py2k::LOAD_GLOBAL): + case (PY_3000 | Py3k::LOAD_GLOBAL): + case (PY_1000 | Py1k::LOAD_NAME): + case (PY_2000 | Py2k::LOAD_NAME): + case (PY_3000 | Py3k::LOAD_NAME): + stack.push(new ASTName(code->getName(operand))); + break; + case (PY_1000 | Py1k::MAKE_FUNCTION): + case (PY_2000 | Py2k::MAKE_FUNCTION): + case (PY_3000 | Py3k::MAKE_FUNCTION): + { + PycRef code = stack.top(); + stack.pop(); + ASTFunction::defarg_t defArgs; + for (int i=0; i value = stack.top(); + stack.pop(); + lines.push_back(new ASTReturn(value)); + } + break; + case (PY_1000 | Py1k::STORE_NAME): + case (PY_2000 | Py2k::STORE_NAME): + case (PY_3000 | Py3k::STORE_NAME): + { + PycRef value = stack.top(); + stack.pop(); + PycRef name = new ASTName(code->getName(operand)); + lines.push_back(new ASTStore(value, name)); + } + break; default: if (mod->majorVer() == 1) fprintf(stderr, "Unsupported opcode: %s\n", Py1k::OpcodeNames[opcode & 0xFF]); @@ -180,45 +161,137 @@ static void start_indent(int indent) printf(" "); } -static void print_src(PycRef node, PycModule* mod, int indent = 0) +void print_src(PycRef node, PycModule* mod, int indent) { switch (node->type()) { + case ASTNode::NODE_BINARY: + case ASTNode::NODE_COMPARE: + { + PycRef bin = node.cast(); + printf("("); + print_src(bin->left(), mod); + printf(" %s ", bin->op_str()); + print_src(bin->right(), mod); + printf(")"); + } + break; + case ASTNode::NODE_CALL: + { + PycRef call = node.cast(); + start_indent(indent); + print_src(call->func(), mod); + printf("("); + bool first = true; + for (ASTCall::pparam_t::const_iterator p = call->pparams().begin(); p != call->pparams().end(); ++p) { + if (!first) printf(", "); + print_src(*p, mod); + first = false; + } + for (ASTCall::kwparam_t::const_iterator p = call->kwparams().begin(); p != call->kwparams().end(); ++p) { + if (!first) printf(", "); + print_src(p->first, mod); + printf("="); + print_src(p->second, mod); + first = false; + } + printf(")"); + } + break; case ASTNode::NODE_LIST: { ASTNodeList::list_t lines = node.cast()->nodes(); - for (ASTNodeList::list_t::iterator ln = lines.begin(); ln != lines.end(); ++ln) + for (ASTNodeList::list_t::const_iterator ln = lines.begin(); ln != lines.end(); ++ln) { print_src(*ln, mod, indent); + printf("\n"); + } } break; case ASTNode::NODE_STORE: { PycRef src = node.cast()->src(); PycRef dest = node.cast()->dest(); - start_indent(indent); - print_src(dest, mod); - printf(" = "); - print_src(src, mod); - printf("\n"); + if (src->type() == ASTNode::NODE_FUNCTION) { + printf("\n"); + start_indent(indent); + printf("def "); + print_src(dest, mod); + printf("("); + //TODO: Keyword and Default args + PycRef code = src.cast()->code(); + PycRef code_src = code.cast()->object().cast(); + for (int i=0; iargCount(); i++) { + if (i > 0) printf(", "); + printf("%s", code_src->getVarName(i)->value()); + } + printf("):\n"); + print_src(code, mod, indent + 1); + } else { + start_indent(indent); + print_src(dest, mod); + printf(" = "); + print_src(src, mod); + } } break; - case ASTNode::NODE_OBJECT: - print_const(node.cast()->object(), mod); - break; case ASTNode::NODE_NAME: { ASTName::name_t name = node.cast()->name(); - ASTName::name_t::iterator n = name.begin(); + ASTName::name_t::const_iterator n = name.begin(); printf("%s", (*n)->value()); while (++n != name.end()) printf(".%s", (*n)->value()); } break; + case ASTNode::NODE_OBJECT: + { + PycRef obj = node.cast()->object(); + if (obj->type() == PycObject::TYPE_CODE) + decompyle(obj.cast(), mod, indent); + else + print_const(obj, mod); + } + break; + case ASTNode::NODE_PASS: + start_indent(indent); + printf("pass"); + break; + case ASTNode::NODE_RETURN: + start_indent(indent); + printf("return "); + print_src(node.cast()->value(), mod); + break; default: - printf("Unsupported Node type: %d\n", node->type()); + fprintf(stderr, "Unsupported Node type: %d\n", node->type()); } } -void ASTree::printSource(PycModule* mod) const +void decompyle(PycRef code, PycModule* mod, int indent) { - print_src(m_root, mod, 0); + PycRef source = BuildFromCode(code, mod); + + // The Python compiler adds some stuff that we don't really care + // about, and would add extra code for re-compilation anyway. + // We strip these lines out here, and then add a "pass" statement + // if the cleaned up code is empty + PycRef clean = source.cast(); + if (clean->nodes().front()->type() == ASTNode::NODE_STORE) { + PycRef store = clean->nodes().front().cast(); + if (store->src()->type() == ASTNode::NODE_NAME && + store->dest()->type() == ASTNode::NODE_NAME) { + PycRef src = store->src().cast(); + PycRef dest = store->dest().cast(); + if (src->name().size() == 1 && dest->name().size() == 1 && + src->name().front()->isEqual("__name__") && + dest->name().front()->isEqual("__module__")) { + // __module__ = __name__ + clean->removeFirst(); + } + } + } + clean->removeLast(); // Always an extraneous return statement + + if (clean->nodes().size() == 0) + clean->append(new ASTNode(ASTNode::NODE_PASS)); + + print_src(source, mod, indent); } diff --git a/ASTree.h b/ASTree.h index 2b96de7..2361a0d 100644 --- a/ASTree.h +++ b/ASTree.h @@ -4,16 +4,8 @@ #include "ASTNode.h" PycRef BuildFromCode(PycRef code, PycModule* mod); +void print_src(PycRef node, PycModule* mod, int indent = 0); -class ASTree { -public: - void load(PycModule* mod) - { m_root = BuildFromCode(mod->code(), mod); } - - void printSource(PycModule* mod) const; - -private: - PycRef m_root; -}; +void decompyle(PycRef code, PycModule* mod, int indent = 0); #endif diff --git a/bytecode.cpp b/bytecode.cpp index 7595caa..49df5d2 100644 --- a/bytecode.cpp +++ b/bytecode.cpp @@ -250,7 +250,7 @@ void print_const(PycRef obj, PycModule* mod) { printf("("); PycTuple::value_t values = obj.cast()->values(); - PycTuple::value_t::iterator it = values.begin(); + PycTuple::value_t::const_iterator it = values.begin(); if (it != values.end()) { print_const(*it, mod); while (++it != values.end()) { @@ -265,7 +265,7 @@ void print_const(PycRef obj, PycModule* mod) { printf("["); PycList::value_t values = obj.cast()->values(); - PycList::value_t::iterator it = values.begin(); + PycList::value_t::const_iterator it = values.begin(); if (it != values.end()) { print_const(*it, mod); while (++it != values.end()) { @@ -281,8 +281,8 @@ void print_const(PycRef obj, PycModule* mod) printf("{"); PycDict::key_t keys = obj.cast()->keys(); PycDict::value_t values = obj.cast()->values(); - PycDict::key_t::iterator ki = keys.begin(); - PycDict::value_t::iterator vi = values.begin(); + PycDict::key_t::const_iterator ki = keys.begin(); + PycDict::value_t::const_iterator vi = values.begin(); if (ki != keys.end()) { print_const(*ki, mod); printf(": "); @@ -302,7 +302,7 @@ void print_const(PycRef obj, PycModule* mod) { printf("{"); PycSet::value_t values = obj.cast()->values(); - PycSet::value_t::iterator it = values.begin(); + PycSet::value_t::const_iterator it = values.begin(); if (it != values.end()) { print_const(*it, mod); while (++it != values.end()) { diff --git a/module.cpp b/module.cpp index a6536c2..9f09f45 100644 --- a/module.cpp +++ b/module.cpp @@ -128,7 +128,7 @@ void PycModule::loadFromFile(const char* filename) PycRef PycModule::getIntern(int ref) { - std::list >::iterator it = m_interns.begin(); + std::list >::const_iterator it = m_interns.begin(); for (int i=0; i value() const { return m_value; } + const std::list& value() const { return m_value; } private: int m_size; diff --git a/pycdas.cpp b/pycdas.cpp index 84728c5..2c631c3 100644 --- a/pycdas.cpp +++ b/pycdas.cpp @@ -90,7 +90,7 @@ void output_object(PycRef obj, PycModule* mod, int indent) { iprintf(indent, "(\n"); PycTuple::value_t values = obj.cast()->values(); - for (PycTuple::value_t::iterator i = values.begin(); i != values.end(); i++) + for (PycTuple::value_t::const_iterator i = values.begin(); i != values.end(); i++) output_object(*i, mod, indent + 1); iprintf(indent, ")\n"); } @@ -99,7 +99,7 @@ void output_object(PycRef obj, PycModule* mod, int indent) { iprintf(indent, "[\n"); PycList::value_t values = obj.cast()->values(); - for (PycList::value_t::iterator i = values.begin(); i != values.end(); i++) + for (PycList::value_t::const_iterator i = values.begin(); i != values.end(); i++) output_object(*i, mod, indent + 1); iprintf(indent, "]\n"); } @@ -109,8 +109,8 @@ void output_object(PycRef obj, PycModule* mod, int indent) iprintf(indent, "{\n"); PycDict::key_t keys = obj.cast()->keys(); PycDict::value_t values = obj.cast()->values(); - PycDict::key_t::iterator ki = keys.begin(); - PycDict::value_t::iterator vi = values.begin(); + PycDict::key_t::const_iterator ki = keys.begin(); + PycDict::value_t::const_iterator vi = values.begin(); while (ki != keys.end()) { output_object(*ki, mod, indent + 1); output_object(*vi, mod, indent + 2); @@ -123,7 +123,7 @@ void output_object(PycRef obj, PycModule* mod, int indent) { iprintf(indent, "{\n"); PycSet::value_t values = obj.cast()->values(); - for (PycSet::value_t::iterator i = values.begin(); i != values.end(); i++) + for (PycSet::value_t::const_iterator i = values.begin(); i != values.end(); i++) output_object(*i, mod, indent + 1); iprintf(indent, "}\n"); } diff --git a/pycdc.cpp b/pycdc.cpp index 7de71a5..f3230e6 100644 --- a/pycdc.cpp +++ b/pycdc.cpp @@ -9,13 +9,10 @@ int main(int argc, char* argv[]) PycModule mod; mod.loadFromFile(argv[1]); - printf("# Source Generated with Decompyle++ pycdc\n"); + printf("# Source Generated with Decompyle++\n"); printf("# File: %s (Python %d.%d%s)\n", argv[1], mod.majorVer(), mod.minorVer(), (mod.majorVer() < 3 && mod.isUnicode()) ? " Unicode" : ""); - - ASTree source; - source.load(&mod); - source.printSource(&mod); + decompyle(mod.code(), &mod); return 0; } diff --git a/sequence.h b/sequence.h index 8ce3654..348d454 100644 --- a/sequence.h +++ b/sequence.h @@ -28,7 +28,7 @@ public: void load(class PycData* stream, class PycModule* mod); - value_t values() const { return m_values; } + const value_t& values() const { return m_values; } PycRef get(int idx) const { return m_values[idx]; } private: @@ -45,7 +45,7 @@ public: void load(class PycData* stream, class PycModule* mod); - value_t values() const { return m_values; } + const value_t& values() const { return m_values; } PycRef get(int idx) const { value_t::const_iterator it = m_values.begin(); @@ -69,8 +69,8 @@ public: void load(class PycData* stream, class PycModule* mod); PycRef get(PycRef key) const; - key_t keys() const { return m_keys; } - value_t values() const { return m_values; } + const key_t& keys() const { return m_keys; } + const value_t& values() const { return m_values; } PycRef get(int idx) const { @@ -94,7 +94,7 @@ public: void load(class PycData* stream, class PycModule* mod); - value_t values() const { return m_values; } + const value_t& values() const { return m_values; } PycRef get(int idx) const { value_t::const_iterator it = m_values.begin(); diff --git a/string.cpp b/string.cpp index 6030a3a..3c6e536 100644 --- a/string.cpp +++ b/string.cpp @@ -39,11 +39,15 @@ bool PycString::isEqual(PycRef obj) const return false; PycRef strObj = obj.cast(); - if (m_value == strObj->m_value) - return true; - return (strcmp(m_value, strObj->m_value) == 0); + return isEqual(strObj->m_value); } +bool PycString::isEqual(const char* str) const +{ + if (m_value == str) + return true; + return (strcmp(m_value, str) == 0); +} void OutputString(PycRef str, QuoteStyle style, FILE* F) { diff --git a/string.h b/string.h index d572751..8c1cdd3 100644 --- a/string.h +++ b/string.h @@ -16,6 +16,7 @@ public: ~PycString() { if (m_value) delete[] m_value; } bool isEqual(PycRef obj) const; + bool isEqual(const char* str) const; void load(class PycData* stream, class PycModule* mod);