diff options
Diffstat (limited to 'lib/compilers')
-rw-r--r-- | lib/compilers/_all.js | 1 | ||||
-rw-r--r-- | lib/compilers/argument-parsers.js | 7 | ||||
-rw-r--r-- | lib/compilers/dosbox-compiler.ts | 168 | ||||
-rw-r--r-- | lib/compilers/dotnet.ts | 3 | ||||
-rw-r--r-- | lib/compilers/turboc.ts | 75 |
5 files changed, 252 insertions, 2 deletions
diff --git a/lib/compilers/_all.js b/lib/compilers/_all.js index 4ddf9d498..44fd91c0c 100644 --- a/lib/compilers/_all.js +++ b/lib/compilers/_all.js @@ -87,3 +87,4 @@ export {WslVcCompiler} from './wsl-vc'; export {ZigCompiler} from './zig'; export {ZigCC} from './zigcc'; export {ZigCXX} from './zigcxx'; +export {TurboCCompiler} from './turboc'; diff --git a/lib/compilers/argument-parsers.js b/lib/compilers/argument-parsers.js index 1047677ce..10255df3e 100644 --- a/lib/compilers/argument-parsers.js +++ b/lib/compilers/argument-parsers.js @@ -351,3 +351,10 @@ export class TypeScriptNativeParser extends BaseParser { return compiler; } } + +export class TurboCParser extends BaseParser { + static async parse(compiler) { + await TurboCParser.getOptions(compiler, ''); + return compiler; + } +} diff --git a/lib/compilers/dosbox-compiler.ts b/lib/compilers/dosbox-compiler.ts new file mode 100644 index 000000000..3bb784e15 --- /dev/null +++ b/lib/compilers/dosbox-compiler.ts @@ -0,0 +1,168 @@ +// Copyright (c) 2022, Compiler Explorer Authors +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +import path from 'path'; + +import fs from 'fs-extra'; + +import {BaseCompiler} from '../base-compiler'; +import * as exec from '../exec'; +import {logger} from '../logger'; +import {TurboCAsmParser} from '../parsers/asm-parser-turboc'; + +export class DosboxCompiler extends BaseCompiler { + private readonly dosbox: string; + private readonly root: string; + + constructor(compilerInfo, env) { + super(compilerInfo, env); + + this.dosbox = this.compilerProps(`compiler.${this.compiler.id}.dosbox`); + this.root = this.compilerProps(`compiler.${this.compiler.id}.root`); + this.asm = new TurboCAsmParser(this.compilerProps); + } + + protected override async writeMultipleFiles(files: any[], dirPath: string): Promise<any[]> { + const filesToWrite: any[] = []; + + for (const file of files) { + if (!file.filename) throw new Error('One of more files do not have a filename'); + + const fullpath = this.getExtraFilepath(dirPath, file.filename); + const contents = file.contents.replaceAll(/\n/g, '\r\n'); + filesToWrite.push(fs.outputFile(fullpath, contents)); + } + + return Promise.all(filesToWrite); + } + + protected override async writeAllFiles(dirPath: string, source: string, files: any[], filters: object) { + if (!source) throw new Error(`File ${this.compileFilename} has no content or file is missing`); + + const inputFilename = path.join(dirPath, this.compileFilename); + await fs.writeFile(inputFilename, source.replaceAll(/\n/g, '\r\n')); + + if (files && files.length > 0) { + (filters as any).dontMaskFilenames = true; + + await this.writeMultipleFiles(files, dirPath); + } + + return { + inputFilename, + }; + } + + private getDosboxArgs(tempDir: string, compileArgs: string[]) { + const binPath = path.relative(this.root, path.dirname(this.compiler.exe)); + const exeName = path.basename(this.compiler.exe).replace(/\.exe$/i, ''); + return [ + '-c', + `mount c ${this.root}`, + '-c', + `mount d ${tempDir}`, + '-c', + `PATH=%PATH%;C:\\${binPath}`, + '-c', + 'd:', + '-c', + `${exeName} ${compileArgs.join(' ')} > STDOUT.TXT`, + '-c', + 'exit', + ]; + } + + private getDosboxEnv() { + return { + SDL_VIDEODRIVER: 'dummy', + }; + } + + protected override async execCompilerCached(compiler, args, options) { + if (this.mtime === null) { + throw new Error('Attempt to access cached compiler before initialise() called'); + } + if (!options) { + options = this.getDefaultExecOptions(); + options.timeoutMs = 0; + options.ldPath = this.getSharedLibraryPathsAsLdLibraryPaths([]); + } + + const key = this.getCompilerCacheKey(compiler, args, options); + let result = await this.env.compilerCacheGet(key); + if (!result) { + result = await this.env.enqueue(async () => this.exec(compiler, args, options)); + if (result.okToCache) { + this.env + .compilerCachePut(key, result) + .then(() => { + // Do nothing, but we don't await here. + }) + .catch(e => { + logger.info('Uncaught exception caching compilation results', e); + }); + } + } + + return result; + } + + public override async exec(filepath: string, args: string[], execOptions: any) { + if (!execOptions) { + execOptions = this.getDefaultExecOptions(); + } + + execOptions.env = this.getDosboxEnv(); + + if (!execOptions.customCwd) { + execOptions.customCwd = await this.newTempDir(); + } + + const tempDir = execOptions.customCwd; + const fullArgs = this.getDosboxArgs(tempDir, args); + + const result = await exec.executeDirect(this.dosbox, fullArgs, execOptions); + + const stdoutFilename = path.join(tempDir, 'STDOUT.TXT'); + const stdout = await fs.readFile(stdoutFilename); + (result as any).stdout = stdout.toString('utf8'); + + return result; + } + + public override async runCompiler(compiler, options, inputFilename, execOptions) { + return super.runCompiler( + compiler, + options.map(option => { + if (option === inputFilename) { + return path.basename(option); + } else { + return option; + } + }), + inputFilename, + execOptions, + ); + } +} diff --git a/lib/compilers/dotnet.ts b/lib/compilers/dotnet.ts index 8bbcdc4a5..12e607bfe 100644 --- a/lib/compilers/dotnet.ts +++ b/lib/compilers/dotnet.ts @@ -38,7 +38,6 @@ class DotNetCompiler extends BaseCompiler { private clrBuildDir: string; private additionalSources: string; private langVersion: string; - protected asm: DotNetAsmParser; constructor(compilerInfo, env) { super(compilerInfo, env); @@ -174,7 +173,7 @@ class DotNetCompiler extends BaseCompiler { return compilerResult; } - optionsForFilter() { + override optionsForFilter() { return this.compilerOptions; } diff --git a/lib/compilers/turboc.ts b/lib/compilers/turboc.ts new file mode 100644 index 000000000..757526da1 --- /dev/null +++ b/lib/compilers/turboc.ts @@ -0,0 +1,75 @@ +// Copyright (c) 2022, Compiler Explorer Authors +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +import path from 'path'; + +import {logger} from '../logger'; + +import {TurboCParser} from './argument-parsers'; +import {DosboxCompiler} from './dosbox-compiler'; + +export class TurboCCompiler extends DosboxCompiler { + static get key() { + return 'turboc'; + } + + override optionsForFilter() { + return ['-B']; + } + + override getSharedLibraryPathsAsArguments(libraries: object[], libDownloadPath: string) { + return []; + } + + override getSharedLibraryPathsAsLdLibraryPaths(libraries: object[]) { + return []; + } + + override async getVersion() { + logger.info(`Gathering ${this.compiler.id} version information on ${this.compiler.exe}...`); + if (this.compiler.explicitVersion) { + logger.debug(`${this.compiler.id} has forced version output: ${this.compiler.explicitVersion}`); + return {stdout: [this.compiler.explicitVersion], stderr: [], code: 0}; + } + const execOptions = this.getDefaultExecOptions(); + const versionFlag = ''; + execOptions.timeoutMs = 0; + execOptions.ldPath = this.getSharedLibraryPathsAsLdLibraryPaths([]); + + try { + return this.execCompilerCached(this.compiler.exe, [versionFlag], execOptions); + } catch (err) { + logger.error(`Unable to get version for compiler '${this.compiler.exe}' - ${err}`); + return null; + } + } + + override getOutputFilename(dirPath: string, outputFilebase: string, key?: object) { + return path.join(dirPath, 'EXAMPLE.ASM'); + } + + override getArgumentParser() { + return TurboCParser; + } +} |