server: updated parsing, flags

This commit is contained in:
Steven Hugg 2023-11-07 17:00:35 -06:00
parent d31a8c4efe
commit c6345ec728
5 changed files with 54 additions and 30 deletions

View File

@ -695,3 +695,9 @@ export function coerceToArray<T>(arrobj: any) : T[] {
else if (typeof arrobj === 'object') return Array.from(Object.values(arrobj))
else throw new Error(`Expected array or object, got "${arrobj}"`);
}
export function replaceAll(s:string, search:string, replace:string) : string {
if (s == '') return '';
if (search == '') return s;
return s.split(search).join(replace);
}

View File

@ -64,6 +64,7 @@ export class SourceEditor implements ProjectView {
errorwidgets = [];
errormarks = [];
inspectWidget;
refreshDelayMsec = 300;
createDiv(parent:HTMLElement) {
var div = document.createElement('div');
@ -77,6 +78,9 @@ export class SourceEditor implements ProjectView {
this.editor.setSelection({line:0,ch:0}, {line:0,ch:0}, {scroll:true}); // move cursor to start
}
this.setupEditor();
if (current_project.getToolForFilename(this.path).startsWith("remote:")) {
this.refreshDelayMsec = 1000; // remote URLs get slower refresh
}
return div;
}
@ -114,7 +118,7 @@ export class SourceEditor implements ProjectView {
clearTimeout(this.updateTimer);
this.updateTimer = setTimeout( () => {
current_project.updateFile(this.path, this.editor.getValue());
}, 300);
}, this.refreshDelayMsec);
if (this.markHighlight) {
this.markHighlight.clear();
this.markHighlight = null;

View File

@ -58,6 +58,7 @@ const VCS_PRESETS = [
];
function getToolForFilename_vcs(fn: string) {
if (fn.endsWith("-llvm.c")) return "remote:llvm-mos";
if (fn.endsWith(".wiz")) return "wiz";
if (fn.endsWith(".bb") || fn.endsWith(".bas")) return "bataribasic";
if (fn.endsWith(".ca65")) return "ca65";

View File

@ -3,15 +3,15 @@ import fs from 'fs';
import path from 'path';
import { spawn } from 'child_process';
import { CodeListingMap, WorkerBuildStep, WorkerError, WorkerErrorResult, WorkerFileUpdate, WorkerResult, isOutputResult } from '../../common/workertypes';
import { getBasePlatform, getRootBasePlatform } from '../../common/util';
import { getBasePlatform, getRootBasePlatform, replaceAll } from '../../common/util';
import { BuildStep, makeErrorMatcher } from '../workermain';
import { parseObjDumpListing, parseObjDumpSymbolTable } from './clang';
import { parseObjDump } from './clang';
const LLVM_MOS_TOOL: ServerBuildTool = {
name: 'llvm-mos',
version: '',
extensions: ['.c', '.cpp', '.s'],
extensions: ['.c', '.cpp', '.s', '.S', '.C'],
archs: ['6502'],
platforms: ['atari8', 'c64', 'nes', 'pce', 'vcs'],
platform_configs: {
@ -27,11 +27,9 @@ const LLVM_MOS_TOOL: ServerBuildTool = {
},
c64: {
command: 'mos-c64-clang',
libargs: ['-D', '__C64__']
},
atari8: {
command: 'mos-atari8-clang',
libargs: ['-D', '__ATARI__']
},
nes: {
command: 'mos-nes-nrom-clang', // TODO
@ -39,7 +37,9 @@ const LLVM_MOS_TOOL: ServerBuildTool = {
},
pce: {
command: 'mos-pce-clang', // TODO
libargs: ['-D', '__PCE__']
},
vcs: {
command: 'mos-atari2600-3e-clang', // TODO
},
}
}
@ -175,6 +175,10 @@ export class ServerBuildEnv {
resolve(this.processOutput(step));
}
} else {
errorData = replaceAll(errorData, this.sessionDir, '');
errorData = replaceAll(errorData, this.rootdir, '');
// remove folder paths
errorData = errorData.replace(/(\/var\/folders\/.+?\/).+?:/g, '');
let errorResult = await this.processErrors(step, errorData);
if (errorResult.errors.length === 0) {
errorResult.errors.push({ line: 0, msg: `Build failed.\n\n${errorData}` });
@ -203,10 +207,9 @@ export class ServerBuildEnv {
async processDebugInfo(step: WorkerBuildStep): Promise<WorkerResult> {
let dbgfile = path.join(this.sessionDir, 'debug.out');
let dbglist = await fs.promises.readFile(dbgfile);
let listings = parseObjDumpListing(dbglist.toString());
let symbolmap = parseObjDumpSymbolTable(dbglist.toString());
return { output: [], listings, symbolmap };
let dbglist = (await fs.promises.readFile(dbgfile)).toString();
let { listings, symbolmap, segments } = parseObjDump(dbglist);
return { output: [], listings, symbolmap, segments };
}
async compileAndLink(step: WorkerBuildStep, updates: WorkerFileUpdate[]): Promise<WorkerResult> {

View File

@ -1,27 +1,37 @@
import path from 'path';
import { CodeListing, CodeListingMap } from "../../common/workertypes";
import { CodeListing, CodeListingMap, Segment } from "../../common/workertypes";
export function parseObjDumpSymbolTable(symbolTable) {
const lines = symbolTable.split('\n');
const result = {};
export function parseObjDump(lst: string) {
// parse symbol map
const lines = lst.split('\n');
const symbolmap = {};
const segments : Segment[] = [];
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith('00')) {
if (line.startsWith("Disassembly")) break;
if (line.startsWith('0')) {
const parts = line.split(/\s+/);
if (parts.length < 5) continue;
const symbol = parts[parts.length-1];
const address = parseInt(parts[0], 16);
result[symbol] = address;
const address = parseInt(parts[0], 16) & 0xffff; // TODO: 32-bit addresses
symbolmap[symbol] = address;
// is it a segment?
if (symbol.startsWith('__')) {
if (symbol.endsWith('_start')) {
let name = symbol.substring(2, symbol.length - 6);
let type = parts[2] == '.text' ? 'rom' : 'ram';
segments.push({ name, start: address, size: 0, type })
} else if (symbol.endsWith('_size')) {
let name = symbol.substring(2, symbol.length - 5);
let seg = segments.find(s => s.name === name);
if (seg) seg.size = address;
}
}
}
}
return result;
}
export function parseObjDumpListing(lst: string): CodeListingMap {
const lines = lst.split('\n');
const result: CodeListingMap = {};
// parse listings
const listings: CodeListingMap = {};
var lastListing : CodeListing = null;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith(';')) {
@ -32,18 +42,18 @@ export function parseObjDumpListing(lst: string): CodeListingMap {
const file = path.basename(fileParts[0].trim()).split('.')[0] + '.lst';
const lineNumber = parseInt(fileParts[1], 10);
if (lineNumber > 0) {
if (!result[file]) result[file] = { lines: [], text: lst };
lastListing = result[file];
if (!listings[file]) listings[file] = { lines: [], text: lst };
lastListing = listings[file];
lastListing.lines.push({ line: lineNumber, offset: null });
}
}
} else if (lastListing && line.match(/^\s*[A-F0-9]+:.+/i)) {
const offsetIndex = line.indexOf(':');
if (offsetIndex !== -1) {
const offset = parseInt(line.substring(0, offsetIndex).trim(), 16);
const offset = parseInt(line.substring(0, offsetIndex).trim(), 16) & 0xffff; // TODO: 32-bit addresses;
lastListing.lines[lastListing.lines.length - 1].offset = offset;
}
}
}
return result;
}
return { listings, symbolmap, segments };
}