Use C++ streams over C style IO
This commit is contained in:

committed by
Perceval Wajsbürt

parent
409f175827
commit
c4c35fc531
526
ASTree.cpp
526
ASTree.cpp
File diff suppressed because it is too large
Load Diff
4
ASTree.h
4
ASTree.h
@@ -4,8 +4,8 @@
|
||||
#include "ASTNode.h"
|
||||
|
||||
PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod);
|
||||
void print_src(PycRef<ASTNode> node, PycModule* mod);
|
||||
void print_src(PycRef<ASTNode> node, PycModule* mod, std::ostream& pyc_output);
|
||||
|
||||
void decompyle(PycRef<PycCode> code, PycModule* mod);
|
||||
void decompyle(PycRef<PycCode> code, PycModule* mod, std::ostream& pyc_output);
|
||||
|
||||
#endif
|
||||
|
148
bytecode.cpp
148
bytecode.cpp
@@ -160,10 +160,10 @@ bool Pyc::IsCompareArg(int opcode)
|
||||
return (opcode == Pyc::COMPARE_OP_A);
|
||||
}
|
||||
|
||||
void print_const(PycRef<PycObject> obj, PycModule* mod, const char* parent_f_string_quote)
|
||||
void print_const(PycRef<PycObject> obj, PycModule* mod, const char* parent_f_string_quote, std::ostream& pyc_output)
|
||||
{
|
||||
if (obj == NULL) {
|
||||
fputs("<NULL>", pyc_output);
|
||||
pyc_output << "<NULL>";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -190,112 +190,112 @@ void print_const(PycRef<PycObject> obj, PycModule* mod, const char* parent_f_str
|
||||
case PycObject::TYPE_TUPLE:
|
||||
case PycObject::TYPE_SMALL_TUPLE:
|
||||
{
|
||||
fputs("(", pyc_output);
|
||||
pyc_output << "(";
|
||||
PycTuple::value_t values = obj.cast<PycTuple>()->values();
|
||||
auto it = values.cbegin();
|
||||
if (it != values.cend()) {
|
||||
print_const(*it, mod);
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
while (++it != values.cend()) {
|
||||
fputs(", ", pyc_output);
|
||||
print_const(*it, mod);
|
||||
pyc_output << ", ";
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
}
|
||||
}
|
||||
if (values.size() == 1)
|
||||
fputs(",)", pyc_output);
|
||||
pyc_output << ",)";
|
||||
else
|
||||
fputs(")", pyc_output);
|
||||
pyc_output << ")";
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_LIST:
|
||||
{
|
||||
fputs("[", pyc_output);
|
||||
pyc_output << "[";
|
||||
PycList::value_t values = obj.cast<PycList>()->values();
|
||||
auto it = values.cbegin();
|
||||
if (it != values.cend()) {
|
||||
print_const(*it, mod);
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
while (++it != values.cend()) {
|
||||
fputs(", ", pyc_output);
|
||||
print_const(*it, mod);
|
||||
pyc_output << ", ";
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
}
|
||||
}
|
||||
fputs("]", pyc_output);
|
||||
pyc_output << "]";
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_DICT:
|
||||
{
|
||||
fputs("{", pyc_output);
|
||||
pyc_output << "{";
|
||||
PycDict::key_t keys = obj.cast<PycDict>()->keys();
|
||||
PycDict::value_t values = obj.cast<PycDict>()->values();
|
||||
auto ki = keys.cbegin();
|
||||
auto vi = values.cbegin();
|
||||
if (ki != keys.cend()) {
|
||||
print_const(*ki, mod);
|
||||
fputs(": ", pyc_output);
|
||||
print_const(*vi, mod);
|
||||
print_const(*ki, mod, nullptr, pyc_output);
|
||||
pyc_output << ": ";
|
||||
print_const(*vi, mod, nullptr, pyc_output);
|
||||
while (++ki != keys.cend()) {
|
||||
++vi;
|
||||
fputs(", ", pyc_output);
|
||||
print_const(*ki, mod);
|
||||
fputs(": ", pyc_output);
|
||||
print_const(*vi, mod);
|
||||
pyc_output << ", ";
|
||||
print_const(*ki, mod, nullptr, pyc_output);
|
||||
pyc_output << ": ";
|
||||
print_const(*vi, mod, nullptr, pyc_output);
|
||||
}
|
||||
}
|
||||
fputs("}", pyc_output);
|
||||
pyc_output << "}";
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_SET:
|
||||
{
|
||||
fputs("{", pyc_output);
|
||||
pyc_output << "{";
|
||||
PycSet::value_t values = obj.cast<PycSet>()->values();
|
||||
auto it = values.cbegin();
|
||||
if (it != values.cend()) {
|
||||
print_const(*it, mod);
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
while (++it != values.cend()) {
|
||||
fputs(", ", pyc_output);
|
||||
print_const(*it, mod);
|
||||
pyc_output << ", ";
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
}
|
||||
}
|
||||
fputs("}", pyc_output);
|
||||
pyc_output << "}";
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_FROZENSET:
|
||||
{
|
||||
fputs("frozenset({", pyc_output);
|
||||
pyc_output << "frozenset({";
|
||||
PycSet::value_t values = obj.cast<PycSet>()->values();
|
||||
auto it = values.cbegin();
|
||||
if (it != values.cend()) {
|
||||
print_const(*it, mod);
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
while (++it != values.cend()) {
|
||||
fputs(", ", pyc_output);
|
||||
print_const(*it, mod);
|
||||
pyc_output << ", ";
|
||||
print_const(*it, mod, nullptr, pyc_output);
|
||||
}
|
||||
}
|
||||
fputs("})", pyc_output);
|
||||
pyc_output << "})";
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_NONE:
|
||||
fputs("None", pyc_output);
|
||||
pyc_output << "None";
|
||||
break;
|
||||
case PycObject::TYPE_TRUE:
|
||||
fputs("True", pyc_output);
|
||||
pyc_output << "True";
|
||||
break;
|
||||
case PycObject::TYPE_FALSE:
|
||||
fputs("False", pyc_output);
|
||||
pyc_output << "False";
|
||||
break;
|
||||
case PycObject::TYPE_ELLIPSIS:
|
||||
fputs("...", pyc_output);
|
||||
pyc_output << "...";
|
||||
break;
|
||||
case PycObject::TYPE_INT:
|
||||
fprintf(pyc_output, "%d", obj.cast<PycInt>()->value());
|
||||
formatted_print(pyc_output, "%d", obj.cast<PycInt>()->value());
|
||||
break;
|
||||
case PycObject::TYPE_LONG:
|
||||
fprintf(pyc_output, "%s", obj.cast<PycLong>()->repr().c_str());
|
||||
formatted_print(pyc_output, "%s", obj.cast<PycLong>()->repr().c_str());
|
||||
break;
|
||||
case PycObject::TYPE_FLOAT:
|
||||
fprintf(pyc_output, "%s", obj.cast<PycFloat>()->value());
|
||||
formatted_print(pyc_output, "%s", obj.cast<PycFloat>()->value());
|
||||
break;
|
||||
case PycObject::TYPE_COMPLEX:
|
||||
fprintf(pyc_output, "(%s+%sj)", obj.cast<PycComplex>()->value(),
|
||||
formatted_print(pyc_output, "(%s+%sj)", obj.cast<PycComplex>()->value(),
|
||||
obj.cast<PycComplex>()->imag());
|
||||
break;
|
||||
case PycObject::TYPE_BINARY_FLOAT:
|
||||
@@ -305,31 +305,31 @@ void print_const(PycRef<PycObject> obj, PycModule* mod, const char* parent_f_str
|
||||
bool is_negative = std::signbit(value);
|
||||
if (std::isnan(value)) {
|
||||
if (is_negative) {
|
||||
fprintf(pyc_output, "float('-nan')");
|
||||
pyc_output << "float('-nan')";
|
||||
} else {
|
||||
fprintf(pyc_output, "float('nan')");
|
||||
pyc_output << "float('nan')";
|
||||
}
|
||||
} else if (std::isinf(value)) {
|
||||
if (is_negative) {
|
||||
fprintf(pyc_output, "float('-inf')");
|
||||
pyc_output << "float('-inf')";
|
||||
} else {
|
||||
fprintf(pyc_output, "float('inf')");
|
||||
pyc_output << "float('inf')";
|
||||
}
|
||||
} else {
|
||||
fprintf(pyc_output, "%g", value);
|
||||
formatted_print(pyc_output, "%g", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_BINARY_COMPLEX:
|
||||
fprintf(pyc_output, "(%g+%gj)", obj.cast<PycCComplex>()->value(),
|
||||
formatted_print(pyc_output, "(%g+%gj)", obj.cast<PycCComplex>()->value(),
|
||||
obj.cast<PycCComplex>()->imag());
|
||||
break;
|
||||
case PycObject::TYPE_CODE:
|
||||
case PycObject::TYPE_CODE2:
|
||||
fprintf(pyc_output, "<CODE> %s", obj.cast<PycCode>()->name()->value());
|
||||
formatted_print(pyc_output, "<CODE> %s", obj.cast<PycCode>()->name()->value());
|
||||
break;
|
||||
default:
|
||||
fprintf(pyc_output, "<TYPE: %d>\n", obj->type());
|
||||
formatted_print(pyc_output, "<TYPE: %d>\n", obj->type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ void bc_next(PycBuffer& source, PycModule* mod, int& opcode, int& operand, int&
|
||||
}
|
||||
}
|
||||
|
||||
void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent, unsigned flags)
|
||||
void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent, unsigned flags, std::ostream &pyc_output)
|
||||
{
|
||||
static const char *cmp_strings[] = {
|
||||
"<", "<=", "==", "!=", ">", ">=", "in", "not in", "is", "is not",
|
||||
@@ -388,78 +388,78 @@ void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent, unsigned flags)
|
||||
continue;
|
||||
|
||||
for (int i=0; i<indent; i++)
|
||||
fputs(" ", pyc_output);
|
||||
fprintf(pyc_output, "%-7d %-30s", start_pos, Pyc::OpcodeName(opcode));
|
||||
pyc_output << " ";
|
||||
formatted_print(pyc_output, "%-7d %-30s", start_pos, Pyc::OpcodeName(opcode));
|
||||
|
||||
if (opcode >= Pyc::PYC_HAVE_ARG) {
|
||||
if (Pyc::IsConstArg(opcode)) {
|
||||
try {
|
||||
auto constParam = code->getConst(operand);
|
||||
fprintf(pyc_output, "%d: ", operand);
|
||||
print_const(constParam, mod);
|
||||
formatted_print(pyc_output, "%d: ", operand);
|
||||
print_const(constParam, mod, nullptr, pyc_output);
|
||||
} catch (const std::out_of_range &) {
|
||||
fprintf(pyc_output, "%d <INVALID>", operand);
|
||||
formatted_print(pyc_output, "%d <INVALID>", operand);
|
||||
}
|
||||
} else if (opcode == Pyc::LOAD_GLOBAL_A) {
|
||||
// Special case for Python 3.11+
|
||||
try {
|
||||
if (operand & 1)
|
||||
fprintf(pyc_output, "%d: NULL + %s", operand, code->getName(operand >> 1)->value());
|
||||
formatted_print(pyc_output, "%d: NULL + %s", operand, code->getName(operand >> 1)->value());
|
||||
else
|
||||
fprintf(pyc_output, "%d: %s", operand, code->getName(operand >> 1)->value());
|
||||
formatted_print(pyc_output, "%d: %s", operand, code->getName(operand >> 1)->value());
|
||||
} catch (const std::out_of_range &) {
|
||||
fprintf(pyc_output, "%d <INVALID>", operand);
|
||||
formatted_print(pyc_output, "%d <INVALID>", operand);
|
||||
}
|
||||
} else if (Pyc::IsNameArg(opcode)) {
|
||||
try {
|
||||
fprintf(pyc_output, "%d: %s", operand, code->getName(operand)->value());
|
||||
formatted_print(pyc_output, "%d: %s", operand, code->getName(operand)->value());
|
||||
} catch (const std::out_of_range &) {
|
||||
fprintf(pyc_output, "%d <INVALID>", operand);
|
||||
formatted_print(pyc_output, "%d <INVALID>", operand);
|
||||
}
|
||||
} else if (Pyc::IsVarNameArg(opcode)) {
|
||||
try {
|
||||
fprintf(pyc_output, "%d: %s", operand, code->getLocal(operand)->value());
|
||||
formatted_print(pyc_output, "%d: %s", operand, code->getLocal(operand)->value());
|
||||
} catch (const std::out_of_range &) {
|
||||
fprintf(pyc_output, "%d <INVALID>", operand);
|
||||
formatted_print(pyc_output, "%d <INVALID>", operand);
|
||||
}
|
||||
} else if (Pyc::IsCellArg(opcode)) {
|
||||
try {
|
||||
fprintf(pyc_output, "%d: %s", operand, code->getCellVar(mod, operand)->value());
|
||||
formatted_print(pyc_output, "%d: %s", operand, code->getCellVar(mod, operand)->value());
|
||||
} catch (const std::out_of_range &) {
|
||||
fprintf(pyc_output, "%d <INVALID>", operand);
|
||||
formatted_print(pyc_output, "%d <INVALID>", operand);
|
||||
}
|
||||
} else if (Pyc::IsJumpOffsetArg(opcode)) {
|
||||
int offs = operand;
|
||||
if (mod->verCompare(3, 10) >= 0)
|
||||
offs *= sizeof(uint16_t); // BPO-27129
|
||||
fprintf(pyc_output, "%d (to %d)", operand, pos+offs);
|
||||
formatted_print(pyc_output, "%d (to %d)", operand, pos+offs);
|
||||
} else if (Pyc::IsJumpArg(opcode)) {
|
||||
if (mod->verCompare(3, 10) >= 0) // BPO-27129
|
||||
fprintf(pyc_output, "%d (to %d)", operand, int(operand * sizeof(uint16_t)));
|
||||
formatted_print(pyc_output, "%d (to %d)", operand, int(operand * sizeof(uint16_t)));
|
||||
else
|
||||
fprintf(pyc_output, "%d", operand);
|
||||
formatted_print(pyc_output, "%d", operand);
|
||||
} else if (Pyc::IsCompareArg(opcode)) {
|
||||
if (static_cast<size_t>(operand) < cmp_strings_len)
|
||||
fprintf(pyc_output, "%d (%s)", operand, cmp_strings[operand]);
|
||||
formatted_print(pyc_output, "%d (%s)", operand, cmp_strings[operand]);
|
||||
else
|
||||
fprintf(pyc_output, "%d (UNKNOWN)", operand);
|
||||
formatted_print(pyc_output, "%d (UNKNOWN)", operand);
|
||||
} else if (opcode == Pyc::BINARY_OP_A) {
|
||||
if (static_cast<size_t>(operand) < binop_strings_len)
|
||||
fprintf(pyc_output, "%d (%s)", operand, binop_strings[operand]);
|
||||
formatted_print(pyc_output, "%d (%s)", operand, binop_strings[operand]);
|
||||
else
|
||||
fprintf(pyc_output, "%d (UNKNOWN)", operand);
|
||||
formatted_print(pyc_output, "%d (UNKNOWN)", operand);
|
||||
} else if (opcode == Pyc::IS_OP_A) {
|
||||
fprintf(pyc_output, "%d (%s)", operand, (operand == 0) ? "is"
|
||||
formatted_print(pyc_output, "%d (%s)", operand, (operand == 0) ? "is"
|
||||
: (operand == 1) ? "is not"
|
||||
: "UNKNOWN");
|
||||
} else if (opcode == Pyc::CONTAINS_OP_A) {
|
||||
fprintf(pyc_output, "%d (%s)", operand, (operand == 0) ? "in"
|
||||
formatted_print(pyc_output, "%d (%s)", operand, (operand == 0) ? "in"
|
||||
: (operand == 1) ? "not in"
|
||||
: "UNKNOWN");
|
||||
} else {
|
||||
fprintf(pyc_output, "%d", operand);
|
||||
formatted_print(pyc_output, "%d", operand);
|
||||
}
|
||||
}
|
||||
fputs("\n", pyc_output);
|
||||
pyc_output << "\n";
|
||||
}
|
||||
}
|
||||
|
@@ -35,6 +35,6 @@ bool IsCompareArg(int opcode);
|
||||
|
||||
}
|
||||
|
||||
void print_const(PycRef<PycObject> obj, PycModule* mod, const char* parent_f_string_quote = nullptr);
|
||||
void print_const(PycRef<PycObject> obj, PycModule* mod, const char* parent_f_string_quote, std::ostream& pyc_output);
|
||||
void bc_next(PycBuffer& source, PycModule* mod, int& opcode, int& operand, int& pos);
|
||||
void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent, unsigned flags);
|
||||
void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent, unsigned flags, std::ostream& pyc_output);
|
||||
|
22
data.cpp
22
data.cpp
@@ -1,7 +1,7 @@
|
||||
#include "data.h"
|
||||
#include <cstring>
|
||||
|
||||
FILE* pyc_output = stdout;
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
/* PycData */
|
||||
int PycData::get16()
|
||||
@@ -82,3 +82,21 @@ int PycBuffer::getBuffer(int bytes, void* buffer)
|
||||
memcpy(buffer, (m_buffer + m_pos), bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wvarargs"
|
||||
int formatted_print(std::ostream& stream, const std::string& format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
size_t len = std::vsnprintf(NULL, 0, format.c_str(), args);
|
||||
va_end(args);
|
||||
std::vector<char> vec(len + 1);
|
||||
va_start(args, format);
|
||||
std::vsnprintf(&vec[0], len + 1, format.c_str(), args);
|
||||
va_end(args);
|
||||
stream << &vec[0];
|
||||
return 0;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
3
data.h
3
data.h
@@ -2,6 +2,7 @@
|
||||
#define _PYC_FILE_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <ostream>
|
||||
|
||||
#ifdef WIN32
|
||||
typedef __int64 Pyc_INT64;
|
||||
@@ -56,6 +57,6 @@ private:
|
||||
int m_size, m_pos;
|
||||
};
|
||||
|
||||
extern FILE* pyc_output;
|
||||
int formatted_print(std::ostream& stream, const std::string& format, ...);
|
||||
|
||||
#endif
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include "pyc_module.h"
|
||||
#include "data.h"
|
||||
#include <stdexcept>
|
||||
#include <ostream>
|
||||
|
||||
static bool check_ascii(const std::string& data)
|
||||
{
|
||||
@@ -56,15 +57,15 @@ bool PycString::isEqual(PycRef<PycObject> obj) const
|
||||
return isEqual(strObj->m_value);
|
||||
}
|
||||
|
||||
void OutputString(PycRef<PycString> str, char prefix, bool triple, FILE* F, const char* parent_f_string_quote)
|
||||
void OutputString(PycRef<PycString> str, char prefix, bool triple, std::ostream &pyc_output, const char* parent_f_string_quote)
|
||||
{
|
||||
if (prefix != 0)
|
||||
fputc(prefix, F);
|
||||
pyc_output << prefix;
|
||||
|
||||
const char* ch = str->value();
|
||||
int len = str->length();
|
||||
if (ch == 0) {
|
||||
fputs("''", F);
|
||||
pyc_output << "''";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,51 +90,51 @@ void OutputString(PycRef<PycString> str, char prefix, bool triple, FILE* F, cons
|
||||
// Output the string
|
||||
if (!parent_f_string_quote) {
|
||||
if (triple)
|
||||
fputs(useQuotes ? "\"\"\"" : "'''", F);
|
||||
pyc_output << (useQuotes ? "\"\"\"" : "'''");
|
||||
else
|
||||
fputc(useQuotes ? '"' : '\'', F);
|
||||
pyc_output << (useQuotes ? '"' : '\'');
|
||||
}
|
||||
while (len--) {
|
||||
if ((unsigned char)(*ch) < 0x20 || *ch == 0x7F) {
|
||||
if (*ch == '\r') {
|
||||
fputs("\\r", F);
|
||||
pyc_output << "\\r";
|
||||
} else if (*ch == '\n') {
|
||||
if (triple)
|
||||
fputc('\n', F);
|
||||
pyc_output << '\n';
|
||||
else
|
||||
fputs("\\n", F);
|
||||
pyc_output << "\\n";
|
||||
} else if (*ch == '\t') {
|
||||
fputs("\\t", F);
|
||||
pyc_output << "\\t";
|
||||
} else {
|
||||
fprintf(F, "\\x%02x", (*ch & 0xFF));
|
||||
formatted_print(pyc_output, "\\x%02x", (*ch & 0xFF));
|
||||
}
|
||||
} else if ((unsigned char)(*ch) >= 0x80) {
|
||||
if (str->type() == PycObject::TYPE_UNICODE) {
|
||||
// Unicode stored as UTF-8... Let the stream interpret it
|
||||
fputc(*ch, F);
|
||||
pyc_output << *ch;
|
||||
} else {
|
||||
fprintf(F, "\\x%x", (*ch & 0xFF));
|
||||
formatted_print(pyc_output, "\\x%x", (*ch & 0xFF));
|
||||
}
|
||||
} else {
|
||||
if (!useQuotes && *ch == '\'')
|
||||
fputs("\\'", F);
|
||||
pyc_output << "\\'";
|
||||
else if (useQuotes && *ch == '"')
|
||||
fputs("\\\"", F);
|
||||
pyc_output << "\\\"";
|
||||
else if (*ch == '\\')
|
||||
fputs("\\\\", F);
|
||||
pyc_output << "\\\\";
|
||||
else if (parent_f_string_quote && *ch == '{')
|
||||
fputs("{{", F);
|
||||
pyc_output << "{{";
|
||||
else if (parent_f_string_quote && *ch == '}')
|
||||
fputs("}}", F);
|
||||
pyc_output << "}}";
|
||||
else
|
||||
fputc(*ch, F);
|
||||
pyc_output << *ch;
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
if (!parent_f_string_quote) {
|
||||
if (triple)
|
||||
fputs(useQuotes ? "\"\"\"" : "'''", F);
|
||||
pyc_output << (useQuotes ? "\"\"\"" : "'''");
|
||||
else
|
||||
fputc(useQuotes ? '"' : '\'', F);
|
||||
pyc_output << (useQuotes ? '"' : '\'');
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
void OutputString(PycRef<PycString> str, char prefix = 0, bool triple = false,
|
||||
FILE* F = pyc_output, const char* parent_f_string_quote = nullptr);
|
||||
void OutputString(PycRef<PycString> str, char prefix, bool triple,
|
||||
std::ostream& stream, const char* parent_f_string_quote = nullptr);
|
||||
|
||||
#endif
|
||||
|
180
pycdas.cpp
180
pycdas.cpp
@@ -2,9 +2,11 @@
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "pyc_module.h"
|
||||
#include "pyc_numeric.h"
|
||||
#include "bytecode.h"
|
||||
#include <fstream>
|
||||
|
||||
#ifdef WIN32
|
||||
# define PATHSEP '\\'
|
||||
@@ -25,57 +27,57 @@ static const char* flag_names[] = {
|
||||
"<0x10000000>", "<0x20000000>", "<0x40000000>", "<0x80000000>"
|
||||
};
|
||||
|
||||
static void print_coflags(unsigned long flags)
|
||||
static void print_coflags(unsigned long flags, std::ostream& pyc_output)
|
||||
{
|
||||
if (flags == 0) {
|
||||
fputs("\n", pyc_output);
|
||||
pyc_output << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
fputs(" (", pyc_output);
|
||||
pyc_output << " (";
|
||||
unsigned long f = 1;
|
||||
int k = 0;
|
||||
while (k < 32) {
|
||||
if ((flags & f) != 0) {
|
||||
flags &= ~f;
|
||||
if (flags == 0)
|
||||
fputs(flag_names[k], pyc_output);
|
||||
pyc_output << flag_names[k];
|
||||
else
|
||||
fprintf(pyc_output, "%s | ", flag_names[k]);
|
||||
pyc_output << flag_names[k] << " | ";
|
||||
}
|
||||
++k;
|
||||
f <<= 1;
|
||||
}
|
||||
fputs(")\n", pyc_output);
|
||||
pyc_output << ")\n";
|
||||
}
|
||||
|
||||
static void iputs(int indent, const char* text)
|
||||
static void iputs(std::ostream& pyc_output, int indent, const char* text)
|
||||
{
|
||||
for (int i=0; i<indent; i++)
|
||||
fputs(" ", pyc_output);
|
||||
fputs(text, pyc_output);
|
||||
pyc_output << " ";
|
||||
pyc_output << text;
|
||||
}
|
||||
|
||||
static void ivprintf(int indent, const char* fmt, va_list varargs)
|
||||
static void ivprintf(std::ostream& pyc_output, int indent, const char* fmt, va_list varargs)
|
||||
{
|
||||
for (int i=0; i<indent; i++)
|
||||
fputs(" ", pyc_output);
|
||||
vfprintf(pyc_output, fmt, varargs);
|
||||
pyc_output << " ";
|
||||
formatted_print(pyc_output, fmt, varargs);
|
||||
}
|
||||
|
||||
static void iprintf(int indent, const char* fmt, ...)
|
||||
static void iprintf(std::ostream& pyc_output, int indent, const char* fmt, ...)
|
||||
{
|
||||
va_list varargs;
|
||||
va_start(varargs, fmt);
|
||||
ivprintf(indent, fmt, varargs);
|
||||
ivprintf(pyc_output, indent, fmt, varargs);
|
||||
va_end(varargs);
|
||||
}
|
||||
|
||||
void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
|
||||
unsigned flags)
|
||||
unsigned flags, std::ostream& pyc_output)
|
||||
{
|
||||
if (obj == NULL) {
|
||||
iputs(indent, "<NULL>");
|
||||
iputs(pyc_output, indent, "<NULL>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,175 +86,175 @@ void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
|
||||
case PycObject::TYPE_CODE2:
|
||||
{
|
||||
PycRef<PycCode> codeObj = obj.cast<PycCode>();
|
||||
iputs(indent, "[Code]\n");
|
||||
iprintf(indent + 1, "File Name: %s\n", codeObj->fileName()->value());
|
||||
iprintf(indent + 1, "Object Name: %s\n", codeObj->name()->value());
|
||||
iputs(pyc_output, indent, "[Code]\n");
|
||||
iprintf(pyc_output, indent + 1, "File Name: %s\n", codeObj->fileName()->value());
|
||||
iprintf(pyc_output, indent + 1, "Object Name: %s\n", codeObj->name()->value());
|
||||
if (mod->verCompare(3, 11) >= 0)
|
||||
iprintf(indent + 1, "Qualified Name: %s\n", codeObj->qualName()->value());
|
||||
iprintf(indent + 1, "Arg Count: %d\n", codeObj->argCount());
|
||||
iprintf(pyc_output, indent + 1, "Qualified Name: %s\n", codeObj->qualName()->value());
|
||||
iprintf(pyc_output, indent + 1, "Arg Count: %d\n", codeObj->argCount());
|
||||
if (mod->verCompare(3, 8) >= 0)
|
||||
iprintf(indent + 1, "Pos Only Arg Count: %d\n", codeObj->posOnlyArgCount());
|
||||
iprintf(pyc_output, indent + 1, "Pos Only Arg Count: %d\n", codeObj->posOnlyArgCount());
|
||||
if (mod->majorVer() >= 3)
|
||||
iprintf(indent + 1, "KW Only Arg Count: %d\n", codeObj->kwOnlyArgCount());
|
||||
iprintf(pyc_output, indent + 1, "KW Only Arg Count: %d\n", codeObj->kwOnlyArgCount());
|
||||
if (mod->verCompare(3, 11) < 0)
|
||||
iprintf(indent + 1, "Locals: %d\n", codeObj->numLocals());
|
||||
iprintf(pyc_output, indent + 1, "Locals: %d\n", codeObj->numLocals());
|
||||
if (mod->verCompare(1, 5) >= 0)
|
||||
iprintf(indent + 1, "Stack Size: %d\n", codeObj->stackSize());
|
||||
iprintf(pyc_output, indent + 1, "Stack Size: %d\n", codeObj->stackSize());
|
||||
if (mod->verCompare(1, 3) >= 0) {
|
||||
iprintf(indent + 1, "Flags: 0x%08X", codeObj->flags());
|
||||
print_coflags(codeObj->flags());
|
||||
iprintf(pyc_output, indent + 1, "Flags: 0x%08X", codeObj->flags());
|
||||
print_coflags(codeObj->flags(), pyc_output);
|
||||
}
|
||||
|
||||
iputs(indent + 1, "[Names]\n");
|
||||
iputs(pyc_output, indent + 1, "[Names]\n");
|
||||
for (int i=0; i<codeObj->names()->size(); i++)
|
||||
output_object(codeObj->names()->get(i), mod, indent + 2, flags);
|
||||
output_object(codeObj->names()->get(i), mod, indent + 2, flags, pyc_output);
|
||||
|
||||
if (mod->verCompare(1, 3) >= 0 && mod->verCompare(3, 11) < 0) {
|
||||
if (mod->verCompare(3, 11) >= 0)
|
||||
iputs(indent + 1, "[Locals+Names]\n");
|
||||
iputs(pyc_output, indent + 1, "[Locals+Names]\n");
|
||||
else
|
||||
iputs(indent + 1, "[Var Names]\n");
|
||||
iputs(pyc_output, indent + 1, "[Var Names]\n");
|
||||
for (int i=0; i<codeObj->localNames()->size(); i++)
|
||||
output_object(codeObj->localNames()->get(i), mod, indent + 2, flags);
|
||||
output_object(codeObj->localNames()->get(i), mod, indent + 2, flags, pyc_output);
|
||||
}
|
||||
|
||||
if (mod->verCompare(3, 11) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) {
|
||||
iputs(indent + 1, "[Locals+Kinds]\n");
|
||||
output_object(codeObj->localKinds().cast<PycObject>(), mod, indent + 2, flags);
|
||||
iputs(pyc_output, indent + 1, "[Locals+Kinds]\n");
|
||||
output_object(codeObj->localKinds().cast<PycObject>(), mod, indent + 2, flags, pyc_output);
|
||||
}
|
||||
|
||||
if (mod->verCompare(2, 1) >= 0 && mod->verCompare(3, 11) < 0) {
|
||||
iputs(indent + 1, "[Free Vars]\n");
|
||||
iputs(pyc_output, indent + 1, "[Free Vars]\n");
|
||||
for (int i=0; i<codeObj->freeVars()->size(); i++)
|
||||
output_object(codeObj->freeVars()->get(i), mod, indent + 2, flags);
|
||||
output_object(codeObj->freeVars()->get(i), mod, indent + 2, flags, pyc_output);
|
||||
|
||||
iputs(indent + 1, "[Cell Vars]\n");
|
||||
iputs(pyc_output, indent + 1, "[Cell Vars]\n");
|
||||
for (int i=0; i<codeObj->cellVars()->size(); i++)
|
||||
output_object(codeObj->cellVars()->get(i), mod, indent + 2, flags);
|
||||
output_object(codeObj->cellVars()->get(i), mod, indent + 2, flags, pyc_output);
|
||||
}
|
||||
|
||||
iputs(indent + 1, "[Constants]\n");
|
||||
iputs(pyc_output, indent + 1, "[Constants]\n");
|
||||
for (int i=0; i<codeObj->consts()->size(); i++)
|
||||
output_object(codeObj->consts()->get(i), mod, indent + 2, flags);
|
||||
output_object(codeObj->consts()->get(i), mod, indent + 2, flags, pyc_output);
|
||||
|
||||
iputs(indent + 1, "[Disassembly]\n");
|
||||
bc_disasm(codeObj, mod, indent + 2, flags);
|
||||
iputs(pyc_output, indent + 1, "[Disassembly]\n");
|
||||
bc_disasm(codeObj, mod, indent + 2, flags, pyc_output);
|
||||
|
||||
if (mod->verCompare(1, 5) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) {
|
||||
iputs(indent + 1, "[Line Number Table]\n");
|
||||
output_object(codeObj->lnTable().cast<PycObject>(), mod, indent + 2, flags);
|
||||
iputs(pyc_output, indent + 1, "[Line Number Table]\n");
|
||||
output_object(codeObj->lnTable().cast<PycObject>(), mod, indent + 2, flags, pyc_output);
|
||||
}
|
||||
|
||||
if (mod->verCompare(3, 11) >= 0 && (flags & Pyc::DISASM_PYCODE_VERBOSE) != 0) {
|
||||
iputs(indent + 1, "[Exception Table]\n");
|
||||
output_object(codeObj->exceptTable().cast<PycObject>(), mod, indent + 2, flags);
|
||||
iputs(pyc_output, indent + 1, "[Exception Table]\n");
|
||||
output_object(codeObj->exceptTable().cast<PycObject>(), mod, indent + 2, flags, pyc_output);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_STRING:
|
||||
iputs(indent, "");
|
||||
OutputString(obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0);
|
||||
fputs("\n", pyc_output);
|
||||
iputs(pyc_output, indent, "");
|
||||
OutputString(obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0, false, pyc_output);
|
||||
pyc_output << "\n";
|
||||
break;
|
||||
case PycObject::TYPE_UNICODE:
|
||||
iputs(indent, "");
|
||||
OutputString(obj.cast<PycString>(), mod->strIsUnicode() ? 0 : 'u');
|
||||
fputs("\n", pyc_output);
|
||||
iputs(pyc_output, indent, "");
|
||||
OutputString(obj.cast<PycString>(), mod->strIsUnicode() ? 0 : 'u', false, pyc_output);
|
||||
pyc_output << "\n";
|
||||
break;
|
||||
case PycObject::TYPE_INTERNED:
|
||||
case PycObject::TYPE_ASCII:
|
||||
case PycObject::TYPE_ASCII_INTERNED:
|
||||
case PycObject::TYPE_SHORT_ASCII:
|
||||
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
||||
iputs(indent, "");
|
||||
iputs(pyc_output, indent, "");
|
||||
if (mod->majorVer() >= 3)
|
||||
OutputString(obj.cast<PycString>(), 0);
|
||||
OutputString(obj.cast<PycString>(), 0, false, pyc_output);
|
||||
else
|
||||
OutputString(obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0);
|
||||
fputs("\n", pyc_output);
|
||||
OutputString(obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0, false, pyc_output);
|
||||
pyc_output << "\n";
|
||||
break;
|
||||
case PycObject::TYPE_TUPLE:
|
||||
case PycObject::TYPE_SMALL_TUPLE:
|
||||
{
|
||||
iputs(indent, "(\n");
|
||||
iputs(pyc_output, indent, "(\n");
|
||||
for (const auto& val : obj.cast<PycTuple>()->values())
|
||||
output_object(val, mod, indent + 1, flags);
|
||||
iputs(indent, ")\n");
|
||||
output_object(val, mod, indent + 1, flags, pyc_output);
|
||||
iputs(pyc_output, indent, ")\n");
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_LIST:
|
||||
{
|
||||
iputs(indent, "[\n");
|
||||
iputs(pyc_output, indent, "[\n");
|
||||
for (const auto& val : obj.cast<PycList>()->values())
|
||||
output_object(val, mod, indent + 1, flags);
|
||||
iputs(indent, "]\n");
|
||||
output_object(val, mod, indent + 1, flags, pyc_output);
|
||||
iputs(pyc_output, indent, "]\n");
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_DICT:
|
||||
{
|
||||
iputs(indent, "{\n");
|
||||
iputs(pyc_output, indent, "{\n");
|
||||
PycDict::key_t keys = obj.cast<PycDict>()->keys();
|
||||
PycDict::value_t values = obj.cast<PycDict>()->values();
|
||||
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, flags);
|
||||
output_object(*vi, mod, indent + 2, flags);
|
||||
output_object(*ki, mod, indent + 1, flags, pyc_output);
|
||||
output_object(*vi, mod, indent + 2, flags, pyc_output);
|
||||
++ki, ++vi;
|
||||
}
|
||||
iputs(indent, "}\n");
|
||||
iputs(pyc_output, indent, "}\n");
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_SET:
|
||||
{
|
||||
iputs(indent, "{\n");
|
||||
iputs(pyc_output, indent, "{\n");
|
||||
for (const auto& val : obj.cast<PycSet>()->values())
|
||||
output_object(val, mod, indent + 1, flags);
|
||||
iputs(indent, "}\n");
|
||||
output_object(val, mod, indent + 1, flags, pyc_output);
|
||||
iputs(pyc_output, indent, "}\n");
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_FROZENSET:
|
||||
{
|
||||
iputs(indent, "frozenset({\n");
|
||||
iputs(pyc_output, indent, "frozenset({\n");
|
||||
for (const auto& val : obj.cast<PycSet>()->values())
|
||||
output_object(val, mod, indent + 1, flags);
|
||||
iputs(indent, "})\n");
|
||||
output_object(val, mod, indent + 1, flags, pyc_output);
|
||||
iputs(pyc_output, indent, "})\n");
|
||||
}
|
||||
break;
|
||||
case PycObject::TYPE_NONE:
|
||||
iputs(indent, "None\n");
|
||||
iputs(pyc_output, indent, "None\n");
|
||||
break;
|
||||
case PycObject::TYPE_FALSE:
|
||||
iputs(indent, "False\n");
|
||||
iputs(pyc_output, indent, "False\n");
|
||||
break;
|
||||
case PycObject::TYPE_TRUE:
|
||||
iputs(indent, "True\n");
|
||||
iputs(pyc_output, indent, "True\n");
|
||||
break;
|
||||
case PycObject::TYPE_ELLIPSIS:
|
||||
iputs(indent, "...\n");
|
||||
iputs(pyc_output, indent, "...\n");
|
||||
break;
|
||||
case PycObject::TYPE_INT:
|
||||
iprintf(indent, "%d\n", obj.cast<PycInt>()->value());
|
||||
iprintf(pyc_output, indent, "%d\n", obj.cast<PycInt>()->value());
|
||||
break;
|
||||
case PycObject::TYPE_LONG:
|
||||
iprintf(indent, "%s\n", obj.cast<PycLong>()->repr().c_str());
|
||||
iprintf(pyc_output, indent, "%s\n", obj.cast<PycLong>()->repr().c_str());
|
||||
break;
|
||||
case PycObject::TYPE_FLOAT:
|
||||
iprintf(indent, "%s\n", obj.cast<PycFloat>()->value());
|
||||
iprintf(pyc_output, indent, "%s\n", obj.cast<PycFloat>()->value());
|
||||
break;
|
||||
case PycObject::TYPE_COMPLEX:
|
||||
iprintf(indent, "(%s+%sj)\n", obj.cast<PycComplex>()->value(),
|
||||
iprintf(pyc_output, indent, "(%s+%sj)\n", obj.cast<PycComplex>()->value(),
|
||||
obj.cast<PycComplex>()->imag());
|
||||
break;
|
||||
case PycObject::TYPE_BINARY_FLOAT:
|
||||
iprintf(indent, "%g\n", obj.cast<PycCFloat>()->value());
|
||||
iprintf(pyc_output, indent, "%g\n", obj.cast<PycCFloat>()->value());
|
||||
break;
|
||||
case PycObject::TYPE_BINARY_COMPLEX:
|
||||
iprintf(indent, "(%g+%gj)\n", obj.cast<PycCComplex>()->value(),
|
||||
iprintf(pyc_output, indent, "(%g+%gj)\n", obj.cast<PycCComplex>()->value(),
|
||||
obj.cast<PycCComplex>()->imag());
|
||||
break;
|
||||
default:
|
||||
iprintf(indent, "<TYPE: %d>\n", obj->type());
|
||||
iprintf(pyc_output, indent, "<TYPE: %d>\n", obj->type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,18 +264,20 @@ int main(int argc, char* argv[])
|
||||
bool marshalled = false;
|
||||
const char* version = nullptr;
|
||||
unsigned disasm_flags = 0;
|
||||
std::ostream &pyc_output = std::cout;
|
||||
|
||||
for (int arg = 1; arg < argc; ++arg) {
|
||||
if (strcmp(argv[arg], "-o") == 0) {
|
||||
if (arg + 1 < argc) {
|
||||
const char* filename = argv[++arg];
|
||||
FILE* outfile = fopen(filename, "w");
|
||||
if (!outfile) {
|
||||
|
||||
auto* outfile = new std::filebuf;
|
||||
if(! outfile->open(filename, std::ios::out)) {
|
||||
fprintf(stderr, "Error opening file '%s' for writing\n",
|
||||
argv[arg]);
|
||||
return 1;
|
||||
}
|
||||
pyc_output = outfile;
|
||||
pyc_output.rdbuf(outfile);
|
||||
} else {
|
||||
fputs("Option '-o' requires a filename\n", stderr);
|
||||
return 1;
|
||||
@@ -339,10 +343,10 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
const char* dispname = strrchr(infile, PATHSEP);
|
||||
dispname = (dispname == NULL) ? infile : dispname + 1;
|
||||
fprintf(pyc_output, "%s (Python %d.%d%s)\n", dispname, mod.majorVer(), mod.minorVer(),
|
||||
formatted_print(pyc_output, "%s (Python %d.%d%s)\n", dispname, mod.majorVer(), mod.minorVer(),
|
||||
(mod.majorVer() < 3 && mod.isUnicode()) ? " -U" : "");
|
||||
try {
|
||||
output_object(mod.code().try_cast<PycObject>(), &mod, 0, disasm_flags);
|
||||
output_object(mod.code().try_cast<PycObject>(), &mod, 0, disasm_flags, pyc_output);
|
||||
} catch (std::exception& ex) {
|
||||
fprintf(stderr, "Error disassembling %s: %s\n", infile, ex.what());
|
||||
return 1;
|
||||
|
16
pycdc.cpp
16
pycdc.cpp
@@ -1,4 +1,6 @@
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "ASTree.h"
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -12,17 +14,19 @@ int main(int argc, char* argv[])
|
||||
const char* infile = nullptr;
|
||||
bool marshalled = false;
|
||||
const char* version = nullptr;
|
||||
std::ostream &pyc_output = std::cout;
|
||||
|
||||
for (int arg = 1; arg < argc; ++arg) {
|
||||
if (strcmp(argv[arg], "-o") == 0) {
|
||||
if (arg + 1 < argc) {
|
||||
const char* filename = argv[++arg];
|
||||
FILE* outfile = fopen(filename, "w");
|
||||
if (!outfile) {
|
||||
auto* outfile = new std::filebuf;
|
||||
if(! outfile->open(filename, std::ios::out)) {
|
||||
fprintf(stderr, "Error opening file '%s' for writing\n",
|
||||
argv[arg]);
|
||||
return 1;
|
||||
}
|
||||
pyc_output = outfile;
|
||||
pyc_output.rdbuf(outfile);
|
||||
} else {
|
||||
fputs("Option '-o' requires a filename\n", stderr);
|
||||
return 1;
|
||||
@@ -84,11 +88,11 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
const char* dispname = strrchr(infile, PATHSEP);
|
||||
dispname = (dispname == NULL) ? infile : dispname + 1;
|
||||
fputs("# Source Generated with Decompyle++\n", pyc_output);
|
||||
fprintf(pyc_output, "# File: %s (Python %d.%d%s)\n\n", dispname, mod.majorVer(), mod.minorVer(),
|
||||
std::cout << "# Source Generated with Decompyle++\n";
|
||||
formatted_print(pyc_output, "# File: %s (Python %d.%d%s)\n\n", dispname, mod.majorVer(), mod.minorVer(),
|
||||
(mod.majorVer() < 3 && mod.isUnicode()) ? " Unicode" : "");
|
||||
try {
|
||||
decompyle(mod.code(), &mod);
|
||||
decompyle(mod.code(), &mod, pyc_output);
|
||||
} catch (std::exception& ex) {
|
||||
fprintf(stderr, "Error decompyling %s: %s\n", infile, ex.what());
|
||||
return 1;
|
||||
|
Reference in New Issue
Block a user