From 0e36f078d4a9666303340506638726d316096e07 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 16:44:17 -0800 Subject: add fputwc, which enables wprintf --- emcc | 1 + src/library.js | 6 +++- system/lib/libc/musl/readme.txt | 3 ++ system/lib/libc/musl/src/internal/stdio_impl.h | 6 ++++ system/lib/libc/musl/src/stdio/fputwc.c | 39 ++++++++++++++++++++++++++ tests/core/test_wprintf.c | 15 ++++++++++ tests/core/test_wprintf.out | 8 ++++++ tests/test_core.py | 6 ++++ tools/shared.py | 2 +- 9 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 system/lib/libc/musl/src/stdio/fputwc.c create mode 100644 tests/core/test_wprintf.c create mode 100644 tests/core/test_wprintf.out diff --git a/emcc b/emcc index 4d6b8a73..8bfa0942 100755 --- a/emcc +++ b/emcc @@ -1593,6 +1593,7 @@ try: 'vswprintf.c', 'vwprintf.c', 'wprintf.c', + 'fputwc.c', ]], ['stdlib', [ 'ecvt.c', diff --git a/src/library.js b/src/library.js index c41a8cda..69569601 100644 --- a/src/library.js +++ b/src/library.js @@ -9172,6 +9172,10 @@ LibraryManager.library = { tempRet0 = 0; return (high >>> (bits - 32))|0; }, + + // misc shims for musl + __lockfile: function() { return 1 }, + __unlockfile: function(){}, }; function autoAddDeps(object, name) { @@ -9184,7 +9188,7 @@ function autoAddDeps(object, name) { } // Add aborting stubs for various libc stuff needed by libc++ -['pthread_cond_signal', 'pthread_equal', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose', 'fputwc', '__lockfile', '__unlockfile'].forEach(function(aborter) { +['pthread_cond_signal', 'pthread_equal', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose'].forEach(function(aborter) { LibraryManager.library[aborter] = function aborting_stub() { throw 'TODO: ' + aborter }; }); diff --git a/system/lib/libc/musl/readme.txt b/system/lib/libc/musl/readme.txt index 9ca04036..5e6f8389 100644 --- a/system/lib/libc/musl/readme.txt +++ b/system/lib/libc/musl/readme.txt @@ -7,3 +7,6 @@ Differences from upstream musl include: ino_t, dev_t, blkcnt_t, fsblkcnt_t, fsfilcnt_t, rlim_t. * We don't define _POSIX_SHARED_MEMORY_OBJECTS. * We flag __assert_fail as _Noreturn. +* Disable FLOCK, FUNLOCK and FFINALLOCK +* Simplify fputwc to not rely on musl stream internals + diff --git a/system/lib/libc/musl/src/internal/stdio_impl.h b/system/lib/libc/musl/src/internal/stdio_impl.h index 2083b2fe..6bcd44dc 100644 --- a/system/lib/libc/musl/src/internal/stdio_impl.h +++ b/system/lib/libc/musl/src/internal/stdio_impl.h @@ -7,9 +7,15 @@ #define UNGET 8 +#if 1 // XXX EMSCRIPTEN +#define FFINALLOCK(f) 0 +#define FLOCK(f) 0 +#define FUNLOCK(f) 0 +#else #define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0) #define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0) #define FUNLOCK(f) if (__need_unlock) __unlockfile((f)); else +#endif #define F_PERM 1 #define F_NORD 4 diff --git a/system/lib/libc/musl/src/stdio/fputwc.c b/system/lib/libc/musl/src/stdio/fputwc.c new file mode 100644 index 00000000..11db2804 --- /dev/null +++ b/system/lib/libc/musl/src/stdio/fputwc.c @@ -0,0 +1,39 @@ +#include "stdio_impl.h" +#include +#include +#include + +wint_t __fputwc_unlocked(wchar_t c, FILE *f) +{ + char mbc[MB_LEN_MAX]; + int l; + + f->mode |= f->mode+1; + + if (isascii(c)) { +#if 0 // XXX EMSCRIPTEN + c = putc_unlocked(c, f); + } else if (f->wpos + MB_LEN_MAX < f->wend) { + l = wctomb((void *)f->wpos, c); + if (l < 0) c = WEOF; + else f->wpos += l; +#else + c = fputc(c, f); +#endif + } else { + l = wctomb(mbc, c); + if (l < 0 || __fwritex((void *)mbc, l, f) < l) c = WEOF; + } + return c; +} + +wint_t fputwc(wchar_t c, FILE *f) +{ + FLOCK(f); + c = __fputwc_unlocked(c, f); + FUNLOCK(f); + return c; +} + +weak_alias(__fputwc_unlocked, fputwc_unlocked); +weak_alias(__fputwc_unlocked, putwc_unlocked); diff --git a/tests/core/test_wprintf.c b/tests/core/test_wprintf.c new file mode 100644 index 00000000..e938bf69 --- /dev/null +++ b/tests/core/test_wprintf.c @@ -0,0 +1,15 @@ +#include + +int main() +{ + wprintf (L"Characters: %lc %lc \n", L'a', 65); + wprintf (L"Decimals: %d %ld\n", 1977, 650000L); + wprintf (L"Preceding with blanks: %10d \n", 1977); + wprintf (L"Preceding with zeros: %010d \n", 1977); + wprintf (L"Some different radixes: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100); + wprintf (L"floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); + wprintf (L"Width trick: %*d \n", 5, 10); + wprintf (L"%ls \n", L"A wide string"); + return 0; +} + diff --git a/tests/core/test_wprintf.out b/tests/core/test_wprintf.out new file mode 100644 index 00000000..f85abebb --- /dev/null +++ b/tests/core/test_wprintf.out @@ -0,0 +1,8 @@ +Characters: a A +Decimals: 1977 650000 +Preceding with blanks: 1977 +Preceding with zeros: 0000001977 +Some different radixes: 100 64 144 0x64 0144 +floats: 3.14 +3e+00 3.141600E+00 +Width trick: 10 +A wide string diff --git a/tests/test_core.py b/tests/test_core.py index c89e785e..d7bebdc6 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4090,6 +4090,12 @@ def process(filename): self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.') self.do_run(open(path_from_root('tests', 'utf32.cpp')).read(), 'OK.', args=['-fshort-wchar']) + def test_wprintf(self): + if self.emcc_args is None: return self.skip('requires libcxx') + test_path = path_from_root('tests', 'core', 'test_wprintf') + src, output = (test_path + s for s in ('.c', '.out')) + self.do_run_from_file(src, output) + def test_direct_string_constant_usage(self): if self.emcc_args is None: return self.skip('requires libcxx') diff --git a/tools/shared.py b/tools/shared.py index 32f8f797..5f7e591c 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -345,7 +345,7 @@ def find_temp_directory(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.8.8' +EMSCRIPTEN_VERSION = '1.8.9' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version() -- cgit v1.2.3-18-g5258