diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/deps_info.json | 7 | ||||
-rw-r--r-- | src/headlessCanvas.js | 1 | ||||
-rw-r--r-- | src/jsifier.js | 59 | ||||
-rw-r--r-- | src/library.js | 413 | ||||
-rw-r--r-- | src/library_browser.js | 12 | ||||
-rw-r--r-- | src/library_egl.js | 2 | ||||
-rw-r--r-- | src/library_fs.js | 213 | ||||
-rw-r--r-- | src/library_gl.js | 198 | ||||
-rw-r--r-- | src/library_html5.js | 19 | ||||
-rw-r--r-- | src/library_idbfs.js | 324 | ||||
-rw-r--r-- | src/library_openal.js | 501 | ||||
-rw-r--r-- | src/library_sdl.js | 31 | ||||
-rw-r--r-- | src/parseTools.js | 4 | ||||
-rw-r--r-- | src/preamble.js | 4 | ||||
-rw-r--r-- | src/runtime.js | 4 | ||||
-rw-r--r-- | src/settings.js | 14 | ||||
-rw-r--r-- | src/struct_info.json | 4 |
17 files changed, 1221 insertions, 589 deletions
diff --git a/src/deps_info.json b/src/deps_info.json new file mode 100644 index 00000000..b38ffd00 --- /dev/null +++ b/src/deps_info.json @@ -0,0 +1,7 @@ +{ + "uuid_compare": ["memcmp"], + "SDL_Init": ["malloc", "free"], + "SDL_GL_GetProcAddress": ["emscripten_GetProcAddress"], + "eglGetProcAddress": ["emscripten_GetProcAddress"] +} + diff --git a/src/headlessCanvas.js b/src/headlessCanvas.js index 6b0f9d47..4bd17a7b 100644 --- a/src/headlessCanvas.js +++ b/src/headlessCanvas.js @@ -446,6 +446,7 @@ function headlessCanvas() { case /* GL_MAX_FRAGMENT_UNIFORM_VECTORS */ 0x8DFD: return 4096; case /* GL_MAX_VARYING_VECTORS */ 0x8DFC: return 32; case /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */ 0x8B4D: return 32; + case /* GL_ARRAY_BUFFER_BINDING */ 0x8894: return 0; default: console.log('getParameter ' + pname + '?'); return 0; } }, diff --git a/src/jsifier.js b/src/jsifier.js index 726a5eda..6742f504 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -224,6 +224,7 @@ function JSify(data, functionsOnly) { // globalVariable function globalVariableHandler(item) { + function needsPostSet(value) { if (typeof value !== 'string') return false; // (' is ok, as it is something we can indexize later into a concrete int: ('{{ FI_ ... @@ -274,7 +275,9 @@ function JSify(data, functionsOnly) { constant = Runtime.alignMemory(calcAllocatedSize(item.type)); } else { if (item.external) { - if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { + if (LibraryManager.library[item.ident.slice(1)]) { + constant = LibraryManager.library[item.ident.slice(1)]; + } else if (Runtime.isNumberType(item.type) || isPointerType(item.type)) { constant = zeros(Runtime.getNativeFieldSize(item.type)); } else { constant = makeEmptyStruct(item.type); @@ -282,22 +285,23 @@ function JSify(data, functionsOnly) { } else { constant = parseConst(item.value, item.type, item.ident); } - assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]); // This is a flattened object. We need to find its idents, so they can be assigned to later - var structTypes = null; - constant.forEach(function(value, i) { - if (needsPostSet(value)) { // ident, or expression containing an ident - if (!structTypes) structTypes = generateStructTypes(item.type); - itemsDict.GlobalVariablePostSet.push({ - intertype: 'GlobalVariablePostSet', - JS: makeSetValue(makeGlobalUse(item.ident), i, value, structTypes[i], false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors - }); - constant[i] = '0'; - } else { - if (typeof value === 'string') constant[i] = deParenCarefully(value); - } - }); + if (typeof constant === 'object') { + var structTypes = null; + constant.forEach(function(value, i) { + if (needsPostSet(value)) { // ident, or expression containing an ident + if (!structTypes) structTypes = generateStructTypes(item.type); + itemsDict.GlobalVariablePostSet.push({ + intertype: 'GlobalVariablePostSet', + JS: makeSetValue(makeGlobalUse(item.ident), i, value, structTypes[i], false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors + }); + constant[i] = '0'; + } else { + if (typeof value === 'string') constant[i] = deParenCarefully(value); + } + }); + } if (item.external) { // External variables in shared libraries should not be declared as @@ -312,14 +316,18 @@ function JSify(data, functionsOnly) { } // ensure alignment - var extra = Runtime.alignMemory(constant.length) - constant.length; - if (item.ident.substr(0, 5) == '__ZTV') extra += Runtime.alignMemory(QUANTUM_SIZE); - while (extra-- > 0) constant.push(0); + if (typeof constant === 'object') { + var extra = Runtime.alignMemory(constant.length) - constant.length; + if (item.ident.substr(0, 5) == '__ZTV') extra += Runtime.alignMemory(QUANTUM_SIZE); + while (extra-- > 0) constant.push(0); + } } // NOTE: This is the only place that could potentially create static // allocations in a shared library. - constant = makePointer(constant, null, allocator, item.type, index); + if (typeof constant !== 'string') { + constant = makePointer(constant, null, allocator, item.type, index); + } var js = (index !== null ? '' : item.ident + '=') + constant; if (js) js += ';'; @@ -491,12 +499,8 @@ function JSify(data, functionsOnly) { if (!LINKABLE && !LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) { if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + shortident); else if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) warn('unresolved symbol: ' + shortident); - if (ASM_JS) { - // emit a stub that will fail during runtime. this allows asm validation to succeed. - LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); - } else { - cancel = true; // emit nothing, not even var X = undefined; - } + // emit a stub that will fail at runtime + LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); } item.JS = cancel ? ';' : addFromLibrary(shortident); } @@ -1223,7 +1227,7 @@ function JSify(data, functionsOnly) { // in an assignment var disabled = DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST); var phiSets = calcPhiSets(item); - var call_ = makeFunctionCall(item, item.params, item.funcData, item.type, ASM_JS && !disabled, !!item.assignTo || !item.standalone, true); + var call_ = makeFunctionCall(item, item.params, item.funcData, item.type, ASM_JS && !disabled, !!item.assignTo || !item.standalone, !disabled); var ret; @@ -1844,7 +1848,7 @@ function JSify(data, functionsOnly) { // rest of the output that we started to print out earlier (see comment on the // "Final shape that will be created"). if (PRECISE_I64_MATH && Types.preciseI64MathUsed) { - if (!INCLUDE_FULL_LIBRARY) { + if (!INCLUDE_FULL_LIBRARY && !SIDE_MODULE && !BUILD_AS_SHARED_LIB) { // first row are utilities called from generated code, second are needed from fastLong ['i64Add', 'i64Subtract', 'bitshift64Shl', 'bitshift64Lshr', 'bitshift64Ashr', 'llvm_ctlz_i32', 'llvm_cttz_i32'].forEach(function(func) { @@ -1866,6 +1870,7 @@ function JSify(data, functionsOnly) { } }); } + // these may be duplicated in side modules and the main module without issue print(read('fastLong.js')); print('// EMSCRIPTEN_END_FUNCS\n'); print(read('long.js')); diff --git a/src/library.js b/src/library.js index bc577e78..db9b891c 100644 --- a/src/library.js +++ b/src/library.js @@ -52,32 +52,33 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.ENOTDIR); return 0; } - var err = _open(dirname, {{{ cDefine('O_RDONLY') }}}, allocate([0, 0, 0, 0], 'i32', ALLOC_STACK)); - // open returns 0 on failure, not -1 - return err === -1 ? 0 : err; + var fd = _open(dirname, {{{ cDefine('O_RDONLY') }}}, allocate([0, 0, 0, 0], 'i32', ALLOC_STACK)); + return fd === -1 ? 0 : FS.getPtrForStream(FS.getStream(fd)); }, - closedir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'close'], + closedir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'close', 'fileno'], closedir: function(dirp) { // int closedir(DIR *dirp); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/closedir.html - return _close(dirp); + var fd = _fileno(dirp); + return _close(fd); }, telldir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], telldir: function(dirp) { // long int telldir(DIR *dirp); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/telldir.html - var stream = FS.getStream(dirp); + var stream = FS.getStreamFromPtr(dirp); if (!stream || !FS.isDir(stream.node.mode)) { ___setErrNo(ERRNO_CODES.EBADF); return -1; } return stream.position; }, - seekdir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'lseek'], + seekdir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'lseek', 'fileno'], seekdir: function(dirp, loc) { // void seekdir(DIR *dirp, long int loc); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/seekdir.html - _lseek(dirp, loc, {{{ cDefine('SEEK_SET') }}}); + var fd = _fileno(dirp); + _lseek(fd, loc, {{{ cDefine('SEEK_SET') }}}); }, rewinddir__deps: ['seekdir'], rewinddir: function(dirp) { @@ -89,7 +90,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 - var stream = FS.getStream(dirp); + var stream = FS.getStreamFromPtr(dirp); if (!stream) { return ___setErrNo(ERRNO_CODES.EBADF); } @@ -134,7 +135,7 @@ LibraryManager.library = { readdir: function(dirp) { // struct dirent *readdir(DIR *dirp); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/readdir_r.html - var stream = FS.getStream(dirp); + var stream = FS.getStreamFromPtr(dirp); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return 0; @@ -162,7 +163,7 @@ LibraryManager.library = { if (times) { // NOTE: We don't keep track of access timestamps. var offset = {{{ C_STRUCTS.utimbuf.modtime }}}; - time = {{{ makeGetValue('times', 'offset', 'i32') }}} + time = {{{ makeGetValue('times', 'offset', 'i32') }}}; time *= 1000; } else { time = Date.now(); @@ -1182,7 +1183,7 @@ LibraryManager.library = { for (var i = 0; i < length; i++) { {{{ makeSetValue('buf', 'i', 'value.charCodeAt(i)', 'i8') }}}; } - if (len > length) {{{ makeSetValue('buf', 'i++', '0', 'i8') }}} + if (len > length) {{{ makeSetValue('buf', 'i++', '0', 'i8') }}}; return i; } }, @@ -1641,6 +1642,7 @@ LibraryManager.library = { for (var i = 0; i < maxx; i++) { next = get(); {{{ makeSetValue('argPtr++', 0, 'next', 'i8') }}}; + if (next === 0) return i > 0 ? fields : fields-1; // we failed to read the full length of this field } formatIndex += nextC - formatIndex + 1; continue; @@ -2289,19 +2291,20 @@ LibraryManager.library = { clearerr: function(stream) { // void clearerr(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/clearerr.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { return; } stream.eof = false; stream.error = false; }, - fclose__deps: ['close', 'fsync'], + fclose__deps: ['close', 'fsync', 'fileno'], fclose: function(stream) { // int fclose(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fclose.html - _fsync(stream); - return _close(stream); + var fd = _fileno(stream); + _fsync(fd); + return _close(fd); }, fdopen__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], fdopen: function(fildes, mode) { @@ -2322,21 +2325,21 @@ LibraryManager.library = { } else { stream.error = false; stream.eof = false; - return fildes; + return FS.getPtrForStream(stream); } }, feof__deps: ['$FS'], feof: function(stream) { // int feof(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/feof.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); return Number(stream && stream.eof); }, ferror__deps: ['$FS'], ferror: function(stream) { // int ferror(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/ferror.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); return Number(stream && stream.error); }, fflush__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], @@ -2350,7 +2353,7 @@ LibraryManager.library = { fgetc: function(stream) { // int fgetc(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetc.html - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) return -1; if (streamObj.eof || streamObj.error) return -1; var ret = _fread(_fgetc.ret, 1, 1, stream); @@ -2375,7 +2378,7 @@ LibraryManager.library = { fgetpos: function(stream, pos) { // int fgetpos(FILE *restrict stream, fpos_t *restrict pos); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetpos.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; @@ -2393,7 +2396,7 @@ LibraryManager.library = { fgets: function(s, n, stream) { // char *fgets(char *restrict s, int n, FILE *restrict stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgets.html - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) return 0; if (streamObj.error || streamObj.eof) return 0; var byte_; @@ -2417,8 +2420,7 @@ LibraryManager.library = { 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; + return FS.getStreamFromPtr(stream).fd; }, ftrylockfile: function() { // int ftrylockfile(FILE *file); @@ -2460,19 +2462,20 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.EINVAL); return 0; } - var ret = _open(filename, flags, allocate([0x1FF, 0, 0, 0], 'i32', ALLOC_STACK)); // All creation permissions. - return (ret == -1) ? 0 : ret; + var fd = _open(filename, flags, allocate([0x1FF, 0, 0, 0], 'i32', ALLOC_STACK)); // All creation permissions. + return fd === -1 ? 0 : FS.getPtrForStream(FS.getStream(fd)); }, - fputc__deps: ['$FS', 'write'], + fputc__deps: ['$FS', 'write', 'fileno'], fputc__postset: '_fputc.ret = allocate([0], "i8", ALLOC_STATIC);', fputc: function(c, stream) { // int fputc(int c, FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fputc.html var chr = unSign(c & 0xFF); {{{ makeSetValue('_fputc.ret', '0', 'chr', 'i8') }}}; - var ret = _write(stream, _fputc.ret, 1); + var fd = _fileno(stream); + var ret = _write(fd, _fputc.ret, 1); if (ret == -1) { - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (streamObj) streamObj.error = true; return -1; } else { @@ -2488,11 +2491,12 @@ LibraryManager.library = { return _fputc(c, {{{ makeGetValue(makeGlobalUse('_stdout'), '0', 'void*') }}}); }, putchar_unlocked: 'putchar', - fputs__deps: ['write', 'strlen'], + fputs__deps: ['write', 'strlen', 'fileno'], 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)); + var fd = _fileno(stream); + return _write(fd, s, _strlen(s)); }, puts__deps: ['fputs', 'fputc', 'stdout'], puts: function(s) { @@ -2517,7 +2521,7 @@ LibraryManager.library = { return 0; } var bytesRead = 0; - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) { ___setErrNo(ERRNO_CODES.EBADF); return 0; @@ -2527,7 +2531,7 @@ LibraryManager.library = { bytesToRead--; bytesRead++; } - var err = _read(stream, ptr, bytesToRead); + var err = _read(streamObj.fd, ptr, bytesToRead); if (err == -1) { if (streamObj) streamObj.error = true; return 0; @@ -2541,7 +2545,7 @@ LibraryManager.library = { // FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/freopen.html if (!filename) { - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) { ___setErrNo(ERRNO_CODES.EBADF); return 0; @@ -2553,15 +2557,16 @@ LibraryManager.library = { _fclose(stream); return _fopen(filename, mode); }, - fseek__deps: ['$FS', 'lseek'], + fseek__deps: ['$FS', 'lseek', 'fileno'], fseek: function(stream, offset, whence) { // int fseek(FILE *stream, long offset, int whence); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fseek.html - var ret = _lseek(stream, offset, whence); + var fd = _fileno(stream); + var ret = _lseek(fd, offset, whence); if (ret == -1) { return -1; } - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); stream.eof = false; return 0; }, @@ -2570,7 +2575,7 @@ LibraryManager.library = { fsetpos: function(stream, pos) { // int fsetpos(FILE *stream, const fpos_t *pos); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fsetpos.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; @@ -2589,7 +2594,7 @@ LibraryManager.library = { ftell: function(stream) { // long ftell(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/ftell.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; @@ -2602,15 +2607,16 @@ LibraryManager.library = { } }, ftello: 'ftell', - fwrite__deps: ['$FS', 'write'], + fwrite__deps: ['$FS', 'write', 'fileno'], 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); + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); if (bytesWritten == -1) { - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (streamObj) streamObj.error = true; return 0; } else { @@ -2673,7 +2679,7 @@ LibraryManager.library = { // void rewind(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/rewind.html _fseek(stream, 0, 0); // SEEK_SET. - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (streamObj) streamObj.error = false; }, setvbuf: function(stream, buf, type, size) { @@ -2730,7 +2736,7 @@ LibraryManager.library = { ungetc: function(c, stream) { // int ungetc(int c, FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/ungetc.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { return -1; } @@ -2755,7 +2761,7 @@ LibraryManager.library = { fscanf: function(stream, format, varargs) { // int fscanf(FILE *restrict stream, const char *restrict format, ... ); // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) { return -1; } @@ -2898,7 +2904,7 @@ LibraryManager.library = { // ========================================================================== mmap__deps: ['$FS'], - mmap: function(start, num, prot, flags, stream, offset) { + mmap: function(start, num, prot, flags, fd, offset) { /* FIXME: Since mmap is normally implemented at the kernel level, * this implementation simply uses malloc underneath the call to * mmap. @@ -2909,13 +2915,13 @@ LibraryManager.library = { if (!_mmap.mappings) _mmap.mappings = {}; - if (stream == -1) { + if (fd == -1) { ptr = _malloc(num); if (!ptr) return -1; _memset(ptr, 0, num); allocated = true; } else { - var info = FS.getStream(stream); + var info = FS.getStream(fd); if (!info) return -1; try { var res = FS.mmap(info, HEAPU8, start, num, offset, prot, flags); @@ -3229,22 +3235,34 @@ LibraryManager.library = { strtoll: function(str, endptr, base) { return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX. }, - strtoll_l: 'strtoll', // no locale support yet + strtoll_l__deps: ['strtoll'], + strtoll_l: function(str, endptr, base) { + return _strtoll(str, endptr, base); // no locale support yet + }, strtol__deps: ['_parseInt'], strtol: function(str, endptr, base) { return __parseInt(str, endptr, base, -2147483648, 2147483647, 32); // LONG_MIN, LONG_MAX. }, - strtol_l: 'strtol', // no locale support yet + strtol_l__deps: ['strtol'], + strtol_l: function(str, endptr, base) { + return _strtol(str, endptr, base); // no locale support yet + }, strtoul__deps: ['_parseInt'], strtoul: function(str, endptr, base) { return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX. }, - strtoul_l: 'strtoul', // no locale support yet + strtoul_l__deps: ['strtoul'], + strtoul_l: function(str, endptr, base) { + return _strtoul(str, endptr, base); // no locale support yet + }, strtoull__deps: ['_parseInt64'], strtoull: function(str, endptr, base) { return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX. }, - strtoull_l: 'strtoull', // no locale support yet + strtoull_l__deps: ['strtoull'], + strtoull_l: function(str, endptr, base) { + return _strtoull(str, endptr, base); // no locale support yet + }, atoi__deps: ['strtol'], atoi: function(ptr) { @@ -3435,13 +3453,25 @@ LibraryManager.library = { return limit; }, - // Use browser's Math.random(). We can't set a seed, though. - srand: function(seed) {}, // XXX ignored - rand: function() { - return Math.floor(Math.random()*0x80000000); + __rand_seed: 'allocate([0x0273459b, 0, 0, 0], "i32", ALLOC_STATIC)', + srand__deps: ['__rand_seed'], + srand: function(seed) { + {{{ makeSetValue('___rand_seed', 0, 'seed', 'i32') }}} + }, + rand_r__sig: 'ii', + rand_r__asm: true, + rand_r: function(seedp) { + seedp = seedp|0; + var val = 0; + val = ((Math_imul({{{ makeGetValueAsm('seedp', 0, 'i32') }}}, 31010991)|0) + 0x676e6177 ) & {{{ cDefine('RAND_MAX') }}}; // assumes RAND_MAX is in bit mask form (power of 2 minus 1) + {{{ makeSetValueAsm('seedp', 0, 'val', 'i32') }}}; + return val|0; }, - rand_r: function(seed) { // XXX ignores the seed - return Math.floor(Math.random()*0x80000000); + rand__sig: 'i', + rand__asm: true, + rand__deps: ['rand_r', '__rand_seed'], + rand: function() { + return _rand_r(___rand_seed)|0; }, drand48: function() { @@ -3485,11 +3515,18 @@ LibraryManager.library = { return ret; }, + emscripten_memcpy_big: function(dest, src, num) { + HEAPU8.set(HEAPU8.subarray(src, src+num), dest); + return dest; + }, + memcpy__asm: true, memcpy__sig: 'iiii', + memcpy__deps: ['emscripten_memcpy_big'], memcpy: function(dest, src, num) { dest = dest|0; src = src|0; num = num|0; var ret = 0; + if ((num|0) >= 4096) return _emscripten_memcpy_big(dest|0, src|0, num|0)|0; ret = dest|0; if ((dest&3) == (src&3)) { while (dest & 3) { @@ -3729,76 +3766,6 @@ LibraryManager.library = { return pdest; }, - strcmp__deps: ['strncmp'], - strcmp: function(px, py) { - return _strncmp(px, py, TOTAL_MEMORY); - }, - // We always assume ASCII locale. - strcoll: 'strcmp', - strcoll_l: 'strcmp', - - strcasecmp__asm: true, - strcasecmp__sig: 'iii', - strcasecmp__deps: ['strncasecmp'], - strcasecmp: function(px, py) { - px = px|0; py = py|0; - return _strncasecmp(px, py, -1)|0; - }, - - strncmp: function(px, py, n) { - var i = 0; - while (i < n) { - var x = {{{ makeGetValue('px', 'i', 'i8', 0, 1) }}}; - var y = {{{ makeGetValue('py', 'i', 'i8', 0, 1) }}}; - if (x == y && x == 0) return 0; - if (x == 0) return -1; - if (y == 0) return 1; - if (x == y) { - i ++; - continue; - } else { - return x > y ? 1 : -1; - } - } - return 0; - }, - - strncasecmp__asm: true, - strncasecmp__sig: 'iiii', - strncasecmp__deps: ['tolower'], - strncasecmp: function(px, py, n) { - px = px|0; py = py|0; n = n|0; - var i = 0, x = 0, y = 0; - while ((i>>>0) < (n>>>0)) { - x = _tolower({{{ makeGetValueAsm('px', 'i', 'i8', 0, 1) }}})|0; - y = _tolower({{{ makeGetValueAsm('py', 'i', 'i8', 0, 1) }}})|0; - if (((x|0) == (y|0)) & ((x|0) == 0)) return 0; - if ((x|0) == 0) return -1; - if ((y|0) == 0) return 1; - if ((x|0) == (y|0)) { - i = (i + 1)|0; - continue; - } else { - return ((x>>>0) > (y>>>0) ? 1 : -1)|0; - } - } - return 0; - }, - - memcmp__asm: true, - memcmp__sig: 'iiii', - memcmp: function(p1, p2, num) { - p1 = p1|0; p2 = p2|0; num = num|0; - var i = 0, v1 = 0, v2 = 0; - while ((i|0) < (num|0)) { - v1 = {{{ makeGetValueAsm('p1', 'i', 'i8', true) }}}; - v2 = {{{ makeGetValueAsm('p2', 'i', 'i8', true) }}}; - if ((v1|0) != (v2|0)) return ((v1|0) > (v2|0) ? 1 : -1)|0; - i = (i+1)|0; - } - return 0; - }, - memchr: function(ptr, chr, num) { chr = unSign(chr); for (var i = 0; i < num; i++) { @@ -4000,7 +3967,10 @@ LibraryManager.library = { } }, _toupper: 'toupper', - toupper_l: 'toupper', + toupper_l__deps: ['toupper'], + toupper_l: function(str, endptr, base) { + return _toupper(str, endptr, base); // no locale support yet + }, tolower__asm: true, tolower__sig: 'ii', @@ -4011,65 +3981,104 @@ LibraryManager.library = { return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0; }, _tolower: 'tolower', - tolower_l: 'tolower', + tolower_l__deps: ['tolower'], + tolower_l: function(chr) { + return _tolower(chr); // no locale support yet + }, // The following functions are defined as macros in glibc. islower: function(chr) { return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}; }, - islower_l: 'islower', + islower_l__deps: ['islower'], + islower_l: function(chr) { + return _islower(chr); // no locale support yet + }, isupper: function(chr) { return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}; }, - isupper_l: 'isupper', + isupper_l__deps: ['isupper'], + isupper_l: function(chr) { + return _isupper(chr); // no locale support yet + }, isalpha: function(chr) { return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) || (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}); }, - isalpha_l: 'isalpha', + isalpha_l__deps: ['isalpha'], + isalpha_l: function(chr) { + return _isalpha(chr); // no locale support yet + }, isdigit: function(chr) { return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}; }, - isdigit_l: 'isdigit', + isdigit_l__deps: ['isdigit'], + isdigit_l: function(chr) { + return _isdigit(chr); // no locale support yet + }, isxdigit: function(chr) { return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) || (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) || (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}}); }, - isxdigit_l: 'isxdigit', + isxdigit_l__deps: ['isxdigit'], + isxdigit_l: function(chr) { + return _isxdigit(chr); // no locale support yet + }, isalnum: function(chr) { return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) || (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) || (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}); }, - isalnum_l: 'isalnum', + isalnum_l__deps: ['isalnum'], + isalnum_l: function(chr) { + return _isalnum(chr); // no locale support yet + }, ispunct: function(chr) { return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) || (chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) || (chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) || (chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}}); }, - ispunct_l: 'ispunct', + ispunct_l__deps: ['ispunct'], + ispunct_l: function(chr) { + return _ispunct(chr); // no locale support yet + }, isspace: function(chr) { return (chr == 32) || (chr >= 9 && chr <= 13); }, - isspace_l: 'isspace', + isspace_l__deps: ['isspace'], + isspace_l: function(chr) { + return _isspace(chr); // no locale support yet + }, isblank: function(chr) { return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}}; }, - isblank_l: 'isblank', + isblank_l__deps: ['isblank'], + isblank_l: function(chr) { + return _isblank(chr); // no locale support yet + }, iscntrl: function(chr) { return (0 <= chr && chr <= 0x1F) || chr === 0x7F; }, - iscntrl_l: 'iscntrl', + iscntrl_l__deps: ['iscntrl'], + iscntrl_l: function(chr) { + return _iscntrl(chr); // no locale support yet + }, isprint: function(chr) { return 0x1F < chr && chr < 0x7F; }, - isprint_l: 'isprint', + isprint_l__deps: ['isprint'], + isprint_l: function(chr) { + return _isprint(chr); // no locale support yet + }, isgraph: function(chr) { return 0x20 < chr && chr < 0x7F; }, - isgraph_l: 'isgraph', + isgraph_l__deps: ['isgraph'], + isgraph_l: function(chr) { + return _isgraph(chr); // no locale support yet + }, // Lookup tables for glibc ctype implementation. __ctype_b_loc: function() { // http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/baselib---ctype-b-loc.html @@ -4318,21 +4327,36 @@ LibraryManager.library = { _ZTVN10__cxxabiv120__si_class_type_infoE: [2], // yes inherited classes #endif + // We store an extra header in front of the exception data provided + // by the user. + // This header is: + // * type + // * destructor function pointer + // This is then followed by the actual exception data. + __cxa_exception_header_size: 8, + __cxa_last_thrown_exception: 0, + __cxa_caught_exceptions: [], + // Exceptions + __cxa_allocate_exception__deps: ['__cxa_exception_header_size'], __cxa_allocate_exception: function(size) { - return _malloc(size); + var ptr = _malloc(size + ___cxa_exception_header_size); + return ptr + ___cxa_exception_header_size; }, + __cxa_free_exception__deps: ['__cxa_exception_header_size'], __cxa_free_exception: function(ptr) { try { - return _free(ptr); + return _free(ptr - ___cxa_exception_header_size); } catch(e) { // XXX FIXME #if ASSERTIONS Module.printErr('exception during cxa_free_exception: ' + e); #endif } }, + // Here, we throw an exception after recording a couple of values that we need to remember + // We also remember that it was the last exception thrown as we need to know that later. __cxa_throw__sig: 'viii', - __cxa_throw__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'], + __cxa_throw__deps: ['_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch', '__cxa_exception_header_size', '__cxa_last_thrown_exception'], __cxa_throw: function(ptr, type, destructor) { if (!___cxa_throw.initialized) { try { @@ -4349,28 +4373,34 @@ LibraryManager.library = { #if EXCEPTION_DEBUG Module.printErr('Compiled code throwing |