summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormax99x <max99x@gmail.com>2011-07-28 13:55:24 +0300
committermax99x <max99x@gmail.com>2011-07-28 14:01:08 +0300
commit16f60de7f278ce8fb38253cfb1bf8d218dfe9ce9 (patch)
tree906d31b3c6bf8d6638e55cb96308c86333e1d7ff
parent4c3f2fb804c66e5056c8d26d206eed0114b12a40 (diff)
Implemented most of stdio.h and updated all references.
-rw-r--r--src/library.js1333
-rw-r--r--src/preamble.js40
-rw-r--r--tests/runner.py50
-rw-r--r--tests/unistd/dup.out12
-rw-r--r--tests/unistd/isatty.js2
5 files changed, 930 insertions, 507 deletions
diff --git a/src/library.js b/src/library.js
index 3e346280..1ef8d0ec 100644
--- a/src/library.js
+++ b/src/library.js
@@ -18,8 +18,12 @@ LibraryManager.library = {
// File system base.
// ==========================================================================
- $FS__deps: ['$ERRNO_CODES', '__setErrNo'],
- $FS__postset: 'FS.ignorePermissions = false;',
+ stdin: 0,
+ stdout: 0,
+ stderr: 0,
+
+ $FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr'],
+ $FS__postset: 'FS.init();',
$FS: {
// The main file system tree. All the contents are inside this.
root: {
@@ -240,7 +244,8 @@ LibraryManager.library = {
// Creates a character device with input and output callbacks:
// input: Takes no parameters, returns a byte value or null if no data is
// currently available.
- // output: Takes a byte value; doesn't return anything.
+ // output: Takes a byte value; doesn't return anything. Can also be passed
+ // null to perform a flush of any cached data.
createDevice: function(parent, name, input, output) {
if (!(input || output)) {
throw new Error('A device must have at least one callback defined.');
@@ -262,11 +267,11 @@ LibraryManager.library = {
xhr.overrideMimeType('text/plain; charset=x-user-defined'); // Binary.
xhr.send(null);
if (xhr.status != 200 && xhr.status != 0) success = false;
- obj.contents = intArrayFromString(xhr.responseText || '');
+ obj.contents = intArrayFromString(xhr.responseText || '', true);
} else if (typeof read !== 'undefined') {
// Command-line.
try {
- obj.contents = intArrayFromString(read(obj.url));
+ obj.contents = intArrayFromString(read(obj.url), true);
} catch (e) {
success = false;
}
@@ -275,6 +280,103 @@ LibraryManager.library = {
}
if (!success) ___setErrNo(ERRNO_CODES.EIO);
return success;
+ },
+ // Initializes the filesystems with stdin/stdout/stderr devices, given
+ // optional handlers.
+ init: function(input, output, error) {
+ // Make sure we initialize only once.
+ if (FS.init.initialized) return;
+ else FS.init.initialized = true;
+
+ // Default handlers.
+ if (!input) input = function() {
+ if (!input.cache) {
+ var result;
+ if (window && typeof window.prompt == 'function') {
+ // Browser.
+ result = window.prompt('Input: ');
+ } else if (typeof readline == 'function') {
+ // Command line.
+ result = readline();
+ }
+ if (!result) return null;
+ input.cache = intArrayFromString(result + '\n', true);
+ }
+ return input.cache.shift();
+ };
+ if (!output) output = function(val) {
+ if (!output.printer) {
+ if (typeof print == 'function') {
+ // Either console or custom print function defined.
+ output.printer = print;
+ } else if (console && typeof console.log == 'function') {
+ // Browser-like environment with a console.
+ output.printer = console.log;
+ } else {
+ // Fallback to a harmless no-op.
+ output.printer = function() {};
+ }
+ }
+ if (!output.buffer) output.buffer = [];
+ if (val === null || val === '\n'.charCodeAt(0)) {
+ output.printer(output.buffer.join(''));
+ output.buffer = [];
+ } else {
+ output.buffer.push(String.fromCharCode(val));
+ }
+ };
+ if (!error) error = output;
+
+ // Create the temporary folder.
+ FS.createFolder('/', 'tmp', true, true);
+
+ // Create the I/O devices.
+ var devFolder = FS.createFolder('/', 'dev', true, false);
+ var stdin = FS.createDevice(devFolder, 'stdin', input);
+ var stdout = FS.createDevice(devFolder, 'stdout', null, output);
+ var stderr = FS.createDevice(devFolder, 'stderr', null, error);
+ FS.createDevice(devFolder, 'tty', input, error);
+
+ // Create default streams.
+ FS.streams[1] = {
+ path: '/dev/stdin',
+ object: stdin,
+ position: 0,
+ isRead: true,
+ isWrite: false,
+ isAppend: false,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ FS.streams[2] = {
+ path: '/dev/stdout',
+ object: stdout,
+ position: 0,
+ isRead: false,
+ isWrite: true,
+ isAppend: false,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ FS.streams[3] = {
+ path: '/dev/stderr',
+ object: stderr,
+ position: 0,
+ isRead: false,
+ isWrite: true,
+ isAppend: false,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ _stdin = allocate([1], 'void*', ALLOC_STATIC);
+ _stdout = allocate([2], 'void*', ALLOC_STATIC);
+ _stderr = allocate([3], 'void*', ALLOC_STATIC);
+
+ // Once initialized, permissions start having effect.
+ FS.ignorePermissions = false;
}
},
@@ -307,14 +409,20 @@ LibraryManager.library = {
var contents = [];
for (var key in target.contents) contents.push(key);
FS.streams[id] = {
- isFolder: true,
path: path,
object: target,
+ // An index into contents. Special values: -2 is ".", -1 is "..".
+ position: -2,
+ isRead: true,
+ isWrite: false,
+ isAppend: false,
+ error: false,
+ eof: false,
+ ungotten: [],
+ // Folder-specific properties:
// Remember the contents at the time of opening in an array, so we can
// seek between them relying on a single order.
contents: contents,
- // An index into contents. Special values: -2 is ".", -1 is "..".
- position: -2,
// Each stream has its own area for readdir() returns.
currentEntry: _malloc(___dirent_struct_layout.__size__)
};
@@ -324,7 +432,7 @@ LibraryManager.library = {
closedir: function(dirp) {
// int closedir(DIR *dirp);
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/closedir.html
- if (!FS.streams[dirp] || !FS.streams[dirp].isFolder) {
+ if (!FS.streams[dirp] || !FS.streams[dirp].object.isFolder) {
return ___setErrNo(ERRNO_CODES.EBADF);
} else {
_free(FS.streams[dirp].currentEntry);
@@ -336,7 +444,7 @@ LibraryManager.library = {
telldir: function(dirp) {
// long int telldir(DIR *dirp);
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/telldir.html
- if (!FS.streams[dirp] || !FS.streams[dirp].isFolder) {
+ if (!FS.streams[dirp] || !FS.streams[dirp].object.isFolder) {
return ___setErrNo(ERRNO_CODES.EBADF);
} else {
return FS.streams[dirp].position;
@@ -346,7 +454,7 @@ LibraryManager.library = {
seekdir: function(dirp, loc) {
// void seekdir(DIR *dirp, long int loc);
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/seekdir.html
- if (!FS.streams[dirp] || !FS.streams[dirp].isFolder) {
+ if (!FS.streams[dirp] || !FS.streams[dirp].object.isFolder) {
___setErrNo(ERRNO_CODES.EBADF);
} else {
var entries = 0;
@@ -368,7 +476,7 @@ LibraryManager.library = {
readdir_r: function(dirp, entry, result) {
// int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/readdir_r.html
- if (!FS.streams[dirp] || !FS.streams[dirp].isFolder) {
+ if (!FS.streams[dirp] || !FS.streams[dirp].object.isFolder) {
return ___setErrNo(ERRNO_CODES.EBADF);
}
var stream = FS.streams[dirp];
@@ -381,10 +489,10 @@ LibraryManager.library = {
var name, inode;
if (loc === -2) {
name = '.';
- inode = 1; // Really undefined.
+ inode = 1; // Really undefined.
} else if (loc === -1) {
name = '..';
- inode = 1; // Really undefined.
+ inode = 1; // Really undefined.
} else {
name = stream.contents[loc];
inode = stream.object.contents[name].inodeNumber;
@@ -398,9 +506,9 @@ LibraryManager.library = {
{{{ makeSetValue('entry + offsets.d_name', 'i', 'name.charCodeAt(i)', 'i8') }}}
}
{{{ makeSetValue('entry + offsets.d_name', 'i', '0', 'i8') }}}
- var type = stream.isDevice ? 2 // DT_CHR, character device.
- : stream.isFolder ? 4 // DT_DIR, directory.
- : stream.link !== undefined ? 10 // DT_LNK, symbolic link.
+ var type = stream.object.isDevice ? 2 // DT_CHR, character device.
+ : stream.object.isFolder ? 4 // DT_DIR, directory.
+ : stream.object.link !== undefined ? 10 // DT_LNK, symbolic link.
: 8; // DT_REG, regular file.
{{{ makeSetValue('entry', 'offsets.d_type', 'type', 'i8') }}}
{{{ makeSetValue('result', '0', 'entry', 'i8*') }}}
@@ -411,7 +519,7 @@ LibraryManager.library = {
readdir: function(dirp) {
// struct dirent *readdir(DIR *dirp);
// http://pubs.opengroup.org/onlinepubs/007908799/xsh/readdir_r.html
- if (!FS.streams[dirp] || !FS.streams[dirp].isFolder) {
+ if (!FS.streams[dirp] || !FS.streams[dirp].object.isFolder) {
___setErrNo(ERRNO_CODES.EBADF);
return 0;
} else {
@@ -721,7 +829,7 @@ LibraryManager.library = {
// ==========================================================================
__flock_struct_layout: Runtime.generateStructInfo(null, '%struct.flock'),
- open__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
+ open__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__dirent_struct_layout'],
open: function(path, oflag, mode) {
// int open(const char *path, int oflag, ...);
// http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html
@@ -738,6 +846,7 @@ LibraryManager.library = {
var isAppend = Boolean(oflag & 0x400); // O_APPEND.
// Verify path.
+ var origPath = path;
path = FS.analyzePath(Pointer_stringify(path));
if (!path.parentExists) {
___setErrNo(path.error);
@@ -779,18 +888,46 @@ LibraryManager.library = {
target = FS.createDataFile(path.parentObject, path.name, [],
mode & 0x100, mode & 0x80); // S_IRUSR, S_IWUSR.
}
-
// Actually create an open stream.
var id = FS.streams.length;
- FS.streams[id] = {
- isFolder: false,
- path: path.path,
- object: target,
- position: 0,
- isRead: isRead,
- isWrite: isWrite,
- isAppend: isAppend
- };
+ if (target.isFolder) {
+ var entryBuffer = 0;
+ if (___dirent_struct_layout) {
+ entryBuffer = _malloc(___dirent_struct_layout.__size__);
+ }
+ var contents = [];
+ for (var key in target.contents) contents.push(key);
+ FS.streams[id] = {
+ path: path.path,
+ object: target,
+ // An index into contents. Special values: -2 is ".", -1 is "..".
+ position: -2,
+ isRead: true,
+ isWrite: false,
+ isAppend: false,
+ error: false,
+ eof: false,
+ ungotten: [],
+ // Folder-specific properties:
+ // Remember the contents at the time of opening in an array, so we can
+ // seek between them relying on a single order.
+ contents: contents,
+ // Each stream has its own area for readdir() returns.
+ currentEntry: entryBuffer
+ };
+ } else {
+ FS.streams[id] = {
+ path: path.path,
+ object: target,
+ position: 0,
+ isRead: isRead,
+ isWrite: isWrite,
+ isAppend: isAppend,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ }
return id;
},
creat__deps: ['open'],
@@ -965,6 +1102,9 @@ LibraryManager.library = {
// int close(int fildes);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html
if (FS.streams[fildes]) {
+ if (FS.streams[fildes].currentEntry) {
+ _free(FS.streams[fildes].currentEntry);
+ }
delete FS.streams[fildes];
return 0;
} else {
@@ -1220,6 +1360,7 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
} else {
+ stream.ungotten = [];
stream.position = position;
return position;
}
@@ -1255,12 +1396,19 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
} else {
+ var bytesRead = 0;
+ while (stream.ungotten.length && nbyte > 0) {
+ {{{ makeSetValue('buf++', '0', 'stream.ungotten.pop()', 'i8') }}}
+ nbyte--;
+ bytesRead++;
+ }
var contents = stream.object.contents;
var size = Math.min(contents.length - offset, nbyte);
for (var i = 0; i < size; i++) {
{{{ makeSetValue('buf', 'i', 'contents[offset + i]', 'i8') }}}
+ bytesRead++;
}
- return i;
+ return bytesRead;
}
},
read__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'pread'],
@@ -1278,8 +1426,15 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
} else {
+ var bytesRead;
if (stream.object.isDevice) {
if (stream.object.input) {
+ bytesRead = 0;
+ while (stream.ungotten.length && nbyte > 0) {
+ {{{ makeSetValue('buf++', '0', 'stream.ungotten.pop()', 'i8') }}}
+ nbyte--;
+ bytesRead++;
+ }
for (var i = 0; i < nbyte; i++) {
try {
var result = stream.object.input();
@@ -1288,15 +1443,16 @@ LibraryManager.library = {
return -1;
}
if (result === null || result === undefined) break;
+ bytesRead++;
{{{ makeSetValue('buf', 'i', 'result', 'i8') }}}
}
- return i;
+ return bytesRead;
} else {
___setErrNo(ERRNO_CODES.ENXIO);
return -1;
}
} else {
- var bytesRead = _pread(fildes, buf, nbyte, stream.position);
+ bytesRead = _pread(fildes, buf, nbyte, stream.position);
if (bytesRead != -1) stream.position += bytesRead;
return bytesRead;
}
@@ -1444,6 +1600,7 @@ LibraryManager.library = {
for (var i = 0; i < nbyte; i++) {
contents[offset + i] = {{{ makeGetValue('buf', 'i', 'i8') }}};
}
+ stream.object.timestamp = new Date();
return i;
}
},
@@ -1472,6 +1629,7 @@ LibraryManager.library = {
return -1;
}
}
+ stream.object.timestamp = new Date();
return i;
} else {
___setErrNo(ERRNO_CODES.ENXIO);
@@ -1891,7 +2049,7 @@ LibraryManager.library = {
// We must control this entirely. So we don't even need to do
// unfreeable allocations - the HEAP is ours, from STATICTOP up.
// TODO: We could in theory slice off the top of the HEAP when
- // sbrk gets a negative increment in |bytes|...
+ // sbrk gets a negative increment in |bytes|...
var self = _sbrk;
if (!self.STATICTOP) {
STATICTOP = alignMemoryPage(STATICTOP);
@@ -1909,97 +2067,114 @@ LibraryManager.library = {
__01lseek64_: 'lseek',
// ==========================================================================
+ // stdio.h
+ // ==========================================================================
- _scanString: function() {
- // Supports %x, %4x, %d.%d, %s
- var str = Pointer_stringify(arguments[0]);
- var stri = 0;
- var fmt = Pointer_stringify(arguments[1]);
- var fmti = 0;
- var args = Array.prototype.slice.call(arguments, 2);
+ // TODO: Document.
+ _scanString: function(format, get, unget, args) {
+ // Supports %x, %4x, %d.%d, %s.
+ // TODO: Support all format specifiers.
+ format = Pointer_stringify(format);
+ var formatIndex = 0;
var argsi = 0;
var fields = 0;
- while (fmti < fmt.length) {
- if (fmt[fmti] === '%') {
- fmti++;
- var max_ = parseInt(fmt[fmti]);
- if (!isNaN(max_)) fmti++;
- var type = fmt[fmti];
- fmti++;
+ for (var formatIndex = 0; formatIndex < format.length; formatIndex++) {
+ var next = get();
+ if (next <= 0) return fields; // End of input.
+ if (format[formatIndex] === '%') {
+ formatIndex++;
+ var maxSpecifierStart = formatIndex;
+ while (format[formatIndex].charCodeAt(0) >= '0'.charCodeAt(0) &&
+ format[formatIndex].charCodeAt(0) <= '9'.charCodeAt(0)) {
+ formatIndex++;
+ }
+ var max_;
+ if (formatIndex != maxSpecifierStart) {
+ max_ = parseInt(format.slice(maxSpecifierStart, formatIndex), 10);
+ }
+ // TODO: Handle type size modifier.
+ var type = format[formatIndex];
+ formatIndex++;
var curr = 0;
- while ((curr < max_ || isNaN(max_)) && stri+curr < str.length) {
- if ((type === 'd' && parseInt(str[stri+curr]) >= 0) ||
- (type === 'x' && parseInt(str[stri+curr].replace(/[a-fA-F]/, 5)) >= 0) ||
+ var buffer = [];
+ while ((curr < max_ || isNaN(max_)) && next > 0) {
+ if ((type === 'd' && next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
+ (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
+ next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
+ next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0))) ||
(type === 's')) {
- curr++;
+ buffer.push(String.fromCharCode(next));
+ next = get();
} else {
break;
}
}
- if (curr === 0) return 0; // failure
- var text = str.substr(stri, curr);
- stri += curr;
+ if (buffer.length === 0) return 0; // Failure.
+ var text = buffer.join('');
switch (type) {
- case 'd': {
- {{{ makeSetValue('args[argsi]', '0', 'parseInt(text)', 'i32') }}}
+ case 'd':
+ {{{ makeSetValue('args.shift()', '0', 'parseInt(text, 10)', 'i32') }}}
break;
- }
- case 'x': {
- {{{ makeSetValue('args[argsi]', '0', 'eval("0x" + text)', 'i32') }}}
+ case 'x':
+ {{{ makeSetValue('args.shift()', '0', 'parseInt(text, 16)', 'i32') }}}
break;
- }
- case 's': {
+ case 's':
var array = intArrayFromString(text);
+ var buf = args.shift();
for (var j = 0; j < array.length; j++) {
- {{{ makeSetValue('args[argsi]', 'j', 'array[j]', 'i8') }}}
+ {{{ makeSetValue('buf', 'j', 'array[j]', 'i8') }}}
}
break;
- }
}
- argsi++;
fields++;
- } else { // not '%'
- if (fmt[fmti] === str[stri]) {
- fmti++;
- stri++;
- } else {
- break;
+ } else {
+ // Not a specifier.
+ if (format[formatIndex].charCodeAt(0) !== next) {
+ unget(next);
+ return fields;
}
}
}
- return { fields: fields, bytes: stri };
- },
- sscanf__deps: ['_scanString'],
- sscanf: function() {
- return __scanString.apply(null, arguments).fields;
- },
-
- _formatString__deps: ['$STDIO', 'isdigit'],
- _formatString: function() {
- var cStyle = false;
- var textIndex = arguments[0];
- var argIndex = 1;
- if (textIndex < 0) {
- cStyle = true;
- textIndex = -textIndex;
- argIndex = arguments[1];
- } else {
- var _arguments = arguments;
- }
- function getNextArg(isFloat, size) {
- var ret;
- if (!cStyle) {
- ret = _arguments[argIndex];
- argIndex++;
- } else {
- if (isFloat) {
- ret = {{{ makeGetValue(0, 'argIndex', 'double') }}};
+ return fields;
+ },
+ // Performs prtinf-style formatting.
+ // isVarArgs: Whether the arguments are passed in varargs style, i.e. the
+ // third parameter is an address of the start of the argument list.
+ // format: A pointer to the format string.
+ // Returns the resulting string string as a character array.
+ _formatString: function(isVarArgs, format/*, ...*/) {
+ var textIndex = format;
+ var argIndex = 0;
+ var getNextArg;
+ if (isVarArgs) {
+ var varArgStart = arguments[2];
+ getNextArg = function(type) {
+ var ret;
+ if (type === 'double') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'double') }}};
+ } else if (type === 'float') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'float') }}};
+ } else if (type === 'i64') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i64') }}};
+ } else if (type === 'i32') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i32') }}};
+ } else if (type === 'i16') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i16') }}};
+ } else if (type === 'i8') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i8') }}};
+ } else if (type[type.length - 1] === '*') {
+ ret = {{{ makeGetValue('varArgStart', 'argIndex', 'void*') }}};
} else {
- ret = {{{ makeGetValue(0, 'argIndex', 'i32') }}};
+ throw new Error('Unknown formatString argument type: ' + type);
}
- argIndex += {{{ QUANTUM_SIZE === 1 ? 1 : 'Math.max(4, size || 0)' }}};
- }
- return +ret; // +: boolean=>int
+ argIndex += Runtime.getNativeFieldSize(type);
+ return Number(ret);
+ };
+ } else {
+ var args = arguments;
+ getNextArg = function() {
+ return Number(args[2 + argIndex++]);
+ };
}
var ret = [];
@@ -2043,11 +2218,11 @@ LibraryManager.library = {
// Handle width.
var width = 0;
if (next == '*'.charCodeAt(0)) {
- width = getNextArg();
+ width = getNextArg('i32');
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
} else {
- while (_isdigit(next)) {
+ while (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) {
width = width * 10 + (next - '0'.charCodeAt(0));
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
@@ -2062,12 +2237,13 @@ LibraryManager.library = {
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
if (next == '*'.charCodeAt(0)) {
- precision = getNextArg();
+ precision = getNextArg('i32');
textIndex++;
} else {
while(1) {
var precisionChr = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- if (!_isdigit(precisionChr)) break;
+ if (precisionChr < '0'.charCodeAt(0) ||
+ precisionChr > '9'.charCodeAt(0)) break;
precision = precision * 10 + (precisionChr - '0'.charCodeAt(0));
textIndex++;
}
@@ -2118,9 +2294,9 @@ LibraryManager.library = {
if (['d', 'i', 'u', 'o', 'x', 'X', 'p'].indexOf(String.fromCharCode(next)) != -1) {
// Integer.
var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
- var currArg = getNextArg(false, argSize);
- // Truncate to requested size.
argSize = argSize || 4;
+ var currArg = getNextArg('i' + (argSize * 8));
+ // Truncate to requested size.
if (argSize <= 4) {
var limit = Math.pow(256, argSize) - 1;
currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
@@ -2196,7 +2372,7 @@ LibraryManager.library = {
});
} else if (['f', 'F', 'e', 'E', 'g', 'G'].indexOf(String.fromCharCode(next)) != -1) {
// Float.
- var currArg = getNextArg(true, argSize);
+ var currArg = getNextArg(argSize === 4 ? 'float' : 'double');
var argText;
if (isNaN(currArg)) {
@@ -2281,7 +2457,7 @@ LibraryManager.library = {
});
} else if (next == 's'.charCodeAt(0)) {
// String.
- var arg = getNextArg();
+ var arg = getNextArg('i8*');
var copiedString;
if (arg) {
copiedString = String_copy(arg);
@@ -2304,14 +2480,15 @@ LibraryManager.library = {
}
} else if (next == 'c'.charCodeAt(0)) {
// Character.
- if (flagLeftAlign) ret.push(getNextArg());
+ if (flagLeftAlign) ret.push(getNextArg('i8'));
while (--width > 0) {
ret.push(' '.charCodeAt(0));
}
- if (!flagLeftAlign) ret.push(getNextArg());
+ if (!flagLeftAlign) ret.push(getNextArg('i8'));
} else if (next == 'n'.charCodeAt(0)) {
// Write the length written so far to the next parameter.
- {{{ makeSetValue('getNextArg()', '0', 'ret.length', 'i32') }}}
+ var ptr = getNextArg('i32*');
+ {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}}
} else if (next == '%'.charCodeAt(0)) {
// Literal percent sign.
ret.push(curr);
@@ -2329,372 +2506,626 @@ LibraryManager.library = {
textIndex += 1;
}
}
- return allocate(ret.concat(0), 'i8', ALLOC_STACK); // NB: Stored on the stack
- //var len = ret.length+1;
- //var ret = allocate(ret.concat(0), 0, ALLOC_STACK); // NB: Stored on the stack
- //STACKTOP -= len; // XXX horrible hack. we rewind the stack, to 'undo' the alloc we just did.
- // // the point is that this works if nothing else allocs on the stack before
- // // the string is read, which should be true - it is very transient, see the *printf* functions below.
- //return ret;
- },
-
- printf__deps: ['_formatString'],
- printf: function() {
- __print__(Pointer_stringify(__formatString.apply(null, arguments)));
- },
-
- sprintf__deps: ['strcpy', '_formatString'],
- sprintf: function() {
- var str = arguments[0];
- var args = Array.prototype.slice.call(arguments, 1);
- _strcpy(str, __formatString.apply(null, args)); // not terribly efficient
- },
-
- snprintf__deps: ['strncpy', '_formatString'],
- snprintf: function() {
- var str = arguments[0];
- var num = arguments[1];
- var args = Array.prototype.slice.call(arguments, 2);
- _strncpy(str, __formatString.apply(null, args), num); // not terribly efficient
- },
-
- puts: function(p) {
- __print__(Pointer_stringify(p) + '\n');
- },
-
- putc: 'fputc',
- _IO_putc: 'fputc',
-
- putchar: function(p) {
- __print__(String.fromCharCode(p));
- },
- _ZNSo3putEc: 'putchar',
-
- _ZNSo5flushEv: function() {
- __print__('\n');
+ return ret;
},
-
- vsprintf__deps: ['strcpy', '_formatString'],
- vsprintf: function(dst, src, ptr) {
- _strcpy(dst, __formatString(-src, ptr));
+ // NOTE: Invalid stream pointers passed to these functions would cause a crash
+ // in native code. We, on the other hand, just ignore them, since it's
+ // easier.
+ clearerr__deps: ['$FS'],
+ clearerr: function(stream) {
+ // void clearerr(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/clearerr.html
+ if (stream in FS.streams) FS.streams[stream].error = false;
},
-
- vsnprintf__deps: ['_formatString'],
- vsnprintf: function(dst, num, src, ptr) {
- var text = __formatString(-src, ptr); // |-|src tells formatstring to use C-style params (typically they are from varargs)
- var i;
- for (i = 0; i < num; i++) {
- {{{ makeCopyValues('dst+i', 'text+i', 1, 'i8') }}}
- if ({{{ makeGetValue('dst', 'i', 'i8') }}} == 0) break;
+ fclose__deps: ['close', 'fsync'],
+ fclose: function(stream) {
+ // int fclose(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fclose.html
+ _fsync(stream);
+ return _close(stream);
+ },
+ fdopen__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
+ fdopen: function(fildes, mode) {
+ // FILE *fdopen(int fildes, const char *mode);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fdopen.html
+ if (fildes in FS.streams) {
+ var stream = FS.streams[fildes];
+ mode = Pointer_stringify(mode);
+ if ((mode.indexOf('w') != -1 && !stream.isWrite) ||
+ (mode.indexOf('r') != -1 && !stream.isRead) ||
+ (mode.indexOf('a') != -1 && !stream.isAppend) ||
+ (mode.indexOf('+') != -1 && (!stream.isRead || !stream.isWrite))) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return 0;
+ } else {
+ stream.error = false;
+ stream.eof = false;
+ return fildes;
+ }
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return 0;
}
- return i; // Actually, should return how many *would* have been written, if the |num| had not stopped us.
},
-
- fileno: function(file) {
- return file;
+ feof__deps: ['$FS'],
+ feof: function(stream) {
+ // int feof(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/feof.html
+ return Number(stream in FS.streams && FS.streams[stream].eof);
},
-
- clearerr: function(stream) {
+ ferror__deps: ['$FS'],
+ ferror: function(stream) {
+ // int ferror(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/ferror.html
+ return Number(stream in FS.streams && FS.streams[stream].error);
},
-
- flockfile: function(file) {
+ fflush__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
+ fflush: function(stream) {
+ // int fflush(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html
+ var flush = function(filedes) {
+ // Right now we write all data directly, except for output devices.
+ if (filedes in FS.streams && FS.streams[filedes].object.output) {
+ FS.streams[filedes].object.output(null);
+ }
+ };
+ try {
+ if (stream === 0) {
+ for (var i in FS.streams) flush(i);
+ } else {
+ flush(stream);
+ }
+ return 0;
+ } catch (e) {
+ ___setErrNo(ERRNO_CODES.EIO);
+ return -1;
+ }
},
-
- funlockfile: function(file) {
+ fgetc__deps: ['$FS', 'read'],
+ fgetc: function(stream) {
+ // int fgetc(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetc.html
+ if (!(stream in FS.streams)) return -1;
+ if (!_fgetc.buffer) _fgetc.buffer = _malloc(1);
+ var streamObj = FS.streams[stream];
+ if (streamObj.eof || streamObj.error) return -1;
+ var ret = _read(stream, _fgetc.buffer, 1);
+ if (ret == 0) {
+ streamObj.eof = true;
+ return -1;
+ } else if (ret == -1) {
+ streamObj.error = true;
+ return -1;
+ } else {
+ return {{{ makeGetValue('_fgetc.buffer', '0', 'i8') }}};
+ }
},
-
- stdin: 0,
- stdout: 0,
- stderr: 0,
-
- $STDIO__postset: 'STDIO.init()',
- $STDIO__deps: ['stdin', 'stdout', 'stderr'],
- $STDIO: {
- streams: {},
- filenames: {},
- counter: 1,
- SEEK_SET: 0, /* Beginning of file. */
- SEEK_CUR: 1, /* Current position. */
- SEEK_END: 2, /* End of file. */
- init: function() {
- _stdin = allocate([0], 'void*', ALLOC_STATIC);
- {{{ makeSetValue('_stdin', '0', "STDIO.prepare('<<stdin>>', null, null, true)", 'i32') }}};
- if (Module.stdin) {
- // Make sure stdin returns a newline
- var orig = Module.stdin;
- Module.stdin = function stdinFixed(prompt) {
- var ret = orig(prompt);
- if (ret[ret.length-1] !== '\n') ret = ret + '\n';
- return ret;
- }
+ getc: 'fgetc',
+ getc_unlocked: 'fgetc',
+ getchar__deps: ['fgetc', 'stdin'],
+ getchar: function() {
+ // int getchar(void);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/getchar.html
+ return _fgetc({{{ makeGetValue('_stdin', '0', 'void*') }}});
+ },
+ fgetpos__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
+ fgetpos: function(stream, pos) {
+ // int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetpos.html
+ if (stream in FS.streams) {
+ stream = FS.streams[stream];
+ if (stream.object.isDevice) {
+ ___setErrNo(ERRNO_CODES.ESPIPE);
+ return -1;
} else {
- Module.stdin = function stdin(prompt) {
- return window.prompt(prompt) || '';
- };
+ {{{ makeSetValue('pos', '0', 'stream.position', 'i32') }}}
+ var state = (stream.eof ? 1 : 0) + (stream.error ? 2 : 0);
+ {{{ makeSetValue('pos', Runtime.getNativeFieldSize('i32'), 'state', 'i32') }}}
+ return 0;
}
-
- _stdout = allocate([0], 'void*', ALLOC_STATIC);
- {{{ makeSetValue('_stdout', '0', "STDIO.prepare('<<stdout>>', null, true)", 'i32') }}};
-
- _stderr = allocate([0], 'void*', ALLOC_STATIC);
- {{{ makeSetValue('_stderr', '0', "STDIO.prepare('<<stderr>>', null, true)", 'i32') }}};
- },
- cleanFilename: function(filename) {
- return filename.replace('./', '');
- },
- prepare: function(filename, data, print_, interactiveInput) {
- filename = STDIO.cleanFilename(filename);
- var stream = STDIO.counter++;
- STDIO.streams[stream] = {
- filename: filename,
- data: data ? data : [],
- position: 0,
- eof: 0,
- error: 0,
- interactiveInput: interactiveInput, // true for stdin - on the web, we allow interactive input
- print: print_ // true for stdout and stderr - we print when receiving data for them
- };
- STDIO.filenames[filename] = stream;
- return stream;
- },
- open: function(filename) {
- filename = STDIO.cleanFilename(filename);
- var stream = STDIO.filenames[filename];
- if (!stream) {
- // Not already cached; try to load it right now
- try {
- return STDIO.prepare(filename, readBinary(filename));
- } catch(e) {
- return 0;
- }
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ },
+ fgets__deps: ['fgetc'],
+ fgets: function(s, n, stream) {
+ // char *fgets(char *restrict s, int n, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgets.html
+ if (!(stream in FS.streams)) return 0;
+ var streamObj = FS.streams[stream];
+ if (streamObj.error || streamObj.eof) return 0;
+ for (var i = 0; i < n - 1; i++) {
+ var byte = _fgetc(stream);
+ if (byte == -1) {
+ if (streamObj.error) return 0;
+ else if (streamObj.eof) break;
+ } else if (byte == '\n'.charCodeAt(0)) {
+ break;
}
- var info = STDIO.streams[stream];
- info.position = info.error = info.eof = 0;
- return stream;
- },
- read: function(stream, ptr, size) {
- var info = STDIO.streams[stream];
- if (!info) return -1;
- if (info.interactiveInput) {
- for (var i = 0; i < size; i++) {
- if (info.data.length === 0) {
- info.data = intArrayFromString(Module.stdin(PRINTBUFFER.length > 0 ? PRINTBUFFER : '?')).map(function(x) { return x === 0 ? 10 : x }); // change 0 to newline
- PRINTBUFFER = '';
- if (info.data.length === 0) return i;
- }
- {{{ makeSetValue('ptr', '0', 'info.data.shift()', 'i8') }}}
- ptr++;
- }
- return size;
+ {{{ makeSetValue('s', 'i', 'byte', 'i8') }}}
+ }
+ {{{ makeSetValue('s', 'i', '0', 'i8') }}}
+ return s;
+ },
+ gets__deps: ['fgets'],
+ gets: function(s) {
+ // char *gets(char *s);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/gets.html
+ return _fgets(s, 1e6, {{{ makeGetValue('_stdin', '0', 'void*') }}});
+ },
+ fileno: function(stream) {
+ // int fileno(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html
+ // We use file descriptor numbers and FILE* streams interchangeably.
+ return stream;
+ },
+ ftrylockfile: function() {
+ // int ftrylockfile(FILE *file);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/flockfile.html
+ // Locking is useless in a single-threaded environment. Pretend to succeed.
+ return 0;
+ },
+ flockfile: 'ftrylockfile',
+ funlockfile: 'ftrylockfile',
+ fopen__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'open'],
+ fopen: function(filename, mode) {
+ // FILE *fopen(const char *restrict filename, const char *restrict mode);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fopen.html
+ var flags;
+ mode = Pointer_stringify(mode);
+ if (mode[0] == 'r') {
+ if (mode.indexOf('+') != -1) {
+ flags = 0x2; // O_RDWR
+ } else {
+ flags = 0x0; // O_RDONLY
}
- for (var i = 0; i < size; i++) {
- if (info.position >= info.data.length) {
- info.eof = 1;
- return 0; // EOF
- }
- {{{ makeSetValue('ptr', '0', 'info.data[info.position]', 'i8') }}}
- info.position++;
- ptr++;
+ } else if (mode[0] == 'w') {
+ if (mode.indexOf('+') != -1) {
+ flags = 0x2; // O_RDWR
+ } else {
+ flags = 0x1; // O_WRONLY
}
- return size;
- },
- write: function(stream, ptr, size) {
- var info = STDIO.streams[stream];
- if (!info) return -1;
- if (info.print) {
- __print__(intArrayToString(Array_copy(ptr, size)));
+ flags |= 0x40; // O_CREAT
+ flags |= 0x200; // O_TRUNC
+ } else if (mode[0] == 'a') {
+ if (mode.indexOf('+') != -1) {
+ flags = 0x2; // O_RDWR
} else {
- for (var i = 0; i < size; i++) {
- info.data[info.position] = {{{ makeGetValue('ptr', '0', 'i8') }}};
- info.position++;
- ptr++;
- }
+ flags = 0x1; // O_WRONLY
}
- return size;
+ flags |= 0x40; // O_CREAT
+ flags |= 0x400; // O_APPEND
+ } else {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return 0;
+ }
+ var ret = _open(filename, flags, 0x1FF); // All creation permissions.
+ return (ret == -1) ? 0 : ret;
+ },
+ fputc__deps: ['write'],
+ fputc: function(c, stream) {
+ // int fputc(int c, FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fputc.html
+ if (!_fputc.buffer) _fputc.buffer = _malloc(1);
+ var chr = unSign(c & 0xFF);
+ {{{ makeSetValue('_fputc.buffer', '0', 'chr', 'i8') }}}
+ var ret = _write(stream, _fputc.buffer, 1);
+ if (ret == -1) {
+ if (stream in FS.streams) FS.streams[stream].error = true;
+ return -1;
+ } else {
+ return chr;
}
},
-
- fopen__deps: ['$STDIO'],
- fopen: function(filename, mode) {
- filename = Pointer_stringify(filename);
- mode = Pointer_stringify(mode);
- if (mode.indexOf('r') >= 0) {
- return STDIO.open(filename);
- } else if (mode.indexOf('w') >= 0) {
- return STDIO.prepare(filename);
+ putc: 'fputc',
+ putc_unlocked: 'fputc',
+ putchar__deps: ['fputc', 'stdout'],
+ putchar: function(c) {
+ // int putchar(int c);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/putchar.html
+ return _fputc(c, {{{ makeGetValue('_stdout', '0', 'void*') }}});
+ },
+ putchar_unlocked: 'putchar',
+ fputs__deps: ['write', 'strlen'],
+ fputs: function(s, stream) {
+ // int fputs(const char *restrict s, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fputs.html
+ return _write(stream, s, _strlen(s));
+ },
+ puts__deps: ['fputs', 'fputc', 'stdout'],
+ puts: function(s) {
+ // int puts(const char *s);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/puts.html
+ // NOTE: puts() always writes an extra newline.
+ var stdout = {{{ makeGetValue('_stdout', '0', 'void*') }}};
+ var ret = _fputs(s, stdout);
+ if (ret < 0) {
+ return ret;
} else {
- return assert(false, 'fopen with odd params: ' + mode);
+ var newlineRet = _fputc('\n'.charCodeAt(0), stdout);
+ return (newlineRet < 0) ? -1 : ret + 1;
}
},
- __01fopen64_: 'fopen',
-
- fdopen: function(descriptor, mode) {
- // TODO: Check whether mode is acceptable for the current stream.
- return descriptor;
+ fread__deps: ['$FS', 'read'],
+ fread: function(ptr, size, nitems, stream) {
+ // size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fread.html
+ var bytesToRead = nitems * size;
+ if (bytesToRead == 0) return 0;
+ var bytesRead = _read(stream, ptr, bytesToRead);
+ var streamObj = FS.streams[stream];
+ if (bytesRead == -1) {
+ if (streamObj) streamObj.error = true;
+ return -1;
+ } else {
+ if (bytesRead < bytesToRead) streamObj.eof = true;
+ return Math.floor(bytesRead / size);
+ }
},
-
- rewind__deps: ['$STDIO'],
- rewind: function(stream) {
- var info = STDIO.streams[stream];
- info.position = 0;
- info.error = 0;
+ freopen__deps: ['$FS', 'fclose', 'fopen', '__setErrNo', '$ERRNO_CODES'],
+ freopen: function(filename, mode, stream) {
+ // FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/freopen.html
+ if (!filename) {
+ if (!(stream in FS.streams)) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return 0;
+ }
+ if (_freopen.buffer) _free(_freopen.buffer);
+ filename = intArrayFromString(FS.streams[stream].path);
+ filename = allocate(filename, 'i8', ALLOC_NORMAL);
+ }
+ _fclose(stream);
+ return _fopen(filename, mode);
},
-
- fseek__deps: ['$STDIO'],
+ fseek__deps: ['$FS', 'lseek'],
fseek: function(stream, offset, whence) {
- var info = STDIO.streams[stream];
- if (whence === STDIO.SEEK_CUR) {
- offset += info.position;
- } else if (whence === STDIO.SEEK_END) {
- offset += info.data.length;
- }
- info.position = offset;
- info.eof = 0;
- return 0;
+ // int fseek(FILE *stream, long offset, int whence);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fseek.html
+ var ret = _lseek(stream, offset, whence);
+ if (ret == -1) {
+ return -1;
+ } else {
+ FS.streams[stream].eof = false;
+ return 0;
+ }
},
- __01fseeko64_: 'fseek',
-
- ftell__deps: ['$STDIO'],
- ftell: function(stream) {
- return STDIO.streams[stream].position;
+ fseeko: 'fseek',
+ fsetpos__deps: ['$FS', 'lseek', '__setErrNo', '$ERRNO_CODES'],
+ fsetpos: function(stream, pos) {
+ // int fsetpos(FILE *stream, const fpos_t *pos);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fsetpos.html
+ if (stream in FS.streams) {
+ if (FS.streams[stream].object.isDevice) {
+ ___setErrNo(ERRNO_CODES.EPIPE);
+ return -1;
+ } else {
+ FS.streams[stream].position = {{{ makeGetValue('pos', '0', 'i32') }}};
+ var state = {{{ makeGetValue('pos', Runtime.getNativeFieldSize('i32'), 'i32') }}};
+ FS.streams[stream].eof = Boolean(state & 1);
+ FS.streams[stream].error = Boolean(state & 2);
+ return 0;
+ }
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
},
- __01ftello64_: 'ftell',
-
- fread__deps: ['$STDIO'],
- fread: function(ptr, size, count, stream) {
- var info = STDIO.streams[stream];
- if (info.interactiveInput) return STDIO.read(stream, ptr, size*count);
- for (var i = 0; i < count; i++) {
- if (info.position + size > info.data.length) {
- info.eof = 1;
- return i;
+ ftell__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
+ ftell: function(stream) {
+ // long ftell(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/ftell.html
+ if (stream in FS.streams) {
+ stream = FS.streams[stream];
+ if (stream.object.isDevice) {
+ ___setErrNo(ERRNO_CODES.ESPIPE);
+ return -1;
+ } else {
+ return stream.position;
}
- STDIO.read(stream, ptr, size);
- ptr += size;
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
}
- return count;
},
-
- fwrite__deps: ['$STDIO'],
- fwrite: function(ptr, size, count, stream) {
- STDIO.write(stream, ptr, size*count);
- return count;
+ ftello: 'ftell',
+ fwrite__deps: ['$FS', 'write'],
+ fwrite: function(ptr, size, nitems, stream) {
+ // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html
+ var bytesToWrite = nitems * size;
+ if (bytesToWrite == 0) return 0;
+ var bytesWritten = _write(stream, ptr, bytesToWrite);
+ if (bytesWritten == -1) {
+ if (FS.streams[stream]) FS.streams[stream].error = true;
+ return -1;
+ } else {
+ return Math.floor(bytesWritten / size);
+ }
},
-
- fclose__deps: ['$STDIO'],
- fclose: function(stream) {
+ popen__deps: ['__setErrNo', '$ERRNO_CODES'],
+ popen: function(command, mode) {
+ // FILE *popen(const char *command, const char *mode);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/popen.html
+ // We allow only one process, so no pipes.
+ ___setErrNo(ERRNO_CODES.EMFILE);
return 0;
},
-
- feof__deps: ['$STDIO'],
- feof: function(stream) {
- return STDIO.streams[stream].eof;
+ pclose__deps: ['__setErrNo', '$ERRNO_CODES'],
+ pclose: function(stream) {
+ // int pclose(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/pclose.html
+ // We allow only one process, so no pipes.
+ ___setErrNo(ERRNO_CODES.ECHILD);
+ return -1;
},
-
- ferror__deps: ['$STDIO'],
- ferror: function(stream) {
- return STDIO.streams[stream].error;
+ perror__deps: ['puts', 'putc', 'strerror', '__errno_location'],
+ perror: function(s) {
+ // void perror(const char *s);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/perror.html
+ if (s) {
+ _puts(s);
+ _putc(':'.charCodeAt(0));
+ _putc(' '.charCodeAt(0));
+ }
+ var errnum = {{{ makeGetValue('___errno_location()', '0', 'i32') }}};
+ _puts(_strerror(errnum));
+ },
+ remove__deps: ['unlink', 'rmdir'],
+ remove: function(path) {
+ // int remove(const char *path);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/remove.html
+ var ret = _unlink(path);
+ if (ret == -1) ret = _rmdir(path);
+ return ret;
},
-
- fprintf__deps: ['_formatString', '$STDIO'],
- fprintf: function() {
- var stream = arguments[0];
- var args = Array.prototype.slice.call(arguments, 1);
- var ptr = __formatString.apply(null, args);
- STDIO.write(stream, ptr, String_len(ptr));
+ rename__deps: ['__setErrNo', '$ERRNO_CODES'],
+ rename: function(old, new_) {
+ // int rename(const char *old, const char *new);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/rename.html
+ var oldObj = FS.analyzePath(Pointer_stringify(old));
+ var newObj = FS.analyzePath(Pointer_stringify(new_));
+ if (newObj.path == oldObj.path) {
+ return 0;
+ } else if (!oldObj.exists) {
+ ___setErrNo(oldObj.error);
+ return -1;
+ } else if (oldObj.isRoot || oldObj.path == FS.currentPath) {
+ ___setErrNo(ERRNO_CODES.EBUSY);
+ return -1;
+ } else if (newObj.path && newObj.path.indexOf(oldObj.path) == 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ } else if (newObj.exists && newObj.object.isFolder) {
+ ___setErrNo(ERRNO_CODES.EISDIR);
+ return -1;
+ } else {
+ delete oldObj.parentObject.contents[oldObj.name];
+ newObj.parentObject.contents[newObj.name] = oldObj.object;
+ return 0;
+ }
},
-
- vfprintf__deps: ['$STDIO', '_formatString'],
- vfprintf: function(stream, format, args) {
- var ptr = __formatString(-format, args);
- STDIO.write(stream, ptr, String_len(ptr));
+ rewind__deps: ['$FS', 'fseek'],
+ rewind: function(stream) {
+ // void rewind(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/rewind.html
+ _fseek(stream, 0, 0); // SEEK_SET.
+ if (stream in FS.streams) FS.streams[stream].error = false;
+ },
+ setvbuf: function(stream, buf, type, size) {
+ // int setvbuf(FILE *restrict stream, char *restrict buf, int type, size_t size);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/setvbuf.html
+ // TODO: Implement buffering.
+ return 0;
},
-
- fflush__deps: ['$STDIO'],
- fflush: function(stream) {
- var info = STDIO.streams[stream];
- if (info && info.print) {
- __print__(null);
+ setbuf__deps: ['setvbuf'],
+ setbuf: function(stream, buf) {
+ // void setbuf(FILE *restrict stream, char *restrict buf);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/setbuf.html
+ if (buf) _setvbuf(stream, buf, 0, 8192); // _IOFBF, BUFSIZ.
+ else _setvbuf(stream, buf, 2, 8192); // _IONBF, BUFSIZ.
+ },
+ tmpnam__deps: ['$FS'],
+ tmpnam: function(s, dir, prefix) {
+ // char *tmpnam(char *s);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/tmpnam.html
+ // NOTE: The dir and prefix arguments are for internal use only.
+ var folder = FS.findObject(dir || '/tmp');
+ if (!folder || !folder.isFolder) {
+ dir = '/tmp';
+ folder = FS.findObject(dir);
+ if (!folder || !folder.isFolder) return 0;
+ }
+ var name = prefix || 'file';
+ do {
+ name += String.fromCharCode(65 + Math.floor(Math.random() * 25));
+ } while (name in folder.contents);
+ var result = dir + '/' + name;
+ if (!_tmpnam.buffer) _tmpnam.buffer = _malloc(256);
+ if (!s) s = _tmpnam.buffer;
+ for (var i = 0; i < result.length; i++) {
+ {{{ makeSetValue('s', 'i', 'result.charCodeAt(i)', 'i8') }}};
+ }
+ {{{ makeSetValue('s', 'i', '0', 'i8') }}};
+ return s;
+ },
+ tempnam__deps: ['tmpnam'],
+ tempnam: function(dir, pfx) {
+ // char *tempnam(const char *dir, const char *pfx);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/tempnam.html
+ return _tmpnam(0, Pointer_stringify(dir), Pointer_stringify(pfx));
+ },
+ tmpfile__deps: ['tmpnam', 'fopen'],
+ tmpfile: function() {
+ // FILE *tmpfile(void);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/tmpfile.html
+ // TODO: Delete the created file on closing.
+ if (_tmpfile.mode) {
+ _tmpfile.mode = allocate(intArrayFromString('w+'), 'i8', ALLOC_STATIC);
+ }
+ return _fopen(_tmpnam(0), _tmpfile.mode);
+ },
+ ungetc__deps: ['$FS'],
+ ungetc: function(c, stream) {
+ // int ungetc(int c, FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/ungetc.html
+ if (stream in FS.streams) {
+ c = unSign(c & 0xFF);
+ FS.streams[stream].ungotten.push(c);
+ return c;
+ } else {
+ return -1;
}
},
-
- fputs__deps: ['$STDIO', 'fputc'],
- fputs: function(p, stream) {
- STDIO.write(stream, p, String_len(p));
+ system__deps: ['__setErrNo', '$ERRNO_CODES'],
+ system: function(command) {
+ // int system(const char *command);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/system.html
+ // Can't call external programs.
+ ___setErrNo(ERRNO_CODES.EAGAIN);
+ return -1;
},
-
- fputc__deps: ['$STDIO'],
- fputc: function(chr, stream) {
- if (!Module._fputc_ptr) Module._fputc_ptr = _malloc(1);
- {{{ makeSetValue('Module._fputc_ptr', '0', 'chr', 'i8') }}}
- var ret = STDIO.write(stream, Module._fputc_ptr, 1);
- return (ret == -1) ? -1 /* EOF */ : chr;
+ fscanf__deps: ['$FS', '__setErrNo', '$ERRNO_CODES',
+ '_scanString', 'getc', 'ungetc'],
+ fscanf: function(stream, format/*, ...*/) {
+ // int fscanf(FILE *restrict stream, const char *restrict format, ... );
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
+ if (stream in FS.streams) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ var get = function() { return _fgetc(stream); };
+ var unget = function(c) { return _ungetc(c, stream); };
+ return __scanString(format, get, unget, args);
+ } else {
+ return -1;
+ }
},
-
- getc__deps: ['$STDIO'],
- getc: function(file) {
- if (!Module._getc_ptr) Module._getc_ptr = _malloc(1);
- var ret = STDIO.read(file, Module._getc_ptr, 1);
- if (ret === 0) return -1; // EOF
- return {{{ makeGetValue('Module._getc_ptr', '0', 'i8') }}}
+ scanf__deps: ['fscanf'],
+ scanf: function(format/*, ...*/) {
+ // int scanf(const char *restrict format, ... );
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
+ var args = Array.prototype.slice.call(arguments, 0);
+ args.unshift({{{ makeGetValue('_stdin', '0', 'void*') }}});
+ return _fscanf.apply(null, args);
},
- getc_unlocked: 'getc',
- _IO_getc: 'getc',
-
- getchar__deps: ['getc'],
- getchar: function() {
- return _getc(_stdin);
+ sscanf__deps: ['_scanString'],
+ sscanf: function(s, format/*, ...*/) {
+ // int sscanf(const char *restrict s, const char *restrict format, ... );
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
+ var index = 0;
+ var get = function() { return {{{ makeGetValue('s', 'index++', 'i8') }}}; };
+ var unget = function() { index--; };
+ var args = Array.prototype.slice.call(arguments, 2);
+ return __scanString(format, get, unget, args);
},
-
- ungetc: function(chr, stream) {
- var f = STDIO.streams[stream];
- if (!f)
- return -1; // EOF
- if (!f.interactiveInput)
- f.position--;
- return chr;
+ snprintf__deps: ['_formatString'],
+ snprintf: function(s, n, format/*, ... */) {
+ // int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ var args = Array.prototype.slice.call(arguments, 2);
+ args.unshift(false);
+ var result = __formatString.apply(null, args);
+ var limit = (n === undefined) ? result.length
+ : Math.min(result.length, n - 1);
+ for (var i = 0; i < limit; i++) {
+ {{{ makeSetValue('s', 'i', 'result[i]', 'i8') }}};
+ }
+ {{{ makeSetValue('s', 'i', '0', 'i8') }}};
+ return result.length;
},
-
- gets: function(ptr) {
- var num = 0;
- while (STDIO.read({{{ makeGetValue('_stdin', '0', 'void*') }}}, ptr+num, 1) &&
- {{{ makeGetValue('ptr', 'num', 'i8') }}} !== 10) { num++; }
- if (num === 0) return 0;
- {{{ makeSetValue('ptr', 'num', 0, 'i8') }}}
- return ptr;
+ fprintf__deps: ['fwrite', '_formatString'],
+ fprintf: function(stream, format/*, ... */) {
+ // int fprintf(FILE *restrict stream, const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ var args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(false);
+ var result = __formatString.apply(null, args);
+ var buffer = allocate(result, 'i8', ALLOC_NORMAL);
+ var ret = _fwrite(buffer, 1, result.length, stream);
+ _free(buffer);
+ return ret;
},
-
- fscanf__deps: ['_scanString'],
- fscanf: function(stream, format) {
- var f = STDIO.streams[stream];
- if (!f)
- return -1; // EOF
- arguments[0] = allocate(f.data.slice(f.position).concat(0), 'i8', ALLOC_STACK);
- var ret = __scanString.apply(null, arguments);
- f.position += ret.bytes;
- return ret.fields;
+ printf__deps: ['fprintf'],
+ printf: function(format/*, ... */) {
+ // int printf(const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ var args = Array.prototype.slice.call(arguments, 0);
+ args.unshift({{{ makeGetValue('_stdout', '0', 'void*') }}});
+ return _fprintf.apply(null, args);
+ },
+ sprintf__deps: ['snprintf'],
+ sprintf: function(s, format/*, ... */) {
+ // int sprintf(char *restrict s, const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ var args = [s, undefined].concat(Array.prototype.slice.call(arguments, 1));
+ return _snprintf.apply(null, args);
+ },
+ vfprintf__deps: ['fwrite', '_formatString'],
+ vfprintf: function(stream, format, ap) {
+ // int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html
+ var result = __formatString(true, format, ap);
+ var buffer = allocate(result, 'i8', ALLOC_NORMAL);
+ var ret = _fwrite(buffer, 1, result.length, stream);
+ _free(buffer);
+ return ret;
+ },
+ vsnprintf__deps: ['_formatString'],
+ vsnprintf: function(s, n, format, ap) {
+ // int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html
+ var result = __formatString(true, format, ap);
+ var limit = (n === undefined) ? result.length
+ : Math.min(result.length, n - 1);
+ for (var i = 0; i < limit; i++) {
+ {{{ makeSetValue('s', 'i', 'result[i]', 'i8') }}};
+ }
+ {{{ makeSetValue('s', 'i', '0', 'i8') }}};
+ return result.length;
+ },
+ vprintf__deps: ['vfprintf'],
+ vprintf: function(format, ap) {
+ // int vprintf(const char *restrict format, va_list ap);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html
+ return _vfprintf({{{ makeGetValue('_stdout', '0', 'void*') }}}, format, ap);
+ },
+ vsprintf__deps: ['vsnprintf'],
+ vsprintf: function(s, format, ap) {
+ // int vsprintf(char *restrict s, const char *restrict format, va_list ap);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html
+ return _vsnprintf(s, undefined, format, ap);
+ },
+ // TODO: Implement v*scanf().
+ // TODO: Check if these aliases are correct and if any others are needed.
+ __01fopen64_: 'fopen',
+ __01fseeko64_: 'fseek',
+ __01ftello64_: 'ftell',
+ _IO_getc: 'getc',
+ _IO_putc: 'putc',
+ _ZNSo3putEc: 'putchar',
+ _ZNSo5flushEv__deps: ['fflush', 'stdout'],
+ _ZNSo5flushEv: function() {
+ _fflush({{{ makeGetValue('_stdout', '0', 'void*') }}});
},
- // unix file IO, see http://rabbit.eng.miami.edu/info/functions/unixio.html
+ // ==========================================================================
+ // sys/mman.h
+ // ==========================================================================
+ mmap__deps: ['$FS'],
mmap: function(start, num, prot, flags, stream, offset) {
- // Leaky and non-shared... FIXME
- var info = STDIO.streams[stream];
+ // FIXME: Leaky and non-shared.
+ var info = FS.streams[stream];
if (!info) return -1;
- return allocate(info.data.slice(offset, offset+num), 'i8', ALLOC_NORMAL);
+ return allocate(info.object.contents.slice(offset, offset+num),
+ 'i8', ALLOC_NORMAL);
},
munmap: function(start, num) {
- _free(start); // FIXME: not really correct at all
+ // FIXME: Not really correct at all.
+ _free(start);
},
- setbuf: function(stream, buffer) {
- // just a stub
- assert(!buffer);
- },
-
- setvbuf: 'setbuf',
-
// ==========================================================================
// stdlib.h
// ==========================================================================
@@ -3266,7 +3697,11 @@ LibraryManager.library = {
return -1; // 'indeterminable' for FLT_ROUNDS
},
- // iostream
+ // ==========================================================================
+ // iostream.h
+ // ==========================================================================
+
+ // TODO: Document; compile from real implementation.
_ZNSt8ios_base4InitC1Ev: function() {
// need valid 'file descriptors'
@@ -3275,21 +3710,23 @@ LibraryManager.library = {
},
_ZNSt8ios_base4InitD1Ev: '_ZNSt8ios_base4InitC1Ev',
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_: 0, // endl
- _ZNSolsEi: function(stream, data) {
- __print__(data);
- },
- _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc: function(stream, data) {
- __print__(Pointer_stringify(data));
- },
- _ZNSolsEd: function(stream, data) {
- __print__('\n');
- },
- _ZNSolsEPFRSoS_E: function(stream, data) {
- __print__('\n');
+ _ZNSolsEd__deps: ['putchar'],
+ _ZNSolsEd: function(undefined_stream, data) {
+ _putchar('\n'.charCodeAt(0));
+ },
+ _ZNSolsEPFRSoS_E: '_ZNSolsEd',
+ _ZNSolsEi__deps: ['putchar'],
+ _ZNSolsEi: function(undefined_stream, data) {
+ var str = String(data);
+ for (var i = 0; i < str.length; i++) {
+ _putchar(str.charCodeAt(i));
+ }
},
- _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i: function(stream, data, call_) {
- __print__(Pointer_stringify(data));
+ _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc__deps: ['fputs', 'stdout'],
+ _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc: function(undefined_stream, data) {
+ _fputs(data, {{{ makeGetValue('_stdout', '0', 'void*') }}});
},
+ _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i: '_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc',
// ==========================================================================
// math.h
@@ -3423,7 +3860,7 @@ LibraryManager.library = {
loadedLibNames: {}, // name -> handle
},
// void* dlopen(const char* filename, int flag);
- dlopen__deps: ['$DLFCN_DATA'],
+ dlopen__deps: ['$DLFCN_DATA', '$FS'],
dlopen: function(filename, flag) {
// TODO: Add support for LD_LIBRARY_PATH.
filename = Pointer_stringify(filename);
@@ -3435,11 +3872,13 @@ LibraryManager.library = {
return handle;
}
- try {
- var lib_data = read(filename);
- } catch (e) {
+ var target = FS.findObject(filename);
+ if (!target || target.isFolder || target.isDevice) {
DLFCN_DATA.isError = true;
return 0;
+ } else {
+ FS.forceLoadFile(target);
+ var lib_data = intArrayToString(target.contents);
}
try {
@@ -3465,7 +3904,6 @@ LibraryManager.library = {
if (flag & 256) { // RTLD_GLOBAL
for (var ident in lib_module) {
if (lib_module.hasOwnProperty(ident)) {
- // TODO: Check if we need to unmangle here.
Module[ident] = lib_module[ident];
}
}
@@ -3491,9 +3929,7 @@ LibraryManager.library = {
// void* dlsym(void* handle, const char* symbol);
dlsym__deps: ['$DLFCN_DATA'],
dlsym: function(handle, symbol) {
- symbol = Pointer_stringify(symbol);
- // TODO: Properly mangle.
- symbol = '_' + symbol;
+ symbol = '_' + Pointer_stringify(symbol);
if (!DLFCN_DATA.loadedLibs[handle]) {
DLFCN_DATA.isError = true;
@@ -3524,8 +3960,7 @@ LibraryManager.library = {
// TODO: Return non-generic error messages.
if (DLFCN_DATA.error === null) {
var msg = 'An error occurred while loading dynamic library.';
- var arr = Module.intArrayFromString(msg)
- DLFCN_DATA.error = allocate(arr, 'i8', 2);
+ DLFCN_DATA.error = allocate(Module.intArrayFromString(msg), 'i8', 2);
}
DLFCN_DATA.isError = false;
return DLFCN_DATA.error;
diff --git a/src/preamble.js b/src/preamble.js
index 95bde991..bf6628ae 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -534,24 +534,6 @@ function String_copy(ptr, addZero) {
// Tools
-var PRINTBUFFER = '';
-function __print__(text) {
- if (text === null) {
- // Flush
- print(PRINTBUFFER);
- PRINTBUFFER = '';
- return;
- }
- // We print only when we see a '\n', as console JS engines always add
- // one anyhow.
- PRINTBUFFER = PRINTBUFFER + text;
- var endIndex;
- while ((endIndex = PRINTBUFFER.indexOf('\n')) != -1) {
- print(PRINTBUFFER.substr(0, endIndex));
- PRINTBUFFER = PRINTBUFFER.substr(endIndex + 1);
- }
-}
-
function jrint(label, obj) { // XXX manual debugging
if (!obj) {
obj = label;
@@ -603,27 +585,5 @@ function intArrayToString(array) {
{{{ unSign }}}
{{{ reSign }}}
-// Use console read if available, otherwise we are in a browser, use an XHR
-if (!this['read']) {
- this['read'] = function(url) {
- // TODO: use mozResponseArrayBuffer/responseStream/etc. if available
- var xhr = new XMLHttpRequest();
- xhr.open("GET", url, false);
- xhr.overrideMimeType('text/plain; charset=x-user-defined'); // ask for binary data
- xhr.send(null);
- if (xhr.status != 200 && xhr.status != 0) throw 'failed to open: ' + url;
- return xhr.responseText;
- };
-}
-
-function readBinary(filename) {
- var stringy = read(filename);
- var data = new Array(stringy.length);
- for (var i = 0; i < stringy.length; i++) {
- data[i] = stringy.charCodeAt(i) & 0xff;
- }
- return data;
-}
-
// === Body ===
diff --git a/tests/runner.py b/tests/runner.py
index 7e3ac99c..98ea0f28 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -1831,7 +1831,14 @@ if 'benchmark' not in sys.argv:
}
'''
BUILD_AS_SHARED_LIB = 0
- self.do_test(src, 'Constructing main object.\nConstructing lib object.\n')
+ def addPreRunAndChecks(filename):
+ src = open(filename, 'r').read().replace(
+ '// {{PRE_RUN_ADDITIONS}}',
+ '''FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);'''
+ )
+ open(filename, 'w').write(src)
+ self.do_test(src, 'Constructing main object.\nConstructing lib object.\n',
+ post_build=addPreRunAndChecks)
def test_dlfcn_qsort(self):
global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS
@@ -1909,8 +1916,15 @@ if 'benchmark' not in sys.argv:
'''
BUILD_AS_SHARED_LIB = 0
EXPORTED_FUNCTIONS = ['_main']
+ def addPreRunAndChecks(filename):
+ src = open(filename, 'r').read().replace(
+ '// {{PRE_RUN_ADDITIONS}}',
+ '''FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);'''
+ )
+ open(filename, 'w').write(src)
self.do_test(src, 'Sort with main comparison: 5 4 3 2 1 *Sort with lib comparison: 1 2 3 4 5 *',
- output_nicerizer=lambda x: x.replace('\n', '*'))
+ output_nicerizer=lambda x: x.replace('\n', '*'),
+ post_build=addPreRunAndChecks)
def test_dlfcn_data_and_fptr(self):
global LLVM_OPTS
@@ -2000,8 +2014,15 @@ if 'benchmark' not in sys.argv:
BUILD_AS_SHARED_LIB = 0
EXPORTED_FUNCTIONS = ['_main']
EXPORTED_GLOBALS = []
+ def addPreRunAndChecks(filename):
+ src = open(filename, 'r').read().replace(
+ '// {{PRE_RUN_ADDITIONS}}',
+ '''FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);'''
+ )
+ open(filename, 'w').write(src)
self.do_test(src, 'In func: 13*First calling main_fptr from lib.*Second calling lib_fptr from main.*parent_func called from child*parent_func called from child*Var: 42*',
- output_nicerizer=lambda x: x.replace('\n', '*'))
+ output_nicerizer=lambda x: x.replace('\n', '*'),
+ post_build=addPreRunAndChecks)
def test_strtod(self):
src = r'''
@@ -2065,8 +2086,14 @@ if 'benchmark' not in sys.argv:
src = open(filename, 'r').read().replace(
'// {{PRE_RUN_ADDITIONS}}',
'''
- STDIO.prepare('somefile.binary', [100, 200, 50, 25, 10, 77, 123]); // 200 becomes -56, since signed chars are used in memory
- Module.stdin = function(prompt) { return 'hi there!' };
+ FS.createDataFile('/', 'somefile.binary', [100, 200, 50, 25, 10, 77, 123], true, false); // 200 becomes -56, since signed chars are used in memory
+ FS.createLazyFile('/', 'test.file', 'test.file', true, false);
+ FS.root.write = true;
+ var test_files_input = 'hi there!';
+ var test_files_input_index = 0;
+ FS.init(function() {
+ return test_files_input.charCodeAt(test_files_input_index++) || null;
+ });
'''
)
open(filename, 'w').write(src)
@@ -2296,7 +2323,7 @@ if 'benchmark' not in sys.argv:
f_blocks: 1000000
f_bfree: 500000
f_bavail: 500000
- f_files: 2
+ f_files: 8
f_ffree: 1000000
f_favail: 1000000
f_fsid: 42
@@ -2711,7 +2738,7 @@ if 'benchmark' not in sys.argv:
# Embed the font into the document
src = open(filename, 'r').read().replace(
'// {{PRE_RUN_ADDITIONS}}',
- '''STDIO.prepare('font.ttf', %s);''' % str(
+ '''FS.createDataFile('/', 'font.ttf', %s, true, false);''' % str(
map(ord, open(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), 'rb').read())
)
)
@@ -2806,9 +2833,10 @@ if 'benchmark' not in sys.argv:
src = open(filename, 'a')
src.write(
'''
- STDIO.prepare('paper.pdf', eval(read('paper.pdf.js')));
+ FS.createDataFile('/', 'paper.pdf', eval(read('paper.pdf.js')), true, false);
+ FS.root.write = true;
run();
- print("Data: " + JSON.stringify(STDIO.streams[STDIO.filenames['filename-1.ppm']].data));
+ print("Data: " + JSON.stringify(FS.root.contents['filename-1.ppm'].contents));
'''
)
src.close()
@@ -2857,12 +2885,12 @@ if 'benchmark' not in sys.argv:
def post(filename):
src = open(filename, 'r').read().replace(
'// {{PRE_RUN_ADDITIONS}}',
- '''STDIO.prepare('image.j2k', %s);''' % line_splitter(str(
+ '''FS.createDataFile('/', 'image.j2k', %s, true, false);FS.root.write = true;''' % line_splitter(str(
map(ord, open(original_j2k, 'rb').read())
))
).replace(
'// {{POST_RUN_ADDITIONS}}',
- '''print("Data: " + JSON.stringify(STDIO.streams[STDIO.filenames['image.raw']].data));'''
+ '''print("Data: " + JSON.stringify(FS.root.contents['image.raw'].contents));'''
)
open(filename, 'w').write(src)
diff --git a/tests/unistd/dup.out b/tests/unistd/dup.out
index 439c6fd5..da95157d 100644
--- a/tests/unistd/dup.out
+++ b/tests/unistd/dup.out
@@ -1,17 +1,17 @@
DUP
errno: 0
-f: 1
-f2: 2
-f3: 3
+f: 4
+f2: 5
+f3: 6
close(f1): 0
close(f2): 0
close(f3): 0
DUP2
errno: 0
-f: 4
-f2: 5
-f3: 5
+f: 7
+f2: 8
+f3: 8
close(f1): 0
close(f2): 0
close(f3): -1
diff --git a/tests/unistd/isatty.js b/tests/unistd/isatty.js
index 6399f9e9..d88bd2be 100644
--- a/tests/unistd/isatty.js
+++ b/tests/unistd/isatty.js
@@ -2,4 +2,4 @@ FS.createDevice('/', 'read', function() {}, null);
FS.createDevice('/', 'write', null, function() {});
FS.createDevice('/', 'all', function() {}, function() {});
FS.createFolder('/', 'folder', true, true);
-FS.createDataFile('/', 'file', true, true);
+FS.createDataFile('/', 'file', 'test', true, true);