Верно. Но, с другой стороны, в подавляющем большинстве случаев выравнивание идёт на 4 байта в x86 и на 8 байт в x64 с целью ускорения вычитки данных (чтобы совпадало с размером регистров процессора). Это уже скорее аппаратное требование. (Вспомним даже некоторые Виндовские функции работы с памятью, которые требуют адрес указателя, выравненный на 4 байта.) И в случае несоблюдение такого выравнивания я бы в первую очередь предположил кривизну компилятора.FeyFre wrote:Выравнивание унаследуется от умолчания компилятора, или от какого-нибудь хидера который об этом подумал
Вопросы по AkelPad Plugin API.
Discuss and announce AkelPad plugins
- Author
- Message
-
Offline
- Posts: 1250
- Joined: Thu Nov 16, 2006 11:53 am
- Location: Kyiv, Ukraine
-
Offline
- Posts: 1250
- Joined: Thu Nov 16, 2006 11:53 am
- Location: Kyiv, Ukraine
-
Offline
- Posts: 876
- Joined: Tue Jul 24, 2007 8:54 am
В pArray[0] у нас хранится количество элементов. Отчего же оно вдруг стало 8?
Поэкспериментировал.
1 параметр - 8 ( (1+1)*4 )
2 параметра - 12 ( (2+1)*4 )
3 параметра - 16 ( (3+1)*4 )
Выходит, pArray[0] содержит не количество элементов, а физический размер массива. В байтах.
Т.е.
Array_Len = pArray[0] / sizeof(INT_PTR),
Param_Count = Array_Len - 1
Что, кстати, подтверждается строкой из ContextMenu.c:
Поэкспериментировал.
1 параметр - 8 ( (1+1)*4 )
2 параметра - 12 ( (2+1)*4 )
3 параметра - 16 ( (3+1)*4 )
Выходит, pArray[0] содержит не количество элементов, а физический размер массива. В байтах.
Т.е.
Array_Len = pArray[0] / sizeof(INT_PTR),
Param_Count = Array_Len - 1
Что, кстати, подтверждается строкой из ContextMenu.c:
Code: Select all
if (*((INT_PTR *)lParam) >= (INT_PTR)((nIndex + 1) * sizeof(INT_PTR)))
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
Да, да, но нет, не с целью совпадения с размерами регистров. Мне было впадло писать "Не уменьшение" скорости обращения к памяти скорее побочный эффект чем прямой. ЕМНИП, если процессор(x86 семья) встречает такую операцию, то возникает аппаратное исключение, обработчик которого "довыполняет" виновную операцию своим ходом - отсюда и замедление.Верно. Но, с другой стороны, в подавляющем большинстве случаев выравнивание идёт на 4 байта в x86 и на 8 байт в x64 с целью ускорения вычитки данных (чтобы совпадало с размером регистров процессора). Это уже скорее аппаратное требование.
Что-то мне вспоминаются только GDI DIB функции. Оно и понятно, они там работают с не хилым массивом, и тормоза там не нужны. С другой стороны, возможно указанные буфера опускаются вниз(в ядро), и там такая обработка больше хлопот доставляет.(Вспомним даже некоторые Виндовские функции работы с памятью, которые требуют адрес указателя, выравненный на 4 байта.)
Хотя на самом деле кривизна программиста. Ибо если в плагине поставить #pragma pack(1) перед #include "AkelDll.h"/"AkelEdit.h" то можно напороться на грабли: сам AP будет считать свои структуры выровненными на границу 4(8) а плагин - тулить поля рядом. В итоге, если плагин использует структуру, в которой есть поля размером меньше чем размер указателя, то это чревато SEGFAULT-ом(в лучшем случае порчей данных). НА 32бит архитектуре таких структур мало, на 64бит - каждая вторая(где есть int и некоторые другие типы).И в случае несоблюдение такого выравнивания я бы в первую очередь предположил кривизну компилятора.
-
Offline
- Posts: 1250
- Joined: Thu Nov 16, 2006 11:53 am
- Location: Kyiv, Ukraine
Да. Как один товарищ писал выше,Fr0sT wrote:Выходит, pArray[0] содержит не количество элементов, а физический размер массива. В байтах.
DV wrote:Далее первая же строчка кода убеждает нас в том, что ранее я допустил неточность. Эта строчказаписывает в самый первый (нулевой) параметр не 3 по общему количеству параметров, а размер структуры, равный 3*sizeof(INT_PTR).Code: Select all
hlParams.dwStructSize = sizeof(DLLECHIGHLIGHT_UNMARK);
-
Offline
- Posts: 876
- Joined: Tue Jul 24, 2007 8:54 am
Вот и славно, разобрались Хотя обернуть всё это шаманство в пару API функций — на самом деле хорошая идея.
Значит, надо в "AkelDll.h"/"AkelEdit.h" прямо указывать нужное выравнивание.Ибо если в плагине поставить #pragma pack(1) перед #include "AkelDll.h"/"AkelEdit.h" то можно напороться на грабли: сам AP будет считать свои структуры выровненными на границу 4( а плагин - тулить поля рядом.
Это еще одна причина, по которой я недолюбливаю С. Сборка всех исходников в единый кусок кода несет с собой прорву подводных камней, в итоге запороть одной некорректной директивой всю программу - как два байта переслать
-
Offline
- Posts: 876
- Joined: Tue Jul 24, 2007 8:54 am
Инструктор, большая просьба поменять принцип проверки версий плагинов, либо что-то сделать с версионностью API. Объясню, в чем проблема. API постоянно обновляется, и поддерживать его постоянно в актуальном состоянии на других языках - довольно большой геморрой. Получается делать это только от случая к случаю.
В то же время, добавления не означают несовместимости со старыми редакциями, т.е. старые плагины вполне себе могут корректно работать с новым Акелем. Однако всё упирается в версию AkelDLL, которая зашита в плагине.
Есть простой вариант - это отменить проверку версий при определенных значениях, например, если плагин сообщает версию 0.0.0.0.
Более сложный - это сменить принцип постановки версий для API, либо меняя его только в случае возможной несовместимости, либо различая минорный-мажорный инкремент.
В то же время, добавления не означают несовместимости со старыми редакциями, т.е. старые плагины вполне себе могут корректно работать с новым Акелем. Однако всё упирается в версию AkelDLL, которая зашита в плагине.
Есть простой вариант - это отменить проверку версий при определенных значениях, например, если плагин сообщает версию 0.0.0.0.
Более сложный - это сменить принцип постановки версий для API, либо меняя его только в случае возможной несовместимости, либо различая минорный-мажорный инкремент.
-
Offline
- Posts: 3217
- Joined: Wed Nov 29, 2006 1:19 pm
- Location: Киев, Русь
- Contact:
DV
Идея Fr0sT'а в том, чтобы не перекомпиливать плагин каждый раз, при выходе нового пакована плагинов.
Для этого проще всего использовать нумерацию из 2-х значений, например № 2.16, где:
- 16 - некритическое обновление (например добавили какую-то функциональность. но обратная совместимость присутствует);
- 2 - версия ядра (критические изменения в структуре плагинов).
Т.о. если меняется суффикс, то перекомпиливать старые плаги ненужно, и они должны работать при новой версии проги/всех других плагов.
Идея Fr0sT'а в том, чтобы не перекомпиливать плагин каждый раз, при выходе нового пакована плагинов.
Для этого проще всего использовать нумерацию из 2-х значений, например № 2.16, где:
- 16 - некритическое обновление (например добавили какую-то функциональность. но обратная совместимость присутствует);
- 2 - версия ядра (критические изменения в структуре плагинов).
Т.о. если меняется суффикс, то перекомпиливать старые плаги ненужно, и они должны работать при новой версии проги/всех других плагов.
-
Offline
- Posts: 876
- Joined: Tue Jul 24, 2007 8:54 am
Да-да, Влад понял мою идею (как раз второй вариант из моего предложения).
DV, легко сказать скрипт, даже специализированные проги типа C to Pascal Converter столько лажи дают, что за ними править и править.
Одна только морока с комментариями в детальных samples чего стоит; скрипт, который смог бы это разрулить, должен быть чертовски умён.
DV, легко сказать скрипт, даже специализированные проги типа C to Pascal Converter столько лажи дают, что за ними править и править.
Одна только морока с комментариями в детальных samples чего стоит; скрипт, который смог бы это разрулить, должен быть чертовски умён.
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
Надыбал я вчера некий питоноский скрип который, занимается генерацией кода JavaScript из других языков. В том числе из C/C++. Кому интересно могу показать во что превращается элементарный
Code: Select all
#include <stdio.h>
int main(int argc,char*argv[])
{
printf("%s\n","Hello,World!");
return 0;
}
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
где-то так
Code: Select all
try {
this["Module"] = Module;
} catch (e) {
this["Module"] = Module = {};
}
var ENVIRONMENT_IS_NODE = typeof process === "object";
var ENVIRONMENT_IS_WEB = typeof window === "object";
var ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
if (ENVIRONMENT_IS_NODE) {
Module["print"] = (function(x) {
process["stdout"].write(x + "\n");
});
Module["printErr"] = (function(x) {
process["stderr"].write(x + "\n");
});
var nodeFS = require("fs");
var nodePath = require("path");
Module["read"] = (function(filename) {
filename = nodePath["normalize"](filename);
var ret = nodeFS["readFileSync"](filename).toString();
if (!ret && filename != nodePath["resolve"](filename)) {
filename = path.join(__dirname, "..", "src", filename);
ret = nodeFS["readFileSync"](filename).toString();
}
return ret;
});
Module["load"] = (function(f) {
globalEval(read(f));
});
if (!Module["arguments"]) {
Module["arguments"] = process["argv"].slice(2);
}
}
if (ENVIRONMENT_IS_SHELL) {
Module["print"] = print;
if (typeof printErr != "undefined") Module["printErr"] = printErr;
if (typeof read != "undefined") {
Module["read"] = read;
} else {
Module["read"] = (function(f) {
snarf(f);
});
}
if (!Module["arguments"]) {
if (typeof scriptArgs != "undefined") {
Module["arguments"] = scriptArgs;
} else if (typeof arguments != "undefined") {
Module["arguments"] = arguments;
}
}
}
if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER) {
if (!Module["print"]) {
Module["print"] = (function(x) {
console.log(x);
});
}
if (!Module["printErr"]) {
Module["printErr"] = (function(x) {
console.log(x);
});
}
}
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
Module["read"] = (function(url) {
var xhr = new XMLHttpRequest;
xhr.open("GET", url, false);
xhr.send(null);
return xhr.responseText;
});
if (!Module["arguments"]) {
if (typeof arguments != "undefined") {
Module["arguments"] = arguments;
}
}
}
if (ENVIRONMENT_IS_WORKER) {
var TRY_USE_DUMP = false;
if (!Module["print"]) {
Module["print"] = TRY_USE_DUMP && typeof dump !== "undefined" ? (function(x) {
dump(x);
}) : (function(x) {});
}
Module["load"] = importScripts;
}
if (!ENVIRONMENT_IS_WORKER && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_SHELL) {
throw "Unknown runtime environment. Where are we?";
}
function globalEval(x) {
eval.call(null, x);
}
if (!Module["load"] == "undefined" && Module["read"]) {
Module["load"] = (function(f) {
globalEval(Module["read"](f));
});
}
if (!Module["print"]) {
Module["print"] = (function() {});
}
if (!Module["printErr"]) {
Module["printErr"] = Module["print"];
}
if (!Module["arguments"]) {
Module["arguments"] = [];
}
Module.print = Module["print"];
Module.printErr = Module["printErr"];
if (!Module["preRun"]) Module["preRun"] = [];
if (!Module["postRun"]) Module["postRun"] = [];
var Runtime = {
stackSave: (function() {
return STACKTOP;
}),
stackRestore: (function(stackTop) {
STACKTOP = stackTop;
}),
forceAlign: (function(target, quantum) {
quantum = quantum || 4;
if (quantum == 1) return target;
if (isNumber(target) && isNumber(quantum)) {
return Math.ceil(target / quantum) * quantum;
} else if (isNumber(quantum) && isPowerOfTwo(quantum)) {
var logg = log2(quantum);
return "((((" + target + ")+" + (quantum - 1) + ")>>" + logg + ")<<" + logg + ")";
}
return "Math.ceil((" + target + ")/" + quantum + ")*" + quantum;
}),
isNumberType: (function(type) {
return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES;
}),
isPointerType: function isPointerType(type) {
return type[type.length - 1] == "*";
},
isStructType: function isStructType(type) {
if (isPointerType(type)) return false;
if (/^\[\d+\ x\ (.*)\]/.test(type)) return true;
if (/<?{ ?[^}]* ?}>?/.test(type)) return true;
return type[0] == "%";
},
INT_TYPES: {
"i1": 0,
"i8": 0,
"i16": 0,
"i32": 0,
"i64": 0
},
FLOAT_TYPES: {
"float": 0,
"double": 0
},
bitshift64: (function(low, high, op, bits) {
var ander = Math.pow(2, bits) - 1;
if (bits < 32) {
switch (op) {
case "shl":
return [ low << bits, high << bits | (low & ander << 32 - bits) >>> 32 - bits ];
case "ashr":
return [ (low >>> bits | (high & ander) << 32 - bits) >> 0 >>> 0, high >> bits >>> 0 ];
case "lshr":
return [ (low >>> bits | (high & ander) << 32 - bits) >>> 0, high >>> bits ];
}
} else if (bits == 32) {
switch (op) {
case "shl":
return [ 0, low ];
case "ashr":
return [ high, (high | 0) < 0 ? ander : 0 ];
case "lshr":
return [ high, 0 ];
}
} else {
switch (op) {
case "shl":
return [ 0, low << bits - 32 ];
case "ashr":
return [ high >> bits - 32 >>> 0, (high | 0) < 0 ? ander : 0 ];
case "lshr":
return [ high >>> bits - 32, 0 ];
}
}
abort("unknown bitshift64 op: " + [ value, op, bits ]);
}),
or64: (function(x, y) {
var l = x | 0 | (y | 0);
var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
return l + h;
}),
and64: (function(x, y) {
var l = (x | 0) & (y | 0);
var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
return l + h;
}),
xor64: (function(x, y) {
var l = (x | 0) ^ (y | 0);
var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
return l + h;
}),
getNativeTypeSize: (function(type, quantumSize) {
if (Runtime.QUANTUM_SIZE == 1) return 1;
var size = {
"%i1": 1,
"%i8": 1,
"%i16": 2,
"%i32": 4,
"%i64": 8,
"%float": 4,
"%double": 8
}["%" + type];
if (!size) {
if (type.charAt(type.length - 1) == "*") {
size = Runtime.QUANTUM_SIZE;
} else if (type[0] == "i") {
var bits = parseInt(type.substr(1));
assert(bits % 8 == 0);
size = bits / 8;
}
}
return size;
}),
getNativeFieldSize: (function(type) {
return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
}),
dedup: function dedup(items, ident) {
var seen = {};
if (ident) {
return items.filter((function(item) {
if (seen[item[ident]]) return false;
seen[item[ident]] = true;
return true;
}));
} else {
return items.filter((function(item) {
if (seen[item]) return false;
seen[item] = true;
return true;
}));
}
},
set: function set() {
var args = typeof arguments[0] === "object" ? arguments[0] : arguments;
var ret = {};
for (var i = 0; i < args.length; i++) {
ret[args[i]] = 0;
}
return ret;
},
calculateStructAlignment: function calculateStructAlignment(type) {
type.flatSize = 0;
type.alignSize = 0;
var diffs = [];
var prev = -1;
type.flatIndexes = type.fields.map((function(field) {
var size, alignSize;
if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) {
size = Runtime.getNativeTypeSize(field);
alignSize = size;
} else if (Runtime.isStructType(field)) {
size = Types.types[field].flatSize;
alignSize = Types.types[field].alignSize;
} else {
throw "Unclear type in struct: " + field + ", in " + type.name_ + " :: " + dump(Types.types[type.name_]);
}
alignSize = type.packed ? 1 : Math.min(alignSize, Runtime.QUANTUM_SIZE);
type.alignSize = Math.max(type.alignSize, alignSize);
var curr = Runtime.alignMemory(type.flatSize, alignSize);
type.flatSize = curr + size;
if (prev >= 0) {
diffs.push(curr - prev);
}
prev = curr;
return curr;
}));
type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize);
if (diffs.length == 0) {
type.flatFactor = type.flatSize;
} else if (Runtime.dedup(diffs).length == 1) {
type.flatFactor = diffs[0];
}
type.needsFlattening = type.flatFactor != 1;
return type.flatIndexes;
},
generateStructInfo: (function(struct, typeName, offset) {
var type, alignment;
if (typeName) {
offset = offset || 0;
type = (typeof Types === "undefined" ? Runtime.typeInfo : Types.types)[typeName];
if (!type) return null;
if (type.fields.length != struct.length) {
printErr("Number of named fields must match the type for " + typeName + ": possibly duplicate struct names. Cannot return structInfo");
return null;
}
alignment = type.flatIndexes;
} else {
var type = {
fields: struct.map((function(item) {
return item[0];
}))
};
alignment = Runtime.calculateStructAlignment(type);
}
var ret = {
__size__: type.flatSize
};
if (typeName) {
struct.forEach((function(item, i) {
if (typeof item === "string") {
ret[item] = alignment[i] + offset;
} else {
var key;
for (var k in item) key = k;
ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]);
}
}));
} else {
struct.forEach((function(item, i) {
ret[item[1]] = alignment[i];
}));
}
return ret;
}),
addFunction: (function(func) {
var ret = FUNCTION_TABLE.length;
FUNCTION_TABLE.push(func);
FUNCTION_TABLE.push(0);
return ret;
}),
warnOnce: (function(text) {
if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
if (!Runtime.warnOnce.shown[text]) {
Runtime.warnOnce.shown[text] = 1;
Module.printErr(text);
}
}),
funcWrappers: {},
getFuncWrapper: (function(func) {
if (!Runtime.funcWrappers[func]) {
Runtime.funcWrappers[func] = (function() {
FUNCTION_TABLE[func].apply(null, arguments);
});
}
return Runtime.funcWrappers[func];
}),
UTF8Processor: (function() {
var buffer = [];
var needed = 0;
this.processCChar = (function(code) {
code = code & 255;
if (needed) {
buffer.push(code);
needed--;
}
if (buffer.length == 0) {
if (code < 128) return String.fromCharCode(code);
buffer.push(code);
if (code > 191 && code < 224) {
needed = 1;
} else {
needed = 2;
}
return "";
}
if (needed > 0) return "";
var c1 = buffer[0];
var c2 = buffer[1];
var c3 = buffer[2];
var ret;
if (c1 > 191 && c1 < 224) {
ret = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
} else {
ret = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
}
buffer.length = 0;
return ret;
});
this.processJSString = (function(string) {
string = unescape(encodeURIComponent(string));
var ret = [];
for (var i = 0; i < string.length; i++) {
ret.push(string.charCodeAt(i));
}
return ret;
});
}),
stackAlloc: function stackAlloc(size) {
var ret = STACKTOP;
STACKTOP += size;
return ret;
},
staticAlloc: function staticAlloc(size) {
var ret = STATICTOP;
STATICTOP += size;
STATICTOP = STATICTOP + 3 >> 2 << 2;
return ret;
},
alignMemory: function alignMemory(size, quantum) {
var ret = size = Math.ceil(size / (quantum ? quantum : 4)) * (quantum ? quantum : 4);
return ret;
},
makeBigInt: function makeBigInt(low, high, unsigned) {
var ret = unsigned ? (low >>> 0) + (high >>> 0) * 4294967296 : (low >>> 0) + (high | 0) * 4294967296;
return ret;
},
QUANTUM_SIZE: 4,
__dummy__: 0
};
var CorrectionsMonitor = {
MAX_ALLOWED: 0,
corrections: 0,
sigs: {},
note: (function(type, succeed, sig) {
if (!succeed) {
this.corrections++;
if (this.corrections >= this.MAX_ALLOWED) abort("\n\nToo many corrections!");
}
}),
print: (function() {})
};
var __THREW__ = false;
var ABORT = false;
var undef = 0;
var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD;
function abort(text) {
Module.print(text + ":\n" + (new Error).stack);
ABORT = true;
throw "Assertion: " + text;
}
function assert(condition, text) {
if (!condition) {
abort("Assertion failed: " + text);
}
}
var globalScope = this;
function ccall(ident, returnType, argTypes, args) {
var stack = 0;
function toC(value, type) {
if (type == "string") {
if (value === null || value === undefined || value === 0) return 0;
if (!stack) stack = Runtime.stackSave();
var ret = Runtime.stackAlloc(value.length + 1);
writeStringToMemory(value, ret);
return ret;
} else if (type == "array") {
if (!stack) stack = Runtime.stackSave();
var ret = Runtime.stackAlloc(value.length);
writeArrayToMemory(value, ret);
return ret;
}
return value;
}
function fromC(value, type) {
if (type == "string") {
return Pointer_stringify(value);
}
assert(type != "array");
return value;
}
try {
var func = eval("_" + ident);
} catch (e) {
try {
func = globalScope["Module"]["_" + ident];
} catch (e) {}
}
assert(func, "Cannot call unknown function " + ident + " (perhaps LLVM optimizations or closure removed it?)");
var i = 0;
var cArgs = args ? args.map((function(arg) {
return toC(arg, argTypes[i++]);
})) : [];
var ret = fromC(func.apply(null, cArgs), returnType);
if (stack) Runtime.stackRestore(stack);
return ret;
}
Module["ccall"] = ccall;
function cwrap(ident, returnType, argTypes) {
return (function() {
return ccall(ident, returnType, argTypes, Array.prototype.slice.call(arguments));
});
}
Module["cwrap"] = cwrap;
function setValue(ptr, value, type, noSafe) {
type = type || "i8";
if (type.charAt(type.length - 1) === "*") type = "i32";
switch (type) {
case "i1":
HEAP[ptr] = value;
break;
case "i8":
HEAP[ptr] = value;
break;
case "i16":
HEAP[ptr] = value;
break;
case "i32":
HEAP[ptr] = value;
break;
case "i64":
HEAP[ptr] = value;
break;
case "float":
HEAP[ptr] = value;
break;
case "double":
HEAP[ptr] = value;
break;
default:
abort("invalid type for setValue: " + type);
}
}
Module["setValue"] = setValue;
function getValue(ptr, type, noSafe) {
type = type || "i8";
if (type.charAt(type.length - 1) === "*") type = "i32";
switch (type) {
case "i1":
return HEAP[ptr];
case "i8":
return HEAP[ptr];
case "i16":
return HEAP[ptr];
case "i32":
return HEAP[ptr];
case "i64":
return HEAP[ptr];
case "float":
return HEAP[ptr];
case "double":
return HEAP[ptr];
default:
abort("invalid type for setValue: " + type);
}
return null;
}
Module["getValue"] = getValue;
var ALLOC_NORMAL = 0;
var ALLOC_STACK = 1;
var ALLOC_STATIC = 2;
Module["ALLOC_NORMAL"] = ALLOC_NORMAL;
Module["ALLOC_STACK"] = ALLOC_STACK;
Module["ALLOC_STATIC"] = ALLOC_STATIC;
function allocate(slab, types, allocator) {
var zeroinit, size;
if (typeof slab === "number") {
zeroinit = true;
size = slab;
} else {
zeroinit = false;
size = slab.length;
}
var singleType = typeof types === "string" ? types : null;
var ret = [ _malloc, Runtime.stackAlloc, Runtime.staticAlloc ][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
if (zeroinit) {
_memset(ret, 0, size);
return ret;
}
var i = 0, type;
while (i < size) {
var curr = slab[i];
if (typeof curr === "function") {
curr = Runtime.getFunctionIndex(curr);
}
type = singleType || types[i];
if (type === 0) {
i++;
continue;
}
setValue(ret + i, curr, type);
i += Runtime.getNativeTypeSize(type);
}
return ret;
}
Module["allocate"] = allocate;
function Pointer_stringify(ptr, length) {
var utf8 = new Runtime.UTF8Processor;
var nullTerminated = typeof length == "undefined";
var ret = "";
var i = 0;
var t;
while (1) {
t = HEAP[ptr + i];
if (nullTerminated && t == 0) break;
ret += utf8.processCChar(t);
i += 1;
if (!nullTerminated && i == length) break;
}
return ret;
}
Module["Pointer_stringify"] = Pointer_stringify;
function Array_stringify(array) {
var ret = "";
for (var i = 0; i < array.length; i++) {
ret += String.fromCharCode(array[i]);
}
return ret;
}
Module["Array_stringify"] = Array_stringify;
var FUNCTION_TABLE;
var PAGE_SIZE = 4096;
function alignMemoryPage(x) {
return x + 4095 >> 12 << 12;
}
var HEAP;
var STACK_ROOT, STACKTOP, STACK_MAX;
var STATICTOP;
var TOTAL_STACK = Module["TOTAL_STACK"] || 5242880;
var TOTAL_MEMORY = Module["TOTAL_MEMORY"] || 10485760;
var FAST_MEMORY = Module["FAST_MEMORY"] || 2097152;
HEAP = [];
for (var i = 0; i < FAST_MEMORY; i++) {
HEAP[i] = 0;
}
Module["HEAP"] = HEAP;
STACK_ROOT = STACKTOP = Runtime.alignMemory(1);
STACK_MAX = STACK_ROOT + TOTAL_STACK;
STATICTOP = alignMemoryPage(STACK_MAX);
assert(STATICTOP < TOTAL_MEMORY);
var nullString = allocate(intArrayFromString("(null)"), "i8", ALLOC_STATIC);
function callRuntimeCallbacks(callbacks) {
while (callbacks.length > 0) {
var callback = callbacks.shift();
var func = callback.func;
if (typeof func === "number") {
func = FUNCTION_TABLE[func];
}
func(callback.arg === undefined ? null : callback.arg);
}
}
var __ATINIT__ = [];
var __ATMAIN__ = [];
var __ATEXIT__ = [];
function initRuntime() {
callRuntimeCallbacks(__ATINIT__);
}
function preMain() {
callRuntimeCallbacks(__ATMAIN__);
}
function exitRuntime() {
callRuntimeCallbacks(__ATEXIT__);
CorrectionsMonitor.print();
}
function String_len(ptr) {
var i = ptr;
while (HEAP[i++]) {}
return i - ptr - 1;
}
Module["String_len"] = String_len;
function intArrayFromString(stringy, dontAddNull, length) {
var ret = (new Runtime.UTF8Processor).processJSString(stringy);
if (length) {
ret.length = length;
}
if (!dontAddNull) {
ret.push(0);
}
return ret;
}
Module["intArrayFromString"] = intArrayFromString;
function intArrayToString(array) {
var ret = [];
for (var i = 0; i < array.length; i++) {
var chr = array[i];
if (chr > 255) {
chr &= 255;
}
ret.push(String.fromCharCode(chr));
}
return ret.join("");
}
Module["intArrayToString"] = intArrayToString;
function writeStringToMemory(string, buffer, dontAddNull) {
var array = intArrayFromString(string, dontAddNull);
var i = 0;
while (i < array.length) {
var chr = array[i];
HEAP[buffer + i] = chr;
i = i + 1;
}
}
Module["writeStringToMemory"] = writeStringToMemory;
function writeArrayToMemory(array, buffer) {
for (var i = 0; i < array.length; i++) {
HEAP[buffer + i] = array[i];
}
}
Module["writeArrayToMemory"] = writeArrayToMemory;
var STRING_TABLE = [];
function unSign(value, bits, ignore, sig) {
if (value >= 0) {
return value;
}
return bits <= 32 ? 2 * Math.abs(1 << bits - 1) + value : Math.pow(2, bits) + value;
}
function reSign(value, bits, ignore, sig) {
if (value <= 0) {
return value;
}
var half = bits <= 32 ? Math.abs(1 << bits - 1) : Math.pow(2, bits - 1);
if (value >= half && (bits <= 32 || value > half)) {
value = -2 * half + value;
}
return value;
}
var runDependencies = 0;
var runDependencyTracking = {};
var calledRun = false;
var runDependencyWatcher = null;
function addRunDependency(id) {
runDependencies++;
if (Module["monitorRunDependencies"]) {
Module["monitorRunDependencies"](runDependencies);
}
if (id) {
assert(!runDependencyTracking[id]);
runDependencyTracking[id] = 1;
if (runDependencyWatcher === null && typeof setInterval !== "undefined") {
runDependencyWatcher = setInterval((function() {
var shown = false;
for (var dep in runDependencyTracking) {
if (!shown) {
shown = true;
Module.printErr("still waiting on run dependencies:");
}
Module.printErr("dependency: " + dep);
}
if (shown) {
Module.printErr("(end of list)");
}
}), 6e3);
}
} else {
Module.printErr("warning: run dependency added without ID");
}
}
Module["addRunDependency"] = addRunDependency;
function removeRunDependency(id) {
runDependencies--;
if (Module["monitorRunDependencies"]) {
Module["monitorRunDependencies"](runDependencies);
}
if (id) {
assert(runDependencyTracking[id]);
delete runDependencyTracking[id];
} else {
Module.printErr("warning: run dependency removed without ID");
}
if (runDependencies == 0) {
if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
}
if (!calledRun) run();
}
}
Module["removeRunDependency"] = removeRunDependency;
Module["preloadedImages"] = {};
Module["preloadedAudios"] = {};
function _main($argc, $argv) {
var __stackBase__ = STACKTOP;
$retval = 0;
$argc_addr = $argc;
$argv_addr = $argv;
var $call = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP[tempInt] = STRING_TABLE.__str1 | 0, tempInt));
STACKTOP = __stackBase__;
return 0;
}
Module["_main"] = _main;
var i64Math = null;
var ERRNO_CODES = {
E2BIG: 7,
EACCES: 13,
EADDRINUSE: 98,
EADDRNOTAVAIL: 99,
EAFNOSUPPORT: 97,
EAGAIN: 11,
EALREADY: 114,
EBADF: 9,
EBADMSG: 74,
EBUSY: 16,
ECANCELED: 125,
ECHILD: 10,
ECONNABORTED: 103,
ECONNREFUSED: 111,
ECONNRESET: 104,
EDEADLK: 35,
EDESTADDRREQ: 89,
EDOM: 33,
EDQUOT: 122,
EEXIST: 17,
EFAULT: 14,
EFBIG: 27,
EHOSTUNREACH: 113,
EIDRM: 43,
EILSEQ: 84,
EINPROGRESS: 115,
EINTR: 4,
EINVAL: 22,
EIO: 5,
EISCONN: 106,
EISDIR: 21,
ELOOP: 40,
EMFILE: 24,
EMLINK: 31,
EMSGSIZE: 90,
EMULTIHOP: 72,
ENAMETOOLONG: 36,
ENETDOWN: 100,
ENETRESET: 102,
ENETUNREACH: 101,
ENFILE: 23,
ENOBUFS: 105,
ENODATA: 61,
ENODEV: 19,
ENOENT: 2,
ENOEXEC: 8,
ENOLCK: 37,
ENOLINK: 67,
ENOMEM: 12,
ENOMSG: 42,
ENOPROTOOPT: 92,
ENOSPC: 28,
ENOSR: 63,
ENOSTR: 60,
ENOSYS: 38,
ENOTCONN: 107,
ENOTDIR: 20,
ENOTEMPTY: 39,
ENOTRECOVERABLE: 131,
ENOTSOCK: 88,
ENOTSUP: 95,
ENOTTY: 25,
ENXIO: 6,
EOVERFLOW: 75,
EOWNERDEAD: 130,
EPERM: 1,
EPIPE: 32,
EPROTO: 71,
EPROTONOSUPPORT: 93,
EPROTOTYPE: 91,
ERANGE: 34,
EROFS: 30,
ESPIPE: 29,
ESRCH: 3,
ESTALE: 116,
ETIME: 62,
ETIMEDOUT: 110,
ETXTBSY: 26,
EWOULDBLOCK: 11,
EXDEV: 18
};
function ___setErrNo(value) {
if (!___setErrNo.ret) ___setErrNo.ret = allocate([ 0 ], "i32", ALLOC_STATIC);
HEAP[___setErrNo.ret] = value;
return value;
}
var _stdin = 0;
var _stdout = 0;
var _stderr = 0;
var __impure_ptr = 0;
var FS = {
currentPath: "/",
nextInode: 2,
streams: [ null ],
ignorePermissions: true,
joinPath: (function(parts, forceRelative) {
var ret = parts[0];
for (var i = 1; i < parts.length; i++) {
if (ret[ret.length - 1] != "/") ret += "/";
ret += parts[i];
}
if (forceRelative && ret[0] == "/") ret = ret.substr(1);
return ret;
}),
absolutePath: (function(relative, base) {
if (typeof relative !== "string") return null;
if (base === undefined) base = FS.currentPath;
if (relative && relative[0] == "/") base = "";
var full = base + "/" + relative;
var parts = full.split("/").reverse();
var absolute = [ "" ];
while (parts.length) {
var part = parts.pop();
if (part == "" || part == ".") {} else if (part == "..") {
if (absolute.length > 1) absolute.pop();
} else {
absolute.push(part);
}
}
return absolute.length == 1 ? "/" : absolute.join("/");
}),
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
Code: Select all
analyzePath: (function(path, dontResolveLastLink, linksVisited) {
var ret = {
isRoot: false,
exists: false,
error: 0,
name: null,
path: null,
object: null,
parentExists: false,
parentPath: null,
parentObject: null
};
path = FS.absolutePath(path);
if (path == "/") {
ret.isRoot = true;
ret.exists = ret.parentExists = true;
ret.name = "/";
ret.path = ret.parentPath = "/";
ret.object = ret.parentObject = FS.root;
} else if (path !== null) {
linksVisited = linksVisited || 0;
path = path.slice(1).split("/");
var current = FS.root;
var traversed = [ "" ];
while (path.length) {
if (path.length == 1 && current.isFolder) {
ret.parentExists = true;
ret.parentPath = traversed.length == 1 ? "/" : traversed.join("/");
ret.parentObject = current;
ret.name = path[0];
}
var target = path.shift();
if (!current.isFolder) {
ret.error = ERRNO_CODES.ENOTDIR;
break;
} else if (!current.read) {
ret.error = ERRNO_CODES.EACCES;
break;
} else if (!current.contents.hasOwnProperty(target)) {
ret.error = ERRNO_CODES.ENOENT;
break;
}
current = current.contents[target];
if (current.link && !(dontResolveLastLink && path.length == 0)) {
if (linksVisited > 40) {
ret.error = ERRNO_CODES.ELOOP;
break;
}
var link = FS.absolutePath(current.link, traversed.join("/"));
ret = FS.analyzePath([ link ].concat(path).join("/"), dontResolveLastLink, linksVisited + 1);
return ret;
}
traversed.push(target);
if (path.length == 0) {
ret.exists = true;
ret.path = traversed.join("/");
ret.object = current;
}
}
}
return ret;
}),
findObject: (function(path, dontResolveLastLink) {
FS.ensureRoot();
var ret = FS.analyzePath(path, dontResolveLastLink);
if (ret.exists) {
return ret.object;
} else {
___setErrNo(ret.error);
return null;
}
}),
createObject: (function(parent, name, properties, canRead, canWrite) {
if (!parent) parent = "/";
if (typeof parent === "string") parent = FS.findObject(parent);
if (!parent) {
___setErrNo(ERRNO_CODES.EACCES);
throw new Error("Parent path must exist.");
}
if (!parent.isFolder) {
___setErrNo(ERRNO_CODES.ENOTDIR);
throw new Error("Parent must be a folder.");
}
if (!parent.write && !FS.ignorePermissions) {
___setErrNo(ERRNO_CODES.EACCES);
throw new Error("Parent folder must be writeable.");
}
if (!name || name == "." || name == "..") {
___setErrNo(ERRNO_CODES.ENOENT);
throw new Error("Name must not be empty.");
}
if (parent.contents.hasOwnProperty(name)) {
___setErrNo(ERRNO_CODES.EEXIST);
throw new Error("Can't overwrite object.");
}
parent.contents[name] = {
read: canRead === undefined ? true : canRead,
write: canWrite === undefined ? false : canWrite,
timestamp: Date.now(),
inodeNumber: FS.nextInode++
};
for (var key in properties) {
if (properties.hasOwnProperty(key)) {
parent.contents[name][key] = properties[key];
}
}
return parent.contents[name];
}),
createFolder: (function(parent, name, canRead, canWrite) {
var properties = {
isFolder: true,
isDevice: false,
contents: {}
};
return FS.createObject(parent, name, properties, canRead, canWrite);
}),
createPath: (function(parent, path, canRead, canWrite) {
var current = FS.findObject(parent);
if (current === null) throw new Error("Invalid parent.");
path = path.split("/").reverse();
while (path.length) {
var part = path.pop();
if (!part) continue;
if (!current.contents.hasOwnProperty(part)) {
FS.createFolder(current, part, canRead, canWrite);
}
current = current.contents[part];
}
return current;
}),
createFile: (function(parent, name, properties, canRead, canWrite) {
properties.isFolder = false;
return FS.createObject(parent, name, properties, canRead, canWrite);
}),
createDataFile: (function(parent, name, data, canRead, canWrite) {
if (typeof data === "string") {
var dataArray = new Array(data.length);
for (var i = 0, len = data.length; i < len; ++i) dataArray[i] = data.charCodeAt(i);
data = dataArray;
}
var properties = {
isDevice: false,
contents: data.subarray ? data.subarray(0) : data
};
return FS.createFile(parent, name, properties, canRead, canWrite);
}),
createLazyFile: (function(parent, name, url, canRead, canWrite) {
if (typeof XMLHttpRequest !== "undefined") {
if (!ENVIRONMENT_IS_WORKER) throw "Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";
var LazyUint8Array = (function(chunkSize, length) {
this.length = length;
this.chunkSize = chunkSize;
this.chunks = [];
});
LazyUint8Array.prototype.get = (function(idx) {
if (idx > this.length - 1 || idx < 0) {
return undefined;
}
var chunkOffset = idx % chunkSize;
var chunkNum = Math.floor(idx / chunkSize);
return this.getter(chunkNum)[chunkOffset];
});
LazyUint8Array.prototype.setDataGetter = (function(getter) {
this.getter = getter;
});
var xhr = new XMLHttpRequest;
xhr.open("HEAD", url, false);
xhr.send(null);
if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
var datalength = Number(xhr.getResponseHeader("Content-length"));
var header;
var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
var chunkSize = 1024 * 1024;
if (!hasByteServing) chunkSize = datalength;
var doXHR = (function(from, to) {
if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
if (to > datalength - 1) throw new Error("only " + datalength + " bytes available! programmer error!");
var xhr = new XMLHttpRequest;
xhr.open("GET", url, false);
if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
if (typeof Uint8Array != "undefined") xhr.responseType = "arraybuffer";
if (xhr.overrideMimeType) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
xhr.send(null);
if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
if (xhr.response !== undefined) {
return new Uint8Array(xhr.response || []);
} else {
return intArrayFromString(xhr.responseText || "", true);
}
});
var lazyArray = new LazyUint8Array(chunkSize, datalength);
lazyArray.setDataGetter((function(chunkNum) {
var start = chunkNum * lazyArray.chunkSize;
var end = (chunkNum + 1) * lazyArray.chunkSize - 1;
end = Math.min(end, datalength - 1);
if (typeof lazyArray.chunks[chunkNum] === "undefined") {
lazyArray.chunks[chunkNum] = doXHR(start, end);
}
if (typeof lazyArray.chunks[chunkNum] === "undefined") throw new Error("doXHR failed!");
return lazyArray.chunks[chunkNum];
}));
var properties = {
isDevice: false,
contents: lazyArray
};
} else {
var properties = {
isDevice: false,
url: url
};
}
return FS.createFile(parent, name, properties, canRead, canWrite);
}),
createPreloadedFile: (function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) {
Browser.ensureObjects();
var fullname = FS.joinPath([ parent, name ], true);
function processData(byteArray) {
function finish(byteArray) {
if (!dontCreateFile) {
FS.createDataFile(parent, name, byteArray, canRead, canWrite);
}
if (onload) onload();
removeRunDependency("cp " + fullname);
}
var handled = false;
Module["preloadPlugins"].forEach((function(plugin) {
if (handled) return;
if (plugin["canHandle"](fullname)) {
plugin["handle"](byteArray, fullname, finish, (function() {
if (onerror) onerror();
removeRunDependency("cp " + fullname);
}));
handled = true;
}
}));
if (!handled) finish(byteArray);
}
addRunDependency("cp " + fullname);
if (typeof url == "string") {
Browser.asyncLoad(url, (function(byteArray) {
processData(byteArray);
}), onerror);
} else {
processData(url);
}
}),
createLink: (function(parent, name, target, canRead, canWrite) {
var properties = {
isDevice: false,
link: target
};
return FS.createFile(parent, name, properties, canRead, canWrite);
}),
createDevice: (function(parent, name, input, output) {
if (!(input || output)) {
throw new Error("A device must have at least one callback defined.");
}
var ops = {
isDevice: true,
input: input,
output: output
};
return FS.createFile(parent, name, ops, Boolean(input), Boolean(output));
}),
forceLoadFile: (function(obj) {
if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
var success = true;
if (typeof XMLHttpRequest !== "undefined") {
throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
} else if (Module["read"]) {
try {
obj.contents = intArrayFromString(Module["read"](obj.url), true);
} catch (e) {
success = false;
}
} else {
throw new Error("Cannot load without read() or XMLHttpRequest.");
}
if (!success) ___setErrNo(ERRNO_CODES.EIO);
return success;
}),
ensureRoot: (function() {
if (FS.root) return;
FS.root = {
read: true,
write: true,
isFolder: true,
isDevice: false,
timestamp: Date.now(),
inodeNumber: 1,
contents: {}
};
}),
init: (function(input, output, error) {
assert(!FS.init.initialized, "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");
FS.init.initialized = true;
FS.ensureRoot();
input = input || Module["stdin"];
output = output || Module["stdout"];
error = error || Module["stderr"];
var stdinOverridden = true, stdoutOverridden = true, stderrOverridden = true;
if (!input) {
stdinOverridden = false;
input = (function() {
if (!input.cache || !input.cache.length) {
var result;
if (typeof window != "undefined" && typeof window.prompt == "function") {
result = window.prompt("Input: ");
if (result === null) result = String.fromCharCode(0);
} else if (typeof readline == "function") {
result = readline();
}
if (!result) result = "";
input.cache = intArrayFromString(result + "\n", true);
}
return input.cache.shift();
});
}
var utf8 = new Runtime.UTF8Processor;
function simpleOutput(val) {
if (val === null || val === "\n".charCodeAt(0)) {
output.printer(output.buffer.join(""));
output.buffer = [];
} else {
output.buffer.push(utf8.processCChar(val));
}
}
if (!output) {
stdoutOverridden = false;
output = simpleOutput;
}
if (!output.printer) output.printer = Module["print"];
if (!output.buffer) output.buffer = [];
if (!error) {
stderrOverridden = false;
error = simpleOutput;
}
if (!error.printer) error.printer = Module["print"];
if (!error.buffer) error.buffer = [];
try {
FS.createFolder("/", "tmp", true, true);
} catch (e) {}
var devFolder = FS.createFolder("/", "dev", true, true);
var stdin = FS.createDevice(devFolder, "stdin", input);
var stdout = FS.createDevice(devFolder, "stdout", null, output);
var stderr = FS.createDevice(devFolder, "stderr", null, error);
FS.createDevice(devFolder, "tty", input, output);
FS.streams[1] = {
path: "/dev/stdin",
object: stdin,
position: 0,
isRead: true,
isWrite: false,
isAppend: false,
isTerminal: !stdinOverridden,
error: false,
eof: false,
ungotten: []
};
FS.streams[2] = {
path: "/dev/stdout",
object: stdout,
position: 0,
isRead: false,
isWrite: true,
isAppend: false,
isTerminal: !stdoutOverridden,
error: false,
eof: false,
ungotten: []
};
FS.streams[3] = {
path: "/dev/stderr",
object: stderr,
position: 0,
isRead: false,
isWrite: true,
isAppend: false,
isTerminal: !stderrOverridden,
error: false,
eof: false,
ungotten: []
};
_stdin = allocate([ 1 ], "void*", ALLOC_STACK);
_stdout = allocate([ 2 ], "void*", ALLOC_STACK);
_stderr = allocate([ 3 ], "void*", ALLOC_STACK);
FS.createPath("/", "dev/shm/tmp", true, true);
for (var i = FS.streams.length; i < Math.max(_stdin, _stdout, _stderr) + 4; i++) {
FS.streams[i] = null;
}
FS.streams[_stdin] = FS.streams[1];
FS.streams[_stdout] = FS.streams[2];
FS.streams[_stderr] = FS.streams[3];
__impure_ptr = allocate([ allocate([ 0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0 ], "void*", ALLOC_STATIC) ], "void*", ALLOC_STATIC);
}),
quit: (function() {
if (!FS.init.initialized) return;
if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output("\n".charCodeAt(0));
if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output("\n".charCodeAt(0));
}),
standardizePath: (function(path) {
if (path.substr(0, 2) == "./") path = path.substr(2);
return path;
}),
deleteFile: (function(path) {
var path = FS.analyzePath(path);
if (!path.parentExists || !path.exists) {
throw "Invalid path " + path;
}
delete path.parentObject.contents[path.name];
})
};
function _pwrite(fildes, buf, nbyte, offset) {
var stream = FS.streams[fildes];
if (!stream || stream.object.isDevice) {
___setErrNo(ERRNO_CODES.EBADF);
return -1;
} else if (!stream.isWrite) {
___setErrNo(ERRNO_CODES.EACCES);
return -1;
} else if (stream.object.isFolder) {
___setErrNo(ERRNO_CODES.EISDIR);
return -1;
} else if (nbyte < 0 || offset < 0) {
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
} else {
var contents = stream.object.contents;
while (contents.length < offset) contents.push(0);
for (var i = 0; i < nbyte; i++) {
contents[offset + i] = HEAP[buf + i];
}
stream.object.timestamp = Date.now();
return i;
}
}
function _write(fildes, buf, nbyte) {
var stream = FS.streams[fildes];
if (!stream) {
___setErrNo(ERRNO_CODES.EBADF);
return -1;
} else if (!stream.isWrite) {
___setErrNo(ERRNO_CODES.EACCES);
return -1;
} else if (nbyte < 0) {
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
} else {
if (stream.object.isDevice) {
if (stream.object.output) {
for (var i = 0; i < nbyte; i++) {
try {
stream.object.output(HEAP[buf + i]);
} catch (e) {
___setErrNo(ERRNO_CODES.EIO);
return -1;
}
}
stream.object.timestamp = Date.now();
return i;
} else {
___setErrNo(ERRNO_CODES.ENXIO);
return -1;
}
} else {
var bytesWritten = _pwrite(fildes, buf, nbyte, stream.position);
if (bytesWritten != -1) stream.position += bytesWritten;
return bytesWritten;
}
}
}
function _fwrite(ptr, size, nitems, stream) {
var bytesToWrite = nitems * size;
if (bytesToWrite == 0) return 0;
var bytesWritten = _write(stream, ptr, bytesToWrite);
if (bytesWritten == -1) {
if (FS.streams[stream]) FS.streams[stream].error = true;
return -1;
} else {
return Math.floor(bytesWritten / size);
}
}
function __formatString(format, varargs) {
var textIndex = format;
var argIndex = 0;
function getNextArg(type) {
var ret;
if (type === "double") {
ret = HEAP[varargs + argIndex];
} else if (type == "i64") {
ret = HEAP[varargs + argIndex];
} else {
type = "i32";
ret = HEAP[varargs + argIndex];
}
argIndex += Runtime.getNativeFieldSize(type);
return ret;
}
var ret = [];
var curr, next, currArg;
while (1) {
var startTextIndex = textIndex;
curr = HEAP[textIndex];
if (curr === 0) break;
next = HEAP[textIndex + 1];
if (curr == "%".charCodeAt(0)) {
var flagAlwaysSigned = false;
var flagLeftAlign = false;
var flagAlternative = false;
var flagZeroPad = false;
flagsLoop : while (1) {
switch (next) {
case "+".charCodeAt(0):
flagAlwaysSigned = true;
break;
case "-".charCodeAt(0):
flagLeftAlign = true;
break;
case "#".charCodeAt(0):
flagAlternative = true;
break;
case "0".charCodeAt(0):
if (flagZeroPad) {
break flagsLoop;
} else {
flagZeroPad = true;
break;
}
default:
break flagsLoop;
}
textIndex++;
next = HEAP[textIndex + 1];
}
var width = 0;
if (next == "*".charCodeAt(0)) {
width = getNextArg("i32");
textIndex++;
next = HEAP[textIndex + 1];
} else {
while (next >= "0".charCodeAt(0) && next <= "9".charCodeAt(0)) {
width = width * 10 + (next - "0".charCodeAt(0));
textIndex++;
next = HEAP[textIndex + 1];
}
}
var precisionSet = false;
if (next == ".".charCodeAt(0)) {
var precision = 0;
precisionSet = true;
textIndex++;
next = HEAP[textIndex + 1];
if (next == "*".charCodeAt(0)) {
precision = getNextArg("i32");
textIndex++;
} else {
while (1) {
var precisionChr = HEAP[textIndex + 1];
if (precisionChr < "0".charCodeAt(0) || precisionChr > "9".charCodeAt(0)) break;
precision = precision * 10 + (precisionChr - "0".charCodeAt(0));
textIndex++;
}
}
next = HEAP[textIndex + 1];
} else {
var precision = 6;
}
var argSize;
switch (String.fromCharCode(next)) {
case "h":
var nextNext = HEAP[textIndex + 2];
if (nextNext == "h".charCodeAt(0)) {
textIndex++;
argSize = 1;
} else {
argSize = 2;
}
break;
case "l":
var nextNext = HEAP[textIndex + 2];
if (nextNext == "l".charCodeAt(0)) {
textIndex++;
argSize = 8;
} else {
argSize = 4;
}
break;
case "L":
case "q":
case "j":
argSize = 8;
break;
case "z":
case "t":
case "I":
argSize = 4;
break;
default:
argSize = null;
}
if (argSize) textIndex++;
next = HEAP[textIndex + 1];
if ([ "d", "i", "u", "o", "x", "X", "p" ].indexOf(String.fromCharCode(next)) != -1) {
var signed = next == "d".charCodeAt(0) || next == "i".charCodeAt(0);
argSize = argSize || 4;
var currArg = getNextArg("i" + argSize * 8);
var origArg = currArg;
var argText;
if (argSize <= 4) {
var limit = Math.pow(256, argSize) - 1;
currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
}
var currAbsArg = Math.abs(currArg);
var prefix = "";
if (next == "d".charCodeAt(0) || next == "i".charCodeAt(0)) {
if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1]); else argText = reSign(currArg, 8 * argSize, 1).toString(10);
} else if (next == "u".charCodeAt(0)) {
if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else argText = unSign(currArg, 8 * argSize, 1).toString(10);
currArg = Math.abs(currArg);
} else if (next == "o".charCodeAt(0)) {
argText = (flagAlternative ? "0" : "") + currAbsArg.toString(8);
} else if (next == "x".charCodeAt(0) || next == "X".charCodeAt(0)) {
prefix = flagAlternative ? "0x" : "";
if (currArg < 0) {
currArg = -currArg;
argText = (currAbsArg - 1).toString(16);
var buffer = [];
for (var i = 0; i < argText.length; i++) {
buffer.push((15 - parseInt(argText[i], 16)).toString(16));
}
argText = buffer.join("");
while (argText.length < argSize * 2) argText = "f" + argText;
} else {
argText = currAbsArg.toString(16);
}
if (next == "X".charCodeAt(0)) {
prefix = prefix.toUpperCase();
argText = argText.toUpperCase();
}
} else if (next == "p".charCodeAt(0)) {
if (currAbsArg === 0) {
argText = "(nil)";
} else {
prefix = "0x";
argText = currAbsArg.toString(16);
}
}
if (precisionSet) {
while (argText.length < precision) {
argText = "0" + argText;
}
}
if (flagAlwaysSigned) {
if (currArg < 0) {
prefix = "-" + prefix;
} else {
prefix = "+" + prefix;
}
}
while (prefix.length + argText.length < width) {
if (flagLeftAlign) {
argText += " ";
} else {
if (flagZeroPad) {
argText = "0" + argText;
} else {
prefix = " " + prefix;
}
}
}
argText = prefix + argText;
argText.split("").forEach((function(chr) {
ret.push(chr.charCodeAt(0));
}));
} else if ([ "f", "F", "e", "E", "g", "G" ].indexOf(String.fromCharCode(next)) != -1) {
var currArg = getNextArg("double");
var argText;
if (isNaN(currArg)) {
argText = "nan";
flagZeroPad = false;
} else if (!isFinite(currArg)) {
argText = (currArg < 0 ? "-" : "") + "inf";
flagZeroPad = false;
} else {
var isGeneral = false;
var effectivePrecision = Math.min(precision, 20);
if (next == "g".charCodeAt(0) || next == "G".charCodeAt(0)) {
isGeneral = true;
precision = precision || 1;
var exponent = parseInt(currArg.toExponential(effectivePrecision).split("e")[1], 10);
if (precision > exponent && exponent >= -4) {
next = (next == "g".charCodeAt(0) ? "f" : "F").charCodeAt(0);
precision -= exponent + 1;
} else {
next = (next == "g".charCodeAt(0) ? "e" : "E").charCodeAt(0);
precision--;
}
effectivePrecision = Math.min(precision, 20);
}
if (next == "e".charCodeAt(0) || next == "E".charCodeAt(0)) {
argText = currArg.toExponential(effectivePrecision);
if (/[eE][-+]\d$/.test(argText)) {
argText = argText.slice(0, -1) + "0" + argText.slice(-1);
}
} else if (next == "f".charCodeAt(0) || next == "F".charCodeAt(0)) {
argText = currArg.toFixed(effectivePrecision);
}
var parts = argText.split("e");
if (isGeneral && !flagAlternative) {
while (parts[0].length > 1 && parts[0].indexOf(".") != -1 && (parts[0].slice(-1) == "0" || parts[0].slice(-1) == ".")) {
parts[0] = parts[0].slice(0, -1);
}
} else {
if (flagAlternative && argText.indexOf(".") == -1) parts[0] += ".";
while (precision > effectivePrecision++) parts[0] += "0";
}
argText = parts[0] + (parts.length > 1 ? "e" + parts[1] : "");
if (next == "E".charCodeAt(0)) argText = argText.toUpperCase();
if (flagAlwaysSigned && currArg >= 0) {
argText = "+" + argText;
}
}
while (argText.length < width) {
if (flagLeftAlign) {
argText += " ";
} else {
if (flagZeroPad && (argText[0] == "-" || argText[0] == "+")) {
argText = argText[0] + "0" + argText.slice(1);
} else {
argText = (flagZeroPad ? "0" : " ") + argText;
}
}
}
if (next < "a".charCodeAt(0)) argText = argText.toUpperCase();
argText.split("").forEach((function(chr) {
ret.push(chr.charCodeAt(0));
}));
} else if (next == "s".charCodeAt(0)) {
var arg = getNextArg("i8*") || nullString;
var argLength = String_len(arg);
if (precisionSet) argLength = Math.min(argLength, precision);
if (!flagLeftAlign) {
while (argLength < width--) {
ret.push(" ".charCodeAt(0));
}
}
for (var i = 0; i < argLength; i++) {
ret.push(HEAP[arg++]);
}
if (flagLeftAlign) {
while (argLength < width--) {
ret.push(" ".charCodeAt(0));
}
}
} else if (next == "c".charCodeAt(0)) {
if (flagLeftAlign) ret.push(getNextArg("i8"));
while (--width > 0) {
ret.push(" ".charCodeAt(0));
}
if (!flagLeftAlign) ret.push(getNextArg("i8"));
} else if (next == "n".charCodeAt(0)) {
var ptr = getNextArg("i32*");
HEAP[ptr] = ret.length;
} else if (next == "%".charCodeAt(0)) {
ret.push(curr);
} else {
for (var i = startTextIndex; i < textIndex + 2; i++) {
ret.push(HEAP[i]);
}
}
textIndex += 2;
} else {
ret.push(curr);
textIndex += 1;
}
}
return ret;
}
function _fprintf(stream, format, varargs) {
var result = __formatString(format, varargs);
var stack = Runtime.stackSave();
var ret = _fwrite(allocate(result, "i8", ALLOC_STACK), 1, result.length, stream);
Runtime.stackRestore(stack);
return ret;
}
function _printf(format, varargs) {
var stdout = HEAP[_stdout];
return _fprintf(stdout, format, varargs);
}
function _memcpy(dest, src, num, align) {
for (var $$src = src, $$dest = dest, $$stop = $$src + num; $$src < $$stop; $$src++, $$dest++) {
HEAP[$$dest] = HEAP[$$src];
}
}
function _memset(ptr, value, num, align) {
for (var $$dest = ptr, $$stop = $$dest + num; $$dest < $$stop; $$dest++) {
HEAP[$$dest] = value;
}
}
function _malloc(bytes) {
ptr = Runtime.staticAlloc(bytes + 8);
return ptr + 8 & 4294967288;
}
Module["_malloc"] = _malloc;
function _free() {}
Module["_free"] = _free;
var Browser = {
mainLoop: {
scheduler: null,
shouldPause: false,
paused: false,
queue: [],
pause: (function() {
Browser.mainLoop.shouldPause = true;
}),
resume: (function() {
if (Browser.mainLoop.paused) {
Browser.mainLoop.paused = false;
Browser.mainLoop.scheduler();
}
Browser.mainLoop.shouldPause = false;
}),
updateStatus: (function() {
if (Module["setStatus"]) {
var message = Module["statusMessage"] || "Please wait...";
var remaining = Browser.mainLoop.remainingBlockers;
var expected = Browser.mainLoop.expectedBlockers;
if (remaining) {
if (remaining < expected) {
Module["setStatus"](message + " (" + (expected - remaining) + "/" + expected + ")");
} else {
Module["setStatus"](message);
}
} else {
Module["setStatus"]("");
}
}
})
},
pointerLock: false,
moduleContextCreatedCallbacks: [],
workers: [],
ensureObjects: (function() {
if (Browser.ensured) return;
Browser.ensured = true;
try {
new Blob;
Browser.hasBlobConstructor = true;
} catch (e) {
Browser.hasBlobConstructor = false;
console.log("warning: no blob constructor, cannot create blobs with mimetypes");
}
Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : !Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null;
Browser.URLObject = typeof window != "undefined" ? window.URL ? window.URL : window.webkitURL : console.log("warning: cannot create object URLs");
function getMimetype(name) {
return {
"jpg": "image/jpeg",
"png": "image/png",
"bmp": "image/bmp",
"ogg": "audio/ogg",
"wav": "audio/wav",
"mp3": "audio/mpeg"
}[name.substr(-3)];
return ret;
}
if (!Module["preloadPlugins"]) Module["preloadPlugins"] = [];
var imagePlugin = {};
imagePlugin["canHandle"] = (function(name) {
return name.substr(-4) in {
".jpg": 1,
".png": 1,
".bmp": 1
};
});
imagePlugin["handle"] = (function(byteArray, name, onload, onerror) {
var b = null;
if (Browser.hasBlobConstructor) {
try {
b = new Blob([ byteArray ], {
type: getMimetype(name)
});
} catch (e) {
Runtime.warnOnce("Blob constructor present but fails: " + e + "; falling back to blob builder");
}
}
if (!b) {
var bb = new Browser.BlobBuilder;
bb.append((new Uint8Array(byteArray)).buffer);
b = bb.getBlob();
}
var url = Browser.URLObject.createObjectURL(b);
var img = new Image;
img.onload = (function() {
assert(img.complete, "Image " + name + " could not be decoded");
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
Module["preloadedImages"][name] = canvas;
Browser.URLObject.revokeObjectURL(url);
if (onload) onload(byteArray);
});
img.onerror = (function(event) {
console.log("Image " + url + " could not be decoded");
if (onerror) onerror();
});
img.src = url;
});
Module["preloadPlugins"].push(imagePlugin);
var audioPlugin = {};
audioPlugin["canHandle"] = (function(name) {
return name.substr(-4) in {
".ogg": 1,
".wav": 1,
".mp3": 1
};
});
audioPlugin["handle"] = (function(byteArray, name, onload, onerror) {
var done = false;
function finish(audio) {
if (done) return;
done = true;
Module["preloadedAudios"][name] = audio;
if (onload) onload(byteArray);
}
function fail() {
if (done) return;
done = true;
Module["preloadedAudios"][name] = new Audio;
if (onerror) onerror();
}
if (Browser.hasBlobConstructor) {
try {
var b = new Blob([ byteArray ], {
type: getMimetype(name)
});
} catch (e) {
return fail();
}
var url = Browser.URLObject.createObjectURL(b);
var audio = new Audio;
audio.addEventListener("canplaythrough", (function() {
finish(audio);
}), false);
audio.onerror = (function(event) {
if (done) return;
console.log("warning: browser could not fully decode audio " + name + ", trying slower base64 approach");
function encode64(data) {
var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var PAD = "=";
var ret = "";
var leftchar = 0;
var leftbits = 0;
for (var i = 0; i < data.length; i++) {
leftchar = leftchar << 8 | data[i];
leftbits += 8;
while (leftbits >= 6) {
var curr = leftchar >> leftbits - 6 & 63;
leftbits -= 6;
ret += BASE[curr];
}
}
if (leftbits == 2) {
ret += BASE[(leftchar & 3) << 4];
ret += PAD + PAD;
} else if (leftbits == 4) {
ret += BASE[(leftchar & 15) << 2];
ret += PAD;
}
return ret;
}
audio.src = "data:audio/x-" + name.substr(-3) + ";base64," + encode64(byteArray);
finish(audio);
});
audio.src = url;
setTimeout((function() {
finish(audio);
}), 1e4);
} else {
return fail();
}
});
Module["preloadPlugins"].push(audioPlugin);
}),
createContext: (function(canvas, useWebGL, setInModule) {
try {
var ctx = canvas.getContext(useWebGL ? "experimental-webgl" : "2d");
if (!ctx) throw ":(";
} catch (e) {
Module.print("Could not create canvas - " + e);
return null;
}
if (useWebGL) {
canvas.style.backgroundColor = "black";
canvas.addEventListener("webglcontextlost", (function(event) {
alert("WebGL context lost. You will need to reload the page.");
}), false);
}
if (setInModule) {
Module.ctx = ctx;
Module.useWebGL = useWebGL;
Browser.moduleContextCreatedCallbacks.forEach((function(callback) {
callback();
}));
}
return ctx;
}),
requestFullScreen: (function() {
var canvas = Module["canvas"];
function fullScreenChange() {
var isFullScreen = false;
if ((document["webkitFullScreenElement"] || document["webkitFullscreenElement"] || document["mozFullScreenElement"] || document["mozFullscreenElement"] || document["fullScreenElement"] || document["fullscreenElement"]) === canvas) {
canvas.requestPointerLock = canvas["requestPointerLock"] || canvas["mozRequestPointerLock"] || canvas["webkitRequestPointerLock"];
canvas.requestPointerLock();
isFullScreen = true;
}
if (Module["onFullScreen"]) Module["onFullScreen"](isFullScreen);
}
document.addEventListener("fullscreenchange", fullScreenChange, false);
document.addEventListener("mozfullscreenchange", fullScreenChange, false);
document.addEventListener("webkitfullscreenchange", fullScreenChange, false);
function pointerLockChange() {
Browser.pointerLock = document["pointerLockElement"] === canvas || document["mozPointerLockElement"] === canvas || document["webkitPointerLockElement"] === canvas;
}
document.addEventListener("pointerlockchange", pointerLockChange, false);
document.addEventListener("mozpointerlockchange", pointerLockChange, false);
document.addEventListener("webkitpointerlockchange", pointerLockChange, false);
canvas.requestFullScreen = canvas["requestFullScreen"] || canvas["mozRequestFullScreen"] || (canvas["webkitRequestFullScreen"] ? (function() {
canvas["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]);
}) : null);
canvas.requestFullScreen();
}),
requestAnimationFrame: (function(func) {
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = window["requestAnimationFrame"] || window["mozRequestAnimationFrame"] || window["webkitRequestAnimationFrame"] || window["msRequestAnimationFrame"] || window["oRequestAnimationFrame"] || window["setTimeout"];
}
window.requestAnimationFrame(func);
}),
getMovementX: (function(event) {
return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0;
}),
getMovementY: (function(event) {
return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0;
}),
xhrLoad: (function(url, onload, onerror) {
var xhr = new XMLHttpRequest;
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = (function() {
if (xhr.status == 200) {
onload(xhr.response);
} else {
onerror();
}
});
xhr.onerror = onerror;
xhr.send(null);
}),
asyncLoad: (function(url, onload, onerror) {
Browser.xhrLoad(url, (function(arrayBuffer) {
assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
onload(new Uint8Array(arrayBuffer));
removeRunDependency("al " + url);
}), (function(event) {
if (onerror) {
onerror();
} else {
throw 'Loading data file "' + url + '" failed.';
}
}));
addRunDependency("al " + url);
}),
resizeListeners: [],
updateResizeListeners: (function() {
var canvas = Module["canvas"];
Browser.resizeListeners.forEach((function(listener) {
listener(canvas.width, canvas.height);
}));
}),
setCanvasSize: (function(width, height, noUpdates) {
var canvas = Module["canvas"];
canvas.width = width;
canvas.height = height;
if (!noUpdates) Browser.updateResizeListeners();
})
};
__ATINIT__.unshift({
func: (function() {
if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
})
});
__ATMAIN__.push({
func: (function() {
FS.ignorePermissions = false;
})
});
__ATEXIT__.push({
func: (function() {
FS.quit();
})
});
Module["FS_createFolder"] = FS.createFolder;
Module["FS_createPath"] = FS.createPath;
Module["FS_createDataFile"] = FS.createDataFile;
Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
Module["FS_createLazyFile"] = FS.createLazyFile;
Module["FS_createLink"] = FS.createLink;
Module["FS_createDevice"] = FS.createDevice;
___setErrNo(0);
Module["requestFullScreen"] = (function() {
Browser.requestFullScreen();
});
Module["requestAnimationFrame"] = (function(func) {
Browser.requestAnimationFrame(func);
});
Module["pauseMainLoop"] = (function() {
Browser.mainLoop.pause();
});
Module["resumeMainLoop"] = (function() {
Browser.mainLoop.resume();
});
Module.callMain = function callMain(args) {
var argc = args.length + 1;
function pad() {
for (var i = 0; i < 4 - 1; i++) {
argv.push(0);
}
}
var argv = [ allocate(intArrayFromString("/bin/this.program"), "i8", ALLOC_STATIC) ];
pad();
for (var i = 0; i < argc - 1; i = i + 1) {
argv.push(allocate(intArrayFromString(args[i]), "i8", ALLOC_STATIC));
pad();
}
argv.push(0);
argv = allocate(argv, "i32", ALLOC_STATIC);
return _main(argc, argv, 0);
};
STRING_TABLE.__str = allocate([ 37, 115, 0 ], "i8", ALLOC_STATIC);
STRING_TABLE.__str1 = allocate([ 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33, 0 ], "i8", ALLOC_STATIC);
FUNCTION_TABLE = [ 0, 0 ];
Module["FUNCTION_TABLE"] = FUNCTION_TABLE;
function run(args) {
args = args || Module["arguments"];
if (runDependencies > 0) {
Module.printErr("run() called, but dependencies remain, so not running");
return 0;
}
if (Module["preRun"]) {
if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
var toRun = Module["preRun"];
Module["preRun"] = [];
for (var i = toRun.length - 1; i >= 0; i--) {
toRun[i]();
}
if (runDependencies > 0) {
return 0;
}
}
function doRun() {
var ret = 0;
calledRun = true;
if (Module["_main"]) {
preMain();
ret = Module.callMain(args);
if (!Module["noExitRuntime"]) {
exitRuntime();
}
}
if (Module["postRun"]) {
if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
while (Module["postRun"].length > 0) {
Module["postRun"].pop()();
}
}
return ret;
}
if (Module["setStatus"]) {
Module["setStatus"]("Running...");
setTimeout((function() {
setTimeout((function() {
Module["setStatus"]("");
}), 1);
doRun();
}), 1);
return 0;
} else {
return doRun();
}
}
Module["run"] = run;
if (Module["preInit"]) {
if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
while (Module["preInit"].length > 0) {
Module["preInit"].pop()();
}
}
initRuntime();
var shouldRunNow = true;
if (Module["noInitialRun"]) {
shouldRunNow = false;
}
if (shouldRunNow) {
var ret = run();
}
// EMSCRIPTEN_GENERATED_FUNCTIONS: ["_main"]
Дело в том, что тут не напрямую из языка (С/С++ или другого) а через промежуточный байткод LLVM-машины. Собственно за счет этого переводчик из чего угодно в JavaScript.
Зато из коробки есть примеры таким макаром перегнанных OpenJPEG кодкеа, интерпретатора Lua, физического движка Bullet, библиотеки рендеринга(просмотра) PDF Poppler и кое-чего другого.
Зато из коробки есть примеры таким макаром перегнанных OpenJPEG кодкеа, интерпретатора Lua, физического движка Bullet, библиотеки рендеринга(просмотра) PDF Poppler и кое-чего другого.