aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js116
1 files changed, 77 insertions, 39 deletions
diff --git a/src/library.js b/src/library.js
index 344ec8d6..e65754ba 100644
--- a/src/library.js
+++ b/src/library.js
@@ -619,7 +619,7 @@ LibraryManager.library = {
#endif
allocate([ allocate(
{{{ Runtime.QUANTUM_SIZE === 4 ? '[0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0]' : '[0, _stdin, _stdout, _stderr]' }}},
- 'void*', ALLOC_DYNAMIC) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}});
+ 'void*', ALLOC_NORMAL) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}});
},
quit: function() {
@@ -3576,14 +3576,14 @@ LibraryManager.library = {
return -1;
},
fscanf__deps: ['$FS', '__setErrNo', '$ERRNO_CODES',
- '_scanString', 'getc', 'ungetc'],
+ '_scanString', 'fgetc', 'fseek', 'ftell'],
fscanf: function(stream, format, varargs) {
// int fscanf(FILE *restrict stream, const char *restrict format, ... );
// http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
if (FS.streams[stream]) {
- var stack = [];
- var get = function() { var ret = _fgetc(stream); stack.push(ret); return ret };
- var unget = function(c) { return _ungetc(stack.pop(), stream) };
+ var i = _ftell(stream), SEEK_SET = 0;
+ var get = function () { i++; return _fgetc(stream); };
+ var unget = function () { _fseek(stream, --i, SEEK_SET); };
return __scanString(format, get, unget, varargs);
} else {
return -1;
@@ -3726,30 +3726,44 @@ LibraryManager.library = {
* this implementation simply uses malloc underneath the call to
* mmap.
*/
+ var MAP_PRIVATE = 2;
+ var allocated = false;
+
if (!_mmap.mappings) _mmap.mappings = {};
+
if (stream == -1) {
var ptr = _malloc(num);
+ if (!ptr) return -1;
+ _memset(ptr, 0, num);
+ allocated = true;
} else {
var info = FS.streams[stream];
if (!info) return -1;
var contents = info.object.contents;
- contents = Array.prototype.slice.call(contents, offset, offset+num);
- ptr = allocate(contents, 'i8', ALLOC_NORMAL);
- }
- // align to page size
- var ret = ptr;
- if (ptr % PAGE_SIZE != 0) {
- var old = ptr;
- ptr = _malloc(num + PAGE_SIZE);
- ret = alignMemoryPage(ptr);
- _memcpy(ret, old, num);
- _free(old);
- }
- if (stream == -1) {
- _memset(ret, 0, num);
+ // Only make a new copy when MAP_PRIVATE is specified.
+ if (flags & MAP_PRIVATE == 0) {
+ // We can't emulate MAP_SHARED when the file is not backed by HEAP.
+ assert(contents.buffer === HEAPU8.buffer);
+ ptr = contents.byteOffset;
+ allocated = false;
+ } else {
+ // Try to avoid unnecessary slices.
+ if (offset > 0 || offset + num < contents.length) {
+ if (contents.subarray) {
+ contents = contents.subarray(offset, offset+num);
+ } else {
+ contents = Array.prototype.slice.call(contents, offset, offset+num);
+ }
+ }
+ ptr = _malloc(num);
+ if (!ptr) return -1;
+ HEAPU8.set(contents, ptr);
+ allocated = true;
+ }
}
- _mmap.mappings[ret] = { malloc: ptr, num: num };
- return ret;
+
+ _mmap.mappings[ptr] = { malloc: ptr, num: num, allocated: allocated };
+ return ptr;
},
__01mmap64_: 'mmap',
@@ -3760,7 +3774,9 @@ LibraryManager.library = {
if (!info) return 0;
if (num == info.num) {
_mmap.mappings[start] = null;
- _free(info.malloc);
+ if (info.allocated) {
+ _free(info.malloc);
+ }
}
return 0;
},
@@ -3902,7 +3918,14 @@ LibraryManager.library = {
str++;
}
}
- }
+ } else if (finalBase==16) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
+ str += 2;
+ }
+ }
+ }
if (!finalBase) finalBase = 10;
// Get digits.
@@ -3953,13 +3976,14 @@ LibraryManager.library = {
#if USE_TYPED_ARRAYS == 2
_parseInt64__deps: ['isspace', '__setErrNo', '$ERRNO_CODES', function() { Types.preciseI64MathUsed = 1 }],
_parseInt64: function(str, endptr, base, min, max, unsign) {
- var start = str;
+ var isNegative = false;
// Skip space.
while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
-
+
// Check for a plus/minus sign.
if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('-') }}}) {
str++;
+ isNegative = true;
} else if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('+') }}}) {
str++;
}
@@ -3975,12 +3999,19 @@ LibraryManager.library = {
str += 2;
} else {
finalBase = 8;
- str++;
ok = true; // we saw an initial zero, perhaps the entire thing is just "0"
}
}
- }
+ } else if (finalBase==16) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
+ str += 2;
+ }
+ }
+ }
if (!finalBase) finalBase = 10;
+ start = str;
// Get digits.
var chr;
@@ -3993,6 +4024,7 @@ LibraryManager.library = {
ok = true;
}
}
+
if (!ok) {
___setErrNo(ERRNO_CODES.EINVAL);
{{{ makeStructuralReturn(['0', '0']) }}};
@@ -4004,7 +4036,8 @@ LibraryManager.library = {
}
try {
- i64Math.fromString(Pointer_stringify(start, str - start), finalBase, min, max, unsign);
+ var numberString = isNegative ? '-'+Pointer_stringify(start, str - start) : Pointer_stringify(start, str - start);
+ i64Math.fromString(numberString, finalBase, min, max, unsign);
} catch(e) {
___setErrNo(ERRNO_CODES.ERANGE); // not quite correct
}
@@ -5072,7 +5105,13 @@ LibraryManager.library = {
return _malloc(size);
},
__cxa_free_exception: function(ptr) {
- return _free(ptr);
+ try {
+ return _free(ptr);
+ } catch(e) { // XXX FIXME
+#if ASSERTIONS
+ Module.printErr('exception during cxa_free_exception: ' + e);
+#endif
+ }
},
__cxa_throw__sig: 'viii',
__cxa_throw__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'],
@@ -6170,8 +6209,9 @@ LibraryManager.library = {
clock_gettime__deps: ['__timespec_struct_layout'],
clock_gettime: function(clk_id, tp) {
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
- {{{ makeSetValue('tp', '___timespec_struct_layout.tv_sec', '0', 'i32') }}}
- {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}}
+ var now = Date.now();
+ {{{ makeSetValue('tp', '___timespec_struct_layout.tv_sec', 'Math.floor(now/1000)', 'i32') }}}; // seconds
+ {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}}; // nanoseconds - not supported
return 0;
},
clock_settime: function(clk_id, tp) {
@@ -6794,19 +6834,17 @@ LibraryManager.library = {
26: 'Text file busy',
18: 'Invalid cross-device link'
},
+ __errno_state: 0,
+ __setErrNo__deps: ['__errno_state'],
+ __setErrNo__postset: '___errno_state = Runtime.staticAlloc(4); {{{ makeSetValue("___errno_state", 0, 0, "i32") }}};',
__setErrNo: function(value) {
// For convenient setting and returning of errno.
- if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
- {{{ makeSetValue('___setErrNo.ret', '0', 'value', 'i32') }}}
+ {{{ makeSetValue('___errno_state', '0', 'value', 'i32') }}}
return value;
},
__errno_location__deps: ['__setErrNo'],
__errno_location: function() {
- if (!___setErrNo.ret) {
- ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
- {{{ makeSetValue('___setErrNo.ret', '0', '0', 'i32') }}}
- }
- return ___setErrNo.ret;
+ return ___errno_state;
},
__errno: '__errno_location',
@@ -7563,7 +7601,7 @@ LibraryManager.library = {
},
emscripten_run_script_int: function(ptr) {
- return eval(Pointer_stringify(ptr));
+ return eval(Pointer_stringify(ptr))|0;
},
emscripten_run_script_string: function(ptr) {