aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js362
1 files changed, 307 insertions, 55 deletions
diff --git a/src/library.js b/src/library.js
index 1ef8d0ec..031cf42d 100644
--- a/src/library.js
+++ b/src/library.js
@@ -335,7 +335,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] = {
@@ -3184,10 +3184,6 @@ LibraryManager.library = {
return ret;
},
- getenv: function(name_) {
- return 0; // TODO
- },
-
strtod__deps: ['isspace', 'isdigit'],
strtod: function(str, endptr) {
// Skip space.
@@ -3269,6 +3265,139 @@ 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.
+ __environ: null,
+ __buildEnvironment__deps: ['__environ'],
+ __buildEnvironment: function(env) {
+ if (___environ === null) ___environ = allocate([0], "i8**", ALLOC_STATIC);
+ var ptrSize = {{{ Runtime.getNativeFieldSize('i8*') }}};
+ 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;
+ },
+
// ==========================================================================
// string.h
// ==========================================================================
@@ -3513,59 +3642,75 @@ 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 (chr >= 0 && 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;
- },
-
- // ==========================================================================
- // 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 table 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 = [
@@ -3597,7 +3742,9 @@ LibraryManager.library = {
return me.ret;
},
+ // ==========================================================================
// LLVM specifics
+ // ==========================================================================
llvm_va_copy: function(ppdest, ppsrc) {
{{{ makeCopyValues('ppdest', 'ppsrc', QUANTUM_SIZE, 'null') }}}
@@ -3746,6 +3893,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',
@@ -3754,6 +3905,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',
@@ -3761,14 +3914,23 @@ LibraryManager.library = {
llvm_log_f32: 'Math.log',
llvm_log_f64: 'Math.log',
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) {
@@ -3780,63 +3942,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
@@ -4163,8 +4413,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;
},
@@ -4449,8 +4700,9 @@ LibraryManager.library = {
},
// ==========================================================================
- // ** emscripten.h **
+ // emscripten.h
// ==========================================================================
+
emscripten_run_script: function(ptr) {
eval(Pointer_stringify(ptr));
},