Update
This commit is contained in:
parent
e99239fecf
commit
ddbbbcb8e3
@ -3,9 +3,12 @@ import * as fs from 'node:fs';
|
|||||||
export const INDENT = ' ';
|
export const INDENT = ' ';
|
||||||
export const POINTER_SIZE = 4;
|
export const POINTER_SIZE = 4;
|
||||||
export const EXTENSION = '.def';
|
export const EXTENSION = '.def';
|
||||||
|
export const STRUCTURE_FILES: {[id: string]: string} = {};
|
||||||
export function readDefinition(name: string) {
|
export function readDefinition(name: string) {
|
||||||
const file = `${__dirname}/../symbols/${name}${EXTENSION}`;
|
if (!STRUCTURE_FILES[name]) {
|
||||||
return fs.readFileSync(file, {encoding: 'utf8'});
|
throw new Error(`Missing Definition File: ${name}${EXTENSION}`);
|
||||||
|
}
|
||||||
|
return fs.readFileSync(STRUCTURE_FILES[name]!, {encoding: 'utf8'});
|
||||||
}
|
}
|
||||||
export function parseTypeAndName(parts: string[]) {
|
export function parseTypeAndName(parts: string[]) {
|
||||||
let type = parts[0]!;
|
let type = parts[0]!;
|
||||||
|
177
src/index.ts
177
src/index.ts
@ -1,30 +1,51 @@
|
|||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import { EXTENSION, INDENT } from './common';
|
import { STRUCTURE_FILES, EXTENSION, INDENT } from './common';
|
||||||
import { getStructure, setCppAllowed } from './map';
|
import { getStructure, setCppAllowed } from './map';
|
||||||
|
|
||||||
// Output Directory
|
// Arguments
|
||||||
let outputDirectory = process.argv[2];
|
if (process.argv.length < 5) {
|
||||||
if (!outputDirectory) {
|
console.log('USAGE: npm run <Source Output File> <Header Output File> <Input Files...>');
|
||||||
outputDirectory = `${__dirname}/../out`;
|
process.exit(1);
|
||||||
}
|
}
|
||||||
fs.rmSync(outputDirectory, {force: true, recursive: true});
|
process.argv.shift();
|
||||||
fs.mkdirSync(outputDirectory, {recursive: true});
|
process.argv.shift();
|
||||||
|
function invalidFileType(file: string) {
|
||||||
// Main
|
throw new Error(`Invalid File Type: ${file}`);
|
||||||
function loadSymbols() {
|
}
|
||||||
// Load
|
const sourceOutput = process.argv.shift()!;
|
||||||
const files = fs.readdirSync(`${__dirname}/../symbols`);
|
if (!sourceOutput.endsWith('.cpp')) {
|
||||||
const structureObjects = [];
|
invalidFileType(sourceOutput);
|
||||||
for (const file of files) {
|
}
|
||||||
|
const headerOutput = process.argv.shift()!;
|
||||||
|
if (!headerOutput.endsWith('.h')) {
|
||||||
|
invalidFileType(headerOutput);
|
||||||
|
}
|
||||||
|
const extraHeaders: string[] = [];
|
||||||
|
while (process.argv.length > 0) {
|
||||||
|
const file = process.argv.shift()!;
|
||||||
if (file.endsWith(EXTENSION)) {
|
if (file.endsWith(EXTENSION)) {
|
||||||
// Get Name
|
// Get Class Name
|
||||||
const parts = file.split('/');
|
const parts = file.split('/');
|
||||||
let name = parts[parts.length - 1]!;
|
let name = parts[parts.length - 1]!;
|
||||||
name = name.substring(0, name.length - EXTENSION.length);
|
name = name.substring(0, name.length - EXTENSION.length);
|
||||||
// Structures
|
// Store
|
||||||
structureObjects.push(getStructure(name));
|
STRUCTURE_FILES[name] = file;
|
||||||
|
} else if (file.endsWith('.h')) {
|
||||||
|
// Extra Headers
|
||||||
|
extraHeaders.push(file);
|
||||||
|
} else {
|
||||||
|
// Invalid File Type
|
||||||
|
invalidFileType(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load And Sort Structures
|
||||||
|
function loadSymbols() {
|
||||||
|
// Load
|
||||||
|
const structureObjects = [];
|
||||||
|
for (const name in STRUCTURE_FILES) {
|
||||||
|
structureObjects.push(getStructure(name));
|
||||||
|
}
|
||||||
// Sort
|
// Sort
|
||||||
structureObjects.sort((a, b) => {
|
structureObjects.sort((a, b) => {
|
||||||
if (a.getName() > b.getName()) {
|
if (a.getName() > b.getName()) {
|
||||||
@ -38,20 +59,15 @@ function loadSymbols() {
|
|||||||
// Return
|
// Return
|
||||||
return structureObjects;
|
return structureObjects;
|
||||||
}
|
}
|
||||||
function makeHeader(output: string, allowCpp: boolean) {
|
|
||||||
|
// Generate Part Of Header
|
||||||
|
function makeHeaderPart(allowCpp: boolean) {
|
||||||
// Set Mode
|
// Set Mode
|
||||||
setCppAllowed(allowCpp);
|
setCppAllowed(allowCpp);
|
||||||
|
|
||||||
// Load Symbols
|
// Load Symbols
|
||||||
const structureObjects = loadSymbols();
|
const structureObjects = loadSymbols();
|
||||||
|
|
||||||
// Forward Declarations
|
|
||||||
let forwardDeclarations = '// Forward Declarations\n';
|
|
||||||
for (const structure of structureObjects) {
|
|
||||||
const name = structure.getName();
|
|
||||||
forwardDeclarations += `typedef struct ${name} ${name};\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort Structures By Dependency
|
// Sort Structures By Dependency
|
||||||
while (true) {
|
while (true) {
|
||||||
let valid = true;
|
let valid = true;
|
||||||
@ -84,9 +100,15 @@ function makeHeader(output: string, allowCpp: boolean) {
|
|||||||
|
|
||||||
// Generate Code
|
// Generate Code
|
||||||
let structures = '';
|
let structures = '';
|
||||||
|
let isFirst = true;
|
||||||
for (const structure of structureObjects) {
|
for (const structure of structureObjects) {
|
||||||
const name = structure.getName();
|
const name = structure.getName();
|
||||||
structures += `\n// ${name}\n`;
|
if (isFirst) {
|
||||||
|
isFirst = false;
|
||||||
|
} else {
|
||||||
|
structures += '\n';
|
||||||
|
}
|
||||||
|
structures += `// ${name}\n`;
|
||||||
try {
|
try {
|
||||||
structures += structure.generate();
|
structures += structure.generate();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -95,22 +117,50 @@ function makeHeader(output: string, allowCpp: boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write
|
// Return
|
||||||
let result = '';
|
return structures;
|
||||||
result += '#pragma once\n';
|
|
||||||
result += '\n';
|
|
||||||
result += forwardDeclarations;
|
|
||||||
result += '\n// Init\n';
|
|
||||||
result += 'void init_symbols();';
|
|
||||||
result += '\n// Extra Definitions\n';
|
|
||||||
result += fs.readFileSync(`${__dirname}/../symbols/extra.h`, {encoding: 'utf8'}).trim() + '\n';
|
|
||||||
result += structures;
|
|
||||||
fs.writeFileSync(output, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run
|
// Create Main Header
|
||||||
makeHeader(`${outputDirectory}/minecraft_c.h`, false);
|
function makeMainHeader(output: string) {
|
||||||
makeHeader(`${outputDirectory}/minecraft_cpp.h`, true);
|
let result = '';
|
||||||
|
result += '#pragma once\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 int uint;\n';
|
||||||
|
result += '\n// Init\n';
|
||||||
|
result += 'void init_symbols();\n';
|
||||||
|
result += '\n// Forward Declarations\n';
|
||||||
|
for (const name in STRUCTURE_FILES) {
|
||||||
|
result += `typedef struct ${name} ${name};\n`;
|
||||||
|
}result += '\n// Extra Headers\n';
|
||||||
|
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 += '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 += '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';
|
||||||
|
fs.writeFileSync(output, result);
|
||||||
|
}
|
||||||
|
makeMainHeader(headerOutput);
|
||||||
|
|
||||||
// Generate Compiled Code
|
// Generate Compiled Code
|
||||||
function makeCompiledCode(output: string) {
|
function makeCompiledCode(output: string) {
|
||||||
@ -122,10 +172,17 @@ function makeCompiledCode(output: string) {
|
|||||||
// Generate
|
// Generate
|
||||||
let declarations = '';
|
let declarations = '';
|
||||||
let init = '';
|
let init = '';
|
||||||
|
let isFirst = true;
|
||||||
for (const structure of structureObjects) {
|
for (const structure of structureObjects) {
|
||||||
const name = structure.getName();
|
const name = structure.getName();
|
||||||
declarations += `\n// ${name}\n`;
|
if (isFirst) {
|
||||||
init += `\n${INDENT}// ${name}\n`;
|
isFirst = false;
|
||||||
|
} else {
|
||||||
|
declarations += '\n';
|
||||||
|
init += '\n';
|
||||||
|
}
|
||||||
|
declarations += `// ${name}\n`;
|
||||||
|
init += `${INDENT}// ${name}\n`;
|
||||||
try {
|
try {
|
||||||
const code = structure.generateCode();
|
const code = structure.generateCode();
|
||||||
declarations += code.functions;
|
declarations += code.functions;
|
||||||
@ -138,39 +195,13 @@ function makeCompiledCode(output: string) {
|
|||||||
|
|
||||||
// Write
|
// Write
|
||||||
let result = '';
|
let result = '';
|
||||||
result += '#include "minecraft.h"\n';
|
result += `#include "${fs.realpathSync(headerOutput)}"\n`;
|
||||||
|
result += '\n#include <cstring>\n';
|
||||||
result += '\n// Init\n';
|
result += '\n// Init\n';
|
||||||
result += 'void init_symbols() {';
|
result += 'void init_symbols() {\n';
|
||||||
result += init;
|
result += init;
|
||||||
result += '}\n';
|
result += '}\n\n';
|
||||||
result += declarations;
|
result += declarations;
|
||||||
fs.writeFileSync(output, result);
|
fs.writeFileSync(output, result);
|
||||||
}
|
}
|
||||||
makeCompiledCode(`${outputDirectory}/minecraft.cpp`);
|
makeCompiledCode(sourceOutput);
|
||||||
|
|
||||||
// Create Main Header
|
|
||||||
function makeMainHeader(output: string) {
|
|
||||||
let result = '';
|
|
||||||
result += '#pragma once\n';
|
|
||||||
result += '#pragma GCC diagnostic push\n';
|
|
||||||
result += '#pragma GCC diagnostic ignored "-Wunused-variable"\n';
|
|
||||||
result += '#pragma GCC diagnostic ignored "-Wunused-function"\n';
|
|
||||||
result += 'typedef unsigned char uchar;\n';
|
|
||||||
result += 'typedef unsigned int uint;\n';
|
|
||||||
result += '#include <string.h>\n';
|
|
||||||
result += '#include <stdlib.h>\n';
|
|
||||||
result += '#include <stddef.h>\n';
|
|
||||||
result += '#ifndef __cplusplus\n';
|
|
||||||
result += 'typedef unsigned char bool;\n';
|
|
||||||
result += '#include "minecraft_c.h"\n';
|
|
||||||
result += '#else\n';
|
|
||||||
result += '#include <string>\n';
|
|
||||||
result += '#include <vector>\n';
|
|
||||||
result += 'extern "C" {\n';
|
|
||||||
result += '#include "minecraft_cpp.h"\n';
|
|
||||||
result += '}\n';
|
|
||||||
result += '#endif\n';
|
|
||||||
result += '#pragma GCC diagnostic pop\n';
|
|
||||||
fs.writeFileSync(output, result);
|
|
||||||
}
|
|
||||||
makeMainHeader(`${outputDirectory}/minecraft.h`);
|
|
@ -4,6 +4,7 @@ import { Method } from './method';
|
|||||||
import { SimpleProperty, StaticProperty } from './property';
|
import { SimpleProperty, StaticProperty } from './property';
|
||||||
import { Struct } from './struct';
|
import { Struct } from './struct';
|
||||||
|
|
||||||
|
// Error Handling
|
||||||
function safeParseInt(str: string) {
|
function safeParseInt(str: string) {
|
||||||
const x = parseInt(str);
|
const x = parseInt(str);
|
||||||
if (isNaN(x)) {
|
if (isNaN(x)) {
|
||||||
@ -14,7 +15,6 @@ function safeParseInt(str: string) {
|
|||||||
function syntaxError(message?: string) {
|
function syntaxError(message?: string) {
|
||||||
throw new Error('Syntax Error' + (message ? `: ${message}` : ''));
|
throw new Error('Syntax Error' + (message ? `: ${message}` : ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ErrorOnLine {
|
export class ErrorOnLine {
|
||||||
readonly error: unknown;
|
readonly error: unknown;
|
||||||
readonly file: string;
|
readonly file: string;
|
||||||
@ -199,14 +199,6 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'requires': {
|
|
||||||
// Add Dependency
|
|
||||||
if (args.length === 0) {
|
|
||||||
syntaxError('Missing Dependency Name');
|
|
||||||
}
|
|
||||||
target.addDependency(args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
throw new Error(`Invalid Command: ${command}`);
|
throw new Error(`Invalid Command: ${command}`);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ const structures: {[id: string]: Struct} = {};
|
|||||||
|
|
||||||
// Get Or Load Structure
|
// Get Or Load Structure
|
||||||
export function getStructure(name: string) {
|
export function getStructure(name: string) {
|
||||||
if (Object.prototype.hasOwnProperty.call(structures, name)) {
|
if (name in structures) {
|
||||||
// Already Loaded
|
// Already Loaded
|
||||||
return structures[name]!;
|
return structures[name]!;
|
||||||
} else {
|
} else {
|
||||||
@ -45,8 +45,6 @@ export function getStructure(name: string) {
|
|||||||
// Clear Loaded Structures
|
// Clear Loaded Structures
|
||||||
function clearStructures() {
|
function clearStructures() {
|
||||||
for (const name in structures) {
|
for (const name in structures) {
|
||||||
if (Object.prototype.hasOwnProperty.call(structures, name)) {
|
|
||||||
delete structures[name];
|
delete structures[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { INDENT, MIN_SIZE, toUpperSnakeCase, formatType } from './common';
|
import { INDENT, MIN_SIZE, toUpperSnakeCase, formatType, STRUCTURE_FILES } from './common';
|
||||||
import { isCppAllowed } from './map';
|
import { isCppAllowed } from './map';
|
||||||
import { Method } from './method';
|
import { Method } from './method';
|
||||||
import { Property, StaticProperty } from './property';
|
import { Property, StaticProperty } from './property';
|
||||||
@ -25,7 +25,7 @@ export class Struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
addDependency(dependency: string) {
|
#addDependency(dependency: string) {
|
||||||
this.#dependencies.push(dependency);
|
this.#dependencies.push(dependency);
|
||||||
}
|
}
|
||||||
getDependencies() {
|
getDependencies() {
|
||||||
@ -94,6 +94,11 @@ export class Struct {
|
|||||||
// Add Property
|
// Add Property
|
||||||
addProperty(property: Property) {
|
addProperty(property: Property) {
|
||||||
this.#properties.push(property);
|
this.#properties.push(property);
|
||||||
|
// Add Dependency If Needed
|
||||||
|
const type = property.propertyType();
|
||||||
|
if (type in STRUCTURE_FILES) {
|
||||||
|
this.#addDependency(type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Add Static Property
|
// Add Static Property
|
||||||
addStaticProperty(property: StaticProperty) {
|
addStaticProperty(property: StaticProperty) {
|
||||||
|
Loading…
Reference in New Issue
Block a user