Use C++ streams over C style IO

This commit is contained in:
Perceval Wajsbürt
2023-06-02 00:36:58 +02:00
committed by Perceval Wajsbürt
parent 409f175827
commit c4c35fc531
10 changed files with 488 additions and 460 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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";
}
}

View File

@@ -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);

View File

@@ -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
View File

@@ -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

View File

@@ -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 ? '"' : '\'');
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;