Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / simple / float-mm.c.js
1 // The Module object: Our interface to the outside world. We import
2 // and export values on it, and do the work to get that through
3 // closure compiler if necessary. There are various ways Module can be used:
4 // 1. Not defined. We create it here
5 // 2. A function parameter, function(Module) { ..generated code.. }
6 // 3. pre-run appended it, var Module = {}; ..generated code..
7 // 4. External script tag defines var Module.
8 // We need to do an eval in order to handle the closure compiler
9 // case, where this code here is minified but Module was defined
10 // elsewhere (e.g. case 4 above). We also need to check if Module
11 // already exists (e.g. case 3 above).
12 // Note that if you want to run closure, and also to use Module
13 // after the generated code, you will need to define   var Module = {};
14 // before the code. Then that object will be used in the code, and you
15 // can continue to use Module afterwards as well.
16 function run() {
17
18 var Module;
19 if (!Module) Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()');
20
21 // Sometimes an existing Module object exists with properties
22 // meant to overwrite the default module functionality. Here
23 // we collect those properties and reapply _after_ we configure
24 // the current environment's defaults to avoid having to be so
25 // defensive during initialization.
26 var moduleOverrides = {};
27 for (var key in Module) {
28   if (Module.hasOwnProperty(key)) {
29     moduleOverrides[key] = Module[key];
30   }
31 }
32
33 // The environment setup code below is customized to use Module.
34 // *** Environment setup code ***
35 var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
36 var ENVIRONMENT_IS_WEB = typeof window === 'object';
37 var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
38 var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
39
40 if (ENVIRONMENT_IS_NODE) {
41   // Expose functionality in the same simple way that the shells work
42   // Note that we pollute the global namespace here, otherwise we break in node
43   if (!Module['print']) Module['print'] = function print(x) {
44     process['stdout'].write(x + '\n');
45   };
46   if (!Module['printErr']) Module['printErr'] = function printErr(x) {
47     process['stderr'].write(x + '\n');
48   };
49
50   var nodeFS = require('fs');
51   var nodePath = require('path');
52
53   Module['read'] = function read(filename, binary) {
54     filename = nodePath['normalize'](filename);
55     var ret = nodeFS['readFileSync'](filename);
56     // The path is absolute if the normalized version is the same as the resolved.
57     if (!ret && filename != nodePath['resolve'](filename)) {
58       filename = path.join(__dirname, '..', 'src', filename);
59       ret = nodeFS['readFileSync'](filename);
60     }
61     if (ret && !binary) ret = ret.toString();
62     return ret;
63   };
64
65   Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) };
66
67   Module['load'] = function load(f) {
68     globalEval(read(f));
69   };
70
71   Module['arguments'] = process['argv'].slice(2);
72
73   module['exports'] = Module;
74 }
75 else if (ENVIRONMENT_IS_SHELL) {
76   if (!Module['print']) Module['print'] = print;
77   if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm
78
79   if (typeof read != 'undefined') {
80     Module['read'] = read;
81   } else {
82     Module['read'] = function read() { throw 'no read() available (jsc?)' };
83   }
84
85   Module['readBinary'] = function readBinary(f) {
86     return read(f, 'binary');
87   };
88
89   if (typeof scriptArgs != 'undefined') {
90     Module['arguments'] = scriptArgs;
91   } else if (typeof arguments != 'undefined') {
92     Module['arguments'] = arguments;
93   }
94
95   this['Module'] = Module;
96
97   eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly)
98 }
99 else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
100   Module['read'] = function read(url) {
101     var xhr = new XMLHttpRequest();
102     xhr.open('GET', url, false);
103     xhr.send(null);
104     return xhr.responseText;
105   };
106
107   if (typeof arguments != 'undefined') {
108     Module['arguments'] = arguments;
109   }
110
111   if (typeof console !== 'undefined') {
112     if (!Module['print']) Module['print'] = function print(x) {
113       console.log(x);
114     };
115     if (!Module['printErr']) Module['printErr'] = function printErr(x) {
116       console.log(x);
117     };
118   } else {
119     // Probably a worker, and without console.log. We can do very little here...
120     var TRY_USE_DUMP = false;
121     if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) {
122       dump(x);
123     }) : (function(x) {
124       // self.postMessage(x); // enable this if you want stdout to be sent as messages
125     }));
126   }
127
128   if (ENVIRONMENT_IS_WEB) {
129     this['Module'] = Module;
130   } else {
131     Module['load'] = importScripts;
132   }
133 }
134 else {
135   // Unreachable because SHELL is dependant on the others
136   throw 'Unknown runtime environment. Where are we?';
137 }
138
139 function globalEval(x) {
140   eval.call(null, x);
141 }
142 if (!Module['load'] == 'undefined' && Module['read']) {
143   Module['load'] = function load(f) {
144     globalEval(Module['read'](f));
145   };
146 }
147 if (!Module['print']) {
148   Module['print'] = function(){};
149 }
150 if (!Module['printErr']) {
151   Module['printErr'] = Module['print'];
152 }
153 if (!Module['arguments']) {
154   Module['arguments'] = [];
155 }
156 // *** Environment setup code ***
157
158 // Closure helpers
159 Module.print = Module['print'];
160 Module.printErr = Module['printErr'];
161
162 // Callbacks
163 Module['preRun'] = [];
164 Module['postRun'] = [];
165
166 // Merge back in the overrides
167 for (var key in moduleOverrides) {
168   if (moduleOverrides.hasOwnProperty(key)) {
169     Module[key] = moduleOverrides[key];
170   }
171 }
172
173
174
175 // === Auto-generated preamble library stuff ===
176
177 //========================================
178 // Runtime code shared with compiler
179 //========================================
180
181 var Runtime = {
182   stackSave: function () {
183     return STACKTOP;
184   },
185   stackRestore: function (stackTop) {
186     STACKTOP = stackTop;
187   },
188   forceAlign: function (target, quantum) {
189     quantum = quantum || 4;
190     if (quantum == 1) return target;
191     if (isNumber(target) && isNumber(quantum)) {
192       return Math.ceil(target/quantum)*quantum;
193     } else if (isNumber(quantum) && isPowerOfTwo(quantum)) {
194       return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')';
195     }
196     return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum;
197   },
198   isNumberType: function (type) {
199     return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES;
200   },
201   isPointerType: function isPointerType(type) {
202   return type[type.length-1] == '*';
203 },
204   isStructType: function isStructType(type) {
205   if (isPointerType(type)) return false;
206   if (isArrayType(type)) return true;
207   if (/<?\{ ?[^}]* ?\}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
208   // See comment in isStructPointerType()
209   return type[0] == '%';
210 },
211   INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0},
212   FLOAT_TYPES: {"float":0,"double":0},
213   or64: function (x, y) {
214     var l = (x | 0) | (y | 0);
215     var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
216     return l + h;
217   },
218   and64: function (x, y) {
219     var l = (x | 0) & (y | 0);
220     var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
221     return l + h;
222   },
223   xor64: function (x, y) {
224     var l = (x | 0) ^ (y | 0);
225     var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
226     return l + h;
227   },
228   getNativeTypeSize: function (type) {
229     switch (type) {
230       case 'i1': case 'i8': return 1;
231       case 'i16': return 2;
232       case 'i32': return 4;
233       case 'i64': return 8;
234       case 'float': return 4;
235       case 'double': return 8;
236       default: {
237         if (type[type.length-1] === '*') {
238           return Runtime.QUANTUM_SIZE; // A pointer
239         } else if (type[0] === 'i') {
240           var bits = parseInt(type.substr(1));
241           assert(bits % 8 === 0);
242           return bits/8;
243         } else {
244           return 0;
245         }
246       }
247     }
248   },
249   getNativeFieldSize: function (type) {
250     return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
251   },
252   dedup: function dedup(items, ident) {
253   var seen = {};
254   if (ident) {
255     return items.filter(function(item) {
256       if (seen[item[ident]]) return false;
257       seen[item[ident]] = true;
258       return true;
259     });
260   } else {
261     return items.filter(function(item) {
262       if (seen[item]) return false;
263       seen[item] = true;
264       return true;
265     });
266   }
267 },
268   set: function set() {
269   var args = typeof arguments[0] === 'object' ? arguments[0] : arguments;
270   var ret = {};
271   for (var i = 0; i < args.length; i++) {
272     ret[args[i]] = 0;
273   }
274   return ret;
275 },
276   STACK_ALIGN: 8,
277   getAlignSize: function (type, size, vararg) {
278     // we align i64s and doubles on 64-bit boundaries, unlike x86
279     if (!vararg && (type == 'i64' || type == 'double')) return 8;
280     if (!type) return Math.min(size, 8); // align structures internally to 64 bits
281     return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
282   },
283   calculateStructAlignment: function calculateStructAlignment(type) {
284     type.flatSize = 0;
285     type.alignSize = 0;
286     var diffs = [];
287     var prev = -1;
288     var index = 0;
289     type.flatIndexes = type.fields.map(function(field) {
290       index++;
291       var size, alignSize;
292       if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) {
293         size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s.
294         alignSize = Runtime.getAlignSize(field, size);
295       } else if (Runtime.isStructType(field)) {
296         if (field[1] === '0') {
297           // this is [0 x something]. When inside another structure like here, it must be at the end,
298           // and it adds no size
299           // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!');
300           size = 0;
301           if (Types.types[field]) {
302             alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
303           } else {
304             alignSize = type.alignSize || QUANTUM_SIZE;
305           }
306         } else {
307           size = Types.types[field].flatSize;
308           alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
309         }
310       } else if (field[0] == 'b') {
311         // bN, large number field, like a [N x i8]
312         size = field.substr(1)|0;
313         alignSize = 1;
314       } else if (field[0] === '<') {
315         // vector type
316         size = alignSize = Types.types[field].flatSize; // fully aligned
317       } else if (field[0] === 'i') {
318         // illegal integer field, that could not be legalized because it is an internal structure field
319         // it is ok to have such fields, if we just use them as markers of field size and nothing more complex
320         size = alignSize = parseInt(field.substr(1))/8;
321         assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field);
322       } else {
323         assert(false, 'invalid type for calculateStructAlignment');
324       }
325       if (type.packed) alignSize = 1;
326       type.alignSize = Math.max(type.alignSize, alignSize);
327       var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory
328       type.flatSize = curr + size;
329       if (prev >= 0) {
330         diffs.push(curr-prev);
331       }
332       prev = curr;
333       return curr;
334     });
335     if (type.name_ && type.name_[0] === '[') {
336       // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid
337       // allocating a potentially huge array for [999999 x i8] etc.
338       type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2;
339     }
340     type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize);
341     if (diffs.length == 0) {
342       type.flatFactor = type.flatSize;
343     } else if (Runtime.dedup(diffs).length == 1) {
344       type.flatFactor = diffs[0];
345     }
346     type.needsFlattening = (type.flatFactor != 1);
347     return type.flatIndexes;
348   },
349   generateStructInfo: function (struct, typeName, offset) {
350     var type, alignment;
351     if (typeName) {
352       offset = offset || 0;
353       type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName];
354       if (!type) return null;
355       if (type.fields.length != struct.length) {
356         printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo');
357         return null;
358       }
359       alignment = type.flatIndexes;
360     } else {
361       var type = { fields: struct.map(function(item) { return item[0] }) };
362       alignment = Runtime.calculateStructAlignment(type);
363     }
364     var ret = {
365       __size__: type.flatSize
366     };
367     if (typeName) {
368       struct.forEach(function(item, i) {
369         if (typeof item === 'string') {
370           ret[item] = alignment[i] + offset;
371         } else {
372           // embedded struct
373           var key;
374           for (var k in item) key = k;
375           ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]);
376         }
377       });
378     } else {
379       struct.forEach(function(item, i) {
380         ret[item[1]] = alignment[i];
381       });
382     }
383     return ret;
384   },
385   dynCall: function (sig, ptr, args) {
386     if (args && args.length) {
387       if (!args.splice) args = Array.prototype.slice.call(args);
388       args.splice(0, 0, ptr);
389       return Module['dynCall_' + sig].apply(null, args);
390     } else {
391       return Module['dynCall_' + sig].call(null, ptr);
392     }
393   },
394   functionPointers: [],
395   addFunction: function (func) {
396     for (var i = 0; i < Runtime.functionPointers.length; i++) {
397       if (!Runtime.functionPointers[i]) {
398         Runtime.functionPointers[i] = func;
399         return 2*(1 + i);
400       }
401     }
402     throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
403   },
404   removeFunction: function (index) {
405     Runtime.functionPointers[(index-2)/2] = null;
406   },
407   getAsmConst: function (code, numArgs) {
408     // code is a constant string on the heap, so we can cache these
409     if (!Runtime.asmConstCache) Runtime.asmConstCache = {};
410     var func = Runtime.asmConstCache[code];
411     if (func) return func;
412     var args = [];
413     for (var i = 0; i < numArgs; i++) {
414       args.push(String.fromCharCode(36) + i); // $0, $1 etc
415     }
416     code = Pointer_stringify(code);
417     if (code[0] === '"') {
418       // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct
419       if (code.indexOf('"', 1) === code.length-1) {
420         code = code.substr(1, code.length-2);
421       } else {
422         // something invalid happened, e.g. EM_ASM("..code($0)..", input)
423         abort('invalid EM_ASM input |' + code + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)');
424       }
425     }
426     return Runtime.asmConstCache[code] = eval('(function(' + args.join(',') + '){ ' + code + ' })'); // new Function does not allow upvars in node
427   },
428   warnOnce: function (text) {
429     if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
430     if (!Runtime.warnOnce.shown[text]) {
431       Runtime.warnOnce.shown[text] = 1;
432       Module.printErr(text);
433     }
434   },
435   funcWrappers: {},
436   getFuncWrapper: function (func, sig) {
437     assert(sig);
438     if (!Runtime.funcWrappers[func]) {
439       Runtime.funcWrappers[func] = function dynCall_wrapper() {
440         return Runtime.dynCall(sig, func, arguments);
441       };
442     }
443     return Runtime.funcWrappers[func];
444   },
445   UTF8Processor: function () {
446     var buffer = [];
447     var needed = 0;
448     this.processCChar = function (code) {
449       code = code & 0xFF;
450
451       if (buffer.length == 0) {
452         if ((code & 0x80) == 0x00) {        // 0xxxxxxx
453           return String.fromCharCode(code);
454         }
455         buffer.push(code);
456         if ((code & 0xE0) == 0xC0) {        // 110xxxxx
457           needed = 1;
458         } else if ((code & 0xF0) == 0xE0) { // 1110xxxx
459           needed = 2;
460         } else {                            // 11110xxx
461           needed = 3;
462         }
463         return '';
464       }
465
466       if (needed) {
467         buffer.push(code);
468         needed--;
469         if (needed > 0) return '';
470       }
471
472       var c1 = buffer[0];
473       var c2 = buffer[1];
474       var c3 = buffer[2];
475       var c4 = buffer[3];
476       var ret;
477       if (buffer.length == 2) {
478         ret = String.fromCharCode(((c1 & 0x1F) << 6)  | (c2 & 0x3F));
479       } else if (buffer.length == 3) {
480         ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6)  | (c3 & 0x3F));
481       } else {
482         // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
483         var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
484                         ((c3 & 0x3F) << 6)  | (c4 & 0x3F);
485         ret = String.fromCharCode(
486           Math.floor((codePoint - 0x10000) / 0x400) + 0xD800,
487           (codePoint - 0x10000) % 0x400 + 0xDC00);
488       }
489       buffer.length = 0;
490       return ret;
491     }
492     this.processJSString = function processJSString(string) {
493       string = unescape(encodeURIComponent(string));
494       var ret = [];
495       for (var i = 0; i < string.length; i++) {
496         ret.push(string.charCodeAt(i));
497       }
498       return ret;
499     }
500   },
501   getCompilerSetting: function (name) {
502     throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work';
503   },
504   stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; },
505   staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; },
506   dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; },
507   alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; },
508   makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; },
509   GLOBAL_BASE: 8,
510   QUANTUM_SIZE: 4,
511   __dummy__: 0
512 }
513
514
515 Module['Runtime'] = Runtime;
516
517
518
519
520
521
522
523
524
525 //========================================
526 // Runtime essentials
527 //========================================
528
529 var __THREW__ = 0; // Used in checking for thrown exceptions.
530
531 var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort()
532 var EXITSTATUS = 0;
533
534 var undef = 0;
535 // tempInt is used for 32-bit signed values or smaller. tempBigInt is used
536 // for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
537 var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat;
538 var tempI64, tempI64b;
539 var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9;
540
541 function assert(condition, text) {
542   if (!condition) {
543     abort('Assertion failed: ' + text);
544   }
545 }
546
547 var globalScope = this;
548
549 // C calling interface. A convenient way to call C functions (in C files, or
550 // defined with extern "C").
551 //
552 // Note: LLVM optimizations can inline and remove functions, after which you will not be
553 //       able to call them. Closure can also do so. To avoid that, add your function to
554 //       the exports using something like
555 //
556 //         -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]'
557 //
558 // @param ident      The name of the C function (note that C++ functions will be name-mangled - use extern "C")
559 // @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
560 //                   'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit).
561 // @param argTypes   An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
562 //                   except that 'array' is not possible (there is no way for us to know the length of the array)
563 // @param args       An array of the arguments to the function, as native JS values (as in returnType)
564 //                   Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
565 // @return           The return value, as a native JS value (as in returnType)
566 function ccall(ident, returnType, argTypes, args) {
567   return ccallFunc(getCFunc(ident), returnType, argTypes, args);
568 }
569 Module["ccall"] = ccall;
570
571 // Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
572 function getCFunc(ident) {
573   try {
574     var func = Module['_' + ident]; // closure exported function
575     if (!func) func = eval('_' + ident); // explicit lookup
576   } catch(e) {
577   }
578   assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
579   return func;
580 }
581
582 // Internal function that does a C call using a function, not an identifier
583 function ccallFunc(func, returnType, argTypes, args) {
584   var stack = 0;
585   function toC(value, type) {
586     if (type == 'string') {
587       if (value === null || value === undefined || value === 0) return 0; // null string
588       value = intArrayFromString(value);
589       type = 'array';
590     }
591     if (type == 'array') {
592       if (!stack) stack = Runtime.stackSave();
593       var ret = Runtime.stackAlloc(value.length);
594       writeArrayToMemory(value, ret);
595       return ret;
596     }
597     return value;
598   }
599   function fromC(value, type) {
600     if (type == 'string') {
601       return Pointer_stringify(value);
602     }
603     assert(type != 'array');
604     return value;
605   }
606   var i = 0;
607   var cArgs = args ? args.map(function(arg) {
608     return toC(arg, argTypes[i++]);
609   }) : [];
610   var ret = fromC(func.apply(null, cArgs), returnType);
611   if (stack) Runtime.stackRestore(stack);
612   return ret;
613 }
614
615 // Returns a native JS wrapper for a C function. This is similar to ccall, but
616 // returns a function you can call repeatedly in a normal way. For example:
617 //
618 //   var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
619 //   alert(my_function(5, 22));
620 //   alert(my_function(99, 12));
621 //
622 function cwrap(ident, returnType, argTypes) {
623   var func = getCFunc(ident);
624   return function() {
625     return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments));
626   }
627 }
628 Module["cwrap"] = cwrap;
629
630 // Sets a value in memory in a dynamic way at run-time. Uses the
631 // type data. This is the same as makeSetValue, except that
632 // makeSetValue is done at compile-time and generates the needed
633 // code then, whereas this function picks the right code at
634 // run-time.
635 // Note that setValue and getValue only do *aligned* writes and reads!
636 // Note that ccall uses JS types as for defining types, while setValue and
637 // getValue need LLVM types ('i8', 'i32') - this is a lower-level operation
638 function setValue(ptr, value, type, noSafe) {
639   type = type || 'i8';
640   if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
641     switch(type) {
642       case 'i1': HEAP8[(ptr)]=value; break;
643       case 'i8': HEAP8[(ptr)]=value; break;
644       case 'i16': HEAP16[((ptr)>>1)]=value; break;
645       case 'i32': HEAP32[((ptr)>>2)]=value; break;
646       case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
647       case 'float': HEAPF32[((ptr)>>2)]=value; break;
648       case 'double': HEAPF64[((ptr)>>3)]=value; break;
649       default: abort('invalid type for setValue: ' + type);
650     }
651 }
652 Module['setValue'] = setValue;
653
654 // Parallel to setValue.
655 function getValue(ptr, type, noSafe) {
656   type = type || 'i8';
657   if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
658     switch(type) {
659       case 'i1': return HEAP8[(ptr)];
660       case 'i8': return HEAP8[(ptr)];
661       case 'i16': return HEAP16[((ptr)>>1)];
662       case 'i32': return HEAP32[((ptr)>>2)];
663       case 'i64': return HEAP32[((ptr)>>2)];
664       case 'float': return HEAPF32[((ptr)>>2)];
665       case 'double': return HEAPF64[((ptr)>>3)];
666       default: abort('invalid type for setValue: ' + type);
667     }
668   return null;
669 }
670 Module['getValue'] = getValue;
671
672 var ALLOC_NORMAL = 0; // Tries to use _malloc()
673 var ALLOC_STACK = 1; // Lives for the duration of the current function call
674 var ALLOC_STATIC = 2; // Cannot be freed
675 var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk
676 var ALLOC_NONE = 4; // Do not allocate
677 Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
678 Module['ALLOC_STACK'] = ALLOC_STACK;
679 Module['ALLOC_STATIC'] = ALLOC_STATIC;
680 Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC;
681 Module['ALLOC_NONE'] = ALLOC_NONE;
682
683 // allocate(): This is for internal use. You can use it yourself as well, but the interface
684 //             is a little tricky (see docs right below). The reason is that it is optimized
685 //             for multiple syntaxes to save space in generated code. So you should
686 //             normally not use allocate(), and instead allocate memory using _malloc(),
687 //             initialize it with setValue(), and so forth.
688 // @slab: An array of data, or a number. If a number, then the size of the block to allocate,
689 //        in *bytes* (note that this is sometimes confusing: the next parameter does not
690 //        affect this!)
691 // @types: Either an array of types, one for each byte (or 0 if no type at that position),
692 //         or a single type which is used for the entire block. This only matters if there
693 //         is initial data - if @slab is a number, then this does not matter at all and is
694 //         ignored.
695 // @allocator: How to allocate memory, see ALLOC_*
696 function allocate(slab, types, allocator, ptr) {
697   var zeroinit, size;
698   if (typeof slab === 'number') {
699     zeroinit = true;
700     size = slab;
701   } else {
702     zeroinit = false;
703     size = slab.length;
704   }
705
706   var singleType = typeof types === 'string' ? types : null;
707
708   var ret;
709   if (allocator == ALLOC_NONE) {
710     ret = ptr;
711   } else {
712     ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
713   }
714
715   if (zeroinit) {
716     var ptr = ret, stop;
717     assert((ret & 3) == 0);
718     stop = ret + (size & ~3);
719     for (; ptr < stop; ptr += 4) {
720       HEAP32[((ptr)>>2)]=0;
721     }
722     stop = ret + size;
723     while (ptr < stop) {
724       HEAP8[((ptr++)|0)]=0;
725     }
726     return ret;
727   }
728
729   if (singleType === 'i8') {
730     if (slab.subarray || slab.slice) {
731       HEAPU8.set(slab, ret);
732     } else {
733       HEAPU8.set(new Uint8Array(slab), ret);
734     }
735     return ret;
736   }
737
738   var i = 0, type, typeSize, previousType;
739   while (i < size) {
740     var curr = slab[i];
741
742     if (typeof curr === 'function') {
743       curr = Runtime.getFunctionIndex(curr);
744     }
745
746     type = singleType || types[i];
747     if (type === 0) {
748       i++;
749       continue;
750     }
751
752     if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
753
754     setValue(ret+i, curr, type);
755
756     // no need to look up size unless type changes, so cache it
757     if (previousType !== type) {
758       typeSize = Runtime.getNativeTypeSize(type);
759       previousType = type;
760     }
761     i += typeSize;
762   }
763
764   return ret;
765 }
766 Module['allocate'] = allocate;
767
768 function Pointer_stringify(ptr, /* optional */ length) {
769   // TODO: use TextDecoder
770   // Find the length, and check for UTF while doing so
771   var hasUtf = false;
772   var t;
773   var i = 0;
774   while (1) {
775     t = HEAPU8[(((ptr)+(i))|0)];
776     if (t >= 128) hasUtf = true;
777     else if (t == 0 && !length) break;
778     i++;
779     if (length && i == length) break;
780   }
781   if (!length) length = i;
782
783   var ret = '';
784
785   if (!hasUtf) {
786     var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
787     var curr;
788     while (length > 0) {
789       curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
790       ret = ret ? ret + curr : curr;
791       ptr += MAX_CHUNK;
792       length -= MAX_CHUNK;
793     }
794     return ret;
795   }
796
797   var utf8 = new Runtime.UTF8Processor();
798   for (i = 0; i < length; i++) {
799     t = HEAPU8[(((ptr)+(i))|0)];
800     ret += utf8.processCChar(t);
801   }
802   return ret;
803 }
804 Module['Pointer_stringify'] = Pointer_stringify;
805
806 // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
807 // a copy of that string as a Javascript String object.
808 function UTF16ToString(ptr) {
809   var i = 0;
810
811   var str = '';
812   while (1) {
813     var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
814     if (codeUnit == 0)
815       return str;
816     ++i;
817     // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
818     str += String.fromCharCode(codeUnit);
819   }
820 }
821 Module['UTF16ToString'] = UTF16ToString;
822
823 // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
824 // null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP.
825 function stringToUTF16(str, outPtr) {
826   for(var i = 0; i < str.length; ++i) {
827     // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
828     var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
829     HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit;
830   }
831   // Null-terminate the pointer to the HEAP.
832   HEAP16[(((outPtr)+(str.length*2))>>1)]=0;
833 }
834 Module['stringToUTF16'] = stringToUTF16;
835
836 // Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns
837 // a copy of that string as a Javascript String object.
838 function UTF32ToString(ptr) {
839   var i = 0;
840
841   var str = '';
842   while (1) {
843     var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
844     if (utf32 == 0)
845       return str;
846     ++i;
847     // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
848     if (utf32 >= 0x10000) {
849       var ch = utf32 - 0x10000;
850       str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
851     } else {
852       str += String.fromCharCode(utf32);
853     }
854   }
855 }
856 Module['UTF32ToString'] = UTF32ToString;
857
858 // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
859 // null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP,
860 // but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string.
861 function stringToUTF32(str, outPtr) {
862   var iChar = 0;
863   for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) {
864     // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
865     var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate
866     if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
867       var trailSurrogate = str.charCodeAt(++iCodeUnit);
868       codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
869     }
870     HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit;
871     ++iChar;
872   }
873   // Null-terminate the pointer to the HEAP.
874   HEAP32[(((outPtr)+(iChar*4))>>2)]=0;
875 }
876 Module['stringToUTF32'] = stringToUTF32;
877
878 function demangle(func) {
879   var i = 3;
880   // params, etc.
881   var basicTypes = {
882     'v': 'void',
883     'b': 'bool',
884     'c': 'char',
885     's': 'short',
886     'i': 'int',
887     'l': 'long',
888     'f': 'float',
889     'd': 'double',
890     'w': 'wchar_t',
891     'a': 'signed char',
892     'h': 'unsigned char',
893     't': 'unsigned short',
894     'j': 'unsigned int',
895     'm': 'unsigned long',
896     'x': 'long long',
897     'y': 'unsigned long long',
898     'z': '...'
899   };
900   var subs = [];
901   var first = true;
902   function dump(x) {
903     //return;
904     if (x) Module.print(x);
905     Module.print(func);
906     var pre = '';
907     for (var a = 0; a < i; a++) pre += ' ';
908     Module.print (pre + '^');
909   }
910   function parseNested() {
911     i++;
912     if (func[i] === 'K') i++; // ignore const
913     var parts = [];
914     while (func[i] !== 'E') {
915       if (func[i] === 'S') { // substitution
916         i++;
917         var next = func.indexOf('_', i);
918         var num = func.substring(i, next) || 0;
919         parts.push(subs[num] || '?');
920         i = next+1;
921         continue;
922       }
923       if (func[i] === 'C') { // constructor
924         parts.push(parts[parts.length-1]);
925         i += 2;
926         continue;
927       }
928       var size = parseInt(func.substr(i));
929       var pre = size.toString().length;
930       if (!size || !pre) { i--; break; } // counter i++ below us
931       var curr = func.substr(i + pre, size);
932       parts.push(curr);
933       subs.push(curr);
934       i += pre + size;
935     }
936     i++; // skip E
937     return parts;
938   }
939   function parse(rawList, limit, allowVoid) { // main parser
940     limit = limit || Infinity;
941     var ret = '', list = [];
942     function flushList() {
943       return '(' + list.join(', ') + ')';
944     }
945     var name;
946     if (func[i] === 'N') {
947       // namespaced N-E
948       name = parseNested().join('::');
949       limit--;
950       if (limit === 0) return rawList ? [name] : name;
951     } else {
952       // not namespaced
953       if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L'
954       var size = parseInt(func.substr(i));
955       if (size) {
956         var pre = size.toString().length;
957         name = func.substr(i + pre, size);
958         i += pre + size;
959       }
960     }
961     first = false;
962     if (func[i] === 'I') {
963       i++;
964       var iList = parse(true);
965       var iRet = parse(true, 1, true);
966       ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>';
967     } else {
968       ret = name;
969     }
970     paramLoop: while (i < func.length && limit-- > 0) {
971       //dump('paramLoop');
972       var c = func[i++];
973       if (c in basicTypes) {
974         list.push(basicTypes[c]);
975       } else {
976         switch (c) {
977           case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer
978           case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference
979           case 'L': { // literal
980             i++; // skip basic type
981             var end = func.indexOf('E', i);
982             var size = end - i;
983             list.push(func.substr(i, size));
984             i += size + 2; // size + 'EE'
985             break;
986           }
987           case 'A': { // array
988             var size = parseInt(func.substr(i));
989             i += size.toString().length;
990             if (func[i] !== '_') throw '?';
991             i++; // skip _
992             list.push(parse(true, 1, true)[0] + ' [' + size + ']');
993             break;
994           }
995           case 'E': break paramLoop;
996           default: ret += '?' + c; break paramLoop;
997         }
998       }
999     }
1000     if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void)
1001     return rawList ? list : ret + flushList();
1002   }
1003   try {
1004     // Special-case the entry point, since its name differs from other name mangling.
1005     if (func == 'Object._main' || func == '_main') {
1006       return 'main()';
1007     }
1008     if (typeof func === 'number') func = Pointer_stringify(func);
1009     if (func[0] !== '_') return func;
1010     if (func[1] !== '_') return func; // C function
1011     if (func[2] !== 'Z') return func;
1012     switch (func[3]) {
1013       case 'n': return 'operator new()';
1014       case 'd': return 'operator delete()';
1015     }
1016     return parse();
1017   } catch(e) {
1018     return func;
1019   }
1020 }
1021
1022 function demangleAll(text) {
1023   return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') });
1024 }
1025
1026 function stackTrace() {
1027   var stack = new Error().stack;
1028   return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6.
1029 }
1030
1031 // Memory management
1032
1033 var PAGE_SIZE = 4096;
1034 function alignMemoryPage(x) {
1035   return (x+4095)&-4096;
1036 }
1037
1038 var HEAP;
1039 var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
1040
1041 var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area
1042 var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area
1043 var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk
1044
1045 function enlargeMemory() {
1046   abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.');
1047 }
1048
1049 var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880;
1050 var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216;
1051 var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152;
1052
1053 var totalMemory = 4096;
1054 while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
1055   if (totalMemory < 16*1024*1024) {
1056     totalMemory *= 2;
1057   } else {
1058     totalMemory += 16*1024*1024
1059   }
1060 }
1061 if (totalMemory !== TOTAL_MEMORY) {
1062   Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable');
1063   TOTAL_MEMORY = totalMemory;
1064 }
1065
1066 // Initialize the runtime's memory
1067 // check for full engine support (use string 'subarray' to avoid closure compiler confusion)
1068 assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
1069        'JS engine does not provide full typed array support');
1070
1071 var buffer = new ArrayBuffer(TOTAL_MEMORY);
1072 HEAP8 = new Int8Array(buffer);
1073 HEAP16 = new Int16Array(buffer);
1074 HEAP32 = new Int32Array(buffer);
1075 HEAPU8 = new Uint8Array(buffer);
1076 HEAPU16 = new Uint16Array(buffer);
1077 HEAPU32 = new Uint32Array(buffer);
1078 HEAPF32 = new Float32Array(buffer);
1079 HEAPF64 = new Float64Array(buffer);
1080
1081 // Endianness check (note: assumes compiler arch was little-endian)
1082 HEAP32[0] = 255;
1083 assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
1084
1085 Module['HEAP'] = HEAP;
1086 Module['HEAP8'] = HEAP8;
1087 Module['HEAP16'] = HEAP16;
1088 Module['HEAP32'] = HEAP32;
1089 Module['HEAPU8'] = HEAPU8;
1090 Module['HEAPU16'] = HEAPU16;
1091 Module['HEAPU32'] = HEAPU32;
1092 Module['HEAPF32'] = HEAPF32;
1093 Module['HEAPF64'] = HEAPF64;
1094
1095 function callRuntimeCallbacks(callbacks) {
1096   while(callbacks.length > 0) {
1097     var callback = callbacks.shift();
1098     if (typeof callback == 'function') {
1099       callback();
1100       continue;
1101     }
1102     var func = callback.func;
1103     if (typeof func === 'number') {
1104       if (callback.arg === undefined) {
1105         Runtime.dynCall('v', func);
1106       } else {
1107         Runtime.dynCall('vi', func, [callback.arg]);
1108       }
1109     } else {
1110       func(callback.arg === undefined ? null : callback.arg);
1111     }
1112   }
1113 }
1114
1115 var __ATPRERUN__  = []; // functions called before the runtime is initialized
1116 var __ATINIT__    = []; // functions called during startup
1117 var __ATMAIN__    = []; // functions called when main() is to be run
1118 var __ATEXIT__    = []; // functions called during shutdown
1119 var __ATPOSTRUN__ = []; // functions called after the runtime has exited
1120
1121 var runtimeInitialized = false;
1122
1123 function preRun() {
1124   // compatibility - merge in anything from Module['preRun'] at this time
1125   if (Module['preRun']) {
1126     if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
1127     while (Module['preRun'].length) {
1128       addOnPreRun(Module['preRun'].shift());
1129     }
1130   }
1131   callRuntimeCallbacks(__ATPRERUN__);
1132 }
1133
1134 function ensureInitRuntime() {
1135   if (runtimeInitialized) return;
1136   runtimeInitialized = true;
1137   callRuntimeCallbacks(__ATINIT__);
1138 }
1139
1140 function preMain() {
1141   callRuntimeCallbacks(__ATMAIN__);
1142 }
1143
1144 function exitRuntime() {
1145   callRuntimeCallbacks(__ATEXIT__);
1146 }
1147
1148 function postRun() {
1149   // compatibility - merge in anything from Module['postRun'] at this time
1150   if (Module['postRun']) {
1151     if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
1152     while (Module['postRun'].length) {
1153       addOnPostRun(Module['postRun'].shift());
1154     }
1155   }
1156   callRuntimeCallbacks(__ATPOSTRUN__);
1157 }
1158
1159 function addOnPreRun(cb) {
1160   __ATPRERUN__.unshift(cb);
1161 }
1162 Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun;
1163
1164 function addOnInit(cb) {
1165   __ATINIT__.unshift(cb);
1166 }
1167 Module['addOnInit'] = Module.addOnInit = addOnInit;
1168
1169 function addOnPreMain(cb) {
1170   __ATMAIN__.unshift(cb);
1171 }
1172 Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain;
1173
1174 function addOnExit(cb) {
1175   __ATEXIT__.unshift(cb);
1176 }
1177 Module['addOnExit'] = Module.addOnExit = addOnExit;
1178
1179 function addOnPostRun(cb) {
1180   __ATPOSTRUN__.unshift(cb);
1181 }
1182 Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun;
1183
1184 // Tools
1185
1186 // This processes a JS string into a C-line array of numbers, 0-terminated.
1187 // For LLVM-originating strings, see parser.js:parseLLVMString function
1188 function intArrayFromString(stringy, dontAddNull, length /* optional */) {
1189   var ret = (new Runtime.UTF8Processor()).processJSString(stringy);
1190   if (length) {
1191     ret.length = length;
1192   }
1193   if (!dontAddNull) {
1194     ret.push(0);
1195   }
1196   return ret;
1197 }
1198 Module['intArrayFromString'] = intArrayFromString;
1199
1200 function intArrayToString(array) {
1201   var ret = [];
1202   for (var i = 0; i < array.length; i++) {
1203     var chr = array[i];
1204     if (chr > 0xFF) {
1205       chr &= 0xFF;
1206     }
1207     ret.push(String.fromCharCode(chr));
1208   }
1209   return ret.join('');
1210 }
1211 Module['intArrayToString'] = intArrayToString;
1212
1213 // Write a Javascript array to somewhere in the heap
1214 function writeStringToMemory(string, buffer, dontAddNull) {
1215   var array = intArrayFromString(string, dontAddNull);
1216   var i = 0;
1217   while (i < array.length) {
1218     var chr = array[i];
1219     HEAP8[(((buffer)+(i))|0)]=chr;
1220     i = i + 1;
1221   }
1222 }
1223 Module['writeStringToMemory'] = writeStringToMemory;
1224
1225 function writeArrayToMemory(array, buffer) {
1226   for (var i = 0; i < array.length; i++) {
1227     HEAP8[(((buffer)+(i))|0)]=array[i];
1228   }
1229 }
1230 Module['writeArrayToMemory'] = writeArrayToMemory;
1231
1232 function writeAsciiToMemory(str, buffer, dontAddNull) {
1233   for (var i = 0; i < str.length; i++) {
1234     HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i);
1235   }
1236   if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0;
1237 }
1238 Module['writeAsciiToMemory'] = writeAsciiToMemory;
1239
1240 function unSign(value, bits, ignore) {
1241   if (value >= 0) {
1242     return value;
1243   }
1244   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
1245                     : Math.pow(2, bits)         + value;
1246 }
1247 function reSign(value, bits, ignore) {
1248   if (value <= 0) {
1249     return value;
1250   }
1251   var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
1252                         : Math.pow(2, bits-1);
1253   if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that
1254                                                        // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
1255                                                        // TODO: In i64 mode 1, resign the two parts separately and safely
1256     value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
1257   }
1258   return value;
1259 }
1260
1261 // check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 )
1262 if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) {
1263   var ah  = a >>> 16;
1264   var al = a & 0xffff;
1265   var bh  = b >>> 16;
1266   var bl = b & 0xffff;
1267   return (al*bl + ((ah*bl + al*bh) << 16))|0;
1268 };
1269 Math.imul = Math['imul'];
1270
1271
1272 var Math_abs = Math.abs;
1273 var Math_cos = Math.cos;
1274 var Math_sin = Math.sin;
1275 var Math_tan = Math.tan;
1276 var Math_acos = Math.acos;
1277 var Math_asin = Math.asin;
1278 var Math_atan = Math.atan;
1279 var Math_atan2 = Math.atan2;
1280 var Math_exp = Math.exp;
1281 var Math_log = Math.log;
1282 var Math_sqrt = Math.sqrt;
1283 var Math_ceil = Math.ceil;
1284 var Math_floor = Math.floor;
1285 var Math_pow = Math.pow;
1286 var Math_imul = Math.imul;
1287 var Math_fround = Math.fround;
1288 var Math_min = Math.min;
1289
1290 // A counter of dependencies for calling run(). If we need to
1291 // do asynchronous work before running, increment this and
1292 // decrement it. Incrementing must happen in a place like
1293 // PRE_RUN_ADDITIONS (used by emcc to add file preloading).
1294 // Note that you can add dependencies in preRun, even though
1295 // it happens right before run - run will be postponed until
1296 // the dependencies are met.
1297 var runDependencies = 0;
1298 var runDependencyWatcher = null;
1299 var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
1300
1301 function addRunDependency(id) {
1302   runDependencies++;
1303   if (Module['monitorRunDependencies']) {
1304     Module['monitorRunDependencies'](runDependencies);
1305   }
1306 }
1307 Module['addRunDependency'] = addRunDependency;
1308 function removeRunDependency(id) {
1309   runDependencies--;
1310   if (Module['monitorRunDependencies']) {
1311     Module['monitorRunDependencies'](runDependencies);
1312   }
1313   if (runDependencies == 0) {
1314     if (runDependencyWatcher !== null) {
1315       clearInterval(runDependencyWatcher);
1316       runDependencyWatcher = null;
1317     }
1318     if (dependenciesFulfilled) {
1319       var callback = dependenciesFulfilled;
1320       dependenciesFulfilled = null;
1321       callback(); // can add another dependenciesFulfilled
1322     }
1323   }
1324 }
1325 Module['removeRunDependency'] = removeRunDependency;
1326
1327 Module["preloadedImages"] = {}; // maps url to image data
1328 Module["preloadedAudios"] = {}; // maps url to audio data
1329
1330
1331 var memoryInitializer = null;
1332
1333 // === Body ===
1334
1335
1336
1337
1338
1339 STATIC_BASE = 8;
1340
1341 STATICTOP = STATIC_BASE + Runtime.alignMemory(20195);
1342 /* global initializers */ __ATINIT__.push();
1343
1344
1345 /* memory initializer */ allocate([], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE);
1346
1347
1348
1349
1350 var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);
1351
1352 assert(tempDoublePtr % 8 == 0);
1353
1354 function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
1355
1356   HEAP8[tempDoublePtr] = HEAP8[ptr];
1357
1358   HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
1359
1360   HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
1361
1362   HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
1363
1364 }
1365
1366 function copyTempDouble(ptr) {
1367
1368   HEAP8[tempDoublePtr] = HEAP8[ptr];
1369
1370   HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
1371
1372   HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
1373
1374   HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
1375
1376   HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];
1377
1378   HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];
1379
1380   HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];
1381
1382   HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];
1383
1384 }
1385
1386
1387   function _malloc(bytes) {
1388       /* Over-allocate to make sure it is byte-aligned by 8.
1389        * This will leak memory, but this is only the dummy
1390        * implementation (replaced by dlmalloc normally) so
1391        * not an issue.
1392        */
1393       var ptr = Runtime.dynamicAlloc(bytes + 8);
1394       return (ptr+8) & 0xFFFFFFF8;
1395     }
1396   Module["_malloc"] = _malloc;
1397
1398   
1399   
1400   
1401   var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};
1402   
1403   var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can   access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"};
1404   
1405   
1406   var ___errno_state=0;function ___setErrNo(value) {
1407       // For convenient setting and returning of errno.
1408       HEAP32[((___errno_state)>>2)]=value;
1409       return value;
1410     }
1411   
1412   var TTY={ttys:[],init:function () {
1413         // https://github.com/kripken/emscripten/pull/1555
1414         // if (ENVIRONMENT_IS_NODE) {
1415         //   // currently, FS.init does not distinguish if process.stdin is a file or TTY
1416         //   // device, it always assumes it's a TTY device. because of this, we're forcing
1417         //   // process.stdin to UTF8 encoding to at least make stdin reading compatible
1418         //   // with text files until FS.init can be refactored.
1419         //   process['stdin']['setEncoding']('utf8');
1420         // }
1421       },shutdown:function () {
1422         // https://github.com/kripken/emscripten/pull/1555
1423         // if (ENVIRONMENT_IS_NODE) {
1424         //   // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
1425         //   // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation
1426         //   // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
1427         //   // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
1428         //   // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
1429         //   process['stdin']['pause']();
1430         // }
1431       },register:function (dev, ops) {
1432         TTY.ttys[dev] = { input: [], output: [], ops: ops };
1433         FS.registerDevice(dev, TTY.stream_ops);
1434       },stream_ops:{open:function (stream) {
1435           var tty = TTY.ttys[stream.node.rdev];
1436           if (!tty) {
1437             throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
1438           }
1439           stream.tty = tty;
1440           stream.seekable = false;
1441         },close:function (stream) {
1442           // flush any pending line data
1443           if (stream.tty.output.length) {
1444             stream.tty.ops.put_char(stream.tty, 10);
1445           }
1446         },read:function (stream, buffer, offset, length, pos /* ignored */) {
1447           if (!stream.tty || !stream.tty.ops.get_char) {
1448             throw new FS.ErrnoError(ERRNO_CODES.ENXIO);
1449           }
1450           var bytesRead = 0;
1451           for (var i = 0; i < length; i++) {
1452             var result;
1453             try {
1454               result = stream.tty.ops.get_char(stream.tty);
1455             } catch (e) {
1456               throw new FS.ErrnoError(ERRNO_CODES.EIO);
1457             }
1458             if (result === undefined && bytesRead === 0) {
1459               throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
1460             }
1461             if (result === null || result === undefined) break;
1462             bytesRead++;
1463             buffer[offset+i] = result;
1464           }
1465           if (bytesRead) {
1466             stream.node.timestamp = Date.now();
1467           }
1468           return bytesRead;
1469         },write:function (stream, buffer, offset, length, pos) {
1470           if (!stream.tty || !stream.tty.ops.put_char) {
1471             throw new FS.ErrnoError(ERRNO_CODES.ENXIO);
1472           }
1473           for (var i = 0; i < length; i++) {
1474             try {
1475               stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
1476             } catch (e) {
1477               throw new FS.ErrnoError(ERRNO_CODES.EIO);
1478             }
1479           }
1480           if (length) {
1481             stream.node.timestamp = Date.now();
1482           }
1483           return i;
1484         }},default_tty_ops:{get_char:function (tty) {
1485           if (!tty.input.length) {
1486             var result = null;
1487             if (ENVIRONMENT_IS_NODE) {
1488               result = process['stdin']['read']();
1489               if (!result) {
1490                 if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) {
1491                   return null;  // EOF
1492                 }
1493                 return undefined;  // no data available
1494               }
1495             } else if (typeof window != 'undefined' &&
1496               typeof window.prompt == 'function') {
1497               // Browser.
1498               result = window.prompt('Input: ');  // returns null on cancel
1499               if (result !== null) {
1500                 result += '\n';
1501               }
1502             } else if (typeof readline == 'function') {
1503               // Command line.
1504               result = readline();
1505               if (result !== null) {
1506                 result += '\n';
1507               }
1508             }
1509             if (!result) {
1510               return null;
1511             }
1512             tty.input = intArrayFromString(result, true);
1513           }
1514           return tty.input.shift();
1515         },put_char:function (tty, val) {
1516           if (val === null || val === 10) {
1517             Module['print'](tty.output.join(''));
1518             tty.output = [];
1519           } else {
1520             tty.output.push(TTY.utf8.processCChar(val));
1521           }
1522         }},default_tty1_ops:{put_char:function (tty, val) {
1523           if (val === null || val === 10) {
1524             Module['printErr'](tty.output.join(''));
1525             tty.output = [];
1526           } else {
1527             tty.output.push(TTY.utf8.processCChar(val));
1528           }
1529         }}};
1530   
1531   var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) {
1532         return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
1533       },createNode:function (parent, name, mode, dev) {
1534         if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
1535           // no supported
1536           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
1537         }
1538         if (!MEMFS.ops_table) {
1539           MEMFS.ops_table = {
1540             dir: {
1541               node: {
1542                 getattr: MEMFS.node_ops.getattr,
1543                 setattr: MEMFS.node_ops.setattr,
1544                 lookup: MEMFS.node_ops.lookup,
1545                 mknod: MEMFS.node_ops.mknod,
1546                 rename: MEMFS.node_ops.rename,
1547                 unlink: MEMFS.node_ops.unlink,
1548                 rmdir: MEMFS.node_ops.rmdir,
1549                 readdir: MEMFS.node_ops.readdir,
1550                 symlink: MEMFS.node_ops.symlink
1551               },
1552               stream: {
1553                 llseek: MEMFS.stream_ops.llseek
1554               }
1555             },
1556             file: {
1557               node: {
1558                 getattr: MEMFS.node_ops.getattr,
1559                 setattr: MEMFS.node_ops.setattr
1560               },
1561               stream: {
1562                 llseek: MEMFS.stream_ops.llseek,
1563                 read: MEMFS.stream_ops.read,
1564                 write: MEMFS.stream_ops.write,
1565                 allocate: MEMFS.stream_ops.allocate,
1566                 mmap: MEMFS.stream_ops.mmap
1567               }
1568             },
1569             link: {
1570               node: {
1571                 getattr: MEMFS.node_ops.getattr,
1572                 setattr: MEMFS.node_ops.setattr,
1573                 readlink: MEMFS.node_ops.readlink
1574               },
1575               stream: {}
1576             },
1577             chrdev: {
1578               node: {
1579                 getattr: MEMFS.node_ops.getattr,
1580                 setattr: MEMFS.node_ops.setattr
1581               },
1582               stream: FS.chrdev_stream_ops
1583             },
1584           };
1585         }
1586         var node = FS.createNode(parent, name, mode, dev);
1587         if (FS.isDir(node.mode)) {
1588           node.node_ops = MEMFS.ops_table.dir.node;
1589           node.stream_ops = MEMFS.ops_table.dir.stream;
1590           node.contents = {};
1591         } else if (FS.isFile(node.mode)) {
1592           node.node_ops = MEMFS.ops_table.file.node;
1593           node.stream_ops = MEMFS.ops_table.file.stream;
1594           node.contents = [];
1595           node.contentMode = MEMFS.CONTENT_FLEXIBLE;
1596         } else if (FS.isLink(node.mode)) {
1597           node.node_ops = MEMFS.ops_table.link.node;
1598           node.stream_ops = MEMFS.ops_table.link.stream;
1599         } else if (FS.isChrdev(node.mode)) {
1600           node.node_ops = MEMFS.ops_table.chrdev.node;
1601           node.stream_ops = MEMFS.ops_table.chrdev.stream;
1602         }
1603         node.timestamp = Date.now();
1604         // add the new node to the parent
1605         if (parent) {
1606           parent.contents[name] = node;
1607         }
1608         return node;
1609       },ensureFlexible:function (node) {
1610         if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
1611           var contents = node.contents;
1612           node.contents = Array.prototype.slice.call(contents);
1613           node.contentMode = MEMFS.CONTENT_FLEXIBLE;
1614         }
1615       },node_ops:{getattr:function (node) {
1616           var attr = {};
1617           // device numbers reuse inode numbers.
1618           attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
1619           attr.ino = node.id;
1620           attr.mode = node.mode;
1621           attr.nlink = 1;
1622           attr.uid = 0;
1623           attr.gid = 0;
1624           attr.rdev = node.rdev;
1625           if (FS.isDir(node.mode)) {
1626             attr.size = 4096;
1627           } else if (FS.isFile(node.mode)) {
1628             attr.size = node.contents.length;
1629           } else if (FS.isLink(node.mode)) {
1630             attr.size = node.link.length;
1631           } else {
1632             attr.size = 0;
1633           }
1634           attr.atime = new Date(node.timestamp);
1635           attr.mtime = new Date(node.timestamp);
1636           attr.ctime = new Date(node.timestamp);
1637           // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
1638           //       but this is not required by the standard.
1639           attr.blksize = 4096;
1640           attr.blocks = Math.ceil(attr.size / attr.blksize);
1641           return attr;
1642         },setattr:function (node, attr) {
1643           if (attr.mode !== undefined) {
1644             node.mode = attr.mode;
1645           }
1646           if (attr.timestamp !== undefined) {
1647             node.timestamp = attr.timestamp;
1648           }
1649           if (attr.size !== undefined) {
1650             MEMFS.ensureFlexible(node);
1651             var contents = node.contents;
1652             if (attr.size < contents.length) contents.length = attr.size;
1653             else while (attr.size > contents.length) contents.push(0);
1654           }
1655         },lookup:function (parent, name) {
1656           throw FS.genericErrors[ERRNO_CODES.ENOENT];
1657         },mknod:function (parent, name, mode, dev) {
1658           return MEMFS.createNode(parent, name, mode, dev);
1659         },rename:function (old_node, new_dir, new_name) {
1660           // if we're overwriting a directory at new_name, make sure it's empty.
1661           if (FS.isDir(old_node.mode)) {
1662             var new_node;
1663             try {
1664               new_node = FS.lookupNode(new_dir, new_name);
1665             } catch (e) {
1666             }
1667             if (new_node) {
1668               for (var i in new_node.contents) {
1669                 throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
1670               }
1671             }
1672           }
1673           // do the internal rewiring
1674           delete old_node.parent.contents[old_node.name];
1675           old_node.name = new_name;
1676           new_dir.contents[new_name] = old_node;
1677           old_node.parent = new_dir;
1678         },unlink:function (parent, name) {
1679           delete parent.contents[name];
1680         },rmdir:function (parent, name) {
1681           var node = FS.lookupNode(parent, name);
1682           for (var i in node.contents) {
1683             throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
1684           }
1685           delete parent.contents[name];
1686         },readdir:function (node) {
1687           var entries = ['.', '..']
1688           for (var key in node.contents) {
1689             if (!node.contents.hasOwnProperty(key)) {
1690               continue;
1691             }
1692             entries.push(key);
1693           }
1694           return entries;
1695         },symlink:function (parent, newname, oldpath) {
1696           var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
1697           node.link = oldpath;
1698           return node;
1699         },readlink:function (node) {
1700           if (!FS.isLink(node.mode)) {
1701             throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
1702           }
1703           return node.link;
1704         }},stream_ops:{read:function (stream, buffer, offset, length, position) {
1705           var contents = stream.node.contents;
1706           if (position >= contents.length)
1707             return 0;
1708           var size = Math.min(contents.length - position, length);
1709           assert(size >= 0);
1710           if (size > 8 && contents.subarray) { // non-trivial, and typed array
1711             buffer.set(contents.subarray(position, position + size), offset);
1712           } else
1713           {
1714             for (var i = 0; i < size; i++) {
1715               buffer[offset + i] = contents[position + i];
1716             }
1717           }
1718           return size;
1719         },write:function (stream, buffer, offset, length, position, canOwn) {
1720           var node = stream.node;
1721           node.timestamp = Date.now();
1722           var contents = node.contents;
1723           if (length && contents.length === 0 && position === 0 && buffer.subarray) {
1724             // just replace it with the new data
1725             if (canOwn && offset === 0) {
1726               node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source.
1727               node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED;
1728             } else {
1729               node.contents = new Uint8Array(buffer.subarray(offset, offset+length));
1730               node.contentMode = MEMFS.CONTENT_FIXED;
1731             }
1732             return length;
1733           }
1734           MEMFS.ensureFlexible(node);
1735           var contents = node.contents;
1736           while (contents.length < position) contents.push(0);
1737           for (var i = 0; i < length; i++) {
1738             contents[position + i] = buffer[offset + i];
1739           }
1740           return length;
1741         },llseek:function (stream, offset, whence) {
1742           var position = offset;
1743           if (whence === 1) {  // SEEK_CUR.
1744             position += stream.position;
1745           } else if (whence === 2) {  // SEEK_END.
1746             if (FS.isFile(stream.node.mode)) {
1747               position += stream.node.contents.length;
1748             }
1749           }
1750           if (position < 0) {
1751             throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
1752           }
1753           stream.ungotten = [];
1754           stream.position = position;
1755           return position;
1756         },allocate:function (stream, offset, length) {
1757           MEMFS.ensureFlexible(stream.node);
1758           var contents = stream.node.contents;
1759           var limit = offset + length;
1760           while (limit > contents.length) contents.push(0);
1761         },mmap:function (stream, buffer, offset, length, position, prot, flags) {
1762           if (!FS.isFile(stream.node.mode)) {
1763             throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
1764           }
1765           var ptr;
1766           var allocated;
1767           var contents = stream.node.contents;
1768           // Only make a new copy when MAP_PRIVATE is specified.
1769           if ( !(flags & 2) &&
1770                 (contents.buffer === buffer || contents.buffer === buffer.buffer) ) {
1771             // We can't emulate MAP_SHARED when the file is not backed by the buffer
1772             // we're mapping to (e.g. the HEAP buffer).
1773             allocated = false;
1774             ptr = contents.byteOffset;
1775           } else {
1776             // Try to avoid unnecessary slices.
1777             if (position > 0 || position + length < contents.length) {
1778               if (contents.subarray) {
1779                 contents = contents.subarray(position, position + length);
1780               } else {
1781                 contents = Array.prototype.slice.call(contents, position, position + length);
1782               }
1783             }
1784             allocated = true;
1785             ptr = _malloc(length);
1786             if (!ptr) {
1787               throw new FS.ErrnoError(ERRNO_CODES.ENOMEM);
1788             }
1789             buffer.set(contents, ptr);
1790           }
1791           return { ptr: ptr, allocated: allocated };
1792         }}};
1793   
1794   var IDBFS={dbs:{},indexedDB:function () {
1795         return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
1796       },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) {
1797         // reuse all of the core MEMFS functionality
1798         return MEMFS.mount.apply(null, arguments);
1799       },syncfs:function (mount, populate, callback) {
1800         IDBFS.getLocalSet(mount, function(err, local) {
1801           if (err) return callback(err);
1802   
1803           IDBFS.getRemoteSet(mount, function(err, remote) {
1804             if (err) return callback(err);
1805   
1806             var src = populate ? remote : local;
1807             var dst = populate ? local : remote;
1808   
1809             IDBFS.reconcile(src, dst, callback);
1810           });
1811         });
1812       },getDB:function (name, callback) {
1813         // check the cache first
1814         var db = IDBFS.dbs[name];
1815         if (db) {
1816           return callback(null, db);
1817         }
1818   
1819         var req;
1820         try {
1821           req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION);
1822         } catch (e) {
1823           return callback(e);
1824         }
1825         req.onupgradeneeded = function(e) {
1826           var db = e.target.result;
1827           var transaction = e.target.transaction;
1828   
1829           var fileStore;
1830   
1831           if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
1832             fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME);
1833           } else {
1834             fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME);
1835           }
1836   
1837           fileStore.createIndex('timestamp', 'timestamp', { unique: false });
1838         };
1839         req.onsuccess = function() {
1840           db = req.result;
1841   
1842           // add to the cache
1843           IDBFS.dbs[name] = db;
1844           callback(null, db);
1845         };
1846         req.onerror = function() {
1847           callback(this.error);
1848         };
1849       },getLocalSet:function (mount, callback) {
1850         var entries = {};
1851   
1852         function isRealDir(p) {
1853           return p !== '.' && p !== '..';
1854         };
1855         function toAbsolute(root) {
1856           return function(p) {
1857             return PATH.join2(root, p);
1858           }
1859         };
1860   
1861         var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));
1862   
1863         while (check.length) {
1864           var path = check.pop();
1865           var stat;
1866   
1867           try {
1868             stat = FS.stat(path);
1869           } catch (e) {
1870             return callback(e);
1871           }
1872   
1873           if (FS.isDir(stat.mode)) {
1874             check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
1875           }
1876   
1877           entries[path] = { timestamp: stat.mtime };
1878         }
1879   
1880         return callback(null, { type: 'local', entries: entries });
1881       },getRemoteSet:function (mount, callback) {
1882         var entries = {};
1883   
1884         IDBFS.getDB(mount.mountpoint, function(err, db) {
1885           if (err) return callback(err);
1886   
1887           var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly');
1888           transaction.onerror = function() { callback(this.error); };
1889   
1890           var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
1891           var index = store.index('timestamp');
1892   
1893           index.openKeyCursor().onsuccess = function(event) {
1894             var cursor = event.target.result;
1895   
1896             if (!cursor) {
1897               return callback(null, { type: 'remote', db: db, entries: entries });
1898             }
1899   
1900             entries[cursor.primaryKey] = { timestamp: cursor.key };
1901   
1902             cursor.continue();
1903           };
1904         });
1905       },loadLocalEntry:function (path, callback) {
1906         var stat, node;
1907   
1908         try {
1909           var lookup = FS.lookupPath(path);
1910           node = lookup.node;
1911           stat = FS.stat(path);
1912         } catch (e) {
1913           return callback(e);
1914         }
1915   
1916         if (FS.isDir(stat.mode)) {
1917           return callback(null, { timestamp: stat.mtime, mode: stat.mode });
1918         } else if (FS.isFile(stat.mode)) {
1919           return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents });
1920         } else {
1921           return callback(new Error('node type not supported'));
1922         }
1923       },storeLocalEntry:function (path, entry, callback) {
1924         try {
1925           if (FS.isDir(entry.mode)) {
1926             FS.mkdir(path, entry.mode);
1927           } else if (FS.isFile(entry.mode)) {
1928             FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true });
1929           } else {
1930             return callback(new Error('node type not supported'));
1931           }
1932   
1933           FS.utime(path, entry.timestamp, entry.timestamp);
1934         } catch (e) {
1935           return callback(e);
1936         }
1937   
1938         callback(null);
1939       },removeLocalEntry:function (path, callback) {
1940         try {
1941           var lookup = FS.lookupPath(path);
1942           var stat = FS.stat(path);
1943   
1944           if (FS.isDir(stat.mode)) {
1945             FS.rmdir(path);
1946           } else if (FS.isFile(stat.mode)) {
1947             FS.unlink(path);
1948           }
1949         } catch (e) {
1950           return callback(e);
1951         }
1952   
1953         callback(null);
1954       },loadRemoteEntry:function (store, path, callback) {
1955         var req = store.get(path);
1956         req.onsuccess = function(event) { callback(null, event.target.result); };
1957         req.onerror = function() { callback(this.error); };
1958       },storeRemoteEntry:function (store, path, entry, callback) {
1959         var req = store.put(entry, path);
1960         req.onsuccess = function() { callback(null); };
1961         req.onerror = function() { callback(this.error); };
1962       },removeRemoteEntry:function (store, path, callback) {
1963         var req = store.delete(path);
1964         req.onsuccess = function() { callback(null); };
1965         req.onerror = function() { callback(this.error); };
1966       },reconcile:function (src, dst, callback) {
1967         var total = 0;
1968   
1969         var create = [];
1970         Object.keys(src.entries).forEach(function (key) {
1971           var e = src.entries[key];
1972           var e2 = dst.entries[key];
1973           if (!e2 || e.timestamp > e2.timestamp) {
1974             create.push(key);
1975             total++;
1976           }
1977         });
1978   
1979         var remove = [];
1980         Object.keys(dst.entries).forEach(function (key) {
1981           var e = dst.entries[key];
1982           var e2 = src.entries[key];
1983           if (!e2) {
1984             remove.push(key);
1985             total++;
1986           }
1987         });
1988   
1989         if (!total) {
1990           return callback(null);
1991         }
1992   
1993         var errored = false;
1994         var completed = 0;
1995         var db = src.type === 'remote' ? src.db : dst.db;
1996         var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite');
1997         var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
1998   
1999         function done(err) {
2000           if (err) {
2001             if (!done.errored) {
2002               done.errored = true;
2003               return callback(err);
2004             }
2005             return;
2006           }
2007           if (++completed >= total) {
2008             return callback(null);
2009           }
2010         };
2011   
2012         transaction.onerror = function() { done(this.error); };
2013   
2014         // sort paths in ascending order so directory entries are created
2015         // before the files inside them
2016         create.sort().forEach(function (path) {
2017           if (dst.type === 'local') {
2018             IDBFS.loadRemoteEntry(store, path, function (err, entry) {
2019               if (err) return done(err);
2020               IDBFS.storeLocalEntry(path, entry, done);
2021             });
2022           } else {
2023             IDBFS.loadLocalEntry(path, function (err, entry) {
2024               if (err) return done(err);
2025               IDBFS.storeRemoteEntry(store, path, entry, done);
2026             });
2027           }
2028         });
2029   
2030         // sort paths in descending order so files are deleted before their
2031         // parent directories
2032         remove.sort().reverse().forEach(function(path) {
2033           if (dst.type === 'local') {
2034             IDBFS.removeLocalEntry(path, done);
2035           } else {
2036             IDBFS.removeRemoteEntry(store, path, done);
2037           }
2038         });
2039       }};
2040   
2041   var NODEFS={isWindows:false,staticInit:function () {
2042         NODEFS.isWindows = !!process.platform.match(/^win/);
2043       },mount:function (mount) {
2044         assert(ENVIRONMENT_IS_NODE);
2045         return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0);
2046       },createNode:function (parent, name, mode, dev) {
2047         if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
2048           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2049         }
2050         var node = FS.createNode(parent, name, mode);
2051         node.node_ops = NODEFS.node_ops;
2052         node.stream_ops = NODEFS.stream_ops;
2053         return node;
2054       },getMode:function (path) {
2055         var stat;
2056         try {
2057           stat = fs.lstatSync(path);
2058           if (NODEFS.isWindows) {
2059             // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so 
2060             // propagate write bits to execute bits.
2061             stat.mode = stat.mode | ((stat.mode & 146) >> 1);
2062           }
2063         } catch (e) {
2064           if (!e.code) throw e;
2065           throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2066         }
2067         return stat.mode;
2068       },realPath:function (node) {
2069         var parts = [];
2070         while (node.parent !== node) {
2071           parts.push(node.name);
2072           node = node.parent;
2073         }
2074         parts.push(node.mount.opts.root);
2075         parts.reverse();
2076         return PATH.join.apply(null, parts);
2077       },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) {
2078         if (flags in NODEFS.flagsToPermissionStringMap) {
2079           return NODEFS.flagsToPermissionStringMap[flags];
2080         } else {
2081           return flags;
2082         }
2083       },node_ops:{getattr:function (node) {
2084           var path = NODEFS.realPath(node);
2085           var stat;
2086           try {
2087             stat = fs.lstatSync(path);
2088           } catch (e) {
2089             if (!e.code) throw e;
2090             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2091           }
2092           // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096.
2093           // See http://support.microsoft.com/kb/140365
2094           if (NODEFS.isWindows && !stat.blksize) {
2095             stat.blksize = 4096;
2096           }
2097           if (NODEFS.isWindows && !stat.blocks) {
2098             stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0;
2099           }
2100           return {
2101             dev: stat.dev,
2102             ino: stat.ino,
2103             mode: stat.mode,
2104             nlink: stat.nlink,
2105             uid: stat.uid,
2106             gid: stat.gid,
2107             rdev: stat.rdev,
2108             size: stat.size,
2109             atime: stat.atime,
2110             mtime: stat.mtime,
2111             ctime: stat.ctime,
2112             blksize: stat.blksize,
2113             blocks: stat.blocks
2114           };
2115         },setattr:function (node, attr) {
2116           var path = NODEFS.realPath(node);
2117           try {
2118             if (attr.mode !== undefined) {
2119               fs.chmodSync(path, attr.mode);
2120               // update the common node structure mode as well
2121               node.mode = attr.mode;
2122             }
2123             if (attr.timestamp !== undefined) {
2124               var date = new Date(attr.timestamp);
2125               fs.utimesSync(path, date, date);
2126             }
2127             if (attr.size !== undefined) {
2128               fs.truncateSync(path, attr.size);
2129             }
2130           } catch (e) {
2131             if (!e.code) throw e;
2132             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2133           }
2134         },lookup:function (parent, name) {
2135           var path = PATH.join2(NODEFS.realPath(parent), name);
2136           var mode = NODEFS.getMode(path);
2137           return NODEFS.createNode(parent, name, mode);
2138         },mknod:function (parent, name, mode, dev) {
2139           var node = NODEFS.createNode(parent, name, mode, dev);
2140           // create the backing node for this in the fs root as well
2141           var path = NODEFS.realPath(node);
2142           try {
2143             if (FS.isDir(node.mode)) {
2144               fs.mkdirSync(path, node.mode);
2145             } else {
2146               fs.writeFileSync(path, '', { mode: node.mode });
2147             }
2148           } catch (e) {
2149             if (!e.code) throw e;
2150             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2151           }
2152           return node;
2153         },rename:function (oldNode, newDir, newName) {
2154           var oldPath = NODEFS.realPath(oldNode);
2155           var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
2156           try {
2157             fs.renameSync(oldPath, newPath);
2158           } catch (e) {
2159             if (!e.code) throw e;
2160             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2161           }
2162         },unlink:function (parent, name) {
2163           var path = PATH.join2(NODEFS.realPath(parent), name);
2164           try {
2165             fs.unlinkSync(path);
2166           } catch (e) {
2167             if (!e.code) throw e;
2168             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2169           }
2170         },rmdir:function (parent, name) {
2171           var path = PATH.join2(NODEFS.realPath(parent), name);
2172           try {
2173             fs.rmdirSync(path);
2174           } catch (e) {
2175             if (!e.code) throw e;
2176             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2177           }
2178         },readdir:function (node) {
2179           var path = NODEFS.realPath(node);
2180           try {
2181             return fs.readdirSync(path);
2182           } catch (e) {
2183             if (!e.code) throw e;
2184             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2185           }
2186         },symlink:function (parent, newName, oldPath) {
2187           var newPath = PATH.join2(NODEFS.realPath(parent), newName);
2188           try {
2189             fs.symlinkSync(oldPath, newPath);
2190           } catch (e) {
2191             if (!e.code) throw e;
2192             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2193           }
2194         },readlink:function (node) {
2195           var path = NODEFS.realPath(node);
2196           try {
2197             return fs.readlinkSync(path);
2198           } catch (e) {
2199             if (!e.code) throw e;
2200             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2201           }
2202         }},stream_ops:{open:function (stream) {
2203           var path = NODEFS.realPath(stream.node);
2204           try {
2205             if (FS.isFile(stream.node.mode)) {
2206               stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags));
2207             }
2208           } catch (e) {
2209             if (!e.code) throw e;
2210             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2211           }
2212         },close:function (stream) {
2213           try {
2214             if (FS.isFile(stream.node.mode) && stream.nfd) {
2215               fs.closeSync(stream.nfd);
2216             }
2217           } catch (e) {
2218             if (!e.code) throw e;
2219             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2220           }
2221         },read:function (stream, buffer, offset, length, position) {
2222           // FIXME this is terrible.
2223           var nbuffer = new Buffer(length);
2224           var res;
2225           try {
2226             res = fs.readSync(stream.nfd, nbuffer, 0, length, position);
2227           } catch (e) {
2228             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2229           }
2230           if (res > 0) {
2231             for (var i = 0; i < res; i++) {
2232               buffer[offset + i] = nbuffer[i];
2233             }
2234           }
2235           return res;
2236         },write:function (stream, buffer, offset, length, position) {
2237           // FIXME this is terrible.
2238           var nbuffer = new Buffer(buffer.subarray(offset, offset + length));
2239           var res;
2240           try {
2241             res = fs.writeSync(stream.nfd, nbuffer, 0, length, position);
2242           } catch (e) {
2243             throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2244           }
2245           return res;
2246         },llseek:function (stream, offset, whence) {
2247           var position = offset;
2248           if (whence === 1) {  // SEEK_CUR.
2249             position += stream.position;
2250           } else if (whence === 2) {  // SEEK_END.
2251             if (FS.isFile(stream.node.mode)) {
2252               try {
2253                 var stat = fs.fstatSync(stream.nfd);
2254                 position += stat.size;
2255               } catch (e) {
2256                 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2257               }
2258             }
2259           }
2260   
2261           if (position < 0) {
2262             throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2263           }
2264   
2265           stream.position = position;
2266           return position;
2267         }}};
2268   
2269   var _stdin=allocate(1, "i32*", ALLOC_STATIC);
2270   
2271   var _stdout=allocate(1, "i32*", ALLOC_STATIC);
2272   
2273   var _stderr=allocate(1, "i32*", ALLOC_STATIC);
2274   
2275   function _fflush(stream) {
2276       // int fflush(FILE *stream);
2277       // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html
2278       // we don't currently perform any user-space buffering of data
2279     }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) {
2280         if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
2281         return ___setErrNo(e.errno);
2282       },lookupPath:function (path, opts) {
2283         path = PATH.resolve(FS.cwd(), path);
2284         opts = opts || {};
2285   
2286         var defaults = {
2287           follow_mount: true,
2288           recurse_count: 0
2289         };
2290         for (var key in defaults) {
2291           if (opts[key] === undefined) {
2292             opts[key] = defaults[key];
2293           }
2294         }
2295   
2296         if (opts.recurse_count > 8) {  // max recursive lookup of 8
2297           throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
2298         }
2299   
2300         // split the path
2301         var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
2302           return !!p;
2303         }), false);
2304   
2305         // start at the root
2306         var current = FS.root;
2307         var current_path = '/';
2308   
2309         for (var i = 0; i < parts.length; i++) {
2310           var islast = (i === parts.length-1);
2311           if (islast && opts.parent) {
2312             // stop resolving
2313             break;
2314           }
2315   
2316           current = FS.lookupNode(current, parts[i]);
2317           current_path = PATH.join2(current_path, parts[i]);
2318   
2319           // jump to the mount's root node if this is a mountpoint
2320           if (FS.isMountpoint(current)) {
2321             if (!islast || (islast && opts.follow_mount)) {
2322               current = current.mounted.root;
2323             }
2324           }
2325   
2326           // by default, lookupPath will not follow a symlink if it is the final path component.
2327           // setting opts.follow = true will override this behavior.
2328           if (!islast || opts.follow) {
2329             var count = 0;
2330             while (FS.isLink(current.mode)) {
2331               var link = FS.readlink(current_path);
2332               current_path = PATH.resolve(PATH.dirname(current_path), link);
2333               
2334               var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
2335               current = lookup.node;
2336   
2337               if (count++ > 40) {  // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
2338                 throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
2339               }
2340             }
2341           }
2342         }
2343   
2344         return { path: current_path, node: current };
2345       },getPath:function (node) {
2346         var path;
2347         while (true) {
2348           if (FS.isRoot(node)) {
2349             var mount = node.mount.mountpoint;
2350             if (!path) return mount;
2351             return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
2352           }
2353           path = path ? node.name + '/' + path : node.name;
2354           node = node.parent;
2355         }
2356       },hashName:function (parentid, name) {
2357         var hash = 0;
2358   
2359   
2360         for (var i = 0; i < name.length; i++) {
2361           hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
2362         }
2363         return ((parentid + hash) >>> 0) % FS.nameTable.length;
2364       },hashAddNode:function (node) {
2365         var hash = FS.hashName(node.parent.id, node.name);
2366         node.name_next = FS.nameTable[hash];
2367         FS.nameTable[hash] = node;
2368       },hashRemoveNode:function (node) {
2369         var hash = FS.hashName(node.parent.id, node.name);
2370         if (FS.nameTable[hash] === node) {
2371           FS.nameTable[hash] = node.name_next;
2372         } else {
2373           var current = FS.nameTable[hash];
2374           while (current) {
2375             if (current.name_next === node) {
2376               current.name_next = node.name_next;
2377               break;
2378             }
2379             current = current.name_next;
2380           }
2381         }
2382       },lookupNode:function (parent, name) {
2383         var err = FS.mayLookup(parent);
2384         if (err) {
2385           throw new FS.ErrnoError(err);
2386         }
2387         var hash = FS.hashName(parent.id, name);
2388         for (var node = FS.nameTable[hash]; node; node = node.name_next) {
2389           var nodeName = node.name;
2390           if (node.parent.id === parent.id && nodeName === name) {
2391             return node;
2392           }
2393         }
2394         // if we failed to find it in the cache, call into the VFS
2395         return FS.lookup(parent, name);
2396       },createNode:function (parent, name, mode, rdev) {
2397         if (!FS.FSNode) {
2398           FS.FSNode = function(parent, name, mode, rdev) {
2399             if (!parent) {
2400               parent = this;  // root node sets parent to itself
2401             }
2402             this.parent = parent;
2403             this.mount = parent.mount;
2404             this.mounted = null;
2405             this.id = FS.nextInode++;
2406             this.name = name;
2407             this.mode = mode;
2408             this.node_ops = {};
2409             this.stream_ops = {};
2410             this.rdev = rdev;
2411           };
2412   
2413           FS.FSNode.prototype = {};
2414   
2415           // compatibility
2416           var readMode = 292 | 73;
2417           var writeMode = 146;
2418   
2419           // NOTE we must use Object.defineProperties instead of individual calls to
2420           // Object.defineProperty in order to make closure compiler happy
2421           Object.defineProperties(FS.FSNode.prototype, {
2422             read: {
2423               get: function() { return (this.mode & readMode) === readMode; },
2424               set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; }
2425             },
2426             write: {
2427               get: function() { return (this.mode & writeMode) === writeMode; },
2428               set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; }
2429             },
2430             isFolder: {
2431               get: function() { return FS.isDir(this.mode); },
2432             },
2433             isDevice: {
2434               get: function() { return FS.isChrdev(this.mode); },
2435             },
2436           });
2437         }
2438   
2439         var node = new FS.FSNode(parent, name, mode, rdev);
2440   
2441         FS.hashAddNode(node);
2442   
2443         return node;
2444       },destroyNode:function (node) {
2445         FS.hashRemoveNode(node);
2446       },isRoot:function (node) {
2447         return node === node.parent;
2448       },isMountpoint:function (node) {
2449         return !!node.mounted;
2450       },isFile:function (mode) {
2451         return (mode & 61440) === 32768;
2452       },isDir:function (mode) {
2453         return (mode & 61440) === 16384;
2454       },isLink:function (mode) {
2455         return (mode & 61440) === 40960;
2456       },isChrdev:function (mode) {
2457         return (mode & 61440) === 8192;
2458       },isBlkdev:function (mode) {
2459         return (mode & 61440) === 24576;
2460       },isFIFO:function (mode) {
2461         return (mode & 61440) === 4096;
2462       },isSocket:function (mode) {
2463         return (mode & 49152) === 49152;
2464       },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) {
2465         var flags = FS.flagModes[str];
2466         if (typeof flags === 'undefined') {
2467           throw new Error('Unknown file open mode: ' + str);
2468         }
2469         return flags;
2470       },flagsToPermissionString:function (flag) {
2471         var accmode = flag & 2097155;
2472         var perms = ['r', 'w', 'rw'][accmode];
2473         if ((flag & 512)) {
2474           perms += 'w';
2475         }
2476         return perms;
2477       },nodePermissions:function (node, perms) {
2478         if (FS.ignorePermissions) {
2479           return 0;
2480         }
2481         // return 0 if any user, group or owner bits are set.
2482         if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
2483           return ERRNO_CODES.EACCES;
2484         } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
2485           return ERRNO_CODES.EACCES;
2486         } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
2487           return ERRNO_CODES.EACCES;
2488         }
2489         return 0;
2490       },mayLookup:function (dir) {
2491         return FS.nodePermissions(dir, 'x');
2492       },mayCreate:function (dir, name) {
2493         try {
2494           var node = FS.lookupNode(dir, name);
2495           return ERRNO_CODES.EEXIST;
2496         } catch (e) {
2497         }
2498         return FS.nodePermissions(dir, 'wx');
2499       },mayDelete:function (dir, name, isdir) {
2500         var node;
2501         try {
2502           node = FS.lookupNode(dir, name);
2503         } catch (e) {
2504           return e.errno;
2505         }
2506         var err = FS.nodePermissions(dir, 'wx');
2507         if (err) {
2508           return err;
2509         }
2510         if (isdir) {
2511           if (!FS.isDir(node.mode)) {
2512             return ERRNO_CODES.ENOTDIR;
2513           }
2514           if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
2515             return ERRNO_CODES.EBUSY;
2516           }
2517         } else {
2518           if (FS.isDir(node.mode)) {
2519             return ERRNO_CODES.EISDIR;
2520           }
2521         }
2522         return 0;
2523       },mayOpen:function (node, flags) {
2524         if (!node) {
2525           return ERRNO_CODES.ENOENT;
2526         }
2527         if (FS.isLink(node.mode)) {
2528           return ERRNO_CODES.ELOOP;
2529         } else if (FS.isDir(node.mode)) {
2530           if ((flags & 2097155) !== 0 ||  // opening for write
2531               (flags & 512)) {
2532             return ERRNO_CODES.EISDIR;
2533           }
2534         }
2535         return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
2536       },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) {
2537         fd_start = fd_start || 0;
2538         fd_end = fd_end || FS.MAX_OPEN_FDS;
2539         for (var fd = fd_start; fd <= fd_end; fd++) {
2540           if (!FS.streams[fd]) {
2541             return fd;
2542           }
2543         }
2544         throw new FS.ErrnoError(ERRNO_CODES.EMFILE);
2545       },getStream:function (fd) {
2546         return FS.streams[fd];
2547       },createStream:function (stream, fd_start, fd_end) {
2548         if (!FS.FSStream) {
2549           FS.FSStream = function(){};
2550           FS.FSStream.prototype = {};
2551           // compatibility
2552           Object.defineProperties(FS.FSStream.prototype, {
2553             object: {
2554               get: function() { return this.node; },
2555               set: function(val) { this.node = val; }
2556             },
2557             isRead: {
2558               get: function() { return (this.flags & 2097155) !== 1; }
2559             },
2560             isWrite: {
2561               get: function() { return (this.flags & 2097155) !== 0; }
2562             },
2563             isAppend: {
2564               get: function() { return (this.flags & 1024); }
2565             }
2566           });
2567         }
2568         if (stream.__proto__) {
2569           // reuse the object
2570           stream.__proto__ = FS.FSStream.prototype;
2571         } else {
2572           var newStream = new FS.FSStream();
2573           for (var p in stream) {
2574             newStream[p] = stream[p];
2575           }
2576           stream = newStream;
2577         }
2578         var fd = FS.nextfd(fd_start, fd_end);
2579         stream.fd = fd;
2580         FS.streams[fd] = stream;
2581         return stream;
2582       },closeStream:function (fd) {
2583         FS.streams[fd] = null;
2584       },getStreamFromPtr:function (ptr) {
2585         return FS.streams[ptr - 1];
2586       },getPtrForStream:function (stream) {
2587         return stream ? stream.fd + 1 : 0;
2588       },chrdev_stream_ops:{open:function (stream) {
2589           var device = FS.getDevice(stream.node.rdev);
2590           // override node's stream ops with the device's
2591           stream.stream_ops = device.stream_ops;
2592           // forward the open call
2593           if (stream.stream_ops.open) {
2594             stream.stream_ops.open(stream);
2595           }
2596         },llseek:function () {
2597           throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
2598         }},major:function (dev) {
2599         return ((dev) >> 8);
2600       },minor:function (dev) {
2601         return ((dev) & 0xff);
2602       },makedev:function (ma, mi) {
2603         return ((ma) << 8 | (mi));
2604       },registerDevice:function (dev, ops) {
2605         FS.devices[dev] = { stream_ops: ops };
2606       },getDevice:function (dev) {
2607         return FS.devices[dev];
2608       },getMounts:function (mount) {
2609         var mounts = [];
2610         var check = [mount];
2611   
2612         while (check.length) {
2613           var m = check.pop();
2614   
2615           mounts.push(m);
2616   
2617           check.push.apply(check, m.mounts);
2618         }
2619   
2620         return mounts;
2621       },syncfs:function (populate, callback) {
2622         if (typeof(populate) === 'function') {
2623           callback = populate;
2624           populate = false;
2625         }
2626   
2627         var mounts = FS.getMounts(FS.root.mount);
2628         var completed = 0;
2629   
2630         function done(err) {
2631           if (err) {
2632             if (!done.errored) {
2633               done.errored = true;
2634               return callback(err);
2635             }
2636             return;
2637           }
2638           if (++completed >= mounts.length) {
2639             callback(null);
2640           }
2641         };
2642   
2643         // sync all mounts
2644         mounts.forEach(function (mount) {
2645           if (!mount.type.syncfs) {
2646             return done(null);
2647           }
2648           mount.type.syncfs(mount, populate, done);
2649         });
2650       },mount:function (type, opts, mountpoint) {
2651         var root = mountpoint === '/';
2652         var pseudo = !mountpoint;
2653         var node;
2654   
2655         if (root && FS.root) {
2656           throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2657         } else if (!root && !pseudo) {
2658           var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
2659   
2660           mountpoint = lookup.path;  // use the absolute path
2661           node = lookup.node;
2662   
2663           if (FS.isMountpoint(node)) {
2664             throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2665           }
2666   
2667           if (!FS.isDir(node.mode)) {
2668             throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
2669           }
2670         }
2671   
2672         var mount = {
2673           type: type,
2674           opts: opts,
2675           mountpoint: mountpoint,
2676           mounts: []
2677         };
2678   
2679         // create a root node for the fs
2680         var mountRoot = type.mount(mount);
2681         mountRoot.mount = mount;
2682         mount.root = mountRoot;
2683   
2684         if (root) {
2685           FS.root = mountRoot;
2686         } else if (node) {
2687           // set as a mountpoint
2688           node.mounted = mount;
2689   
2690           // add the new mount to the current mount's children
2691           if (node.mount) {
2692             node.mount.mounts.push(mount);
2693           }
2694         }
2695   
2696         return mountRoot;
2697       },unmount:function (mountpoint) {
2698         var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
2699   
2700         if (!FS.isMountpoint(lookup.node)) {
2701           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2702         }
2703   
2704         // destroy the nodes for this mount, and all its child mounts
2705         var node = lookup.node;
2706         var mount = node.mounted;
2707         var mounts = FS.getMounts(mount);
2708   
2709         Object.keys(FS.nameTable).forEach(function (hash) {
2710           var current = FS.nameTable[hash];
2711   
2712           while (current) {
2713             var next = current.name_next;
2714   
2715             if (mounts.indexOf(current.mount) !== -1) {
2716               FS.destroyNode(current);
2717             }
2718   
2719             current = next;
2720           }
2721         });
2722   
2723         // no longer a mountpoint
2724         node.mounted = null;
2725   
2726         // remove this mount from the child mounts
2727         var idx = node.mount.mounts.indexOf(mount);
2728         assert(idx !== -1);
2729         node.mount.mounts.splice(idx, 1);
2730       },lookup:function (parent, name) {
2731         return parent.node_ops.lookup(parent, name);
2732       },mknod:function (path, mode, dev) {
2733         var lookup = FS.lookupPath(path, { parent: true });
2734         var parent = lookup.node;
2735         var name = PATH.basename(path);
2736         var err = FS.mayCreate(parent, name);
2737         if (err) {
2738           throw new FS.ErrnoError(err);
2739         }
2740         if (!parent.node_ops.mknod) {
2741           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2742         }
2743         return parent.node_ops.mknod(parent, name, mode, dev);
2744       },create:function (path, mode) {
2745         mode = mode !== undefined ? mode : 438 /* 0666 */;
2746         mode &= 4095;
2747         mode |= 32768;
2748         return FS.mknod(path, mode, 0);
2749       },mkdir:function (path, mode) {
2750         mode = mode !== undefined ? mode : 511 /* 0777 */;
2751         mode &= 511 | 512;
2752         mode |= 16384;
2753         return FS.mknod(path, mode, 0);
2754       },mkdev:function (path, mode, dev) {
2755         if (typeof(dev) === 'undefined') {
2756           dev = mode;
2757           mode = 438 /* 0666 */;
2758         }
2759         mode |= 8192;
2760         return FS.mknod(path, mode, dev);
2761       },symlink:function (oldpath, newpath) {
2762         var lookup = FS.lookupPath(newpath, { parent: true });
2763         var parent = lookup.node;
2764         var newname = PATH.basename(newpath);
2765         var err = FS.mayCreate(parent, newname);
2766         if (err) {
2767           throw new FS.ErrnoError(err);
2768         }
2769         if (!parent.node_ops.symlink) {
2770           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2771         }
2772         return parent.node_ops.symlink(parent, newname, oldpath);
2773       },rename:function (old_path, new_path) {
2774         var old_dirname = PATH.dirname(old_path);
2775         var new_dirname = PATH.dirname(new_path);
2776         var old_name = PATH.basename(old_path);
2777         var new_name = PATH.basename(new_path);
2778         // parents must exist
2779         var lookup, old_dir, new_dir;
2780         try {
2781           lookup = FS.lookupPath(old_path, { parent: true });
2782           old_dir = lookup.node;
2783           lookup = FS.lookupPath(new_path, { parent: true });
2784           new_dir = lookup.node;
2785         } catch (e) {
2786           throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2787         }
2788         // need to be part of the same mount
2789         if (old_dir.mount !== new_dir.mount) {
2790           throw new FS.ErrnoError(ERRNO_CODES.EXDEV);
2791         }
2792         // source must exist
2793         var old_node = FS.lookupNode(old_dir, old_name);
2794         // old path should not be an ancestor of the new path
2795         var relative = PATH.relative(old_path, new_dirname);
2796         if (relative.charAt(0) !== '.') {
2797           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2798         }
2799         // new path should not be an ancestor of the old path
2800         relative = PATH.relative(new_path, old_dirname);
2801         if (relative.charAt(0) !== '.') {
2802           throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
2803         }
2804         // see if the new path already exists
2805         var new_node;
2806         try {
2807           new_node = FS.lookupNode(new_dir, new_name);
2808         } catch (e) {
2809           // not fatal
2810         }
2811         // early out if nothing needs to change
2812         if (old_node === new_node) {
2813           return;
2814         }
2815         // we'll need to delete the old entry
2816         var isdir = FS.isDir(old_node.mode);
2817         var err = FS.mayDelete(old_dir, old_name, isdir);
2818         if (err) {
2819           throw new FS.ErrnoError(err);
2820         }
2821         // need delete permissions if we'll be overwriting.
2822         // need create permissions if new doesn't already exist.
2823         err = new_node ?
2824           FS.mayDelete(new_dir, new_name, isdir) :
2825           FS.mayCreate(new_dir, new_name);
2826         if (err) {
2827           throw new FS.ErrnoError(err);
2828         }
2829         if (!old_dir.node_ops.rename) {
2830           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2831         }
2832         if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
2833           throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2834         }
2835         // if we are going to change the parent, check write permissions
2836         if (new_dir !== old_dir) {
2837           err = FS.nodePermissions(old_dir, 'w');
2838           if (err) {
2839             throw new FS.ErrnoError(err);
2840           }
2841         }
2842         // remove the node from the lookup hash
2843         FS.hashRemoveNode(old_node);
2844         // do the underlying fs rename
2845         try {
2846           old_dir.node_ops.rename(old_node, new_dir, new_name);
2847         } catch (e) {
2848           throw e;
2849         } finally {
2850           // add the node back to the hash (in case node_ops.rename
2851           // changed its name)
2852           FS.hashAddNode(old_node);
2853         }
2854       },rmdir:function (path) {
2855         var lookup = FS.lookupPath(path, { parent: true });
2856         var parent = lookup.node;
2857         var name = PATH.basename(path);
2858         var node = FS.lookupNode(parent, name);
2859         var err = FS.mayDelete(parent, name, true);
2860         if (err) {
2861           throw new FS.ErrnoError(err);
2862         }
2863         if (!parent.node_ops.rmdir) {
2864           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2865         }
2866         if (FS.isMountpoint(node)) {
2867           throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2868         }
2869         parent.node_ops.rmdir(parent, name);
2870         FS.destroyNode(node);
2871       },readdir:function (path) {
2872         var lookup = FS.lookupPath(path, { follow: true });
2873         var node = lookup.node;
2874         if (!node.node_ops.readdir) {
2875           throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
2876         }
2877         return node.node_ops.readdir(node);
2878       },unlink:function (path) {
2879         var lookup = FS.lookupPath(path, { parent: true });
2880         var parent = lookup.node;
2881         var name = PATH.basename(path);
2882         var node = FS.lookupNode(parent, name);
2883         var err = FS.mayDelete(parent, name, false);
2884         if (err) {
2885           // POSIX says unlink should set EPERM, not EISDIR
2886           if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM;
2887           throw new FS.ErrnoError(err);
2888         }
2889         if (!parent.node_ops.unlink) {
2890           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2891         }
2892         if (FS.isMountpoint(node)) {
2893           throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2894         }
2895         parent.node_ops.unlink(parent, name);
2896         FS.destroyNode(node);
2897       },readlink:function (path) {
2898         var lookup = FS.lookupPath(path);
2899         var link = lookup.node;
2900         if (!link.node_ops.readlink) {
2901           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2902         }
2903         return link.node_ops.readlink(link);
2904       },stat:function (path, dontFollow) {
2905         var lookup = FS.lookupPath(path, { follow: !dontFollow });
2906         var node = lookup.node;
2907         if (!node.node_ops.getattr) {
2908           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2909         }
2910         return node.node_ops.getattr(node);
2911       },lstat:function (path) {
2912         return FS.stat(path, true);
2913       },chmod:function (path, mode, dontFollow) {
2914         var node;
2915         if (typeof path === 'string') {
2916           var lookup = FS.lookupPath(path, { follow: !dontFollow });
2917           node = lookup.node;
2918         } else {
2919           node = path;
2920         }
2921         if (!node.node_ops.setattr) {
2922           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2923         }
2924         node.node_ops.setattr(node, {
2925           mode: (mode & 4095) | (node.mode & ~4095),
2926           timestamp: Date.now()
2927         });
2928       },lchmod:function (path, mode) {
2929         FS.chmod(path, mode, true);
2930       },fchmod:function (fd, mode) {
2931         var stream = FS.getStream(fd);
2932         if (!stream) {
2933           throw new FS.ErrnoError(ERRNO_CODES.EBADF);
2934         }
2935         FS.chmod(stream.node, mode);
2936       },chown:function (path, uid, gid, dontFollow) {
2937         var node;
2938         if (typeof path === 'string') {
2939           var lookup = FS.lookupPath(path, { follow: !dontFollow });
2940           node = lookup.node;
2941         } else {
2942           node = path;
2943         }
2944         if (!node.node_ops.setattr) {
2945           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2946         }
2947         node.node_ops.setattr(node, {
2948           timestamp: Date.now()
2949           // we ignore the uid / gid for now
2950         });
2951       },lchown:function (path, uid, gid) {
2952         FS.chown(path, uid, gid, true);
2953       },fchown:function (fd, uid, gid) {
2954         var stream = FS.getStream(fd);
2955         if (!stream) {
2956           throw new FS.ErrnoError(ERRNO_CODES.EBADF);
2957         }
2958         FS.chown(stream.node, uid, gid);
2959       },truncate:function (path, len) {
2960         if (len < 0) {
2961           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2962         }
2963         var node;
2964         if (typeof path === 'string') {
2965           var lookup = FS.lookupPath(path, { follow: true });
2966           node = lookup.node;
2967         } else {
2968           node = path;
2969         }
2970         if (!node.node_ops.setattr) {
2971           throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2972         }
2973         if (FS.isDir(node.mode)) {
2974           throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
2975         }
2976         if (!FS.isFile(node.mode)) {
2977           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2978         }
2979         var err = FS.nodePermissions(node, 'w');
2980         if (err) {
2981           throw new FS.ErrnoError(err);
2982         }
2983         node.node_ops.setattr(node, {
2984           size: len,
2985           timestamp: Date.now()
2986         });
2987       },ftruncate:function (fd, len) {
2988         var stream = FS.getStream(fd);
2989         if (!stream) {
2990           throw new FS.ErrnoError(ERRNO_CODES.EBADF);
2991         }
2992         if ((stream.flags & 2097155) === 0) {
2993           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2994         }
2995         FS.truncate(stream.node, len);
2996       },utime:function (path, atime, mtime) {
2997         var lookup = FS.lookupPath(path, { follow: true });
2998         var node = lookup.node;
2999         node.node_ops.setattr(node, {
3000           timestamp: Math.max(atime, mtime)
3001         });
3002       },open:function (path, flags, mode, fd_start, fd_end) {
3003         flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
3004         mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode;
3005         if ((flags & 64)) {
3006           mode = (mode & 4095) | 32768;
3007         } else {
3008           mode = 0;
3009         }
3010         var node;
3011         if (typeof path === 'object') {
3012           node = path;
3013         } else {
3014           path = PATH.normalize(path);
3015           try {
3016             var lookup = FS.lookupPath(path, {
3017               follow: !(flags & 131072)
3018             });
3019             node = lookup.node;
3020           } catch (e) {
3021             // ignore
3022           }
3023         }
3024         // perhaps we need to create the node
3025         if ((flags & 64)) {
3026           if (node) {
3027             // if O_CREAT and O_EXCL are set, error out if the node already exists
3028             if ((flags & 128)) {
3029               throw new FS.ErrnoError(ERRNO_CODES.EEXIST);
3030             }
3031           } else {
3032             // node doesn't exist, try to create it
3033             node = FS.mknod(path, mode, 0);
3034           }
3035         }
3036         if (!node) {
3037           throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
3038         }
3039         // can't truncate a device
3040         if (FS.isChrdev(node.mode)) {
3041           flags &= ~512;
3042         }
3043         // check permissions
3044         var err = FS.mayOpen(node, flags);
3045         if (err) {
3046           throw new FS.ErrnoError(err);
3047         }
3048         // do truncation if necessary
3049         if ((flags & 512)) {
3050           FS.truncate(node, 0);
3051         }
3052         // we've already handled these, don't pass down to the underlying vfs
3053         flags &= ~(128 | 512);
3054   
3055         // register the stream with the filesystem
3056         var stream = FS.createStream({
3057           node: node,
3058           path: FS.getPath(node),  // we want the absolute path to the node
3059           flags: flags,
3060           seekable: true,
3061           position: 0,
3062           stream_ops: node.stream_ops,
3063           // used by the file family libc calls (fopen, fwrite, ferror, etc.)
3064           ungotten: [],
3065           error: false
3066         }, fd_start, fd_end);
3067         // call the new stream's open function
3068         if (stream.stream_ops.open) {
3069           stream.stream_ops.open(stream);
3070         }
3071         if (Module['logReadFiles'] && !(flags & 1)) {
3072           if (!FS.readFiles) FS.readFiles = {};
3073           if (!(path in FS.readFiles)) {
3074             FS.readFiles[path] = 1;
3075             Module['printErr']('read file: ' + path);
3076           }
3077         }
3078         return stream;
3079       },close:function (stream) {
3080         try {
3081           if (stream.stream_ops.close) {
3082             stream.stream_ops.close(stream);
3083           }
3084         } catch (e) {
3085           throw e;
3086         } finally {
3087           FS.closeStream(stream.fd);
3088         }
3089       },llseek:function (stream, offset, whence) {
3090         if (!stream.seekable || !stream.stream_ops.llseek) {
3091           throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
3092         }
3093         return stream.stream_ops.llseek(stream, offset, whence);
3094       },read:function (stream, buffer, offset, length, position) {
3095         if (length < 0 || position < 0) {
3096           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3097         }
3098         if ((stream.flags & 2097155) === 1) {
3099           throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3100         }
3101         if (FS.isDir(stream.node.mode)) {
3102           throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
3103         }
3104         if (!stream.stream_ops.read) {
3105           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3106         }
3107         var seeking = true;
3108         if (typeof position === 'undefined') {
3109           position = stream.position;
3110           seeking = false;
3111         } else if (!stream.seekable) {
3112           throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
3113         }
3114         var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
3115         if (!seeking) stream.position += bytesRead;
3116         return bytesRead;
3117       },write:function (stream, buffer, offset, length, position, canOwn) {
3118         if (length < 0 || position < 0) {
3119           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3120         }
3121         if ((stream.flags & 2097155) === 0) {
3122           throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3123         }
3124         if (FS.isDir(stream.node.mode)) {
3125           throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
3126         }
3127         if (!stream.stream_ops.write) {
3128           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3129         }
3130         var seeking = true;
3131         if (typeof position === 'undefined') {
3132           position = stream.position;
3133           seeking = false;
3134         } else if (!stream.seekable) {
3135           throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
3136         }
3137         if (stream.flags & 1024) {
3138           // seek to the end before writing in append mode
3139           FS.llseek(stream, 0, 2);
3140         }
3141         var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
3142         if (!seeking) stream.position += bytesWritten;
3143         return bytesWritten;
3144       },allocate:function (stream, offset, length) {
3145         if (offset < 0 || length <= 0) {
3146           throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3147         }
3148         if ((stream.flags & 2097155) === 0) {
3149           throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3150         }
3151         if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) {
3152           throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
3153         }
3154         if (!stream.stream_ops.allocate) {
3155           throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP);
3156         }
3157         stream.stream_ops.allocate(stream, offset, length);
3158       },mmap:function (stream, buffer, offset, length, position, prot, flags) {
3159         // TODO if PROT is PROT_WRITE, make sure we have write access
3160         if ((stream.flags & 2097155) === 1) {
3161           throw new FS.ErrnoError(ERRNO_CODES.EACCES);
3162         }
3163         if (!stream.stream_ops.mmap) {
3164           throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
3165         }
3166         return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags);
3167       },ioctl:function (stream, cmd, arg) {
3168         if (!stream.stream_ops.ioctl) {
3169           throw new FS.ErrnoError(ERRNO_CODES.ENOTTY);
3170         }
3171         return stream.stream_ops.ioctl(stream, cmd, arg);
3172       },readFile:function (path, opts) {
3173         opts = opts || {};
3174         opts.flags = opts.flags || 'r';
3175         opts.encoding = opts.encoding || 'binary';
3176         if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
3177           throw new Error('Invalid encoding type "' + opts.encoding + '"');
3178         }
3179         var ret;
3180         var stream = FS.open(path, opts.flags);
3181         var stat = FS.stat(path);
3182         var length = stat.size;
3183         var buf = new Uint8Array(length);
3184         FS.read(stream, buf, 0, length, 0);
3185         if (opts.encoding === 'utf8') {
3186           ret = '';
3187           var utf8 = new Runtime.UTF8Processor();
3188           for (var i = 0; i < length; i++) {
3189             ret += utf8.processCChar(buf[i]);
3190           }
3191         } else if (opts.encoding === 'binary') {
3192           ret = buf;
3193         }
3194         FS.close(stream);
3195         return ret;
3196       },writeFile:function (path, data, opts) {
3197         opts = opts || {};
3198         opts.flags = opts.flags || 'w';
3199         opts.encoding = opts.encoding || 'utf8';
3200         if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
3201           throw new Error('Invalid encoding type "' + opts.encoding + '"');
3202         }
3203         var stream = FS.open(path, opts.flags, opts.mode);
3204         if (opts.encoding === 'utf8') {
3205           var utf8 = new Runtime.UTF8Processor();
3206           var buf = new Uint8Array(utf8.processJSString(data));
3207           FS.write(stream, buf, 0, buf.length, 0, opts.canOwn);
3208         } else if (opts.encoding === 'binary') {