mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 07:04:04 -05:00
Add IDEA files.
Update copyrights, fix jslint issues, tidy code.
This commit is contained in:
2
.idea/.gitignore
generated
vendored
Normal file
2
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/.name
|
||||
/workspace.xml
|
||||
4
.idea/deployment.xml
generated
Normal file
4
.idea/deployment.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PublishConfigData" serverName="GCC explorer" />
|
||||
</project>
|
||||
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
11
.idea/gcc-explorer.iml
generated
Normal file
11
.idea/gcc-explorer.iml
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="gcc-explorer node_modules" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/jsLibraryMappings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<file url="file://$PROJECT_DIR$" libraries="{gcc-explorer node_modules}" />
|
||||
</component>
|
||||
</project>
|
||||
14
.idea/libraries/gcc_explorer_node_modules.xml
generated
Normal file
14
.idea/libraries/gcc_explorer_node_modules.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<component name="libraryTable">
|
||||
<library name="gcc-explorer node_modules" type="javaScript">
|
||||
<properties>
|
||||
<option name="frameworkName" value="node_modules" />
|
||||
<sourceFilesUrls>
|
||||
<item url="file://$PROJECT_DIR$/node_modules" />
|
||||
</sourceFilesUrls>
|
||||
</properties>
|
||||
<CLASSES>
|
||||
<root url="file://$PROJECT_DIR$/node_modules" />
|
||||
</CLASSES>
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/gcc-explorer.iml" filepath="$PROJECT_DIR$/.idea/gcc-explorer.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
5
.idea/scopes/scope_settings.xml
generated
Normal file
5
.idea/scopes/scope_settings.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<state>
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</state>
|
||||
</component>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
14
.idea/webResources.xml
generated
Normal file
14
.idea/webResources.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WebResourcesPaths">
|
||||
<contentEntries>
|
||||
<entry url="file://$PROJECT_DIR$">
|
||||
<entryData>
|
||||
<resourceRoots>
|
||||
<path value="file://$PROJECT_DIR$/static" />
|
||||
</resourceRoots>
|
||||
</entryData>
|
||||
</entry>
|
||||
</contentEntries>
|
||||
</component>
|
||||
</project>
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2012, Matt Godbolt
|
||||
Copyright (c) 2012-2014, Matt Godbolt
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
3
Notes.md
3
Notes.md
@@ -12,5 +12,4 @@ Notes:
|
||||
NB
|
||||
--
|
||||
|
||||
Killing due to time seems broken.
|
||||
Bug with clicked URLs and race to get the list of copmilers (null compiler)
|
||||
Bug with clicked URLs and race to get the list of compilers (null compiler)
|
||||
|
||||
@@ -15,4 +15,4 @@ Assuming you have npm and node installed, simply running `make` ought to get you
|
||||
|
||||
If you want to point it at your own GCC or similar binaries, either edit the `etc/config/gcc-explorer.defaults.properties` or else make a new one with the name `gcc-explorer.YOURHOSTNAME.properties`. The config system leaves a lot to be desired, I'm working on porting [CCS](https://github.com/hellige/ccs-cpp) to javascript and then something more rational can be used.
|
||||
|
||||
Feel free to raise an issue on github or email me directly for more help.
|
||||
Feel free to raise an issue on [github](https://github.com/mattgodbolt/gcc-explorer/issues) or [email me directly](mailto:matt@godbolt.org) for more help.
|
||||
|
||||
109
app.js
109
app.js
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Copyright (c) 2012, Matt Godbolt
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,7 +27,6 @@
|
||||
var nopt = require('nopt'),
|
||||
os = require('os'),
|
||||
props = require('./lib/properties'),
|
||||
querystring = require('querystring'),
|
||||
connect = require('connect'),
|
||||
child_process = require('child_process'),
|
||||
temp = require('temp'),
|
||||
@@ -37,11 +36,12 @@ var nopt = require('nopt'),
|
||||
fs = require('fs-extra');
|
||||
|
||||
var opts = nopt({
|
||||
'env': [String],
|
||||
'rootDir': [String]});
|
||||
'env': [String],
|
||||
'rootDir': [String]
|
||||
});
|
||||
|
||||
var propHierarchy = [
|
||||
'defaults',
|
||||
'defaults',
|
||||
opts.env || 'dev',
|
||||
os.hostname()];
|
||||
|
||||
@@ -54,30 +54,31 @@ var compilers = [];
|
||||
var compilersByExe = {};
|
||||
var compilerExecutables;
|
||||
|
||||
var cache = LRU({
|
||||
max: props.get('gcc-explorer', 'cacheMb') * 1024 * 1024,
|
||||
length: function(n) { return n.length; }
|
||||
var cache = LRU({
|
||||
max: props.get('gcc-explorer', 'cacheMb') * 1024 * 1024,
|
||||
length: function (n) {
|
||||
return n.length;
|
||||
}
|
||||
});
|
||||
var cacheHits = 0;
|
||||
var cacheMisses = 0;
|
||||
|
||||
var compileQueue = async.queue(function(task, callback) {
|
||||
var compileQueue = async.queue(function (task, callback) {
|
||||
console.log("Compiling, queue size " + compileQueue.length());
|
||||
task.task(callback);
|
||||
}, props.get("gcc-explorer", "maxConcurrentCompiles", 1));
|
||||
compileQueue.drain = function() {
|
||||
compileQueue.drain = function () {
|
||||
console.log("Compile queue empty");
|
||||
};
|
||||
compileQueue.saturated = function() {
|
||||
compileQueue.saturated = function () {
|
||||
console.log("Compile queue full");
|
||||
};
|
||||
|
||||
|
||||
function checkOptions(options) {
|
||||
var okOptions = new RegExp(props.get('gcc-options', 'whitelistRe', '.*'));
|
||||
var badOptions = new RegExp(props.get('gcc-options', 'blacklistRe'));
|
||||
var error = [];
|
||||
options.forEach(function(option) {
|
||||
options.forEach(function (option) {
|
||||
if (!option.match(okOptions) || option.match(badOptions)) {
|
||||
error.push(option);
|
||||
}
|
||||
@@ -89,7 +90,7 @@ function checkOptions(options) {
|
||||
function checkSource(source) {
|
||||
var re = /^\s*#include(_next)?\s+["<"](\/|.*\.\.)/;
|
||||
var failed = [];
|
||||
source.split('\n').forEach(function(line, index) {
|
||||
source.split('\n').forEach(function (line, index) {
|
||||
if (line.match(re)) {
|
||||
failed.push("<stdin>:" + (index + 1) + ":1: no absolute or relative includes please");
|
||||
}
|
||||
@@ -112,7 +113,9 @@ function compile(req, res) {
|
||||
if (!compilerInfo) {
|
||||
return res.end(JSON.stringify({code: -1, stderr: "bad compiler " + compiler}));
|
||||
}
|
||||
var options = req.body.options.split(' ').filter(function(x){return x!=""});
|
||||
var options = req.body.options.split(' ').filter(function (x) {
|
||||
return x !== "";
|
||||
});
|
||||
var filters = req.body.filters;
|
||||
var optionsErr = checkOptions(options);
|
||||
if (optionsErr) {
|
||||
@@ -123,7 +126,7 @@ function compile(req, res) {
|
||||
return res.end(JSON.stringify({code: -1, stderr: sourceErr}));
|
||||
}
|
||||
|
||||
var key = compiler + " | " + source + " | " + options + " | " + filters["intel"];
|
||||
var key = compiler + " | " + source + " | " + options + " | " + filters.intel;
|
||||
var cached = cache.get(key);
|
||||
if (cached) {
|
||||
cacheHits++;
|
||||
@@ -133,8 +136,8 @@ function compile(req, res) {
|
||||
}
|
||||
cacheMisses++;
|
||||
|
||||
var compileTask = function(taskFinished) {
|
||||
temp.mkdir('gcc-explorer-compiler', function(err, dirPath) {
|
||||
var compileTask = function (taskFinished) {
|
||||
temp.mkdir('gcc-explorer-compiler', function (err, dirPath) {
|
||||
if (err) {
|
||||
return res.end(JSON.stringify({code: -1, stderr: "Unable to open temp file: " + err}));
|
||||
}
|
||||
@@ -143,7 +146,7 @@ function compile(req, res) {
|
||||
var outputFilename = path.join(dirPath, 'output.S');
|
||||
if (compilerInfo.supportedOpts['-masm']) {
|
||||
var syntax = '-masm=att'; // default at&t
|
||||
if (filters["intel"] == "true") syntax = '-masm=intel';
|
||||
if (filters.intel == "true") syntax = '-masm=intel';
|
||||
options = options.concat([syntax]);
|
||||
}
|
||||
var compileToAsm = props.get("gcc-explorer", "compileToAsm", "-S").split(" ");
|
||||
@@ -161,21 +164,25 @@ function compile(req, res) {
|
||||
compiler,
|
||||
options,
|
||||
{detached: true}
|
||||
);
|
||||
);
|
||||
var stdout = "";
|
||||
var stderr = "";
|
||||
var timeout = setTimeout(function() {
|
||||
var timeout = setTimeout(function () {
|
||||
okToCache = false;
|
||||
child.kill();
|
||||
stderr += "\nKilled - processing time exceeded";
|
||||
}, props.get("gcc-explorer", "compileTimeoutMs", 100));
|
||||
child.stdout.on('data', function (data) { stdout += data; });
|
||||
child.stderr.on('data', function (data) { stderr += data; });
|
||||
child.stdout.on('data', function (data) {
|
||||
stdout += data;
|
||||
});
|
||||
child.stderr.on('data', function (data) {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('exit', function (code) {
|
||||
clearTimeout(timeout);
|
||||
child_process.exec('cat "' + outputFilename + '" | ' + postProcess,
|
||||
{ maxBuffer: props.get("gcc-explorer", "max-asm-size", 8 * 1024 * 1024) },
|
||||
function(err, filt_stdout, filt_stderr) {
|
||||
{maxBuffer: props.get("gcc-explorer", "max-asm-size", 8 * 1024 * 1024)},
|
||||
function (err, filt_stdout, filt_stderr) {
|
||||
var data = filt_stdout;
|
||||
if (err) {
|
||||
data = '<No output: ' + err + '>';
|
||||
@@ -185,7 +192,8 @@ function compile(req, res) {
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
asm: data,
|
||||
code: code });
|
||||
code: code
|
||||
});
|
||||
if (okToCache) {
|
||||
cache.set(key, result);
|
||||
cacheStats();
|
||||
@@ -205,17 +213,23 @@ function compile(req, res) {
|
||||
function loadSources() {
|
||||
var sourcesDir = "lib/sources";
|
||||
var sources = fs.readdirSync(sourcesDir)
|
||||
.filter(function(file) { return file.match(/.*\.js$/); })
|
||||
.map(function(file) { return require("./" + path.join(sourcesDir, file)); });
|
||||
.filter(function (file) {
|
||||
return file.match(/.*\.js$/);
|
||||
})
|
||||
.map(function (file) {
|
||||
return require("./" + path.join(sourcesDir, file));
|
||||
});
|
||||
return sources;
|
||||
}
|
||||
|
||||
var fileSources = loadSources();
|
||||
var sourceToHandler = {};
|
||||
fileSources.forEach(function(source) { sourceToHandler[source.urlpart] = source; });
|
||||
fileSources.forEach(function (source) {
|
||||
sourceToHandler[source.urlpart] = source;
|
||||
});
|
||||
|
||||
function compareOn(key) {
|
||||
return function(xObj, yObj) {
|
||||
return function (xObj, yObj) {
|
||||
var x = xObj[key];
|
||||
var y = yObj[key];
|
||||
if (x < y) return -1;
|
||||
@@ -225,7 +239,7 @@ function compareOn(key) {
|
||||
}
|
||||
|
||||
function getSources(req, res) {
|
||||
var sources = fileSources.map(function(source) {
|
||||
var sources = fileSources.map(function (source) {
|
||||
return {name: source.name, urlpart: source.urlpart};
|
||||
});
|
||||
res.end(JSON.stringify(sources.sort(compareOn("name"))));
|
||||
@@ -250,16 +264,17 @@ function getSource(req, res, next) {
|
||||
else if (action == "load") action = handler.load;
|
||||
else if (action == "save") action = handler.save;
|
||||
else action = null;
|
||||
if (action == null) {
|
||||
if (action === null) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
action.apply(handler, bits.slice(3).concat(function(err, response) {
|
||||
action.apply(handler, bits.slice(3).concat(function (err, response) {
|
||||
if (err) {
|
||||
res.end(JSON.stringify({err: err}));
|
||||
} else {
|
||||
res.end(JSON.stringify(response));
|
||||
}}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function getCompilerExecutables() {
|
||||
@@ -270,10 +285,10 @@ function getCompilerExecutables() {
|
||||
var ndk = props.get('gcc-explorer', 'androidNdk');
|
||||
if (ndk) {
|
||||
var toolchains = fs.readdirSync(ndk + "/toolchains");
|
||||
toolchains.forEach(function(v, i, a) {
|
||||
toolchains.forEach(function (v, i, a) {
|
||||
var path = ndk + "/toolchains/" + v + "/prebuilt/linux-x86_64/bin/";
|
||||
if (fs.existsSync(path)) {
|
||||
var cc = fs.readdirSync(path).filter(function(filename) {
|
||||
var cc = fs.readdirSync(path).filter(function (filename) {
|
||||
return filename.indexOf("g++") != -1;
|
||||
});
|
||||
a[i] = path + cc[0];
|
||||
@@ -281,7 +296,9 @@ function getCompilerExecutables() {
|
||||
a[i] = null;
|
||||
}
|
||||
});
|
||||
toolchains = toolchains.filter(function(x){return x!=null;});
|
||||
toolchains = toolchains.filter(function (x) {
|
||||
return x !== null;
|
||||
});
|
||||
exes.push.apply(exes, toolchains);
|
||||
}
|
||||
compilerExecutables = exes;
|
||||
@@ -295,16 +312,16 @@ function getCompilers(req, res) {
|
||||
function findCompilers() {
|
||||
async.map(getCompilerExecutables(),
|
||||
function (compiler, callback) {
|
||||
fs.stat(compiler, function(err, result) {
|
||||
fs.stat(compiler, function (err, result) {
|
||||
if (err) return callback(null, null);
|
||||
child_process.exec(compiler + ' --version', function(err, output) {
|
||||
child_process.exec(compiler + ' --version', function (err, output) {
|
||||
if (err) return callback(null, null);
|
||||
var version = output.split('\n')[0];
|
||||
child_process.exec(compiler + ' --target-help', function(err, output) {
|
||||
child_process.exec(compiler + ' --target-help', function (err, output) {
|
||||
var options = {};
|
||||
if (!err) {
|
||||
var splitness = /--?[-a-zA-Z]+( ?[-a-zA-Z]+)/;
|
||||
output.split('\n').forEach(function(line) {
|
||||
output.split('\n').forEach(function (line) {
|
||||
var match = line.match(splitness);
|
||||
if (!match) return;
|
||||
options[match[0]] = true;
|
||||
@@ -316,10 +333,14 @@ function findCompilers() {
|
||||
});
|
||||
},
|
||||
function (err, all) {
|
||||
all = all.filter(function(x){return x!=null;});
|
||||
compilers = all.sort(function(x,y){return x.version < y.version ? -1 : x.version > y.version ? 1 : 0;});
|
||||
all = all.filter(function (x) {
|
||||
return x !== null;
|
||||
});
|
||||
compilers = all.sort(function (x, y) {
|
||||
return x.version < y.version ? -1 : x.version > y.version ? 1 : 0;
|
||||
});
|
||||
compilersByExe = {};
|
||||
compilers.forEach(function(compiler) {
|
||||
compilers.forEach(function (compiler) {
|
||||
compilersByExe[compiler.exe] = compiler;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// 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.
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
24
d/demangle.d
24
d/demangle.d
@@ -1,3 +1,27 @@
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// 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 std.stdio;
|
||||
import std.demangle;
|
||||
import std.regex;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2012, Matt Godbolt
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -40,7 +40,7 @@ function debug(string) {
|
||||
function get(base, property, defaultValue) {
|
||||
var result = defaultValue;
|
||||
var source = 'default';
|
||||
hierarchy.forEach(function(elem) {
|
||||
hierarchy.forEach(function (elem) {
|
||||
var propertyMap = findProps(base, elem);
|
||||
if (propertyMap && propertyMap[property]) {
|
||||
debug(base + '.' + property + ': overriding ' + source + ' value (' + result + ') with ' + propertyMap[property]);
|
||||
@@ -62,12 +62,12 @@ function toProperty(prop) {
|
||||
|
||||
function parseProperties(blob, name) {
|
||||
var props = {};
|
||||
blob.split('\n').forEach(function(line, index) {
|
||||
blob.split('\n').forEach(function (line, index) {
|
||||
line = line.replace(/#.*/, '').trim();
|
||||
if (!line) return;
|
||||
var split = line.match(/([^=]+)=(.*)/);
|
||||
if (!split) {
|
||||
console.log("Bad line: " + line + " in " + name + ":" + (index+1));
|
||||
console.log("Bad line: " + line + " in " + name + ":" + (index + 1));
|
||||
return;
|
||||
}
|
||||
props[split[1].trim()] = toProperty(split[2].trim());
|
||||
@@ -77,15 +77,15 @@ function parseProperties(blob, name) {
|
||||
}
|
||||
|
||||
function initialize(directory, hier) {
|
||||
if (hier == null) throw new Error('Must supply a hierarchy array');
|
||||
if (hier === null) throw new Error('Must supply a hierarchy array');
|
||||
console.log("Reading properties from " + directory + " with hierarchy " + hier);
|
||||
hierarchy = hier;
|
||||
var endsWith = /\.properties$/;
|
||||
var propertyFiles = fs.readdirSync(directory).filter(function(filename) {
|
||||
var propertyFiles = fs.readdirSync(directory).filter(function (filename) {
|
||||
return filename.match(endsWith);
|
||||
});
|
||||
properties = {};
|
||||
propertyFiles.forEach(function(file) {
|
||||
propertyFiles.forEach(function (file) {
|
||||
var baseName = file.replace(endsWith, '');
|
||||
file = directory + '/' + file;
|
||||
debug('Reading config from ' + file);
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
(function() {
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// 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.
|
||||
|
||||
(function () {
|
||||
// This is a fake plugin. All of the functionality is in the browser code.
|
||||
exports.name = "Browser";
|
||||
exports.urlpart = "browser";
|
||||
exports.name = "Browser";
|
||||
exports.urlpart = "browser";
|
||||
}).call(this);
|
||||
|
||||
@@ -1,39 +1,75 @@
|
||||
(function() {
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// 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.
|
||||
|
||||
var props = require('../properties.js'),
|
||||
path = require('path'),
|
||||
fs = require('fs');
|
||||
(function () {
|
||||
|
||||
var sourcePath = props.get('builtin', 'sourcepath', './examples/c++');
|
||||
var sourceMatch = new RegExp(props.get('builtin', 'extensionRe', '.*\.cpp$'));
|
||||
var examples = fs.readdirSync(sourcePath)
|
||||
.filter(function(file) { return file.match(sourceMatch); })
|
||||
.map(function(file) {
|
||||
var nicename = file.replace(/\.cpp$/, '');
|
||||
return { urlpart: nicename, name: nicename.replace(/_/g, ' '), path: path.join(sourcePath, file) };
|
||||
}).sort(function(x,y) { return y.name < x.name; });
|
||||
var byUrlpart = {};
|
||||
examples.forEach(function(e) { byUrlpart[e.urlpart] = e.path });
|
||||
var props = require('../properties.js'),
|
||||
path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
function load(filename, callback) {
|
||||
var path = byUrlpart[filename];
|
||||
if (!path) { callback("No such path"); return; }
|
||||
fs.readFile(path, 'utf-8', function(err, res) {
|
||||
if (err) { callback(err); return; }
|
||||
callback(null, {file: res});
|
||||
var sourcePath = props.get('builtin', 'sourcepath', './examples/c++');
|
||||
var sourceMatch = new RegExp(props.get('builtin', 'extensionRe', '.*\.cpp$'));
|
||||
var examples = fs.readdirSync(sourcePath)
|
||||
.filter(function (file) {
|
||||
return file.match(sourceMatch);
|
||||
})
|
||||
.map(function (file) {
|
||||
var nicename = file.replace(/\.cpp$/, '');
|
||||
return {urlpart: nicename, name: nicename.replace(/_/g, ' '), path: path.join(sourcePath, file)};
|
||||
}).sort(function (x, y) {
|
||||
return y.name < x.name;
|
||||
});
|
||||
var byUrlpart = {};
|
||||
examples.forEach(function (e) {
|
||||
byUrlpart[e.urlpart] = e.path
|
||||
});
|
||||
}
|
||||
|
||||
function list(callback) {
|
||||
callback(null, examples.map(function(example) {
|
||||
return {urlpart: example.urlpart, name: example.name};
|
||||
}));
|
||||
}
|
||||
function load(filename, callback) {
|
||||
var path = byUrlpart[filename];
|
||||
if (!path) {
|
||||
callback("No such path");
|
||||
return;
|
||||
}
|
||||
fs.readFile(path, 'utf-8', function (err, res) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
callback(null, {file: res});
|
||||
});
|
||||
}
|
||||
|
||||
exports.load = load;
|
||||
exports.save = null;
|
||||
exports.list = list;
|
||||
exports.name = "Examples";
|
||||
exports.urlpart = "builtin";
|
||||
function list(callback) {
|
||||
callback(null, examples.map(function (example) {
|
||||
return {urlpart: example.urlpart, name: example.name};
|
||||
}));
|
||||
}
|
||||
|
||||
exports.load = load;
|
||||
exports.save = null;
|
||||
exports.list = list;
|
||||
exports.name = "Examples";
|
||||
exports.urlpart = "builtin";
|
||||
|
||||
}).call(this);
|
||||
|
||||
14
package.json
14
package.json
@@ -8,15 +8,15 @@
|
||||
},
|
||||
"main": "./app.js",
|
||||
"dependencies": {
|
||||
"async": "0.7.x",
|
||||
"connect": "2.14.x",
|
||||
"fs-extra": "0.8.x",
|
||||
"lru-cache": "2.5.x",
|
||||
"nopt": "1.0.x",
|
||||
"temp": "0.7.x"
|
||||
"async": "0.7.x",
|
||||
"connect": "2.14.x",
|
||||
"fs-extra": "0.8.x",
|
||||
"lru-cache": "2.5.x",
|
||||
"nopt": "1.0.x",
|
||||
"temp": "0.7.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"supervisor": "0.3.1"
|
||||
"supervisor": "0.3.1"
|
||||
},
|
||||
"license": "BSD-2-Clause"
|
||||
}
|
||||
|
||||
@@ -1,49 +1,75 @@
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// 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.
|
||||
|
||||
CodeMirror.defineMode("asm", function() {
|
||||
function tokenString(quote) {
|
||||
return function(stream) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped) {end = true; break;}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
token: function(stream) {
|
||||
if (stream.match(/^.+:$/)) {
|
||||
return "variable-2";
|
||||
}
|
||||
if (stream.sol() && stream.match(/^\s*\.\w+/)) {
|
||||
return "header";
|
||||
}
|
||||
if (stream.sol() && stream.match(/^\s\w+/)) {
|
||||
return "keyword";
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'") {
|
||||
return tokenString(ch)(stream);
|
||||
}
|
||||
if (/[\[\]{}\(\),;\:]/.test(ch)) return null;
|
||||
if (/[\d$]/.test(ch) || (ch == '-' && stream.peek().match(/[0-9]/))) {
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (ch == '%') {
|
||||
stream.eatWhile(/\w+/);
|
||||
return "variable-3";
|
||||
}
|
||||
if (ch == '#') {
|
||||
stream.eatWhile(/.*/);
|
||||
return "comment";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "word";
|
||||
CodeMirror.defineMode("asm", function () {
|
||||
function tokenString(quote) {
|
||||
return function (stream) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) !== null) {
|
||||
if (next == quote && !escaped) {
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
token: function (stream) {
|
||||
if (stream.match(/^.+:$/)) {
|
||||
return "variable-2";
|
||||
}
|
||||
if (stream.sol() && stream.match(/^\s*\.\w+/)) {
|
||||
return "header";
|
||||
}
|
||||
if (stream.sol() && stream.match(/^\s\w+/)) {
|
||||
return "keyword";
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'") {
|
||||
return tokenString(ch)(stream);
|
||||
}
|
||||
if (/[\[\]{}\(\),;\:]/.test(ch)) return null;
|
||||
if (/[\d$]/.test(ch) || (ch == '-' && stream.peek().match(/[0-9]/))) {
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (ch == '%') {
|
||||
stream.eatWhile(/\w+/);
|
||||
return "variable-3";
|
||||
}
|
||||
if (ch == '#') {
|
||||
stream.eatWhile(/.*/);
|
||||
return "comment";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "word";
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-asm", "asm");
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// 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.
|
||||
|
||||
function processAsm(asm, filters) {
|
||||
var result = [];
|
||||
var asmLines = asm.split("\n");
|
||||
@@ -8,12 +32,14 @@ function processAsm(asm, filters) {
|
||||
var dataDefn = /\.(string|asciz|ascii|[1248]?byte|short|word|long|quad|value|zero)/;
|
||||
var fileFind = /^\s*\.file\s+(\d+)\s+"([^"]+)"$/;
|
||||
var hasOpcode = /^\s*([a-zA-Z0-9$_][a-zA-Z0-9$_.]*:\s*)?[a-zA-Z].*/;
|
||||
asmLines.forEach(function(line) {
|
||||
if (line == "" || line[0] == ".") return;
|
||||
asmLines.forEach(function (line) {
|
||||
if (line === "" || line[0] === ".") return;
|
||||
var match = line.match(labelFind);
|
||||
if (match && (!filters.directives || line.match(hasOpcode))) {
|
||||
// Only count a label as used if it's used by an opcode, or else we're not filtering directives.
|
||||
match.forEach(function(label) { labelsUsed[label] = true; });
|
||||
match.forEach(function (label) {
|
||||
labelsUsed[label] = true;
|
||||
});
|
||||
}
|
||||
match = line.match(fileFind);
|
||||
if (match) {
|
||||
@@ -28,13 +54,13 @@ function processAsm(asm, filters) {
|
||||
var stdInLooking = /.*<stdin>|-/;
|
||||
var endBlock = /\.(cfi_endproc|data|text|section)/;
|
||||
var source = null;
|
||||
asmLines.forEach(function(line) {
|
||||
asmLines.forEach(function (line) {
|
||||
var match;
|
||||
if (line.trim() == "") {
|
||||
result.push({text:"", source:null});
|
||||
if (line.trim() === "") {
|
||||
result.push({text: "", source: null});
|
||||
return;
|
||||
}
|
||||
if (match = line.match(sourceTag)) {
|
||||
if (!!(match = line.match(sourceTag))) {
|
||||
source = null;
|
||||
var file = files[parseInt(match[1])];
|
||||
if (file && file.match(stdInLooking)) {
|
||||
@@ -51,7 +77,7 @@ function processAsm(asm, filters) {
|
||||
match = line.match(labelDefinition);
|
||||
if (match) {
|
||||
// It's a label definition.
|
||||
if (labelsUsed[match[1]] == undefined) {
|
||||
if (labelsUsed[match[1]] === undefined) {
|
||||
// It's an unused label.
|
||||
if (filters.labels) return;
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2012, Matt Godbolt
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
function parseLines(lines, callback) {
|
||||
var re = /^\/tmp\/[^:]+:([0-9]+)(:([0-9]+))?:\s+(.*)/;
|
||||
$.each(lines.split('\n'), function(_, line) {
|
||||
$.each(lines.split('\n'), function (_, line) {
|
||||
line = line.trim();
|
||||
if (line != "") {
|
||||
if (line !== "") {
|
||||
var match = line.match(re);
|
||||
if (match) {
|
||||
callback(parseInt(match[1]), match[4].trim());
|
||||
@@ -72,6 +72,7 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
function getSetting(name) {
|
||||
return window.localStorage[windowLocalPrefix + "." + name];
|
||||
}
|
||||
|
||||
function setSetting(name, value) {
|
||||
window.localStorage[windowLocalPrefix + "." + name] = value;
|
||||
}
|
||||
@@ -95,10 +96,11 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
}
|
||||
|
||||
var errorWidgets = [];
|
||||
|
||||
function onCompileResponse(request, data) {
|
||||
var stdout = data.stdout || "";
|
||||
var stderr = data.stderr || "";
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
stdout += "\nCompiled ok";
|
||||
} else {
|
||||
stderr += "\nCompilation failed";
|
||||
@@ -108,17 +110,16 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
_gaq.push(['_trackTiming', 'Compile', 'Timing', new Date() - request.timestamp]);
|
||||
}
|
||||
$('.result .output :visible').remove();
|
||||
var highlightLine = (data.asm == null);
|
||||
for (var i = 0; i < errorWidgets.length; ++i)
|
||||
for (var i = 0; i < errorWidgets.length; ++i)
|
||||
cppEditor.removeLineWidget(errorWidgets[i]);
|
||||
errorWidgets.length = 0;
|
||||
parseLines(stderr + stdout, function(lineNum, msg) {
|
||||
parseLines(stderr + stdout, function (lineNum, msg) {
|
||||
var elem = $('.result .output .template').clone().appendTo('.result .output').removeClass('template');
|
||||
if (lineNum) {
|
||||
errorWidgets.push(cppEditor.addLineWidget(lineNum - 1, makeErrNode(msg), {
|
||||
coverGutter:false, noHScroll: true
|
||||
coverGutter: false, noHScroll: true
|
||||
}));
|
||||
elem.html($('<a href="#">').append(lineNum + " : " + msg)).click(function() {
|
||||
elem.html($('<a href="#">').append(lineNum + " : " + msg)).click(function () {
|
||||
cppEditor.setSelection({line: lineNum - 1, ch: 0}, {line: lineNum, ch: 0});
|
||||
return false;
|
||||
});
|
||||
@@ -132,43 +133,56 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
|
||||
function numberUsedLines(asm) {
|
||||
var sourceLines = {};
|
||||
$.each(asm, function(_, x) { if (x.source) sourceLines[x.source - 1] = true; });
|
||||
$.each(asm, function (_, x) {
|
||||
if (x.source) sourceLines[x.source - 1] = true;
|
||||
});
|
||||
var ordinal = 0;
|
||||
$.each(sourceLines, function(k, _) { sourceLines[k] = ordinal++; });
|
||||
$.each(sourceLines, function (k, _) {
|
||||
sourceLines[k] = ordinal++;
|
||||
});
|
||||
var asmLines = {};
|
||||
$.each(asm, function(index, x) { if (x.source) asmLines[index] = sourceLines[x.source - 1]; });
|
||||
return { source: sourceLines, asm: asmLines };
|
||||
$.each(asm, function (index, x) {
|
||||
if (x.source) asmLines[index] = sourceLines[x.source - 1];
|
||||
});
|
||||
return {source: sourceLines, asm: asmLines};
|
||||
}
|
||||
|
||||
var lastUpdatedAsm = null;
|
||||
|
||||
function updateAsm(forceUpdate) {
|
||||
if (!currentAssembly) return;
|
||||
var hashedUpdate = JSON.stringify({
|
||||
asm: currentAssembly,
|
||||
asm: currentAssembly,
|
||||
filters: filters
|
||||
});
|
||||
if (!forceUpdate && lastUpdatedAsm == hashedUpdate) { return; }
|
||||
if (!forceUpdate && lastUpdatedAsm == hashedUpdate) {
|
||||
return;
|
||||
}
|
||||
lastUpdatedAsm = hashedUpdate;
|
||||
|
||||
var asm = processAsm(currentAssembly, filters);
|
||||
var asmText = $.map(asm, function(x){ return x.text; }).join("\n");
|
||||
var asmText = $.map(asm, function (x) {
|
||||
return x.text;
|
||||
}).join("\n");
|
||||
var numberedLines = numberUsedLines(asm);
|
||||
|
||||
cppEditor.operation(function(){ clearBackground(cppEditor);});
|
||||
asmCodeMirror.operation(function() {
|
||||
asmCodeMirror.setValue(asmText);
|
||||
|
||||
cppEditor.operation(function () {
|
||||
clearBackground(cppEditor);
|
||||
});
|
||||
asmCodeMirror.operation(function () {
|
||||
asmCodeMirror.setValue(asmText);
|
||||
clearBackground(asmCodeMirror);
|
||||
});
|
||||
if (filters.colouriseAsm) {
|
||||
cppEditor.operation(function() {
|
||||
$.each(numberedLines.source, function(line, ordinal) {
|
||||
cppEditor.addLineClass(parseInt(line),
|
||||
cppEditor.operation(function () {
|
||||
$.each(numberedLines.source, function (line, ordinal) {
|
||||
cppEditor.addLineClass(parseInt(line),
|
||||
"background", "rainbow-" + (ordinal % NumRainbowColours));
|
||||
});
|
||||
});
|
||||
asmCodeMirror.operation(function() {
|
||||
$.each(numberedLines.asm, function(line, ordinal) {
|
||||
asmCodeMirror.addLineClass(parseInt(line),
|
||||
asmCodeMirror.operation(function () {
|
||||
$.each(numberedLines.asm, function (line, ordinal) {
|
||||
asmCodeMirror.addLineClass(parseInt(line),
|
||||
"background", "rainbow-" + (ordinal % NumRainbowColours));
|
||||
});
|
||||
});
|
||||
@@ -176,14 +190,14 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
}
|
||||
|
||||
function pickOnlyRequestFilters(filters) {
|
||||
return {intel: !!filters.intel };
|
||||
return {intel: !!filters.intel};
|
||||
}
|
||||
|
||||
function onChange() {
|
||||
if (ignoreChanges) return; // Ugly hack during startup.
|
||||
if (pendingTimeout) clearTimeout(pendingTimeout);
|
||||
pendingTimeout = setTimeout(function() {
|
||||
var data = {
|
||||
pendingTimeout = setTimeout(function () {
|
||||
var data = {
|
||||
source: cppEditor.getValue(),
|
||||
compiler: $('.compiler').val(),
|
||||
options: $('.compiler_options').val(),
|
||||
@@ -200,7 +214,9 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
url: '/compile',
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: function(result) { onCompileResponse(data, result);}
|
||||
success: function (result) {
|
||||
onCompileResponse(data, result);
|
||||
}
|
||||
});
|
||||
currentAssembly = "[Processing...]";
|
||||
updateAsm();
|
||||
@@ -250,11 +266,11 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback, cmM
|
||||
return;
|
||||
domRoot.find('.filter button.btn[value="intel"]').toggleClass("disabled", !compiler.supportedOpts["-masm"]);
|
||||
}
|
||||
|
||||
|
||||
function setCompilers(compilers) {
|
||||
domRoot.find('.compiler option').remove();
|
||||
compilersByExe = {};
|
||||
$.each(compilers, function(index, arg) {
|
||||
$.each(compilers, function (index, arg) {
|
||||
compilersByExe[arg.exe] = arg;
|
||||
domRoot.find('.compiler').append($('<option value="' + arg.exe + '">' + arg.version + '</option>'));
|
||||
});
|
||||
|
||||
130
static/gcc.js
130
static/gcc.js
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2012, Matt Godbolt
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,55 +28,63 @@ var allCompilers = [];
|
||||
function getSource() {
|
||||
var source = $('.source').val();
|
||||
if (source == "browser") {
|
||||
if (window.localStorage['files'] == undefined) window.localStorage['files'] = "{}";
|
||||
if (window.localStorage.files === undefined) window.localStorage.files = "{}";
|
||||
return {
|
||||
list: function(callback) {
|
||||
var files = JSON.parse(window.localStorage['files']);
|
||||
callback($.map(files, function(val, key) { return val; }));
|
||||
list: function (callback) {
|
||||
var files = JSON.parse(window.localStorage.files);
|
||||
callback($.map(files, function (val, key) {
|
||||
return val;
|
||||
}));
|
||||
},
|
||||
load: function(name, callback) {
|
||||
var files = JSON.parse(window.localStorage['files']);
|
||||
load: function (name, callback) {
|
||||
var files = JSON.parse(window.localStorage.files);
|
||||
callback(files[name]);
|
||||
},
|
||||
save: function(obj, callback) {
|
||||
var files = JSON.parse(window.localStorage['files']);
|
||||
save: function (obj, callback) {
|
||||
var files = JSON.parse(window.localStorage.files);
|
||||
files[obj.name] = obj;
|
||||
window.localStorage['files'] = JSON.stringify(files);
|
||||
window.localStorage.files = JSON.stringify(files);
|
||||
callback(true);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
var base = "/source/" + source;
|
||||
return {
|
||||
list: function(callback) { $.getJSON(base + "/list", callback); },
|
||||
load: function(name, callback) { $.getJSON(base + "/load/" + name, callback); },
|
||||
save: function(obj, callback) { alert("Coming soon..."); }
|
||||
list: function (callback) {
|
||||
$.getJSON(base + "/list", callback);
|
||||
},
|
||||
load: function (name, callback) {
|
||||
$.getJSON(base + "/load/" + name, callback);
|
||||
},
|
||||
save: function (obj, callback) {
|
||||
alert("Coming soon...");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var currentFileList = {};
|
||||
function updateFileList() {
|
||||
getSource().list(function(results) {
|
||||
getSource().list(function (results) {
|
||||
currentFileList = {};
|
||||
$('.filename option').remove();
|
||||
$.each(results, function(index, arg) {
|
||||
$.each(results, function (index, arg) {
|
||||
currentFileList[arg.name] = arg;
|
||||
$('.filename').append($('<option value="' + arg.urlpart + '">' + arg.name + '</option>'));
|
||||
if (window.localStorage['filename'] == arg.urlpart) $('.filename').val(arg.urlpart);
|
||||
if (window.localStorage.filename == arg.urlpart) $('.filename').val(arg.urlpart);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onSourceChange() {
|
||||
updateFileList();
|
||||
window.localStorage['source'] = $('.source').val();
|
||||
window.localStorage.source = $('.source').val();
|
||||
}
|
||||
|
||||
function loadFile() {
|
||||
var name = $('.filename').val();
|
||||
window.localStorage['filename'] = name;
|
||||
getSource().load(name, function(results) {
|
||||
window.localStorage.filename = name;
|
||||
getSource().load(name, function (results) {
|
||||
if (results.file) {
|
||||
currentCompiler.setSource(results.file);
|
||||
} else {
|
||||
@@ -91,16 +99,16 @@ function saveFile() {
|
||||
}
|
||||
|
||||
function saveAs(filename) {
|
||||
var prevFilename = window.localStorage['filename'] || "";
|
||||
var prevFilename = window.localStorage.filename || "";
|
||||
if (filename != prevFilename && currentFileList[filename]) {
|
||||
// TODO!
|
||||
alert("Coming soon - overwriting files");
|
||||
return;
|
||||
}
|
||||
var obj = { urlpart: filename, name: filename, file: currentCompiler.getSource() };
|
||||
getSource().save(obj, function(ok) {
|
||||
var obj = {urlpart: filename, name: filename, file: currentCompiler.getSource()};
|
||||
getSource().save(obj, function (ok) {
|
||||
if (ok) {
|
||||
window.localStorage['filename'] = filename;
|
||||
window.localStorage.filename = filename;
|
||||
updateFileList();
|
||||
}
|
||||
});
|
||||
@@ -113,9 +121,10 @@ function saveFileAs() {
|
||||
function onSave() {
|
||||
$('#saveDialog').modal('hide');
|
||||
saveAs($('#saveDialog .save-filename').val());
|
||||
};
|
||||
}
|
||||
|
||||
$('#saveDialog .save').click(onSave);
|
||||
$('#saveDialog .save-filename').keyup(function(event) {
|
||||
$('#saveDialog .save-filename').keyup(function (event) {
|
||||
if (event.keyCode == 13) onSave();
|
||||
});
|
||||
}
|
||||
@@ -141,7 +150,7 @@ function makePermalink() {
|
||||
longUrl: window.location.href.split('#')[0] + '#' + serialiseState(),
|
||||
}
|
||||
});
|
||||
request.execute(function(response) {
|
||||
request.execute(function (response) {
|
||||
$('#permalink').val(response.id);
|
||||
});
|
||||
}
|
||||
@@ -167,7 +176,9 @@ function serialiseState() {
|
||||
var state = {
|
||||
version: 3,
|
||||
filterAsm: getAsmFilters(),
|
||||
compilers: $.map(allCompilers, function(compiler) { return compiler.serialiseState(); })
|
||||
compilers: $.map(allCompilers, function (compiler) {
|
||||
return compiler.serialiseState();
|
||||
})
|
||||
};
|
||||
return encodeURIComponent(JSON.stringify(state));
|
||||
}
|
||||
@@ -176,18 +187,20 @@ function deserialiseState(state) {
|
||||
try {
|
||||
state = $.parseJSON(decodeURIComponent(state));
|
||||
switch (state.version) {
|
||||
case 1:
|
||||
state.filterAsm = {};
|
||||
// falls into
|
||||
case 2:
|
||||
state.compilers = [state];
|
||||
// falls into
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
case 1:
|
||||
state.filterAsm = {};
|
||||
/* falls through */
|
||||
case 2:
|
||||
state.compilers = [state];
|
||||
/* falls through */
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} catch (ignored) { return false; }
|
||||
} catch (ignored) {
|
||||
return false;
|
||||
}
|
||||
setFilterUi(state.filterAsm);
|
||||
for (var i = 0; i < Math.min(allCompilers.length, state.compilers.length); i++) {
|
||||
allCompilers[i].deserialiseState(state.compilers[i]);
|
||||
@@ -197,7 +210,7 @@ function deserialiseState(state) {
|
||||
|
||||
function initialise() {
|
||||
var defaultFilters = JSON.stringify(getAsmFilters());
|
||||
var actualFilters = $.parseJSON(window.localStorage['filter'] || defaultFilters);
|
||||
var actualFilters = $.parseJSON(window.localStorage.filter || defaultFilters);
|
||||
setFilterUi(actualFilters);
|
||||
|
||||
// Synchronous request here to make the whole race condition problem of
|
||||
@@ -207,7 +220,7 @@ function initialise() {
|
||||
url: "/info",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(results) {
|
||||
success: function (results) {
|
||||
$(".language-name").text(results.language);
|
||||
if (results.language == "Rust") {
|
||||
languageType = "text/x-rustsrc";
|
||||
@@ -218,52 +231,54 @@ function initialise() {
|
||||
}
|
||||
}); // must be ahead of the compiler creation. This is all terrible.
|
||||
|
||||
var compiler = new Compiler($('body'), actualFilters, "a", function() {
|
||||
var compiler = new Compiler($('body'), actualFilters, "a", function () {
|
||||
hidePermalink();
|
||||
}, languageType);
|
||||
allCompilers.push(compiler);
|
||||
currentCompiler = compiler;
|
||||
|
||||
$('form').submit(function() { return false; });
|
||||
$('form').submit(function () {
|
||||
return false;
|
||||
});
|
||||
$('.files .source').change(onSourceChange);
|
||||
$.getJSON("/compilers", function(results) {
|
||||
$.getJSON("/compilers", function (results) {
|
||||
compilersByExe = {};
|
||||
$.each(results, function(index, arg) {
|
||||
$.each(results, function (index, arg) {
|
||||
compilersByExe[arg.exe] = arg;
|
||||
});
|
||||
compiler.setCompilers(results);
|
||||
});
|
||||
$.getJSON("/sources", function(results) {
|
||||
$.getJSON("/sources", function (results) {
|
||||
$('.source option').remove();
|
||||
$.each(results, function(index, arg) {
|
||||
$.each(results, function (index, arg) {
|
||||
$('.files .source').append($('<option value="' + arg.urlpart + '">' + arg.name + '</option>'));
|
||||
if (window.localStorage['source'] == arg.urlpart) {
|
||||
if (window.localStorage.source == arg.urlpart) {
|
||||
$('.files .source').val(arg.urlpart);
|
||||
}
|
||||
});
|
||||
onSourceChange();
|
||||
});
|
||||
$('.files .load').click(function() {
|
||||
$('.files .load').click(function () {
|
||||
loadFile();
|
||||
return false;
|
||||
});
|
||||
$('.files .save').click(function() {
|
||||
$('.files .save').click(function () {
|
||||
saveFile();
|
||||
return false;
|
||||
});
|
||||
$('.files .saveas').click(function() {
|
||||
$('.files .saveas').click(function () {
|
||||
saveFileAs();
|
||||
return false;
|
||||
});
|
||||
$('.files .permalink').click(function(e) {
|
||||
$('.files .permalink').click(function (e) {
|
||||
togglePermalink(e);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.filter button.btn').click(function(e) {
|
||||
|
||||
$('.filter button.btn').click(function (e) {
|
||||
$(e.target).toggleClass('active');
|
||||
var filters = getAsmFilters();
|
||||
window.localStorage['filter'] = JSON.stringify(filters);
|
||||
window.localStorage.filter = JSON.stringify(filters);
|
||||
currentCompiler.setFilters(filters);
|
||||
});
|
||||
|
||||
@@ -271,7 +286,7 @@ function initialise() {
|
||||
deserialiseState(window.location.hash.substr(1));
|
||||
}
|
||||
|
||||
$(window).bind('hashchange', function() {
|
||||
$(window).bind('hashchange', function () {
|
||||
loadFromHash();
|
||||
});
|
||||
loadFromHash();
|
||||
@@ -286,20 +301,21 @@ function initialise() {
|
||||
var height = windowHeight - top - resultHeight - 40;
|
||||
currentCompiler.setEditorHeight(height);
|
||||
}
|
||||
|
||||
$(window).on("resize", resizeEditors);
|
||||
resizeEditors();
|
||||
}
|
||||
|
||||
function getAsmFilters() {
|
||||
var asmFilters = {};
|
||||
$('.filter button.btn.active').each(function() {
|
||||
$('.filter button.btn.active').each(function () {
|
||||
asmFilters[$(this).val()] = true;
|
||||
});
|
||||
return asmFilters;
|
||||
}
|
||||
|
||||
function setFilterUi(asmFilters) {
|
||||
$('.filter button.btn').each(function() {
|
||||
$('.filter button.btn').each(function () {
|
||||
$(this).toggleClass('active', !!asmFilters[$(this).val()]);
|
||||
});
|
||||
}
|
||||
|
||||
32
test/test.js
32
test/test.js
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Copyright (c) 2012, Matt Godbolt
|
||||
// Copyright (c) 2012-2014, Matt Godbolt
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,8 +33,12 @@ function processAsm(filename, filters) {
|
||||
}
|
||||
|
||||
var cases = fs.readdirSync('./cases')
|
||||
.filter(function(x){return x.match(/\.asm$/)})
|
||||
.map(function(x){return './cases/' + x;});
|
||||
.filter(function (x) {
|
||||
return x.match(/\.asm$/)
|
||||
})
|
||||
.map(function (x) {
|
||||
return './cases/' + x;
|
||||
});
|
||||
|
||||
var failures = 0;
|
||||
|
||||
@@ -56,17 +60,25 @@ function testFilter(filename, suffix, filters) {
|
||||
assertEq(file.length, result.length, expected);
|
||||
if (file.length != result.length) return;
|
||||
for (var i = 0; i < file.length; ++i) {
|
||||
assertEq(file[i], result[i].text, expected + ":" + (i+1));
|
||||
assertEq(file[i], result[i].text, expected + ":" + (i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cases.forEach(function(x){ testFilter(x, "", {}) });
|
||||
cases.forEach(function(x){ testFilter(x, ".directives", { directives: true}) });
|
||||
cases.forEach(function(x){ testFilter(x, ".directives.labels",
|
||||
{ directives: true, labels: true}) });
|
||||
cases.forEach(function(x){ testFilter(x, ".directives.labels.comments",
|
||||
{ directives: true, labels: true, commentOnly: true }) });
|
||||
cases.forEach(function (x) {
|
||||
testFilter(x, "", {})
|
||||
});
|
||||
cases.forEach(function (x) {
|
||||
testFilter(x, ".directives", {directives: true})
|
||||
});
|
||||
cases.forEach(function (x) {
|
||||
testFilter(x, ".directives.labels",
|
||||
{directives: true, labels: true})
|
||||
});
|
||||
cases.forEach(function (x) {
|
||||
testFilter(x, ".directives.labels.comments",
|
||||
{directives: true, labels: true, commentOnly: true})
|
||||
});
|
||||
|
||||
if (failures) {
|
||||
console.log(failures + " failures");
|
||||
|
||||
Reference in New Issue
Block a user