aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rwxr-xr-xemcc8
-rw-r--r--src/library.js18
-rw-r--r--src/library_browser.js1
-rw-r--r--src/library_gl.js2
-rw-r--r--src/parseTools.js10
-rw-r--r--tests/cases/funcptr.ll27
-rw-r--r--tests/cases/funcptr.txt1
-rwxr-xr-xtests/runner.py82
-rw-r--r--tests/sdl_mouse.c10
-rwxr-xr-xtools/bindings_generator.py29
-rw-r--r--tools/shared.py30
12 files changed, 185 insertions, 34 deletions
diff --git a/AUTHORS b/AUTHORS
index 1dd6039a..3d189c9f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,3 +22,4 @@ under the licensing terms detailed in LICENSE.
* Brian Anderson <banderson@mozilla.com>
* Jon Bardin <diclophis@gmail.com>
* Jukka Jylänki <jujjyl@gmail.com>
+* Aleksander Guryanov <caiiiycuk@gmail.com>
diff --git a/emcc b/emcc
index 7db1ca3b..6471f8f3 100755
--- a/emcc
+++ b/emcc
@@ -548,9 +548,11 @@ try:
settings_changes = []
for i in range(len(newargs)):
if newargs[i] == '-s':
- assert '=' in newargs[i+1], 'Incorrect syntax for -s (use -s OPT=VAL): ' + newargs[i+1]
- settings_changes.append(newargs[i+1])
- newargs[i] = newargs[i+1] = ''
+ if i+1 < len(newargs) and '=' in newargs[i+1]: # -s OPT=VALUE is for us, -s by itself is a linker option
+ settings_changes.append(newargs[i+1])
+ newargs[i] = newargs[i+1] = ''
+ else:
+ print >> sys.stderr, 'emcc: warning: treating -s as linker option and not as -s OPT=VALUE for js compilation'
elif newargs[i].startswith('--typed-arrays'):
assert '=' not in newargs[i], 'Invalid typed arrays parameter (do not use "=")'
settings_changes.append('USE_TYPED_ARRAYS=' + newargs[i+1])
diff --git a/src/library.js b/src/library.js
index f406f02a..8d68251f 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4199,6 +4199,24 @@ LibraryManager.library = {
return newStr;
},
+ strndup__deps: ['strdup'],
+ strndup: function(ptr, size) {
+ var len = String_len(ptr);
+
+ if (size >= len) {
+ return _strdup(ptr);
+ }
+
+ if (size < 0) {
+ size = 0;
+ }
+
+ var newStr = _malloc(size + 1);
+ {{{ makeCopyValues('newStr', 'ptr', 'size', 'null', null, 1) }}};
+ {{{ makeSetValue('newStr', 'size', '0', 'i8') }}};
+ return newStr;
+ },
+
strpbrk: function(ptr1, ptr2) {
var searchSet = Runtime.set.apply(null, String_copy(ptr2));
while ({{{ makeGetValue('ptr1', 0, 'i8') }}}) {
diff --git a/src/library_browser.js b/src/library_browser.js
index d49c4103..e9860742 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -77,6 +77,7 @@ mergeInto(LibraryManager.library, {
}
if (setInModule) {
Module.ctx = ctx;
+ Module.useWebGL = useWebGL;
Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
}
return ctx;
diff --git a/src/library_gl.js b/src/library_gl.js
index 3eba76d0..2be48ba1 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1517,6 +1517,8 @@ var LibraryGL = {
Module.printErr('WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports');
GL.immediate.initted = true;
+ if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case
+
this.matrixStack['m'] = [];
this.matrixStack['p'] = [];
for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
diff --git a/src/parseTools.js b/src/parseTools.js
index 81fa61d9..158e6340 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -169,7 +169,15 @@ function isFunctionDef(token, out) {
function isFunctionType(type, out) {
type = type.replace(/"[^"]+"/g, '".."');
- var parts = type.split(' ');
+ var parts;
+ // hackish, but quick splitting of function def parts. this must be fast as it happens a lot
+ if (type[0] != '[') {
+ parts = type.split(' ');
+ } else {
+ var index = type.search(']');
+ index += type.substr(index).search(' ');
+ parts = [type.substr(0, index), type.substr(index+1)];
+ }
if (pointingLevels(type) !== 1) return false;
var text = removeAllPointing(parts.slice(1).join(' '));
if (!text) return false;
diff --git a/tests/cases/funcptr.ll b/tests/cases/funcptr.ll
new file mode 100644
index 00000000..07e2bf91
--- /dev/null
+++ b/tests/cases/funcptr.ll
@@ -0,0 +1,27 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [17 x i8] c"hello %d world!\0A\00", align 1 ; [#uses=1 type=[17 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ %access_virt_barray = bitcast i32 0 to [64 x i16]* (i32*, i32)**
+ store [64 x i16]* (i32*, i32)* @access_virt_barray, [64 x i16]* (i32*, i32)** %access_virt_barray, align 4
+ %wakaptr = bitcast [64 x i16]* (i32*, i32)** %access_virt_barray to i32*
+ %waka = load i32* %wakaptr
+ %waka2 = icmp eq i32 %waka, 0
+ %waka3 = zext i1 %waka2 to i32
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str, i32 0, i32 0), i32 %waka3) ; [#uses=0 type=i32]
+ ret i32 1
+}
+
+define [64 x i16]* @access_virt_barray(i32*, i32) {
+ ret void
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/funcptr.txt b/tests/cases/funcptr.txt
new file mode 100644
index 00000000..1030830d
--- /dev/null
+++ b/tests/cases/funcptr.txt
@@ -0,0 +1 @@
+hello 0 world!
diff --git a/tests/runner.py b/tests/runner.py
index 8e2e7b28..ce19aadb 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -1393,6 +1393,48 @@ m_divisor is 1091269979
'''
self.do_run(src, '4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\n', ['wowie', 'too', '74'])
+ def test_strndup(self):
+ src = '''
+ //---------------
+ //- http://pubs.opengroup.org/onlinepubs/9699919799/functions/strndup.html
+ //---------------
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ int main(int argc, char **argv) {
+ const char* source = "strndup - duplicate a specific number of bytes from a string";
+
+ char* strdup_val = strndup(source, 0);
+ printf("1:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 7);
+ printf("2:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 1000);
+ printf("3:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 60);
+ printf("4:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 19);
+ printf("5:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, -1);
+ printf("6:%s\\n", strdup_val);
+ free(strdup_val);
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '1:\n2:strndup\n3:strndup - duplicate a specific number of bytes from a string\n4:strndup - duplicate a specific number of bytes from a string\n5:strndup - duplicate\n6:\n')
+
def test_errar(self):
src = r'''
#include <stdio.h>
@@ -5493,6 +5535,7 @@ def process(filename):
int value;
public:
Parent(int val);
+ Parent(Parent *p, Parent *q); // overload constructor
int getVal() { return value; }; // inline should work just fine here, unlike Way 1 before
void mulVal(int mul);
};
@@ -5530,6 +5573,7 @@ def process(filename):
#include "header.h"
Parent::Parent(int val) : value(val) { printf("Parent:%d\\n", val); }
+ Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value) { printf("Parent:%d\\n", value); }
void Parent::mulVal(int mul) { value *= mul; }
#include "bindingtest.cpp"
@@ -6988,6 +7032,37 @@ fscanfed: 10 - hello
output = Popen(['python', EMCONFIG, 'sys.argv[1]'], stdout=PIPE, stderr=PIPE).communicate()[0]
assert output == invalid
+ def test_link_s(self):
+ # -s OPT=VALUE can conflict with -s as a linker option. We warn and ignore
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ extern "C" {
+ void something();
+ }
+
+ int main() {
+ something();
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'supp.cpp'), 'w').write(r'''
+ #include <stdio.h>
+
+ extern "C" {
+ void something() {
+ printf("yello\n");
+ }
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'main.o']).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'supp.cpp'), '-o', 'supp.o']).communicate()
+
+ output = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.o'), '-s', os.path.join(self.get_dir(), 'supp.o'), '-s', 'SAFE_HEAP=1'], stderr=PIPE).communicate()
+ self.assertContained('emcc: warning: treating -s as linker option', output[1])
+ output = run_js('a.out.js')
+ assert 'yello' in output, 'code works'
+ code = open('a.out.js').read()
+ assert 'SAFE_HEAP' in code, 'valid -s option had an effect'
+
elif 'browser' in str(sys.argv):
# Browser tests.
@@ -8111,9 +8186,10 @@ elif 'sanity' in str(sys.argv):
assert os.path.exists(EMCC_CACHE)
assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc'))
if libname == 'libcxx':
- assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 3500000, 'libc++ is big'
- assert os.stat(basebc_name).st_size > 3500000, 'libc++ is indeed big'
- assert os.stat(dcebc_name).st_size < 2000000, 'Dead code elimination must remove most of libc++'
+ print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size
+ assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 2000000, 'libc++ is big'
+ assert os.stat(basebc_name).st_size > 2000000, 'libc++ is indeed big'
+ assert os.stat(dcebc_name).st_size < 1500000, 'Dead code elimination must remove most of libc++'
finally:
if emcc_debug:
os.environ['EMCC_DEBUG'] = emcc_debug
diff --git a/tests/sdl_mouse.c b/tests/sdl_mouse.c
index 8af87c8c..0c10198a 100644
--- a/tests/sdl_mouse.c
+++ b/tests/sdl_mouse.c
@@ -43,6 +43,8 @@ void one() {
}
}
+void main_2();
+
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
@@ -50,6 +52,12 @@ int main() {
SDL_Rect rect = { 0, 0, 600, 450 };
SDL_FillRect(screen, &rect, 0x2244ffff);
+ emscripten_async_call(main_2, 3000); // avoid startup delays and intermittent errors
+
+ return 0;
+}
+
+void main_2() {
emscripten_run_script("window.simulateMouseEvent(10, 20, -1)"); // move from 0,0 to 10,20
emscripten_run_script("window.simulateMouseEvent(10, 20, 0)"); // click
emscripten_run_script("window.simulateMouseEvent(10, 20, 0)"); // click some more, but this one should be ignored through PeepEvent
@@ -57,7 +65,5 @@ int main() {
emscripten_run_script("window.simulateMouseEvent(30, 77, 1)"); // trigger the end
emscripten_set_main_loop(one, 0);
-
- return 0;
}
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 3fbff13d..0c7c814f 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -671,25 +671,22 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
has_string_convs = False
- # We can assume that NULL is passed for null pointers, so object arguments can always
- # have .ptr done on them
- justargs_fixed = justargs(args)[:]
- for i in range(len(args)):
- arg = args[i]
- clean = clean_type(arg['type'])
- if clean in classes:
- justargs_fixed[i] += '.ptr'
- elif arg['type'].replace(' ', '').endswith('char*'):
- justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')'
- has_string_convs = True
-
calls = ''
- if has_string_convs:
- calls += 'var stack = Runtime.stackSave();\n';
- calls += 'try {\n'
#print 'js loopin', params, '|', len(args)#, args
for args in params:
+ # We can assume that NULL is passed for null pointers, so object arguments can always
+ # have .ptr done on them
+ justargs_fixed = justargs(args)[:]
+ for i in range(len(args)):
+ arg = args[i]
+ clean = clean_type(arg['type'])
+ if clean in classes:
+ justargs_fixed[i] += '.ptr'
+ elif arg['type'].replace(' ', '').endswith('char*'):
+ justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')'
+ has_string_convs = True
+
i = len(args)
if args != params[0]:
calls += ' else '
@@ -715,7 +712,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
calls += '\n'
if has_string_convs:
- calls += '} finally { Runtime.stackRestore(stack) }\n';
+ calls = 'var stack = Runtime.stackSave();\ntry {\n' + calls + '} finally { Runtime.stackRestore(stack) }\n';
print 'Maekin:', classname, generating_classname, mname, mname_suffixed
if constructor:
diff --git a/tools/shared.py b/tools/shared.py
index 30de8685..f71bec72 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -37,9 +37,10 @@ This command will now exit. When you are done editing those paths, re-run it.
''' % (EM_CONFIG, CONFIG_FILE)
sys.exit(0)
try:
- exec(open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG)
+ config_text = open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG
+ exec(config_text)
except Exception, e:
- print >> sys.stderr, 'Error in evaluating %s (at %s): %s' % (EM_CONFIG, CONFIG_FILE, str(e))
+ print >> sys.stderr, 'Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text)
sys.exit(1)
# Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM)
@@ -172,6 +173,12 @@ try:
except:
CLOSURE_COMPILER = path_from_root('third_party', 'closure-compiler', 'compiler.jar')
+try:
+ JAVA
+except:
+ print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"'
+ JAVA = 'java'
+
# Additional compiler options
try:
@@ -504,13 +511,18 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |link| call)
Building.configure(configure + configure_args, stdout=open(os.path.join(project_dir, 'configure_'), 'w'),
stderr=open(os.path.join(project_dir, 'configure_err'), 'w'), env=env)
- Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_'), 'w'),
- stderr=open(os.path.join(project_dir, 'make_err'), 'w'), env=env)
- if cache is not None:
- cache[cache_name] = []
- for f in generated_libs:
- basename = os.path.basename(f)
- cache[cache_name].append((basename, open(f, 'rb').read()))
+ for i in range(2): # workaround for some build systems that need to be run twice to succeed (e.g. poppler)
+ Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_' + str(i)), 'w'),
+ stderr=open(os.path.join(project_dir, 'make_err' + str(i)), 'w'), env=env)
+ try:
+ if cache is not None:
+ cache[cache_name] = []
+ for f in generated_libs:
+ basename = os.path.basename(f)
+ cache[cache_name].append((basename, open(f, 'rb').read()))
+ break
+ except:
+ if i > 0: raise Exception('could not build library ' + name)
if old_dir:
os.chdir(old_dir)
return generated_libs