diff --git a/src/common.ts b/src/common.ts index 7915320..a35a088 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,4 +1,5 @@ import * as fs from 'node:fs'; +import { isCppAllowed } from './map'; export const INDENT = ' '; export const POINTER_SIZE = 4; @@ -49,4 +50,24 @@ export function formatType(type: string) { } return type; } -export const COMMENT = '//'; \ No newline at end of file +export const COMMENT = '//'; +export function toHex(x: number) { + return '0x' + x.toString(16); +} +export function getAssertFunction() { + return isCppAllowed() ? 'static_assert' : '_Static_assert'; +} +export function assertSize(name: string, size: number, isDefined: boolean) { + let out = ''; + // Define Size Macro + const macro = toUpperSnakeCase(name) + '_SIZE'; + out += `#define ${macro} ${toHex(size)}\n`; + // Check Size + out += `${getAssertFunction()}(sizeof (${name}) == ${macro}, "Invalid Size");\n`; + // Hide Structure Size Of The Real Size Is Unknown + if (!isDefined) { + out += `#undef ${macro}\n`; + } + // Return + return out; +} \ No newline at end of file diff --git a/src/struct.ts b/src/struct.ts index 87b0e26..ff2cc92 100644 --- a/src/struct.ts +++ b/src/struct.ts @@ -1,5 +1,4 @@ -import { INDENT, MIN_SIZE, toUpperSnakeCase, formatType, STRUCTURE_FILES } from './common'; -import { isCppAllowed } from './map'; +import { INDENT, MIN_SIZE, formatType, STRUCTURE_FILES, toHex, getAssertFunction, assertSize } from './common'; import { Method } from './method'; import { Property, StaticProperty } from './property'; import { VTable } from './vtable'; @@ -221,25 +220,21 @@ export class Struct { out += `};\n`; // Sanity Check Offsets - const assertFunction = isCppAllowed() ? 'static_assert' : '_Static_assert'; + const assertFunction = getAssertFunction(); for (let i = 0; i < this.#properties.length; i++) { const property = this.#properties[i]!; const name = property.propertyName(); const offset = property.propertyOffset(); - out += `${assertFunction}(offsetof(${this.#name}, ${name}) == ${offset}, "Invalid Offset");\n`; + out += `${assertFunction}(offsetof(${this.#name}, ${name}) == ${toHex(offset)}, "Invalid Offset");\n`; } // Sanity Check Size const size = this.getSize(); - out += `#define ${toUpperSnakeCase(this.#name)}_SIZE ${size}\n`; - out += `${assertFunction}(sizeof (${this.#name}) == ${toUpperSnakeCase(this.#name)}_SIZE, "Invalid Structure Size");\n`; - if (this.#size === null) { - // Hide Structure Size As The Real Size Is Unknown - out += `#undef ${toUpperSnakeCase(this.#name)}_SIZE\n`; - } + const isSizeDefined = this.#size !== null; + out += assertSize(this.#name, size, isSizeDefined); // Allocation Function - if (this.#size !== null) { + if (isSizeDefined) { out += `${this.#name} *alloc_${this.#name}();\n`; } @@ -257,13 +252,13 @@ export class Struct { // Static Properties for (const property of this.#staticProperties) { - init += `${INDENT}${property.getName()} = (${property.getType()}) ${property.address};\n`; + init += `${INDENT}${property.getName()} = (${property.getType()}) ${toHex(property.address)};\n`; declarations += property.generateDefinition(); } // Methods for (const method of this.#methods) { - init += `${INDENT}${method.getName()} = (${method.getType()}) ${method.address};\n`; + init += `${INDENT}${method.getName()} = (${method.getType()}) ${toHex(method.address)};\n`; declarations += method.generateDefinition(); } @@ -277,7 +272,7 @@ export class Struct { // Allocation Function if (this.#size !== null) { declarations += `${this.#name} *alloc_${this.#name}() {\n`; - declarations += `${INDENT}return (${this.#name} *) ::operator new(${this.#size});\n`; + declarations += `${INDENT}return new ${this.#name};\n`; declarations += '}\n'; } diff --git a/src/vtable.ts b/src/vtable.ts index aaecf71..f0889d4 100644 --- a/src/vtable.ts +++ b/src/vtable.ts @@ -1,4 +1,4 @@ -import { INDENT, POINTER_SIZE } from './common'; +import { INDENT, POINTER_SIZE, assertSize, toHex } from './common'; import { Method } from './method'; import { Property } from './property'; @@ -107,6 +107,11 @@ export class VTable implements Property { } out += `};\n`; + // Sanity Check Size + const isSizeDefined = this.#size !== null; + const size = isSizeDefined ? this.#size! : (this.#methods.length * POINTER_SIZE); + out += assertSize(this.#getName(), size, isSizeDefined); + // Pointers if (this.#address !== null) { // Base @@ -123,7 +128,7 @@ export class VTable implements Property { } // Duplication Method - if (this.#size !== null) { + if (isSizeDefined) { out += `${this.#getName()} *dup_${this.#getName()}(${this.#getName()} *vtable);\n`; } @@ -142,7 +147,7 @@ export class VTable implements Property { // Pointers if (this.#address !== null) { // Base - init += `${INDENT}${this.#getName()}_base = (${this.#getName()} *) ${this.#address};\n`; + init += `${INDENT}${this.#getName()}_base = (${this.#getName()} *) ${toHex(this.#address)};\n`; declarations += `${this.#getName()} *${this.#getName()}_base;\n`; // Methods for (let i = 0; i < this.#methods.length; i++) { @@ -150,7 +155,7 @@ export class VTable implements Property { if (info) { const vtableAddress = this.#address + (i * POINTER_SIZE); const type = `${info.getType()} *`; - init += `${INDENT}${info.getName()}_vtable_addr = (${type}) ${vtableAddress};\n`; + init += `${INDENT}${info.getName()}_vtable_addr = (${type}) ${toHex(vtableAddress)};\n`; declarations += `${type}${info.getName()}_vtable_addr;\n`; init += `${INDENT}${info.getName()}_non_virtual = *${info.getName()}_vtable_addr;\n`; declarations += info.generateDefinition(); @@ -161,11 +166,11 @@ export class VTable implements Property { // Duplication Method if (this.#size !== null) { declarations += `${this.#getName()} *dup_${this.#getName()}(${this.#getName()} *vtable) {\n`; - declarations += `${INDENT}${this.#getName()} *obj = (${this.#getName()} *) malloc(${this.#size});\n`; + declarations += `${INDENT}${this.#getName()} *obj = new ${this.#getName()};\n`; declarations += `${INDENT}if (obj == NULL) {\n`; declarations += `${INDENT}${INDENT}return NULL;\n`; declarations += `${INDENT}}\n`; - declarations += `${INDENT}memcpy((void *) obj, (void *) vtable, ${this.#size});\n`; + declarations += `${INDENT}memcpy((void *) obj, (void *) vtable, sizeof (${this.#getName()});\n`; declarations += `${INDENT}return obj;\n`; declarations += '}\n'; }