Better Static Properties
This commit is contained in:
parent
603010e3cc
commit
fbb9b6d6da
@ -66,14 +66,7 @@ export function toHex(x: number) {
|
||||
return '0x' + x.toString(16);
|
||||
}
|
||||
export function assertSize(name: string, size: number) {
|
||||
let out = '';
|
||||
// Define Size Macro
|
||||
const macro = toUpperSnakeCase(name) + '_SIZE';
|
||||
out += `#define ${macro} ${toHex(size)}\n`;
|
||||
// Check Size
|
||||
out += `static_assert(sizeof(${name}) == ${macro}, "Invalid Size");\n`;
|
||||
// Return
|
||||
return out;
|
||||
return `static_assert(sizeof(${name}) == ${toHex(size)}, "Invalid Size");\n`;
|
||||
}
|
||||
export function safeParseInt(str: string) {
|
||||
const x = parseInt(str);
|
||||
|
20
src/index.ts
20
src/index.ts
@ -1,5 +1,5 @@
|
||||
import * as fs from 'node:fs';
|
||||
import { STRUCTURE_FILES, EXTENSION, INDENT } from './common';
|
||||
import { STRUCTURE_FILES, EXTENSION } from './common';
|
||||
import { getStructure } from './map';
|
||||
import { Struct } from './struct';
|
||||
|
||||
@ -130,11 +130,7 @@ function makeHeaderPart() {
|
||||
}
|
||||
|
||||
// Return
|
||||
let result = '';
|
||||
result += '// Init\n';
|
||||
result += 'void init_symbols();\n\n';
|
||||
result += structures;
|
||||
return result;
|
||||
return structures;
|
||||
}
|
||||
|
||||
// Create Main Header
|
||||
@ -180,7 +176,6 @@ function makeCompiledCode(output: string) {
|
||||
|
||||
// Generate
|
||||
let declarations = '';
|
||||
let init = '';
|
||||
let isFirst = true;
|
||||
for (const structure of structureObjects) {
|
||||
const name = structure.getName();
|
||||
@ -188,14 +183,11 @@ function makeCompiledCode(output: string) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
declarations += '\n';
|
||||
init += '\n';
|
||||
}
|
||||
declarations += `// ${name}\n`;
|
||||
init += `${INDENT}// ${name}\n`;
|
||||
try {
|
||||
const code = structure.generateCode();
|
||||
declarations += code.functions;
|
||||
init += code.init;
|
||||
declarations += code;
|
||||
} catch (e) {
|
||||
console.log(`Error Generating Code: ${name}: ${e instanceof Error ? e.stack : e}`);
|
||||
process.exit(1);
|
||||
@ -205,11 +197,7 @@ function makeCompiledCode(output: string) {
|
||||
// Write
|
||||
let result = '';
|
||||
result += `#include "${fs.realpathSync(headerOutput)}"\n`;
|
||||
result += '\n#include <cstring>\n';
|
||||
result += '\n// Init\n';
|
||||
result += 'void init_symbols() {\n';
|
||||
result += init;
|
||||
result += '}\n\n';
|
||||
result += '\n#include <cstring>\n\n';
|
||||
result += declarations;
|
||||
fs.writeFileSync(output, result);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ export class Method {
|
||||
|
||||
// Generate Variable Definition
|
||||
generateDefinition(nameSuffix?: string) {
|
||||
return `${this.getType()} ${this.getName()}${nameSuffix !== undefined ? nameSuffix : ''};\n`;
|
||||
return `${this.getType()} ${this.getName()}${nameSuffix !== undefined ? nameSuffix : ''}`;
|
||||
}
|
||||
|
||||
// Generate "New Method" Test
|
||||
|
@ -34,8 +34,14 @@ export class Property {
|
||||
}
|
||||
return name;
|
||||
}
|
||||
#fullName(separator: string) {
|
||||
return this.#self + separator + this.name();
|
||||
}
|
||||
fullName() {
|
||||
return `${this.#self}_${this.name()}`;
|
||||
return this.#fullName('_');
|
||||
}
|
||||
prettyName() {
|
||||
return this.#fullName('::');
|
||||
}
|
||||
rawType() {
|
||||
return this.#type;
|
||||
@ -48,13 +54,8 @@ export class StaticProperty extends Property {
|
||||
super(address, type, name, self);
|
||||
}
|
||||
|
||||
// Generate Variable Definition
|
||||
globalPointerDefinition() {
|
||||
return `${this.type()} *${this.fullName()}_pointer;\n`;
|
||||
}
|
||||
|
||||
// Generate Macro
|
||||
macro() {
|
||||
return `#define ${this.fullName()} (*${this.fullName()}_pointer)\n`;
|
||||
// Reference
|
||||
referenceDefinition(addSelf: boolean) {
|
||||
return `${this.type()} &${addSelf ? this.prettyName() : this.name()}`;
|
||||
}
|
||||
}
|
@ -193,16 +193,14 @@ export class Struct {
|
||||
// Static Properties
|
||||
for (const property of this.#staticProperties) {
|
||||
out += property.typedef();
|
||||
out += `extern ${property.globalPointerDefinition()}`;
|
||||
out += property.macro();
|
||||
}
|
||||
|
||||
// Methods
|
||||
for (const method of this.#methods) {
|
||||
if (!method.isInherited) {
|
||||
out += method.generateTypedef();
|
||||
out += `extern ${method.generateDefinition()}`;
|
||||
out += `extern ${method.generateDefinition(ORIGINAL_SUFFIX)}`;
|
||||
out += `extern ${method.generateDefinition()};\n`;
|
||||
out += `extern ${method.generateDefinition(ORIGINAL_SUFFIX)};\n`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,6 +218,10 @@ export class Struct {
|
||||
out += `struct ${this.#name} {\n`;
|
||||
out += this.#generateProperties();
|
||||
out += this.#generateMethods();
|
||||
for (const property of this.#staticProperties) {
|
||||
// Static Property References
|
||||
out += `${INDENT}static ${property.referenceDefinition(false)};\n`;
|
||||
}
|
||||
if (this.#size === null) {
|
||||
// Prevent Manually Copying/Allocating Structure With Undefined
|
||||
out += `${INDENT}${this.#name}() = delete;\n`;
|
||||
@ -247,34 +249,29 @@ export class Struct {
|
||||
|
||||
// Generate Compiled Code
|
||||
generateCode() {
|
||||
let declarations = '';
|
||||
let init = '';
|
||||
let out = '';
|
||||
|
||||
// Static Properties
|
||||
for (const property of this.#staticProperties) {
|
||||
init += `${INDENT}${property.fullName()}_pointer = (${property.type()} *) ${toHex(property.offset)};\n`;
|
||||
declarations += property.globalPointerDefinition();
|
||||
out += `${property.referenceDefinition(true)} = *(${property.type()} *) ${toHex(property.offset)};\n`;
|
||||
}
|
||||
|
||||
// Methods
|
||||
for (const method of this.#methods) {
|
||||
if (!method.isInherited) {
|
||||
init += `${INDENT}${method.getName()} = (${method.getType()}) ${toHex(method.address)};\n`;
|
||||
declarations += method.generateDefinition();
|
||||
init += `${INDENT}${method.getName()}${ORIGINAL_SUFFIX} = ${method.getName()};\n`;
|
||||
declarations += method.generateDefinition(ORIGINAL_SUFFIX);
|
||||
out += `${method.generateDefinition()} = (${method.getType()}) ${toHex(method.address)};\n`;
|
||||
out += `${method.generateDefinition(ORIGINAL_SUFFIX)} = ${method.getName()};\n`;
|
||||
}
|
||||
}
|
||||
|
||||
// VTable
|
||||
if (this.#vtable !== null) {
|
||||
const vtable = this.#vtable.generateCode();
|
||||
declarations += vtable.declarations;
|
||||
init += vtable.init;
|
||||
out += vtable;
|
||||
}
|
||||
|
||||
// Return
|
||||
return {functions: declarations, init};
|
||||
return out;
|
||||
}
|
||||
|
||||
// Set Direct Parent (Used For "New Method" Testing)
|
||||
|
@ -133,7 +133,7 @@ export class VTable {
|
||||
const pointerType = `${type} *`;
|
||||
out += `extern ${pointerType}${name}_vtable_addr;\n`;
|
||||
out += info.generateNewMethodTest(directParent, '*', '_vtable_addr');
|
||||
out += `extern ${info.generateDefinition(ORIGINAL_SUFFIX)}`;
|
||||
out += `extern ${info.generateDefinition(ORIGINAL_SUFFIX)};\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,8 +149,7 @@ export class VTable {
|
||||
|
||||
// Generate Compiled Code
|
||||
generateCode() {
|
||||
let declarations = '';
|
||||
let init = '';
|
||||
let out = '';
|
||||
|
||||
// Check
|
||||
this.#check();
|
||||
@ -158,8 +157,7 @@ export class VTable {
|
||||
// Pointers
|
||||
if (this.#address !== null) {
|
||||
// Base
|
||||
init += `${INDENT}${this.#getName()}_base = (${this.#getName()} *) ${toHex(this.#address)};\n`;
|
||||
declarations += `${this.#getName()} *${this.#getName()}_base;\n`;
|
||||
out += `${this.#getName()} *${this.#getName()}_base = (${this.#getName()} *) ${toHex(this.#address)};\n`;
|
||||
// Methods
|
||||
const methods = this.getMethods();
|
||||
for (let i = 0; i < methods.length; i++) {
|
||||
@ -169,31 +167,29 @@ export class VTable {
|
||||
const name = info.getName();
|
||||
const type = info.getType();
|
||||
const pointerType = `${type} *`;
|
||||
init += `${INDENT}${name}_vtable_addr = (${pointerType}) ${toHex(vtableAddress)};\n`;
|
||||
declarations += `${pointerType}${name}_vtable_addr;\n`;
|
||||
init += `${INDENT}${name}${ORIGINAL_SUFFIX} = *${name}_vtable_addr;\n`;
|
||||
declarations += info.generateDefinition(ORIGINAL_SUFFIX);
|
||||
out += `${pointerType}${name}_vtable_addr = (${pointerType}) ${toHex(vtableAddress)};\n`;
|
||||
out += `${info.generateDefinition(ORIGINAL_SUFFIX)} = *${name}_vtable_addr;\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Duplication Method
|
||||
if (this.#size !== null) {
|
||||
declarations += `${this.#getName()} *dup_${this.#getName()}(${this.#getName()} *vtable) {\n`;
|
||||
declarations += `${INDENT}uchar *real_vtable = (uchar *) vtable;\n`;
|
||||
declarations += `${INDENT}real_vtable -= ${RTTI_SIZE};\n`;
|
||||
declarations += `${INDENT}size_t real_vtable_size = sizeof(${this.#getName()}) + ${RTTI_SIZE};\n`;
|
||||
declarations += `${INDENT}uchar *new_vtable = (uchar *) ::operator new(real_vtable_size);\n`;
|
||||
declarations += `${INDENT}if (new_vtable == NULL) {\n`;
|
||||
declarations += `${INDENT}${INDENT}return NULL;\n`;
|
||||
declarations += `${INDENT}}\n`;
|
||||
declarations += `${INDENT}memcpy((void *) new_vtable, (void *) real_vtable, real_vtable_size);\n`;
|
||||
declarations += `${INDENT}new_vtable += ${RTTI_SIZE};\n`;
|
||||
declarations += `${INDENT}return (${this.#getName()} *) new_vtable;\n`;
|
||||
declarations += '}\n';
|
||||
out += `${this.#getName()} *dup_${this.#getName()}(${this.#getName()} *vtable) {\n`;
|
||||
out += `${INDENT}uchar *real_vtable = (uchar *) vtable;\n`;
|
||||
out += `${INDENT}real_vtable -= ${RTTI_SIZE};\n`;
|
||||
out += `${INDENT}size_t real_vtable_size = sizeof(${this.#getName()}) + ${RTTI_SIZE};\n`;
|
||||
out += `${INDENT}uchar *new_vtable = (uchar *) ::operator new(real_vtable_size);\n`;
|
||||
out += `${INDENT}if (new_vtable == NULL) {\n`;
|
||||
out += `${INDENT}${INDENT}return NULL;\n`;
|
||||
out += `${INDENT}}\n`;
|
||||
out += `${INDENT}memcpy((void *) new_vtable, (void *) real_vtable, real_vtable_size);\n`;
|
||||
out += `${INDENT}new_vtable += ${RTTI_SIZE};\n`;
|
||||
out += `${INDENT}return (${this.#getName()} *) new_vtable;\n`;
|
||||
out += '}\n';
|
||||
}
|
||||
|
||||
// Return
|
||||
return {declarations, init};
|
||||
return out;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user