This Is So Cursed, I Hate It
This commit is contained in:
parent
8bca4b7ec6
commit
1b29e09e67
@ -1,5 +1,4 @@
|
||||
import * as fs from 'node:fs';
|
||||
import { isCppAllowed } from './map';
|
||||
|
||||
export const INDENT = ' ';
|
||||
export const POINTER_SIZE = 4;
|
||||
@ -67,7 +66,7 @@ export function toHex(x: number) {
|
||||
return '0x' + x.toString(16);
|
||||
}
|
||||
export function getAssertFunction() {
|
||||
return isCppAllowed() ? 'static_assert' : '_Static_assert';
|
||||
return 'static_assert';
|
||||
}
|
||||
export function assertSize(name: string, size: number, isDefined: boolean) {
|
||||
let out = '';
|
||||
@ -75,7 +74,7 @@ export function assertSize(name: string, size: number, isDefined: boolean) {
|
||||
const macro = toUpperSnakeCase(name) + '_SIZE';
|
||||
out += `#define ${macro} ${toHex(size)}\n`;
|
||||
// Check Size
|
||||
out += `${getAssertFunction()}(sizeof (${name}) == ${macro}, "Invalid Size");\n`;
|
||||
out += `${getAssertFunction()}(sizeof(${name}) == ${macro}, "Invalid Size");\n`;
|
||||
// Hide Structure Size If The Real Size Is Unknown
|
||||
if (!isDefined) {
|
||||
out += `#undef ${macro}\n`;
|
||||
|
110
src/cpp.ts
Normal file
110
src/cpp.ts
Normal file
@ -0,0 +1,110 @@
|
||||
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;
|
||||
}
|
53
src/index.ts
53
src/index.ts
@ -1,7 +1,8 @@
|
||||
import * as fs from 'node:fs';
|
||||
import { STRUCTURE_FILES, EXTENSION, INDENT } from './common';
|
||||
import { getStructure, setCppAllowed } from './map';
|
||||
import { getStructure } from './map';
|
||||
import { Struct } from './struct';
|
||||
import { fixupCpp } from './cpp';
|
||||
|
||||
// Arguments
|
||||
if (process.argv.length < 5) {
|
||||
@ -103,10 +104,7 @@ function dependencySort(structureObjects: Struct[]) {
|
||||
}
|
||||
|
||||
// Generate Part Of Header
|
||||
function makeHeaderPart(allowCpp: boolean) {
|
||||
// Set Mode
|
||||
setCppAllowed(allowCpp);
|
||||
|
||||
function makeHeaderPart() {
|
||||
// Load Symbols
|
||||
const structureObjects = loadSymbols();
|
||||
|
||||
@ -148,10 +146,6 @@ function makeMainHeader(output: string) {
|
||||
result += '#ifndef __arm__\n';
|
||||
result += '#error "Symbols Are ARM-Only"\n';
|
||||
result += '#endif\n';
|
||||
result += '\n// Suppress Warnings\n';
|
||||
result += '#pragma GCC diagnostic push\n';
|
||||
result += '#pragma GCC diagnostic ignored "-Wunused-variable"\n';
|
||||
result += '#pragma GCC diagnostic ignored "-Wunused-function"\n';
|
||||
result += '\n// Shortcuts\n';
|
||||
result += 'typedef unsigned char uchar;\n';
|
||||
result += 'typedef unsigned short ushort;\n';
|
||||
@ -164,34 +158,31 @@ function makeMainHeader(output: string) {
|
||||
for (const file of extraHeaders) {
|
||||
result += fs.readFileSync(file, {encoding: 'utf8'});
|
||||
}
|
||||
result += '\n// Switch Mode\n';
|
||||
result += '#ifndef __cplusplus\n';
|
||||
result += '\n// C Mode\n';
|
||||
result += '#include <stddef.h>\n';
|
||||
result += 'typedef uchar bool;\n\n';
|
||||
result += makeHeaderPart(false);
|
||||
result += '\n// End C Mode\n';
|
||||
result += '#else\n';
|
||||
result += '\n// C++ Mode\n';
|
||||
result += '#include <string>\n';
|
||||
result += '#include <vector>\n';
|
||||
result += '#include <cstddef>\n';
|
||||
result += '#include <map>\n';
|
||||
result += 'extern "C" {\n\n';
|
||||
result += makeHeaderPart(true);
|
||||
result += '\n// End C++ Mode\n';
|
||||
result += '}\n';
|
||||
result += '#endif\n';
|
||||
result += '\n// Stop Suppressing Warnings\n';
|
||||
result += '#pragma GCC diagnostic pop\n';
|
||||
let core = '';
|
||||
core += '// C/C++ Support\n';
|
||||
core += '#ifndef __cplusplus\n';
|
||||
core += '#include <stddef.h>\n';
|
||||
core += '#include <assert.h>\n';
|
||||
core += 'typedef uchar bool;\n';
|
||||
core += '#else\n';
|
||||
core += '#include <cstddef>\n';
|
||||
core += 'extern "C" {\n';
|
||||
core += '#pragma GCC diagnostic push\n';
|
||||
core += '#pragma GCC diagnostic ignored "-Winvalid-offsetof"\n';
|
||||
core += '#endif\n\n';
|
||||
core += makeHeaderPart();
|
||||
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);
|
||||
}
|
||||
makeMainHeader(headerOutput);
|
||||
|
||||
// Generate Compiled Code
|
||||
function makeCompiledCode(output: string) {
|
||||
// Set Mode
|
||||
setCppAllowed(true);
|
||||
// Load Symbols
|
||||
const structureObjects = loadSymbols();
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { COMMENT, EXTENSION, getSelfArg, parseTypeAndName, readDefinition, safeParseInt, syntaxError } from './common';
|
||||
import { isCppAllowed } from './map';
|
||||
import { Method } from './method';
|
||||
import { SimpleProperty, StaticProperty } from './property';
|
||||
import { Struct } from './struct';
|
||||
@ -93,10 +92,6 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
||||
if (piece.length === 0) {
|
||||
continue;
|
||||
}
|
||||
// Skip C++ Types If Applicable
|
||||
if (!isCppAllowed() && piece.includes('std::')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle Commands
|
||||
let firstSpace = piece.indexOf(' ');
|
||||
|
17
src/map.ts
17
src/map.ts
@ -1,16 +1,6 @@
|
||||
import { Struct } from './struct';
|
||||
import { ErrorOnLine, load } from './loader';
|
||||
|
||||
// Track Mode
|
||||
let allowCpp = false;
|
||||
export function isCppAllowed() {
|
||||
return allowCpp;
|
||||
}
|
||||
export function setCppAllowed(newMode: boolean) {
|
||||
clearStructures();
|
||||
allowCpp = newMode;
|
||||
}
|
||||
|
||||
// Store Loaded Structures
|
||||
const structures: {[id: string]: Struct} = {};
|
||||
|
||||
@ -40,11 +30,4 @@ export function getStructure(name: string) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear Loaded Structures
|
||||
function clearStructures() {
|
||||
for (const name in structures) {
|
||||
delete structures[name];
|
||||
}
|
||||
}
|
@ -60,6 +60,9 @@ export class SimpleProperty implements Property {
|
||||
} else if (this.#type.startsWith('std::vector<')) {
|
||||
// C++ Vector
|
||||
return 12;
|
||||
} else if (this.#type.startsWith('std::map<')) {
|
||||
// C++ Map
|
||||
return 24;
|
||||
} else {
|
||||
// Structure
|
||||
const structure = getStructure(this.#type);
|
||||
@ -96,6 +99,9 @@ export class SimpleProperty implements Property {
|
||||
} else if (this.#type.startsWith('std::vector<')) {
|
||||
// C++ Vector
|
||||
return 4;
|
||||
} else if (this.#type.startsWith('std::map<')) {
|
||||
// C++ Map
|
||||
return 4;
|
||||
} else {
|
||||
// Structure
|
||||
const structure = getStructure(this.#type);
|
||||
|
@ -174,7 +174,7 @@ export class VTable implements Property {
|
||||
declarations += `${INDENT}if (obj == NULL) {\n`;
|
||||
declarations += `${INDENT}${INDENT}return NULL;\n`;
|
||||
declarations += `${INDENT}}\n`;
|
||||
declarations += `${INDENT}memcpy((void *) obj, (void *) vtable, sizeof (${this.#getName()}));\n`;
|
||||
declarations += `${INDENT}memcpy((void *) obj, (void *) vtable, sizeof(${this.#getName()}));\n`;
|
||||
declarations += `${INDENT}return obj;\n`;
|
||||
declarations += '}\n';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user