diff options
Diffstat (limited to 'lib/compilers/argument-parsers.js')
-rw-r--r-- | lib/compilers/argument-parsers.js | 174 |
1 files changed, 160 insertions, 14 deletions
diff --git a/lib/compilers/argument-parsers.js b/lib/compilers/argument-parsers.js index 56b5a40cc..0476ad827 100644 --- a/lib/compilers/argument-parsers.js +++ b/lib/compilers/argument-parsers.js @@ -27,18 +27,53 @@ const _ = require('underscore'), utils = require('../utils'); class BaseParser { + static hasSupport(options, forOption) { + return _.keys(options).find(option => option.includes(forOption)); + } + + static parseLines(stdout, optionRegex) { + let previousOption = false; + let options = {}; + + utils.eachLine(stdout, line => { + const match = line.match(optionRegex); + if (!match) { + if (previousOption && (line.trim().length !== 0)) { + if (options[previousOption].description.endsWith("-")) + options[previousOption].description += line.trim(); + else { + if (options[previousOption].description.length !== 0) + options[previousOption].description += " " + line.trim(); + else + options[previousOption].description = line.trim(); + } + } else { + previousOption = false; + } + return; + } + + if (match) previousOption = match[1]; + if (previousOption) { + options[previousOption] = { + description: match[2].trim(), + timesused: 0 + }; + } + }); + + return options; + } + static getOptions(compiler, helpArg) { return compiler.exec(compiler.compiler.exe, [helpArg]).then(result => { - const options = {}; + let options = {}; if (result.code === 0) { - const optionFinder = /^\s*(--?[-a-zA-Z]+)/; + const optionFinder = /^\s*(--?[a-z0-9=+,[\]<>|-]*)\s*(.*)/i; - utils.eachLine(result.stdout + result.stderr, line => { - const match = line.match(optionFinder); - if (!match) return; - options[match[1]] = true; - }); + options = BaseParser.parseLines(result.stdout + result.stderr, optionFinder); } + compiler.possibleArguments.populateOptions(options); return options; }); } @@ -52,16 +87,17 @@ class GCCParser extends BaseParser { static parse(compiler) { return Promise.all([ GCCParser.getOptions(compiler, "--target-help"), - GCCParser.getOptions(compiler, "--help=common") + GCCParser.getOptions(compiler, "--help=common"), + GCCParser.getOptions(compiler, "--help=optimizers") ]).then(results => { const options = _.extend.apply(_.extend, results); const keys = _.keys(options); logger.debug("gcc-like compiler options: ", keys.join(" ")); - if (options['-masm']) { + if (BaseParser.hasSupport(options, "-masm=")) { compiler.compiler.intelAsm = "-masm=intel"; compiler.compiler.supportsIntel = true; } - if (options['-fdiagnostics-color']) { + if (BaseParser.hasSupport(options, "-fdiagnostics-color")) { if (compiler.compiler.options) compiler.compiler.options += " "; compiler.compiler.options += "-fdiagnostics-color=always"; } @@ -78,25 +114,135 @@ class ClangParser extends BaseParser { static parse(compiler) { return ClangParser.getOptions(compiler, "--help").then(options => { logger.debug("clang-like compiler options: ", _.keys(options).join(" ")); - if (options['-fsave-optimization-record']) { + if (BaseParser.hasSupport(options, '-fsave-optimization-record')) { compiler.compiler.optArg = "-fsave-optimization-record"; compiler.compiler.supportsOptOutput = true; } - if (options['-fcolor-diagnostics']) { + if (BaseParser.hasSupport(options, "-fcolor-diagnostics")) { if (compiler.compiler.options) compiler.compiler.options += " "; compiler.compiler.options += "-fcolor-diagnostics"; } - if (options['-emit-llvm']) { + if (BaseParser.hasSupport(options, "-emit-llvm")) { compiler.compiler.supportsIrView = true; compiler.compiler.irArg = ['-Xclang', '-emit-llvm', '-fsyntax-only']; } + if (BaseParser.hasSupport(options, "-fno-crash-diagnostics")) { + if (compiler.compiler.options) compiler.compiler.options += " "; + compiler.compiler.options += "-fno-crash-diagnostics"; + } return compiler; }); } } +class PascalParser extends BaseParser { + static parse(compiler) { + return PascalParser.getOptions(compiler, "-help").then(() => compiler); + } +} + +class ISPCParser extends BaseParser { + static parse(compiler) { + return ISPCParser.getOptions(compiler, "--help").then(() => compiler); + } + + static getOptions(compiler, helpArg) { + return compiler.exec(compiler.compiler.exe, [helpArg]).then(result => { + let options = {}; + if (result.code === 0) { + const optionFinder = /^\s*\[(--?[a-z0-9=+,{}\s[\]<>|-]*)\]\s*(.*)/i; + + options = BaseParser.parseLines(result.stdout + result.stderr, optionFinder); + } + compiler.possibleArguments.populateOptions(options); + return options; + }); + } +} + +class VCParser extends BaseParser { + static parse(compiler) { + return Promise.all([ + VCParser.getOptions(compiler, "/help") + ]).then(() => { + return compiler; + }); + } + + static parseLines(stdout, optionRegex) { + let previousOption = false; + let options = {}; + + const matchLine = (line) => { + if (line.startsWith("/?")) return; + + const match = line.match(optionRegex); + if (!match) { + if (previousOption && (line.trim().length !== 0)) { + if (options[previousOption].description.endsWith(":")) + options[previousOption].description += " " + line.trim(); + else { + if (options[previousOption].description.length !== 0) + options[previousOption].description += ", " + line.trim(); + else + options[previousOption].description = line.trim(); + } + } else { + previousOption = false; + } + return; + } + + if (match) previousOption = match[1]; + if (previousOption) { + options[previousOption] = { + description: match[2].trim(), + timesused: 0 + }; + } + }; + + utils.eachLine(stdout, line => { + if (line.length === 0) return; + if (line.includes("C/C++ COMPILER OPTIONS")) return; + if (line.match(/^\s\s*-.*-$/)) return; + + let col1; + let col2; + if ((line.length > 39) && (line[40] === '/')) { + col1 = line.substr(0, 39); + col2 = line.substr(40); + } else { + col1 = line; + col2 = ""; + } + + if (col1) matchLine(col1); + if (col2) matchLine(col2); + }); + + return options; + } + + static getOptions(compiler, helpArg) { + return compiler.exec(compiler.compiler.exe, [helpArg]).then(result => { + let options = {}; + if (result.code === 0) { + const optionFinder = /^\s*(\/[a-z0-9=:+#.,[\]{}<>|_-]*)\s*(.*)/i; + + options = this.parseLines(result.stdout, optionFinder); + } + compiler.possibleArguments.populateOptions(options); + return options; + }); + } +} + module.exports = { Base: BaseParser, Clang: ClangParser, - GCC: GCCParser + GCC: GCCParser, + VC: VCParser, + Pascal: PascalParser, + ISPC: ISPCParser }; |