This repository was archived by the owner on Jul 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction-definitions.cpp
More file actions
148 lines (120 loc) · 5.74 KB
/
function-definitions.cpp
File metadata and controls
148 lines (120 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef FUNCTION_DEFINITIONS_CPP
#define FUNCTION_DEFINITIONS_CPP
#include "decompile.cpp"
namespace jdecompiler {
EnumClass::EnumClass(const Version& version, const ClassType& thisType, const ClassType* superType, const ConstantPool& constPool, modifiers_t modifiers,
const vector<const ClassType*>& interfaces, const Attributes& attributes, const vector<FieldDataHolder>& fieldsData,
const vector<MethodDataHolder>& methodData, const vector<const GenericParameter*>& genericParameters):
Class(version, thisType, superType, constPool, modifiers, interfaces, attributes, fieldsData, methodData, genericParameters) {
for(const Field* field : fields) {
const InvokespecialOperation* invokespecialOperation;
const Dup1Operation* dupOperation;
const NewOperation* newOperation;
if(field->modifiers & ACC_ENUM && field->descriptor.type == thisType && field->hasInitializer() &&
(invokespecialOperation = dynamic_cast<const InvokespecialOperation*>(field->getInitializer())) != nullptr &&
(dupOperation = dynamic_cast<const Dup1Operation*>(invokespecialOperation->object)) != nullptr &&
(newOperation = dynamic_cast<const NewOperation*>(dupOperation->operation)) != nullptr) {
if(field->modifiers != (ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_ENUM))
throw IllegalModifiersException("Enum constant must has public, static, final and enum flags, got " + hexWithPrefix<4>(field->modifiers));
if(invokespecialOperation->arguments.size() < 2)
throw DecompilationException("Enum constant initializer should have at least two arguments, got " +
to_string(invokespecialOperation->arguments.size()));
enumFields.push_back(new EnumField(*field, invokespecialOperation->arguments));
} else {
otherFields.push_back(field);
}
}
}
DecompilationContext::DecompilationContext(const DisassemblerContext& disassemblerContext, const ClassInfo& classinfo, MethodScope* methodScope,
modifiers_t modifiers, const MethodDescriptor& descriptor, const Attributes& attributes, uint16_t maxLocals):
DecompilationAndStringifyContext(disassemblerContext, classinfo, *methodScope, modifiers, descriptor, attributes),
stack(*new CodeStack()) {
for(uint32_t i = methodScope->getVariablesCount(); i < maxLocals; i++)
methodScope->addVariable(new UnnamedVariable(AnyType::getInstance(), false));
}
void DecompilationContext::updateScopes() {
while(index >= currentScope->end()) {
if(currentScope->parentScope == nullptr)
throw DecompilationException("Unexpected end of global function scope " + currentScope->toDebugString());
currentScope->finalize(*this);
log(index, " end of ", currentScope->toDebugString());
currentScope = currentScope->parentScope;
}
for(auto i = inactiveScopes.begin(); i != inactiveScopes.end(); ) {
const Scope* scope = *i;
if(scope->start() <= index) {
/*if(scope->end() > currentScope->end())
throw DecompilationException((string)"Scope " + scope->toDebugString() +
" is out of bounds of the parent scope " + currentScope->toDebugString());*/
/*if(index > scope->start()) {
throw IllegalStateException("Scope " + scope->toDebugString() + " is added after it starts");
}*/
log(index, "start of ", scope->toDebugString());
currentScope->addOperation(scope, *this);
currentScope = scope;
//scope->initiate(*this);
inactiveScopes.erase(i);
} else
++i;
}
}
string ClassInfo::importsToString() const {
string str;
for(const ClassType* clazz : imports) {
if(clazz->packageName != "java.lang" && clazz->packageName != thisType.packageName) {
str += (string)this->getIndent() + "import " + clazz->getName() + ";\n";
}
}
return str.empty() ? str : str + '\n';
}
/* Returns true if we can write simple class name */
bool ClassInfo::addImport(const ClassType* clazz) const {
if(clazz->simpleName == thisType.simpleName) {
return *clazz == thisType;
}
if(any_of(imports.begin(), imports.end(), [clazz] (const ClassType* imp) { return *clazz == *imp; })) { // find class
return true;
} else {
if(all_of(imports.begin(), imports.end(), [clazz] (const ClassType* imp)
{ return imp->simpleName != clazz->simpleName; })) { // check has no class with same name
imports.push_back(clazz);
return true;
}
return false;
}
}
string ClassType::toString(const ClassInfo& classinfo) const {
return this->isAnonymous ? fullSimpleName : (classinfo.addImport(this) ? simpleName : name) + (parameters.empty() ? EMPTY_STRING :
'<' + join<const ReferenceType*>(parameters, [&classinfo] (const ReferenceType* type) { return type->toString(classinfo); }) + '>');
}
void JDecompiler::readClassFiles() const {
if(atLeastOneFileSpecified) {
for(ClassInputStream* classFile : files) {
try {
Class::readClass(*classFile); /* Adding a class to JDecompiler::classes takes place in the class constructor */
} catch(const EOFException& ex) {
error("unexpected end of file while reading ", classFile->fileName);
} catch(const Exception& ex) {
error(ex.toString());
}
}
} else {
error("no input file specified");
}
}
void StringifyContext::enterScope(const Scope* scope) const {
currentScope = scope;
}
void StringifyContext::exitScope(const Scope* scope) const {
/*if(scope != currentScope) {
throw IllegalStateException("While stringify method " + descriptor.toString() + ": scope != currentScope (scope = " + scope->toDebugString() + "; currentScope = " + currentScope->toDebugString() + ')');
}*/
currentScope = scope->parentScope;
}
const DisassemblerContext& ClassInfo::getEmptyDisassemblerContext() const {
if(emptyDisassemblerContext == nullptr)
emptyDisassemblerContext = new DisassemblerContext(constPool, 0, (const uint8_t*)"");
return *emptyDisassemblerContext;
}
}
#endif