// An implementation of a libc for the web. Basically, implementations of
// the various standard C libraries, that can be called from compiled code,
// and work using the actual JavaScript environment.
//
// We search the Library object when there is an external function. If the
// entry in the Library is a function, we insert it. If it is a string, we
// do another lookup in the library (a simple way to write a function once,
// if it can be called by different names). We also allow dependencies,
// using __deps.
//
// Note that the full function name will be '_' + the name in the Library
// object. For convenience, the short name appears here. Note that if you add a
// new function with an '_', it will not be found.
var Library = {
// stdio.h
_formatString: function() {
function isFloatArg(type) {
return String.fromCharCode(type) in Runtime.set('f', 'e', 'g');
}
var cStyle = false;
var textIndex = arguments[0];
var argIndex = 1;
if (textIndex < 0) {
cStyle = true;
textIndex = -textIndex;
slab = null;
argIndex = arguments[1];
} else {
var _arguments = arguments;
}
function getNextArg(type) {
var ret;
if (!cStyle) {
ret = _arguments[argIndex];
argIndex++;
} else {
if (isFloatArg(type)) {
ret = {{{ makeGetValue(0, 'argIndex', 'double') }}};
} else {
ret = {{{ makeGetValue(0, 'argIndex', 'i32') }}};
}
argIndex += type === 'l'.charCodeAt(0) ? 8 : 4; // XXX hardcoded native sizes
}
return ret;
}
var ret = [];
var curr, next, currArg;
while(1) {
curr = {{{ makeGetValue(0, 'textIndex', 'i8') }}};
if (curr === 0) break;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
if (curr == '%'.charCodeAt(0)) {
// Handle very very simply formatting, namely only %.X[f|d|u|etc.]
var precision = -1;
if (next == '.'.charCodeAt(0)) {
textIndex++;
precision = 0;
while(1) {
var precisionChr = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
if (!(precisionChr >= '0'.charCodeAt(0) && precisionChr <= '9'.charCodeAt(0))) break;
precision *= 10;
precision += precisionChr - '0'.charCodeAt(0);
textIndex++;
}
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
}
if (next == 'l'.charCodeAt(0)) {
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
}
if (isFloatArg(next)) {
next = 'f'.charCodeAt(0); // no support for 'e'
}
if (['d', 'i', 'u', 'p', 'f'].indexOf(String.fromCharCode(next)) != -1) {
var currArg;
var argText;
currArg = getNextArg(next);
argText = String(+currArg); // +: boolean=>int
if (next == 'u'.charCodeAt(0)) {
argText = String(unSign(currArg, 32));
} else if (next == 'p'.charCodeAt(0)) {
argText = '0x' + currArg.toString(16);
} else {
argText = String(+currArg); // +: boolean=>int
}
if (precision >= 0) {
if (isFloatArg(next)) {
var dotIndex = argText.indexOf('.');
if (dotIndex == -1 && next == 'f'.charCodeAt(0)) {
dotIndex = argText.length;
argText += '.';
}
argText += '00000000000'; // padding
argText = argText.substr(0, dotIndex+1+precision);
} else {
while (argText.length < precision) {
argText = '0' + argText;
}
}
}
argText.split('').forEach(function(chr) {
ret.push(chr.charCodeAt(0));
});
textIndex += 2;
} else if (next == 's'.charCodeAt(0)) {
ret = ret.concat(String_copy(getNextArg(next)));
textIndex += 2;
} else if (next == 'c'.charCodeAt(0)) {
ret =