aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js122
1 files changed, 121 insertions, 1 deletions
diff --git a/src/library.js b/src/library.js
index 42e2cc5c..083bf29c 100644
--- a/src/library.js
+++ b/src/library.js
@@ -277,7 +277,7 @@ var Library = {
}
} else {
Module.stdin = function stdin(prompt) {
- return window.prompt(prompt);
+ return window.prompt(prompt) || '';
};
}
@@ -1194,6 +1194,126 @@ var Library = {
return Math.pow(2, x);
},
+
+ // ==========================================================================
+ // dlfcn.h
+ // ==========================================================================
+
+ // Data for dlfcn.h.
+ $DLFCN_DATA: {
+ error: null,
+ isError: false,
+ loadedLibs: {}, // handle -> [refcount, name, lib_object]
+ loadedLibNames: {}, // name -> handle
+ },
+ // void* dlopen(const char* filename, int flag);
+ dlopen__deps: ['$DLFCN_DATA'],
+ dlopen: function(filename, flag) {
+ // TODO: Add support for LD_LIBRARY_PATH.
+ filename = Pointer_stringify(filename);
+ filename += '.js';
+
+ if (DLFCN_DATA.loadedLibNames[filename]) {
+ // Already loaded; increment ref count and return.
+ var handle = DLFCN_DATA.loadedLibNames[filename];
+ DLFCN_DATA.loadedLibs[handle][0]++;
+ return handle;
+ }
+
+ try {
+ var lib_data = read(filename);
+ } catch (e) {
+ DLFCN_DATA.isError = true;
+ return 0;
+ }
+
+ try {
+ var lib_module = eval(lib_data)(FUNCTION_TABLE.length);
+ } catch (e) {
+ DLFCN_DATA.isError = true;
+ return 0;
+ }
+
+ // Not all browsers support Object.keys().
+ var handle = 1;
+ for (var key in DLFCN_DATA.loadedLibs) {
+ if (DLFCN_DATA.loadedLibs.hasOwnProperty(key)) handle++;
+ }
+
+ DLFCN_DATA.loadedLibs[handle] = [1, filename, lib_module];
+ DLFCN_DATA.loadedLibNames[filename] = handle;
+
+ // We don't care about RTLD_NOW and RTLD_LAZY.
+ if (flag & 256) { // RTLD_GLOBAL
+ for (var ident in lib_module) {
+ if (lib_module.hasOwnProperty(ident)) {
+ // TODO: Check if we need to unmangle here.
+ Module[ident] = lib_module[ident];
+ }
+ }
+ }
+
+ return handle;
+ },
+ // int dlclose(void* handle);
+ dlclose__deps: ['$DLFCN_DATA'],
+ dlclose: function(handle) {
+ if (!DLFCN_DATA.loadedLibs[handle]) {
+ DLFCN_DATA.isError = true;
+ return 1;
+ } else {
+ var lib_record = DLFCN_DATA.loadedLibs[handle];
+ if (lib_record[0]-- == 0) {
+ delete DLFCN_DATA.loadedLibNames[lib_record[1]];
+ delete DLFCN_DATA.loadedLibs[handle];
+ }
+ return 0;
+ }
+ },
+ // void* dlsym(void* handle, const char* symbol);
+ dlsym__deps: ['$DLFCN_DATA'],
+ dlsym: function(handle, symbol) {
+ symbol = Pointer_stringify(symbol);
+ // TODO: Properly mangle.
+ symbol = '_' + symbol;
+
+ if (!DLFCN_DATA.loadedLibs[handle]) {
+ DLFCN_DATA.isError = true;
+ return 0;
+ } else {
+ var lib_module = DLFCN_DATA.loadedLibs[handle][2];
+ if (!lib_module[symbol]) {
+ DLFCN_DATA.isError = true;
+ return 0;
+ } else {
+ var result = lib_module[symbol];
+ if (typeof result == 'function') {
+ // TODO: Cache functions rather than appending on every lookup.
+ FUNCTION_TABLE.push(result);
+ FUNCTION_TABLE.push(0);
+ result = FUNCTION_TABLE.length - 2;
+ }
+ return result;
+ }
+ }
+ },
+ // char* dlerror(void);
+ dlerror__deps: ['$DLFCN_DATA'],
+ dlerror: function() {
+ if (DLFCN_DATA.isError) {
+ return 0;
+ } else {
+ // TODO: Return non-generic error messages.
+ if (DLFCN_DATA.error === null) {
+ var msg = 'An error occurred while loading dynamic library.';
+ var arr = Module.intArrayFromString(msg)
+ DLFCN_DATA.error = Pointer_make(arr, 0, 2, 'i8');
+ }
+ DLFCN_DATA.isError = false;
+ return DLFCN_DATA.error;
+ }
+ },
+
// ==========================================================================
// unistd.h
// ==========================================================================