Pure Evil
This commit is contained in:
parent
842f05a288
commit
67c4adaa77
@ -163,4 +163,31 @@ export class Size {
|
|||||||
isExact() {
|
isExact() {
|
||||||
return this.#isExact;
|
return this.#isExact;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
export function getArgNames(args: string) {
|
||||||
|
// Remove Parentheses
|
||||||
|
args = args.substring(1, args.length - 1);
|
||||||
|
if (args.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// Split
|
||||||
|
const argsList = args.split(',');
|
||||||
|
// Parse
|
||||||
|
const out = [];
|
||||||
|
for (let arg of argsList) {
|
||||||
|
arg = arg.trim();
|
||||||
|
// Remove Type
|
||||||
|
const nameStart = Math.max(arg.lastIndexOf(' '), arg.lastIndexOf('*')) + 1;
|
||||||
|
arg = arg.substring(nameStart);
|
||||||
|
// Collect
|
||||||
|
out.push(arg);
|
||||||
|
}
|
||||||
|
// Return
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
export function prependArg(args: string, arg: string) {
|
||||||
|
if (args !== '()') {
|
||||||
|
arg += ', ';
|
||||||
|
}
|
||||||
|
return '(' + arg + args.substring(1);
|
||||||
}
|
}
|
110
src/cpp.ts
110
src/cpp.ts
@ -1,110 +0,0 @@
|
|||||||
import { INDENT } from './common';
|
|
||||||
import { SimpleProperty } from './property';
|
|
||||||
|
|
||||||
// List Of Supported C++ Types
|
|
||||||
const CPP_TYPES = [
|
|
||||||
'std::string',
|
|
||||||
'std::vector<',
|
|
||||||
'std::map<'
|
|
||||||
];
|
|
||||||
const CPP_HEADERS = [
|
|
||||||
'string',
|
|
||||||
'vector',
|
|
||||||
'map'
|
|
||||||
];
|
|
||||||
|
|
||||||
// Get Fake Type Name
|
|
||||||
function isGeneric(type: string) {
|
|
||||||
return type.endsWith('<');
|
|
||||||
}
|
|
||||||
function removeGeneric(type: string) {
|
|
||||||
if (isGeneric(type)) {
|
|
||||||
// Remove Generic Parameters
|
|
||||||
type = type.substring(0, type.length - 1);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
function getFakeName(type: string) {
|
|
||||||
return removeGeneric(type).replaceAll('std::', '_std_');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate C Type Definition
|
|
||||||
function generateStruct(type: string) {
|
|
||||||
// Get Information
|
|
||||||
const property = new SimpleProperty(0, type, 'fake');
|
|
||||||
const size = property.propertySize();
|
|
||||||
const alignment = property.propertyAlignment();
|
|
||||||
// Generate
|
|
||||||
let struct = '';
|
|
||||||
struct += `typedef struct __attribute__((aligned(${alignment}))) __attribute__((packed)) {\n`;
|
|
||||||
struct += `${INDENT}uchar data[${size}];\n`;
|
|
||||||
struct += `} ${getFakeName(type)};\n`;
|
|
||||||
return struct;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn A C++ Header Into A C/C++ Headeer
|
|
||||||
export function fixupCpp(data: string) {
|
|
||||||
// Replace Types
|
|
||||||
for (const type of CPP_TYPES) {
|
|
||||||
// Check If Type Is Generic
|
|
||||||
if (isGeneric(type)) {
|
|
||||||
// Generic
|
|
||||||
while (data.includes(type)) {
|
|
||||||
// Find Type
|
|
||||||
let index = data.indexOf(type);
|
|
||||||
// Replace Type
|
|
||||||
data = data.substring(0, index) + getFakeName(type) + '(' + data.substring(index + type.length);
|
|
||||||
// Replace > With (
|
|
||||||
index = data.indexOf('>', index);
|
|
||||||
if (index !== -1) {
|
|
||||||
data = data.substring(0, index) + ')' + data.substring(index + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Normal
|
|
||||||
data = data.replaceAll(type, getFakeName(type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup Macros
|
|
||||||
let header = '';
|
|
||||||
header += '// C++ Types\n';
|
|
||||||
|
|
||||||
// C++ Support
|
|
||||||
header += '#ifdef __cplusplus\n';
|
|
||||||
for (const headerFile of CPP_HEADERS) {
|
|
||||||
header += `#include <${headerFile}>\n`;
|
|
||||||
}
|
|
||||||
for (const type of CPP_TYPES) {
|
|
||||||
const fakeName = getFakeName(type);
|
|
||||||
if (isGeneric(type)) {
|
|
||||||
header += `#define ${fakeName}(...) ${type}__VA_ARGS__>\n`;
|
|
||||||
} else {
|
|
||||||
header += `#define ${fakeName} ${type}\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// C Support
|
|
||||||
header += '#else\n';
|
|
||||||
for (let type of CPP_TYPES) {
|
|
||||||
const fakeName = getFakeName(type);
|
|
||||||
header += generateStruct(type);
|
|
||||||
// Strip Generic Information
|
|
||||||
if (isGeneric(type)) {
|
|
||||||
type = removeGeneric(type);
|
|
||||||
header += `#define ${fakeName}(...) ${fakeName}\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
header += '#endif\n';
|
|
||||||
|
|
||||||
// Cleanup Macros
|
|
||||||
let footer = '';
|
|
||||||
footer += '// Cleanup C++ Types\n';
|
|
||||||
for (const type of CPP_TYPES) {
|
|
||||||
const fakeName = getFakeName(type);
|
|
||||||
footer += `#undef ${fakeName}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return header + '\n' + data + '\n' + footer;
|
|
||||||
}
|
|
43
src/index.ts
43
src/index.ts
@ -2,7 +2,6 @@ import * as fs from 'node:fs';
|
|||||||
import { STRUCTURE_FILES, EXTENSION, INDENT } from './common';
|
import { STRUCTURE_FILES, EXTENSION, INDENT } from './common';
|
||||||
import { getStructure } from './map';
|
import { getStructure } from './map';
|
||||||
import { Struct } from './struct';
|
import { Struct } from './struct';
|
||||||
import { fixupCpp } from './cpp';
|
|
||||||
|
|
||||||
// Arguments
|
// Arguments
|
||||||
if (process.argv.length < 5) {
|
if (process.argv.length < 5) {
|
||||||
@ -158,25 +157,19 @@ function makeMainHeader(output: string) {
|
|||||||
for (const file of extraHeaders) {
|
for (const file of extraHeaders) {
|
||||||
result += fs.readFileSync(file, {encoding: 'utf8'});
|
result += fs.readFileSync(file, {encoding: 'utf8'});
|
||||||
}
|
}
|
||||||
let core = '';
|
result += '\n// Headers\n';
|
||||||
core += '// C/C++ Support\n';
|
result += '#include <cstddef>\n';
|
||||||
core += '#ifndef __cplusplus\n';
|
result += '#include <string>\n';
|
||||||
core += '#include <stddef.h>\n';
|
result += '#include <vector>\n';
|
||||||
core += '#include <assert.h>\n';
|
result += '#include <map>\n';
|
||||||
core += 'typedef uchar bool;\n';
|
result += '\n// Warnings\n';
|
||||||
core += '#else\n';
|
result += '#pragma GCC diagnostic push\n';
|
||||||
core += '#include <cstddef>\n';
|
result += '#pragma GCC diagnostic ignored "-Winvalid-offsetof"\n\n';
|
||||||
core += 'extern "C" {\n';
|
result += makeHeaderPart();
|
||||||
core += '#pragma GCC diagnostic push\n';
|
result += '\n// Cleanup Warnings\n';
|
||||||
core += '#pragma GCC diagnostic ignored "-Winvalid-offsetof"\n';
|
result += '#pragma GCC diagnostic pop\n';
|
||||||
core += '#endif\n\n';
|
result += '\n// Array Of All Method Symbols\n';
|
||||||
core += makeHeaderPart();
|
result += 'extern void *_all_method_symbols[];\n';
|
||||||
core += '\n// Cleanup C++ Support\n';
|
|
||||||
core += '#ifdef __cplusplus\n';
|
|
||||||
core += '#pragma GCC diagnostic pop\n';
|
|
||||||
core += '}\n';
|
|
||||||
core += '#endif\n';
|
|
||||||
result += '\n' + fixupCpp(core);
|
|
||||||
fs.writeFileSync(output, result);
|
fs.writeFileSync(output, result);
|
||||||
}
|
}
|
||||||
makeMainHeader(headerOutput);
|
makeMainHeader(headerOutput);
|
||||||
@ -219,6 +212,16 @@ function makeCompiledCode(output: string) {
|
|||||||
result += init;
|
result += init;
|
||||||
result += '}\n\n';
|
result += '}\n\n';
|
||||||
result += declarations;
|
result += declarations;
|
||||||
|
result += '\n// Setup Methods Array\n';
|
||||||
|
result += 'void *_all_method_symbols[] = {\n';
|
||||||
|
for (const structure of structureObjects) {
|
||||||
|
const methods = structure.getMethodSymbols();
|
||||||
|
for (const method of methods) {
|
||||||
|
result += `${INDENT}&${method},\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += `${INDENT}nullptr\n`;
|
||||||
|
result += '};\n';
|
||||||
fs.writeFileSync(output, result);
|
fs.writeFileSync(output, result);
|
||||||
}
|
}
|
||||||
makeCompiledCode(sourceOutput);
|
makeCompiledCode(sourceOutput);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { COMMENT, EXTENSION, getSelfArg, parseTypeAndName, readDefinition, safeParseInt, syntaxError } from './common';
|
import { COMMENT, EXTENSION, getSelfArg, parseTypeAndName, prependArg, readDefinition, safeParseInt, syntaxError } from './common';
|
||||||
import { Method } from './method';
|
import { Method } from './method';
|
||||||
import { SimpleProperty, StaticProperty } from './property';
|
import { SimpleProperty, StaticProperty } from './property';
|
||||||
import { Struct } from './struct';
|
import { Struct } from './struct';
|
||||||
@ -27,7 +27,7 @@ function parseProperty(args: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse Method
|
// Parse Method
|
||||||
function parseMethod(args: string, self: string, insertSelfArg: boolean) {
|
function parseMethod(args: string, self: string, insertSelfArg: boolean, isInherited: boolean) {
|
||||||
const argsStart = args.indexOf('(');
|
const argsStart = args.indexOf('(');
|
||||||
if (argsStart === -1) {
|
if (argsStart === -1) {
|
||||||
syntaxError('Cannot Find Arguments');
|
syntaxError('Cannot Find Arguments');
|
||||||
@ -43,14 +43,11 @@ function parseMethod(args: string, self: string, insertSelfArg: boolean) {
|
|||||||
syntaxError('Invalid Method Arguments');
|
syntaxError('Invalid Method Arguments');
|
||||||
}
|
}
|
||||||
if (insertSelfArg) {
|
if (insertSelfArg) {
|
||||||
let selfArg = `(${getSelfArg(self)}`;
|
const selfArg = getSelfArg(self);
|
||||||
if (methodArgs !== '()') {
|
methodArgs = prependArg(methodArgs, selfArg);
|
||||||
selfArg += ', ';
|
|
||||||
}
|
|
||||||
methodArgs = selfArg + methodArgs.substring(1);
|
|
||||||
}
|
}
|
||||||
const address = safeParseInt(end[1]!);
|
const address = safeParseInt(end[1]!);
|
||||||
return new Method(self, name, type, methodArgs, address);
|
return new Method(self, name, type, methodArgs, address, isInherited);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Structure
|
// Load Structure
|
||||||
@ -103,6 +100,9 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
|||||||
switch (command) {
|
switch (command) {
|
||||||
case 'extends': {
|
case 'extends': {
|
||||||
// Load Parent
|
// Load Parent
|
||||||
|
if (!isExtended) {
|
||||||
|
target.setDirectParent(args);
|
||||||
|
}
|
||||||
load(target, args, true);
|
load(target, args, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -148,20 +148,20 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
|||||||
}
|
}
|
||||||
case 'method': {
|
case 'method': {
|
||||||
// Add Method
|
// Add Method
|
||||||
const method = parseMethod(args, target.getName(), true);
|
const method = parseMethod(args, target.getName(), true, isExtended);
|
||||||
target.addMethod(method, false);
|
target.addMethod(method, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'virtual-method': {
|
case 'virtual-method': {
|
||||||
// Add Virtual Method
|
// Add Virtual Method
|
||||||
const method = parseMethod(args, target.getName(), true);
|
const method = parseMethod(args, target.getName(), true, isExtended);
|
||||||
target.addMethod(method, true);
|
target.addMethod(method, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'static-method': {
|
case 'static-method': {
|
||||||
// Add Static Method
|
// Add Static Method
|
||||||
if (!isExtended) {
|
if (!isExtended) {
|
||||||
const method = parseMethod(args, target.getName(), false);
|
const method = parseMethod(args, target.getName(), false, false);
|
||||||
target.addMethod(method, false);
|
target.addMethod(method, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -178,11 +178,16 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
|||||||
data += '_';
|
data += '_';
|
||||||
}
|
}
|
||||||
data += args;
|
data += args;
|
||||||
const method = parseMethod(data, target.getName(), true);
|
const method = parseMethod(data, target.getName(), true, false);
|
||||||
target.addMethod(method, false);
|
target.addMethod(method, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'vtable-destructor-offset': {
|
||||||
|
// Set VTable Destructor Offset
|
||||||
|
target.setVTableDestructorOffset(safeParseInt(args));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new Error(`Invalid Command: ${command}`);
|
throw new Error(`Invalid Command: ${command}`);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { formatType } from './common';
|
import { INDENT, formatType, getArgNames } from './common';
|
||||||
|
|
||||||
export class Method {
|
export class Method {
|
||||||
readonly self: string;
|
readonly self: string;
|
||||||
@ -6,19 +6,24 @@ export class Method {
|
|||||||
readonly returnType: string;
|
readonly returnType: string;
|
||||||
readonly args: string;
|
readonly args: string;
|
||||||
readonly address: number;
|
readonly address: number;
|
||||||
|
readonly isInherited: boolean;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor(self: string, name: string, returnType: string, args: string, address: number) {
|
constructor(self: string, name: string, returnType: string, args: string, address: number, isInherited: boolean) {
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.shortName = name;
|
this.shortName = name;
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
|
this.isInherited = isInherited;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Type
|
// Get Type
|
||||||
|
getNameWithCustomSelf(self: string) {
|
||||||
|
return `${self}_${this.shortName}`;
|
||||||
|
}
|
||||||
getName() {
|
getName() {
|
||||||
return `${this.self}_${this.shortName}`;
|
return this.getNameWithCustomSelf(this.self);
|
||||||
}
|
}
|
||||||
getType() {
|
getType() {
|
||||||
return `${this.getName()}_t`;
|
return `${this.getName()}_t`;
|
||||||
@ -26,12 +31,39 @@ export class Method {
|
|||||||
|
|
||||||
// Generate Type Definition
|
// Generate Type Definition
|
||||||
generateTypedef() {
|
generateTypedef() {
|
||||||
|
let out = '';
|
||||||
|
|
||||||
|
// Normal Definition
|
||||||
const returnType = formatType(this.returnType);
|
const returnType = formatType(this.returnType);
|
||||||
return `typedef ${returnType}(*${this.getType()})${this.args};\n`;
|
out += `typedef ${returnType}(*${this.getType()})${this.args};\n`;
|
||||||
|
|
||||||
|
// Fancy Overwrite Does Not Support Varargs
|
||||||
|
if (!this.args.includes('...')) {
|
||||||
|
// Overwrite Helper
|
||||||
|
out += `#define _overwrite_helper_for_${this.getName()}(method, original) \\\n`;
|
||||||
|
out += `${INDENT}[]${this.args} { \\\n`;
|
||||||
|
out += `${INDENT}${INDENT}${returnType.trim() === 'void' ? '' : 'return '}method(${['original'].concat(getArgNames(this.args)).join(', ')}); \\\n`;
|
||||||
|
out += `${INDENT}}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Variable Definition
|
// Generate Variable Definition
|
||||||
generateDefinition(nameSuffix?: string) {
|
generateDefinition(nameSuffix?: string) {
|
||||||
return `${this.getType()} ${this.getName()}${nameSuffix !== undefined ? nameSuffix : ''};\n`;
|
return `${this.getType()} ${this.getName()}${nameSuffix !== undefined ? nameSuffix : ''};\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate "New Method" Test
|
||||||
|
generateNewMethodTest(parent: string | null, prefix: string, suffix: string) {
|
||||||
|
let out = `#define _is_new_method_${this.getName()}() (`;
|
||||||
|
if (!this.isInherited) {
|
||||||
|
out += 'true';
|
||||||
|
} else {
|
||||||
|
out += `((void *) ${prefix}${this.getName()}${suffix}) != ((void *) ${prefix}${this.getNameWithCustomSelf(parent!)}${suffix})`;
|
||||||
|
}
|
||||||
|
out += ')\n';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
@ -11,6 +11,8 @@ export class Struct {
|
|||||||
readonly #size: Size;
|
readonly #size: Size;
|
||||||
readonly #dependencies: string[];
|
readonly #dependencies: string[];
|
||||||
readonly #staticProperties: StaticProperty[];
|
readonly #staticProperties: StaticProperty[];
|
||||||
|
#directParent: string | null;
|
||||||
|
#vtableDestructorOffset: number;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
@ -21,6 +23,8 @@ export class Struct {
|
|||||||
this.#size = new Size(false);
|
this.#size = new Size(false);
|
||||||
this.#dependencies = [];
|
this.#dependencies = [];
|
||||||
this.#staticProperties = [];
|
this.#staticProperties = [];
|
||||||
|
this.#directParent = null;
|
||||||
|
this.#vtableDestructorOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
@ -34,11 +38,19 @@ export class Struct {
|
|||||||
// Ensure VTable Exists
|
// Ensure VTable Exists
|
||||||
ensureVTable() {
|
ensureVTable() {
|
||||||
if (this.#vtable === null) {
|
if (this.#vtable === null) {
|
||||||
this.#vtable = new VTable(this.#name);
|
this.#vtable = new VTable(this.#name, this.#vtableDestructorOffset);
|
||||||
this.addProperty(this.#vtable);
|
this.addProperty(this.#vtable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set VTable Destructor Offset
|
||||||
|
setVTableDestructorOffset(offset: number) {
|
||||||
|
if (this.#vtable) {
|
||||||
|
throw new Error('VTable Already Created');
|
||||||
|
}
|
||||||
|
this.#vtableDestructorOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
setSize(size: number, isExact: boolean) {
|
setSize(size: number, isExact: boolean) {
|
||||||
this.#size.set(size, isExact);
|
this.#size.set(size, isExact);
|
||||||
@ -200,11 +212,12 @@ export class Struct {
|
|||||||
for (const method of this.#methods) {
|
for (const method of this.#methods) {
|
||||||
out += method.generateTypedef();
|
out += method.generateTypedef();
|
||||||
out += `extern ${method.generateDefinition()}`;
|
out += `extern ${method.generateDefinition()}`;
|
||||||
|
out += method.generateNewMethodTest(this.#directParent, '', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// VTable
|
// VTable
|
||||||
if (this.#vtable !== null) {
|
if (this.#vtable !== null) {
|
||||||
out += this.#vtable.generate();
|
out += this.#vtable.generate(this.#directParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Structure
|
// Structure
|
||||||
@ -294,4 +307,18 @@ export class Struct {
|
|||||||
// Return
|
// Return
|
||||||
return {functions: declarations, init};
|
return {functions: declarations, init};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Method Symbols
|
||||||
|
getMethodSymbols() {
|
||||||
|
const ret = [];
|
||||||
|
for (const method of this.#methods) {
|
||||||
|
ret.push(method.getName());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Direct Parent (Used For "New Method" Testing)
|
||||||
|
setDirectParent(directParent: string) {
|
||||||
|
this.#directParent = directParent;
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ export class VTable implements Property {
|
|||||||
readonly #methods: Method[];
|
readonly #methods: Method[];
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor(name: string) {
|
constructor(name: string, destructorOffset: number) {
|
||||||
this.#name = name;
|
this.#name = name;
|
||||||
this.#address = null;
|
this.#address = null;
|
||||||
this.#size = new Size(true);
|
this.#size = new Size(true);
|
||||||
@ -17,8 +17,8 @@ export class VTable implements Property {
|
|||||||
// Add Destructors (https://stackoverflow.com/a/17960941)
|
// Add Destructors (https://stackoverflow.com/a/17960941)
|
||||||
const destructor_return = `${name} *`;
|
const destructor_return = `${name} *`;
|
||||||
const destructor_args = `(${getSelfArg(name)})`;
|
const destructor_args = `(${getSelfArg(name)})`;
|
||||||
this.add(new Method(name, 'destructor_complete', destructor_return, destructor_args, 0x0));
|
this.add(new Method(name, 'destructor_complete', destructor_return, destructor_args, 0x0 + destructorOffset, false));
|
||||||
this.add(new Method(name, 'destructor_deleting', destructor_return, destructor_args, 0x4));
|
this.add(new Method(name, 'destructor_deleting', destructor_return, destructor_args, 0x4 + destructorOffset, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Property Information
|
// Property Information
|
||||||
@ -82,7 +82,7 @@ export class VTable implements Property {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate Code
|
// Generate Code
|
||||||
generate() {
|
generate(directParent: string | null) {
|
||||||
let out = '';
|
let out = '';
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
@ -126,7 +126,7 @@ export class VTable implements Property {
|
|||||||
if (info) {
|
if (info) {
|
||||||
const type = `${info.getType()} *`;
|
const type = `${info.getType()} *`;
|
||||||
out += `extern ${type}${info.getName()}_vtable_addr;\n`;
|
out += `extern ${type}${info.getName()}_vtable_addr;\n`;
|
||||||
out += `extern ${info.generateDefinition('_non_virtual')}`;
|
out += info.generateNewMethodTest(directParent, '*', '_vtable_addr');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,8 +161,6 @@ export class VTable implements Property {
|
|||||||
const type = `${info.getType()} *`;
|
const type = `${info.getType()} *`;
|
||||||
init += `${INDENT}${info.getName()}_vtable_addr = (${type}) ${toHex(vtableAddress)};\n`;
|
init += `${INDENT}${info.getName()}_vtable_addr = (${type}) ${toHex(vtableAddress)};\n`;
|
||||||
declarations += `${type}${info.getName()}_vtable_addr;\n`;
|
declarations += `${type}${info.getName()}_vtable_addr;\n`;
|
||||||
init += `${INDENT}${info.getName()}_non_virtual = *${info.getName()}_vtable_addr;\n`;
|
|
||||||
declarations += info.generateDefinition('_non_virtual');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ syntax def "\.def$"
|
|||||||
comment "//"
|
comment "//"
|
||||||
|
|
||||||
# Commands
|
# Commands
|
||||||
color magenta "\<(extends|size|vtable(-size)?|property|static-property(-array)?|((static|virtual)-)?method|constructor)\>"
|
color magenta "\<(extends|size|vtable(-size|-destructor-offset)?|property|static-property(-array)?|((static|virtual)-)?method|constructor)\>"
|
||||||
|
|
||||||
# Types
|
# Types
|
||||||
color green "\<(char|uchar|short|ushort|int|uint|float|bool|void|std::(string|vector|map))\>"
|
color green "\<(char|uchar|short|ushort|int|uint|float|bool|void|std::(string|vector|map))\>"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
<item>virtual-method</item>
|
<item>virtual-method</item>
|
||||||
<item>static-method</item>
|
<item>static-method</item>
|
||||||
<item>constructor</item>
|
<item>constructor</item>
|
||||||
|
<item>vtable-destructor-offset</item>
|
||||||
</list>
|
</list>
|
||||||
<list name="types">
|
<list name="types">
|
||||||
<item>char</item>
|
<item>char</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user