aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS5
-rw-r--r--cmake/Platform/Emscripten.cmake61
-rwxr-xr-xemcc120
-rwxr-xr-xemscripten.py73
-rw-r--r--src/analyzer.js2766
-rw-r--r--src/compiler.js15
-rw-r--r--src/compiler_phase.html33
-rw-r--r--src/framework.js257
-rw-r--r--src/intertyper.js1850
-rw-r--r--src/jsifier.js1222
-rw-r--r--src/library.js158
-rw-r--r--src/library_fs.js72
-rw-r--r--src/library_gl.js168
-rw-r--r--src/library_idbfs.js216
-rw-r--r--src/library_memfs.js26
-rw-r--r--src/library_nodefs.js234
-rw-r--r--src/library_sdl.js280
-rw-r--r--src/library_sockfs.js12
-rw-r--r--src/modules.js6
-rw-r--r--src/parseTools.js211
-rw-r--r--src/postamble.js3
-rw-r--r--src/preamble.js25
-rw-r--r--src/relooper/Relooper.cpp2
-rw-r--r--src/relooper/emscripten/glue.js11
-rw-r--r--src/runtime.js41
-rw-r--r--src/settings.js3
-rw-r--r--src/utility.js11
-rw-r--r--system/include/libc/assert.h2
-rw-r--r--system/lib/libc/musl/readme.txt1
-rw-r--r--system/lib/libc/musl/src/internal/locale_impl.h5
-rw-r--r--system/lib/libc/musl/src/internal/stdio_impl.h92
-rw-r--r--system/lib/libc/musl/src/locale/big5.h1085
-rw-r--r--system/lib/libc/musl/src/locale/codepages.h238
-rw-r--r--system/lib/libc/musl/src/locale/gb18030.h1836
-rw-r--r--system/lib/libc/musl/src/locale/hkscs.h390
-rw-r--r--system/lib/libc/musl/src/locale/iconv.c454
-rw-r--r--system/lib/libc/musl/src/locale/iswalnum_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswalpha_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswblank_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswcntrl_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswctype_l.c9
-rw-r--r--system/lib/libc/musl/src/locale/iswdigit_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswgraph_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswlower_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswprint_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswpunct_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswspace_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswupper_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iswxdigit_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/jis0208.h550
-rw-r--r--system/lib/libc/musl/src/locale/ksc.h640
-rw-r--r--system/lib/libc/musl/src/locale/legacychars.h39
-rw-r--r--system/lib/libc/musl/src/locale/strfmon.c101
-rw-r--r--system/lib/libc/musl/src/locale/strxfrm.c18
-rw-r--r--system/lib/libc/musl/src/locale/towctrans_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/towlower_l.c9
-rw-r--r--system/lib/libc/musl/src/locale/towupper_l.c9
-rw-r--r--system/lib/libc/musl/src/locale/wcscoll.c16
-rw-r--r--system/lib/libc/musl/src/locale/wcscoll_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/wcsxfrm.c21
-rw-r--r--system/lib/libc/musl/src/locale/wcsxfrm_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/wctrans_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/wctype_l.c9
-rw-r--r--system/lib/libc/musl/src/stdio/fwprintf.c13
-rw-r--r--system/lib/libc/musl/src/stdio/swprintf.c14
-rw-r--r--system/lib/libc/musl/src/stdio/vfwprintf.c361
-rw-r--r--system/lib/libc/musl/src/stdio/vswprintf.c53
-rw-r--r--system/lib/libc/musl/src/stdio/vwprintf.c7
-rw-r--r--system/lib/libc/musl/src/stdio/wprintf.c13
-rw-r--r--system/lib/libcextra.symbols44
-rw-r--r--tests/cases/atomicrmw_unaligned.emcc1
-rw-r--r--tests/cases/atomicrmw_unaligned.ll21
-rw-r--r--tests/cases/atomicrmw_unaligned.txt1
-rw-r--r--tests/cmake/target_js/CMakeLists.txt26
-rw-r--r--tests/cmake/target_js/jslibrary.js7
-rw-r--r--tests/cmake/target_js/jslibrary2.js7
-rw-r--r--tests/cmake/target_js/main.cpp10
-rw-r--r--tests/cmake/target_js/out.txt4
-rw-r--r--tests/cmake/target_js/postjs.js1
-rw-r--r--tests/cmake/target_js/prejs.js1
-rw-r--r--tests/fs/test_idbfs_sync.c48
-rw-r--r--tests/fs/test_nodefs_rw.c49
-rw-r--r--tests/printf/output.txt11
-rw-r--r--tests/printf/output_i64_1.txt11
-rw-r--r--tests/printf/test.c11
-rw-r--r--tests/sdl_audio_beep.cpp246
-rw-r--r--tests/sdl_canvas_alpha.c46
-rw-r--r--tests/sdl_canvas_alpha.pngbin0 -> 169826 bytes
-rw-r--r--tests/test_browser.py20
-rw-r--r--tests/test_core.py149
-rw-r--r--tests/test_other.py10
-rw-r--r--tests/unistd/access.c17
-rw-r--r--tests/unistd/access.out40
-rw-r--r--tests/unistd/io.c19
-rw-r--r--tests/unistd/io.out4
-rw-r--r--tests/unistd/links.c21
-rw-r--r--tests/unistd/links.out6
-rw-r--r--tests/unistd/misc.c24
-rw-r--r--tests/unistd/truncate.c23
-rw-r--r--tests/unistd/unlink.c12
-rw-r--r--tools/js_optimizer.py13
-rw-r--r--tools/jsrun.py18
-rw-r--r--tools/shared.py25
-rw-r--r--tools/tempfiles.py1
104 files changed, 11293 insertions, 3616 deletions
diff --git a/AUTHORS b/AUTHORS
index 23325a7d..d8f9da02 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,4 @@
-The following authors have all licensed their contributions to Emscripten
+The following authors have all licensed their contributions to Emscripten
under the licensing terms detailed in LICENSE.
(Authors keep copyright of their contributions, of course; they just grant
@@ -97,3 +97,6 @@ a license to everyone to use it as detailed in LICENSE.)
* Charlie Birks <admin@daftgames.net>
* Ranger Harke <ranger.harke@autodesk.com> (copyright owned by Autodesk, Inc.)
* Tobias Vrinssen <tobias@vrinssen.de>
+* Patrick R. Martin <patrick.martin.r@gmail.com>
+* Richard Quirk <richard.quirk@gmail.com>
+
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake
index ec3f5383..7c8e83fa 100644
--- a/cmake/Platform/Emscripten.cmake
+++ b/cmake/Platform/Emscripten.cmake
@@ -104,8 +104,8 @@ set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
# Specify the program to use when building static libraries. Force Emscripten-related command line options to clang.
-set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_CXX_COMPILER} ${CMAKE_START_TEMP_FILE} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
-set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_C_COMPILER} ${CMAKE_START_TEMP_FILE} -o <TARGET> -emit-llvm <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
+set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_AR} rc <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
+set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_AR} rc <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
# Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten.
# There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1".
@@ -139,3 +139,60 @@ set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-over
function(em_validate_asmjs_after_build target)
add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo Validating build output for asm.js... COMMAND "python" ARGS "${EMSCRIPTEN_ROOT_PATH}/tools/validate_asmjs.py" "$<TARGET_FILE:${target}>")
endfunction()
+
+# A global counter to guarantee unique names for js library files.
+set(link_js_counter 1)
+
+# Internal function: Do not call from user CMakeLists.txt files. Use one of em_link_js_library()/em_link_pre_js()/em_link_post_js() instead.
+function(em_add_tracked_link_flag target flagname)
+ get_target_property(props ${target} LINK_FLAGS)
+ # User can input list of JS files either as a single list, or as variable arguments to this function, so iterate over varargs, and treat each
+ # item in varargs as a list itself, to support both syntax forms.
+ foreach(jsFileList ${ARGN})
+ foreach(jsfile ${jsFileList})
+ # Add link command to the given JS file.
+ set(props "${props} ${flagname} \"${jsfile}\"")
+
+ # If the user edits the JS file, we want to relink the emscripten application, but unfortunately it is not possible to make a link step
+ # depend directly on a source file. Instead, we must make a dummy no-op build target on that source file, and make the project depend on
+ # that target.
+
+ # Sanitate the source .js filename to a good symbol name to use as a dummy filename.
+ get_filename_component(jsname "${jsfile}" NAME)
+ string(REGEX REPLACE "[/:\\\\.\ ]" "_" dummy_js_target ${jsname})
+ set(dummy_lib_name ${target}_${link_js_counter}_${dummy_js_target})
+ set(dummy_c_name "${CMAKE_BINARY_DIR}/${dummy_js_target}_tracker.c")
+
+ # Create a new static library target that with a single dummy .c file.
+ add_library(${dummy_lib_name} STATIC ${dummy_c_name})
+ # Make the dummy .c file depend on the .js file we are linking, so that if the .js file is edited, the dummy .c file, and hence the static library will be rebuild (no-op). This causes the main application to be relinked, which is what we want.
+ # This approach was recommended by http://www.cmake.org/pipermail/cmake/2010-May/037206.html
+ add_custom_command(OUTPUT ${dummy_c_name} COMMAND ${CMAKE_COMMAND} -E touch ${dummy_c_name} DEPENDS ${jsfile})
+ target_link_libraries(${target} ${dummy_lib_name})
+
+ math(EXPR link_js_counter "${link_js_counter} + 1")
+ endforeach()
+ endforeach()
+ set_target_properties(${target} PROPERTIES LINK_FLAGS "${props}")
+endfunction()
+
+# This function links a (list of ) .js library file(s) to the given CMake project.
+# Example: em_link_js_library(my_executable "lib1.js" "lib2.js")
+# will result in emcc passing --js-library lib1.js --js-library lib2.js to the emscripten linker, as well as
+# tracking the modification timestamp between the linked .js files and the main project, so that editing the .js file
+# will cause the target project to be relinked.
+function(em_link_js_library target)
+ em_add_tracked_link_flag(${target} "--js-library" ${ARGN})
+endfunction()
+
+# This function is identical to em_link_js_library(), except the .js files will be added with '--pre-js file.js' command line flag,
+# which is generally used to add some preamble .js code to a generated output file.
+function(em_link_pre_js target)
+ em_add_tracked_link_flag(${target} "--pre-js" ${ARGN})
+endfunction()
+
+# This function is identical to em_link_js_library(), except the .js files will be added with '--post-js file.js' command line flag,
+# which is generally used to add some postamble .js code to a generated output file.
+function(em_link_post_js target)
+ em_add_tracked_link_flag(${target} "--post-js" ${ARGN})
+endfunction()
diff --git a/emcc b/emcc
index 9a687bd8..c528fb9e 100755
--- a/emcc
+++ b/emcc
@@ -238,6 +238,9 @@ Options that are modified or new in %s include:
(see --llvm-opts), setting this has no
effect.
+ Note that LLVM LTO is not perfectly stable yet,
+ and can can cause code to behave incorrectly.
+
--closure <on> 0: No closure compiler (default in -O2 and below)
1: Run closure compiler. This greatly reduces
code size and may in some cases increase
@@ -717,6 +720,13 @@ else:
def in_temp(name):
return os.path.join(temp_dir, os.path.basename(name))
+# Parses the essential suffix of a filename, discarding Unix-style version numbers in the name. For example for 'libz.so.1.2.8' returns '.so'
+def filename_type_suffix(filename):
+ for i in reversed(filename.split('.')[1:]):
+ if not i.isdigit():
+ return '.' + i
+ return ''
+
try:
call = CXX if use_cxx else CC
@@ -971,35 +981,45 @@ try:
if i > 0:
prev = newargs[i-1]
- if prev in ['-MT', '-MF', '-MQ', '-D', '-U', '-o', '-x', '-Xpreprocessor', '-include', '-imacros', '-idirafter', '-iprefix', '-iwithprefix', '-iwithprefixbefore', '-isysroot', '-imultilib', '-A', '-isystem', '-iquote', '-install_name', '-I', '-L']: continue # ignore this gcc-style argument
+ if prev in ['-MT', '-MF', '-MQ', '-D', '-U', '-o', '-x', '-Xpreprocessor', '-include', '-imacros', '-idirafter', '-iprefix', '-iwithprefix', '-iwithprefixbefore', '-isysroot', '-imultilib', '-A', '-isystem', '-iquote', '-install_name', '-compatibility_version', '-current_version', '-I', '-L']: continue # ignore this gcc-style argument
if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)):
arg = os.path.realpath(arg)
- if not arg.startswith('-') and (arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg)): # we already removed -o <target>, so all these should be inputs
- newargs[i] = ''
- if os.path.exists(arg):
- if arg.endswith(SOURCE_SUFFIXES):
+ if not arg.startswith('-'):
+ if not os.path.exists(arg):
+ logging.error(arg + ': No such file or directory')
+ exit(1)
+
+ arg_suffix = filename_type_suffix(arg)
+ if arg_suffix.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
+ newargs[i] = ''
+ if arg_suffix.endswith(SOURCE_SUFFIXES):
input_files.append(arg)
has_source_inputs = True
+ elif arg_suffix.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid
+ input_files.append(arg)
+ elif arg_suffix.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES):
+ # if it's not, and it's a library, just add it to libs to find later
+ l = unsuffixed_basename(arg)
+ for prefix in LIB_PREFIXES:
+ if not prefix: continue
+ if l.startswith(prefix):
+ l = l[len(prefix):]
+ break
+ libs.append(l)
+ newargs[i] = ''
else:
- # this should be bitcode, make sure it is valid
- if arg.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg):
- input_files.append(arg)
- elif arg.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES):
- # if it's not, and it's a library, just add it to libs to find later
- l = unsuffixed_basename(arg)
- for prefix in LIB_PREFIXES:
- if not prefix: continue
- if l.startswith(prefix):
- l = l[len(prefix):]
- break
- libs.append(l)
- newargs[i] = ''
+ logging.warning(arg + ' is not valid LLVM bitcode')
+ elif arg_suffix.endswith(STATICLIB_SUFFIXES):
+ if not shared.Building.is_ar(arg):
+ if shared.Building.is_bitcode(arg):
+ logging.error(arg + ': File has a suffix of a static library ' + str(STATICLIB_SUFFIXES) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_SUFFIXES))
else:
- logging.warning(arg + ' is not valid LLVM bitcode')
+ logging.error(arg + ': Unknown format, not a static library!')
+ exit(1)
else:
- logging.error(arg + ': No such file or directory')
+ logging.error(arg + ": Input file has an unknown suffix, don't know what to do with it!")
exit(1)
elif arg.startswith('-L'):
lib_dirs.append(arg[2:])
@@ -1148,13 +1168,14 @@ try:
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
- if input_file.endswith(SOURCE_SUFFIXES):
+ file_suffix = filename_type_suffix(input_file)
+ if file_suffix.endswith(SOURCE_SUFFIXES):
logging.debug('compiling source file: ' + input_file)
input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file)))
output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
- if input_file.endswith(CXX_SUFFIXES):
+ if file_suffix.endswith(CXX_SUFFIXES):
args += shared.EMSDK_CXX_OPTS
logging.debug("running: " + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
@@ -1162,17 +1183,17 @@ try:
logging.error('compiler frontend failed to generate LLVM bitcode, halting')
sys.exit(1)
else: # bitcode
- if input_file.endswith(BITCODE_SUFFIXES):
+ if file_suffix.endswith(BITCODE_SUFFIXES):
logging.debug('copying bitcode file: ' + input_file)
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
- elif input_file.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file):
+ elif file_suffix.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file):
logging.debug('copying library file: ' + input_file)
temp_file = in_temp(uniquename(input_file))
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
- else: #.ll
+ elif file_suffix.endswith(ASSEMBLY_SUFFIXES):
if not LEAVE_INPUTS_RAW:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
@@ -1180,6 +1201,9 @@ try:
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shared.Building.llvm_as(input_file, temp_file)
temp_files.append(temp_file)
+ else:
+ logging.error(input_file + ': Unknown file suffix when compiling to LLVM bitcode!')
+ sys.exit(1)
if not LEAVE_INPUTS_RAW:
assert len(temp_files) == len(input_files)
@@ -1187,7 +1211,8 @@ try:
# Optimize source files
if llvm_opts > 0:
for i, input_file in enumerate(input_files):
- if input_file.endswith(SOURCE_SUFFIXES):
+ file_suffix = filename_type_suffix(input_file)
+ if file_suffix.endswith(SOURCE_SUFFIXES):
temp_file = temp_files[i]
logging.debug('optimizing %s with -O%d' % (input_file, llvm_opts))
shared.Building.llvm_opt(temp_file, llvm_opts)
@@ -1279,6 +1304,10 @@ try:
os.path.join('libc', 'gen', 'vwarnx.c'),
os.path.join('libc', 'stdlib', 'strtod.c'),
]
+ musl_files = [
+ ]
+ for directory, sources in musl_files:
+ libc_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
return build_libc('libc.bc', libc_files)
def apply_libc(need):
@@ -1316,6 +1345,33 @@ try:
'wctrans.c',
'wcwidth.c',
]],
+ ['locale', [
+ 'iconv.c',
+ 'iswalnum_l.c',
+ 'iswalpha_l.c',
+ 'iswblank_l.c',
+ 'iswcntrl_l.c',
+ 'iswctype_l.c',
+ 'iswdigit_l.c',
+ 'iswgraph_l.c',
+ 'iswlower_l.c',
+ 'iswprint_l.c',
+ 'iswpunct_l.c',
+ 'iswspace_l.c',
+ 'iswupper_l.c',
+ 'iswxdigit_l.c',
+ 'strfmon.c',
+ 'strxfrm.c',
+ 'towctrans_l.c',
+ 'towlower_l.c',
+ 'towupper_l.c',
+ 'wcscoll.c',
+ 'wcscoll_l.c',
+ 'wcsxfrm.c',
+ 'wcsxfrm_l.c',
+ 'wctrans_l.c',
+ 'wctype_l.c',
+ ]],
['multibyte', [
'btowc.c',
'mblen.c',
@@ -1333,6 +1389,14 @@ try:
'wctob.c',
'wctomb.c',
]],
+ ['stdio', [
+ 'fwprintf.c',
+ 'swprintf.c',
+ 'vfwprintf.c',
+ 'vswprintf.c',
+ 'vwprintf.c',
+ 'wprintf.c',
+ ]],
['stdlib', [
'ecvt.c',
'fcvt.c',
@@ -1342,7 +1406,7 @@ try:
'wcpcpy.c',
'wcpncpy.c',
'wcscasecmp.c',
- # 'wcscasecmp_l.c', # XXX: alltypes.h issue
+ 'wcscasecmp_l.c',
'wcscat.c',
'wcschr.c',
'wcscmp.c',
@@ -1351,7 +1415,7 @@ try:
'wcsdup.c',
'wcslen.c',
'wcsncasecmp.c',
- # 'wcsncasecmp_l.c', # XXX: alltypes.h issue
+ 'wcsncasecmp_l.c',
'wcsncat.c',
'wcsncmp.c',
'wcsncpy.c',
diff --git a/emscripten.py b/emscripten.py
index e6a6e124..b70f2abb 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -9,7 +9,7 @@ header files (so that the JS compiler can see the constants in those
headers, for the libc implementation in JS).
'''
-import os, sys, json, optparse, subprocess, re, time, multiprocessing, string
+import os, sys, json, optparse, subprocess, re, time, multiprocessing, string, logging
from tools import jsrun, cache as cache_module, tempfiles
from tools.response_file import read_response_file
@@ -39,14 +39,14 @@ def scan(ll, settings):
if len(blockaddrs) > 0:
settings['NECESSARY_BLOCKADDRS'] = blockaddrs
-NUM_CHUNKS_PER_CORE = 1.25
+NUM_CHUNKS_PER_CORE = 1.0
MIN_CHUNK_SIZE = 1024*1024
MAX_CHUNK_SIZE = float(os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or 'inf') # configuring this is just for debugging purposes
STDERR_FILE = os.environ.get('EMCC_STDERR_FILE')
if STDERR_FILE:
STDERR_FILE = os.path.abspath(STDERR_FILE)
- print >> sys.stderr, 'logging stderr in js compiler phase into %s' % STDERR_FILE
+ logging.info('logging stderr in js compiler phase into %s' % STDERR_FILE)
STDERR_FILE = open(STDERR_FILE, 'w')
def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG)):
@@ -58,6 +58,8 @@ def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libr
f.write('\n')
f.write(meta)
f.close()
+ #print >> sys.stderr, 'running', str([settings_file, funcs_file, 'funcs', forwarded_file] + libraries).replace("'/", "'") # can use this in src/compiler_funcs.html arguments,
+ # # just copy temp dir to under this one
out = jsrun.run_js(
compiler,
engine=compiler_engine,
@@ -68,9 +70,7 @@ def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libr
except KeyboardInterrupt:
# Python 2.7 seems to lock up when a child process throws KeyboardInterrupt
raise Exception()
- finally:
- tempfiles.try_delete(funcs_file)
- if DEBUG: print >> sys.stderr, '.'
+ if DEBUG: logging.debug('.')
return out
def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
@@ -91,7 +91,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
# 2 aka 'funcs': Process functions. We can parallelize this, working on each function independently.
# 3 aka 'post' : Process globals, generate postamble and finishing touches.
- if DEBUG: print >> sys.stderr, 'emscript: ll=>js'
+ if DEBUG: logging.debug('emscript: ll=>js')
if jcache: jcache.ensure()
@@ -101,7 +101,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
scan(ll, settings)
total_ll_size = len(ll)
ll = None # allow collection
- if DEBUG: print >> sys.stderr, ' emscript: scan took %s seconds' % (time.time() - t)
+ if DEBUG: logging.debug(' emscript: scan took %s seconds' % (time.time() - t))
# Split input into the relevant parts for each phase
pre = []
@@ -136,19 +136,19 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
pre.append(line) # pre needs it so we know about globals in pre and funcs. So emit globals there
ll_lines = None
meta = ''.join(meta)
- if DEBUG and len(meta) > 1024*1024: print >> sys.stderr, 'emscript warning: large amounts of metadata, will slow things down'
- if DEBUG: print >> sys.stderr, ' emscript: split took %s seconds' % (time.time() - t)
+ if DEBUG and len(meta) > 1024*1024: logging.debug('emscript warning: large amounts of metadata, will slow things down')
+ if DEBUG: logging.debug(' emscript: split took %s seconds' % (time.time() - t))
if len(funcs) == 0:
- print >> sys.stderr, 'No functions to process. Make sure you prevented LLVM from eliminating them as dead (use EXPORTED_FUNCTIONS if necessary, see the FAQ)'
+ logging.error('No functions to process. Make sure you prevented LLVM from eliminating them as dead (use EXPORTED_FUNCTIONS if necessary, see the FAQ)')
#if DEBUG:
- # print >> sys.stderr, '========= pre ================\n'
- # print >> sys.stderr, ''.join(pre)
- # print >> sys.stderr, '========== funcs ===============\n'
+ # logging.debug('========= pre ================\n')
+ # logging.debug(''.join(pre))
+ # logging.debug('========== funcs ===============\n')
# for func in funcs:
- # print >> sys.stderr, '\n// ===\n\n', ''.join(func)
- # print >> sys.stderr, '=========================\n'
+ # logging.debug('\n// ===\n\n', ''.join(func))
+ # logging.debug('=========================\n')
# Save settings to a file to work around v8 issue 1579
settings_file = temp_files.get('.txt').name
@@ -168,7 +168,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if jcache:
keys = [pre_input, settings_text, ','.join(libraries)]
shortkey = jcache.get_shortkey(keys)
- if DEBUG_CACHE: print >>sys.stderr, 'shortkey', shortkey
+ if DEBUG_CACHE: logging.debug('shortkey', shortkey)
out = jcache.get(shortkey, keys)
@@ -181,21 +181,22 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
dfp.write("\n\n========================== libraries\n\n")
dfp.write("\n".join(libraries))
dfp.close()
- print >>sys.stderr, ' cache miss, key data dumped to %s' % dfpath
+ logging.debug(' cache miss, key data dumped to %s' % dfpath)
- if out and DEBUG: print >> sys.stderr, ' loading pre from jcache'
+ if out and DEBUG: logging.debug(' loading pre from jcache')
if not out:
open(pre_file, 'w').write(pre_input)
+ #print >> sys.stderr, 'running', str([settings_file, pre_file, 'pre'] + libraries).replace("'/", "'") # see funcs
out = jsrun.run_js(compiler, compiler_engine, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE, stderr=STDERR_FILE,
cwd=path_from_root('src'))
assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?'
if jcache:
- if DEBUG: print >> sys.stderr, ' saving pre to jcache'
+ if DEBUG: logging.debug(' saving pre to jcache')
jcache.set(shortkey, keys, out)
pre, forwarded_data = out.split('//FORWARDED_DATA:')
forwarded_file = temp_files.get('.json').name
open(forwarded_file, 'w').write(forwarded_data)
- if DEBUG: print >> sys.stderr, ' emscript: phase 1 took %s seconds' % (time.time() - t)
+ if DEBUG: logging.debug(' emscript: phase 1 took %s seconds' % (time.time() - t))
indexed_functions = set()
forwarded_json = json.loads(forwarded_data)
@@ -209,7 +210,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if cores > 1:
intended_num_chunks = int(round(cores * NUM_CHUNKS_PER_CORE))
chunk_size = max(MIN_CHUNK_SIZE, total_ll_size / intended_num_chunks)
- chunk_size += 3*len(meta) + len(forwarded_data)/3 # keep ratio of lots of function code to meta (expensive to process, and done in each parallel task) and forwarded data (less expensive but potentially significant)
+ chunk_size += 3*len(meta) # keep ratio of lots of function code to meta (expensive to process, and done in each parallel task)
chunk_size = min(MAX_CHUNK_SIZE, chunk_size)
else:
chunk_size = MAX_CHUNK_SIZE # if 1 core, just use the max chunk size
@@ -223,6 +224,9 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
funcs, chunk_size,
jcache.get_cachename('emscript_files') if jcache else None)
+ #sys.exit(1)
+ #chunks = [chunks[0]] # pick specific chunks for debugging/profiling
+
funcs = None
if jcache:
@@ -238,7 +242,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
return True
chunks = filter(load_from_cache, chunks)
if len(cached_outputs) > 0:
- if out and DEBUG: print >> sys.stderr, ' loading %d funcchunks from jcache' % len(cached_outputs)
+ if out and DEBUG: logging.debug(' loading %d funcchunks from jcache' % len(cached_outputs))
else:
cached_outputs = []
@@ -248,10 +252,11 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if cores == 1 and total_ll_size < MAX_CHUNK_SIZE:
assert len(chunks) == 1, 'no point in splitting up without multiple cores'
- if DEBUG: print >> sys.stderr, ' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.))
+ if DEBUG: logging.debug(' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.)))
commands = [
- (i, chunk, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG)
+ (i, chunk, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine,# + ['--prof'],
+ temp_files, DEBUG)
for i, chunk in enumerate(chunks)
]
@@ -273,7 +278,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
keys = [settings_text, forwarded_data, chunk]
shortkey = jcache.get_shortkey(keys)
jcache.set(shortkey, keys, outputs[i])
- if out and DEBUG and len(chunks) > 0: print >> sys.stderr, ' saving %d funcchunks to jcache' % len(chunks)
+ if out and DEBUG and len(chunks) > 0: logging.debug(' saving %d funcchunks to jcache' % len(chunks))
chunks = None
@@ -283,7 +288,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
for output in outputs:
assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0][-3000:]
- if DEBUG: print >> sys.stderr, ' emscript: phase 2 took %s seconds' % (time.time() - t)
+ if DEBUG: logging.debug(' emscript: phase 2 took %s seconds' % (time.time() - t))
if DEBUG: t = time.time()
# merge forwarded data
@@ -319,7 +324,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
funcs_js = [output[0] for output in outputs]
outputs = None
- if DEBUG: print >> sys.stderr, ' emscript: phase 2b took %s seconds' % (time.time() - t)
+ if DEBUG: logging.debug(' emscript: phase 2b took %s seconds' % (time.time() - t))
if DEBUG: t = time.time()
# calculations on merged forwarded data
@@ -340,7 +345,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
else:
curr = i
i += 2
- #print >> sys.stderr, 'function indexing', indexed, curr, sig
+ #logging.debug('function indexing', indexed, curr, sig)
forwarded_json['Functions']['indexedFunctions'][indexed] = curr # make sure not to modify this python object later - we use it in indexize
def split_32(x):
@@ -378,7 +383,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
forwarded_data = json.dumps(forwarded_json)
forwarded_file = temp_files.get('.2.json').name
open(forwarded_file, 'w').write(indexize(forwarded_data))
- if DEBUG: print >> sys.stderr, ' emscript: phase 2c took %s seconds' % (time.time() - t)
+ if DEBUG: logging.debug(' emscript: phase 2c took %s seconds' % (time.time() - t))
# Phase 3 - post
if DEBUG: t = time.time()
@@ -539,7 +544,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
# finalize
- if DEBUG: print >> sys.stderr, 'asm text sizes', map(len, funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)
+ if DEBUG: logging.debug('asm text sizes' + str([map(len, funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)]))
funcs_js = ['''
%s
@@ -687,7 +692,7 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
funcs_js = None
outfile.write(indexize(post))
- if DEBUG: print >> sys.stderr, ' emscript: phase 3 took %s seconds' % (time.time() - t)
+ if DEBUG: logging.debug(' emscript: phase 3 took %s seconds' % (time.time() - t))
outfile.close()
@@ -786,11 +791,11 @@ def _main(environ):
keywords, positional = parser.parse_args()
if not keywords.suppressUsageWarning:
- print >> sys.stderr, '''
+ logging.warning('''
==============================================================
WARNING: You should normally never use this! Use emcc instead.
==============================================================
- '''
+ ''')
if len(positional) != 1:
raise RuntimeError('Must provide exactly one positional argument. Got ' + str(len(positional)) + ': "' + '", "'.join(positional) + '"')
diff --git a/src/analyzer.js b/src/analyzer.js
index b20dedff..3fb20253 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -27,82 +27,72 @@ var SHADOW_FLIP = { i64: 'double', double: 'i64' }; //, i32: 'float', float: 'i3
function analyzer(data, sidePass) {
var mainPass = !sidePass;
- // Substrate
- var substrate = new Substrate('Analyzer');
-
- // Sorter
- substrate.addActor('Sorter', {
- processItem: function(item) {
- item.items.sort(function (a, b) { return a.lineNum - b.lineNum });
- this.forwardItem(item, 'Gatherer');
+ var item = { items: data };
+ var data = item;
+
+ var newTypes = {};
+
+ // Gather
+ // Single-liners
+ ['globalVariable', 'functionStub', 'unparsedFunction', 'unparsedGlobals', 'unparsedTypes', 'alias'].forEach(function(intertype) {
+ var temp = splitter(item.items, function(item) { return item.intertype == intertype });
+ item.items = temp.leftIn;
+ item[intertype + 's'] = temp.splitOut;
+ });
+ var temp = splitter(item.items, function(item) { return item.intertype == 'type' });
+ item.items = temp.leftIn;
+ temp.splitOut.forEach(function(type) {
+ //dprint('types', 'adding defined type: ' + type.name_);
+ Types.types[type.name_] = type;
+ newTypes[type.name_] = 1;
+ if (QUANTUM_SIZE === 1) {
+ Types.fatTypes[type.name_] = copy(type);
}
});
- // Gatherer
- substrate.addActor('Gatherer', {
- processItem: function(item) {
- // Single-liners
- ['globalVariable', 'functionStub', 'unparsedFunction', 'unparsedGlobals', 'unparsedTypes', 'alias'].forEach(function(intertype) {
- var temp = splitter(item.items, function(item) { return item.intertype == intertype });
- item.items = temp.leftIn;
- item[intertype + 's'] = temp.splitOut;
- });
- var temp = splitter(item.items, function(item) { return item.intertype == 'type' });
- item.items = temp.leftIn;
- temp.splitOut.forEach(function(type) {
- //dprint('types', 'adding defined type: ' + type.name_);
- Types.types[type.name_] = type;
- if (QUANTUM_SIZE === 1) {
- Types.fatTypes[type.name_] = copy(type);
- }
- });
-
- // Functions & labels
- item.functions = [];
- var currLabelFinished; // Sometimes LLVM puts a branch in the middle of a label. We need to ignore all lines after that.
- item.items.sort(function(a, b) { return a.lineNum - b.lineNum });
- for (var i = 0; i < item.items.length; i++) {
- var subItem = item.items[i];
- assert(subItem.lineNum);
- if (subItem.intertype == 'function') {
- item.functions.push(subItem);
- subItem.endLineNum = null;
- subItem.lines = []; // We will fill in the function lines after the legalizer, since it can modify them
- subItem.labels = [];
- subItem.forceEmulated = false;
-
- // no explicit 'entry' label in clang on LLVM 2.8 - most of the time, but not all the time! - so we add one if necessary
- if (item.items[i+1].intertype !== 'label') {
- item.items.splice(i+1, 0, {
- intertype: 'label',
- ident: ENTRY_IDENT,
- lineNum: subItem.lineNum + '.5'
- });
- }
- } else if (subItem.intertype == 'functionEnd') {
- item.functions.slice(-1)[0].endLineNum = subItem.lineNum;
- } else if (subItem.intertype == 'label') {
- item.functions.slice(-1)[0].labels.push(subItem);
- subItem.lines = [];
- currLabelFinished = false;
- } else if (item.functions.length > 0 && item.functions.slice(-1)[0].endLineNum === null) {
- // Internal line
- if (!currLabelFinished) {
- item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem); // If this line fails, perhaps missing a label?
- if (subItem.intertype in LABEL_ENDERS) {
- currLabelFinished = true;
- }
- } else {
- print('// WARNING: content after a branch in a label, line: ' + subItem.lineNum);
- }
- } else {
- throw 'ERROR: what is this? ' + dump(subItem);
+ // Functions & labels
+ item.functions = [];
+ var currLabelFinished = false; // Sometimes LLVM puts a branch in the middle of a label. We need to ignore all lines after that.
+ item.items.sort(function(a, b) { return a.lineNum - b.lineNum });
+ for (var i = 0; i < item.items.length; i++) {
+ var subItem = item.items[i];
+ assert(subItem.lineNum);
+ if (subItem.intertype == 'function') {
+ item.functions.push(subItem);
+ subItem.endLineNum = null;
+ subItem.lines = []; // We will fill in the function lines after the legalizer, since it can modify them
+ subItem.labels = [];
+ subItem.forceEmulated = false;
+
+ // no explicit 'entry' label in clang on LLVM 2.8 - most of the time, but not all the time! - so we add one if necessary
+ if (item.items[i+1].intertype !== 'label') {
+ item.items.splice(i+1, 0, {
+ intertype: 'label',
+ ident: ENTRY_IDENT,
+ lineNum: subItem.lineNum + '.5'
+ });
+ }
+ } else if (subItem.intertype == 'functionEnd') {
+ item.functions.slice(-1)[0].endLineNum = subItem.lineNum;
+ } else if (subItem.intertype == 'label') {
+ item.functions.slice(-1)[0].labels.push(subItem);
+ subItem.lines = [];
+ currLabelFinished = false;
+ } else if (item.functions.length > 0 && item.functions.slice(-1)[0].endLineNum === null) {
+ // Internal line
+ if (!currLabelFinished) {
+ item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem); // If this line fails, perhaps missing a label?
+ if (subItem.intertype in LABEL_ENDERS) {
+ currLabelFinished = true;
}
+ } else {
+ print('// WARNING: content after a branch in a label, line: ' + subItem.lineNum);
}
- delete item.items;
- this.forwardItem(item, 'CastAway');
+ } else {
+ throw 'ERROR: what is this? ' + dump(subItem);
}
- });
+ }
+ delete item.items;
// CastAway - try to remove bitcasts of double<-->i64, which LLVM sometimes generates unnecessarily
// (load a double, convert to i64, use as i64).
@@ -113,75 +103,72 @@ function analyzer(data, sidePass) {
// Note that aside from being an optimization, this is needed for correctness in some cases: If code
// assumes it can bitcast a double to an i64 and back and forth without loss, that may be violated
// due to NaN canonicalization.
- substrate.addActor('CastAway', {
- processItem: function(item) {
- this.forwardItem(item, 'Legalizer');
- if (USE_TYPED_ARRAYS != 2) return;
+ function castAway() {
+ if (USE_TYPED_ARRAYS != 2) return;
- item.functions.forEach(function(func) {
- var has = false;
- func.labels.forEach(function(label) {
- var lines = label.lines;
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- if (line.intertype == 'bitcast' && line.type in SHADOW_FLIP) {
- has = true;
- }
+ item.functions.forEach(function(func) {
+ var has = false;
+ func.labels.forEach(function(label) {
+ var lines = label.lines;
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+ if (line.intertype == 'bitcast' && line.type in SHADOW_FLIP) {
+ has = true;
}
- });
- if (!has) return;
- // there are integer<->floating-point bitcasts, create shadows for everything
- var shadowed = {};
- func.labels.forEach(function(label) {
- var lines = label.lines;
- var i = 0;
- while (i < lines.length) {
- var lines = label.lines;
- var line = lines[i];
- if (line.intertype == 'load' && line.type in SHADOW_FLIP) {
- if (line.pointer.intertype != 'value') { i++; continue } // TODO
- shadowed[line.assignTo] = 1;
- var shadow = line.assignTo + '$$SHADOW';
- var flip = SHADOW_FLIP[line.type];
- lines.splice(i + 1, 0, { // if necessary this element will be legalized in the next phase
- tokens: null,
- indent: 2,
- lineNum: line.lineNum + 0.5,
- assignTo: shadow,
- intertype: 'load',
- pointerType: flip + '*',
- type: flip,
- valueType: flip,
- pointer: {
- intertype: 'value',
- ident: line.pointer.ident,
- type: flip + '*'
- },
- align: line.align,
- ident: line.ident
- });
- // note: no need to update func.lines, it is generated in a later pass
- i++;
- }
+ }
+ });
+ if (!has) return;
+ // there are integer<->floating-point bitcasts, create shadows for everything
+ var shadowed = {};
+ func.labels.forEach(function(label) {
+ var lines = label.lines;
+ var i = 0;
+ while (i < lines.length) {
+ var lines = label.lines;
+ var line = lines[i];
+ if (line.intertype == 'load' && line.type in SHADOW_FLIP) {
+ if (line.pointer.intertype != 'value') { i++; continue } // TODO
+ shadowed[line.assignTo] = 1;
+ var shadow = line.assignTo + '$$SHADOW';
+ var flip = SHADOW_FLIP[line.type];
+ lines.splice(i + 1, 0, { // if necessary this element will be legalized in the next phase
+ tokens: null,
+ indent: 2,
+ lineNum: line.lineNum + 0.5,
+ assignTo: shadow,
+ intertype: 'load',
+ pointerType: flip + '*',
+ type: flip,
+ valueType: flip,
+ pointer: {
+ intertype: 'value',
+ ident: line.pointer.ident,
+ type: flip + '*'
+ },
+ align: line.align,
+ ident: line.ident
+ });
+ // note: no need to update func.lines, it is generated in a later pass
i++;
}
- });
- // use shadows where possible
- func.labels.forEach(function(label) {
- var lines = label.lines;
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- if (line.intertype == 'bitcast' && line.type in SHADOW_FLIP && line.ident in shadowed) {
- var shadow = line.ident + '$$SHADOW';
- line.params[0].ident = shadow;
- line.params[0].type = line.type;
- line.type2 = line.type;
- }
+ i++;
+ }
+ });
+ // use shadows where possible
+ func.labels.forEach(function(label) {
+ var lines = label.lines;
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+ if (line.intertype == 'bitcast' && line.type in SHADOW_FLIP && line.ident in shadowed) {
+ var shadow = line.ident + '$$SHADOW';
+ line.params[0].ident = shadow;
+ line.params[0].type = line.type;
+ line.type2 = line.type;
}
- });
+ }
});
- }
- });
+ });
+ }
// Legalize LLVM unrealistic types into realistic types.
//
@@ -196,727 +183,724 @@ function analyzer(data, sidePass) {
// Currently we just legalize completely unrealistic types into bundles of i32s, and just
// the most common instructions that can be involved with such types: load, store, shifts,
// trunc and zext.
- substrate.addActor('Legalizer', {
- processItem: function(data) {
- // Legalization
- if (USE_TYPED_ARRAYS == 2) {
- function getLegalVars(base, bits, allowLegal) {
- bits = bits || 32; // things like pointers are all i32, but show up as 0 bits from getBits
- if (allowLegal && bits <= 32) return [{ ident: base + ('i' + bits in Runtime.INT_TYPES ? '' : '$0'), bits: bits }];
- if (isNumber(base)) return getLegalLiterals(base, bits);
- if (base[0] == '{') {
- warnOnce('seeing source of illegal data ' + base + ', likely an inline struct - assuming zeroinit');
- return getLegalLiterals('0', bits);
- }
- var ret = new Array(Math.ceil(bits/32));
- var i = 0;
- if (base == 'zeroinitializer' || base == 'undef') base = 0;
- while (bits > 0) {
- ret[i] = { ident: base ? base + '$' + i : '0', bits: Math.min(32, bits) };
- bits -= 32;
- i++;
- }
- return ret;
- }
- function getLegalLiterals(text, bits) {
- var parsed = parseArbitraryInt(text, bits);
- var ret = new Array(Math.ceil(bits/32));
- var i = 0;
- while (bits > 0) {
- ret[i] = { ident: (parsed[i]|0).toString(), bits: Math.min(32, bits) }; // resign all values
- bits -= 32;
- i++;
- }
- return ret;
+ function legalizer() {
+ // Legalization
+ if (USE_TYPED_ARRAYS == 2) {
+ function getLegalVars(base, bits, allowLegal) {
+ bits = bits || 32; // things like pointers are all i32, but show up as 0 bits from getBits
+ if (allowLegal && bits <= 32) return [{ ident: base + ('i' + bits in Runtime.INT_TYPES ? '' : '$0'), bits: bits }];
+ if (isNumber(base)) return getLegalLiterals(base, bits);
+ if (base[0] == '{') {
+ warnOnce('seeing source of illegal data ' + base + ', likely an inline struct - assuming zeroinit');
+ return getLegalLiterals('0', bits);
}
- function getLegalStructuralParts(value) {
- return value.params.slice(0);
+ var ret = new Array(Math.ceil(bits/32));
+ var i = 0;
+ if (base == 'zeroinitializer' || base == 'undef') base = 0;
+ while (bits > 0) {
+ ret[i] = { ident: base ? base + '$' + i : '0', bits: Math.min(32, bits) };
+ bits -= 32;
+ i++;
}
- function getLegalParams(params, bits) {
- return params.map(function(param) {
- var value = param.value || param;
- if (isNumber(value.ident)) {
- return getLegalLiterals(value.ident, bits);
- } else if (value.intertype == 'structvalue') {
- return getLegalStructuralParts(value).map(function(part) {
- return { ident: part.ident, bits: part.type.substr(1) };
- });
- } else {
- return getLegalVars(value.ident, bits);
- }
- });
+ return ret;
+ }
+ function getLegalLiterals(text, bits) {
+ var parsed = parseArbitraryInt(text, bits);
+ var ret = new Array(Math.ceil(bits/32));
+ var i = 0;
+ while (bits > 0) {
+ ret[i] = { ident: (parsed[i]|0).toString(), bits: Math.min(32, bits) }; // resign all values
+ bits -= 32;
+ i++;
}
- // Uses the right factor to multiply line numbers by so that they fit in between
- // the line[i] and the line after it
- function interpLines(lines, i, toAdd) {
- var prev = i >= 0 ? lines[i].lineNum : -1;
- var next = (i < lines.length-1) ? lines[i+1].lineNum : (lines[i].lineNum + 0.5);
- var factor = (next - prev)/(4*toAdd.length+3);
- for (var k = 0; k < toAdd.length; k++) {
- toAdd[k].lineNum = prev + ((k+1)*factor);
- assert(k == 0 || toAdd[k].lineNum > toAdd[k-1].lineNum);
+ return ret;
+ }
+ function getLegalStructuralParts(value) {
+ return value.params.slice(0);
+ }
+ function getLegalParams(params, bits) {
+ return params.map(function(param) {
+ var value = param.value || param;
+ if (isNumber(value.ident)) {
+ return getLegalLiterals(value.ident, bits);
+ } else if (value.intertype == 'structvalue') {
+ return getLegalStructuralParts(value).map(function(part) {
+ return { ident: part.ident, bits: part.type.substr(1) };
+ });
+ } else {
+ return getLegalVars(value.ident, bits);
}
+ });
+ }
+ // Uses the right factor to multiply line numbers by so that they fit in between
+ // the line[i] and the line after it
+ function interpLines(lines, i, toAdd) {
+ var prev = i >= 0 ? lines[i].lineNum : -1;
+ var next = (i < lines.length-1) ? lines[i+1].lineNum : (lines[i].lineNum + 0.5);
+ var factor = (next - prev)/(4*toAdd.length+3);
+ for (var k = 0; k < toAdd.length; k++) {
+ toAdd[k].lineNum = prev + ((k+1)*factor);
+ assert(k == 0 || toAdd[k].lineNum > toAdd[k-1].lineNum);
}
- function removeAndAdd(lines, i, toAdd) {
- var item = lines[i];
- interpLines(lines, i, toAdd);
- Array.prototype.splice.apply(lines, [i, 1].concat(toAdd));
- if (i > 0) assert(lines[i].lineNum > lines[i-1].lineNum);
- if (i + toAdd.length < lines.length) assert(lines[i + toAdd.length - 1].lineNum < lines[i + toAdd.length].lineNum);
- return toAdd.length;
- }
- function legalizeFunctionParameters(params) {
- var i = 0;
- while (i < params.length) {
- var param = params[i];
- if (param.intertype == 'value' && isIllegalType(param.type)) {
- var toAdd = getLegalVars(param.ident, getBits(param.type)).map(function(element) {
- return {
- intertype: 'value',
- type: 'i' + element.bits,
- ident: element.ident,
- byval: 0
- };
- });
- Array.prototype.splice.apply(params, [i, 1].concat(toAdd));
- i += toAdd.length;
- continue;
- } else if (param.intertype == 'structvalue') {
- // 'flatten' out the struct into scalars
- var toAdd = param.params;
- toAdd.forEach(function(param) {
- param.byval = 0;
- });
- Array.prototype.splice.apply(params, [i, 1].concat(toAdd));
- continue; // do not increment i; proceed to process the new params
- }
- i++;
+ }
+ function removeAndAdd(lines, i, toAdd) {
+ var item = lines[i];
+ interpLines(lines, i, toAdd);
+ Array.prototype.splice.apply(lines, [i, 1].concat(toAdd));
+ if (i > 0) assert(lines[i].lineNum > lines[i-1].lineNum);
+ if (i + toAdd.length < lines.length) assert(lines[i + toAdd.length - 1].lineNum < lines[i + toAdd.length].lineNum);
+ return toAdd.length;
+ }
+ function legalizeFunctionParameters(params) {
+ var i = 0;
+ while (i < params.length) {
+ var param = params[i];
+ if (param.intertype == 'value' && isIllegalType(param.type)) {
+ var toAdd = getLegalVars(param.ident, getBits(param.type)).map(function(element) {
+ return {
+ intertype: 'value',
+ type: 'i' + element.bits,
+ ident: element.ident,
+ byval: 0
+ };
+ });
+ Array.prototype.splice.apply(params, [i, 1].concat(toAdd));
+ i += toAdd.length;
+ continue;
+ } else if (param.intertype == 'structvalue') {
+ // 'flatten' out the struct into scalars
+ var toAdd = param.params;
+ toAdd.forEach(function(param) {
+ param.byval = 0;
+ });
+ Array.prototype.splice.apply(params, [i, 1].concat(toAdd));
+ continue; // do not increment i; proceed to process the new params
}
+ i++;
}
- function fixUnfolded(item) {
- // Unfolded items may need some correction to work properly in the global scope
- if (item.intertype in MATHOPS) {
- item.op = item.intertype;
- item.intertype = 'mathop';
- }
+ }
+ function fixUnfolded(item) {
+ // Unfolded items may need some correction to work properly in the global scope
+ if (item.intertype in MATHOPS) {
+ item.op = item.intertype;
+ item.intertype = 'mathop';
}
- data.functions.forEach(function(func) {
- // Legalize function params
- legalizeFunctionParameters(func.params);
- // Legalize lines in labels
- var tempId = 0;
- func.labels.forEach(function(label) {
- if (dcheck('legalizer')) dprint('zz legalizing: \n' + dump(label.lines));
- var i = 0, bits;
- while (i < label.lines.length) {
- var item = label.lines[i];
- var value = item;
- // Check if we need to legalize here, and do some trivial legalization along the way
- var isIllegal = false;
- walkInterdata(item, function(item) {
- if (item.intertype == 'getelementptr' || (item.intertype == 'call' && item.ident in LLVM.INTRINSICS_32)) {
- // Turn i64 args into i32
- for (var i = 0; i < item.params.length; i++) {
- if (item.params[i].type == 'i64') item.params[i].type = 'i32';
- }
- } else if (item.intertype == 'inttoptr') {
- var input = item.params[0];
- if (input.type == 'i64') input.type = 'i32'; // inttoptr can only care about 32 bits anyhow since pointers are 32-bit
- }
- if (isIllegalType(item.valueType) || isIllegalType(item.type)) {
- isIllegal = true;
- } else if ((item.intertype == 'load' || item.intertype == 'store') && isStructType(item.valueType)) {
- isIllegal = true; // storing an entire structure is illegal
- } else if (item.intertype == 'mathop' && item.op == 'trunc' && isIllegalType(item.params[1].ident)) { // trunc stores target value in second ident
- isIllegal = true;
+ }
+ data.functions.forEach(function(func) {
+ // Legalize function params
+ legalizeFunctionParameters(func.params);
+ // Legalize lines in labels
+ var tempId = 0;
+ func.labels.forEach(function(label) {
+ if (dcheck('legalizer')) dprint('zz legalizing: \n' + dump(label.lines));
+ var i = 0, bits;
+ while (i < label.lines.length) {
+ var item = label.lines[i];
+ var value = item;
+ // Check if we need to legalize here, and do some trivial legalization along the way
+ var isIllegal = false;
+ walkInterdata(item, function(item) {
+ if (item.intertype == 'getelementptr' || (item.intertype == 'call' && item.ident in LLVM.INTRINSICS_32)) {
+ // Turn i64 args into i32
+ for (var i = 0; i < item.params.length; i++) {
+ if (item.params[i].type == 'i64') item.params[i].type = 'i32';
}
- });
- if (!isIllegal) {
- //if (dcheck('legalizer')) dprint('no need to legalize \n' + dump(item));
- i++;
- continue;
+ } else if (item.intertype == 'inttoptr') {
+ var input = item.params[0];
+ if (input.type == 'i64') input.type = 'i32'; // inttoptr can only care about 32 bits anyhow since pointers are 32-bit
}
- // Unfold this line. If we unfolded, we need to return and process the lines we just
- // generated - they may need legalization too
- var unfolded = [];
- walkAndModifyInterdata(item, function(subItem) {
- // Unfold all non-value interitems that we can, and also unfold all numbers (doing the latter
- // makes it easier later since we can then assume illegal expressions are always variables
- // accessible through ident$x, and not constants we need to parse then and there)
- if (subItem != item && (!(subItem.intertype in UNUNFOLDABLE) ||
- (subItem.intertype == 'value' && isNumber(subItem.ident) && isIllegalType(subItem.type)))) {
- if (item.intertype == 'phi') {
- assert(subItem.intertype == 'value' || subItem.intertype == 'structvalue' || subItem.intertype in PARSABLE_LLVM_FUNCTIONS, 'We can only unfold some expressions in phis');
- // we must handle this in the phi itself, if we unfold normally it will not be pushed back with the phi
- } else {
+ if (isIllegalType(item.valueType) || isIllegalType(item.type)) {
+ isIllegal = true;
+ } else if ((item.intertype == 'load' || item.intertype == 'store') && isStructType(item.valueType)) {
+ isIllegal = true; // storing an entire structure is illegal
+ } else if (item.intertype == 'mathop' && item.op == 'trunc' && isIllegalType(item.params[1].ident)) { // trunc stores target value in second ident
+ isIllegal = true;
+ }
+ });
+ if (!isIllegal) {
+ //if (dcheck('legalizer')) dprint('no need to legalize \n' + dump(item));
+ i++;
+ continue;
+ }
+ // Unfold this line. If we unfolded, we need to return and process the lines we just
+ // generated - they may need legalization too
+ var unfolded = [];
+ walkAndModifyInterdata(item, function(subItem) {
+ // Unfold all non-value interitems that we can, and also unfold all numbers (doing the latter
+ // makes it easier later since we can then assume illegal expressions are always variables
+ // accessible through ident$x, and not constants we need to parse then and there)
+ if (subItem != item && (!(subItem.intertype in UNUNFOLDABLE) ||
+ (subItem.intertype == 'value' && isNumber(subItem.ident) && isIllegalType(subItem.type)))) {
+ if (item.intertype == 'phi') {
+ assert(subItem.intertype == 'value' || subItem.intertype == 'structvalue' || subItem.intertype in PARSABLE_LLVM_FUNCTIONS, 'We can only unfold some expressions in phis');
+ // we must handle this in the phi itself, if we unfold normally it will not be pushed back with the phi
+ } else {
+ var tempIdent = '$$etemp$' + (tempId++);
+ subItem.assignTo = tempIdent;
+ unfolded.unshift(subItem);
+ fixUnfolded(subItem);
+ return { intertype: 'value', ident: tempIdent, type: subItem.type };
+ }
+ } else if (subItem.intertype == 'switch' && isIllegalType(subItem.type)) {
+ subItem.switchLabels.forEach(function(switchLabel) {
+ if (switchLabel.value[0] != '$') {
var tempIdent = '$$etemp$' + (tempId++);
- subItem.assignTo = tempIdent;
- unfolded.unshift(subItem);
- fixUnfolded(subItem);
- return { intertype: 'value', ident: tempIdent, type: subItem.type };
+ unfolded.unshift({
+ assignTo: tempIdent,
+ intertype: 'value',
+ ident: switchLabel.value,
+ type: subItem.type
+ });
+ switchLabel.value = tempIdent;
}
- } else if (subItem.intertype == 'switch' && isIllegalType(subItem.type)) {
- subItem.switchLabels.forEach(function(switchLabel) {
- if (switchLabel.value[0] != '$') {
- var tempIdent = '$$etemp$' + (tempId++);
- unfolded.unshift({
- assignTo: tempIdent,
- intertype: 'value',
- ident: switchLabel.value,
- type: subItem.type
- });
- switchLabel.value = tempIdent;
- }
+ });
+ }
+ });
+ if (unfolded.length > 0) {
+ interpLines(label.lines, i-1, unfolded);
+ Array.prototype.splice.apply(label.lines, [i, 0].concat(unfolded));
+ continue; // remain at this index, to unfold newly generated lines
+ }
+ // This is an illegal-containing line, and it is unfolded. Legalize it now
+ dprint('legalizer', 'Legalizing ' + item.intertype + ' at line ' + item.lineNum);
+ var finalizer = null;
+ switch (item.intertype) {
+ case 'store': {
+ var toAdd = [];
+ bits = getBits(item.valueType);
+ var elements = getLegalParams([item.value], bits)[0];
+ var j = 0;
+ elements.forEach(function(element) {
+ var tempVar = '$st$' + (tempId++) + '$' + j;
+ toAdd.push({
+ intertype: 'getelementptr',
+ assignTo: tempVar,
+ ident: item.pointer.ident,
+ type: '[0 x i32]*',
+ params: [
+ { intertype: 'value', ident: item.pointer.ident, type: '[0 x i32]*' }, // technically a bitcase is needed in llvm, but not for us
+ { intertype: 'value', ident: '0', type: 'i32' },
+ { intertype: 'value', ident: j.toString(), type: 'i32' }
+ ],
});
- }
- });
- if (unfolded.length > 0) {
- interpLines(label.lines, i-1, unfolded);
- Array.prototype.splice.apply(label.lines, [i, 0].concat(unfolded));
- continue; // remain at this index, to unfold newly generated lines
+ var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
+ toAdd.push({
+ intertype: 'store',
+ valueType: actualSizeType,
+ value: { intertype: 'value', ident: element.ident, type: actualSizeType },
+ pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
+ ident: tempVar,
+ pointerType: actualSizeType + '*',
+ align: item.align,
+ });
+ j++;
+ });
+ Types.needAnalysis['[0 x i32]'] = 0;
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
}
- // This is an illegal-containing line, and it is unfolded. Legalize it now
- dprint('legalizer', 'Legalizing ' + item.intertype + ' at line ' + item.lineNum);
- var finalizer = null;
- switch (item.intertype) {
- case 'store': {
- var toAdd = [];
- bits = getBits(item.valueType);
- var elements = getLegalParams([item.value], bits)[0];
- var j = 0;
- elements.forEach(function(element) {
- var tempVar = '$st$' + (tempId++) + '$' + j;
- toAdd.push({
- intertype: 'getelementptr',
- assignTo: tempVar,
- ident: item.pointer.ident,
- type: '[0 x i32]*',
- params: [
- { intertype: 'value', ident: item.pointer.ident, type: '[0 x i32]*' }, // technically a bitcase is needed in llvm, but not for us
- { intertype: 'value', ident: '0', type: 'i32' },
- { intertype: 'value', ident: j.toString(), type: 'i32' }
- ],
- });
- var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
+ // call, return: Return the first 32 bits, the rest are in temp
+ case 'call': {
+ var toAdd = [value];
+ // legalize parameters
+ legalizeFunctionParameters(value.params);
+ // legalize return value, if any
+ var returnType = getReturnType(item.type);
+ if (value.assignTo && isIllegalType(returnType)) {
+ bits = getBits(returnType);
+ var elements = getLegalVars(item.assignTo, bits);
+ // legalize return value
+ value.assignTo = elements[0].ident;
+ for (var j = 1; j < elements.length; j++) {
+ var element = elements[j];
toAdd.push({
- intertype: 'store',
- valueType: actualSizeType,
- value: { intertype: 'value', ident: element.ident, type: actualSizeType },
- pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
- ident: tempVar,
- pointerType: actualSizeType + '*',
- align: item.align,
+ intertype: 'value',
+ assignTo: element.ident,
+ type: element.bits,
+ ident: 'tempRet' + (j - 1)
});
- j++;
- });
- Types.needAnalysis['[0 x i32]'] = 0;
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- // call, return: Return the first 32 bits, the rest are in temp
- case 'call': {
- var toAdd = [value];
- // legalize parameters
- legalizeFunctionParameters(value.params);
- // legalize return value, if any
- var returnType = getReturnType(item.type);
- if (value.assignTo && isIllegalType(returnType)) {
- bits = getBits(returnType);
- var elements = getLegalVars(item.assignTo, bits);
- // legalize return value
- value.assignTo = elements[0].ident;
- for (var j = 1; j < elements.length; j++) {
- var element = elements[j];
- toAdd.push({
- intertype: 'value',
- assignTo: element.ident,
- type: element.bits,
- ident: 'tempRet' + (j - 1)
- });
- assert(j<10); // TODO: dynamically create more than 10 tempRet-s
- }
+ assert(j<10); // TODO: dynamically create more than 10 tempRet-s
}
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
}
- case 'landingpad': {
- // not much to legalize
- i++;
- continue;
- }
- case 'return': {
- bits = getBits(item.type);
- var elements = getLegalVars(item.value.ident, bits);
- item.value.ident = '(';
- for (var j = 1; j < elements.length; j++) {
- item.value.ident += 'tempRet' + (j-1) + '=' + elements[j].ident + ',';
- }
- item.value.ident += elements[0].ident + ')';
- i++;
- continue;
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'landingpad': {
+ // not much to legalize
+ i++;
+ continue;
+ }
+ case 'return': {
+ bits = getBits(item.type);
+ var elements = getLegalVars(item.value.ident, bits);
+ item.value.ident = '(';
+ for (var j = 1; j < elements.length; j++) {
+ item.value.ident += 'tempRet' + (j-1) + '=' + elements[j].ident + ',';
}
- case 'invoke': {
- legalizeFunctionParameters(value.params);
- // We can't add lines after this, since invoke already modifies control flow. So we handle the return in invoke
- i++;
- continue;
+ item.value.ident += elements[0].ident + ')';
+ i++;
+ continue;
+ }
+ case 'invoke': {
+ legalizeFunctionParameters(value.params);
+ // We can't add lines after this, since invoke already modifies control flow. So we handle the return in invoke
+ i++;
+ continue;
+ }
+ case 'value': {
+ bits = getBits(value.type);
+ var elements = getLegalVars(item.assignTo, bits);
+ var values = getLegalLiterals(item.ident, bits);
+ var j = 0;
+ var toAdd = elements.map(function(element) {
+ return {
+ intertype: 'value',
+ assignTo: element.ident,
+ type: 'i' + bits,
+ ident: values[j++].ident
+ };
+ });
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'structvalue': {
+ bits = getBits(value.type);
+ var elements = getLegalVars(item.assignTo, bits);
+ var toAdd = [];
+ for (var j = 0; j < item.params.length; j++) {
+ toAdd[j] = {
+ intertype: 'value',
+ assignTo: elements[j].ident,
+ type: 'i32',
+ ident: item.params[j].ident
+ };
}
- case 'value': {
- bits = getBits(value.type);
- var elements = getLegalVars(item.assignTo, bits);
- var values = getLegalLiterals(item.ident, bits);
- var j = 0;
- var toAdd = elements.map(function(element) {
- return {
- intertype: 'value',
- assignTo: element.ident,
- type: 'i' + bits,
- ident: values[j++].ident
- };
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'load': {
+ bits = getBits(value.valueType);
+ var elements = getLegalVars(item.assignTo, bits);
+ var j = 0;
+ var toAdd = [];
+ elements.forEach(function(element) {
+ var tempVar = '$ld$' + (tempId++) + '$' + j;
+ toAdd.push({
+ intertype: 'getelementptr',
+ assignTo: tempVar,
+ ident: value.pointer.ident,
+ type: '[0 x i32]*',
+ params: [
+ { intertype: 'value', ident: value.pointer.ident, type: '[0 x i32]*' }, // technically bitcast is needed in llvm, but not for us
+ { intertype: 'value', ident: '0', type: 'i32' },
+ { intertype: 'value', ident: j.toString(), type: 'i32' }
+ ]
});
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- case 'structvalue': {
- bits = getBits(value.type);
- var elements = getLegalVars(item.assignTo, bits);
- var toAdd = [];
- for (var j = 0; j < item.params.length; j++) {
- toAdd[j] = {
- intertype: 'value',
- assignTo: elements[j].ident,
- type: 'i32',
- ident: item.params[j].ident
- };
- }
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- case 'load': {
- bits = getBits(value.valueType);
- var elements = getLegalVars(item.assignTo, bits);
- var j = 0;
- var toAdd = [];
- elements.forEach(function(element) {
- var tempVar = '$ld$' + (tempId++) + '$' + j;
- toAdd.push({
- intertype: 'getelementptr',
- assignTo: tempVar,
- ident: value.pointer.ident,
- type: '[0 x i32]*',
- params: [
- { intertype: 'value', ident: value.pointer.ident, type: '[0 x i32]*' }, // technically bitcast is needed in llvm, but not for us
- { intertype: 'value', ident: '0', type: 'i32' },
- { intertype: 'value', ident: j.toString(), type: 'i32' }
- ]
- });
- var newItem = {
- intertype: 'load',
+ var newItem = {
+ intertype: 'load',
+ assignTo: element.ident,
+ pointerType: 'i32*',
+ valueType: 'i32',
+ type: 'i32',
+ pointer: { intertype: 'value', ident: tempVar, type: 'i32*' },
+ ident: tempVar,
+ align: value.align
+ };
+ var newItem2 = null;
+ // The last one may be smaller than 32 bits
+ if (element.bits < 32) {
+ newItem.assignTo += '$preadd$';
+ newItem2 = {
+ intertype: 'mathop',
+ op: 'and',
assignTo: element.ident,
- pointerType: 'i32*',
- valueType: 'i32',
type: 'i32',
- pointer: { intertype: 'value', ident: tempVar, type: 'i32*' },
- ident: tempVar,
- align: value.align
- };
- var newItem2 = null;
- // The last one may be smaller than 32 bits
- if (element.bits < 32) {
- newItem.assignTo += '$preadd$';
- newItem2 = {
- intertype: 'mathop',
- op: 'and',
- assignTo: element.ident,
+ params: [{
+ intertype: 'value',
type: 'i32',
- params: [{
- intertype: 'value',
- type: 'i32',
- ident: newItem.assignTo
- }, {
- intertype: 'value',
- type: 'i32',
- ident: (0xffffffff >>> (32 - element.bits)).toString()
- }],
- };
- }
- toAdd.push(newItem);
- if (newItem2) toAdd.push(newItem2);
- j++;
- });
- Types.needAnalysis['[0 x i32]'] = 0;
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- case 'phi': {
- bits = getBits(value.type);
- var toAdd = [];
- var elements = getLegalVars(item.assignTo, bits);
- var j = 0;
- var values = getLegalParams(value.params, bits);
- elements.forEach(function(element) {
- var k = 0;
- toAdd.push({
- intertype: 'phi',
- assignTo: element.ident,
- type: 'i' + element.bits,
- params: value.params.map(function(param) {
- return {
- intertype: 'phiparam',
- label: param.label,
- value: {
- intertype: 'value',
- ident: values[k++][j].ident,
- type: 'i' + element.bits,
- }
- };
- })
- });
- j++;
- });
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- case 'switch': {
- i++;
- continue; // special case, handled in makeComparison
- }
- case 'va_arg': {
- assert(value.type == 'i64');
- assert(value.value.type == 'i32*', value.value.type);
- i += removeAndAdd(label.lines, i, range(2).map(function(x) {
- return {
- intertype: 'va_arg',
- assignTo: value.assignTo + '$' + x,
- type: 'i32',
- value: {
+ ident: newItem.assignTo
+ }, {
intertype: 'value',
- ident: value.value.ident, // We read twice from the same i32* var, incrementing // + '$' + x,
- type: 'i32*'
- }
+ type: 'i32',
+ ident: (0xffffffff >>> (32 - element.bits)).toString()
+ }],
};
- }));
- continue;
- }
- case 'extractvalue': { // XXX we assume 32-bit alignment in extractvalue/insertvalue,
- // but in theory they can run on packed structs too (see use getStructuralTypePartBits)
- // potentially legalize the actual extracted value too if it is >32 bits, not just the extraction in general
- var index = item.indexes[0][0].text;
- var parts = getStructureTypeParts(item.type);
- var indexedType = parts[index];
- var targetBits = getBits(indexedType);
- var sourceBits = getBits(item.type);
- var elements = getLegalVars(item.assignTo, targetBits, true); // possibly illegal
- var sourceElements = getLegalVars(item.ident, sourceBits); // definitely illegal
- var toAdd = [];
- var sourceIndex = 0;
- for (var partIndex = 0; partIndex < parts.length; partIndex++) {
- if (partIndex == index) {
- for (var j = 0; j < elements.length; j++) {
- toAdd.push({
- intertype: 'value',
- assignTo: elements[j].ident,
- type: 'i' + elements[j].bits,
- ident: sourceElements[sourceIndex+j].ident
- });
- }
- break;
- }
- sourceIndex += getStructuralTypePartBits(parts[partIndex])/32;
}
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- case 'insertvalue': {
- var index = item.indexes[0][0].text; // the modified index
- var parts = getStructureTypeParts(item.type);
- var indexedType = parts[index];
- var indexBits = getBits(indexedType);
- var bits = getBits(item.type); // source and target
- bits = getBits(value.type);
- var toAdd = [];
- var elements = getLegalVars(item.assignTo, bits);
- var sourceElements = getLegalVars(item.ident, bits);
- var indexElements = getLegalVars(item.value.ident, indexBits, true); // possibly legal
- var sourceIndex = 0;
- for (var partIndex = 0; partIndex < parts.length; partIndex++) {
- var currNum = getStructuralTypePartBits(parts[partIndex])/32;
- for (var j = 0; j < currNum; j++) {
+ toAdd.push(newItem);
+ if (newItem2) toAdd.push(newItem2);
+ j++;
+ });
+ Types.needAnalysis['[0 x i32]'] = 0;
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'phi': {
+ bits = getBits(value.type);
+ var toAdd = [];
+ var elements = getLegalVars(item.assignTo, bits);
+ var j = 0;
+ var values = getLegalParams(value.params, bits);
+ elements.forEach(function(element) {
+ var k = 0;
+ toAdd.push({
+ intertype: 'phi',
+ assignTo: element.ident,
+ type: 'i' + element.bits,
+ params: value.params.map(function(param) {
+ return {
+ intertype: 'phiparam',
+ label: param.label,
+ value: {
+ intertype: 'value',
+ ident: values[k++][j].ident,
+ type: 'i' + element.bits,
+ }
+ };
+ })
+ });
+ j++;
+ });
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'switch': {
+ i++;
+ continue; // special case, handled in makeComparison
+ }
+ case 'va_arg': {
+ assert(value.type == 'i64');
+ assert(value.value.type == 'i32*', value.value.type);
+ i += removeAndAdd(label.lines, i, range(2).map(function(x) {
+ return {
+ intertype: 'va_arg',
+ assignTo: value.assignTo + '$' + x,
+ type: 'i32',
+ value: {
+ intertype: 'value',
+ ident: value.value.ident, // We read twice from the same i32* var, incrementing // + '$' + x,
+ type: 'i32*'
+ }
+ };
+ }));
+ continue;
+ }
+ case 'extractvalue': { // XXX we assume 32-bit alignment in extractvalue/insertvalue,
+ // but in theory they can run on packed structs too (see use getStructuralTypePartBits)
+ // potentially legalize the actual extracted value too if it is >32 bits, not just the extraction in general
+ var index = item.indexes[0][0].text;
+ var parts = getStructureTypeParts(item.type);
+ var indexedType = parts[index];
+ var targetBits = getBits(indexedType);
+ var sourceBits = getBits(item.type);
+ var elements = getLegalVars(item.assignTo, targetBits, true); // possibly illegal
+ var sourceElements = getLegalVars(item.ident, sourceBits); // definitely illegal
+ var toAdd = [];
+ var sourceIndex = 0;
+ for (var partIndex = 0; partIndex < parts.length; partIndex++) {
+ if (partIndex == index) {
+ for (var j = 0; j < elements.length; j++) {
toAdd.push({
intertype: 'value',
- assignTo: elements[sourceIndex+j].ident,
- type: 'i' + elements[sourceIndex+j].bits,
- ident: partIndex == index ? indexElements[j].ident : sourceElements[sourceIndex+j].ident
+ assignTo: elements[j].ident,
+ type: 'i' + elements[j].bits,
+ ident: sourceElements[sourceIndex+j].ident
});
}
- sourceIndex += currNum;
+ break;
}
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
+ sourceIndex += getStructuralTypePartBits(parts[partIndex])/32;
}
- case 'bitcast': {
- var inType = item.type2;
- var outType = item.type;
- if ((inType in Runtime.INT_TYPES && outType in Runtime.FLOAT_TYPES) ||
- (inType in Runtime.FLOAT_TYPES && outType in Runtime.INT_TYPES)) {
- i++;
- continue; // special case, handled in processMathop
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'insertvalue': {
+ var index = item.indexes[0][0].text; // the modified index
+ var parts = getStructureTypeParts(item.type);
+ var indexedType = parts[index];
+ var indexBits = getBits(indexedType);
+ var bits = getBits(item.type); // source and target
+ bits = getBits(value.type);
+ var toAdd = [];
+ var elements = getLegalVars(item.assignTo, bits);
+ var sourceElements = getLegalVars(item.ident, bits);
+ var indexElements = getLegalVars(item.value.ident, indexBits, true); // possibly legal
+ var sourceIndex = 0;
+ for (var partIndex = 0; partIndex < parts.length; partIndex++) {
+ var currNum = getStructuralTypePartBits(parts[partIndex])/32;
+ for (var j = 0; j < currNum; j++) {
+ toAdd.push({
+ intertype: 'value',
+ assignTo: elements[sourceIndex+j].ident,
+ type: 'i' + elements[sourceIndex+j].bits,
+ ident: partIndex == index ? indexElements[j].ident : sourceElements[sourceIndex+j].ident
+ });
}
- // fall through
+ sourceIndex += currNum;
}
- case 'inttoptr': case 'ptrtoint': case 'zext': case 'sext': case 'trunc': case 'ashr': case 'lshr': case 'shl': case 'or': case 'and': case 'xor': {
- value = {
- op: item.intertype,
- variant: item.variant,
- type: item.type,
- params: item.params
- };
- // fall through
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'bitcast': {
+ var inType = item.type2;
+ var outType = item.type;
+ if ((inType in Runtime.INT_TYPES && outType in Runtime.FLOAT_TYPES) ||
+ (inType in Runtime.FLOAT_TYPES && outType in Runtime.INT_TYPES)) {
+ i++;
+ continue; // special case, handled in processMathop
}
- case 'mathop': {
- var toAdd = [];
- var sourceBits = getBits(value.params[0].type);
- // All mathops can be parametrized by how many shifts we do, and how big the source is
- var shifts = 0;
- var targetBits = sourceBits;
- var processor = null;
- var signed = false;
- switch (value.op) {
- case 'ashr': {
- signed = true;
- // fall through
- }
- case 'lshr': {
- shifts = parseInt(value.params[1].ident);
- break;
- }
- case 'shl': {
- shifts = -parseInt(value.params[1].ident);
- break;
- }
- case 'sext': {
- signed = true;
- // fall through
- }
- case 'trunc': case 'zext': case 'ptrtoint': {
- targetBits = getBits(value.params[1] ? value.params[1].ident : value.type);
- break;
- }
- case 'inttoptr': {
- targetBits = 32;
- break;
- }
- case 'bitcast': {
- if (!sourceBits) {
- // we can be asked to bitcast doubles or such to integers, handle that as best we can (if it's a double that
- // was an x86_fp80, this code will likely break when called)
- sourceBits = targetBits = Runtime.getNativeTypeSize(value.params[0].type);
- warn('legalizing non-integer bitcast on ll #' + item.lineNum);
- }
- break;
- }
- case 'select': {
- sourceBits = targetBits = getBits(value.params[1].type);
- var params = getLegalParams(value.params.slice(1), sourceBits);
- processor = function(result, j) {
- return {
- intertype: 'mathop',
- op: 'select',
- type: 'i' + params[0][j].bits,
- params: [
- value.params[0],
- { intertype: 'value', ident: params[0][j].ident, type: 'i' + params[0][j].bits },
- { intertype: 'value', ident: params[1][j].ident, type: 'i' + params[1][j].bits }
- ]
- };
- };
- break;
- }
- case 'or': case 'and': case 'xor': case 'icmp': {
- var otherElements = getLegalVars(value.params[1].ident, sourceBits);
- processor = function(result, j) {
- return {
- intertype: 'mathop',
- op: value.op,
- variant: value.variant,
- type: 'i' + otherElements[j].bits,
- params: [
- result,
- { intertype: 'value', ident: otherElements[j].ident, type: 'i' + otherElements[j].bits }
- ]
- };
- };
- if (value.op == 'icmp') {
- if (sourceBits == 64) { // handle the i64 case in processMathOp, where we handle full i64 math
- i++;
- continue;
- }
- finalizer = function() {
- var ident = '';
- for (var i = 0; i < targetElements.length; i++) {
- if (i > 0) {
- switch(value.variant) {
- case 'eq': ident += '&'; break;
- case 'ne': ident += '|'; break;
- default: throw 'unhandleable illegal icmp: ' + value.variant;
- }
- }
- ident += targetElements[i].ident;
- }
- return {
- intertype: 'value',
- ident: ident,
- type: 'rawJS',
- assignTo: item.assignTo
- };
- }
- }
- break;
- }
- case 'add': case 'sub': case 'sdiv': case 'udiv': case 'mul': case 'urem': case 'srem': {
- if (sourceBits < 32) {
- // when we add illegal types like i24, we must work on the singleton chunks
- item.assignTo += '$0';
- item.params[0].ident += '$0';
- item.params[1].ident += '$0';
- }
- // fall through
- }
- case 'uitofp': case 'sitofp': case 'fptosi': case 'fptoui': {
- // We cannot do these in parallel chunks of 32-bit operations. We will handle these in processMathop
- i++;
- continue;
- }
- default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum, dump(item)];
+ // fall through
+ }
+ case 'inttoptr': case 'ptrtoint': case 'zext': case 'sext': case 'trunc': case 'ashr': case 'lshr': case 'shl': case 'or': case 'and': case 'xor': {
+ value = {
+ op: item.intertype,
+ variant: item.variant,
+ type: item.type,
+ params: item.params
+ };
+ // fall through
+ }
+ case 'mathop': {
+ var toAdd = [];
+ var sourceBits = getBits(value.params[0].type);
+ // All mathops can be parametrized by how many shifts we do, and how big the source is
+ var shifts = 0;
+ var targetBits = sourceBits;
+ var processor = null;
+ var signed = false;
+ switch (value.op) {
+ case 'ashr': {
+ signed = true;
+ // fall through
}
- // Do the legalization
- var sourceElements = getLegalVars(value.params[0].ident, sourceBits, true);
- if (!isNumber(shifts)) {
- // We can't statically legalize this, do the operation at runtime TODO: optimize
- assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits');
- assert(PRECISE_I64_MATH, 'Must have precise i64 math for non-constant 64-bit shifts');
- Types.preciseI64MathUsed = 1;
- value.intertype = 'value';
- value.ident = 'var ' + value.assignTo + '$0 = ' +
- asmCoercion('_bitshift64' + value.op[0].toUpperCase() + value.op.substr(1) + '(' +
- asmCoercion(sourceElements[0].ident, 'i32') + ',' +
- asmCoercion(sourceElements[1].ident, 'i32') + ',' +
- asmCoercion(value.params[1].ident + '$0', 'i32') + ')', 'i32'
- ) + ';' +
- 'var ' + value.assignTo + '$1 = tempRet0;';
- value.assignTo = null;
- i++;
- continue;
+ case 'lshr': {
+ shifts = parseInt(value.params[1].ident);
+ break;
}
- var targetElements = getLegalVars(item.assignTo, targetBits);
- var sign = shifts >= 0 ? 1 : -1;
- var shiftOp = shifts >= 0 ? 'shl' : 'lshr';
- var shiftOpReverse = shifts >= 0 ? 'lshr' : 'shl';
- var whole = shifts >= 0 ? Math.floor(shifts/32) : Math.ceil(shifts/32);
- var fraction = Math.abs(shifts % 32);
- if (signed) {
- var signedFill = '(' + makeSignOp(sourceElements[sourceElements.length-1].ident, 'i' + sourceElements[sourceElements.length-1].bits, 're', 1, 1) + ' < 0 ? -1 : 0)';
- var signedKeepAlive = { intertype: 'value', ident: sourceElements[sourceElements.length-1].ident, type: 'i32' };
+ case 'shl': {
+ shifts = -parseInt(value.params[1].ident);
+ break;
}
- for (var j = 0; j < targetElements.length; j++) {
- var result = {
- intertype: 'value',
- ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : (signed ? signedFill : '0'),
- params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null],
- type: 'i32',
- };
- if (j == 0 && sourceBits < 32) {
- // zext sign correction
- result.ident = makeSignOp(result.ident, 'i' + sourceBits, isUnsignedOp(value.op) ? 'un' : 're', 1, 1);
+ case 'sext': {
+ signed = true;
+ // fall through
+ }
+ case 'trunc': case 'zext': case 'ptrtoint': {
+ targetBits = getBits(value.params[1] ? value.params[1].ident : value.type);
+ break;
+ }
+ case 'inttoptr': {
+ targetBits = 32;
+ break;
+ }
+ case 'bitcast': {
+ if (!sourceBits) {
+ // we can be asked to bitcast doubles or such to integers, handle that as best we can (if it's a double that
+ // was an x86_fp80, this code will likely break when called)
+ sourceBits = targetBits = Runtime.getNativeTypeSize(value.params[0].type);
+ warn('legalizing non-integer bitcast on ll #' + item.lineNum);
}
- if (fraction != 0) {
- var other = {
- intertype: 'value',
- ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : (signed ? signedFill : '0'),
- params: [(signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null],
- type: 'i32',
- };
- other = {
+ break;
+ }
+ case 'select': {
+ sourceBits = targetBits = getBits(value.params[1].type);
+ var params = getLegalParams(value.params.slice(1), sourceBits);
+ processor = function(result, j) {
+ return {
intertype: 'mathop',
- op: shiftOp,
- type: 'i32',
+ op: 'select',
+ type: 'i' + params[0][j].bits,
params: [
- other,
- { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
+ value.params[0],
+ { intertype: 'value', ident: params[0][j].ident, type: 'i' + params[0][j].bits },
+ { intertype: 'value', ident: params[1][j].ident, type: 'i' + params[1][j].bits }
]
};
- result = {
+ };
+ break;
+ }
+ case 'or': case 'and': case 'xor': case 'icmp': {
+ var otherElements = getLegalVars(value.params[1].ident, sourceBits);
+ processor = function(result, j) {
+ return {
intertype: 'mathop',
- // shifting in 1s from the top is a special case
- op: (signed && shifts >= 0 && j + sign + whole >= sourceElements.length) ? 'ashr' : shiftOpReverse,
- type: 'i32',
+ op: value.op,
+ variant: value.variant,
+ type: 'i' + otherElements[j].bits,
params: [
result,
- { intertype: 'value', ident: fraction.toString(), type: 'i32' }
+ { intertype: 'value', ident: otherElements[j].ident, type: 'i' + otherElements[j].bits }
]
};
- result = {
- intertype: 'mathop',
- op: 'or',
- type: 'i32',
- params: [
- result,
- other
- ]
+ };
+ if (value.op == 'icmp') {
+ if (sourceBits == 64) { // handle the i64 case in processMathOp, where we handle full i64 math
+ i++;
+ continue;
}
- }
- if (targetElements[j].bits < 32 && shifts < 0) {
- // truncate bits that fall off the end. This is not needed in most cases, can probably be optimized out
- result = {
- intertype: 'mathop',
- op: 'and',
- type: 'i32',
- params: [
- result,
- { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' }
- ]
+ finalizer = function() {
+ var ident = '';
+ for (var i = 0; i < targetElements.length; i++) {
+ if (i > 0) {
+ switch(value.variant) {
+ case 'eq': ident += '&'; break;
+ case 'ne': ident += '|'; break;
+ default: throw 'unhandleable illegal icmp: ' + value.variant;
+ }
+ }
+ ident += targetElements[i].ident;
+ }
+ return {
+ intertype: 'value',
+ ident: ident,
+ type: 'rawJS',
+ assignTo: item.assignTo
+ };
}
}
- if (processor) {
- result = processor(result, j);
+ break;
+ }
+ case 'add': case 'sub': case 'sdiv': case 'udiv': case 'mul': case 'urem': case 'srem': {
+ if (sourceBits < 32) {
+ // when we add illegal types like i24, we must work on the singleton chunks
+ item.assignTo += '$0';
+ item.params[0].ident += '$0';
+ item.params[1].ident += '$0';
}
- result.assignTo = targetElements[j].ident;
- toAdd.push(result);
+ // fall through
}
- if (targetBits <= 32) {
- // We are generating a normal legal type here
- legalValue = {
+ case 'uitofp': case 'sitofp': case 'fptosi': case 'fptoui': {
+ // We cannot do these in parallel chunks of 32-bit operations. We will handle these in processMathop
+ i++;
+ continue;
+ }
+ default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum, dump(item)];
+ }
+ // Do the legalization
+ var sourceElements = getLegalVars(value.params[0].ident, sourceBits, true);
+ if (!isNumber(shifts)) {
+ // We can't statically legalize this, do the operation at runtime TODO: optimize
+ assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits');
+ assert(PRECISE_I64_MATH, 'Must have precise i64 math for non-constant 64-bit shifts');
+ Types.preciseI64MathUsed = 1;
+ value.intertype = 'value';
+ value.ident = 'var ' + value.assignTo + '$0 = ' +
+ asmCoercion('_bitshift64' + value.op[0].toUpperCase() + value.op.substr(1) + '(' +
+ asmCoercion(sourceElements[0].ident, 'i32') + ',' +
+ asmCoercion(sourceElements[1].ident, 'i32') + ',' +
+ asmCoercion(value.params[1].ident + '$0', 'i32') + ')', 'i32'
+ ) + ';' +
+ 'var ' + value.assignTo + '$1 = tempRet0;';
+ value.assignTo = null;
+ i++;
+ continue;
+ }
+ var targetElements = getLegalVars(item.assignTo, targetBits);
+ var sign = shifts >= 0 ? 1 : -1;
+ var shiftOp = shifts >= 0 ? 'shl' : 'lshr';
+ var shiftOpReverse = shifts >= 0 ? 'lshr' : 'shl';
+ var whole = shifts >= 0 ? Math.floor(shifts/32) : Math.ceil(shifts/32);
+ var fraction = Math.abs(shifts % 32);
+ if (signed) {
+ var signedFill = '(' + makeSignOp(sourceElements[sourceElements.length-1].ident, 'i' + sourceElements[sourceElements.length-1].bits, 're', 1, 1) + ' < 0 ? -1 : 0)';
+ var signedKeepAlive = { intertype: 'value', ident: sourceElements[sourceElements.length-1].ident, type: 'i32' };
+ }
+ for (var j = 0; j < targetElements.length; j++) {
+ var result = {
+ intertype: 'value',
+ ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : (signed ? signedFill : '0'),
+ params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null],
+ type: 'i32',
+ };
+ if (j == 0 && sourceBits < 32) {
+ // zext sign correction
+ result.ident = makeSignOp(result.ident, 'i' + sourceBits, isUnsignedOp(value.op) ? 'un' : 're', 1, 1);
+ }
+ if (fraction != 0) {
+ var other = {
intertype: 'value',
- ident: targetElements[0].ident + (targetBits < 32 ? '&' + (Math.pow(2, targetBits)-1) : ''),
- type: 'rawJS'
+ ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : (signed ? signedFill : '0'),
+ params: [(signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null],
+ type: 'i32',
+ };
+ other = {
+ intertype: 'mathop',
+ op: shiftOp,
+ type: 'i32',
+ params: [
+ other,
+ { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
+ ]
};
- legalValue.assignTo = item.assignTo;
- toAdd.push(legalValue);
- } else if (finalizer) {
- toAdd.push(finalizer());
+ result = {
+ intertype: 'mathop',
+ // shifting in 1s from the top is a special case
+ op: (signed && shifts >= 0 && j + sign + whole >= sourceElements.length) ? 'ashr' : shiftOpReverse,
+ type: 'i32',
+ params: [
+ result,
+ { intertype: 'value', ident: fraction.toString(), type: 'i32' }
+ ]
+ };
+ result = {
+ intertype: 'mathop',
+ op: 'or',
+ type: 'i32',
+ params: [
+ result,
+ other
+ ]
+ }
}
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
+ if (targetElements[j].bits < 32 && shifts < 0) {
+ // truncate bits that fall off the end. This is not needed in most cases, can probably be optimized out
+ result = {
+ intertype: 'mathop',
+ op: 'and',
+ type: 'i32',
+ params: [
+ result,
+ { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' }
+ ]
+ }
+ }
+ if (processor) {
+ result = processor(result, j);
+ }
+ result.assignTo = targetElements[j].ident;
+ toAdd.push(result);
}
+ if (targetBits <= 32) {
+ // We are generating a normal legal type here
+ legalValue = {
+ intertype: 'value',
+ ident: targetElements[0].ident + (targetBits < 32 ? '&' + (Math.pow(2, targetBits)-1) : ''),
+ type: 'rawJS'
+ };
+ legalValue.assignTo = item.assignTo;
+ toAdd.push(legalValue);
+ } else if (finalizer) {
+ toAdd.push(finalizer());
+ }
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
}
- assert(0, 'Could not legalize illegal line: ' + [item.lineNum, dump(item)]);
}
- if (dcheck('legalizer')) dprint('zz legalized: \n' + dump(label.lines));
- });
- });
- }
-
- // Add function lines to func.lines, after our modifications to the label lines
- data.functions.forEach(function(func) {
- func.labels.forEach(function(label) {
- func.lines = func.lines.concat(label.lines);
+ assert(0, 'Could not legalize illegal line: ' + [item.lineNum, dump(item)]);
+ }
+ if (dcheck('legalizer')) dprint('zz legalized: \n' + dump(label.lines));
});
});
- this.forwardItem(data, 'Typevestigator');
}
- });
- function addTypeInternal(type, data) {
+ // Add function lines to func.lines, after our modifications to the label lines
+ data.functions.forEach(function(func) {
+ func.labels.forEach(function(label) {
+ func.lines = func.lines.concat(label.lines);
+ });
+ });
+ }
+
+ function addTypeInternal(type) {
if (type.length == 1) return;
if (Types.types[type]) return;
if (['internal', 'hidden', 'inbounds', 'void'].indexOf(type) != -1) return;
@@ -927,8 +911,9 @@ function analyzer(data, sidePass) {
// to look at the underlying type - it was not defined explicitly
// anywhere else.
var nonPointing = removeAllPointing(type);
+ if (Types.types[nonPointing]) return;
var check = /^\[(\d+)\ x\ (.*)\]$/.exec(nonPointing);
- if (check && !Types.types[nonPointing]) {
+ if (check) {
var num = parseInt(check[1]);
num = Math.max(num, 1); // [0 x something] is used not for allocations and such of course, but
// for indexing - for an |array of unknown length|, basically. So we
@@ -936,7 +921,7 @@ function analyzer(data, sidePass) {
// check that we never allocate with this (either as a child structure
// in the analyzer, or in calcSize in alloca).
var subType = check[2];
- addTypeInternal(subType, data); // needed for anonymous structure definitions (see below)
+ addTypeInternal(subType); // needed for anonymous structure definitions (see below)
// Huge structural types are represented very inefficiently, both here and in generated JS. Best to avoid them - for example static char x[10*1024*1024]; is bad, while static char *x = malloc(10*1024*1024) is fine.
if (num >= 10*1024*1024) warnOnce('warning: very large fixed-size structural type: ' + type + ' - can you reduce it? (compilation may be slow)');
@@ -945,6 +930,7 @@ function analyzer(data, sidePass) {
fields: range(num).map(function() { return subType }),
lineNum: '?'
};
+ newTypes[nonPointing] = 1;
// Also add a |[0 x type]| type
var zerod = '[0 x ' + subType + ']';
if (!Types.types[zerod]) {
@@ -953,6 +939,7 @@ function analyzer(data, sidePass) {
fields: [subType, subType], // Two, so we get the flatFactor right. We care about the flatFactor, not the size here
lineNum: '?'
};
+ newTypes[zerod] = 1;
}
return;
}
@@ -983,6 +970,7 @@ function analyzer(data, sidePass) {
packed: packed,
lineNum: '?'
};
+ newTypes[type] = 1;
return;
}
@@ -994,251 +982,243 @@ function analyzer(data, sidePass) {
flatSize: 1,
lineNum: '?'
};
+ newTypes[type] = 1;
}
- function addType(type, data) {
- addTypeInternal(type, data);
+ function addType(type) {
+ addTypeInternal(type);
if (QUANTUM_SIZE === 1) {
Types.flipTypes();
- addTypeInternal(type, data);
+ addTypeInternal(type);
Types.flipTypes();
}
}
// Typevestigator
- substrate.addActor('Typevestigator', {
- processItem: function(data) {
- if (sidePass) { // Do not investigate in the main pass - it is only valid to start to do so in the first side pass,
- // which handles type definitions, and later. Doing so before the first side pass will result in
- // making bad guesses about types which are actually defined
- for (var type in Types.needAnalysis) {
- if (type) addType(type, data);
- }
- Types.needAnalysis = {};
+ function typevestigator() {
+ if (sidePass) { // Do not investigate in the main pass - it is only valid to start to do so in the first side pass,
+ // which handles type definitions, and later. Doing so before the first side pass will result in
+ // making bad guesses about types which are actually defined
+ for (var type in Types.needAnalysis) {
+ if (type) addType(type);
}
- this.forwardItem(data, 'Typeanalyzer');
+ Types.needAnalysis = {};
}
- });
+ }
// Type analyzer
- substrate.addActor('Typeanalyzer', {
- processItem: function analyzeTypes(item, fatTypes) {
- var types = Types.types;
-
- // 'fields' is the raw list of LLVM fields. However, we embed
- // child structures into parent structures, basically like C.
- // So { int, { int, int }, int } would be represented as
- // an Array of 4 ints. getelementptr on the parent would take
- // values 0, 1, 2, where 2 is the entire middle structure.
- // We also need to be careful with getelementptr to child
- // structures - we return a pointer to the same slab, just
- // a different offset. Likewise, need to be careful for
- // getelementptr of 2 (the last int) - it's real index is 4.
- // The benefit of this approach is inheritance -
- // { { ancestor } , etc. } = descendant
- // In this case it is easy to bitcast ancestor to descendant
- // pointers - nothing needs to be done. If the ancestor were
- // a new slab, it would need some pointer to the outer one
- // for casting in that direction.
- // TODO: bitcasts of non-inheritance cases of embedding (not at start)
- var more = true;
- while (more) {
- more = false;
- for (var typeName in types) {
- var type = types[typeName];
- if (type.flatIndexes) continue;
- var ready = true;
- type.fields.forEach(function(field) {
- if (isStructType(field)) {
- if (!types[field]) {
- addType(field, item);
+ function analyzeTypes(fatTypes) {
+ var types = Types.types;
+
+ // 'fields' is the raw list of LLVM fields. However, we embed
+ // child structures into parent structures, basically like C.
+ // So { int, { int, int }, int } would be represented as
+ // an Array of 4 ints. getelementptr on the parent would take
+ // values 0, 1, 2, where 2 is the entire middle structure.
+ // We also need to be careful with getelementptr to child
+ // structures - we return a pointer to the same slab, just
+ // a different offset. Likewise, need to be careful for
+ // getelementptr of 2 (the last int) - it's real index is 4.
+ // The benefit of this approach is inheritance -
+ // { { ancestor } , etc. } = descendant
+ // In this case it is easy to bitcast ancestor to descendant
+ // pointers - nothing needs to be done. If the ancestor were
+ // a new slab, it would need some pointer to the outer one
+ // for casting in that direction.
+ // TODO: bitcasts of non-inheritance cases of embedding (not at start)
+ var more = true;
+ while (more) {
+ more = false;
+ for (var typeName in newTypes) {
+ var type = types[typeName];
+ if (type.flatIndexes) continue;
+ var ready = true;
+ type.fields.forEach(function(field) {
+ if (isStructType(field)) {
+ if (!types[field]) {
+ addType(field);
+ ready = false;
+ } else {
+ if (!types[field].flatIndexes) {
+ newTypes[field] = 1;
ready = false;
- } else {
- if (!types[field].flatIndexes) {
- ready = false;
- }
}
}
- });
- if (!ready) {
- more = true;
- continue;
}
-
- Runtime.calculateStructAlignment(type);
-
- if (dcheck('types')) dprint('type (fat=' + !!fatTypes + '): ' + type.name_ + ' : ' + JSON.stringify(type.fields));
- if (dcheck('types')) dprint(' has final size of ' + type.flatSize + ', flatting: ' + type.needsFlattening + ' ? ' + (type.flatFactor ? type.flatFactor : JSON.stringify(type.flatIndexes)));
+ });
+ if (!ready) {
+ more = true;
+ continue;
}
- }
- if (QUANTUM_SIZE === 1 && !fatTypes) {
- Types.flipTypes();
- // Fake a quantum size of 4 for fat types. TODO: Might want non-4 for some reason?
- var trueQuantumSize = QUANTUM_SIZE;
- Runtime.QUANTUM_SIZE = 4;
- analyzeTypes(item, true);
- Runtime.QUANTUM_SIZE = trueQuantumSize;
- Types.flipTypes();
- }
+ Runtime.calculateStructAlignment(type);
- if (!fatTypes) {
- this.forwardItem(item, 'VariableAnalyzer');
+ if (dcheck('types')) dprint('type (fat=' + !!fatTypes + '): ' + type.name_ + ' : ' + JSON.stringify(type.fields));
+ if (dcheck('types')) dprint(' has final size of ' + type.flatSize + ', flatting: ' + type.needsFlattening + ' ? ' + (type.flatFactor ? type.flatFactor : JSON.stringify(type.flatIndexes)));
}
}
- });
+
+ if (QUANTUM_SIZE === 1 && !fatTypes) {
+ Types.flipTypes();
+ // Fake a quantum size of 4 for fat types. TODO: Might want non-4 for some reason?
+ var trueQuantumSize = QUANTUM_SIZE;
+ Runtime.QUANTUM_SIZE = 4;
+ analyzeTypes(true);
+ Runtime.QUANTUM_SIZE = trueQuantumSize;
+ Types.flipTypes();
+ }
+
+ newTypes = null;
+ }
// Variable analyzer
- substrate.addActor('VariableAnalyzer', {
- processItem: function(item) {
- // Globals
-
- var old = item.globalVariables;
- item.globalVariables = {};
- old.forEach(function(variable) {
- variable.impl = 'emulated'; // All global variables are emulated, for now. Consider optimizing later if useful
- item.globalVariables[variable.ident] = variable;
+ function variableAnalyzer() {
+ // Globals
+
+ var old = item.globalVariables;
+ item.globalVariables = {};
+ old.forEach(function(variable) {
+ variable.impl = 'emulated'; // All global variables are emulated, for now. Consider optimizing later if useful
+ item.globalVariables[variable.ident] = variable;
+ });
+
+ // Function locals
+
+ item.functions.forEach(function(func) {
+ func.variables = {};
+
+ // LLVM is SSA, so we always have a single assignment/write. We care about
+ // the reads/other uses.
+
+ // Function parameters
+ func.params.forEach(function(param) {
+ if (param.intertype !== 'varargs') {
+ if (func.variables[param.ident]) warn('cannot have duplicate variable names: ' + param.ident); // toNiceIdent collisions?
+ func.variables[param.ident] = {
+ ident: param.ident,
+ type: param.type,
+ origin: 'funcparam',
+ lineNum: func.lineNum,
+ rawLinesIndex: -1
+ };
+ }
});
- // Function locals
-
- item.functions.forEach(function(func) {
- func.variables = {};
-
- // LLVM is SSA, so we always have a single assignment/write. We care about
- // the reads/other uses.
-
- // Function parameters
- func.params.forEach(function(param) {
- if (param.intertype !== 'varargs') {
- if (func.variables[param.ident]) warn('cannot have duplicate variable names: ' + param.ident); // toNiceIdent collisions?
- func.variables[param.ident] = {
- ident: param.ident,
- type: param.type,
- origin: 'funcparam',
- lineNum: func.lineNum,
- rawLinesIndex: -1
- };
+ // Normal variables
+ func.lines.forEach(function(item, i) {
+ if (item.assignTo) {
+ if (func.variables[item.assignTo]) warn('cannot have duplicate variable names: ' + item.assignTo); // toNiceIdent collisions?
+ var variable = func.variables[item.assignTo] = {
+ ident: item.assignTo,
+ type: item.type,
+ origin: item.intertype,
+ lineNum: item.lineNum,
+ rawLinesIndex: i
+ };
+ if (variable.origin === 'alloca') {
+ variable.allocatedNum = item.allocatedNum;
}
- });
-
- // Normal variables
- func.lines.forEach(function(item, i) {
- if (item.assignTo) {
- if (func.variables[item.assignTo]) warn('cannot have duplicate variable names: ' + item.assignTo); // toNiceIdent collisions?
- var variable = func.variables[item.assignTo] = {
- ident: item.assignTo,
- type: item.type,
- origin: item.intertype,
- lineNum: item.lineNum,
- rawLinesIndex: i
- };
- if (variable.origin === 'alloca') {
- variable.allocatedNum = item.allocatedNum;
- }
- if (variable.origin === 'call') {
- variable.type = getReturnType(variable.type);
- }
+ if (variable.origin === 'call') {
+ variable.type = getReturnType(variable.type);
}
- });
+ }
+ });
- if (QUANTUM_SIZE === 1) {
- // Second pass over variables - notice when types are crossed by bitcast
-
- func.lines.forEach(function(item) {
- if (item.assignTo && item.intertype === 'bitcast') {
- // bitcasts are unique in that they convert one pointer to another. We
- // sometimes need to know the original type of a pointer, so we save that.
- //
- // originalType is the type this variable is created from
- // derivedTypes are the types that this variable is cast into
- func.variables[item.assignTo].originalType = item.type2;
-
- if (!isNumber(item.assignTo)) {
- if (!func.variables[item.assignTo].derivedTypes) {
- func.variables[item.assignTo].derivedTypes = [];
- }
- func.variables[item.assignTo].derivedTypes.push(item.type);
+ if (QUANTUM_SIZE === 1) {
+ // Second pass over variables - notice when types are crossed by bitcast
+
+ func.lines.forEach(function(item) {
+ if (item.assignTo && item.intertype === 'bitcast') {
+ // bitcasts are unique in that they convert one pointer to another. We
+ // sometimes need to know the original type of a pointer, so we save that.
+ //
+ // originalType is the type this variable is created from
+ // derivedTypes are the types that this variable is cast into
+ func.variables[item.assignTo].originalType = item.type2;
+
+ if (!isNumber(item.assignTo)) {
+ if (!func.variables[item.assignTo].derivedTypes) {
+ func.variables[item.assignTo].derivedTypes = [];
}
+ func.variables[item.assignTo].derivedTypes.push(item.type);
}
- });
- }
+ }
+ });
+ }
- // Analyze variable uses
+ // Analyze variable uses
- function analyzeVariableUses() {
- dprint('vars', 'Analyzing variables for ' + func.ident + '\n');
+ function analyzeVariableUses() {
+ dprint('vars', 'Analyzing variables for ' + func.ident + '\n');
- for (vname in func.variables) {
- var variable = func.variables[vname];
+ for (vname in func.variables) {
+ var variable = func.variables[vname];
- // Whether the value itself is used. For an int, always yes. For a pointer,
- // we might never use the pointer's value - we might always just store to it /
- // read from it. If so, then we can optimize away the pointer.
- variable.hasValueTaken = false;
+ // Whether the value itself is used. For an int, always yes. For a pointer,
+ // we might never use the pointer's value - we might always just store to it /
+ // read from it. If so, then we can optimize away the pointer.
+ variable.hasValueTaken = false;
- variable.pointingLevels = pointingLevels(variable.type);
+ variable.pointingLevels = pointingLevels(variable.type);
- variable.uses = 0;
- }
+ variable.uses = 0;
+ }
- // TODO: improve the analysis precision. bitcast, for example, means we take the value, but perhaps we only use it to load/store
- var inNoop = 0;
- func.lines.forEach(function(line) {
- walkInterdata(line, function(item) {
- if (item.intertype == 'noop') inNoop++;
- if (!inNoop) {
- if (item.ident in func.variables) {
- func.variables[item.ident].uses++;
-
- if (item.intertype != 'load' && item.intertype != 'store') {
- func.variables[item.ident].hasValueTaken = true;
- }
+ // TODO: improve the analysis precision. bitcast, for example, means we take the value, but perhaps we only use it to load/store
+ var inNoop = 0;
+ func.lines.forEach(function(line) {
+ walkInterdata(line, function(item) {
+ if (item.intertype == 'noop') inNoop++;
+ if (!inNoop) {
+ if (item.ident in func.variables) {
+ func.variables[item.ident].uses++;
+
+ if (item.intertype != 'load' && item.intertype != 'store') {
+ func.variables[item.ident].hasValueTaken = true;
}
}
- }, function(item) {
- if (item.intertype == 'noop') inNoop--;
- });
+ }
+ }, function(item) {
+ if (item.intertype == 'noop') inNoop--;
});
+ });
- //if (dcheck('vars')) dprint('analyzed variables: ' + dump(func.variables));
- }
-
- analyzeVariableUses();
-
- // Decision time
+ //if (dcheck('vars')) dprint('analyzed variables: ' + dump(func.variables));
+ }
- for (vname in func.variables) {
- var variable = func.variables[vname];
- var pointedType = pointingLevels(variable.type) > 0 ? removePointing(variable.type) : null;
- if (variable.origin == 'getelementptr') {
- // Use our implementation that emulates pointers etc.
- // TODO Can we perhaps nativize some of these? However to do so, we need to discover their
- // true types; we have '?' for them now, as they cannot be discovered in the intertyper.
- variable.impl = VAR_EMULATED;
- } else if (variable.origin == 'funcparam') {
- variable.impl = VAR_EMULATED;
- } else if (variable.type == 'i64*' && USE_TYPED_ARRAYS == 2) {
- variable.impl = VAR_EMULATED;
- } else if (MICRO_OPTS && variable.pointingLevels === 0) {
- // A simple int value, can be implemented as a native variable
- variable.impl = VAR_NATIVE;
- } else if (MICRO_OPTS && variable.origin === 'alloca' && !variable.hasValueTaken &&
- variable.allocatedNum === 1 &&
- (Runtime.isNumberType(pointedType) || Runtime.isPointerType(pointedType))) {
- // A pointer to a value which is only accessible through this pointer. Basically
- // a local value on the stack, which nothing fancy is done on. So we can
- // optimize away the pointing altogether, and just have a native variable
- variable.impl = VAR_NATIVIZED;
- } else {
- variable.impl = VAR_EMULATED;
- }
- if (dcheck('vars')) dprint('// var ' + vname + ': ' + JSON.stringify(variable));
+ analyzeVariableUses();
+
+ // Decision time
+
+ for (vname in func.variables) {
+ var variable = func.variables[vname];
+ var pointedType = pointingLevels(variable.type) > 0 ? removePointing(variable.type) : null;
+ if (variable.origin == 'getelementptr') {
+ // Use our implementation that emulates pointers etc.
+ // TODO Can we perhaps nativize some of these? However to do so, we need to discover their
+ // true types; we have '?' for them now, as they cannot be discovered in the intertyper.
+ variable.impl = VAR_EMULATED;
+ } else if (variable.origin == 'funcparam') {
+ variable.impl = VAR_EMULATED;
+ } else if (variable.type == 'i64*' && USE_TYPED_ARRAYS == 2) {
+ variable.impl = VAR_EMULATED;
+ } else if (MICRO_OPTS && variable.pointingLevels === 0) {
+ // A simple int value, can be implemented as a native variable
+ variable.impl = VAR_NATIVE;
+ } else if (MICRO_OPTS && variable.origin === 'alloca' && !variable.hasValueTaken &&
+ variable.allocatedNum === 1 &&
+ (Runtime.isNumberType(pointedType) || Runtime.isPointerType(pointedType))) {
+ // A pointer to a value which is only accessible through this pointer. Basically
+ // a local value on the stack, which nothing fancy is done on. So we can
+ // optimize away the pointing altogether, and just have a native variable
+ variable.impl = VAR_NATIVIZED;
+ } else {
+ variable.impl = VAR_EMULATED;
}
- });
- this.forwardItem(item, 'Signalyzer');
- }
- });
+ if (dcheck('vars')) dprint('// var ' + vname + ': ' + JSON.stringify(variable));
+ }
+ });
+ }
// Sign analyzer
//
@@ -1251,214 +1231,208 @@ function analyzer(data, sidePass) {
// to see where it is used. We only care about mathops, since only they
// need signs.
//
- substrate.addActor('Signalyzer', {
- processItem: function(item) {
- this.forwardItem(item, 'QuantumFixer');
- if (USE_TYPED_ARRAYS != 2 || CORRECT_SIGNS == 1) return;
-
- function seekIdent(item, obj) {
- if (item.ident === obj.ident) {
- obj.found++;
- }
+ function signalyzer() {
+ if (USE_TYPED_ARRAYS != 2 || CORRECT_SIGNS == 1) return;
+
+ function seekIdent(item, obj) {
+ if (item.ident === obj.ident) {
+ obj.found++;
}
+ }
- function seekMathop(item, obj) {
- if (item.intertype === 'mathop' && obj.found && !obj.decided) {
- if (isUnsignedOp(item.op, item.variant)) {
- obj.unsigned++;
- } else {
- obj.signed++;
- }
+ function seekMathop(item, obj) {
+ if (item.intertype === 'mathop' && obj.found && !obj.decided) {
+ if (isUnsignedOp(item.op, item.variant)) {
+ obj.unsigned++;
+ } else {
+ obj.signed++;
}
}
+ }
- item.functions.forEach(function(func) {
- func.lines.forEach(function(line, i) {
- if (line.intertype === 'load') {
- // Floats have no concept of signedness. Mark them as 'signed', which is the default, for which we do nothing
- if (line.type in Runtime.FLOAT_TYPES) {
- line.unsigned = false;
- return;
- }
- // Booleans are always unsigned
- var data = func.variables[line.assignTo];
- if (data.type === 'i1') {
- line.unsigned = true;
- return;
- }
-
- var total = data.uses;
- if (total === 0) return;
- var obj = { ident: line.assignTo, found: 0, unsigned: 0, signed: 0, total: total };
- // in loops with phis, we can also be used *before* we are defined
- var j = i-1, k = i+1;
- while(1) {
- assert(j >= 0 || k < func.lines.length, 'Signalyzer ran out of space to look for sign indications for line ' + line.lineNum);
- if (j >= 0 && walkInterdata(func.lines[j], seekIdent, seekMathop, obj)) break;
- if (k < func.lines.length && walkInterdata(func.lines[k], seekIdent, seekMathop, obj)) break;
- if (obj.total && obj.found >= obj.total) break; // see comment below
- j -= 1;
- k += 1;
- }
+ item.functions.forEach(function(func) {
+ func.lines.forEach(function(line, i) {
+ if (line.intertype === 'load') {
+ // Floats have no concept of signedness. Mark them as 'signed', which is the default, for which we do nothing
+ if (line.type in Runtime.FLOAT_TYPES) {
+ line.unsigned = false;
+ return;
+ }
+ // Booleans are always unsigned
+ var data = func.variables[line.assignTo];
+ if (data.type === 'i1') {
+ line.unsigned = true;
+ return;
+ }
- // unsigned+signed might be < total, since the same ident can appear multiple times in the same mathop.
- // found can actually be > total, since we currently have the same ident in a GEP (see cubescript test)
- // in the GEP item, and a child item (we have the ident copied onto the GEP item as a convenience).
- // probably not a bug-causer, but FIXME. see also a reference to this above
- // we also leave the loop above potentially early due to this. otherwise, though, we end up scanning the
- // entire function in some cases which is very slow
- assert(obj.found >= obj.total, 'Could not Signalyze line ' + line.lineNum);
- line.unsigned = obj.unsigned > 0;
- dprint('vars', 'Signalyzer: ' + line.assignTo + ' has unsigned == ' + line.unsigned + ' (line ' + line.lineNum + ')');
+ var total = data.uses;
+ if (total === 0) return;
+ var obj = { ident: line.assignTo, found: 0, unsigned: 0, signed: 0, total: total };
+ // in loops with phis, we can also be used *before* we are defined
+ var j = i-1, k = i+1;
+ while(1) {
+ assert(j >= 0 || k < func.lines.length, 'Signalyzer ran out of space to look for sign indications for line ' + line.lineNum);
+ if (j >= 0 && walkInterdata(func.lines[j], seekIdent, seekMathop, obj)) break;
+ if (k < func.lines.length && walkInterdata(func.lines[k], seekIdent, seekMathop, obj)) break;
+ if (obj.total && obj.found >= obj.total) break; // see comment below
+ j -= 1;
+ k += 1;
}
- });
+
+ // unsigned+signed might be < total, since the same ident can appear multiple times in the same mathop.
+ // found can actually be > total, since we currently have the same ident in a GEP (see cubescript test)
+ // in the GEP item, and a child item (we have the ident copied onto the GEP item as a convenience).
+ // probably not a bug-causer, but FIXME. see also a reference to this above
+ // we also leave the loop above potentially early due to this. otherwise, though, we end up scanning the
+ // entire function in some cases which is very slow
+ assert(obj.found >= obj.total, 'Could not Signalyze line ' + line.lineNum);
+ line.unsigned = obj.unsigned > 0;
+ dprint('vars', 'Signalyzer: ' + line.assignTo + ' has unsigned == ' + line.unsigned + ' (line ' + line.lineNum + ')');
+ }
});
- }
- });
+ });
+ }
// Quantum fixer
//
// See settings.js for the meaning of QUANTUM_SIZE. The issue we fix here is,
// to correct the .ll assembly code so that things work with QUANTUM_SIZE=1.
//
- substrate.addActor('QuantumFixer', {
- processItem: function(item) {
- this.forwardItem(item, 'LabelAnalyzer');
- if (QUANTUM_SIZE !== 1) return;
-
- // ptrs: the indexes of parameters that are pointers, whose originalType is what we want
- // bytes: the index of the 'bytes' parameter
- // TODO: malloc, realloc?
- var FIXABLE_CALLS = {
- 'memcpy': { ptrs: [0,1], bytes: 2 },
- 'memmove': { ptrs: [0,1], bytes: 2 },
- 'memset': { ptrs: [0], bytes: 2 },
- 'qsort': { ptrs: [0], bytes: 2 }
- };
+ function quantumFixer() {
+ if (QUANTUM_SIZE !== 1) return;
+
+ // ptrs: the indexes of parameters that are pointers, whose originalType is what we want
+ // bytes: the index of the 'bytes' parameter
+ // TODO: malloc, realloc?
+ var FIXABLE_CALLS = {
+ 'memcpy': { ptrs: [0,1], bytes: 2 },
+ 'memmove': { ptrs: [0,1], bytes: 2 },
+ 'memset': { ptrs: [0], bytes: 2 },
+ 'qsort': { ptrs: [0], bytes: 2 }
+ };
- function getSize(types, type, fat) {
- if (types[type]) return types[type].flatSize;
- if (fat) {
- Runtime.QUANTUM_SIZE = 4;
- }
- var ret = Runtime.getNativeTypeSize(type);
- if (fat) {
- Runtime.QUANTUM_SIZE = 1;
- }
- return ret;
+ function getSize(types, type, fat) {
+ if (types[type]) return types[type].flatSize;
+ if (fat) {
+ Runtime.QUANTUM_SIZE = 4;
}
-
- function getFlatIndexes(types, type) {
- if (types[type]) return types[type].flatIndexes;
- return [0];
+ var ret = Runtime.getNativeTypeSize(type);
+ if (fat) {
+ Runtime.QUANTUM_SIZE = 1;
}
+ return ret;
+ }
- item.functions.forEach(function(func) {
- function getOriginalType(param) {
- function get() {
- if (param.intertype === 'value' && !isNumber(param.ident)) {
- if (func.variables[param.ident]) {
- return func.variables[param.ident].originalType || null;
- } else {
- return item.globalVariables[param.ident].originalType;
- }
- } else if (param.intertype === 'bitcast') {
- return param.params[0].type;
- } else if (param.intertype === 'getelementptr') {
- if (param.params[0].type[0] === '[') return param.params[0].type;
- }
- return null;
- }
- var ret = get();
- if (ret && ret[0] === '[') {
- var check = /^\[(\d+)\ x\ (.*)\]\*$/.exec(ret);
- assert(check);
- ret = check[2] + '*';
- }
- return ret;
- }
+ function getFlatIndexes(types, type) {
+ if (types[type]) return types[type].flatIndexes;
+ return [0];
+ }
- func.lines.forEach(function(line) {
- // Call
- if (line.intertype === 'call') {
- var funcIdent = LibraryManager.getRootIdent(line.ident.substr(1));
- var fixData = FIXABLE_CALLS[funcIdent];
- if (!fixData) return;
- var ptrs = fixData.ptrs.map(function(ptr) { return line.params[ptr] });
- var bytes = line.params[fixData.bytes].ident;
-
- // Only consider original types. This assumes memcpy always has pointers bitcast to i8*
- var originalTypes = ptrs.map(getOriginalType);
- for (var i = 0; i < originalTypes.length; i++) {
- if (!originalTypes[i]) return;
- }
- originalTypes = originalTypes.map(function(type) { return removePointing(type) });
- var sizes = originalTypes.map(function(type) { return getSize(Types.types, type) });
- var fatSizes = originalTypes.map(function(type) { return getSize(Types.fatTypes, type, true) });
- // The sizes may not be identical, if we copy a descendant class into a parent class. We use
- // the smaller size in that case. However, this may also be a bug, it is hard to tell, hence a warning
- warn(dedup(sizes).length === 1, 'All sizes should probably be identical here: ' + dump(originalTypes) + ':' + dump(sizes) + ':' +
- line.lineNum);
- warn(dedup(fatSizes).length === 1, 'All fat sizes should probably be identical here: ' + dump(originalTypes) + ':' + dump(sizes) + ':' +
- line.lineNum);
- var size = Math.min.apply(null, sizes);
- var fatSize = Math.min.apply(null, fatSizes);
- if (isNumber(bytes)) {
- // Figure out how much to copy.
- var fixedBytes;
- if (bytes % fatSize === 0) {
- fixedBytes = size*(bytes/fatSize);
- } else if (fatSize % bytes === 0 && size % (fatSize/bytes) === 0) {
- // Assume this is a simple array. XXX We can be wrong though! See next TODO
- fixedBytes = size/(fatSize/bytes);
- } else {
- // Just part of a structure. Align them to see how many fields. Err on copying more.
- // TODO: properly generate a complete structure, including nesteds, and calculate on that
- var flatIndexes = getFlatIndexes(Types.types, originalTypes[0]).concat(size);
- var fatFlatIndexes = getFlatIndexes(Types.fatTypes, originalTypes[0]).concat(fatSize);
- var index = 0;
- var left = bytes;
- fixedBytes = 0;
- while (left > 0) {
- left -= fatFlatIndexes[index+1] - fatFlatIndexes[index]; // note: we copy the alignment bytes too, which is unneeded
- fixedBytes += flatIndexes[index+1] - flatIndexes[index];
- }
- }
- line.params[fixData.bytes].ident = fixedBytes;
+ item.functions.forEach(function(func) {
+ function getOriginalType(param) {
+ function get() {
+ if (param.intertype === 'value' && !isNumber(param.ident)) {
+ if (func.variables[param.ident]) {
+ return func.variables[param.ident].originalType || null;
} else {
- line.params[fixData.bytes].intertype = 'jsvalue';
- // We have an assertion in library::memcpy() that this is round
- line.params[fixData.bytes].ident = size + '*(' + bytes + '/' + fatSize + ')';
+ return item.globalVariables[param.ident].originalType;
}
+ } else if (param.intertype === 'bitcast') {
+ return param.params[0].type;
+ } else if (param.intertype === 'getelementptr') {
+ if (param.params[0].type[0] === '[') return param.params[0].type;
}
- });
- });
+ return null;
+ }
+ var ret = get();
+ if (ret && ret[0] === '[') {
+ var check = /^\[(\d+)\ x\ (.*)\]\*$/.exec(ret);
+ assert(check);
+ ret = check[2] + '*';
+ }
+ return ret;
+ }
- // 2nd part - fix hardcoded constant offsets in global constants
- values(item.globalVariables).forEach(function(variable) {
- function recurse(item) {
- if (item.contents) {
- item.contents.forEach(recurse);
- } else if (item.intertype === 'getelementptr' && item.params[0].intertype === 'bitcast' && item.params[0].type === 'i8*') {
- var originalType = removePointing(item.params[0].params[0].type);
- var fatSize = getSize(Types.fatTypes, originalType, true);
- var slimSize = getSize(Types.types, originalType, false);
- assert(fatSize % slimSize === 0);
- item.params.slice(1).forEach(function(param) {
- if (param.intertype === 'value' && isNumber(param.ident)) {
- var corrected = parseInt(param.ident)/(fatSize/slimSize);
- assert(corrected % 1 === 0);
- param.ident = corrected.toString();
+ func.lines.forEach(function(line) {
+ // Call
+ if (line.intertype === 'call') {
+ var funcIdent = LibraryManager.getRootIdent(line.ident.substr(1));
+ var fixData = FIXABLE_CALLS[funcIdent];
+ if (!fixData) return;
+ var ptrs = fixData.ptrs.map(function(ptr) { return line.params[ptr] });
+ var bytes = line.params[fixData.bytes].ident;
+
+ // Only consider original types. This assumes memcpy always has pointers bitcast to i8*
+ var originalTypes = ptrs.map(getOriginalType);
+ for (var i = 0; i < originalTypes.length; i++) {
+ if (!originalTypes[i]) return;
+ }
+ originalTypes = originalTypes.map(function(type) { return removePointing(type) });
+ var sizes = originalTypes.map(function(type) { return getSize(Types.types, type) });
+ var fatSizes = originalTypes.map(function(type) { return getSize(Types.fatTypes, type, true) });
+ // The sizes may not be identical, if we copy a descendant class into a parent class. We use
+ // the smaller size in that case. However, this may also be a bug, it is hard to tell, hence a warning
+ warn(dedup(sizes).length === 1, 'All sizes should probably be identical here: ' + dump(originalTypes) + ':' + dump(sizes) + ':' +
+ line.lineNum);
+ warn(dedup(fatSizes).length === 1, 'All fat sizes should probably be identical here: ' + dump(originalTypes) + ':' + dump(sizes) + ':' +
+ line.lineNum);
+ var size = Math.min.apply(null, sizes);
+ var fatSize = Math.min.apply(null, fatSizes);
+ if (isNumber(bytes)) {
+ // Figure out how much to copy.
+ var fixedBytes;
+ if (bytes % fatSize === 0) {
+ fixedBytes = size*(bytes/fatSize);
+ } else if (fatSize % bytes === 0 && size % (fatSize/bytes) === 0) {
+ // Assume this is a simple array. XXX We can be wrong though! See next TODO
+ fixedBytes = size/(fatSize/bytes);
+ } else {
+ // Just part of a structure. Align them to see how many fields. Err on copying more.
+ // TODO: properly generate a complete structure, including nesteds, and calculate on that
+ var flatIndexes = getFlatIndexes(Types.types, originalTypes[0]).concat(size);
+ var fatFlatIndexes = getFlatIndexes(Types.fatTypes, originalTypes[0]).concat(fatSize);
+ var index = 0;
+ var left = bytes;
+ fixedBytes = 0;
+ while (left > 0) {
+ left -= fatFlatIndexes[index+1] - fatFlatIndexes[index]; // note: we copy the alignment bytes too, which is unneeded
+ fixedBytes += flatIndexes[index+1] - flatIndexes[index];
}
- });
- } else if (item.params) {
- item.params.forEach(recurse);
+ }
+ line.params[fixData.bytes].ident = fixedBytes;
+ } else {
+ line.params[fixData.bytes].intertype = 'jsvalue';
+ // We have an assertion in library::memcpy() that this is round
+ line.params[fixData.bytes].ident = size + '*(' + bytes + '/' + fatSize + ')';
}
}
- if (!variable.external && variable.value) recurse(variable.value);
});
- }
- });
+ });
+
+ // 2nd part - fix hardcoded constant offsets in global constants
+ values(item.globalVariables).forEach(function(variable) {
+ function recurse(item) {
+ if (item.contents) {
+ item.contents.forEach(recurse);
+ } else if (item.intertype === 'getelementptr' && item.params[0].intertype === 'bitcast' && item.params[0].type === 'i8*') {
+ var originalType = removePointing(item.params[0].params[0].type);
+ var fatSize = getSize(Types.fatTypes, originalType, true);
+ var slimSize = getSize(Types.types, originalType, false);
+ assert(fatSize % slimSize === 0);
+ item.params.slice(1).forEach(function(param) {
+ if (param.intertype === 'value' && isNumber(param.ident)) {
+ var corrected = parseInt(param.ident)/(fatSize/slimSize);
+ assert(corrected % 1 === 0);
+ param.ident = corrected.toString();
+ }
+ });
+ } else if (item.params) {
+ item.params.forEach(recurse);
+ }
+ }
+ if (!variable.external && variable.value) recurse(variable.value);
+ });
+ }
function operateOnLabels(line, func) {
function process(item, id) {
@@ -1477,268 +1451,260 @@ function analyzer(data, sidePass) {
}
// Label analyzer
- substrate.addActor('LabelAnalyzer', {
- processItem: function(item) {
- item.functions.forEach(function(func) {
- func.labelsDict = {};
- func.labelIds = {};
- func.labelIdsInverse = {};
- func.labelIdCounter = 1;
- func.labels.forEach(function(label) {
- if (!(label.ident in func.labelIds)) {
- func.labelIds[label.ident] = func.labelIdCounter++;
- func.labelIdsInverse[func.labelIdCounter-1] = label.ident;
- }
- });
- var entryIdent = func.labels[0].ident;
-
- // Minify label ids to numeric ids.
- func.labels.forEach(function(label) {
- label.ident = func.labelIds[label.ident];
- label.lines.forEach(function(line) {
- operateOnLabels(line, function(item, id) {
- item[id] = func.labelIds[item[id]].toString(); // strings, because we will append as we process
- });
+ function labelAnalyzer() {
+ item.functions.forEach(function(func) {
+ func.labelsDict = {};
+ func.labelIds = {};
+ func.labelIdsInverse = {};
+ func.labelIdCounter = 1;
+ func.labels.forEach(function(label) {
+ if (!(label.ident in func.labelIds)) {
+ func.labelIds[label.ident] = func.labelIdCounter++;
+ func.labelIdsInverse[func.labelIdCounter-1] = label.ident;
+ }
+ });
+ var entryIdent = func.labels[0].ident;
+
+ // Minify label ids to numeric ids.
+ func.labels.forEach(function(label) {
+ label.ident = func.labelIds[label.ident];
+ label.lines.forEach(function(line) {
+ operateOnLabels(line, function(item, id) {
+ item[id] = func.labelIds[item[id]].toString(); // strings, because we will append as we process
});
});
+ });
- func.labels.forEach(function(label) {
- func.labelsDict[label.ident] = label;
- });
+ func.labels.forEach(function(label) {
+ func.labelsDict[label.ident] = label;
+ });
- // Correct phis
- func.labels.forEach(function(label) {
- label.lines.forEach(function(phi) {
- if (phi.intertype == 'phi') {
- for (var i = 0; i < phi.params.length; i++) {
- phi.params[i].label = func.labelIds[phi.params[i].label];
- if (VERBOSE && !phi.params[i].label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
- }
+ // Correct phis
+ func.labels.forEach(function(label) {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
+ for (var i = 0; i < phi.params.length; i++) {
+ phi.params[i].label = func.labelIds[phi.params[i].label];
+ if (VERBOSE && !phi.params[i].label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
}
- });
- });
-
- func.lines.forEach(function(line) {
- if (line.intertype == 'indirectbr') {
- func.forceEmulated = true;
}
});
+ });
- function getActualLabelId(labelId) {
- if (func.labelsDict[labelId]) return labelId;
- // If not present, it must be a surprisingly-named entry (or undefined behavior, in which case, still ok to use the entry)
- labelId = func.labelIds[entryIdent];
- assert(func.labelsDict[labelId]);
- return labelId;
+ func.lines.forEach(function(line) {
+ if (line.intertype == 'indirectbr') {
+ func.forceEmulated = true;
}
+ });
- // Basic longjmp support, see library.js setjmp/longjmp
- var setjmp = toNiceIdent('@setjmp');
- func.setjmpTable = null;
- for (var i = 0; i < func.labels.length; i++) {
- var label = func.labels[i];
- for (var j = 0; j < label.lines.length; j++) {
- var line = label.lines[j];
- if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
- // Add a new label
- var oldLabel = label.ident;
- var newLabel = func.labelIdCounter++;
- if (!func.setjmpTable) func.setjmpTable = [];
- func.setjmpTable.push({ oldLabel: oldLabel, newLabel: newLabel, assignTo: line.assignTo });
- func.labels.splice(i+1, 0, {
- intertype: 'label',
- ident: newLabel,
- lineNum: label.lineNum + 0.5,
- lines: label.lines.slice(j+1)
- });
- func.labelsDict[newLabel] = func.labels[i+1];
- label.lines = label.lines.slice(0, j+1);
- label.lines.push({
- intertype: 'branch',
- label: toNiceIdent(newLabel),
- lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this
- });
- // Correct phis
- func.labels.forEach(function(label) {
- label.lines.forEach(function(phi) {
- if (phi.intertype == 'phi') {
- for (var i = 0; i < phi.params.length; i++) {
- var sourceLabelId = getActualLabelId(phi.params[i].label);
- if (sourceLabelId == oldLabel) {
- phi.params[i].label = newLabel;
- }
+ function getActualLabelId(labelId) {
+ if (func.labelsDict[labelId]) return labelId;
+ // If not present, it must be a surprisingly-named entry (or undefined behavior, in which case, still ok to use the entry)
+ labelId = func.labelIds[entryIdent];
+ assert(func.labelsDict[labelId]);
+ return labelId;
+ }
+
+ // Basic longjmp support, see library.js setjmp/longjmp
+ var setjmp = toNiceIdent('@setjmp');
+ func.setjmpTable = null;
+ for (var i = 0; i < func.labels.length; i++) {
+ var label = func.labels[i];
+ for (var j = 0; j < label.lines.length; j++) {
+ var line = label.lines[j];
+ if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
+ // Add a new label
+ var oldLabel = label.ident;
+ var newLabel = func.labelIdCounter++;
+ if (!func.setjmpTable) func.setjmpTable = [];
+ func.setjmpTable.push({ oldLabel: oldLabel, newLabel: newLabel, assignTo: line.assignTo });
+ func.labels.splice(i+1, 0, {
+ intertype: 'label',
+ ident: newLabel,
+ lineNum: label.lineNum + 0.5,
+ lines: label.lines.slice(j+1)
+ });
+ func.labelsDict[newLabel] = func.labels[i+1];
+ label.lines = label.lines.slice(0, j+1);
+ label.lines.push({
+ intertype: 'branch',
+ label: toNiceIdent(newLabel),
+ lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this
+ });
+ // Correct phis
+ func.labels.forEach(function(label) {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
+ for (var i = 0; i < phi.params.length; i++) {
+ var sourceLabelId = getActualLabelId(phi.params[i].label);
+ if (sourceLabelId == oldLabel) {
+ phi.params[i].label = newLabel;
}
}
- });
+ }
});
- }
+ });
}
}
- if (func.setjmpTable) {
- func.forceEmulated = true;
- recomputeLines(func);
- }
-
- // Properly implement phis, by pushing them back into the branch
- // that leads to here. We will only have the |var| definition in this location.
+ }
+ if (func.setjmpTable) {
+ func.forceEmulated = true;
+ recomputeLines(func);
+ }
- // First, push phis back
- func.labels.forEach(function(label) {
- label.lines.forEach(function(phi) {
- if (phi.intertype == 'phi') {
- for (var i = 0; i < phi.params.length; i++) {
- var param = phi.params[i];
- 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];
- var lastLine = sourceLabel.lines.slice(-1)[0];
- assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
- if (!lastLine.phi) {
- lastLine.phi = true;
- assert(!lastLine.dependent);
- lastLine.dependent = {
- intertype: 'phiassigns',
- params: []
- };
+ // Properly implement phis, by pushing them back into the branch
+ // that leads to here. We will only have the |var| definition in this location.
+
+ // First, push phis back
+ func.labels.forEach(function(label) {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
+ for (var i = 0; i < phi.params.length; i++) {
+ var param = phi.params[i];
+ 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];
+ var lastLine = sourceLabel.lines.slice(-1)[0];
+ assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
+ if (!lastLine.phi) {
+ lastLine.phi = true;
+ assert(!lastLine.dependent);
+ lastLine.dependent = {
+ intertype: 'phiassigns',
+ params: []
};
- lastLine.dependent.params.push({
- intertype: 'phiassign',
- ident: phi.assignTo,
- value: param.value,
- targetLabel: label.ident
- });
- }
+ };
+ lastLine.dependent.params.push({
+ intertype: 'phiassign',
+ ident: phi.assignTo,
+ value: param.value,
+ targetLabel: label.ident
+ });
}
- // The assign to phi is now just a var
- phi.intertype = 'var';
- phi.ident = phi.assignTo;
- phi.assignTo = null;
}
- });
+ // The assign to phi is now just a var
+ phi.intertype = 'var';
+ phi.ident = phi.assignTo;
+ phi.assignTo = null;
+ }
});
+ });
- if (func.ident in NECESSARY_BLOCKADDRS) {
- Functions.blockAddresses[func.ident] = {};
- for (var needed in NECESSARY_BLOCKADDRS[func.ident]) {
- assert(needed in func.labelIds);
- Functions.blockAddresses[func.ident][needed] = func.labelIds[needed];
- }
+ if (func.ident in NECESSARY_BLOCKADDRS) {
+ Functions.blockAddresses[func.ident] = {};
+ for (var needed in NECESSARY_BLOCKADDRS[func.ident]) {
+ assert(needed in func.labelIds);
+ Functions.blockAddresses[func.ident][needed] = func.labelIds[needed];
}
- });
- this.forwardItem(item, 'StackAnalyzer');
- }
- });
+ }
+ });
+ }
// Stack analyzer - calculate the base stack usage
- substrate.addActor('StackAnalyzer', {
- processItem: function(data) {
- data.functions.forEach(function(func) {
- var lines = func.labels[0].lines;
- for (var i = 0; i < lines.length; i++) {
- var item = lines[i];
- if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break;
- item.allocatedSize = func.variables[item.assignTo].impl === VAR_EMULATED ?
- calcAllocatedSize(item.allocatedType)*item.allocatedNum: 0;
- if (USE_TYPED_ARRAYS === 2) {
- // We need to keep the stack aligned
- item.allocatedSize = Runtime.forceAlign(item.allocatedSize, Runtime.STACK_ALIGN);
- }
+ function stackAnalyzer() {
+ data.functions.forEach(function(func) {
+ var lines = func.labels[0].lines;
+ for (var i = 0; i < lines.length; i++) {
+ var item = lines[i];
+ if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break;
+ item.allocatedSize = func.variables[item.assignTo].impl === VAR_EMULATED ?
+ calcAllocatedSize(item.allocatedType)*item.allocatedNum: 0;
+ if (USE_TYPED_ARRAYS === 2) {
+ // We need to keep the stack aligned
+ item.allocatedSize = Runtime.forceAlign(item.allocatedSize, Runtime.STACK_ALIGN);
}
- var index = 0;
- for (var i = 0; i < lines.length; i++) {
- var item = lines[i];
- if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break;
- item.allocatedIndex = index;
- index += item.allocatedSize;
- delete item.allocatedSize;
- }
- func.initialStack = index;
- func.otherStackAllocations = false;
- while (func.initialStack == 0) { // one-time loop with possible abort in the middle
- // If there is no obvious need for stack management, perhaps we don't need it
- // (we try to optimize that way with SKIP_STACK_IN_SMALL). However,
- // we need to note if stack allocations other than initial allocs can happen here
- // If so, we need to rewind the stack when we leave.
-
- // By-value params are causes of additional allocas (although we could in theory make them normal allocas too)
- func.params.forEach(function(param) {
- if (param.byVal) {
- func.otherStackAllocations = true;
- }
- });
- if (func.otherStackAllocations) break;
+ }
+ var index = 0;
+ for (var i = 0; i < lines.length; i++) {
+ var item = lines[i];
+ if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break;
+ item.allocatedIndex = index;
+ index += item.allocatedSize;
+ delete item.allocatedSize;
+ }
+ func.initialStack = index;
+ func.otherStackAllocations = false;
+ while (func.initialStack == 0) { // one-time loop with possible abort in the middle
+ // If there is no obvious need for stack management, perhaps we don't need it
+ // (we try to optimize that way with SKIP_STACK_IN_SMALL). However,
+ // we need to note if stack allocations other than initial allocs can happen here
+ // If so, we need to rewind the stack when we leave.
+
+ // By-value params are causes of additional allocas (although we could in theory make them normal allocas too)
+ func.params.forEach(function(param) {
+ if (param.byVal) {
+ func.otherStackAllocations = true;
+ }
+ });
+ if (func.otherStackAllocations) break;
- // Allocas
- var finishedInitial = false;
+ // Allocas
+ var finishedInitial = false;
- lines = func.lines; // We need to consider all the function lines now, not just the first label
+ lines = func.lines; // We need to consider all the function lines now, not just the first label
- for (var i = 0; i < lines.length; i++) {
- var item = lines[i];
- if (!finishedInitial && (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum))) {
- finishedInitial = true;
- }
- if (item.intertype == 'alloca' && finishedInitial) {
- func.otherStackAllocations = true;
- break;
- }
+ for (var i = 0; i < lines.length; i++) {
+ var item = lines[i];
+ if (!finishedInitial && (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum))) {
+ finishedInitial = true;
}
- if (func.otherStackAllocations) break;
-
- // Varargs
- for (var i = 0; i < lines.length; i++) {
- var item = lines[i];
- if (item.intertype == 'call' && isVarArgsFunctionType(item.type)) {
- func.otherStackAllocations = true;
- break;
- }
+ if (item.intertype == 'alloca' && finishedInitial) {
+ func.otherStackAllocations = true;
+ break;
}
- if (func.otherStackAllocations) break;
+ }
+ if (func.otherStackAllocations) break;
- break;
+ // Varargs
+ for (var i = 0; i < lines.length; i++) {
+ var item = lines[i];
+ if (item.intertype == 'call' && isVarArgsFunctionType(item.type)) {
+ func.otherStackAllocations = true;
+ break;
+ }
}
- });
- this.forwardItem(data, 'Relooper');
- }
- });
+ if (func.otherStackAllocations) break;
- // ReLooper - reconstruct nice loops, as much as possible
- // This is now done in the jsify stage, using compiled relooper2
- substrate.addActor('Relooper', {
- processItem: function(item) {
- function finish() {
- item.__finalResult__ = true;
- return [item];
- }
- function makeBlock(labels, entries, labelsDict, forceEmulated) {
- if (labels.length == 0) return null;
- dprint('relooping', 'prelooping: ' + entries + ',' + labels.length + ' labels');
- assert(entries && entries[0]); // need at least 1 entry
-
- var emulated = {
- type: 'emulated',
- id: 'B',
- labels: labels,
- entries: entries.slice(0)
- };
- return emulated;
+ break;
}
- item.functions.forEach(function(func) {
- dprint('relooping', "// relooping function: " + func.ident);
- func.block = makeBlock(func.labels, [func.labels[0].ident], func.labelsDict, func.forceEmulated);
- });
+ });
+ }
- return finish();
+ // ReLooper - reconstruct nice loops, as much as possible
+ // This is now done in the jsify stage, using compiled relooper2
+ function relooper() {
+ function makeBlock(labels, entries, labelsDict, forceEmulated) {
+ if (labels.length == 0) return null;
+ dprint('relooping', 'prelooping: ' + entries + ',' + labels.length + ' labels');
+ assert(entries && entries[0]); // need at least 1 entry
+
+ var emulated = {
+ type: 'emulated',
+ id: 'B',
+ labels: labels,
+ entries: entries.slice(0)
+ };
+ return emulated;
}
- });
-
- // Data
- substrate.addItem({
- items: data
- }, 'Sorter');
+ item.functions.forEach(function(func) {
+ dprint('relooping', "// relooping function: " + func.ident);
+ func.block = makeBlock(func.labels, [func.labels[0].ident], func.labelsDict, func.forceEmulated);
+ });
+ }
- // Solve it
- return substrate.solve();
+ // main
+ castAway();
+ legalizer();
+ typevestigator();
+ analyzeTypes();
+ variableAnalyzer();
+ signalyzer();
+ quantumFixer();
+ labelAnalyzer();
+ stackAnalyzer();
+ relooper();
+
+ return item;
}
diff --git a/src/compiler.js b/src/compiler.js
index f7c6dd59..90060837 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -121,6 +121,8 @@ if (typeof print === 'undefined') {
// *** Environment setup code ***
+DEBUG_MEMORY = false;
+
// Basic utilities
load('utility.js');
@@ -211,15 +213,19 @@ C_DEFINES = temp.defines;
// Load compiler code
-load('framework.js');
load('modules.js');
load('parseTools.js');
load('intertyper.js');
load('analyzer.js');
load('jsifier.js');
-if (RELOOP) {
+if (phase == 'funcs' && RELOOP) { // XXX handle !singlePhase
RelooperModule = { TOTAL_MEMORY: ceilPowerOfTwo(2*RELOOPER_BUFFER_SIZE) };
- load(RELOOPER);
+ try {
+ load(RELOOPER);
+ } catch(e) {
+ printErr('cannot load relooper at ' + RELOOPER + ' : ' + e + ', trying in current dir');
+ load('relooper.js');
+ }
assert(typeof Relooper != 'undefined');
}
globalEval(processMacros(preprocess(read('runtime.js'))));
@@ -273,6 +279,9 @@ function compile(raw) {
intertyped = null;
JSify(analyzed);
+ //dumpInterProf();
+ //printErr(phase + ' paths (fast, slow): ' + [fastPaths, slowPaths]);
+
phase = null;
if (DEBUG_MEMORY) {
diff --git a/src/compiler_phase.html b/src/compiler_phase.html
new file mode 100644
index 00000000..8ca631e8
--- /dev/null
+++ b/src/compiler_phase.html
@@ -0,0 +1,33 @@
+<html>
+<body>
+<h2>Run the emscripten compiler in a web page, just for laughs</h2>
+Open the web console to see stderr output
+<hr>
+<pre id="output"></pre>
+<script>
+ arguments = ['tmp/emscripten_temp/tmpbTF9CI.txt', 'tmp/emscripten_temp/tmpz8Yvie.pre.ll', 'pre']; // copy from emscripten.py output
+
+ var outputElement = document.getElementById('output');
+ print = function(x) {
+ outputElement.innerHTML += 'output hidden, profiling mode';
+ print = function(){};
+ //outputElement.innerHTML += x;
+ };
+
+ // For generated code
+ var Module = {
+ print: function(x) {
+ throw 'what?'
+ }
+ };
+
+ var startTime = Date.now();
+</script>
+<script src="compiler.js">
+</script>
+<script>
+ outputElement.innerHTML += '<br>total time: ' + (Date.now() - startTime);
+</script>
+</body>
+</html>
+
diff --git a/src/framework.js b/src/framework.js
deleted file mode 100644
index 1a98ca16..00000000
--- a/src/framework.js
+++ /dev/null
@@ -1,257 +0,0 @@
-//"use strict";
-
-//
-// A framework to make building Emscripten easier. Lets you write modular
-// code to handle specific issues.
-//
-// Actor - Some code that processes items.
-// Item - Some data that is processed by actors.
-// Substrate - A 'world' with some actors and some items.
-//
-// The idea is to create a substrate, fill it with the proper items
-// and actors, and then run it to completion. Actors will process
-// the items they are given, and forward the results to other actors,
-// until we are finished. Some of the results are then the final
-// output of the entire calculation done in the substrate.
-//
-
-var DEBUG = 0;
-var DEBUG_MEMORY = 0;
-
-var MemoryDebugger = {
- clear: function() {
- MemoryDebugger.time = Date.now();
- MemoryDebugger.datas = {};
- var info = MemoryDebugger.doGC();
- MemoryDebugger.last = info[2];
- MemoryDebugger.max = 0;
- MemoryDebugger.tick('--clear--');
- },
-
- doGC: function() {
- var raw = gc().replace('\n', '');
- print('zz raw gc info: ' + raw);
- return /before (\d+), after (\d+),.*/.exec(raw);
- },
-
- tick: function(name) {
- var now = Date.now();
- if (now - this.time > 1000) {
- // ..
- this.time = now;
- }
-
- // assume |name| exists from now on
-
- var raw = gc().replace('\n', '');
- var info = MemoryDebugger.doGC();
- var before = info[1];
- var after = info[2];
- MemoryDebugger.max = Math.max(MemoryDebugger.max, before, after);
- // A GC not called by us may have done some work 'silently'
- var garbage = before - after;
- var real = after - MemoryDebugger.last;
- print('zz gc stats changes: ' + [name, real, garbage]);
- MemoryDebugger.last = after;
-
- if (Math.abs(garbage) + Math.abs(real) > 0) {
- var data = MemoryDebugger.datas[name];
- if (!data) {
- data = MemoryDebugger.datas[name] = {
- name: name,
- count: 0,
- garbage: 0,
- real: 0
- };
- }
- data.garbage += garbage;
- data.real += real;
- data.count++;
- }
-
- MemoryDebugger.dump();
- },
-
- dump: function() {
- var vals = values(MemoryDebugger.datas);
- print('zz max: ' + (MemoryDebugger.max/(1024*1024)).toFixed(3));
- print('zz real:');
- vals.sort(function(x, y) { return y.real - x.real });
- vals.forEach(function(v) { if (Math.abs(v.real) > 1024*1024) print('zz ' + v.name + ' real = ' + (v.real/(1024*1024)).toFixed(3) + ' mb'); });
- print('zz garbage:');
- vals.sort(function(x, y) { return y.garbage - x.garbage });
- vals.forEach(function(v) { if (Math.abs(v.garbage) > 1024*1024) print('zz ' + v.name + ' garbage = ' + (v.garbage/(1024*1024)).toFixed(3) + ' mb'); });
- }
-}
-
-if (DEBUG_MEMORY) MemoryDebugger.clear();
-
-function Substrate(name_) {
- this.name_ = name_;
- this.actors = {};
- this.currUid = 1;
-};
-
-Substrate.prototype = {
- addItem: function(item, targetActor) {
- if (targetActor == '/dev/null') return;
- if (targetActor == '/dev/stdout') {
- this.results.push(item);
- return;
- }
- this.actors[targetActor].inbox.push(item);
- },
-
- addItems: function(items, targetActor) {
- if (targetActor == '/dev/null') return;
- if (targetActor == '/dev/stdout') {
- this.results = this.results.concat(items);
- return;
- }
- this.actors[targetActor].inbox = this.actors[targetActor].inbox.concat(items);
- },
-
- checkInbox: function(actor) {
- var items = actor.inbox;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (!item.__uid__) {
- item.__uid__ = this.currUid;
- this.currUid ++;
- }
- }
- var MAX_INCOMING = Infinity;
- if (MAX_INCOMING == Infinity) {
- actor.inbox = [];
- actor.items = actor.items.concat(items);
- } else {
- throw 'Warning: Enter this code at your own risk. It can save memory, but often regresses speed.';
- actor.inbox = items.slice(MAX_INCOMING);
- actor.items = actor.items.concat(items.slice(0, MAX_INCOMING));
- }
- },
-
- addActor: function(name_, actor) {
- assert(name_ && actor);
- actor.name_ = name_;
- actor.items = [];
- actor.inbox = [];
- actor.forwardItem = bind(this, this.addItem);
- actor.forwardItems = bind(this, this.addItems);
- this.actors[name_] = actor;
- if (!actor.process) actor.process = Actor.prototype.process;
- return actor;
- },
-
- solve: function() {
- dprint('framework', "// Solving " + this.name_ + "...");
-
- if (DEBUG_MEMORY) MemoryDebugger.tick('pre-run substrate ' + this.name_ + ' (priors may be cleaned)');
-
- var startTime = Date.now();
- var midTime = startTime;
- var that = this;
- function midComment() {
- var curr = Date.now();
- if (curr - midTime > 500) {
- dprint('framework', '// Working on ' + that.name_ + ', so far ' + ((curr-startTime)/1000).toString().substr(0,10) + ' seconds.');
- midTime = curr;
- }
- }
- function finalComment() {
- dprint('framework', '// Completed ' + that.name_ + ' in ' + ((Date.now() - startTime)/1000).toString().substr(0,10) + ' seconds.');
- }
-
- var ret = null;
- var finalResult = null;
- this.results = [];
- var finished = false;
- var onResult = this.onResult;
- var actors = values(this.actors); // Assumes actors are not constantly added
- while (!finished) {
- dprint('framework', "Cycle start, items: ");// + values(this.actors).map(function(actor) actor.items).reduce(function(x,y) x+y, 0));
- var hadProcessing = false;
- for (var i = 0; i < actors.length; i++) {
- var actor = actors[i];
- if (actor.inbox.length == 0 && actor.items.length == 0) continue;
-
- midComment();
-
- this.checkInbox(actor);
- var outputs;
- var currResultCount = this.results.length;
- dprint('framework', 'Processing using ' + actor.name_ + ': ' + actor.items.length);
- outputs = actor.process(actor.items);
- actor.items = [];
- if (DEBUG_MEMORY) MemoryDebugger.tick('actor ' + actor.name_);
- dprint('framework', 'New results: ' + (outputs.length + this.results.length - currResultCount) + ' out of ' + (this.results.length + outputs.length));
- hadProcessing = true;
-
- if (outputs && outputs.length > 0) {
- if (outputs.length === 1 && outputs[0].__finalResult__) {
- if (DEBUG) print("Solving complete: __finalResult__");
- delete outputs[0].__finalResult__; // Might recycle this
- delete outputs[0].__uid__;
- finalComment();
- finished = true;
- finalResult = outputs[0];
- } else {
- this.results = this.results.concat(outputs);
- }
- }
- }
- if (!hadProcessing) {
- if (DEBUG) print("Solving complete: no remaining items");
- finalComment();
- this.results.forEach(function(result) {
- delete result.__uid__; // Might recycle these
- if (onResult) onResult(result);
- });
- ret = this.results;
- this.results = null; // No need to hold on to them any more
- break;
- }
- if (finalResult) {
- ret = finalResult;
- break;
- }
- midComment();
- }
-
- // Clear the actors. Do not forget about the actors, though, to make this substrate reusable.
- actors.forEach(function(actor) {
- actor.items = null;
- actor.inbox = null;
- });
-
- if (DEBUG_MEMORY) MemoryDebugger.tick('finished ' + this.name_);
-
- return ret;
- }
-};
-
-// Global access to the currently-being processed item.
-// Note that if you overload process in Actor, this will need to be set if you rely on it.
-var Framework = {
- currItem: null
-};
-
-function Actor() { };
-Actor.prototype = {
- process: function(items) {
- var ret = [];
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- items[i] = null; // items may be very very large. Allow GCing to occur in the loop by releasing refs here
- dprint('frameworkLines', 'Processing item for llvm line ' + item.lineNum);
- Framework.currItem = item;
- var outputs = this.processItem(item);
- Framework.currItem = null;
- if (outputs) {
- ret = ret.concat(outputs);
- }
- }
- return ret;
- }
-};
-
diff --git a/src/intertyper.js b/src/intertyper.js
index 082fd993..07f2020c 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -3,10 +3,151 @@
// LLVM assembly => internal intermediate representation, which is ready
// to be processed by the later stages.
-var tokenizer; // TODO: Clean this up/out
- // XXX In particular, this closes over the substrate, which can keep stuff in memory, which is bad
+var fastPaths = 0, slowPaths = 0;
+
+// Line tokenizer
+function tokenizer(item, inner) {
+ //assert(item.lineNum != 40000);
+ //if (item.lineNum) print(item.lineNum);
+ var tokens = [];
+ var quotes = 0;
+ var lastToken = null;
+ var CHUNKSIZE = 64; // How much forward to peek forward. Too much means too many string segments copied
+ // Note: '{' is not an encloser, as its use in functions is split over many lines
+ var enclosers = {
+ '[': 0,
+ ']': '[',
+ '(': 0,
+ ')': '(',
+ '<': 0,
+ '>': '<'
+ };
+ var totalEnclosing = 0;
+ function makeToken(text) {
+ if (text.length == 0) return;
+ // merge certain tokens
+ if (lastToken && ( (lastToken.text == '%' && text[0] == '"') || /^\**$/.test(text) ) ) {
+ lastToken.text += text;
+ return;
+ }
+
+ var token = {
+ text: text
+ };
+ if (text[0] in enclosers) {
+ token.item = tokenizer({
+ lineText: text.substr(1, text.length-2)
+ }, true);
+ token.type = text[0];
+ }
+ // merge certain tokens
+ if (lastToken && isType(lastToken.text) && isFunctionDef(token)) {
+ lastToken.text += ' ' + text;
+ } else if (lastToken && text[0] == '}') { // }, }*, etc.
+ var openBrace = tokens.length-1;
+ while (tokens[openBrace].text.substr(-1) != '{') openBrace --;
+ token = combineTokens(tokens.slice(openBrace+1));
+ tokens.splice(openBrace, tokens.length-openBrace+1);
+ tokens.push(token);
+ token.type = '{';
+ token.text = '{ ' + token.text + ' }';
+ var pointingLevelsToAdd = pointingLevels(text) - pointingLevels(token.text);
+ while (pointingLevelsToAdd > 0) {
+ token.text += '*';
+ pointingLevelsToAdd--;
+ }
+ lastToken = token;
+ } else {
+ tokens.push(token);
+ lastToken = token;
+ }
+ }
+ // Split using meaningful characters
+ var lineText = item.lineText + ' ';
+ var re = /[\[\]\(\)<>, "]/g;
+ var segments = lineText.split(re);
+ segments.pop();
+ var len = segments.length;
+ var i = -1;
+ var curr = '';
+ var segment, letter;
+ for (var s = 0; s < len; s++) {
+ segment = segments[s];
+ i += segment.length + 1;
+ letter = lineText[i];
+ curr += segment;
+ switch (letter) {
+ case ' ':
+ if (totalEnclosing == 0 && quotes == 0) {
+ makeToken(curr);
+ curr = '';
+ } else {
+ curr += ' ';
+ }
+ break;
+ case '"':
+ if (totalEnclosing == 0) {
+ if (quotes == 0) {
+ if (curr == '@' || curr == '%') {
+ curr += '"';
+ } else {
+ makeToken(curr);
+ curr = '"';
+ }
+ } else {
+ makeToken(curr + '"');
+ curr = '';
+ }
+ } else {
+ curr += '"';
+ }
+ quotes = 1-quotes;
+ break;
+ case ',':
+ if (totalEnclosing == 0 && quotes == 0) {
+ makeToken(curr);
+ curr = '';
+ tokens.push({ text: ',' });
+ } else {
+ curr += ',';
+ }
+ break;
+ default:
+ assert(letter in enclosers);
+ if (quotes) {
+ curr += letter;
+ break;
+ }
+ if (letter in ENCLOSER_STARTERS) {
+ if (totalEnclosing == 0) {
+ makeToken(curr);
+ curr = '';
+ }
+ curr += letter;
+ enclosers[letter]++;
+ totalEnclosing++;
+ } else {
+ enclosers[enclosers[letter]]--;
+ totalEnclosing--;
+ if (totalEnclosing == 0) {
+ makeToken(curr + letter);
+ curr = '';
+ } else {
+ curr += letter;
+ }
+ }
+ }
+ }
+ var newItem = {
+ tokens: tokens,
+ indent: lineText.search(/[^ ]/),
+ lineNum: item.lineNum
+ };
+ return newItem;
+}
+
function tokenize(text) {
- return tokenizer.processItem({ lineText: text }, true);
+ return tokenizer({ lineText: text }, true);
}
// Handy sets
@@ -22,672 +163,490 @@ var NSW_NUW = set('nsw', 'nuw');
// Intertyper
-function intertyper(data, sidePass, baseLineNums) {
+function intertyper(lines, sidePass, baseLineNums) {
var mainPass = !sidePass;
baseLineNums = baseLineNums || [[0,0]]; // each pair [#0,#1] means "starting from line #0, the base line num is #1"
dprint('framework', 'Big picture: Starting intertyper, main pass=' + mainPass);
- // Substrate
-
- var substrate = new Substrate('Intertyper');
+ var finalResults = [];
- // Line splitter. We break off some bunches of lines into unparsedBundles, which are
+ // Line splitter. We break off some bunches of lines into unparsed bundles, which are
// parsed in separate passes later. This helps to keep memory usage low - we can start
// from raw lines and end up with final JS for each function individually that way, instead
// of intertyping them all, then analyzing them all, etc.
- substrate.addActor('LineSplitter', {
- processItem: function _lineSplitter(item) {
- var lines = item.llvmLines;
- var ret = [];
- var inContinual = false;
- var inFunction = false;
- var currFunctionLines;
- var currFunctionLineNum;
- var unparsedBundles = [];
- var unparsedTypes, unparsedGlobals;
- if (mainPass) {
- unparsedTypes = {
- intertype: 'unparsedTypes',
- lines: []
- };
- unparsedBundles.push(unparsedTypes);
- unparsedGlobals = {
- intertype: 'unparsedGlobals',
- lines: []
- };
- unparsedBundles.push(unparsedGlobals);
- }
- var baseLineNumPosition = 0;
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- if (singlePhase) lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
+ function lineSplitter() {
+ var ret = [];
+ var inContinual = false;
+ var inFunction = false;
+ var currFunctionLines;
+ var currFunctionLineNum;
+ var unparsedTypes, unparsedGlobals;
+ if (mainPass) {
+ unparsedTypes = {
+ intertype: 'unparsedTypes',
+ lines: []
+ };
+ finalResults.push(unparsedTypes);
+ unparsedGlobals = {
+ intertype: 'unparsedGlobals',
+ lines: []
+ };
+ finalResults.push(unparsedGlobals);
+ }
+ var baseLineNumPosition = 0;
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+ if (singlePhase) lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
- while (baseLineNumPosition < baseLineNums.length-1 && i >= baseLineNums[baseLineNumPosition+1][0]) {
- baseLineNumPosition++;
- }
+ while (baseLineNumPosition < baseLineNums.length-1 && i >= baseLineNums[baseLineNumPosition+1][0]) {
+ baseLineNumPosition++;
+ }
- if (mainPass && (line[0] == '%' || line[0] == '@')) {
- // If this isn't a type, it's a global variable, make a note of the information now, we will need it later
- var parts = line.split(' = ');
- assert(parts.length >= 2);
- var left = parts[0], right = parts.slice(1).join(' = ');
- var testType = /^type .*/.exec(right);
- if (!testType) {
- var globalIdent = toNiceIdent(left);
- var testAlias = /^(hidden )?alias .*/.exec(right);
- Variables.globals[globalIdent] = {
- name: globalIdent,
- alias: !!testAlias,
- impl: VAR_EMULATED
- };
- unparsedGlobals.lines.push(line);
- } else {
- unparsedTypes.lines.push(line);
- }
- continue;
- }
- if (mainPass && /^define .*/.test(line)) {
- inFunction = true;
- currFunctionLines = [];
- currFunctionLineNum = i + 1;
+ if (mainPass && (line[0] == '%' || line[0] == '@')) {
+ // If this isn't a type, it's a global variable, make a note of the information now, we will need it later
+ var parts = line.split(' = ');
+ assert(parts.length >= 2);
+ var left = parts[0], right = parts.slice(1).join(' = ');
+ var testType = /^type .*/.exec(right);
+ if (!testType) {
+ var globalIdent = toNiceIdent(left);
+ var testAlias = /^(hidden )?alias .*/.exec(right);
+ Variables.globals[globalIdent] = {
+ name: globalIdent,
+ alias: !!testAlias,
+ impl: VAR_EMULATED
+ };
+ unparsedGlobals.lines.push(line);
+ } else {
+ unparsedTypes.lines.push(line);
}
- if (!inFunction || !mainPass) {
- if (inContinual || /^\ +(to|catch |filter |cleanup).*/.test(line)) {
- // to after invoke or landingpad second line
- ret.slice(-1)[0].lineText += line;
- if (/^\ +\]/.test(line)) { // end of llvm switch
- inContinual = false;
- }
- } else {
- ret.push({
- lineText: line,
- lineNum: i + 1 + baseLineNums[baseLineNumPosition][1] - baseLineNums[baseLineNumPosition][0]
- });
- if (/^\ +switch\ .*/.test(line)) {
- // beginning of llvm switch
- inContinual = true;
- }
+ continue;
+ }
+ if (mainPass && /^define .*/.test(line)) {
+ inFunction = true;
+ currFunctionLines = [];
+ currFunctionLineNum = i + 1;
+ }
+ if (!inFunction || !mainPass) {
+ if (inContinual || /^\ +(to|catch |filter |cleanup).*/.test(line)) {
+ // to after invoke or landingpad second line
+ ret.slice(-1)[0].lineText += line;
+ if (/^\ +\]/.test(line)) { // end of llvm switch
+ inContinual = false;
}
} else {
- currFunctionLines.push(line);
- }
- if (mainPass && /^}.*/.test(line)) {
- inFunction = false;
- if (mainPass) {
- var func = funcHeader.processItem(tokenizer.processItem({ lineText: currFunctionLines[0], lineNum: currFunctionLineNum }, true))[0];
-
- if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) {
- warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data');
- SKIP_STACK_IN_SMALL = 0;
- }
-
- var ident = toNiceIdent(func.ident);
- if (!(ident in DEAD_FUNCTIONS)) {
- unparsedBundles.push({
- intertype: 'unparsedFunction',
- // We need this early, to know basic function info - ident, params, varargs
- ident: ident,
- params: func.params,
- returnType: func.returnType,
- hasVarArgs: func.hasVarArgs,
- lineNum: currFunctionLineNum,
- lines: currFunctionLines
- });
- }
- currFunctionLines = [];
+ ret.push({
+ lineText: line,
+ lineNum: i + 1 + baseLineNums[baseLineNumPosition][1] - baseLineNums[baseLineNumPosition][0]
+ });
+ if (/^\ +switch\ .*/.test(line)) {
+ // beginning of llvm switch
+ inContinual = true;
}
}
+ } else {
+ currFunctionLines.push(line);
}
- // We need lines beginning with ';' inside functions, because older LLVM versions generated labels that way. But when not
- // parsing functions, we can ignore all such lines and save some time that way.
- this.forwardItems(ret.filter(function(item) { return item.lineText && (item.lineText[0] != ';' || !mainPass); }), 'Tokenizer');
- return unparsedBundles;
- }
- });
+ if (mainPass && /^}.*/.test(line)) {
+ inFunction = false;
+ if (mainPass) {
+ var func = funcHeaderHandler(tokenizer({ lineText: currFunctionLines[0], lineNum: currFunctionLineNum }, true));
- // Line tokenizer
- tokenizer = substrate.addActor('Tokenizer', {
- processItem: function _tokenizer(item, inner) {
- //assert(item.lineNum != 40000);
- //if (item.lineNum) print(item.lineNum);
- var tokens = [];
- var quotes = 0;
- var lastToken = null;
- var CHUNKSIZE = 64; // How much forward to peek forward. Too much means too many string segments copied
- // Note: '{' is not an encloser, as its use in functions is split over many lines
- var enclosers = {
- '[': 0,
- ']': '[',
- '(': 0,
- ')': '(',
- '<': 0,
- '>': '<'
- };
- var totalEnclosing = 0;
- var that = this;
- function makeToken(text) {
- if (text.length == 0) return;
- // merge certain tokens
- if (lastToken && ( (lastToken.text == '%' && text[0] == '"') || /^\**$/.test(text) ) ) {
- lastToken.text += text;
- return;
- }
+ if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) {
+ warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data');
+ SKIP_STACK_IN_SMALL = 0;
+ }
- var token = {
- text: text
- };
- if (text[0] in enclosers) {
- token.item = that.processItem({
- lineText: text.substr(1, text.length-2)
- }, true);
- token.type = text[0];
- }
- // merge certain tokens
- if (lastToken && isType(lastToken.text) && isFunctionDef(token)) {
- lastToken.text += ' ' + text;
- } else if (lastToken && text[0] == '}') { // }, }*, etc.
- var openBrace = tokens.length-1;
- while (tokens[openBrace].text.substr(-1) != '{') openBrace --;
- token = combineTokens(tokens.slice(openBrace+1));
- tokens.splice(openBrace, tokens.length-openBrace+1);
- tokens.push(token);
- token.type = '{';
- token.text = '{ ' + token.text + ' }';
- var pointingLevelsToAdd = pointingLevels(text) - pointingLevels(token.text);
- while (pointingLevelsToAdd > 0) {
- token.text += '*';
- pointingLevelsToAdd--;
+ var ident = toNiceIdent(func.ident);
+ if (!(ident in DEAD_FUNCTIONS)) {
+ finalResults.push({
+ intertype: 'unparsedFunction',
+ // We need this early, to know basic function info - ident, params, varargs
+ ident: ident,
+ params: func.params,
+ returnType: func.returnType,
+ hasVarArgs: func.hasVarArgs,
+ lineNum: currFunctionLineNum,
+ lines: currFunctionLines
+ });
}
- lastToken = token;
- } else {
- tokens.push(token);
- lastToken = token;
- }
- }
- // Split using meaningful characters
- var lineText = item.lineText + ' ';
- var re = /[\[\]\(\)<>, "]/g;
- var segments = lineText.split(re);
- segments.pop();
- var len = segments.length;
- var i = -1;
- var curr = '';
- var segment, letter;
- for (var s = 0; s < len; s++) {
- segment = segments[s];
- i += segment.length + 1;
- letter = lineText[i];
- curr += segment;
- switch (letter) {
- case ' ':
- if (totalEnclosing == 0 && quotes == 0) {
- makeToken(curr);
- curr = '';
- } else {
- curr += ' ';
- }
- break;
- case '"':
- if (totalEnclosing == 0) {
- if (quotes == 0) {
- if (curr == '@' || curr == '%') {
- curr += '"';
- } else {
- makeToken(curr);
- curr = '"';
- }
- } else {
- makeToken(curr + '"');
- curr = '';
- }
- } else {
- curr += '"';
- }
- quotes = 1-quotes;
- break;
- case ',':
- if (totalEnclosing == 0 && quotes == 0) {
- makeToken(curr);
- curr = '';
- tokens.push({ text: ',' });
- } else {
- curr += ',';
- }
- break;
- default:
- assert(letter in enclosers);
- if (quotes) {
- curr += letter;
- break;
- }
- if (letter in ENCLOSER_STARTERS) {
- if (totalEnclosing == 0) {
- makeToken(curr);
- curr = '';
- }
- curr += letter;
- enclosers[letter]++;
- totalEnclosing++;
- } else {
- enclosers[enclosers[letter]]--;
- totalEnclosing--;
- if (totalEnclosing == 0) {
- makeToken(curr + letter);
- curr = '';
- } else {
- curr += letter;
- }
- }
+ currFunctionLines = [];
}
}
- var newItem = {
- tokens: tokens,
- indent: lineText.search(/[^ ]/),
- lineNum: item.lineNum
- };
- if (inner) {
- return newItem;
- } else {
- this.forwardItem(newItem, 'Triager');
- }
- return null;
}
- });
+ // We need lines beginning with ';' inside functions, because older LLVM versions generated labels that way. But when not
+ // parsing functions, we can ignore all such lines and save some time that way.
+ return ret.filter(function(item) { return item.lineText && (item.lineText[0] != ';' || !mainPass); });
+ }
- substrate.addActor('Triager', {
- processItem: function _triager(item) {
- function triage() {
- assert(!item.intertype);
- var token0Text = item.tokens[0].text;
- var token1Text = item.tokens[1] ? item.tokens[1].text : null;
- var tokensLength = item.tokens.length;
- if (item.indent === 2) {
- if (tokensLength >= 5 &&
- (token0Text == 'store' || token1Text == 'store'))
- return 'Store';
- if (tokensLength >= 3 && token0Text == 'br')
- return 'Branch';
- if (tokensLength >= 2 && token0Text == 'ret')
- return 'Return';
- if (tokensLength >= 2 && token0Text == 'switch')
- return 'Switch';
- if (token0Text == 'unreachable')
- return 'Unreachable';
- if (tokensLength >= 3 && token0Text == 'indirectbr')
- return 'IndirectBr';
- if (tokensLength >= 2 && token0Text == 'resume')
- return 'Resume';
- if (tokensLength >= 3 &&
- (token0Text == 'load' || token1Text == 'load'))
- return 'Load';
- if (tokensLength >= 3 &&
- token0Text in MATHOPS)
- return 'Mathops';
- if (tokensLength >= 3 && token0Text == 'bitcast')
- return 'Bitcast';
- if (tokensLength >= 3 && token0Text == 'getelementptr')
- return 'GEP';
- if (tokensLength >= 2 && token0Text == 'alloca')
- return 'Alloca';
- if (tokensLength >= 3 && token0Text == 'extractvalue')
- return 'ExtractValue';
- if (tokensLength >= 3 && token0Text == 'insertvalue')
- return 'InsertValue';
- if (tokensLength >= 3 && token0Text == 'phi')
- return 'Phi';
- if (tokensLength >= 3 && token0Text == 'va_arg')
- return 'va_arg';
- if (tokensLength >= 3 && token0Text == 'landingpad')
- return 'Landingpad';
- if (token0Text == 'fence')
- return '/dev/null';
- } else if (item.indent === 0) {
- if ((tokensLength >= 1 && token0Text.substr(-1) == ':') ||
- (tokensLength >= 3 && token1Text == '<label>') ||
- (tokensLength >= 2 && token1Text == ':'))
- return 'Label';
- if (tokensLength >= 4 && token0Text == 'declare')
- return 'External';
- if (tokensLength >= 3 && token1Text == '=')
- return 'Global';
- if (tokensLength >= 4 && token0Text == 'define' &&
- item.tokens.slice(-1)[0].text == '{')
- return 'FuncHeader';
- if (tokensLength >= 1 && token0Text == '}')
- return 'FuncEnd';
- if (token0Text == 'module' && token1Text == 'asm') {
- warn('Ignoring module asm: ' + item.tokens[2].text);
- return '/dev/null';
- }
- if (token0Text == 'attributes')
- return '/dev/null';
- }
- if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call'))
- return 'Call';
- if (token0Text == 'target') {
- if (token1Text == 'triple') {
- var triple = item.tokens[3].text;
- triple = triple.substr(1, triple.length-2);
- var expected = TARGET_LE32 ? 'le32-unknown-nacl' : 'i386-pc-linux-gnu';
- if (triple !== expected) {
- warn('using an unexpected LLVM triple: ' + [triple, ' !== ', expected] + ' (are you using emcc for everything and not clang?)');
- }
- }
- return '/dev/null';
- }
- if (token0Text == ';')
- return '/dev/null';
- if (tokensLength >= 3 && token0Text == 'invoke')
- return 'Invoke';
- if (tokensLength >= 3 && token0Text == 'atomicrmw' || token0Text == 'cmpxchg')
- return 'Atomic';
- throw 'Invalid token, cannot triage: ' + dump(item);
+ function triager(item) {
+ assert(!item.intertype);
+ if (item.indent == 2 && (eq = findTokenText(item, '=')) >= 0) {
+ item.assignTo = toNiceIdent(combineTokens(item.tokens.slice(0, eq)).text);
+ item.tokens = item.tokens.slice(eq+1);
+ }
+ var token0Text = item.tokens[0].text;
+ var token1Text = item.tokens[1] ? item.tokens[1].text : null;
+ var tokensLength = item.tokens.length;
+ if (item.indent === 2) {
+ if (tokensLength >= 5 &&
+ (token0Text == 'store' || token1Text == 'store'))
+ return storeHandler(item);
+ if (tokensLength >= 3 && token0Text == 'br')
+ return branchHandler(item);
+ if (tokensLength >= 2 && token0Text == 'ret')
+ return returnHandler(item);
+ if (tokensLength >= 2 && token0Text == 'switch')
+ return switchHandler(item);
+ if (token0Text == 'unreachable')
+ return unreachableHandler(item);
+ if (tokensLength >= 3 && token0Text == 'indirectbr')
+ return indirectBrHandler(item);
+ if (tokensLength >= 2 && token0Text == 'resume')
+ return resumeHandler(item);
+ if (tokensLength >= 3 &&
+ (token0Text == 'load' || token1Text == 'load'))
+ return loadHandler(item);
+ if (tokensLength >= 3 &&
+ token0Text in MATHOPS)
+ return mathopsHandler(item);
+ if (tokensLength >= 3 && token0Text == 'bitcast')
+ return bitcastHandler(item);
+ if (tokensLength >= 3 && token0Text == 'getelementptr')
+ return GEPHandler(item);
+ if (tokensLength >= 2 && token0Text == 'alloca')
+ return allocaHandler(item);
+ if (tokensLength >= 3 && token0Text == 'extractvalue')
+ return extractValueHandler(item);
+ if (tokensLength >= 3 && token0Text == 'insertvalue')
+ return insertValueHandler(item);
+ if (tokensLength >= 3 && token0Text == 'phi')
+ return phiHandler(item);
+ if (tokensLength >= 3 && token0Text == 'va_arg')
+ return va_argHandler(item);
+ if (tokensLength >= 3 && token0Text == 'landingpad')
+ return landingpadHandler(item);
+ if (token0Text == 'fence')
+ return null;
+ } else if (item.indent === 0) {
+ if ((tokensLength >= 1 && token0Text.substr(-1) == ':') ||
+ (tokensLength >= 3 && token1Text == '<label>') ||
+ (tokensLength >= 2 && token1Text == ':'))
+ return labelHandler(item);
+ if (tokensLength >= 4 && token0Text == 'declare')
+ return externalHandler(item);
+ if (tokensLength >= 3 && token1Text == '=')
+ return globalHandler(item);
+ if (tokensLength >= 4 && token0Text == 'define' &&
+ item.tokens.slice(-1)[0].text == '{')
+ return funcHeaderHandler(item);
+ if (tokensLength >= 1 && token0Text == '}')
+ return funcEndHandler(item);
+ if (token0Text == 'module' && token1Text == 'asm') {
+ warn('Ignoring module asm: ' + item.tokens[2].text);
+ return null;
}
- var eq;
- if (item.indent == 2 && (eq = findTokenText(item, '=')) >= 0) {
- item.assignTo = toNiceIdent(combineTokens(item.tokens.slice(0, eq)).text);
- item.tokens = item.tokens.slice(eq+1);
+ if (token0Text == 'attributes')
+ return null;
+ }
+ if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call'))
+ return callHandler(item);
+ if (token0Text == 'target') {
+ if (token1Text == 'triple') {
+ var triple = item.tokens[3].text;
+ triple = triple.substr(1, triple.length-2);
+ var expected = TARGET_LE32 ? 'le32-unknown-nacl' : 'i386-pc-linux-gnu';
+ if (triple !== expected) {
+ warn('using an unexpected LLVM triple: ' + [triple, ' !== ', expected] + ' (are you using emcc for everything and not clang?)');
+ }
}
- this.forwardItem(item, triage());
+ return null;
}
- });
+ if (token0Text == ';')
+ return null;
+ if (tokensLength >= 3 && token0Text == 'invoke')
+ return invokeHandler(item);
+ if (tokensLength >= 3 && token0Text == 'atomicrmw' || token0Text == 'cmpxchg')
+ return atomicHandler(item);
+ throw 'Invalid token, cannot triage: ' + dump(item);
+ }
// Line parsers to intermediate form
// globals: type or variable
- substrate.addActor('Global', {
- processItem: function _global(item) {
- function scanConst(value, type) {
- // Gets an array of constant items, separated by ',' tokens
- function handleSegments(tokens) {
- // Handle a single segment (after comma separation)
- function handleSegment(segment) {
- if (segment[1].text == 'null') {
- return { intertype: 'value', ident: '0', type: 'i32' };
- } else if (segment[1].text == 'zeroinitializer') {
- Types.needAnalysis[segment[0].text] = 0;
- return { intertype: 'emptystruct', type: segment[0].text };
- } else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
- return parseLLVMFunctionCall(segment);
- } else if (segment[1].type && segment[1].type == '{') {
- Types.needAnalysis[segment[0].text] = 0;
- return { intertype: 'struct', type: segment[0].text, contents: handleSegments(segment[1].tokens) };
- } else if (segment[1].type && segment[1].type == '<') {
- Types.needAnalysis[segment[0].text] = 0;
- return { intertype: 'struct', type: segment[0].text, contents: handleSegments(segment[1].item.tokens[0].tokens) };
- } else if (segment[1].type && segment[1].type == '[') {
- Types.needAnalysis[segment[0].text] = 0;
- return { intertype: 'list', type: segment[0].text, contents: handleSegments(segment[1].item.tokens) };
- } else if (segment.length == 2) {
- Types.needAnalysis[segment[0].text] = 0;
- return { intertype: 'value', type: segment[0].text, ident: toNiceIdent(segment[1].text) };
- } else if (segment[1].text === 'c') {
- // string
- var text = segment[2].text;
- text = text.substr(1, text.length-2);
- return { intertype: 'string', text: text, type: 'i8*' };
- } else if (segment[1].text === 'blockaddress') {
- return parseBlockAddress(segment);
- } else {
- throw 'Invalid segment: ' + dump(segment);
- }
- };
- return splitTokenList(tokens).map(handleSegment);
- }
+ function noteGlobalVariable(ret) {
+ if (!NAMED_GLOBALS) {
+ Variables.globals[ret.ident].type = ret.type;
+ Variables.globals[ret.ident].external = ret.external;
+ }
+ Types.needAnalysis[ret.type] = 0;
+ }
- Types.needAnalysis[type] = 0;
- if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) {
- return { value: toNiceIdent(value.text), type: type };
- } else if (value.text in ZEROINIT_UNDEF) { // undef doesn't really need initting, but why not
- return { intertype: 'emptystruct', type: type };
- } else if (value.text && value.text[0] == '"') {
- return { intertype: 'string', text: value.text.substr(1, value.text.length-2) };
- } else {
- if (value.type == '<') { // <{ i8 }> etc.
- value = value.item.tokens;
- }
- var contents;
- if (value.item) {
- // list of items
- contents = value.item.tokens;
- } else if (value.type == '{') {
- // struct
- contents = value.tokens;
- } else if (value[0]) {
- contents = value[0];
+ function globalHandler(item) {
+ function scanConst(value, type) {
+ // Gets an array of constant items, separated by ',' tokens
+ function handleSegments(tokens) {
+ // Handle a single segment (after comma separation)
+ function handleSegment(segment) {
+ if (segment[1].text == 'null') {
+ return { intertype: 'value', ident: '0', type: 'i32' };
+ } else if (segment[1].text == 'zeroinitializer') {
+ Types.needAnalysis[segment[0].text] = 0;
+ return { intertype: 'emptystruct', type: segment[0].text };
+ } else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) {
+ return parseLLVMFunctionCall(segment);
+ } else if (segment[1].type && segment[1].type == '{') {
+ Types.needAnalysis[segment[0].text] = 0;
+ return { intertype: 'struct', type: segment[0].text, contents: handleSegments(segment[1].tokens) };
+ } else if (segment[1].type && segment[1].type == '<') {
+ Types.needAnalysis[segment[0].text] = 0;
+ return { intertype: 'struct', type: segment[0].text, contents: handleSegments(segment[1].item.tokens[0].tokens) };
+ } else if (segment[1].type && segment[1].type == '[') {
+ Types.needAnalysis[segment[0].text] = 0;
+ return { intertype: 'list', type: segment[0].text, contents: handleSegments(segment[1].item.tokens) };
+ } else if (segment.length == 2) {
+ Types.needAnalysis[segment[0].text] = 0;
+ return { intertype: 'value', type: segment[0].text, ident: toNiceIdent(segment[1].text) };
+ } else if (segment[1].text === 'c') {
+ // string
+ var text = segment[2].text;
+ text = text.substr(1, text.length-2);
+ return { intertype: 'string', text: text, type: 'i8*' };
+ } else if (segment[1].text === 'blockaddress') {
+ return parseBlockAddress(segment);
} else {
- throw '// interfailzzzzzzzzzzzzzz ' + dump(value.item) + ' ::: ' + dump(value);
+ throw 'Invalid segment: ' + dump(segment);
}
- return { intertype: 'segments', contents: handleSegments(contents) };
- }
+ };
+ return splitTokenList(tokens).map(handleSegment);
}
- cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 2);
- if (item.tokens[2].text == 'alias') {
- cleanOutTokens(LLVM.LINKAGES, item.tokens, 3);
- cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 3);
- var last = getTokenIndexByText(item.tokens, ';');
- var ret = {
- intertype: 'alias',
- ident: toNiceIdent(item.tokens[0].text),
- value: parseLLVMSegment(item.tokens.slice(3, last)),
- lineNum: item.lineNum
- };
- ret.type = ret.value.type;
- Types.needAnalysis[ret.type] = 0;
- if (!NAMED_GLOBALS) {
- Variables.globals[ret.ident].type = ret.type;
+ Types.needAnalysis[type] = 0;
+ if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) {
+ return { value: toNiceIdent(value.text), type: type };
+ } else if (value.text in ZEROINIT_UNDEF) { // undef doesn't really need initting, but why not
+ return { intertype: 'emptystruct', type: type };
+ } else if (value.text && value.text[0] == '"') {
+ return { intertype: 'string', text: value.text.substr(1, value.text.length-2) };
+ } else {
+ if (value.type == '<') { // <{ i8 }> etc.
+ value = value.item.tokens;
+ }
+ var contents;
+ if (value.item) {
+ // list of items
+ contents = value.item.tokens;
+ } else if (value.type == '{') {
+ // struct
+ contents = value.tokens;
+ } else if (value[0]) {
+ contents = value[0];
+ } else {
+ throw '// interfailzzzzzzzzzzzzzz ' + dump(value.item) + ' ::: ' + dump(value);
}
- return [ret];
+ return { intertype: 'segments', contents: handleSegments(contents) };
}
- if (item.tokens[2].text == 'type') {
- var fields = [];
- var packed = false;
- if (Runtime.isNumberType(item.tokens[3].text)) {
- // Clang sometimes has |= i32| instead of |= { i32 }|
- fields = [item.tokens[3].text];
- } else if (item.tokens[3].text != 'opaque') {
- if (item.tokens[3].type == '<') {
- packed = true;
- item.tokens[3] = item.tokens[3].item.tokens[0];
- }
- var subTokens = item.tokens[3].tokens;
- if (subTokens) {
- subTokens.push({text:','});
- while (subTokens[0]) {
- var stop = 1;
- while ([','].indexOf(subTokens[stop].text) == -1) stop ++;
- fields.push(combineTokens(subTokens.slice(0, stop)).text);
- subTokens.splice(0, stop+1);
- }
- }
+ }
+
+ cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 2);
+ if (item.tokens[2].text == 'alias') {
+ cleanOutTokens(LLVM.LINKAGES, item.tokens, 3);
+ cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 3);
+ var last = getTokenIndexByText(item.tokens, ';');
+ var ret = {
+ intertype: 'alias',
+ ident: toNiceIdent(item.tokens[0].text),
+ value: parseLLVMSegment(item.tokens.slice(3, last)),
+ lineNum: item.lineNum
+ };
+ ret.type = ret.value.type;
+ Types.needAnalysis[ret.type] = 0;
+ if (!NAMED_GLOBALS) {
+ Variables.globals[ret.ident].type = ret.type;
+ }
+ return ret;
+ }
+ if (item.tokens[2].text == 'type') {
+ var fields = [];
+ var packed = false;
+ if (Runtime.isNumberType(item.tokens[3].text)) {
+ // Clang sometimes has |= i32| instead of |= { i32 }|
+ fields = [item.tokens[3].text];
+ } else if (item.tokens[3].text != 'opaque') {
+ if (item.tokens[3].type == '<') {
+ packed = true;
+ item.tokens[3] = item.tokens[3].item.tokens[0];
}
- return [{
- intertype: 'type',
- name_: item.tokens[0].text,
- fields: fields,
- packed: packed,
- lineNum: item.lineNum
- }];
- } else {
- // variable
- var ident = item.tokens[0].text;
- var private_ = findTokenText(item, 'private') >= 0 || findTokenText(item, 'internal') >= 0;
- var named = findTokenText(item, 'unnamed_addr') < 0;
- cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [2, 3]);
- var external = false;
- if (item.tokens[2].text === 'external') {
- external = true;
- item.tokens.splice(2, 1);
+ var subTokens = item.tokens[3].tokens;
+ if (subTokens) {
+ subTokens.push({text:','});
+ while (subTokens[0]) {
+ var stop = 1;
+ while ([','].indexOf(subTokens[stop].text) == -1) stop ++;
+ fields.push(combineTokens(subTokens.slice(0, stop)).text);
+ subTokens.splice(0, stop+1);
+ }
}
- Types.needAnalysis[item.tokens[2].text] = 0;
- var ret = {
- intertype: 'globalVariable',
- ident: toNiceIdent(ident),
- type: item.tokens[2].text,
- external: external,
- private_: private_,
- named: named,
- lineNum: item.lineNum
- };
- if (!NAMED_GLOBALS) {
- Variables.globals[ret.ident].type = ret.type;
- Variables.globals[ret.ident].external = external;
+ }
+ return {
+ intertype: 'type',
+ name_: item.tokens[0].text,
+ fields: fields,
+ packed: packed,
+ lineNum: item.lineNum
+ };
+ } else {
+ // variable
+ var ident = item.tokens[0].text;
+ var private_ = findTokenText(item, 'private') >= 0 || findTokenText(item, 'internal') >= 0;
+ var named = findTokenText(item, 'unnamed_addr') < 0;
+ cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [2, 3]);
+ var external = false;
+ if (item.tokens[2].text === 'external') {
+ external = true;
+ item.tokens.splice(2, 1);
+ }
+ var ret = {
+ intertype: 'globalVariable',
+ ident: toNiceIdent(ident),
+ type: item.tokens[2].text,
+ external: external,
+ private_: private_,
+ named: named,
+ lineNum: item.lineNum
+ };
+ noteGlobalVariable(ret);
+ if (ident == '@llvm.global_ctors') {
+ ret.ctors = [];
+ if (item.tokens[3].item) {
+ var subTokens = item.tokens[3].item.tokens;
+ splitTokenList(subTokens).forEach(function(segment) {
+ var ctor = toNiceIdent(segment[1].tokens.slice(-1)[0].text);
+ ret.ctors.push(ctor);
+ if (ASM_JS) { // must export the global constructors from asm.js module, so mark as implemented and exported
+ Functions.implementedFunctions[ctor] = 'v';
+ EXPORTED_FUNCTIONS[ctor] = 1;
+ }
+ });
}
- Types.needAnalysis[ret.type] = 0;
- if (ident == '@llvm.global_ctors') {
- ret.ctors = [];
- if (item.tokens[3].item) {
- var subTokens = item.tokens[3].item.tokens;
- splitTokenList(subTokens).forEach(function(segment) {
- var ctor = toNiceIdent(segment[1].tokens.slice(-1)[0].text);
- ret.ctors.push(ctor);
- if (ASM_JS) { // must export the global constructors from asm.js module, so mark as implemented and exported
- Functions.implementedFunctions[ctor] = 'v';
- EXPORTED_FUNCTIONS[ctor] = 1;
- }
- });
+ } else if (!external) {
+ if (item.tokens[3] && item.tokens[3].text != ';') {
+ if (item.tokens[3].text == 'c') {
+ item.tokens.splice(3, 1);
}
- } else if (!external) {
- if (item.tokens[3] && item.tokens[3].text != ';') {
- if (item.tokens[3].text == 'c') {
- item.tokens.splice(3, 1);
- }
- if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
- ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
- } else {
- ret.value = scanConst(item.tokens[3], ret.type);
- }
+ if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
+ ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
} else {
- ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type };
+ ret.value = scanConst(item.tokens[3], ret.type);
}
+ } else {
+ ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type };
}
- return [ret];
}
+ return ret;
}
- });
+ }
// function header
- var funcHeader = substrate.addActor('FuncHeader', {
- processItem: function(item) {
- item.tokens = item.tokens.filter(function(token) {
- return !(token.text in LLVM.LINKAGES || token.text in LLVM.PARAM_ATTR || token.text in LLVM.FUNC_ATTR || token.text in LLVM.CALLING_CONVENTIONS);
- });
- var params = parseParamTokens(item.tokens[2].item.tokens);
- if (sidePass) dprint('unparsedFunctions', 'Processing function: ' + item.tokens[1].text);
- return [{
- intertype: 'function',
- ident: toNiceIdent(item.tokens[1].text),
- returnType: item.tokens[0].text,
- params: params,
- hasVarArgs: hasVarArgs(params),
- lineNum: item.lineNum,
- }];
- }
- });
+ function funcHeaderHandler(item) {
+ item.tokens = item.tokens.filter(function(token) {
+ return !(token.text in LLVM.LINKAGES || token.text in LLVM.PARAM_ATTR || token.text in LLVM.FUNC_ATTR || token.text in LLVM.CALLING_CONVENTIONS);
+ });
+ var params = parseParamTokens(item.tokens[2].item.tokens);
+ if (sidePass) dprint('unparsedFunctions', 'Processing function: ' + item.tokens[1].text);
+ return {
+ intertype: 'function',
+ ident: toNiceIdent(item.tokens[1].text),
+ returnType: item.tokens[0].text,
+ params: params,
+ hasVarArgs: hasVarArgs(params),
+ lineNum: item.lineNum,
+ };
+ }
// label
- substrate.addActor('Label', {
- processItem: function(item) {
- var rawLabel = item.tokens[0].text.substr(-1) == ':' ?
- '%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) :
- (item.tokens[1].text == '<label>' ?
- '%' + item.tokens[2].text.substr(1) :
- '%' + item.tokens[0].text)
- var niceLabel = toNiceIdent(rawLabel);
- return [{
- intertype: 'label',
- ident: niceLabel,
- lineNum: item.lineNum
- }];
- }
- });
-
- // TODO: remove dis
- substrate.addActor('Reintegrator', {
- processItem: function(item) {
- this.forwardItem(item, '/dev/stdout');
- }
- });
+ function labelHandler(item) {
+ var rawLabel = item.tokens[0].text.substr(-1) == ':' ?
+ '%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) :
+ (item.tokens[1].text == '<label>' ?
+ '%' + item.tokens[2].text.substr(1) :
+ '%' + item.tokens[0].text)
+ var niceLabel = toNiceIdent(rawLabel);
+ return {
+ intertype: 'label',
+ ident: niceLabel,
+ lineNum: item.lineNum
+ };
+ }
// 'load'
- substrate.addActor('Load', {
- processItem: function(item) {
- item.intertype = 'load';
- cleanOutTokens(LLVM.ACCESS_OPTIONS, item.tokens, [0, 1]);
- item.pointerType = item.tokens[1].text;
- item.valueType = item.type = removePointing(item.pointerType);
- Types.needAnalysis[item.type] = 0;
- var last = getTokenIndexByText(item.tokens, ';');
- var segments = splitTokenList(item.tokens.slice(1, last));
- item.pointer = parseLLVMSegment(segments[0]);
- if (segments.length > 1) {
- assert(segments[1][0].text == 'align');
- item.align = parseInt(segments[1][1].text) || QUANTUM_SIZE; // 0 means preferred arch align
- } else {
- item.align = QUANTUM_SIZE;
- }
- item.ident = item.pointer.ident || null;
- this.forwardItem(item, 'Reintegrator');
+ function loadHandler(item) {
+ item.intertype = 'load';
+ cleanOutTokens(LLVM.ACCESS_OPTIONS, item.tokens, [0, 1]);
+ item.pointerType = item.tokens[1].text;
+ item.valueType = item.type = removePointing(item.pointerType);
+ Types.needAnalysis[item.type] = 0;
+ var last = getTokenIndexByText(item.tokens, ';');
+ var segments = splitTokenList(item.tokens.slice(1, last));
+ item.pointer = parseLLVMSegment(segments[0]);
+ if (segments.length > 1) {
+ assert(segments[1][0].text == 'align');
+ item.align = parseInt(segments[1][1].text) || QUANTUM_SIZE; // 0 means preferred arch align
+ } else {
+ item.align = QUANTUM_SIZE;
}
- });
+ item.ident = item.pointer.ident || null;
+ return item;
+ }
// 'extractvalue'
- substrate.addActor('ExtractValue', {
- processItem: function(item) {
- var last = getTokenIndexByText(item.tokens, ';');
- item.intertype = 'extractvalue';
- item.type = item.tokens[1].text; // Of the origin aggregate - not what we extract from it. For that, can only infer it later
- Types.needAnalysis[item.type] = 0;
- item.ident = toNiceIdent(item.tokens[2].text);
- item.indexes = splitTokenList(item.tokens.slice(4, last));
- this.forwardItem(item, 'Reintegrator');
- }
- });
+ function extractValueHandler(item) {
+ var last = getTokenIndexByText(item.tokens, ';');
+ item.intertype = 'extractvalue';
+ item.type = item.tokens[1].text; // Of the origin aggregate - not what we extract from it. For that, can only infer it later
+ Types.needAnalysis[item.type] = 0;
+ item.ident = toNiceIdent(item.tokens[2].text);
+ item.indexes = splitTokenList(item.tokens.slice(4, last));
+ return item;
+ }
// 'insertvalue'
- substrate.addActor('InsertValue', {
- processItem: function(item) {
- var last = getTokenIndexByText(item.tokens, ';');
- item.intertype = 'insertvalue';
- item.type = item.tokens[1].text; // Of the origin aggregate, as well as the result
- Types.needAnalysis[item.type] = 0;
- item.ident = toNiceIdent(item.tokens[2].text);
- var segments = splitTokenList(item.tokens.slice(4, last));
- item.value = parseLLVMSegment(segments[0]);
- item.indexes = segments.slice(1);
- this.forwardItem(item, 'Reintegrator');
- }
- });
+ function insertValueHandler(item) {
+ var last = getTokenIndexByText(item.tokens, ';');
+ item.intertype = 'insertvalue';
+ item.type = item.tokens[1].text; // Of the origin aggregate, as well as the result
+ Types.needAnalysis[item.type] = 0;
+ item.ident = toNiceIdent(item.tokens[2].text);
+ var segments = splitTokenList(item.tokens.slice(4, last));
+ item.value = parseLLVMSegment(segments[0]);
+ item.indexes = segments.slice(1);
+ return item;
+ }
// 'bitcast'
- substrate.addActor('Bitcast', {
- processItem: function(item) {
- item.intertype = 'bitcast';
- item.type = item.tokens[4].text; // The final type
- Types.needAnalysis[item.type] = 0;
- var to = getTokenIndexByText(item.tokens, 'to');
- item.params = [parseLLVMSegment(item.tokens.slice(1, to))];
- item.ident = item.params[0].ident;
- item.type2 = item.tokens[1].text; // The original type
- Types.needAnalysis[item.type2] = 0;
- this.forwardItem(item, 'Reintegrator');
- }
- });
+ function bitcastHandler(item) {
+ item.intertype = 'bitcast';
+ item.type = item.tokens[4].text; // The final type
+ Types.needAnalysis[item.type] = 0;
+ var to = getTokenIndexByText(item.tokens, 'to');
+ item.params = [parseLLVMSegment(item.tokens.slice(1, to))];
+ item.ident = item.params[0].ident;
+ item.type2 = item.tokens[1].text; // The original type
+ Types.needAnalysis[item.type2] = 0;
+ return item;
+ }
// 'getelementptr'
- substrate.addActor('GEP', {
- processItem: function(item) {
- var first = 0;
- while (!isType(item.tokens[first].text)) first++;
- Types.needAnalysis[item.tokens[first].text] = 0;
- var last = getTokenIndexByText(item.tokens, ';');
- var segment = [ item.tokens[first], { text: 'getelementptr' }, null, { item: {
- tokens: item.tokens.slice(first, last)
- } } ];
- var data = parseLLVMFunctionCall(segment);
- item.intertype = 'getelementptr';
- item.type = '*'; // We need type info to determine this - all we know is it's a pointer
- item.params = data.params;
- item.ident = data.ident;
- this.forwardItem(item, 'Reintegrator');
- }
- });
+ function GEPHandler(item) {
+ var first = 0;
+ while (!isType(item.tokens[first].text)) first++;
+ Types.needAnalysis[item.tokens[first].text] = 0;
+ var last = getTokenIndexByText(item.tokens, ';');
+ var segment = [ item.tokens[first], { text: 'getelementptr' }, null, { item: {
+ tokens: item.tokens.slice(first, last)
+ } } ];
+ var data = parseLLVMFunctionCall(segment);
+ item.intertype = 'getelementptr';
+ item.type = '*'; // We need type info to determine this - all we know is it's a pointer
+ item.params = data.params;
+ item.ident = data.ident;
+ return item;
+ }
// 'call', 'invoke'
function makeCall(item, type) {
item.intertype = type;
@@ -727,7 +686,7 @@ function intertyper(data, sidePass, baseLineNums) {
});
if (item.assignTo) item.ident = 'return ' + item.ident;
item.ident = '(function(' + params + ') { ' + item.ident + ' })(' + args + ');';
- return { forward: null, ret: [item], item: item };
+ return { forward: null, ret: item, item: item };
}
if (item.ident.substr(-2) == '()') {
// See comment in isStructType()
@@ -750,330 +709,417 @@ function intertyper(data, sidePass, baseLineNums) {
if (item.indent == 2) {
// standalone call - not in assign
item.standalone = true;
- return { forward: null, ret: [item], item: item };
+ return { forward: null, ret: item, item: item };
}
- return { forward: item, ret: [], item: item };
+ return { forward: item, ret: null, item: item };
}
- substrate.addActor('Call', {
- processItem: function(item) {
- var result = makeCall.call(this, item, 'call');
- if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
- return result.ret;
- }
- });
- substrate.addActor('Invoke', {
- processItem: function(item) {
- var result = makeCall.call(this, item, 'invoke');
- if (DISABLE_EXCEPTION_CATCHING == 1) {
- result.item.intertype = 'call';
- result.ret.push({
- intertype: 'branch',
- label: result.item.toLabel,
- lineNum: (result.forward ? item.parentLineNum : item.lineNum) + 0.5
- });
- }
- if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
- return result.ret;
+ function callHandler(item) {
+ var result = makeCall.call(this, item, 'call');
+ if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
+ return result.ret;
+ }
+ function invokeHandler(item) {
+ var result = makeCall.call(this, item, 'invoke');
+ if (DISABLE_EXCEPTION_CATCHING == 1) {
+ result.item.intertype = 'call';
+ finalResults.push({
+ intertype: 'branch',
+ label: result.item.toLabel,
+ lineNum: (result.forward ? item.parentLineNum : item.lineNum) + 0.5
+ });
}
- });
- substrate.addActor('Atomic', {
- processItem: function(item) {
- item.intertype = 'atomic';
- if (item.tokens[0].text == 'atomicrmw') {
- if (item.tokens[1].text == 'volatile') item.tokens.splice(1, 1);
- item.op = item.tokens[1].text;
- item.tokens.splice(1, 1);
- } else {
- assert(item.tokens[0].text == 'cmpxchg')
- if (item.tokens[1].text == 'volatile') item.tokens.splice(1, 1);
- item.op = 'cmpxchg';
- }
- var last = getTokenIndexByText(item.tokens, ';');
- item.params = splitTokenList(item.tokens.slice(1, last)).map(parseLLVMSegment);
- item.type = item.params[1].type;
- this.forwardItem(item, 'Reintegrator');
+ if (result.forward) this.forwardItem(result.forward, 'Reintegrator');
+ return result.ret;
+ }
+ function atomicHandler(item) {
+ item.intertype = 'atomic';
+ if (item.tokens[0].text == 'atomicrmw') {
+ if (item.tokens[1].text == 'volatile') item.tokens.splice(1, 1);
+ item.op = item.tokens[1].text;
+ item.tokens.splice(1, 1);
+ } else {
+ assert(item.tokens[0].text == 'cmpxchg')
+ if (item.tokens[1].text == 'volatile') item.tokens.splice(1, 1);
+ item.op = 'cmpxchg';
}
- });
+ var last = getTokenIndexByText(item.tokens, ';');
+ item.params = splitTokenList(item.tokens.slice(1, last)).map(parseLLVMSegment);
+ item.type = item.params[1].type;
+ return item;
+ }
// 'landingpad'
- substrate.addActor('Landingpad', {
- processItem: function(item) {
- item.intertype = 'landingpad';
- item.type = item.tokens[1].text;
- item.catchables = [];
- var catchIdx = findTokenText(item, "catch");
- if (catchIdx != -1) {
- do {
- var nextCatchIdx = findTokenTextAfter(item, "catch", catchIdx+1);
- if (nextCatchIdx == -1)
- nextCatchIdx = item.tokens.length;
- item.catchables.push(parseLLVMSegment(item.tokens.slice(catchIdx+2, nextCatchIdx)));
- catchIdx = nextCatchIdx;
- } while (catchIdx != item.tokens.length);
- }
- Types.needAnalysis[item.type] = 0;
- this.forwardItem(item, 'Reintegrator');
+ function landingpadHandler(item) {
+ item.intertype = 'landingpad';
+ item.type = item.tokens[1].text;
+ item.catchables = [];
+ var catchIdx = findTokenText(item, "catch");
+ if (catchIdx != -1) {
+ do {
+ var nextCatchIdx = findTokenTextAfter(item, "catch", catchIdx+1);
+ if (nextCatchIdx == -1)
+ nextCatchIdx = item.tokens.length;
+ item.catchables.push(parseLLVMSegment(item.tokens.slice(catchIdx+2, nextCatchIdx)));
+ catchIdx = nextCatchIdx;
+ } while (catchIdx != item.tokens.length);
}
- });
+ Types.needAnalysis[item.type] = 0;
+ return item;
+ }
// 'alloca'
var allocaPossibleVars = ['allocatedNum'];
- substrate.addActor('Alloca', {
- processItem: function(item) {
- item.intertype = 'alloca';
- item.allocatedType = item.tokens[1].text;
- if (item.tokens.length > 3 && Runtime.isNumberType(item.tokens[3].text)) {
- item.allocatedNum = toNiceIdent(item.tokens[4].text);
- item.possibleVars = allocaPossibleVars;
- } else {
- item.allocatedNum = 1;
- }
- item.type = addPointing(item.tokens[1].text); // type of pointer we will get
- Types.needAnalysis[item.type] = 0;
- item.type2 = item.tokens[1].text; // value we will create, and get a pointer to
- Types.needAnalysis[item.type2] = 0;
- this.forwardItem(item, 'Reintegrator');
+ function allocaHandler(item) {
+ item.intertype = 'alloca';
+ item.allocatedType = item.tokens[1].text;
+ if (item.tokens.length > 3 && Runtime.isNumberType(item.tokens[3].text)) {
+ item.allocatedNum = toNiceIdent(item.tokens[4].text);
+ item.possibleVars = allocaPossibleVars;
+ } else {
+ item.allocatedNum = 1;
}
- });
+ item.type = addPointing(item.tokens[1].text); // type of pointer we will get
+ Types.needAnalysis[item.type] = 0;
+ item.type2 = item.tokens[1].text; // value we will create, and get a pointer to
+ Types.needAnalysis[item.type2] = 0;
+ return item;
+ }
// 'phi'
- substrate.addActor('Phi', {
- processItem: function(item) {
- item.intertype = 'phi';
- item.type = item.tokens[1].text;
- var typeToken = [item.tokens[1]];
- Types.needAnalysis[item.type] = 0;
- var last = getTokenIndexByText(item.tokens, ';');
- item.params = splitTokenList(item.tokens.slice(2, last)).map(function(segment) {
- var subSegments = splitTokenList(segment[0].item.tokens);
- var ret = {
- intertype: 'phiparam',
- label: toNiceIdent(subSegments[1][0].text),
- value: parseLLVMSegment(typeToken.concat(subSegments[0]))
- };
- return ret;
- }).filter(function(param) { return param.value && param.value.ident != 'undef' });
- this.forwardItem(item, 'Reintegrator');
- }
- });
+ function phiHandler(item) {
+ item.intertype = 'phi';
+ item.type = item.tokens[1].text;
+ var typeToken = [item.tokens[1]];
+ Types.needAnalysis[item.type] = 0;
+ var last = getTokenIndexByText(item.tokens, ';');
+ item.params = splitTokenList(item.tokens.slice(2, last)).map(function(segment) {
+ var subSegments = splitTokenList(segment[0].item.tokens);
+ var ret = {
+ intertype: 'phiparam',
+ label: toNiceIdent(subSegments[1][0].text),
+ value: parseLLVMSegment(typeToken.concat(subSegments[0]))
+ };
+ return ret;
+ }).filter(function(param) { return param.value && param.value.ident != 'undef' });
+ return item;
+ }
// 'phi'
- substrate.addActor('va_arg', {
- processItem: function(item) {
- item.intertype = 'va_arg';
- var segments = splitTokenList(item.tokens.slice(1));
- item.type = segments[1][0].text;
- item.value = parseLLVMSegment(segments[0]);
- this.forwardItem(item, 'Reintegrator');
- }
- });
+ function va_argHandler(item) {
+ item.intertype = 'va_arg';
+ var segments = splitTokenList(item.tokens.slice(1));
+ item.type = segments[1][0].text;
+ item.value = parseLLVMSegment(segments[0]);
+ return item;
+ }
// mathops
- substrate.addActor('Mathops', {
- processItem: function(item) {
- item.intertype = 'mathop';
- item.op = item.tokens[0].text;
- item.variant = null;
- while (item.tokens[1].text in NSW_NUW) item.tokens.splice(1, 1);
- if (['icmp', 'fcmp'].indexOf(item.op) != -1) {
- item.variant = item.tokens[1].text;
- item.tokens.splice(1, 1);
- }
- if (item.tokens[1].text == 'exact') item.tokens.splice(1, 1); // TODO: Implement trap values
- var segments = splitTokenList(item.tokens.slice(1));
- item.params = [];
- for (var i = 1; i <= 4; i++) {
- if (segments[i-1]) {
- if (i > 1 && segments[i-1].length == 1 && segments[0].length > 1 && !isType(segments[i-1][0].text)) {
- segments[i-1].unshift(segments[0][0]); // Add the type from the first segment, they are all alike
- }
- item.params[i-1] = parseLLVMSegment(segments[i-1]);
- }
- }
- var setParamTypes = true;
- if (item.op === 'select') {
- assert(item.params[1].type === item.params[2].type);
- item.type = item.params[1].type;
- } else if (item.op in LLVM.CONVERSIONS) {
- item.type = item.params[1].type;
- setParamTypes = false;
- } else {
- item.type = item.params[0].type;
- }
- if (setParamTypes) {
- for (var i = 0; i < 4; i++) {
- if (item.params[i]) item.params[i].type = item.type; // All params have the same type, normally
+ function mathopsHandler(item) {
+ item.intertype = 'mathop';
+ item.op = item.tokens[0].text;
+ item.variant = null;
+ while (item.tokens[1].text in NSW_NUW) item.tokens.splice(1, 1);
+ if (['icmp', 'fcmp'].indexOf(item.op) != -1) {
+ item.variant = item.tokens[1].text;
+ item.tokens.splice(1, 1);
+ }
+ if (item.tokens[1].text == 'exact') item.tokens.splice(1, 1); // TODO: Implement trap values
+ var segments = splitTokenList(item.tokens.slice(1));
+ item.params = [];
+ for (var i = 1; i <= 4; i++) {
+ if (segments[i-1]) {
+ if (i > 1 && segments[i-1].length == 1 && segments[0].length > 1 && !isType(segments[i-1][0].text)) {
+ segments[i-1].unshift(segments[0][0]); // Add the type from the first segment, they are all alike
}
+ item.params[i-1] = parseLLVMSegment(segments[i-1]);
}
- if (item.op in LLVM.EXTENDS) {
- item.type = item.params[1].ident;
- item.params[0].type = item.params[1].type;
- // TODO: also remove 2nd param?
- } else if (item.op in LLVM.COMPS) {
- item.type = 'i1';
+ }
+ var setParamTypes = true;
+ if (item.op === 'select') {
+ assert(item.params[1].type === item.params[2].type);
+ item.type = item.params[1].type;
+ } else if (item.op in LLVM.CONVERSIONS) {
+ item.type = item.params[1].type;
+ setParamTypes = false;
+ } else {
+ item.type = item.params[0].type;
+ }
+ if (setParamTypes) {
+ for (var i = 0; i < 4; i++) {
+ if (item.params[i]) item.params[i].type = item.type; // All params have the same type, normally
}
- if (USE_TYPED_ARRAYS == 2) {
- // Some specific corrections, since 'i64' is special
- if (item.op in LLVM.SHIFTS) {
- item.params[1].type = 'i32';
- } else if (item.op == 'select') {
- item.params[0].type = 'i1';
- }
+ }
+ if (item.op in LLVM.EXTENDS) {
+ item.type = item.params[1].ident;
+ item.params[0].type = item.params[1].type;
+ // TODO: also remove 2nd param?
+ } else if (item.op in LLVM.COMPS) {
+ item.type = 'i1';
+ }
+ if (USE_TYPED_ARRAYS == 2) {
+ // Some specific corrections, since 'i64' is special
+ if (item.op in LLVM.SHIFTS) {
+ item.params[1].type = 'i32';
+ } else if (item.op == 'select') {
+ item.params[0].type = 'i1';
}
- Types.needAnalysis[item.type] = 0;
- this.forwardItem(item, 'Reintegrator');
}
- });
+ Types.needAnalysis[item.type] = 0;
+ return item;
+ }
// 'store'
- substrate.addActor('Store', {
- processItem: function(item) {
- cleanOutTokens(LLVM.ACCESS_OPTIONS, item.tokens, [0, 1]);
- var segments = splitTokenList(item.tokens.slice(1));
- var ret = {
- intertype: 'store',
- valueType: item.tokens[1].text,
- value: parseLLVMSegment(segments[0]),
- pointer: parseLLVMSegment(segments[1]),
- lineNum: item.lineNum
- };
- Types.needAnalysis[ret.valueType] = 0;
- ret.ident = toNiceIdent(ret.pointer.ident);
- ret.pointerType = ret.pointer.type;
- Types.needAnalysis[ret.pointerType] = 0;
- if (segments.length > 2) {
- assert(segments[2][0].text == 'align');
- ret.align = parseInt(segments[2][1].text) || QUANTUM_SIZE; // 0 means preferred arch align
- } else {
- ret.align = QUANTUM_SIZE;
- }
- return [ret];
+ function storeHandler(item) {
+ cleanOutTokens(LLVM.ACCESS_OPTIONS, item.tokens, [0, 1]);
+ var segments = splitTokenList(item.tokens.slice(1));
+ var ret = {
+ intertype: 'store',
+ valueType: item.tokens[1].text,
+ value: parseLLVMSegment(segments[0]),
+ pointer: parseLLVMSegment(segments[1]),
+ lineNum: item.lineNum
+ };
+ Types.needAnalysis[ret.valueType] = 0;
+ ret.ident = toNiceIdent(ret.pointer.ident);
+ ret.pointerType = ret.pointer.type;
+ Types.needAnalysis[ret.pointerType] = 0;
+ if (segments.length > 2) {
+ assert(segments[2][0].text == 'align');
+ ret.align = parseInt(segments[2][1].text) || QUANTUM_SIZE; // 0 means preferred arch align
+ } else {
+ ret.align = QUANTUM_SIZE;
}
- });
+ return ret;
+ }
// 'br'
- substrate.addActor('Branch', {
- processItem: function(item) {
- if (item.tokens[1].text == 'label') {
- return [{
- intertype: 'branch',
- label: toNiceIdent(item.tokens[2].text),
- lineNum: item.lineNum
- }];
- } else {
- var commaIndex = findTokenText(item, ',');
- return [{
- intertype: 'branch',
- value: parseLLVMSegment(item.tokens.slice(1, commaIndex)),
- labelTrue: toNiceIdent(item.tokens[commaIndex+2].text),
- labelFalse: toNiceIdent(item.tokens[commaIndex+5].text),
- lineNum: item.lineNum
- }];
- }
- }
- });
- // 'ret'
- substrate.addActor('Return', {
- processItem: function(item) {
- var type = item.tokens[1].text;
- Types.needAnalysis[type] = 0;
- return [{
- intertype: 'return',
- type: type,
- value: (item.tokens[2] && type !== 'void') ? parseLLVMSegment(item.tokens.slice(1)) : null,
+ function branchHandler(item) {
+ if (item.tokens[1].text == 'label') {
+ return {
+ intertype: 'branch',
+ label: toNiceIdent(item.tokens[2].text),
lineNum: item.lineNum
- }];
- }
- });
- // 'resume' - partial implementation
- substrate.addActor('Resume', {
- processItem: function(item) {
- return [{
- intertype: 'resume',
- ident: toNiceIdent(item.tokens[2].text),
+ };
+ } else {
+ var commaIndex = findTokenText(item, ',');
+ return {
+ intertype: 'branch',
+ value: parseLLVMSegment(item.tokens.slice(1, commaIndex)),
+ labelTrue: toNiceIdent(item.tokens[commaIndex+2].text),
+ labelFalse: toNiceIdent(item.tokens[commaIndex+5].text),
lineNum: item.lineNum
- }];
+ };
}
- });
+ }
+ // 'ret'
+ function returnHandler(item) {
+ var type = item.tokens[1].text;
+ Types.needAnalysis[type] = 0;
+ return {
+ intertype: 'return',
+ type: type,
+ value: (item.tokens[2] && type !== 'void') ? parseLLVMSegment(item.tokens.slice(1)) : null,
+ lineNum: item.lineNum
+ };
+ }
+ // 'resume' - partial implementation
+ function resumeHandler(item) {
+ return {
+ intertype: 'resume',
+ ident: toNiceIdent(item.tokens[2].text),
+ lineNum: item.lineNum
+ };
+ }
// 'switch'
- substrate.addActor('Switch', {
- processItem: function(item) {
- function parseSwitchLabels(item) {
- var ret = [];
- var tokens = item.item.tokens;
- while (tokens.length > 0) {
- ret.push({
- value: tokens[1].text,
- label: toNiceIdent(tokens[4].text)
- });
- tokens = tokens.slice(5);
- }
- return ret;
+ function switchHandler(item) {
+ function parseSwitchLabels(item) {
+ var ret = [];
+ var tokens = item.item.tokens;
+ while (tokens.length > 0) {
+ ret.push({
+ value: tokens[1].text,
+ label: toNiceIdent(tokens[4].text)
+ });
+ tokens = tokens.slice(5);
}
- var type = item.tokens[1].text;
- Types.needAnalysis[type] = 0;
- return [{
- intertype: 'switch',
- type: type,
- ident: toNiceIdent(item.tokens[2].text),
- defaultLabel: toNiceIdent(item.tokens[5].text),
- switchLabels: parseSwitchLabels(item.tokens[6]),
- lineNum: item.lineNum
- }];
+ return ret;
}
- });
+ var type = item.tokens[1].text;
+ Types.needAnalysis[type] = 0;
+ return {
+ intertype: 'switch',
+ type: type,
+ ident: toNiceIdent(item.tokens[2].text),
+ defaultLabel: toNiceIdent(item.tokens[5].text),
+ switchLabels: parseSwitchLabels(item.tokens[6]),
+ lineNum: item.lineNum
+ };
+ }
// function end
- substrate.addActor('FuncEnd', {
- processItem: function(item) {
- return [{
- intertype: 'functionEnd',
- lineNum: item.lineNum
- }];
- }
- });
+ function funcEndHandler(item) {
+ return {
+ intertype: 'functionEnd',
+ lineNum: item.lineNum
+ };
+ }
// external function stub
- substrate.addActor('External', {
- processItem: function(item) {
- while (item.tokens[1].text in LLVM.LINKAGES || item.tokens[1].text in LLVM.PARAM_ATTR || item.tokens[1].text in LLVM.VISIBILITIES || item.tokens[1].text in LLVM.CALLING_CONVENTIONS) {
- item.tokens.splice(1, 1);
- }
- var params = parseParamTokens(item.tokens[3].item.tokens);
- return [{
- intertype: 'functionStub',
- ident: toNiceIdent(item.tokens[2].text),
- returnType: item.tokens[1],
- params: params,
- hasVarArgs: hasVarArgs(params),
- lineNum: item.lineNum
- }];
+ function externalHandler(item) {
+ while (item.tokens[1].text in LLVM.LINKAGES || item.tokens[1].text in LLVM.PARAM_ATTR || item.tokens[1].text in LLVM.VISIBILITIES || item.tokens[1].text in LLVM.CALLING_CONVENTIONS) {
+ item.tokens.splice(1, 1);
}
- });
+ var params = parseParamTokens(item.tokens[3].item.tokens);
+ return {
+ intertype: 'functionStub',
+ ident: toNiceIdent(item.tokens[2].text),
+ returnType: item.tokens[1],
+ params: params,
+ hasVarArgs: hasVarArgs(params),
+ lineNum: item.lineNum
+ };
+ }
// 'unreachable'
- substrate.addActor('Unreachable', {
- processItem: function(item) {
- return [{
- intertype: 'unreachable',
- lineNum: item.lineNum
- }];
- }
- });
+ function unreachableHandler(item) {
+ return {
+ intertype: 'unreachable',
+ lineNum: item.lineNum
+ };
+ }
// 'indirectbr'
- substrate.addActor('IndirectBr', {
- processItem: function(item) {
- var ret = {
- intertype: 'indirectbr',
- value: parseLLVMSegment(splitTokenList(item.tokens.slice(1))[0]),
- type: item.tokens[1].text,
- lineNum: item.lineNum
- };
- Types.needAnalysis[ret.type] = 0;
- return [ret];
+ function indirectBrHandler(item) {
+ var ret = {
+ intertype: 'indirectbr',
+ value: parseLLVMSegment(splitTokenList(item.tokens.slice(1))[0]),
+ type: item.tokens[1].text,
+ lineNum: item.lineNum
+ };
+ Types.needAnalysis[ret.type] = 0;
+ return ret;
+ }
+
+ // Fast paths - quick parses of common patterns, avoid tokenizing entirely
+
+ function tryFastPaths(line) {
+ var m, ret;
+ if (phase === 'pre') {
+ // string constant
+ if (0) { // works, but not worth it m = /([@\.\w\d_]+) = (private )?(unnamed_addr )?(constant )?(\[\d+ x i8\]) c"([^"]+)".*/.exec(line.lineText)) {
+ if (m[1] === '@llvm.global_ctors') return ret;
+ ret = {
+ intertype: 'globalVariable',
+ ident: toNiceIdent(m[1]),
+ type: m[5],
+ external: false,
+ private_: m[2] !== null,
+ named: m[3] === null,
+ lineNum: line.lineNum,
+ value: {
+ intertype: 'string',
+ text: m[6]
+ }
+ };
+ noteGlobalVariable(ret);
+ }
+ } else if (phase === 'funcs') {
+ if (m = /^ (%[\w\d\._]+) = (getelementptr|load) ([%\w\d\._ ,\*\-@]+)$/.exec(line.lineText)) {
+ var assignTo = m[1];
+ var intertype = m[2];
+ var args = m[3];
+ switch (intertype) {
+ case 'getelementptr': {
+ if (args[0] === 'i' && args.indexOf('inbounds ') === 0) {
+ args = args.substr(9);
+ }
+ var params = args.split(', ').map(function(param) {
+ var parts = param.split(' ');
+ assert(parts.length === 2);
+ Types.needAnalysis[parts[0]] = 0;
+ return {
+ intertype: 'value',
+ type: parts[0],
+ ident: toNiceIdent(parts[1]),
+ byVal: 0
+ }
+ });
+ ret = {
+ intertype: 'getelementptr',
+ lineNum: line.lineNum,
+ assignTo: toNiceIdent(assignTo),
+ ident: params[0].ident,
+ type: '*',
+ params: params
+ };
+ break;
+ }
+ case 'load': {
+ if (m = /(^[%\w\d\._\-@\*]+) ([%\w\d\._\-@]+)(, align \d+)?$/.exec(args)) {
+ var ident = toNiceIdent(m[2]);
+ var type = m[1];
+ assert(type[type.length-1] === '*', type);
+ var valueType = type.substr(0, type.length-1);
+ ret = {
+ intertype: 'load',
+ lineNum: line.lineNum,
+ assignTo: toNiceIdent(assignTo),
+ ident: ident,
+ type: valueType,
+ valueType: valueType,
+ pointerType: type,
+ pointer: {
+ intertype: 'value',
+ ident: ident,
+ type: type,
+ },
+ align: parseAlign(m[3])
+ };
+ }
+ break;
+ }
+ default: throw 'unexpected fast path type ' + intertype;
+ }
+ //else if (line.lineText.indexOf(' = load ') > 0) printErr('close: ' + JSON.stringify(line.lineText));
+ }
}
- });
+ if (ret) {
+ if (COMPILER_ASSERTIONS) {
+ //printErr(['\n', JSON.stringify(ret), '\n', JSON.stringify(triager(tokenizer(line)))]);
+ var normal = triager(tokenizer(line));
+ delete normal.tokens;
+ delete normal.indent;
+ assert(sortedJsonCompare(normal, ret), 'fast path: ' + dump(normal) + '\n vs \n' + dump(ret));
+ }
+ }
+ return ret;
+ }
// Input
- substrate.addItem({
- llvmLines: data
- }, 'LineSplitter');
+ lineSplitter().forEach(function(line) {
+ var item = tryFastPaths(line);
+ if (item) {
+ finalResults.push(item);
+ fastPaths++;
+ return;
+ }
+ slowPaths++;
- substrate.onResult = function(result) {
- if (result.tokens) result.tokens = null; // We do not need tokens, past the intertyper. Clean them up as soon as possible here.
- };
+ //var time = Date.now();
+
+ var t = tokenizer(line);
+ item = triager(t);
+
+ /*
+ var type = item ? item.intertype + (item.op ? ':' + item.op : ''): 'none';
+ if (!interProf[type]) interProf[type] = { ms: 0, n: 0 };
+ interProf[type].ms += Date.now() - time;
+ interProf[type].n++;
+ */
+
+ if (!item) return;
+ finalResults.push(item);
+ if (item.tokens) item.tokens = null; // We do not need tokens, past the intertyper. Clean them up as soon as possible here.
+ });
+ return finalResults;
+}
+
+// intertyper profiler
- return substrate.solve();
+/*
+var interProf = {};
+function dumpInterProf() {
+ printErr('\nintertyper/' + phase + ' (ms | n): ' + JSON.stringify(keys(interProf).sort(function(x, y) { return interProf[y].ms - interProf[x].ms }).map(function(x) { return x + ' : ' + interProf[x].ms + ' | ' + interProf[x].n }), null, ' ') + '\n');
}
+*/
diff --git a/src/jsifier.js b/src/jsifier.js
index 1f53b1a2..96cb8d9a 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -22,6 +22,8 @@ var functionStubSigs = {};
function JSify(data, functionsOnly, givenFunctions) {
var mainPass = !functionsOnly;
+ var itemsDict = { type: [], GlobalVariableStub: [], functionStub: [], function: [], GlobalVariable: [], GlobalVariablePostSet: [] };
+
if (mainPass) {
var shellFile = SHELL_FILE ? SHELL_FILE : (BUILD_AS_SHARED_LIB || SIDE_MODULE ? 'shell_sharedlib.js' : 'shell.js');
@@ -58,17 +60,6 @@ function JSify(data, functionsOnly, givenFunctions) {
}
}
- // Does simple 'macro' substitution, using Django-like syntax,
- // {{{ code }}} will be replaced with |eval(code)|.
- function processMacros(text) {
- return text.replace(/{{{[^}]+}}}/g, function(str) {
- str = str.substr(3, str.length-6);
- return eval(str).toString();
- });
- }
-
- var substrate = new Substrate('JSifyer');
-
if (mainPass) {
// Handle unparsed types TODO: Batch them
analyzer(intertyper(data.unparsedTypess[0].lines, true), true);
@@ -138,21 +129,6 @@ function JSify(data, functionsOnly, givenFunctions) {
// Actors
- // type
- // FIXME: This is no longer used, we do not actually need to JSify on types. TODO: Remove this and related code
- substrate.addActor('Type', {
- processItem: function(item) {
- var type = Types.types[item.name_];
- var niceName = toNiceIdent(item.name_);
- // We might export all of Types.types, cleaner that way, but do not want slowdowns in accessing flatteners
- item.JS = 'var ' + niceName + '___SIZE = ' + Types.types[item.name_].flatSize + '; // ' + item.name_ + '\n';
- if (type.needsFlattening && !type.flatFactor) {
- item.JS += 'var ' + niceName + '___FLATTENER = ' + JSON.stringify(Types.types[item.name_].flatIndexes) + ';';
- }
- return [item];
- }
- });
-
function makeEmptyStruct(type) {
var ret = [];
var typeData = Types.types[type];
@@ -255,146 +231,144 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// globalVariable
- substrate.addActor('GlobalVariable', {
- processItem: function(item) {
- function needsPostSet(value) {
- if (typeof value !== 'string') return false;
- return value[0] in UNDERSCORE_OPENPARENS || value.substr(0, 14) === 'CHECK_OVERFLOW'
- || value.substr(0, 6) === 'GLOBAL';
- }
-
- item.intertype = 'GlobalVariableStub';
- assert(!item.lines); // FIXME remove this, after we are sure it isn't needed
- var ret = [item];
- if (item.ident == '_llvm_global_ctors') {
- item.JS = '\n/* global initializers */ __ATINIT__.push(' +
- item.ctors.map(function(ctor) { return '{ func: function() { ' + ctor + '() } }' }).join(',') +
- ');\n';
- return ret;
- }
+ function globalVariableHandler(item) {
+ function needsPostSet(value) {
+ if (typeof value !== 'string') return false;
+ return value[0] in UNDERSCORE_OPENPARENS || value.substr(0, 14) === 'CHECK_OVERFLOW'
+ || value.substr(0, 6) === 'GLOBAL';
+ }
+
+ item.intertype = 'GlobalVariableStub';
+ itemsDict.GlobalVariableStub.push(item);
+ assert(!item.lines); // FIXME remove this, after we are sure it isn't needed
+ if (item.ident == '_llvm_global_ctors') {
+ item.JS = '\n/* global initializers */ __ATINIT__.push(' +
+ item.ctors.map(function(ctor) { return '{ func: function() { ' + ctor + '() } }' }).join(',') +
+ ');\n';
+ return;
+ }
- var constant = null;
- var allocator = (BUILD_AS_SHARED_LIB && !item.external) ? 'ALLOC_NORMAL' : 'ALLOC_STATIC';
- var index = null;
- if (item.external && BUILD_AS_SHARED_LIB) {
- // External variables in shared libraries should not be declared as
- // they would shadow similarly-named globals in the parent.
- item.JS = '';
- } else {
- item.JS = makeGlobalDef(item.ident);
- }
+ var constant = null;
+ var allocator = (BUILD_AS_SHARED_LIB && !item.external) ? 'ALLOC_NORMAL' : 'ALLOC_STATIC';
+ var index = null;
+ if (item.external && BUILD_AS_SHARED_LIB) {
+ // External variables in shared libraries should not be declared as
+ // they would shadow similarly-named globals in the parent.
+ item.JS = '';
+ } else {
+ item.JS = makeGlobalDef(item.ident);
+ }
- if (!NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
- index = makeGlobalUse(item.ident); // index !== null indicates we are indexing this
- allocator = 'ALLOC_NONE';
- }
+ if (!NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
+ index = makeGlobalUse(item.ident); // index !== null indicates we are indexing this
+ allocator = 'ALLOC_NONE';
+ }
- Variables.globals[item.ident].named = item.named;
+ Variables.globals[item.ident].named = item.named;
- if (ASM_JS && (MAIN_MODULE || SIDE_MODULE) && !item.private_ && !NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
- // We need this to be named (and it normally would not be), so that it can be linked to and used from other modules
- Variables.globals[item.ident].linkable = 1;
- }
+ if (ASM_JS && (MAIN_MODULE || SIDE_MODULE) && !item.private_ && !NAMED_GLOBALS && isIndexableGlobal(item.ident)) {
+ // We need this to be named (and it normally would not be), so that it can be linked to and used from other modules
+ Variables.globals[item.ident].linkable = 1;
+ }
- if (isBSS(item)) {
- var length = calcAllocatedSize(item.type);
- length = Runtime.alignMemory(length);
+ if (isBSS(item)) {
+ var length = calcAllocatedSize(item.type);
+ length = Runtime.alignMemory(length);
- // If using indexed globals, go ahead and early out (no need to explicitly
- // initialize).
- if (!NAMED_GLOBALS) {
- return ret;
- }
- // If using named globals, we can at least shorten the call to allocate by
- // passing an integer representing the size of memory to alloc instead of
- // an array of 0s of size length.
- else {
- constant = length;
+ // If using indexed globals, go ahead and early out (no need to explicitly
+ // initialize).
+ if (!NAMED_GLOBALS) {
+ return;
+ }
+ // If using named globals, we can at least shorten the call to allocate by
+ // passing an integer representing the size of memory to alloc instead of
+ // an array of 0s of size length.
+ else {
+ constant = length;
+ }
+ } else {
+ if (item.external) {
+ if (Runtime.isNumberType(item.type) || isPointerType(item.type)) {
+ constant = zeros(Runtime.getNativeFieldSize(item.type));
+ } else {
+ constant = makeEmptyStruct(item.type);
}
} else {
- if (item.external) {
- if (Runtime.isNumberType(item.type) || isPointerType(item.type)) {
- constant = zeros(Runtime.getNativeFieldSize(item.type));
- } else {
- constant = makeEmptyStruct(item.type);
- }
- } else {
- constant = parseConst(item.value, item.type, item.ident);
+ constant = parseConst(item.value, item.type, item.ident);
+ }
+ assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]);
+
+ // This is a flattened object. We need to find its idents, so they can be assigned to later
+ var structTypes = null;
+ constant.forEach(function(value, i) {
+ if (needsPostSet(value)) { // ident, or expression containing an ident
+ if (!structTypes) structTypes = generateStructTypes(item.type);
+ itemsDict.GlobalVariablePostSet.push({
+ intertype: 'GlobalVariablePostSet',
+ JS: makeSetValue(makeGlobalUse(item.ident), i, value, structTypes[i], false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors
+ });
+ constant[i] = '0';
}
- assert(typeof constant === 'object');//, [typeof constant, JSON.stringify(constant), item.external]);
-
- // This is a flattened object. We need to find its idents, so they can be assigned to later
- var structTypes = null;
- constant.forEach(function(value, i) {
- if (needsPostSet(value)) { // ident, or expression containing an ident
- if (!structTypes) structTypes = generateStructTypes(item.type);
- ret.push({
- intertype: 'GlobalVariablePostSet',
- JS: makeSetValue(makeGlobalUse(item.ident), i, value, structTypes[i], false, true) + ';' // ignore=true, since e.g. rtti and statics cause lots of safe_heap errors
- });
- constant[i] = '0';
- }
- });
+ });
- if (item.external) {
- // External variables in shared libraries should not be declared as
- // they would shadow similarly-named globals in the parent, so do nothing here.
- if (BUILD_AS_SHARED_LIB) return ret;
- if (SIDE_MODULE) return [];
- // Library items need us to emit something, but everything else requires nothing.
- if (!LibraryManager.library[item.ident.slice(1)]) return ret;
+ if (item.external) {
+ // External variables in shared libraries should not be declared as
+ // they would shadow similarly-named globals in the parent, so do nothing here.
+ if (BUILD_AS_SHARED_LIB) return;
+ if (SIDE_MODULE) {
+ itemsDict.GlobalVariableStub.pop(); // remove this item
+ return;
}
+ // Library items need us to emit something, but everything else requires nothing.
+ if (!LibraryManager.library[item.ident.slice(1)]) return;
+ }
- // ensure alignment
- constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length));
+ // ensure alignment
+ constant = constant.concat(zeros(Runtime.alignMemory(constant.length) - constant.length));
- // Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations
- if (item.ident.substr(0, 5) == '__ZTV') {
- constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE)));
- }
+ // Special case: class vtables. We make sure they are null-terminated, to allow easy runtime operations
+ if (item.ident.substr(0, 5) == '__ZTV') {
+ constant = constant.concat(zeros(Runtime.alignMemory(QUANTUM_SIZE)));
}
+ }
- // NOTE: This is the only place that could potentially create static
- // allocations in a shared library.
- constant = makePointer(constant, null, allocator, item.type, index);
+ // NOTE: This is the only place that could potentially create static
+ // allocations in a shared library.
+ constant = makePointer(constant, null, allocator, item.type, index);
- var js = (index !== null ? '' : item.ident + '=') + constant;
- if (js) js += ';';
+ var js = (index !== null ? '' : item.ident + '=') + constant;
+ if (js) js += ';';
- if (!ASM_JS && NAMED_GLOBALS && (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS))) {
- js += '\nModule["' + item.ident + '"] = ' + item.ident + ';';
- }
- if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
- // TODO: make the assert conditional on ASSERTIONS
- js += 'if (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + item.ident + ' }';
- }
- if (item.external && !NAMED_GLOBALS) {
- js = 'var ' + item.ident + ' = ' + js; // force an explicit naming, even if unnamed globals, for asm forwarding
- }
- return ret.concat({
- intertype: 'GlobalVariable',
- JS: js,
- });
+ if (!ASM_JS && NAMED_GLOBALS && (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS))) {
+ js += '\nModule["' + item.ident + '"] = ' + item.ident + ';';
}
- });
+ if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
+ // TODO: make the assert conditional on ASSERTIONS
+ js += 'if (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + item.ident + ' }';
+ }
+ if (item.external && !NAMED_GLOBALS) {
+ js = 'var ' + item.ident + ' = ' + js; // force an explicit naming, even if unnamed globals, for asm forwarding
+ }
+ itemsDict.GlobalVariableStub.push({
+ intertype: 'GlobalVariable',
+ JS: js,
+ });
+ }
// alias
- substrate.addActor('Alias', {
- processItem: function(item) {
- item.intertype = 'GlobalVariableStub';
- var ret = [item];
- 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
- Variables.globals[item.ident].targetIdent = item.value.ident;
- var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value);
- if ((MAIN_MODULE || SIDE_MODULE) && isFunctionType(item.type)) {
- var target = item.value.ident;
- if (!Functions.aliases[target]) Functions.aliases[target] = [];
- Functions.aliases[target].push(item.ident);
- }
- return ret;
+ function aliasHandler(item) {
+ item.intertype = 'GlobalVariableStub';
+ itemsDict.GlobalVariableStub.push(item);
+ 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
+ Variables.globals[item.ident].targetIdent = item.value.ident;
+ var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value);
+ if ((MAIN_MODULE || SIDE_MODULE) && isFunctionType(item.type)) {
+ var target = item.value.ident;
+ if (!Functions.aliases[target]) Functions.aliases[target] = [];
+ Functions.aliases[target].push(item.ident);
}
- });
+ }
function processLibraryFunction(snippet, ident) {
snippet = snippet.toString();
@@ -411,147 +385,163 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// functionStub
- substrate.addActor('FunctionStub', {
- processItem: function(item) {
- // note the signature
- if (item.returnType && item.params) {
- functionStubSigs[item.ident] = Functions.getSignature(item.returnType.text, item.params.map(function(arg) { return arg.type }), false);
- }
-
- function addFromLibrary(ident) {
- if (ident in addedLibraryItems) return '';
- addedLibraryItems[ident] = true;
-
- // dependencies can be JS functions, which we just run
- if (typeof ident == 'function') return ident();
-
- // Don't replace implemented functions with library ones (which can happen when we add dependencies).
- // Note: We don't return the dependencies here. Be careful not to end up where this matters
- if (('_' + ident) in Functions.implementedFunctions) return '';
-
- var snippet = LibraryManager.library[ident];
- var redirectedIdent = null;
- var deps = LibraryManager.library[ident + '__deps'] || [];
- var isFunction = false;
-
- if (typeof snippet === 'string') {
- var target = LibraryManager.library[snippet];
- if (target) {
- // Redirection for aliases. We include the parent, and at runtime make ourselves equal to it.
- // This avoid having duplicate functions with identical content.
- redirectedIdent = snippet;
- deps.push(snippet);
- snippet = '_' + snippet;
- }
- // In asm, we need to know about library functions. If there is a target, though, then no
- // need to consider this a library function - we will call directly to it anyhow
- if (ASM_JS && !redirectedIdent && (typeof target == 'function' || /Math\.\w+/.exec(snippet))) {
- Functions.libraryFunctions[ident] = 1;
- }
- } else if (typeof snippet === 'object') {
- snippet = stringifyWithFunctions(snippet);
- } else if (typeof snippet === 'function') {
- isFunction = true;
- snippet = processLibraryFunction(snippet, ident);
- if (ASM_JS) Functions.libraryFunctions[ident] = 1;
+ function functionStubHandler(item) {
+ // note the signature
+ if (item.returnType && item.params) {
+ functionStubSigs[item.ident] = Functions.getSignature(item.returnType.text, item.params.map(function(arg) { return arg.type }), false);
+ }
+
+ function addFromLibrary(ident) {
+ if (ident in addedLibraryItems) return '';
+ addedLibraryItems[ident] = true;
+
+ // dependencies can be JS functions, which we just run
+ if (typeof ident == 'function') return ident();
+
+ // Don't replace implemented functions with library ones (which can happen when we add dependencies).
+ // Note: We don't return the dependencies here. Be careful not to end up where this matters
+ if (('_' + ident) in Functions.implementedFunctions) return '';
+
+ var snippet = LibraryManager.library[ident];
+ var redirectedIdent = null;
+ var deps = LibraryManager.library[ident + '__deps'] || [];
+ var isFunction = false;
+
+ if (typeof snippet === 'string') {
+ var target = LibraryManager.library[snippet];
+ if (target) {
+ // Redirection for aliases. We include the parent, and at runtime make ourselves equal to it.
+ // This avoid having duplicate functions with identical content.
+ redirectedIdent = snippet;
+ deps.push(snippet);
+ snippet = '_' + snippet;
}
-
- var postsetId = ident + '__postset';
- var postset = LibraryManager.library[postsetId];
- if (postset && !addedLibraryItems[postsetId] && !SIDE_MODULE) {
- addedLibraryItems[postsetId] = true;
- ret.push({
- intertype: 'GlobalVariablePostSet',
- JS: postset
- });
+ // In asm, we need to know about library functions. If there is a target, though, then no
+ // need to consider this a library function - we will call directly to it anyhow
+ if (ASM_JS && !redirectedIdent && (typeof target == 'function' || /Math\.\w+/.exec(snippet))) {
+ Functions.libraryFunctions[ident] = 1;
}
+ } else if (typeof snippet === 'object') {
+ snippet = stringifyWithFunctions(snippet);
+ } else if (typeof snippet === 'function') {
+ isFunction = true;
+ snippet = processLibraryFunction(snippet, ident);
+ if (ASM_JS) Functions.libraryFunctions[ident] = 1;
+ }
+
+ var postsetId = ident + '__postset';
+ var postset = LibraryManager.library[postsetId];
+ if (postset && !addedLibraryItems[postsetId] && !SIDE_MODULE) {
+ addedLibraryItems[postsetId] = true;
+ itemsDict.GlobalVariablePostSet.push({
+ intertype: 'GlobalVariablePostSet',
+ JS: postset
+ });
+ }
- if (redirectedIdent) {
- deps = deps.concat(LibraryManager.library[redirectedIdent + '__deps'] || []);
- }
- if (ASM_JS) {
- // In asm, dependencies implemented in C might be needed by JS library functions.
- // We don't know yet if they are implemented in C or not. To be safe, export such
- // special cases.
- [LIBRARY_DEPS_TO_AUTOEXPORT].forEach(function(special) {
- deps.forEach(function(dep) {
- if (dep == special && !EXPORTED_FUNCTIONS[dep]) {
- EXPORTED_FUNCTIONS[dep] = 1;
- }
- });
+ if (redirectedIdent) {
+ deps = deps.concat(LibraryManager.library[redirectedIdent + '__deps'] || []);
+ }
+ if (ASM_JS) {
+ // In asm, dependencies implemented in C might be needed by JS library functions.
+ // We don't know yet if they are implemented in C or not. To be safe, export such
+ // special cases.
+ [LIBRARY_DEPS_TO_AUTOEXPORT].forEach(function(special) {
+ deps.forEach(function(dep) {
+ if (dep == special && !EXPORTED_FUNCTIONS[dep]) {
+ EXPORTED_FUNCTIONS[dep] = 1;
+ }
});
+ });
+ }
+ // $ident's are special, we do not prefix them with a '_'.
+ if (ident[0] === '$') {
+ ident = ident.substr(1);
+ } else {
+ ident = '_' + ident;
+ }
+ if (VERBOSE) printErr('adding ' + ident + ' and deps ' + deps);
+ var depsText = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
+ var contentText = isFunction ? snippet : ('var ' + ident + '=' + snippet + ';');
+ if (ASM_JS) {
+ var sig = LibraryManager.library[ident.substr(1) + '__sig'];
+ if (isFunction && sig && LibraryManager.library[ident.substr(1) + '__asm']) {
+ // asm library function, add it as generated code alongside the generated code
+ Functions.implementedFunctions[ident] = sig;
+ asmLibraryFunctions.push(contentText);
+ contentText = ' ';
+ EXPORTED_FUNCTIONS[ident] = 1;
+ Functions.libraryFunctions[ident.substr(1)] = 2;
}
- // $ident's are special, we do not prefix them with a '_'.
- if (ident[0] === '$') {
- ident = ident.substr(1);
- } else {
- ident = '_' + ident;
- }
- if (VERBOSE) printErr('adding ' + ident + ' and deps ' + deps);
- var depsText = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
- var contentText = isFunction ? snippet : ('var ' + ident + '=' + snippet + ';');
- if (ASM_JS) {
- var sig = LibraryManager.library[ident.substr(1) + '__sig'];
- if (isFunction && sig && LibraryManager.library[ident.substr(1) + '__asm']) {
- // asm library function, add it as generated code alongside the generated code
- Functions.implementedFunctions[ident] = sig;
- asmLibraryFunctions.push(contentText);
- contentText = ' ';
- EXPORTED_FUNCTIONS[ident] = 1;
- Functions.libraryFunctions[ident.substr(1)] = 2;
- }
- }
- if (SIDE_MODULE) return ';'; // we import into the side module js library stuff from the outside parent
- if ((!ASM_JS || phase == 'pre') &&
- (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS))) {
- contentText += '\nModule["' + ident + '"] = ' + ident + ';';
- }
- return depsText + contentText;
}
+ if (SIDE_MODULE) return ';'; // we import into the side module js library stuff from the outside parent
+ if ((!ASM_JS || phase == 'pre') &&
+ (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS))) {
+ contentText += '\nModule["' + ident + '"] = ' + ident + ';';
+ }
+ return depsText + contentText;
+ }
- var ret = [item];
- if (IGNORED_FUNCTIONS.indexOf(item.ident) >= 0) return null;
- var shortident = item.ident.substr(1);
- if (BUILD_AS_SHARED_LIB) {
- // Shared libraries reuse the runtime of their parents.
- item.JS = '';
- } else {
- // If this is not linkable, anything not in the library is definitely missing
- var cancel = false;
- if (!LINKABLE && !LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) {
- if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + shortident);
- if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) printErr('warning: unresolved symbol: ' + shortident);
- if (ASM_JS || item.ident in DEAD_FUNCTIONS) {
- // emit a stub that will fail during runtime. this allows asm validation to succeed.
- LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);");
- } else {
- cancel = true; // emit nothing, not even var X = undefined;
- }
+ itemsDict.functionStub.push(item);
+ if (IGNORED_FUNCTIONS.indexOf(item.ident) >= 0) return;
+ var shortident = item.ident.substr(1);
+ if (BUILD_AS_SHARED_LIB) {
+ // Shared libraries reuse the runtime of their parents.
+ item.JS = '';
+ } else {
+ // If this is not linkable, anything not in the library is definitely missing
+ var cancel = false;
+ if (!LINKABLE && !LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) {
+ if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + shortident);
+ if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) printErr('warning: unresolved symbol: ' + shortident);
+ if (ASM_JS || item.ident in DEAD_FUNCTIONS) {
+ // emit a stub that will fail during runtime. this allows asm validation to succeed.
+ LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);");
+ } else {
+ cancel = true; // emit nothing, not even var X = undefined;
}
- item.JS = cancel ? ';' : addFromLibrary(shortident);
}
- return ret;
+ item.JS = cancel ? ';' : addFromLibrary(shortident);
}
- });
+ }
// function splitter
- substrate.addActor('FunctionSplitter', {
- processItem: function(item) {
- var ret = [item];
- item.splitItems = 0;
- item.labels.forEach(function(label) {
- label.lines.forEach(function(line) {
- line.func = item.ident;
- line.funcData = item; // TODO: remove all these, access it globally
- line.parentLabel = label.ident;
- ret.push(line);
- item.splitItems ++;
- });
- });
-
- this.forwardItems(ret, 'FuncLineTriager');
- }
- });
+ function functionSplitter(item) {
+ item.lines.forEach(function(line) {
+ Framework.currItem = line;
+ line.funcData = item; // TODO: remove all these, access it globally
+ switch (line.intertype) {
+ case 'value': line.JS = valueHandler(line); break;
+ case 'noop': line.JS = noopHandler(line); break;
+ case 'var': line.JS = varHandler(line); break;
+ case 'store': line.JS = storeHandler(line); break;
+ case 'deleted': line.JS = deletedHandler(line); break;
+ case 'branch': line.JS = branchHandler(line); break;
+ case 'switch': line.JS = switchHandler(line); break;
+ case 'return': line.JS = returnHandler(line); break;
+ case 'resume': line.JS = resumeHandler(line); break;
+ case 'invoke': line.JS = invokeHandler(line); break;
+ case 'atomic': line.JS = atomicHandler(line); break;
+ case 'landingpad': line.JS = landingpadHandler(line); break;
+ case 'load': line.JS = loadHandler(line); break;
+ case 'extractvalue': line.JS = extractvalueHandler(line); break;
+ case 'insertvalue': line.JS = insertvalueHandler(line); break;
+ case 'indirectbr': line.JS = indirectbrHandler(line); break;
+ case 'alloca': line.JS = allocaHandler(line); break;
+ case 'va_arg': line.JS = va_argHandler(line); break;
+ case 'mathop': line.JS = mathopHandler(line); break;
+ case 'bitcast': line.JS = bitcastHandler(line); break;
+ case 'getelementptr': line.JS = getelementptrHandler(line); break;
+ case 'call': line.JS = callHandler(line); break;
+ case 'unreachable': line.JS = unreachableHandler(line); break;
+ default: throw 'what is this line? ' + dump(line);
+ }
+ assert(line.JS);
+ if (line.assignTo) makeAssign(line);
+ Framework.currItem = null;
+ });
+ functionReconstructor(item);
+ }
// function for filtering functions for label debugging
if (LABEL_FUNCTION_FILTERS.length > 0) {
@@ -567,322 +557,297 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// function reconstructor & post-JS optimizer
- substrate.addActor('FunctionReconstructor', {
- funcs: {},
- seen: {},
- processItem: function(item) {
- if (this.seen[item.__uid__]) return null;
- if (item.intertype == 'function') {
- this.funcs[item.ident] = item;
- item.relines = {};
- this.seen[item.__uid__] = true;
- return null;
- }
- var line = item;
- var func = this.funcs[line.func];
- if (!func) return null;
-
- // Re-insert our line
- this.seen[item.__uid__] = true;
- var label = func.labels.filter(function(label) { return label.ident == line.parentLabel })[0];
- label.lines = label.lines.map(function(line2) {
- return (line2.lineNum !== line.lineNum) ? line2 : line;
- });
- func.splitItems --;
- // OLD delete line.funcData; // clean up
- if (func.splitItems > 0) return null;
+ function functionReconstructor(func) {
+ // We have this function all reconstructed, go and finalize it's JS!
- // We have this function all reconstructed, go and finalize it's JS!
+ if (IGNORED_FUNCTIONS.indexOf(func.ident) >= 0) return null;
- if (IGNORED_FUNCTIONS.indexOf(func.ident) >= 0) return null;
+ func.JS = '\n';
- func.JS = '\n';
+ var paramIdents = func.params.map(function(param) {
+ return toNiceIdent(param.ident);
+ });
- var paramIdents = func.params.map(function(param) {
- return toNiceIdent(param.ident);
+ if (CLOSURE_ANNOTATIONS) {
+ func.JS += '/**\n';
+ paramIdents.forEach(function(param) {
+ func.JS += ' * @param {number} ' + param + '\n';
});
+ func.JS += ' * @return {number}\n'
+ func.JS += ' */\n';
+ }
- if (CLOSURE_ANNOTATIONS) {
- func.JS += '/**\n';
- paramIdents.forEach(function(param) {
- func.JS += ' * @param {number} ' + param + '\n';
- });
- func.JS += ' * @return {number}\n'
- func.JS += ' */\n';
- }
-
- if (PRINT_SPLIT_FILE_MARKER) {
- func.JS += '\n//FUNCTION_BEGIN_MARKER\n'
- var associatedSourceFile = "NO_SOURCE";
- }
-
- if (DLOPEN_SUPPORT) Functions.getIndex(func.ident);
+ if (PRINT_SPLIT_FILE_MARKER) {
+ func.JS += '\n//FUNCTION_BEGIN_MARKER\n'
+ var associatedSourceFile = "NO_SOURCE";
+ }
+
+ if (DLOPEN_SUPPORT) Functions.getIndex(func.ident);
- func.JS += 'function ' + func.ident + '(' + paramIdents.join(', ') + ') {\n';
+ func.JS += 'function ' + func.ident + '(' + paramIdents.join(', ') + ') {\n';
- if (PGO) {
- func.JS += INDENTATION + 'PGOMonitor.called["' + func.ident + '"] = 1;\n';
- }
+ if (PGO) {
+ func.JS += INDENTATION + 'PGOMonitor.called["' + func.ident + '"] = 1;\n';
+ }
- if (ASM_JS) {
- // spell out argument types
- func.params.forEach(function(param) {
- func.JS += INDENTATION + param.ident + ' = ' + asmCoercion(param.ident, param.type) + ';\n';
- });
+ if (ASM_JS) {
+ // spell out argument types
+ func.params.forEach(function(param) {
+ func.JS += INDENTATION + param.ident + ' = ' + asmCoercion(param.ident, param.type) + ';\n';
+ });
- // spell out local variables
- var vars = values(func.variables).filter(function(v) { return v.origin != 'funcparam' });
- if (vars.length > 0) {
- var chunkSize = 8;
- var chunks = [];
- var i = 0;
- while (i < vars.length) {
- chunks.push(vars.slice(i, i+chunkSize));
- i += chunkSize;
- }
- for (i = 0; i < chunks.length; i++) {
- func.JS += INDENTATION + 'var ' + chunks[i].map(function(v) {
- var type = getImplementationType(v);
- if (!isIllegalType(type) || v.ident.indexOf('$', 1) > 0) { // not illegal, or a broken up illegal
- return v.ident + ' = ' + asmInitializer(type); //, func.variables[v.ident].impl);
- } else {
- return range(Math.ceil(getBits(type)/32)).map(function(i) {
- return v.ident + '$' + i + '= 0';
- }).join(',');
- }
- }).join(', ') + ';\n';
- }
+ // spell out local variables
+ var vars = values(func.variables).filter(function(v) { return v.origin != 'funcparam' });
+ if (vars.length > 0) {
+ var chunkSize = 8;
+ var chunks = [];
+ var i = 0;
+ while (i < vars.length) {
+ chunks.push(vars.slice(i, i+chunkSize));
+ i += chunkSize;
+ }
+ for (i = 0; i < chunks.length; i++) {
+ func.JS += INDENTATION + 'var ' + chunks[i].map(function(v) {
+ var type = getImplementationType(v);
+ if (!isIllegalType(type) || v.ident.indexOf('$', 1) > 0) { // not illegal, or a broken up illegal
+ return v.ident + ' = ' + asmInitializer(type); //, func.variables[v.ident].impl);
+ } else {
+ return range(Math.ceil(getBits(type)/32)).map(function(i) {
+ return v.ident + '$' + i + '= 0';
+ }).join(',');
+ }
+ }).join(', ') + ';\n';
}
}
+ }
- if (true) { // TODO: optimize away when not needed
- if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
- func.JS += INDENTATION + 'var label = 0;\n';
- }
+ if (true) { // TODO: optimize away when not needed
+ if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
+ func.JS += INDENTATION + 'var label = 0;\n';
+ }
- if (ASM_JS) {
- var hasByVal = false;
- func.params.forEach(function(param) {
- hasByVal = hasByVal || param.byVal;
- });
- if (hasByVal) {
- func.JS += INDENTATION + 'var tempParam = 0;\n';
- }
+ if (ASM_JS) {
+ var hasByVal = false;
+ func.params.forEach(function(param) {
+ hasByVal = hasByVal || param.byVal;
+ });
+ if (hasByVal) {
+ func.JS += INDENTATION + 'var tempParam = 0;\n';
}
+ }
+
+ if (func.hasVarArgsCall) {
+ func.JS += INDENTATION + 'var tempVarArgs = 0;\n';
+ }
+
+ // Prepare the stack, if we need one. If we have other stack allocations, force the stack to be set up.
+ func.JS += INDENTATION + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n';
- if (func.hasVarArgsCall) {
- func.JS += INDENTATION + 'var tempVarArgs = 0;\n';
+ // Make copies of by-value params
+ // XXX It is not clear we actually need this. While without this we fail, it does look like
+ // Clang normally does the copy itself, in the calling function. We only need this code
+ // when Clang optimizes the code and passes the original, not the copy, to the other
+ // function. But Clang still copies, the copy is just unused! Need to figure out if that
+ // is caused by our running just some optimizations (the safe ones), or if its a bug
+ // in Clang, or a bug in our understanding of the IR.
+ func.params.forEach(function(param) {
+ if (param.byVal) {
+ var type = removePointing(param.type);
+ var typeInfo = Types.types[type];
+ func.JS += INDENTATION + (ASM_JS ? '' : 'var ') + 'tempParam = ' + param.ident + '; ' + param.ident + ' = ' + RuntimeGenerator.stackAlloc(typeInfo.flatSize) + ';' +
+ makeCopyValues(param.ident, 'tempParam', typeInfo.flatSize, 'null', null, param.byVal) + ';\n';
}
+ });
- // Prepare the stack, if we need one. If we have other stack allocations, force the stack to be set up.
- func.JS += INDENTATION + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n';
+ if (LABEL_DEBUG && functionNameFilterTest(func.ident)) func.JS += " Module.print(INDENT + ' Entering: " + func.ident + ": ' + Array.prototype.slice.call(arguments)); INDENT += ' ';\n";
- // Make copies of by-value params
- // XXX It is not clear we actually need this. While without this we fail, it does look like
- // Clang normally does the copy itself, in the calling function. We only need this code
- // when Clang optimizes the code and passes the original, not the copy, to the other
- // function. But Clang still copies, the copy is just unused! Need to figure out if that
- // is caused by our running just some optimizations (the safe ones), or if its a bug
- // in Clang, or a bug in our understanding of the IR.
- func.params.forEach(function(param) {
- if (param.byVal) {
- var type = removePointing(param.type);
- var typeInfo = Types.types[type];
- func.JS += INDENTATION + (ASM_JS ? '' : 'var ') + 'tempParam = ' + param.ident + '; ' + param.ident + ' = ' + RuntimeGenerator.stackAlloc(typeInfo.flatSize) + ';' +
- makeCopyValues(param.ident, 'tempParam', typeInfo.flatSize, 'null', null, param.byVal) + ';\n';
+ // Walk function blocks and generate JS
+ function walkBlock(block, indent) {
+ if (!block) return '';
+ dprint('relooping', 'walking block: ' + block.type + ',' + block.entries + ' : ' + block.labels.length);
+ function getLabelLines(label, indent, relooping) {
+ if (!label) return '';
+ var ret = '';
+ if ((LABEL_DEBUG >= 2) && functionNameFilterTest(func.ident)) {
+ ret += indent + "Module.print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
}
- });
-
- if (LABEL_DEBUG && functionNameFilterTest(func.ident)) func.JS += " Module.print(INDENT + ' Entering: " + func.ident + ": ' + Array.prototype.slice.call(arguments)); INDENT += ' ';\n";
-
- // Walk function blocks and generate JS
- function walkBlock(block, indent) {
- if (!block) return '';
- dprint('relooping', 'walking block: ' + block.type + ',' + block.entries + ' : ' + block.labels.length);
- function getLabelLines(label, indent, relooping) {
- if (!label) return '';
- var ret = '';
- if ((LABEL_DEBUG >= 2) && functionNameFilterTest(func.ident)) {
- ret += indent + "Module.print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
- }
- if (EXECUTION_TIMEOUT > 0) {
- ret += indent + 'if (Date.now() - START_TIME >= ' + (EXECUTION_TIMEOUT*1000) + ') throw "Timed out!" + (new Error().stack);\n';
- }
-
- if (PRINT_SPLIT_FILE_MARKER && Debugging.on && Debugging.getAssociatedSourceFile(line.lineNum)) {
- // Overwrite the associated source file for every line. The last line should contain the source file associated to
- // the return value/address of outer most block (the marked function).
- associatedSourceFile = Debugging.getAssociatedSourceFile(line.lineNum);
- }
-
- // for special labels we care about (for phi), mark that we visited them
- var i = 0;
- return ret + label.lines.map(function(line) {
- var JS = line.JS;
- if (relooping && i == label.lines.length-1) {
- if (line.intertype == 'branch' || line.intertype == 'switch') {
- JS = ''; // just branching operations - done in the relooper, so nothing need be done here
- } else if (line.intertype == 'invoke') {
- JS = line.reloopingJS; // invokes have code that is not rendered in the relooper (the call inside a try-catch)
- }
- }
- i++;
- // invoke instructions span two lines, and the debug info is located
- // on the second line, hence the +1
- return JS + (Debugging.on ? Debugging.getComment(line.lineNum + (line.intertype === 'invoke' ? 1 : 0)) : '');
- })
- .join('\n')
- .split('\n') // some lines include line breaks
- .map(function(line) { return indent + line })
- .join('\n');
+ if (EXECUTION_TIMEOUT > 0) {
+ ret += indent + 'if (Date.now() - START_TIME >= ' + (EXECUTION_TIMEOUT*1000) + ') throw "Timed out!" + (new Error().stack);\n';
}
- var ret = '';
- if (!RELOOP || func.forceEmulated) { // TODO: also if just 1 label?
- if (block.labels.length > 1) {
- if (block.entries.length == 1) {
- ret += indent + 'label = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
- } // otherwise, should have been set before!
- if (func.setjmpTable) {
- if (!ASM_JS) {
- var setjmpTable = {};
- ret += indent + 'var mySetjmpIds = {};\n';
- ret += indent + 'var setjmpTable = {';
- func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
- ret += '"' + getLabelId(triple.oldLabel) + '": ' + 'function(value) { label = ' + getLabelId(triple.newLabel) + '; ' + triple.assignTo + ' = value },';
- });
- ret += 'dummy: 0';
- ret += '};\n';
- } else {
- ret += 'var setjmpLabel = 0;\n';
- ret += 'var setjmpTable = ' + RuntimeGenerator.stackAlloc(4 * (MAX_SETJMPS + 1) * 2) + ';\n';
- ret += makeSetValue('setjmpTable', '0', '0', 'i32') + ';'; // initialize first entry to 0
- }
- }
- ret += indent + 'while(1) ';
- if (func.setjmpTable && !ASM_JS) {
- ret += 'try { ';
- }
- ret += 'switch(' + asmCoercion('label', 'i32') + ') {\n';
- ret += block.labels.map(function(label) {
- return indent + INDENTATION + 'case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
- + getLabelLines(label, indent + INDENTATION + INDENTATION);
- }).join('\n') + '\n';
- if (func.setjmpTable && ASM_JS) {
- // emit a label in which we write to the proper local variable, before jumping to the actual label
- ret += INDENTATION + 'case ' + SETJMP_LABEL + ': ';
- ret += func.setjmpTable.map(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
- return 'if ((setjmpLabel|0) == ' + getLabelId(triple.oldLabel) + ') { ' + triple.assignTo + ' = threwValue; label = ' + triple.newLabel + ' }\n';
- }).join(' else ');
- if (ASSERTIONS) ret += 'else abort(-3);\n';
- ret += '__THREW__ = threwValue = 0;\n';
- ret += 'break;\n';
- }
- if (ASSERTIONS) ret += indent + INDENTATION + 'default: assert(0' + (ASM_JS ? '' : ', "bad label: " + label') + ');\n';
- ret += indent + '}\n';
- if (func.setjmpTable && !ASM_JS) {
- ret += ' } catch(e) { if (!e.longjmp || !(e.id in mySetjmpIds)) throw(e); setjmpTable[setjmpLabels[e.id]](e.value) }';
+
+ if (PRINT_SPLIT_FILE_MARKER && Debugging.on && Debugging.getAssociatedSourceFile(label.lines[label.lines.length-1].lineNum)) {
+ // Overwrite the associated source file for every line. The last line should contain the source file associated to
+ // the return value/address of outer most block (the marked function).
+ associatedSourceFile = Debugging.getAssociatedSourceFile(label.lines[label.lines.length-1].lineNum);
+ }
+
+ // for special labels we care about (for phi), mark that we visited them
+ var i = 0;
+ return ret + label.lines.map(function(line) {
+ var JS = line.JS;
+ if (relooping && i == label.lines.length-1) {
+ if (line.intertype == 'branch' || line.intertype == 'switch') {
+ JS = ''; // just branching operations - done in the relooper, so nothing need be done here
+ } else if (line.intertype == 'invoke') {
+ JS = line.reloopingJS; // invokes have code that is not rendered in the relooper (the call inside a try-catch)
}
- } else {
- ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0], indent);
}
- ret += '\n';
- } else {
- // Reloop multiple blocks using the compiled relooper
-
- //Relooper.setDebug(1);
- Relooper.init();
-
- if (ASM_JS) Relooper.setAsmJSMode(1);
-
- var blockMap = {};
- // add blocks
- for (var i = 0; i < block.labels.length; i++) {
- var label = block.labels[i];
- var content = getLabelLines(label, '', true);
- //printErr(func.ident + ' : ' + label.ident + ' : ' + content + '\n');
- var last = label.lines[label.lines.length-1];
- if (!last.signedIdent) {
- blockMap[label.ident] = Relooper.addBlock(content);
+ i++;
+ // invoke instructions span two lines, and the debug info is located
+ // on the second line, hence the +1
+ return JS + (Debugging.on ? Debugging.getComment(line.lineNum + (line.intertype === 'invoke' ? 1 : 0)) : '');
+ })
+ .join('\n')
+ .split('\n') // some lines include line breaks
+ .map(function(line) { return indent + line })
+ .join('\n');
+ }
+ var ret = '';
+ if (!RELOOP || func.forceEmulated) { // TODO: also if just 1 label?
+ if (block.labels.length > 1) {
+ if (block.entries.length == 1) {
+ ret += indent + 'label = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
+ } // otherwise, should have been set before!
+ if (func.setjmpTable) {
+ if (!ASM_JS) {
+ var setjmpTable = {};
+ ret += indent + 'var mySetjmpIds = {};\n';
+ ret += indent + 'var setjmpTable = {';
+ func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
+ ret += '"' + getLabelId(triple.oldLabel) + '": ' + 'function(value) { label = ' + getLabelId(triple.newLabel) + '; ' + triple.assignTo + ' = value },';
+ });
+ ret += 'dummy: 0';
+ ret += '};\n';
} else {
- assert(last.intertype == 'switch');
- blockMap[label.ident] = Relooper.addBlock(content, last.signedIdent);
+ ret += 'var setjmpLabel = 0;\n';
+ ret += 'var setjmpTable = ' + RuntimeGenerator.stackAlloc(4 * (MAX_SETJMPS + 1) * 2) + ';\n';
+ ret += makeSetValue('setjmpTable', '0', '0', 'i32') + ';'; // initialize first entry to 0
}
}
- // add branchings
- function relevant(x) { return x && x.length > 2 ? x : 0 } // ignores ';' which valueJS and label*JS can be if empty
- for (var i = 0; i < block.labels.length; i++) {
- var label = block.labels[i];
- var ident = label.ident;
- var last = label.lines[label.lines.length-1];
- //printErr('zz last ' + dump(last));
- if (last.intertype == 'branch') {
- if (last.label) { // 1 target
- Relooper.addBranch(blockMap[ident], blockMap[last.label], 0, relevant(last.labelJS));
- } else { // 2 targets
- Relooper.addBranch(blockMap[ident], blockMap[last.labelTrue], last.valueJS, relevant(last.labelTrueJS));
- Relooper.addBranch(blockMap[ident], blockMap[last.labelFalse], 0, relevant(last.labelFalseJS));
- }
- } else if (last.intertype == 'switch') {
- last.groupedLabels.forEach(function(switchLabel) {
- Relooper.addBranch(blockMap[ident], blockMap[switchLabel.label], switchLabel.value, relevant(switchLabel.labelJS));
- });
- Relooper.addBranch(blockMap[ident], blockMap[last.defaultLabel], 0, relevant(last.defaultLabelJS));
- } else if (last.intertype == 'invoke') {
- Relooper.addBranch(blockMap[ident], blockMap[last.toLabel], '!__THREW__', relevant(last.toLabelJS));
- Relooper.addBranch(blockMap[ident], blockMap[last.unwindLabel], 0, relevant(last.unwindLabelJS));
- } else if (last.intertype in RELOOP_IGNORED_LASTS) {
- } else {
- throw 'unknown reloop last line: ' + last.intertype;
+ ret += indent + 'while(1) ';
+ if (func.setjmpTable && !ASM_JS) {
+ ret += 'try { ';
+ }
+ ret += 'switch(' + asmCoercion('label', 'i32') + ') {\n';
+ ret += block.labels.map(function(label) {
+ return indent + INDENTATION + 'case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
+ + getLabelLines(label, indent + INDENTATION + INDENTATION);
+ }).join('\n') + '\n';
+ if (func.setjmpTable && ASM_JS) {
+ // emit a label in which we write to the proper local variable, before jumping to the actual label
+ ret += INDENTATION + 'case ' + SETJMP_LABEL + ': ';
+ ret += func.setjmpTable.map(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
+ return 'if ((setjmpLabel|0) == ' + getLabelId(triple.oldLabel) + ') { ' + triple.assignTo + ' = threwValue; label = ' + triple.newLabel + ' }\n';
+ }).join(' else ');
+ if (ASSERTIONS) ret += 'else abort(-3);\n';
+ ret += '__THREW__ = threwValue = 0;\n';
+ ret += 'break;\n';
+ }
+ if (ASSERTIONS) ret += indent + INDENTATION + 'default: assert(0' + (ASM_JS ? '' : ', "bad label: " + label') + ');\n';
+ ret += indent + '}\n';
+ if (func.setjmpTable && !ASM_JS) {
+ ret += ' } catch(e) { if (!e.longjmp || !(e.id in mySetjmpIds)) throw(e); setjmpTable[setjmpLabels[e.id]](e.value) }';
+ }
+ } else {
+ ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0], indent);
+ }
+ ret += '\n';
+ } else {
+ // Reloop multiple blocks using the compiled relooper
+
+ //Relooper.setDebug(1);
+ Relooper.init();
+
+ if (ASM_JS) Relooper.setAsmJSMode(1);
+
+ var blockMap = {};
+ // add blocks
+ for (var i = 0; i < block.labels.length; i++) {
+ var label = block.labels[i];
+ var content = getLabelLines(label, '', true);
+ //printErr(func.ident + ' : ' + label.ident + ' : ' + content + '\n');
+ var last = label.lines[label.lines.length-1];
+ if (!last.signedIdent) {
+ blockMap[label.ident] = Relooper.addBlock(content);
+ } else {
+ assert(last.intertype == 'switch');
+ blockMap[label.ident] = Relooper.addBlock(content, last.signedIdent);
+ }
+ }
+ // add branchings
+ function relevant(x) { return x && x.length > 2 ? x : 0 } // ignores ';' which valueJS and label*JS can be if empty
+ for (var i = 0; i < block.labels.length; i++) {
+ var label = block.labels[i];
+ var ident = label.ident;
+ var last = label.lines[label.lines.length-1];
+ //printErr('zz last ' + dump(last));
+ if (last.intertype == 'branch') {
+ if (last.label) { // 1 target
+ Relooper.addBranch(blockMap[ident], blockMap[last.label], 0, relevant(last.labelJS));
+ } else { // 2 targets
+ Relooper.addBranch(blockMap[ident], blockMap[last.labelTrue], last.valueJS, relevant(last.labelTrueJS));
+ Relooper.addBranch(blockMap[ident], blockMap[last.labelFalse], 0, relevant(last.labelFalseJS));
}
+ } else if (last.intertype == 'switch') {
+ last.groupedLabels.forEach(function(switchLabel) {
+ Relooper.addBranch(blockMap[ident], blockMap[switchLabel.label], switchLabel.value, relevant(switchLabel.labelJS));
+ });
+ Relooper.addBranch(blockMap[ident], blockMap[last.defaultLabel], 0, relevant(last.defaultLabelJS));
+ } else if (last.intertype == 'invoke') {
+ Relooper.addBranch(blockMap[ident], blockMap[last.toLabel], '!__THREW__', relevant(last.toLabelJS));
+ Relooper.addBranch(blockMap[ident], blockMap[last.unwindLabel], 0, relevant(last.unwindLabelJS));
+ } else if (last.intertype in RELOOP_IGNORED_LASTS) {
+ } else {
+ throw 'unknown reloop last line: ' + last.intertype;
}
- ret += Relooper.render(blockMap[block.entries[0]]);
}
- return ret;
- }
- func.JS += walkBlock(func.block, INDENTATION);
- // Finalize function
- if (LABEL_DEBUG && functionNameFilterTest(func.ident)) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
- // Ensure a return in a function with a type that returns, even if it lacks a return (e.g., if it aborts())
- if (RELOOP && func.lines.length > 0 && func.returnType != 'void') {
- var returns = func.labels.filter(function(label) { return label.lines[label.lines.length-1].intertype == 'return' }).length;
- if (returns == 0) func.JS += INDENTATION + 'return ' + asmCoercion('0', func.returnType);
- }
- func.JS += '}\n';
-
- if (PRINT_SPLIT_FILE_MARKER) {
- func.JS += '\n//FUNCTION_END_MARKER_OF_SOURCE_FILE_' + associatedSourceFile + '\n';
+ ret += Relooper.render(blockMap[block.entries[0]]);
+ Relooper.cleanup();
}
+ return ret;
+ }
+ func.JS += walkBlock(func.block, INDENTATION);
+ // Finalize function
+ if (LABEL_DEBUG && functionNameFilterTest(func.ident)) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
+ // Ensure a return in a function with a type that returns, even if it lacks a return (e.g., if it aborts())
+ if (RELOOP && func.lines.length > 0 && func.returnType != 'void') {
+ var returns = func.labels.filter(function(label) { return label.lines[label.lines.length-1].intertype == 'return' }).length;
+ if (returns == 0) func.JS += INDENTATION + 'return ' + asmCoercion('0', func.returnType);
+ }
+ func.JS += '}\n';
+
+ if (PRINT_SPLIT_FILE_MARKER) {
+ func.JS += '\n//FUNCTION_END_MARKER_OF_SOURCE_FILE_' + associatedSourceFile + '\n';
+ }
- if (!ASM_JS && (EXPORT_ALL || (func.ident in EXPORTED_FUNCTIONS))) {
- func.JS += 'Module["' + func.ident + '"] = ' + func.ident + ';';
- }
+ if (!ASM_JS && (EXPORT_ALL || (func.ident in EXPORTED_FUNCTIONS))) {
+ func.JS += 'Module["' + func.ident + '"] = ' + func.ident + ';';
+ }
- if (!ASM_JS && INLINING_LIMIT && func.lines.length >= INLINING_LIMIT) {
- func.JS += func.ident + '["X"]=1;';
- }
+ if (!ASM_JS && INLINING_LIMIT && func.lines.length >= INLINING_LIMIT) {
+ func.JS += func.ident + '["X"]=1;';
+ }
- if (BUILD_AS_SHARED_LIB == 2) {
- // TODO: make the assert conditional on ASSERTIONS
- func.JS += 'if (globalScope) { assert(!globalScope["' + func.ident + '"]); globalScope["' + func.ident + '"] = ' + func.ident + ' }';
- }
+ if (BUILD_AS_SHARED_LIB == 2) {
+ // TODO: make the assert conditional on ASSERTIONS
+ func.JS += 'if (globalScope) { assert(!globalScope["' + func.ident + '"]); globalScope["' + func.ident + '"] = ' + func.ident + ' }';
+ }
- func.JS = func.JS.replace(/\n *;/g, '\n'); // remove unneeded lines
+ func.JS = func.JS.replace(/\n *;/g, '\n'); // remove unneeded lines
- if (MAIN_MODULE || SIDE_MODULE) {
- // Clone the function for each of its aliases. We do not know which name it will be used by in another module,
- // and we do not have a heavyweight metadata system to resolve aliases during linking
- var aliases = Functions.aliases[func.ident];
- if (aliases) {
- var body = func.JS.substr(func.JS.indexOf('('));
- aliases.forEach(function(alias) {
- func.JS += '\n' + 'function ' + alias + body;
- });
- }
+ if (MAIN_MODULE || SIDE_MODULE) {
+ // Clone the function for each of its aliases. We do not know which name it will be used by in another module,
+ // and we do not have a heavyweight metadata system to resolve aliases during linking
+ var aliases = Functions.aliases[func.ident];
+ if (aliases) {
+ var body = func.JS.substr(func.JS.indexOf('('));
+ aliases.forEach(function(alias) {
+ func.JS += '\n' + 'function ' + alias + body;
+ });
}
-
- return func;
}
- });
+ itemsDict.function.push(func);
+ }
function getVarData(funcData, ident) {
var local = funcData.variables[ident];
@@ -898,18 +863,6 @@ function JSify(data, functionsOnly, givenFunctions) {
return data.impl;
}
- substrate.addActor('FuncLineTriager', {
- processItem: function(item) {
- if (item.intertype == 'function') {
- this.forwardItem(item, 'FunctionReconstructor'); // XXX not really needed
- } else if (item.JS) {
- this.forwardItem(item, 'FunctionReconstructor'); // XXX not really needed
- } else {
- this.forwardItem(item, 'Intertype:' + item.intertype);
- }
- }
- });
-
// An interitem that has |assignTo| is an assign to that item. They call this function which
// generates the actual assignment.
function makeAssign(item) {
@@ -944,29 +897,16 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// Function lines
- function makeFuncLineActor(intertype, func) {
- return substrate.addActor('Intertype:' + intertype, {
- processItem: function(item) {
- item.JS = func(item);
- if (!item.JS) throw "No JS generated for " + dump((item.funcData=null,item));
- if (item.assignTo) {
- makeAssign(item);
- if (!item.JS) throw "No assign JS generated for " + dump(item);
- }
- this.forwardItem(item, 'FunctionReconstructor');
- }
- });
- }
- makeFuncLineActor('value', function(item) {
+ function valueHandler(item) {
return item.ident;
- });
- makeFuncLineActor('noop', function(item) {
+ }
+ function noopHandler(item) {
return ';';
- });
- makeFuncLineActor('var', function(item) { // assigns into phis become simple vars
+ }
+ function varHandler(item) { // assigns into phis become simple vars
return ASM_JS ? ';' : ('var ' + item.ident + ';');
- });
- makeFuncLineActor('store', function(item) {
+ }
+ function storeHandler(item) {
var value = finalizeLLVMParameter(item.value);
if (pointingLevels(item.pointerType) == 1) {
value = parseNumerical(value, item.valueType);
@@ -998,9 +938,9 @@ function JSify(data, functionsOnly, givenFunctions) {
throw 'unknown [store] impl: ' + impl;
}
return null;
- });
+ }
- makeFuncLineActor('deleted', function(item) { return ';' });
+ function deletedHandler(item) { return ';' }
function getOriginalLabelId(label) {
var funcData = Framework.currItem.funcData;
@@ -1113,7 +1053,7 @@ function JSify(data, functionsOnly, givenFunctions) {
*/
}
- makeFuncLineActor('branch', function(item) {
+ function branchHandler(item) {
var phiSets = calcPhiSets(item);
if (!item.value) {
return (item.labelJS = getPhiSetsForLabel(phiSets, item.label)) + makeBranch(item.label, item.currLabelId);
@@ -1134,8 +1074,8 @@ function JSify(data, functionsOnly, givenFunctions) {
return head + labelTrue + else_ + labelFalse + tail;
}
}
- });
- makeFuncLineActor('switch', function(item) {
+ }
+ function switchHandler(item) {
// use a switch if the range is not too big or sparse
var minn = Infinity, maxx = -Infinity;
item.switchLabels.forEach(function(switchLabel) {
@@ -1174,7 +1114,8 @@ function JSify(data, functionsOnly, givenFunctions) {
if (!useIfs) {
ret += 'switch(' + signedIdent + ') {\n';
}
- for (var targetLabel in targetLabels) {
+ // process target labels, sorting them so output is consistently ordered
+ keys(targetLabels).sort().forEach(function(targetLabel) {
if (!first && useIfs) {
ret += 'else ';
} else {
@@ -1202,7 +1143,7 @@ function JSify(data, functionsOnly, givenFunctions) {
labelJS: phiSet
});
}
- }
+ });
var phiSet = item.defaultLabelJS = getPhiSetsForLabel(phiSets, item.defaultLabel);
if (useIfs) {
if (item.switchLabels.length > 0) ret += 'else {\n';
@@ -1219,8 +1160,8 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += ' ' + toNiceIdent(item.value);
}
return ret;
- });
- makeFuncLineActor('return', function(item) {
+ }
+ function returnHandler(item) {
var ret = RuntimeGenerator.stackExit(item.funcData.initialStack, item.funcData.otherStackAllocations) + ';\n';
if (LABEL_DEBUG && functionNameFilterTest(item.funcData.ident)) {
ret += "Module.print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
@@ -1233,9 +1174,9 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += ' ' + asmCoercion(value, item.type);
}
return ret + ';';
- });
- makeFuncLineActor('resume', function(item) {
- if (DISABLE_EXCEPTION_CATCHING) return 'abort()';
+ }
+ function resumeHandler(item) {
+ if (DISABLE_EXCEPTION_CATCHING && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST)) return 'abort()';
if (item.ident == 0) {
// No exception to resume, so we can just bail.
// This is related to issue #917 and http://llvm.org/PR15518
@@ -1244,8 +1185,8 @@ function JSify(data, functionsOnly, givenFunctions) {
// If there is no current exception, set this one as it (during a resume, the current exception can be wiped out)
var ptr = makeStructuralAccess(item.ident, 0);
return '___resumeException(' + asmCoercion(ptr, 'i32') + ')';
- });
- makeFuncLineActor('invoke', function(item) {
+ }
+ function invokeHandler(item) {
// Wrapping in a function lets us easily return values if we are
// in an assignment
var disabled = DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST);
@@ -1291,14 +1232,14 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += 'if (!__THREW__) { ' + item.toLabelJS + makeBranch(item.toLabel, item.currLabelId)
+ ' } else { ' + item.unwindLabelJS + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
return ret;
- });
- makeFuncLineActor('atomic', function(item) {
+ }
+ function atomicHandler(item) {
var type = item.params[0].type;
var param1 = finalizeLLVMParameter(item.params[0]);
var param2 = finalizeLLVMParameter(item.params[1]);
switch (item.op) {
- case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type, null, null, null, null, ',') + ',tempValue)';
- case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, asmCoercion('tempValue+' + param2, type), type, null, null, null, null, ',') + ',tempValue)';
+ case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, asmCoercion('tempValue-' + param2, type), type, null, null, null, null, ',') + ',tempValue)';
case 'or': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue|' + param2, type, null, null, null, null, ',') + ',tempValue)';
case 'and': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue&' + param2, type, null, null, null, null, ',') + ',tempValue)';
case 'xor': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue^' + param2, type, null, null, null, null, ',') + ',tempValue)';
@@ -1309,9 +1250,9 @@ function JSify(data, functionsOnly, givenFunctions) {
}
default: throw 'unhandled atomic op: ' + item.op;
}
- });
- makeFuncLineActor('landingpad', function(item) {
- if (DISABLE_EXCEPTION_CATCHING && USE_TYPED_ARRAYS == 2) {
+ }
+ function landingpadHandler(item) {
+ if (DISABLE_EXCEPTION_CATCHING && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST) && USE_TYPED_ARRAYS == 2) {
ret = makeVarDef(item.assignTo) + '$0 = 0; ' + item.assignTo + '$1 = 0;';
item.assignTo = null;
if (VERBOSE) warnOnce('landingpad, but exceptions are disabled!');
@@ -1324,18 +1265,18 @@ function JSify(data, functionsOnly, givenFunctions) {
item.assignTo = null;
}
return ret;
- });
- makeFuncLineActor('load', function(item) {
+ }
+ function loadHandler(item) {
var value = finalizeLLVMParameter(item.pointer);
var impl = item.ident ? getVarImpl(item.funcData, item.ident) : VAR_EMULATED;
switch (impl) {
case VAR_NATIVIZED: {
if (isNumber(item.ident)) {
- item.assignTo = null;
// Direct read from a memory address; this may be an intentional segfault, if not, it is a bug in the source
if (ASM_JS) {
- return 'abort(' + item.ident + ')';
+ return asmCoercion('abort(' + item.ident + ')', item.type);
} else {
+ item.assignTo = null;
return 'throw "fault on read from ' + item.ident + '";';
}
}
@@ -1344,8 +1285,8 @@ function JSify(data, functionsOnly, givenFunctions) {
case VAR_EMULATED: return makeGetValue(value, 0, item.type, 0, item.unsigned, 0, item.align);
default: throw "unknown [load] impl: " + impl;
}
- });
- makeFuncLineActor('extractvalue', function(item) {
+ }
+ function extractvalueHandler(item) {
assert(item.indexes.length == 1); // TODO: use getelementptr parsing stuff, for depth. For now, we assume that LLVM aggregates are flat,
// and we emulate them using simple JS objects { f1: , f2: , } etc., for speed
var index = item.indexes[0][0].text;
@@ -1358,8 +1299,8 @@ function JSify(data, functionsOnly, givenFunctions) {
return 'var ' + assignTo + '$0 = ' + item.ident + '.f' + index + '[0];' +
'var ' + assignTo + '$1 = ' + item.ident + '.f' + index + '[1];';
}
- });
- makeFuncLineActor('insertvalue', function(item) {
+ }
+ function insertvalueHandler(item) {
assert(item.indexes.length == 1); // TODO: see extractvalue
var ret = '(', ident;
if (item.ident === '0') {
@@ -1367,24 +1308,24 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += item.ident + ' = [' + makeEmptyStruct(item.type) + '], ';
}
return ret + item.ident + '.f' + item.indexes[0][0].text + ' = ' + finalizeLLVMParameter(item.value) + ', ' + item.ident + ')';
- });
- makeFuncLineActor('indirectbr', function(item) {
+ }
+ function indirectbrHandler(item) {
var phiSets = calcPhiSets(item);
var js = 'var ibr = ' + finalizeLLVMParameter(item.value) + ';\n';
for (var targetLabel in phiSets) {
js += 'if (' + makeComparison('ibr', '==', targetLabel, 'i32') + ') { ' + getPhiSetsForLabel(phiSets, targetLabel) + ' }\n';
}
return js + makeBranch('ibr', item.currLabelId, true);
- });
- makeFuncLineActor('alloca', function(item) {
+ }
+ function allocaHandler(item) {
if (typeof item.allocatedIndex === 'number') {
if (item.allocatedSize === 0) return ''; // This will not actually be shown - it's nativized
return asmCoercion(getFastValue('sp', '+', item.allocatedIndex.toString()), 'i32');
} else {
return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.allocatedNum));
}
- });
- makeFuncLineActor('va_arg', function(item) {
+ }
+ function va_argHandler(item) {
assert(TARGET_LE32);
var ident = item.value.ident;
var move = Runtime.STACK_ALIGN;
@@ -1393,11 +1334,11 @@ function JSify(data, functionsOnly, givenFunctions) {
return '(tempInt=' + makeGetValue(ident, Runtime.QUANTUM_SIZE, '*') + ',' +
makeSetValue(ident, Runtime.QUANTUM_SIZE, 'tempInt + ' + move, '*') + ',' +
makeGetValue(makeGetValue(ident, 0, '*'), 'tempInt', item.type) + ')';
- });
+ }
- makeFuncLineActor('mathop', processMathop);
+ var mathopHandler = processMathop;
- makeFuncLineActor('bitcast', function(item) {
+ function bitcastHandler(item) {
var temp = {
op: 'bitcast', variant: null, type: item.type,
assignTo: item.assignTo,
@@ -1406,7 +1347,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var ret = processMathop(temp);
if (!temp.assignTo) item.assignTo = null; // If the assign was stolen, propagate that
return ret;
- });
+ }
function makeFunctionCall(ident, params, funcData, type, forceByPointer, hasReturn, invoke) {
// We cannot compile assembly. See comment in intertyper.js:'Call'
@@ -1614,33 +1555,26 @@ function JSify(data, functionsOnly, givenFunctions) {
return js;
}
- makeFuncLineActor('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
- makeFuncLineActor('call', function(item) {
+ function getelementptrHandler(item) { return finalizeLLVMFunctionCall(item) }
+ function callHandler(item) {
if (item.standalone && LibraryManager.isStubFunction(item.ident)) return ';';
var ret = makeFunctionCall(item.ident, item.params, item.funcData, item.type, false, !!item.assignTo || !item.standalone) + (item.standalone ? ';' : '');
return makeVarArgsCleanup(ret);
- });
+ }
- makeFuncLineActor('unreachable', function(item) {
+ function unreachableHandler(item) {
var ret = '';
if (ASM_JS && item.funcData.returnType != 'void') ret = 'return ' + asmCoercion('0', item.funcData.returnType) + ';';
if (ASSERTIONS) {
ret = (ASM_JS ? 'abort()' : 'throw "Reached an unreachable!"') + ';' + ret;
}
return ret || ';';
- });
+ }
// Final combiner
- function finalCombiner(items) {
+ function finalCombiner() {
dprint('unparsedFunctions', 'Starting finalCombiner');
- var itemsDict = { type: [], GlobalVariableStub: [], functionStub: [], function: [], GlobalVariable: [], GlobalVariablePostSet: [] };
- items.forEach(function(item) {
- item.lines = null;
- var small = { intertype: item.intertype, JS: item.JS, ident: item.ident, dependencies: item.dependencies }; // Release memory
- itemsDict[small.intertype].push(small);
- });
- items = null;
var splitPostSets = splitter(itemsDict.GlobalVariablePostSet, function(x) { return x.ident && x.dependencies });
itemsDict.GlobalVariablePostSet = splitPostSets.leftIn;
@@ -1897,7 +1831,7 @@ function JSify(data, functionsOnly, givenFunctions) {
Functions.implementedFunctions[func.ident] = Functions.getSignature(func.returnType, func.params.map(function(param) { return param.type }));
});
}
- substrate.addItems(data.functionStubs, 'FunctionStub');
+ data.functionStubs.forEach(functionStubHandler);
assert(data.functions.length == 0);
} else {
if (phase == 'pre') {
@@ -1906,21 +1840,21 @@ function JSify(data, functionsOnly, givenFunctions) {
data.globalVariables._llvm_global_ctors.ctors.unshift('runPostSets'); // run postsets right before global initializers
hasCtors = true;
} else {
- substrate.addItems([{
+ globalVariableHandler({
intertype: 'GlobalVariableStub',
ident: '_llvm_global_ctors',
type: '[1 x { i32, void ()* }]',
ctors: ["runPostSets"],
- }], 'GlobalVariable');
+ });
}
}
- substrate.addItems(sortGlobals(data.globalVariables), 'GlobalVariable');
- substrate.addItems(data.aliass, 'Alias');
- substrate.addItems(data.functions, 'FunctionSplitter');
+ sortGlobals(data.globalVariables).forEach(globalVariableHandler);
+ data.aliass.forEach(aliasHandler);
+ data.functions.forEach(functionSplitter);
}
- finalCombiner(substrate.solve());
+ finalCombiner();
dprint('framework', 'Big picture: Finishing JSifier, main pass=' + mainPass);
}
diff --git a/src/library.js b/src/library.js
index 7a144951..abee70c4 100644
--- a/src/library.js
+++ b/src/library.js
@@ -628,24 +628,13 @@ LibraryManager.library = {
// http://pubs.opengroup.org/onlinepubs/000095399/functions/chdir.html
// NOTE: The path argument may be a string, to simplify fchdir().
if (typeof path !== 'string') path = Pointer_stringify(path);
- var lookup;
try {
- lookup = FS.lookupPath(path, { follow: true });
+ FS.chdir(path);
+ return 0;
} catch (e) {
FS.handleFSError(e);
return -1;
}
- if (!FS.isDir(lookup.node.mode)) {
- ___setErrNo(ERRNO_CODES.ENOTDIR);
- return -1;
- }
- var err = FS.nodePermissions(lookup.node, 'x');
- if (err) {
- ___setErrNo(err);
- return -1;
- }
- FS.currentPath = lookup.path;
- return 0;
},
chown__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
chown: function(path, owner, group, dontResolveLastLink) {
@@ -849,12 +838,14 @@ LibraryManager.library = {
if (size == 0) {
___setErrNo(ERRNO_CODES.EINVAL);
return 0;
- } else if (size < FS.currentPath.length + 1) {
+ }
+ var cwd = FS.cwd();
+ if (size < cwd.length + 1) {
___setErrNo(ERRNO_CODES.ERANGE);
return 0;
} else {
- for (var i = 0; i < FS.currentPath.length; i++) {
- {{{ makeSetValue('buf', 'i', 'FS.currentPath.charCodeAt(i)', 'i8') }}}
+ for (var i = 0; i < cwd.length; i++) {
+ {{{ makeSetValue('buf', 'i', 'cwd.charCodeAt(i)', 'i8') }}}
}
{{{ makeSetValue('buf', 'i', '0', 'i8') }}}
return buf;
@@ -1600,12 +1591,6 @@ LibraryManager.library = {
__scanString.whiteSpace[{{{ charCode('\v') }}}] = 1;
__scanString.whiteSpace[{{{ charCode('\f') }}}] = 1;
__scanString.whiteSpace[{{{ charCode('\r') }}}] = 1;
- __scanString.whiteSpace[' '] = 1;
- __scanString.whiteSpace['\t'] = 1;
- __scanString.whiteSpace['\n'] = 1;
- __scanString.whiteSpace['\v'] = 1;
- __scanString.whiteSpace['\f'] = 1;
- __scanString.whiteSpace['\r'] = 1;
}
// Supports %x, %4x, %d.%d, %lld, %s, %f, %lf.
// TODO: Support all format specifiers.
@@ -1645,7 +1630,7 @@ LibraryManager.library = {
if (nextC > 0) {
var maxx = 1;
if (nextC > formatIndex+1) {
- var sub = format.substring(formatIndex+1, nextC)
+ var sub = format.substring(formatIndex+1, nextC);
maxx = parseInt(sub);
if (maxx != sub) maxx = 0;
}
@@ -1663,6 +1648,53 @@ LibraryManager.library = {
}
}
+ // handle %[...]
+ if (format[formatIndex] === '%' && format.indexOf('[', formatIndex+1) > 0) {
+ var match = /\%([0-9]*)\[(\^)?(\]?[^\]]*)\]/.exec(format.substring(formatIndex));
+ if (match) {
+ var maxNumCharacters = parseInt(match[1]) || Infinity;
+ var negateScanList = (match[2] === '^');
+ var scanList = match[3];
+
+ // expand "middle" dashs into character sets
+ var middleDashMatch;
+ while ((middleDashMatch = /([^\-])\-([^\-])/.exec(scanList))) {
+ var rangeStartCharCode = middleDashMatch[1].charCodeAt(0);
+ var rangeEndCharCode = middleDashMatch[2].charCodeAt(0);
+ for (var expanded = ''; rangeStartCharCode <= rangeEndCharCode; expanded += String.fromCharCode(rangeStartCharCode++));
+ scanList = scanList.replace(middleDashMatch[1] + '-' + middleDashMatch[2], expanded);
+ }
+
+ var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
+ argIndex += Runtime.getAlignSize('void*', null, true);
+ fields++;
+
+ for (var i = 0; i < maxNumCharacters; i++) {
+ next = get();
+ if (negateScanList) {
+ if (scanList.indexOf(String.fromCharCode(next)) < 0) {
+ {{{ makeSetValue('argPtr++', 0, 'next', 'i8') }}};
+ } else {
+ unget();
+ break;
+ }
+ } else {
+ if (scanList.indexOf(String.fromCharCode(next)) >= 0) {
+ {{{ makeSetValue('argPtr++', 0, 'next', 'i8') }}};
+ } else {
+ unget();
+ break;
+ }
+ }
+ }
+
+ // write out null-terminating character
+ {{{ makeSetValue('argPtr++', 0, '0', 'i8') }}};
+ formatIndex += match[0].length;
+
+ continue;
+ }
+ }
// remove whitespace
while (1) {
next = get();
@@ -1724,6 +1756,17 @@ LibraryManager.library = {
} else {
next = get();
var first = true;
+
+ // Strip the optional 0x prefix for %x.
+ if ((type == 'x' || type == 'X') && (next == {{{ charCode('0') }}})) {
+ var peek = get();
+ if (peek == {{{ charCode('x') }}} || peek == {{{ charCode('X') }}}) {
+ next = get();
+ } else {
+ unget();
+ }
+ }
+
while ((curr < max_ || isNaN(max_)) && next > 0) {
if (!(next in __scanString.whiteSpace) && // stop on whitespace
(type == 's' ||
@@ -1785,7 +1828,7 @@ LibraryManager.library = {
break;
}
fields++;
- } else if (format[formatIndex] in __scanString.whiteSpace) {
+ } else if (format[formatIndex].charCodeAt(0) in __scanString.whiteSpace) {
next = get();
while (next in __scanString.whiteSpace) {
if (next <= 0) break mainLoop; // End of input.
@@ -1856,6 +1899,7 @@ LibraryManager.library = {
var flagLeftAlign = false;
var flagAlternative = false;
var flagZeroPad = false;
+ var flagPadSign = false;
flagsLoop: while (1) {
switch (next) {
case {{{ charCode('+') }}}:
@@ -1874,6 +1918,9 @@ LibraryManager.library = {
flagZeroPad = true;
break;
}
+ case {{{ charCode(' ') }}}:
+ flagPadSign = true;
+ break;
default:
break flagsLoop;
}
@@ -2040,14 +2087,20 @@ LibraryManager.library = {
}
// Add sign if needed
- if (flagAlwaysSigned) {
- if (currArg < 0) {
- prefix = '-' + prefix;
- } else {
+ if (currArg >= 0) {
+ if (flagAlwaysSigned) {
prefix = '+' + prefix;
+ } else if (flagPadSign) {
+ prefix = ' ' + prefix;
}
}
+ // Move sign to prefix so we zero-pad after the sign
+ if (argText.charAt(0) == '-') {
+ prefix = '-' + prefix;
+ argText = argText.substr(1);
+ }
+
// Add padding.
while (prefix.length + argText.length < width) {
if (flagLeftAlign) {
@@ -2130,8 +2183,12 @@ LibraryManager.library = {
if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase();
// Add sign.
- if (flagAlwaysSigned && currArg >= 0) {
- argText = '+' + argText;
+ if (currArg >= 0) {
+ if (flagAlwaysSigned) {
+ argText = '+' + argText;
+ } else if (flagPadSign) {
+ argText = ' ' + argText;
+ }
}
}
@@ -2769,6 +2826,13 @@ LibraryManager.library = {
asprintf: function(s, format, varargs) {
return _sprintf(-s, format, varargs);
},
+ dprintf__deps: ['_formatString', 'write'],
+ dprintf: function(fd, format, varargs) {
+ var result = __formatString(format, varargs);
+ var stack = Runtime.stackSave();
+ var ret = _write(fd, allocate(result, 'i8', ALLOC_STACK), result.length);
+ Runtime.stackRestore(stack);
+ },
#if TARGET_X86
// va_arg is just like our varargs
@@ -2777,6 +2841,7 @@ LibraryManager.library = {
vprintf: 'printf',
vsprintf: 'sprintf',
vasprintf: 'asprintf',
+ vdprintf: 'dprintf',
vscanf: 'scanf',
vfscanf: 'fscanf',
vsscanf: 'sscanf',
@@ -2804,6 +2869,10 @@ LibraryManager.library = {
vasprintf: function(s, format, va_arg) {
return _asprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
},
+ vdprintf__deps: ['dprintf'],
+ vdprintf: function (fd, format, va_arg) {
+ return _dprintf(fd, format, {{{ makeGetValue('va_arg', 0, '*') }}});
+ },
vscanf__deps: ['scanf'],
vscanf: function(format, va_arg) {
return _scanf(format, {{{ makeGetValue('va_arg', 0, '*') }}});
@@ -3674,6 +3743,7 @@ LibraryManager.library = {
},
// We always assume ASCII locale.
strcoll: 'strcmp',
+ strcoll_l: 'strcmp',
strcasecmp__asm: true,
strcasecmp__sig: 'iii',
@@ -3940,6 +4010,7 @@ LibraryManager.library = {
}
},
_toupper: 'toupper',
+ toupper_l: 'toupper',
tolower__asm: true,
tolower__sig: 'ii',
@@ -3950,54 +4021,65 @@ LibraryManager.library = {
return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0;
},
_tolower: 'tolower',
+ tolower_l: 'tolower',
// The following functions are defined as macros in glibc.
islower: function(chr) {
return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}};
},
+ islower_l: 'islower',
isupper: function(chr) {
return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}};
},
+ isupper_l: 'isupper',
isalpha: function(chr) {
return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
(chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
},
+ isalpha_l: 'isalpha',
isdigit: function(chr) {
return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}};
},
- isdigit_l: 'isdigit', // no locale support yet
+ isdigit_l: 'isdigit',
isxdigit: function(chr) {
return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
(chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) ||
(chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}});
},
- isxdigit_l: 'isxdigit', // no locale support yet
+ isxdigit_l: 'isxdigit',
isalnum: function(chr) {
return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
(chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
(chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
},
+ isalnum_l: 'isalnum',
ispunct: function(chr) {
return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) ||
(chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) ||
(chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) ||
(chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}});
},
+ ispunct_l: 'ispunct',
isspace: function(chr) {
return (chr == 32) || (chr >= 9 && chr <= 13);
},
+ isspace_l: 'isspace',
isblank: function(chr) {
return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}};
},
+ isblank_l: 'isblank',
iscntrl: function(chr) {
return (0 <= chr && chr <= 0x1F) || chr === 0x7F;
},
+ iscntrl_l: 'iscntrl',
isprint: function(chr) {
return 0x1F < chr && chr < 0x7F;
},
+ isprint_l: 'isprint',
isgraph: function(chr) {
return 0x20 < chr && chr < 0x7F;
},
+ isgraph_l: 'isgraph',
// Lookup tables 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
@@ -4098,7 +4180,7 @@ LibraryManager.library = {
llvm_va_end: function() {},
llvm_va_copy: function(ppdest, ppsrc) {
- // copy the list start
+ // copy the list start
{{{ makeCopyValues('ppdest', 'ppsrc', Runtime.QUANTUM_SIZE, 'null', null, 1) }}};
// copy the list's current offset (will be advanced with each call to va_arg)
@@ -6270,11 +6352,15 @@ LibraryManager.library = {
// locale.h
// ==========================================================================
+ newlocale__deps: ['malloc'],
newlocale: function(mask, locale, base) {
- return 0;
+ return _malloc({{{ QUANTUM_SIZE}}});
},
- freelocale: function(locale) {},
+ freelocale__deps: ['free'],
+ freelocale: function(locale) {
+ _free(locale);
+ },
uselocale: function(locale) {
return 0;
@@ -8619,7 +8705,7 @@ function autoAddDeps(object, name) {
}
// Add aborting stubs for various libc stuff needed by libc++
-['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'swprintf', 'pthread_join', 'pthread_detach', 'strcoll_l', 'strxfrm_l', 'wcscoll_l', 'toupper_l', 'tolower_l', 'iswspace_l', 'iswprint_l', 'iswcntrl_l', 'iswupper_l', 'iswlower_l', 'iswalpha_l', 'iswdigit_l', 'iswpunct_l', 'iswxdigit_l', 'iswblank_l', 'wcsxfrm_l', 'towupper_l', 'towlower_l', 'catgets', 'catopen', 'catclose'].forEach(function(aborter) {
+['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose'].forEach(function(aborter) {
LibraryManager.library[aborter] = function() { throw 'TODO: ' + aborter };
});
diff --git a/src/library_fs.js b/src/library_fs.js
index 8bf0a83a..c4b29227 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -1,5 +1,5 @@
mergeInto(LibraryManager.library, {
- $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$VFS', '$PATH', '$TTY', '$MEMFS', 'stdin', 'stdout', 'stderr', 'fflush'],
+ $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$VFS', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', 'stdin', 'stdout', 'stderr', 'fflush'],
$FS__postset: 'FS.staticInit();' +
'__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' +
'__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' +
@@ -14,6 +14,7 @@ mergeInto(LibraryManager.library, {
'Module["FS_createDevice"] = FS.createDevice;',
$FS: {
root: null,
+ mounts: [],
devices: [null],
streams: [null],
nextInode: 1,
@@ -50,11 +51,8 @@ mergeInto(LibraryManager.library, {
//
// paths
//
- cwd: function() {
- return FS.currentPath;
- },
lookupPath: function(path, opts) {
- path = PATH.resolve(FS.currentPath, path);
+ path = PATH.resolve(FS.cwd(), path);
opts = opts || { recurse_count: 0 };
if (opts.recurse_count > 8) { // max recursive lookup of 8
@@ -309,7 +307,7 @@ mergeInto(LibraryManager.library, {
if (!FS.isDir(node.mode)) {
return ERRNO_CODES.ENOTDIR;
}
- if (FS.isRoot(node) || FS.getPath(node) === FS.currentPath) {
+ if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
return ERRNO_CODES.EBUSY;
}
} else {
@@ -422,17 +420,45 @@ mergeInto(LibraryManager.library, {
//
// core
//
+ syncfs: function(populate, callback) {
+ if (typeof(populate) === 'function') {
+ callback = populate;
+ populate = false;
+ }
+
+ var completed = 0;
+ var total = FS.mounts.length;
+ var done = function(err) {
+ if (err) {
+ return callback(err);
+ }
+ if (++completed >= total) {
+ callback(null);
+ }
+ };
+
+ // sync all mounts
+ for (var i = 0; i < FS.mounts.length; i++) {
+ var mount = FS.mounts[i];
+ if (!mount.type.syncfs) {
+ done(null);
+ continue;
+ }
+ mount.type.syncfs(mount, populate, done);
+ }
+ },
mount: function(type, opts, mountpoint) {
+ var lookup;
+ if (mountpoint) {
+ lookup = FS.lookupPath(mountpoint, { follow: false });
+ mountpoint = lookup.path; // use the absolute path
+ }
var mount = {
type: type,
opts: opts,
mountpoint: mountpoint,
root: null
};
- var lookup;
- if (mountpoint) {
- lookup = FS.lookupPath(mountpoint, { follow: false });
- }
// create a root node for the fs
var root = type.mount(mount);
root.mount = mount;
@@ -446,6 +472,8 @@ mergeInto(LibraryManager.library, {
FS.root = mount.root;
}
}
+ // add to our cached list of mounts
+ FS.mounts.push(mount);
return root;
},
lookup: function(parent, name) {
@@ -759,7 +787,6 @@ mergeInto(LibraryManager.library, {
follow: !(flags & {{{ cDefine('O_NOFOLLOW') }}})
});
node = lookup.node;
- path = lookup.path;
} catch (e) {
// ignore
}
@@ -791,10 +818,13 @@ mergeInto(LibraryManager.library, {
if ((flags & {{{ cDefine('O_TRUNC')}}})) {
FS.truncate(node, 0);
}
+ // we've already handled these, don't pass down to the underlying vfs
+ flags &= ~({{{ cDefine('O_EXCL') }}} | {{{ cDefine('O_TRUNC') }}});
+
// register the stream with the filesystem
var stream = FS.createStream({
- path: path,
node: node,
+ path: FS.getPath(node), // we want the absolute path to the node
flags: flags,
seekable: true,
position: 0,
@@ -959,8 +989,21 @@ mergeInto(LibraryManager.library, {
//
// module-level FS code
- // TODO move to pre/postamble
//
+ cwd: function() {
+ return FS.currentPath;
+ },
+ chdir: function(path) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ if (!FS.isDir(lookup.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
+ }
+ var err = FS.nodePermissions(lookup.node, 'x');
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ FS.currentPath = lookup.path;
+ },
createDefaultDirectories: function() {
FS.mkdir('/tmp');
},
@@ -1367,7 +1410,10 @@ mergeInto(LibraryManager.library, {
throw new FS.ErrnoError(ERRNO_CODES.EIO);
}
var contents = stream.node.contents;
+ if (position >= contents.length)
+ return 0;
var size = Math.min(contents.length - position, length);
+ assert(size >= 0);
if (contents.slice) { // normal array
for (var i = 0; i < size; i++) {
buffer[offset + i] = contents[position + i];
diff --git a/src/library_gl.js b/src/library_gl.js
index 16ea5531..83e68777 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -217,6 +217,23 @@ var LibraryGL = {
throw 'Invalid format (' + format + ')';
}
break;
+ case 0x1403 /* GL_UNSIGNED_SHORT */:
+ if (format == 0x1902 /* GL_DEPTH_COMPONENT */) {
+ sizePerPixel = 2;
+ } else {
+ throw 'Invalid format (' + format + ')';
+ }
+ break;
+ case 0x1405 /* GL_UNSIGNED_INT */:
+ if (format == 0x1902 /* GL_DEPTH_COMPONENT */) {
+ sizePerPixel = 4;
+ } else {
+ throw 'Invalid format (' + format + ')';
+ }
+ break;
+ case 0x84FA /* UNSIGNED_INT_24_8_WEBGL */:
+ sizePerPixel = 4;
+ break;
case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */:
case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */:
case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */:
@@ -244,6 +261,8 @@ var LibraryGL = {
pixels = {{{ makeHEAPView('U8', 'pixels', 'pixels+bytes') }}};
} else if (type == 0x1406 /* GL_FLOAT */) {
pixels = {{{ makeHEAPView('F32', 'pixels', 'pixels+bytes') }}};
+ } else if (type == 0x1405 /* GL_UNSIGNED_INT */ || type == 0x84FA /* UNSIGNED_INT_24_8_WEBGL */) {
+ pixels = {{{ makeHEAPView('U32', 'pixels', 'pixels+bytes') }}};
} else {
pixels = {{{ makeHEAPView('U16', 'pixels', 'pixels+bytes') }}};
}
@@ -291,6 +310,9 @@ var LibraryGL = {
Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER,
0,
HEAPU8.subarray(cb.ptr, cb.ptr + size));
+#if GL_ASSERTIONS
+ GL.validateVertexAttribPointer(cb.size, cb.type, cb.stride, 0);
+#endif
Module.ctx.vertexAttribPointer(i, cb.size, cb.type, cb.normalized, cb.stride, 0);
}
},
@@ -302,6 +324,56 @@ var LibraryGL = {
},
#endif
+#if GL_ASSERTIONS
+ validateGLObjectID: function(objectHandleArray, objectID, callerFunctionName, objectReadableType) {
+ if (objectID != 0) {
+ if (objectHandleArray[objectID] === null) {
+ console.error(callerFunctionName + ' called with an already deleted ' + objectReadableType + ' ID ' + objectID + '!');
+ } else if (!objectHandleArray[objectID]) {
+ console.error(callerFunctionName + ' called with an invalid ' + objectReadableType + ' ID ' + objectID + '!');
+ }
+ }
+ },
+ // Validates that user obeys GL spec #6.4: http://www.khronos.org/registry/webgl/specs/latest/1.0/#6.4
+ validateVertexAttribPointer: function(dimension, dataType, stride, offset) {
+ var sizeBytes = 1;
+ switch(dataType) {
+ case 0x1400 /* GL_BYTE */:
+ case 0x1401 /* GL_UNSIGNED_BYTE */:
+ sizeBytes = 1;
+ break;
+ case 0x1402 /* GL_SHORT */:
+ case 0x1403 /* GL_UNSIGNED_SHORT */:
+ sizeBytes = 2;
+ break;
+ case 0x1404 /* GL_INT */:
+ case 0x1405 /* GL_UNSIGNED_INT */:
+ case 0x1406 /* GL_FLOAT */:
+ sizeBytes = 4;
+ break;
+ case 0x140A /* GL_DOUBLE */:
+ sizeBytes = 8;
+ break;
+ default:
+ console.error('Invalid vertex attribute data type GLenum ' + dataType + ' passed to GL function!');
+ }
+ if (dimension == 0x80E1 /* GL_BGRA */) {
+ console.error('WebGL does not support size=GL_BGRA in a call to glVertexAttribPointer! Please use size=4 and type=GL_UNSIGNED_BYTE instead!');
+ } else if (dimension < 1 || dimension > 4) {
+ console.error('Invalid dimension='+dimension+' in call to glVertexAttribPointer, must be 1,2,3 or 4.');
+ }
+ if (stride < 0 || stride > 255) {
+ console.error('Invalid stride='+stride+' in call to glVertexAttribPointer. Note that maximum supported stride in WebGL is 255!');
+ }
+ if (offset % sizeBytes != 0) {
+ console.error('GL spec section 6.4 error: vertex attribute data offset of ' + offset + ' bytes should have been a multiple of the data type size that was used: GLenum ' + dataType + ' has size of ' + sizeBytes + ' bytes!');
+ }
+ if (stride % sizeBytes != 0) {
+ console.error('GL spec section 6.4 error: vertex attribute data stride of ' + stride + ' bytes should have been a multiple of the data type size that was used: GLenum ' + dataType + ' has size of ' + sizeBytes + ' bytes!');
+ }
+ },
+#endif
+
initExtensions: function() {
if (GL.initExtensions.done) return;
GL.initExtensions.done = true;
@@ -334,6 +406,10 @@ var LibraryGL = {
GL.elementIndexUintExt = Module.ctx.getExtension('OES_element_index_uint');
GL.standardDerivativesExt = Module.ctx.getExtension('OES_standard_derivatives');
+
+ GL.depthTextureExt = Module.ctx.getExtension("WEBGL_depth_texture") ||
+ Module.ctx.getExtension("MOZ_WEBGL_depth_texture") ||
+ Module.ctx.getExtension("WEBKIT_WEBGL_depth_texture");
}
},
@@ -588,6 +664,9 @@ var LibraryGL = {
glBindTexture__sig: 'vii',
glBindTexture: function(target, texture) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.textures, texture, 'glBindTexture', 'texture');
+#endif
Module.ctx.bindTexture(target, texture ? GL.textures[texture] : null);
},
@@ -710,6 +789,9 @@ var LibraryGL = {
glBindRenderbuffer__sig: 'vii',
glBindRenderbuffer: function(target, renderbuffer) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.renderbuffers, renderbuffer, 'glBindRenderbuffer', 'renderbuffer');
+#endif
Module.ctx.bindRenderbuffer(target, renderbuffer ? GL.renderbuffers[renderbuffer] : null);
},
@@ -727,6 +809,9 @@ var LibraryGL = {
glGetUniformfv__sig: 'viii',
glGetUniformfv: function(program, location, params) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetUniformfv', 'program');
+#endif
var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]);
if (typeof data == 'number') {
{{{ makeSetValue('params', '0', 'data', 'float') }}};
@@ -739,6 +824,9 @@ var LibraryGL = {
glGetUniformiv__sig: 'viii',
glGetUniformiv: function(program, location, params) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetUniformiv', 'program');
+#endif
var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]);
if (typeof data == 'number' || typeof data == 'boolean') {
{{{ makeSetValue('params', '0', 'data', 'i32') }}};
@@ -751,6 +839,9 @@ var LibraryGL = {
glGetUniformLocation__sig: 'iii',
glGetUniformLocation: function(program, name) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetUniformLocation', 'program');
+#endif
name = Pointer_stringify(name);
var ptable = GL.uniformTable[program];
if (!ptable) ptable = GL.uniformTable[program] = {};
@@ -810,6 +901,9 @@ var LibraryGL = {
glGetActiveUniform__sig: 'viiiiiii',
glGetActiveUniform: function(program, index, bufSize, length, size, type, name) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetActiveUniform', 'program');
+#endif
program = GL.programs[program];
var info = Module.ctx.getActiveUniform(program, index);
@@ -1018,6 +1112,9 @@ var LibraryGL = {
glBindBuffer__sig: 'vii',
glBindBuffer: function(target, buffer) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.buffers, buffer, 'glBindBuffer', 'buffer');
+#endif
var bufferObj = buffer ? GL.buffers[buffer] : null;
if (target == Module.ctx.ARRAY_BUFFER) {
@@ -1062,6 +1159,9 @@ var LibraryGL = {
glGetActiveAttrib__sig: 'viiiiiii',
glGetActiveAttrib: function(program, index, bufSize, length, size, type, name) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetActiveAttrib', 'program');
+#endif
program = GL.programs[program];
var info = Module.ctx.getActiveAttrib(program, index);
@@ -1094,6 +1194,9 @@ var LibraryGL = {
glGetAttachedShaders__sig: 'viiii',
glGetAttachedShaders: function(program, maxCount, count, shaders) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetAttachedShaders', 'program');
+#endif
var result = Module.ctx.getAttachedShaders(GL.programs[program]);
var len = result.length;
if (len > maxCount) {
@@ -1109,12 +1212,18 @@ var LibraryGL = {
glShaderSource__sig: 'viiii',
glShaderSource: function(shader, count, string, length) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.shaders, shader, 'glShaderSource', 'shader');
+#endif
var source = GL.getSource(shader, count, string, length);
Module.ctx.shaderSource(GL.shaders[shader], source);
},
glGetShaderSource__sig: 'viiii',
glGetShaderSource: function(shader, bufSize, length, source) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.shaders, shader, 'glGetShaderSource', 'shader');
+#endif
var result = Module.ctx.getShaderSource(GL.shaders[shader]);
result = result.slice(0, Math.max(0, bufSize - 1));
writeStringToMemory(result, source);
@@ -1125,11 +1234,17 @@ var LibraryGL = {
glCompileShader__sig: 'vi',
glCompileShader: function(shader) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.shaders, shader, 'glCompileShader', 'shader');
+#endif
Module.ctx.compileShader(GL.shaders[shader]);
},
glGetShaderInfoLog__sig: 'viiii',
glGetShaderInfoLog: function(shader, maxLength, length, infoLog) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.shaders, shader, 'glGetShaderInfoLog', 'shader');
+#endif
var log = Module.ctx.getShaderInfoLog(GL.shaders[shader]);
// Work around a bug in Chromium which causes getShaderInfoLog to return null
if (!log) {
@@ -1144,6 +1259,9 @@ var LibraryGL = {
glGetShaderiv__sig: 'viii',
glGetShaderiv : function(shader, pname, p) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.shaders, shader, 'glGetShaderiv', 'shader');
+#endif
if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
{{{ makeSetValue('p', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[shader]).length + 1', 'i32') }}};
} else {
@@ -1153,6 +1271,9 @@ var LibraryGL = {
glGetProgramiv__sig: 'viii',
glGetProgramiv : function(program, pname, p) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetProgramiv', 'program');
+#endif
if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
{{{ makeSetValue('p', '0', 'Module.ctx.getProgramInfoLog(GL.programs[program]).length + 1', 'i32') }}};
} else {
@@ -1187,12 +1308,20 @@ var LibraryGL = {
glAttachShader__sig: 'vii',
glAttachShader: function(program, shader) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glAttachShader', 'program');
+ GL.validateGLObjectID(GL.shaders, shader, 'glAttachShader', 'shader');
+#endif
Module.ctx.attachShader(GL.programs[program],
GL.shaders[shader]);
},
glDetachShader__sig: 'vii',
glDetachShader: function(program, shader) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glDetachShader', 'program');
+ GL.validateGLObjectID(GL.shaders, shader, 'glDetachShader', 'shader');
+#endif
Module.ctx.detachShader(GL.programs[program],
GL.shaders[shader]);
},
@@ -1206,12 +1335,18 @@ var LibraryGL = {
glLinkProgram__sig: 'vi',
glLinkProgram: function(program) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glLinkProgram', 'program');
+#endif
Module.ctx.linkProgram(GL.programs[program]);
GL.uniformTable[program] = {}; // uniforms no longer keep the same names after linking
},
glGetProgramInfoLog__sig: 'viiii',
glGetProgramInfoLog: function(program, maxLength, length, infoLog) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glGetProgramInfoLog', 'program');
+#endif
var log = Module.ctx.getProgramInfoLog(GL.programs[program]);
// Work around a bug in Chromium which causes getProgramInfoLog to return null
if (!log) {
@@ -1226,11 +1361,17 @@ var LibraryGL = {
glUseProgram__sig: 'vi',
glUseProgram: function(program) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glUseProgram', 'program');
+#endif
Module.ctx.useProgram(program ? GL.programs[program] : null);
},
glValidateProgram__sig: 'vi',
glValidateProgram: function(program) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glValidateProgram', 'program');
+#endif
Module.ctx.validateProgram(GL.programs[program]);
},
@@ -1243,12 +1384,18 @@ var LibraryGL = {
glBindAttribLocation__sig: 'viii',
glBindAttribLocation: function(program, index, name) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.programs, program, 'glBindAttribLocation', 'program');
+#endif
name = Pointer_stringify(name);
Module.ctx.bindAttribLocation(GL.programs[program], index, name);
},
glBindFramebuffer__sig: 'vii',
glBindFramebuffer: function(target, framebuffer) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.framebuffers, framebuffer, 'glBindFramebuffer', 'framebuffer');
+#endif
Module.ctx.bindFramebuffer(target, framebuffer ? GL.framebuffers[framebuffer] : null);
},
@@ -1276,12 +1423,18 @@ var LibraryGL = {
glFramebufferRenderbuffer__sig: 'viiii',
glFramebufferRenderbuffer: function(target, attachment, renderbuffertarget, renderbuffer) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.renderbuffers, renderbuffer, 'glFramebufferRenderbuffer', 'renderbuffer');
+#endif
Module.ctx.framebufferRenderbuffer(target, attachment, renderbuffertarget,
GL.renderbuffers[renderbuffer]);
},
glFramebufferTexture2D__sig: 'viiiii',
glFramebufferTexture2D: function(target, attachment, textarget, texture, level) {
+#if GL_ASSERTIONS
+ GL.validateGLObjectID(GL.textures, texture, 'glFramebufferTexture2D', 'texture');
+#endif
Module.ctx.framebufferTexture2D(target, attachment, textarget,
GL.textures[texture], level);
},
@@ -3161,6 +3314,9 @@ var LibraryGL = {
var clientAttributes = GL.immediate.clientAttributes;
+#if GL_ASSERTIONS
+ GL.validateVertexAttribPointer(positionSize, positionType, GL.immediate.stride, clientAttributes[GL.immediate.VERTEX].offset);
+#endif
Module.ctx.vertexAttribPointer(this.positionLocation, positionSize, positionType, false,
GL.immediate.stride, clientAttributes[GL.immediate.VERTEX].offset);
Module.ctx.enableVertexAttribArray(this.positionLocation);
@@ -3173,6 +3329,9 @@ var LibraryGL = {
if (attribLoc === undefined || attribLoc < 0) continue;
if (texUnitID < textureSizes.length && textureSizes[texUnitID]) {
+#if GL_ASSERTIONS
+ GL.validateVertexAttribPointer(textureSizes[texUnitID], textureTypes[texUnitID], GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + texUnitID].offset);
+#endif
Module.ctx.vertexAttribPointer(attribLoc, textureSizes[texUnitID], textureTypes[texUnitID], false,
GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + texUnitID].offset);
Module.ctx.enableVertexAttribArray(attribLoc);
@@ -3189,6 +3348,9 @@ var LibraryGL = {
}
}
if (colorSize) {
+#if GL_ASSERTIONS
+ GL.validateVertexAttribPointer(colorSize, colorType, GL.immediate.stride, clientAttributes[GL.immediate.COLOR].offset);
+#endif
Module.ctx.vertexAttribPointer(this.colorLocation, colorSize, colorType, true,
GL.immediate.stride, clientAttributes[GL.immediate.COLOR].offset);
Module.ctx.enableVertexAttribArray(this.colorLocation);
@@ -3197,6 +3359,9 @@ var LibraryGL = {
Module.ctx.vertexAttrib4fv(this.colorLocation, GL.immediate.clientColor);
}
if (this.hasNormal) {
+#if GL_ASSERTIONS
+ GL.validateVertexAttribPointer(normalSize, normalType, GL.immediate.stride, clientAttributes[GL.immediate.NORMAL].offset);
+#endif
Module.ctx.vertexAttribPointer(this.normalLocation, normalSize, normalType, true,
GL.immediate.stride, clientAttributes[GL.immediate.NORMAL].offset);
Module.ctx.enableVertexAttribArray(this.normalLocation);
@@ -4176,6 +4341,9 @@ var LibraryGL = {
}
cb.clientside = false;
#endif
+#if GL_ASSERTIONS
+ GL.validateVertexAttribPointer(size, type, stride, ptr);
+#endif
Module.ctx.vertexAttribPointer(index, size, type, normalized, stride, ptr);
},
diff --git a/src/library_idbfs.js b/src/library_idbfs.js
new file mode 100644
index 00000000..9031bad8
--- /dev/null
+++ b/src/library_idbfs.js
@@ -0,0 +1,216 @@
+mergeInto(LibraryManager.library, {
+ $IDBFS__deps: ['$FS', '$MEMFS', '$PATH'],
+ $IDBFS: {
+ dbs: {},
+ indexedDB: function() {
+ return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
+ },
+ DB_VERSION: 20,
+ DB_STORE_NAME: 'FILE_DATA',
+ // reuse all of the core MEMFS functionality
+ mount: function(mount) {
+ return MEMFS.mount.apply(null, arguments);
+ },
+ // the only custom function IDBFS implements is to handle
+ // synchronizing the wrapped MEMFS with a backing IDB instance
+ syncfs: function(mount, populate, callback) {
+ IDBFS.getLocalSet(mount, function(err, local) {
+ if (err) return callback(err);
+
+ IDBFS.getRemoteSet(mount, function(err, remote) {
+ if (err) return callback(err);
+
+ var src = populate ? remote : local;
+ var dst = populate ? local : remote;
+
+ IDBFS.reconcile(src, dst, callback);
+ });
+ });
+ },
+ reconcile: function(src, dst, callback) {
+ var total = 0;
+
+ var create = {};
+ for (var key in src.files) {
+ if (!src.files.hasOwnProperty(key)) continue;
+ var e = src.files[key];
+ var e2 = dst.files[key];
+ if (!e2 || e.timestamp > e2.timestamp) {
+ create[key] = e;
+ total++;
+ }
+ }
+
+ var remove = {};
+ for (var key in dst.files) {
+ if (!dst.files.hasOwnProperty(key)) continue;
+ var e = dst.files[key];
+ var e2 = src.files[key];
+ if (!e2) {
+ remove[key] = e;
+ total++;
+ }
+ }
+
+ if (!total) {
+ // early out
+ return callback(null);
+ }
+
+ var completed = 0;
+ var done = function(err) {
+ if (err) return callback(err);
+ if (++completed >= total) {
+ return callback(null);
+ }
+ };
+
+ // create a single transaction to handle and IDB reads / writes we'll need to do
+ var db = src.type === 'remote' ? src.db : dst.db;
+ var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite');
+ transaction.onerror = function() { callback(this.error); };
+ var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
+
+ for (var path in create) {
+ if (!create.hasOwnProperty(path)) continue;
+ var entry = create[path];
+
+ if (dst.type === 'local') {
+ // save file to local
+ try {
+ if (FS.isDir(entry.mode)) {
+ FS.mkdir(path, entry.mode);
+ } else if (FS.isFile(entry.mode)) {
+ var stream = FS.open(path, 'w+', 0666);
+ FS.write(stream, entry.contents, 0, entry.contents.length, 0, true /* canOwn */);
+ FS.close(stream);
+ }
+ done(null);
+ } catch (e) {
+ return done(e);
+ }
+ } else {
+ // save file to IDB
+ var req = store.put(entry, path);
+ req.onsuccess = function() { done(null); };
+ req.onerror = function() { done(this.error); };
+ }
+ }
+
+ for (var path in remove) {
+ if (!remove.hasOwnProperty(path)) continue;
+ var entry = remove[path];
+
+ if (dst.type === 'local') {
+ // delete file from local
+ try {
+ if (FS.isDir(entry.mode)) {
+ // TODO recursive delete?
+ FS.rmdir(path);
+ } else if (FS.isFile(entry.mode)) {
+ FS.unlink(path);
+ }
+ done(null);
+ } catch (e) {
+ return done(e);
+ }
+ } else {
+ // delete file from IDB
+ var req = store.delete(path);
+ req.onsuccess = function() { done(null); };
+ req.onerror = function() { done(this.error); };
+ }
+ }
+ },
+ getLocalSet: function(mount, callback) {
+ var files = {};
+
+ var isRealDir = function(p) {
+ return p !== '.' && p !== '..';
+ };
+ var toAbsolute = function(root) {
+ return function(p) {
+ return PATH.join(root, p);
+ }
+ };
+
+ var check = FS.readdir(mount.mountpoint)
+ .filter(isRealDir)
+ .map(toAbsolute(mount.mountpoint));
+
+ while (check.length) {
+ var path = check.pop();
+ var stat, node;
+
+ try {
+ var lookup = FS.lookupPath(path);
+ node = lookup.node;
+ stat = FS.stat(path);
+ } catch (e) {
+ return callback(e);
+ }
+
+ if (FS.isDir(stat.mode)) {
+ check.push.apply(check, FS.readdir(path)
+ .filter(isRealDir)
+ .map(toAbsolute(path)));
+
+ files[path] = { mode: stat.mode, timestamp: stat.mtime };
+ } else if (FS.isFile(stat.mode)) {
+ files[path] = { contents: node.contents, mode: stat.mode, timestamp: stat.mtime };
+ } else {
+ return callback(new Error('node type not supported'));
+ }
+ }
+
+ return callback(null, { type: 'local', files: files });
+ },
+ getDB: function(name, callback) {
+ // look it up in the cache
+ var db = IDBFS.dbs[name];
+ if (db) {
+ return callback(null, db);
+ }
+ var req;
+ try {
+ req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ req.onupgradeneeded = function() {
+ db = req.result;
+ db.createObjectStore(IDBFS.DB_STORE_NAME);
+ };
+ req.onsuccess = function() {
+ db = req.result;
+ // add to the cache
+ IDBFS.dbs[name] = db;
+ callback(null, db);
+ };
+ req.onerror = function() {
+ callback(this.error);
+ };
+ },
+ getRemoteSet: function(mount, callback) {
+ var files = {};
+
+ IDBFS.getDB(mount.mountpoint, function(err, db) {
+ if (err) return callback(err);
+
+ var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly');
+ transaction.onerror = function() { callback(this.error); };
+
+ var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
+ store.openCursor().onsuccess = function(event) {
+ var cursor = event.target.result;
+ if (!cursor) {
+ return callback(null, { type: 'remote', db: db, files: files });
+ }
+
+ files[cursor.key] = cursor.value;
+ cursor.continue();
+ };
+ });
+ }
+ }
+});
diff --git a/src/library_memfs.js b/src/library_memfs.js
index 354f5e95..4e56d996 100644
--- a/src/library_memfs.js
+++ b/src/library_memfs.js
@@ -5,18 +5,10 @@ mergeInto(LibraryManager.library, {
CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it, without copying (note: someone else needs to free() it, if that is necessary)
CONTENT_FLEXIBLE: 2, // has been modified or never set to anything, and is a flexible js array that can grow/shrink
CONTENT_FIXED: 3, // contains some fixed-size content written into it, in a typed array
- ensureFlexible: function(node) {
- if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
- var contents = node.contents;
- node.contents = Array.prototype.slice.call(contents);
- node.contentMode = MEMFS.CONTENT_FLEXIBLE;
- }
- },
-
mount: function(mount) {
- return MEMFS.create_node(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
+ return MEMFS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
},
- create_node: function(parent, name, mode, dev) {
+ createNode: function(parent, name, mode, dev) {
if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
// no supported
throw new FS.ErrnoError(ERRNO_CODES.EPERM);
@@ -74,6 +66,13 @@ mergeInto(LibraryManager.library, {
}
return node;
},
+ ensureFlexible: function(node) {
+ if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
+ var contents = node.contents;
+ node.contents = Array.prototype.slice.call(contents);
+ node.contentMode = MEMFS.CONTENT_FLEXIBLE;
+ }
+ },
node_ops: {
getattr: function(node) {
var attr = {};
@@ -121,7 +120,7 @@ mergeInto(LibraryManager.library, {
throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
},
mknod: function(parent, name, mode, dev) {
- return MEMFS.create_node(parent, name, mode, dev);
+ return MEMFS.createNode(parent, name, mode, dev);
},
rename: function(old_node, new_dir, new_name) {
// if we're overwriting a directory at new_name, make sure it's empty.
@@ -163,7 +162,7 @@ mergeInto(LibraryManager.library, {
return entries;
},
symlink: function(parent, newname, oldpath) {
- var node = MEMFS.create_node(parent, newname, 0777 | {{{ cDefine('S_IFLNK') }}}, 0);
+ var node = MEMFS.createNode(parent, newname, 0777 | {{{ cDefine('S_IFLNK') }}}, 0);
node.link = oldpath;
return node;
},
@@ -177,7 +176,10 @@ mergeInto(LibraryManager.library, {
stream_ops: {
read: function(stream, buffer, offset, length, position) {
var contents = stream.node.contents;
+ if (position >= contents.length)
+ return 0;
var size = Math.min(contents.length - position, length);
+ assert(size >= 0);
#if USE_TYPED_ARRAYS == 2
if (size > 8 && contents.subarray) { // non-trivial, and typed array
buffer.set(contents.subarray(position, position + size), offset);
diff --git a/src/library_nodefs.js b/src/library_nodefs.js
new file mode 100644
index 00000000..d8df1689
--- /dev/null
+++ b/src/library_nodefs.js
@@ -0,0 +1,234 @@
+mergeInto(LibraryManager.library, {
+ $NODEFS__deps: ['$FS', '$PATH'],
+ $NODEFS__postset: 'if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); }',
+ $NODEFS: {
+ mount: function (mount) {
+ assert(ENVIRONMENT_IS_NODE);
+ return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0);
+ },
+ createNode: function (parent, name, mode, dev) {
+ if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ var node = FS.createNode(parent, name, mode);
+ node.node_ops = NODEFS.node_ops;
+ node.stream_ops = NODEFS.stream_ops;
+ return node;
+ },
+ getMode: function (path) {
+ var stat;
+ try {
+ stat = fs.lstatSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ return stat.mode;
+ },
+ realPath: function (node) {
+ var parts = [];
+ while (node.parent !== node) {
+ parts.push(node.name);
+ node = node.parent;
+ }
+ parts.push(node.mount.opts.root);
+ parts.reverse();
+ return PATH.join.apply(null, parts);
+ },
+ node_ops: {
+ getattr: function(node) {
+ var path = NODEFS.realPath(node);
+ var stat;
+ try {
+ stat = fs.lstatSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ return {
+ dev: stat.dev,
+ ino: stat.ino,
+ mode: stat.mode,
+ nlink: stat.nlink,
+ uid: stat.uid,
+ gid: stat.gid,
+ rdev: stat.rdev,
+ size: stat.size,
+ atime: stat.atime,
+ mtime: stat.mtime,
+ ctime: stat.ctime,
+ blksize: stat.blksize,
+ blocks: stat.blocks
+ };
+ },
+ setattr: function(node, attr) {
+ var path = NODEFS.realPath(node);
+ try {
+ if (attr.mode !== undefined) {
+ fs.chmodSync(path, attr.mode);
+ // update the common node structure mode as well
+ node.mode = attr.mode;
+ }
+ if (attr.timestamp !== undefined) {
+ var date = new Date(attr.timestamp);
+ fs.utimesSync(path, date, date);
+ }
+ if (attr.size !== undefined) {
+ fs.truncateSync(path, attr.size);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ lookup: function (parent, name) {
+ var path = PATH.join(NODEFS.realPath(parent), name);
+ var mode = NODEFS.getMode(path);
+ return NODEFS.createNode(parent, name, mode);
+ },
+ mknod: function (parent, name, mode, dev) {
+ var node = NODEFS.createNode(parent, name, mode, dev);
+ // create the backing node for this in the fs root as well
+ var path = NODEFS.realPath(node);
+ try {
+ if (FS.isDir(node.mode)) {
+ fs.mkdirSync(path, node.mode);
+ } else {
+ fs.writeFileSync(path, '', { mode: node.mode });
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ return node;
+ },
+ rename: function (oldNode, newDir, newName) {
+ var oldPath = NODEFS.realPath(oldNode);
+ var newPath = PATH.join(NODEFS.realPath(newDir), newName);
+ try {
+ fs.renameSync(oldPath, newPath);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ unlink: function(parent, name) {
+ var path = PATH.join(NODEFS.realPath(parent), name);
+ try {
+ fs.unlinkSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ rmdir: function(parent, name) {
+ var path = PATH.join(NODEFS.realPath(parent), name);
+ try {
+ fs.rmdirSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ readdir: function(node) {
+ var path = NODEFS.realPath(node);
+ try {
+ return fs.readdirSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ symlink: function(parent, newName, oldPath) {
+ var newPath = PATH.join(NODEFS.realPath(parent), newName);
+ try {
+ fs.symlinkSync(oldPath, newPath);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ readlink: function(node) {
+ var path = NODEFS.realPath(node);
+ try {
+ return fs.readlinkSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ },
+ stream_ops: {
+ open: function (stream) {
+ var path = NODEFS.realPath(stream.node);
+ try {
+ if (FS.isFile(stream.node.mode)) {
+ stream.nfd = fs.openSync(path, stream.flags);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ close: function (stream) {
+ try {
+ if (FS.isFile(stream.node.mode)) {
+ fs.closeSync(stream.nfd);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },
+ read: function (stream, buffer, offset, length, position) {
+ // FIXME this is terrible.
+ var nbuffer = new Buffer(length);
+ var res;
+ try {
+ res = fs.readSync(stream.nfd, nbuffer, 0, length, position);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ if (res > 0) {
+ for (var i = 0; i < res; i++) {
+ buffer[offset + i] = nbuffer[i];
+ }
+ }
+ return res;
+ },
+ write: function (stream, buffer, offset, length, position) {
+ // FIXME this is terrible.
+ var nbuffer = new Buffer(buffer.subarray(offset, offset + length));
+ var res;
+ try {
+ res = fs.writeSync(stream.nfd, nbuffer, 0, length, position);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ return res;
+ },
+ llseek: function (stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) { // SEEK_CUR.
+ position += stream.position;
+ } else if (whence === 2) { // SEEK_END.
+ if (FS.isFile(stream.node.mode)) {
+ try {
+ var stat = fs.fstatSync(stream.nfd);
+ position += stat.size;
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ }
+ }
+
+ if (position < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+
+ stream.position = position;
+ return position;
+ }
+ }
+ }
+}); \ No newline at end of file
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 656b5a02..1d6a00b6 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -627,7 +627,7 @@ var LibrarySDL = {
// since the browser engine handles that for us. Therefore, in JS we just
// maintain a list of channels and return IDs for them to the SDL consumer.
allocateChannels: function(num) { // called from Mix_AllocateChannels and init
- if (SDL.numChannels && SDL.numChannels >= num) return;
+ if (SDL.numChannels && SDL.numChannels >= num && num != 0) return;
SDL.numChannels = num;
SDL.channels = [];
for (var i = 0; i < num; i++) {
@@ -1054,7 +1054,10 @@ var LibrarySDL = {
} else {
dr = { x: 0, y: 0, w: -1, h: -1 };
}
+ var oldAlpha = dstData.ctx.globalAlpha;
+ dstData.ctx.globalAlpha = srcData.alpha/255;
dstData.ctx.drawImage(srcData.canvas, sr.x, sr.y, sr.w, sr.h, dr.x, dr.y, sr.w, sr.h);
+ dstData.ctx.globalAlpha = oldAlpha;
if (dst != SDL.screen) {
// XXX As in IMG_Load, for compatibility we write out |pixels|
console.log('WARNING: copying canvas data to memory for compatibility');
@@ -1377,60 +1380,240 @@ var LibrarySDL = {
// SDL_Audio
- // TODO fix SDL_OpenAudio, and add some tests for it. It's currently broken.
SDL_OpenAudio: function(desired, obtained) {
- SDL.allocateChannels(32);
-
- SDL.audio = {
- freq: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.freq, 'i32', 0, 1) }}},
- format: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.format, 'i16', 0, 1) }}},
- channels: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.channels, 'i8', 0, 1) }}},
- samples: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.samples, 'i16', 0, 1) }}},
- callback: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.callback, 'void*', 0, 1) }}},
- userdata: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.userdata, 'void*', 0, 1) }}},
- paused: true,
- timer: null
- };
-
- if (obtained) {
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.freq, 'SDL.audio.freq', 'i32') }}}; // no good way for us to know if the browser can really handle this
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.format, 33040, 'i16') }}}; // float, signed, 16-bit
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.channels, 'SDL.audio.channels', 'i8') }}};
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.silence, makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.silence, 'i8', 0, 1), 'i8') }}}; // unclear if browsers can provide this
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.samples, 'SDL.audio.samples', 'i16') }}};
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.callback, 'SDL.audio.callback', '*') }}};
- {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.userdata, 'SDL.audio.userdata', '*') }}};
- }
-
- var totalSamples = SDL.audio.samples*SDL.audio.channels;
- SDL.audio.bufferSize = totalSamples*2; // hardcoded 16-bit audio
- SDL.audio.buffer = _malloc(SDL.audio.bufferSize);
- SDL.audio.caller = function() {
- Runtime.dynCall('viii', SDL.audio.callback, [SDL.audio.userdata, SDL.audio.buffer, SDL.audio.bufferSize]);
- SDL.audio.pushAudio(SDL.audio.buffer, SDL.audio.bufferSize);
- };
- // Mozilla Audio API. TODO: Other audio APIs
try {
- SDL.audio.mozOutput = new Audio();
- SDL.audio.mozOutput['mozSetup'](SDL.audio.channels, SDL.audio.freq); // use string attributes on mozOutput for closure compiler
- SDL.audio.mozBuffer = new Float32Array(totalSamples);
- SDL.audio.pushAudio = function(ptr, size) {
- var mozBuffer = SDL.audio.mozBuffer;
- for (var i = 0; i < totalSamples; i++) {
- mozBuffer[i] = ({{{ makeGetValue('ptr', 'i*2', 'i16', 0, 0) }}}) / 0x8000; // hardcoded 16-bit audio, signed (TODO: reSign if not ta2?)
+ SDL.audio = {
+ freq: {{{ makeGetValue('desired', 'C_STRUCTS.SDL_AudioSpec.freq', 'i32', 0, 1) }}},
+ format: {{{ makeGetValue('desired', 'C_STRUCTS.SDL_AudioSpec.format', 'i16', 0, 1) }}},
+ channels: {{{ makeGetValue('desired', 'C_STRUCTS.SDL_AudioSpec.channels', 'i8', 0, 1) }}},
+ samples: {{{ makeGetValue('desired', 'C_STRUCTS.SDL_AudioSpec.samples', 'i16', 0, 1) }}}, // Samples in the CB buffer per single sound channel.
+ callback: {{{ makeGetValue('desired', 'C_STRUCTS.SDL_AudioSpec.callback', 'void*', 0, 1) }}},
+ userdata: {{{ makeGetValue('desired', 'C_STRUCTS.SDL_AudioSpec.userdata', 'void*', 0, 1) }}},
+ paused: true,
+ timer: null
+ };
+ // The .silence field tells the constant sample value that corresponds to the safe un-skewed silence value for the wave data.
+ if (SDL.audio.format == 0x0008 /*AUDIO_U8*/) {
+ SDL.audio.silence = 128; // Audio ranges in [0, 255], so silence is half-way in between.
+ } else if (SDL.audio.format == 0x8010 /*AUDIO_S16LSB*/) {
+ SDL.audio.silence = 0; // Signed data in range [-32768, 32767], silence is 0.
+ } else {
+ throw 'Invalid SDL audio format ' + SDL.audio.format + '!';
+ }
+ // Round the desired audio frequency up to the next 'common' frequency value.
+ // Web Audio API spec states 'An implementation must support sample-rates in at least the range 22050 to 96000.'
+ if (SDL.audio.freq <= 0) {
+ throw 'Unsupported sound frequency ' + SDL.audio.freq + '!';
+ } else if (SDL.audio.freq <= 22050) {
+ SDL.audio.freq = 22050; // Take it safe and clamp everything lower than 22kHz to that.
+ } else if (SDL.audio.freq <= 32000) {
+ SDL.audio.freq = 32000;
+ } else if (SDL.audio.freq <= 44100) {
+ SDL.audio.freq = 44100;
+ } else if (SDL.audio.freq <= 48000) {
+ SDL.audio.freq = 48000;
+ } else if (SDL.audio.freq <= 96000) {
+ SDL.audio.freq = 96000;
+ } else {
+ throw 'Unsupported sound frequency ' + SDL.audio.freq + '!';
+ }
+ if (SDL.audio.channels == 0) {
+ SDL.audio.channels = 1; // In SDL both 0 and 1 mean mono.
+ } else if (SDL.audio.channels < 0 || SDL.audio.channels > 32) {
+ throw 'Unsupported number of audio channels for SDL audio: ' + SDL.audio.channels + '!';
+ } else if (SDL.audio.channels != 1 && SDL.audio.channels != 2) { // Unsure what SDL audio spec supports. Web Audio spec supports up to 32 channels.
+ console.log('Warning: Using untested number of audio channels ' + SDL.audio.channels);
+ }
+ if (SDL.audio.samples < 1024 || SDL.audio.samples > 524288 /* arbitrary cap */) {
+ throw 'Unsupported audio callback buffer size ' + SDL.audio.samples + '!';
+ } else if ((SDL.audio.samples & (SDL.audio.samples-1)) != 0) {
+ throw 'Audio callback buffer size ' + SDL.audio.samples + ' must be a power-of-two!';
+ }
+
+ var totalSamples = SDL.audio.samples*SDL.audio.channels;
+ SDL.audio.bytesPerSample = (SDL.audio.format == 0x0008 /*AUDIO_U8*/ || SDL.audio.format == 0x8008 /*AUDIO_S8*/) ? 1 : 2;
+ SDL.audio.bufferSize = totalSamples*SDL.audio.bytesPerSample;
+ SDL.audio.buffer = _malloc(SDL.audio.bufferSize);
+
+ // Create a callback function that will be routinely called to ask more audio data from the user application.
+ SDL.audio.caller = function() {
+ if (!SDL.audio) {
+ return;
+ }
+ Runtime.dynCall('viii', SDL.audio.callback, [SDL.audio.userdata, SDL.audio.buffer, SDL.audio.bufferSize]);
+ SDL.audio.pushAudio(SDL.audio.buffer, SDL.audio.bufferSize);
+ };
+
+ SDL.audio.audioOutput = new Audio();
+ // As a workaround use Mozilla Audio Data API on Firefox until it ships with Web Audio and sound quality issues are fixed.
+ if (typeof(SDL.audio.audioOutput['mozSetup'])==='function') {
+ SDL.audio.audioOutput['mozSetup'](SDL.audio.channels, SDL.audio.freq); // use string attributes on mozOutput for closure compiler
+ SDL.audio.mozBuffer = new Float32Array(totalSamples);
+ SDL.audio.nextPlayTime = 0;
+ SDL.audio.pushAudio = function(ptr, size) {
+ var mozBuffer = SDL.audio.mozBuffer;
+ // The input audio data for SDL audio is either 8-bit or 16-bit interleaved across channels, output for Mozilla Audio Data API
+ // needs to be Float32 interleaved, so perform a sample conversion.
+ if (SDL.audio.format == 0x8010 /*AUDIO_S16LSB*/) {
+ for (var i = 0; i < totalSamples; i++) {
+ mozBuffer[i] = ({{{ makeGetValue('ptr', 'i*2', 'i16', 0, 0) }}}) / 0x8000;
+ }
+ } else if (SDL.audio.format == 0x0008 /*AUDIO_U8*/) {
+ for (var i = 0; i < totalSamples; i++) {
+ var v = ({{{ makeGetValue('ptr', 'i', 'i8', 0, 0) }}});
+ mozBuffer[i] = ((v >= 0) ? v-128 : v+128) /128;
+ }
+ }
+ // Submit the audio data to audio device.
+ SDL.audio.audioOutput['mozWriteAudio'](mozBuffer);
+
+ // Compute when the next audio callback should be called.
+ var curtime = Date.now() / 1000.0 - SDL.audio.startTime;
+ if (curtime > SDL.audio.nextPlayTime && SDL.audio.nextPlayTime != 0) {
+ console.log('warning: Audio callback had starved sending audio by ' + (curtime - SDL.audio.nextPlayTime) + ' seconds.');
+ }
+ var playtime = Math.max(curtime, SDL.audio.nextPlayTime);
+ var buffer_duration = SDL.audio.samples / SDL.audio.freq;
+ SDL.audio.nextPlayTime = playtime + buffer_duration;
+ // Schedule the next audio callback call.
+ SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1000.0 * (playtime-curtime));
+ }
+ } else {
+ // Initialize Web Audio API if we haven't done so yet. Note: Only initialize Web Audio context ever once on the web page,
+ // since initializing multiple times fails on Chrome saying 'audio resources have been exhausted'.
+ if (!SDL.audioContext) {
+ if (typeof(AudioContext) === 'function') {
+ SDL.audioContext = new AudioContext();
+ } else if (typeof(webkitAudioContext) === 'function') {
+ SDL.audioContext = new webkitAudioContext();
+ } else {
+ throw 'Web Audio API is not available!';
+ }
+ }
+ SDL.audio.soundSource = new Array(); // Use an array of sound sources as a ring buffer to queue blocks of synthesized audio to Web Audio API.
+ SDL.audio.nextSoundSource = 0; // Index of the next sound buffer in the ring buffer queue to play.
+ SDL.audio.nextPlayTime = 0; // Time in seconds when the next audio block is due to start.
+
+ // The pushAudio function with a new audio buffer whenever there is new audio data to schedule to be played back on the device.
+ SDL.audio.pushAudio=function(ptr,sizeBytes) {
+ try {
+ --SDL.audio.numAudioTimersPending;
+
+ var sizeSamples = sizeBytes / SDL.audio.bytesPerSample; // How many samples fit in the callback buffer?
+ var sizeSamplesPerChannel = sizeSamples / SDL.audio.channels; // How many samples per a single channel fit in the cb buffer?
+ if (sizeSamplesPerChannel != SDL.audio.samples) {
+ throw 'Received mismatching audio buffer size!';
+ }
+ // Allocate new sound buffer to be played.
+ var source = SDL.audioContext['createBufferSource']();
+ if (SDL.audio.soundSource[SDL.audio.nextSoundSource]) {
+ SDL.audio.soundSource[SDL.audio.nextSoundSource]['disconnect'](); // Explicitly disconnect old source, since we know it shouldn't be running anymore.
+ }
+ SDL.audio.soundSource[SDL.audio.nextSoundSource] = source;
+ var soundBuffer = SDL.audioContext['createBuffer'](SDL.audio.channels,sizeSamplesPerChannel,SDL.audio.freq);
+ SDL.audio.soundSource[SDL.audio.nextSoundSource]['connect'](SDL.audioContext['destination']);
+
+ // The input audio data is interleaved across the channels, i.e. [L, R, L, R, L, R, ...] and is either 8-bit or 16-bit as
+ // supported by the SDL API. The output audio wave data for Web Audio API must be in planar buffers of [-1,1]-normalized Float32 data,
+ // so perform a buffer conversion for the data.
+ var numChannels = SDL.audio.channels;
+ for(var i = 0; i < numChannels; ++i) {
+ var channelData = soundBuffer['getChannelData'](i);
+ if (channelData.length != sizeSamplesPerChannel) {
+ throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + sizeSamplesPerChannel + ' samples!';
+ }
+ if (SDL.audio.format == 0x8010 /*AUDIO_S16LSB*/) {
+ for(var j = 0; j < sizeSamplesPerChannel; ++j) {
+ channelData[j] = ({{{ makeGetValue('ptr', '(j*numChannels + i)*2', 'i16', 0, 0) }}}) / 0x8000;
+ }
+ } else if (SDL.audio.format == 0x0008 /*AUDIO_U8*/) {
+ for(var j = 0; j < sizeSamplesPerChannel; ++j) {
+ var v = ({{{ makeGetValue('ptr', 'j*numChannels + i', 'i8', 0, 0) }}});
+ channelData[j] = ((v >= 0) ? v-128 : v+128) /128;
+ }
+ }
+ }
+ // Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=883675 by setting the buffer only after filling. The order is important here!
+ source['buffer'] = soundBuffer;
+
+ // Schedule the generated sample buffer to be played out at the correct time right after the previously scheduled
+ // sample buffer has finished.
+ var curtime = SDL.audioContext['currentTime'];
+// if (curtime > SDL.audio.nextPlayTime && SDL.audio.nextPlayTime != 0) {
+// console.log('warning: Audio callback had starved sending audio by ' + (curtime - SDL.audio.nextPlayTime) + ' seconds.');
+// }
+ var playtime = Math.max(curtime, SDL.audio.nextPlayTime);
+ SDL.audio.soundSource[SDL.audio.nextSoundSource]['start'](playtime);
+ var buffer_duration = sizeSamplesPerChannel / SDL.audio.freq;
+ SDL.audio.nextPlayTime = playtime + buffer_duration;
+ SDL.audio.nextSoundSource = (SDL.audio.nextSoundSource + 1) % 4;
+ var secsUntilNextCall = playtime-curtime;
+
+ // Queue the next audio frame push to be performed when the previously queued buffer has finished playing.
+ if (SDL.audio.numAudioTimersPending == 0) {
+ var preemptBufferFeedMSecs = buffer_duration/2.0;
+ SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, Math.max(0.0, 1000.0*secsUntilNextCall-preemptBufferFeedMSecs));
+ ++SDL.audio.numAudioTimersPending;
+ }
+
+ // If we are risking starving, immediately queue an extra second buffer.
+ if (secsUntilNextCall <= buffer_duration && SDL.audio.numAudioTimersPending <= 1) {
+ ++SDL.audio.numAudioTimersPending;
+ Browser.safeSetTimeout(SDL.audio.caller, 1.0);
+ }
+ } catch(e) {
+ console.log('Web Audio API error playing back audio: ' + e.toString());
+ }
}
- SDL.audio.mozOutput['mozWriteAudio'](mozBuffer);
}
+
+ if (obtained) {
+ // Report back the initialized audio parameters.
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.freq', 'SDL.audio.freq', 'i32') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.format', 'SDL.audio.format', 'i16') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.channels', 'SDL.audio.channels', 'i8') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.silence', 'SDL.audio.silence', 'i8') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.samples', 'SDL.audio.samples', 'i16') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.callback', 'SDL.audio.callback', '*') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.userdata', 'SDL.audio.userdata', '*') }}};
+ }
+ SDL.allocateChannels(32);
+
} catch(e) {
+ console.log('Initializing SDL audio threw an exception: "' + e.toString() + '"! Continuing without audio.');
SDL.audio = null;
+ SDL.allocateChannels(0);
+ if (obtained) {
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.freq', 0, 'i32') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.format', 0, 'i16') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.channels', 0, 'i8') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.silence', 0, 'i8') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.samples', 0, 'i16') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.callback', 0, '*') }}};
+ {{{ makeSetValue('obtained', 'C_STRUCTS.SDL_AudioSpec.userdata', 0, '*') }}};
+ }
+ }
+ if (!SDL.audio) {
+ return -1;
}
- if (!SDL.audio) return -1;
return 0;
},
SDL_PauseAudio: function(pauseOn) {
- if (SDL.audio.paused !== pauseOn) {
- SDL.audio.timer = pauseOn ? SDL.audio.timer && clearInterval(SDL.audio.timer) : Browser.safeSetInterval(SDL.audio.caller, 1/35);
+ if (!SDL.audio) {
+ return;
+ }
+ if (pauseOn) {
+ if (SDL.audio.timer !== undefined) {
+ clearTimeout(SDL.audio.timer);
+ SDL.audio.numAudioTimersPending = 0;
+ SDL.audio.timer = undefined;
+ }
+ } else if (!SDL.audio.timer) {
+ // Start the audio playback timer callback loop.
+ SDL.audio.numAudioTimersPending = 1;
+ SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1);
+ SDL.audio.startTime = Date.now() / 1000.0; // Only used for Mozilla Audio Data API. Not needed for Web Audio API.
}
SDL.audio.paused = pauseOn;
},
@@ -1438,9 +1621,18 @@ var LibrarySDL = {
SDL_CloseAudio__deps: ['SDL_PauseAudio', 'free'],
SDL_CloseAudio: function() {
if (SDL.audio) {
+ try{
+ for(var i = 0; i < SDL.audio.soundSource.length; ++i) {
+ if (!(typeof(SDL.audio.soundSource[i]==='undefined'))) {
+ SDL.audio.soundSource[i].stop(0);
+ }
+ }
+ } catch(e) {}
+ SDL.audio.soundSource = null;
_SDL_PauseAudio(1);
_free(SDL.audio.buffer);
SDL.audio = null;
+ SDL.allocateChannels(0);
}
},
diff --git a/src/library_sockfs.js b/src/library_sockfs.js
index b11c6495..af29d11b 100644
--- a/src/library_sockfs.js
+++ b/src/library_sockfs.js
@@ -5,12 +5,6 @@ mergeInto(LibraryManager.library, {
mount: function(mount) {
return FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
},
- nextname: function() {
- if (!SOCKFS.nextname.current) {
- SOCKFS.nextname.current = 0;
- }
- return 'socket[' + (SOCKFS.nextname.current++) + ']';
- },
createSocket: function(family, type, protocol) {
var streaming = type == {{{ cDefine('SOCK_STREAM') }}};
if (protocol) {
@@ -95,6 +89,12 @@ mergeInto(LibraryManager.library, {
sock.sock_ops.close(sock);
}
},
+ nextname: function() {
+ if (!SOCKFS.nextname.current) {
+ SOCKFS.nextname.current = 0;
+ }
+ return 'socket[' + (SOCKFS.nextname.current++) + ']';
+ },
// backend-specific stream ops
websocket_sock_ops: {
//
diff --git a/src/modules.js b/src/modules.js
index 1a931572..2757c2cb 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -422,7 +422,7 @@ var LibraryManager = {
load: function() {
if (this.library) return;
- var libraries = ['library.js', 'library_path.js', 'library_fs.js', 'library_memfs.js', 'library_sockfs.js', 'library_tty.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js', 'library_jansson.js', 'library_openal.js', 'library_glfw.js'].concat(additionalLibraries);
+ var libraries = ['library.js', 'library_path.js', 'library_fs.js', 'library_idbfs.js', 'library_memfs.js', 'library_nodefs.js', 'library_sockfs.js', 'library_tty.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js', 'library_jansson.js', 'library_openal.js', 'library_glfw.js'].concat(additionalLibraries);
for (var i = 0; i < libraries.length; i++) {
eval(processMacros(preprocess(read(libraries[i]))));
}
@@ -508,3 +508,7 @@ var PassManager = {
}
};
+var Framework = {
+ currItem: null
+};
+
diff --git a/src/parseTools.js b/src/parseTools.js
index 2ccf0179..7ebc0de2 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -111,12 +111,22 @@ function isNiceIdent(ident, loose) {
}
function isJSVar(ident) {
- return /^\(?[$_]?[\w$_\d ]*\)+$/.test(ident);
-
+ if (ident[0] === '(') {
+ if (ident[ident.length-1] !== ')') return false;
+ ident = ident.substr(1, ident.length-2);
+ }
+ return /^[$_]?[\w$_\d]* *$/.test(ident);
}
function isLocalVar(ident) {
- return ident[0] == '$';
+ return ident[0] === '$';
+}
+
+// Simple variables or numbers, or things already quoted, do not need to be quoted
+function needsQuoting(ident) {
+ if (/^[-+]?[$_]?[\w$_\d]*$/.test(ident)) return false; // number or variable
+ if (ident[0] === '(' && ident[ident.length-1] === ')' && ident.indexOf('(', 1) < 0) return false; // already fully quoted
+ return true;
}
function isStructPointerType(type) {
@@ -933,12 +943,12 @@ function parseLLVMString(str) {
var ret = [];
var i = 0;
while (i < str.length) {
- var chr = str[i];
- if (chr != '\\') {
- ret.push(chr.charCodeAt(0));
+ var chr = str.charCodeAt(i);
+ if (chr !== 92) { // 92 === '//'.charCodeAt(0)
+ ret.push(chr);
i++;
} else {
- ret.push(eval('0x' + str[i+1]+str[i+2]));
+ ret.push(parseInt(str[i+1]+str[i+2], '16'));
i += 3;
}
}
@@ -1197,7 +1207,7 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa
var typeData = Types.types[type];
var ret = [];
for (var i = 0; i < typeData.fields.length; i++) {
- ret.push('f' + i + ': ' + makeGetValue(ptr, pos + typeData.flatIndexes[i], typeData.fields[i], noNeedFirst, unsigned));
+ ret.push('f' + i + ': ' + makeGetValue(ptr, pos + typeData.flatIndexes[i], typeData.fields[i], noNeedFirst, unsigned, 0, 0, noSafe));
}
return '{ ' + ret.join(', ') + ' }';
}
@@ -1205,8 +1215,8 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa
// In double mode 1, in x86 we always assume unaligned because we can't trust that; otherwise in le32
// we need this code path if we are not fully aligned.
if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double' && (TARGET_X86 || align < 8)) {
- return '(' + makeSetTempDouble(0, 'i32', makeGetValue(ptr, pos, 'i32', noNeedFirst, unsigned, ignore, align)) + ',' +
- makeSetTempDouble(1, 'i32', makeGetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'i32', noNeedFirst, unsigned, ignore, align)) + ',' +
+ return '(' + makeSetTempDouble(0, 'i32', makeGetValue(ptr, pos, 'i32', noNeedFirst, unsigned, ignore, align, noSafe)) + ',' +
+ makeSetTempDouble(1, 'i32', makeGetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'i32', noNeedFirst, unsigned, ignore, align, noSafe)) + ',' +
makeGetTempDouble(0, 'double') + ')';
}
@@ -1219,12 +1229,12 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa
if (isIntImplemented(type)) {
if (bytes == 4 && align == 2) {
// Special case that we can optimize
- ret += makeGetValue(ptr, pos, 'i16', noNeedFirst, 2, ignore) + '|' +
- '(' + makeGetValue(ptr, getFastValue(pos, '+', 2), 'i16', noNeedFirst, 2, ignore) + '<<16)';
+ ret += makeGetValue(ptr, pos, 'i16', noNeedFirst, 2, ignore, 2, noSafe) + '|' +
+ '(' + makeGetValue(ptr, getFastValue(pos, '+', 2), 'i16', noNeedFirst, 2, ignore, 2, noSafe) + '<<16)';
} else { // XXX we cannot truly handle > 4... (in x86)
ret = '';
for (var i = 0; i < bytes; i++) {
- ret += '(' + makeGetValue(ptr, getFastValue(pos, '+', i), 'i8', noNeedFirst, 1, ignore) + (i > 0 ? '<<' + (8*i) : '') + ')';
+ ret += '(' + makeGetValue(ptr, getFastValue(pos, '+', i), 'i8', noNeedFirst, 1, ignore, 1, noSafe) + (i > 0 ? '<<' + (8*i) : '') + ')';
if (i < bytes-1) ret += '|';
}
ret = '(' + makeSignOp(ret, type, unsigned ? 'un' : 're', true);
@@ -1303,7 +1313,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
value = range(typeData.fields.length).map(function(i) { return value + '.f' + i });
}
for (var i = 0; i < typeData.fields.length; i++) {
- ret.push(makeSetValue(ptr, getFastValue(pos, '+', typeData.flatIndexes[i]), value[i], typeData.fields[i], noNeedFirst));
+ ret.push(makeSetValue(ptr, getFastValue(pos, '+', typeData.flatIndexes[i]), value[i], typeData.fields[i], noNeedFirst, 0, 0, noSafe));
}
return ret.join('; ');
}
@@ -1330,17 +1340,17 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
if (bytes == 4 && align == 2) {
// Special case that we can optimize
ret += 'tempBigInt=' + value + sep;
- ret += makeSetValue(ptr, pos, 'tempBigInt&0xffff', 'i16', noNeedFirst, ignore, 2) + sep;
- ret += makeSetValue(ptr, getFastValue(pos, '+', 2), 'tempBigInt>>16', 'i16', noNeedFirst, ignore, 2);
+ ret += makeSetValue(ptr, pos, 'tempBigInt&0xffff', 'i16', noNeedFirst, ignore, 2, noSafe) + sep;
+ ret += makeSetValue(ptr, getFastValue(pos, '+', 2), 'tempBigInt>>16', 'i16', noNeedFirst, ignore, 2, noSafe);
} else {
ret += 'tempBigInt=' + value + sep;
for (var i = 0; i < bytes; i++) {
- ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore, 1);
+ ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore, 1, noSafe);
if (i < bytes-1) ret += sep + 'tempBigInt = tempBigInt>>8' + sep;
}
}
} else {
- ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8, null, null, true) + sep;
+ ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8, noSafe, null, true) + sep;
ret += makeCopyValues(getFastValue(ptr, '+', pos), 'tempDoublePtr', Runtime.getNativeTypeSize(type), type, null, align, sep);
}
return ret;
@@ -1349,6 +1359,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
value = indexizeFunctions(value, type);
var offset = calcFastOffset(ptr, pos, noNeedFirst);
+ if (phase === 'pre' && isNumber(offset)) offset += ' '; // avoid pure numeric strings, seem to be perf issues with overly-aggressive interning or slt in pre processing of heap inits
if (SAFE_HEAP && !noSafe) {
var printType = type;
if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"';
@@ -1465,77 +1476,97 @@ function makeHEAPView(which, start, end) {
return 'HEAP' + which + '.subarray((' + start + ')' + mod + ',(' + end + ')' + mod + ')';
}
-var PLUS_MUL = set('+', '*');
-var MUL_DIV = set('*', '/');
-var PLUS_MINUS = set('+', '-');
var TWO_TWENTY = Math.pow(2, 20);
// Given two values and an operation, returns the result of that operation.
// Tries to do as much as possible at compile time.
// Leaves overflows etc. unhandled, *except* for integer multiply, in order to be efficient with Math.imul
function getFastValue(a, op, b, type) {
- a = a.toString();
- b = b.toString();
- a = a == 'true' ? '1' : (a == 'false' ? '0' : a);
- b = b == 'true' ? '1' : (b == 'false' ? '0' : b);
- if (isNumber(a) && isNumber(b)) {
- if (op == 'pow') {
- return Math.pow(a, b).toString();
- } else {
- var value = eval(a + op + '(' + b + ')'); // parens protect us from "5 - -12" being seen as "5--12" which is "(5--)12"
- if (op == '/' && type in Runtime.INT_TYPES) value = value|0; // avoid emitting floats
- return value.toString();
+ a = a === 'true' ? '1' : (a === 'false' ? '0' : a);
+ b = b === 'true' ? '1' : (b === 'false' ? '0' : b);
+
+ var aNumber = null, bNumber = null;
+ if (typeof a === 'number') {
+ aNumber = a;
+ a = a.toString();
+ } else if (isNumber(a)) aNumber = parseFloat(a);
+ if (typeof b === 'number') {
+ bNumber = b;
+ b = b.toString();
+ } else if (isNumber(b)) bNumber = parseFloat(b);
+
+ if (aNumber !== null && bNumber !== null) {
+ switch (op) {
+ case '+': return (aNumber + bNumber).toString();
+ case '-': return (aNumber - bNumber).toString();
+ case '*': return (aNumber * bNumber).toString();
+ case '/': {
+ if (type[0] === 'i') {
+ return ((aNumber / bNumber)|0).toString();
+ } else {
+ return (aNumber / bNumber).toString();
+ }
+ }
+ case '%': return (aNumber % bNumber).toString();
+ case '|': return (aNumber | bNumber).toString();
+ case '>>>': return (aNumber >>> bNumber).toString();
+ case '&': return (aNumber & bNumber).toString();
+ case 'pow': return Math.pow(aNumber, bNumber).toString();
+ default: throw 'need to implement getFastValue pn ' + op;
}
}
- if (op == 'pow') {
- if (a == '2' && isIntImplemented(type)) {
+ if (op === 'pow') {
+ if (a === '2' && isIntImplemented(type)) {
return '(1 << (' + b + '))';
}
return 'Math.pow(' + a + ', ' + b + ')';
}
- if (op in PLUS_MUL && isNumber(a)) { // if one of them is a number, keep it last
+ if ((op === '+' || op === '*') && aNumber !== null) { // if one of them is a number, keep it last
var c = b;
b = a;
a = c;
- }
- if (op in MUL_DIV) {
- if (op == '*') {
- if (a == 0 || b == 0) {
- return '0';
- } else if (a == 1) {
- return b;
- } else if (b == 1) {
- return a;
- } else if (isNumber(b) && type && isIntImplemented(type) && Runtime.getNativeTypeSize(type) <= 32) {
- var shifts = Math.log(parseFloat(b))/Math.LN2;
- if (shifts % 1 == 0) {
- return '(' + a + '<<' + shifts + ')';
- }
+ var cNumber = bNumber;
+ bNumber = aNumber;
+ aNumber = cNumber;
+ }
+ if (op === '*') {
+ // We can't eliminate where a or b are 0 as that would break things for creating
+ // a negative 0.
+ if ((aNumber === 0 || bNumber === 0) && !(type in Runtime.FLOAT_TYPES)) {
+ return '0';
+ } else if (aNumber === 1) {
+ return b;
+ } else if (bNumber === 1) {
+ return a;
+ } else if (bNumber !== null && type && isIntImplemented(type) && Runtime.getNativeTypeSize(type) <= 32) {
+ var shifts = Math.log(bNumber)/Math.LN2;
+ if (shifts % 1 === 0) {
+ return '(' + a + '<<' + shifts + ')';
}
- if (!(type in Runtime.FLOAT_TYPES)) {
- // if guaranteed small enough to not overflow into a double, do a normal multiply
- var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes
- // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there
- if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
- return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
- }
- return '(Math.imul(' + a + ',' + b + ')|0)';
+ }
+ if (!(type in Runtime.FLOAT_TYPES)) {
+ // if guaranteed small enough to not overflow into a double, do a normal multiply
+ var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes
+ // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there
+ if ((aNumber !== null && Math.abs(a) < TWO_TWENTY) || (bNumber !== null && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
+ return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
}
- } else {
- if (a == '0') {
- return '0';
- } else if (b == 1) {
- return a;
- } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
- }
- } else if (op in PLUS_MINUS) {
- if (b[0] == '-') {
- op = op == '+' ? '-' : '+';
+ return '(Math.imul(' + a + ',' + b + ')|0)';
+ }
+ } else if (op === '/') {
+ if (a === '0' && !(type in Runtime.FLOAT_TYPES)) { // careful on floats, since 0*NaN is not 0
+ return '0';
+ } else if (b === 1) {
+ return a;
+ } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
+ } else if (op === '+' || op === '-') {
+ if (b[0] === '-') {
+ op = op === '+' ? '-' : '+';
b = b.substr(1);
}
- if (a == 0) {
- return op == '+' ? b : '(-' + b + ')';
- } else if (b == 0) {
+ if (aNumber === 0) {
+ return op === '+' ? b : '(-' + b + ')';
+ } else if (bNumber === 0) {
return a;
}
}
@@ -1564,12 +1595,8 @@ function getFastValues(list, op, type) {
}
function calcFastOffset(ptr, pos, noNeedFirst) {
- var offset = noNeedFirst ? '0' : makeGetPos(ptr);
- return getFastValue(offset, '+', pos, 'i32');
-}
-
-function makeGetPos(ptr) {
- return ptr;
+ assert(!noNeedFirst);
+ return getFastValue(ptr, '+', pos, 'i32');
}
var IHEAP_FHEAP = set('IHEAP', 'IHEAPU', 'FHEAP');
@@ -1759,7 +1786,7 @@ function checkBitcast(item) {
} else {
warnOnce('Casting a function pointer type to a potentially incompatible one (use -s VERBOSE=1 to see more)');
}
- warnOnce('See https://github.com/kripken/emscripten/wiki/CodeGuidlinesAndLimitations#function-pointer-issues for more information on dangerous function pointer casts');
+ warnOnce('See https://github.com/kripken/emscripten/wiki/CodeGuidelinesAndLimitations#function-pointer-issues for more information on dangerous function pointer casts');
if (ASM_JS) warnOnce('Incompatible function pointer casts are very dangerous with ASM_JS=1, you should investigate and correct these');
}
if (oldCount != newCount && oldCount && newCount) showWarning();
@@ -1806,7 +1833,7 @@ function getGetElementPtrIndexes(item) {
// struct, and possibly further substructures, all embedded
// can also be to 'blocks': [8 x i32]*, not just structs
type = removePointing(type);
- var indexes = [makeGetPos(ident)];
+ var indexes = [ident];
var offset = item.params[1];
if (offset != 0) {
if (isStructType(type)) {
@@ -1961,13 +1988,12 @@ function makeSignOp(value, type, op, force, ignore) {
if (USE_TYPED_ARRAYS == 2 && type == 'i64') {
return value; // these are always assumed to be two 32-bit unsigneds.
}
-
if (isPointerType(type)) type = 'i32'; // Pointers are treated as 32-bit ints
if (!value) return value;
var bits, full;
if (type in Runtime.INT_TYPES) {
bits = parseInt(type.substr(1));
- full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(ignore || (correctSpecificSign())) + ')';
+ full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(ignore || correctSpecificSign()) + ')';
// Always sign/unsign constants at compile time, regardless of CHECK/CORRECT
if (isNumber(value)) {
return eval(full).toString();
@@ -1975,23 +2001,25 @@ function makeSignOp(value, type, op, force, ignore) {
}
if ((ignore || !correctSigns()) && !CHECK_SIGNS && !force) return value;
if (type in Runtime.INT_TYPES) {
+ // this is an integer, but not a number (or we would have already handled it)
// shortcuts
if (!CHECK_SIGNS || ignore) {
+ if (value === 'true') {
+ value = '1';
+ } else if (value === 'false') {
+ value = '0';
+ } else if (needsQuoting(value)) value = '(' + value + ')';
if (bits === 32) {
if (op === 're') {
- return '(' + getFastValue(value, '|', '0') + ')';
+ return '(' + value + '|0)';
} else {
-
- return '(' + getFastValue(value, '>>>', '0') + ')';
- // Alternatively, we can consider the lengthier
- // return makeInlineCalculation('VALUE >= 0 ? VALUE : ' + Math.pow(2, bits) + ' + VALUE', value, 'tempBigInt');
- // which does not always turn us into a 32-bit *un*signed value
+ return '(' + value + '>>>0)';
}
} else if (bits < 32) {
if (op === 're') {
- return makeInlineCalculation('(VALUE << ' + (32-bits) + ') >> ' + (32-bits), value, 'tempInt');
+ return '((' + value + '<<' + (32-bits) + ')>>' + (32-bits) + ')';
} else {
- return '(' + getFastValue(value, '&', Math.pow(2, bits)-1) + ')';
+ return '(' + value + '&' + (Math.pow(2, bits)-1) + ')';
}
} else { // bits > 32
if (op === 're') {
@@ -2081,7 +2109,7 @@ function processMathop(item) {
if (item.params[i]) {
paramTypes[i] = item.params[i].type || type;
idents[i] = finalizeLLVMParameter(item.params[i]);
- if (!isNumber(idents[i]) && !isNiceIdent(idents[i])) {
+ if (needsQuoting(idents[i])) {
idents[i] = '(' + idents[i] + ')'; // we may have nested expressions. So enforce the order of operations we want
}
} else {
@@ -2520,3 +2548,8 @@ function makePrintChars(s, sep) {
return ret;
}
+function parseAlign(text) { // parse ", align \d+"
+ if (!text) return QUANTUM_SIZE;
+ return parseInt(text.substr(8));
+}
+
diff --git a/src/postamble.js b/src/postamble.js
index 8f585b86..cd892733 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -35,9 +35,10 @@ var preloadStartTime = null;
var calledMain = false;
var calledRun = false;
-dependenciesFulfilled = function() {
+dependenciesFulfilled = function runCaller() {
// If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
if (!calledRun && shouldRunNow) run();
+ if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
}
Module['callMain'] = Module.callMain = function callMain(args) {
diff --git a/src/preamble.js b/src/preamble.js
index 02935f8f..183fd0c8 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -299,11 +299,10 @@ function ccallFunc(func, returnType, argTypes, args) {
function toC(value, type) {
if (type == 'string') {
if (value === null || value === undefined || value === 0) return 0; // null string
- if (!stack) stack = Runtime.stackSave();
- var ret = Runtime.stackAlloc(value.length+1);
- writeStringToMemory(value, ret);
- return ret;
- } else if (type == 'array') {
+ value = intArrayFromString(value);
+ type = 'array';
+ }
+ if (type == 'array') {
if (!stack) stack = Runtime.stackSave();
var ret = Runtime.stackAlloc(value.length);
writeArrayToMemory(value, ret);
@@ -717,7 +716,7 @@ var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}};
// Initialize the runtime's memory
#if USE_TYPED_ARRAYS
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
-assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
+assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
'Cannot fallback to non-typed array case: Code is too specialized');
#if USE_TYPED_ARRAYS == 1
@@ -908,6 +907,17 @@ function writeArrayToMemory(array, buffer) {
}
Module['writeArrayToMemory'] = writeArrayToMemory;
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; i++) {
+#if ASSERTIONS
+ assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff);
+#endif
+ {{{ makeSetValue('buffer', 'i', 'str.charCodeAt(i)', 'i8') }}}
+ }
+ if (!dontAddNull) {{{ makeSetValue('buffer', 'str.length', 0, 'i8') }}}
+}
+Module['writeAsciiToMemory'] = writeAsciiToMemory;
+
{{{ unSign }}}
{{{ reSign }}}
@@ -993,8 +1003,9 @@ function removeRunDependency(id) {
runDependencyWatcher = null;
}
if (dependenciesFulfilled) {
- dependenciesFulfilled();
+ var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
+ callback(); // can add another dependenciesFulfilled
}
}
}
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index afb6ecc8..d79dca5a 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -8,8 +8,6 @@
#include "ministring.h"
-// TODO: move all set to unorderedset
-
template <class T, class U> bool contains(const T& container, const U& contained) {
return container.find(contained) != container.end();
}
diff --git a/src/relooper/emscripten/glue.js b/src/relooper/emscripten/glue.js
index 92c50500..587cf529 100644
--- a/src/relooper/emscripten/glue.js
+++ b/src/relooper/emscripten/glue.js
@@ -13,13 +13,16 @@
RelooperGlue['init'] = function() {
this.r = _rl_new_relooper();
},
+ RelooperGlue['cleanup'] = function() {
+ _rl_delete_relooper(this.r);
+ },
RelooperGlue['addBlock'] = function(text, branchVar) {
assert(this.r);
assert(text.length+1 < TBUFFER_SIZE, 'buffer too small, increase RELOOPER_BUFFER_SIZE');
- writeStringToMemory(text, tbuffer);
+ writeAsciiToMemory(text, tbuffer);
if (branchVar) {
assert(branchVar.length+1 < VBUFFER_SIZE, 'buffer too small, increase RELOOPER_BUFFER_SIZE');
- writeStringToMemory(branchVar, vbuffer);
+ writeAsciiToMemory(branchVar, vbuffer);
}
var b = _rl_new_block(tbuffer, branchVar ? vbuffer : 0);
_rl_relooper_add_block(this.r, b);
@@ -29,14 +32,14 @@
assert(this.r);
if (condition) {
assert(condition.length+1 < TBUFFER_SIZE/2, 'buffer too small, increase RELOOPER_BUFFER_SIZE');
- writeStringToMemory(condition, tbuffer);
+ writeAsciiToMemory(condition, tbuffer);
condition = tbuffer;
} else {
condition = 0; // allow undefined, null, etc. as inputs
}
if (code) {
assert(code.length+1 < TBUFFER_SIZE/2, 'buffer too small, increase RELOOPER_BUFFER_SIZE');
- writeStringToMemory(code, tbuffer + TBUFFER_SIZE/2);
+ writeAsciiToMemory(code, tbuffer + TBUFFER_SIZE/2);
code = tbuffer + TBUFFER_SIZE/2;
} else {
code = 0; // allow undefined, null, etc. as inputs
diff --git a/src/runtime.js b/src/runtime.js
index 6b1afd80..00031fed 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -145,29 +145,30 @@ var Runtime = {
return l + h;
},
- //! Returns the size of a type, as C/C++ would have it (in 32-bit, for now), in bytes.
+ //! Returns the size of a type, as C/C++ would have it (in 32-bit), in bytes.
//! @param type The type, by name.
- getNativeTypeSize: function(type, quantumSize) {
- if (Runtime.QUANTUM_SIZE == 1) return 1;
- var size = {
- '%i1': 1,
- '%i8': 1,
- '%i16': 2,
- '%i32': 4,
- '%i64': 8,
- "%float": 4,
- "%double": 8
- }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc
- if (!size) {
- if (type.charAt(type.length-1) == '*') {
- size = Runtime.QUANTUM_SIZE; // A pointer
- } else if (type[0] == 'i') {
- var bits = parseInt(type.substr(1));
- assert(bits % 8 == 0);
- size = bits/8;
+ getNativeTypeSize: function(type) {
+#if QUANTUM_SIZE == 1
+ return 1;
+#else
+ switch (type) {
+ case 'i1': case 'i8': return 1;
+ case 'i16': return 2;
+ case 'i32': return 4;
+ case 'i64': return 8;
+ case 'float': return 4;
+ case 'double': return 8;
+ default: {
+ if (type[type.length-1] === '*') {
+ return Runtime.QUANTUM_SIZE; // A pointer
+ } else if (type[0] === 'i') {
+ var bits = parseInt(type.substr(1));
+ assert(bits % 8 === 0);
+ return bits/8;
+ }
}
}
- return size;
+#endif
},
//! Returns the size of a structure field, as C/C++ would have it (in 32-bit,
diff --git a/src/settings.js b/src/settings.js
index 8cdf420c..6e2b9e6c 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -202,6 +202,7 @@ var SOCKET_WEBRTC = 0; // Select socket backend, either webrtc or websockets.
var OPENAL_DEBUG = 0; // Print out debugging information from our OpenAL implementation.
+var GL_ASSERTIONS = 0; // Adds extra checks for error situations in the GL library. Can impact performance.
var GL_DEBUG = 0; // Print out all calls into WebGL. As with LIBRARY_DEBUG, you can set a runtime
// option, in this case GL.debug.
var GL_TESTING = 0; // When enabled, sets preserveDrawingBuffer in the context, to allow tests to work (but adds overhead)
@@ -425,6 +426,8 @@ var JS_CHUNK_SIZE = 10240; // Used as a maximum size before breaking up expressi
var EXPORT_NAME = 'Module'; // Global variable to export the module as for environments without a standardized module
// loading system (e.g. the browser and SM shell).
+var COMPILER_ASSERTIONS = 0; // costly (slow) compile-time assertions
+
// Compiler debugging options
var DEBUG_TAGS_SHOWING = [];
// Some useful items:
diff --git a/src/utility.js b/src/utility.js
index 7d122cef..b793106c 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -334,6 +334,17 @@ function jsonCompare(x, y) {
return JSON.stringify(x) == JSON.stringify(y);
}
+function sortedJsonCompare(x, y) {
+ if (x === null || typeof x !== 'object') return x === y;
+ for (var i in x) {
+ if (!sortedJsonCompare(x[i], y[i])) return false;
+ }
+ for (var i in y) {
+ if (!sortedJsonCompare(x[i], y[i])) return false;
+ }
+ return true;
+}
+
function stringifyWithFunctions(obj) {
if (typeof obj === 'function') return obj.toString();
if (obj === null || typeof obj !== 'object') return JSON.stringify(obj);
diff --git a/system/include/libc/assert.h b/system/include/libc/assert.h
index ab745db1..c64d3e52 100644
--- a/system/include/libc/assert.h
+++ b/system/include/libc/assert.h
@@ -12,7 +12,7 @@
extern "C" {
#endif
-void __assert_fail (const char *, const char *, int, const char *);
+_Noreturn void __assert_fail (const char *, const char *, int, const char *);
#ifdef __cplusplus
}
diff --git a/system/lib/libc/musl/readme.txt b/system/lib/libc/musl/readme.txt
index 16c58423..9ca04036 100644
--- a/system/lib/libc/musl/readme.txt
+++ b/system/lib/libc/musl/readme.txt
@@ -6,3 +6,4 @@ Differences from upstream musl include:
* various 64 bit types are 32 bit instead including off_t,
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.
diff --git a/system/lib/libc/musl/src/internal/locale_impl.h b/system/lib/libc/musl/src/internal/locale_impl.h
new file mode 100644
index 00000000..c268124f
--- /dev/null
+++ b/system/lib/libc/musl/src/internal/locale_impl.h
@@ -0,0 +1,5 @@
+#include <locale.h>
+
+struct __locale {
+ int dummy;
+};
diff --git a/system/lib/libc/musl/src/internal/stdio_impl.h b/system/lib/libc/musl/src/internal/stdio_impl.h
new file mode 100644
index 00000000..2083b2fe
--- /dev/null
+++ b/system/lib/libc/musl/src/internal/stdio_impl.h
@@ -0,0 +1,92 @@
+#ifndef _STDIO_IMPL_H
+#define _STDIO_IMPL_H
+
+#include <stdio.h>
+#include "syscall.h"
+#include "libc.h"
+
+#define UNGET 8
+
+#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
+
+#define F_PERM 1
+#define F_NORD 4
+#define F_NOWR 8
+#define F_EOF 16
+#define F_ERR 32
+#define F_SVB 64
+
+struct _IO_FILE {
+ unsigned flags;
+ unsigned char *rpos, *rend;
+ int (*close)(FILE *);
+ unsigned char *wend, *wpos;
+ unsigned char *mustbezero_1;
+ unsigned char *wbase;
+ size_t (*read)(FILE *, unsigned char *, size_t);
+ size_t (*write)(FILE *, const unsigned char *, size_t);
+ off_t (*seek)(FILE *, off_t, int);
+ unsigned char *buf;
+ size_t buf_size;
+ FILE *prev, *next;
+ int fd;
+ int pipe_pid;
+ long lockcount;
+ short dummy3;
+ signed char mode;
+ signed char lbf;
+ int lock;
+ int waiters;
+ void *cookie;
+ off_t off;
+ char *getln_buf;
+ void *mustbezero_2;
+ unsigned char *shend;
+ off_t shlim, shcnt;
+};
+
+size_t __stdio_read(FILE *, unsigned char *, size_t);
+size_t __stdio_write(FILE *, const unsigned char *, size_t);
+size_t __stdout_write(FILE *, const unsigned char *, size_t);
+off_t __stdio_seek(FILE *, off_t, int);
+int __stdio_close(FILE *);
+
+size_t __string_read(FILE *, unsigned char *, size_t);
+
+int __toread(FILE *);
+int __towrite(FILE *);
+
+#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303)
+__attribute__((visibility("protected")))
+#endif
+int __overflow(FILE *, int), __uflow(FILE *);
+
+int __fseeko(FILE *, off_t, int);
+int __fseeko_unlocked(FILE *, off_t, int);
+off_t __ftello(FILE *);
+off_t __ftello_unlocked(FILE *);
+size_t __fwritex(const unsigned char *, size_t, FILE *);
+int __putc_unlocked(int, FILE *);
+
+FILE *__fdopen(int, const char *);
+int __fmodeflags(const char *);
+
+#define OFLLOCK() LOCK(libc.ofl_lock)
+#define OFLUNLOCK() UNLOCK(libc.ofl_lock)
+
+#define feof(f) ((f)->flags & F_EOF)
+#define ferror(f) ((f)->flags & F_ERR)
+
+#define getc_unlocked(f) \
+ ( ((f)->rpos < (f)->rend) ? *(f)->rpos++ : __uflow((f)) )
+
+#define putc_unlocked(c, f) ( ((c)!=(f)->lbf && (f)->wpos<(f)->wend) \
+ ? *(f)->wpos++ = (c) : __overflow((f),(c)) )
+
+/* Caller-allocated FILE * operations */
+FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t);
+int __fclose_ca(FILE *);
+
+#endif
diff --git a/system/lib/libc/musl/src/locale/big5.h b/system/lib/libc/musl/src/locale/big5.h
new file mode 100644
index 00000000..332ea3bc
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/big5.h
@@ -0,0 +1,1085 @@
+12288,65292,12289,12290,65294,8231,65307,65306,65311,65281,65072,8230,8229,
+65104,65105,65106,183,65108,65109,65110,65111,65372,8211,65073,8212,65075,
+9588,65076,65103,65288,65289,65077,65078,65371,65373,65079,65080,12308,12309,
+65081,65082,12304,12305,65083,65084,12298,12299,65085,65086,12296,12297,65087,
+65088,12300,12301,65089,65090,12302,12303,65091,65092,65113,65114,65115,65116,
+65117,65118,8216,8217,8220,8221,12317,12318,8245,8242,65283,65286,65290,8251,
+167,12291,9675,9679,9651,9650,9678,9734,9733,9671,9670,9633,9632,9661,9660,
+12963,8453,175,65507,65343,717,65097,65098,65101,65102,65099,65100,65119,
+65120,65121,65291,65293,215,247,177,8730,65308,65310,65309,8806,8807,8800,
+8734,8786,8801,65122,65123,65124,65125,65126,65374,8745,8746,8869,8736,8735,
+8895,13266,13265,8747,8750,8757,8756,9792,9794,8853,8857,8593,8595,8592,8594,
+8598,8599,8601,8600,8741,8739,65295,65340,8725,65128,65284,65509,12306,65504,
+65505,65285,65312,8451,8457,65129,65130,65131,13269,13212,13213,13214,13262,
+13217,13198,13199,13252,176,20825,20827,20830,20829,20833,20835,21991,29929,
+31950,9601,9602,9603,9604,9605,9606,9607,9608,9615,9614,9613,9612,9611,9610,
+9609,9532,9524,9516,9508,9500,9620,9472,9474,9621,9484,9488,9492,9496,9581,
+9582,9584,9583,9552,9566,9578,9569,9698,9699,9701,9700,9585,9586,9587,65296,
+65297,65298,65299,65300,65301,65302,65303,65304,65305,8544,8545,8546,8547,
+8548,8549,8550,8551,8552,8553,12321,
+12322,12323,12324,12325,12326,12327,12328,12329,21313,21316,21317,65313,65314,
+65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,
+65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,
+65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,
+65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,913,914,915,
+916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,
+936,937,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,
+963,964,965,966,967,968,969,12549,12550,12551,12552,12553,12554,12555,12556,
+12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,
+12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,
+12583,12584,12585,729,713,714,711,715,9216,9217,9218,9219,9220,9221,9222,9223,
+9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,
+9239,9240,9241,9242,9243,9244,9245,9246,9247,9249,8364,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19968,20057,19969,19971,20035,20061,20102,
+20108,20154,20799,20837,20843,20960,20992,20993,21147,21269,21313,21340,21448,
+19977,19979,19976,19978,20011,20024,20961,20037,20040,20063,20062,20110,20129,
+20800,20995,21242,21315,21449,21475,22303,
+22763,22805,22823,22899,23376,23377,23379,23544,23567,23586,23608,23665,24029,
+24037,24049,24050,24051,24062,24178,24318,24331,24339,25165,19985,19984,19981,
+20013,20016,20025,20043,23609,20104,20113,20117,20114,20116,20130,20161,20160,
+20163,20166,20167,20173,20170,20171,20164,20803,20801,20839,20845,20846,20844,
+20887,20982,20998,20999,21000,21243,21246,21247,21270,21305,21320,21319,21317,
+21342,21380,21451,21450,21453,22764,22825,22827,22826,22829,23380,23569,23588,
+23610,23663,24052,24187,24319,24340,24341,24515,25096,25142,25163,25166,25903,
+25991,26007,26020,26041,26085,26352,26376,26408,27424,27490,27513,27595,27604,
+27611,27663,27700,28779,29226,29238,29243,29255,29273,29275,29356,29579,19993,
+19990,19989,19988,19992,20027,20045,20047,20046,20197,20184,20180,20181,20182,
+20183,20195,20196,20185,20190,20805,20804,20873,20874,20908,20985,20986,20984,
+21002,21152,21151,21253,21254,21271,21277,20191,21322,21321,21345,21344,21359,
+21358,21435,21487,21476,21491,21484,21486,21481,21480,21500,21496,21493,21483,
+21478,21482,21490,21489,21488,21477,21485,21499,22235,22234,22806,22830,22833,
+22900,22902,23381,23427,23612,24040,24039,24038,24066,24067,24179,24188,24321,
+24344,24343,24517,25098,25171,25172,25170,25169,26021,26086,26414,26412,26410,
+26411,26413,27491,27597,27665,27664,27704,27713,27712,27710,29359,29572,29577,
+29916,29926,29976,29983,29992,29993,30000,30001,30002,30003,30091,30333,30382,
+30399,30446,30683,30690,30707,31034,31166,31348,31435,19998,19999,20050,20051,
+20073,20121,20132,20134,20133,20223,20233,20249,20234,
+20245,20237,20240,20241,20239,20210,20214,20219,20208,20211,20221,20225,20235,
+20809,20807,20806,20808,20840,20849,20877,20912,21015,21009,21010,21006,21014,
+21155,21256,21281,21280,21360,21361,21513,21519,21516,21514,21520,21505,21515,
+21508,21521,21517,21512,21507,21518,21510,21522,22240,22238,22237,22323,22320,
+22312,22317,22316,22319,22313,22809,22810,22839,22840,22916,22904,22915,22909,
+22905,22914,22913,23383,23384,23431,23432,23429,23433,23546,23574,23673,24030,
+24070,24182,24180,24335,24347,24537,24534,25102,25100,25101,25104,25187,25179,
+25176,25910,26089,26088,26092,26093,26354,26355,26377,26429,26420,26417,26421,
+27425,27492,27515,27670,27741,27735,27737,27743,27744,27728,27733,27745,27739,
+27725,27726,28784,29279,29277,30334,31481,31859,31992,32566,32650,32701,32769,
+32771,32780,32786,32819,32895,32905,32907,32908,33251,33258,33267,33276,33292,
+33307,33311,33390,33394,33406,34411,34880,34892,34915,35199,38433,20018,20136,
+20301,20303,20295,20311,20318,20276,20315,20309,20272,20304,20305,20285,20282,
+20280,20291,20308,20284,20294,20323,20316,20320,20271,20302,20278,20313,20317,
+20296,20314,20812,20811,20813,20853,20918,20919,21029,21028,21033,21034,21032,
+21163,21161,21162,21164,21283,21363,21365,21533,21549,21534,21566,21542,21582,
+21543,21574,21571,21555,21576,21570,21531,21545,21578,21561,21563,21560,21550,
+21557,21558,21536,21564,21568,21553,21547,21535,21548,22250,22256,22244,22251,
+22346,22353,22336,22349,22343,22350,22334,22352,22351,22331,22767,22846,22941,
+22930,22952,22942,22947,22937,22934,22925,22948,22931,
+22922,22949,23389,23388,23386,23387,23436,23435,23439,23596,23616,23617,23615,
+23614,23696,23697,23700,23692,24043,24076,24207,24199,24202,24311,24324,24351,
+24420,24418,24439,24441,24536,24524,24535,24525,24561,24555,24568,24554,25106,
+25105,25220,25239,25238,25216,25206,25225,25197,25226,25212,25214,25209,25203,
+25234,25199,25240,25198,25237,25235,25233,25222,25913,25915,25912,26097,26356,
+26463,26446,26447,26448,26449,26460,26454,26462,26441,26438,26464,26451,26455,
+27493,27599,27714,27742,27801,27777,27784,27785,27781,27803,27754,27770,27792,
+27760,27788,27752,27798,27794,27773,27779,27762,27774,27764,27782,27766,27789,
+27796,27800,27778,28790,28796,28797,28792,29282,29281,29280,29380,29378,29590,
+29996,29995,30007,30008,30338,30447,30691,31169,31168,31167,31350,31995,32597,
+32918,32915,32925,32920,32923,32922,32946,33391,33426,33419,33421,35211,35282,
+35328,35895,35910,35925,35997,36196,36208,36275,36523,36554,36763,36784,36802,
+36806,36805,36804,24033,37009,37026,37034,37030,37027,37193,37318,37324,38450,
+38446,38449,38442,38444,20006,20054,20083,20107,20123,20126,20139,20140,20335,
+20381,20365,20339,20351,20332,20379,20363,20358,20355,20336,20341,20360,20329,
+20347,20374,20350,20367,20369,20346,20820,20818,20821,20841,20855,20854,20856,
+20925,20989,21051,21048,21047,21050,21040,21038,21046,21057,21182,21179,21330,
+21332,21331,21329,21350,21367,21368,21369,21462,21460,21463,21619,21621,21654,
+21624,21653,21632,21627,21623,21636,21650,21638,21628,21648,21617,21622,21644,
+21658,21602,21608,21643,21629,21646,22266,22403,22391,
+22378,22377,22369,22374,22372,22396,22812,22857,22855,22856,22852,22868,22974,
+22971,22996,22969,22958,22993,22982,22992,22989,22987,22995,22986,22959,22963,
+22994,22981,23391,23396,23395,23447,23450,23448,23452,23449,23451,23578,23624,
+23621,23622,23735,23713,23736,23721,23723,23729,23731,24088,24090,24086,24085,
+24091,24081,24184,24218,24215,24220,24213,24214,24310,24358,24359,24361,24448,
+24449,24447,24444,24541,24544,24573,24565,24575,24591,24596,24623,24629,24598,
+24618,24597,24609,24615,24617,24619,24603,25110,25109,25151,25150,25152,25215,
+25289,25292,25284,25279,25282,25273,25298,25307,25259,25299,25300,25291,25288,
+25256,25277,25276,25296,25305,25287,25293,25269,25306,25265,25304,25302,25303,
+25286,25260,25294,25918,26023,26044,26106,26132,26131,26124,26118,26114,26126,
+26112,26127,26133,26122,26119,26381,26379,26477,26507,26517,26481,26524,26483,
+26487,26503,26525,26519,26479,26480,26495,26505,26494,26512,26485,26522,26515,
+26492,26474,26482,27427,27494,27495,27519,27667,27675,27875,27880,27891,27825,
+27852,27877,27827,27837,27838,27836,27874,27819,27861,27859,27832,27844,27833,
+27841,27822,27863,27845,27889,27839,27835,27873,27867,27850,27820,27887,27868,
+27862,27872,28821,28814,28818,28810,28825,29228,29229,29240,29256,29287,29289,
+29376,29390,29401,29399,29392,29609,29608,29599,29611,29605,30013,30109,30105,
+30106,30340,30402,30450,30452,30693,30717,31038,31040,31041,31177,31176,31354,
+31353,31482,31998,32596,32652,32651,32773,32954,32933,32930,32945,32929,32939,
+32937,32948,32938,32943,33253,33278,33293,33459,33437,
+33433,33453,33469,33439,33465,33457,33452,33445,33455,33464,33443,33456,33470,
+33463,34382,34417,21021,34920,36555,36814,36820,36817,37045,37048,37041,37046,
+37319,37329,38263,38272,38428,38464,38463,38459,38468,38466,38585,38632,38738,
+38750,20127,20141,20142,20449,20405,20399,20415,20448,20433,20431,20445,20419,
+20406,20440,20447,20426,20439,20398,20432,20420,20418,20442,20430,20446,20407,
+20823,20882,20881,20896,21070,21059,21066,21069,21068,21067,21063,21191,21193,
+21187,21185,21261,21335,21371,21402,21467,21676,21696,21672,21710,21705,21688,
+21670,21683,21703,21698,21693,21674,21697,21700,21704,21679,21675,21681,21691,
+21673,21671,21695,22271,22402,22411,22432,22435,22434,22478,22446,22419,22869,
+22865,22863,22862,22864,23004,23000,23039,23011,23016,23043,23013,23018,23002,
+23014,23041,23035,23401,23459,23462,23460,23458,23461,23553,23630,23631,23629,
+23627,23769,23762,24055,24093,24101,24095,24189,24224,24230,24314,24328,24365,
+24421,24456,24453,24458,24459,24455,24460,24457,24594,24605,24608,24613,24590,
+24616,24653,24688,24680,24674,24646,24643,24684,24683,24682,24676,25153,25308,
+25366,25353,25340,25325,25345,25326,25341,25351,25329,25335,25327,25324,25342,
+25332,25361,25346,25919,25925,26027,26045,26082,26149,26157,26144,26151,26159,
+26143,26152,26161,26148,26359,26623,26579,26609,26580,26576,26604,26550,26543,
+26613,26601,26607,26564,26577,26548,26586,26597,26552,26575,26590,26611,26544,
+26585,26594,26589,26578,27498,27523,27526,27573,27602,27607,27679,27849,27915,
+27954,27946,27969,27941,27916,27953,27934,27927,27963,
+27965,27966,27958,27931,27893,27961,27943,27960,27945,27950,27957,27918,27947,
+28843,28858,28851,28844,28847,28845,28856,28846,28836,29232,29298,29295,29300,
+29417,29408,29409,29623,29642,29627,29618,29645,29632,29619,29978,29997,30031,
+30028,30030,30027,30123,30116,30117,30114,30115,30328,30342,30343,30344,30408,
+30406,30403,30405,30465,30457,30456,30473,30475,30462,30460,30471,30684,30722,
+30740,30732,30733,31046,31049,31048,31047,31161,31162,31185,31186,31179,31359,
+31361,31487,31485,31869,32002,32005,32000,32009,32007,32004,32006,32568,32654,
+32703,32772,32784,32781,32785,32822,32982,32997,32986,32963,32964,32972,32993,
+32987,32974,32990,32996,32989,33268,33314,33511,33539,33541,33507,33499,33510,
+33540,33509,33538,33545,33490,33495,33521,33537,33500,33492,33489,33502,33491,
+33503,33519,33542,34384,34425,34427,34426,34893,34923,35201,35284,35336,35330,
+35331,35998,36000,36212,36211,36276,36557,36556,36848,36838,36834,36842,36837,
+36845,36843,36836,36840,37066,37070,37057,37059,37195,37194,37325,38274,38480,
+38475,38476,38477,38754,38761,38859,38893,38899,38913,39080,39131,39135,39318,
+39321,20056,20147,20492,20493,20515,20463,20518,20517,20472,20521,20502,20486,
+20540,20511,20506,20498,20497,20474,20480,20500,20520,20465,20513,20491,20505,
+20504,20467,20462,20525,20522,20478,20523,20489,20860,20900,20901,20898,20941,
+20940,20934,20939,21078,21084,21076,21083,21085,21290,21375,21407,21405,21471,
+21736,21776,21761,21815,21756,21733,21746,21766,21754,21780,21737,21741,21729,
+21769,21742,21738,21734,21799,21767,21757,21775,22275,
+22276,22466,22484,22475,22467,22537,22799,22871,22872,22874,23057,23064,23068,
+23071,23067,23059,23020,23072,23075,23081,23077,23052,23049,23403,23640,23472,
+23475,23478,23476,23470,23477,23481,23480,23556,23633,23637,23632,23789,23805,
+23803,23786,23784,23792,23798,23809,23796,24046,24109,24107,24235,24237,24231,
+24369,24466,24465,24464,24665,24675,24677,24656,24661,24685,24681,24687,24708,
+24735,24730,24717,24724,24716,24709,24726,25159,25331,25352,25343,25422,25406,
+25391,25429,25410,25414,25423,25417,25402,25424,25405,25386,25387,25384,25421,
+25420,25928,25929,26009,26049,26053,26178,26185,26191,26179,26194,26188,26181,
+26177,26360,26388,26389,26391,26657,26680,26696,26694,26707,26681,26690,26708,
+26665,26803,26647,26700,26705,26685,26612,26704,26688,26684,26691,26666,26693,
+26643,26648,26689,27530,27529,27575,27683,27687,27688,27686,27684,27888,28010,
+28053,28040,28039,28006,28024,28023,27993,28051,28012,28041,28014,27994,28020,
+28009,28044,28042,28025,28037,28005,28052,28874,28888,28900,28889,28872,28879,
+29241,29305,29436,29433,29437,29432,29431,29574,29677,29705,29678,29664,29674,
+29662,30036,30045,30044,30042,30041,30142,30149,30151,30130,30131,30141,30140,
+30137,30146,30136,30347,30384,30410,30413,30414,30505,30495,30496,30504,30697,
+30768,30759,30776,30749,30772,30775,30757,30765,30752,30751,30770,31061,31056,
+31072,31071,31062,31070,31069,31063,31066,31204,31203,31207,31199,31206,31209,
+31192,31364,31368,31449,31494,31505,31881,32033,32023,32011,32010,32032,32034,
+32020,32016,32021,32026,32028,32013,32025,32027,32570,
+32607,32660,32709,32705,32774,32792,32789,32793,32791,32829,32831,33009,33026,
+33008,33029,33005,33012,33030,33016,33011,33032,33021,33034,33020,33007,33261,
+33260,33280,33296,33322,33323,33320,33324,33467,33579,33618,33620,33610,33592,
+33616,33609,33589,33588,33615,33586,33593,33590,33559,33600,33585,33576,33603,
+34388,34442,34474,34451,34468,34473,34444,34467,34460,34928,34935,34945,34946,
+34941,34937,35352,35344,35342,35340,35349,35338,35351,35347,35350,35343,35345,
+35912,35962,35961,36001,36002,36215,36524,36562,36564,36559,36785,36865,36870,
+36855,36864,36858,36852,36867,36861,36869,36856,37013,37089,37085,37090,37202,
+37197,37196,37336,37341,37335,37340,37337,38275,38498,38499,38497,38491,38493,
+38500,38488,38494,38587,39138,39340,39592,39640,39717,39730,39740,20094,20602,
+20605,20572,20551,20547,20556,20570,20553,20581,20598,20558,20565,20597,20596,
+20599,20559,20495,20591,20589,20828,20885,20976,21098,21103,21202,21209,21208,
+21205,21264,21263,21273,21311,21312,21310,21443,26364,21830,21866,21862,21828,
+21854,21857,21827,21834,21809,21846,21839,21845,21807,21860,21816,21806,21852,
+21804,21859,21811,21825,21847,22280,22283,22281,22495,22533,22538,22534,22496,
+22500,22522,22530,22581,22519,22521,22816,22882,23094,23105,23113,23142,23146,
+23104,23100,23138,23130,23110,23114,23408,23495,23493,23492,23490,23487,23494,
+23561,23560,23559,23648,23644,23645,23815,23814,23822,23835,23830,23842,23825,
+23849,23828,23833,23844,23847,23831,24034,24120,24118,24115,24119,24247,24248,
+24246,24245,24254,24373,24375,24407,24428,24425,24427,
+24471,24473,24478,24472,24481,24480,24476,24703,24739,24713,24736,24744,24779,
+24756,24806,24765,24773,24763,24757,24796,24764,24792,24789,24774,24799,24760,
+24794,24775,25114,25115,25160,25504,25511,25458,25494,25506,25509,25463,25447,
+25496,25514,25457,25513,25481,25475,25499,25451,25512,25476,25480,25497,25505,
+25516,25490,25487,25472,25467,25449,25448,25466,25949,25942,25937,25945,25943,
+21855,25935,25944,25941,25940,26012,26011,26028,26063,26059,26060,26062,26205,
+26202,26212,26216,26214,26206,26361,21207,26395,26753,26799,26786,26771,26805,
+26751,26742,26801,26791,26775,26800,26755,26820,26797,26758,26757,26772,26781,
+26792,26783,26785,26754,27442,27578,27627,27628,27691,28046,28092,28147,28121,
+28082,28129,28108,28132,28155,28154,28165,28103,28107,28079,28113,28078,28126,
+28153,28088,28151,28149,28101,28114,28186,28085,28122,28139,28120,28138,28145,
+28142,28136,28102,28100,28074,28140,28095,28134,28921,28937,28938,28925,28911,
+29245,29309,29313,29468,29467,29462,29459,29465,29575,29701,29706,29699,29702,
+29694,29709,29920,29942,29943,29980,29986,30053,30054,30050,30064,30095,30164,
+30165,30133,30154,30157,30350,30420,30418,30427,30519,30526,30524,30518,30520,
+30522,30827,30787,30798,31077,31080,31085,31227,31378,31381,31520,31528,31515,
+31532,31526,31513,31518,31534,31890,31895,31893,32070,32067,32113,32046,32057,
+32060,32064,32048,32051,32068,32047,32066,32050,32049,32573,32670,32666,32716,
+32718,32722,32796,32842,32838,33071,33046,33059,33067,33065,33072,33060,33282,
+33333,33335,33334,33337,33678,33694,33688,33656,33698,
+33686,33725,33707,33682,33674,33683,33673,33696,33655,33659,33660,33670,33703,
+34389,24426,34503,34496,34486,34500,34485,34502,34507,34481,34479,34505,34899,
+34974,34952,34987,34962,34966,34957,34955,35219,35215,35370,35357,35363,35365,
+35377,35373,35359,35355,35362,35913,35930,36009,36012,36011,36008,36010,36007,
+36199,36198,36286,36282,36571,36575,36889,36877,36890,36887,36899,36895,36893,
+36880,36885,36894,36896,36879,36898,36886,36891,36884,37096,37101,37117,37207,
+37326,37365,37350,37347,37351,37357,37353,38281,38506,38517,38515,38520,38512,
+38516,38518,38519,38508,38592,38634,38633,31456,31455,38914,38915,39770,40165,
+40565,40575,40613,40635,20642,20621,20613,20633,20625,20608,20630,20632,20634,
+26368,20977,21106,21108,21109,21097,21214,21213,21211,21338,21413,21883,21888,
+21927,21884,21898,21917,21912,21890,21916,21930,21908,21895,21899,21891,21939,
+21934,21919,21822,21938,21914,21947,21932,21937,21886,21897,21931,21913,22285,
+22575,22570,22580,22564,22576,22577,22561,22557,22560,22777,22778,22880,23159,
+23194,23167,23186,23195,23207,23411,23409,23506,23500,23507,23504,23562,23563,
+23601,23884,23888,23860,23879,24061,24133,24125,24128,24131,24190,24266,24257,
+24258,24260,24380,24429,24489,24490,24488,24785,24801,24754,24758,24800,24860,
+24867,24826,24853,24816,24827,24820,24936,24817,24846,24822,24841,24832,24850,
+25119,25161,25507,25484,25551,25536,25577,25545,25542,25549,25554,25571,25552,
+25569,25558,25581,25582,25462,25588,25578,25563,25682,25562,25593,25950,25958,
+25954,25955,26001,26000,26031,26222,26224,26228,26230,
+26223,26257,26234,26238,26231,26366,26367,26399,26397,26874,26837,26848,26840,
+26839,26885,26847,26869,26862,26855,26873,26834,26866,26851,26827,26829,26893,
+26898,26894,26825,26842,26990,26875,27454,27450,27453,27544,27542,27580,27631,
+27694,27695,27692,28207,28216,28244,28193,28210,28263,28234,28192,28197,28195,
+28187,28251,28248,28196,28246,28270,28205,28198,28271,28212,28237,28218,28204,
+28227,28189,28222,28363,28297,28185,28238,28259,28228,28274,28265,28255,28953,
+28954,28966,28976,28961,28982,29038,28956,29260,29316,29312,29494,29477,29492,
+29481,29754,29738,29747,29730,29733,29749,29750,29748,29743,29723,29734,29736,
+29989,29990,30059,30058,30178,30171,30179,30169,30168,30174,30176,30331,30332,
+30358,30355,30388,30428,30543,30701,30813,30828,30831,31245,31240,31243,31237,
+31232,31384,31383,31382,31461,31459,31561,31574,31558,31568,31570,31572,31565,
+31563,31567,31569,31903,31909,32094,32080,32104,32085,32043,32110,32114,32097,
+32102,32098,32112,32115,21892,32724,32725,32779,32850,32901,33109,33108,33099,
+33105,33102,33081,33094,33086,33100,33107,33140,33298,33308,33769,33795,33784,
+33805,33760,33733,33803,33729,33775,33777,33780,33879,33802,33776,33804,33740,
+33789,33778,33738,33848,33806,33796,33756,33799,33748,33759,34395,34527,34521,
+34541,34516,34523,34532,34512,34526,34903,35009,35010,34993,35203,35222,35387,
+35424,35413,35422,35388,35393,35412,35419,35408,35398,35380,35386,35382,35414,
+35937,35970,36015,36028,36019,36029,36033,36027,36032,36020,36023,36022,36031,
+36024,36234,36229,36225,36302,36317,36299,36314,36305,
+36300,36315,36294,36603,36600,36604,36764,36910,36917,36913,36920,36914,36918,
+37122,37109,37129,37118,37219,37221,37327,37396,37397,37411,37385,37406,37389,
+37392,37383,37393,38292,38287,38283,38289,38291,38290,38286,38538,38542,38539,
+38525,38533,38534,38541,38514,38532,38593,38597,38596,38598,38599,38639,38642,
+38860,38917,38918,38920,39143,39146,39151,39145,39154,39149,39342,39341,40643,
+40653,40657,20098,20653,20661,20658,20659,20677,20670,20652,20663,20667,20655,
+20679,21119,21111,21117,21215,21222,21220,21218,21219,21295,21983,21992,21971,
+21990,21966,21980,21959,21969,21987,21988,21999,21978,21985,21957,21958,21989,
+21961,22290,22291,22622,22609,22616,22615,22618,22612,22635,22604,22637,22602,
+22626,22610,22603,22887,23233,23241,23244,23230,23229,23228,23219,23234,23218,
+23913,23919,24140,24185,24265,24264,24338,24409,24492,24494,24858,24847,24904,
+24863,24819,24859,24825,24833,24840,24910,24908,24900,24909,24894,24884,24871,
+24845,24838,24887,25121,25122,25619,25662,25630,25642,25645,25661,25644,25615,
+25628,25620,25613,25654,25622,25623,25606,25964,26015,26032,26263,26249,26247,
+26248,26262,26244,26264,26253,26371,27028,26989,26970,26999,26976,26964,26997,
+26928,27010,26954,26984,26987,26974,26963,27001,27014,26973,26979,26971,27463,
+27506,27584,27583,27603,27645,28322,28335,28371,28342,28354,28304,28317,28359,
+28357,28325,28312,28348,28346,28331,28369,28310,28316,28356,28372,28330,28327,
+28340,29006,29017,29033,29028,29001,29031,29020,29036,29030,29004,29029,29022,
+28998,29032,29014,29242,29266,29495,29509,29503,29502,
+29807,29786,29781,29791,29790,29761,29759,29785,29787,29788,30070,30072,30208,
+30192,30209,30194,30193,30202,30207,30196,30195,30430,30431,30555,30571,30566,
+30558,30563,30585,30570,30572,30556,30565,30568,30562,30702,30862,30896,30871,
+30872,30860,30857,30844,30865,30867,30847,31098,31103,31105,33836,31165,31260,
+31258,31264,31252,31263,31262,31391,31392,31607,31680,31584,31598,31591,31921,
+31923,31925,32147,32121,32145,32129,32143,32091,32622,32617,32618,32626,32681,
+32680,32676,32854,32856,32902,32900,33137,33136,33144,33125,33134,33139,33131,
+33145,33146,33126,33285,33351,33922,33911,33853,33841,33909,33894,33899,33865,
+33900,33883,33852,33845,33889,33891,33897,33901,33862,34398,34396,34399,34553,
+34579,34568,34567,34560,34558,34555,34562,34563,34566,34570,34905,35039,35028,
+35033,35036,35032,35037,35041,35018,35029,35026,35228,35299,35435,35442,35443,
+35430,35433,35440,35463,35452,35427,35488,35441,35461,35437,35426,35438,35436,
+35449,35451,35390,35432,35938,35978,35977,36042,36039,36040,36036,36018,36035,
+36034,36037,36321,36319,36328,36335,36339,36346,36330,36324,36326,36530,36611,
+36617,36606,36618,36767,36786,36939,36938,36947,36930,36948,36924,36949,36944,
+36935,36943,36942,36941,36945,36926,36929,37138,37143,37228,37226,37225,37321,
+37431,37463,37432,37437,37440,37438,37467,37451,37476,37457,37428,37449,37453,
+37445,37433,37439,37466,38296,38552,38548,38549,38605,38603,38601,38602,38647,
+38651,38649,38646,38742,38772,38774,38928,38929,38931,38922,38930,38924,39164,
+39156,39165,39166,39347,39345,39348,39649,40169,40578,
+40718,40723,40736,20711,20718,20709,20694,20717,20698,20693,20687,20689,20721,
+20686,20713,20834,20979,21123,21122,21297,21421,22014,22016,22043,22039,22013,
+22036,22022,22025,22029,22030,22007,22038,22047,22024,22032,22006,22296,22294,
+22645,22654,22659,22675,22666,22649,22661,22653,22781,22821,22818,22820,22890,
+22889,23265,23270,23273,23255,23254,23256,23267,23413,23518,23527,23521,23525,
+23526,23528,23522,23524,23519,23565,23650,23940,23943,24155,24163,24149,24151,
+24148,24275,24278,24330,24390,24432,24505,24903,24895,24907,24951,24930,24931,
+24927,24922,24920,24949,25130,25735,25688,25684,25764,25720,25695,25722,25681,
+25703,25652,25709,25723,25970,26017,26071,26070,26274,26280,26269,27036,27048,
+27029,27073,27054,27091,27083,27035,27063,27067,27051,27060,27088,27085,27053,
+27084,27046,27075,27043,27465,27468,27699,28467,28436,28414,28435,28404,28457,
+28478,28448,28460,28431,28418,28450,28415,28399,28422,28465,28472,28466,28451,
+28437,28459,28463,28552,28458,28396,28417,28402,28364,28407,29076,29081,29053,
+29066,29060,29074,29246,29330,29334,29508,29520,29796,29795,29802,29808,29805,
+29956,30097,30247,30221,30219,30217,30227,30433,30435,30596,30589,30591,30561,
+30913,30879,30887,30899,30889,30883,31118,31119,31117,31278,31281,31402,31401,
+31469,31471,31649,31637,31627,31605,31639,31645,31636,31631,31672,31623,31620,
+31929,31933,31934,32187,32176,32156,32189,32190,32160,32202,32180,32178,32177,
+32186,32162,32191,32181,32184,32173,32210,32199,32172,32624,32736,32737,32735,
+32862,32858,32903,33104,33152,33167,33160,33162,33151,
+33154,33255,33274,33287,33300,33310,33355,33993,33983,33990,33988,33945,33950,
+33970,33948,33995,33976,33984,34003,33936,33980,34001,33994,34623,34588,34619,
+34594,34597,34612,34584,34645,34615,34601,35059,35074,35060,35065,35064,35069,
+35048,35098,35055,35494,35468,35486,35491,35469,35489,35475,35492,35498,35493,
+35496,35480,35473,35482,35495,35946,35981,35980,36051,36049,36050,36203,36249,
+36245,36348,36628,36626,36629,36627,36771,36960,36952,36956,36963,36953,36958,
+36962,36957,36955,37145,37144,37150,37237,37240,37239,37236,37496,37504,37509,
+37528,37526,37499,37523,37532,37544,37500,37521,38305,38312,38313,38307,38309,
+38308,38553,38556,38555,38604,38610,38656,38780,38789,38902,38935,38936,39087,
+39089,39171,39173,39180,39177,39361,39599,39600,39654,39745,39746,40180,40182,
+40179,40636,40763,40778,20740,20736,20731,20725,20729,20738,20744,20745,20741,
+20956,21127,21128,21129,21133,21130,21232,21426,22062,22075,22073,22066,22079,
+22068,22057,22099,22094,22103,22132,22070,22063,22064,22656,22687,22686,22707,
+22684,22702,22697,22694,22893,23305,23291,23307,23285,23308,23304,23534,23532,
+23529,23531,23652,23653,23965,23956,24162,24159,24161,24290,24282,24287,24285,
+24291,24288,24392,24433,24503,24501,24950,24935,24942,24925,24917,24962,24956,
+24944,24939,24958,24999,24976,25003,24974,25004,24986,24996,24980,25006,25134,
+25705,25711,25721,25758,25778,25736,25744,25776,25765,25747,25749,25769,25746,
+25774,25773,25771,25754,25772,25753,25762,25779,25973,25975,25976,26286,26283,
+26292,26289,27171,27167,27112,27137,27166,27161,27133,
+27169,27155,27146,27123,27138,27141,27117,27153,27472,27470,27556,27589,27590,
+28479,28540,28548,28497,28518,28500,28550,28525,28507,28536,28526,28558,28538,
+28528,28516,28567,28504,28373,28527,28512,28511,29087,29100,29105,29096,29270,
+29339,29518,29527,29801,29835,29827,29822,29824,30079,30240,30249,30239,30244,
+30246,30241,30242,30362,30394,30436,30606,30599,30604,30609,30603,30923,30917,
+30906,30922,30910,30933,30908,30928,31295,31292,31296,31293,31287,31291,31407,
+31406,31661,31665,31684,31668,31686,31687,31681,31648,31692,31946,32224,32244,
+32239,32251,32216,32236,32221,32232,32227,32218,32222,32233,32158,32217,32242,
+32249,32629,32631,32687,32745,32806,33179,33180,33181,33184,33178,33176,34071,
+34109,34074,34030,34092,34093,34067,34065,34083,34081,34068,34028,34085,34047,
+34054,34690,34676,34678,34656,34662,34680,34664,34649,34647,34636,34643,34907,
+34909,35088,35079,35090,35091,35093,35082,35516,35538,35527,35524,35477,35531,
+35576,35506,35529,35522,35519,35504,35542,35533,35510,35513,35547,35916,35918,
+35948,36064,36062,36070,36068,36076,36077,36066,36067,36060,36074,36065,36205,
+36255,36259,36395,36368,36381,36386,36367,36393,36383,36385,36382,36538,36637,
+36635,36639,36649,36646,36650,36636,36638,36645,36969,36974,36968,36973,36983,
+37168,37165,37159,37169,37255,37257,37259,37251,37573,37563,37559,37610,37548,
+37604,37569,37555,37564,37586,37575,37616,37554,38317,38321,38660,38662,38663,
+38665,38752,38797,38795,38799,38945,38955,38940,39091,39178,39187,39186,39192,
+39389,39376,39391,39387,39377,39381,39378,39385,39607,
+39662,39663,39719,39749,39748,39799,39791,40198,40201,40195,40617,40638,40654,
+22696,40786,20754,20760,20756,20752,20757,20864,20906,20957,21137,21139,21235,
+22105,22123,22137,22121,22116,22136,22122,22120,22117,22129,22127,22124,22114,
+22134,22721,22718,22727,22725,22894,23325,23348,23416,23536,23566,24394,25010,
+24977,25001,24970,25037,25014,25022,25034,25032,25136,25797,25793,25803,25787,
+25788,25818,25796,25799,25794,25805,25791,25810,25812,25790,25972,26310,26313,
+26297,26308,26311,26296,27197,27192,27194,27225,27243,27224,27193,27204,27234,
+27233,27211,27207,27189,27231,27208,27481,27511,27653,28610,28593,28577,28611,
+28580,28609,28583,28595,28608,28601,28598,28582,28576,28596,29118,29129,29136,
+29138,29128,29141,29113,29134,29145,29148,29123,29124,29544,29852,29859,29848,
+29855,29854,29922,29964,29965,30260,30264,30266,30439,30437,30624,30622,30623,
+30629,30952,30938,30956,30951,31142,31309,31310,31302,31308,31307,31418,31705,
+31761,31689,31716,31707,31713,31721,31718,31957,31958,32266,32273,32264,32283,
+32291,32286,32285,32265,32272,32633,32690,32752,32753,32750,32808,33203,33193,
+33192,33275,33288,33368,33369,34122,34137,34120,34152,34153,34115,34121,34157,
+34154,34142,34691,34719,34718,34722,34701,34913,35114,35122,35109,35115,35105,
+35242,35238,35558,35578,35563,35569,35584,35548,35559,35566,35582,35585,35586,
+35575,35565,35571,35574,35580,35947,35949,35987,36084,36420,36401,36404,36418,
+36409,36405,36667,36655,36664,36659,36776,36774,36981,36980,36984,36978,36988,
+36986,37172,37266,37664,37686,37624,37683,37679,37666,
+37628,37675,37636,37658,37648,37670,37665,37653,37678,37657,38331,38567,38568,
+38570,38613,38670,38673,38678,38669,38675,38671,38747,38748,38758,38808,38960,
+38968,38971,38967,38957,38969,38948,39184,39208,39198,39195,39201,39194,39405,
+39394,39409,39608,39612,39675,39661,39720,39825,40213,40227,40230,40232,40210,
+40219,40664,40660,40845,40860,20778,20767,20769,20786,21237,22158,22144,22160,
+22149,22151,22159,22741,22739,22737,22734,23344,23338,23332,23418,23607,23656,
+23996,23994,23997,23992,24171,24396,24509,25033,25026,25031,25062,25035,25138,
+25140,25806,25802,25816,25824,25840,25830,25836,25841,25826,25837,25986,25987,
+26329,26326,27264,27284,27268,27298,27292,27355,27299,27262,27287,27280,27296,
+27484,27566,27610,27656,28632,28657,28639,28640,28635,28644,28651,28655,28544,
+28652,28641,28649,28629,28654,28656,29159,29151,29166,29158,29157,29165,29164,
+29172,29152,29237,29254,29552,29554,29865,29872,29862,29864,30278,30274,30284,
+30442,30643,30634,30640,30636,30631,30637,30703,30967,30970,30964,30959,30977,
+31143,31146,31319,31423,31751,31757,31742,31735,31756,31712,31968,31964,31966,
+31970,31967,31961,31965,32302,32318,32326,32311,32306,32323,32299,32317,32305,
+32325,32321,32308,32313,32328,32309,32319,32303,32580,32755,32764,32881,32882,
+32880,32879,32883,33222,33219,33210,33218,33216,33215,33213,33225,33214,33256,
+33289,33393,34218,34180,34174,34204,34193,34196,34223,34203,34183,34216,34186,
+34407,34752,34769,34739,34770,34758,34731,34747,34746,34760,34763,35131,35126,
+35140,35128,35133,35244,35598,35607,35609,35611,35594,
+35616,35613,35588,35600,35905,35903,35955,36090,36093,36092,36088,36091,36264,
+36425,36427,36424,36426,36676,36670,36674,36677,36671,36991,36989,36996,36993,
+36994,36992,37177,37283,37278,37276,37709,37762,37672,37749,37706,37733,37707,
+37656,37758,37740,37723,37744,37722,37716,38346,38347,38348,38344,38342,38577,
+38584,38614,38684,38686,38816,38867,38982,39094,39221,39425,39423,39854,39851,
+39850,39853,40251,40255,40587,40655,40670,40668,40669,40667,40766,40779,21474,
+22165,22190,22745,22744,23352,24413,25059,25139,25844,25842,25854,25862,25850,
+25851,25847,26039,26332,26406,27315,27308,27331,27323,27320,27330,27310,27311,
+27487,27512,27567,28681,28683,28670,28678,28666,28689,28687,29179,29180,29182,
+29176,29559,29557,29863,29887,29973,30294,30296,30290,30653,30655,30651,30652,
+30990,31150,31329,31330,31328,31428,31429,31787,31783,31786,31774,31779,31777,
+31975,32340,32341,32350,32346,32353,32338,32345,32584,32761,32763,32887,32886,
+33229,33231,33290,34255,34217,34253,34256,34249,34224,34234,34233,34214,34799,
+34796,34802,34784,35206,35250,35316,35624,35641,35628,35627,35920,36101,36441,
+36451,36454,36452,36447,36437,36544,36681,36685,36999,36995,37000,37291,37292,
+37328,37780,37770,37782,37794,37811,37806,37804,37808,37784,37786,37783,38356,
+38358,38352,38357,38626,38620,38617,38619,38622,38692,38819,38822,38829,38905,
+38989,38991,38988,38990,38995,39098,39230,39231,39229,39214,39333,39438,39617,
+39683,39686,39759,39758,39757,39882,39881,39933,39880,39872,40273,40285,40288,
+40672,40725,40748,20787,22181,22750,22751,22754,23541,
+40848,24300,25074,25079,25078,25077,25856,25871,26336,26333,27365,27357,27354,
+27347,28699,28703,28712,28698,28701,28693,28696,29190,29197,29272,29346,29560,
+29562,29885,29898,29923,30087,30086,30303,30305,30663,31001,31153,31339,31337,
+31806,31807,31800,31805,31799,31808,32363,32365,32377,32361,32362,32645,32371,
+32694,32697,32696,33240,34281,34269,34282,34261,34276,34277,34295,34811,34821,
+34829,34809,34814,35168,35167,35158,35166,35649,35676,35672,35657,35674,35662,
+35663,35654,35673,36104,36106,36476,36466,36487,36470,36460,36474,36468,36692,
+36686,36781,37002,37003,37297,37294,37857,37841,37855,37827,37832,37852,37853,
+37846,37858,37837,37848,37860,37847,37864,38364,38580,38627,38698,38695,38753,
+38876,38907,39006,39000,39003,39100,39237,39241,39446,39449,39693,39912,39911,
+39894,39899,40329,40289,40306,40298,40300,40594,40599,40595,40628,21240,22184,
+22199,22198,22196,22204,22756,23360,23363,23421,23542,24009,25080,25082,25880,
+25876,25881,26342,26407,27372,28734,28720,28722,29200,29563,29903,30306,30309,
+31014,31018,31020,31019,31431,31478,31820,31811,31821,31983,31984,36782,32381,
+32380,32386,32588,32768,33242,33382,34299,34297,34321,34298,34310,34315,34311,
+34314,34836,34837,35172,35258,35320,35696,35692,35686,35695,35679,35691,36111,
+36109,36489,36481,36485,36482,37300,37323,37912,37891,37885,38369,38704,39108,
+39250,39249,39336,39467,39472,39479,39477,39955,39949,40569,40629,40680,40751,
+40799,40803,40801,20791,20792,22209,22208,22210,22804,23660,24013,25084,25086,
+25885,25884,26005,26345,27387,27396,27386,27570,28748,
+29211,29351,29910,29908,30313,30675,31824,32399,32396,32700,34327,34349,34330,
+34851,34850,34849,34847,35178,35180,35261,35700,35703,35709,36115,36490,36493,
+36491,36703,36783,37306,37934,37939,37941,37946,37944,37938,37931,38370,38712,
+38713,38706,38911,39015,39013,39255,39493,39491,39488,39486,39631,39764,39761,
+39981,39973,40367,40372,40386,40376,40605,40687,40729,40796,40806,40807,20796,
+20795,22216,22218,22217,23423,24020,24018,24398,25087,25892,27402,27489,28753,
+28760,29568,29924,30090,30318,30316,31155,31840,31839,32894,32893,33247,35186,
+35183,35324,35712,36118,36119,36497,36499,36705,37192,37956,37969,37970,38717,
+38718,38851,38849,39019,39253,39509,39501,39634,39706,40009,39985,39998,39995,
+40403,40407,40756,40812,40810,40852,22220,24022,25088,25891,25899,25898,26348,
+27408,29914,31434,31844,31843,31845,32403,32406,32404,33250,34360,34367,34865,
+35722,37008,37007,37987,37984,37988,38760,39023,39260,39514,39515,39511,39635,
+39636,39633,40020,40023,40022,40421,40607,40692,22225,22761,25900,28766,30321,
+30322,30679,32592,32648,34870,34873,34914,35731,35730,35734,33399,36123,37312,
+37994,38722,38728,38724,38854,39024,39519,39714,39768,40031,40441,40442,40572,
+40573,40711,40823,40818,24307,27414,28771,31852,31854,34875,35264,36513,37313,
+38002,38000,39025,39262,39638,39715,40652,28772,30682,35738,38007,38857,39522,
+39525,32412,35740,36522,37317,38013,38014,38012,40055,40056,40695,35924,38015,
+40474,29224,39530,39729,40475,40478,31858,9312,9313,9314,9315,9316,9317,9318,
+9319,9320,9321,9332,9333,9334,9335,9336,
+9337,9338,9339,9340,9341,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,
+20022,20031,20101,20128,20866,20886,20907,21241,21304,21353,21430,22794,23424,
+24027,24186,24191,24308,24400,24417,25908,26080,30098,30326,36789,38582,168,
+710,12541,12542,12445,12446,0,0,12293,12294,12295,12540,65339,65341,10045,
+12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,
+12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,
+12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
+12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,
+12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,
+12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,
+12431,12432,12433,12434,12435,12449,12450,12451,12452,12453,12454,12455,12456,
+12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,
+12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,
+12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,
+12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,
+12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,
+12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,
+1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,
+1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,
+1069,1070,
+1071,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,
+1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,
+1100,1101,1102,1103,8679,8632,8633,12751,204,20058,138,20994,17553,40880,
+20872,40881,30215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,65506,65508,65287,65282,12849,8470,8481,12443,12444,11904,
+11908,11910,11911,11912,11914,11916,11917,11925,11932,11933,11941,11943,11946,
+11948,11950,11958,11964,11966,11974,11978,11980,11981,11983,11990,11991,11998,
+12003,0,0,0,643,592,603,596,629,339,248,331,650,618,20034,20060,20981,21274,
+21378,19975,19980,20039,20109,22231,64012,23662,24435,19983,20871,19982,20014,
+20115,20162,20169,20168,20888,21244,21356,21433,22304,22787,22828,23568,24063,
+26081,27571,27596,27668,29247,20017,20028,20200,20188,20201,20193,20189,20186,
+21004,21276,21324,22306,22307,22807,22831,23425,23428,23570,23611,23668,23667,
+24068,24192,24194,24521,25097,25168,27669,27702,27715,27711,27707,29358,29360,
+29578,31160,32906,38430,20238,20248,20268,20213,20244,20209,20224,20215,20232,
+20253,20226,20229,20258,20243,20228,20212,20242,20913,21011,21001,21008,21158,
+21282,21279,21325,21386,21511,22241,22239,22318,22314,22324,22844,22912,22908,
+22917,22907,22910,22903,22911,23382,23573,23589,23676,23674,23675,
+23678,24031,24181,24196,24322,24346,24436,24533,24532,24527,25180,25182,25188,
+25185,25190,25186,25177,25184,25178,25189,26095,26094,26430,26425,26424,26427,
+26426,26431,26428,26419,27672,27718,27730,27740,27727,27722,27732,27723,27724,
+28785,29278,29364,29365,29582,29994,30335,31349,32593,33400,33404,33408,33405,
+33407,34381,35198,37017,37015,37016,37019,37012,38434,38436,38432,38435,20310,
+20283,20322,20297,20307,20324,20286,20327,20306,20319,20289,20312,20269,20275,
+20287,20321,20879,20921,21020,21022,21025,21165,21166,21257,21347,21362,21390,
+21391,21552,21559,21546,21588,21573,21529,21532,21541,21528,21565,21583,21569,
+21544,21540,21575,22254,22247,22245,22337,22341,22348,22345,22347,22354,22790,
+22848,22950,22936,22944,22935,22926,22946,22928,22927,22951,22945,23438,23442,
+23592,23594,23693,23695,23688,23691,23689,23698,23690,23686,23699,23701,24032,
+24074,24078,24203,24201,24204,24200,24205,24325,24349,24440,24438,24530,24529,
+24528,24557,24552,24558,24563,24545,24548,24547,24570,24559,24567,24571,24576,
+24564,25146,25219,25228,25230,25231,25236,25223,25201,25211,25210,25200,25217,
+25224,25207,25213,25202,25204,25911,26096,26100,26099,26098,26101,26437,26439,
+26457,26453,26444,26440,26461,26445,26458,26443,27600,27673,27674,27768,27751,
+27755,27780,27787,27791,27761,27759,27753,27802,27757,27783,27797,27804,27750,
+27763,27749,27771,27790,28788,28794,29283,29375,29373,29379,29382,29377,29370,
+29381,29589,29591,29587,29588,29586,30010,30009,30100,30101,30337,31037,32820,
+32917,32921,32912,32914,32924,33424,33423,33413,33422,
+33425,33427,33418,33411,33412,35960,36809,36799,37023,37025,37029,37022,37031,
+37024,38448,38440,38447,38445,20019,20376,20348,20357,20349,20352,20359,20342,
+20340,20361,20356,20343,20300,20375,20330,20378,20345,20353,20344,20368,20380,
+20372,20382,20370,20354,20373,20331,20334,20894,20924,20926,21045,21042,21043,
+21062,21041,21180,21258,21259,21308,21394,21396,21639,21631,21633,21649,21634,
+21640,21611,21626,21630,21605,21612,21620,21606,21645,21615,21601,21600,21656,
+21603,21607,21604,22263,22265,22383,22386,22381,22379,22385,22384,22390,22400,
+22389,22395,22387,22388,22370,22376,22397,22796,22853,22965,22970,22991,22990,
+22962,22988,22977,22966,22972,22979,22998,22961,22973,22976,22984,22964,22983,
+23394,23397,23443,23445,23620,23623,23726,23716,23712,23733,23727,23720,23724,
+23711,23715,23725,23714,23722,23719,23709,23717,23734,23728,23718,24087,24084,
+24089,24360,24354,24355,24356,24404,24450,24446,24445,24542,24549,24621,24614,
+24601,24626,24587,24628,24586,24599,24627,24602,24606,24620,24610,24589,24592,
+24622,24595,24593,24588,24585,24604,25108,25149,25261,25268,25297,25278,25258,
+25270,25290,25262,25267,25263,25275,25257,25264,25272,25917,26024,26043,26121,
+26108,26116,26130,26120,26107,26115,26123,26125,26117,26109,26129,26128,26358,
+26378,26501,26476,26510,26514,26486,26491,26520,26502,26500,26484,26509,26508,
+26490,26527,26513,26521,26499,26493,26497,26488,26489,26516,27429,27520,27518,
+27614,27677,27795,27884,27883,27886,27865,27830,27860,27821,27879,27831,27856,
+27842,27834,27843,27846,27885,27890,27858,27869,27828,
+27786,27805,27776,27870,27840,27952,27853,27847,27824,27897,27855,27881,27857,
+28820,28824,28805,28819,28806,28804,28817,28822,28802,28826,28803,29290,29398,
+29387,29400,29385,29404,29394,29396,29402,29388,29393,29604,29601,29613,29606,
+29602,29600,29612,29597,29917,29928,30015,30016,30014,30092,30104,30383,30451,
+30449,30448,30453,30712,30716,30713,30715,30714,30711,31042,31039,31173,31352,
+31355,31483,31861,31997,32821,32911,32942,32931,32952,32949,32941,33312,33440,
+33472,33451,33434,33432,33435,33461,33447,33454,33468,33438,33466,33460,33448,
+33441,33449,33474,33444,33475,33462,33442,34416,34415,34413,34414,35926,36818,
+36811,36819,36813,36822,36821,36823,37042,37044,37039,37043,37040,38457,38461,
+38460,38458,38467,20429,20421,20435,20402,20425,20427,20417,20436,20444,20441,
+20411,20403,20443,20423,20438,20410,20416,20409,20460,21060,21065,21184,21186,
+21309,21372,21399,21398,21401,21400,21690,21665,21677,21669,21711,21699,33549,
+21687,21678,21718,21686,21701,21702,21664,21616,21692,21666,21694,21618,21726,
+21680,22453,22430,22431,22436,22412,22423,22429,22427,22420,22424,22415,22425,
+22437,22426,22421,22772,22797,22867,23009,23006,23022,23040,23025,23005,23034,
+23037,23036,23030,23012,23026,23031,23003,23017,23027,23029,23008,23038,23028,
+23021,23464,23628,23760,23768,23756,23767,23755,23771,23774,23770,23753,23751,
+23754,23766,23763,23764,23759,23752,23750,23758,23775,23800,24057,24097,24098,
+24099,24096,24100,24240,24228,24226,24219,24227,24229,24327,24366,24406,24454,
+24631,24633,24660,24690,24670,24645,24659,24647,24649,
+24667,24652,24640,24642,24671,24612,24644,24664,24678,24686,25154,25155,25295,
+25357,25355,25333,25358,25347,25323,25337,25359,25356,25336,25334,25344,25363,
+25364,25338,25365,25339,25328,25921,25923,26026,26047,26166,26145,26162,26165,
+26140,26150,26146,26163,26155,26170,26141,26164,26169,26158,26383,26384,26561,
+26610,26568,26554,26588,26555,26616,26584,26560,26551,26565,26603,26596,26591,
+26549,26573,26547,26615,26614,26606,26595,26562,26553,26574,26599,26608,26546,
+26620,26566,26605,26572,26542,26598,26587,26618,26569,26570,26563,26602,26571,
+27432,27522,27524,27574,27606,27608,27616,27680,27681,27944,27956,27949,27935,
+27964,27967,27922,27914,27866,27955,27908,27929,27962,27930,27921,27904,27933,
+27970,27905,27928,27959,27907,27919,27968,27911,27936,27948,27912,27938,27913,
+27920,28855,28831,28862,28849,28848,28833,28852,28853,28841,29249,29257,29258,
+29292,29296,29299,29294,29386,29412,29416,29419,29407,29418,29414,29411,29573,
+29644,29634,29640,29637,29625,29622,29621,29620,29675,29631,29639,29630,29635,
+29638,29624,29643,29932,29934,29998,30023,30024,30119,30122,30329,30404,30472,
+30467,30468,30469,30474,30455,30459,30458,30695,30696,30726,30737,30738,30725,
+30736,30735,30734,30729,30723,30739,31050,31052,31051,31045,31044,31189,31181,
+31183,31190,31182,31360,31358,31441,31488,31489,31866,31864,31865,31871,31872,
+31873,32003,32008,32001,32600,32657,32653,32702,32775,32782,32783,32788,32823,
+32984,32967,32992,32977,32968,32962,32976,32965,32995,32985,32988,32970,32981,
+32969,32975,32983,32998,32973,33279,33313,33428,33497,
+33534,33529,33543,33512,33536,33493,33594,33515,33494,33524,33516,33505,33522,
+33525,33548,33531,33526,33520,33514,33508,33504,33530,33523,33517,34423,34420,
+34428,34419,34881,34894,34919,34922,34921,35283,35332,35335,36210,36835,36833,
+36846,36832,37105,37053,37055,37077,37061,37054,37063,37067,37064,37332,37331,
+38484,38479,38481,38483,38474,38478,20510,20485,20487,20499,20514,20528,20507,
+20469,20468,20531,20535,20524,20470,20471,20503,20508,20512,20519,20533,20527,
+20529,20494,20826,20884,20883,20938,20932,20933,20936,20942,21089,21082,21074,
+21086,21087,21077,21090,21197,21262,21406,21798,21730,21783,21778,21735,21747,
+21732,21786,21759,21764,21768,21739,21777,21765,21745,21770,21755,21751,21752,
+21728,21774,21763,21771,22273,22274,22476,22578,22485,22482,22458,22470,22461,
+22460,22456,22454,22463,22471,22480,22457,22465,22798,22858,23065,23062,23085,
+23086,23061,23055,23063,23050,23070,23091,23404,23463,23469,23468,23555,23638,
+23636,23788,23807,23790,23793,23799,23808,23801,24105,24104,24232,24238,24234,
+24236,24371,24368,24423,24669,24666,24679,24641,24738,24712,24704,24722,24705,
+24733,24707,24725,24731,24727,24711,24732,24718,25113,25158,25330,25360,25430,
+25388,25412,25413,25398,25411,25572,25401,25419,25418,25404,25385,25409,25396,
+25432,25428,25433,25389,25415,25395,25434,25425,25400,25431,25408,25416,25930,
+25926,26054,26051,26052,26050,26186,26207,26183,26193,26386,26387,26655,26650,
+26697,26674,26675,26683,26699,26703,26646,26673,26652,26677,26667,26669,26671,
+26702,26692,26676,26653,26642,26644,26662,26664,26670,
+26701,26682,26661,26656,27436,27439,27437,27441,27444,27501,32898,27528,27622,
+27620,27624,27619,27618,27623,27685,28026,28003,28004,28022,27917,28001,28050,
+27992,28002,28013,28015,28049,28045,28143,28031,28038,27998,28007,28000,28055,
+28016,28028,27999,28034,28056,27951,28008,28043,28030,28032,28036,27926,28035,
+28027,28029,28021,28048,28892,28883,28881,28893,28875,32569,28898,28887,28882,
+28894,28896,28884,28877,28869,28870,28871,28890,28878,28897,29250,29304,29303,
+29302,29440,29434,29428,29438,29430,29427,29435,29441,29651,29657,29669,29654,
+29628,29671,29667,29673,29660,29650,29659,29652,29661,29658,29655,29656,29672,
+29918,29919,29940,29941,29985,30043,30047,30128,30145,30139,30148,30144,30143,
+30134,30138,30346,30409,30493,30491,30480,30483,30482,30499,30481,30485,30489,
+30490,30498,30503,30755,30764,30754,30773,30767,30760,30766,30763,30753,30761,
+30771,30762,30769,31060,31067,31055,31068,31059,31058,31057,31211,31212,31200,
+31214,31213,31210,31196,31198,31197,31366,31369,31365,31371,31372,31370,31367,
+31448,31504,31492,31507,31493,31503,31496,31498,31502,31497,31506,31876,31889,
+31882,31884,31880,31885,31877,32030,32029,32017,32014,32024,32022,32019,32031,
+32018,32015,32012,32604,32609,32606,32608,32605,32603,32662,32658,32707,32706,
+32704,32790,32830,32825,33018,33010,33017,33013,33025,33019,33024,33281,33327,
+33317,33587,33581,33604,33561,33617,33573,33622,33599,33601,33574,33564,33570,
+33602,33614,33563,33578,33544,33596,33613,33558,33572,33568,33591,33583,33577,
+33607,33605,33612,33619,33566,33580,33611,33575,33608,
+34387,34386,34466,34472,34454,34445,34449,34462,34439,34455,34438,34443,34458,
+34437,34469,34457,34465,34471,34453,34456,34446,34461,34448,34452,34883,34884,
+34925,34933,34934,34930,34944,34929,34943,34927,34947,34942,34932,34940,35346,
+35911,35927,35963,36004,36003,36214,36216,36277,36279,36278,36561,36563,36862,
+36853,36866,36863,36859,36868,36860,36854,37078,37088,37081,37082,37091,37087,
+37093,37080,37083,37079,37084,37092,37200,37198,37199,37333,37346,37338,38492,
+38495,38588,39139,39647,39727,20095,20592,20586,20577,20574,20576,20563,20555,
+20573,20594,20552,20557,20545,20571,20554,20578,20501,20549,20575,20585,20587,
+20579,20580,20550,20544,20590,20595,20567,20561,20944,21099,21101,21100,21102,
+21206,21203,21293,21404,21877,21878,21820,21837,21840,21812,21802,21841,21858,
+21814,21813,21808,21842,21829,21772,21810,21861,21838,21817,21832,21805,21819,
+21824,21835,22282,22279,22523,22548,22498,22518,22492,22516,22528,22509,22525,
+22536,22520,22539,22515,22479,22535,22510,22499,22514,22501,22508,22497,22542,
+22524,22544,22503,22529,22540,22513,22505,22512,22541,22532,22876,23136,23128,
+23125,23143,23134,23096,23093,23149,23120,23135,23141,23148,23123,23140,23127,
+23107,23133,23122,23108,23131,23112,23182,23102,23117,23097,23116,23152,23145,
+23111,23121,23126,23106,23132,23410,23406,23489,23488,23641,23838,23819,23837,
+23834,23840,23820,23848,23821,23846,23845,23823,23856,23826,23843,23839,23854,
+24126,24116,24241,24244,24249,24242,24243,24374,24376,24475,24470,24479,24714,
+24720,24710,24766,24752,24762,24787,24788,24783,24804,
+24793,24797,24776,24753,24795,24759,24778,24767,24771,24781,24768,25394,25445,
+25482,25474,25469,25533,25502,25517,25501,25495,25515,25486,25455,25479,25488,
+25454,25519,25461,25500,25453,25518,25468,25508,25403,25503,25464,25477,25473,
+25489,25485,25456,25939,26061,26213,26209,26203,26201,26204,26210,26392,26745,
+26759,26768,26780,26733,26734,26798,26795,26966,26735,26787,26796,26793,26741,
+26740,26802,26767,26743,26770,26748,26731,26738,26794,26752,26737,26750,26779,
+26774,26763,26784,26761,26788,26744,26747,26769,26764,26762,26749,27446,27443,
+27447,27448,27537,27535,27533,27534,27532,27690,28096,28075,28084,28083,28276,
+28076,28137,28130,28087,28150,28116,28160,28104,28128,28127,28118,28094,28133,
+28124,28125,28123,28148,28106,28093,28141,28144,28090,28117,28098,28111,28105,
+28112,28146,28115,28157,28119,28109,28131,28091,28922,28941,28919,28951,28916,
+28940,28912,28932,28915,28944,28924,28927,28934,28947,28928,28920,28918,28939,
+28930,28942,29310,29307,29308,29311,29469,29463,29447,29457,29464,29450,29448,
+29439,29455,29470,29576,29686,29688,29685,29700,29697,29693,29703,29696,29690,
+29692,29695,29708,29707,29684,29704,30052,30051,30158,30162,30159,30155,30156,
+30161,30160,30351,30345,30419,30521,30511,30509,30513,30514,30516,30515,30525,
+30501,30523,30517,30792,30802,30793,30797,30794,30796,30758,30789,30800,31076,
+31079,31081,31082,31075,31083,31073,31163,31226,31224,31222,31223,31375,31380,
+31376,31541,31559,31540,31525,31536,31522,31524,31539,31512,31530,31517,31537,
+31531,31533,31535,31538,31544,31514,31523,31892,31896,
+31894,31907,32053,32061,32056,32054,32058,32069,32044,32041,32065,32071,32062,
+32063,32074,32059,32040,32611,32661,32668,32669,32667,32714,32715,32717,32720,
+32721,32711,32719,32713,32799,32798,32795,32839,32835,32840,33048,33061,33049,
+33051,33069,33055,33068,33054,33057,33045,33063,33053,33058,33297,33336,33331,
+33338,33332,33330,33396,33680,33699,33704,33677,33658,33651,33700,33652,33679,
+33665,33685,33689,33653,33684,33705,33661,33667,33676,33693,33691,33706,33675,
+33662,33701,33711,33672,33687,33712,33663,33702,33671,33710,33654,33690,34393,
+34390,34495,34487,34498,34497,34501,34490,34480,34504,34489,34483,34488,34508,
+34484,34491,34492,34499,34493,34494,34898,34953,34965,34984,34978,34986,34970,
+34961,34977,34975,34968,34983,34969,34971,34967,34980,34988,34956,34963,34958,
+35202,35286,35289,35285,35376,35367,35372,35358,35897,35899,35932,35933,35965,
+36005,36221,36219,36217,36284,36290,36281,36287,36289,36568,36574,36573,36572,
+36567,36576,36577,36900,36875,36881,36892,36876,36897,37103,37098,37104,37108,
+37106,37107,37076,37099,37100,37097,37206,37208,37210,37203,37205,37356,37364,
+37361,37363,37368,37348,37369,37354,37355,37367,37352,37358,38266,38278,38280,
+38524,38509,38507,38513,38511,38591,38762,38916,39141,39319,20635,20629,20628,
+20638,20619,20643,20611,20620,20622,20637,20584,20636,20626,20610,20615,20831,
+20948,21266,21265,21412,21415,21905,21928,21925,21933,21879,22085,21922,21907,
+21896,21903,21941,21889,21923,21906,21924,21885,21900,21926,21887,21909,21921,
+21902,22284,22569,22583,22553,22558,22567,22563,22568,
+22517,22600,22565,22556,22555,22579,22591,22582,22574,22585,22584,22573,22572,
+22587,22881,23215,23188,23199,23162,23202,23198,23160,23206,23164,23205,23212,
+23189,23214,23095,23172,23178,23191,23171,23179,23209,23163,23165,23180,23196,
+23183,23187,23197,23530,23501,23499,23508,23505,23498,23502,23564,23600,23863,
+23875,23915,23873,23883,23871,23861,23889,23886,23893,23859,23866,23890,23869,
+23857,23897,23874,23865,23881,23864,23868,23858,23862,23872,23877,24132,24129,
+24408,24486,24485,24491,24777,24761,24780,24802,24782,24772,24852,24818,24842,
+24854,24837,24821,24851,24824,24828,24830,24769,24835,24856,24861,24848,24831,
+24836,24843,25162,25492,25521,25520,25550,25573,25576,25583,25539,25757,25587,
+25546,25568,25590,25557,25586,25589,25697,25567,25534,25565,25564,25540,25560,
+25555,25538,25543,25548,25547,25544,25584,25559,25561,25906,25959,25962,25956,
+25948,25960,25957,25996,26013,26014,26030,26064,26066,26236,26220,26235,26240,
+26225,26233,26218,26226,26369,26892,26835,26884,26844,26922,26860,26858,26865,
+26895,26838,26871,26859,26852,26870,26899,26896,26867,26849,26887,26828,26888,
+26992,26804,26897,26863,26822,26900,26872,26832,26877,26876,26856,26891,26890,
+26903,26830,26824,26845,26846,26854,26868,26833,26886,26836,26857,26901,26917,
+26823,27449,27451,27455,27452,27540,27543,27545,27541,27581,27632,27634,27635,
+27696,28156,28230,28231,28191,28233,28296,28220,28221,28229,28258,28203,28223,
+28225,28253,28275,28188,28211,28235,28224,28241,28219,28163,28206,28254,28264,
+28252,28257,28209,28200,28256,28273,28267,28217,28194,
+28208,28243,28261,28199,28280,28260,28279,28245,28281,28242,28262,28213,28214,
+28250,28960,28958,28975,28923,28974,28977,28963,28965,28962,28978,28959,28968,
+28986,28955,29259,29274,29320,29321,29318,29317,29323,29458,29451,29488,29474,
+29489,29491,29479,29490,29485,29478,29475,29493,29452,29742,29740,29744,29739,
+29718,29722,29729,29741,29745,29732,29731,29725,29737,29728,29746,29947,29999,
+30063,30060,30183,30170,30177,30182,30173,30175,30180,30167,30357,30354,30426,
+30534,30535,30532,30541,30533,30538,30542,30539,30540,30686,30700,30816,30820,
+30821,30812,30829,30833,30826,30830,30832,30825,30824,30814,30818,31092,31091,
+31090,31088,31234,31242,31235,31244,31236,31385,31462,31460,31562,31547,31556,
+31560,31564,31566,31552,31576,31557,31906,31902,31912,31905,32088,32111,32099,
+32083,32086,32103,32106,32079,32109,32092,32107,32082,32084,32105,32081,32095,
+32078,32574,32575,32613,32614,32674,32672,32673,32727,32849,32847,32848,33022,
+32980,33091,33098,33106,33103,33095,33085,33101,33082,33254,33262,33271,33272,
+33273,33284,33340,33341,33343,33397,33595,33743,33785,33827,33728,33768,33810,
+33767,33764,33788,33782,33808,33734,33736,33771,33763,33727,33793,33757,33765,
+33752,33791,33761,33739,33742,33750,33781,33737,33801,33807,33758,33809,33798,
+33730,33779,33749,33786,33735,33745,33770,33811,33731,33772,33774,33732,33787,
+33751,33762,33819,33755,33790,34520,34530,34534,34515,34531,34522,34538,34525,
+34539,34524,34540,34537,34519,34536,34513,34888,34902,34901,35002,35031,35001,
+35000,35008,35006,34998,35004,34999,35005,34994,35073,
+35017,35221,35224,35223,35293,35290,35291,35406,35405,35385,35417,35392,35415,
+35416,35396,35397,35410,35400,35409,35402,35404,35407,35935,35969,35968,36026,
+36030,36016,36025,36021,36228,36224,36233,36312,36307,36301,36295,36310,36316,
+36303,36309,36313,36296,36311,36293,36591,36599,36602,36601,36582,36590,36581,
+36597,36583,36584,36598,36587,36593,36588,36596,36585,36909,36916,36911,37126,
+37164,37124,37119,37116,37128,37113,37115,37121,37120,37127,37125,37123,37217,
+37220,37215,37218,37216,37377,37386,37413,37379,37402,37414,37391,37388,37376,
+37394,37375,37373,37382,37380,37415,37378,37404,37412,37401,37399,37381,37398,
+38267,38285,38284,38288,38535,38526,38536,38537,38531,38528,38594,38600,38595,
+38641,38640,38764,38768,38766,38919,39081,39147,40166,40697,20099,20100,20150,
+20669,20671,20678,20654,20676,20682,20660,20680,20674,20656,20673,20666,20657,
+20683,20681,20662,20664,20951,21114,21112,21115,21116,21955,21979,21964,21968,
+21963,21962,21981,21952,21972,21956,21993,21951,21970,21901,21967,21973,21986,
+21974,21960,22002,21965,21977,21954,22292,22611,22632,22628,22607,22605,22601,
+22639,22613,22606,22621,22617,22629,22619,22589,22627,22641,22780,23239,23236,
+23243,23226,23224,23217,23221,23216,23231,23240,23227,23238,23223,23232,23242,
+23220,23222,23245,23225,23184,23510,23512,23513,23583,23603,23921,23907,23882,
+23909,23922,23916,23902,23912,23911,23906,24048,24143,24142,24138,24141,24139,
+24261,24268,24262,24267,24263,24384,24495,24493,24823,24905,24906,24875,24901,
+24886,24882,24878,24902,24879,24911,24873,24896,25120,
+37224,25123,25125,25124,25541,25585,25579,25616,25618,25609,25632,25636,25651,
+25667,25631,25621,25624,25657,25655,25634,25635,25612,25638,25648,25640,25665,
+25653,25647,25610,25626,25664,25637,25639,25611,25575,25627,25646,25633,25614,
+25967,26002,26067,26246,26252,26261,26256,26251,26250,26265,26260,26232,26400,
+26982,26975,26936,26958,26978,26993,26943,26949,26986,26937,26946,26967,26969,
+27002,26952,26953,26933,26988,26931,26941,26981,26864,27000,26932,26985,26944,
+26991,26948,26998,26968,26945,26996,26956,26939,26955,26935,26972,26959,26961,
+26930,26962,26927,27003,26940,27462,27461,27459,27458,27464,27457,27547,64013,
+27643,27644,27641,27639,27640,28315,28374,28360,28303,28352,28319,28307,28308,
+28320,28337,28345,28358,28370,28349,28353,28318,28361,28343,28336,28365,28326,
+28367,28338,28350,28355,28380,28376,28313,28306,28302,28301,28324,28321,28351,
+28339,28368,28362,28311,28334,28323,28999,29012,29010,29027,29024,28993,29021,
+29026,29042,29048,29034,29025,28994,29016,28995,29003,29040,29023,29008,29011,
+28996,29005,29018,29263,29325,29324,29329,29328,29326,29500,29506,29499,29498,
+29504,29514,29513,29764,29770,29771,29778,29777,29783,29760,29775,29776,29774,
+29762,29766,29773,29780,29921,29951,29950,29949,29981,30073,30071,27011,30191,
+30223,30211,30199,30206,30204,30201,30200,30224,30203,30198,30189,30197,30205,
+30361,30389,30429,30549,30559,30560,30546,30550,30554,30569,30567,30548,30553,
+30573,30688,30855,30874,30868,30863,30852,30869,30853,30854,30881,30851,30841,
+30873,30848,30870,30843,31100,31106,31101,31097,31249,
+31256,31257,31250,31255,31253,31266,31251,31259,31248,31395,31394,31390,31467,
+31590,31588,31597,31604,31593,31602,31589,31603,31601,31600,31585,31608,31606,
+31587,31922,31924,31919,32136,32134,32128,32141,32127,32133,32122,32142,32123,
+32131,32124,32140,32148,32132,32125,32146,32621,32619,32615,32616,32620,32678,
+32677,32679,32731,32732,32801,33124,33120,33143,33116,33129,33115,33122,33138,
+26401,33118,33142,33127,33135,33092,33121,33309,33353,33348,33344,33346,33349,
+34033,33855,33878,33910,33913,33935,33933,33893,33873,33856,33926,33895,33840,
+33869,33917,33882,33881,33908,33907,33885,34055,33886,33847,33850,33844,33914,
+33859,33912,33842,33861,33833,33753,33867,33839,33858,33837,33887,33904,33849,
+33870,33868,33874,33903,33989,33934,33851,33863,33846,33843,33896,33918,33860,
+33835,33888,33876,33902,33872,34571,34564,34551,34572,34554,34518,34549,34637,
+34552,34574,34569,34561,34550,34573,34565,35030,35019,35021,35022,35038,35035,
+35034,35020,35024,35205,35227,35295,35301,35300,35297,35296,35298,35292,35302,
+35446,35462,35455,35425,35391,35447,35458,35460,35445,35459,35457,35444,35450,
+35900,35915,35914,35941,35940,35942,35974,35972,35973,36044,36200,36201,36241,
+36236,36238,36239,36237,36243,36244,36240,36242,36336,36320,36332,36337,36334,
+36304,36329,36323,36322,36327,36338,36331,36340,36614,36607,36609,36608,36613,
+36615,36616,36610,36619,36946,36927,36932,36937,36925,37136,37133,37135,37137,
+37142,37140,37131,37134,37230,37231,37448,37458,37424,37434,37478,37427,37477,
+37470,37507,37422,37450,37446,37485,37484,37455,37472,
+37479,37487,37430,37473,37488,37425,37460,37475,37456,37490,37454,37459,37452,
+37462,37426,38303,38300,38302,38299,38546,38547,38545,38551,38606,38650,38653,
+38648,38645,38771,38775,38776,38770,38927,38925,38926,39084,39158,39161,39343,
+39346,39344,39349,39597,39595,39771,40170,40173,40167,40576,40701,20710,20692,
+20695,20712,20723,20699,20714,20701,20708,20691,20716,20720,20719,20707,20704,
+20952,21120,21121,21225,21227,21296,21420,22055,22037,22028,22034,22012,22031,
+22044,22017,22035,22018,22010,22045,22020,22015,22009,22665,22652,22672,22680,
+22662,22657,22655,22644,22667,22650,22663,22673,22670,22646,22658,22664,22651,
+22676,22671,22782,22891,23260,23278,23269,23253,23274,23258,23277,23275,23283,
+23266,23264,23259,23276,23262,23261,23257,23272,23263,23415,23520,23523,23651,
+23938,23936,23933,23942,23930,23937,23927,23946,23945,23944,23934,23932,23949,
+23929,23935,24152,24153,24147,24280,24273,24279,24270,24284,24277,24281,24274,
+24276,24388,24387,24431,24502,24876,24872,24897,24926,24945,24947,24914,24915,
+24946,24940,24960,24948,24916,24954,24923,24933,24891,24938,24929,24918,25129,
+25127,25131,25643,25677,25691,25693,25716,25718,25714,25715,25725,25717,25702,
+25766,25678,25730,25694,25692,25675,25683,25696,25680,25727,25663,25708,25707,
+25689,25701,25719,25971,26016,26273,26272,26271,26373,26372,26402,27057,27062,
+27081,27040,27086,27030,27056,27052,27068,27025,27033,27022,27047,27021,27049,
+27070,27055,27071,27076,27069,27044,27092,27065,27082,27034,27087,27059,27027,
+27050,27041,27038,27097,27031,27024,27074,27061,27045,
+27078,27466,27469,27467,27550,27551,27552,27587,27588,27646,28366,28405,28401,
+28419,28453,28408,28471,28411,28462,28425,28494,28441,28442,28455,28440,28475,
+28434,28397,28426,28470,28531,28409,28398,28461,28480,28464,28476,28469,28395,
+28423,28430,28483,28421,28413,28406,28473,28444,28412,28474,28447,28429,28446,
+28424,28449,29063,29072,29065,29056,29061,29058,29071,29051,29062,29057,29079,
+29252,29267,29335,29333,29331,29507,29517,29521,29516,29794,29811,29809,29813,
+29810,29799,29806,29952,29954,29955,30077,30096,30230,30216,30220,30229,30225,
+30218,30228,30392,30593,30588,30597,30594,30574,30592,30575,30590,30595,30898,
+30890,30900,30893,30888,30846,30891,30878,30885,30880,30892,30882,30884,31128,
+31114,31115,31126,31125,31124,31123,31127,31112,31122,31120,31275,31306,31280,
+31279,31272,31270,31400,31403,31404,31470,31624,31644,31626,31633,31632,31638,
+31629,31628,31643,31630,31621,31640,21124,31641,31652,31618,31931,31935,31932,
+31930,32167,32183,32194,32163,32170,32193,32192,32197,32157,32206,32196,32198,
+32203,32204,32175,32185,32150,32188,32159,32166,32174,32169,32161,32201,32627,
+32738,32739,32741,32734,32804,32861,32860,33161,33158,33155,33159,33165,33164,
+33163,33301,33943,33956,33953,33951,33978,33998,33986,33964,33966,33963,33977,
+33972,33985,33997,33962,33946,33969,34000,33949,33959,33979,33954,33940,33991,
+33996,33947,33961,33967,33960,34006,33944,33974,33999,33952,34007,34004,34002,
+34011,33968,33937,34401,34611,34595,34600,34667,34624,34606,34590,34593,34585,
+34587,34627,34604,34625,34622,34630,34592,34610,34602,
+34605,34620,34578,34618,34609,34613,34626,34598,34599,34616,34596,34586,34608,
+34577,35063,35047,35057,35058,35066,35070,35054,35068,35062,35067,35056,35052,
+35051,35229,35233,35231,35230,35305,35307,35304,35499,35481,35467,35474,35471,
+35478,35901,35944,35945,36053,36047,36055,36246,36361,36354,36351,36365,36349,
+36362,36355,36359,36358,36357,36350,36352,36356,36624,36625,36622,36621,37155,
+37148,37152,37154,37151,37149,37146,37156,37153,37147,37242,37234,37241,37235,
+37541,37540,37494,37531,37498,37536,37524,37546,37517,37542,37530,37547,37497,
+37527,37503,37539,37614,37518,37506,37525,37538,37501,37512,37537,37514,37510,
+37516,37529,37543,37502,37511,37545,37533,37515,37421,38558,38561,38655,38744,
+38781,38778,38782,38787,38784,38786,38779,38788,38785,38783,38862,38861,38934,
+39085,39086,39170,39168,39175,39325,39324,39363,39353,39355,39354,39362,39357,
+39367,39601,39651,39655,39742,39743,39776,39777,39775,40177,40178,40181,40615,
+20735,20739,20784,20728,20742,20743,20726,20734,20747,20748,20733,20746,21131,
+21132,21233,21231,22088,22082,22092,22069,22081,22090,22089,22086,22104,22106,
+22080,22067,22077,22060,22078,22072,22058,22074,22298,22699,22685,22705,22688,
+22691,22703,22700,22693,22689,22783,23295,23284,23293,23287,23286,23299,23288,
+23298,23289,23297,23303,23301,23311,23655,23961,23959,23967,23954,23970,23955,
+23957,23968,23964,23969,23962,23966,24169,24157,24160,24156,32243,24283,24286,
+24289,24393,24498,24971,24963,24953,25009,25008,24994,24969,24987,24979,25007,
+25005,24991,24978,25002,24993,24973,24934,25011,25133,
+25710,25712,25750,25760,25733,25751,25756,25743,25739,25738,25740,25763,25759,
+25704,25777,25752,25974,25978,25977,25979,26034,26035,26293,26288,26281,26290,
+26295,26282,26287,27136,27142,27159,27109,27128,27157,27121,27108,27168,27135,
+27116,27106,27163,27165,27134,27175,27122,27118,27156,27127,27111,27200,27144,
+27110,27131,27149,27132,27115,27145,27140,27160,27173,27151,27126,27174,27143,
+27124,27158,27473,27557,27555,27554,27558,27649,27648,27647,27650,28481,28454,
+28542,28551,28614,28562,28557,28553,28556,28514,28495,28549,28506,28566,28534,
+28524,28546,28501,28530,28498,28496,28503,28564,28563,28509,28416,28513,28523,
+28541,28519,28560,28499,28555,28521,28543,28565,28515,28535,28522,28539,29106,
+29103,29083,29104,29088,29082,29097,29109,29085,29093,29086,29092,29089,29098,
+29084,29095,29107,29336,29338,29528,29522,29534,29535,29536,29533,29531,29537,
+29530,29529,29538,29831,29833,29834,29830,29825,29821,29829,29832,29820,29817,
+29960,29959,30078,30245,30238,30233,30237,30236,30243,30234,30248,30235,30364,
+30365,30366,30363,30605,30607,30601,30600,30925,30907,30927,30924,30929,30926,
+30932,30920,30915,30916,30921,31130,31137,31136,31132,31138,31131,27510,31289,
+31410,31412,31411,31671,31691,31678,31660,31694,31663,31673,31690,31669,31941,
+31944,31948,31947,32247,32219,32234,32231,32215,32225,32259,32250,32230,32246,
+32241,32240,32238,32223,32630,32684,32688,32685,32749,32747,32746,32748,32742,
+32744,32868,32871,33187,33183,33182,33173,33186,33177,33175,33302,33359,33363,
+33362,33360,33358,33361,34084,34107,34063,34048,34089,
+34062,34057,34061,34079,34058,34087,34076,34043,34091,34042,34056,34060,34036,
+34090,34034,34069,34039,34027,34035,34044,34066,34026,34025,34070,34046,34088,
+34077,34094,34050,34045,34078,34038,34097,34086,34023,34024,34032,34031,34041,
+34072,34080,34096,34059,34073,34095,34402,34646,34659,34660,34679,34785,34675,
+34648,34644,34651,34642,34657,34650,34641,34654,34669,34666,34640,34638,34655,
+34653,34671,34668,34682,34670,34652,34661,34639,34683,34677,34658,34663,34665,
+34906,35077,35084,35092,35083,35095,35096,35097,35078,35094,35089,35086,35081,
+35234,35236,35235,35309,35312,35308,35535,35526,35512,35539,35537,35540,35541,
+35515,35543,35518,35520,35525,35544,35523,35514,35517,35545,35902,35917,35983,
+36069,36063,36057,36072,36058,36061,36071,36256,36252,36257,36251,36384,36387,
+36389,36388,36398,36373,36379,36374,36369,36377,36390,36391,36372,36370,36376,
+36371,36380,36375,36378,36652,36644,36632,36634,36640,36643,36630,36631,36979,
+36976,36975,36967,36971,37167,37163,37161,37162,37170,37158,37166,37253,37254,
+37258,37249,37250,37252,37248,37584,37571,37572,37568,37593,37558,37583,37617,
+37599,37592,37609,37591,37597,37580,37615,37570,37608,37578,37576,37582,37606,
+37581,37589,37577,37600,37598,37607,37585,37587,37557,37601,37574,37556,38268,
+38316,38315,38318,38320,38564,38562,38611,38661,38664,38658,38746,38794,38798,
+38792,38864,38863,38942,38941,38950,38953,38952,38944,38939,38951,39090,39176,
+39162,39185,39188,39190,39191,39189,39388,39373,39375,39379,39380,39374,39369,
+39382,39384,39371,39383,39372,39603,39660,39659,39667,
+39666,39665,39750,39747,39783,39796,39793,39782,39798,39797,39792,39784,39780,
+39788,40188,40186,40189,40191,40183,40199,40192,40185,40187,40200,40197,40196,
+40579,40659,40719,40720,20764,20755,20759,20762,20753,20958,21300,21473,22128,
+22112,22126,22131,22118,22115,22125,22130,22110,22135,22300,22299,22728,22717,
+22729,22719,22714,22722,22716,22726,23319,23321,23323,23329,23316,23315,23312,
+23318,23336,23322,23328,23326,23535,23980,23985,23977,23975,23989,23984,23982,
+23978,23976,23986,23981,23983,23988,24167,24168,24166,24175,24297,24295,24294,
+24296,24293,24395,24508,24989,25000,24982,25029,25012,25030,25025,25036,25018,
+25023,25016,24972,25815,25814,25808,25807,25801,25789,25737,25795,25819,25843,
+25817,25907,25983,25980,26018,26312,26302,26304,26314,26315,26319,26301,26299,
+26298,26316,26403,27188,27238,27209,27239,27186,27240,27198,27229,27245,27254,
+27227,27217,27176,27226,27195,27199,27201,27242,27236,27216,27215,27220,27247,
+27241,27232,27196,27230,27222,27221,27213,27214,27206,27477,27476,27478,27559,
+27562,27563,27592,27591,27652,27651,27654,28589,28619,28579,28615,28604,28622,
+28616,28510,28612,28605,28574,28618,28584,28676,28581,28590,28602,28588,28586,
+28623,28607,28600,28578,28617,28587,28621,28591,28594,28592,29125,29122,29119,
+29112,29142,29120,29121,29131,29140,29130,29127,29135,29117,29144,29116,29126,
+29146,29147,29341,29342,29545,29542,29543,29548,29541,29547,29546,29823,29850,
+29856,29844,29842,29845,29857,29963,30080,30255,30253,30257,30269,30259,30268,
+30261,30258,30256,30395,30438,30618,30621,30625,30620,
+30619,30626,30627,30613,30617,30615,30941,30953,30949,30954,30942,30947,30939,
+30945,30946,30957,30943,30944,31140,31300,31304,31303,31414,31416,31413,31409,
+31415,31710,31715,31719,31709,31701,31717,31706,31720,31737,31700,31722,31714,
+31708,31723,31704,31711,31954,31956,31959,31952,31953,32274,32289,32279,32268,
+32287,32288,32275,32270,32284,32277,32282,32290,32267,32271,32278,32269,32276,
+32293,32292,32579,32635,32636,32634,32689,32751,32810,32809,32876,33201,33190,
+33198,33209,33205,33195,33200,33196,33204,33202,33207,33191,33266,33365,33366,
+33367,34134,34117,34155,34125,34131,34145,34136,34112,34118,34148,34113,34146,
+34116,34129,34119,34147,34110,34139,34161,34126,34158,34165,34133,34151,34144,
+34188,34150,34141,34132,34149,34156,34403,34405,34404,34715,34703,34711,34707,
+34706,34696,34689,34710,34712,34681,34695,34723,34693,34704,34705,34717,34692,
+34708,34716,34714,34697,35102,35110,35120,35117,35118,35111,35121,35106,35113,
+35107,35119,35116,35103,35313,35552,35554,35570,35572,35573,35549,35604,35556,
+35551,35568,35528,35550,35553,35560,35583,35567,35579,35985,35986,35984,36085,
+36078,36081,36080,36083,36204,36206,36261,36263,36403,36414,36408,36416,36421,
+36406,36412,36413,36417,36400,36415,36541,36662,36654,36661,36658,36665,36663,
+36660,36982,36985,36987,36998,37114,37171,37173,37174,37267,37264,37265,37261,
+37263,37671,37662,37640,37663,37638,37647,37754,37688,37692,37659,37667,37650,
+37633,37702,37677,37646,37645,37579,37661,37626,37669,37651,37625,37623,37684,
+37634,37668,37631,37673,37689,37685,37674,37652,37644,
+37643,37630,37641,37632,37627,37654,38332,38349,38334,38329,38330,38326,38335,
+38325,38333,38569,38612,38667,38674,38672,38809,38807,38804,38896,38904,38965,
+38959,38962,39204,39199,39207,39209,39326,39406,39404,39397,39396,39408,39395,
+39402,39401,39399,39609,39615,39604,39611,39670,39674,39673,39671,39731,39808,
+39813,39815,39804,39806,39803,39810,39827,39826,39824,39802,39829,39805,39816,
+40229,40215,40224,40222,40212,40233,40221,40216,40226,40208,40217,40223,40584,
+40582,40583,40622,40621,40661,40662,40698,40722,40765,20774,20773,20770,20772,
+20768,20777,21236,22163,22156,22157,22150,22148,22147,22142,22146,22143,22145,
+22742,22740,22735,22738,23341,23333,23346,23331,23340,23335,23334,23343,23342,
+23419,23537,23538,23991,24172,24170,24510,24507,25027,25013,25020,25063,25056,
+25061,25060,25064,25054,25839,25833,25827,25835,25828,25832,25985,25984,26038,
+26074,26322,27277,27286,27265,27301,27273,27295,27291,27297,27294,27271,27283,
+27278,27285,27267,27304,27300,27281,27263,27302,27290,27269,27276,27282,27483,
+27565,27657,28620,28585,28660,28628,28643,28636,28653,28647,28646,28638,28658,
+28637,28642,28648,29153,29169,29160,29170,29156,29168,29154,29555,29550,29551,
+29847,29874,29867,29840,29866,29869,29873,29861,29871,29968,29969,29970,29967,
+30084,30275,30280,30281,30279,30372,30441,30645,30635,30642,30647,30646,30644,
+30641,30632,30704,30963,30973,30978,30971,30972,30962,30981,30969,30974,30980,
+31147,31144,31324,31323,31318,31320,31316,31322,31422,31424,31425,31749,31759,
+31730,31744,31743,31739,31758,31732,31755,31731,31746,
+31753,31747,31745,31736,31741,31750,31728,31729,31760,31754,31976,32301,32316,
+32322,32307,38984,32312,32298,32329,32320,32327,32297,32332,32304,32315,32310,
+32324,32314,32581,32639,32638,32637,32756,32754,32812,33211,33220,33228,33226,
+33221,33223,33212,33257,33371,33370,33372,34179,34176,34191,34215,34197,34208,
+34187,34211,34171,34212,34202,34206,34167,34172,34185,34209,34170,34168,34135,
+34190,34198,34182,34189,34201,34205,34177,34210,34178,34184,34181,34169,34166,
+34200,34192,34207,34408,34750,34730,34733,34757,34736,34732,34745,34741,34748,
+34734,34761,34755,34754,34764,34743,34735,34756,34762,34740,34742,34751,34744,
+34749,34782,34738,35125,35123,35132,35134,35137,35154,35127,35138,35245,35247,
+35246,35314,35315,35614,35608,35606,35601,35589,35595,35618,35599,35602,35605,
+35591,35597,35592,35590,35612,35603,35610,35919,35952,35954,35953,35951,35989,
+35988,36089,36207,36430,36429,36435,36432,36428,36423,36675,36672,36997,36990,
+37176,37274,37282,37275,37273,37279,37281,37277,37280,37793,37763,37807,37732,
+37718,37703,37756,37720,37724,37750,37705,37712,37713,37728,37741,37775,37708,
+37738,37753,37719,37717,37714,37711,37745,37751,37755,37729,37726,37731,37735,
+37760,37710,37721,38343,38336,38345,38339,38341,38327,38574,38576,38572,38688,
+38687,38680,38685,38681,38810,38817,38812,38814,38813,38869,38868,38897,38977,
+38980,38986,38985,38981,38979,39205,39211,39212,39210,39219,39218,39215,39213,
+39217,39216,39320,39331,39329,39426,39418,39412,39415,39417,39416,39414,39419,
+39421,39422,39420,39427,39614,39678,39677,39681,39676,
+39752,39834,39848,39838,39835,39846,39841,39845,39844,39814,39842,39840,39855,
+40243,40257,40295,40246,40238,40239,40241,40248,40240,40261,40258,40259,40254,
+40247,40256,40253,32757,40237,40586,40585,40589,40624,40648,40666,40699,40703,
+40740,40739,40738,40788,40864,20785,20781,20782,22168,22172,22167,22170,22173,
+22169,22896,23356,23657,23658,24000,24173,24174,25048,25055,25069,25070,25073,
+25066,25072,25067,25046,25065,25855,25860,25853,25848,25857,25859,25852,26004,
+26075,26330,26331,26328,27333,27321,27325,27361,27334,27322,27318,27319,27335,
+27316,27309,27486,27593,27659,28679,28684,28685,28673,28677,28692,28686,28671,
+28672,28667,28710,28668,28663,28682,29185,29183,29177,29187,29181,29558,29880,
+29888,29877,29889,29886,29878,29883,29890,29972,29971,30300,30308,30297,30288,
+30291,30295,30298,30374,30397,30444,30658,30650,30975,30988,30995,30996,30985,
+30992,30994,30993,31149,31148,31327,31772,31785,31769,31776,31775,31789,31773,
+31782,31784,31778,31781,31792,32348,32336,32342,32355,32344,32354,32351,32337,
+32352,32343,32339,32693,32691,32759,32760,32885,33233,33234,33232,33375,33374,
+34228,34246,34240,34243,34242,34227,34229,34237,34247,34244,34239,34251,34254,
+34248,34245,34225,34230,34258,34340,34232,34231,34238,34409,34791,34790,34786,
+34779,34795,34794,34789,34783,34803,34788,34772,34780,34771,34797,34776,34787,
+34724,34775,34777,34817,34804,34792,34781,35155,35147,35151,35148,35142,35152,
+35153,35145,35626,35623,35619,35635,35632,35637,35655,35631,35644,35646,35633,
+35621,35639,35622,35638,35630,35620,35643,35645,35642,
+35906,35957,35993,35992,35991,36094,36100,36098,36096,36444,36450,36448,36439,
+36438,36446,36453,36455,36443,36442,36449,36445,36457,36436,36678,36679,36680,
+36683,37160,37178,37179,37182,37288,37285,37287,37295,37290,37813,37772,37778,
+37815,37787,37789,37769,37799,37774,37802,37790,37798,37781,37768,37785,37791,
+37773,37809,37777,37810,37796,37800,37812,37795,37797,38354,38355,38353,38579,
+38615,38618,24002,38623,38616,38621,38691,38690,38693,38828,38830,38824,38827,
+38820,38826,38818,38821,38871,38873,38870,38872,38906,38992,38993,38994,39096,
+39233,39228,39226,39439,39435,39433,39437,39428,39441,39434,39429,39431,39430,
+39616,39644,39688,39684,39685,39721,39733,39754,39756,39755,39879,39878,39875,
+39871,39873,39861,39864,39891,39862,39876,39865,39869,40284,40275,40271,40266,
+40283,40267,40281,40278,40268,40279,40274,40276,40287,40280,40282,40590,40588,
+40671,40705,40704,40726,40741,40747,40746,40745,40744,40780,40789,20788,20789,
+21142,21239,21428,22187,22189,22182,22183,22186,22188,22746,22749,22747,22802,
+23357,23358,23359,24003,24176,24511,25083,25863,25872,25869,25865,25868,25870,
+25988,26078,26077,26334,27367,27360,27340,27345,27353,27339,27359,27356,27344,
+27371,27343,27341,27358,27488,27568,27660,28697,28711,28704,28694,28715,28705,
+28706,28707,28713,28695,28708,28700,28714,29196,29194,29191,29186,29189,29349,
+29350,29348,29347,29345,29899,29893,29879,29891,29974,30304,30665,30666,30660,
+30705,31005,31003,31009,31004,30999,31006,31152,31335,31336,31795,31804,31801,
+31788,31803,31980,31978,32374,32373,32376,32368,32375,
+32367,32378,32370,32372,32360,32587,32586,32643,32646,32695,32765,32766,32888,
+33239,33237,33380,33377,33379,34283,34289,34285,34265,34273,34280,34266,34263,
+34284,34290,34296,34264,34271,34275,34268,34257,34288,34278,34287,34270,34274,
+34816,34810,34819,34806,34807,34825,34828,34827,34822,34812,34824,34815,34826,
+34818,35170,35162,35163,35159,35169,35164,35160,35165,35161,35208,35255,35254,
+35318,35664,35656,35658,35648,35667,35670,35668,35659,35669,35665,35650,35666,
+35671,35907,35959,35958,35994,36102,36103,36105,36268,36266,36269,36267,36461,
+36472,36467,36458,36463,36475,36546,36690,36689,36687,36688,36691,36788,37184,
+37183,37296,37293,37854,37831,37839,37826,37850,37840,37881,37868,37836,37849,
+37801,37862,37834,37844,37870,37859,37845,37828,37838,37824,37842,37863,38269,
+38362,38363,38625,38697,38699,38700,38696,38694,38835,38839,38838,38877,38878,
+38879,39004,39001,39005,38999,39103,39101,39099,39102,39240,39239,39235,39334,
+39335,39450,39445,39461,39453,39460,39451,39458,39456,39463,39459,39454,39452,
+39444,39618,39691,39690,39694,39692,39735,39914,39915,39904,39902,39908,39910,
+39906,39920,39892,39895,39916,39900,39897,39909,39893,39905,39898,40311,40321,
+40330,40324,40328,40305,40320,40312,40326,40331,40332,40317,40299,40308,40309,
+40304,40297,40325,40307,40315,40322,40303,40313,40319,40327,40296,40596,40593,
+40640,40700,40749,40768,40769,40781,40790,40791,40792,21303,22194,22197,22195,
+22755,23365,24006,24007,24302,24303,24512,24513,25081,25879,25878,25877,25875,
+26079,26344,26339,26340,27379,27376,27370,27368,27385,
+27377,27374,27375,28732,28725,28719,28727,28724,28721,28738,28728,28735,28730,
+28729,28736,28731,28723,28737,29203,29204,29352,29565,29564,29882,30379,30378,
+30398,30445,30668,30670,30671,30669,30706,31013,31011,31015,31016,31012,31017,
+31154,31342,31340,31341,31479,31817,31816,31818,31815,31813,31982,32379,32382,
+32385,32384,32698,32767,32889,33243,33241,33291,33384,33385,34338,34303,34305,
+34302,34331,34304,34294,34308,34313,34309,34316,34301,34841,34832,34833,34839,
+34835,34838,35171,35174,35257,35319,35680,35690,35677,35688,35683,35685,35687,
+35693,36270,36486,36488,36484,36697,36694,36695,36693,36696,36698,37005,37187,
+37185,37303,37301,37298,37299,37899,37907,37883,37920,37903,37908,37886,37909,
+37904,37928,37913,37901,37877,37888,37879,37895,37902,37910,37906,37882,37897,
+37880,37898,37887,37884,37900,37878,37905,37894,38366,38368,38367,38702,38703,
+38841,38843,38909,38910,39008,39010,39011,39007,39105,39106,39248,39246,39257,
+39244,39243,39251,39474,39476,39473,39468,39466,39478,39465,39470,39480,39469,
+39623,39626,39622,39696,39698,39697,39947,39944,39927,39941,39954,39928,40000,
+39943,39950,39942,39959,39956,39945,40351,40345,40356,40349,40338,40344,40336,
+40347,40352,40340,40348,40362,40343,40353,40346,40354,40360,40350,40355,40383,
+40361,40342,40358,40359,40601,40603,40602,40677,40676,40679,40678,40752,40750,
+40795,40800,40798,40797,40793,40849,20794,20793,21144,21143,22211,22205,22206,
+23368,23367,24011,24015,24305,25085,25883,27394,27388,27395,27384,27392,28739,
+28740,28746,28744,28745,28741,28742,29213,29210,29209,
+29566,29975,30314,30672,31021,31025,31023,31828,31827,31986,32394,32391,32392,
+32395,32390,32397,32589,32699,32816,33245,34328,34346,34342,34335,34339,34332,
+34329,34343,34350,34337,34336,34345,34334,34341,34857,34845,34843,34848,34852,
+34844,34859,34890,35181,35177,35182,35179,35322,35705,35704,35653,35706,35707,
+36112,36116,36271,36494,36492,36702,36699,36701,37190,37188,37189,37305,37951,
+37947,37942,37929,37949,37948,37936,37945,37930,37943,37932,37952,37937,38373,
+38372,38371,38709,38714,38847,38881,39012,39113,39110,39104,39256,39254,39481,
+39485,39494,39492,39490,39489,39482,39487,39629,39701,39703,39704,39702,39738,
+39762,39979,39965,39964,39980,39971,39976,39977,39972,39969,40375,40374,40380,
+40385,40391,40394,40399,40382,40389,40387,40379,40373,40398,40377,40378,40364,
+40392,40369,40365,40396,40371,40397,40370,40570,40604,40683,40686,40685,40731,
+40728,40730,40753,40782,40805,40804,40850,20153,22214,22213,22219,22897,23371,
+23372,24021,24017,24306,25889,25888,25894,25890,27403,27400,27401,27661,28757,
+28758,28759,28754,29214,29215,29353,29567,29912,29909,29913,29911,30317,30381,
+31029,31156,31344,31345,31831,31836,31833,31835,31834,31988,31985,32401,32591,
+32647,33246,33387,34356,34357,34355,34348,34354,34358,34860,34856,34854,34858,
+34853,35185,35263,35262,35323,35710,35716,35714,35718,35717,35711,36117,36501,
+36500,36506,36498,36496,36502,36503,36704,36706,37191,37964,37968,37962,37963,
+37967,37959,37957,37960,37961,37958,38719,38883,39018,39017,39115,39252,39259,
+39502,39507,39508,39500,39503,39496,39498,39497,39506,
+39504,39632,39705,39723,39739,39766,39765,40006,40008,39999,40004,39993,39987,
+40001,39996,39991,39988,39986,39997,39990,40411,40402,40414,40410,40395,40400,
+40412,40401,40415,40425,40409,40408,40406,40437,40405,40413,40630,40688,40757,
+40755,40754,40770,40811,40853,40866,20797,21145,22760,22759,22898,23373,24024,
+34863,24399,25089,25091,25092,25897,25893,26006,26347,27409,27410,27407,27594,
+28763,28762,29218,29570,29569,29571,30320,30676,31847,31846,32405,33388,34362,
+34368,34361,34364,34353,34363,34366,34864,34866,34862,34867,35190,35188,35187,
+35326,35724,35726,35723,35720,35909,36121,36504,36708,36707,37308,37986,37973,
+37981,37975,37982,38852,38853,38912,39510,39513,39710,39711,39712,40018,40024,
+40016,40010,40013,40011,40021,40025,40012,40014,40443,40439,40431,40419,40427,
+40440,40420,40438,40417,40430,40422,40434,40432,40418,40428,40436,40435,40424,
+40429,40642,40656,40690,40691,40710,40732,40760,40759,40758,40771,40783,40817,
+40816,40814,40815,22227,22221,23374,23661,25901,26349,26350,27411,28767,28769,
+28765,28768,29219,29915,29925,30677,31032,31159,31158,31850,32407,32649,33389,
+34371,34872,34871,34869,34891,35732,35733,36510,36511,36512,36509,37310,37309,
+37314,37995,37992,37993,38629,38726,38723,38727,38855,38885,39518,39637,39769,
+40035,40039,40038,40034,40030,40032,40450,40446,40455,40451,40454,40453,40448,
+40449,40457,40447,40445,40452,40608,40734,40774,40820,40821,40822,22228,25902,
+26040,27416,27417,27415,27418,28770,29222,29354,30680,30681,31033,31849,31851,
+31990,32410,32408,32411,32409,33248,33249,34374,34375,
+34376,35193,35194,35196,35195,35327,35736,35737,36517,36516,36515,37998,37997,
+37999,38001,38003,38729,39026,39263,40040,40046,40045,40459,40461,40464,40463,
+40466,40465,40609,40693,40713,40775,40824,40827,40826,40825,22302,28774,31855,
+34876,36274,36518,37315,38004,38008,38006,38005,39520,40052,40051,40049,40053,
+40468,40467,40694,40714,40868,28776,28773,31991,34410,34878,34877,34879,35742,
+35996,36521,36553,38731,39027,39028,39116,39265,39339,39524,39526,39527,39716,
+40469,40471,40776,25095,27422,29223,34380,36520,38018,38016,38017,39529,39528,
+39726,40473,29225,34379,35743,38019,40057,40631,30325,39531,40058,40477,28777,
+28778,40612,40830,40777,40856,30849,37561,35023,22715,24658,31911,23290,9556,
+9574,9559,9568,9580,9571,9562,9577,9565,9554,9572,9557,9566,9578,9569,9560,
+9575,9563,9555,9573,9558,9567,9579,9570,9561,9576,9564,9553,9552,9581,9582,
+9584,9583,9619,
diff --git a/system/lib/libc/musl/src/locale/codepages.h b/system/lib/libc/musl/src/locale/codepages.h
new file mode 100644
index 00000000..35acd5a3
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/codepages.h
@@ -0,0 +1,238 @@
+"iso88591\0"
+"latin1\0"
+"\0\200"
+
+"iso88592\0"
+"\0\40"
+"\0\124\0\211\22\0\40\1\6\0\0\230\101\206\32\177\0\60\110\40\0\130\40\311\22"
+"\0\44\21\306\43\0\234\121\306\32\200\120\102\210\40\132\0\0\300\4\0\20\161\1\0"
+"\35\0\160\2\0\51\0\0\300\7\41\60\1\5\0\0\130\1\0\0\136\320\1\200\35"
+"\0\0\200\6\0\133\0\0\0\5\0\24\201\1\0\36\0\200\2\0\52\0\0\0\10\42\64\21\5\0"
+"\0\134\1\0\0\137\324\1\300\35\0\0\220\106\44"
+
+"iso88593\0"
+"\0\40"
+"\0\324\0\11\0\0\4\60\3\0\0\364\100\106\13\77\0\20\100\40\0\330\0\0\0"
+"\0\0\100\3\0\0\370\120\206\13\100\0\20\200\40\0\0\0\100\0\0\154\220\1\0"
+"\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\274\0\0\0\53\0\0\0\0\0\310\41\6\0\0\0\0\100\0"
+"\0\160\240\1\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\300\0\0\0\54\0\0\0\0"
+"\0\314\61\106\44"
+
+"iso88594\0"
+"\0\40"
+"\0\124\60\4\27\0\334\140\4\0\0\230\61\102\14\154\0\60\10\0\0\130\40\111\27"
+"\0\340\160\304\43\0\234\101\202\14\155\110\101\310\24\21\0\0\0\0\0\0\0\300\16"
+"\35\0\160\2\0\45\0\0\100\16\41\70\101\105\20\0\0\0\0\0\0\340\1\0\0\0\270\1\7\0"
+"\22\0\0\0\0\0\0\0\0\17\36\0\200\2\0\46\0\0\200\16\42\74\121\205\20\0\0\0\0\0"
+"\0\344\1\0\0\0\274\21\107\44"
+
+"iso88595\0"
+"\0\40"
+"\0\210\63\16\71\345\230\163\16\72\351\250\263\16\73\355\0\340\316\73"
+"\360\304\43\317\74\364\324\143\317\75\370\344\243\317\76\374\364\343\317\77"
+"\0\5\44\320\100\4\25\144\320\101\10\45\244\320\102\14\65\344\320\103"
+"\20\105\44\321\104\24\125\144\321\105\30\145\244\321\106\34\165\344\321\107"
+"\40\205\44\322\110\44\225\144\322\111\50\245\244\322\112\54\265\344\322\113"
+"\65\302\24\223\114\63\321\124\223\115\67\341\224\223\116\73\15\300\123\117"
+
+"iso88596\0"
+"\0\40"
+"\0\4\20\100\0\0\4\20\100\0\1\4\20\100\0\163\1\20\100\0\1\4\20\100\0"
+"\1\4\20\100\0\1\4\20\0\135\1\4\20\100\135\1\330\165\27\136\171\351\265\27\137"
+"\175\371\365\27\140\201\11\66\30\141\205\31\166\30\142\211\51\266\30\143"
+"\215\71\366\130\0\1\4\20\100\0\220\105\46\331\144\224\125\146\331\145"
+"\230\145\246\331\146\234\165\346\331\147\240\205\46\132\0\1\4\20\100\0"
+"\1\4\20\100\0\1\4\20\100\0"
+
+"iso88597\0"
+"\0\40"
+"\0\220\130\42\0\63\322\10\0\0\0\0\240\11\0\0\0\20\200\210\0\0\0\0\0"
+"\233\160\322\11\0\236\174\2\12\0\241\0\40\312\50\244\224\142\312\51"
+"\250\244\242\312\52\254\264\342\312\53\260\304\42\313\54\264\324\22\200\55"
+"\267\340\222\213\56\273\360\322\213\57\277\0\23\214\60\303\20\123\214\61"
+"\307\40\223\214\62\313\60\323\214\63\317\100\23\215\64\323\120\123\215\65"
+"\327\140\223\215\66\333\160\323\215\67\337\200\23\116\0"
+
+"iso88598\0"
+"\0\40"
+"\0\4\0\0\0\0\0\0\0\0\0\0\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\360\0\0"
+"\0\0\0\100\0\1\4\20\100\0\1\4\20\100\0\1\4\20\100\0\1\4\20\100\0\1\4\20\100\0"
+"\1\4\20\100\0\1\4\20\100\0\1\4\20\300\210\123\121\125\225\125"
+"\127\141\225\225\126\133\161\325\225\127\137\201\25\226\130"
+"\143\221\125\226\131\147\241\225\226\132\153\261\325\126\0\1\170\370\141\0"
+
+"iso88599\0"
+"\0\120"
+"\55\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\364\100\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\56\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\370\120\6\0"
+
+"iso885910\0"
+"\0\40"
+"\0\124\60\102\14\71\334\20\4\0\106\204\140\6\33\203\0\0\207\24"
+"\0\130\100\202\14\72\340\40\4\0\107\210\160\106\33\204\210\30\307\24"
+"\21\0\0\0\0\0\0\0\300\16\35\0\160\2\0\45\0\0\0\0\0\70\101\5\0\0\0\0\200\33"
+"\0\340\1\0\0\0\0\0\0\0\22\0\0\0\0\0\0\0\0\17\36\0\200\2\0\46\0\0\0\0"
+"\0\74\121\5\0\0\0\0\300\33\0\344\1\0\0\0\0\0\300\20"
+
+"iso885911\0"
+"tis620\0"
+"\0\40"
+"\0\274\6\133\154\262\315\106\133\155\266\335\206\133\156\272\355\306\133\157"
+"\276\375\6\134\160\302\15\107\134\161\306\35\207\134\162\312\55\307\134\163"
+"\316\75\7\135\164\322\115\107\135\165\326\135\207\135\166\332\155\307\135\167"
+"\336\175\7\136\170\342\215\107\136\171\346\235\207\136\0\1\4\20\100\172"
+"\352\255\307\136\173\356\275\7\137\174\362\315\107\137\175\366\335\207\137\176"
+"\372\355\307\137\177\376\375\7\140\200\2\16\110\140\201\1\4\20\100\0"
+
+"iso885913\0"
+"\0\40"
+"\0\240\10\0\0\0\244\10\0\0\15\0\300\5\0\0\0\0\300\2\0\0\0\0\0\47\2\0\0\0"
+"\20\0\320\5\0\0\0\0\200\3\25\354\20\301\5\0\0\160\302\10\35\0\360\107\11"
+"\61\4\221\203\21\146\60\341\4\0\124\0\0\0\0\170\50\1\6\34\0\4\62\10\0"
+"\26\360\40\1\6\0\0\200\2\11\36\0\0\210\11\62\10\241\303\21\147\64\361\4\0"
+"\125\0\0\0\0\171\54\21\106\34\0\10\102\110\211"
+
+"iso885914\0"
+"\0\40"
+"\0\30\170\40\0\33\160\200\40\0\24\2\140\141\202\32\2\0\200\37\12\56\370\2\14"
+"\14\66\10\200\203\25\76\170\41\204\33\142\230\141\204\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\172\0\0\0\0\0\0\0\200\204\0\0\0\0\0\0\0\300\7\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\173\0\0\0\0\0\0\0\300\204\0\0\0\0\0\0\0\320\7\0"
+
+"iso885915\0"
+"latin9\0"
+"\0\44"
+"\63\2\140\6\0\147\0\0\0\0\0\0\0\0\0\0\0\0\0\0\203\0\0\0\0\204\0\0\0\0"
+"\130\144\341\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+
+"iso885916\0"
+"\0\40"
+"\0\124\140\201\22\63\246\150\6\0\147\0\240\10\0\177\0\0\110\40\0\0\320\301\22"
+"\203\240\10\0\0\204\170\260\10\0\130\144\341\207\40\0\0\0\300\4\0\134\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\41\60\1\0\0\0\130\1\0\30\166\0\0\0\0\0\234\300\10\0"
+"\0\0\0\0\5\0\140\0\0\0\0\0\0\0\0\0\0\0\0\0\42\64\1\0\0\0\134\1\100\30"
+"\167\0\0\0\0\0\240\320\10\0"
+
+"cp1250\0"
+"windows1250\0"
+"\0\0"
+"\63\6\140\142\0\51\266\250\342\212\1\270\150\306\213\140\250\61\310\37"
+"\1\220\130\342\211\50\262\10\142\210\1\330\170\6\214\141\254\101\10\40"
+"\0\74\2\211\22\0\124\0\0\0\0\0\100\6\0\0\0\0\100\40\0\0\40\311\22\0\0\0\0\0"
+"\0\130\120\6\0\110\120\222\204\40\132\0\0\300\4\0\20\161\1\0\35\0\160\2\0"
+"\51\0\0\300\7\41\60\1\5\0\0\130\1\0\0\136\320\1\200\35\0\0\200\6\0\133\0\0\0\5"
+"\0\24\201\1\0\36\0\200\2\0\52\0\0\0\10\42\64\21\5\0\0\134\1\0\0"
+"\137\324\1\300\35\0\0\220\106\44"
+
+"cp1251\0"
+"windows1251\0"
+"\0\0"
+"\343\220\143\242\114\51\266\250\342\212\63\272\250\316\213\353\264\303\316\73"
+"\61\221\130\342\211\50\262\10\142\210\1\330\210\23\214\71\355\244\123\117"
+"\0\270\303\123\72\0\370\4\0\0\342\0\120\16\0\0\0\0\0\72\0\0\160\116\115"
+"\77\1\0\0\0\60\325\70\23\0\67\231\103\223\115\360\304\43\317\74"
+"\364\324\143\317\75\370\344\243\317\76\374\364\343\317\77\0\5\44\320\100"
+"\4\25\144\320\101\10\45\244\320\102\14\65\344\320\103\20\105\44\321\104"
+"\24\125\144\321\105\30\145\244\321\106\34\165\344\321\107\40\205\44\322\110"
+"\44\225\144\322\111\50\245\244\322\112\54\265\344\322\113"
+
+"cp1252\0"
+"windows1252\0"
+"\0\0"
+"\63\6\140\142\41\51\266\250\342\212\216\270\150\306\213\130\4\60\110\0"
+"\1\220\130\342\211\50\262\10\142\210\223\330\170\6\214\131\4\100\210\37"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+
+"cp1253\0"
+"windows1253\0"
+"\0\0"
+"\63\6\140\142\41\51\266\250\342\212\1\270\30\300\213\1\4\20\100\0"
+"\1\220\130\342\211\50\262\10\142\210\1\330\30\0\214\1\4\20\100\0"
+"\0\160\322\11\0\0\0\0\0\0\0\0\20\0\0\0\0\0\200\210\0\0\0\0\0\233\0\0\0\0"
+"\236\174\2\12\0\241\0\40\312\50\244\224\142\312\51\250\244\242\312\52"
+"\254\264\342\312\53\260\304\42\313\54\264\324\22\200\55\267\340\222\213\56"
+"\273\360\322\213\57\277\0\23\214\60\303\20\123\214\61\307\40\223\214\62"
+"\313\60\323\214\63\317\100\23\215\64\323\120\123\215\65\327\140\223\215\66"
+"\333\160\323\215\67\337\200\23\116\0"
+
+"cp1254\0"
+"windows1254\0"
+"\0\0"
+"\63\6\140\142\41\51\266\250\342\212\216\270\150\306\213\130\4\20\100\0"
+"\1\220\130\342\211\50\262\10\142\210\223\330\170\6\214\131\4\20\200\37"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\55\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\364\100\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\56\0\0\0\0"
+"\0\0\0\0\0\0\0\0\0\0\0\370\120\6\0"
+
+"cp1255\0"
+"windows1255\0"
+"\0\0"
+"\63\6\140\142\41\51\266\250\342\212\216\270\30\300\213\1\4\20\100\0"
+"\1\220\130\342\211\50\262\10\142\210\223\330\30\0\214\1\4\20\100\0\0\0\0\0\0"
+"\61\2\0\0\0\0\0\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\360\0\0\0\0\0\0\0"
+"\100\5\45\324\120\104\25\145\324\121\110\45\25\200\122\113\61\325\224\123"
+"\117\101\25\225\124\156\275\5\127\134\162\5\20\100\0\1\4\20\100\0"
+"\123\121\125\225\125\127\141\225\225\126\133\161\325\225\127"
+"\137\201\25\226\130\143\221\125\226\131\147\241\225\226\132\153\261\325\126\0"
+"\1\170\370\141\0"
+
+"cp1256\0"
+"windows1256\0"
+"\0\0"
+"\63\222\146\142\41\51\266\250\342\212\216\270\70\332\213\130\224\206\232\151"
+"\252\221\130\342\211\50\262\10\142\210\251\331\170\32\214\131\160\330\341\152"
+"\0\314\5\0\0\0\0\0\0\0\0\0\300\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\100\27\0"
+"\0\0\0\100\135\255\331\165\27\136\171\351\265\27\137\175\371\365\27\140"
+"\201\11\66\30\141\205\31\166\30\142\211\51\266\30\0\214\65\346\330\143"
+"\220\105\46\331\144\0\120\6\100\145\226\135\206\31\0\0\0\0\0\0\231\151\6\0\0"
+"\233\161\326\231\147\0\174\6\32\0\241\1\40\32\0\0\170\370\241\153"
+
+"cp1257\0"
+"windows1257\0"
+"\0\0"
+"\63\6\140\142\0\51\266\250\342\212\1\270\30\300\213\1\20\360\210\2"
+"\1\220\130\342\211\50\262\10\142\210\1\330\30\0\214\1\30\40\111\0\0\4\0\0\0"
+"\0\4\0\0\0\15\0\300\5\0\0\0\0\300\2\0\0\0\0\0\0\0\0\0\0\20\0\320\5\0"
+"\0\0\0\200\3\25\354\20\301\5\0\0\160\302\10\35\0\360\107\11\61\4\221\203\21"
+"\146\60\341\4\0\124\0\0\0\0\170\50\1\6\34\0\4\62\10\0\26\360\40\1\6"
+"\0\0\200\2\11\36\0\0\210\11\62\10\241\303\21\147\64\361\4\0\125\0\0\0\0"
+"\171\54\21\106\34\0\10\102\110\44"
+
+"cp1258\0"
+"windows1258\0"
+"\0\0"
+"\63\6\140\142\41\51\266\250\342\212\216\270\30\300\213\130\4\20\100\0"
+"\1\220\130\342\211\50\262\10\142\210\223\330\30\0\214\131\4\20\200\37"
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+"\0\0\0\0\0\0\0\0\300\4\0\0\0\0\0\0\0\0\0\0\225\0\0\0\0\41\0\200\11\0"
+"\0\30\2\0\0\0\0\0\0\0\0\40\162\11\0\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\226\0\0\0\0"
+"\42\0\220\11\0\0\34\2\0\0\0\0\0\0\0\0\44\42\43\0"
+
+"koi8r\0"
+"\0\0"
+"\76\376\10\144\220\102\16\111\144\221\106\36\211\244\231\147\242\231\246\232"
+"\153\262\331\46\217\156\336\210\143\216\72\356\50\100\217\7\40\220\300\3"
+"\111\52\271\44\114\114\66\351\344\223\120\106\51\345\224\124\126\151\345\225"
+"\130\146\251\245\70\133\162\331\245\227\137\202\31\246\230\143\222\131\146\1"
+"\56\101\24\221\111\24\125\104\322\104\45\141\224\221\106\33\161\324\221\107"
+"\37\275\4\122\110\42\215\144\221\104\54\255\164\21\112\55\245\164\222\112"
+"\16\301\23\217\101\364\324\103\320\74\5\341\223\217\76\373\360\323\217\77"
+"\377\74\4\120\100\2\15\144\217\74\14\55\164\17\102\15\45\164\220\102"
+
+"koi8u\0"
+"\0\0"
+"\76\376\10\144\220\102\16\111\144\221\106\36\211\244\231\147\242\231\246\232"
+"\153\262\331\46\217\156\336\210\143\216\72\356\50\100\217\7\40\220\300\3"
+"\111\52\271\44\114\63\65\131\223\115\120\106\51\345\224\124\376\144\345\225"
+"\130\146\251\245\70\345\160\171\16\72\137\202\31\246\230\143\372\124\146\1"
+"\56\101\24\221\111\24\125\104\322\104\45\141\224\221\106\33\161\324\221\107"
+"\37\275\4\122\110\42\215\144\221\104\54\255\164\21\112\55\245\164\222\112"
+"\16\301\23\217\101\364\324\103\320\74\5\341\223\217\76\373\360\323\217\77"
+"\377\74\4\120\100\2\15\144\217\74\14\55\164\17\102\15\45\164\220\102"
+
diff --git a/system/lib/libc/musl/src/locale/gb18030.h b/system/lib/libc/musl/src/locale/gb18030.h
new file mode 100644
index 00000000..5aceb329
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/gb18030.h
@@ -0,0 +1,1836 @@
+19970,19972,19973,19974,19983,19986,19991,19999,20000,20001,20003,20006,20009,
+20014,20015,20017,20019,20021,20023,20028,20032,20033,20034,20036,20038,20042,
+20049,20053,20055,20058,20059,20066,20067,20068,20069,20071,20072,20074,20075,
+20076,20077,20078,20079,20082,20084,20085,20086,20087,20088,20089,20090,20091,
+20092,20093,20095,20096,20097,20098,20099,20100,20101,20103,20106,20112,20118,
+20119,20121,20124,20125,20126,20131,20138,20143,20144,20145,20148,20150,20151,
+20152,20153,20156,20157,20158,20168,20172,20175,20176,20178,20186,20187,20188,
+20192,20194,20198,20199,20201,20205,20206,20207,20209,20212,20216,20217,20218,
+20220,20222,20224,20226,20227,20228,20229,20230,20231,20232,20235,20236,20242,
+20243,20244,20245,20246,20252,20253,20257,20259,20264,20265,20268,20269,20270,
+20273,20275,20277,20279,20281,20283,20286,20287,20288,20289,20290,20292,20293,
+20295,20296,20297,20298,20299,20300,20306,20308,20310,20321,20322,20326,20328,
+20330,20331,20333,20334,20337,20338,20341,20343,20344,20345,20346,20349,20352,
+20353,20354,20357,20358,20359,20362,20364,20366,20368,20370,20371,20373,20374,
+20376,20377,20378,20380,20382,20383,20385,20386,20388,20395,20397,20400,20401,
+20402,20403,20404,20406,20407,20408,20409,20410,20411,20412,20413,20414,20416,
+20417,20418,20422,20423,20424,20425,20427,20428,20429,20434,20435,20436,20437,
+20438,20441,20443,20448,20450,20452,20453,20455,20459,20460,20464,20466,20468,
+20469,20470,20471,20473,20475,20476,20477,20479,20480,20481,20482,20483,20484,
+20485,20486,20487,20488,20489,20490,20491,20494,20496,20497,20499,20501,20502,
+20503,20507,20509,20510,20512,20514,20515,20516,20519,20523,20527,20528,20529,
+20530,20531,20532,20533,20534,20535,20536,20537,20539,20541,20543,20544,20545,
+20546,20548,20549,20550,20553,20554,20555,20557,20560,20561,20562,20563,20564,
+20566,20567,20568,20569,20571,20573,20574,20575,20576,20577,20578,20579,20580,
+20582,20583,20584,20585,20586,20587,20589,20590,20591,20592,20593,20594,20595,
+20596,20597,20600,20601,20602,20604,20605,20609,20610,20611,20612,20614,20615,
+20617,20618,20619,20620,20622,20623,20624,20625,20626,20627,20628,20629,20630,
+20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20644,
+20646,20650,20651,20653,20654,20655,20656,20657,20659,20660,20661,20662,20663,
+20664,20665,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,
+20679,20680,20681,20682,20683,20684,20685,20686,20688,20689,20690,20691,20692,
+20693,20695,20696,20697,20699,20700,20701,20702,20703,20704,20705,20706,20707,
+20708,20709,20712,20713,20714,20715,20719,20720,20721,20722,20724,20726,20727,
+20728,20729,20730,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,
+20744,20745,20746,20748,20749,20750,20751,20752,20753,20755,20756,20757,20758,
+20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20770,20771,20772,
+20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,
+20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,
+20802,20807,20810,20812,20814,20815,20816,20818,20819,20823,20824,20825,20827,
+20829,20830,20831,20832,20833,20835,20836,20838,20839,20841,20842,20847,20850,
+20858,20862,20863,20867,20868,20870,20871,20874,20875,20878,20879,20880,20881,
+20883,20884,20888,20890,20893,20894,20895,20897,20899,20902,20903,20904,20905,
+20906,20909,20910,20916,20920,20921,20922,20926,20927,20929,20930,20931,20933,
+20936,20938,20941,20942,20944,20946,20947,20948,20949,20950,20951,20952,20953,
+20954,20956,20958,20959,20962,20963,20965,20966,20967,20968,20969,20970,20972,
+20974,20977,20978,20980,20983,20990,20996,20997,21001,21003,21004,21007,21008,
+21011,21012,21013,21020,21022,21023,21025,21026,21027,21029,21030,21031,21034,
+21036,21039,21041,21042,21044,21045,21052,21054,21060,21061,21062,21063,21064,
+21065,21067,21070,21071,21074,21075,21077,21079,21080,21081,21082,21083,21085,
+21087,21088,21090,21091,21092,21094,21096,21099,21100,21101,21102,21104,21105,
+21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21118,21120,21123,
+21124,21125,21126,21127,21129,21130,21131,21132,21133,21134,21135,21137,21138,
+21140,21141,21142,21143,21144,21145,21146,21148,21156,21157,21158,21159,21166,
+21167,21168,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21184,
+21185,21186,21188,21189,21190,21192,21194,21196,21197,21198,21199,21201,21203,
+21204,21205,21207,21209,21210,21211,21212,21213,21214,21216,21217,21218,21219,
+21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21233,21234,
+21235,21236,21237,21238,21239,21240,21243,21244,21245,21249,21250,21251,21252,
+21255,21257,21258,21259,21260,21262,21265,21266,21267,21268,21272,21275,21276,
+21278,21279,21282,21284,21285,21287,21288,21289,21291,21292,21293,21295,21296,
+21297,21298,21299,21300,21301,21302,21303,21304,21308,21309,21312,21314,21316,
+21318,21323,21324,21325,21328,21332,21336,21337,21339,21341,21349,21352,21354,
+21356,21357,21362,21366,21369,21371,21372,21373,21374,21376,21377,21379,21383,
+21384,21386,21390,21391,21392,21393,21394,21395,21396,21398,21399,21401,21403,
+21404,21406,21408,21409,21412,21415,21418,21419,21420,21421,21423,21424,21425,
+21426,21427,21428,21429,21431,21432,21433,21434,21436,21437,21438,21440,21443,
+21444,21445,21446,21447,21454,21455,21456,21458,21459,21461,21466,21468,21469,
+21470,21473,21474,21479,21492,21498,21502,21503,21504,21506,21509,21511,21515,
+21524,21528,21529,21530,21532,21538,21540,21541,21546,21552,21555,21558,21559,
+21562,21565,21567,21569,21570,21572,21573,21575,21577,21580,21581,21582,21583,
+21585,21594,21597,21598,21599,21600,21601,21603,21605,21607,21609,21610,21611,
+21612,21613,21614,21615,21616,21620,21625,21626,21630,21631,21633,21635,21637,
+21639,21640,21641,21642,21645,21649,21651,21655,21656,21660,21662,21663,21664,
+21665,21666,21669,21678,21680,21682,21685,21686,21687,21689,21690,21692,21694,
+21699,21701,21706,21707,21718,21720,21723,21728,21729,21730,21731,21732,21739,
+21740,21743,21744,21745,21748,21749,21750,21751,21752,21753,21755,21758,21760,
+21762,21763,21764,21765,21768,21770,21771,21772,21773,21774,21778,21779,21781,
+21782,21783,21784,21785,21786,21788,21789,21790,21791,21793,21797,21798,21800,
+21801,21803,21805,21810,21812,21813,21814,21816,21817,21818,21819,21821,21824,
+21826,21829,21831,21832,21835,21836,21837,21838,21839,21841,21842,21843,21844,
+21847,21848,21849,21850,21851,21853,21854,21855,21856,21858,21859,21864,21865,
+21867,21871,21872,21873,21874,21875,21876,21881,21882,21885,21887,21893,21894,
+21900,21901,21902,21904,21906,21907,21909,21910,21911,21914,21915,21918,21920,
+21921,21922,21923,21924,21925,21926,21928,21929,21930,21931,21932,21933,21934,
+21935,21936,21938,21940,21942,21944,21946,21948,21951,21952,21953,21954,21955,
+21958,21959,21960,21962,21963,21966,21967,21968,21973,21975,21976,21977,21978,
+21979,21982,21984,21986,21991,21993,21997,21998,22000,22001,22004,22006,22008,
+22009,22010,22011,22012,22015,22018,22019,22020,22021,22022,22023,22026,22027,
+22029,22032,22033,22034,22035,22036,22037,22038,22039,22041,22042,22044,22045,
+22048,22049,22050,22053,22054,22056,22057,22058,22059,22062,22063,22064,22067,
+22069,22071,22072,22074,22076,22077,22078,22080,22081,22082,22083,22084,22085,
+22086,22087,22088,22089,22090,22091,22095,22096,22097,22098,22099,22101,22102,
+22106,22107,22109,22110,22111,22112,22113,22115,22117,22118,22119,22125,22126,
+22127,22128,22130,22131,22132,22133,22135,22136,22137,22138,22141,22142,22143,
+22144,22145,22146,22147,22148,22151,22152,22153,22154,22155,22156,22157,22160,
+22161,22162,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,
+22175,22176,22177,22178,22180,22181,22182,22183,22184,22185,22186,22187,22188,
+22189,22190,22192,22193,22194,22195,22196,22197,22198,22200,22201,22202,22203,
+22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,
+22219,22220,22221,22222,22223,22224,22225,22226,22227,22229,22230,22232,22233,
+22236,22243,22245,22246,22247,22248,22249,22250,22252,22254,22255,22258,22259,
+22262,22263,22264,22267,22268,22272,22273,22274,22277,22279,22283,22284,22285,
+22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,
+22299,22301,22302,22304,22305,22306,22308,22309,22310,22311,22315,22321,22322,
+22324,22325,22326,22327,22328,22332,22333,22335,22337,22339,22340,22341,22342,
+22344,22345,22347,22354,22355,22356,22357,22358,22360,22361,22370,22371,22373,
+22375,22380,22382,22384,22385,22386,22388,22389,22392,22393,22394,22397,22398,
+22399,22400,22401,22407,22408,22409,22410,22413,22414,22415,22416,22417,22420,
+22421,22422,22423,22424,22425,22426,22428,22429,22430,22431,22437,22440,22442,
+22444,22447,22448,22449,22451,22453,22454,22455,22457,22458,22459,22460,22461,
+22462,22463,22464,22465,22468,22469,22470,22471,22472,22473,22474,22476,22477,
+22480,22481,22483,22486,22487,22491,22492,22494,22497,22498,22499,22501,22502,
+22503,22504,22505,22506,22507,22508,22510,22512,22513,22514,22515,22517,22518,
+22519,22523,22524,22526,22527,22529,22531,22532,22533,22536,22537,22538,22540,
+22542,22543,22544,22546,22547,22548,22550,22551,22552,22554,22555,22556,22557,
+22559,22562,22563,22565,22566,22567,22568,22569,22571,22572,22573,22574,22575,
+22577,22578,22579,22580,22582,22583,22584,22585,22586,22587,22588,22589,22590,
+22591,22592,22593,22594,22595,22597,22598,22599,22600,22601,22602,22603,22606,
+22607,22608,22610,22611,22613,22614,22615,22617,22618,22619,22620,22621,22623,
+22624,22625,22626,22627,22628,22630,22631,22632,22633,22634,22637,22638,22639,
+22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,
+22653,22655,22658,22660,22662,22663,22664,22666,22667,22668,22669,22670,22671,
+22672,22673,22676,22677,22678,22679,22680,22683,22684,22685,22688,22689,22690,
+22691,22692,22693,22694,22695,22698,22699,22700,22701,22702,22703,22704,22705,
+22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22717,22718,22719,
+22720,22722,22723,22724,22726,22727,22728,22729,22730,22731,22732,22733,22734,
+22735,22736,22738,22739,22740,22742,22743,22744,22745,22746,22747,22748,22749,
+22750,22751,22752,22753,22754,22755,22757,22758,22759,22760,22761,22762,22765,
+22767,22769,22770,22772,22773,22775,22776,22778,22779,22780,22781,22782,22783,
+22784,22785,22787,22789,22790,22792,22793,22794,22795,22796,22798,22800,22801,
+22802,22803,22807,22808,22811,22813,22814,22816,22817,22818,22819,22822,22824,
+22828,22832,22834,22835,22837,22838,22843,22845,22846,22847,22848,22851,22853,
+22854,22858,22860,22861,22864,22866,22867,22873,22875,22876,22877,22878,22879,
+22881,22883,22884,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,
+22896,22897,22898,22901,22903,22906,22907,22908,22910,22911,22912,22917,22921,
+22923,22924,22926,22927,22928,22929,22932,22933,22936,22938,22939,22940,22941,
+22943,22944,22945,22946,22950,22951,22956,22957,22960,22961,22963,22964,22965,
+22966,22967,22968,22970,22972,22973,22975,22976,22977,22978,22979,22980,22981,
+22983,22984,22985,22988,22989,22990,22991,22997,22998,23001,23003,23006,23007,
+23008,23009,23010,23012,23014,23015,23017,23018,23019,23021,23022,23023,23024,
+23025,23026,23027,23028,23029,23030,23031,23032,23034,23036,23037,23038,23040,
+23042,23050,23051,23053,23054,23055,23056,23058,23060,23061,23062,23063,23065,
+23066,23067,23069,23070,23073,23074,23076,23078,23079,23080,23082,23083,23084,
+23085,23086,23087,23088,23091,23093,23095,23096,23097,23098,23099,23101,23102,
+23103,23105,23106,23107,23108,23109,23111,23112,23115,23116,23117,23118,23119,
+23120,23121,23122,23123,23124,23126,23127,23128,23129,23131,23132,23133,23134,
+23135,23136,23137,23139,23140,23141,23142,23144,23145,23147,23148,23149,23150,
+23151,23152,23153,23154,23155,23160,23161,23163,23164,23165,23166,23168,23169,
+23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,
+23183,23184,23185,23187,23188,23189,23190,23191,23192,23193,23196,23197,23198,
+23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23211,23212,
+23213,23214,23215,23216,23217,23220,23222,23223,23225,23226,23227,23228,23229,
+23231,23232,23235,23236,23237,23238,23239,23240,23242,23243,23245,23246,23247,
+23248,23249,23251,23253,23255,23257,23258,23259,23261,23262,23263,23266,23268,
+23269,23271,23272,23274,23276,23277,23278,23279,23280,23282,23283,23284,23285,
+23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,
+23299,23300,23301,23302,23303,23304,23306,23307,23308,23309,23310,23311,23312,
+23313,23314,23315,23316,23317,23320,23321,23322,23323,23324,23325,23326,23327,
+23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,
+23341,23342,23343,23344,23345,23347,23349,23350,23352,23353,23354,23355,23356,
+23357,23358,23359,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,
+23371,23372,23373,23374,23375,23378,23382,23390,23392,23393,23399,23400,23403,
+23405,23406,23407,23410,23412,23414,23415,23416,23417,23419,23420,23422,23423,
+23426,23430,23434,23437,23438,23440,23441,23442,23444,23446,23455,23463,23464,
+23465,23468,23469,23470,23471,23473,23474,23479,23482,23483,23484,23488,23489,
+23491,23496,23497,23498,23499,23501,23502,23503,23505,23508,23509,23510,23511,
+23512,23513,23514,23515,23516,23520,23522,23523,23526,23527,23529,23530,23531,
+23532,23533,23535,23537,23538,23539,23540,23541,23542,23543,23549,23550,23552,
+23554,23555,23557,23559,23560,23563,23564,23565,23566,23568,23570,23571,23575,
+23577,23579,23582,23583,23584,23585,23587,23590,23592,23593,23594,23595,23597,
+23598,23599,23600,23602,23603,23605,23606,23607,23619,23620,23622,23623,23628,
+23629,23634,23635,23636,23638,23639,23640,23642,23643,23644,23645,23647,23650,
+23652,23655,23656,23657,23658,23659,23660,23661,23664,23666,23667,23668,23669,
+23670,23671,23672,23675,23676,23677,23678,23680,23683,23684,23685,23686,23687,
+23689,23690,23691,23694,23695,23698,23699,23701,23709,23710,23711,23712,23713,
+23716,23717,23718,23719,23720,23722,23726,23727,23728,23730,23732,23734,23737,
+23738,23739,23740,23742,23744,23746,23747,23749,23750,23751,23752,23753,23754,
+23756,23757,23758,23759,23760,23761,23763,23764,23765,23766,23767,23768,23770,
+23771,23772,23773,23774,23775,23776,23778,23779,23783,23785,23787,23788,23790,
+23791,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23804,23805,
+23806,23807,23808,23809,23812,23813,23816,23817,23818,23819,23820,23821,23823,
+23824,23825,23826,23827,23829,23831,23832,23833,23834,23836,23837,23839,23840,
+23841,23842,23843,23845,23848,23850,23851,23852,23855,23856,23857,23858,23859,
+23861,23862,23863,23864,23865,23866,23867,23868,23871,23872,23873,23874,23875,
+23876,23877,23878,23880,23881,23885,23886,23887,23888,23889,23890,23891,23892,
+23893,23894,23895,23897,23898,23900,23902,23903,23904,23905,23906,23907,23908,
+23909,23910,23911,23912,23914,23917,23918,23920,23921,23922,23923,23925,23926,
+23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23939,23940,
+23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,
+23954,23955,23956,23957,23958,23959,23960,23962,23963,23964,23966,23967,23968,
+23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,
+23982,23983,23984,23985,23986,23987,23988,23989,23990,23992,23993,23994,23995,
+23996,23997,23998,23999,24000,24001,24002,24003,24004,24006,24007,24008,24009,
+24010,24011,24012,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,
+24024,24025,24026,24028,24031,24032,24035,24036,24042,24044,24045,24048,24053,
+24054,24056,24057,24058,24059,24060,24063,24064,24068,24071,24073,24074,24075,
+24077,24078,24082,24083,24087,24094,24095,24096,24097,24098,24099,24100,24101,
+24104,24105,24106,24107,24108,24111,24112,24114,24115,24116,24117,24118,24121,
+24122,24126,24127,24128,24129,24131,24134,24135,24136,24137,24138,24139,24141,
+24142,24143,24144,24145,24146,24147,24150,24151,24152,24153,24154,24156,24157,
+24159,24160,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,
+24174,24175,24176,24177,24181,24183,24185,24190,24193,24194,24195,24197,24200,
+24201,24204,24205,24206,24210,24216,24219,24221,24225,24226,24227,24228,24232,
+24233,24234,24235,24236,24238,24239,24240,24241,24242,24244,24250,24251,24252,
+24253,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24267,24268,
+24269,24270,24271,24272,24276,24277,24279,24280,24281,24282,24284,24285,24286,
+24287,24288,24289,24290,24291,24292,24293,24294,24295,24297,24299,24300,24301,
+24302,24303,24304,24305,24306,24307,24309,24312,24313,24315,24316,24317,24325,
+24326,24327,24329,24332,24333,24334,24336,24338,24340,24342,24345,24346,24348,
+24349,24350,24353,24354,24355,24356,24360,24363,24364,24366,24368,24370,24371,
+24372,24373,24374,24375,24376,24379,24381,24382,24383,24385,24386,24387,24388,
+24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24401,24404,
+24409,24410,24411,24412,24414,24415,24416,24419,24421,24423,24424,24427,24430,
+24431,24434,24436,24437,24438,24440,24442,24445,24446,24447,24451,24454,24461,
+24462,24463,24465,24467,24468,24470,24474,24475,24477,24478,24479,24480,24482,
+24483,24484,24485,24486,24487,24489,24491,24492,24495,24496,24497,24498,24499,
+24500,24502,24504,24505,24506,24507,24510,24511,24512,24513,24514,24519,24520,
+24522,24523,24526,24531,24532,24533,24538,24539,24540,24542,24543,24546,24547,
+24549,24550,24552,24553,24556,24559,24560,24562,24563,24564,24566,24567,24569,
+24570,24572,24583,24584,24585,24587,24588,24592,24593,24595,24599,24600,24602,
+24606,24607,24610,24611,24612,24620,24621,24622,24624,24625,24626,24627,24628,
+24630,24631,24632,24633,24634,24637,24638,24640,24644,24645,24646,24647,24648,
+24649,24650,24652,24654,24655,24657,24659,24660,24662,24663,24664,24667,24668,
+24670,24671,24672,24673,24677,24678,24686,24689,24690,24692,24693,24695,24702,
+24704,24705,24706,24709,24710,24711,24712,24714,24715,24718,24719,24720,24721,
+24723,24725,24727,24728,24729,24732,24734,24737,24738,24740,24741,24743,24745,
+24746,24750,24752,24755,24757,24758,24759,24761,24762,24765,24766,24767,24768,
+24769,24770,24771,24772,24775,24776,24777,24780,24781,24782,24783,24784,24786,
+24787,24788,24790,24791,24793,24795,24798,24801,24802,24803,24804,24805,24810,
+24817,24818,24821,24823,24824,24827,24828,24829,24830,24831,24834,24835,24836,
+24837,24839,24842,24843,24844,24848,24849,24850,24851,24852,24854,24855,24856,
+24857,24859,24860,24861,24862,24865,24866,24869,24872,24873,24874,24876,24877,
+24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,
+24891,24892,24893,24894,24896,24897,24898,24899,24900,24901,24902,24903,24905,
+24907,24909,24911,24912,24914,24915,24916,24918,24919,24920,24921,24922,24923,
+24924,24926,24927,24928,24929,24931,24932,24933,24934,24937,24938,24939,24940,
+24941,24942,24943,24945,24946,24947,24948,24950,24952,24953,24954,24955,24956,
+24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,
+24970,24972,24973,24975,24976,24977,24978,24979,24981,24982,24983,24984,24985,
+24986,24987,24988,24990,24991,24992,24993,24994,24995,24996,24997,24998,25002,
+25003,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25016,25017,
+25018,25019,25020,25021,25023,25024,25025,25027,25028,25029,25030,25031,25033,
+25036,25037,25038,25039,25040,25043,25045,25046,25047,25048,25049,25050,25051,
+25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25063,25064,25065,
+25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25078,25079,
+25080,25081,25082,25083,25084,25085,25086,25088,25089,25090,25091,25092,25093,
+25095,25097,25107,25108,25113,25116,25117,25118,25120,25123,25126,25127,25128,
+25129,25131,25133,25135,25136,25137,25138,25141,25142,25144,25145,25146,25147,
+25148,25154,25156,25157,25158,25162,25167,25168,25173,25174,25175,25177,25178,
+25180,25181,25182,25183,25184,25185,25186,25188,25189,25192,25201,25202,25204,
+25205,25207,25208,25210,25211,25213,25217,25218,25219,25221,25222,25223,25224,
+25227,25228,25229,25230,25231,25232,25236,25241,25244,25245,25246,25251,25254,
+25255,25257,25258,25261,25262,25263,25264,25266,25267,25268,25270,25271,25272,
+25274,25278,25280,25281,25283,25291,25295,25297,25301,25309,25310,25312,25313,
+25316,25322,25323,25328,25330,25333,25336,25337,25338,25339,25344,25347,25348,
+25349,25350,25354,25355,25356,25357,25359,25360,25362,25363,25364,25365,25367,
+25368,25369,25372,25382,25383,25385,25388,25389,25390,25392,25393,25395,25396,
+25397,25398,25399,25400,25403,25404,25406,25407,25408,25409,25412,25415,25416,
+25418,25425,25426,25427,25428,25430,25431,25432,25433,25434,25435,25436,25437,
+25440,25444,25445,25446,25448,25450,25451,25452,25455,25456,25458,25459,25460,
+25461,25464,25465,25468,25469,25470,25471,25473,25475,25476,25477,25478,25483,
+25485,25489,25491,25492,25493,25495,25497,25498,25499,25500,25501,25502,25503,
+25505,25508,25510,25515,25519,25521,25522,25525,25526,25529,25531,25533,25535,
+25536,25537,25538,25539,25541,25543,25544,25546,25547,25548,25553,25555,25556,
+25557,25559,25560,25561,25562,25563,25564,25565,25567,25570,25572,25573,25574,
+25575,25576,25579,25580,25582,25583,25584,25585,25587,25589,25591,25593,25594,
+25595,25596,25598,25603,25604,25606,25607,25608,25609,25610,25613,25614,25617,
+25618,25621,25622,25623,25624,25625,25626,25629,25631,25634,25635,25636,25637,
+25639,25640,25641,25643,25646,25647,25648,25649,25650,25651,25653,25654,25655,
+25656,25657,25659,25660,25662,25664,25666,25667,25673,25675,25676,25677,25678,
+25679,25680,25681,25683,25685,25686,25687,25689,25690,25691,25692,25693,25695,
+25696,25697,25698,25699,25700,25701,25702,25704,25706,25707,25708,25710,25711,
+25712,25713,25714,25715,25716,25717,25718,25719,25723,25724,25725,25726,25727,
+25728,25729,25731,25734,25736,25737,25738,25739,25740,25741,25742,25743,25744,
+25747,25748,25751,25752,25754,25755,25756,25757,25759,25760,25761,25762,25763,
+25765,25766,25767,25768,25770,25771,25775,25777,25778,25779,25780,25782,25785,
+25787,25789,25790,25791,25793,25795,25796,25798,25799,25800,25801,25802,25803,
+25804,25807,25809,25811,25812,25813,25814,25817,25818,25819,25820,25821,25823,
+25824,25825,25827,25829,25831,25832,25833,25834,25835,25836,25837,25838,25839,
+25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,
+25853,25854,25855,25857,25858,25859,25860,25861,25862,25863,25864,25866,25867,
+25868,25869,25870,25871,25872,25873,25875,25876,25877,25878,25879,25881,25882,
+25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25894,25895,25896,
+25897,25898,25900,25901,25904,25905,25906,25907,25911,25914,25916,25917,25920,
+25921,25922,25923,25924,25926,25927,25930,25931,25933,25934,25936,25938,25939,
+25940,25943,25944,25946,25948,25951,25952,25953,25956,25957,25959,25960,25961,
+25962,25965,25966,25967,25969,25971,25973,25974,25976,25977,25978,25979,25980,
+25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25992,25993,25994,
+25997,25998,25999,26002,26004,26005,26006,26008,26010,26013,26014,26016,26018,
+26019,26022,26024,26026,26028,26030,26033,26034,26035,26036,26037,26038,26039,
+26040,26042,26043,26046,26047,26048,26050,26055,26056,26057,26058,26061,26064,
+26065,26067,26068,26069,26072,26073,26074,26075,26076,26077,26078,26079,26081,
+26083,26084,26090,26091,26098,26099,26100,26101,26104,26105,26107,26108,26109,
+26110,26111,26113,26116,26117,26119,26120,26121,26123,26125,26128,26129,26130,
+26134,26135,26136,26138,26139,26140,26142,26145,26146,26147,26148,26150,26153,
+26154,26155,26156,26158,26160,26162,26163,26167,26168,26169,26170,26171,26173,
+26175,26176,26178,26180,26181,26182,26183,26184,26185,26186,26189,26190,26192,
+26193,26200,26201,26203,26204,26205,26206,26208,26210,26211,26213,26215,26217,
+26218,26219,26220,26221,26225,26226,26227,26229,26232,26233,26235,26236,26237,
+26239,26240,26241,26243,26245,26246,26248,26249,26250,26251,26253,26254,26255,
+26256,26258,26259,26260,26261,26264,26265,26266,26267,26268,26270,26271,26272,
+26273,26274,26275,26276,26277,26278,26281,26282,26283,26284,26285,26287,26288,
+26289,26290,26291,26293,26294,26295,26296,26298,26299,26300,26301,26303,26304,
+26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,
+26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26330,26334,
+26335,26336,26337,26338,26339,26340,26341,26343,26344,26346,26347,26348,26349,
+26350,26351,26353,26357,26358,26360,26362,26363,26365,26369,26370,26371,26372,
+26373,26374,26375,26380,26382,26383,26385,26386,26387,26390,26392,26393,26394,
+26396,26398,26400,26401,26402,26403,26404,26405,26407,26409,26414,26416,26418,
+26419,26422,26423,26424,26425,26427,26428,26430,26431,26433,26436,26437,26439,
+26442,26443,26445,26450,26452,26453,26455,26456,26457,26458,26459,26461,26466,
+26467,26468,26470,26471,26475,26476,26478,26481,26484,26486,26488,26489,26490,
+26491,26493,26496,26498,26499,26501,26502,26504,26506,26508,26509,26510,26511,
+26513,26514,26515,26516,26518,26521,26523,26527,26528,26529,26532,26534,26537,
+26540,26542,26545,26546,26548,26553,26554,26555,26556,26557,26558,26559,26560,
+26562,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26581,26582,
+26583,26587,26591,26593,26595,26596,26598,26599,26600,26602,26603,26605,26606,
+26610,26613,26614,26615,26616,26617,26618,26619,26620,26622,26625,26626,26627,
+26628,26630,26637,26640,26642,26644,26645,26648,26649,26650,26651,26652,26654,
+26655,26656,26658,26659,26660,26661,26662,26663,26664,26667,26668,26669,26670,
+26671,26672,26673,26676,26677,26678,26682,26683,26687,26695,26699,26701,26703,
+26706,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26730,26732,
+26733,26734,26735,26736,26737,26738,26739,26741,26744,26745,26746,26747,26748,
+26749,26750,26751,26752,26754,26756,26759,26760,26761,26762,26763,26764,26765,
+26766,26768,26769,26770,26772,26773,26774,26776,26777,26778,26779,26780,26781,
+26782,26783,26784,26785,26787,26788,26789,26793,26794,26795,26796,26798,26801,
+26802,26804,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26817,
+26819,26820,26821,26822,26823,26824,26826,26828,26830,26831,26832,26833,26835,
+26836,26838,26839,26841,26843,26844,26845,26846,26847,26849,26850,26852,26853,
+26854,26855,26856,26857,26858,26859,26860,26861,26863,26866,26867,26868,26870,
+26871,26872,26875,26877,26878,26879,26880,26882,26883,26884,26886,26887,26888,
+26889,26890,26892,26895,26897,26899,26900,26901,26902,26903,26904,26905,26906,
+26907,26908,26909,26910,26913,26914,26915,26917,26918,26919,26920,26921,26922,
+26923,26924,26926,26927,26929,26930,26931,26933,26934,26935,26936,26938,26939,
+26940,26942,26944,26945,26947,26948,26949,26950,26951,26952,26953,26954,26955,
+26956,26957,26958,26959,26960,26961,26962,26963,26965,26966,26968,26969,26971,
+26972,26975,26977,26978,26980,26981,26983,26984,26985,26986,26988,26989,26991,
+26992,26994,26995,26996,26997,26998,27002,27003,27005,27006,27007,27009,27011,
+27013,27018,27019,27020,27022,27023,27024,27025,27026,27027,27030,27031,27033,
+27034,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27049,27050,
+27052,27054,27055,27056,27058,27059,27061,27062,27064,27065,27066,27068,27069,
+27070,27071,27072,27074,27075,27076,27077,27078,27079,27080,27081,27083,27085,
+27087,27089,27090,27091,27093,27094,27095,27096,27097,27098,27100,27101,27102,
+27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27118,
+27119,27120,27121,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,
+27134,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,
+27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27161,27162,27163,
+27164,27165,27166,27168,27170,27171,27172,27173,27174,27175,27177,27179,27180,
+27181,27182,27184,27186,27187,27188,27190,27191,27192,27193,27194,27195,27196,
+27199,27200,27201,27202,27203,27205,27206,27208,27209,27210,27211,27212,27213,
+27214,27215,27217,27218,27219,27220,27221,27222,27223,27226,27228,27229,27230,
+27231,27232,27234,27235,27236,27238,27239,27240,27241,27242,27243,27244,27245,
+27246,27247,27248,27250,27251,27252,27253,27254,27255,27256,27258,27259,27261,
+27262,27263,27265,27266,27267,27269,27270,27271,27272,27273,27274,27275,27276,
+27277,27279,27282,27283,27284,27285,27286,27288,27289,27290,27291,27292,27293,
+27294,27295,27297,27298,27299,27300,27301,27302,27303,27304,27306,27309,27310,
+27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,
+27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,
+27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,
+27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,
+27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,
+27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,
+27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,
+27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,
+27415,27416,27417,27418,27419,27420,27421,27422,27423,27429,27430,27432,27433,
+27434,27435,27436,27437,27438,27439,27440,27441,27443,27444,27445,27446,27448,
+27451,27452,27453,27455,27456,27457,27458,27460,27461,27464,27466,27467,27469,
+27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27482,27483,
+27484,27485,27486,27487,27488,27489,27496,27497,27499,27500,27501,27502,27503,
+27504,27505,27506,27507,27508,27509,27510,27511,27512,27514,27517,27518,27519,
+27520,27525,27528,27532,27534,27535,27536,27537,27540,27541,27543,27544,27545,
+27548,27549,27550,27551,27552,27554,27555,27556,27557,27558,27559,27560,27561,
+27563,27564,27565,27566,27567,27568,27569,27570,27574,27576,27577,27578,27579,
+27580,27581,27582,27584,27587,27588,27590,27591,27592,27593,27594,27596,27598,
+27600,27601,27608,27610,27612,27613,27614,27615,27616,27618,27619,27620,27621,
+27622,27623,27624,27625,27628,27629,27630,27632,27633,27634,27636,27638,27639,
+27640,27642,27643,27644,27646,27647,27648,27649,27650,27651,27652,27656,27657,
+27658,27659,27660,27662,27666,27671,27676,27677,27678,27680,27683,27685,27691,
+27692,27693,27697,27699,27702,27703,27705,27706,27707,27708,27710,27711,27715,
+27716,27717,27720,27723,27724,27725,27726,27727,27729,27730,27731,27734,27736,
+27737,27738,27746,27747,27749,27750,27751,27755,27756,27757,27758,27759,27761,
+27763,27765,27767,27768,27770,27771,27772,27775,27776,27780,27783,27786,27787,
+27789,27790,27793,27794,27797,27798,27799,27800,27802,27804,27805,27806,27808,
+27810,27816,27820,27823,27824,27828,27829,27830,27831,27834,27840,27841,27842,
+27843,27846,27847,27848,27851,27853,27854,27855,27857,27858,27864,27865,27866,
+27868,27869,27871,27876,27878,27879,27881,27884,27885,27890,27892,27897,27903,
+27904,27906,27907,27909,27910,27912,27913,27914,27917,27919,27920,27921,27923,
+27924,27925,27926,27928,27932,27933,27935,27936,27937,27938,27939,27940,27942,
+27944,27945,27948,27949,27951,27952,27956,27958,27959,27960,27962,27967,27968,
+27970,27972,27977,27980,27984,27989,27990,27991,27992,27995,27997,27999,28001,
+28002,28004,28005,28007,28008,28011,28012,28013,28016,28017,28018,28019,28021,
+28022,28025,28026,28027,28029,28030,28031,28032,28033,28035,28036,28038,28039,
+28042,28043,28045,28047,28048,28050,28054,28055,28056,28057,28058,28060,28066,
+28069,28076,28077,28080,28081,28083,28084,28086,28087,28089,28090,28091,28092,
+28093,28094,28097,28098,28099,28104,28105,28106,28109,28110,28111,28112,28114,
+28115,28116,28117,28119,28122,28123,28124,28127,28130,28131,28133,28135,28136,
+28137,28138,28141,28143,28144,28146,28148,28149,28150,28152,28154,28157,28158,
+28159,28160,28161,28162,28163,28164,28166,28167,28168,28169,28171,28175,28178,
+28179,28181,28184,28185,28187,28188,28190,28191,28194,28198,28199,28200,28202,
+28204,28206,28208,28209,28211,28213,28214,28215,28217,28219,28220,28221,28222,
+28223,28224,28225,28226,28229,28230,28231,28232,28233,28234,28235,28236,28239,
+28240,28241,28242,28245,28247,28249,28250,28252,28253,28254,28256,28257,28258,
+28259,28260,28261,28262,28263,28264,28265,28266,28268,28269,28271,28272,28273,
+28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28288,
+28289,28290,28292,28295,28296,28298,28299,28300,28301,28302,28305,28306,28307,
+28308,28309,28310,28311,28313,28314,28315,28317,28318,28320,28321,28323,28324,
+28326,28328,28329,28331,28332,28333,28334,28336,28339,28341,28344,28345,28348,
+28350,28351,28352,28355,28356,28357,28358,28360,28361,28362,28364,28365,28366,
+28368,28370,28374,28376,28377,28379,28380,28381,28387,28391,28394,28395,28396,
+28397,28398,28399,28400,28401,28402,28403,28405,28406,28407,28408,28410,28411,
+28412,28413,28414,28415,28416,28417,28419,28420,28421,28423,28424,28426,28427,
+28428,28429,28430,28432,28433,28434,28438,28439,28440,28441,28442,28443,28444,
+28445,28446,28447,28449,28450,28451,28453,28454,28455,28456,28460,28462,28464,
+28466,28468,28469,28471,28472,28473,28474,28475,28476,28477,28479,28480,28481,
+28482,28483,28484,28485,28488,28489,28490,28492,28494,28495,28496,28497,28498,
+28499,28500,28501,28502,28503,28505,28506,28507,28509,28511,28512,28513,28515,
+28516,28517,28519,28520,28521,28522,28523,28524,28527,28528,28529,28531,28533,
+28534,28535,28537,28539,28541,28542,28543,28544,28545,28546,28547,28549,28550,
+28551,28554,28555,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,
+28569,28570,28571,28573,28574,28575,28576,28578,28579,28580,28581,28582,28584,
+28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28596,28597,28599,
+28600,28602,28603,28604,28605,28606,28607,28609,28611,28612,28613,28614,28615,
+28616,28618,28619,28620,28621,28622,28623,28624,28627,28628,28629,28630,28631,
+28632,28633,28634,28635,28636,28637,28639,28642,28643,28644,28645,28646,28647,
+28648,28649,28650,28651,28652,28653,28656,28657,28658,28659,28660,28661,28662,
+28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
+28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,
+28690,28691,28692,28693,28694,28695,28696,28697,28700,28701,28702,28703,28704,
+28705,28706,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,
+28719,28720,28721,28722,28723,28724,28726,28727,28728,28730,28731,28732,28733,
+28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,
+28747,28749,28750,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,
+28762,28763,28764,28765,28767,28768,28769,28770,28771,28772,28773,28774,28775,
+28776,28777,28778,28782,28785,28786,28787,28788,28791,28793,28794,28795,28797,
+28801,28802,28803,28804,28806,28807,28808,28811,28812,28813,28815,28816,28817,
+28819,28823,28824,28826,28827,28830,28831,28832,28833,28834,28835,28836,28837,
+28838,28839,28840,28841,28842,28848,28850,28852,28853,28854,28858,28862,28863,
+28868,28869,28870,28871,28873,28875,28876,28877,28878,28879,28880,28881,28882,
+28883,28884,28885,28886,28887,28890,28892,28893,28894,28896,28897,28898,28899,
+28901,28906,28910,28912,28913,28914,28915,28916,28917,28918,28920,28922,28923,
+28924,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28939,
+28940,28941,28942,28943,28945,28946,28948,28951,28955,28956,28957,28958,28959,
+28960,28961,28962,28963,28964,28965,28967,28968,28969,28970,28971,28972,28973,
+28974,28978,28979,28980,28981,28983,28984,28985,28986,28987,28988,28989,28990,
+28991,28992,28993,28994,28995,28996,28998,28999,29000,29001,29003,29005,29007,
+29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29021,
+29023,29024,29025,29026,29027,29029,29033,29034,29035,29036,29037,29039,29040,
+29041,29044,29045,29046,29047,29049,29051,29052,29054,29055,29056,29057,29058,
+29059,29061,29062,29063,29064,29065,29067,29068,29069,29070,29072,29073,29074,
+29075,29077,29078,29079,29082,29083,29084,29085,29086,29089,29090,29091,29092,
+29093,29094,29095,29097,29098,29099,29101,29102,29103,29104,29105,29106,29108,
+29110,29111,29112,29114,29115,29116,29117,29118,29119,29120,29121,29122,29124,
+29125,29126,29127,29128,29129,29130,29131,29132,29133,29135,29136,29137,29138,
+29139,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29153,29154,
+29155,29156,29158,29160,29161,29162,29163,29164,29165,29167,29168,29169,29170,
+29171,29172,29173,29174,29175,29176,29178,29179,29180,29181,29182,29183,29184,
+29185,29186,29187,29188,29189,29191,29192,29193,29194,29195,29196,29197,29198,
+29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,
+29212,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29225,29227,
+29229,29230,29231,29234,29235,29236,29242,29244,29246,29248,29249,29250,29251,
+29252,29253,29254,29257,29258,29259,29262,29263,29264,29265,29267,29268,29269,
+29271,29272,29274,29276,29278,29280,29283,29284,29285,29288,29290,29291,29292,
+29293,29296,29297,29299,29300,29302,29303,29304,29307,29308,29309,29314,29315,
+29317,29318,29319,29320,29321,29324,29326,29328,29329,29331,29332,29333,29334,
+29335,29336,29337,29338,29339,29340,29341,29342,29344,29345,29346,29347,29348,
+29349,29350,29351,29352,29353,29354,29355,29358,29361,29362,29363,29365,29370,
+29371,29372,29373,29374,29375,29376,29381,29382,29383,29385,29386,29387,29388,
+29391,29393,29395,29396,29397,29398,29400,29402,29403,58566,58567,58568,58569,
+58570,58571,58572,58573,58574,58575,58576,58577,58578,58579,58580,58581,58582,
+58583,58584,58585,58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,
+58596,58597,58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,
+58609,58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,
+58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,58634,
+58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,58646,58647,
+58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,58658,58659,58660,
+58661,12288,12289,12290,183,713,711,168,12291,12293,8212,65374,8214,8230,8216,
+8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,
+12310,12311,12304,12305,177,215,247,8758,8743,8744,8721,8719,8746,8745,8712,
+8759,8730,8869,8741,8736,8978,8857,8747,8750,8801,8780,8776,8765,8733,8800,
+8814,8815,8804,8805,8734,8757,8756,9794,9792,176,8242,8243,8451,65284,164,
+65504,65505,8240,167,8470,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,
+9650,8251,8594,8592,8593,8595,12307,58662,58663,58664,58665,58666,58667,58668,
+58669,58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,
+58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,58694,
+58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,58706,58707,
+58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,58718,58719,58720,
+58721,58722,58723,58724,58725,58726,58727,58728,58729,58730,58731,58732,58733,
+58734,58735,58736,58737,58738,58739,58740,58741,58742,58743,58744,58745,58746,
+58747,58748,58749,58750,58751,58752,58753,58754,58755,58756,58757,8560,8561,
+8562,8563,8564,8565,8566,8567,8568,8569,59238,59239,59240,59241,59242,59243,
+9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,
+9367,9368,9369,9370,9371,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,
+9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9312,9313,9314,9315,9316,
+9317,9318,9319,9320,9321,8364,59245,12832,12833,12834,12835,12836,12837,12838,
+12839,12840,12841,59246,59247,8544,8545,8546,8547,8548,8549,8550,8551,8552,
+8553,8554,8555,59248,59249,58758,58759,58760,58761,58762,58763,58764,58765,
+58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,58778,
+58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,58790,58791,
+58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,58802,58803,58804,
+58805,58806,58807,58808,58809,58810,58811,58812,58813,58814,58815,58816,58817,
+58818,58819,58820,58821,58822,58823,58824,58825,58826,58827,58828,58829,58830,
+58831,58832,58833,58834,58835,58836,58837,58838,58839,58840,58841,58842,58843,
+58844,58845,58846,58847,58848,58849,58850,58851,58852,58853,65281,65282,65283,
+65509,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,
+65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,
+65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,
+65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,
+65336,65337,65338,65339,65340,65341,65342,65343,65344,65345,65346,65347,65348,
+65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,
+65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,
+58854,58855,58856,58857,58858,58859,58860,58861,58862,58863,58864,58865,58866,
+58867,58868,58869,58870,58871,58872,58873,58874,58875,58876,58877,58878,58879,
+58880,58881,58882,58883,58884,58885,58886,58887,58888,58889,58890,58891,58892,
+58893,58894,58895,58896,58897,58898,58899,58900,58901,58902,58903,58904,58905,
+58906,58907,58908,58909,58910,58911,58912,58913,58914,58915,58916,58917,58918,
+58919,58920,58921,58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,
+58932,58933,58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,
+58945,58946,58947,58948,58949,12353,12354,12355,12356,12357,12358,12359,12360,
+12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,
+12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,
+12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,
+12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,
+12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,
+12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,59250,59251,59252,
+59253,59254,59255,59256,59257,59258,59259,59260,58950,58951,58952,58953,58954,
+58955,58956,58957,58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,
+58968,58969,58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,
+58981,58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,
+58994,58995,58996,58997,58998,58999,59000,59001,59002,59003,59004,59005,59006,
+59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,59018,59019,
+59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,59030,59031,59032,
+59033,59034,59035,59036,59037,59038,59039,59040,59041,59042,59043,59044,59045,
+12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,
+12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,
+12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
+12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,
+12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,
+12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,
+12527,12528,12529,12530,12531,12532,12533,12534,59261,59262,59263,59264,59265,
+59266,59267,59268,59046,59047,59048,59049,59050,59051,59052,59053,59054,59055,
+59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,59066,59067,59068,
+59069,59070,59071,59072,59073,59074,59075,59076,59077,59078,59079,59080,59081,
+59082,59083,59084,59085,59086,59087,59088,59089,59090,59091,59092,59093,59094,
+59095,59096,59097,59098,59099,59100,59101,59102,59103,59104,59105,59106,59107,
+59108,59109,59110,59111,59112,59113,59114,59115,59116,59117,59118,59119,59120,
+59121,59122,59123,59124,59125,59126,59127,59128,59129,59130,59131,59132,59133,
+59134,59135,59136,59137,59138,59139,59140,59141,913,914,915,916,917,918,919,
+920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,59269,
+59270,59271,59272,59273,59274,59275,59276,945,946,947,948,949,950,951,952,953,
+954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,59277,59278,59279,
+59280,59281,59282,59283,65077,65078,65081,65082,65087,65088,65085,65086,65089,
+65090,65091,65092,59284,59285,65083,65084,65079,65080,65073,59286,65075,65076,
+59287,59288,59289,59290,59291,59292,59293,59294,59295,59142,59143,59144,59145,
+59146,59147,59148,59149,59150,59151,59152,59153,59154,59155,59156,59157,59158,
+59159,59160,59161,59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,
+59172,59173,59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,
+59185,59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,
+59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,59210,
+59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,59222,59223,
+59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,59234,59235,59236,
+59237,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,
+1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,
+1068,1069,1070,1071,59296,59297,59298,59299,59300,59301,59302,59303,59304,
+59305,59306,59307,59308,59309,59310,1072,1073,1074,1075,1076,1077,1105,1078,
+1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,
+1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,59311,59312,59313,59314,
+59315,59316,59317,59318,59319,59320,59321,59322,59323,714,715,729,8211,8213,
+8229,8245,8453,8457,8598,8599,8600,8601,8725,8735,8739,8786,8806,8807,8895,
+9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,
+9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,
+9582,9583,9584,9585,9586,9587,9601,9602,9603,9604,9605,9606,9607,9608,9609,
+9610,9611,9612,9613,9614,9615,9619,9620,9621,9660,9661,9698,9699,9700,9701,
+9737,8853,12306,12317,12318,59324,59325,59326,59327,59328,59329,59330,59331,
+59332,59333,59334,257,225,462,224,275,233,283,232,299,237,464,236,333,243,466,
+242,363,250,468,249,470,472,474,476,252,234,593,59335,324,328,505,609,59337,
+59338,59339,59340,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,
+12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
+12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,
+12585,59341,59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,
+59353,59354,59355,59356,59357,59358,59359,59360,59361,12321,12322,12323,12324,
+12325,12326,12327,12328,12329,12963,13198,13199,13212,13213,13214,13217,13252,
+13262,13265,13266,13269,65072,65506,65508,59362,8481,12849,59363,8208,59364,
+59365,59366,12540,12443,12444,12541,12542,12294,12445,12446,65097,65098,65099,
+65100,65101,65102,65103,65104,65105,65106,65108,65109,65110,65111,65113,65114,
+65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,65126,65128,
+65129,65130,65131,12350,12272,12273,12274,12275,12276,12277,12278,12279,12280,
+12281,12282,12283,12295,59380,59381,59382,59383,59384,59385,59386,59387,59388,
+59389,59390,59391,59392,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,
+9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,
+9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,
+9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,
+9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,
+9542,9543,9544,9545,9546,9547,59393,59394,59395,59396,59397,59398,59399,59400,
+59401,59402,59403,59404,59405,59406,59407,29404,29405,29407,29410,29411,29412,
+29413,29414,29415,29418,29419,29429,29430,29433,29437,29438,29439,29440,29442,
+29444,29445,29446,29447,29448,29449,29451,29452,29453,29455,29456,29457,29458,
+29460,29464,29465,29466,29471,29472,29475,29476,29478,29479,29480,29485,29487,
+29488,29490,29491,29493,29494,29498,29499,29500,29501,29504,29505,29506,29507,
+29508,29509,29510,29511,29512,29513,29514,29515,29516,29518,29519,29521,29523,
+29524,29525,29526,29528,29529,29530,29531,29532,29533,29534,29535,29537,29538,
+29539,29540,29541,29542,29543,29544,29545,29546,29547,29550,29552,29553,57344,
+57345,57346,57347,57348,57349,57350,57351,57352,57353,57354,57355,57356,57357,
+57358,57359,57360,57361,57362,57363,57364,57365,57366,57367,57368,57369,57370,
+57371,57372,57373,57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,
+57384,57385,57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,
+57397,57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,
+57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,57422,
+57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,57434,57435,
+57436,57437,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,
+29565,29567,29568,29569,29570,29571,29573,29574,29576,29578,29580,29581,29583,
+29584,29586,29587,29588,29589,29591,29592,29593,29594,29596,29597,29598,29600,
+29601,29603,29604,29605,29606,29607,29608,29610,29612,29613,29617,29620,29621,
+29622,29624,29625,29628,29629,29630,29631,29633,29635,29636,29637,29638,29639,
+29643,29644,29646,29650,29651,29652,29653,29654,29655,29656,29658,29659,29660,
+29661,29663,29665,29666,29667,29668,29670,29672,29674,29675,29676,29678,29679,
+29680,29681,29683,29684,29685,29686,29687,57438,57439,57440,57441,57442,57443,
+57444,57445,57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,
+57457,57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,
+57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,57482,
+57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,57494,57495,
+57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,57506,57507,57508,
+57509,57510,57511,57512,57513,57514,57515,57516,57517,57518,57519,57520,57521,
+57522,57523,57524,57525,57526,57527,57528,57529,57530,57531,29688,29689,29690,
+29691,29692,29693,29694,29695,29696,29697,29698,29700,29703,29704,29707,29708,
+29709,29710,29713,29714,29715,29716,29717,29718,29719,29720,29721,29724,29725,
+29726,29727,29728,29729,29731,29732,29735,29737,29739,29741,29743,29745,29746,
+29751,29752,29753,29754,29755,29757,29758,29759,29760,29762,29763,29764,29765,
+29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,
+29779,29780,29782,29784,29789,29792,29793,29794,29795,29796,29797,29798,29799,
+29800,29801,29802,29803,29804,29806,29807,29809,29810,29811,29812,29813,29816,
+29817,29818,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,57542,
+57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,57554,57555,
+57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,57566,57567,57568,
+57569,57570,57571,57572,57573,57574,57575,57576,57577,57578,57579,57580,57581,
+57582,57583,57584,57585,57586,57587,57588,57589,57590,57591,57592,57593,57594,
+57595,57596,57597,57598,57599,57600,57601,57602,57603,57604,57605,57606,57607,
+57608,57609,57610,57611,57612,57613,57614,57615,57616,57617,57618,57619,57620,
+57621,57622,57623,57624,57625,29819,29820,29821,29823,29826,29828,29829,29830,
+29832,29833,29834,29836,29837,29839,29841,29842,29843,29844,29845,29846,29847,
+29848,29849,29850,29851,29853,29855,29856,29857,29858,29859,29860,29861,29862,
+29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,
+29879,29880,29881,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,
+29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,
+29907,29908,29909,29910,29911,29912,29913,29914,29915,29917,29919,29921,29925,
+29927,29928,29929,29930,29931,29932,29933,29936,29937,29938,57626,57627,57628,
+57629,57630,57631,57632,57633,57634,57635,57636,57637,57638,57639,57640,57641,
+57642,57643,57644,57645,57646,57647,57648,57649,57650,57651,57652,57653,57654,
+57655,57656,57657,57658,57659,57660,57661,57662,57663,57664,57665,57666,57667,
+57668,57669,57670,57671,57672,57673,57674,57675,57676,57677,57678,57679,57680,
+57681,57682,57683,57684,57685,57686,57687,57688,57689,57690,57691,57692,57693,
+57694,57695,57696,57697,57698,57699,57700,57701,57702,57703,57704,57705,57706,
+57707,57708,57709,57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,
+29939,29941,29944,29945,29946,29947,29948,29949,29950,29952,29953,29954,29955,
+29957,29958,29959,29960,29961,29962,29963,29964,29966,29968,29970,29972,29973,
+29974,29975,29979,29981,29982,29984,29985,29986,29987,29988,29990,29991,29994,
+29998,30004,30006,30009,30012,30013,30015,30017,30018,30019,30020,30022,30023,
+30025,30026,30029,30032,30033,30034,30035,30037,30038,30039,30040,30045,30046,
+30047,30048,30049,30050,30051,30052,30055,30056,30057,30059,30060,30061,30062,
+30063,30064,30065,30067,30069,30070,30071,30074,30075,30076,30077,30078,30080,
+30081,30082,30084,30085,30087,57720,57721,57722,57723,57724,57725,57726,57727,
+57728,57729,57730,57731,57732,57733,57734,57735,57736,57737,57738,57739,57740,
+57741,57742,57743,57744,57745,57746,57747,57748,57749,57750,57751,57752,57753,
+57754,57755,57756,57757,57758,57759,57760,57761,57762,57763,57764,57765,57766,
+57767,57768,57769,57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,
+57780,57781,57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,
+57793,57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,
+57806,57807,57808,57809,57810,57811,57812,57813,30088,30089,30090,30092,30093,
+30094,30096,30099,30101,30104,30107,30108,30110,30114,30118,30119,30120,30121,
+30122,30125,30134,30135,30138,30139,30143,30144,30145,30150,30155,30156,30158,
+30159,30160,30161,30163,30167,30169,30170,30172,30173,30175,30176,30177,30181,
+30185,30188,30189,30190,30191,30194,30195,30197,30198,30199,30200,30202,30203,
+30205,30206,30210,30212,30214,30215,30216,30217,30219,30221,30222,30223,30225,
+30226,30227,30228,30230,30234,30236,30237,30238,30241,30243,30247,30248,30252,
+30254,30255,30257,30258,30262,30263,30265,30266,30267,30269,30273,30274,30276,
+57814,57815,57816,57817,57818,57819,57820,57821,57822,57823,57824,57825,57826,
+57827,57828,57829,57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,
+57840,57841,57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,
+57853,57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,
+57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,57878,
+57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,57890,57891,
+57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,57902,57903,57904,
+57905,57906,57907,30277,30278,30279,30280,30281,30282,30283,30286,30287,30288,
+30289,30290,30291,30293,30295,30296,30297,30298,30299,30301,30303,30304,30305,
+30306,30308,30309,30310,30311,30312,30313,30314,30316,30317,30318,30320,30321,
+30322,30323,30324,30325,30326,30327,30329,30330,30332,30335,30336,30337,30339,
+30341,30345,30346,30348,30349,30351,30352,30354,30356,30357,30359,30360,30362,
+30363,30364,30365,30366,30367,30368,30369,30370,30371,30373,30374,30375,30376,
+30377,30378,30379,30380,30381,30383,30384,30387,30389,30390,30391,30392,30393,
+30394,30395,30396,30397,30398,30400,30401,30403,21834,38463,22467,25384,21710,
+21769,21696,30353,30284,34108,30702,33406,30861,29233,38552,38797,27688,23433,
+20474,25353,26263,23736,33018,26696,32942,26114,30414,20985,25942,29100,32753,
+34948,20658,22885,25034,28595,33453,25420,25170,21485,21543,31494,20843,30116,
+24052,25300,36299,38774,25226,32793,22365,38712,32610,29240,30333,26575,30334,
+25670,20336,36133,25308,31255,26001,29677,25644,25203,33324,39041,26495,29256,
+25198,25292,20276,29923,21322,21150,32458,37030,24110,26758,27036,33152,32465,
+26834,30917,34444,38225,20621,35876,33502,32990,21253,35090,21093,30404,30407,
+30409,30411,30412,30419,30421,30425,30426,30428,30429,30430,30432,30433,30434,
+30435,30436,30438,30439,30440,30441,30442,30443,30444,30445,30448,30451,30453,
+30454,30455,30458,30459,30461,30463,30464,30466,30467,30469,30470,30474,30476,
+30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30491,30492,
+30493,30494,30497,30499,30500,30501,30503,30506,30507,30508,30510,30512,30513,
+30514,30515,30516,30521,30523,30525,30526,30527,30530,30532,30533,30534,30536,
+30537,30538,30539,30540,30541,30542,30543,30546,30547,30548,30549,30550,30551,
+30552,30553,30556,34180,38649,20445,22561,39281,23453,25265,25253,26292,35961,
+40077,29190,26479,30865,24754,21329,21271,36744,32972,36125,38049,20493,29384,
+22791,24811,28953,34987,22868,33519,26412,31528,23849,32503,29997,27893,36454,
+36856,36924,40763,27604,37145,31508,24444,30887,34006,34109,27605,27609,27606,
+24065,24199,30201,38381,25949,24330,24517,36767,22721,33218,36991,38491,38829,
+36793,32534,36140,25153,20415,21464,21342,36776,36777,36779,36941,26631,24426,
+33176,34920,40150,24971,21035,30250,24428,25996,28626,28392,23486,25672,20853,
+20912,26564,19993,31177,39292,28851,30557,30558,30559,30560,30564,30567,30569,
+30570,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,
+30586,30587,30588,30593,30594,30595,30598,30599,30600,30601,30602,30603,30607,
+30608,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,
+30625,30627,30628,30630,30632,30635,30637,30638,30639,30641,30642,30644,30646,
+30647,30648,30649,30650,30652,30654,30656,30657,30658,30659,30660,30661,30662,
+30663,30664,30665,30666,30667,30668,30670,30671,30672,30673,30674,30675,30676,
+30677,30678,30680,30681,30682,30685,30686,30687,30688,30689,30692,30149,24182,
+29627,33760,25773,25320,38069,27874,21338,21187,25615,38082,31636,20271,24091,
+33334,33046,33162,28196,27850,39539,25429,21340,21754,34917,22496,19981,24067,
+27493,31807,37096,24598,25830,29468,35009,26448,25165,36130,30572,36393,37319,
+24425,33756,34081,39184,21442,34453,27531,24813,24808,28799,33485,33329,20179,
+27815,34255,25805,31961,27133,26361,33609,21397,31574,20391,20876,27979,23618,
+36461,25554,21449,33580,33590,26597,30900,25661,23519,23700,24046,35815,25286,
+26612,35962,25600,25530,34633,39307,35863,32544,38130,20135,38416,39076,26124,
+29462,30694,30696,30698,30703,30704,30705,30706,30708,30709,30711,30713,30714,
+30715,30716,30723,30724,30725,30726,30727,30728,30730,30731,30734,30735,30736,
+30739,30741,30745,30747,30750,30752,30753,30754,30756,30760,30762,30763,30766,
+30767,30769,30770,30771,30773,30774,30781,30783,30785,30786,30787,30788,30790,
+30792,30793,30794,30795,30797,30799,30801,30803,30804,30808,30809,30810,30811,
+30812,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,
+30831,30832,30833,30834,30835,30836,30837,30838,30840,30841,30842,30843,30845,
+30846,30847,30848,30849,30850,30851,22330,23581,24120,38271,20607,32928,21378,
+25950,30021,21809,20513,36229,25220,38046,26397,22066,28526,24034,21557,28818,
+36710,25199,25764,25507,24443,28552,37108,33251,36784,23576,26216,24561,27785,
+38472,36225,34924,25745,31216,22478,27225,25104,21576,20056,31243,24809,28548,
+35802,25215,36894,39563,31204,21507,30196,25345,21273,27744,36831,24347,39536,
+32827,40831,20360,23610,36196,32709,26021,28861,20805,20914,34411,23815,23456,
+25277,37228,30068,36364,31264,24833,31609,20167,32504,30597,19985,33261,21021,
+20986,27249,21416,36487,38148,38607,28353,38500,26970,30852,30853,30854,30856,
+30858,30859,30863,30864,30866,30868,30869,30870,30873,30877,30878,30880,30882,
+30884,30886,30888,30889,30890,30891,30892,30893,30894,30895,30901,30902,30903,
+30904,30906,30907,30908,30909,30911,30912,30914,30915,30916,30918,30919,30920,
+30924,30925,30926,30927,30929,30930,30931,30934,30935,30936,30938,30939,30940,
+30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30953,30954,
+30955,30957,30958,30959,30960,30961,30963,30965,30966,30968,30969,30971,30972,
+30973,30974,30975,30976,30978,30979,30980,30982,30983,30984,30985,30986,30987,
+30988,30784,20648,30679,25616,35302,22788,25571,24029,31359,26941,20256,33337,
+21912,20018,30126,31383,24162,24202,38383,21019,21561,28810,25462,38180,22402,
+26149,26943,37255,21767,28147,32431,34850,25139,32496,30133,33576,30913,38604,
+36766,24904,29943,35789,27492,21050,36176,27425,32874,33905,22257,21254,20174,
+19995,20945,31895,37259,31751,20419,36479,31713,31388,25703,23828,20652,33030,
+30209,31929,28140,32736,26449,23384,23544,30923,25774,25619,25514,25387,38169,
+25645,36798,31572,30249,25171,22823,21574,27513,20643,25140,24102,27526,20195,
+36151,34955,24453,36910,30989,30990,30991,30992,30993,30994,30996,30997,30998,
+30999,31000,31001,31002,31003,31004,31005,31007,31008,31009,31010,31011,31013,
+31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,
+31027,31029,31030,31031,31032,31033,31037,31039,31042,31043,31044,31045,31047,
+31050,31051,31052,31053,31054,31055,31056,31057,31058,31060,31061,31064,31065,
+31073,31075,31076,31078,31081,31082,31083,31084,31086,31088,31089,31090,31091,
+31092,31093,31094,31097,31099,31100,31101,31102,31103,31106,31107,31110,31111,
+31112,31113,31115,31116,31117,31118,31120,31121,31122,24608,32829,25285,20025,
+21333,37112,25528,32966,26086,27694,20294,24814,28129,35806,24377,34507,24403,
+25377,20826,33633,26723,20992,25443,36424,20498,23707,31095,23548,21040,31291,
+24764,36947,30423,24503,24471,30340,36460,28783,30331,31561,30634,20979,37011,
+22564,20302,28404,36842,25932,31515,29380,28068,32735,23265,25269,24213,22320,
+33922,31532,24093,24351,36882,32532,39072,25474,28359,30872,28857,20856,38747,
+22443,30005,20291,30008,24215,24806,22880,28096,27583,30857,21500,38613,20939,
+20993,25481,21514,38035,35843,36300,29241,30879,34678,36845,35853,21472,31123,
+31124,31125,31126,31127,31128,31129,31131,31132,31133,31134,31135,31136,31137,
+31138,31139,31140,31141,31142,31144,31145,31146,31147,31148,31149,31150,31151,
+31152,31153,31154,31156,31157,31158,31159,31160,31164,31167,31170,31172,31173,
+31175,31176,31178,31180,31182,31183,31184,31187,31188,31190,31191,31193,31194,
+31195,31196,31197,31198,31200,31201,31202,31205,31208,31210,31212,31214,31217,
+31218,31219,31220,31221,31222,31223,31225,31226,31228,31230,31231,31233,31236,
+31237,31239,31240,31241,31242,31244,31247,31248,31249,31250,31251,31253,31254,
+31256,31257,31259,31260,19969,30447,21486,38025,39030,40718,38189,23450,35746,
+20002,19996,20908,33891,25026,21160,26635,20375,24683,20923,27934,20828,25238,
+26007,38497,35910,36887,30168,37117,30563,27602,29322,29420,35835,22581,30585,
+36172,26460,38208,32922,24230,28193,22930,31471,30701,38203,27573,26029,32526,
+22534,20817,38431,23545,22697,21544,36466,25958,39039,22244,38045,30462,36929,
+25479,21702,22810,22842,22427,36530,26421,36346,33333,21057,24816,22549,34558,
+23784,40517,20420,39069,35769,23077,24694,21380,25212,36943,37122,39295,24681,
+32780,20799,32819,23572,39285,27953,20108,31261,31263,31265,31266,31268,31269,
+31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,
+31284,31285,31286,31288,31290,31294,31296,31297,31298,31299,31300,31301,31303,
+31304,31305,31306,31307,31308,31309,31310,31311,31312,31314,31315,31316,31317,
+31318,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,
+31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31345,
+31346,31347,31349,31355,31356,31357,31358,31362,31365,31367,31369,31370,31371,
+31372,31374,31375,31376,31379,31380,31385,31386,31387,31390,31393,31394,36144,
+21457,32602,31567,20240,20047,38400,27861,29648,34281,24070,30058,32763,27146,
+30718,38034,32321,20961,28902,21453,36820,33539,36137,29359,39277,27867,22346,
+33459,26041,32938,25151,38450,22952,20223,35775,32442,25918,33778,38750,21857,
+39134,32933,21290,35837,21536,32954,24223,27832,36153,33452,37210,21545,27675,
+20998,32439,22367,28954,27774,31881,22859,20221,24575,24868,31914,20016,23553,
+26539,34562,23792,38155,39118,30127,28925,36898,20911,32541,35773,22857,20964,
+20315,21542,22827,25975,32932,23413,25206,25282,36752,24133,27679,31526,20239,
+20440,26381,31395,31396,31399,31401,31402,31403,31406,31407,31408,31409,31410,
+31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31424,31425,
+31426,31427,31428,31429,31430,31431,31432,31433,31434,31436,31437,31438,31439,
+31440,31441,31442,31443,31444,31445,31447,31448,31450,31451,31452,31453,31457,
+31458,31460,31463,31464,31465,31466,31467,31468,31470,31472,31473,31474,31475,
+31476,31477,31478,31479,31480,31483,31484,31486,31488,31489,31490,31493,31495,
+31497,31500,31501,31502,31504,31506,31507,31510,31511,31512,31514,31516,31517,
+31519,31521,31522,31523,31527,31529,31533,28014,28074,31119,34993,24343,29995,
+25242,36741,20463,37340,26023,33071,33105,24220,33104,36212,21103,35206,36171,
+22797,20613,20184,38428,29238,33145,36127,23500,35747,38468,22919,32538,21648,
+22134,22030,35813,25913,27010,38041,30422,28297,24178,29976,26438,26577,31487,
+32925,36214,24863,31174,25954,36195,20872,21018,38050,32568,32923,32434,23703,
+28207,26464,31705,30347,39640,33167,32660,31957,25630,38224,31295,21578,21733,
+27468,25601,25096,40509,33011,30105,21106,38761,33883,26684,34532,38401,38548,
+38124,20010,21508,32473,26681,36319,32789,26356,24218,32697,31535,31536,31538,
+31540,31541,31542,31543,31545,31547,31549,31551,31552,31553,31554,31555,31556,
+31558,31560,31562,31565,31566,31571,31573,31575,31577,31580,31582,31583,31585,
+31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31599,31600,
+31603,31604,31606,31608,31610,31612,31613,31615,31617,31618,31619,31620,31622,
+31623,31624,31625,31626,31627,31628,31630,31631,31633,31634,31635,31638,31640,
+31641,31642,31643,31646,31647,31648,31651,31652,31653,31662,31663,31664,31666,
+31667,31669,31670,31671,31673,31674,31675,31676,31677,31678,31679,31680,31682,
+31683,31684,22466,32831,26775,24037,25915,21151,24685,40858,20379,36524,20844,
+23467,24339,24041,27742,25329,36129,20849,38057,21246,27807,33503,29399,22434,
+26500,36141,22815,36764,33735,21653,31629,20272,27837,23396,22993,40723,21476,
+34506,39592,35895,32929,25925,39038,22266,38599,21038,29916,21072,23521,25346,
+35074,20054,25296,24618,26874,20851,23448,20896,35266,31649,39302,32592,24815,
+28748,36143,20809,24191,36891,29808,35268,22317,30789,24402,40863,38394,36712,
+39740,35809,30328,26690,26588,36330,36149,21053,36746,28378,26829,38149,37101,
+22269,26524,35065,36807,21704,31685,31688,31689,31690,31691,31693,31694,31695,
+31696,31698,31700,31701,31702,31703,31704,31707,31708,31710,31711,31712,31714,
+31715,31716,31719,31720,31721,31723,31724,31725,31727,31728,31730,31731,31732,
+31733,31734,31736,31737,31738,31739,31741,31743,31744,31745,31746,31747,31748,
+31749,31750,31752,31753,31754,31757,31758,31760,31761,31762,31763,31764,31765,
+31767,31768,31769,31770,31771,31772,31773,31774,31776,31777,31778,31779,31780,
+31781,31784,31785,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,
+31797,31798,31799,31801,31802,31803,31804,31805,31806,31810,39608,23401,28023,
+27686,20133,23475,39559,37219,25000,37039,38889,21547,28085,23506,20989,21898,
+32597,32752,25788,25421,26097,25022,24717,28938,27735,27721,22831,26477,33322,
+22741,22158,35946,27627,37085,22909,32791,21495,28009,21621,21917,33655,33743,
+26680,31166,21644,20309,21512,30418,35977,38402,27827,28088,36203,35088,40548,
+36154,22079,40657,30165,24456,29408,24680,21756,20136,27178,34913,24658,36720,
+21700,28888,34425,40511,27946,23439,24344,32418,21897,20399,29492,21564,21402,
+20505,21518,21628,20046,24573,29786,22774,33899,32993,34676,29392,31946,28246,
+31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31822,31823,31824,
+31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,
+31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,
+31851,31852,31853,31854,31855,31856,31857,31858,31861,31862,31863,31864,31865,
+31866,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31882,
+31883,31884,31885,31886,31887,31888,31891,31892,31894,31897,31898,31899,31904,
+31905,31907,31910,31911,31912,31913,31915,31916,31917,31919,31920,31924,31925,
+31926,31927,31928,31930,31931,24359,34382,21804,25252,20114,27818,25143,33457,
+21719,21326,29502,28369,30011,21010,21270,35805,27088,24458,24576,28142,22351,
+27426,29615,26707,36824,32531,25442,24739,21796,30186,35938,28949,28067,23462,
+24187,33618,24908,40644,30970,34647,31783,30343,20976,24822,29004,26179,24140,
+24653,35854,28784,25381,36745,24509,24674,34516,22238,27585,24724,24935,21321,
+24800,26214,36159,31229,20250,28905,27719,35763,35826,32472,33636,26127,23130,
+39746,27985,28151,35905,27963,20249,28779,33719,25110,24785,38669,36135,31096,
+20987,22334,22522,26426,30072,31293,31215,31637,31935,31936,31938,31939,31940,
+31942,31945,31947,31950,31951,31952,31953,31954,31955,31956,31960,31962,31963,
+31965,31966,31969,31970,31971,31972,31973,31974,31975,31977,31978,31979,31980,
+31981,31982,31984,31985,31986,31987,31988,31989,31990,31991,31993,31994,31996,
+31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,
+32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
+32024,32025,32026,32027,32028,32029,32030,32031,32033,32035,32036,32037,32038,
+32040,32041,32042,32044,32045,32046,32048,32049,32050,32051,32052,32053,32054,
+32908,39269,36857,28608,35749,40481,23020,32489,32521,21513,26497,26840,36753,
+31821,38598,21450,24613,30142,27762,21363,23241,32423,25380,20960,33034,24049,
+34015,25216,20864,23395,20238,31085,21058,24760,27982,23492,23490,35745,35760,
+26082,24524,38469,22931,32487,32426,22025,26551,22841,20339,23478,21152,33626,
+39050,36158,30002,38078,20551,31292,20215,26550,39550,23233,27516,30417,22362,
+23574,31546,38388,29006,20860,32937,33392,22904,32516,33575,26816,26604,30897,
+30839,25315,25441,31616,20461,21098,20943,33616,27099,37492,36341,36145,35265,
+38190,31661,20214,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,
+32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,
+32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,
+32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,
+32104,32105,32106,32107,32108,32109,32111,32112,32113,32114,32115,32116,32117,
+32118,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
+32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,
+32145,32146,32147,32148,32149,32150,32151,32152,20581,33328,21073,39279,28176,
+28293,28071,24314,20725,23004,23558,27974,27743,30086,33931,26728,22870,35762,
+21280,37233,38477,34121,26898,30977,28966,33014,20132,37066,27975,39556,23047,
+22204,25605,38128,30699,20389,33050,29409,35282,39290,32564,32478,21119,25945,
+37237,36735,36739,21483,31382,25581,25509,30342,31224,34903,38454,25130,21163,
+33410,26708,26480,25463,30571,31469,27905,32467,35299,22992,25106,34249,33445,
+30028,20511,20171,30117,35819,23626,24062,31563,26020,37329,20170,27941,35167,
+32039,38182,20165,35880,36827,38771,26187,31105,36817,28908,28024,32153,32154,
+32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32167,32168,
+32169,32170,32171,32172,32173,32175,32176,32177,32178,32179,32180,32181,32182,
+32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,
+32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,
+32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,
+32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,
+32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,
+32248,32249,32250,23613,21170,33606,20834,33550,30555,26230,40120,20140,24778,
+31934,31923,32463,20117,35686,26223,39048,38745,22659,25964,38236,24452,30153,
+38742,31455,31454,20928,28847,31384,25578,31350,32416,29590,38893,20037,28792,
+20061,37202,21417,25937,26087,33276,33285,21646,23601,30106,38816,25304,29401,
+30141,23621,39545,33738,23616,21632,30697,20030,27822,32858,25298,25454,24040,
+20855,36317,36382,38191,20465,21477,24807,28844,21095,25424,40515,23071,20518,
+30519,21367,32482,25733,25899,25225,25496,20500,29237,35273,20915,35776,32477,
+22343,33740,38055,20891,21531,23803,32251,32252,32253,32254,32255,32256,32257,
+32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,
+32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,
+32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,
+32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,
+32310,32311,32312,32313,32314,32316,32317,32318,32319,32320,32322,32323,32324,
+32325,32326,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,
+32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,20426,31459,
+27994,37089,39567,21888,21654,21345,21679,24320,25577,26999,20975,24936,21002,
+22570,21208,22350,30733,30475,24247,24951,31968,25179,25239,20130,28821,32771,
+25335,28900,38752,22391,33499,26607,26869,30933,39063,31185,22771,21683,21487,
+28212,20811,21051,23458,35838,32943,21827,22438,24691,22353,21549,31354,24656,
+23380,25511,25248,21475,25187,23495,26543,21741,31391,33510,37239,24211,35044,
+22840,22446,25358,36328,33007,22359,31607,20393,24555,23485,27454,21281,31568,
+29378,26694,30719,30518,26103,20917,20111,30420,23743,31397,33909,22862,39745,
+20608,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,
+32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,
+32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32387,32388,
+32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,
+32402,32403,32404,32405,32406,32407,32408,32409,32410,32412,32413,32414,32430,
+32436,32443,32444,32470,32484,32492,32505,32522,32528,32542,32567,32569,32571,
+32572,32573,32574,32575,32576,32577,32579,32582,32583,32584,32585,32586,32587,
+32588,32589,32590,32591,32594,32595,39304,24871,28291,22372,26118,25414,22256,
+25324,25193,24275,38420,22403,25289,21895,34593,33098,36771,21862,33713,26469,
+36182,34013,23146,26639,25318,31726,38417,20848,28572,35888,25597,35272,25042,
+32518,28866,28389,29701,27028,29436,24266,37070,26391,28010,25438,21171,29282,
+32769,20332,23013,37226,28889,28061,21202,20048,38647,38253,34174,30922,32047,
+20769,22418,25794,32907,31867,27882,26865,26974,20919,21400,26792,29313,40654,
+31729,29432,31163,28435,29702,26446,37324,40100,31036,33673,33620,21519,26647,
+20029,21385,21169,30782,21382,21033,20616,20363,20432,32598,32601,32603,32604,
+32605,32606,32608,32611,32612,32613,32614,32615,32619,32620,32621,32623,32624,
+32627,32629,32630,32631,32632,32634,32635,32636,32637,32639,32640,32642,32643,
+32644,32645,32646,32647,32648,32649,32651,32653,32655,32656,32657,32658,32659,
+32661,32662,32663,32664,32665,32667,32668,32672,32674,32675,32677,32678,32680,
+32681,32682,32683,32684,32685,32686,32689,32691,32692,32693,32694,32695,32698,
+32699,32702,32704,32706,32707,32708,32710,32711,32712,32713,32715,32717,32719,
+32720,32721,32722,32723,32726,32727,32729,32730,32731,32732,32733,32734,32738,
+32739,30178,31435,31890,27813,38582,21147,29827,21737,20457,32852,33714,36830,
+38256,24265,24604,28063,24088,25947,33080,38142,24651,28860,32451,31918,20937,
+26753,31921,33391,20004,36742,37327,26238,20142,35845,25769,32842,20698,30103,
+29134,23525,36797,28518,20102,25730,38243,24278,26009,21015,35010,28872,21155,
+29454,29747,26519,30967,38678,20020,37051,40158,28107,20955,36161,21533,25294,
+29618,33777,38646,40836,38083,20278,32666,20940,28789,38517,23725,39046,21478,
+20196,28316,29705,27060,30827,39311,30041,21016,30244,27969,26611,20845,40857,
+32843,21657,31548,31423,32740,32743,32744,32746,32747,32748,32749,32751,32754,
+32756,32757,32758,32759,32760,32761,32762,32765,32766,32767,32770,32775,32776,
+32777,32778,32782,32783,32785,32787,32794,32795,32797,32798,32799,32801,32803,
+32804,32811,32812,32813,32814,32815,32816,32818,32820,32825,32826,32828,32830,
+32832,32833,32836,32837,32839,32840,32841,32846,32847,32848,32849,32851,32853,
+32854,32855,32857,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,
+32869,32870,32871,32872,32875,32876,32877,32878,32879,32880,32882,32883,32884,
+32885,32886,32887,32888,32889,32890,32891,32892,32893,38534,22404,25314,38471,
+27004,23044,25602,31699,28431,38475,33446,21346,39045,24208,28809,25523,21348,
+34383,40065,40595,30860,38706,36335,36162,40575,28510,31108,24405,38470,25134,
+39540,21525,38109,20387,26053,23653,23649,32533,34385,27695,24459,29575,28388,
+32511,23782,25371,23402,28390,21365,20081,25504,30053,25249,36718,20262,20177,
+27814,32438,35770,33821,34746,32599,36923,38179,31657,39585,35064,33853,27931,
+39558,32476,22920,40635,29595,30721,34434,39532,39554,22043,21527,22475,20080,
+40614,21334,36808,33033,30610,39314,34542,28385,34067,26364,24930,28459,32894,
+32897,32898,32901,32904,32906,32909,32910,32911,32912,32913,32914,32916,32917,
+32919,32921,32926,32931,32934,32935,32936,32940,32944,32947,32949,32950,32952,
+32953,32955,32965,32967,32968,32969,32970,32971,32975,32976,32977,32978,32979,
+32980,32981,32984,32991,32992,32994,32995,32998,33006,33013,33015,33017,33019,
+33022,33023,33024,33025,33027,33028,33029,33031,33032,33035,33036,33045,33047,
+33049,33051,33052,33053,33055,33056,33057,33058,33059,33060,33061,33062,33063,
+33064,33065,33066,33067,33069,33070,33072,33075,33076,33077,33079,33081,33082,
+33083,33084,33085,33087,35881,33426,33579,30450,27667,24537,33725,29483,33541,
+38170,27611,30683,38086,21359,33538,20882,24125,35980,36152,20040,29611,26522,
+26757,37238,38665,29028,27809,30473,23186,38209,27599,32654,26151,23504,22969,
+23194,38376,38391,20204,33804,33945,27308,30431,38192,29467,26790,23391,30511,
+37274,38753,31964,36855,35868,24357,31859,31192,35269,27852,34588,23494,24130,
+26825,30496,32501,20885,20813,21193,23081,32517,38754,33495,25551,30596,34256,
+31186,28218,24217,22937,34065,28781,27665,25279,30399,25935,24751,38397,26126,
+34719,40483,38125,21517,21629,35884,25720,33088,33089,33090,33091,33092,33093,
+33095,33097,33101,33102,33103,33106,33110,33111,33112,33115,33116,33117,33118,
+33119,33121,33122,33123,33124,33126,33128,33130,33131,33132,33135,33138,33139,
+33141,33142,33143,33144,33153,33155,33156,33157,33158,33159,33161,33163,33164,
+33165,33166,33168,33170,33171,33172,33173,33174,33175,33177,33178,33182,33183,
+33184,33185,33186,33188,33189,33191,33193,33195,33196,33197,33198,33199,33200,
+33201,33202,33204,33205,33206,33207,33208,33209,33212,33213,33214,33215,33220,
+33221,33223,33224,33225,33227,33229,33230,33231,33232,33233,33234,33235,25721,
+34321,27169,33180,30952,25705,39764,25273,26411,33707,22696,40664,27819,28448,
+23518,38476,35851,29279,26576,25287,29281,20137,22982,27597,22675,26286,24149,
+21215,24917,26408,30446,30566,29287,31302,25343,21738,21584,38048,37027,23068,
+32435,27670,20035,22902,32784,22856,21335,30007,38590,22218,25376,33041,24700,
+38393,28118,21602,39297,20869,23273,33021,22958,38675,20522,27877,23612,25311,
+20320,21311,33147,36870,28346,34091,25288,24180,30910,25781,25467,24565,23064,
+37247,40479,23615,25423,32834,23421,21870,38218,38221,28037,24744,26592,29406,
+20957,23425,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,
+33247,33248,33249,33250,33252,33253,33254,33256,33257,33259,33262,33263,33264,
+33265,33266,33269,33270,33271,33272,33273,33274,33277,33279,33283,33287,33288,
+33289,33290,33291,33294,33295,33297,33299,33301,33302,33303,33304,33305,33306,
+33309,33312,33316,33317,33318,33319,33321,33326,33330,33338,33340,33341,33343,
+33344,33345,33346,33347,33349,33350,33352,33354,33356,33357,33358,33360,33361,
+33362,33363,33364,33365,33366,33367,33369,33371,33372,33373,33374,33376,33377,
+33378,33379,33380,33381,33382,33383,33385,25319,27870,29275,25197,38062,32445,
+33043,27987,20892,24324,22900,21162,24594,22899,26262,34384,30111,25386,25062,
+31983,35834,21734,27431,40485,27572,34261,21589,20598,27812,21866,36276,29228,
+24085,24597,29750,25293,25490,29260,24472,28227,27966,25856,28504,30424,30928,
+30460,30036,21028,21467,20051,24222,26049,32810,32982,25243,21638,21032,28846,
+34957,36305,27873,21624,32986,22521,35060,36180,38506,37197,20329,27803,21943,
+30406,30768,25256,28921,28558,24429,34028,26842,30844,31735,33192,26379,40527,
+25447,30896,22383,30738,38713,25209,25259,21128,29749,27607,33386,33387,33388,
+33389,33393,33397,33398,33399,33400,33403,33404,33408,33409,33411,33413,33414,
+33415,33417,33420,33424,33427,33428,33429,33430,33434,33435,33438,33440,33442,
+33443,33447,33458,33461,33462,33466,33467,33468,33471,33472,33474,33475,33477,
+33478,33481,33488,33494,33497,33498,33501,33506,33511,33512,33513,33514,33516,
+33517,33518,33520,33522,33523,33525,33526,33528,33530,33532,33533,33534,33535,
+33536,33546,33547,33549,33552,33554,33555,33558,33560,33561,33565,33566,33567,
+33568,33569,33570,33571,33572,33573,33574,33577,33578,33582,33584,33586,33591,
+33595,33597,21860,33086,30130,30382,21305,30174,20731,23617,35692,31687,20559,
+29255,39575,39128,28418,29922,31080,25735,30629,25340,39057,36139,21697,32856,
+20050,22378,33529,33805,24179,20973,29942,35780,23631,22369,27900,39047,23110,
+30772,39748,36843,31893,21078,25169,38138,20166,33670,33889,33769,33970,22484,
+26420,22275,26222,28006,35889,26333,28689,26399,27450,26646,25114,22971,19971,
+20932,28422,26578,27791,20854,26827,22855,27495,30054,23822,33040,40784,26071,
+31048,31041,39569,36215,23682,20062,20225,21551,22865,30732,22120,27668,36804,
+24323,27773,27875,35755,25488,33598,33599,33601,33602,33604,33605,33608,33610,
+33611,33612,33613,33614,33619,33621,33622,33623,33624,33625,33629,33634,33648,
+33649,33650,33651,33652,33653,33654,33657,33658,33662,33663,33664,33665,33666,
+33667,33668,33671,33672,33674,33675,33676,33677,33679,33680,33681,33684,33685,
+33686,33687,33689,33690,33693,33695,33697,33698,33699,33700,33701,33702,33703,
+33708,33709,33710,33711,33717,33723,33726,33727,33730,33731,33732,33734,33736,
+33737,33739,33741,33742,33744,33745,33746,33747,33749,33751,33753,33754,33755,
+33758,33762,33763,33764,33766,33767,33768,33771,33772,33773,24688,27965,29301,
+25190,38030,38085,21315,36801,31614,20191,35878,20094,40660,38065,38067,21069,
+28508,36963,27973,35892,22545,23884,27424,27465,26538,21595,33108,32652,22681,
+34103,24378,25250,27207,38201,25970,24708,26725,30631,20052,20392,24039,38808,
+25772,32728,23789,20431,31373,20999,33540,19988,24623,31363,38054,20405,20146,
+31206,29748,21220,33465,25810,31165,23517,27777,38738,36731,27682,20542,21375,
+28165,25806,26228,27696,24773,39031,35831,24198,29756,31351,31179,19992,37041,
+29699,27714,22234,37195,27845,36235,21306,34502,26354,36527,23624,39537,28192,
+33774,33775,33779,33780,33781,33782,33783,33786,33787,33788,33790,33791,33792,
+33794,33797,33799,33800,33801,33802,33808,33810,33811,33812,33813,33814,33815,
+33817,33818,33819,33822,33823,33824,33825,33826,33827,33833,33834,33835,33836,
+33837,33838,33839,33840,33842,33843,33844,33845,33846,33847,33849,33850,33851,
+33854,33855,33856,33857,33858,33859,33860,33861,33863,33864,33865,33866,33867,
+33868,33869,33870,33871,33872,33874,33875,33876,33877,33878,33880,33885,33886,
+33887,33888,33890,33892,33893,33894,33895,33896,33898,33902,33903,33904,33906,
+33908,33911,33913,33915,33916,21462,23094,40843,36259,21435,22280,39079,26435,
+37275,27849,20840,30154,25331,29356,21048,21149,32570,28820,30264,21364,40522,
+27063,30830,38592,35033,32676,28982,29123,20873,26579,29924,22756,25880,22199,
+35753,39286,25200,32469,24825,28909,22764,20161,20154,24525,38887,20219,35748,
+20995,22922,32427,25172,20173,26085,25102,33592,33993,33635,34701,29076,28342,
+23481,32466,20887,25545,26580,32905,33593,34837,20754,23418,22914,36785,20083,
+27741,20837,35109,36719,38446,34122,29790,38160,38384,28070,33509,24369,25746,
+27922,33832,33134,40131,22622,36187,19977,21441,33917,33918,33919,33920,33921,
+33923,33924,33925,33926,33930,33933,33935,33936,33937,33938,33939,33940,33941,
+33942,33944,33946,33947,33949,33950,33951,33952,33954,33955,33956,33957,33958,
+33959,33960,33961,33962,33963,33964,33965,33966,33968,33969,33971,33973,33974,
+33975,33979,33980,33982,33984,33986,33987,33989,33990,33991,33992,33995,33996,
+33998,33999,34002,34004,34005,34007,34008,34009,34010,34011,34012,34014,34017,
+34018,34020,34023,34024,34025,34026,34027,34029,34030,34031,34033,34034,34035,
+34036,34037,34038,34039,34040,34041,34042,34043,34045,34046,34048,34049,34050,
+20254,25955,26705,21971,20007,25620,39578,25195,23234,29791,33394,28073,26862,
+20711,33678,30722,26432,21049,27801,32433,20667,21861,29022,31579,26194,29642,
+33515,26441,23665,21024,29053,34923,38378,38485,25797,36193,33203,21892,27733,
+25159,32558,22674,20260,21830,36175,26188,19978,23578,35059,26786,25422,31245,
+28903,33421,21242,38902,23569,21736,37045,32461,22882,36170,34503,33292,33293,
+36198,25668,23556,24913,28041,31038,35774,30775,30003,21627,20280,36523,28145,
+23072,32453,31070,27784,23457,23158,29978,32958,24910,28183,22768,29983,29989,
+29298,21319,32499,34051,34052,34053,34054,34055,34056,34057,34058,34059,34061,
+34062,34063,34064,34066,34068,34069,34070,34072,34073,34075,34076,34077,34078,
+34080,34082,34083,34084,34085,34086,34087,34088,34089,34090,34093,34094,34095,
+34096,34097,34098,34099,34100,34101,34102,34110,34111,34112,34113,34114,34116,
+34117,34118,34119,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,
+34133,34135,34136,34138,34139,34140,34141,34143,34144,34145,34146,34147,34149,
+34150,34151,34153,34154,34155,34156,34157,34158,34159,34160,34161,34163,34165,
+34166,34167,34168,34172,34173,34175,34176,34177,30465,30427,21097,32988,22307,
+24072,22833,29422,26045,28287,35799,23608,34417,21313,30707,25342,26102,20160,
+39135,34432,23454,35782,21490,30690,20351,23630,39542,22987,24335,31034,22763,
+19990,26623,20107,25325,35475,36893,21183,26159,21980,22124,36866,20181,20365,
+37322,39280,27663,24066,24643,23460,35270,35797,25910,25163,39318,23432,23551,
+25480,21806,21463,30246,20861,34092,26530,26803,27530,25234,36755,21460,33298,
+28113,30095,20070,36174,23408,29087,34223,26257,26329,32626,34560,40653,40736,
+23646,26415,36848,26641,26463,25101,31446,22661,24246,25968,28465,34178,34179,
+34182,34184,34185,34186,34187,34188,34189,34190,34192,34193,34194,34195,34196,
+34197,34198,34199,34200,34201,34202,34205,34206,34207,34208,34209,34210,34211,
+34213,34214,34215,34217,34219,34220,34221,34225,34226,34227,34228,34229,34230,
+34232,34234,34235,34236,34237,34238,34239,34240,34242,34243,34244,34245,34246,
+34247,34248,34250,34251,34252,34253,34254,34257,34258,34260,34262,34263,34264,
+34265,34266,34267,34269,34270,34271,34272,34273,34274,34275,34277,34278,34279,
+34280,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,
+34294,34295,34296,24661,21047,32781,25684,34928,29993,24069,26643,25332,38684,
+21452,29245,35841,27700,30561,31246,21550,30636,39034,33308,35828,30805,26388,
+28865,26031,25749,22070,24605,31169,21496,19997,27515,32902,23546,21987,22235,
+20282,20284,39282,24051,26494,32824,24578,39042,36865,23435,35772,35829,25628,
+33368,25822,22013,33487,37221,20439,32032,36895,31903,20723,22609,28335,23487,
+35785,32899,37240,33948,31639,34429,38539,38543,32485,39635,30862,23681,31319,
+36930,38567,31071,23385,25439,31499,34001,26797,21766,32553,29712,32034,38145,
+25152,22604,20182,23427,22905,22612,34297,34298,34300,34301,34302,34304,34305,
+34306,34307,34308,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,
+34320,34322,34323,34324,34325,34327,34328,34329,34330,34331,34332,34333,34334,
+34335,34336,34337,34338,34339,34340,34341,34342,34344,34346,34347,34348,34349,
+34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34361,34362,34363,
+34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,
+34378,34379,34380,34386,34387,34389,34390,34391,34392,34393,34395,34396,34397,
+34399,34400,34401,34403,34404,34405,34406,34407,34408,34409,34410,29549,25374,
+36427,36367,32974,33492,25260,21488,27888,37214,22826,24577,27760,22349,25674,
+36138,30251,28393,22363,27264,30192,28525,35885,35848,22374,27631,34962,30899,
+25506,21497,28845,27748,22616,25642,22530,26848,33179,21776,31958,20504,36538,
+28108,36255,28907,25487,28059,28372,32486,33796,26691,36867,28120,38518,35752,
+22871,29305,34276,33150,30140,35466,26799,21076,36386,38161,25552,39064,36420,
+21884,20307,26367,22159,24789,28053,21059,23625,22825,28155,22635,30000,29980,
+24684,33300,33094,25361,26465,36834,30522,36339,36148,38081,24086,21381,21548,
+28867,34413,34415,34416,34418,34419,34420,34421,34422,34423,34424,34435,34436,
+34437,34438,34439,34440,34441,34446,34447,34448,34449,34450,34452,34454,34455,
+34456,34457,34458,34459,34462,34463,34464,34465,34466,34469,34470,34475,34477,
+34478,34482,34483,34487,34488,34489,34491,34492,34493,34494,34495,34497,34498,
+34499,34501,34504,34508,34509,34514,34515,34517,34518,34519,34522,34524,34525,
+34528,34529,34530,34531,34533,34534,34535,34536,34538,34539,34540,34543,34549,
+34550,34551,34554,34555,34556,34557,34559,34561,34564,34565,34566,34571,34572,
+34574,34575,34576,34577,34580,34582,27712,24311,20572,20141,24237,25402,33351,
+36890,26704,37230,30643,21516,38108,24420,31461,26742,25413,31570,32479,30171,
+20599,25237,22836,36879,20984,31171,31361,22270,24466,36884,28034,23648,22303,
+21520,20820,28237,22242,25512,39059,33151,34581,35114,36864,21534,23663,33216,
+25302,25176,33073,40501,38464,39534,39548,26925,22949,25299,21822,25366,21703,
+34521,27964,23043,29926,34972,27498,22806,35916,24367,28286,29609,39037,20024,
+28919,23436,30871,25405,26202,30358,24779,23451,23113,19975,33109,27754,29579,
+20129,26505,32593,24448,26106,26395,24536,22916,23041,34585,34587,34589,34591,
+34592,34596,34598,34599,34600,34602,34603,34604,34605,34607,34608,34610,34611,
+34613,34614,34616,34617,34618,34620,34621,34624,34625,34626,34627,34628,34629,
+34630,34634,34635,34637,34639,34640,34641,34642,34644,34645,34646,34648,34650,
+34651,34652,34653,34654,34655,34657,34658,34662,34663,34664,34665,34666,34667,
+34668,34669,34671,34673,34674,34675,34677,34679,34680,34681,34682,34687,34688,
+34689,34692,34694,34695,34697,34698,34700,34702,34703,34704,34705,34706,34708,
+34709,34710,34712,34713,34714,34715,34716,34717,34718,34720,34721,34722,34723,
+34724,24013,24494,21361,38886,36829,26693,22260,21807,24799,20026,28493,32500,
+33479,33806,22996,20255,20266,23614,32428,26410,34074,21619,30031,32963,21890,
+39759,20301,28205,35859,23561,24944,21355,30239,28201,34442,25991,38395,32441,
+21563,31283,32010,38382,21985,32705,29934,25373,34583,28065,31389,25105,26017,
+21351,25569,27779,24043,21596,38056,20044,27745,35820,23627,26080,33436,26791,
+21566,21556,27595,27494,20116,25410,21320,33310,20237,20398,22366,25098,38654,
+26212,29289,21247,21153,24735,35823,26132,29081,26512,35199,30802,30717,26224,
+22075,21560,38177,29306,34725,34726,34727,34729,34730,34734,34736,34737,34738,
+34740,34742,34743,34744,34745,34747,34748,34750,34751,34753,34754,34755,34756,
+34757,34759,34760,34761,34764,34765,34766,34767,34768,34772,34773,34774,34775,
+34776,34777,34778,34780,34781,34782,34783,34785,34786,34787,34788,34790,34791,
+34792,34793,34795,34796,34797,34799,34800,34801,34802,34803,34804,34805,34806,
+34807,34808,34810,34811,34812,34813,34815,34816,34817,34818,34820,34821,34822,
+34823,34824,34825,34827,34828,34829,34830,34831,34832,34833,34834,34836,34839,
+34840,34841,34842,34844,34845,34846,34847,34848,34851,31232,24687,24076,24713,
+33181,22805,24796,29060,28911,28330,27728,29312,27268,34989,24109,20064,23219,
+21916,38115,27927,31995,38553,25103,32454,30606,34430,21283,38686,36758,26247,
+23777,20384,29421,19979,21414,22799,21523,25472,38184,20808,20185,40092,32420,
+21688,36132,34900,33335,38386,28046,24358,23244,26174,38505,29616,29486,21439,
+33146,39301,32673,23466,38519,38480,32447,30456,21410,38262,39321,31665,35140,
+28248,20065,32724,31077,35814,24819,21709,20139,39033,24055,27233,20687,21521,
+35937,33831,30813,38660,21066,21742,22179,38144,28040,23477,28102,26195,34852,
+34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,
+34867,34868,34869,34870,34871,34872,34874,34875,34877,34878,34879,34881,34882,
+34883,34886,34887,34888,34889,34890,34891,34894,34895,34896,34897,34898,34899,
+34901,34902,34904,34906,34907,34908,34909,34910,34911,34912,34918,34919,34922,
+34925,34927,34929,34931,34932,34933,34934,34936,34937,34938,34939,34940,34944,
+34947,34950,34951,34953,34954,34956,34958,34959,34960,34961,34963,34964,34965,
+34967,34968,34969,34970,34971,34973,34974,34975,34976,34977,34979,34981,34982,
+34983,34984,34985,34986,23567,23389,26657,32918,21880,31505,25928,26964,20123,
+27463,34638,38795,21327,25375,25658,37034,26012,32961,35856,20889,26800,21368,
+34809,25032,27844,27899,35874,23633,34218,33455,38156,27427,36763,26032,24571,
+24515,20449,34885,26143,33125,29481,24826,20852,21009,22411,24418,37026,34892,
+37266,24184,26447,24615,22995,20804,20982,33016,21256,27769,38596,29066,20241,
+20462,32670,26429,21957,38152,31168,34966,32483,22687,25100,38656,34394,22040,
+39035,24464,35768,33988,37207,21465,26093,24207,30044,24676,32110,23167,32490,
+32493,36713,21927,23459,24748,26059,29572,34988,34990,34991,34992,34994,34995,
+34996,34997,34998,35000,35001,35002,35003,35005,35006,35007,35008,35011,35012,
+35015,35016,35018,35019,35020,35021,35023,35024,35025,35027,35030,35031,35034,
+35035,35036,35037,35038,35040,35041,35046,35047,35049,35050,35051,35052,35053,
+35054,35055,35058,35061,35062,35063,35066,35067,35069,35071,35072,35073,35075,
+35076,35077,35078,35079,35080,35081,35083,35084,35085,35086,35087,35089,35092,
+35093,35094,35095,35096,35100,35101,35102,35103,35104,35106,35107,35108,35110,
+35111,35112,35113,35116,35117,35118,35119,35121,35122,35123,35125,35127,36873,
+30307,30505,32474,38772,34203,23398,31348,38634,34880,21195,29071,24490,26092,
+35810,23547,39535,24033,27529,27739,35757,35759,36874,36805,21387,25276,40486,
+40493,21568,20011,33469,29273,34460,23830,34905,28079,38597,21713,20122,35766,
+28937,21693,38409,28895,28153,30416,20005,30740,34578,23721,24310,35328,39068,
+38414,28814,27839,22852,25513,30524,34893,28436,33395,22576,29141,21388,30746,
+38593,21761,24422,28976,23476,35866,39564,27523,22830,40495,31207,26472,25196,
+20335,30113,32650,27915,38451,27687,20208,30162,20859,26679,28478,36992,33136,
+22934,29814,35128,35129,35130,35131,35132,35133,35134,35135,35136,35138,35139,
+35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,
+35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35168,
+35169,35170,35171,35172,35173,35175,35176,35177,35178,35179,35180,35181,35182,
+35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35196,
+35197,35198,35200,35202,35204,35205,35207,35208,35209,35210,35211,35212,35213,
+35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,
+35227,35228,35229,35230,35231,35232,35233,25671,23591,36965,31377,35875,23002,
+21676,33280,33647,35201,32768,26928,22094,32822,29239,37326,20918,20063,39029,
+25494,19994,21494,26355,33099,22812,28082,19968,22777,21307,25558,38129,20381,
+20234,34915,39056,22839,36951,31227,20202,33008,30097,27778,23452,23016,24413,
+26885,34433,20506,24050,20057,30691,20197,33402,25233,26131,37009,23673,20159,
+24441,33222,36920,32900,30123,20134,35028,24847,27589,24518,20041,30410,28322,
+35811,35758,35850,35793,24322,32764,32716,32462,33589,33643,22240,27575,38899,
+38452,23035,21535,38134,28139,23493,39278,23609,24341,38544,35234,35235,35236,
+35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,
+35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,
+35263,35264,35267,35277,35283,35284,35285,35287,35288,35289,35291,35293,35295,
+35296,35297,35298,35300,35303,35304,35305,35306,35308,35309,35310,35312,35313,
+35314,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,
+35329,35330,35331,35332,35333,35334,35336,35337,35338,35339,35340,35341,35342,
+35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,
+35356,35357,21360,33521,27185,23156,40560,24212,32552,33721,33828,33829,33639,
+34631,36814,36194,30408,24433,39062,30828,26144,21727,25317,20323,33219,30152,
+24248,38605,36362,34553,21647,27891,28044,27704,24703,21191,29992,24189,20248,
+24736,24551,23588,30001,37038,38080,29369,27833,28216,37193,26377,21451,21491,
+20305,37321,35825,21448,24188,36802,28132,20110,30402,27014,34398,24858,33286,
+20313,20446,36926,40060,24841,28189,28180,38533,20104,23089,38632,19982,23679,
+31161,23431,35821,32701,29577,22495,33419,37057,21505,36935,21947,23786,24481,
+24840,27442,29425,32946,35465,35358,35359,35360,35361,35362,35363,35364,35365,
+35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,
+35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35391,35392,
+35393,35394,35395,35396,35397,35398,35399,35401,35402,35403,35404,35405,35406,
+35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,
+35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,
+35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,
+35446,35447,35448,35450,35451,35452,35453,35454,35455,35456,28020,23507,35029,
+39044,35947,39533,40499,28170,20900,20803,22435,34945,21407,25588,36757,22253,
+21592,22278,29503,28304,32536,36828,33489,24895,24616,38498,26352,32422,36234,
+36291,38053,23731,31908,26376,24742,38405,32792,20113,37095,21248,38504,20801,
+36816,34164,37213,26197,38901,23381,21277,30776,26434,26685,21705,28798,23472,
+36733,20877,22312,21681,25874,26242,36190,36163,33039,33900,36973,31967,20991,
+34299,26531,26089,28577,34468,36481,22122,36896,30338,28790,29157,36131,25321,
+21017,27901,36156,24590,22686,24974,26366,36192,25166,21939,28195,26413,36711,
+35457,35458,35459,35460,35461,35462,35463,35464,35467,35468,35469,35470,35471,
+35472,35473,35474,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,
+35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,
+35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,
+35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,
+35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,
+35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,
+35551,35552,35553,35554,35555,38113,38392,30504,26629,27048,21643,20045,28856,
+35784,25688,25995,23429,31364,20538,23528,30651,27617,35449,31896,27838,30415,
+26025,36759,23853,23637,34360,26632,21344,25112,31449,28251,32509,27167,31456,
+24432,28467,24352,25484,28072,26454,19976,24080,36134,20183,32960,30260,38556,
+25307,26157,25214,27836,36213,29031,32617,20806,32903,21484,36974,25240,21746,
+34544,36761,32773,38167,34071,36825,27993,29645,26015,30495,29956,30759,33275,
+36126,38024,20390,26517,30137,35786,38663,25391,38215,38453,33976,25379,30529,
+24449,29424,20105,24596,25972,25327,27491,25919,35556,35557,35558,35559,35560,
+35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,
+35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,
+35587,35588,35589,35590,35592,35593,35594,35595,35596,35597,35598,35599,35600,
+35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,
+35614,35615,35616,35617,35618,35619,35620,35621,35623,35624,35625,35626,35627,
+35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,
+35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,
+24103,30151,37073,35777,33437,26525,25903,21553,34584,30693,32930,33026,27713,
+20043,32455,32844,30452,26893,27542,25191,20540,20356,22336,25351,27490,36286,
+21482,26088,32440,24535,25370,25527,33267,33268,32622,24092,23769,21046,26234,
+31209,31258,36136,28825,30164,28382,27835,31378,20013,30405,24544,38047,34935,
+32456,31181,32959,37325,20210,20247,33311,21608,24030,27954,35788,31909,36724,
+32920,24090,21650,30385,23449,26172,39588,29664,26666,34523,26417,29482,35832,
+35803,36880,31481,28891,29038,25284,30633,22065,20027,33879,26609,21161,34496,
+36142,38136,31569,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,
+35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,
+35677,35678,35679,35680,35681,35682,35683,35684,35685,35687,35688,35689,35690,
+35691,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,
+35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,
+35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,
+35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,
+35756,35761,35771,35783,35792,35818,35849,35870,20303,27880,31069,39547,25235,
+29226,25341,19987,30742,36716,25776,36186,31686,26729,24196,35013,22918,25758,
+22766,29366,26894,38181,36861,36184,22368,32512,35846,20934,25417,25305,21331,
+26700,29730,33537,37196,21828,30528,28796,27978,20857,21672,36164,23039,28363,
+28100,23388,32043,20180,31869,28371,23376,33258,28173,23383,39683,26837,36394,
+23447,32508,24635,32437,37049,36208,22863,25549,31199,36275,21330,26063,31062,
+35781,38459,32452,38075,32386,22068,37257,26368,32618,23562,36981,26152,24038,
+20304,26590,20570,20316,22352,24231,59408,59409,59410,59411,59412,35896,35897,
+35898,35899,35900,35901,35902,35903,35904,35906,35907,35908,35909,35912,35914,
+35915,35917,35918,35919,35920,35921,35922,35923,35924,35926,35927,35928,35929,
+35931,35932,35933,35934,35935,35936,35939,35940,35941,35942,35943,35944,35945,
+35948,35949,35950,35951,35952,35953,35954,35956,35957,35958,35959,35963,35964,
+35965,35966,35967,35968,35969,35971,35972,35974,35975,35976,35979,35981,35982,
+35983,35984,35985,35986,35987,35989,35990,35991,35993,35994,35995,35996,35997,
+35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,
+36011,36012,36013,20109,19980,20800,19984,24319,21317,19989,20120,19998,39730,
+23404,22121,20008,31162,20031,21269,20039,22829,29243,21358,27664,22239,32996,
+39319,27603,30590,40727,20022,20127,40720,20060,20073,20115,33416,23387,21868,
+22031,20164,21389,21405,21411,21413,21422,38757,36189,21274,21493,21286,21294,
+21310,36188,21350,21347,20994,21000,21006,21037,21043,21055,21056,21068,21086,
+21089,21084,33967,21117,21122,21121,21136,21139,20866,32596,20155,20163,20169,
+20162,20200,20193,20203,20190,20251,20211,20258,20324,20213,20261,20263,20233,
+20267,20318,20327,25912,20314,20317,36014,36015,36016,36017,36018,36019,36020,
+36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,
+36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,
+36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,
+36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,
+36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,
+36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,
+36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,20319,20311,
+20274,20285,20342,20340,20369,20361,20355,20367,20350,20347,20394,20348,20396,
+20372,20454,20456,20458,20421,20442,20451,20444,20433,20447,20472,20521,20556,
+20467,20524,20495,20526,20525,20478,20508,20492,20517,20520,20606,20547,20565,
+20552,20558,20588,20603,20645,20647,20649,20666,20694,20742,20717,20716,20710,
+20718,20743,20747,20189,27709,20312,20325,20430,40864,27718,31860,20846,24061,
+40649,39320,20865,22804,21241,21261,35335,21264,20971,22809,20821,20128,20822,
+20147,34926,34980,20149,33044,35026,31104,23348,34819,32696,20907,20913,20925,
+20924,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,
+36122,36123,36124,36128,36177,36178,36183,36191,36197,36200,36201,36202,36204,
+36206,36207,36209,36210,36216,36217,36218,36219,36220,36221,36222,36223,36224,
+36226,36227,36230,36231,36232,36233,36236,36237,36238,36239,36240,36242,36243,
+36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36256,36257,36258,
+36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,
+36274,36278,36279,36281,36283,36285,36288,36289,36290,36293,36295,36296,36297,
+36298,36301,36304,36306,36307,36308,20935,20886,20898,20901,35744,35750,35751,
+35754,35764,35765,35767,35778,35779,35787,35791,35790,35794,35795,35796,35798,
+35800,35801,35804,35807,35808,35812,35816,35817,35822,35824,35827,35830,35833,
+35836,35839,35840,35842,35844,35847,35852,35855,35857,35858,35860,35861,35862,
+35865,35867,35864,35869,35871,35872,35873,35877,35879,35882,35883,35886,35887,
+35890,35891,35893,35894,21353,21370,38429,38434,38433,38449,38442,38461,38460,
+38466,38473,38484,38495,38503,38508,38514,38516,38536,38541,38551,38576,37015,
+37019,37021,37017,37036,37025,37044,37043,37046,37050,36309,36312,36313,36316,
+36320,36321,36322,36325,36326,36327,36329,36333,36334,36336,36337,36338,36340,
+36342,36348,36350,36351,36352,36353,36354,36355,36356,36358,36359,36360,36363,
+36365,36366,36368,36369,36370,36371,36373,36374,36375,36376,36377,36378,36379,
+36380,36384,36385,36388,36389,36390,36391,36392,36395,36397,36400,36402,36403,
+36404,36406,36407,36408,36411,36412,36414,36415,36419,36421,36422,36428,36429,
+36430,36431,36432,36435,36436,36437,36438,36439,36440,36442,36443,36444,36445,
+36446,36447,36448,36449,36450,36451,36452,36453,36455,36456,36458,36459,36462,
+36465,37048,37040,37071,37061,37054,37072,37060,37063,37075,37094,37090,37084,
+37079,37083,37099,37103,37118,37124,37154,37150,37155,37169,37167,37177,37187,
+37190,21005,22850,21154,21164,21165,21182,21759,21200,21206,21232,21471,29166,
+30669,24308,20981,20988,39727,21430,24321,30042,24047,22348,22441,22433,22654,
+22716,22725,22737,22313,22316,22314,22323,22329,22318,22319,22364,22331,22338,
+22377,22405,22379,22406,22396,22395,22376,22381,22390,22387,22445,22436,22412,
+22450,22479,22439,22452,22419,22432,22485,22488,22490,22489,22482,22456,22516,
+22511,22520,22500,22493,36467,36469,36471,36472,36473,36474,36475,36477,36478,
+36480,36482,36483,36484,36486,36488,36489,36490,36491,36492,36493,36494,36497,
+36498,36499,36501,36502,36503,36504,36505,36506,36507,36509,36511,36512,36513,
+36514,36515,36516,36517,36518,36519,36520,36521,36522,36525,36526,36528,36529,
+36531,36532,36533,36534,36535,36536,36537,36539,36540,36541,36542,36543,36544,
+36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,
+36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,
+36572,36573,36574,36575,36576,36577,36578,36579,36580,22539,22541,22525,22509,
+22528,22558,22553,22596,22560,22629,22636,22657,22665,22682,22656,39336,40729,
+25087,33401,33405,33407,33423,33418,33448,33412,33422,33425,33431,33433,33451,
+33464,33470,33456,33480,33482,33507,33432,33463,33454,33483,33484,33473,33449,
+33460,33441,33450,33439,33476,33486,33444,33505,33545,33527,33508,33551,33543,
+33500,33524,33490,33496,33548,33531,33491,33553,33562,33542,33556,33557,33504,
+33493,33564,33617,33627,33628,33544,33682,33596,33588,33585,33691,33630,33583,
+33615,33607,33603,33631,33600,33559,33632,33581,33594,33587,33638,33637,36581,
+36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,
+36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,
+36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,
+36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,
+36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,
+36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,
+36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,
+36673,36674,36675,36676,33640,33563,33641,33644,33642,33645,33646,33712,33656,
+33715,33716,33696,33706,33683,33692,33669,33660,33718,33705,33661,33720,33659,
+33688,33694,33704,33722,33724,33729,33793,33765,33752,22535,33816,33803,33757,
+33789,33750,33820,33848,33809,33798,33748,33759,33807,33795,33784,33785,33770,
+33733,33728,33830,33776,33761,33884,33873,33882,33881,33907,33927,33928,33914,
+33929,33912,33852,33862,33897,33910,33932,33934,33841,33901,33985,33997,34000,
+34022,33981,34003,33994,33983,33978,34016,33953,33977,33972,33943,34021,34019,
+34060,29965,34104,34032,34105,34079,34106,36677,36678,36679,36680,36681,36682,
+36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,
+36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,
+36709,36714,36736,36748,36754,36765,36768,36769,36770,36772,36773,36774,36775,
+36778,36780,36781,36782,36783,36786,36787,36788,36789,36791,36792,36794,36795,
+36796,36799,36800,36803,36806,36809,36810,36811,36812,36813,36815,36818,36822,
+36823,36826,36832,36833,36835,36839,36844,36847,36849,36850,36852,36853,36854,
+36858,36859,36860,36862,36863,36871,36872,36876,36878,36883,36885,36888,34134,
+34107,34047,34044,34137,34120,34152,34148,34142,34170,30626,34115,34162,34171,
+34212,34216,34183,34191,34169,34222,34204,34181,34233,34231,34224,34259,34241,
+34268,34303,34343,34309,34345,34326,34364,24318,24328,22844,22849,32823,22869,
+22874,22872,21263,23586,23589,23596,23604,25164,25194,25247,25275,25290,25306,
+25303,25326,25378,25334,25401,25419,25411,25517,25590,25457,25466,25486,25524,
+25453,25516,25482,25449,25518,25532,25586,25592,25568,25599,25540,25566,25550,
+25682,25542,25534,25669,25665,25611,25627,25632,25612,25638,25633,25694,25732,
+25709,25750,36889,36892,36899,36900,36901,36903,36904,36905,36906,36907,36908,
+36912,36913,36914,36915,36916,36919,36921,36922,36925,36927,36928,36931,36933,
+36934,36936,36937,36938,36939,36940,36942,36948,36949,36950,36953,36954,36956,
+36957,36958,36959,36960,36961,36964,36966,36967,36969,36970,36971,36972,36975,
+36976,36977,36978,36979,36982,36983,36984,36985,36986,36987,36988,36990,36993,
+36996,36997,36998,36999,37001,37002,37004,37005,37006,37007,37008,37010,37012,
+37014,37016,37018,37020,37022,37023,37024,37028,37029,37031,37032,37033,37035,
+37037,37042,37047,37052,37053,37055,37056,25722,25783,25784,25753,25786,25792,
+25808,25815,25828,25826,25865,25893,25902,24331,24530,29977,24337,21343,21489,
+21501,21481,21480,21499,21522,21526,21510,21579,21586,21587,21588,21590,21571,
+21537,21591,21593,21539,21554,21634,21652,21623,21617,21604,21658,21659,21636,
+21622,21606,21661,21712,21677,21698,21684,21714,21671,21670,21715,21716,21618,
+21667,21717,21691,21695,21708,21721,21722,21724,21673,21674,21668,21725,21711,
+21726,21787,21735,21792,21757,21780,21747,21794,21795,21775,21777,21799,21802,
+21863,21903,21941,21833,21869,21825,21845,21823,21840,21820,37058,37059,37062,
+37064,37065,37067,37068,37069,37074,37076,37077,37078,37080,37081,37082,37086,
+37087,37088,37091,37092,37093,37097,37098,37100,37102,37104,37105,37106,37107,
+37109,37110,37111,37113,37114,37115,37116,37119,37120,37121,37123,37125,37126,
+37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,
+37140,37141,37142,37143,37144,37146,37147,37148,37149,37151,37152,37153,37156,
+37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37168,37170,37171,
+37172,37173,37174,37175,37176,37178,37179,37180,37181,37182,37183,37184,37185,
+37186,37188,21815,21846,21877,21878,21879,21811,21808,21852,21899,21970,21891,
+21937,21945,21896,21889,21919,21886,21974,21905,21883,21983,21949,21950,21908,
+21913,21994,22007,21961,22047,21969,21995,21996,21972,21990,21981,21956,21999,
+21989,22002,22003,21964,21965,21992,22005,21988,36756,22046,22024,22028,22017,
+22052,22051,22014,22016,22055,22061,22104,22073,22103,22060,22093,22114,22105,
+22108,22092,22100,22150,22116,22129,22123,22139,22140,22149,22163,22191,22228,
+22231,22237,22241,22261,22251,22265,22271,22276,22282,22281,22300,24079,24089,
+24084,24081,24113,24123,24124,37189,37191,37192,37201,37203,37204,37205,37206,
+37208,37209,37211,37212,37215,37216,37222,37223,37224,37227,37229,37235,37242,
+37243,37244,37248,37249,37250,37251,37252,37254,37256,37258,37262,37263,37267,
+37268,37269,37270,37271,37272,37273,37276,37277,37278,37279,37280,37281,37284,
+37285,37286,37287,37288,37289,37291,37292,37296,37297,37298,37299,37302,37303,
+37304,37305,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,
+37318,37320,37323,37328,37330,37331,37332,37333,37334,37335,37336,37337,37338,
+37339,37341,37342,37343,37344,37345,37346,37347,37348,37349,24119,24132,24148,
+24155,24158,24161,23692,23674,23693,23696,23702,23688,23704,23705,23697,23706,
+23708,23733,23714,23741,23724,23723,23729,23715,23745,23735,23748,23762,23780,
+23755,23781,23810,23811,23847,23846,23854,23844,23838,23814,23835,23896,23870,
+23860,23869,23916,23899,23919,23901,23915,23883,23882,23913,23924,23938,23961,
+23965,35955,23991,24005,24435,24439,24450,24455,24457,24460,24469,24473,24476,
+24488,24493,24501,24508,34914,24417,29357,29360,29364,29367,29368,29379,29377,
+29390,29389,29394,29416,29423,29417,29426,29428,29431,29441,29427,29443,29434,
+37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,
+37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,
+37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,
+37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,
+37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,
+37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,
+37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,
+37441,37442,37443,37444,37445,29435,29463,29459,29473,29450,29470,29469,29461,
+29474,29497,29477,29484,29496,29489,29520,29517,29527,29536,29548,29551,29566,
+33307,22821,39143,22820,22786,39267,39271,39272,39273,39274,39275,39276,39284,
+39287,39293,39296,39300,39303,39306,39309,39312,39313,39315,39316,39317,24192,
+24209,24203,24214,24229,24224,24249,24245,24254,24243,36179,24274,24273,24283,
+24296,24298,33210,24516,24521,24534,24527,24579,24558,24580,24545,24548,24574,
+24581,24582,24554,24557,24568,24601,24629,24614,24603,24591,24589,24617,24619,
+24586,24639,24609,24696,24697,24699,24698,24642,37446,37447,37448,37449,37450,
+37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,
+37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,
+37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,
+37490,37491,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,
+37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,
+37517,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,
+37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,
+24682,24701,24726,24730,24749,24733,24707,24722,24716,24731,24812,24763,24753,
+24797,24792,24774,24794,24756,24864,24870,24853,24867,24820,24832,24846,24875,
+24906,24949,25004,24980,24999,25015,25044,25077,24541,38579,38377,38379,38385,
+38387,38389,38390,38396,38398,38403,38404,38406,38408,38410,38411,38412,38413,
+38415,38418,38421,38422,38423,38425,38426,20012,29247,25109,27701,27732,27740,
+27722,27811,27781,27792,27796,27788,27752,27753,27764,27766,27782,27817,27856,
+27860,27821,27895,27896,27889,27863,27826,27872,27862,27898,27883,27886,27825,
+27859,27887,27902,37544,37545,37546,37547,37548,37549,37551,37552,37553,37554,
+37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,
+37568,37569,37570,37571,37572,37573,37574,37575,37577,37578,37579,37580,37581,
+37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,
+37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,
+37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,
+37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,
+37634,37635,37636,37637,37638,37639,37640,37641,27961,27943,27916,27971,27976,
+27911,27908,27929,27918,27947,27981,27950,27957,27930,27983,27986,27988,27955,
+28049,28015,28062,28064,27998,28051,28052,27996,28000,28028,28003,28186,28103,
+28101,28126,28174,28095,28128,28177,28134,28125,28121,28182,28075,28172,28078,
+28203,28270,28238,28267,28338,28255,28294,28243,28244,28210,28197,28228,28383,
+28337,28312,28384,28461,28386,28325,28327,28349,28347,28343,28375,28340,28367,
+28303,28354,28319,28514,28486,28487,28452,28437,28409,28463,28470,28491,28532,
+28458,28425,28457,28553,28557,28556,28536,28530,28540,28538,28625,37642,37643,
+37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,
+37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,
+37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,
+37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37695,37696,
+37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,
+37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,
+37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,
+37736,37737,37739,28617,28583,28601,28598,28610,28641,28654,28638,28640,28655,
+28698,28707,28699,28729,28725,28751,28766,23424,23428,23445,23443,23461,23480,
+29999,39582,25652,23524,23534,35120,23536,36423,35591,36790,36819,36821,36837,
+36846,36836,36841,36838,36851,36840,36869,36868,36875,36902,36881,36877,36886,
+36897,36917,36918,36909,36911,36932,36945,36946,36944,36968,36952,36962,36955,
+26297,36980,36989,36994,37000,36995,37003,24400,24407,24406,24408,23611,21675,
+23632,23641,23409,23651,23654,32700,24362,24361,24365,33396,24380,39739,23662,
+22913,22915,22925,22953,22954,22947,37740,37741,37742,37743,37744,37745,37746,
+37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,
+37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,
+37773,37774,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,
+37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,
+37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,
+37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,
+37826,37827,37828,37829,37830,37831,37832,37833,37835,37836,37837,22935,22986,
+22955,22942,22948,22994,22962,22959,22999,22974,23045,23046,23005,23048,23011,
+23000,23033,23052,23049,23090,23092,23057,23075,23059,23104,23143,23114,23125,
+23100,23138,23157,33004,23210,23195,23159,23162,23230,23275,23218,23250,23252,
+23224,23264,23267,23281,23254,23270,23256,23260,23305,23319,23318,23346,23351,
+23360,23573,23580,23386,23397,23411,23377,23379,23394,39541,39543,39544,39546,
+39551,39549,39552,39553,39557,39560,39562,39568,39570,39571,39574,39576,39579,
+39580,39581,39583,39584,39586,39587,39589,39591,32415,32417,32419,32421,32424,
+32425,37838,37839,37840,37841,37842,37843,37844,37845,37847,37848,37849,37850,
+37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,
+37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,
+37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,
+37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,
+37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,
+37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,
+37929,37930,37931,37932,37933,37934,32429,32432,32446,32448,32449,32450,32457,
+32459,32460,32464,32468,32471,32475,32480,32481,32488,32491,32494,32495,32497,
+32498,32525,32502,32506,32507,32510,32513,32514,32515,32519,32520,32523,32524,
+32527,32529,32530,32535,32537,32540,32539,32543,32545,32546,32547,32548,32549,
+32550,32551,32554,32555,32556,32557,32559,32560,32561,32562,32563,32565,24186,
+30079,24027,30014,37013,29582,29585,29614,29602,29599,29647,29634,29649,29623,
+29619,29632,29641,29640,29669,29657,39036,29706,29673,29671,29662,29626,29682,
+29711,29738,29787,29734,29733,29736,29744,29742,29740,37935,37936,37937,37938,
+37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37951,37952,
+37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,
+37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,
+37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,
+37992,37993,37994,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,
+38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,
+38019,38020,38033,38038,38040,38087,38095,38099,38100,38106,38118,38139,38172,
+38176,29723,29722,29761,29788,29783,29781,29785,29815,29805,29822,29852,29838,
+29824,29825,29831,29835,29854,29864,29865,29840,29863,29906,29882,38890,38891,
+38892,26444,26451,26462,26440,26473,26533,26503,26474,26483,26520,26535,26485,
+26536,26526,26541,26507,26487,26492,26608,26633,26584,26634,26601,26544,26636,
+26585,26549,26586,26547,26589,26624,26563,26552,26594,26638,26561,26621,26674,
+26675,26720,26721,26702,26722,26692,26724,26755,26653,26709,26726,26689,26727,
+26688,26686,26698,26697,26665,26805,26767,26740,26743,26771,26731,26818,26990,
+26876,26911,26912,26873,38183,38195,38205,38211,38216,38219,38229,38234,38240,
+38254,38260,38261,38263,38264,38265,38266,38267,38268,38269,38270,38272,38273,
+38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,
+38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,
+38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,
+38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,
+38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,
+38339,38340,38341,38342,38343,38344,38345,38346,38347,26916,26864,26891,26881,
+26967,26851,26896,26993,26937,26976,26946,26973,27012,26987,27008,27032,27000,
+26932,27084,27015,27016,27086,27017,26982,26979,27001,27035,27047,27067,27051,
+27053,27092,27057,27073,27082,27103,27029,27104,27021,27135,27183,27117,27159,
+27160,27237,27122,27204,27198,27296,27216,27227,27189,27278,27257,27197,27176,
+27224,27260,27281,27280,27305,27287,27307,29495,29522,27521,27522,27527,27524,
+27538,27539,27533,27546,27547,27553,27562,36715,36717,36721,36722,36723,36725,
+36726,36728,36727,36729,36730,36732,36734,36737,36738,36740,36743,36747,38348,
+38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,
+38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,
+38375,38380,38399,38407,38419,38424,38427,38430,38432,38435,38436,38437,38438,
+38439,38440,38441,38443,38444,38445,38447,38448,38455,38456,38457,38458,38462,
+38465,38467,38474,38478,38479,38481,38482,38483,38486,38487,38488,38489,38490,
+38492,38493,38494,38496,38499,38501,38502,38507,38509,38510,38511,38512,38513,
+38515,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,
+38532,38535,38537,38538,36749,36750,36751,36760,36762,36558,25099,25111,25115,
+25119,25122,25121,25125,25124,25132,33255,29935,29940,29951,29967,29969,29971,
+25908,26094,26095,26096,26122,26137,26482,26115,26133,26112,28805,26359,26141,
+26164,26161,26166,26165,32774,26207,26196,26177,26191,26198,26209,26199,26231,
+26244,26252,26279,26269,26302,26331,26332,26342,26345,36146,36147,36150,36155,
+36157,36160,36165,36166,36168,36169,36167,36173,36181,36185,35271,35274,35275,
+35276,35278,35279,35280,35281,29294,29343,29277,29286,29295,29310,29311,29316,
+29323,29325,29327,29330,25352,25394,25520,38540,38542,38545,38546,38547,38549,
+38550,38554,38555,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,
+38568,38569,38570,38571,38572,38573,38574,38575,38577,38578,38580,38581,38583,
+38584,38586,38587,38591,38594,38595,38600,38602,38603,38608,38609,38611,38612,
+38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38625,38626,38627,
+38628,38629,38630,38631,38635,38636,38637,38638,38640,38641,38642,38644,38645,
+38648,38650,38651,38652,38653,38655,38658,38659,38661,38666,38667,38668,38672,
+38673,38674,38676,38677,38679,38680,38681,38682,38683,38685,38687,38688,25663,
+25816,32772,27626,27635,27645,27637,27641,27653,27655,27654,27661,27669,27672,
+27673,27674,27681,27689,27684,27690,27698,25909,25941,25963,29261,29266,29270,
+29232,34402,21014,32927,32924,32915,32956,26378,32957,32945,32939,32941,32948,
+32951,32999,33000,33001,33002,32987,32962,32964,32985,32973,32983,26384,32989,
+33003,33009,33012,33005,33037,33038,33010,33020,26389,33042,35930,33078,33054,
+33068,33048,33074,33096,33100,33107,33140,33113,33114,33137,33120,33129,33148,
+33149,33133,33127,22605,23221,33160,33154,33169,28373,33187,33194,33228,26406,
+33226,33211,38689,38690,38691,38692,38693,38694,38695,38696,38697,38699,38700,
+38702,38703,38705,38707,38708,38709,38710,38711,38714,38715,38716,38717,38719,
+38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,
+38733,38734,38735,38736,38737,38740,38741,38743,38744,38746,38748,38749,38751,
+38755,38756,38758,38759,38760,38762,38763,38764,38765,38766,38767,38768,38769,
+38770,38773,38775,38776,38777,38778,38779,38781,38782,38783,38784,38785,38786,
+38787,38788,38790,38791,38792,38793,38794,38796,38798,38799,38800,38803,38805,
+38806,38807,38809,38810,38811,38812,38813,33217,33190,27428,27447,27449,27459,
+27462,27481,39121,39122,39123,39125,39129,39130,27571,24384,27586,35315,26000,
+40785,26003,26044,26054,26052,26051,26060,26062,26066,26070,28800,28828,28822,
+28829,28859,28864,28855,28843,28849,28904,28874,28944,28947,28950,28975,28977,
+29043,29020,29032,28997,29042,29002,29048,29050,29080,29107,29109,29096,29088,
+29152,29140,29159,29177,29213,29224,28780,28952,29030,29113,25150,25149,25155,
+25160,25161,31035,31040,31046,31049,31067,31068,31059,31066,31074,31063,31072,
+31087,31079,31098,31109,31114,31130,31143,31155,24529,24528,38814,38815,38817,
+38818,38820,38821,38822,38823,38824,38825,38826,38828,38830,38832,38833,38835,
+38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,
+38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,
+38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,
+38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38888,38894,38895,
+38896,38897,38898,38900,38903,38904,38905,38906,38907,38908,38909,38910,38911,
+38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,
+38925,38926,24636,24669,24666,24679,24641,24665,24675,24747,24838,24845,24925,
+25001,24989,25035,25041,25094,32896,32895,27795,27894,28156,30710,30712,30720,
+30729,30743,30744,30737,26027,30765,30748,30749,30777,30778,30779,30751,30780,
+30757,30764,30755,30761,30798,30829,30806,30807,30758,30800,30791,30796,30826,
+30875,30867,30874,30855,30876,30881,30883,30898,30905,30885,30932,30937,30921,
+30956,30962,30981,30964,30995,31012,31006,31028,40859,40697,40699,40700,30449,
+30468,30477,30457,30471,30472,30490,30498,30489,30509,30502,30517,30520,30544,
+30545,30535,30531,30554,30568,38927,38928,38929,38930,38931,38932,38933,38934,
+38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,
+38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,
+38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,
+38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,
+38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,
+39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,
+39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,30562,30565,30591,
+30605,30589,30592,30604,30609,30623,30624,30640,30645,30653,30010,30016,30030,
+30027,30024,30043,30066,30073,30083,32600,32609,32607,35400,32616,32628,32625,
+32633,32641,32638,30413,30437,34866,38021,38022,38023,38027,38026,38028,38029,
+38031,38032,38036,38039,38037,38042,38043,38044,38051,38052,38059,38058,38061,
+38060,38063,38064,38066,38068,38070,38071,38072,38073,38074,38076,38077,38079,
+38084,38088,38089,38090,38091,38092,38093,38094,38096,38097,38098,38101,38102,
+38103,38105,38104,38107,38110,38111,38112,38114,38116,38117,38119,38120,38122,
+39023,39024,39025,39026,39027,39028,39051,39054,39058,39061,39065,39075,39080,
+39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,
+39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,
+39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39119,39120,
+39124,39126,39127,39131,39132,39133,39136,39137,39138,39139,39140,39141,39142,
+39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,
+39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,
+39171,39172,39173,39174,39175,38121,38123,38126,38127,38131,38132,38133,38135,
+38137,38140,38141,38143,38147,38146,38150,38151,38153,38154,38157,38158,38159,
+38162,38163,38164,38165,38166,38168,38171,38173,38174,38175,38178,38186,38187,
+38185,38188,38193,38194,38196,38198,38199,38200,38204,38206,38207,38210,38197,
+38212,38213,38214,38217,38220,38222,38223,38226,38227,38228,38230,38231,38232,
+38233,38235,38238,38239,38237,38241,38242,38244,38245,38246,38247,38248,38249,
+38250,38251,38252,38255,38257,38258,38259,38202,30695,30700,38601,31189,31213,
+31203,31211,31238,23879,31235,31234,31262,31252,39176,39177,39178,39179,39180,
+39182,39183,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,
+39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,
+39209,39210,39211,39212,39213,39215,39216,39217,39218,39219,39220,39221,39222,
+39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,
+39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,
+39249,39250,39251,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,
+39264,39265,39266,39268,39270,39283,39288,39289,39291,39294,39298,39299,39305,
+31289,31287,31313,40655,39333,31344,30344,30350,30355,30361,30372,29918,29920,
+29996,40480,40482,40488,40489,40490,40491,40492,40498,40497,40502,40504,40503,
+40505,40506,40510,40513,40514,40516,40518,40519,40520,40521,40523,40524,40526,
+40529,40533,40535,40538,40539,40540,40542,40547,40550,40551,40552,40553,40554,
+40555,40556,40561,40557,40563,30098,30100,30102,30112,30109,30124,30115,30131,
+30132,30136,30148,30129,30128,30147,30146,30166,30157,30179,30184,30182,30180,
+30187,30183,30211,30193,30204,30207,30224,30208,30213,30220,30231,30218,30245,
+30232,30229,30233,39308,39310,39322,39323,39324,39325,39326,39327,39328,39329,
+39330,39331,39332,39334,39335,39337,39338,39339,39340,39341,39342,39343,39344,
+39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,
+39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,
+39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,
+39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,
+39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,
+39410,39411,39412,39413,39414,39415,39416,39417,30235,30268,30242,30240,30272,
+30253,30256,30271,30261,30275,30270,30259,30285,30302,30292,30300,30294,30315,
+30319,32714,31462,31352,31353,31360,31366,31368,31381,31398,31392,31404,31400,
+31405,31411,34916,34921,34930,34941,34943,34946,34978,35014,34999,35004,35017,
+35042,35022,35043,35045,35057,35098,35068,35048,35070,35056,35105,35097,35091,
+35099,35082,35124,35115,35126,35137,35174,35195,30091,32997,30386,30388,30684,
+32786,32788,32790,32796,32800,32802,32805,32806,32807,32809,32808,32817,32779,
+32821,32835,32838,32845,32850,32873,32881,35203,39032,39040,39043,39418,39419,
+39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,
+39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,
+39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,
+39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,
+39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,
+39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,
+39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,
+39511,39512,39513,39049,39052,39053,39055,39060,39066,39067,39070,39071,39073,
+39074,39077,39078,34381,34388,34412,34414,34431,34426,34428,34427,34472,34445,
+34443,34476,34461,34471,34467,34474,34451,34473,34486,34500,34485,34510,34480,
+34490,34481,34479,34505,34511,34484,34537,34545,34546,34541,34547,34512,34579,
+34526,34548,34527,34520,34513,34563,34567,34552,34568,34570,34573,34569,34595,
+34619,34590,34597,34606,34586,34622,34632,34612,34609,34601,34615,34623,34690,
+34594,34685,34686,34683,34656,34672,34636,34670,34699,34643,34659,34684,34660,
+34649,34661,34707,34735,34728,34770,39514,39515,39516,39517,39518,39519,39520,
+39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39538,39555,
+39561,39565,39566,39572,39573,39577,39590,39593,39594,39595,39596,39597,39598,
+39599,39602,39603,39604,39605,39609,39611,39613,39614,39615,39619,39620,39622,
+39623,39624,39625,39626,39629,39630,39631,39632,39634,39636,39637,39638,39639,
+39641,39642,39643,39644,39645,39646,39648,39650,39651,39652,39653,39655,39656,
+39657,39658,39660,39662,39664,39665,39666,39667,39668,39669,39670,39671,39672,
+39674,39676,39677,39678,39679,39680,39681,39682,39684,39685,39686,34758,34696,
+34693,34733,34711,34691,34731,34789,34732,34741,34739,34763,34771,34749,34769,
+34752,34762,34779,34794,34784,34798,34838,34835,34814,34826,34843,34849,34873,
+34876,32566,32578,32580,32581,33296,31482,31485,31496,31491,31492,31509,31498,
+31531,31503,31559,31544,31530,31513,31534,31537,31520,31525,31524,31539,31550,
+31518,31576,31578,31557,31605,31564,31581,31584,31598,31611,31586,31602,31601,
+31632,31654,31655,31672,31660,31645,31656,31621,31658,31644,31650,31659,31668,
+31697,31681,31692,31709,31706,31717,31718,31722,31756,31742,31740,31759,31766,
+31755,39687,39689,39690,39691,39692,39693,39694,39696,39697,39698,39700,39701,
+39702,39703,39704,39705,39706,39707,39708,39709,39710,39712,39713,39714,39716,
+39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39728,39729,39731,
+39732,39733,39734,39735,39736,39737,39738,39741,39742,39743,39744,39750,39754,
+39755,39756,39758,39760,39762,39763,39765,39766,39767,39768,39769,39770,39771,
+39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,
+39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,
+39798,39799,39800,39801,39802,39803,31775,31786,31782,31800,31809,31808,33278,
+33281,33282,33284,33260,34884,33313,33314,33315,33325,33327,33320,33323,33336,
+33339,33331,33332,33342,33348,33353,33355,33359,33370,33375,33384,34942,34949,
+34952,35032,35039,35166,32669,32671,32679,32687,32688,32690,31868,25929,31889,
+31901,31900,31902,31906,31922,31932,31933,31937,31943,31948,31949,31944,31941,
+31959,31976,33390,26280,32703,32718,32725,32741,32737,32742,32745,32750,32755,
+31992,32119,32166,32174,32327,32411,40632,40628,36211,36228,36244,36241,36273,
+36199,36205,35911,35913,37194,37200,37198,37199,37220,39804,39805,39806,39807,
+39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,
+39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,
+39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,
+39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,
+39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,
+39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,
+39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,
+39899,37218,37217,37232,37225,37231,37245,37246,37234,37236,37241,37260,37253,
+37264,37261,37265,37282,37283,37290,37293,37294,37295,37301,37300,37306,35925,
+40574,36280,36331,36357,36441,36457,36277,36287,36284,36282,36292,36310,36311,
+36314,36318,36302,36303,36315,36294,36332,36343,36344,36323,36345,36347,36324,
+36361,36349,36372,36381,36383,36396,36398,36387,36399,36410,36416,36409,36405,
+36413,36401,36425,36417,36418,36433,36434,36426,36464,36470,36476,36463,36468,
+36485,36495,36500,36496,36508,36510,35960,35970,35978,35973,35992,35988,26011,
+35286,35294,35290,35292,39900,39901,39902,39903,39904,39905,39906,39907,39908,
+39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,
+39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,
+39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,
+39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,
+39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,
+39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,
+39987,39988,39989,39990,39991,39992,39993,39994,39995,35301,35307,35311,35390,
+35622,38739,38633,38643,38639,38662,38657,38664,38671,38670,38698,38701,38704,
+38718,40832,40835,40837,40838,40839,40840,40841,40842,40844,40702,40715,40717,
+38585,38588,38589,38606,38610,30655,38624,37518,37550,37576,37694,37738,37834,
+37775,37950,37995,40063,40066,40069,40070,40071,40072,31267,40075,40078,40080,
+40081,40082,40084,40085,40090,40091,40094,40095,40096,40097,40098,40099,40101,
+40102,40103,40104,40105,40107,40109,40110,40112,40113,40114,40115,40116,40117,
+40118,40119,40122,40123,40124,40125,40132,40133,40134,40135,40138,40139,39996,
+39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,
+40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,
+40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,
+40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,
+40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40061,40062,
+40064,40067,40068,40073,40074,40076,40079,40083,40086,40087,40088,40089,40093,
+40106,40108,40111,40121,40126,40127,40128,40129,40130,40136,40137,40145,40146,
+40154,40155,40160,40161,40140,40141,40142,40143,40144,40147,40148,40149,40151,
+40152,40153,40156,40157,40159,40162,38780,38789,38801,38802,38804,38831,38827,
+38819,38834,38836,39601,39600,39607,40536,39606,39610,39612,39617,39616,39621,
+39618,39627,39628,39633,39749,39747,39751,39753,39752,39757,39761,39144,39181,
+39214,39253,39252,39647,39649,39654,39663,39659,39675,39661,39673,39688,39695,
+39699,39711,39715,40637,40638,32315,40578,40583,40584,40587,40594,37846,40605,
+40607,40667,40668,40669,40672,40671,40674,40681,40679,40677,40682,40687,40738,
+40748,40751,40761,40759,40765,40766,40772,40163,40164,40165,40166,40167,40168,
+40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,
+40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,
+40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,
+40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,
+40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,
+40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,
+40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,57908,
+57909,57910,57911,57912,57913,57914,57915,57916,57917,57918,57919,57920,57921,
+57922,57923,57924,57925,57926,57927,57928,57929,57930,57931,57932,57933,57934,
+57935,57936,57937,57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,
+57948,57949,57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,
+57961,57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,
+57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,57986,
+57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,57998,57999,
+58000,58001,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,
+40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,
+40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,
+40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,
+40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,
+40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,
+40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,
+40348,40349,40350,40351,40352,40353,40354,58002,58003,58004,58005,58006,58007,
+58008,58009,58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,
+58021,58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,
+58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,58046,
+58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,58058,58059,
+58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,58070,58071,58072,
+58073,58074,58075,58076,58077,58078,58079,58080,58081,58082,58083,58084,58085,
+58086,58087,58088,58089,58090,58091,58092,58093,58094,58095,40355,40356,40357,
+40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,
+40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,
+40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,
+40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,
+40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,
+40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,
+40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,
+40449,40450,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,58106,
+58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,58118,58119,
+58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,58130,58131,58132,
+58133,58134,58135,58136,58137,58138,58139,58140,58141,58142,58143,58144,58145,
+58146,58147,58148,58149,58150,58151,58152,58153,58154,58155,58156,58157,58158,
+58159,58160,58161,58162,58163,58164,58165,58166,58167,58168,58169,58170,58171,
+58172,58173,58174,58175,58176,58177,58178,58179,58180,58181,58182,58183,58184,
+58185,58186,58187,58188,58189,40451,40452,40453,40454,40455,40456,40457,40458,
+40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,
+40472,40473,40474,40475,40476,40477,40478,40484,40487,40494,40496,40500,40507,
+40508,40512,40525,40528,40530,40531,40532,40534,40537,40541,40543,40544,40545,
+40546,40549,40558,40559,40562,40564,40565,40566,40567,40568,40569,40570,40571,
+40572,40573,40576,40577,40579,40580,40581,40582,40585,40586,40588,40589,40590,
+40591,40592,40593,40596,40597,40598,40599,40600,40601,40602,40603,40604,40606,
+40608,40609,40610,40611,40612,40613,40615,40616,40617,40618,58190,58191,58192,
+58193,58194,58195,58196,58197,58198,58199,58200,58201,58202,58203,58204,58205,
+58206,58207,58208,58209,58210,58211,58212,58213,58214,58215,58216,58217,58218,
+58219,58220,58221,58222,58223,58224,58225,58226,58227,58228,58229,58230,58231,
+58232,58233,58234,58235,58236,58237,58238,58239,58240,58241,58242,58243,58244,
+58245,58246,58247,58248,58249,58250,58251,58252,58253,58254,58255,58256,58257,
+58258,58259,58260,58261,58262,58263,58264,58265,58266,58267,58268,58269,58270,
+58271,58272,58273,58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,
+40619,40620,40621,40622,40623,40624,40625,40626,40627,40629,40630,40631,40633,
+40634,40636,40639,40640,40641,40642,40643,40645,40646,40647,40648,40650,40651,
+40652,40656,40658,40659,40661,40662,40663,40665,40666,40670,40673,40675,40676,
+40678,40680,40683,40684,40685,40686,40688,40689,40690,40691,40692,40693,40694,
+40695,40696,40698,40701,40703,40704,40705,40706,40707,40708,40709,40710,40711,
+40712,40713,40714,40716,40719,40721,40722,40724,40725,40726,40728,40730,40731,
+40732,40733,40734,40735,40737,40739,40740,40741,40742,40743,40744,40745,40746,
+40747,40749,40750,40752,40753,58284,58285,58286,58287,58288,58289,58290,58291,
+58292,58293,58294,58295,58296,58297,58298,58299,58300,58301,58302,58303,58304,
+58305,58306,58307,58308,58309,58310,58311,58312,58313,58314,58315,58316,58317,
+58318,58319,58320,58321,58322,58323,58324,58325,58326,58327,58328,58329,58330,
+58331,58332,58333,58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,
+58344,58345,58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,
+58357,58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,
+58370,58371,58372,58373,58374,58375,58376,58377,40754,40755,40756,40757,40758,
+40760,40762,40764,40767,40768,40769,40770,40771,40773,40774,40775,40776,40777,
+40778,40779,40780,40781,40782,40783,40786,40787,40788,40789,40790,40791,40792,
+40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,
+40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,
+40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40833,
+40834,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,
+40860,40861,40862,40865,40866,40867,40868,40869,63788,63865,63893,63975,63985,
+58378,58379,58380,58381,58382,58383,58384,58385,58386,58387,58388,58389,58390,
+58391,58392,58393,58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,
+58404,58405,58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,
+58417,58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,
+58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,58442,
+58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,58454,58455,
+58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,58466,58467,58468,
+58469,58470,58471,64012,64013,64014,64015,64017,64019,64020,64024,64031,64032,
+64033,64035,64036,64039,64040,64041,11905,59414,59415,59416,11908,13427,13383,
+11912,11915,59422,13726,13850,13838,11916,11927,14702,14616,59430,14799,14815,
+14963,14800,59435,59436,15182,15470,15584,11943,59441,59442,11946,16470,16735,
+11950,17207,11955,11958,11959,59451,17329,17324,11963,17373,17622,18017,17996,
+59459,18211,18217,18300,18317,11978,18759,18810,18813,18818,18819,18821,18822,
+18847,18843,18871,18870,59476,59477,19619,19615,19616,19617,19575,19618,19731,
+19732,19733,19734,19735,19736,19737,19886,59492,58472,58473,58474,58475,58476,
+58477,58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,
+58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,58502,
+58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,58514,58515,
+58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,58526,58527,58528,
+58529,58530,58531,58532,58533,58534,58535,58536,58537,58538,58539,58540,58541,
+58542,58543,58544,58545,58546,58547,58548,58549,58550,58551,58552,58553,58554,
+58555,58556,58557,58558,58559,58560,58561,58562,58563,58564,58565,
diff --git a/system/lib/libc/musl/src/locale/hkscs.h b/system/lib/libc/musl/src/locale/hkscs.h
new file mode 100644
index 00000000..d3565174
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/hkscs.h
@@ -0,0 +1,390 @@
+17392,19506,17923,17830,17784,29287,19831,17843,31921,19682,31941,15253,18230,
+18244,19527,19520,17087,13847,29522,28299,28882,19543,41809,18255,17882,19589,
+31852,19719,19108,18081,27427,29221,23124,6755,15878,16225,26189,22267,0,
+32149,22813,35769,15860,38708,31727,23515,7518,23204,13861,40624,23249,23479,
+23804,26478,34195,39237,29793,29853,14453,7507,13982,24609,16108,22750,15093,
+31484,40855,16737,35085,12778,2698,12894,17162,33924,40854,37935,18736,34323,
+22678,38730,37400,31184,31282,26208,27177,34973,29772,31685,26498,31276,21071,
+36934,13542,29636,23993,29894,40903,22451,18735,21580,16689,13966,22552,31346,
+31589,35727,18094,28296,16769,23961,31662,9404,40904,9409,9417,9420,40905,
+34052,13755,16564,40906,17633,44543,25281,28782,40907,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12736,12737,12738,12739,12740,268,12741,
+209,205,12742,12743,203,8168,12744,202,12745,12746,12747,12748,270,12749,
+12750,256,193,461,192,274,201,282,200,332,211,465,210,56320,7870,56324,7872,
+202,257,225,462,224,593,275,233,283,232,299,237,464,236,333,243,466,242,363,
+250,468,249,470,472,474,476,252,56328,7871,56332,7873,234,609,9178,9179,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41897,4421,0,25866,0,0,20029,28381,
+40270,37343,0,0,30517,25745,20250,20264,20392,20822,20852,20892,20964,21153,
+21160,21307,21326,21457,21464,22242,22768,22788,22791,22834,22836,23398,23454,
+23455,23706,24198,24635,25993,26622,26628,26725,27982,28860,30005,32420,32428,
+32442,32455,32463,32479,32518,32567,33402,33487,33647,35270,35774,35810,36710,
+36711,36718,29713,31996,32205,26950,31433,21031,0,0,0,0,37260,30904,37214,
+32956,0,36107,33014,2535,0,0,32927,40647,19661,40393,40460,19518,40438,28686,
+40458,41267,13761,0,28314,33342,29977,0,18705,39532,39567,40857,31111,33900,
+7626,1488,10982,20004,20097,20096,20103,20159,20203,20279,13388,20413,15944,
+20483,20616,13437,13459,13477,20870,22789,20955,20988,20997,20105,21113,21136,
+21287,13767,21417,13649,21424,13651,21442,21539,13677,13682,13953,21651,21667,
+21684,21689,21712,21743,21784,21795,21800,13720,21823,13733,13759,21975,13765,
+32132,21797,0,3138,3349,20779,21904,11462,14828,833,36422,19896,38117,16467,
+32958,30586,11320,14900,18389,33117,27122,19946,25821,3452,4020,3285,4340,
+25741,36478,3734,3083,3940,11433,33366,17619,0,3398,39501,33001,18420,
+20135,11458,39602,14951,38388,16365,13574,21191,38868,30920,11588,40302,38933,
+0,17369,24741,25780,21731,11596,11210,4215,14843,4207,26330,26390,31136,25834,
+20562,3139,36456,8609,35660,1841,0,18443,425,16378,22643,11661,0,17864,1276,
+24727,3916,3478,21881,16571,17338,0,19124,10854,4253,33194,39157,3484,25465,
+14846,10101,36288,22177,25724,15939,0,42497,3593,10959,11465,0,4296,14786,
+14738,14854,33435,13688,24137,8391,22098,3889,11442,38688,13500,27709,20027,0,
+0,30068,11915,8712,42587,36045,3706,3124,26652,32659,4303,10243,10553,13819,
+20963,3724,3981,3754,16275,3888,3399,4431,3660,0,3755,2985,3400,4288,4413,
+16377,9878,25650,4013,13300,30265,11214,3454,3455,11345,11349,14872,3736,4295,
+3886,42546,27472,36050,36249,36042,38314,21708,33476,21945,0,40643,39974,
+39606,30558,11758,28992,33133,33004,23580,25970,33076,14231,21343,32957,37302,
+3834,3599,3703,3835,13789,19947,13833,3286,22191,10165,4297,3600,3704,4216,
+4424,33287,5205,3705,20048,11684,23124,4125,4126,4341,4342,22428,3601,30356,
+33485,4021,3707,20862,14083,4022,4480,21208,41661,18906,6202,16759,33404,
+22681,21096,13850,22333,31666,23400,18432,19244,40743,18919,39967,39821,23412,
+12605,22011,13810,22153,20008,22786,7105,63608,38737,134,20059,20155,13630,
+23587,24401,24516,14586,25164,25909,27514,27701,27706,28780,29227,20012,29357,
+18665,32594,31035,31993,32595,25194,13505,0,25419,32770,32896,26130,26961,
+21341,34916,35265,30898,35744,36125,38021,38264,38271,38376,
+36367,38886,39029,39118,39134,39267,38928,40060,40479,40644,27503,63751,20023,
+135,38429,25143,38050,0,20539,28158,40051,40870,15817,34959,16718,28791,23797,
+19232,20941,13657,23856,24866,35378,36775,37366,29073,26393,29626,12929,41223,
+15499,6528,19216,30948,29698,20910,34575,16393,27235,41658,16931,34319,2671,
+31274,39239,35562,38741,28749,21284,8318,37876,30425,35299,40871,30685,20131,
+20464,20668,20015,20247,40872,21556,32139,22674,22736,7606,24210,24217,24514,
+10002,25995,13305,26905,27203,15459,27903,0,29184,17669,29580,16091,18963,
+23317,29881,35715,23716,22165,31379,31724,31939,32364,33528,34199,40873,34960,
+40874,36537,40875,36815,34143,39392,37409,40876,36281,5183,16497,17058,23066,
+0,0,0,39016,26475,17014,22333,0,34262,18811,33471,28941,19585,28020,23931,
+27413,28606,40877,40878,23446,40879,26343,32347,28247,31178,15752,17603,12886,
+10134,17306,17718,0,23765,15130,35577,23672,15634,13649,23928,40882,29015,
+17752,16620,7715,19575,14712,13386,420,27713,35532,20404,569,22975,33132,
+38998,39162,24379,2975,0,8641,35181,16642,18107,36985,16135,40883,41397,16632,
+14294,18167,27718,16764,34482,29695,17773,14548,21658,17761,17691,19849,19579,
+19830,17898,16328,19215,13921,17630,17597,16877,23870,23880,23894,15868,14351,
+23972,23993,14368,14392,24130,24253,24357,24451,14600,14612,14655,14669,24791,
+24893,23781,14729,25015,25017,25039,14776,25132,25232,25317,25368,14840,22193,
+14851,25570,25595,25607,25690,14923,25792,23829,22049,40863,14999,25990,15037,
+26111,26195,15090,26258,15138,
+26390,15170,26532,26624,15192,26698,26756,15218,15217,15227,26889,26947,29276,
+26980,27039,27013,15292,27094,15325,27237,27252,27249,27266,15340,27289,15346,
+27307,27317,27348,27382,27521,27585,27626,27765,27818,15563,27906,27910,27942,
+28033,15599,28068,28081,28181,28184,28201,28294,35264,28347,28386,28378,40831,
+28392,28393,28452,28468,15686,16193,28545,28606,15722,15733,29111,23705,15754,
+28716,15761,28752,28756,28783,28799,28809,805,17345,13809,3800,16087,22462,
+28371,28990,22496,13902,27042,35817,23412,31305,22753,38105,31333,31357,22956,
+31419,31408,31426,31427,29137,25741,16842,31450,31453,31466,16879,21682,23553,
+31499,31573,31529,21262,23806,31650,31599,33692,23476,27775,31696,33825,31634,
+0,23840,15789,23653,33938,31738,0,31797,23745,31812,31875,18562,31910,26237,
+17784,31945,31943,31974,31860,31987,31989,0,32359,17693,28228,32093,28374,
+29837,32137,32171,28981,32179,0,16471,24617,32228,15635,32245,6137,32229,
+33645,0,24865,24922,32366,32402,17195,37996,32295,32576,32577,32583,31030,
+25296,39393,32663,25425,32675,5729,104,17756,14182,17667,33594,32762,25737,0,
+32776,32797,0,32815,41095,27843,32827,32828,32865,10004,18825,26150,15843,
+26344,26405,32935,35400,33031,33050,22704,9974,27775,25752,20408,25831,5258,
+33304,6238,27219,19045,19093,17530,33321,2829,27218,15742,20473,5373,34018,
+33634,27402,18855,13616,6003,15864,33450,26907,63892,16859,34123,33488,33562,
+3606,6068,14017,12669,13658,33403,33506,33560,16011,28067,27397,27543,13774,
+15807,33565,21996,33669,17675,28069,33708,
+0,33747,13438,28372,27223,34138,13462,28226,12015,33880,23524,33905,15827,
+17636,27303,33866,15541,31064,0,27542,28279,28227,34014,0,33681,17568,33939,
+34020,23697,16960,23744,17731,34100,23282,28313,17703,34163,17686,26559,34326,
+34341,34363,34241,28808,34306,5506,28877,63922,17770,34344,13896,6306,21495,
+29594,34430,34673,41208,34798,11303,34737,34778,34831,22113,34412,26710,17935,
+34885,34886,30176,15801,30180,34910,34972,18011,34996,34997,25537,35013,30583,
+30479,35207,35210,0,0,35239,35260,35365,35303,31012,31421,35484,30611,37374,
+35472,31321,31465,31546,16271,18195,31544,29052,35596,35615,21552,21861,35647,
+35660,35661,35497,19066,35728,35739,35503,5855,17941,34895,35995,32084,32143,
+63956,14117,32083,36054,32152,32189,36114,36099,6416,36059,28764,36113,19657,
+16080,0,36265,32770,4116,18826,15228,33212,28940,31463,36525,36534,36547,
+37588,36633,36653,33637,33810,36773,37635,41631,2640,36787,18730,35294,34109,
+15803,24312,12898,36857,40980,34492,34049,8997,14720,28375,36919,34108,31422,
+36961,34156,34315,37032,34579,37060,34534,37038,0,37223,15088,37289,37316,
+31916,35123,7817,37390,27807,37441,37474,21945,0,35526,15515,35596,21979,3377,
+37676,37739,35553,35819,28815,23235,35554,35557,18789,37444,35820,35897,35839,
+37747,37979,36540,38277,38310,37926,38304,28662,17081,9850,34520,4732,15918,
+18911,27676,38523,38550,16748,38563,28373,25050,38582,30965,35552,38589,21452,
+18849,27832,628,25616,37039,37093,19153,6421,13066,38705,34370,38710,18959,
+17725,17797,19177,28789,23361,38683,
+0,37333,38743,23370,37355,38751,37925,20688,12471,12476,38793,38815,38833,
+38846,38848,38866,38880,21612,38894,29724,37939,0,38901,37917,31098,19153,
+38964,38963,38987,39014,15118,29045,15697,1584,16732,22278,39114,39095,39112,
+39111,19199,27943,5843,21936,39137,39142,39148,37752,39225,18985,19314,38999,
+39173,39413,39436,39483,39440,39512,22309,14020,37041,39893,39648,39650,39685,
+39668,19470,39700,39725,34304,20532,39732,27048,14531,12413,39760,39744,40254,
+23109,6243,39822,16971,39938,39935,39948,40552,40404,40887,41362,41387,41185,
+41251,41439,40318,40323,41268,40462,26760,40388,8539,41363,41504,6459,41523,
+40249,41145,41652,40592,40597,40606,40610,19764,40618,40623,17252,40641,15200,
+14821,15645,20274,14270,35883,40706,40712,19350,37924,28066,40727,0,40761,
+22175,22154,40773,39352,37003,38898,33919,40802,40809,31452,40846,29206,19390,
+18805,18875,29047,18936,17224,19025,29598,35802,6394,31135,35198,36406,37737,
+37875,35396,37612,37761,37835,35180,17593,29207,16107,30578,31299,28880,17523,
+17400,29054,6127,28835,6334,13721,16071,6277,21551,6136,14114,5883,6201,14049,
+6004,6353,24395,14115,5824,22363,18981,5118,4776,5062,5302,34051,13990,0,
+33877,18836,29029,15921,21852,16123,28754,17652,14062,39325,28454,26617,14131,
+15381,15847,22636,6434,26640,16471,14143,16609,16523,16655,27681,21707,22174,
+26289,22162,4063,2984,3597,37830,35603,37788,20216,20779,14361,17462,20156,
+1125,895,20299,20362,22097,23144,427,971,14745,778,1044,13365,20265,704,36531,
+629,35546,524,20120,20685,
+20749,20386,20227,18958,16010,20290,20526,20588,20609,20428,20453,20568,20732,
+0,0,0,0,28278,13717,15929,16063,28018,6276,16009,20904,20931,1504,17629,1187,
+1170,1169,36218,35484,1806,21081,21156,2163,21217,0,18042,29068,17292,3104,
+18860,4324,27089,3613,0,16094,29849,29716,29782,29592,19342,19132,16525,21456,
+13700,29199,16585,21940,837,21709,3014,22301,37469,38644,37734,22493,22413,
+22399,13886,22731,23193,35398,5882,5999,5904,23084,22968,37519,23166,23247,
+23058,22854,6643,6241,17045,14069,27909,29763,23073,24195,23169,35799,1043,
+37856,29836,4867,28933,18802,37896,35323,37821,14240,23582,23710,24158,24136,
+6550,6524,15086,24269,23375,6403,6404,14081,6304,14045,5886,14035,33066,35399,
+7610,13426,35240,24332,24334,6439,6059,23147,5947,23364,34324,30205,34912,
+24702,10336,9771,24539,16056,9647,9662,37000,28531,25024,62,70,9755,24985,
+24984,24693,11419,11527,18132,37197,25713,18021,11114,14889,11042,13392,39146,
+11896,25399,42075,25782,25393,25553,18915,11623,25252,11425,25659,25963,26994,
+15348,12430,12973,18825,12971,21773,13024,6361,37951,26318,12937,12723,15072,
+16784,21892,35618,21903,5884,21851,21541,30958,12547,6186,12852,13412,12815,
+12674,17097,26254,27940,26219,19347,26160,30832,7659,26211,13010,13025,26142,
+22642,14545,14394,14268,15257,14242,13310,29904,15254,26511,17962,26806,26654,
+15300,27326,14435,14293,17543,27187,27218,27337,27397,6418,25873,26776,27212,
+15319,27258,27479,16320,15514,37792,37618,35818,35531,37513,32798,35292,37991,
+28069,28427,
+18924,0,16255,15759,28164,16444,23101,28170,22599,27940,30786,28987,17178,
+17014,28913,29264,29319,29332,18319,18213,20857,19108,1515,29818,16120,13919,
+19018,18711,24545,16134,16049,19167,35875,16181,24743,16115,29900,29756,37767,
+29751,17567,28138,17745,30083,16227,19673,19718,16216,30037,30323,42438,15129,
+29800,35532,18859,18830,15099,15821,19022,16127,18885,18675,37370,22322,37698,
+35555,6244,20703,21025,20967,30584,12850,30478,30479,30587,18071,14209,14942,
+18672,29752,29851,16063,19130,19143,16584,19094,25006,37639,21889,30750,30861,
+30856,30930,29648,31065,30529,22243,16654,0,33942,31141,27181,16122,31290,
+31220,16750,5862,16690,37429,31217,3404,18828,665,15802,5998,13719,21867,
+13680,13994,468,3085,31458,23129,9973,23215,23196,23053,603,30960,23082,23494,
+31486,16889,31837,31853,16913,23475,24252,24230,31949,18937,6064,31886,31868,
+31918,27314,32220,32263,32211,32590,25185,24924,31560,32151,24194,17002,27509,
+2326,26582,78,13775,22468,25618,25592,18786,32733,31527,2092,23273,23875,
+31500,24078,39398,34373,39523,27164,13375,14818,18935,26029,39455,26016,33920,
+28967,27857,17642,33079,17410,32966,33033,33090,26548,39107,27202,33378,33381,
+27217,33875,28071,34320,29211,23174,16767,6208,23339,6305,23268,6360,34464,
+63932,15759,34861,29730,23042,34926,20293,34951,35007,35046,35173,35149,22147,
+35156,30597,30596,35829,35801,35740,35321,16045,33955,18165,18127,14322,35389,
+35356,37960,24397,37419,17028,26068,28969,28868,6213,40301,35999,36073,32220,
+22938,30659,23024,17262,14036,36394,36519,19465,
+36656,36682,17140,27736,28603,8993,18587,28537,28299,6106,39913,14005,18735,
+37051,0,21873,18694,37307,37892,35403,16482,35580,37927,35869,35899,34021,
+35371,38297,38311,38295,38294,36148,29765,16066,18687,19010,17386,16103,12837,
+38543,36583,36454,36453,16076,18925,19064,16366,29714,29803,16124,38721,37040,
+26695,18973,37011,22495,0,37736,35209,35878,35631,25534,37562,23313,35689,
+18748,29689,16923,38811,38769,39224,3878,24001,35781,19122,38943,38106,37622,
+38359,37349,17600,35664,19047,35684,39132,35397,16128,37418,18725,33812,39227,
+39245,31494,15869,39323,19311,39338,39516,35685,22728,27279,39457,23294,39471,
+39153,19344,39240,39356,19389,19351,37757,22642,4866,22562,18872,5352,30788,
+10015,15800,26821,15741,37976,14631,24912,10113,10603,24839,40015,40019,40059,
+39989,39952,39807,39887,40493,39839,41461,41214,40225,19630,16644,40472,19632,
+40204,41396,41197,41203,39215,40357,33981,28178,28639,27522,34300,17715,28068,
+28292,28144,33824,34286,28160,14295,24676,31202,13724,13888,18733,18910,15714,
+37851,37566,37704,703,30905,37495,37965,20452,13376,36964,21853,30781,30804,
+30902,30795,5975,12745,18753,13978,20338,28634,28633,0,28702,21524,16821,
+22459,22771,22410,40214,22487,28980,13487,16812,29163,27712,20375,0,6069,
+35401,24844,23246,23051,17084,17544,14124,19323,35324,37819,37816,6358,3869,
+33906,27840,5139,17146,11302,17345,22932,15799,26433,32168,24923,24740,18873,
+18827,35322,37605,29666,16105,29876,35683,6303,16097,19123,27352,29683,29691,
+16086,19006,19092,6105,19046,935,5156,18917,29768,
+18710,28837,18806,37508,29670,37727,1278,37681,35534,35350,37766,35815,21973,
+18741,35458,29035,18755,3327,22180,1562,3051,3256,21762,31172,6138,32254,5826,
+19024,6226,17710,37889,14090,35520,18861,22960,6335,6275,29828,23201,14050,
+15707,14000,37471,23161,35457,6242,37748,15565,2740,19094,14730,20724,15721,
+15692,5020,29045,17147,33304,28175,37092,17643,27991,32335,28775,27823,15574,
+16365,15917,28162,28428,15727,1013,30033,14012,13512,18048,16090,18545,22980,
+37486,18750,36673,35868,27584,22546,22472,14038,5202,28926,17250,19057,12259,
+4784,9149,26809,26983,5016,13541,31732,14047,35459,14294,13306,19615,27162,
+13997,27831,33854,17631,17614,27942,27985,27778,28638,28439,28937,33597,5946,
+33773,27776,28755,6107,22921,23170,6067,23137,23153,6405,16892,14125,23023,
+5948,14023,29070,37776,26266,17061,23150,23083,17043,27179,16121,30518,17499,
+17098,28957,16985,35297,20400,27944,23746,17614,32333,17341,27148,16982,4868,
+28838,28979,17385,15781,27871,63525,19023,32357,23019,23855,15859,24412,19037,
+6111,32164,33830,21637,15098,13056,532,22398,2261,1561,16357,8094,41654,28675,
+37211,23920,29583,31955,35417,37920,20424,32743,29389,29456,31476,29496,29497,
+22262,29505,29512,16041,31512,36972,29173,18674,29665,33270,16074,30476,16081,
+27810,22269,29721,29726,29727,16098,16112,16116,16122,29907,16142,16211,30018,
+30061,30066,30093,16252,30152,30172,16320,30285,16343,30324,16348,30330,20316,
+29064,22051,35200,22633,16413,30531,16441,26465,16453,13787,30616,16490,16495,
+23646,30654,30667,22770,30744,28857,30748,
+16552,30777,30791,30801,30822,33864,21813,31027,26627,31026,16643,16649,31121,
+31129,36795,31238,36796,16743,31377,16818,31420,33401,16836,31439,31451,16847,
+20001,31586,31596,31611,31762,31771,16992,17018,31867,31900,17036,31928,17044,
+31981,36755,28864,3279,32207,32212,32208,32253,32686,32692,29343,17303,32800,
+32805,31545,32814,32817,32852,15820,22452,28832,32951,33001,17389,33036,29482,
+33038,33042,30048,33044,17409,15161,33110,33113,33114,17427,22586,33148,33156,
+17445,33171,17453,33189,22511,33217,33252,33364,17551,33446,33398,33482,33496,
+33535,17584,33623,38505,27018,33797,28917,33892,24803,33928,17668,33982,34017,
+34040,34064,34104,34130,17723,34159,34160,34272,17783,34418,34450,34482,34543,
+38469,34699,17926,17943,34990,35071,35108,35143,35217,31079,35369,35384,35476,
+35508,35921,36052,36082,36124,18328,22623,36291,18413,20206,36410,21976,22356,
+36465,22005,36528,18487,36558,36578,36580,36589,36594,36791,36801,36810,36812,
+36915,39364,18605,39136,37395,18718,37416,37464,37483,37553,37550,37567,37603,
+37611,37619,37620,37629,37699,37764,37805,18757,18769,40639,37911,21249,37917,
+37933,37950,18794,37972,38009,38189,38306,18855,38388,38451,18917,26528,18980,
+38720,18997,38834,38850,22100,19172,24808,39097,19225,39153,22596,39182,39193,
+20916,39196,39223,39234,39261,39266,19312,39365,19357,39484,39695,31363,39785,
+39809,39901,39921,39924,19565,39968,14191,7106,40265,39994,40702,22096,40339,
+40381,40384,40444,38134,36790,40571,40620,40625,40637,40646,38108,40674,40689,
+40696,31432,40772,148,695,928,26906,38083,22956,
+1239,22592,38081,14265,1493,1557,1654,5818,22359,29043,2754,2765,3007,21610,
+63547,3019,21662,3067,3131,3155,3173,3196,24807,3213,22138,3253,3293,3309,
+3439,3506,3528,26965,39983,34725,3588,3598,3799,3984,3885,3699,23584,4028,
+24075,4188,4175,4214,26398,4219,4232,4246,13895,4287,4307,4399,4411,21348,
+33965,4835,4981,4918,35713,5495,5657,6083,6087,20088,28859,6189,6506,6701,
+6725,7210,7280,7340,7880,25283,7893,7957,29080,26709,8261,27113,14024,8828,
+9175,9210,10026,10353,10575,33533,10599,10643,10965,35237,10984,36768,11022,
+38840,11071,38983,39613,11340,0,11400,11447,23528,11528,11538,11703,11669,
+11842,12148,12236,12339,12390,13087,13278,24497,26184,26303,31353,13671,13811,
+0,18874,0,13850,14102,0,838,22709,26382,26904,15015,30295,24546,15889,16057,
+30206,8346,18640,19128,16665,35482,17134,17165,16443,17204,17302,19013,1482,
+20946,1553,22943,7848,15294,15615,17412,17622,22408,18036,14747,18223,34280,
+39369,14178,8643,35678,35662,0,18450,18683,18965,29193,19136,3192,22885,20133,
+20358,1913,36570,20524,21135,22335,29041,21145,21529,16202,19111,21948,21574,
+21614,27474,0,13427,21823,30258,21854,18200,21858,21862,22471,18751,22621,
+20582,13563,13260,0,22787,18300,35144,23214,23433,23558,7568,22433,29009,0,
+24834,31762,36950,25010,20378,35682,25602,25674,23899,27639,0,25732,6428,
+35562,18934,25736,16367,25874,19392,26047,26293,10011,37989,22497,24981,23079,
+63693,0,22201,17697,26364,20074,18740,38486,28047,27837,13848,35191,
+26521,26734,25617,26718,0,26823,31554,37056,2577,26918,0,26937,31301,0,27130,
+39462,27181,13919,25705,33,31107,27188,27483,23852,13593,0,27549,18128,27812,
+30011,34917,28078,22710,14108,9613,28747,29133,15444,29312,29317,37505,8570,
+29323,37680,29414,18896,27705,38047,29776,3832,34855,35061,10534,33907,6065,
+28344,18986,6176,14756,14009,0,0,17727,26294,40109,39076,35139,30668,30808,
+22230,16607,5642,14753,14127,33000,5061,29101,33638,31197,37288,0,19639,28847,
+35243,31229,31242,31499,32102,16762,31555,31102,32777,28597,41695,27139,33560,
+21410,28167,37823,26678,38749,33135,32803,27061,5101,12847,32840,23941,35888,
+32899,22293,38947,35145,23979,18824,26046,27093,21458,19109,16257,15377,26422,
+32912,33012,33070,8097,33103,33161,33199,33306,33542,33583,33674,13770,33896,
+34474,18682,25574,35158,30728,37461,35256,17394,35303,17375,35304,35654,35796,
+23032,35849,0,36805,37100,0,37136,37180,15863,37214,19146,36816,29327,22155,
+38119,38377,38320,38328,38706,39121,39241,39274,39363,39464,39694,40282,40347,
+32415,40696,40739,19620,38215,41619,29090,41727,19857,36882,42443,19868,3228,
+36798,21953,36794,9392,36793,19091,17673,32383,28502,27313,20202,13540,35628,
+30877,14138,36480,6133,32804,35692,35737,31294,26287,15851,30293,15543,22069,
+22870,20122,24193,25176,22207,3693,36366,23405,16008,19614,25566,0,6134,6267,
+25904,22061,23626,21530,21265,15814,40344,19581,22050,22046,32585,24280,22901,
+15680,34672,19996,4074,3401,14010,33047,40286,36120,30267,40005,30286,30649,
+37701,21554,
+33096,33527,22053,33074,33816,32957,21994,31074,22083,21526,3741,13774,22021,
+22001,26353,33506,13869,30004,22000,21946,21655,21874,3137,3222,24272,20808,
+3702,11362,3746,40619,32090,21982,4213,25245,38765,21652,36045,29174,37238,
+25596,25529,25598,21865,11075,40050,11955,20890,13535,3495,20903,21581,21790,
+21779,30310,36397,26762,30129,32950,34820,34694,35015,33206,33820,4289,17644,
+29444,18182,23440,33547,26771,22139,9972,32047,16803,32115,28368,29366,37232,
+4569,37384,15612,42665,3756,3833,29286,7330,18254,20418,32761,4075,16634,
+40029,25887,11680,18675,18400,40316,4076,3594,0,30115,4077,0,24648,4487,29091,
+32398,40272,19994,19972,13687,23309,27826,21351,13996,14812,21373,13989,17944,
+22682,19310,33325,21579,22442,23189,2425,0,14930,9317,29556,40620,19721,39917,
+15614,40752,19547,20393,38302,40926,33884,15798,29362,26547,14112,25390,32037,
+16119,15916,14890,36872,21196,15988,13946,17897,1166,30272,23280,3766,30842,
+32558,22695,16575,22140,39819,23924,30292,42036,40581,19681,0,14331,24857,
+12506,17394,0,22109,4777,22439,18787,40454,21044,28846,13741,0,40316,31830,
+39737,22494,5996,23635,25811,38096,25397,29028,34477,3368,27938,19170,3441,0,
+20990,7951,23950,38659,7633,40577,36940,31519,39682,23761,31651,25192,25397,
+39679,31695,39722,31870,0,31810,31878,39957,31740,39689,0,39963,18750,40794,
+21875,23491,20477,40600,20466,21088,15878,21201,22375,20566,22967,24082,38856,
+40363,36700,21609,38836,39232,38842,21292,24880,26924,21466,39946,40194,19515,
+38465,27008,20646,
+30022,5997,39386,21107,0,37209,38529,37212,0,37201,36503,25471,27939,27338,
+22033,37262,30074,25221,1020,29519,31856,23585,15613,0,18713,30422,39837,
+20010,3284,33726,34882,0,23626,27072,0,22394,21023,24053,20174,27697,498,
+20281,21660,21722,21146,36226,13822,0,13811,0,27474,37244,40869,39831,38958,
+39092,39610,40616,40580,29050,31508,0,27642,34840,32632,0,22048,42570,36471,
+40787,0,36308,36431,40476,36353,25218,33661,36392,36469,31443,19063,31294,
+30936,27882,35431,30215,35418,40742,27854,34774,30147,41650,30803,63552,36108,
+29410,29553,35629,29442,29937,36075,19131,34351,24506,34976,17591,0,6203,
+28165,0,35454,9499,0,24829,30311,39639,40260,37742,39823,34805,0,0,36087,
+29484,38689,39856,13782,29362,19463,31825,39242,24921,24921,19460,40598,24957,
+0,22367,24943,25254,25145,0,14940,25058,21418,13301,25444,26626,13778,23895,
+35778,36826,36409,0,20697,7494,30982,21298,38456,3899,16485,0,30718,0,31938,
+24346,31962,31277,32870,32867,32077,29957,29938,35220,33306,26380,32866,29830,
+32859,29936,33027,30500,35209,26572,30035,28369,34729,34766,33224,34700,35401,
+36013,35651,30507,29944,34010,13877,27058,36262,0,35241,0,28089,34753,16401,
+29927,15835,29046,24740,24988,15569,0,24695,0,32625,35629,0,24809,19326,21024,
+15384,15559,24279,30294,21809,6468,4862,39171,28124,28845,23745,25005,35343,
+13943,238,26694,20238,17762,23327,25420,40784,40614,25195,1351,37595,1503,
+16325,34124,17077,29679,20917,13897,18754,35300,37700,6619,
+33518,15560,30780,26436,25311,18739,35242,672,27571,4869,20395,9453,20488,
+27945,31364,13824,19121,9491,0,894,24484,896,839,28379,1055,0,20737,13434,
+20750,39020,14147,33814,18852,1159,20832,13236,20842,3071,8444,741,9520,1422,
+12851,6531,23426,34685,1459,15513,20914,20920,40244,20937,20943,20945,15580,
+20947,19110,20915,20962,21314,20973,33741,26942,14125,24443,21003,21030,21052,
+21173,21079,21140,21177,21189,31765,34114,21216,34317,27411,0,35550,21833,
+28377,16256,2388,16364,21299,0,3042,27851,5926,26651,29653,24650,16042,14540,
+5864,29149,17570,21357,21364,34475,21374,0,5526,5651,30694,21395,35483,21408,
+21419,21422,29607,22386,16217,29596,21441,21445,27721,20041,22526,21465,15019,
+2959,21472,16363,11683,21494,3191,21523,28793,21803,26199,27995,21613,27475,
+3444,21853,21647,21668,18342,5901,3805,15796,3405,35260,9880,21831,19693,
+21551,29719,21894,21929,0,6359,16442,17746,17461,26291,4276,22071,26317,12938,
+26276,26285,22093,22095,30961,22257,38791,21502,22272,22255,22253,35686,13859,
+4687,22342,16805,27758,28811,22338,14001,27774,22502,5142,22531,5204,17251,
+22566,19445,22620,22698,13665,22752,22748,4668,22779,23551,22339,41296,17016,
+37843,13729,22815,26790,14019,28249,5694,23076,21843,5778,34053,22985,3406,
+27777,27946,6108,23001,6139,6066,28070,28017,6184,5845,23033,28229,23211,
+23139,14054,18857,0,14088,23190,29797,23251,28577,9556,15749,6417,14130,5816,
+24195,21200,23414,25992,23420,31246,16388,18525,516,23509,24928,6708,22988,
+1445,23539,
+23453,19728,23557,6980,23571,29646,23572,7333,27432,23625,18653,23685,23785,
+23791,23947,7673,7735,23824,23832,23878,7844,23738,24023,33532,14381,18689,
+8265,8563,33415,14390,15298,24110,27274,0,24186,17596,3283,21414,20151,0,
+21416,6001,24073,24308,33922,24313,24315,14496,24316,26686,37915,24333,449,
+63636,15070,18606,4922,24378,26760,9168,0,9329,24419,38845,28270,24434,37696,
+35382,24487,23990,15711,21072,8042,28920,9832,37334,670,35369,24625,26245,
+6263,14691,15815,13881,22416,10164,31089,15936,24734,0,24755,18818,18831,
+31315,29860,20705,23200,24932,33828,24898,63654,28370,24961,20980,1622,24967,
+23466,16311,10335,25043,35741,39261,25040,14642,10624,10433,24611,24924,25886,
+25483,280,25285,6000,25301,11789,25452,18911,14871,25656,25592,5006,6140,0,
+28554,11830,38932,16524,22301,25825,25829,38011,14950,25658,14935,25933,28438,
+18984,18979,25989,25965,25951,12414,26037,18752,19255,26065,16600,6185,26080,
+26083,24543,13312,26136,12791,12792,26180,12708,12709,26187,3701,26215,20966,
+26227,0,7741,12849,34292,12744,21267,30661,10487,39332,26370,17308,18977,
+15147,27130,14274,0,26471,26466,16845,37101,26583,17641,26658,28240,37436,
+26625,13286,28064,26717,13423,27105,27147,35551,26995,26819,13773,26881,26880,
+15666,14849,13884,15232,26540,26977,35402,17148,26934,27032,15265,969,33635,
+20624,27129,13913,8490,27205,14083,27293,15347,26545,27336,37276,15373,27421,
+2339,24798,27445,27508,10189,28341,15067,949,6488,14144,21537,15194,27617,
+16124,27612,27703,9355,18673,27473,
+27738,33318,27769,15804,17605,15805,16804,18700,18688,15561,14053,15595,3378,
+39811,12793,9361,32655,26679,27941,28065,28139,28054,27996,28284,28420,18815,
+16517,28274,34099,28532,20935,0,0,33838,35617,0,15919,29779,16258,31180,28239,
+23185,12363,28664,14093,28573,15920,28410,5271,16445,17749,37872,28484,28508,
+15694,28532,37232,15675,28575,16708,28627,16529,16725,16441,16368,16308,16703,
+20959,16726,16727,16704,25053,28747,28798,28839,28801,28876,28885,28886,28895,
+16644,15848,29108,29078,17015,28971,28997,23176,29002,0,23708,17253,29007,
+37730,17089,28972,17498,18983,18978,29114,35816,28861,29198,37954,29205,22801,
+37955,29220,37697,22021,29230,29248,18804,26813,29269,29271,15957,12356,26637,
+28477,29314,0,29483,18467,34859,18669,34820,29480,29486,29647,29610,3130,
+27182,29641,29769,16866,5863,18980,26147,14021,18871,18829,18939,29687,29717,
+26883,18982,29753,1475,16087,0,10413,29792,36530,29767,29668,29814,33721,
+29804,14128,29812,37873,27180,29826,18771,19084,16735,19065,35727,23366,35843,
+6302,29896,6536,29966,0,29982,36569,6731,23511,36524,37765,30029,30026,30055,
+30062,20354,16132,19731,30094,29789,30110,30132,30210,30252,30289,30287,30319,
+30326,25589,30352,33263,14328,26897,26894,30369,30373,30391,30412,28575,33890,
+20637,20861,7708,30494,30502,30528,25775,21024,30552,12972,30639,35172,35176,
+5825,30708,0,4982,18962,26826,30895,30919,30931,38565,31022,21984,30935,31028,
+30897,30220,36792,34948,35627,24707,9756,31110,35072,26882,31104,22615,31133,
+31545,31036,31145,28202,28966,
+16040,31174,37133,31188,1312,17503,21007,47234,248,16384,43296,1102,0,0,2868,
+1,0,0,0,0,0,0,0,3072,64,0,0,0,1024,88,60,0,0,23680,56493,48115,17353,60910,
+4004,49446,30363,61426,64478,63482,12815,44868,61438,65277,24593,176,8448,
+33049,4128,43144,8544,9321,17408,50313,0,16387,53,33859,20785,26771,514,0,0,0,
+0,0,16384,256,44160,33380,35904,37025,20484,54368,53760,6186,26781,38709,
+55375,8440,33476,10268,30082,660,16440,41376,4293,19825,3524,47512,23390,
+17153,39327,30723,57888,2079,393,16585,775,39437,21136,20433,892,8450,49184,
+4974,46467,62939,30693,20368,39447,5942,12,47726,12041,21600,7680,26744,28706,
+40534,62245,46990,2839,59119,6007,7003,4289,36248,6162,53174,12545,6770,11355,
+49334,57888,23747,7042,56032,34254,16598,21673,53259,18447,16452,2320,16596,
+15278,7780,11076,2071,33414,6198,35232,40167,2139,900,55810,60560,34779,49029,
+44450,36509,39069,9504,70,40774,58239,51669,62596,19926,58118,6326,2322,0,
+1024,0,32,0,512,0,0,0,0,8192,0,0,0,0,0,0,8,36352,28280,16223,56702,63293,
+39932,44796,65490,27535,59377,47807,28334,61207,42972,46654,30645,37577,42455,
+19126,39790,33209,26445,21758,39921,65122,21103,14039,49150,17705,63873,26045,
+17062,57,16896,36704,37888,16448,45010,53719,219,39072,31666,20998,38944,
+51222,2365,0,1,0,2561,2226,128,0,34820,5152,19472,0,4,17569,16,321,
+2048,61504,20447,22582,62961,32949,26613,16512,20480,16718,33992,23040,55392,
+11009,20481,5793,16580,28402,44049,14624,49348,1800,2316,38552,39876,7184,
+27800,10886,422,4422,58733,50379,37568,8464,4630,29341,27124,5902,41514,62593,
+123,41992,36875,11280,14796,330,5872,2571,3136,59933,17420,17678,2,
diff --git a/system/lib/libc/musl/src/locale/iconv.c b/system/lib/libc/musl/src/locale/iconv.c
new file mode 100644
index 00000000..a0b02320
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iconv.c
@@ -0,0 +1,454 @@
+#include <iconv.h>
+#include <errno.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+
+#define UTF_32BE 0300
+#define UTF_16LE 0301
+#define UTF_16BE 0302
+#define UTF_32LE 0303
+#define UCS2BE 0304
+#define UCS2LE 0305
+#define WCHAR_T 0306
+#define US_ASCII 0307
+#define UTF_8 0310
+#define EUC_JP 0320
+#define SHIFT_JIS 0321
+#define GB18030 0330
+#define GBK 0331
+#define GB2312 0332
+#define BIG5 0340
+#define EUC_KR 0350
+
+/* FIXME: these are not implemented yet
+ * EUC: A1-FE A1-FE
+ * GBK: 81-FE 40-7E,80-FE
+ * Big5: A1-FE 40-7E,A1-FE
+ */
+
+/* Definitions of charmaps. Each charmap consists of:
+ * 1. Empty-string-terminated list of null-terminated aliases.
+ * 2. Special type code or number of elided entries.
+ * 3. Character table (size determined by field 2). */
+
+static const unsigned char charmaps[] =
+"utf8\0\0\310"
+"wchart\0\0\306"
+"ucs2\0ucs2be\0\0\304"
+"ucs2le\0\0\305"
+"utf16\0utf16be\0\0\302"
+"utf16le\0\0\301"
+"ucs4\0ucs4be\0utf32\0utf32be\0\0\300"
+"ucs4le\0utf32le\0\0\303"
+"ascii\0usascii\0iso646\0iso646us\0\0\307"
+"eucjp\0\0\320"
+"shiftjis\0sjis\0\0\321"
+"gb18030\0\0\330"
+"gbk\0\0\331"
+"gb2312\0\0\332"
+"big5\0bigfive\0cp950\0big5hkscs\0\0\340"
+"euckr\0ksc5601\0ksx1001\0cp949\0\0\350"
+#include "codepages.h"
+;
+
+static const unsigned short legacy_chars[] = {
+#include "legacychars.h"
+};
+
+static const unsigned short jis0208[84][94] = {
+#include "jis0208.h"
+};
+
+static const unsigned short gb18030[126][190] = {
+#include "gb18030.h"
+};
+
+static const unsigned short big5[89][157] = {
+#include "big5.h"
+};
+
+static const unsigned short hkscs[] = {
+#include "hkscs.h"
+};
+
+static const unsigned short ksc[93][94] = {
+#include "ksc.h"
+};
+
+static int fuzzycmp(const unsigned char *a, const unsigned char *b)
+{
+ for (; *a && *b; a++, b++) {
+ while (*a && (*a|32U)-'a'>26 && *a-'0'>10U) a++;
+ if ((*a|32U) != *b) return 1;
+ }
+ return *a != *b;
+}
+
+static size_t find_charmap(const void *name)
+{
+ const unsigned char *s;
+ for (s=charmaps; *s; ) {
+ if (!fuzzycmp(name, s)) {
+ for (; *s; s+=strlen((void *)s)+1);
+ return s+1-charmaps;
+ }
+ s += strlen((void *)s)+1;
+ if (!*s) {
+ if (s[1] > 0200) s+=2;
+ else s+=2+(128U-s[1])/4*5;
+ }
+ }
+ return -1;
+}
+
+iconv_t iconv_open(const char *to, const char *from)
+{
+ size_t f, t;
+
+ if ((t = find_charmap(to))==-1
+ || (f = find_charmap(from))==-1
+ || (charmaps[t] >= 0320)) {
+ errno = EINVAL;
+ return (iconv_t)-1;
+ }
+
+ return (void *)(f<<16 | t);
+}
+
+int iconv_close(iconv_t cd)
+{
+ return 0;
+}
+
+static unsigned get_16(const unsigned char *s, int e)
+{
+ e &= 1;
+ return s[e]<<8 | s[1-e];
+}
+
+static void put_16(unsigned char *s, unsigned c, int e)
+{
+ e &= 1;
+ s[e] = c>>8;
+ s[1-e] = c;
+}
+
+static unsigned get_32(const unsigned char *s, int e)
+{
+ e &= 3;
+ return s[e]+0U<<24 | s[e^1]<<16 | s[e^2]<<8 | s[e^3];
+}
+
+static void put_32(unsigned char *s, unsigned c, int e)
+{
+ e &= 3;
+ s[e^0] = c>>24;
+ s[e^1] = c>>16;
+ s[e^2] = c>>8;
+ s[e^3] = c;
+}
+
+/* Adapt as needed */
+#define mbrtowc_utf8 mbrtowc
+#define wctomb_utf8 wctomb
+
+size_t iconv(iconv_t cd0, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
+{
+ size_t x=0;
+ unsigned long cd = (unsigned long)cd0;
+ unsigned to = cd & 0xffff;
+ unsigned from = cd >> 16;
+ const unsigned char *map = charmaps+from+1;
+ const unsigned char *tomap = charmaps+to+1;
+ mbstate_t st = {0};
+ wchar_t wc;
+ unsigned c, d;
+ size_t k, l;
+ int err;
+ unsigned char type = map[-1];
+ unsigned char totype = tomap[-1];
+
+ if (!in || !*in || !*inb) return 0;
+
+ for (; *inb; *in+=l, *inb-=l) {
+ c = *(unsigned char *)*in;
+ l = 1;
+
+ if (c >= 128 || type-UTF_32BE < 7U) switch (type) {
+ case UTF_8:
+ l = mbrtowc_utf8(&wc, *in, *inb, &st);
+ if (!l) l++;
+ else if (l == (size_t)-1) goto ilseq;
+ else if (l == (size_t)-2) goto starved;
+ c = wc;
+ break;
+ case US_ASCII:
+ goto ilseq;
+ case WCHAR_T:
+ l = sizeof(wchar_t);
+ if (*inb < l) goto starved;
+ c = *(wchar_t *)*in;
+ if (0) {
+ case UTF_32BE:
+ case UTF_32LE:
+ l = 4;
+ if (*inb < 4) goto starved;
+ c = get_32((void *)*in, type);
+ }
+ if (c-0xd800u < 0x800u || c >= 0x110000u) goto ilseq;
+ break;
+ case UCS2BE:
+ case UCS2LE:
+ case UTF_16BE:
+ case UTF_16LE:
+ l = 2;
+ if (*inb < 2) goto starved;
+ c = get_16((void *)*in, type);
+ if ((unsigned)(c-0xdc00) < 0x400) goto ilseq;
+ if ((unsigned)(c-0xd800) < 0x400) {
+ if (type-UCS2BE < 2U) goto ilseq;
+ l = 4;
+ if (*inb < 4) goto starved;
+ d = get_16((void *)(*in + 2), type);
+ if ((unsigned)(d-0xdc00) >= 0x400) goto ilseq;
+ c = ((c-0xd7c0)<<10) + (d-0xdc00);
+ }
+ break;
+ case SHIFT_JIS:
+ if (c-0xa1 <= 0xdf-0xa1) {
+ c += 0xff61-0xa1;
+ break;
+ }
+ l = 2;
+ if (*inb < 2) goto starved;
+ d = *((unsigned char *)*in + 1);
+ if (c-129 <= 159-129) c -= 129;
+ else if (c-224 <= 239-224) c -= 193;
+ else goto ilseq;
+ c *= 2;
+ if (d-64 <= 158-64) {
+ if (d==127) goto ilseq;
+ if (d>127) d--;
+ d -= 64;
+ } else if (d-159 <= 252-159) {
+ c++;
+ d -= 159;
+ }
+ c = jis0208[c][d];
+ if (!c) goto ilseq;
+ break;
+ case EUC_JP:
+ l = 2;
+ if (*inb < 2) goto starved;
+ d = *((unsigned char *)*in + 1);
+ if (c==0x8e) {
+ c = d;
+ if (c-0xa1 > 0xdf-0xa1) goto ilseq;
+ c += 0xff61 - 0xa1;
+ break;
+ }
+ c -= 0xa1;
+ d -= 0xa1;
+ if (c >= 84 || d >= 94) goto ilseq;
+ c = jis0208[c][d];
+ if (!c) goto ilseq;
+ break;
+ case GB2312:
+ if (c < 0xa1) goto ilseq;
+ case GBK:
+ case GB18030:
+ c -= 0x81;
+ if (c >= 126) goto ilseq;
+ l = 2;
+ if (*inb < 2) goto starved;
+ d = *((unsigned char *)*in + 1);
+ if (d < 0xa1 && type == GB2312) goto ilseq;
+ if (d-0x40>=191 || d==127) {
+ if (d-'0'>9 || type != GB18030)
+ goto ilseq;
+ l = 4;
+ if (*inb < 4) goto starved;
+ c = (10*c + d-'0') * 1260;
+ d = *((unsigned char *)*in + 2);
+ if (d-0x81>126) goto ilseq;
+ c += 10*(d-0x81);
+ d = *((unsigned char *)*in + 3);
+ if (d-'0'>9) goto ilseq;
+ c += d-'0';
+ c += 128;
+ for (d=0; d<=c; ) {
+ k = 0;
+ for (int i=0; i<126; i++)
+ for (int j=0; j<190; j++)
+ if (gb18030[i][j]-d <= c-d)
+ k++;
+ d = c+1;
+ c += k;
+ }
+ break;
+ }
+ d -= 0x40;
+ if (d>63) d--;
+ c = gb18030[c][d];
+ break;
+ case BIG5:
+ l = 2;
+ if (*inb < 2) goto starved;
+ d = *((unsigned char *)*in + 1);
+ if (d-0x40>=0xff-0x40 || d-0x7f<0xa1-0x7f) goto ilseq;
+ d -= 0x40;
+ if (d > 0x3e) d -= 0x22;
+ if (c-0xa1>=0xfa-0xa1) {
+ if (c-0x87>=0xff-0x87) goto ilseq;
+ if (c < 0xa1) c -= 0x87;
+ else c -= 0x87 + (0xfa-0xa1);
+ c = (hkscs[4867+(c*157+d)/16]>>(c*157+d)%16)%2<<17
+ | hkscs[c*157+d];
+ /* A few HKSCS characters map to pairs of UCS
+ * characters. These are mapped to surrogate
+ * range in the hkscs table then hard-coded
+ * here. Ugly, yes. */
+ if (c/256 == 0xdc) {
+ if (totype-0300U > 8) k = 2;
+ else k = "\10\4\4\10\4\4\10\2\4"[totype-0300];
+ if (k > *outb) goto toobig;
+ x += iconv((iconv_t)(uintptr_t)to,
+ &(char *){"\303\212\314\204"
+ "\303\212\314\214"
+ "\303\252\314\204"
+ "\303\252\314\214"
+ +c%256}, &(size_t){4},
+ out, outb);
+ continue;
+ }
+ if (!c) goto ilseq;
+ break;
+ }
+ c -= 0xa1;
+ c = big5[c][d]|(c==0x27&&(d==0x3a||d==0x3c||d==0x42))<<17;
+ if (!c) goto ilseq;
+ break;
+ case EUC_KR:
+ l = 2;
+ if (*inb < 2) goto starved;
+ d = *((unsigned char *)*in + 1);
+ c -= 0xa1;
+ d -= 0xa1;
+ if (c >= 93 || d >= 94) {
+ c += (0xa1-0x81);
+ d += 0xa1;
+ if (c >= 93 || c>=0xc6-0x81 && d>0x52)
+ goto ilseq;
+ if (d-'A'<26) d = d-'A';
+ else if (d-'a'<26) d = d-'a'+26;
+ else if (d-0x81<0xff-0x81) d = d-0x81+52;
+ else goto ilseq;
+ if (c < 0x20) c = 178*c + d;
+ else c = 178*0x20 + 84*(c-0x20) + d;
+ c += 0xac00;
+ for (d=0xac00; d<=c; ) {
+ k = 0;
+ for (int i=0; i<93; i++)
+ for (int j=0; j<94; j++)
+ if (ksc[i][j]-d <= c-d)
+ k++;
+ d = c+1;
+ c += k;
+ }
+ break;
+ }
+ c = ksc[c][d];
+ if (!c) goto ilseq;
+ break;
+ default:
+ if (c < 128+type) break;
+ c -= 128+type;
+ c = legacy_chars[ map[c*5/4]>>2*c%8 |
+ map[c*5/4+1]<<8-2*c%8 & 1023 ];
+ if (!c) c = *(unsigned char *)*in;
+ if (c==1) goto ilseq;
+ }
+
+ switch (totype) {
+ case WCHAR_T:
+ if (*outb < sizeof(wchar_t)) goto toobig;
+ *(wchar_t *)*out = c;
+ *out += sizeof(wchar_t);
+ *outb -= sizeof(wchar_t);
+ break;
+ case UTF_8:
+ if (*outb < 4) {
+ char tmp[4];
+ k = wctomb_utf8(tmp, c);
+ if (*outb < k) goto toobig;
+ memcpy(*out, tmp, k);
+ } else k = wctomb_utf8(*out, c);
+ *out += k;
+ *outb -= k;
+ break;
+ case US_ASCII:
+ if (c > 0x7f) subst: x++, c='*';
+ default:
+ if (*outb < 1) goto toobig;
+ if (c < 128+totype) {
+ revout:
+ *(*out)++ = c;
+ *outb -= 1;
+ break;
+ }
+ d = c;
+ for (c=0; c<128-totype; c++) {
+ if (d == legacy_chars[ tomap[c*5/4]>>2*c%8 |
+ tomap[c*5/4+1]<<8-2*c%8 & 1023 ]) {
+ c += 128;
+ goto revout;
+ }
+ }
+ goto subst;
+ case UCS2BE:
+ case UCS2LE:
+ case UTF_16BE:
+ case UTF_16LE:
+ if (c < 0x10000 || type-UCS2BE < 2U) {
+ if (c >= 0x10000) c = 0xFFFD;
+ if (*outb < 2) goto toobig;
+ put_16((void *)*out, c, totype);
+ *out += 2;
+ *outb -= 2;
+ break;
+ }
+ if (*outb < 4) goto toobig;
+ c -= 0x10000;
+ put_16((void *)*out, (c>>10)|0xd800, totype);
+ put_16((void *)(*out + 2), (c&0x3ff)|0xdc00, totype);
+ *out += 4;
+ *outb -= 4;
+ break;
+ case UTF_32BE:
+ case UTF_32LE:
+ if (*outb < 4) goto toobig;
+ put_32((void *)*out, c, totype);
+ *out += 4;
+ *outb -= 4;
+ break;
+ }
+ }
+ return x;
+ilseq:
+ err = EILSEQ;
+ x = -1;
+ goto end;
+toobig:
+ err = E2BIG;
+ x = -1;
+ goto end;
+starved:
+ err = EINVAL;
+ x = -1;
+end:
+ errno = err;
+ return x;
+}
diff --git a/system/lib/libc/musl/src/locale/iswalnum_l.c b/system/lib/libc/musl/src/locale/iswalnum_l.c
new file mode 100644
index 00000000..c888060c
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswalnum_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswalnum_l(wint_t c, locale_t l)
+{
+ return iswalnum(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswalpha_l.c b/system/lib/libc/musl/src/locale/iswalpha_l.c
new file mode 100644
index 00000000..cd2be91e
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswalpha_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswalpha_l(wint_t c, locale_t l)
+{
+ return iswalpha(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswblank_l.c b/system/lib/libc/musl/src/locale/iswblank_l.c
new file mode 100644
index 00000000..f3a2691f
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswblank_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswblank_l(wint_t c, locale_t l)
+{
+ return iswblank(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswcntrl_l.c b/system/lib/libc/musl/src/locale/iswcntrl_l.c
new file mode 100644
index 00000000..7681fe09
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswcntrl_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswcntrl_l(wint_t c, locale_t l)
+{
+ return iswcntrl(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswctype_l.c b/system/lib/libc/musl/src/locale/iswctype_l.c
new file mode 100644
index 00000000..13dfb1ed
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswctype_l.c
@@ -0,0 +1,9 @@
+#include <wctype.h>
+#include "libc.h"
+
+int iswctype_l(wint_t c, wctype_t t, locale_t l)
+{
+ return iswctype(c, t);
+}
+
+weak_alias(iswctype_l, __iswctype_l);
diff --git a/system/lib/libc/musl/src/locale/iswdigit_l.c b/system/lib/libc/musl/src/locale/iswdigit_l.c
new file mode 100644
index 00000000..3de678c2
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswdigit_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswdigit_l(wint_t c, locale_t l)
+{
+ return iswdigit(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswgraph_l.c b/system/lib/libc/musl/src/locale/iswgraph_l.c
new file mode 100644
index 00000000..34df64fc
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswgraph_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswgraph_l(wint_t c, locale_t l)
+{
+ return iswgraph(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswlower_l.c b/system/lib/libc/musl/src/locale/iswlower_l.c
new file mode 100644
index 00000000..c52421a0
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswlower_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswlower_l(wint_t c, locale_t l)
+{
+ return iswlower(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswprint_l.c b/system/lib/libc/musl/src/locale/iswprint_l.c
new file mode 100644
index 00000000..73d83ab3
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswprint_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswprint_l(wint_t c, locale_t l)
+{
+ return iswprint(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswpunct_l.c b/system/lib/libc/musl/src/locale/iswpunct_l.c
new file mode 100644
index 00000000..831e0e54
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswpunct_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswpunct_l(wint_t c, locale_t l)
+{
+ return iswpunct(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswspace_l.c b/system/lib/libc/musl/src/locale/iswspace_l.c
new file mode 100644
index 00000000..b507e9e3
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswspace_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswspace_l(wint_t c, locale_t l)
+{
+ return iswspace(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswupper_l.c b/system/lib/libc/musl/src/locale/iswupper_l.c
new file mode 100644
index 00000000..fc988ef1
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswupper_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswupper_l(wint_t c, locale_t l)
+{
+ return iswupper(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iswxdigit_l.c b/system/lib/libc/musl/src/locale/iswxdigit_l.c
new file mode 100644
index 00000000..9527cf3e
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iswxdigit_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswxdigit_l(wint_t c, locale_t l)
+{
+ return iswxdigit(c);
+}
diff --git a/system/lib/libc/musl/src/locale/jis0208.h b/system/lib/libc/musl/src/locale/jis0208.h
new file mode 100644
index 00000000..f465b9d8
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/jis0208.h
@@ -0,0 +1,550 @@
+12288,12289,12290,65292,65294,12539,65306,65307,65311,65281,12443,12444,180,
+65344,168,65342,65507,65343,12541,12542,12445,12446,12291,20189,12293,12294,
+12295,12540,8213,8208,65295,92,12316,8214,65372,8230,8229,8216,8217,8220,8221,
+65288,65289,12308,12309,65339,65341,65371,65373,12296,12297,12298,12299,12300,
+12301,12302,12303,12304,12305,65291,8722,177,215,247,65309,8800,65308,65310,
+8806,8807,8734,8756,9794,9792,176,8242,8243,8451,65509,65284,162,163,65285,
+65283,65286,65290,65312,167,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,
+9650,9661,9660,8251,12306,8594,8592,8593,8595,12307,0,0,0,0,0,0,0,0,0,0,0,
+8712,8715,8838,8839,8834,8835,8746,8745,0,0,0,0,0,0,0,0,8743,8744,172,8658,
+8660,8704,8707,0,0,0,0,0,0,0,0,0,0,0,8736,8869,8978,8706,8711,8801,8786,8810,
+8811,8730,8765,8733,8757,8747,8748,0,0,0,0,0,0,0,8491,8240,9839,9837,9834,
+8224,8225,182,0,0,0,0,9711,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65296,65297,65298,
+65299,65300,65301,65302,65303,65304,65305,0,0,0,0,0,0,0,65313,65314,65315,
+65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,
+65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,0,0,0,0,0,0,65345,
+65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,
+65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,0,0,0,
+0,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,
+12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,
+12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,
+12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
+12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,
+12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,
+12430,12431,12432,12433,12434,12435,0,0,0,0,0,0,0,0,0,0,0,12449,12450,12451,
+12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,
+12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,
+12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,
+12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,
+12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,
+12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,
+12530,12531,12532,12533,12534,0,0,0,0,0,0,0,0,913,914,915,916,917,918,919,920,
+921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,0,0,0,0,0,0,0,
+0,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,
+965,966,967,968,969,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,
+1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,
+1066,1067,1068,1069,1070,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1072,1073,1074,
+1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,
+1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,0,
+0,0,0,0,0,0,0,0,0,0,0,0,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,
+9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,
+9527,9535,9501,9520,9509,9528,9538,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20124,
+21782,23043,38463,21696,24859,25384,23030,36898,33909,33564,31312,24746,25569,
+28197,26093,33894,33446,39925,26771,22311,26017,25201,23451,22992,34427,39156,
+32098,32190,39822,25110,31903,34999,23433,24245,25353,26263,26696,38343,38797,
+26447,20197,20234,20301,20381,20553,22258,22839,22996,23041,23561,24799,24847,
+24944,26131,26885,28858,30031,30064,31227,32173,32239,32963,33806,34915,35586,
+36949,36986,21307,20117,20133,22495,32946,37057,30959,19968,22769,28322,36920,
+31282,33576,33419,39983,20801,21360,21693,21729,22240,23035,24341,39154,28139,
+32996,34093,38498,38512,38560,38907,21515,21491,23431,28879,32701,36802,38632,
+21359,40284,31418,19985,30867,33276,28198,22040,21764,27421,34074,39995,23013,
+21417,28006,29916,38287,22082,20113,36939,38642,33615,39180,21473,21942,23344,
+24433,26144,26355,26628,27704,27891,27945,29787,30408,31310,38964,33521,34907,
+35424,37613,28082,30123,30410,39365,24742,35585,36234,38322,27022,21421,20870,
+22290,22576,22852,23476,24310,24616,25513,25588,27839,28436,28814,28948,29017,
+29141,29503,32257,33398,33489,34199,36960,37467,40219,22633,26044,27738,29989,
+20985,22830,22885,24448,24540,25276,26106,27178,27431,27572,29579,32705,35158,
+40236,40206,40644,23713,27798,33659,20740,23627,25014,33222,26742,29281,20057,
+20474,21368,24681,28201,31311,38899,19979,21270,20206,20309,20285,20385,20339,
+21152,21487,22025,22799,23233,23478,23521,31185,26247,26524,26550,27468,27827,
+28779,29634,31117,31166,31292,31623,33457,33499,33540,33655,33775,33747,34662,
+35506,22057,36008,36838,36942,38686,34442,20420,23784,25105,29273,30011,33253,
+33469,34558,36032,38597,39187,39381,20171,20250,35299,22238,22602,22730,24315,
+24555,24618,24724,24674,25040,25106,25296,25913,39745,26214,26800,28023,28784,
+30028,30342,32117,33445,34809,38283,38542,35997,20977,21182,22806,21683,23475,
+23830,24936,27010,28079,30861,33995,34903,35442,37799,39608,28012,39336,34521,
+22435,26623,34510,37390,21123,22151,21508,24275,25313,25785,26684,26680,27579,
+29554,30906,31339,35226,35282,36203,36611,37101,38307,38548,38761,23398,23731,
+27005,38989,38990,25499,31520,27179,27263,26806,39949,28511,21106,21917,24688,
+25324,27963,28167,28369,33883,35088,36676,19988,39993,21494,26907,27194,38788,
+26666,20828,31427,33970,37340,37772,22107,40232,26658,33541,33841,31909,21000,
+33477,29926,20094,20355,20896,23506,21002,21208,21223,24059,21914,22570,23014,
+23436,23448,23515,24178,24185,24739,24863,24931,25022,25563,25954,26577,26707,
+26874,27454,27475,27735,28450,28567,28485,29872,29976,30435,30475,31487,31649,
+31777,32233,32566,32752,32925,33382,33694,35251,35532,36011,36996,37969,38291,
+38289,38306,38501,38867,39208,33304,20024,21547,23736,24012,29609,30284,30524,
+23721,32747,36107,38593,38929,38996,39000,20225,20238,21361,21916,22120,22522,
+22855,23305,23492,23696,24076,24190,24524,25582,26426,26071,26082,26399,26827,
+26820,27231,24112,27589,27671,27773,30079,31048,23395,31232,32000,24509,35215,
+35352,36020,36215,36556,36637,39138,39438,39740,20096,20605,20736,22931,23452,
+25135,25216,25836,27450,29344,30097,31047,32681,34811,35516,35696,25516,33738,
+38816,21513,21507,21931,26708,27224,35440,30759,26485,40653,21364,23458,33050,
+34384,36870,19992,20037,20167,20241,21450,21560,23470,24339,24613,25937,26429,
+27714,27762,27875,28792,29699,31350,31406,31496,32026,31998,32102,26087,29275,
+21435,23621,24040,25298,25312,25369,28192,34394,35377,36317,37624,28417,31142,
+39770,20136,20139,20140,20379,20384,20689,20807,31478,20849,20982,21332,21281,
+21375,21483,21932,22659,23777,24375,24394,24623,24656,24685,25375,25945,27211,
+27841,29378,29421,30703,33016,33029,33288,34126,37111,37857,38911,39255,39514,
+20208,20957,23597,26241,26989,23616,26354,26997,29577,26704,31873,20677,21220,
+22343,24062,37670,26020,27427,27453,29748,31105,31165,31563,32202,33465,33740,
+34943,35167,35641,36817,37329,21535,37504,20061,20534,21477,21306,29399,29590,
+30697,33510,36527,39366,39368,39378,20855,24858,34398,21936,31354,20598,23507,
+36935,38533,20018,27355,37351,23633,23624,25496,31391,27795,38772,36705,31402,
+29066,38536,31874,26647,32368,26705,37740,21234,21531,34219,35347,32676,36557,
+37089,21350,34952,31041,20418,20670,21009,20804,21843,22317,29674,22411,22865,
+24418,24452,24693,24950,24935,25001,25522,25658,25964,26223,26690,28179,30054,
+31293,31995,32076,32153,32331,32619,33550,33610,34509,35336,35427,35686,36605,
+38938,40335,33464,36814,39912,21127,25119,25731,28608,38553,26689,20625,27424,
+27770,28500,31348,32080,34880,35363,26376,20214,20537,20518,20581,20860,21048,
+21091,21927,22287,22533,23244,24314,25010,25080,25331,25458,26908,27177,29309,
+29356,29486,30740,30831,32121,30476,32937,35211,35609,36066,36562,36963,37749,
+38522,38997,39443,40568,20803,21407,21427,24187,24358,28187,28304,29572,29694,
+32067,33335,35328,35578,38480,20046,20491,21476,21628,22266,22993,23396,24049,
+24235,24359,25144,25925,26543,28246,29392,31946,34996,32929,32993,33776,34382,
+35463,36328,37431,38599,39015,40723,20116,20114,20237,21320,21577,21566,23087,
+24460,24481,24735,26791,27278,29786,30849,35486,35492,35703,37264,20062,39881,
+20132,20348,20399,20505,20502,20809,20844,21151,21177,21246,21402,21475,21521,
+21518,21897,22353,22434,22909,23380,23389,23439,24037,24039,24055,24184,24195,
+24218,24247,24344,24658,24908,25239,25304,25511,25915,26114,26179,26356,26477,
+26657,26775,27083,27743,27946,28009,28207,28317,30002,30343,30828,31295,31968,
+32005,32024,32094,32177,32789,32771,32943,32945,33108,33167,33322,33618,34892,
+34913,35611,36002,36092,37066,37237,37489,30783,37628,38308,38477,38917,39321,
+39640,40251,21083,21163,21495,21512,22741,25335,28640,35946,36703,40633,20811,
+21051,21578,22269,31296,37239,40288,40658,29508,28425,33136,29969,24573,24794,
+39592,29403,36796,27492,38915,20170,22256,22372,22718,23130,24680,25031,26127,
+26118,26681,26801,28151,30165,32058,33390,39746,20123,20304,21449,21766,23919,
+24038,24046,26619,27801,29811,30722,35408,37782,35039,22352,24231,25387,20661,
+20652,20877,26368,21705,22622,22971,23472,24425,25165,25505,26685,27507,28168,
+28797,37319,29312,30741,30758,31085,25998,32048,33756,35009,36617,38555,21092,
+22312,26448,32618,36001,20916,22338,38442,22586,27018,32948,21682,23822,22524,
+30869,40442,20316,21066,21643,25662,26152,26388,26613,31364,31574,32034,37679,
+26716,39853,31545,21273,20874,21047,23519,25334,25774,25830,26413,27578,34217,
+38609,30352,39894,25420,37638,39851,30399,26194,19977,20632,21442,23665,24808,
+25746,25955,26719,29158,29642,29987,31639,32386,34453,35715,36059,37240,39184,
+26028,26283,27531,20181,20180,20282,20351,21050,21496,21490,21987,22235,22763,
+22987,22985,23039,23376,23629,24066,24107,24535,24605,25351,25903,23388,26031,
+26045,26088,26525,27490,27515,27663,29509,31049,31169,31992,32025,32043,32930,
+33026,33267,35222,35422,35433,35430,35468,35566,36039,36060,38604,39164,27503,
+20107,20284,20365,20816,23383,23546,24904,25345,26178,27425,28363,27835,29246,
+29885,30164,30913,31034,32780,32819,33258,33940,36766,27728,40575,24335,35672,
+40235,31482,36600,23437,38635,19971,21489,22519,22833,23241,23460,24713,28287,
+28422,30142,36074,23455,34048,31712,20594,26612,33437,23649,34122,32286,33294,
+20889,23556,25448,36198,26012,29038,31038,32023,32773,35613,36554,36974,34503,
+37034,20511,21242,23610,26451,28796,29237,37196,37320,37675,33509,23490,24369,
+24825,20027,21462,23432,25163,26417,27530,29417,29664,31278,33131,36259,37202,
+39318,20754,21463,21610,23551,25480,27193,32172,38656,22234,21454,21608,23447,
+23601,24030,20462,24833,25342,27954,31168,31179,32066,32333,32722,33261,33311,
+33936,34886,35186,35728,36468,36655,36913,37195,37228,38598,37276,20160,20303,
+20805,21313,24467,25102,26580,27713,28171,29539,32294,37325,37507,21460,22809,
+23487,28113,31069,32302,31899,22654,29087,20986,34899,36848,20426,23803,26149,
+30636,31459,33308,39423,20934,24490,26092,26991,27529,28147,28310,28516,30462,
+32020,24033,36981,37255,38918,20966,21021,25152,26257,26329,28186,24246,32210,
+32626,26360,34223,34295,35576,21161,21465,22899,24207,24464,24661,37604,38500,
+20663,20767,21213,21280,21319,21484,21736,21830,21809,22039,22888,22974,23100,
+23477,23558,23567,23569,23578,24196,24202,24288,24432,25215,25220,25307,25484,
+25463,26119,26124,26157,26230,26494,26786,27167,27189,27836,28040,28169,28248,
+28988,28966,29031,30151,30465,30813,30977,31077,31216,31456,31505,31911,32057,
+32918,33750,33931,34121,34909,35059,35359,35388,35412,35443,35937,36062,37284,
+37478,37758,37912,38556,38808,19978,19976,19998,20055,20887,21104,22478,22580,
+22732,23330,24120,24773,25854,26465,26454,27972,29366,30067,31331,33976,35698,
+37304,37664,22065,22516,39166,25325,26893,27542,29165,32340,32887,33394,35302,
+39135,34645,36785,23611,20280,20449,20405,21767,23072,23517,23529,24515,24910,
+25391,26032,26187,26862,27035,28024,28145,30003,30137,30495,31070,31206,32051,
+33251,33455,34218,35242,35386,36523,36763,36914,37341,38663,20154,20161,20995,
+22645,22764,23563,29978,23613,33102,35338,36805,38499,38765,31525,35535,38920,
+37218,22259,21416,36887,21561,22402,24101,25512,27700,28810,30561,31883,32736,
+34928,36930,37204,37648,37656,38543,29790,39620,23815,23913,25968,26530,36264,
+38619,25454,26441,26905,33733,38935,38592,35070,28548,25722,23544,19990,28716,
+30045,26159,20932,21046,21218,22995,24449,24615,25104,25919,25972,26143,26228,
+26866,26646,27491,28165,29298,29983,30427,31934,32854,22768,35069,35199,35488,
+35475,35531,36893,37266,38738,38745,25993,31246,33030,38587,24109,24796,25114,
+26021,26132,26512,30707,31309,31821,32318,33034,36012,36196,36321,36447,30889,
+20999,25305,25509,25666,25240,35373,31363,31680,35500,38634,32118,33292,34633,
+20185,20808,21315,21344,23459,23554,23574,24029,25126,25159,25776,26643,26676,
+27849,27973,27927,26579,28508,29006,29053,26059,31359,31661,32218,32330,32680,
+33146,33307,33337,34214,35438,36046,36341,36984,36983,37549,37521,38275,39854,
+21069,21892,28472,28982,20840,31109,32341,33203,31950,22092,22609,23720,25514,
+26366,26365,26970,29401,30095,30094,30990,31062,31199,31895,32032,32068,34311,
+35380,38459,36961,40736,20711,21109,21452,21474,20489,21930,22766,22863,29245,
+23435,23652,21277,24803,24819,25436,25475,25407,25531,25805,26089,26361,24035,
+27085,27133,28437,29157,20105,30185,30456,31379,31967,32207,32156,32865,33609,
+33624,33900,33980,34299,35013,36208,36865,36973,37783,38684,39442,20687,22679,
+24974,33235,34101,36104,36896,20419,20596,21063,21363,24687,25417,26463,28204,
+36275,36895,20439,23646,36042,26063,32154,21330,34966,20854,25539,23384,23403,
+23562,25613,26449,36956,20182,22810,22826,27760,35409,21822,22549,22949,24816,
+25171,26561,33333,26965,38464,39364,39464,20307,22534,23550,32784,23729,24111,
+24453,24608,24907,25140,26367,27888,28382,32974,33151,33492,34955,36024,36864,
+36910,38538,40667,39899,20195,21488,22823,31532,37261,38988,40441,28381,28711,
+21331,21828,23429,25176,25246,25299,27810,28655,29730,35351,37944,28609,35582,
+33592,20967,34552,21482,21481,20294,36948,36784,22890,33073,24061,31466,36799,
+26842,35895,29432,40008,27197,35504,20025,21336,22022,22374,25285,25506,26086,
+27470,28129,28251,28845,30701,31471,31658,32187,32829,32966,34507,35477,37723,
+22243,22727,24382,26029,26262,27264,27573,30007,35527,20516,30693,22320,24347,
+24677,26234,27744,30196,31258,32622,33268,34584,36933,39347,31689,30044,31481,
+31569,33988,36880,31209,31378,33590,23265,30528,20013,20210,23449,24544,25277,
+26172,26609,27880,34411,34935,35387,37198,37619,39376,27159,28710,29482,33511,
+33879,36015,19969,20806,20939,21899,23541,24086,24115,24193,24340,24373,24427,
+24500,25074,25361,26274,26397,28526,29266,30010,30522,32884,33081,33144,34678,
+35519,35548,36229,36339,37530,38263,38914,40165,21189,25431,30452,26389,27784,
+29645,36035,37806,38515,27941,22684,26894,27084,36861,37786,30171,36890,22618,
+26626,25524,27131,20291,28460,26584,36795,34086,32180,37716,26943,28528,22378,
+22775,23340,32044,29226,21514,37347,40372,20141,20302,20572,20597,21059,35998,
+21576,22564,23450,24093,24213,24237,24311,24351,24716,25269,25402,25552,26799,
+27712,30855,31118,31243,32224,33351,35330,35558,36420,36883,37048,37165,37336,
+40718,27877,25688,25826,25973,28404,30340,31515,36969,37841,28346,21746,24505,
+25764,36685,36845,37444,20856,22635,22825,23637,24215,28155,32399,29980,36028,
+36578,39003,28857,20253,27583,28593,30000,38651,20814,21520,22581,22615,22956,
+23648,24466,26007,26460,28193,30331,33759,36077,36884,37117,37709,30757,30778,
+21162,24230,22303,22900,24594,20498,20826,20908,20941,20992,21776,22612,22616,
+22871,23445,23798,23947,24764,25237,25645,26481,26691,26812,26847,30423,28120,
+28271,28059,28783,29128,24403,30168,31095,31561,31572,31570,31958,32113,21040,
+33891,34153,34276,35342,35588,35910,36367,36867,36879,37913,38518,38957,39472,
+38360,20685,21205,21516,22530,23566,24999,25758,27934,30643,31461,33012,33796,
+36947,37509,23776,40199,21311,24471,24499,28060,29305,30563,31167,31716,27602,
+29420,35501,26627,27233,20984,31361,26932,23626,40182,33515,23493,37193,28702,
+22136,23663,24775,25958,27788,35930,36929,38931,21585,26311,37389,22856,37027,
+20869,20045,20970,34201,35598,28760,25466,37707,26978,39348,32260,30071,21335,
+26976,36575,38627,27741,20108,23612,24336,36841,21250,36049,32905,34425,24319,
+26085,20083,20837,22914,23615,38894,20219,22922,24525,35469,28641,31152,31074,
+23527,33905,29483,29105,24180,24565,25467,25754,29123,31896,20035,24316,20043,
+22492,22178,24745,28611,32013,33021,33075,33215,36786,35223,34468,24052,25226,
+25773,35207,26487,27874,27966,29750,30772,23110,32629,33453,39340,20467,24259,
+25309,25490,25943,26479,30403,29260,32972,32954,36649,37197,20493,22521,23186,
+26757,26995,29028,29437,36023,22770,36064,38506,36889,34687,31204,30695,33833,
+20271,21093,21338,25293,26575,27850,30333,31636,31893,33334,34180,36843,26333,
+28448,29190,32283,33707,39361,40614,20989,31665,30834,31672,32903,31560,27368,
+24161,32908,30033,30048,20843,37474,28300,30330,37271,39658,20240,32624,25244,
+31567,38309,40169,22138,22617,34532,38588,20276,21028,21322,21453,21467,24070,
+25644,26001,26495,27710,27726,29256,29359,29677,30036,32321,33324,34281,36009,
+31684,37318,29033,38930,39151,25405,26217,30058,30436,30928,34115,34542,21290,
+21329,21542,22915,24199,24444,24754,25161,25209,25259,26000,27604,27852,30130,
+30382,30865,31192,32203,32631,32933,34987,35513,36027,36991,38750,39131,27147,
+31800,20633,23614,24494,26503,27608,29749,30473,32654,40763,26570,31255,21305,
+30091,39661,24422,33181,33777,32920,24380,24517,30050,31558,36924,26727,23019,
+23195,32016,30334,35628,20469,24426,27161,27703,28418,29922,31080,34920,35413,
+35961,24287,25551,30149,31186,33495,37672,37618,33948,34541,39981,21697,24428,
+25996,27996,28693,36007,36051,38971,25935,29942,19981,20184,22496,22827,23142,
+23500,20904,24067,24220,24598,25206,25975,26023,26222,28014,29238,31526,33104,
+33178,33433,35676,36000,36070,36212,38428,38468,20398,25771,27494,33310,33889,
+34154,37096,23553,26963,39080,33914,34135,20239,21103,24489,24133,26381,31119,
+33145,35079,35206,28149,24343,25173,27832,20175,29289,39826,20998,21563,22132,
+22707,24996,25198,28954,22894,31881,31966,32027,38640,25991,32862,19993,20341,
+20853,22592,24163,24179,24330,26564,20006,34109,38281,38491,31859,38913,20731,
+22721,30294,30887,21029,30629,34065,31622,20559,22793,29255,31687,32232,36794,
+36820,36941,20415,21193,23081,24321,38829,20445,33303,37610,22275,25429,27497,
+29995,35036,36628,31298,21215,22675,24917,25098,26286,27597,31807,33769,20515,
+20472,21253,21574,22577,22857,23453,23792,23791,23849,24214,25265,25447,25918,
+26041,26379,27861,27873,28921,30770,32299,32990,33459,33804,34028,34562,35090,
+35370,35914,37030,37586,39165,40179,40300,20047,20129,20621,21078,22346,22952,
+24125,24536,24537,25151,26292,26395,26576,26834,20882,32033,32938,33192,35584,
+35980,36031,37502,38450,21536,38956,21271,20693,21340,22696,25778,26420,29287,
+30566,31302,37350,21187,27809,27526,22528,24140,22868,26412,32763,20961,30406,
+25705,30952,39764,40635,22475,22969,26151,26522,27598,21737,27097,24149,33180,
+26517,39850,26622,40018,26717,20134,20451,21448,25273,26411,27819,36804,20397,
+32365,40639,19975,24930,28288,28459,34067,21619,26410,39749,24051,31637,23724,
+23494,34588,28234,34001,31252,33032,22937,31885,27665,30496,21209,22818,28961,
+29279,30683,38695,40289,26891,23167,23064,20901,21517,21629,26126,30431,36855,
+37528,40180,23018,29277,28357,20813,26825,32191,32236,38754,40634,25720,27169,
+33538,22916,23391,27611,29467,30450,32178,32791,33945,20786,26408,40665,30446,
+26466,21247,39173,23588,25147,31870,36016,21839,24758,32011,38272,21249,20063,
+20918,22812,29242,32822,37326,24357,30690,21380,24441,32004,34220,35379,36493,
+38742,26611,34222,37971,24841,24840,27833,30290,35565,36664,21807,20305,20778,
+21191,21451,23461,24189,24736,24962,25558,26377,26586,28263,28044,29494,29495,
+30001,31056,35029,35480,36938,37009,37109,38596,34701,22805,20104,20313,19982,
+35465,36671,38928,20653,24188,22934,23481,24248,25562,25594,25793,26332,26954,
+27096,27915,28342,29076,29992,31407,32650,32768,33865,33993,35201,35617,36362,
+36965,38525,39178,24958,25233,27442,27779,28020,32716,32764,28096,32645,34746,
+35064,26469,33713,38972,38647,27931,32097,33853,37226,20081,21365,23888,27396,
+28651,34253,34349,35239,21033,21519,23653,26446,26792,29702,29827,30178,35023,
+35041,37324,38626,38520,24459,29575,31435,33870,25504,30053,21129,27969,28316,
+29705,30041,30827,31890,38534,31452,40845,20406,24942,26053,34396,20102,20142,
+20698,20001,20940,23534,26009,26753,28092,29471,30274,30637,31260,31975,33391,
+35538,36988,37327,38517,38936,21147,32209,20523,21400,26519,28107,29136,29747,
+33256,36650,38563,40023,40607,29792,22593,28057,32047,39006,20196,20278,20363,
+20919,21169,23994,24604,29618,31036,33491,37428,38583,38646,38666,40599,40802,
+26278,27508,21015,21155,28872,35010,24265,24651,24976,28451,29001,31806,32244,
+32879,34030,36899,37676,21570,39791,27347,28809,36034,36335,38706,21172,23105,
+24266,24324,26391,27004,27028,28010,28431,29282,29436,31725,32769,32894,34635,
+37070,20845,40595,31108,32907,37682,35542,20525,21644,35441,27498,36036,33031,
+24785,26528,40434,20121,20120,39952,35435,34241,34152,26880,28286,30871,33109,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,24332,19984,19989,20010,20017,20022,20028,20031,20034,20054,20056,
+20098,20101,35947,20106,33298,24333,20110,20126,20127,20128,20130,20144,20147,
+20150,20174,20173,20164,20166,20162,20183,20190,20205,20191,20215,20233,20314,
+20272,20315,20317,20311,20295,20342,20360,20367,20376,20347,20329,20336,20369,
+20335,20358,20374,20760,20436,20447,20430,20440,20443,20433,20442,20432,20452,
+20453,20506,20520,20500,20522,20517,20485,20252,20470,20513,20521,20524,20478,
+20463,20497,20486,20547,20551,26371,20565,20560,20552,20570,20566,20588,20600,
+20608,20634,20613,20660,20658,20681,20682,20659,20674,20694,20702,20709,20717,
+20707,20718,20729,20725,20745,20737,20738,20758,20757,20756,20762,20769,20794,
+20791,20796,20795,20799,20800,20818,20812,20820,20834,31480,20841,20842,20846,
+20864,20866,22232,20876,20873,20879,20881,20883,20885,20886,20900,20902,20898,
+20905,20906,20907,20915,20913,20914,20912,20917,20925,20933,20937,20955,20960,
+34389,20969,20973,20976,20981,20990,20996,21003,21012,21006,21031,21034,21038,
+21043,21049,21071,21060,21067,21068,21086,21076,21098,21108,21097,21107,21119,
+21117,21133,21140,21138,21105,21128,21137,36776,36775,21164,21165,21180,21173,
+21185,21197,21207,21214,21219,21222,39149,21216,21235,21237,21240,21241,21254,
+21256,30008,21261,21264,21263,21269,21274,21283,21295,21297,21299,21304,21312,
+21318,21317,19991,21321,21325,20950,21342,21353,21358,22808,21371,21367,21378,
+21398,21408,21414,21413,21422,21424,21430,21443,31762,38617,21471,26364,29166,
+21486,21480,21485,21498,21505,21565,21568,21548,21549,21564,21550,21558,21545,
+21533,21582,21647,21621,21646,21599,21617,21623,21616,21650,21627,21632,21622,
+21636,21648,21638,21703,21666,21688,21669,21676,21700,21704,21672,21675,21698,
+21668,21694,21692,21720,21733,21734,21775,21780,21757,21742,21741,21754,21730,
+21817,21824,21859,21836,21806,21852,21829,21846,21847,21816,21811,21853,21913,
+21888,21679,21898,21919,21883,21886,21912,21918,21934,21884,21891,21929,21895,
+21928,21978,21957,21983,21956,21980,21988,21972,22036,22007,22038,22014,22013,
+22043,22009,22094,22096,29151,22068,22070,22066,22072,22123,22116,22063,22124,
+22122,22150,22144,22154,22176,22164,22159,22181,22190,22198,22196,22210,22204,
+22209,22211,22208,22216,22222,22225,22227,22231,22254,22265,22272,22271,22276,
+22281,22280,22283,22285,22291,22296,22294,21959,22300,22310,22327,22328,22350,
+22331,22336,22351,22377,22464,22408,22369,22399,22409,22419,22432,22451,22436,
+22442,22448,22467,22470,22484,22482,22483,22538,22486,22499,22539,22553,22557,
+22642,22561,22626,22603,22640,27584,22610,22589,22649,22661,22713,22687,22699,
+22714,22750,22715,22712,22702,22725,22739,22737,22743,22745,22744,22757,22748,
+22756,22751,22767,22778,22777,22779,22780,22781,22786,22794,22800,22811,26790,
+22821,22828,22829,22834,22840,22846,31442,22869,22864,22862,22874,22872,22882,
+22880,22887,22892,22889,22904,22913,22941,20318,20395,22947,22962,22982,23016,
+23004,22925,23001,23002,23077,23071,23057,23068,23049,23066,23104,23148,23113,
+23093,23094,23138,23146,23194,23228,23230,23243,23234,23229,23267,23255,23270,
+23273,23254,23290,23291,23308,23307,23318,23346,23248,23338,23350,23358,23363,
+23365,23360,23377,23381,23386,23387,23397,23401,23408,23411,23413,23416,25992,
+23418,23424,23427,23462,23480,23491,23495,23497,23508,23504,23524,23526,23522,
+23518,23525,23531,23536,23542,23539,23557,23559,23560,23565,23571,23584,23586,
+23592,23608,23609,23617,23622,23630,23635,23632,23631,23409,23660,23662,20066,
+23670,23673,23692,23697,23700,22939,23723,23739,23734,23740,23735,23749,23742,
+23751,23769,23785,23805,23802,23789,23948,23786,23819,23829,23831,23900,23839,
+23835,23825,23828,23842,23834,23833,23832,23884,23890,23886,23883,23916,23923,
+23926,23943,23940,23938,23970,23965,23980,23982,23997,23952,23991,23996,24009,
+24013,24019,24018,24022,24027,24043,24050,24053,24075,24090,24089,24081,24091,
+24118,24119,24132,24131,24128,24142,24151,24148,24159,24162,24164,24135,24181,
+24182,24186,40636,24191,24224,24257,24258,24264,24272,24271,24278,24291,24285,
+24282,24283,24290,24289,24296,24297,24300,24305,24307,24304,24308,24312,24318,
+24323,24329,24413,24412,24331,24337,24342,24361,24365,24376,24385,24392,24396,
+24398,24367,24401,24406,24407,24409,24417,24429,24435,24439,24451,24450,24447,
+24458,24456,24465,24455,24478,24473,24472,24480,24488,24493,24508,24534,24571,
+24548,24568,24561,24541,24755,24575,24609,24672,24601,24592,24617,24590,24625,
+24603,24597,24619,24614,24591,24634,24666,24641,24682,24695,24671,24650,24646,
+24653,24675,24643,24676,24642,24684,24683,24665,24705,24717,24807,24707,24730,
+24708,24731,24726,24727,24722,24743,24715,24801,24760,24800,24787,24756,24560,
+24765,24774,24757,24792,24909,24853,24838,24822,24823,24832,24820,24826,24835,
+24865,24827,24817,24845,24846,24903,24894,24872,24871,24906,24895,24892,24876,
+24884,24893,24898,24900,24947,24951,24920,24921,24922,24939,24948,24943,24933,
+24945,24927,24925,24915,24949,24985,24982,24967,25004,24980,24986,24970,24977,
+25003,25006,25036,25034,25033,25079,25032,25027,25030,25018,25035,32633,25037,
+25062,25059,25078,25082,25076,25087,25085,25084,25086,25088,25096,25097,25101,
+25100,25108,25115,25118,25121,25130,25134,25136,25138,25139,25153,25166,25182,
+25187,25179,25184,25192,25212,25218,25225,25214,25234,25235,25238,25300,25219,
+25236,25303,25297,25275,25295,25343,25286,25812,25288,25308,25292,25290,25282,
+25287,25243,25289,25356,25326,25329,25383,25346,25352,25327,25333,25424,25406,
+25421,25628,25423,25494,25486,25472,25515,25462,25507,25487,25481,25503,25525,
+25451,25449,25534,25577,25536,25542,25571,25545,25554,25590,25540,25622,25652,
+25606,25619,25638,25654,25885,25623,25640,25615,25703,25711,25718,25678,25898,
+25749,25747,25765,25769,25736,25788,25818,25810,25797,25799,25787,25816,25794,
+25841,25831,33289,25824,25825,25260,25827,25839,25900,25846,25844,25842,25850,
+25856,25853,25880,25884,25861,25892,25891,25899,25908,25909,25911,25910,25912,
+30027,25928,25942,25941,25933,25944,25950,25949,25970,25976,25986,25987,35722,
+26011,26015,26027,26039,26051,26054,26049,26052,26060,26066,26075,26073,26080,
+26081,26097,26482,26122,26115,26107,26483,26165,26166,26164,26140,26191,26180,
+26185,26177,26206,26205,26212,26215,26216,26207,26210,26224,26243,26248,26254,
+26249,26244,26264,26269,26305,26297,26313,26302,26300,26308,26296,26326,26330,
+26336,26175,26342,26345,26352,26357,26359,26383,26390,26398,26406,26407,38712,
+26414,26431,26422,26433,26424,26423,26438,26462,26464,26457,26467,26468,26505,
+26480,26537,26492,26474,26508,26507,26534,26529,26501,26551,26607,26548,26604,
+26547,26601,26552,26596,26590,26589,26594,26606,26553,26574,26566,26599,27292,
+26654,26694,26665,26688,26701,26674,26702,26803,26667,26713,26723,26743,26751,
+26783,26767,26797,26772,26781,26779,26755,27310,26809,26740,26805,26784,26810,
+26895,26765,26750,26881,26826,26888,26840,26914,26918,26849,26892,26829,26836,
+26855,26837,26934,26898,26884,26839,26851,26917,26873,26848,26863,26920,26922,
+26906,26915,26913,26822,27001,26999,26972,27000,26987,26964,27006,26990,26937,
+26996,26941,26969,26928,26977,26974,26973,27009,26986,27058,27054,27088,27071,
+27073,27091,27070,27086,23528,27082,27101,27067,27075,27047,27182,27025,27040,
+27036,27029,27060,27102,27112,27138,27163,27135,27402,27129,27122,27111,27141,
+27057,27166,27117,27156,27115,27146,27154,27329,27171,27155,27204,27148,27250,
+27190,27256,27207,27234,27225,27238,27208,27192,27170,27280,27277,27296,27268,
+27298,27299,27287,34327,27323,27331,27330,27320,27315,27308,27358,27345,27359,
+27306,27354,27370,27387,27397,34326,27386,27410,27414,39729,27423,27448,27447,
+30428,27449,39150,27463,27459,27465,27472,27481,27476,27483,27487,27489,27512,
+27513,27519,27520,27524,27523,27533,27544,27541,27550,27556,27562,27563,27567,
+27570,27569,27571,27575,27580,27590,27595,27603,27615,27628,27627,27635,27631,
+40638,27656,27667,27668,27675,27684,27683,27742,27733,27746,27754,27778,27789,
+27802,27777,27803,27774,27752,27763,27794,27792,27844,27889,27859,27837,27863,
+27845,27869,27822,27825,27838,27834,27867,27887,27865,27882,27935,34893,27958,
+27947,27965,27960,27929,27957,27955,27922,27916,28003,28051,28004,27994,28025,
+27993,28046,28053,28644,28037,28153,28181,28170,28085,28103,28134,28088,28102,
+28140,28126,28108,28136,28114,28101,28154,28121,28132,28117,28138,28142,28205,
+28270,28206,28185,28274,28255,28222,28195,28267,28203,28278,28237,28191,28227,
+28218,28238,28196,28415,28189,28216,28290,28330,28312,28361,28343,28371,28349,
+28335,28356,28338,28372,28373,28303,28325,28354,28319,28481,28433,28748,28396,
+28408,28414,28479,28402,28465,28399,28466,28364,28478,28435,28407,28550,28538,
+28536,28545,28544,28527,28507,28659,28525,28546,28540,28504,28558,28561,28610,
+28518,28595,28579,28577,28580,28601,28614,28586,28639,28629,28652,28628,28632,
+28657,28654,28635,28681,28683,28666,28689,28673,28687,28670,28699,28698,28532,
+28701,28696,28703,28720,28734,28722,28753,28771,28825,28818,28847,28913,28844,
+28856,28851,28846,28895,28875,28893,28889,28937,28925,28956,28953,29029,29013,
+29064,29030,29026,29004,29014,29036,29071,29179,29060,29077,29096,29100,29143,
+29113,29118,29138,29129,29140,29134,29152,29164,29159,29173,29180,29177,29183,
+29197,29200,29211,29224,29229,29228,29232,29234,29243,29244,29247,29248,29254,
+29259,29272,29300,29310,29314,29313,29319,29330,29334,29346,29351,29369,29362,
+29379,29382,29380,29390,29394,29410,29408,29409,29433,29431,20495,29463,29450,
+29468,29462,29469,29492,29487,29481,29477,29502,29518,29519,40664,29527,29546,
+29544,29552,29560,29557,29563,29562,29640,29619,29646,29627,29632,29669,29678,
+29662,29858,29701,29807,29733,29688,29746,29754,29781,29759,29791,29785,29761,
+29788,29801,29808,29795,29802,29814,29822,29835,29854,29863,29898,29903,29908,
+29681,29920,29923,29927,29929,29934,29938,29936,29937,29944,29943,29956,29955,
+29957,29964,29966,29965,29973,29971,29982,29990,29996,30012,30020,30029,30026,
+30025,30043,30022,30042,30057,30052,30055,30059,30061,30072,30070,30086,30087,
+30068,30090,30089,30082,30100,30106,30109,30117,30115,30146,30131,30147,30133,
+30141,30136,30140,30129,30157,30154,30162,30169,30179,30174,30206,30207,30204,
+30209,30192,30202,30194,30195,30219,30221,30217,30239,30247,30240,30241,30242,
+30244,30260,30256,30267,30279,30280,30278,30300,30296,30305,30306,30312,30313,
+30314,30311,30316,30320,30322,30326,30328,30332,30336,30339,30344,30347,30350,
+30358,30355,30361,30362,30384,30388,30392,30393,30394,30402,30413,30422,30418,
+30430,30433,30437,30439,30442,34351,30459,30472,30471,30468,30505,30500,30494,
+30501,30502,30491,30519,30520,30535,30554,30568,30571,30555,30565,30591,30590,
+30585,30606,30603,30609,30624,30622,30640,30646,30649,30655,30652,30653,30651,
+30663,30669,30679,30682,30684,30691,30702,30716,30732,30738,31014,30752,31018,
+30789,30862,30836,30854,30844,30874,30860,30883,30901,30890,30895,30929,30918,
+30923,30932,30910,30908,30917,30922,30956,30951,30938,30973,30964,30983,30994,
+30993,31001,31020,31019,31040,31072,31063,31071,31066,31061,31059,31098,31103,
+31114,31133,31143,40779,31146,31150,31155,31161,31162,31177,31189,31207,31212,
+31201,31203,31240,31245,31256,31257,31264,31263,31104,31281,31291,31294,31287,
+31299,31319,31305,31329,31330,31337,40861,31344,31353,31357,31368,31383,31381,
+31384,31382,31401,31432,31408,31414,31429,31428,31423,36995,31431,31434,31437,
+31439,31445,31443,31449,31450,31453,31457,31458,31462,31469,31472,31490,31503,
+31498,31494,31539,31512,31513,31518,31541,31528,31542,31568,31610,31492,31565,
+31499,31564,31557,31605,31589,31604,31591,31600,31601,31596,31598,31645,31640,
+31647,31629,31644,31642,31627,31634,31631,31581,31641,31691,31681,31692,31695,
+31668,31686,31709,31721,31761,31764,31718,31717,31840,31744,31751,31763,31731,
+31735,31767,31757,31734,31779,31783,31786,31775,31799,31787,31805,31820,31811,
+31828,31823,31808,31824,31832,31839,31844,31830,31845,31852,31861,31875,31888,
+31908,31917,31906,31915,31905,31912,31923,31922,31921,31918,31929,31933,31936,
+31941,31938,31960,31954,31964,31970,39739,31983,31986,31988,31990,31994,32006,
+32002,32028,32021,32010,32069,32075,32046,32050,32063,32053,32070,32115,32086,
+32078,32114,32104,32110,32079,32099,32147,32137,32091,32143,32125,32155,32186,
+32174,32163,32181,32199,32189,32171,32317,32162,32175,32220,32184,32159,32176,
+32216,32221,32228,32222,32251,32242,32225,32261,32266,32291,32289,32274,32305,
+32287,32265,32267,32290,32326,32358,32315,32309,32313,32323,32311,32306,32314,
+32359,32349,32342,32350,32345,32346,32377,32362,32361,32380,32379,32387,32213,
+32381,36782,32383,32392,32393,32396,32402,32400,32403,32404,32406,32398,32411,
+32412,32568,32570,32581,32588,32589,32590,32592,32593,32597,32596,32600,32607,
+32608,32616,32617,32615,32632,32642,32646,32643,32648,32647,32652,32660,32670,
+32669,32666,32675,32687,32690,32697,32686,32694,32696,35697,32709,32710,32714,
+32725,32724,32737,32742,32745,32755,32761,39132,32774,32772,32779,32786,32792,
+32793,32796,32801,32808,32831,32827,32842,32838,32850,32856,32858,32863,32866,
+32872,32883,32882,32880,32886,32889,32893,32895,32900,32902,32901,32923,32915,
+32922,32941,20880,32940,32987,32997,32985,32989,32964,32986,32982,33033,33007,
+33009,33051,33065,33059,33071,33099,38539,33094,33086,33107,33105,33020,33137,
+33134,33125,33126,33140,33155,33160,33162,33152,33154,33184,33173,33188,33187,
+33119,33171,33193,33200,33205,33214,33208,33213,33216,33218,33210,33225,33229,
+33233,33241,33240,33224,33242,33247,33248,33255,33274,33275,33278,33281,33282,
+33285,33287,33290,33293,33296,33302,33321,33323,33336,33331,33344,33369,33368,
+33373,33370,33375,33380,33378,33384,33386,33387,33326,33393,33399,33400,33406,
+33421,33426,33451,33439,33467,33452,33505,33507,33503,33490,33524,33523,33530,
+33683,33539,33531,33529,33502,33542,33500,33545,33497,33589,33588,33558,33586,
+33585,33600,33593,33616,33605,33583,33579,33559,33560,33669,33690,33706,33695,
+33698,33686,33571,33678,33671,33674,33660,33717,33651,33653,33696,33673,33704,
+33780,33811,33771,33742,33789,33795,33752,33803,33729,33783,33799,33760,33778,
+33805,33826,33824,33725,33848,34054,33787,33901,33834,33852,34138,33924,33911,
+33899,33965,33902,33922,33897,33862,33836,33903,33913,33845,33994,33890,33977,
+33983,33951,34009,33997,33979,34010,34000,33985,33990,34006,33953,34081,34047,
+34036,34071,34072,34092,34079,34069,34068,34044,34112,34147,34136,34120,34113,
+34306,34123,34133,34176,34212,34184,34193,34186,34216,34157,34196,34203,34282,
+34183,34204,34167,34174,34192,34249,34234,34255,34233,34256,34261,34269,34277,
+34268,34297,34314,34323,34315,34302,34298,34310,34338,34330,34352,34367,34381,
+20053,34388,34399,34407,34417,34451,34467,34473,34474,34443,34444,34486,34479,
+34500,34502,34480,34505,34851,34475,34516,34526,34537,34540,34527,34523,34543,
+34578,34566,34568,34560,34563,34555,34577,34569,34573,34553,34570,34612,34623,
+34615,34619,34597,34601,34586,34656,34655,34680,34636,34638,34676,34647,34664,
+34670,34649,34643,34659,34666,34821,34722,34719,34690,34735,34763,34749,34752,
+34768,38614,34731,34756,34739,34759,34758,34747,34799,34802,34784,34831,34829,
+34814,34806,34807,34830,34770,34833,34838,34837,34850,34849,34865,34870,34873,
+34855,34875,34884,34882,34898,34905,34910,34914,34923,34945,34942,34974,34933,
+34941,34997,34930,34946,34967,34962,34990,34969,34978,34957,34980,34992,35007,
+34993,35011,35012,35028,35032,35033,35037,35065,35074,35068,35060,35048,35058,
+35076,35084,35082,35091,35139,35102,35109,35114,35115,35137,35140,35131,35126,
+35128,35148,35101,35168,35166,35174,35172,35181,35178,35183,35188,35191,35198,
+35203,35208,35210,35219,35224,35233,35241,35238,35244,35247,35250,35258,35261,
+35263,35264,35290,35292,35293,35303,35316,35320,35331,35350,35344,35340,35355,
+35357,35365,35382,35393,35419,35410,35398,35400,35452,35437,35436,35426,35461,
+35458,35460,35496,35489,35473,35493,35494,35482,35491,35524,35533,35522,35546,
+35563,35571,35559,35556,35569,35604,35552,35554,35575,35550,35547,35596,35591,
+35610,35553,35606,35600,35607,35616,35635,38827,35622,35627,35646,35624,35649,
+35660,35663,35662,35657,35670,35675,35674,35691,35679,35692,35695,35700,35709,
+35712,35724,35726,35730,35731,35734,35737,35738,35898,35905,35903,35912,35916,
+35918,35920,35925,35938,35948,35960,35962,35970,35977,35973,35978,35981,35982,
+35988,35964,35992,25117,36013,36010,36029,36018,36019,36014,36022,36040,36033,
+36068,36067,36058,36093,36090,36091,36100,36101,36106,36103,36111,36109,36112,
+40782,36115,36045,36116,36118,36199,36205,36209,36211,36225,36249,36290,36286,
+36282,36303,36314,36310,36300,36315,36299,36330,36331,36319,36323,36348,36360,
+36361,36351,36381,36382,36368,36383,36418,36405,36400,36404,36426,36423,36425,
+36428,36432,36424,36441,36452,36448,36394,36451,36437,36470,36466,36476,36481,
+36487,36485,36484,36491,36490,36499,36497,36500,36505,36522,36513,36524,36528,
+36550,36529,36542,36549,36552,36555,36571,36579,36604,36603,36587,36606,36618,
+36613,36629,36626,36633,36627,36636,36639,36635,36620,36646,36659,36667,36665,
+36677,36674,36670,36684,36681,36678,36686,36695,36700,36706,36707,36708,36764,
+36767,36771,36781,36783,36791,36826,36837,36834,36842,36847,36999,36852,36869,
+36857,36858,36881,36885,36897,36877,36894,36886,36875,36903,36918,36917,36921,
+36856,36943,36944,36945,36946,36878,36937,36926,36950,36952,36958,36968,36975,
+36982,38568,36978,36994,36989,36993,36992,37002,37001,37007,37032,37039,37041,
+37045,37090,37092,25160,37083,37122,37138,37145,37170,37168,37194,37206,37208,
+37219,37221,37225,37235,37234,37259,37257,37250,37282,37291,37295,37290,37301,
+37300,37306,37312,37313,37321,37323,37328,37334,37343,37345,37339,37372,37365,
+37366,37406,37375,37396,37420,37397,37393,37470,37463,37445,37449,37476,37448,
+37525,37439,37451,37456,37532,37526,37523,37531,37466,37583,37561,37559,37609,
+37647,37626,37700,37678,37657,37666,37658,37667,37690,37685,37691,37724,37728,
+37756,37742,37718,37808,37804,37805,37780,37817,37846,37847,37864,37861,37848,
+37827,37853,37840,37832,37860,37914,37908,37907,37891,37895,37904,37942,37931,
+37941,37921,37946,37953,37970,37956,37979,37984,37986,37982,37994,37417,38000,
+38005,38007,38013,37978,38012,38014,38017,38015,38274,38279,38282,38292,38294,
+38296,38297,38304,38312,38311,38317,38332,38331,38329,38334,38346,28662,38339,
+38349,38348,38357,38356,38358,38364,38369,38373,38370,38433,38440,38446,38447,
+38466,38476,38479,38475,38519,38492,38494,38493,38495,38502,38514,38508,38541,
+38552,38549,38551,38570,38567,38577,38578,38576,38580,38582,38584,38585,38606,
+38603,38601,38605,35149,38620,38669,38613,38649,38660,38662,38664,38675,38670,
+38673,38671,38678,38681,38692,38698,38704,38713,38717,38718,38724,38726,38728,
+38722,38729,38748,38752,38756,38758,38760,21202,38763,38769,38777,38789,38780,
+38785,38778,38790,38795,38799,38800,38812,38824,38822,38819,38835,38836,38851,
+38854,38856,38859,38876,38893,40783,38898,31455,38902,38901,38927,38924,38968,
+38948,38945,38967,38973,38982,38991,38987,39019,39023,39024,39025,39028,39027,
+39082,39087,39089,39094,39108,39107,39110,39145,39147,39171,39177,39186,39188,
+39192,39201,39197,39198,39204,39200,39212,39214,39229,39230,39234,39241,39237,
+39248,39243,39249,39250,39244,39253,39319,39320,39333,39341,39342,39356,39391,
+39387,39389,39384,39377,39405,39406,39409,39410,39419,39416,39425,39439,39429,
+39394,39449,39467,39479,39493,39490,39488,39491,39486,39509,39501,39515,39511,
+39519,39522,39525,39524,39529,39531,39530,39597,39600,39612,39616,39631,39633,
+39635,39636,39646,39647,39650,39651,39654,39663,39659,39662,39668,39665,39671,
+39675,39686,39704,39706,39711,39714,39715,39717,39719,39720,39721,39722,39726,
+39727,39730,39748,39747,39759,39757,39758,39761,39768,39796,39827,39811,39825,
+39830,39831,39839,39840,39848,39860,39872,39882,39865,39878,39887,39889,39890,
+39907,39906,39908,39892,39905,39994,39922,39921,39920,39957,39956,39945,39955,
+39948,39942,39944,39954,39946,39940,39982,39963,39973,39972,39969,39984,40007,
+39986,40006,39998,40026,40032,40039,40054,40056,40167,40172,40176,40201,40200,
+40171,40195,40198,40234,40230,40367,40227,40223,40260,40213,40210,40257,40255,
+40254,40262,40264,40285,40286,40292,40273,40272,40281,40306,40329,40327,40363,
+40303,40314,40346,40356,40361,40370,40388,40385,40379,40376,40378,40390,40399,
+40386,40409,40403,40440,40422,40429,40431,40445,40474,40475,40478,40565,40569,
+40573,40577,40584,40587,40588,40594,40597,40593,40605,40613,40617,40632,40618,
+40621,38753,40652,40654,40655,40656,40660,40668,40670,40669,40672,40677,40680,
+40687,40692,40694,40695,40697,40699,40700,40701,40711,40712,30391,40725,40737,
+40748,40766,40778,40786,40788,40803,40799,40800,40801,40806,40807,40812,40810,
+40823,40818,40822,40853,40860,40864,22575,27079,36953,29796,20956,29081,
diff --git a/system/lib/libc/musl/src/locale/ksc.h b/system/lib/libc/musl/src/locale/ksc.h
new file mode 100644
index 00000000..8f6eca4b
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/ksc.h
@@ -0,0 +1,640 @@
+12288,12289,12290,183,8229,8230,168,12291,173,8213,8741,65340,8764,8216,8217,
+8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12304,
+12305,177,215,247,8800,8804,8805,8734,8756,176,8242,8243,8451,8491,65504,
+65505,65509,9794,9792,8736,8869,8978,8706,8711,8801,8786,167,8251,9734,9733,
+9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8594,8592,8593,8595,
+8596,12307,8810,8811,8730,8765,8733,8757,8747,8748,8712,8715,8838,8839,8834,
+8835,8746,8745,8743,8744,65506,8658,8660,8704,8707,180,65374,711,728,733,730,
+729,184,731,161,191,720,8750,8721,8719,164,8457,8240,9665,9664,9655,9654,9828,
+9824,9825,9829,9831,9827,8857,9672,9635,9680,9681,9618,9636,9637,9640,9639,
+9638,9641,9832,9743,9742,9756,9758,182,8224,8225,8597,8599,8601,8598,8600,
+9837,9833,9834,9836,12927,12828,8470,13255,8482,13250,13272,8481,8364,174,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65281,65282,65283,65284,65285,65286,
+65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,
+65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,
+65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,
+65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,
+65339,65510,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,
+65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,
+65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,12593,12594,12595,
+12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,
+12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,
+12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,
+12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,
+12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,
+12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,
+12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,
+8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,0,0,0,0,0,8544,8545,8546,
+8547,8548,8549,8550,8551,8552,8553,0,0,0,0,0,0,0,913,914,915,916,917,918,919,
+920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,0,0,0,0,0,
+0,0,0,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,
+964,965,966,967,968,969,0,0,0,0,0,0,9472,9474,9484,9488,9496,9492,9500,9516,
+9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,
+9519,9512,9527,9535,9501,9520,9509,9528,9538,9490,9489,9498,9497,9494,9493,
+9486,9485,9502,9503,9505,9506,9510,9511,9513,9514,9517,9518,9521,9522,9525,
+9526,9529,9530,9533,9534,9536,9537,9539,9540,9541,9542,9543,9544,9545,9546,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13205,13206,13207,8467,
+13208,13252,13219,13220,13221,13222,13209,13210,13211,13212,13213,13214,13215,
+13216,13217,13218,13258,13197,13198,13199,13263,13192,13193,13256,13223,13224,
+13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13184,13185,13186,
+13187,13188,13242,13243,13244,13245,13246,13247,13200,13201,13202,13203,13204,
+8486,13248,13249,13194,13195,13196,13270,13253,13229,13230,13231,13275,13225,
+13226,13227,13228,13277,13264,13267,13251,13257,13276,13254,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,198,208,170,294,0,306,0,319,321,216,338,186,222,358,330,0,12896,
+12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,
+12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,
+12923,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433,9434,9435,9436,9437,
+9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,9312,9313,9314,
+9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,189,8531,8532,188,
+190,8539,8540,8541,8542,230,273,240,295,305,307,312,320,322,248,339,223,254,
+359,331,329,12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,
+12811,12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
+12824,12825,12826,12827,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,
+9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,
+9397,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,
+9346,185,178,179,8308,8319,8321,8322,8323,8324,12353,12354,12355,12356,12357,
+12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,
+12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,
+12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,
+12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,
+12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,
+12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,
+0,0,0,0,0,0,0,0,0,0,0,12449,12450,12451,12452,12453,12454,12455,12456,12457,
+12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,
+12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,
+12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,
+12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,
+12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,
+12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,0,0,0,
+0,0,0,0,0,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,
+1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,
+1067,1068,1069,1070,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1072,1073,1074,1075,
+1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,
+1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44032,44033,44036,44039,44040,44041,44042,
+44048,44049,44050,44051,44052,44053,44054,44055,44057,44058,44059,44060,44061,
+44064,44068,44076,44077,44079,44080,44081,44088,44089,44092,44096,44107,44109,
+44116,44120,44124,44144,44145,44148,44151,44152,44154,44160,44161,44163,44164,
+44165,44166,44169,44170,44171,44172,44176,44180,44188,44189,44191,44192,44193,
+44200,44201,44202,44204,44207,44208,44216,44217,44219,44220,44221,44225,44228,
+44232,44236,44245,44247,44256,44257,44260,44263,44264,44266,44268,44271,44272,
+44273,44275,44277,44278,44284,44285,44288,44292,44294,44300,44301,44303,44305,
+44312,44316,44320,44329,44332,44333,44340,44341,44344,44348,44356,44357,44359,
+44361,44368,44372,44376,44385,44387,44396,44397,44400,44403,44404,44405,44406,
+44411,44412,44413,44415,44417,44418,44424,44425,44428,44432,44444,44445,44452,
+44471,44480,44481,44484,44488,44496,44497,44499,44508,44512,44516,44536,44537,
+44540,44543,44544,44545,44552,44553,44555,44557,44564,44592,44593,44596,44599,
+44600,44602,44608,44609,44611,44613,44614,44618,44620,44621,44622,44624,44628,
+44630,44636,44637,44639,44640,44641,44645,44648,44649,44652,44656,44664,44665,
+44667,44668,44669,44676,44677,44684,44732,44733,44734,44736,44740,44748,44749,
+44751,44752,44753,44760,44761,44764,44776,44779,44781,44788,44792,44796,44807,
+44808,44813,44816,44844,44845,44848,44850,44852,44860,44861,44863,44865,44866,
+44867,44872,44873,44880,44892,44893,44900,44901,44921,44928,44932,44936,44944,
+44945,44949,44956,44984,44985,44988,44992,44999,45000,45001,45003,45005,45006,
+45012,45020,45032,45033,45040,45041,45044,45048,45056,45057,45060,45068,45072,
+45076,45084,45085,45096,45124,45125,45128,45130,45132,45134,45139,45140,45141,
+45143,45145,45149,45180,45181,45184,45188,45196,45197,45199,45201,45208,45209,
+45210,45212,45215,45216,45217,45218,45224,45225,45227,45228,45229,45230,45231,
+45233,45235,45236,45237,45240,45244,45252,45253,45255,45256,45257,45264,45265,
+45268,45272,45280,45285,45320,45321,45323,45324,45328,45330,45331,45336,45337,
+45339,45340,45341,45347,45348,45349,45352,45356,45364,45365,45367,45368,45369,
+45376,45377,45380,45384,45392,45393,45396,45397,45400,45404,45408,45432,45433,
+45436,45440,45442,45448,45449,45451,45453,45458,45459,45460,45464,45468,45480,
+45516,45520,45524,45532,45533,45535,45544,45545,45548,45552,45561,45563,45565,
+45572,45573,45576,45579,45580,45588,45589,45591,45593,45600,45620,45628,45656,
+45660,45664,45672,45673,45684,45685,45692,45700,45701,45705,45712,45713,45716,
+45720,45721,45722,45728,45729,45731,45733,45734,45738,45740,45744,45748,45768,
+45769,45772,45776,45778,45784,45785,45787,45789,45794,45796,45797,45798,45800,
+45803,45804,45805,45806,45807,45811,45812,45813,45815,45816,45817,45818,45819,
+45823,45824,45825,45828,45832,45840,45841,45843,45844,45845,45852,45908,45909,
+45910,45912,45915,45916,45918,45919,45924,45925,45927,45929,45931,45934,45936,
+45937,45940,45944,45952,45953,45955,45956,45957,45964,45968,45972,45984,45985,
+45992,45996,46020,46021,46024,46027,46028,46030,46032,46036,46037,46039,46041,
+46043,46045,46048,46052,46056,46076,46096,46104,46108,46112,46120,46121,46123,
+46132,46160,46161,46164,46168,46176,46177,46179,46181,46188,46208,46216,46237,
+46244,46248,46252,46261,46263,46265,46272,46276,46280,46288,46293,46300,46301,
+46304,46307,46308,46310,46316,46317,46319,46321,46328,46356,46357,46360,46363,
+46364,46372,46373,46375,46376,46377,46378,46384,46385,46388,46392,46400,46401,
+46403,46404,46405,46411,46412,46413,46416,46420,46428,46429,46431,46432,46433,
+46496,46497,46500,46504,46506,46507,46512,46513,46515,46516,46517,46523,46524,
+46525,46528,46532,46540,46541,46543,46544,46545,46552,46572,46608,46609,46612,
+46616,46629,46636,46644,46664,46692,46696,46748,46749,46752,46756,46763,46764,
+46769,46804,46832,46836,46840,46848,46849,46853,46888,46889,46892,46895,46896,
+46904,46905,46907,46916,46920,46924,46932,46933,46944,46948,46952,46960,46961,
+46963,46965,46972,46973,46976,46980,46988,46989,46991,46992,46993,46994,46998,
+46999,47000,47001,47004,47008,47016,47017,47019,47020,47021,47028,47029,47032,
+47047,47049,47084,47085,47088,47092,47100,47101,47103,47104,47105,47111,47112,
+47113,47116,47120,47128,47129,47131,47133,47140,47141,47144,47148,47156,47157,
+47159,47160,47161,47168,47172,47185,47187,47196,47197,47200,47204,47212,47213,
+47215,47217,47224,47228,47245,47272,47280,47284,47288,47296,47297,47299,47301,
+47308,47312,47316,47325,47327,47329,47336,47337,47340,47344,47352,47353,47355,
+47357,47364,47384,47392,47420,47421,47424,47428,47436,47439,47441,47448,47449,
+47452,47456,47464,47465,47467,47469,47476,47477,47480,47484,47492,47493,47495,
+47497,47498,47501,47502,47532,47533,47536,47540,47548,47549,47551,47553,47560,
+47561,47564,47566,47567,47568,47569,47570,47576,47577,47579,47581,47582,47585,
+47587,47588,47589,47592,47596,47604,47605,47607,47608,47609,47610,47616,47617,
+47624,47637,47672,47673,47676,47680,47682,47688,47689,47691,47693,47694,47699,
+47700,47701,47704,47708,47716,47717,47719,47720,47721,47728,47729,47732,47736,
+47747,47748,47749,47751,47756,47784,47785,47787,47788,47792,47794,47800,47801,
+47803,47805,47812,47816,47832,47833,47868,47872,47876,47885,47887,47889,47896,
+47900,47904,47913,47915,47924,47925,47926,47928,47931,47932,47933,47934,47940,
+47941,47943,47945,47949,47951,47952,47956,47960,47969,47971,47980,48008,48012,
+48016,48036,48040,48044,48052,48055,48064,48068,48072,48080,48083,48120,48121,
+48124,48127,48128,48130,48136,48137,48139,48140,48141,48143,48145,48148,48149,
+48150,48151,48152,48155,48156,48157,48158,48159,48164,48165,48167,48169,48173,
+48176,48177,48180,48184,48192,48193,48195,48196,48197,48201,48204,48205,48208,
+48221,48260,48261,48264,48267,48268,48270,48276,48277,48279,48281,48282,48288,
+48289,48292,48295,48296,48304,48305,48307,48308,48309,48316,48317,48320,48324,
+48333,48335,48336,48337,48341,48344,48348,48372,48373,48374,48376,48380,48388,
+48389,48391,48393,48400,48404,48420,48428,48448,48456,48457,48460,48464,48472,
+48473,48484,48488,48512,48513,48516,48519,48520,48521,48522,48528,48529,48531,
+48533,48537,48538,48540,48548,48560,48568,48596,48597,48600,48604,48617,48624,
+48628,48632,48640,48643,48645,48652,48653,48656,48660,48668,48669,48671,48708,
+48709,48712,48716,48718,48724,48725,48727,48729,48730,48731,48736,48737,48740,
+48744,48746,48752,48753,48755,48756,48757,48763,48764,48765,48768,48772,48780,
+48781,48783,48784,48785,48792,48793,48808,48848,48849,48852,48855,48856,48864,
+48867,48868,48869,48876,48897,48904,48905,48920,48921,48923,48924,48925,48960,
+48961,48964,48968,48976,48977,48981,49044,49072,49093,49100,49101,49104,49108,
+49116,49119,49121,49212,49233,49240,49244,49248,49256,49257,49296,49297,49300,
+49304,49312,49313,49315,49317,49324,49325,49327,49328,49331,49332,49333,49334,
+49340,49341,49343,49344,49345,49349,49352,49353,49356,49360,49368,49369,49371,
+49372,49373,49380,49381,49384,49388,49396,49397,49399,49401,49408,49412,49416,
+49424,49429,49436,49437,49438,49439,49440,49443,49444,49446,49447,49452,49453,
+49455,49456,49457,49462,49464,49465,49468,49472,49480,49481,49483,49484,49485,
+49492,49493,49496,49500,49508,49509,49511,49512,49513,49520,49524,49528,49541,
+49548,49549,49550,49552,49556,49558,49564,49565,49567,49569,49573,49576,49577,
+49580,49584,49597,49604,49608,49612,49620,49623,49624,49632,49636,49640,49648,
+49649,49651,49660,49661,49664,49668,49676,49677,49679,49681,49688,49689,49692,
+49695,49696,49704,49705,49707,49709,49711,49713,49714,49716,49736,49744,49745,
+49748,49752,49760,49765,49772,49773,49776,49780,49788,49789,49791,49793,49800,
+49801,49808,49816,49819,49821,49828,49829,49832,49836,49837,49844,49845,49847,
+49849,49884,49885,49888,49891,49892,49899,49900,49901,49903,49905,49910,49912,
+49913,49915,49916,49920,49928,49929,49932,49933,49939,49940,49941,49944,49948,
+49956,49957,49960,49961,49989,50024,50025,50028,50032,50034,50040,50041,50044,
+50045,50052,50056,50060,50112,50136,50137,50140,50143,50144,50146,50152,50153,
+50157,50164,50165,50168,50184,50192,50212,50220,50224,50228,50236,50237,50248,
+50276,50277,50280,50284,50292,50293,50297,50304,50324,50332,50360,50364,50409,
+50416,50417,50420,50424,50426,50431,50432,50433,50444,50448,50452,50460,50472,
+50473,50476,50480,50488,50489,50491,50493,50500,50501,50504,50505,50506,50508,
+50509,50510,50515,50516,50517,50519,50520,50521,50525,50526,50528,50529,50532,
+50536,50544,50545,50547,50548,50549,50556,50557,50560,50564,50567,50572,50573,
+50575,50577,50581,50583,50584,50588,50592,50601,50612,50613,50616,50617,50619,
+50620,50621,50622,50628,50629,50630,50631,50632,50633,50634,50636,50638,50640,
+50641,50644,50648,50656,50657,50659,50661,50668,50669,50670,50672,50676,50678,
+50679,50684,50685,50686,50687,50688,50689,50693,50694,50695,50696,50700,50704,
+50712,50713,50715,50716,50724,50725,50728,50732,50733,50734,50736,50739,50740,
+50741,50743,50745,50747,50752,50753,50756,50760,50768,50769,50771,50772,50773,
+50780,50781,50784,50796,50799,50801,50808,50809,50812,50816,50824,50825,50827,
+50829,50836,50837,50840,50844,50852,50853,50855,50857,50864,50865,50868,50872,
+50873,50874,50880,50881,50883,50885,50892,50893,50896,50900,50908,50909,50912,
+50913,50920,50921,50924,50928,50936,50937,50941,50948,50949,50952,50956,50964,
+50965,50967,50969,50976,50977,50980,50984,50992,50993,50995,50997,50999,51004,
+51005,51008,51012,51018,51020,51021,51023,51025,51026,51027,51028,51029,51030,
+51031,51032,51036,51040,51048,51051,51060,51061,51064,51068,51069,51070,51075,
+51076,51077,51079,51080,51081,51082,51086,51088,51089,51092,51094,51095,51096,
+51098,51104,51105,51107,51108,51109,51110,51116,51117,51120,51124,51132,51133,
+51135,51136,51137,51144,51145,51148,51150,51152,51160,51165,51172,51176,51180,
+51200,51201,51204,51208,51210,51216,51217,51219,51221,51222,51228,51229,51232,
+51236,51244,51245,51247,51249,51256,51260,51264,51272,51273,51276,51277,51284,
+51312,51313,51316,51320,51322,51328,51329,51331,51333,51334,51335,51339,51340,
+51341,51348,51357,51359,51361,51368,51388,51389,51396,51400,51404,51412,51413,
+51415,51417,51424,51425,51428,51445,51452,51453,51456,51460,51461,51462,51468,
+51469,51471,51473,51480,51500,51508,51536,51537,51540,51544,51552,51553,51555,
+51564,51568,51572,51580,51592,51593,51596,51600,51608,51609,51611,51613,51648,
+51649,51652,51655,51656,51658,51664,51665,51667,51669,51670,51673,51674,51676,
+51677,51680,51682,51684,51687,51692,51693,51695,51696,51697,51704,51705,51708,
+51712,51720,51721,51723,51724,51725,51732,51736,51753,51788,51789,51792,51796,
+51804,51805,51807,51808,51809,51816,51837,51844,51864,51900,51901,51904,51908,
+51916,51917,51919,51921,51923,51928,51929,51936,51948,51956,51976,51984,51988,
+51992,52000,52001,52033,52040,52041,52044,52048,52056,52057,52061,52068,52088,
+52089,52124,52152,52180,52196,52199,52201,52236,52237,52240,52244,52252,52253,
+52257,52258,52263,52264,52265,52268,52270,52272,52280,52281,52283,52284,52285,
+52286,52292,52293,52296,52300,52308,52309,52311,52312,52313,52320,52324,52326,
+52328,52336,52341,52376,52377,52380,52384,52392,52393,52395,52396,52397,52404,
+52405,52408,52412,52420,52421,52423,52425,52432,52436,52452,52460,52464,52481,
+52488,52489,52492,52496,52504,52505,52507,52509,52516,52520,52524,52537,52572,
+52576,52580,52588,52589,52591,52593,52600,52616,52628,52629,52632,52636,52644,
+52645,52647,52649,52656,52676,52684,52688,52712,52716,52720,52728,52729,52731,
+52733,52740,52744,52748,52756,52761,52768,52769,52772,52776,52784,52785,52787,
+52789,52824,52825,52828,52831,52832,52833,52840,52841,52843,52845,52852,52853,
+52856,52860,52868,52869,52871,52873,52880,52881,52884,52888,52896,52897,52899,
+52900,52901,52908,52909,52929,52964,52965,52968,52971,52972,52980,52981,52983,
+52984,52985,52992,52993,52996,53000,53008,53009,53011,53013,53020,53024,53028,
+53036,53037,53039,53040,53041,53048,53076,53077,53080,53084,53092,53093,53095,
+53097,53104,53105,53108,53112,53120,53125,53132,53153,53160,53168,53188,53216,
+53217,53220,53224,53232,53233,53235,53237,53244,53248,53252,53265,53272,53293,
+53300,53301,53304,53308,53316,53317,53319,53321,53328,53332,53336,53344,53356,
+53357,53360,53364,53372,53373,53377,53412,53413,53416,53420,53428,53429,53431,
+53433,53440,53441,53444,53448,53449,53456,53457,53459,53460,53461,53468,53469,
+53472,53476,53484,53485,53487,53488,53489,53496,53517,53552,53553,53556,53560,
+53562,53568,53569,53571,53572,53573,53580,53581,53584,53588,53596,53597,53599,
+53601,53608,53612,53628,53636,53640,53664,53665,53668,53672,53680,53681,53683,
+53685,53690,53692,53696,53720,53748,53752,53767,53769,53776,53804,53805,53808,
+53812,53820,53821,53823,53825,53832,53852,53860,53888,53889,53892,53896,53904,
+53905,53909,53916,53920,53924,53932,53937,53944,53945,53948,53951,53952,53954,
+53960,53961,53963,53972,53976,53980,53988,53989,54000,54001,54004,54008,54016,
+54017,54019,54021,54028,54029,54030,54032,54036,54038,54044,54045,54047,54048,
+54049,54053,54056,54057,54060,54064,54072,54073,54075,54076,54077,54084,54085,
+54140,54141,54144,54148,54156,54157,54159,54160,54161,54168,54169,54172,54176,
+54184,54185,54187,54189,54196,54200,54204,54212,54213,54216,54217,54224,54232,
+54241,54243,54252,54253,54256,54260,54268,54269,54271,54273,54280,54301,54336,
+54340,54364,54368,54372,54381,54383,54392,54393,54396,54399,54400,54402,54408,
+54409,54411,54413,54420,54441,54476,54480,54484,54492,54495,54504,54508,54512,
+54520,54523,54525,54532,54536,54540,54548,54549,54551,54588,54589,54592,54596,
+54604,54605,54607,54609,54616,54617,54620,54624,54629,54632,54633,54635,54637,
+54644,54645,54648,54652,54660,54661,54663,54664,54665,54672,54693,54728,54729,
+54732,54736,54738,54744,54745,54747,54749,54756,54757,54760,54764,54772,54773,
+54775,54777,54784,54785,54788,54792,54800,54801,54803,54804,54805,54812,54816,
+54820,54829,54840,54841,54844,54848,54853,54856,54857,54859,54861,54865,54868,
+54869,54872,54876,54887,54889,54896,54897,54900,54915,54917,54924,54925,54928,
+54932,54941,54943,54945,54952,54956,54960,54969,54971,54980,54981,54984,54988,
+54993,54996,54999,55001,55008,55012,55016,55024,55029,55036,55037,55040,55044,
+55057,55064,55065,55068,55072,55080,55081,55083,55085,55092,55093,55096,55100,
+55108,55111,55113,55120,55121,55124,55126,55127,55128,55129,55136,55137,55139,
+55141,55145,55148,55152,55156,55164,55165,55169,55176,55177,55180,55184,55192,
+55193,55195,55197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20285,20339,20551,20729,
+21152,21487,21621,21733,22025,23233,23478,26247,26550,26551,26607,27468,29634,
+30146,31292,33499,33540,34903,34952,35382,36040,36303,36603,36838,39381,21051,
+21364,21508,24682,24932,27580,29647,33050,35258,35282,38307,20355,21002,22718,
+22904,23014,24178,24185,25031,25536,26438,26604,26751,28567,30286,30475,30965,
+31240,31487,31777,32925,33390,33393,35563,38291,20075,21917,26359,28212,30883,
+31469,33883,35088,34638,38824,21208,22350,22570,23884,24863,25022,25121,25954,
+26577,27204,28187,29976,30131,30435,30640,32058,37039,37969,37970,40853,21283,
+23724,30002,32987,37440,38296,21083,22536,23004,23713,23831,24247,24378,24394,
+24951,27743,30074,30086,31968,32115,32177,32652,33108,33313,34193,35137,35611,
+37628,38477,40007,20171,20215,20491,20977,22607,24887,24894,24936,25913,27114,
+28433,30117,30342,30422,31623,33445,33995,63744,37799,38283,21888,23458,22353,
+63745,31923,32697,37301,20520,21435,23621,24040,25298,25454,25818,25831,28192,
+28844,31067,36317,36382,63746,36989,37445,37624,20094,20214,20581,24062,24314,
+24838,26967,33137,34388,36423,37749,39467,20062,20625,26480,26688,20745,21133,
+21138,27298,30652,37392,40660,21163,24623,36850,20552,25001,25581,25802,26684,
+27268,28608,33160,35233,38548,22533,29309,29356,29956,32121,32365,32937,35211,
+35700,36963,40273,25225,27770,28500,32080,32570,35363,20860,24906,31645,35609,
+37463,37772,20140,20435,20510,20670,20742,21185,21197,21375,22384,22659,24218,
+24465,24950,25004,25806,25964,26223,26299,26356,26775,28039,28805,28913,29855,
+29861,29898,30169,30828,30956,31455,31478,32069,32147,32789,32831,33051,33686,
+35686,36629,36885,37857,38915,38968,39514,39912,20418,21843,22586,22865,23395,
+23622,24760,25106,26690,26800,26856,28330,30028,30328,30926,31293,31995,32363,
+32380,35336,35489,35903,38542,40388,21476,21481,21578,21617,22266,22993,23396,
+23611,24235,25335,25911,25925,25970,26272,26543,27073,27837,30204,30352,30590,
+31295,32660,32771,32929,33167,33510,33533,33776,34241,34865,34996,35493,63747,
+36764,37678,38599,39015,39640,40723,21741,26011,26354,26767,31296,35895,40288,
+22256,22372,23825,26118,26801,26829,28414,29736,34974,39908,27752,63748,39592,
+20379,20844,20849,21151,23380,24037,24656,24685,25329,25511,25915,29657,31354,
+34467,36002,38799,20018,23521,25096,26524,29916,31185,33747,35463,35506,36328,
+36942,37707,38982,24275,27112,34303,37101,63749,20896,23448,23532,24931,26874,
+27454,28748,29743,29912,31649,32592,33733,35264,36011,38364,39208,21038,24669,
+25324,36866,20362,20809,21281,22745,24291,26336,27960,28826,29378,29654,31568,
+33009,37979,21350,25499,32619,20054,20608,22602,22750,24618,24871,25296,27088,
+39745,23439,32024,32945,36703,20132,20689,21676,21932,23308,23968,24039,25898,
+25934,26657,27211,29409,30350,30703,32094,32761,33184,34126,34527,36611,36686,
+37066,39171,39509,39851,19992,20037,20061,20167,20465,20855,21246,21312,21475,
+21477,21646,22036,22389,22434,23495,23943,24272,25084,25304,25937,26552,26601,
+27083,27472,27590,27628,27714,28317,28792,29399,29590,29699,30655,30697,31350,
+32127,32777,33276,33285,33290,33503,34914,35635,36092,36544,36881,37041,37476,
+37558,39378,39493,40169,40407,40860,22283,23616,33738,38816,38827,40628,21531,
+31384,32676,35033,36557,37089,22528,23624,25496,31391,23470,24339,31353,31406,
+33422,36524,20518,21048,21240,21367,22280,25331,25458,27402,28099,30519,21413,
+29527,34152,36470,38357,26426,27331,28528,35437,36556,39243,63750,26231,27512,
+36020,39740,63751,21483,22317,22862,25542,27131,29674,30789,31418,31429,31998,
+33909,35215,36211,36917,38312,21243,22343,30023,31584,33740,37406,63752,27224,
+20811,21067,21127,25119,26840,26997,38553,20677,21156,21220,25027,26020,26681,
+27135,29822,31563,33465,33771,35250,35641,36817,39241,63753,20170,22935,25810,
+26129,27278,29748,31105,31165,33449,34942,34943,35167,63754,37670,20235,21450,
+24613,25201,27762,32026,32102,20120,20834,30684,32943,20225,20238,20854,20864,
+21980,22120,22331,22522,22524,22804,22855,22931,23492,23696,23822,24049,24190,
+24524,25216,26071,26083,26398,26399,26462,26827,26820,27231,27450,27683,27773,
+27778,28103,29592,29734,29738,29826,29859,30072,30079,30849,30959,31041,31047,
+31048,31098,31637,32000,32186,32648,32774,32813,32908,35352,35663,35912,36215,
+37665,37668,39138,39249,39438,39439,39525,40594,32202,20342,21513,25326,26708,
+37329,21931,20794,63755,63756,23068,25062,63757,25295,25343,63758,63759,63760,
+63761,63762,63763,37027,63764,63765,63766,63767,63768,35582,63769,63770,63771,
+63772,26262,63773,29014,63774,63775,38627,63776,25423,25466,21335,63777,26511,
+26976,28275,63778,30007,63779,63780,63781,32013,63782,63783,34930,22218,23064,
+63784,63785,63786,63787,63788,20035,63789,20839,22856,26608,32784,63790,22899,
+24180,25754,31178,24565,24684,25288,25467,23527,23511,21162,63791,22900,24361,
+24594,63792,63793,63794,29785,63795,63796,63797,63798,63799,63800,39377,63801,
+63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,28611,63812,63813,
+33215,36786,24817,63814,63815,33126,63816,63817,23615,63818,63819,63820,63821,
+63822,63823,63824,63825,23273,35365,26491,32016,63826,63827,63828,63829,63830,
+63831,33021,63832,63833,23612,27877,21311,28346,22810,33590,20025,20150,20294,
+21934,22296,22727,24406,26039,26086,27264,27573,28237,30701,31471,31774,32222,
+34507,34962,37170,37723,25787,28606,29562,30136,36948,21846,22349,25018,25812,
+26311,28129,28251,28525,28601,30192,32835,33213,34113,35203,35527,35674,37663,
+27795,30035,31572,36367,36957,21776,22530,22616,24162,25095,25758,26848,30070,
+31958,34739,40680,20195,22408,22382,22823,23565,23729,24118,24453,25140,25825,
+29619,33274,34955,36024,38538,40667,23429,24503,24755,20498,20992,21040,22294,
+22581,22615,23566,23648,23798,23947,24230,24466,24764,25361,25481,25623,26691,
+26873,27330,28120,28193,28372,28644,29182,30428,30585,31153,31291,33796,35241,
+36077,36339,36424,36867,36884,36947,37117,37709,38518,38876,27602,28678,29272,
+29346,29544,30563,31167,31716,32411,35712,22697,24775,25958,26109,26302,27788,
+28958,29129,35930,38931,20077,31361,20189,20908,20941,21205,21516,24999,26481,
+26704,26847,27934,28540,30140,30643,31461,33012,33891,37509,20828,26007,26460,
+26515,30168,31431,33651,63834,35910,36887,38957,23663,33216,33434,36929,36975,
+37389,24471,23965,27225,29128,30331,31561,34276,35588,37159,39472,21895,25078,
+63835,30313,32645,34367,34746,35064,37007,63836,27931,28889,29662,32097,33853,
+63837,37226,39409,63838,20098,21365,27396,27410,28734,29211,34349,40478,21068,
+36771,23888,25829,25900,27414,28651,31811,32412,34253,35172,35261,25289,33240,
+34847,24266,26391,28010,29436,29701,29807,34690,37086,20358,23821,24480,33802,
+20919,25504,30053,20142,20486,20841,20937,26753,27153,31918,31921,31975,33391,
+35538,36635,37327,20406,20791,21237,21570,24300,24942,25150,26053,27354,28670,
+31018,34268,34851,38317,39522,39530,40599,40654,21147,26310,27511,28701,31019,
+36706,38722,24976,25088,25891,28451,29001,29833,32244,32879,34030,36646,36899,
+37706,20925,21015,21155,27916,28872,35010,24265,25986,27566,28610,31806,29557,
+20196,20278,22265,63839,23738,23994,24604,29618,31533,32666,32718,32838,36894,
+37428,38646,38728,38936,40801,20363,28583,31150,37300,38583,21214,63840,25736,
+25796,27347,28510,28696,29200,30439,32769,34310,34396,36335,36613,38706,39791,
+40442,40565,30860,31103,32160,33737,37636,40575,40595,35542,22751,24324,26407,
+28711,29903,31840,32894,20769,28712,29282,30922,36034,36058,36084,38647,20102,
+20698,23534,24278,26009,29134,30274,30637,32842,34044,36988,39719,40845,22744,
+23105,23650,27155,28122,28431,30267,32047,32311,34078,35128,37860,38475,21129,
+26066,26611,27060,27969,28316,28687,29705,29792,30041,30244,30827,35628,39006,
+20845,25134,38520,20374,20523,23833,28138,32184,36650,24459,24900,26647,63841,
+38534,21202,32907,20956,20940,26974,31260,32190,33777,38517,20442,21033,21400,
+21519,21774,23653,24743,26446,26792,28012,29313,29432,29702,29827,63842,30178,
+31852,32633,32696,33673,35023,35041,37324,37328,38626,39881,21533,28542,29136,
+29848,34298,36522,38563,40023,40607,26519,28107,29747,33256,38678,30764,31435,
+31520,31890,25705,29802,30194,30908,30952,39340,39764,40635,23518,24149,28448,
+33180,33707,37000,19975,21325,23081,24018,24398,24930,25405,26217,26364,28415,
+28459,28771,30622,33836,34067,34875,36627,39237,39995,21788,25273,26411,27819,
+33545,35178,38778,20129,22916,24536,24537,26395,32178,32596,33426,33579,33725,
+36638,37017,22475,22969,23186,23504,26151,26522,26757,27599,29028,32629,36023,
+36067,36993,39749,33032,35978,38476,39488,40613,23391,27667,29467,30450,30431,
+33804,20906,35219,20813,20885,21193,26825,27796,30468,30496,32191,32236,38754,
+40629,28357,34065,20901,21517,21629,26126,26269,26919,28319,30399,30609,33559,
+33986,34719,37225,37528,40180,34946,20398,20882,21215,22982,24125,24917,25720,
+25721,26286,26576,27169,27597,27611,29279,29281,29761,30520,30683,32791,33468,
+33541,35584,35624,35980,26408,27792,29287,30446,30566,31302,40361,27519,27794,
+22818,26406,33945,21359,22675,22937,24287,25551,26164,26483,28218,29483,31447,
+33495,37672,21209,24043,25006,25035,25098,25287,25771,26080,26969,27494,27595,
+28961,29687,30045,32326,33310,33538,34154,35491,36031,38695,40289,22696,40664,
+20497,21006,21563,21839,25991,27766,32010,32011,32862,34442,38272,38639,21247,
+27797,29289,21619,23194,23614,23883,24396,24494,26410,26806,26979,28220,28228,
+30473,31859,32654,34183,35598,36855,38753,40692,23735,24758,24845,25003,25935,
+26107,26108,27665,27887,29599,29641,32225,38292,23494,34588,35600,21085,21338,
+25293,25615,25778,26420,27192,27850,29632,29854,31636,31893,32283,33162,33334,
+34180,36843,38649,39361,20276,21322,21453,21467,25292,25644,25856,26001,27075,
+27886,28504,29677,30036,30242,30436,30460,30928,30971,31020,32070,33324,34784,
+36820,38930,39151,21187,25300,25765,28196,28497,30332,36299,37297,37474,39662,
+39747,20515,20621,22346,22952,23592,24135,24439,25151,25918,26041,26049,26121,
+26507,27036,28354,30917,32033,32938,33152,33323,33459,33953,34444,35370,35607,
+37030,38450,40848,20493,20467,63843,22521,24472,25308,25490,26479,28227,28953,
+30403,32972,32986,35060,35061,35097,36064,36649,37197,38506,20271,20336,24091,
+26575,26658,30333,30334,39748,24161,27146,29033,29140,30058,63844,32321,34115,
+34281,39132,20240,31567,32624,38309,20961,24070,26805,27710,27726,27867,29359,
+31684,33539,27861,29754,20731,21128,22721,25816,27287,29863,30294,30887,34327,
+38370,38713,63845,21342,24321,35722,36776,36783,37002,21029,30629,40009,40712,
+19993,20482,20853,23643,24183,26142,26170,26564,26821,28851,29953,30149,31177,
+31453,36647,39200,39432,20445,22561,22577,23542,26222,27493,27921,28282,28541,
+29668,29995,33769,35036,35091,35676,36628,20239,20693,21264,21340,23443,24489,
+26381,31119,33145,33583,34068,35079,35206,36665,36667,39333,39954,26412,20086,
+20472,22857,23553,23791,23792,25447,26834,28925,29090,29739,32299,34028,34562,
+36898,37586,40179,19981,20184,20463,20613,21078,21103,21542,21648,22496,22827,
+23142,23386,23413,23500,24220,63846,25206,25975,26023,28014,28325,29238,31526,
+31807,32566,33104,33105,33178,33344,33433,33705,35331,36000,36070,36091,36212,
+36282,37096,37340,38428,38468,39385,40167,21271,20998,21545,22132,22707,22868,
+22894,24575,24996,25198,26128,27774,28954,30406,31881,31966,32027,33452,36033,
+38640,63847,20315,24343,24447,25282,23849,26379,26842,30844,32323,40300,19989,
+20633,21269,21290,21329,22915,23138,24199,24754,24970,25161,25209,26000,26503,
+27047,27604,27606,27607,27608,27832,63848,29749,30202,30738,30865,31189,31192,
+31875,32203,32737,32933,33086,33218,33778,34586,35048,35513,35692,36027,37145,
+38750,39131,40763,22188,23338,24428,25996,27315,27567,27996,28657,28693,29277,
+29613,36007,36051,38971,24977,27703,32856,39425,20045,20107,20123,20181,20282,
+20284,20351,20447,20735,21490,21496,21766,21987,22235,22763,22882,23057,23531,
+23546,23556,24051,24107,24473,24605,25448,26012,26031,26614,26619,26797,27515,
+27801,27863,28195,28681,29509,30722,31038,31040,31072,31169,31721,32023,32114,
+32902,33293,33678,34001,34503,35039,35408,35422,35613,36060,36198,36781,37034,
+39164,39391,40605,21066,63849,26388,63850,20632,21034,23665,25955,27733,29642,
+29987,30109,31639,33948,37240,38704,20087,25746,27578,29022,34217,19977,63851,
+26441,26862,28183,33439,34072,34923,25591,28545,37394,39087,19978,20663,20687,
+20767,21830,21930,22039,23360,23577,23776,24120,24202,24224,24258,24819,26705,
+27233,28248,29245,29248,29376,30456,31077,31665,32724,35059,35316,35443,35937,
+36062,38684,22622,29885,36093,21959,63852,31329,32034,33394,29298,29983,29989,
+63853,31513,22661,22779,23996,24207,24246,24464,24661,25234,25471,25933,26257,
+26329,26360,26646,26866,29312,29790,31598,32110,32214,32626,32997,33298,34223,
+35199,35475,36893,37604,40653,40736,22805,22893,24109,24796,26132,26227,26512,
+27728,28101,28511,30707,30889,33990,37323,37675,20185,20682,20808,21892,23307,
+23459,25159,25982,26059,28210,29053,29697,29764,29831,29887,30316,31146,32218,
+32341,32680,33146,33203,33337,34330,34796,35445,36323,36984,37521,37925,39245,
+39854,21352,23633,26964,27844,27945,28203,33292,34203,35131,35373,35498,38634,
+40807,21089,26297,27570,32406,34814,36109,38275,38493,25885,28041,29166,63854,
+22478,22995,23468,24615,24826,25104,26143,26207,29481,29689,30427,30465,31596,
+32854,32882,33125,35488,37266,19990,21218,27506,27927,31237,31545,32048,63855,
+36016,21484,22063,22609,23477,23567,23569,24034,25152,25475,25620,26157,26803,
+27836,28040,28335,28703,28836,29138,29990,30095,30094,30233,31505,31712,31787,
+32032,32057,34092,34157,34311,35380,36877,36961,37045,37559,38902,39479,20439,
+23660,26463,28049,31903,32396,35606,36118,36895,23403,24061,25613,33984,36956,
+39137,29575,23435,24730,26494,28126,35359,35494,36865,38924,21047,63856,28753,
+30862,37782,34928,37335,20462,21463,22013,22234,22402,22781,23234,23432,23723,
+23744,24101,24833,25101,25163,25480,25628,25910,25976,27193,27530,27700,27929,
+28465,29159,29417,29560,29703,29874,30246,30561,31168,31319,31466,31929,32143,
+32172,32353,32670,33065,33585,33936,34010,34282,34966,35504,35728,36664,36930,
+36995,37228,37526,37561,38539,38567,38568,38614,38656,38920,39318,39635,39706,
+21460,22654,22809,23408,23487,28113,28506,29087,29729,29881,32901,33789,24033,
+24455,24490,24642,26092,26642,26991,27219,27529,27957,28147,29667,30462,30636,
+31565,32020,33059,33308,33600,34036,34147,35426,35524,37255,37662,38918,39348,
+25100,34899,36848,37477,23815,23847,23913,29791,33181,34664,28629,25342,32722,
+35126,35186,19998,20056,20711,21213,21319,25215,26119,32361,34821,38494,20365,
+21273,22070,22987,23204,23608,23630,23629,24066,24337,24643,26045,26159,26178,
+26558,26612,29468,30690,31034,32709,33940,33997,35222,35430,35433,35553,35925,
+35962,22516,23508,24335,24687,25325,26893,27542,28252,29060,31698,34645,35672,
+36606,39135,39166,20280,20353,20449,21627,23072,23480,24892,26032,26216,29180,
+30003,31070,32051,33102,33251,33688,34218,34254,34563,35338,36523,36763,63857,
+36805,22833,23460,23526,24713,23529,23563,24515,27777,63858,28145,28683,29978,
+33455,35574,20160,21313,63859,38617,27663,20126,20420,20818,21854,23077,23784,
+25105,29273,33469,33706,34558,34905,35357,38463,38597,39187,40201,40285,22538,
+23731,23997,24132,24801,24853,25569,27138,28197,37122,37716,38990,39952,40823,
+23433,23736,25353,26191,26696,30524,38593,38797,38996,39839,26017,35585,36555,
+38332,21813,23721,24022,24245,26263,30284,33780,38343,22739,25276,29390,40232,
+20208,22830,24591,26171,27523,31207,40230,21395,21696,22467,23830,24859,26326,
+28079,30861,33406,38552,38724,21380,25212,25494,28082,32266,33099,38989,27387,
+32588,40367,40474,20063,20539,20918,22812,24825,25590,26928,29242,32822,63860,
+37326,24369,63861,63862,32004,33509,33903,33979,34277,36493,63863,20335,63864,
+63865,22756,23363,24665,25562,25880,25965,26264,63866,26954,27171,27915,28673,
+29036,30162,30221,31155,31344,63867,32650,63868,35140,63869,35731,37312,38525,
+63870,39178,22276,24481,26044,28417,30208,31142,35486,39341,39770,40812,20740,
+25014,25233,27277,33222,20547,22576,24422,28937,35328,35578,23420,34326,20474,
+20796,22196,22852,25513,28153,23978,26989,20870,20104,20313,63871,63872,63873,
+22914,63874,63875,27487,27741,63876,29877,30998,63877,33287,33349,33593,36671,
+36701,63878,39192,63879,63880,63881,20134,63882,22495,24441,26131,63883,63884,
+30123,32377,35695,63885,36870,39515,22181,22567,23032,23071,23476,63886,24310,
+63887,63888,25424,25403,63889,26941,27783,27839,28046,28051,28149,28436,63890,
+28895,28982,29017,63891,29123,29141,63892,30799,30831,63893,31605,32227,63894,
+32303,63895,34893,36575,63896,63897,63898,37467,63899,40182,63900,63901,63902,
+24709,28037,63903,29105,63904,63905,38321,21421,63906,63907,63908,26579,63909,
+28814,28976,29744,33398,33490,63910,38331,39653,40573,26308,63911,29121,33865,
+63912,63913,22603,63914,63915,23992,24433,63916,26144,26254,27001,27054,27704,
+27891,28214,28481,28634,28699,28719,29008,29151,29552,63917,29787,63918,29908,
+30408,31310,32403,63919,63920,33521,35424,36814,63921,37704,63922,38681,63923,
+63924,20034,20522,63925,21000,21473,26355,27757,28618,29450,30591,31330,33454,
+34269,34306,63926,35028,35427,35709,35947,63927,37555,63928,38675,38928,20116,
+20237,20425,20658,21320,21566,21555,21978,22626,22714,22887,23067,23524,24735,
+63929,25034,25942,26111,26212,26791,27738,28595,28879,29100,29522,31613,34568,
+35492,39986,40711,23627,27779,29508,29577,37434,28331,29797,30239,31337,32277,
+34314,20800,22725,25793,29934,29973,30320,32705,37013,38605,39252,28198,29926,
+31401,31402,33253,34521,34680,35355,23113,23436,23451,26785,26880,28003,29609,
+29715,29740,30871,32233,32747,33048,33109,33694,35916,38446,38929,26352,24448,
+26106,26505,27754,29579,20525,23043,27498,30702,22806,23916,24013,29477,30031,
+63930,63931,20709,20985,22575,22829,22934,23002,23525,63932,63933,23970,25303,
+25622,25747,25854,63934,26332,63935,27208,63936,29183,29796,63937,31368,31407,
+32327,32350,32768,33136,63938,34799,35201,35616,36953,63939,36992,39250,24958,
+27442,28020,32287,35109,36785,20433,20653,20887,21191,22471,22665,23481,24248,
+24898,27029,28044,28263,28342,29076,29794,29992,29996,32883,33592,33993,36362,
+37780,37854,63940,20110,20305,20598,20778,21448,21451,21491,23431,23507,23588,
+24858,24962,26100,29275,29591,29760,30402,31056,31121,31161,32006,32701,33419,
+34261,34398,36802,36935,37109,37354,38533,38632,38633,21206,24423,26093,26161,
+26671,29020,31286,37057,38922,20113,63941,27218,27550,28560,29065,32792,33464,
+34131,36939,38549,38642,38907,34074,39729,20112,29066,38596,20803,21407,21729,
+22291,22290,22435,23195,23236,23491,24616,24895,25588,27781,27961,28274,28304,
+29232,29503,29783,33489,34945,36677,36960,63942,38498,39000,40219,26376,36234,
+37470,20301,20553,20702,21361,22285,22996,23041,23561,24944,26256,28205,29234,
+29771,32239,32963,33806,33894,34111,34655,34907,35096,35586,36949,38859,39759,
+20083,20369,20754,20842,63943,21807,21929,23418,23461,24188,24189,24254,24736,
+24799,24840,24841,25540,25912,26377,63944,26580,26586,63945,26977,26978,27833,
+27943,63946,28216,63947,28641,29494,29495,63948,29788,30001,63949,30290,63950,
+63951,32173,33278,33848,35029,35480,35547,35565,36400,36418,36938,36926,36986,
+37193,37321,37742,63952,63953,22537,63954,27603,32905,32946,63955,63956,20801,
+22891,23609,63957,63958,28516,29607,32996,36103,63959,37399,38287,63960,63961,
+63962,63963,32895,25102,28700,32104,34701,63964,22432,24681,24903,27575,35518,
+37504,38577,20057,21535,28139,34093,38512,38899,39150,25558,27875,37009,20957,
+25033,33210,40441,20381,20506,20736,23452,24847,25087,25836,26885,27589,30097,
+30691,32681,33380,34191,34811,34915,35516,35696,37291,20108,20197,20234,63965,
+63966,22839,23016,63967,24050,24347,24411,24609,63968,63969,63970,63971,29246,
+29669,63972,30064,30157,63973,31227,63974,32780,32819,32900,33505,33617,63975,
+63976,36029,36019,36999,63977,63978,39156,39180,63979,63980,28727,30410,32714,
+32716,32764,35610,20154,20161,20995,21360,63981,21693,22240,23035,23493,24341,
+24525,28270,63982,63983,32106,33589,63984,34451,35469,63985,38765,38775,63986,
+63987,19968,20314,20350,22777,26085,28322,36920,37808,39353,20219,22764,22922,
+23001,24641,63988,63989,31252,63990,33615,36035,20837,21316,63991,63992,63993,
+20173,21097,23381,33471,20180,21050,21672,22985,23039,23376,23383,23388,24675,
+24904,28363,28825,29038,29574,29943,30133,30913,32043,32773,33258,33576,34071,
+34249,35566,36039,38604,20316,21242,22204,26027,26152,28796,28856,29237,32189,
+33421,37196,38592,40306,23409,26855,27544,28538,30430,23697,26283,28507,31668,
+31786,34870,38620,19976,20183,21280,22580,22715,22767,22892,23559,24115,24196,
+24373,25484,26290,26454,27167,27299,27404,28479,29254,63994,29520,29835,31456,
+31911,33144,33247,33255,33674,33900,34083,34196,34255,35037,36115,37292,38263,
+38556,20877,21705,22312,23472,25165,26448,26685,26771,28221,28371,28797,32289,
+35009,36001,36617,40779,40782,29229,31631,35533,37658,20295,20302,20786,21632,
+22992,24213,25269,26485,26990,27159,27822,28186,29401,29482,30141,31672,32053,
+33511,33785,33879,34295,35419,36015,36487,36889,37048,38606,40799,21219,21514,
+23265,23490,25688,25973,28404,29380,63995,30340,31309,31515,31821,32318,32735,
+33659,35627,36042,36196,36321,36447,36842,36857,36969,37841,20291,20346,20659,
+20840,20856,21069,21098,22625,22652,22880,23560,23637,24283,24731,25136,26643,
+27583,27656,28593,29006,29728,30000,30008,30033,30322,31564,31627,31661,31686,
+32399,35438,36670,36681,37439,37523,37666,37931,38651,39002,39019,39198,20999,
+25130,25240,27993,30308,31434,31680,32118,21344,23742,24215,28472,28857,31896,
+38673,39822,40670,25509,25722,34678,19969,20117,20141,20572,20597,21576,22979,
+23450,24128,24237,24311,24449,24773,25402,25919,25972,26060,26230,26232,26622,
+26984,27273,27491,27712,28096,28136,28191,28254,28702,28833,29582,29693,30010,
+30555,30855,31118,31243,31357,31934,32142,33351,35330,35562,35998,37165,37194,
+37336,37478,37580,37664,38662,38742,38748,38914,40718,21046,21137,21884,22564,
+24093,24351,24716,25552,26799,28639,31085,31532,33229,34234,35069,35576,36420,
+37261,38500,38555,38717,38988,40778,20430,20806,20939,21161,22066,24340,24427,
+25514,25805,26089,26177,26362,26361,26397,26781,26839,27133,28437,28526,29031,
+29157,29226,29866,30522,31062,31066,31199,31264,31381,31895,31967,32068,32368,
+32903,34299,34468,35412,35519,36249,36481,36896,36973,37347,38459,38613,40165,
+26063,31751,36275,37827,23384,23562,21330,25305,29469,20519,23447,24478,24752,
+24939,26837,28121,29742,31278,32066,32156,32305,33131,36394,36405,37758,37912,
+20304,22352,24038,24231,25387,32618,20027,20303,20367,20570,23005,32964,21610,
+21608,22014,22863,23449,24030,24282,26205,26417,26609,26666,27880,27954,28234,
+28557,28855,29664,30087,31820,32002,32044,32162,33311,34523,35387,35461,36208,
+36490,36659,36913,37198,37202,37956,39376,31481,31909,20426,20737,20934,22472,
+23535,23803,26201,27197,27994,28310,28652,28940,30063,31459,34850,36897,36981,
+38603,39423,33537,20013,20210,34886,37325,21373,27355,26987,27713,33914,22686,
+24974,26366,25327,28893,29969,30151,32338,33976,35657,36104,20043,21482,21675,
+22320,22336,24535,25345,25351,25711,25903,26088,26234,26525,26547,27490,27744,
+27802,28460,30693,30757,31049,31063,32025,32930,33026,33267,33437,33463,34584,
+35468,63996,36100,36286,36978,30452,31257,31287,32340,32887,21767,21972,22645,
+25391,25634,26185,26187,26733,27035,27524,27941,28337,29645,29800,29857,30043,
+30137,30433,30494,30603,31206,32265,32285,33275,34095,34967,35386,36049,36587,
+36784,36914,37805,38499,38515,38663,20356,21489,23018,23241,24089,26702,29894,
+30142,31209,31378,33187,34541,36074,36300,36845,26015,26389,63997,22519,28503,
+32221,36655,37878,38598,24501,25074,28548,19988,20376,20511,21449,21983,23919,
+24046,27425,27492,30923,31642,63998,36425,36554,36974,25417,25662,30528,31364,
+37679,38015,40810,25776,28591,29158,29864,29914,31428,31762,32386,31922,32408,
+35738,36106,38013,39184,39244,21049,23519,25830,26413,32046,20717,21443,22649,
+24920,24921,25082,26028,31449,35730,35734,20489,20513,21109,21809,23100,24288,
+24432,24884,25950,26124,26166,26274,27085,28356,28466,29462,30241,31379,33081,
+33369,33750,33980,20661,22512,23488,23528,24425,25505,30758,32181,33756,34081,
+37319,37365,20874,26613,31574,36012,20932,22971,24765,34389,20508,63999,21076,
+23610,24957,25114,25299,25842,26021,28364,30240,33034,36448,38495,38587,20191,
+21315,21912,22825,24029,25797,27849,28154,29588,31359,33307,34214,36068,36368,
+36983,37351,38369,38433,38854,20984,21746,21894,24505,25764,28552,32180,36639,
+36685,37941,20681,23574,27838,28155,29979,30651,31805,31844,35449,35522,22558,
+22974,24086,25463,29266,30090,30571,35548,36028,36626,24307,26228,28152,32893,
+33729,35531,38737,39894,64000,21059,26367,28053,28399,32224,35558,36910,36958,
+39636,21021,21119,21736,24980,25220,25307,26786,26898,26970,27189,28818,28966,
+30813,30977,30990,31186,31245,32918,33400,33493,33609,34121,35970,36229,37218,
+37259,37294,20419,22225,29165,30679,34560,35320,23544,24534,26449,37032,21474,
+22618,23541,24740,24961,25696,32317,32880,34085,37507,25774,20652,23828,26368,
+22684,25277,25512,26894,27000,27166,28267,30394,31179,33467,33833,35535,36264,
+36861,37138,37195,37276,37648,37656,37786,38619,39478,39949,19985,30044,31069,
+31482,31569,31689,32302,33988,36441,36468,36600,36880,26149,26943,29763,20986,
+26414,40668,20805,24544,27798,34802,34909,34935,24756,33205,33795,36101,21462,
+21561,22068,23094,23601,28810,32736,32858,33030,33261,36259,37257,39519,40434,
+20596,20164,21408,24827,28204,23652,20360,20516,21988,23769,24159,24677,26772,
+27835,28100,29118,30164,30196,30305,31258,31305,32199,32251,32622,33268,34473,
+36636,38601,39347,40786,21063,21189,39149,35242,19971,26578,28422,20405,23522,
+26517,27784,28024,29723,30759,37341,37756,34756,31204,31281,24555,20182,21668,
+21822,22702,22949,24816,25171,25302,26422,26965,33333,38464,39345,39389,20524,
+21331,21828,22396,64001,25176,64002,25826,26219,26589,28609,28655,29730,29752,
+35351,37944,21585,22022,22374,24392,24986,27470,28760,28845,32187,35477,22890,
+33067,25506,30472,32829,36010,22612,25645,27067,23445,24081,28271,64003,34153,
+20812,21488,22826,24608,24907,27526,27760,27888,31518,32974,33492,36294,37040,
+39089,64004,25799,28580,25745,25860,20814,21520,22303,35342,24927,26742,64005,
+30171,31570,32113,36890,22534,27084,33151,35114,36864,38969,20600,22871,22956,
+25237,36879,39722,24925,29305,38358,22369,23110,24052,25226,25773,25850,26487,
+27874,27966,29228,29750,30772,32631,33453,36315,38935,21028,22338,26495,29256,
+29923,36009,36774,37393,38442,20843,21485,25420,20329,21764,24726,25943,27803,
+28031,29260,29437,31255,35207,35997,24429,28558,28921,33192,24846,20415,20559,
+25153,29255,31687,32232,32745,36941,38829,39449,36022,22378,24179,26544,33805,
+35413,21536,23318,24163,24290,24330,25987,32954,34109,38281,38491,20296,21253,
+21261,21263,21638,21754,22275,24067,24598,25243,25265,25429,64006,27873,28006,
+30129,30770,32990,33071,33502,33889,33970,34957,35090,36875,37610,39165,39825,
+24133,26292,26333,28689,29190,64007,20469,21117,24426,24915,26451,27161,28418,
+29922,31080,34920,35961,39111,39108,39491,21697,31263,26963,35575,35914,39080,
+39342,24444,25259,30130,30382,34987,36991,38466,21305,24380,24517,27852,29644,
+30050,30091,31558,33534,39325,20047,36924,19979,20309,21414,22799,24264,26160,
+27827,29781,33655,34662,36032,36944,38686,39957,22737,23416,34384,35604,40372,
+23506,24680,24717,26097,27735,28450,28579,28698,32597,32752,38289,38290,38480,
+38867,21106,36676,20989,21547,21688,21859,21898,27323,28085,32216,33382,37532,
+38519,40569,21512,21704,30418,34532,38308,38356,38492,20130,20233,23022,23270,
+24055,24658,25239,26477,26689,27782,28207,32568,32923,33322,64008,64009,38917,
+20133,20565,21683,22419,22874,23401,23475,25032,26999,28023,28707,34809,35299,
+35442,35559,36994,39405,39608,21182,26680,20502,24184,26447,33607,34892,20139,
+21521,22190,29670,37141,38911,39177,39255,39321,22099,22687,34395,35377,25010,
+27382,29563,36562,27463,38570,39511,22869,29184,36203,38761,20436,23796,24358,
+25080,26203,27883,28843,29572,29625,29694,30505,30541,32067,32098,32291,33335,
+34898,64010,36066,37449,39023,23377,31348,34880,38913,23244,20448,21332,22846,
+23805,25406,28025,29433,33029,33031,33698,37583,38960,20136,20804,21009,22411,
+24418,27842,28366,28677,28752,28847,29074,29673,29801,33610,34722,34913,36872,
+37026,37795,39336,20846,24407,24800,24935,26291,34137,36426,37295,38795,20046,
+20114,21628,22741,22778,22909,23733,24359,25142,25160,26122,26215,27627,28009,
+28111,28246,28408,28564,28640,28649,28765,29392,29733,29786,29920,30355,31068,
+31946,32286,32993,33446,33899,33983,34382,34399,34676,35703,35946,37804,38912,
+39013,24785,25110,37239,23130,26127,28151,28222,29759,39746,24573,24794,31503,
+21700,24344,27742,27859,27946,28888,32005,34425,35340,40251,21270,21644,23301,
+27194,28779,30069,31117,31166,33457,33775,35441,35649,36008,38772,64011,25844,
+25899,30906,30907,31339,20024,21914,22864,23462,24187,24739,25563,27489,26213,
+26707,28185,29029,29872,32008,36996,39529,39973,27963,28369,29502,35905,38346,
+20976,24140,24488,24653,24822,24880,24908,26179,26180,27045,27841,28255,28361,
+28514,29004,29852,30343,31681,31783,33618,34647,36945,38541,40643,21295,22238,
+24315,24458,24674,24724,25079,26214,26371,27292,28142,28590,28784,29546,32362,
+33214,33588,34516,35496,36036,21123,29554,23446,27243,37892,21742,22150,23389,
+25928,25989,26313,26783,28045,28102,29243,32948,37237,39501,20399,20505,21402,
+21518,21564,21897,21957,24127,24460,26429,29030,29661,36869,21211,21235,22628,
+22734,28932,29071,29179,34224,35347,26248,34216,21927,26244,29002,33841,21321,
+21913,27585,24409,24509,25582,26249,28999,35569,36637,40638,20241,25658,28875,
+30054,34407,24676,35662,40440,20807,20982,21256,27958,33016,40657,26133,27427,
+28824,30165,21507,23673,32007,35350,27424,27453,27462,21560,24688,27965,32725,
+33288,20694,20958,21916,22123,22221,23020,23305,24076,24985,24984,25137,26206,
+26342,29081,29113,29114,29351,31143,31232,32690,35440,
diff --git a/system/lib/libc/musl/src/locale/legacychars.h b/system/lib/libc/musl/src/locale/legacychars.h
new file mode 100644
index 00000000..4ddbaeba
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/legacychars.h
@@ -0,0 +1,39 @@
+0,1,160,167,168,169,175,176,178,183,184,198,215,216,230,247,248,256,257,258,
+259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,278,279,
+280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,
+299,302,303,304,305,308,309,310,311,312,313,314,315,316,317,318,321,322,323,
+324,325,326,327,328,330,331,332,333,336,337,338,339,340,341,342,343,344,345,
+346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,
+365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,402,
+416,417,431,432,536,537,538,539,710,711,728,729,731,732,733,768,769,771,777,
+803,890,900,901,902,904,905,906,908,910,911,912,913,914,915,916,917,918,919,
+920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,938,939,
+940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,
+959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,1025,1026,
+1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1038,1039,1040,1041,1042,
+1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,
+1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,
+1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,
+1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,
+1103,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1118,1119,
+1168,1169,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1467,1468,1469,
+1470,1471,1472,1473,1474,1475,1488,1489,1490,1491,1492,1493,1494,1495,1496,
+1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,
+1512,1513,1514,1520,1521,1522,1523,1524,1548,1563,1567,1569,1570,1571,1572,
+1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,
+1588,1589,1590,1591,1592,1593,1594,1600,1601,1602,1603,1604,1605,1606,1607,
+1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1657,1662,1670,1672,
+1681,1688,1705,1711,1722,1726,1729,1746,3585,3586,3587,3588,3589,3590,3591,
+3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,
+3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,
+3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,
+3637,3638,3639,3640,3641,3642,3647,3648,3649,3650,3651,3652,3653,3654,3655,
+3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,
+3671,3672,3673,3674,3675,7682,7683,7690,7691,7710,7711,7744,7745,7766,7767,
+7776,7777,7786,7787,7808,7809,7810,7811,7812,7813,7922,7923,8204,8205,8206,
+8207,8211,8212,8213,8215,8216,8217,8218,8220,8221,8222,8224,8225,8226,8230,
+8240,8249,8250,8362,8363,8364,8367,8470,8482,8729,8730,8776,8804,8805,8992,
+8993,9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9552,9553,9554,
+9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,
+9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9600,9604,9608,9612,
+9616,9617,9618,9619,9632,
diff --git a/system/lib/libc/musl/src/locale/strfmon.c b/system/lib/libc/musl/src/locale/strfmon.c
new file mode 100644
index 00000000..f510d9a4
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/strfmon.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <monetary.h>
+#include <errno.h>
+#include <stdarg.h>
+
+static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_list ap)
+{
+ size_t l;
+ double x;
+ int fill, nogrp, negpar, nosym, left, intl;
+ int lp, rp, w, fw;
+ char *s0=s;
+ for (; n && *fmt; ) {
+ if (*fmt != '%') {
+ literal:
+ *s++ = *fmt++;
+ n--;
+ continue;
+ }
+ fmt++;
+ if (*fmt == '%') goto literal;
+
+ fill = ' ';
+ nogrp = 0;
+ negpar = 0;
+ nosym = 0;
+ left = 0;
+ for (; ; fmt++) {
+ switch (*fmt) {
+ case '=':
+ fill = *++fmt;
+ continue;
+ case '^':
+ nogrp = 1;
+ continue;
+ case '(':
+ negpar = 1;
+ case '+':
+ continue;
+ case '!':
+ nosym = 1;
+ continue;
+ case '-':
+ left = 1;
+ continue;
+ }
+ break;
+ }
+
+ for (fw=0; isdigit(*fmt); fmt++)
+ fw = 10*fw + (*fmt-'0');
+ lp = 0;
+ rp = 2;
+ if (*fmt=='#') for (lp=0, fmt++; isdigit(*fmt); fmt++)
+ lp = 10*lp + (*fmt-'0');
+ if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt); fmt++)
+ rp = 10*rp + (*fmt-'0');
+
+ intl = *fmt++ == 'i';
+
+ w = lp + 1 + rp;
+ if (!left && fw>w) w = fw;
+
+ x = va_arg(ap, double);
+ l = snprintf(s, n, "%*.*f", w, rp, x);
+ if (l >= n) {
+ errno = E2BIG;
+ return -1;
+ }
+ s += l;
+ n -= l;
+ }
+ return s-s0;
+}
+
+ssize_t strfmon_l(char *restrict s, size_t n, locale_t loc, const char *restrict fmt, ...)
+{
+ va_list ap;
+ ssize_t ret;
+
+ va_start(ap, fmt);
+ ret = vstrfmon_l(s, n, loc, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+
+ssize_t strfmon(char *restrict s, size_t n, const char *restrict fmt, ...)
+{
+ va_list ap;
+ ssize_t ret;
+
+ va_start(ap, fmt);
+ ret = vstrfmon_l(s, n, 0, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/locale/strxfrm.c b/system/lib/libc/musl/src/locale/strxfrm.c
new file mode 100644
index 00000000..32c46193
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/strxfrm.c
@@ -0,0 +1,18 @@
+#include <string.h>
+#include <locale.h>
+#include "libc.h"
+
+/* collate only by code points */
+size_t __strxfrm_l(char *restrict dest, const char *restrict src, size_t n, locale_t loc)
+{
+ size_t l = strlen(src);
+ if (n > l) strcpy(dest, src);
+ return l;
+}
+
+size_t strxfrm(char *restrict dest, const char *restrict src, size_t n)
+{
+ return __strxfrm_l(dest, src, n, 0);
+}
+
+weak_alias(__strxfrm_l, strxfrm_l);
diff --git a/system/lib/libc/musl/src/locale/towctrans_l.c b/system/lib/libc/musl/src/locale/towctrans_l.c
new file mode 100644
index 00000000..6222058c
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/towctrans_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+wint_t towctrans_l(wint_t c, wctrans_t t, locale_t l)
+{
+ return towctrans(c, t);
+}
diff --git a/system/lib/libc/musl/src/locale/towlower_l.c b/system/lib/libc/musl/src/locale/towlower_l.c
new file mode 100644
index 00000000..aaaea370
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/towlower_l.c
@@ -0,0 +1,9 @@
+#include <wctype.h>
+#include "libc.h"
+
+wint_t towlower_l(wint_t c, locale_t l)
+{
+ return towlower(c);
+}
+
+weak_alias(towlower_l, __towlower_l);
diff --git a/system/lib/libc/musl/src/locale/towupper_l.c b/system/lib/libc/musl/src/locale/towupper_l.c
new file mode 100644
index 00000000..ad02a4be
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/towupper_l.c
@@ -0,0 +1,9 @@
+#include <wctype.h>
+#include "libc.h"
+
+wint_t towupper_l(wint_t c, locale_t l)
+{
+ return towupper(c);
+}
+
+weak_alias(towupper_l, __towupper_l);
diff --git a/system/lib/libc/musl/src/locale/wcscoll.c b/system/lib/libc/musl/src/locale/wcscoll.c
new file mode 100644
index 00000000..20a60900
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/wcscoll.c
@@ -0,0 +1,16 @@
+#include <wchar.h>
+#include <locale.h>
+#include "libc.h"
+
+/* FIXME: stub */
+int __wcscoll_l(const wchar_t *l, const wchar_t *r, locale_t locale)
+{
+ return wcscmp(l, r);
+}
+
+int wcscoll(const wchar_t *l, const wchar_t *r)
+{
+ return __wcscoll_l(l, r, 0);
+}
+
+weak_alias(__wcscoll_l, wcscoll_l);
diff --git a/system/lib/libc/musl/src/locale/wcscoll_l.c b/system/lib/libc/musl/src/locale/wcscoll_l.c
new file mode 100644
index 00000000..f257ec8d
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/wcscoll_l.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+int wcscoll_l(const wchar_t *l, const wchar_t *r, locale_t locale)
+{
+ return wcscoll(l, r);
+}
diff --git a/system/lib/libc/musl/src/locale/wcsxfrm.c b/system/lib/libc/musl/src/locale/wcsxfrm.c
new file mode 100644
index 00000000..cb79c97e
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/wcsxfrm.c
@@ -0,0 +1,21 @@
+#include <wchar.h>
+#include <locale.h>
+#include "libc.h"
+
+/* collate only by code points */
+size_t __wcsxfrm_l(wchar_t *restrict dest, const wchar_t *restrict src, size_t n, locale_t loc)
+{
+ size_t l = wcslen(src);
+ if (l >= n) {
+ wmemcpy(dest, src, n-1);
+ dest[n-1] = 0;
+ } else wcscpy(dest, src);
+ return l;
+}
+
+size_t wcsxfrm(wchar_t *restrict dest, const wchar_t *restrict src, size_t n)
+{
+ return __wcsxfrm_l(dest, src, n, 0);
+}
+
+weak_alias(__wcsxfrm_l, wcsxfrm_l);
diff --git a/system/lib/libc/musl/src/locale/wcsxfrm_l.c b/system/lib/libc/musl/src/locale/wcsxfrm_l.c
new file mode 100644
index 00000000..66a00193
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/wcsxfrm_l.c
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+size_t wcsxfrm_l(wchar_t *restrict dest, const wchar_t *restrict src, size_t n, locale_t locale)
+{
+ return wcsxfrm(dest, src, n);
+}
diff --git a/system/lib/libc/musl/src/locale/wctrans_l.c b/system/lib/libc/musl/src/locale/wctrans_l.c
new file mode 100644
index 00000000..dae3381e
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/wctrans_l.c
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+wctrans_t wctrans_l(const char *s, locale_t l)
+{
+ return wctrans(s);
+}
diff --git a/system/lib/libc/musl/src/locale/wctype_l.c b/system/lib/libc/musl/src/locale/wctype_l.c
new file mode 100644
index 00000000..601bab37
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/wctype_l.c
@@ -0,0 +1,9 @@
+#include <wctype.h>
+#include "libc.h"
+
+wctype_t wctype_l(const char *s, locale_t l)
+{
+ return wctype(s);
+}
+
+weak_alias(wctype_l, __wctype_l);
diff --git a/system/lib/libc/musl/src/stdio/fwprintf.c b/system/lib/libc/musl/src/stdio/fwprintf.c
new file mode 100644
index 00000000..9ce4f010
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/fwprintf.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int fwprintf(FILE *restrict f, const wchar_t *restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vfwprintf(f, fmt, ap);
+ va_end(ap);
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/stdio/swprintf.c b/system/lib/libc/musl/src/stdio/swprintf.c
new file mode 100644
index 00000000..cbf83d23
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/swprintf.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int swprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vswprintf(s, n, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
diff --git a/system/lib/libc/musl/src/stdio/vfwprintf.c b/system/lib/libc/musl/src/stdio/vfwprintf.c
new file mode 100644
index 00000000..eb079312
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vfwprintf.c
@@ -0,0 +1,361 @@
+#include "stdio_impl.h"
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <inttypes.h>
+
+/* Convenient bit representation for modifier flags, which all fall
+ * within 31 codepoints of the space character. */
+
+#define ALT_FORM (1U<<'#'-' ')
+#define ZERO_PAD (1U<<'0'-' ')
+#define LEFT_ADJ (1U<<'-'-' ')
+#define PAD_POS (1U<<' '-' ')
+#define MARK_POS (1U<<'+'-' ')
+#define GROUPED (1U<<'\''-' ')
+
+#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
+
+#if UINT_MAX == ULONG_MAX
+#define LONG_IS_INT
+#endif
+
+#if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX
+#define ODD_TYPES
+#endif
+
+/* State machine to accept length modifiers + conversion specifiers.
+ * Result is 0 on failure, or an argument type to pop on success. */
+
+enum {
+ BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
+ ZTPRE, JPRE,
+ STOP,
+ PTR, INT, UINT, ULLONG,
+#ifndef LONG_IS_INT
+ LONG, ULONG,
+#else
+#define LONG INT
+#define ULONG UINT
+#endif
+ SHORT, USHORT, CHAR, UCHAR,
+#ifdef ODD_TYPES
+ LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
+#else
+#define LLONG ULLONG
+#define SIZET ULONG
+#define IMAX LLONG
+#define UMAX ULLONG
+#define PDIFF LONG
+#define UIPTR ULONG
+#endif
+ DBL, LDBL,
+ NOARG,
+ MAXSTATE
+};
+
+#define S(x) [(x)-'A']
+
+static const unsigned char states[]['z'-'A'+1] = {
+ { /* 0: bare types */
+ S('d') = INT, S('i') = INT,
+ S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
+ S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
+ S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
+ S('c') = CHAR, S('C') = INT,
+ S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
+ S('m') = NOARG,
+ S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
+ }, { /* 1: l-prefixed */
+ S('d') = LONG, S('i') = LONG,
+ S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
+ S('c') = INT, S('s') = PTR, S('n') = PTR,
+ S('l') = LLPRE,
+ }, { /* 2: ll-prefixed */
+ S('d') = LLONG, S('i') = LLONG,
+ S('o') = ULLONG, S('u') = ULLONG,
+ S('x') = ULLONG, S('X') = ULLONG,
+ S('n') = PTR,
+ }, { /* 3: h-prefixed */
+ S('d') = SHORT, S('i') = SHORT,
+ S('o') = USHORT, S('u') = USHORT,
+ S('x') = USHORT, S('X') = USHORT,
+ S('n') = PTR,
+ S('h') = HHPRE,
+ }, { /* 4: hh-prefixed */
+ S('d') = CHAR, S('i') = CHAR,
+ S('o') = UCHAR, S('u') = UCHAR,
+ S('x') = UCHAR, S('X') = UCHAR,
+ S('n') = PTR,
+ }, { /* 5: L-prefixed */
+ S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
+ S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
+ S('n') = PTR,
+ }, { /* 6: z- or t-prefixed (assumed to be same size) */
+ S('d') = PDIFF, S('i') = PDIFF,
+ S('o') = SIZET, S('u') = SIZET,
+ S('x') = SIZET, S('X') = SIZET,
+ S('n') = PTR,
+ }, { /* 7: j-prefixed */
+ S('d') = IMAX, S('i') = IMAX,
+ S('o') = UMAX, S('u') = UMAX,
+ S('x') = UMAX, S('X') = UMAX,
+ S('n') = PTR,
+ }
+};
+
+#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
+
+union arg
+{
+ uintmax_t i;
+ long double f;
+ void *p;
+};
+
+static void pop_arg(union arg *arg, int type, va_list *ap)
+{
+ /* Give the compiler a hint for optimizing the switch. */
+ if ((unsigned)type > MAXSTATE) return;
+ switch (type) {
+ case PTR: arg->p = va_arg(*ap, void *);
+ break; case INT: arg->i = va_arg(*ap, int);
+ break; case UINT: arg->i = va_arg(*ap, unsigned int);
+#ifndef LONG_IS_INT
+ break; case LONG: arg->i = va_arg(*ap, long);
+ break; case ULONG: arg->i = va_arg(*ap, unsigned long);
+#endif
+ break; case ULLONG: arg->i = va_arg(*ap, unsigned long long);
+ break; case SHORT: arg->i = (short)va_arg(*ap, int);
+ break; case USHORT: arg->i = (unsigned short)va_arg(*ap, int);
+ break; case CHAR: arg->i = (signed char)va_arg(*ap, int);
+ break; case UCHAR: arg->i = (unsigned char)va_arg(*ap, int);
+#ifdef ODD_TYPES
+ break; case LLONG: arg->i = va_arg(*ap, long long);
+ break; case SIZET: arg->i = va_arg(*ap, size_t);
+ break; case IMAX: arg->i = va_arg(*ap, intmax_t);
+ break; case UMAX: arg->i = va_arg(*ap, uintmax_t);
+ break; case PDIFF: arg->i = va_arg(*ap, ptrdiff_t);
+ break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *);
+#endif
+ break; case DBL: arg->f = va_arg(*ap, double);
+ break; case LDBL: arg->f = va_arg(*ap, long double);
+ }
+}
+
+static void out(FILE *f, const wchar_t *s, size_t l)
+{
+ while (l--) fputwc(*s++, f);
+}
+
+static int getint(wchar_t **s) {
+ int i;
+ for (i=0; iswdigit(**s); (*s)++)
+ i = 10*i + (**s-'0');
+ return i;
+}
+
+static const char sizeprefix['y'-'a'] = {
+['a'-'a']='L', ['e'-'a']='L', ['f'-'a']='L', ['g'-'a']='L',
+['d'-'a']='j', ['i'-'a']='j', ['o'-'a']='j', ['u'-'a']='j', ['x'-'a']='j',
+['p'-'a']='j'
+};
+
+static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
+{
+ wchar_t *a, *z, *s=(wchar_t *)fmt, *s0;
+ unsigned l10n=0, litpct, fl;
+ int w, p;
+ union arg arg;
+ int argpos;
+ unsigned st, ps;
+ int cnt=0, l=0;
+ int i;
+ int t;
+ char *bs;
+ char charfmt[16];
+ wchar_t wc;
+
+ for (;;) {
+ /* Update output count, end loop when fmt is exhausted */
+ if (cnt >= 0) {
+ if (l > INT_MAX - cnt) {
+ if (!ferror(f)) errno = EOVERFLOW;
+ cnt = -1;
+ } else cnt += l;
+ }
+ if (!*s) break;
+
+ /* Handle literal text and %% format specifiers */
+ for (a=s; *s && *s!='%'; s++);
+ litpct = wcsspn(s, L"%")/2; /* Optimize %%%% runs */
+ z = s+litpct;
+ s += 2*litpct;
+ l = z-a;
+ if (f) out(f, a, l);
+ if (l) continue;
+
+ if (iswdigit(s[1]) && s[2]=='$') {
+ l10n=1;
+ argpos = s[1]-'0';
+ s+=3;
+ } else {
+ argpos = -1;
+ s++;
+ }
+
+ /* Read modifier flags */
+ for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
+ fl |= 1U<<*s-' ';
+
+ /* Read field width */
+ if (*s=='*') {
+ if (iswdigit(s[1]) && s[2]=='$') {
+ l10n=1;
+ nl_type[s[1]-'0'] = INT;
+ w = nl_arg[s[1]-'0'].i;
+ s+=3;
+ } else if (!l10n) {
+ w = f ? va_arg(*ap, int) : 0;
+ s++;
+ } else return -1;
+ if (w<0) fl|=LEFT_ADJ, w=-w;
+ } else if ((w=getint(&s))<0) return -1;
+
+ /* Read precision */
+ if (*s=='.' && s[1]=='*') {
+ if (isdigit(s[2]) && s[3]=='$') {
+ nl_type[s[2]-'0'] = INT;
+ p = nl_arg[s[2]-'0'].i;
+ s+=4;
+ } else if (!l10n) {
+ p = f ? va_arg(*ap, int) : 0;
+ s+=2;
+ } else return -1;
+ } else if (*s=='.') {
+ s++;
+ p = getint(&s);
+ } else p = -1;
+
+ /* Format specifier state machine */
+ s0=s;
+ st=0;
+ do {
+ if (OOB(*s)) return -1;
+ ps=st;
+ st=states[st]S(*s++);
+ } while (st-1<STOP);
+ if (!st) return -1;
+
+ /* Check validity of argument type (nl/normal) */
+ if (st==NOARG) {
+ if (argpos>=0) return -1;
+ else if (!f) continue;
+ } else {
+ if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
+ else if (f) pop_arg(&arg, st, ap);
+ else return 0;
+ }
+
+ if (!f) continue;
+ t = s[-1];
+ if (ps && (t&15)==3) t&=~32;
+
+ switch (t) {
+ case 'n':
+ switch(ps) {
+ case BARE: *(int *)arg.p = cnt; break;
+ case LPRE: *(long *)arg.p = cnt; break;
+ case LLPRE: *(long long *)arg.p = cnt; break;
+ case HPRE: *(unsigned short *)arg.p = cnt; break;
+ case HHPRE: *(unsigned char *)arg.p = cnt; break;
+ case ZTPRE: *(size_t *)arg.p = cnt; break;
+ case JPRE: *(uintmax_t *)arg.p = cnt; break;
+ }
+ continue;
+ case 'c':
+ fputwc(btowc(arg.i), f);
+ l = 1;
+ continue;
+ case 'C':
+ fputwc(arg.i, f);
+ l = 1;
+ continue;
+ case 'S':
+ a = arg.p;
+ z = wmemchr(a, 0, p);
+ if (!z) z=a+p;
+ else p=z-a;
+ if (w<p) w=p;
+ if (!(fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, "");
+ out(f, a, p);
+ if ((fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, "");
+ l=w;
+ continue;
+ case 's':
+ bs = arg.p;
+ if (p<0) p = INT_MAX;
+ for (i=l=0; l<p && (i=mbtowc(&wc, bs, MB_LEN_MAX))>0; bs+=i, l++);
+ if (i<0) return -1;
+ p=l;
+ if (w<p) w=p;
+ if (!(fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, "");
+ bs = arg.p;
+ while (l--) {
+ i=mbtowc(&wc, bs, MB_LEN_MAX);
+ bs+=i;
+ fputwc(wc, f);
+ }
+ if ((fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, "");
+ l=w;
+ continue;
+ }
+
+ snprintf(charfmt, sizeof charfmt, "%%%s%s%s%s%s*.*%c%c",
+ "#"+!(fl & ALT_FORM),
+ "+"+!(fl & MARK_POS),
+ "-"+!(fl & LEFT_ADJ),
+ " "+!(fl & PAD_POS),
+ "0"+!(fl & ZERO_PAD),
+ sizeprefix[(t|32)-'a'], t);
+
+ switch (t|32) {
+ case 'a': case 'e': case 'f': case 'g':
+ l = fprintf(f, charfmt, w, p, arg.f);
+ break;
+ case 'd': case 'i': case 'o': case 'u': case 'x': case 'p':
+ l = fprintf(f, charfmt, w, p, arg.i);
+ break;
+ }
+ }
+
+ if (f) return cnt;
+ if (!l10n) return 0;
+
+ for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
+ pop_arg(nl_arg+i, nl_type[i], ap);
+ for (; i<=NL_ARGMAX && !nl_type[i]; i++);
+ if (i<=NL_ARGMAX) return -1;
+ return 1;
+}
+
+int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
+{
+ va_list ap2;
+ int nl_type[NL_ARGMAX] = {0};
+ union arg nl_arg[NL_ARGMAX];
+ int ret;
+
+ va_copy(ap2, ap);
+ if (wprintf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) return -1;
+
+ FLOCK(f);
+ ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type);
+ FUNLOCK(f);
+ va_end(ap2);
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/stdio/vswprintf.c b/system/lib/libc/musl/src/stdio/vswprintf.c
new file mode 100644
index 00000000..7d237bae
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vswprintf.c
@@ -0,0 +1,53 @@
+#include "stdio_impl.h"
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <wchar.h>
+
+struct cookie {
+ wchar_t *ws;
+ size_t l;
+};
+
+static size_t sw_write(FILE *f, const unsigned char *s, size_t l)
+{
+ size_t l0 = l;
+ int i = 0;
+ struct cookie *c = f->cookie;
+ if (s!=f->wbase && sw_write(f, f->wbase, f->wpos-f->wbase)==-1)
+ return -1;
+ while (c->l && l && (i=mbtowc(c->ws, (void *)s, l))>=0) {
+ s+=i;
+ l-=i;
+ c->l--;
+ c->ws++;
+ }
+ *c->ws = 0;
+ return i<0 ? i : l0;
+}
+
+int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_list ap)
+{
+ int r;
+ FILE f;
+ unsigned char buf[256];
+ struct cookie c = { s, n-1 };
+
+ memset(&f, 0, sizeof(FILE));
+ f.lbf = EOF;
+ f.write = sw_write;
+ f.buf_size = sizeof buf;
+ f.buf = buf;
+ f.lock = -1;
+ f.cookie = &c;
+ if (!n) {
+ return -1;
+ } else if (n > INT_MAX) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ r = vfwprintf(&f, fmt, ap);
+ sw_write(&f, 0, 0);
+ return r>=n ? -1 : r;
+}
diff --git a/system/lib/libc/musl/src/stdio/vwprintf.c b/system/lib/libc/musl/src/stdio/vwprintf.c
new file mode 100644
index 00000000..eeeecdc7
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vwprintf.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <wchar.h>
+
+int vwprintf(const wchar_t *restrict fmt, va_list ap)
+{
+ return vfwprintf(stdout, fmt, ap);
+}
diff --git a/system/lib/libc/musl/src/stdio/wprintf.c b/system/lib/libc/musl/src/stdio/wprintf.c
new file mode 100644
index 00000000..342cd979
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/wprintf.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int wprintf(const wchar_t *restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vwprintf(fmt, ap);
+ va_end(ap);
+ return ret;
+}
diff --git a/system/lib/libcextra.symbols b/system/lib/libcextra.symbols
index a365271d..522137c6 100644
--- a/system/lib/libcextra.symbols
+++ b/system/lib/libcextra.symbols
@@ -1,20 +1,44 @@
+ W __iswctype_l
+ T __strxfrm_l
+ W __towlower_l
+ W __towupper_l
+ T __wcscoll_l
+ T __wcsxfrm_l
+ W __wctype_l
T btowc
T ecvt
T fcvt
+ T fwprintf
T gcvt
+ T iconv
+ T iconv_close
+ T iconv_open
T iswalnum
+ T iswalnum_l
T iswalpha
+ T iswalpha_l
T iswblank
+ T iswblank_l
T iswcntrl
+ T iswcntrl_l
T iswctype
+ T iswctype_l
T iswdigit
+ T iswdigit_l
T iswgraph
+ T iswgraph_l
T iswlower
+ T iswlower_l
T iswprint
+ T iswprint_l
T iswpunct
+ T iswpunct_l
T iswspace
+ T iswspace_l
T iswupper
+ T iswupper_l
T iswxdigit
+ T iswxdigit_l
T mblen
T mbrlen
T mbrtowc
@@ -23,21 +47,36 @@
T mbsrtowcs
T mbstowcs
T mbtowc
+ T strfmon
+ T strfmon_l
+ T strxfrm
+ W strxfrm_l
+ T swprintf
T towctrans
+ T towctrans_l
T towlower
+ T towlower_l
T towupper
+ T towupper_l
+ T vfwprintf
+ T vswprintf
+ T vwprintf
T wcpcpy
T wcpncpy
T wcrtomb
T wcscasecmp
+ T wcscasecmp_l
T wcscat
T wcschr
T wcscmp
+ T wcscoll
+ T wcscoll_l
T wcscpy
T wcscspn
T wcsdup
T wcslen
T wcsncasecmp
+ T wcsncasecmp_l
T wcsncat
T wcsncmp
T wcsncpy
@@ -52,13 +91,18 @@
T wcstombs
T wcswcs
T wcswidth
+ T wcsxfrm
+ T wcsxfrm_l
T wctob
T wctomb
T wctrans
+ T wctrans_l
T wctype
+ T wctype_l
T wcwidth
T wmemchr
T wmemcmp
T wmemcpy
T wmemmove
T wmemset
+ T wprintf
diff --git a/tests/cases/atomicrmw_unaligned.emcc b/tests/cases/atomicrmw_unaligned.emcc
new file mode 100644
index 00000000..9faeda24
--- /dev/null
+++ b/tests/cases/atomicrmw_unaligned.emcc
@@ -0,0 +1 @@
+["-s", "UNALIGNED_MEMORY=1"]
diff --git a/tests/cases/atomicrmw_unaligned.ll b/tests/cases/atomicrmw_unaligned.ll
new file mode 100644
index 00000000..fe479dce
--- /dev/null
+++ b/tests/cases/atomicrmw_unaligned.ll
@@ -0,0 +1,21 @@
+; 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 [15 x i8] c"hello, %d,%d!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %t = alloca i32, align 4 ; [#uses=2 type=i32**]
+ store i32 50, i32* %t, align 4
+ %0 = load i32* %t
+ %1 = atomicrmw add i32* %t, i32 3 seq_cst, ; [#uses=0 type=i32] [debug line = 21:12]
+ %2 = load i32* %t
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i32 %0, i32 %2) ; [#uses=0 type=i32]
+ %3 = atomicrmw volatile add i32* %t, i32 3 seq_cst, ; [#uses=0 type=i32] [debug line = 21:12]
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/atomicrmw_unaligned.txt b/tests/cases/atomicrmw_unaligned.txt
new file mode 100644
index 00000000..45d16fb1
--- /dev/null
+++ b/tests/cases/atomicrmw_unaligned.txt
@@ -0,0 +1 @@
+hello, 50,53!
diff --git a/tests/cmake/target_js/CMakeLists.txt b/tests/cmake/target_js/CMakeLists.txt
index cee5fc42..244cc70a 100644
--- a/tests/cmake/target_js/CMakeLists.txt
+++ b/tests/cmake/target_js/CMakeLists.txt
@@ -1,11 +1,15 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world)
+project(test_cmake)
-file(GLOB sourceFiles ../../hello_world.cpp)
+file(GLOB sourceFiles main.cpp)
+
+file(GLOB preJsFiles pre*.js)
+file(GLOB postJsFiles post*.js)
+file(GLOB libraryJsFiles jslibrary*.js)
if (CMAKE_BUILD_TYPE STREQUAL Debug)
- SET(linkFlags "")
+ SET(linkFlags "-g4")
else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimizations enabled.
SET(linkFlags "-O2")
endif()
@@ -28,5 +32,17 @@ if (NOT CMAKE_C_SIZEOF_DATA_PTR)
message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!")
endif()
-add_executable(hello_world ${sourceFiles})
-set_target_properties(hello_world PROPERTIES LINK_FLAGS "${linkFlags}")
+add_executable(test_cmake ${sourceFiles})
+
+# GOTCHA: If your project has custom link flags, these must be set *before* calling any of the em_link_xxx functions!
+set_target_properties(test_cmake PROPERTIES LINK_FLAGS "${linkFlags}")
+
+message(STATUS "js libs '${libraryJsFiles}'")
+# To link .js files using the --js-library flag, use the following helper function.
+em_link_js_library(test_cmake ${libraryJsFiles})
+
+# To link .js files using the --pre-js flag, use the following helper function.
+em_link_pre_js(test_cmake ${preJsFiles})
+
+# To link .js files using the --post-js flag, use the following helper function.
+em_link_post_js(test_cmake ${postJsFiles})
diff --git a/tests/cmake/target_js/jslibrary.js b/tests/cmake/target_js/jslibrary.js
new file mode 100644
index 00000000..63375d8f
--- /dev/null
+++ b/tests/cmake/target_js/jslibrary.js
@@ -0,0 +1,7 @@
+var mylib = {};
+
+mylib.lib_function = function() {
+ console.log('lib_function');
+}
+
+mergeInto(LibraryManager.library, mylib);
diff --git a/tests/cmake/target_js/jslibrary2.js b/tests/cmake/target_js/jslibrary2.js
new file mode 100644
index 00000000..5d322e2d
--- /dev/null
+++ b/tests/cmake/target_js/jslibrary2.js
@@ -0,0 +1,7 @@
+var mylib = {};
+
+mylib.lib_function2 = function() {
+ console.log('lib_function2');
+}
+
+mergeInto(LibraryManager.library, mylib);
diff --git a/tests/cmake/target_js/main.cpp b/tests/cmake/target_js/main.cpp
new file mode 100644
index 00000000..4b61dbf7
--- /dev/null
+++ b/tests/cmake/target_js/main.cpp
@@ -0,0 +1,10 @@
+extern "C" {
+ void lib_function();
+ void lib_function2();
+}
+
+int main()
+{
+ lib_function();
+ lib_function2();
+}
diff --git a/tests/cmake/target_js/out.txt b/tests/cmake/target_js/out.txt
new file mode 100644
index 00000000..76135df7
--- /dev/null
+++ b/tests/cmake/target_js/out.txt
@@ -0,0 +1,4 @@
+prejs executed
+lib_function
+lib_function2
+postjs executed \ No newline at end of file
diff --git a/tests/cmake/target_js/postjs.js b/tests/cmake/target_js/postjs.js
new file mode 100644
index 00000000..5a1b44ce
--- /dev/null
+++ b/tests/cmake/target_js/postjs.js
@@ -0,0 +1 @@
+console.log('postjs executed');
diff --git a/tests/cmake/target_js/prejs.js b/tests/cmake/target_js/prejs.js
new file mode 100644
index 00000000..87beb770
--- /dev/null
+++ b/tests/cmake/target_js/prejs.js
@@ -0,0 +1 @@
+console.log('prejs executed');
diff --git a/tests/fs/test_idbfs_sync.c b/tests/fs/test_idbfs_sync.c
new file mode 100644
index 00000000..ff356416
--- /dev/null
+++ b/tests/fs/test_idbfs_sync.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <emscripten.h>
+
+#define EM_ASM_REEXPAND(x) EM_ASM(x)
+
+void success() {
+ int result = 1;
+ REPORT_RESULT();
+}
+
+int main() {
+ EM_ASM(
+ FS.mkdir('/working');
+ FS.mount(IDBFS, {}, '/working');
+ );
+
+#if FIRST
+ // store local files to backing IDB
+ EM_ASM_REEXPAND(
+ FS.writeFile('/working/waka.txt', 'az');
+ FS.writeFile('/working/moar.txt', SECRET);
+ FS.syncfs(function (err) {
+ assert(!err);
+
+ ccall('success', 'v', '', []);
+ });
+ );
+#else
+ // load files from backing IDB
+ EM_ASM_REEXPAND(
+ FS.syncfs(true, function (err) {
+ assert(!err);
+
+ var contents = FS.readFile('/working/waka.txt', { encoding: 'utf8' });
+ assert(contents === 'az');
+
+ var secret = FS.readFile('/working/moar.txt', { encoding: 'utf8' });
+ assert(secret === SECRET);
+
+ ccall('success', 'v', '', []);
+ });
+ );
+#endif
+
+ emscripten_exit_with_live_runtime();
+
+ return 0;
+}
diff --git a/tests/fs/test_nodefs_rw.c b/tests/fs/test_nodefs_rw.c
new file mode 100644
index 00000000..140da332
--- /dev/null
+++ b/tests/fs/test_nodefs_rw.c
@@ -0,0 +1,49 @@
+#include <assert.h>
+#include <stdio.h>
+#include <emscripten.h>
+
+int main() {
+ FILE *file;
+ int res;
+ char buffer[512];
+
+ // write something locally with node
+ EM_ASM(
+ var fs = require('fs');
+ fs.writeFileSync('foobar.txt', 'yeehaw');
+ );
+
+ // mount the current folder as a NODEFS instance
+ // inside of emscripten
+ EM_ASM(
+ FS.mkdir('/working');
+ FS.mount(NODEFS, { root: '.' }, '/working');
+ );
+
+ // read and validate the contents of the file
+ file = fopen("/working/foobar.txt", "r");
+ assert(file);
+ res = fread(buffer, sizeof(char), 6, file);
+ assert(res == 6);
+ fclose(file);
+
+ assert(!strcmp(buffer, "yeehaw"));
+
+ // write out something new
+ file = fopen("/working/foobar.txt", "w");
+ assert(file);
+ res = fwrite("cheez", sizeof(char), 5, file);
+ assert(res == 5);
+ fclose(file);
+
+ // validate the changes were persisted to the underlying fs
+ EM_ASM(
+ var fs = require('fs');
+ var contents = fs.readFileSync('foobar.txt', { encoding: 'utf8' });
+ assert(contents === 'cheez');
+ );
+
+ puts("success");
+
+ return 0;
+}
diff --git a/tests/printf/output.txt b/tests/printf/output.txt
index 19a6c1c2..0155f0da 100644
--- a/tests/printf/output.txt
+++ b/tests/printf/output.txt
@@ -3,10 +3,15 @@ n=7
Characters: a A
Decimals: 1977 650000 12 4
-Preceding with blanks: 1977
-Preceding with zeros: 0000001977
+Preceding with blanks: 1977 -1977
+Preceding with zeros: 0000001977 -000001977
+Force sign: +1977 -1977 +1977 -1977
+Force sign or space: 1977 -1977 1977 -1977
+Sign overrides space: +1977 -1977 +1977 -1977
Some different radixes: 100 64 144 0x64 0144
-floats: 3.14 +3e+00 3.141600E+00
+floats: 3.14 +3e+00 3.141600E+00 00003.14
+negative floats: -3.14 -3e+00 -3.141600E+00 -0003.14
+Force sign or space: 3.14 -3.14 3.14 -3.14
Width trick: 10
A string %
Null string: (null)
diff --git a/tests/printf/output_i64_1.txt b/tests/printf/output_i64_1.txt
index 775f3f8d..e38fb78f 100644
--- a/tests/printf/output_i64_1.txt
+++ b/tests/printf/output_i64_1.txt
@@ -3,10 +3,15 @@ n=7
Characters: a A
Decimals: 1977 650000 12 4
-Preceding with blanks: 1977
-Preceding with zeros: 0000001977
+Preceding with blanks: 1977 -1977
+Preceding with zeros: 0000001977 -000001977
+Force sign: +1977 -1977 +1977 -1977
+Force sign or space: 1977 -1977 1977 -1977
+Sign overrides space: +1977 -1977 +1977 -1977
Some different radixes: 100 64 144 0x64 0144
-floats: 3.14 +3e+00 3.141600E+00
+floats: 3.14 +3e+00 3.141600E+00 00003.14
+negative floats: -3.14 -3e+00 -3.141600E+00 -0003.14
+Force sign or space: 3.14 -3.14 3.14 -3.14
Width trick: 10
A string %
Null string: (null)
diff --git a/tests/printf/test.c b/tests/printf/test.c
index d05ba096..1c8ad9f7 100644
--- a/tests/printf/test.c
+++ b/tests/printf/test.c
@@ -8,10 +8,15 @@ int main() {
printf("\n");
printf("Characters: %c %c\n", 'a', 65);
printf("Decimals: %d %ld %lld %d\n", 1977, 650000L, 12LL, 4);
- printf("Preceding with blanks: %10d\n", 1977);
- printf("Preceding with zeros: %010d\n", 1977);
+ printf("Preceding with blanks: %10d %10d\n", 1977, -1977);
+ printf("Preceding with zeros: %010d %010d\n", 1977, -1977);
+ printf("Force sign: %+d %+d %+6d %+6d\n", 1977, -1977, 1977, -1977);
+ printf("Force sign or space: % d % d % 6d % 6d\n", 1977, -1977, 1977, -1977);
+ printf("Sign overrides space: % +d % +d % +6d % +6d\n", 1977, -1977, 1977, -1977);
printf("Some different radixes: %d %x %o %#x %#o\n", 100, 100, 100, 100, 100);
- printf("floats: %4.2f %+.0e %E\n", 3.1416, 3.1416, 3.1416);
+ printf("floats: %4.2f %+.0e %E %08.2f\n", 3.1416, 3.1416, 3.1416, 3.1416);
+ printf("negative floats: %4.2f %+.0e %E %08.2f\n", -3.1416, -3.1416, -3.1416, -3.1416);
+ printf("Force sign or space: % .2f % .2f % 6.2f % 6.2f\n", 3.1416, -3.1416, 3.1416, -3.1416);
printf("Width trick: %*d\n", 5, 10);
printf("%s %%\n", "A string");
printf("Null string: %7s\n", NULL);
diff --git a/tests/sdl_audio_beep.cpp b/tests/sdl_audio_beep.cpp
new file mode 100644
index 00000000..95a5a7e8
--- /dev/null
+++ b/tests/sdl_audio_beep.cpp
@@ -0,0 +1,246 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_audio.h>
+#include <queue>
+#include <cmath>
+#include <stdio.h>
+#include <assert.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846f
+#endif
+
+#ifdef EMSCRIPTEN
+#include "emscripten/emscripten.h"
+#endif
+
+#ifdef main
+#undef main
+#endif
+
+const int tone_duration = 1000;
+
+struct BeepObject {
+ double toneFrequency;
+ int samplesLeft;
+};
+
+class Beeper {
+private:
+ double phase;
+ int frequency;
+ int numChannels;
+ int mutedChannel;
+public:
+ Beeper(int frequency, int numChannels, int sdlAudioFormat);
+ ~Beeper();
+ void beep(double toneFrequency, int durationMSecs);
+ template<typename T>
+ void generateSamples(T *stream, int length);
+ void wait();
+
+ std::queue<BeepObject> beeps;
+ int sdlAudioFormat;
+};
+
+void audio_callback(void*, Uint8*, int);
+
+Beeper::Beeper(int frequency_, int numChannels_, int sdlAudioFormat_) {
+ phase = 0.0;
+ mutedChannel = 1;
+
+ SDL_AudioSpec desiredSpec;
+
+ desiredSpec.freq = frequency_;
+ desiredSpec.format = sdlAudioFormat_;
+ desiredSpec.channels = numChannels_;
+ desiredSpec.samples = 1024; // This is samples per channel.
+ desiredSpec.callback = audio_callback;
+ desiredSpec.userdata = this;
+
+ SDL_AudioSpec obtainedSpec;
+
+ // you might want to look for errors here
+ SDL_OpenAudio(&desiredSpec, &obtainedSpec);
+
+ // In this test, we require *exactly* the identical SDL result that we provide, since we test
+ // all various configurations individually.
+ if (obtainedSpec.freq != desiredSpec.freq || obtainedSpec.format != desiredSpec.format
+ || obtainedSpec.channels != desiredSpec.channels || obtainedSpec.samples != desiredSpec.samples) {
+ SDL_CloseAudio();
+ throw std::runtime_error("Failed to initialize desired SDL_OpenAudio!");
+ }
+
+ frequency = obtainedSpec.freq;
+ numChannels = obtainedSpec.channels;
+ sdlAudioFormat = obtainedSpec.format;
+
+ // Immediately start producing audio.
+ SDL_PauseAudio(0);
+}
+
+Beeper::~Beeper() {
+ SDL_CloseAudio();
+}
+
+template<typename T>
+void Beeper::generateSamples(T *stream, int length) {
+ const int AMPLITUDE = (sizeof(T) == 2) ? 28000 : 120;
+ const int offset = (sdlAudioFormat == AUDIO_U8) ? 120 : 0;
+
+ int i = 0;
+ length /= numChannels;
+ while (i < length) {
+ if (beeps.empty()) {
+ memset(stream + numChannels*i, 0, sizeof(T)*numChannels*(length-i));
+ return;
+ }
+ BeepObject& bo = beeps.front();
+
+ // In Stereo tests, mute one of the channels to be able to distinguish that Stereo output works.
+ if (bo.samplesLeft > tone_duration * frequency / 2 / 1000) {
+ mutedChannel = 1;
+ } else {
+ mutedChannel = 0;
+ }
+
+ int samplesToDo = std::min(i + bo.samplesLeft, length);
+ bo.samplesLeft -= samplesToDo - i;
+
+ while (i < samplesToDo) {
+ for(int j = 0; j < numChannels; ++j) {
+ stream[numChannels*i+j] = (T)(offset + (int)(AMPLITUDE * std::sin(phase * 2 * M_PI / frequency)));
+ if (numChannels > 1 && j == mutedChannel) {
+ stream[numChannels*i+j] = 0;
+ }
+ }
+ phase += bo.toneFrequency;
+ i++;
+ }
+
+ if (bo.samplesLeft == 0) {
+ beeps.pop();
+ }
+ }
+}
+
+void Beeper::beep(double toneFrequency, int durationMSecs) {
+ BeepObject bo;
+ bo.toneFrequency = toneFrequency;
+ bo.samplesLeft = durationMSecs * frequency / 1000;
+
+ SDL_LockAudio();
+ beeps.push(bo);
+ SDL_UnlockAudio();
+}
+
+Beeper *beep = 0;
+
+// Test all kinds of various possible formats. Not all are supported, but running this
+// test will report you which work.
+const int freqs[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 96000 };
+const int channels[] = { 1, 2 };
+const int sdlAudioFormats[] = { AUDIO_U8, AUDIO_S16LSB /*, AUDIO_S8, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16MSB */ };
+
+const char *SdlAudioFormatToString(int sdlAudioType) {
+ switch(sdlAudioType) {
+ case AUDIO_U8: return "AUDIO_U8";
+ case AUDIO_S8: return "AUDIO_S8";
+ case AUDIO_U16LSB: return "AUDIO_U16LSB";
+ case AUDIO_U16MSB: return "AUDIO_U16MSB";
+ case AUDIO_S16LSB: return "AUDIO_S16LSB";
+ case AUDIO_S16MSB: return "AUDIO_S16MSB";
+ default: return "(unknown)";
+ }
+}
+
+#define NUM_ELEMS(x) (sizeof(x)/sizeof((x)[0]))
+
+// Indices to the currently running test.
+int f = -1;
+int c = 0;
+int s = 0;
+
+void nextTest(void *unused = 0) {
+ ++f;
+ if (f >= NUM_ELEMS(freqs)) {
+ f = 0;
+ ++c;
+ if (c >= NUM_ELEMS(channels)) {
+ c = 0;
+ ++s;
+ if (s >= NUM_ELEMS(sdlAudioFormats)) {
+ printf("All tests done. Quit.\n");
+#ifdef EMSCRIPTEN
+ emscripten_cancel_main_loop();
+#ifdef REPORT_RESULT
+ int result = 1;
+ REPORT_RESULT();
+#endif
+#endif
+ return;
+ }
+ }
+ }
+
+ double Hz = 440;
+ try {
+ beep = new Beeper(freqs[f], channels[c], sdlAudioFormats[s]);
+ } catch(...) {
+ printf("FAILED to play beep for %d msecs at %d Hz tone with audio format %s, %d channels, and %d samples/sec.\n",
+ tone_duration, (int)Hz, SdlAudioFormatToString(sdlAudioFormats[s]), channels[c], freqs[f]);
+ nextTest();
+ return;
+ }
+
+ printf("Playing back a beep for %d msecs at %d Hz tone with audio format %s, %d channels, and %d samples/sec.\n",
+ tone_duration, (int)Hz, SdlAudioFormatToString(sdlAudioFormats[s]), channels[c], freqs[f]);
+ beep->beep(Hz, tone_duration);
+}
+
+void update() {
+ SDL_LockAudio();
+ int size = beep->beeps.size();
+ SDL_UnlockAudio();
+ if (size == 0 && beep) {
+ delete beep;
+ beep = 0;
+#ifdef EMSCRIPTEN
+ emscripten_async_call(nextTest, 0, 1500);
+#else
+ SDL_Delay(1500);
+ nextTest();
+#endif
+ }
+}
+
+void audio_callback(void *_beeper, Uint8 *_stream, int _length) {
+ Beeper* beeper = (Beeper*) _beeper;
+
+ if (beeper->sdlAudioFormat == AUDIO_U8) {
+ Uint8 *stream = (Uint8*) _stream;
+ beeper->generateSamples(stream, _length);
+ } else if (beeper->sdlAudioFormat == AUDIO_S16LSB) {
+ Sint16 *stream = (Sint16*) _stream;
+ int length = _length / 2;
+ beeper->generateSamples(stream, length);
+ } else {
+ assert(false && "Audio sample generation not implemented for current format!\n");
+ }
+}
+
+int main(int argc, char** argv) {
+ SDL_Init(SDL_INIT_AUDIO);
+
+ nextTest();
+
+#ifdef EMSCRIPTEN
+ emscripten_set_main_loop(update, 60, 0);
+#else
+ while(beep) {
+ SDL_Delay(20);
+ update();
+ }
+#endif
+
+ return 0;
+}
diff --git a/tests/sdl_canvas_alpha.c b/tests/sdl_canvas_alpha.c
new file mode 100644
index 00000000..1a41d115
--- /dev/null
+++ b/tests/sdl_canvas_alpha.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <emscripten.h>
+
+
+int main(int argc, char **argv) {
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ printf("Init: %d\n", TTF_Init());
+
+ TTF_Font *font = TTF_OpenFont("sans-serif", 40);
+ printf("Font: %p\n", font);
+
+ SDL_Color color = { 0xff, 0x99, 0x00, 0xff };
+ SDL_Surface *text = TTF_RenderText_Solid(font, "hello orange world", color);
+
+ // render
+ for (int i = 0; i < 255; i++) {
+ SDL_Rect dest = { i, i, 0, 0 };
+ SDL_SetAlpha(text, 0, (((float)i)/255)*(((float)i)/255)*255);
+ SDL_BlitSurface (text, NULL, screen, &dest);
+ }
+
+ SDL_Flip(screen);
+
+ SDL_LockSurface(screen);
+
+ int width, height, isFullscreen;
+ emscripten_get_canvas_size(&width, &height, &isFullscreen);
+
+ if (width != 600 && height != 450)
+ {
+ printf("error: wrong width/height\n");
+ abort();
+ }
+
+ SDL_Quit();
+
+ printf("done.\n");
+
+ return 0;
+}
+
diff --git a/tests/sdl_canvas_alpha.png b/tests/sdl_canvas_alpha.png
new file mode 100644
index 00000000..fb9d6165
--- /dev/null
+++ b/tests/sdl_canvas_alpha.png
Binary files differ
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 6a23b41c..799759a1 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -19,6 +19,7 @@ class browser(BrowserCore):
'test_sdl_audio_mix_channels',
'test_sdl_audio_mix',
'test_sdl_audio_quickload',
+ 'test_sdl_audio_beeps',
'test_openal_playback',
'test_openal_buffers',
'test_freealut'
@@ -649,6 +650,9 @@ window.close = function() {
self.btest('sdl_canvas_proxy.c', reference='sdl_canvas_proxy.png', args=['--proxy-to-worker', '--preload-file', 'data.txt'], manual_reference=True, post_build=post)
+ def test_sdl_canvas_alpha(self):
+ self.btest('sdl_canvas_alpha.c', reference='sdl_canvas_alpha.png', reference_slack=1)
+
def test_sdl_key(self):
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
Module.postRun = function() {
@@ -876,6 +880,11 @@ keydown(100);keyup(100); // trigger the end
self.btest('file_db.cpp', secret, args=['--preload-file', 'moar.txt']) # even with a file there, we load over it
shutil.move('test.html', 'third.html')
+ def test_fs_idbfs_sync(self):
+ secret = str(time.time())
+ self.btest(path_from_root('tests', 'fs', 'test_idbfs_sync.c'), '1', force_c=True, args=['-DFIRST', '-DSECRET=\'' + secret + '\'', '-s', '''EXPORTED_FUNCTIONS=['_main', '_success']'''])
+ self.btest(path_from_root('tests', 'fs', 'test_idbfs_sync.c'), '1', force_c=True, args=['-DSECRET=\'' + secret + '\'', '-s', '''EXPORTED_FUNCTIONS=['_main', '_success']'''])
+
def test_sdl_pumpevents(self):
# key events should be detected using SDL_PumpEvents
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
@@ -923,6 +932,13 @@ keydown(100);keyup(100); // trigger the end
Popen([PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_quickload.c'), '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play"]']).communicate()
self.run_browser('page.html', '', '/report_result?1')
+ def test_sdl_audio_beeps(self):
+ open(os.path.join(self.get_dir(), 'sdl_audio_beep.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_beep.cpp')).read()))
+
+ # use closure to check for a possible bug with closure minifying away newer Audio() attributes
+ Popen([PYTHON, EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_beep.cpp'), '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-o', 'page.html']).communicate()
+ self.run_browser('page.html', '', '/report_result?1')
+
def test_sdl_gl_read(self):
# SDL, OpenGL, readPixels
open(os.path.join(self.get_dir(), 'sdl_gl_read.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_gl_read.c')).read()))
@@ -1477,7 +1493,9 @@ keydown(100);keyup(100); // trigger the end
}, 2000);
};
''')
- self.btest('pre_run_deps.cpp', expected='10', args=['--pre-js', 'pre.js'])
+
+ for mem in [0, 1]:
+ self.btest('pre_run_deps.cpp', expected='10', args=['--pre-js', 'pre.js', '--memory-init-file', str(mem)])
def test_worker_api(self):
Popen([PYTHON, EMCC, path_from_root('tests', 'worker_api_worker.cpp'), '-o', 'worker.js', '-s', 'BUILD_AS_WORKER=1', '-s', 'EXPORTED_FUNCTIONS=["_one"]']).communicate()
diff --git a/tests/test_core.py b/tests/test_core.py
index dd3b7c44..f51c1691 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1372,6 +1372,50 @@ Succeeded!
'''
self.do_run(src, '*1,10,10.5,1,1.2340,0.00*\n0.50, 3.30, 3.30, 3.30\nsmall: 0.0000010000\n')
+ def test_zerodiv(self):
+ self.do_run(r'''
+ #include <stdio.h>
+ int main(int argc, const char* argv[])
+ {
+ float f1 = 1.0f;
+ float f2 = 0.0f;
+ float f_zero = 0.0f;
+
+ float f3 = 0.0f / f2;
+ float f4 = f2 / 0.0f;
+ float f5 = f2 / f2;
+ float f6 = f2 / f_zero;
+
+ printf("f3: %f\n", f3);
+ printf("f4: %f\n", f4);
+ printf("f5: %f\n", f5);
+ printf("f6: %f\n", f6);
+
+ return 0;
+ }
+ ''', '''f3: nan
+f4: nan
+f5: nan
+f6: nan
+''')
+
+ def test_zero_multiplication(self):
+ src = '''
+ #include <stdio.h>
+ int main(int argc, char * argv[]) {
+ int one = argc;
+
+ printf("%d ", 0 * one);
+ printf("%d ", 0 * -one);
+ printf("%d ", -one * 0);
+ printf("%g ", 0.0 * one);
+ printf("%g ", 0.0 * -one);
+ printf("%g", -one * 0.0);
+ return 0;
+ }
+ '''
+ self.do_run(src, '0 0 0 0 -0 -0')
+
def test_isnan(self):
src = r'''
#include <stdio.h>
@@ -1744,7 +1788,7 @@ Succeeded!
int xx, yy, zz;
char s[32];
- int cc = sscanf("abc_10.b1_xyz_543_defg", "abc_%d.%2x_xyz_%3d_%3s", &xx, &yy, &zz, s);
+ int cc = sscanf("abc_10.b1_xyz9_543_defg", "abc_%d.%2x_xyz9_%3d_%3s", &xx, &yy, &zz, s);
printf("%d:%d,%d,%d,%s\\n", cc, xx, yy, zz, s);
printf("%d\\n", argc);
@@ -5046,7 +5090,7 @@ The current type of b is: 9
src = r'''
int main () {
*(volatile char *)0 = 0;
- return 0;
+ return *(volatile char *)0;
}
'''
self.do_run(src, 'fault on write to 0' if not Settings.ASM_JS else 'abort()')
@@ -6908,6 +6952,29 @@ at function.:blag
printf("%i\n", a);
}
+ char buf1[100], buf2[100], buf3[100], buf4[100];
+
+ int numItems = sscanf("level=4:ref=3", "%255[^:=]=%255[^:]:%255[^=]=%255c", buf1, buf2, buf3, buf4);
+ printf("%d, %s, %s, %s, %s\n", numItems, buf1, buf2, buf3, buf4);
+
+ numItems = sscanf("def|456", "%[a-z]|%[0-9]", buf1, buf2);
+ printf("%d, %s, %s\n", numItems, buf1, buf2);
+
+ numItems = sscanf("3-4,-ab", "%[-0-9],%[ab-z-]", buf1, buf2);
+ printf("%d, %s, %s\n", numItems, buf1, buf2);
+
+ numItems = sscanf("Hello,World", "%[A-Za-z],%[^0-9]", buf1, buf2);
+ printf("%d, %s, %s\n", numItems, buf1, buf2);
+
+ numItems = sscanf("Hello4711", "%[^0-9],%[^0-9]", buf1, buf2);
+ printf("%d, %s\n", numItems, buf1);
+
+ numItems = sscanf("JavaScript", "%4[A-Za-z]", buf1);
+ printf("%d, %s\n", numItems, buf1);
+
+ numItems = sscanf("[]", "%1[[]%1[]]", buf1, buf2);
+ printf("%d, %s, %s\n", numItems, buf1, buf2);
+
return 0;
}
'''
@@ -6915,7 +6982,14 @@ at function.:blag
'1\n1499\n' +
'5\n87,0.481565,0.059481,0,1\n' +
'3\n-123,4294966531,-34\n' +
- '1\n')
+ '1\n' +
+ '4, level, 4, ref, 3\n' +
+ '2, def, 456\n' +
+ '2, 3-4, -ab\n' +
+ '2, Hello, World\n' +
+ '1, Hello\n' +
+ '1, Java\n' +
+ '2, [, ]')
def test_sscanf_2(self):
# doubles
@@ -7171,6 +7245,18 @@ date: 18.07.2013w; day 18, month 7, year 2013, extra: 201, 3
'''
self.do_run(src, '10 1.1 1.1 1.1');
+ def test_sscanf_hex(self):
+ src = r'''
+ #include "stdio.h"
+
+ int main(){
+ unsigned int a, b;
+ sscanf("0x12AB 12AB", "%x %x", &a, &b);
+ printf("%d %d\n", a, b);
+ }
+ '''
+ self.do_run(src, '4779 4779')
+
def test_langinfo(self):
src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read()
expected = open(path_from_root('tests', 'langinfo', 'output.txt'), 'r').read()
@@ -7656,12 +7742,18 @@ def process(filename):
finally:
Settings.INCLUDE_FULL_LIBRARY = 0
+ def test_fs_nodefs_rw(self):
+ src = open(path_from_root('tests', 'fs', 'test_nodefs_rw.c'), 'r').read()
+ self.do_run(src, 'success', force_c=True)
+
def test_unistd_access(self):
if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
if not self.is_le32(): return self.skip('le32 needed for inline js')
- src = open(path_from_root('tests', 'unistd', 'access.c'), 'r').read()
- expected = open(path_from_root('tests', 'unistd', 'access.out'), 'r').read()
- self.do_run(src, expected)
+ for fs in ['MEMFS', 'NODEFS']:
+ src = open(path_from_root('tests', 'unistd', 'access.c'), 'r').read()
+ expected = open(path_from_root('tests', 'unistd', 'access.out'), 'r').read()
+ Building.COMPILER_TEST_OPTS += ['-D' + fs]
+ self.do_run(src, expected)
def test_unistd_curdir(self):
if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
@@ -7697,9 +7789,11 @@ def process(filename):
def test_unistd_truncate(self):
if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
if not self.is_le32(): return self.skip('le32 needed for inline js')
- src = open(path_from_root('tests', 'unistd', 'truncate.c'), 'r').read()
- expected = open(path_from_root('tests', 'unistd', 'truncate.out'), 'r').read()
- self.do_run(src, expected)
+ for fs in ['MEMFS', 'NODEFS']:
+ src = open(path_from_root('tests', 'unistd', 'truncate.c'), 'r').read()
+ expected = open(path_from_root('tests', 'unistd', 'truncate.out'), 'r').read()
+ Building.COMPILER_TEST_OPTS += ['-D' + fs]
+ self.do_run(src, expected)
def test_unistd_swab(self):
src = open(path_from_root('tests', 'unistd', 'swab.c'), 'r').read()
@@ -7721,15 +7815,19 @@ def process(filename):
self.do_run(src, expected)
def test_unistd_unlink(self):
- src = open(path_from_root('tests', 'unistd', 'unlink.c'), 'r').read()
- self.do_run(src, 'success', force_c=True)
+ for fs in ['MEMFS', 'NODEFS']:
+ src = open(path_from_root('tests', 'unistd', 'unlink.c'), 'r').read()
+ Building.COMPILER_TEST_OPTS += ['-D' + fs]
+ self.do_run(src, 'success', force_c=True)
def test_unistd_links(self):
if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
if not self.is_le32(): return self.skip('le32 needed for inline js')
- src = open(path_from_root('tests', 'unistd', 'links.c'), 'r').read()
- expected = open(path_from_root('tests', 'unistd', 'links.out'), 'r').read()
- self.do_run(src, expected)
+ for fs in ['MEMFS', 'NODEFS']:
+ src = open(path_from_root('tests', 'unistd', 'links.c'), 'r').read()
+ expected = open(path_from_root('tests', 'unistd', 'links.out'), 'r').read()
+ Building.COMPILER_TEST_OPTS += ['-D' + fs]
+ self.do_run(src, expected)
def test_unistd_sleep(self):
src = open(path_from_root('tests', 'unistd', 'sleep.c'), 'r').read()
@@ -7740,14 +7838,18 @@ def process(filename):
if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
if not self.is_le32(): return self.skip('le32 needed for inline js')
if self.run_name == 'o2': return self.skip('non-asm optimized builds can fail with inline js')
- src = open(path_from_root('tests', 'unistd', 'io.c'), 'r').read()
- expected = open(path_from_root('tests', 'unistd', 'io.out'), 'r').read()
- self.do_run(src, expected)
+ for fs in ['MEMFS', 'NODEFS']:
+ src = open(path_from_root('tests', 'unistd', 'io.c'), 'r').read()
+ expected = open(path_from_root('tests', 'unistd', 'io.out'), 'r').read()
+ Building.COMPILER_TEST_OPTS += ['-D' + fs]
+ self.do_run(src, expected)
def test_unistd_misc(self):
- src = open(path_from_root('tests', 'unistd', 'misc.c'), 'r').read()
- expected = open(path_from_root('tests', 'unistd', 'misc.out'), 'r').read()
- self.do_run(src, expected)
+ for fs in ['MEMFS', 'NODEFS']:
+ src = open(path_from_root('tests', 'unistd', 'misc.c'), 'r').read()
+ expected = open(path_from_root('tests', 'unistd', 'misc.out'), 'r').read()
+ Building.COMPILER_TEST_OPTS += ['-D' + fs]
+ self.do_run(src, expected)
def test_uname(self):
src = r'''
@@ -8895,6 +8997,8 @@ def process(filename):
def test_cases(self):
if Building.LLVM_OPTS: return self.skip("Our code is not exactly 'normal' llvm assembly")
+ emcc_args = self.emcc_args
+
try:
os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1'
Settings.CHECK_OVERFLOWS = 0
@@ -8908,6 +9012,10 @@ def process(filename):
if '_noasm' in shortname and Settings.ASM_JS:
print self.skip('case "%s" not relevant for asm.js' % shortname)
continue
+ self.emcc_args = emcc_args
+ if os.path.exists(shortname + '.emcc'):
+ if not self.emcc_args: continue
+ self.emcc_args = self.emcc_args + json.loads(open(shortname + '.emcc').read())
print >> sys.stderr, "Testing case '%s'..." % shortname
output_file = path_from_root('tests', 'cases', shortname + '.txt')
if Settings.QUANTUM_SIZE == 1:
@@ -8928,6 +9036,7 @@ def process(filename):
finally:
del os.environ['EMCC_LEAVE_INPUTS_RAW']
+ self.emcc_args = emcc_args
def test_fuzz(self):
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2')
diff --git a/tests/test_other.py b/tests/test_other.py
index b11f22e5..9f331439 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -295,7 +295,7 @@ f.close()
make = make_commands[generator]
cmake_cases = ['target_js', 'target_html']
- cmake_outputs = ['hello_world.js', 'hello_world_gles.html']
+ cmake_outputs = ['test_cmake.js', 'hello_world_gles.html']
for i in range(0, 2):
for configuration in ['Debug', 'Release']:
# CMake can be invoked in two ways, using 'emconfigure cmake', or by directly running 'cmake'.
@@ -342,7 +342,7 @@ f.close()
# Run through node, if CMake produced a .js file.
if cmake_outputs[i].endswith('.js'):
ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
- assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
+ self.assertTextDataIdentical(open(cmakelistsdir + '/out.txt', 'r').read().strip(), ret.strip())
finally:
os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
shutil.rmtree(tempdirname)
@@ -1665,10 +1665,10 @@ f.close()
if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores')
try:
os.environ['EMCC_DEBUG'] = '1'
- os.environ['EMCC_CORES'] = '2'
+ os.environ['EMCC_CORES'] = '2' # standardize over machines
for asm, linkable, chunks, js_chunks in [
- (0, 0, 3, 2), (0, 1, 3, 4),
- (1, 0, 3, 2), (1, 1, 3, 4)
+ (0, 0, 2, 2), (0, 1, 2, 4),
+ (1, 0, 2, 2), (1, 1, 2, 4)
]:
print asm, linkable, chunks, js_chunks
output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate()
diff --git a/tests/unistd/access.c b/tests/unistd/access.c
index 4d5ba08e..57d38f5c 100644
--- a/tests/unistd/access.c
+++ b/tests/unistd/access.c
@@ -5,14 +5,19 @@
int main() {
EM_ASM(
- FS.writeFile('/forbidden', ''); FS.chmod('/forbidden', 0000);
- FS.writeFile('/readable', ''); FS.chmod('/readable', 0444);
- FS.writeFile('/writeable', ''); FS.chmod('/writeable', 0222);
- FS.writeFile('/allaccess', ''); FS.chmod('/allaccess', 0777);
+ FS.mkdir('working');
+#if NODEFS
+ FS.mount(NODEFS, { root: '.' }, 'working');
+#endif
+ FS.chdir('working');
+ FS.writeFile('forbidden', ''); FS.chmod('forbidden', 0000);
+ FS.writeFile('readable', ''); FS.chmod('readable', 0444);
+ FS.writeFile('writeable', ''); FS.chmod('writeable', 0222);
+ FS.writeFile('allaccess', ''); FS.chmod('allaccess', 0777);
);
- char* files[] = {"/readable", "/writeable",
- "/allaccess", "/forbidden", "/nonexistent"};
+ char* files[] = {"readable", "writeable",
+ "allaccess", "forbidden", "nonexistent"};
for (int i = 0; i < sizeof files / sizeof files[0]; i++) {
printf("F_OK(%s): %d\n", files[i], access(files[i], F_OK));
printf("errno: %d\n", errno);
diff --git a/tests/unistd/access.out b/tests/unistd/access.out
index d462e5a5..b5e4a541 100644
--- a/tests/unistd/access.out
+++ b/tests/unistd/access.out
@@ -1,45 +1,45 @@
-F_OK(/readable): 0
+F_OK(readable): 0
errno: 0
-R_OK(/readable): 0
+R_OK(readable): 0
errno: 0
-X_OK(/readable): -1
+X_OK(readable): -1
errno: 13
-W_OK(/readable): -1
+W_OK(readable): -1
errno: 13
-F_OK(/writeable): 0
+F_OK(writeable): 0
errno: 0
-R_OK(/writeable): -1
+R_OK(writeable): -1
errno: 13
-X_OK(/writeable): -1
+X_OK(writeable): -1
errno: 13
-W_OK(/writeable): 0
+W_OK(writeable): 0
errno: 0
-F_OK(/allaccess): 0
+F_OK(allaccess): 0
errno: 0
-R_OK(/allaccess): 0
+R_OK(allaccess): 0
errno: 0
-X_OK(/allaccess): 0
+X_OK(allaccess): 0
errno: 0
-W_OK(/allaccess): 0
+W_OK(allaccess): 0
errno: 0
-F_OK(/forbidden): 0
+F_OK(forbidden): 0
errno: 0
-R_OK(/forbidden): -1
+R_OK(forbidden): -1
errno: 13
-X_OK(/forbidden): -1
+X_OK(forbidden): -1
errno: 13
-W_OK(/forbidden): -1
+W_OK(forbidden): -1
errno: 13
-F_OK(/nonexistent): -1
+F_OK(nonexistent): -1
errno: 2
-R_OK(/nonexistent): -1
+R_OK(nonexistent): -1
errno: 2
-X_OK(/nonexistent): -1
+X_OK(nonexistent): -1
errno: 2
-W_OK(/nonexistent): -1
+W_OK(nonexistent): -1
errno: 2
diff --git a/tests/unistd/io.c b/tests/unistd/io.c
index 0ff5f4fb..5dcdbbb6 100644
--- a/tests/unistd/io.c
+++ b/tests/unistd/io.c
@@ -7,6 +7,11 @@
int main() {
EM_ASM(
+ FS.mkdir('/working');
+#if NODEFS
+ FS.mount(NODEFS, { root: '.' }, '/working');
+#endif
+
var major = 80;
var device = FS.makedev(major++, 0);
@@ -51,14 +56,14 @@ int main() {
FS.createDevice('/', 'createDevice-read-only', function() {});
FS.createDevice('/', 'createDevice-write-only', null, function() {});
- FS.mkdir('/folder', 0777);
- FS.writeFile('/file', '1234567890');
+ FS.mkdir('/working/folder');
+ FS.writeFile('/working/file', '1234567890');
);
char readBuffer[256] = {0};
char writeBuffer[] = "writeme";
- int fl = open("/folder", O_RDWR);
+ int fl = open("/working/folder", O_RDWR);
printf("read from folder: %d\n", read(fl, readBuffer, sizeof readBuffer));
printf("errno: %d\n", errno);
errno = 0;
@@ -97,13 +102,19 @@ int main() {
printf("open write-only device from createDevice for write, errno: %d\n\n", errno);
errno = 0;
- int f = open("/file", O_RDWR);
+ int f = open("/working/file", O_RDWR);
printf("read from file: %d\n", read(f, readBuffer, sizeof readBuffer));
printf("data: %s\n", readBuffer);
memset(readBuffer, 0, sizeof readBuffer);
printf("errno: %d\n\n", errno);
errno = 0;
+ printf("pread past end of file: %d\n", pread(f, readBuffer, sizeof readBuffer, 99999999999));
+ printf("data: %s\n", readBuffer);
+ memset(readBuffer, 0, sizeof readBuffer);
+ printf("errno: %d\n\n", errno);
+ errno = 0;
+
printf("seek: %d\n", lseek(f, 3, SEEK_SET));
printf("errno: %d\n\n", errno);
printf("partial read from file: %d\n", read(f, readBuffer, 3));
diff --git a/tests/unistd/io.out b/tests/unistd/io.out
index 037d0c34..c979557e 100644
--- a/tests/unistd/io.out
+++ b/tests/unistd/io.out
@@ -31,6 +31,10 @@ read from file: 10
data: 1234567890
errno: 0
+pread past end of file: 0
+data:
+errno: 0
+
seek: 3
errno: 0
diff --git a/tests/unistd/links.c b/tests/unistd/links.c
index 5b403c1f..c46c6294 100644
--- a/tests/unistd/links.c
+++ b/tests/unistd/links.c
@@ -5,12 +5,17 @@
int main() {
EM_ASM(
- FS.symlink('../test/../there!', '/link');
- FS.writeFile('/file', 'test');
- FS.mkdir('/folder');
+ FS.mkdir('working');
+#if NODEFS
+ FS.mount(NODEFS, { root: '.' }, 'working');
+#endif
+ FS.chdir('working');
+ FS.symlink('../test/../there!', 'link');
+ FS.writeFile('file', 'test');
+ FS.mkdir('folder');
);
- char* files[] = {"/link", "/file", "/folder"};
+ char* files[] = {"link", "file", "folder"};
char buffer[256] = {0};
for (int i = 0; i < sizeof files / sizeof files[0]; i++) {
@@ -22,23 +27,23 @@ int main() {
}
printf("symlink/overwrite\n");
- printf("ret: %d\n", symlink("new-nonexistent-path", "/link"));
+ printf("ret: %d\n", symlink("new-nonexistent-path", "link"));
printf("errno: %d\n\n", errno);
errno = 0;
printf("symlink/normal\n");
- printf("ret: %d\n", symlink("new-nonexistent-path", "/folder/link"));
+ printf("ret: %d\n", symlink("new-nonexistent-path", "folder/link"));
printf("errno: %d\n", errno);
errno = 0;
printf("readlink(created link)\n");
- printf("ret: %d\n", readlink("/folder/link", buffer, 256));
+ printf("ret: %d\n", readlink("folder/link", buffer, 256));
printf("errno: %d\n", errno);
printf("result: %s\n\n", buffer);
errno = 0;
printf("readlink(short buffer)\n");
- printf("ret: %d\n", readlink("/link", buffer, 4));
+ printf("ret: %d\n", readlink("link", buffer, 4));
printf("errno: %d\n", errno);
printf("result: %s\n", buffer);
errno = 0;
diff --git a/tests/unistd/links.out b/tests/unistd/links.out
index 75e410cb..f2a7aed6 100644
--- a/tests/unistd/links.out
+++ b/tests/unistd/links.out
@@ -1,14 +1,14 @@
-readlink(/link)
+readlink(link)
ret: 17
errno: 0
result: ../test/../there!
-readlink(/file)
+readlink(file)
ret: -1
errno: 22
result: ../test/../there!
-readlink(/folder)
+readlink(folder)
ret: -1
errno: 22
result: ../test/../there!
diff --git a/tests/unistd/misc.c b/tests/unistd/misc.c
index 5b0d63d2..2ca5b390 100644
--- a/tests/unistd/misc.c
+++ b/tests/unistd/misc.c
@@ -2,9 +2,17 @@
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
+#include <emscripten.h>
int main() {
- int f = open("/", O_RDONLY);
+ EM_ASM(
+ FS.mkdir('working');
+#if NODEFS
+ FS.mount(NODEFS, { root: '.' }, 'working');
+#endif
+ );
+
+ int f = open("working", O_RDONLY);
sync();
@@ -36,7 +44,7 @@ int main() {
printf(", errno: %d\n", errno);
errno = 0;
- printf("link: %d", link("/here", "/there"));
+ printf("link: %d", link("working/here", "working/there"));
printf(", errno: %d\n", errno);
errno = 0;
@@ -65,10 +73,10 @@ int main() {
char* exec_argv[] = {"arg", 0};
char* exec_env[] = {"a=b", 0};
- printf("execl: %d", execl("/program", "arg", 0));
+ printf("execl: %d", execl("working/program", "arg", 0));
printf(", errno: %d\n", errno);
errno = 0;
- printf("execle: %d", execle("/program", "arg", 0, exec_env));
+ printf("execle: %d", execle("working/program", "arg", 0, exec_env));
printf(", errno: %d\n", errno);
errno = 0;
printf("execlp: %d", execlp("program", "arg", 0));
@@ -84,16 +92,16 @@ int main() {
printf(", errno: %d\n", errno);
errno = 0;
- printf("chown(good): %d", chown("/", 123, 456));
+ printf("chown(good): %d", chown("working", 123, 456));
printf(", errno: %d\n", errno);
errno = 0;
- printf("chown(bad): %d", chown("/noexist", 123, 456));
+ printf("chown(bad): %d", chown("working/noexist", 123, 456));
printf(", errno: %d\n", errno);
errno = 0;
- printf("lchown(good): %d", lchown("/", 123, 456));
+ printf("lchown(good): %d", lchown("working", 123, 456));
printf(", errno: %d\n", errno);
errno = 0;
- printf("lchown(bad): %d", lchown("/noexist", 123, 456));
+ printf("lchown(bad): %d", lchown("working/noexist", 123, 456));
printf(", errno: %d\n", errno);
errno = 0;
printf("fchown(good): %d", fchown(f, 123, 456));
diff --git a/tests/unistd/truncate.c b/tests/unistd/truncate.c
index b1d9fc96..e63a4c13 100644
--- a/tests/unistd/truncate.c
+++ b/tests/unistd/truncate.c
@@ -8,14 +8,19 @@
int main() {
EM_ASM(
- FS.writeFile('/towrite', 'abcdef');
- FS.writeFile('/toread', 'abcdef');
- FS.chmod('/toread', 0444);
+ FS.mkdir('working');
+#if NODEFS
+ FS.mount(NODEFS, { root: '.' }, 'working');
+#endif
+ FS.chdir('working');
+ FS.writeFile('towrite', 'abcdef');
+ FS.writeFile('toread', 'abcdef');
+ FS.chmod('toread', 0444);
);
struct stat s;
- int f = open("/towrite", O_WRONLY);
- int f2 = open("/toread", O_RDONLY);
+ int f = open("towrite", O_WRONLY);
+ int f2 = open("toread", O_RDONLY);
printf("f2: %d\n", f2);
fstat(f, &s);
@@ -48,17 +53,17 @@ int main() {
errno = 0;
printf("\n");
- printf("truncate(2): %d\n", truncate("/towrite", 2));
+ printf("truncate(2): %d\n", truncate("towrite", 2));
printf("errno: %d\n", errno);
- stat("/towrite", &s);
+ stat("towrite", &s);
printf("st_size: %d\n", s.st_size);
memset(&s, 0, sizeof s);
errno = 0;
printf("\n");
- printf("truncate(readonly, 2): %d\n", truncate("/toread", 2));
+ printf("truncate(readonly, 2): %d\n", truncate("toread", 2));
printf("errno: %d\n", errno);
- stat("/toread", &s);
+ stat("toread", &s);
printf("st_size: %d\n", s.st_size);
memset(&s, 0, sizeof s);
errno = 0;
diff --git a/tests/unistd/unlink.c b/tests/unistd/unlink.c
index f0a8f4dd..9f532325 100644
--- a/tests/unistd/unlink.c
+++ b/tests/unistd/unlink.c
@@ -7,6 +7,9 @@
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
+#if EMSCRIPTEN
+#include <emscripten.h>
+#endif
static void create_file(const char *path, const char *buffer, int mode) {
int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
@@ -19,6 +22,15 @@ static void create_file(const char *path, const char *buffer, int mode) {
}
void setup() {
+ mkdir("working", 0777);
+#if EMSCRIPTEN
+ EM_ASM(
+#if NODEFS
+ FS.mount(NODEFS, { root: '.' }, 'working');
+#endif
+ );
+#endif
+ chdir("working");
create_file("file", "test", 0777);
create_file("file1", "test", 0777);
symlink("file1", "file1-link");
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index a11da7f0..d6f8921c 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -367,6 +367,17 @@ EMSCRIPTEN_FUNCS();
return filename
-def run(filename, passes, js_engine, jcache, source_map=False, extra_info=None):
+def run(filename, passes, js_engine=shared.NODE_JS, jcache=False, source_map=False, extra_info=None):
return temp_files.run_and_clean(lambda: run_on_js(filename, passes, js_engine, jcache, source_map, extra_info))
+if __name__ == '__main__':
+ last = sys.argv[-1]
+ if '{' in last:
+ extra_info = json.loads(last)
+ sys.argv = sys.argv[:-1]
+ else:
+ extra_info = None
+ out = run(sys.argv[1], sys.argv[2:], extra_info=extra_info)
+ import shutil
+ shutil.copyfile(out, sys.argv[1] + '.jsopt.js')
+
diff --git a/tools/jsrun.py b/tools/jsrun.py
index 6f77ce51..7acfc978 100644
--- a/tools/jsrun.py
+++ b/tools/jsrun.py
@@ -1,6 +1,8 @@
-import time
+import time, os, sys, logging
from subprocess import Popen, PIPE, STDOUT
+TRACK_PROCESS_SPAWNS = True if (os.getenv('EM_BUILD_VERBOSE') and int(os.getenv('EM_BUILD_VERBOSE')) >= 3) else False
+
def timeout_run(proc, timeout, note='unnamed process', full_output=False):
start = time.time()
if timeout is not None:
@@ -11,19 +13,25 @@ def timeout_run(proc, timeout, note='unnamed process', full_output=False):
raise Exception("Timed out: " + note)
out = proc.communicate()
out = map(lambda o: '' if o is None else o, out)
+ if TRACK_PROCESS_SPAWNS:
+ logging.info('Process ' + str(proc.pid) + ' finished after ' + str(time.time() - start) + ' seconds.')
return '\n'.join(out) if full_output else out[0]
def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdout=PIPE, stderr=None, cwd=None, full_output=False):
if type(engine) is not list:
engine = [engine]
command = engine + [filename] + (['--'] if 'd8' in engine[0] or 'jsc' in engine[0] else []) + args
- return timeout_run(
- Popen(
+ proc = Popen(
command,
stdin=stdin,
stdout=stdout,
stderr=stderr,
- cwd=cwd),
- 15*60 if check_timeout else None,
+ cwd=cwd)
+ timeout = 15*60 if check_timeout else None
+ if TRACK_PROCESS_SPAWNS:
+ logging.info('Blocking on process ' + str(proc.pid) + ': ' + str(command) + (' for ' + str(timeout) + ' seconds' if timeout else ' until it finishes.'))
+ return timeout_run(
+ proc,
+ timeout,
'Execution',
full_output=full_output)
diff --git a/tools/shared.py b/tools/shared.py
index 53f83185..c5df34f1 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -47,6 +47,7 @@ class WindowsPopen:
try:
# Call the process with fixed streams.
self.process = subprocess.Popen(args, bufsize, executable, self.stdin_, self.stdout_, self.stderr_, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
+ self.pid = self.process.pid
except Exception, e:
logging.error('\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e)))
raise e
@@ -84,10 +85,6 @@ class WindowsPopen:
except:
pass # Mute all exceptions in dtor, particularly if we didn't use a response file, self.response_filename doesn't exist.
-# Install our replacement Popen handler if we are running on Windows to avoid python spawn process function.
-if os.name == 'nt':
- Popen = WindowsPopen
-
__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
def path_from_root(*pathelems):
return os.path.join(__rootpath__, *pathelems)
@@ -250,6 +247,19 @@ except Exception, e:
logging.error('Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text))
sys.exit(1)
+try:
+ EM_POPEN_WORKAROUND
+except:
+ EM_POPEN_WORKAROUND = os.environ.get('EM_POPEN_WORKAROUND')
+
+# Install our replacement Popen handler if we are running on Windows to avoid python spawn process function.
+# nb. This is by default disabled since it has the adverse effect of buffering up all logging messages, which makes
+# builds look unresponsive (messages are printed only after the whole build finishes). Whether this workaround is needed
+# seems to depend on how the host application that invokes emcc has set up its stdout and stderr.
+if EM_POPEN_WORKAROUND and os.name == 'nt':
+ logging.debug('Installing Popen workaround handler to avoid bug http://bugs.python.org/issue3905')
+ Popen = WindowsPopen
+
# Expectations
EXPECTED_LLVM_VERSION = (3,2)
@@ -304,7 +314,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.5.10'
+EMSCRIPTEN_VERSION = '1.6.4'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT
@@ -1413,6 +1423,9 @@ class Building:
emcc_debug = os.environ.get('EMCC_DEBUG')
if emcc_debug: del os.environ['EMCC_DEBUG']
+ emcc_leave_inputs_raw = os.environ.get('EMCC_LEAVE_INPUTS_RAW')
+ if emcc_leave_inputs_raw: del os.environ['EMCC_LEAVE_INPUTS_RAW']
+
def make(opt_level):
raw = relooper + '.raw.js'
Building.emcc(os.path.join('relooper', 'Relooper.cpp'), ['-I' + os.path.join('relooper'), '--post-js',
@@ -1442,8 +1455,10 @@ class Building:
finally:
os.chdir(curr)
if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug
+ if emcc_leave_inputs_raw: os.environ['EMCC_LEAVE_INPUTS_RAW'] = emcc_leave_inputs_raw
if not ok:
logging.error('bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten')
+ try_delete(relooper) # do not leave a phase-1 version if phase 2 broke
1/0
@staticmethod
diff --git a/tools/tempfiles.py b/tools/tempfiles.py
index 1721b2bb..27da1082 100644
--- a/tools/tempfiles.py
+++ b/tools/tempfiles.py
@@ -27,6 +27,7 @@ class TempFiles:
def clean(self):
if self.save_debug_files:
+ import sys
print >> sys.stderr, 'not cleaning up temp files since in debug-save mode, see them in %s' % (self.tmp,)
return
for filename in self.to_clean: