aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js4
-rw-r--r--src/embind/embind.js620
-rw-r--r--src/embind/emval.js111
-rw-r--r--src/jsifier.js14
-rw-r--r--src/library.js271
-rw-r--r--src/library_browser.js66
-rw-r--r--src/library_egl.js421
-rw-r--r--src/library_gl.js11
-rw-r--r--src/library_jansson.js225
-rw-r--r--src/library_sdl.js37
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js8
-rw-r--r--src/preamble.js8
-rw-r--r--src/runtime.js2
-rw-r--r--src/settings.js9
15 files changed, 1762 insertions, 47 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 69b811f0..9d060a2c 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -1237,7 +1237,7 @@ function analyzer(data, sidePass) {
if (phi.intertype == 'phi') {
for (var i = 0; i < phi.params.length; i++) {
phi.params[i].label = func.labelIds[phi.params[i].label];
- if (!phi.params[i].label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
+ if (VERBOSE && !phi.params[i].label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
}
}
});
@@ -1316,7 +1316,7 @@ function analyzer(data, sidePass) {
if (phi.intertype == 'phi') {
for (var i = 0; i < phi.params.length; i++) {
var param = phi.params[i];
- if (!param.label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
+ if (VERBOSE && !param.label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
var sourceLabelId = getActualLabelId(param.label);
if (sourceLabelId) {
var sourceLabel = func.labelsDict[sourceLabelId];
diff --git a/src/embind/embind.js b/src/embind/embind.js
new file mode 100644
index 00000000..d40d6ca2
--- /dev/null
+++ b/src/embind/embind.js
@@ -0,0 +1,620 @@
+/*global Module*/
+/*global _malloc, _free, _memcpy*/
+/*global FUNCTION_TABLE, HEAP32*/
+/*global Pointer_stringify, writeStringToMemory*/
+/*global __emval_register, _emval_handle_array, __emval_decref*/
+
+function createNamedFunction(name, body) {
+ /*jshint evil:true*/
+ return new Function(
+ "body",
+ "return function " + name + "() {\n" +
+ " return body.apply(this, arguments);\n" +
+ "};\n"
+ )(body);
+}
+
+function _embind_repr(v) {
+ var t = typeof v;
+ if (t === 'object' || t === 'array' || t === 'function') {
+ return v.toString();
+ } else {
+ return '' + v;
+ }
+}
+
+var typeRegistry = {};
+
+function validateType(type, name) {
+ if (!type) {
+ throw new BindingError('type "' + name + '" must have a positive integer typeid pointer');
+ }
+ if (undefined !== typeRegistry[type]) {
+ throw new BindingError('cannot register type "' + name + '" twice');
+ }
+}
+
+function __embind_register_void(voidType, name) {
+ name = Pointer_stringify(name);
+ validateType(voidType, name);
+ typeRegistry[voidType] = {
+ name: name,
+ fromWireType: function() {
+ return undefined;
+ }
+ };
+}
+
+function __embind_register_bool(boolType, name, trueValue, falseValue) {
+ name = Pointer_stringify(name);
+ validateType(boolType, name);
+ typeRegistry[boolType] = {
+ name: name,
+ toWireType: function(destructors, o) {
+ return o ? trueValue : falseValue;
+ },
+ fromWireType: function(wt) {
+ return wt === trueValue;
+ },
+ };
+}
+
+function __embind_register_integer(primitiveType, name) {
+ name = Pointer_stringify(name);
+ validateType(primitiveType, name);
+ typeRegistry[primitiveType] = {
+ name: name,
+ toWireType: function(destructors, value) {
+ if (typeof value !== "number") {
+ throw new TypeError('Cannot convert "' + _embind_repr(value) + '" to ' + name);
+ }
+ return value | 0;
+ },
+ fromWireType: function(value) {
+ return value;
+ }
+ };
+}
+
+function __embind_register_float(primitiveType, name) {
+ name = Pointer_stringify(name);
+ validateType(primitiveType, name);
+ typeRegistry[primitiveType] = {
+ name: name,
+ toWireType: function(destructors, value) {
+ if (typeof value !== "number") {
+ throw new TypeError('Cannot convert "' + _embind_repr(value) + '" to ' + name);
+ }
+ return value;
+ },
+ fromWireType: function(value) {
+ return value;
+ }
+ };
+}
+
+function __embind_register_cstring(stringType, name) {
+ name = Pointer_stringify(name);
+ validateType(stringType, name);
+ typeRegistry[stringType] = {
+ name: name,
+ toWireType: function(destructors, value) {
+ var ptr = _malloc(value.length + 1);
+ writeStringToMemory(value, ptr);
+ destructors.push(_free);
+ destructors.push(ptr);
+ return ptr;
+ },
+ fromWireType: function(value) {
+ var rv = Pointer_stringify(value);
+ _free(value);
+ return rv;
+ }
+ };
+}
+
+function __embind_register_emval(emvalType, name) {
+ name = Pointer_stringify(name);
+ validateType(emvalType, name);
+ typeRegistry[emvalType] = {
+ name: name,
+ toWireType: function(destructors, value) {
+ return __emval_register(value);
+ },
+ fromWireType: function(handle) {
+ var rv = _emval_handle_array[handle].value;
+ __emval_decref(handle);
+ return rv;
+ }
+ };
+}
+
+var BindingError = Error;
+/** @expose */
+Module.BindingError = BindingError;
+
+function typeName(typeID) {
+ // could use our carnal knowledge of RTTI but for now just return the pointer...
+ return typeID;
+}
+
+function requireRegisteredType(type, humanName) {
+ var impl = typeRegistry[type];
+ if (undefined === impl) {
+ throw new BindingError(humanName + " has unknown type: " + typeName(type));
+ }
+ return impl;
+}
+
+function requireArgumentTypes(argCount, argTypes, name) {
+ var argTypeImpls = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ var argType = HEAP32[(argTypes >> 2) + i];
+ argTypeImpls[i] = requireRegisteredType(argType, name + " parameter " + i);
+ }
+ return argTypeImpls;
+}
+
+function runDestructors(destructors) {
+ while (destructors.length) {
+ var ptr = destructors.pop();
+ var del = destructors.pop();
+ del(ptr);
+ }
+}
+
+function __embind_register_function(name, returnType, argCount, argTypes, invoker, fn) {
+ name = Pointer_stringify(name);
+ returnType = requireRegisteredType(returnType, "Function " + name + " return value");
+ invoker = FUNCTION_TABLE[invoker];
+ argTypes = requireArgumentTypes(argCount, argTypes, name);
+
+ Module[name] = function() {
+ if (arguments.length !== argCount) {
+ throw new BindingError('emscripten binding function ' + name + ' called with ' + arguments.length + ' arguments, expected ' + argCount);
+ }
+ var destructors = [];
+ var args = new Array(argCount + 1);
+ args[0] = fn;
+ for (var i = 0; i < argCount; ++i) {
+ args[i + 1] = argTypes[i].toWireType(destructors, arguments[i]);
+ }
+ var rv = returnType.fromWireType(invoker.apply(null, args));
+ runDestructors(destructors);
+ return rv;
+ };
+}
+
+function __embind_register_tuple(tupleType, name, constructor, destructor) {
+ name = Pointer_stringify(name);
+ constructor = FUNCTION_TABLE[constructor];
+ destructor = FUNCTION_TABLE[destructor];
+
+ var elements = [];
+
+ typeRegistry[tupleType] = {
+ name: name,
+ elements: elements,
+ fromWireType: function(ptr) {
+ var len = elements.length;
+ var rv = new Array(len);
+ for (var i = 0; i < len; ++i) {
+ rv[i] = elements[i].read(ptr);
+ }
+ destructor(ptr);
+ return rv;
+ },
+ toWireType: function(destructors, o) {
+ var len = elements.length;
+ if (len !== o.length) {
+ throw new TypeError("Incorrect number of tuple elements");
+ }
+ var ptr = constructor();
+ for (var i = 0; i < len; ++i) {
+ elements[i].write(ptr, o[i]);
+ }
+ destructors.push(destructor);
+ destructors.push(ptr);
+ return ptr;
+ }
+ };
+}
+
+function copyMemberPointer(memberPointer, memberPointerSize) {
+ var copy = _malloc(memberPointerSize);
+ if (!copy) {
+ throw new Error('Failed to allocate member pointer copy');
+ }
+ _memcpy(copy, memberPointer, memberPointerSize);
+ return copy;
+}
+
+function __embind_register_tuple_element(
+ tupleType,
+ elementType,
+ getter,
+ setter,
+ memberPointerSize,
+ memberPointer
+) {
+ tupleType = requireRegisteredType(tupleType, 'tuple');
+ elementType = requireRegisteredType(elementType, "element " + tupleType.name + "[" + tupleType.elements.length + "]");
+ getter = FUNCTION_TABLE[getter];
+ setter = FUNCTION_TABLE[setter];
+ memberPointer = copyMemberPointer(memberPointer, memberPointerSize);
+
+ tupleType.elements.push({
+ read: function(ptr) {
+ return elementType.fromWireType(getter(ptr, memberPointer));
+ },
+ write: function(ptr, o) {
+ var destructors = [];
+ setter(ptr, memberPointer, elementType.toWireType(destructors, o));
+ runDestructors(destructors);
+ }
+ });
+}
+
+function __embind_register_tuple_element_accessor(
+ tupleType,
+ elementType,
+ staticGetter,
+ getterSize,
+ getter,
+ staticSetter,
+ setterSize,
+ setter
+) {
+ tupleType = requireRegisteredType(tupleType, 'tuple');
+ elementType = requireRegisteredType(elementType, "element " + tupleType.name + "[" + tupleType.elements.length + "]");
+ staticGetter = FUNCTION_TABLE[staticGetter];
+ getter = copyMemberPointer(getter, getterSize);
+ staticSetter = FUNCTION_TABLE[staticSetter];
+ setter = copyMemberPointer(setter, setterSize);
+
+ tupleType.elements.push({
+ read: function(ptr) {
+ return elementType.fromWireType(staticGetter(ptr, HEAP32[getter >> 2]));
+ },
+ write: function(ptr, o) {
+ var destructors = [];
+ staticSetter(
+ ptr,
+ HEAP32[setter >> 2],
+ elementType.toWireType(destructors, o));
+ runDestructors(destructors);
+ }
+ });
+}
+
+function __embind_register_struct(
+ structType,
+ name,
+ constructor,
+ destructor
+) {
+ name = Pointer_stringify(name);
+ constructor = FUNCTION_TABLE[constructor];
+ destructor = FUNCTION_TABLE[destructor];
+
+ typeRegistry[structType] = {
+ fields: {},
+ fromWireType: function(ptr) {
+ var fields = this.fields;
+ var rv = {};
+ for (var i in fields) {
+ rv[i] = fields[i].read(ptr);
+ }
+ destructor(ptr);
+ return rv;
+ },
+ toWireType: function(destructors, o) {
+ var fields = this.fields;
+ for (var fieldName in fields) {
+ if (!(fieldName in o)) {
+ throw new TypeError('Missing field');
+ }
+ }
+ var ptr = constructor();
+ for (var fieldName in fields) {
+ fields[fieldName].write(ptr, o[fieldName]);
+ }
+ destructors.push(destructor);
+ destructors.push(ptr);
+ return ptr;
+ }
+ };
+}
+
+function __embind_register_struct_field(
+ structType,
+ fieldName,
+ fieldType,
+ getter,
+ setter,
+ memberPointerSize,
+ memberPointer
+) {
+ structType = requireRegisteredType(structType, 'struct');
+ fieldName = Pointer_stringify(fieldName);
+ fieldType = requireRegisteredType(fieldType, 'field "' + structType.name + '.' + fieldName + '"');
+ getter = FUNCTION_TABLE[getter];
+ setter = FUNCTION_TABLE[setter];
+ memberPointer = copyMemberPointer(memberPointer, memberPointerSize);
+
+ structType.fields[fieldName] = {
+ read: function(ptr) {
+ return fieldType.fromWireType(getter(ptr, memberPointer));
+ },
+ write: function(ptr, o) {
+ var destructors = [];
+ setter(ptr, memberPointer, fieldType.toWireType(destructors, o));
+ runDestructors(destructors);
+ }
+ };
+}
+
+function __embind_register_class(
+ classType,
+ name,
+ destructor
+) {
+ name = Pointer_stringify(name);
+ destructor = FUNCTION_TABLE[destructor];
+
+ var Handle = createNamedFunction(name, function(ptr) {
+ this.count = {value: 1};
+ this.ptr = ptr;
+ });
+
+ Handle.prototype.clone = function() {
+ if (!this.ptr) {
+ throw new BindingError(classType.name + ' instance already deleted');
+ }
+
+ var clone = Object.create(Handle.prototype);
+ clone.count = this.count;
+ clone.ptr = this.ptr;
+
+ clone.count.value += 1;
+ return clone;
+ };
+
+ Handle.prototype.move = function() {
+ var rv = this.clone();
+ this.delete();
+ return rv;
+ };
+
+ Handle.prototype['delete'] = function() {
+ if (!this.ptr) {
+ throw new BindingError(classType.name + ' instance already deleted');
+ }
+
+ this.count.value -= 1;
+ if (0 === this.count.value) {
+ destructor(this.ptr);
+ }
+ this.ptr = undefined;
+ };
+
+ var constructor = createNamedFunction(name, function() {
+ var body = constructor.body;
+ body.apply(this, arguments);
+ });
+ constructor.prototype = Object.create(Handle.prototype);
+
+ typeRegistry[classType] = {
+ name: name,
+ constructor: constructor,
+ Handle: Handle,
+ fromWireType: function(ptr) {
+ return new Handle(ptr);
+ },
+ toWireType: function(destructors, o) {
+ return o.ptr;
+ }
+ };
+
+ Module[name] = constructor;
+}
+
+function __embind_register_class_constructor(
+ classType,
+ argCount,
+ argTypes,
+ constructor
+) {
+ classType = requireRegisteredType(classType, 'class');
+ var humanName = 'constructor ' + classType.name;
+ argTypes = requireArgumentTypes(argCount, argTypes, humanName);
+ constructor = FUNCTION_TABLE[constructor];
+
+ classType.constructor.body = function() {
+ if (arguments.length !== argCount) {
+ throw new BindingError('emscripten binding ' + humanName + ' called with ' + arguments.length + ' arguments, expected ' + argCount);
+ }
+ var destructors = [];
+ var args = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ args[i] = argTypes[i].toWireType(destructors, arguments[i]);
+ }
+
+ var ptr = constructor.apply(null, args);
+ runDestructors(destructors);
+ classType.Handle.call(this, ptr);
+ };
+}
+
+function __embind_register_class_method(
+ classType,
+ methodName,
+ returnType,
+ argCount,
+ argTypes,
+ invoker,
+ memberFunctionSize,
+ memberFunction
+) {
+ classType = requireRegisteredType(classType, 'class');
+ methodName = Pointer_stringify(methodName);
+ var humanName = classType.name + '.' + methodName;
+ returnType = requireRegisteredType(returnType, 'method ' + humanName + ' return value');
+ argTypes = requireArgumentTypes(argCount, argTypes, 'method ' + humanName);
+ invoker = FUNCTION_TABLE[invoker];
+ memberFunction = copyMemberPointer(memberFunction, memberFunctionSize);
+
+ classType.Handle.prototype[methodName] = function() {
+ if (!this.ptr) {
+ throw new BindingError('cannot call emscripten binding method ' + humanName + ' on deleted object');
+ }
+ if (arguments.length !== argCount) {
+ throw new BindingError('emscripten binding method ' + humanName + ' called with ' + arguments.length + ' arguments, expected ' + argCount);
+ }
+
+ var destructors = [];
+ var args = new Array(argCount + 2);
+ args[0] = this.ptr;
+ args[1] = memberFunction;
+ for (var i = 0; i < argCount; ++i) {
+ args[i + 2] = argTypes[i].toWireType(destructors, arguments[i]);
+ }
+
+ var rv = returnType.fromWireType(invoker.apply(null, args));
+ runDestructors(destructors);
+ return rv;
+ };
+}
+
+function __embind_register_class_classmethod(
+ classType,
+ methodName,
+ returnType,
+ argCount,
+ argTypes,
+ method
+) {
+ classType = requireRegisteredType(classType, 'class');
+ methodName = Pointer_stringify(methodName);
+ var humanName = classType.name + '.' + methodName;
+ returnType = requireRegisteredType(returnType, 'classmethod ' + humanName + ' return value');
+ argTypes = requireArgumentTypes(argCount, argTypes, 'classmethod ' + humanName);
+ method = FUNCTION_TABLE[method];
+
+ classType.constructor[methodName] = function() {
+ if (arguments.length !== argCount) {
+ throw new BindingError('emscripten binding method ' + humanName + ' called with ' + arguments.length + ' arguments, expected ' + argCount);
+ }
+
+ var destructors = [];
+ var args = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ args[i] = argTypes[i].toWireType(destructors, arguments[i]);
+ }
+
+ var rv = returnType.fromWireType(method.apply(null, args));
+ runDestructors(destructors);
+ return rv;
+ };
+}
+
+function __embind_register_class_field(
+ classType,
+ fieldName,
+ fieldType,
+ getter,
+ setter,
+ memberPointerSize,
+ memberPointer
+) {
+ classType = requireRegisteredType(classType, 'class');
+ fieldName = Pointer_stringify(fieldName);
+ var humanName = classType.name + '.' + fieldName;
+ fieldType = requireRegisteredType(fieldType, 'field ' + humanName);
+ getter = FUNCTION_TABLE[getter];
+ setter = FUNCTION_TABLE[setter];
+ memberPointer = copyMemberPointer(memberPointer, memberPointerSize);
+
+ Object.defineProperty(classType.Handle.prototype, fieldName, {
+ get: function() {
+ if (!this.ptr) {
+ throw new BindingError('cannot access emscripten binding field ' + humanName + ' on deleted object');
+ }
+ return fieldType.fromWireType(getter(this.ptr, memberPointer));
+ },
+ set: function(v) {
+ if (!this.ptr) {
+ throw new BindingError('cannot modify emscripten binding field ' + humanName + ' on deleted object');
+ }
+ var destructors = [];
+ setter(this.ptr, memberPointer, fieldType.toWireType(destructors, v));
+ runDestructors(destructors);
+ },
+ enumerable: true
+ });
+}
+
+function __embind_register_enum(
+ enumType,
+ name
+) {
+ name = Pointer_stringify(name);
+
+ function Enum() {
+ }
+ Enum.values = {};
+
+ typeRegistry[enumType] = {
+ name: name,
+ constructor: Enum,
+ toWireType: function(destructors, c) {
+ return c.value;
+ },
+ fromWireType: function(c) {
+ return Enum.values[c];
+ },
+ };
+
+ Module[name] = Enum;
+}
+
+function __embind_register_enum_value(
+ enumType,
+ name,
+ enumValue
+) {
+ enumType = requireRegisteredType(enumType, 'enum');
+ name = Pointer_stringify(name);
+
+ var Enum = enumType.constructor;
+
+ var Value = Object.create(enumType.constructor.prototype, {
+ value: {value: enumValue},
+ constructor: {value: createNamedFunction(enumType.name + '_' + name, function() {})},
+ });
+ Enum.values[enumValue] = Value;
+ Enum[name] = Value;
+}
+
+function __embind_register_interface(
+ interfaceType,
+ name,
+ constructor,
+ destructor
+) {
+ name = Pointer_stringify(name);
+ constructor = FUNCTION_TABLE[constructor];
+ destructor = FUNCTION_TABLE[destructor];
+
+ typeRegistry[interfaceType] = {
+ name: name,
+ toWireType: function(destructors, o) {
+ var handle = __emval_register(o);
+ var ptr = constructor(handle);
+ destructors.push(destructor);
+ destructors.push(ptr);
+ return ptr;
+ },
+ };
+}
+
diff --git a/src/embind/emval.js b/src/embind/emval.js
new file mode 100644
index 00000000..9574ab37
--- /dev/null
+++ b/src/embind/emval.js
@@ -0,0 +1,111 @@
+/*global Module*/
+/*global HEAP32*/
+/*global Pointer_stringify, writeStringToMemory*/
+/*global requireRegisteredType*/
+
+var _emval_handle_array = [];
+var _emval_free_list = [];
+
+// Public JS API
+
+/** @expose */
+Module.count_emval_handles = function() {
+ return _emval_handle_array.length;
+};
+
+// Private C++ API
+
+function __emval_register(value) {
+ var handle = _emval_free_list.length ?
+ _emval_free_list.pop() :
+ _emval_handle_array.length;
+ _emval_handle_array[handle] = {refcount: 1, value: value};
+ return handle;
+}
+
+function __emval_incref(handle) {
+ _emval_handle_array[handle].refcount += 1;
+}
+
+function __emval_decref(handle) {
+ if (0 === --_emval_handle_array[handle].refcount) {
+ delete _emval_handle_array[handle];
+ _emval_free_list.push(handle);
+
+ var actual_length = _emval_handle_array.length;
+ while (actual_length > 0 && _emval_handle_array[actual_length - 1] === undefined) {
+ --actual_length;
+ }
+ _emval_handle_array.length = actual_length;
+ }
+}
+
+function __emval_new_object() {
+ return __emval_register({});
+}
+
+function __emval_new_long(value) {
+ return __emval_register(value);
+}
+
+function __emval_new_cstring(str) {
+ return __emval_register(Pointer_stringify(str));
+}
+
+function __emval_get_property(handle, k) {
+ k = Pointer_stringify(k);
+ return __emval_register(_emval_handle_array[handle].value[k]);
+}
+
+function __emval_get_property_by_long(handle, k) {
+ return __emval_register(_emval_handle_array[handle].value[k]);
+}
+
+function __emval_get_property_by_unsigned_long(handle, k) {
+ return __emval_register(_emval_handle_array[handle].value[k]);
+}
+
+function __emval_set_property(handle, k, value) {
+ k = Pointer_stringify(k);
+ _emval_handle_array[handle].value[k] = _emval_handle_array[value].value;
+}
+
+function __emval_set_property_by_int(handle, k, value) {
+ _emval_handle_array[handle].value[k] = _emval_handle_array[value].value;
+}
+
+function __emval_as(handle, returnType) {
+ returnType = requireRegisteredType(returnType, 'emval::as');
+ var destructors = [];
+ // caller owns destructing
+ return returnType.toWireType(destructors, _emval_handle_array[handle].value);
+}
+
+function __emval_call(handle, argCount, argTypes) {
+ var args = Array.prototype.slice.call(arguments, 3);
+ var fn = _emval_handle_array[handle].value;
+ var a = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ var argType = requireRegisteredType(
+ HEAP32[(argTypes >> 2) + i],
+ "parameter " + i);
+ a[i] = argType.fromWireType(args[i]);
+ }
+ var rv = fn.apply(undefined, a);
+ return __emval_register(rv);
+}
+
+function __emval_call_method(handle, name, argCount, argTypes) {
+ name = Pointer_stringify(name);
+ var args = Array.prototype.slice.call(arguments, 4);
+ var obj = _emval_handle_array[handle].value;
+ var a = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ var argType = requireRegisteredType(
+ HEAP32[(argTypes >> 2) + i],
+ "parameter " + i);
+ a[i] = argType.fromWireType(args[i]);
+ }
+ var rv = obj[name].apply(obj, a);
+ return __emval_register(rv);
+}
diff --git a/src/jsifier.js b/src/jsifier.js
index 8021f8a1..02459193 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -358,11 +358,21 @@ function JSify(data, functionsOnly, givenFunctions) {
item.JS = 'var ' + item.ident + ';';
// Set the actual value in a postset, since it may be a global variable. We also order by dependencies there
var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value);
+ var fix = '';
+ if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
+ var target = item.ident;
+ if (isFunctionType(item.type)) {
+ target = item.value.ident; // the other side does not know this is an alias/function table index. So make it the alias target.
+ var varData = Variables.globals[target];
+ assert(!varData, 'multi-level aliasing does not work yet in shared lib 2 exports');
+ }
+ fix = '\nif (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + target + ' }'
+ }
ret.push({
intertype: 'GlobalVariablePostSet',
ident: item.ident,
dependencies: set([value]),
- JS: item.ident + ' = ' + value + ';'
+ JS: item.ident + ' = ' + value + ';' + fix
});
return ret;
}
@@ -1243,7 +1253,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// Load runtime-linked libraries
RUNTIME_LINKED_LIBS.forEach(function(lib) {
- print('eval(read("' + lib + '"))(FUNCTION_TABLE.length, this);');
+ print('eval(Module["read"]("' + lib + '"))(FUNCTION_TABLE.length, this);');
});
print(postParts[1]);
diff --git a/src/library.js b/src/library.js
index 594ba931..69642151 100644
--- a/src/library.js
+++ b/src/library.js
@@ -382,12 +382,14 @@ LibraryManager.library = {
// You can also call this with a typed array instead of a url. It will then
// do preloading for the Image/Audio part, as if the typed array were the
// result of an XHR that you did manually.
- createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror) {
+ createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) {
Browser.ensureObjects();
var fullname = FS.joinPath([parent, name], true);
function processData(byteArray) {
function finish(byteArray) {
- FS.createDataFile(parent, name, byteArray, canRead, canWrite);
+ if (!dontCreateFile) {
+ FS.createDataFile(parent, name, byteArray, canRead, canWrite);
+ }
if (onload) onload();
removeRunDependency('cp ' + fullname);
}
@@ -1286,7 +1288,7 @@ LibraryManager.library = {
return 0;
case {{{ cDefine('F_SETOWN') }}}:
case {{{ cDefine('F_GETOWN') }}}:
- // These are for sockets. We don't have them implemented (yet?).
+ // These are for sockets. We don't have them fully implemented yet.
___setErrNo(ERRNO_CODES.EINVAL);
return -1;
default:
@@ -2498,8 +2500,8 @@ LibraryManager.library = {
while ((curr < max_ || isNaN(max_)) && next > 0) {
if (!(next in __scanString.whiteSpace) && // stop on whitespace
(type == 's' ||
- ((type === 'd' || type == 'u') && ((next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
- (first && next == '-'.charCodeAt(0)))) ||
+ ((type === 'd' || type == 'u' || type == 'i') && ((next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
+ (first && next == '-'.charCodeAt(0)))) ||
(type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0)))) &&
@@ -2518,7 +2520,7 @@ LibraryManager.library = {
var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
argIndex += Runtime.getNativeFieldSize('void*');
switch (type) {
- case 'd': case 'u':
+ case 'd': case 'u': case 'i':
if (half) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
} else {
@@ -6398,14 +6400,18 @@ LibraryManager.library = {
ntohl: 'htonl',
ntohs: 'htons',
- inet_pton__deps: ['__setErrNo', '$ERRNO_CODES'],
+ inet_addr: function(ptr) {
+ var b = Pointer_stringify(ptr).split(".");
+ if (b.length !== 4) return -1; // we return -1 for error, and otherwise a uint32. this helps inet_pton differentiate
+ return (Number(b[0]) | (Number(b[1]) << 8) | (Number(b[2]) << 16) | (Number(b[3]) << 24)) >>> 0;
+ },
+
+ inet_pton__deps: ['__setErrNo', '$ERRNO_CODES', 'inet_addr'],
inet_pton: function(af, src, dst) {
// int af, const char *src, void *dst
if ((af ^ {{{ cDefine("AF_INET") }}}) !== 0) { ___setErrNo(ERRNO_CODES.EAFNOSUPPORT); return -1; }
- var b = Pointer_stringify(src).split(".");
- if (b.length !== 4) return 0;
- var ret = Number(b[0]) | (Number(b[1]) << 8) | (Number(b[2]) << 16) | (Number(b[3]) << 24);
- if (isNaN(ret)) return 0;
+ var ret = _inet_addr(src);
+ if (ret == -1 || isNaN(ret)) return 0;
setValue(dst, ret, 'i32');
return 1;
},
@@ -6423,7 +6429,62 @@ LibraryManager.library = {
},
// ==========================================================================
- // sockets
+ // netdb.h
+ // ==========================================================================
+
+ // All we can do is alias names to ips. you give this a name, it returns an
+ // "ip" that we later know to use as a name. There is no way to do actual
+ // name resolving clientside in a browser.
+ // we do the aliasing in 172.29.*.*, giving us 65536 possibilities
+ // note: lots of leaking here!
+ __hostent_struct_layout: Runtime.generateStructInfo([
+ ['i8*', 'h_name'],
+ ['i8**', 'h_aliases'],
+ ['i32', 'h_addrtype'],
+ ['i32', 'h_length'],
+ ['i8**', 'h_addr_list'],
+ ]),
+ gethostbyname__deps: ['__hostent_struct_layout'],
+ gethostbyname: function(name) {
+ name = Pointer_stringify(name);
+ if (!_gethostbyname.id) {
+ _gethostbyname.id = 1;
+ _gethostbyname.table = {};
+ }
+ var id = _gethostbyname.id++;
+ assert(id < 65535);
+ var fakeAddr = 172 | (29 << 8) | ((id & 0xff) << 16) | ((id & 0xff00) << 24);
+ _gethostbyname.table[id] = name;
+ // generate hostent
+ var ret = _malloc(___hostent_struct_layout.__size__);
+ var nameBuf = _malloc(name.length+1);
+ writeStringToMemory(name, nameBuf);
+ setValue(ret+___hostent_struct_layout.h_name, nameBuf, 'i8*');
+ var aliasesBuf = _malloc(4);
+ setValue(aliasesBuf, 0, 'i8*');
+ setValue(ret+___hostent_struct_layout.h_aliases, aliasesBuf, 'i8**');
+ setValue(ret+___hostent_struct_layout.h_addrtype, {{{ cDefine("AF_INET") }}}, 'i32');
+ setValue(ret+___hostent_struct_layout.h_length, 4, 'i32');
+ var addrListBuf = _malloc(12);
+ setValue(addrListBuf, addrListBuf+8, 'i32*');
+ setValue(addrListBuf+4, 0, 'i32*');
+ setValue(addrListBuf+8, fakeAddr, 'i32');
+ setValue(ret+___hostent_struct_layout.h_addr_list, addrListBuf, 'i8**');
+ return ret;
+ },
+
+ gethostbyname_r__deps: ['gethostbyname'],
+ gethostbyname_r: function(name, hostData, buffer, bufferSize, hostEntry, errnum) {
+ var data = _gethostbyname(name);
+ _memcpy(hostData, data, ___hostent_struct_layout.__size__);
+ _free(data);
+ setValue(errnum, 0, 'i32');
+ return 0;
+ },
+
+ // ==========================================================================
+ // sockets. Note that the implementation assumes all sockets are always
+ // nonblocking
// =============================================================