summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library.js581
-rw-r--r--tests/ctype/output.txt233
-rw-r--r--tests/ctype/src.c194
-rw-r--r--tests/env/output.txt29
-rw-r--r--tests/env/src.c43
-rw-r--r--tests/runner.py66
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):