diff options
-rw-r--r-- | src/library.js | 581 | ||||
-rw-r--r-- | tests/ctype/output.txt | 233 | ||||
-rw-r--r-- | tests/ctype/src.c | 194 | ||||
-rw-r--r-- | tests/env/output.txt | 29 | ||||
-rw-r--r-- | tests/env/src.c | 43 | ||||
-rw-r--r-- | tests/runner.py | 66 |
6 files changed, 1054 insertions, 92 deletions
diff --git a/src/library.js b/src/library.js index afcea851..dcd1e22c 100644 --- a/src/library.js +++ b/src/library.js @@ -340,7 +340,7 @@ LibraryManager.library = { 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); + FS.createDevice(devFolder, 'tty', input, output); // Create default streams. FS.streams[1] = { @@ -537,7 +537,8 @@ LibraryManager.library = { } } }, - // TODO: Check if we need to link any aliases. + __01readdir64_: 'readdir', + // TODO: Check if we need to link any other aliases. // ========================================================================== // utime.h @@ -828,6 +829,8 @@ LibraryManager.library = { // http://pubs.opengroup.org/onlinepubs/009604499/functions/statvfs.html return _statvfs(0, buf); }, + __01statvfs64_: 'statvfs', + __01fstatvfs64_: 'fstatvfs', // ========================================================================== // fcntl.h @@ -1102,6 +1105,13 @@ LibraryManager.library = { target.timestamp = new Date(); return 0; }, + chroot__deps: ['__setErrNo', '$ERRNO_CODES'], + chroot: function(path) { + // int chroot(const char *path); + // http://pubs.opengroup.org/onlinepubs/7908799/xsh/chroot.html + ___setErrNo(ERRNO_CODES.EACCES); + return -1; + }, close__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], close: function(fildes) { // int close(int fildes); @@ -1751,6 +1761,16 @@ LibraryManager.library = { getpgrp: 'getgid', getpid: 'getgid', getppid: 'getgid', + getresuid: function(ruid, euid, suid) { + // int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); + // http://linux.die.net/man/2/getresuid + // We have just one process/group/user, all with ID 0. + {{{ makeSetValue('ruid', '0', '0', 'i32') }}} + {{{ makeSetValue('euid', '0', '0', 'i32') }}} + {{{ makeSetValue('suid', '0', '0', 'i32') }}} + return 0; + }, + getresgid: 'getresuid', getgroups__deps: ['__setErrNo', '$ERRNO_CODES'], getgroups: function(gidsetsize, grouplist) { // int getgroups(int gidsetsize, gid_t grouplist[]); @@ -1763,6 +1783,7 @@ LibraryManager.library = { return 1; } }, + // TODO: Implement initgroups, setgroups (grp.h). gethostid: function() { // long gethostid(void); // http://pubs.opengroup.org/onlinepubs/000095399/functions/gethostid.html @@ -1862,6 +1883,9 @@ LibraryManager.library = { }, setregid: 'setpgid', setreuid: 'setpgid', + // NOTE: These do not match the signatures, but they all use the same stub. + setresuid: 'setpgid', + setresgid: 'setpgid', sleep__deps: ['usleep'], sleep: function(seconds) { // unsigned sleep(unsigned seconds); @@ -2067,9 +2091,10 @@ LibraryManager.library = { self.DATASIZE += alignMemoryPage(bytes); return ret; // Previous break location. }, - // TODO: Check if these aliases are correct and if any others are needed. __01open64_: 'open', __01lseek64_: 'lseek', + __01ftruncate64_: 'ftruncate', + // TODO: Check if any other aliases are needed. // ========================================================================== // stdio.h @@ -2172,7 +2197,7 @@ LibraryManager.library = { } else { throw new Error('Unknown formatString argument type: ' + type); } - argIndex += Runtime.getNativeFieldSize(type); + argIndex += Runtime.getNativeFieldSize(type, true); return Number(ret); }; } else { @@ -2625,7 +2650,7 @@ LibraryManager.library = { } else { {{{ makeSetValue('pos', '0', 'stream.position', 'i32') }}} var state = (stream.eof ? 1 : 0) + (stream.error ? 2 : 0); - {{{ makeSetValue('pos', Runtime.getNativeFieldSize('i32'), 'state', 'i32') }}} + {{{ makeSetValue('pos', Runtime.getNativeFieldSize('i32', true), 'state', 'i32') }}} return 0; } } else { @@ -2807,7 +2832,7 @@ LibraryManager.library = { return -1; } else { FS.streams[stream].position = {{{ makeGetValue('pos', '0', 'i32') }}}; - var state = {{{ makeGetValue('pos', Runtime.getNativeFieldSize('i32'), 'i32') }}}; + var state = {{{ makeGetValue('pos', Runtime.getNativeFieldSize('i32', true), 'i32') }}}; FS.streams[stream].eof = Boolean(state & 1); FS.streams[stream].error = Boolean(state & 2); return 0; @@ -3101,10 +3126,11 @@ LibraryManager.library = { 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', + __01tmpfile64_: 'tmpfile', + // TODO: Check if any other aliases are needed. _IO_getc: 'getc', _IO_putc: 'putc', _ZNSo3putEc: 'putchar', @@ -3131,6 +3157,8 @@ LibraryManager.library = { _free(start); }, + // TODO: Implement mremap. + // ========================================================================== // stdlib.h // ========================================================================== @@ -3189,10 +3217,6 @@ LibraryManager.library = { return ret; }, - getenv: function(name_) { - return 0; // TODO - }, - strtod__deps: ['isspace', 'isdigit'], strtod: function(str, endptr) { // Skip space. @@ -3274,6 +3298,150 @@ LibraryManager.library = { _free(temp); }, + // NOTE: The global environment array is rebuilt from scratch after every + // change, which is inefficient, but should not be a bottleneck unless + // no malloc is used, in which case it'll leak memory. + __environ: null, + __buildEnvironment__deps: ['__environ'], + __buildEnvironment: function(env) { + if (___environ === null) ___environ = allocate([0], "i8**", ALLOC_STATIC); + var ptrSize = {{{ Runtime.getNativeFieldSize('i8*', true) }}}; + var envPtr = {{{ makeGetValue('___environ', '0', 'i8**') }}}; + // Clear old. + if (envPtr !== 0) { + var cur = envPtr; + while ({{{ makeGetValue('cur', '0', 'i8*') }}} !== 0) { + _free({{{ makeGetValue('cur', '0', 'i8*') }}}); + cur += ptrSize; + } + _free(envPtr); + } + // Collect key=value lines. + var strings = []; + for (var key in env) { + if (typeof env[key] === 'string') { + strings.push(key + '=' + env[key]); + } + } + // Make new. + envPtr = _malloc(ptrSize * (strings.length + 1)); + {{{ makeSetValue('___environ', '0', 'envPtr', 'i8**') }}} + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + var ptr = _malloc(line.length + 1); + for (var j = 0; j < line.length; j++) { + {{{ makeSetValue('ptr', 'j', 'line.charCodeAt(j)', 'i8') }}} + } + {{{ makeSetValue('ptr', 'j', '0', 'i8') }}} + {{{ makeSetValue('envPtr', 'i * ptrSize', 'ptr', 'i8*') }}} + } + {{{ makeSetValue('envPtr', 'strings.length * ptrSize', '0', 'i8*') }}} + }, + $ENV__deps: ['__buildEnvironment'], + $ENV__postset: '___buildEnvironment(ENV);', + $ENV: { + 'USER': 'root', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/', + 'LANG': 'en_US.UTF-8', + '_': './this.program' + }, + getenv__deps: ['$ENV'], + getenv: function(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + }, + clearenv__deps: ['$ENV', '__buildEnvironment'], + clearenv: function(name) { + // int clearenv (void); + // http://www.gnu.org/s/hello/manual/libc/Environment-Access.html#index-clearenv-3107 + ENV = {}; + ___buildEnvironment(ENV); + return 0; + }, + setenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], + setenv: function(envname, envval, overwrite) { + // int setenv(const char *envname, const char *envval, int overwrite); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/setenv.html + if (envname === 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + var name = Pointer_stringify(envname); + var val = Pointer_stringify(envval); + if (name === '' || name.indexOf('=') !== -1) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + if (ENV.hasOwnProperty(name) && !overwrite) return 0; + ENV[name] = val; + ___buildEnvironment(ENV); + return 0; + }, + unsetenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], + unsetenv: function(name) { + // int unsetenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/unsetenv.html + if (name === 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + name = Pointer_stringify(name); + if (name === '' || name.indexOf('=') !== -1) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + if (ENV.hasOwnProperty(name)) { + delete ENV[name]; + ___buildEnvironment(ENV); + } + return 0; + }, + putenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], + putenv: function(string) { + // int putenv(char *string); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/putenv.html + // WARNING: According to the standard (and the glibc implementation), the + // string is taken by reference so future changes are reflected. + // We copy it instead, possibly breaking some uses. + if (string === 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + string = Pointer_stringify(string); + var splitPoint = string.indexOf('=') + if (string === '' || string.indexOf('=') === -1) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + var name = string.slice(0, splitPoint); + var value = string.slice(splitPoint + 1); + if (!(name in ENV) || ENV[name] !== value) { + ENV[name] = value; + ___buildEnvironment(ENV); + } + return 0; + }, + + getloadavg: function(loadavg, nelem) { + // int getloadavg(double loadavg[], int nelem); + // http://linux.die.net/man/3/getloadavg + var limit = Math.min(nelem, 3); + var doubleSize = {{{ Runtime.getNativeFieldSize('double', true) }}}; + for (var i = 0; i < limit; i++) { + {{{ makeSetValue('loadavg', 'i * doubleSize', '0.1', 'double') }}} + } + return limit; + }, + // ========================================================================== // string.h // ========================================================================== @@ -3489,6 +3657,7 @@ LibraryManager.library = { // Compiled from newlib; for the original source and licensing, see library_strtok_r.c XXX will not work with typed arrays strtok_r: function(b,j,f){var a;a=null;var c,e;b=b;var i=b!=0;a:do if(i)a=0;else{b=HEAP[f];if(b!=0){a=0;break a}c=0;a=3;break a}while(0);if(a==0){a:for(;;){e=HEAP[b];b+=1;a=j;var g=e;i=a;a=2;b:for(;;){d=a==5?d:0;a=HEAP[i+d];if(a!=0==0){a=9;break a}var d=d+1;if(g==a)break b;else a=5}a=2}if(a==9)if(g==0)c=HEAP[f]=0;else{c=b+-1;a:for(;;){e=HEAP[b];b+=1;a=j;g=e;d=a;a=10;b:for(;;){h=a==13?h:0;a=HEAP[d+h];if(a==g!=0)break a;var h=h+1;if(a!=0)a=13;else break b}}if(e==0)b=0;else HEAP[b+-1]=0; HEAP[f]=b;c=c}else if(a==7){HEAP[f]=b;HEAP[b+-1]=0;c=b+-1}}return c}, + // TODO: Compile strtok() from source. strerror_r__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo'], strerror_r: function(errnum, strerrbuf, buflen) { @@ -3518,99 +3687,156 @@ LibraryManager.library = { // ctype.h // ========================================================================== + isascii: function(chr) { + return chr >= 0 && (chr & 0x80) == 0; + }, + toascii: function(chr) { + return chr & 0x7F; + }, + toupper: function(chr) { + if (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) { + return chr - 'a'.charCodeAt(0) + 'A'.charCodeAt(0); + } else { + return chr; + } + }, + _toupper: 'toupper', + tolower: function(chr) { + if (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)) { + return chr - 'A'.charCodeAt(0) + 'a'.charCodeAt(0); + } else { + return chr; + } + }, + _tolower: 'tolower', + // The following functions are defined as macros in glibc. + islower: function(chr) { + return chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0); + }, + isupper: function(chr) { + return chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0); + }, + isalpha: function(chr) { + return (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) || + (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)); + }, isdigit: function(chr) { return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0); }, - isxdigit: function(chr) { return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) || (chr >= 'a'.charCodeAt(0) && chr <= 'f'.charCodeAt(0)) || (chr >= 'A'.charCodeAt(0) && chr <= 'F'.charCodeAt(0)); }, - - isalpha: function(chr) { - return (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) || - (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)); - }, - isalnum: function(chr) { return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) || (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) || (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)); }, - + ispunct: function(chr) { + return (chr >= '!'.charCodeAt(0) && chr <= '/'.charCodeAt(0)) || + (chr >= ':'.charCodeAt(0) && chr <= '@'.charCodeAt(0)) || + (chr >= '['.charCodeAt(0) && chr <= '`'.charCodeAt(0)) || + (chr >= '{'.charCodeAt(0) && chr <= '~'.charCodeAt(0)); + }, isspace: function(chr) { return chr in { 32: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0 }; }, - + isblank: function(chr) { + return chr == ' '.charCodeAt(0) || chr == '\t'.charCodeAt(0); + }, iscntrl: function(chr) { - return (chr >= 0 && chr <= 0x1f) || chr === 0x7f; + return (0 <= chr && chr <= 0x1F) || chr === 0x7F; }, - - isprint__deps: ['iscntrl'], isprint: function(chr) { - return !_iscntrl(chr); - }, - - toupper: function(chr) { - if (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) { - return chr - 'a'.charCodeAt(0) + 'A'.charCodeAt(0); - } - return chr; - }, - - tolower: function(chr) { - if (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)) { - return chr - 'A'.charCodeAt(0) + 'a'.charCodeAt(0); - } - return chr; - }, - - isupper: function(chr) { - return (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)); - }, - - islower: function(chr) { - return (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)); + return 0x1F < chr && chr < 0x7F; }, - - // ========================================================================== - // ctype.h Linux specifics - // ========================================================================== - - __ctype_b_loc: function() { // http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/baselib---ctype-b-loc.html + isgraph: 'isprint', + // 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 var me = ___ctype_b_loc; if (!me.ret) { var values = [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,8195,8194,8194,8194,8194,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,24577,49156,49156,49156, + 49156,49156,49156,49156,49156,49156,49156,49156,49156,49156,49156,49156,55304,55304,55304,55304,55304,55304,55304,55304, + 55304,55304,49156,49156,49156,49156,49156,49156,49156,54536,54536,54536,54536,54536,54536,50440,50440,50440,50440,50440, + 50440,50440,50440,50440,50440,50440,50440,50440,50440,50440,50440,50440,50440,50440,50440,49156,49156,49156,49156,49156, + 49156,54792,54792,54792,54792,54792,54792,50696,50696,50696,50696,50696,50696,50696,50696,50696,50696,50696,50696,50696, + 50696,50696,50696,50696,50696,50696,50696,49156,49156,49156,49156,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,8195,0,8194,0,8194,0,8194,0,8194,0,2,0,2, - 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,24577,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156, - 0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,55304,0,55304,0,55304,0,55304,0,55304,0,55304, - 0,55304,0,55304,0,55304,0,55304,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,54536,0,54536,0,54536,0,54536, - 0,54536,0,54536,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440, - 0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,50440,0,49156,0,49156,0,49156,0,49156,0,49156,0,49156,0,54792,0,54792, - 0,54792,0,54792,0,54792,0,54792,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696, - 0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,50696,0,49156,0,49156,0,49156,0,49156,0,2,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]; - me.ret = allocate([allocate(values, 'i16', ALLOC_STATIC)+256], 'void*', ALLOC_STATIC); -#if USE_TYPED_ARRAYS == 0 - assert(HEAP[HEAP[me.ret]] == 2); - assert(HEAP[HEAP[me.ret]-2] == 0); - assert(HEAP[HEAP[me.ret]+18] == 8195); -#endif + var i16size = {{{ Runtime.getNativeFieldSize('i16', true) }}}; + var arr = _malloc(values.length * i16size); + for (var i = 0; i < values.length; i++) { + {{{ makeSetValue('arr', 'i * i16size', 'values[i]', 'i16') }}} + } + me.ret = allocate([arr + 128 * i16size], 'i16*', ALLOC_STATIC); + } + return me.ret; + }, + __ctype_tolower_loc: function() { + // http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/libutil---ctype-tolower-loc.html + var me = ___ctype_tolower_loc; + if (!me.ret) { + var values = [ + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157, + 158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, + 188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247, + 248,249,250,251,252,253,254,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,97,98,99,100,101,102,103, + 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,96,97,98,99,100,101,102,103, + 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, + 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163, + 164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193, + 194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, + 254,255 + ]; + var i32size = {{{ Runtime.getNativeFieldSize('i32', true) }}}; + var arr = _malloc(values.length * i32size); + for (var i = 0; i < values.length; i++) { + {{{ makeSetValue('arr', 'i * i32size', 'values[i]', 'i32') }}} + } + me.ret = allocate([arr + 128 * i32size], 'i32*', ALLOC_STATIC); + } + return me.ret; + }, + __ctype_toupper_loc: function() { + // http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/libutil---ctype-toupper-loc.html + var me = ___ctype_toupper_loc; + if (!me.ret) { + var values = [ + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157, + 158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, + 188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, + 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247, + 248,249,250,251,252,253,254,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72, + 73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, + 81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144, + 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, + 175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204, + 205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, + 235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 + ]; + var i32size = {{{ Runtime.getNativeFieldSize('i32', true) }}}; + var arr = _malloc(values.length * i32size); + for (var i = 0; i < values.length; i++) { + {{{ makeSetValue('arr', 'i * i32size', 'values[i]', 'i32') }}} + } + me.ret = allocate([arr + 128 * i32size], 'i32*', ALLOC_STATIC); } return me.ret; }, + // ========================================================================== // LLVM specifics + // ========================================================================== llvm_va_copy: function(ppdest, ppsrc) { {{{ makeCopyValues('ppdest', 'ppsrc', QUANTUM_SIZE, 'null') }}} @@ -3759,6 +3985,10 @@ LibraryManager.library = { atanf: 'Math.atan', atan2: 'Math.atan2', atan2f: 'Math.atan2', + exp: 'Math.exp', + expf: 'Math.exp', + log: 'Math.log', + logf: 'Math.log', sqrt: 'Math.sqrt', sqrtf: 'Math.sqrt', fabs: 'Math.abs', @@ -3767,6 +3997,8 @@ LibraryManager.library = { ceilf: 'Math.ceil', floor: 'Math.floor', floorf: 'Math.floor', + pow: 'Math.pow', + powf: 'Math.powf', llvm_sqrt_f32: 'Math.sqrt', llvm_sqrt_f64: 'Math.sqrt', llvm_pow_f32: 'Math.pow', @@ -3776,14 +4008,23 @@ LibraryManager.library = { llvm_exp_f32: 'Math.exp', llvm_exp_f64: 'Math.exp', ldexp: function(x, exp_) { - return x*Math.pow(2, exp_); + return x * Math.pow(2, exp_); }, + ldexpf: 'ldexp', + scalb: 'ldexp', + scalbn: 'ldexp', + scalbnf: 'ldexp', + scalbln: 'ldexp', + scalblnf: 'ldexp', modf: function(x, intpart) { {{{ makeSetValue('intpart', 0, 'Math.floor(x)', 'double') }}} return x - {{{ makeGetValue('intpart', 0, 'double') }}}; }, - + modff: function(x, intpart) { + {{{ makeSetValue('intpart', 0, 'Math.floor(x)', 'float') }}} + return x - {{{ makeGetValue('intpart', 0, 'float') }}}; + }, frexp: function(x, exp_addr) { var sig = 0, exp_ = 0; if (x !== 0) { @@ -3795,63 +4036,151 @@ LibraryManager.library = { {{{ makeSetValue('exp_addr', 0, 'exp_', 'i32') }}} return sig; }, - + frexpf: 'frexp', finite: function(x) { return isFinite(x); }, __finite: 'finite', - isinf: function(x) { return !isNaN(x) && !isFinite(x); }, __isinf: 'isinf', - isnan: function(x) { return isNaN(x); }, __isnan: 'isnan', - copysign: function(a, b) { - if (a<0 === b<0) return a; + if (a < 0 === b < 0) return a; return -a; }, - + copysignf: 'copysign', hypot: function(a, b) { return Math.sqrt(a*a + b*b); }, - + hypotf: 'hypot', sinh: function(x) { var p = Math.pow(Math.E, x); return (p - (1 / p)) / 2; }, - + sinhf: 'sinh', cosh: function(x) { var p = Math.pow(Math.E, x); return (p + (1 / p)) / 2; }, - + coshf: 'cosh', tanh__deps: ['sinh', 'cosh'], tanh: function(x) { return _sinh(x) / _cosh(x); }, - + tanhf: 'tanh', asinh: function(x) { return Math.log(x + Math.sqrt(x * x + 1)); }, - + asinhf: 'asinh', acosh: function(x) { return Math.log(x * 1 + Math.sqrt(x * x - 1)); }, - + acoshf: 'acosh', atanh: function(x) { return Math.log((1 + x) / (1 - x)) / 2; }, - - // LLVM internal math - + atanhf: 'atanh', exp2: function(x) { return Math.pow(2, x); }, + exp2f: 'exp2', + expm1: function(x) { + return Math.exp(x) - 1; + }, + expm1f: 'expm1', + round: function(x) { + return (x < 0) ? -Math.round(-x) : Math.round(x); + }, + roundf: 'round', + lround: 'round', + lroundf: 'round', + llround: 'round', + llroundf: 'round', + rint: function(x) { + return (x > 0) ? -Math.round(-x) : Math.round(x); + }, + rintf: 'rint', + lrint: 'rint', + lrintf: 'rint', + llrint: 'rint', + llrintf: 'rint', + nearbyint: 'rint', + nearbyintf: 'rint', + trunc: function(x) { + return (x < 0) ? Math.ceil(x) : Math.floor(x); + }, + truncf: 'trunc', + fdim: function(x, y) { + return (x > y) ? x - y : 0; + }, + fdimf: 'fdim', + fmax: function(x, y) { + return isNaN(x) ? y : isNaN(y) ? x : Math.max(x, y); + }, + fmaxf: 'fmax', + fmin: function(x, y) { + return isNaN(x) ? y : isNaN(y) ? x : Math.max(x, y); + }, + fminf: 'fmin', + fma: function(x, y, z) { + return x * y + z; + }, + fmaf: 'fma', + fmod: function(x, y) { + return x % y; + }, + fmodf: 'fmod', + remainder: 'fmod', + remainderf: 'fmod', + log10: function(x) { + return Math.log(x) / Math.LN10; + }, + log10f: 'log10', + log1p: function(x) { + return Math.log(1 + x); + }, + log1pf: 'log1p', + log2: function(x) { + return Math.log(x) / Math.LN2; + }, + log2f: 'log2', + nan: function(x) { + return NaN; + }, + nanf: 'nan', + + // ========================================================================== + // sys/utsname.h + // ========================================================================== + + __utsname_struct_layout: Runtime.generateStructInfo(null, '%struct.utsname'), + uname__deps: ['__utsname_struct_layout'], + uname: function(name) { + // int uname(struct utsname *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/uname.html + if (name === 0) { + return -1; + } else { + var copyString = function(element, value) { + var offset = ___utsname_struct_layout[element]; + for (var i = 0; i < value.length; i++) { + {{{ makeSetValue('name', 'offset + i', 'value.charCodeAt(i)', 'i8') }}} + } + {{{ makeSetValue('name', 'offset + i', '0', 'i8') }}} + }; + copyString('sysname', 'Emscripten'); + copyString('nodename', 'emscripten'); + copyString('release', '1.0'); + copyString('version', '#1'); + copyString('machine', 'x86-JS'); + return 0; + } + }, // ========================================================================== // dlfcn.h - Dynamic library loading @@ -3986,6 +4315,8 @@ LibraryManager.library = { // pwd.h // ========================================================================== + // TODO: Implement. + // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/pwd.h.html getpwuid: function(uid) { return 0; // NULL }, @@ -4178,8 +4509,9 @@ LibraryManager.library = { {{{ makeSetValue('_tzname', QUANTUM_SIZE, 'summerNamePtr', 'i32') }}} }, + stime__deps: ['$ERRNO_CODES', '__setErrNo'], stime: function(when) { - // TODO: Set errno. + ___setErrNo(ERRNO_CODES.EPERM); return -1; }, @@ -4189,6 +4521,8 @@ LibraryManager.library = { // sys/time.h // ========================================================================== + // TODO: Implement remaining functions. + // http://pubs.opengroup.org/onlinepubs/000095399/basedefs/sys/time.h.html gettimeofday: function(ptr) { // %struct.timeval = type { i32, i32 } var indexes = Runtime.calculateStructAlignment({ fields: ['i32', 'i32'] }); @@ -4199,6 +4533,41 @@ LibraryManager.library = { }, // ========================================================================== + // sys/times.h + // ========================================================================== + + __tms_struct_layout: Runtime.generateStructInfo(null, '%struct.tms'), + times__deps: ['__tms_struct_layout'], + times: function(buffer) { + // clock_t times(struct tms *buffer); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html + // NOTE: This is fake, since we can't calculate real CPU time usage in JS. + if (buffer !== 0) { + {{{ makeSetValues('buffer', '0', '0', 'null', '___tms_struct_layout.__size__') }}} + } + return 0; + }, + + // ========================================================================== + // sys/types.h + // ========================================================================== + + // NOTE: These are fake, since we don't support the C device creation API. + // http://www.kernel.org/doc/man-pages/online/pages/man3/minor.3.html + makedev: function(maj, min) { + return 0; + }, + gnu_dev_makedev: 'makedev', + major: function(dev) { + return 0; + }, + gnu_dev_major: 'major', + minor: function(dev) { + return 0; + }, + gnu_dev_minor: 'minor', + + // ========================================================================== // setjmp.h // ========================================================================== @@ -4220,13 +4589,39 @@ LibraryManager.library = { // TODO return 0; }, - __libc_current_sigrtmin: function() { return 0; }, __libc_current_sigrtmax: function() { return 0; }, + kill__deps: ['$ERRNO_CODES', '__setErrNo'], + kill: function(pid, sig) { + // int kill(pid_t pid, int sig); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/kill.html + // Makes no sense in a single-process environment. + ___setErrNo(ERRNO_CODES.EPERM); + return -1; + }, + killpg: 'kill', + + // ========================================================================== + // sys/wait.h + // ========================================================================== + + wait__deps: ['$ERRNO_CODES', '__setErrNo'], + wait: function(stat_loc) { + // pid_t wait(int *stat_loc); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/wait.html + // Makes no sense in a single-process environment. + ___setErrNo(ERRNO_CODES.ECHILD); + return -1; + }, + // NOTE: These aren't really the same, but we use the same stub for them all. + waitid: 'wait', + waitpid: 'wait', + wait3: 'wait', + wait4: 'wait', // ========================================================================== // locale.h @@ -4250,6 +4645,7 @@ LibraryManager.library = { // langinfo.h // ========================================================================== + // TODO: Implement for real. nl_langinfo: function(item) { var me = _nl_langinfo; if (!me.ret) { @@ -4464,8 +4860,9 @@ LibraryManager.library = { }, // ========================================================================== - // ** emscripten.h ** + // emscripten.h // ========================================================================== + emscripten_run_script: function(ptr) { eval(Pointer_stringify(ptr)); }, diff --git a/tests/ctype/output.txt b/tests/ctype/output.txt new file mode 100644 index 00000000..5f98d20d --- /dev/null +++ b/tests/ctype/output.txt @@ -0,0 +1,233 @@ +ab1 +AB1 +cd2 +CD2 + +toascii(-45): 83 +toascii( 10): 10 +toascii('a'): 97 +toascii(183): 55 + +isascii/call(-45): 0 +isascii/call( 10): 1 +isascii/call('a'): 1 +isascii/call('A'): 1 +isascii/call('5'): 1 +isascii/call('.'): 1 +isascii/call(183): 0 + +islower/call(-45): 0 +islower/call( 10): 0 +islower/call('a'): 1 +islower/call('A'): 0 +islower/call('5'): 0 +islower/call('.'): 0 +islower/call(183): 0 + +isupper/call(-45): 0 +isupper/call( 10): 0 +isupper/call('a'): 0 +isupper/call('A'): 1 +isupper/call('5'): 0 +isupper/call('.'): 0 +isupper/call(183): 0 + +isupper/call(-45): 0 +isupper/call( 10): 0 +isupper/call('a'): 0 +isupper/call('A'): 1 +isupper/call('5'): 0 +isupper/call('.'): 0 +isupper/call(183): 0 + +isalpha/call(-45): 0 +isalpha/call( 10): 0 +isalpha/call('a'): 1 +isalpha/call('A'): 1 +isalpha/call('5'): 0 +isalpha/call('.'): 0 +isalpha/call(183): 0 + +isdigit/call(-45): 0 +isdigit/call( 10): 0 +isdigit/call('a'): 0 +isdigit/call('A'): 0 +isdigit/call('5'): 1 +isdigit/call('.'): 0 +isdigit/call(183): 0 + +isxdigit/call(-45): 0 +isxdigit/call( 10): 0 +isxdigit/call('a'): 1 +isxdigit/call('A'): 1 +isxdigit/call('5'): 1 +isxdigit/call('.'): 0 +isxdigit/call(183): 0 + +isalnum/call(-45): 0 +isalnum/call( 10): 0 +isalnum/call('a'): 1 +isalnum/call('A'): 1 +isalnum/call('5'): 1 +isalnum/call('.'): 0 +isalnum/call(183): 0 + +ispunct/call(-45): 0 +ispunct/call( 10): 0 +ispunct/call('a'): 0 +ispunct/call('A'): 0 +ispunct/call('5'): 0 +ispunct/call('.'): 1 +ispunct/call(183): 0 + +isspace/call(-45): 0 +isspace/call( 10): 1 +isspace/call('a'): 0 +isspace/call('A'): 0 +isspace/call('5'): 0 +isspace/call('.'): 0 +isspace/call(183): 0 + +isblank/call(-45): 0 +isblank/call( 10): 0 +isblank/call('a'): 0 +isblank/call('A'): 0 +isblank/call('5'): 0 +isblank/call('.'): 0 +isblank/call(183): 0 + +iscntrl/call(-45): 0 +iscntrl/call( 10): 1 +iscntrl/call('a'): 0 +iscntrl/call('A'): 0 +iscntrl/call('5'): 0 +iscntrl/call('.'): 0 +iscntrl/call(183): 0 + +isprint/call(-45): 0 +isprint/call( 10): 0 +isprint/call('a'): 1 +isprint/call('A'): 1 +isprint/call('5'): 1 +isprint/call('.'): 1 +isprint/call(183): 0 + +isgraph/call(-45): 0 +isgraph/call( 10): 0 +isgraph/call('a'): 1 +isgraph/call('A'): 1 +isgraph/call('5'): 1 +isgraph/call('.'): 1 +isgraph/call(183): 0 + +isascii(-45): 0 +isascii( 10): 1 +isascii('a'): 1 +isascii('A'): 1 +isascii('5'): 1 +isascii('.'): 1 +isascii(183): 0 + +islower(-45): 0 +islower( 10): 0 +islower('a'): 1 +islower('A'): 0 +islower('5'): 0 +islower('.'): 0 +islower(183): 0 + +isupper(-45): 0 +isupper( 10): 0 +isupper('a'): 0 +isupper('A'): 1 +isupper('5'): 0 +isupper('.'): 0 +isupper(183): 0 + +isupper(-45): 0 +isupper( 10): 0 +isupper('a'): 0 +isupper('A'): 1 +isupper('5'): 0 +isupper('.'): 0 +isupper(183): 0 + +isalpha(-45): 0 +isalpha( 10): 0 +isalpha('a'): 1 +isalpha('A'): 1 +isalpha('5'): 0 +isalpha('.'): 0 +isalpha(183): 0 + +isdigit(-45): 0 +isdigit( 10): 0 +isdigit('a'): 0 +isdigit('A'): 0 +isdigit('5'): 1 +isdigit('.'): 0 +isdigit(183): 0 + +isxdigit(-45): 0 +isxdigit( 10): 0 +isxdigit('a'): 1 +isxdigit('A'): 1 +isxdigit('5'): 1 +isxdigit('.'): 0 +isxdigit(183): 0 + +isalnum(-45): 0 +isalnum( 10): 0 +isalnum('a'): 1 +isalnum('A'): 1 +isalnum('5'): 1 +isalnum('.'): 0 +isalnum(183): 0 + +ispunct(-45): 0 +ispunct( 10): 0 +ispunct('a'): 0 +ispunct('A'): 0 +ispunct('5'): 0 +ispunct('.'): 1 +ispunct(183): 0 + +isspace(-45): 0 +isspace( 10): 1 +isspace('a'): 0 +isspace('A'): 0 +isspace('5'): 0 +isspace('.'): 0 +isspace(183): 0 + +isblank(-45): 0 +isblank( 10): 0 +isblank('a'): 0 +isblank('A'): 0 +isblank('5'): 0 +isblank('.'): 0 +isblank(183): 0 + +iscntrl(-45): 0 +iscntrl( 10): 1 +iscntrl('a'): 0 +iscntrl('A'): 0 +iscntrl('5'): 0 +iscntrl('.'): 0 +iscntrl(183): 0 + +isprint(-45): 0 +isprint( 10): 0 +isprint('a'): 1 +isprint('A'): 1 +isprint('5'): 1 +isprint('.'): 1 +isprint(183): 0 + +isgraph(-45): 0 +isgraph( 10): 0 +isgraph('a'): 1 +isgraph('A'): 1 +isgraph('5'): 1 +isgraph('.'): 1 +isgraph(183): 0 diff --git a/tests/ctype/src.c b/tests/ctype/src.c new file mode 100644 index 00000000..4dce6999 --- /dev/null +++ b/tests/ctype/src.c @@ -0,0 +1,194 @@ +#define _BSD_SOURCE +#include <stdio.h> +#include <ctype.h> + +int main() { + printf("%c%c%c\n", tolower('a'), tolower('B'), tolower('1')); + printf("%c%c%c\n", toupper('a'), toupper('B'), toupper('1')); + + const int* tl = *__ctype_tolower_loc(); + printf("%c%c%c\n", (char)tl['c'], (char)tl['D'], (char)tl['2']); + const int* tu = *__ctype_toupper_loc(); + printf("%c%c%c\n", (char)tu['c'], (char)tu['D'], (char)tu['2']); + + printf("\n"); + + printf("toascii(-45): %d\n", toascii(-45)); + printf("toascii( 10): %d\n", toascii(10)); + printf("toascii('a'): %d\n", toascii('a')); + printf("toascii(183): %d\n", toascii(183)); + + // These will be compiled as actual function calls. + int (*funcs[])(int) = { + isascii, + islower, + isupper, + isupper, + isalpha, + isdigit, + isxdigit, + isalnum, + ispunct, + isspace, + isblank, + iscntrl, + isprint, + isgraph + }; + char* funcNames[] = { + "isascii", + "islower", + "isupper", + "isupper", + "isalpha", + "isdigit", + "isxdigit", + "isalnum", + "ispunct", + "isspace", + "isblank", + "iscntrl", + "isprint", + "isgraph" + }; + for (int i = 0; i < sizeof funcs / sizeof funcs[0]; i++) { + printf("\n"); + printf("%s/call(-45): %d\n", funcNames[i], funcs[i](-45) != 0); + printf("%s/call( 10): %d\n", funcNames[i], funcs[i](10) != 0); + printf("%s/call('a'): %d\n", funcNames[i], funcs[i]('a') != 0); + printf("%s/call('A'): %d\n", funcNames[i], funcs[i]('A') != 0); + printf("%s/call('5'): %d\n", funcNames[i], funcs[i]('5') != 0); + printf("%s/call('.'): %d\n", funcNames[i], funcs[i]('.') != 0); + printf("%s/call(183): %d\n", funcNames[i], funcs[i](183) != 0); + } + + printf("\n"); + printf("isascii(-45): %d\n", isascii(-45) != 0); + printf("isascii( 10): %d\n", isascii( 10) != 0); + printf("isascii('a'): %d\n", isascii('a') != 0); + printf("isascii('A'): %d\n", isascii('A') != 0); + printf("isascii('5'): %d\n", isascii('5') != 0); + printf("isascii('.'): %d\n", isascii('.') != 0); + printf("isascii(183): %d\n", isascii(183) != 0); + + // These are manually preprocessed to use __ctype_b_loc. The flags combination + // that the test runner uses seems to cause the macro to be ignored. + printf("\n"); + printf("islower(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISlower) != 0); + printf("islower( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISlower) != 0); + printf("islower('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISlower) != 0); + printf("islower('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISlower) != 0); + printf("islower('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISlower) != 0); + printf("islower('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISlower) != 0); + printf("islower(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISlower) != 0); + + printf("\n"); + printf("isupper(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISupper) != 0); + printf("isupper( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISupper) != 0); + printf("isupper('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISupper) != 0); + printf("isupper('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISupper) != 0); + printf("isupper('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISupper) != 0); + printf("isupper('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISupper) != 0); + printf("isupper(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISupper) != 0); + + printf("\n"); + printf("isupper(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISupper) != 0); + printf("isupper( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISupper) != 0); + printf("isupper('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISupper) != 0); + printf("isupper('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISupper) != 0); + printf("isupper('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISupper) != 0); + printf("isupper('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISupper) != 0); + printf("isupper(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISupper) != 0); + + printf("\n"); + printf("isalpha(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISalpha) != 0); + printf("isalpha( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISalpha) != 0); + printf("isalpha('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISalpha) != 0); + printf("isalpha('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISalpha) != 0); + printf("isalpha('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISalpha) != 0); + printf("isalpha('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISalpha) != 0); + printf("isalpha(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISalpha) != 0); + + printf("\n"); + printf("isdigit(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISdigit) != 0); + printf("isdigit( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISdigit) != 0); + printf("isdigit('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISdigit) != 0); + printf("isdigit('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISdigit) != 0); + printf("isdigit('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISdigit) != 0); + printf("isdigit('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISdigit) != 0); + printf("isdigit(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISdigit) != 0); + + printf("\n"); + printf("isxdigit(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISxdigit) != 0); + printf("isxdigit( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISxdigit) != 0); + printf("isxdigit('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISxdigit) != 0); + printf("isxdigit('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISxdigit) != 0); + printf("isxdigit('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISxdigit) != 0); + printf("isxdigit('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISxdigit) != 0); + printf("isxdigit(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISxdigit) != 0); + + printf("\n"); + printf("isalnum(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISalnum) != 0); + printf("isalnum( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISalnum) != 0); + printf("isalnum('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISalnum) != 0); + printf("isalnum('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISalnum) != 0); + printf("isalnum('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISalnum) != 0); + printf("isalnum('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISalnum) != 0); + printf("isalnum(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISalnum) != 0); + + printf("\n"); + printf("ispunct(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISpunct) != 0); + printf("ispunct( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISpunct) != 0); + printf("ispunct('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISpunct) != 0); + printf("ispunct('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISpunct) != 0); + printf("ispunct('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISpunct) != 0); + printf("ispunct('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISpunct) != 0); + printf("ispunct(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISpunct) != 0); + + printf("\n"); + printf("isspace(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISspace) != 0); + printf("isspace( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISspace) != 0); + printf("isspace('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISspace) != 0); + printf("isspace('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISspace) != 0); + printf("isspace('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISspace) != 0); + printf("isspace('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISspace) != 0); + printf("isspace(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISspace) != 0); + + printf("\n"); + printf("isblank(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISblank) != 0); + printf("isblank( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISblank) != 0); + printf("isblank('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISblank) != 0); + printf("isblank('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISblank) != 0); + printf("isblank('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISblank) != 0); + printf("isblank('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISblank) != 0); + printf("isblank(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISblank) != 0); + + printf("\n"); + printf("iscntrl(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _IScntrl) != 0); + printf("iscntrl( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _IScntrl) != 0); + printf("iscntrl('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _IScntrl) != 0); + printf("iscntrl('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _IScntrl) != 0); + printf("iscntrl('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _IScntrl) != 0); + printf("iscntrl('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _IScntrl) != 0); + printf("iscntrl(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _IScntrl) != 0); + + printf("\n"); + printf("isprint(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISprint) != 0); + printf("isprint( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISprint) != 0); + printf("isprint('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISprint) != 0); + printf("isprint('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISprint) != 0); + printf("isprint('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISprint) != 0); + printf("isprint('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISprint) != 0); + printf("isprint(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISprint) != 0); + + printf("\n"); + printf("isgraph(-45): %d\n", ((*__ctype_b_loc ())[(int) ((-45))] & (unsigned short int) _ISgraph) != 0); + printf("isgraph( 10): %d\n", ((*__ctype_b_loc ())[(int) ((10))] & (unsigned short int) _ISgraph) != 0); + printf("isgraph('a'): %d\n", ((*__ctype_b_loc ())[(int) (('a'))] & (unsigned short int) _ISgraph) != 0); + printf("isgraph('A'): %d\n", ((*__ctype_b_loc ())[(int) (('A'))] & (unsigned short int) _ISgraph) != 0); + printf("isgraph('5'): %d\n", ((*__ctype_b_loc ())[(int) (('5'))] & (unsigned short int) _ISgraph) != 0); + printf("isgraph('.'): %d\n", ((*__ctype_b_loc ())[(int) (('.'))] & (unsigned short int) _ISgraph) != 0); + printf("isgraph(183): %d\n", ((*__ctype_b_loc ())[(int) ((183))] & (unsigned short int) _ISgraph) != 0); + + return 0; +} diff --git a/tests/env/output.txt b/tests/env/output.txt new file mode 100644 index 00000000..fa342d48 --- /dev/null +++ b/tests/env/output.txt @@ -0,0 +1,29 @@ +List: +USER=root +PATH=/ +PWD=/ +HOME=/ +LANG=en_US.UTF-8 +_=./this.program + +getenv(PATH): / +getenv(NONEXISTENT): (null) +setenv/0(PATH) ret: 0 +getenv(PATH) after setenv/0: / +setenv/1(PATH) ret: 0 +getenv(PATH) after setenv/1: test2 +setenv(SET_VALUE) ret: 0 +setenv(SET_VALUE2) ret: 0 +getenv(SET_VALUE): test3 +getenv(SET_VALUE2): test4 +putenv(PUT_VALUE) ret: 0 +getenv(PUT_VALUE): test5 +getenv(PUT_VALUE) after alteration: test5 +unsetenv(PUT_VALUE) ret: 0 +getenv(PUT_VALUE) after unsetenv: (null) +setenv(0) ret: -1 +setenv('') ret: -1 +setenv(X=Y) ret: -1 +unsetenv(0) ret: -1 +unsetenv('') ret: -1 +unsetenv(X=Y) ret: -1 diff --git a/tests/env/src.c b/tests/env/src.c new file mode 100644 index 00000000..46419495 --- /dev/null +++ b/tests/env/src.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main() { + printf("List:\n"); + for (char** str = __environ; *str; str++) { + printf("%s\n", *str); + } + printf("\n"); + + printf("getenv(PATH): %s\n", getenv("PATH")); + printf("getenv(NONEXISTENT): %s\n", getenv("NONEXISTENT")); + + printf("setenv/0(PATH) ret: %d\n", setenv("PATH", "test", 0)); + printf("getenv(PATH) after setenv/0: %s\n", getenv("PATH")); + printf("setenv/1(PATH) ret: %d\n", setenv("PATH", "test2", 1)); + printf("getenv(PATH) after setenv/1: %s\n", getenv("PATH")); + + printf("setenv(SET_VALUE) ret: %d\n", setenv("SET_VALUE", "test3", 0)); + printf("setenv(SET_VALUE2) ret: %d\n", setenv("SET_VALUE2", "test4", 1)); + printf("getenv(SET_VALUE): %s\n", getenv("SET_VALUE")); + printf("getenv(SET_VALUE2): %s\n", getenv("SET_VALUE2")); + + char buffer[] = "PUT_VALUE=test5"; + printf("putenv(PUT_VALUE) ret: %d\n", putenv(buffer)); + printf("getenv(PUT_VALUE): %s\n", getenv("PUT_VALUE")); + // NOTE: This should change the value. In our implementation, it doesn't. + buffer[10] = 'Q'; + printf("getenv(PUT_VALUE) after alteration: %s\n", getenv("PUT_VALUE")); + + printf("unsetenv(PUT_VALUE) ret: %d\n", unsetenv("PUT_VALUE")); + printf("getenv(PUT_VALUE) after unsetenv: %s\n", getenv("PUT_VALUE")); + + printf("setenv(0) ret: %d\n", setenv(0, "foo", 1)); + printf("setenv('') ret: %d\n", setenv("", "foo", 1)); + printf("setenv(X=Y) ret: %d\n", setenv("X=Y", "foo", 1)); + printf("unsetenv(0) ret: %d\n", unsetenv(0)); + printf("unsetenv('') ret: %d\n", unsetenv("")); + printf("unsetenv(X=Y) ret: %d\n", unsetenv("X=Y")); + + return 0; +} diff --git a/tests/runner.py b/tests/runner.py index 8e1fdfa5..330c0726 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -2576,6 +2576,72 @@ if 'benchmark' not in sys.argv: expected = open(path_from_root('tests', 'unistd', 'misc.out'), 'r').read() self.do_test(src, expected) + def test_uname(self): + src = r''' + #include <stdio.h> + #include <sys/utsname.h> + + int main() { + struct utsname u; + printf("ret: %d\n", uname(&u)); + printf("sysname: %s\n", u.sysname); + printf("nodename: %s\n", u.nodename); + printf("release: %s\n", u.release); + printf("version: %s\n", u.version); + printf("machine: %s\n", u.machine); + printf("invalid: %d\n", uname(0)); + return 0; + } + ''' + expected = ''' + ret: 0 + sysname: Emscripten + nodename: emscripten + release: 1.0 + version: #1 + machine: x86-JS + ''' + self.do_test(src, re.sub('(^|\n)\s+', '\\1', expected)) + + def test_env(self): + src = open(path_from_root('tests', 'env', 'src.c'), 'r').read() + expected = open(path_from_root('tests', 'env', 'output.txt'), 'r').read() + self.do_test(src, expected) + + def test_getloadavg(self): + src = r''' + #include <stdio.h> + #include <stdlib.h> + + int main() { + double load[5] = {42.13, 42.13, 42.13, 42.13, 42.13}; + printf("ret: %d\n", getloadavg(load, 5)); + printf("load[0]: %lf\n", load[0]); + printf("load[1]: %lf\n", load[1]); + printf("load[2]: %lf\n", load[2]); + printf("load[3]: %lf\n", load[3]); + printf("load[4]: %lf\n", load[4]); + return 0; + } + ''' + expected = ''' + ret: 3 + load[0]: 0.100000 + load[1]: 0.100000 + load[2]: 0.100000 + load[3]: 42.130000 + load[4]: 42.130000 + ''' + self.do_test(src, re.sub('(^|\n)\s+', '\\1', expected)) + + def test_ctype(self): + # The bit fiddling done by the macros using __ctype_b_loc requires this. + global CORRECT_SIGNS; CORRECT_SIGNS = 1 + src = open(path_from_root('tests', 'ctype', 'src.c'), 'r').read() + expected = open(path_from_root('tests', 'ctype', 'output.txt'), 'r').read() + self.do_test(src, expected) + CORRECT_SIGNS = 0 + ### 'Big' tests def test_fannkuch(self): |