8bitworkshop/src/worker/tools/acme.ts

98 lines
3.5 KiB
TypeScript

import { CodeListing, CodeListingMap } from "../../common/workertypes";
import { BuildStep, BuildStepResult, gatherFiles, staleFiles, populateFiles, fixParamsWithDefines, putWorkFile } from "../builder";
import { msvcErrorMatcher } from "../listingutils";
import { loadNative, moduleInstFn, print_fn, setupFS, execMain, emglobal, EmscriptenModule } from "../wasmutils";
function parseACMESymbolTable(text: string) {
var symbolmap = {};
var lines = text.split("\n");
for (var i = 0; i < lines.length; ++i) {
var line = lines[i].trim();
// init_text = $81b ; ?
var m = line.match(/(\w+)\s*=\s*[$]([0-9a-f]+)/i);
if (m) {
symbolmap[m[1]] = parseInt(m[2], 16);
}
}
return symbolmap;
}
function parseACMEReportFile(text: string) {
var listings : CodeListingMap = {};
var listing : CodeListing;
var lines = text.split("\n");
for (var i = 0; i < lines.length; ++i) {
var line = lines[i].trim();
// ; ******** Source: hello.acme
var m1 = line.match(/^;\s*[*]+\s*Source: (.+)$/);
if (m1) {
var file = m1[1];
listings[file] = listing = {
lines: [],
};
continue;
}
// 15 0815 201b08 jsr init_text ; write line of text
var m2 = line.match(/^(\d+)\s+([0-9a-f]+)\s+([0-9a-f]+)/i);
if (m2) {
if (listing) {
listing.lines.push({
line: parseInt(m2[1]),
offset: parseInt(m2[2], 16),
insns: m2[3],
});
}
}
}
return listings;
}
export function assembleACME(step: BuildStep): BuildStepResult {
loadNative("acme");
var errors = [];
gatherFiles(step, { mainFilePath: "main.acme" });
var binpath = step.prefix + ".bin";
var lstpath = step.prefix + ".lst";
var sympath = step.prefix + ".sym";
if (staleFiles(step, [binpath])) {
var binout, lstout, symout;
var ACME: EmscriptenModule = emglobal.acme({
instantiateWasm: moduleInstFn('acme'),
noInitialRun: true,
print: print_fn,
printErr: msvcErrorMatcher(errors),
//printErr: makeErrorMatcher(errors, /(Error|Warning) - File (.+?), line (\d+)[^:]+: (.+)/, 3, 4, step.path, 2),
});
var FS = ACME.FS;
populateFiles(step, FS);
fixParamsWithDefines(step.path, step.params);
var args = ['--msvc', '--initmem', '0', '-o', binpath, '-r', lstpath, '-l', sympath, step.path];
if (step.params?.acmeargs) {
args.unshift.apply(args, step.params.acmeargs);
} else {
args.unshift.apply(args, ['-f', 'plain']);
}
args.unshift.apply(args, ["-D__8BITWORKSHOP__=1"]);
if (step.mainfile) {
args.unshift.apply(args, ["-D__MAIN__=1"]);
}
execMain(step, ACME, args);
if (errors.length) {
let listings: CodeListingMap = {};
return { errors, listings };
}
binout = FS.readFile(binpath, { encoding: 'binary' });
lstout = FS.readFile(lstpath, { encoding: 'utf8' });
symout = FS.readFile(sympath, { encoding: 'utf8' });
putWorkFile(binpath, binout);
putWorkFile(lstpath, lstout);
putWorkFile(sympath, symout);
return {
output: binout,
listings: parseACMEReportFile(lstout),
errors: errors,
symbolmap: parseACMESymbolTable(symout),
};
}
}