Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- "use strict";
- /*
- // Capture the output of this into a variable, if you want
- (function(Module, args) {
- Module = Module || {};
- Module.arguments = args || [];
- */
- ///*
- // Runs much faster, for some reason
- if (!this['Module']) {
- this['Module'] = {};
- }
- if (!Module.arguments) {
- try {
- Module.arguments = scriptArgs;
- } catch(e) {
- try {
- Module.arguments = arguments;
- } catch(e) {
- Module.arguments = [];
- }
- }
- }
- //*/
- // === Auto-generated preamble library stuff ===
- //========================================
- // Runtime code shared with compiler
- //========================================
- var Runtime = {
- forceAlign: function (target, quantum) {
- quantum = quantum || 4;
- if (isNumber(target) && isNumber(quantum)) {
- return Math.ceil(target/quantum)*quantum;
- } else {
- return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum;
- }
- },
- isNumberType: function (type) {
- return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES;
- },
- isPointerType: function isPointerType(type) {
- return pointingLevels(type) > 0;
- },
- isStructType: function isStructType(type) {
- if (isPointerType(type)) return false;
- if (new RegExp(/^\[\d+\ x\ (.*)\]/g).test(type)) return true; // [15 x ?] blocks. Like structs
- // See comment in isStructPointerType()
- return !Runtime.isNumberType(type) && type[0] == '%';
- },
- INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0},
- FLOAT_TYPES: {"float":0,"double":0},
- or64: function (x, y) {
- var l = (x | 0) | (y | 0);
- var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
- return l + h;
- },
- and64: function (x, y) {
- var l = (x | 0) & (y | 0);
- var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
- return l + h;
- },
- xor64: function (x, y) {
- var l = (x | 0) ^ (y | 0);
- var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
- return l + h;
- },
- getNativeFieldSize: function getNativeFieldSize(type) {
- return Math.max(Runtime.getNativeTypeSize(type), 4);
- },
- getNativeTypeSize: function getNativeTypeSize(type) {
- if (4 == 1) return 1;
- var size = {
- '_i1': 1,
- '_i8': 1,
- '_i16': 2,
- '_i32': 4,
- '_i64': 8,
- "_float": 4,
- "_double": 8
- }['_'+type]; // add '_' since float&double confuse Closure compiler as keys.
- if (!size && type[type.length-1] == '*') {
- size = 4; // A pointer
- }
- return size;
- },
- dedup: function dedup(items, ident) {
- var seen = {};
- if (ident) {
- return items.filter(function(item) {
- if (seen[item[ident]]) return false;
- seen[item[ident]] = true;
- return true;
- });
- } else {
- return items.filter(function(item) {
- if (seen[item]) return false;
- seen[item] = true;
- return true;
- });
- }
- },
- set: function set() {
- var args = typeof arguments[0] === 'object' ? arguments[0] : arguments;
- var ret = {};
- for (var i = 0; i < args.length; i++) {
- ret[args[i]] = 0;
- }
- return ret;
- },
- calculateStructAlignment: function calculateStructAlignment(type) {
- type.flatSize = 0;
- type.alignSize = 0;
- var diffs = [];
- var prev = -1;
- type.flatIndexes = type.fields.map(function(field) {
- var size, alignSize;
- if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) {
- size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s.
- alignSize = size;
- } else if (Runtime.isStructType(field)) {
- size = Types.types[field].flatSize;
- alignSize = Types.types[field].alignSize;
- } else {
- dprint('Unclear type in struct: ' + field + ', in ' + type.name_);
- assert(0);
- }
- alignSize = type.packed ? 1 : Math.min(alignSize, 4);
- type.alignSize = Math.max(type.alignSize, alignSize);
- var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory
- type.flatSize = curr + size;
- if (prev >= 0) {
- diffs.push(curr-prev);
- }
- prev = curr;
- return curr;
- });
- type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize);
- if (diffs.length == 0) {
- type.flatFactor = type.flatSize;
- } else if (Runtime.dedup(diffs).length == 1) {
- type.flatFactor = diffs[0];
- }
- type.needsFlattening = (type.flatFactor != 1);
- return type.flatIndexes;
- },
- generateStructInfo: function (struct, typeName, offset) {
- var type, alignment;
- if (typeName) {
- offset = offset || 0;
- type = typeof Types === 'undefined' ? Runtime.typeInfo[typeName] : Types.types[typeName];
- if (!type) return null;
- if (!struct) struct = Types.structMetadata[typeName.replace(/.*\./, '')];
- if (!struct) return null;
- assert(type.fields.length === struct.length, 'Number of named fields must match the type for ' + typeName);
- alignment = type.flatIndexes;
- } else {
- var type = { fields: struct.map(function(item) { return item[0] }) };
- alignment = Runtime.calculateStructAlignment(type);
- }
- var ret = {
- __size__: type.flatSize
- };
- if (typeName) {
- struct.forEach(function(item, i) {
- if (typeof item === 'string') {
- ret[item] = alignment[i] + offset;
- } else {
- // embedded struct
- var key;
- for (var k in item) key = k;
- ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]);
- }
- });
- } else {
- struct.forEach(function(item, i) {
- ret[item[1]] = alignment[i];
- });
- }
- return ret;
- },
- stackAlloc: function stackAlloc(size) { var ret = STACKTOP; assert(size > 0, "Trying to allocate 0"); _memset(STACKTOP, 0, size); STACKTOP += size;STACKTOP = Math.ceil((STACKTOP)/4)*4;; assert(STACKTOP < STACK_ROOT + STACK_MAX, "Ran out of stack"); return ret; },
- staticAlloc: function staticAlloc(size) { var ret = STATICTOP; assert(size > 0, "Trying to allocate 0"); STATICTOP += size;STATICTOP = Math.ceil((STATICTOP)/4)*4;; return ret; },
- alignMemory: function alignMemory(size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 4))*(quantum ? quantum : 4);; return ret; },
- __dummy__: 0
- }
- var CorrectionsMonitor = {
- MAX_ALLOWED: 0, // XXX
- corrections: 0,
- sigs: {},
- note: function(type, succeed, sig) {
- if (!succeed) {
- this.corrections++;
- if (this.corrections >= this.MAX_ALLOWED) abort('\n\nToo many corrections!');
- }
- },
- print: function() {
- var items = [];
- for (var sig in this.sigs) {
- items.push({
- sig: sig,
- fails: this.sigs[sig][0],
- succeeds: this.sigs[sig][1],
- total: this.sigs[sig][0] + this.sigs[sig][1]
- });
- }
- items.sort(function(x, y) { return y.total - x.total; });
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- print(item.sig + ' : ' + item.total + ' hits, %' + (Math.floor(100*item.fails/item.total)) + ' failures');
- }
- }
- };
- function cRound(x) {
- return x >= 0 ? Math.floor(x) : Math.ceil(x);
- }
- //========================================
- // Runtime essentials
- //========================================
- var __globalConstructor__ = function globalConstructor() {
- };
- var __THREW__ = false; // Used in checking for thrown exceptions.
- var __ATEXIT__ = [];
- var ABORT = false;
- var undef = 0;
- function abort(text) {
- print(text + ':\n' + (new Error).stack);
- ABORT = true;
- throw "Assertion: " + text;
- }
- function assert(condition, text) {
- if (!condition) {
- abort('Assertion failed: ' + text);
- }
- }
- // Sets a value in memory in a dynamic way at run-time. Uses the
- // type data. This is the same as makeSetValue, except that
- // makeSetValue is done at compile-time and generates the needed
- // code then, whereas this function picks the right code at
- // run-time.
- function setValue(ptr, value, type) {
- if (type[type.length-1] === '*') type = 'i32'; // pointers are 32-bit
- switch(type) {
- case 'i1': HEAP[ptr]=value;; break;
- case 'i8': HEAP[ptr]=value;; break;
- case 'i16': HEAP[ptr]=value;; break;
- case 'i32': HEAP[ptr]=value;; break;
- case 'i64': HEAP[ptr]=value;; break;
- case 'float': HEAP[ptr]=value;; break;
- case 'double': HEAP[ptr]=value;; break;
- default: abort('invalid type for setValue: ' + type);
- }
- }
- // Parallel to setValue.
- function getValue(ptr, type) {
- if (type[type.length-1] === '*') type = 'i32'; // pointers are 32-bit
- switch(type) {
- case 'i1': return HEAP[ptr];
- case 'i8': return HEAP[ptr];
- case 'i16': return HEAP[ptr];
- case 'i32': return HEAP[ptr];
- case 'i64': return HEAP[ptr];
- case 'float': return HEAP[ptr];
- case 'double': return HEAP[ptr];
- default: abort('invalid type for setValue: ' + type);
- }
- return null;
- }
- // Allocates memory for some data and initializes it properly.
- var ALLOC_NORMAL = 0; // Tries to use _malloc()
- var ALLOC_STACK = 1; // Lives for the duration of the current function call
- var ALLOC_STATIC = 2; // Cannot be freed
- function allocate(slab, types, allocator) {
- var zeroinit, size;
- if (typeof slab === 'number') {
- zeroinit = true;
- size = slab;
- } else {
- zeroinit = false;
- size = slab.length;
- }
- var ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, 1));
- var singleType = typeof types === 'string' ? types : null;
- var i = 0, type;
- while (i < size) {
- var curr = zeroinit ? 0 : slab[i];
- if (typeof curr === 'function') {
- curr = Runtime.getFunctionIndex(curr);
- }
- type = singleType || types[i];
- if (type === 0) {
- i++;
- continue;
- }
- assert(type, 'Must know what type to store in allocate!');
- setValue(ret+i, curr, type);
- i += Runtime.getNativeTypeSize(type);
- }
- return ret;
- }
- Module['allocate'] = allocate;
- function Pointer_stringify(ptr) {
- var ret = "";
- var i = 0;
- var t;
- while (1) {
- t = String.fromCharCode(HEAP[ptr+i]);
- if (t == "\0") { break; } else {}
- ret += t;
- i += 1;
- }
- return ret;
- }
- function Array_stringify(array) {
- var ret = "";
- for (var i = 0; i < array.length; i++) {
- ret += String.fromCharCode(array[i]);
- }
- return ret;
- }
- // Memory management
- var PAGE_SIZE = 4096;
- function alignMemoryPage(x) {
- return Math.ceil(x/PAGE_SIZE)*PAGE_SIZE;
- }
- var HEAP;
- var STACK_ROOT, STACKTOP, STACK_MAX;
- var STATICTOP;
- var HAS_TYPED_ARRAYS = false;
- var TOTAL_MEMORY = 50*1024*1024;
- // Initialize the runtime's memory
- {
- // Without this optimization, Chrome is slow. Sadly, the constant here needs to be tweaked depending on the code being run...
- var FAST_MEMORY = TOTAL_MEMORY/32;
- HEAP = new Array(FAST_MEMORY);
- for (var i = 0; i < FAST_MEMORY; i++) {
- HEAP[i] = 0; // XXX We do *not* use {{| makeSetValue(0, 'i', 0, 'null') |}} here, since this is done just to optimize runtime speed
- }
- }
- var base = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)'
- // Also this ensures we leave 0 as an invalid address, 'NULL'
- for (var i = 0; i < base.length; i++) {
- HEAP[i]=base[i];
- }
- Module['HEAP'] = HEAP;
- STACK_ROOT = STACKTOP = alignMemoryPage(10);
- var TOTAL_STACK = 1024*1024; // XXX: Changing this value can lead to bad perf on v8!
- STACK_MAX = STACK_ROOT + TOTAL_STACK;
- STATICTOP = alignMemoryPage(STACK_MAX);
- function __shutdownRuntime__() {
- while(__ATEXIT__.length > 0) {
- var atexit = __ATEXIT__.pop();
- var func = atexit.func;
- if (typeof func === 'number') {
- func = FUNCTION_TABLE[func];
- }
- func(atexit.arg === undefined ? null : atexit.arg);
- }
- // allow browser to GC, set heaps to null?
- // Print summary of correction activity
- CorrectionsMonitor.print();
- }
- // Copies a list of num items on the HEAP into a
- // a normal JavaScript array of numbers
- function Array_copy(ptr, num) {
- // TODO: In the SAFE_HEAP case, do some reading here, for debugging purposes - currently this is an 'unnoticed read'.
- return HEAP.slice(ptr, ptr+num);
- }
- function String_len(ptr) {
- var i = 0;
- while (HEAP[ptr+i]) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds
- return i;
- }
- // Copies a C-style string, terminated by a zero, from the HEAP into
- // a normal JavaScript array of numbers
- function String_copy(ptr, addZero) {
- var len = String_len(ptr);
- if (addZero) len++;
- var ret = Array_copy(ptr, len);
- if (addZero) ret[len-1] = 0;
- return ret;
- }
- // Tools
- if (typeof print === 'undefined') {
- print = console.log; // we are on the web
- }
- // This processes a JS string into a C-line array of numbers, 0-terminated.
- // For LLVM-originating strings, see parser.js:parseLLVMString function
- function intArrayFromString(stringy, dontAddNull) {
- var ret = [];
- var t;
- var i = 0;
- while (i < stringy.length) {
- var chr = stringy.charCodeAt(i);
- if (chr > 0xFF) {
- assert(false, 'Character code ' + chr + ' (' + stringy[i] + ') at offset ' + i + ' not in 0x00-0xFF.');
- chr &= 0xFF;
- }
- ret.push(chr);
- i = i + 1;
- }
- if (!dontAddNull) {
- ret.push(0);
- }
- return ret;
- }
- Module['intArrayFromString'] = intArrayFromString;
- function intArrayToString(array) {
- var ret = [];
- for (var i = 0; i < array.length; i++) {
- var chr = array[i];
- if (chr > 0xFF) {
- assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
- chr &= 0xFF;
- }
- ret.push(String.fromCharCode(chr));
- }
- return ret.join('');
- }
- function unSign(value, bits, ignore, sig) {
- if (value >= 0) {
- return value;
- }
- return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
- : Math.pow(2, bits) + value;
- // TODO: clean up previous line
- }
- function reSign(value, bits, ignore, sig) {
- if (value <= 0) {
- return value;
- }
- var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
- : Math.pow(2, bits-1);
- if (value >= half) {
- value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
- }
- return value;
- }
- // === Body ===
- var $struct_data___SIZE = 8; // %struct.data
- var __str;
- var _memcpy=function _memcpy (dest, src, num, idunno) {
- assert(num % 1 === 0, 'memcpy given ' + num + ' bytes to copy. Problem with 4=1 corrections perhaps?');
- // || 0, since memcpy sometimes copies uninitialized areas XXX: Investigate why initializing alloc'ed memory does not fix that too
- for (var $mcpi$ = 0; $mcpi$ < num; $mcpi$++) {
- HEAP[dest+$mcpi$]=HEAP[src+$mcpi$];
- };
- };var _llvm_memcpy_p0i8_p0i8_i64=_memcpy;
- var ERRNO_CODES={"E2BIG":7,"EACCES":13,"EADDRINUSE":98,"EADDRNOTAVAIL":99,"EAFNOSUPPORT":97,"EAGAIN":11,"EALREADY":114,"EBADF":9,"EBADMSG":74,"EBUSY":16,"ECANCELED":125,"ECHILD":10,"ECONNABORTED":103,"ECONNREFUSED":111,"ECONNRESET":104,"EDEADLK":35,"EDESTADDRREQ":89,"EDOM":33,"EDQUOT":122,"EEXIST":17,"EFAULT":14,"EFBIG":27,"EHOSTUNREACH":113,"EIDRM":43,"EILSEQ":84,"EINPROGRESS":115,"EINTR":4,"EINVAL":22,"EIO":5,"EISCONN":106,"EISDIR":21,"ELOOP":40,"EMFILE":24,"EMLINK":31,"EMSGSIZE":90,"EMULTIHOP":72,"ENAMETOOLONG":36,"ENETDOWN":100,"ENETRESET":102,"ENETUNREACH":101,"ENFILE":23,"ENOBUFS":105,"ENODATA":61,"ENODEV":19,"ENOENT":2,"ENOEXEC":8,"ENOLCK":37,"ENOLINK":67,"ENOMEM":12,"ENOMSG":42,"ENOPROTOOPT":92,"ENOSPC":28,"ENOSR":63,"ENOSTR":60,"ENOSYS":38,"ENOTCONN":107,"ENOTDIR":20,"ENOTEMPTY":39,"ENOTRECOVERABLE":131,"ENOTSOCK":88,"ENOTSUP":95,"ENOTTY":25,"ENXIO":6,"EOVERFLOW":75,"EOWNERDEAD":130,"EPERM":1,"EPIPE":32,"EPROTO":71,"EPROTONOSUPPORT":93,"EPROTOTYPE":91,"ERANGE":34,"EROFS":30,"ESPIPE":29,"ESRCH":3,"ESTALE":116,"ETIME":62,"ETIMEDOUT":110,"ETXTBSY":26,"EWOULDBLOCK":11,"EXDEV":18};
- var ___setErrNo=function ___setErrNo (value) {
- // For convenient setting and returning of errno.
- var me = ___setErrNo;
- if (!me.ptr) me.ptr = allocate([0], 'i32', ALLOC_NORMAL);
- HEAP[me.ptr]=value;
- return value;
- };
- var _stdin=0;
- var _stdout=0;
- var _stderr=0;var FS={"root":{"read":true,"write":false,"isFolder":true,"isDevice":false,"timestamp":1312660155623,"inodeNumber":1,"contents":{}},"currentPath":"/","nextInode":2,"streams":[null],"ignorePermissions":true, absolutePath: function (relative, base) {
- if (typeof relative !== 'string') return null;
- if (base === undefined) base = FS.currentPath;
- if (relative && relative[0] == '/') base = '';
- var full = base + '/' + relative;
- var parts = full.split('/').reverse();
- var absolute = [''];
- while (parts.length) {
- var part = parts.pop();
- if (part == '' || part == '.') {
- // Nothing.
- } else if (part == '..') {
- if (absolute.length > 1) absolute.pop();
- } else {
- absolute.push(part);
- }
- }
- return absolute.length == 1 ? '/' : absolute.join('/');
- }, analyzePath: function (path, dontResolveLastLink, linksVisited) {
- var ret = {
- isRoot: false,
- exists: false,
- error: 0,
- name: null,
- path: null,
- object: null,
- parentExists: false,
- parentPath: null,
- parentObject: null
- };
- path = FS.absolutePath(path);
- if (path == '/') {
- ret.isRoot = true;
- ret.exists = ret.parentExists = true;
- ret.name = '/';
- ret.path = ret.parentPath = '/';
- ret.object = ret.parentObject = FS.root;
- } else if (path !== null) {
- linksVisited = linksVisited || 0;
- path = path.slice(1).split('/');
- var current = FS.root;
- var traversed = [''];
- while (path.length) {
- if (path.length == 1 && current.isFolder) {
- ret.parentExists = true;
- ret.parentPath = traversed.length == 1 ? '/' : traversed.join('/');
- ret.parentObject = current;
- ret.name = path[0];
- }
- var target = path.shift();
- if (!current.isFolder) {
- ret.error = ERRNO_CODES.ENOTDIR;
- break;
- } else if (!current.read) {
- ret.error = ERRNO_CODES.EACCES;
- break;
- } else if (!current.contents.hasOwnProperty(target)) {
- ret.error = ERRNO_CODES.ENOENT;
- break;
- }
- current = current.contents[target];
- if (current.link && !(dontResolveLastLink && path.length == 0)) {
- if (linksVisited > 40) { // Usual Linux SYMLOOP_MAX.
- ret.error = ERRNO_CODES.ELOOP;
- break;
- }
- var link = FS.absolutePath(current.link, traversed.join('/'));
- return FS.analyzePath([link].concat(path).join('/'),
- dontResolveLastLink, linksVisited + 1);
- }
- traversed.push(target);
- if (path.length == 0) {
- ret.exists = true;
- ret.path = traversed.join('/');
- ret.object = current;
- }
- }
- return ret;
- }
- return ret;
- }, findObject: function (path, dontResolveLastLink) {
- var ret = FS.analyzePath(path, dontResolveLastLink);
- if (ret.exists) {
- return ret.object;
- } else {
- ___setErrNo(ret.error);
- return null;
- }
- }, createObject: function (parent, name, properties, canRead, canWrite) {
- if (!parent) parent = '/';
- if (typeof parent === 'string') parent = FS.findObject(parent);
- if (!parent) {
- ___setErrNo(ERRNO_CODES.EACCES);
- throw new Error('Parent path must exist.');
- }
- if (!parent.isFolder) {
- ___setErrNo(ERRNO_CODES.ENOTDIR);
- throw new Error('Parent must be a folder.');
- }
- if (!parent.write && !FS.ignorePermissions) {
- ___setErrNo(ERRNO_CODES.EACCES);
- throw new Error('Parent folder must be writeable.');
- }
- if (!name || name == '.' || name == '..') {
- ___setErrNo(ERRNO_CODES.ENOENT);
- throw new Error('Name must not be empty.');
- }
- if (parent.contents.hasOwnProperty(name)) {
- ___setErrNo(ERRNO_CODES.EEXIST);
- throw new Error("Can't overwrite object.");
- }
- parent.contents[name] = {
- read: canRead === undefined ? true : canRead,
- write: canWrite === undefined ? false : canWrite,
- timestamp: Date.now(),
- inodeNumber: FS.nextInode++
- };
- for (var key in properties) {
- if (properties.hasOwnProperty(key)) {
- parent.contents[name][key] = properties[key];
- }
- }
- return parent.contents[name];
- }, createFolder: function (parent, name, canRead, canWrite) {
- var properties = {isFolder: true, isDevice: false, contents: {}};
- return FS.createObject(parent, name, properties, canRead, canWrite);
- }, createPath: function (parent, path, canRead, canWrite) {
- var current = FS.findObject(parent);
- if (current === null) throw new Error('Invalid parent.');
- path = path.split('/').reverse();
- while (path.length) {
- var part = path.pop();
- if (!part) continue;
- if (!current.contents.hasOwnProperty(part)) {
- FS.createFolder(current, part, canRead, canWrite);
- }
- current = current.contents[part];
- }
- return current;
- }, createFile: function (parent, name, properties, canRead, canWrite) {
- properties.isFolder = false;
- return FS.createObject(parent, name, properties, canRead, canWrite);
- }, createDataFile: function (parent, name, data, canRead, canWrite) {
- if (typeof data === 'string') {
- var dataArray = [];
- for (var i = 0; i < data.length; i++) dataArray.push(data.charCodeAt(i));
- data = dataArray;
- }
- var properties = {isDevice: false, contents: data};
- return FS.createFile(parent, name, properties, canRead, canWrite);
- }, createLazyFile: function (parent, name, url, canRead, canWrite) {
- var properties = {isDevice: false, url: url};
- return FS.createFile(parent, name, properties, canRead, canWrite);
- }, createLink: function (parent, name, target, canRead, canWrite) {
- var properties = {isDevice: false, link: target};
- return FS.createFile(parent, name, properties, canRead, canWrite);
- }, createDevice: function (parent, name, input, output) {
- if (!(input || output)) {
- throw new Error('A device must have at least one callback defined.');
- }
- var ops = {isDevice: true, input: input, output: output};
- return FS.createFile(parent, name, ops, Boolean(input), Boolean(output));
- }, forceLoadFile: function (obj) {
- if (obj.isDevice || obj.isFolder || obj.link ||
- 'contents' in obj) return true;
- var success = true;
- if (typeof XMLHttpRequest !== 'undefined') {
- // Browser.
- // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
- var xhr = new XMLHttpRequest();
- xhr.open('GET', obj.url, false);
- xhr.responseType = 'arraybuffer'; // hint to the browser that we want binary data
- xhr.overrideMimeType('text/plain; charset=x-user-defined'); // another hint
- xhr.send(null);
- if (xhr.status != 200 && xhr.status != 0) success = false;
- if (xhr.response !== undefined) {
- obj.contents = new Uint8Array(xhr.response || []);
- } else {
- obj.contents = intArrayFromString(xhr.responseText || '', true);
- }
- } else if (typeof read !== 'undefined') {
- // Command-line.
- try {
- // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
- // read() will try to parse UTF8.
- obj.contents = intArrayFromString(read(obj.url), true);
- } catch (e) {
- success = false;
- }
- } else {
- throw new Error('Cannot load without read() or XMLHttpRequest.');
- }
- if (!success) ___setErrNo(ERRNO_CODES.EIO);
- return success;
- }, init: function (input, output, error) {
- // Make sure we initialize only once.
- if (FS.init.initialized) return;
- else FS.init.initialized = true;
- // Default handlers.
- if (!input) input = function() {
- if (!input.cache || !input.cache.length) {
- var result;
- if (window && typeof window.prompt == 'function') {
- // Browser.
- result = window.prompt('Input: ');
- } else if (typeof readline == 'function') {
- // Command line.
- result = readline();
- }
- if (!result) return null;
- input.cache = intArrayFromString(result + '\n', true);
- }
- return input.cache.shift();
- };
- if (!output) output = function(val) {
- if (!output.printer) {
- if (typeof print == 'function') {
- // Either console or custom print function defined.
- output.printer = print;
- } else if (console && typeof console.log == 'function') {
- // Browser-like environment with a console.
- output.printer = console.log;
- } else {
- // Fallback to a harmless no-op.
- output.printer = function() {};
- }
- }
- if (!output.buffer) output.buffer = [];
- if (val === null || val === '\n'.charCodeAt(0)) {
- output.printer(output.buffer.join(''));
- output.buffer = [];
- } else {
- output.buffer.push(String.fromCharCode(val));
- }
- };
- if (!error) error = output;
- // Create the temporary folder.
- FS.createFolder('/', 'tmp', true, true);
- // Create the I/O devices.
- var devFolder = FS.createFolder('/', 'dev', true, false);
- var stdin = FS.createDevice(devFolder, 'stdin', input);
- var stdout = FS.createDevice(devFolder, 'stdout', null, output);
- var stderr = FS.createDevice(devFolder, 'stderr', null, error);
- FS.createDevice(devFolder, 'tty', input, output);
- // Create default streams.
- FS.streams[1] = {
- path: '/dev/stdin',
- object: stdin,
- position: 0,
- isRead: true,
- isWrite: false,
- isAppend: false,
- error: false,
- eof: false,
- ungotten: []
- };
- FS.streams[2] = {
- path: '/dev/stdout',
- object: stdout,
- position: 0,
- isRead: false,
- isWrite: true,
- isAppend: false,
- error: false,
- eof: false,
- ungotten: []
- };
- FS.streams[3] = {
- path: '/dev/stderr',
- object: stderr,
- position: 0,
- isRead: false,
- isWrite: true,
- isAppend: false,
- error: false,
- eof: false,
- ungotten: []
- };
- _stdin = allocate([1], 'void*', ALLOC_STATIC);
- _stdout = allocate([2], 'void*', ALLOC_STATIC);
- _stderr = allocate([3], 'void*', ALLOC_STATIC);
- // Once initialized, permissions start having effect.
- FS.ignorePermissions = false;
- } };
- var _pwrite=function _pwrite (fildes, buf, nbyte, offset) {
- // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html
- var stream = FS.streams[fildes];
- if (!stream || stream.object.isDevice) {
- ___setErrNo(ERRNO_CODES.EBADF);
- return -1;
- } else if (!stream.isWrite) {
- ___setErrNo(ERRNO_CODES.EACCES);
- return -1;
- } else if (stream.object.isFolder) {
- ___setErrNo(ERRNO_CODES.EISDIR);
- return -1;
- } else if (nbyte < 0 || offset < 0) {
- ___setErrNo(ERRNO_CODES.EINVAL);
- return -1;
- } else {
- var contents = stream.object.contents;
- while (contents.length < offset) contents.push(0);
- for (var i = 0; i < nbyte; i++) {
- contents[offset + i] = HEAP[buf+i];
- }
- stream.object.timestamp = Date.now();
- return i;
- }
- };var _write=function _write (fildes, buf, nbyte) {
- // ssize_t write(int fildes, const void *buf, size_t nbyte);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html
- var stream = FS.streams[fildes];
- if (!stream) {
- ___setErrNo(ERRNO_CODES.EBADF);
- return -1;
- } else if (!stream.isWrite) {
- ___setErrNo(ERRNO_CODES.EACCES);
- return -1;
- } else if (nbyte < 0) {
- ___setErrNo(ERRNO_CODES.EINVAL);
- return -1;
- } else {
- if (stream.object.isDevice) {
- if (stream.object.output) {
- for (var i = 0; i < nbyte; i++) {
- try {
- stream.object.output(HEAP[buf+i]);
- } catch (e) {
- ___setErrNo(ERRNO_CODES.EIO);
- return -1;
- }
- }
- stream.object.timestamp = Date.now();
- return i;
- } else {
- ___setErrNo(ERRNO_CODES.ENXIO);
- return -1;
- }
- } else {
- var bytesWritten = _pwrite(fildes, buf, nbyte, stream.position);
- if (bytesWritten != -1) stream.position += bytesWritten;
- return bytesWritten;
- }
- }
- };var _fwrite=function _fwrite (ptr, size, nitems, stream) {
- // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html
- var bytesToWrite = nitems * size;
- if (bytesToWrite == 0) return 0;
- var bytesWritten = _write(stream, ptr, bytesToWrite);
- if (bytesWritten == -1) {
- if (FS.streams[stream]) FS.streams[stream].error = true;
- return -1;
- } else {
- return Math.floor(bytesWritten / size);
- }
- };
- var __formatString=function __formatString (isVarArgs, format/*, ...*/) {
- var textIndex = format;
- var argIndex = 0;
- var getNextArg;
- if (isVarArgs) {
- var varArgStart = arguments[2];
- getNextArg = function(type) {
- var ret;
- if (type === 'double') {
- ret = HEAP[varArgStart+argIndex];
- } else if (type === 'float') {
- ret = HEAP[varArgStart+argIndex];
- } else if (type === 'i64') {
- ret = HEAP[varArgStart+argIndex];
- } else if (type === 'i32') {
- ret = HEAP[varArgStart+argIndex];
- } else if (type === 'i16') {
- ret = HEAP[varArgStart+argIndex];
- } else if (type === 'i8') {
- ret = HEAP[varArgStart+argIndex];
- } else if (type[type.length - 1] === '*') {
- ret = HEAP[varArgStart+argIndex];
- } else {
- throw new Error('Unknown formatString argument type: ' + type);
- }
- argIndex += Runtime.getNativeFieldSize(type);
- return Number(ret);
- };
- } else {
- var args = arguments;
- getNextArg = function() {
- return Number(args[2 + argIndex++]);
- };
- }
- var ret = [];
- var curr, next, currArg;
- while(1) {
- var startTextIndex = textIndex;
- curr = HEAP[textIndex];
- if (curr === 0) break;
- next = HEAP[textIndex+1];
- if (curr == '%'.charCodeAt(0)) {
- // Handle flags.
- var flagAlwaysSigned = false;
- var flagLeftAlign = false;
- var flagAlternative = false;
- var flagZeroPad = false;
- flagsLoop: while (1) {
- switch (next) {
- case '+'.charCodeAt(0):
- flagAlwaysSigned = true;
- break;
- case '-'.charCodeAt(0):
- flagLeftAlign = true;
- break;
- case '#'.charCodeAt(0):
- flagAlternative = true;
- break;
- case '0'.charCodeAt(0):
- if (flagZeroPad) {
- break flagsLoop;
- } else {
- flagZeroPad = true;
- break;
- }
- default:
- break flagsLoop;
- }
- textIndex++;
- next = HEAP[textIndex+1];
- }
- // Handle width.
- var width = 0;
- if (next == '*'.charCodeAt(0)) {
- width = getNextArg('i32');
- textIndex++;
- next = HEAP[textIndex+1];
- } else {
- while (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) {
- width = width * 10 + (next - '0'.charCodeAt(0));
- textIndex++;
- next = HEAP[textIndex+1];
- }
- }
- // Handle precision.
- var precisionSet = false;
- if (next == '.'.charCodeAt(0)) {
- var precision = 0;
- precisionSet = true;
- textIndex++;
- next = HEAP[textIndex+1];
- if (next == '*'.charCodeAt(0)) {
- precision = getNextArg('i32');
- textIndex++;
- } else {
- while(1) {
- var precisionChr = HEAP[textIndex+1];
- if (precisionChr < '0'.charCodeAt(0) ||
- precisionChr > '9'.charCodeAt(0)) break;
- precision = precision * 10 + (precisionChr - '0'.charCodeAt(0));
- textIndex++;
- }
- }
- next = HEAP[textIndex+1];
- } else {
- var precision = 6; // Standard default.
- }
- // Handle integer sizes. WARNING: These assume a 32-bit architecture!
- var argSize;
- switch (String.fromCharCode(next)) {
- case 'h':
- var nextNext = HEAP[textIndex+2];
- if (nextNext == 'h'.charCodeAt(0)) {
- textIndex++;
- argSize = 1; // char
- } else {
- argSize = 2; // short
- }
- break;
- case 'l':
- var nextNext = HEAP[textIndex+2];
- if (nextNext == 'l'.charCodeAt(0)) {
- textIndex++;
- argSize = 8; // long long
- } else {
- argSize = 4; // long
- }
- break;
- case 'L': // long long
- case 'q': // int64_t
- case 'j': // intmax_t
- argSize = 8;
- break;
- case 'z': // size_t
- case 't': // ptrdiff_t
- case 'I': // signed ptrdiff_t or unsigned size_t
- argSize = 4;
- break;
- default:
- argSize = undefined;
- }
- if (argSize !== undefined) textIndex++;
- next = HEAP[textIndex+1];
- // Handle type specifier.
- if (['d', 'i', 'u', 'o', 'x', 'X', 'p'].indexOf(String.fromCharCode(next)) != -1) {
- // Integer.
- var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
- argSize = argSize || 4;
- var currArg = getNextArg('i' + (argSize * 8));
- // Truncate to requested size.
- if (argSize <= 4) {
- var limit = Math.pow(256, argSize) - 1;
- currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
- }
- // Format the number.
- var currAbsArg = Math.abs(currArg);
- var argText;
- var prefix = '';
- if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) {
- argText = currAbsArg.toString(10);
- } else if (next == 'u'.charCodeAt(0)) {
- argText = unSign(currArg, 8 * argSize).toString(10);
- currArg = Math.abs(currArg);
- } else if (next == 'o'.charCodeAt(0)) {
- argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8);
- } else if (next == 'x'.charCodeAt(0) || next == 'X'.charCodeAt(0)) {
- prefix = flagAlternative ? '0x' : '';
- if (currArg < 0) {
- // Represent negative numbers in hex as 2's complement.
- currArg = -currArg;
- argText = (currAbsArg - 1).toString(16);
- var buffer = [];
- for (var i = 0; i < argText.length; i++) {
- buffer.push((0xF - parseInt(argText[i], 16)).toString(16));
- }
- argText = buffer.join('');
- while (argText.length < argSize * 2) argText = 'f' + argText;
- } else {
- argText = currAbsArg.toString(16);
- }
- if (next == 'X'.charCodeAt(0)) {
- prefix = prefix.toUpperCase();
- argText = argText.toUpperCase();
- }
- } else if (next == 'p'.charCodeAt(0)) {
- if (currAbsArg === 0) {
- argText = '(nil)';
- } else {
- prefix = '0x';
- argText = currAbsArg.toString(16);
- }
- }
- if (precisionSet) {
- while (argText.length < precision) {
- argText = '0' + argText;
- }
- }
- // Add sign.
- if (currArg < 0) {
- prefix = '-' + prefix;
- } else if (flagAlwaysSigned) {
- prefix = '+' + prefix;
- }
- // Add padding.
- while (prefix.length + argText.length < width) {
- if (flagLeftAlign) {
- argText += ' ';
- } else {
- if (flagZeroPad) {
- argText = '0' + argText;
- } else {
- prefix = ' ' + prefix;
- }
- }
- }
- // Insert the result into the buffer.
- argText = prefix + argText;
- argText.split('').forEach(function(chr) {
- ret.push(chr.charCodeAt(0));
- });
- } else if (['f', 'F', 'e', 'E', 'g', 'G'].indexOf(String.fromCharCode(next)) != -1) {
- // Float.
- var currArg = getNextArg(argSize === 4 ? 'float' : 'double');
- var argText;
- if (isNaN(currArg)) {
- argText = 'nan';
- flagZeroPad = false;
- } else if (!isFinite(currArg)) {
- argText = (currArg < 0 ? '-' : '') + 'inf';
- flagZeroPad = false;
- } else {
- var isGeneral = false;
- var effectivePrecision = Math.min(precision, 20);
- // Convert g/G to f/F or e/E, as per:
- // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
- if (next == 'g'.charCodeAt(0) || next == 'G'.charCodeAt(0)) {
- isGeneral = true;
- precision = precision || 1;
- var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10);
- if (precision > exponent && exponent >= -4) {
- next = ((next == 'g'.charCodeAt(0)) ? 'f' : 'F').charCodeAt(0);
- precision -= exponent + 1;
- } else {
- next = ((next == 'g'.charCodeAt(0)) ? 'e' : 'E').charCodeAt(0);
- precision--;
- }
- effectivePrecision = Math.min(precision, 20);
- }
- if (next == 'e'.charCodeAt(0) || next == 'E'.charCodeAt(0)) {
- argText = currArg.toExponential(effectivePrecision);
- // Make sure the exponent has at least 2 digits.
- if (/[eE][-+]\d$/.test(argText)) {
- argText = argText.slice(0, -1) + '0' + argText.slice(-1);
- }
- } else if (next == 'f'.charCodeAt(0) || next == 'F'.charCodeAt(0)) {
- argText = currArg.toFixed(effectivePrecision);
- }
- var parts = argText.split('e');
- if (isGeneral && !flagAlternative) {
- // Discard trailing zeros and periods.
- while (parts[0].length > 1 && parts[0].indexOf('.') != -1 &&
- (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) {
- parts[0] = parts[0].slice(0, -1);
- }
- } else {
- // Make sure we have a period in alternative mode.
- if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.';
- // Zero pad until required precision.
- while (precision > effectivePrecision++) parts[0] += '0';
- }
- argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : '');
- // Capitalize 'E' if needed.
- if (next == 'E'.charCodeAt(0)) argText = argText.toUpperCase();
- // Add sign.
- if (flagAlwaysSigned && currArg >= 0) {
- argText = '+' + argText;
- }
- }
- // Add padding.
- while (argText.length < width) {
- if (flagLeftAlign) {
- argText += ' ';
- } else {
- if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) {
- argText = argText[0] + '0' + argText.slice(1);
- } else {
- argText = (flagZeroPad ? '0' : ' ') + argText;
- }
- }
- }
- // Adjust case.
- if (next < 'a'.charCodeAt(0)) argText = argText.toUpperCase();
- // Insert the result into the buffer.
- argText.split('').forEach(function(chr) {
- ret.push(chr.charCodeAt(0));
- });
- } else if (next == 's'.charCodeAt(0)) {
- // String.
- var arg = getNextArg('i8*');
- var copiedString;
- if (arg) {
- copiedString = String_copy(arg);
- if (precisionSet && copiedString.length > precision) {
- copiedString = copiedString.slice(0, precision);
- }
- } else {
- copiedString = intArrayFromString('(null)', true);
- }
- if (!flagLeftAlign) {
- while (copiedString.length < width--) {
- ret.push(' '.charCodeAt(0));
- }
- }
- ret = ret.concat(copiedString);
- if (flagLeftAlign) {
- while (copiedString.length < width--) {
- ret.push(' '.charCodeAt(0));
- }
- }
- } else if (next == 'c'.charCodeAt(0)) {
- // Character.
- if (flagLeftAlign) ret.push(getNextArg('i8'));
- while (--width > 0) {
- ret.push(' '.charCodeAt(0));
- }
- if (!flagLeftAlign) ret.push(getNextArg('i8'));
- } else if (next == 'n'.charCodeAt(0)) {
- // Write the length written so far to the next parameter.
- var ptr = getNextArg('i32*');
- HEAP[ptr]=ret.length;
- } else if (next == '%'.charCodeAt(0)) {
- // Literal percent sign.
- ret.push(curr);
- } else {
- // Unknown specifiers remain untouched.
- for (var i = startTextIndex; i < textIndex + 2; i++) {
- ret.push(HEAP[i]);
- }
- }
- textIndex += 2;
- // TODO: Support a/A (hex float) and m (last error) specifiers.
- // TODO: Support %1${specifier} for arg selection.
- } else {
- ret.push(curr);
- textIndex += 1;
- }
- }
- return ret;
- };var _fprintf=function _fprintf (stream, format/*, ... */) {
- // int fprintf(FILE *restrict stream, const char *restrict format, ...);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
- var args = Array.prototype.slice.call(arguments, 1);
- args.unshift(false);
- var result = __formatString.apply(null, args);
- var buffer = allocate(result, 'i8', ALLOC_NORMAL);
- var ret = _fwrite(buffer, 1, result.length, stream);
- _free(buffer);
- return ret;
- };var _printf=function _printf (format/*, ... */) {
- // int printf(const char *restrict format, ...);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
- var args = Array.prototype.slice.call(arguments, 0);
- args.unshift(HEAP[_stdout]);
- return _fprintf.apply(null, args);
- };
- var _memset=function _memset (ptr, value, num) {
- for (var $mspi$ = 0; $mspi$ < num; $mspi$++) {
- HEAP[ptr+$mspi$]=value;;
- }
- };
- var _malloc=function staticAlloc(size) { var ret = STATICTOP; assert(size > 0, "Trying to allocate 0"); STATICTOP += size;STATICTOP = Math.ceil((STATICTOP)/4)*4;; return ret; };
- var _free=function _free (){};
- function _f($x, $y) {
- var __stackBase__ = STACKTOP; STACKTOP += 24; assert(STACKTOP < STACK_MAX); _memset(__stackBase__, 0, 24);
- var __label__;
- var $1=__stackBase__;
- var $2=__stackBase__+8;
- var $3=__stackBase__+12;
- var $tmp=__stackBase__+16;
- HEAP[$2]=$x;
- HEAP[$3]=$y;
- var $4=HEAP[$2];
- var $5=(($tmp)&4294967295);
- HEAP[$5]=$4;
- var $6=HEAP[$3];
- var $7=(($tmp+4)&4294967295);
- HEAP[$7]=$6;
- var $8=$1;
- var $9=$tmp;
- _llvm_memcpy_p0i8_p0i8_i64($8, $9, 8, 4, 0);
- var $10=$1;
- var $11=HEAP[$10];
- STACKTOP = __stackBase__;
- return $11;
- }
- function _main() {
- var __stackBase__ = STACKTOP; STACKTOP += 12; assert(STACKTOP < STACK_MAX); _memset(__stackBase__, 0, 12);
- var __label__;
- var $1=__stackBase__;
- var $d=__stackBase__+4;
- HEAP[$1]=0;
- var $2=_f(5, 6);
- var $3=$d;
- HEAP[$3]=$2;
- var $4=(($d)&4294967295);
- var $5=HEAP[$4];
- var $6=(($d+4)&4294967295);
- var $7=HEAP[$6];
- var $8=_printf(((__str)&4294967295), $5, $7);
- var $9=HEAP[$1];
- STACKTOP = __stackBase__;
- return $9;
- }
- Module["_main"] = _main;
- var FUNCTION_TABLE = [0,0];
- // === Auto-generated postamble setup entry stuff ===
- Module.callMain = function callMain(args) {
- var argc = args.length+1;
- function pad() {
- for (var i = 0; i < 4-1; i++) {
- argv.push(0);
- }
- }
- var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_STATIC) ];
- pad();
- for (var i = 0; i < argc-1; i = i + 1) {
- argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_STATIC));
- pad();
- }
- argv.push(0);
- argv = allocate(argv, 'i32', ALLOC_STATIC);
- return _main(argc, argv, 0);
- }
- function run(args) {
- args = args || Module['arguments'];
- __str=allocate([37,100,32,37,100,10,0] /* %d %d\0A\00 */, "i8", ALLOC_STATIC);
- FS.init();
- __globalConstructor__();
- var ret = null;
- if (Module['_main']) {
- ret = Module.callMain(args);
- __shutdownRuntime__();
- }
- return ret;
- }
- Module['run'] = run;
- // {{PRE_RUN_ADDITIONS}}
- if (!Module['noInitialRun']) {
- run();
- }
- // {{POST_RUN_ADDITIONS}}
- // {{MODULE_ADDITIONS}}
- /*
- return Module;
- }).call(this, {}, arguments); // Replace parameters as needed
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement