Browse Source

Initial import of GCC-Explorer

diffs
Matt Godbolt 11 years ago
commit
15ea5e164b
  1. 2
      .gitignore
  2. 23
      LICENSE
  3. 12
      Makefile
  4. 4
      README.md
  5. 186
      app.js
  6. 2
      etc/config/gcc-explorer.defaults.properties
  7. 5
      examples/max_array.cpp
  8. 10
      examples/max_array_opt.cpp
  9. 7
      examples/sum_over_array.cpp
  10. 12
      examples/sum_over_array_opt.cpp
  11. 99
      lib/properties.js
  12. 5
      lib/sources/browser.js
  13. 38
      lib/sources/builtin.js
  14. 21
      package.json
  15. 49
      static/asm.js
  16. 218
      static/ext/bootstrap/bootstrap-modal.js
  17. 808
      static/ext/bootstrap/css/bootstrap-responsive.css
  18. 9
      static/ext/bootstrap/css/bootstrap-responsive.min.css
  19. 4960
      static/ext/bootstrap/css/bootstrap.css
  20. 9
      static/ext/bootstrap/css/bootstrap.min.css
  21. BIN
      static/ext/bootstrap/img/glyphicons-halflings-white.png
  22. BIN
      static/ext/bootstrap/img/glyphicons-halflings.png
  23. 1824
      static/ext/bootstrap/js/bootstrap.js
  24. 6
      static/ext/bootstrap/js/bootstrap.min.js
  25. 234
      static/ext/codemirror/clike.js
  26. 114
      static/ext/codemirror/codemirror.css
  27. 3047
      static/ext/codemirror/codemirror.js
  28. 174
      static/ext/codemirror/util/closetag.js
  29. 23
      static/ext/codemirror/util/dialog.css
  30. 63
      static/ext/codemirror/util/dialog.js
  31. 191
      static/ext/codemirror/util/foldcode.js
  32. 294
      static/ext/codemirror/util/formatting.js
  33. 134
      static/ext/codemirror/util/javascript-hint.js
  34. 50
      static/ext/codemirror/util/loadmode.js
  35. 44
      static/ext/codemirror/util/match-highlighter.js
  36. 51
      static/ext/codemirror/util/overlay.js
  37. 49
      static/ext/codemirror/util/runmode.js
  38. 114
      static/ext/codemirror/util/search.js
  39. 117
      static/ext/codemirror/util/searchcursor.js
  40. 16
      static/ext/codemirror/util/simple-hint.css
  41. 72
      static/ext/codemirror/util/simple-hint.js
  42. 4
      static/ext/jquery/jquery-1.7.1.min.js
  43. BIN
      static/favicon.ico
  44. 44
      static/gcc.css
  45. 188
      static/gcc.js
  46. 134
      static/index.html

2
.gitignore vendored

@ -0,0 +1,2 @@
*.swp
/node_modules

23
LICENSE

@ -0,0 +1,23 @@
Copyright (c) 2012, 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.

12
Makefile

@ -0,0 +1,12 @@
default: run
node_modules: package.json
npm install
@touch $@
clean:
rm -rf node_modules
.PHONY: clean run
run: node_modules
./node_modules/.bin/supervisor ./app.js

4
README.md

@ -0,0 +1,4 @@
GCC Explorer
------------
GCC Explorer is an interactive compiler. The left-hand pane shows editable C/C++ code. The right, the assembly output of having compiled the code with a given compiler and settings.

186
app.js

@ -0,0 +1,186 @@
#!/usr/bin/env node
// Copyright (c) 2012, 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 nopt = require('nopt'),
os = require('os'),
props = require('./lib/properties'),
querystring = require('querystring'),
connect = require('connect'),
child_process = require('child_process'),
temp = require('temp'),
path = require('path'),
async = require('async'),
fs = require('fs');
var opts = nopt({
'env': [String],
'rootDir': [String]});
var propHierarchy = [
'defaults',
opts.env || 'dev',
os.hostname()];
var rootDir = opts.rootDir || './etc';
props.initialize(rootDir + '/config', propHierarchy);
var port = props.get('gcc-explorer', 'port', 10240);
function compile(req, res) {
var source = req.body.source;
var compiler = req.body.compiler;
var options = req.body.options.split(' ').filter(function(x){return x!=""});
temp.mkdir('gcc-explorer-compiler', function(err, dirPath) {
if (err) {
res.end(JSON.stringify({code: -1, stderr: "Unable to open temp file: " + err}));
return;
}
var outputFilename = path.join(dirPath, 'output.S');
options = options.concat([ '-x', 'c++', '-o', outputFilename, '-S', '-']);
var child = child_process.spawn(
compiler, // TODO: yes, this is a gaping security hole
options
);
var stdout = "";
var stderr = "";
child.stdout.on('data', function (data) { stdout += data; });
child.stderr.on('data', function (data) { stderr += data; });
child.stdin.write(source);
child.stdin.end();
child.on('exit', function (code) {
child_process.exec('cat "' + outputFilename + '" | c++filt', function(err, filt_stdout, filt_stderr) {
var data = filt_stdout;
if (err) {
data = '<No output>';
}
res.end(JSON.stringify({
stdout: stdout,
stderr: stderr,
asm: data,
code: code }))
});
});
});
}
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)); });
return sources;
}
var fileSources = loadSources();
var sourceToHandler = {};
fileSources.forEach(function(source) { sourceToHandler[source.urlpart] = source; });
function compareOn(key) {
return function(xObj, yObj) {
var x = xObj[key];
var y = yObj[key];
if (x < y) return -1;
if (x > y) return 1;
return 0;
};
}
function getSources(req, res) {
var sources = fileSources.map(function(source) {
return {name: source.name, urlpart: source.urlpart};
});
res.end(JSON.stringify(sources.sort(compareOn("name"))));
}
function getSource(req, res, next) {
var bits = req.url.split("/");
var handler = sourceToHandler[bits[1]];
if (!handler) {
next();
return;
}
var action = bits[2];
if (action == "list") action = handler.list;
else if (action == "load") action = handler.load;
else if (action == "save") action = handler.save;
else action = null;
if (action == null) {
next();
return;
}
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 getCompilers(req, res) {
var compilers = props.get("gcc-explorer", "compilers", "/usr/bin/g++").split(":");
async.map(compilers,
function (compiler, callback) {
fs.stat(compiler, function(err, result) {
if (err) {
callback(null, null);
} else {
child_process.exec(compiler + ' --version', function(err, output) {
if (err) {
callback(null, null);
} else {
callback(null, {exe: compiler, version: output.split('\n')[0]});
}
});
}
});
},
function (err, all) {
all = all.filter(function(x){return x!=null;});
res.end(JSON.stringify(all));
}
);
}
// WebServer.
var webServer = connect();
webServer
.use(connect.logger())
.use(connect.favicon('static/favicon.ico'))
.use(connect.static('static'))
.use(connect.bodyParser())
.use('/sources', getSources)
.use('/source', getSource)
.use('/compilers', getCompilers)
.use('/compile', compile);
// GO!
console.log("=======================================");
console.log("Listening on http://" + os.hostname() + ":" + port + "/");
console.log("=======================================");
webServer.listen(port);

2
etc/config/gcc-explorer.defaults.properties

@ -0,0 +1,2 @@
port=10240
compilers=/usr/bin/g++-4.4:/usr/bin/g++-4.5:/usr/bin/g++-4.6

5
examples/max_array.cpp

@ -0,0 +1,5 @@
void maxArray(double* x, double* y) {
for (auto i = 0; i < 65536; i++) {
if (y[i] > x[i]) x[i] = y[i];
}
}

10
examples/max_array_opt.cpp

@ -0,0 +1,10 @@
// Compile with O3 and gcc4.7 and -march=corei7-avx for Sandy Bridge
void maxArray(double* __restrict x, double* __restrict y) {
#if __GNUC_MINOR__ >= 7 // 4.7+
x = static_cast<double*>(__builtin_assume_aligned(x, 64));
y = static_cast<double*>(__builtin_assume_aligned(y, 64));
#endif
for (auto i = 0; i < 65536; i++) {
x[i] = ((y[i] > x[i]) ? y[i] : x[i]);
}
}

7
examples/sum_over_array.cpp

@ -0,0 +1,7 @@
int testFunction(int* input, int length) {
int sum = 0;
for (int i = 0; i < length; ++i) {
sum += input[i];
}
return sum;
}

12
examples/sum_over_array_opt.cpp

@ -0,0 +1,12 @@
// Compile with -O3 to see autovectorization
int testFunction(int* input, int length) {
#if __GNUC_MINOR__ >= 7
// gcc 4.7 allows us to tell it about alignments.
input = static_cast<int*>(__builtin_assume_aligned(input, 16));
#endif
int sum = 0;
for (int i = 0; i < length; ++i) {
sum += input[i];
}
return sum;
}

99
lib/properties.js

@ -0,0 +1,99 @@
// Copyright (c) 2012, 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 fs = require('fs');
var properties = {};
var hierarchy = [];
function findProps(base, elem) {
var name = base + '.' + elem;
return properties[name];
}
function debug(string) {
//console.log("prop: " + string);
}
function get(base, property, defaultValue) {
var result = defaultValue;
var source = 'default';
hierarchy.forEach(function(elem) {
var propertyMap = findProps(base, elem);
if (propertyMap && propertyMap[property]) {
debug(base + '.' + property + ': overriding ' + source + ' value (' + result + ') with ' + propertyMap[property]);
result = propertyMap[property];
source = elem;
}
});
debug(base + '.' + property + ': returning ' + result + ' (from ' + source + ')');
return result;
}
function toProperty(prop) {
if (prop == 'true' || prop == 'yes') return true;
if (prop == 'false' || prop == 'no') return false;
if (prop.match(/^[0-9]+$/)) return parseInt(prop);
if (prop.match(/^[0-9]*\.[0-9]+$/)) return parseFloat(prop);
return prop;
}
function parseProperties(blob, name) {
var props = {};
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));
return;
}
props[split[1].trim()] = toProperty(split[2].trim());
debug(split[1].trim() + " = " + split[2].trim());
});
return props;
}
function initialize(directory, hier) {
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) {
return filename.match(endsWith);
});
properties = {};
propertyFiles.forEach(function(file) {
var baseName = file.replace(endsWith, '');
file = directory + '/' + file;
debug('Reading config from ' + file);
properties[baseName] = parseProperties(fs.readFileSync(file, 'utf-8'), file);
});
}
module.exports = {
get: get,
initialize: initialize
};

5
lib/sources/browser.js

@ -0,0 +1,5 @@
(function() {
// This is a fake plugin. All of the functionality is in the browser code.
exports.name = "Browser";
exports.urlpart = "browser";
}).call(this);

38
lib/sources/builtin.js

@ -0,0 +1,38 @@
(function() {
var props = require('../properties.js'),
path = require('path'),
fs = require('fs');
var sourcePath = props.get('builtin', 'sourcepath', './examples');
var examples = fs.readdirSync(sourcePath)
.filter(function(file) { return file.match(/.*\.cpp$/); })
.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 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});
});
}
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);

21
package.json

@ -0,0 +1,21 @@
{
"author": "Matt Godbolt <matt@godbolt.org>",
"name": "gcc-explorer",
"description": "Investigate what on earth GCC does",
"version": "0.0.1",
"engines": {
"node": "0.4.x"
},
"main": "./app.js",
"dependencies": {
"connect": "1.7.x",
"async": "0.1.x",
"mustache": "0.4.x",
"nopt": "1.0.x",
"temp": "0.4.x"
},
"devDependencies": {
"supervisor": "0.2.x"
},
"license": "BSD-2-Clause"
}

49
static/asm.js

@ -0,0 +1,49 @@
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)) {
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");

218
static/ext/bootstrap/bootstrap-modal.js vendored

@ -0,0 +1,218 @@
/* =========================================================
* bootstrap-modal.js v2.0.3
* http://twitter.github.com/bootstrap/javascript.html#modals
* =========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================= */
!function ($) {
"use strict"; // jshint ;_;
/* MODAL CLASS DEFINITION
* ====================== */
var Modal = function (content, options) {
this.options = options
this.$element = $(content)
.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
}
Modal.prototype = {
constructor: Modal
, toggle: function () {
return this[!this.isShown ? 'show' : 'hide']()
}
, show: function () {
var that = this
, e = $.Event('show')
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
$('body').addClass('modal-open')
this.isShown = true
escape.call(this)
backdrop.call(this, function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(document.body) //don't move modals dom position
}
that.$element
.show()
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element.addClass('in')
transition ?
that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
that.$element.trigger('shown')
})
}
, hide: function (e) {
e && e.preventDefault()
var that = this
e = $.Event('hide')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
$('body').removeClass('modal-open')
escape.call(this)
this.$element.removeClass('in')
$.support.transition && this.$element.hasClass('fade') ?
hideWithTransition.call(this) :
hideModal.call(this)
}
}
/* MODAL PRIVATE METHODS
* ===================== */
function hideWithTransition() {
var that = this
, timeout = setTimeout(function () {
that.$element.off($.support.transition.end)
hideModal.call(that)
}, 500)
this.$element.one($.support.transition.end, function () {
clearTimeout(timeout)
hideModal.call(that)
})
}
function hideModal(that) {
this.$element
.hide()
.trigger('hidden')
backdrop.call(this)
}
function backdrop(callback) {
var that = this
, animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
if (this.options.backdrop != 'static') {
this.$backdrop.click($.proxy(this.hide, this))
}
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
doAnimate ?
this.$backdrop.one($.support.transition.end, callback) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
$.support.transition && this.$element.hasClass('fade')?
this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
removeBackdrop.call(this)
} else if (callback) {
callback()
}
}
function removeBackdrop() {
this.$backdrop.remove()
this.$backdrop = null
}
function escape() {
var that = this
if (this.isShown && this.options.keyboard) {
$(document).on('keyup.dismiss.modal', function ( e ) {
e.which == 27 && that.hide()
})
} else if (!this.isShown) {
$(document).off('keyup.dismiss.modal')
}
}
/* MODAL PLUGIN DEFINITION
* ======================= */
$.fn.modal = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('modal')
, options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option]()
else if (options.show) data.show()
})
}
$.fn.modal.defaults = {
backdrop: true
, keyboard: true
, show: true
}
$.fn.modal.Constructor = Modal
/* MODAL DATA-API
* ============== */
$(function () {
$('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
var $this = $(this), href
, $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
, option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
e.preventDefault()
$target.modal(option)
})
})
}(window.jQuery);

808
static/ext/bootstrap/css/bootstrap-responsive.css vendored

@ -0,0 +1,808 @@
/*!
* Bootstrap Responsive v2.0.3
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.input-block-level {
display: block;
width: 100%;
min-height: 28px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.hidden {
display: none;
visibility: hidden;
}
.visible-phone {
display: none !important;
}
.visible-tablet {
display: none !important;
}
.hidden-desktop {
display: none !important;
}
@media (max-width: 767px) {
.visible-phone {
display: inherit !important;
}
.hidden-phone {
display: none !important;
}
.hidden-desktop {
display: inherit !important;
}
.visible-desktop {
display: none !important;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.visible-tablet {
display: inherit !important;
}
.hidden-tablet {
display: none !important;
}
.hidden-desktop {
display: inherit !important;
}
.visible-desktop {
display: none !important ;
}
}
@media (max-width: 480px) {
.nav-collapse {
-webkit-transform: translate3d(0, 0, 0);
}
.page-header h1 small {
display: block;
line-height: 18px;
}
input[type="checkbox"],
input[type="radio"] {
border: 1px solid #ccc;
}
.form-horizontal .control-group > label {
float: none;
width: auto;
padding-top: 0;
text-align: left;
}
.form-horizontal .controls {
margin-left: 0;
}
.form-horizontal .control-list {
padding-top: 0;
}
.form-horizontal .form-actions {
padding-right: 10px;
padding-left: 10px;
}
.modal {
position: absolute;
top: 10px;
right: 10px;
left: 10px;
width: auto;
margin: 0;
}
.modal.fade.in {
top: auto;
}
.modal-header .close {
padding: 10px;
margin: -10px;
}
.carousel-caption {
position: static;
}
}
@media (max-width: 767px) {
body {
padding-right: 20px;
padding-left: 20px;
}
.navbar-fixed-top,
.navbar-fixed-bottom {
margin-right: -20px;
margin-left: -20px;
}
.container-fluid {
padding: 0;
}
.dl-horizontal dt {
float: none;
width: auto;
clear: none;
text-align: left;
}
.dl-horizontal dd {
margin-left: 0;
}
.container {
width: auto;
}
.row-fluid {
width: 100%;
}
.row,
.thumbnails {
margin-left: 0;
}
[class*="span"],
.row-fluid [class*="span"] {
display: block;
float: none;
width: auto;
margin-left: 0;
}
.input-large,
.input-xlarge,
.input-xxlarge,
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
display: block;
width: 100%;
min-height: 28px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.input-prepend input,
.input-append input,
.input-prepend input[class*="span"],
.input-append input[class*="span"] {
display: inline-block;
width: auto;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.row {
margin-left: -20px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 20px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 724px;
}
.span12 {
width: 724px;
}
.span11 {
width: 662px;
}
.span10 {
width: 600px;
}
.span9 {
width: 538px;
}
.span8 {
width: 476px;
}
.span7 {
width: 414px;
}
.span6 {
width: 352px;
}
.span5 {
width: 290px;
}
.span4 {
width: 228px;
}
.span3 {
width: 166px;
}
.span2 {
width: 104px;
}
.span1 {
width: 42px;
}
.offset12 {
margin-left: 764px;
}
.offset11 {
margin-left: 702px;
}
.offset10 {
margin-left: 640px;
}
.offset9 {
margin-left: 578px;
}
.offset8 {
margin-left: 516px;
}
.offset7 {
margin-left: 454px;
}
.offset6 {
margin-left: 392px;
}
.offset5 {
margin-left: 330px;
}
.offset4 {
margin-left: 268px;
}
.offset3 {
margin-left: 206px;
}
.offset2 {
margin-left: 144px;
}
.offset1 {
margin-left: 82px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 28px;
margin-left: 2.762430939%;
*margin-left: 2.709239449638298%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .span12 {
width: 99.999999993%;
*width: 99.9468085036383%;
}
.row-fluid .span11 {
width: 91.436464082%;
*width: 91.38327259263829%;
}
.row-fluid .span10 {
width: 82.87292817100001%;
*width: 82.8197366816383%;
}
.row-fluid .span9 {
width: 74.30939226%;
*width: 74.25620077063829%;
}
.row-fluid .span8 {
width: 65.74585634900001%;
*width: 65.6926648596383%;
}
.row-fluid .span7 {
width: 57.182320438000005%;
*width: 57.129128948638304%;
}
.row-fluid .span6 {
width: 48.618784527%;
*width: 48.5655930376383%;
}
.row-fluid .span5 {
width: 40.055248616%;
*width: 40.0020571266383%;
}
.row-fluid .span4 {
width: 31.491712705%;
*width: 31.4385212156383%;
}
.row-fluid .span3 {
width: 22.928176794%;
*width: 22.874985304638297%;
}
.row-fluid .span2 {
width: 14.364640883%;
*width: 14.311449393638298%;
}
.row-fluid .span1 {
width: 5.801104972%;
*width: 5.747913482638298%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 714px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 652px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 590px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 528px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 466px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 404px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 342px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 280px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 218px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 156px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 94px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 32px;
}
}
@media (min-width: 1200px) {
.row {
margin-left: -30px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 30px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 1170px;
}
.span12 {
width: 1170px;
}
.span11 {
width: 1070px;
}
.span10 {
width: 970px;
}
.span9 {
width: 870px;
}
.span8 {
width: 770px;
}
.span7 {
width: 670px;
}
.span6 {
width: 570px;
}
.span5 {
width: 470px;
}
.span4 {
width: 370px;
}
.span3 {
width: 270px;
}
.span2 {
width: 170px;
}
.span1 {
width: 70px;
}
.offset12 {
margin-left: 1230px;
}
.offset11 {
margin-left: 1130px;
}
.offset10 {
margin-left: 1030px;
}
.offset9 {
margin-left: 930px;
}
.offset8 {
margin-left: 830px;
}
.offset7 {
margin-left: 730px;
}
.offset6 {
margin-left: 630px;
}
.offset5 {
margin-left: 530px;
}
.offset4 {
margin-left: 430px;
}
.offset3 {
margin-left: 330px;
}
.offset2 {
margin-left: 230px;
}
.offset1 {
margin-left: 130px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 28px;
margin-left: 2.564102564%;
*margin-left: 2.510911074638298%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .span12 {
width: 100%;
*width: 99.94680851063829%;
}
.row-fluid .span11 {
width: 91.45299145300001%;
*width: 91.3997999636383%;
}
.row-fluid .span10 {
width: 82.905982906%;
*width: 82.8527914166383%;
}
.row-fluid .span9 {
width: 74.358974359%;
*width: 74.30578286963829%;
}
.row-fluid .span8 {
width: 65.81196581200001%;
*width: 65.7587743226383%;
}
.row-fluid .span7 {
width: 57.264957265%;
*width: 57.2117657756383%;
}
.row-fluid .span6 {
width: 48.717948718%;
*width: 48.6647572286383%;
}
.row-fluid .span5 {
width: 40.170940171000005%;
*width: 40.117748681638304%;
}
.row-fluid .span4 {
width: 31.623931624%;
*width: 31.5707401346383%;
}
.row-fluid .span3 {
width: 23.076923077%;
*width: 23.0237315876383%;
}
.row-fluid .span2 {
width: 14.529914530000001%;
*width: 14.4767230406383%;
}
.row-fluid .span1 {
width: 5.982905983%;
*width: 5.929714493638298%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 1160px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 1060px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 960px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 860px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 760px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 660px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 560px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 460px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 360px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 260px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 160px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 60px;
}
.thumbnails {
margin-left: -30px;
}
.thumbnails > li {
margin-left: 30px;
}
.row-fluid .thumbnails {
margin-left: 0;
}
}
@media (max-width: 979px) {
body {
padding-top: 0;
}
.navbar-fixed-top {
position: static;
margin-bottom: 18px;
}
.navbar-fixed-top .navbar-inner {
padding: 5px;
}
.navbar .container <