Auto-Generate Custom Wrappers
This commit is contained in:
parent
fd720d2321
commit
4018ff0fb9
94
data/custom.h
Normal file
94
data/custom.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// Get Custom Data
|
||||||
|
template <typename Data>
|
||||||
|
Data *custom_get(typename Data::__Self *self) {
|
||||||
|
return (Data *) (self + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicate VTable
|
||||||
|
template <typename T>
|
||||||
|
T *__dup_vtable(const T *vtable) {
|
||||||
|
// Get Size
|
||||||
|
constexpr size_t rtti_size = sizeof(void *);
|
||||||
|
const unsigned char *const real_vtable = ((const unsigned char *) vtable) - rtti_size;
|
||||||
|
constexpr size_t real_vtable_size = sizeof(T) + rtti_size;
|
||||||
|
// Allocate
|
||||||
|
unsigned char *const new_vtable = (unsigned char *) ::operator new(real_vtable_size);
|
||||||
|
T *ret = (T *) (new_vtable + rtti_size);
|
||||||
|
new (ret) T;
|
||||||
|
// Copy
|
||||||
|
memcpy(new_vtable, real_vtable, real_vtable_size);
|
||||||
|
// Return
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base
|
||||||
|
template <typename A, typename B>
|
||||||
|
struct __CustomBase {
|
||||||
|
// Properties
|
||||||
|
typedef A __Self;
|
||||||
|
typedef B __VTable;
|
||||||
|
__Self *const self;
|
||||||
|
|
||||||
|
// Prevent Copying
|
||||||
|
__PREVENT_COPY(__CustomBase);
|
||||||
|
|
||||||
|
#define get_self(ptr) (((__Self *) ptr) - 1)
|
||||||
|
#ifdef {{ BUILDING_SYMBOLS_GUARD }}
|
||||||
|
// Constructor
|
||||||
|
__CustomBase():
|
||||||
|
self(get_self(this)) {}
|
||||||
|
#else
|
||||||
|
// Prevent Construction
|
||||||
|
__PREVENT_JUST_CONSTRUCTION(__CustomBase);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
virtual ~__CustomBase() = default;
|
||||||
|
|
||||||
|
// Allocation
|
||||||
|
void *operator new(const size_t count) {
|
||||||
|
const size_t size = sizeof(__Self) + count;
|
||||||
|
__Self *out = (__Self *) ::operator new(size);
|
||||||
|
return (void *) custom_get<__CustomBase>(out);
|
||||||
|
}
|
||||||
|
void *operator new[](size_t) = delete;
|
||||||
|
|
||||||
|
// Deallocation
|
||||||
|
void operator delete(__CustomBase *ptr, std::destroying_delete_t) {
|
||||||
|
if (ptr) {
|
||||||
|
__Self *self = ptr->self;
|
||||||
|
// This Calls The Actual Destructor
|
||||||
|
self->vtable->destructor_deleting(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void operator delete(void *ptr) {
|
||||||
|
if (ptr) {
|
||||||
|
// Issue During Construction, Just Free Memory
|
||||||
|
::operator delete(get_self(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef get_self
|
||||||
|
void operator delete[](void *) = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// VTable
|
||||||
|
virtual void __patch_vtable(__VTable *vtable) {
|
||||||
|
// Patch Destructors
|
||||||
|
#define patch(type) \
|
||||||
|
vtable->type = [](__Self *self) { \
|
||||||
|
custom_get<__CustomBase>(self)->~__CustomBase(); \
|
||||||
|
return __VTable::base->type(self); \
|
||||||
|
}
|
||||||
|
patch(destructor_complete);
|
||||||
|
patch(destructor_deleting);
|
||||||
|
#undef patch
|
||||||
|
}
|
||||||
|
void __set_vtable() {
|
||||||
|
static __VTable *vtable = nullptr;
|
||||||
|
if (!vtable) {
|
||||||
|
vtable = __dup_vtable(__VTable::base);
|
||||||
|
__patch_vtable(vtable);
|
||||||
|
}
|
||||||
|
this->self->vtable = vtable;
|
||||||
|
}
|
||||||
|
};
|
@ -65,5 +65,6 @@ public:
|
|||||||
|
|
||||||
// Disable Warnings
|
// Disable Warnings
|
||||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||||
|
#pragma GCC diagnostic ignored "-Wshadow"
|
||||||
|
|
||||||
{{ main }}
|
{{ main }}
|
11
data/out.h
11
data/out.h
@ -21,6 +21,13 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
// Warnings
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wshadow"
|
||||||
|
|
||||||
|
// Custom Wrappers
|
||||||
|
{{ include custom.h }}
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
typedef unsigned char uchar;
|
typedef unsigned char uchar;
|
||||||
typedef unsigned short ushort;
|
typedef unsigned short ushort;
|
||||||
@ -32,10 +39,6 @@ typedef unsigned int uint;
|
|||||||
// Extra Headers
|
// Extra Headers
|
||||||
{{ extraHeaders }}
|
{{ extraHeaders }}
|
||||||
|
|
||||||
// Warnings
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wshadow"
|
|
||||||
|
|
||||||
{{ main }}
|
{{ main }}
|
||||||
|
|
||||||
// Cleanup Warnings
|
// Cleanup Warnings
|
||||||
|
@ -10,6 +10,8 @@ export const STRUCTURE_FILES: Record<string, string> = {};
|
|||||||
export const COMMENT = '//';
|
export const COMMENT = '//';
|
||||||
export const INTERNAL = '__';
|
export const INTERNAL = '__';
|
||||||
export const BUILDING_SYMBOLS_GUARD = 'BUILDING_SYMBOLS_LIB';
|
export const BUILDING_SYMBOLS_GUARD = 'BUILDING_SYMBOLS_LIB';
|
||||||
|
export const CONSTRUCTOR_FUNCTION_NAME = 'constructor';
|
||||||
|
export const SELF_ARG = 'self';
|
||||||
// Read Definition File
|
// Read Definition File
|
||||||
export function readDefinition(name: string) {
|
export function readDefinition(name: string) {
|
||||||
if (!STRUCTURE_FILES[name]) {
|
if (!STRUCTURE_FILES[name]) {
|
||||||
@ -115,7 +117,7 @@ export function safeParseInt(str: string) {
|
|||||||
}
|
}
|
||||||
// Generate "Self" Argument For Functions
|
// Generate "Self" Argument For Functions
|
||||||
export function getSelfArg(type: string) {
|
export function getSelfArg(type: string) {
|
||||||
return `${type} *self`;
|
return type + ' *' + SELF_ARG;
|
||||||
}
|
}
|
||||||
// Prepend Argument To Function
|
// Prepend Argument To Function
|
||||||
export function prependArg(args: string, arg: string) {
|
export function prependArg(args: string, arg: string) {
|
||||||
|
128
src/custom.ts
Normal file
128
src/custom.ts
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import { CONSTRUCTOR_FUNCTION_NAME, formatType, forwardArguments, INDENT, INTERNAL, SELF_ARG } from './common';
|
||||||
|
import { Struct } from './struct';
|
||||||
|
import { structuresWithVTableAddress } from './vtable';
|
||||||
|
|
||||||
|
// Allow Making Custom Structures
|
||||||
|
export class CustomWrapperGenerator {
|
||||||
|
readonly #struct: Struct;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
constructor(struct: Struct) {
|
||||||
|
this.#struct = struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter
|
||||||
|
#getBase() {
|
||||||
|
return `${INTERNAL}CustomBase<${this.#struct.name}, ${this.#struct.getVTable().getName()}>`;
|
||||||
|
}
|
||||||
|
#getMethods() {
|
||||||
|
const out = [];
|
||||||
|
out.push(this.#struct.getMainConstructor());
|
||||||
|
const methods = this.#struct.getVTable().getMethods(false);
|
||||||
|
for (const method of methods) {
|
||||||
|
if (method) {
|
||||||
|
out.push(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#getName() {
|
||||||
|
return 'Custom' + this.#struct.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Header
|
||||||
|
generate() {
|
||||||
|
let out = '';
|
||||||
|
|
||||||
|
// Check
|
||||||
|
if (!structuresWithVTableAddress.includes(this.#struct.name)) {
|
||||||
|
throw new Error('Generating A Custom Wrapper Requires The VTable Address To Be Specified');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structure
|
||||||
|
const base = this.#getBase();
|
||||||
|
out += `struct ${this.#getName()} : ${base} {\n`;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const methods = this.#getMethods();
|
||||||
|
for (const method of methods) {
|
||||||
|
// Generate Method
|
||||||
|
const name = method.shortName;
|
||||||
|
out += INDENT;
|
||||||
|
if (name === CONSTRUCTOR_FUNCTION_NAME) {
|
||||||
|
out += 'explicit ' + this.#getName();
|
||||||
|
} else {
|
||||||
|
out += 'virtual ' + formatType(method.returnType) + name;
|
||||||
|
}
|
||||||
|
out += method.getArgs(false) + ';\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// VTable
|
||||||
|
out += 'private:\n';
|
||||||
|
out += INDENT + `virtual void ${INTERNAL}patch_vtable(${base}::${INTERNAL}VTable *) override;\n`;
|
||||||
|
out += '};\n';
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Code
|
||||||
|
generateCode() {
|
||||||
|
let out = '';
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const methods = this.#getMethods();
|
||||||
|
for (const method of methods) {
|
||||||
|
const name = method.shortName;
|
||||||
|
const isConstructor = name === CONSTRUCTOR_FUNCTION_NAME;
|
||||||
|
// Generate Method
|
||||||
|
if (!isConstructor) {
|
||||||
|
out += formatType(method.returnType);
|
||||||
|
}
|
||||||
|
out += this.#getName() + '::';
|
||||||
|
out += isConstructor ? this.#getName() : name;
|
||||||
|
const args = method.getArgs(false);
|
||||||
|
out += args + ' {\n';
|
||||||
|
out += INDENT;
|
||||||
|
const forwardedArgs = forwardArguments(args, ['this->self']);
|
||||||
|
if (!isConstructor) {
|
||||||
|
// Virtual Method
|
||||||
|
if (method.doesReturnValue()) {
|
||||||
|
out += 'return ';
|
||||||
|
}
|
||||||
|
out += `${INTERNAL}VTable::base->${name}${forwardedArgs}`;
|
||||||
|
} else {
|
||||||
|
// Constructor
|
||||||
|
out += method.getDirectCall() + forwardedArgs;
|
||||||
|
}
|
||||||
|
out += ';\n';
|
||||||
|
if (isConstructor) {
|
||||||
|
out += `${INDENT}${INTERNAL}set_vtable();\n`;
|
||||||
|
}
|
||||||
|
out += '}\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// VTable
|
||||||
|
const base = this.#getBase();
|
||||||
|
out += `void ${this.#getName()}::${INTERNAL}patch_vtable(${base}::${INTERNAL}VTable *vtable) {\n`;
|
||||||
|
out += `${INDENT}${base}::${INTERNAL}patch_vtable(vtable);\n`;
|
||||||
|
for (const method of methods) {
|
||||||
|
const name = method.shortName;
|
||||||
|
if (name === CONSTRUCTOR_FUNCTION_NAME) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Patch Entry
|
||||||
|
out += `${INDENT}vtable->${name} = []${method.getArgs()} {\n`;
|
||||||
|
out += INDENT + INDENT;
|
||||||
|
if (method.doesReturnValue()) {
|
||||||
|
out += 'return ';
|
||||||
|
}
|
||||||
|
out += `custom_get<${this.#getName()}>(${SELF_ARG})->${name}${forwardArguments(method.getArgs(false), [])};\n`;
|
||||||
|
out += INDENT + '};\n';
|
||||||
|
}
|
||||||
|
out += '}\n';
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import { COMMENT, extendErrorMessage, EXTENSION, parseTypeAndName, readDefinition, safeParseInt, syntaxError } from './common';
|
import { COMMENT, CONSTRUCTOR_FUNCTION_NAME, extendErrorMessage, EXTENSION, parseTypeAndName, readDefinition, safeParseInt, syntaxError } from './common';
|
||||||
import { Method } from './method';
|
import { Method } from './method';
|
||||||
import { Property, StaticProperty } from './property';
|
import { Property, StaticProperty } from './property';
|
||||||
import { Struct } from './struct';
|
import { Struct } from './struct';
|
||||||
@ -166,7 +166,7 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
|||||||
case 'constructor': {
|
case 'constructor': {
|
||||||
// Constructor
|
// Constructor
|
||||||
if (!isExtended) {
|
if (!isExtended) {
|
||||||
let data = `${target.name} *constructor`;
|
let data = target.name + ' *' + CONSTRUCTOR_FUNCTION_NAME;
|
||||||
if (args.startsWith('(')) {
|
if (args.startsWith('(')) {
|
||||||
// No Custom Name
|
// No Custom Name
|
||||||
} else {
|
} else {
|
||||||
@ -192,6 +192,13 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
|||||||
target.markAsSimple();
|
target.markAsSimple();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'generate-custom-wrapper': {
|
||||||
|
// Custom Wrapper
|
||||||
|
if (!isExtended) {
|
||||||
|
target.enableCustomWrapper();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new Error(`Invalid Command: ${command}`);
|
throw new Error(`Invalid Command: ${command}`);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,9 @@ export class Method {
|
|||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
getDirectCall() {
|
||||||
|
return this.getName() + '->get(false)';
|
||||||
|
}
|
||||||
|
|
||||||
// Typedefs
|
// Typedefs
|
||||||
generateTypedefs() {
|
generateTypedefs() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { INDENT, STRUCTURE_FILES, toHex, assertSize, INTERNAL, preventConstruction, BUILDING_SYMBOLS_GUARD, formatType, forwardArguments } from './common';
|
import { INDENT, STRUCTURE_FILES, toHex, assertSize, INTERNAL, preventConstruction, BUILDING_SYMBOLS_GUARD, formatType, forwardArguments, CONSTRUCTOR_FUNCTION_NAME } from './common';
|
||||||
|
import { CustomWrapperGenerator } from './custom';
|
||||||
import { Method } from './method';
|
import { Method } from './method';
|
||||||
import { Property, StaticProperty } from './property';
|
import { Property, StaticProperty } from './property';
|
||||||
import { VTable } from './vtable';
|
import { VTable } from './vtable';
|
||||||
@ -14,6 +15,7 @@ export class Struct {
|
|||||||
readonly #staticProperties: StaticProperty[];
|
readonly #staticProperties: StaticProperty[];
|
||||||
#directParent: string | null;
|
#directParent: string | null;
|
||||||
#isSimple: boolean;
|
#isSimple: boolean;
|
||||||
|
#custom: CustomWrapperGenerator | null;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
@ -26,6 +28,7 @@ export class Struct {
|
|||||||
this.#staticProperties = [];
|
this.#staticProperties = [];
|
||||||
this.#directParent = null;
|
this.#directParent = null;
|
||||||
this.#isSimple = false;
|
this.#isSimple = false;
|
||||||
|
this.#custom = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
@ -98,6 +101,20 @@ export class Struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "Custom" Wrapper
|
||||||
|
enableCustomWrapper() {
|
||||||
|
this.getVTable();
|
||||||
|
this.#custom = new CustomWrapperGenerator(this);
|
||||||
|
}
|
||||||
|
getMainConstructor() {
|
||||||
|
for (const method of this.#methods) {
|
||||||
|
if (method.shortName === CONSTRUCTOR_FUNCTION_NAME) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Unable To Find Main Constructor');
|
||||||
|
}
|
||||||
|
|
||||||
// Generate Properties
|
// Generate Properties
|
||||||
#generateProperties() {
|
#generateProperties() {
|
||||||
// Sort Properties
|
// Sort Properties
|
||||||
@ -160,7 +177,7 @@ export class Struct {
|
|||||||
if (isVirtual) {
|
if (isVirtual) {
|
||||||
out += `this->vtable->${method.shortName}`;
|
out += `this->vtable->${method.shortName}`;
|
||||||
} else {
|
} else {
|
||||||
out += `${method.getName()}->get(false)`;
|
out += method.getDirectCall();
|
||||||
}
|
}
|
||||||
const extra = [];
|
const extra = [];
|
||||||
if (!method.isStatic) {
|
if (!method.isStatic) {
|
||||||
@ -240,6 +257,11 @@ export class Struct {
|
|||||||
}
|
}
|
||||||
out += '};\n';
|
out += '};\n';
|
||||||
|
|
||||||
|
// Generate Custom Wrapper
|
||||||
|
if (this.#custom !== null) {
|
||||||
|
out += this.#custom.generate();
|
||||||
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -278,6 +300,11 @@ export class Struct {
|
|||||||
out += vtable;
|
out += vtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate Custom Wrapper
|
||||||
|
if (this.#custom !== null) {
|
||||||
|
out += this.#custom.generateCode();
|
||||||
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { Method } from './method';
|
|||||||
import { Property } from './property';
|
import { Property } from './property';
|
||||||
|
|
||||||
// A VTable
|
// A VTable
|
||||||
const structuresWithVTableAddress: string[] = [];
|
export const structuresWithVTableAddress: string[] = [];
|
||||||
export class VTable {
|
export class VTable {
|
||||||
readonly #self: string;
|
readonly #self: string;
|
||||||
#address: number | null;
|
#address: number | null;
|
||||||
@ -22,7 +22,7 @@ export class VTable {
|
|||||||
this.#destructorOffset = 0;
|
this.#destructorOffset = 0;
|
||||||
this.#destructors = [];
|
this.#destructors = [];
|
||||||
// Create Property
|
// Create Property
|
||||||
this.property = new Property(0, this.#getName() + ' *', 'vtable', this.#self);
|
this.property = new Property(0, this.getName() + ' *', 'vtable', this.#self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
@ -56,7 +56,7 @@ export class VTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get Structure Name
|
// Get Structure Name
|
||||||
#getName() {
|
getName() {
|
||||||
return this.#self + '_vtable';
|
return this.#self + '_vtable';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ export class VTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get Full Methods Table
|
// Get Full Methods Table
|
||||||
getMethods() {
|
getMethods(includeDestructors = true) {
|
||||||
// Copy Array
|
// Copy Array
|
||||||
const out = [];
|
const out = [];
|
||||||
out.push(...this.#methods);
|
out.push(...this.#methods);
|
||||||
@ -89,8 +89,10 @@ export class VTable {
|
|||||||
new Method(this.#self, 'destructor_deleting', destructor_return, destructor_args, 0x4 + this.#destructorOffset, false, false)
|
new Method(this.#self, 'destructor_deleting', destructor_return, destructor_args, 0x4 + this.#destructorOffset, false, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (const destructor of this.#destructors) {
|
if (includeDestructors) {
|
||||||
this.#add(out, destructor);
|
for (const destructor of this.#destructors) {
|
||||||
|
this.#add(out, destructor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Return
|
// Return
|
||||||
return out;
|
return out;
|
||||||
@ -142,8 +144,8 @@ export class VTable {
|
|||||||
out += '#endif\n';
|
out += '#endif\n';
|
||||||
|
|
||||||
// Structure
|
// Structure
|
||||||
out += `typedef struct ${this.#getName()} ${this.#getName()};\n`;
|
out += `typedef struct ${this.getName()} ${this.getName()};\n`;
|
||||||
out += `struct ${this.#getName()} final {\n`;
|
out += `struct ${this.getName()} final {\n`;
|
||||||
for (let i = 0; i < methods.length; i++) {
|
for (let i = 0; i < methods.length; i++) {
|
||||||
const info = methods[i];
|
const info = methods[i];
|
||||||
if (info) {
|
if (info) {
|
||||||
@ -154,11 +156,11 @@ export class VTable {
|
|||||||
}
|
}
|
||||||
if (this.#size === null) {
|
if (this.#size === null) {
|
||||||
// Prevent Construction
|
// Prevent Construction
|
||||||
out += preventConstruction(this.#getName());
|
out += preventConstruction(this.getName());
|
||||||
}
|
}
|
||||||
if (this.#address !== null) {
|
if (this.#address !== null) {
|
||||||
// Base
|
// Base
|
||||||
out += `${INDENT}static ${this.#getName()} *base;\n`;
|
out += `${INDENT}static ${this.getName()} *base;\n`;
|
||||||
}
|
}
|
||||||
out += '};\n';
|
out += '};\n';
|
||||||
|
|
||||||
@ -176,7 +178,7 @@ export class VTable {
|
|||||||
// Pointers
|
// Pointers
|
||||||
if (this.#address !== null) {
|
if (this.#address !== null) {
|
||||||
// Base
|
// Base
|
||||||
out += `${this.#getName()} *${this.#getName()}::base = (${this.#getName()} *) ${toHex(this.#address)};\n`;
|
out += `${this.getName()} *${this.getName()}::base = (${this.getName()} *) ${toHex(this.#address)};\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Wrappers
|
// Method Wrappers
|
||||||
@ -191,7 +193,7 @@ export class VTable {
|
|||||||
|
|
||||||
// Sanity Check Size
|
// Sanity Check Size
|
||||||
if (this.#size !== null) {
|
if (this.#size !== null) {
|
||||||
out += assertSize(this.#getName(), this.#size);
|
out += assertSize(this.getName(), this.#size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
<item>constructor</item>
|
<item>constructor</item>
|
||||||
<item>vtable-destructor-offset</item>
|
<item>vtable-destructor-offset</item>
|
||||||
<item>mark-as-simple</item>
|
<item>mark-as-simple</item>
|
||||||
|
<item>generate-custom-wrapper</item>
|
||||||
</list>
|
</list>
|
||||||
<list name="types">
|
<list name="types">
|
||||||
<item>const</item>
|
<item>const</item>
|
||||||
|
@ -2,7 +2,7 @@ syntax def "\.def$"
|
|||||||
comment "//"
|
comment "//"
|
||||||
|
|
||||||
# Commands
|
# Commands
|
||||||
color magenta "\<(extends|size|vtable(-size|-destructor-offset)?|property|static-property|((static|virtual)-)?method|constructor|mark-as-simple)\>"
|
color magenta "\<(extends|size|vtable(-size|-destructor-offset)?|property|static-property|((static|virtual)-)?method|constructor|mark-as-simple|generate-custom-wrapper)\>"
|
||||||
|
|
||||||
# Types
|
# Types
|
||||||
color green "\<((u?(char|short|int))|float|bool|void|std::(string|vector|map))\>"
|
color green "\<((u?(char|short|int))|float|bool|void|std::(string|vector|map))\>"
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<key>name</key>
|
<key>name</key>
|
||||||
<string>keyword.control.symbol-processor</string>
|
<string>keyword.control.symbol-processor</string>
|
||||||
<key>match</key>
|
<key>match</key>
|
||||||
<string>\b(extends|size|vtable-size|vtable-destructor-offset|vtable|property|static-property|method|virtual-method|static-method|constructor|mark-as-simple)\b</string>
|
<string>\b(extends|size|vtable-size|vtable-destructor-offset|vtable|property|static-property|method|virtual-method|static-method|constructor|mark-as-simple|generate-custom-wrapper)\b</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>name</key>
|
<key>name</key>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user