pax_global_header00006660000000000000000000000064132161317200014506gustar00rootroot0000000000000052 comment=97e85495a65df776a14b0d2d1486195762300dbd neko-2-2-0/000077500000000000000000000000001321613172000124415ustar00rootroot00000000000000neko-2-2-0/CHANGES000066400000000000000000000410261321613172000134370ustar00rootroot000000000000002017-12-19 : 2.2.0 nekotools : added `nekotools boot -c *.n`, which generates a C file that contains the input Neko bytecode (#130) nekotools : fixed `nekotools boot` not able to find neko when a value in PATH does not have a trailing slash (#148) cmake : recognize common install location variables by using GNUInstallDirs cmake : fixed various build issues, particularly for FreeBSD (Thanks, ppenzin!), and cygwin cmake : added NekoConfig.cmake to ease building ndll or native program using Neko with CMake cmake : replaces WITH_NDLLS with WITH_* (#157) cmake : does not recompile nekoc/nekoml unless RECOMPILE_NEKOC_NEKOML (#171) all : added NEKO_MODULE_PATH in neko.h that points to the installation path of the ndll files std : bugfix in utf8_compare (https://github.com/HaxeFoundation/haxe/issues/5308) ssl : handle MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY (#150) ssl : allow partial failure on loading certificates (#160) mysql : use eof terminated string when appropriated (#159) jit : disable jit for win64, which never worked all : introduced NEKO_BIG_ENDIAN and NEKO_LITTLE_ENDIAN to replace IS_BIG_ENDIAN, IS_LITTLE_ENDIAN, LITTLE_ENDIAN, BIG_ENDIAN, and BYTE_ORDER all : renamed TAG_BITS to NEKO_TAG_BITS all : add NEKO_JIT_DISABLE and NEKO_JIT_DEBUG CMake options all : VS2015 and 2017 compatiblity (#133 #172) sqlite : fixed reading 32-bit int from sqlite (#167) 2016-05-08 : 2.1.0 all : switched to use CMake for building (#122) mod_neko/tora : use remote_ip (fixes Apache 2.2 returning 0.0.0.0 in 64 bits ?) std : added buffer_get_length std : added socket_send_to and socket_recv_from for UDP, added socket_set_keepalive all : increased max codesize from 65K opcodes to 1M nekoc : allow break/continue in try/catch std : bugfix in utf8_compare vm : added $sget16/$sget32/$sgetf/$sgetd, $sset16/$sset32/$ssetf/$ssetd, and $itof/$itod/$ftoi/$dtoi vm : bugfix with arrays/strings having length >128MB jit : bugfix on some GCC versions causing invalid array access std : fixed escaping of arguments in process_run all : nekotools boot executable can now be safely striped on Linux (#86) all : nekotools boot now looks for the Neko VM binary in cwd, $loader.path, and PATH in order (#110) std : added epoll support (#67) all : libneko can now be loaded from current directory all : libneko is now versioned vm : comparisons with NaN and Int/Float now always returns false api : added kind_lookup (#6) mod_neko/tora : distribute ndlls compiled against Apache 2.4 (can still manually compile against Apache 2.2) mysql : use MariaDB's LGPL connector/c instead of MySQL's GPL connector/c (can still use MySQL for compilation) all : copyright to Haxe Foundation instead of Nicolas and other license clean up (#102) 2013-02-23 : 2.0.0 all : changed license to MIT mod_neko+mod_tora : fixed issue with get_client_ip in 64 bits mode /gcc mysql : added support for timestamp to date conversion std : added merge_sort native implementation std : added mem_local_size regexp : fix in regexp_match, ^ no longer match if pos > 0 tools : don't abort server on invalid http request std : fixed sys_command error code (was <<8 on Linux/OSX) nekoc : added -version which adds Loop opcode and ensure correct $array evaluation order vm : support for bytecode version and new Loop/MakeArray2 opcodes mod_neko/tora : only mix POST with GET params if content-type contains 'urlencoded' mysql5 : added charset support check for escape() nekoc : fixed bug with switch tables where max >= 256 neko : int32 is now a first class value std : md5 and hashing now takes the int32 value into account neko : max array/string size is now 256MB instead of 512MB std : date_new("YYYY-MM-DD") now uses localtime instead of UTC (same as Y-M-D H:M:S) neko : fixed missing stack for array write in interp mode with invalid index neko : added "-version" to print version and exit 2011-09-10 : 1.8.2 vm : use 15 digits (instead of 10) for float display std : allow up to 512MB array/string size in serialize (instead of 1MB) std : bugfix in utf8 (with 4 bytes codes) vm : finalizers bugfix on Windows std : added sys_thread_cpu_time() vm : use VEXTERN for neko_kind_module and neko_id_module std : hide process console in process_run nekoml : added Math core module std : fixed timeout error for sockets on Windows mod_tora : added PROXY_MODE configuration std : fixed timeout error for sockets on Linux vm : fixed $int and $float - return null on invalid strings mysql : added result_get_fields_names gc : prevent issues with AV softs / GoogleDesktop which inject threads vm : use sse2 for fp calculus on gcc (double precision, same as msvc/flash) removed in updated build (some CPU are not compatible) mysql : added support for BINARY(size) type vm : keep stack infos for object/array ops (interp) std : added thread_stack vm : added $fasthash mysql5 : fixed 5.5 protocol change std : fixed sha1 for 64-bits (also fix mysql5 auth) std : added make_sha1 mysql : added set_conv_funs for string + bytes wrapping support 2009-07-26 : 1.8.1 nekoc : small fix in evaluation of using jump tables for switch on integers regexp : use a recursion limit to prevent stack overflows in pcre mysql5 : completely rewrote mysql client mod_tora : complete rearchitecture with abstract protocol std : added socket_set_fast_send mod_tora : use socket fast send to optimize timing mod_tora : fixed bug when .n file does not exists mod_tora : fix for Apache 2.x - does not set the content-type if declined mod_tora : added port range configuration (for random tora server) std, mod_tora : propagate jit mode to created threads nekoc : optimization for debug infos : precompute file table at compile-time threads : added neko_gc_register_thread (but buggy, so not used) mysql5 : added 5 hours network timeout while waiting for an answer mysql5 : fixed some additional errors handling mysql5 : allow big requests (more than 16MB) vm : optimize object table - one word and one memory block saved per object jit : one more crash fix for the + operation and unexisting overloaded operator nekoml : added Sys.is_directory, Sys.read_directory and Regexp.split nekoml : don't allow empty match vm : create pthreads in detached mode (prevent leak on osx/linux) std : added math_fceil,math_ffloor,math_fround,math_int,process_kill nekoc : forbidden usage of 'var' outside blocks 2008-09-23 : 1.8.0 added mod_tora (neko application server) changed mod_neko get_host_name : return the http host instead of the server IP bugfix in nekoml : fixed usage of nekoml.std + added -nostd std : added EINTR handling in send/recv socket operations and fread/fwrite gc : upgraded windows version to 7.1 vm : fixed comparison of bool vm : moved threads stuff into threads.c nekoml : fixed lexing engine, allow escape sequences in char groups mysql : link with thread_safe version on linux std : fixed threads issues with host_resolve and host_reverse libs : compile with -pthread on linux/osx to ensure thread safety main : turned ON jit by default for bootable executables std : added set_trusted primitive gc : use alloc_ignore_off_page for large blocks gc : use finalizers with no_order (prevent cycles) mysql : prevent hashing the fields that looks like inner requests vm : optimized global fields cache std : string_split doesn't copy the string anymore if the pattern is not found vm : added neko_vm_dump_stack std : use per-thread locale on POSIX systems std : url_encode does not encode anymore - and . chars std : fixed sleep() for unix (more accurate and deal with signals) std : added module_read_string and module_set_name std : fixed some file descriptor issues with processes and threads jit : fixed crash whith unsupported OO overloading vm : added $getkind and $iskind builtins std : added same_closure for closure comparison 2008-07-28 : 1.7.1 nekotools : fixed set_return_code in web server std : display windowed application in process_run mod_neko : allowed to uncache module with set_main(null) mod_neko : use strmcpi for set_header("Content-Type") nekoc : one last fix for big arrays (first element was not compiled) mod_neko : added get_http_method nekoml : minor fixes in lexer nekoml : added -pack and -use, auto build nekoml.std include nekoml as part of standard distribution vm/security : $smake now fills the string with 0 std/int32 : fixed need_32_bits macro (negative values) bugfix : >> and >>> were reversed in JIT bugfix : date functions are now MT-safe removed context.h and context.c added lock and tls multithread API to neko.h std : added date_get_tz() mod_neko : added log_message regexp : fix for unmatched optional groups, return null instead of empty string threads : for windows, use critical_section instead of mutex for locks threads : for posix, use a recursive mutex which match windows behavior std : added mutex and deque api (threads) 2008-03-16 : 1.7.0 nekoc : allow binary ast format with -p, don't allow inline nxml std : allow int32_new float parameter vm : reduce debug infos memory size by 16 vm : fixed $int in case of overflow regexp : upgraded windows ndll to use pcre 7.3 with utf8 support fixed : math_round(0.5) is now 1 fixed : date_set_hour and date_set_day crash with invalid dates fixed : bug in vm/callback.c when stack address is >2GB sockets : added support for socket_poll for Windows sockets : added socket_poll_prepare and socket_poll_events thread : added tls_create, tls_set, tls_get vm : threaded interpreter (gcc only) vm : always use COMPACT_TABLE for objects mod_neko : log some errors into apache log neko+vm : added perf statistics hooks (-stats) mod_neko : scriptable configuration and statistics regexp : allow more than 10 matches std : added process_close vm : added $aconcat nekoc : fixed big arrays declarations std : added sys_is64 2007-07-25 : 1.6.0 display error message when uncaught exception in neko thread fix bug in long run JIT programs : no C functions callable anymore use a smarter way to prevent C stack overflow nekoc : stack align error message set max-stack-per-function to 128 and default-stack-size to 256 jit now check stack overflow on function entry and not on every push mod_neko2 set MOD_NEKO=2 env var (for version detection) mod_neko2 : remove Apache 2.0 error message, use 302 http code for redirect fixed fallback of interp operator overloading fix for 64-bit CPU minor optimization for [0] jit array access gnuk/freebsd support fixed thread messages on Windows (do not use system queue) thread_current returns unique value remove kind_import, kind_export, added kind_share added ui library added libs/std/process api functions new binary ast format (faster than nxml) 2007-01-28 : 1.5.3 minor fixes in mod_neko multipart and POST data handling fixed $objremove result (was always true) fixed one-last-bug when using more-than-five-arguments method call return value fixed bug in dev webserver when accessing a directory added xcross support fixed bug with $setresolver in bytecode interpreter changed bootable vm implementation (easier, allow compressed bin) added .mode in sys_stat change in $version format 2006-11-22 : 1.5.2 fixed std math_pow float minor thread cleanup added MySQL5.ndll for Windows fields hash cache is now global (instead of per-thread) socket_select retry on EINTR fixed under-second lock timeout for Linux/OSX added socket_poll for Linux/OSX (emulate with select() on Windows) fixed compilation bug when accessing 'this' in arguments and more than 5 args fixed string_split with empty string (was causing infinite loop) fixes in more-than-five-arguments-calls added $varargs 2006-10-29 : 1.5 neko web server : get_client_header is now case-insensitive std : new thread and lock api neko : when run from commandline, SEGV on Linux are turned into exceptions + added mod_neko2 error if used with Apache 2.0.x 2006-10-09 : 1.4.5 sqlite : added BOOL handling jit : added mmap support (for execution protection) jit : fixed bug when unsupported operation exception vm : fixed bug in debug infos reading when nfiles > 255 vm : fixed bug in interp -> jit call vm : default NEKOPATH is now the same on OSX/Linux vm : optimized debug infos runtime memory size std : added misc.c (float & double bytes manipulations + gc/vm functions) std : fixed buf in sys_read_dir on windows (directory not closed correctly) std : added sys_getch, sys_get_pid std : fixed socket_host (was returning the same as socket_peer) std : improved performances of serialize/unserialize allowed break & continues in try/catch if they don't break outside nekoml : fixed bug in lexer allocating too bug memory when small reads nekotools : bugfixes in server, added static file streaming nekotools : fixed boot for universal binaries mod_neko : minor updates for better memory handling mod_neko : use soft timeout for Apache 1.3 2006-08-02 : 1.4 std : added a SO_REUSEADDR before socket_bind (except windows) nekoc/nekovm : allowed more than 127 filenames in debug infos nekotools server : added -rewrite for mod_rewrite'style urls added zlib wrapper mod_neko for apache 2.0 added sqlite wrapper std : fixed socket_set_timeout (changed unit from millisec to seconds) std : fixed math_pow (integer overflow) , fixed readdir (missing closedir on Linux) added PPC registers neko.h : added NEKO_* OS/CPU flags added JIT for x86 vm : (int mod 0) is now an exception (and not NaN) neko.h : added kind_import and kind_export to share abstracts between libraries std : handle signals in socket send and recv allowed OSX universal build added $setresolver for unknown object field handling 2006-05-11 : 1.3 neko : fixed endianness bug needed to boot, exported neko_is_big_endian neko : fixed bug on Linux x86 gcc with object operators (eax get overwritten) neko : fixed bug : error when __string or __compare does not exist neko : allowed runtime printer redirection (+ added std@print_redirect) neko : defined a default NEKOPATH when not specified (less configuration) neko : fixed int32 calculus bug (need_32_bits macro) neko : fixed calls with a lot of arguments (some cases were failing) neko : fixed preservation of 'this' through tailcall, if changed inside the call neko : added unary operator minus parsing neko : fixed error reporting of unclosed parenthesis nekoml : added Net core module for sockets nekoml : when catching Neko errors, wrap them using Neko_error constructor std : supported serialization of C primitives and __serialize/__unserialize overrides added nekotools (merged nekoboot and neko webserver) std : fixed math_round, fixed math docs std : fixed bug in utf8_resize, utf8_get and utf8_iter. regexp : added regexp_new_options for matching options and regexp_replace_fun regexp : fixed invalid matched length when not index 0 added some benchmarks in src/benchs neko : fixed $ablit and $sblit (when used with same array/string) neko : fixed multithread win32 support mod_neko : changed Content-Type handling for POST data std : added blocking sockets support std : changed sys_time to sys_cpu_time, added sys_time (local time). std : fixed put_env on Linux (GC issue) cleanup of some stuff needed by experimental JIT std : added memory module 2006-01-09 : 1.2 nekoc: added linker : provide linked versions of neko & nekoml compilers added tail calls optimization nekoml: little improved nekoml->neko patterns generator libs: added md5 digest , utf8 api and base_encode/base_decode in std some changes in mod_neko api mysql api now threat tinyint(1) as booleans improved xml parser : support for doctype some fixes for OSX and C++ compilation neko: renamed 'nekovm' to 'neko' experimental jit support object prototypes moved args from builtin ($args) to loader ($loader.args) makeboot can create standalone binaries runtime errors on : - calls with invalid number of arguments - field accesses of not-an-object - binary operations on invalid types - array accesses on not-an-array and not-an-object license change : from GPL to LGPL 2005-11-10 : 1.1 vm : ports PPC (big endian) and AMD64 added stack conservation check at bytecode loadtime : faster VM runtime some more opcodes for better speed added exception and call stack traces added debug informations for bytecode added dispatch tables (for integer switchs) tuned GC usage reorganized VM apis neko: added labels in the language specification added $goto and $apply added switchs added documentation generator nekoml: added NekoML bootstrapped the language (no more need for ocaml) libs: rewrote and completed standard library added generated documentation 2005-08-17 : 1.0 compiler in ocaml virtual machine mod_neko some small libraries neko-2-2-0/CMakeLists.txt000066400000000000000000000576711321613172000152210ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.12) include(GNUInstallDirs) include(CheckCCompilerFlag) include(CheckIncludeFile) include(TestBigEndian) project(Neko C) set(CMAKE_OSX_ARCHITECTURES x86_64) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") # FreeBSD puts all thirdparty libraries in /usr/local link_directories(/usr/local/lib) endif() # put output in "bin" set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR}) # avoid the extra "Debug", "Release" directories # http://stackoverflow.com/questions/7747857/in-cmake-how-do-i-work-around-the-debug-and-release-directories-visual-studio-2 foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${OUTPUT_DIR} ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${OUTPUT_DIR} ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${OUTPUT_DIR} ) endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) # Make sure CMAKE_INSTALL_LIBDIR is relative if(IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR}) file(RELATIVE_PATH CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_LIBDIR}) endif() set(NEKO_VERSION_MAJOR 2) set(NEKO_VERSION_MINOR 2) set(NEKO_VERSION_PATCH 0) set(NEKO_VERSION ${NEKO_VERSION_MAJOR}.${NEKO_VERSION_MINOR}.${NEKO_VERSION_PATCH}) # Determine target endianness TEST_BIG_ENDIAN(NEKO_BIG_ENDIAN) option(WITH_REGEXP "Build Perl-compatible regex support." ON) option(WITH_UI "Build GTK-2 UI support." ON) option(WITH_SSL "Build SSL support." ON) option(WITH_MYSQL "Build MySQL support." ON) option(WITH_SQLITE "Build Sqlite support." ON) option(WITH_APACHE "Build Apach modules." ON) option(WITH_NEKOML "Build NekoML." ON) # Process common headers in libraries # TODO libraries should not be built from this file, but rather by traversing the tree using add_subdirectory #add_subdirectory(libs) if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") if (${CMAKE_OSX_ARCHITECTURES} STREQUAL "i386") set(arch_64 "") elseif (${CMAKE_OSX_ARCHITECTURES} STREQUAL "x86_64") set(arch_64 "64") else() message( FATAL_ERROR "CMAKE_OSX_ARCHITECTURES should be i386 or x86_64." ) endif() else() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(arch_64 "64") else() set(arch_64 "") endif() endif() if(WIN32) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "C:/HaxeToolkit/neko" CACHE PATH "default install path" FORCE) endif() set(NEKO_MODULE_PATH ${CMAKE_INSTALL_PREFIX}) else() set(NEKO_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/neko) endif() if(APPLE AND STATIC_DEPS STREQUAL "all") if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "CMAKE_OSX_DEPLOYMENT_TARGET" FORCE) endif() endif() check_include_file(xlocale.h NEKO_XLOCALE_H) option(NEKO_JIT_DISABLE "Disable Neko JIT." OFF) option(NEKO_JIT_DEBUG "Debug Neko JIT." OFF) configure_file ( "${CMAKE_SOURCE_DIR}/vm/neko.h.in" "${CMAKE_BINARY_DIR}/neko.h" ) set(external_deps BoehmGC Zlib OpenSSL MariaDBConnector PCRE Sqlite3 APR APRutil Apache MbedTLS ) if (WIN32) set(STATIC_DEPS_DEFAULT "all") else() set(STATIC_DEPS_DEFAULT "none") option(RELOCATABLE "Set RPATH to $ORIGIN (Linux) / @executable_path (Mac)." ON) if (NOT APPLE) option(RUN_LDCONFIG "Run ldconfig after install." ON) endif() endif() set(STATIC_DEPS_DOC "Dependencies that should be linked statically. Can be \"all\", \"none\", or a list of library names (e.g. \"${external_deps}\").") set(STATIC_DEPS ${STATIC_DEPS_DEFAULT} CACHE STRING "${STATIC_DEPS_DOC}") # Validate STATIC_DEPS if (STATIC_DEPS STREQUAL "all") set(STATIC_DEPS ${external_deps} CACHE STRING "${STATIC_DEPS_DOC}" FORCE) elseif (STATIC_DEPS STREQUAL "none") message(STATUS "set STATIC_DEPS to nothing") set(STATIC_DEPS CACHE STRING "${STATIC_DEPS_DOC}" FORCE) endif() foreach(dep ${STATIC_DEPS}) list(FIND external_deps ${dep} idx) if(idx EQUAL -1) message(FATAL_ERROR "Invalid STATIC_DEPS. There is no ${dep} in the list of ${external_deps}") endif() endforeach() # Set STATIC_* variables according to STATIC_DEPS. foreach(dep ${external_deps}) string(TOUPPER ${dep} var) list(FIND STATIC_DEPS ${dep} static_idx) if (static_idx EQUAL -1) set(STATIC_${var} FALSE) else() set(STATIC_${var} TRUE) endif() endforeach() include(ExternalProject) # CMAKE_BUILD_WITH_INSTALL_RPATH should be set to true. # It is because `nekotools boot` will use the neko in build dir during build. set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) if (RELOCATABLE) # https://cmake.org/Wiki/CMake_RPATH_handling set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_SKIP_INSTALL_RPATH FALSE) if(APPLE) set(CMAKE_MACOSX_RPATH TRUE) set(CMAKE_INSTALL_RPATH @executable_path/) elseif(UNIX) set(CMAKE_INSTALL_RPATH \$ORIGIN) endif() endif() if(UNIX AND NOT APPLE) add_definitions(-DABI_ELF) endif() if(UNIX) add_definitions(-D_GNU_SOURCE) add_compile_options(-fno-omit-frame-pointer) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) set(ARG_PIC -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE) # https://github.com/HaxeFoundation/neko/pull/17 if(CMAKE_SIZEOF_VOID_P EQUAL 4) check_c_compiler_flag(-mincoming-stack-boundary=2 HAS_MINCOMING_STACK_BOUNDARY) check_c_compiler_flag(-mstack-alignment=2 HAS_MSTACK_ALIGNMENT) if(HAS_MINCOMING_STACK_BOUNDARY) add_compile_options(-mincoming-stack-boundary=2) elseif(HAS_MSTACK_ALIGNMENT) add_compile_options(-mstack-alignment=2) endif() endif() find_package(PkgConfig REQUIRED) endif() # git is used for source_archive and for applying patch find_package(Git REQUIRED) # copy the lib/src folder to build directory # (if it is a fat archive, there will be external libraries) if(EXISTS ${CMAKE_SOURCE_DIR}/libs/src) file(COPY ${CMAKE_SOURCE_DIR}/libs/src DESTINATION ${CMAKE_BINARY_DIR}/libs) endif() # ExternalProject configs set(EP_CONFIGS PREFIX ${CMAKE_BINARY_DIR}/libs DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/libs/download ) if(NOT ${CMAKE_VERSION} VERSION_LESS 3.1) list(APPEND EP_CONFIGS DOWNLOAD_NO_PROGRESS 1 ) endif() if(${CMAKE_VERSION} VERSION_LESS 3.2) list(APPEND EP_CONFIGS STEP_TARGETS download ) else() list(APPEND EP_CONFIGS INDEPENDENT_STEP_TARGETS download ) endif() set(EP_PROPS EXCLUDE_FROM_ALL 1 ) include_directories( ${CMAKE_BINARY_DIR} vm libs/common ) file(GLOB libneko_public_headers vm/neko*.h ) list(APPEND libneko_public_headers ${CMAKE_BINARY_DIR}/neko.h ) add_library(libneko SHARED vm/alloc.c vm/builtins.c vm/callback.c vm/elf.c vm/interp.c vm/load.c vm/objtable.c vm/others.c vm/hash.c vm/module.c vm/jit_x86.c vm/threads.c ) add_executable(nekovm vm/stats.c vm/main.c ) if (STATIC_BOEHMGC) ExternalProject_Add(libatomic_ops ${EP_CONFIGS} URL https://github.com/ivmai/libatomic_ops/releases/download/v7.6.0/libatomic_ops-7.6.0.tar.gz URL_MD5 4d4cd729e55fafb56d48f667c3e46331 CONFIGURE_COMMAND echo skip config BUILD_COMMAND echo skip build INSTALL_COMMAND echo skip install ) set(BoehmGC_URL "http://www.hboehm.info/gc/gc_source/gc-7.6.0.tar.gz") if (NOT ${CMAKE_VERSION} VERSION_LESS 3.7) list(APPEND BoehmGC_URL "https://github.com/ivmai/bdwgc/files/1005477/gc-7.6.0.tar.gz" ) endif() set ( BoehmGC_CONFIGS DEPENDS libatomic_ops URL ${BoehmGC_URL} URL_MD5 bf46ccbdaccfa3186c2ab87191c8855a ) if (WIN32) ExternalProject_Add(BoehmGC ${EP_CONFIGS} ${BoehmGC_CONFIGS} CMAKE_ARGS -Wno-dev -Denable_threads=ON -Denable_parallel_mark=ON -DCMAKE_USE_WIN32_THREADS_INIT=ON PATCH_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/libs/src/libatomic_ops ${CMAKE_BINARY_DIR}/libs/src/BoehmGC/libatomic_ops INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/libs/src/BoehmGC/include ${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build/include/gc ) set(GC_INCLUDE_DIR ${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build/include) set(GC_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build/${CMAKE_CFG_INTDIR}/gcmt-dll.lib ) add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gcmt-dll.dll DEPENDS BoehmGC COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build/${CMAKE_CFG_INTDIR}/gcmt-dll.dll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) add_custom_target(gcmt-dll.dll ALL DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gcmt-dll.dll ) add_dependencies(nekovm gcmt-dll.dll) else() if (APPLE) set(GC_CFLAGS "-w -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") else() set(GC_CFLAGS "-w") endif() set(GC_INCLUDE_DIR ${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build/include) set(GC_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build/lib/libgc.a ) ExternalProject_Add(BoehmGC ${EP_CONFIGS} ${BoehmGC_CONFIGS} PATCH_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/libs/src/libatomic_ops ${CMAKE_BINARY_DIR}/libs/src/BoehmGC/libatomic_ops CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/BoehmGC && ./configure --prefix=${CMAKE_BINARY_DIR}/libs/src/BoehmGC-build --enable-threads=posix --with-pic --enable-shared=no --enable-static=yes --enable-silent-rules --silent BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/BoehmGC && make "CFLAGS=${GC_CFLAGS}" INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/BoehmGC && make install BYPRODUCTS ${GC_LIBRARIES} ) # don't want to add libatomic_ops to external_deps, # but want download_static_deps depends on it add_dependencies(BoehmGC-download libatomic_ops-download) endif() set_target_properties(BoehmGC PROPERTIES ${EP_PROPS}) add_dependencies(libneko BoehmGC) else() find_package(BoehmGC REQUIRED) endif() target_include_directories(libneko PRIVATE ${GC_INCLUDE_DIR}) target_link_libraries(libneko ${GC_LIBRARIES}) target_link_libraries(nekovm libneko) if(UNIX) if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(DL_LIB "dl") endif() find_package(Threads) target_link_libraries(libneko ${DL_LIB} m ${CMAKE_THREAD_LIBS_INIT}) endif() set_target_properties(nekovm libneko PROPERTIES OUTPUT_NAME neko ) set_target_properties(libneko PROPERTIES VERSION ${NEKO_VERSION} SOVERSION ${NEKO_VERSION_MAJOR} COMPILE_DEFINITIONS "_USRDLL;NEKOVM_DLL_EXPORTS;NEKO_SOURCES" PUBLIC_HEADER "${libneko_public_headers}" PDB_NAME libneko ) ####################### # compilers # nekoc, nekoml, nekotools, and test.n if (CMAKE_HOST_WIN32) set(set_neko_env set NEKOPATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set(neko_exec $) elseif(CMAKE_HOST_APPLE) set(set_neko_env "") set(neko_exec DYLD_FALLBACK_LIBRARY_PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} NEKOPATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} $) else() set(set_neko_env "") set(neko_exec LD_LIBRARY_PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} NEKOPATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} $) endif() file(GLOB compilers_src src/neko/*.nml src/nekoml/*.nml boot/*.n ) if (RECOMPILE_NEKOC_NEKOML) add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n COMMAND ${set_neko_env} COMMAND ${neko_exec} ../boot/nekoml.n -nostd neko/Main.nml nekoml/Main.nml COMMAND ${neko_exec} ../boot/nekoc.n -link ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n neko/Main COMMAND ${neko_exec} ../boot/nekoc.n -link ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n nekoml/Main VERBATIM DEPENDS nekovm std.ndll ${compilers_src} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src ) else() add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n COMMAND ${CMAKE_COMMAND} -E copy ../boot/nekoc.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND ${CMAKE_COMMAND} -E copy ../boot/nekoml.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS std.ndll VERBATIM WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src ) endif() add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test.n COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n tools/test.neko COMMAND ${CMAKE_COMMAND} -E copy tools/test.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND ${CMAKE_COMMAND} -E remove tools/test.n VERBATIM DEPENDS nekovm std.ndll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n ${CMAKE_SOURCE_DIR}/src/tools/test.neko WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src ) add_custom_target(test.n ALL DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test.n) add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot.n COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n tools/nekoboot.neko COMMAND ${CMAKE_COMMAND} -E copy tools/nekoboot.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} # COMMAND ${CMAKE_COMMAND} -E remove tools/nekoboot.n VERBATIM DEPENDS nekovm std.ndll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n ${CMAKE_SOURCE_DIR}/src/tools/nekoboot.neko WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src ) file(GLOB nekotools_src src/tools/*.nml ) add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekotools.n COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n -nostd -p tools Tools.nml COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n -link ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekotools.n Tools VERBATIM DEPENDS nekovm std.ndll ${nekotools_src} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot.n WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src ) add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/nekoc.c COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot -c ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.c ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.c VERBATIM DEPENDS nekovm std.ndll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoc.n WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_executable(nekoc ${CMAKE_BINARY_DIR}/nekoc.c) target_link_libraries(nekoc libneko) if (WITH_NEKOML) add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/nekoml.c COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot -c ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.c ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.c VERBATIM DEPENDS nekovm std.ndll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_executable(nekoml ${CMAKE_BINARY_DIR}/nekoml.c) target_link_libraries(nekoml libneko) endif() add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/nekotools.c COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot -c ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekotools.n COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekotools.c ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekotools.c VERBATIM DEPENDS nekovm std.ndll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoboot.n ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekotools.n WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_executable(nekotools ${CMAKE_BINARY_DIR}/nekotools.c) target_link_libraries(nekotools libneko) if (WITH_NEKOML) file(GLOB CORE_NMLS RELATIVE ${CMAKE_SOURCE_DIR}/src src/core/*.nml) set(nekoml_std ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.std) add_custom_command(OUTPUT ${nekoml_std} COMMAND ${set_neko_env} COMMAND ${neko_exec} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n -nostd neko/Main.nml nekoml/Main.nml ${CORE_NMLS} -pack ${nekoml_std} VERBATIM DEPENDS zlib.ndll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.n WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src ) add_custom_target(nekoml.std ALL DEPENDS ${nekoml_std}) endif() ####################### add_custom_target(download_static_deps) if (STATIC_BOEHMGC) add_dependencies(download_static_deps BoehmGC-download) endif() ####################### # source_archive # We create our own source package target instead of using CPack's package_source. # One reason is that the CPack VS generator doesn't generate package_source target. # See https://cmake.org/Bug/view.php?id=13058 if (WIN32) set(source_archive_format zip) else() set(source_archive_format tar.gz) endif() set(source_archive_name_we neko-${NEKO_VERSION}-src) set(source_archive_name ${source_archive_name_we}.${source_archive_format}) add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_name} COMMAND ${GIT_EXECUTABLE} archive --prefix=${source_archive_name_we}/ -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_name} HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} VERBATIM ) add_custom_target(source_archive DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_name} ) # source_archive_fat # It is source_archive + STATIC_DEPS placed in libs/src. set(source_archive_fat_name_we neko-${NEKO_VERSION}-src-fat) set(source_archive_fat_name ${source_archive_fat_name_we}.${source_archive_format}) add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_fat_name} COMMAND ${CMAKE_COMMAND} -Dsource_archive_name_we=${source_archive_name_we} -Dsource_archive=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_name} -Dsource_archive_fat_name_we=${source_archive_fat_name_we} -Dsource_archive_fat_name=${source_archive_fat_name} -Dbin_dir=${CMAKE_BINARY_DIR} -Dsrc_dir=${CMAKE_SOURCE_DIR} -Dlib_src_dir=libs/src -P ${CMAKE_SOURCE_DIR}/cmake/source_archive_fat.cmake DEPENDS source_archive download_static_deps VERBATIM ) add_custom_target(source_archive_fat DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_fat_name} ) ####################### # install target if (WIN32) set(DEST_BIN .) set(DEST_LIB .) set(DEST_NDLL .) set(DEST_INCLUDE "include") set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .) include(InstallRequiredSystemLibraries) install ( FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gcmt-dll.dll DESTINATION . ) else() set(DEST_BIN ${CMAKE_INSTALL_BINDIR}) set(DEST_LIB ${CMAKE_INSTALL_LIBDIR}) set(DEST_NDLL ${CMAKE_INSTALL_LIBDIR}/neko) # should match NEKO_MODULE_PATH set(DEST_INCLUDE ${CMAKE_INSTALL_INCLUDEDIR}) endif() install ( TARGETS nekovm nekoc nekotools libneko EXPORT NekoTargets RUNTIME DESTINATION ${DEST_BIN} LIBRARY DESTINATION ${DEST_LIB} PUBLIC_HEADER DESTINATION ${DEST_INCLUDE} ) if (WITH_NEKOML) install ( TARGETS nekoml EXPORT NekoTargets RUNTIME DESTINATION ${DEST_BIN} LIBRARY DESTINATION ${DEST_LIB} PUBLIC_HEADER DESTINATION ${DEST_INCLUDE} ) install ( FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/nekoml.std DESTINATION ${DEST_NDLL} ) endif() include(CMakePackageConfigHelpers) if(WIN32 AND NOT CYGWIN) set(DEF_INSTALL_CMAKE_DIR CMake) else() set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/Neko) endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") export(TARGETS nekovm nekoc nekotools libneko FILE "${CMAKE_BINARY_DIR}/NekoTargets.cmake") if (WITH_NEKOML) export(TARGETS nekoml FILE "${CMAKE_BINARY_DIR}/NekoTargets.cmake") endif() export(PACKAGE Neko) # NekoConfig referencing build dir set(NEKO_INCLUDE_DIRS "${CMAKE_BINARY_DIR};${CMAKE_SOURCE_DIR}/vm") set(NEKO_TARGETS_FILE "${CMAKE_BINARY_DIR}/NekoTargets.cmake") configure_package_config_file( cmake/NekoConfig.cmake.in "${CMAKE_BINARY_DIR}/NekoConfig.cmake" INSTALL_DESTINATION ${CMAKE_BINARY_DIR} PATH_VARS NEKO_INCLUDE_DIRS NEKO_TARGETS_FILE ) # NekoConfig referencing install dirs set(NEKO_INCLUDE_DIRS "${DEST_INCLUDE}") set(NEKO_TARGETS_FILE "${INSTALL_CMAKE_DIR}/NekoTargets.cmake") configure_package_config_file( cmake/NekoConfig.cmake.in "${OUTPUT_DIR}/NekoConfig.cmake" INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}" PATH_VARS NEKO_INCLUDE_DIRS NEKO_TARGETS_FILE ) write_basic_package_version_file( NekoConfigVersion.cmake VERSION ${NEKO_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES ${OUTPUT_DIR}/NekoConfig.cmake ${CMAKE_BINARY_DIR}/NekoConfigVersion.cmake DESTINATION ${INSTALL_CMAKE_DIR} COMPONENT dev ) install( EXPORT NekoTargets DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev ) if (RUN_LDCONFIG) install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/ldconfig.cmake") endif() # A script to create a flat installation for archive package set (NEKO_FLATTEN_SCRIPT ${CMAKE_BINARY_DIR}/cmake/flatten.cmake) configure_file( "${CMAKE_SOURCE_DIR}/cmake/flatten.cmake.in" ${NEKO_FLATTEN_SCRIPT} IMMEDIATE @ONLY) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) # uninstall target configure_file( "${CMAKE_SOURCE_DIR}/cmake/uninstall.cmake.in" "${CMAKE_BINARY_DIR}/cmake/uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake/uninstall.cmake) # package set(CPACK_OUTPUT_FILE_PREFIX ${OUTPUT_DIR}) set(CPACK_PACKAGE_VERSION_MAJOR ${NEKO_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${NEKO_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${NEKO_VERSION_PATCH}) set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") if (WIN32) set(CPACK_GENERATOR "ZIP") set(bin_archive_format zip) else() set(CPACK_GENERATOR "TGZ") set(bin_archive_format tar.gz) endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") if (${CMAKE_OSX_ARCHITECTURES} STREQUAL "i386") set(arch_64 "") elseif (${CMAKE_OSX_ARCHITECTURES} STREQUAL "x86_64") set(arch_64 "64") else() message( FATAL_ERROR "CMAKE_OSX_ARCHITECTURES should be i386 or x86_64." ) endif() else() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(arch_64 "64") else() set(arch_64 "") endif() endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(OS_NAME "win") elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(OS_NAME "osx") elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(OS_NAME "linux") elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(OS_NAME "freebsd") else() message( WARNING "unknown ${CMAKE_SYSTEM_NAME}" ) set(OS_NAME "") endif() set(bin_archive_name_we "neko-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-${OS_NAME}${arch_64}") set(bin_archive_name "${bin_archive_name_we}.${bin_archive_format}") set(CPACK_PACKAGE_FILE_NAME ${bin_archive_name_we}) # set(CPACK_SOURCE_PACKAGE_FILE_NAME # "neko-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-src") include(CPack) ####################### # tests include(CTest) add_test(NAME -version COMMAND nekovm -version ) add_test(NAME test.n COMMAND nekovm test.n WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) add_test(NAME nekoc COMMAND nekoc WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) if (WITH_NEKOML) add_test(NAME nekoml COMMAND nekoml WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) set_tests_properties(nekoml PROPERTIES ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) endif() add_test(NAME nekotools COMMAND nekotools WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) if (UNIX AND NOT APPLE) set_tests_properties(-version test.n nekoc nekotools PROPERTIES ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) endif() ####################### # debian source packages if(UNIX AND NOT APPLE) add_custom_target(upload_to_ppa COMMAND ${CMAKE_COMMAND} -Dsource_dir=${CMAKE_SOURCE_DIR} -Dbin_dir=${CMAKE_BINARY_DIR} -Dsource_archive=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_archive_fat_name} -DNEKO_VERSION=${NEKO_VERSION} -P ${CMAKE_SOURCE_DIR}/cmake/upload_to_ppa.cmake DEPENDS source_archive_fat ) endif() ####################### # chocolatey if(WIN32) add_custom_target(package_choco COMMAND ${CMAKE_COMMAND} -Dsource_dir=${CMAKE_SOURCE_DIR} -Dbin_dir=${CMAKE_BINARY_DIR} -Dbin_archive=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${bin_archive_name} -Dbin_archive_name_we=${bin_archive_name_we} -DNEKO_VERSION=${NEKO_VERSION} -P ${CMAKE_SOURCE_DIR}/cmake/package_choco.cmake DEPENDS package ) endif() add_subdirectory(libs) neko-2-2-0/LICENSE000066400000000000000000002155431321613172000134600ustar00rootroot00000000000000Neko Virtual Machine (neko) and Neko Tools (nekotools) ====================================================== Copyright (C)2005-2017 Haxe Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Boehm GC -------- Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. Copyright 1996-1999 by Silicon Graphics. All rights reserved. Copyright 1999 by Hewlett-Packard Company. All rights reserved. Copyright (C) 2007 Free Software Foundation, Inc THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. Permission is hereby granted to use or copy this program for any purpose, provided the above notices are retained on all copies. Permission to modify the code and to distribute modified code is granted, provided the above notices are retained, and a notice that the code was modified is included with the above copyright notice. Neko Runtime Libraries ====================== std, sqlite, mysql5, ui ----------------------- Copyright (C)2005-2017 Haxe Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. regexp ------ PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2007 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University of Cambridge nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zlib ---- Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). mysql ----- mysql.ndll uses the LGPL-licensed MariaDB Connector/C. GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! mod_neko and mod_tora --------------------- Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Neko Compiler (nekoc) and NekoML Compiler (nekoml) ================================================== GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {description} Copyright (C) {year} {fullname} This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. {signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. mbedTLS ------ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. neko-2-2-0/README.md000066400000000000000000000147211321613172000137250ustar00rootroot00000000000000![NekoVM](https://cloud.githubusercontent.com/assets/576184/14234981/10528a0e-f9f1-11e5-8922-894569b2feea.png) [![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/neko.svg?branch=master)](https://travis-ci.org/HaxeFoundation/neko) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/neko?branch=master&svg=true)](https://ci.appveyor.com/project/HaxeFoundation/neko) # Neko Virtual Machine See http://nekovm.org/ ## Snapshot Builds ### Windows Compiled binaries can be found in the "artifacts" tab of each [AppVeyor build](https://ci.appveyor.com/project/HaxeFoundation/neko/history). ### Mac Neko snapshot of the latest master branch can be built using [homebrew](http://brew.sh/) in a single command: `brew install neko --HEAD`. It will install required dependencies, build, and install Neko to the system. The binaries can be found at `brew --prefix neko`. Use `brew reinstall neko --HEAD` to upgrade in the future. ### Linux Ubuntu users can use the [Haxe Foundation snapshots PPA](https://launchpad.net/~haxe/+archive/ubuntu/snapshots) to install a Neko package built from the latest master branch. To do so, run the commands as follows: ``` sudo add-apt-repository ppa:haxe/snapshots -y sudo apt-get update sudo apt-get install neko -y ``` Users of other Linux/FreeBSD distributions should build Neko from source. See below for additional instructions. ## Build instruction Neko can be built using CMake (version 3.x is recommended) and one of the C compilers listed as follows: * Windows: Visual Studio 2010 / 2013 / 2015 / 2017 * Mac: XCode (with its "Command line tools") * Linux: gcc (can be obtained by installing the "build-essential" Debian/Ubuntu package) Neko needs to link with various third-party libraries, which are summarized as follows: | library / tool | OS | Debian/Ubuntu package | |-----------------------------------------|-------------|-----------------------------------------------------------| | Boehm GC | all | libgc-dev | | OpenSSL | all | libssl-dev | | PCRE | all | libpcre3-dev | | zlib | all | zlib1g-dev | | Apache 2.2 / 2.4, with apr and apr-util | all | apache2-dev | | MariaDB / MySQL (Connector/C) | all | libmariadb-client-lgpl-dev-compat (or libmysqlclient-dev) | | SQLite | all | libsqlite3-dev | | mbed TLS | all | libmbedtls-dev | | GTK+2 | Linux | libgtk2.0-dev | On Windows, CMake will automatically download and build the libraries in the build folder during the build process. However, you need to install [Perl](http://www.activestate.com/activeperl) manually because OpenSSL needs it for configuration. On Mac/Linux, you should install the libraries manually to your system before building Neko, or use the `STATIC_DEPS` CMake option, which will be explained in [CMake options](#cmake-options). ### Building on Mac/Linux ```shell # make a build directory, and change to it mkdir build cd build # run cmake cmake .. # let's build, the outputs can be located in the "bin" directory make # install it if you want # default installation prefix is /usr/local make install ``` ### Building on Windows Below is the instructions of building Neko in a Visual Studio command prompt. You may use the CMake GUI and Visual Studio to build it instead. ```shell # make a build directory, and change to it mkdir build cd build # run cmake specifying the visual studio version you need # Visual Studio 12 2013, Visual Studio 14 2015, Visual Studio 15 2017 # you can additionally specify platform via -A switch (x86, x64) cmake -G "Visual Studio 12 2013" .. # let's build, the outputs can be located in the "bin" directory msbuild ALL_BUILD.vcxproj /p:Configuration=Release # install it if you want # default installation location is C:\HaxeToolkit\neko msbuild INSTALL.vcxproj /p:Configuration=Release ``` ### CMake options A number of options can be used to customize the build. They can be specified in the CMake GUI, or passed to `cmake` in command line as follows: ```shell cmake "-Doption=value" .. ``` #### NDLLs Settings that allow to exclude libraries and their dependencies from the build; available on all platforms. By default all are `ON`: - `WITH_REGEXP` - Build Perl-compatible regex support - `WITH_UI` - Build GTK-2 UI support - `WITH_SSL` - Build SSL support - `WITH_MYSQL` - Build MySQL support - `WITH_SQLITE` - Build Sqlite support - `WITH_APACHE` - Build Apache modules #### `STATIC_DEPS` Default value: `all` for Windows, `none` otherwise It defines the dependencies that should be linked statically. Can be `all`, `none`, or a list of library names (e.g. `BoehmGC;Zlib;OpenSSL;MariaDBConnector;PCRE;Sqlite3;APR;APRutil;Apache;MbedTLS`). CMake will automatically download and build the specified dependencies into the build folder. If a library is not present in this list, it should be installed manually, and it will be linked dynamically. All third-party libraries, except GTK+2 (Linux), can be linked statically. We do not support statically linking GTK+2 due to the difficulty of building it and its own dependencies. #### `RELOCATABLE` Available on Mac/Linux. Default value: `ON` Set RPATH to `$ORIGIN` (Linux) / `@executable_path` (Mac). It allows the resulting Neko VM executable to locate libraries (e.g. "libneko" and ndll files) in its local directory, such that the libraries need not be installed to "/usr/lib" or "/usr/local/lib". #### `NEKO_JIT_DISABLE` Default `OFF`. Disable Neko JIT. By default, Neko JIT will be enabled for platforms it supports. Setting this to `ON` disable JIT for all platforms. #### `NEKO_JIT_DEBUG` Default `OFF`. Debug Neko JIT. #### `RUN_LDCONFIG` Available on Linux. Default value: `ON` Whether to run `ldconfig` automatically after `make install`. It is for refreshing the shared library cache such that "libneko" can be located correctly by the Neko VM. neko-2-2-0/boot/000077500000000000000000000000001321613172000134045ustar00rootroot00000000000000neko-2-2-0/boot/nekoc.n000066400000000000000000005116661321613172000147010ustar00rootroot00000000000000NEKO¨ J{@Neko_Main@IOIO@Neko_Printer neko/Printer@ListList@Neko_Binast neko/Binast@Neko_Compile neko/Compile@LexerLexer@StringString@Neko_Xmlneko/Xml@Neko_Console neko/Console@Neko_Lexer neko/Lexer@Neko_Linker neko/Linker@Neko_Docneko/Doc@SysSys@Neko_Parser neko/Parser@ArrayArray@StackStack@ArgsArgs@BufferBuffer@CoreCore@Neko_Bytecode neko/Bytecode@Sys_exit@Array_map@Neko_Printer_create@Stack_dump@IO_close_in@List_rev@Neko_Bytecode_write@Neko_Binast_parse@IO_read_string@Core_@compare@String_length@IO_close_out@Neko_Doc_to_html@Lexer_input@Neko_Compile_compile@IO_stderr@Neko_Binast_header@Core_printf@Lexer_create@Args_String@Args_Int@Core_@pcons@Neko_Printer_print@Core_Neko_error@IO_write_file@Neko_Doc_error_msg@Core_@empty@Neko_Bytecode_read@Sys_version@Neko_Xml_parse@IO_file_contents@Neko_Parser_parse@Core_None@Lexer_line@String_sub@Neko_Parser_error_msg@Args_Void@Neko_Lexer_error_msg@Neko_Console_run@Stack_exc@String_get@Buffer_create@IO_printf@Core_Some@Sys_without_dir@Neko_Bytecode_dump@Neko_Doc_parse@Lexer_null_pos@IO_read_file@Neko_Bytecode_GlobalVar@Lexer_source@Neko_Linker_link@Neko_Compile_error_msg@Core_string@Sys_without_extension@Neko_Doc_status@Args_parse   Jø Compiling %s .nš Dumping %s .dumpÞ Printing %s 2.neko' Releasing %s eŸBuilding documentation for %s .htmlÿException : %s  %s(%d): %s g/»Neko Compiler v.@ - (c)2005-2013 Haxe Foundation Usage : neko [options] files...ù : dump bytecode-d : make bytecode release-z $ : parse and print neko source-p : make documentation-doc : set output directory-o+: run the console-console5 : link bytecodes files-linkB: verbose mode-vJ: set the bytecode version-versionRneko/Main@IO@String@Buffer@Core@Core_@print_union@String_blit@Buffer_add_char@String_create@String_sub@Core_assert@Core_ord@Core_Exit@Buffer_add_sub@Core_Neko_error@Buffer_string@Core_sprintf@Core_throw@String_length@String_get@Buffer_add@Buffer_create@Core_magic@Core_chr@Core_min@Core_invalid_argOverflow Overflow«Eof¸EofClosedÃClosedBlockedÎBlocked@loadstd@Ù file_open file_contents file_close file_readfile_read_char file_writefile_write_char file_flushí&/_rbrœàã>GPwbww’¥¨«´ file_stdin file_stdout file_stderràêòIO.inputÿIO.readA IO.read_buf³} core/IO.nmlÚF  › Æ ô ý   * 8 A  IO.write_i8S  IO.outputv ¸   IO.write_ui16:  IO.write_i16e  IO.write_ui24š Ñ Ú ã ì õ þ  IO@String@List@Buffer@Core@List_iter@Buffer_string@Core_sprintf@Buffer_add_char@Core_throw@Buffer_add@Buffer_create@Core_chr@Core_invalid_arg@Core_Not_found@Core_ord@string_splitstd@string_splitA  String.getk  String.set†  String.blitŸ  String.subÇ ç   ‰ ¹ \n\t\r\\\"\%.3dÇ T:String.unescapemÙW@serialize std@serialize@unserializestd@unserializeÕÝString@List@Array@Core@Core_@pcons@Array_make@Core_@aset@Array_list@Core_@compare@Array_create@Core_throw@Core_@empty@Array_sort@Core_invalid_arg@Core_Not_found@makeö@rmake7DList.hdwList.tl¥Ó List.iter2[îX›å?•Þ"-r·ø List.chop`£ List.loopæList.nth3 a º !l!List@Array@Core@Core_@aset@Core_throw@Core_@aget@Core_Not_found[, ]”!@makeã!@merge_sortstd@merge_sortó!ø!"Y"c"r"¢"×"#.#o##´#$asubâ#$*$Array@CoreNoneSomex$NoneSome²$ Neko_error¿$Neko_errorÍ$Invalid_argumentÚ$Invalid_argumentè$Assert_failureõ$Assert_failure%Error%Error"% Stream_error/%Stream_error Not_found=%Not_foundExitK%Exit@sprintf std@sprintf@string()Y%{ __string = ; }Õ%L&@compare©&â' Array.getî' Array.set(@empty[]4(@pcons :: 8(@consP(_(b(j(y(†(“(–(ž(Core.int¦( Core.float¿(Ø(Core.chrÛ(ó(û()))%)<)S)])o:0l)Core.stream_tokenˆ)Core.stream_junký)n*nekoCore@Buffer@Core@buffer_newstd@buffer_new@buffer_addstd@buffer_add@buffer_add_substd@buffer_add_sub@buffer_add_charstd@buffer_add_char@buffer_stringstd@buffer_string@buffer_resetstd@buffer_resetr0x0‚0Buffer@Neko_Printer@IO@List@String@Neko_Astneko/Ast@Core@IO_write_char@List_iter@IO_write_string@String_make@Core_@compare@Core_None@IO_close_out@IO_write@Neko_Ast_s_constant@Core_assert@IO_printf@Core_fst66+6F6%sp6â6{;ò6 }(  ).%s,var 7while do if elsetrycatch %s function( %s return;return break;break continue $new(null)neko/Printer.nml%s => ^7%s:switch  => 8 default => :8 ÷=Å>ê>.?neko/Printer@Neko_Ast@List@Lexer@String@Core@Core_@pcons@Core_Some@Core_@print_union@List_iter@Core_None@String_escape@Core_@empty@Core_string@List_mapTrueFalseNullThisIntFloatBuiltinIdentv?TrueFalseNullThisInt@Float@String@Builtin(@Ident5@VarWhileDoIfElseFunctionReturnBreakContinueDefaultTryCatchSwitchB@VarWhileDoIfElseFunctionReturnBreakContinueDefaultTryCatchSwitch SemicolonDotCommaArrow BraceOpen BraceClose ParentOpen ParentClose BracketOpen BracketCloseConstKeywordBinopComment CommentLineAEofSemicolonDotCommaArrowBraceOpenBraceCloseParentOpenParentCloseBracketOpenBracketCloseConstòAKeywordÿABinop BCommentBCommentLine&B NormalWhileDoWhile3BNormalWhileDoWhileEConstEBlock EParenthesisEFieldECallEArrayEVarsEWhileEIfETry EFunctionEBinopEReturnEBreak EContinueENextEObjectELabelESwitchgBEConst~CEBlock‹CEParenthesis˜CEField¥CECall¶CEArrayÇCEVarsØCEWhileåCEIfùCETry DEFunction!DEBinop2DEReturnFDEBreakSDEContinueENext`DEObjectqDELabel~DESwitch‹DŸD§D·DÇDâDôDEE*E=E|EE©E¡HÓHàHöHtruefalsenullthis"$CKvarwhiledoiffunctionreturnbreakdefaultcatchswitchµK=>/**///Lneko/Ast@Lexer@IO@List@String@LexEngine LexEngine@Core@Core_Some@List_array@Core_@print_union@String_blit@IO_input@String_create@Core_None@LexEngine_make_tables@String_sub@Core_assert@Core_fst@Core_@aget@Core_max@Core_Exit@Core_Neko_error@LexEngine_determinize@IO_read_string@Core_snd@String_length@String_get@Core_throw@LexEngine_parse@Core_@empty@Core_min@Core_invalid_arg@List_map Invalid_rule¾LInvalid_ruleÉLÖLÚLÞLM=MAMHM…M¤M¨M›NÈN*O‰Ocore/Lexer.nmlOPPQ‰QLexer.empty_tableÀQÉQLexer@LexEngine@List@HashtblHashtbl@Array@String@Core@List_array@Array_make@Core_@print_union@List_iter@Array_map@Hashtbl_find@Core_None@Core_assert@Array_sort@List_mem@List_filter@Core_fst@List_rev@Core_compare@Array_iteri@Core_@aset@Core_@compare@Array_iter@String_get@String_length@List_exists@Array_init@Core_Some@List_fold@Core_ignore@Hashtbl_add@Core_@aget@Core_ord@List_assoc@Core_@pcons@List_concat@Core_Neko_error@List_sort@Core_snd@Array_length@Core_throw@Core_@empty@List_map@List_append@Hashtbl_createEmptyMatchStarPlusNextChoiceóQEmptyMatchTRStaraRPlusnRNext{RChoiceŒRRcore/LexEngine.nml¬R›STtTT¡T±T¼TçTöTU%V?V|VWW.WQWhWyWùWX,XÎX8Y\InvalidRegexpI\V\r\˜\³\À\W]]Ã]ü]^\_LexEngine@Hashtbl@Core@Core_throw@Core_Not_foundÜ`ä`í`õ`a"a1a@aTaHashtbl@Neko_Binast@IO@Lexer@Array@Neko_Ast@Core@IO_read_byte@Neko_Ast_ETry@Core_None@Array_create@Core_assert@Neko_Ast_Builtin@IO_read_ui16@Neko_Ast_True@Neko_Ast_EConst@Core_fst@IO_read_i32@Neko_Ast_String@Neko_Ast_ESwitch@Neko_Ast_EFunction@IO_read@Neko_Ast_EBlock@Neko_Ast_NormalWhile@Neko_Ast_DoWhile@Neko_Ast_EObject@IO_read_ui24@Neko_Ast_EVars@Neko_Ast_EReturn@Array_get@Neko_Ast_EBinop@Neko_Ast_ELabel@Neko_Ast_Ident@Neko_Ast_EContinue@Neko_Ast_ENext@Core_Some@Array_add@Neko_Ast_EArray@Neko_Ast_EWhile@Neko_Ast_EIf@Neko_Ast_False@Neko_Ast_Int@Neko_Ast_This@Neko_Ast_Float@Neko_Ast_EParenthesis@Neko_Ast_Null@Core_@pcons@Neko_Ast_EField@Array_length@Neko_Ast_ECall@Core_@empty@Neko_Ast_EBreak@Core_errorneko/Binast.nml+lNBA7l€lInvalid const tag : ³l+-*%<<>>>>>|&^==!=>>=<<==&&||++=--=+=-=/=*=%=<<=>>=>>>=|=&=^=Invalid op tag \m…n›nµnên oInvalid expr tag : #oInvalid binast headerÎrneko/Binast@Neko_Compile@Hashtbl@List@Lexer@Array@MapMap@String@Neko_Ast@Neko_Bytecode@Core@Neko_Bytecode_op_param@Neko_Ast_Builtin@Neko_Bytecode_SetIndex@Neko_Bytecode_trap_stack_delta@Neko_Bytecode_GlobalFloat@List_rev@Neko_Bytecode_Mod@Neko_Bytecode_Bool@Neko_Bytecode_Apply@Neko_Bytecode_MakeEnv@String_length@Array_iter@Neko_Bytecode_SetGlobal@Neko_Bytecode_Lte@Neko_Bytecode_Neq@Neko_Bytecode_AccIndex0@Array_set@Neko_Bytecode_AccIndex1@Neko_Bytecode_Or@Hashtbl_length@Core_Neko_error@Neko_Ast_EField@Core_snd@Neko_Bytecode_Not@Neko_Bytecode_GlobalString@Neko_Bytecode_AccEnv@Neko_Bytecode_SetThis@Core_@empty@Neko_Bytecode_ObjCall@Neko_Bytecode_Jump@List_length@Array_make@Core_@print_union@Neko_Bytecode_AccInt@Core_assert@String_sub@Array_sort@Neko_Bytecode_New@Neko_Bytecode_Pop@Neko_Bytecode_JumpTable@Neko_Ast_Ident@Array_add@Neko_Bytecode_PhysCompare@Neko_Bytecode_AccGlobal@Neko_Bytecode_Div@Neko_Bytecode_Ret@Hashtbl_add@Neko_Bytecode_Xor@Core_Exit@Neko_Bytecode_GlobalVersion@Neko_Bytecode_TypeOf@Array_length@Neko_Bytecode_SetField@Neko_Bytecode_Lt@Array_append@Neko_Bytecode_JumpIf@Neko_Bytecode_AccThis@Map_iter@Hashtbl_create@Neko_Bytecode_JumpIfNot@List_iter@Neko_Bytecode_SetEnv@Map_find@Map_add@Neko_Bytecode_Hash@Array_map@Neko_Bytecode_EndTrap@Neko_Ast_EConst@Neko_Bytecode_AccStack@Hashtbl_exists@Neko_Bytecode_Shl@Core_@aset@Core_compare@Neko_Ast_EBlock@Neko_Bytecode_GlobalDebug@Core_@compare@Neko_Bytecode_SetArray@Neko_Ast_EVars@Neko_Ast_EBinop@Neko_Bytecode_Eq@Neko_Ast_EIf@Neko_Bytecode_AccTrue@Core_ignore@Neko_Bytecode_Gte@Neko_Ast_Int@Neko_Bytecode_Sub@Core_@pcons@Neko_Bytecode_TailCall@Core_sprintf@List_sort@Core_throw@Neko_Ast_ECall@Neko_Bytecode_Mult@Map_empty@Neko_Bytecode_AccField@Neko_Bytecode_AccIndex@Hashtbl_iter@Neko_Bytecode_Shr@Hashtbl_find@Core_None@Array_create@Neko_Bytecode_UShr@Neko_Bytecode_IsNotNull@Core_fst@Neko_Bytecode_AccFalse@Neko_Bytecode_AccNull@Neko_Bytecode_Push@Neko_Bytecode_SetStack@Neko_Ast_iter@Neko_Bytecode_MakeArray@Neko_Bytecode_AccArray@Neko_Bytecode_Compare@Neko_Bytecode_AccBuiltin@Neko_Bytecode_Call@Core_Some@Neko_Bytecode_IsNull@Neko_Ast_This@Lexer_null_pos@Neko_Bytecode_And@Neko_Bytecode_GlobalVar@Neko_Bytecode_AccStack0@Neko_Bytecode_Add@Neko_Bytecode_AccStack1@Neko_Bytecode_Loop@Neko_Bytecode_GlobalFunction@Core_string@Neko_Bytecode_Trap@List_map@Neko_Bytecode_GtXEnvXStackXGlobalXFieldXIndexXArrayXThis*uXEnv™uXStack¦uXGlobal³uXFieldÀuXIndexÍuXArrayXThisÚuErroråuöuvvStack alignment failureâw÷wxÀxÿxyByiyy¯yÓyëyNz‹z—z²z¾zBreak outside a loopðzContinue outside a loop{{array2{Q{°{!|@|apply_|~|0Variable declaration must be done inside a block|neko/Compile.nmlæ|#}2Label is not supported in this part of the programDuplicate label =}}tnulltinttfloattbooltstringtobjecttarray tfunction tabstract^„Invalid access;‡+‰Ó‰Unknown operation”Š5Œ]”‚””²”istruenottypeofhashnewcomparepcomparegotoUnknown label –q–›–throwß–Invalid $goto statement—aconcat¡—º—Ó—ì—˜.žcall$tmpŸ!Ÿ:ŸŸŸÉŸ o:G Label failure %d %d %s %s€ ‡ ¢ ¯ Í Р¡"¡d¡¡¤¡_ñ¯3°C°S°|°½°neko/Compile@Map@Core@Core_compare@Core_@print_union@Core_@compare@Core_throw@Core_assert@Core_Not_found@Core_invalid_arg@Core_maxNodet²EmptyNode¨²²ë² core/Map.nml³*µMap.remove_min_bindingƒµôµD¶L¶U¶e¶!·T·Æ·í·¸±¸¹:¹¹®¹ºBºšºMap@Neko_Bytecode@Hashtbl@IO@List@Array@String@Buffer@Core@Array_make@IO_read_byte@Core_@print_union@List_iter@Array_create@Hashtbl_find@String_make@IO_write_i32@Core_assert@IO_read_ui16@IO_read_i32@Array_iteri@Core_@aset@IO_read@IO_write_ui16@IO_write_string@Array_iter@String_length@Buffer_create@Core_invalid_arg@Array_get@IO_printf@IO_read_char@Array_init@Array_add@IO_write_char@Buffer_add_char@Array_set@IO_write_byte@Hashtbl_add@IO_write@Core_@aget@Core_@pcons@Core_Neko_error@Buffer_string@Core_sprintf@String_escape@Array_length@Core_throw@Core_@empty@Core_string@Core_error@Hashtbl_createAccNullAccTrueAccFalseAccThisAccIntAccStack AccGlobalAccEnvAccFieldAccArrayAccIndex AccBuiltinSetStack SetGlobalSetEnvSetFieldSetArraySetIndexSetThisPushPopCallObjCallJumpJumpIf JumpIfNotTrapEndTrapRetMakeEnv MakeArrayBoolIsNull IsNotNullAddSubMultDivModShlShrUShrOrAndXorEqNeqGtGteLtLteNotTypeOfCompareHashNew JumpTableApply AccStack0 AccStack1 AccIndex0 AccIndex1 PhysCompareTailCallLoop¼AccNullAccTrueAccFalseAccThisAccInt¯¿AccStack¼¿AccGlobalÉ¿AccEnvÖ¿AccFieldã¿AccArrayAccIndexð¿AccBuiltiný¿SetStack ÀSetGlobalÀSetEnv$ÀSetField1ÀSetArraySetIndex>ÀSetThisPushPopKÀCallXÀObjCalleÀJumprÀJumpIfÀJumpIfNotŒÀTrap™ÀEndTrapRet¦ÀMakeEnv³ÀMakeArrayÀÀBoolIsNullIsNotNullAddSubMultDivModShlShrUShrOrAndXorEqNeqGtGteLtLteNotTypeOfCompareHashNewJumpTableÍÀApplyÚÀAccStack0AccStack1AccIndex0AccIndex1PhysCompareTailCallçÀLoop GlobalVarGlobalFunction GlobalString GlobalFloat GlobalDebug GlobalVersionøÀGlobalVarYÁGlobalFunctionfÁGlobalStringwÁGlobalFloat„ÁGlobalDebug‘ÁGlobalVersion¢Á Invalid_file¯ÁInvalid_fileºÁ¾ÁField hashing conflict  and öÄßÄNeko.Bytecode.write_debug_infosOÅdÅéżÆNEKO€Ç~È“È{ÌÍ2ÍNeko.Bytecode.read_debug_infos[ÍNeko.Bytecode.loopdÍ¿ÎkÏÐneko/Bytecode.nml•жМÑÜÑnglobals : %d  nfields : %d codesize : %d ops , %d total  GLOBALS =  global %d : %s  function  nargs string "float debug %d ops %d bytesversion Ö× FIELDS =  %s%s%.8X ÑØCODE = Ù%.6X %6d %s  AccField  AccBuiltin  SetField ÙEND ëÛneko/Bytecode@Neko_Xml@List@Lexer@String@Neko_Ast@XmlXml@Core@List_iter@String_split@String_concat@Neko_Ast_Builtin@Neko_Ast_EConst@Neko_Ast_True@List_rev@Neko_Ast_String@Neko_Ast_ESwitch@Neko_Ast_EBlock@Core_@compare@Xml_attrib@String_unescape@String_length@Neko_Ast_EVars@Neko_Ast_EBinop@Neko_Ast_EWhile@Neko_Ast_EIf@Neko_Ast_Int@Neko_Ast_Float@Xml_Node@Neko_Ast_Null@Core_int@Core_@pcons@Core_Neko_error@Neko_Ast_EField@Neko_Ast_ECall@Core_throw@Core_@empty@Xml_node_text@List_append@Xml_node_name@Core_@print_union@Neko_Ast_ETry@Core_None@Core_assert@String_sub@Xml_firstNode@Neko_Ast_EFunction@Neko_Ast_NormalWhile@Neko_Ast_DoWhile@Neko_Ast_EObject@String_get@Neko_Ast_EReturn@Neko_Ast_s_constant@Core_invalid_arg@Neko_Ast_ELabel@Xml_nodes@Neko_Ast_Ident@Neko_Ast_EContinue@Neko_Ast_ENext@Core_Some@Neko_Ast_EArray@Xml_parse@Neko_Ast_False@Neko_Ast_This@Neko_Ast_EParenthesis@Lexer_null_pos@Neko_Ast_EBreak@Core_string@List_mapôèErrorÿè neko/Xml.nml ép:éNeko.Xml.errorê'êifsvbgcaonextobjectlabelneko–ê ëë&ë4ëcaseQëUnknown node name : WìNeko.Xml.parseùòOó±óìó+ôCûneko/Xml@Xml@List@IO@String@Buffer@Core@Core_@print_union@List_iter@List_find@IO_write@String_concat@List_filter@List_hd@String_lowercase@Buffer_string@IO_write_string@Core_snd@String_escape@Buffer_add@Buffer_create@Core_invalid_arg@IO_printf@List_mapPCDataCDataDocumentlûNode±ûPCDataÅûCDataÒûDocumentßûìûError÷û@parsero:0üü*üŒüÊü@parse std@parse_xmlöü>ýTýjý Xml.firstNode€ý Xml.nodesÉý Xml.node_nameþ Xml.node_text6þ†þÆþ Xml.attrib×þ<%s%s="ÿ/> 7ÿXml@Neko_Console@IO@Hashtbl@Neko_Compile@Lexer@Neko_Parser@Array@String@ReflectReflect@Stack@Neko_Lexer@Buffer@Neko_Bytecode@Core@Neko_Parser_parse@IO_input@Reflect_module_get_global@Hashtbl_find@Lexer_line@Stack_dump@Core_nprint@String_sub@Neko_Parser_error_msg@IO_close_in@Core_fst@Reflect_neko_value@Hashtbl_replace@Neko_Lexer_error_msg@Neko_Bytecode_write@Reflect_module_read@Array_iteri@IO_write_string@IO_read_all@IO_read_string@Reflect_module_set_global@Stack_exc@String_length@String_get@Buffer_add@Buffer_create@IO_stderr@Core_print@Lexer_input@Neko_Compile_compile@IO_printf@Buffer_add_char@Lexer_create@Lexer_source@IO_read_file@Reflect_module_execute@Buffer_string@Core_Neko_error@IO_stdout@Neko_Compile_error_msg@IO_read_line@Neko_Bytecode_read@IO_stdin@Hashtbl_createÚ<h> #load @console‰  Exception : ì¹neko/Console@Neko_Parser@IO@Neko_Binast@Lexer@Neko_Xml@Neko_Ast@Neko_Lexer@Buffer@Core@Core_@print_union@Core_stream_junk@Neko_Ast_ETry@Core_None@Neko_Ast_Keyword@Neko_Ast_Default@Core_stream@Neko_Xml_parse_string@Lexer_punion@Neko_Ast_EConst@Core_fst@Neko_Ast_ESwitch@Neko_Ast_EFunction@Neko_Ast_NormalWhile@Neko_Ast_DoWhile@Neko_Ast_EBlock@Core_Stream_error@Core_stream_pos@Neko_Ast_EObject@IO_read_string@Neko_Ast_s_token@Neko_Ast_EVars@Neko_Ast_EReturn@Buffer_create@Lexer_input@Neko_Ast_EBinop@Core_stream_token@Neko_Ast_ELabel@Neko_Ast_pos@Neko_Ast_EContinue@Neko_Ast_Ident@Core_Some@Neko_Ast_EWhile@Neko_Ast_EIf@Neko_Ast_EArray@Lexer_create@Neko_Ast_Int@Neko_Ast_EParenthesis@Lexer_null_pos@Neko_Binast_parse_from_string@Core_@pcons@Neko_Ast_Eof@Neko_Ast_EField@Core_Neko_error@Core_snd@Core_throw@Neko_Ast_ECall@Neko_Lexer_expr@Core_string@Core_@empty@Neko_Ast_EBreak@Lexer_token UnexpectedUnclosed Invalid_nxml–UnexpectedÍUnclosedÚInvalid_nxmlçôErrorÿ Unexpected  Unclosed Invalid nxml (Xgh p  : Z B˜-!""˜#½%Ö&g'æ'›)"*‚* +neko/Parser@Neko_Lexer@Hashtbl@List@Lexer@String@Neko_Ast@Buffer@Core@List_iter@Neko_Ast_Default@Neko_Ast_Keyword@Neko_Ast_Semicolon@Neko_Ast_BraceOpen@Neko_Ast_Function@Neko_Ast_ParentOpen@Neko_Ast_BracketClose@Neko_Ast_Builtin@Lexer_punion@Neko_Ast_True@Lexer_char@Neko_Ast_String@Neko_Ast_Return@Neko_Ast_Continue@Neko_Ast_While@Lexer_current@String_length@Neko_Ast_BracketOpen@Core_chr@Neko_Ast_Try@Neko_Ast_Int@Neko_Ast_Float@Neko_Ast_BraceClose@Neko_Ast_ParentClose@Neko_Ast_Null@Buffer_reset@Core_@pcons@Core_int@Core_sprintf@Core_Neko_error@Neko_Ast_Switch@Lexer_build@Core_throw@Neko_Ast_Do@Core_@empty@Neko_Ast_Binop@Neko_Ast_s_keyword@Core_@print_union@Hashtbl_find@Neko_Ast_Dot@Neko_Ast_Arrow@String_sub@Neko_Ast_If@Neko_Ast_Else@Neko_Ast_Catch@String_get@Buffer_add@Neko_Ast_Ident@Buffer_add_char@Neko_Ast_Break@Neko_Ast_Const@Neko_Ast_False@Neko_Ast_This@Hashtbl_add@Lexer_empty@Neko_Ast_Comma@Core_ord@Neko_Ast_Comment@Core_Exit@Lexer_data@Neko_Ast_Eof@Buffer_string@Neko_Ast_Var@Neko_Ast_CommentLine@Lexer_token@Lexer_curpos@Hashtbl_createInvalid_characterUnterminated_stringUnclosed_comment Unclosed_nxmlInvalid_escaped_characterInvalid_escape^+Invalid_character¿+Unterminated_stringUnclosed_commentUnclosed_nxmlInvalid_escaped_characterÌ+Invalid_escapeÙ+Errorä+Invalid character '%c'Invalid character 0x%.2XUnterminated stringUnclosed comment Unclosed nxmlInvalid escaped character %dInvalid escape sequenceõ+v,‹,ž,ª,È,á,[a-zA-Z_@][a-zA-Z0-9_@]*[-!=\*/<>&|^%\+:]9-E-Q-]-Continueh-u-€-‹-–-¡-¬-·-Â-\[Í-Ø-ã-[ ]+0x[0-9a-fA-F]+[0-9]+ [0-9]+.[0-9]*.[0-9]+ï-#.3.C.S.c.k.é./\*b/ //[^ ]* ?«/?¿/Ó/ã/ó/60\*/90\*S0[^*]+m0v0\\"Œ0\\\\¢0\\n¸0\\tÎ0\\rä0\\[0-9][0-9][0-9]+16191[^\\"]+S1\1i1„1[^<]+ž1neko/Lexer@Reflect@List@Core@Core_@print_union@Core_magic@Core_invalid_arg@List_mapVNullVIntVFloatVBoolVStringVObject VAbstract VFunctionVArrayÃ<VNullVIntN=VFloat[=VBoolh=VStringu=VObject‚=VAbstract=VFunctionœ=VArray©=@module_readstd@module_read@module_namestd@module_name@module_exportsstd@module_exports@module_loaderstd@module_loader@module_execstd@module_exec@module_nglobalsstd@module_nglobals@module_global_getstd@module_global_get@module_global_setstd@module_global_set@module_code_sizestd@module_code_size@module_read_pathstd@module_read_path Reflect.value¶=¿=[>í>õ>???-?f?n?{?ˆ?•??¬?Ä?Reflect@Stack@IO@Array@Core@Core_@print_union@IO_stdout@Array_iter@IO_write@IO_printf CFunctionModulePosöACFunctionModule-BPos:B@make_stackKB³B¾BCalled from a C function $Called from %s (no debug available) Called from %s line %d ÉBC,CStack@Neko_Linker@Hashtbl@IO@List@Array@Neko_Bytecode@Core@Array_make@Neko_Bytecode_JumpIfNot@Array_list@List_iter@Neko_Bytecode_op_param@Core_None@Array_map@Hashtbl_find@Array_create@Core_assert@IO_close_in@Hashtbl_replace@Core_Error@Neko_Bytecode_write@Neko_Bytecode_AccNull@Neko_Bytecode_GlobalDebug@Core_@compare@Neko_Bytecode_Push@IO_close_out@Core_print@Array_index@Array_get@Neko_Bytecode_SetGlobal@Core_Some@Neko_Bytecode_AccBuiltin@Neko_Bytecode_Call@Array_add@Neko_Bytecode_AccGlobal@Array_set@Core_ignore@Hashtbl_add@Core_@aget@IO_read_file@Neko_Bytecode_GlobalVar@Core_@pcons@Neko_Bytecode_GlobalVersion@Core_Neko_error@Core_snd@Core_throw@Array_length@Array_append@Core_@empty@Neko_Bytecode_JumpIf@Neko_Bytecode_GlobalFunction@IO_write_file@Neko_Bytecode_read@Neko_Bytecode_Jump@Neko_Bytecode_Trap@Hashtbl_createFile not found : (E™EÄE&Linking modules with different version6GQGiG¿Gneko/Linker.nmlloader loadmoduleRecursive loading Cannot link not constant fileexportsöGèK,LYL OOneko/Linker@Neko_Doc@IO@List@Lexer@String@Xml@Buffer@Core@Core_@print_union@Core_stream_junk@List_iter@Core_None@Core_stream@String_split@Lexer_punion@String_concat@Lexer_char@Core_fst@Core_Stream_error@Core_stream_pos@Lexer_current@Buffer_add@Buffer_create@Core_stream_token@IO_printf@Core_Some@Xml_parse@Buffer_add_char@Xml_to_string@Lexer_empty@IO_write@Lexer_null_pos@String_escape_char@Buffer_reset@Core_Exit@Core_@pcons@Lexer_data@Core_int@Core_Neko_error@Buffer_string@Lexer_build@Core_snd@Core_throw@Core_string@Core_@empty@Lexer_token@Lexer_curposTBase TAbstractTCustomTFunTOptTStarTMultTObjTNamedTPoly TFunction5QTBaseÜQTAbstractéQTCustomöQTFunRTOptRTStar!RTMult.RTObj;RTNamedHRTPolyYRTFunctionjRwRFunction«RDocument¿RBeginEndQuestion DoubleDotPOpenPCloseBrOpenBrCloseFieldQuoteSharpDocÌREofBeginEndStarQuestionArrowDoubleDotPOpenPCloseBrOpenBrCloseCommaFieldOrQuoteSharpIntãSDocðSIdentýS Invalid_char Unknown_type Unclosed_doc Invalid_doc TUnexpected]TInvalid_charjTUnknown_typewTUnclosed_docInvalid_doc„TErrorT T/****/->'#¯TInvalid character  Unknown type Unclosed doc tag Documentation is not XHTML validOUŸU«U·U/\*\*ÌUØU[^/]+äUïU\*\*/VVV%V0V;VFVQV\VgVrV\?}VˆV“V>W[ ]+JWcW$?[a-zA-Z_@][a-zA-Z0-9_@]*wW¿WÂWÝWüWX YUZ·Zintfloatstringboolanyvoidnumber [list®_pa.b1cWc'%s#%s ->  | Óc?d%s :  %s function:%dådf  »f äf' %s :  . %s(-g  —gineko/Doc@Sys@List@Array@String@Core@Array_make@Core_Some@String_split@Core_None@String_concat@Core_assert@List_rev@sys_exit std@sys_exit@get_env std@get_env@get_cwd std@get_cwd@exe_pathstd@sys_exe_path@sys_file_typestd@sys_file_type@sys_read_dirstd@sys_read_dir–pùp\ core/Sys.nmlCq•q£qstd@sys_exists«q std@put_envÆq std@set_cwdÌqdirÒqÞqSys@Args@List@Sys@Hashtbl@Array@Core@Sys_exit@Core_int@Core_@print_union@List_iter@Core_Neko_error@Hashtbl_find@Array_length@Core_throw@Core_print@Hashtbl_add@Sys_args@Core_@aget@Core_printf@Hashtbl_createVoid€sVoid·sStringÄsIntÑsInvalidÞsInvalid Options :  %s %s ést"t-help--help.tDtInvalid argument : MtvArgs6neko/Mainneko/Main.nmlIOcore/IO.nmlStringcore/String.nmlListcore/List.nmlArraycore/Array.nmlCorecore/Core.nmlBuffercore/Buffer.nmlneko/Printerneko/Printer.nmlneko/Astneko/Ast.nmlLexercore/Lexer.nmlLexEnginecore/LexEngine.nmlHashtblcore/Hashtbl.nmlneko/Binastneko/Binast.nmlneko/Compileneko/Compile.nmlMapcore/Map.nmlneko/Bytecodeneko/Bytecode.nmlneko/Xmlneko/Xml.nmlXmlcore/Xml.nmlneko/Consoleneko/Console.nmlneko/Parserneko/Parser.nmlneko/Lexerneko/Lexer.nmlReflectcore/Reflect.nmlStackcore/Stack.nmlneko/Linkerneko/Linker.nmlneko/Docneko/Doc.nmlSyscore/Sys.nmlArgscore/Args.nml{"@Øf>fàŽ>àjR>Z>b>Z>b>Z>¢$Z>>†v>>J>4^r>N2tv^j>Nf*$vf^Z>Nf*$v^>Jz*L>¦–ÞØvfv^4 ø<>Jz*$vfr>N^^>Nf*$zz¾>>F&$Z>>vžT^bbb>Njvbâ>fv>"Ð" 0>bnn.D>„>>>n&>>>Jj*6<>F*t~~>Vr–€~rr`RD.< x>´b& Zj.*D>F*D~ŽŽÎ&€Ú$Š&T6œF p<$2$^>>j>$v^’^VVb>Jzr¾,v^’^VVJf>J>rr>†à>"T~:à>ŒZNJN>–*x>"4x>\ZJNbz¶:Ø>"DØ>lZ^bb>:$Z^2$Z^b>$Z^fnž,bf&8ZZZ"TŠ ¨ ˜D"$> $>V:$^>>j>$Rfb>Jzr>,^rr:$>Vb:$>V^¾*$>Vbr:$",bff&È ZZZZ"$> " èZN^n¦Dbv$>&$>>&$vv$vv<>Z€¶&€>$fj>€phŽ>TV*$6$>>z – Ö $,&4>6<*tn¦>>>b*˜–*˜Ö*˜$&˜,&˜&4>>˜6<*˜L2phŽ>>„&$Z^VVb>’r>Fr>>>>>>>>>>>>>>>>D6hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hT6hŽ:h46h$6h´h@ô>@@f¶>,ZvV>Jbr>>r>†$ZvV>Jbr>>r>†L$* "PÈNZ>$NN>î6,>ZHŽ> H<>Z&€Ž€<>Z&¸Ž¸<>Zð¢>>ð<>Z(¢>&(<>šnp–p`"<>^&˜âj>˜&`Œ>Z&èþz>>.èL>Z0¢>:0<>Zh¢>>h<>Z& ¾>>& <>Z&ؾ>>Ø<>Z&¢>:<>ZH¢>:H<*$>Z ¢>> <>ZØ¢>>ØD>Zâ>.N><2$ZN>^&xŽ>x<>Z°â>:°D>Zðâ>:ðL>Z&8â>>8(N:Z¢>>>d>Zðâv>ðÈ>Z"Èâ>ØŽ>Df.È”Zf*"ÈÈJNVN^>V^^ªb4><$6,JVn>F>Ržb:,&$:,ZN^b¦:4ZN^v¦:4NNV^j6F¦:4>4NVV^^>–4NNV^z6N>.4>4NVN^>^Nî&"X >>>>*<>n>r>>F>rzz:ÜžN>V^NbN^>J^^ªbÚ*$ZNNrZ^^^ª>>F²b$Z^RNb^>J^^ªb"$nRfbbZZNR>FbžN^>z^N®šfJR>FbžbN^Z~>>N^N²šêò>Fj$~jîR>¦>D $$:$2$òÎNÖN$Zv$Zv$ $>V$$$2$$2$>$>$&$:$RZZ.,¶^RNjr>V^z¦Z.,¶fv^>®fZ^f6<X >¼ >>,>J>N>N>N>N>N>¼º¼”„xš44bRÒ^^Þ$ $$$$Ê$ $44 $, $ $$ $ $ $ $ $&$ D””>>>>>>>>>>>>>6¼ ”Þ~Þ$$ t $ $dd d dt 4 ldD 4>>>>>>>> >>>>:Ä44ZÞ>< < <>>>.<><>Œ>L><><><><:<6<$>>*<><>\>L:D6D d> <”>>>>>>>>>>>*  "˜($&$¼$z~~~~>$ $ $ ,JN>>> >>>>:ÄúdJŽ4 $ $ 4 4Š< „ $&d6¬6x*l*tzþ$>>>>>>>>> >>>>>>>>>¼4<>J>N>N><,jnnnnnn®:D&, ´>L&, „rv¶bb"< D $ $ 4 ” Äl tD4<T \ L $ $, 4 \<4D< $ D>>>>>>>>>>>>>>>>>>>>>>"8J N"$V>^–&$>ZжÐ>$V~>*Ð\>dVZj&ìVz>^˜Îj2˜À>Z2À>Ö~ZÀ>2 ÀÄVZjfZ6@Vn>>>š>"P$ff> 4€¬fZ:PÌV>PäVj>F>PXVjZ>P€f>"D ˆLf.P>>èfZ>P"frjZ> P28f^>n>^PÎj>P&P2ˆfv~>P°f>nj>P2ØR>zv~v>>&P>.P f:P>8.PHfº2PpVj^2P&˜&P&¨f& Î>>|Rf>PP> P2`f^j^> 4 €<>Z¸ÎjfZ>¸Df>P Z>ª>F> (&,~jfrf*(&db>Jz&(¼nZj&È>Ž> 4ØÈ&T.È|r^f^*>!"# È>>>>>>>>>>>>>"d>>>>>>>>>>>>:„>>>>>>>>>>>>>>>>>>>>œ>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>2Ä,>$>$>.$> $> $> $> $>\V>^ Ž>  &l>R>*Xä`>>>Ü`N>`Ž>`Þ>`$>2`,>"`<,˜2`2l>>`2t>>>>>`2|>>`„>`2Œ>>`>2”>L`>2œ>D.`¤>"`¬>4`2´>>>>>.`ˆ>>>Lr>PV>>> ¬ XN6XŽ*XÞ2X$>X,> X4> X<> X2D>>>>XL> XT&X\> X>2d&LX>2l&D&Xt> X|> 4 X2„>>>>2XÔ>nRRR(,&(4(<> (D"(L(t>>RRRRRRRRRRRRR˜”>>jRRRRRRRRRR(d&(l&(t(|2(„"(%"'ˆ >"$N,J~>èD $J^NŽhŠNbNN@8Œ$$Z^ff^^^"fzzVºf>fVZ>nv¾vrr$Z^rV:,Fbvvf2Ð>"<Ð:´>Fn^^^^šz>ÒRR^^V>N>Ž’vf>^vfvVb>V²X^bb"P,>> d>ÌFj: >>,br>† \ >lZ®>$>>>>^>ÆJX>)"+h @>>>>>>>>>>>Œ:$~èº è>>>>$^>>Z>>^².è>*T&è„>Z>> h¾>>>hXN>4>v2>Š.<>&$>DJ &<>nŽ>&$:,>†>šÈ$^>^ÈD^j>vÈl^j>vÈ”>"Ȥ^>>>F&ÈÌ>*°R¨Î>Ô>"D>>>’>>>>*Ð>âÐ>R>b> @¶>¾>^>Xæ>>4>"$>.¸Ž>D~Ž &¸Œ>"L>âþ^f>.dF:(>"$Nrv>R(:d\>ˆfJ:>"$Nrvz^r>F>>J>„>ž2$>>>ª>0Rž8Î:èZ^^VVVV:à¤>> ŒR>Jr>J<>V*DjRb>Z> j*4 ¨<,jRn޾>JZ>øf:Dz®HÒ.4>â^>$>>>J> $2$fn>>>:<( <( <( <( <( <( <( D( l>J: ® <>J:È ®È <>J: ®& fN^>f>^>. þ~r>  D>V>f>.X Î^>>X p RVbbrr>>~6  –6  Ö6  ,À Ž>>Ìn^r>žv>"  Ð >>  Ø >*  ð -"/ØÐ$"$$vn$:$:$:$>$*>¼ $ $ $ 4 $ $ $ $>>>>-+>>>>>>>>>>>>>>>>>ä4>>>>>>\ŠN>’$> |l&$&4 D><:$¸>à.˜ dœ>Š,*, $|>6<:<6< <>>>>>>>>>>>>>>)'>>>>>>>>>>:¼<„4>ŠºNŽL œ $ $ d L $ Ä L"d,*8 T>>>>>>>:%#>>>>¼>>>>>>>>>d>>>>>>>>>>>>>„>>>>>>>>>>>>>>>>œ>>,>>>>>>>>>>>>>>>>>>>´ŠŽ$ $ $ $ $ $ $ $ ü Ô t ”>>>>>>>&!>>>>>¼4 D ,, D>\$>>* >¤2|>>>>6"1"3 .,^^bnj–>&$Z’b>> ,>>R ÈŽ ÈÎ È$È,.È4.È<*ÈD*ÈL*ÈT*È\.È„>>>>>V HŽ HÎ H$H,H4H<HDHLHTH\HdHlHtH|H„HŒH”HœH¤H¬H´H¼HÄHÌHÔHÜHäHìHôHüHHHPHX.H€Z>4^b*¨^.$ °,b> $r’:^b*8^^>Vf>J²x>>>>ž2x$>&x4>&xD2xTb>xlb>:x„b> xœ6,>&xÔbf6xôbf6xˆbf>x¨bb>xÈ>R> xà^ff>xx> x(x8> xHxXbf*xx>"xˆ>"x˜.x¨>x¸>xÈ>J> xàb>:xø.x&8Z 0$>^*>>>>>>>>>>>>>>>>>>>:¼ 4’Ž\> L„ x>>,>\6<>>" >>>>>215"7ø Ø>>>>>>>>>>>*`>ò>$ $>>>>>>>>>À>>¤À>¬NhÀ¼¸€"¸ˆ"¸2À.äN"À¸˜"¸˜"À.œ>>>>À¬À.¸ˆ"À>œ¸ˆ"À¸Ð>$&$f>>V>ÎJ>8>ânz>J86D^> ,>Fv>Z2<>>àZz>L>>" Zz>L>>`Zz>4>"$JJ>È>"$bzrÈ>dNRVVf^^>$.xVn*$. >FnZZ*$~>à~>$>>,V>z^z8>$8(R< 0LZz>>j>F>À r>,~>T~>H ~>0 J>^8 Ž>8 $>ÌJ>n( $( $( 4( € V>TVv>Fv>¸>>>€ > R>Z*€ >,>¸>>>:¨ b>Fú ¸ $>’ú è $~>¸>6 Z>¸>>>@ ö @ $~>¸>>@ ö @ $~>&¨ >¸t>R:40 € >>>¸Ø r>^>Fv>>>jv>F>¸ž^V^v>Fv:¸> N:TZ>F>Fv>F>"¸.¨ >€ >>>>"¸8 >F>"¸x rº € Î> ¸´R>¸>Äv>¸>ìfVN˜ 4>¸>>>¨ ^>>>¸>> À ~>>>~v>, Ø 4>Z Ž> $>¸Ð >nrrr2Ð ,> Ð 4>>Ð <>>Ð L>>>>r> –> Ö> $: ,: 4: <: D: L: &\> Ð ¼FvfJ>  >âVv>V  6D>Šb>>:ˆ >"Œ~>ˆ >Ð H>>>²JvfJ>p>âVv>Vp6D¦2X>"|~"X2H`H> ¬rjH>>>ÌrjH>"ìrjvj H&p:H˜>n>˜Ž>*˜Î>˜$> ˜,>Š2È.˜d>n>øŽ>*øÎ>ø$> ø,>Êj~2(.ø|>>>>>>>>b*p–*pÖ*p$&p,&p4&p<&pD&pL&pT&p\&pd&pl&pt&p|&p„&pŒ&p”&p¼>>>>>>>>Šnv.(4rjz(\rjz(ŒfVnf>Zjv>>Nf~> (ŒfVnf>Zjv>>Nf~> (`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(˜>>>>’v*˜>>Dr*˜>>.,r*˜>>\r*˜>>>>>*t>> ˜>>&„rjv6˜(r>&t¶>^2Èxd˜Z4’°J¨ ˆJ€lRhœÚ$Nr>^>Fšj>>r>–jv>F>Ê ˆ$z>š>Ð>>>F>.Ð>ªÐ<>zòZ>~f².TRj>Nþ:\>^>(âb>>Š>>(tf>,r2>>>>>>–v*à>>:,r*à>>:Dr*à>>:\r*à>>:tr*à>>>>Œrjv*à>>>>6´rjv*à>>>>>"Ü>>>>j°Î:4>fî"$6< D>>R>f^>j>2xŽ>x$>D˜à>è&à>*øš>–Î>T>>~>>Vfvú$¾úÀ$r>à>>ö $r^>"à> @ö@$>JR>>Ž>àø>Z2ø>º:ø>>>$v:ø>> ø(r2Dr2„V>^2Ž>$f>.>z2dbr>~2Tbr>~2ÔVjvz:4\V>švZ>&t ÀV>®Zz®ÈT$Vjjvj> >Vî Vj>>>š>°&$&°&4RØÎ>&dV>~v6°Ì> °Ür>°>>>>>>>>>>>>ì>>>f>N>>>>>>^>®V>J>>z>>>>v~&°6L>>>>&°°>>>>>>2>°>> ö $rj~>°>hö h$rR>>Š>*°>>¸r>>°>"Ðrjv>°ø6<ø°>>@^>RvjbvZjZ:°"˜^>RbvZv>f>°2àRvjzv>¢"$^Zzv6.°2`^>^vj>>>jbZjV>^z~Z>° >°2Ø>>°è>>>>vVîø$>^2°0>Z0Ž>0$R>N64`<>>R^>>šV>N64È<>>R^>>°0r>°&Hf*°&`>NJ>h>â>r~h6°ø>>>>Z>>>>>fnZ>°>>>(>>>°>> 8Fzvzjž`Î>NŽ €Î>b2˜Ž>˜$^> L ÀTV>8>"ôrj> 4 8 <>^2p Ž>>.p $^>$ ˜ ,Vf> 8>°8"~>vf6$~>4zj>€"Vjj~:$ "!š!š^^!"T 4€!$Z`!JNN< !J$ZbP!Œ>bvnZ>~RR^^Z^~:$&8",>Z^~f.L€"Tf²>b:>9";àà>>>>> \>jV8<>>2$^^j>>²>>>R>>®>>>f:À.,6¨Tj>>²>>>R>>²>>>f:.,6T>>$>>jp¾n.pD>>V°>¶>>J.°D~ðº ð$r>"ðd HD €4>4>>¾n>v^f>’f>>Ê>"àÐÈŽ>2”`D>>ªn>J>Fº.  ˆŽ>\*4>>ªn>R>>>>V  Ž>2\hD>>ªn>>^¨˜ Ž>D*,>Z>Îbj>øN> L&,>Zp>âff>>&p`N> \¸"<>Zð>Î>>&ðàN> <6>>>*ä>>,, <$"ä>D>D.T < < $Ä „*Œ l l „>>>>>>>*972="?¸>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> L*4$>>>>>>>>>°.h:° h> ° h °h>° h"°>>>>:h°:h ° ˜ð>>>$ZJn>>>â>":ð.$ZJn>>>â>":ð.$ZJn>>>â>":ðLð|v>2ØZ^:d èlR>Vö`$>J:Œ>4bf>Nr¦^>V>n^>$VbZZV>J¾>Šzbº^z>’zzº6¨$N^r^V>N>†^~~VV œ>"|>Ä °Ì*T>f>>Èž>>2ÈÎ>>È$>> È,>6È4>ÈTbòV>>>>>>>>>RRRR@ ,.@ 4>@ <.@ D.@ L>F@ \>@ d>@ l.@ t.@ |.@ „>F@ ”nR@ ¬.@ ´.@ ¼.@ Ä>>@ Ì>>@ Ô>>@ Ü>>Z@ ì.@ ô.@ ünRRRRRRRRRRRRRRRRRRRRRRRR@  .@  nRRRR@ @ >^*@ X J^>F>Z>vz>N®>N6Vj>N~~f:L ÀTÞ $>¸ 0 &è ^^¦f.Ø Ð Ž>L"|"4ZŽbnVb>†Z>RZrnZjVb>j²r>Fn>F>V¶bb>r>V>H šR^ŽVb>†z>NbVV>@ Œ>>ð V*d>¶2X$^>X<^>XT.Xdv*X|.XŒX´ZŽb^Jn>0>",r20>Hfz¦Z>>>>>b>p®>pî>p.$>p,&p*L>J>:¸®¸Fnzbbb>>>Z>¬ì>.„V~VV^fb>Z.¸Ž>¸Î>>¸$>¸,&¸"<>>>>>>>>>N ðŽ ðÎ ð$ð,ð4&ð<ðDðL>>>>ðTð\&ðd>>>>ðlðtð|ð„>>>>ðŒð”ðœð¤ð¬ð´ð¼ðÄ>>ðÌ>>ðÔ>>ðÜ>>ðäðìðôðüðððøððððð ð(ð0ð8ð@ðHðPðXð`ðhðpðxð€ðˆðð˜ð ð¨ð°ð¸ðÀðÈðÐðØðàðèðð>ðøðð >N>j¶>F>R","DhL&, °4.>>øø> XV>n:`Þ>n>:`,> `46`Drr>>`d6` X*”>>>>Æþ>^>>>>>>>>>V& ®& î& .$" ., .4" .< .D" .L" .T" .\ .d" .l" .t" .|" .„6 .Œ6 .”6 .œ6 .¤" .¬" .´" .¼" .Ä" Ì 2Ü>.V>N>N>N>brf> „ PŒn®àÎrNV>ô ü> >>>>>>>>>>>>>>>>>>>¼>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>L>ŠNŠ$ Ð"Ô :Ð t> >>>>>>=7>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ¼ >>>>>>>TDTœ>Š$ $ È$ $ œ<&D*D*D*$ l \ , <, $ ”>"È *@>>>2>d>|>¼>>X>2Ø>> >>>>"ø >>>>>>>>>>>>>> 52A"CàØ>¢òJn>>N*>’2> $>n20â>> 0"tpRh&>"œ:Ì"$>>>Š>>è>$èH>>>F>>>>ê¶:d6„>6T>¶>>>N>&¸>’¸ $>¨D>^>.¨\>^>¨ÀÊn>D>>>>>>>>>>>>Ž>F> ,j> Dj>" \j~>>b>>b2–2Ö2$.4> ¼>> Ì>* Üj>> ô>r"¢>>> 0 X @ê"@* h x ˆ>>>>N>>ˆ>>¶>>>ˆ>òˆ ¸j6 Ðj6 è>N>> >>>F>>>> >>>F>>>> 0 @ ` Pª"P* pj6 ˆRVV>"| „>^" Ž>>  H>^& &`> ˆZ>>f&>Š V>>>>>> H>>>64>>>> È^VVV>>>ž>20Z>0Z>0Z>øTZ>ølZ>ø„Z>0Z>0Z>øè´Z>*èÌZ>>èäZn>>èèZ>>> èZ>>>"èZº &è>>@Z>>>"è"XZ>>>2è2pZ>>>>>>>&è2ˆZr>>>*è¨Z>V>>è2ÈZr>>>*èèZ>>>>&èZ>>>>¦&è(Z>>>"è@Z>2èXZ>è2pZ>R>>>>>>>6èf>~j>®N>>>v>2$*>E"G ¸>>>>>>>><>"\>Î>Ò^^JN^Z>r®>RæRR>>r2(RVVÚÚl*|RJj>¦bn24f¸–¸Vv>XN6X<>Vv>N6v& n& ¦ ¶^, 4&TŒ>xZ~>€¦€d>>¸>:,>>Nj*èž>>*è&¸Î6¸Ž>>¸N>¸trf& >>>>>>>>>>¼>>>><>Š$ :$ t < < 4<< < | D> t>>>>>>EC>>>>>>>>>>>>>>>>>>>>>>>>:¼ >Š–Ä>&€D> à>>>AI"K`Ð^^>j>²jj.À¸Ž>\R*$>> h¶Jn>x>"$x2h&Dhä¶>H&$H€Zž>¾>^f^Zj^Zê^r>N^jvf6¼>†b.\`lF>J.È> ,Zf^z¦$"È6|*<@hZ:ˆJJ*>>>Ú6>$2>,2>*>M"OˆÐ>>>>>>4>ò>R:Ž&Î>D:$>>>>>>>>>>>>>>>~ xV xV xV xV xV xV xV xV xV xV xV x– x– xÖ xÖ x$x$x$x$x$x$x,x,x4x4x<x<x<xDxDxDxDxLxt$^>b>N~>>&>,>>"\j2h>>V2h>>R6h>>>Š2h>>’h>>>Ò h>ˆ>>>>b2ˆ>>R>>:ˆ>>>¢ˆæ>>*ˆ>¨>>>>>>–>>>>Z>"¸¶>¸:¨>>>>&<>¨>>>D.¨>>L>>>J>"ð>>>Š>ð>¨>>>l.¨>>t>>>J>6>>>Š>>¨>>>>*”:¨>>”V>6¨>>>>>¤.¨>>¤.¨>>¬>>"¨>>>>>´.¨>>>>>>´.¨>>¼>>¨>>>>>>Ä.¨>>>>>Ä.¨>>Ĩ>>&Ì>>¨>>>>>>Ô.¨>>Ô.¨>>ÔN>><¨>>>>>>>À.¨>>È>>>R2È>>R>>È>>>’>È>¨>>>>>ðn2ð>>N>>ð>>¶>ð>¨>>>>*n2>>N>>>>¶>>¨>>>>*@:¨>>>>2H.¨>>>>>>>>>>2H.¨>>P>>"¨>>>>>>>X.¨>>`>>>¨>6ˆ>>>>>>>ž>>ˆ>>>>Ö2ˆ>>$>>>J>>¨>>>Š>¨>ˆ>>>D*ˆ>>L>>>J>>Ð>>>Š>Ð>ˆ>>>>l*ˆ>>t2ˆ6„ˆ>¬>>>>>š>>>V.@>>Z2@>>R>"@>>>>®2@>>’>>@>Ê>:@>>Ö2@>>Ò>@>0> <.0>>D0>lj.˜>>V2˜>>R6˜>>>Š2˜>>’˜î ˜>D>>>>>>>b.Ø>>Z2Ø>>R>Ø>>>>ž2Ø>>’Øî Ø>Dj.>>>>~.>>Z2>>R>6>>>>>>>–.>>š2>>’Z>^z>&0>:<>d>>>>>b2x>>R6x>>>²2x>>’xî x>Dj.¸>>V2¸>>R6¸ž ¸><>>>N.ð>>Rð® ð><>>>>>š>>>>b.8>>Z>8>>R>>8>¢>8>>Ž>68>(>6T>>>N:x>>Rx®x>Ln>>’È®È&$ZȰ&¨Ž>TFv> >"$>.>LZr>^*>"Q"S(È>>>>>>>> L>ò>j>>(¾>NRR(4r(d>,>4.$>:$>&$Z>>>>>d.$.$î>ænnnnnnnnnn24Z>^>¢>F>F>F>F¢^^Z>>>>Vb>>Î^^Z>>>>Vb>ö^^>j>>’>V>V>F>Æ>r2ÀŽ>ÀDJ>n>n&$vâzâzâzâzâ>b>V>NªnN>næv>r>n&>>>>>>>>>>>>>>>>>>>>>>>>>>>>>¼>>>>>>L>Šd ,Z^>>>>>>>>>.°ŽÒ$$$*,JŽfff¦$$$>ŠN>F>F>F>F>F>F>F>F>F>F>Fnnnn>,~>F>F>F>F>D>D>4>b>f>F>>>>>>>>>>¦.øJn>F>>Rø4J>$>$>$>$>$>4~n>>>>R((Jnn>>R(>>>>>>>:QO>>>>>>>>>>>>>>>>>>>>>&¼ >>>4>ŠD $ t $>>>>:d>D>>*€>6¬>*l>D>D>d>D><><> T:<*¤>>>>>>>>MK2U"WÀð>>>>>>>>>>>>>>>> Ô®V^^^^^^^^VØNfffffff><>nPŽ*PÎ*P$&P,&P4&P<&PD&PL&Pt$*$Z6$*46,FVV^bº>,$2$2$2$$:$Z> $>>¼ >>>>>>>>>lz~~~~~~~~þ” t $$, $Š$ l $$$$ $$,>>>>>>>> UKY"[ ¸>>>>>&\ZN^Z^Zf>Nv²>4*$*,z2àŽ> àÞ>&àØ4ØT>>>>¼>>>4$Œ $ $ T>>"YK>>>>>>>>>>>>>>>>>>:¼ Œ $>>I"]"_@8>Z>8âJ> P¾P> 8(N>L>d>–fnØ4bn>ræJ>8>"$bn8>F>8>"$bn8:جV>F"ØÌ>Jn¾ZØxfr–>&,f>Zrb>Z:$br>>’Z>^20>>>>>>>>>>>>>>>>>>>>>>>&d>ž>>>>r>^>.¨Înr> ¨&\.0>>>>>> Ô>N>>>>"$>>†2.4>.D2.T2.d2.t2„”> 0Ð~>r>ªn>>˜fnv^VVV> Ø Ðà>¦>à$>*à4bjr>F>>>>>n>j~bj>f>Xê"$ p,>"X TRV:L2(>>.°z>Z¶îÐ$ªðÎ>V>F>J>Jl>XZ^^žxP"D>F>nj>F*>>>>>>>>>>>>>>>>>>>>>¼T²l>@>>]a"cØ ¸>>>>>>>>>>>>>>>>>>>>>t>>>>>&<>>>>>>>>>>>>>>>>>>>>> Ü>>>>>>>>D>ò>$>>>FRRÒTØÐÎRRRRRRRR°Œ&°œ> °”°Ä>^:pŽ:pÎfRpT.,ZL>Vrrî>Znnnnnnnnnnnn®^bZ>>>>Rb>>>j>¢r>j>–>r2@Ž>*@r>>Fæ>>>J ¨>>>’2¨>>>>>†2¨>>’6¨>><>>>>>>J2à>>Z2à>>R6à>>>>¾à>&<>>>~® >>N*P>4>>>>>~€>>>>>>®€>>>>.$>>>>>® – – – – – – – – – $>>>>>>FÀ>’À: L>>>R2è>>R&è®>è: €>>>”*€>>”.€>>>>:”> €>>>>œ.€>>>>:œ€>> Ä>>>N.@>>R>@>>>’>@>>>Ê>@>>>>$>@>>>>&,>@64@>\>>>N.˜>>Z2˜>>R6˜¶ ˜><>>>>>>J.Ð>>R>"Ð>>>º"Ðæ Ð>T>nZ&Ž>&,F>@>â>2@>Ì>Z ¶* >$jj> t>Zx >Öjj*x >2 x €>>R6€Ž> €Î> €,jj>€Lf:€df:€|&ðŽ>TR>€ì&` Ž>|R>€ r>€ f>€0 >€X ¦jj*X 4&X \>J>Nd>Šz> ., ”>Z° ¶&° >$fj>° è >ª>R:è 6,& Ž:Lrªv*h ,fj6ˆ $>T>>nø >Šø $.h Äf>b0 Ž>*0 $>è à >` à >>>>>>>>>>>>>>>>>*¼>>>>>>>>>>>t>>,>>>>>>>>>>>>>>>>>>>´,>>>>>D>Š$ ÄT $ F>F>>R"04F>F>F>F>F>F>F>F>F>F>F>F>F>F>F>L~>F>>>>>>>R.`pFn>F>>Rp4>>><><.<>4>6Ä>\> <> D>t>&P :\ 4>>>>>>>>>>*ae"gX8>>R8¶8>Î>8D>>Rxf x®x<>J>>V2¸Ž¸T64„Z>44$.$>>>>>Äz~~~~þ4 D < DŠ4 4öÖz€:4 ,¶$¶$ $>>>>>>>e>i"kˆ¸>>>>>>4*,Z>V^Ž Î&<îZ>4"HRb^>RrržxÎJfrr>>>>b>’&¸$~rr2¸L~rr>>>J2¸&>"¼~^Z^2>>>>>>>>> ¼>>>4>ŠLˆ>6i>>>>>>>>>>>>>>>>>>>>>>>6¼R’D t|2L*T6D*Œ*d L DFN>vVV–>f>f>f>f>r>f>f>f>>>>²>.4>>>:@>>>>Ì2@>Ô2@>Ü2@>ä2@6ì6@>>>>>>"newloaderloadprimrethrowsmakessetsgetsblitssubsfind@make@empty@consstringasizearrayamakeablitthrowasub@compare@print_unionnargsobjfieldsfieldobjgetinvalid_argintfloatprintgetposcacheNoneSomeNeko_errorInvalid_argumentAssert_failureErrorStream_errorNot_foundExit@print_record@aget@aset@pconsstream_tokenstream_posstream_junkstreamsprintfsndprintfordnstringnprintnekominmaxmagicignorefsterrorcomparechrassertsubsortsetmapmakelistlengthiteriiterinitindexcreateblitappendadd@rmaketlsplitrev_recrevphysnthnonememiter2hdfoldfindfilterexistsconcatchopassocallresetadd_subadd_charssizeuppercaseunserializeunescapeserializelowercaselist_depencyis_printableescape_charescapeOverflowEofClosedBlockedwrite_ui24write_ui16write_stringwrite_i8write_i32write_i16write_filewrite_charwrite_bytewritestdoutstdinstderrread_ui24read_ui16read_stringread_lineread_i32read_i16read_fileread_charread_byteread_bufread_allreadoutputinputflushfile_write_charfile_writefile_stdoutfile_stdinfile_stderrfile_read_charfile_readfile_outputfile_openfile_inputfile_flushfile_contentsfile_closecreate_outcreate_inclose_outclose_inhkeyhnewhcounthgethmemhaddhremovehsethiterreplaceremovehashEmptyMatchStarPlusNextChoiceInvalidRegexptransitionsstarsingleplusparseoptnodesnodenextmax_codemake_transmake_tablesis_emptyinvalidgroupescapeddeterminizecunioncintercemptycdiffccomplementcalladd_nodesadd_nodeInvalid_ruletokensourcepunionnull_poslineinc_lineemptydatacurrentcurposcharbuildTrueFalseNullThisIntFloatStringBuiltinIdentVarWhileDoIfElseFunctionReturnBreakContinueDefaultTryCatchSwitchSemicolonDotCommaArrowBraceOpenBraceCloseParentOpenParentCloseBracketOpenBracketCloseConstKeywordBinopCommentCommentLineNormalWhileDoWhileEConstEBlockEParenthesisEFieldECallEArrayEVarsEWhileEIfETryEFunctionEBinopEReturnEBreakEContinueENextEObjectELabelESwitchvar_argss_tokens_keywords_constantmk_stringmk_intmk_identmk_call1mk_call0mk_callmk_builtinmk_binopto_stringprint_listprint_astnewlinelevel_exprlevelparse_switchparse_stringparse_opparse_listparse_from_stringparse_fieldparse_expr_optparse_exprparse_constantheaderidivNoderemove_min_bindingmin_bindingmergeheightbalAccNullAccTrueAccFalseAccThisAccIntAccStackAccGlobalAccEnvAccFieldAccArrayAccIndexAccBuiltinSetStackSetGlobalSetEnvSetFieldSetArraySetIndexSetThisPushPopCallObjCallJumpJumpIfJumpIfNotTrapEndTrapRetMakeEnvMakeArrayBoolIsNullIsNotNullAddSubMultDivModShlShrUShrOrAndXorEqNeqGtGteLtLteNotTypeOfCompareHashNewJumpTableApplyAccStack0AccStack1AccIndex0AccIndex1PhysCompareTailCallLoopGlobalVarGlobalFunctionGlobalStringGlobalFloatGlobalDebugGlobalVersionInvalid_filewrite_debug_infostrap_stack_deltaread_debug_infosop_paraminullhash_fielddumpcode_tablesXEnvXStackXGlobalXFieldXIndexXArrayXThiswrite_optrapstack_deltaset_posscan_labelssave_breaksprocess_continuesprocess_breaksmake_arrayjmpgotoglobalget_cases_intserror_msgcompile_functioncompile_constantcompile_builtincompile_binopcompile_access_setcompile_access_getcompile_accesscompilecjmpcheck_stackcheck_breaksdocstackcdatapcdataxmldonePCDataCDataDocumentnode_textnode_nameis_pcdatais_nodeis_cdatafirstNodeattrib__listto_xml_recto_xmlparse_xmlparse_posInvalid_characterUnterminated_stringUnclosed_commentUnclosed_nxmlInvalid_escaped_characterInvalid_escapestrnxmlmk_floatmkkeywordsidentexprestringenxmlecommentcommentbinopUnexpectedUnclosedInvalid_nxmlvariables_nextvariablesswitch_casesprogrampriorityparameters_nextparametersparameter_namesobject_fieldsmake_binopexpr_nextblock1blockpathVNullVIntVFloatVBoolVStringVObjectVAbstractVFunctionVArrayvalueneko_valuemodule_set_globalmodule_read_pathmodule_readmodule_namemodule_loadermodule_globals_countmodule_get_globalmodule_exportsmodule_executemodule_code_sizeloader_pathasetaget__list_depacopycallstackexcstackCFunctionModulePosexcrunreportneko_pathlinkdo_linkTBaseTAbstractTCustomTFunTOptTStarTMultTObjTNamedTPolyTFunctionBeginEndQuestionDoubleDotPOpenPCloseBrOpenBrCloseFieldQuoteSharpDocInvalid_charUnknown_typeUnclosed_docInvalid_doctype_write_partype_writeto_htmlstatusmk_tokformat_xmldocumentationdocumentdoc_type_nextdoc_type_listdoc_type_fieldsdoc_type_basedoc_typedoc_tokendoc_optiondoc_docdoc_contentargsversionwithout_extensionwithout_dirset_cwdread_directoryput_envis_directoryget_envget_cwdextensionexitexecutable_patharray_dependencyVoidInvalidparse_argshelpverbosereleaseparse_multiformatoutis_nxmldircompleteL/`ÐS­6_ŠìL_­LìˆL9ðLèðLèL!´b èL%´b ^)^ìQLèLLU­ˆ¥^¥¥¥rèL3­LèL ÈbìL!LLKVLc¸fI^ˆìLìLŒLLKVLd´fìLL)L ŒLKVLTþ^\ìLìLŒLLKVLe´fìLL)LŒLKVLTþ^0ìLìL ŒL LKVLf´fìLL)LŒLKVLTþ^I¥åèLG­LèL9­LèðLèL%´b èL!´b^zìQLèLXLFþ:¥^i)L3­L¼f)L!LLKVL9´f)L1­LXL0V¥^8^^)L1­LLR­L;­LèLL-L%L!L6VèLHþ9R^¥¥¥å9ðf iLìL:VèL=­L)LìL7VL)LjLVLLAVLèL)L/VèL4þ1Rr9ðf lLìL:VèLLYVLèLD­LìL-­)LmL=VLLAVLèL)LVVèL4þ)Rå9ðf oLìL:VèL=­LìLpLVLLAVLèL+­L)L?VèL4þ!RåèLèðLèL!´bèL´b¥^ ^sLZ­¥^^sLZ­¥^^¥ì¥å9ðf rLìL:VèLLYVLèLD­LèðLìôL-L-­tL)L*VLLjL=VLLAVLèL-L-õL/VèL4þARå9ðf vLìL:VèLLYVLL`­L;­LèL-L-L%L!L6VèLW­L)L-­-LwL=VLLAVLèL)L5VèL4þ1RåèLXL2VL!´f8LLP­L,V8LyL-LSV^!8LzL)LJ­LLL[­zLSVÿÿÿÿL)ærèL3­LèL!¼fìLìL%ŒLQVL/¸fìLìL%ŒLQVL\¸f ìL|ˆ^ì¥åèL9þåèL9þåèL9þåèL9þå9LìL=­LT­‰å9ðLOþå9LìLT­‰å9L‰å9Lì‰å9ðLèðLèL!´b èL%´b^$=ðL-Lþ*^L>LLðL%z‰^¥¥åiL/`ÐS­7_•·LìL¢þå9LìLt! zåå»LìL¢þå¾LìL¢þåÁLìL¢þåÅL)ˆLìL/HoØL#Œg%ÐZrrj9LLLL=Vl^$LèÐL¸f èL«­a½L®­^èL/“°*öþ)¥r9L=þåj 9L=­l^$LèÐL¸f èL«­a½L®­^èL/“°*öþ¥åèL9LÏvLìL=LÐvL)LLÑvzåìLìfÓ^ÔL9VLèL=þ!¥r9ðL=´f ½L®­èL=L9ðŒLµVL-L-LL9ðLL£V9L9ðL)ˆ‰è¥rå9ðL=´f ½L®­L9ðL°VL9L9ðL%ˆ‰è¥å!ñLìL¯­LìLìLLÖvL×L-L-LLØvzRå9L=þå9L=þåèL9æLìL=LÚvL)LLÛvL-LæzåìLìfÝ^ÞL9VLèL=þ!¥r9L-L-L-LªVèråå9L¬þåL²­LèLàíLáLâL-L¤æzLìLãíLìõRåìLìLzrLìðþåLìð­L¨þå)L¯­L)L!ÄbìL!Äb)Lì¼b )L)ˆLì¼f ëL¶­-L-L-LôþC¥rèL!Äf íL¶­èL!´fs^YèL¥­L!ñL)ñLèðL!¼f<)L)ðL)ðLôVLèL!´f ÃL®­)L-ðL)ˆ‰ìL)ðL)Œ‰¥_Àÿÿÿ)RrèL!Äf ïL¶­èL!´fs^±èL¥­L!ñL)ñLjXðL!¼fJLðLðL ôVLèL!´fðL!´fÃ^½L®­LðL)ˆ‰LðL)Œ‰¥_±ÿÿÿl^FLèÐL¸f èL«­aèðLÀà´f$)ðL!´f ½L®­-L!LðL¦V^ ^èL/“°*öþ9¥RrL²­LLj"fLLL9VL±V_ëÿÿÿL³­l^/LèÐL¸f èL«­aèðLÀà´f )L¬­^ ^èL/“°*öþ)¥RåL²­Lj5f%Lð­LèL ´f ©L®­LìL¤V¥_ÜÿÿÿòLáL§Vl^.LèÐL¸f èL«­aèðLßUD´f ìL¬­^ ^èL/“°*öþ!¥¥åèL9­LìL9­L)L9­L-L9­L-L-Lœ¨L)Lœ¨LìLœ¨RåèL9­LìL9­LìLìLœ¨RåèL9­LìL9­L)L9­L)L)Lœ¨LìLœ¨RåèL9­LìL9­LìLìLœ¨LìL€¬L!¸f èLŒ^èRåÀL®þåÀL®þ!rÀL®þåLìQ­èLø‰èLùèLúFå)LìL-LzrèL)ðþrèLÿ¬L´­L)ðþrèLÄbèL€¼f ÿL¶­ìLìLÿ¬L9þ"r)L¯­L)L!ÄbìL!Äb)Lì¼b )L)ˆLì¼f L¶­-L-L-LôþC¥r!ñLìL¯­ñLèðL!¼f<)L)ðL)ðLôVLèL!´f ÃL®­)L-ðL)ˆ‰ìL)ðL)Œ‰¥_ÀÿÿÿRrìLìL9VìLìL L9VìLìL L9VìLìL¤L9þ"rèL!ÄbèLÿÿ¼f L¶­ìLìL9VìLìL L9þ"rèL€ÿÿÄbèLÿ¼f L¶­èL!ÄfìLL)ˆL9þ"^ ìLìL9þ"rèL!ÄbèLÿÿÿ¼f  L¶­ìLìL9VìLìL L9VìLìL L9þ"rLìUþåÀL®þåÀL®þåÀL®þ!rÀL®þåLìQ­èL FèL ‰èLèLFå)L)L)L­VL9þ*r6žL/`ÐS­7E_© ìL/áïjÿ­L!LèLÄfìLìLL/%[ÌVèL%ˆa_çÿÿÿìRrìLìL/ RÌVLèL´f %L­è¥r)L)L)L/%[ÌV€f 'Lþ!rjLLLLL/(î-øVl^L¥f )Lþ1r)L)L)L/í2[ÌVLèL´f +L­è¥r)L)L)L/,†ÐúVLèL´f  L­è¥rìLìL"VLèLL#.Zû!µr¥rèLèðLèL!´b èL%´b^P^MìUðL!´fìQL9LìLVR^4¥^^ìQL)UL9L)LV9L=LVèLðþ1¥¥^¥¥åL­LñLèL)LL-L/v‰èða)Lì­ìLþ)RrèL ÀfèL~ÈåèLèLèL ´b$èL ´b%èL ´b&èL\´b'èL"´b(¥^.^*2¥^X^"3¥^P^4¥^H^5¥^@^ 6¥^8^¥èLèL9­Ìf7LìL!­LV¥^^¥^¥èL%LìL=þ*¥¥åèL9L=­´f Lþ^Ñ9LìLVLèLèL ´b$èL ´b-èL ´b6èL\´b?èL"´bH¥^V^RL2LV¥^^BL3LV¥^q^2L4LV¥^a^"L5LV¥^Q^L6LV¥^A^¥èLèL­ÌfL7L)L!­LVLV¥^^¥^¥èLLìLV¥¥èL%ˆLðþåL­LñLèL-L9LL=LLL9v‰èða!Lìþ!RåèL9­LèL=­L!ñL!ñLìðLÄg< L)ðL/ RÌVLèL\´gü)L-ðL%ˆ‰)ðL´f ;L­L-ðL/ RÌVLèLèâu^ê^è^æ^ä^â^à^Þ^Ü^Ú^Ø^Ö^Ô^Ò^Ð^Î^Ì^Ê^È^Æ^Ä^Â^À^¾^¼^º^¸^¶^´^²^°^®^¬^ª^¨^ª^¤^¢^ ^ž^œ^š^˜^–^”^’^^Ž^Œ^ _]__×_”_Q__Ë_ˆ_E^v^t^r^p^n^l^j^h^f^d^b^`^^^\^Z^X^V^T^R^P^N^L^J^H^F^D^B^@^>^<^:^8^6^4_¾^0^.^,^*^(^&^$^"^ ^^^^^^^^_¬^ ^ ^_¶^_Ä_Ô_ÒLðL"L/%[ÌV_É_ÀðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR_ _ðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR_K_BðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR_Œ_ƒðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR_Í_ÄðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR__ðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR_O_FðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR__‡ðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR_Ñ_ÈðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR__ ðLˆLÀf ;L­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f ;L­0L!­LL!­LìŒLdL-L!­L)ŒL ˆL)L!­L)ŒˆLèLÿ¼f ;L­LðL)L­L/%[ÌVR^S^JLðL\L/%[ÌV^A^8LðL L/%[ÌV^/^&LðL L/%[ÌV^^LðL L/%[ÌV^ ^;L­¥¥^^^èLL-ðL)L/%[ÌV¥¥èLìðL%ˆ‰ìL)ðL%ˆ‰_Àöÿÿ)L!L)ðLþCRåèL9­LìL!L)L=VL!ñLaL!­LAL!­ŒLìðLÄfHL)ðL/ RÌVLèLAÀfèLZÈf-L-ðL)L!­LˆL­L/%[ÌV)L-ðL%ˆ‰¥_´ÿÿÿ)RåèL9­LìL!L)L=VL!ñLAL!­LaL!­ŒLìðLÄfHL)ðL/ RÌVLèLaÀfèLzÈf-L-ðL)L!­LˆL­L/%[ÌV)L-ðL%ˆ‰¥_´ÿÿÿ)RåèL?þåèL/HoØLAþåE7L/`ÐS­7z_’è€fH#MR±åèðLìôLT­LHL#1ÚiZååì€fèrìôL)ðL)LHL#1ÚiZLVþ"rrèLH#MR±LVþåèLèðLèL!´b èL%´b ^!^ìUL%LìL9𭈥^¥¥åèLèðLèL!´b èL%´b^ZLRæ^ ìQLè¥^¥¥åèLèðLèL!´b èL%´b^\LRþ!^ ìULè¥^¥¥åèLèðLèL!´b èL%´b ^0P^,ìQL)ULIL)LæLL-L9ðVL%z¥¥^¥¥rèLèðLèL!´b èL%´b^$^!ìQL)ULìL­LìL9ðþB¥¥^¥¥rìLèðLèL!´b èL%´b"^y)LèðL!´f^ ^^`LRþ9¥^\ìQL)ULLèðLèL!´b èL%´b^2`LRþQ^)ìQL)ULL)L VLL)L9ðþs¥¥^¥¥¥¥^¥¥rèLèðLèL!´b èL%´b^PPLPõ^GìQðL)QôL-ULèL9ð­LèðLìôLILL)L%zLILLL%zõR¥¥¥^¥¥åèLèðLèL!´b èL%´b^)^&ìQL)ULìL­f^ LìL9ðþB¥¥^¥¥rèLèðLèL!´b èL%´b^0^-ìQL)ULìLLMVL!´f^ LìL9ðþB¥¥^¥¥rèLèðLèL!´b èL%´b^@SLOæ^7ìQðL)QôL-ULL-LMVL!´fì^ LìL9ðæ¥¥¥^¥¥rèLèðLèL!´b èL%´b^<SLOæ^3ìQðL)QôL-ULL-øL!´fì^ LìL9ðæ¥¥¥^¥¥rèLèðLèL!´b èL%´b^/SLOæ^&ìQL)ULìL­fì^ LìL9ðæ¥¥^¥¥rìLèðLèL!´b èL%´b ^*)^&ìQL)ULèLIL-LL%zL9ðþB¥¥^¥¥rèLPL9þåèLèðLèL!´b èL%´b ^+-^'ìQL)ULLL-LæL)L9ðæ¥¥^¥¥rìLèðLèL!´b èL%´b ^+)^'ìQL)ULIL)L)LL9ðVL%z¥¥^¥¥rìLèðLèL!´b èL%´b ^')^#ìQL)ULèLL-L9VL=ðþB¥¥^¥¥rñLèL9L)Llv‰èðaìLPL)þ"¥åìL!´fè^;èLèðLèL!´b èL%´b^!nLRþ)^ìULL%ŒLìL9ðþ:¥^¥¥rèLèðLèL!´b èL%´b^)^&ìQL)ULìL­fLìL9ðþB^¥¥^¥¥rèLèðLèL!´b èL%´b^)^&ìQL)ULìL­f^ LìL9ðþB¥¥^¥¥rìLèðLèL!´b èL%´b^3rLRæ^*ìQL)ULL!´fì^èLL%ŒL9ðæ¥¥^¥¥rñLèLìLsí‰èðaìL!Äf tLR­)L)L)æ¥rèLèðLèL!´b èL%´b ^?P^;ìQL)ULìL­fIL)LL-L9ðVL%z^ LìL9ðþB¥¥^¥¥rèLèðLèL!´b èL%´b^/^,ìQL)UL9LL-LKVL%ˆLìL=ðþB¥¥^¥¥rèLèðLèL!´b èL%´b ^OLNþ!^GìQL)UL%LìL9­ˆL)LJVLñLèL)L)Lwv‰èða%L-L)VìR¥¥^¥¥åèL9­L)LìLQVèLLþ!¥rz7FL/`ÐS­7š_ØLìðL)QL!LèL)Äf.-L-L)$L|L#Ñ(0µˆ2èL%ˆaèL)Äf -L‚ˆ2_Ïÿÿÿ-Lƒˆ2-Rå9LìL/¢å1&­L)zåèQå9L!L/™m%©zåìðL)QLìL/¢å1&­Lì´f,èLL%ˆL/Ï~4"­eìL!LðL!LL/}÷V-L)‰èL)L@-LìL%ˆFRrìLìLþ"r)L)L)L}þ3rìL/Ï~4"­L!LèLÄfèL)L@èL%ˆa_êÿÿÿ9LL-zRrìL/Ï~4"­L!LèLÄfèL)L)Læ@èL%ˆa_åÿÿÿ9LL-zRrèQL!L)ð2èL)Äf)Lì$L­èL%ˆa_èÿÿÿRrèQL!L)ð2èL)ÄfèL-L)$LVèL%ˆa_åÿÿÿRrèQL!LìL/Ï~4"­L-ð2ìL-ÄfìLìLL$Læ@ìL%ˆe_âÿÿÿ9L-L)zRrèðLìQL-L‡þ+rèQL|#MR±L)ð2ìL!¼fìL%Œe)L)$LìL|L#1ÚiZa_àÿÿÿèRåìQL!L-ð2èL)Äf)LL)$L9VèL%ˆa_äÿÿÿRr)QL)L)ˆLì¼f –L/&]­9L)LðLLL/¿[uÀVz¥rðLLðLLL/}÷þUrìQL)ð2!LèL)Äf$-Lì$L-L|L#e ÐZL!´fèrèL%ˆa_ÙÿÿÿR€L~þrš7{L/`ÐS­7÷_ýèLèðLèL!´b èL%´b^ œL-L›L#ýKZ^L-L›L#ýKZ^¥¥å9LìL%zåå¢LìL›L#ýKZå9LìL9eê*zåå¦LìL›L#ýKZå9LìLâ% zååªLìL›L#ýKZå9L)L)Lv¨zrr®LìL›L#ýKZå9LìL5/zåå²LìL›L#ýKZåµLìL›L#ýKZå¸LìL›L#ýKZåèÐL´flèôLèÐL´f èL/Ë\ˆ­L%´f ìLìþr¾L)L/¢å1&­L!LèL)Äf+)LL)$L½­ˆ2èL%ˆaèL)Äf )L‚ˆ2_Òÿÿÿ)L¿ˆ2)rRèL/Ñ(0þåå L/°ñm­LÁL!L)L/¢å1&­L%ŒLìLìÄfL-L)$LèL/º”“­LèL´f )L%ˆ2^!LìˆLÈL L-L/ÿAVL½­ˆLĈ2-L%ˆ2R_²ÿÿÿ)Lň2)RáèL/¢å1&­LèL´f)rL-L¾ˆ2èL)Äf+-L-L)$L½­ˆ2èL%ˆaèL)Äf -L‚ˆ2_Òÿÿÿ-L¿ˆ2-rRr)L)øL!´f!r)ÐL´f†)L/¢å1&­L)L/¢å1&­LìLì¸fìLìÔr)Lè„f!èðL´fèôL´f LørèQa_ßÿÿÿ!LèLÄf4Lì$LL)$LLLzLÈVLèL!¸fèrìL%ˆe¥_Éÿÿÿ!rR)ÐL´f‹èLè„f!èðL´fèôL-´f -L-ørèQa_ßÿÿÿ-L/°ñm­L!LìL/¢å1&­LìLìÄfHL-L-$L/ÿAVLLL$L/ÿAVLìLLL zLÈVLèL!¸fèr -L%ˆ2R_¶ÿÿÿ!rR)L)ÔrrìLìLLÈþ+rèL!Äb èL)QÀf ËL÷L#ÎeK<µìðLì$rìL!Äb ìL-QÀf ÍL÷L#ÎeK<µìL-ðL)@rÐåèQL½­LÓˆLìUL½­ˆåÒL)L)L%zrèåèL/&]þåìLìL¬VL9ærèL¨­L9æåèL°­L9æååèðLè¥åèôLè¥åèL/ï P­LèL´f ßL9­è¥åèL/œÅ–­LèL´f áL9­è¥åèåèL!ÄbèLÿ¼f äL9­èåèL½þåèL/Ñ(0þåèL9­L/-X‹ÈþåèL/-X‹ÈþåìLìL÷L#e ÐZrìLìL›L#e ÐZL!Äfì^èrìLìL›L#e ÐZL!Äfè^ìrìLìL»þ"rìLìL9VL=þrïÜLL)?–€NèL!?”]UèL/™m%©?BšÁè¥åèL!Äf ñL9­ì#BšÁLì$Lè„fèr)#BšÁL/¢å1&­L)L%ˆL/Ï~4"­LèL!L#BšÁL!LL/}÷VìLÈfìLìLLL#–€Nµ@ìL%ˆe_äÿÿÿLì?BšÁèL$rRrèL!Äf óL9­ì#BšÁL/¢å1&­L)L-#”]UL-ˆ?”]UèL)Àf)L-#BšÁL-L-LŒL/¿[uÀV?BšÁ^*)L/™m%©?BšÁìLìŒeìL!¼fL-L#–€NµìL%Œe_éÿÿÿ¥rè#”]UåÜ7ïïL?BšÁïL?–€NïL?”]U÷7›žLèL!õ7Ÿ›LŸ?Ø>ã3èL¡í7 ›L ?O17¥£LèL¥í7¤›L¤?7ä.§LèL©í7¨›L¨?%Ðý«LèL­í7¬›L¬?±Úx+¯LèL±í7°›L°?¨;W³LèL65õ7´›L´?©Óà¶LèLw ùõ7·›L·?¶’¥ê¹LèLßUDõ7º›Lº?>#÷-¼LL/HoØL#Œg%ÐZ7»À7½÷LÆ?ãŸpð÷LÇ?ýKÉ7È÷LÊ?e Ð÷LÌ?S÷LÎ?!nÑL!õ7ÏÔ7ÒÖ7Õ÷LÒ?!Ê|Õ÷LÕ?1Úi÷LÏ?MR±×LØLèLÙíLìLÚíL)LÛíLÜLÝLÞLLàíLLâíLãLLåíLæLçLìLèíLéLêLëLìLíLèLLîvLðLLòíLLôíLõL÷L?&]÷L ?Ñ(0÷L-?º>9÷Lì?÷±!÷L)?'}Ö÷L?€-÷L?L(†ß÷L?i£W÷L?™Ïa1÷L ?-X‹È÷L ?áT÷L ?¿/iï÷L?ÿÍÃ÷Lö?›yÉ÷L?’S÷L?¤ S÷L?-q÷L?ÎeK<÷L?ï P÷L?¹È÷L?‡ÊM÷L?œÅ–÷L?ÈË)ó÷L?¥i÷L ?-zK÷L?ÆFÌR ÷÷7||#!n7}|#&]7~|#S7|#¶’¥ê7€„LèL†í7…ˆLL/HoØL#Œg%ÐZ7‡šL…?.Zû!‰LìLŠíL‹LŒLLLŽíLLíLL‘LL’íL“L”LL•íL L—íL˜L™LšL-?€©WšL?Ñ(0šL?^'XÌšL ?¢›WšL?œ SšL ?î9VÈšL?^³ÇšL?攚L?Q° šL?ſŚL?;»ÅšLì?›>šL ?–€NšL ?üfüšL)?58ÁšL?ÚáÓšL ?!òIRšš7G÷7HH#!Ê|Õ7IG#î9VÈ7JH#!n7KG#^³Ç7LH#e Ð7MG#üfü7NH#&]7OH#MR±7PG#^'XÌ7QH#ÎeK<7RH#¶’¥ê7SU7TW7VzLX? sÛzLT?.Zû!ñLèLìLYí‰èða[L]LñLñLñLñLñLñLñLñLñLñLLL^í‰ð2 LL_í‰ð2LLaí‰ð2LLbí‰ð2LLcí‰ð2LLdí‰ð2-LLeí‰-ð2)L-Lfí‰)ð2ìL)Lgí‰ìðeèLìLhí‰èðaèLiíLñLñLñLñLñLñLLLjí‰ð2LLkí‰ð2-LLmí‰-ð2)L-Loí‰)ð2ìL)Lpí‰ìðeèLìLqí‰èðauLñLèLìLví‰èðaLxíLèLyíLzL?xezL?ÚênzLì?^'XÌzL ?4åzL ?cÙVzL ?Ò9WÊzL?bÝSzL?¸ ÉzL?SzL?œ SzL?æ”zL?° ÂzL?Å¿ÅzL?üZzL?\ÀÃzL ?9лÃzL-?¸5zL?Üà?zL? ÐÇzL?k¿ÁzL ?•r9&zL)?™m%zL?ÚáÓzL?!ùIRzz7L/`ÐS­7 ^úþåìLìLüþ"rèLþå 7ø÷7ùûL!L/HoØL#Œg%ÐZ7úýLL/HoØL#Œg%ÐZ7üÿLL/HoØL#Œg%ÐZ7þLL/HoØL#Œg%ÐZ7L%L/HoØL#Œg%ÐZ7L%L/HoØL#Œg%ÐZ7LLLLþLL L-?Ñ(0 L?ÏIÈæ L?üfü L)?"‡ Lì?ô0Û L?!òIR  7÷7#Å¿Å7#Ñ(07#L(†ß7#ô0Û7#&]7#!òI7#üfü7#-zK7#ÎeK<7#¶’¥ê7 #áT7!#LL/HoØL#Œg%ÐZ7"$L/áïjÿL/´VhL&L(L*L,L-LL.L0L1LèL L8vLLL-L:vL L LL<vL LL=vL LL>vL@L%L/HoØL#Œg%ÐZ7?BLL/HoØL#Œg%ÐZ7ACLDLEL-?‘>çELì?gä˜úEL?šr!ÝEL ?€©WEL?ÚênEL ?¢›WEL)?à]òôEL?î9VÈEL?1­¥æEL ?,ñ(EL?æ”EL?r€˜ EL?–€NEL ?9лÃEL?”ãìEL?CÚÚEL?üfüEL? ÐÇEL ?58ÁREE6Ÿ 6 ÷6¡¡#ýK6¢Ÿ#58Á6£ #ô0Û6¤Ÿ#üfü6¥Ÿ#€©W6¦¡#ÆFÌ6§¡#áT6¨¡#>#÷-6© #"‡6ª¡#7ä.6« #Ñ(06¬¡#L(†ß6­¡#&]6®Ÿ#æ”6¯Ÿ#–€N6° #!òI6± #üfü6²¡#-q6³¡#-zK6´¡#’S6µ¡#ÎeK<6¶¸LèLºí6¹žL¹?bŸí¼LèLÀàõ6½žL½?œ¼4¿LèL^!‰õ6ÀžLÀ?ÌæÂÂLèLlûq õ6ÞLÃ?Ì¢OÆ6ÄÇLLÄVLÈL%LÄVLÉL%LÄVLÊLLÄVLËL%LÄVLÌLLÄVLÍLLÄVLÎL%LÄVLLLLÒvLLìLÕvLÙLLLLLÜvL LìLßvLäLåL!LÄV©LæL!LÄV©LçL!LÄV©L)L­L)L­L)L­LèLéLêLìLîLðLèLñíLóLLôíLLõíLLöíLL÷íLûLüLýLþLèLíLLL-LíLLíLèLíLL íL LLLíLL?¶uKL?ÙtKL?q·„÷L?O$L?¨æõÜL?îäõÜL ?uaøL ?veöL ?¨ÅÈõL?ßlYÐL?Ë¿óL?H³ L?¢&ìL?ßÇp>L?Çp>L"?Ú¥AL?½~8L?ŸÌ9üL ?åÊ9üL#?Edž4L?ŸWŠ2L?Ñî1L?ж4üL?xì3üL?VK§ËLì?™Ïa1L? L? Ä>L-?Äb›L&?™ÝÜL'?œ‡0øL?n T<L?Îä+L?EqL<L(?ܲÏL)?9—²íL!?¤YáÀL,?­O¿ëL$?ÇÞôåL%?}r*L+?}~&ôL*?u2:ðL ?‹zÔæL?ˆîÉL)?G9L ?LýLR2mL/`ÐS­7J_O !LL)zåèðL LVèLFåìL)ôL)f%^ÿÿÿÿˆìL9þrèQÌfèðLìôLL LVLVèLFèðLæåèLèðLèL!´b èL%´b^X^UìUðL!´fìQLèL­R^?¥^^ìQL)ULìL­!LLL9æVLLL-L=ðþd¥¥^¥¥r!LìL-L9æþ"rèL9­=Qf=L%LV=LþåèôLìðL!LìL9L=æVìLèðLèL!´b èL%´b^^ìQL9LÃLVèLþ9¥^¥¥RåèLèðLèL!´b èL%´b^<L¹Lþ*^„ìUðL!´f3ìQðL)QôL=L)L9L=æVèL­9L­R^Q¥¥^^ìQðL)QôL-UL=L-L9L=æVìL­9L‚LV9L­èLðþ9¥¥¥^¥¥åèôLìðLèL9­=LALV=LLVìL9­=LLþ*RåèôLìðLLL9ðæLìLèðâ^)^B^^à__6_b_¡_ _™_Þ_$_¡_ß__'_P_¿_Ó_wèQL!LìL­LL=æþR¥_\èQLL$LVLLV)LLLL&vLìLVLôL%ŒLÅLVLþI¥_ èQLQÌf"LÁLVèL-­L'LV¥_ä^¥^¥èQLL(LVèL-­L)LþR¥_ºèQLìULìL­*LìLL=æþZ¥¥_˜èQLìULìL­L¾LVL+LL-LVL¿LþZ¥¥_`èQLìULìL­LLVèL­LƒLþZ¥¥_2èQLL,LVL‚LL=LLL-vL-LVL%LVLþI¥_ñè*ðLèL!´b èL%´b0^iìQL)ULL.LVìL­LìLLðþk¥¥^>ìQL)ULL/LVLìLLðVL.LVìL­LþY¥¥^¥_pèQLìUL)*LL0LV)L­L)L)LLVL!´LðVèLèðLèL!´b èL%´b^#^ ìQL L1LV LìLLðþƒ¥^¥¥¥¥¥_õèQLìUL)*LL2LVL-LLðV3L)L L=æVLìLLðþk¥¥¥_®èQLìULL4LVL+L!L L=ææLLVL¿LVLìLLðþc¥¥_fèQLìUL)*LQLfèfL¾LV^ L$LVLLL9ðV5LL L=æVLL-L9ðVfèfL¿Lþj^ LÅLþj¥¥¥¥_çèQðLèL!´b èL%´b^(L6LþR^ìQQLL7LVèLþQ¥^¥_§èQðLèL!´b èL%´b^(L8LþR^ìQQLL9LVèLþQ¥^¥_gL:LþJ_[èQLìULìL­L%LVL­èLþQ¥¥_0èQðL!´fL;LV_^^èQLL$LVLLVñLèLL=LLLLL>v‰èðaìLì­LLVLÅLþZ¥¥^¿èQL?LìLL=æþR¥^©èQLìUL)*LL@LV)L­L$LVL­LLLLBvL)LVèLèðLèL!´b èL%´b^/^,ìQL LCLV LLVèL­ LLV¥^¥¥LÅLVLþY¥¥¥^¥¥RrìôL)ðLèLèðLèL%´bèL´b/¥^{^wQf LEL9VLLLõL=V¥^…^PìQLQf LEL9VL$L9VLLVLL)L=VLLVLÅL9VR^9¥^¥LLVLLLõL=V-f L%L9VLLþB¥Rr9LL)L=V9Qf9L%LV9LþåèL­LèðL%´f%èQL-L9L=LLGvLìLV¥^¥^^)LL-L9þ3¥rL­LèðLìôLìL9­LèLL=V)L­L)þ1RåJ7 7 z7 E7 L/`ÐS­7_8 èLèðâ ^^^)^3^=^G^Q^[^e^nYL)LRþ"^bZL)LRþ"^V[L)LRþ"^J\L)LRþ"^>]L)LRþ"^2^L)LRþ"^&L)LRþ"^_L)LRþ"^`L)LRþ"^¥å9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzååèLèðâ ^^'^1^;^E^O^Y^c^m^w^^‹^•^žpL)LRþ"^’qL)LRþ"^†rL)LRþ"^zsL)LRþ"^ntL)LRþ"^buL)LRþ"^VvL)LRþ"^JwL)LRþ"^>xL)LRþ"^2yL)LRþ"^&zL)LRþ"^{L)LRþ"^|L)LRþ"^¥åèLèðâ^#^-^7^A^K^U^_^i^s^}^‡^‘^›^¥^¯^¹^»L)LRþ"^¶‹L)LRþ"^ªŒL)LRþ"^žL)LRþ"^’ŽL)LRþ"^†L)LRþ"^zL)LRþ"^n‘L)LRþ"^b’L)LRþ"^V“L)LRþ"^J”L)LRþ"^>•L)LRþ"^2–L)LRþ"^&—L)LRþ"^˜L)LRþ"^™L)LRþ"^¥å9LìL zåå9LìL zåå9LìL zåå9LìLzåå9LìLzååèLèðLèL!´b èL%´b^°L-LRþ*^±L-LRþ*^¥¥åèLèðâ^)^3^=^G^Q^[^e^o^y^ƒ^^—^¡^«^µ^¿^É^Ó^Ý^æµL)LRþ"^Ú¶L)LRþ"^ηL)LRþ"^¸L)LRþ"^¶¹L)LRþ"^ªºL)LRþ"^ž»L)LRþ"^’¼L)LRþ"^†½L)LRþ"^z¾L)LRþ"^n¿L)LRþ"^bÀL)LRþ"^VÁL)LRþ"^JÂL)LRþ"^>ÃL)LRþ"^2ÄL)LRþ"^&ÅL)LRþ"^ÆL)LRþ"^ÇL)LRþ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9LìLzåå9L-L-L-Lzrr9L-L-L-Lzrr9L-L-L-L zrr9L)L)L zrr9L-L-L-L zrr9LìL zåå9LìL zåå9L)L)Lzrr9LìLzåå9LìLzåå9L-L-L-LzrrèôLè¥åèL-L-LÑVõrèL)LVLÑVõrèL-LPLLVL%zLÑVõrèL)Ln­LÉ­õrèL)Ll­LÉ­õrèL)Lf­LÉ­õrèL)Lj­LÉ­õrèLLLLßVõrèôLìðLìLèðLèL!´b èL%´b ^T^ìQLèL9­LQ­¥^¥¥LìõRåèôLìðLìL9­LìõRåèôLìðLìL9­LìL9­õRåèôLìðLìLìLèðâ^)^+^?^P^i^‹^©^Â^ì_F_p_‰_³_é__!_?_X_Z_»)_·èQLLìLXVLË­¥_¡èQLèL­LÍ­¥_ŽèQLìULìL­LìLÏV¥¥_sèQLìULìL­LL)LXVLÑV¥¥_OèQLìULìL­LìL­LÓV¥¥_/èQLL÷íLìLXVLÕ­¥_èQLìUL)*L)L­L)L­L)L×V¥¥¥_èèQLìUL)*L)L­L)L­L)LèðLèL!´b èL%´b ^T^ìQLèL ­LQ­¥^¥¥LÙV¥¥¥_ŒèQLìUL)*L)L­L)L)L ­LÛV¥¥¥_`èQLìULìLìL­LÝV¥¥_EèQLìUL)*L)L)L­L)L ­LßV¥¥¥_èQðLèL%´b èL!´b^ ìQQLèL­LQ­Lá­¥^-^¥^áèQðLèL%´b èL!´b^ ìQQLèL­LQ­Lã­¥^-^¥^©)^¥èQLìULìL­LìL­LæV¥¥^…èQLLøíLìLXVLè­¥^j)^fèQLìUL)*L)L­LLùíL-LXVL)LèðLèL!´b èL%´b ^T^ìQLèL ­LQ­¥^¥¥LìV¥¥¥^¥õRrèôLèLèðLèL!´b èL%´b^^ìQLèL9þ1¥^¥¥¥åèôLèL9þ¥åèôLìðLèL9­ìL9þ!RåèôLìðLèLèðâ^)^*^9^E^W^r^Š^ž^¶___%_=_h_“_”_¬_À_Á__èQLLìLSþB¥_èQLèLþ9¥_òèQLìULìLþA¥¥_ÞèQLìULìL­LìLSþJ¥¥_ÁèQLìULìL­èLþA¥¥_§èQLLûíLìLSþB¥_‘èQLìULìL­èLþA¥¥_wèQLìUL)*L)L­ìL­èLèðLèL!´b èL%´b^^ìQLèL þa¥^¥¥¥¥¥_*èQLì*LìL­èLþA¥¥_èULèLþ9¥_èULì*LìL­èLþA¥¥^èèQðLèL%´b èL!´b^ìQQLèLþA¥^^¥^»èQðLèL%´b èL!´b^ìQQLèLþA¥^^¥^Ž^‹èQLìULìL­èLþA¥¥^qèQLLüíLìLSþB¥^[^XèQLìUL)*L)L­LýíL)LSVèLèðLèL!´b èL%´b^^ìQLèL þa¥^¥¥¥¥¥^¥RrèLèðâ ^^^^^^)^0^D^O^Uÿ^Q^M^I^EèQLèLWþ!¥^7èQLè¥^.èQLLìLU­ˆLˆ¥^èQLL숥^ èQLè¥^¥åèLèðâ ^^^!^#^%^'^)^+^-^/^1^3^5^6^2^.^* ^&1^" ^ ^ ^:^ ^2^ ^^¥åèLèðâ^#^%^'^)^+^-^/^1^3^5^7^9^E^Q^X^g^q^m%^i^e+^a^]$^YÅ^U¾^Q¿^M^Iƒ^EèQLèL9þ!¥^7èQLèL=þ!¥^)èQLè¥^ èQLLìˆLˆ¥^èQLL숥^¥å7Kz7LL/`ÐS­7S_9LìL!þå9LìL¤©r9zååèðåèôåìôL)QL)QL6VL-UL-UL+VLðzrLsLìL$­L)L!LL!LLsL/­L=L!L!LL z ¥åèðåìLì‰rL!FL!FLUFLUFL-FLF L)F LìF rè*Lì* L)ôL1­ŒL)* L-*zåèôåè*L!´fÂè*LìU´fVèULL$­LèL)UL-QL!LUL"VìL)*L-UˆFìL)*L-UˆFìLìFìL)ULF¥è*Lì*ŒLìQL!L-QL*LL"VìLìFìL!Fì*L)QL)LULŒL#VL)L-*L)ˆF)L-*L)ˆFRèQLì*L2VLìL)*L%ˆFìL)*L%ŒFè¥åèL ´f ìLF ^èL ´bì* fìLF ìL)*L%ˆF rj8L9­LL*L%ŒFL*L%ˆFLìL=VèL­¥l^*LèÐL¸f èL-­aèðLÀà´f%^ ^èL/“°*öþ¥å9ðLì$ðL=L­$LL)L*VLL‰L)èLÿÿÿÿ¸fL‰LììLÿÿÿÿ´f ,L3­-L%ˆL)Lðþ2Rr9ðL9ôLèLÿÿÿÿ´f6=Ls)Ìf&=L=*LðL%ˆŒF=L=*LðL%ˆˆFÿÿÿÿ^=L=*L-ŒF=L=*F=L=QL=*LL'V=L=*L-ˆF=L=*F=L=* L-ˆF !ñLèðL-Äf"=L=ôL)ðL2VLVèLìðL%ˆ‰_Úÿÿÿì¥RåèðL)­LìðL0­LÿÿÿÿL!õLÿÿÿÿL!õLñLèLLL9LLLLLJv‰èðaìLLL=LKvLj!L!LVLLÖL(Vl^nLèÐL¸f èL-­aèðLèLÀà´b èLßUD´b6^?ôLÿÿÿÿ¸fLðL%ˆ‰LLôL*VL-­¥^^L-­¥^ ^¥èL/“°*ö­¥LèLÿÿÿÿ´f LQæ^LôL)L*VæRrèðLj L4­l^(LèÐL¸f èL-­aìL;­L3­^èL/“°*öþ!¥¥åNL)L8VL0L-L8VL ­LèL-L-L ­L.­L&­zRrPL7æåQL5LìL9þ"¥åS77z7E7L/`ÐS­7Î_ÙèLèðâ^^^#^-^7^A^JƒL)L]þ"^>„L)L]þ"^2…L)L]þ"^&†L)L]þ"^‡L)L]þ"^ˆL)L]þ"^¥å9LìL%zåå9LìLzåå9LìLzåå9L)L)Lzrr9L)L)LzrrèLLkVL!´åèL)õLèððL!´fì^Ú^^èôðL!´f)^É^^èððL%´f°èôðL%´f£èðQLèðLìôL-ðULôQðLôQôLôULL-ÈfWL%ˆL-ÄfxLLL L9ðVL%z^1L)Äf-LxL-LõL-L%zL9ðV^ LìL9ðV^ LL9ðVR^"¥¥¥¥¥¥¥^^^^–LGLbþ*¥rèLèðLèL!´b èL%´b%^]-L9ÈfxL9LõLL%z^^=ìQðL)QôL-ULxL-L%ŒLõL-L%ˆL-L=ðVL%z¥¥¥^¥¥rñLèL9L)L˜v‰èðaìLèðL%´f/èQðLÿÿÿÿ´f!èQôLìULìL%ˆLìLVR^¥¥^^^^èLÿÿÿÿLìLþ2¥¥¥åìL9­LìL9­L=VL9þrìL9­LìL=VL9þrLLL-­zåèL9øL!´åèLíL)LoVfì^xLìL-L%zLìQL9ðþ"r9L)L)Lrþ+r9L9ðL%ˆ‰9ðåìLèðâ^^^7^n^¥^Ã_ì_èQL9L=­LèLxLLõLL%z襥^ÛèQL9L=­LìLìLðVLìLxL)LxLLL%zL%zFìR¥^¢èQL9L=­LìLìLðVLìLxL)LxLLL%zL%zFèR¥^ièQLìULìLìLLðVLðþ:¥¥^IèQLìUL9L=­LèLxLLLðVLxLLLðVLL%zL%zF襥¥^¥r9L=­LèL)L)LVõ¥å!ñLèL íLñLèL)L9L-L¡v‰èðaìL9L)L¢vLL_þ2RåèLèðL%´f†èUðL%´fxèQðLìQôL)ULèQðLìQôL)ULL)øL!´f$xLLLL9VõL)L%zL=ð­^xLLõLL=ð­L%zR^¥¥¥¥¥¥^^^^ì¥åèôåèôLìðL-ôLðLìðLðŒRrèôLìðLxL9L-L%zLìL=LVõRåèôLìðLìLìL9L=VõRåèôLìðLèL9­ÌRåèôLìðL-ôLðLxLxLLL%zLL-L9VõLLL=L§vLL€VLL9L¨vLL€VLVL%zLL©íLìLeVL)LLVõ¥RrèôLìðLL)L9VLìõRåèôLìðL-ôLðLèL-LhþBRrñLèL9L)L¤v‰èða¥L)L€VLy­L¦LìL{VL)­LñLèL=LLL9Lªv‰èðaèLLõL-LrVLèðLìôLL«íLìL€VLèL[­L¬LìLcV|LìL_VLfL)L_VõR åj9LL`Vl^[LèÐL¸f èLz­aèðLw ù´f9=ðL=L=ðL%ˆ‰9L-L)LtVLxLLðL%z‰è¥^ ^èL/“°*öþ¥åèðåèôLèL9Ldþ"¥å¯LìL€VLj9LL`Vl^šLèÐL¸f èLz­aèðLw ù´fx=ðL=L=ðL%ˆ‰9L-L)LtV-L­LèðLìôLìL­LðL)L_VLL°íLL_VLLxL-L-LzLõLðL%z‰R^ ^èL/“°*öþ!¥¥åèðL9L9ðL)L=V‰¥åèL9ðLwþåèôLìðL9LxL-L=LzL9ðL%z‰Rå9L)L´vLìL^þ"rèðL)ðLèL)Lhþ2RrñLèLµíL)LiV¶LìðL{þ"¥åèL9­LL‚­LL‚­L!ñL!ñLñLñLL-L-L®vLñLèLLL=LLL LL±v‰èðañLèLL²vLLlVèðL)­Ls­ðLL³íLpVL·LèLðLg­L€VL[­LèL-õR åèQLìôL)ðLèñLèðL-Èf#9LìðL=LLuVLjVèLìðL%ˆ‰_Ùÿÿÿ¥RåLÿÿÿÿL\VLèL)L¹vL-L^Vè¥rìLìL}­´fÿÿÿÿ^èL)LuVfì^ìL%ˆLìL9ðþ"rèQL!LìL9þ"¥åèôLìðL9LìLuVL)L=þ*RåèôLìðLñLèLìL»í‰èðaèL¼íL)L_VL-L9L½vL-L_VLìLìõRRå¿LìL]þå9LìL±ý1.zååèLv­LxLìL)õLL%z¥åèôLìðLxL)Lv­L)Lv­õLL%zRåÄLìL€VL9L=L)Lrþ+¥åèLÁ­L~æåìLìðLmVLìL)ðL%ˆ‰èLèLèL\´b2èL+´b3èL*´b4èL?´b5èL[´b6èL]´b7èL-´b8¥^>^:)¥^=^2)¥^5^*)¥^-^")¥^%^)¥^^)¥^^ )¥^ ^¥-L9þ)¥¥rèLèðL´f"èQLìULìLìL9ð­L‘VR^¥¥^^ìLþ¥åèLèðL´f"èQLìULìLìL9ð­L‘VR^¥¥^^ìLþ¥åèLèðL´f"èQLìULìLìL9ð­L‘VR^¥¥^^ìLŠL“þ"¥åìLèðL!´fì^^^)L)L‘þ*¥r9L=ðLmVL=L=ðL%ˆ‰èL]´fðLaLkVL!¸f 9L­ì_èL-´fŠðLaLkVL!¸f 9L­ìLèðLèL!´b èL%´b^VxL-LõLL%zLðþ)^<ìQðL)QôL-UL)L)¸f 9L­L-Lq­‰èLðþA¥¥¥^¥¥^vèL\´f9L=LV^èLðLèðLèL!´b èL%´b^CxL-LõLL%zLðþ1^)ìQLLa‰xLL)õLL%zLðþ9¥^¥¥¥¥å!ñLŠñL)Ln­L)ðLìÄgP-L-ðLmVL-LðL%ˆ‰èLèLèL+´b$èL*´b0èL?´b<èL[´bHèL\´bÇ¥^í^éLðL9­‰¥^ô^ÖLðL=­‰¥^á^ÃLðL­‰¥^Î^°añLñLèLLLLLLLÌv‰èðaLðLmVLèL^´f$LðL%ˆ‰LL-­L­LV^L)­L­LLðL)L‹­LV‰R¥^H^*LðLLLVL ­L‹­LV‰¥^ ^¥-LðL-L ­L‹­LV‰¥¥_¬þÿÿìðRåÎ7Tz7UL/`ÐS­7Ü^…èL/7ºÅþå!L/øÅþåèL/gË€ßþåìLìLÐ#e ÐL/.± ÅVLè€f ÒLÑ­è¥rìLìLÐ#e ÐL/­>Åþ+r)L)L)L/¹"Åþ3rìLìLÐ#e ÐL/¬Ú@éþ+r)L)L)LÐ#e ÐL/:ÌÅþã37aZ#ÆFÌ7bX#^'XÌ7cU#S7dU#¸57eZ#‡ÊM7fU#cÙV7gZ#¥i7hX#Q° Â7iZ#!n7jZ#e Ð7kX#Å¿Å7lY#–€N7mY#æ”7nU#Üà?7oX#;»Å7pZ#O177qU#\ÀÃ7rZ#¹È7sV#!òI7tZ#S7uZ#áT7vU#•r9&7wZ#!Ê|Õ7xU# ÐÇ7yZ#7ä.7zU#^'XÌ7{Z#i£W7|X#æ”7}Z#&]7~Z#MR±7U#œ S7€U#ÚáÓ7V#üfü7‚‰LèL!õ7ŠTLŠ?mªèLŒí7‹TL‹?%¹PèLŽí7TL?ò57èLí7TL?zk35èL’í7‘TL‘?±Û3èL”í7“TL“?3Dõ¥ÿLLxL)L!õLL%zL•LñLèLìL—í‰èðaL™íLèL)LšvLìL-L›vLœLñLñLìLìLží‰ìðeèL)LŸí‰èða)L£íLLLL L LL­vLìLìLL¸vLºLèL¾íLÀLèLÂí7ÁTLÁ?rëÍÃL LLÅvLÆLèLÇíLñLñLñL)L-LÈí‰)ð2ìL)LÉí‰ìðeèLìLÊí‰èðaËL-L-L-LLLL LLLLÍv LÎL ?>UìÀÎL?Òã[ÌÎL?ˆf!9ÎL?Z?ZÊÎLì?3U=ÎL-?3œTÎL ?1¸¾ÎL? ÉÎL)?ó„ÉÎL?è¯Å ÎL ?×?B/ÎL ?fáÎL?8©–ÎL?÷ÚG;ÎL??³ôÎL?ÃÍ $ÎL ?z2ÎL?Ì<<ÎL?ÙwuÓÎL?Jó.ÎL?èÉÃÎL? ½·ÓÎL?žºÁÎL?SÀ5ÎL? ÜJâRÎÎ7÷7#O177#™m%7 #ýK7!#58Á7"# Ä>7##üfü7$#Ø>ã37%#fá7&#€©W7'#ÆFÌ7(#‡ÊM7)#S7*#¤ S7+#>#÷-7,#7ä.7-#z27.#Ú¥A7/#i£W70#æ”71#–€N72#&]73#3U=74#MR±75#’S76#ÎeK<77#œ S78:LèL<í7;L;?¤æþØ!L!L!L=zL>L?L@LALBLCLDLELFLGLHLìLìLIvL)L)LMvLOLèLRíLSL-?ù‚+SL ?Û°12SL?¢›WSL?VK§ËSL ?ŸÎßîSL?œî1SL ?ô³ÇSL? Ä>SL?5ÂäSLì?:ÚïSL ?*VcÂSL?9œãËSL?Hæ>SL ?üfüSL?Ö^¿ÁSL)?.Ûê:RSS7ME7N÷7OO#!Ê|Õ7PO#O177QO#ýK7RL#Å¿Å7SO#Ø>ã37TN#CÚÚ7UO#MR±7VO#Ñ(07WL#œ S7XaLèL!õ7bKLb?nÓÜ7èL%õ7cKLc?ƒ¥|èLõ7dKLd?§Êç3èLõ7eKLe?~2Õ7èLgí7fKLf?ÏÄ7èLií7hKLh?|5ÄèLkí7jKLj?ñœÄÅèLmí7lKLl?ƒ*=èLoí7nKLn?в¦Ê¥}LèL!õ7~KL~?Ç–AèL%õ7KL?‘³êÜèLõ7€KL€?«;èLõ7KL?ý?èLõ7‚KL‚?Ùî-èLõ7ƒKLƒ?8gîèLõ7„KL„?ÐÂ=èLõ7…KL…?Ÿ”ÌèLõ7†KL†?‡œz èL õ7‡KL‡?¡éèL õ7ˆKLˆ?!@èL õ7‰KL‰?ìNÔèL õ7ŠKLŠ?¾ ú¥šLèL!õ7›KL›?œ¼4èL%õ7œKLœ?ö¤ïèLõ7KL?iú3èLõ7žKLž?µ¡ŠÝèLõ7ŸKLŸ?©é¼8èLõ7 KL ?½b° èLõ7¡KL¡?eÍ9èLõ7¢KL¢?4wßèLõ7£KL£?"P=èL õ7¤KL¤?ò)èL õ7¥KL¥?üüÒèL§í7¦KL¦?Ci‹ÝèL©í7¨KL¨?ÉnN èL«í7ªKLª?ˆ‰-ÆèL­í7¬KL¬??¢ÁÎèL¯í7®KL®?Óq&¥²LèL!õ7³KL³?ê«!;èL%õ7´KL´?L;Ê¥ÈLèLÊí7ÉKLÉ?ÞN+ôèLÌí7ËKLË?ÈÊÉÞèLÎí7ÍKLÍ?‘¦?èLÐí7ÏKLÏ?5ê`*èLÒí7ÑKLÑ?ƒK9çèLÔí7ÓKLÓ?Ã\ÏèLÖí7ÕKLÕ?‘^ÈóèLØí7×KL×?,™ŠóèLÚí7ÙKLÙ?‚›4èLÜí7ÛKLÛ?öÙÛ-èLÞí7ÝKLÝ?}´ÉèLàí7ßKLß?#oÍÜèLâí7áKLá?Õ óèLäí7ãKLã?:z¹âèLõ7åKLå?Ì鋿èLçí7æKLæ?Ø·îèLéí7èKLè?äôÿèLëí7êKLê?oc|èLíí7ìKLì?ÀV/¥îLÿÿÿÿLïLðLñLòLóLôLõLöLúLþLLLìLìLvLL ?õd'Lì?í"7>L)?ÝË':L-?ð‘§ÎL ?”]UL?Ò¢†8L?N¸áïL?ÄSïL ?òòõøL ?ñòõøL ?_`žñL?‚I4L?ÇšÚêL?œ SL?Å¿ÅR7÷7 #veö7 #Å¿Å7 #q·„÷7 #î9VÈ7#e Ð7#Ø>ã37 #G97 #ßlYÐ7#ð‘§Î7#ÆFÌ7 #™Ïa17#‡ÊM7LLèLíL LñLèL)L)L"v‰èðaìL#íLñLñLìL)LLLL LLLDv‰ìðeèL-L-LLFv‰èðaìL-LLHvLLìLIvLJLì?UJêáJL?™Ïa1JL?ð)ÀJL?ð¶4ÕJL)?-X‹ÈJL?T˜¦ JL-?…›ÂJL?„còJL?üfüR JJ6z6L/`ÐS­7C_ÔL Lçþ"rèðLã­LèL!´f$ìðLé­L)ðLìLñVL-ôLìLVèR^ìôL)ôL ­L)ŒLùþ"¥åèL!´f^()L)æL LìLLLL%ŒL9ðVL%z¥rèðLã­Lèâ ^^^ ^$^(^6^D^Q^^^k^x^vê^€^p^z^j ^t^d^n^^ìðLã­L­^^^NìðLí­L­^N^>ìL9­L­^?^/ìL9­Lî­^0^ ìL9­Lè­^!^ìL9­Lü­^^èLLìˆLþ!¥¥åèðLã­Lèâ!^F^J^N^R^V^Z^^^b^f^j^n^r^v^z^~^‚^†^Š^Ž^’^–^š^ž^¢^¦^ª^®^²^¶^º^¾^Â^Æ^Ê^È^Ò^Â^Ì^¼|^Æ^¶^À^°^º^ª^´^¤^®^ž^¨^˜^¢^’ ^œ^Œ!^–^†"^^€#^Š^z$^„^t%^~^n&^x^h'^r^b(^l^\)^f^V*^`^P+^Z^J,^T^D-^N^>.^H^8/^B^20^<^,1^6^&2^0^ 3^*^4^$^5^^6^^7^^èL8LìˆLþ!¥¥åèL9­LìL=ð­Lìõ¥åèL9ð­LìL9ð­LèL)õRåìL9ð­L)L9L;íL-L=VL-Lð­L)L)L)LïþCRrèðLã­L!´få^èL9ð­Lÿþå9L=­L9L­LèL)õRåèðLã­LèLÄf<èL%´fìQð^ìL9­L)ðLö­L-LìL!L!LzF-L=ðþ)R_`ìQLèL)Lèâ^:^8^:^H^c^~^^¨^Ð^ì__6_W_}_£_Ê_õ_þ___/_3_Q_k_…_“_¥_·_Ü__L­Lë­__òL=ðLðLã­LVLò­_å_ÕL=ðLðLö­LVLò­_È_¸L=ð­L­_·_§L=ð­LèLL9­L V¥_š_ŠL=ð­LèLL=ðLðLã­LVL V¥_p_`L=ð­LèLL=ð­LV¥_R_BL9LL>vLLìLðLã­LVL÷­¥_'_L=ð­LL=ð­LìLìLóLVR__ôL=ð­LL=ð­LìLìLôLVR_á_ÑL=ð­LL=ð­LìLìLL­LVR_¹_©L=ð­LL9­LìLìLL=ð­LäVR_‘_L9LðLã­LVLèLL=ð­LðV¥_h_XL­LL=ð­LL=ð­L)L)L)LúVR_;_+åLø­_0_ L=ð­Lÿ­Lø­__ åL­_^ÿL=ð­Lÿ­L­^ù^éý^ó^ãL=ð­LL=ð­LìLìLþVR^Ó^ÃLLðLã­LVLõ­^·^§LLðLö­LVLõ­^›^‹L9­Lû­^‹^{LðLã­LV^w^gLðLö­LV^c^SðLðLö­LñVLèLLðVLì­¥^<^,L=ð­LèLL=ðLðLö­LVL V¥^^èL?LìˆL­¥¥õ¥¥åLæ­LìL-zLèðLLñVL9¸f AL­èL=þ!¥rC7Ý7ÞS7ßš7à7á÷7âÞ#Ñî17ãá#öÙÛ-7äâ#Ø>ã37åà#üfü7æâ#ÆFÌ7çá#ƒ*=7èÞ#Çp>7éá#nÓÜ77êá#ÞN+ô7ëâ#‡ÊM7ìÞ#ŸÌ9ü7íá#ñœÄÅ7îá#ÀV/7ïá#}´É7ðÞ#VK§Ë7ñá#ÈÊÉÞ7òá#ê«!;7óá#L;Ê7ôá#äôÿ7õÞ#ßÇp>7öá#‘^Èó7÷á#Õ ó7øà#–€N7ùá##oÍÜ7úá#oc|7ûá#в¦Ê7üá#Ì鋿7ýá#Ø·î7þâ#O177ÿà#!òI7á#Ã\Ï7á#,™Šó7á#‚›47á#ƒ¥|7á#ÏÄ77á#~2Õ77á#|5Ä7á#‘¦?7á#§Êç37 â#!Ê|Õ7 á#5ê`*7 à#æ”7 á#ƒK9ç7 â#MR±7á#:z¹â7â#ÈË)ó7ñLLLñLèLìLí‰èðaìLíL9LñLñLñLñL-LL)L:v‰-ð2)LìLLL<v‰)ð2ìLìL=í‰ìðeèLL)LLLLLLLL@v ‰èðaLìLBvLCL?À‡yÀCL?f0 CL?íÈ‚ÖCL?*xCL ?ú´fÅCL?n#ÃCL-?µe¡#CL)?ðâ CL?0 ‚CLì?3U=CL? ýR CC6L/`ÐS­7\_.=èLèðâ^^^%^/^9^C^M^VÐL)Loþ"^JÑL)Loþ"^>ÒL)Loþ"^2ÓL)Loþ"^&ÔL)Loþ"^ÕL)Loþ"^ÖL)Loþ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9LìLzåå9LìLzåå®LìLoþå9L)L)LïZg6zrrìLìLåVL©ærèåèLèðâA^…^‡^‰^‹^^^‘^“^•^—^™^›^^Ÿ^¡^£^¥^§^©^«^­^¸^Ã^Ò^Ô^Ö^Ø^Ú^à^â^í^ø^ú^ü^þ______ _ __________ _"_$_&_(_*_,_7_9_;_=_?_A_L_M!_I!_E!_A!_=!_9!_5!_1!_-!_)ÿÿÿÿ_%!_!!_!_!_!_ÿÿÿÿ_ þÿÿÿ_ ÿÿÿÿ_!_%^ýèQL!L쌥^ðèQL!L쌥^ãèQL!LìL%ˆŒ¥^Ò!^Î!^Ê!^ÆR^Â!LRŒ^º!^¶èQL!L쌥^©èQL!L쌥^œ!^˜!^”!^ÿÿÿÿ^Œÿÿÿÿ^ˆÿÿÿÿ^„ÿÿÿÿ^€ÿÿÿÿ^|ÿÿÿÿ^xÿÿÿÿ^tÿÿÿÿ^pÿÿÿÿ^lÿÿÿÿ^hÿÿÿÿ^dÿÿÿÿ^`ÿÿÿÿ^\ÿÿÿÿ^Xÿÿÿÿ^Tÿÿÿÿ^Pÿÿÿÿ^L!^H!^Dÿÿÿÿ^@!^^`^u^‰_6_J_x__¢_O_ _>_S_h_}_«_ß_e_§LLL9ðæL)L»þ:_*LLLL9ðæL-L»VLìF¥_lLLL9ðæL)L»þ:_ULLL9ðæL)L»þ:_?èQððL!´g`èQðQðL´gOèQðQQL´fèUðL%´fèUQLìUULôLÀf:LLLL9ðVLL9LvLìL‹VL*L)Lm­ŒF^8LL9LvLìL‹VLLLL9ðVL*L)Lm­ŒFR_ˆ¥¥^^^^èQðQQLìULìL¸fLLL9ðæLL»VR_P^R^¥¥èQðQQL´f\èUðL%´fNèUQLìUULLL9LvLìL‹VLLLL9ðVL*L)Lm­ŒFR_襥^^^^ ^^^^èQLìULLL9L vLìL‹VLLLL9ðVL*L)Lm­ŒF¥¥_LLL9ðæL)L»þ:_zèQL-Ìf L-Le­L=VLL9L vLìL‹þB¥_JLLL9ðæL)L»þ:_3LLL9ðæL)L»þ:_èQLì*LL*LRˆFL¥L*L*L%zF LLLL9ðVL*LRŒFL*LèðLèL!´b èL%´b^ L?LqV^ ìULè¥^¥¥F L*L%ˆFLLL-L9ðVL*L%ŒF¥¥_mèQLìULìLm­L*LLjF L*L-ˆFLLLL9ðVL*L-ŒFLìF R¥¥_èQL(´fèULì*LñLèLìL í‰èða)Lì­LèfL*L%ˆFLLLL9ðVL*L%ˆFLLLL9ðVL*L)f^%ŒFRR_˜¥¥^^LLL9ðæL)L»þ:_zLLL9ðæL)L»þ:_cLLL9ðæL)L»þ:_LLLL9ðæL)L»þ:_5èQLìULLLLL9ðVLLL-L9ðþ\¥¥_èQLL*LˆFLL9LvLìL‹VL*LŒF¥_ÏèQLÌfL-Le­L=V¥_³^¥^¥èQLð*LìL”VfLìˆL-Le­L=V¥_ƒ^¥^¥èQL*LT­L*L²LjLzLð*L)L)L}þS¥¥_GèUðL%´frèUUðL!´fbèQLìUQðL)UQôL-*LLe­LLLL-LL"LLLVõLLLŸVõL9ðV¥R^Û¥¥¥¥^^^^èQLìUL)*LLLLL9ðVjL­L¡­!l^*LèÐL¸f èLc­aèðLßUD´f%^ ^èL/“°*ö­¥LL*L)ˆFLìLL9LvL-L‹VìLèðLèL!´b èL%´b^^ìQL L LL-L9ðV¥^¥¥L*L)ŒF¥¥¥¥^¥rìLèðâ ^^^)^3^=^Q^s^•_·_À-L L9þ2_´-L·L9þ2_¨-L¸L9þ2_œ-L‡L9þ2_èQLLìLp­L9þ:¥_zèQLLL)LS­L=VLz­L9þ:¥_VèQLLL)Lg­L=VLz­L9þ:¥_2èQLèLèLèL´b@èL´bNèL´b\èL´bjèL´bxèL´b†èL´b”èL´b¢èL´b°¥^Ã^¿L!Lp­L9V¥^À^ªL%Lp­L9V¥^«^•LLp­L9V¥^–^€LLp­L9V¥^^kLLp­L9V¥^l^VLLp­L9V¥^W^ALLp­L9V¥^B^,LLp­L9V¥^-^LLp­L9V¥^^¥èLLìL¿­L9þJ¥¥¥_èQLj¾ULLVLèL *Èfuj*L LVl^QLèÐL¸f èLc­aèðLw ù´f/ *L L *L%ˆF L *L L-LŽVFè¥^ ^èL/“°*ö­¥L LìLh­L9V¥^0 *LìŒL LìL!´fÇ^ìL%´fÉ^ìL“­L9V¥¥l^HLèÐL¸f èLc­aèðLw ù´f&L)LÆ­L=VLLìLz­L9V¥^ ^èL/“°*öþ9¥¥^¥rèL¶­Lèðâ^^ ^_ ^_4_Æ_ÄèQðLèL´bèL´bâ¥_­^äìQQLjŽULLVLèL *Èfmj*L LVl^QLèÐL¸f èLc­aèðLw ù´f/ *L L *L%ˆF L *L L-LŽVFè¥^ ^èL/“°*ö­¥LèLØ­¥^èLÚ­¥l^@LèÐL¸f èLc­aèðLw ù´fL)LÆ­L9VLèLÜ­¥^ ^èL/“°*ö­¥R^ä¥^ ã¥^Ú^¥^ÅèQLìULLL-L=ðVL¹LVèLÞ­R^«¥¥^–èUððL!´fGèUðQðL´f6èQLìUðQQLLL-L=ðVL¹LVèLà­R^_¥¥^^^^èQLìULLL)L=ðVL¹LVLL-L=ðVL¹LVâR^¥¥^L)Le­Lþ*¥rèLèðâ^^%^@^T^h^|^†^èQL-LìLŒ­L9þ2¥^yèQL-L*L)ŒLº­L9þ2¥^\èQL-LìL[­L9þ2¥^FèQL-LìLƒ­L9þ2¥^0èQL-LìLQ­L9þ2¥^)L›L9þ*^)LiL9þ*^¥rèLèðâ^^%^@^T^h^|^Ÿ^¨èQL-LìLh­L9þ2¥^’èQL-L*L)ŒL“­L9þ2¥^uèQL-LìLz­L9þ2¥^_èQL-LìL­­L9þ2¥^IèQL-LìL®­L9þ2¥^3)L¹L9V)LL“­L9V)L½L9þ*^)L‡L9þ*^¥rìLèLèL´bxèL´bèL|´bŠèL´b“èL´bœèL´b¥èL´b®èL´b·èL´bÀèL ´bÉèL!´bÒèL"´bÛèL#´bäèL$´bíèL%´böèL&´bÿèL'´c¥__LÈL9V¥__L¤L9V¥_^òL{L9V¥^ð^âL«L9V¥^à^ÒLUL9V¥^Ð^ÂL•L9V¥^À^²L°L9V¥^°^¢L´L9V¥^ ^’LaL9V¥^^‚LÅL9V¥^€^rL~L9V¥^p^bLžL9V¥^`^RL]L9V¥^P^BLÏL9V¥^@^2L¢L9V¥^0^"L„L9V¥^ ^L\L9V¥^^¥!L)L=þ2¥r-LèLèL(´bqèL)´b“èL*´b¾èL+´béèL,´cèL-´cèL.´coèL/´cÅèL0´cèL1´cqèL2´cÇèL3´cèL4´csèL5´cÉèL6´cèL7´cu¥_Ð_ÌLL9VLLLL=ðVLìLV¥¥_„_£LLL=ðVLLæLLLL=ðVLì­¥¥_R_qLLL=ðVLLæLLLL=ðVLì­¥¥_ _?L¹LV*LLL9VLLìLVL*L-ŒLº­LVL¹LVLLL=ðVLL!LLY­LŒLrVLLVLìLVL!L“­LVL%Lu­LVR¥__ L¹LV*LLL9VLLìLVL*L-ŒLº­LVL¹LVLLL=ðVLL!LLY­LŒLrVLLVLìLVL!L“­LVL%Lu­LVR¥_â_LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_…_¤LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_(_GLL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_Ë_êLL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_n_LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥__0LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_´_ÓLL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_W_vLL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_ú_LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_^¼LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_@^_LL9VLLìLVL¹LVLLL=ðVLL!LLY­L%ŒLrVLLVLìLV¥¥_ã^¥-L-LzLèðLèL"´bèL#´b‰èL´bü¥_…_ìQððL!´f0ìQðQðL´fLLL=ðVLÂLV¥_^^^^ìôððL!´f1ìôðQðL´fLLL=ðVLÂLV¥_H^¥_^¥_ _ìQððL!´f0ìQðQðL´fLLL=ðVLµLV¥_^^^^ìôððL!´f1ìôðQðL´fLLL=ðVLµLV¥^Î^¥^—^¥^‘^ìôððL!´f}ìôðQðL´fkìôðQQL!´fXìQððL!´fGìQðQðL´f4ìQðQQLLLL!LŒL£­L’­õL=ðVR^W¥^¥^^¥^^¥^^¥^ ^¥^^¥LLL=ðVL¹LVLLL=ðVLLLþ[¥¥r9L9*L%ˆF9L9UL)L9*LŽVFå9LìL-L–þ+r9LìLw­L=Le­LV9L¹Lþå)ôLL³­LULL¬­L!L*L*L!L*LjLjLjLL³­L * L* LðzLèL$íL-L‹Vè*LìLLL9ðVìL)*L-*ŒL|­L=VìLìLLe­LVìL­ìðUL‚­L)ðL¥L* L-LLm­LQzLðQL%zF)ðULìLÿÿÿÿLËVLxV)*L!¼fZ)*LsLnVLèL%íL*LˆVLLL=L&vLìLZVL)Lz­L=VL*LX­L=þJ¥^LìLz­L=þBRrèL)õLèððL%´fSèôðL%´fFèðQLìðUL)ôQL-ôUL-L)LšVL!´f)LìL9ðVR^^R^¥¥¥¥^^^^ìL-õ¥r9*Lì¸f9L9*L)ŒLu­L=V9L‘L=þåèLRŒLèL9*Äf9L9*L)ŒLu­L=V9*LìÄf9L¹L=V_íÿÿÿ9Læ¥åLì­9L¹L=V9L4LP­LLV9L%LÀ­L=V9LæL¡þå)LèðLèL!´b èL%´b^i¥LLT­LjL%z^UìQL)ULL9´f"¥LLT­LLjL!L=ðVL%z^èL¥L-LL%zLL%ˆL=ðþS¥¥^¥¥r9L¹L=V9LL)Lðþ#å9LL)L=ðV9L¹Lþå9LL)L=ðV9L¹Lþå9LL)L=ðV9L¹LþåìL-õLèðLèL(´bGèL)´b„èL*´bÁèL+´bþèL,´c;èL-´cxèL.´céèL/´cZèL´cèL´c¥_s_oìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLVL=VR_¥^¥_5^¥_/_+ìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLfL=VR_Y¥^¥_ñ^¥_ë_çìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLL=VR_¥^¥_­^¥_§_£ìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLL=VR_Ñ¥^¥_i^¥_c__ìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLtL=VR_¥^¥_%^¥__ìôðL%´fkìôUðL%´fZìôUUðL!´fGìôQL)ôUQLLL-L9ðVL¹L=VLL)L9ðVL¾L=VR_¥¥^¥_³^¥_­^¥_§_£ìôðL%´fkìôUðL%´fZìôUUðL!´fGìôQL)ôUQLLL-L9ðVL¹L=VLL)L9ðVLyL=VR_¥¥¥^¥_;^¥_5^¥_/_+ìôðL%´g”ìôQððL!´g„ìôQðQðL´grìôUðL!´gcìôQðQQLj ð*LL±Vl^6LèÐL¸f èLc­aèðLw ù´f0L)ˆLLV^ ^èL/“°*ö­¥L*LñLèLìL1í‰èða*LT­L-ôL)VLèðLìôL L=L2vL)LT­L‹V L=LL3vLìLÎVLQL *Äf L *LQŒLu­L=VQL *¼f L¹L=V_êÿÿÿ LFULèðLèL!´b èL%´b ^3L¥LLæL *L%zF^ìQLLìLl­L=V¥^¥¥ L=L LLL5vLìL‹VRR_¥^^^^ ^^^^6L-LV¥_â_~ìôðL%´g ìôQL)ôULèLm­LèLxL *Œ¼fèL¼foèL LñLèL)L)L7v‰èðaLLæL¥LLL%zLjL!LVLÎVLVL L L8L¥LLjL%zL LðVR^môLÀf4LLL9ðVL=L9L9vL)L‹VLìL¼­L=V^2L9L=L:vL)L‹VLLL9ðVLìL¼­L=V¥R^Ó¥¥^¥^i^eìôðL%´fVìôQL)ôULL9L=L;vLìL‹VLL-L9ðVèLm­LèL!¼fLìLW­L=V¥R^p¥¥^¥^^¥L9L=L<vL-L‹VLLP­L-LVf#L-Lm­L*L*ŒL¦VL=þB^L-Lm­LÀ­L=þB¥rèLèðLèL!´b èL%´b^À L Lqþ*^´ìUðLèL!´bèL%´b#¥^z^v)QL9L=L)LðVR^†¥^[)UQððL´fG)UUðL!´f4)QL-UQL9L=L-LðV9L=L)LðVR^;¥¥^¥^ ^¥^^¥ìQL)UL9LL-LðVèLðþ1¥¥^¥¥å9LL)L=ðV9L¹Lþå9LL)L=ðV9L¹LþåèôLìðLìLèðLèL!´b èL%´b^#9L¸L=V^ìQL9LL)LðV¥^¥¥9L¹L=V9L9UL)L9*LŽVFRå9*Lì¼f9L9*L)ŒLu­L=V9L‘L=þå9ðL!¼f69L9ðL%Œ‰=*Lì¼f=L=*L)ŒLu­LV=L‘Lþå9ðL!¼f69L9ðL%Œ‰=*Lì¼f=L=*L)ŒLu­LV=L‘LþåèôLìðL9L¹L=V9LL-LðV9LìLƒ­L=V9LÇL=þ*RåLìþåèôLìðL9LìL-LÁ­L–þ3RåèL9L=æõåèôLìðLìL²LšVL!´fLìþ!RååèôLìðLìLèðLèL%´b èL!´b(^)ìQLL­9L=L)LðV9Læ¥^N^¥¥RåLìþåèôLìðL9LÇL=V9L¹L=V9LL)LðV9LžL=VìLL9LæõRåèôLìðLLì­9L=LL¥LLjL%zL˜­õLðV9LæRåLìþåèôLìðLL)L9VèLèðâ^)^;^»^Ï^ö_È_h_‚_€_'___M_Õ_„ _û _" _ _Ì _ èQLLìLL=þS¥_ö èQðL!´fL¸LV_à ^^èQLUL*LñLèLLLLL>v‰èða-Lì­ìL*ÄfL*L-ŒLu­LVL)LLVL-FR¥_t èQLLL)LðþS¥_^ èQLìULLL-LðVLìL­­LþR¥¥_5 èUðL%´gèUUðL%´gèUUUðL%´g{èUUUUðL%´ggèUUUUUðL%´gQèUUUUUUðL%´g9èQLìUQL)UUQL-UUUQLUUUUQLUUUUUQLUUUUUUQLUUUUUUULLèððL!´f&èðQðL´fèðQQL´f^^^ ^^^^¥gL?LP­L’­õL L LLP­L’­õL¥LL¥L L¥L L¥L L¥L L¥L L L%zL%zL%zL%zL%zL%zLªVõLLèððL´f¿èðQLìðUL)ôLULìL@Lw­L’­õLLLL¥LLÁ­L@õLjL%zLœ­õLðVLLLL¥LLLLdVõL¥LL¥L LjL%zL%zL%zLªVõLðVL%Lu­LVL)FRR^R¥¥¥^^LL LL¥L L¥LLÃL’­õL¥LLjL%zL%zL%zLªVõLðV¥RR_¼ ^R^*¥¥¥¥¥¥¥¥^^^^^^^^ ^^^^èQððLèL!´bèL´bF¥^±^­ìQðQðL´f-ìQðQQL)ULLL-L-LLVR_B ¥¥^¥^s^oìQðQL)QðUL-ULLLLAvLìL‹VLLLðVL¹LVL)L­­LVLìLm­Lk­LVR_Ñ ¥¥¥^¥èQLìULLLLBvLìL‹VLL-LðVf"LìLm­L*L*ŒL¦VLþR^LìLm­LÀ­LþR¥¥_a èUððL!´f[èUðQðL´fJèQLìUðQQLLL-LðVLìL!´f^^ìL%´f`^ìL®­LVR_ ¥¥^^^^èQLìULLL-LðVL¹LVLL)LðVL½LþR¥¥_¿èQLLLLCvLìL‹þJ¥_£è*ðLèL!´b èL%´by^èìQL)ULL­LôLÀf LÊLVLLLðVLLæLL­L LLLðVèL ­ L-L VèL ­L)þiR¥¥^tìQL)ULL­LôLÀf LÊLVL­LLLLðVèL ­LLLðVL)L L­ŒL†­LVèL þaR¥¥^¥_£èQLìUL)*L*LLLLðVLLæLLLLðVL)LLV)LèðLèL!´b èL%´b ^BL-þq^:ìQL L æLL­ L L-LðV LL LVLìþ¥¥^¥¥R¥¥¥_úèQLìUL)*LL æLL¥L *L *L%zF LLLðVL‘LVL*LèðLèL!´b èL%´b^ LLqV^ ìULè¥^¥¥F L æLL)­L¹LVUL L ULL *LŽVF L LLðV L%Lu­LV LìFL)þiR¥¥¥_èQLìULL)L)Lþ[¥¥_èQLìUL)*LL LLLLL L zL/žºÁþc¥¥¥_ÎèQLèLèðLèL!´b èL%´b^2L¸LV^&ìQLL*LjLšVL!´L)LðV¥^¥¥*LLLDvL*L‹VL*L*ŒL|­LVLìF¥¥_DèQLèLèðLèL!´b èL%´b^^ìQLLL)LðV¥^¥¥*L*Lm­L*ŒñLèLLLEvL*L‹V*L*¸fL*L*ŒLu­LVL)FL¥LL L æõL * L%zF R¥_“*L*Lm­L*ŒñLèLLLFvL*L‹V*L*¸fL*L*ŒLu­LVL)FL¥LLL æõL* L%zF R_èQLìULLL-LðVLL)Lðþ[¥¥_ñèQðL!´fL¸LVLtLV_Ñ^^èQL—L¶L)LÎVL¨VLj ðôLL±Vl^ULèÐL¸f èLc­aèðLw ù´f3LGLðôLb­ˆLÆ­LVLðôL-L)L}Vè¥^ ^èL/“°*ö­¥LLìLz­LVLtLVL¹LVLLLHvL-L‹VL%Lu­LþZR¥_èQLj ð*LL±Vl^2LèÐL¸f èLc­aèðLw ù´f LßLqV^ ^èL/“°*ö­¥L*LìQ¸b*LT­LìôLšVL!¸f4ILìQL*LT­LÌ­L-ôLÌ­L *zL§VLLVJLì*L‹VèLjFèLL­LÁ­F¥¥_CèUðL%´ffèUUðL!´fVèQLìUQðL)UQôL-*LLLLL"LLLVõLLLŸVõLðVR_㥥¥¥^^^^èQLìUL)*LjÐL­LèðLìôLLL LðVLìLv­LVèL²LnVLèLKíL-L‹VL LLvLìLVLMLìLZV LèðLèL!´b èL%´b^$L¸LV^ìQLLL)LðV¥^¥¥L æLLLL LOvL)LVLL)­PLìLZVRl^îLèÐL¸f èLc­aèðLßUD´fÌLLLðVL¹LVLLLLQvL-LÎVL)LèðLèL!´b èL%´b^9 L¸LV^-ìQL L L L¥LLjL%zL˜­õLðV¥^¥¥L æL L LLL LRvL)LÎVLL)­SLìL‹V L%Lu­LVR^ ^èL/“°*öþY¥¥¥¥^¥RrèULìQL)ôL-ðL9UL-L=L‚­LLËVL_VèL=L…VìLL…þ:Rå9LìL-õLxþ"rèôL)ôLèL)ŒRr9L=Lz­LV9L¹LV9LìLƒ­LþåèôLìðL9L¸L=V9LtL=V9L)L[­L=V9L)L=LYvLìL‹þ*RåL‰­LjLL³­LL‰­LL‰­LL³­LL‰­zL)LL³­LL¬­LL¬­L!L!L!L!LÿÿÿÿLjLjLjLL³­L!L!õLUL zL-LÀfìULL€­LxVèLLLL9VèLLL=VèL­ìQLjLšVL!¸b ìôLb­L!¸f¬èQLì* LL³­LL³­LLìF L)FL!Ll­LVL)L)LVvLQLT­L‹VìL!L-L‚­Ll­L_VL³­LèLWíLôL¯VXLìLsVLLZvLìLZV-L)L…VL-L…VRìULìð*L)* L™VLxVèQL)UõRr\7DÜ7Ez7FS7Gš7HL/`ÐS­7…_KèLèðLèL!´b èL%´b^ƒL-L`þ*^gL-L`þ*^¥¥å9LLLLLL%zrrèLèðLèL%´b èL!´b^ì*Lè¥^!^¥¥å-L-L-L-LL9­LL9­LfVL%ˆLjþMr-L9­LìL9­LìLìLˆ¼fèLèðLèL%´b èL!´bÂ^ËìQL)UL-*L*L-L9­LìL9­Àf"-L-L-L-L L L L=VL=þ„^qèLèðLèL%´b èL!´bN^WìQL)UL-*L*LLLLL=VL-L-L-LLLL=VL=þ´¥¥¥¥^nL;Lcþ‚^¥¥¥¥¥¥^nL=LcþR^¥¥_èL)Lˆ¼fé)LèðLèL%´b èL!´bÃ^ÌìQL)UL-*L*LèL9­LL9­Àf" L L LL=VL-L-L-L=þ„^r-LèðLèL%´b èL!´bN^WìQL)UL-*L*LLLLL=VL-L-L-L L L L=VL=þ´¥¥¥¥^nLFLcþ‚^¥¥¥¥¥¥^nLHLcþR^¥¥^!LLLLLLfVL%ˆLjþ]RrèLèðLèL%´b èL!´b9^?ìQðL!´fìUL)*LèL)õR^$¥¥^^ìQLèL9ðþ)¥^ dLbþ!^¥¥åèLèðLèL%´b èL!´bQ^WìQðL!´fì*LèR^F¥^^ìQL)UL-*L*L-L9ð­L-L-L-L=þ\¥¥¥¥^ qLeþ!^¥¥åèL)õLèððL!´fì^;^^èôðL!´f)^*^^ìL9­LèðLìôLL)L)LL=­LþTR¥riLìõåiL_õåèôLiLaVL!´åèLèðLèL%´b èL!´b^¢ìQL)UL-*L*L*L9LL=VLèL!´fL9LLLLjþu^@èL!ÄfLð­LèLLLLþt¥^)Lð­LLLL-Lþt¥¥¥¥¥¥¥^iL9LLiL%LjþE^¥¥å)ðLñLèLL-LLL9Lwv‰èðaôLì­L)õRrèLèðLèL%´b èL!´bR^XìQL)UL-*L*L9L-L=VLèL!Äf Lðæ^èL!¼f ìLðæ^)¥¥¥¥¥^ dLbæ^¥¥åìðLñLèL-L-L-Lyv‰èða-ôLìæRrèLèðLèL%´b èL!´bw^xìQL)UL-*L*L9L-L=VLèL!´fL)LþR^7èL!ÄfLð­LLLLþd^LLLLð­Lþd¥¥¥¥¥^i^¥¥åìðLñLèL-L-L9LL=L{v‰èða-ôLì­L)õRrèLèðLèL%´b èL!´bH^HìQL)UL-*L*L9L-L=VLèL!´bèL!Äf^ìLðþI¥¥¥¥¥^^¥¥åìðLñLèL-L-L-L}v‰èða-ôLìþ)RrèLèðLèL!´b èL%´b^;^8ìQL)UL-*L*L-L9ð­)L)L=VèL9ðþA¥¥¥¥^¥¥åñLèLìLLv‰èðaìôLìþ!¥rèLèðLèL!´b èL%´b ^Ui^QìQL)UL-*L*L*LL9ð­L)L9ð­LìLLL=æL-LLjþ}R¥¥¥¥¥^¥¥åñLèLìLLv‰èðaìôLì­L)ðõ¥rèLèðLèL!´b èL%´b ^>-^:ìQL)UL-*L*LLL9ðæL)L=æLìL9ðæ¥¥¥¥^¥¥rñLèLìLLƒv‰èðaìL-ôL)æ¥r…7]÷7^^#¥i7_^#ýK7`^#e Ð7a^#&]7b^#ÆFÌ7c^#¶’¥ê7d^#ÎeK<7e^#¤ S7fhLèL!õ7i]Li?mªèLkí7j]Lj?"6ã3¥lLèLmíLìLìLovLñLñLìL)Lpí‰ìðeèLìLLrv‰èðaìLìLLsvLtLuLvLLxíLzLLL|vL~L€L‚L„L…L ?x …L?Dœˆ…L ?XØß…L ?¸¢Æ…L)?œ S…L ?î9VÈ…L-?ſŅL?8©–…L?çL…Lì?\ÀÃ…L?9лÃ…L?Üà?…L?:Úï…L?üfü…L ?ͱJ…L?!òIR……7IE7K7LL/`ÐS­7¢_¸ èLèðâA^…^^™^£^­^·^Á^Ë^Õ^ß^é^ó^ý____%_/_9_C_M_W_a_k_u__‰_“__§_±_»_Å_Ï_Ù_ã_í_÷__ ___)_3_=_G_Q_[_e_o_y_ƒ__—_¡_«_µ_¿_É_Ó_Ý_ç_ñ_û__¹L)Lþ"_ºL)Lþ"_ö»L)Lþ"_ê¼L)Lþ"_Þ½L)Lþ"_Ò¾L)Lþ"_Æ¿L)Lþ"_ºÀL)Lþ"_®ÁL)Lþ"_¢ÂL)Lþ"_–ÃL)Lþ"_ŠÄL)Lþ"_~ÅL)Lþ"_rÆL)Lþ"_fÇL)Lþ"_ZÈL)Lþ"_NÉL)Lþ"_BÊL)Lþ"_6ËL)Lþ"_*ÌL)Lþ"_ÍL)Lþ"_ÎL)Lþ"_ÏL)Lþ"_úÐL)Lþ"_îÑL)Lþ"_âÒL)Lþ"_ÖÓL)Lþ"_ÊÔL)Lþ"_¾ÕL)Lþ"_²ÖL)Lþ"_¦×L)Lþ"_šØL)Lþ"_ŽÙL)Lþ"_‚ÚL)Lþ"_vÛL)Lþ"_jÜL)Lþ"_^ÝL)Lþ"_RÞL)Lþ"_FßL)Lþ"_:àL)Lþ"_.áL)Lþ"_"âL)Lþ"_ãL)Lþ"_ äL)Lþ"^þåL)Lþ"^òæL)Lþ"^æçL)Lþ"^ÚèL)Lþ"^ÎéL)Lþ"^ÂêL)Lþ"^¶ëL)Lþ"^ªìL)Lþ"^žíL)Lþ"^’îL)Lþ"^†ïL)Lþ"^zðL)Lþ"^nñL)Lþ"^bòL)Lþ"^VóL)Lþ"^JôL)Lþ"^>õL)Lþ"^2öL)Lþ"^&÷L)Lþ"^øL)Lþ"^ùL)Lþ"^¥å9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìL zåå9LìL zåå9LìL zåå9LìL zåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìL8zåå9LìL9zåå9L)L)L?zrrèLèðâ^^^#^-^7^A^JUL)Lþ"^>VL)Lþ"^2WL)Lþ"^&XL)Lþ"^YL)Lþ"^ZL)Lþ"^¥å9LìL!zåå9L)L)L%zrr9LìLzåå9LìLzåå9L)L)Lzrr9LìLzååhLìLþåèØåèLèðâA^…^†^‡^ˆ^‰^Š^‹^Œ^^Ž^^^‘^’^“^”^•^–^—^˜^™^š^›^œ^^ž^Ÿ^ ^¡^¢^£^¤^¥^¦^§^¨^©^ª^«^¬^­^®^¯^°^±^²^³^´^µ^¶^·^¸^¹^º^»^¼^½^¾^¿^À^Á^Â^Ã^Ä^Å^Å^Â^¿^¼^¹^¶^³^°^­^ª^§^¤^¡^ž^›^˜^•^’^^Œ^‰^†^ƒ^€^}^z^w^t^q^n^k^h^e^b^_^\^Y^V^S^P^M^J^G^D^A^>^;^8^5^2^/^,^)^&^#^ ^^^^^^^ ^^^¥åèLèðâ^ ^^^^^^^^^^ ^‹^^^__{_yèQLèL9­Lj+=LL“VLèL¸fmLˆLnˆLìˆL·­¥l^?LèÐL¸f èL¯­aèðLw ù´f=L)LL«VL-L¦V^ ^èL/“°*ö­¥¥¥_¥^üèQLèL9­Lj+=LL“VLèL¸fmLˆLnˆLìˆL·­¥l^?LèÐL¸f èL¯­aèðLw ù´f=L)LL«VL-L¦V^ ^èL/“°*ö­¥¥¥^„¥^èQLèL9­Lj+=LL“VLèL¸fmLˆLnˆLìˆL·­¥l^?LèÐL¸f èL¯­aèðLw ù´f=L)LL«VL-L¦V^ ^èL/“°*ö­¥¥¥^¥^¥å9L)L=ðLšV=L=ðL)L­f^%ˆ‰rL¸­LL’­L9L)L)LovL-LžV!ñL-L³­L%ˆL!LŽVLèL)L=LpvLL™VèLL³­L-ðLšVèL)ðLzRå9LìL¬V9L!L§þå9ðL!¼f|9ðL¼f)=LLœL¨LªV9L9ðLŒ‰èLðþ^LèLðŒLèL!¼fèLÄfè^!L=LìLœL9ðLœ¨L¨LªV9L!‰LðL)ˆ‰RåèôLìðLèL9ð¸fDìL=­9Lì‰ðf"LìL L%¨LªVLìLÿ¬LªV^LìL%œL%¨LªVìLð¸fìL=­ìLð´fLðL%ˆ‰^]ìLðŒLèL!¼fèL ÄfLìLœL¨LªV^,L-LœLªVL-L LªVL-L  LªVL-‰¥RåìL³­LñLìL€ÄfL)LªV^7ìL€Äf)èL‰L)L L€¨LªVL)Lÿ¬LªV^ rL¡­LsíLLžVL-L³­L•V!ñL!ñL!ñLñLèL)LL-LLtv‰èða-LìLL LLLuvLLžV)ðLìþQRrèLèðâ^^2^b^‰^¬^Ï^çèQL9L%LªV9LìL¬V9L!L§þ*¥^ÂèQLìUL9LLªV9L=L-L­VL)Lœ¨L•þ2¥¥^èQL9LLªV9LìLŸ­LœV9LìL¬þ*¥^gèQL9LLªV9LìL¬V9L!L§þ*¥^BèQLìUL9LLªV9L)L)Lþ;¥¥^èQL9LLªV9LìLªþ*¥^¥å9LìL¬V9L!L§þå9ñLìLèðâA^…^‡^‰^‹^^›^­^»^É^Ü^Þ^ð____-_@_B_P_R_T_b_p_~_¥_Ì_ó___*_8_F_H_J_L_N_P_R_T_V_X_Z_\_^_`_b_d_f_h_j_l_n_p_r_t_v_x_†_”_–_˜_š_œ_ž_»_Â!_¾%_º_¶_²èQL)L쉥_¢èQL)LìLŒ‰¥_ŽèQL)L쉥_~èQL)L쉥_nèQL)LìL=­‰¥_Y _UèQL)LìLŒ‰ ¥_AèQL)LìL=­‰ ¥_,èQL)Lì‰ ¥_èQL)Lì‰ ¥_ èQL)L쉥_üèQL)LìL=­‰¥_ç_ãèQL)L쉥_Ó_Ï_ËèQL)L쉥_»èQL)L쉥_«èQL)L쉥_›èQL)LLL-ˆL­VLLL­VŒ‰¥_rèQL)LLL-ˆL­VLLL­VŒ‰¥_IèQL)LLL-ˆL­VLLL­VŒ‰¥_ èQL)LLL-ˆL­VLLL­VŒ‰¥^÷^óèQL)L쉥^ãèQL)L쉥^ÓèQL)L쉥^Ã^¿ ^»!^·"^³#^¯$^«%^§&^£'^Ÿ(^›)^—*^“+^,^‹-^‡.^ƒ/^0^{1^w2^s3^o4^k5^g6^c7^_èQL)Lì‰8¥^OèQL)Lì‰9¥^?:^;;^7<^3=^/>^+èQLìUL-L)L)Lœ¨‰?¥¥^ ìL@‰!^¥LìðLèL9´fL)LœLªþ:^yìL ÄfèL!´bèL%´fL)LœL)Lœ¨L%¨Lªþ:^HèL!ÀfèLÿÈfL)LœL¨LªVLìLªþ:^L)LœL¨LªVLìL•þ:RrèôLìðL-LwL¬VìL9­LèðLìôL)QLLL³­L•VL-L³­L•VLìL•VL)L=LxvLLžVLyíL-LžVLL-LLzvLL™þRRRr9L¤­LèL!´f =L°þ^=LìL¨VLðþ¥åL ­LñLèL-L-L-L|v‰èðaLìþ!Rå9L=þåèL9´f_Q=L­LèL%¬L!¸fJðf=L­LìL% LœL쨥^èL% LèLL³­Àf €L¡­Lì‰)Lðþ!¥^ôèL¬L!¸f`èL LìL L¬L!ñLèðL)Äf'LL)ðˆLðLðõLšVèLìðL%ˆ‰_ÕÿÿÿLðLˆ‰L)ˆLðþ1R^‹èL¬L!¸f3LðL)L ˆ‰L)LðLðõLšVìL%ˆLðþ^O=L­L=L­LL-L L-Lœ¨L)L œ¨‰LLðLðõLšV-L%ˆLðþ)R¥åèL­LñLìL€Äfì^èL‰)L­L)L¬LœL쨥LèL!´f ~L¡­èLL9LvL¥VLL˜­L!ñL!ñL)L!L!õLŽVLñLèLL LLLLLLLv‰èða!Lì­ìLõR å9L­Lèâ^^^^:^T^b^|^Š^ˆ9L=­L\­^^x9L˜­LèLÿÿÿ¬LìL L^V¥^c^Z9L—­L9LìL›VL`­¥^G^>9L=­Lb­^7^.9L­LèðLìôLìLìLdVR^^9L­Lf­^ ^jL´þ¥åèL!´f^r9L=­LèL­Lj LL“VLLì¸f jL´­¥l^ALèÐL¸f èL¯­aèðLw ù´fL)LL«V-L%ŒLð­^ ^èL/“°*öþ)¥Rå9LìL­VLèLÿÿÿÿ´f jL´­èL-Œ¥rèôLìðL9L)L9LL¢VLèðâ^6^4^2^0^.^,^*^(^&^$^"^ ^^^^^^^^^^ ^ ^ ^)^F^c^€^~èQLLL)ˆL=VL!­¥^m¥^_èQLLL)ˆL=VL#­¥^N¥^@èQLLL)ˆL=VL%­¥^/¥^!èQLLL)ˆL=VL'­¥^¥^…LSL–V¥L©þ3RåèLèðL%´f1èQLìUL9LL!LL=VL-L^VLšVR^ ¥¥^^¥rk¯LL›VLèLw¸f jL´­L˜­LL˜­LL˜­L)L!Äb)Lÿÿ¼bìL!ÄbìLÿÿ¼bèL!ÄbèLÿÿÿ¼f jL´­)L L9L=LƒvL¥VLL¸­LñLèL L9LLLL„v‰èðaLì­-L%ˆLÿÿÿÿLŽVL!ñLµñLL’­L)ðLÄgˆL­LèL¬Lèâ^ ^^-^T^f^dL)L õ^a^UìL L%¬L)L õ^K^?ìL´fLL­õ^L­L)L õ^"^L˜­L)L õ^^…LüL–V¥LèðLìôLìLèâA^†^Š^Ž^’^–^ž^ª^²^º^ý__ _P_X_`_h_«_¯_·_»_¿_Ç_Ï_×_ý_#_I_o_s_{_ƒ_‹__“_—_›_Ÿ_£_§_«_¯_³_·_»_¿_Ã_Ç_Ë_Ï_Ó_×_Û_ß_ã_ç_ë_ï_÷_ÿ___ ___&_*_(û_+_"ü_%_ý__þ__ìLÿ­__ìLˆL­__øìL­_÷_îìL­_í_äjLL“Vl^/LèÐL¸f èL¯­aèðLw ù´f jL´­^ ^èL/“°*ö­¥L­_¨_Ÿ _¢_™ìLˆL ­_”_‹jLL“Vl^/LèÐL¸f èL¯­aèðLw ù´f jL´­^ ^èL/“°*ö­¥L ­_O_FìL­_E_<ìL­_;_2ìL­_1_(jLL“Vl^/LèÐL¸f èL¯­aèðLw ù´f jL´­^ ^èL/“°*ö­¥L­_ì_ã_æ_ÝìL­_Ü_Ó_Ö_Í_Ð_ÇìL­_Æ_½ìL­_¼_³ìL­_²_©L®LL³­LðõLðL%z‰ìL!­_Š_L®LL³­LðõLðL%z‰ìL#­_b_YL®LL³­LðõLðL%z‰ìL%­_:_1L®LL³­LðõLðL%z‰ìL'­__ )_ _ìL*­_^ùìL,­^ø^ïìL.­^î^å0^è^ß1^â^Ù2^Ü^Ó3^Ö^Í4^Ð^Ç5^Ê^Á6^Ä^»7^¾^µ8^¸^¯9^²^©:^¬^£;^¦^<^ ^—=^š^‘>^”^‹?^Ž^…@^ˆ^A^‚^yB^|^sC^v^mD^p^gE^j^aF^d^[G^^^UH^X^OìLI­^N^EìLK­^D^;M^>^5N^8^/O^2^)P^,^#Q^&^ìL¬L)L LRV^^T^ ^jL´­¥LLðLL³­LšVLðL)L­f^%ˆ‰LìL¦VR_sûÿÿ)ðL¸f jL´­-L-ðL)L³­LšV-L†íLìLìL‡vL-ðL‘VLìLˆvLL™VìLõR l^KLèÐL¸f èL¯­aèðLèLÀà´b èLt! ´b^jL´­¥^^jL´­¥^ ^¥èL/“°*öþ¥å9LŽL)Lèðâ^^^\^p^€^Ä^ÓèQL,LìL²­ˆ¥^ÁèQLìULìL!ÀfìL=ÄfL)LLšVL)L¶­ˆLˆLìL¶­ˆ¥¥^‚èQL‘LìL²­ˆLˆ¥^lèQL’LìL²­ˆ¥^ZèQLìULL­LèðLìôLìLLLV“LL)­LŸ­LL³­õL±VR¥¥^èQL”LìL¶­ˆ¥^¥LõL£þ+r9L—L)LŸ­LÀfE^L-LŸ­ŒL L”VL-L=­LzL£þ#åìLEˆLìL¶­ˆr9L)L­Vf =L L§V=L›L-L-Lèðâ:^t^r^p^n^p^ƒ^–^©^¼^b^É^Ü^ë^þ__$^T_1^P^N_@_S_f_y_‘_©_Á^>_×_ê_ý^6^4^2^0^.^,^*^(^&^$^"^ ^^^^^^^^^^ ^ ^^_Þ_ñ__èQL½LìLV¥_ø¥_íèQL¾LìLV¥_ã¥_ØèQL¿LìLV¥_Î¥_ÃèQLÀLìLV¥_¹¥_®èQLœL숥_¨¥_èQLÃLìLV¥_“¥_ˆèQLL숥_‚¥_wèQLÅLìLV¥_m¥_bèQLÆLìLV¥_X¥_MèQLÇLìLV¥_C¥_8èQLžL숥_2¥_'èQLÊLìLV¥_¥_èQLÍLìLV¥_¥^ýèQLÎLìLV¥^ó¥^èèQLÏLìLV¥^Þ¥^ÓèQLÐLL)ˆLV¥^Ä¥^¹èQLÑLL)ˆLV¥^ª¥^ŸèQLÒLL)ˆLV¥^¥^…èQLÓLL)ˆLV¥^v¥^kèQLÕLìLV¥^a¥^VèQLÖLìLV¥^L¥^AèQL×LìLV¥^7¥^,èQLñLìLV¥^"¥^èQLòLìLV¥^ ¥^L¶­¥LðzL£VLðL)L­f^%ˆ‰rèôLìðLìL9­LèðLìôL)QLLŠLL³­L£VL‹LL³­L£VLŒL)LL³­õL£VLLL£VèLLŽVLL)L)L=L•vLL™VL–LL£VLL˜vLLžVL™LL£VšL!ñL)L L-L-LLŸvLL™VL LL£þsRRr¢7†Ü7‡7ˆz7‰š7ŠE7‹ 7Œ÷7Š#î9VÈ7Žˆ#Ñî17#ýK7‰#Å¿Å7‘Š#üfü7’‡#9лÃ7“‹#î9VÈ7”ˆ#¨æõÜ7•#ÆFÌ7–ˆ#Çp>7—ˆ#ŸÌ9ü7˜Š#Q° Â7™#!n7šˆ#VK§Ë7›ˆ#ÙtK7œˆ#q·„÷7Š#Å¿Å7ž‹#æ”7ŸŒ#üfü7 #ÎeK<7¡Š#–€N7¢ˆ#™Ïa17£ˆ#ŸWŠ27¤Š#;»Å7¥Š#!òI7¦ˆ#veö7§Œ#ô0Û7¨Š#¢›W7©ˆ#¨ÅÈõ7ª‡#!òI7«ˆ#ßlYÐ7¬#S7­#!Ê|Õ7®#7ä.7¯Œ#Ñ(07°#L(†ß7±‹#CÚÚ7²Š#æ”7³#&]7´#MR±7µ#Ñ(07¶#ÈË)ó7·‡#üfü7¸úLèL!õ7û†Lû?HÛØèL%õ7ü†Lü?!ÐÜèLõ7ý†Lý?ÂDm>èLõ7þ†Lþ?€ÈÜèLí7ÿ†Lÿ?NÆ…?èLí7†L?gv)ÇèLí7†L?d]áèLí7†L?L½‚?èLí7†L?Ù£±ÃèL õ7 †L ?¸|­èèL í7 †L ?1ª2èL í7 †L ?‚WÞÁèLí7†L?fŒñëèLí7†L?…†,)èLí7†L?‹ù#èLí7†L?عyèèLõ7†L?·’u èLí7†L?0Àú%èLõ7†L?oÑßèLõ7†L?ú=:5èLí7†L?q=èLí7†L?¾D“,èL í7†L?Ä%9èL"í7!†L!?ñB1èL$í7#†L#?‹¬<èL&í7%†L%?H)ZæèL(í7'†L'? ÂÜ7èLõ7)†L)?HwyüèL+í7*†L*?A‘>èL-í7,†L,?j)èL/í7.†L.?«ÄúèLõ70†L0?J°ô+èL õ71†L1?±× èL!õ72†L2?P† äèL"õ73†L3?ª1èL#õ74†L4?`a?èL$õ75†L5?”>3èL%õ76†L6?1õ3èL&õ77†L7?¢Î:èL'õ78†L8?V?èL(õ79†L9?V?èL)õ7:†L:?èxn8èL*õ7;†L;?CEèL+õ7<†L<?·²1èL,õ7=†L=?{'CèL-õ7>†L>?Œ<èL.õ7?†L??:ˆ;èL/õ7@†L@?M>èL0õ7A†LA?xE6èL1õ7B†LB?¨BèL2õ7C†LC?½:èL3õ7D†LD?ó;èL4õ7E†LE?‘NË èL5õ7F†LF?…@ºÐèL6õ7G†LG?î[á/èL7õ7H†LH?@ˆ;èLJí7I†LI? ¤ƒ8èLLí7K†LK?Nõh7èL:õ7M†LM?é#ýèL;õ7N†LN?ê#ýèL<õ7O†LO?ß@" èL=õ7P†LP?à@" èL>õ7Q†LQ?Ó\@èLSí7R†LR?n?‚ÝèL@õ7T†LT?„Ò2¥[LèL]í7\†L\?$‡úèL_í7^†L^?»Ç€ èLaí7`†L`?´Æ7èLcí7b†Lb?µ?èLeí7d†Ld?ÐAèLgí7f†Lf?Õoë¥iLèL»gÁ(õ7j†Lj?$<ÑLLkLlLìLìLqvLvLìLìLLL{vL}LèL‚íLìLìLLLL‰vLLLLL¡vL¢L?y/^Ý¢L?ßlYТL ?ï/÷ ¢L?Ú¥A¢L-?pd{ñ¢L)?VK§Ë¢L?¯7€7¢L?p‡!>¢L?IÚ•¢Lì?4}r¢L?·äUR ¢¢7M÷7NM#¯7€77OL#ƒ*=7PM#0Àú%7QM#ï/÷ 7RM#µ?7SF#cÙV7TM#¢Î:7UM#J°ô+7VM#Nõh77WM#j)7XK#æ”7YH#Å¿Å7ZM#…†,)7[M#½:7\M#:ˆ;7]M#ß@" 7^H#¢›W7_M#à@" 7`M#CE7aE#æ”7bN#7ä.7cL#5ê`*7dN#i£W7eM#ó;7fM#´Æ77gM#L½‚?7hM#oÑß7iN#MR±7jM#Ä%97kM#ñB17lF#æ”7mH#î9VÈ7nN#ýK7oM#NÆ…?7pN#ÆFÌ7qK#€©W7rH#^'XÌ7sM#@ˆ;7tM#q=7uM# ¤ƒ87vL#в¦Ê7wH#!òI7xM#Ó\@7yM#d]á7zM#1õ37{M#A‘>7|E#!òI7}M#{'C7~N#>#÷-7M#Õoë7€M#‘NË 7H#æ”7‚M#عyè7ƒM#¨B7„H#ÚáÓ7…M#‹¬<7†M#€ÈÜ7‡I#Å¿Å7ˆE#üfü7‰M#H)Zæ7ŠF#Å¿Å7‹M#‹ù#7ŒI#9лÃ7I#!òI7ŽM#î[á/7H#œ S7M#Hwyü7‘L#ÞN+ô7’M#gv)Ç7“E#Üà?7”M#V?7•N#!n7–N#¥i7—L#ÈÊÉÞ7˜M#ÐA7™N#e Ð7šM#·’u 7›L#‘^Èó7œL##oÍÜ7M#Œ<7žL#‚›47ŸM#!ÐÜ7 N#¹È7¡M#xE67¢L#ÏÄ77£M#`a?7¤N#!Ê|Õ7¥M#n?‚Ý7¦N#L(†ß7§F#^'XÌ7¨N#&]7©L#ƒK9ç7ªM#”>37«I#:Úï7¬M#Ù£±Ã7­M#1ª27®E#Å¿Å7¯M#V?7°E#9лÃ7±N#Ø>ã37²H#üfü7³M#èxn87´M#P† ä7µN#‡ÊM7¶M#ÂDm>7·M#HÛØ7¸M#ú=:57¹M#fŒñë7ºL#Å¿Å7»M#«Äú7¼M#¸|­è7½M#…@ºÐ7¾M#‚WÞÁ7¿M#¾D“,7ÀN#O177ÁM#±× 7ÂL#~2Õ77ÃG#œî17ÄM#·²17ÅM#$‡ú7ÆM#é#ý7ÇM#ª17ÈM#ê#ý7ÉM#„Ò27ÊM#»Ç€ 7ËN#Ñ(07ÌM# ÂÜ77ÍF#œ S7ÎM#M>7Ï×LèLÙí7ØDLØ?u‚_:èLÛí7ÚDLÚ?З ÆèLÝí7ÜDLÜ?Ûw§'èLßí7ÞDLÞ?BÅ(ÃèLáí7àDLà?šË©èLõ7âDLâ?!ž$èèLõ7ãDLã?Ö>ã¥äLèLæí7åDLå?¨;WçLèLéL)LëíLìLíL-LîíL)LìLðvL-L)LòvLL-LôvLLLõvLöL÷LùLûL LíLLLñLèLìLLLv‰èða LLvLñLñLñLñLñLñLñLñLLL)LLLv‰ð2LLí‰ð2LL í‰ð2LLL"v‰ð2-LL)LLLL L L#v‰-ð2)LìLLLL L'v‰)ð2ìLìLLLLL LLL=v‰ìðeèLLLLLLLLLLLLLLLLLL+LLTv‰èðaLìL LL[vL\L?Á$\L?ßlYÐ\L?í•Í\L?<*Æ\L?7·Ë\L ?Á•Ðù\L?Öz\L?™· \L ?ä-8é\L?”]U\L ?H²>\L?MÎP\L?£™iÄ\L?c1²'\L ?)ª²Í\L? ¯­ú\L?ÈË)ó\L?¤¶`\L?ðÌ«(\L-?—¬Ú\L?œžä7\L?Ó Ò\L?Ç—Ò\L?0fÎ\Lì?s%o\L?ÊíÀÁ\L?Q p-\L ?«¤`$R\\6 S6 E6 L/`ÐS­7_\®LìLËþå9LìLûÅ3*zååëLLÎþ"rjÜLíL¶VLèLîL¬VLèðLèL!´bèL%´b¥^>^:ëL#LÎV¥^„^*ìUðL!´fìQLèLÁ­L ðõR^d¥^¥^^¥èLèL±­LèðLèL!´b èL%´b^5ëL'LÎV^)ìQL)ULìLÁ­LîL)L±­L­Võ¥¥^¥¥¥¥LèðLìôLèL QL ULzRl^*LèÐL¸f èLíaèðLw ù´f)^ ^èL/“°*öþ!¥rðLØæå9LÚ­LèðL%´fUèUðL%´fGèUUðL!´f7èQLìUQL=L=L-LðVL=L-LðVLæõR^¥¥^^ ^^^^Lþ¥åjLЭLÞ­l^LèÐL¸f èLíaÍ^èL/“°*ö­¥LèLèðLèL!´b èL%´b ^Í^ìQL9LìL=ðVLÞ­¥^¥¥L)LöL¶Võ¥åìLìLÒL»þ+rèL)LÓL»þ+rìL9L)LÌþ+r9LìLЭL=ðVLìLöL¶VõåèLÊ­LèLèL´bèL ´bˆ¥^½^¹)LÚ­LèðL%´fLèUðL%´f>èUUðL!´f.èQLìUQL9LìL=ðVL9L-L=ðVõR^¥¥^^ ^^^^L­¥LLÂL)LðL%z‰¥¥^i^9ðLÍLµVL!¸fL­L9LLЭL=ðVLÞ­‰¥^2^¥ðLÍLµVL!¸fL­L9L-L=ðVLÞ­‰¥åñL)L)L9VL)LìL=LLòvL-LÊ­LèLèLó´b©èLô´bÊèLõ´bæèLö´cèL÷´cËèLí´céèLø´cèLù´c+èLú´c‡èL´cèL´c­èL´c³èL ´c¹èLû´cžèL2´cµèL ´cÌèL ´cüèL ´ckèL:´cÚèLü´càèLý´cæèLþ´cèL´cèLÿ´c“¥_·_³LöL¶VLÁ­LLìL½­L¯­õ¥¥_¢_‹LöL¶VLLìL¾­L¯­õ¥¥__hLöL¶VLLìL·­L²­L¯­õ¥¥_W_@LöL¶VLèL!LÕVL$´f(LìL%L-L¸­L%ŒLÏVL®­L¯­õ^…èLèLèLÿ´bèL´b(èL´b3èL´b>¥^N^JL°L¯­õ¥^M^8LáL¯­õ¥^;^&LÀL¯­õ¥^)^LâL¯­õ¥^^¥L)LÛ­L¯­õ¥¥¥_Œ_u-LL=ðæLLÚ­LçVL´­õ¥_g_P-LLLЭL=ðVLã­õ¥_G_0LöL¶VLLLLЭL=ðVL)LÄVõ¥¥__LÚ­LèðLèL!´b èL%´b ^?L­^7ìQL)ULLL-L=ðVLL=ðæL-LçVLÅVõ¥¥^¥¥¥_´_ßL-­¥_§_-LL=LvLLÚ­LçVL¹­õ¥_€_iL-­¥_s_\L-­¥_f_OLÚ­LèðL%´fÎèUðL%´fÀèUUðLèL!´bèL%´bA¥^­^¡ìQL)UQLLL-L=ðVLL-L=ðVLÍL¼VõR^~¥¥^hìUUUðL!´fTìQL)UQL-UUQLLLL=ðVLLL=ðVL LL=ðVLÞ­L¼VõR^ ¥¥¥^¥^^¥^^^^L­¥¥_z_cLöL¶VLèLºæL­¥¥_\_ELöL¶VLèLíL­¥¥_>_'LöL¶VLîL¬VLLìLLLЭL=ðVLÑVõ¥¥__ðj LЭLÞ­l^LèÐL¸f èLíaÍ^èL/“°*ö­¥LLìLèðLèL!´b èL%´b ^Í^ìQLLìL=ðVLÞ­¥^¥¥LÖ­õ¥¥_‘_zj LЭLÞ­l^LèÐL¸f èLíaÍ^èL/“°*ö­¥LLìLèðLèL!´b èL%´b ^Í^ìQLLìL=ðVLÞ­¥^¥¥Lå­õ¥¥__-LÜõ¥_^÷ÝL-­¥_^ê-LL=LvLLÚ­LçVLÔ­õ¥^Ú^ÃLöL¶VLLìLÙ­õ¥¥^¼^¥ÇñLÍñLÍñLL=LLLLLvLLÚ­L«VèðLèðLèL!´b èL%´b ^*L­^"ìQLLìLðL±­LðL³Võ¥^¥¥R¥^?^(LÈ­LLðVLèðLìôLL)õR¥^^¥èLLìˆLé­LÆþA¥¥RrìLà­LèLÚ­LèðL%´f3èQðL!´f%èUðL!´fèQL-LìL9V¥^¥^^ ^^^^ LØþ)¥¥rèôLìðLöLÂL)LöõLÇL%zL-LèðLèL!´b èL%´b ^$Ç^ ìQLÂL9L)L=ðVLÇL%z¥^¥¥L¿þ3RåèôLìðLöLÂL)LöõLÇL%zLÂL9LL=ðVLÇL%zL¿þ3RåèôLìðLLÇLÂL9LL=ðVLÂL9LL=ðVLÇL%zL%zL¿þ3RåèLèðLìôLsñLÍñLÇñLLèðâ^)_;_]_…_¾_ú_<_`__†_Û__r_À___W_{_“_-èQLèLèðâ ^^-^E^]^u^’^ª^Â^Ú^ñLö‰L)L×­LÞ­‰^×Lö‰L)L×­LÞ­‰^½Lö‰L)L×­LÞ­‰^£Lö‰L)L×­LÞ­‰^‰èQLLó‰LìLæ­LÞ­‰¥^jèQLLô‰LìLÞ­‰¥^PèQLLõ‰LìLÞ­‰¥^6Lö‰L)L×­LÞ­‰^Lö‰L)L×­LÞ­‰^¥¥_èQLL÷‰)LL9ðæL)LçV‰¥_õèQLLí‰)LÂLL-L9ðVLÇL%z‰¥_ËèQLìULLø‰LìLÞ­‰-LÂLLL9ðVLÇL%z‰¥¥_èQLìULLù‰-LÂLLL9ðVLL9ðæLLçVL%z‰¥¥_RèQLìULLú‰-LÂLLL9ðVLÂLLL9ðVLÇL%zL%z‰¥¥_èQLL‰)LL9L vL)LçV‰¥_èè*ðLèL!´b èL%´bJ^ŒìQL)ULL‰LÂLLL9ðVLÂL LL9ðVLÇL%zL%z‰¥¥^GìQL)ULL‰LÂLL-L9ðVLÂL LL9ðVLÇL%zL%z‰¥¥^¥_DèQLìUL)*LL ‰LÂLLL9ðVLÂL LL9ðVLLèðLèL!´b èL%´b ^$Ç^ ìQLÂLL)L9ðVLÇL%z¥^¥¥L%zL%z‰¥¥¥_¾èQLìUL)*LL2‰L)LÞ­‰LÂLLL9ðVLÂL LL9ðVLÇL%zL%z‰¥¥¥_gèQLìULL ‰LîL-L­VLÞ­‰-LÂLL-L9ðVLÇL%z‰¥¥_#èQLìUL)*LLû‰L-LÞ­‰LÂLLL9ðVLÂL LL9ðVLÇL%zL%z‰¥¥¥_ÌèQLL ‰)LìLèðLèL!´b èL%´b ^$Ç^ ìQLÂLL)L9ðVLÇL%z¥^¥¥‰¥_|èQLL ‰)LìLèðLèL!´b èL%´b ^$Ç^ ìQLÂLL)L9ðVLÇL%z¥^¥¥‰¥_,-L:‰_#èQLìULLü‰-LÂLLL9ðVLÂLLL9ðVLÇL%zL%z‰¥¥^ßèQLLý‰)LL9L vL)LçV‰¥^¹èQLLþ‰-LìLÞ­‰¥^ŸèQLìUL)*LL‰L9L vL)LçVLLÂLLL9ðVLLèðLèL!´b èL%´b ^:^6ìQLÂL LÇLÂLLL9ðVLÇL%zL¿VLL%z¥^¥¥L%z‰¥¥¥¥^¥-ðLð¸f ÂLðLîˆLôˆLíõLÇL%z^(-ôLô¸fÂLôLæ­LíõLÇL%z^ÇL)ðLèðLèL!´b èL%´b ^Ç^ìQLÂLìLöõLÇL%z¥^¥¥LðL)L)LÉVLðL¿þkRräLìL9þå7£z7¤S7¥E7¦7§L/`ÐS­7Y_ËèLèðâ^ ^^^)^2gL)Lþ"^&(L)Lþ"^)L)Lþ"^*L)Lþ"^¥å9L-L-L-L!zrr9LìL%zåå9LìLzåå9LìLzåå®LìLþå9LìLÛTÎ5zåå L #xBLL)L0­õ?xBLå L #xBLL)L.­õ?xBLåèL/°ñm­LèL/¢å1&­LL!LèL-Äf.-Lì$L)LL)L/ÿAVL)L/º”“­õõ2ìL%ˆe¥_Ïÿÿÿ L)L #xBLL #Hg Lz?Hg  L?xBLRr #Hg L #xBLL L)QL-ðLôLL# sÛµLLL# sÛµL,Võ?xBL L)U?Hg Rá8ÜLL?Hg èL?xBLèL9? ÄÃèL:?- èL;?×m[èL<?‚ðmÂè¥áá7©Lj#LL>V#xBLLL# sÛµL2­lrl^LèÐL´f èL5­L/“°*ö­èL/“°*öþ!¥¥åèLèðL!´f^^^¥åèLèðL%´f^^^¥åèLèðL´f^^^¥åèLèðâ^ ^^!^(^6è*L9LìLþ*¥^%DL%þ^DL%þ^èQL9LìLþ*¥^¥åèLèðâ^ ^^!^(^6è*L9LìLþ*¥^%FL%þ^FL%þ^èQL9LìLþ*¥^¥åèLèðL!´fèQLè¥^¥^^HL%þ¥åèLèðLèL´bèL%´b¥^0^,ìQL9LìL#VR^$¥^ìQL9LìL#VR^¥^¥JL%þ¥åèLèðL!´f+è*LL$­LèLKíL)LVèL­¥¥^¥^^JL%þ¥åèðLèL­L9´¥åèL­L)LèðL!´f!èUL)LMíLìLVL!­¥^¥^^NL%þ)¥¥rèôLìðLELìˆLQˆL)L"­ˆLˆRåèLèðâ^ ^†^•^¸^ÌèQLìUL)*LLPLsLRLL'VLVLõL&VèLèðL!´fLSLV^0^^èLL$LVL9ðæLìLVLTLL&þ[¥¥¥¥¥^OèQL-LìLþ2¥^>èQL-LULV-LìLV-LVLþ2¥^èQL-L9ðæLìLþ2¥^¥rL ­LèðLìôLìLL9VLìþ)RåÜ788L? ÄÃ8L?xBL8L?‚ðmÂ8L?- 8L?Hg 8L?×m[Y7z77E7 7÷7#ýK7#Å¿Å7#9лÃ7#ßlYÐ7# ÐÇ7#¸57#üZ7#1­¥æ7#Ñ(07#q·„÷7 #i£W7!#CÚÚ7"#!òI7##üfü7$#ÎeK<7%#™Ïa17&#œ S7'+LèL-í7,L,?"6ã3èL/í7.L.?½=¢=èL1í70L0? `ÁèL3í72L2?;«Äô¥4LèL6í75L5?¨;WL=77?LL/HoØL#Œg%ÐZ7>@LALBLCL)LEíL-LGíLILLLOLñLèLìLWí‰èðaèLXíLYL)?ßlYÐYLì?UJêáYL ?3U=YL?1¸¾YL?JWYL?èü YL?’”+0YL?·YsYL?¸2ËâYL?R†ØÿYL-?JçàYL ?~«öR YY7¨÷7ª¤#Å¿Å7«¦#Úên7¬¦# ÐÇ7­§#ƒ*=7®§#ÞN+ô7¯§#nÓÜ77°¤#cÙV7±§#ñœÄÅ7²§#ÀV/7³§#ÈÊÉÞ7´ª#e Ð7µ¨#Jçà7¶¦#šr!Ý7·¦#æ”7¸§#‘^Èó7¹§##oÍÜ7º§#,™Šó7»§#‚›47¼§#ÏÄ77½§#|5Ä7¾¨#"6ã37¿§#§Êç37Àª#ï P7Áª#!Ê|Õ7ª#7ä.7ç#5ê`*7ħ#ƒK9ç7Ū#&]7ƪ#MR±7Ǩ#JW7Ȥ#ÚáÓ7ɨ#èü 7ʪ#ýK7˧#öÙÛ-7̪#Ø>ã37ͪ#ÆFÌ7Φ#€©W7Ϩ#R†Øÿ7Ч#}´É7ѧ#ê«!;7Ò§#L;Ê7Ó§#äôÿ7Ô¦#–€N7Õ§#Õ ó7Ö§#ð‘§Î7ת#ÎeK<7ا#oc|7Ù¨#1¸¾7Ú§#в¦Ê7Û§#Ì鋿7ܧ#Ø·î7ݪ#O177Þ§#Ã\Ï7ߨ#3U=7à§#ƒ¥|7á§#~2Õ77â§#‘¦?7ã¥#œî17ä§#:z¹â7åª#Ñ(07æ¤#œ S7çèLèLêí7é£Lé?¨;WìñLïLñLèL)L)LLv‰èðaèL íLñLèLìLí‰èðaèLíLL)?¤õÓLì?Óñ L?‹ØóÛL?f0 L?HÈíÛL-?3U=R6L/`ÐS­7¡_ “L‘­LèL­LèL!¼fìLìL%ŒL€VL!´f9L)L!L-L%ŒLpVLþ*^9L)LV9L LˆVL=ðþ!RåL‚­LñLèL)L)L•v‰èðaLì­ìLþ!RåƒLzL)Lm­LLLŠ­zL‡þ+rèLèðL!´fTèQLj9LLlVL=L L)L}V¥l^)LèÐL¸f èLŽ­aèðLw ù´f^ ^èL/“°*ö­¥¥^ ¥^^¥rèLèðL!´f"èQL9LìL=LLkVLuV¥^ ¥^^¥r˜L„­L9­LèL­L¼fèL!LLpVL™´fOèLL)L­LŒLpVLèLL‹VLèL’­LìLr­)LL‹VLèL{­LìLr­èL-õR^ZèL|­LL‚­L‰­LèLšL-L%L!L…VèLi­L=LìL†VLLz­LèðLìôLìLLwVLì­LõRLèðLìôLèL|­LjæLx­L)Ls­LL)L›vLìLyVjLŒ­Lt­Lo­œLo­l^jLèÐL¸f èLŽ­aèLL~­LLìLnVL„­ìLèðL9eê*´fèQLèLo­¥^¥^^)L„­¥œL„­¥¥^ ¥èL/“°*ö­¥L)LžvLìLyþJRåL”­L9L)L)LŸvLf¥j L­l^˜LèÐL¸f èLŽ­aèðLèLø_²:´bèL (I/´b,èLïZg6´bE^bìQL)ULìLv­LìL=VR^P¥¥^BìQL)ULìLq­LìL=VR^0¥¥^"ìQL)ULìL­LìL=VR^¥¥^¥èL/“°*ö­¥_\ÿÿÿRå¡7Z7[Ü7\\7]S7^L/`ÐS­7_¨#èLèðâ^ ^^^&ßL)L«þ"^àL)L«þ"^áL)L«þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå®LìL«þå9L)L)L (I/zrrèLèðâ^ ^^$^7èQLìLìL¿­ˆ¥^%èQLíL숥^èQLîLìLÛ­ˆL¿ˆ¥^¥åìLìLêVLØærèLèLèL(´bèèL-´béèL.´bêèL0´bëèL/´bìèL1´bíèL2´bîèL3´bïèL4´bðèL5´bñèL6´bòèL7´bóèL+´bôèL,´bõèL)´böèL*´b÷èL"´bøèL#´bùèL$´búèL&´bûèL'´büèL%´býèL´bþèL´bÿèL´cèL|´cèL´cèL ´cèL!´cèL´cèL´cèL´cèL´c¥__ üÿÿÿ¥__üÿÿÿ¥_^úüÿÿÿ¥^ø^òüÿÿÿ¥^ð^êüÿÿÿ¥^è^âüÿÿÿ¥^à^Úüÿÿÿ¥^Ø^Òüÿÿÿ¥^Ð^Êüÿÿÿ¥^È^Âüÿÿÿ¥^À^ºüÿÿÿ¥^¸^²üÿÿÿ¥^°^ªýÿÿÿ¥^¨^¢ýÿÿÿ¥^ ^šþÿÿÿ¥^˜^’þÿÿÿ¥^^Šÿÿÿÿ¥^ˆ^‚ÿÿÿÿ¥^€^zÿÿÿÿ¥^x^rÿÿÿÿ¥^p^jÿÿÿÿ¥^h^bÿÿÿÿ¥^`^Z!¥^X^R!¥^P^J%¥^H^B%¥^@^:¥^8^2¥^0^*¥^(^"¥^ ^¥^^¥^^ ¥^^¥¥åèL)õrèLèðLìôLìLèðL ´fièQLìUL)*L)L9­LL9­Èf>LL-L=ðVL-LìL-LÄVLìLÇ­L-LÇ­L³VLV¥R^9^R^ ¥¥¥^^LLLÄVLLÇ­LLÇ­L³VLþJ¥RrèLèL¼­Lj L9ð­l^$LèL»´f ìL-L¼­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL»´f )LL¼­´fR^¸^èL/“°*ö­¥LÓL)L)L%zR^¥¥¥ìL!LÅVððL%´fSìL!LÅVôL)L%L¬Vj L=ð­l^%LèL»´f )LL¼­´fR^L^èL/“°*ö­¥LèR^E¥¥^^ìL!LÅVððL!´f!ìL!LÅVôL)L%L¬VÜR^¥^^»L/&]þ!¥¥å9LèL¼­LìL!LÅVððL ´f•ìL!LÅVðQðL´f~ìL!LÅVôL)L%L¬Vj 9L=ð­l^%LèL»´f )LL¼­´fR^¬^èL/“°*ö­¥LLìLÇ­L³VLLL-LÊ­LÌVõL9LðVR^z¥¥^^^^ìL!LÅVððL%´f&ìL!LÅVôL)L%L¬VLð­R^=¥^^LLÇ­L³VLLL®LÌVõL9LðV¥^ »L/&]þ!¥¥åèLèL¼­LìL!LÅVððL ´fãìL!LÅVðQðL´fÌìL!LÅVðQQL)L!LÅVôL-L!LÅVðQLL%L¬VLèL¼­LìL!LÅVððL ´fLìL!LÅVðQLî´f6ìL!LÅVôL)L%L¬VLÆ­LL)L³VL9VR^.¥^^^^-L-L´­õLL=ðV¥^ »L/&]­¥¥R_÷ ¥¥¥^^^^ìL!LÅVððL ´fCìL!LÅVðQL)L!LÅVôL-L%L¬VèL)L´­õLL=ðVR_ ¥¥^^ìL!LÅVððL´fíìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR_@ ^èL/“°*ö­¥LLèL¼­LìL!LÅVððL´f6ìL!LÅVôL)L%L¬VLìL³VLõLL=ðVR^P¥^^ìL!LÅVððL!´f.ìL!LÅVôL)L%L¬V$Lå­LLVR^¥^^»L/&]­¥¥R_Ÿ ¥¥^^ìL!LÅVððL´fòìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR_B ^èL/“°*ö­¥LLèL¼­LìL!LÅVððL´f;ìL!LÅVôL)L%L¬VLìL³VLLЭõLL=ðVR^P¥^^ìL!LÅVððL!´f.ìL!LÅVôL)L%L¬V¾Lå­LLVR^¥^^»L/&]­¥¥R_œ ¥¥^^ìL!LÅVððL ´f’ìL!LÅVðQðL!´f{ìL!LÅVôL)L%L¬VjLLðVl^%LèL»´f )LL¼­´fR_) ^èL/“°*ö­¥LèðLìôL-LìL³VL)LÀ­õLL=ðVR_ ¥¥¥¥^^^^ìL!LÅVððL ´fÃìL!LÅVðQðL%´f¬ìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR_‰ ^èL/“°*ö­¥Lj Lð­l^%LèL»´f -LL¼­´fR_X ^èL/“°*ö­¥L)LìLÇ­L³VL)L)L¸LËVõLL=ðVR_+ ¥¥¥^^^^ìL!LÅVððL ´g ìL!LÅVðQðL´fõìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR_µ^èL/“°*ö­¥L-L!LÅVððL ´f“-L!LÅVðQðL%´fy-L!LÅVôLL%L¬Vj  Lð­l^%LèL»´f LL¼­´fR_H^èL/“°*ö­¥L-LìLÇ­L³VLìLL¹LËVõLL=ðVR_¥¥^R^^R^¥¥^^^^ìL!LÅVððL ´g(ìL!LÅVðQðL ´gìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR_˜^èL/“°*ö­¥L-L!LÅVððL´f¯-L!LÅVôLL%L¬Vj  Lð­l^%LèL»´f LL¼­´fR_?^èL/“°*ö­¥LèðLìôLL!LÅVððL´fBL!LÅVôLL%L¬VLìL³VLLLL¶VõLL=ðVR_é¥^R^¥¥¥¥^R^¥¥^^^^ìL!LÅVððL ´fÈìL!LÅVðQðL´f±ìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR__^èL/“°*ö­¥Lj Lð­l^%LèL»´f -LL¼­´fR_.^èL/“°*ö­¥LñLèLLLLLL=LLõv‰èðaLì­¥R_ü¥¥¥^^^^ìL!LÅVððL ´gjìL!LÅVðQðL´gSìL!LÅVôL)L%LÅVððL´g.)L%LÅVôL-LL¬Vj Lð­l^%LèL»´f -LL¼­´fR_h^èL/“°*ö­¥LLèL¼­LìL!LÅVððL´fvìL!LÅVôL)L%L¬Vj  Lð­l^%LèL»´f )LL¼­´fR^|^èL/“°*ö­¥LLìLÇ­L³VLL)L·VõLL=ðVR^R¥¥^^ìL!LÅVððL!´f.ìL!LÅVôL)L%L¬V¾Lå­LLVR^¥^^»L/&]­¥¥R_‡¥¥^¥^ ¥^^^^ìL!LÅVððL ´fëìL!LÅVðQðL´fÔìL!LÅVôL)L%L¬V-LèL¼­Lj  Lð­l^$LèL»´f ìL-L¼­´f¥^8^èL/“°*ö­¥L-LìLÇ­L³VLìLÊ­LÁ­õLL=ðVR^R¥ìL!LÅVððL%´f4ìL!LÅVôL)L%L¬V-L®LÁ­õLL=ðVR^¥^^»L/&]­¥¥R_¥^^^^ìL!LÅVððL ´fëìL!LÅVðQðL´fÔìL!LÅVôL)L%L¬V-LèL¼­Lj  Lð­l^$LèL»´f ìL-L¼­´f¥^8^èL/“°*ö­¥L-LìLÇ­L³VLìLÊ­LÝ­õLL=ðVR^R¥ìL!LÅVððL%´f4ìL!LÅVôL)L%L¬V-L®LÝ­õLL=ðVR^¥^^»L/&]­¥¥R_…¥^^^^ìL!LÅVððL ´fEìL!LÅVðQðL´f.ìL!LÅVôL)L%L¬VèLÈõLL=ðVR_/¥^^^^ìL!LÅVððL ´g_ìL!LÅVðQðL ´gHìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR_½^èL/“°*ö­¥L-L!LÅVððL ´fæ-L!LÅVðQðL ´fÌ-L!LÅVôLL%LÅVððL ´f¦L%LÅVðQðL´fŒL%LÅVðQQLL%LÅVôLLL¬Vj  Lð­l^%LèL»´f LL¼­´fR_^èL/“°*ö­¥LLìLÇ­L³VLLL-L­VõLL=ðVR^ᥥ¥^R^"^R^¥^R^^R^¥¥^^^^ìL!LÅVððL ´f™ìL!LÅVðQL´fƒìL!LÅVôL)L%L¬Vj Lð­l^%LèL»´f )LL¼­´fR^N^èL/“°*ö­¥LìLìLÇ­L³VLL-L!LÏ­L´­õL-LVLЭõR^¥¥^^^^»L/&]þ!¥¥åèLèL¼­LìL!LÅVððL´f•ìL!LÅVôL)L%LÅVððL ´fp)L%LÅVðQðL´fV)L%LÅVðQQL-L%LÅVôLLL¬VLÇ­LìL³VLL-LÕVõLL9ðVR_»¥¥^¥^^¥^¥^^ìL!LÅVððL´fúìL!LÅVôL)L%L¬Vj L=ð­l^%LèL»´f )LL¼­´fR_P^èL/“°*ö­¥LLèL¼­LìL!LÅVððL´fCìL!LÅVôL)L%L¬VLÇ­LìL³VLLLÙVõLL9ðVR^P¥^^ìL!LÅVððL!´f.ìL!LÅVôL)L%L¬V¾Lå­LLVR^¥^^»L/&]­¥¥R_¢¥¥^^ìL!LÅVððL ´fùìL!LÅVôL)L%L¬Vj L­l^%LèL»´f )LL¼­´fR_F^èL/“°*ö­¥LLèL¼­LìL!LÅVððL ´fCìL!LÅVôL)L%L¬VLÇ­LìL³VLLLÍVõLL9ðVR^P¥^^ìL!LÅVððL!´f.ìL!LÅVôL)L%L¬VLå­LLVR^¥^^»L/&]­¥¥R^˜¥¥^^ìL!LÅVððL ´fnìL!LÅVðQL)L!LÅVôL-L%L¬Vj L­l^%LèL»´f -LL¼­´fR^.^èL/“°*ö­¥L)LL)LVR^¥¥¥^^-¥^ »L/&]þ)¥¥rèLèL¼­LìL!LÅVððL ´g2ìL!LÅVðQðL´gìL!LÅVðQQL)L!LÅVôL-L%L¬VLèL¼­LìL!LÅVððL´f›ìL!LÅVôL)L%L¬Vj  L9­l^%LèL»´f )LL¼­´fR_Œ^èL/“°*ö­¥Lj  L=ð­l^%LèL»´f -LL¼­´fR_[^èL/“°*ö­¥LÓL)LõL)L%zL½­R_>¥¥¥^^ìL!LÅVððL ´fŒìL!LÅVðQLî´fvìL!LÅVôL)L%L¬Vj  Lð­l^%LèL»´f )LL¼­´fR^Í^èL/“°*ö­¥LÓLL-L³VLLÆ­õL)L%zLº­R^£¥¥^^^^jLLÉ­L´­õL LVl^$LèL»´f ìL-L¼­´f¥^X^èL/“°*ö­¥Lj  Lð­l^%LèL»´f )LL¼­´fR^'^èL/“°*ö­¥LÓL)L)L%zLº­R^¥¥»L/&]­¥¥R^S¥¥^^^^j Lð­l^$LèL»´f ìL-L¼­´f¥^^èL/“°*ö­¥LèLº­R^ ¥»L/&]þ!¥¥åèLèL¼­Lj L9­l^$LèL»´f ìL-L¼­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL»´f )LL¼­´fR^Œ^èL/“°*ö­¥LÓL)L)L%zR^y¥¥ìL!LÅVððL%´fSìL!LÅVôL)L%L¬Vj L=ð­l^%LèL»´f )LL¼­´fR^ ^èL/“°*ö­¥LèR^¥¥^^Ü¥^ »L/&]þ!¥¥åèLèL¼­LìL!LÅVððL ´fåìL!LÅVðQðL´fÎìL!LÅVðQQL)L!LÅVôL-L%LÅVððL´f—-L%LÅVôLLL¬Vj  L9­l^%LèL»´f LL¼­´fR^Ö^èL/“°*ö­¥Lj  L=ð­l^%LèL»´f LL¼­´fR^¥^èL/“°*ö­¥LÓL)LõL)L%zR^¥¥¥^R^¥¥^^^^ìL!LÅVððL´fSìL!LÅVôL)L%L¬Vj L=ð­l^%LèL»´f )LL¼­´fR^ ^èL/“°*ö­¥LèR^¥¥^^Ü¥^ »L/&]þ!¥¥åèLèL¼­Lj L9­l^$LèL»´f ìL-L¼­´f¥^È^èL/“°*ö­¥L)L!LÅVððL´f¥)L!LÅVôL-L%L¬Vj L9­l^%LèL»´f -LL¼­´fR_•^èL/“°*ö­¥Lj  L=ð­l^%LèL»´f LL¼­´fR_d^èL/“°*ö­¥LèðLìôLèLÓLLõLL%zõR_B¥¥¥¥¥^¥^¥ìL!LÅVððL ´g ìL!LÅVðQðL ´fòìL!LÅVôL)L%LÅVððL´fÍ)L%LÅVôL-LL¬Vj L9­l^%LèL»´f -LL¼­´fR^«^èL/“°*ö­¥Lj  L=ð­l^%LèL»´f LL¼­´fR^z^èL/“°*ö­¥LèðLìôLèLèðLèL!´b èL%´b^&LÊ­Lõ^°L¯­Lã­LLV^¥¥R^0¥¥¥¥¥^¥^ ¥^^^^®LÜõ¥^ »L/&]þ!¥¥åèLèL¼­LìL!LÅVððL ´fˆìL!LÅVðQðL´fqìL!LÅVðQQL)L!LÅVôL-L%L¬Vj L9ð­l^%LèL»´f -LL¼­´fR^–^èL/“°*ö­¥LÓL-L)L%zR^ƒ¥¥¥^^^^ìL!LÅVððL´fSìL!LÅVôL)L%L¬Vj L9ð­l^%LèL»´f )LL¼­´fR^ ^èL/“°*ö­¥LèR^¥¥^^Ü¥^ »L/&]þ!¥¥åèLèL¼­Lj L9­l^$LèL»´f ìL-L¼­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL»´f )LL¼­´fR^(^èL/“°*ö­¥LÓL)L)L%zR^¥¥Ü¥^ »L/&]þ!¥¥åèLèL¼­LìL!LÅVððL´fRìL!LÅVôL)L%L¬Vj L9­l^%LèL»´f )LL¼­´fR^ ^èL/“°*ö­¥LèR^¥¥^^Ü¥^ »L/&]þ!¥¥åèLèL¼­LìL!LÅVððL ´gŽìL!LÅVðQðL´gwìL!LÅVðQQL)L!LÅVôL-L%L¬VLèL¼­LìL!LÅVððL ´fÇìL!LÅVðQL(´f±ìL!LÅVôL)L%L¬Vj  L9­l^%LèL»´f )LL¼­´fR^Ö^èL/“°*ö­¥LjLÇ­L L=ðVl^%LèL»´f -LL¼­´fR^^èL/“°*ö­¥LèðLìôLèLÓLLÊ­L õLL%zõR^v¥¥¥¥¥^^^^jL L=ðVl^$LèL»´f ìL-L¼­´f¥^3^èL/“°*ö­¥LèðLìôLèLÓL®LõLL%zõR^¥¥¥»L/&]­¥¥R^¥¥^^^^»L/&]þ)¥¥rèLèL¼­LìL!LÅVððL´fUìL!LÅVôL)L%L¬VjLL9Vl^%LèL»´f )LL¼­´fR^%^èL/“°*ö­¥LèR^¥¥^^-LÜõ¥^ »L/&]þ)¥¥r9LÚðLÞVLèLµ­LèðLèL´bèL´b¥^,^(ìQLL=ð­R^#¥^ìQLL=ð­R^¥^¥L)‰ì¥¥åÑLÔõñLñLèL-L)LLv‰èðajL±­L9­LÑLìLº­õ¥l^CLèÐL¸f èLÖ­aèðL65´f!)ðLµ­Lã­L-ðL×­L=V^ ^èL/“°*öþ)¥RåìL¾­LL­LέLèL-ðL-LôLQLÃVèL9þ)Rr7¢7£C7¤S7¥7¦7§L/`ÐS­7¸_KèLèðâ^^^#^-^7^A^JQL)L3þ"^>RL)L3þ"^2SL)L3þ"^&TL)L3þ"^UL)L3þ"^VL)L3þ"^¥å9LìL!zåå9LìLzåå®LìL3þå9L)L)Lø_²:zrrèLèðâ^^T^V^X^Z^i^jèQLèLF­L ¼f èLF­L€ÄfcLìL*V¥^A^¥^¥èQLdLìLF­L*þ*¥^#e^f^g^èQLhLìL*þ*¥^i^¥åèL)LO­LaVL.ær9LìL2­L)LCþ#åìLO­LìõrèLìL­L)­L"­L@­L9þåèLìL­L#­L@­L9þåèL­LìLj9LL4VL­l^4LèÐL¸f èL+­aèðLw ù´f)L=­L@­^ ^èL/“°*ö­¥L=þ"¥åèL9ðLNþåèL9ðLNþåèL9ðLNæåxLìL3þå9LìLI"W3zååèLL9þåèL5L9þåèLEL9þåèLL9þåèL$L9þåèLL9þåèL%L9þåèLL9þåèLL9þåèL6L9þåèL9ðLNþåèL­LèL%L)L­L%ŒL7VL)LìL­L@­L9þ*RåèLL@­L9þåèLAL@­L9þåèL&L@­L9þåèLBL@­L9þåèL9þåèLO­LìLI­LèL'­j L9­l^7LèÐL¸f èL+­aèðLßUD´fZL-LaVL.­^ ^èL/“°*ö­¥)LO­L)LìLVL)LK­L­L@­õRåèLO­LìLI­LèL'­j L9­l^7LèÐL¸f èL+­aèðLßUD´f[L-LaVL.­^ ^èL/“°*ö­¥)LO­L)LìLVL)LK­LG­õRåèL­LèL­LìLìL%ŒL;VL ´f^L-L-L!LLŒL7VLM­L9þ2RåèLìL­L1­L9þåèLìL­L1­L9þåèLL1­L9þåèL4L1­L9þåèL­LèðLèL!´b èL%´b^$)LJL9þ*^ìQL-LìLX­L=þ2¥^¥¥ååèLI­LìL­L<VèL9þåèLI­LìL­L<VèL9þåHL.þåèLI­L"L>VèL9þåèLI­L\L>VèL9þåèLI­L L>VèL9þåèLI­L L>VèL9þåèLI­L L>VèL9þåèL­L%LL7VL)­LèLÿ¼fìLìL]­L9VìLI­LìL ­L>VìL=þ¥åèL_L9þååèLI­LìL­L<VèL9þåHL.þåLw­L.æåèLI­LVLw­L.æåèLI­LìL­L<VèL9æåHL.æå¸7Ü7z7S7E7 7  7 ÷7 #Å¿Å7  #¡é7 #ÉnN 7 #ö¤ï7 #½b° 7 #8gî7 #4wß7 #üüÒ7 #ƒ*=7#ŸÎßî7 #nÓÜ77#Ö^¿Á7 #ñœÄÅ7 #ÐÂ=7 #‡œz 7 #‘³êÜ7#9œãË7 #æ”7 #ò)7 #-zK7  #!@7! #ÏÄ77" #|5Ä7# #eÍ97$ #"P=7% #§Êç37& #ÏIÈæ7' #!Ê|Õ7( #ï P7) #L(†ß7* #7ä.7+ #¾ ú7,#.Ûê:7- #&]7. #«;7/ #MR±70 #ˆ‰-Æ71 #ÝË':72 #ýK73#9лÃ74 #iú375 #©é¼876 #€©W77 #ý?78 #Ùî-79 #ìNÔ7: #–€N7; #!òI7< #в¦Ê7= #ô0Û7> #Ÿ”Ì7? #Ci‹Ý7@ #ƒ¥|7A #~2Õ77B#!òI7C#:Úï7D #µ¡ŠÝ7E #áT7F #?¢ÁÎ7G #>#÷-7H#*VcÂ7I #œ¼47J #Ñ(07K #Ç–A7L #Óq&7M#ù‚+7N#Hæ>7O#üfü7PWLèLYí7XLX?íï6èL%õ7ZLZ?T'qèLõ7[L[?ÅUÂèLõ7\L\?¸æèL^í7]L]?E@ö<èLõ7_L_?)kä¥`LèLbí7aLa?¨;WjLkLLP­LèLlíL(LLL(LL(L/L(L8L(L9L(LL(LL(L?L(LL(L!L(L:L(L,L(LL0L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL Vè¥LmLèLníLìLoíL-L-LpvLqLrLLD­ñLLD­ñLLD­ñLLD­ñLìLsíL-LtíL)LuíLvLèLxí7wLw?‡œz L(L LyíL%õL(LLzíLõL(LL{íL+õL(LL|íL$õL(LL}íLÅõL(LL~íL¾õL(LLíL¿õL(LL€íLõL(LL‚íLƒõL(LLƒíLõL(LL„íL…õL(L"L†õL(L$L‡õL(L%LˆõL(L'L‰õL(L+LŠíLL)ˆõL(L-L‹íLÿõL(L/LŒíLõL(L1LíLõL(L3LŽíLõL(L2LíL2õL(L,LíLõL(L/L‘íL’õL(L;L“íL”õL(L=L•íL9L:ˆL–ˆõL(L?L—íL;L<ˆL(ˆõL(LAL˜íLõL(LCL™íL4õL0L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL LLšvL-V‰L(L›LœõL(LLíLžõL(LLŸíL õL0L%zL%zL%zL¡L-V‰L(LL¢íL£õL(LL¤íL¥õL(LL¦íL§õL(LL¨íL©õL(L LªíL«õL(LL L¬vL­õL(LL®íL5õL(L¯LõL(LL°íL±õL0L%zL%zL%zL%zL%zL%zL%zL%zL%zL²L-V‰L(L³LdõL(L´L&õL(LLµíL¶õL0L%zL%zL%zL·L-V‰¸L-?±¨W¸L)?)æÉ¸L ?N¸áï¸L ?ÄSï¸L ?»Fq:¸L ?^_¸L ?jÅ ÿ¸L?ðBy7¸L?5ýøL?ö(ù¸L? ¯­ú¸L?ÈË)ó¸L?}‰ð¸L?š€W¸L?_zp¸L?¨3R¸¸7¨ 7©÷7ªª#ýK7«ª#'}Ö7¬§#öÙÛ-7­ª#Ø>ã37®§#ÉnN 7¯§#¡é7°ª#€-7±¦#f0 7²¥#ŸÎßî7³§#ÞN+ô7´ª#‡ÊM7µ§#ÀV/7¶§#}´É7·§#ê«!;7¸§#L;Ê7¹§#ÈÊÉÞ7ºª#©Óà7»ª#÷±!7¼§#äôÿ7½£#Ú¥A7¾§#í"7>7¿§#‘^Èó7À§#Õ ó7Á©#üfü7Â¥# Ä>7ç##oÍÜ7Ī#º>97ŧ#oc|7Ƨ#”]U7ǧ#Ì鋿7ȧ#в¦Ê7ɪ#O177ʧ#,™Šó7˧#‚›47̧#Ã\Ï7Í¥#üfü7Χ#ÏÄ77ϧ#‘¦?7Ð¥#œî17Ѥ#ú´fÅ7Òª#!Ê|Õ7Ó§#œ¼47Ô§#5ê`*7Õª#7ä.7Öª#i£W7ת#&]7ا#ƒK9ç7Ù¨#5ýÃ7Úª#Ñ(07Ûª#MR±7ܧ#:z¹â7Ý¥#ù‚+7ÞâLèLäí7ã¢Lã?ñ¥<èLæí7å¢Lå?å”JêèLèí7ç¢Lç?ÑS\Ö¥éLèLëí7ê¢Lê?¨;WïLðLñLòLñLñLñLñLñLñLñLñLñLñLñLñLñL L L LLóv‰ ð2  L L Lôv‰ ð2 L L L LL LL L LLöv ‰ð2 LLLL LL÷v‰ð2 L LLL Løv‰ð2L LLùv‰ð2L LLúv‰ð2L LLLûv‰ð2LLüí‰ð2-L LLýv‰-ð2)LLþí‰)ð2ìL L)Lÿv‰ìðeèL)Lí‰èða LLvLèLíL²Lì‰ÒLì‰L-?»†LéL?·âbL?ø;“$L ?„JùóL?d{>;Lì?f0 L)?3U=L?èyÉL?ª¾~ÑL?r1]äL?9uL?^_L ?WÁ"ÌL ?}£ ËL ?5ýÃL? ¯­úL?ÈË)óL ?D.ê'L?Muü4R7_š7`E7aL/`ÐS­7 _ èLèðâ ^^^)^3^=^G^Q^[^e^nÀL)L¼þ"^bÁL)L¼þ"^VÂL)L¼þ"^JÃL)L¼þ"^>ÄL)L¼þ"^2ÅL)L¼þ"^&ÆL)L¼þ"^ÇL)L¼þ"^ÈL)L¼þ"^¥å9LìL%zåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzååïL¾æåðLìÐLèL!´b?èL%´b<èL´b>èL´b@èL´bBèL´bDèL´bFèL´bHèL´bJìþ^NÊ^J)LËþ!^A)LÍþ!^8)LÏþ!^/)LÑþ!^&)LÓþ!^)LÕþ!^)L×þ!^ )LÙþ!^¥¥åèLèðâ ^^^"^.^:^F^R^^^j^u^rèQLèL½þ!¥^dèQLèL½þ!¥^VèQLèL½þ!¥^HèQLèL½þ!¥^:èQLèL½þ!¥^,èQLèL½þ!¥^èQLèL½þ!¥^èQLèL½þ!¥^¥åèL/¢å1&þåìLì$L9þrèL9­L)LL)@¥rèL/HoØLÛþå/HoØ#¥åQÊLºL#.Zû!µåL-QLð2èL!¼fþÿÿÿL%ŒaìLL)$õe_åÿÿÿìLLLíþCRrèLÝþåèLã­L9þåèLß­L9þåèLá­L9þåèLåþåìLìLçVL9þrèL9­L-L-L)Léþ;¥rèLëþå 7¹z7º÷7»»#ýK7¼»#-q7½»#ÎeK<7¾º#œ S7¿ÉLèL!õ7ʹLÊ?ý­]8èLÌí7˹LË?99èLÎí7͹LÍ?f=uøèLÐí7ϹLÏ? “j0èLÒí7ѹLÑ?Çú=èLÔí7Ó¹LÓ?µ× ÂèLÖí7Õ¹LÕ?XÃIßèLØí7×¹L×?Ž­ËèLÚí7Ù¹LÙ?cåm¥ÜLL/HoØL#Œg%ÐZ7ÛÞL%L/HoØL#Œg%ÐZ7ÝàL%L/HoØL#Œg%ÐZ7ßâL%L/HoØL#Œg%ÐZ7áäL%L/HoØL#Œg%ÐZ7ãæL%L/HoØL#Œg%ÐZ7åèLL/HoØL#Œg%ÐZ7çêLL/HoØL#Œg%ÐZ7éìL%L/HoØL#Œg%ÐZ7ëîLL/HoØL#Œg%ÐZ7íñLòLóL)LôíL)LõíLöL¿L÷LøLùLLúíLLûíL LüíLýL LþíL LÿíL L L?q¸1 L?æÁö L)?“ÿ/ L?Û‹ L ? Ã*5 L?þé‚2 L?†R†Ã L?­o>- L-?a² L?¬Îsò L?b$ Lì?Àg|Å L?‘”Vý L ?¢å1& L ?áMuÀ L ?Õ2lÀ L ?N•k×R  7bL/`ÐS­7 _HèLèðâ^ ^^^& L)L þ"^ L)L þ"^ L)L þ"^¥å9LìL%zåå9L)L)LzrrèL/–£­L!LìL/¢å1&­LìLìÄfC)L)$L)LL)€f ^ )ÐL´f )L ­^)ðL-ôL V@)L%ˆ2¥_»ÿÿÿ)L L#.Zû!µrRå/êQý©L þå/¸ÐV(©L þåèLèðâ^ ^^&^C9L L þ"^7èQL9L L)L þ3¥^"èQLìUL9L L)LõL þ;¥¥^¥åìL íLìL þ"r LL9­L=þå 7 7 š7 ÷7  #ýK7  #Ë¿ó7  #Å¿Å7  #ßlYÐ7  #™Ïa17  LèL!õ7  L ?{â2#èL í7  L ?̨gõèL í7  L ?t=¥ 7  L L L)LìL vL Lì?-X‹È L-? M L)?4}r L?žºÁR  7d¸7e 7f¢7g÷7h_#3U=7i[# Ä>7jb#a²7k\#9лÃ7l^#ô³Ç7md#4}rÂ7nh#ÿÍÃ7oa#€©W7p_# ¯­ú7q[#LýL7rh#‡ÊM7sb#æÁö7t\#4H(+7ue# ¯­ú7vg#ßlYÐ7wb# Ã*57x`#Q° Â7y[#q·„÷7z[#xì3ü7{[#Ú¥A7|b#“ÿ/7}d# M7~a#æ”7a#–€N7€f#!òI7f#üfü7‚[#¢&ì7ƒh#-X‹È7„^# Ä>7…]#s%o7†[#™Ïa17‡f#ô0Û7ˆ^#üfü7‰^#Û°127Š[#Edž47‹b#b$7Œf#Ñ(07h#7ä.7Ž[#Ë¿ó7]# ¯­ú7[#½~87‘g#VK§Ë7’[#H³ 7“\#üfü7”–L—LìLìL vL¡Lì?KçV¡L)?´<„¡L-?VK§ËR¡¡6¸6L/`ÐS­7l _m èLèðLèL!´b èL%´b^WW L9ˆL2 ­LL þ!^EìQL)ULjL9ˆLLF Vl^$LèÐL¸f èLJ ­aìL=ð­^èL/“°*öþ9¥¥¥^¥¥åñLèL)L)LX v‰èðaH LsL9L%zLìþ¥åèLèðâ^^&^d^±^þ_"_[9ðLM ­L9ðL-L@ Vè¥_BèQLìUL9ðLM ­L9ðLL@ V=LH L-L-LzL=ðL%z‰è¥¥¥_j9ðLL: Vl^?LèÐL¸f èLJ ­aèðLw ù´f9ðLM ­L9ðLL@ Vè¥^ ^èL/“°*öþ!¥^³j9ðLL: Vl^?LèÐL¸f èLJ ­aèðLw ù´f9ðLM ­L9ðLL@ Vè¥^ ^èL/“°*öþ!¥^dèQLìUL9LFLìL-õL= ­‰ÿÿÿÿ¥¥^>èQL9*L+ L6 VL!´f9LìL= ­F9ðLìLI ­L@ VLì‰ÿÿÿÿ¥^¥å9ULM ­L9UL)L@ Vè¥åèôLìðLìL9L)LE VõRå9ôLìL@ V9QL=LðL; VL@ VLðL%ˆ‰èL* ­f#9QL=LðL; VL@ VLðL%ˆ‰å9ôLM ­L!LT ­L=­LH L)LLLzLðL%z‰¥rèôLìðLìLèðLèL!´b èL%´b_Ð` L‡L/ þ:_ÄìQðL´g„ìUðL%´gvìUQðL´gfìUUðL%´gVìUUQðL ´gDìUUQQLa ´g1ìUUUðL%´gìUUUQðL´g ìUUUUðL%´g÷ìUUUUQðL ´gáìUUUUQQLa ´gÊìUUUUUðL%´g´ìUUUUUQðL´gœìUUUUUUðL%´g„ìUUUUUUQðL´gjìUUUUUUQQLb ´gOìUUUUUUUðL%´g5ìUUUUUUUQðL´gìUUUUUUUQQL´füìQQL)UUUUUUUUL9L)L; VLèðL´f¶èQLj=*LL- Vl^8LèÐL¸f èLJ ­aèðLw ù´f=L)LðVL= ­^ ^èL/“°*ö­¥LèLèðLèL!´b èL%´b^Fc LˆLAˆLˆL2 ­LL ­^,ìQLèLA ­L­LðL ˆ‰L Lˆõ¥^¥¥¥¥^¥^^d L2 ­LL ­¥R_ˆ¥¥^^J^^F^^B^^>^^:^^6^^2^^.^^*^^&^^"^^^^^^^^^^^^ ^^^^ìQL)ULLL=ôLM ­LB VìLèðâ^6^4^2^0^.^,^.^(^&^$^"^C^^\^^^^^^^^ ^ ^g^~^•^¬^Ã^ÁèQLLìL; VLA ­L­¥^­¥^¢èQLe ´fLA ­L­^’^^‡^…èQLLìL; VL< ­L­¥^q¥^fèQLT LL)L V¥^X¥^MèQLP LL)L V¥^?¥^4èQL' LL)L V¥^&¥^èQLU LL)L V¥^ ¥^)L­¥èLL%ˆõ¥¥^¥¥RåèULìQL)ôL-ðL9L-LˆL; VL9LL; VŒL=ôL-L)L­LB þK¥RåèQLìôL)ðL9ðL-L=L-L; VLLQ VLB þ;RåèLœˆL9 ­èLjˆL9­LèLS ­LèðLìôL-L0 ­+ ñLO ñL!ñLL)LL-LZ vLL, VL*LèðLèL!´b èL%´b^- LðL= ­F^ìQLèLð¸f[ L2 ­LL ­¥^¥¥ðLM ­LULM ­L UL L@ V ðL LG ­L@ V ôL@ æLH L4 LH L7 LH L,L> ­LH L%L? ­LH L L< ­LO L%zL%zL%zL%zL%zL) VL!L)õL& VL QLN V *L L+ LD VLM ­LèLÿÿÿÿL& VLðLèðLèL!´b èL%´b^H-LL!LõL& V^3ìQðL)QôLL\ íL)L, VLèL] íL)L, V¥¥¥^¥¥L!ñLO ñLL-L-L^ vLLìL-L_ vLñLèLLL=LLLL LLL Lf v ‰èða L( ­L!õñLèðLK ­LO L6 VL!¸fèLìðL-­‰_àÿÿÿLLg vLðL) VLLh vL ðL) V*LL L= ­L1 VôL LA ­L@ VQL!L õL@ VQL!L õL@ VRr9LìL=VLC þåL. ­LL. ­LL. ­LLV ­L+ LLL. ­zLèL9Lj vL)L) Vè*fèðLìUL)QL5 VL@ V)LLR VLèL)ôL-ðõL3 VèL8 þ)Rrl 7 Ü7 7! z7" š7# ¢7$ ÷7% # #î9VÈ7& $ #H)Zæ7' # #^³Ç7( " #Å¿Å7) $ #¯7€77* % #Ø>ã37+ # #œ S7,  #9лÃ7- # #üfü7. % #ÆFÌ7/ ! #LýL70  #4H(+71 % #¨;W72 $ #ßlYÐ73 $ #HÛØ74 $ #ÐA75 % #e Ð76 $ #ú=:577 ! #G978 % #-X‹È79 # #›>7: # #–€N7; $ #…†,)7< % #O177= $ #‚WÞÁ7> $ #¾D“,7? # #!òI7@ $ #d]á7A # #¢›W7B % #¹È7C  #!òI7D % #S7E ! #Edž47F $ #$‡ú7G % #!Ê|Õ7H $ #Õoë7I % #7ä.7J % #i£W7K % #&]7L # #æ”7M # #ÚáÓ7N % #MR±7O $ #‹¬<7P $ #»Ç€ 7Q ! #uaø7R $ #VK§Ë7S $ #ñB17T $ # ÂÜ77U  #üfü7V /HoØ#¥åQÊL" L#.Zû!µLèLY íLñLèL)L)Li v‰èðaèLk íLl L? Öõl Lì?ú³Çl L-?­O¿ël L)?n¤ÃRl l 6L/`ÐS­7Q _èLèðâ ^^#^-^7^A^K^U^_^i^s^}^†œ L)Lu þ"^z L)Lu þ"^nž L)Lu þ"^bŸ L)Lu þ"^V  L)Lu þ"^J¡ L)Lu þ"^>¢ L)Lu þ"^2£ L)Lu þ"^&¤ L)Lu þ"^¥ L)Lu þ"^¦ L)Lu þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9L)L)Lzrr9LìLzåå9LìLzåå9LìLzåå9LìLzåå9L)L)Lzrr9L)L)L zrr9LìL zååèLèðLèL!´b èL%´b^uL-Lu þ*^*L-Lu þ*^¥¥å9L-L-L-L!zrr9LìL%zååèLèðâ^)^3^=^G^Q^[^e^o^y^ƒ^^—^¡^«^µ^¿^É^Ó^Ý^æ»L)Lu þ"^Úà L)Lu þ"^ÎÄ L)Lu þ"^Â…L)Lu þ"^¶Å L)Lu þ"^ªŽL)Lu þ"^žÆ L)Lu þ"^’Ç L)Lu þ"^†È L)Lu þ"^zÉ L)Lu þ"^nÊ L)Lu þ"^bL)Lu þ"^VË L)Lu þ"^JãL)Lu þ"^>Ì L)Lu þ"^2Í L)Lu þ"^&]L)Lu þ"^Î L)Lu þ"^`L)Lu þ"^¥å9LìLzåå9LìLzåå9LìLzååèLèðâ^ ^^!^+^5^>ßL)Lu þ"^2æ L)Lu þ"^&ç L)Lu þ"^è L)Lu þ"^é L)Lu þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå®LìLu þå9L)L)L¨ìr)zrrìLìLô VL— ærèLèðâ^)^+^-^/^1^3^5^7^9^;^=^?^A^C^E^G^I^U^i^o^k÷ ^gø ^c^_–^[ù ^Wî^S¾^O¿^K$^GÅ^C+^?^;^7ú ^3û ^/èQLèL˜ þ!¥^!èQLü LìL‰ ­ˆLý ˆ¥^ èQLè¥^¥åèLèðâ^ ^^-^8^:^;èQLìLìL9­ˆ¥^)èQLÿ LìL ­ˆ¥^èQL L숥^  ^ ^¥åìL› ­LìõrLƒ ­LõåèL‘ ­L‰èLÑ L9þåèL9ðLš þåèL9ðLš þåèLÐ L9þåèL‘ ­L‰èLÒ L9þåèLÖ L9þåèL× L9þåèLØ L9þåèLÙ L9þåèLÚ L9þåèLÛ L9þåèLÜ L9þåèLÝ L9þåèLÕ L9þåèLÓ L9þåèLÔ L9þåèLÞ L9þåèLß L9þåèL› ­LìL‘ ­ôLèLŽ ­jL9ðLš Vl^2LèÐL¸f èL“ ­aèðLßUD´fñ L-L=V^ ^èL/“°*ö­¥)L› ­LjL” ­L‡ ­l^'LèÐL¸f èL“ ­aò LL=V^èL/“°*ö­¥L-L)L{ VLìLâ ­õRåèL9ðLš þåèLìL ­L’ ­Là ­L9þåèLìL ­Lä ­L9þåèL} ­LèðLèL!´b èL%´b^))LÐ L9þ*^ìQLèLí ­LL› ­L=þ2¥^¥¥ååèL‘ ­ôLèQLìULL)L9ðVL; L‹ VLìL=ðþ:¥¥_èQL-LìL9ðV-L–L‹ þ2¥^õèQL-LìL9ðV-LL‹ þ2¥^ÙèQL-L¾L‹ VñLèLL9L-L= v‰èðaìLì­L¿L‹ þ:¥¥^èQL-LÁL‹ VñLèLL=L-L> v‰èðaìLì­LÅL‹ þ:¥¥^aèQLìULL? L-L… VLìL9ðþ:¥¥^<èQLìULLìL9ðVL@ L-L… þC¥¥^èQL-LA L)L… þ;¥^¥rèLèðL´f$)L¾L‹ V)L)L9V)L¿L‹ V^^^)L)L9þ*¥rD LìLLz VL| VLE LìLƒLz VL| VLèRåèLèðL´f5èQLìULèL9ð­LèðLìôLèL LLL%zõRR^¥¥^^ìL™ õ¥åèLèðLèL!´b èL%´b^P^MìUðL!´fìQL9LìL=VR^4¥^^ìQL)UL9L)L=V9L‚L‹ VèLðþ1¥¥^¥¥åèLèðLèL%´b èL!´b*_jìQL9LìL‰ ­L=­L‹ V9LœL‹ þ2¥_EìQL)UL-*L9LG L‹ VñLèLìLH í‰èða)Lì­LèðLìôLìLèðL!´f9LI LL… V9L)LV^’^^9LJ L‹ V9L)LV9LK LL… VñLèL9LL-LL v‰èða-LèðL%´f2èQðL!´f$èQQL0 ´fèUðL!´f^^^^^ ^^^^L)­¥9L¿L‹ V¥¥9LM L‹ VLèðLèL!´b èL%´b^ ^ìQL9LìL‰ ­L=­L‹ V¥^¥¥9LN L‹ þbR¥¥¥^¥¥åìL9L=LLO vLìLw þ"rQ 7m 7n z7o S7p E7q Y7r  7s ÷7t t #ýK7u t #'}Ö7v o #Å¿Å7w t #Ø>ã37x t #€-7y q #Úên7z p #ŸÎßî7{ q # ÐÇ7| p #Ö^¿Á7} t #‡ÊM7~ t #©Óà7 t #÷±!7€ p #9œãË7 s #!òI7‚ s #üfü7ƒ t #º>97„ n #™Ïa17… t #O177† r #3U=7‡ s #ô0Û7ˆ r #UJêá7‰ p #:Úï7Š n #ßlYÐ7‹ p #œî17Œ q #”ãì7 s #ÏIÈæ7Ž t #>#÷-7 t #!Ê|Õ7 p #*VcÂ7‘ t #ï P7’ t #7ä.7“ s #Ñ(07” p #.Ûê:7• t #i£W7– t #&]7— t #Ñ(07˜ t #MR±7™ p #ù‚+7š p #Hæ>7› § LèL© í7¨ m L¨ ?…Î’ èL« í7ª m Lª ?Vñf9èL­ í7¬ m L¬ ?%ó1èL¯ í7® m L® ?Kp»7èL± í7° m L° ??@Â7èL³ í7² m L² ?FÊÝèLµ í7´ m L´ ?dNçèL· í7¶ m L¶ ?4Â7èL¹ í7¸ m L¸ ?ÅN¬?èL» í7º m Lº ?ÀdÞèL½ í7¼ m L¼ ?ŒÛ:%¥¾ LèLÀ í7¿ m L¿ ?8gîèL í7Á m LÁ ?;«Äô¥Ï LèL!õ7Ð m LÐ ?œ¼4èL%õ7Ñ m LÑ ? ZƒÃèLõ7Ò m LÒ ?»»4èLõ7Ó m LÓ ?ò57èLõ7Ô m LÔ ?FWbèLõ7Õ m LÕ ?©é¼8èLõ7Ö m LÖ ?Ø/…÷èLõ7× m L× ?:˜›ÄèLõ7Ø m LØ ?HeØèL õ7Ù m LÙ ?Ú!É;èL õ7Ú m LÚ ?¨GÈ(èL õ7Û m LÛ ?µ¡ŠÝèL õ7Ü m LÜ ?šÁèL õ7Ý m LÝ ?CEèLõ7Þ m LÞ ?“ñèLõ7ß m Lß ?ÊTJèLá í7à m Là ?ÏÄ7èLã í7â m Lâ ?Xú3èLå í7ä m Lä ?в¦Ê¥ê LèLì í7ë m Lë ?ñ¥<èLî í7í m Lí ?~Ì ÏèLð í7ï m Lï ?ï"²ÓèLõ7ñ m Lñ ?Þòþ>èLõ7ò m Lò ?ÐA€ ¥ó LèLõ í7ô m Lô ?¨;Wö Lþ LèL íL L LLŠ ­ñLLŠ ­ñLLŠ ­ñL)L LL íL õL LL íL|õL LL íL õL™ L%zL%zL%zLL íL• V‰ìL LL íL õL LL íLîõL LL íL¾õL L L íL¿õL L L íL$õL LL íLÅõL LL íL+õL LL íLõL LL íLõL LL íLù õL LL íLžõL LL íL õL LL íLú õL LL íLû õL LL$L vLü õL LL íL õL L$L íL‡õL L&L íL! õL™ L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zLLL" vL• V‰èL L# Lý õL LL$ íL&õL LL% íL¶õL™ L%zL%zL%zL& L• V‰ñLñLñLñLñLñLñLñLLLL' v‰ð2LLL( v‰ð2L) ‰ð2LLL* v‰ð2-LLLLLL2 v‰-ð2)LLL4 v‰)ð2ìLL-L5 v‰ìðeèLL)L6 v‰èðaL LLL8 vLñLñLìLìL-LB v‰ìðeèL)LC í‰èðaF LèL-L-LP vLQ L-?¼9£Q L?Zn#Q Lì?ï~1Q L?2çûQ L?í"7>Q L?3U=Q L?ïêïQ L)?©²Q L? ¯­úQ L?ÈË)óQ L ?ºhÁQ L ?ïQ L?– Q L?|§FQ L?q Q L?/s¤Q L?!ÙñôQ L?²6 ØQ L ?œa7ÌQ L ?ñeÂßQ L ?2a·RQ Q 6L/`ÐS­7z _ZèLLY VL] ­LèðLèL!´b èL%´b ^<s^8ìUðL!´fìQLèR^'¥^^ìQL)ULLìL] ­L[ þ:¥¥^¥¥åèLLY VL] ­LèðLèL!´b èL%´b ^#s^ìUðL!´f s¥^^^ìQLè¥^¥¥å|LìLl LY VL[ VLèL|LY VL] ­LèðLèL!´b èL%´b^m L8L\ þ2^ ìQLè¥^¥¥¥å/HoØ#]tÀLT L#.Zû!µåèL^ þåèL` ­LèL´fZ ^èLX þ¥åb þåd þåèLf ­Lw ´åèLh ­LS L#.Zû!µåz 7R z7S š7T E7U ÷7V T #î9VÈ7W V #O177X U #Úên7Y V #Ø>ã37Z U # ÐÇ7[ V #ÆFÌ7\ S #cÙV7] _ L%L/HoØL#Œg%ÐZ7^ a L%L/HoØL#Œg%ÐZ7` c L!L/HoØL#Œg%ÐZ7b e L!L/HoØL#Œg%ÐZ7d g L%L/HoØL#Œg%ÐZ7f i L%L/HoØL#Œg%ÐZ7h j Lk Ln LW Lo Lp Lq L%L/HoØL#Œg%ÐZL/çñü©LèL L/ˆ¤³ÅVL ˜LìL ˜L)LdL/ˆ¤³ÅVz¥Lr Ls LL/HoØL#Œg%ÐZLt Lu L%L/HoØL#Œg%ÐZLv Lx Ly Lz L ?ˆëôz L ?–xóðz L?çñüz L?ÓàÁz Lì?râz L?=¿¸z L)?˜’UÇz L?„ÌÁ&z L?ÇOÀ&z L ?“åz L?÷Ãz L?Üà?z L-?z_(?z L ?ñ9íz L ?]tÀRz z 66š6 6L/`ÐS­7¦ _·èLèðâ^ ^^^& L)Lƒ þ"^L)Lƒ þ"^]L)Lƒ þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå— LìLƒ þåèQLìðL› L)L)õL þ*RåìL‰ ­š L‰ ­œ LìL„ V%L ær9L=LþåèôLìðL9LìL-LŠ þ3Rå9L=þå!ñLL‡ ­LLŽ ­LLL9Lž vL‘ ­LìLŸ L)LŠ VìL  L)LŠ VìL¡ íLL„ Vk+ðLÄg LðLŒ VLL ðL%ˆ‰j LL† Vl^6LèÐL¸f èL… ­aèðLw ù´fìL L¢ vL‘ ­^ ^èL/“°*ö­¥LèLèðâ^ ^^J^®èQLLì­¥^¡èQL ðL ´f ™ Lˆ ­L ðLŒ VL L ðL%ˆ‰èL)­¥¥^ièQL ðL ´f ™ Lˆ ­L ðLŒ VL L ðL%ˆ‰j L‚ ­l^$LèÐL¸f èL… ­a™ Lˆ ­^èL/“°*ö­¥LèL-­R¥^¥R_Üþÿÿl^XLèÐL¸f èL… ­aèðL”u´f6LðL%ŒLŒ VL£ L‰ ­èL‰ ­œL‰ ­LL9V¥^ ^èL/“°*öþQ¥RrL‹ ­L-L-L-L9þ66 #s%o675#¢&ì68# ý69%#™Ïa16: #üfü6;!#ñœÄÅ6<!#ÏÄ76=%#!Ê|Õ6>#-X‹È6?%#7ä.6@5#uaø6A# ¯­ú6B%#MR±6C'#VK§Ë6D#çñü6E#3U=6F5#}~&ô6G#3U=6H%#Ø>ã36I #ô³Ç6J #€©W6K# ¯­ú6L!#tï,96M# ¯­ú6N#KçV6O# M6P #–€N6Q##üfü6R5#™Ïa16S%#O176T#–xóð6U'#4}rÂ6V#3U=6W #œî16X5#Edž46Y'#$‡ú6Z #Û°126[#ú³Ç6\ # ¯­ú6]%#Ñ(06^#ˆëô6_#2çû6`!#3U=6aIñLñLìLbíLgLèLhíL-LìLLkvLLLnvLL-LLqvLLLuvLLLxvL{L}LkEL~LìðˆLˆLìôˆLˆLìQˆL€ˆLIñLCñL!ñL>LLíL<­L‚LƒzL>LL„íL<­L…L†zL>LL‡íL<­LˆL‰zL>LLŠíL<­L‹LŒzL>LLLvL<­LŽLzL>L LíLM­L‘L’zL>L L“íL<­L”L•zL>L"L–íLM­L—L˜zL>LL™íL=­LšL›zLCL%zL%zL%zL%zL%zL%zL%zL%zL%zLLìLLLLLœvLaV-ðLèðLèL!´b èL%´b^^ìQLèLðL.­L\V¥^¥¥Rl^ØLèÐL¸f èL@­aèðLèLø_²:´bèL (I/´b6èLïZg6´bOèL¨ìr)´bh¥^†^‚ìQL)ULìLN­LìLVR^†¥¥^bìQL)ULìLL­LìLVR^f¥¥^BìQL)ULìL]­LìLVR^F¥¥^"ìQL)ULìLB­LìLVR^&¥¥^¥èLèL^­LXLV¥^ ¥èL/“°*ö­¥L ?‚×¹ñL)?´<„L?Ç…íØL?ð¶4ÕL?$ù0L?Ž TL?Þ5zL?4}rÂL-?ºhÁL ?M=LLì?¹ÈÿL?s%oR neko-2-2-0/boot/nekoml.n000066400000000000000000010324271321613172000150610ustar00rootroot00000000000000NEKOóGQ@Nekoml_Main@IOIO@Neko_Printer neko/Printer@HashtblHashtbl@ListList@Nekoml_Type nekoml/Type@Neko_Compile neko/Compile@LexerLexer@StringString@ReflectReflect@Nekoml_Neko nekoml/Neko@Neko_Lexer neko/Lexer@Nekoml_Typer nekoml/Typer@SysSys@Nekoml_Lexer nekoml/Lexer@ZipZip@Neko_Parser neko/Parser@StackStack@Nekoml_Parser nekoml/Parser@ArgsArgs@Neko_Bytecode neko/Bytecode@CoreCore@Sys_exit@List_iter@String_split@Stack_dump@Neko_Printer_create@String_concat@List_rev@Neko_Bytecode_write@Nekoml_Neko_generate@Core_@compare@String_length@IO_close_out@IO_stderr@Neko_Compile_compile@Core_chr@Core_printf@Nekoml_Lexer_error_msg@Args_String@Core_ignore@String_unserialize@Zip_uncompress@Core_@pcons@Neko_Printer_print@Core_Neko_error@Core_throw@IO_write_file@Core_@empty@Nekoml_Typer_load_module@Nekoml_Typer_module_infos@Sys_version@Zip_init@Hashtbl_iter@List_append@IO_file_contents@Core_@print_union@Core_None@Lexer_line@Nekoml_Type_file_name@String_sub@Neko_Parser_error_msg@Args_Void@Neko_Lexer_error_msg@String_serialize@Stack_exc@Nekoml_Parser_error_msg@String_get@Nekoml_Typer_context@IO_printf@String_set@Core_Some@Zip_compress@Hashtbl_add@IO_write@Lexer_null_pos@Core_ord@Reflect_loader_path@Lexer_source@Neko_Compile_error_msg@Nekoml_Typer_error_msg@Core_string@Nekoml_Typer_verbose@Sys_without_extension@Hashtbl_create@Args_parse@List_map/ Exception : %s  %s(%d): %s H.nekoGenerating %s œ.n Compiling %s þa FileNotFound½FileNotFoundÈNekoML Compiler v.B - (c)2005-2013 Haxe Foundation Usage : nekoml [options] files... nekoml.stdCached %s [%d bytes] ÕüS$ : additional file search path-pm: verbose mode-vu#: generate intermediate .neko files-n} : build module packages-pack : use this module package-usecore/Š: disable std lib-nostd%s not found in %s :®8MpØnekoml/Main@IO@String@BufferBuffer@Core@Core_@print_union@String_blit@Buffer_add_char@String_create@String_sub@Core_assert@Core_ord@Core_Exit@Buffer_add_sub@Core_Neko_error@Buffer_string@Core_sprintf@Core_throw@String_length@String_get@Buffer_add@Buffer_create@Core_magic@Core_chr@Core_min@Core_invalid_argOverflowOverflowEofEofClosed&ClosedBlocked1Blocked@loadstd@< file_open file_contents file_close file_readfile_read_char file_writefile_write_char file_flushP‰’ÂrbräÿCFs¡ª³wbwÚõ  file_stdin file_stdout file_stderrCMUIO.inputbIO.read¤ IO.read_bufà core/IO.nml=©äþ) W ` i r  › ¤  IO.write_i8¶  IO.outputÙ  o  IO.write_ui16  IO.write_i16È  IO.write_ui24ý 4 = F O X a ‚ IO@String@List@Buffer@Core@List_iter@Buffer_string@Core_sprintf@Buffer_add_char@Core_throw@Buffer_add@Buffer_create@Core_chr@Core_invalid_arg@Core_Not_found@Core_ord@string_splitstd@string_split¤  String.getÎ  String.seté  String.blit  String.sub* J j ‚ ì  \n\t\r\\\"\%.3d* · String.unescapeÐ<º@serialize std@serialize@unserializestd@unserialize8@String@List@ArrayArray@Core@Core_@pcons@Array_make@Core_@aset@Array_list@Core_@compare@Array_create@Core_throw@Core_@empty@Array_sort@Core_invalid_arg@Core_Not_found@makeY@rmakeyš§List.hdÚList.tl6€ List.iter2¾Q»þH¢øA…Õ[ List.chop~à List.loopIList.nth–Ä f Ï List@Array@Core@Core_@aset@Core_throw@Core_@aget@Core_Not_found[, ]÷ @makeF!@merge_sortstd@merge_sortV![!i!¼!Æ!Õ!":"d"‘"Ò"â"#$asubE#v##Array@CoreNoneSomeÛ#NoneSome$ Neko_error"$Neko_error0$Invalid_argument=$Invalid_argumentK$Assert_failureX$Assert_failuref$Errorw$Error…$ Stream_error’$Stream_error Not_found $Not_foundExit®$Exit@sprintf std@sprintf@string()¼${ __string = ; }8%¯%@compare &E' Array.getQ' Array.setr'@empty[]—'@pcons :: ›'@cons³'Â'Å'Í'Ü'é'ö'ù'(Core.int ( Core.float"(;(Core.chr>(V(^(f(s({(ˆ(Ÿ(¶(À(o:0Ï(Core.stream_tokenë(Core.stream_junk`)Ñ)nekoCore@Buffer@Core@buffer_newstd@buffer_new@buffer_addstd@buffer_add@buffer_add_substd@buffer_add_sub@buffer_add_charstd@buffer_add_char@buffer_stringstd@buffer_string@buffer_resetstd@buffer_resetÕ/Û/å/Buffer@Neko_Printer@IO@List@String@Neko_Astneko/Ast@Core@IO_write_char@List_iter@IO_write_string@String_make@Core_@compare@Core_None@IO_close_out@IO_write@Neko_Ast_s_constant@Core_assert@IO_printf@Core_fstr5}5Ž5©5%sÓ5E6{;U6 }(  ).%s,var t6while do if elsetrycatch %s function( %s return;return break;break continue $new(null)neko/Printer.nml%s => Á6%s:switch  => k7 default => 7 Z=(>M>‘>neko/Printer@Neko_Ast@List@Lexer@String@Core@Core_@pcons@Core_Some@Core_@print_union@List_iter@Core_None@String_escape@Core_@empty@Core_string@List_mapTrueFalseNullThisIntFloatBuiltinIdentÙ>TrueFalseNullThisIntd?Floatq?String~?Builtin‹?Ident˜?VarWhileDoIfElseFunctionReturnBreakContinueDefaultTryCatchSwitch¥?VarWhileDoIfElseFunctionReturnBreakContinueDefaultTryCatchSwitch SemicolonDotCommaArrow BraceOpen BraceClose ParentOpen ParentClose BracketOpen BracketCloseConstKeywordBinopComment CommentLineh@EofSemicolonDotCommaArrowBraceOpenBraceCloseParentOpenParentCloseBracketOpenBracketCloseConstUAKeywordbABinopoAComment|ACommentLine‰A NormalWhileDoWhile–ANormalWhileDoWhileEConstEBlock EParenthesisEFieldECallEArrayEVarsEWhileEIfETry EFunctionEBinopEReturnEBreak EContinueENextEObjectELabelESwitchÊAEConstáBEBlockîBEParenthesisûBEFieldCECallCEArray*CEVars;CEWhileHCEIf\CETrypCEFunction„CEBinop•CEReturn©CEBreak¶CEContinueENextÃCEObjectÔCELabeláCESwitchîCD DD*DEDWDiD{DD DßDóD EH6HCHYHtruefalsenullthis"$¦JvarwhiledoiffunctionreturnbreakdefaultcatchswitchK=>/**///sKneko/Ast@Lexer@IO@List@String@LexEngine LexEngine@Core@Core_Some@List_array@Core_@print_union@String_blit@IO_input@String_create@Core_None@LexEngine_make_tables@String_sub@Core_assert@Core_fst@Core_@aget@Core_max@Core_Exit@Core_Neko_error@LexEngine_determinize@IO_read_string@Core_snd@String_length@String_get@Core_throw@LexEngine_parse@Core_@empty@Core_min@Core_invalid_arg@List_map Invalid_rule!LInvalid_rule,L9L=LALiL L¤L«LèLM MþM+NNìNcore/Lexer.nml²O³PìPLexer.empty_table#Q,QLexer@LexEngine@List@Hashtbl@Array@String@Core@List_array@Array_make@Core_@print_union@List_iter@Array_map@Hashtbl_find@Core_None@Core_assert@Array_sort@List_mem@List_filter@Core_fst@List_rev@Core_compare@Array_iteri@Core_@aset@Core_@compare@Array_iter@String_get@String_length@List_exists@Array_init@Core_Some@List_fold@Core_ignore@Hashtbl_add@Core_@aget@Core_ord@List_assoc@Core_@pcons@List_concat@Core_Neko_error@List_sort@Core_snd@Array_length@Core_throw@Core_@empty@List_map@List_append@Hashtbl_createEmptyMatchStarPlusNextChoiceVQEmptyMatch·QStarÄQPlusÑQNextÞQChoiceïQRcore/LexEngine.nmlRþRuS×SðSTTTJTYTjTˆU¢UßUtVxV‘V´VËVÜV\WtWW1X›XŸX¯XdY{Y‡Y¬Y¿YÓYôY¥ZãZ[0[A[\[ InvalidRegexp¡[InvalidRegexp¬[¹[Õ[û[\#\º\ð\&]_]~]¿^LexEngine@Hashtbl@Core@Core_throw@Core_Not_found?`G`P`X`v`…`”`£`·`Hashtbl@Nekoml_Type@List@Hashtbl@Lexer@String@Core@String_set@Core_@print_union@List_iter@String_make@Hashtbl_find@String_sub@Core_assert@Hashtbl_add@String_concat@Core_ord@Core_@pcons@Core_sprintf@Core_Neko_error@String_get@String_length@Core_@empty@Core_chr@Core_string@Core_invalid_arg@List_exists@List_length@Hashtbl_create@List_phys@List_mapMutable Immutable’kMutableImmutable TAbstractTMonoTPolyTRecordTUnionTTupleTLinkTFunTNamedÆkTAbstractTMonoQlTPolyTRecord^lTUnionklTTuple|lTLink‰lTFun–lTNamed§lTVoidTIntTBoolTFloatTStringTCharTIdentTConstrTModule»lTVoidTIntFmTBoolSmTFloat`mTStringmmTCharzmTIdent‡mTConstr”mTModule¡mMRootMFailureMHandleMExecute MConstantsMFieldMTupleMToken MRecordFieldMJunkMSwitchMBindMWhenMNext²mMRootMFailureMHandleƒnMExecute”nMConstants¥nMField¶nMTupleÇnMTokenØnMRecordFieldénMJunkýnMSwitchoMBind"oMWhen6oMNextGoTConstTBlock TParenthesisTCallTFieldTArrayTVarTIf TFunctionTBinop TTupleDecl TTypeDeclTMut TRecordDecl TListDeclTUnopTMatchTTry TTupleGet TErrorDeclTWhileXoTConst‹pTBlock˜pTParenthesis¥pTCall²pTFieldÃpTArrayÔpTVaråpTIföpTFunction qTBinop!qTTupleDecl5qTTypeDeclBqTMutOqTRecordDecl\qTListDecliqTUnopvqTMatch‡qTTry›qTTupleGet¬qTErrorDecl½qTWhileÎqßqäq=rHrVr\rfrvoidintfloatcharerrorstringbool„ròrssRsZs‰s‘s³sÁsãsðsNekoml.Type.file_nametÙtìtmutable u '_%snekoml/Type.nml'%s{ %s } : =uhu(%s) -> ) †u>x xÄxàx‚z˜z­znekoml/Type@Neko_Compile@Hashtbl@List@Lexer@Array@MapMap@String@Neko_Ast@Neko_Bytecode@Core@Neko_Bytecode_op_param@Neko_Ast_Builtin@Neko_Bytecode_SetIndex@Neko_Bytecode_trap_stack_delta@Neko_Bytecode_GlobalFloat@List_rev@Neko_Bytecode_Mod@Neko_Bytecode_Bool@Neko_Bytecode_Apply@Neko_Bytecode_MakeEnv@String_length@Array_iter@Neko_Bytecode_SetGlobal@Neko_Bytecode_Lte@Neko_Bytecode_Neq@Neko_Bytecode_AccIndex0@Array_set@Neko_Bytecode_AccIndex1@Neko_Bytecode_Or@Hashtbl_length@Core_Neko_error@Neko_Ast_EField@Core_snd@Neko_Bytecode_Not@Neko_Bytecode_GlobalString@Neko_Bytecode_AccEnv@Neko_Bytecode_SetThis@Core_@empty@Neko_Bytecode_ObjCall@Neko_Bytecode_Jump@List_length@Array_make@Core_@print_union@Neko_Bytecode_AccInt@Core_assert@String_sub@Array_sort@Neko_Bytecode_New@Neko_Bytecode_Pop@Neko_Bytecode_JumpTable@Neko_Ast_Ident@Array_add@Neko_Bytecode_PhysCompare@Neko_Bytecode_AccGlobal@Neko_Bytecode_Div@Neko_Bytecode_Ret@Hashtbl_add@Neko_Bytecode_Xor@Core_Exit@Neko_Bytecode_GlobalVersion@Neko_Bytecode_TypeOf@Array_length@Neko_Bytecode_SetField@Neko_Bytecode_Lt@Array_append@Neko_Bytecode_JumpIf@Neko_Bytecode_AccThis@Map_iter@Hashtbl_create@Neko_Bytecode_JumpIfNot@List_iter@Neko_Bytecode_SetEnv@Map_find@Map_add@Neko_Bytecode_Hash@Array_map@Neko_Bytecode_EndTrap@Neko_Ast_EConst@Neko_Bytecode_AccStack@Hashtbl_exists@Neko_Bytecode_Shl@Core_@aset@Core_compare@Neko_Ast_EBlock@Neko_Bytecode_GlobalDebug@Core_@compare@Neko_Bytecode_SetArray@Neko_Ast_EVars@Neko_Ast_EBinop@Neko_Bytecode_Eq@Neko_Ast_EIf@Neko_Bytecode_AccTrue@Core_ignore@Neko_Bytecode_Gte@Neko_Ast_Int@Neko_Bytecode_Sub@Core_@pcons@Neko_Bytecode_TailCall@Core_sprintf@List_sort@Core_throw@Neko_Ast_ECall@Neko_Bytecode_Mult@Map_empty@Neko_Bytecode_AccField@Neko_Bytecode_AccIndex@Hashtbl_iter@Neko_Bytecode_Shr@Hashtbl_find@Core_None@Array_create@Neko_Bytecode_UShr@Neko_Bytecode_IsNotNull@Core_fst@Neko_Bytecode_AccFalse@Neko_Bytecode_AccNull@Neko_Bytecode_Push@Neko_Bytecode_SetStack@Neko_Ast_iter@Neko_Bytecode_MakeArray@Neko_Bytecode_AccArray@Neko_Bytecode_Compare@Neko_Bytecode_AccBuiltin@Neko_Bytecode_Call@Core_Some@Neko_Bytecode_IsNull@Neko_Ast_This@Lexer_null_pos@Neko_Bytecode_And@Neko_Bytecode_GlobalVar@Neko_Bytecode_AccStack0@Neko_Bytecode_Add@Neko_Bytecode_AccStack1@Neko_Bytecode_Loop@Neko_Bytecode_GlobalFunction@Core_string@Neko_Bytecode_Trap@List_map@Neko_Bytecode_GtXEnvXStackXGlobalXFieldXIndexXArrayXThis‚XEnv‰‚XStack–‚XGlobal£‚XField°‚XIndex½‚XArrayXThisÊ‚ErrorÕ‚æ‚õ‚ø‚Stack alignment failureÒ„ç„ñ„°…ï…†2†Y†€†Ÿ†ÆÛ†>‡{‡‡‡¢‡®‡Break outside a loopà‡Continue outside a loopð‡ˆarray"ˆAˆ ˆ‰0‰applyO‰n‰0Variable declaration must be done inside a block‰neko/Compile.nml=Ö‰Š2Label is not supported in this part of the programDuplicate label ==-ŠqŠtnulltinttfloattbooltstringtobjecttarray tfunction tabstractN‘Invalid access+”–Ö+-*%<<>>>>>|&^!=>>=<<=Unknown operation„—&&||++=--=+=-=/=*=%=<<=>>=>>>=|=&=^=%™M¡r¡€¡¢¡istruenottypeofhashnewcomparepcomparegotoUnknown label ô¢a£‹£throwÏ£Invalid $goto statement ¤aconcat‘¤ª¤äܤõ¤«call$tmpø«¬*¬¬¹¬ø¬o:7­Label failure %d %d %s %sp­w­’­Ÿ­½­À­ ®®T®®”®_á¼#½3½C½l½­½neko/Compile@Map@Core@Core_compare@Core_@print_union@Core_@compare@Core_throw@Core_assert@Core_Not_found@Core_invalid_arg@Core_maxNoded¿EmptyNode˜¿²¿Û¿ core/Map.nmlÀÂMap.remove_min_bindingsÂäÂ4Ã<ÃEÃUÃÄDĶÄÝÄošů*ÆÆžÆ Ç2ÇŠÇMap@Neko_Bytecode@Hashtbl@IO@List@Array@String@Buffer@Core@Array_make@IO_read_byte@Core_@print_union@List_iter@Array_create@Hashtbl_find@String_make@IO_write_i32@Core_assert@IO_read_ui16@IO_read_i32@Array_iteri@Core_@aset@IO_read@IO_write_ui16@IO_write_string@Array_iter@String_length@Buffer_create@Core_invalid_arg@Array_get@IO_printf@IO_read_char@Array_init@Array_add@IO_write_char@Buffer_add_char@Array_set@IO_write_byte@Hashtbl_add@IO_write@Core_@aget@Core_@pcons@Core_Neko_error@Buffer_string@Core_sprintf@String_escape@Array_length@Core_throw@Core_@empty@Core_string@Core_error@Hashtbl_createAccNullAccTrueAccFalseAccThisAccIntAccStack AccGlobalAccEnvAccFieldAccArrayAccIndex AccBuiltinSetStack SetGlobalSetEnvSetFieldSetArraySetIndexSetThisPushPopCallObjCallJumpJumpIf JumpIfNotTrapEndTrapRetMakeEnv MakeArrayBoolIsNull IsNotNullAddSubMultDivModShlShrUShrOrAndXorEqNeqGtGteLtLteNotTypeOfCompareHashNew JumpTableApply AccStack0 AccStack1 AccIndex0 AccIndex1 PhysCompareTailCallLoopÉAccNullAccTrueAccFalseAccThisAccIntŸÌAccStack¬ÌAccGlobal¹ÌAccEnvÆÌAccFieldÓÌAccArrayAccIndexàÌAccBuiltiníÌSetStackúÌSetGlobalÍSetEnvÍSetField!ÍSetArraySetIndex.ÍSetThisPushPop;ÍCallHÍObjCallUÍJumpbÍJumpIfoÍJumpIfNot|ÍTrap‰ÍEndTrapRet–ÍMakeEnv£ÍMakeArray°ÍBoolIsNullIsNotNullAddSubMultDivModShlShrUShrOrAndXorEqNeqGtGteLtLteNotTypeOfCompareHashNewJumpTable½ÍApplyÊÍAccStack0AccStack1AccIndex0AccIndex1PhysCompareTailCall×ÍLoop GlobalVarGlobalFunction GlobalString GlobalFloat GlobalDebug GlobalVersionèÍGlobalVarIÎGlobalFunctionVÎGlobalStringgÎGlobalFloattÎGlobalDebugÎGlobalVersion’Î Invalid_fileŸÎInvalid_fileªÎ®ÎField hashing conflict  and ЦÑÏÑNeko.Bytecode.write_debug_infos?ÒTÒÙÒ¬ÓNEKOpÔnÕƒÕkÙöÙ"ÚNeko.Bytecode.read_debug_infosKÚNeko.Bytecode.loopTÚ¯Û[Ü Ýneko/Bytecode.nml…ݦ݌ÞÌÞnglobals : %d  nfields : %d codesize : %d ops , %d total  GLOBALS =  global %d : %s  function  nargs string "float debug %d ops %d bytesversion Æä FIELDS =  %s%s%.8X ÁåCODE = ÿå%.6X %6d %s  AccField  AccBuiltin  SetField æEND Ûèneko/Bytecode@Reflect@List@Core@Core_@print_union@Core_magic@Core_invalid_arg@List_mapVNullVIntVFloatVBoolVStringVObject VAbstract VFunctionVArrayäõVNullVIntoöVFloat|öVBool‰öVString–öVObject£öVAbstract°öVFunction½öVArrayÊö@module_readstd@module_read@module_namestd@module_name@module_exportsstd@module_exports@module_loaderstd@module_loader@module_execstd@module_exec@module_nglobalsstd@module_nglobals@module_global_getstd@module_global_get@module_global_setstd@module_global_set@module_code_sizestd@module_code_size@module_read_pathstd@module_read_path Reflect.value×öàö|÷øø!ø5ø@øNø‡øøœø©ø¶ø¾øÍøåøReflect@Nekoml_Neko@Nekoml_Typer@Hashtbl@List@IO@Nekoml_Type@Lexer@Array@Neko_Parser@SetSet@String@Neko_Ast@Buffer@Core@Nekoml_Typer_module@Array_list@Set_add@List_iter@Nekoml_Type_TIdent@String_split@String_concat@Neko_Ast_Builtin@Neko_Ast_EConst@Neko_Ast_True@Neko_Ast_String@Neko_Ast_ESwitch@Nekoml_Type_t_string@List_rev@Neko_Ast_EBlock@Core_compare@Core_@compare@IO_read_string@Neko_Ast_EVars@Lexer_input@Neko_Ast_EBinop@Nekoml_Type_mk@Neko_Ast_EIf@Lexer_create@Neko_Ast_EWhile@Neko_Ast_Int@Neko_Ast_Float@Nekoml_Type_t_error@Neko_Ast_Null@Core_@pcons@Core_Neko_error@Neko_Ast_EField@Nekoml_Typer_union@Core_snd@List_sort@Neko_Ast_ECall@Core_@empty@Nekoml_Type_MRoot@Nekoml_Type_TModule@List_length@List_phys@Hashtbl_iter@List_append@Core_@print_union@Nekoml_Type_tlinks@Neko_Ast_ETry@Neko_Parser_parse@Hashtbl_find@Core_None@Core_assert@Nekoml_Type_file_name@Core_fst@Set_remove@Neko_Ast_EFunction@Nekoml_Type_TListDecl@Neko_Ast_NormalWhile@Nekoml_Type_MFailure@Neko_Ast_EReturn@Nekoml_Type_TString@Buffer_create@Neko_Ast_ELabel@Neko_Ast_Ident@Hashtbl_hash@Neko_Ast_ENext@Core_Some@Array_init@Neko_Ast_EArray@Neko_Ast_False@Nekoml_Type_TConstr@Hashtbl_add@Nekoml_Type_MExecute@Neko_Ast_EParenthesis@Lexer_null_pos@Core_ord@Set_empty@Nekoml_Type_TConst@Nekoml_Type_MSwitch@Nekoml_Type_TCall@Nekoml_Type_is_int@Core_string@Set_exists@Nekoml_Type_t_void@List_map@Hashtbl_createNative StructuralûNativeStructurallKûviû@‡û—û©û»ûnekoml/Neko.nmlÍûünüÀüËý"þdþ‚þ·þÿüÿ::@empty@cons¤@exc stream_pos@posrethrow% stream_token stream_junkLæ  p¢ ® À    @print_union›ÉýM@compareÚ;`andorxor===!==:=@asetidivneko'@pcons@aget@tmp}¿å!öœ"=#G$”$ç%exportsloader loadmodule/&¦&Ñ&L'nekoml/Neko@Nekoml_Typer@Hashtbl@List@IO@Nekoml_Type@Nekoml_Ast nekoml/Ast@Nekoml_Match nekoml/Match@Array@Lexer@Map@String@Set@Nekoml_Parser@Buffer@Core@Array_list@Nekoml_Type_polymorphize@String_concat@Nekoml_Type_TLink@Nekoml_Ast_EType@Nekoml_Type_TWhile@List_rev@Nekoml_Type_t_string@Nekoml_Type_TErrorDecl@Nekoml_Type_duplicate@String_length@Core_print@Nekoml_Ast_PRecord@Core_magic@Lexer_input@Nekoml_Ast_ETypeDecl@Nekoml_Type_TField@Nekoml_Ast_ATyped@Core_printf@Nekoml_Ast_EBlock@Lexer_create@List_iter2@Nekoml_Type_generator@Nekoml_Type_TTypeDecl@Core_@aget@Nekoml_Ast_Int@Core_Neko_error@Nekoml_Type_TFunction@Core_snd@Core_@empty@Nekoml_Ast_PConstr@Nekoml_Type_TModule@Nekoml_Type_TVoid@Nekoml_Type_TMut@List_length@List_append@Nekoml_Type_TIf@Nekoml_Type_TTry@Nekoml_Ast_SMagicExpr@Core_@print_union@Nekoml_Type_tlinks@Nekoml_Type_TNamed@Nekoml_Ast_Ident@Nekoml_Type_TInt@Nekoml_Match_make@Core_assert@Nekoml_Type_mk_record@Nekoml_Type_file_name@Nekoml_Type_TArray@Nekoml_Type_t_abstract@Set_union@Nekoml_Match_error_ref@Hashtbl_remove@String_get@Buffer_create@List_fold@Nekoml_Type_TRecordDecl@Hashtbl_add@Nekoml_Ast_PStream@Set_empty@IO_read_file@Nekoml_Type_genid@Nekoml_Type_t_bool@Nekoml_Type_t_char@Nekoml_Ast_EAbstract@Nekoml_Type_TConst@Nekoml_Type_TBlock@Nekoml_Ast_SPattern@Hashtbl_create@Nekoml_Type_t_float@Nekoml_Type_t_void@Map_iter@Nekoml_Ast_ETuple@Nekoml_Type_t_polymorph@Nekoml_Type_TChar@Set_add@Nekoml_Type_s_context@List_iter@Map_add@Map_find@Nekoml_Type_TIdent@Nekoml_Type_TBinop@Nekoml_Type_s_type@List_find@Nekoml_Ast_EConst@Nekoml_Ast_PTyped@Nekoml_Ast_EUnion@Hashtbl_exists@Nekoml_Type_TTupleDecl@List_all@Core_@compare@IO_read_string@Nekoml_Type_mk@Nekoml_Type_TParenthesis@List_exists@Nekoml_Ast_ECall@Nekoml_Ast_String@Core_ignore@Nekoml_Ast_ETupleDecl@Nekoml_Type_TFloat@Nekoml_Match_fully_matched_ref@Nekoml_Type_t_error@Nekoml_Type_mk_union@Core_@pcons@List_hd@Core_throw@Nekoml_Type_TMono@Nekoml_Ast_ETupleGet@List_nth@Nekoml_Ast_ANamed@Nekoml_Ast_PTuple@Map_empty@Hashtbl_iter@Nekoml_Type_Immutable@Nekoml_Type_Mutable@Hashtbl_find@Core_None@Nekoml_Type_t_int@Nekoml_Type_TTupleGet@Core_fst@Hashtbl_replace@Nekoml_Parser_parse@Nekoml_Type_TVar@Nekoml_Type_t_mono@Nekoml_Type_mk_fun@Nekoml_Type_TUnop@Nekoml_Ast_PIdent@Nekoml_Type_TString@Set_diff@Nekoml_Type_TMatch@Set_iter@Core_Some@Array_init@Nekoml_Type_t_poly@Nekoml_Ast_EVar@Nekoml_Ast_s_path@Nekoml_Type_TConstr@Lexer_null_pos@Nekoml_Ast_EPoly@Nekoml_Type_TBool@Nekoml_Ast_PAlias@Nekoml_Type_mk_tup@Nekoml_Type_TCall@Nekoml_Type_etype@Core_string@List_split@Set_exists@Nekoml_Type_pos@List_map Cannot_unify Have_no_field Unknown_fieldModule_not_loadedCustom\(Cannot_unify½(Have_no_fieldÎ(Stackß(Unknown_fieldð(Module_not_loadedý(Custom ))Error") Cannot unify  have no field  Unknown field Module  require an interface3)ø)**(*nekoml/Typer.nml7*C*d*k*t*€*‘* Unknown type (+®+Unknown constructor ,Å,Unknown identifier 1-Ó-?.¹."/o/.0‘0ã01Þ1ñ122&Invalid number of type parameters for ç5Unbound type variable 'ù56‡6|9NIntNFloatNStringNNanN;NIntNFloatNStringNNan“;7<P<Field  is not mutablereflistInvalid operation \< K"K@tZL‹LlMÅMInvalid % sequence}OTyping  jR€R{S—SòS4Topenassert invalid_argTYPE%s:(%d): type : %s format#Constant string required for formatToo many arguments@TýV0Variable declaration not allowed outside a blockW&Invalid number of parameters for type "Invalid type redefinition of type W WqWÒW Duplicate declaration for field ÞW—XMissing field  in record declarationáXþXYThis matching is not complete)Y3YrYèY®hii,This variable is several time in the pattern{jkk$Constructor does not take parametersConstructor require parametersstream»kÊkm Variable  must occur in all patterns‰s¡s1t@t%uòuUvkv€v.nmlFile not found  wÒw anonymous Parsed %s  xTyping done with %s 4x]z~za˜znekoml/Typer@Nekoml_Ast@Lexer@String@Core@Core_@print_union@Core_snd@String_escape@Core_string@String_concat@String_escape_charCharConstrModule |Int|Charª|Bool·|FloatÄ|StringÑ|IdentÞ|Constrë|Moduleø|TypeThenWhen Exception }VarIfElseFunctionTryCatchTypeMatchThenWhenWhileExceptionQuoteVertical StreamOpen StreamClose¾}EofSemicolonDotCommaQuoteBraceOpenBraceCloseParentOpenã~ParentCloseBracketOpenBracketCloseArrowVerticalStreamOpenStreamCloseConstð~Keywordý~Binop CommentCommentLine$ETypeEPolyETupleEArrow1ETypevEPolyŠETuple—EArrow¤ EAbstractEAliasERecordEUnionµEAbstractEAliasúERecord€EUnion€ATypedANamedATuple!€ATypedX€ANamedi€ATuplev€SPatternSExpr SMagicExprƒ€SPatternº€SExprÇ€SMagicExprØ€PIdentPConstPTuplePRecordPConstrPAliasPTypedPStreamé€PIdentfPConstsPTuple€PRecordPConstržPAlias²PTypedÃPStreamÔå‚)‚:‚EVarEUnop ETypeAnnot ETupleDecl ETypeDecl EErrorDecl ERecordDeclEMatch ETupleGetEApplyK‚EConstpƒEBlock}ƒEFieldŠƒECall›ƒEArray¬ƒEVar½ƒEIf΃EFunctionâƒEBinopüƒEUnop„ETypeAnnot!„ETupleDecl2„ETypeDecl?„EErrorDeclS„ERecordDecld„EMatchq„ETry‚„ETupleGet“„EApply¤„EWhileµ„Æ„n…typematchthenwhen exception•…->[<>]*--ê…nekoml/Ast@Nekoml_Match@List@Nekoml_Type@Nekoml_Ast@Core@Nekoml_Type_TChar@Core_@print_union@Nekoml_Ast_Ident@Core_None@Nekoml_Type_TIdent@Nekoml_Type_MRecordField@Nekoml_Ast_PConst@Nekoml_Type_TInt@Core_assert@Nekoml_Ast_PTyped@Nekoml_Type_MField@Core_fst@List_rev@Nekoml_Type_MFailure@Core_@compare@Nekoml_Type_MHandle@Nekoml_Ast_PRecord@Nekoml_Type_TString@Nekoml_Type_MTuple@Core_magic@Nekoml_Type_mk@Core_Some@List_fold@Nekoml_Type_TConstr@Nekoml_Type_MExecute@Nekoml_Ast_PStream@Nekoml_Type_TFloat@Nekoml_Type_MToken@Nekoml_Type_MJunk@Nekoml_Type_MBind@Nekoml_Type_TBool@List_assoc@Core_@pcons@List_concat@Nekoml_Ast_PAlias@Core_Neko_error@Nekoml_Type_MSwitch@Core_snd@Nekoml_Type_TConst@Nekoml_Type_MConstants@Nekoml_Type_MWhen@Nekoml_Ast_PConstr@Core_@empty@Nekoml_Type_MRoot@Nekoml_Type_MNext@Nekoml_Ast_PTuple@Nekoml_Type_TVoid@Nekoml_Type_TModule@List_map@List_length@List_append@Nekoml_Type_t_voidTotalPartialDubious]ŒTotalPartialDubious”Œnekoml/Match.nml—Œ£Œ®ŒÜŒæŒðŒXbÀŽ3ŽY“#z¨ç‘D‘W‘•‘’"’†’é’“ “^“¹”$•œ¨§ » Some pattern are never matchedThis pattern is never matched¡nekoml/Match@Set@Core@Core_compare@Core_@print_union@Core_throw@Core_assert@Core_Not_found@Core_max˜¥EmptyNode̥㥠¦ core/Set.nml4¦ ¨|¨ߨ/©Æ©Ϊ!«ë«¬¬¬(¬„¬¨¬.­^­­®ä®ì¯#°*±a±«±Set@Nekoml_Parser@Nekoml_Lexer@Nekoml_Ast@Lexer@Core@Nekoml_Ast_EMatch@Nekoml_Ast_ETypeAnnot@Lexer_punion@Nekoml_Ast_EConst@Nekoml_Ast_EUnion@Nekoml_Ast_PTyped@Nekoml_Ast_EUnop@Nekoml_Ast_EType@Core_Stream_error@Nekoml_Ast_EArrow@Nekoml_Ast_EBinop@Nekoml_Ast_ETypeDecl@Nekoml_Ast_PRecord@Nekoml_Ast_ECall@Nekoml_Ast_EApply@Nekoml_Ast_ATyped@Nekoml_Ast_EBlock@Nekoml_Ast_EWhile@Nekoml_Ast_s_token@Nekoml_Ast_EFunction@Nekoml_Ast_EErrorDecl@Nekoml_Ast_ETupleDecl@Nekoml_Ast_SExpr@Core_@pcons@Nekoml_Ast_EField@Nekoml_Ast_Int@Nekoml_Ast_Module@Nekoml_Ast_ERecordDecl@Core_Neko_error@Core_snd@Nekoml_Ast_Constr@Nekoml_Ast_EAlias@Core_throw@Nekoml_Ast_PConstr@Core_@empty@Nekoml_Ast_PTuple@Nekoml_Ast_ANamed@Nekoml_Ast_EIf@Core_@print_union@Core_stream_junk@Core_None@Nekoml_Ast_Ident@Core_stream@Nekoml_Ast_PConst@Core_assert@Core_fst@Nekoml_Lexer_token@Nekoml_Ast_ATuple@Nekoml_Ast_ETry@Core_stream_pos@Nekoml_Ast_PIdent@Core_stream_token@Nekoml_Ast_ERecord@Core_Some@Nekoml_Ast_EArray@Nekoml_Ast_EVar@Nekoml_Ast_pos@Nekoml_Ast_PStream@Nekoml_Ast_EPoly@Lexer_null_pos@Nekoml_Ast_EAbstract@Nekoml_Ast_PAlias@Nekoml_Ast_SPattern@Nekoml_Ast_Eof@Lexer_token@Nekoml_Ast_ETuple UnexpectedUnclosed¬³Unexpectedà³Unclosedí³ú³Error´ Unexpected  Unclosed ´Q´<>`´C¶m¶ ·z·¸…¸θݸ帺ÇwÊRËnekoml/Parser.nmlÎÏFÑYÒgÔöÕN×CØuÙÍÚrecrÛíÛhÜùÜxÝÏàxáÿáJä%åtæLçËçmutable_éØëlíîÄïasƒð óùúÒûòüqýþþÿ‘ÿ … €nekoml/Parser@Nekoml_Lexer@Hashtbl@List@Nekoml_Ast@Lexer@String@Neko_Lexer@Buffer@Core@List_iter@Nekoml_Ast_Var@Lexer_punion@Lexer_char@Nekoml_Ast_Float@Nekoml_Ast_Quote@Nekoml_Ast_Keyword@Nekoml_Ast_Char@Nekoml_Ast_Then@Lexer_current@String_length@Core_chr@Nekoml_Ast_String@Nekoml_Ast_Binop@Neko_Lexer_ecomment@Nekoml_Ast_Vertical@Nekoml_Ast_Try@Nekoml_Ast_ParentOpen@Nekoml_Ast_BracketClose@Nekoml_Ast_Match@Nekoml_Ast_Arrow@String_escape_char@Buffer_reset@Nekoml_Ast_StreamOpen@Core_@pcons@Nekoml_Ast_Int@Core_int@Neko_Lexer_estring@Core_sprintf@Core_Neko_error@Lexer_build@Nekoml_Ast_Constr@Core_throw@Nekoml_Ast_Bool@Nekoml_Ast_Catch@Core_@empty@Nekoml_Ast_CommentLine@Core_@print_union@Nekoml_Ast_Ident@Hashtbl_find@Nekoml_Ast_Semicolon@String_sub@Nekoml_Ast_Const@Nekoml_Ast_BraceClose@Nekoml_Ast_Function@Nekoml_Ast_Dot@Nekoml_Ast_Comma@String_get@Nekoml_Ast_BraceOpen@Nekoml_Ast_BracketOpen@Nekoml_Ast_Else@Nekoml_Ast_Exception@Hashtbl_add@Lexer_empty@Nekoml_Ast_ParentClose@Nekoml_Ast_If@Lexer_data@Buffer_string@Nekoml_Ast_StreamClose@Nekoml_Ast_Type@Nekoml_Ast_When@Nekoml_Ast_Comment@Lexer_token@Nekoml_Ast_Eof@Lexer_curpos@Hashtbl_create@Nekoml_Ast_s_keyword@Nekoml_Ast_WhileInvalid_characterUnterminated_stringUnclosed_commentInvalid_escaped_characterInvalid_escapeInvalid_characterkUnterminated_stringUnclosed_commentInvalid_escaped_characterxInvalid_escape…ErrorInvalid character '%s'Unterminated stringUnclosed commentInvalid escaped character %dInvalid escape sequence¡ëw•®[a-z_][a-zA-Z0-9_]*[A-Z][a-zA-Z0-9_]*[-!=*/<>&|%+:][0-9][ ]+ÂÎÚåðû /:\[EP[f0x[0-9a-fA-F]+r†š/\*‘'\\n'¦'\\t'»'\\r'Ð'\\''å'\\\\'ú'\\"''[^\\]'0'\\[0-9][0-9][0-9]'z //[^ ]* ?Ã\[<ÎÙ?äýnekoml/Lexer@Neko_Lexer@Hashtbl@List@Lexer@String@Neko_Ast@Buffer@Core@List_iter@Neko_Ast_Default@Neko_Ast_Keyword@Neko_Ast_Semicolon@Neko_Ast_BraceOpen@Neko_Ast_Function@Neko_Ast_ParentOpen@Neko_Ast_BracketClose@Neko_Ast_Builtin@Lexer_punion@Neko_Ast_True@Lexer_char@Neko_Ast_String@Neko_Ast_Return@Neko_Ast_Continue@Neko_Ast_While@Lexer_current@String_length@Neko_Ast_BracketOpen@Core_chr@Neko_Ast_Try@Neko_Ast_Int@Neko_Ast_Float@Neko_Ast_BraceClose@Neko_Ast_ParentClose@Neko_Ast_Null@Buffer_reset@Core_@pcons@Core_int@Core_sprintf@Core_Neko_error@Neko_Ast_Switch@Lexer_build@Core_throw@Neko_Ast_Do@Core_@empty@Neko_Ast_Binop@Neko_Ast_s_keyword@Core_@print_union@Hashtbl_find@Neko_Ast_Dot@Neko_Ast_Arrow@String_sub@Neko_Ast_If@Neko_Ast_Else@Neko_Ast_Catch@String_get@Buffer_add@Neko_Ast_Ident@Buffer_add_char@Neko_Ast_Break@Neko_Ast_Const@Neko_Ast_False@Neko_Ast_This@Hashtbl_add@Lexer_empty@Neko_Ast_Comma@Core_ord@Neko_Ast_Comment@Core_Exit@Lexer_data@Neko_Ast_Eof@Buffer_string@Neko_Ast_Var@Neko_Ast_CommentLine@Lexer_token@Lexer_curpos@Hashtbl_create Unclosed_nxmlbInvalid_characterÃUnterminated_stringUnclosed_commentUnclosed_nxmlInvalid_escaped_characterÐInvalid_escapeÝErrorèInvalid character '%c'Invalid character 0x%.2X Unclosed nxmlùz  ¢ ® Ì å [a-zA-Z_@][a-zA-Z0-9_@]*[-!=\*/<>&|^%\+:]= I U a Continuel y „  š ¥ ° » Æ Ñ Ü ç [ ]+[0-9]+ [0-9]+.[0-9]*.[0-9]+ó ' 7 G W g o í f ¯ à × ç ÷ : \*/= \*W [^*]+q z \\" \\\\¦ \\n¼ \\tÒ \\rè \\[0-9][0-9][0-9]/:=[^\\"]+W`mˆ[^<]+¢neko/Lexer@Neko_Parser@IO@Neko_Binast neko/Binast@Lexer@Neko_Xmlneko/Xml@Neko_Ast@Neko_Lexer@Buffer@Core@Core_@print_union@Core_stream_junk@Neko_Ast_ETry@Core_None@Neko_Ast_Keyword@Neko_Ast_Default@Core_stream@Neko_Xml_parse_string@Lexer_punion@Neko_Ast_EConst@Core_fst@Neko_Ast_ESwitch@Neko_Ast_EFunction@Neko_Ast_NormalWhile@Neko_Ast_DoWhile@Neko_Ast_EBlock@Core_Stream_error@Core_stream_pos@Neko_Ast_EObject@IO_read_string@Neko_Ast_s_token@Neko_Ast_EVars@Neko_Ast_EReturn@Buffer_create@Lexer_input@Neko_Ast_EBinop@Core_stream_token@Neko_Ast_ELabel@Neko_Ast_pos@Neko_Ast_EContinue@Neko_Ast_Ident@Core_Some@Neko_Ast_EWhile@Neko_Ast_EIf@Neko_Ast_EArray@Lexer_create@Neko_Ast_Int@Neko_Ast_EParenthesis@Lexer_null_pos@Neko_Binast_parse_from_string@Core_@pcons@Neko_Ast_Eof@Neko_Ast_EField@Core_Neko_error@Core_snd@Core_throw@Neko_Ast_ECall@Neko_Lexer_expr@Core_string@Core_@empty@Neko_Ast_EBreak@Lexer_token Invalid_nxmlg-Unexpectedž-Unclosed«-Invalid_nxml¸-Å-ErrorÐ-Invalid nxml (á-).8.90A0é0 2+3AiDþFóGiIŽK§L8M·MlOóOSPÚPneko/Parser@Neko_Binast@IO@Lexer@Array@Neko_Ast@Core@IO_read_byte@Neko_Ast_ETry@Core_None@Array_create@Core_assert@Neko_Ast_Builtin@IO_read_ui16@Neko_Ast_True@Neko_Ast_EConst@Core_fst@IO_read_i32@Neko_Ast_String@Neko_Ast_ESwitch@Neko_Ast_EFunction@IO_read@Neko_Ast_EBlock@Neko_Ast_NormalWhile@Neko_Ast_DoWhile@Neko_Ast_EObject@IO_read_ui24@Neko_Ast_EVars@Neko_Ast_EReturn@Array_get@Neko_Ast_EBinop@Neko_Ast_ELabel@Neko_Ast_Ident@Neko_Ast_EContinue@Neko_Ast_ENext@Core_Some@Array_add@Neko_Ast_EArray@Neko_Ast_EWhile@Neko_Ast_EIf@Neko_Ast_False@Neko_Ast_Int@Neko_Ast_This@Neko_Ast_Float@Neko_Ast_EParenthesis@Neko_Ast_Null@Core_@pcons@Neko_Ast_EField@Array_length@Neko_Ast_ECall@Core_@empty@Neko_Ast_EBreak@Core_errorneko/Binast.nmlQNBA+QtQInvalid const tag : §QInvalid op tag PRySS©SÞSýSInvalid expr tag : TInvalid binast headerÂWneko/Binast@Neko_Xml@List@Lexer@String@Neko_Ast@XmlXml@Core@List_iter@String_split@String_concat@Neko_Ast_Builtin@Neko_Ast_EConst@Neko_Ast_True@List_rev@Neko_Ast_String@Neko_Ast_ESwitch@Neko_Ast_EBlock@Core_@compare@Xml_attrib@String_unescape@String_length@Neko_Ast_EVars@Neko_Ast_EBinop@Neko_Ast_EWhile@Neko_Ast_EIf@Neko_Ast_Int@Neko_Ast_Float@Xml_Node@Neko_Ast_Null@Core_int@Core_@pcons@Core_Neko_error@Neko_Ast_EField@Neko_Ast_ECall@Core_throw@Core_@empty@Xml_node_text@List_append@Xml_node_name@Core_@print_union@Neko_Ast_ETry@Core_None@Core_assert@String_sub@Xml_firstNode@Neko_Ast_EFunction@Neko_Ast_NormalWhile@Neko_Ast_DoWhile@Neko_Ast_EObject@String_get@Neko_Ast_EReturn@Neko_Ast_s_constant@Core_invalid_arg@Neko_Ast_ELabel@Xml_nodes@Neko_Ast_Ident@Neko_Ast_EContinue@Neko_Ast_ENext@Core_Some@Neko_Ast_EArray@Xml_parse@Neko_Ast_False@Neko_Ast_This@Neko_Ast_EParenthesis@Lexer_null_pos@Neko_Ast_EBreak@Core_string@List_map"ZError-Z neko/Xml.nml:ZFZNeko.Xml.errorL[U[ifsbgconextobjectlabelÄ[9\F\T\b\case\Unknown node name : …]Neko.Xml.parse'd}dßdeYeqlneko/Xml@Xml@List@IO@String@Buffer@Core@Core_@print_union@List_iter@List_find@IO_write@String_concat@List_filter@List_hd@String_lowercase@Buffer_string@IO_write_string@Core_snd@String_escape@Buffer_add@Buffer_create@Core_invalid_arg@IO_printf@List_mapPCDataCDataDocumentšlNodeßlPCDataólCDatamDocument mmError%m@parsero:02mEmXmºmøm@parse std@parse_xml$nln‚n˜n Xml.firstNode®n Xml.nodes÷n Xml.node_name@o Xml.node_textdo´oôo Xml.attribp<%s%s="Ep/> epDqXml@Sys@List@Array@String@Core@Array_make@Core_Some@String_split@Core_None@String_concat@Core_assert@List_rev@sys_exit std@sys_exit@get_env std@get_env@get_cwd std@get_cwd@exe_pathstd@sys_exe_path@sys_file_typestd@sys_file_type@sys_read_dirstd@sys_read_dirú}]~\ core/Sys.nml§~ù~std@sys_exists std@put_env* std@set_cwd0dir6BSys@Zip@String@Buffer@Core@Buffer_add_sub@Core_@print_union@Buffer_string@String_create@Core_None@String_length@Core_throw@Core_string@String_sub@Buffer_create@Core_ErrorNOSYNCFULLFINISHBLOCKÜ€NOSYNCFULLFINISHBLOCK@set_flush_modezlib@set_flush_mode@inflate_initzlib@inflate_init@deflate_bufferzlib@deflate_buffer@inflate_bufferzlib@inflate_buffer@deflate_initzlib@deflate_init@deflate_boundzlib@deflate_bound@deflate_endzlib@deflate_end@inflate_endzlib@inflate_end/©¹ÁËÓí‚4‚<‚K‚Compression failedZ‚È‚ƒZip@Stack@IO@Array@Core@Core_@print_union@IO_stdout@Array_iter@IO_write@IO_printf CFunctionPosÅ„CFunctionModuleü„Pos …@make_stack…‚……Called from a C function $Called from %s (no debug available) Called from %s line %d ˜…ì…û…Stack@Args@List@Sys@Hashtbl@Array@Core@Sys_exit@Core_int@Core_@print_union@List_iter@Core_Neko_error@Hashtbl_find@Array_length@Core_throw@Core_print@Hashtbl_add@Sys_args@Core_@aget@Core_printf@Hashtbl_createVoid´†Voidë†Stringø†Int‡Invalid‡Invalid Options :  %s %s ‡7‡V‡-help--helpb‡x‡Invalid argument : ‡S‰ArgsBnekoml/Mainnekoml/Main.nmlIOcore/IO.nmlStringcore/String.nmlListcore/List.nmlArraycore/Array.nmlCorecore/Core.nmlBuffercore/Buffer.nmlneko/Printerneko/Printer.nmlneko/Astneko/Ast.nmlLexercore/Lexer.nmlLexEnginecore/LexEngine.nmlHashtblcore/Hashtbl.nmlnekoml/Typenekoml/Type.nmlneko/Compileneko/Compile.nmlMapcore/Map.nmlneko/Bytecodeneko/Bytecode.nmlReflectcore/Reflect.nmlnekoml/Nekonekoml/Neko.nmlnekoml/Typernekoml/Typer.nmlnekoml/Astnekoml/Ast.nmlnekoml/Matchnekoml/Match.nmlSetcore/Set.nmlnekoml/Parsernekoml/Parser.nmlnekoml/Lexernekoml/Lexer.nmlneko/Lexerneko/Lexer.nmlneko/Parserneko/Parser.nmlneko/Binastneko/Binast.nmlneko/Xmlneko/Xml.nmlXmlcore/Xml.nmlSyscore/Sys.nmlZipcore/Zip.nmlStackcore/Stack.nmlArgscore/Args.nmlQ"pÐZ>>vž$zz¾>>F&$>Jnz>Vf^f*$>Jnú>vff*$fzŽ>N>>j$>"„>b>À>>>VZrâ Ø4>jbb¶>>$>Z>>PâJ>h>â.h>PT>,>>’z~>>Fè¾è $><>6" 0>bnn.D>„>>>n&>>>Jj*6<>F*t~~>Vr–€~rr`RD.< x>´b& Zj.*D>F*D~ŽŽÎ&€Ú$Š&T6œF p<$2$^>>j>$v^’^VVb>Jzr¾,v^’^VVJf>J>rr>†à>"T~:à>ŒZNJN>–*x>"4x>\ZJNbz¶:Ø>"DØ>lZ^bb>:$Z^2$Z^b>$Z^fnž,bf&8ZZZ"TŠ ¨ ˜D"$> $>V:$^>>j>$Rfb>Jzr>,^rr:$>Vb:$>V^¾*$>Vbr:$",bff&È ZZZZ"$> " èZN^n¦Dbv$>&$>>&$vv$vv<>Z€¶&€>$fj>€phŽ>TV*$6$>>z – Ö $,&4>6<*tn¦>>>b*˜–*˜Ö*˜$&˜,&˜&4>>˜6<*˜L2phŽ>>„&$Z^VVb>’r>Fr>>>>>>>>>>>>>>>>D6hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hd>R>F>Fr>>Vb>>~z>hT6hŽ:h46h$6h´h@ô>@@f¶>,ZvV>Jbr>>r>†$ZvV>Jbr>>r>†L$* "PÈNZ>$NN>î6,>ZHŽ> H<>Z&€Ž€<>Z&¸Ž¸<>Zð¢>>ð<>Z(¢>&(<>šnp–p`"<>^&˜âj>˜&`Œ>Z&èþz>>.èL>Z0¢>:0<>Zh¢>>h<>Z& ¾>>& <>Z&ؾ>>Ø<>Z&¢>:<>ZH¢>:H<*$>Z ¢>> <>ZØ¢>>ØD>Zâ>.N><2$ZN>^&xŽ>x<>Z°â>:°D>Zðâ>:ðL>Z&8â>>8(N:Z¢>>>d>Zðâv>ðÈ>Z"Èâ>ØŽ>Df.È”Zf*"ÈÈJNVN^>V^^ªb4><$6,JVn>F>Ržb:,&$:,ZN^b¦:4ZN^v¦:4NNV^j6F¦:4>4NVV^^>–4NNV^z6N>.4>4NVN^>^Nî&"X >>>>*<>n>r>>F>rzz:ÜžN>V^NbN^>J^^ªbÚ*$ZNNrZ^^^ª>>F²b$Z^RNb^>J^^ªb"$nRfbbZZNR>FbžN^>z^N®šfJR>FbžbN^Z~>>N^N²šêò>Fj$~jîR>¦>D $$:$2$òÎNÖN$Zv$Zv$ $>V$$$2$$2$>$>$&$:$RZZ.,¶^RNjr>V^z¦Z.,¶fv^>®fZ^f6<X >¼ >>,>J>N>N>N>N>N>¼º¼”„xš44bRÒ^^Þ$ $$$$Ê$ $44 $, $ $$ $ $ $ $ $&$ D””>>>>>>>>>>>>>6¼ ”Þ~Þ$$ t $ $dd d dt 4 ldD 4>>>>>>>> >>>>:Ä44ZÞ>< < <>>>.<><>Œ>L><><><><:<6<$>>*<><>\>L:D6D d> <”>>>>>>>>>>>*  "˜($&$¼$z~~~~>$ $ $ ,JN>>> >>>>:ÄúdJŽ4 $ $ 4 4Š< „ $&d6¬6x*l*tzþ$>>>>>>>>> >>>>>>>>>¼4<>J>N>N><,jnnnnnn®:D&, ´>L&, „rv¶bb"< D $ $ 4 ” Äl tD4<T \ L $ $, 4 \<4D< $ D>>>>>>>>>>>>>>>>>>>>>>"8J N"$V>^–&$>ZжÐ>$V~>*Ð\>dVZj&ìVz>^˜Îj2˜À>Z2À>Ö~ZÀ>2 ÀÄVZjfZ6@Vn>>>š>"P$ff> 4€¬fZ:PÌV>PäVj>F>PXVjZ>P€f>"D ˆLf.P>>èfZ>P"frjZ> P28f^>n>^PÎj>P&P2ˆfv~>P°f>nj>P2ØR>zv~v>>&P>.P f:P>8.PHfº2PpVj^2P&˜&P&¨f& Î>>|Rf>PP> P2`f^j^> 4 €<>Z¸ÎjfZ>¸Df>P Z>ª>F> (&,~jfrf*(&db>Jz&(¼nZj&È>Ž> 4ØÈ&T.È|r^f^*>!"# È>>>>>>>>>>>>>"d>>>>>>>>>>>>:„>>>>>>>>>>>>>>>>>>>>œ>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>2Ä,>$>$>.$> $> $> $> $>\V>^ Ž>  &l>R>*Xä`>>>Ü`N>`Ž>`Þ>`$>2`,>"`<,˜2`2l>>`2t>>>>>`2|>>`„>`2Œ>>`>2”>L`>2œ>D.`¤>"`¬>4`2´>>>>>.`ˆ>>>Lr>PV>>> ¬ XN6XŽ*XÞ2X$>X,> X4> X<> X2D>>>>XL> XT&X\> X>2d&LX>2l&D&Xt> X|> 4 X2„>>>>2XÔ>nRRR(,&(4(<> (D"(L(t>>RRRRRRRRRRRRR˜”>>jRRRRRRRRRR(d&(l&(t(|2(„"(%"'ˆ >"$N,J~>èD $J^NŽhŠNbNN@8Œ$$Z^ff^^^"fzzVºf>fVZ>nv¾vrr$Z^rV:,Fbvvf2Ð>"<Ð:´>Fn^^^^šz>ÒRR^^V>N>Ž’vf>^vfvVb>V²X^bb"P,>> d>ÌFj: >>,br>† \ >lZ®>$>>>>^>ÆJX>)"+h @>>>>>>>>>>>Œ:$~èº è>>>>$^>>Z>>^².è>*T&è„>Z>> h¾>>>hXN>4>v2>Š.<>&$>DJ &<>nŽ>&$:,>†>šÈ$^>^ÈD^j>vÈl^j>vÈ”>"Ȥ^>>>F&ÈÌ>*°R¨Î>Ô>"D>>>’>>>>*Ð>âÐ>R>b> @¶>¾>^>Xæ>>4>"$>.¸Ž>D~Ž &¸Œ>"L>âþ^f>.dF:(>"$Nrv>R(:d\>ˆfJ:>"$Nrvz^r>F>>J>„>ž2$>>>ª>0Rž8Î:èZ^^VVVV:à¤>> ŒR>Jr>J<>V*DjRb>Z> j*4 ¨<,jRn޾>JZ>øf:Dz®HÒ.4>â^>$>>>J> $2$fn>>>:<( <( <( <( <( <( <( D( l>J: ® <>J:È ®È <>J: ®& fN^>f>^>. þ~r>  D>V>f>.X Î^>>X p RVbbrr>>~6  –6  Ö6  ,À Ž>>Ìn^r>žv>"  Ð >>  Ø >*  ð -"/ØÐ$"$$vn$:$:$:$>$*>¼ $ $ $ 4 $ $ $ $>>>>-+>>>>>>>>>>>>>>>>>ä4>>>>>>\ŠN>’$> |l&$&4 D><:$¸>à.˜ dœ>Š,*, $|>6<:<6< <>>>>>>>>>>>>>>)'>>>>>>>>>>:¼<„4>ŠºNŽL œ $ $ d L $ Ä L"d,*8 T>>>>>>>:%#>>>>¼>>>>>>>>>d>>>>>>>>>>>>>„>>>>>>>>>>>>>>>>œ>>,>>>>>>>>>>>>>>>>>>>´ŠŽ$ $ $ $ $ $ $ $ ü Ô t ”>>>>>>>&!>>>>>¼4 D ,, D>\$>>* >¤2|>>>>621"3 È>>><>>>>>>>>>>>>>>>>Œ>>>>>>>>>>>>>>>>t>>>>>>>>>>>>>>>>>>>>>>>>>>>>Œ>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ˆ$>z*¨®>¨þ ¨D*$f$4F XT>" Ä>>>v`>²`æ`T.¨D à&4$(>>* :<^&X>><^>...4>Z&0¶0>$f>N>R>>j’>60ÄJNèDZ>®2$>ZR`ô>>²>>˜>r’V>R>°>"$Nr>j°>&TR>R> >"$Nr>F >&˜¼>>*˜Ì>>˜Ü>>˜ì> ˜ü>~>&˜2¨ >f ¨ >’> ¨ >Ê>>¨ ,jR>ª:˜ >z: ž> Þ6 ´>>V>6X ^NJ>h >", ˆ æz>>FRr>¨ $>6¨ ,>>¨ 4>.¨ <>¨ D>>:¨ 2L>>>¨ \ h :ô>Z>( ^N>v8 Ž>~8 $>"8 ,>"8 4>8 <> 8 D>>"8 L>&8 >>>>>>>>>>> ¼>>,>>>>>>>>>d,>>>>>>>>>d>>>>>>>>>>>>>>Œ>>>>>>>>>>>>>>>>>>>>>Ä4 $> D$ , $ DžŠNn>& T> D<<&D<<<<> |< L < <>>. >D> Ô>>>>>>>>>>>>>>>*15"7ø Ø>>>>>>>>>>>*`>ò>$ $>>>>>>>>>À>>¤À>¬NhÀ¼¸€"¸ˆ"¸2À.äN"À¸˜"¸˜"À.œ>>>>À¬À.¸ˆ"À>œ¸ˆ"À¸Ð>$&$f>>V>ÎJ>8>ânz>J86D^> ,>Fv>Z2<>>àZz>L>>" Zz>L>>`Zz>4>"$JJ>È>"$bzrÈ>dNRVVf^^>$.xVn*$. >FnZZ*$~>à~>$>>,V>z^z8>$8(R< 0LZz>>j>F>À r>,~>T~>H ~>0 J>^8 Ž>8 $>ÌJ>n( $( $( 4( € V>TVv>Fv>¸>>>€ > R>Z*€ >,>¸>>>:¨ b>Fú ¸ $>’ú è $~>¸>6 Z>¸>>>@ ö @ $~>¸>>@ ö @ $~>&¨ >¸t>R:40 € >>>¸Ø r>^>Fv>>>jv>F>¸ž^V^v>Fv:¸> N:TZ>F>Fv>F>"¸.¨ >€ >>>>"¸8 >F>"¸x rº € Î> ¸´R>¸>Äv>¸>ìfVN˜ 4>¸>>>¨ ^>>>¸>> À ~>>>~v>, Ø 4>Z Ž> $>¸Ð >nrrr2Ð ,> Ð 4>>Ð <>>Ð L>>>>r> –> Ö> $: ,: 4: <: D: L: &\> Ð ¼FvfJ>  >âVv>V  6D>Šb>>:ˆ >"Œ~>ˆ >Ð H>>>²JvfJ>p>âVv>Vp6D¦2X>"|~"X2H`H> ¬rjH>>>ÌrjH>"ìrjvj H&p:H˜>n>˜Ž>*˜Î>˜$> ˜,>Š2È.˜d>n>øŽ>*øÎ>ø$> ø,>Êj~2(.ø|>>>>>>>>b*p–*pÖ*p$&p,&p4&p<&pD&pL&pT&p\&pd&pl&pt&p|&p„&pŒ&p”&p¼>>>>>>>>Šnv.(4rjz(\rjz(ŒfVnf>Zjv>>Nf~> (ŒfVnf>Zjv>>Nf~> (`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(`jfjv>>N.(˜>>>>’v*˜>>Dr*˜>>.,r*˜>>\r*˜>>>>>*t>> ˜>>&„rjv6˜(r>&t¶>^2Èxd˜Z4’°J¨ ˆJ€lRhœÚ$Nr>^>Fšj>>r>–jv>F>Ê ˆ$z>š>Ð>>>F>.Ð>ªÐ<>zòZ>~f².TRj>Nþ:\>^>(âb>>Š>>(tf>,r2>>>>>>–v*à>>:,r*à>>:Dr*à>>:\r*à>>:tr*à>>>>Œrjv*à>>>>6´rjv*à>>>>>"Ü>>>>j°Î:4>fî"$6< D>>R>f^>j>2xŽ>x$>D˜à>è&à>*øš>–Î>T>>~>>Vfvú$¾úÀ$r>à>>ö $r^>"à> @ö@$>JR>>Ž>àø>Z2ø>º:ø>>>$v:ø>> ø(r2Dr2„V>^2Ž>$f>.>z2dbr>~2Tbr>~2ÔVjvz:4\V>švZ>&t ÀV>®Zz®ÈT$Vjjvj> >Vî Vj>>>š>°&$&°&4RØÎ>&dV>~v6°Ì> °Ür>°>>>>>>>>>>>>ì>>>f>N>>>>>>^>®V>J>>z>>>>v~&°6L>>>>&°°>>>>>>2>°>> ö $rj~>°>hö h$rR>>Š>*°>>¸r>>°>"Ðrjv>°ø6<ø°>>@^>RvjbvZjZ:°"˜^>RbvZv>f>°2àRvjzv>¢"$^Zzv6.°2`^>^vj>>>jbZjV>^z~Z>° >°2Ø>>°è>>>>vVîø$>^2°0>Z0Ž>0$R>N64`<>>R^>>šV>N64È<>>R^>>°0r>°&Hf*°&`>NJ>h>â>r~h6°ø>>>>Z>>>>>fnZ>°>>>(>>>°>> 8Fzvzjž`Î>NŽ €Î>b2˜Ž>˜$^> L ÀTV>8>"ôrj> 4 8 <>^2p Ž>>.p $^>$ ˜ ,Vf> 8>°8"~>vf6$~>4zj>€"Vjj~:$ "!š!š^^!"T 4€!$Z`!JNN< !J$ZbP!Œ>bvnZ>~RR^^Z^~:$&8",>Z^~f.L€"Tf²>b:>9";àà>>>>> \>jV8<>>2$^^j>>²>>>R>>®>>>f:À.,6¨Tj>>²>>>R>>²>>>f:.,6T>>$>>jp¾n.pD>>V°>¶>>J.°D~ðº ð$r>"ðd HD €4>4>>¾n>v^f>’f>>Ê>"àÐÈŽ>2”`D>>ªn>J>Fº.  ˆŽ>\*4>>ªn>R>>>>V  Ž>2\hD>>ªn>>^¨˜ Ž>D*,>Z>Îbj>øN> L&,>Zp>âff>>&p`N> \¸"<>Zð>Î>>&ðàN> <6>>>*ä>>,, <$"ä>D>D.T < < $Ä „*Œ l l „>>>>>>>*972="?¸>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> L*4$>>>>>>>>>°.h:° h> ° h °h>° h"°>>>>:h°:h ° ˜ð>>>$ZJn>>>â>":ð.$ZJn>>>â>":ð.$ZJn>>>â>":ðLð|v>2ØZ^:d èlR>Vö`$>J:Œ>4bf>Nr¦^>V>n^>$VbZZV>J¾>Šzbº^z>’zzº6¨$N^r^V>N>†^~~VV œ>"|>Ä °Ì*T>f>>Èž>>2ÈÎ>>È$>> È,>6È4>ÈTbòV>>>>>>>>>RRRR@ ,.@ 4>@ <.@ D.@ L>F@ \>@ d>@ l.@ t.@ |.@ „>F@ ”nR@ ¬.@ ´.@ ¼.@ Ä>>@ Ì>>@ Ô>>@ Ü>>Z@ ì.@ ô.@ ünRRRRRRRRRRRRRRRRRRRRRRRR@  .@  nRRRR@ @ >^*@ X J^>F>Z>vz>N®>N6Vj>N~~f:L ÀTÞ $>¸ 0 &è ^^¦f.Ø Ð Ž>L"|"4ZŽbnVb>†Z>RZrnZjVb>j²r>Fn>F>V¶bb>r>V>H šR^ŽVb>†z>NbVV>@ Œ>>ð V*d>¶2X$^>X<^>XT.Xdv*X|.XŒX´ZŽb^Jn>0>",r20>Hfz¦Z>>>>>b>p®>pî>p.$>p,&p*L>J>:¸®¸Fnzbbb>>>Z>¬ì>.„V~VV^fb>Z.¸Ž>¸Î>>¸$>¸,&¸"<>>>>>>>>>N ðŽ ðÎ ð$ð,ð4&ð<ðDðL>>>>ðTð\&ðd>>>>ðlðtð|ð„>>>>ðŒð”ðœð¤ð¬ð´ð¼ðÄ>>ðÌ>>ðÔ>>ðÜ>>ðäðìðôðüðððøððððð ð(ð0ð8ð@ðHðPðXð`ðhðpðxð€ðˆðð˜ð ð¨ð°ð¸ðÀðÈðÐðØðàðèðð>ðøðð >N>j¶>F>R","DhL&, °4.>>øø> XV>n:`Þ>n>:`,> `46`Drr>>`d6` X*”>>>>Æþ>^>>>>>>>>>V& ®& î& .$" ., .4" .< .D" .L" .T" .\ .d" .l" .t" .|" .„6 .Œ6 .”6 .œ6 .¤" .¬" .´" .¼" .Ä" Ì 2Ü>.V>N>N>N>brf> „ PŒn®àÎrNV>ô ü> >>>>>>>>>>>>>>>>>>>¼>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>L>ŠNŠ$ Ð"Ô :Ð t> >>>>>>=7>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ¼ >>>>>>>TDTœ>Š$ $ È$ $ œ<&D*D*D*$ l \ , <, $ ”>"È *@>>>2>d>|>¼>>X>2Ø>> >>>>"ø >>>>>>>>>>>>>> 52A"CÀð>>>>>>>>>>>>>>>> Ô®V^^^^^^^^VØNfffffff><>nPŽ*PÎ*P$&P,&P4&P<&PD&PL&Pt$*$Z6$*46,FVV^bº>,$2$2$2$$:$Z> $>>¼ >>>>>>>>>lz~~~~~~~~þ” t $$, $Š$ l $$$$ $$,>>>>>>>> AE"G Ð>>>|Nr:$Nr:$>$> $> $> \>Z2`æ>>`H>VR><.H&\&HÄ>Z2æ>>È>Z>>>>V>>>>R~>V>ZR><.ð&\&ð„>6$p$p^p$p^p,pTb>>®>$>:$z–>2<>f PžPîP$PL>>>>>6$˜>>&$˜>>&$˜>>&$˜>2,˜T>F>¢:DF>>"$>^~>6äh>r&hŽ>>hþ>hL> h$:h4:h,>hD>>>h>"T>h\>h.d:h>>>>>"T>h\>h>>l> h> |>>>>>>hàV>>œV>>>Fˆ>’ˆ&$&ˆ"4>>&`F>`>âVRf>>"l. >f^º>>.D^rz>>>>|N>>b>>>Z>f>>>>>fZr.8–>28,VV¶>>f>>>>>>*¨2$ ¸>>Z>>°>:Ør>¢àÒ>>2(>>&>>8 >>>>22>>>2H r$ ` >>>~>>X >x>~>"D €L>>.2ØrV>jz^>>>>> nzz>>8RbZv^z>>>>`:À ¸ ° >$ È ¨ <~~RN>>>F>>>F>>>>>>®$^b>>N>>>J>>>dn>˜ ¶>>b>˜ ,z>>>Z>>>^>˜ € ^>Z>.d>>b>&$>>rJ>r>>* Ò $ÌV>F>&$>>>È >Z2È ¶È ö6È ` >2D>>>` ¬>ò æ $>nV>r>>>>  2` T>  2` *D*` 6\N:<>:` p >>>>f>ò>>Þ>>>>h >2$>Î>â>>>>>>r¸ –¸ Ö¸ ,>vf.à ¸ ,>vf.à ¸ ,>vf.à ¸ ,>vf.à ¸ ,>vf.à ¸ ,>vf.à ¸ L>2¸ T>2¸ d>n ú>>>>>: .,>>>* ¸ œ>R¸ 6´¸ Ü>>>$>>>¢>br>^6° ><&°  >„>>r>>>>>>>>’* >>>>>$>>>¢>br>^6° ><&°  >*„>>r>>>>>>>>’* >>>>>"$>>>¢>br>^6° ><&°  >*„>>r>>>>>>>>’* >>¬>>6 Ø>Fr>>„>>^> `N>>>n>hŽ>hÎ>h$>*h,>>h<>>>>&h>>L>F>>h>"dR>>>$ Ð>h2”>>>>>>h> ¬^>>RV>>>>–>>>h2Ü>>hä>>hì>&hô>hh>J>>h€>Z2€â>>>>>€*h°>>^>2°–>&°Ö>>>°$>>°,&°h2ð>>*h8^>>>z>>>>>b>>F>>b>>>>^>>h>6h>j>>>N>>b>>>>hœ>>h x",>²>>> >$>F>> &<& \N>¦bj>z>>r>>>>>R>Z>6\&è˜>T ˜6\>| ð„<>Z>>>"¨>>>>Ž>¨>>Ò>"¨>,>>>V>r>¨RˆÎ>>\f^.„f>>>>>J>>Ê>>6D>Z2ðâ>>>&ð ,>(ÚJŠPŠ8v>$ €,¶¨Ò>jÀ®:À $R> <èD>>>"I"K¸&˜>>>>>>>>>>>>L>ò>z>>*øž>*øÞ>>ø$"ø,>ø4ø\:$> $ú>$î>>$$"$.$>$f€ÖJ>˜>¢:˜ö>J>V>Š€„>Z>:âJ>>â>ðN>2\ª>P$>6PT>Z>: âJ>R>>¸>"$¸> N>>dª>ø$>6øT>Z>:HâJ>>:`>â`>H8N>>\ª>˜$>6˜T>Z> èâJ>>â>èØN>&\>>J^>>$>¶h^hîh$hLfN>6$â>&ÀD>ÀL6ÀT>>À\>À„>vrf>>Š> $>r>&ˆ>Š"ˆ<>î4Ø4.Àt>²0,>@Š>&04>0<60D>>0L>0Ì>d>,> ~N>b>°>¢> °>Î>°:$>°>,>&°>"4>&°>>><~J>6ð>Š6ð6°>.\bJ> >Š6 6°>:|bJ>0 >Š60 6°>>>>.œ>JJ>f>P >Ê6P 6°>>>Ä~J>6x >Š6x 6°>"ì> °¸ > ð >ð >Š>Z>"ð .,>V>ð À >:”>>>>R>J>’>>n p >>²2p >>>ê>p >$>.p 4Zz>V>b` .t&` .À DF: >"$>bfv >À >¦*À >"$>À >4>>&ôN>>T6À ` >v>.` ,>*` Î>.` Ž>.` $>*` <>^>R>>` \>r>>b À ¦6À æ>*À ,>>` œ>` ¼>>>>"D>>>>n X >¢ X >âX >2$X L>&¨.  >F>>>>>>>>>>>4Z>>>fæ&,"$>^2à >$> ,"$>^2à >L>.$>^2à >”>^*p >^*p >^ª>^>^.à ¨ 4Z>>>fæ&,"$>^2à >$> ,"$>^2à >L>.$>^2à >”>^*p >^*p >^ª>^>^.à ¨ 4Z>>>fæ&,"$>^2à >$> ,"$>^2à >L>.$>^2à >”>^*p >^*p >^ª>^>^.à ¨ 4Z>>>fæ&,"$>^2à >$> ,"$>^2à >L>.$>^2à >”>^*p >^*p >^ª>^>^.à ¨ 4Z>>>fæ&,"$>^2à >$> ,"$>^2à >L>.$>^2à >”>^*p >^*p >^ª>^>^.à ¨ Ø >Z>^¨ Ø >Z>^¨ Ø >Z>^¨ Ø >Z>^¨ Ø >Z>^¨ Ø >Z>^¨ >Z>^¨ >Z>^¨ X>^¨ X>^¨ X>^¨ X>^¨ X>^¨ X>^¨ X>^¨ X>^¨ p>®>bp:,>ž>>>>>V>>v>b&˜&4&˜p.t>J>^>^&p¨ >J>^>^>~>>:¨ @>¨ h>>V>>¦>N>^"p4>J>^"pT>Zpl>>JØ–Ø$>ZØp¬&p >>R:@>ž>r>>F:@4>@D>J>>^Vö˜$>@Hj>j>>>"à>nn>>è– è $>V^V>j>>n>J 0Þâ> H$:0 L>^*xŽ>&x $>^>>v>J>>,RRVb^rVZ>>>>>>>>>>>>>>>>®ttttttttttt$>T>d>$>4>D>$>„:œ¢°$°4¾>V>r ø>’ø>Ê> ø¤V>X>>VbVbz>R¢®˜Îrj^>f>F>>J>N>†Z>8N~N^>.œX¤ª ø&|Z>br>&Ð.h>>>>Š>>>>>’>¶~>ˆ6,>>>>>’> °>:$>°ˆx>:|>xŒ>>h>6¬>*h*¼>>h>Ì>j>>:0®>0h&ô&hˆ˜lbvtj>Rn>j>$V>^ÈŽ>&È $>Z2œ.x>š>J>š>x>4^x>&L>F>6xlV>JZr>Z²N>.\>>2d>z>~ö>~®>>>æ(V>>>¢>0>$>024^r:$>p*,Zj>>0°n>šJ>rÈ>"$>È2¸&L>f>^¸ l>.0>>>>>>>>>>>>>œ>>>R>0>>>.´>>n>0>>> Ì>>>>> 0>:Ü>>>0>>>:ìj>>V>0>>&8n>>z>F>nR>>p>P.€b>b>J>"P&00nr>Z>N>^>¶> 0>>xn>Zr>Z>>0>¨n>Zrr>^>>:0>>>J^>020>>:0`>>0@n>b>^>0>&h> 0>"xj>&0>~>>*02¨>>>>>nJ>f>v>>Z:°>"<>>R^*$ ø<2(Ò>J>>f.°>&´>J`Ž>`$>,€4>`d><ÀD>` ´>>j>Nz>60@>>>~>^>608>>>j>j>^H¦*H $0D>.t> 4 à<ªÎ>"0pn>~>~>f>>0 n>z>F>60Èn>À<><>>0Œ>:0àn>Zr>Z>20ˆ>Z*ˆŽ>6ˆ $r4>X^>>’^j> D>j*À>®"À> $>"À 4>V>>`>>¬>>`>¼Z*`ô>n>FJ:`>âfv>J`:p.XV>>^J>rh>"$> h64>V2€ : >Ž>>Z>Z2 >>4fj>N>6 >"\f~>v>V>º2 @V>"d>6Ø>>¨T ¸>v¸$¸,¸Ž¸Î$>>¸¨>2d>>Z6¨> |>>>N>.¨”>>>f>f>ž>>"T XH&t&H „>&¨2è>Z&èÚ>>^>>è"4>r>>n>> –> >>Ê> 2,Zz~>>>V>>>>>`>>Š`>Ò>>>>.`",>>>>Z~>6 .¨°>>Vj>Z>¨Ø>>Z>>J>¨ø>Jb>> ¤  ¬f>¨"È >”>"!b>>fVZªvv>¶>FÖ>ð jR^f>> l !t^>N>b!Îj>N:! Zjú>>>>ž>v~N>ž* "&$& "ø!> dø!.tø!è b>>"ü ð ð!:”~6D>Ú>¨"Z>>>>>^VžÀ"ΞØ"Î>4>šJ>>0#>â>0#: #"DF^>`#þ`#> ##&#Ž>>|.%Zn>&°#F>°#>"$>RJ>>Ø#>âf"Ø#><LJ:H$ 8$Òު΀$Z$˜$Fp$ $RV$¬~r>N^~>>ªnî>%*$Z>"è$> T&è$ dzb>J°#:@&>>Ê>.À% °%JΨ% ˜%\6$&Ú&ø%Fè% %,Š%"¬æÞ>>>V>>Fn>>*p&>>$>>z>j>M"O È>>>>>>>>>>>>>>>\>>>>>>>>>>>>|>>>>>>>>>>>>>>>>>>>>>>>>*¼>>>>>>>>.<>>>>>>> <>>>>>>D>>>>>>®>>>>>>>>>>>>>>>>2\>>>>>>.4>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ì>v*€$> €Î6€Ž€,> €4€<€D>6€lfè–>è<>>JRRRRRRRRRRR Œ>>>NRRRRRRRRRRÒRN¨„&¨Œ&¨”¨œ2¨¤"¨>>>¼>>>>>>>>\>>>>>>>>>>>>|>>>>>>>>>>>>>>>>>>>>¼>>>><>>>><>>>4 >>>’>>>>>>>>\>>>4>>>>>>>>>>>>>>>>>>>>¼ Š>l < Œ>>>MKQ"S >>>&TJò.4zN~Ž*$&$&$>>V@>Ž>@þ*@D&$>^>* ¾>. <>^>*ؾ>.Ø\>T>v>Ž*Î>$>22,>>>>&4><>D6l>fx¦xæxD>j¸.$¸.4¸î¸®¸.,¸<&¸d>>f ® >Æ $L~`º `Ö `z ž Þ $>Z2Ž>"<>DZ’>j>.X>Z2X¢R>2D>>Xœ>>Ø>^2Øâ>j>2ØLFnz" >"4>& :\>*4"$>ZÈÎ>Fà¦6àÈ„>>>>>4v>> H>>>$>>>H>>¶>>H>"L> H >ž2 úR>:l> Ü>¦>ø>>$&ø>>>>"T>N>>&ø>>>Œ>N>>ø>>6¤>N>>>"ø>>>&¼>N>>>> ø>>>>l>Nb>>>>ø>>>6D>>>ø>>>4>>ø>>>>>>>>>.Ô>N>>>>>>ø>>>>>>>>ì>N>>F>>>>>>>>>&ø>>>>>>> >N>>>>>>>ø>>>> >N>>6ø>:0 >øÐ>ž2ÐúR>>>&H >Ðp >š2p >$>R>V>>>&p \>ª*È >>$b>f>–*È >6T&È >>6\^z>R>V>F>ª>>> È >>¤>ºh >:$>J>V>>h >2D>J>V>>N>>Ž>>:h .|&h È &ø &È @ >( jb>>>R>( *$ ( &,>J>N>^` >ž2` â>` $>>>>>>>>>>>>>>>>>>>>>>> >>>4R–$ŠL $ $> D $>> <><:l6D d L D> D $ < $ „ L\ $Š"$ \*´>>h >2\>>> >>>>>>>>>>>>>>>>QK>U"W` Ø>>>>:l>Z@Ž@<>>&$^^j>>ž>J>n>>š>>v:Ð&,6°\j>>ž>J>n>>ž>>v:0&,6d>>,>Z2˜>Ž˜>ê>:˜D>Z&Ø>ŽØ>ê>ØD>N>šæ>"D>š>X6$j^R^>²>>X|~6к6Ð>>>>&$>>j>>n6Ð>2<&Ðd>N0>š0&$>*0L>š.x6$j^n^>n>²>n>>x¼6(D `D ˜4jÈ–ÈD>Zör>>øN>D*,>Zhör>R>>>:hXN>2\°"D>Nð>šð>>>>6$Z^¾>j>>âb¾>j>>ð>2œ&ðà ØŽ>2Ì2¨D>N è>š è>>"$>>²>>> $>>.4&è>l&èØ ÐŽ>2œ2pD>N °>š°>>"$>>²>>Ð> $>>Ð.4&а>l&°  ˜Ž>2œ28 <>Zp öbZ> p ` N> L&>>6Ü>>,< <$">*D6D2D>*|>"d6L>*¬:< < < < d*„6ü6Ì6Ì>>>>>>>>>"UKY"[èÈ>>>>> ,>ò>n:Ž.L:$>>>>>>>>>>>>>>>F pV pV pV pV pV pV pV p– p– pÖ pÖ pÖ pÖ pÖ pÖ pÖ pÖ pÖ pÖ p$p$p,p,p4p4p4p<p<p<p<pDplZ^ZNZ¢$^>br~>>8>,>>8T^>b>>"¶>"<>Z>Èâ^>>v>> ÈT>Z>â^>>>>&L>>^`V`V`V`ž`<:$$j2Ø>>V2Ø>>R6Ø>>>Š2Ø>>’Ø>>>Ò Ø>D>>>N2>>’>>>N>(>>>Š*(>>>>>>>>>>4.>>4.>>4.>><>>>>>>>>>D.>>>>>>D.>>L>>>>b2`>>R>>&`¾>>`:>>>>>>l.>>l.>>>>>>l.>>l.>>l.>>t>>&>>>>>> |.>>>>>>>|:>>|V>:>>>>>>>>>>2Œ.>>”>&>>>>>>œ.>>>>>œ.>>¤>>>J>.¸>>>Š*¸>>>>>>&Ä.>>>>>>>>Ä.>>Ì>>>J>>:à>>>Š*à>>>>>>>"ì.>>>>>ì.>>ô>>>J>>:>>>Š*>>2(.>>0>X>>>>J2X>>’>>>N>6h>>>Š*h>X>>>><~r.˜>>N>˜>X>>>>>.\> X>>d&X>>>>&t>X>>>|.X>>>>:„>*X>> ¨Z>>f>>2°>¢>>*°ö>>> °>>>>Z2>>RZ>>>>>>>Æ2>>$>>>J>> >>>Š* >>>>"L>>>>>^>>H>>>ª.H>>Ò>>>N>>`>>>Š*`>H>>>>>Œ*>>”2>œ*>>œN>&Dô>>>>N2>>RZ>>ª>>.(®>>.(>Ò>>.(6$&(>D>>l>>>>>Z>€>>>>>¾> €>>’€>><>>>>>š>>>>b.È>>Z2È>>R>"È>’>:È>>–2È>>’>È>¸> 4.¸>><¸>d>>>>>>>>r.>>Z2>>R>>>>>¶2>>’î >D>>>>R X>>>>>>>º2X>>š2X>>’>X>>2>V2>>R6>>>Š2>>’î >D>>>>>Z>Ð>>>>¦2Ð>>’>Ð>>>Ú Ð>D>>>N. >>R6 >>>>¦2 >>’>* >>>ò6 >D>>>>Z2P >>R2P >’ P ><>>>>>jˆ >Šˆ ><>>>>>ZÀ ¾ À >>V2ø >>R6ø ž ø ><>>>N.0 >>R0 ® 0 ><>>>>>š>&h >>>>>>>þ2h >>>>>>>$>>h >>>>>>>>>*4>h >>>>><.h >><h <:h >><h >>&D>:h >>:lj.Ð >>NÐ F>Ð >>R>.Ð >64>>>N: >>R ® ><>>>N.8 >>RZ> 8 >>>>>6$>68 >>>>>>>>,.8 >>>>>>>4>>*8 >>.D8 >l>>>>>>>b2  >>R6  >ª   ><>>>>>>>^6Ø >>>>>’2Ø >>>>ºØ >Ú Ø >D>>>>>>>f2 >>R6 >>*4>>>N.H >>RH ® H ><>>>†r: >>N> ®2 >>Ž> >€ >>>>4*€ >>4>€ ><&€ >d>>>F&à >>>>>¶:à >>’à >>>ú:à >>Òà >>>>>>>>>$*à >>$à $6à >>$V>6à >>>&T>>>F&0 >>>’20 >>’0 >>>>>î.0 >>Ú20 >>Ò>>0 >>D>>>N2p >>Rp ¶2p >>Žp >>V2¨ >>Z2¨ >>>>>F.¨ >>Z.¨ >>’>>>>>J:¨ >$¨ >L>>>N2ð >>Z2ð >>R6ð ¶ ð >>NZ>>>>>>>>>>Ž>>8>>>>>>Æ28>>ÒZ>>>>>&8>,*8>>4>Z2hŽ>6h8>(>Œ>>>>J2°>>>>º>°>>>>>>>>>>>î.°>>Ú2°>>>>:$>>.°>>>>>>>>,> °>>,*°,:°>>,V>:°>>>>>>2D2°>>>>T2°>>>>>>>>6d>>°>>>>&l.°>>>>:t>°>>>:|.°>>>>:„>&°>> ¬>>>>>>>f>X>>R>>X>>Ž*X><>>>>>šr2 >>V. >>R>>" ž>> :> 4*>>4.>>4> <>d>>>>>>>f2ð>>R6ð>>>>>¢ ð>.<>>>N.(>>R(® (>>V2`>>R6`ž `><>>>N.˜>>R˜® ˜>>V2Ð>>R6О Ð><>>>N.>>R® ><>>>>>>>>r.@>>Z2@>>R>@>>>>¶2@>>’@î @>Dj.€>>N>€–€><>>>>^.¸>>R¸¾ ¸>Ln>>’®&$Zð&èŽ>TFv>H>"$>.H>]"_øÈ>>>>>>>D>ò>b>NR $r T>,>4.$Z>>>>>$>:$>&$>t.$.$jnnnn~~nnnnn2,>R>–^^Z>>>>Vb>>Î^^Z>>>>Vb>¶>Z>Z>Z>Z>Z>Z>>Ž>N^>Z>ö^^>j>>’nn.L>¦>r2Ž>>"a"c(È>>>>>>>> L>ò>j>>(¾>NRR(4r(d>,>4.$>:$>&$Z>>>>>d.$.$î>ænnnnnnnnnn24Z>^>¢>F>F>F>F¢^^Z>>>>Vb>>Î^^Z>>>>Vb>ö^^>j>>’>V>V>F>Æ>r2ÀŽ>ÀDJ>n>n&$vâzâzâzâzâ>b>V>NªnN>næv>r>n&>>>>>>>>>>>>>>>>>>>>>>>>>>>>>¼>>>>>>L>Šd ,Z^>>>>>>>>>.°ŽÒ$$$*,JŽfff¦$$$>ŠN>F>F>F>F>F>F>F>F>F>F>Fnnnn>,~>F>F>F>F>D>D>4>b>f>F>>>>>>>>>>¦.øJn>F>>Rø4J>$>$>$>$>$>4~n>>>>R((Jnn>>R(>>>>>>>:a_>>>>>>>>>>>>>>>>>>>>>>>>>>>>¼>>>>>D>ŠT ,Z^>>>>>>>>>˜ŽÒ$",$$,JNNNZަ$ $J>F>F>F>F>F>V>F>F>F>F>F>F>Fnn>b~>F>F>D>D~>F>F>F>F>F>F>4>4~>F>F>Rnnnnnnn>>>>>>>>>>>>>>>R.ø>>>>>>>>][>>>>>>>>>>>>>>>>>>>>>>>>>>>¼>>,>Š<Š$ l\>>"\>D:T6L <$ $>>>>>>>>>>>>>D>>>6P>>6¬>>*>l><>*d>D><>D>D>D><.<.<><><>*l>4><>*l><>D>4><>*d>T>D><>>L><>6Œ>>6¬><>*d><><><><><><>D:<:<>>>>>>>>>>>>>>>>>>>>>>>>>>>"YK>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>¼ \t>>>>>>L>Š>\$ $ $ª’–$ $ $ $ $*|&¤*¬*¤Œ>L6”&L< t>> t>>¸ >"X >Ä>>>>< L2`*Ü>"¤2ü0>>>ü>>>>P>>ô>>:à >> " l¤>€%&¸&>>>>>>>>>>>>>>>>>>> IG>6e"gˆÐ>>>>>>4>ò>R:Ž&Î>D:$>>>>>>>>>>>>>>>~ xV xV xV xV xV xV xV xV xV xV xV x– x– xÖ xÖ x$x$x$x$x$x$x,x,x4x4x<x<x<xDxDxDxDxLxt$^>b>N~>>&>,>>"\j2h>>V2h>>R6h>>>Š2h>>’h>>>Ò h>ˆ>>>>b2ˆ>>R>>:ˆ>>>¢ˆæ>>*ˆ>¨>>>>>>–>>>>Z>"¸¶>¸:¨>>>>&<>¨>>>D.¨>>L>>>J>"ð>>>Š>ð>¨>>>l.¨>>t>>>J>6>>>Š>>¨>>>>*”:¨>>”V>6¨>>>>>¤.¨>>¤.¨>>¬>>"¨>>>>>´.¨>>>>>>´.¨>>¼>>¨>>>>>>Ä.¨>>>>>Ä.¨>>Ĩ>>&Ì>>¨>>>>>>Ô.¨>>Ô.¨>>ÔN>><¨>>>>>>>À.¨>>È>>>R2È>>R>>È>>>’>È>¨>>>>>ðn2ð>>N>>ð>>¶>ð>¨>>>>*n2>>N>>>>¶>>¨>>>>*@:¨>>>>2H.¨>>>>>>>>>>2H.¨>>P>>"¨>>>>>>>X.¨>>`>>>¨>6ˆ>>>>>>>ž>>ˆ>>>>Ö2ˆ>>$>>>J>>¨>>>Š>¨>ˆ>>>D*ˆ>>L>>>J>>Ð>>>Š>Ð>ˆ>>>>l*ˆ>>t2ˆ6„ˆ>¬>>>>>š>>>V.@>>Z2@>>R>"@>>>>®2@>>’>>@>Ê>:@>>Ö2@>>Ò>@>0> <.0>>D0>lj.˜>>V2˜>>R6˜>>>Š2˜>>’˜î ˜>D>>>>>>>b.Ø>>Z2Ø>>R>Ø>>>>ž2Ø>>’Øî Ø>Dj.>>>>~.>>Z2>>R>6>>>>>>>–.>>š2>>’Z>^z>&0>:<>d>>>>>b2x>>R6x>>>²2x>>’xî x>Dj.¸>>V2¸>>R6¸ž ¸><>>>N.ð>>Rð® ð><>>>>>š>>>>b.8>>Z>8>>R>>8>¢>8>>Ž>68>(>6T>>>N:x>>Rx®x>Ln>>’È®È&$ZȰ&¨Ž>TFv> >"$>.>LZr>^*i"k .,^^bnj–>&$Z’b>> ,>>R ÈŽ ÈÎ È$È,.È4.È<*ÈD*ÈL*ÈT*È\.È„>>>>>V HŽ HÎ H$H,H4H<HDHLHTH\HdHlHtH|H„HŒH”HœH¤H¬H´H¼HÄHÌHÔHÜHäHìHôHüHHHPHX.H€Z>4^b*¨^.$ °,b> $r’:^b*8^^>Vf>J²x>>>>ž2x$>&x4>&xD2xTb>xlb>:x„b> xœ6,>&xÔbf6xôbf6xˆbf>x¨bb>xÈ>R> xà^ff>xx> x(x8> xHxXbf*xx>"xˆ>"x˜.x¨>x¸>xÈ>J> xàb>:xø.x&8Z 0$>^*>>>>>>>>>>>>>>>>>>>:¼ 4’Ž\> L„ x>>,>\6<>>" >>>>>2ig"m"oàØ>¢òJn>>N*>’2> $>n20â>> 0"tpRh&>"œ:Ì"$>>>Š>>è>$èH>>>F>>>>ê¶:d6„>6T>¶>>>N>&¸>’¸ $>¨D>^>.¨\>^>¨ÀÊn>D>>>>>>>>>>>>Ž>F> ,j> Dj>" \j~>>b>>b2–2Ö2$.4> ¼>> Ì>* Üj>> ô>r"¢>>> 0 X @ê"@* h x ˆ>>>>N>>ˆ>>¶>>>ˆ>òˆ ¸j6 Ðj6 è>N>> >>>F>>>> >>>F>>>> 0 @ ` Pª"P* pj6 ˆRVV>"| „>^" Ž>>  H>^& &`> ˆZ>>f&>Š V>>>>>> H>>>64>>>> È^VVV>>>ž>20Z>0Z>0Z>øTZ>ølZ>ø„Z>0Z>0Z>øè´Z>*èÌZ>>èäZn>>èèZ>>> èZ>>>"èZº &è>>@Z>>>"è"XZ>>>2è2pZ>>>>>>>&è2ˆZr>>>*è¨Z>V>>è2ÈZr>>>*èèZ>>>>&èZ>>>>¦&è(Z>>>"è@Z>2èXZ>è2pZ>R>>>>>>>6èf>~j>®N>>>v>2$*>q"s ¸>>>>>>>><>"\>Î>Ò^^JN^Z>r®>RæRR>>r2(RVVÚÚl*|RJj>¦bn24f¸–¸Vv>XN6X<>Vv>N6v& n& ¦ ¶^, 4&TŒ>xZ~>€¦€d>>¸>:,>>Nj*èž>>*è&¸Î6¸Ž>>¸N>¸trf& >>>>>>>>>>¼>>>><>Š$ :$ t < < 4<< < | D> t>>>>>>qo>>>>>>>>>>>>>>>>>>>>>>>>:¼ >Š–Ä>&€D> à>>>mg>>>>>>>>>>>>>>>>>>>>>> ¼ >>>4>ŠD $ t $>>>>:d>D>>*€>6¬>*l>D>D>d>D><><> T:<*¤>>>>>>>>eG>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>´ >>,L 4 4 $ $ $ $²º„ ¬> T< $ <> L T„>>¤LŠ>>>>>>˜ >>¤>D>*œ.L>6` >>ˆ >6Ô>>>>>>:ü> œ>>>>>>>>>>>>>>>2E2u"wX8>>R8¶8>Î>8D>>Rxf x®x<>J>>V2¸Ž¸T64„Z>44$.$>>>>>Äz~~~~þ4 D < DŠ4 4öÖz€:4 ,¶$¶$ $>>>>>>>u"y"{8Ð>>>>>„z~~~~~~> ,>$$&$$>*$>>:$>*$$:$:$Zf>V>R^>~>L>R>N>@^r^*8,>:,V^*>>>>>¼ >>>>>D4 l $ $ $ $$ $$ $ $ $>T>>>>>>>y"}" ¸>>>>>&\ZN^Z^Zf>Nv²>4*$*,z2àŽ> àÞ>&àØ4ØT>>>>¼>>>4$Œ $ $ T>>"}""ƒˆ¸>>>>>>4*,Z>V^Ž Î&<îZ>4"HRb^>RrržxÎJfrr>>>>b>’&¸$~rr2¸L~rr>>>J2¸&>"¼~^Z^2>>>>>>>>> ¼>>>4>ŠLˆ>6>>>>>>>>>>>>>>>>>>>>>>>>>>2¼ D L \ d \>ŠJN>v>FVRjV^T>n>R>f>f>R>>>¾>pÜ>\>J>f¨Ž>¨$>j*D"ÐL>bÎ^ž8ÎZf>^:p>>>>>€2p>ˆ2p>2p>˜2p> 2p>¨2p6°6p>>>newrethrowloaderloadprimsmakessetsgetsblitssubsfind@make@empty@consstringasizearrayamakeablitthrowasub@compare@print_unionnargsobjfieldsfieldobjgetinvalid_argintfloatprintgetposcacheNoneSomeNeko_errorInvalid_argumentAssert_failureErrorStream_errorNot_foundExit@print_record@aget@aset@pconsstream_tokenstream_posstream_junkstreamsprintfsndprintfordnstringnprintnekominmaxmagicignorefsterrorcomparechrassertsubsortsetmapmakelistlengthiteriiterinitindexcreateblitappendadd@rmaketlsplitrev_recrevphysnthnonememiter2hdfoldfindfilterexistsconcatchopassocallresetadd_subadd_charssizeuppercaseunserializeunescapeserializelowercaselist_depencyis_printableescape_charescapeOverflowEofClosedBlockedwrite_ui24write_ui16write_stringwrite_i8write_i32write_i16write_filewrite_charwrite_bytewritestdoutstdinstderrread_ui24read_ui16read_stringread_lineread_i32read_i16read_fileread_charread_byteread_bufread_allreadoutputinputflushfile_write_charfile_writefile_stdoutfile_stdinfile_stderrfile_read_charfile_readfile_outputfile_openfile_inputfile_flushfile_contentsfile_closecreate_outcreate_inclose_outclose_inhkeyhnewhcounthgethmemhaddhremovehsethiterreplaceremovehashEmptyMatchStarPlusNextChoiceInvalidRegexptransitionsstarsingleplusparseoptnodesnodenextmax_codemake_transmake_tablesis_emptyinvalidgroupescapeddeterminizecunioncintercemptycdiffccomplementcalladd_nodesadd_nodeInvalid_ruletokensourcepunionnull_poslineinc_lineemptydatacurrentcurposcharbuildTrueFalseNullThisIntFloatStringBuiltinIdentVarWhileDoIfElseFunctionReturnBreakContinueDefaultTryCatchSwitchSemicolonDotCommaArrowBraceOpenBraceCloseParentOpenParentCloseBracketOpenBracketCloseConstKeywordBinopCommentCommentLineNormalWhileDoWhileEConstEBlockEParenthesisEFieldECallEArrayEVarsEWhileEIfETryEFunctionEBinopEReturnEBreakEContinueENextEObjectELabelESwitchvar_argss_tokens_keywords_constantmk_stringmk_intmk_identmk_call1mk_call0mk_callmk_builtinmk_binopto_stringprint_listprint_astnewlinelevel_exprlevelMutableImmutableTAbstractTMonoTPolyTRecordTUnionTTupleTLinkTFunTNamedTVoidTIntTBoolTFloatTStringTCharTIdentTConstrTModuleMRootMFailureMHandleMExecuteMConstantsMFieldMTupleMTokenMRecordFieldMJunkMSwitchMBindMWhenMNextTConstTBlockTParenthesisTCallTFieldTArrayTVarTIfTFunctionTBinopTTupleDeclTTypeDeclTMutTRecordDeclTListDeclTUnopTMatchTTryTTupleGetTErrorDeclTWhiletlinkst_voidt_stringt_polymorpht_polyt_monot_intt_floatt_errort_chart_boolt_abstracts_types_mutables_funs_contextpolymorphizepoly_idmk_unionmk_tupmk_recordmk_funmkis_intgenidgeneratorfile_nameetypeduplicateabstractidivNoderemove_min_bindingmin_bindingmergeheightbalAccNullAccTrueAccFalseAccThisAccIntAccStackAccGlobalAccEnvAccFieldAccArrayAccIndexAccBuiltinSetStackSetGlobalSetEnvSetFieldSetArraySetIndexSetThisPushPopCallObjCallJumpJumpIfJumpIfNotTrapEndTrapRetMakeEnvMakeArrayBoolIsNullIsNotNullAddSubMultDivModShlShrUShrOrAndXorEqNeqGtGteLtLteNotTypeOfCompareHashNewJumpTableApplyAccStack0AccStack1AccIndex0AccIndex1PhysCompareTailCallLoopGlobalVarGlobalFunctionGlobalStringGlobalFloatGlobalDebugGlobalVersionInvalid_filewrite_debug_infostrap_stack_deltaread_debug_infosop_paraminullhash_fielddumpcode_tablesXEnvXStackXGlobalXFieldXIndexXArrayXThiswrite_optrapstack_deltaset_posscan_labelssave_breaksprocess_continuesprocess_breaksmake_arrayjmpgotoglobalget_cases_intserror_msgcompile_functioncompile_constantcompile_builtincompile_binopcompile_access_setcompile_access_getcompile_accesscompilecjmpcheck_stackcheck_breakspathVNullVIntVFloatVBoolVStringVObjectVAbstractVFunctionVArrayvalueneko_valuemodule_set_globalmodule_read_pathmodule_readmodule_namemodule_loadermodule_globals_countmodule_get_globalmodule_exportsmodule_executemodule_code_sizeloader_pathasetaget__list_depapplyCharConstrModuleTypeThenWhenExceptionQuoteVerticalStreamOpenStreamCloseETypeEPolyETupleEArrowEAbstractEAliasERecordEUnionATypedANamedATupleSPatternSExprSMagicExprPIdentPConstPTuplePRecordPConstrPAliasPTypedPStreamEVarEUnopETypeAnnotETupleDeclETypeDeclEErrorDeclERecordDeclEMatchETupleGetEApplys_pathTotalPartialDubioustotalt_conststream_patternstart_by_a_variablesplit_matchingpartialmswitchmake_token_matchmake_record_matchmake_construct_matchmake_constant_matchlines_of_matchingjunkhave_whenhandlefully_matched_reffully_matchedflattenfailureexecewhenerror_refdivide_matchingconquer_matchingconquer_divided_matchingcondbindalways_addadd_to_matchadd_to_divisionunionremove_min_eltmin_eltjoininterdiffadd_loopInvalid_characterUnterminated_stringUnclosed_commentUnclosed_nxmlInvalid_escaped_characterInvalid_escapestrnxmlmk_floatkeywordsidentexprestringenxmlecommentcommentbinopspacesnumbersnumbermodidentUnexpectedUnclosedwhen_clausevarsunion_declarationunclosedtype_path_nexttype_path_modtype_path_list_nexttype_path_listtype_pathtype_opttype_declarationtype_decl_plist_nexttype_decl_plisttype_decl_parametersstream_nextstream_liststream_ident_listrecord_fieldsrecord_declarationprogramprioritypatterns_beginpatternspattern_tuple_nextpattern_tuplepattern_recordpattern_optpattern_nextpattern_mod_pathpattern_list_nextpattern_listpattern_declpatternparameters_nextparameters_decl_nextparameters_declparametersmake_unopmake_list_patmake_listmake_binopis_unopident_optfunction_recexpr_shortexpr_nextexpr_constr2expr_constrcan_swapblock1blockCannot_unifyHave_no_fieldStackUnknown_fieldModule_not_loadedCustomNIntNFloatNStringNNanverboseunify_stackunifytype_unoptype_typetype_patterntype_matchtype_functionstype_formattype_exprtype_constanttype_blocktype_binoptype_argsave_localss_ttyperestore_localsregister_functionpropagateopen_filemodule_infosmoduleload_module_refload_modulelinkis_tupleis_recursiveis_aliasget_typeget_recordget_moduleget_identget_constrerror_msg_loopcontextaddableadd_localparse_switchparse_stringparse_opparse_listparse_from_stringparse_fieldparse_expr_optparse_exprparse_constantheaderdocstackcdatapcdataxmldonePCDataCDataDocumentnode_textnode_nameis_pcdatais_nodeis_cdatafirstNodeattrib__listto_xml_recto_xmlparse_xmlparse_posInvalid_nxmlvariables_nextvariablesswitch_casesparameter_namesobject_fieldsNativeStructuralrecord_indexno_labelis_funimportgenerategen_variablegen_type_printergen_typegen_matchinggen_match_recgen_matchgen_labelgen_functionsgen_exprgen_constructorgen_constantgen_callgen_blockgen_binopenullcoreconstruct_idcomparisonbuiltinarityargsversionwithout_extensionwithout_dirset_cwdread_directoryput_envis_directoryget_envget_cwdextensionexitexecutable_patharray_dependencyNOSYNCFULLFINISHBLOCKuncompressoutput_set_flush_modeoutput_endoutput_bufferoutput_boundinput_set_flush_modeinput_endinput_buffercompress__resultacopycallstackexcstackCFunctionPosexcVoidInvalidparse_argshelpFileNotFoundreportgen_nekocompletecapitalizeL/`ÐS­6_íèL5­LèL!¼fìLìL%ŒLXVL\¸fìLìL%ŒLXVL/¸f ìLlˆ^ì¥åèL`L4VL!´f7LLV­L.V7LnL-LZV^!7LoL)LO­LLLc­zLZVÿÿÿÿL+ærìLG­LèðLìôL)QL)LqLPVLgðf rLìL:VLLLLL3VLìLLDVLèL/­LèL-LAVìL6þaRrìLG­LèðLìôL)QL)LtLPVLgðf uLìL:V!LLLLLL3VL8VLìLLDVLèL)L2VèL6þYRrèL!LXVLèLaÄbèLz¼fì^?ìL!L-L5­LQVLèL!L-La­LaLa­ŒLALa­ˆL9­L[V襥åxLìLMþå9LìL_Œ $zåågðfLìL5­L-õL:V9L)L)L^þ+rj LL­l^(LèÐL¸f èLB­aìLz­LC­^èL/“°*ö­¥LLI­èL?­L>­L9L‚íLìLJþ*Rå9L@L)L=­L9ðL%z‰ågL‰å9L‰å9LìL\­‰å9L9ðL@L’LEL%zLKV‰=LN‰åèLèðLèL!´b èL%´b#^pgðf–L—L9L0VLõL:þ2^RìQL)ULjL ˆL=­l^3LèÐL¸f èLB­aèðL_Œ $´fL)LðV^ ^èL/“°*öþA¥¥¥^¥¥r9L@L)L9ðL%z‰å9ðf)L)L)L=þ3^)L)L)Lþ3rgðf uLìL:VèLh­LlL-VL9LìLkVLèðL%´fèQL*´fèULè¥^¥^^^^èL襥L=LìL`LFVL=þ!Rå9L}L-L0VL)ðLL­L^þ+riL/`ÐS­7_•¸LìL£þå9LìLt! zåå¼LìL£þå¿LìL£þåÂLìL£þåÆL)ˆLìL/HoØL#Œg%ÐZrrj9LLLL=Vl^$LèÐL¸f èL¬­a¾L¯­^èL/“°*öþ)¥r9L=þåj 9L=­l^$LèÐL¸f èL¬­a¾L¯­^èL/“°*öþ¥åèL9LÐvLìL=LÑvL)LLÒvzåìLìfÔ^ÕL9VLèL=þ!¥r9ðL=´f ¾L¯­èL=L9ðŒL¶VL-L-LL9ðLL¤V9L9ðL)ˆ‰è¥rå9ðL=´f ¾L¯­L9ðL±VL9L9ðL%ˆ‰è¥å!ñLìL°­LìLìLL×vLØL-L-LLÙvzRå9L=þå9L=þåèL9æLìL=LÛvL)LLÜvL-LæzåìLìfÞ^ßL9VLèL=þ!¥r9L-L-L-L«Vèråå9L­þåL³­LèLáíLâLãL-L¥æzLìLäíLìõRåìLìLzrLìðþåLìð­L©þå)L°­L)L!ÄbìL!Äb)Lì¼b )L)ˆLì¼f ìL·­-L-L-LôþC¥rèL!Äf îL·­èL!´f^YèL¦­L!ñL)ñLèðL!¼f<)L)ðL)ðLôVLèL!´f ÄL¯­)L-ðL)ˆ‰ìL)ðL)Œ‰¥_Àÿÿÿ)RrèL!Äf ðL·­èL!´f^±èL¦­L!ñL)ñLjXðL!¼fJLðLðL ôVLèL!´fðL!´fÄ^¾L¯­LðL)ˆ‰LðL)Œ‰¥_±ÿÿÿl^FLèÐL¸f èL¬­aèðLÀà´f$)ðL!´f ¾L¯­-L!LðL§V^ ^èL/“°*öþ9¥RrL³­LLj"fLLL9VL²V_ëÿÿÿL´­l^/LèÐL¸f èL¬­aèðLÀà´f )L­­^ ^èL/“°*öþ)¥RåL³­Lj5f%Lð­LèL ´f ªL¯­LìL¥V¥_ÜÿÿÿóLáL¨Vl^.LèÐL¸f èL¬­aèðLßUD´f ìL­­^ ^èL/“°*öþ!¥¥åèL9­LìL9­L)L9­L-L9­L-L-Lœ¨L)Lœ¨LìLœ¨RåèL9­LìL9­LìLìLœ¨RåèL9­LìL9­L)L9­L)L)Lœ¨LìLœ¨RåèL9­LìL9­LìLìLœ¨LìL€¬L!¸f èLŒ^èRåÁL¯þåÁL¯þ!rÁL¯þåLìQ­èLù‰èLúèLûFå)LìL-LzrèL)ðþrèLÿ¬Lµ­L)ðþrèLÄbèL€¼f L·­ìLìLÿ¬L9þ"r)L°­L)L!ÄbìL!Äb)Lì¼b )L)ˆLì¼f L·­-L-L-LôþC¥r!ñLìL°­ñLèðL!¼f<)L)ðL)ðLôVLèL!´f ÄL¯­)L-ðL)ˆ‰ìL)ðL)Œ‰¥_ÀÿÿÿRrìLìL9VìLìL L9VìLìL L9VìLìL¤L9þ"rèL!ÄbèLÿÿ¼f L·­ìLìL9VìLìL L9þ"rèL€ÿÿÄbèLÿ¼f L·­èL!ÄfìLL)ˆL9þ"^ ìLìL9þ"rèL!ÄbèLÿÿÿ¼f  L·­ìLìL9VìLìL L9VìLìL L9þ"rLìUþåÁL¯þåÁL¯þåÁL¯þ!rÁL¯þåLìQ­èL FèL‰èLèLFå)L)L)L®VL9þ*r6žL/`ÐS­7F_© ìL/áïjÿ­L!LèLÄfìLìLL/%[ÌVèL%ˆa_çÿÿÿìRrìLìL/ RÌVLèL´f &L ­è¥r)L)L)L/%[ÌV€f (L þ!rjLLLLL/(î-øVl^L¥f *L þ1r)L)L)L/í2[ÌVLèL´f ,L ­è¥r)L)L)L/,†ÐúVLèL´f !L­è¥rìLìL#VLèLL#.Zû!µr¥rèLèðLèL!´b èL%´b^P^MìUðL!´fìQL9LìLVR^4¥^^ìQL)UL9L)LV9L=LVèLðþ1¥¥^¥¥åL­LñLèL)LL-L0v‰èða)Lì­ìLþ)RrèL ÀfèL~ÈåèLèLèL ´b$èL ´b%èL ´b&èL\´b'èL"´b(¥^.^*3¥^X^"4¥^P^5¥^H^6¥^@^ 7¥^8^¥èLèL9­Ìf8LìL"­LV¥^^¥^¥èL%LìL=þ*¥¥åèL9L=­´f Lþ^Ñ9LìLVLèLèL ´b$èL ´b-èL ´b6èL\´b?èL"´bH¥^V^RL3LV¥^^BL4LV¥^q^2L5LV¥^a^"L6LV¥^Q^L7LV¥^A^¥èLèL­ÌfL8L)L"­LVLV¥^^¥^¥èLLìLV¥¥èL%ˆLðþåL­LñLèL-L9LL=LLL:v‰èða!Lìþ!RåèL9­LèL=­L!ñL!ñLìðLÄg< L)ðL/ RÌVLèL\´gü)L-ðL%ˆ‰)ðL´f <L ­L-ðL/ RÌVLèLèâu^ê^è^æ^ä^â^à^Þ^Ü^Ú^Ø^Ö^Ô^Ò^Ð^Î^Ì^Ê^È^Æ^Ä^Â^À^¾^¼^º^¸^¶^´^²^°^®^¬^ª^¨^ª^¤^¢^ ^ž^œ^š^˜^–^”^’^^Ž^Œ^ _]__×_”_Q__Ë_ˆ_E^v^t^r^p^n^l^j^h^f^d^b^`^^^\^Z^X^V^T^R^P^N^L^J^H^F^D^B^@^>^<^:^8^6^4_¾^0^.^,^*^(^&^$^"^ ^^^^^^^^_¬^ ^ ^_¶^_Ä_Ô_ÒLðL"L/%[ÌV_É_ÀðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR_ _ðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR_K_BðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR_Œ_ƒðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR_Í_ÄðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR__ðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR_O_FðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR__‡ðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR_Ñ_ÈðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR__ ðLˆLÀf <L ­LðL%ˆL/ RÌVLLðLˆL/ RÌVLLðLˆ‰ìL0ÄbìL9¼bèL0ÄbèL9¼f <L ­0L"­LL"­LìŒLdL-L"­L)ŒL ˆL)L"­L)ŒˆLèLÿ¼f <L ­LðL)L­L/%[ÌVR^S^JLðL\L/%[ÌV^A^8LðL L/%[ÌV^/^&LðL L/%[ÌV^^LðL L/%[ÌV^ ^<L ­¥¥^^^èLL-ðL)L/%[ÌV¥¥èLìðL%ˆ‰ìL)ðL%ˆ‰_Àöÿÿ)L!L)ðLþCRåèL9­LìL!L)L=VL!ñLaL"­LAL"­ŒLìðLÄfHL)ðL/ RÌVLèLAÀfèLZÈf-L-ðL)L"­LˆL­L/%[ÌV)L-ðL%ˆ‰¥_´ÿÿÿ)RåèL9­LìL!L)L=VL!ñLAL"­LaL"­ŒLìðLÄfHL)ðL/ RÌVLèLaÀfèLzÈf-L-ðL)L"­LˆL­L/%[ÌV)L-ðL%ˆ‰¥_´ÿÿÿ)RåèL@þåèL/HoØLBþåF7L/`ÐS­7|_’è€fJ#MR±åèðLìôLV­LJL#1ÚiZååì€fèrìôL)ðL)LJL#1ÚiZLXþ"rrèLJ#MR±LXþåèLèðLèL!´b èL%´b ^!^ìUL%LìL9𭈥^¥¥åèLèðLèL!´b èL%´b^\LTæ^ ìQLè¥^¥¥åèLèðLèL!´b èL%´b^^LTþ!^ ìULè¥^¥¥åèLèðLèL!´b èL%´b ^0R^,ìQL)ULKL)LæLL-L9ðVL%z¥¥^¥¥rèLèðLèL!´b èL%´b^$^!ìQL)ULìL­LìL9ðþB¥¥^¥¥rìLèðLèL!´b èL%´b"^y)LèðL!´f^ ^^bLTþ9¥^\ìQL)ULLèðLèL!´b èL%´b^2bLTþQ^)ìQL)ULL)L VLL)L9ðþs¥¥^¥¥¥¥^¥¥rèLèðLèL!´b èL%´b^PRLRõ^GìQðL)QôL-ULèL9ð­LèðLìôLKLL)L%zLKLLL%zõR¥¥¥^¥¥åèLèðLèL!´b èL%´b^)^&ìQL)ULìL­f^ LìL9ðþB¥¥^¥¥rèLèðLèL!´b èL%´b^0^-ìQL)ULìLLOVL!´f^ LìL9ðþB¥¥^¥¥rèLèðLèL!´b èL%´b^@ULQæ^7ìQðL)QôL-ULL-LOVL!´fì^ LìL9ðæ¥¥¥^¥¥rèLèðLèL!´b èL%´b^<ULQæ^3ìQðL)QôL-ULL-øL!´fì^ LìL9ðæ¥¥¥^¥¥rèLèðLèL!´b èL%´b^/ULQæ^&ìQL)ULìL­fì^ LìL9ðæ¥¥^¥¥rìLèðLèL!´b èL%´b ^*)^&ìQL)ULèLKL-LL%zL9ðþB¥¥^¥¥rèLRL9þåèLèðLèL!´b èL%´b ^+-^'ìQL)ULLL-LæL)L9ðæ¥¥^¥¥rìLèðLèL!´b èL%´b ^+)^'ìQL)ULKL)L)LL9ðVL%z¥¥^¥¥rìLèðLèL!´b èL%´b ^')^#ìQL)ULèLL-L9VL=ðþB¥¥^¥¥rñLèL9L)Lnv‰èðaìLRL)þ"¥åìL!´fè^;èLèðLèL!´b èL%´b^!pLTþ)^ìULL%ŒLìL9ðþ:¥^¥¥rèLèðLèL!´b èL%´b^)^&ìQL)ULìL­fLìL9ðþB^¥¥^¥¥rèLèðLèL!´b èL%´b^)^&ìQL)ULìL­f^ LìL9ðþB¥¥^¥¥rìLèðLèL!´b èL%´b^3tLTæ^*ìQL)ULL!´fì^èLL%ŒL9ðæ¥¥^¥¥rñLèLìLuí‰èðaìL!Äf vLT­)L)L)æ¥rèLèðLèL!´b èL%´b ^?R^;ìQL)ULìL­fKL)LL-L9ðVL%z^ LìL9ðþB¥¥^¥¥rèLèðLèL!´b èL%´b^/^,ìQL)UL9LL-LMVL%ˆLìL=ðþB¥¥^¥¥rèLèðLèL!´b èL%´b ^OLPþ!^GìQL)UL%LìL9­ˆL)LLVLñLèL)L)Lyv‰èða%L-L)VìR¥¥^¥¥åèL9­L)LìLSVèLNþ!¥r|7GL/`ÐS­7œ_؃LìðL)QL!LèL)Äf.-L-L)$L~L#Ñ(0µˆ2èL%ˆaèL)Äf -L„ˆ2_Ïÿÿÿ-L…ˆ2-Rå9LìL/¢å1&­L)zåèQå9L!L/™m%©zåìðL)QLìL/¢å1&­Lì´f,èLL%ˆL/Ï~4"­eìL!LðL!LL/}÷V-L)‰èL)L@-LìL%ˆFRrìLìLþ"r)L)L)Lþ3rìL/Ï~4"­L!LèLÄfèL)L@èL%ˆa_êÿÿÿ9LL-zRrìL/Ï~4"­L!LèLÄfèL)L)Læ@èL%ˆa_åÿÿÿ9LL-zRrèQL!L)ð2èL)Äf)Lì$L­èL%ˆa_èÿÿÿRrèQL!L)ð2èL)ÄfèL-L)$LVèL%ˆa_åÿÿÿRrèQL!LìL/Ï~4"­L-ð2ìL-ÄfìLìLL$Læ@ìL%ˆe_âÿÿÿ9L-L)zRrèðLìQL-L‰þ+rèQL~#MR±L)ð2ìL!¼fìL%Œe)L)$LìL~L#1ÚiZa_àÿÿÿèRåìQL!L-ð2èL)Äf)LL)$L9VèL%ˆa_äÿÿÿRr)QL)L)ˆLì¼f ˜L/&]­9L)LðLLL/¿[uÀVz¥rðLLðLLL/}÷þUrìQL)ð2!LèL)Äf$-Lì$L-L~L#e ÐZL!´fèrèL%ˆa_ÙÿÿÿR‚L€þrœ7}L/`ÐS­7ù_ýèLèðLèL!´b èL%´b^ žL-LL#ýKZ^ŸL-LL#ýKZ^¥¥å9LìL%zåå¤LìLL#ýKZå9LìL9eê*zåå¨LìLL#ýKZå9LìLâ% zåå¬LìLL#ýKZå9L)L)Lv¨zrr°LìLL#ýKZå9LìL5/zåå´LìLL#ýKZå·LìLL#ýKZåºLìLL#ýKZåèÐL´flèôLèÐL´f èL/Ë\ˆ­L%´f ìLìþrÀL)L/¢å1&­L!LèL)Äf+)LL)$L¿­ˆ2èL%ˆaèL)Äf )L„ˆ2_Òÿÿÿ)LÁˆ2)rRèL/Ñ(0þåå L/°ñm­LÃL!L)L/¢å1&­L%ŒLìLìÄfL-L)$LèL/º”“­LèLÄ´f )L%ˆ2^!LìˆLňL L-L/ÿAVL¿­ˆLƈ2-L%ˆ2R_²ÿÿÿ)LLj2)RáèL/¢å1&­LèL´f)rL-LÀˆ2èL)Äf+-L-L)$L¿­ˆ2èL%ˆaèL)Äf -L„ˆ2_Òÿÿÿ-LÁˆ2-rRr)L)øL!´f!r)ÐL´f†)L/¢å1&­L)L/¢å1&­LìLì¸fìLìÔr)Lè„f!èðL´fèôL´f LørèQa_ßÿÿÿ!LèLÄf4Lì$LL)$LLLzLÊVLèL!¸fèrìL%ˆe¥_Éÿÿÿ!rR)ÐL´f‹èLè„f!èðL´fèôL-´f -L-ørèQa_ßÿÿÿ-L/°ñm­L!LìL/¢å1&­LìLìÄfHL-L-$L/ÿAVLLL$L/ÿAVLìLLL zLÊVLèL!¸fèr -L%ˆ2R_¶ÿÿÿ!rR)L)ÔrrìLìLLÊþ+rèL!Äb èL)QÀf ÍLùL#ÎeK<µìðLì$rìL!Äb ìL-QÀf ÏLùL#ÎeK<µìL-ðL)@rÒåèQL¿­LÕˆLìUL¿­ˆåÔL)L)L%zrèåèL/&]þåìLìL®VL9ærèLª­L9æåèL²­L9æååèðLè¥åèôLè¥åèL/ï P­LèL´f áL9­è¥åèL/œÅ–­LèL´f ãL9­è¥åèåèL!ÄbèLÿ¼f æL9­èåèL¿þåèL/Ñ(0þåèL9­L/-X‹ÈþåèL/-X‹ÈþåìLìLùL#e ÐZrìLìLL#e ÐZL!Äfì^èrìLìLL#e ÐZL!Äfè^ìrìLìL½þ"rìLìL9VL=þrñÜLL)?–€NèL!?”]UèL/™m%©?BšÁè¥åèL!Äf óL9­ì#BšÁLì$Lè„fèr)#BšÁL/¢å1&­L)L%ˆL/Ï~4"­LèL!L#BšÁL!LL/}÷VìLÈfìLìLLL#–€Nµ@ìL%ˆe_äÿÿÿLì?BšÁèL$rRrèL!Äf õL9­ì#BšÁL/¢å1&­L)L-#”]UL-ˆ?”]UèL)Àf)L-#BšÁL-L-LŒL/¿[uÀV?BšÁ^*)L/™m%©?BšÁìLìŒeìL!¼fL-L#–€NµìL%Œe_éÿÿÿ¥rè#”]UåÜ7ññL?BšÁñL?–€NñL?”]Uù7 LèL!õ7¡L¡?Ø>ã3èL£í7¢L¢?O17¥¥LèL§í7¦L¦?7ä.©LèL«í7ªLª?%Ðý­LèL¯í7®L®?±Úx+±LèL³í7²L²?¨;WµLèL65õ7¶L¶?©Óà¸LèLw ùõ7¹L¹?¶’¥ê»LèLßUDõ7¼L¼?>#÷-¾LL/HoØL#Œg%ÐZ7½Â7¿ùLÈ?ãŸpðùLÉ?ýKË7ÊùLÌ?e ÐùLÎ?SùLÐ?!nÓL!õ7ÑÖ7ÔØ7×ùLÔ?!Ê|ÕùL×?1ÚiùLÑ?MR±ÙLÚLèLÛíLìLÜíL)LÝíLÞLßLàLLâíLLäíLåLLçíLèLéLìLêíLëLìLíLîLïLèLLðvLòLLôíLLöíL÷LùL?&]ùL ?Ñ(0ùL-?º>9ùLì?÷±!ùL)?'}ÖùL?€-ùL?L(†ßùL?i£WùL?™Ïa1ùL ?-X‹ÈùL ?áTùL ?¿/iïùL?ÿÍÃùLø?›yÉùL?’SùL?¤ SùL?-qùL?ÎeK<ùL?ï PùL?¹ÈùL?‡ÊMùL?œÅ–ùL?ÈË)óùL?¥iùL ?-zKùL?ÆFÌR ùù7~~#!n7~#&]7€~#S7~#¶’¥ê7‚†LèLˆí7‡ŠLL/HoØL#Œg%ÐZ7‰œL‡?.Zû!‹LìLŒíLLŽLLLíLL‘íL’L“LL”íL•L–LL—íL L™íLšL›LœL-?€©WœL?Ñ(0œL?^'XÌœL ?¢›WœL?œ SœL ?î9VÈœL?^³ÇœL?攜L?Q° œL?ſŜL?;»ÅœLì?›>œL ?–€NœL ?üfüœL)?58ÁœL?ÚáÓœL ?!òIRœœ7Hù7JJ#!Ê|Õ7KH#î9VÈ7LJ#!n7MH#^³Ç7NJ#e Ð7OH#üfü7PJ#&]7QJ#MR±7RH#^'XÌ7SJ#ÎeK<7TJ#¶’¥ê7UW7VY7X|LZ? sÛ|LV?.Zû!ñLèLìL[í‰èða]L_LñLñLñLñLñLñLñLñLñLñLLL`í‰ð2 LLaí‰ð2LLcí‰ð2LLdí‰ð2LLeí‰ð2LLfí‰ð2-LLgí‰-ð2)L-Lhí‰)ð2ìL)Lií‰ìðeèLìLjí‰èðaèLkíLñLñLñLñLñLñLLLlí‰ð2LLmí‰ð2-LLoí‰-ð2)L-Lqí‰)ð2ìL)Lrí‰ìðeèLìLsí‰èðawLñLèLìLxí‰èðaLzíLèL{íL|L?xe|L?Úên|Lì?^'XÌ|L ?4å|L ?cÙV|L ?Ò9WÊ|L?bÝS|L?¸ É|L?S|L?œ S|L?æ”|L?° Â|L?Å¿Å|L?üZ|L?\ÀÃ|L ?9лÃ|L-?¸5|L?Üà?|L? ÐÇ|L?k¿Á|L ?•r9&|L)?™m%|L?ÚáÓ|L?!ùIR||7L/`ÐS­7 ^üþåìLìLþþ"rèLþå 7úù7ûýL!L/HoØL#Œg%ÐZ7üÿLL/HoØL#Œg%ÐZ7þLL/HoØL#Œg%ÐZ7LL/HoØL#Œg%ÐZ7L%L/HoØL#Œg%ÐZ7L%L/HoØL#Œg%ÐZ7L L LLLL L-?Ñ(0 L?ÏIÈæ L?üfü L)?"‡ Lì?ô0Û L?!òIR  7ù7#Å¿Å7#Ñ(07#L(†ß7#ô0Û7#&]7#!òI7#üfü7#-zK7#ÎeK<7 #¶’¥ê7!#áT7"$LL/HoØL#Œg%ÐZ7#%L/áïjÿL/´VhL'L)L+L-L.LL/L1L2LèL L9vLLL-L;vL L LL=vL LL>vL LL?vLAL%L/HoØL#Œg%ÐZ7@CLL/HoØL#Œg%ÐZ7BDLELFL-?‘>çFLì?gä˜úFL?šr!ÝFL ?€©WFL?ÚênFL ?¢›WFL)?à]òôFL?î9VÈFL?1­¥æFL ?,ñ(FL?æ”FL?r€˜ FL?–€NFL ?9лÃFL?”ãìFL?CÚÚFL?üfüFL? ÐÇFL ?58ÁRFF6Ÿ 6 ù6¢¢#ýK6£Ÿ#58Á6¤ #ô0Û6¥Ÿ#üfü6¦Ÿ#€©W6§¢#ÆFÌ6¨¢#áT6©¢#>#÷-6ª #"‡6«¢#7ä.6¬ #Ñ(06­¢#L(†ß6®¢#&]6¯Ÿ#æ”6°Ÿ#–€N6± #!òI6² #üfü6³¢#-q6´¢#-zK6µ¢#’S6¶¢#ÎeK<6·¹LèL»í6ºžLº?bŸí½LèLÀàõ6¾žL¾?œ¼4ÀLèL^!‰õ6ÁžLÁ?ÌæÂÃLèLlûq õ6ÄžLÄ?Ì¢OÇ6ÅÈLLÅVLÉL%LÅVLÊL%LÅVLËLLÅVLÌL%LÅVLÍLLÅVLÎLLÅVLÏL%LÅVLLLLÓvLLìLÖvLÚLLLLLÝvL LìLàvLåLæL!LÅV©LçL!LÅV©LèL!LÅV©L)L­L)L­L)L­LéLêLëLíLïLñLèLòíLôLLõíLLöíLL÷íLLøíLüLýLþLÿLèLíLLL-LíLLíLèL íLL íL LLLíLL?¶uKL?ÙtKL?q·„÷L?O$L?¨æõÜL?îäõÜL ?uaøL ?veöL ?¨ÅÈõL?ßlYÐL?Ë¿óL?H³ L?¢&ìL?ßÇp>L?Çp>L"?Ú¥AL?½~8L?ŸÌ9üL ?åÊ9üL#?Edž4L?ŸWŠ2L?Ñî1L?ж4üL?xì3üL?VK§ËLì?™Ïa1L? L? Ä>L-?Äb›L&?™ÝÜL'?œ‡0øL?n T<L?Îä+L?EqL<L(?ܲÏL)?9—²íL!?¤YáÀL,?­O¿ëL$?ÇÞôåL%?}r*L+?}~&ôL*?u2:ðL ?‹zÔæL?ˆîÉL)?G9L ?LýLR2mL/`ÐS­7L_O !LL)zåèðL LVèLFåìL)ôL)f%^ÿÿÿÿˆìL9þrèQÌfèðLìôLL LVLVèLFèðLæåèLèðLèL!´b èL%´b^X^UìUðL!´fìQLèL­R^?¥^^ìQL)ULìL­#LLL9æVLLL-L=ðþd¥¥^¥¥r#LìL-L9æþ"rèL9­=Qf=L'LV=LþåèôLìðL#LìL9L=æVìLèðLèL!´b èL%´b^^ìQL9LÅLVèLþ9¥^¥¥RåèLèðLèL!´b èL%´b^>L¹Lþ*^„ìUðL!´f3ìQðL)QôL?L)L9L=æVèL­9L­R^Q¥¥^^ìQðL)QôL-UL?L-L9L=æVìL­9L„LV9L­èLðþ9¥¥¥^¥¥åèôLìðLèL9­=LCLV=LLVìL9­=LLþ*RåèôLìðLLL9ðæLìLèðâ^)^B^^à__6_b_¡_ _™_Þ_$_¡_ß__'_P_¿_Ó_wèQL#LìL­LL=æþR¥_\èQLL&LVLLV)LLLL(vLìLVLôL%ŒLÇLVLþI¥_ èQLQÌf"LÃLVèL-­L)LV¥_ä^¥^¥èQLL*LVèL-­L+LþR¥_ºèQLìULìL­,LìLL=æþZ¥¥_˜èQLìULìL­LÀLVL-LL-LVLÁLþZ¥¥_`èQLìULìL­LƒLVèL­L…LþZ¥¥_2èQLL.LVL„LL=LLL/vL-LVL'LVLþI¥_ñè*ðLèL!´b èL%´b0^iìQL)ULL0LVìL­LìLLðþk¥¥^>ìQL)ULL1LVLìLLðVL0LVìL­LþY¥¥^¥_pèQLìUL)*LL2LV)L­L)L)LLVL!´LðVèLèðLèL!´b èL%´b^#^ ìQL L3LV LìLLðþƒ¥^¥¥¥¥¥_õèQLìUL)*LL4LVL-LLðV5L)L L=æVLìLLðþk¥¥¥_®èQLìULL6LVL-L#L L=ææLLVLÁLVLìLLðþc¥¥_fèQLìUL)*LQLfèfLÀLV^ L&LVLLL9ðV7LL L=æVLL-L9ðVfèfLÁLþj^ LÇLþj¥¥¥¥_çèQðLèL!´b èL%´b^(L8LþR^ìQQLL9LVèLþQ¥^¥_§èQðLèL!´b èL%´b^(L:LþR^ìQQLL;LVèLþQ¥^¥_gL<LþJ_[èQLìULìL­L'LVL­èLþQ¥¥_0èQðL!´fL=LV_^^èQLL&LVLLVñLèLL=LLLLL@v‰èðaìLì­LLVLÇLþZ¥¥^¿èQLALìLL=æþR¥^©èQLìUL)*LLBLV)L­L&LVL­LLLLDvL)LVèLèðLèL!´b èL%´b^/^,ìQL LELV LLVèL­ LLV¥^¥¥LÇLVLþY¥¥¥^¥¥RrìôL)ðLèLèðLèL%´bèL´b/¥^{^wQf LGL9VLLLõL=V¥^…^PìQLQf LGL9VL&L9VLLVLL)L=VLLVLÇL9VR^9¥^¥LLVLLLõL=V-f L'L9VLLþB¥Rr9LL)L=V9Qf9L'LV9LþåèL­LèðL%´f%èQL-L9L=LLIvLìLV¥^¥^^)LL-L9þ3¥rL­LèðLìôLìL9­LèLL=V)L­L)þ1RåL7 7 |7F7L/`ÐS­7_8 èLèðâ ^^^)^3^=^G^Q^[^e^n[L)LTþ"^b\L)LTþ"^V]L)LTþ"^J^L)LTþ"^>_L)LTþ"^2`L)LTþ"^&L)LTþ"^aL)LTþ"^bL)LTþ"^¥å9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzååèLèðâ ^^'^1^;^E^O^Y^c^m^w^^‹^•^žrL)LTþ"^’sL)LTþ"^†tL)LTþ"^zuL)LTþ"^nvL)LTþ"^bwL)LTþ"^VxL)LTþ"^JyL)LTþ"^>zL)LTþ"^2{L)LTþ"^&|L)LTþ"^}L)LTþ"^~L)LTþ"^¥åèLèðâ^#^-^7^A^K^U^_^i^s^}^‡^‘^›^¥^¯^¹^¼L)LTþ"^¶L)LTþ"^ªŽL)LTþ"^žL)LTþ"^’L)LTþ"^†‘L)LTþ"^z’L)LTþ"^n“L)LTþ"^b”L)LTþ"^V•L)LTþ"^J–L)LTþ"^>—L)LTþ"^2˜L)LTþ"^&™L)LTþ"^šL)LTþ"^›L)LTþ"^¥å9LìL zåå9LìL zåå9LìL zåå9LìLzåå9LìLzååèLèðLèL!´b èL%´b^²L-LTþ*^³L-LTþ*^¥¥åèLèðâ^)^3^=^G^Q^[^e^o^y^ƒ^^—^¡^«^µ^¿^É^Ó^Ý^æ·L)LTþ"^Ú¸L)LTþ"^ιL)LTþ"^ºL)LTþ"^¶»L)LTþ"^ª¼L)LTþ"^ž½L)LTþ"^’¾L)LTþ"^†¿L)LTþ"^zÀL)LTþ"^nÁL)LTþ"^bÂL)LTþ"^VÃL)LTþ"^JÄL)LTþ"^>ÅL)LTþ"^2ÆL)LTþ"^&ÇL)LTþ"^ÈL)LTþ"^ÉL)LTþ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9LìLzåå9L-L-L-Lzrr9L-L-L-Lzrr9L-L-L-L zrr9L)L)L zrr9L-L-L-L zrr9LìL zåå9LìL zåå9L)L)Lzrr9LìLzåå9LìLzåå9L-L-L-LzrrèôLè¥åèL-L-LÓVõrèL)LXLÓVõrèL-LRLLXL%zLÓVõrèL)Lp­LË­õrèL)Ln­LË­õrèL)Lh­LË­õrèL)Ll­LË­õrèLLLLáVõrèôLìðLìLèðLèL!´b èL%´b ^V^ìQLèL9­LS­¥^¥¥LìõRåèôLìðLìL9­LìõRåèôLìðLìL9­LìL9­õRåèôLìðLìLìLèðâ^)^+^?^P^i^‹^©^Â^ì_F_p_‰_³_é__!_?_X_Z_»)_·èQLLìLZVLÍ­¥_¡èQLèL­LÏ­¥_ŽèQLìULìL­LìLÑV¥¥_sèQLìULìL­LL)LZVLÓV¥¥_OèQLìULìL­LìL­LÕV¥¥_/èQLLùíLìLZVL×­¥_èQLìUL)*L)L­L)L­L)LÙV¥¥¥_èèQLìUL)*L)L­L)L­L)LèðLèL!´b èL%´b ^V^ìQLèL ­LS­¥^¥¥LÛV¥¥¥_ŒèQLìUL)*L)L­L)L)L ­LÝV¥¥¥_`èQLìULìLìL­LßV¥¥_EèQLìUL)*L)L)L­L)L ­LáV¥¥¥_èQðLèL%´b èL!´b^ ìQQLèL­LS­Lã­¥^-^¥^áèQðLèL%´b èL!´b^ ìQQLèL­LS­Lå­¥^-^¥^©)^¥èQLìULìL­LìL­LèV¥¥^…èQLLúíLìLZVLê­¥^j)^fèQLìUL)*L)L­LLûíL-LZVL)LèðLèL!´b èL%´b ^V^ìQLèL ­LS­¥^¥¥LîV¥¥¥^¥õRrèôLèLèðLèL!´b èL%´b^^ìQLèL9þ1¥^¥¥¥åèôLèL9þ¥åèôLìðLèL9­ìL9þ!RåèôLìðLèLèðâ^)^*^9^E^W^r^Š^ž^¶___%_=_h_“_”_¬_À_Á__èQLLìLUþB¥_èQLèLþ9¥_òèQLìULìLþA¥¥_ÞèQLìULìL­LìLUþJ¥¥_ÁèQLìULìL­èLþA¥¥_§èQLLýíLìLUþB¥_‘èQLìULìL­èLþA¥¥_wèQLìUL)*L)L­ìL­èLèðLèL!´b èL%´b^^ìQLèL þa¥^¥¥¥¥¥_*èQLì*LìL­èLþA¥¥_èULèLþ9¥_èULì*LìL­èLþA¥¥^èèQðLèL%´b èL!´b^ìQQLèLþA¥^^¥^»èQðLèL%´b èL!´b^ìQQLèLþA¥^^¥^Ž^‹èQLìULìL­èLþA¥¥^qèQLLþíLìLUþB¥^[^XèQLìUL)*L)L­LÿíL)LUVèLèðLèL!´b èL%´b^^ìQLèL þa¥^¥¥¥¥¥^¥RrèLèðâ ^^^^^^)^0^D^O^U^Q^M^I^EèQLèLYþ!¥^7èQLè¥^.èQLLìLW­ˆLˆ¥^èQLL숥^ èQLè¥^¥åèLèðâ ^^^!^#^%^'^)^+^-^/^1^3^5^6^2 ^. ^* ^&3^" ^ ^^<^^4^ ^^¥åèLèðâ^#^%^'^)^+^-^/^1^3^5^7^9^E^Q^X^g^q^m'^i}^e-^a^]&^YÇ^UÀ^QÁ^Mƒ^I…^EèQLèL9þ!¥^7èQLèL=þ!¥^)èQLè¥^ èQLLìˆLˆ¥^èQLL숥^¥å7M|7NL/`ÐS­7U_;LìL#þå9LìL¤©r9zååèðåèôåìôL)QL)QL8VL-UL-UL-VLðzrLLìL&­L)L!LL!LLL1­L?L!L!LL z ¥åèðåìLì‰rL!FL!FLUFLUFL-FLF L)F LìF rè*Lì* L)ôL3­ŒL)* L-*zåèôåè*L!´fÂè*LìU´fVèULL&­LèL)UL-QL!LUL$VìL)*L-UˆFìL)*L-UˆFìLìFìL)ULF¥è*Lì*ŒLìQL!L-QL*LL$VìLìFìL!Fì*L)QL)LULŒL%VL)L-*L)ˆF)L-*L)ˆFRèQLì*L4VLìL)*L%ˆFìL)*L%ŒFè¥åèL ´f ìLF ^èL ´bì* fìLF ìL)*L%ˆF rj8L9­LL*L%ŒFL*L%ˆFLìL=VèL!­¥l^*LèÐL¸f èL/­aèðLÀà´f'^ ^èL/“°*öþ¥å9ðLì$ðL=L­$LL)L,VLL‰L)èLÿÿÿÿ¸fL‰LììLÿÿÿÿ´f .L5­-L%ˆL)Lðþ2Rr9ðL9ôLèLÿÿÿÿ´f6=L)Ìf&=L=*LðL%ˆŒF=L=*LðL%ˆˆFÿÿÿÿ^=L=*L-ŒF=L=*F=L=QL=*LL)V=L=*L-ˆF=L=*F=L=* L-ˆF !ñLèðL-Äf"=L=ôL)ðL4VLVèLìðL%ˆ‰_Úÿÿÿì¥RåèðL+­LìðL2­LÿÿÿÿL!õLÿÿÿÿL!õLñLèLLL9LLLLLLv‰èðaìLLL=LMvLj!L!LVNLÖL*Vl^nLèÐL¸f èL/­aèðLèLÀà´b èLßUD´b6^?ôLÿÿÿÿ¸fLðL%ˆ‰LLôL,VL-­¥^^L-­¥^ ^¥èL/“°*ö­¥LèLÿÿÿÿ´f LQæ^LôL)L,VæRrèðLj L6­l^(LèÐL¸f èL/­aìL=­L5­^èL/“°*öþ!¥¥åPL)L:VL2L-L:VL"­LèL-L-L"­L0­L(­zRrRL9æåSL7LìL9þ"¥åU77|7F7L/`ÐS­7Ï_ÙèLèðâ^^^#^-^7^A^J„L)L^þ"^>…L)L^þ"^2†L)L^þ"^&‡L)L^þ"^ˆL)L^þ"^‰L)L^þ"^¥å9LìL%zåå9LìLzåå9LìLzåå9L)L)Lzrr9L)L)LzrrèL€LlVL!´åèL)õLèððL!´fì^Ú^^èôðL!´f)^É^^èððL%´f°èôðL%´f£èðQLèðLìôL-ðULôQðLôQôLôULL-ÈfWL%ˆL-ÄfyLLL L9ðVL%z^1L)Äf-LyL-LõL-L%zL9ðV^ LìL9ðV^ LL9ðVR^"¥¥¥¥¥¥¥^^^^—LGLcþ*¥rèLèðLèL!´b èL%´b%^]-L9ÈfyL9LõL€L%z^€^=ìQðL)QôL-ULyL-L%ŒLõL-L%ˆL-L=ðVL%z¥¥¥^¥¥rñLèL9L)L™v‰èðaìLèðL%´f/èQðLÿÿÿÿ´f!èQôLìULìL%ˆLìLVR^¥¥^^^^èLÿÿÿÿLìLþ2¥¥¥åìL9­LìL9­L=VL9þrìL9­LìL=VL9þr€L€LL-­zåèL9øL!´åèLžíL)LpVfì^yLìL-L%zLìQL9ðþ"r9L)L)Lsþ+r9L9ðL%ˆ‰9ðåìLèðâ^^^7^n^¥^Ã_ì_èQL9L=­LèLyLLõL€L%z襥^ÛèQL9L=­LìLìLðVLìLyL)LyLL€L%zL%zFìR¥^¢èQL9L=­LìLìLðVLìLyL)LyLL€L%zL%zFèR¥^ièQLìULìLìLLðVLðþ:¥¥^IèQLìUL9L=­LèLyLLLðVLyLLLðVL€L%zL%zF襥¥^¥r9L=­LèL)L)LVõ¥å!ñLèL¡íLñLèL)L9L-L¢v‰èðaìL9L)L£vLL`þ2RåèLèðL%´f†èUðL%´fxèQðLìQôL)ULèQðLìQôL)ULL)øL!´f$yLLLL9VõL)L%zL=ð­^yLLõLL=ð­L%zR^¥¥¥¥¥¥^^^^ì¥åèôåèôLìðL-ôLðLìðLðŒRrèôLìðLyL9L-L%zLìL=LVõRåèôLìðLìLìL9L=VõRåèôLìðLèL9­ÌRåèôLìðL-ôLðLyLyLL€L%zLL-L9VõLLL=L¨vLLVLL9L©vLLVL‚VL%zLLªíLìLfVL)LLVõ¥RrèôLìðL€L)L9VLìõRåèôLìðL-ôLðLèL-LiþBRrñLèL9L)L¥v‰èða¦L)LVLz­L§LìL|VL)­LñLèL=LLL9L«v‰èðaèL€LõL-LsVLèðLìôLL¬íLìLVLèL\­L­LìLdV}LìL`VLgL)L`VõR åj9LLaVl^[LèÐL¸f èL{­aèðLw ù´f9=ðL=L=ðL%ˆ‰9L-L)LuVLyLLðL%z‰è¥^ ^èL/“°*öþ¥åèðåèôLèL9Leþ"¥å°LìLVLj9LLaVl^šLèÐL¸f èL{­aèðLw ù´fx=ðL=L=ðL%ˆ‰9L-L)LuV-L­LèðLìôLìL­LðL)L`VLL±íLL`VLLyL-L-LzLõLðL%z‰R^ ^èL/“°*öþ!¥¥åèðL9L9ðL)L=V‰¥åèL9ðLxþåèôLìðL9LyL-L=LzL9ðL%z‰Rå9L)LµvLìL_þ"rèðL)ðLèL)Liþ2Rr€ñLèL¶íL)LjV·LìðL|þ"¥åèL9­LLƒ­LLƒ­L!ñL!ñL€ñL€ñLL-L-L¯vLñLèLLL=LLL LL²v‰èða€ñLèLL³vLLmVèðL)­Lt­ðLL´íLqVL¸LèLðLh­LVL\­LèL-õR åèQLìôL)ðLèñLèðL-Èf#9LìðL=LLvVLkVèLìðL%ˆ‰_Ùÿÿÿ¥RåLÿÿÿÿL]VLèL)LºvL-L_Vè¥rìLìL~­´fÿÿÿÿ^èL)LvVfì^ìL%ˆLìL9ðþ"rèQL!LìL9þ"¥åèôLìðL9LìLvVL)L=þ*RåèôLìðLñLèLìL¼í‰èðaèL½íL)L`VL-L9L¾vL-L`VLìLìõRRåÀLìL^þå9LìL±ý1.zååèLw­LyLìL)õL€L%z¥åèôLìðLyL)Lw­L)Lw­õL€L%zRåÅLìLVL9L=L)Lsþ+¥åèL­LæåìLìðLnVLìL)ðL%ˆ‰èLèLèL\´b2èL+´b3èL*´b4èL?´b5èL[´b6èL]´b7èL-´b8¥^>^:)¥^=^2)¥^5^*)¥^-^")¥^%^)¥^^)¥^^ )¥^ ^¥-L9þ)¥¥rèLèðL´f"èQLìULìLìL9ð­L’VR^¥¥^^ìLþ¥åèLèðL´f"èQLìULìLìL9ð­L’VR^¥¥^^ìLŽþ¥åèLèðL´f"èQLìULìLìL9ð­L’VR^¥¥^^ìL‹L”þ"¥åìLèðL!´fì^^^)L)L’þ*¥r9L=ðLnVL=L=ðL%ˆ‰èL]´fðLbLlVL!¸f 9L­ì_èL-´fŠðLbLlVL!¸f 9L­ìLèðLèL!´b èL%´b^VyL-LõLL%zLðþ)^<ìQðL)QôL-UL)L)¸f 9L­L-Lr­‰èLðþA¥¥¥^¥¥^vèL\´f9L=LV^èLðLèðLèL!´b èL%´b^CyL-LõLL%zLðþ1^)ìQLLb‰yLL)õLL%zLðþ9¥^¥¥¥¥å!ñL‹ñL)Lo­L)ðLìÄgP-L-ðLnVL-LðL%ˆ‰èLèLèL+´b$èL*´b0èL?´b<èL[´bHèL\´bÇ¥^í^éLðL9­‰¥^ô^ÖLðL=­‰¥^á^ÃLðL­‰¥^Î^°bñLñLèLLLLLLLÍv‰èðaLðLnVLèL^´f$LðL%ˆ‰L€L-­L­LV^€L)­L­LLðL)LŒ­LV‰R¥^H^*LðLLLVL ­LŒ­LV‰¥^ ^¥-LðL-L ­LŒ­LV‰¥¥_¬þÿÿìðRåÏ7V|7WL/`ÐS­7Ý^…èL/7ºÅþå!L/øÅþåèL/gË€ßþåìLìLÑ#e ÐL/.± ÅVLè€f ÓLÒ­è¥rìLìLÑ#e ÐL/­>Åþ+r)L)L)L/¹"Åþ3rìLìLÑ#e ÐL/¬Ú@éþ+r)L)L)LÑ#e ÐL/:ÌÅþã37b[#ÆFÌ7cY#^'XÌ7dW#S7eW#¸57f[#‡ÊM7gW#cÙV7h[#¥i7iY#Q° Â7j[#!n7k[#e Ð7lY#Å¿Å7mZ#–€N7nZ#æ”7oW#Üà?7pY#;»Å7q[#O177rW#\ÀÃ7s[#¹È7tX#!òI7u[#S7v[#áT7wW#•r9&7x[#!Ê|Õ7yW# ÐÇ7z[#7ä.7{W#^'XÌ7|[#i£W7}Y#æ”7~[#&]7[#MR±7€W#œ S7W#ÚáÓ7‚X#üfü7ƒŠLèL!õ7‹VL‹?mªèLí7ŒVLŒ?%¹PèLí7ŽVLŽ?ò57èL‘í7VL?zk35èL“í7’VL’?±Û3èL•í7”VL”?3Dõ¥ÿL€LyL)L!õL€L%zL–LñLèLìL˜í‰èðaLšíLèL)L›vLìL-LœvLLñLñLìLìLŸí‰ìðeèL)L í‰èða)L¤íLLLL L LL®vLìLìLL¹vL»LèL¿íLÁLèLÃí7ÂVLÂ?rëÍÄL LLÆvLÇLèLÈíLñLñLñL)L-LÉí‰)ð2ìL)LÊí‰ìðeèLìLËí‰èðaÌL-L-L-LLLL LLLLÎv LÏL ?>UìÀÏL?Òã[ÌÏL?ˆf!9ÏL?Z?ZÊÏLì?3U=ÏL-?3œTÏL ?1¸¾ÏL? ÉÏL)?ó„ÉÏL?è¯Å ÏL ?×?B/ÏL ?fáÏL?8©–ÏL?÷ÚG;ÏL??³ôÏL?ÃÍ $ÏL ?z2ÏL?Ì<<ÏL?ÙwuÓÏL?Jó.ÏL?èÉÃÏL? ½·ÓÏL?žºÁÏL?SÀ5ÏL? ÜJâRÏÏ7ù7  #O177!#™m%7" #ýK7##58Á7$# Ä>7%#üfü7& #Ø>ã37'#fá7(#€©W7) #ÆFÌ7* #‡ÊM7+ #S7, #¤ S7- #>#÷-7. #7ä.7/#z270#Ú¥A71 #i£W72#æ”73#–€N74 #&]75#3U=76 #MR±77 #’S78 #ÎeK<79#œ S7:<LèL>í7=L=?¤æþØ!L!L!L?zL@LALBLCLDLELFLGLHLILJLìLìLKvL)L)LOvLQLèLTíLUL-?ù‚+UL ?Û°12UL?¢›WUL?VK§ËUL ?ŸÎßîUL?œî1UL ?ô³ÇUL? Ä>UL?5ÂäULì?:ÚïUL ?*VcÂUL?9œãËUL?Hæ>UL ?üfüUL?Ö^¿ÁUL)?.Ûê:RUU7OF7Pù7QQ#!Ê|Õ7RQ#O177SQ#ýK7TN#Å¿Å7UQ#Ø>ã37VP#CÚÚ7WQ#MR±7XQ#Ñ(07YN#œ S7ZcLèL!õ7dMLd?nÓÜ7èL%õ7eMLe?ƒ¥|èLõ7fMLf?§Êç3èLõ7gMLg?~2Õ7èLií7hMLh?ÏÄ7èLkí7jMLj?|5ÄèLmí7lMLl?ñœÄÅèLoí7nMLn?ƒ*=èLqí7pMLp?в¦Ê¥LèL!õ7€ML€?Ç–AèL%õ7ML?‘³êÜèLõ7‚ML‚?«;èLõ7ƒMLƒ?ý?èLõ7„ML„?Ùî-èLõ7…ML…?8gîèLõ7†ML†?ÐÂ=èLõ7‡ML‡?Ÿ”ÌèLõ7ˆMLˆ?‡œz èL õ7‰ML‰?¡éèL õ7ŠMLŠ?!@èL õ7‹ML‹?ìNÔèL õ7ŒMLŒ?¾ ú¥œLèL!õ7ML?œ¼4èL%õ7žMLž?ö¤ïèLõ7ŸMLŸ?iú3èLõ7 ML ?µ¡ŠÝèLõ7¡ML¡?©é¼8èLõ7¢ML¢?½b° èLõ7£ML£?eÍ9èLõ7¤ML¤?4wßèLõ7¥ML¥?"P=èL õ7¦ML¦?ò)èL õ7§ML§?üüÒèL©í7¨ML¨?Ci‹ÝèL«í7ªMLª?ÉnN èL­í7¬ML¬?ˆ‰-ÆèL¯í7®ML®??¢ÁÎèL±í7°ML°?Óq&¥´LèL!õ7µMLµ?ê«!;èL%õ7¶ML¶?L;Ê¥ÊLèLÌí7ËMLË?ÞN+ôèLÎí7ÍMLÍ?ÈÊÉÞèLÐí7ÏMLÏ?‘¦?èLÒí7ÑMLÑ?5ê`*èLÔí7ÓMLÓ?ƒK9çèLÖí7ÕMLÕ?Ã\ÏèLØí7×ML×?‘^ÈóèLÚí7ÙMLÙ?,™ŠóèLÜí7ÛMLÛ?‚›4èLÞí7ÝMLÝ?öÙÛ-èLàí7ßMLß?}´ÉèLâí7áMLá?#oÍÜèLäí7ãMLã?Õ óèLæí7åMLå?:z¹âèLõ7çMLç?Ì鋿èLéí7èMLè?Ø·îèLëí7êMLê?äôÿèLíí7ìMLì?oc|èLïí7îMLî?ÀV/¥ðLÿÿÿÿLñLòLóLôLõLöL÷LøLüLLLLìLìLvLL ?õd'Lì?í"7>L)?ÝË':L-?ð‘§ÎL ?”]UL?Ò¢†8L?N¸áïL?ÄSïL ?òòõøL ?ñòõøL ?_`žñL?‚I4L?ÇšÚêL?œ SL?Å¿ÅR7ù7 #veö7#Å¿Å7 #q·„÷7#î9VÈ7#e Ð7#Ø>ã37 #G97 #ßlYÐ7#ð‘§Î7#ÆFÌ7 #™Ïa17#‡ÊM7L LèL!íL"LñLèL)L)L$v‰èðaìL%íLñLñLìL)LLLL LLLFv‰ìðeèL-L-LLHv‰èðaìL-LLJvLLìLKvLLLì?UJêáLL?™Ïa1LL?ð)ÀLL?ð¶4ÕLL)?-X‹ÈLL?T˜¦ LL-?…›ÂLL?„còLL?üfüR LL6Ý6|6L/`ÐS­7Ò_(èLèðLèL!´b èL%´b^üL-Låþ*^ýL-Låþ*^¥¥åèLèðâ ^^^)^3^=^G^Q^[^e^nL)Låþ"^bL)Låþ"^VL)Låþ"^JL)Låþ"^>L)Låþ"^2L)Låþ"^&L)Låþ"^L)Låþ"^ L)Låþ"^¥å9LìL%zåå9LìLzåå9L)L)Lzrr9LìLzåå9LìLzåå9L)L)Lzrr9L-L-L-LzrrèLèðâ ^^^)^3^=^G^Q^[^e^nL)Låþ"^bL)Låþ"^VL)Låþ"^JL)Låþ"^>L)Låþ"^2 L)Låþ"^&!L)Låþ"^"L)Låþ"^#L)Låþ"^¥å9LìL%zåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9L)L)LzrrèLèðâ^^)^3^=^G^Q^[^e^o^y^ƒ^^—^¡^ª6L)Låþ"^ž7L)Låþ"^’8L)Låþ"^†9L)Låþ"^z:L)Låþ"^n;L)Låþ"^b<L)Låþ"^V=L)Låþ"^J>L)Låþ"^>?L)Låþ"^2@L)Låþ"^&AL)Låþ"^BL)Låþ"^CL)Låþ"^¥å9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L-L-L-Lzrr9L-L-L-L zrr9L)L)L zrr9L-L-L-L zrr9L)L)L zrr9L)L)L zrrèLèðâ^-^7^A^K^U^_^i^s^}^‡^‘^›^¥^¯^¹^Ã^Í^×^á^ë^õ^þ_L)Låþ"^ò`L)Låþ"^æaL)Låþ"^ÚbL)Låþ"^ÎcL)Låþ"^ÂdL)Låþ"^¶eL)Låþ"^ªfL)Låþ"^žgL)Låþ"^’hL)Låþ"^†iL)Låþ"^zjL)Låþ"^nkL)Låþ"^blL)Låþ"^VmL)Låþ"^JnL)Låþ"^>oL)Låþ"^2pL)Låþ"^&qL)Låþ"^rL)Låþ"^sL)Låþ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L-L-L-Lzrr9LLLLLzrr9L-L-L-L zrr9LìL zåå9LìL zåå9LìL zåå9LìL zåå9LìLzåå9L)L)Lzrr9L-L-L-Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)LzrrèQåèôLèðLèL´bèL´b¥^=^9ìQLLìL9ðVR^+¥^#ì*LÌfLìL9ðVR^^R^¥^¥ìô¥rìLìôL9þ"rèLìðL%ˆ‰èðå!ñåìLìLzrîLìLóL%zLóL9LVLÿÿÿÿõåèôLèðLèL´bèL´bB¥^S^OìQðL%´f,ìQQL§´fìQUðL!´f ¥^,^¥^%^¥^^¥^^ìQLèL9ð­R^ ¥^¥¥åèL9­L ­LþÿÿÿõåLìL9­õåìL9­LèLîL-LóL%zLîL-LóL%zL LÿÿÿÿõLVLL=­õõ¥rèðLÿÿÿÿ¸åìLìLVL±LîL-LL%zL÷Vf -L9­^ÿÿÿÿõrèðLÿÿÿÿ¸åèL­L³L)L÷Vf )L9­^ÿÿÿÿõrèQLèðLÿÿÿÿ¸¥åèL­LµL)L÷Vf )L9­^ÿÿÿÿõrèôLèðLÿÿÿÿ¸¥åèLø­LìLVL·L)L÷Vf )L9­^ÿÿÿÿõrìLèðLèL!´b èL%´b^¦¹Löþ)^ìUðL!´fìQLèLˆR^ˆ¥^^ìQL)ULìL!LñVLèLAÄbèLZ¼f)^@)L!LLò­LéVLèL!L-Lí­LALí­ŒLaLí­ˆLô­LäVè¥LèLlˆL-LL9ðVˆR¥¥^¥¥r!LóLLù­L!zåèLÄf%LaLí­L)ˆLô­Lçþ^ èLŒLõþåèLèðLèL!´b èL%´b ^ ½^^¥¥åèQLìôL)ðLìL9­LìˆLĈLL=LLðVˆRåèôLìðLèLĈLL9LL=ðVˆRåèôLèðâ ^^^š__@_h__¤_á_š¿_–ÀLj$ðLþÿÿÿ¸f ÁLLêVLQLúVl^TLèÐL¸f èLð­aèðLw ù´f2ðLLðL%ˆ‰LîL)LõLQL%zFè¥^ ^èL/“°*ö­¥L9­Lïþ2_ÂLj%ðLÿÿÿÿ´f ÁL!LêVULðLèVl^KLèÐL¸f èLð­aèðLw ù´f)ôLLôL%ˆULðL)LëVè¥^ ^èL/“°*ö­¥L9­Lïþ2_”èQLÃLÆL=LLLÅvL-LûVLìVLïþ:¥_gèULÃLÆLLLÆvL-LûVLìVLïþ:¥_=èQLÇL„LLLðæL-LûVLìVLïþ:¥_èQLLL)LðþC¥^ýèQLìULÈLLLðæL-LûVLìVLȈLèLLLLðVˆ¥¥¥^¾èQLìUL)*LìLèðLèL!´bèL%´b¥^;^7¥^Y^/ìUðL!´fìQLLL)LðVLGˆR^4¥^¥^^¥èLÀL„LLLðæL-LûVLìVˆLɈ¥¥L}LLìVLfìLìˆLňLLLLðVˆ^ìLìˆR¥¥¥^¥rèôLèðLèL´bèL´b"¥^;^7ìQLLL)L9ðVR^0¥^ÀLLLL=VˆLÁˆ¥^^¥-L-L-L=þ;¥rèQLìôL)ðLìL9L=LLðVL)zRåèôLìðL9L=L-LðVLìõRåèðL!Äfè_—jLðLèVl_‡LèÐL¸f èLð­aèðLw ù´ge LL9­õL-L-ðL)LëVèL-ôLèðâ ^^^!^4^S^{^˜^±^ä_  _ÁLWLêV_)Lþÿÿÿ‰L9­L ­^ûèQLLL=LÌvLìLûVL­¥^ÚèQLìULìLLL=LÍvL)LûVLV¥¥^°èQLLL=ðæLìLûVL­¥^‘èQLLL)L=ðVL­¥^vèQLìULLL=ðæL)LûVLLL-L=ðVLV¥¥^AèQLìUL)*L)LLL=ðæL-LûVL L LL=ðVLV¥¥¥^¥è¥^ ^èL/“°*öþ)¥rèQL9L=L)Lðþ+¥åèôL9L=L)Lðþ+¥åèðLÿÿÿÿ´f_èôLèðâ ^^^6^7^Q^k^ƒ^—^Ä^â^ßèQLèL¼f)L)LL9­‰¥^½^ºèQLLL=LÏvLìLæþ:¥^žèULLL=LÐvLìLæþ:¥^‚èQLLL=ðæLìLæþ:¥^hèQLLL)L=ðþC¥^RèQLìULLL=ðæL)LæVLL)L=ðþK¥¥^#èULì*LLL=ðæL)LæþB¥¥^¥rÒ7Þ|7ßÝ7àU7áF7âù7ãâ#¢›W7äã#ýK7åß#Å¿Å7æâ#î9VÈ7çà#9лÃ7èâ#€©W7éã#ÆFÌ7êà#!òI7ëâ# ÐÇ7ìã#áT7íã#!Ê|Õ7îã#L(†ß7ïã#7ä.7ðâ#–€N7ñâ#æ”7òã#MR±7óã#-zK7ôã#Ñ(07õã#ÎeK<7öß#Üà?7÷ß#æ”7øà#üfü7ùß#Ò9WÊ7úß#œ S7ûþLèL!õ7ÿÞLÿ?†§™ÔèL%õ7ÞL?"š¥ LèL!õ7 ÞL ?Vñf9èL í7 ÞL ?—ÂâèLõ7ÞL?ÀdÞèLí7ÞL?â‹×èLí7ÞL?$ÐèLí7ÞL?[NÁèLí7ÞL?nþ4èLí7ÞL?Kp»7èLí7ÞL?ÅN¬?¥$LèL!õ7%ÞL%?È©ÕèL'í7&ÞL&?û°½7èL)í7(ÞL(?žj èL+í7*ÞL*?¨„¾+èL-í7,ÞL,?E”ÏêèL/í7.ÞL.?JEA èL1í70ÞL0?ü¡àèL3í72ÞL2?#©{!èL5í74ÞL4?  r¥DLèL!õ7EÞLE?Åb èL%õ7FÞLF?}ëwèLHí7GÞLG?Õ¯†îèLJí7IÞLI?h…ŠÍèLLí7KÞLK?‚d¤<èLNí7MÞLM?-Í;ÝèLPí7OÞLO?{ÔÎôèLRí7QÞLQ?l»ÓðèLTí7SÞLS?±nßèLVí7UÞLU?µœèLXí7WÞLW?!vüèLZí7YÞLY?ªÌÊèL\í7[ÞL[?§}«èL^í7]ÞL]?à[¶ ¥tLèLví7uÞLu?o¸…óèLxí7wÞLw?Y4$ÞèLzí7yÞLy?âVèL|í7{ÞL{?ÿ; èL~í7}ÞL}?ÆS»)èL€í7ÞL?¥,·ÎèL‚í7ÞL?ó‚Ç7èL„í7ƒÞLƒ?Qý?èL†í7…ÞL…?ŒÛ:%èLˆí7‡ÞL‡?´Ø'ÜèLŠí7‰ÞL‰?žñZ(èLŒí7‹ÞL‹?¸„ÀèLŽí7ÞL?ÀÀ7èLí7ÞL?EeèL’í7‘ÞL‘?\PC3èL”í7“ÞL“?.¶+èL–í7•ÞL•?QK,èL˜í7—ÞL—?G Æ7èLší7™ÞL™?âK7èLœí7›ÞL›?^#èLží7ÞL?½åò¥ŸLñLèLìL í‰èðaèL¡íL¢L£L¤L LÿÿÿÿõLèL¥íL¦Lì­L§L)­L¨L-­L©L­LªL­L«L­LîL¬LóL%zLóLLîL LõLîL LõLóL%zL%zLVLÿÿÿÿõLVLÿÿÿÿõLñLèLìL­í‰èða L®íL L¯íLìL L°vL L²íLL´íLL¶íLL¸íLñLèLìLºí‰èða»L¼L¾LñLñLñLñL-LLLLLÊv‰-ð2)L-LLËv‰)ð2ìLL-LÎv‰ìðeèLL)LÑv‰èðaÒL?E¾gÖÒL??ºÊâÒL?|ð‚êÒL ?1ˆÏÒL ?7uÓÞÒL ?Ó×ÜÒL?dœ– ÒL?QÜ7ÖÒL?}âÊÆÒL?ÁU6ÖÒL?{’ÕÒL?M ÓÒL?F$ûÒL?šsÒL-?3Ç-öÒL?ã¢ÒL?”]UÒLì?Ø!0ÒL?.ëŠÒL?.æÁÞÒL ?.êïÒL?’ðB%ÒL ?žwßïÒL?^_ÒL?Úê¨ñÒL?k \ÒL?SøpÒL?.¾ ëÒL?Ÿ‰ôÒL)?‹!!ÒL?âÀ~(RÒÒ6 L/`ÐS­7 _.=èLèðâ^^^%^/^9^C^M^V_L)Lþþ"^J`L)Lþþ"^>aL)Lþþ"^2bL)Lþþ"^&cL)Lþþ"^dL)Lþþ"^eL)Lþþ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9LìLzåå9LìLzåå°LìLþþå9L)L)LïZg6zrrìLìLtVL8ærèåèLèðâA^…^‡^‰^‹^^^‘^“^•^—^™^›^^Ÿ^¡^£^¥^§^©^«^­^¸^Ã^Ò^Ô^Ö^Ø^Ú^à^â^í^ø^ú^ü^þ______ _ __________ _"_$_&_(_*_,_7_9_;_=_?_A_L_M!_I!_E!_A!_=!_9!_5!_1!_-!_)ÿÿÿÿ_%!_!!_!_!_!_ÿÿÿÿ_ þÿÿÿ_ ÿÿÿÿ_!_%^ýèQL!L쌥^ðèQL!L쌥^ãèQL!LìL%ˆŒ¥^Ò!^Î!^Ê!^Æá^Â!LáŒ^º!^¶èQL!L쌥^©èQL!L쌥^œ!^˜!^”!^ÿÿÿÿ^Œÿÿÿÿ^ˆÿÿÿÿ^„ÿÿÿÿ^€ÿÿÿÿ^|ÿÿÿÿ^xÿÿÿÿ^tÿÿÿÿ^pÿÿÿÿ^lÿÿÿÿ^hÿÿÿÿ^dÿÿÿÿ^`ÿÿÿÿ^\ÿÿÿÿ^Xÿÿÿÿ^Tÿÿÿÿ^Pÿÿÿÿ^L!^H!^Dÿÿÿÿ^@!^^`^u^‰_6_J_x__¢_O_ _>_S_h_}_«_ß_e_§LLL9ðæL)LJþ:_*LLLL9ðæL-LJVLìF¥_lLLL9ðæL)LJþ:_ULLL9ðæL)LJþ:_?èQððL!´g`èQðQðL´gOèQðQQL´fèUðL%´fèUQLìUULôLÀf:LLLL9ðVLL9L”vLìLVL*L)Lü­ŒF^8LL9L•vLìLVLLLL9ðVL*L)Lü­ŒFR_ˆ¥¥^^^^èQðQQLìULìL–¸fLLL9ðæLLJVR_P^R^¥¥èQðQQL–´f\èUðL%´fNèUQLìUULLL9L—vLìLVLLLL9ðVL*L)Lü­ŒFR_襥^^^^ ^^^^èQLìULLL9L˜vLìLVLLLL9ðVL*L)Lü­ŒF¥¥_LLL9ðæL)LJþ:_zèQL-Ìf™L-Lô­L=VLL9LšvLìLþB¥_JLLL9ðæL)LJþ:_3LLL9ðæL)LJþ:_èQLì*LL*LáˆFL4L*L*L%zF LLLL9ðVL*LáŒFL*LèðLèL!´b èL%´b^›L?LV^ ìULè¥^¥¥F L*L%ˆFLLL-L9ðVL*L%ŒF¥¥_mèQLìULìLü­L*LLùF L*L-ˆFLLLL9ðVL*L-ŒFLìF R¥¥_èQLœ´fèULì*LñLèLìLí‰èða)Lì­LèfL*L%ˆFLLLL9ðVL*L%ˆFLLLL9ðVL*L)f^%ŒFRR_˜¥¥^^LLL9ðæL)LJþ:_zLLL9ðæL)LJþ:_cLLL9ðæL)LJþ:_LLLL9ðæL)LJþ:_5èQLìULLLLL9ðVLLL-L9ðþ\¥¥_èQLL*LˆFLL9LžvLìLVL*LŒF¥_ÏèQLÌfŸL-Lô­L=V¥_³^¥^¥èQLð*LìL#Vf LìˆL-Lô­L=V¥_ƒ^¥^¥èQL*Lã­L*LALùLzLð*L)L)L þS¥¥_GèUðL%´frèUUðL!´fbèQLìUQðL)UQôL-*LLô­LLLL-LL¡LLL,VõLLL.VõL9ðV¥R^Û¥¥¥¥^^^^èQLìUL)*LLLLL9ðVjL­L0­!l^*LèÐL¸f èLò­aèðLßUD´f%^ ^èL/“°*ö­¥LL*L)ˆFLìLL9L¢vL-LVìLèðLèL!´b èL%´b^^ìQL L LL-L9ðV¥^¥¥L*L)ŒF¥¥¥¥^¥rìLèðâ ^^^)^3^=^Q^s^•_·_À-L/L9þ2_´-LFL9þ2_¨-LGL9þ2_œ-LL9þ2_èQLLìLÿ­L9þ:¥_zèQLLL)Lâ­L=VL ­L9þ:¥_VèQLLL)Lö­L=VL ­L9þ:¥_2èQLèLèLèL¤´b@èL¥´bNèL¦´b\èL§´bjèL¨´bxèL©´b†èLª´b”èL«´b¢èL¬´b°¥^Ã^¿L!Lÿ­L9V¥^À^ªL%Lÿ­L9V¥^«^•LLÿ­L9V¥^–^€LLÿ­L9V¥^^kLLÿ­L9V¥^l^VLLÿ­L9V¥^W^ALLÿ­L9V¥^B^,LLÿ­L9V¥^-^LLÿ­L9V¥^^¥èLLìLN­L9þJ¥¥¥_èQLj¾ULLVLèL *Èfuj*L LVl^QLèÐL¸f èLò­aèðLw ù´f/ *L L *L%ˆF L *L L-LVFè¥^ ^èL/“°*ö­¥L LìL÷­L9V¥^0 *LìŒL LìL!´fV^ìL%´fX^ìL"­L9V¥¥l^HLèÐL¸f èLò­aèðLw ù´f&L)LU­L=VLLìL ­L9V¥^ ^èL/“°*öþ9¥¥^¥rèLE­Lèðâ^^ ^_ ^_4_Æ_ÄèQðLèL´bèL´bâ¥_­^äìQQLjŽULLVLèL *Èfmj*L LVl^QLèÐL¸f èLò­aèðLw ù´f/ *L L *L%ˆF L *L L-LVFè¥^ ^èL/“°*ö­¥LèLg­¥^èLi­¥l^@LèÐL¸f èLò­aèðLw ù´fL)LU­L9VLèLk­¥^ ^èL/“°*ö­¥R^ä¥^ r¥^Ú^¥^ÅèQLìULLL-L=ðVLHLVèLm­R^«¥¥^–èUððL!´fGèUðQðL´f6èQLìUðQQLLL-L=ðVLHLVèLo­R^_¥¥^^^^èQLìULLL)L=ðVLHLVLL-L=ðVLHLVqR^¥¥^®L)Lô­Lþ*¥rèLèðâ^^%^@^T^h^|^†^èQL-LìL­L9þ2¥^yèQL-L*L)ŒLI­L9þ2¥^\èQL-LìLê­L9þ2¥^FèQL-LìL­L9þ2¥^0èQL-LìLà­L9þ2¥^)L*L9þ*^)LøL9þ*^¥rèLèðâ^^%^@^T^h^|^Ÿ^¨èQL-LìL÷­L9þ2¥^’èQL-L*L)ŒL"­L9þ2¥^uèQL-LìL ­L9þ2¥^_èQL-LìL<­L9þ2¥^IèQL-LìL=­L9þ2¥^3)LHL9V)LL"­L9V)LLL9þ*^)LL9þ*^¥rìLèLèL²´bxèL³´bèLl´bŠèL´´b“èLµ´bœèL¶´b¥èL·´b®èL¸´b·èL¹´bÀèLº´bÉèL»´bÒèL¡´bÛèL¼´bäèL½´bíèL¾´böèL¿´bÿèLÀ´c¥__LWL9V¥__L3L9V¥_^òL L9V¥^ð^âL:L9V¥^à^ÒLäL9V¥^Ð^ÂL$L9V¥^À^²L?L9V¥^°^¢LCL9V¥^ ^’LðL9V¥^^‚LTL9V¥^€^rL L9V¥^p^bL-L9V¥^`^RLìL9V¥^P^BL^L9V¥^@^2L1L9V¥^0^"LL9V¥^ ^LëL9V¥^^¥ÁL)L=þ2¥r-LèLèLœ´bqèLôb“èLÄ´b¾èLÅ´béèLÆ´cèLÇ´cèLÈ´coèLÉ´cÅèLÊ´cèLË´cqèLÌ´cÇèLÍ´cèLδcsèLÏ´cÉèLдcèLÑ´cu¥_Ð_ÌLL9VLLLL=ðVLìLV¥¥_„_£LLL=ðVLLæLLLL=ðVLì­¥¥_R_qLLL=ðVLLæLLLL=ðVLì­¥¥_ _?LHLV*LLL9VLLìLVL*L-ŒLI­LVLHLVLLL=ðVLL!LLè­LŒLVLLVLìLVL!L"­LVL%L­LVR¥__ LHLV*LLL9VLLìLVL*L-ŒLI­LVLHLVLLL=ðVLL!LLè­LŒLVLLVLìLVL!L"­LVL%L­LVR¥_â_LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_…_¤LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_(_GLL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_Ë_êLL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_n_LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥__0LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_´_ÓLL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_W_vLL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_ú_LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_^¼LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_@^_LL9VLLìLVLHLVLLL=ðVLL!LLè­L%ŒLVLLVLìLV¥¥_ã^¥-L-LzLèðLèL¡´bèL¼´b‰èL³´bü¥_…_ìQððL!´f0ìQðQðL´fLLL=ðVLQLV¥_^^^^ìôððL!´f1ìôðQðL´fLLL=ðVLQLV¥_H^¥_^¥_ _ìQððL!´f0ìQðQðL´fLLL=ðVLDLV¥_^^^^ìôððL!´f1ìôðQðL´fLLL=ðVLDLV¥^Î^¥^—^¥^‘^ìôððL!´f}ìôðQðL´fkìôðQQL!´fXìQððL!´fGìQðQðL´f4ìQðQQLLLL!LŒL2­L!­õL=ðVR^W¥^¥^^¥^^¥^^¥^ ^¥^^¥LLL=ðVLHLVLLL=ðVLLLþ[¥¥r9L9*L%ˆF9L9UL)L9*LVFå9LìL-L%þ+r9LìL­L=Lô­LV9LHLþå)ôLLB­LULL;­L!L*L*L!L*LùLùLùLLB­L * L* LðzLèLÓíL-LVè*LìLLL9ðVìL)*L-*ŒL ­L=VìLìLLô­LVìL­ìðUL­L)ðL4L* L-LLü­LQzLðQL%zF)ðULìLÿÿÿÿLZVLV)*L!¼fZ)*LLýVLèLÔíL*LVLLL=LÕvLìLéVL)L ­L=VL*Lç­L=þJ¥^LìL ­L=þBRrèL)õLèððL%´fSèôðL%´fFèðQLìðUL)ôQL-ôUL-L)L)VL!´f)LìL9ðVR^^R^¥¥¥¥^^^^ìL-õ¥r9*Lì¸f9L9*L)ŒL­L=V9L L=þåèLáŒLèL9*Äf9L9*L)ŒL­L=V9*LìÄf9LHL=V_íÿÿÿ9Læ¥åLì­9LHL=V9LãLß­LLV9L%LO­L=V9LæL0þå)LèðLèL!´b èL%´b^i4LLã­LùL%z^UìQL)ULL9´f"4LLã­LLùL!L=ðVL%z^èL4L-LL%zLL%ˆL=ðþS¥¥^¥¥r9LHL=V9LL)Lðþ#å9LL)L=ðV9LHLþå9LL)L=ðV9LHLþå9LL)L=ðV9LHLþåìL-õLèðLèL×´bGèLØ´b„èLÙ´bÁèLÚ´bþèLÛ´c;èLÜ´cxèLÝ´céèLÞ´cZèL´cèL–´c¥_s_oìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLåL=VR_¥^¥_5^¥_/_+ìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLõL=VR_Y¥^¥_ñ^¥_ë_çìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLL=VR_¥^¥_­^¥_§_£ìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLL=VR_Ñ¥^¥_i^¥_c__ìôðL%´f7ìôUðL!´f&ìôQLLL)L9ðVLL=VR_¥^¥_%^¥__ìôðL%´fkìôUðL%´fZìôUUðL!´fGìôQL)ôUQLLL-L9ðVLHL=VLL)L9ðVLML=VR_¥¥^¥_³^¥_­^¥_§_£ìôðL%´fkìôUðL%´fZìôUUðL!´fGìôQL)ôUQLLL-L9ðVLHL=VLL)L9ðVLL=VR_¥¥¥^¥_;^¥_5^¥_/_+ìôðL%´g”ìôQððL!´g„ìôQðQðL´grìôUðL!´gcìôQðQQLj ð*LL@Vl^6LèÐL¸f èLò­aèðLw ù´fßL)ˆLLV^ ^èL/“°*ö­¥L*LñLèLìLàí‰èða*Lã­L-ôL)VLèðLìôL L=LávL)Lã­LV L=LLâvLìL]VLQL *Äf L *LQŒL­L=VQL *¼f LHL=V_êÿÿÿ LFULèðLèL!´b èL%´b ^3L4LLæL *L%zF^ìQLLìLû­L=V¥^¥¥ L=L LLLävLìLVRR_¥^^^^ ^^^^åL-LV¥_â_~ìôðL%´g ìôQL)ôULèLü­LèLxL *Œ¼fèL¼foèL LñLèL)L)Læv‰èðaLLæL4LLL%zLùL!LVL]VLVL L LçL4LLùL%zL LðVR^môLÀf4LLL9ðVL=L9LèvL)LVLìLK­L=V^2L9L=LévL)LVLLL9ðVLìLK­L=V¥R^Ó¥¥^¥^i^eìôðL%´fVìôQL)ôULL9L=LêvLìLVLL-L9ðVèLü­LèL!¼fLìLæ­L=V¥R^p¥¥^¥^^¥L9L=LëvL-LVLLß­L-LVf#L-Lü­L*L*ŒL5VL=þB^L-Lü­LO­L=þB¥rèLèðLèL!´b èL%´b^À›L Lþ*^´ìUðLèL!´bèL%´b#¥^z^v)QL9L=L)LðVR^†¥^[)UQððL´fG)UUðL!´f4)QL-UQL9L=L-LðV9L=L)LðVR^;¥¥^¥^ ^¥^^¥ìQL)UL9LL-LðVèLðþ1¥¥^¥¥å9LL)L=ðV9LHLþå9LL)L=ðV9LHLþåèôLìðLìLèðLèL!´b èL%´b^#9LGL=V^ìQL9LL)LðV¥^¥¥9LHL=V9L9UL)L9*LVFRå9*Lì¼f9L9*L)ŒL­L=V9L L=þå9ðL!¼f69L9ðL%Œ‰=*Lì¼f=L=*L)ŒL­LV=L Lþå9ðL!¼f69L9ðL%Œ‰=*Lì¼f=L=*L)ŒL­LV=L LþåèôLìðL9LHL=V9LL-LðV9LìL­L=V9LVL=þ*RåLìþåèôLìðL9LìL-LP­L%þ3RåèL9L=æõåèôLìðLìLAL)VL!´fLìþ!RååèôLìðLìLèðLèL%´b èL!´b(^)ìQLL­9L=L)LðV9Læ¥^ý^¥¥RåLìþåèôLìðL9LVL=V9LHL=V9LL)LðV9L-L=VìLL9LæõRåèôLìðLLì­9L=LL4LLùL%zL'­õLðV9LæRåLìþåèôLìðLL)L9VèLèðâ^)^;^»^Ï^ö_È_h_‚_€_'___M_Õ_„ _û _" _ _Ì _ èQLLìLL=þS¥_ö èQðL!´fLGLV_à ^^èQLUL*LñLèLLLLLív‰èða-Lì­ìL*ÄfL*L-ŒL­LVL)LLVL-FR¥_t èQLLL)LðþS¥_^ èQLìULLL-LðVLìL<­LþR¥¥_5 èUðL%´gèUUðL%´gèUUUðL%´g{èUUUUðL%´ggèUUUUUðL%´gQèUUUUUUðL%´g9èQLìUQL)UUQL-UUUQLUUUUQLUUUUUQLUUUUUUQLUUUUUUULLèððL!´f&èðQðL´fèðQQL´f^^^ ^^^^¥gLîLß­L!­õL L LLß­L!­õL4LL4L L4L L4L L4L L4L L L%zL%zL%zL%zL%zL%zL9VõLLèððL´f¿èðQLìðUL)ôLULìLïL­L!­õLLLL4LLP­LïõLùL%zL+­õLðVLLLL4LLLLóVõL4LL4L LùL%zL%zL%zL9VõLðVL%L­LVL)FRR^R¥¥¥^^LL LL4L L4LLRL!­õL4LLùL%zL%zL%zL9VõLðV¥RR_¼ ^R^*¥¥¥¥¥¥¥¥^^^^^^^^ ^^^^èQððLèL!´bèL´bF¥^±^­ìQðQðL´f-ìQðQQL)ULLL-L-LLVR_B ¥¥^¥^s^oìQðQL)QðUL-ULLLLðvLìLVLLLðVLHLVL)L<­LVLìLü­Lú­LVR_Ñ ¥¥¥^¥èQLìULLLLñvLìLVLL-LðVf"LìLü­L*L*ŒL5VLþR^LìLü­LO­LþR¥¥_a èUððL!´f[èUðQðL´fJèQLìUðQQLLL-LðVLìL!´fí^ìL%´fï^ìL=­LVR_ ¥¥^^^^èQLìULLL-LðVLHLVLL)LðVLLLþR¥¥_¿èQLLLLòvLìLþJ¥_£è*ðLèL!´b èL%´by^èìQL)ULL­LôLÀf LYLVLLLðVLLæLL­L LLLðVèL ­ L-L VèL ­L)þiR¥¥^tìQL)ULL­LôLÀf LYLVL­LLLLðVèL ­LLLðVL)L L­ŒL­LVèL þaR¥¥^¥_£èQLìUL)*L*LLLLðVLLæLLLLðVL)LLV)LèðLèL!´b èL%´b ^BL-þq^:ìQL L æLL­ L L-LðV LL LVLìþ¥¥^¥¥R¥¥¥_úèQLìUL)*LL æLL4L *L *L%zF LLLðVL LVL*LèðLèL!´b èL%´b^›LLV^ ìULè¥^¥¥F L æLL)­LHLVUL L ULL *LVF L LLðV L%L­LV LìFL)þiR¥¥¥_èQLìULL)L)Lþ[¥¥_èQLìUL)*LL LLLLL L zL/žºÁþc¥¥¥_ÎèQLèLèðLèL!´b èL%´b^2LGLV^&ìQLL*LùL)VL!´L)LðV¥^¥¥*LLLóvL*LVL*L*ŒL ­LVLìF¥¥_DèQLèLèðLèL!´b èL%´b^^ìQLLL)LðV¥^¥¥*L*Lü­L*ŒñLèLLLôvL*LV*L*¸fL*L*ŒL­LVL)FL4LL L æõL * L%zF R¥_“*L*Lü­L*ŒñLèLLLõvL*LV*L*¸fL*L*ŒL­LVL)FL4LLL æõL* L%zF R_èQLìULLL-LðVLL)Lðþ[¥¥_ñèQðL!´fLGLVLLV_Ñ^^èQL&LEL)L]VL7VLj ðôLL@Vl^ULèÐL¸f èLò­aèðLw ù´f3LöLðôLñ­ˆLU­LVLðôL-L)L Vè¥^ ^èL/“°*ö­¥LLìL ­LVLLVLHLVLLL÷vL-LVL%L­LþZR¥_èQLj ð*LL@Vl^2LèÐL¸f èLò­aèðLw ù´f›LßLV^ ^èL/“°*ö­¥L*LìQ¸b*Lã­LìôL)VL!¸f4øLìQL*Lã­L[­L-ôL[­L *zL6VLLVùLì*LVèLùFèLL­LP­F¥¥_CèUðL%´ffèUUðL!´fVèQLìUQðL)UQôL-*LLLLL¡LLL,VõLLL.VõLðVR_㥥¥¥^^^^èQLìUL)*LjÐL­LèðLìôLLL LðVLìL­LVèLALýVLèLúíL-LVL LûvLìLVLüLìLéV LèðLèL!´b èL%´b^$LGLV^ìQLLL)LðV¥^¥¥L æLLLL LþvL)LVLL)­ÿLìLéVRl^îLèÐL¸f èLò­aèðLßUD´fÌLLLðVLHLVLLLLvL-L]VL)LèðLèL!´b èL%´b^9 LGLV^-ìQL L L L4LLùL%zL'­õLðV¥^¥¥L æL L LLL LvL)L]VLL)­LìLV L%L­LVR^ ^èL/“°*öþY¥¥¥¥^¥RrèULìQL)ôL-ðL9UL-L=L­LLZVLîVèL=LVìLLþ:Rå9LìL-õLþ"rèôL)ôLèL)ŒRr9L=L ­LV9LHLV9LìL­LþåèôLìðL9LGL=V9LL=V9L)Lê­L=V9L)L=LvLìLþ*RåL­LùLLB­LL­LL­LLB­LL­zL)LLB­LL;­LL;­L!L!L!L!LÿÿÿÿLùLùLùLLB­L!L!õLL zL-LÀfìULL­LVèLLLL9VèLLL=VèL­ìQLùL)VL!¸b ìôLñ­L!¸f¬èQLì* LLB­LLB­LLìF L)FL!Lû­LVL)L)LvLQLã­LVìL!L-L­Lû­LîVLB­LèLíLôL>VLìLVLL vLìLéV-L)LVL-LVRìULìð*L)* L(VLVèQL)UõRr 7ÓÝ7Ô|7ÕU7Öœ7×L/`ÐS­74_KèLèðLèL!´b èL%´b^„L-Lþ*^L-Lþ*^¥¥å9LLLLLL%zrrèLèðLèL%´b èL!´b^ì*Lè¥^!^¥¥å-L-L-L-LL9­LL9­LVL%ˆLþMr-L9­LìL9­LìLìLˆ¼fèLèðLèL%´b èL!´bÂ^ËìQL)UL-*L*L-L9­LìL9­Àf"-L-L-L-L L L L=VL=þ„^qèLèðLèL%´b èL!´bN^WìQL)UL-*L*LLLLL=VL-L-L-LLLL=VL=þ´¥¥¥¥^L;Lþ‚^¥¥¥¥¥¥^L=LþR^¥¥_èL)Lˆ¼fé)LèðLèL%´b èL!´bÃ^ÌìQL)UL-*L*LèL9­LL9­Àf" L L LL=VL-L-L-L=þ„^r-LèðLèL%´b èL!´bN^WìQL)UL-*L*LLLLL=VL-L-L-L L L L=VL=þ´¥¥¥¥^LFLþ‚^¥¥¥¥¥¥^LHLþR^¥¥^!LLLLLLVL%ˆLþ]RrèLèðLèL%´b èL!´b9^?ìQðL!´fìUL)*LèL)õR^$¥¥^^ìQLèL9ðþ)¥^ Lþ!^¥¥åèLèðLèL%´b èL!´bQ^WìQðL!´fì*LèR^F¥^^ìQL)UL-*L*L-L9ð­L-L-L-L=þ\¥¥¥¥^  Lþ!^¥¥åèL)õLèððL!´fì^;^^èôðL!´f)^*^^ìL9­LèðLìôLL)L)LL=­LþTR¥rLìõåLõåèôLLVL!´åèLèðLèL%´b èL!´b^¢ìQL)UL-*L*L*L9LL=VLèL!´fL9LLLLþu^@èL!ÄfLð­LèLLLLþt¥^)Lð­LLLL-Lþt¥¥¥¥¥¥¥^L9LLL%LþE^¥¥å)ðLñLèLL-LLL9L&v‰èðaôLì­L)õRrèLèðLèL%´b èL!´bR^XìQL)UL-*L*L9L-L=VLèL!Äf Lðæ^èL!¼f ìLðæ^)¥¥¥¥¥^ Læ^¥¥åìðLñLèL-L-L-L(v‰èða-ôLìæRrèLèðLèL%´b èL!´bw^xìQL)UL-*L*L9L-L=VLèL!´fL)LþR^7èL!ÄfLð­LLLLþd^LLLLð­Lþd¥¥¥¥¥^^¥¥åìðLñLèL-L-L9LL=L*v‰èða-ôLì­L)õRrèLèðLèL%´b èL!´bH^HìQL)UL-*L*L9L-L=VLèL!´bèL!Äf^ìLðþI¥¥¥¥¥^^¥¥åìðLñLèL-L-L-L,v‰èða-ôLìþ)RrèLèðLèL!´b èL%´b^;^8ìQL)UL-*L*L-L9ð­)L)L=VèL9ðþA¥¥¥¥^¥¥åñLèLìLL.v‰èðaìôLìþ!¥rèLèðLèL!´b èL%´b ^U^QìQL)UL-*L*L*LL9ð­L)L9ð­LìLLL=æL-LLþ}R¥¥¥¥¥^¥¥åñLèLìLL0v‰èðaìôLì­L)ðõ¥rèLèðLèL!´b èL%´b ^>-^:ìQL)UL-*L*LLL9ðæL)L=æLìL9ðæ¥¥¥¥^¥¥rñLèLìLL2v‰èðaìL-ôL)æ¥r47 ù7  #¥i7 #ýK7 #e Ð7 #&]7 #ÆFÌ7 #¶’¥ê7 #ÎeK<7 #¤ S7LèL!õ7 L?mªèLí7 L?"6ã3¥LèLíLìLìLvLñLñLìL)Lí‰ìðeèLìLL!v‰èðaìLìLL"vL#L$L%LL'íL)LLL+vL-L/L1L3L4L ?x 4L?Dœˆ4L ?XØß4L ?¸¢Æ4L)?œ S4L ?î9VÈ4L-?Å¿Å4L?8©–4L?çL4Lì?\ÀÃ4L?9лÃ4L?Üà?4L?:Úï4L?üfü4L ?ͱJ4L?!òIR447ØF7Ú7ÛL/`ÐS­7Q_¸ èLèðâA^…^^™^£^­^·^Á^Ë^Õ^ß^é^ó^ý____%_/_9_C_M_W_a_k_u__‰_“__§_±_»_Å_Ï_Ù_ã_í_÷__ ___)_3_=_G_Q_[_e_o_y_ƒ__—_¡_«_µ_¿_É_Ó_Ý_ç_ñ_û__hL)L?þ"_iL)L?þ"_öjL)L?þ"_êkL)L?þ"_ÞlL)L?þ"_ÒmL)L?þ"_ÆnL)L?þ"_ºoL)L?þ"_®pL)L?þ"_¢qL)L?þ"_–rL)L?þ"_ŠsL)L?þ"_~tL)L?þ"_ruL)L?þ"_fvL)L?þ"_ZwL)L?þ"_NxL)L?þ"_ByL)L?þ"_6zL)L?þ"_*{L)L?þ"_|L)L?þ"_}L)L?þ"_~L)L?þ"_úL)L?þ"_î€L)L?þ"_âL)L?þ"_Ö‚L)L?þ"_ʃL)L?þ"_¾„L)L?þ"_²…L)L?þ"_¦†L)L?þ"_š‡L)L?þ"_ŽˆL)L?þ"_‚‰L)L?þ"_vŠL)L?þ"_j‹L)L?þ"_^ŒL)L?þ"_RL)L?þ"_FŽL)L?þ"_:L)L?þ"_.L)L?þ"_"‘L)L?þ"_’L)L?þ"_ “L)L?þ"^þ”L)L?þ"^ò•L)L?þ"^æ–L)L?þ"^Ú—L)L?þ"^ΘL)L?þ"^™L)L?þ"^¶šL)L?þ"^ª›L)L?þ"^žœL)L?þ"^’L)L?þ"^†žL)L?þ"^zŸL)L?þ"^n L)L?þ"^b¡L)L?þ"^V¢L)L?þ"^J£L)L?þ"^>¤L)L?þ"^2¥L)L?þ"^&¦L)L?þ"^§L)L?þ"^¨L)L?þ"^¥å9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìL zåå9LìL zåå9LìL zåå9LìL zåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìL8zåå9LìL9zåå9L)L)L?zrrèLèðâ^^^#^-^7^A^JL)L?þ"^>L)L?þ"^2L)L?þ"^&L)L?þ"^L)L?þ"^ L)L?þ"^¥å9LìL!zåå9L)L)L%zrr9LìLzåå9LìLzåå9L)L)Lzrr9LìLzååLìL?þåèØåèLèðâA^…^†^‡^ˆ^‰^Š^‹^Œ^^Ž^^^‘^’^“^”^•^–^—^˜^™^š^›^œ^^ž^Ÿ^ ^¡^¢^£^¤^¥^¦^§^¨^©^ª^«^¬^­^®^¯^°^±^²^³^´^µ^¶^·^¸^¹^º^»^¼^½^¾^¿^À^Á^Â^Ã^Ä^Å^Å^Â^¿^¼^¹^¶^³^°^­^ª^§^¤^¡^ž^›^˜^•^’^^Œ^‰^†^ƒ^€^}^z^w^t^q^n^k^h^e^b^_^\^Y^V^S^P^M^J^G^D^A^>^;^8^5^2^/^,^)^&^#^ ^^^^^^^ ^^^¥åèLèðâ^ ^^^^^^^^^^ ^‹^^^__{_yèQLèL9­Lj+=LLBVLèL¸fLˆLˆLìˆLf­¥l^?LèÐL¸f èL^­aèðLw ù´f=L)LLZVL-LUV^ ^èL/“°*ö­¥¥¥_¥^üèQLèL9­Lj+=LLBVLèL¸fLˆLˆLìˆLf­¥l^?LèÐL¸f èL^­aèðLw ù´f=L)LLZVL-LUV^ ^èL/“°*ö­¥¥¥^„¥^èQLèL9­Lj+=LLBVLèL¸fLˆLˆLìˆLf­¥l^?LèÐL¸f èL^­aèðLw ù´f=L)LLZVL-LUV^ ^èL/“°*ö­¥¥¥^¥^¥å9L)L=ðLIV=L=ðL)L­f^%ˆ‰rLg­LLA­L9L)L)LvL-LMV!ñL-Lb­L%ˆL!L=VLèL)L=LvLLHVèLLb­L-ðLIVèL)ðLzRå9LìL[V9L!LVþå9ðL!¼f|9ðL¼f)=LLœL¨LYV9L9ðLŒ‰èLðþ^LèLðŒLèL!¼fèLÄfè^!L=LìLœL9ðLœ¨L¨LYV9L!‰LðL)ˆ‰RåèôLìðLèL9ð¸fDìL=­9Lì‰ðf"LìL L%¨LYVLìLÿ¬LYV^LìL%œL%¨LYVìLð¸fìL=­ìLð´fLðL%ˆ‰^]ìLðŒLèL!¼fèL ÄfLìLœL¨LYV^,L-LœLYVL-L LYVL-L  LYVL-‰¥RåìLb­LñLìL€ÄfL)LYV^7ìL€Äf)èL‰L)L L€¨LYVL)Lÿ¬LYV^ !LP­L"íLLMVL-Lb­LDV!ñL!ñL!ñLñLèL)LL-LL#v‰èða-LìLL LLL$vLLMV)ðLìþQRrèLèðâ^^2^b^‰^¬^Ï^çèQL9L%LYV9LìL[V9L!LVþ*¥^ÂèQLìUL9LLYV9L=L-L\VL)Lœ¨LDþ2¥¥^èQL9LLYV9LìLN­LKV9LìL[þ*¥^gèQL9LLYV9LìL[V9L!LVþ*¥^BèQLìUL9LLYV9L)L)Lþ;¥¥^èQL9LLYV9LìLYþ*¥^¥å9LìL[V9L!LVþå9ñLìLèðâA^…^‡^‰^‹^^›^­^»^É^Ü^Þ^ð____-_@_B_P_R_T_b_p_~_¥_Ì_ó___*_8_F_H_J_L_N_P_R_T_V_X_Z_\_^_`_b_d_f_h_j_l_n_p_r_t_v_x_†_”_–_˜_š_œ_ž_»_Â!_¾%_º_¶_²èQL)L쉥_¢èQL)LìLŒ‰¥_ŽèQL)L쉥_~èQL)L쉥_nèQL)LìL=­‰¥_Y _UèQL)LìLŒ‰ ¥_AèQL)LìL=­‰ ¥_,èQL)Lì‰ ¥_èQL)Lì‰ ¥_ èQL)L쉥_üèQL)LìL=­‰¥_ç_ãèQL)L쉥_Ó_Ï_ËèQL)L쉥_»èQL)L쉥_«èQL)L쉥_›èQL)LLL-ˆL\VLLL\VŒ‰¥_rèQL)LLL-ˆL\VLLL\VŒ‰¥_IèQL)LLL-ˆL\VLLL\VŒ‰¥_ èQL)LLL-ˆL\VLLL\VŒ‰¥^÷^óèQL)L쉥^ãèQL)L쉥^ÓèQL)L쉥^Ã^¿ ^»!^·"^³#^¯$^«%^§&^£'^Ÿ(^›)^—*^“+^,^‹-^‡.^ƒ/^0^{1^w2^s3^o4^k5^g6^c7^_èQL)Lì‰8¥^OèQL)Lì‰9¥^?:^;;^7<^3=^/>^+èQLìUL-L)L)Lœ¨‰?¥¥^ ìL@‰!^¥LìðLèL9´fL)LœLYþ:^yìL ÄfèL!´bèL%´fL)LœL)Lœ¨L%¨LYþ:^HèL!ÀfèLÿÈfL)LœL¨LYVLìLYþ:^L)LœL¨LYVLìLDþ:RrèôLìðL-L&L[VìL9­LèðLìôL)QLLLb­LDVL-Lb­LDVLìLDVL)L=L'vLLMVL(íL-LMVLL-LL)vLLHþRRRr9LS­LèL!´f =L_þ^=LìLWVLðþ¥åLO­LñLèL-L-L-L+v‰èðaLìþ!Rå9L=þåèL9´f_Q=L>­LèL%¬L!¸fJðf=L>­LìL% LœL쨥^èL% LèLLb­Àf /LP­Lì‰)Lðþ!¥^ôèL¬L!¸f`èL LìL L¬L!ñLèðL)Äf'LL)ðˆLðLðõLIVèLìðL%ˆ‰_ÕÿÿÿLðLˆ‰L)ˆLðþ1R^‹èL¬L!¸f3LðL)L ˆ‰L)LðLðõLIVìL%ˆLðþ^O=L>­L=L>­LL-L L-Lœ¨L)L œ¨‰LLðLðõLIV-L%ˆLðþ)R¥åèL>­LñLìL€Äfì^èL‰)L>­L)L¬LœL쨥LèL!´f -LP­èLL9L.vLTVLLG­L!ñL!ñL)L!L!õL=VLñLèLL LLLLLLL0v‰èða!Lì­ìLõR å9L>­Lèâ^^^^:^T^b^|^Š^ˆ9L=­L ­^^x9LG­LèLÿÿÿ¬LìL L V¥^c^Z9LF­L9LìLJVL­¥^G^>9L=­L­^7^.9L­LèðLìôLìLìLVR^^9L>­L­^ ^Lcþ¥åèL!´f^r9L=­LèL­Lj LLBVLLì¸f Lc­¥l^ALèÐL¸f èL^­aèðLw ù´fL)LLZV-L%ŒLð­^ ^èL/“°*öþ)¥Rå9LìL\VLèLÿÿÿÿ´f Lc­èL-Œ¥rèôLìðL9L)L9LLQVLèðâ^6^4^2^0^.^,^*^(^&^$^"^ ^^^^^^^^^^ ^ ^ ^)^F^c^€^~èQLLL)ˆL=VLЭ¥^m¥^_èQLLL)ˆL=VLÒ­¥^N¥^@èQLLL)ˆL=VLÔ­¥^/¥^!èQLLL)ˆL=VLÖ­¥^¥^4LSLEV¥LXþ3RåèLèðL%´f1èQLìUL9LL!LL=VL-L VLIVR^ ¥¥^^¥rk¯LLJVLèL&¸f Lc­LG­LLG­LLG­L)L!Äb)Lÿÿ¼bìL!ÄbìLÿÿ¼bèL!ÄbèLÿÿÿ¼f Lc­)L L9L=L2vLTVLLg­LñLèL L9LLLL3v‰èðaLì­-L%ˆLÿÿÿÿL=VL!ñLdñLLA­L)ðLÄgˆL>­LèL¬Lèâ^ ^^-^T^f^dL)L õ^a^UìL L%¬L)L õ^K^?ìL´fLL>­õ^L>­L)L õ^"^LG­L)L õ^^4LüLEV¥LèðLìôLìLèâA^†^Š^Ž^’^–^ž^ª^²^º^ý__ _P_X_`_h_«_¯_·_»_¿_Ç_Ï_×_ý_#_I_o_s_{_ƒ_‹__“_—_›_Ÿ_£_§_«_¯_³_·_»_¿_Ã_Ç_Ë_Ï_Ó_×_Û_ß_ã_ç_ë_ï_÷_ÿ___ ___&_*_(ª_+_"«_%_¬__­__ìL®­__ìLˆL°­__øìL²­_÷_îìL´­_í_äjLLBVl^/LèÐL¸f èL^­aèðLw ù´f Lc­^ ^èL/“°*ö­¥L¶­_¨_Ÿ¸_¢_™ìLˆL¹­_”_‹jLLBVl^/LèÐL¸f èL^­aèðLw ù´f Lc­^ ^èL/“°*ö­¥L»­_O_FìL½­_E_<ìL¿­_;_2ìLÁ­_1_(jLLBVl^/LèÐL¸f èL^­aèðLw ù´f Lc­^ ^èL/“°*ö­¥Lí_ì_ãÅ_æ_ÝìLÆ­_Ü_ÓÈ_Ö_ÍÉ_Ð_ÇìLÊ­_Æ_½ìLÌ­_¼_³ìLέ_²_©L]LLb­LðõLðL%z‰ìLЭ_Š_L]LLb­LðõLðL%z‰ìLÒ­_b_YL]LLb­LðõLðL%z‰ìLÔ­_:_1L]LLb­LðõLðL%z‰ìLÖ­__ Ø_ _ìLÙ­_^ùìLÛ­^ø^ïìLÝ­^î^åß^è^ßà^â^Ùá^Ü^Óâ^Ö^Íã^Ð^Çä^Ê^Áå^Ä^»æ^¾^µç^¸^¯è^²^©é^¬^£ê^¦^ë^ ^—ì^š^‘í^”^‹î^Ž^…ï^ˆ^ð^‚^yñ^|^sò^v^mó^p^gô^j^aõ^d^[ö^^^U÷^X^OìLø­^N^EìLú­^D^;ü^>^5ý^8^/þ^2^)ÿ^,^#^&^ìL¬L)L LV^^^ ^Lc­¥LLðLLb­LIVLðL)L­f^%ˆ‰LìLUVR_sûÿÿ)ðL¸f Lc­-L-ðL)Lb­LIV-L5íLìLìL6vL-ðL@VLìL7vLLHVìLõR l^KLèÐL¸f èL^­aèðLèLÀà´b èLt! ´b^Lc­¥^^Lc­¥^ ^¥èL/“°*öþ¥å9L=L)Lèðâ^^^\^p^€^Ä^ÓèQL.LìLa­ˆ¥^ÁèQLìULìL!ÀfìL=ÄfL)LLIV>L)Le­ˆL?ˆLìLe­ˆ¥¥^‚èQL@LìLa­ˆLˆ¥^lèQLALìLa­ˆ¥^ZèQLìULLL­LèðLìôLìLLLVBLL)­LN­LLb­õL`VR¥¥^èQLCLìLe­ˆ¥^¥LõLRþ+r9LFL)LN­LÀfG^L-LN­ŒL LCVL-L=­LzLRþ#åìLGˆLìLe­ˆr9L)L\Vf =L LVV=LJL-L-Lèðâ:^t^r^p^n^p^ƒ^–^©^¼^b^É^Ü^ë^þ__$^T_1^P^N_@_S_f_y_‘_©_Á^>_×_ê_ý^6^4^2^0^.^,^*^(^&^$^"^ ^^^^^^^^^^ ^ ^^_Þ_ñ__èQLlLìLV¥_ø¥_íèQLmLìLV¥_ã¥_ØèQLnLìLV¥_Î¥_ÃèQLoLìLV¥_¹¥_®èQLKL숥_¨¥_èQLrLìLV¥_“¥_ˆèQLLL숥_‚¥_wèQLtLìLV¥_m¥_bèQLuLìLV¥_X¥_MèQLvLìLV¥_C¥_8èQLML숥_2¥_'èQLyLìLV¥_¥_èQL|LìLV¥_¥^ýèQL}LìLV¥^ó¥^èèQL~LìLV¥^Þ¥^ÓèQLLL)ˆLV¥^Ä¥^¹èQL€LL)ˆLV¥^ª¥^ŸèQLLL)ˆLV¥^¥^…èQL‚LL)ˆLV¥^v¥^kèQL„LìLV¥^a¥^VèQL…LìLV¥^L¥^AèQL†LìLV¥^7¥^,èQL LìLV¥^"¥^èQL¡LìLV¥^ ¥^Le­¥LðzLRVLðL)L­f^%ˆ‰rèôLìðLìL9­LèðLìôL)QLL9LLb­LRVL:LLb­LRVL;L)LLb­õLRVL<LLRVèLL=VLL)L)L=LDvLLHVLELLRVLLGvLLMVLHLLRVIL!ñL)L L-L-LLNvLLHVLOLLRþsRRrQ75Ý7677|78œ79F7: 7;ù7<9#î9VÈ7=7#Ñî17><#ýK7?8#Å¿Å7@9#üfü7A6#9лÃ7B:#î9VÈ7C7#¨æõÜ7D<#ÆFÌ7E7#Çp>7F7#ŸÌ9ü7G9#Q° Â7H<#!n7I7#VK§Ë7J7#ÙtK7K7#q·„÷7L9#Å¿Å7M:#æ”7N;#üfü7O<#ÎeK<7P9#–€N7Q7#™Ïa17R7#ŸWŠ27S9#;»Å7T9#!òI7U7#veö7V;#ô0Û7W9#¢›W7X7#¨ÅÈõ7Y6#!òI7Z7#ßlYÐ7[<#S7\<#!Ê|Õ7]<#7ä.7^;#Ñ(07_<#L(†ß7`:#CÚÚ7a9#æ”7b<#&]7c<#MR±7d<#Ñ(07e<#ÈË)ó7f6#üfü7g©LèL!õ7ª5Lª?HÛØèL%õ7«5L«?!ÐÜèLõ7¬5L¬?ÂDm>èLõ7­5L­?€ÈÜèL¯í7®5L®?NÆ…?èL±í7°5L°?gv)ÇèL³í7²5L²?d]áèLµí7´5L´?L½‚?èL·í7¶5L¶?Ù£±ÃèL õ7¸5L¸?¸|­èèLºí7¹5L¹?1ª2èL¼í7»5L»?‚WÞÁèL¾í7½5L½?fŒñëèLÀí7¿5L¿?…†,)èLÂí7Á5LÁ?‹ù#èLÄí7Ã5LÃ?عyèèLõ7Å5LÅ?·’u èLÇí7Æ5LÆ?0Àú%èLõ7È5LÈ?oÑßèLõ7É5LÉ?ú=:5èLËí7Ê5LÊ?q=èLÍí7Ì5LÌ?¾D“,èLÏí7Î5LÎ?Ä%9èLÑí7Ð5LÐ?ñB1èLÓí7Ò5LÒ?‹¬<èLÕí7Ô5LÔ?H)ZæèL×í7Ö5LÖ? ÂÜ7èLõ7Ø5LØ?HwyüèLÚí7Ù5LÙ?A‘>èLÜí7Û5LÛ?j)èLÞí7Ý5LÝ?«ÄúèLõ7ß5Lß?J°ô+èL õ7à5Là?±× èL!õ7á5Lá?P† äèL"õ7â5Lâ?ª1èL#õ7ã5Lã?`a?èL$õ7ä5Lä?”>3èL%õ7å5Lå?1õ3èL&õ7æ5Læ?¢Î:èL'õ7ç5Lç?V?èL(õ7è5Lè?V?èL)õ7é5Lé?èxn8èL*õ7ê5Lê?CEèL+õ7ë5Lë?·²1èL,õ7ì5Lì?{'CèL-õ7í5Lí?Œ<èL.õ7î5Lî?:ˆ;èL/õ7ï5Lï?M>èL0õ7ð5Lð?xE6èL1õ7ñ5Lñ?¨BèL2õ7ò5Lò?½:èL3õ7ó5Ló?ó;èL4õ7ô5Lô?‘NË èL5õ7õ5Lõ?…@ºÐèL6õ7ö5Lö?î[á/èL7õ7÷5L÷?@ˆ;èLùí7ø5Lø? ¤ƒ8èLûí7ú5Lú?Nõh7èL:õ7ü5Lü?é#ýèL;õ7ý5Lý?ê#ýèL<õ7þ5Lþ?ß@" èL=õ7ÿ5Lÿ?à@" èL>õ75L?Ó\@èLí75L?n?‚ÝèL@õ75L?„Ò2¥ LèL í7 5L ?$‡úèLí7 5L ?»Ç€ èLí75L?´Æ7èLí75L?µ?èLí75L?ÐAèLí75L?Õoë¥LèL»gÁ(õ75L?$<ÑLLLLìLìL vL%LìLìLLL*vL,LèL1íLìLìLLLL8vLLLLLPvLQL?y/^ÝQL?ßlYÐQL ?ï/÷ QL?Ú¥AQL-?pd{ñQL)?VK§ËQL?¯7€7QL?p‡!>QL?IÚ•QLì?4}rÂQL?·äUR QQ7Üù7ÝÜ#¯7€77ÞÛ#ƒ*=7ßÜ#0Àú%7àÜ#ï/÷ 7áÜ#µ?7âÕ#cÙV7ãÜ#¢Î:7äÜ#J°ô+7åÜ#Nõh77æÜ#j)7çÚ#æ”7è×#Å¿Å7éÜ#…†,)7êÜ#½:7ëÜ#:ˆ;7ìÜ#ß@" 7í×#¢›W7îÜ#à@" 7ïÜ#CE7ðÔ#æ”7ñÝ#7ä.7òÛ#5ê`*7óÝ#i£W7ôÜ#ó;7õÜ#´Æ77öÜ#L½‚?7÷Ü#oÑß7øÝ#MR±7ùÜ#Ä%97úÜ#ñB17ûÕ#æ”7ü×#î9VÈ7ýÝ#ýK7þÜ#NÆ…?7ÿÝ#ÆFÌ7Ú#€©W7×#^'XÌ7Ü#@ˆ;7Ü#q=7Ü# ¤ƒ87Û#в¦Ê7×#!òI7Ü#Ó\@7Ü#d]á7 Ü#1õ37 Ü#A‘>7 Ô#!òI7 Ü#{'C7 Ý#>#÷-7Ü#Õoë7Ü#‘NË 7×#æ”7Ü#عyè7Ü#¨B7×#ÚáÓ7Ü#‹¬<7Ü#€ÈÜ7Ø#Å¿Å7Ô#üfü7Ü#H)Zæ7Õ#Å¿Å7Ü#‹ù#7Ø#9лÃ7Ø#!òI7Ü#î[á/7×#œ S7Ü#Hwyü7 Û#ÞN+ô7!Ü#gv)Ç7"Ô#Üà?7#Ü#V?7$Ý#!n7%Ý#¥i7&Û#ÈÊÉÞ7'Ü#ÐA7(Ý#e Ð7)Ü#·’u 7*Û#‘^Èó7+Û##oÍÜ7,Ü#Œ<7-Û#‚›47.Ü#!ÐÜ7/Ý#¹È70Ü#xE671Û#ÏÄ772Ü#`a?73Ý#!Ê|Õ74Ü#n?‚Ý75Ý#L(†ß76Õ#^'XÌ77Ý#&]78Û#ƒK9ç79Ü#”>37:Ø#:Úï7;Ü#Ù£±Ã7<Ü#1ª27=Ô#Å¿Å7>Ü#V?7?Ô#9лÃ7@Ý#Ø>ã37A×#üfü7BÜ#èxn87CÜ#P† ä7DÝ#‡ÊM7EÜ#ÂDm>7FÜ#HÛØ7GÜ#ú=:57HÜ#fŒñë7IÛ#Å¿Å7JÜ#«Äú7KÜ#¸|­è7LÜ#…@ºÐ7MÜ#‚WÞÁ7NÜ#¾D“,7OÝ#O177PÜ#±× 7QÛ#~2Õ77RÖ#œî17SÜ#·²17TÜ#$‡ú7UÜ#é#ý7VÜ#ª17WÜ#ê#ý7XÜ#„Ò27YÜ#»Ç€ 7ZÝ#Ñ(07[Ü# ÂÜ77\Õ#œ S7]Ü#M>7^fLèLhí7gÓLg?u‚_:èLjí7iÓLi?З ÆèLlí7kÓLk?Ûw§'èLní7mÓLm?BÅ(ÃèLpí7oÓLo?šË©èLõ7qÓLq?!ž$èèLõ7rÓLr?Ö>ã¥sLèLuí7tÓLt?¨;WvLwLxL)LzíL{L|L-L}íL)LìLvL-L)LvLL-LƒvLLL„vL…L†LˆLŠL LíL‘L“LñLèLìLLL£v‰èða LL­vLñLñLñLñLñLñLñLñLLL)LLL¯v‰ð2LL°í‰ð2LL±í‰ð2LLLÂv‰ð2-LL)LLLL L LÒv‰-ð2)LìLLLL LÖv‰)ð2ìLìLLLLL LLLìv‰ìðeèLLLLLLLLLLLLLLLLLL+LLv‰èðaLìL LL vL L?Á$ L?ßlYÐ L?í•Í L?<*Æ L?7·Ë L ?Á•Ðù L?Öz L?™·  L ?ä-8é L?”]U L ?H²> L?MÎP L?£™iÄ L?c1²' L ?)ª²Í L? ¯­ú L?ÈË)ó L?¤¶` L?ðÌ«( L-?—¬Ú L?œžä7 L?Ó Ò L?Ç—Ò L?0fÎ Lì?s%o L?ÊíÀÁ L?Q p- L ?«¤`$R  6 U6 F6L/`ÐS­7š_ èLèðâ ^^^)^3^=^G^Q^[^e^nYL)LUþ"^bZL)LUþ"^V[L)LUþ"^J\L)LUþ"^>]L)LUþ"^2^L)LUþ"^&_L)LUþ"^`L)LUþ"^aL)LUþ"^¥å9LìL%zåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzååˆLWæå‰LìÐLèL!´b?èL%´b<èL´b>èL´b@èL´bBèL´bDèL´bFèL´bHèL´bJìþ^Nc^J)Ldþ!^A)Lfþ!^8)Lhþ!^/)Ljþ!^&)Llþ!^)Lnþ!^)Lpþ!^ )Lrþ!^¥¥åèLèðâ ^^^"^.^:^F^R^^^j^u^rèQLèLVþ!¥^dèQLèLVþ!¥^VèQLèLVþ!¥^HèQLèLVþ!¥^:èQLèLVþ!¥^,èQLèLVþ!¥^èQLèLVþ!¥^èQLèLVþ!¥^¥åèL/¢å1&þåìLì$L9þrèL9­L)LL)@¥rèL/HoØLtþå/HoØ#¥åQÊLSL#.Zû!µåL-QLð2èL!¼fþÿÿÿL%ŒaìLL)$õe_åÿÿÿìLLL†þCRrèLvþåèL|­L9þåèLx­L9þåèLz­L9þåèL~þåìLìL€VL9þrèL9­L-L-L)L‚þ;¥rèL„þåš7R|7Sù7TT#ýK7UT#-q7VT#ÎeK<7WS#œ S7XbLèL!õ7cRLc?ý­]8èLeí7dRLd?99èLgí7fRLf?f=uøèLií7hRLh? “j0èLkí7jRLj?Çú=èLmí7lRLl?µ× ÂèLoí7nRLn?XÃIßèLqí7pRLp?Ž­ËèLsí7rRLr?cåm¥uLL/HoØL#Œg%ÐZ7twL%L/HoØL#Œg%ÐZ7vyL%L/HoØL#Œg%ÐZ7x{L%L/HoØL#Œg%ÐZ7z}L%L/HoØL#Œg%ÐZ7|L%L/HoØL#Œg%ÐZ7~LL/HoØL#Œg%ÐZ7€ƒLL/HoØL#Œg%ÐZ7‚…L%L/HoØL#Œg%ÐZ7„‡LL/HoØL#Œg%ÐZ7†ŠL‹LŒL)LíL)LŽíLLXLL‘L’LL“íLL”íL L•íL–L L—íL L˜íL™LšL?q¸1šL?æÁöšL)?“ÿ/šL?Û‹šL ? Ã*5šL?þé‚2šL?†R†ÃšL?­o>-šL-?a²šL?¬ÎsòšL?b$šLì?Àg|ÅšL?‘”VýšL ?¢å1&šL ?áMuÀšL ?Õ2lÀšL ?N•k×Ršš6L/`ÐS­7W_9-èLèðLèL!´b èL%´b^þL-LÕþ*^ÿL-LÕþ*^¥¥åè*LìL)*L%ˆFLìLù­ˆ¥åè*LìL)*L%ˆFLìLù­ˆ¥åLL)L°VˆåòLìL±­L²­õåòLìLç­L²­õåòLìLíL²­õåèLèðLèL!´b èL%´b^8 LMLÛþ2^,ìQðL)UL9L)´f^L%ˆLìL=ðþB¥¥^¥¥rLìLÖVLèðL´f0èQLñLèLL)L v‰èða!L)L)V¥¥^¥^^ LTLÛþ*¥rèLèðLèL!´b èL%´b^8 LbLÛþ2^,ìQðL)UL9L)´f^L%ˆLìL=ðþB¥¥^¥¥rìLÎLºVL!´f)ô^ìLjðLLªVl^2LèÐL¸f èLÈ­aèðLw ù´f LZLÛV^ ^èL/“°*ö­¥LjLLÊVl^2LèÐL¸f èLÈ­aèðLw ù´f L[LÛV^ ^èL/“°*ö­¥LèLÅLºVL!´fÇLLL%zLèþ9^OLìLÖVLèðL´f0èULñLèLL)Lv‰èða!L)L)V¥¥^¥^^ LiLÛþJ¥RrèôLèðâ ^^^^ ^ ^^^%^(^9^7^5^2^0^-èQLèL9ð­¥^¥^^^è*LèL9ð­¥^¥^¥å-L9­f+èLìL–L±­L²­õLÇLLL%zLÍVõ^èL-L-LÍVõrèLìLL±­L²­õL-LÍVõrèLÝ­LèðL%´fì^!^^ìLË­LÇL-LÎL%zL¸­õ¥åèôLèðâ^^ ^ ^^^^^/^-!^+^'èQLèLÑ­¥^¥^èQLèL9ð­¥^¥^%¥åLìLÖVLèðL´fäèQðL%´fÖèQQLèL§´bèL©´b@èL¨´bcèL«´b†¥^¶^ªìQUðL!´fìUðL!´f ¥^š^¥^’^¥^Œ^€ìQUðL!´fìUðL!´f ¥^p^¥^h^¥^b^VìQUðL!´fìUðL!´f ¥^F^¥^>^¥^8^,ìQUðL!´fìUðL!´f ¥^^¥^^¥^^¥^^^^¥å)LôLºVL!´fèLQL9­L-LÉVõ^€ÇL)LL%zLìLj ULLÙVl^QLèÐL¸f èLÈ­aèðLw ù´f/LLL°VˆLˆLˆLULL)LïVè¥^ ^èL/“°*ö­¥Lç­L²­õ¥rèL)Lèðâ ^^^_^s^„^•^«^Þ_?__ÆL²­_VèQLèL!Äf#³L!L9­L!L-ŒL9­L¾V¥_,^¥^¥èQLèLíL²­¥_èQLèf³^íL²­¥_ûèQLèLÄ­L²­¥_èèQLèL´­L²­¥_ÕèQLèLó­LíL²­¥_½èQL*LìLúVfèL=­L!L9­LìV^ èLç­L²­¥_ˆèQLèLÒ´bèL´b#¥^<^8LLLLVLÝ­¥_W^LLLLVLÝ­¥_<^¥èQLèLç­L²­¥_%èQðLèL%´bèL!´b¥^«^§ìQQL*´fxìQUðL!´ffìUðL´fVìUQLèLÒ´bèL´b#R^p^8LLLLVLÝ­R^¸^LLLLVLÝ­R^^¥^¥^0^¥^*^¥^$^ ìULLìLLðVLÝ­R^k¥^¥èQLìULL)L)LèðLèL´bèL´b¥^ ^ìQLèR^¥^ìQLèR^¥^¥ L¼LÛV¥LLVLÝ­¥¥^¥õrèôLìðL9L=L-LVLL)LLVõRåèôLìðLèLèðLèL´bèL´b3¥^D^@ìUðL´fìQL)UQLèL)õR^-¥¥^¥^^ìQLèL9ôõR^¥^¥ LLÛV¥LèðLìôL=LLLVL9L-L-LVL­õRRåjLULÒVL9­l_LèÐL¸f èLÈ­aèðLw ù´gåQLðLL=ðæLLèðâ^^)^~^å_j_o__Ç__O_Û_I_ß_,_¥ LßLÛV_™*f *L¸f*^LèL´fLÎL¸­õ^'ûLÞL­LÇL-L9­LÎL%zLLV¥_BèQLìULL­LèLLLVL L LLVLLÇL-LÇL LLæ­õLÇLLÎL%zL%zL%zL¸­õR¥¥_ÙèQLìULèÌg L¡LL9­LLL´L LVL¾VõLLLLLLVLÇL LLÏLVLÎL%zLÍVõLL¡LL9­L-L¾VõLLLÃLLL¾VõL LLâL VL L L­LÇLL9­LÎL%zLÍVõLê­LÀVõL LFðLèðL!´fLLðV^!^^LLLðVLLL×Võ¥R^nLFÌfL)LðV^VûLÞL­LÇL ôL9­LÎL%zLLVLLÇLLLðVLÇLLÎL%zL%zL¸­õ¥¥¥_RèUðL%´fŸèUQððL´fŽèUUðL!´f~èQLìUQðQL)UQôLLLLVLLÇLLÇLLê­LõLÎL%zL¼­õLÇL L LL VLÎL%zL%zL¸­õ¥R_»¥¥¥^^ ^^^^èQLìULLL-LVLLLLLL L!vL)LüVLL)L)L L LâL VLê­LµVõR¥¥_KèQLìULLLLLVL)LˆL ­LìVõ¥¥_èQLìULLLLLVL)L ­LìVõ¥¥_ïèQLìULûLLL"LLVLÇL LLLVLÇLL ­LÎL%zL%zLLV¥¥_žèQLìUL)*LL LLLVL-L-L VL ­LìVõ¥¥¥_cèQLìUL)*LLLLVL LFLÇLûLLL#L LVLÇLLÇLL ­LÎL%zL%zL LVLÇL L LL VLÎL%zL%zL¸­õ¥¥¥¥_ÕèQLìULLLLLVL!L ­LìVõLL L LL L L$vL)LüVLL)L)L L LâL VLê­LµVõR¥¥_eèQLìUL)*LLL-LVL UL LÇLLõLUL%zF L LLVL L)FLÇL LÇLLê­LõLÎL%zL¼­õLÇLLÎL%zL%zL¸­õR¥¥¥^ÍèQLìULL)LðVLLL-LVL L LâLVLL-L-L-Lê­LÀVõR¥¥^~èQLìUL*LL­L LìF LLLVL L-F L LLVLLÇL-LÇL LLæ­õLÇLLÎL%zL%zL%zL¸­õR¥¥^¥R^ ^èL/“°*öþ1¥rèLLÇLLÏõLÎL%zL9LL zL-f L=­^9LìLìLLLVLfÆLL LLL LVLÇL L­LÎL%zLÍVõLLãL­LÇL LL´L LVLÎL%zLÍVõLLÇL LÇLLê­LõLÎL%zL¼­õLÇLLÇL L Læ­õLÇLLÎL%zL%zL%zL%zL¸­õR^èRrL9­LL=­LL L)LLLLLL zL/žºÁVL-LLÇLLê­LõLÎL%zL¼­õL)LéVõLLÇL)LÇLLLæ­õLÎL%zL%zL¸­õRr(LìLù­ˆå9LìLç­L²­õåèL9­LèL!´f@ÇL=L­LÇLLÎL%zL%zLLVLLœLL-L¾Võ¥^”^^èLèL)LëVL«­LÇL=L­LÇLLL*íLLüVL%zL%zLLVLL)LLÇLLLê­Lã­õLÎL%zL¸­õLßVõLLœLL-L¾VõR¥¥å-L9­LìLLĈLç­L²­õL=LLL-LLLL+vL-LœLL QL9­LLÉVõLL¾VõLLL-­L)LéVõRrÇL*LÎL%zL-L®­LÐVLõ­LûL)L¿VLèLÇLLä­Lõ­L¶LL¿VLÇLL®­Lõ­LûLL¿VLÎL%zL%zL÷VL¶L-L¿VLèRrèôLìðL9LìL-L=LVLèLLðVL)Lî­õ¥RåèôLìðL9L9ðL%ˆ‰=L LL-L9ðLLLzL/žºÁþ3RåèLèðLèL!´b èL%´b^6 LzLÛæ^*ìUðL!´fìQLèR^¥^^ìULèL9ðæ¥^¥¥åìôLèðâ ^^ ^+^6^A^ñ^ü___oìLÎL¸­õ_bìLÎL¸­õ_UìLÎL¸­õ_HìLÎL¸­õ_;èULLL9­LÏLLL=L/vLLüVLöVLLLVL-LÇLLÎL%zL)LßVõLÿÿÿÿñLèLLLL L0vLLüVLLÇLLÇLLê­L LĈõLÎL%zL¼­õL-L%zL¸­õR¥^‰ìLÎL¸­õ^|èQLLL)LLðþT¥^cìLÎL¸­õ^Vè*ôðL´fìLÎL¸­õ^>^^èQLì*LñLèLìL1í‰èðaL-L)­L-LLðþd¥¥¥^¥r9L=LL3L9LVLÇL=LLðVLÇL=LLðVLÎL%zL%zLÍVõL9L)L)L!L­L¾Võ¥å9LìL=LLðVL=LLðVL¾Võå9LìL=­LÇLLLðVLÇLLLðVLÎL%zL%zLÍVõåèLL9L=LLLLL4vLìLLLLL5vL)LLLLLL6vLLèLèL7´b\èL8´bbèL9´bhèL¡´bnèL¼´b èL½´bÒèL¿´cèL¾´c6èLÀ´chèL:´cšèL;´cµèL<´cÐèLl´cŸ¥_Ä_ÀºL­¥_¾_³¹L­¥_±_¦²L­¥_¤_™ôL­LèðLèL%´b èL!´b^L­^ L­^¥¥¥_k_`ôL­LèðLèL%´b èL!´b^L­^ L­^¥¥¥_2_'ôL­LèðLèL%´b èL!´b^L­^ L­^¥¥¥_ù_îôL­LèðLèL%´b èL!´b^L­^ L­^¥¥¥_À_µôL­LèðLèL%´b èL!´b^L­^ L­^¥¥¥_‡_|ôL­LèðLèL%´b èL!´b^L­^ L­^¥¥¥_N_CL¡LÝL­L!L­L¾Võ¥_,_!L¼LÝL­L!L­L¾Võ¥_ ^ÿðLèðLèL´bèL´b¥^^{œL­¥^ª^nìQL)ULL L9L=L L=VLÇLLLðVLÇLLLðVLÇLLLðVLÎL%zL%zL%zLÍVõR^B¥¥^¥LœLQL L LðVL!L­LìVõL L LðVL¾Võ¥¥^4^)ôLø­f ôLø­f>L-­¥^^¥^^¥L-þQ¥Rr)ðLèðL!´g+èQðâ ^^^^ ^ ^^ ^¹___ èQQL@´f¤)LèðL%´f‡èQððL!´fxèQðQðL´fgèUðL!´fYèQðQQLLìLAL¯VL°VL»­LLå­LÁ­LèLðL-LôLQL½VèLØ­LÝ­R¥^¥^^^^ ^^^^ L½LÛV¥_’^_b_\èQQL´f»)LèðL%´fžèUðL%´fèUUðL!´f€èQLìUQLLL±­L²­õLÇL%L9­LÇL L=LBL LVLÇL LLðVLÇLLLðVLÎL%zL%zL%zL%zLÍVR^¥¥^^ ^^^^ LÄLÛV¥_Ê^_š_”èQQðLèL!´bèL%´c®¥__uìQUðLèL´bèL´bÀR_d_‰)QUQL@´f¦LèðL%´f‡èQððL!´fxèQðQðL´fgèUðL!´fYèQðQQLLìLAL¯VL°VL»­LLå­LÁ­LèLðL-LôL QL½VèLØ­LÝ­R¥^¥^^^^ ^^^^ L½LÛV¥R_Þ^R_¬^Ñ)QUQL´f½LèðL%´fžèUðL%´fèUUðL!´f€èQLìUQLLL±­L²­õLÇL%L9­LÇL L=LBL LVLÇLLLðVLÇLLLðVLÎL%zL%zL%zL%zLÍVR^¥¥^^ ^^^^ LÄLÛV¥R_^R_Ý^¥_ÏìQQQL*´g¼ìQQUðL!´g¨ìQUðLèL´bèL´bÀR_£_‰)QUQL@´f¦LèðL%´f‡èQððL!´fxèQðQðL´fgèUðL!´fYèQðQQLLìLAL¯VL°VL»­LLå­LÁ­LèLðL-LôL QL½VèLØ­LÝ­R¥^¥^^^^ ^^^^ L½LÛV¥R_^R^ë^Ñ)QUQL´f½LèðL%´fžèUðL%´fèUUðL!´f€èQLìUQLLL±­L²­õLÇL%L9­LÇL L=LBL LVLÇLLLðVLÇLLLðVLÎL%zL%zL%zL%zLÍVR^¥¥^^ ^^^^ LÄLÛV¥R^N^R^^¥^¥^^¥^ ^¥^^^LLLðVLLðæLLüVLLVLÝþ9¥r9L9*L)LÞVF=L=ðL%ˆ‰LEL­L=ðL­LìVõLê­LìõåèðL)ðLèL9ôL=VL)L9ôL=VL¹þ2RrèôL9LìL=ðþ"¥åèQLìðLèðâ^-^D^\^q^‘^½_ _À_&_Ù__&_A_W___î_"_d_‡_:_dèQLLìLL9VLÝ­¥_KèQLLìLL=ðVL¸­¥_1èQLLìLðVLñ­¥_èQLìULLôL-L-LLV¥¥_øèQLìULL)LðVLìL-ôLVL­LìV¥¥_ÊèQLìULLLDLLVLÇLLLðVLÇLLLðVLÎL%zL%zLÍV¥¥_|èQðL%´f\èQUðL!´fLèQQLìULL*L-LÞVFÇLL)LðVLê­L-õLÎL%zL¼­R_"¥¥^^^^èQLìULÿÿÿÿñLÇLL-LðVLê­LEõLL-LLLLFvLLüVL%zL¼­¥¥¥_ÃèQLìUL)*LL-LðVLL-LðVL)LèðLèL!´b èL%´b ^Ú^ìQL LìLðVLê­¥^¥¥LÀV¥¥¥_[èQLìUL)*L-*L)L´f$ÝL)LüVLL)LðVL ­LßV^q-ÌfCÇLLÝLLüVLLLðVL ­LßVõLê­LõLÎL%zL¼­^+ÇLLÇLLÎL%zLL ðVLÎL%zL¸­¥¥¥¥_¦èQLìUL)*LL-L-L-LL VLÝ­¥¥¥_yèQLLðæLìLüVL-L VLÝ­¥_UèQLLL)LL VLÝ­¥_8èQLLìðLðVLÝ­¥_ èQL-LLGvLìLÌVLLLHvLìLüVLL VLÝ­¥¥_æèQLèLèðLèL!´b èL%´b^`ÎLL V^TìQL)ULÇLL-LðVLÇL LLà­L ôL L¿VLðVLÎL%zL%zLL V¥¥^¥¥LÝ­¥_aèQLìULìLèLèL³´bèL´´b7èLI´bNèLº´b{¥^¢^ž³L!L­LLLðVL¾V¥^‹^}L-LðVL!L­LìV¥^m^_ûLØL­LÇLLLðVLÎL%zLLVLÝ­¥^9^+ÇLLLðVLÎL%zLL VLÝ­¥^^¥ LûLÛV¥¥¥_ƒèQLìUL)*LLLLðVL-L-LLVLÝ­¥¥¥_MèQLìULL­LL¼LûLÙL­LÇLL­LÎL%zLLVLªL­L¾VõLLìLLœLL­LûL LL¤L LVLÇLL­LÎL%zL LVL¾VõLÚLÀVõLL LLLLLLLzL/žºÁVLûL L­LÇLL­LÎL%zLLVLLÇLLÇLLÇLLÇLL Læ­õLÎL%zL%zL%zL%zL¸­õL LLðVLL)L×VR¥¥_ èQLìULL)LðVLìL­LìV¥¥^äèQLìULLL-L-LLVLðVLLÇLLÎL%zLLÇLLÎL%zL¸­õLßVõLLÇL)Lê­LLĈõLÎL%zL¼­õLèLL LLLÇLL ôL%zLè­LL LzL/žºÁVLéVR¥¥^/èQLìULL)LðVLL)LðVLáLÂV¥¥^¥LìLìõRrèðLèðL´fˆèUL´fBè*Lì*L9LÝL-LüVL=L-LVL­LßVõLê­LõR^Q¥¥^^èUL=L=*L)L¬VFÇLLÎL%zL9LVLê­Lìõ¥^¥^^ LLÛþ"¥åèQLìðLèðL´fëèULì*L)*L)L¸fÊ9LìL=VLLÝLLüVL)L­LßVõLLœLLL­L!L­LìVõL-L¾VõLLÇL)LÇL LœL L­L L L­L!L­LìVõL¾VõLÎL%zL%zL¸­õLLLðL-LéVõ‰9L9*LLÞVFRR^¥¥¥^^ L+LÛþ*¥¥åèLìLL9L=LLLKvL-LüVL¼­õñL-L9L=LLLLLvL-L­Vèð¥rèLèðLèL!´b èL%´b:_9-LÎLºVL!¸f%9LÇL=LL·­LLVL9ðL%z‰_ìQððLèL´bèL ´bY¥^…^)QðQL´fA)QLèðULìð*L)ð*LULÇLL L%zLìLðVR^­¥¥¥¥¥^¥^4^0)QðQL-ULLÇL-ðL-L%zLðVR^s¥¥^¥ìQL)ULLÎLºVL!¸f%9LÇL=LL·­LLVL9ðL%z‰9LÇL=LLVL9ðL%z‰ÎLìLðþB¥¥^¥¥r)*LÎñLñLèL)LLL9LL=LNv‰èðaÎLL)VL-FìðL·þ9RrèLLÜVL9L9LQL=­LRLÉVõLÇLLLä­L9LVLÇLQL=­LÎL%zL%zLÍVõL9LœLL­L­L-L¾VõRå9LœL9LPL=­LLÉVõL-L­L¾VõåìLèðLèL!´b èL%´b^K L_LÛV^?ìQL)UL9LœLL=­L9LL­L=­LLÉVõL¾Võ¥¥^¥¥LLÇL)LðL%z‰¥rèL9­LìLìLLý­L!LLô­LzLQLèLœLL=­LPL­L¾VõLìLLLL9L=LSvLLüVL)LL=LTvLLüVLLLVLèððL%´fèðQLè¥^¥^^èLÇLìLÎL%z¥¥LÎñLL=L9L-LUvLULÓV QLÇLLLðLÔVL%zL-LLÔVLÔVL¸­õRrW7›L/`ÐS­7© _¨SèLèðâ^^^#^-^7^A^JþL)Lþ"^>ÿL)Lþ"^2"L)Lþ"^& L)Lþ"^ L)Lþ"^ L)Lþ"^¥å9L)L)L!zrr9L)L)L%zrr9L)L)Lzrr9LìLzåå9LìLzåå9LìLzåå°LìLþå9L)L)L?”zrrèLèðâ^^=^\^„^^¨^®èQLìUL LLLL»VˆLˆLLL-L»Vˆ¥¥^~èQLìULLL-L»VL ˆL숥¥^]èQLìULL)L9ðVL ˆLL)L9ðVˆ¥¥^3èQL L숥^&èQL L}L)ôLkVˆL ˆ¥^ èQLè¥^¥rLµ­LìL9þåLLµ­L)L»þ#åìLìL VLÒærìL ­LìL9þ"r LYL–þ*rìL¸f)*L-**L-L-L·VFrè**åì*LìFrì*LìLÜþ"rìULìLÜVLàþrìLèðL!´f -*^…^^j*LLÜVl^6LèÐL¸f èLƒ­aèðLw ù´fLLL9ðV^ ^èL/“°*ö­¥LèL*LÃVL!¸f'è*ÌfèL ­L-L=V**LìôL)LáV襥rèLèðLèL!´b èL%´b"^l& L9L=LðVˆL ­LLþ*^OìQL)ULjQL=LÜVl^/LèÐL¸f èLƒ­aèðLw ù´f ìLð­^ ^èL/“°*öþ9¥¥¥^¥¥åñLèLLLL9LL' v‰èða-LèðL!´fÐL*LUL%zL)­^#^^ÐLLLL=VL†L%zL)þ9¥¥rèLèðLèL!´b èL%´b"^”) L9L=LðVˆL ­LLþ*^wìQL)ULj9UL=LÜVLèðLìôLìLìL L*LÃVL!´f†^ ôzRl^/LèÐL¸f èLƒ­aèðLw ù´f ìLð­^ ^èL/“°*öþ9¥¥¥^¥¥åñLèLLLL9LLL* v‰èða-LèðL!´fÐL*LUL%zL)­^#^^ÐLLLL=VL†L%zL)þ9¥¥rèLèðLèL!´b èL%´b"^ˆ, L9L=LðVˆL ­LLþ*^kìQL)ULj-*L=L¸VLL*LÃVL!´f†^ôõl^/LèÐL¸f èLƒ­aèðLw ù´f ìLð­^ ^èL/“°*öþ9¥¥¥^¥¥åñLèLLLL9LLL- v‰èða-LèðL!´fÐL*LUL%zL)­^#^^ÐLLLL=VL†L%zL)þ9¥¥rèLèðLèL!´b èL%´b^`9L ­L=Lþ*^OìQL)ULj*L9LÜVl^/LèÐL¸f èLƒ­aèðLw ù´f ìLð­^ ^èL/“°*öþ9¥¥¥^¥¥åñLèL-L-L9LL/ v‰èðaÐL*LUL%zLì­LèðLìôL)QLL­­LðLìLLrVL)LðL-LLrVzRrèôLèðâ ^^^^ ^ ^ ^^^^/^-^+^(èQLèL9ð­¥^¥^è*LèL9ð­¥^¥^¥åìLìøL!´f^²èôLèðâ ^^^^^"^,^A^Q^y^”^‘^Ž^‹ LßL–þ*^ LßL–þ*^sèQL-L9ðæLìLÇþ2¥^\èQL-LìL9ðþ2¥^JèQLìULL9ðæL)LÇVb LìL9ðþ:¥¥^ èULì*LL9ðæL)LÇþ:¥¥^¥r)L)L9Vf)L)L VLìL=V)L)Ll­)ðL!Äf"ìðLÿÿÿÿ´f )Lÿÿÿÿ‰^)LðL¦­‰^ìðLÿÿÿÿ´f )Lÿÿÿÿ‰rèLèðL?”´f:èQðL!´f,èQLìULìLLL VL VLìL9æR^¥¥^^^^èLèLÒæ¥¥rèLèðâ ^^^^^^^^^^^^^^^^ ^^^¥åèôLèðâ ^^^/^0^:^D^Y^i^^£^ èQL-LìÄf)LLÓ­¥^…^‚ L L–þ*^v L L–þ*^jèQL-L9ðæLìL¶þ2¥^SèQL-LìL9ðþ2¥^AèQLìULLìL9ðVL9ðæL)L¶þ:¥¥^èUL-L9ðæLìL¶þ2¥^¥r9L)L)L=Lðþ4r9L)L)L=Lðþ4r9L)L)L=Lðþ4r)L)LÃVL!´f_½ìôL-ôõLèððL´fèðQLLìLLL9ðV¥_¥^^èôðL´f èôQLLL)LL9ðV¥_g¥^^èððL´fLLLL=V_F^^èôðL´fL-LLL=V_'^^èððL%´f(èðQLLLLL=VèLLV¥_ø¥^^èôðL%´f(èôQLLLLL=VèLLV¥_Ç¥^^èððL´fòèôðL´f‡èðQLìðUL)ôQL-ôUL-L)LÃVL!´fSj L L9L7 vLLL~Vl^0LèÐL¸f èLƒ­aèLLL)LV¥^ ¥èL/“°*ö­¥R_:^R^¥¥¥¥^^èð*LèôL­fLj LL L L9ðVl^0LèÐL¸f èLƒ­aèL)LL)LV¥^ ¥èL/“°*ö­¥¥_Ò^¥^¥^^èôðL´fbèô*LèôL­fLj L LL L9ðVl^0LèÐL¸f èLƒ­aèLL-L)LV¥^ ¥èL/“°*ö­¥¥_g^¥^¥^^èððLèL´bèL´b°¥_3_/ìôðL´f›ìðQL)ðUL-ôQLôUL-L‹­L)L‹­´fdj. L L9L8 vLLL~V LLL L9ðVl^0LèÐL¸f èLƒ­aèLLL)LV¥^ ¥èL/“°*ö­¥R^±^R^™¥¥¥¥^¥^‹^‡ìôðL´fxìðQL)ôQLìL‹­LìL‹­´fSj L L9L9 vLLL~Vl^0LèÐL¸f èLƒ­aèLLL)LV¥^ ¥èL/“°*ö­¥R^(^R^¥¥^¥^^¥-L-L VL)Lþ:¥r9L)L)L=Lþ4r9L=LL-LLðþ5åèLèðL´f@èQLìUL9L=LLLLðVLÐLìLL%zL)LðV¥R^4¥¥^^9L=LLLLðVLðLLo­L)Låþ;¥¥rìLèðâ^ _À_,_µ_âèQLìUL)*L)LèðLèL!´b èL%´b ^'Ý^#ìQL L L L-L L9ðVLì­¥^¥¥LL-L-LL=VLèôLèðL´g7èULì*LL)õLèððLèL!´bèL%´b¥^^^ZìôðL!´f †¥^°^¥^G^CìðUðL!´f2ìôðL%´f#ìðQL)ôQLÐLìL†L%zR^y¥¥^¥^ ^¥^^¥èôðL%´f?èôQôðL´f/èðLìôQôQLèL‹­L)L‹­´f èR^/^R^¥¥^^^^; LLLðVˆL ­L LV¥LL­­L ðLìLLrVL ðL)LræLLýVL L LL< vLìLL~VìRR^¥¥^^ LZL–þr¥R¥¥¥_+èQLj LLÜVl^YLèÐL¸f èLƒ­aèðLw ù´f7Ìf= L)ˆL ­LLVðLä­LL-L)L¢Vè¥^ ^èL/“°*öþI¥¥^½èQðLèL!´bèL%´b¥^J^F L:L–V¥^–^6ìQUðL!´f$ìQQLLLL-LL9ðVR^j¥^¥^^¥èQLðLLLLL9L> vL)LýVLöþJ¥^2ñLèLLLLL9LL? v‰èða†LL)þJ¥^¥rìLèðâ^^/^K^g^ƒ^Ÿ^ï_›_·èQLèL”­Lª­LÞLLÅþK¥_™èQLèL³­Lª­L¨LLÅþK¥_{èQLèLô­Lª­L§LLÅþK¥_]èQLèLÌ­Lª­L®LLÅþK¥_?èQLèLè­Lª­LpLLÅþK¥_!èQLLL)LL9VLèðLìôLðLL­­L)LrVL)LL¹­LˆVLª­LìLLÅþkR¥^ÏèQLLL)LL=VLèðLìôL)QLðLL­­L)ôLèðLèL!´bèL´b¥^'^#¥^8^ìQL ðLìLLåVR^!¥^¥ ðLÐLL†L%zLLåV¥LrVL-LLñ­LˆVLª­LìLLÅþsR¥^!èQLìULL)L)LLðþ\¥¥^¥rèLèðâ^ ^^^)^2B L)Lþ"^&C L)Lþ"^D L)Lþ"^E L)Lþ"^¥åLìLøVLèðL´fèQðL%´fèQQLèL§´bèL¨´b)èL«´b<¥^f^ZìQUðL!´f G ¥^T^¥^L^@ìQUðL!´f H ¥^:^¥^2^&ìQUðL!´f-f I ¥^^¥^^¥^^¥^^^^J ¥r9L=LLºVLìLLÅþ#åèðLèL9´¥å-L-L-L-LL vLLèLèLµ´b¢èL²´cfèL³´c*èLl´cîèL´´c²èL·´cv èL¸´c¨ èL¶´cÚ èL7´c èL8´c> èL9´cp èLôc¢ èLÄ´cÔ èL¿´c èLÀ´c# èL½´c@ èL¾´c] èL¡´cz èL¼´c— èL:´c´ èL;´cÑ èL<´cî èL´cR ¥_Þ _Ú L²´LèLL9VLìLL9VõLèððâ^ ^W^£^ï_–èôðâ^ ^^^ ^>ÞL­^5®L­^,pL­^#LôLôLLü­L=VôL­^_Hèôðâ^ ^^^ ^>®L­^5®L­^,pL­^#LôLôLLü­L=VôL­^^úèôðâ^ ^^^ ^>pL­^5pL­^,pL­^#LôLôLLü­L=VôL­^^¬èôðâ^ ^*^I^h^šLôLôLLü­L=VôL­^yLôLôLLü­L=VôL­^XLôLôLLü­L=VôL­^7LôLÞLLü­L=VLôLÞLLü­L=VÞL­^^¥¥¥_& _ L²´LèLL9VLìLL9VõLèððâ^ ^W^£^ï_–èôðâ^ ^^^ ^>ÞL­^5®L­^,pL­^#LôLôLLü­L=VôL­^_Hèôðâ^ ^^^ ^>®L­^5®L­^,pL­^#LôLôLLü­L=VôL­^^úèôðâ^ ^^^ ^>pL­^5pL­^,pL­^#LôLôLLü­L=VôL­^^¬èôðâ^ ^*^I^h^šLôLôLLü­L=VôL­^yLôLôLLü­L=VôL­^XLôLôLLü­L=VôL­^7LôLÞLLü­L=VLôLÞLLü­L=VÞL­^^¥¥¥_[ _D L²´LèLL9VLìLL9VõLèððâ^ ^W^£^ï_–èôðâ^ ^^^ ^>ÞL­^5®L­^,pL­^#LôLôLLü­L=VôL­^_Hèôðâ^ ^^^ ^>®L­^5®L­^,pL­^#LôLôLLü­L=VôL­^^úèôðâ^ ^^^ ^>pL­^5pL­^,pL­^#LôLôLLü­L=VôL­^^¬èôðâ^ ^*^I^h^šLôLôLLü­L=VôL­^yLôLôLLü­L=VôL­^XLôLôLLü­L=VôL­^7LôLÞLLü­L=VLôLÞLLü­L=VÞL­^^¥¥¥__yL²´LèLL9VLìLL9VõLèððâ^ ^W^£^ï_–èôðâ^ ^^^ ^>ÞL­^5®L­^,pL­^#LôLôLLü­L=VôL­^_Hèôðâ^ ^^^ ^>®L­^5®L­^,pL­^#LôLôLLü­L=VôL­^^úèôðâ^ ^^^ ^>pL­^5pL­^,pL­^#LôLôLLü­L=VôL­^^¬èôðâ^ ^*^I^h^šLôLôLLü­L=VôL­^yLôLôLLü­L=VôL­^XLôLôLLü­L=VôL­^7LôLÞLLü­L=VLôLÞLLü­L=VÞL­^^¥¥¥_Å_®L²´LèLL9VLìLL9VõLèððâ^ ^W^£^ï_–èôðâ^ ^^^ ^>ÞL­^5®L­^,pL­^#LôLôLLü­L=VôL­^_Hèôðâ^ ^^^ ^>®L­^5®L­^,pL­^#LôLôLLü­L=VôL­^^úèôðâ^ ^^^ ^>pL­^5pL­^,pL­^#LôLôLLü­L=VôL­^^¬èôðâ^ ^*^I^h^šLôLôLLü­L=VôL­^yLôLôLLü­L=VôL­^XLôLôLLü­L=VôL­^7LôLÞLLü­L=VLôLÞLLü­L=VÞL­^^¥¥¥_ú_ãLôLÞLLü­L=VLôLÞLLü­L=VÞL-­¥_Á_ªLôLÞLLü­L=VLôLÞLLü­L=VÞL-­¥_ˆ_qLôLÞLLü­L=VLôLÞLLü­L=VÞL-­¥_O_8LôLÞLLü­L=VLôLÞLLü­L=VÞL-­¥__ÿLôLÞLLü­L=VLôLÞLLü­L=VÞL-­¥_Ý_ÆLôLÞLLü­L=VLôLÞLLü­L=VÞL-­¥_¤_LôL§LLü­L=VLôL§LLü­L=V§L-­¥_k_TLôL§LLü­L=VLôL§LLü­L=V§L-­¥_2_LôLôLLü­L=V§L-­¥__÷LôLôLLü­L=V§L-­¥_ê_ÓLôLôLLü­L=V§L-­¥_Æ_¯LôLôLLü­L=V§L-­¥_¢_‹LôLôLLü­L=V§L-­¥_~_gLôLôLLü­L=V§L-­¥_Z_CLôLôLLü­L=V§L-­¥_6_LôLôLLü­L=V§L-­¥__ûðLèðLèL´bèL´b,¥__LôLôLLü­L=V¯L­¥_(^ÝìQL)ULL)ôL‘VLèðL´f©èQLjLM íLL¼Vl^2LèÐL¸f èLƒ­aèðLw ù´f LÕL–V^ ^èL/“°*ö­¥LèðLìôL)QLìLÚLÃVL!´fN LˆLO ˆL ­LLü­LVL ôLôLLü­L=V¯L ­R¥^¥^^ LÙL–V¥R^Q¥¥^¥ðLP LîVLèðLìôL LôL)L Lü­L=V LôL-L Lü­L=V¯L­R¥¥^§^ðLQ LîVLèðLìôLLôL)L Lü­L=VLôL-LLü­L=VLñ­Lª­L ðLä­LLÅVLèLÐL LÐL L†L%zL%zL÷VL-LLÅVR¥^^¥R LˆL ­L-LþJ¥¥r9L=LæVLìLLÅþ#å)L)L)LT vL-LèLèLº´bèL´´bLèLI´b{èL³´b—¥^÷^óðLP LîVLèðLìôLLôL)LLü­L9VìL­R¥^Ë^½ðLP LîVLèðLìôLLôL-LLü­L9VèL­R¥^•^‡LôL§LLü­L9V§L-­¥^r^dLL=VLèðLèL!´bèL%´b¥^ ^ÞL­¥^0^®L­¥^#^¥LôLÞLLü­L9VÞL­¥¥^^¥ LL–þB¥¥rèL¸f9LÐL=ðL-LzL9ðL%z‰=L=ðL%ˆ‰åèLèðâ^ ^W^i^ÐèQLìULLLLLL9ðVLèðLìôLLìLL L LL L=VLLVèL)õR¥¥^€èQLðLä­Lìõ¥^lèQLV LðL¦­Lù­ˆLLLLL9ðæL)LýVLú­LèðLìôL!ñLLìLLW vL-L¶V ðL)LöVLõR¥^¥rèQLìôL)ðL9LìL“­L½­õL)LÔVLÐL9LÐLÝLõL†L%zL9LõLïVõLL%z¥RrQL†LÃVL!´f Lðð-LèðL!´f+ÐLLÖ­LÝL†L¦LmVLzVL†L%z^^^¥L‰Lª­L¯L-LÅVñLL­­L†ñLL)L)LL9æLLýVLLèðLèL!´b èL%´b ^^ ìQLè¥^¥¥L)ðLo­LèðL!´f^5^^èLLY íLÐL L†L%zL)L VLLìL|­õ¥¥¥LLèðLèL!´b èL%´b^& ðLä­^ìQLLLL-L L=V¥^¥¥L ðL…LLýVL)LåVL LÐLLLLLLLLzLQL%zF f LL)LVLŠ­LL´fì^¯L LÅþ›R r†ñLñL!ñLLs­LìðLìÄgcL)ðLžVL-ðg*-L‰èLèây^ò^ð^î^ì^ê^è^æ^ä^â^à^Þ^Ü^Ú^Ø^Ö^Ô^Ò^Ð^Î^Ì^Ê^È^Æ^Ä^Â^À^¾^¼^º^¸^¶^´^²^°^®^¬^ª^¬^¦^¤^¢^ ^ž^œ^š^˜^Ÿ^”^¥^­^µ^½^Å^Í^Õ^Ý^å^í^~^|^z^x^v^t^r^p^n^l^j^h^f^d^b^`^^^\^Z^X^V^T^R^P^N^L^J^H^F^D^¹^@^>^<^:^8^6^4^2^0^¼^Ñ^æ^(^ù^$^"^ ^^^^^^^^^^ö^ ^^^____"_L‰__L‰_^ýL‰_^óL‰^ú^éL‰^ð^ßL‰^æ^ÕL‰^Ü^ËL‰^Ò^ÁL‰^È^·L‰^¾^­L‰^´^£LÐLÞLðL%z‰^^ŒLÐL§LðL%z‰^†^uLÐL¨LðL%z‰^o^^LÐLÞLðL%z‰^X^GLÐL®LðL%z‰^A^0LÐLpLðL%z‰^*^LÐLÞLðL%z‰^^[ L ­LL9V¥^èLèL%´f L‰^^^¥)L-ðL%ˆ‰¥_šýÿÿ)ðf[ L ­LL9V-ðLèðLèL!´bèL%´b¥^+^'¯¥^6^ìUðL!´fìQLèR^!¥^¥^^¥èLðLìLo­LöþZ¥¥RrèôLìðL9LìL-L=þ3Råè*Lì*L)*L-*LULQLôLðL9L=­L9*L-L¸f+9*ôLLðVLðf] LìˆL^ ˆLt­9LìF¥9LL_ vLL¶V9LLðVL9L-LV9L)F9ðL…LLýVL)ôLåVL9LL)L LVLLL LL„VL)L LÅV‰Ìf9LLLVèLL´õRRåèôLìðLèÌf9ðL=L-Ljþ3RåèQLèL†LÃVL!¸fFìôL)L†F)L9L=LLLLL` vL)Lo­LýVL-L)La vLìL¶þ2R¥åìôL)ðL9L)L¯L-LÑ­QL=V9L-LðVLèôLÐL)LL%zõ¥RrèðL9Lì´¥åìL-õLèððLèL%´bèL!´cÁ¥__ìôðL%´g¬ìðQL)ðUL-ôQLôULL)L‘VLèðL´g<èQðL%´g.èQQLj ´gèQUðL!´gèUðL%´gèUUðL!´fñèUQLðLèðL!´fAèQðL´f3èQQL9LìLQL=VL9LL)L QLV¥¥^ž¥^^^^LôL‘VLèðL´flèQðL%´f^èQQLj ´fOèQUðL!´f?èUðL%´f1èUUðL!´f!èUQL9LìLL QLV¥^-¥^^^^^^^^ ^^^^k L ­LQLV¥¥¥^2¥^^^^^^^^ ^^^^9LôLLLü­LV¥ÐLL L%zLLL-LLðVR^ó¥¥¥¥^¥^b^^ìôðL!´f"LLo­L÷VL-LLÅV¥^¼^^ìôLLLo­L÷VL9ðL)LLåVLLÅVR^‹¥^¥èôðL!´fpèðLL-L‘VLèðL´f@èQLìUL†LL Lo­L÷VLLLÅVLLLLðVR^¥¥^^l L ­LLV¥¥^¥^^ LËL–þB¥rèôåèôå9ðLä­L=L)L)L¢Vè¥åèQLìôL)ðLL9L=LLLVL)fÛ^ÚL=**L-L-L-LzL¢VèL)LzRRåèôLìðLìLèðLèL!´b èL%´b ^ š^ìQLL9L=L-LLV¥^¥¥L=*UL)L)LõL¢VèL)õ¥RåèðL9Lì´¥åèLèðLèL!´b èL%´b?^Ÿ-Lv íL9LÇVfw LˆL ­L=Lþ2^LL VL=Lþ2^eìQðL)QQL-ULL-´fèL)õR^D^R^¥¥¥ìQL)ULLìLðVLèðLìôLÐLL)L%zL)õR¥¥^¥¥rèôLìðLèL9ðL=VLèðLìôL9Lì‰LLðVLLìôLL-Lü­LVèLõRRåèðLz LìˆL{ ˆL ­L9L=þ"¥åèðLèLèðL´f^^^¥¥åèðL} LìLÂþ"¥å9ðLäþå9L%ˆL=L€ íLíVL=L)L=ðL-Li­LöVLLVèL9Lþ"¥åèôLèðLèL´bèL´b¥^V^RìQLèL9ð­R^K¥^?ìQLjL=LÕVl^$LèÐL¸f èLƒ­aL­^èL/“°*ö­¥R^¥^¥ìLþ¥åèôLìðLèLèðâ^+^A^ë_È_¯_&_5_=_‰_Á_æ_9_é_k _à _È _M _¨ __)_‹èQLL†L)LL9þT¥_sèQðLèL!´b èL%´b^”‰Lª­L¯LLÅþK^€ìQQL)QULL=­LL-LðVLLLLc vLìôLÐL-L†L%zõLL VLèðLìôL L­ LLVìLo­L«­LìL LÅþƒR¥¥^¥_Ç èQLìULL)LðVLLìLøVLèðL´fjèQLj#Ld íLL¼VLèðLìôL)QLèRl^;LèÐL¸f èLƒ­aèðLw ù´f-ôLL VLLV^ ^èL/“°*ö­¥¥^:¥^^L-LLVLèðLìôL)QL LôLLLü­LVìR¥LìL-LyVLìLLÅþcR¥¥_è èQððL!´gßèQðQðLèL´bèL´c@¥_Ç_¿ìQðQQLèLe ´bèLf ´caèLg ´cÆR_£_)UðL%´gC)UQððL!´g/)UQðQðLèL´bèL´b¥R_k_ -UQðQUðL´f‡-UUðL!´ft-UQðQQLUQðQUQLUQôLLÐL LLÐLL†L%zLŒVLL VL UL%zF‰Lª­L¯L)LÅVR_Ü ¥¥¥^R_Ô^R_Î^o-UUðL!´f\-UQðQQLUQôLLÐL LÐLL†L%zLL VL UL%zF‰Lª­L¯L)LÅVR_g ¥¥^R_a^¥^R_W^R_Q^À)UðL!´f])QLLL)LÐLLðLÉ­L½­õLÐL L ôL‚­L½­õL†L%zL%zLÈVõLðVR_é ¥^R^å^T)UðL!´fC)QLLL)LÐLL *LÉ­L½­õL†L%zLÈVõLðVR_— ¥^R^“^¥^‡ìQðQQLh ´fsìUðL%´fcìUUðL!´fQìUQLLìLðVLi LôLLLµ­LôL»VLðzL{VèLÆ­L¯LLÅV¥R_ ¥^¥^^¥^^¥^ ^¥^^èQLìULL)LðVLìLèðL!´fÐLL†LË­õL†L%z^^^)¥LLðæLìLýVLL-LøVLèðL´fKèQLìULñLèL L LLLLLm v‰èða†LLLLLV¥R^R¥¥^^ðLä­L ðLn LLýVL)LåVL LôL)L LVLL÷VL)L LÅþƒR¥R¥¥_ÿèQLìULL)LðVLL)LðVLLìôLÞL-Lü­LVðLLîVLèðLìôL LôL-LLü­LVLL™VLìL LÅþ{R¥¥_†o L ­L-Lþ:_uè*ðLèL!´b èL%´bn^òìQL)ULL)LðVLLìôL§L-Lü­LVL)LðVLLìôL¯L-Lü­LVìLìLÝLVL¯LLÅþkR¥¥^‰ìQL)UL-*QLL-LðVLLìôL§L-Lü­LVL-LðVLL-LðVL LìôL-ôL-Lü­LV)L)L)Lì­LVL)ôL LÅþ{R¥¥¥^¥_kèQLìUL)*L-*L*L L LLLLLL LzL/žºÁVLL­è¥¥¥¥¥¥_èQLìUL)*LL-LLLðVLLLðVLL þm¥¥¥_ãèQLìULL)LL-LðVLL þ\¥¥_¼èQLìULL)LðVLLL­­LLLLVLL)ôL)LLü­LVìðLìLLÅþcR¥¥_gèQðLèL!´bèL%´b ¥^a^]‰Lª­L¯LLÅV¥_8^EìQUðL!´f3ìQQLLìLðVLèLÆ­LìôL)Lü­LÅV¥R_ý¥^¥^^¥èQLLðæLìLýVLèLÁ­LðLp L-LýVLöVLLÅþS¥¥_µèQLìUL)*L*ôLèðL%´f.èQL*´f!èUðL!´fÐL-L†L%z^&^^ ^^^^èLèLÐLL†L%zLŒV¥¥Ljg *LLÜVLèðLìôL)QL L©LÃVL!¸f*L LVìL‹­L L‹­¸fq L ˆL ­LLVìLìLzRl^¹LèÐL¸f èLƒ­aèðLw ù´f—*QLLÀVfr LˆL ­LLVL­­LLìLs vLLýVL-LìLšL’VLÿÿÿÿõL *QLL)L¢VL©LÃVL!´f *LL-LLzL¢VìL-L)zR^ ^èL/“°*ö­¥LèðLìôL)QLLèðâ^ ^ ^%^R^~š^zèQLL-LL-LLV¥^`èQL)L L LLLt vLìLýVL ðLìL—V¥¥^1èQL)L L LLLu vLìLýVL ðLìLÏV¥¥^¥L-LìðLÿÿÿÿ´fL†LÃVL!´fÿÿÿÿ^  ðL¦­‰-LLL-L’V ðL!LLjV-L€­L¯L LÅþ‹R¥¥¥_1èQLìULèLèðLèL!´b èL%´b ^$š^ ìQLLL­­L L-L LV¥^¥¥L*UL-L)LÎõL¢V)LìLqVL¯LLÅþ[¥¥¥_ºèQLj LÑ­l^'LèÐL¸f èLƒ­a LGL–V^èL/“°*ö­¥LèðLìôLL)LLVLèðLìôL)QLL-L‘VLèðL´fèQLè¥^¥^^ LKL–V¥LèñLñLèL-L LLLLx v‰èðaìLìLLLLy vL LýVL LL| vL-ðL¶VèL¡­LLLÅþ£R ¥_ÐèQLìULL)LðVLìLèðL!´f^^^~ L-LÂV¥LL)ôLLLðVLèðLìôL)QLÌf)f L ­L LVL)LLêVLìL LÅþƒR¥¥_IèQLìULL)LðVLLÎL-LLðVLèðLìôL)QL LìLôL LVL)LŽVLìL LÅþ{R¥¥^ìèQLìULL)LðVLìLLLL vLñLèLìLLL‚ v‰èða)LLßVL-ôL)­LLÅþkR¥¥^èQLìULLL-L-LÈVõLðþJ¥¥^gèQLìULL)LðVLLìôL§L-Lü­LVL)LðVLLìôL¯L-Lü­LVìLìLnVL¯LLÅþcR¥¥^¥RrèLèðLèL!´b èL%´b^*9ðLä­^ ìQLLL­­L9L-L=LV¥^¥¥L9L-L)LVè¥rèôLìðLèL)L9þ*RåèLèðLìôLìLèðLèL´bèL´bå¥_1_-ìQL)ULL9­LìL=VLLLLL„ vL-LèðLèL!´bèL%´b¥^C^? L™L–V¥^K^/ìUðL!´fìQðL)QôLìLìLVR^(¥¥^¥^^¥ ðL)L… íLLýVLöV¥L LìLôLLü­LVàLLýVL-LãVL¯LLÅVRR^i¥¥^PìQL´fBìUL)*L-*L*LL LLLLLL LzL/žºÁVR^%¥¥¥¥^¥^^¥L9­LL=þB¥Rr9ðLìLûVf‡ L ­L=LV9L9ðL)L´V‰jLLÜVl^RLèÐL¸f èLƒ­aèðLw ù´f0ðLä­LL-L)L¢V-fL-L)LVè¥^ ^èL/“°*öþ!¥rèðL9Lì´¥åèôLìðL9ðL L=LLLLLzL/žºÁVLèðLìôLj#L‰ íLL¼VLèðLìôL)QLèRl^:LèÐL¸f èLƒ­aèðLw ù´fLL VLL V^ ^èL/“°*ö­¥LL-L)LL…­L VìLõRRå9QLìLç­õåèLèðâ^ ^P_._7èQL9ðL L=LLLLLzL/žºÁVLèðLìôLL)LL-L…­LVèL¬þ9R¥^îèQðL%´fhèQUðL!´fXèQQLìULLìLVLL-LVLLìL-ôLQLVìQLLç­õL)Lv­LVRR^ˆ¥¥^^^^èQLìULLìLVLLæL-LýVLLðL)LöVL-ôLQLVìLŽ íLLýVL×­L)QLìõL-Lv­LþJR¥¥^ LL–þ"^¥åèôLìðLL)L9LL L=Lˆ vLìLèðâ^^9^µ_^_"__a_Â_)èQL-LìL´f  ðLä­^ L)LVõ¥_èQL-LìLèðâ^^^#^+^3^;^E^O^XèQLÞ¥^NèQL¨¥^DèQL§¥^:èQL®¥^0èQLp¥^& L¾L–V^ L¾L–V^ L¾L–V^¥õ¥_ƒèQðL%´fRèQUðL!´fBèQQLðL L L L L LLzL/žºÁVLèðLìôLèLà­L)õR¥_1¥^^^^èQL/n…;$L L L L L L LðzL/žºÁVLìLýVLú­LèðLìôLèL×­L ðL-LöVõR¥_ØèQLjLÑ­Là­l^'LèÐL¸f èLƒ­a LÇL–V^èL/“°*ö­¥L LìLLVLèðLìôL)QLL-L‘VLèðL´f;èQLLLLLLLL LL9LLŠ v LLýV¥^¥^^ L×L–V¥LèLLv­LuVLõR¥_èQLìUL)*LèLèðLèL!´b èL%´b^TÝLÝõ^KìQLèôLðL LLLLLLzL/žºÁVLèðLìôLèLì­L)LõLì­õR¥¥^¥¥LèðLìôL LLL LVLèðLìôL)QLLìôõLèððL!´f[èôðLèL!´bèL%´b0¥^G^?L LL‡VLðLL­­LLrVõ¥_í^‹ L ­LL9V¥_Ø^¥^^èôðLèL!´b èL%´b_¹Œ L ­LL9V_¨ìôQðL)ôQôLL­­LðLìLLrVLðL)LLrVL LèðL%´f®èQððLèL´bèL!´bp¥^˜^ìQðQL)QôLL­ÌfIðLÐLL†L%zLLåVLìLÐL-LL×­õL†L%zL×­õLì­õR^^R^4¥¥^(ìQðQL´fìQôLL õR^Y¥^¥^ ^¥^^ôLèðL´fèQLðLìLLåV¥^!¥^^ðLÐLL†L%zLLåV¥L õ¥LèðLìôL-ôLèðL´fèQLðLìLLåV¥^!¥^^ðLÐLL†L%zLLåV¥LLìL-L LV LLL‡VLõR¥¥^¥¥R¥¥¥_0èQLìULðL L L L LLLzL/žºÁVLèðLìôLLLVL L-L)LL…­LVL)LõVLìõR¥¥^ÏèQLìULðL L L L L LLzL/žºÁVLèðLìôL L)LL LLL LVL LVèLL¾VL)õR¥¥^lèQLìUL ðL LîVLèðLìôL L­LL L L LLLL L L v LLýVLL)L VèLL£VLõR¥¥^¥LèðLìôLLìõL)õRRr‘ LìˆL’ ˆL ­L9L=þåL¤­ñL9L L=LL­­LLLLzL/žºÁVLèðLìôLðfL‰Lð‰^8-ðLðLéVLðLðLéVLLL“ vL)L)L›VLëVRL)LLLVèRå9L)L)L=þ+rèQLìôL)ðLñLL­­LL¤­ñL9L)L=LLLLLLL” v LLýVL=L­L=LL• vLLÙVLèðLèL!´b èL%´b ^2Ý^.ìQL=LìLVL=LìôL§L-QLVèLì­¥¥^¥¥L=LLVL=LìôL L-Lü­LV=L-L VìLìLzRRåèLèðL%´f¾èQðLèL´bèL!´b ¥^©^¡ìQUðL´fˆìQQL)QUQL-UL9L-L-LòL=VLèðLìôL)QLìLÎLÃVL!´f^8L)L‘VLèðL´fèQLèL L‹­´¥^¥^^ LHL–V¥RR^¥¥¥^¥^^ ¥^ ^¥^^¥å-ðLä­L9LL-L=LLLLLLLL– v L-LýVLÍLLL— v‰èL-L•VLèðLìôLèLL-zRr9LÐL)ôL9ðL%z‰r9LÐL-L9ðL%z‰rL­­LìôLÐL*L†L%zLÃVL!´bì*LÐL*L†L%zLÀVf†^ÐLÐL*L†L%zL†L%zñL†ñLìL™ íL*LÙVèLš íL*L°VìðLìðLôzRåèLèðLèL!´b èL%´bc^«j#9*L}L=LkVLÜVLÄ­Lõl^;LèÐL¸f èLƒ­aèðLw ù´f LˆL ­LLV^ ^èL/“°*öþ)¥^MìQL)ULjLˆLèLL¥VLìõ¥l^$LèÐL¸f èLƒ­aìLð­^èL/“°*öþ9¥¥¥^¥¥åìLœ L˜VLñLèLLLLL9LLž v‰èða*Lìþ1RrìôL)ðL9L-L=VLèôLÐL)LL%zõ¥Rrj*LLÜVl_LèÐL¸f èLƒ­aèðLw ù´gö-L-L-L9VLèðLìôLj  *LÐL*L†L%zLÜVLõl^9LèÐL¸f èLƒ­aèðLw ù´f*L-‰*Lõ^ ^èL/“°*ö­¥LèðLìôLôL†LÐL-L†L%zL  L *LL­­Lf *^. LL­­LL­­LL­­LL­­LLLØ­LzL*L*L*Lðz Lè*LL)*L¢VLŸ­L}­LèLLL%L!LwVèLâ­L=ðf ¡ LL{VèLèððL%´f„èðQðL%´fuèðQQLìðQUL)ôLL-LVLLL¢ vLìôLÐL-L†L%zõLL VLèðLìôLL­ìLo­L«­LìLLÅVRR^¥¥¥^^^^-L)LV¥L=ðf £ LL{V-*LF-L*L)L*V-*R ^ ^èL/“°*öþ)¥r9LòLLLLxVõL=VLÊþ!r9*L9**L-L-L·VFr!L†L†L  LLL­­LÐL*L†L%zLL­­LL­­LL­­LL­­LLLØ­LzLL­­LLLL­z LèL9L¥ vLìL¦ íL†L¬LÐLÝLõLÐLÝLõL†L%zL%zL¿­LVÐL§ L†L%zLQ LÐLÝLÒõLÐLÐL§ Ló­LÐL§ Ló­Lì­L†LQ LmVL†L%zL%zL±­Lì­LõL†L%zL%zL¿­LV@L-ðLÐLðL²­L†L%zLðL²­LåVL)V)LÐL*L†L%zLòL=VL-Rr© 7XÝ7Y|7Z7[Ò7\L/`ÐS­7‚ _€ èLèðâ^^^'^1^;^E^O^Y^b_L)L® þ"^V´ L)L® þ"^J‡L)L® þ"^>`L)L® þ"^2L)L® þ"^&bL)L® þ"^µ L)L® þ"^¶ L)L® þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9L)L)LzrrèLèðâ ^^%^/^9^C^M^W^a^k^u^^‰^’rL)L® þ"^†uL)L® þ"^zvL)L® þ"^nwL)L® þ"^b|L)L® þ"^V}L)L® þ"^JÈ L)L® þ"^>…L)L® þ"^2É L)L® þ"^&Ê L)L® þ"^sL)L® þ"^Ë L)L® þ"^¥åèLèðâ^+^5^?^I^S^]^g^q^{^…^^™^£^­^·^Á^Ë^Õ^ß^é^ò¼L)L® þ"^æL)L® þ"^ÚŽL)L® þ"^ÎL)L® þ"^ÂÙ L)L® þ"^¶‘L)L® þ"^ª’L)L® þ"^ž“L)L® þ"^’”L)L® þ"^†•L)L® þ"^z–L)L® þ"^nL)L® þ"^bÚ L)L® þ"^VÛ L)L® þ"^JÜ L)L® þ"^>—L)L® þ"^2˜L)L® þ"^&™L)L® þ"^šL)L® þ"^›L)L® þ"^¥å9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzåå9LìLzååèLèðâ^ ^^^)^2ø L)L® þ"^&ù L)L® þ"^ú L)L® þ"^û L)L® þ"^¥å9L-L-L-L!zrr9LìL%zåå9LìLzåå9L)L)LzrrèLèðâ^ ^^^)^2 L)L® þ"^& L)L® þ"^ L)L® þ"^ L)L® þ"^¥å9LìL%zåå9LìLzåå9LìLzååèLèðâ^ ^^^& L)L® þ"^ L)L® þ"^ L)L® þ"^¥å9L)L)L!zrr9LìL%zåå9LìLzååèLèðâ^ ^^^& L)L® þ"^ L)L® þ"^ L)L® þ"^¥å9LìL!zåå9L)L)L%zrr9L)L)LzrrèLèðâ^^^'^1^;^E^O^Y^b% L)L® þ"^V& L)L® þ"^J' L)L® þ"^>( L)L® þ"^2) L)L® þ"^&* L)L® þ"^+ L)L® þ"^, L)L® þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå9L)L)Lzrr9L-L-L-Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)LzrrèLèðâ^ ^^^& L)L® þ"^ L)L® þ"^ L)L® þ"^¥å9LìL!zåå9L)L)L%zrr9L)L)LzrrèLèðâ^+^5^?^I^S^]^g^q^{^…^^™^£^­^·^Á^Ë^Õ^ß^é^ò·L)L® þ"^æ¸L)L® þ"^ÚºL)L® þ"^λL)L® þ"^¼L)L® þ"^¶B L)L® þ"^ª¿L)L® þ"^žÁL)L® þ"^’ÂL)L® þ"^†C L)L® þ"^zD L)L® þ"^nE L)L® þ"^bF L)L® þ"^VG L)L® þ"^JH L)L® þ"^>I L)L® þ"^2ÀL)L® þ"^&J L)L® þ"^K L)L® þ"^¾L)L® þ"^¥å9LìL!zåå9LìL%zåå9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L-L-L-Lzrr9LLLLLLzrr9L-L-L-Lzrr9L)L)L zrr9L)L)L zrr9LìL zåå9L-L-L-L zrr9L)L)L zrr9LìLzåå9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)Lzrr9L)L)LzrrèLèðâ^^^3^B^I^]^d^k^èQLèL± þ!¥^èQLLìL³ ­ˆLˆ¥^ièQLèf^¥^XèQLè¥^OèQLLìL° ­ˆLˆ¥^9èQLè¥^0èQLè¥^'èQLìUL}L)L² VL}ˆLìL9𭈥¥^¥åìLèðL!´fì^^^}L-L² VL}ˆL)ˆ¥rèLèðâ ^^^^!^#^%^'^)^+^-^/^1^2^. ^*3^& ^"4^^w ^x ^y ^z ^  ^{ ^¥åèLèðâ^+^-^/^1^3^5^7^9^;^=^?^A^C^E^G^I^U^a^h^w^^}'^y}^u-^qA^m&^iÇ^eÀ^aÁ^]ƒ^Y…^U} ^Q¹^M~ ^I ^EèQLèL9þ!¥^7èQLèL=þ!¥^)èQLè¥^ èQLLìˆL€ ˆ¥^èQLL숥^¥å‚ 7ª U7« F7¬ ù7­ ­ #ýK7® ­ #i£W7¯ ¬ #CÚÚ7° ­ #Ñ(07± ¬ # ÐÇ7² ¬ #”ãì7³ · LèL¹ í7¸ ª L¸ ?ÏÄ7èL» í7º ª Lº ?öŠ˜,èL½ í7¼ ª L¼ ?J°ô+èL¿ í7¾ ª L¾ ?|5ÄèLÁ í7À ª LÀ ?ñœÄÅèLà í7 ª L ?в¦ÊèLÅ í7Ä ª LÄ ?ϱpüèLÇ í7Æ ª LÆ ?̨gõ¥Ì LèL!õ7Í ª LÍ ?Ç–AèL%õ7Î ª LÎ ?ý?èLõ7Ï ª LÏ ?Ùî-èLõ7Ð ª LÐ ?8gîèLõ7Ñ ª LÑ ?!@èLõ7Ò ª LÒ ?ìNÔèLõ7Ó ª LÓ ?Úâ7èLõ7Ô ª LÔ ?%¹PèLõ7Õ ª LÕ ?ý.Õ7èL õ7Ö ª LÖ ?ÚÒÐ9èL õ7× ª L× ?‘³êÜèL õ7Ø ª LØ ?/ðlë¥Ý LèL!õ7Þ ª LÞ ?œ¼4èL%õ7ß ª Lß ?ö¤ïèLõ7à ª Là ?iú3èLõ7á ª Lá ?µ¡ŠÝèLõ7â ª Lâ ?“ñèLõ7ã ª Lã ?½b° èLõ7ä ª Lä ?eÍ9èLæ í7å ª Lå ?4wßèLõ7ç ª Lç ?"P=èL õ7è ª Lè ?ò)èL õ7é ª Lé ?üüÒèL õ7ê ª Lê ?©é¼8èL õ7ë ª Lë ?–xÇÃèL õ7ì ª Lì ?ŠˆÏ èLõ7í ª Lí ?øº[èLï í7î ª Lî ?Ci‹ÝèLñ í7ð ª Lð ?ÉnN èLó í7ò ª Lò ?ˆ‰-ÆèLõ í7ô ª Lô ??¢ÁÎèL÷ í7ö ª Lö ?Óq&¥ü LèLþ í7ý ª Lý ?Ÿ%ˆòèL í7ÿ ª Lÿ ?1±ÛïèL í7 ª L ?ƒñóÁèL í7 ª L ?DÏ\Ï¥ LèL!õ7 ª L ?GÊAÝèL í7 ª L ? §^ËèL í7 ª L ?¶ìÉçèL í7 ª L ?Šº´Ð¥ LèL í7 ª L ?iT++èL í7 ª L ?¸sä&èL í7 ª L ?€†(¥ LèL í7 ª L ?=.#êèL" í7! ª L! ?(O9øèL$ í7# ª L# ?/òÜ¥- LèL/ í7. ª L. ?€3ÇèL1 í70 ª L0 ?óFÚèL3 í72 ª L2 ?˜éà'èL5 í74 ª L4 ?61èL7 í76 ª L6 ?Î%ûèL9 í78 ª L8 ? ŸK1èL; í7: ª L: ?ú½…*èL= í7< ª L< ?ð¤vÄ¥> LèL? í7 ª L ?=.#êèL@ í7! ª L! ?(O9øèLA í7# ª L# ?/òÜ¥L LèLN í7M ª LM ?ÞN+ôèLP í7O ª LO ?ÈÊÉÞèLR í7Q ª LQ ?5ê`*èLT í7S ª LS ?ƒK9çèLV í7U ª LU ?Ã\ÏèLX í7W ª LW ?¢OÝ-èLZ í7Y ª LY ?‚›4èL\ í7[ ª L[ ?}´ÉèL^ í7] ª L] ?#oÍÜèL` í7_ ª L_ ?Ÿ)óèLb í7a ª La ?' ¥ÝèLd í7c ª Lc ?ëýãèLf í7e ª Le ?©]ôãèLh í7g ª Lg ?Mû³ÞèLj í7i ª Li ?@ü\ èLl í7k ª Lk ?Àžð,èLn í7m ª Lm ?öÙÛ-èLp í7o ª Lo ?ÓÚ%ÛèLr í7q ª Lq ?éÚÎèLt í7s ª Ls ?,™Šó¥¯ LñLèLìLu í‰èðav L| L)LìL vL‚ Lì?í"7>‚ L-?1€mø‚ L)?ÝË':‚ L?ð‘§Î‚ L?”]UR‚ ‚ 7]L/`ÐS­7ë _eèLèðâ^ ^^^&¼ L)L‰ þ"^½ L)L‰ þ"^¾ L)L‰ þ"^¥ååÄ L.L þ"rìLìL9ðþ"rèL• L– VL!´fì^ìL• L– VL!´fè^ ìLìL— þ"rèLL  þåìLìL¯ þ"rèLèðL%´fPèQððL!´fAèUðL!´fèQôLè¥^=¥^^èQôLìULìLL)L9ðVL´ VR^¥¥^^^^)L)L¬ þ*¥rìLìL° þ"rèLèðL ´f4èQLìUL)*L)L)LLLL9ðVL¥ VR^(¥¥¥^^èLL´fè^LL)L¥ þC¥¥rèLèðL ´f4èQLìUL)*L)L)LLLL9ðVL¥ VR^(¥¥¥^^èL-L!´fè^LL)L¤ þC¥¥rèôLìðLìL9ð­LìõRåèôLìðLìLìLèðâ^^$^0^E^g^¸^Ò^ì^ÿèQLèLŠ ­LŽ ­¥^ìèQLèLŽ ­¥^ÞèQL9ðLìL¸ VLµ ­¥^ÇèQLìUL9LÎ íL)L¸ VLìL˜ V¥¥^£èQLìUL)*L)L)L)LèðLèL!´b èL%´b ^‹ ^ìQLèL9ð­L ­¥^¥¥L± V¥¥¥^PèQLìULìLìL9ð­Lª V¥¥^4èQLìULìL9ð­LìL‘ V¥¥^èQLìULìLìL¡ V¥¥^¥õRåèLèðLèL ´bèL ´b¥^ ^¥^^ì*LèL9ð­R^ ¥^¥¥åèLèðâ^^ ^0^@^P^`^p^nèQLèL ­¥^j¥^\èQLèLˆ ­¥^X¥^JèQLèL¦ ­¥^F¥^8èQLèL¢ ­¥^4¥^&èQLèL™ ­¥^"¥^èQLèLŒ ­¥^¥^Ä L~L þ"¥åèL)õLèððLèL!´bèL%´b¥^%^!ìôðL!´f À ¥^'^¥^^ Á ¥^^¥èôðL%´fÁ ^^^ ¥rèL)õLèððL!´fì^^^èôðL!´fÀ ^^^ ¥rèðLèLèðLèL´bèL!´b¥^ ^ìULèL9ð­R^¥^ ¥^^¥¥¥åìôL)ðLìL¨ LL-L%zõRrìLèðLèL!´b èL%´b^'Ä L¡L þ2^ìULèL¨ LL² L%zõ¥^¥¥rìL¨ L)L² L%zõrèL9Àf=^3f LìLš V^ LìL’ VL¨ LìL-L%ˆLð­L%z¥åìLèðLèL!´b èL%´b^TÄ L¬L þB^HìQL)ULñLèLL-L LLLØ v‰èða!Lì­L¨ LL² L%zõ¥¥¥^¥¥rèðL¨ L9L)L=L VLL%z¥r)LèðLèL!´b èL%´b^IÄ L¼L þB^=ìQL)ULìLLÚ vLìLL” ­Lž VLèL¨ LL² L%zõ¥¥¥^¥¥rj"LL§ VLèLìðLL9V‰¥l^ALèÐL¸f èL« ­aèðLw ù´f¨ L)L­ñLõLL%z^ ^èL/“°*öþ1¥r¨ LìLæñL¶ õL-L%zrèL9ðþåèLèðLèL!´b èL%´b ^8² ^4ìQLèLèððL´fèðQLè¥^¥^^¨ L)L² L%z¥¥^¥¥åèLèðL%´g9èQððL%´g*èQðQððâ^^ ^ ^^^`^Ã__ èQðQðQLìQðUL)QôL-ULèL9ð­LèðLìôLèL)LL=LLVLõLVõRR^Ú¥¥¥¥^´èQðQðQLìQðQðUL)QðUL-QôLUL¨ LL=LLVL¨ LLL%zõL)L%zL9ð­R^w¥¥¥¥¥^OèQðQðQLìQðUL)QôL-UL¨ L)L¨ LLL%zõL)L%zL9ð­R^(¥¥¥¥^^^^^èLLìõLL² õõ¥¥åèLèôðLèL!´b èL%´b^PÄ LæL þ*^DìðL)ôLèQLìULñLèLìLL9L=LLLà v‰èðaLìþI¥¥¥¥¥^¥¥åèLèðLèL!´bèL%´b¥_@_<² L9L² õL² z¥_>_'ìQððLèL!´bèL%´bR__ Ä LL VR__ù)QðQððâ^^^x_R_Ú_{_à_-R_à_Ö)QðQðQL-QðULQôLULèL=ð­LèðLìôL)QLìLìL9LæLL L­LL õLVzRR_•¥¥¥¥_p)QðQðQðL!´fW)QðUL-QôLULèL=ð­LèðLìôL)QL9LæL)L¶ LLõLVLìLzRR_-¥¥¥^^)QðQðQL-QðULQôLULèL=ð­LèðLìôL)QLLL¹ ­L9LæL)L¶ LL L Lº VõLVLìLzRR_¹¥¥¥¥_”)QðQðQL-QðQðULQðULQôLULèL=ð­LèðLìôL)QLL9LL› ­LæL)L¶ LL­ L L¸ VL Lº VõLVLìLzRR_1¥¥¥¥¥_ )QðQðQL-QðQðULQðQð*LQðULQôLULèL=ð­LèðLìôL)QLL­LLìL¹ ­L9LæL-L L LŸ ­L· VLLL Lº VõLVL)LzRR_¥¥¥¥¥¥_g)QðQðQL-QðQðULQðULQôLUL¨ LLLL VL¨ LLL%zõL)L%zL=ð­R_'¥¥¥¥¥_)QðQðQL-QðULQôLUL¨ L)L¨ LLL%zõL)L%zL=ð­R_Ö¥¥¥¥_±)QðQðQðLèL%´bèL!´cR_›_-QðQðQQðLèL!´bèL´bÑR_y_òQðQðQQQLQðQðQULQðQðULQðQôLQðULQôLULèL=ð­LèðLìôL)QL¨ LLL£ VL9L%zL æL)LL¨ L L ­L¨ L LLL%ˆL¡ VõL L%zL%zõL VLìLzRR _Ñ¥¥¥¥¥¥¥_)QðQðQQQððL´g,QðQðQQQLQðQðQQULQðQðQULQðQðULQðQôLQðULQôL ULèL=ð­LèðLìôL)QLELŒ ­L® ­L» LLœ VLL  VL¨ LL L L› ­LL  VL VL¨ L-L9L%zL%zL æL-LL¨ L LELŠ ­LŽ ­õL¨ LL ­L¨ LLL!L¡ VõLL%zL%zL%zõL VL)LzRR _“¥¥¥¥¥¥¥¥^^QðQðQQQLQðQðQQULQðQðQULQðQðULQðQôLQðULQôL ULèL=ð­LèðLìôL)QL¨ LLL L› ­LL  VL VL9L%zL æL)LL¨ L L ­L¨ L LL!L¡ VõL L%zL%zõL VLìLzRR ^¬¥¥¥¥¥¥¥¥^¥^w-QðQðULQðQôLQðULQôLULèL=ð­LèðLìôL)QL9LæL)LL LL VLõL VLìLzRR^-¥¥¥¥¥^¥^^¥^¥èL² L9L)õL² z¥¥åèLèôðLèL!´b èL%´b^iÄ LüL þ*^]ìðL)ôLèQLìULñLèLL)L9L=LLLLL LLLL L Lâ v‰èðaLìþI¥¥¥¥¥^¥¥åèLèðLèL!´b èL%´b^zÀ L² L² z^nìQðL)QôL-ULìðL9ð­LèðLìôL)QLL=ð­LèðLìôL)QLL)LVLL)Lº VL¨ LL õLL%zzR¥¥¥^¥¥åèLèððLèL!´bèL%´b¥^ƒ^Á L² L9z¥_Õ^oìðQððL!´f]ìðQôL)ðUL-ôL)L=­f.èL)õLð­LèðLìôL)QLìLìLLLVzR^ À L)LzR_t¥¥¥^¥^^¥èôðL!´fÄ LCL V_O^^èððL%´fÊèðQððL%´fºèôðL%´f­èðQðQLèL­f•)L­LèðLìôLìLð­LèðLìôL)QLLð­LèðLìôL)QLLÀ L– VL!´fÀ LLL­Lº VLz^/ìLÀ L– VL!´fÀ ^ LL)Lº VLLLVzR ¥_Œ^¥^¥^^ ^^^^èôðL%´gcèôQL)L­LèððL!´f"èôðL!´fèQLèLð­¥_+¥^^^^èôðL!´f\èðLìQLìL­LèðLìôL)QLLð­LèðLìôL)QLìLL)Lº VL LL VLLVzRR^Ä¥¥^^èððL!´f§èôLìQLìL­LèðLìôL)QLLð­LèðLìôL)QL“ LL¸ VL ­fLÀ L– VL!´f#À LLL­Lº VL LL Vz^,L)L VLL)Lº VL LL VLLVzRR^¥¥^^Ä L\L V¥¥^¥^^Ä L_L þ"¥å9L¨ L)L² L%zõåèQLìôL)ðL)L9­L)LèðLèL!´b èL%´b ^)^ìQLèLL=V¥^¥¥LèLæ íL-L¸ þBRRå9L=Lç vL)L¸ VL© ­L¨ L³ L² L%zLìõLèL­LèðLìôL)QLèLèðLèL!´b èL%´b^B^?ìQððLèL!´b èL%´b^$è LLV^)QðQôLé LìLV¥^¥^¥¥)L)LÀ L– VL!¸õRrë 7ƒ |7„ Ò7… ‚ 7† ù7‡ … #JEA 7ˆ ‡ #ýK7‰ † #в¦Ê7Š ‡ #Ø>ã37‹ … #ü¡à7Œ … #±nß7 † #óFÚ7Ž … #û°½77 ‡ #ÆFÌ7 † #ú½…*7‘ … #-Í;Ý7’ ‡ #‡ÊM7“ „ #cÙV7” … #}ëw7• ‡ #e Ð7– … #Õ¯†î7— † #617˜ … #E”Ïê7™ … #{ÔÎô7š ‡ #-q7› … #^_7œ ‡ #O177 „ #\ÀÃ7ž … ##©{!7Ÿ … #h…ŠÍ7  † #ð¤vÄ7¡ … #¨„¾+7¢ … #l»Óð7£ … #µœ7¤ … #ªÌÊ7¥ … #žj 7¦ „ #•r9&7§ ‡ #!Ê|Õ7¨ „ # ÐÇ7© † # ŸK17ª ‡ #7ä.7« … #!vü7¬ ‡ #i£W7­ … #o¸…ó7® … #‚d¤<7¯ … #§}«7° † #Î%û7± ‡ #MR±7² … #Åb 7³ … #à[¶ 7´ † #˜éà'7µ … #È©Õ7¶ … #  r7· „ #œ S7¸ „ #æ”7¹ „ #ÚáÓ7º … #?ºÊâ7» ¿ LèL!õ7À ƒ LÀ ?¤Ã_'èL%õ7Á ƒ LÁ ?aÿý7èLõ7 ƒ L ?Õ£u¥à ñLÅ ñLèLÆ íL• LÇ LÈ LÉ LñLèLìLÊ í‰èðaË LñLñLñLñL-LLÌ í‰-ð2)L-LÍ í‰)ð2ìL)LÏ í‰ìðeèLìLÐ í‰èðaÑ LÒ LÓ LñLèLìLÔ í‰èðaÕ LÖ L× LÙ LÛ LLÜ íLÝ L“ LLÞ íLß LLLá vLL LLLLLL LL LLã v LñLñLìLìL-LLä v‰ìðeèLLL-LLLL LLL LL!LLå v ‰èðaLL)LLê vLë L?ÄS2ë L?ÿë L?QôD&ë L?å©âÒë L?þŸ<ë L?׬êë L?!Úúë L ?.)jêë L ?hÙë L ?LL\3ë L ?[ß ßë Lì?î9VÈë L?¥fŽë L?ÈÅiÆë L?1×(íë L?¨ƒý7ë L?C¦<ë L?o$¾Ëë L?Ä«ûæë L?Jpúë L?‘óÃë L?Ÿ=pöë L?n±úë L?ÈË)óë L?ƒ­´èë L)?)Dd!ë L-?]ûKûë L?â¹ÄÁë L?½õÁë L?qY} ë L ?_ýËë L?SµtR ë ë 7_œ7aU7b47cF7dL/`ÐS­7 _4 èLèðLèL!´b èL%´b^„L-Lï þ*^L-Lï þ*^¥¥å9LLLLL%zrrèLèðLèL!´b èL%´b ^!^ ì*Lè¥^¥¥å)L)L)LL9­LL9­Ló VL%ˆLö þ^GìQL)UL-*LLLL=VL)L)LLL=VL=þ“¥¥¥^ú L=Lñ þr^¥¥¥¥¥^ú L?Lñ þJ^¥¥^óèL)Lˆ¼fÌ)LèðLèL%´b èL!´b¦^¯ìQL)UL-*LèL9­L-L9­ÀfLLL=VL)L)L=þk^b)LèðLèL%´b èL!´b>^GìQL)UL-*L L LL=VL)L)LLL=VL=þ“¥¥¥^ú LILñ þr^¥¥¥¥¥^ú LKLñ þJ^¥¥^LLLLLó VL%ˆLö þLRrèLèðLèL!´b èL%´b^Wú LTLñ þ*^KìQðL!´fìUL)*LèR^5¥¥^^ìQL)UL-*L)L9ð­L)L)L=þK¥¥¥^¥¥åèLèðLèL!´b èL%´b^Iò Lð æ^@ìQðL!´fìUL)*LìR^*¥¥^^ìQL)UL-*L)L9ðæ¥¥¥^¥¥åèL)õLèððL!´fèôLè¥^6¥^^èôðL!´fèðLè¥^¥^^)L)L9æL-L=­Lþ3¥rèLèðLèL!´b èL%´b^}õ LLõ L%Lö þL^kìQL)UL-*LL)LVLèL!´f^=èL!ÄfLLL9ðVL-L-L=þc^-L-LLLL9ðVL=þc¥¥¥¥^¥¥rèL-õLèððL!´fL-L-L9V^ç^^èôðL!´fL-LL9V^Ë^^èððL%´f²èôðL%´f¥èðQLìðUL)ð*L-ð*LôQLôULô*Lô*LLìLˆ¼f LL LL L L=ðVLV^8èLLˆ¼f  L L LL=ðVL-L-LV^ L L LVR^$¥¥¥¥¥¥¥¥^^^^ú LLñ þ:¥rèL)õLèððL!´fèôLè¥^9¥^^èôðL!´fèðLè¥^"¥^^-L-L-L9æLL=­LþD¥rèLèðLèL!´b èL%´b^°Lõ Lõ z^¥ìQL)UL-*LL)LVLèL!´f L)Lz^pèL!Äf7LLL9ðVLèðLìôL)QLìL L)LLL=VLzR^4LL-L9ðVLèðLìôL)QLìLìL LLLL=VzR¥¥¥¥^¥¥rìðLìL-ôL9VL)ðõrõ Lìõåõ Lî õåèôLèðL!´f^^^¥åèLèðLèL!´b èL%´b^B^?ìQL)UL-*L9L)L=ðVLèL!´bèL!Äf-^ìLðþA¥¥¥¥^¥¥åñLèL)LL-L v‰èða)ôLìþ!¥rèLèðLèL!´b èL%´b ^lõ ^hìQL)UL-*L9L)L=ðVLèL!´f-L)LþJ^1èL!Äf-Lð­L-L-LþS^-L-L-Lð­LþS¥¥¥¥^¥¥åñLèL)LL9LL=L v‰èða)ôLì­L-ðõ¥rèL)õLèððL!´fèôLè¥_5¥^^èôðL!´fèðLè¥_¥^^èððL%´gèôðL%´föèðQLìðUL)ð*L-ð*LôQLôULô*Lô*LLìÀfWèL%´f9L-L L=V^?9LL LVLèðLìôL)QL9L LLðVL L LLðVLVR^VL%´f9LL L=V^?9L-L LVLèðLìôL)QL9L-LLðVLL-LLðVLVRR^$¥¥¥¥¥¥¥¥^^^^ú LñLñ þ*¥rìðLñLèL)L9L=LLL v‰èða-ôL-ôL)VL)õRrèL)õLèððL!´fèôLõ ¥^í¥^^èôðL!´fèðLõ ¥^Õ¥^^èððL%´fºèðQLìðUL)ð*L-ôL9L-L)L=VLèôLèL´bèL´b9¥^k^gìðL)QL9LL-LðVLL-LðVLVR^H¥¥^6ìðL)QL9LL-LðVLLLLðVLVR^¥¥^¥ú LLñ V¥R^¥¥¥¥^^ú L Lñ þ*¥rìðLñLèL)L9L-L=LL v‰èða-ôL-ôL)VL)õRrèL)õLèððL!´fèôLõ ¥^ì¥^^èôðL!´fèðLè¥^Õ¥^^èððL%´fºèðQLìðUL)ð*L-ôL9L-L)L=VLèôLèL´bèL´b<¥^k^gìðL)QL9LL-LðVLLLLðVLVR^E¥¥^3ìðL)QL9LL-LðVLL-LðVLVR^¥¥^¥ú L Lñ V¥R^¥¥¥¥^^ú L#Lñ þ*¥rìðLñLèL)L9L-L=LL v‰èða-ôL-ôL)VL)õRrèLèðLèL!´b èL%´b^0^-ìQL)UL-*L)L9ð­ìL=­èL9ðþ9¥¥¥^¥¥åñLèLìLL v‰èðaìôLìþ!¥r 7ì ù7í í #¥i7î í #ýK7ï í #&]7ð í #ÆFÌ7ñ í #¶’¥ê7ò í #¤ S7ó ô LèL!õ7õ ì Lõ ?mªèL÷ í7ö ì Lö ?"6ã3¥ø LèLù íLìLìLû vLñLñLìL)LLü v‰ìðeèLìLý í‰èðaèL)LLþ vLñLñLìL)LLÿ v‰ìðeèL)L)LLL v‰èða-LL)L vLñLñLìL)LL v‰ìðeèLL í‰èða L L L LL L vLLLL vLLL L vLL L L vL L L?eç& L ?Úên L?…c¥ï L?Dœˆ L?À‰HÅ L ?¸¢Æ L?î9VÈ L ?ê3eÆ Lì?ſŠL?8©– L-?¿ > L?çL L?Üà? L?:Úï L)?\i L?üfü L ? ÐÇ L?ͱJ L ?‚xøà L?!òIR  7eL/`ÐS­7¦ _`OèLèðLèL!´b èL%´b^[ L-L? þ*^\ L-L? þ*^¥¥å9LìL!zåå9LìL%zåå°LìL? þå9L)L)LLúÿ4zrrèLèðLèL!´b èL%´b^!ìQLe LìL+ ­ˆ¥^ìQLf L숥^¥¥åìLìLc VL9 ærèLèLèLÇ´bÚèLÈ´bÛèLÊ´bÜèLÉ´bÝèLÏ´bÞèLдbßèLÑ´bàèL<´báèLôbâèLÄ´bãèL¡´bäèL¼´båèL½´bæèL¿´bçèLÀ´bèèL¾´béèL:´bêèL;´bëèLi ´bìèLœ´bíèL²´bîèL³´bïèL´´bðèLl´bñèL8´bòèL7´bóèL9´bôèL¶´bõèL·´böèLµ´b÷èL¸´bø¥^þ^úýÿÿÿ¥^ø^òýÿÿÿ¥^ð^êýÿÿÿ¥^è^âýÿÿÿ¥^à^Úýÿÿÿ¥^Ø^Òýÿÿÿ¥^Ð^Êýÿÿÿ¥^È^Âýÿÿÿ¥^À^ºþÿÿÿ¥^¸^²þÿÿÿ¥^°^ªÿÿÿÿ¥^¨^¢ÿÿÿÿ¥^ ^šÿÿÿÿ¥^˜^’ÿÿÿÿ¥^^Šÿÿÿÿ¥^ˆ^‚ÿÿÿÿ¥^€^zÿÿÿÿ¥^x^rÿÿÿÿ¥^p^jÿÿÿÿ¥^h^bÿÿÿÿ¥^`^Z!¥^X^R!¥^P^J%¥^H^B%¥^@^:¥^8^2¥^0^*¥^(^"¥^ ^¥^^¥^^ ¥^^¥¥åìL9­LìL9­LìLìÄf^ìLì´f )L¸^RrèLèðLìôLìLèðL´faèQLìUL)*L)LL9Vf<LL-L=ðVLèLQ ­L)LQ ­LVLL)LL# Võ¥R^6^R^ ¥¥¥^^LQ ­LLQ ­LVLLLL# Võ¥RrìLèðLìôLìLèðL´fAèQLìUL)*LLL9VL-L LL L=ðVL-L# VõR^#¥¥¥^^L)L9VLLL Võ¥RrèLèðLèL!´b èL%´b^o-L; LÒLA L: Võ^[ìQL)ULìL6 ­LèL0 LL0 LLL9ðVL; L%zL%zL< ­õLìL; LL-LN ­L: VõR¥¥^¥¥rèLèðLèL!´b èL%´b^h-LÒL7 ­L ­õ^UìQL)ULìL6 ­LèLìLL7 ­L ­õL0 LL0 LLL9ðVL; L%zL%zL& Võ¥¥¥^¥¥rèLèLèL³´bèL´´bèLI´bèLº´b¥^"^¥^^¥^^¥^^ ¥^^¥¥åìL` ­LìL9ærèL)õrèLèLJ ­Lj L9ð­l^$LèL! ´f ìL-LJ ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f )LLJ ­´fR^¸^èL/“°*ö­¥L0 L)L)L%zR^¥¥¥ìL!LL VððL%´fSìL!LL VôL)L%L@ Vj L=ð­l^%LèL! ´f )LLJ ­´fR^L^èL/“°*ö­¥LèR^E¥¥^^ìL!LL VððL!´f!ìL!LL VôL)L%L@ V; R^¥^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fãìL!LL VôL)L%L@ Vj L9ð­l^%LèL! ´f )LLJ ­´fR_  ^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´f1ìL!LL VôL)L%L@ V-LL)L=VLVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ V&LLVR^¥^^! L/&]­¥¥R_ ¥¥^^ìL!LL VððL´gOìL!LL VðQðL!´g8ìL!LL VôL)L%LL VððL´g)L%LL VðQðL´fù)L%LL VðQQL-L%LL VôLLL@ Vj  Lð­l^%LèL! ´f LLJ ­´fR_W ^èL/“°*ö­¥Lj  Lð­l^%LèL! ´f LLJ ­´fR_& ^èL/“°*ö­¥Lj  Lð­l^%LèL! ´f LLJ ­´fR_õ ^èL/“°*ö­¥L0 L-LõL-L%zLìLP VLL)LQ ­L=VLVR_Á ¥¥¥¥¥^¥^^¥^ ¥^^^^ìL!LL VððL´gÂìL!LL VðQðL%´g«ìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR_9 ^èL/“°*ö­¥L-L!LL VððL´gI-L!LL VðQðL´g/-L!LL VôLL%L@ Vj  Lð­l^%LèL! ´f LLJ ­´fR_Ì ^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´fìL!LL VðQðL´fyìL!LL VôL)L%L@ Vj  Lð­l^%LèL! ´f )LLJ ­´fR^j^èL/“°*ö­¥LLL)LN ­L> VLL)LQ ­L=VLVR^=¥¥^^^^L-LA L> VLLLQ ­L=VLV¥^ ! L/&]­¥¥R_ꥥ^R^^R^¥¥^^^^ìL!LL VððL´gìL!LL VðQðL´g†ìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR_f^èL/“°*ö­¥Lj Lð­l^%LèL! ´f -LLJ ­´fR_5^èL/“°*ö­¥LL!LL VððL´fñL!LL VðQLL!LL VôLL%L@ Vj  L ð­l^%LèL! ´f LLJ ­´fR_Î^èL/“°*ö­¥Lj  Lð­l^%LèL! ´f LLJ ­´fR_^èL/“°*ö­¥Lj  Lð­l^%LèL! ´f LLJ ­´fR_l^èL/“°*ö­¥LLLL-LL, VLL)LQ ­L=VLVR _>¥¥¥¥¥^R^¥¥¥^^^^ìL!LL VððL´g"ìL!LL VðQðL´g ìL!LL VôL)L%L@ Vj L ð­l^%LèL! ´f )LLJ ­´fR_¸^èL/“°*ö­¥L-L!LL VððL´f©-L!LL VðQðL´f-L!LL VðQQLL!LL VôLL%L@ VjL L ðVl^%LèL! ´f LLJ ­´fR_8^èL/“°*ö­¥LèðLìôLLL-L$ VLL)L=VLVR_¥¥¥¥¥^R^^R^¥¥^^^^ìL!LL VððL´fÔìL!LL VðQðL ´f½ìL!LL VôL)L%LL VððL´f˜)L%LL VðQðL´f~)L%LL VðQQL-L%LL VôLLL@ Vj  Lð­l^%LèL! ´f LLJ ­´fR_C^èL/“°*ö­¥L)LìL- VLL-L=VLVR_$¥¥¥^¥^^¥^ ¥^^^^ìL!LL VððL´geìL!LL VðQðL´gNìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR_ ^èL/“°*ö­¥L-L!LL VððL´fì-L!LL VôLL%L@ Vj  L ð­l^%LèL! ´f LLJ ­´fR_G^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´f9ìL!LL VôL)L%L@ VLL VLL)L=VLVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ V&LLVR^¥^^! L/&]­¥¥R_¨¥¥^R^¥¥^^^^ìL!LL VððL´g·ìL!LL VðQðL´g ìL!LL VôL)L%L@ Vj L ð­l^%LèL! ´f )LLJ ­´fR_*^èL/“°*ö­¥L-L!LL VððL´g>-L!LL VðQðL´g$-L!LL VôLL%LL VððL´fþL%LL VôLLL@ Vj  L ð­l^%LèL! ´f LLJ ­´fR_Ÿ^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´fKìL!LL VôL)L%L@ VLL=VLL) ­õLLI VLL)L=VLVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ V&LLVR^¥^^! L/&]­¥¥R_^R^¥^R^^R^¥¥^^^^ìL!LL VððL´gwìL!LL VðQðL ´g`ìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR_b^èL/“°*ö­¥L-L!LL VððL´fþ-L!LL VôLL%L@ Vj  L ð­l^%LèL! ´f LLJ ­´fR_ ^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´fKìL!LL VôL)L%L@ VLL)L=VLL) ­õL* VLL)L=VLVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ V&LLVR^¥^^! L/&]­¥¥R^X¥¥^R^¥¥^^^^j Lð­l^$LèL! ´f ìL-LJ ­´f¥^^èL/“°*ö­¥LèR^ ¥! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fýìL!LL VðQL)L!LL VôL-L%L@ Vj L9ð­l^%LèL! ´f -LLJ ­´fR_^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´f;ìL!LL VôL)L%L@ VLìL=VLL. ­õLLðVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ VÀLLVR^¥^^! L/&]­¥¥R_a¥¥¥^^ìL!LL VððL´fžìL!LL VðQL)L!LL VôL-L%L@ VìL­Ìf ! L9 ­LèLJ ­Lj  L­l^$LèL! ´f ìL-LJ ­´f¥^(^èL/“°*ö­¥LLìLLVLLðVR^ ¥! L/&]­¥¥R_°¥¥^^ìL!LL VððL´f‹ìL!LL VðQðL´ftìL!LL VðQQL)L!LL VôL-L%L@ VjLL LðVl^%LèL! ´f -LLJ ­´fR_*^èL/“°*ö­¥LèLLðVR_¥¥¥^^^^ìL!LL VððL´fCìL!LL VðQL)L!LL VôL-L%L@ VèL)L ­õLLðVR^À¥¥^^ìL!LL VððL ´fœìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR^c^èL/“°*ö­¥L-L!LL VððL ´f:-L!LL VôLL%L@ V)LìL=VL)L VLLðVR^¥^R^ ¥¥^^! L/&]þ!¥¥åèLQ ­LìLF ­LèðLèL´bèL´bE¥^…^ìQL)UL9L0 L-L-L%zL' VL9LQ ­LL=VLVR^{¥¥^DìQL)UL-*L)L)Lð­L)L# VL9LQ ­LL=VLVR^;¥¥¥^¥9L0 LL; L%zL' VL9LQ ­LLQ ­L=VLþ*¥¥åèLèLJ ­LìL!LL VððL´f–ìL!LL VðQL—´f€ìL!LL VôL)L%L@ Vj L9ð­l^%LèL! ´f )LLJ ­´fR_ ^èL/“°*ö­¥LèðLìôLLQ ­LìL=VLL-L VõLLðVR_Ú¥¥¥¥^^^^ìL!LL VððL´g ìL!LL VðQL´fõìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR_d^èL/“°*ö­¥LLèLJ ­LìL!LL VððL´fCìL!LL VôL)L%L@ VLQ ­LìL=VLLL& VõLLðVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ VÀLLVR^¥^^! L/&]­¥¥R_»¥¥^^^^ìL!LL VððL´g¶ìL!LL VôL)L%L@ V-LèLJ ­LìL!LL VððL´flìL!LL VðQðL´fUìL!LL VðQQL)L!LL VôL-L%L@ VLQ ­LìL=VLL-L1 VõLLðVR_¥¥^^^^ìL!LL VððL ´fôìL!LL VôL)L%L@ Vj  L­l^%LèL! ´f )LLJ ­´fR^¼^èL/“°*ö­¥LLèLJ ­LìL!LL VððL ´fCìL!LL VôL)L%L@ V LQ ­LìL=VL LLO VõL LðVR^K¥^^ìL!LL VððL!´f)ìL!LL VôL)L%L@ VƒLLVR^¥^^! L/&]­¥¥R^¥¥^^! L/&]­¥¥R^î¥^^ìL!LL VððL´fnìL!LL VðQL)L!LL VôL-L%L@ Vj L­l^%LèL! ´f -LLJ ­´fR^†^èL/“°*ö­¥L)LL)LVR^s¥¥¥^^j L­l^$LèL! ´f ìL-LJ ­´f¥^6^èL/“°*ö­¥LñLèLL=LLLv v‰èðaìLì­¥R^¥-¥^ ! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL´g9ìL!LL VôL)L%L@ Vj L9ð­l^%LèL! ´f )LLJ ­´fR_^èL/“°*ö­¥LèðLìôLìLèðL!´fÇèQðâ^^^ ^ ^^ ^=^p^±^«èQL0 L L; L%zLìL3 VL ­LLL=VLV¥^ˆ¥^vèQL0 L L; L%zLìL3 VL ­LLL=VLV¥^S¥^AèQQLìQUL0 L L-L%zLìL3 VL ­L LL=VLVR^¥¥^^^x LéLE V¥R^/¥¥¥¥^^L7 ­L ­LLV¥^ ! L/&]þ1¥¥rèLèLJ ­LìL!LL VððL´fZìL!LL VðQðL´fCìL!LL VðQQL)L!LL VôL-L%L@ VìLB ­L ­LìL9VR^©¥¥^^^^ìL!LL VððL´fìL!LL VðQðL´fjìL!LL VðQQL)L!LL VôL-L%L@ VjLL L=Vl^%LèL! ´f -LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥¥^^^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´g«ìL!LL VðQðL´g”ìL!LL VðQQL)L!LL VôL-L%L@ VLèLJ ­LìL!LL VððL´f±ìL!LL VðQLœ´f›ìL!LL VôL)L%L@ Vj  L9­l^%LèL! ´f )LLJ ­´fR^ó^èL/“°*ö­¥Lj  L=ð­l^%LèL! ´f -LLJ ­´fR^Â^èL/“°*ö­¥L0 L)LõL)L%zL4 ­R^¥¥¥¥^^^^jLLB ­L ­õL LVl^$LèL! ´f ìL-LJ ­´f¥^X^èL/“°*ö­¥Lj  Lð­l^%LèL! ´f )LLJ ­´fR^'^èL/“°*ö­¥L0 L)L)L%zL) ­R^¥¥! L/&]­¥¥R^S¥¥^^^^j Lð­l^$LèL! ´f ìL-LJ ­´f¥^^èL/“°*ö­¥LèL) ­R^ ¥! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fþìL!LL VðQðL´fçìL!LL VðQQL)L!LL VôL-L%LL VððL´f°-L%LL VðQLœ´f—-L%LL VôLLL@ Vj  L9­l^%LèL! ´f LLJ ­´fR^Ü^èL/“°*ö­¥Lj  L=ð­l^%LèL! ´f LLJ ­´fR^«^èL/“°*ö­¥L0 L)LõL)L%zR^“¥¥¥^R^^R^¥¥^^^^ìL!LL VððL%´fSìL!LL VôL)L%L@ Vj L=ð­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f7ìL!LL VðQLœ´f!ìL!LL VôL)L%L@ V; R_¥^^^^ìL!LL VððL´féìL!LL VôL)L%LL VððL´fÄ)L%LL VðQðL´fª)L%LL VðQQL-L%LL VôLLL@ Vj  L9ð­l^%LèL! ´f LLJ ­´fR^n^èL/“°*ö­¥Lj  L=ð­l^%LèL! ´f LLJ ­´fR^=^èL/“°*ö­¥L0 L)LõL)L%zR^%¥¥¥¥^¥^^¥^¥^^! L/&]þ!¥¥åèLèLJ ­Lj L9­l^$LèL! ´f ìL-LJ ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f )LLJ ­´fR^Œ^èL/“°*ö­¥L0 L)L)L%zR^y¥¥ìL!LL VððL%´fSìL!LL VôL)L%L@ Vj L=ð­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fWìL!LL VðQðL´f@ìL!LL VðQQL)L!LL VôL-L%L@ VìL= ­LL9ðVR^Ë¥¥^^^^ìL!LL VððL´fqìL!LL VðQL)L!LL VôL-L%L@ Vj L=ð­l^%LèL! ´f -LLJ ­´fR^\^èL/“°*ö­¥LèLH ­LL9ðVR^G¥¥¥^^ìL!LL VððL´f!ìL!LL VôL)L%L@ V; R^¥^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f^ìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^ù^èL/“°*ö­¥L0 LL)L%zR^楥^^ìL!LL VððL´f…ìL!LL VðQL—´foìL!LL VôL)L%L@ Vj L=ð­l^%LèL! ´f )LLJ ­´fR^w^èL/“°*ö­¥LèðLìôLL)L( VLLðVR^X¥¥¥¥^^^^ìL!LL VððL´f,ìL!LL VôL)L%L@ V0 LL; L%zR^¥^^! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL´fxìL!LL VðQL—´fbìL!LL VôL)L%L@ Vj L9ð­l^%LèL! ´f )LLJ ­´fR^3^èL/“°*ö­¥LèðLìôLìLN ­R^!¥¥¥¥^^^^A ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fOìL!LL VðQðL´f8ìL!LL VðQQL‚ ´f ìL!LL VôL)L%L@ VR^¥^^ ^^^^¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fNìL!LL VðQðL´f7ìL!LL VðQQL)L!LL VôL-L%L@ VìLN ­R^¥¥^^^^A ¥^ ! L/&]þ!¥¥åèLèLJ ­Lj L9­l^$LèL! ´f ìL-LJ ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f )LLJ ­´fR^(^èL/“°*ö­¥L0 L)L)L%zR^¥¥; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fRìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f`ìL!LL VðQðL´fIìL!LL VðQQL)L!LL VôL-L%L@ VA L; L-L VLìLL9ðVR_祥^^^^ìL!LL VððL´g!ìL!LL VðQðL´g ìL!LL VðQQL)L!LL VôL-L%LL VððL´fÓ-L%LL VôLLL@ Vj  L=ð­l^%LèL! ´f LLJ ­´fR_E^èL/“°*ö­¥LL!LL VððL´fpL!LL VðQðL´fVL!LL VðQQLL!LL VôLL%L@ VA L0 LLL%zL-L VLLL9ðVR_Ï¥¥^R^^R^¥¥^R^¥¥^^^^ìL!LL VððL´f‚ìL!LL VôL)L%LL VððL´f])L%LL VðQðL´fC)L%LL VðQQL-L%LL VôLLL@ VìLS ­LìLL9ðVR_,¥¥^¥^^¥^¥^^ìL!LL VððL´fúìL!LL VðQL)L!LL VôL-L%L@ Vj Lð­l^%LèL! ´f -LLJ ­´fR^³^èL/“°*ö­¥LèðLìôLjL LðVl^%LèL! ´f LLJ ­´fR^y^èL/“°*ö­¥LèðLìôLL!LL VððL´f>L!LL VôLL%L@ V0 LLL%zLZ ­L)L L9ðVR ^'¥^R^¥¥¥¥¥¥¥¥^^! L/&]þ!¥¥åèLèLJ ­Lj L9­l^$LèL! ´f ìL-LJ ­´f¥^q^èL/“°*ö­¥LèðLìôLjL L=ðVl^%LèL! ´f LLJ ­´fR^7^èL/“°*ö­¥LèðLìôL0 LL-L%zLìLVR^¥¥¥¥¥¥! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL´fUìL!LL VôL)L%L@ VjLL9Vl^%LèL! ´f )LLJ ­´fR^%^èL/“°*ö­¥LèR^¥¥^^-L; õ¥^ ! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL ´flìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR_ì^èL/“°*ö­¥LèðLìôLL)L" VLìL=VR_Ï¥¥¥¥^^ìL!LL VððL´feìL!LL VðQðL´fNìL!LL VðQQL)L!LL VôL-L%L@ VLN ­L; L-L VLìLLðVR_Y¥¥^^^^ìL!LL VððL´g&ìL!LL VðQðL´gìL!LL VðQQL)L!LL VôL-L%LL VððL´fØ-L%LL VôLLL@ Vj  Lð­l^%LèL! ´f LLJ ­´fR^·^èL/“°*ö­¥LL!LL VððL´fuL!LL VðQðL´f[L!LL VðQQLL!LL VôLL%L@ VLN ­L0 LLL%zL-L VLLLðVR^<¥¥^R^^R^¥¥^R^¥¥^^^^-Lõ¥^ ! L/&]þ1¥¥rèLèLJ ­LìL!LL VððL´f®ìL!LL VðQðL´f—ìL!LL VðQQL)L!LL VôL-L%LL VððL´f`-L%LL VôLLL@ Vj  L9ð­l^%LèL! ´f LLJ ­´fR^:^èL/“°*ö­¥L0 LL)L%zR^'¥¥^R^¥¥^^^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f~ìL!LL VôL)L%LL VððL´fY)L%LL VðQðL´f?)L%LL VðQQL-L%LL VôLLL@ V0 L)L; L%zR^Ë¥¥^¥^^¥^¥^^ìL!LL VððL´f“ìL!LL VðQL)L!LL VôL-L%L@ Vj L9ð­l^%LèL! ´f -LLJ ­´fR^R^èL/“°*ö­¥LL!LL VððL´f!L!LL VôLL%L@ VìR^#¥^R^ ¥¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f±ìL!LL VôL)L%LL VððL´fŒ)L%LL VðQðL´fr)L%LL VðQQL-L%LL VôLLL@ Vj  L9ð­l^%LèL! ´f LLJ ­´fR^6^èL/“°*ö­¥L0 L-L)L%zR^#¥¥¥^¥^^¥^¥^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fRìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fÐìL!LL VôL)L%L@ V-LèLJ ­LjL L9ðVl^$LèL! ´f ìL-LJ ­´f¥^*^èL/“°*ö­¥LèðLìôLìLM ­LìL=VR^^¥¥¥j  Lð­l^$LèL! ´f ìL-LJ ­´f¥^*^èL/“°*ö­¥LèðLìôLìL ­LìL=VR^¥¥¥! L/&]­¥¥R^®¥^^ìL!LL VððL´f~ìL!LL VðQLœ´fhìL!LL VôL)L%L@ Vj L­l^%LèL! ´f )LLJ ­´fR^B^èL/“°*ö­¥LèðLìôLìL8 ­LìL=VR^)¥¥¥¥^^^^U LL=V¥^ ! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL´f(ìL!LL VôL)L%L@ V; LìL9VR_;¥^^ìL!LL VððL´f„ìL!LL VðQðL´fmìL!LL VðQQL ´fUìL!LL VôL)L%L@ VjLL=ðVl^%LèL! ´f )LLJ ­´fR_·^èL/“°*ö­¥LèR_°¥¥^^ ^^^^ìL!LL VððL%´fUìL!LL VôL)L%L@ VjLL=ðVl^%LèL! ´f )LLJ ­´fR_I^èL/“°*ö­¥LèR_B¥¥^^ìL!LL VððL´gìL!LL VðQðL´gìL!LL VðQQL)L!LL VôL-L%LL VððL´fÐ-L%LL VðQL—´f·-L%LL VôLLL@ Vj  L­l^%LèL! ´f LLJ ­´fR^’^èL/“°*ö­¥LèðLìôLjL L=ðVl^%LèL! ´f LLJ ­´fR^Y^èL/“°*ö­¥LèðLìôL0 L LL zL-L%zLìL9VR ^1¥¥¥¥¥¥¥^R^^R^¥¥^^^^! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL´f(ìL!LL VôL)L%L@ V; LìL9VR_V¥^^ìL!LL VððL%´fSìL!LL VôL)L%L@ Vj L=ð­l^%LèL! ´f )LLJ ­´fR^û^èL/“°*ö­¥LèR^ô¥¥^^ìL!LL VððL´fÐìL!LL VðQðL´f¹ìL!LL VðQQL)L!LL VôL-L%L@ Vj L­l^%LèL! ´f -LLJ ­´fR^u^èL/“°*ö­¥Lj  L=ð­l^%LèL! ´f LLJ ­´fR^D^èL/“°*ö­¥LèðLìôL0 LLõL-L%zLìL9VR^¥¥¥¥¥¥^^^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL ´fSìL!LL VôL)L%L@ Vj L9ð­l^%LèL! ´f )LLJ ­´fR^Q^èL/“°*ö­¥LèR^J¥¥^^j L9ð­l^$LèL! ´f ìL-LJ ­´f¥^^èL/“°*ö­¥LèR^ ¥! L/&]þ!¥¥åèLèLJ ­Lj L9ð­l^$LèL! ´f ìL-LJ ­´f¥_h^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f )LLJ ­´fR_=^èL/“°*ö­¥Lj Lð­l^%LèL! ´f -LLJ ­´fR_ ^èL/“°*ö­¥LL!LL VððL ´fßL!LL VôLL%L@ Vj  L­l^%LèL! ´f LLJ ­´fR^´^èL/“°*ö­¥Lj  L­l^%LèL! ´f LLJ ­´fR^„^èL/“°*ö­¥L-L)LèðL%´fèUðL!´fèQLè¥^¥^^^^-L) ­LLV¥L0 LLL%zzL0 LìL-L%z¥R^#¥¥¥^R^¥¥¥; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL ´f’ìL!LL VôL)L%L@ Vj L9ð­l^%LèL! ´f )LLJ ­´fR^_^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f -LLJ ­´fR^.^èL/“°*ö­¥L0 L)L)L%zR^¥¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­Lj L9ð­l^$LèL! ´f ìL-LJ ­´f¥_Q^èL/“°*ö­¥LèðLìôLLèLJ ­LìL!LL VððL´f¾ìL!LL VðQðL´f§ìL!LL VðQQL– ´fìL!LL VôL)L%LL VððL´fj)L%LL VðQðL´fP)L%LL VðQQL-L%LL VôLLL@ VìLLõLV VLL)L=VLVR_y¥¥^¥^^¥^¥^^ ^^^^ìL!LL VððL´fÆìL!LL VðQL´f°ìL!LL VôL)L%L@ Vj  Lð­l^%LèL! ´f )LLJ ­´fR^ô^èL/“°*ö­¥LèðLìôL; LLL-L=VL0 LL õL0 LLõL; L%zL%zL< ­õLN ­L: VLL)L=VLVR^”¥¥¥¥^^^^j  L­l^$LèL! ´f ìL-LJ ­´f¥^W^èL/“°*ö­¥LèLèðLèL!´b èL%´b^,LLV^ ìQLLõLìL VLLV¥^¥¥R^ ¥! L/&]­¥¥R^¥¥¥! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f¨ìL!LL VðQL)L!LL VôL-L%L@ Vj L9ð­l^%LèL! ´f -LLJ ­´fR_œ^èL/“°*ö­¥LL!LL VððL´f6L!LL VôLL%L@ VìL< ­L-L)L=VLVR_X¥^R^ ¥¥¥^^ìL!LL VððL´goìL!LL VôL)L%LL VððL´gJ)L%LL VðQðL´g0)L%LL VðQQL-L%LL VôLLLL VððL´føLLL VðQLœ´fßLLL VôLLL@ Vj  L­l^%LèL! ´f LLJ ­´fR_^èL/“°*ö­¥Lj  Lð­l^%LèL! ´f LLJ ­´fR_N^èL/“°*ö­¥LL!LL VððL´fJL!LL VôLL%L@ V0 L-LõL-L%zL!L% VLL)L=VLVR_ö¥^R^*¥¥¥^R^^R^¥¥^¥^^¥^¥^^ìL!LL VððL´fïìL!LL VðQðL´fØìL!LL VðQQL)L!LL VôL-L%L@ VjLL LðVl^%LèL! ´f -LLJ ­´fR_H^èL/“°*ö­¥LèðLìôL)QLjL LðVl^%LèL! ´f LLJ ­´fR_ ^èL/“°*ö­¥LèðLìôLLL-L: VLL)L=VLVR _॥¥¥¥¥¥¥¥^^^^ìL!LL VððL´fUìL!LL VðQðL´f>ìL!LL VðQQL)L!LL VôL-L%L@ VìLK ­LìLVR_l¥¥^^^^ìL!LL VððL´f<ìL!LL VðQL)L!LL VôL-L%L@ VìLD ­LìLVR_¥¥^^ìL!LL VððL´f§ìL!LL VðQL³´f‘ìL!LL VôL)L%LL VððL´fl)L%LL VðQðL!´fR)L%LL VðQQL-L%LL VôLLL@ V!L)ŒL2 ­LD ­L-L)L=VLVR_u¥¥^¥^^¥^ ¥^^^^ìL!LL VððL ´f“ìL!LL VôL)L%L@ Vj Lð­l^%LèL! ´f )LLJ ­´fR_^èL/“°*ö­¥L-L!LL VððL ´f1-L!LL VôLL%L@ V)LìL=VL)LVR^Ç¥^R^ ¥¥^^ìL!LL VððL ´f›ìL!LL VôL)L%L@ Vj L ð­l^%LèL! ´f )LLJ ­´fR^b^èL/“°*ö­¥L-L!LL VððL´f9-L!LL VôLL%L@ VìL!LR VL-L)L=VLVR^¥^R^ ¥¥^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fÎìL!LL VôL)L%LL VððL´f©)L%LL VðQðL´f)L%LL VðQQL-L%LL VôLLL@ VjLL L9ðVl^%LèL! ´f LLJ ­´fR^[^èL/“°*ö­¥LèðLìôL)QLìLìL0 L LL%zzR^7¥¥¥¥¥¥^¥^^¥^¥^^LL; z¥^ ! L/&]þ1¥¥rèLèLJ ­LìL!LL VððL´gìL!LL VðQðL´fúìL!LL VðQQL)L!LL VôL-L%L@ VLèLJ ­Lj  L9ð­l^$LèL! ´f ìL-LJ ­´f¥^k^èL/“°*ö­¥Lj  L=­l^%LèL! ´f )LLJ ­´fR^a^èL/“°*ö­¥L0 L0 LLL%zL)L/ VLLð­L%zR^5¥¥0 L-LLK ­õLW ­LLð­L%z¥^ ! L/&]­¥¥R^—¥¥^^^^j L­l^$LèL! ´f ìL-LJ ­´f¥^X^èL/“°*ö­¥Lj Lð­l^%LèL! ´f )LLJ ­´fR^-^èL/“°*ö­¥L0 L)LW ­L)L%zR^¥¥; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´f±ìL!LL VôL)L%LL VððL´fŒ)L%LL VðQðL´fr)L%LL VðQQL-L%LL VôLLL@ Vj  L9ð­l^%LèL! ´f LLJ ­´fR^~^èL/“°*ö­¥L0 L-L)L%zR^k¥¥¥^¥^^¥^¥^^ìL!LL VððL´f7ìL!LL VðQLœ´f!ìL!LL VôL)L%L@ V; R^¥^^^^! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL%´fRìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­Lj L9­l^$LèL! ´f ìL-LJ ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f )LLJ ­´fR^(^èL/“°*ö­¥L0 L)L)L%zR^¥¥; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL%´fRìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­Lj L9­l^$LèL! ´f ìL-LJ ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL! ´f )LLJ ­´fR^(^èL/“°*ö­¥L0 L)L)L%zR^¥¥; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fRìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­LìL!LL VððL´fþìL!LL VðQðL´fçìL!LL VðQQL)L!LL VôL-L%LL VððL´f°-L%LL VðQLœ´f—-L%LL VôLLL@ Vj  L9­l^%LèL! ´f LLJ ­´fR^Ü^èL/“°*ö­¥Lj  L=ð­l^%LèL! ´f LLJ ­´fR^«^èL/“°*ö­¥L0 L)LõL)L%zR^“¥¥¥^R^^R^¥¥^^^^ìL!LL VððL%´fSìL!LL VôL)L%L@ Vj L=ð­l^%LèL! ´f )LLJ ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^; ¥^ ! L/&]þ!¥¥åèLèLJ ­Lj L9­l^$LèL! ´f ìL-LJ ­´f¥^"^èL/“°*ö­¥LèL6 ­LìLN ­õR^¥-LA õ¥^ ! L/&]þ)¥¥rèLèLJ ­LìL!LL VððL´fnìL!LL VðQðL ´fWìL!LL VôL)L%L@ Vj L9­l^%LèL! ´f )LLJ ­´fR^)^èL/“°*ö­¥LèLN ­R^¥¥^^^^A ¥^ ! L/&]þ!¥¥å9LG ðLY VLèLF ­LèðLèL´bèL´b¥^,^(ìQLL=ð­R^#¥^ìQLL=ð­R^¥^¥L)‰ì¥¥åT LX õñLñLèL-L)LL¤ v‰èðaj"LC ­L9­LèL) ­LT L=V¥l^CLèÐL¸f èL5 ­aèðL65´f!)ðLF ­L^ ­L-ðL6 ­LV^ ^èL/“°*öþ)¥Rå¦ 7 L/`ÐS­7E _*èLèðâ^ ^^!^+^5^>ô L)LÕ þ"^2õ L)LÕ þ"^&ö L)LÕ þ"^÷ L)LÕ þ"^ø L)LÕ þ"^¥å9LìL!zåå9LìLzåå°LìLÕ þå9L)L)LSÚ_ zrrèLèðâ^ ^!^#^%^4^5èQL LìLÅ ­LÌ þ*¥^ ^ ^èQL LìLÌ þ*¥^ ^¥åèL)Lð ­L VLÐ ær9LìLò ­L)Lä þ#åìLð ­LìõrèL¹ ­LìLj9LL× VL¶ ­l^4LèÐL¸f èLÍ ­aèðLw ù´f)LÖ ­LÚ ­^ ^èL/“°*ö­¥L=þ"¥åèLìL¹ ­LÊ ­LÉ ­LÚ ­L9þåèLìL¹ ­L´ ­LÚ ­L9þåèLìL¹ ­L½ ­L9þåèL¾ ðLî þåèLË ðLî þåèLØ L9þåèLÝ L9þåèLÞ L9þåèLà L9þåèLÛ L9þåèLLÁ ­L9þåèLLÁ ­L9þåèLæ L9þåèLá L9þåèL L9þåèLµ L9þåèL¿ L9þåèL9ðLî þåèLLÑ ­LÚ ­L9þåèLLÑ ­LÚ ­L9þåèLð ­LìLè ­LèLÆ ­j L9­l^7LèÐL¸f èLÍ ­aèðLßUD´fü L-L VLÐ ­^ ^èL/“°*ö­¥)Lð ­L)LìL² VL)Lé ­L¼ ­LÚ ­õRåèLð ­LìLè ­LèLÆ ­j L9­l^7LèÐL¸f èLÍ ­aèðLßUD´fý L-L VLÐ ­^ ^èL/“°*ö­¥)Lð ­L)LìL² VL)Lé ­Lí ­õRåèL L· ­LÚ ­L9þåèL L· ­LÚ ­L9þåèL L· ­LÚ ­L9þåèL'L· ­LÚ ­L9þåèL\L· ­LÚ ­L9þåèL"L· ­LÚ ­L9þåèLìL¹ ­L%Lß VL· ­LÚ ­L9þåèL¹ ­LLLÙ VLèLÊ ­LèLÿ¼f)LìLþ ­L9V)LìL» ­L· ­LÚ ­L=þ*RåèL¹ ­LèLº ­LìLìL%ŒLß VL ´f^L-L-L!LLŒLÙ VLÔ ­L9þ2RåèLÇ L9þåèLê L9þåèLÄ L9þåèLìL¹ ­LÏ ­LÚ ­L9þåèL³ ­LèðLèL!´b èL%´b^$)Lï L9þ*^ìQL-LìLú ­L=þ2¥^¥¥åE 7§ Ý7¨ |7© ‚ 7ª U7« F7¬ L/`ÐS­7ì _KèLèðâ^^^#^-^7^A^Jô L)Lt þ"^>õ L)Lt þ"^2ö L)Lt þ"^&’ L)Lt þ"^÷ L)Lt þ"^ø L)Lt þ"^¥å9LìL!zåå9LìLzåå°LìLt þå9L)L)Lø_²:zrrèLèðâ^^T^V^X^Z^i^jèQLèL‡ ­L ¼f èL‡ ­L€ÄfŸ LìLk V¥^A^¥^¥èQL  LìL‡ ­Lk þ*¥^# ^ ^¡ ^èQL LìLk þ*¥^ ^¥åèL)L ­L VLo ær9LìLs ­L)L„ þ#åìL ­LìõrèLìL^ ­Lj ­Lc ­L ­L9þåèLìL^ ­Ld ­L ­L9þåèL^ ­LìLj9LLu VLP ­l^4LèÐL¸f èLl ­aèðLw ù´f)L~ ­L ­^ ^èL/“°*ö­¥L=þ"¥åèL9ðL þåèL9ðL þåèL9ðL æåzLìLt þå9LìLI"W3zååèLQ L9þåèLv L9þåèL† L9þåèLR L9þåèLe L9þåèLT L9þåèLf L9þåèL` L9þåèLU L9þåèLw L9þåèL9ðL þåèL^ ­LèL%L)L_ ­L%ŒLx VL)LìLV ­L ­L9þ*RåèLX L ­L9þåèL‚ L ­L9þåèLg L ­L9þåèLƒ L ­L9þåèL9þåèL ­LìLŠ ­LèLh ­j L9­l^7LèÐL¸f èLl ­aèðLßUD´f– L-L VLo ­^ ^èL/“°*ö­¥)L ­L)LìLW VL)LŒ ­LZ ­L ­õRåèL ­LìLŠ ­LèLh ­j L9­l^7LèÐL¸f èLl ­aèðLßUD´f— L-L VLo ­^ ^èL/“°*ö­¥)L ­L)LìLW VL)LŒ ­Lˆ ­õRåèL^ ­LèL_ ­LìLìL%ŒL| VL ´f^L-L-L!LLŒLx VLŽ ­L9þ2RåèLìL^ ­Lr ­L9þåèLìL^ ­Lr ­L9þåèL¸Lr ­L9þåèLÎLr ­L9þåèLY ­LèðLèL!´b èL%´b^$)L‹ L9þ*^ìQL-LìL” ­L=þ2¥^¥¥ååèLŠ ­LìL^ ­L} VèL9þåèLŠ ­LìL^ ­L} VèL9þå‰ Lo þåèLŠ ­L"L VèL9þåèLŠ ­L\L VèL9þåèLŠ ­L L VèL9þåèLŠ ­L L VèL9þåèLŠ ­L L VèL9þåèL^ ­L%LLx VLj ­LèLÿ¼fìLìL™ ­L9VìLŠ ­LìLa ­L VìL=þ¥åèL› L9þååèLŠ ­LìL^ ­L} VèL9þå‰ Lo þåL¯ ­Lo æåèLŠ ­L#÷-7‰ I #*VcÂ7Š K #œ¼47‹ L #Ñ(07Œ K #Ç–A7 K #Óq&7Ž I #ù‚+7 I #Hæ>7 G #üfü7‘ “ LèL• í7” F L” ?íï6èL%õ7– F L– ?T'qèLõ7— F L— ?ÅUÂèLõ7˜ F L˜ ?¸æèLš í7™ F L™ ?E@ö<èLõ7› F L› ?)k䥜 LèLž í7 F L ?¨;W¢ L£ LL‘ ­LèL¤ íLi L Li L] Li Lp Li Ly Li Lz Li LS Li L[ Li L€ Li L\ Li Lb Li L{ Li Lm Li LO Lq L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zLN Vè¥L¥ LèL¦ íLìL§ íL-L-L¨ vL© Lª LL… ­ñLL… ­ñLL… ­ñLL… ­ñLìL« íL-L¬ íL)L­ íL® LèL° í7¯ F L¯ ?‡œz Li L L± íL'õLi LL² íL}õLi LL³ íL-õLi LL´ íL&õLi LLµ íLÇõLi LL¶ íLÀõLi LL· íLÁõLi LL¸ íL! õLi LL¹ íL…õLi LLº íLõLi LL» íL¼ õLi L"L& õLi L$L½ õLi L%L¾ õLi L'L¿ õLi L+LÀ íLL)ˆõLi L-LÁ íLõLi L/L íLõLi L1Là íLõLi L3LÄ íLõLi L2LÅ íL2õLi L,LÆ íLõLi L/LÇ íL+ õLi L;LÈ íL= õLi L=LÉ íL9L:ˆLB ˆõLi L?LÊ íL;L<ˆLœˆõLi LALË íL¸õLi LCLÌ íLÎõLq L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL LLÍ vLn V‰Li LÎ LÏ õLi LLÐ íLÑ õLi LLÒ íLÓ õLq L%zL%zL%zLÔ Ln V‰Li LLÕ íLÖ õLi LL× íLØ õLi LLÙ íLÚ õLi LLÛ íLÜ õLi L LÝ íLÞ õLi LL Lß vLà õLi LLá íL6õLi Lâ LõLi LLã íLä õLq L%zL%zL%zL%zL%zL%zL%zL%zL%zLå Ln V‰Li Læ Lç õLi Lè L¿õLi LLé íLê õLq L%zL%zL%zLë Ln V‰ì L-?±¨Wì L)?)æÉì L ?N¸áïì L ?ÄSïì L ?»Fq:ì L ?^_ì L ?jÅ ÿì L?ðBy7ì L?5ýÃì L?ö(ùì L? ¯­úì L?ÈË)óì L?}‰ðì L?š€Wì L?_zpì L?¨3Rì ì 7­  7® ù7¯ © #Å¿Å7° ª #Ç–A7± « #ŸÎßî7² « #Ö^¿Á7³ ª #|5Ä7´ ª #“ñ7µ ª #ÉnN 7¶ ª #öŠ˜,7· ª #ý.Õ77¸ « #9œãË7¹ ¬ #æ”7º ¯ #-zK7» ª #ñœÄÅ7¼ ª #ˆ‰-Æ7½ ­ #š€W7¾ ª #–xÇÃ7¿ ª #!@7À ª #4wß7Á ª #üüÒ7 ª #%¹P7à ª #©é¼87Ä ¬ #”ãì7Å ® #ÏIÈæ7Æ ª #ŠˆÏ 7Ç ¯ #!Ê|Õ7È ª #ÏÄ77É ¯ #ï P7Ê ­ #ö(ù7Ë ¯ #L(†ß7Ì ¯ #7ä.7Í « #.Ûê:7Î ª #ϱpü7Ï ¯ #&]7Ð ª #J°ô+7Ñ ª #ìNÔ7Ò ¯ #MR±7Ó ª #Óq&7Ô ¯ #ýK7Õ ª #в¦Ê7Ö ¨ #9лÃ7× ª #ö¤ï7Ø ¬ #€©W7Ù ª #Ci‹Ý7Ú ª #eÍ97Û ª #8gî7Ü ª #iú37Ý ª #µ¡ŠÝ7Þ ¬ #–€N7ß ª #½b° 7à ª #ò)7á ª #Ùî-7â ª #/ðlë7ã ¨ #!òI7ä « #:Úï7å ª #"P=7æ ª #ý?7ç « #*VcÂ7è ® #Ñ(07é ª #øº[7ê ª #Úâ77ë ª #ÚÒÐ97ì ª #?¢ÁÎ7í « #ù‚+7î ª #œ¼47ï « #Hæ>7ð ¨ #üfü7ñ ª #ÝË':7ò ª #‘³êÜ7ó ù LèLû í7ú § Lú ?íï6èL%õ7ü § Lü ?T'qèLõ7ý § Lý ?ÅUÂèLÿ í7þ § Lþ ?E@ö<èLõ7 § L ?)kä¥ LèL í7 § L ?¨;W L LLñ ­LèL íLÈ L± LÈ Lç LÈ Lâ LÈ LÜ LÈ LÀ LÈ LÒ LÈ Lë LÈ Là LÈ L¸ LÈ Lì LÈ Ló LÈ Lã LÓ L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL° Vè¥L LìLìL vLìL íL)L íL-L íL L L L LèL²ˆL LLå ­ñL L L)LÈ L L íL'õLÈ LL íL}õLÈ LL íL-õLÈ LL íL&õLÈ LL íLÇõLÈ LL íLLÀˆõLÈ LL íLÀõLÈ LL íLÁõLÈ LL íL! õLÈ LL" íL…õLÈ L!L# íLAõLÈ L#L$ íL¹õLÈ LL% íLõLÈ L%L& õLÈ L'L!õLÈ L(L#L}ˆL%ˆL´ˆõLÈ L*L}L&ˆõLÈ L/L' íLõLÈ L1L( íLõLÈ L&L) íLõLÈ L)L* íL+ õLÈ L7L, íL- õLÈ L9L. íL/ õLÈ L;L0 íL1 õLÈ L=L2 íL3 õLÈ L?L4 íL5 õLÈ LAL6 íL7 õLÈ LCL8 íL9 õLÈ LGLFL: vL; õLÈ LGL< íL= õLÈ LIL> íL? õLÈ LKL@ íL õLÈ LMLA íL} õLÈ LKLILJˆLB ˆõLÈ LML¸õLÈ LOL:õLÈ LQL;õLÈ LSL8õLÈ LUL7õLÈ LWL9õLÈ L\LYõLÈ L_LC íLZõLÓ L%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL%zL LLD vLÎ V‰E L-?ù‚+E Lì?±¨WE L?í T8E L?Ši»)E L?Ɇz!E L?îlrE L ?N¸áïE L ?ÄSïE L ?»Fq:E L?ÇšÚêE L ?^_E L ?jÅ ÿE L?ðBy7E L? ¯­úE L?ÈË)óE L)?_zpE L?¨3RE E 7 ‚ 7 U7 ù7  #Àžð,7  #' ¥Ý7  #ŸÎßî7  #ÞN+ô7  #Šº´Ð7  #ú½…*7  #Ÿ)ó7  #Ÿ%ˆò7  #©Óà7!  #DÏ\Ï7"  ##oÍÜ7#  #©]ôã7$  #617%  #ƒK9ç7&  #éÚÎ7'  #iT++7(  #ÈÊÉÞ7)  #,™Šó7*  #í"7>7+  #}´É7,  #Mû³Þ7-  #ëýã7.  #(O9ø7/  #!Ê|Õ70  #5ê`*71  #ÏÄ772  #̨gõ73  #@ü\ 74  #7ä.75  #i£W76  #ϱpü77  # §^Ë78  #&]79  #Î%û7:  #MR±7;  #˜éà'7<  #¸sä&7=  #‚›47>  #ýK7?  #'}Ö7@  #Ø>ã37A  #в¦Ê7B  #€-7C  #óFÚ7D  #ÆFÌ7E  #‡ÊM7F  #ù‚+7G  #€†(7H  #öÙÛ-7I  #÷±!7J  #€3Ç7K  #º>97L  #¶ìÉç7M  #O177N  #Ã\Ï7O  #¢OÝ-7P  #”]U7Q  #ð¤vÄ7R  #1±Ûï7S  #œî17T  #GÊAÝ7U  # ŸK17V  #=.#ê7W  #œ¼47X  #ù‚+7Y  #ƒñóÁ7Z ] LèL_ í7^  L^ ?ñ¥<èLa í7`  L` ?å”Jê¥b LèLd í7c  Lc ?¨;Wg L Lh Lj LèLk íLñLñLñLñL-LLLLl v‰-ð2)LLLm v‰)ð2ìL)Ln í‰ìðeèLìLo í‰èðap LLq íLr LñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñLñL)L)L+Ls v‰)ð2+(L$L6L-L/L"L'L/L$L$L)LLLL.L6Lt v‰(ð2*'LL6L)L/L1L.L6L-L)L7Lu v ‰'ð2)&LL6L)LL0L.L7L/L3Lw v ‰&ð2(%L%L6L-Ly v‰%ð2'$L+L'Lz v‰$ð2&#L)L$L)L$L{ v‰#ð2%"L)L$L| v‰"ð2$!LL#L} v‰!ð2# L)L"L~ v‰ ð2"LL!L v‰ð2!L LL!L€ v‰ð2 LL í‰ð2Lƒ ‰ð2L„ ‰ð2L)LL… v‰ð2LL† í‰ð2LLLLL‡ v‰ð2LLL-Lˆ v‰ð2LL‰ í‰ð2LL,LLLŠ v‰ð2LL‹ í‰ð2LLŒ í‰ð2LL í‰ð2LLŽ í‰ð2LL,LLL v‰ð2L+LLL‘ v‰ð2L+LL L’ v‰ð2 L L“ í‰ ð2 L L L-L$LL0L” v‰ ð2 L L L• v‰ ð2  L L6L-LL"L— v‰ ð2  LL6L-LLLLL L7LL˜ v ‰ ð2 L L™ í‰ð2 LL*LLLš v‰ð2 LL› í‰ð2LLœ í‰ð2L LL v‰ð2LLž í‰ð2L LLŸ v‰ð2-LL  í‰-ð2)L LL¡ v‰)ð2ìL L¢ í‰ìðeèL)L£ í‰èða)L+L5L¥ vL¦ L)?ÔSƦ L#?¬+IΦ L?ŠO9¦ L-?ÅØ˜¦ L?N¦ L?MUÞþ¦ L?(Ü>¦ L?s—þ¦ L?Šì /¦ L?î¸Á¦ L?µô£)¦ L?t ·¦ L?ž˜˜ ¦ L?ÚhzĦ L?R<¬Ø¦ L ?½Ó\צ L?ìWæ ¦ L$?§Æì¦ L? _é7¦ L6?ŸÎßî¦ L+?„Jùó¦ L4?d{>;¦ L?Íí:¦ L?#€®6¦ L?™0)ئ L?™…B¦ L?àë<¦ L-?„O Ï¦ L ?‚¸óÛ¦ L ?‘Ò¯¦ L?Åu¦ L?íO¤Ú¦ L ?ùƒWÕ¦ L ?Pw¦ Lì?3U=¦ L?èyɦ L ?ƒ¦ L!?_Es¦ L?ª¾~Ѧ L,?^_¦ L1?ëò%Á¦ L0?sI¨Ò¦ L/??/;¦ L2?WÁ"̦ L.?o ¦ L?$\ɦ L?i5D;¦ L)?²:Á¦ L(?}£ ˦ L&?YÏo;¦ L'?¹’ó¦ L*?5ýæ L7? ¯­ú¦ L5?ÈË)ó¦ L3?bÕÚ¦ L%?D.ê'¦ L"?Muü4R:¦ ¦ 7f 7gù7ha#^³Ç7i\#Ø!07jd# ÐÇ7k\#nþ47l]#Ÿ%ˆò7m\#½åò7nZ#cÙV7o\#|ð‚ê7p\#^#7q\#‹!!7rd#æ”7sh#-X‹È7t]#617uh#-q7vb# Ä>7w]#©]ôã7x\#ÆS»)7y]#iT++7zh#™Ïa17{]#ÈÊÉÞ7|b#üfü7}Z#° Â7~\#Søp7\#¸„À7€h#S7]#ÏÄ77‚h#7ä.7ƒ\#ŒÛ:%7„h#i£W7…h#MR±7†]#Î%û7‡\#  r7ˆ\#È©Õ7‰\#ÀÀ77ŠZ#æ”7‹Z#ÚáÓ7Œ\#Qý?7\#G Æ77Ž]#/òÜ7h#ýK7\#E¾gÖ7‘\#ÅN¬?7’]#в¦Ê7“\#û°½77”_#î9VÈ7•h#ÆFÌ7–\#’ðB%7—\#.¾ ë7˜\#¥,·Î7™\#M Ó7še#eç&7›_#n±ú7œY#Dœˆ7d#–€N7žg#üfü7ŸZ#\ÀÃ7 \#Ee7¡Y#!òI7¢]#ð¤vÄ7£e#:Úï7¤[#Edž47¥\#k \7¦\#{’Õ7§\#ÁU6Ö7¨]#GÊAÝ7©\#o¸…ó7ª\#Y4$Þ7«]#=.#ê7¬Y#üfü7­\#QÜ7Ö7®\#?ºÊâ7¯c#Å¿Å7°]#ƒñóÁ7±\#1ˆÏ7²\#JEA 7³e#!òI7´\#ã¢7µZ#Å¿Å7¶c#!òI7·c#9лÃ7¸\#ü¡à7¹\#´Ø'Ü7º\#F$û7»Z#9лÃ7¼]#ÞN+ô7½]#ú½…*7¾]#Šº´Ð7¿Y#Üà?7À\#žñZ(7ÁZ#!ùI7Âh#e Ð7Ã[#Ú¥A7Ä\#^_7Å\#âV7ÆZ#Üà?7Ç]#ƒK9ç7È]#ñœÄÅ7Éh#¹È7Ê]#ëýã7Ë\#¨„¾+7Ì_#C¦<7Í\#}âÊÆ7Î\#.æÁÞ7Ïh#!Ê|Õ7ÐZ#üZ7Ñh#&]7Ò\#—Ââ7Ó]#ÓÚ%Û7ÔZ#bÝS7Õ]#¸sä&7Ö]#˜éà'7×c#:Úï7ØY#Å¿Å7Ù\#"š7Ú\#†§™Ô7ÛY#9лÃ7Üh#Ø>ã37Ý\#dœ– 7Þ\#âK77ßh#‡ÊM7àY#4H(+7áf#3U=7â\#ó‚Ç77ã\#Ó×Ü7ä\#žwßï7å\#.¶+7æ]#€3Ç7ç\#E”Ïê7èe#\iÂ7é\#QK,7êe#Å¿Å7ëh#O177ìa#;»Å7í\#7uÓÞ7î]#¢OÝ-7ï]#1€mø7ð\##©{!7ñb#œî17ò]#1±Ûï7ó\#žj 7ô]# ŸK17õ\#.êï7ö\#ÿ; 7÷\#Ÿ‰ô7øh#Ñ(07ùZ#Úên7úe#Üà?7û\#”]U7üZ#œ S7ý LèL í7 XL ?çã‚èL í7 XL ?Óê+èL í7 XL ?(×8èL í7 XL ?å’ôÍèL í7 XL ?ĘlåèL í7 XL ?Ñû&ô¥ LèL í7 XL ?¨;WñLèLìL í‰èðaèL íL L LœLìL í‰ñL ñL L! L" L# L$ LLL% vLLìL( vLL)L+ vLL-L. vL L0 íLñLñLìL)L1 í‰ìðeèLìL2 í‰èðaèL L3 vL L4 íL5 LñLñLñLñL-LL6 í‰-ð2)L-LLLLLL: v‰)ð2ìL)L LLL@ v‰ìðeèL L L-LA v‰èðaF LèL!õ7G XLG ?AiÆ3èL%õ7H XLH ?nZšÅèLõ7I XLI ?¿ËNñèLõ7J XLJ ?-)Ê3¥K LèLLLS vLL)LU vLñLèLìLLLX v‰èðaèLLLZ vLL\ íLñLñLñLñLñLLLLLLLLb v‰ð2-L LLLLLLL&LL LLLLLLLƒ v‰-ð2)LLL LLL L† v‰)ð2ìLLLLLLLLL#L L$L v ‰ìðeèL)L LLL LL LL˜ v‰èða› LLŸ íLèL LLLL¤ vLLìL¨ vL L)‰© L"?‚×¹ñ© L?eç&© L? à[ü© L?C]ç&© L ?ŸÖe2© L?ŸùÄ1© L?‹œàØ© L?ÀJí© L?VåªÙ© L?\Ù…© L?Ú'© L?Éž—Ú© L?ÈvÆô© L ?#Êò© L ?Á© L?ªŒ…Ô© L$?"ÝÁ© L?¹ÄÏÌ© L ?´—ð%© L?iè0© L-?QêÄÖ© L?2m›'© L?¬4ÓÀ© L!?¹Ñ÷© L)?åÜ–2© L?ú³Ç© L?³ ã7© L?K© L?;ÀMÁ© L?C®ÃÌ© L?Zæsî© L?u¤Z1© L?GŸ"û© L?x­c8© L&?ùN² © L%? ¯­ú© L#?ÈË)ó© Lì?ï•w© L ?;„Ì© L ?ÑgøR)© © 7œÝ7|7ž7ŸÒ7 U7¡œ7¢L/`ÐS­7M _¨#èLèðâ^ ^^^&[ L)Lø þ"^\ L)Lø þ"^, L)Lø þ"^¥å9LìL!zåå9LìL%zåå9LìLzåå°LìLø þå9L)L)L (I/zrrèLèðâ^ ^^$^7èQLe LìL ­ˆ¥^%èQLf L숥^èQL7 LìL( ­ˆLÁˆ¥^¥åìLìL5 VL% ærèLèLèLœ´bèèLÇ´béèLÈ´bêèLÊ´bëèLÉ´bìèLË´bíèLÌ´bîèLÍ´bïèLδbðèLÏ´bñèLдbòèLÑ´bóèLÅ´bôèLÆ´bõèLôböèLÄ´b÷èL¡´bøèL¼´bùèL½´búèL¿´bûèLÀ´büèL¾´býèL²´bþèL³´bÿèL´´cèLl´cèL¹´cèLº´cèL»´cèL¶´cèL·´cèLµ´cèL¸´c¥__ üÿÿÿ¥__üÿÿÿ¥_^úüÿÿÿ¥^ø^òüÿÿÿ¥^ð^êüÿÿÿ¥^è^âüÿÿÿ¥^à^Úüÿÿÿ¥^Ø^Òüÿÿÿ¥^Ð^Êüÿÿÿ¥^È^Âüÿÿÿ¥^À^ºüÿÿÿ¥^¸^²üÿÿÿ¥^°^ªýÿÿÿ¥^¨^¢ýÿÿÿ¥^ ^šþÿÿÿ¥^˜^’þÿÿÿ¥^^Šÿÿÿÿ¥^ˆ^‚ÿÿÿÿ¥^€^zÿÿÿÿ¥^x^rÿÿÿÿ¥^p^jÿÿÿÿ¥^h^bÿÿÿÿ¥^`^Z!¥^X^R!¥^P^J%¥^H^B%¥^@^:¥^8^2¥^0^*¥^(^"¥^ ^¥^^¥^^ ¥^^¥¥åèL)õrèLèðLìôLìLèðL ´fièQLìUL)*L)L9­LL9­Èf>LL-L=ðVL-LìL-L VLìL ­L-L ­L VLV¥R^9^R^ ¥¥¥^^LLL VLL ­LL ­L VLþJ¥RrèLèL ­Lj L9ð­l^$LèL ´f ìL-L ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL ´f )LL ­´fR^¸^èL/“°*ö­¥L L)L)L%zR^¥¥¥ìL!L VððL%´fSìL!L VôL)L%Lù Vj L=ð­l^%LèL ´f )LL ­´fR^L^èL/“°*ö­¥LèR^E¥¥^^ìL!L VððL!´f!ìL!L VôL)L%Lù V) R^¥^^ L/&]þ!¥¥å9LèL ­LìL!L VððL ´f•ìL!L VðQðL´f~ìL!L VôL)L%Lù Vj 9L=ð­l^%LèL ´f )LL ­´fR^¬^èL/“°*ö­¥LLìL ­L VLLL-L ­L VõL9LðVR^z¥¥^^^^ìL!L VððL%´f&ìL!L VôL)L%Lù VLð­R^=¥^^LL ­L VLLLû L VõL9LðV¥^  L/&]þ!¥¥åèLèL ­LìL!L VððL ´fãìL!L VðQðL´fÌìL!L VðQQL)L!L VôL-L!L VðQLL%Lù VLèL ­LìL!L VððL ´fLìL!L VðQL—´f6ìL!L VôL)L%Lù VL ­LL)L VL9VR^.¥^^^^-L-L ­õLL=ðV¥^  L/&]­¥¥R_÷ ¥¥¥^^^^ìL!L VððL ´fCìL!L VðQL)L!L VôL-L%Lù VèL)L ­õLL=ðVR_ ¥¥^^ìL!L VððL´fíìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR_@ ^èL/“°*ö­¥LLèL ­LìL!L VððL´f6ìL!L VôL)L%Lù VLìL VLõLL=ðVR^P¥^^ìL!L VððL!´f.ìL!L VôL)L%Lù V&L0 ­LLVR^¥^^ L/&]­¥¥R_Ÿ ¥¥^^ìL!L VððL´fòìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR_B ^èL/“°*ö­¥LLèL ­LìL!L VððL´f;ìL!L VôL)L%Lù VLìL VLL ­õLL=ðVR^P¥^^ìL!L VððL!´f.ìL!L VôL)L%Lù VÀL0 ­LLVR^¥^^ L/&]­¥¥R_œ ¥¥^^ìL!L VððL ´f’ìL!L VðQðL!´f{ìL!L VôL)L%Lù VjLLðVl^%LèL ´f )LL ­´fR_) ^èL/“°*ö­¥LèðLìôL-LìL VL)L ­õLL=ðVR_ ¥¥¥¥^^^^ìL!L VððL ´fÃìL!L VðQðL%´f¬ìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR_‰ ^èL/“°*ö­¥Lj Lð­l^%LèL ´f -LL ­´fR_X ^èL/“°*ö­¥L)LìL ­L VL)L)L L VõLL=ðVR_+ ¥¥¥^^^^ìL!L VððL ´g ìL!L VðQðL´fõìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR_µ^èL/“°*ö­¥L-L!L VððL ´f“-L!L VðQðL%´fy-L!L VôLL%Lù Vj  Lð­l^%LèL ´f LL ­´fR_H^èL/“°*ö­¥L-LìL ­L VLìLL L VõLL=ðVR_¥¥^R^^R^¥¥^^^^ìL!L VððL ´g(ìL!L VðQðL ´gìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR_˜^èL/“°*ö­¥L-L!L VððL´f¯-L!L VôLL%Lù Vj  Lð­l^%LèL ´f LL ­´fR_?^èL/“°*ö­¥LèðLìôLL!L VððL´fBL!L VôLL%Lù VLìL VLLLL VõLL=ðVR_é¥^R^¥¥¥¥^R^¥¥^^^^ìL!L VððL ´fÈìL!L VðQðL´f±ìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR__^èL/“°*ö­¥Lj Lð­l^%LèL ´f -LL ­´fR_.^èL/“°*ö­¥LñLèLLLLLL=LL> v‰èðaLì­¥R_ü¥¥¥^^^^ìL!L VððL ´gjìL!L VðQðL´gSìL!L VôL)L%L VððL´g.)L%L VôL-LLù Vj Lð­l^%LèL ´f -LL ­´fR_h^èL/“°*ö­¥LLèL ­LìL!L VððL´fvìL!L VôL)L%Lù Vj  Lð­l^%LèL ´f )LL ­´fR^|^èL/“°*ö­¥LLìL ­L VLL)L VõLL=ðVR^R¥¥^^ìL!L VððL!´f.ìL!L VôL)L%Lù VÀL0 ­LLVR^¥^^ L/&]­¥¥R_‡¥¥^¥^ ¥^^^^ìL!L VððL ´fëìL!L VðQðL´fÔìL!L VôL)L%Lù V-LèL ­Lj  Lð­l^$LèL ´f ìL-L ­´f¥^8^èL/“°*ö­¥L-LìL ­L VLìL ­L ­õLL=ðVR^R¥ìL!L VððL%´f4ìL!L VôL)L%Lù V-Lû L ­õLL=ðVR^¥^^ L/&]­¥¥R_¥^^^^ìL!L VððL ´fëìL!L VðQðL´fÔìL!L VôL)L%Lù V-LèL ­Lj  Lð­l^$LèL ´f ìL-L ­´f¥^8^èL/“°*ö­¥L-LìL ­L VLìL ­L* ­õLL=ðVR^R¥ìL!L VððL%´f4ìL!L VôL)L%Lù V-Lû L* ­õLL=ðVR^¥^^ L/&]­¥¥R_…¥^^^^ìL!L VððL ´fEìL!L VðQðL´f.ìL!L VôL)L%Lù VèL õLL=ðVR_/¥^^^^ìL!L VððL ´g_ìL!L VðQðL ´gHìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR_½^èL/“°*ö­¥L-L!L VððL ´fæ-L!L VðQðL ´fÌ-L!L VôLL%L VððL ´f¦L%L VðQðL´fŒL%L VðQQLL%L VôLLLù Vj  Lð­l^%LèL ´f LL ­´fR_^èL/“°*ö­¥LLìL ­L VLLL-Lú VõLL=ðVR^ᥥ¥^R^"^R^¥^R^^R^¥¥^^^^ìL!L VððL ´f™ìL!L VðQL³´fƒìL!L VôL)L%Lù Vj Lð­l^%LèL ´f )LL ­´fR^N^èL/“°*ö­¥LìLìL ­L VL³L-L!L ­L ­õL-LVL ­õR^¥¥^^^^ L/&]þ!¥¥åèLèL ­LìL!L VððL´f•ìL!L VôL)L%L VððL ´fp)L%L VðQðL´fV)L%L VðQQL-L%L VôLLLù VL ­LìL VLL-L" VõLL9ðVR_»¥¥^¥^^¥^¥^^ìL!L VððL´fúìL!L VôL)L%Lù Vj L=ð­l^%LèL ´f )LL ­´fR_P^èL/“°*ö­¥LLèL ­LìL!L VððL´fCìL!L VôL)L%Lù VL ­LìL VLLL& VõLL9ðVR^P¥^^ìL!L VððL!´f.ìL!L VôL)L%Lù VÀL0 ­LLVR^¥^^ L/&]­¥¥R_¢¥¥^^ìL!L VððL ´fùìL!L VôL)L%Lù Vj L­l^%LèL ´f )LL ­´fR_F^èL/“°*ö­¥LLèL ­LìL!L VððL ´fCìL!L VôL)L%Lù VL ­LìL VLLL VõLL9ðVR^P¥^^ìL!L VððL!´f.ìL!L VôL)L%Lù VƒL0 ­LLVR^¥^^ L/&]­¥¥R^˜¥¥^^ìL!L VððL ´fnìL!L VðQL)L!L VôL-L%Lù Vj L­l^%LèL ´f -LL ­´fR^.^èL/“°*ö­¥L)LL)LVR^¥¥¥^^-¥^  L/&]þ)¥¥rèLèL ­LìL!L VððL ´g2ìL!L VðQðL´gìL!L VðQQL)L!L VôL-L%Lù VLèL ­LìL!L VððL´f›ìL!L VôL)L%Lù Vj  L9­l^%LèL ´f )LL ­´fR_Œ^èL/“°*ö­¥Lj  L=ð­l^%LèL ´f -LL ­´fR_[^èL/“°*ö­¥L L)LõL)L%zL ­R_>¥¥¥^^ìL!L VððL ´fŒìL!L VðQL—´fvìL!L VôL)L%Lù Vj  Lð­l^%LèL ´f )LL ­´fR^Í^èL/“°*ö­¥L LL-L VLL ­õL)L%zL ­R^£¥¥^^^^jLL ­L ­õL LVl^$LèL ´f ìL-L ­´f¥^X^èL/“°*ö­¥Lj  Lð­l^%LèL ´f )LL ­´fR^'^èL/“°*ö­¥L L)L)L%zL ­R^¥¥ L/&]­¥¥R^S¥¥^^^^j Lð­l^$LèL ´f ìL-L ­´f¥^^èL/“°*ö­¥LèL ­R^ ¥ L/&]þ!¥¥åèLèL ­Lj L9­l^$LèL ´f ìL-L ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL ´f )LL ­´fR^Œ^èL/“°*ö­¥L L)L)L%zR^y¥¥ìL!L VððL%´fSìL!L VôL)L%Lù Vj L=ð­l^%LèL ´f )LL ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^) ¥^  L/&]þ!¥¥åèLèL ­LìL!L VððL ´fåìL!L VðQðL´fÎìL!L VðQQL)L!L VôL-L%L VððL´f—-L%L VôLLLù Vj  L9­l^%LèL ´f LL ­´fR^Ö^èL/“°*ö­¥Lj  L=ð­l^%LèL ´f LL ­´fR^¥^èL/“°*ö­¥L L)LõL)L%zR^¥¥¥^R^¥¥^^^^ìL!L VððL´fSìL!L VôL)L%Lù Vj L=ð­l^%LèL ´f )LL ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^) ¥^  L/&]þ!¥¥åèLèL ­Lj L9­l^$LèL ´f ìL-L ­´f¥^È^èL/“°*ö­¥L)L!L VððL´f¥)L!L VôL-L%Lù Vj L9­l^%LèL ´f -LL ­´fR_•^èL/“°*ö­¥Lj  L=ð­l^%LèL ´f LL ­´fR_d^èL/“°*ö­¥LèðLìôLèL LLõLL%zõR_B¥¥¥¥¥^¥^¥ìL!L VððL ´g ìL!L VðQðL ´fòìL!L VôL)L%L VððL´fÍ)L%L VôL-LLù Vj L9­l^%LèL ´f -LL ­´fR^«^èL/“°*ö­¥Lj  L=ð­l^%LèL ´f LL ­´fR^z^èL/“°*ö­¥LèðLìôLèLèðLèL!´b èL%´b^&L ­Lõ^ý Lü ­L. ­LLV^¥¥R^0¥¥¥¥¥^¥^ ¥^^^^û L) õ¥^  L/&]þ!¥¥åèLèL ­LìL!L VððL ´fˆìL!L VðQðL´fqìL!L VðQQL)L!L VôL-L%Lù Vj L9ð­l^%LèL ´f -LL ­´fR^–^èL/“°*ö­¥L L-L)L%zR^ƒ¥¥¥^^^^ìL!L VððL´fSìL!L VôL)L%Lù Vj L9ð­l^%LèL ´f )LL ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^) ¥^  L/&]þ!¥¥åèLèL ­Lj L9­l^$LèL ´f ìL-L ­´f¥^S^èL/“°*ö­¥Lj L=ð­l^%LèL ´f )LL ­´fR^(^èL/“°*ö­¥L L)L)L%zR^¥¥) ¥^  L/&]þ!¥¥åèLèL ­LìL!L VððL´fRìL!L VôL)L%Lù Vj L9­l^%LèL ´f )LL ­´fR^ ^èL/“°*ö­¥LèR^¥¥^^) ¥^  L/&]þ!¥¥åèLèL ­LìL!L VððL ´gŽìL!L VðQðL´gwìL!L VðQQL)L!L VôL-L%Lù VLèL ­LìL!L VððL ´fÇìL!L VðQLœ´f±ìL!L VôL)L%Lù Vj  L9­l^%LèL ´f )LL ­´fR^Ö^èL/“°*ö­¥LjL ­L L=ðVl^%LèL ´f -LL ­´fR^^èL/“°*ö­¥LèðLìôLèL LL ­L õLL%zõR^v¥¥¥¥¥^^^^jL L=ðVl^$LèL ´f ìL-L ­´f¥^3^èL/“°*ö­¥LèðLìôLèL Lû LõLL%zõR^¥¥¥ L/&]­¥¥R^¥¥^^^^ L/&]þ)¥¥rèLèL ­LìL!L VððL´fUìL!L VôL)L%Lù VjLL9Vl^%LèL ´f )LL ­´fR^%^èL/“°*ö­¥LèR^¥¥^^-L) õ¥^  L/&]þ)¥¥r9L' ðL+ VLèL ­LèðLèL´bèL´b¥^,^(ìQLL=ð­R^#¥^ìQLL=ð­R^¥^¥L)‰ì¥¥å L! õñLñLèL-L)LLJ v‰èðajLþ ­L9­L LìL ­õ¥l^CLèÐL¸f èL# ­aèðL65´f!)ðL ­L. ­L-ðL$ ­L=V^ ^èL/“°*öþ)¥RåìL ­LL ­L ­LèL-ðL-LôLQL VèL9þ)RrM 7í 7î L/`ÐS­7” _Ô‚ L LX þ"rèðLT ­LèL!´f$ìðLZ ­L)ðLìLb VL-ôLìLq VèR^ìôL)ôL} ­L)ŒLj þ"¥åèL!´f ^()L)æL{ LìLLLL%ŒL9ðVL%z¥rèðLT ­Lèâ ^^^ ^$^(^6^D^Q^^^k^x^v[ ^€^pu ^z^jz ^t^dw ^n^^ìðLT ­Lv ­^^^NìðL^ ­Lv ­^N^>ìL9­Lx ­^?^/ìL9­L_ ­^0^ ìL9­LY ­^!^ìL9­Lm ­^^èL‡ LìˆL þ!¥¥åèðLT ­Lèâ!^F^J^N^R^V^Z^^^b^f^j^n^r^v^z^~^‚^†^Š^Ž^’^–^š^ž^¢^¦^ª^®^²^¶^º^¾^Â^Æ^Ê^Ȳ^Ò^³^Ì^¼l^Æ^¶´^À^°µ^º^ª¶^´^¤·^®^ž¸^¨^˜¹^¢^’º^œ^Œ»^–^†¡^^€¼^Š^z½^„^t¾^~^n¿^x^hÀ^r^bœ^l^\Ã^f^VÄ^`^PÅ^Z^JÆ^T^DÇ^N^>È^H^8É^B^2Ê^<^,Ë^6^&Ì^0^ Í^*^Î^$^Ï^^Ð^^Ñ^^èL‰ LìˆL þ!¥¥åèL9­LìL=ð­Lìõ¥åèL9ð­LìL9ð­LèL)õRåìL9ð­L)L9LŒ íL-L=VL-Lð­L)L)L)L` þCRrèðLT ­L!´fV ^èL9ð­Lp þå9L=­L9L­LèL)õRåèðLT ­LèLÄf<èL%´fìQð^ìL9­L)ðLg ­L-LìL!L!LzF-L=ðþ)R_`ìQLèL)Lèâ^:^8^:^H^c^~^^¨^Ð^ì__6_W_}_£_Ê_õ_þ___/_3_Q_k_…_“_¥_·_Ü__L­L\ ­__òL=ðLðLT ­LVLc ­_å_ÕL=ðLðLg ­LVLc ­_È_¸L=ð­Ly ­_·_§L=ð­LèLL9­L| V¥_š_ŠL=ð­LèLL=ðLðLT ­LVL~ V¥_p_`L=ð­LèLL=ð­Lr V¥_R_BL9LL vLLìLðLT ­LVLh ­¥_'_L=ð­LL=ð­LìLìLd Ls VR__ôL=ð­LL=ð­LìLìLe Ls VR_á_ÑL=ð­LL=ð­LìLìLL­Lt VR_¹_©L=ð­LL9­LìLìLL=ð­LU VR_‘_L9LðLT ­LVLèLL=ð­La V¥_h_XL­LL=ð­LL=ð­L)L)L)Lk VR_;_+V Li ­_0_ L=ð­Lp ­Li ­__ V L€ ­_^ÿL=ð­Lp ­L€ ­^ù^én ^ó^ãL=ð­LL=ð­LìLìLo VR^Ó^ÃLLðLT ­LVLf ­^·^§LLðLg ­LVLf ­^›^‹L9­Ll ­^‹^{LðLT ­LV^w^gLðLg ­LV^c^SðLðLg ­Lb VLèLLðVL] ­¥^<^,L=ð­LèLL=ðLðLg ­LVL~ V¥^^èL LìˆL ­¥¥õ¥¥åLW ­LìL-zLèðLLb VL9¸f ’ L ­èL=þ!¥r” 7N 7O U7P œ7Q 7R ù7S O #Ñî17T R #öÙÛ-7U S #Ø>ã37V Q #üfü7W S #ÆFÌ7X R #ƒ*=7Y O #Çp>7Z R #nÓÜ77[ R #ÞN+ô7\ S #‡ÊM7] O #ŸÌ9ü7^ R #ñœÄÅ7_ R #ÀV/7` R #}´É7a O #VK§Ë7b R #ÈÊÉÞ7c R #ê«!;7d R #L;Ê7e R #äôÿ7f O #ßÇp>7g R #‘^Èó7h R #Õ ó7i Q #–€N7j R ##oÍÜ7k R #oc|7l R #в¦Ê7m R #Ì鋿7n R #Ø·î7o S #O177p Q #!òI7q R #Ã\Ï7r R #,™Šó7s R #‚›47t R #ƒ¥|7u R #ÏÄ77v R #~2Õ77w R #|5Ä7x R #‘¦?7y R #§Êç37z S #!Ê|Õ7{ R #5ê`*7| Q #æ”7} R #ƒK9ç7~ S #MR±7 R #:z¹â7€ S #ÈË)ó7 ƒ ñL„ L… LñLèLìL† í‰èðaìLˆ íLŠ LñLñLñLñL-LL)L‹ v‰-ð2)LìLLL v‰)ð2ìLìLŽ í‰ìðeèLL)LLLLLLLL‘ v ‰èðaLìL“ vL” L?À‡yÀ” L?f0 ” L?íȂ֔ L?*x” L ?ú´fÅ” L?n#Ô L-?µe¡#” L)?ðâ ” L?0 ‚” Lì?3U=” L? ýR ” ” 7ï U7ñ L/`ÐS­7ý _\°LìL½ þå9LìLûÅ3*zååÝ LLÀ þ"rjÜL(L¨ VLèL—Lž VLèðLèL!´bèL%´b¥^>^:Ý L#LÀ V¥^„^*ìUðL!´fìQLèL³ ­L ðõR^d¥^¥^^¥èLèL£ ­LèðLèL!´b èL%´b^5Ý L'LÀ V^)ìQL)ULìL³ ­L—L)L£ ­LŸ Võ¥¥^¥¥¥¥LèðLìôLèL QL ULzRl^*LèÐL¸f èLµ ­aèðLw ù´f)^ ^èL/“°*öþ!¥rà LÊ æå9LÌ ­LèðL%´fUèUðL%´fGèUUðL!´f7èQLìUQL=L=L-LðVL=L-LðVLæõR^¥¥^^ ^^^^Lþ¥åjL ­LÐ ­l^LèÐL¸f èLµ ­a¿ ^èL/“°*ö­¥LèLèðLèL!´b èL%´b ^¿ ^ìQL9LìL=ðVLÐ ­¥^¥¥L)LL¨ Võ¥åìLìLÄ L­ þ+rèL)LÅ L­ þ+rìL9L)L¾ þ+r9LìL ­L=ðVLìLL¨ VõåèL¼ ­LèLèLò ´bèL´bˆ¥^½^¹)LÌ ­LèðL%´fLèUðL%´f>èUUðL!´f.èQLìUQL9LìL=ðVL9L-L=ðVõR^¥¥^^ ^^^^L­¥LL´ L)LðL%z‰¥¥^i^9ðL¿ L§ VL!¸fL­L9LL ­L=ðVLÐ ­‰¥^2^¥ðL¿ L§ VL!¸fL­L9L-L=ðVLÐ ­‰¥åá L)L)L9VL)LìL=LLâ vL-L¼ ­LèLèLã ´b©èLä ´bÊèLå ´bæèL´cèLæ ´cËèL(´céèLç ´cèLè ´c+èL§ ´c‡èL´cèL ´c­èL ´c³èL ´c¹èLé ´cžèL4´cµèL ´cÌèL ´cüèL´ckèL<´cÚèLê ´càèLë ´cæèLì ´cèL´cèL@´c“¥_·_³LL¨ VL³ ­LLìL¯ ­L¡ ­õ¥¥_¢_‹LL¨ VLLìL° ­L¡ ­õ¥¥__hLL¨ VLLìL© ­L¤ ­L¡ ­õ¥¥_W_@LL¨ VLèL!LÇ VL$´f(LìL%L-Lª ­L%ŒLÁ VL  ­L¡ ­õ^…èLèLèL´bèL´b(èL´b3èL´b>¥^N^JL¢ L¡ ­õ¥^M^8LÓ L¡ ­õ¥^;^&L² L¡ ­õ¥^)^LÔ L¡ ­õ¥^^¥L)LÍ ­L¡ ­õ¥¥¥_Œ_u-LL=ðæLLÌ ­LÙ VL¦ ­õ¥_g_P-LLL ­L=ðVLÕ ­õ¥_G_0LL¨ VLLLL ­L=ðVL)L¶ Võ¥¥__LÌ ­LèðLèL!´b èL%´b ^?L­^7ìQL)ULLL-L=ðVLL=ðæL-LÙ VL· Võ¥¥^¥¥¥_´_Ñ L-­¥_§_-LL=Lí vLLÌ ­LÙ VL« ­õ¥_€_iî L-­¥_s_\ï L-­¥_f_OLÌ ­LèðL%´fÎèUðL%´fÀèUUðLèL!´bèL%´bA¥^­^¡ìQL)UQLLL-L=ðVLL-L=ðVL¿ L® VõR^~¥¥^hìUUUðL!´fTìQL)UQL-UUQLLLL=ðVLLL=ðVL LL=ðVLÐ ­L® VõR^ ¥¥¥^¥^^¥^^^^L­¥¥_z_cLL¨ VLèL¬ æL­¥¥_\_ELL¨ VLèLð íL­¥¥_>_'LL¨ VL—Lž VLLìLLL ­L=ðVLà Võ¥¥__ðj L ­LÐ ­l^LèÐL¸f èLµ ­a¿ ^èL/“°*ö­¥LLìLèðLèL!´b èL%´b ^¿ ^ìQLLìL=ðVLÐ ­¥^¥¥LÈ ­õ¥¥_‘_zj L ­LÐ ­l^LèÐL¸f èLµ ­a¿ ^èL/“°*ö­¥LLìLèðLèL!´b èL%´b ^¿ ^ìQLLìL=ðVLÐ ­¥^¥¥L× ­õ¥¥__-LÎ õ¥_^÷Ï L-­¥_^ê-LL=Lñ vLLÌ ­LÙ VLÆ ­õ¥^Ú^ÃLL¨ VLLìLË ­õ¥¥^¼^¥¹ ñL¿ ñL¿ ñLL=LLLLLó vLLÌ ­L VèðLèðLèL!´b èL%´b ^*L­^"ìQLLìLðL£ ­LðL¥ Võ¥^¥¥R¥^?^(Lº ­LLðVLèðLìôLL)õR¥^^¥èLô LìˆLÛ ­L¸ þA¥¥RrìLÒ ­LèLÌ ­LèðL%´f3èQðL!´f%èUðL!´fèQL-LìL9V¥^¥^^ ^^^^ö LÊ þ)¥¥rèôLìðLL´ L)LõL¹ L%zL-LèðLèL!´b èL%´b ^$¹ ^ ìQL´ L9L)L=ðVL¹ L%z¥^¥¥L± þ3RåèôLìðLL´ L)LõL¹ L%zL´ L9LL=ðVL¹ L%zL± þ3RåèôLìðLò L¹ L´ L9LL=ðVL´ L9LL=ðVL¹ L%zL%zL± þ3RåèLèðLìôLñL¿ ñL¹ ñLLèðâ^)_;_]_…_¾_ú_<_`__†_Û__r_À___W_{_“_-èQLèLèðâ ^^-^E^]^u^’^ª^Â^Ú^ñL‰L)LÉ ­LÐ ­‰^×L‰L)LÉ ­LÐ ­‰^½L‰L)LÉ ­LÐ ­‰^£L‰L)LÉ ­LÐ ­‰^‰èQLLã ‰LìLØ ­LÐ ­‰¥^jèQLLä ‰LìLÐ ­‰¥^PèQLLå ‰LìLÐ ­‰¥^6L‰L)LÉ ­LÐ ­‰^L‰L)LÉ ­LÐ ­‰^¥¥_èQLLæ ‰)LL9ðæL)LÙ V‰¥_õèQLL(‰)L´ LL-L9ðVL¹ L%z‰¥_ËèQLìULLç ‰LìLÐ ­‰-L´ LLL9ðVL¹ L%z‰¥¥_èQLìULLè ‰-L´ LLL9ðVLL9ðæLLÙ VL%z‰¥¥_RèQLìULL§ ‰-L´ LLL9ðVL´ LLL9ðVL¹ L%zL%z‰¥¥_èQLL‰)LL9Lø vL)LÙ V‰¥_èè*ðLèL!´b èL%´bJ^ŒìQL)ULL ‰L´ LLL9ðVL´ L LL9ðVL¹ L%zL%z‰¥¥^GìQL)ULL ‰L´ LL-L9ðVL´ L LL9ðVL¹ L%zL%z‰¥¥^¥_DèQLìUL)*LL ‰L´ LLL9ðVL´ L LL9ðVLLèðLèL!´b èL%´b ^$¹ ^ ìQL´ LL)L9ðVL¹ L%z¥^¥¥L%zL%z‰¥¥¥_¾èQLìUL)*LL4‰L)LÐ ­‰L´ LLL9ðVL´ L LL9ðVL¹ L%zL%z‰¥¥¥_gèQLìULL ‰L—L-LŸ VLÐ ­‰-L´ LL-L9ðVL¹ L%z‰¥¥_#èQLìUL)*LLé ‰L-LÐ ­‰L´ LLL9ðVL´ L LL9ðVL¹ L%zL%z‰¥¥¥_ÌèQLL ‰)LìLèðLèL!´b èL%´b ^$¹ ^ ìQL´ LL)L9ðVL¹ L%z¥^¥¥‰¥_|èQLL‰)LìLèðLèL!´b èL%´b ^$¹ ^ ìQL´ LL)L9ðVL¹ L%z¥^¥¥‰¥_,-L<‰_#èQLìULLê ‰-L´ LLL9ðVL´ LLL9ðVL¹ L%zL%z‰¥¥^ßèQLLë ‰)LL9Lù vL)LÙ V‰¥^¹èQLLì ‰-LìLÐ ­‰¥^ŸèQLìUL)*LL‰L9Lú vL)LÙ VLL´ LLL9ðVLLèðLèL!´b èL%´b ^:^6ìQL´ LL¹ L´ LLL9ðVL¹ L%zL± VLL%z¥^¥¥L%z‰¥¥¥¥^¥-ðLð¸f ´ LðL—ˆLôˆL(õL¹ L%z^(-ôLô¸f´ LôLØ ­L(õL¹ L%z^¹ L)ðLèðLèL!´b èL%´b ^¹ ^ìQL´ LìLõL¹ L%z¥^¥¥LðL)L)L» VLðL± þkRrÖ LìL9þåý 7• |7– U7— F7˜ 7™ L/`ÐS­7F_ËèLèðâ^ ^^^)^2L)Lþ"^&L)Lþ"^L)Lþ"^L)Lþ"^¥å9L-L-L-L!zrr9LìL%zåå9LìLzåå9LìLzåå°LìLþå9LìLÛTÎ5zåå L #xBLL)L­õ?xBLå L #xBLL)L­õ?xBLåèL/°ñm­LèL/¢å1&­LL!LèL-Äf.-Lì$L)LL)L/ÿAVL)L/º”“­õõ2ìL%ˆe¥_Ïÿÿÿ L)L #xBLL #Hg Lz?Hg  L?xBLRr #Hg L #xBLL L)QL-ðLôLÿ L# sÛµLLÿ L# sÛµLVõ?xBL L)U?Hg Rá%ÜLL?Hg èL?xBLèL&? ÄÃèL'?- èL(?×m[èL)?‚ðmÂè¥áá$©Lj#LL+V#xBLLÿ L# sÛµL­lrl^LèÐL´f èL"­L/“°*ö­èL/“°*öþ!¥¥åèLèðL!´f^^^¥åèLèðL%´f^^^¥åèLèðL´f^^^¥åèLèðâ^ ^^!^(^6è*L9LìLþ*¥^%1Lþ^1Lþ^èQL9LìLþ*¥^¥åèLèðâ^ ^^!^(^6è*L9LìL þ*¥^%3Lþ^3Lþ^èQL9LìL þ*¥^¥åèLèðL!´fèQLè¥^¥^^5Lþ¥åèLèðLèL´bèL%´b¥^0^,ìQL9LìLVR^$¥^ìQL9LìLVR^¥^¥7Lþ¥åèLèðL!´f+è*LL­LèL8íL)LVèL ­¥¥^¥^^7Lþ¥åèðLèL ­L9´¥åèL ­L)LèðL!´f!èUL)L:íLìLVL­¥^¥^^;Lþ)¥¥rèôLìðLGLìˆL>ˆL)L­ˆLˆRåèLèðâ^ ^†^•^¸^ÌèQLìUL)*LL=LL?LLVLVLõLVèLèðL!´fL@LV^0^^èLL½LVL9ðæLìLVLALLþ[¥¥¥¥¥^OèQL-LìLþ2¥^>èQL-LBLV-LìLV-LCLþ2¥^èQL-L9ðæLìLþ2¥^¥rL ­LèðLìôLìLL9VLìþ)RåÜ7%%L? ÄÃ%L?xBL%L?‚ðmÂ%L?- %L?Hg %L?×m[F7þ |7ÿ 7F7 7ù7#ýK7ÿ #Å¿Å7ÿ #9лÃ7#ßlYÐ7# ÐÇ7ÿ #¸57 ÿ #üZ7 #1­¥æ7 #Ñ(07 #q·„÷7 #i£W7#CÚÚ7#!òI7#üfü7#ÎeK<7#™Ïa17ÿ #œ S7LèLí7þ L?"6ã3èLí7þ L?½=¢=èLí7þ L? `ÁèL í7þ L?;«Äô¥!LèL#í7"þ L"?¨;W L*7$,LL/HoØL#Œg%ÐZ7+-L.L/L0L)L2íL-L4íL6L9L<LñLèLìLDí‰èðaèLEíLFL)?ßlYÐFLì?UJêáFL ?3U=FL?1¸¾FL?JWFL?èü FL?’”+0FL?·YsFL?¸2ËâFL?R†ØÿFL-?JçàFL ?~«öR FF7š ù7œ – #Å¿Å7 ˜ #Úên7ž ˜ # ÐÇ7Ÿ ™ #ƒ*=7  ™ #ÞN+ô7¡ ™ #nÓÜ77¢ – #cÙV7£ ™ #ñœÄÅ7¤ ™ #ÀV/7¥ ™ #ÈÊÉÞ7¦ œ #e Ð7§ š #Jçà7¨ ˜ #šr!Ý7© ˜ #æ”7ª ™ #‘^Èó7« ™ ##oÍÜ7¬ ™ #,™Šó7­ ™ #‚›47® ™ #ÏÄ77¯ ™ #|5Ä7° š #"6ã37± ™ #§Êç37² œ #ï P7³ œ #!Ê|Õ7´ œ #7ä.7µ ™ #5ê`*7¶ ™ #ƒK9ç7· œ #&]7¸ œ #MR±7¹ š #JW7º – #ÚáÓ7» š #èü 7¼ œ #ýK7½ ™ #öÙÛ-7¾ œ #Ø>ã37¿ œ #ÆFÌ7À ˜ #€©W7Á š #R†Øÿ7 ™ #}´É7à ™ #ê«!;7Ä ™ #L;Ê7Å ™ #äôÿ7Æ ˜ #–€N7Ç ™ #Õ ó7È ™ #ð‘§Î7É œ #ÎeK<7Ê ™ #oc|7Ë š #1¸¾7Ì ™ #в¦Ê7Í ™ #Ì鋿7Î ™ #Ø·î7Ï œ #O177Ð ™ #Ã\Ï7Ñ š #3U=7Ò ™ #ƒ¥|7Ó ™ #~2Õ77Ô ™ #‘¦?7Õ — #œî17Ö ™ #:z¹â7× œ #Ñ(07Ø – #œ S7Ù Ú LèLÜ í7Û • LÛ ?¨;WÞ ñLß LñLèL)L)LLõ v‰èðaèL÷ íLñLèLìLû í‰èðaèLü íLý L)?¤õÓý Lì?Óñ ý L?‹ØóÛý L?f0 ý L?HÈíÛý L-?3U=Rý ý 7ò 7ô ì 7õ  7ö ù7÷ ÷ #ýK7ø ÷ #'}Ö7ù ô #öÙÛ-7ú ÷ #Ø>ã37û ô #ÉnN 7ü ô #¡é7ý ÷ #€-7þ ò #f0 7ÿ ñ #ŸÎßî7 ô #ÞN+ô7 ÷ #‡ÊM7 ô #ÀV/7 ô #}´É7 ô #ê«!;7 ô #L;Ê7 ô #ÈÊÉÞ7 ÷ #©Óà7 ÷ #÷±!7 ô #äôÿ7 î #Ú¥A7 ô #í"7>7 ô #‘^Èó7 ô #Õ ó7 ö #üfü7 ñ # Ä>7 ô ##oÍÜ7 ÷ #º>97 ô #oc|7 ô #”]U7 ô #Ì鋿7 ô #в¦Ê7 ÷ #O177 ô #,™Šó7 ô #‚›47 ô #Ã\Ï7 ñ #üfü7 ô #ÏÄ77 ô #‘¦?7 ñ #œî17 ï #ú´fÅ7 ÷ #!Ê|Õ7 ô #œ¼47! ô #5ê`*7" ÷ #7ä.7# ÷ #i£W7$ ÷ #&]7% ô #ƒK9ç7& õ #5ýÃ7' ÷ #Ñ(07( ÷ #MR±7) ô #:z¹â7* ñ #ù‚+7+ - LèL/ í7. í L. ?ñ¥<èL1 í70 í L0 ?å”JêèL3 í72 í L2 ?ÑS\Ö¥4 LèL6 í75 í L5 ?¨;W8 L9 L: L; LñLñLñLñLñLñLñLñLñLñLñLñLñL L L LL< v‰ ð2  L L L= v‰ ð2 L L L LL LL L LL? v ‰ð2 LLLL LL@ v‰ð2 L LLL LA v‰ð2L LLB v‰ð2L LLC v‰ð2L LLLD v‰ð2LLE í‰ð2-L LLF v‰-ð2)LLG í‰)ð2ìL L)LH v‰ìðeèL)LI í‰èða LLK vLèLL íLÿ Lì‰ Lì‰M L-?»†LéM L?·âbM L?ø;“$M L ?„JùóM L?d{>;M Lì?f0 M L)?3U=M L?èyÉM L?ª¾~ÑM L?r1]äM L?9uM L?^_M L ?WÁ"ÌM L ?}£ ËM L ?5ýÃM L? ¯­úM L?ÈË)óM L ?D.ê'M L?Muü4RM M 7£ 7¤F7¦7§ 7¨ù7©œ#¬4ÓÀ7ª¢#^³Ç7«¤#!òI7¬ž#Å¿Å7­ #ü¡à7®¦#Úên7¯¦# ÐÇ7°§#ƒ*=7±§#ÞN+ô7²§#nÓÜ77³§#ñœÄÅ7´§#ÀV/7µ #|ð‚ê7¶ž#cÙV7·§#ÈÊÉÞ7¸©#¥i7¹©#e Ð7ºŸ#Ú¥A7»§#‘^Èó7¼¡# Ä>7½§##oÍÜ7¾ #^_7¿§#‚›47À¡#üfü7Á§#,™Šó7§#ÏÄ77ç#|5Ä7Ä #}âÊÆ7ŧ#§Êç37Æ©#!Ê|Õ7Ç©#7ä.7ȧ#5ê`*7Éœ#eç&7Ê©#i£W7Ëž#^'XÌ7̧#ƒK9ç7Í©#MR±7Π#Åb 7Ï #  r7О#æ”7Ñž#Ò9WÊ7Ò#Å¿Å7Óž#ÚáÓ7Ô©#ýK7Õ #E¾gÖ7Ö§#öÙÛ-7×£#3U=7Ø#9лÃ7Ù©#Ø>ã37Ú©#ÆFÌ7Û #.¾ ë7Ü©#‡ÊM7ݤ#Dœˆ7Þ§#}´É7ß #\PC37à§#ê«!;7á #}ëw7â§#Õ ó7ã #E”Ïê7ä¨#üfü7å§#oc|7æ§#в¦Ê7ç#Î/Å7è§#Ø·î7é©#O177ê¢#;»Å7ë§#Ã\Ï7ì§#ƒ¥|7í ##©{!7î#!òI7ï #h…ŠÍ7ð§#‘¦?7ñ¡#œî17ò©#áT7ó¤#:Úï7ô #o¸…ó7õ #!vü7ö #ÿ; 7÷ #Úê¨ñ7ø©#Ñ(07ù¤#Üà?7ú #?ºÊâ7ûž#œ S7ü#üfü7ýLèL!õ7›L?·=±ÖèL%õ7›L?}YË¥LLL L L LòLÆL²­õLÇL*LÎL%zLLLñLèLìLí‰èðaèLíLLLñLèLìLí‰èðaL LíLñLèL L L LLLv‰èðaLñLñLñLñLñLñLñLñLñLñLñLLL L LLL!LLL LL!LLL%v ‰ð2 L LL LLLLL&v‰ð2 LLL L'v‰ð2LLLLL,v‰ð2L.‰ð2LLL L LL2v‰ð2LL LLLLL?v‰ð2-LLLLLLCv‰-ð2)L L)LLLLLLL LL LLLL'L LL-LLLLJv‰)ð2ìL-LLLLLLMv‰ìðeèL)LLOv‰èðaLLL LLVvLWL?¤MãWL ?6ÜWL?þé‚2WL?*ª¦ñWL?ï PWL ?e¡‚WL?ðBy7WLì?5_¢ÙWL? ÷gWL?dd,ÀWL? „ŸæWL ?Œ—öWL ?g>ñÆWL?ÝKÍWL?Å¡×9WL-?¬Z0ðWL?„Ž´ÜWL?‹ó#6WL ?3¦øØWL?í©PÛWL)? %ÿWL?y­(ýWL?l5‡ðWL?_½ÄÁWL?C¶4WL?I›bWL?žºÁWL?£ÇïWL?Muü4WL?™m%WL?Ý©ˆ%RWW6ì 6© 6L/`ÐS­7o_ZèL}LNVLR­LèðLèL!´b èL%´b ^<^8ìUðL!´fìQLèR^'¥^^ìQL)UL}LìLR­LPþ:¥¥^¥¥åèL}LNVLR­LèðLèL!´b èL%´b ^#^ìUðL!´f ¥^^^ìQLè¥^¥¥ålLìLaLNVLPVLèLlLNVLR­LèðLèL!´b èL%´b^bL8LQþ2^ ìQLè¥^¥¥¥å/HoØ#]tÀLIL#.Zû!µåèLSþåèLU­LèL´fO^èLMþ¥åWþåYþåèL[­Ll´åèL]­LHL#.Zû!µåo7G|7Hœ7IF7Jù7KI#î9VÈ7LK#O177MJ#Úên7NK#Ø>ã37OJ# ÐÇ7PK#ÆFÌ7QH#cÙV7RTL%L/HoØL#Œg%ÐZ7SVL%L/HoØL#Œg%ÐZ7UXL!L/HoØL#Œg%ÐZ7WZL!L/HoØL#Œg%ÐZ7Y\L%L/HoØL#Œg%ÐZ7[^L%L/HoØL#Œg%ÐZ7]_L`LcLLLdLeLfL%L/HoØL#Œg%ÐZL/çñü©LèL L/ˆ¤³ÅVL ˜LìL ˜L)LdL/ˆ¤³ÅVz¥LgLhLL/HoØL#Œg%ÐZLiLjL%L/HoØL#Œg%ÐZLkLmLnLoL ?ˆëôoL ?–xóðoL?çñüoL?ÓàÁoLì?râoL?=¿¸oL)?˜’UÇoL?„ÌÁ&oL?ÇOÀ&oL ?“åoL?÷ÃoL?Üà?oL-?z_(?oL ?ñ9íoL ?]tÀRoo6E 6L/`ÐS­7©_†èLèðâ^ ^^!^+^5^>L)Luþ"^2€L)Luþ"^&L)Luþ"^‚L)Luþ"^ƒL)Luþ"^¥å‹LL/HoØL#Œg%ÐZ7ŠL%L/HoØL#Œg%ÐZ7ŒLL/HoØL#Œg%ÐZ7Ž‘LL/HoØL#Œg%ÐZ7“L%L/HoØL#Œg%ÐZ7’•LL/HoØL#Œg%ÐZ7”—L%L/HoØL#Œg%ÐZ7–™L%L/HoØL#Œg%ÐZ7˜åè#VK§ËLì#ßlYÐL)#‚ðmÂzåèL’þåìLìL”þ"rèL–þåLLLLLŽVL9þ1rèLèðLèL!´b èL%´b^^ ìQLè¥^¥¥LŒþåLLLLLVL9þ1rèL˜þåìLìL{­LŠþ"rìLìL{­LŠþ"rèL9­LèLˆL=VèL-Ly­LVLw­LìLL!L-L!LVL)L­èðÌb èôLLy­¸f¥L~­Lz­ìL!L)QL|þCRr9L=L)LL!LVLLL!L-QLtVèðÌf ìLìôˆLðþ¥åxL9­L%LœLw­LL}­L)L†L=VñLèLLLLLLL§v‰èða!Lì­-L­ìLvþ1Rå©7pF7q 7rù7sr#"‡7ts#ýK7ur#Ñ(07vq#üfü7ws#Ø>ã37xq#æ”7ys#&]7zs#Ñ(07{q#€©W7|r#üfü7}s#¨;W7~„LèL!õ7…pL…?ADèL%õ7†pL†?[‚ 7èLõ7‡pL‡?±….èLõ7ˆpLˆ?Sì9èLõ7‰pL‰?-­ê2¥šL›LœLLžL-LŸíL LL¡íL¢L£L¤LL)LLLL¦vLL)LLL¨vL©Lì?û.ƒ ©L?y¹ó#©L?]l36©L?¾â©L?@½¯©L ? ©L-?œ/©L?æÙi©L?Õÿæ ©L? Ä>©L ?;»Å©L)?¢G¿©L ?ýÓ³0R ©©6M 6L/`ÐS­7Å_HèLèðâ^ ^^^&³L)L®þ"^¶ L)L®þ"^´L)L®þ"^¥å9LìL%zåå9L)L)LzrrèL/–£­L!LìL/¢å1&­LìLìÄfC)L)$L)LL)€f¶^ )ÐL´f )L·­^)ðL-ôL¹V@)L%ˆ2¥_»ÿÿÿ)L¬L#.Zû!µrRå/êQý©L»þå/¸ÐV(©L»þåèLèðâ^ ^^&^C9L¿L±þ"^7èQL9LÀL)L²þ3¥^"èQLìUL9LÁL)LõL²þ;¥¥^¥åìLÂíLìL°þ"r¯LL9­L=þåÅ7ª7«œ7¬ù7­­#ýK7®«#Ë¿ó7¯¬#Å¿Å7°«#ßlYÐ7±«#™Ïa17²µLèL!õ7¶ªL¶?{â2#èL¸í7·ªL·?̨gõèLºí7¹ªL¹?t=¥¼7»½L¾LÃL)LìLÄvLÅLì?-X‹ÈÅL-? MÅL)?4}rÂÅL?žºÁRÅÅ6!¦ 6#L/`ÐS­7ñ_·èLèðâ^ ^^^&ÚL)LÎþ"^L)LÎþ"^_L)LÎþ"^¥å9LìL!zåå9LìL%zåå9LìLzååâLìLÎþåèQLìðLæL)L)õLØþ*RåìLÔ­åLÔ­çLìLÏV%LÌær9L=LþåèôLìðL9LìL-LÕþ3Rå9L=þå!ñLLÒ­LLÙ­LLL9LévLÜ­LìLêL)LÕVìLëL)LÕVìLìíLLÏVk+ðLÄg LðL×VLL ðL%ˆ‰j LLÑVl^6LèÐL¸f èLЭaèðLw ù´fìL LívLÜ­^ ^èL/“°*ö­¥LèLèðâ^ ^^J^®èQLLì­¥^¡èQL ðL ´f äLÓ­L ðL×VL L ðL%ˆ‰èL)­¥¥^ièQL ðL ´f äLÓ­L ðL×VL L ðL%ˆ‰j LÍ­l^$LèÐL¸f èLЭaäLÓ­^èL/“°*ö­¥LèL-­R¥^¥R_Üþÿÿl^XLèÐL¸f èLЭaèðL”u´f6LðL%ŒL×VLîLÔ­èLÔ­^ LÔ­LL9V¥^ ^èL/“°*öþQ¥RrLÖ­L-L-L-L9þ#û.ƒ 6?)#!Ê|Õ6@#-X‹È6A)#7ä.6B)#&]6C5#uaø6D)#MR±6E#åÜ–26F#2m›'6G#çñü6H#;»Å6I#Å¿Å6J#ÚáÓ6K5#}~&ô6L)#ýK6M)#Ø>ã36N #ô³Ç6O #.¾ ë6P#€©W6Q# ¯­ú6R%#tï,96S# ¯­ú6T#à]òô6U!# M6V## ¯­ú6W#–€N6X#ï•w6Y5#™Ïa16Z#¢›W6[)#O176\#¢G¿6]#!òI6^5#ßlYÐ6_ #œî16`)#áT6a#‘”Vý6b #Û°126c # ¯­ú6d# ¯­ú6e)#Ñ(06f#‚×¹ñ6g#ˆëô6h#üfü6i%#3U=6j#œ S6kmLpLsLvLwLyLèL{í6z1Lz?높kHL|LìðˆL}ˆLìôˆL}ˆLìQˆL~ˆL@LLEL%zñLEñLñL€L\­ñLNñLLi­LèLƒíL@LLL„vL<­L…L†zL@L‡LS­LˆL‰zL@LLŠíLS­L‹LŒzL@LLíL<­LŽLzL@LL<­LL‘zL@LL L“vLS­L”L•zLEL%zL%zL%zL%zL%zL%zLðLLb­LKVLñLèL)LL-L˜v‰èðaL-LL™íLjVðLèðLèL!´b èL%´b^^ìQLèLLV¥^¥¥ðLLLLLšvLYVLLìL›vLðL1­L,VðLèðLèL!´b èL%´b^Q^NìQLLi­LèLœíL*LJVLI­ìLLDVLèL)LU­L L]VL_VèL6­R¥^¥¥R l_&LèÐL¸f èLB­aèðLèLø_²:´b+èL (I/´bDèLïZg6´b]èLSÚ_ ´bvèLLúÿ4´bèL?”´b¨¥^Æ^ÂìQL)ULìLT­LìLVR^Æ¥¥^¢ìQL)ULìLR­LìLVR^¦¥¥^‚ìQL)ULìLd­LìLVR^†¥¥^bìQL)ULìL;­LìLVR^f¥¥^BìQL)ULìLW­LìLVR^F¥¥^"ìQL)ULìLe­LìLVR^&¥¥^¥èLèLf­L`LV¥^ ¥èL/“°*ö­¥L?´<„L?ê ™âL?¹ÈÿL-?s%oL)?¬ œáRneko-2-2-0/cmake/000077500000000000000000000000001321613172000135215ustar00rootroot00000000000000neko-2-2-0/cmake/FindAPACHE.cmake000066400000000000000000000020361321613172000162460ustar00rootroot00000000000000# # APACHE_FOUND - System has APACHE # APACHE_INCLUDE_DIR - The APACHE include directory # # APACHE_LOCATION # setting this enables search for apache libraries / headers in this location # # Include directories # find_path(APACHE_INCLUDE_DIR NAMES httpd.h PATH_SUFFIXES httpd apache apache2 apache22 apache24 ) set(HTTPD_NAMES ${HTTPD_NAMES} httpd) find_library(HTTPD_LIBRARIES NAMES ${HTTPD_NAMES} PATHS /usr/lib /usr/local/lib ) if(NOT DEFINED APACHE_MODULE_DIR) find_program(APXS_BIN NAMES apxs apxs2 PATH_SUFFIXES httpd apache apache2 ) if(APXS_BIN) EXEC_PROGRAM(${APXS_BIN} ARGS -q LIBEXECDIR OUTPUT_VARIABLE APACHE_MODULE_DIR ) endif(APXS_BIN) endif(NOT DEFINED APACHE_MODULE_DIR) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set APACHE_FOUND to TRUE if # all listed variables are TRUE find_package_handle_standard_args(APACHE DEFAULT_MSG APACHE_INCLUDE_DIR ) mark_as_advanced(APACHE_INCLUDE_DIR HTTPD_LIBRARIES) neko-2-2-0/cmake/FindAPR.cmake000066400000000000000000000056631321613172000157600ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # - Find Apache Portable Runtime # Find the APR includes and libraries # This module defines # APR_INCLUDE_DIR and APRUTIL_INCLUDE_DIR, where to find apr.h, etc. # APR_LIBRARIES and APRUTIL_LIBRARIES, the libraries needed to use APR. # APR_FOUND and APRUTIL_FOUND, If false, do not try to use APR. # also defined, but not for general use are # APR_LIBRARY and APRUTIL_LIBRARY, where to find the APR library. # APR first. FIND_PATH(APR_INCLUDE_DIR apr.h PATH_SUFFIXES apr-1 apr-1.0 ) SET(APR_NAMES ${APR_NAMES} apr-1) FIND_LIBRARY(APR_LIBRARY NAMES ${APR_NAMES} ) IF (APR_LIBRARY AND APR_INCLUDE_DIR) SET(APR_LIBRARIES ${APR_LIBRARY}) SET(APR_FOUND "YES") ELSE (APR_LIBRARY AND APR_INCLUDE_DIR) SET(APR_FOUND "NO") ENDIF (APR_LIBRARY AND APR_INCLUDE_DIR) IF (APR_FOUND) IF (NOT APR_FIND_QUIETLY) MESSAGE(STATUS "Found APR: ${APR_LIBRARIES}") ENDIF (NOT APR_FIND_QUIETLY) ELSE (APR_FOUND) IF (APR_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find APR library") ENDIF (APR_FIND_REQUIRED) ENDIF (APR_FOUND) # Deprecated declarations. SET (NATIVE_APR_INCLUDE_PATH ${APR_INCLUDE_DIR} ) GET_FILENAME_COMPONENT (NATIVE_APR_LIB_PATH ${APR_LIBRARY} PATH) MARK_AS_ADVANCED( APR_LIBRARY APR_INCLUDE_DIR ) # Next, APRUTIL. FIND_PATH(APRUTIL_INCLUDE_DIR apu.h PATH_SUFFIXES apr-1 apr-1.0 ) SET(APRUTIL_NAMES ${APRUTIL_NAMES} aprutil-1) FIND_LIBRARY(APRUTIL_LIBRARY NAMES ${APRUTIL_NAMES} ) IF (APRUTIL_LIBRARY AND APRUTIL_INCLUDE_DIR) SET(APRUTIL_LIBRARIES ${APRUTIL_LIBRARY}) SET(APRUTIL_FOUND "YES") ELSE (APRUTIL_LIBRARY AND APRUTIL_INCLUDE_DIR) SET(APRUTIL_FOUND "NO") ENDIF (APRUTIL_LIBRARY AND APRUTIL_INCLUDE_DIR) IF (APRUTIL_FOUND) IF (NOT APRUTIL_FIND_QUIETLY) MESSAGE(STATUS "Found APRUTIL: ${APRUTIL_LIBRARIES}") ENDIF (NOT APRUTIL_FIND_QUIETLY) ELSE (APRUTIL_FOUND) IF (APRUTIL_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find APRUTIL library") ENDIF (APRUTIL_FIND_REQUIRED) ENDIF (APRUTIL_FOUND) # Deprecated declarations. SET (NATIVE_APRUTIL_INCLUDE_PATH ${APRUTIL_INCLUDE_DIR} ) GET_FILENAME_COMPONENT (NATIVE_APRUTIL_LIB_PATH ${APRUTIL_LIBRARY} PATH) MARK_AS_ADVANCED( APRUTIL_LIBRARY APRUTIL_INCLUDE_DIR )neko-2-2-0/cmake/FindBoehmGC.cmake000066400000000000000000000013411321613172000165670ustar00rootroot00000000000000find_path(GC_INCLUDE_DIR gc.h PATH_SUFFIXES include) if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(GC_NAME "gc-threaded") else() set(GC_NAME "gc") endif() find_library(GC_STATIC_LIBRARIES "lib${GC_NAME}.a" PATH_SUFFIXES lib lib64) find_library(GC_LIBRARIES "${GC_NAME}" PATH_SUFFIXES lib lib64) if (NOT GC_LIBRARIES AND NOT GC_STATIC_LIBRARIES) message(FATAL_ERROR "BoehmGC not found in ${GC_ROOT}") set(GC_FOUND FALSE) else() message(STATUS "GC: ${GC_INCLUDE_DIR}") message(STATUS "GC_LIBRARIES: ${GC_LIBRARIES}") message(STATUS "GC_STATIC_LIBRARIES: ${GC_STATIC_LIBRARIES}") set(GC_FOUND TRUE) endif() mark_as_advanced( GC_INCLUDE_DIR GC_LIBRARIES GC_STATIC_LIBRARIES GC_STATIC GC_STATIC_FOUND ) neko-2-2-0/cmake/FindGTK2.cmake000066400000000000000000000072011321613172000160330ustar00rootroot00000000000000FILE(TO_CMAKE_PATH "$ENV{GTK2_DIR}" TRY1_DIR) FILE(TO_CMAKE_PATH "${GTK2_DIR}" TRY2_DIR) FILE(GLOB GTK_DIR ${TRY1_DIR} ${TRY2_DIR}) FIND_PATH(GTK_gtk_2_INCLUDE_DIR gtk/gtk.h ENV INCLUDE DOC "Directory containing gtk/gtk.h include file") FIND_PATH(GTK_gdk_2_INCLUDE_DIR gdk/gdk.h ENV INCLUDE DOC "Directory containing gdk/gdk.h include file") FIND_PATH(GTK_gdkconfig_2_INCLUDE_DIR gdkconfig.h ENV INCLUDE DOC "Directory containing gdkconfig.h include file") FIND_LIBRARY(GTK_gdk_pixbuf_2_LIBRARY NAMES gdk_pixbuf-2.0 PATHS ${GTK_DIR}/lib ${GTK_DIR}/bin ${GTK_DIR}/win32/bin ${GTK_DIR}/lib ${GTK_DIR}/win32/lib /usr/local/lib /usr/lib ENV LIB DOC "gdk_pixbuf library to link with" NO_SYSTEM_ENVIRONMENT_PATH) FIND_LIBRARY(GTK_gdk_2_LIBRARY NAMES gdk-win32-2.0 gdk-x11-2.0 PATHS ${GTK_DIR}/lib ${GTK_DIR}/bin ${GTK_DIR}/win32/bin ${GTK_DIR}/lib ${GTK_DIR}/win32/lib /usr/lib /usr/local/lib ENV LIB DOC "gdk2 library to link with" NO_SYSTEM_ENVIRONMENT_PATH) FIND_LIBRARY(GTK_gtk_2_LIBRARY NAMES gtk-win32-2.0 gtk-x11-2.0 PATHS ${GTK_DIR}/lib ${GTK_DIR}/bin ${GTK_DIR}/win32/bin ${GTK_DIR}/lib ${GTK_DIR}/win32/lib /usr/lib /usr/local/lib ENV LIB DOC "gtk2 library to link with" NO_SYSTEM_ENVIRONMENT_PATH) FIND_LIBRARY(GTK_gdk_pixbuf_2_STATIC_LIBRARY NAMES libgdk_pixbuf-2.0.a PATHS ${GTK_DIR}/lib ${GTK_DIR}/bin ${GTK_DIR}/win32/bin ${GTK_DIR}/lib ${GTK_DIR}/win32/lib /usr/local/lib /usr/lib ENV LIB DOC "gdk_pixbuf library to link with" NO_SYSTEM_ENVIRONMENT_PATH) FIND_LIBRARY(GTK_gdk_2_STATIC_LIBRARY NAMES libgdk-x11-2.0.a PATHS ${GTK_DIR}/lib ${GTK_DIR}/bin ${GTK_DIR}/win32/bin ${GTK_DIR}/lib ${GTK_DIR}/win32/lib /usr/lib /usr/local/lib ENV LIB DOC "gdk2 library to link with" NO_SYSTEM_ENVIRONMENT_PATH) FIND_LIBRARY(GTK_gtk_2_STATIC_LIBRARY NAMES libgtk-x11-2.0.a PATHS ${GTK_DIR}/lib ${GTK_DIR}/bin ${GTK_DIR}/win32/bin ${GTK_DIR}/lib ${GTK_DIR}/win32/lib /usr/lib /usr/local/lib ENV LIB DOC "gtk2 library to link with" NO_SYSTEM_ENVIRONMENT_PATH) IF (GTK_gtk_2_INCLUDE_DIR AND GTK_gdk_2_INCLUDE_DIR AND GTK_gdkconfig_2_INCLUDE_DIR) SET(GTK2_INCLUDE_DIR ${GTK_gtk_2_INCLUDE_DIR} ${GTK_gdk_2_INCLUDE_DIR} ${GTK_gdkconfig_2_INCLUDE_DIR}) list(REMOVE_DUPLICATES GTK2_INCLUDE_DIR) SET(GTK2_LIBRARIES ${GTK_gdk_pixbuf_2_LIBRARY} ${GTK_gdk_2_LIBRARY} ${GTK_gtk_2_LIBRARY}) list(REMOVE_DUPLICATES GTK2_LIBRARIES) SET(GTK2_STATIC_LIBRARIES ${GTK_gdk_pixbuf_2_STATIC_LIBRARY} ${GTK_gdk_2_STATIC_LIBRARY} ${GTK_gtk_2_STATIC_LIBRARY}) list(REMOVE_DUPLICATES GTK2_STATIC_LIBRARIES) SET(GTK2_FOUND TRUE) message(STATUS "GTK2_INCLUDE_DIR: ${GTK2_INCLUDE_DIR}") message(STATUS "GTK2_LIBRARIES: ${GTK2_LIBRARIES}") message(STATUS "GTK2_STATIC_LIBRARIES: ${GTK2_STATIC_LIBRARIES}") ENDIF ()neko-2-2-0/cmake/FindMariaDBConnector.cmake000066400000000000000000000043371321613172000204450ustar00rootroot00000000000000# https://github.com/mariadb-corporation/MaxScale/blob/develop/cmake/FindMariaDBConnector.cmake # This CMake file tries to find the the MariaDB Connector-C # The following variables are set: # MARIADB_CONNECTOR_FOUND - System has the connector # MARIADB_CONNECTOR_STATIC_FOUND - System has static version of the connector library # MARIADB_CONNECTOR_LIBRARIES - The dynamic connector libraries # MARIADB_CONNECTOR_STATIC_LIBRARIES - The static connector libraries # MARIADB_CONNECTOR_INCLUDE_DIR - The connector headers find_library(MARIADB_CONNECTOR_LIBRARIES NAMES mysqlclient PATH_SUFFIXES mariadb mysql) if(${MARIADB_CONNECTOR_LIBRARIES} MATCHES "NOTFOUND") set(MARIADB_CONNECTOR_FOUND FALSE CACHE INTERNAL "") message(STATUS "Dynamic MySQL client library not found.") unset(MARIADB_CONNECTOR_LIBRARIES) else() set(MARIADB_CONNECTOR_FOUND TRUE CACHE INTERNAL "") message(STATUS "Found dynamic MySQL client library: ${MARIADB_CONNECTOR_LIBRARIES}") endif() set(OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") find_library(MARIADB_CONNECTOR_STATIC_LIBRARIES NAMES mysqlclient PATH_SUFFIXES mariadb mysql) set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) if(${MARIADB_CONNECTOR_STATIC_LIBRARIES} MATCHES "NOTFOUND") set(MARIADB_CONNECTOR_STATIC_FOUND FALSE CACHE INTERNAL "") message(STATUS "Static MySQL client library not found.") unset(MARIADB_CONNECTOR_STATIC_LIBRARIES) else() set(MARIADB_CONNECTOR_STATIC_FOUND TRUE CACHE INTERNAL "") message(STATUS "Found statc MySQL client library: ${MARIADB_CONNECTOR_STATIC_LIBRARIES}") endif() find_path(MARIADB_CONNECTOR_INCLUDE_DIR mysql.h PATH_SUFFIXES mariadb mysql) if(NOT (${MARIADB_CONNECTOR_INCLUDE_DIR} MATCHES "NOTFOUND")) include(CheckSymbolExists) set(CMAKE_REQUIRED_INCLUDES ${MARIADB_CONNECTOR_INCLUDE_DIR}) check_symbol_exists(LIBMARIADB mysql.h HAVE_MARIADB_CONNECTOR) endif() if(HAVE_MARIADB_CONNECTOR) message(STATUS "Found MariaDB Connector-C") set(MARIADB_CONNECTOR_FOUND TRUE CACHE INTERNAL "" FORCE) else() set(MARIADB_CONNECTOR_FOUND FALSE CACHE INTERNAL "") unset(MARIADB_CONNECTOR_STATIC_FOUND) unset(MARIADB_CONNECTOR_LIBRARIES) unset(MARIADB_CONNECTOR_STATIC_LIBRARIES) unset(MARIADB_CONNECTOR_INCLUDE_DIR) endif() neko-2-2-0/cmake/FindMbedTLS.cmake000066400000000000000000000027651321613172000165700ustar00rootroot00000000000000# https://github.com/FreeRDP/FreeRDP/blob/master/cmake/FindMbedTLS.cmake find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/ssl.h PATH_SUFFIXES include HINTS ${MBEDTLS_ROOT}) find_library(MBEDTLS_LIBRARY NAMES mbedtls PATH_SUFFIXES lib HINTS ${MBEDTLS_ROOT}) find_library(MBEDCRYPTO_LIBRARY NAMES mbedcrypto PATH_SUFFIXES lib HINTS ${MBEDTLS_ROOT}) find_library(MBEDX509_LIBRARY NAMES mbedx509 PATH_SUFFIXES lib HINTS ${MBEDTLS_ROOT}) find_library(MBEDTLS_STATIC_LIBRARY NAMES libmbedtls.a PATH_SUFFIXES lib HINTS ${MBEDTLS_ROOT}) find_library(MBEDCRYPTO_STATIC_LIBRARY NAMES libmbedcrypto.a PATH_SUFFIXES lib HINTS ${MBEDTLS_ROOT}) find_library(MBEDX509_STATIC_LIBRARY NAMES libmbedx509.a PATH_SUFFIXES lib HINTS ${MBEDTLS_ROOT}) if(MBEDTLS_INCLUDE_DIR) set(MBEDTLS_FOUND TRUE) endif() if(MBEDTLS_LIBRARY) set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDCRYPTO_LIBRARY} ${MBEDX509_LIBRARY}) endif() if(MBEDTLS_STATIC_LIBRARY) set(MBEDTLS_STATIC_LIBRARIES ${MBEDTLS_STATIC_LIBRARY} ${MBEDX509_STATIC_LIBRARY} ${MBEDCRYPTO_STATIC_LIBRARY}) endif() if(MBEDTLS_FOUND) if(NOT MBEDTLS_FIND_QUIETLY) if (MBEDTLS_LIBRARIES) message(STATUS "Found MBEDTLS_LIBRARIES: ${MBEDTLS_LIBRARIES}") endif() if (MBEDTLS_STATIC_LIBRARIES) message(STATUS "Found MBEDTLS_STATIC_LIBRARIES: ${MBEDTLS_STATIC_LIBRARIES}") endif() endif() else() if(MBEDTLS_FIND_REQUIRED) message(FATAL_ERROR "mbed TLS was not found") endif() endif() mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY)neko-2-2-0/cmake/FindPCRE.cmake000066400000000000000000000032311321613172000160540ustar00rootroot00000000000000# https://github.com/CBL-ORION/Vaa3D-tools-mirror/blob/filter-large-files/released_plugins/v3d_plugins/neurontracing_neutube/src_neutube/neurolabi/c/cmake_modules/FindPCRE.cmake # - Try to find PCRE # Once done, this will define # # PCRE_FOUND - system has PCRE # PCRE_INCLUDE_DIRS - the PCRE include directories # PCRE_LIBRARIES - link these to use PCRE # # By default, the dynamic libraries will be found. To find the static ones instead, # you must set the PCRE_STATIC_LIBRARY variable to TRUE before calling find_package. # include(LibFindMacros) # Use pkg-config to get hints about paths libfind_pkg_check_modules(PCRE_PKGCONF libpcre) # attempt to find static library first if this is set if(PCRE_STATIC_LIBRARY) set(PCRE_POSIX_STATIC libpcreposix.a) set(PCRE_STATIC libpcre.a) endif(PCRE_STATIC_LIBRARY) # additional hints if(MINGW) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} C:/Mingw) endif(MINGW) if(MSVC) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} D:/devlib/vc/PCRE) endif(MSVC) # Include dir find_path(PCRE_INCLUDE_DIR NAMES pcreposix.h PATHS ${PCRE_PKGCONF_INCLUDE_DIRS} ) # Finally the library itself find_library(PCRE_POSIX_LIBRARY NAMES ${PCRE_POSIX_STATIC} pcreposix PATHS ${PCRE_PKGCONF_LIBRARY_DIRS} ) find_library(PCRE_LIBRARY NAMES ${PCRE_STATIC} pcre PATHS ${PCRE_PKGCONF_LIBRARY_DIRS} ) set(PCRE_POSIX_LIBRARY ${PCRE_POSIX_LIBRARY} ${PCRE_LIBRARY}) # Set the include dir variables and the libraries and let libfind_process do the rest. # NOTE: Singular variables for this library, plural for libraries this this lib depends on. set(PCRE_PROCESS_INCLUDES PCRE_INCLUDE_DIR) set(PCRE_PROCESS_LIBS PCRE_POSIX_LIBRARY) libfind_process(PCRE)neko-2-2-0/cmake/FindSqlite3.cmake000066400000000000000000000037501321613172000166550ustar00rootroot00000000000000# https://github.com/decimalbell/dust/blob/master/cmake/FindSqlite3.cmake # FindSqlite3 # -------- # # Find sqlite3 # # Find the sqlite3 includes and library. Once done this will define # # SQLITE3_INCLUDE_DIRS - where to find sqlite3.h, etc. # SQLITE3_LIBRARIES - List of libraries when using sqlite3. # SQLITE3_STATIC_LIBRARIES - List of static libraries when using sqlite3. # SQLITE3_FOUND - True if sqlite3 found. # #============================================================================= # Copyright 2001-2011 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) find_path(SQLITE3_INCLUDE_DIR NAMES sqlite3.h) find_library(SQLITE3_LIBRARY NAMES sqlite3) find_library(SQLITE3_STATIC_LIBRARY NAMES libsqlite3.a) mark_as_advanced(SQLITE3_LIBRARY SQLITE3_STATIC_LIBRARY SQLITE3_INCLUDE_DIR) # handle the QUIETLY and REQUIRED arguments and set SQLITE3_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Sqlite3 REQUIRED_VARS SQLITE3_LIBRARY SQLITE3_STATIC_LIBRARY SQLITE3_INCLUDE_DIR VERSION_VAR SQLITE3_VERSION_STRING) if(SQLITE3_FOUND) set(SQLITE3_INCLUDE_DIRS ${SQLITE3_INCLUDE_DIR}) set(SQLITE3_LIBRARIES ${SQLITE3_LIBRARY}) set(SQLITE3_STATIC_LIBRARIES ${SQLITE3_STATIC_LIBRARY}) message(STATUS "SQLITE3_INCLUDE_DIRS ${SQLITE3_INCLUDE_DIRS}") message(STATUS "SQLITE3_LIBRARIES ${SQLITE3_LIBRARIES}") message(STATUS "SQLITE3_STATIC_LIBRARIES ${SQLITE3_STATIC_LIBRARIES}") endif() neko-2-2-0/cmake/FindZlib.cmake000066400000000000000000000014301321613172000162220ustar00rootroot00000000000000# ZLIB_ROOT hints the location # Provides # - ZLIB, # - ZLIB_LIBRARIES, # - ZLIB_STATIC_LIBRARIES, # - ZLIB_FOUND find_path(ZLIB_INCLUDE_DIR zlib.h PATH_SUFFIXES include) find_library(ZLIB_STATIC_LIBRARIES libz.a PATH_SUFFIXES lib lib64) set(ZLIB_NAMES z zlib zdll zlib1 zlibd zlibd1) find_library(ZLIB_LIBRARIES ${ZLIB_NAMES} PATH_SUFFIXES lib lib64) if (NOT ZLIB_LIBRARIES AND NOT ZLIB_STATIC_LIBRARIES) message(FATAL_ERROR "zlib not found in ${ZLIB_ROOT}") set(ZLIB_FOUND FALSE) else() message(STATUS "Zlib: ${ZLIB_INCLUDE_DIR}") message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}") message(STATUS "ZLIB_STATIC_LIBRARIES: ${ZLIB_STATIC_LIBRARIES}") set(ZLIB_FOUND TRUE) endif() mark_as_advanced( ZLIB_INCLUDE_DIR ZLIB_LIBRARIES ZLIB_STATIC ZLIB_STATIC_FOUND )neko-2-2-0/cmake/LibFindMacros.cmake000066400000000000000000000247161321613172000172110ustar00rootroot00000000000000# Version 2.2 # Public Domain, originally written by Lasse Kärkkäinen # Maintained at https://github.com/Tronic/cmake-modules # Please send your improvements as pull requests on Github. # Find another package and make it a dependency of the current package. # This also automatically forwards the "REQUIRED" argument. # Usage: libfind_package( [extra args to find_package]) macro (libfind_package PREFIX PKG) set(${PREFIX}_args ${PKG} ${ARGN}) if (${PREFIX}_FIND_REQUIRED) set(${PREFIX}_args ${${PREFIX}_args} REQUIRED) endif() find_package(${${PREFIX}_args}) set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG}) unset(${PREFIX}_args) endmacro() # A simple wrapper to make pkg-config searches a bit easier. # Works the same as CMake's internal pkg_check_modules but is always quiet. macro (libfind_pkg_check_modules) find_package(PkgConfig QUIET) if (PKG_CONFIG_FOUND) pkg_check_modules(${ARGN} QUIET) endif() endmacro() # Avoid useless copy&pasta by doing what most simple libraries do anyway: # pkg-config, find headers, find library. # Usage: libfind_pkg_detect( FIND_PATH [other args] FIND_LIBRARY [other args]) # E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2) function (libfind_pkg_detect PREFIX) # Parse arguments set(argname pkgargs) foreach (i ${ARGN}) if ("${i}" STREQUAL "FIND_PATH") set(argname pathargs) elseif ("${i}" STREQUAL "FIND_LIBRARY") set(argname libraryargs) else() set(${argname} ${${argname}} ${i}) endif() endforeach() if (NOT pkgargs) message(FATAL_ERROR "libfind_pkg_detect requires at least a pkg_config package name to be passed.") endif() # Find library libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs}) if (pathargs) find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS}) endif() if (libraryargs) find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}) endif() endfunction() # Extracts a version #define from a version.h file, output stored to _VERSION. # Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR) # Fourth argument "QUIET" may be used for silently testing different define names. # This function does nothing if the version variable is already defined. function (libfind_version_header PREFIX VERSION_H DEFINE_NAME) # Skip processing if we already have a version or if the include dir was not found if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR) return() endif() set(quiet ${${PREFIX}_FIND_QUIETLY}) # Process optional arguments foreach(arg ${ARGN}) if (arg STREQUAL "QUIET") set(quiet TRUE) else() message(AUTHOR_WARNING "Unknown argument ${arg} to libfind_version_header ignored.") endif() endforeach() # Read the header and parse for version number set(filename "${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") if (NOT EXISTS ${filename}) if (NOT quiet) message(AUTHOR_WARNING "Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") endif() return() endif() file(READ "${filename}" header) string(REGEX REPLACE ".*#[ \t]*define[ \t]*${DEFINE_NAME}[ \t]*\"([^\n]*)\".*" "\\1" match "${header}") # No regex match? if (match STREQUAL header) if (NOT quiet) message(AUTHOR_WARNING "Unable to find \#define ${DEFINE_NAME} \"\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") endif() return() endif() # Export the version string set(${PREFIX}_VERSION "${match}" PARENT_SCOPE) endfunction() # Do the final processing once the paths have been detected. # If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain # all the variables, each of which contain one include directory. # Ditto for ${PREFIX}_PROCESS_LIBS and library files. # Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. # Also handles errors in case library detection was required, etc. function (libfind_process PREFIX) # Skip processing if already processed during this configuration run if (${PREFIX}_FOUND) return() endif() set(found TRUE) # Start with the assumption that the package was found # Did we find any files? Did we miss includes? These are for formatting better error messages. set(some_files FALSE) set(missing_headers FALSE) # Shorthands for some variables that we need often set(quiet ${${PREFIX}_FIND_QUIETLY}) set(required ${${PREFIX}_FIND_REQUIRED}) set(exactver ${${PREFIX}_FIND_VERSION_EXACT}) set(findver "${${PREFIX}_FIND_VERSION}") set(version "${${PREFIX}_VERSION}") # Lists of config option names (all, includes, libs) unset(configopts) set(includeopts ${${PREFIX}_PROCESS_INCLUDES}) set(libraryopts ${${PREFIX}_PROCESS_LIBS}) # Process deps to add to foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES}) if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS) # The package seems to export option lists that we can use, woohoo! list(APPEND includeopts ${${i}_INCLUDE_OPTS}) list(APPEND libraryopts ${${i}_LIBRARY_OPTS}) else() # If plural forms don't exist or they equal singular forms if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR ({i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES)) # Singular forms can be used if (DEFINED ${i}_INCLUDE_DIR) list(APPEND includeopts ${i}_INCLUDE_DIR) endif() if (DEFINED ${i}_LIBRARY) list(APPEND libraryopts ${i}_LIBRARY) endif() else() # Oh no, we don't know the option names message(FATAL_ERROR "We couldn't determine config variable names for ${i} includes and libs. Aieeh!") endif() endif() endforeach() if (includeopts) list(REMOVE_DUPLICATES includeopts) endif() if (libraryopts) list(REMOVE_DUPLICATES libraryopts) endif() string(REGEX REPLACE ".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))" "\\1" tmp "${includeopts} ${libraryopts}") if (NOT tmp STREQUAL "${includeopts} ${libraryopts}") message(AUTHOR_WARNING "Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).") endif() # Include/library names separated by spaces (notice: not CMake lists) unset(includes) unset(libs) # Process all includes and set found false if any are missing foreach (i ${includeopts}) list(APPEND configopts ${i}) if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") list(APPEND includes "${${i}}") else() set(found FALSE) set(missing_headers TRUE) endif() endforeach() # Process all libraries and set found false if any are missing foreach (i ${libraryopts}) list(APPEND configopts ${i}) if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") list(APPEND libs "${${i}}") else() set (found FALSE) endif() endforeach() # Version checks if (found AND findver) if (NOT version) message(WARNING "The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.") elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver)) set(found FALSE) set(version_unsuitable TRUE) endif() endif() # If all-OK, hide all config options, export variables, print status and exit if (found) foreach (i ${configopts}) mark_as_advanced(${i}) endforeach() if (NOT quiet) message(STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") if (LIBFIND_DEBUG) message(STATUS " ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}") message(STATUS " ${PREFIX}_INCLUDE_OPTS=${includeopts}") message(STATUS " ${PREFIX}_INCLUDE_DIRS=${includes}") message(STATUS " ${PREFIX}_LIBRARY_OPTS=${libraryopts}") message(STATUS " ${PREFIX}_LIBRARIES=${libs}") endif() set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE) set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE) set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE) set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE) set (${PREFIX}_FOUND TRUE PARENT_SCOPE) endif() return() endif() # Format messages for debug info and the type of error set(vars "Relevant CMake configuration variables:\n") foreach (i ${configopts}) mark_as_advanced(CLEAR ${i}) set(val ${${i}}) if ("${val}" STREQUAL "${i}-NOTFOUND") set (val "") elseif (val AND NOT EXISTS ${val}) set (val "${val} (does not exist)") else() set(some_files TRUE) endif() set(vars "${vars} ${i}=${val}\n") endforeach() set(vars "${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\n") if (version_unsuitable) set(msg "${PREFIX} ${${PREFIX}_VERSION} was found but") if (exactver) set(msg "${msg} only version ${findver} is acceptable.") else() set(msg "${msg} version ${findver} is the minimum requirement.") endif() else() if (missing_headers) set(msg "We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?") elseif (some_files) set(msg "We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?") if(findver) set(msg "${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).") endif() else() set(msg "We were unable to find package ${PREFIX}.") endif() endif() # Fatal error out if REQUIRED if (required) set(msg "REQUIRED PACKAGE NOT FOUND\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.") message(FATAL_ERROR "${msg}\n${vars}") endif() # Otherwise just print a nasty warning if (NOT quiet) message(WARNING "WARNING: MISSING PACKAGE\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \n${vars}") endif() endfunction() neko-2-2-0/cmake/NekoConfig.cmake.in000066400000000000000000000017141321613172000171550ustar00rootroot00000000000000# - Config file for the Neko package # It defines the following variables # NEKO_INCLUDE_DIRS - include directories for Neko # NEKO_LIBRARIES - libraries to link against # NEKO_EXECUTABLE - the Neko VM executable # NEKOC_EXECUTABLE - the Neko compiler executable # NEKOML_EXECUTABLE - the NekoML compiler executable # NEKOTOOLS_EXECUTABLE - the nekotools executable @PACKAGE_INIT@ # Our library dependencies (contains definitions for IMPORTED targets) if(NOT TARGET neko) include("@PACKAGE_NEKO_TARGETS_FILE@") endif() # Use set instead of set_and_check, which doesn't handle lists properly # https://gitlab.kitware.com/cmake/cmake/issues/16219 set(NEKO_INCLUDE_DIRS "@PACKAGE_NEKO_INCLUDE_DIRS@") # These are IMPORTED targets created by NekoTargets.cmake set(NEKO_LIBRARIES libneko) set(NEKO_EXECUTABLE nekovm) set(NEKOC_EXECUTABLE nekoc) set(NEKOML_EXECUTABLE nekoml) set(NEKOTOOLS_EXECUTABLE nekotools) check_required_components(Neko) neko-2-2-0/cmake/flatten.cmake.in000066400000000000000000000026651321613172000165760ustar00rootroot00000000000000# Detect if the install is run by CPack. if (${CMAKE_INSTALL_PREFIX} MATCHES "/_CPack_Packages/.*/(TGZ|ZIP)/") # Flatten the directory structure such that everything except the header files is placed in root. if (${CMAKE_VERSION} VERSION_LESS 3.3) file(GLOB bin_files ${CMAKE_INSTALL_PREFIX}/bin/*) file(GLOB lib_files ${CMAKE_INSTALL_PREFIX}/lib/* ${CMAKE_INSTALL_PREFIX}/lib/**/*) foreach(file ${bin_files} ${lib_files}) if (NOT IS_DIRECTORY ${file}) get_filename_component(file_name ${file} NAME) execute_process( COMMAND ${CMAKE_COMMAND} -E rename ${file} ${CMAKE_INSTALL_PREFIX}/${file_name} ) endif() endforeach() else() file(GLOB bin_files LIST_DIRECTORIES FALSE ${CMAKE_INSTALL_PREFIX}/bin/*) file(GLOB lib_files LIST_DIRECTORIES FALSE ${CMAKE_INSTALL_PREFIX}/lib/* ${CMAKE_INSTALL_PREFIX}/lib/**/*) foreach(file ${bin_files} ${lib_files}) get_filename_component(file_name ${file} NAME) execute_process( COMMAND ${CMAKE_COMMAND} -E rename ${file} ${CMAKE_INSTALL_PREFIX}/${file_name} ) endforeach() endif() execute_process( COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/bin) execute_process( COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/lib) # install additional files file ( INSTALL @CMAKE_SOURCE_DIR@/README.md @CMAKE_SOURCE_DIR@/LICENSE @CMAKE_SOURCE_DIR@/CHANGES DESTINATION ${CMAKE_INSTALL_PREFIX} ) endif() neko-2-2-0/cmake/ldconfig.cmake000066400000000000000000000004611321613172000163110ustar00rootroot00000000000000# Detect if the install is run by CPack. if (NOT CMAKE_INSTALL_PREFIX MATCHES "/_CPack_Packages/.*/(TGZ|ZIP)/") message(STATUS "Running: ldconfig") execute_process(COMMAND "ldconfig" RESULT_VARIABLE ldconfig_result) if (NOT ldconfig_result EQUAL 0) message(WARNING "ldconfig failed") endif() endif()neko-2-2-0/cmake/package_choco.cmake000066400000000000000000000032511321613172000172720ustar00rootroot00000000000000find_package(Git REQUIRED) # format SNAPSHOT_VERSION execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD OUTPUT_VARIABLE COMMIT_SHA OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%cI HEAD OUTPUT_VARIABLE COMMIT_TIME OUTPUT_STRIP_TRAILING_WHITESPACE ) string(SUBSTRING ${COMMIT_TIME} 0 19 COMMIT_TIME) string(REGEX REPLACE [^0-9] "" COMMIT_TIME ${COMMIT_TIME}) set(SNAPSHOT_VERSION ${NEKO_VERSION}-SNAP${COMMIT_TIME}) message(STATUS "building package version ${SNAPSHOT_VERSION} using ${bin_archive}") get_filename_component(bin_archive_dir ${bin_archive} DIRECTORY) execute_process( COMMAND ${CMAKE_COMMAND} -E tar x ${bin_archive} WORKING_DIRECTORY ${bin_archive_dir} ) configure_file( ${source_dir}/extra/neko.nuspec ${bin_archive_dir}/${bin_archive_name_we}/neko.nuspec @ONLY ) configure_file( ${source_dir}/extra/chocolateyInstall.ps1 ${bin_archive_dir}/${bin_archive_name_we}/chocolateyInstall.ps1 @ONLY ) configure_file( ${source_dir}/extra/chocolateyUninstall.ps1 ${bin_archive_dir}/${bin_archive_name_we}/chocolateyUninstall.ps1 @ONLY ) execute_process( COMMAND choco pack WORKING_DIRECTORY ${bin_archive_dir}/${bin_archive_name_we} ) file(GLOB nupkg ${bin_archive_dir}/${bin_archive_name_we}/*.nupkg ) get_filename_component(nupkg_name ${nupkg} NAME) message(STATUS "created ${nupkg_name}") file(COPY ${nupkg} DESTINATION ${bin_archive_dir}) file(REMOVE_RECURSE ${bin_archive_dir}/${bin_archive_name_we}) if(DEFINED ENV{APPVEYOR}) message(STATUS "pushing ${nupkg_name} to AppVeyor feeds") execute_process( COMMAND appveyor PushArtifact ${nupkg_name} WORKING_DIRECTORY ${bin_archive_dir} ) endif()neko-2-2-0/cmake/patch_mariadb.cmake000066400000000000000000000005711321613172000173040ustar00rootroot00000000000000# https://jira.mariadb.org/browse/CONC-174 set(cmakelists ${mariadb_source}/CMakeLists.txt) file(READ ${cmakelists} content) # do not use replace /MD with /MT string(REPLACE "STRING(REPLACE \"/MD\" \"/MT\" COMPILER_FLAGS \${COMPILER_FLAGS})" "# STRING(REPLACE \"/MD\" \"/MT\" COMPILER_FLAGS \${COMPILER_FLAGS})" content ${content} ) file(WRITE ${cmakelists} ${content})neko-2-2-0/cmake/patch_mbedtls.cmake000066400000000000000000000031101321613172000173270ustar00rootroot00000000000000# Apply config adjustments similer to Debian's # https://anonscm.debian.org/cgit/collab-maint/mbedtls.git/tree/debian/patches/01_config.patch set(config ${MbedTLS_source}/include/mbedtls/config.h) file(READ ${config} content) # disable support for SSL 3.0 string(REPLACE "#define MBEDTLS_SSL_PROTO_SSL3" "//#define MBEDTLS_SSL_PROTO_SSL3" content ${content} ) if (WIN32) # allow alternate threading implementation string(REPLACE "//#define MBEDTLS_THREADING_ALT" "#define MBEDTLS_THREADING_ALT" content ${content} ) # disable the TCP/IP networking routines # such that it wouldn't interfere with the #include in our threading_alt.h string(REPLACE "#define MBEDTLS_NET_C" "//#define MBEDTLS_NET_C" content ${content} ) file(COPY ${source}/libs/ssl/threading_alt.h DESTINATION ${MbedTLS_source}/include/mbedtls/ ) else() # enable pthread mutexes string(REPLACE "//#define MBEDTLS_THREADING_PTHREAD" "#define MBEDTLS_THREADING_PTHREAD" content ${content} ) endif() # enable the HAVEGE random generator string(REPLACE "//#define MBEDTLS_HAVEGE_C" "#define MBEDTLS_HAVEGE_C" content ${content} ) # enable support for (rare) MD2-signed X.509 certs string(REPLACE "//#define MBEDTLS_MD2_C" "#define MBEDTLS_MD2_C" content ${content} ) # enable support for (rare) MD4-signed X.509 certs string(REPLACE "//#define MBEDTLS_MD4_C" "#define MBEDTLS_MD4_C" content ${content} ) # allow use of mutexes within mbed TLS string(REPLACE "//#define MBEDTLS_THREADING_C" "#define MBEDTLS_THREADING_C" content ${content} ) file(WRITE ${config} ${content})neko-2-2-0/cmake/patch_openssl.cmake000066400000000000000000000005051321613172000173650ustar00rootroot00000000000000set(configure ${openssl_source}/Configure) file(READ ${configure} content) # Make it possible to disable building and running tests # https://github.com/openssl/openssl/pull/1514/files string(REPLACE "my @disablables = \(" "my @disablables = \( \"tests\"," content "${content}" ) file(WRITE ${configure} "${content}")neko-2-2-0/cmake/source_archive_fat.cmake000066400000000000000000000024041321613172000203560ustar00rootroot00000000000000get_filename_component(source_archive_dir ${source_archive} DIRECTORY) execute_process( COMMAND ${CMAKE_COMMAND} -E tar x ${source_archive} WORKING_DIRECTORY ${source_archive_dir} ) file(RENAME ${source_archive_dir}/${source_archive_name_we} ${source_archive_dir}/${source_archive_fat_name_we}) if (${CMAKE_VERSION} VERSION_LESS 3.3) file(GLOB archives ${bin_dir}/${lib_src_dir}/* ) foreach(file ${archives}) if(NOT IS_DIRECTORY ${file}) file(COPY ${file} DESTINATION ${source_archive_dir}/${source_archive_fat_name_we}/${lib_src_dir}) endif() endforeach() else() file(GLOB archives LIST_DIRECTORIES FALSE ${bin_dir}/${lib_src_dir}/* ) file(COPY ${archives} DESTINATION ${source_archive_dir}/${source_archive_fat_name_we}/${lib_src_dir}) endif() if (${source_archive_fat_name} MATCHES ^.*.zip$) execute_process( COMMAND ${CMAKE_COMMAND} -E tar cf ${source_archive_fat_name} ${source_archive_dir}/${source_archive_fat_name_we} --format=zip WORKING_DIRECTORY ${source_archive_dir} ) else() execute_process( COMMAND ${CMAKE_COMMAND} -E tar czf ${source_archive_fat_name} ${source_archive_dir}/${source_archive_fat_name_we} WORKING_DIRECTORY ${source_archive_dir} ) endif() file(REMOVE_RECURSE ${source_archive_dir}/${source_archive_fat_name_we}) neko-2-2-0/cmake/uninstall.cmake.in000066400000000000000000000021321321613172000171370ustar00rootroot00000000000000# https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif(NOT "${rm_retval}" STREQUAL 0) else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endforeach(file)neko-2-2-0/cmake/upload_to_ppa.cmake000066400000000000000000000061411321613172000173530ustar00rootroot00000000000000find_package(Git REQUIRED) set(neko_debian_dir ${bin_dir}/neko-debian) # format SNAPSHOT_VERSION execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD OUTPUT_VARIABLE COMMIT_SHA OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%ct HEAD OUTPUT_VARIABLE COMMIT_TIME OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND date -u -d @${COMMIT_TIME} +%Y%m%d%H%M%S OUTPUT_VARIABLE COMMIT_TIME OUTPUT_STRIP_TRAILING_WHITESPACE ) set(SNAPSHOT_VERSION ${NEKO_VERSION}+1SNAPSHOT${COMMIT_TIME}+${COMMIT_SHA}) message(STATUS "building source package version ${SNAPSHOT_VERSION}") message(STATUS "setting up neko-debian repo") if (EXISTS ${neko_debian_dir}) execute_process( COMMAND ${GIT_EXECUTABLE} fetch --all WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} clean -fx WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} reset --hard HEAD WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} tag -d upstream/${SNAPSHOT_VERSION} WORKING_DIRECTORY ${neko_debian_dir} ) else() execute_process( COMMAND ${GIT_EXECUTABLE} clone https://github.com/HaxeFoundation/neko-debian.git ${neko_debian_dir} ) endif() foreach(branch upstream next) execute_process( COMMAND ${GIT_EXECUTABLE} checkout ${branch} WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} reset --hard origin/${branch} WORKING_DIRECTORY ${neko_debian_dir} ) endforeach() message(STATUS "import changes from source archive to neko-debian") get_filename_component(source_archive_name ${source_archive} NAME) file(COPY ${source_archive} DESTINATION ${bin_dir}) file(RENAME ${bin_dir}/${source_archive_name} ${bin_dir}/neko_${SNAPSHOT_VERSION}.orig.tar.gz) execute_process( COMMAND gbp import-orig ${bin_dir}/neko_${SNAPSHOT_VERSION}.orig.tar.gz -u ${SNAPSHOT_VERSION} --debian-branch=next WORKING_DIRECTORY ${neko_debian_dir} ) set(distros trusty xenial zesty artful bionic ) if (DEFINED ENV{PPA}) set(PPA $ENV{PPA}) else() set(PPA "ppa:haxe/snapshots") endif() foreach(distro ${distros}) message(STATUS "backporting to ${distro} and will upload to ${PPA}") execute_process( COMMAND ${GIT_EXECUTABLE} checkout . WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} checkout next-${distro} WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} clean -fx WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} reset --hard origin/next-${distro} WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND ${GIT_EXECUTABLE} merge next -m "merge" WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND dch -v "${SNAPSHOT_VERSION}-1" --urgency low "snapshot build" WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND debuild -S -sa WORKING_DIRECTORY ${neko_debian_dir} ) execute_process( COMMAND backportpackage -d ${distro} --upload ${PPA} --yes neko_${SNAPSHOT_VERSION}-1.dsc WORKING_DIRECTORY ${bin_dir} ) endforeach()neko-2-2-0/deploy.sh000077500000000000000000000011511321613172000142720ustar00rootroot00000000000000#!/bin/bash set -ex if [ -z $haxeci_decrypt ]; then echo "haxeci_decrypt is unset, skip deploy" exit fi openssl aes-256-cbc -k "$haxeci_decrypt" -in haxeci_ssh.enc -out haxeci_ssh -d chmod 600 haxeci_ssh eval `ssh-agent -s` ssh-add haxeci_ssh openssl aes-256-cbc -k "$haxeci_decrypt" -in haxeci_sec.gpg.enc -out haxeci_sec.gpg -d gpg --allow-secret-key-import --import haxeci_sec.gpg sudo apt-get install devscripts git-buildpackage ubuntu-dev-tools dh-make dh-apache2 -y git config --global user.name "${DEBFULLNAME}" git config --global user.email "${DEBEMAIL}" pushd build make upload_to_ppa popd neko-2-2-0/extra/000077500000000000000000000000001321613172000135645ustar00rootroot00000000000000neko-2-2-0/extra/chocolateyInstall.ps1000066400000000000000000000010411321613172000176660ustar00rootroot00000000000000$scriptPath = (Split-Path -parent $MyInvocation.MyCommand.Definition) # Install the dll files to C:\ProgramData\chocolatey\bin # It is because they are loaded by other neko binaries, e.g. haxelib.exe $chocoBin = Join-Path $env:ChocolateyInstall 'bin' $dllFiles = @('gcmt-dll.dll', 'neko.dll') foreach ($file in $dllFiles) { $dllFile = Join-Path $scriptPath $file copy "$dllFile" "$chocoBin" } # Set NEKOPATH such that the ndll files can be loaded. Install-ChocolateyEnvironmentVariable -VariableName NEKOPATH -VariableValue $scriptPathneko-2-2-0/extra/chocolateyUninstall.ps1000066400000000000000000000005721321613172000202410ustar00rootroot00000000000000$scriptPath = (Split-Path -parent $MyInvocation.MyCommand.Definition) # Remove the dll files from C:\ProgramData\chocolatey\bin $chocoBin = Join-Path $env:ChocolateyInstall 'bin' $dllFiles = @('gcmt-dll.dll', 'neko.dll') foreach ($file in $dllFiles) { $dllFile = Join-Path $chocoBin $file del "$dllFile" } Uninstall-ChocolateyEnvironmentVariable -VariableName NEKOPATHneko-2-2-0/extra/neko.nuspec000066400000000000000000000031631321613172000157420ustar00rootroot00000000000000 neko @SNAPSHOT_VERSION@ Neko Haxe Foundation Haxe Foundation https://github.com/HaxeFoundation/neko/blob/master/LICENSE http://nekovm.org/ http://nekovm.org/doc https://groups.google.com/forum/#!forum/haxelang https://github.com/HaxeFoundation/neko/issues https://github.com/HaxeFoundation/neko https://github.com/HaxeFoundation/neko/tree/master/extra https://cdn.rawgit.com/andyli/cc07575f598351e0ad74/raw/6a9cae9a136670c0052356b773f8e13bf37c13dd/logo.png false Neko is a lightweight and yet well optimized virtual machine. Neko is a lightweight and yet well optimized virtual machine. The VM can be easily embedded into any application and your libraries can be accessed using the C foreign function interface. https://github.com/HaxeFoundation/neko/blob/master/CHANGES neko haxe vm admin neko-2-2-0/libs/000077500000000000000000000000001321613172000133725ustar00rootroot00000000000000neko-2-2-0/libs/CMakeLists.txt000066400000000000000000000126201321613172000161330ustar00rootroot00000000000000add_subdirectory(common) add_subdirectory(std) add_subdirectory(zlib) if (WITH_MYSQL) add_subdirectory(mysql) endif() if (WITH_REGEXP) add_subdirectory(regexp) endif() if (WITH_SQLITE) add_subdirectory(sqlite) endif() if (WITH_SSL) add_subdirectory(ssl) endif() if (WITH_UI) add_subdirectory(ui) endif() if (WITH_APACHE) # Locate Apache if (STATIC_APACHE) if (STATIC_OPENSSL) set(OPENSSL_CONF --with-openssl=${CMAKE_BINARY_DIR}/libs/src/install-prefix) set(OPENSSL_DEP OpenSSL) elseif() set(OPENSSL_CONF "") set(OPENSSL_DEP "") endif() if (STATIC_APR) set(APR_CONF --with-apr=${CMAKE_BINARY_DIR}/libs/src/install-prefix) set(APR_DEP APR) elseif() set(APR_CONF "") set(APR_DEP "") endif() if (STATIC_APRUTIL) set(APRUTIL_CONF --with-apr-util=${CMAKE_BINARY_DIR}/libs/src/install-prefix) set(APRUTIL_DEP APRutil) elseif() set(APRUTIL_CONF "") set(APRUTIL_DEP "") endif() if (STATIC_PCRE) set(PCRE_CONF --with-pcre=${CMAKE_BINARY_DIR}/libs/src/install-prefix) set(PCRE_DEP PCRE) elseif() set(PCRE_CONF "") set(PCRE_DEP "") endif() if (STATIC_ZLIB) set(ZLIB_CONF --with-z=${CMAKE_BINARY_DIR}/libs/src/install-prefix) set(ZLIB_DEP Zlib) elseif() set(ZLIB_CONF "") set(ZLIB_DEP "") endif() if (APPLE) set(APACHE_CFLAGS "-w -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") else() set(APACHE_CFLAGS "-w") endif() if(WIN32) set(APR_CONFIGS CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libs/src/install-prefix -Wno-dev -DAPR_INSTALL_PRIVATE_H=ON -DINSTALL_PDB=OFF ) else() set(APR_CONFIGS CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/APR && ./configure --prefix=${CMAKE_BINARY_DIR}/libs/src/install-prefix --enable-shared=no --enable-static=yes --silent BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/APR && make "CFLAGS=${APACHE_CFLAGS}" INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/APR && make install ) endif() ExternalProject_Add(APR ${EP_CONFIGS} URL http://archive.apache.org/dist/apr/apr-1.5.2.tar.gz URL_MD5 98492e965963f852ab29f9e61b2ad700 ${APR_CONFIGS} ) set_target_properties(APR PROPERTIES ${EP_PROPS}) if(WIN32) set(APRutil_CONFIGS CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libs/src/install-prefix -Wno-dev -DOPENSSL_ROOT_DIR=${CMAKE_BINARY_DIR}/libs/src/install-prefix -DINSTALL_PDB=OFF ) else() set(APRutil_CONFIGS CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/APRutil && ./configure --prefix=${CMAKE_BINARY_DIR}/libs/src/install-prefix --silent ${APR_CONF} ${OPENSSL_CONF} BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/APRutil && make "CFLAGS=${APACHE_CFLAGS}" INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/APRutil && make install ) endif() ExternalProject_Add(APRutil ${EP_CONFIGS} DEPENDS ${APR_DEP} ${OPENSSL_DEP} URL http://archive.apache.org/dist/apr/apr-util-1.5.4.tar.gz URL_MD5 866825c04da827c6e5f53daff5569f42 ${APRutil_CONFIGS} ) set_target_properties(APRutil PROPERTIES ${EP_PROPS}) if(WIN32) set(Apache_CONFIGS CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libs/src/install-prefix -Wno-dev -DOPENSSL_ROOT_DIR=${CMAKE_BINARY_DIR}/libs/src/install-prefix "-DEXTRA_COMPILE_FLAGS=/D PCRE_STATIC" -DEXTRA_LIBS=Ws2_32 BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/Apache-build && ${CMAKE_COMMAND} --build . --target libhttpd --config ${CMAKE_CFG_INTDIR} INSTALL_COMMAND echo skip install ) set(APACHE_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/libs/src/install-prefix/include ${CMAKE_BINARY_DIR}/libs/src/Apache/include ${CMAKE_BINARY_DIR}/libs/src/Apache/os/win32 ${CMAKE_BINARY_DIR}/libs/src/Apache-build ) set(APACHE_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/libapr-1.lib ${CMAKE_BINARY_DIR}/libs/src/Apache-build/${CMAKE_CFG_INTDIR}/libhttpd.lib ) else() set(Apache_CONFIGS CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/Apache && ./configure --prefix=${CMAKE_BINARY_DIR}/libs/src/Apache-build --silent ${APR_CONF} ${APRUTIL_CONF} ${OPENSSL_CONF} ${PCRE_CONF} ${ZLIB_CONF} BUILD_COMMAND echo skip build INSTALL_COMMAND echo skip install ) set(APACHE_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/libs/src/install-prefix/include/apr-1 ${CMAKE_BINARY_DIR}/libs/src/Apache/include ${CMAKE_BINARY_DIR}/libs/src/Apache/os/unix ) set(APACHE_LIBRARIES ) endif() ExternalProject_Add(Apache ${EP_CONFIGS} DEPENDS ${APR_DEP} ${APRUTIL_DEP} ${OPENSSL_DEP} ${PCRE_DEP} URL http://archive.apache.org/dist/httpd/httpd-2.4.29.tar.gz URL_MD5 6380b0856658f07479fdcba9e20294a6 ${Apache_CONFIGS} ) set_target_properties(Apache PROPERTIES ${EP_PROPS}) # Download sources for fat source archive add_dependencies(download_static_deps Apache-download) add_dependencies(download_static_deps APR-download) add_dependencies(download_static_deps APRutil-download) else() find_package(APACHE REQUIRED) find_package(APR REQUIRED) set(APACHE_LIBRARIES ${APR_LIBRARIES} ${APRUTIL_LIBRARIES}) if(HTTPD_LIBRARIES) list(APPEND APACHE_LIBRARIES ${HTTPD_LIBRARIES}) endif() set(APACHE_INCLUDE_DIRS ${APACHE_INCLUDE_DIR} ${APR_INCLUDE_DIR} ${APRUTIL_INCLUDE_DIR}) endif() add_subdirectory(mod_neko) add_subdirectory(mod_tora) endif() neko-2-2-0/libs/common/000077500000000000000000000000001321613172000146625ustar00rootroot00000000000000neko-2-2-0/libs/common/CMakeLists.txt000066400000000000000000000002411321613172000174170ustar00rootroot00000000000000configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/osdef.h.in" "${CMAKE_BINARY_DIR}/osdef.h" ) add_library(socket STATIC socket.c) add_library(sha1 STATIC sha1.c) neko-2-2-0/libs/common/osdef.h.in000066400000000000000000000040061321613172000165400ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef OS_H #define OS_H #if defined(_WIN32) # define OS_WINDOWS #endif #if defined(__APPLE__) || defined(macintosh) # define OS_MAC #endif #if defined(linux) || defined(__linux__) # define OS_LINUX #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # define OS_BSD #endif #if defined(__GNU__) # define OS_HURD #endif #if defined(__CYGWIN__) # define OS_CYGWIN #endif #if defined(OS_LINUX) || defined(OS_MAC) || defined(OS_BSD) || defined(OS_GNUKBSD) || defined (OS_HURD) || defined (OS_CYGWIN) # define OS_POSIX #endif #if defined(OS_MAC) || defined(OS_BSD) # include #elif !defined(OS_WINDOWS) # include #endif #cmakedefine NEKO_BIG_ENDIAN #ifndef NEKO_BIG_ENDIAN # define NEKO_LITTLE_ENDIAN #endif #ifndef true # define true 1 # define false 0 typedef int bool; #endif #endif /* ************************************************************************ */ neko-2-2-0/libs/common/sha1.c000066400000000000000000000125041321613172000156640ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "osdef.h" #include "sha1.h" #include #include // original code by Steve Reid #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) #ifdef NEKO_BIG_ENDIAN # define blk0(i) block[i] #else # define blk0(i) (block[i] = (rol(block[i],24)&0xFF00FF00) \ |(rol(block[i],8)&0x00FF00FF)) #endif #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ ^block[(i+2)&15]^block[i&15],1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); static void sha1_transform( unsigned int state[5], unsigned char buffer[64] ) { unsigned int a, b, c, d, e; unsigned int block[16]; memcpy(block, buffer, 64); /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; } void sha1_init( SHA1_CTX *context ) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } void sha1_update( SHA1_CTX *context, const unsigned char *data, unsigned int len ) { unsigned int i, j; j = (context->count[0] >> 3) & 63; if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; context->count[1] += (len >> 29); if ((j + len) > 63) { memcpy(&context->buffer[j], data, (i = 64-j)); sha1_transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64 ) sha1_transform(context->state, (unsigned char *)&data[i]); j = 0; } else i = 0; memcpy(&context->buffer[j], &data[i], len - i); } void sha1_final( SHA1_CTX *context, unsigned char digest[SHA1_SIZE] ) { unsigned int i; unsigned char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ } sha1_update(context, (unsigned char *)"\200", 1); while ((context->count[0] & 504) != 448) { sha1_update(context, (unsigned char *)"\0", 1); } sha1_update(context, finalcount, 8); for (i = 0; i < SHA1_SIZE; i++) { digest[i] = (unsigned char) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } sha1_transform(context->state, context->buffer); } neko-2-2-0/libs/common/sha1.h000066400000000000000000000030511321613172000156660ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef SHA1_H #define SHA1_H #define SHA1_SIZE 20 typedef unsigned char SHA1_DIGEST[SHA1_SIZE]; typedef struct { unsigned int state[5]; unsigned int count[2]; unsigned char buffer[64]; } SHA1_CTX; void sha1_init( SHA1_CTX *c ); void sha1_update( SHA1_CTX *c, const unsigned char *data, unsigned int len ); void sha1_final( SHA1_CTX *c, SHA1_DIGEST digest ); #endif /* ************************************************************************ */ neko-2-2-0/libs/common/socket.c000066400000000000000000000121421321613172000163160ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "socket.h" #include #ifdef OS_WINDOWS static int init_done = 0; static WSADATA init_data; # define POSIX_LABEL(x) # define HANDLE_EINTR(x) #else # include # include # include # include # include # include # include # include # include # include # include # include # define closesocket close # define SOCKET_ERROR (-1) # define POSIX_LABEL(x) x: # define HANDLE_EINTR(x) if( errno == EINTR ) goto x #endif #if defined(OS_WINDOWS) || defined(OS_MAC) # define MSG_NOSIGNAL 0 #endif static int block_error() { #ifdef OS_WINDOWS int err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAEALREADY ) #else if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY ) #endif return PS_BLOCK; return PS_ERROR; } void psock_init() { #ifdef OS_WINDOWS if( !init_done ) { WSAStartup(MAKEWORD(2,0),&init_data); init_done = 1; } #endif } PSOCK psock_create() { PSOCK s = socket(AF_INET,SOCK_STREAM,0); # if defined(OS_MAC) || defined(OS_BSD) if( s != INVALID_SOCKET ) setsockopt(s,SOL_SOCKET,SO_NOSIGPIPE,NULL,0); # endif # ifdef OS_POSIX // we don't want sockets to be inherited in case of exec { int old = fcntl(s,F_GETFD,0); if( old >= 0 ) fcntl(s,F_SETFD,old|FD_CLOEXEC); } # endif return s; } void psock_close( PSOCK s ) { POSIX_LABEL(close_again); if( closesocket(s) ) { HANDLE_EINTR(close_again); } } int psock_send( PSOCK s, const char *buf, int size ) { int ret; POSIX_LABEL(send_again); ret = send(s,buf,size,MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return ret; } int psock_recv( PSOCK s, char *buf, int size ) { int ret; POSIX_LABEL(recv_again); ret = recv(s,buf,size,MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } return ret; } PHOST phost_resolve( const char *host ) { PHOST ip = inet_addr(host); if( ip == INADDR_NONE ) { struct hostent *h; # if defined(OS_WINDOWS) || defined(OS_MAC) || defined(OS_CYGWIN) h = gethostbyname(host); # else struct hostent hbase; char buf[1024]; int errcode; gethostbyname_r(host,&hbase,buf,1024,&h,&errcode); # endif if( h == NULL ) return UNRESOLVED_HOST; ip = *((unsigned int*)h->h_addr); } return ip; } SERR psock_connect( PSOCK s, PHOST host, int port ) { struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); *(int*)&addr.sin_addr.s_addr = host; if( connect(s,(struct sockaddr*)&addr,sizeof(addr)) != 0 ) return block_error(); return PS_OK; } SERR psock_set_timeout( PSOCK s, double t ) { #ifdef OS_WINDOWS int time = (int)(t * 1000); #else struct timeval time; time.tv_usec = (int)((t - (int)t)*1000000); time.tv_sec = (int)t; #endif if( setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) return PS_ERROR; if( setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) return PS_ERROR; return PS_OK; } SERR psock_set_blocking( PSOCK s, int block ) { #ifdef OS_WINDOWS { unsigned long arg = !block; if( ioctlsocket(s,FIONBIO,&arg) != 0 ) return PS_ERROR; } #else { int rights = fcntl(s,F_GETFL); if( rights == -1 ) return PS_ERROR; if( block ) rights &= ~O_NONBLOCK; else rights |= O_NONBLOCK; if( fcntl(s,F_SETFL,rights) == -1 ) return PS_ERROR; } #endif return PS_OK; } SERR psock_set_fastsend( PSOCK s, int fast ) { if( setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&fast,sizeof(fast)) ) return block_error(); return PS_OK; } void psock_wait( PSOCK s ) { # ifdef OS_WINDOWS fd_set set; FD_ZERO(&set); FD_SET(s,&set); select((int)s+1,&set,NULL,NULL,NULL); # else struct pollfd fds; POSIX_LABEL(poll_again); fds.fd = s; fds.events = POLLIN; fds.revents = 0; if( poll(&fds,1,-1) < 0 ) { HANDLE_EINTR(poll_again); } # endif } /* ************************************************************************ */ neko-2-2-0/libs/common/socket.h000066400000000000000000000036241321613172000163300ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef SOCKET_H #define SOCKET_H #include "osdef.h" #ifdef OS_WINDOWS # include typedef SOCKET PSOCK; #else typedef int PSOCK; # define INVALID_SOCKET (-1) #endif typedef unsigned int PHOST; #define UNRESOLVED_HOST ((PHOST)-1) typedef enum { PS_OK = 0, PS_ERROR = -1, PS_BLOCK = -2, } SERR; void psock_init(); PSOCK psock_create(); void psock_close( PSOCK s ); SERR psock_connect( PSOCK s, PHOST h, int port ); SERR psock_set_timeout( PSOCK s, double timeout ); SERR psock_set_blocking( PSOCK s, int block ); SERR psock_set_fastsend( PSOCK s, int fast ); int psock_send( PSOCK s, const char *buf, int size ); int psock_recv( PSOCK s, char *buf, int size ); PHOST phost_resolve( const char *hostname ); #endif /* ************************************************************************ */ neko-2-2-0/libs/mod_neko/000077500000000000000000000000001321613172000151655ustar00rootroot00000000000000neko-2-2-0/libs/mod_neko/CMakeLists.txt000066400000000000000000000013361321613172000177300ustar00rootroot00000000000000 ###################### # mod_neko2.ndll add_library(mod_neko2.ndll MODULE ../../vm/stats.c # FIXME mod_neko.c cgi.c ) target_include_directories(mod_neko2.ndll PRIVATE ${APACHE_INCLUDE_DIRS} ) target_link_libraries(mod_neko2.ndll libneko ${APACHE_LIBRARIES}) # In static Apache case build dependencies first if (STATIC_APACHE) add_dependencies(mod_neko2.ndll Apache APR APRutil) endif() set_target_properties(mod_neko2.ndll PROPERTIES PREFIX "" OUTPUT_NAME mod_neko2 SUFFIX .ndll ) if(APPLE) set_target_properties(mod_neko2.ndll PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ${LINK_FLAGS}" ) endif(APPLE) install ( TARGETS mod_neko2.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/mod_neko/cgi.c000066400000000000000000000357451321613172000161110ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "mod_neko.h" DEFINE_KIND(k_mod_neko); #ifndef NEKO_WINDOWS # define strcmpi strcasecmp #endif #ifdef APACHE_2_X # define ap_table_get apr_table_get # define ap_table_set apr_table_set # define ap_table_add apr_table_add # define ap_table_do apr_table_do # define REDIRECT HTTP_MOVED_TEMPORARILY #endif #define PARSE_HEADER(start,cursor) \ cursor = start; \ if( *cursor == '"' ) { \ start++; \ cursor++; \ while( *cursor != '"' && *cursor != 0 ) \ cursor++; \ } else { \ while( *cursor != 0 && *cursor != '\r' && *cursor != '\n' && *cursor != '\t' ) \ cursor++; \ } #define HEADERS_NOT_SENT(msg) \ if( c->headers_sent ) { \ buffer b = alloc_buffer("Cannot set "); \ buffer_append(b,msg); \ buffer_append(b," : Headers already sent"); \ bfailure(b); \ } /**

Mod_neko

Apache access when running inside mod_neko.

**/ /** get_cookies : void -> #list Return a cookie list as a (name,value) chained list **/ static value get_cookies() { const char *k = ap_table_get(CONTEXT()->r->headers_in,"Cookie"); char *start, *end; value p = val_null, tmp; if( k == NULL ) return p; while( (start = strchr(k,'=')) != NULL ) { start++; end = start; while( *end != 0 && *end != '\r' && *end != '\n' && *end != ';' ) end++; tmp = alloc_array(3); val_array_ptr(tmp)[0] = copy_string(k,(int)(start-k-1)); val_array_ptr(tmp)[1] = copy_string(start,(int)(end-start)); val_array_ptr(tmp)[2] = p; p = tmp; if( *end != ';' || end[1] != ' ' ) break; k = end + 2; } return p; } /** set_cookie : name:string -> val:string -> void Set a cookie **/ static value set_cookie( value name, value v ) { mcontext *c = CONTEXT(); buffer b; value str; val_check(name,string); val_check(v,string); HEADERS_NOT_SENT("Cookie"); b = alloc_buffer(NULL); val_buffer(b,name); buffer_append(b,"="); val_buffer(b,v); buffer_append(b,";"); str = buffer_to_string(b); ap_table_add(c->r->headers_out,"Set-Cookie",val_string(str)); return val_true; } /** get_host_name : void -> string Get the local host IP **/ static value get_host_name() { mcontext *c = CONTEXT(); return alloc_string( c->r->hostname ); } /** get_client_ip : void -> string Get the connected client IP **/ static value get_client_ip() { #if AP_SERVER_MAJORVERSION_NUMBER >= 2 && AP_SERVER_MINORVERSION_NUMBER >= 4 return alloc_string( CONTEXT()->r->useragent_ip ); #else return alloc_string( CONTEXT()->r->connection->remote_ip ); #endif } /** get_uri : void -> string Get the original URI requested by the client (before any internal redirection) **/ static value get_uri() { request_rec *r = CONTEXT()->r; while( r->prev != NULL ) r = r->prev; return alloc_string( r->uri ); } /** redirect : string -> void Redirect the client to another page (Location header) **/ static value redirect( value s ) { mcontext *c = CONTEXT(); val_check(s,string); HEADERS_NOT_SENT("Redirection"); ap_table_set(c->r->headers_out,"Location",val_string(s)); c->r->status = REDIRECT; return val_true; } /** set_return_code : int -> void Set the HTTP return code **/ static value set_return_code( value i ) { mcontext *c = CONTEXT(); val_check(i,int); HEADERS_NOT_SENT("Return code"); c->r->status = val_int(i); return val_true; } /** set_header : name:string -> val:string -> void Set a HTTP header value **/ static value set_header( value s, value k ) { mcontext *c = CONTEXT(); val_check(s,string); val_check(k,string); HEADERS_NOT_SENT("Header"); if( strcmpi(val_string(s),"Content-Type") == 0 ) { c->content_type = alloc_string(val_string(k)); c->r->content_type = val_string(c->content_type); } else ap_table_set(c->r->headers_out,val_string(s),val_string(k)); return val_true; } /** get_client_header : name:string -> string? Get a HTTP header sent by the client **/ static value get_client_header( value s ) { mcontext *c = CONTEXT(); val_check(s,string); return alloc_string( ap_table_get(c->r->headers_in,val_string(s)) ); } static int store_table( void *r, const char *key, const char *val ) { value a; if( key == NULL || val == NULL ) return 1; a = alloc_array(3); val_array_ptr(a)[0] = alloc_string(key); val_array_ptr(a)[1] = alloc_string(val); val_array_ptr(a)[2] = *(value*)r; *((value*)r) = a; return 1; } /** get_client_headers : void -> string list Get all the HTTP client headers **/ static value get_client_headers() { value r = val_null; ap_table_do(store_table,&r,CONTEXT()->r->headers_in,NULL); return r; } /** get_params_string : void -> string Return the whole parameters string **/ static value get_params_string() { return alloc_string(CONTEXT()->r->args); } /** get_post_data : void -> string Return the whole unparsed POST string **/ static value get_post_data() { return CONTEXT()->post_data; } static char *memfind( char *mem, int mlen, const char *v ) { char *found; int len = (int)strlen(v); if( len == 0 ) return mem; while( (found = memchr(mem,*v,mlen)) != NULL ) { if( (int)(found - mem) + len > mlen ) break; if( memcmp(found,v,len) == 0 ) return found; mlen -= (int)(found - mem + 1); mem = found + 1; } return NULL; } #define BUFSIZE 1024 static void fill_buffer( mcontext *c, value buf, int *len ) { int pos = *len; while( pos < BUFSIZE ) { int k = ap_get_client_block(c->r,val_string(buf)+pos,BUFSIZE-pos); if( k == 0 ) break; pos += k; } *len = pos; } static value discard_body( mcontext *c ) { char buf[256]; while( ap_get_client_block(c->r,buf,256) > 0 ) { } neko_error(); } /** parse_multipart_data : onpart:function:2 -> ondata:function:3 -> void Incrementally parse the multipart data. call [onpart(name,filename)] for each part found and [ondata(buf,pos,len)] when some data is available **/ static value parse_multipart_data( value onpart, value ondata ) { value buf; int len = 0; mcontext *c = CONTEXT(); const char *ctype = ap_table_get(c->r->headers_in,"Content-Type"); value boundstr; val_check_function(onpart,2); val_check_function(ondata,3); buf = alloc_empty_string(BUFSIZE); if( !ctype || strstr(ctype,"multipart/form-data") == NULL ) return val_null; // extract boundary value { const char *boundary, *bend; if( (boundary = strstr(ctype,"boundary=")) == NULL ) neko_error(); boundary += 9; PARSE_HEADER(boundary,bend); len = (int)(bend - boundary); boundstr = alloc_empty_string(len+2); if( val_strlen(boundstr) > BUFSIZE / 2 ) neko_error(); val_string(boundstr)[0] = '-'; val_string(boundstr)[1] = '-'; memcpy(val_string(boundstr)+2,boundary,len); } len = 0; if( !ap_should_client_block(c->r) ) neko_error(); while( true ) { char *name, *end_name, *filename, *end_file_name, *data; int pos; // refill buffer // we assume here that the the whole multipart header can fit in the buffer fill_buffer(c,buf,&len); // is boundary at the beginning of buffer ? if( len < val_strlen(boundstr) || memcmp(val_string(buf),val_string(boundstr),val_strlen(boundstr)) != 0 ) return discard_body(c); name = memfind(val_string(buf),len,"Content-Disposition:"); if( name == NULL ) break; name = memfind(name,len - (int)(name - val_string(buf)),"name="); if( name == NULL ) return discard_body(c); name += 5; PARSE_HEADER(name,end_name); data = memfind(end_name,len - (int)(end_name - val_string(buf)),"\r\n\r\n"); if( data == NULL ) return discard_body(c); filename = memfind(name,(int)(data - name),"filename="); if( filename != NULL ) { filename += 9; PARSE_HEADER(filename,end_file_name); } data += 4; pos = (int)(data - val_string(buf)); // send part name val_call2(onpart,copy_string(name,(int)(end_name - name)),filename?copy_string(filename,(int)(end_file_name - filename)):val_null); // read data while( true ) { const char *boundary; // recall buffer memmove(val_string(buf),val_string(buf)+pos,len - pos); len -= pos; pos = 0; fill_buffer(c,buf,&len); // lookup bounds boundary = memfind(val_string(buf),len,val_string(boundstr)); if( boundary == NULL ) { if( len == 0 ) return discard_body(c); // send as much buffer as possible to client if( len < BUFSIZE ) pos = len; else pos = len - val_strlen(boundstr) + 1; val_call3(ondata,buf,alloc_int(0),alloc_int(pos)); } else { // send remaining data pos = (int)(boundary - val_string(buf)); val_call3(ondata,buf,alloc_int(0),alloc_int(pos-2)); // recall memmove(val_string(buf),val_string(buf)+pos,len - pos); len -= pos; break; } } } return val_null; } static value url_decode( const char *in, int len ) { int pin = 0; int pout = 0; value v = alloc_empty_string(len); char *out = (char*)val_string(v); while( len-- > 0 ) { char c = in[pin++]; if( c == '+' ) c = ' '; else if( c == '%' ) { int p1, p2; if( len < 2 ) break; p1 = in[pin++]; p2 = in[pin++]; len -= 2; if( p1 >= '0' && p1 <= '9' ) p1 -= '0'; else if( p1 >= 'a' && p1 <= 'f' ) p1 -= 'a' - 10; else if( p1 >= 'A' && p1 <= 'F' ) p1 -= 'A' - 10; else continue; if( p2 >= '0' && p2 <= '9' ) p2 -= '0'; else if( p2 >= 'a' && p2 <= 'f' ) p2 -= 'a' - 10; else if( p2 >= 'A' && p2 <= 'F' ) p2 -= 'A' - 10; else continue; c = (char)((unsigned char)((p1 << 4) + p2)); } out[pout++] = c; } out[pout] = 0; val_set_size(v,pout); return v; } static void parse_get( value *p, const char *args ) { char *aand, *aeq, *asep; value tmp; while( true ) { aand = strchr(args,'&'); if( aand == NULL ) { asep = strchr(args,';'); aand = asep; } else { asep = strchr(args,';'); if( asep != NULL && asep < aand ) aand = asep; } if( aand != NULL ) *aand = 0; aeq = strchr(args,'='); if( aeq != NULL ) { *aeq = 0; tmp = alloc_array(3); val_array_ptr(tmp)[0] = url_decode(args,(int)(aeq-args)); val_array_ptr(tmp)[1] = url_decode(aeq+1,(int)strlen(aeq+1)); val_array_ptr(tmp)[2] = *p; *p = tmp; *aeq = '='; } if( aand == NULL ) break; *aand = (aand == asep)?';':'&'; args = aand+1; } } /** get_params : void -> #list parse all GET and POST params and return them into a chained list **/ static value get_params() { mcontext *c = CONTEXT(); const char *args = c->r->args; value p = val_null; // PARSE "GET" PARAMS if( args != NULL ) parse_get(&p,args); // PARSE "POST" PARAMS if( c->post_data != NULL ) { const char *ctype = ap_table_get(c->r->headers_in,"Content-Type"); if( ctype == NULL || strstr(ctype,"urlencoded") != NULL ) parse_get(&p,val_string(c->post_data)); } return p; } /** cgi_get_cwd : void -> string Return current bytecode file working directory **/ static value cgi_get_cwd() { mcontext *c = CONTEXT(); char *s = strrchr(c->r->filename,'/'); value v; char old; if( s != NULL ) { old = s[1]; s[1] = 0; } v = alloc_string(c->r->filename); if( s != NULL ) s[1] = old; return v; } /** cgi_set_main : function:0? -> void Set or disable the main entry point function **/ static value cgi_set_main( value f ) { if( val_is_null(f) ) { CONTEXT()->main = NULL; return val_true; } val_check_function(f,0); CONTEXT()->main = f; return val_true; } /** cgi_flush : void -> void Flush the data written so it's immediatly sent to the client **/ static value cgi_flush() { ap_rflush(CONTEXT()->r); return val_null; } /** cgi_get_config : void -> object Return the current configuration **/ #define FSET(name,t) alloc_field(v,val_id(#name),alloc_##t(c-> name)) static value cgi_get_config() { value v = alloc_object(NULL); mconfig *c = mod_neko_get_config(); FSET(hits,int); FSET(use_jit,bool); FSET(use_stats,bool); FSET(use_prim_stats,bool); FSET(use_cache,bool); FSET(exceptions,int); FSET(gc_period,int); FSET(max_post_size,int); return v; } /** cgi_set_config : object -> void Set the current configuration **/ #define FGET(name,t) f = val_field(v,val_id(#name)); val_check(f,t); c. name = val_##t(f) static value cgi_set_config( value v ) { mconfig c; value f; val_check(v,object); FGET(hits,int); FGET(use_jit,bool); FGET(use_stats,bool); FGET(use_prim_stats,bool); FGET(use_cache,bool); FGET(exceptions,int); FGET(gc_period,int); FGET(max_post_size,int); mod_neko_set_config(&c); return val_null; } /** cgi_command : any -> any Perform a configuration-specific command :
  • stats : returns the statistics
  • cache : returns the current cache
**/ extern value cgi_command( value v ); /** get_http_method : void -> string Returns the http method (GET,POST...) used by the client **/ static value get_http_method() { return alloc_string(CONTEXT()->r->method); } /** log_message : string -> void Write the message into the apache log **/ static value log_message( value message ) { mcontext *c = CONTEXT(); val_check(message, string); #ifdef APACHE_2_X ap_log_rerror(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, c->r, "[mod_neko] %s", val_string(message)); #else ap_log_rerror(APLOG_MARK, APLOG_NOTICE, c->r, "[mod_neko] %s", val_string(message)); #endif return val_null; } DEFINE_PRIM(cgi_get_cwd,0); DEFINE_PRIM(cgi_set_main,1); DEFINE_PRIM(get_cookies,0); DEFINE_PRIM(set_cookie,2); DEFINE_PRIM(get_host_name,0); DEFINE_PRIM(get_client_ip,0); DEFINE_PRIM(get_uri,0); DEFINE_PRIM(redirect,1); DEFINE_PRIM(get_params,0); DEFINE_PRIM(get_params_string,0); DEFINE_PRIM(get_post_data,0); DEFINE_PRIM(set_header,2); DEFINE_PRIM(set_return_code,1); DEFINE_PRIM(get_client_header,1); DEFINE_PRIM(get_client_headers,0); DEFINE_PRIM(parse_multipart_data,2); DEFINE_PRIM(cgi_flush,0); DEFINE_PRIM(cgi_get_config,0); DEFINE_PRIM(cgi_set_config,1); DEFINE_PRIM(cgi_command,1); DEFINE_PRIM(get_http_method,0); DEFINE_PRIM(log_message,1); /* ************************************************************************ */ neko-2-2-0/libs/mod_neko/mod_neko.c000066400000000000000000000317401321613172000171310ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "mod_neko.h" #include #include #include #ifndef MOD_NEKO_POST_SIZE # define MOD_NEKO_POST_SIZE (1 << 18) // 256 K #endif #ifdef APACHE_2_X # define FTIME(r) r->finfo.mtime # define ap_send_http_header(x) # define ap_soft_timeout(msg,r) # define ap_kill_timeout(r) # define ap_table_get apr_table_get # define LOG_SUCCESS APR_SUCCESS, typedef apr_time_t aptime; #else # define FTIME(r) r->finfo.st_mtime # define LOG_SUCCESS typedef time_t aptime; #endif #define apache_error(level,request,message) \ ap_rprintf(request,"Error : %s",message); \ ap_log_rerror(APLOG_MARK, level, LOG_SUCCESS request, "[mod_neko error] %s", message) typedef struct cache { value file; value main; int hits; aptime time; struct cache *next; } cache; static mconfig config; static int init_done = 0; static mt_local *cache_root = NULL; extern void neko_stats_measure( neko_vm *vm, const char *kind, int start ); extern value neko_stats_build( neko_vm *vm ); value cgi_command( value v ) { val_check(v,string); if( strcmp(val_string(v),"stats") == 0 ) return neko_stats_build(neko_vm_current()); if( strcmp(val_string(v),"cache") == 0 ) { cache *c = (cache*)local_get(cache_root); value l = val_null; while( c != NULL ) { value a = alloc_array(4); val_array_ptr(a)[0] = c->file; val_array_ptr(a)[1] = c->main; val_array_ptr(a)[2] = alloc_int(c->hits); val_array_ptr(a)[3] = l; l = a; c = c->next; } return l; } neko_error(); } mconfig *mod_neko_get_config() { return &config; } void mod_neko_set_config( mconfig *c ) { config = *c; } static void gc_major() { if( config.gc_period <= 0 || config.hits % config.gc_period != 0 ) return; if( config.use_stats ) neko_stats_measure(NULL,"gc",1); neko_gc_major(); if( config.use_stats ) neko_stats_measure(NULL,"gc",0); } static void send_headers( mcontext *c ) { if( !c->headers_sent ) { ap_send_http_header(c->r); c->headers_sent = true; } } static void request_print( const char *data, int size, void *_c ) { mcontext *c = (mcontext *)_c; if( c == NULL ) c = CONTEXT(); if( size == -1 ) size = (int)strlen(data); ap_soft_timeout("Client Timeout",c->r); send_headers(c); ap_rwrite(data,size,c->r); ap_kill_timeout(c->r); } static void null_print( const char *data, int size, void *_c ) { } static value cache_find( request_rec *r ) { cache *c = (cache*)local_get(cache_root); cache *prev = NULL; value fname = alloc_string(r->filename); while( c != NULL ) { if( val_compare(fname,c->file) == 0 ) { if( config.use_cache && FTIME(r) == c->time ) { c->hits++; return c->main; } if( prev == NULL ) local_set(cache_root,c->next); else prev->next = c->next; free_root((value*)c); // try to lower memory partitioning // when a module is updated c = NULL; gc_major(); break; } prev = c; c = c->next; } return NULL; } static char *request_base_uri( request_rec *r ) { while( r->prev != NULL ) r = r->prev; return r->unparsed_uri; } static void cache_module( const char *filename, aptime time, value main ) { cache *c = (cache*)local_get(cache_root), *prev = NULL; value fname = alloc_string(filename); while( c != NULL ) { if( val_compare(fname,c->file) == 0 ) { if( main == NULL ) { if( prev == NULL ) local_set(cache_root,c->next); else prev->next = c->next; free_root((value*)c); } else { c->main = main; c->time = time; } return; } prev = c; c = c->next; } c = (cache*)alloc_root(sizeof(struct cache) / sizeof(value)); c->file = fname; c->main = main; c->time = time; c->hits = 0; c->next = (cache*)local_get(cache_root); local_set(cache_root,c); } static int neko_handler_rec( request_rec *r ) { mcontext ctx; neko_vm *vm; const char *ctype; value exc = NULL; /* Seems to crash on Windows. And on Linux, we rarely have libGC 7.x installed anyway # if defined(APACHE_2_X) || defined(NEKO_WINDOWS) // we are using threads, so let's make sure that the current thread is registered neko_thread_register(true); # endif */ config.hits++; ctx.r = r; ctx.main = cache_find(r); ctx.post_data = val_null; ctx.headers_sent = false; ctx.content_type = alloc_string("text/html"); r->content_type = val_string(ctx.content_type); if( ap_setup_client_block(r,REQUEST_CHUNKED_ERROR) != 0 ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"ap_setup_client_block failed"); return OK; } ctype = ap_table_get(r->headers_in,"Content-Type"); if( (!ctype || strstr(ctype,"multipart/form-data") == NULL) && ap_should_client_block(r) ) { # define MAXLEN 1024 char buf[MAXLEN]; int len; int tlen = 0; buffer b = alloc_buffer(NULL); while( (len = ap_get_client_block(r,buf,MAXLEN)) > 0 ) { if( tlen < config.max_post_size ) buffer_append_sub(b,buf,len); tlen += len; } if( tlen >= config.max_post_size ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"Maximum POST data exceeded. Try using multipart encoding"); return OK; } ctx.post_data = buffer_to_string(b); } vm = neko_vm_alloc(NULL); if( config.use_stats ) neko_vm_set_stats(vm,neko_stats_measure,config.use_prim_stats?neko_stats_measure:NULL); neko_vm_set_custom(vm,k_mod_neko,&ctx); if( config.use_jit && !neko_vm_jit(vm,1) ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"JIT required by env. var but not enabled in NekoVM"); return OK; } neko_vm_redirect(vm,request_print,&ctx); neko_vm_select(vm); if( ctx.main != NULL ) { value old = ctx.main; if( config.use_stats ) neko_stats_measure(vm,r->filename,1); val_callEx(val_null,old,NULL,0,&exc); if( config.use_stats ) neko_stats_measure(vm,r->filename,0); if( old != ctx.main ) cache_module(r->filename,FTIME(r),ctx.main); } else { char *base_uri = request_base_uri(r); value mload = neko_default_loader(&base_uri,1); value args[] = { alloc_string(r->filename), mload }; char *p = strrchr(val_string(args[0]),'.'); if( p != NULL ) *p = 0; val_callEx(mload,val_field(mload,val_id("loadmodule")),args,2,&exc); if( ctx.main != NULL && config.use_cache ) cache_module(r->filename,FTIME(r),ctx.main); } if( exc != NULL ) { buffer b = alloc_buffer(NULL); value v; int i; const char *p, *start; value st = neko_exc_stack(vm); val_buffer(b,exc); config.exceptions++; ap_soft_timeout("Client Timeout",r); send_headers(&ctx); v = buffer_to_string(b); p = val_string(v); start = p; ap_rprintf(r,"Uncaught exception - "); while( *p ) { if( *p == '<' || *p == '>' ) { ap_rwrite(start,(int)(p - start),r); ap_rwrite((*p == '<')?"<":">",4, r); start = p + 1; } p++; } ap_rwrite(start,(int)(p - start),r); ap_rprintf(r,"

"); for(i=0;i"); else if( val_is_string(s) ) { ap_rprintf(r,"Called from %s (no debug available)
",val_string(s)); } else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) ap_rprintf(r,"Called from %s line %d
",val_string(val_array_ptr(s)[0]),val_int(val_array_ptr(s)[1])); else { b = alloc_buffer(NULL); val_buffer(b,s); ap_rprintf(r,"Called from %s
",val_string(buffer_to_string(b))); } } ap_kill_timeout(r); return OK; } send_headers(&ctx); return OK; } static int neko_handler( request_rec *r ) { int ret; if( strcmp(r->handler,"neko-handler") != 0) return DECLINED; if( config.use_stats ) neko_stats_measure(NULL,r->hostname,1); ret = neko_handler_rec(r); neko_vm_select(NULL); if( config.use_stats ) neko_stats_measure(NULL,r->hostname,0); gc_major(); return ret; } static void mod_neko_do_init() { int tmp = 0; if( init_done ) return; init_done = 1; memset(&config,0,sizeof(config)); config.use_cache = 1; config.gc_period = 1; config.max_post_size = MOD_NEKO_POST_SIZE; # ifdef APACHE_2_X putenv(strdup("MOD_NEKO=2")); # else putenv(strdup("MOD_NEKO=1")); # endif neko_global_init(); cache_root = alloc_local(); } static value init_module() { neko_vm *vm = neko_vm_current(); mcontext *ctx = CONTEXT(); value env = vm->env; ctx->main = NULL; val_call1(val_array_ptr(env)[0],val_array_ptr(env)[1]); cache_module(ctx->r->filename,FTIME(ctx->r),ctx->main); return val_null; } static void preload_module( const char *name, server_rec *serv ) { value exc = NULL; neko_vm *vm = neko_vm_alloc(NULL); value mload = neko_default_loader(NULL,0); value m, read_path, exec; time_t time = 0; neko_vm_select(vm); if( config.use_jit ) neko_vm_jit(vm,1); if( !exc ) { value args[] = { alloc_string("std@module_read_path"), alloc_int(3) }; read_path = val_callEx(mload,val_field(mload,val_id("loadprim")),args,2,&exc); } if( !exc ) { value args[] = { alloc_string("std@module_exec"), alloc_int(1) }; exec = val_callEx(mload,val_field(mload,val_id("loadprim")),args,2,&exc); } if( !exc ) { value args[] = { val_null, alloc_string(name), mload }; char *p = strrchr(val_string(args[1]),'.'); if( p != NULL ) *p = 0; m = val_callEx(mload,read_path,args,3,&exc); } if( !exc ) { struct stat t; if( stat(name,&t) ) exc = alloc_string("failed to stat()"); else time = t.st_mtime; } if( !exc ) { value f = alloc_function(init_module,0,"init_module"); value env = alloc_array(2); val_array_ptr(env)[0] = exec; val_array_ptr(env)[1] = m; ((vfunction*)f)->env = env; cache_module(name,time,f); } if( exc ) { buffer b = alloc_buffer(NULL); val_buffer(b,exc); ap_log_error(APLOG_MARK,APLOG_WARNING,LOG_SUCCESS serv,"Failed to preload module '%s' : %s",name,val_string(buffer_to_string(b))); } neko_vm_select(NULL); } #ifdef APACHE_2_X # define MCONFIG void* #else # define MCONFIG char* #endif static const char *mod_neko_config( cmd_parms *cmd, MCONFIG mconfig, const char *fargs ) { char *code = strdup(fargs); char *args = code; int value; while( true ) { char c = *args; if( c == 0 || c == ' ' || c == '\t' ) break; args++; } while( *args == ' ' || *args == '\t' ) *args++ = 0; value = atoi(args); mod_neko_do_init(); if( strcmp(code,"JIT") == 0 ) config.use_jit = value; else if( strcmp(code,"CACHE") == 0 ) config.use_cache = value; else if( strcmp(code,"GC_PERIOD") == 0 ) config.gc_period = value; else if( strcmp(code,"POST_SIZE") == 0 ) config.max_post_size = value; else if( strcmp(code,"STATS") == 0 ) config.use_stats = value; else if( strcmp(code,"PRIM_STATS") == 0 ) config.use_prim_stats = value; else if( strcmp(code,"PRELOAD") == 0 ) preload_module(args,cmd->server); else ap_log_error(APLOG_MARK,APLOG_WARNING,LOG_SUCCESS cmd->server,"Unknown ModNeko configuration command '%s'",code); free(code); return NULL; } #ifdef APACHE_2_X static int neko_init( apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s ) { mod_neko_do_init(); return OK; } #else static void neko_init(server_rec *s, pool *p) { mod_neko_do_init(); } #endif static command_rec neko_module_cmds[] = { # ifdef APACHE_2_X AP_INIT_RAW_ARGS( "ModNeko", mod_neko_config , NULL, RSRC_CONF, NULL ), # else { "ModNeko", mod_neko_config, NULL, RSRC_CONF, RAW_ARGS, NULL }, # endif { NULL } }; #ifdef APACHE_2_X static void neko_register_hooks( apr_pool_t *p ) { ap_hook_post_config( neko_init, NULL, NULL, APR_HOOK_MIDDLE ); ap_hook_handler( neko_handler, NULL, NULL, APR_HOOK_LAST ); }; module AP_MODULE_DECLARE_DATA neko_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, neko_module_cmds, neko_register_hooks }; #else /* APACHE 1.3 */ static const handler_rec neko_handlers[] = { {"neko-handler", neko_handler}, {NULL} }; module MODULE_VAR_EXPORT neko_module = { STANDARD_MODULE_STUFF, neko_init, NULL, NULL, NULL, NULL, neko_module_cmds, neko_handlers, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #endif /* ************************************************************************ */ neko-2-2-0/libs/mod_neko/mod_neko.h000066400000000000000000000041221321613172000171300ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef MODNEKO_H #define MODNEKO_H #include #include #include #include #include #include #undef NOERROR #undef INLINE #include #ifndef NEKO_WINDOWS # include #endif typedef struct { request_rec *r; value main; value post_data; value content_type; bool headers_sent; } mcontext; typedef struct { int hits; int use_jit; int use_stats; int use_prim_stats; int use_cache; int exceptions; int gc_period; int max_post_size; } mconfig; #define CONTEXT() ((mcontext*)neko_vm_custom(neko_vm_current(),k_mod_neko)) DECLARE_KIND(k_mod_neko) #ifdef STANDARD20_MODULE_STUFF # define APACHE_2_X # define REMOTE_ADDR(c) c->remote_addr->sa.sin.sin_addr #else # define REMOTE_ADDR(c) c->remote_addr.sin_addr #endif extern mconfig *mod_neko_get_config(); extern void mod_neko_set_config( mconfig *cfg ); #endif /* ************************************************************************ */ neko-2-2-0/libs/mod_tora/000077500000000000000000000000001321613172000151765ustar00rootroot00000000000000neko-2-2-0/libs/mod_tora/CMakeLists.txt000066400000000000000000000013411321613172000177350ustar00rootroot00000000000000 ###################### # mod_tora2.ndll add_library(mod_tora2.ndll MODULE protocol.c mod_tora.c ) add_dependencies(mod_tora2.ndll mod_neko2.ndll socket ) target_include_directories(mod_tora2.ndll PRIVATE ${APACHE_INCLUDE_DIRS} ) target_link_libraries(mod_tora2.ndll socket ${APACHE_LIBRARIES} ) if (WIN32) target_link_libraries(mod_tora2.ndll ws2_32) endif() set_target_properties(mod_tora2.ndll PROPERTIES PREFIX "" OUTPUT_NAME mod_tora2 SUFFIX .ndll ) ####################### if(APPLE) set_target_properties(mod_tora2.ndll PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ${LINK_FLAGS}" ) endif(APPLE) install ( TARGETS mod_tora2.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/mod_tora/mod_tora.c000066400000000000000000000245011321613172000171500ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "protocol.h" #ifndef OS_WINDOWS # include # define strcmpi strcasecmp #endif #define send_headers(c) \ if( !c->headers_sent ) { \ ap_send_http_header(c->r); \ c->headers_sent = 1; \ } #ifdef STANDARD20_MODULE_STUFF # define APACHE_2_X # define ap_send_http_header(x) # define ap_soft_timeout(msg,r) # define ap_kill_timeout(r) # define ap_table_get apr_table_get # define ap_table_set apr_table_set # define ap_table_add apr_table_add # define ap_table_do apr_table_do # define ap_palloc apr_palloc # define LOG_SUCCESS APR_SUCCESS, # define REDIRECT HTTP_MOVED_TEMPORARILY # define REMOTE_ADDR(c) c->remote_addr->sa.sin.sin_addr #else # define LOG_SUCCESS # define REMOTE_ADDR(c) c->remote_addr.sin_addr #endif #if AP_SERVER_MAJORVERSION_NUMBER >= 2 && AP_SERVER_MINORVERSION_NUMBER >= 4 # define REMOTE_IP(r) r->useragent_ip #else # define REMOTE_IP(r) r->connection->remote_ip #endif #define DEFAULT_HOST "127.0.0.1" #define DEFAULT_PORT 6666 #define DEFAULT_MAX_POST_DATA (1 << 18) // 256 K typedef struct { char *host; int port_min; int port_max; int max_post_size; int hits; bool proxy_mode; } mconfig; typedef struct { request_rec *r; proto *p; char *post_data; char *xff; char *client_ip; int post_data_size; bool headers_sent; bool is_multipart; bool is_form_post; bool need_discard; } mcontext; static mconfig config; static bool init_done = false; static int get_client_header( void *_c, const char *key, const char *val ) { mcontext *c = (mcontext*)_c; if( key == NULL || val == NULL ) return 1; if( config.proxy_mode && strcmpi(key,"X-Forwarded-For") == 0 ) protocol_send_header(c->p,key,c->xff); else protocol_send_header(c->p,key,val); return 1; } static void do_get_headers( void *_c ) { mcontext *c = (mcontext*)_c; ap_table_do(get_client_header,c,c->r->headers_in,NULL); } static void do_get_params( void *_c ) { mcontext *c = (mcontext*)_c; if( c->r->args ) protocol_send_raw_params(c->p,c->r->args); if( c->post_data && c->is_form_post ) protocol_send_raw_params(c->p,c->post_data); } static int do_print( void *_c, const char *buf, int len ) { mcontext *c = (mcontext*)_c; ap_soft_timeout("Client Timeout",c->r); send_headers(c); ap_rwrite(buf,len,c->r); ap_kill_timeout(c->r); return c->r->connection->aborted == 0; } static void do_flush( void *_c ) { mcontext *c = (mcontext*)_c; ap_rflush(c->r); } static void do_set_header( void *_c, const char *key, const char *value, bool add ) { mcontext *c = (mcontext*)_c; if( add ) ap_table_add(c->r->headers_out,key,value); else if( strcmpi(key,"Content-Type") == 0 ) { int len = (int)strlen(value); char *ct = (char*)ap_palloc(c->r->pool,len+1); memcpy(ct,value,len+1); c->r->content_type = ct; } else ap_table_set(c->r->headers_out,key,value); } static void do_set_return_code( void *_c, int code ) { mcontext *c = (mcontext*)_c; c->r->status = code; } static void do_log( void *_c, const char *msg, bool user_log ) { mcontext *c = (mcontext*)_c; if( user_log ) { c->r->content_type = "text/plain"; do_print(c,"Error : ",8); do_print(c,msg,(int)strlen(msg)); } else ap_log_rerror(APLOG_MARK, APLOG_WARNING, LOG_SUCCESS c->r, "[mod_tora] %s", msg); } static void log_error( mcontext *c, const char *msg ) { do_log(c,msg,false); // add to apache log do_log(c,msg,true); // display to user } static int do_stream_data( void *_c, char *buf, int size ) { mcontext *c = (mcontext*)_c; // startup if( size == 0 ) { if( !ap_should_client_block(c->r) ) return -1; c->need_discard = true; return 0; } return ap_get_client_block(c->r,buf,size); } static void discard_body( mcontext *c ) { char buf[1024]; while( ap_get_client_block(c->r,buf,1024) > 0 ) { } } static int tora_handler( request_rec *r ) { mcontext ctx, *c = &ctx; if( strcmp(r->handler,"tora-handler") != 0) return DECLINED; // init context c->need_discard = false; c->is_multipart = false; c->headers_sent = false; c->is_form_post = false; c->r = r; c->post_data = NULL; c->xff = NULL; c->client_ip = NULL; c->p = NULL; c->r->content_type = "text/html"; config.hits++; // read post data { const char *ctype = ap_table_get(r->headers_in,"Content-Type"); ap_setup_client_block(r,REQUEST_CHUNKED_ERROR); if( ctype && strstr(ctype,"multipart/form-data") ) c->is_multipart = true; else if( ap_should_client_block(r) ) { int tlen = 0; c->post_data = (char*)malloc(config.max_post_size); while( true ) { int len = ap_get_client_block(r,c->post_data + tlen,config.max_post_size - tlen); if( len <= 0 ) break; tlen += len; } if( tlen >= config.max_post_size ) { discard_body(c); free(c->post_data); log_error(c,"Maximum POST data exceeded. Try using multipart encoding"); return OK; } c->post_data[tlen] = 0; c->post_data_size = tlen; c->is_form_post = ctype == NULL || (strstr(ctype,"urlencoded") != NULL); } } // init protocol { protocol_infos infos; request_rec *first = r; while( first->prev != NULL ) first = first->prev; infos.custom = c; infos.script = r->filename; infos.uri = first->uri; infos.hostname = r->hostname ? r->hostname : ""; if( config.proxy_mode ) { const char *xff = ap_table_get(r->headers_in,"X-Forwarded-For"); if( xff == NULL ) infos.client_ip = REMOTE_IP(r); else { char tmp; char *xend = (char*)xff + strlen(xff) - 1; while( xend > xff && *xend != ' ' && *xend != ',' ) xend--; c->client_ip = strdup(xend); infos.client_ip = c->client_ip; if( xend > xff && *xend == ' ' && xend[-1] == ',' ) xend--; tmp = *xend; *xend = 0; c->xff = strdup(xff); *xend = tmp; } } else infos.client_ip = REMOTE_IP(r); infos.http_method = r->method; infos.get_data = r->args; infos.post_data = c->post_data; infos.post_data_size = c->post_data_size; infos.content_type = ap_table_get(r->headers_in,"Content-Type"); infos.do_get_headers = do_get_headers; infos.do_get_params = do_get_params; infos.do_set_header = do_set_header; infos.do_set_return_code = do_set_return_code; infos.do_print = do_print; infos.do_flush = do_flush; infos.do_log = do_log; infos.do_stream_data = c->is_multipart ? do_stream_data : NULL; c->p = protocol_init(&infos); } // run protocol { int port = config.port_min + (config.hits % (1 + config.port_max - config.port_min)); if( !protocol_connect(c->p,config.host,port) || !protocol_send_request(c->p) || !protocol_read_answer(c->p) ) log_error(c,protocol_get_error(c->p)); } // cleanup protocol_free(c->p); free(c->xff); free(c->client_ip); free(c->post_data); send_headers(c); // in case... if( c->need_discard ) discard_body(c); return OK; } static void mod_tora_do_init() { int tmp = 0; if( init_done ) return; init_done = true; memset(&config,0,sizeof(config)); config.host = DEFAULT_HOST; config.port_min = DEFAULT_PORT; config.port_max = DEFAULT_PORT; config.max_post_size = DEFAULT_MAX_POST_DATA; } #ifdef APACHE_2_X # define MCONFIG void* #else # define MCONFIG char* #endif static const char *mod_tora_config( cmd_parms *cmd, MCONFIG mconfig, const char *fargs ) { char *code = strdup(fargs); char *args = code; int value; while( true ) { char c = *args; if( c == 0 || c == ' ' || c == '\t' ) break; args++; } while( *args == ' ' || *args == '\t' ) *args++ = 0; value = atoi(args); mod_tora_do_init(); if( strcmp(code,"HOST") == 0 ) config.host = strdup(args); else if( strcmp(code,"PORT") == 0 ) { config.port_min = value; config.port_max = value; } else if( strcmp(code,"PORT_MAX") == 0 ) config.port_max = value; else if( strcmp(code,"POST_SIZE") == 0 ) config.max_post_size = value; else if( strcmp(code,"PROXY_MODE") == 0 ) config.proxy_mode = value; else ap_log_error(APLOG_MARK,APLOG_WARNING,LOG_SUCCESS cmd->server,"Unknown ModTora configuration command '%s'",code); free(code); return NULL; } #ifdef APACHE_2_X static int tora_init( apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s ) { mod_tora_do_init(); return OK; } #else static void tora_init(server_rec *s, pool *p) { mod_tora_do_init(); } #endif static command_rec tora_module_cmds[] = { # ifdef APACHE_2_X AP_INIT_RAW_ARGS( "ModTora", mod_tora_config , NULL, RSRC_CONF, NULL ), # else { "ModTora", mod_tora_config, NULL, RSRC_CONF, RAW_ARGS, NULL }, # endif { NULL } }; #ifdef APACHE_2_X static void tora_register_hooks( apr_pool_t *p ) { ap_hook_post_config( tora_init, NULL, NULL, APR_HOOK_MIDDLE ); ap_hook_handler( tora_handler, NULL, NULL, APR_HOOK_LAST ); }; module AP_MODULE_DECLARE_DATA tora_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, tora_module_cmds, tora_register_hooks }; #else /* APACHE 1.3 */ static const handler_rec tora_handlers[] = { {"tora-handler", tora_handler}, {NULL} }; module MODULE_VAR_EXPORT tora_module = { STANDARD_MODULE_STUFF, tora_init, NULL, NULL, NULL, NULL, tora_module_cmds, tora_handlers, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #endif /* ************************************************************************ */ neko-2-2-0/libs/mod_tora/protocol.c000066400000000000000000000275021321613172000172110ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "protocol.h" #include "socket.h" struct _protocol { PSOCK s; bool error; char *error_msg; protocol_infos inf; }; typedef enum { CODE_FILE = 1, CODE_URI, CODE_CLIENT_IP, CODE_GET_PARAMS, CODE_POST_DATA, CODE_HEADER_KEY, CODE_HEADER_VALUE, CODE_HEADER_ADD_VALUE, CODE_PARAM_KEY, CODE_PARAM_VALUE, CODE_HOST_NAME, CODE_HTTP_METHOD, CODE_EXECUTE, CODE_ERROR, CODE_PRINT, CODE_LOG, CODE_FLUSH, CODE_REDIRECT, CODE_RETURNCODE, CODE_QUERY_MULTIPART, CODE_PART_FILENAME, CODE_PART_KEY, CODE_PART_DATA, CODE_PART_DONE, CODE_TEST_CONNECT, CODE_LISTEN, } proto_code; #define PARSE_HEADER(start,cursor) \ cursor = start; \ if( *cursor == '"' ) { \ start++; \ cursor++; \ while( *cursor != '"' && *cursor != 0 ) \ cursor++; \ } else { \ while( *cursor != 0 && *cursor != '\r' && *cursor != '\n' && *cursor != '\t' ) \ cursor++; \ } static bool proto_error( proto *p, const char *error ) { free(p->error_msg); p->error_msg = strdup(error); p->error = true; return false; } proto *protocol_init( protocol_infos *inf ) { proto *p = (proto*)malloc(sizeof(struct _protocol)); p->s = INVALID_SOCKET; p->inf = *inf; p->error = false; p->error_msg = NULL; psock_init(); return p; } bool protocol_connect( proto *p, const char *host, int port ) { PHOST h = phost_resolve(host); if( h == UNRESOLVED_HOST ) return proto_error(p,"Failed to resolve host"); p->s = psock_create(); if( p->s == INVALID_SOCKET ) return proto_error(p,"Failed to create socket"); if( psock_connect(p->s,h,port) != PS_OK ) return proto_error(p,"Failed to connect to TORA host"); return true; } const char *protocol_get_error( proto *p ) { return p->error_msg ? p->error_msg : "NO ERROR"; } void protocol_free( proto *p ) { psock_close(p->s); free(p->error_msg); free(p); } static void proto_write( proto *p, const char *str, int len ) { while( len ) { int b = psock_send(p->s,str,len); if( b <= 0 ) { p->error = true; return; } len -= b; str += b; } } static bool proto_read( proto *p, char *str, int len ) { while( len ) { int b = psock_recv(p->s,str,len); if( b <= 0 ) { p->error = true; return false; } len -= b; str += b; } return true; } static void proto_send_size( proto *p, proto_code code, const char *str, int len ) { unsigned char h[4]; h[0] = (unsigned char)code; h[1] = (unsigned char)len; h[2] = (unsigned char)(len >> 8); h[3] = (unsigned char)(len >> 16); proto_write(p,(char*)h,4); proto_write(p,str,len); } static void proto_send( proto *p, proto_code code, const char *str ) { proto_send_size(p,code,str,(int)strlen(str)); } void protocol_send_header( proto *p, const char *key, const char *val ) { proto_send(p,CODE_HEADER_KEY,key); proto_send(p,CODE_HEADER_VALUE,val); } static int url_decode( const char *bin, int len, char *bout ) { int pin = 0; int pout = 0; while( len-- > 0 ) { char c = bin[pin++]; if( c == '+' ) c = ' '; else if( c == '%' ) { int p1, p2; if( len < 2 ) break; p1 = bin[pin++]; p2 = bin[pin++]; len -= 2; if( p1 >= '0' && p1 <= '9' ) p1 -= '0'; else if( p1 >= 'a' && p1 <= 'f' ) p1 -= 'a' - 10; else if( p1 >= 'A' && p1 <= 'F' ) p1 -= 'A' - 10; else continue; if( p2 >= '0' && p2 <= '9' ) p2 -= '0'; else if( p2 >= 'a' && p2 <= 'f' ) p2 -= 'a' - 10; else if( p2 >= 'A' && p2 <= 'F' ) p2 -= 'A' - 10; else continue; c = (char)((unsigned char)((p1 << 4) + p2)); } bout[pout++] = c; } bout[pout] = 0; return pout; } #define DEFAULT_SIZE 256 static void proto_send_decode( proto *p, proto_code code, const char *str, int len ) { char tmp[DEFAULT_SIZE]; char *buf = NULL; int size; if( len >= DEFAULT_SIZE ) buf = malloc(len+1); size = url_decode(str,len,buf?buf:tmp); proto_send_size(p,code,buf?buf:tmp,size); if( buf ) free(buf); } void protocol_send_param( proto *p, const char *param, int param_size, const char *value, int value_size ) { proto_send_size(p,CODE_PARAM_KEY,param,param_size); proto_send_size(p,CODE_PARAM_VALUE,value,value_size); } void protocol_send_raw_params( proto *p, const char *args ) { char *aand, *aeq, *asep; while( true ) { aand = strchr(args,'&'); if( aand == NULL ) { asep = strchr(args,';'); aand = asep; } else { asep = strchr(args,';'); if( asep != NULL && asep < aand ) aand = asep; } if( aand != NULL ) *aand = 0; aeq = strchr(args,'='); if( aeq != NULL ) { *aeq = 0; proto_send_decode(p,CODE_PARAM_KEY,args,(int)(aeq-args)); proto_send_decode(p,CODE_PARAM_VALUE,aeq+1,(int)strlen(aeq+1)); *aeq = '='; } if( aand == NULL ) break; *aand = (aand == asep)?';':'&'; args = aand+1; } } static char *memfind( char *mem, int mlen, const char *v ) { char *found; int len = (int)strlen(v); if( len == 0 ) return mem; while( (found = memchr(mem,*v,mlen)) != NULL ) { if( (int)(found - mem) + len > mlen ) break; if( memcmp(found,v,len) == 0 ) return found; mlen -= (int)(found - mem + 1); mem = found + 1; } return NULL; } bool protocol_send_request( proto *p ) { proto_send(p,CODE_FILE,p->inf.script); proto_send(p,CODE_URI,p->inf.uri); proto_send(p,CODE_HOST_NAME,p->inf.hostname); proto_send(p,CODE_CLIENT_IP,p->inf.client_ip); if( p->inf.do_get_headers ) p->inf.do_get_headers(p->inf.custom); if( p->inf.get_data ) proto_send(p,CODE_GET_PARAMS,p->inf.get_data); if( p->inf.post_data ) proto_send_size(p,CODE_POST_DATA,p->inf.post_data,p->inf.post_data_size); if( p->inf.do_get_params ) p->inf.do_get_params(p->inf.custom); proto_send(p,CODE_HTTP_METHOD,p->inf.http_method); psock_set_fastsend(p->s,1); proto_send_size(p,CODE_EXECUTE,NULL,0); psock_set_fastsend(p->s,0); return !p->error; } static int fill_buffer( proto *p, char *buf, int bufsize, int pos ) { while( pos < bufsize ) { int k = p->inf.do_stream_data(p->inf.custom,buf+pos,bufsize-pos); if( k <= 0 ) break; pos += k; } return pos; } static bool send_multipart_data( proto *p, char *buf, int bufsize ) { int len = 0; char *boundstr = NULL; int boundstr_len; if( p->inf.content_type == NULL || p->inf.do_stream_data == NULL ) return true; // extract boundary value { const char *boundary, *bend; if( (boundary = strstr(p->inf.content_type,"boundary=")) == NULL ) return false; boundary += 9; PARSE_HEADER(boundary,bend); len = (int)(bend - boundary); boundstr_len = len + 2; if( boundstr_len > bufsize / 2 ) return false; boundstr = (char*)malloc(boundstr_len + 1); boundstr[0] = '-'; boundstr[1] = '-'; boundstr[boundstr_len] = 0; memcpy(boundstr+2,boundary,len); } len = 0; // permit the server to start download if needed if( p->inf.do_stream_data(p->inf.custom,NULL,0) != 0 ) { free(boundstr); return false; } while( true ) { char *name, *end_name, *filename, *end_file_name, *data; int pos; // refill buffer // we assume here that the the whole multipart header can fit in the buffer len = fill_buffer(p,buf,bufsize,len); // is boundary at the beginning of buffer ? if( len < boundstr_len || memcmp(buf,boundstr,boundstr_len) != 0 ) { free(boundstr); return false; } name = memfind(buf,len,"Content-Disposition:"); if( name == NULL ) break; name = memfind(name,len - (int)(name - buf),"name="); if( name == NULL ) { free(boundstr); return false; } name += 5; PARSE_HEADER(name,end_name); data = memfind(end_name,len - (int)(end_name - buf),"\r\n\r\n"); if( data == NULL ) { free(boundstr); return false; } filename = memfind(name,(int)(data - name),"filename="); if( filename != NULL ) { filename += 9; PARSE_HEADER(filename,end_file_name); } data += 4; pos = (int)(data - buf); // send part name if( filename ) proto_send_size(p,CODE_PART_FILENAME,filename,(int)(end_file_name - filename)); proto_send_size(p,CODE_PART_KEY,name,(int)(end_name - name)); // read data while( true ) { const char *boundary; // recall buffer memmove(buf,buf+pos,len - pos); len -= pos; pos = 0; len = fill_buffer(p,buf,bufsize,len); // lookup bounds boundary = memfind(buf,len,boundstr); if( boundary == NULL ) { if( len == 0 ) { free(boundstr); return false; } // send as much buffer as possible to client if( len < bufsize ) pos = len; else pos = len - boundstr_len + 1; proto_send_size(p,CODE_PART_DATA,buf,pos); } else { // send remaining data pos = (int)(boundary - buf); proto_send_size(p,CODE_PART_DATA,buf,pos - 2); // recall memmove(buf,buf+pos,len - pos); len -= pos; break; } } proto_send_size(p,CODE_PART_DONE,"",0); } free(boundstr); return true; } #define BUFSIZE (1 << 16) // 64 KB #define ABORT(msg) { proto_error(p,msg); goto exit; } bool protocol_read_answer( proto *p ) { unsigned char header[4]; int len; char *buf = (char*)malloc(BUFSIZE), *key = NULL; int buflen = BUFSIZE; int listening = 0; while( true ) { if( !proto_read(p,header,4) ) ABORT("Connection Closed"); len = header[1] | (header[2] << 8) | (header[3] << 16); if( buflen <= len ) { while( buflen <= len ) buflen <<= 1; free(buf); buf = (char*)malloc(buflen); } if( !proto_read(p,buf,len) ) ABORT("Connection Closed"); buf[len] = 0; switch( *header ) { case CODE_HEADER_KEY: key = strdup(buf); break; case CODE_HEADER_VALUE: if( !key ) ABORT("Missing key"); p->inf.do_set_header(p->inf.custom,key,buf,false); free(key); key = NULL; break; case CODE_HEADER_ADD_VALUE: if( !key ) ABORT("Missing key"); p->inf.do_set_header(p->inf.custom,key,buf,true); free(key); key = NULL; break; case CODE_EXECUTE: goto exit; case CODE_ERROR: p->inf.do_log(p->inf.custom,buf,true); goto exit; case CODE_PRINT: if( !p->inf.do_print(p->inf.custom,buf,len) && listening ) goto exit; if( listening ) p->inf.do_flush(p->inf.custom); break; case CODE_LOG: p->inf.do_log(p->inf.custom,buf,false); break; case CODE_FLUSH: p->inf.do_flush(p->inf.custom); break; case CODE_REDIRECT: p->inf.do_set_header(p->inf.custom,"Location",buf,false); p->inf.do_set_return_code(p->inf.custom,302); break; case CODE_RETURNCODE: p->inf.do_set_return_code(p->inf.custom,atoi(buf)); break; case CODE_QUERY_MULTIPART: { int tmpsize = atoi(buf); char *tmp = (char*)malloc(tmpsize + 1); tmp[tmpsize] = 0; if( !send_multipart_data(p,tmp,tmpsize) ) { free(tmp); ABORT("Failed to send multipart data"); } free(tmp); proto_send(p,CODE_EXECUTE,""); } break; case CODE_LISTEN: listening = 1; p->inf.do_flush(p->inf.custom); break; default: ABORT("Unexpected code"); } } exit: free(key); free(buf); return !p->error; } /* ************************************************************************ */ neko-2-2-0/libs/mod_tora/protocol.h000066400000000000000000000052321321613172000172120ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef PROTOCOL_H #define PROTOCOL_H #include "osdef.h" typedef void (*pf_callback)( void *custom ); typedef int (*pf_print)( void *custom, const char *buffer, int size ); typedef void (*pf_set_header)( void *custom, const char *key, const char *value, bool add ); typedef void (*pf_set_code)( void *custom, int code ); typedef void (*pf_log)( void *custom, const char *message, bool inner_log ); typedef int (*pf_stream_data)( void *custom, char *buffer, int size ); typedef struct { const char *script; const char *uri; const char *hostname; const char *client_ip; const char *http_method; const char *get_data; const char *post_data; const char *content_type; int post_data_size; pf_callback do_get_headers; pf_callback do_get_params; pf_print do_print; pf_callback do_flush; pf_set_header do_set_header; pf_set_code do_set_return_code; pf_stream_data do_stream_data; pf_log do_log; void *custom; } protocol_infos; struct _protocol; typedef struct _protocol proto; proto *protocol_init( protocol_infos *inf ); bool protocol_connect( proto *p, const char *host, int port ); bool protocol_send_request( proto *p ); void protocol_send_header( proto *p, const char *header, const char *value ); void protocol_send_param( proto *p, const char *param, int param_size, const char *value, int value_size ); void protocol_send_raw_params( proto *p, const char *data ); bool protocol_read_answer( proto *p ); const char *protocol_get_error( proto *p ); void protocol_free( proto *p ); #endif /* ************************************************************************ */ neko-2-2-0/libs/mysql/000077500000000000000000000000001321613172000145375ustar00rootroot00000000000000neko-2-2-0/libs/mysql/CMakeLists.txt000066400000000000000000000116121321613172000173000ustar00rootroot00000000000000 ###################### # OpenSSL if (STATIC_OPENSSL) if (APPLE) if (${CMAKE_OSX_ARCHITECTURES} STREQUAL "i386") set(OPENSSL_CONF ./Configure darwin-i386-cc "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") elseif (${CMAKE_OSX_ARCHITECTURES} STREQUAL "x86_64") set(OPENSSL_CONF ./Configure darwin64-x86_64-cc "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() else() set(OPENSSL_CONF ./config) endif() if (WIN32) # perl is needed to run the openssl Configure script... find_package(Perl REQUIRED) if (arch_64) set(openssl_target VC-WIN64A) else() set(openssl_target VC-WIN32) endif() message("arch_64 is ${arch_64}") message("openssl_target is ${openssl_target}") set(OPENSSL_CONFS CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/openssl && ${PERL_EXECUTABLE} Configure ${openssl_target} no-asm no-tests --prefix=${CMAKE_BINARY_DIR}/libs/src/install-prefix BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/openssl && nmake /S INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/openssl && nmake /S install_sw ) else() set(OPENSSL_CONFS CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/openssl && ${OPENSSL_CONF} no-tests --prefix=${CMAKE_BINARY_DIR}/libs/src/install-prefix BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/openssl && make INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/openssl && make install_sw ) endif() ExternalProject_Add(OpenSSL ${EP_CONFIGS} URL https://www.openssl.org/source/openssl-1.1.0g.tar.gz URL_MD5 ba5f1b8b835b88cadbce9b35ed9531a6 ${OPENSSL_CONFS} PATCH_COMMAND ${CMAKE_COMMAND} -Dopenssl_source=${CMAKE_BINARY_DIR}/libs/src/openssl -P ${CMAKE_SOURCE_DIR}/cmake/patch_openssl.cmake SOURCE_DIR ${CMAKE_BINARY_DIR}/libs/src/openssl ) set_target_properties(OpenSSL PROPERTIES ${EP_PROPS}) if (WIN32) set(OPENSSL_LIBRARIES Crypt32 ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/libcrypto.lib ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/libssl.lib ) endif() # Download project for fat source archive add_dependencies(download_static_deps OpenSSL-download) else() find_package(OpenSSL) endif() ###################### # mysql.ndll add_library(mysql.ndll MODULE mysql.c) if (STATIC_MARIADBCONNECTOR) if (STATIC_OPENSSL AND NOT WIN32) set(OPENSSL_CONF -DOPENSSL_ROOT_DIR=${CMAKE_BINARY_DIR}/libs/src/install-prefix) set(OPENSSL_DEP OpenSSL) elseif() set(OPENSSL_CONF "") set(OPENSSL_DEP "") endif() if (WIN32) set(MARIADB_CONNECTOR_LIBRARIES ${OPENSSL_LIBRARIES} ${CMAKE_BINARY_DIR}/libs/src/MariaDBConnector-build/libmariadb/${CMAKE_CFG_INTDIR}/mariadbclient.lib ) else() set(MARIADB_CONNECTOR_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/MariaDBConnector-build/libmariadb/libmariadbclient.a ) endif() ExternalProject_Add(MariaDBConnector ${EP_CONFIGS} DEPENDS ${OPENSSL_DEP} URL https://downloads.mariadb.org/f/connector-c-3.0.2/mariadb-connector-c-3.0.2-src.tar.gz URL_MD5 2eb5ba004ac105eebb538ead352c0c78 CMAKE_ARGS -Wno-dev -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DWITH_SSL=ON ${OPENSSL_CONF} PATCH_COMMAND ${CMAKE_COMMAND} -Dmariadb_source=${CMAKE_BINARY_DIR}/libs/src/MariaDBConnector -P ${CMAKE_SOURCE_DIR}/cmake/patch_mariadb.cmake BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/MariaDBConnector-build && ${CMAKE_COMMAND} --build . --target mariadbclient --config ${CMAKE_CFG_INTDIR} INSTALL_COMMAND echo skip install BYPRODUCTS ${MARIADB_CONNECTOR_LIBRARIES} ) set_target_properties(MariaDBConnector PROPERTIES ${EP_PROPS}) set(MARIADB_CONNECTOR_INCLUDE_DIR ${CMAKE_BINARY_DIR}/libs/src/MariaDBConnector/include ${CMAKE_BINARY_DIR}/libs/src/MariaDBConnector-build/include ) add_dependencies(mysql.ndll MariaDBConnector) # Download project for fat source archive add_dependencies(download_static_deps MariaDBConnector-download) else() find_package(MariaDBConnector REQUIRED) endif() target_include_directories(mysql.ndll PRIVATE ${MARIADB_CONNECTOR_INCLUDE_DIR} ) target_link_libraries(mysql.ndll libneko ${MARIADB_CONNECTOR_LIBRARIES}) if (WIN32) target_link_libraries(mysql.ndll ws2_32 crypt32 shlwapi) endif() set_target_properties(mysql.ndll PROPERTIES PREFIX "" OUTPUT_NAME mysql SUFFIX .ndll ) if(APPLE) set_target_properties(mysql.ndll PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ${LINK_FLAGS}" ) endif(APPLE) ###################### # mysql5.ndll add_library(mysql5.ndll MODULE my_proto/my_proto.c my_proto/my_api.c mysql.c ) target_include_directories(mysql5.ndll PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/my_proto ) target_link_libraries(mysql5.ndll socket sha1 libneko ) if (WIN32) target_link_libraries(mysql5.ndll ws2_32) endif() set_target_properties(mysql5.ndll PROPERTIES PREFIX "" OUTPUT_NAME mysql5 SUFFIX .ndll ) install ( TARGETS mysql.ndll mysql5.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/mysql/my_proto/000077500000000000000000000000001321613172000164075ustar00rootroot00000000000000neko-2-2-0/libs/mysql/my_proto/my_api.c000066400000000000000000000322021321613172000200300ustar00rootroot00000000000000/* * MYSQL 5.0 Protocol Implementation * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include "my_proto.h" static void error( MYSQL *m, const char *err, const char *param ) { if( param ) { unsigned int max = MAX_ERR_SIZE - (strlen(err) + 3); if( strlen(param) > max ) { char *p2 = (char*)malloc(max + 1); memcpy(p2,param,max-3); p2[max - 3] = '.'; p2[max - 2] = '.'; p2[max - 1] = '.'; p2[max] = 0; sprintf(m->last_error,err,param); free(p2); return; } } sprintf(m->last_error,err,param); m->errcode = -1; } static void save_error( MYSQL *m, MYSQL_PACKET *p ) { int ecode; p->pos = 0; // seems like we sometimes get some FFFFFF sequences before // the actual error... do { if( myp_read_byte(p) != 0xFF ) { m->errcode = -1; error(m,"Failed to decode error",NULL); return; } ecode = myp_read_ui16(p); } while( ecode == 0xFFFF ); if( m->is41 && p->buf[p->pos] == '#' ) p->pos += 6; // skip sqlstate marker error(m,"%s",myp_read_string(p)); m->errcode = ecode; } static int myp_ok( MYSQL *m, int allow_others ) { int code; MYSQL_PACKET *p = &m->packet; if( !myp_read_packet(m,p) ) { error(m,"Failed to read packet",NULL); return 0; } code = myp_read_byte(p); if( code == 0x00 ) return 1; if( code == 0xFF ) save_error(m,p); else if( allow_others ) return 1; else error(m,"Invalid packet error",NULL); return 0; } static void myp_close( MYSQL *m ) { psock_close(m->s); m->s = INVALID_SOCKET; } MYSQL *mysql_init( void *unused ) { MYSQL *m = (MYSQL*)malloc(sizeof(struct _MYSQL)); psock_init(); memset(m,0,sizeof(struct _MYSQL)); m->s = INVALID_SOCKET; error(m,"NO ERROR",NULL); m->errcode = 0; m->last_field_count = -1; m->last_insert_id = -1; m->affected_rows = -1; return m; } MYSQL *mysql_real_connect( MYSQL *m, const char *host, const char *user, const char *pass, void *unused, int port, const char *socket, int options ) { PHOST h; char scramble_buf[21]; MYSQL_PACKET *p = &m->packet; int pcount = 1; if( socket && *socket ) { error(m,"Unix Socket connections are not supported",NULL); return NULL; } h = phost_resolve(host); if( h == UNRESOLVED_HOST ) { error(m,"Failed to resolve host '%s'",host); return NULL; } m->s = psock_create(); if( m->s == INVALID_SOCKET ) { error(m,"Failed to create socket",NULL); return NULL; } psock_set_fastsend(m->s,1); psock_set_timeout(m->s,50); // 50 seconds if( psock_connect(m->s,h,port) != PS_OK ) { myp_close(m); error(m,"Failed to connect on host '%s'",host); return NULL; } if( !myp_read_packet(m,p) ) { myp_close(m); error(m,"Failed to read handshake packet",NULL); return NULL; } // process handshake packet { char filler[13]; unsigned int len; m->infos.proto_version = myp_read_byte(p); // this seems like an error packet if( m->infos.proto_version == 0xFF ) { myp_close(m); save_error(m,p); return NULL; } m->infos.server_version = strdup(myp_read_string(p)); m->infos.thread_id = myp_read_int(p); myp_read(p,scramble_buf,8); myp_read_byte(p); // should be 0 m->infos.server_flags = myp_read_ui16(p); m->infos.server_charset = myp_read_byte(p); m->infos.server_status = myp_read_ui16(p); m->infos.server_flags |= myp_read_ui16(p) << 16; len = myp_read_byte(p); myp_read(p,filler,10); // try to disable 41 m->is41 = (m->infos.server_flags & FL_PROTOCOL_41) != 0; if( !p->error && m->is41 ) myp_read(p,scramble_buf + 8,13); if( p->pos != p->size ) myp_read_string(p); // 5.5+ if( p->error ) { myp_close(m); error(m,"Failed to decode server handshake",NULL); return NULL; } // fill answer packet { unsigned int flags = m->infos.server_flags; int max_packet_size = 0x01000000; SHA1_DIGEST hpass; char filler[23]; flags &= (FL_PROTOCOL_41 | FL_TRANSACTIONS | FL_SECURE_CONNECTION); myp_begin_packet(p,128); if( m->is41 ) { myp_write_int(p,flags); myp_write_int(p,max_packet_size); myp_write_byte(p,m->infos.server_charset); memset(filler,0,23); myp_write(p,filler,23); myp_write_string(p,user); if( *pass ) { myp_encrypt_password(pass,scramble_buf,hpass); myp_write_bin(p,SHA1_SIZE); myp_write(p,hpass,SHA1_SIZE); myp_write_byte(p,0); } else myp_write_bin(p,0); } else { myp_write_ui16(p,flags); // max_packet_size myp_write_byte(p,0xFF); myp_write_byte(p,0xFF); myp_write_byte(p,0xFF); myp_write_string(p,user); if( *pass ) { char hpass[SEED_LENGTH_323 + 1]; myp_encrypt_pass_323(pass,scramble_buf,hpass); hpass[SEED_LENGTH_323] = 0; myp_write(p,hpass,SEED_LENGTH_323 + 1); } else myp_write_bin(p,0); } } } // send connection packet send_cnx_packet: if( !myp_send_packet(m,p,&pcount) ) { myp_close(m); error(m,"Failed to send connection packet",NULL); return NULL; } // read answer packet if( !myp_read_packet(m,p) ) { myp_close(m); error(m,"Failed to read packet",NULL); return NULL; } // increase packet counter (because we read one packet) pcount++; // process answer { int code = myp_read_byte(p); switch( code ) { case 0: // OK packet break; case 0xFF: // ERROR myp_close(m); save_error(m,p); return NULL; case 0xFE: // EOF // we are asked to send old password authentification if( p->size == 1 ) { char hpass[SEED_LENGTH_323 + 1]; myp_encrypt_pass_323(pass,scramble_buf,hpass); hpass[SEED_LENGTH_323] = 0; myp_begin_packet(p,0); myp_write(p,hpass,SEED_LENGTH_323 + 1); goto send_cnx_packet; } // fallthrough default: myp_close(m); error(m,"Invalid packet error",NULL); return NULL; } } // we are connected, setup a longer timeout psock_set_timeout(m->s,18000); return m; } int mysql_select_db( MYSQL *m, const char *dbname ) { MYSQL_PACKET *p = &m->packet; int pcount = 0; myp_begin_packet(p,0); myp_write_byte(p,COM_INIT_DB); myp_write_string_eof(p,dbname); if( !myp_send_packet(m,p,&pcount) ) { error(m,"Failed to send packet",NULL); return -1; } return myp_ok(m,0) ? 0 : -1; } int mysql_real_query( MYSQL *m, const char *query, int qlength ) { MYSQL_PACKET *p = &m->packet; int pcount = 0; myp_begin_packet(p,0); myp_write_byte(p,COM_QUERY); myp_write(p,query,qlength); m->last_field_count = -1; m->affected_rows = -1; m->last_insert_id = -1; if( !myp_send_packet(m,p,&pcount) ) { error(m,"Failed to send packet",NULL); return -1; } if( !myp_ok(m,1) ) return -1; p->id = IS_QUERY; return 0; } static int do_store( MYSQL *m, MYSQL_RES *r ) { int i; MYSQL_PACKET *p = &m->packet; p->pos = 0; r->nfields = myp_read_bin(p); if( p->error ) return 0; r->fields = (MYSQL_FIELD*)malloc(sizeof(MYSQL_FIELD) * r->nfields); memset(r->fields,0,sizeof(MYSQL_FIELD) * r->nfields); for(i=0;infields;i++) { if( !myp_read_packet(m,p) ) return 0; { MYSQL_FIELD *f = r->fields + i; f->catalog = m->is41 ? myp_read_bin_str(p) : NULL; f->db = m->is41 ? myp_read_bin_str(p) : NULL; f->table = myp_read_bin_str(p); f->org_table = m->is41 ? myp_read_bin_str(p) : NULL; f->name = myp_read_bin_str(p); f->org_name = m->is41 ? myp_read_bin_str(p) : NULL; if( m->is41 ) myp_read_byte(p); f->charset = m->is41 ? myp_read_ui16(p) : 0x08; f->length = m->is41 ? myp_read_int(p) : myp_read_bin(p); f->type = m->is41 ? myp_read_byte(p) : myp_read_bin(p); f->flags = m->is41 ? myp_read_ui16(p) : myp_read_bin(p); f->decimals = myp_read_byte(p); if( m->is41 ) myp_read_byte(p); // should be 0 if( m->is41 ) myp_read_byte(p); // should be 0 if( p->error ) return 0; } } // first EOF packet if( !myp_read_packet(m,p) ) return 0; if( myp_read_byte(p) != 0xFE || p->size >= 9 ) return 0; // reset packet buffer (to prevent to store large buffer in row data) free(p->buf); p->buf = NULL; p->mem = 0; // datas while( 1 ) { if( !myp_read_packet(m,p) ) return 0; // EOF : end of datas if( (unsigned char)p->buf[0] == 0xFE && p->size < 9 ) break; // ERROR ? if( (unsigned char)p->buf[0] == 0xFF ) { save_error(m,p); return 0; } // allocate one more row if( r->row_count == r->memory_rows ) { MYSQL_ROW_DATA *rows; r->memory_rows = r->memory_rows ? (r->memory_rows << 1) : 1; rows = (MYSQL_ROW_DATA*)malloc(r->memory_rows * sizeof(MYSQL_ROW_DATA)); memcpy(rows,r->rows,r->row_count * sizeof(MYSQL_ROW_DATA)); free(r->rows); r->rows = rows; } // read row fields { MYSQL_ROW_DATA *current = r->rows + r->row_count++; int prev = 0; current->raw = p->buf; current->lengths = (unsigned long*)malloc(sizeof(unsigned long) * r->nfields); current->datas = (char**)malloc(sizeof(char*) * r->nfields); for(i=0;infields;i++) { int l = myp_read_bin(p); if( !p->error ) p->buf[prev] = 0; if( l == -1 ) { current->lengths[i] = 0; current->datas[i] = NULL; } else { current->lengths[i] = l; current->datas[i] = p->buf + p->pos; p->pos += l; } prev = p->pos; } if( !p->error ) p->buf[prev] = 0; } // the packet buffer as been stored, don't reuse it p->buf = NULL; p->mem = 0; if( p->error ) return 0; } return 1; } MYSQL_RES *mysql_store_result( MYSQL *m ) { MYSQL_RES *r; MYSQL_PACKET *p = &m->packet; if( p->id != IS_QUERY ) return NULL; // OK without result if( p->buf[0] == 0 ) { p->pos = 0; m->last_field_count = myp_read_byte(p); // 0 m->affected_rows = myp_read_bin(p); m->last_insert_id = myp_read_bin(p); return NULL; } r = (MYSQL_RES*)malloc(sizeof(struct _MYSQL_RES)); memset(r,0,sizeof(struct _MYSQL_RES)); m->errcode = 0; if( !do_store(m,r) ) { mysql_free_result(r); if( !m->errcode ) error(m,"Failure while storing result",NULL); return NULL; } m->last_field_count = r->nfields; return r; } int mysql_field_count( MYSQL *m ) { return m->last_field_count; } int mysql_affected_rows( MYSQL *m ) { return m->affected_rows; } int mysql_escape_string( MYSQL *m, char *sout, const char *sin, int length ) { return myp_escape_string(m->infos.server_charset,sout,sin,length); } const char *mysql_character_set_name( MYSQL *m ) { const char *name = myp_charset_name(m->infos.server_charset); if( name == NULL ) { static char tmp[512]; sprintf(tmp,"#%d",m->infos.server_charset); return tmp; } return name; } int mysql_real_escape_string( MYSQL *m, char *sout, const char *sin, int length ) { if( !myp_supported_charset(m->infos.server_charset) ) return -1; if( m->infos.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES ) return myp_escape_quotes(m->infos.server_charset,sout,sin,length); return myp_escape_string(m->infos.server_charset,sout,sin,length); } void mysql_close( MYSQL *m ) { myp_close(m); free(m->packet.buf); free(m->infos.server_version); free(m); } const char *mysql_error( MYSQL *m ) { return m->last_error; } // RESULTS API unsigned int mysql_num_rows( MYSQL_RES *r ) { return r->row_count; } int mysql_num_fields( MYSQL_RES *r ) { return r->nfields; } MYSQL_FIELD *mysql_fetch_fields( MYSQL_RES *r ) { return r->fields; } unsigned long *mysql_fetch_lengths( MYSQL_RES *r ) { return r->current ? r->current->lengths : NULL; } MYSQL_ROW mysql_fetch_row( MYSQL_RES * r ) { MYSQL_ROW_DATA *cur = r->current; if( cur == NULL ) cur = r->rows; else { // free the previous result, since we're done with it free(cur->datas); free(cur->lengths); free(cur->raw); cur->datas = NULL; cur->lengths = NULL; cur->raw = NULL; // next cur++; } if( cur >= r->rows + r->row_count ) { free(r->rows); r->rows = NULL; r->memory_rows = 0; cur = NULL; } r->current = cur; return cur ? cur->datas : NULL; } void mysql_free_result( MYSQL_RES *r ) { if( r->fields ) { int i; for(i=0;infields;i++) { MYSQL_FIELD *f = r->fields + i; free(f->catalog); free(f->db); free(f->table); free(f->org_table); free(f->name); free(f->org_name); } free(r->fields); } if( r->rows ) { int i; for(i=0;irow_count;i++) { MYSQL_ROW_DATA *row = r->rows + i; free(row->datas); free(row->lengths); free(row->raw); } free(r->rows); } free(r); } /* ************************************************************************ */ neko-2-2-0/libs/mysql/my_proto/my_proto.c000066400000000000000000000232071321613172000204270ustar00rootroot00000000000000/* * MYSQL 5.0 Protocol Implementation * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include "my_proto.h" #define MAX_PACKET_LENGTH 0xFFFFFF int myp_recv( MYSQL *m, void *buf, int size ) { while( size ) { int len = psock_recv(m->s,(char*)buf,size); if( len <= 0 ) return size == 0 ? 1 : 0; buf = ((char*)buf) + len; size -= len; } return 1; } int myp_send( MYSQL *m, void *buf, int size ) { while( size ) { int len = psock_send(m->s,(char*)buf,size); if( len <= 0 ) return size == 0 ? 1 : 0; buf = ((char*)buf) + len; size -= len; } return 1; } int myp_read( MYSQL_PACKET *p, void *buf, int size ) { if( p->size - p->pos < size ) { p->error = 1; return 0; } memcpy(buf,p->buf + p->pos,size); p->pos += size; return 1; } unsigned char myp_read_byte( MYSQL_PACKET *p ) { unsigned char c; if( !myp_read(p,&c,1) ) return 0; return c; } unsigned short myp_read_ui16( MYSQL_PACKET *p ) { unsigned short i; if( !myp_read(p,&i,2) ) return 0; return i; } int myp_read_int( MYSQL_PACKET *p ) { int i; if( !myp_read(p,&i,4) ) return 0; return i; } int myp_read_bin( MYSQL_PACKET *p ) { int c = myp_read_byte(p); if( c <= 250 ) return c; if( c == 251 ) return -1; // NULL if( c == 252 ) return myp_read_ui16(p); if( c == 253 ) { c = 0; myp_read(p,&c,3); return c; } if( c == 254 ) return myp_read_int(p); p->error = 1; return 0; } const char *myp_read_string( MYSQL_PACKET *p ) { char *str; if( p->pos >= p->size ) { p->error = 1; return ""; } str = p->buf + p->pos; p->pos += strlen(str) + 1; return str; } char *myp_read_bin_str( MYSQL_PACKET *p ) { int size = myp_read_bin(p); char *str; if( size == -1 ) return NULL; if( p->error || p->pos + size > p->size ) { p->error = 1; return NULL; } str = (char*)malloc(size + 1); memcpy(str,p->buf + p->pos, size); str[size] = 0; p->pos += size; return str; } int myp_read_packet( MYSQL *m, MYSQL_PACKET *p ) { unsigned int psize; p->pos = 0; p->error = 0; if( !myp_recv(m,&psize,4) ) { p->error = 1; p->size = 0; return 0; } //p->id = (psize >> 24); psize &= 0xFFFFFF; p->size = psize; if( p->mem < (int)psize ) { free(p->buf); p->buf = (char*)malloc(psize + 1); p->mem = psize; } p->buf[psize] = 0; if( psize == 0 || !myp_recv(m,p->buf,psize) ) { p->error = 1; p->size = 0; p->buf[0] = 0; return 0; } return 1; } int myp_send_packet( MYSQL *m, MYSQL_PACKET *p, int *packet_counter ) { unsigned int header; char *buf = p->buf; int size = p->size; int next = 1; while( next ) { int psize; if( size >= MAX_PACKET_LENGTH ) psize = MAX_PACKET_LENGTH; else { psize = size; next = 0; } header = psize | (((*packet_counter)++) << 24); if( !myp_send(m,&header,4) || !myp_send(m,buf,psize) ) { p->error = 1; return 0; } buf += psize; size -= psize; } return 1; } void myp_begin_packet( MYSQL_PACKET *p, int minsize ) { if( p->mem < minsize ) { free(p->buf); p->buf = (char*)malloc(minsize + 1); p->mem = minsize; } p->error = 0; p->size = 0; } void myp_write( MYSQL_PACKET *p, const void *data, int size ) { if( p->size + size > p->mem ) { char *buf2; if( p->mem == 0 ) p->mem = 32; do { p->mem <<= 1; } while( p->size + size > p->mem ); buf2 = (char*)malloc(p->mem + 1); memcpy(buf2,p->buf,p->size); free(p->buf); p->buf = buf2; } memcpy( p->buf + p->size , data, size ); p->size += size; } void myp_write_byte( MYSQL_PACKET *p, int i ) { unsigned char c = (unsigned char)i; myp_write(p,&c,1); } void myp_write_ui16( MYSQL_PACKET *p, int i ) { unsigned short c = (unsigned char)i; myp_write(p,&c,2); } void myp_write_int( MYSQL_PACKET *p, int i ) { myp_write(p,&i,4); } void myp_write_string( MYSQL_PACKET *p, const char *str ) { myp_write(p,str,strlen(str) + 1); } void myp_write_string_eof( MYSQL_PACKET *p, const char *str ) { myp_write(p,str,strlen(str)); } void myp_write_bin( MYSQL_PACKET *p, int size ) { if( size <= 250 ) { unsigned char l = (unsigned char)size; myp_write(p,&l,1); } else if( size < 0x10000 ) { unsigned char c = 252; unsigned short l = (unsigned short)size; myp_write(p,&c,1); myp_write(p,&l,2); } else if( size < 0x1000000 ) { unsigned char c = 253; unsigned int l = (unsigned short)size; myp_write(p,&c,1); myp_write(p,&l,3); } else { unsigned char c = 254; myp_write(p,&c,1); myp_write(p,&size,4); } } void myp_crypt( unsigned char *out, const unsigned char *s1, const unsigned char *s2, unsigned int len ) { unsigned int i; for(i=0;imax_value = 0x3FFFFFFFL; r->max_value_dbl = (double)r->max_value; r->seed1 = seed1 % r->max_value ; r->seed2 = seed2 % r->max_value; } static double myp_rnd( rand_ctx *r ) { r->seed1 = (r->seed1 * 3 + r->seed2) % r->max_value; r->seed2 = (r->seed1 + r->seed2 + 33) % r->max_value; return (((double) r->seed1)/r->max_value_dbl); } static void hash_password( unsigned long *result, const char *password, int password_len ) { register unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L; unsigned long tmp; const char *password_end = password + password_len; for(; password < password_end; password++) { if( *password == ' ' || *password == '\t' ) continue; tmp = (unsigned long)(unsigned char)*password; nr ^= (((nr & 63)+add)*tmp)+(nr << 8); nr2 += (nr2 << 8) ^ nr; add += tmp; } result[0] = nr & (((unsigned long) 1L << 31) -1L); result[1] = nr2 & (((unsigned long) 1L << 31) -1L); } void myp_encrypt_pass_323( const char *password, const char seed[SEED_LENGTH_323], char to[SEED_LENGTH_323] ) { rand_ctx r; unsigned long hash_pass[2], hash_seed[2]; char extra, *to_start = to; const char *seed_end = seed + SEED_LENGTH_323; hash_password(hash_pass,password,(unsigned int)strlen(password)); hash_password(hash_seed,seed,SEED_LENGTH_323); random_init(&r,hash_pass[0] ^ hash_seed[0],hash_pass[1] ^ hash_seed[1]); while( seed < seed_end ) { *to++ = (char)(floor(myp_rnd(&r)*31)+64); seed++; } extra= (char)(floor(myp_rnd(&r)*31)); while( to_start != to ) *(to_start++) ^= extra; } // defined in mysql/strings/ctype-*.c const char *myp_charset_name( int charset ) { switch( charset ) { case 8: case 31: case 47: return "latin1"; case 63: return "binary"; // 101+ : utf16 // 160+ : utf32 case 33: case 83: case 223: case 254: return "utf8"; case 45: case 46: return "utf8mb4"; // superset of utf8 with up to 4 bytes per-char default: if( charset >= 192 && charset <= 211 ) return "utf8"; if( charset >= 224 && charset <= 243 ) return "utf8mb4"; } return NULL; } int myp_supported_charset( int charset ) { return myp_charset_name(charset) != NULL; } int myp_escape_string( int charset, char *sout, const char *sin, int length ) { // this is safe for UTF8 as well since mysql protects against invalid UTF8 char injection const char *send = sin + length; char *sbegin = sout; while( sin != send ) { char c = *sin++; switch( c ) { case 0: *sout++ = '\\'; *sout++ = '0'; break; case '\n': *sout++ = '\\'; *sout++ = 'n'; break; case '\r': *sout++ = '\\'; *sout++ = 'r'; break; case '\\': *sout++ = '\\'; *sout++ = '\\'; break; case '\'': *sout++ = '\\'; *sout++ = '\''; break; case '"': *sout++ = '\\'; *sout++ = '"'; break; case '\032': *sout++ = '\\'; *sout++ = 'Z'; break; default: *sout++ = c; } } *sout = 0; return sout - sbegin; } int myp_escape_quotes( int charset, char *sout, const char *sin, int length ) { const char *send = sin + length; char *sbegin = sout; while( sin != send ) { char c = *sin++; *sout++ = c; if( c == '\'' ) *sout++ = c; } *sout = 0; return sout - sbegin; } /* ************************************************************************ */ neko-2-2-0/libs/mysql/my_proto/my_proto.h000066400000000000000000000121651321613172000204350ustar00rootroot00000000000000/* * MYSQL 5.0 Protocol Implementation * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef MY_PROTO_H #define MY_PROTO_H #include "mysql.h" #include "socket.h" #include "sha1.h" typedef enum { FL_LONG_PASSWORD = 1, FL_FOUND_ROWS = 2, FL_LONG_FLAG = 4, FL_CONNECT_WITH_DB = 8, FL_NO_SCHEMA = 16, FL_COMPRESS = 32, FL_ODBC = 64, FL_LOCAL_FILES = 128, FL_IGNORE_SPACE = 256, FL_PROTOCOL_41 = 512, FL_INTERACTIVE = 1024, FL_SSL = 2048, FL_IGNORE_SIGPIPE = 4096, FL_TRANSACTIONS = 8192, FL_RESERVED = 16384, FL_SECURE_CONNECTION = 32768, FL_MULTI_STATEMENTS = 65536, FL_MULTI_RESULTS = 131072, } MYSQL_FLAG; typedef enum { COM_SLEEP = 0x00, COM_QUIT = 0x01, COM_INIT_DB = 0x02, COM_QUERY = 0x03, COM_FIELD_LIST = 0x04, //COM_CREATE_DB = 0x05, //COM_DROP_DB = 0x06 COM_REFRESH = 0x07, COM_SHUTDOWN = 0x08, COM_STATISTICS = 0x09, COM_PROCESS_INFO = 0x0A, //COM_CONNECT = 0x0B, COM_PROCESS_KILL = 0x0C, COM_DEBUG = 0x0D, COM_PING = 0x0E, //COM_TIME = 0x0F, //COM_DELAYED_INSERT = 0x10, COM_CHANGE_USER = 0x11, COM_BINLOG_DUMP = 0x12, COM_TABLE_DUMP = 0x13, COM_CONNECT_OUT = 0x14, COM_REGISTER_SLAVE = 0x15, COM_STMT_PREPARE = 0x16, COM_STMT_EXECUTE = 0x17, COM_STMT_SEND_LONG_DATA = 0x18, COM_STMT_CLOSE = 0x19, COM_STMT_RESET = 0x1A, COM_SET_OPTION = 0x1B, COM_STMT_FETCH = 0x1C, } MYSQL_COMMAND; typedef enum { SERVER_STATUS_IN_TRANS = 1, SERVER_STATUS_AUTOCOMMIT = 2, SERVER_MORE_RESULTS_EXISTS = 8, SERVER_QUERY_NO_GOOD_INDEX_USED = 16, SERVER_QUERY_NO_INDEX_USED = 32, SERVER_STATUS_CURSOR_EXISTS = 64, SERVER_STATUS_LAST_ROW_SENT = 128, SERVER_STATUS_DB_DROPPED = 256, SERVER_STATUS_NO_BACKSLASH_ESCAPES = 512, } MYSQL_SERVER_STATUS; typedef struct { unsigned char proto_version; char *server_version; unsigned int thread_id; unsigned int server_flags; unsigned char server_charset; unsigned short server_status; } MYSQL_INFOS; typedef struct { int id; int error; int size; int pos; int mem; char *buf; } MYSQL_PACKET; #define MAX_ERR_SIZE 1024 #define IS_QUERY -123456 struct _MYSQL { PSOCK s; MYSQL_INFOS infos; MYSQL_PACKET packet; int is41; int errcode; int last_field_count; int affected_rows; int last_insert_id; char last_error[MAX_ERR_SIZE]; }; typedef struct { char *raw; unsigned long *lengths; char **datas; } MYSQL_ROW_DATA; struct _MYSQL_RES { int nfields; MYSQL_FIELD *fields; MYSQL_ROW_DATA *rows; MYSQL_ROW_DATA *current; int row_count; int memory_rows; }; // network int myp_recv( MYSQL *m, void *buf, int size ); int myp_send( MYSQL *m, void *buf, int size ); int myp_read_packet( MYSQL *m, MYSQL_PACKET *p ); int myp_send_packet( MYSQL *m, MYSQL_PACKET *p, int *packet_counter ); // packet read int myp_read( MYSQL_PACKET *p, void *buf, int size ); unsigned char myp_read_byte( MYSQL_PACKET *p ); unsigned short myp_read_ui16( MYSQL_PACKET *p ); int myp_read_int( MYSQL_PACKET *p ); const char *myp_read_string( MYSQL_PACKET *p ); int myp_read_bin( MYSQL_PACKET *p ); char *myp_read_bin_str( MYSQL_PACKET *p ); // packet write void myp_begin_packet( MYSQL_PACKET *p, int minsize ); void myp_write( MYSQL_PACKET *p, const void *data, int size ); void myp_write_byte( MYSQL_PACKET *p, int b ); void myp_write_ui16( MYSQL_PACKET *p, int b ); void myp_write_int( MYSQL_PACKET *p, int b ); void myp_write_string( MYSQL_PACKET *p, const char *str ); void myp_write_string_eof( MYSQL_PACKET *p, const char *str ); void myp_write_bin( MYSQL_PACKET *p, int size ); // passwords #define SEED_LENGTH_323 8 void myp_crypt( unsigned char *out, const unsigned char *s1, const unsigned char *s2, unsigned int len ); void myp_encrypt_password( const char *pass, const char *seed, SHA1_DIGEST out ); void myp_encrypt_pass_323( const char *pass, const char seed[SEED_LENGTH_323], char out[SEED_LENGTH_323] ); // escaping int myp_supported_charset( int charset ); const char *myp_charset_name( int charset ); int myp_escape_string( int charset, char *sout, const char *sin, int length ); int myp_escape_quotes( int charset, char *sout, const char *sin, int length ); #endif /* ************************************************************************ */ neko-2-2-0/libs/mysql/my_proto/mysql.h000066400000000000000000000103521321613172000177260ustar00rootroot00000000000000/* * MYSQL 5.0 Protocol Implementation * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef MYSQL_H #define MYSQL_H struct _MYSQL; struct _MYSQL_RES; typedef struct _MYSQL MYSQL; typedef struct _MYSQL_RES MYSQL_RES; typedef char **MYSQL_ROW; typedef enum enum_field_types { FIELD_TYPE_DECIMAL = 0x00, FIELD_TYPE_TINY = 0x01, FIELD_TYPE_SHORT = 0x02, FIELD_TYPE_LONG = 0x03, FIELD_TYPE_FLOAT = 0x04, FIELD_TYPE_DOUBLE = 0x05, FIELD_TYPE_NULL = 0x06, FIELD_TYPE_TIMESTAMP = 0x07, FIELD_TYPE_LONGLONG = 0x08, FIELD_TYPE_INT24 = 0x09, FIELD_TYPE_DATE = 0x0A, FIELD_TYPE_TIME = 0x0B, FIELD_TYPE_DATETIME = 0x0C, FIELD_TYPE_YEAR = 0x0D, FIELD_TYPE_NEWDATE = 0x0E, FIELD_TYPE_VARCHAR = 0x0F, FIELD_TYPE_BIT = 0x10, FIELD_TYPE_NEWDECIMAL = 0xF6, FIELD_TYPE_ENUM = 0xF7, FIELD_TYPE_SET = 0xF8, FIELD_TYPE_TINY_BLOB = 0xF9, FIELD_TYPE_MEDIUM_BLOB = 0xFA, FIELD_TYPE_LONG_BLOB = 0xFB, FIELD_TYPE_BLOB = 0xFC, FIELD_TYPE_VAR_STRING = 0xFD, FIELD_TYPE_STRING = 0xFE, FIELD_TYPE_GEOMETRY = 0xFF } FIELD_TYPE; typedef enum { NOT_NULL_FLAG = 1, PRI_KEY_FLAG = 2, UNIQUE_KEY_FLAG = 4, MULTIPLE_KEY_FLAG = 8, BLOB_FLAG = 16, UNSIGNED_FLAG = 32, ZEROFILL_FLAG = 64, BINARY_FLAG = 128, ENUM_FLAG = 256, AUTO_INCREMENT_FLAG = 512, TIMESTAMP_FLAG = 1024, SET_FLAG = 2048, NUM_FLAG = 32768, } __FIELD_FLAG; typedef struct { char *catalog; char *db; char *table; char *org_table; char *name; char *org_name; int charset; int length; int flags; int decimals; FIELD_TYPE type; } MYSQL_FIELD; #define mysql_init mp_init #define mysql_real_connect mp_real_connect #define mysql_select_db mp_select_db #define mysql_real_query mp_real_query #define mysql_store_result mp_store_result #define mysql_field_count mp_field_count #define mysql_affected_rows mp_affected_rows #define mysql_escape_string mp_escape_string #define mysql_real_escape_string mp_real_escape_string #define mysql_close mp_close #define mysql_error mp_error #define mysql_num_rows mp_num_rows #define mysql_num_fields mp_num_fields #define mysql_fetch_fields mp_fetch_fields #define mysql_fetch_lengths mp_fetch_lengths #define mysql_fetch_row mp_fetch_row #define mysql_free_result mp_free_result MYSQL *mysql_init( void * ); MYSQL *mysql_real_connect( MYSQL *m, const char *host, const char *user, const char *pass, void *unused, int port, const char *socket, int options ); int mysql_select_db( MYSQL *m, const char *dbname ); int mysql_real_query( MYSQL *m, const char *query, int qlength ); MYSQL_RES *mysql_store_result( MYSQL *m ); int mysql_field_count( MYSQL *m ); int mysql_affected_rows( MYSQL *m ); int mysql_escape_string( MYSQL *m, char *sout, const char *sin, int length ); int mysql_real_escape_string( MYSQL *m, char *sout, const char *sin, int length ); void mysql_close( MYSQL *m ); const char *mysql_error( MYSQL *m ); const char *mysql_character_set_name( MYSQL *m ); unsigned int mysql_num_rows( MYSQL_RES *r ); int mysql_num_fields( MYSQL_RES *r ); MYSQL_FIELD *mysql_fetch_fields( MYSQL_RES *r ); unsigned long *mysql_fetch_lengths( MYSQL_RES *r ); MYSQL_ROW mysql_fetch_row( MYSQL_RES * r ); void mysql_free_result( MYSQL_RES *r ); #endif /* ************************************************************************ */ neko-2-2-0/libs/mysql/mysql.c000066400000000000000000000334161321613172000160570ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include typedef int SOCKET; #include #include /**

MySQL

API to connect and use MySQL database

**/ #define CNX(o) ((connection*)val_data(o)) #define RESULT(o) ((result*)val_data(o)) typedef struct { MYSQL *m; value conv_date; value conv_bytes; value conv_string; } connection; DEFINE_KIND(k_connection); DEFINE_KIND(k_result); static void error( MYSQL *m, const char *msg ) { buffer b = alloc_buffer(msg); buffer_append(b," "); buffer_append(b,mysql_error(m)); bfailure(b); } // --------------------------------------------------------------- // Result /**

Result

**/ #undef CONV_FLOAT typedef enum { CONV_INT, CONV_STRING, CONV_FLOAT, CONV_BINARY, CONV_DATE, CONV_DATETIME, CONV_BOOL } CONV; typedef struct { MYSQL_RES *r; int nfields; CONV *fields_convs; field *fields_ids; MYSQL_ROW current; value conv_date; value conv_string; value conv_bytes; } result; static void free_result( value o ) { result *r = RESULT(o); mysql_free_result(r->r); } /** result_set_conv_date : 'result -> function:1 -> void Set the function that will convert a Date or DateTime string to the corresponding value. **/ static value result_set_conv_date( value o, value c ) { val_check_function(c,1); if( val_is_int(o) ) return val_true; val_check_kind(o,k_result); RESULT(o)->conv_date = c; return val_true; } /** result_get_length : 'result -> int Return the number of rows returned or affected **/ static value result_get_length( value o ) { if( val_is_int(o) ) return o; val_check_kind(o,k_result); return alloc_int( (int)mysql_num_rows(RESULT(o)->r) ); } /** result_get_nfields : 'result -> int Return the number of fields in a result row **/ static value result_get_nfields( value o ) { val_check_kind(o,k_result); return alloc_int(RESULT(o)->nfields); } /** result_get_fields_names : 'result -> string array Return the fields names corresponding results columns **/ static value result_get_fields_names( value o ) { result *r; value a; int k; MYSQL_FIELD *fields; val_check_kind(o,k_result); r = RESULT(o); fields = mysql_fetch_fields(r->r); a = alloc_array(r->nfields); for(k=0;knfields;k++) val_array_ptr(a)[k] = alloc_string(fields[k].name); return a; } /** result_next : 'result -> object? Return the next row if available. A row is represented as an object, which fields have been converted to the corresponding Neko value (int, float or string). For Date and DateTime you can specify your own conversion function using [result_set_conv_date]. By default they're returned as plain strings. Additionally, the TINYINT(1) will be converted to either true or false if equal to 0. **/ static value result_next( value o ) { result *r; unsigned long *lengths = NULL; MYSQL_ROW row; val_check_kind(o,k_result); r = RESULT(o); row = mysql_fetch_row(r->r); if( row == NULL ) return val_null; { int i; value cur = alloc_object(NULL); r->current = row; for(i=0;infields;i++) if( row[i] != NULL ) { value v; switch( r->fields_convs[i] ) { case CONV_INT: v = alloc_best_int(atoi(row[i])); break; case CONV_STRING: v = alloc_string(row[i]); if( r->conv_string != NULL ) v = val_call1(r->conv_string,v); break; case CONV_BOOL: v = alloc_bool( *row[i] != '0' ); break; case CONV_FLOAT: v = alloc_float(atof(row[i])); break; case CONV_BINARY: if( lengths == NULL ) { lengths = mysql_fetch_lengths(r->r); if( lengths == NULL ) val_throw(alloc_string("mysql_fetch_lengths")); } v = copy_string(row[i],lengths[i]); if( r->conv_bytes != NULL ) v = val_call1(r->conv_bytes,v); break; case CONV_DATE: if( r->conv_date == NULL ) v = alloc_string(row[i]); else { struct tm t; sscanf(row[i],"%4d-%2d-%2d",&t.tm_year,&t.tm_mon,&t.tm_mday); t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; t.tm_isdst = -1; t.tm_year -= 1900; t.tm_mon--; v = val_call1(r->conv_date,alloc_int32((int)mktime(&t))); } break; case CONV_DATETIME: if( r->conv_date == NULL ) v = alloc_string(row[i]); else { struct tm t; sscanf(row[i],"%4d-%2d-%2d %2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_isdst = -1; t.tm_year -= 1900; t.tm_mon--; v = val_call1(r->conv_date,alloc_int32((int)mktime(&t))); } break; default: v = val_null; break; } alloc_field(cur,r->fields_ids[i],v); } return cur; } } /** result_get : 'result -> n:int -> string Return the [n]th field of the current row **/ static value result_get( value o, value n ) { result *r; const char *s; val_check_kind(o,k_result); val_check(n,int); r = RESULT(o); if( val_int(n) < 0 || val_int(n) >= r->nfields ) neko_error(); if( !r->current ) { result_next(o); if( !r->current ) neko_error(); } s = r->current[val_int(n)]; return alloc_string( s?s:"" ); } /** result_get_int : 'result -> n:int -> int Return the [n]th field of the current row as an integer (or 0) **/ static value result_get_int( value o, value n ) { result *r; const char *s; val_check_kind(o,k_result); val_check(n,int); r = RESULT(o); if( val_int(n) < 0 || val_int(n) >= r->nfields ) neko_error(); if( !r->current ) { result_next(o); if( !r->current ) neko_error(); } s = r->current[val_int(n)]; return alloc_int( s?atoi(s):0 ); } /** result_get_float : 'result -> n:int -> float Return the [n]th field of the current row as a float (or 0) **/ static value result_get_float( value o, value n ) { result *r; const char *s; val_check_kind(o,k_result); val_check(n,int); r = RESULT(o); if( val_int(n) < 0 || val_int(n) >= r->nfields ) neko_error(); if( !r->current ) { result_next(o); if( !r->current ) neko_error(); } s = r->current[val_int(n)]; return alloc_float( s?atof(s):0 ); } static CONV convert_type( enum enum_field_types t, int flags, unsigned int length ) { // FIELD_TYPE_TIME // FIELD_TYPE_YEAR // FIELD_TYPE_NEWDATE // FIELD_TYPE_NEWDATE + 2: // 5.0 MYSQL_TYPE_BIT switch( t ) { case FIELD_TYPE_TINY: if( length == 1 ) return CONV_BOOL; case FIELD_TYPE_SHORT: case FIELD_TYPE_LONG: case FIELD_TYPE_INT24: return CONV_INT; case FIELD_TYPE_LONGLONG: case FIELD_TYPE_DECIMAL: case FIELD_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: case 246: // 5.0 MYSQL_NEW_DECIMAL return CONV_FLOAT; case FIELD_TYPE_BLOB: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: if( (flags & BINARY_FLAG) != 0 ) return CONV_BINARY; return CONV_STRING; case FIELD_TYPE_DATETIME: case FIELD_TYPE_TIMESTAMP: return CONV_DATETIME; case FIELD_TYPE_DATE: return CONV_DATE; case FIELD_TYPE_NULL: case FIELD_TYPE_ENUM: case FIELD_TYPE_SET: //case FIELD_TYPE_VAR_STRING: //case FIELD_TYPE_GEOMETRY: // 5.0 MYSQL_TYPE_VARCHAR default: if( (flags & BINARY_FLAG) != 0 ) return CONV_BINARY; return CONV_STRING; } } static value alloc_result( connection *c, MYSQL_RES *r ) { result *res = (result*)alloc(sizeof(result)); value o = alloc_abstract(k_result,res); int num_fields = mysql_num_fields(r); int i,j; MYSQL_FIELD *fields = mysql_fetch_fields(r); res->r = r; res->conv_date = c->conv_date; res->conv_bytes = c->conv_bytes; res->conv_string = c->conv_string; res->current = NULL; res->nfields = num_fields; res->fields_ids = (field*)alloc_private(sizeof(field)*num_fields); res->fields_convs = (CONV*)alloc_private(sizeof(CONV)*num_fields); for(i=0;ifields_ids[j] == id ) { buffer b = alloc_buffer("Error, same field ids for : "); buffer_append(b,fields[i].name); buffer_append(b,":"); val_buffer(b,alloc_int(i)); buffer_append(b," and "); buffer_append(b,fields[j].name); buffer_append(b,":"); val_buffer(b,alloc_int(j)); buffer_append(b,"."); bfailure(b); } } res->fields_ids[i] = id; res->fields_convs[i] = convert_type(fields[i].type,fields[i].flags,fields[i].length); } val_gc(o,free_result); return o; } // --------------------------------------------------------------- // Connection /**

Connection

**/ /** close : 'connection -> void Close the connection. Any subsequent operation will fail on it **/ static value close( value o ) { val_check_kind(o,k_connection); mysql_close(CNX(o)->m); val_data(o) = NULL; val_kind(o) = NULL; val_gc(o,NULL); return val_true; } /** select_db : 'connection -> string -> void Select the database **/ static value select_db( value o, value db ) { val_check_kind(o,k_connection); val_check(db,string); if( mysql_select_db(CNX(o)->m,val_string(db)) != 0 ) error(CNX(o)->m,"Failed to select database :"); return val_true; } /** request : 'connection -> string -> 'result Execute an SQL request. Exception on error **/ static value request( value o, value r ) { MYSQL_RES *res; connection *c; val_check_kind(o,k_connection); val_check(r,string); c = CNX(o); if( mysql_real_query(c->m,val_string(r),val_strlen(r)) != 0 ) error(c->m,val_string(r)); res = mysql_store_result(c->m); if( res == NULL ) { if( mysql_field_count(c->m) == 0 ) return alloc_int( (int)mysql_affected_rows(c->m) ); else error(c->m,val_string(r)); } return alloc_result(c,res); } /** escape : 'connection -> string -> string Escape the string for inserting into a SQL request **/ static value escape( value o, value s ) { int len; value sout; val_check_kind(o,k_connection); val_check(s,string); len = val_strlen(s) * 2; sout = alloc_empty_string(len); len = mysql_real_escape_string(CNX(o)->m,val_string(sout),val_string(s),val_strlen(s)); if( len < 0 ) { buffer b = alloc_buffer("Unsupported charset : "); buffer_append(b,mysql_character_set_name(CNX(o)->m)); bfailure(b); } val_set_length(sout,len); val_string(sout)[len] = 0; return sout; } /** set_conv_funs : 'connection -> function:1 -> function:1 -> function:1 -> void Set three wrapper methods to be be called when creating a string, a date, and binary data in results **/ static value set_conv_funs( value o, value fstring, value fdate, value fbytes ) { val_check_kind(o,k_connection); val_check_function(fstring,1); val_check_function(fdate,1); val_check_function(fbytes,1); CNX(o)->conv_string = fstring; CNX(o)->conv_date = fdate; CNX(o)->conv_bytes = fbytes; return val_null; } // --------------------------------------------------------------- // Sql static void free_connection( value o ) { mysql_close(CNX(o)->m); } /** connect : { host => string, port => int, user => string, pass => string, socket => string? } -> 'connection Connect to a database using the connection informations **/ static value connect_mysql( value params ) { value host, port, user, pass, socket; val_check(params,object); host = val_field(params,val_id("host")); port = val_field(params,val_id("port")); user = val_field(params,val_id("user")); pass = val_field(params,val_id("pass")); socket = val_field(params,val_id("socket")); val_check(host,string); val_check(port,int); val_check(user,string); val_check(pass,string); if( !val_is_string(socket) && !val_is_null(socket) ) neko_error(); { connection *c = (connection*)alloc(sizeof(connection)); value v; c->m = mysql_init(NULL); c->conv_string = NULL; c->conv_date = NULL; c->conv_bytes = NULL; if( mysql_real_connect(c->m,val_string(host),val_string(user),val_string(pass),NULL,val_int(port),val_is_null(socket)?NULL:val_string(socket),0) == NULL ) { buffer b = alloc_buffer("Failed to connect to mysql server : "); buffer_append(b,mysql_error(c->m)); mysql_close(c->m); bfailure(b); } v = alloc_abstract(k_connection,c); val_gc(v,free_connection); return v; } } // --------------------------------------------------------------- // Registers DEFINE_PRIM_WITH_NAME(connect_mysql,connect,1); DEFINE_PRIM(close,1); DEFINE_PRIM(request,2); DEFINE_PRIM(select_db,2); DEFINE_PRIM(escape,2); DEFINE_PRIM(result_get_length,1); DEFINE_PRIM(result_get_nfields,1); DEFINE_PRIM(result_get_fields_names,1); DEFINE_PRIM(result_next,1); DEFINE_PRIM(result_get,2); DEFINE_PRIM(result_get_int,2); DEFINE_PRIM(result_get_float,2); DEFINE_PRIM(result_set_conv_date,2); DEFINE_PRIM(set_conv_funs,4); /* ************************************************************************ */ neko-2-2-0/libs/ocaml/000077500000000000000000000000001321613172000144655ustar00rootroot00000000000000neko-2-2-0/libs/ocaml/binast.ml000066400000000000000000000122751321613172000163060ustar00rootroot00000000000000(* * Neko Binary AST for OCaml * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Nast type context = { ch : unit IO.output; mutable curfile : string; mutable curline : int; mutable scount : int; strings : (string,int) Hashtbl.t; } let b ctx n = IO.write_byte ctx.ch n let write_ui24 ctx n = IO.write_byte ctx.ch n; IO.write_byte ctx.ch (n lsr 8); IO.write_byte ctx.ch (n lsr 16) let write_string ctx s = try let x = ctx.scount - Hashtbl.find ctx.strings s in if x > 0xFF then raise Not_found; b ctx x; with Not_found -> Hashtbl.replace ctx.strings s ctx.scount; ctx.scount <- ctx.scount + 1; b ctx 0; IO.write_ui16 ctx.ch (String.length s); IO.nwrite ctx.ch s let write_constant ctx = function | True -> b ctx 0 | False -> b ctx 1 | Null -> b ctx 2 | This -> b ctx 3 | Int n -> if n >= 0 && n <= 0xFF then begin b ctx 4; b ctx n; end else begin b ctx 5; IO.write_i32 ctx.ch n; end | Float s -> b ctx 6; write_string ctx s | String s -> b ctx 7; write_string ctx s | Builtin s -> b ctx 8; write_string ctx s | Ident s -> b ctx 9; write_string ctx s let write_op ctx op = b ctx (match op with | "+" -> 0 | "-" -> 1 | "/" -> 2 | "*" -> 3 | "%" -> 4 | "<<" -> 5 | ">>" -> 6 | ">>>" -> 7 | "|" -> 8 | "&" -> 9 | "^" -> 10 | "==" -> 11 | "!=" -> 12 | ">" -> 13 | ">=" -> 14 | "<" -> 15 | "<=" -> 16 | "=" -> 17 | "&&" -> 18 | "||" -> 19 | "++=" -> 20 | "--=" -> 21 | "+=" -> 22 | "-=" -> 23 | "/=" -> 24 | "*=" -> 25 | "%=" -> 26 | "<<=" -> 27 | ">>=" -> 28 | ">>>=" -> 29 | "|=" -> 30 | "&=" -> 31 | "^=" -> 32 | op -> failwith ("Invalid neko ast op " ^ op)) let rec write_expr_opt ctx = function | None -> b ctx 0; | Some e -> b ctx 1; write_expr ctx e and write_expr ctx (e,p) = if p.psource <> ctx.curfile then begin b ctx 0; write_string ctx p.psource; write_ui24 ctx p.pline; ctx.curfile <- p.psource; ctx.curline <- p.pline; end else if p.pline <> ctx.curline then begin b ctx 1; write_ui24 ctx p.pline; ctx.curline <- p.pline; end; match e with | EConst c -> b ctx 2; write_constant ctx c | EBlock el -> let n = List.length el in if n <= 0xFF then begin b ctx 3; b ctx n; end else begin b ctx 4; write_ui24 ctx n; end; List.iter (write_expr ctx) el | EParenthesis e -> b ctx 5; write_expr ctx e; | EField (e,f) -> b ctx 6; write_expr ctx e; write_string ctx f; | ECall (e,el) -> let n = List.length el in if n <= 0xFF then begin b ctx 7; write_expr ctx e; b ctx n; end else begin b ctx 28; write_expr ctx e; write_ui24 ctx n; end; List.iter (write_expr ctx) el; | EArray (e1,e2) -> b ctx 8; write_expr ctx e1; write_expr ctx e2; | EVars vl -> b ctx 9; b ctx (List.length vl); List.iter (fun (v,e) -> write_string ctx v; write_expr_opt ctx e; ) vl; | EWhile (e1,e2,NormalWhile) -> b ctx 10; write_expr ctx e1; write_expr ctx e2; | EWhile (e1,e2,DoWhile) -> b ctx 11; write_expr ctx e1; write_expr ctx e2; | EIf (e1,e2,eo) -> b ctx 12; write_expr ctx e1; write_expr ctx e2; write_expr_opt ctx eo; | ETry (e1,v,e2) -> b ctx 13; write_expr ctx e1; write_string ctx v; write_expr ctx e2; | EFunction (pl,e) -> b ctx 14; b ctx (List.length pl); List.iter (write_string ctx) pl; write_expr ctx e; | EBinop (op,e1,e2) -> b ctx 15; write_op ctx op; write_expr ctx e1; write_expr ctx e2; | EReturn None -> b ctx 16; | EReturn (Some e) -> b ctx 17; write_expr ctx e; | EBreak None -> b ctx 18; | EBreak (Some e) -> b ctx 19; write_expr ctx e; | EContinue -> b ctx 20; | ENext (e1,e2) -> b ctx 21; write_expr ctx e1; write_expr ctx e2; | EObject fl -> let n = List.length fl in if n <= 0xFF then begin b ctx 22; b ctx n; end else begin b ctx 23; write_ui24 ctx n; end; List.iter (fun (f,e) -> write_string ctx f; write_expr ctx e; ) fl; | ELabel l -> b ctx 24; write_string ctx l; | ESwitch (e,cases,eo) -> let n = List.length cases in if n <= 0xFF then begin b ctx 25; b ctx n; end else begin b ctx 26; write_ui24 ctx n; end; write_expr ctx e; List.iter (fun (e1,e2) -> write_expr ctx e1; write_expr ctx e2; ) cases; write_expr_opt ctx eo; | ENeko s -> b ctx 27; write_ui24 ctx (String.length s); IO.nwrite ctx.ch s let write ch e = let ctx = { ch = ch; curfile = ""; curline = -1; scount = 0; strings = Hashtbl.create 0; } in IO.nwrite ctx.ch "NBA\001"; write_expr ctx e neko-2-2-0/libs/ocaml/ml/000077500000000000000000000000001321613172000150755ustar00rootroot00000000000000neko-2-2-0/libs/ocaml/ml/mlast.ml000066400000000000000000000111431321613172000165470ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) type pos = { pmin : int; pmax : int; pfile : string; } type constant = | Int of int | Char of char | Bool of bool | Float of string | String of string | Ident of string | Constr of string | Module of string list * constant type keyword = | Var | If | Else | Function | Try | Catch | Type | Match | Then | When | While | Exception type token = | Eof | Semicolon | Dot | Comma | Quote | BraceOpen | BraceClose | ParentOpen of bool | ParentClose | BracketOpen | BracketClose | Arrow | Vertical | StreamOpen | StreamClose | Const of constant | Keyword of keyword | Binop of string | Comment of string | CommentLine of string type type_path = | EType of type_path option * string list * string | EPoly of string | ETuple of type_path list | EArrow of type_path * type_path type type_decl = | EAbstract | EAlias of type_path | ERecord of (string * bool * type_path) list | EUnion of (string * type_path option) list type arg = | ATyped of arg * type_path | ANamed of string | ATuple of arg list type pattern_decl = | PIdent of string | PConst of constant | PTuple of pattern list | PRecord of (string * pattern) list | PConstr of string list * string * pattern option | PAlias of string * pattern | PTyped of pattern * type_path | PStream of stream_item list * int and pattern = pattern_decl * pos and stream_item = | SPattern of pattern | SExpr of string list * expr | SMagicExpr of pattern * int and expr_decl = | EConst of constant | EBlock of expr list | EField of expr * string | ECall of expr * expr list | EArray of expr * expr | EVar of (string * type_path option) list * expr | EIf of expr * expr * expr option | EFunction of bool * string option * arg list * expr * type_path option | EBinop of string * expr * expr | EUnop of string * expr | ETypeAnnot of expr * type_path | ETupleDecl of expr list | ETypeDecl of string list * string * type_decl | EErrorDecl of string * type_path option | ERecordDecl of (string * expr) list | EMatch of expr * (pattern list * expr option * expr) list | ETry of expr * (pattern list * expr option * expr) list | ETupleGet of expr * int | EApply of expr * expr list | EWhile of expr * expr and expr = expr_decl * pos let pos = snd let null_pos = { pmin = -1; pmax = -1; pfile = "" } let punion p p2 = { pfile = p.pfile; pmin = min p.pmin p2.pmin; pmax = max p.pmax p2.pmax; } let escape_char = function | '\n' -> "\\n" | '\t' -> "\\t" | '\r' -> "\\r" | '\\' -> "\\\\" | c -> if c >= '\032' && c <= '\126' then String.make 1 c else Printf.sprintf "\\%.3d" (int_of_char c) let escape s = let b = Buffer.create (String.length s) in for i = 0 to (String.length s) - 1 do Buffer.add_string b (escape_char s.[i]) done; Buffer.contents b let rec s_constant = function | Int i -> string_of_int i | Float s -> s | Bool b -> if b then "true" else "false" | Char c -> "'" ^ escape_char c ^ "\"" | String s -> "\"" ^ escape s ^ "\"" | Ident s -> s | Constr s -> s | Module (l,c) -> String.concat "." l ^ "." ^ s_constant c let s_path path n = match path with | [] -> n | _ -> String.concat "." path ^ "." ^ n let s_keyword = function | Var -> "var" | If -> "if" | Else -> "else" | Function -> "function" | Try -> "try" | Catch -> "catch" | Type -> "type" | Match -> "match" | Then -> "then" | When -> "when" | While -> "while" | Exception -> "exception" let s_token = function | Eof -> "" | Semicolon -> ";" | Dot -> "." | Comma -> "," | Quote -> "'" | BraceOpen -> "{" | BraceClose -> "}" | ParentOpen _ -> "(" | ParentClose -> ")" | BracketOpen -> "[" | BracketClose -> "]" | StreamOpen -> "[<" | StreamClose -> ">]" | Arrow -> "->" | Vertical -> "|" | Const c -> s_constant c | Keyword k -> s_keyword k | Binop s -> s | Comment s -> "/*" ^ s ^ "*/" | CommentLine s -> "//" ^ s neko-2-2-0/libs/ocaml/ml/mllexer.mll000066400000000000000000000153061321613172000172600ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) { open Mlast open Lexing type error_msg = | Invalid_character of char | Unterminated_string | Unclosed_comment | Invalid_escaped_character of int | Invalid_escape exception Error of error_msg * pos let error_msg = function | Invalid_character c when int_of_char c > 32 && int_of_char c < 128 -> Printf.sprintf "Invalid character '%c'" c | Invalid_character c -> Printf.sprintf "Invalid character 0x%.2X" (int_of_char c) | Unterminated_string -> "Unterminated string" | Unclosed_comment -> "Unclosed comment" | Invalid_escaped_character n -> Printf.sprintf "Invalid escaped character %d" n | Invalid_escape -> "Invalid escape sequence" let cur_file = ref "" let all_lines = Hashtbl.create 0 let lines = ref [] let buf = Buffer.create 100 let error e pos = raise (Error (e,{ pmin = pos; pmax = pos; pfile = !cur_file })) let keywords = let h = Hashtbl.create 3 in List.iter (fun k -> Hashtbl.add h (s_keyword k) k) [Var;If;Else;Function;Try;Catch;Type;Match;Then;When;While;Exception] ; h let init file = cur_file := file; lines := [] let save_lines() = Hashtbl.replace all_lines !cur_file !lines let save() = save_lines(); !cur_file let restore file = save_lines(); cur_file := file; lines := Hashtbl.find all_lines file let newline lexbuf = lines := (lexeme_end lexbuf) :: !lines let find_line p lines = let rec loop n delta = function | [] -> n , p - delta | lp :: l when lp > p -> n , p - delta | lp :: l -> loop (n+1) lp l in loop 1 0 lines let get_error_line p = let lines = List.rev (try Hashtbl.find all_lines p.pfile with Not_found -> []) in let l, _ = find_line p.pmin lines in l let get_error_pos printer p = if p.pmin = -1 then "(unknown)" else let lines = List.rev (try Hashtbl.find all_lines p.pfile with Not_found -> []) in let l1, p1 = find_line p.pmin lines in let l2, p2 = find_line p.pmax lines in if l1 = l2 then begin let s = (if p1 = p2 then Printf.sprintf " %d" p1 else Printf.sprintf "s %d-%d" p1 p2) in Printf.sprintf "%s character%s" (printer p.pfile l1) s end else Printf.sprintf "%s lines %d-%d" (printer p.pfile l1) l1 l2 let reset() = Buffer.reset buf let contents() = Buffer.contents buf let store lexbuf = Buffer.add_string buf (lexeme lexbuf) let add c = Buffer.add_string buf c let mk_tok t pmin pmax = t , { pfile = !cur_file; pmin = pmin; pmax = pmax } let mk lexbuf t = mk_tok t (lexeme_start lexbuf) (lexeme_end lexbuf) let mk_ident lexbuf = let s = lexeme lexbuf in mk lexbuf (try Keyword (Hashtbl.find keywords s) with Not_found -> Const (Ident s)) } let ident = ['a'-'z' '_'] ['a'-'z' 'A'-'Z' '0'-'9' '_']* let modident = ['A'-'Z'] ['a'-'z' 'A'-'Z' '0'-'9' '_']* let binop = ['!' '=' '*' '/' '<' '>' '&' '|' '^' '%' '+' ':' '-'] let number = ['0'-'9'] let space = [' ' '\r' '\t'] rule token = parse | eof { mk lexbuf Eof } | ';' { mk lexbuf Semicolon } | '.' { mk lexbuf Dot } | ',' { mk lexbuf Comma } | '{' { mk lexbuf BraceOpen } | '}' { mk lexbuf BraceClose } | space+ '(' { mk lexbuf (ParentOpen true) } | '(' { mk lexbuf (ParentOpen false) } | ')' { mk lexbuf ParentClose } | '[' { mk lexbuf BracketOpen } | ']' { mk lexbuf BracketClose } | '\'' { mk lexbuf Quote } | '|' { mk lexbuf Vertical } | space+ { token lexbuf } | '\n' { newline lexbuf; token lexbuf } | "0x" ['0'-'9' 'a'-'f' 'A'-'F']+ | number+ { mk lexbuf (Const (Int (int_of_string (lexeme lexbuf)))) } | number+ '.' number* | '.' number+ { mk lexbuf (Const (Float (lexeme lexbuf))) } | "true" { mk lexbuf (Const (Bool true)) } | "false" { mk lexbuf (Const (Bool false)) } | '"' { reset(); let pmin = lexeme_start lexbuf in let pmax = (try string lexbuf with Exit -> error Unterminated_string pmin) in mk_tok (Const (String (contents()))) pmin pmax; } | "/*" { reset(); let pmin = lexeme_start lexbuf in let pmax = (try comment lexbuf with Exit -> error Unclosed_comment pmin) in mk_tok (Comment (contents())) pmin pmax; } | "'\\n'" { mk lexbuf (Const (Char '\n')) } | "'\\t'" { mk lexbuf (Const (Char '\t')) } | "'\\r'" { mk lexbuf (Const (Char '\r')) } | "'\\''" { mk lexbuf (Const (Char '\'')) } | "'\\\\'" { mk lexbuf (Const (Char '\\')) } | "'\\\"'" | "'\\t'" { mk lexbuf (Const (Char '"')) } | '\'' [^'\\'] '\'' { mk lexbuf (Const (Char (lexeme lexbuf).[1])) } | "\'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] '\'' { let s = String.sub (lexeme lexbuf) 2 3 in let n = int_of_string s in let c = (try char_of_int n with _ -> error (Invalid_escaped_character n) (lexeme_start lexbuf)) in mk lexbuf (Const (Char c)) } | "//" [^'\n']* { let s = lexeme lexbuf in let n = (if s.[String.length s - 1] = '\r' then 3 else 2) in mk lexbuf (CommentLine (String.sub s 2 ((String.length s)-n))) } | "[<" { mk lexbuf StreamOpen } | ">]" { mk lexbuf StreamClose } | "->" { mk lexbuf Arrow } | binop binop? | ">>>" | "===" | "!==" | "or" | "and" | "xor" { mk lexbuf (Binop (lexeme lexbuf)) } | ident { mk_ident lexbuf } | modident { mk lexbuf (Const (Constr (lexeme lexbuf))) } | _ { error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_start lexbuf) } and comment = parse | eof { raise Exit } | '\r' { comment lexbuf } | '\n' { newline lexbuf; store lexbuf; comment lexbuf } | "*/" { lexeme_end lexbuf } | '*' { store lexbuf; comment lexbuf } | [^'*' '\n' '\r']+ { store lexbuf; comment lexbuf } and string = parse | eof { raise Exit } | '\n' { newline lexbuf; store lexbuf; string lexbuf } | "\\\"" { add "\""; string lexbuf } | "\\\\" { add "\\"; string lexbuf } | "\\n" { add "\n"; string lexbuf } | "\\t" { add "\t"; string lexbuf } | "\\r" { add "\r"; string lexbuf } | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] { let i = int_of_string (String.sub (lexeme lexbuf) 1 3) in if i >= 256 then error (Invalid_escaped_character i) (lexeme_start lexbuf); add (String.make 1 (char_of_int i)); string lexbuf } | '\\' { error Invalid_escape (lexeme_start lexbuf) } | '"' { lexeme_end lexbuf } | [^'"' '\\' '\n']+ { store lexbuf; string lexbuf } neko-2-2-0/libs/ocaml/ml/mlmain.ml000066400000000000000000000041631321613172000167100ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) let nekoml file ch out = IO.close_in ch; Mltyper.verbose := !Plugin.verbose; Mlneko.verbose := !Plugin.verbose; let path = ExtString.String.nsplit (Filename.dirname file) "/" in let modname = path @ [String.capitalize (Filename.chop_extension (Filename.basename file))] in let ctx = Mltyper.context (!Plugin.paths) in ignore(Mltyper.load_module ctx modname Mlast.null_pos); Hashtbl.iter (fun m (e,deps,idents) -> let e = Mlneko.generate e deps idents m in let file = String.concat "/" m ^ ".neko" in let ch = (if m = modname then out else IO.output_channel (open_out file)) in let ctx = Printer.create ch in Printer.print ctx e; IO.close_out ch ) (Mltyper.modules ctx) let nekoml_exn = function | Mllexer.Error (m,p) -> Plugin.exn_infos "syntax error" (Mllexer.error_msg m) (fun f -> Mllexer.get_error_pos f p) | Mlparser.Error (m,p) -> Plugin.exn_infos "parse error" (Mlparser.error_msg m) (fun f -> Mllexer.get_error_pos f p) | Mltyper.Error (m,p) -> Plugin.exn_infos "type error" (Mltyper.error_msg m) (fun f -> Mllexer.get_error_pos f p) | Lexer.Error (m,p) -> Plugin.exn_infos "syntax error" (Lexer.error_msg m) (fun f -> Lexer.get_error_pos f p) | Parser.Error (m,p) -> Plugin.exn_infos "parse error" (Parser.error_msg m) (fun f -> Lexer.get_error_pos f p) | e -> raise e ;; Plugin.register "nml" "neko" nekoml nekoml_exn neko-2-2-0/libs/ocaml/ml/mlmatch.ml000066400000000000000000000230271321613172000170600ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) (* ----- We're using the same algorithm and source code as described in chapter 5.2.4 of "The Zinc experiment" by X. Leroy ( http://citeseer.ist.psu.edu/leroy90zinc.html ) also described in "The Implementation of Functional Programming Languages" by Simon Peyton Jones, in the Chapter 5 by Philip Wadler ( http://research.microsoft.com/Users/simonpj/Papers/slpj-book-1987/ ) *) open Mlast open Mltype type complete = | Total | Partial | Dubious type lambda = match_op type matching = (pattern list * lambda) list * lambda list let fully_matched_ref = ref (fun cl -> false) let error_ref = ref (fun (msg : string) (p : pos) -> assert false; ()) let error msg p = !error_ref msg p; assert false let failure = MFailure let handle l1 l2 = if l2 = MFailure then l1 else if l1 = MFailure then l2 else MHandle (l1,l2) let exec e = MExecute (e,true) let cond path lambdas = MConstants (path,lambdas) let rec switch path lambdas = match lambdas with | [TVoid,m1] -> m1 | (TVoid,m1) :: l -> MNext (m1, switch path l) | _ -> MSwitch (path,lambdas) let ewhen e e2 = MWhen (e,e2) let rec bind v p = function | MBind (v2,p2,m) -> MBind (v2,p2,bind v p m) | act -> if v = "_" then act else MBind (v,p,act) let rec junk p k = function | MBind (v,m,m2) -> MBind (v,m,junk p k m2) | act -> if k = 0 then act else MJunk (p,k,act) let rec stream_pattern (p,pos) = (match p with | PIdent i -> PConst (Ident i) | PConst c -> PConst c | PTuple pl -> PTuple (List.map stream_pattern pl) | PRecord pr -> PRecord (List.map (fun (s,p) -> s , stream_pattern p) pr) | PConstr (path,name,param) -> PConstr (path,name,match param with None -> None | Some p -> Some (stream_pattern p)) | PAlias (s,p) -> PAlias (s,stream_pattern p) | PTyped (p,t) -> PTyped (stream_pattern p,t) | PStream (s,k) -> PStream (s,k)) , pos let rec have_when = function | MWhen _ -> true | MBind (_,_,e) -> have_when e | _ -> false let t_const = function | Int i -> TInt i | String s -> TString s | Float f -> TFloat f | Char c -> TChar c | Ident i -> TIdent i | Bool b -> TBool b | _ -> assert false let total p1 p2 = match p1 , p2 with | Total , Total -> Total | Partial , _ -> Partial | _ , Partial -> Partial | _ , _ -> Dubious let partial p1 p2 = match p1 , p2 with | Total , _ -> p2 | _ , Total -> Total | _ , _ -> Dubious let rec start_by_a_variable (p,_) = match p with | PAlias (_,p) -> start_by_a_variable p | PIdent _ -> true | _ -> false let add_to_match (casel,pathl) cas = cas :: casel , pathl let make_constant_match path cas = match path with | [] -> assert false | _ :: pathl -> [cas] , pathl let make_token_match path cas = [cas] , path let make_construct_match tuple nargs pathl cas = match pathl with | [] -> assert false | path :: pathl -> let rec make_path i = if i >= nargs then pathl else let k = if tuple then MTuple (path,i) else MField (path,i) in k :: make_path (i + 1) in [cas] , make_path 0 let make_record_match args pathl cas = match pathl with | [] -> assert false | path :: pathl -> [cas] , List.fold_left (fun acc (f,_) -> MRecordField (path,f) :: acc) pathl (List.rev args) let add_to_division make_match divlist key cas = try let matchref = List.assoc key divlist in matchref := add_to_match !matchref cas; divlist with Not_found -> (key , ref (make_match cas)) :: divlist let always_add make_match divlist cas = (TVoid , ref (make_match cas)) :: divlist let lines_of_matching = fst let fully_matched cl = !fully_matched_ref cl let flatten = function | None -> [] | Some (PTuple l,_) -> l | Some p -> [p] let split_matching (m:matching) = match m with | _ , [] -> assert false | casel, (curpath :: endpathl as pathl) -> let rec split_rec = function | ((PTyped (p,_),_) :: l , act) :: rest -> split_rec ((p :: l, act) :: rest) | ((PAlias (var,p),_) :: l , act) :: rest -> split_rec ((p :: l, bind var curpath act) :: rest) | ((PIdent var,_) :: l , act) :: rest -> let vars , others = split_rec rest in add_to_match vars (l, bind var curpath act) , others | casel -> ([] , endpathl) , (casel , pathl) in split_rec casel let divide_matching (m:matching) = match m with | _ , [] -> assert false | casel , (curpath :: tailpathl as pathl) -> let rec divide_rec = function | [] -> [] , [] , ([] , pathl) | ([],_) :: _ -> assert false | ((PTyped (p,_),_) :: l , act) :: rest -> divide_rec ((p :: l , act) :: rest) | ((PAlias (var,p),_) :: l, act) :: rest -> divide_rec ((p :: l , bind var curpath act) :: rest) | ((PConst c,_) :: l, act) :: rest -> let constant , constrs, others = divide_rec rest in add_to_division (make_constant_match pathl) constant (t_const c) (l, act), constrs , others | ((PConstr (path,c,arg),_) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in let args = flatten arg in constants , add_to_division (make_construct_match false (List.length args) pathl) constrs (TModule (path,TConstr c)) (args @ l,act) , others | ((PTuple [],_) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in constants , add_to_division (make_constant_match pathl) constrs TVoid (l, act), others | ((PTuple args,_) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in constants , add_to_division (make_construct_match true (List.length args) pathl) constrs TVoid (args @ l,act) , others | ((PRecord args,_) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in constants , add_to_division (make_record_match args pathl) constrs TVoid (List.map snd args @ l,act) , others | ((PStream ((SPattern p :: sl),k),pp) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in constants , always_add (make_token_match ((MToken (curpath,k)) :: pathl)) constrs (stream_pattern p :: (PStream (sl,k+1),pp) :: l, act) , others | ((PStream ((SMagicExpr ((PTuple _,_) as p,e) :: sl),k),pp) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in let bind = MExecute (mk (TConst (TIdent "@tmp")) t_void pp,false) in constants , always_add (make_token_match (junk curpath k (MExecute (Obj.magic e,false)) :: bind :: pathl)) constrs ((PConst (Ident "@tmp"),pp) :: stream_pattern p :: (PStream (sl,0),pp) :: l, act) , others | ((PStream ((SMagicExpr (p,e) :: sl),k),pp) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in constants , always_add (make_token_match (junk curpath k (MExecute (Obj.magic e,false)) :: pathl)) constrs (stream_pattern p :: (PStream (sl,0),pp) :: l, act) , others | ((PStream ([],k),pp) :: l,act) :: rest -> let constants , constrs, others = divide_rec rest in constants , always_add (make_constant_match pathl) constrs (l, junk curpath k act) , others | casel -> [] , [] , (casel,pathl) in divide_rec casel let rec conquer_divided_matching = function | [] -> [], Total, [] | (key, matchref) :: rest -> let l1, p1, u1 = conquer_matching !matchref in let l2, p2, u2 = conquer_divided_matching rest in (key , l1) :: l2 , total p1 p2 , u1 @ u2 and conquer_matching (m:matching) = match m with | [] , _ -> failure , Partial , [] | ([],action) :: rest , k -> if have_when action then let a , p , r = conquer_matching (rest,k) in handle action a , p , r else action , Total, rest | _ , [] -> assert false | (p :: _,_) :: _ , _ :: _ when start_by_a_variable p -> let vars , rest = split_matching m in let l1, p1, u1 = conquer_matching vars in let l2, p2, u2 = conquer_matching rest in if p1 = Total then l1 , Total, u1 @ lines_of_matching rest else handle l1 l2 , (if p2 = Total then Total else Dubious) , u1 @ u2 | _ , path :: _ -> match divide_matching m with | [] , [] , vars -> conquer_matching vars | consts , [] , vars -> let l1, _ , u1 = conquer_divided_matching consts in let l2, p2, u2 = conquer_matching vars in handle (cond path l1) l2 , p2 , u1 @ u2 | [] , constrs , vars -> let l1, p1, u1 = conquer_divided_matching constrs in let l2, p2, u2 = conquer_matching vars in if fully_matched (List.map fst constrs) && p1 = Total then switch path l1 , Total , u1 @ lines_of_matching vars else handle (switch path l1) l2 , partial p1 p2 , u1 @ u2 | _ -> assert false let make (cases : (pattern list * texpr option * texpr) list) p = let cases = List.concat (List.map (fun (pl,wcond,e) -> let e = exec e in let e = (match wcond with None -> e | Some e2 -> ewhen e2 e) in List.map (fun p -> [p] , e) pl ) cases) in let m = cases , [MRoot] in let lambda, partial, unused = conquer_matching m in (match unused with | [] -> () | ([] , _ ) :: _ -> error "Some pattern are never matched" p | ((_,p) :: _ , _) :: _ -> error "This pattern is never matched" p); partial <> Total , lambda neko-2-2-0/libs/ocaml/ml/mlneko.ml000066400000000000000000000360231321613172000167200ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast open Mltype type comparison = | Native | Structural type context = { module_name : string; mutable counter : int; mutable refvars : (string,unit) PMap.t; } let verbose = ref false let gen_label ctx = let c = ctx.counter in ctx.counter <- ctx.counter + 1; "l" ^ string_of_int c let gen_variable ctx = let c = ctx.counter in ctx.counter <- ctx.counter + 1; "v" ^ string_of_int c let module_name m = "@" ^ String.concat "_" m let builtin name = EConst (Builtin name) , Ast.null_pos let ident name = EConst (Ident name) , Ast.null_pos let int n = EConst (Int n) , Ast.null_pos let null = EConst Null , Ast.null_pos let core s p = EField ((EConst (Ident (module_name ["Core"])),p),s) , p let pos (p : Mlast.pos) = { pmin = p.Mlast.pmin; pmax = p.Mlast.pmax; pfile = p.Mlast.pfile; } let rec is_fun t = match t.texpr with | TNamed (_,_,t) | TLink t -> is_fun t | TPoly | TMono _ | TFun _ -> true | _ -> false let rec call ret f args p = match f with | EConst (Builtin _) , _ -> ECall (f,args) , p | _ -> match args with | a :: b :: c :: d :: x :: l -> let app = ECall ((EConst (Builtin "apply"),p),[f;a;b;c;d]) , p in call ret app (x :: l) p | _ -> if is_fun ret then ECall ((EConst (Builtin "apply"),p),f :: args) , p else ECall (f,args) , p let array args p = ECall ((EConst (Builtin "array"),p),args) , p let block e = match e with | EBlock _ , _ -> e | _ -> EBlock [e] , snd e let rec arity t = match t.texpr with | TAbstract -> 0 | TTuple tl -> List.length tl | TLink t -> arity t | _ -> 1 let comparison t = match tlinks true t with | TNamed (["int"],[],_) | TNamed (["char"],[],_) | TNamed (["float"],[],_) | TNamed (["string"],[],_) -> Native | _ -> Structural let rec gen_constant ctx c p = (match c with | TVoid -> EConst Null | TInt n when n < 0 -> EBinop ("-",int 0, int (-n)) | TInt n -> EConst (Int n) | TFloat s -> EConst (Float s) | TChar c -> EConst (Int (int_of_char c)) | TString s -> EConst (String s) | TIdent s -> if PMap.mem s ctx.refvars then EArray ((EConst (Ident s),null_pos),int 0) else EConst (Ident s) | TBool true -> EConst True | TBool false -> EConst False | TConstr "[]" | TModule (["Core"],TConstr "[]") -> fst (core "@empty" p) | TConstr "::" | TModule (["Core"],TConstr "::") -> fst (core "@cons" p) | TConstr s -> EConst (Ident s) | TModule ([],c) -> fst (gen_constant ctx c p) | TModule (m,c) -> EField ( (EConst (Ident (module_name m)),p) , (match c with TConstr x -> x | TIdent s -> s | _ -> assert false)) ) , p type match_context = { ctx : context; h : (match_op , string) Hashtbl.t; out : string; pos : Ast.pos; mutable next : string; mutable first : bool; } let no_label = "" let rec gen_match_rec mctx fail m = try ident (Hashtbl.find mctx.h m) with Not_found -> let p = mctx.pos in let ctx = mctx.ctx in let gen_rec = gen_match_rec mctx in match m with | MFailure -> let label = if mctx.first && mctx.next <> no_label then mctx.next else fail in if label = no_label then EBlock [] , p else call t_void (builtin "goto") [ident label] p | MHandle (m1,m2) -> let label = gen_label ctx in let m1 = gen_rec label m1 in let m2 = gen_rec fail m2 in EBlock [m1; ELabel label, p; m2] , p | MRoot -> assert false | MExecute (e,b) -> if not b then begin let ematch = EBinop ("==" , ident "@exc" , core "Stream_matching" p) , p in let reraise = EIf ( ematch , gen_rec fail MFailure, Some(ECall (builtin "throw", [ident "@exc"]) , p) ) , p in mctx.first <- false; match e.edecl with | TConst _ -> gen_expr ctx e | _ -> ETry (gen_expr ctx e, "@exc" , reraise ) , p end else begin mctx.first <- true; let out = call t_void (builtin "goto") [ident mctx.out] p in EBlock [gen_expr ctx e;out] , p end; | MConstants (m,[TIdent v,m1]) -> let m = gen_rec fail m in EBlock [ EVars [v, Some m] , p; gen_rec fail m1 ] , p | MConstants (m,cl) -> let e = gen_rec fail m in let v = gen_variable ctx in let exec = List.fold_left (fun acc (c,m) -> let test = EBinop ("==", ident v, gen_constant ctx c p) , p in let exec = gen_rec fail m in EIf (test, exec, Some acc) , p ) (gen_rec fail MFailure) (List.rev cl) in EBlock [ EVars [v, Some e] , p; exec ] , p | MRecordField (m,f) -> EField (gen_rec fail m, f) , p | MTuple (m,n) -> EArray (gen_rec fail m, int n) , p | MField (m,n) -> EArray (gen_rec fail m, int (n + 2)) , p | MNext (m1,m2) -> let old = mctx.next in let label = gen_label ctx in mctx.next <- label; let m1 = gen_rec fail m1 in mctx.next <- old; let m2 = gen_rec fail m2 in EBlock [m1; ELabel label, p; m2] , p | MSwitch (m,cl) -> let e = gen_rec fail m in let v = gen_variable ctx in let exec = List.fold_left (fun acc (c,m) -> let test = EBinop ("==", ident v, gen_constant ctx c p) , p in let exec = gen_rec fail m in EIf (test, exec, Some acc) , p ) (gen_rec fail MFailure) (List.rev cl) in EBlock [ EVars [v, Some (EArray (e,int 0),p)] , p; exec; ] , p | MBind (v,m1,m2) -> let e1 = gen_rec fail m1 in Hashtbl.add mctx.h m1 v; let e2 = gen_rec fail m2 in Hashtbl.remove mctx.h m1; EBlock [(EVars [v, Some e1] , p); e2] , p | MWhen (e,m) -> let e = gen_expr ctx e in let m = gen_rec fail m in let fail = gen_rec fail MFailure in EIf (e,m,Some fail) , p | MToken (m,n) -> call t_void (core "stream_token" p) [gen_rec fail m; int n] p | MJunk (m,n,m2) -> let m = gen_rec fail m in mctx.first <- false; EBlock [ call t_void (core "stream_junk" p) [m; int n] p; gen_rec fail m2 ] , p and gen_matching ctx v m p stream out = let mctx = { ctx = ctx; h = Hashtbl.create 0; pos = p; out = out; first = stream; next = no_label; } in let label = (if stream then gen_label ctx else no_label) in Hashtbl.add mctx.h MRoot v; let e = gen_match_rec mctx label m in if stream then begin let vpos = gen_variable ctx in let stream_pos = ECall (core "stream_pos" p, [ident v]) , p in let test = EBinop ("==", ident vpos , stream_pos) , p in let exc = ECall (builtin "throw",[EIf (test, core "Stream_matching" p , Some (core "Stream_error" p)) , p]) , p in EBlock [EVars [vpos , Some stream_pos] , p; e; ELabel label , p; exc] , p end else e and gen_match ctx e m stream p = let out = gen_label ctx in let v = gen_variable ctx in let m = gen_matching ctx v m p stream out in let m = ENext ((EVars [v,Some e],p),m) , p in EBlock [m; ELabel out , p] , p and gen_constructor ctx tname c t p = let field = ident c in let printer = EConst (Ident (tname ^ "__string")) , p in let val_type t = match arity t with | 0 -> let make = array [null;printer] p in ENext ((EBinop ("=" , field, make) ,p) , (EBinop("=" , (EArray (field,int 0),p) , field) , p)) , p | n -> let args = Array.to_list (Array.init n (fun n -> "p" ^ string_of_int n)) in let build = array (field :: printer :: List.map (fun a -> EConst (Ident a) , p) args) p in let func = EFunction (args, (EBlock [EReturn (Some build),p] , p)) , p in EBinop ("=" , field , func ) , p in let export = EBinop ("=", (EField (ident ctx.module_name,c),p) , field) , p in ENext (val_type t , export) , p and gen_type_printer ctx c t = let printer = mk (TConst (TModule (["Core"],TIdent "@print_union"))) t_void Mlast.null_pos in let e = mk (TCall (printer,[ mk (TConst (TString c)) t_string Mlast.null_pos; mk (TConst (TIdent "v")) t_void Mlast.null_pos ])) t_string Mlast.null_pos in e and gen_type ctx name t p = match t.texpr with | TAbstract | TMono _ | TPoly | TRecord _ | TTuple _ | TFun _ | TNamed (_,_,{ texpr = TNamed _ }) -> EBlock [] , p | TLink t -> gen_type ctx name t p | TNamed (name,_,t) -> let rec loop = function | [] -> assert false | [x] -> x | _ :: l -> loop l in gen_type ctx (loop name) t p | TUnion (_,constrs) -> let cmatch = gen_match ctx (ident "v") (MSwitch (MRoot,List.map (fun (c,t) -> let e = gen_type_printer ctx c t in TConstr c , MExecute (e,true) ) constrs)) false p in let printer = EFunction (["v"], cmatch) , p in let regs = List.map (fun (c,t) -> gen_constructor ctx name c t p) constrs in EBlock ((EVars [name ^ "__string",Some printer],p) :: regs) , p and gen_binop ctx op e1 e2 p = let compare op = let cmp = ECall (core "@compare" p,[gen_expr ctx e1; gen_expr ctx e2]) , p in EBinop (op , cmp , int 0) , p in let make op = EBinop (op,gen_expr ctx e1,gen_expr ctx e2) , p in let builtin op = ECall (builtin op,[gen_expr ctx e1; gen_expr ctx e2]) , p in match op with | "and" -> make "&" | "or" -> make "|" | "xor" -> make "^" | "==" | "!=" | ">" | "<" | ">=" | "<=" -> (match comparison e1.etype with | Structural -> compare op | Native -> make op) | "===" -> EBinop ("==", builtin "pcompare" , int 0) , p | "!==" -> EBinop ("!=" , builtin "pcompare" , int 0) , p | ":=" -> (match e1.edecl with | TField _ -> make "=" | TArray (a,i) -> ECall (core "@aset" p,[gen_expr ctx a; gen_expr ctx i; gen_expr ctx e2]) , p | _ -> EBinop ("=",(EArray (gen_expr ctx e1,int 0),pos e1.epos),gen_expr ctx e2) , p) | _ -> make op and gen_expr ctx e = let p = pos e.epos in match e.edecl with | TConst c -> gen_constant ctx c p | TBlock el -> EBlock (gen_block ctx el p) , p | TParenthesis e -> EParenthesis (gen_expr ctx e) , p | TCall ({ edecl = TConst (TIdent "neko") },[{ edecl = TConst (TString s) }]) | TCall ({ edecl = TConst (TModule ([],TIdent "neko")) },[{ edecl = TConst (TString s) }]) | TCall ({ edecl = TConst (TModule (["Core"],TIdent "neko")) },[{ edecl = TConst (TString s) }]) -> let ch = IO.input_string (String.concat "\"" (ExtString.String.nsplit s "'")) in let file = "neko@" ^ p.pfile in Parser.parse (Lexing.from_function (fun s p -> try IO.input ch s 0 p with IO.No_more_input -> 0)) file | TCall (f,el) -> let f = gen_expr ctx f in call e.etype f (List.map (gen_expr ctx) el) p | TField (e,s) -> EField (gen_expr ctx e, s) , p | TArray (e1,e2) -> let e1 = gen_expr ctx e1 in ECall (core "@aget" p,[e1;gen_expr ctx e2]) , p | TVar ([v],e) -> ctx.refvars <- PMap.remove v ctx.refvars; EVars [v , Some (gen_expr ctx e)] , p | TVar (vl,e) -> let n = ref (-1) in EVars (("@tmp" , Some (gen_expr ctx e)) :: List.map (fun v -> ctx.refvars <- PMap.remove v ctx.refvars; incr n; v , Some (EArray (ident "@tmp",int !n),p) ) vl) , p | TIf (e,e1,e2) -> let e = gen_expr ctx e in let e1 = gen_expr ctx e1 in EIf (e, e1, match e2 with None -> None | Some e2 -> Some (gen_expr ctx e2)) , p | TWhile (e1,e2) -> let e1 = gen_expr ctx e1 in let e2 = gen_expr ctx e2 in EWhile (e1, e2, NormalWhile) , p | TFunction (_,"_",params,e) -> EFunction (List.map fst params,block (gen_expr ctx e)) , p | TFunction (false,name,params,e) -> EVars [name , Some (EFunction (List.map fst params,block (gen_expr ctx e)) , p)] , p | TFunction _ -> EBlock [gen_functions ctx [e] p] , p | TBinop (op,e1,e2) -> gen_binop ctx op e1 e2 p | TTupleDecl tl -> array (List.map (gen_expr ctx) tl) p | TTypeDecl t -> gen_type ctx "" t p | TMut e -> gen_expr ctx (!e) | TRecordDecl fl -> EObject (("__string", core "@print_record" p) :: List.map (fun (s,e) -> s , gen_expr ctx e) fl) , p | TListDecl el -> (match el with | [] -> array [] p | x :: l -> let x = gen_expr ctx x in array [x; gen_expr ctx { e with edecl = TListDecl l }] p) | TUnop (op,e) -> (match op with | "-" -> EBinop ("-",int 0,gen_expr ctx e) , p | "*" -> EArray (gen_expr ctx e,int 0) , p | "!" -> call t_void (builtin "not") [gen_expr ctx e] p | "&" -> array [gen_expr ctx e] p | _ -> assert false) | TMatch (e,m,stream) -> gen_match ctx (gen_expr ctx e) m stream p | TTupleGet (e,n) -> EArray (gen_expr ctx e,int n) , p | TErrorDecl (e,t) -> let printer = gen_expr ctx (gen_type_printer ctx e t) in let printer = EFunction (["v"], (EBlock [printer],p)) , p in let printer = EVars [e ^ "__string",Some printer] , p in ENext (printer , gen_constructor ctx e e t p) , p | TTry (e,m) -> let out = gen_label ctx in let matching = gen_matching ctx "@exc" m p false out in let reraise = call t_void (builtin "throw") [ident "@exc"] p in let handle = EBlock [matching;reraise;ELabel out , p] , p in ETry (gen_expr ctx e,"@exc",handle) , p and gen_functions ctx fl p = let ell = ref (EVars (List.map (fun e -> match e.edecl with | TFunction (_,"_",params,e) -> "_" , Some (EFunction (List.map fst params,block (gen_expr ctx e)),p) | TFunction (_,name,_,_) -> ctx.refvars <- PMap.add name () ctx.refvars; name , Some (array [null] null_pos) | _ -> assert false ) fl) , null_pos) in List.iter (fun e -> let p = pos e.epos in match e.edecl with | TFunction (_,name,params,e) -> if name <> "_" then begin let e = gen_expr ctx e in let e = EFunction (List.map fst params,block e) , p in let e = EBinop ("=",(EArray (ident name,int 0),p),e) , p in let e = EBlock [e; EBinop ("=",ident name,(EArray (ident name,int 0),p)) , p] , p in ell := ENext (!ell, e) , p; ctx.refvars <- PMap.remove name ctx.refvars; end; | _ -> assert false ) fl; !ell and gen_block ctx el p = let old = ctx.refvars in let ell = ref [] in let rec loop fl = function | [] -> if fl <> [] then ell := gen_functions ctx (List.rev fl) p :: !ell | { edecl = TFunction (true,name,p,f) } as e :: l -> loop (e :: fl) l | { edecl = TMut r } :: l -> loop fl (!r :: l) | x :: l -> if fl <> [] then ell := gen_functions ctx (List.rev fl) p :: !ell; ell := gen_expr ctx x :: !ell; loop [] l in loop [] el; ctx.refvars <- old; List.rev !ell let generate e deps idents m = let m = module_name m in let ctx = { module_name = m; counter = 0; refvars = PMap.empty; } in if !verbose then print_endline ("Generating " ^ m ^ ".neko"); let init = EBinop ("=",ident m,builtin "exports"), null_pos in let deps = List.map (fun m -> let file = String.concat "/" m in let load = ECall ((EField (builtin "loader","loadmodule"),null_pos),[gen_constant ctx (TString file) null_pos;builtin "loader"]) , null_pos in EBinop ("=", ident (module_name m), load ) , null_pos ) deps in let exports = List.map (fun i -> EBinop ("=", (EField (builtin "exports",i),null_pos) , ident i) , null_pos ) idents in match gen_expr ctx e with | EBlock e , p -> EBlock (init :: deps @ e @ exports) , p | e -> EBlock (init :: deps @ e :: exports) , null_pos neko-2-2-0/libs/ocaml/ml/mlparser.ml000066400000000000000000000332711321613172000172620ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Mlast type error_msg = | Unexpected of token | Unclosed of string | Duplicate_default | Unknown_macro of string | Invalid_macro_parameters of string * int exception Error of error_msg * pos let error_msg = function | Unexpected t -> "Unexpected " ^ s_token t | Unclosed s -> "Unclosed " ^ s | Duplicate_default -> "Duplicate default declaration" | Unknown_macro m -> "Unknown macro " ^ m | Invalid_macro_parameters (m,n) -> "Invalid number of parameters for macro " ^ m ^ " : " ^ string_of_int n ^ " required" let error m p = raise (Error (m,p)) let priority = function | "+=" | "-=" | "*=" | "/=" | "|=" | "&=" | "^=" | ":=" -> -3 | "&&" | "||" -> -2 | "==" | "!=" | ">" | "<" | "<=" | ">=" | "===" | "!==" | "<>" | "=" -> -1 | "+" | "-" -> 0 | "*" | "/" -> 1 | "or" | "and" | "xor" -> 2 | "<<" | ">>" | "%" | ">>>" -> 3 | _ -> 4 let can_swap _op op = let p1 = priority _op in let p2 = priority op in if p1 < p2 then true else if p1 = p2 then op <> "::" else false let rec make_binop op e ((v,p2) as e2) = match v with | EBinop (_op,_e,_e2) when can_swap _op op -> let _e = make_binop op e _e in EBinop (_op,_e,_e2) , punion (pos _e) (pos _e2) | _ -> EBinop (op,e,e2) , punion (pos e) (pos e2) let rec make_unop op ((v,p2) as e) p1 = match v with | EBinop (bop,e,e2) -> EBinop (bop, make_unop op e p1 , e2) , (punion p1 p2) | _ -> EUnop (op,e), punion p1 p2 let rec make_list_pat p = function | [] -> PConstr ([],"[]",None) , p | x :: l -> let p = snd x in let params = PTuple [x;make_list_pat p l] , p in PConstr ([],"::",Some params) , p let rec make_list p = function | [] -> EConst (Constr "[]") , p | x :: l -> let p = snd x in ECall ((EConst (Constr "::") , p), [x;make_list p l]) , p let is_unop = function | "-" | "*" | "!" | "&" -> true | _ -> false let unclosed s p = error (Unclosed s) p let rec program = parser | [< e = expr; p = program >] -> e :: p | [< '(Semicolon,_); p = program >] -> p | [< '(Eof,_) >] -> [] and expr = parser | [< '(BraceOpen,p1); e = block1; s >] -> (match s with parser | [< '(BraceClose,p2); s >] -> e , punion p1 p2 | [< >] -> unclosed "{" p1) | [< '(Keyword Var,p1); '(Const (Ident name),_); t = type_opt; l = vars; e = expr; s >] -> EVar ((name,t) :: l,e) , punion p1 (pos e) | [< '(Keyword If,p1); cond = expr; '(Keyword Then,_); e = expr; s >] -> (match s with parser | [< '(Keyword Else,_); e2 = expr; s >] -> EIf (cond,e,Some e2) , punion p1 (pos e2) | [< >] -> EIf (cond,e,None) , punion p1 (pos e)) | [< '(Keyword Function,p1); r = function_rec; n = ident_opt; '(ParentOpen _,po); p = parameters_decl; t = type_opt; e = expr >] -> EFunction (r,n,p,e,t) , punion p1 (pos e) | [< '(Keyword Type,p1); pl = type_decl_parameters; '(Const (Ident tname),p2); d , p2 = type_declaration p2 >] -> ETypeDecl (pl,tname,d) , punion p1 p2 | [< '(Keyword Exception,p1); '(Const (Constr ename),p2); t = type_opt; s >] -> EErrorDecl (ename,t) , punion p1 p2 | [< '(Keyword Match,p1); e = expr; '(BraceOpen,po); pl = patterns_begin; s >] -> (match s with parser | [< '(BraceClose,pe); >] -> EMatch (e,pl), punion p1 pe | [< >] -> unclosed "{" po) | [< '(Keyword Try,p1); b = block; '(Keyword Catch,p2); '(BraceOpen,po); pl = patterns_begin; s >] -> (match s with parser | [< '(BraceClose,pe); >] -> ETry ((EBlock b,punion p1 p2),pl), punion p1 pe | [< >] -> unclosed "{" po) | [< '(Keyword While,p1); e = expr; '(BraceOpen,po); b = block; s >] -> (match s with parser | [< '(BraceClose,pe); s >] -> EWhile (e,(EBlock b,punion po pe)) , punion po pe | [< >] -> unclosed "{" po) | [< e = expr_short >] -> e and expr_short = parser | [< '(ParentOpen _,p1); pl = parameters; s >] -> (match s with parser | [< '(ParentClose,p2); s >] -> expr_next (ETupleDecl pl,punion p1 p2) s | [< >] -> unclosed "(" p1) | [< '(Binop op,p) when is_unop op; e = expr; s >] -> expr_next (make_unop op e p) s | [< '(Const (Constr n),p); e = expr_constr n p; s >] -> expr_next e s | [< '(Const c,p); s >] -> expr_next (EConst c,p) s | [< '(BracketOpen,p1); b = block; '(BracketClose,p2); s >] -> expr_next (make_list (punion p1 p2) b) s and expr_next e = parser | [< '(Binop ":",_); t , p = type_path; s >] -> expr_next (ETypeAnnot (e,t),punion (pos e) p) s | [< '(ParentOpen false,po); pl = parameters; s >] -> (match s with parser | [< '(ParentClose,p); s >] -> expr_next (ECall (e,pl),punion (pos e) p) s | [< >] -> unclosed "(" po) | [< '(Dot,_); s >] -> (match s with parser | [< '(Const (Ident name),p); s >] -> expr_next (EField (e,name),punion (pos e) p) s | [< '(BracketOpen,po); e2 = expr; s >] -> (match s with parser | [< '(BracketClose,p); s >] -> expr_next (EArray (e,e2),punion (pos e) p) s | [< >] -> unclosed "[" po)) | [< '(Binop op,_); e2 = expr; s >] -> make_binop op e e2 | [< ep = expr_short >] -> let rec loop ep = match ep with | EApply (e2,l) , p -> EApply (e,e2 :: l) , punion (pos e) p | EBinop (op,e1,e2) , p -> EBinop (op,loop e1,e2) , punion (pos e) p | _ -> EApply (e,[ep]) , punion (pos e) (pos ep) in loop ep | [< >] -> e and expr_constr n p = parser | [< '(Dot,_); e = expr_constr2 >] -> (match e with | EConst ((Ident _) as c) , p2 | EConst ((Constr _) as c) , p2 -> EConst (Module ([n],c)) , punion p p2 | EConst (Module (l,c)) , p2 -> EConst (Module (n :: l,c)) , punion p p2 | _ -> assert false); | [< >] -> EConst (Constr n), p and expr_constr2 = parser | [< '(Const (Ident n),p) >] -> EConst (Ident n) , p | [< '(Const (Constr n),p); e = expr_constr n p >] -> e and block1 = parser | [< '(Const (Ident name),p); s >] -> (match s with parser | [< '(Binop "=",_); e = expr; l = record_fields >] -> ERecordDecl ((name,e) :: l) | [< e = expr_next (EConst (Ident name),p); b = block >] -> EBlock (e :: b)) | [< b = block >] -> EBlock b and record_fields = parser | [< '(Const (Ident name),_); '(Binop "=",_); e = expr; l = record_fields >] -> (name,e) :: l | [< '(Semicolon,_); l = record_fields >] -> l | [< >] -> [] and vars = parser | [< '(Binop "=",_) >] -> [] | [< '(Comma,_); '(Const (Ident name),_); t = type_opt; l = vars >] -> (name,t) :: l and block = parser | [< e = expr; b = block >] -> e :: b | [< '(Semicolon,_); b = block >] -> b | [< >] -> [] and parameters_decl = parser | [< '(Const (Ident name),_); s >] -> parameters_decl_next (ANamed name) s | [< '(ParentOpen _,_); l = parameters_decl; s >] -> parameters_decl_next (ATuple l) s | [< '(ParentClose,_) >] -> [] and parameters_decl_next acc = parser | [< '(Comma,_); p = parameters_decl >] -> acc :: p | [< '(Binop ":",_); t , _ = type_path; s >] -> parameters_decl_next (ATyped (acc,t)) s | [< '(ParentClose,_) >] -> [acc] and type_opt = parser | [< '(Binop ":",_); t , _ = type_path; >] -> Some t | [< >] -> None and function_rec = parser | [< '(Const (Ident "rec"),_); >] -> true | [< >] -> false and ident_opt = parser | [< '(Const (Ident name),_); >] -> Some name | [< >] -> None and parameters = parser | [< e = expr; p = parameters_next >] -> e :: p | [< >] -> [] and parameters_next = parser | [< '(Comma,_); p = parameters >] -> p | [< >] -> [] and type_path = parser | [< '(Const (Ident tname),p); t = type_path_next (EType (None,[],tname)) p >] -> t | [< '(Const (Constr m),p); '(Dot,_); l = type_path_mod; '(Const (Ident tname),_); t = type_path_next (EType (None,m :: l,tname)) p >] -> t | [< '(Quote,_); '(Const (Ident a),p); t = type_path_next (EPoly a) p >] -> t | [< '(ParentOpen _,_); t , p = type_path; l , p = type_path_list_next p; '(ParentClose,_); s >] -> type_path_next (ETuple (t :: l)) p s and type_path_list p = parser | [< t , p = type_path; l , p = type_path_list_next p >] -> t :: l , p and type_path_list_next p = parser | [< '(Comma,_); t = type_path_list p >] -> t | [< >] -> [] , p and type_path_next t p = parser | [< '(Arrow,_); t2 , p = type_path >] -> EArrow(t,t2) , p | [< '(Const (Ident tname),p); t = type_path_next (EType (Some t,[],tname)) p >] -> t | [< '(Const (Constr m),p); '(Dot,_); l = type_path_mod; '(Const (Ident tname),_); t = type_path_next (EType (Some t,m :: l,tname)) p >] -> t | [< >] -> t , p and type_path_mod = parser | [< '(Const (Constr m),_); '(Dot,_); l = type_path_mod >] -> m :: l | [< >] -> [] and type_decl_parameters = parser | [< '(Quote,_); '(Const (Ident a),_); >] -> [a] | [< '(ParentOpen _,_); l = type_decl_plist; '(ParentClose,_); >] -> l | [< >] -> [] and type_decl_plist = parser | [< '(Quote,_); '(Const (Ident a),_); l = type_decl_plist_next >] -> a :: l and type_decl_plist_next = parser | [< '(Comma,_); l = type_decl_plist >] -> l | [< >] -> [] and type_declaration p = parser | [< '(BraceOpen,_); s >] -> (match s with parser | [< el , p = record_declaration false >] -> ERecord el , p | [< el , p = union_declaration >] -> EUnion el , p) | [< '(Binop "=",_); t , p = type_path >] -> EAlias t , p | [< >] -> EAbstract , p and record_declaration mut = parser | [< '(BraceClose,p) >] -> [] , p | [< '(Const (Ident "mutable"),_); l = record_declaration true; >] -> l | [< '(Semicolon,_); l = record_declaration false >] -> l | [< '(Const (Ident name),_); '(Binop ":",_); t , _ = type_path; l , p = record_declaration false >] -> (name,mut,t) :: l , p and union_declaration = parser | [< '(BraceClose,p) >] -> [] , p | [< '(Semicolon,_); l = union_declaration >] -> l | [< '(Const (Constr name),_); t = type_opt; l , p = union_declaration >] -> (name,t) :: l , p and patterns_begin = parser | [< '(Vertical,_); l = patterns >] -> l | [< l = patterns >] -> l and patterns = parser | [< p = pattern; pl = pattern_next; w = when_clause; '(Arrow,pa); b = block; l = patterns_begin >] -> let pat = (p :: pl,w,(match b with [e] -> e | _ -> EBlock b , pa) ) in pat :: l | [< >] -> [] and pattern_next = parser | [< '(Vertical,_); p = pattern; l = pattern_next >] -> p :: l | [< >] -> [] and pattern = parser | [< d , p = pattern_decl; s >] -> match s with parser | [< '(Const (Ident "as"),_); '(Const (Ident v),p2); s >] -> PAlias (v, (d,p)) , punion p p2 | [< '(Binop "::",_); d2 , p2 = pattern >] -> PConstr ([],"::",Some (PTuple [(d,p);(d2,p2)] , punion p p2)) , punion p p2 | [< t = type_opt >] -> match t with | None -> d , p | Some t -> PTyped ((d , p), t) , p and pattern_decl = parser | [< '(ParentOpen _,p1); pl = pattern_tuple; '(ParentClose,p2) >] -> PTuple pl , punion p1 p2 | [< '(BraceOpen,p1); '(Const (Ident name),_); '(Binop "=",_); p = pattern; pl = pattern_record; '(BraceClose,p2) >] -> PRecord ((name,p) :: pl) , punion p1 p2 | [< '(Const (Constr name),p1); l, name, p2 = pattern_mod_path name p1; p , p2 = pattern_opt p2 >] -> PConstr (l,name,p) , punion p1 p2 | [< '(Const (Ident i),p); >] -> PIdent i , p | [< '(Const c,p); >] -> PConst c , p | [< '(Binop "-",p1); '(Const (Int i),p2) >] -> PConst (Int (-i)) , punion p1 p2 | [< '(BracketOpen,p1); l = pattern_list; '(BracketClose,p2) >] -> make_list_pat (punion p1 p2) l | [< '(StreamOpen,p1); l = stream_list; '(StreamClose,p2) >] -> PStream (l,0) , punion p1 p2 and pattern_mod_path name p = parser | [< '(Dot,_); '(Const (Constr n),p); l, n, p = pattern_mod_path n p >] -> name :: l , n , p | [< >] -> [], name, p and stream_list = parser | [< '(Const (Ident v),p1); s >] -> (match s with parser | [< l = stream_ident_list; e = expr; s >] -> SExpr (v :: l,e) :: stream_next s | [< >] -> SPattern (PIdent v,p1) :: stream_next s) | [< p = pattern; l = stream_next >] -> SPattern p :: l | [< >] -> [] and stream_ident_list = parser | [< '(Comma,_); '(Const (Ident v),_); l = stream_ident_list >] -> v :: l | [< '(Binop "=",_) >] -> [] and stream_next = parser | [< '(Semicolon,_); l = stream_list >] -> l | [< >] -> [] and pattern_list = parser | [< p = pattern; l = pattern_list_next >] -> p :: l | [< >] -> [] and pattern_list_next = parser | [< '(Semicolon,_); l = pattern_list >] -> l | [< >] -> [] and pattern_tuple = parser | [< p = pattern; l = pattern_tuple_next >] -> p :: l | [< >] -> [] and pattern_tuple_next = parser | [< '(Comma,_); l = pattern_tuple >] -> l | [< >] -> [] and pattern_record = parser | [< '(Const (Ident name),_); '(Binop "=",_); p = pattern; l = pattern_record >] -> (name,p) :: l | [< '(Semicolon,_); l = pattern_record >] -> l | [< >] -> [] and pattern_opt p = parser | [< ( _ , pos as p) = pattern >] -> Some p , pos | [< >] -> None , p and when_clause = parser | [< '(Keyword When,_); e = expr >] -> Some e | [< >] -> None let parse code file = let old = Mllexer.save() in Mllexer.init file; let last = ref (Eof,null_pos) in let rec next_token x = let t, p = Mllexer.token code in match t with | Comment s | CommentLine s -> next_token x | _ -> last := (t , p); Some (t , p) in try let l = program (Stream.from next_token) in Mllexer.restore old; EBlock l, { pmin = 0; pmax = (pos !last).pmax; pfile = file } with | Stream.Error _ | Stream.Failure -> Mllexer.restore old; error (Unexpected (fst !last)) (pos !last) | e -> Mllexer.restore old; raise e neko-2-2-0/libs/ocaml/ml/mltype.ml000066400000000000000000000162561321613172000167530ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) type pos = Mlast.pos type mutflag = | Mutable | Immutable type type_expr = | TAbstract | TMono of int | TPoly | TRecord of (string * mutflag * t) list | TUnion of int * (string * t) list | TTuple of t list | TLink of t | TFun of t list * t | TNamed of string list * t list * t and t = { mutable tid : int; mutable texpr : type_expr; } type tconstant = | TVoid | TInt of int | TBool of bool | TFloat of string | TString of string | TChar of char | TIdent of string | TConstr of string | TModule of string list * tconstant and match_op = | MRoot | MFailure | MHandle of match_op * match_op | MExecute of texpr * bool | MConstants of match_op * (tconstant * match_op) list | MField of match_op * int | MTuple of match_op * int | MToken of match_op * int | MRecordField of match_op * string | MJunk of match_op * int * match_op | MSwitch of match_op * (tconstant * match_op) list | MBind of string * match_op * match_op | MWhen of texpr * match_op | MNext of match_op * match_op and texpr_decl = | TConst of tconstant | TBlock of texpr list | TParenthesis of texpr | TCall of texpr * texpr list | TField of texpr * string | TArray of texpr * texpr | TVar of string list * texpr | TIf of texpr * texpr * texpr option | TFunction of bool * string * (string * t) list * texpr | TBinop of string * texpr * texpr | TTupleDecl of texpr list | TTypeDecl of t | TMut of texpr ref | TRecordDecl of (string * texpr) list | TListDecl of texpr list | TUnop of string * texpr | TMatch of texpr * match_op * bool | TTry of texpr * match_op | TTupleGet of texpr * int | TErrorDecl of string * t | TWhile of texpr * texpr and texpr = { edecl : texpr_decl; etype : t; epos : pos; } type id_gen = int ref let pos e = e.epos let rec tlinks name t = match t.texpr with | TLink t -> tlinks name t | TNamed (_,_,t) when not name -> tlinks name t | _ -> t.texpr let etype name e = tlinks name e.etype let genid i = incr i; !i let generator() = ref 0 let mk e t p = { edecl = e; etype = t; epos = p; } let t_abstract = { tid = -1; texpr = TAbstract } let abstract s = { tid = -1; texpr = TNamed ([s],[], t_abstract); } let t_void = abstract "void" let t_int = abstract "int" let t_float = abstract "float" let t_char = abstract "char" let t_error = abstract "error" let t_bool = { tid = -1; texpr = TNamed (["bool"],[], { tid = -1; texpr = TUnion (2,[ ("true",{ tid = -1; texpr = TAbstract }); ("false",{ tid = -1; texpr = TAbstract }) ]); }); } let t_string = abstract "string" let t_mono g = { tid = -2; texpr = TMono (genid g); } let t_polymorph g = { tid = genid g; texpr = TPoly; } let t_poly g name = let param = t_mono g in { tid = genid g; texpr = TNamed ([name],[param], { tid = -1; texpr = TAbstract }); } , param let mk_fun g params ret = { tid = if List.exists (fun t -> t.tid <> -1) (ret :: params) then genid g else -1; texpr = TFun (params,ret); } let mk_tup g l = { tid = if List.exists (fun t -> t.tid <> -1) l then genid g else -1; texpr = TTuple l; } let mk_record g fl = { tid = if List.exists (fun (_,_,t) -> t.tid <> -1) fl then genid g else -1; texpr = TRecord fl; } let mk_union g fl = { tid = if List.exists (fun (_,t) -> t.tid <> -1) fl then genid g else -1; texpr = TUnion (List.length fl,fl); } type print_infos = { mutable pi_mcount : int; mutable pi_pcount : int; mutable pi_ml : (t * int) list; mutable pi_ph : (int , int) Hashtbl.t; } let s_context() = { pi_mcount = 0; pi_pcount = 0; pi_ml = []; pi_ph = Hashtbl.create 0; } let poly_id n = if n < 26 then String.make 1 (char_of_int (int_of_char 'a' + n)) else string_of_int (n - 25) let s_mutable = function | Mutable -> "mutable " | Immutable -> "" let rec s_type ?(ext=false) ?(h=s_context()) t = match t.texpr with | TAbstract -> "" | TMono _ -> Printf.sprintf "'_%s" (poly_id (try if t.tid <> -2 then assert false; List.assq t h.pi_ml with Not_found -> let k = h.pi_mcount in h.pi_mcount <- h.pi_mcount + 1; h.pi_ml <- (t,k) :: h.pi_ml; k)) | TPoly -> Printf.sprintf "'%s" (poly_id (try if t.tid = -1 then assert false; Hashtbl.find h.pi_ph t.tid with Not_found -> let k = h.pi_pcount in h.pi_pcount <- h.pi_pcount + 1; Hashtbl.add h.pi_ph t.tid k; k)) | TRecord fl -> Printf.sprintf "{ %s }" (String.concat "; " (List.map (fun (f,m,t) -> s_mutable m ^ f ^ " : " ^ s_type ~h t) fl)) | TUnion (_,fl) -> Printf.sprintf "{ %s }" (String.concat "; " (List.map (fun (f,t) -> f ^ " : " ^ s_type ~h t) fl)) | TTuple l -> Printf.sprintf "(%s)" (String.concat ", " (List.map (s_type ~h) l)) | TLink t -> s_type ~ext ~h t | TFun (tl,r) -> let l = String.concat " -> " (List.map (s_fun ~ext ~h) tl) ^ " -> " in l ^ s_type ~ext ~h r | TNamed (name,params,t) -> let s = (match params with | [] -> "" | [p] -> s_type ~h p ^ " " | l -> "(" ^ String.concat ", " (List.map (s_type ~h) l) ^ ") ") in let name = String.concat "." name in if ext then s ^ name ^ " = " ^ s_type ~h t else s ^ name and s_fun ~ext ~h t = match t.texpr with | TLink t -> s_fun ~ext ~h t | TFun _ -> "(" ^ s_type ~ext ~h t ^ ")" | _ -> s_type ~ext ~h t let rec duplicate g ?(h=Hashtbl.create 0) t = if t.tid < 0 then t else try Hashtbl.find h t.tid with Not_found -> let t2 = { tid = genid g; texpr = TAbstract; } in Hashtbl.add h t.tid t2; t2.texpr <- (match t.texpr with | TAbstract -> TAbstract | TMono _ -> assert false | TPoly -> t2.tid <- -2; TMono (genid g) | TRecord tl -> TRecord (List.map (fun (n,m,t) -> n , m, duplicate g ~h t) tl) | TUnion (n,tl) -> TUnion (n,List.map (fun (n,t) -> n , duplicate g ~h t) tl) | TTuple tl -> TTuple (List.map (duplicate g ~h) tl) | TLink t -> TLink (duplicate g ~h t) | TFun (tl,t) -> TFun (List.map (duplicate g ~h) tl, duplicate g ~h t) | TNamed (n,p,t) -> TNamed (n,List.map (duplicate g ~h) p,duplicate g ~h t)); t2 let rec polymorphize g mink t = if t.tid = -1 then () else match t.texpr with | TAbstract -> () | TMono k -> if k > mink then begin t.texpr <- TPoly; t.tid <- genid g end; | TPoly -> () | TRecord fl -> List.iter (fun (_,_,t) -> polymorphize g mink t) fl | TUnion (_,fl) -> List.iter (fun (_,t) -> polymorphize g mink t) fl | TTuple tl -> List.iter (polymorphize g mink) tl | TLink t -> polymorphize g mink t | TFun (tl,t) -> List.iter (polymorphize g mink) tl; polymorphize g mink t | TNamed (_,tl,t) -> List.iter (polymorphize g mink) tl neko-2-2-0/libs/ocaml/ml/mltyper.ml000066400000000000000000000750541321613172000171360ustar00rootroot00000000000000(* * NekoML Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Mlast open Mltype type module_context = { path : string list; types : (string,t) Hashtbl.t; constrs : (string, t * t) Hashtbl.t; records : (string,t * t * mutflag) Hashtbl.t; deps : (string list, module_context) Hashtbl.t; mutable expr : texpr option; mutable idents : (string,t) PMap.t; } type context = { gen : id_gen; mutable mink : int; mutable functions : (bool * string * texpr ref * t * (string * t) list * expr * t * pos) list; mutable opens : module_context list; mutable curfunction : string; tmptypes : (string, t * t list * (string,t) Hashtbl.t) Hashtbl.t; current : module_context; modules : (string list, module_context) Hashtbl.t; classpath : string list; } type error_msg = | Cannot_unify of t * t | Have_no_field of t * string | Stack of error_msg * error_msg | Unknown_field of string | Module_not_loaded of module_context | Custom of string exception Error of error_msg * pos module SSet = Set.Make(String) let rec error_msg ?(h=s_context()) = function | Cannot_unify (t1,t2) -> "Cannot unify " ^ s_type ~h t1 ^ " and " ^ s_type ~h t2 | Have_no_field (t,f) -> s_type ~h t ^ " have no field " ^ f | Stack (m1,m2) -> error_msg ~h m1 ^ "\n " ^ error_msg ~h m2 | Unknown_field s -> "Unknown field " ^ s | Module_not_loaded m -> "Module " ^ String.concat "." m.path ^ " require an interface" | Custom s -> s let error m p = raise (Error (m,p)) let verbose = ref false let load_module_ref = ref (fun _ _ -> assert false) let add_local ctx v t = if v <> "_" then ctx.current.idents <- PMap.add v t ctx.current.idents let save_locals ctx = ctx.current.idents let restore_locals ctx l = ctx.current.idents <- l let get_module ctx path p = match path with | [] -> ctx.current | _ -> let m = (try Hashtbl.find ctx.modules path with Not_found -> !load_module_ref ctx path p) in if m != ctx.current then begin if m.expr = None then error (Module_not_loaded m) p; Hashtbl.replace ctx.current.deps m.path m; end; m let get_type ctx path name p = let rec loop = function | [] -> error (Custom ("Unknown type " ^ s_path path name)) p | m :: l -> try Hashtbl.find m.types name with Not_found -> loop l in match path with | [] -> loop (ctx.current :: ctx.opens) | _ -> loop [get_module ctx path p] let get_constr ctx path name p = let rec loop = function | [] -> error (Custom ("Unknown constructor " ^ s_path path name)) p | m :: l -> try let t1, t2 = Hashtbl.find m.constrs name in (if m == ctx.current then [] else m.path) , t1, t2 with Not_found -> loop l in match path with | [] -> loop (ctx.current :: ctx.opens) | _ -> loop [get_module ctx path p] let get_ident ctx path name p = let rec loop = function | [] -> error (Custom ("Unknown identifier " ^ s_path path name)) p | m :: l -> try (if m == ctx.current then [] else m.path) , PMap.find name m.idents with Not_found -> loop l in match path with | [] -> loop (ctx.current :: ctx.opens) | _ -> loop [get_module ctx path p] let get_record ctx f p = let rec loop = function | [] -> error (Unknown_field f) p | m :: l -> try Hashtbl.find m.records f with Not_found -> loop l in let rt , ft , mut = loop (ctx.current :: ctx.opens) in let h = Hashtbl.create 0 in duplicate ctx.gen ~h rt, duplicate ctx.gen ~h ft, mut let rec is_tuple t = match t.texpr with | TLink t -> is_tuple t | TTuple _ -> true | TNamed(_,_,t) -> is_tuple t | _ -> false let rec is_recursive t1 t2 = if t1 == t2 then true else match t2.texpr with | TAbstract | TMono _ | TPoly -> false | TRecord _ | TUnion _ -> assert false | TTuple tl -> List.exists (is_recursive t1) tl | TLink t -> is_recursive t1 t | TFun (tl,t) -> List.exists (is_recursive t1) tl || is_recursive t1 t | TNamed (_,p,t) -> List.exists (is_recursive t1) p let link ctx t1 t2 p = if is_recursive t1 t2 then error (Cannot_unify (t1,t2)) p; t1.texpr <- TLink t2; if t1.tid < 0 then begin if t2.tid = -1 then t1.tid <- -1 else t1.tid <- genid ctx.gen; end else if t2.tid = -1 then t1.tid <- -1 let unify_stack t1 t2 = function | Error (Cannot_unify _ as e , p) -> error (Stack (e , Cannot_unify (t1,t2))) p | e -> raise e let is_alias = function | TAbstract | TRecord _ | TUnion _ -> false | TMono _ | TPoly | TTuple _ | TLink _ | TFun _ | TNamed _ -> true let rec propagate k t = match t.texpr with | TAbstract | TPoly -> () | TUnion _ | TRecord _ -> assert false | TMono k2 -> if k < k2 then t.texpr <- TMono k | TTuple tl -> List.iter (propagate k) tl | TLink t -> propagate k t | TFun (tl,t) -> propagate k t; List.iter (propagate k) tl | TNamed (_,tl,_) -> List.iter (propagate k) tl let rec unify ctx t1 t2 p = if t1 == t2 then () else match t1.texpr , t2.texpr with | TLink t , _ -> unify ctx t t2 p | _ , TLink t -> unify ctx t1 t p | TMono k , t -> link ctx t1 t2 p; propagate k t2 | t , TMono k -> link ctx t2 t1 p; propagate k t1 | TPoly , t -> link ctx t1 t2 p | t , TPoly -> link ctx t2 t1 p | TNamed (n1,p1,_) , TNamed (n2,p2,_) when n1 = n2 -> (try List.iter2 (fun p1 p2 -> unify ctx p1 p2 p) p1 p2 with e -> unify_stack t1 t2 e) | TNamed (_,_,t1) , _ when is_alias t1.texpr -> (try unify ctx t1 t2 p with e -> unify_stack t1 t2 e) | _ , TNamed (_,_,t2) when is_alias t2.texpr -> (try unify ctx t1 t2 p with e -> unify_stack t1 t2 e) | TFun (tl1,r1) , TFun (tl2,r2) when List.length tl1 = List.length tl2 -> (try List.iter2 (fun t1 t2 -> unify ctx t1 t2 p) tl1 tl2; unify ctx r1 r2 p; with e -> unify_stack t1 t2 e) | TTuple tl1 , TTuple tl2 when List.length tl1 = List.length tl2 -> (try List.iter2 (fun t1 t2 -> unify ctx t1 t2 p) tl1 tl2 with e -> unify_stack t1 t2 e) | _ , _ -> error (Cannot_unify (t1,t2)) p let rec type_type ?(allow=true) ?(h=Hashtbl.create 0) ctx t p = match t with | ETuple [] -> assert false | ETuple [t] -> type_type ~allow ~h ctx t p | ETuple el -> mk_tup ctx.gen (List.map (fun t -> type_type ~allow ~h ctx t p) el) | EPoly s -> (try Hashtbl.find h s with Not_found -> if not allow then error (Custom ("Unbound type variable '" ^ s)) p; let t = t_mono ctx.gen in Hashtbl.add h s t; t) | EType (param,path,name) -> let param = (match param with None -> None | Some t -> Some (type_type ~allow ~h ctx t p)) in let t = get_type ctx path name p in (match t.texpr with | TNamed (_,params,t2) -> let tl = (match params, param with | [] , None -> [] | [x] , Some t -> [t] | l , Some { texpr = TTuple tl } when List.length tl = List.length l -> tl | _ , _ -> error (Custom ("Invalid number of type parameters for " ^ s_path path name)) p ) in let h = Hashtbl.create 0 in let t = duplicate ctx.gen ~h t in let params = List.map (duplicate ctx.gen ~h) params in List.iter2 (fun pa t -> unify ctx pa t p) params tl; t | _ -> assert false) | EArrow _ -> let rec loop params t = match t with | EArrow (ta,tb) -> let ta = type_type ~allow ~h ctx ta p in loop (ta :: params) tb | _ -> let t = type_type ~allow ~h ctx t p in mk_fun ctx.gen (List.rev params) t in loop [] t let rec type_constant ctx ?(path=[]) c p = match c with | Int i -> mk (TConst (TInt i)) t_int p | Float s -> mk (TConst (TFloat s)) t_float p | String s -> mk (TConst (TString s)) t_string p | Bool b -> mk (TConst (TBool b)) t_bool p | Char c -> mk (TConst (TChar c)) t_char p | Ident s -> let path , t = get_ident ctx path s p in let t = duplicate ctx.gen t in mk (TConst (TModule (path,TIdent s))) t p | Constr s -> let path , ut , t = get_constr ctx path s p in let t = duplicate ctx.gen (match t.texpr with | TAbstract -> ut | TTuple tl -> mk_fun ctx.gen tl ut | _ -> mk_fun ctx.gen [t] ut) in mk (TConst (TModule (path,TConstr s))) t p | Module (path,c) -> type_constant ctx ~path c p type addable = NInt | NFloat | NString | NNan let addable str e = match etype true e with | TNamed (["int"],_,_) -> NInt | TNamed (["float"],_,_) -> NFloat | TNamed (["string"],_,_) when str -> NString | _ -> NNan let type_binop ctx op e1 e2 p = let emk t = mk (TBinop (op,e1,e2)) t p in match op with | "%" | "+" | "-" | "/" | "*" -> let str = (op = "+") in (match addable str e1, addable str e2 with | NInt , NInt -> emk t_int | NFloat , NFloat | NInt , NFloat | NFloat , NInt -> emk t_float | NInt , NString | NFloat , NString | NString , NInt | NString , NFloat | NString , NString -> emk t_string | NInt , NNan | NFloat , NNan | NString , NNan -> unify ctx e2.etype e1.etype (pos e2); emk e1.etype | NNan , NInt | NNan , NFloat | NNan , NString -> unify ctx e1.etype e2.etype (pos e1); emk e2.etype | NNan , NNan -> unify ctx e1.etype t_int (pos e1); unify ctx e2.etype t_int (pos e2); emk t_int) | ">>" | ">>>" | "<<" | "and" | "or" | "xor" -> unify ctx e1.etype t_int (pos e1); unify ctx e2.etype t_int (pos e2); emk t_int | "&&" | "||" -> unify ctx e1.etype t_bool (pos e1); unify ctx e2.etype t_bool (pos e2); emk t_bool | "<" | "<=" | ">" | ">=" | "==" | "!=" | "===" | "!==" -> unify ctx e2.etype e1.etype (pos e2); emk t_bool | ":=" -> (match e1.edecl with | TArray _ -> unify ctx e2.etype e1.etype (pos e2); emk t_void | TField (e,f) -> (match tlinks false e.etype with | TRecord fl -> let _ , mut , _ = (try List.find (fun (f2,_,_) -> f2 = f) fl with Not_found -> assert false) in if mut = Immutable then error (Custom ("Field " ^ f ^ " is not mutable")) (pos e1); unify ctx e2.etype e1.etype (pos e2); emk t_void | _ -> assert false); | _ -> let t , pt = t_poly ctx.gen "ref" in unify ctx e2.etype pt (pos e2); unify ctx e1.etype t (pos e1); emk t_void) | "::" -> let t , pt = t_poly ctx.gen "list" in unify ctx e1.etype pt (pos e1); unify ctx e2.etype t (pos e2); let c = mk (TConst (TConstr "::")) (t_mono ctx.gen) p in mk (TCall (c,[e1;e2])) t p | _ -> error (Custom ("Invalid operation " ^ op)) p let type_unop ctx op e p = let emk t = mk (TUnop (op,e)) t p in match op with | "&" -> let p , pt = t_poly ctx.gen "ref" in unify ctx e.etype pt (pos e); emk p | "*" -> let p , pt = t_poly ctx.gen "ref" in unify ctx e.etype p (pos e); emk pt | "!" -> unify ctx e.etype t_bool (pos e); emk t_bool | "-" -> (match addable false e with | NInt -> emk t_int | NFloat -> emk t_float | _ -> unify ctx e.etype t_int (pos e); emk t_int) | _ -> assert false let rec type_arg ctx h binds p = function | ATyped (a,t) -> let n , ta = type_arg ctx h binds p a in unify ctx ta (type_type ~h ctx t p) p; n , ta | ANamed s -> s , t_mono ctx.gen | ATuple al -> let aname = "@t" ^ string_of_int (genid ctx.gen) in let nl , tl = List.split (List.map (type_arg ctx h binds p) al) in let k = ref 0 in List.iter (fun n -> if n <> "_" then binds := (aname,!k,n) :: !binds; incr k; ) nl; aname , mk_tup ctx.gen tl let register_function ctx isrec name pl e rt p = if ctx.functions = [] then ctx.mink <- !(ctx.gen); let pl = (match pl with [] -> [ATyped (ANamed "_",EType (None,[],"void"))] | _ -> pl) in let expr = ref (mk (TConst TVoid) t_void p) in let h = Hashtbl.create 0 in let binds = ref [] in let el = List.map (type_arg ctx h binds p) pl in let name = (match name with None -> "_" | Some n -> n) in let e = (match List.rev !binds with | [] -> e | l -> EBlock (List.fold_left (fun acc (v,n,v2) -> (EVar ([v2,None], (ETupleGet ((EConst (Ident v),p),n),p)) , p) :: acc ) [e] l) , p ) in let rt = (match rt with | None -> t_mono ctx.gen | Some rt -> type_type ~h ctx rt p ) in let ft = mk_fun ctx.gen (List.map snd el) rt in ctx.functions <- (isrec,name,expr,ft,el,e,rt,p) :: ctx.functions; if isrec then add_local ctx name ft; mk (TMut expr) (if name = "_" then ft else t_void) p let type_format ctx s p = let types = ref [] in let percent = ref false in for i = 0 to String.length s - 1 do let c = String.get s i in if !percent then begin percent := false; match c with | '%' -> () | 'x' | 'X' | 'd' -> types := t_int :: !types | 'f' -> types := t_float :: !types | 's' -> types := t_string :: !types | 'b' -> types := t_bool :: !types | 'c' -> types := t_char :: !types | '0'..'9' | '.' -> percent := true | _ -> error (Custom "Invalid % sequence") p end else match c with | '%' -> percent := true | _ -> () done; if !percent then error (Custom "Invalid % sequence") p; match !types with | [] -> t_void | [x] -> x | l -> mk_tup ctx.gen (List.rev l) let rec type_functions ctx = let l = ctx.functions in if l <> [] then let mink = ctx.mink in ctx.functions <- []; let l = List.map (fun (isrec,name,expr,ft,el,e,rt,p) -> let locals = save_locals ctx in let func = ctx.curfunction in if name <> "_" then begin let fname = s_path ctx.current.path name in if !verbose then prerr_endline ("Typing " ^ fname); ctx.curfunction <- fname; end; List.iter (fun (p,pt) -> add_local ctx p pt ) el; let e = type_expr ctx e in restore_locals ctx locals; ctx.curfunction <- func; let ft2 = mk_fun ctx.gen (List.map snd el) e.etype in unify ctx ft ft2 p; expr := mk (TFunction (isrec,name,el,e)) ft2 p; if not isrec then add_local ctx name ft; ft2 ) (List.rev l) in List.iter (polymorphize ctx.gen mink) l and type_expr ctx (e,p) = match e with | EConst c -> type_constant ctx c p | EBlock [] -> mk (TConst TVoid) t_void p | EBlock (e :: l) -> let locals = save_locals ctx in let e = type_block ctx e in let el , t = List.fold_left (fun (l,t) e -> unify ctx t t_void (List.hd l).epos; let e = type_block ctx e in e :: l , e.etype ) ([e] , e.etype) l in type_functions ctx; restore_locals ctx locals; mk (TBlock (List.rev el)) t p | EApply (e,el) -> type_expr ctx (ECall (e,el),p) | ECall ((EConst (Ident "open"),_),[EConst (Module (m,Constr modname)),p]) -> ctx.opens <- get_module ctx (m @ [modname]) p :: ctx.opens; mk (TConst TVoid) t_void p | ECall ((EConst (Ident "open"),_),[EConst (Constr modname),p]) -> ctx.opens <- get_module ctx [modname] p :: ctx.opens; mk (TConst TVoid) t_void p | ECall ((EConst (Ident "assert"),_) as a,[]) -> let line = Mllexer.get_error_line p in type_expr ctx (ECall (a,[EConst (String p.pfile),p;EConst (Int line),p]),p) | ECall ((EConst (Ident "invalid_arg"),_) as a,[]) -> type_expr ctx (ECall (a,[EConst (String ctx.curfunction),p]),p) | ECall ((EConst (Constr "TYPE"),_),[e]) -> let e = type_expr ctx e in prerr_endline ("type : " ^ s_type e.etype); mk (TParenthesis e) t_void p | ECall (e,el) -> let e = type_expr ctx e in let el = (match el with [] -> [ETupleDecl [],p] | _ -> el) in let el = List.map (type_expr ctx) el in (match etype false e with | TFun (args,r) -> let rec loop acc expr l tl r = match l , tl with | e :: l , t :: tl -> (match tlinks true t with | TNamed (["format"],[param],_) -> (match e.edecl with | TConst (TString s) -> let tfmt = type_format ctx s e.epos in unify ctx param tfmt e.epos; | _ -> (match tlinks true e.etype with | TNamed (["format"],[param2],_) -> unify ctx param2 param e.epos | _ -> error (Custom "Constant string required for format") e.epos)) | _ -> unify ctx e.etype t (pos e)); loop (e :: acc) expr l tl r | [] , [] -> mk (TCall (expr,List.rev acc)) r p | [] , tl -> mk (TCall (expr,List.rev acc)) (mk_fun ctx.gen tl r) p | el , [] -> match tlinks false r with | TFun (args,r2) -> loop [] (mk (TCall (expr,List.rev acc)) r p) el args r2 | _ -> error (Custom "Too many arguments") p in loop [] e el args r | _ -> let r = t_mono ctx.gen in let f = mk_fun ctx.gen (List.map (fun e -> e.etype) el) r in unify ctx e.etype f p; mk (TCall (e,el)) r p ); | EField (e,s) -> let e = type_expr ctx e in let t = (match etype false e with | TRecord fl -> (try let _ , _ , t = List.find (fun (s2,_,_) -> s = s2) fl in t with Not_found -> error (Have_no_field (e.etype,s)) p) | _ -> let r , t , _ = get_record ctx s p in unify ctx e.etype r (pos e); t ) in mk (TField (e,s)) t p | EArray (e,ei) -> let e = type_expr ctx e in let ei = type_expr ctx ei in unify ctx ei.etype t_int (pos ei); let t , pt = t_poly ctx.gen "array" in unify ctx e.etype t (pos e); mk (TArray (e,ei)) pt p | EVar _ -> error (Custom "Variable declaration not allowed outside a block") p | EIf (e,e1,None) -> let e = type_expr ctx e in unify ctx e.etype t_bool (pos e); let e1 = type_expr ctx e1 in unify ctx e1.etype t_void (pos e1); mk (TIf (e,e1,None)) t_void p | EIf (e,e1,Some e2) -> let e = type_expr ctx e in unify ctx e.etype t_bool (pos e); let e1 = type_expr ctx e1 in let e2 = type_expr ctx e2 in unify ctx e2.etype e1.etype (pos e2); mk (TIf (e,e1,Some e2)) e1.etype p | EWhile (e1,e2) -> let e1 = type_expr ctx e1 in unify ctx e1.etype t_bool (pos e1); let e2 = type_expr ctx e2 in unify ctx e2.etype t_void (pos e2); mk (TWhile (e1,e2)) t_void p | EFunction (isrec,name,pl,e,rt) -> let r = register_function ctx isrec name pl e rt p in type_functions ctx; r | EBinop (op,e1,e2) -> type_binop ctx op (type_expr ctx e1) (type_expr ctx e2) p | ETypeAnnot (e,t) -> let e = type_expr ctx e in let t = type_type ctx t p in unify ctx e.etype t (pos e); mk e.edecl t p | ETupleDecl [] -> mk (TConst TVoid) t_void p | ETupleDecl [e] -> let e = type_expr ctx e in mk (TParenthesis e) e.etype (pos e) | ETupleDecl el -> let el = List.map (type_expr ctx) el in mk (TTupleDecl el) (mk_tup ctx.gen (List.map (fun e -> e.etype) el)) p | ETypeDecl (params,tname,decl) -> let fullname = (match ctx.current.path with ["Core"] -> [tname] | p -> p @ [tname]) in let t , tl , h = try let t , tl , h = Hashtbl.find ctx.tmptypes tname in if decl <> EAbstract then Hashtbl.remove ctx.tmptypes tname; if List.length tl <> List.length params then error (Custom ("Invalid number of parameters for type " ^ tname)) p; t , tl , h with Not_found -> if Hashtbl.mem ctx.current.types tname then error (Custom ("Invalid type redefinition of type " ^ tname)) p; let h = Hashtbl.create 0 in let tl = List.map (fun p -> let t = t_mono ctx.gen in Hashtbl.add h p t; t ) params in let t = { tid = -1; texpr = TNamed (fullname,tl,t_abstract); } in Hashtbl.add ctx.current.types tname t; if decl = EAbstract then Hashtbl.add ctx.tmptypes tname (t,tl,h); t , tl , h in let t2 = (match decl with | EAbstract -> t_abstract | EAlias t -> type_type ~allow:false ~h ctx t p | ERecord fields -> let fields = List.map (fun (f,m,ft) -> let ft = type_type ~allow:false ~h ctx ft p in let m = (if m then Mutable else Immutable) in Hashtbl.add ctx.current.records f (t,ft,m); f , m , ft ) fields in mk_record ctx.gen fields | EUnion constr -> let constr = List.map (fun (c,ft) -> let ft = (match ft with | None -> t_abstract | Some ft -> type_type ~allow:false ~h ctx ft p ) in Hashtbl.add ctx.current.constrs c (t,ft); c , ft ) constr in mk_union ctx.gen constr ) in t.tid <- if t2.tid = -1 && params = [] then -1 else genid ctx.gen; t.texpr <- TNamed (fullname,tl,t2); polymorphize ctx.gen 0 t; mk (TTypeDecl t) t_void p | ERecordDecl fl -> let s , _ = (try List.hd fl with _ -> assert false) in let r , _ , _ = get_record ctx s p in let fll = (match tlinks false r with | TRecord fl -> fl | _ -> assert false ) in let fl2 = ref fll in let rec loop f = function | [] -> if List.exists (fun (f2,_,_) -> f = f2) fll then error (Custom ("Duplicate declaration for field " ^ f)) p else error (Have_no_field (r,f)) p | (f2,_,ft) :: l when f = f2 -> ft , l | x :: l -> let t , l = loop f l in t , x :: l in let el = List.map (fun (f,e) -> let ft , fl2b = loop f !fl2 in fl2 := fl2b; let e = type_expr ctx e in unify ctx e.etype ft (pos e); (f , e) ) fl in List.iter (fun (f,_,_) -> error (Custom ("Missing field " ^ f ^ " in record declaration")) p; ) !fl2; mk (TRecordDecl el) r p | EErrorDecl (name,t) -> let t = (match t with None -> t_abstract | Some t -> type_type ~allow:false ctx t p) in Hashtbl.add ctx.current.constrs name (t_error,t); mk (TErrorDecl (name,t)) t_void p | EUnop (op,e) -> type_unop ctx op (type_expr ctx e) p | EMatch (e,cl) -> let e = type_expr ctx e in let is_stream = List.for_all (fun (l,_,_) -> List.for_all (fun (p,_) -> match p with PStream _ -> true | _ -> false) l) cl in let partial , m , t = type_match ctx e.etype cl p in if not is_stream && partial then error (Custom "This matching is not complete") p; mk (TMatch (e,m,is_stream)) t p | ETry (e,cl) -> let e = type_expr ctx e in let _ , m , t = type_match ctx t_error cl p in unify ctx t e.etype p; mk (TTry (e,m)) t p | ETupleGet (e,n) -> let e = type_expr ctx e in let try_unify et = let t = Array.init (n + 1) (fun _ -> t_mono ctx.gen) in unify ctx et (mk_tup ctx.gen (Array.to_list t)) p; t.(n) in let rec loop et = match et.texpr with | TLink et -> loop et | TTuple l -> (try List.nth l n with _ -> try_unify et) | _ -> try_unify et in mk (TTupleGet (e,n)) (loop e.etype) p and type_block ctx ((e,p) as x) = match e with | EVar (vl,e) -> type_functions ctx; let e = type_expr ctx e in let make v t = let t = (match t with | None -> t_mono ctx.gen | Some t -> type_type ctx t p ) in add_local ctx v t; t in let t = (match vl with | [] -> assert false | [v,t] -> make v t | _ -> mk_tup ctx.gen (List.map (fun (v,t) -> make v t) vl) ) in unify ctx t e.etype (pos e); mk (TVar (List.map fst vl,e)) t_void p | EFunction (true,name,pl,e,rt) -> register_function ctx true name pl e rt p | _ -> type_functions ctx; type_expr ctx x and type_pattern (ctx:context) h ?(h2 = Hashtbl.create 0) set add (pat,p) = let pvar add s = if SSet.mem s !set then error (Custom "This variable is several time in the pattern") p; set := SSet.add s !set; try Hashtbl.find h s with Not_found -> let t = t_mono ctx.gen in Hashtbl.add h s t; if add then add_local ctx s t; t in let pt , pat = (match pat with | PConst c -> (match c with | Int n -> t_int | Float s -> t_float | String s -> t_string | Char c -> t_char | Bool b -> t_bool | Ident _ | Constr _ | Module _ -> assert false) , pat | PTuple [p] -> let pt , pat = type_pattern ctx h ~h2 set add p in pt , fst pat | PTuple pl -> let pl , patl = List.split (List.map (type_pattern ctx h ~h2 set add) pl) in mk_tup ctx.gen pl , PTuple patl | PRecord fl -> let s = (try fst (List.hd fl) with _ -> assert false) in let r , _ , _ = get_record ctx s p in let fl = (match tlinks false r with | TRecord rl -> List.map (fun (f,pat) -> let pt , pat = type_pattern ctx h ~h2 set add pat in let t = (try let _ , _ , t = List.find (fun (f2,_,_) -> f = f2 ) rl in t with Not_found -> error (Have_no_field (r,f)) p ) in unify ctx pt t (snd pat); f , pat ) fl | _ -> assert false ) in r , PRecord fl | PIdent s -> (if s = "_" then t_mono ctx.gen else pvar add s) , pat | PConstr (path,s,param) -> let tparam , param = (match param with | None -> None , None | Some ((_,p) as param) -> let t , pat = type_pattern ctx h ~h2 set add param in Some (p,t) , Some pat ) in let path , ut , t = get_constr ctx path s p in (match t.texpr , tparam with | TAbstract , None -> duplicate ctx.gen ut , PConstr (path,s,param) | TAbstract , Some _ -> error (Custom "Constructor does not take parameters") p | _ , None -> error (Custom "Constructor require parameters") p | _ , Some (p,pt) -> let h = Hashtbl.create 0 in let ut = duplicate ctx.gen ~h ut in let t = duplicate ctx.gen ~h t in let param , pt = (match param with | Some (PTuple l,p) when not (is_tuple t) -> Some (PTuple [(PTuple l,p)],p) , mk_fun ctx.gen [pt] ut | Some (PIdent "_",p) -> param , pt | _ -> param , (match pt.texpr with TTuple l -> mk_fun ctx.gen l ut | _ -> mk_fun ctx.gen [pt] ut) ) in let t = (match t.texpr with TTuple l -> mk_fun ctx.gen l ut | _ -> mk_fun ctx.gen [t] ut) in unify ctx t pt p; ut , PConstr (path,s,param)); | PAlias (s,pat) -> let pt , pat = type_pattern ctx h ~h2 set false pat in let t = pvar false s in unify ctx pt t (snd pat); t , PAlias (s,pat) | PTyped (pat,t) -> let pt , pat = type_pattern ctx h ~h2 set add pat in unify ctx pt (type_type ~h:h2 ctx t p) p; pt , PTyped (pat,t) | PStream (l,k) -> let t , polyt = t_poly ctx.gen "stream" in let locals = save_locals ctx in let l = List.map (fun s -> match s with | SPattern pat -> let t , p = type_pattern ctx h ~h2 set true pat in unify ctx t polyt (snd p); SPattern p | SExpr ([v],e) -> let e = type_expr ctx e in let t = pvar true v in unify ctx t e.etype e.epos; SMagicExpr((PIdent v,e.epos),Obj.magic e) | SExpr (vl,e) -> let e = type_expr ctx e in let tl = List.map (pvar true) vl in unify ctx (mk_tup ctx.gen tl) e.etype e.epos; let tup = PTuple (List.map (fun v -> PIdent v, e.epos) vl) in SMagicExpr((tup,e.epos),Obj.magic e) | SMagicExpr _ -> assert false ) l in restore_locals ctx locals; t , PStream (l,k) ) in pt , (pat,p) and type_match ctx t cl p = let ret = t_mono ctx.gen in let cl = List.map (fun (pl,wh,pe) -> let first = ref true in let h = Hashtbl.create 0 in let mainset = ref SSet.empty in let pl = List.map (fun pat -> let set = ref SSet.empty in let pt , pat = type_pattern ctx h set false pat in if !first then begin first := false; mainset := !set; end else begin let s1 = SSet.diff !set !mainset in let s2 = SSet.diff !mainset !set in SSet.iter (fun s -> error (Custom ("Variable " ^ s ^ " must occur in all patterns")) p) (SSet.union s1 s2); end; unify ctx pt t p; pat ) pl in let locals = save_locals ctx in Hashtbl.iter (fun v t -> add_local ctx v t) h; let wh = (match wh with | None -> None | Some e -> let e = type_expr ctx e in unify ctx e.etype t_bool e.epos; Some e ) in let pe = type_expr ctx pe in unify ctx pe.etype ret (pos pe); restore_locals ctx locals; pl , wh , pe ) cl in let rec loop cl = match cl with | TModule(path,TConstr c) :: l -> let path , ut , t = get_constr ctx path c null_pos in if ut == t_error then false else (match tlinks false ut with | TUnion (n,_) -> n = List.length cl | _ -> assert false) | TBool b :: l -> let e = List.exists (fun c -> c = TBool (not b)) l in prerr_endline (if e then "ok" else "notok"); e | TVoid :: _ -> true | _ :: l -> loop cl | [] -> false in Mlmatch.fully_matched_ref := loop; let partial , m = Mlmatch.make cl p in partial , m , ret let modules ctx = let h = Hashtbl.create 0 in Hashtbl.iter (fun p m -> match m.expr with | None -> () | Some e -> let deps = ref (if m.path = ["Core"] || Hashtbl.mem m.deps ["Core"] then [] else [["Core"]]) in let idents = ref [] in Hashtbl.iter (fun _ m -> deps := m.path :: !deps ) m.deps; PMap.iter (fun i t -> idents := i :: !idents ) m.idents; Hashtbl.add h p (e,!deps,!idents) ) ctx.modules; h let open_file ctx file p = let rec loop = function | [] -> error (Custom ("File not found " ^ file)) p | p :: l -> try let f = p ^ file in f , open_in f with _ -> loop l in loop ctx.classpath let load_module ctx m p = try Hashtbl.find ctx.modules m with Not_found -> let file , ch = open_file ctx (String.concat "/" m ^ ".nml") p in let is_core , core = (try false , Hashtbl.find ctx.modules ["Core"] with Not_found -> true , ctx.current ) in let ctx = { ctx with tmptypes = Hashtbl.create 0; functions = []; opens = [core]; current = (if is_core then ctx.current else { path = m; constrs = Hashtbl.create 0; records = Hashtbl.create 0; types = Hashtbl.create 0; expr = None; idents = PMap.empty; deps = Hashtbl.create 0; }) } in Hashtbl.add ctx.modules m ctx.current; let ast = Mlparser.parse (Lexing.from_channel ch) file in if !verbose then print_endline ("Parsed " ^ file); let e = (match ast with | EBlock (e :: l) , p -> let e = type_block ctx e in let el , t = List.fold_left (fun (l,t) e -> let e = type_block ctx e in e :: l , e.etype ) ([e] , e.etype) l in type_functions ctx; mk (TBlock (List.rev el)) t p | _ -> type_expr ctx ast ) in ctx.current.expr <- Some e; if !verbose then print_endline ("Typing done with " ^ file); ctx.current let context cpath = let ctx = { gen = generator(); tmptypes = Hashtbl.create 0; modules = Hashtbl.create 0; functions = []; opens = []; mink = 0; classpath = cpath; curfunction = "anonymous"; current = { path = ["Core"]; expr = None; idents = PMap.empty; constrs = Hashtbl.create 0; types = Hashtbl.create 0; deps = Hashtbl.create 0; records = Hashtbl.create 0; }; } in let add_type args name t = ignore(type_expr ctx (ETypeDecl (args,name,t) , null_pos)); in let add_variable name t = ctx.current.idents <- PMap.add name t ctx.current.idents in add_type [] "bool" EAbstract; add_type ["a"] "list" (EUnion ["[]",None;"::",Some (ETuple [ EPoly "a"; EType (Some (EPoly "a"),[],"list"); ])]); add_variable "neko" (mk_fun ctx.gen [t_polymorph ctx.gen] (t_polymorph ctx.gen)); let core = load_module ctx ["Core"] null_pos in ctx ;; Mlmatch.error_ref := (fun msg p -> error (Custom msg) p); load_module_ref := load_moduleneko-2-2-0/libs/ocaml/nast.ml000066400000000000000000000110151321613172000157620ustar00rootroot00000000000000(* * Neko AST for OCaml * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) type pos = { psource : string; pline : int; } type constant = | True | False | Null | This | Int of int | Float of string | String of string | Builtin of string | Ident of string type while_flag = | NormalWhile | DoWhile type expr_decl = | EConst of constant | EBlock of expr list | EParenthesis of expr | EField of expr * string | ECall of expr * expr list | EArray of expr * expr | EVars of (string * expr option) list | EWhile of expr * expr * while_flag | EIf of expr * expr * expr option | ETry of expr * string * expr | EFunction of string list * expr | EBinop of string * expr * expr | EReturn of expr option | EBreak of expr option | EContinue | ENext of expr * expr | EObject of (string * expr) list | ELabel of string | ESwitch of expr * (expr * expr) list * expr option | ENeko of string and expr = expr_decl * pos let pos = snd let null_pos = { pline = 0; psource = "" } let mk_call v args p = ECall (v,args) , p let mk_call0 v p = ECall (v,[]) , p let mk_call1 v a p = ECall (v,[a]) , p let mk_ident i p = EConst (Ident i) , p let mk_builtin b p = EConst (Builtin b) , p let mk_int i p = EConst (Int i) , p let mk_string s p = EConst (String s) , p let mk_binop op e1 e2 p = EBinop (op,e1,e2) , p let map f (e,p) = (match e with | EBlock el -> EBlock (List.map f el) | EParenthesis e -> EParenthesis (f e) | EField (e,s) -> EField (f e, s) | ECall (e,el) -> ECall (f e, List.map f el) | EArray (e1,e2) -> EArray (f e1, f e2) | EVars vl -> EVars (List.map (fun (v,e) -> v , match e with None -> None | Some e -> Some (f e)) vl) | EWhile (e1,e2,flag) -> EWhile (f e1, f e2, flag) | EIf (e,e1,e2) -> EIf (f e, f e1, match e2 with None -> None | Some e -> Some (f e)) | ETry (e,ident,e2) -> ETry (f e, ident, f e2) | EFunction (params,e) -> EFunction (params, f e) | EBinop (op,e1,e2) -> EBinop (op, f e1, f e2) | EReturn (Some e) -> EReturn (Some (f e)) | EBreak (Some e) -> EBreak (Some (f e)) | ENext (e1,e2) -> ENext (f e1,f e2) | EObject fl -> EObject (List.map (fun (s,e) -> s , f e) fl) | ESwitch (e,cases,def) -> ESwitch (f e,List.map (fun(e1,e2) -> f e1, f e2) cases,match def with None -> None | Some e -> Some (f e)) | EReturn None | EBreak None | EContinue | ENeko _ | ELabel _ | EConst _ as x -> x) , p let iter f (e,p) = match e with | EBlock el -> List.iter f el | EParenthesis e -> f e | EField (e,s) -> f e | ECall (e,el) -> f e; List.iter f el | EArray (e1,e2) -> f e1; f e2 | EVars vl -> List.iter (fun (_,e) -> match e with None -> () | Some e -> f e) vl | EWhile (e1,e2,_) -> f e1; f e2 | EIf (e,e1,e2) -> f e; f e1; (match e2 with None -> () | Some e -> f e) | ETry (e1,_,e2) -> f e1; f e2 | EFunction (_,e) -> f e | EBinop (_,e1,e2) -> f e1; f e2 | EReturn (Some e) -> f e | EBreak (Some e) -> f e | ENext (e1,e2) -> f e1; f e2 | EObject fl -> List.iter (fun (_,e) -> f e) fl | ESwitch (e,cases,def) -> f e; List.iter (fun(e1,e2) -> f e1; f e2) cases; (match def with None -> () | Some e -> f e) | EReturn None | EBreak None | EContinue | ENeko _ | ELabel _ | EConst _ -> () let is_printable c = c >= '\032' && c <= '\126' let escape s = let b = Buffer.create (String.length s) in for i = 0 to (String.length s) - 1 do match s.[i] with | '\n' -> Buffer.add_string b "\\n" | '\t' -> Buffer.add_string b "\\t" | '\r' -> Buffer.add_string b "\\r" | '\\' -> Buffer.add_string b "\\\\" | c when c == '"' || not (is_printable c) -> Buffer.add_string b (Printf.sprintf "\\%.3d" (int_of_char c)) | c -> Buffer.add_char b c done; Buffer.contents b let s_constant = function | True -> "true" | False -> "false" | Null -> "null" | This -> "this" | Int i -> string_of_int i | Float s -> s | String s -> "\"" ^ escape s ^ "\"" | Builtin s -> "$" ^ s | Ident s -> s neko-2-2-0/libs/ocaml/neko/000077500000000000000000000000001321613172000154215ustar00rootroot00000000000000neko-2-2-0/libs/ocaml/neko/bytecode.ml000066400000000000000000000301021321613172000175450ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) type opcode = (* getters *) | AccNull | AccTrue | AccFalse | AccThis | AccInt of int | AccStack of int | AccGlobal of int | AccEnv of int | AccField of string | AccArray | AccIndex of int | AccBuiltin of string (* setters *) | SetStack of int | SetGlobal of int | SetEnv of int | SetField of string | SetArray | SetIndex of int | SetThis (* stack ops *) | Push | Pop of int | Call of int | ObjCall of int | Jump of int | JumpIf of int | JumpIfNot of int | Trap of int | EndTrap | Ret of int | MakeEnv of int | MakeArray of int (* value ops *) | Bool | IsNull | IsNotNull | Add | Sub | Mult | Div | Mod | Shl | Shr | UShr | Or | And | Xor | Eq | Neq | Gt | Gte | Lt | Lte | Not | TypeOf | Compare | Hash | New type global = | GlobalVar of string | GlobalFunction of int * int | GlobalString of string | GlobalFloat of string exception Invalid_file let trap_stack_delta = 5 let max_call_args = 5 let hash_field s = let acc = ref 0 in for i = 0 to String.length s - 1 do acc := 223 * !acc + Char.code (String.unsafe_get s i) done; acc := !acc land ((1 lsl 31) - 1); !acc let op_param = function | AccInt _ | AccStack _ | AccGlobal _ | AccEnv _ | AccField _ | AccBuiltin _ | SetStack _ | SetGlobal _ | SetEnv _ | SetField _ | Pop _ | Call _ | ObjCall _ | Jump _ | JumpIf _ | JumpIfNot _ | Trap _ | MakeEnv _ | MakeArray _ | Ret _ | AccIndex _ | SetIndex _ -> true | AccNull | AccTrue | AccFalse | AccThis | AccArray | SetArray | SetThis | Push | EndTrap | Bool | Add | Sub | Mult | Div | Mod | Shl | Shr | UShr | Or | And | Xor | Eq | Neq | Gt | Gte | Lt | Lte | IsNull | IsNotNull | Not | TypeOf | Compare | Hash | New -> false let code_tables ops = let ids = Hashtbl.create 0 in Array.iter (function | AccField s | SetField s | AccBuiltin s -> let id = hash_field s in (try let f = Hashtbl.find ids id in if f <> s then failwith ("Field hashing conflict " ^ s ^ " and " ^ f); with Not_found -> Hashtbl.add ids id s) | _ -> () ) ops; let p = ref 0 in let pos = Array.create (Array.length ops + 1) 0 in Array.iteri (fun i op -> Array.unsafe_set pos i !p; p := !p + (if op_param op then 2 else 1); ) ops; Array.unsafe_set pos (Array.length ops) !p; ids , pos , !p let write ch (globals,ops) = IO.nwrite ch "NEKO"; let globals = DynArray.of_array globals in let ids , pos , csize = code_tables ops in IO.write_i32 ch (DynArray.length globals); IO.write_i32 ch (Hashtbl.length ids); IO.write_i32 ch csize; DynArray.iter (function | GlobalVar s -> IO.write_byte ch 1; IO.nwrite ch s; IO.write ch '\000'; | GlobalFunction (p,nargs) -> IO.write_byte ch 2; IO.write_i32 ch (pos.(p) lor (nargs lsl 24)) | GlobalString s -> IO.write_byte ch 3; IO.write_ui16 ch (String.length s); IO.nwrite ch s | GlobalFloat s -> IO.write_byte ch 4; IO.nwrite ch s; IO.write ch '\000' ) globals; Hashtbl.iter (fun _ s -> IO.nwrite ch s; IO.write ch '\000'; ) ids; Array.iteri (fun i op -> let pop = ref None in let opid = (match op with | AccNull -> 0 | AccTrue -> 1 | AccFalse -> 2 | AccThis -> 3 | AccInt n -> pop := Some n; 4 | AccStack n -> pop := Some n; 5 | AccGlobal n -> pop := Some n; 6 | AccEnv n -> pop := Some n; 7 | AccField s -> pop := Some (hash_field s); 8 | AccArray -> 9 | AccIndex n -> pop := Some n; 10 | AccBuiltin s -> pop := Some (hash_field s); 11 | SetStack n -> pop := Some n; 12 | SetGlobal n -> pop := Some n; 13 | SetEnv n -> pop := Some n; 14 | SetField s -> pop := Some (hash_field s); 15 | SetArray -> 16 | SetIndex n -> pop := Some n; 17 | SetThis -> 18 | Push -> 19 | Pop n -> pop := Some n; 20 | Call n -> pop := Some n; 21 | ObjCall n -> pop := Some n; 22 | Jump n -> pop := Some (pos.(i+n) - pos.(i)); 23 | JumpIf n -> pop := Some (pos.(i+n) - pos.(i)); 24 | JumpIfNot n -> pop := Some (pos.(i+n) - pos.(i)); 25 | Trap n -> pop := Some (pos.(i+n) - pos.(i)); 26 | EndTrap -> 27 | Ret n -> pop := Some n; 28 | MakeEnv n -> pop := Some n; 29 | MakeArray n -> pop := Some n; 30 | Bool -> 31 | IsNull -> 32 | IsNotNull -> 33 | Add -> 34 | Sub -> 35 | Mult -> 36 | Div -> 37 | Mod -> 38 | Shl -> 39 | Shr -> 40 | UShr -> 41 | Or -> 42 | And -> 43 | Xor -> 44 | Eq -> 45 | Neq -> 46 | Gt -> 47 | Gte -> 48 | Lt -> 49 | Lte -> 50 | Not -> 51 | TypeOf -> 52 | Compare -> 53 | Hash -> 54 | New -> 55 ) in match !pop with | None -> IO.write_byte ch (opid lsl 2) | Some n when opid < 32 && (n = 0 || n = 1) -> IO.write_byte ch ((opid lsl 3) lor (n lsl 2) lor 1) | Some n when n >= 0 && n <= 0xFF -> IO.write_byte ch ((opid lsl 2) lor 2); IO.write_byte ch n | Some n -> IO.write_byte ch ((opid lsl 2) lor 3); IO.write_i32 ch n ) ops let read_string ch = let b = Buffer.create 5 in let rec loop() = let c = IO.read ch in if c = '\000' then Buffer.contents b else begin Buffer.add_char b c; loop() end; in loop() let read ch = try let head = IO.nread ch 4 in if head <> "NEKO" then raise Invalid_file; let nglobals = IO.read_i32 ch in let nids = IO.read_i32 ch in let csize = IO.read_i32 ch in if nglobals < 0 || nglobals > 0xFFFF || nids < 0 || nids > 0xFFFF || csize < 0 || csize > 0xFFFFFF then raise Invalid_file; let globals = Array.init nglobals (fun _ -> match IO.read_byte ch with | 1 -> GlobalVar (read_string ch) | 2 -> let v = IO.read_i32 ch in GlobalFunction (v land 0xFFFFFF, v lsr 24) | 3 -> let len = IO.read_ui16 ch in GlobalString (IO.nread ch len) | 4 -> GlobalFloat (read_string ch) | _ -> raise Invalid_file ) in let ids = Hashtbl.create 0 in let rec loop n = if n = 0 then () else let s = read_string ch in let id = hash_field s in try let s2 = Hashtbl.find ids id in if s <> s2 then raise Invalid_file; with Not_found -> Hashtbl.add ids id s; loop (n-1) in loop nids; let pos = Array.create (csize+1) (-1) in let cpos = ref 0 in let jumps = ref [] in let ops = DynArray.create() in while !cpos < csize do let code = IO.read_byte ch in let op , p = (match code land 3 with | 0 -> code lsr 2 , 0 | 1 -> code lsr 3 , ((code lsr 2) land 1) | 2 -> code lsr 2 , IO.read_byte ch | 3 -> code lsr 2 , IO.read_i32 ch | _ -> assert false ) in let op = (match op with | 0 -> AccNull | 1 -> AccTrue | 2 -> AccFalse | 3 -> AccThis | 4 -> AccInt p | 5 -> AccStack p | 6 -> AccGlobal p | 7 -> AccEnv p | 8 -> AccField (try Hashtbl.find ids p with Not_found -> raise Invalid_file) | 9 -> AccArray | 10 -> AccIndex p | 11 -> AccBuiltin (try Hashtbl.find ids p with Not_found -> raise Invalid_file) | 12 -> SetStack p | 13 -> SetGlobal p | 14 -> SetEnv p | 15 -> SetField (try Hashtbl.find ids p with Not_found -> raise Invalid_file) | 16 -> SetArray | 17 -> SetIndex p | 18 -> SetThis | 19 -> Push | 20 -> Pop p | 21 -> Call p | 22 -> ObjCall p | 23 -> jumps := (!cpos , DynArray.length ops) :: !jumps; Jump p | 24 -> jumps := (!cpos , DynArray.length ops) :: !jumps; JumpIf p | 25 -> jumps := (!cpos , DynArray.length ops) :: !jumps; JumpIfNot p | 26 -> jumps := (!cpos , DynArray.length ops) :: !jumps; Trap p | 27 -> EndTrap | 28 -> Ret p | 29 -> MakeEnv p | 30 -> MakeArray p | 31 -> Bool | 32 -> IsNull | 33 -> IsNotNull | 34 -> Add | 35 -> Sub | 36 -> Mult | 37 -> Div | 38 -> Mod | 39 -> Shl | 40 -> Shr | 41 -> UShr | 42 -> Or | 43 -> And | 44 -> Xor | 45 -> Eq | 46 -> Neq | 47 -> Gt | 48 -> Gte | 49 -> Lt | 50 -> Lte | 51 -> Not | 52 -> TypeOf | 53 -> Compare | 54 -> Hash | 55 -> New | _ -> raise Invalid_file ) in pos.(!cpos) <- DynArray.length ops; cpos := !cpos + (if op_param op then 2 else 1); DynArray.add ops op; done; if !cpos <> csize then raise Invalid_file; pos.(!cpos) <- DynArray.length ops; let pos_index i sadr = let idx = pos.(sadr) in if idx = -1 then raise Invalid_file; idx - i in List.iter (fun (a,i) -> DynArray.set ops i (match DynArray.get ops i with | Jump p -> Jump (pos_index i (a+p)) | JumpIf p -> JumpIf (pos_index i (a+p)) | JumpIfNot p -> JumpIfNot (pos_index i (a+p)) | Trap p -> Trap (pos_index i (a+p)) | _ -> assert false) ) !jumps; Array.iteri (fun i g -> match g with | GlobalFunction (f,n) -> globals.(i) <- GlobalFunction (pos_index 0 f,n) | _ -> () ) globals; globals , DynArray.to_array ops with | IO.No_more_input | IO.Overflow _ -> raise Invalid_file let escape str = String.escaped str let dump ch (globals,ops) = let ids, pos , csize = code_tables ops in IO.printf ch "nglobals : %d\n" (Array.length globals); IO.printf ch "nfields : %d\n" (Hashtbl.length ids); IO.printf ch "codesize : %d ops , %d total\n" (Array.length ops) csize; IO.printf ch "GLOBALS =\n"; let marks = Array.create csize false in Array.iteri (fun i g -> IO.printf ch " global %d : %s\n" i (match g with | GlobalVar s -> "var " ^ s | GlobalFunction (p,n) -> if p >= 0 && p < csize then marks.(p) <- true; "function " ^ string_of_int p ^ " nargs " ^ string_of_int n | GlobalString s -> "string \"" ^ escape s ^ "\"" | GlobalFloat s -> "float " ^ s) ) globals; IO.printf ch "FIELDS =\n"; Hashtbl.iter (fun h f -> IO.printf ch " %s%s%.8X\n" f (if String.length f >= 24 then " " else String.make (24 - String.length f) ' ') h; ) ids; IO.printf ch "CODE =\n"; let str s i = s ^ " " ^ string_of_int i in let bpos = ref 0 in Array.iteri (fun pos op -> if marks.(pos) then IO.write ch '\n'; IO.printf ch "%.6X %6d %s\n" (!bpos) pos (match op with | AccNull -> "AccNull" | AccTrue -> "AccTrue" | AccFalse -> "AccFalse" | AccThis -> "AccThis" | AccInt i -> str "AccInt" i | AccStack i -> str "AccStack" i | AccGlobal i -> str "AccGlobal" i | AccEnv i -> str "AccEnv" i | AccField s -> "AccField " ^ s | AccArray -> "AccArray" | AccIndex i -> str "AccIndex" i | AccBuiltin s -> "AccBuiltin " ^ s | SetStack i -> str "SetStack" i | SetGlobal i -> str "SetGlobal" i | SetEnv i -> str "SetEnv" i | SetField f -> "SetField " ^ f | SetArray -> "SetArray" | SetIndex i -> str "SetIndex" i | SetThis -> "SetThis" | Push -> "Push" | Pop i -> str "Pop" i | Call i -> str "Call" i | ObjCall i -> str "ObjCall" i | Jump i -> str "Jump" (pos + i) | JumpIf i -> str "JumpIf" (pos + i) | JumpIfNot i -> str "JumpIfNot" (pos + i) | Trap i -> str "Trap" (pos + i) | EndTrap -> "EndTrap" | Ret i -> str "Ret" i | MakeEnv i -> str "MakeEnv" i | MakeArray i -> str "MakeArray" i | Bool -> "Bool" | IsNull -> "IsNull" | IsNotNull -> "IsNotNull" | Add -> "Add" | Sub -> "Sub" | Mult -> "Mult" | Div -> "Div" | Mod -> "Mod" | Shl -> "Shl" | Shr -> "Shr" | UShr -> "UShr" | Or -> "Or" | And -> "And" | Xor -> "Xor" | Eq -> "Eq" | Neq -> "Neq" | Gt -> "Gt" | Gte -> "Gte" | Lt -> "Lt" | Lte -> "Lte" | Not -> "Not" | TypeOf -> "TypeOf" | Compare -> "Compare" | Hash -> "Hash" | New -> "New" ); bpos := !bpos + if op_param op then 2 else 1; ) ops; IO.printf ch "END\n" neko-2-2-0/libs/ocaml/neko/compile.ml000066400000000000000000000423531321613172000174120ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast open Bytecode type label = { lname : string; ltraps : int; lstack : int; mutable lpos : int option; mutable lwait : (unit -> unit) list; } type context = { mutable ops : opcode DynArray.t; mutable locals : (string,int) PMap.t; globals : (global,int) Hashtbl.t; gobjects : (string list,int) Hashtbl.t; mutable env : (string,int) PMap.t; mutable nenv : int; mutable stack : int; mutable loop_limit : int; mutable limit : int; mutable ntraps : int; mutable breaks : ((unit -> unit) * pos) list; mutable continues : ((unit -> unit) * pos) list; mutable functions : (opcode DynArray.t * int * int) list; mutable gtable : global DynArray.t; labels : (string,label) Hashtbl.t; } type error_msg = | Custom of string exception Error of error_msg * pos let error e p = raise (Error (e,p)) let error_msg = function | Custom s -> s let stack_delta = function | AccNull | AccTrue | AccFalse | AccThis | AccInt _ | AccStack _ | AccGlobal _ | AccEnv _ | AccField _ | AccBuiltin _ | AccIndex _ | JumpIf _ | JumpIfNot _ | Jump _ | Ret _ | SetGlobal _ | SetStack _ | SetEnv _ | SetThis | Bool | EndTrap | IsNull | IsNotNull | Not | Hash | TypeOf | New -> 0 | Add | Sub | Mult | Div | Mod | Shl | Shr | UShr | Or | And | Xor | Eq | Neq | Gt | Gte | Lt | Lte -> -1 | AccArray -> -1 | SetField _ | SetIndex _ | Compare -> -1 | SetArray -> -2 | Push -> 1 | Pop x -> -x | Call nargs -> -nargs | ObjCall nargs -> -(nargs + 1) | MakeEnv size | MakeArray size -> -size | Trap _ -> trap_stack_delta let pos ctx = DynArray.length ctx.ops let write ctx op = ctx.stack <- ctx.stack + stack_delta op; DynArray.add ctx.ops op let jmp ?cond ctx = let p = pos ctx in write ctx (Jump 0); (fun() -> DynArray.set ctx.ops p (match cond with | None -> Jump (pos ctx - p) | Some true -> JumpIf (pos ctx - p) | Some false -> JumpIfNot (pos ctx -p)) ) let goto ctx p = write ctx (Jump (p - pos ctx)) let global ctx g = try Hashtbl.find ctx.globals g with Not_found -> let gid = DynArray.length ctx.gtable in Hashtbl.add ctx.globals g gid; DynArray.add ctx.gtable g; gid let save_breaks ctx = let oldc = ctx.continues in let oldb = ctx.breaks in let oldl = ctx.loop_limit in ctx.loop_limit <- ctx.stack; ctx.breaks <- []; ctx.continues <- []; ctx , oldc, oldb , oldl let process_continues (ctx,oldc,_,_) = List.iter (fun (f,_) -> f()) ctx.continues; ctx.continues <- oldc let process_breaks (ctx,_,oldb,oldl) = List.iter (fun (f,_) -> f()) ctx.breaks; ctx.loop_limit <- oldl; ctx.breaks <- oldb let check_breaks ctx = List.iter (fun (_,p) -> error (Custom "Break outside a loop") p) ctx.breaks; List.iter (fun (_,p) -> error (Custom "Continue outside a loop") p) ctx.continues let rec scan_labels ctx supported e = match fst e with | EFunction (args,e) -> let nargs = List.length args in let ntraps = ctx.ntraps in ctx.ntraps <- 0; ctx.stack <- ctx.stack + nargs; scan_labels ctx supported e; ctx.stack <- ctx.stack - nargs; ctx.ntraps <- ntraps | EBlock _ -> let old = ctx.stack in Ast.iter (scan_labels ctx supported) e; ctx.stack <- old | EVars l -> List.iter (fun (_,e) -> (match e with | None -> () | Some e -> scan_labels ctx supported e); ctx.stack <- ctx.stack + 1 ) l | ELabel l when not supported -> error (Custom "Label is not supported in this part of the program") (snd e); | ELabel l when Hashtbl.mem ctx.labels l -> error (Custom ("Duplicate label " ^ l)) (snd e) | ELabel l -> Hashtbl.add ctx.labels l { lname = l; ltraps = ctx.ntraps; lstack = ctx.stack; lpos = None; lwait = []; } | ETry (e,_,e2) -> ctx.stack <- ctx.stack + trap_stack_delta; ctx.ntraps <- ctx.ntraps + 1; scan_labels ctx supported e; ctx.stack <- ctx.stack - trap_stack_delta; ctx.ntraps <- ctx.ntraps - 1; ctx.stack <- ctx.stack + 1; scan_labels ctx supported e2; ctx.stack <- ctx.stack - 1; | EBinop ("=",e1,e2) -> let rec is_extended (e,_) = match e with | EParenthesis e -> is_extended e | EArray _ | EField _ -> true | _ -> false in let ext = is_extended e1 in if ext then ctx.stack <- ctx.stack + 1; scan_labels ctx supported e2; ctx.stack <- ctx.stack + 1; scan_labels ctx supported e1; ctx.stack <- ctx.stack - (if ext then 2 else 1); | ECall ((EConst (Builtin x),_),el) when x <> "array" && x <> "apply" -> Ast.iter (scan_labels ctx false) e | ECall (_,el) -> List.iter (fun e -> scan_labels ctx supported e; ctx.stack <- ctx.stack + 1; ) el; ctx.stack <- ctx.stack - List.length el | EObject fl -> ctx.stack <- ctx.stack + 2; List.iter (fun (s,e) -> scan_labels ctx supported e ) fl; ctx.stack <- ctx.stack - 2; | EConst _ | EContinue | EBreak _ | EReturn _ | EIf _ | EWhile _ | EParenthesis _ | ENext _ -> Ast.iter (scan_labels ctx supported) e | EBinop _ | EArray _ | EField _ -> Ast.iter (scan_labels ctx false) e let compile_constant ctx c p = match c with | True -> write ctx AccTrue | False -> write ctx AccFalse | Null -> write ctx AccNull | This -> write ctx AccThis | Int n -> write ctx (AccInt n) | Float f -> write ctx (AccGlobal (global ctx (GlobalFloat f))) | String s -> write ctx (AccGlobal (global ctx (GlobalString s))) | Builtin s -> (match s with | "tnull" -> write ctx (AccInt 0) | "tint" -> write ctx (AccInt 1) | "tfloat" -> write ctx (AccInt 2) | "tbool" -> write ctx (AccInt 3) | "tstring" -> write ctx (AccInt 4) | "tobject" -> write ctx (AccInt 5) | "tarray" -> write ctx (AccInt 6) | "tfunction" -> write ctx (AccInt 7) | "tabstract" -> write ctx (AccInt 8) | s -> write ctx (AccBuiltin s)) | Ident s -> try let e = PMap.find s ctx.env in write ctx (AccEnv e); with Not_found -> try let l = PMap.find s ctx.locals in if l <= ctx.limit then begin let e = ctx.nenv in ctx.nenv <- ctx.nenv + 1; ctx.env <- PMap.add s e ctx.env; write ctx (AccEnv e); end else write ctx (AccStack (ctx.stack - l)); with Not_found -> let g = global ctx (GlobalVar s) in write ctx (AccGlobal g) let rec compile_binop ctx op e1 e2 p = match op with | "=" -> (match fst e1 with | EConst (Ident s) -> compile ctx e2; (try let e = PMap.find s ctx.env in write ctx (SetEnv e); with Not_found -> try let l = PMap.find s ctx.locals in if l <= ctx.limit then begin let e = ctx.nenv in ctx.nenv <- ctx.nenv + 1; ctx.env <- PMap.add s e ctx.env; write ctx (SetEnv e); end else write ctx (SetStack (ctx.stack - l)) with Not_found -> let g = global ctx (GlobalVar s) in write ctx (SetGlobal g)) | EField (e,f) -> compile ctx e; write ctx Push; compile ctx e2; write ctx (SetField f) | EArray (e1,(EConst (Int n),_)) -> compile ctx e1; write ctx Push; compile ctx e2; write ctx (SetIndex n) | EArray (ea,ei) -> compile ctx ei; write ctx Push; compile ctx ea; write ctx Push; compile ctx e2; write ctx SetArray | EConst This -> compile ctx e2; write ctx SetThis | _ -> error (Custom "Invalid assign") p) | "&&" -> compile ctx e1; let jnext = jmp ~cond:false ctx in compile ctx e2; jnext() | "||" -> compile ctx e1; let jnext = jmp ~cond:true ctx in compile ctx e2; jnext() | _ -> match op , e1 , e2 with | "==" , _ , (EConst Null,_) -> compile ctx e1; write ctx IsNull | "!=" , _ , (EConst Null,_) -> compile ctx e1; write ctx IsNotNull | "==" , (EConst Null,_) , _ -> compile ctx e2; write ctx IsNull | "!=" , (EConst Null,_) , _ -> compile ctx e2; write ctx IsNotNull | _ -> compile ctx e1; write ctx Push; compile ctx e2; match op with | "+" -> write ctx Add | "-" -> write ctx Sub | "/" -> write ctx Div | "*" -> write ctx Mult | "%" -> write ctx Mod | "<<" -> write ctx Shl | ">>" -> write ctx Shr | ">>>" -> write ctx UShr | "|" -> write ctx Or | "&" -> write ctx And | "^" -> write ctx Xor | "==" -> write ctx Eq | "!=" -> write ctx Neq | ">" -> write ctx Gt | ">=" -> write ctx Gte | "<" -> write ctx Lt | "<=" -> write ctx Lte | _ -> error (Custom "Unknown operation") p and compile_function ctx params e = let limit = ctx.limit in let ops = ctx.ops in let breaks = ctx.breaks in let continues = ctx.continues in let locals = ctx.locals in let env = ctx.env in let nenv = ctx.nenv in let ntraps = ctx.ntraps in ctx.ops <- DynArray.create(); ctx.breaks <- []; ctx.continues <- []; ctx.env <- PMap.empty; ctx.nenv <- 0; ctx.ntraps <- 0; ctx.limit <- ctx.stack; List.iter (fun v -> ctx.stack <- ctx.stack + 1; ctx.locals <- PMap.add v ctx.stack ctx.locals; ) params; let s = ctx.stack in compile ctx e; write ctx (Ret (ctx.stack - ctx.limit)); assert( ctx.stack = s ); check_breaks ctx; ctx.stack <- ctx.limit; ctx.limit <- limit; ctx.breaks <- breaks; ctx.continues <- continues; ctx.locals <- locals; let gid = DynArray.length ctx.gtable in ctx.functions <- (ctx.ops,gid,List.length params) :: ctx.functions; DynArray.add ctx.gtable (GlobalFunction (gid,-1)); ctx.ops <- ops; let local_env = ctx.env in let local_nenv = ctx.nenv in ctx.env <- env; ctx.ntraps <- ntraps; ctx.nenv <- nenv; if local_nenv > 0 then begin let a = Array.create local_nenv "" in PMap.iter (fun v i -> a.(i) <- v) local_env; Array.iter (fun v -> compile_constant ctx (Ident v) null_pos; write ctx Push; ) a; write ctx (AccGlobal gid); write ctx (MakeEnv local_nenv); end else write ctx (AccGlobal gid); and compile_builtin ctx b el p = match b , el with | "istrue" , [e] -> compile ctx e; write ctx Bool | "not" , [e] -> compile ctx e; write ctx Not | "typeof" , [e] -> compile ctx e; write ctx TypeOf | "hash" , [e] -> compile ctx e; write ctx Hash | "compare" , [e1;e2] -> compile ctx e1; write ctx Push; compile ctx e2; write ctx Compare | "goto" , [ EConst (Ident l) , _ ] -> let l = (try Hashtbl.find ctx.labels l with Not_found -> error (Custom ("Unknown label " ^ l)) p) in let os = ctx.stack in let ntraps = ref ctx.ntraps in let etraps = ref [] in while !ntraps > l.ltraps do write ctx EndTrap; ctx.stack <- ctx.stack - trap_stack_delta; ntraps := !ntraps - 1; done; while !ntraps < l.ltraps do etraps := (pos ctx) :: !etraps; write ctx (Trap 0); ntraps := !ntraps + 1; done; if ctx.stack > l.lstack then write ctx (Pop (ctx.stack - l.lstack)); while ctx.stack < l.lstack do write ctx Push; done; ctx.stack <- os; (match l.lpos with | None -> l.lwait <- jmp ctx :: l.lwait | Some p -> write ctx (Jump p)); if !etraps <> [] then begin List.iter (fun p -> DynArray.set ctx.ops p (Trap (pos ctx - p)); ) !etraps; write ctx Push; compile_constant ctx (Builtin "throw") p; write ctx (Call 1); end; | "goto" , _ -> error (Custom "Invalid $goto statement") p | _ -> List.iter (fun e -> compile ctx e; write ctx Push; ) el; compile_constant ctx (Builtin b) p; write ctx (Call (List.length el)) and compile ctx (e,p) = match e with | EConst c -> compile_constant ctx c p | EBlock [] -> write ctx AccNull | EBlock el -> let locals = ctx.locals in let stack = ctx.stack in List.iter (compile ctx) el; if stack < ctx.stack then write ctx (Pop (ctx.stack - stack)); assert( stack = ctx.stack ); ctx.locals <- locals | EParenthesis e -> compile ctx e | EField (e,f) -> compile ctx e; write ctx (AccField f) | ECall ((EConst (Builtin "array"),_),el) -> List.iter (fun e -> compile ctx e; write ctx Push; ) el; write ctx (MakeArray (List.length el)); | ECall (_,el) when List.length el > max_call_args -> error (Custom "Too many arguments") p | ECall ((EField (e,f),_),el) -> List.iter (fun e -> compile ctx e; write ctx Push; ) el; compile ctx e; write ctx Push; write ctx (AccField f); write ctx (ObjCall (List.length el)) | ECall ((EConst (Builtin b),_),el) -> compile_builtin ctx b el p | ECall (e,el) -> List.iter (fun e -> compile ctx e; write ctx Push; ) el; compile ctx e; write ctx (Call (List.length el)) | EArray (e1,(EConst (Int n),_)) -> compile ctx e1; write ctx (AccIndex n) | EArray (e1,e2) -> compile ctx e1; write ctx Push; compile ctx e2; write ctx AccArray | EVars vl -> List.iter (fun (v,o) -> (match o with | None -> write ctx AccNull | Some e -> compile ctx e); write ctx Push; ctx.locals <- PMap.add v ctx.stack ctx.locals; ) vl | EWhile (econd,e,NormalWhile) -> let start = pos ctx in compile ctx econd; let jend = jmp ~cond:false ctx in let save = save_breaks ctx in compile ctx e; process_continues save; goto ctx start; process_breaks save; jend(); | EWhile (econd,e,DoWhile) -> let start = pos ctx in let save = save_breaks ctx in compile ctx e; process_continues save; compile ctx econd; write ctx (JumpIf (start - pos ctx)); process_breaks save | EIf (e,e1,e2) -> let stack = ctx.stack in compile ctx e; let jelse = jmp ~cond:false ctx in compile ctx e1; assert( stack = ctx.stack ); (match e2 with | None -> jelse() | Some e2 -> let jend = jmp ctx in jelse(); compile ctx e2; assert( stack = ctx.stack ); jend()); | ETry (e,v,ecatch) -> let start = pos ctx in write ctx (Trap 0); ctx.ntraps <- ctx.ntraps + 1; compile ctx e; ctx.ntraps <- ctx.ntraps - 1; ctx.stack <- ctx.stack - trap_stack_delta; write ctx EndTrap; let jend = jmp ctx in DynArray.set ctx.ops start (Trap (pos ctx - start)); write ctx Push; let locals = ctx.locals in ctx.locals <- PMap.add v ctx.stack ctx.locals; compile ctx ecatch; write ctx (Pop 1); ctx.locals <- locals; jend() | EBinop ("-",(EConst (Int 0),_),(EConst (Int i),_)) -> compile ctx (EConst (Int (-i)),p) | EBinop (op,e1,e2) -> compile_binop ctx op e1 e2 p | EReturn None -> write ctx AccNull; for i = 1 to ctx.ntraps do write ctx EndTrap; done; write ctx (Ret (ctx.stack - ctx.limit)); | EReturn (Some e) -> compile ctx e; for i = 1 to ctx.ntraps do write ctx EndTrap; done; write ctx (Ret (ctx.stack - ctx.limit - ctx.ntraps * trap_stack_delta)); | EBreak e -> assert (ctx.ntraps = 0); (match e with | None -> () | Some e -> compile ctx e); if ctx.loop_limit <> ctx.stack then DynArray.add ctx.ops (Pop (ctx.stack - ctx.loop_limit)); ctx.breaks <- (jmp ctx , p) :: ctx.breaks | EContinue -> assert (ctx.ntraps = 0); if ctx.loop_limit <> ctx.stack then DynArray.add ctx.ops (Pop (ctx.stack - ctx.loop_limit)); ctx.continues <- (jmp ctx , p) :: ctx.continues | EFunction (params,e) -> compile_function ctx params e | ENext (e1,e2) -> compile ctx e1; compile ctx e2 | EObject [] -> write ctx AccNull; write ctx New | EObject fl -> let fields = List.sort compare (List.map fst fl) in let id = (try Hashtbl.find ctx.gobjects fields with Not_found -> let id = global ctx (GlobalVar ("o:" ^ string_of_int (Hashtbl.length ctx.gobjects))) in Hashtbl.add ctx.gobjects fields id; id ) in write ctx (AccGlobal id); write ctx New; write ctx Push; List.iter (fun (f,e) -> write ctx Push; compile ctx e; write ctx (SetField f); write ctx (AccStack 0); ) fl; write ctx (Pop 1) | ELabel l -> let l = (try Hashtbl.find ctx.labels l with Not_found -> assert false) in if ctx.stack <> l.lstack then assert false; if ctx.ntraps <> l.ltraps then assert false; List.iter (fun f -> f()) l.lwait; l.lwait <- []; l.lpos <- Some (pos ctx) let compile file ast = let ctx = { stack = 0; loop_limit = 0; limit = -1; globals = Hashtbl.create 0; gobjects = Hashtbl.create 0; gtable = DynArray.create(); locals = PMap.empty; ops = DynArray.create(); breaks = []; continues = []; functions = []; env = PMap.empty; nenv = 0; ntraps = 0; labels = Hashtbl.create 0; } in scan_labels ctx true ast; compile ctx ast; check_breaks ctx; if ctx.functions <> [] || Hashtbl.length ctx.gobjects <> 0 then begin let ctxops = ctx.ops in let ops = DynArray.create() in ctx.ops <- ops; write ctx (Jump 0); List.iter (fun (fops,gid,nargs) -> DynArray.set ctx.gtable gid (GlobalFunction (DynArray.length ops,nargs)); DynArray.append fops ops; ) (List.rev ctx.functions); DynArray.set ops 0 (Jump (DynArray.length ops)); Hashtbl.iter (fun fl g -> write ctx AccNull; write ctx New; write ctx (SetGlobal g); List.iter (fun f -> write ctx (AccGlobal g); write ctx Push; write ctx (SetField f); ) fl ) ctx.gobjects; DynArray.append ctxops ops; end; DynArray.to_array ctx.gtable, DynArray.to_array ctx.ops neko-2-2-0/libs/ocaml/neko/lexer.mll000066400000000000000000000135741321613172000172600ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) { open Ast open Lexing type error_msg = | Invalid_character of char | Unterminated_string | Unclosed_comment | Invalid_escaped_character of int | Invalid_escape exception Error of error_msg * pos let error_msg = function | Invalid_character c when int_of_char c > 32 && int_of_char c < 128 -> Printf.sprintf "Invalid character '%c'" c | Invalid_character c -> Printf.sprintf "Invalid character 0x%.2X" (int_of_char c) | Unterminated_string -> "Unterminated string" | Unclosed_comment -> "Unclosed comment" | Invalid_escaped_character n -> Printf.sprintf "Invalid escaped character %d" n | Invalid_escape -> "Invalid escape sequence" let cur_file = ref "" let all_lines = Hashtbl.create 0 let lines = ref [] let buf = Buffer.create 100 let error e pos = raise (Error (e,{ pmin = pos; pmax = pos; pfile = !cur_file })) let keywords = let h = Hashtbl.create 3 in List.iter (fun k -> Hashtbl.add h (s_keyword k) k) [Var;While;Do;If;Else;Function;Return;Break;Continue;Try;Catch] ; h let init file = cur_file := file; lines := [] let save_lines() = Hashtbl.replace all_lines !cur_file !lines let save() = save_lines(); !cur_file let restore file = save_lines(); cur_file := file; lines := Hashtbl.find all_lines file let newline lexbuf = lines := (lexeme_end lexbuf) :: !lines let find_line p lines = let rec loop n delta = function | [] -> n , p - delta | lp :: l when lp > p -> n , p - delta | lp :: l -> loop (n+1) lp l in loop 1 0 lines let get_error_line p = let lines = List.rev (try Hashtbl.find all_lines p.pfile with Not_found -> []) in let l, _ = find_line p.pmin lines in l let get_error_pos printer p = if p.pmin = -1 then "(unknown)" else let lines = List.rev (try Hashtbl.find all_lines p.pfile with Not_found -> []) in let l1, p1 = find_line p.pmin lines in let l2, p2 = find_line p.pmax lines in if l1 = l2 then begin let s = (if p1 = p2 then Printf.sprintf " %d" p1 else Printf.sprintf "s %d-%d" p1 p2) in Printf.sprintf "%s character%s" (printer p.pfile l1) s end else Printf.sprintf "%s lines %d-%d" (printer p.pfile l1) l1 l2 let reset() = Buffer.reset buf let contents() = Buffer.contents buf let store lexbuf = Buffer.add_string buf (lexeme lexbuf) let add c = Buffer.add_string buf c let mk_tok t pmin pmax = t , { pfile = !cur_file; pmin = pmin; pmax = pmax } let mk lexbuf t = mk_tok t (lexeme_start lexbuf) (lexeme_end lexbuf) let mk_ident lexbuf = let s = lexeme lexbuf in mk lexbuf (try Keyword (Hashtbl.find keywords s) with Not_found -> Const (Ident s)) } let ident = ['a'-'z' 'A'-'Z' '_' '@'] ['a'-'z' 'A'-'Z' '0'-'9' '_' '@']* let binop = ['!' '=' '*' '/' '<' '>' '&' '|' '^' '%' '+' ':' '-'] let number = ['0'-'9'] rule token = parse | eof { mk lexbuf Eof } | ';' { mk lexbuf Semicolon } | '.' { mk lexbuf Dot } | ',' { mk lexbuf Comma } | '{' { mk lexbuf BraceOpen } | '}' { mk lexbuf BraceClose } | '(' { mk lexbuf ParentOpen } | ')' { mk lexbuf ParentClose } | '[' { mk lexbuf BracketOpen } | ']' { mk lexbuf BracketClose } | "=>" { mk lexbuf Arrow } | [' ' '\r' '\t']+ { token lexbuf } | '\n' { newline lexbuf; token lexbuf } | "0x" ['0'-'9' 'a'-'f' 'A'-'F']+ | number+ { mk lexbuf (Const (Int (int_of_string (lexeme lexbuf)))) } | number+ '.' number* | '.' number+ { mk lexbuf (Const (Float (lexeme lexbuf))) } | '$' (ident as v) { mk lexbuf (Const (Builtin v)) } | "true" { mk lexbuf (Const True) } | "false" { mk lexbuf (Const False) } | "null" { mk lexbuf (Const Null) } | "this" { mk lexbuf (Const This) } | ident { mk_ident lexbuf } | '"' { reset(); let pmin = lexeme_start lexbuf in let pmax = (try string lexbuf with Exit -> error Unterminated_string pmin) in mk_tok (Const (String (contents()))) pmin pmax; } | "/*" { reset(); let pmin = lexeme_start lexbuf in let pmax = (try comment lexbuf with Exit -> error Unclosed_comment pmin) in mk_tok (Comment (contents())) pmin pmax; } | "//" [^'\n']* { let s = lexeme lexbuf in let n = (if s.[String.length s - 1] = '\r' then 3 else 2) in mk lexbuf (CommentLine (String.sub s 2 ((String.length s)-n))) } | binop binop? | ">>>" { mk lexbuf (Binop (lexeme lexbuf)) } | _ { error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_start lexbuf) } and comment = parse | eof { raise Exit } | '\r' { comment lexbuf } | '\n' { newline lexbuf; store lexbuf; comment lexbuf } | "*/" { lexeme_end lexbuf } | '*' { store lexbuf; comment lexbuf } | [^'*' '\n' '\r']+ { store lexbuf; comment lexbuf } and string = parse | eof { raise Exit } | '\n' { newline lexbuf; store lexbuf; string lexbuf } | "\\\"" { add "\""; string lexbuf } | "\\\\" { add "\\"; string lexbuf } | "\\n" { add "\n"; string lexbuf } | "\\t" { add "\t"; string lexbuf } | "\\r" { add "\r"; string lexbuf } | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] { let i = int_of_string (String.sub (lexeme lexbuf) 1 3) in if i >= 256 then error (Invalid_escaped_character i) (lexeme_start lexbuf); add (String.make 1 (char_of_int i)); string lexbuf } | '\\' { error Invalid_escape (lexeme_start lexbuf) } | '"' { lexeme_end lexbuf } | [^'"' '\\' '\n']+ { store lexbuf; string lexbuf } neko-2-2-0/libs/ocaml/neko/main.ml000066400000000000000000000056601321613172000167060ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Printf type p_style = | StyleJava | StyleMSVC let print_style = ref StyleJava let normalize_path p = let l = String.length p in if l = 0 then "./" else match p.[l-1] with | '\\' | '/' -> p | _ -> p ^ "/" let report inf = let pos file line = (match !print_style with | StyleJava -> sprintf "%s:%d:" file line | StyleMSVC -> sprintf "%s(%d):" file line ) in prerr_endline (sprintf "%s : %s %s" (inf.Plugin.exn_pos pos) inf.Plugin.exn_name inf.Plugin.exn_message); exit 1 let dump file ch out = let data = (try Bytecode.read ch with Bytecode.Invalid_file -> IO.close_in ch; failwith ("Invalid bytecode file " ^ file)) in IO.close_in ch; Bytecode.dump out data; IO.close_out out let dump_exn = function | e -> raise e let compile file ch out = let ast = Parser.parse (Lexing.from_function (fun s p -> try IO.input ch s 0 p with IO.No_more_input -> 0)) file in IO.close_in ch; let data = Compile.compile file ast in Bytecode.write out data; IO.close_out out let compile_exn = function | Lexer.Error (m,p) -> Plugin.exn_infos "syntax error" (Lexer.error_msg m) (fun f -> Lexer.get_error_pos f p) | Parser.Error (m,p) -> Plugin.exn_infos "parse error" (Parser.error_msg m) (fun f -> Lexer.get_error_pos f p) | Compile.Error (m,p) -> Plugin.exn_infos "compile error" (Compile.error_msg m) (fun f -> Lexer.get_error_pos f p) | e -> raise e let main() = try let usage = "Neko v0.4 - (c)2005-2017 Haxe Foundation\n Usage : neko.exe [options] \n Options :" in let output = ref "n" in let args_spec = [ ("-msvc",Arg.Unit (fun () -> print_style := StyleMSVC),": use MSVC style errors"); ("-p", Arg.String (fun p -> Plugin.add_path p)," : add the file to path"); ("-o", Arg.String (fun ext -> output := String.lowercase ext)," : specify output extension"); ("-v", Arg.Unit (fun () -> Plugin.verbose := true),": verbose mode"); ] in Arg.parse args_spec (fun file -> Plugin.generate file !output ) usage; with | Plugin.Error inf -> report inf | Failure msg -> prerr_endline msg; exit 1 ;; Plugin.register "neko" "n" compile compile_exn; Plugin.register "n" "dump" dump dump_exn; at_exit mainneko-2-2-0/libs/ocaml/neko/neko.vcproj000066400000000000000000000045051321613172000176060ustar00rootroot00000000000000 neko-2-2-0/libs/ocaml/neko/parser.ml000066400000000000000000000146241321613172000172560ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast type error_msg = | Unexpected of token | Unclosed of string | Duplicate_default | Unknown_macro of string | Invalid_macro_parameters of string * int exception Error of error_msg * pos let error_msg = function | Unexpected t -> "Unexpected "^(s_token t) | Unclosed s -> "Unclosed " ^ s | Duplicate_default -> "Duplicate default declaration" | Unknown_macro m -> "Unknown macro " ^ m | Invalid_macro_parameters (m,n) -> "Invalid number of parameters for macro " ^ m ^ " : " ^ string_of_int n ^ " required" let error m p = raise (Error (m,p)) let priority = function | "=" | "+=" | "-=" | "*=" | "/=" | "|=" | "&=" | "^=" -> -3 | "&&" | "||" -> -2 | "==" | "!=" | ">" | "<" | "<=" | ">=" -> -1 | "+" | "-" -> 0 | "*" | "/" -> 1 | "|" | "&" | "^" -> 2 | "<<" | ">>" | "%" | ">>>" -> 3 | _ -> 4 let rec make_binop op e ((v,p2) as e2) = match v with | EBinop (_op,_e,_e2) when priority _op <= priority op -> let _e = make_binop op e _e in EBinop (_op,_e,_e2) , punion (pos _e) (pos _e2) | _ -> EBinop (op,e,e2) , punion (pos e) (pos e2) let rec program = parser | [< e = expr; p = program >] -> e :: p | [< '(Semicolon,_); p = program >] -> p | [< '(Eof,_) >] -> [] and expr = parser | [< '(Const ((Ident k) as i),p); s >] -> (match s with parser | [< '(Binop ":",p2); >] -> ELabel k , punion p p2 | [< s >] -> expr_next (EConst i,p) s) | [< '(Const c,p); s >] -> expr_next (EConst c,p) s | [< '(BraceOpen,p1); e = block1; s >] -> (match s with parser | [< '(BraceClose,p2); s >] -> expr_next (e,punion p1 p2) s | [< >] -> error (Unclosed "{") p1) | [< '(ParentOpen,p1); e = expr; s >] -> (match s with parser | [< '(ParentClose,p2); s >] -> expr_next (EParenthesis e,punion p1 p2) s | [< >] -> error (Unclosed "(") p1) | [< '(Keyword Var,p1); v, p2 = variables p1; s >] -> expr_next (EVars v,punion p1 p2) s | [< '(Keyword While,p1); cond = expr; e = expr; s >] -> expr_next (EWhile (cond,e,NormalWhile), punion p1 (pos e)) s | [< '(Keyword Do,p1); e = expr; '(Keyword While,_); cond = expr; s >] -> expr_next (EWhile (cond,e,DoWhile), punion p1 (pos cond)) s | [< '(Keyword If,p1); cond = expr; e = expr; s >] -> let rec loop s = match s with parser | [< '(Keyword Else,_); e2 = expr; s >] -> expr_next (EIf (cond,e,Some e2),punion p1 (pos e2)) s | [< '(Semicolon,_); s >] -> loop s | [< >] -> expr_next (EIf (cond,e,None),punion p1 (pos e)) s in loop s | [< '(Keyword Function,p1); '(ParentOpen,po); p = parameter_names; s >] -> (match s with parser | [< '(ParentClose,_); e = expr; s >] -> expr_next (EFunction (p,e),punion p1 (pos e)) s | [< >] -> error (Unclosed "(") po) | [< '(Keyword Return,p1); s >] -> (match s with parser | [< e = expr; s >] -> expr_next (EReturn (Some e), punion p1 (pos e)) s | [< '(Semicolon,_); s >] -> expr_next (EReturn None,p1) s) | [< '(Keyword Break,p1); s >] -> (match s with parser | [< e = expr; s >] -> expr_next (EBreak (Some e), punion p1 (pos e)) s | [< '(Semicolon,_); s >] -> expr_next (EBreak None,p1) s) | [< '(Keyword Continue,p1); s >] -> expr_next (EContinue,p1) s | [< '(Keyword Try,p1); e = expr; '(Keyword Catch,_); '(Const (Ident name),_); e2 = expr; s >] -> expr_next (ETry (e,name,e2),punion p1 (pos e2)) s and expr_next e = parser | [< '(Dot,_); '(Const (Ident name),p); s >] -> expr_next (EField (e,name),punion (pos e) p) s | [< '(ParentOpen,po); pl = parameters; s >] -> (match s with parser | [< '(ParentClose,p); s >] -> expr_next (ECall (e,pl),punion (pos e) p) s | [< >] -> error (Unclosed "(") po) | [< '(BracketOpen,po); e2 = expr; s >] -> (match s with parser | [< '(BracketClose,p); s >] -> expr_next (EArray (e,e2),punion (pos e) p) s | [< >] -> error (Unclosed "[") po) | [< '(Binop op,_); e2 = expr; s >] -> make_binop op e e2 | [< >] -> e and block1 = parser | [< '(Const (Ident name),p); s >] -> (match s with parser | [< '(Arrow,_); e = expr; l = object_fields >] -> EObject ((name,e) :: l) | [< '(Binop ":",p2); b = block >] -> EBlock ( (ELabel name, punion p p2) :: b ) | [< e = expr_next (EConst (Ident name),p); b = block >] -> EBlock (e :: b)) | [< b = block >] -> EBlock b and block = parser | [< e = expr; b = block >] -> e :: b | [< '(Semicolon,_); b = block >] -> b | [< >] -> [] and object_fields = parser | [< '(Const (Ident name),_); '(Arrow,_); e = expr; l = object_fields >] -> (name,e) :: l | [< '(Comma,_); l = object_fields >] -> l | [< >] -> [] and parameter_names = parser | [< '(Const (Ident name),_); p = parameter_names >] -> name :: p | [< '(Comma,_); p = parameter_names >] -> p | [< >] -> [] and parameters = parser | [< e = expr; p = parameters_next >] -> e :: p | [< >] -> [] and parameters_next = parser | [< '(Comma,_); p = parameters >] -> p | [< >] -> [] and variables sp = parser | [< '(Const (Ident name),p); s >] -> (match s with parser | [< '(Binop "=",_); e = expr; v , p = variables_next (pos e) >] -> (name, Some e) :: v , p | [< v , p = variables_next p >] -> (name, None) :: v , p) and variables_next sp = parser | [< '(Comma,p); v = variables p >] -> v | [< >] -> [] , sp let parse code file = let old = Lexer.save() in Lexer.init file; let last = ref (Eof,null_pos) in let rec next_token x = let t, p = Lexer.token code in match t with | Comment s | CommentLine s -> next_token x | _ -> last := (t , p); Some (t , p) in try let l = program (Stream.from next_token) in Lexer.restore old; EBlock l, { pmin = 0; pmax = (pos !last).pmax; pfile = file } with | Stream.Error _ | Stream.Failure -> Lexer.restore old; error (Unexpected (fst !last)) (pos !last) | e -> Lexer.restore old; raise e neko-2-2-0/libs/ocaml/neko/plugin.ml000066400000000000000000000071411321613172000172540ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) type exn_infos = { exn_name : string; exn_message : string; exn_pos : (string -> int -> string) -> string; } type filter = { ext_in : string; ext_out : string; transform : string -> IO.input -> unit IO.output -> unit; exceptions : exn -> exn_infos; } exception Error of exn_infos let paths = ref [""] let plugins = ref [] let verbose = ref false let register source dest trans exc = plugins := { ext_in = String.lowercase source; ext_out = String.lowercase dest; transform = trans; exceptions = exc; } :: !plugins let exn_infos name msg pos = { exn_name = name; exn_pos = pos; exn_message = msg; } let open_file ?(bin=false) f = let rec loop = function | [] -> None | path :: l -> let file = path ^ f in try let ch = (if bin then open_in_bin else open_in) file in Some (file, IO.input_channel ch) with _ -> loop l in loop (!paths) let switch_ext file ext = try Filename.chop_extension file ^ ext with _ -> file ^ ext let add_path path = let l = String.length path in if l > 0 && path.[l-1] != '\\' && path.[l-1] != '/' then paths := (path ^ "/") :: !paths else paths := path :: !paths let generate_loop file ch fext ext = if ext = fext then () else let rec loop fext acc = function | [] -> raise Not_found | x :: l when x.ext_in = fext && not (List.exists (fun p -> p.ext_in = x.ext_out) acc) -> if x.ext_out = ext then x :: acc else (try let l1 = loop x.ext_out (x :: acc) (!plugins) in (try let l2 = loop fext acc l in if List.length l2 < List.length l1 then l2 else l1 with Not_found -> l1) with Not_found -> loop fext acc l) | x :: l -> loop fext acc l in let ftarget = switch_ext file ("." ^ ext) in let genlist = (try List.rev (loop fext [] (!plugins)) with Not_found -> let fbase = Filename.basename file in failwith ("Don't know how to generate " ^ Filename.basename ftarget ^ " from " ^ fbase) ) in let execute x file ch out = try x.transform file ch out with e -> raise (Error (x.exceptions e)) in let rec loop file ch = function | [] -> assert false | [x] -> let out = IO.output_channel (open_out_bin ftarget) in execute x file ch out; (try IO.close_in ch with IO.Input_closed -> ()); (try IO.close_out out with IO.Output_closed -> ()); | x :: l -> let chin , out = IO.pipe() in execute x file ch out; (try IO.close_in ch with IO.Input_closed -> ()); (try IO.close_out out with IO.Output_closed -> ()); loop ("." ^ x.ext_out) chin l in loop file ch genlist let generate file ext = let fext = (try let p = String.rindex file '.' in String.sub file (p + 1) (String.length file - (p + 1)) with Not_found -> file ) in match open_file ~bin:true file with | None -> failwith ("File not found : " ^ file) | Some (file,ch) -> generate_loop file ch fext ext neko-2-2-0/libs/ocaml/neko/printer.ml000066400000000000000000000113351321613172000174410ustar00rootroot00000000000000(* * Neko Compiler * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast type 'a ctx = { ch : 'a IO.output; mutable level : int; mutable tabs : bool; } let create ch = { ch = ch; level = 0; tabs = true; } let newline ctx = IO.write ctx.ch '\n'; ctx.tabs <- false let level ctx b = ctx.level <- ctx.level + (if b then 1 else -1); newline ctx let print ctx = if not ctx.tabs then begin IO.nwrite ctx.ch (String.make (ctx.level * 4) ' '); ctx.tabs <- true; end; IO.printf ctx.ch let rec print_list ctx sep f = function | [] -> () | x :: [] -> f x | x :: l -> f x; print ctx "%s" sep; print_list ctx sep f l let rec print_ast ?(binop=false) ctx (e,p) = match e with | EConst c -> print ctx "%s" (s_constant c) | EBlock el -> print ctx "{"; level ctx true; List.iter (fun e -> print_ast ctx e; if ctx.tabs then begin print ctx ";"; newline ctx; end ) el; ctx.level <- ctx.level - 1; print ctx "}"; newline ctx; | EParenthesis e when not ctx.tabs -> print ctx "{ "; print_ast ctx e; print ctx " }"; | EParenthesis e -> print ctx "( "; print_ast ctx e; print ctx " )"; | EField (e,s) -> print_ast ctx e; print ctx ".%s" s; | ECall (e,el) -> print_ast ctx e; print ctx "("; print_list ctx "," (print_ast ctx) el; print ctx ")"; | EArray (e1,e2) -> print_ast ctx e1; print ctx "["; print_ast ctx e2; print ctx "]" | EVars vl -> print ctx "var "; print_list ctx ", " (fun (n,v) -> print ctx "%s" n; match v with | None -> () | Some e -> print ctx " = "; print_ast ctx e ) vl; print ctx ";"; newline ctx | EWhile (cond,e,NormalWhile) -> print ctx "while "; print_ast ctx cond; level_expr ctx e; | EWhile (cond,e,DoWhile) -> print ctx "do "; level_expr ctx e; print ctx "while "; print_ast ctx cond; newline ctx | EIf (cond,e,e2) -> print ctx "if "; print_ast ctx cond; level_expr ~closed:(e2=None) ctx e; (match e2 with | None -> () | Some e -> print ctx "else"; level_expr ctx e) | ETry (e,id,e2) -> print ctx "try"; level_expr ctx e; print ctx "catch %s" id; level_expr ctx e2; | EFunction (params,e) -> print ctx "function("; print_list ctx "," (print ctx "%s") params; print ctx ")"; level_expr ctx e; | EBinop (op,e1,e2) -> let tabs = ctx.tabs in if binop then (if tabs then print ctx "(" else print ctx "{"); print_ast ~binop:true ctx e1; print ctx " %s " op; print_ast ~binop:true ctx e2; if binop then (if tabs then print ctx ")" else print ctx "}"); | EReturn None -> print ctx "return;"; | EReturn (Some e) -> print ctx "return "; print_ast ctx e; | EBreak None -> print ctx "break;"; | EBreak (Some e) -> print ctx "break "; print_ast ctx e; | EContinue -> print ctx "continue" | ENext (e1,e2) -> print_ast ctx e1; print ctx ";"; newline ctx; print_ast ctx e2 | EObject [] -> print ctx "$new(null)" | EObject fl -> print ctx "{"; level ctx true; let rec loop = function | [] -> assert false | [f,e] -> print ctx "%s => " f; print_ast ctx e; newline ctx; | (f,e) :: l -> print ctx "%s => " f; print_ast ctx e; print ctx ", "; newline ctx; loop l in loop fl; level ctx false; print ctx "}" | ELabel s -> print ctx "%s:" s and level_expr ?(closed=false) ctx (e,p) = match e with | EBlock _ -> if ctx.tabs then print ctx " "; print_ast ctx (e,p) | ENext _ -> if ctx.tabs then print ctx " "; print_ast ctx (EBlock [(e,p)],p) | EParenthesis e -> if ctx.tabs then print ctx " "; print ctx "{"; level ctx true; print_ast ctx e; level ctx false; print ctx "}"; | _ -> level ctx true; print_ast ctx (e,p); if closed then print ctx ";"; level ctx false let print ctx ast = match fst ast with | EBlock el -> List.iter (fun e -> print_ast ctx e; if ctx.tabs then begin print ctx ";"; newline ctx; end ) el; | _ -> print_ast ctx ast let to_string ast = let ch = IO.output_string() in let ctx = create ch in print ctx ast; IO.close_out chneko-2-2-0/libs/ocaml/nxml.ml000066400000000000000000000112331321613172000157750ustar00rootroot00000000000000(* * Neko NXML for OCaml * Copyright (c)2005-2017 Haxe Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Nast type xml = | Node of string * (string * string) list * xml list | CData of string let node name att children = Node(name,att,children) let rec to_xml_rec p2 ast = let e , p = ast in let name = ref "" in let aval = ref None in let children = ref [] in (match e with | EConst c -> (match c with | True | False | Null | This | Builtin _ | Ident _ -> name := "v"; aval := Some (s_constant c) | Int i -> name := "i"; aval := Some (string_of_int i); | Float s -> name := "f"; aval := Some s; | String s -> name := "s"; aval := Some s; ) | EBlock el -> name := "b"; children := List.map (to_xml_rec p) el; | EParenthesis e -> name := "p"; children := [to_xml_rec p e]; | EField (e,f) -> name := "g"; aval := Some f; children := [to_xml_rec p e]; | ECall (e,el) -> name := "c"; children := to_xml_rec p e :: List.map (to_xml_rec p) el; | EArray (a,b) -> name := "a"; children := [to_xml_rec p a; to_xml_rec p b]; | EVars vl -> name := "var"; children := List.map (fun(v,e) -> node "v" [("v",v)] (match e with None -> [] | Some e -> [to_xml_rec p e]) ) vl; | EWhile (econd,e,NormalWhile) -> name := "while"; children := [to_xml_rec p econd; to_xml_rec p e]; | EWhile (econd,e,DoWhile) -> name := "do"; children := [to_xml_rec p e; to_xml_rec p econd]; | EIf (cond,e,eelse) -> name := "if"; children := to_xml_rec p cond :: to_xml_rec p e :: (match eelse with None -> [] | Some e -> [to_xml_rec p e]) | ETry (e1,v,e2) -> name := "try"; aval := Some v; children := [to_xml_rec p e1; to_xml_rec p e2]; | EFunction (args,e) -> name := "function"; aval := Some (String.concat ":" args); children := [to_xml_rec p e]; | EBinop (op,e1,e2) -> name := "o"; aval := Some op; children := [to_xml_rec p e1; to_xml_rec p e2]; | EReturn e -> name := "return"; children := (match e with None -> [] | Some e -> [to_xml_rec p e]); | EBreak e -> name := "break"; children := (match e with None -> [] | Some e -> [to_xml_rec p e]); | EContinue -> name := "continue"; | ENext (e1,e2) -> name := "next"; children := [to_xml_rec p e1; to_xml_rec p e2]; | EObject fl -> name := "object"; children := List.map (fun(v,e) -> node "v" [("v",v)] [to_xml_rec p e]) fl; | ELabel v -> name := "label"; aval := Some v; | ESwitch (e,cases,def) -> name := "switch"; let cases = List.map (fun(e1,e2) -> node "case" [] [to_xml_rec p e1; to_xml_rec p e2]) cases in children := to_xml_rec p e :: (match def with None -> cases | Some e -> node "default" [] [to_xml_rec p e] :: cases ); | ENeko s -> name := "neko"; children := [CData s]; ); let pos = (if p.psource <> p2.psource then [("p",p.psource ^ ":" ^ string_of_int p.pline)] else if p.pline <> p2.pline then [("p",string_of_int p.pline)] else [] ) in let aval = (match !aval with None -> [] | Some v -> [("v",v)]) in node !name (List.append pos aval) !children let to_xml ast = to_xml_rec null_pos ast let rec write_fmt_rec tabs ch x = match x with | CData s -> IO.printf ch "%s" tabs s | Node (name,att,children) -> IO.printf ch "%s<%s%s" tabs name (String.concat "" (List.map (fun(a,v) -> " " ^ a ^ "=\"" ^ escape v ^ "\"") att)); match children with | [] -> IO.nwrite ch "/>" | l -> IO.nwrite ch ">\n"; List.iter (fun(x) -> write_fmt_rec (tabs ^ " ") ch x; IO.write ch '\n') l; IO.printf ch "%s" tabs name let write_fmt ch x = write_fmt_rec "" ch (node "nxml" [] [x]) let rec write_rec ch x = match x with | CData s -> IO.printf ch "" s | Node (name,att,children) -> IO.printf ch "<%s%s" name (String.concat "" (List.map (fun(a,v) -> " " ^ a ^ "=\"" ^ escape v ^ "\"") att)); match children with | [] -> IO.nwrite ch "/>" | l -> IO.nwrite ch ">"; List.iter (fun(x) -> write_rec ch x) l; IO.printf ch "" name let write ch x = write_rec ch (node "nxml" [] [x]) neko-2-2-0/libs/regexp/000077500000000000000000000000001321613172000146645ustar00rootroot00000000000000neko-2-2-0/libs/regexp/CMakeLists.txt000066400000000000000000000050521321613172000174260ustar00rootroot00000000000000 ###################### # regexp.ndll add_library(regexp.ndll MODULE regexp.c) if (STATIC_PCRE) if (WIN32) set(PCRE_URL "https://ftp.pcre.org/pub/pcre/pcre-8.41.tar.gz") if (NOT ${CMAKE_VERSION} VERSION_LESS 3.7) list(APPEND PCRE_URL "http://downloads.sourceforge.net/project/pcre/pcre/8.41/pcre-8.41.tar.gz" ) endif() ExternalProject_Add(PCRE ${EP_CONFIGS} URL ${PCRE_URL} URL_MD5 2e7896647ee25799cb454fe287ffcd08 CMAKE_ARGS -G ${CMAKE_GENERATOR} -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libs/src/install-prefix -Wno-dev -DPCRE_BUILD_PCRECPP=OFF -DPCRE_BUILD_PCREGREP=OFF -DPCRE_BUILD_TESTS=OFF -DPCRE_SUPPORT_JIT=ON -DPCRE_SUPPORT_UNICODE_PROPERTIES=ON ) set(PCRE_LIBRARIES optimized ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/pcre.lib debug ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/pcred.lib ) else() if (APPLE) set(PCRE_CFLAGS "-w -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") else() set(PCRE_CFLAGS "-w") endif() set(PCRE_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/libpcre.a ) set(PCRE_URL "https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz") if (NOT ${CMAKE_VERSION} VERSION_LESS 3.7) list(APPEND PCRE_URL "http://downloads.sourceforge.net/project/pcre/pcre/8.40/pcre-8.40.tar.gz" ) endif() ExternalProject_Add(PCRE ${EP_CONFIGS} URL ${PCRE_URL} URL_MD5 890c808122bd90f398e6bc40ec862102 CONFIGURE_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/PCRE && ./configure --prefix=${CMAKE_BINARY_DIR}/libs/src/install-prefix --with-pic --enable-unicode-properties --enable-silent-rules --enable-jit --disable-cpp --enable-shared=no --enable-static=yes --silent BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/PCRE && make "CFLAGS=${PCRE_CFLAGS}" INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/PCRE && make install BYPRODUCTS ${PCRE_LIBRARIES} ) endif() set_target_properties(PCRE PROPERTIES ${EP_PROPS}) set(PCRE_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/libs/src/install-prefix/include) add_dependencies(regexp.ndll PCRE) # Download project for fat source archive add_dependencies(download_static_deps PCRE-download) else() find_package(PCRE REQUIRED) endif() target_include_directories(regexp.ndll PRIVATE ${PCRE_INCLUDE_DIRS}) target_link_libraries(regexp.ndll libneko ${PCRE_LIBRARIES}) set_target_properties(regexp.ndll PROPERTIES PREFIX "" OUTPUT_NAME regexp SUFFIX .ndll ) install ( TARGETS regexp.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/regexp/regexp.c000066400000000000000000000173371321613172000163350ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #define PCRE_STATIC #include #define PCRE(o) ((pcredata*)val_data(o)) typedef struct { value str; pcre *r; int nmatchs; int *matchs; } pcredata; DEFINE_KIND(k_regexp); static field id_pos; static field id_len; static pcre_extra limit; /**

Regexp

Regular expressions using PCRE engine.

**/ static void free_regexp( value p ) { pcre_free( PCRE(p)->r ); } static int do_exec( pcredata *d, const char *str, int len, int pos ) { int res = pcre_exec(d->r,&limit,str,len,pos,0,d->matchs,d->nmatchs * 3); if( res >= 0 ) return 1; if( res != PCRE_ERROR_NOMATCH ) val_throw(alloc_string("An error occurred while running pcre_exec")); return 0; } /** regexp_new_options : reg:string -> options:string -> 'regexp Build a new regexpr with the following options :
  • i : case insensitive matching
  • s : . match anything including newlines
  • m : treat the input as a multiline string
  • u : run in utf8 mode
  • g : turn off greedy behavior
**/ static value regexp_new_options( value s, value opt ) { val_check(s,string); val_check(opt,string); { value v; const char *error; int err_offset; pcre *p; pcredata *pdata; char *o = val_string(opt); int options = 0; while( *o ) { switch( *o++ ) { case 'i': options |= PCRE_CASELESS; break; case 's': options |= PCRE_DOTALL; break; case 'm': options |= PCRE_MULTILINE; break; case 'u': options |= PCRE_UTF8; break; case 'g': options |= PCRE_UNGREEDY; break; default: neko_error(); break; } } p = pcre_compile(val_string(s),options,&error,&err_offset,NULL); if( p == NULL ) { buffer b = alloc_buffer("Regexp compilation error : "); buffer_append(b,error); buffer_append(b," in "); val_buffer(b,s); bfailure(b); } v = alloc_abstract(k_regexp,alloc(sizeof(pcredata))); pdata = PCRE(v); pdata->r = p; pdata->str = val_null; pdata->nmatchs = 0; pcre_fullinfo(p,NULL,PCRE_INFO_CAPTURECOUNT,&pdata->nmatchs); pdata->nmatchs++; pdata->matchs = (int*)alloc_private(sizeof(int) * 3 * pdata->nmatchs); val_gc(v,free_regexp); return v; } } /** regexp_new : string -> 'regexp Build a new regexp **/ static value regexp_new( value s ) { return regexp_new_options(s,alloc_string("")); } /** regexp_match : 'regexp -> string -> pos:int -> len:int -> bool Match [len] chars of a string starting at [pos] using the regexp. Return true if match found **/ static value regexp_match( value o, value s, value p, value len ) { pcredata *d; int pp,ll; val_check_kind(o,k_regexp); val_check(s,string); val_check(p,int); val_check(len,int); pp = val_int(p); ll = val_int(len); if( pp < 0 || ll < 0 || pp > val_strlen(s) || pp + ll > val_strlen(s) ) neko_error(); d = PCRE(o); if( do_exec(d,val_string(s),ll+pp,pp) ) { d->str = s; return val_true; } else { d->str = val_null; return val_false; } } static value do_replace( value o, value s, value s2, bool all ) { val_check_kind(o,k_regexp); val_check(s,string); val_check(s2,string); { pcredata *d = PCRE(o); buffer b = alloc_buffer(NULL); int pos = 0; int len = val_strlen(s); const char *str = val_string(s); const char *str2 = val_string(s2); int len2 = val_strlen(s2); while( do_exec(d,str,len,pos) ) { buffer_append_sub(b,str+pos,d->matchs[0] - pos); buffer_append_sub(b,str2,len2); pos = d->matchs[1]; if( !all ) break; } d->str = val_null; buffer_append_sub(b,str+pos,len-pos); return buffer_to_string(b); } } /** regexp_replace : 'regexp -> from:string -> by:string -> string Perform a replacement using a regexp **/ static value regexp_replace( value o, value s, value s2 ) { return do_replace(o,s,s2,false); } /** regexp_replace_all : 'regexp -> from:string -> by:string -> string Perform a replacement of all matched substrings using a regexp **/ static value regexp_replace_all( value o, value s, value s2 ) { return do_replace(o,s,s2,true); } /** regexp_replace_fun : 'regexp -> from:string -> f:('regexp -> any) -> string Perform a replacement of all matched substrings by calling [f] for every match **/ static value regexp_replace_fun( value o, value s, value f ) { val_check_kind(o,k_regexp); val_check(s,string); val_check_function(f,1); { pcredata *d = PCRE(o); buffer b = alloc_buffer(NULL); int pos = 0; int len = val_strlen(s); const char *str = val_string(s); d->str = s; while( do_exec(d,str,len,pos) ) { buffer_append_sub(b,str+pos,d->matchs[0] - pos); val_buffer(b,val_call1(f,o)); pos = d->matchs[1]; } d->str = val_null; buffer_append_sub(b,str+pos,len-pos); return buffer_to_string(b); } } /** regexp_matched : 'regexp -> n:int -> string? Return the [n]th matched block by the regexp. If [n] is 0 then return the whole matched substring. If the [n]th matched block was optional and not matched, returns null **/ static value regexp_matched( value o, value n ) { pcredata *d; int m; val_check_kind(o,k_regexp); d = PCRE(o); val_check(n,int); m = val_int(n); if( m < 0 || m >= d->nmatchs || val_is_null(d->str) ) neko_error(); { int start = d->matchs[m*2]; int len = d->matchs[m*2+1] - start; value str; if( start == -1 ) return val_null; str = alloc_empty_string(len); memcpy((char*)val_string(str),val_string(d->str)+start,len); return str; } } /** regexp_matched_pos : 'regexp -> n:int -> { pos => int, len => int } Return the [n]th matched block position by the regexp. If [n] is 0 then return the whole matched substring position **/ static value regexp_matched_pos( value o, value n ) { pcredata *d; int m; val_check_kind(o,k_regexp); d = PCRE(o); val_check(n,int); m = val_int(n); if( m < 0 || m >= d->nmatchs || val_is_null(d->str) ) neko_error(); { int start = d->matchs[m*2]; int len = d->matchs[m*2+1] - start; value o = alloc_object(NULL); alloc_field(o,id_pos,alloc_int(start)); alloc_field(o,id_len,alloc_int(len)); return o; } } void regexp_main() { id_pos = val_id("pos"); id_len = val_id("len"); limit.flags = PCRE_EXTRA_MATCH_LIMIT_RECURSION; limit.match_limit_recursion = 3500; // adapted based on Windows 1MB stack size } DEFINE_PRIM(regexp_new,1); DEFINE_PRIM(regexp_new_options,2); DEFINE_PRIM(regexp_match,4); DEFINE_PRIM(regexp_replace,3); DEFINE_PRIM(regexp_replace_all,3); DEFINE_PRIM(regexp_replace_fun,3); DEFINE_PRIM(regexp_matched,2); DEFINE_PRIM(regexp_matched_pos,2); DEFINE_ENTRY_POINT(regexp_main); /* ************************************************************************ */ neko-2-2-0/libs/sqlite/000077500000000000000000000000001321613172000146735ustar00rootroot00000000000000neko-2-2-0/libs/sqlite/CMakeLists.txt000066400000000000000000000024321321613172000174340ustar00rootroot00000000000000 ###################### # sqlite.ndll if (STATIC_SQLITE3) ExternalProject_Add(Sqlite3 ${EP_CONFIGS} URL https://www.sqlite.org/2017/sqlite-autoconf-3210000.tar.gz URL_MD5 7913de4c3126ba3c24689cb7a199ea31 CONFIGURE_COMMAND echo skip config BUILD_COMMAND echo skip build INSTALL_COMMAND echo skip install ) add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/libs/src/Sqlite3/sqlite3.c DEPENDS Sqlite3 ) add_library(sqlite.ndll MODULE sqlite.c ${CMAKE_BINARY_DIR}/libs/src/Sqlite3/sqlite3.c ) target_include_directories(sqlite.ndll PRIVATE ${CMAKE_BINARY_DIR}/libs/src/Sqlite3) target_link_libraries(sqlite.ndll libneko) target_compile_definitions(sqlite.ndll PRIVATE SQLITE_MAX_VARIABLE_NUMBER=250000 SQLITE_ENABLE_RTREE=1) # Download project for fat source archive add_dependencies(download_static_deps Sqlite3-download) else() add_library(sqlite.ndll MODULE sqlite.c) pkg_check_modules(SQLITE3 REQUIRED sqlite3) target_include_directories(sqlite.ndll PRIVATE ${SQLITE3_INCLUDEDIR} ${SQLITE3_INCLUDE_DIRS}) target_link_libraries(sqlite.ndll libneko ${SQLITE3_LIBRARIES}) endif() set_target_properties(sqlite.ndll PROPERTIES PREFIX "" OUTPUT_NAME sqlite SUFFIX .ndll ) install ( TARGETS sqlite.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/sqlite/sqlite.c000066400000000000000000000213451321613172000163450ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include /**

SQLite

Sqlite is a small embeddable SQL database that store all its data into a single file. See http://sqlite.org for more details.

**/ DEFINE_KIND(k_db); DEFINE_KIND(k_result); #define val_db(v) ((database*)val_data(v)) #define val_result(v) ((result*)val_data(v)) typedef struct _database { sqlite3 *db; value last; } database; typedef struct _result { database *db; int ncols; int count; field *names; int *bools; int done; int first; sqlite3_stmt *r; } result; static void sqlite_error( sqlite3 *db ) { buffer b = alloc_buffer("Sqlite error : "); buffer_append(b,sqlite3_errmsg(db)); val_throw(buffer_to_string(b)); } static void finalize_result( result *r, int exc ) { r->first = 0; r->done = 1; if( r->ncols == 0 ) r->count = sqlite3_changes(r->db->db); if( sqlite3_finalize(r->r) != SQLITE_OK && exc ) val_throw(alloc_string("Could not finalize request")); r->r = NULL; r->db->last = NULL; r->db = NULL; } static void free_db( value v ) { database *db = val_db(v); if( db->last != NULL ) finalize_result(val_result(db->last),0); if( sqlite3_close(db->db) != SQLITE_OK ) { // No exception : we shouldn't alloc memory in a finalizer anyway } } /** connect : filename:string -> 'db Open or create the database stored in the specified file. **/ static value connect( value filename ) { int err; database *db = (database*)alloc(sizeof(database)); value v; val_check(filename,string); db->last = NULL; if( (err = sqlite3_open(val_string(filename),&db->db)) != SQLITE_OK ) { buffer b = alloc_buffer("Sqlite error : "); buffer_append(b,sqlite3_errmsg(db->db)); sqlite3_close(db->db); val_throw(buffer_to_string(b)); } v = alloc_abstract(k_db,db); val_gc(v,free_db); return v; } /** close : 'db -> void Closes the database. **/ static value close( value v ) { val_check_kind(v,k_db); free_db(v); val_gc(v,NULL); val_kind(v) = NULL; return val_null; } /** last_insert_id : 'db -> int Returns the last inserted auto_increment id. **/ static value last_insert_id( value db ) { val_check_kind(db,k_db); return alloc_int(sqlite3_last_insert_rowid(val_db(db)->db)); } /** request : 'db -> sql:string -> 'result Executes the SQL request and returns its result **/ static value request( value v, value sql ) { database *db; result *r; const char *tl; int i,j; val_check_kind(v,k_db); val_check(sql,string); db = val_db(v); r = (result*)alloc(sizeof(result)); r->db = db; if( sqlite3_prepare(db->db,val_string(sql),val_strlen(sql),&r->r,&tl) != SQLITE_OK ) { buffer b = alloc_buffer("Sqlite error in "); val_buffer(b,sql); buffer_append(b," : "); buffer_append(b,sqlite3_errmsg(db->db)); val_throw(buffer_to_string(b)); } if( *tl ) { sqlite3_finalize(r->r); val_throw(alloc_string("Cannot execute several SQL requests at the same time")); } r->ncols = sqlite3_column_count(r->r); r->names = (field*)alloc_private(sizeof(field)*r->ncols); r->bools = (int*)alloc_private(sizeof(int)*r->ncols); r->first = 1; r->done = 0; for(i=0;incols;i++) { field id = val_id(sqlite3_column_name(r->r,i)); const char *dtype = sqlite3_column_decltype(r->r,i); for(j=0;jnames[j] == id ) { if( strcmp(sqlite3_column_name(r->r,i),sqlite3_column_name(r->r,j)) == 0 ) { buffer b = alloc_buffer("Error, same field is two times in the request "); val_buffer(b,sql); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } else { buffer b = alloc_buffer("Error, same field ids for : "); buffer_append(b,sqlite3_column_name(r->r,i)); buffer_append(b," and "); buffer_append(b,sqlite3_column_name(r->r,j)); buffer_append_char(b,'.'); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } } r->names[i] = id; r->bools[i] = dtype?(strcmp(dtype,"BOOL") == 0):0; } // changes in an update/delete if( db->last != NULL ) finalize_result(val_result(db->last),0); db->last = alloc_abstract(k_result,r); return db->last; } /** result_get_length : 'result -> int Returns the number of rows in the result or the number of rows changed by the request. **/ static value result_get_length( value v ) { result *r; val_check_kind(v,k_result); r = val_result(v); if( r->ncols != 0 ) neko_error(); // ??? return alloc_int(r->count); } /** result_get_nfields : 'result -> int Returns the number of fields in the result. **/ static value result_get_nfields( value r ) { val_check_kind(r,k_result); return alloc_int(val_result(r)->ncols); } /** result_next : 'result -> object? Returns the next row in the result or [null] if no more result. **/ static value result_next( value v ) { int i; result *r; val_check_kind(v,k_result); r = val_result(v); if( r->done ) return val_null; switch( sqlite3_step(r->r) ) { case SQLITE_ROW: r->first = 0; v = alloc_object(NULL); for(i=0;incols;i++) { value f; switch( sqlite3_column_type(r->r,i) ) { case SQLITE_NULL: f = val_null; break; case SQLITE_INTEGER: if( r->bools[i] ) f = alloc_bool(sqlite3_column_int(r->r,i)); else f = alloc_best_int(sqlite3_column_int(r->r,i)); break; case SQLITE_FLOAT: f = alloc_float(sqlite3_column_double(r->r,i)); break; case SQLITE_TEXT: f = alloc_string((char*)sqlite3_column_text(r->r,i)); break; case SQLITE_BLOB: { int size = sqlite3_column_bytes(r->r,i); f = alloc_empty_string(size); memcpy(val_string(f),sqlite3_column_blob(r->r,i),size); break; } default: { buffer b = alloc_buffer("Unknown Sqlite type #"); val_buffer(b,alloc_int(sqlite3_column_type(r->r,i))); val_throw(buffer_to_string(b)); } } alloc_field(v,r->names[i],f); } return v; case SQLITE_DONE: finalize_result(r,1); return val_null; case SQLITE_BUSY: val_throw(alloc_string("Database is busy")); case SQLITE_ERROR: sqlite_error(r->db->db); default: neko_error(); } return val_null; } /** result_get : 'result -> n:int -> string Return the [n]th field of the current result row. **/ static value result_get( value v, value n ) { result *r; val_check_kind(v,k_result); r = val_result(v); if( val_int(n) < 0 || val_int(n) >= r->ncols ) neko_error(); if( r->first ) result_next(v); if( r->done ) neko_error(); return alloc_string((char*)sqlite3_column_text(r->r,val_int(n))); } /** result_get_int : 'result -> n:int -> int Return the [n]th field of the current result row as an integer. **/ static value result_get_int( value v, value n ) { result *r; val_check_kind(v,k_result); r = val_result(v); if( val_int(n) < 0 || val_int(n) >= r->ncols ) neko_error(); if( r->first ) result_next(v); if( r->done ) neko_error(); return alloc_best_int(sqlite3_column_int(r->r,val_int(n))); } /** result_get_float : 'result -> n:int -> float Return the [n]th field of the current result row as a float. **/ static value result_get_float( value v, value n ) { result *r; val_check_kind(v,k_result); r = val_result(v); if( val_int(n) < 0 || val_int(n) >= r->ncols ) neko_error(); if( r->first ) result_next(v); if( r->done ) neko_error(); return alloc_float(sqlite3_column_double(r->r,val_int(n))); } DEFINE_PRIM(connect,1); DEFINE_PRIM(close,1); DEFINE_PRIM(request,2); DEFINE_PRIM(last_insert_id,1); DEFINE_PRIM(result_get_length,1); DEFINE_PRIM(result_get_nfields,1); DEFINE_PRIM(result_next,1); DEFINE_PRIM(result_get,2); DEFINE_PRIM(result_get_int,2); DEFINE_PRIM(result_get_float,2); /* ************************************************************************ */ neko-2-2-0/libs/ssl/000077500000000000000000000000001321613172000141735ustar00rootroot00000000000000neko-2-2-0/libs/ssl/CMakeLists.txt000066400000000000000000000043731321613172000167420ustar00rootroot00000000000000 ###################### # ssl.ndll add_library(ssl.ndll MODULE ssl.c) if (STATIC_MBEDTLS) set(MBEDTLS_CMAKE_ARGS -Wno-dev -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON ) if (UNIX) list(APPEND MBEDTLS_CMAKE_ARGS -DLINK_WITH_PTHREAD=ON -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} ${ARG_PIC} ) endif() if (WIN32) set(MBEDTLS_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/MbedTLS-build/library/${CMAKE_CFG_INTDIR}/mbedx509.lib ${CMAKE_BINARY_DIR}/libs/src/MbedTLS-build/library/${CMAKE_CFG_INTDIR}/mbedtls.lib ${CMAKE_BINARY_DIR}/libs/src/MbedTLS-build/library/${CMAKE_CFG_INTDIR}/mbedcrypto.lib ) target_link_libraries(ssl.ndll ws2_32 Advapi32 Crypt32) else() set(MBEDTLS_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/MbedTLS-build/library/libmbedx509.a ${CMAKE_BINARY_DIR}/libs/src/MbedTLS-build/library/libmbedtls.a ${CMAKE_BINARY_DIR}/libs/src/MbedTLS-build/library/libmbedcrypto.a ) endif() ExternalProject_Add(MbedTLS ${EP_CONFIGS} URL https://tls.mbed.org/download/mbedtls-2.6.0-apache.tgz URL_MD5 01ede06f7d00dd8a6626494d95a63f6b CMAKE_ARGS ${MBEDTLS_CMAKE_ARGS} PATCH_COMMAND ${CMAKE_COMMAND} -Dsource=${CMAKE_SOURCE_DIR} -DMbedTLS_source=${CMAKE_BINARY_DIR}/libs/src/MbedTLS -P ${CMAKE_SOURCE_DIR}/cmake/patch_mbedtls.cmake INSTALL_COMMAND echo skip install BYPRODUCTS ${MBEDTLS_LIBRARIES} ) set_target_properties(MbedTLS PROPERTIES ${EP_PROPS}) set(MBEDTLS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/libs/src/MbedTLS/include) add_dependencies(ssl.ndll MbedTLS) # Download project for fat source archive add_dependencies(download_static_deps MbedTLS-download) else() find_package(MbedTLS REQUIRED) endif() target_include_directories(ssl.ndll PRIVATE ${MBEDTLS_INCLUDE_DIR} ) if(APPLE) find_library(SECURITY_LIBRARY Security REQUIRED) find_library(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) target_link_libraries(ssl.ndll ${COREFOUNDATION_LIBRARY} ${SECURITY_LIBRARY}) endif() target_link_libraries(ssl.ndll libneko ${MBEDTLS_LIBRARIES}) set_target_properties(ssl.ndll PROPERTIES PREFIX "" OUTPUT_NAME ssl SUFFIX .ndll ) install ( TARGETS ssl.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/ssl/ssl.c000066400000000000000000000523741321613172000151530ustar00rootroot00000000000000 #define IMPLEMENT_API #define NEKO_COMPATIBLE #include #include #include #ifdef _MSC_VER #include #include #else #include #include typedef int SOCKET; #endif #ifdef NEKO_MAC #include #endif #define SOCKET_ERROR (-1) #define NRETRYS 20 #include "mbedtls/platform.h" #include "mbedtls/error.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/md.h" #include "mbedtls/pk.h" #include "mbedtls/oid.h" #include "mbedtls/x509_crt.h" #include "mbedtls/ssl.h" #include "mbedtls/net.h" #define val_ssl(o) (mbedtls_ssl_context*)val_data(o) #define val_conf(o) (mbedtls_ssl_config*)val_data(o) #define val_cert(o) (mbedtls_x509_crt*)val_data(o) #define val_pkey(o) (mbedtls_pk_context*)val_data(o) DEFINE_KIND( k_ssl_conf ); DEFINE_KIND( k_ssl ); DEFINE_KIND( k_cert ); DEFINE_KIND( k_pkey ); static vkind k_socket; static mbedtls_entropy_context entropy; static mbedtls_ctr_drbg_context ctr_drbg; static void free_cert( value v ){ mbedtls_x509_crt *x = val_cert(v); mbedtls_x509_crt_free(x); } static void free_pkey( value v ){ mbedtls_pk_context *k = val_pkey(v); mbedtls_pk_free(k); } static value block_error() { #ifdef NEKO_WINDOWS int err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAEALREADY || err == WSAETIMEDOUT ) #else if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY ) #endif val_throw(alloc_string("Blocking")); val_throw(alloc_string("ssl network error")); return val_true; } static value ssl_error( int ret ){ char buf[256]; mbedtls_strerror(ret, buf, sizeof(buf)); val_throw(alloc_string(buf)); return val_false; } static value ssl_new( value config ) { int ret; mbedtls_ssl_context *ssl; val_check_kind(config,k_ssl_conf); ssl = (mbedtls_ssl_context *)alloc(sizeof(mbedtls_ssl_context)); mbedtls_ssl_init(ssl); if( (ret = mbedtls_ssl_setup(ssl, val_conf(config))) != 0 ){ mbedtls_ssl_free(ssl); return ssl_error(ret); } return alloc_abstract( k_ssl, ssl ); } static value ssl_close( value ssl ) { mbedtls_ssl_context *s; val_check_kind(ssl,k_ssl); s = val_ssl(ssl); mbedtls_ssl_free( s ); val_kind(ssl) = NULL; return val_true; } static value ssl_handshake( value ssl ) { int r; val_check_kind(ssl,k_ssl); POSIX_LABEL(handshake_again); r = mbedtls_ssl_handshake( val_ssl(ssl) ); if( r == SOCKET_ERROR ) { HANDLE_EINTR(handshake_again); return block_error(); }else if( r != 0 ) return ssl_error(r); return val_true; } int net_read( void *fd, unsigned char *buf, size_t len ){ return recv((SOCKET)(int_val)fd, (char *)buf, len, 0); } int net_write( void *fd, const unsigned char *buf, size_t len ){ return send((SOCKET)(int_val)fd, (char *)buf, len, 0); } static value ssl_set_socket( value ssl, value socket ) { val_check_kind(ssl,k_ssl); if( k_socket == NULL ) k_socket = kind_lookup("socket"); val_check_kind(socket,k_socket); mbedtls_ssl_set_bio( val_ssl(ssl), val_data(socket), net_write, net_read, NULL ); return val_true; } static value ssl_set_hostname( value ssl, value hostname ){ int ret; val_check_kind(ssl,k_ssl); val_check(hostname,string); if( (ret = mbedtls_ssl_set_hostname(val_ssl(ssl), val_string(hostname))) != 0 ) return ssl_error(ret); return val_true; } static value ssl_get_peer_certificate( value ssl ){ value v; const mbedtls_x509_crt *crt; val_check_kind(ssl,k_ssl); crt = mbedtls_ssl_get_peer_cert(val_ssl(ssl)); if( crt == NULL ) return val_null; v = alloc_abstract( k_cert, (void *)crt ); return v; } static value ssl_get_verify_result( value ssl ){ int r; val_check_kind(ssl,k_ssl); r = mbedtls_ssl_get_verify_result( val_ssl(ssl) ); if( r == 0 ) return val_true; else if( r != -1 ) return val_false; val_throw(alloc_string("not available")); return val_false; } static value ssl_send_char( value ssl, value v ) { unsigned char cc; int c; val_check_kind(ssl,k_ssl); val_check(v,int); c = val_int(v); if( c < 0 || c > 255 ) neko_error(); cc = (unsigned char) c; mbedtls_ssl_write( val_ssl(ssl), &cc, 1 ); return val_true; } static value ssl_send( value ssl, value data, value pos, value len ) { int p,l,dlen; val_check_kind(ssl,k_ssl); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = mbedtls_ssl_write( val_ssl(ssl), (const unsigned char *)val_string(data) + p, l ); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); } static value ssl_write( value ssl, value data ) { int len, slen; const unsigned char *s; mbedtls_ssl_context *ctx; val_check_kind(ssl,k_ssl); val_check(data,string); s = (const unsigned char *)val_string( data ); len = val_strlen( data ); ctx = val_ssl(ssl); while( len > 0 ) { POSIX_LABEL( write_again ); slen = mbedtls_ssl_write( ctx, s, len ); if( slen == SOCKET_ERROR ) { HANDLE_EINTR( write_again ); return block_error(); } s += slen; len -= slen; } return val_true; } static value ssl_recv_char(value ssl) { unsigned char c; int r; val_check_kind(ssl,k_ssl); r = mbedtls_ssl_read( val_ssl(ssl), &c, 1 ); if( r <= 0 ) neko_error(); return alloc_int( c ); } static value ssl_recv( value ssl, value data, value pos, value len ) { int p,l,dlen; void * buf; val_check_kind(ssl,k_ssl); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int( pos ); l = val_int( len ); buf = (void *) (val_string(data) + p); POSIX_LABEL(recv_again); dlen = mbedtls_ssl_read( val_ssl(ssl), buf, l ); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } if( dlen == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) return alloc_int(0); if( dlen < 0 ) neko_error(); return alloc_int( dlen ); } static value ssl_read( value ssl ) { int len, bufsize = 256; buffer b; unsigned char buf[256]; mbedtls_ssl_context *ctx; val_check_kind(ssl,k_ssl); ctx = val_ssl(ssl); b = alloc_buffer(NULL); while( true ) { POSIX_LABEL(read_again); len = mbedtls_ssl_read( ctx, buf, bufsize ); if( len == SOCKET_ERROR ) { HANDLE_EINTR(read_again); return block_error(); } if( len == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) break; if( len == 0 ) break; buffer_append_sub(b,(const char *)buf,len); } return buffer_to_string(b); } static value conf_new( value server ) { int ret; mbedtls_ssl_config *conf; val_check(server,bool); conf = (mbedtls_ssl_config *)alloc(sizeof(mbedtls_ssl_config)); mbedtls_ssl_config_init(conf); if( (ret = mbedtls_ssl_config_defaults( conf, val_bool(server) ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, 0 )) != 0 ){ mbedtls_ssl_config_free(conf); return ssl_error( ret ); } mbedtls_ssl_conf_rng( conf, mbedtls_ctr_drbg_random, &ctr_drbg ); return alloc_abstract( k_ssl_conf, conf ); } static value conf_close( value config ) { mbedtls_ssl_config *conf; val_check_kind(config,k_ssl_conf); conf = val_conf(config); mbedtls_ssl_config_free(conf); val_kind(config) = NULL; return val_true; } static value conf_set_ca( value config, value cert ) { val_check_kind(config,k_ssl_conf); if( !val_is_null(cert) ) val_check_kind(cert,k_cert); mbedtls_ssl_conf_ca_chain( val_conf(config), val_is_null(cert) ? NULL : val_cert(cert), NULL ); return val_true; } static value conf_set_verify( value config, value b ) { val_check_kind(config, k_ssl_conf); if( !val_is_null(b) ) val_check(b, bool); if( val_is_null(b) ) mbedtls_ssl_conf_authmode(val_conf(config), MBEDTLS_SSL_VERIFY_OPTIONAL); else if( val_bool(b) ) mbedtls_ssl_conf_authmode(val_conf(config), MBEDTLS_SSL_VERIFY_REQUIRED); else mbedtls_ssl_conf_authmode(val_conf(config), MBEDTLS_SSL_VERIFY_NONE); return val_true; } static value conf_set_cert( value config, value cert, value key ) { int r; val_check_kind(config,k_ssl_conf); val_check_kind(cert,k_cert); val_check_kind(key,k_pkey); if( (r = mbedtls_ssl_conf_own_cert(val_conf(config), val_cert(cert), val_pkey(key))) != 0 ) return ssl_error(r); return val_true; } static int sni_callback( void *arg, mbedtls_ssl_context *ctx, const unsigned char *name, size_t len ){ if( name && arg ){ value ret = val_call1((value)arg, alloc_string((const char*)name)) ; if( !val_is_null(ret) ){ // TODO authmode and ca return mbedtls_ssl_set_hs_own_cert( ctx, val_cert(val_field(ret, val_id("cert"))), val_pkey(val_field(ret, val_id("key"))) ); } } return -1; } static value conf_set_servername_callback( value config, value cb ){ val_check_kind(config,k_ssl_conf); val_check_function(cb,1); mbedtls_ssl_conf_sni( val_conf(config), sni_callback, (void *)cb ); return val_true; } static value cert_load_file(value file){ int r; mbedtls_x509_crt *x; value v; val_check(file,string); x = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( x ); if( (r = mbedtls_x509_crt_parse_file(x, val_string(file))) < 0 ){ return ssl_error(r); } v = alloc_abstract(k_cert, x); val_gc(v,free_cert); return v; } static value cert_load_path(value path){ int r; mbedtls_x509_crt *x; value v; val_check(path,string); x = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( x ); if( (r = mbedtls_x509_crt_parse_path(x, val_string(path))) < 0 ){ return ssl_error(r); } v = alloc_abstract(k_cert, x); val_gc(v,free_cert); return v; } static value cert_load_defaults(){ #if defined(NEKO_WINDOWS) value v; HCERTSTORE store; PCCERT_CONTEXT cert; mbedtls_x509_crt *chain = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( chain ); if( store = CertOpenSystemStore(0, (LPCSTR)"Root") ){ cert = NULL; while( cert = CertEnumCertificatesInStore(store, cert) ) mbedtls_x509_crt_parse_der( chain, (unsigned char *)cert->pbCertEncoded, cert->cbCertEncoded ); CertCloseStore(store, 0); } v = alloc_abstract(k_cert, chain); val_gc(v,free_cert); return v; #elif defined(NEKO_MAC) CFMutableDictionaryRef search; CFArrayRef result; SecKeychainRef keychain; SecCertificateRef item; CFDataRef dat; value v; mbedtls_x509_crt *chain = NULL; // Load keychain if( SecKeychainOpen("/System/Library/Keychains/SystemRootCertificates.keychain",&keychain) != errSecSuccess ) return val_null; // Search for certificates search = CFDictionaryCreateMutable( NULL, 0, NULL, NULL ); CFDictionarySetValue( search, kSecClass, kSecClassCertificate ); CFDictionarySetValue( search, kSecMatchLimit, kSecMatchLimitAll ); CFDictionarySetValue( search, kSecReturnRef, kCFBooleanTrue ); CFDictionarySetValue( search, kSecMatchSearchList, CFArrayCreate(NULL, (const void **)&keychain, 1, NULL) ); if( SecItemCopyMatching( search, (CFTypeRef *)&result ) == errSecSuccess ){ CFIndex n = CFArrayGetCount( result ); for( CFIndex i = 0; i < n; i++ ){ item = (SecCertificateRef)CFArrayGetValueAtIndex( result, i ); // Get certificate in DER format dat = SecCertificateCopyData( item ); if( dat ){ if( chain == NULL ){ chain = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( chain ); } mbedtls_x509_crt_parse_der( chain, (unsigned char *)CFDataGetBytePtr(dat), CFDataGetLength(dat) ); CFRelease( dat ); } } } CFRelease(keychain); if( chain != NULL ){ v = alloc_abstract(k_cert, chain); val_gc(v,free_cert); return v; }else{ return val_null; } #else return val_null; #endif } static value asn1_buf_to_string( mbedtls_asn1_buf *dat ){ unsigned int i, c; char *b; value buf = alloc_empty_string( dat->len ); b = val_string(buf); for( i = 0; i < dat->len; i++ ) { c = dat->p[i]; if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) b[i] = '?'; else b[i] = c; } return buf; } static value cert_get_subject( value cert, value objname ){ mbedtls_x509_crt *crt; mbedtls_x509_name *obj; int r; const char *oname, *rname; val_check_kind(cert,k_cert); val_check(objname, string); crt = val_cert(cert); obj = &crt->subject; if( obj == NULL ) neko_error(); rname = val_string(objname); while( obj != NULL ){ r = mbedtls_oid_get_attr_short_name( &obj->oid, &oname ); if( r == 0 && strcmp( oname, rname ) == 0 ) return asn1_buf_to_string( &obj->val ); obj = obj->next; } return val_null; } static value cert_get_issuer(value cert, value objname){ mbedtls_x509_crt *crt; mbedtls_x509_name *obj; int r; const char *oname, *rname; val_check_kind(cert,k_cert); val_check(objname, string); crt = val_cert(cert); obj = &crt->issuer; if( obj == NULL ) neko_error(); rname = val_string(objname); while( obj != NULL ){ r = mbedtls_oid_get_attr_short_name( &obj->oid, &oname ); if( r == 0 && strcmp( oname, rname ) == 0 ) return asn1_buf_to_string( &obj->val ); obj = obj->next; } return val_null; } static value cert_get_altnames( value cert ){ mbedtls_x509_crt *crt; mbedtls_asn1_sequence *cur; value l = NULL, first = NULL; val_check_kind(cert, k_cert); crt = val_cert(cert); if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ){ cur = &crt->subject_alt_names; while( cur != NULL ){ value l2 = alloc_array(2); val_array_ptr(l2)[0] = asn1_buf_to_string(&cur->buf); val_array_ptr(l2)[1] = val_null; if (first == NULL) first = l2; else val_array_ptr(l)[1] = l2; l = l2; cur = cur->next; } } return (first==NULL)?val_null:first; } static value x509_time_to_array( mbedtls_x509_time *t ){ value v; if( !t ) neko_error(); v = alloc_array(6); val_array_ptr(v)[0] = alloc_int(t->year); val_array_ptr(v)[1] = alloc_int(t->mon); val_array_ptr(v)[2] = alloc_int(t->day); val_array_ptr(v)[3] = alloc_int(t->hour); val_array_ptr(v)[4] = alloc_int(t->min); val_array_ptr(v)[5] = alloc_int(t->sec); return v; } static value cert_get_notbefore(value cert){ mbedtls_x509_crt *crt; val_check_kind(cert, k_cert); crt = val_cert(cert); if( !crt ) neko_error(); return x509_time_to_array( &crt->valid_from ); } static value cert_get_notafter(value cert){ mbedtls_x509_crt *crt; val_check_kind(cert, k_cert); crt = val_cert(cert); if( !crt ) neko_error(); return x509_time_to_array( &crt->valid_to ); } static value cert_get_next( value cert ){ mbedtls_x509_crt *crt; value v; val_check_kind(cert,k_cert); crt = (mbedtls_x509_crt *)val_cert(cert); crt = crt->next; if( crt == NULL ) return val_null; v = alloc_abstract(k_cert, crt); return v; } static value cert_add_pem( value cert, value data ){ mbedtls_x509_crt *crt; int r, len; unsigned char *buf; val_check(data,string); if( !val_is_null(cert) ){ val_check_kind(cert,k_cert); crt = val_cert(cert); if( !crt ) neko_error(); }else{ crt = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( crt ); cert = alloc_abstract(k_cert, crt); val_gc(cert,free_cert); } len = val_strlen(data)+1; buf = (unsigned char *)alloc(len); memcpy(buf, val_string(data), len-1); buf[len-1] = '\0'; if( (r = mbedtls_x509_crt_parse(crt, buf, len)) < 0 ) return ssl_error(r); return cert; } static value cert_add_der( value cert, value data ){ mbedtls_x509_crt *crt; int r; val_check(data,string); if( !val_is_null(cert) ){ val_check_kind(cert,k_cert); crt = val_cert(cert); if( !crt ) neko_error(); }else{ crt = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( crt ); cert = alloc_abstract(k_cert, crt); val_gc(cert,free_cert); } if( (r = mbedtls_x509_crt_parse_der(crt, (const unsigned char*)val_string(data), val_strlen(data))) < 0 ) return ssl_error(r); return cert; } static value key_from_der( value data, value pub ){ mbedtls_pk_context *pk; int r; value v; val_check(data, string); val_check(pub, bool); pk = (mbedtls_pk_context *)alloc(sizeof(mbedtls_pk_context)); mbedtls_pk_init(pk); if( val_bool(pub) ) r = mbedtls_pk_parse_public_key( pk, (const unsigned char*)val_string(data), val_strlen(data) ); else r = mbedtls_pk_parse_key( pk, (const unsigned char*)val_string(data), val_strlen(data), NULL, 0 ); if( r != 0 ){ mbedtls_pk_free(pk); return ssl_error(r); } v = alloc_abstract(k_pkey, pk); val_gc(v,free_pkey); return v; } static value key_from_pem(value data, value pub, value pass){ mbedtls_pk_context *pk; int r, len; value v; unsigned char *buf; val_check(data, string); val_check(pub, bool); if (!val_is_null(pass)) val_check(pass, string); len = val_strlen(data)+1; buf = (unsigned char *)alloc(len); memcpy(buf, val_string(data), len-1); buf[len-1] = '\0'; pk = (mbedtls_pk_context *)alloc(sizeof(mbedtls_pk_context)); mbedtls_pk_init(pk); if( val_bool(pub) ) r = mbedtls_pk_parse_public_key( pk, buf, len ); else if( val_is_null(pass) ) r = mbedtls_pk_parse_key( pk, buf, len, NULL, 0 ); else r = mbedtls_pk_parse_key( pk, buf, len, (const unsigned char*)val_string(pass), val_strlen(pass) ); if( r != 0 ){ mbedtls_pk_free(pk); return ssl_error(r); } v = alloc_abstract(k_pkey,pk); val_gc(v,free_pkey); return v; } static value dgst_make(value data, value alg){ const mbedtls_md_info_t *md; int r = -1; value out; val_check(data, string); val_check(alg, string); md = mbedtls_md_info_from_string(val_string(alg)); if( md == NULL ){ val_throw(alloc_string("Invalid hash algorithm")); return val_null; } out = alloc_empty_string( mbedtls_md_get_size(md) ); if( (r = mbedtls_md( md, (const unsigned char *)val_string(data), val_strlen(data), (unsigned char *)val_string(out) )) != 0 ) return ssl_error(r); return out; } static value dgst_sign(value data, value key, value alg){ const mbedtls_md_info_t *md; int r = -1; size_t olen = 0; value out; unsigned char *buf; unsigned char hash[32]; val_check(data, string); val_check_kind(key, k_pkey); val_check(alg, string); md = mbedtls_md_info_from_string(val_string(alg)); if( md == NULL ){ val_throw(alloc_string("Invalid hash algorithm")); return val_null; } if( (r = mbedtls_md( md, (const unsigned char *)val_string(data), val_strlen(data), hash )) != 0 ) return ssl_error(r); out = alloc_empty_string(MBEDTLS_MPI_MAX_SIZE); buf = (unsigned char *)val_string(out); if( (r = mbedtls_pk_sign( val_pkey(key), mbedtls_md_get_type(md), hash, 0, buf, &olen, mbedtls_ctr_drbg_random, &ctr_drbg )) != 0 ) return ssl_error(r); buf[olen] = 0; val_set_size(out, olen); return out; } static value dgst_verify( value data, value sign, value key, value alg ){ const mbedtls_md_info_t *md; int r = -1; unsigned char hash[32]; val_check(data, string); val_check(sign, string); val_check_kind(key, k_pkey); val_check(alg, string); md = mbedtls_md_info_from_string(val_string(alg)); if( md == NULL ){ val_throw(alloc_string("Invalid hash algorithm")); return val_null; } if( (r = mbedtls_md( md, (const unsigned char *)val_string(data), val_strlen(data), hash )) != 0 ) return ssl_error(r); if( (r = mbedtls_pk_verify( val_pkey(key), mbedtls_md_get_type(md), hash, 0, (unsigned char *)val_string(sign), val_strlen(sign) )) != 0 ) return val_false; return val_true; } #if _MSC_VER static void threading_mutex_init_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL ) return; InitializeCriticalSection( &mutex->cs ); mutex->is_valid = 1; } static void threading_mutex_free_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL || !mutex->is_valid ) return; DeleteCriticalSection( &mutex->cs ); mutex->is_valid = 0; } static int threading_mutex_lock_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL || !mutex->is_valid ) return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); EnterCriticalSection( &mutex->cs ); return( 0 ); } static int threading_mutex_unlock_alt( mbedtls_threading_mutex_t *mutex ){ if( mutex == NULL || !mutex->is_valid ) return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); LeaveCriticalSection( &mutex->cs ); return( 0 ); } #endif void ssl_main() { #if _MSC_VER mbedtls_threading_set_alt( threading_mutex_init_alt, threading_mutex_free_alt, threading_mutex_lock_alt, threading_mutex_unlock_alt ); #endif // Init RNG mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0 ); } DEFINE_PRIM( ssl_new, 1 ); DEFINE_PRIM( ssl_close, 1 ); DEFINE_PRIM( ssl_handshake, 1 ); DEFINE_PRIM( ssl_set_socket, 2 ); DEFINE_PRIM( ssl_set_hostname, 2 ); DEFINE_PRIM( ssl_get_peer_certificate, 1 ); DEFINE_PRIM( ssl_get_verify_result, 1 ); DEFINE_PRIM( ssl_send_char, 2 ); DEFINE_PRIM( ssl_send, 4 ); DEFINE_PRIM( ssl_write, 2 ); DEFINE_PRIM( ssl_recv_char, 1 ); DEFINE_PRIM( ssl_recv, 4 ); DEFINE_PRIM( ssl_read, 1 ); DEFINE_PRIM( conf_new, 1 ); DEFINE_PRIM( conf_close, 1 ); DEFINE_PRIM( conf_set_ca, 2 ); DEFINE_PRIM( conf_set_verify, 2 ); DEFINE_PRIM( conf_set_cert, 3 ); DEFINE_PRIM( conf_set_servername_callback, 2 ); DEFINE_PRIM( cert_load_defaults, 0 ); DEFINE_PRIM( cert_load_file, 1 ); DEFINE_PRIM( cert_load_path, 1 ); DEFINE_PRIM( cert_get_subject, 2 ); DEFINE_PRIM( cert_get_issuer, 2 ); DEFINE_PRIM( cert_get_altnames, 1 ); DEFINE_PRIM( cert_get_notbefore, 1 ); DEFINE_PRIM( cert_get_notafter, 1 ); DEFINE_PRIM( cert_get_next, 1 ); DEFINE_PRIM( cert_add_pem, 2 ); DEFINE_PRIM( cert_add_der, 2 ); DEFINE_PRIM( key_from_pem, 3 ); DEFINE_PRIM( key_from_der, 2 ); DEFINE_PRIM( dgst_make, 2 ); DEFINE_PRIM( dgst_sign, 3 ); DEFINE_PRIM( dgst_verify, 4 ); DEFINE_ENTRY_POINT(ssl_main); neko-2-2-0/libs/ssl/threading_alt.h000066400000000000000000000001551321613172000171520ustar00rootroot00000000000000#include typedef struct { CRITICAL_SECTION cs; char is_valid; } mbedtls_threading_mutex_t; neko-2-2-0/libs/std/000077500000000000000000000000001321613172000141645ustar00rootroot00000000000000neko-2-2-0/libs/std/CMakeLists.txt000066400000000000000000000010121321613172000167160ustar00rootroot00000000000000 add_library(std.ndll MODULE buffer.c date.c file.c init.c int32.c math.c string.c random.c serialize.c socket.c sys.c xml.c module.c md5.c unicode.c utf8.c memory.c misc.c thread.c process.c elf_update.c ) target_link_libraries(std.ndll sha1 libneko ) if(WIN32) target_link_libraries(std.ndll ws2_32) endif() set_target_properties(std.ndll PROPERTIES PREFIX "" OUTPUT_NAME std SUFFIX .ndll ) install ( TARGETS std.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/std/UCase.hx000066400000000000000000000034471321613172000155350ustar00rootroot00000000000000// haxe program to generate unicase.c from UnicodeData.txt class UCase { static function main(){ var h = sys.io.File.getContent("UnicodeData.txt"); var low = 0, up = 0, max = 0; var a = [], b = []; var bits = 6; for( l in h.split("\n") ) { var l = l.split(";"); var code = Std.parseInt("0x"+l[0]); if( code == 0 ) continue; if( l[13] != "" ) { var k = a[code >> bits]; if( k == null ) a[code>>bits] = k = [for( i in 0...1<> bits]; if( k == null ) b[code>>bits] = k = [for( i in 0...1< max ) max = code; } var sz = a.length; for( i in 0...a.length ) if( a[i] != null ) sz += a[i].length; var bsz = b.length; for( i in 0...b.length ) if( b[i] != null ) bsz += b[i].length; Sys.print("#define UL_BITS "+bits+"\n"); Sys.print("#define UL_SIZE "+(1< /**

Buffer

A buffer can store any value as a string and will only allocate the total needed space when requested. It makes a copy of each value when stored so modifying them after is not a problem.

**/ DEFINE_KIND(k_buffer); /** buffer_new : void -> 'buffer Allocate a new empty buffer **/ static value buffer_new() { buffer b = alloc_buffer(NULL); return alloc_abstract(k_buffer,b); } /** buffer_add : 'buffer -> any -> void Add a value to a buffer **/ static value buffer_add( value b, value v ) { val_check_kind(b,k_buffer); val_buffer( (buffer)val_data(b), v ); return val_true; } /** buffer_add_char : 'buffer -> c:int -> void Add a single char to a buffer. Error if [c] is not in the 0..255 range **/ static value buffer_add_char( value b, value c ) { val_check_kind(b,k_buffer); val_check(c,int); if( val_int(c) < 0 || val_int(c) > 255 ) neko_error(); buffer_append_char( (buffer)val_data(b), (char)(unsigned char)val_int(c) ); return val_true; } /** buffer_add_sub : 'buffer -> s:string -> p:int -> l:int -> void Add [l] characters of the string [s] starting at position [p]. An error occurs if out of string bounds. **/ static value buffer_add_sub( value b, value v, value p, value l ) { val_check_kind(b,k_buffer); val_check(v,string); val_check(p,int); val_check(l,int); if( val_int(p) < 0 || val_int(l) < 0 ) neko_error(); if( val_strlen(v) < val_int(p) || val_strlen(v) < val_int(p) + val_int(l) ) neko_error(); buffer_append_sub( (buffer)val_data(b), val_string(v) + val_int(p) , val_int(l) ); return val_true; } /** buffer_string : 'buffer -> string Build and return the string built with the buffer **/ static value buffer_string( value b ) { val_check_kind(b,k_buffer); return buffer_to_string( (buffer)val_data(b) ); } /** buffer_reset : 'buffer -> void Make the buffer empty **/ static value buffer_reset( value b ) { val_check_kind(b,k_buffer); val_data(b) = alloc_buffer(NULL); return val_true; } /** buffer_get_length : 'buffer -> int Return the number of bytes currently stored into the buffer **/ static value buffer_get_length( value b ) { val_check_kind(b,k_buffer); return alloc_best_int(buffer_length((buffer)val_data(b))); } DEFINE_PRIM(buffer_new,0); DEFINE_PRIM(buffer_add,2); DEFINE_PRIM(buffer_add_char,2); DEFINE_PRIM(buffer_add_sub,4); DEFINE_PRIM(buffer_string,1); DEFINE_PRIM(buffer_reset,1); DEFINE_PRIM(buffer_get_length,1); /* ************************************************************************ */ neko-2-2-0/libs/std/date.c000066400000000000000000000150751321613172000152550ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include /**

Date

Date are using standard C functions in order to manipulate a 32 bit integer. Dates are then represented as the number of seconds elapsed since 1st January 1970.

**/ extern field id_h; extern field id_m; extern field id_s; extern field id_y; extern field id_d; #ifdef NEKO_WINDOWS static struct tm *localtime_r( time_t *t, struct tm *r ) { struct tm *r2 = localtime(t); if( r2 == NULL ) return NULL; *r = *r2; return r; } static struct tm *gmtime_r( time_t *t, struct tm *r ) { struct tm *r2 = gmtime(t); if( r2 == NULL ) return NULL; *r = *r2; return r; } #endif /** date_now : void -> 'int32 Return current date and time **/ static value date_now() { int t = (int)time(NULL); return alloc_int32(t); } /** date_new : string? -> 'int32 Parse a date format. The following formats are accepted :
  • [null] : return current date and time
  • [YYYY-MM-DD HH:MM:SS] : full date and time
  • [YYYY-MM-DD] : date only (time will be set to midnight)
  • [HH:MM:SS] : this represent an elapsed time. It will be corrected with timezone so you can subtract it from a date.
**/ static value date_new( value s ) { int o = 0; if( val_is_null(s) ) o = (int)time(NULL); else { struct tm t; bool recal = true; val_check(s,string); memset(&t,0,sizeof(struct tm)); switch( val_strlen(s) ) { case 19: sscanf(val_string(s),"%4d-%2d-%2d %2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_isdst = -1; break; case 8: sscanf(val_string(s),"%2d:%2d:%2d",&t.tm_hour,&t.tm_min,&t.tm_sec); o = t.tm_sec + t.tm_min * 60 + t.tm_hour * 60 * 60; recal = false; break; case 10: sscanf(val_string(s),"%4d-%2d-%2d",&t.tm_year,&t.tm_mon,&t.tm_mday); t.tm_isdst = -1; break; default: { buffer b = alloc_buffer("Invalid date format : "); val_buffer(b,s); bfailure(b); } } if( recal ) { t.tm_year -= 1900; t.tm_mon--; o = (int)mktime(&t); } } return alloc_int32(o); } /** date_format : #int32 -> fmt:string? -> string Format a date using [strftime]. If [fmt] is [null] then default format is used **/ static value date_format( value o, value fmt ) { char buf[128]; struct tm t; time_t d; val_check(o,any_int); if( val_is_null(fmt) ) fmt = alloc_string("%Y-%m-%d %H:%M:%S"); val_check(fmt,string); d = val_any_int(o); if( localtime_r(&d,&t) == NULL ) neko_error(); if( strftime(buf,127,val_string(fmt),&t) == 0 ) neko_error(); return alloc_string(buf); } /** date_set_hour : #int32 -> h:int -> m:int -> s:int -> 'int32 Change the time of a date. Return the modified date **/ static value date_set_hour( value o, value h, value m, value s ) { struct tm t; time_t d; val_check(o,any_int); val_check(h,int); val_check(m,int); val_check(s,int); d = val_any_int(o); if( localtime_r(&d,&t) == NULL ) neko_error(); t.tm_hour = val_int(h); t.tm_min = val_int(m); t.tm_sec = val_int(s); d = mktime(&t); if( d == -1 ) neko_error(); return alloc_int32((int)d); } /** date_set_day : #int32 -> y:int -> m:int -> d:int -> 'int32 Change the day of a date. Return the modified date **/ static value date_set_day( value o, value y, value m, value d ) { struct tm t; time_t date; val_check(o,any_int); val_check(y,int); val_check(m,int); val_check(d,int); date = val_any_int(o); if( localtime_r(&date,&t) == NULL ) neko_error(); t.tm_year = val_int(y) - 1900; t.tm_mon = val_int(m) - 1; t.tm_mday = val_int(d); date = mktime(&t); if( date == -1 ) neko_error(); return alloc_int32((int)date); } /** date_get_day : #int32 -> { y => int, m => int, d => int } Return the year month and day of a date **/ static value date_get_day( value o ) { value r; struct tm t; time_t d; val_check(o,any_int); d = val_any_int(o); if( localtime_r(&d,&t) == NULL ) neko_error(); r = alloc_object(NULL); alloc_field(r,id_y,alloc_int(t.tm_year + 1900)); alloc_field(r,id_m,alloc_int(t.tm_mon + 1)); alloc_field(r,id_d,alloc_int(t.tm_mday)); return r; } /** date_get_hour : #int32 -> { h => int, m => int, s => int } Return the hour minutes and seconds of a date **/ static value date_get_hour( value o ) { value r; struct tm t; time_t d; val_check(o,any_int); d = val_any_int(o); if( localtime_r(&d,&t) == NULL ) neko_error(); r = alloc_object(NULL); alloc_field(r,id_h,alloc_int(t.tm_hour)); alloc_field(r,id_m,alloc_int(t.tm_min)); alloc_field(r,id_s,alloc_int(t.tm_sec)); return r; } /** date_get_tz : void -> int Return the local Timezone (in seconds) **/ static value date_get_tz() { struct tm local; struct tm gmt; int diff; time_t raw = time(NULL); if( localtime_r(&raw, &local) == NULL || gmtime_r(&raw, &gmt) == NULL ) neko_error(); diff = (local.tm_hour - gmt.tm_hour) * 3600 + (local.tm_min - gmt.tm_min) * 60; // adjust for different days/years if( gmt.tm_year > local.tm_year || gmt.tm_yday > local.tm_yday ) diff -= 24 * 3600; else if( gmt.tm_year < local.tm_year || gmt.tm_yday < local.tm_yday ) diff += 24 * 3600; return alloc_int(diff); } DEFINE_PRIM(date_now,0); DEFINE_PRIM(date_new,1); DEFINE_PRIM(date_format,2); DEFINE_PRIM(date_set_hour,4); DEFINE_PRIM(date_set_day,4); DEFINE_PRIM(date_get_hour,1); DEFINE_PRIM(date_get_day,1); DEFINE_PRIM(date_get_tz,0); /* ************************************************************************ */ neko-2-2-0/libs/std/elf_update.c000066400000000000000000000054731321613172000164510ustar00rootroot00000000000000/* * Copyright (C)2015-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "neko_elf.h" static value elf_update_section_header_for_bytecode(value _file, value _interp_size, value _bytecode_size) { /* This function is a no-op on non-ELF platforms... */ #ifdef SEPARATE_SECTION_FOR_BYTECODE FILE *exe; int interp_size, bytecode_size; char buf[size_Shdr], *file; int bytecode_sec_idx; val_check(_file,string); val_check(_interp_size,int); val_check(_bytecode_size,int); file = val_string(_file); interp_size = val_int(_interp_size); bytecode_size = val_int(_bytecode_size); if ( interp_size%4 != 0 ) { return val_false; } /* Open the file to update the elf nekobytecode section header... */ exe = fopen(file,"r+b"); if( exe == NULL ) return val_false; /* First read the elf header... */ if ( val_true != elf_read_header(exe) ) goto failed; /* Find the right section header... */ bytecode_sec_idx = elf_find_bytecode_section(exe); if ( -1 == bytecode_sec_idx ) goto failed; /* Now that we have the right section header, update it... */ if ( val_true != elf_read_section(exe,bytecode_sec_idx,buf) ) goto failed; elf_set_Shdr(buf,sh_type,SHT_PROGBITS); elf_set_Shdr(buf,sh_flags,elf_get_Shdr(buf,sh_flags) & (SHF_MASKOS|SHF_MASKPROC)); elf_set_Shdr(buf,sh_addr,0); elf_set_Shdr(buf,sh_offset,interp_size); elf_set_Shdr(buf,sh_size,bytecode_size); elf_set_Shdr(buf,sh_addralign,1); elf_set_Shdr(buf,sh_entsize,0); /* ...and write it back... */ if ( val_true != elf_write_section(exe,bytecode_sec_idx,buf) ) goto failed; elf_free_section_string_table(); fclose(exe); return val_true; failed: elf_free_section_string_table(); fclose(exe); return val_false; #else return val_true; #endif } DEFINE_PRIM(elf_update_section_header_for_bytecode,3); neko-2-2-0/libs/std/file.c000066400000000000000000000171761321613172000152630ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #ifdef NEKO_WINDOWS # include #endif /**

File

The file api can be used for different kind of file I/O.

**/ typedef struct { value name; FILE *io; } fio; #define val_file(o) ((fio*)val_data(o)) DEFINE_KIND(k_file); static void file_error( const char *msg, fio *f ) { value a = alloc_array(2); val_array_ptr(a)[0] = alloc_string(msg); val_array_ptr(a)[1] = alloc_string(val_string(f->name)); val_throw(a); } /** file_open : f:string -> r:string -> 'file Call the C function [fopen] with the file path and access rights. Return the opened file or throw an exception if the file couldn't be open. **/ static value file_open( value name, value r ) { fio *f; val_check(name,string); val_check(r,string); f = (fio*)alloc(sizeof(fio)); f->name = alloc_string(val_string(name)); f->io = fopen(val_string(name),val_string(r)); if( f->io == NULL ) file_error("file_open",f); return alloc_abstract(k_file,f); } /** file_close : 'file -> void Close an file. Any other operations on this file will fail **/ static value file_close( value o ) { fio *f; val_check_kind(o,k_file); f = val_file(o); fclose(f->io); val_kind(o) = NULL; return val_null; } /** file_name : 'file -> string Return the name of the file which was opened **/ static value file_name( value o ) { val_check_kind(o,k_file); return alloc_string(val_string(val_file(o)->name)); } /** file_write : 'file -> s:string -> p:int -> l:int -> int Write up to [l] chars of string [s] starting at position [p]. Returns the number of chars written which is >= 0. **/ static value file_write( value o, value s, value pp, value n ) { int p, len; fio *f; val_check_kind(o,k_file); val_check(s,string); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > val_strlen(s) || p + len > val_strlen(s) ) neko_error(); while( len > 0 ) { int d; POSIX_LABEL(file_write_again); d = (int)fwrite(val_string(s)+p,1,len,f->io); if( d <= 0 ) { HANDLE_FINTR(f->io,file_write_again); file_error("file_write",f); } p += d; len -= d; } return n; } /** file_read : 'file -> s:string -> p:int -> l:int -> int Read up to [l] chars into the string [s] starting at position [p]. Returns the number of chars readed which is > 0 (or 0 if l == 0). **/ static value file_read( value o, value s, value pp, value n ) { fio *f; int p; int len; val_check_kind(o,k_file); val_check(s,string); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > val_strlen(s) || p + len > val_strlen(s) ) neko_error(); while( len > 0 ) { int d; POSIX_LABEL(file_read_again); d = (int)fread((char*)val_string(s)+p,1,len,f->io); if( d <= 0 ) { int size = val_int(n) - len; HANDLE_FINTR(f->io,file_read_again); if( size == 0 ) file_error("file_read",f); return alloc_int(size); } p += d; len -= d; } return n; } /** file_write_char : 'file -> c:int -> void Write the char [c]. Error if [c] outside of the range 0..255 **/ static value file_write_char( value o, value c ) { unsigned char cc; fio *f; val_check(c,int); val_check_kind(o,k_file); if( val_int(c) < 0 || val_int(c) > 255 ) neko_error(); cc = (char)val_int(c); f = val_file(o); POSIX_LABEL(write_char_again); if( fwrite(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,write_char_again); file_error("file_write_char",f); } return val_null; } /** file_read_char : 'file -> int Read a char from the file. Exception on error **/ static value file_read_char( value o ) { unsigned char cc; fio *f; val_check_kind(o,k_file); f = val_file(o); POSIX_LABEL(read_char_again); if( fread(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,read_char_again); file_error("file_read_char",f); } return alloc_int(cc); } /** file_seek : 'file -> pos:int -> mode:int -> void Use [fseek] to move the file pointer. **/ static value file_seek( value o, value pos, value kind ) { fio *f; val_check_kind(o,k_file); val_check(pos,int); val_check(kind,int); f = val_file(o); if( fseek(f->io,val_int(pos),val_int(kind)) != 0 ) file_error("file_seek",f); return val_null; } /** file_tell : 'file -> int Return the current position in the file **/ static value file_tell( value o ) { int p; fio *f; val_check_kind(o,k_file); f = val_file(o); p = ftell(f->io); if( p == -1 ) file_error("file_tell",f); return alloc_int(p); } /** file_eof : 'file -> bool Tell if we have reached the end of the file **/ static value file_eof( value o ) { val_check_kind(o,k_file); return alloc_bool( feof(val_file(o)->io) ); } /** file_flush : 'file -> void Flush the file buffer **/ static value file_flush( value o ) { fio *f; val_check_kind(o,k_file); f = val_file(o); if( fflush( f->io ) != 0 ) file_error("file_flush",f); return val_true; } /** file_contents : f:string -> string Read the content of the file [f] and return it. **/ static value file_contents( value name ) { value s; fio f; int len; int p; val_check(name,string); f.name = name; f.io = fopen(val_string(name),"rb"); if( f.io == NULL ) file_error("file_contents",&f); fseek(f.io,0,SEEK_END); len = ftell(f.io); fseek(f.io,0,SEEK_SET); s = alloc_empty_string(len); p = 0; while( len > 0 ) { int d; POSIX_LABEL(file_contents); d = (int)fread((char*)val_string(s)+p,1,len,f.io); if( d <= 0 ) { HANDLE_FINTR(f.io,file_contents); fclose(f.io); file_error("file_contents",&f); } p += d; len -= d; } fclose(f.io); return s; } #define MAKE_STDIO(k) \ static value file_##k() { \ fio *f; \ f = (fio*)alloc(sizeof(fio)); \ f->name = alloc_string(#k); \ f->io = k; \ return alloc_abstract(k_file,f); \ } \ DEFINE_PRIM(file_##k,0); /** file_stdin : void -> 'file The standard input **/ MAKE_STDIO(stdin); /** file_stdout : void -> 'file The standard output **/ MAKE_STDIO(stdout); /** file_stderr : void -> 'file The standard error output **/ MAKE_STDIO(stderr); DEFINE_PRIM(file_open,2); DEFINE_PRIM(file_close,1); DEFINE_PRIM(file_name,1); DEFINE_PRIM(file_write,4); DEFINE_PRIM(file_read,4); DEFINE_PRIM(file_write_char,2); DEFINE_PRIM(file_read_char,1); DEFINE_PRIM(file_seek,3); DEFINE_PRIM(file_tell,1); DEFINE_PRIM(file_eof,1); DEFINE_PRIM(file_flush,1); DEFINE_PRIM(file_contents,1); /* ************************************************************************ */ neko-2-2-0/libs/std/init.c000066400000000000000000000042571321613172000153030ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include field id_h; field id_m; field id_s; field id_y; field id_d; field id_module; field id_loadmodule; field id_loadprim; field id_done; field id_comment; field id_xml; field id_pcdata; field id_cdata; field id_doctype; field id_serialize; field id_unserialize; DEFINE_ENTRY_POINT(std_main); extern vkind k_file; extern vkind k_socket; extern vkind k_buffer; extern vkind k_thread; void std_main() { id_h = val_id("h"); id_m = val_id("m"); id_s = val_id("s"); id_y = val_id("y"); id_d = val_id("d"); id_loadmodule = val_id("loadmodule"); id_loadprim = val_id("loadprim"); id_module = val_id("__module"); id_done = val_id("done"); id_comment = val_id("comment"); id_xml = val_id("xml"); id_pcdata = val_id("pcdata"); id_cdata = val_id("cdata"); id_doctype = val_id("doctype"); id_serialize = val_id("__serialize"); id_unserialize = val_id("__unserialize"); kind_share(&k_file,"file"); kind_share(&k_socket,"socket"); kind_share(&k_buffer,"buffer"); kind_share(&k_thread,"thread"); } /* ************************************************************************ */ neko-2-2-0/libs/std/int32.c000066400000000000000000000123051321613172000152700ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include /**

Int32

Int32 api is deprecated as of Neko 2.0, which have native support for Int32.

**/ /** int32_new : (#int32 | float) -> 'int32 Allocate an int32 from any number **/ static value int32_new( value v ) { val_check(v,number); return alloc_int32((int)val_number(v)); } /** int32_to_int : #int32 -> int Return the int value if it can be represented using 31 bits. Error either **/ static value int32_to_int( value v ) { int i; val_check(v,any_int); i = val_any_int(v); if( need_32_bits(i) ) neko_error(); return alloc_int(i); } /** int32_to_float : #int32 -> float Return the float value of the integer. **/ static value int32_to_float( value v ) { val_check(v,any_int); return alloc_float(val_any_int(v)); } /** int32_compare : #int32 -> #int32 -> int Compare two integers **/ static value int32_compare( value v1, value v2 ) { int i1, i2; val_check(v1,any_int); val_check(v2,any_int); i1 = val_any_int(v1); i2 = val_any_int(v2); if( i1 == i2 ) return alloc_int(0); else if( i1 > i2 ) return alloc_int(1); else return alloc_int(-1); } #define INT32_OP(op_name,op) \ static value int32_##op_name( value v1, value v2 ) { \ int r; \ val_check(v1,any_int); \ val_check(v2,any_int); \ r = val_any_int(v1) op val_any_int(v2); \ return alloc_best_int(r); \ } \ DEFINE_PRIM(int32_##op_name,2) #define INT32_UNOP(op_name,op) \ static value int32_##op_name( value v ) { \ int r; \ val_check(v,any_int); \ r = op val_any_int(v); \ return alloc_best_int(r); \ } \ DEFINE_PRIM(int32_##op_name,1) #define INT32_OP_ZERO(op_name,op) \ static value int32_##op_name( value v1, value v2 ) { \ int d; \ int r; \ val_check(v1,any_int); \ val_check(v2,any_int); \ d = val_any_int(v2); \ if( d == 0 ) \ neko_error(); \ r = val_any_int(v1) op d; \ return alloc_best_int(r); \ } \ DEFINE_PRIM(int32_##op_name,2) /** int32_ushr : #int32 -> #int32 -> #int32 Perform unsigned right bits-shifting **/ static value int32_ushr( value v1, value v2 ) { int r; val_check(v1,any_int); val_check(v2,any_int); r = ((unsigned int)val_any_int(v1)) >> val_any_int(v2); return alloc_best_int(r); } /** int32_add : #int32 -> #int32 -> #int32 Add two integers **/ INT32_OP(add,+); /** int32_sub : #int32 -> #int32 -> #int32 Subtract two integers **/ INT32_OP(sub,-); /** int32_mul : #int32 -> #int32 -> #int32 Multiply two integers **/ INT32_OP(mul,*); /** int32_div : #int32 -> #int32 -> #int32 Divide two integers. Error on division by 0 **/ INT32_OP_ZERO(div,/); /** int32_shl : #int32 -> #int32 -> #int32 Perform left bit-shifting **/ INT32_OP(shl,<<); /** int32_shr : #int32 -> #int32 -> #int32 Perform right bit-shifting **/ INT32_OP(shr,>>); /** int32_mod : #int32 -> #int32 -> #int32 Return the modulo of one integer by the other. Error on modulo by 0 **/ INT32_OP_ZERO(mod,%); /** int32_neg : #int32 -> #int32 Return the negative value of an integer **/ INT32_UNOP(neg,-); /** int32_complement : #int32 -> #int32 Return the one-complement bitwised integer **/ INT32_UNOP(complement,~); /** int32_or : #int32 -> #int32 -> #int32 Return the bitwise or of two integers **/ INT32_OP(or,|); /** int32_and : #int32 -> #int32 -> #int32 Return the bitwise and of two integers **/ INT32_OP(and,&); /** int32_xor : #int32 -> #int32 -> #int32 Return the bitwise xor of two integers **/ INT32_OP(xor,^); /** int32_address : any -> #int32 Return the address of the value. The address should not be considered constant. It is not unique either unless you are sure you are running on a 32-bit platform. **/ static value int32_address( value v ) { return alloc_best_int((int)(int_val)v); } DEFINE_PRIM(int32_new,1); DEFINE_PRIM(int32_to_int,1); DEFINE_PRIM(int32_to_float,1); DEFINE_PRIM(int32_compare,2); DEFINE_PRIM(int32_ushr,2); DEFINE_PRIM(int32_address,1); /* ************************************************************************ */ neko-2-2-0/libs/std/math.c000066400000000000000000000131351321613172000152640ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include /**

Math

Mathematical functions

**/ #define MATH_PRIM(f) \ value math_##f( value n ) { \ val_check(n,number); \ return alloc_float( f( val_number(n) ) ); \ } \ DEFINE_PRIM(math_##f,1) /** math_atan2 : number -> number -> float Return atan2 calculus **/ static value math_atan2( value a, value b ) { val_check(a,number); val_check(b,number); return alloc_float( atan2(val_number(a),val_number(b)) ); } /** math_pow : number -> number -> float Return power calculus **/ static value math_pow( value a, value b ) { tfloat r; val_check(a,number); val_check(b,number); r = (tfloat)pow(val_number(a),val_number(b)); if( (int)r == r && fabs(r) < (1 << 31) ) return alloc_best_int((int)r); return alloc_float(r); } /** math_abs : number -> number Return absolute value of a number **/ static value math_abs( value n ) { switch( val_type(n) ) { case VAL_INT: return alloc_int( abs(val_int(n)) ); case VAL_INT32: return alloc_int32( abs(val_int32(n)) ); case VAL_FLOAT: return alloc_float( fabs(val_float(n)) ); default: neko_error(); } } /** math_ceil : number -> int Return rounded-up integer **/ static value math_ceil( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: return alloc_best_int( (int)ceil(val_float(n)) ); default: neko_error(); } } /** math_floor : number -> int Return rounded-down integer **/ static value math_floor( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: return alloc_best_int( (int)floor(val_float(n)) ); default: neko_error(); } } /** math_round : number -> int Return nearest integer **/ static value math_round( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: return alloc_best_int( (int)floor(val_float(n) + 0.5) ); default: neko_error(); } } /** math_fceil : number -> number Return rounded-up float without integer overflow **/ static value math_fceil( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: return alloc_float( ceil(val_float(n)) ); default: neko_error(); } } /** math_ffloor : number -> number Return rounded-down float without integer overflow **/ static value math_ffloor( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: return alloc_float( floor(val_float(n)) ); default: neko_error(); } } /** math_fround : number -> number Return rounded float without integer overflow **/ static value math_fround( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: return alloc_float( floor(val_float(n) + 0.5) ); default: neko_error(); } } /** math_int : number -> int Return integer rounded down towards 0 **/ static value math_int( value n ) { switch( val_type(n) ) { case VAL_INT: case VAL_INT32: return n; case VAL_FLOAT: { tfloat v = val_float(n); return alloc_best_int( (int)((v < 0) ? ceil(v) : floor(v)) ); } default: neko_error(); } } #define PI 3.1415926535897932384626433832795 /** math_pi : void -> float Return the value of PI **/ static value math_pi() { return alloc_float(PI); } /** math_sqrt : number -> float Return the square-root **/ MATH_PRIM(sqrt); /** math_atan : number -> float Return the arc-tangent **/ MATH_PRIM(atan); /** math_cos : number -> float Return the cosinus **/ MATH_PRIM(cos); /** math_sin : number -> float Return the sinus **/ MATH_PRIM(sin); /** math_tan : number -> float Return the tangent **/ MATH_PRIM(tan); /** math_log : number -> float Return the logarithm **/ MATH_PRIM(log); /** math_exp : number -> float Return the exponant **/ MATH_PRIM(exp); /** math_acos : number -> float Return the arc-cosinus **/ MATH_PRIM(acos); /** math_asin : number -> float Return the arc-sinus **/ MATH_PRIM(asin); DEFINE_PRIM(math_pi,0); DEFINE_PRIM(math_atan2,2); DEFINE_PRIM(math_pow,2); DEFINE_PRIM(math_abs,1); DEFINE_PRIM(math_ceil,1); DEFINE_PRIM(math_floor,1); DEFINE_PRIM(math_round,1); DEFINE_PRIM(math_fceil,1); DEFINE_PRIM(math_ffloor,1); DEFINE_PRIM(math_fround,1); DEFINE_PRIM(math_int,1); /* ************************************************************************ */ neko-2-2-0/libs/std/md5.c000066400000000000000000000252611321613172000150230ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "sha1.h" /**

MD5

MD5 digest functions

**/ #ifndef uint8 #define uint8 unsigned char #endif #ifndef uint32 #define uint32 unsigned long int #endif typedef struct { uint32 total[2]; uint32 state[4]; uint8 buffer[64]; } md5_context; #define GET_UINT32(n,b,i) \ { \ (n) = ( (uint32) (b)[(i) ] ) \ | ( (uint32) (b)[(i) + 1] << 8 ) \ | ( (uint32) (b)[(i) + 2] << 16 ) \ | ( (uint32) (b)[(i) + 3] << 24 ); \ } #define PUT_UINT32(n,b,i) \ { \ (b)[(i) ] = (uint8) ( (n) ); \ (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \ (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \ (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \ } static void md5_starts( md5_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; } static void md5_process( md5_context *ctx, uint8 data[64] ) { uint32 X[16], A, B, C, D; GET_UINT32( X[0], data, 0 ); GET_UINT32( X[1], data, 4 ); GET_UINT32( X[2], data, 8 ); GET_UINT32( X[3], data, 12 ); GET_UINT32( X[4], data, 16 ); GET_UINT32( X[5], data, 20 ); GET_UINT32( X[6], data, 24 ); GET_UINT32( X[7], data, 28 ); GET_UINT32( X[8], data, 32 ); GET_UINT32( X[9], data, 36 ); GET_UINT32( X[10], data, 40 ); GET_UINT32( X[11], data, 44 ); GET_UINT32( X[12], data, 48 ); GET_UINT32( X[13], data, 52 ); GET_UINT32( X[14], data, 56 ); GET_UINT32( X[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define P(a,b,c,d,k,s,t) \ { \ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ } A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; #define F(x,y,z) (z ^ (x & (y ^ z))) P( A, B, C, D, 0, 7, 0xD76AA478 ); P( D, A, B, C, 1, 12, 0xE8C7B756 ); P( C, D, A, B, 2, 17, 0x242070DB ); P( B, C, D, A, 3, 22, 0xC1BDCEEE ); P( A, B, C, D, 4, 7, 0xF57C0FAF ); P( D, A, B, C, 5, 12, 0x4787C62A ); P( C, D, A, B, 6, 17, 0xA8304613 ); P( B, C, D, A, 7, 22, 0xFD469501 ); P( A, B, C, D, 8, 7, 0x698098D8 ); P( D, A, B, C, 9, 12, 0x8B44F7AF ); P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); P( B, C, D, A, 11, 22, 0x895CD7BE ); P( A, B, C, D, 12, 7, 0x6B901122 ); P( D, A, B, C, 13, 12, 0xFD987193 ); P( C, D, A, B, 14, 17, 0xA679438E ); P( B, C, D, A, 15, 22, 0x49B40821 ); #undef F #define F(x,y,z) (y ^ (z & (x ^ y))) P( A, B, C, D, 1, 5, 0xF61E2562 ); P( D, A, B, C, 6, 9, 0xC040B340 ); P( C, D, A, B, 11, 14, 0x265E5A51 ); P( B, C, D, A, 0, 20, 0xE9B6C7AA ); P( A, B, C, D, 5, 5, 0xD62F105D ); P( D, A, B, C, 10, 9, 0x02441453 ); P( C, D, A, B, 15, 14, 0xD8A1E681 ); P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); P( A, B, C, D, 9, 5, 0x21E1CDE6 ); P( D, A, B, C, 14, 9, 0xC33707D6 ); P( C, D, A, B, 3, 14, 0xF4D50D87 ); P( B, C, D, A, 8, 20, 0x455A14ED ); P( A, B, C, D, 13, 5, 0xA9E3E905 ); P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); P( C, D, A, B, 7, 14, 0x676F02D9 ); P( B, C, D, A, 12, 20, 0x8D2A4C8A ); #undef F #define F(x,y,z) (x ^ y ^ z) P( A, B, C, D, 5, 4, 0xFFFA3942 ); P( D, A, B, C, 8, 11, 0x8771F681 ); P( C, D, A, B, 11, 16, 0x6D9D6122 ); P( B, C, D, A, 14, 23, 0xFDE5380C ); P( A, B, C, D, 1, 4, 0xA4BEEA44 ); P( D, A, B, C, 4, 11, 0x4BDECFA9 ); P( C, D, A, B, 7, 16, 0xF6BB4B60 ); P( B, C, D, A, 10, 23, 0xBEBFBC70 ); P( A, B, C, D, 13, 4, 0x289B7EC6 ); P( D, A, B, C, 0, 11, 0xEAA127FA ); P( C, D, A, B, 3, 16, 0xD4EF3085 ); P( B, C, D, A, 6, 23, 0x04881D05 ); P( A, B, C, D, 9, 4, 0xD9D4D039 ); P( D, A, B, C, 12, 11, 0xE6DB99E5 ); P( C, D, A, B, 15, 16, 0x1FA27CF8 ); P( B, C, D, A, 2, 23, 0xC4AC5665 ); #undef F #define F(x,y,z) (y ^ (x | ~z)) P( A, B, C, D, 0, 6, 0xF4292244 ); P( D, A, B, C, 7, 10, 0x432AFF97 ); P( C, D, A, B, 14, 15, 0xAB9423A7 ); P( B, C, D, A, 5, 21, 0xFC93A039 ); P( A, B, C, D, 12, 6, 0x655B59C3 ); P( D, A, B, C, 3, 10, 0x8F0CCC92 ); P( C, D, A, B, 10, 15, 0xFFEFF47D ); P( B, C, D, A, 1, 21, 0x85845DD1 ); P( A, B, C, D, 8, 6, 0x6FA87E4F ); P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); P( C, D, A, B, 6, 15, 0xA3014314 ); P( B, C, D, A, 13, 21, 0x4E0811A1 ); P( A, B, C, D, 4, 6, 0xF7537E82 ); P( D, A, B, C, 11, 10, 0xBD3AF235 ); P( C, D, A, B, 2, 15, 0x2AD7D2BB ); P( B, C, D, A, 9, 21, 0xEB86D391 ); #undef F ctx->state[0] += A; ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; } static void md5_update( md5_context *ctx, uint8 *input, uint32 length ) { uint32 left, fill; if( !length ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += length; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < length ) ctx->total[1]++; if( left && length >= fill ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); md5_process( ctx, ctx->buffer ); length -= fill; input += fill; left = 0; } while( length >= 64 ) { md5_process( ctx, input ); length -= 64; input += 64; } if( length ) { memcpy( (void *) (ctx->buffer + left), (void *) input, length ); } } static uint8 md5_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static void md5_finish( md5_context *ctx, uint8 digest[16] ) { uint32 last, padn; uint32 high, low; uint8 msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_UINT32( low, msglen, 0 ); PUT_UINT32( high, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); md5_update( ctx, md5_padding, padn ); md5_update( ctx, msglen, 8 ); PUT_UINT32( ctx->state[0], digest, 0 ); PUT_UINT32( ctx->state[1], digest, 4 ); PUT_UINT32( ctx->state[2], digest, 8 ); PUT_UINT32( ctx->state[3], digest, 12 ); } static void md5_uint( md5_context *m, uint32 i ) { md5_update(m,(unsigned char*)&i,4); } typedef struct stack { uint32 pos; value v; md5_context *m; struct stack *next; } stack; // build some integers that are not neko ones (last bit at 0) // this reduce the possible collisions. // bit 0 = 0 // bit 1-2 = // 00 : const (null, true, false, abstract) // 01 : ref // 10 : fun // 11 : array // // md5-similar objects can still be forged, in particular // due to the fact that no special flag is added to the string // digest in order to keep compatibility with standard md5 // implementation. // // For example md5(null) == md5("\000\000\000\000") static void make_md5_fields( value v, field f, void * ); static void make_md5_rec( md5_context *m, value v, stack *cur ) { switch( val_type(v) ) { case VAL_NULL: md5_uint(m,0); break; case VAL_INT: md5_uint(m,(uint32)(int_val)v); break; case VAL_INT32: md5_uint(m,(uint32)val_int32(v)); break; case VAL_BOOL: md5_uint(m,val_bool(v)?8:16); break; case VAL_FLOAT: { tfloat f = val_float(v); md5_update(m,(unsigned char *)&f,sizeof(tfloat)); } break; case VAL_STRING: md5_update(m,(uint8*)val_string(v),(uint32)val_strlen(v)); break; case VAL_OBJECT: case VAL_ARRAY: { stack loc; stack *s = cur; while( s != NULL ) { if( s->v == v ) { md5_uint(m,(s->pos << 3) | 2); return; } s = s->next; } loc.v = v; loc.pos = cur?(cur->pos+1):0; loc.next = cur; loc.m = m; if( val_is_object(v) ) { val_iter_fields(v,make_md5_fields,&loc); v = (value)((vobject*)v)->proto; if( v != NULL ) make_md5_rec(m,v,&loc); } else { int len = val_array_size(v); md5_uint(m,(len << 3) | 6); while( len-- > 0 ) make_md5_rec(m,val_array_ptr(v)[len],&loc); } } break; case VAL_FUNCTION: md5_uint(m,(val_fun_nargs(v) << 3) | 4); break; case VAL_ABSTRACT: md5_uint(m,24); break; } } static void make_md5_fields( value v, field f, void *c ) { stack *s = (stack*)c; md5_uint(s->m,f); make_md5_rec(s->m,v,s); } /** make_md5 : any -> string Build a MD5 digest (16 bytes binary string) from any value. **/ static value make_md5( value v ) { value out = alloc_empty_string(16); md5_context m; md5_starts(&m); make_md5_rec(&m,v,NULL); md5_finish(&m,(uint8 *)val_string(out)); return out; } /** make_sha1 : string -> pos:int -> len:int -> string Build a SHA1 digest for the given substring **/ static value make_sha1( value s, value p, value l ) { SHA1_CTX ctx; SHA1_DIGEST result; int pp , ll; val_check(s,string); val_check(p,int); val_check(l,int); pp = val_int(p); ll = val_int(l); if( pp < 0 || ll < 0 || pp + ll < 0 || pp + ll > val_strlen(s) ) neko_error(); sha1_init(&ctx); sha1_update(&ctx,(unsigned char*)val_string(l)+pp,ll); sha1_final(&ctx,result); return copy_string( (char*)result, sizeof(SHA1_DIGEST) ); } DEFINE_PRIM(make_md5,1); DEFINE_PRIM(make_sha1,3); /* ************************************************************************ */ neko-2-2-0/libs/std/memory.c000066400000000000000000000124401321613172000156410ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include /**

Memory

An API for memory manipulation and statistics.

**/ typedef struct _vtree { int_val v; struct _vtree *left; struct _vtree *right; } vtree; typedef struct { vtree **t; int s; } vparams; static int mem_cache( void *v, vtree **t ) { vtree *p = *t; vtree *prev = NULL; while( p != NULL ) { if( p->v == (int_val)v ) return 1; prev = p; if( p->v > (int_val)v ) p = p->left; else p = p->right; } p = (vtree*)alloc(sizeof(vtree)); p->v = (int_val)v; p->left = NULL; p->right = NULL; if( prev == NULL ) *t = p; else { if( prev->v > p->v ) prev->left = p; else prev->right = p; } return 0; } static void mem_obj_field( value v, field f, void *_p ); static int mem_module( neko_module *m, vtree **l ); static int mem_size_rec( value v, vtree **l ) { switch( val_type(v) ) { case VAL_INT: case VAL_BOOL: case VAL_NULL: return 0; case VAL_FLOAT: if( mem_cache(v,l) ) return 0; return sizeof(vfloat); case VAL_INT32: if( mem_cache(v,l) ) return 0; return sizeof(vint32); case VAL_STRING: if( mem_cache(v,l) ) return 0; return sizeof(value) + val_strlen(v); case VAL_OBJECT: if( mem_cache(v,l) ) return 0; { vparams p; p.t = l; p.s = sizeof(vobject); val_iter_fields(v,mem_obj_field,&p); if( ((vobject*)v)->proto != NULL ) p.s += mem_size_rec((value)((vobject*)v)->proto,l); return p.s; } case VAL_ARRAY: if( mem_cache(v,l) ) return 0; { int t = sizeof(value); int size = val_array_size(v); int i; t += size * sizeof(value); for(i=0;ienv,l); if( val_tag(v) == VAL_PRIMITIVE ) t += mem_size_rec((value)((vfunction*)v)->module,l); else t += mem_module(((vfunction*)v)->module,l); return t; } case VAL_ABSTRACT: { int t; if( mem_cache(v,l) ) return 0; t = sizeof(vabstract); if( val_kind(v) == neko_kind_module ) t += mem_module((neko_module*)val_data(v),l); else if( val_kind(v) == k_hash ) { vhash *h = (vhash*)val_data(v); int i; t += sizeof(vhash); t += sizeof(hcell*) * h->ncells; for(i=0;incells;i++) { hcell *c = h->cells[i]; while( c != NULL ) { t += sizeof(hcell); t += mem_size_rec(c->key,l); t += mem_size_rec(c->val,l); c = c->next; } } } return t; } default: val_throw(alloc_string("mem_size : Unexpected value")); break; } return 0; } static void mem_obj_field( value v, field f, void *_p ) { vparams *p = (vparams*)_p; p->s += sizeof(objcell); p->s += mem_size_rec(v,p->t); } static int mem_module( neko_module *m, vtree **l ) { int t = 0; unsigned int i; if( mem_cache(m,l) ) return 0; t += sizeof(neko_module); t += m->codesize * sizeof(int_val); t += m->nglobals * sizeof(int_val); for(i=0;inglobals;i++) t += mem_size_rec(m->globals[i],l); t += m->nfields * sizeof(value*); for(i=0;infields;i++) t += mem_size_rec(m->fields[i],l); t += mem_size_rec(m->loader,l); t += mem_size_rec(m->exports,l); t += mem_size_rec(m->dbgtbl,l); if( m->dbgidxs ) t += sizeof(neko_debug) * (m->codesize >> 5); t += mem_size_rec(m->name,l); return t; } /** mem_size : any -> int Calculate the quite precise amount of VM memory reachable from this value **/ static value mem_size( value v ) { vtree *t = NULL; return alloc_int(mem_size_rec(v,&t)); } /** mem_local_size : any -> any array -> int Calculate the quite precise amount of VM memory reachable from this value, without scanning the values contained in the array. **/ static value mem_local_size( value v, value a ) { vtree *t = NULL; int i; val_check(a,array); for(i=0;i /**

Misc

Misc. functions for different usages.

**/ /** float_bytes : number -> bigendian:bool -> string Returns the 4 bytes representation of the number as an IEEE 32-bit float **/ static value float_bytes( value n, value be ) { float f; val_check(n,number); val_check(be,bool); f = (float)val_number(n); if( neko_is_big_endian() != val_bool(be) ) { char *c = (char*)&f; char tmp; tmp = c[0]; c[0] = c[3]; c[3] = tmp; tmp = c[1]; c[1] = c[2]; c[2] = tmp; } return copy_string((char *)&f,4); } /** double_bytes : number -> bigendian:bool -> string Returns the 8 bytes representation of the number as an IEEE 64-bit float **/ static value double_bytes( value n, value be ) { double f; val_check(n,number); val_check(be,bool); f = (double)val_number(n); if( neko_is_big_endian() != val_bool(be) ) { char *c = (char*)&f; char tmp; tmp = c[0]; c[0] = c[7]; c[7] = tmp; tmp = c[1]; c[1] = c[6]; c[6] = tmp; tmp = c[2]; c[2] = c[5]; c[5] = tmp; tmp = c[3]; c[3] = c[4]; c[4] = tmp; } return copy_string((char*)&f,8); } /** float_of_bytes : string -> bigendian:bool -> float Returns a float from a 4 bytes IEEE 32-bit representation **/ static value float_of_bytes( value s, value be ) { float f; val_check(s,string); val_check(be,bool); if( val_strlen(s) != 4 ) neko_error(); f = *(float*)val_string(s); if( neko_is_big_endian() != val_bool(be) ) { char *c = (char*)&f; char tmp; tmp = c[0]; c[0] = c[3]; c[3] = tmp; tmp = c[1]; c[1] = c[2]; c[2] = tmp; } return alloc_float(f); } /** double_of_bytes : string -> bigendian:bool -> float Returns a float from a 8 bytes IEEE 64-bit representation **/ static value double_of_bytes( value s, value be ) { double f; val_check(s,string); val_check(be,bool); if( val_strlen(s) != 8 ) neko_error(); f = *(double*)val_string(s); if( neko_is_big_endian() != val_bool(be) ) { char *c = (char*)&f; char tmp; tmp = c[0]; c[0] = c[7]; c[7] = tmp; tmp = c[1]; c[1] = c[6]; c[6] = tmp; tmp = c[2]; c[2] = c[5]; c[5] = tmp; tmp = c[3]; c[3] = c[4]; c[4] = tmp; } return alloc_float(f); } /** run_gc : major:bool -> void Run the Neko garbage collector **/ static value run_gc( value b ) { val_check(b,bool); if( val_bool(b) ) neko_gc_major(); else neko_gc_loop(); return val_null; } /** gc_stats : void -> { heap => int, free => int } Return the size of the GC heap and the among of free space, in bytes **/ static value gc_stats() { int heap, free; value o; neko_gc_stats(&heap,&free); o = alloc_object(NULL); alloc_field(o,val_id("heap"),alloc_int(heap)); alloc_field(o,val_id("free"),alloc_int(free)); return o; } /** enable_jit : ?bool -> ?bool Enable or disable the JIT. Calling enable_jit(null) tells if JIT is enabled or not **/ static value enable_jit( value b ) { if( val_is_null(b) ) return alloc_bool(neko_vm_jit(neko_vm_current(),-1)); val_check(b,bool); neko_vm_jit(neko_vm_current(),val_bool(b)); return val_null; } /** test : void -> void The test function, to check that library is reachable and correctly linked **/ static value test() { val_print(alloc_string("Calling a function inside std library...\n")); return val_null; } /** print_redirect : function:1? -> void Set a redirection function for all printed values. Setting it to null will cancel the redirection and restore previous printer. **/ static void print_callback( const char *s, int size, void *f ) { val_call1(f,copy_string(s,size)); } static value print_redirect( value f ) { neko_vm *vm = neko_vm_current(); if( val_is_null(f) ) { neko_vm_redirect(vm,NULL,NULL); return val_null; } val_check_function(f,1); neko_vm_redirect(vm,print_callback,f); return val_null; } /** set_trusted : bool -> void Change the trusted mode of the VM. This can optimize some operations such as module loading by turning off some checks. **/ static value set_trusted( value b ) { val_check(b,bool); neko_vm_trusted(neko_vm_current(),val_bool(b)); return val_null; } /** same_closure : any -> any -> bool Compare two functions by checking that they refer to the same implementation and that their environments contains physically equal values. **/ static value same_closure( value _f1, value _f2 ) { vfunction *f1 = (vfunction*)_f1; vfunction *f2 = (vfunction*)_f2; int i; if( !val_is_function(f1) || !val_is_function(f2) ) return val_false; if( f1 == f2 ) return val_true; if( f1->nargs != f2->nargs || f1->addr != f2->addr || f1->module != f2->module || val_array_size(f1->env) != val_array_size(f2->env) ) return val_false; for(i=0;ienv);i++) if( val_array_ptr(f1->env)[i] != val_array_ptr(f2->env)[i] ) return val_false; return val_true; } // ------------- MERGE SORT HELPERS ----------------------------- typedef struct { value *arr; value cmp; } m_sort; static int ms_compare( m_sort *m, int a, int b ) { value v = val_call2(m->cmp,m->arr[a],m->arr[b]); if( !val_is_int(v) ) return -1; return val_int(v); } static void ms_swap( m_sort *m, int a, int b ) { value tmp = m->arr[a]; m->arr[a] = m->arr[b]; m->arr[b] = tmp; } static int ms_lower( m_sort *m, int from, int to, int val ) { int len = to - from, half, mid; while( len > 0 ) { half = len>>1; mid = from + half; if( ms_compare(m, mid, val) < 0 ) { from = mid+1; len = len - half -1; } else len = half; } return from; } static int ms_upper( m_sort *m, int from, int to, int val ) { int len = to - from, half, mid; while( len > 0 ) { half = len>>1; mid = from + half; if( ms_compare(m, val, mid) < 0 ) len = half; else { from = mid+1; len = len - half -1; } } return from; } static int ms_gcd( int m, int n ) { while( n != 0 ) { int t = m % n; m=n; n=t; } return m; } static void ms_rotate( m_sort *m, int from, int mid, int to ) { int n; if( from==mid || mid==to ) return; n = ms_gcd(to - from, mid - from); while (n-- != 0) { value val = m->arr[from+n]; int shift = mid - from; int p1 = from+n, p2=from+n+shift; while (p2 != from + n) { m->arr[p1] = m->arr[p2]; p1=p2; if( to - p2 > shift) p2 += shift; else p2=from + (shift - (to - p2)); } m->arr[p1] = val; } } static void ms_do_merge( m_sort *m, int from, int pivot, int to, int len1, int len2 ) { int first_cut, second_cut, len11, len22, new_mid; if( len1 == 0 || len2==0 ) return; if( len1+len2 == 2 ) { if( ms_compare(m, pivot, from) < 0 ) ms_swap(m, pivot, from); return; } if (len1 > len2) { len11=len1>>1; first_cut = from + len11; second_cut = ms_lower(m, pivot, to, first_cut); len22 = second_cut - pivot; } else { len22 = len2>>1; second_cut = pivot + len22; first_cut = ms_upper(m, from, pivot, second_cut); len11=first_cut - from; } ms_rotate(m, first_cut, pivot, second_cut); new_mid=first_cut+len22; ms_do_merge(m, from, first_cut, new_mid, len11, len22); ms_do_merge(m, new_mid, second_cut, to, len1 - len11, len2 - len22); } static void merge_sort_rec( m_sort *m, int from, int to ) { int middle; if( to - from < 12 ) { // insert sort int i; if( to <= from ) return; for(i=from+1;i from ) { if( ms_compare(m,j,j-1) < 0 ) ms_swap(m,j-1,j); else break; j--; } } return; } middle = (from + to)>>1; merge_sort_rec(m, from, middle); merge_sort_rec(m, middle, to); ms_do_merge(m, from, middle, to, middle-from, to - middle); } /** merge_sort : array -> length:int -> cmp:function:2 -> void Sort the array using stable in-place merge sort and the [cmp] compare function. **/ static value merge_sort( value arr, value len, value cmp ) { m_sort m; val_check(arr,array); val_check(len,int); val_check_function(cmp,2); m.arr = val_array_ptr(arr); m.cmp = cmp; merge_sort_rec(&m,0,val_int(len)); return val_null; } DEFINE_PRIM(float_bytes,2); DEFINE_PRIM(double_bytes,2); DEFINE_PRIM(float_of_bytes,2); DEFINE_PRIM(double_of_bytes,2); DEFINE_PRIM(run_gc,1); DEFINE_PRIM(gc_stats,0); DEFINE_PRIM(enable_jit,1); DEFINE_PRIM(test,0); DEFINE_PRIM(print_redirect,1); DEFINE_PRIM(set_trusted,1); DEFINE_PRIM(same_closure,2); DEFINE_PRIM(merge_sort,3); /* ************************************************************************ */ neko-2-2-0/libs/std/module.c000066400000000000000000000151561321613172000156250ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #define READ_BUFSIZE 64 /**

Module

An API for reflexion of Neko bytecode modules.

**/ static int read_proxy( readp p, void *buf, int size ) { value fread = val_array_ptr(p)[0]; value vbuf = val_array_ptr(p)[1]; value ret; int len; if( size < 0 ) return -1; if( size > READ_BUFSIZE ) vbuf = alloc_empty_string(size); ret = val_call3(fread,vbuf,alloc_int(0),alloc_int(size)); if( !val_is_int(ret) ) return -1; len = val_int(ret); if( len < 0 || len > size ) return -1; memcpy(buf,val_string(vbuf),len); return len; } /** module_read : fread:(buf:string -> pos:int -> len:int -> int) -> loader:object -> 'module Read a module using the specified read function and the specified loader. **/ static value module_read( value fread, value loader ) { value p; neko_module *m; val_check_function(fread,3); val_check(loader,object); p = alloc_array(2); val_array_ptr(p)[0] = fread; val_array_ptr(p)[1] = alloc_empty_string(READ_BUFSIZE); m = neko_read_module(read_proxy,p,loader); if( m == NULL ) neko_error(); m->name = alloc_string(""); return alloc_abstract(neko_kind_module,m); } /** module_read_string : string -> loader:object -> 'module Read a module using the specified string datas. **/ static value module_read_string( value str, value loader ) { neko_module *m; string_pos p; val_check(str,string); val_check(loader,object); p.p = val_string(str); p.len = val_strlen(str); m = neko_read_module(neko_string_reader,&p,loader); if( m == NULL ) neko_error(); m->name = alloc_string(""); return alloc_abstract(neko_kind_module,m); } /** module_read_path : string list -> name:string -> loader:object -> 'module Read a module using the specified search path. **/ static value module_read_path( value path, value name, value loader ) { FILE *f; value fname; char *mname, *ext; neko_module *m; val_check(name,string); val_check(loader,object); mname = val_string(name); ext = strrchr(mname,'.'); if( ext && ext[1] == 'n' && ext[2] == 0 ) fname = neko_select_file(path,mname,""); else fname = neko_select_file(path,mname,".n"); f = fopen(val_string(fname),"rb"); if( f == NULL ) { buffer b = alloc_buffer("Module not found : "); buffer_append(b,mname); bfailure(b); } m = neko_read_module(neko_file_reader,f,loader); fclose(f); if( m == NULL ) { buffer b = alloc_buffer("Invalid module : "); val_buffer(b,name); bfailure(b); } m->name = alloc_string(val_string(name)); return alloc_abstract(neko_kind_module,m); } /** module_exec : 'module -> any Execute the module, return the calculated value **/ static value module_exec( value mv ) { neko_module *m; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); return neko_vm_execute(neko_vm_current(),m); } /** module_name : 'module -> string Return the module name **/ static value module_name( value mv ) { neko_module *m; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); return m->name; } /** module_set_name : 'module -> string -> void Set the module name **/ static value module_set_name( value mv, value str ) { neko_module *m; val_check_kind(mv,neko_kind_module); val_check(str,string); m = (neko_module*)val_data(mv); m->name = str; return val_null; } /** module_exports : 'module -> object Return the module export table **/ static value module_exports( value mv ) { neko_module *m; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); return m->exports; } /** module_loader : 'module -> object Return the module loader **/ static value module_loader( value mv ) { neko_module *m; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); return m->loader; } /** module_nglobals : 'module -> int Return the number of globals for this module **/ static value module_nglobals( value mv ) { neko_module *m; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); return alloc_int(m->nglobals); } /** module_global_get : 'module -> n:int -> any Get the [n]th global **/ static value module_global_get( value mv, value p ) { neko_module *m; unsigned int pp; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); val_check(p,int); pp = (unsigned)val_int(p); if( pp >= m->nglobals ) neko_error(); return m->globals[pp]; } /** module_global_set : 'module -> n:int -> any -> void Set the [n]th global **/ static value module_global_set( value mv, value p, value v ) { neko_module *m; unsigned int pp; val_check_kind(mv,neko_kind_module); m = (neko_module*)val_data(mv); val_check(p,int); pp = (unsigned)val_int(p); if( pp >= m->nglobals ) neko_error(); m->globals[pp] = v; return v; } /** module_code_size : 'module -> int return the codesize of the module **/ static value module_code_size( value mv ) { val_check_kind(mv,neko_kind_module); return alloc_int( ((neko_module*)val_data(mv))->codesize ); } DEFINE_PRIM(module_read,2); DEFINE_PRIM(module_read_string,2); DEFINE_PRIM(module_read_path,3); DEFINE_PRIM(module_exec,1); DEFINE_PRIM(module_name,1); DEFINE_PRIM(module_exports,1); DEFINE_PRIM(module_loader,1); DEFINE_PRIM(module_nglobals,1); DEFINE_PRIM(module_global_get,2); DEFINE_PRIM(module_global_set,3); DEFINE_PRIM(module_code_size,1); DEFINE_PRIM(module_set_name,2); /* ************************************************************************ */ neko-2-2-0/libs/std/process.c000066400000000000000000000266671321613172000160270ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #ifdef NEKO_WINDOWS # include #else # include # include # include # if !defined(NEKO_MAC) # if defined(NEKO_BSD) # include # else # include # endif # endif #endif #include #include typedef struct { #ifdef NEKO_WINDOWS HANDLE oread; HANDLE eread; HANDLE iwrite; PROCESS_INFORMATION pinf; #else int oread; int eread; int iwrite; int pid; #endif } vprocess; DEFINE_KIND(k_process); #define val_process(v) ((vprocess*)val_data(v)) /**

Process

An API for starting and communication with sub processes.

**/ #ifndef NEKO_WINDOWS static int do_close( int fd ) { POSIX_LABEL(close_again); if( close(fd) != 0 ) { HANDLE_EINTR(close_again); return 1; } return 0; } #endif static void free_process( value vp ) { vprocess *p = val_process(vp); # ifdef NEKO_WINDOWS CloseHandle(p->eread); CloseHandle(p->oread); CloseHandle(p->iwrite); CloseHandle(p->pinf.hProcess); CloseHandle(p->pinf.hThread); # else do_close(p->eread); do_close(p->oread); do_close(p->iwrite); # endif } /** process_run : cmd:string -> args:string array -> 'process Start a process using a command and the specified arguments. When args is not null, cmd and args will be auto-quoted/escaped. If no auto-quoting/escaping is desired, you should append necessary arguments to cmd as if it is inputted to the shell directly, and pass null as args. **/ static value process_run( value cmd, value vargs ) { int i, isRaw; vprocess *p; val_check(cmd,string); isRaw = val_is_null(vargs); if (!isRaw) { val_check(vargs,array); } # ifdef NEKO_WINDOWS { SECURITY_ATTRIBUTES sattr; STARTUPINFO sinf; HANDLE proc = GetCurrentProcess(); HANDLE oread,eread,iwrite; // creates commandline buffer b = alloc_buffer(NULL); value sargs; if (isRaw) { char* cmdexe = getenv("COMSPEC"); if (!cmdexe) cmdexe = "cmd.exe"; buffer_append(b,"\""); buffer_append(b,cmdexe); buffer_append(b,"\" /C \""); buffer_append(b,val_string(cmd)); buffer_append_char(b,'"'); } else { buffer_append_char(b,'"'); val_buffer(b,cmd); buffer_append_char(b,'"'); for(i=0;ioread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,eread,proc,&p->eread,0,FALSE,DUPLICATE_SAME_ACCESS); DuplicateHandle(proc,iwrite,proc,&p->iwrite,0,FALSE,DUPLICATE_SAME_ACCESS); CloseHandle(oread); CloseHandle(eread); CloseHandle(iwrite); if( !CreateProcess(NULL,val_string(sargs),NULL,NULL,TRUE,0,NULL,NULL,&sinf,&p->pinf) ) neko_error(); // close unused pipes CloseHandle(sinf.hStdOutput); CloseHandle(sinf.hStdError); CloseHandle(sinf.hStdInput); } # else char **argv; if (isRaw) { argv = (char**)alloc_private(sizeof(char*)*4); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = val_string(cmd); argv[3] = NULL; } else { argv = (char**)alloc_private(sizeof(char*)*(val_array_size(vargs)+2)); argv[0] = val_string(cmd); for(i=0;ipid = fork(); if( p->pid == -1 ) { do_close(input[0]); do_close(input[1]); do_close(output[0]); do_close(output[1]); do_close(error[0]); do_close(error[1]); neko_error(); } // child if( p->pid == 0 ) { close(input[1]); close(output[0]); close(error[0]); dup2(input[0],0); dup2(output[1],1); dup2(error[1],2); execvp(argv[0],argv); fprintf(stderr,"Command not found : %s\n",val_string(cmd)); exit(1); } // parent do_close(input[0]); do_close(output[1]); do_close(error[1]); p->iwrite = input[1]; p->oread = output[0]; p->eread = error[0]; # endif { value vp = alloc_abstract(k_process,p); val_gc(vp,free_process); return vp; } } #define CHECK_ARGS() \ vprocess *p; \ val_check_kind(vp,k_process); \ val_check(str,string); \ val_check(pos,int); \ val_check(len,int); \ if( val_int(pos) < 0 || val_int(len) < 0 || val_int(pos) + val_int(len) > val_strlen(str) ) \ neko_error(); \ p = val_process(vp); \ /** process_stdout_read : 'process -> buf:string -> pos:int -> len:int -> int Read up to [len] bytes in [buf] starting at [pos] from the process stdout. Returns the number of bytes readed this way. Raise an exception if this process stdout is closed and no more data is available for reading. **/ static value process_stdout_read( value vp, value str, value pos, value len ) { CHECK_ARGS(); # ifdef NEKO_WINDOWS { DWORD nbytes; if( !ReadFile(p->oread,val_string(str)+val_int(pos),val_int(len),&nbytes,NULL) ) neko_error(); return alloc_int(nbytes); } # else int nbytes; POSIX_LABEL(stdout_read_again); nbytes = read(p->oread,val_string(str)+val_int(pos),val_int(len)); if( nbytes < 0 ) { HANDLE_EINTR(stdout_read_again); neko_error(); } if( nbytes == 0 ) neko_error(); return alloc_int(nbytes); # endif } /** process_stderr_read : 'process -> buf:string -> pos:int -> len:int -> int Read up to [len] bytes in [buf] starting at [pos] from the process stderr. Returns the number of bytes readed this way. Raise an exception if this process stderr is closed and no more data is available for reading. **/ static value process_stderr_read( value vp, value str, value pos, value len ) { CHECK_ARGS(); # ifdef NEKO_WINDOWS { DWORD nbytes; if( !ReadFile(p->eread,val_string(str)+val_int(pos),val_int(len),&nbytes,NULL) ) neko_error(); return alloc_int(nbytes); } # else int nbytes; POSIX_LABEL(stderr_read_again); nbytes = read(p->eread,val_string(str)+val_int(pos),val_int(len)); if( nbytes < 0 ) { HANDLE_EINTR(stderr_read_again); neko_error(); } if( nbytes == 0 ) neko_error(); return alloc_int(nbytes); # endif } /** process_stdin_write : 'process -> buf:string -> pos:int -> len:int -> int Write up to [len] bytes from [buf] starting at [pos] to the process stdin. Returns the number of bytes writen this way. Raise an exception if this process stdin is closed. **/ static value process_stdin_write( value vp, value str, value pos, value len ) { CHECK_ARGS(); # ifdef NEKO_WINDOWS { DWORD nbytes; if( !WriteFile(p->iwrite,val_string(str)+val_int(pos),val_int(len),&nbytes,NULL) ) neko_error(); return alloc_int(nbytes); } # else int nbytes; POSIX_LABEL(stdin_write_again); nbytes = write(p->iwrite,val_string(str)+val_int(pos),val_int(len)); if( nbytes == -1 ) { HANDLE_EINTR(stdin_write_again); neko_error(); } return alloc_int(nbytes); # endif } /** process_stdin_close : 'process -> void Close the process standard input. **/ static value process_stdin_close( value vp ) { vprocess *p; val_check_kind(vp,k_process); p = val_process(vp); # ifdef NEKO_WINDOWS if( !CloseHandle(p->iwrite) ) neko_error(); # else if( do_close(p->iwrite) ) neko_error(); p->iwrite = -1; # endif return val_null; } /** process_exit : 'process -> int Wait until the process terminate, then returns its exit code. **/ static value process_exit( value vp ) { vprocess *p; val_check_kind(vp,k_process); p = val_process(vp); # ifdef NEKO_WINDOWS { DWORD rval; WaitForSingleObject(p->pinf.hProcess,INFINITE); if( !GetExitCodeProcess(p->pinf.hProcess,&rval) ) neko_error(); return alloc_int(rval); } # else int rval; while( waitpid(p->pid,&rval,0) != p->pid ) { if( errno == EINTR ) continue; neko_error(); } if( !WIFEXITED(rval) ) { if (WIFSIGNALED(rval)) { char msg[30]; sprintf(msg, "process killed by signal %d", WTERMSIG(rval)); val_throw(alloc_string(msg)); } else { neko_error(); } } return alloc_int(WEXITSTATUS(rval)); # endif } /** process_pid : 'process -> int Returns the process id. **/ static value process_pid( value vp ) { vprocess *p; val_check_kind(vp,k_process); p = val_process(vp); # ifdef NEKO_WINDOWS return alloc_int(p->pinf.dwProcessId); # else return alloc_int(p->pid); # endif } /** process_close : 'process -> void Close the process I/O. **/ static value process_close( value vp ) { val_check_kind(vp,k_process); free_process(vp); val_kind(vp) = NULL; val_gc(vp,NULL); return val_null; } /** process_kill : 'process -> void Terminates a running process. **/ static value process_kill( value vp ) { val_check_kind(vp,k_process); # ifdef NEKO_WINDOWS TerminateProcess(val_process(vp)->pinf.hProcess,-1); # else kill(val_process(vp)->pid,9); # endif return val_null; } DEFINE_PRIM(process_run,2); DEFINE_PRIM(process_stdout_read,4); DEFINE_PRIM(process_stderr_read,4); DEFINE_PRIM(process_stdin_close,1); DEFINE_PRIM(process_stdin_write,4); DEFINE_PRIM(process_exit,1); DEFINE_PRIM(process_pid,1); DEFINE_PRIM(process_close,1); DEFINE_PRIM(process_kill,1); /* ************************************************************************ */ neko-2-2-0/libs/std/random.c000066400000000000000000000103441321613172000156120ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef NEKO_WINDOWS # include # include #else # include # include # include #endif /**

Random

A seeded pseudo-random generator

**/ DEFINE_KIND(k_random); #define val_rnd(o) ((rnd*)val_data(o)) #define NSEEDS 25 #define MAX 7 typedef struct _rnd rnd; struct _rnd { unsigned long seeds[NSEEDS]; unsigned long cur; }; static unsigned long mag01[2]={ 0x0, 0x8ebfd028 // magic, don't change }; static const unsigned long init_seeds[] = { 0x95f24dab, 0x0b685215, 0xe76ccae7, 0xaf3ec239, 0x715fad23, 0x24a590ad, 0x69e4b5ef, 0xbf456141, 0x96bc1b7b, 0xa7bdf825, 0xc1de75b7, 0x8858a9c9, 0x2da87693, 0xb657f9dd, 0xffdc8a9f, 0x8121da71, 0x8b823ecb, 0x885d05f5, 0x4e20cd47, 0x5a9ad5d9, 0x512c0c03, 0xea857ccd, 0x4cc1d30f, 0x8891a8a1, 0xa6b7aadb }; static int rnd_size() { return sizeof(rnd); } static void rnd_set_seed( rnd *r, int s ) { int i; r->cur = 0; memcpy(r->seeds,init_seeds,sizeof(init_seeds)); for(i=0;iseeds[i] ^= s; } static rnd *rnd_init( void *data ) { rnd *r = (rnd*)data; int pid = getpid(); unsigned int time; #ifdef NEKO_WINDOWS time = GetTickCount(); #else struct timeval t; gettimeofday(&t,NULL); time = t.tv_sec * 1000000 + t.tv_usec; #endif rnd_set_seed(r,time ^ (pid | (pid << 16))); return r; } static unsigned int rnd_int( rnd *r ) { unsigned int y; int pos = r->cur++; if( pos >= NSEEDS ) { int kk; for(kk=0;kkseeds[kk] = r->seeds[kk+MAX] ^ (r->seeds[kk] >> 1) ^ mag01[r->seeds[kk] % 2]; for(;kkseeds[kk] = r->seeds[kk+(MAX-NSEEDS)] ^ (r->seeds[kk] >> 1) ^ mag01[r->seeds[kk] % 2]; r->cur = 1; pos = 0; } y = r->seeds[pos]; y ^= (y << 7) & 0x2b5b2500; y ^= (y << 15) & 0xdb8b0000; y ^= (y >> 16); return y; } static double rnd_float( rnd *r ) { double big = 4294967296.0; return ((rnd_int(r) / big + rnd_int(r)) / big + rnd_int(r)) / big; } /** random_new : void -> 'random Create a new random with random seed **/ static value random_new() { return alloc_abstract( k_random, rnd_init(alloc_private(rnd_size())) ); } /** random_set_seed : 'random -> int -> void Set the generator seed **/ static value random_set_seed( value o, value v ) { val_check_kind(o,k_random); val_check(v,any_int); rnd_set_seed(val_rnd(o),val_any_int(v)); return val_true; } /** random_int : 'random -> max:int -> int Return a random integer modulo [max] **/ static value random_int( value o, value max ) { val_check_kind(o,k_random); val_check(max,int); if( val_int(max) <= 0 ) return alloc_int(0); return alloc_int( (rnd_int(val_rnd(o)) & 0x3FFFFFFF) % val_int(max) ); } /** random_float : 'random -> float Return a random float **/ static value random_float( value o ) { val_check_kind(o,k_random); return alloc_float( rnd_float(val_rnd(o)) ); } DEFINE_PRIM(random_new,0); DEFINE_PRIM(random_set_seed,2); DEFINE_PRIM(random_int,2); DEFINE_PRIM(random_float,1); /* ************************************************************************ */ neko-2-2-0/libs/std/serialize.c000066400000000000000000000327221321613172000163250ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #define BUF_SIZE 4096 #define ERROR() val_throw(alloc_string("Invalid serialized data")) typedef struct strlist { unsigned char *str; int slen; struct strlist *next; } strlist; typedef struct odatalist { int k; value data; struct odatalist *left; struct odatalist *right; } odatalist; typedef struct { odatalist *refs; int nrefs; value *trefs; int tsize; strlist *olds; unsigned char *cur; int size; int pos; int totlen; int nrec; } sbuffer; extern field id_module; extern field id_loadmodule; extern field id_loadprim; extern field id_serialize; extern field id_unserialize; static void buffer_alloc( sbuffer *b, int size ) { strlist *str = (strlist*)alloc(sizeof(strlist)); str->str = b->cur; str->slen = b->pos; str->next = b->olds; b->olds = str; b->totlen += b->pos; b->pos = 0; b->size = size; b->cur = (unsigned char*)alloc_private(size); } static void write_char( sbuffer *b, char c ) { if( b->pos == b->size ) buffer_alloc(b,BUF_SIZE); b->cur[b->pos++] = c; } static int read_char( sbuffer *b ) { if( b->pos >= b->size ) return -1; return b->cur[b->pos++]; } static void write_str( sbuffer *b, int len, const void *s ) { int left = b->size - b->pos; if( left == 0 ) { buffer_alloc(b,BUF_SIZE); left = b->size - b->pos; } if( left >= len ) { memcpy(b->cur + b->pos,s,len); b->pos += len; } else { memcpy(b->cur + b->pos,s,left); b->pos += left; write_str(b,len - left, (char*)s + left); } } static void read_str( sbuffer *b, int len, void *s ) { if( b->pos + len > b->size ) ERROR(); memcpy(s,b->cur + b->pos, len); b->pos += len; } static void write_int( sbuffer *b, int n ) { write_str(b,4,&n); } static int read_int( sbuffer *b ) { int n; if( b->pos + 4 > b->size ) ERROR(); memcpy(&n,b->cur + b->pos,4); b->pos += 4; return n; } static void lookup_serialize_field( value data, field id, void *v ) { if( id == id_serialize ) *(value*)v = data; } static bool write_ref( sbuffer *b, value o, value *serialize ) { odatalist *d = b->refs, *prev = NULL; while( d != NULL ) { if( d->data < o ) { prev = d; d = d->left; } else if( d->data == o ) { write_char(b,'r'); write_int(b,b->nrefs - 1 - d->k); return true; } else { prev = d; d = d->right; } } if( serialize != NULL ) { *serialize = NULL; val_iter_fields(o,lookup_serialize_field,serialize); if( *serialize != NULL ) return false; } d = (odatalist*)alloc(sizeof(odatalist)); d->data = o; d->k = b->nrefs++; d->left = NULL; d->right = NULL; if( prev == NULL ) b->refs = d; else if( prev->data < o ) prev->left = d; else prev->right = d; return false; } static void add_ref( sbuffer *b, value v ) { if( b->nrefs == b->tsize ) { int nsize = b->tsize?(b->tsize*2):16; value *ntrefs = (value*)alloc(sizeof(value) * nsize); memcpy(ntrefs,b->trefs,b->tsize * sizeof(value)); b->trefs = ntrefs; b->tsize = nsize; } b->trefs[b->nrefs++] = v; } static void serialize_fields_rec( value data, field id, void *b ); void serialize_rec( sbuffer *b, value o ) { b->nrec++; if( b->nrec > 350 ) failure("Serialization stack overflow"); switch( val_type(o) ) { case VAL_NULL: write_char(b,'N'); break; case VAL_BOOL: if( val_bool(o) ) write_char(b,'T'); else write_char(b,'F'); break; case VAL_INT: write_char(b,'i'); write_int(b,val_int(o)); break; case VAL_FLOAT: write_char(b,'f'); write_str(b,sizeof(tfloat),&val_float(o)); break; case VAL_STRING: if( !write_ref(b,o,NULL) ) { write_char(b,'s'); write_int(b,val_strlen(o)); write_str(b,val_strlen(o),val_string(o)); } break; case VAL_OBJECT: { value s; if( !write_ref(b,o,&s) ) { if( s != NULL ) { // reference was not written if( !val_is_function(s) || (val_fun_nargs(s) != 0 && val_fun_nargs(s) != VAR_ARGS) ) failure("Invalid __serialize method"); write_char(b,'x'); serialize_rec(b,((neko_module*)((vfunction*)s)->module)->name); serialize_rec(b,val_ocall0(o,id_serialize)); // put reference back write_ref(b,o,NULL); break; } write_char(b,'o'); val_iter_fields(o,serialize_fields_rec,b); write_int(b,0); o = (value)((vobject*)o)->proto; if( o == NULL ) write_char(b,'z'); else { write_char(b,'p'); serialize_rec(b,o); } } } break; case VAL_ARRAY: if( !write_ref(b,o,NULL) ) { int i; int n = val_array_size(o); write_char(b,'a'); write_int(b,n); for(i=0;ienv != alloc_array(0) ) failure("Cannot Serialize Primitive with environment"); write_char(b,'p'); write_int(b,((vfunction*)o)->nargs); serialize_rec(b,((vfunction*)o)->module); break; } if( val_tag(o) == VAL_JITFUN ) failure("Cannot Serialize JIT method"); write_char(b,'L'); m = (neko_module*)((vfunction*)o)->module; serialize_rec(b,m->name); write_int(b,(int)((int_val*)((vfunction*)o)->addr - m->code)); write_int(b,((vfunction*)o)->nargs); serialize_rec(b,((vfunction*)o)->env); } break; case VAL_INT32: write_char(b,'I'); write_int(b,val_int32(o)); break; case VAL_ABSTRACT: if( val_is_kind(o,k_hash) ) { int i; vhash *h = val_hdata(o); write_char(b,'h'); write_int(b,h->ncells); write_int(b,h->nitems); for(i=0;incells;i++) { hcell *c = h->cells[i]; while( c != NULL ) { write_int(b,c->hkey); serialize_rec(b,c->key); serialize_rec(b,c->val); c = c->next; } } break; } default: failure("Cannot Serialize Abstract"); break; } b->nrec--; } static void serialize_fields_rec( value data, field id, void *b ) { write_int(b,(int)id); serialize_rec(b,data); } /**

Serialize

Serialization can be used in order to store permanantly some runtime value. Serialization of all values is possible, except Abstracts, with the special cases of ['int32] and ['hash] which are handled as specific cases.

Serialization of bytecode function is possible, but will result in a runtime exception when deserializing if the function offset in the bytecode has changed.

You can define the __serialize method of an object. When this method is found when serializing the object, it is called with no arguments and its return value will be serialized. The name of the module the method is declared in will also be serialized. When unserializing, the module is loaded and its __unserialize exported function is called with the value that was returned by __serialize.

**/ /** serialize : any -> string Serialize any value recursively **/ static value serialize( value o ) { sbuffer b; value v; char *s; strlist *l; b.olds = NULL; b.refs = NULL; b.nrefs = 0; b.cur = (unsigned char*)alloc_private(BUF_SIZE); b.size = BUF_SIZE; b.pos = 0; b.totlen = 0; b.nrec = 0; serialize_rec(&b,o); v = alloc_empty_string(b.pos + b.totlen); s = (char*)val_string(v); s += b.totlen; l = b.olds; memcpy(s,b.cur,b.pos); while( l != NULL ) { s -= l->slen; memcpy(s,l->str,l->slen); l = l->next; } return v; } static value unserialize_rec( sbuffer *b, value loader ) { switch( read_char(b) ) { case 'N': return val_null; case 'T': return val_true; case 'F': return val_false; case 'i': return alloc_int(read_int(b)); case 'I': return alloc_int32(read_int(b)); case 'f': { tfloat d; read_str(b,sizeof(tfloat),&d); return alloc_float(d); } case 's': { int l = read_int(b); value v; if( l < 0 || l > max_string_size ) ERROR(); v = alloc_empty_string(l); add_ref(b,v); read_str(b,l,(char*)val_string(v)); return v; } case 'o': { int f; value o = alloc_object(NULL); add_ref(b,o); while( (f = read_int(b)) != 0 ) { value fval = unserialize_rec(b,loader); alloc_field(o,(field)f,fval); } switch( read_char(b) ) { case 'p': { value v = unserialize_rec(b,loader); if( !val_is_object(v) ) ERROR(); ((vobject*)o)->proto = (vobject*)v; } break; case 'z': break; default: ERROR(); } return o; } case 'r': { int n = read_int(b); if( n < 0 || n >= b->nrefs ) ERROR(); return b->trefs[b->nrefs - n - 1]; } case 'a': { int i; int n = read_int(b); value o; value *t; if( n < 0 || n > max_array_size ) ERROR(); o = alloc_array(n); t = val_array_ptr(o); add_ref(b,o); for(i=0;it = f2->t; f->addr = f2->addr; f->module = f2->module; return (value)f; } case 'L': { vfunction *f = (vfunction*)alloc_function((void*)1,0,NULL); value mname; int pos; int nargs; value env; add_ref(b,(value)f); mname = unserialize_rec(b,loader); pos = read_int(b); nargs = read_int(b); env = unserialize_rec(b,loader); if( !val_is_array(env) ) ERROR(); { value exp = val_ocall2(loader,id_loadmodule,mname,loader); value mval; unsigned int i; int_val *mpos; neko_module *m; if( !val_is_object(exp) ) { buffer b = alloc_buffer("module "); val_buffer(b,mname); buffer_append(b," is not an object"); bfailure(b); } mval = val_field(exp,id_module); if( !val_is_kind(mval,neko_kind_module) ) { buffer b = alloc_buffer("module "); val_buffer(b,mname); buffer_append(b," has invalid type"); bfailure(b); } m = (neko_module*)val_data(mval); mpos = m->code + pos; for(i=0;inglobals;i++) { vfunction *g = (vfunction*)m->globals[i]; if( val_is_function(g) && g->addr == mpos && g->module == m && g->nargs == nargs ) { f->t = VAL_FUNCTION; f->env = env; f->addr = mpos; f->nargs = nargs; f->module = m; return (value)f; } } { buffer b = alloc_buffer("module "); val_buffer(b,mname); buffer_append(b," has been modified"); bfailure(b); } } return val_null; } case 'x': { value mname = unserialize_rec(b,loader); value data = unserialize_rec(b,loader); value exports = val_ocall2(loader,id_loadmodule,mname,loader); value s; if( !val_is_object(exports) ) { buffer b = alloc_buffer("module "); val_buffer(b,mname); buffer_append(b," is not an object"); bfailure(b); } s = val_field(exports,id_unserialize); if( !val_is_function(s) || (val_fun_nargs(s) != 1 && val_fun_nargs(s) != VAR_ARGS) ) { buffer b = alloc_buffer("module "); val_buffer(b,mname); buffer_append(b," has invalid __unserialize function"); } s = val_call1(s,data); add_ref(b,s); return s; } case 'h': { int i; vhash *h = (vhash*)alloc(sizeof(vhash)); h->ncells = read_int(b); h->nitems = read_int(b); h->cells = (hcell**)alloc(sizeof(hcell*)*h->ncells); for(i=0;incells;i++) h->cells[i] = NULL; for(i=0;initems;i++) { hcell **p; hcell *c = (hcell*)alloc(sizeof(hcell)); c->hkey = read_int(b); c->key = unserialize_rec(b,loader); c->val = unserialize_rec(b,loader); c->next = NULL; p = &h->cells[c->hkey % h->ncells]; while( *p != NULL ) p = &(*p)->next; *p = c; } return alloc_abstract(k_hash,h); } default: ERROR(); return val_null; } } /** unserialize : string -> #loader -> any Unserialize a stored value. Need a loader to look for modules if some bytecode functions have been serialized. **/ static value unserialize( value s, value loader ) { sbuffer b; val_check(s,string); b.cur = (unsigned char*)val_string(s); b.pos = 0; b.olds = NULL; b.trefs = NULL; b.tsize = 0; b.nrefs = 0; b.size = val_strlen(s); b.totlen = 0; return unserialize_rec(&b,loader); } DEFINE_PRIM(serialize,1); DEFINE_PRIM(unserialize,2); /* ************************************************************************ */ neko-2-2-0/libs/std/socket.c000066400000000000000000000771561321613172000156400ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef NEKO_WINDOWS # include # include # define FDSIZE(n) (sizeof(u_int) + (n) * sizeof(SOCKET)) # define SHUT_WR SD_SEND # define SHUT_RD SD_RECEIVE # define SHUT_RDWR SD_BOTH static bool init_done = false; static WSADATA init_data; #else # include # include # include # include # include # include # include # include # include # include # include # include typedef int SOCKET; # define closesocket close # define SOCKET_ERROR (-1) # define INVALID_SOCKET (-1) #endif #ifdef NEKO_LINUX # include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) # include # define HAS_EPOLL #endif #endif #ifndef HAS_EPOLL # define EPOLLIN 0x001 # define EPOLLOUT 0x004 #endif #if defined(NEKO_WINDOWS) || defined(NEKO_MAC) # define MSG_NOSIGNAL 0 #endif #define NRETRYS 20 typedef struct { SOCKET sock; char *buf; int size; int ret; } sock_tmp; typedef struct { int max; # ifdef NEKO_WINDOWS struct fd_set *fdr; struct fd_set *fdw; struct fd_set *outr; struct fd_set *outw; # else struct pollfd *fds; int rcount; int wcount; # endif value ridx; value widx; } polldata; typedef struct { int maxevents; value result; #ifndef HAS_EPOLL value read; value write; int rcount; int wcount; #else int epollfd; struct epoll_event *events; #endif } epolldata; DEFINE_KIND(k_socket); DEFINE_KIND(k_poll); DEFINE_KIND(k_epoll); #define val_sock(o) ((SOCKET)(int_val)val_data(o)) #define val_poll(o) ((polldata*)val_data(o)) #define val_epoll(o) ((epolldata*)val_data(o)) static field f_host; static field f_port; /**

Socket

TCP and UDP sockets

**/ static value block_error() { #ifdef NEKO_WINDOWS int err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAEALREADY || err == WSAETIMEDOUT ) #else if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY ) #endif val_throw(alloc_string("Blocking")); neko_error(); return val_true; } /** socket_init : void -> void Initialize the socket API. Must be called at least once per process before using any socket or host function. **/ static value socket_init() { #ifdef NEKO_WINDOWS if( !init_done ) { WSAStartup(MAKEWORD(2,0),&init_data); init_done = true; } #endif f_host = val_id("host"); f_port = val_id("port"); return val_true; } /** socket_new : udp:bool -> 'socket Create a new socket, TCP or UDP **/ static value socket_new( value udp ) { SOCKET s; val_check(udp,bool); if( val_bool(udp) ) s = socket(AF_INET,SOCK_DGRAM,0); else s = socket(AF_INET,SOCK_STREAM,0); if( s == INVALID_SOCKET ) neko_error(); # ifdef NEKO_MAC setsockopt(s,SOL_SOCKET,SO_NOSIGPIPE,NULL,0); # endif # ifdef NEKO_POSIX // we don't want sockets to be inherited in case of exec { int old = fcntl(s,F_GETFD,0); if( old >= 0 ) fcntl(s,F_SETFD,old|FD_CLOEXEC); } # endif return alloc_abstract(k_socket,(value)(int_val)s); } /** socket_close : 'socket -> void Close a socket. Any subsequent operation on this socket will fail **/ static value socket_close( value o ) { val_check_kind(o,k_socket); POSIX_LABEL(close_again); if( closesocket(val_sock(o)) ) { HANDLE_EINTR(close_again); } val_kind(o) = NULL; return val_true; } /** socket_send_char : 'socket -> int -> void Send a character over a connected socket. Must be in the range 0..255 **/ static value socket_send_char( value o, value v ) { int c; unsigned char cc; val_check_kind(o,k_socket); val_check(v,int); c = val_int(v); if( c < 0 || c > 255 ) neko_error(); cc = (unsigned char)c; POSIX_LABEL(send_char_again); if( send(val_sock(o),&cc,1,MSG_NOSIGNAL) == SOCKET_ERROR ) { HANDLE_EINTR(send_char_again); return block_error(); } return val_true; } /** socket_send : 'socket -> buf:string -> pos:int -> len:int -> int Send up to [len] bytes from [buf] starting at [pos] over a connected socket. Return the number of bytes sent. **/ static value socket_send( value o, value data, value pos, value len ) { int p,l,dlen; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = send(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); } static void tmp_recv( void *_t ) { sock_tmp *t = (sock_tmp*)_t; t->ret = recv(t->sock,t->buf,t->size,MSG_NOSIGNAL); } /** socket_recv : 'socket -> buf:string -> pos:int -> len:int -> int Read up to [len] bytes from [buf] starting at [pos] from a connected socket. Return the number of bytes readed. **/ static value socket_recv( value o, value data, value pos, value len ) { int p,l,dlen,ret; int retry = 0; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(recv_again); if( retry++ > NRETRYS ) { sock_tmp t; t.sock = val_sock(o); t.buf = val_string(data) + p; t.size = l; neko_thread_blocking(tmp_recv,&t); ret = t.ret; } else ret = recv(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } return alloc_int(ret); } /** socket_recv_char : 'socket -> int Read a single char from a connected socket. **/ static value socket_recv_char( value o ) { int ret; int retry = 0; unsigned char cc; val_check_kind(o,k_socket); POSIX_LABEL(recv_char_again); if( retry++ > NRETRYS ) { sock_tmp t; t.sock = val_sock(o); t.buf = (char*)&cc; t.size = 1; neko_thread_blocking(tmp_recv,&t); ret = t.ret; } else ret = recv(val_sock(o),&cc,1,MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_char_again); return block_error(); } if( ret == 0 ) neko_error(); return alloc_int(cc); } /** socket_write : 'socket -> string -> void Send the whole content of a string over a connected socket. **/ static value socket_write( value o, value data ) { const char *cdata; int datalen, slen; val_check_kind(o,k_socket); val_check(data,string); cdata = val_string(data); datalen = val_strlen(data); while( datalen > 0 ) { POSIX_LABEL(write_again); slen = send(val_sock(o),cdata,datalen,MSG_NOSIGNAL); if( slen == SOCKET_ERROR ) { HANDLE_EINTR(write_again); return block_error(); } cdata += slen; datalen -= slen; } return val_true; } /** socket_read : 'socket -> string Read the whole content of a the data available from a socket until the connection close. If the socket hasn't been close by the other side, the function might block. **/ static value socket_read( value o ) { buffer b; char buf[256]; int len; val_check_kind(o,k_socket); b = alloc_buffer(NULL); while( true ) { POSIX_LABEL(read_again); len = recv(val_sock(o),buf,256,MSG_NOSIGNAL); if( len == SOCKET_ERROR ) { HANDLE_EINTR(read_again); return block_error(); } if( len == 0 ) break; buffer_append_sub(b,buf,len); } return buffer_to_string(b); } /** host_resolve : string -> 'int32 Resolve the given host string into an IP address. **/ static value host_resolve( value host ) { unsigned int ip; val_check(host,string); ip = inet_addr(val_string(host)); if( ip == INADDR_NONE ) { struct hostent *h; # if defined(NEKO_WINDOWS) || defined(NEKO_MAC) || defined(NEKO_CYGWIN) h = gethostbyname(val_string(host)); # else struct hostent hbase; char buf[1024]; int errcode; gethostbyname_r(val_string(host),&hbase,buf,1024,&h,&errcode); # endif if( h == NULL ) neko_error(); ip = *((unsigned int*)h->h_addr); } return alloc_int32(ip); } /** host_to_string : 'int32 -> string Return a string representation of the IP address. **/ static value host_to_string( value ip ) { struct in_addr i; val_check(ip,int32); *(int*)&i = val_int32(ip); return alloc_string( inet_ntoa(i) ); } /** host_reverse : 'int32 -> string Reverse the DNS of the given IP address. **/ static value host_reverse( value host ) { struct hostent *h; unsigned int ip; val_check(host,int32); ip = val_int32(host); # if defined(NEKO_WINDOWS) || defined(NEKO_MAC) || defined(NEKO_CYGWIN) h = gethostbyaddr((char *)&ip,4,AF_INET); # else struct hostent htmp; int errcode; char buf[1024]; gethostbyaddr_r((char *)&ip,4,AF_INET,&htmp,buf,1024,&h,&errcode); # endif if( h == NULL ) neko_error(); return alloc_string( h->h_name ); } /** host_local : void -> string Return the local host name. **/ static value host_local() { char buf[256]; if( gethostname(buf,256) == SOCKET_ERROR ) neko_error(); return alloc_string(buf); } /** socket_connect : 'socket -> host:'int32 -> port:int -> void Connect the socket the given [host] and [port] **/ static value socket_connect( value o, value host, value port ) { struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(host,int32); val_check(port,int); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int32(host); if( connect(val_sock(o),(struct sockaddr*)&addr,sizeof(addr)) != 0 ) return block_error(); return val_true; } /** socket_listen : 'socket -> int -> void Listen for a number of connections **/ static value socket_listen( value o, value n ) { val_check_kind(o,k_socket); val_check(n,int); if( listen(val_sock(o),val_int(n)) == SOCKET_ERROR ) neko_error(); return val_true; } static fd_set INVALID; static fd_set *make_socket_array( value a, int len, fd_set *tmp, SOCKET *n ) { int i; SOCKET sock; if( val_is_null(a) ) return NULL; if( !val_is_array(a) ) return &INVALID; if( len > FD_SETSIZE ) val_throw(alloc_string("Too many sockets in select")); FD_ZERO(tmp); for(i=0;i *n ) *n = sock; FD_SET(sock,tmp); } return tmp; } static value make_array_result( value a, fd_set *tmp ) { value r; int i, len; int pos = 0; if( tmp == NULL ) return val_null; len = val_array_size(a); r = alloc_array(len); for(i=0;itv_usec = (int)((f - (int)f) * 1000000); t->tv_sec = (int)f; } /** socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array Perform the [select] operation. Timeout is in seconds or [null] if infinite **/ static value socket_select( value rs, value ws, value es, value timeout ) { struct timeval tval; struct timeval *tt; SOCKET n = 0; fd_set rx, wx, ex; fd_set *ra, *wa, *ea; value r; POSIX_LABEL(select_again); ra = make_socket_array(rs,val_array_size(rs),&rx,&n); wa = make_socket_array(ws,val_array_size(ws),&wx,&n); ea = make_socket_array(es,val_array_size(es),&ex,&n); if( ra == &INVALID || wa == &INVALID || ea == &INVALID ) neko_error(); if( val_is_null(timeout) ) tt = NULL; else { val_check(timeout,number); tt = &tval; init_timeval(val_number(timeout),tt); } if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); neko_error(); } r = alloc_array(3); val_array_ptr(r)[0] = make_array_result(rs,ra); val_array_ptr(r)[1] = make_array_result(ws,wa); val_array_ptr(r)[2] = make_array_result(es,ea); return r; } /** socket_bind : 'socket -> host : 'int32 -> port:int -> void Bind the socket for server usage on the given host and port **/ static value socket_bind( value o, value host, value port ) { int opt = 1; struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(host,int32); val_check(port,int); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int32(host); #ifndef NEKO_WINDOWS setsockopt(val_sock(o),SOL_SOCKET,SO_REUSEADDR,(char*)&opt,sizeof(opt)); #endif if( bind(val_sock(o),(struct sockaddr*)&addr,sizeof(addr)) == SOCKET_ERROR ) neko_error(); return val_true; } /** socket_accept : 'socket -> 'socket Accept an incoming connection request **/ static value socket_accept( value o ) { struct sockaddr_in addr; unsigned int addrlen = sizeof(addr); SOCKET s; val_check_kind(o,k_socket); POSIX_LABEL(accept_again); s = accept(val_sock(o),(struct sockaddr*)&addr,&addrlen); if( s == INVALID_SOCKET ) { HANDLE_EINTR(accept_again); return block_error(); } return alloc_abstract(k_socket,(value)(int_val)s); } /** socket_peer : 'socket -> #address Return the socket connected peer address composed of an (host,port) array **/ static value socket_peer( value o ) { struct sockaddr_in addr; unsigned int addrlen = sizeof(addr); value ret; val_check_kind(o,k_socket); if( getpeername(val_sock(o),(struct sockaddr*)&addr,&addrlen) == SOCKET_ERROR ) neko_error(); ret = alloc_array(2); val_array_ptr(ret)[0] = alloc_int32(*(int*)&addr.sin_addr); val_array_ptr(ret)[1] = alloc_int(ntohs(addr.sin_port)); return ret; } /** socket_host : 'socket -> #address Return the socket local address composed of an (host,port) array **/ static value socket_host( value o ) { struct sockaddr_in addr; unsigned int addrlen = sizeof(addr); value ret; val_check_kind(o,k_socket); if( getsockname(val_sock(o),(struct sockaddr*)&addr,&addrlen) == SOCKET_ERROR ) neko_error(); ret = alloc_array(2); val_array_ptr(ret)[0] = alloc_int32(*(int*)&addr.sin_addr); val_array_ptr(ret)[1] = alloc_int(ntohs(addr.sin_port)); return ret; } /** socket_set_timeout : 'socket -> timout:number? -> void Set the socket send and recv timeout in seconds to the given value (or null for blocking) **/ static value socket_set_timeout( value o, value t ) { #ifdef NEKO_WINDOWS int time; val_check_kind(o,k_socket); if( val_is_null(t) ) time = 0; else { val_check(t,number); time = (int)(val_number(t) * 1000); } #else struct timeval time; val_check_kind(o,k_socket); if( val_is_null(t) ) { time.tv_usec = 0; time.tv_sec = 0; } else { val_check(t,number); init_timeval(val_number(t),&time); } #endif if( setsockopt(val_sock(o),SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) neko_error(); if( setsockopt(val_sock(o),SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) neko_error(); return val_true; } /** socket_shutdown : 'socket -> read:bool -> write:bool -> void Prevent the socket from further reading or writing or both. **/ static value socket_shutdown( value o, value r, value w ) { val_check_kind(o,k_socket); val_check(r,bool); val_check(w,bool); if( !val_bool(r) && !val_bool(w) ) return val_true; if( shutdown(val_sock(o),val_bool(r)?(val_bool(w)?SHUT_RDWR:SHUT_RD):SHUT_WR) ) neko_error(); return val_true; } /** socket_set_blocking : 'socket -> bool -> void Turn on/off the socket blocking mode. **/ static value socket_set_blocking( value o, value b ) { val_check_kind(o,k_socket); val_check(b,bool); #ifdef NEKO_WINDOWS { unsigned long arg = val_bool(b)?0:1; if( ioctlsocket(val_sock(o),FIONBIO,&arg) != 0 ) neko_error(); } #else { int rights = fcntl(val_sock(o),F_GETFL); if( rights == -1 ) neko_error(); if( val_bool(b) ) rights &= ~O_NONBLOCK; else rights |= O_NONBLOCK; if( fcntl(val_sock(o),F_SETFL,rights) == -1 ) neko_error(); } #endif return val_true; } /** socket_poll_alloc : int -> 'poll Allocate memory to perform polling on a given number of sockets **/ static value socket_poll_alloc( value nsocks ) { polldata *p; int i; val_check(nsocks,int); p = (polldata*)alloc(sizeof(polldata)); p->max = val_int(nsocks); if( p->max < 0 || p->max > 1000000 ) neko_error(); # ifdef NEKO_WINDOWS { p->fdr = (fd_set*)alloc_private(FDSIZE(p->max)); p->fdw = (fd_set*)alloc_private(FDSIZE(p->max)); p->outr = (fd_set*)alloc_private(FDSIZE(p->max)); p->outw = (fd_set*)alloc_private(FDSIZE(p->max)); p->fdr->fd_count = 0; p->fdw->fd_count = 0; } # else p->fds = (struct pollfd*)alloc_private(sizeof(struct pollfd) * p->max); p->rcount = 0; p->wcount = 0; # endif p->ridx = alloc_array(p->max+1); p->widx = alloc_array(p->max+1); for(i=0;i<=p->max;i++) { val_array_ptr(p->ridx)[i] = alloc_int(-1); val_array_ptr(p->widx)[i] = alloc_int(-1); } return alloc_abstract(k_poll, p); } /** socket_poll_prepare : 'poll -> read:'socket array -> write:'socket array -> int array array Prepare a poll for scanning events on sets of sockets. **/ static value socket_poll_prepare( value pdata, value rsocks, value wsocks ) { polldata *p; int i,len; val_check(rsocks,array); val_check(wsocks,array); val_check_kind(pdata,k_poll); p = val_poll(pdata); len = val_array_size(rsocks); if( len + val_array_size(wsocks) > p->max ) val_throw(alloc_string("Too many sockets in poll")); # ifdef NEKO_WINDOWS for(i=0;ifdr->fd_array[i] = val_sock(s); } p->fdr->fd_count = len; len = val_array_size(wsocks); for(i=0;ifdw->fd_array[i] = val_sock(s); } p->fdw->fd_count = len; # else for(i=0;ifds[i].fd = val_sock(s); p->fds[i].events = POLLIN; p->fds[i].revents = 0; } p->rcount = len; len = val_array_size(wsocks); for(i=0;ircount; value s = val_array_ptr(wsocks)[i]; val_check_kind(s,k_socket); p->fds[k].fd = val_sock(s); p->fds[k].events = POLLOUT; p->fds[k].revents = 0; } p->wcount = len; # endif { value a = alloc_array(2); val_array_ptr(a)[0] = p->ridx; val_array_ptr(a)[1] = p->widx; return a; } } /** socket_poll_events : 'poll -> timeout:float -> void Update the read/write flags arrays that were created with [socket_poll_prepare]. **/ static value socket_poll_events( value pdata, value timeout ) { polldata *p; # ifdef NEKO_WINDOWS unsigned int i; int k = 0; struct timeval t; val_check_kind(pdata,k_poll); p = val_poll(pdata); memcpy(p->outr,p->fdr,FDSIZE(p->fdr->fd_count)); memcpy(p->outw,p->fdw,FDSIZE(p->fdw->fd_count)); val_check(timeout,number); init_timeval(val_number(timeout),&t); if( p->fdr->fd_count + p->fdw->fd_count != 0 && select(0,p->outr,p->outw,NULL,&t) == SOCKET_ERROR ) neko_error(); k = 0; for(i=0;ifdr->fd_count;i++) if( FD_ISSET(p->fdr->fd_array[i],p->outr) ) val_array_ptr(p->ridx)[k++] = alloc_int(i); val_array_ptr(p->ridx)[k] = alloc_int(-1); k = 0; for(i=0;ifdw->fd_count;i++) if( FD_ISSET(p->fdw->fd_array[i],p->outw) ) val_array_ptr(p->widx)[k++] = alloc_int(i); val_array_ptr(p->widx)[k] = alloc_int(-1); #else int i,k; int tot; val_check_kind(pdata,k_poll); val_check(timeout,number); p = val_poll(pdata); tot = p->rcount + p->wcount; POSIX_LABEL(poll_events_again); if( poll(p->fds,tot,(int)(val_number(timeout) * 1000)) < 0 ) { HANDLE_EINTR(poll_events_again); neko_error(); } k = 0; for(i=0;ircount;i++) if( p->fds[i].revents & (POLLIN|POLLHUP) ) val_array_ptr(p->ridx)[k++] = alloc_int(i); val_array_ptr(p->ridx)[k] = alloc_int(-1); k = 0; for(;ifds[i].revents & (POLLOUT|POLLHUP) ) val_array_ptr(p->widx)[k++] = alloc_int(i - p->rcount); val_array_ptr(p->widx)[k] = alloc_int(-1); #endif return val_null; } /** socket_poll : 'socket array -> 'poll -> timeout:float -> 'socket array Perform a polling for data available over a given set of sockets. This is similar to [socket_select] except that [socket_select] is limited to a given number of simultaneous sockets to check. **/ static value socket_poll( value socks, value pdata, value timeout ) { polldata *p; value a; int i, rcount = 0; if( socket_poll_prepare(pdata,socks,alloc_array(0)) == NULL ) neko_error(); if( socket_poll_events(pdata,timeout) == NULL ) neko_error(); p = val_poll(pdata); while( val_array_ptr(p->ridx)[rcount] != alloc_int(-1) ) rcount++; a = alloc_array(rcount); for(i=0;iridx)[i])]; return a; } /** socket_set_fast_send : 'socket -> bool -> void Disable or enable to TCP_NODELAY flag for the socket **/ static value socket_set_fast_send( value s, value f ) { int fast; val_check_kind(s,k_socket); val_check(f,bool); fast = val_bool(f); if( setsockopt(val_sock(s),IPPROTO_TCP,TCP_NODELAY,(char*)&fast,sizeof(fast)) ) neko_error(); return val_null; } /** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int Send data from an unconnected UDP socket to the given address. **/ static value socket_send_to( value o, value data, value pos, value len, value vaddr ) { int p,l,dlen; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int32); val_check(port,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int32(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = sendto(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); } /** socket_recv_from : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int Read data from an unconnected UDP socket, store the address from which we received data in addr. **/ static value socket_recv_from( value o, value data, value pos, value len, value addr ) { int p,l,dlen,ret; int retry = 0; struct sockaddr_in saddr; int slen = sizeof(saddr); val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); val_check(addr,object); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(recv_from_again); if( retry++ > NRETRYS ) { sock_tmp t; t.sock = val_sock(o); t.buf = val_string(data) + p; t.size = l; neko_thread_blocking(tmp_recv,&t); ret = t.ret; } else ret = recvfrom(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_from_again); #ifdef NEKO_WINDOWS if( WSAGetLastError() == WSAECONNRESET ) ret = 0; else #endif return block_error(); } alloc_field(addr,f_host,alloc_int32(*(int*)&saddr.sin_addr)); alloc_field(addr,f_port,alloc_int(ntohs(saddr.sin_port))); return alloc_int(ret); } /** socket_set_keepalive : 'socket -> bool -> time:int? -> interval:int? -> void Enable or disable TCP_KEEPALIVE flag for the socket **/ static value socket_set_keepalive( value o, value b, value time, value interval ) { int val; SOCKET s; val_check_kind(o,k_socket); val_check(b,bool); if( !val_is_null(time) || !val_is_null(interval) ){ val_check(time,int); val_check(interval,int); } s = val_sock(o); if( !val_bool(b) ) { val = 0; if( setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&val, sizeof(val)) != 0 ) neko_error(); } else { val = 1; if( setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&val, sizeof(val)) != 0 ) neko_error(); if( !val_is_null(time) && !val_is_null(interval) ) { # if defined(NEKO_WINDOWS) u_long params[3] = { 1, (unsigned long)val_int(time)*1000, (unsigned long)val_int(interval)*1000 }; if( WSAIoctl(s, SIO_KEEPALIVE_VALS, ¶ms, sizeof(params), NULL, 0, &val, NULL, NULL) != 0 ) neko_error(); # else # if defined(TCP_KEEPIDLE) val = val_int(time); if( setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&val, sizeof(val)) != 0 ) neko_error(); # elif defined(TCP_KEEPALIVE) val = val_int(time); if( setsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE, (void *)&val, sizeof(val)) != 0 ) neko_error(); # endif # if defined(TCP_KEEPINTVL) val = val_int(interval); if( setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&val, sizeof(val)) != 0 ) neko_error(); # endif # endif } } return val_null; } /** socket_epoll_alloc : void -> 'epoll Allocate memory for edge/level-triggered polling (epoll). On Linux, this will use epoll; on other systems, this will fall back to select. **/ static value socket_epoll_alloc(value maxevents) { epolldata *ep; val_check(maxevents,int); ep = (epolldata*)alloc(sizeof(epolldata)); ep->maxevents = val_int(maxevents); ep->result = alloc_array(val_int(maxevents)); #ifndef HAS_EPOLL ep->read = alloc_array(FD_SETSIZE); ep->write = alloc_array(FD_SETSIZE); ep->rcount = 0; ep->wcount = 0; #else ep->epollfd = epoll_create1(0); ep->events = (struct epoll_event*)alloc(sizeof(struct epoll_event) * val_int(maxevents)); #endif return alloc_abstract(k_epoll, ep); } /** socket_epoll_register : 'epoll -> 'socket -> int Register a socket with an epoll instance to be notified of events. Returns the socket's fd. **/ static value socket_epoll_register(value e, value s, value events) { SOCKET sock; int event_types; epolldata *ep; val_check_kind(e,k_epoll); val_check_kind(s,k_socket); val_check(events,int); sock = val_sock(s); event_types = val_int(events); ep = val_epoll(e); #ifndef HAS_EPOLL if (sock >= FD_SETSIZE) val_throw(alloc_string("Can't register file descriptor >= FD_SETSIZE")); if (event_types & EPOLLIN) { if (ep->rcount >= FD_SETSIZE) val_throw(alloc_string("Too many sockets (on non-Linux platforms, 'epoll' uses select)")); val_array_ptr(ep->read)[ep->rcount++] = s; } if (event_types & EPOLLOUT) { if (ep->wcount >= FD_SETSIZE) val_throw(alloc_string("Too many sockets (on non-Linux platforms, 'epoll' uses select)")); val_array_ptr(ep->write)[ep->wcount++] = s; } #else struct epoll_event ev; ev.events = event_types; ev.data.fd = sock; int ret = epoll_ctl(ep->epollfd, EPOLL_CTL_ADD, sock, &ev); if (ret == -1) val_throw(alloc_int(errno)); #endif return alloc_int(sock); } /** socket_epoll_unregister : 'epoll -> 'socket -> int Unegister a socket with an epoll instance. Returns the socket's fd. **/ static value socket_epoll_unregister(value e, value s) { SOCKET sock; epolldata *ep; # ifndef HAS_EPOLL int i, j; # endif val_check_kind(e,k_epoll); val_check_kind(s,k_socket); sock = val_sock(s); ep = val_epoll(e); #ifndef HAS_EPOLL for (i = 0; i < ep->rcount; i++) { if (val_array_ptr(ep->read)[i] == s) { for (j = i+1; j < ep->rcount; j++) { val_array_ptr(ep->read)[j] = val_array_ptr(ep->read)[j-1]; } val_array_ptr(ep->read)[--ep->rcount] = NULL; --i; } } for (i = 0; i < ep->wcount; i++) { if (val_array_ptr(ep->write)[i] == s) { for (j = i+1; j < ep->wcount; j++) { val_array_ptr(ep->write)[j] = val_array_ptr(ep->write)[j-1]; } val_array_ptr(ep->write)[--ep->wcount] = NULL; --i; } } #else struct epoll_event ev; int ret = epoll_ctl(ep->epollfd, EPOLL_CTL_DEL, sock, &ev); if (ret == -1) return alloc_int(ret); else #endif return alloc_int(sock); } /** socket_epoll_wait : 'epoll -> int -> float -> int array Wait and return a list of socket fds with events. **/ static value socket_epoll_wait(value e, value timeout) { epolldata *ep; #ifndef HAS_EPOLL struct timeval t; SOCKET n = 0; bool indefinite; fd_set rx, wx; fd_set *ra, *wa; int i; int pos = 0; val_check_kind(e,k_epoll); ep = val_epoll(e); POSIX_LABEL(select_again); ra = ep->rcount == 0 ? NULL : make_socket_array(ep->read, ep->rcount, &rx, &n); wa = ep->wcount == 0 ? NULL : make_socket_array(ep->write, ep->wcount, &wx, &n); indefinite = val_is_null(timeout); if (!indefinite) { val_check(timeout,number); init_timeval(val_number(timeout),&t); } if( select((int)(n+1),ra,wa,NULL,indefinite ? NULL : &t) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); val_throw(alloc_int(errno)); } if (ra != NULL) { for (i=0; i < ep->rcount && pos < ep->maxevents; i++) { value s = val_array_ptr(ep->read)[i]; if (FD_ISSET(val_sock(s),ra)) val_array_ptr(ep->result)[pos++] = alloc_int(val_sock(s)); } } if (wa != NULL) { for (i=0; i < ep->wcount && pos < ep->maxevents; i++) { value s = val_array_ptr(ep->write)[i]; if (FD_ISSET(val_sock(s),wa)) val_array_ptr(ep->result)[pos++] = alloc_int(val_sock(s)); } } val_set_size(ep->result,pos); return ep->result; #else int t; val_check_kind(e,k_epoll); ep = val_epoll(e); if (val_is_null(timeout)) t = -1; else { val_check(timeout,number); t = (int)(val_number(timeout)) * 1000; } int ret = epoll_wait(ep->epollfd, ep->events, ep->maxevents, t); if (ret == -1) val_throw(alloc_int(errno)); val_set_size(ep->result, ret); int i; for (i = 0; i < ret; i++) { val_array_ptr(ep->result)[i] = alloc_int(ep->events[i].data.fd); } return ep->result; #endif } DEFINE_PRIM(socket_init,0); DEFINE_PRIM(socket_new,1); DEFINE_PRIM(socket_send,4); DEFINE_PRIM(socket_send_char,2); DEFINE_PRIM(socket_recv,4); DEFINE_PRIM(socket_recv_char,1); DEFINE_PRIM(socket_write,2); DEFINE_PRIM(socket_read,1); DEFINE_PRIM(socket_close,1); DEFINE_PRIM(socket_connect,3); DEFINE_PRIM(socket_listen,2); DEFINE_PRIM(socket_select,4); DEFINE_PRIM(socket_bind,3); DEFINE_PRIM(socket_accept,1); DEFINE_PRIM(socket_peer,1); DEFINE_PRIM(socket_host,1); DEFINE_PRIM(socket_set_timeout,2); DEFINE_PRIM(socket_shutdown,3); DEFINE_PRIM(socket_set_blocking,2); DEFINE_PRIM(socket_set_fast_send,2); DEFINE_PRIM(socket_send_to,5); DEFINE_PRIM(socket_recv_from,5); DEFINE_PRIM(socket_set_keepalive,4); DEFINE_PRIM(socket_poll_alloc,1); DEFINE_PRIM(socket_poll,3); DEFINE_PRIM(socket_poll_prepare,3); DEFINE_PRIM(socket_poll_events,2); DEFINE_PRIM(socket_epoll_alloc,1); DEFINE_PRIM(socket_epoll_register,3); DEFINE_PRIM(socket_epoll_unregister,2); DEFINE_PRIM(socket_epoll_wait,2); DEFINE_PRIM(host_local,0); DEFINE_PRIM(host_resolve,1); DEFINE_PRIM(host_to_string,1); DEFINE_PRIM(host_reverse,1); /* ************************************************************************ */ neko-2-2-0/libs/std/string.c000066400000000000000000000234751321613172000156510ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include /**

String Functions

Some useful functions dealing with string manipulation.

**/ /** string_split : s:string -> sep:string -> string list split the string [s] using separator [sep] **/ static value string_split( value o, value s ) { value l, first; int ilen; int slen; int start = 0; int pos; val_check(s,string); val_check(o,string); ilen = val_strlen(o); slen = val_strlen(s); l = NULL; first = NULL; for(pos=slen?0:1;pos<=ilen-slen;pos++) if( memcmp(val_string(o)+pos,val_string(s),slen) == 0 ) { value ss = copy_string(val_string(o)+start,pos-start); value l2 = alloc_array(2); val_array_ptr(l2)[0] = ss; val_array_ptr(l2)[1] = val_null; if( first == NULL ) first = l2; else val_array_ptr(l)[1] = l2; l = l2; start = pos + slen; if( slen ) pos = start - 1; } if( ilen > 0 && slen ) { value ss = start ? copy_string(val_string(o)+start,ilen-start) : o; value l2 = alloc_array(2); val_array_ptr(l2)[0] = ss; val_array_ptr(l2)[1] = val_null; if( first == NULL ) first = l2; else val_array_ptr(l)[1] = l2; } return (first == NULL)?val_null:first; } #define HEX 1 #define HEX_SMALL 2 /** sprintf : fmt:string -> params:(any | array) -> string Format a string. If only one parameter is needed then it can be directly passed, either the parameters need to be stored in an array. The following formats are accepted (with corresponding types) :
  • [%s] : string
  • [%d] [%x] [%X] : int
  • [%c] : int in the 0..255 range
  • [%b] : bool
  • [%f] : float
**/ static value neko_sprintf( value fmt, value params ) { char *last, *cur, *end; int count = 0; buffer b; val_check(fmt,string); b = alloc_buffer(NULL); last = val_string(fmt); cur = last; end = cur + val_strlen(fmt); while( cur != end ) { if( *cur == '%' ) { int width = 0, prec = 0, flags = 0; buffer_append_sub(b,last,cur - last); cur++; while( *cur >= '0' && *cur <= '9' ) { width = width * 10 + (*cur - '0'); cur++; } if( *cur == '.' ) { cur++; while( *cur >= '0' && *cur <= '9' ) { prec = prec * 10 + (*cur - '0'); cur++; } } if( *cur == '%' ) { buffer_append_sub(b,"%",1); cur++; } else { value param; if( count == 0 && !val_is_array(params) ) { // first ? param = params; count++; } else if( !val_is_array(params) || val_array_size(params) <= count ) neko_error(); else param = val_array_ptr(params)[count++]; switch( *cur ) { case 'c': { int c; char cc; val_check(param,int); c = val_int(param); if( c < 0 || c > 255 ) neko_error(); cc = (char)c; buffer_append_sub(b,&cc,1); } break; case 'x': flags |= HEX_SMALL; case 'X': flags |= HEX; case 'd': { char tmp[10]; int sign = 0; int size = 0; int tsize; int n; val_check(param,int); n = val_int(param); if( !(flags & HEX) && n < 0 ) { sign++; prec--; n = -n; } else if( n == 0 ) tmp[9-size++] = '0'; if( flags & HEX ) { unsigned int nn = (unsigned int)n; while( nn > 0 ) { int k = nn&15; if( k < 10 ) tmp[9-size++] = k + '0'; else tmp[9-size++] = (k - 10) + ((flags & HEX_SMALL)?'a':'A'); nn = nn >> 4; } } else { while( n > 0 ) { tmp[9-size++] = (n % 10) + '0'; n = n / 10; } } tsize = (size > prec)?size:prec + sign; while( width > tsize ) { width--; buffer_append_sub(b," ",1); } if( sign ) buffer_append_sub(b,"-",1); while( prec > size ) { prec--; buffer_append_sub(b,"0",1); } buffer_append_sub(b,tmp+10-size,size); } break; case 'f': { val_check(param,float); val_buffer(b,param); } break; case 's': { int size; int tsize; val_check(param,string); size = val_strlen(param); tsize = (size > prec)?size:prec; while( width > tsize ) { width--; buffer_append_sub(b," ",1); } while( prec > size ) { prec--; buffer_append_sub(b," ",1); } buffer_append_sub(b,val_string(param),size); } break; case 'b': { val_check(param,bool); buffer_append_sub(b,val_bool(param)?"true":"false",val_bool(param)?4:5); } break; default: neko_error(); break; } } cur++; last = cur; } else cur++; } buffer_append_sub(b,last,cur - last); return buffer_to_string(b); } /** url_decode : string -> string Decode an url using escaped format **/ static value url_decode( value v ) { val_check(v,string); { int pin = 0; int pout = 0; const char *in = val_string(v); int len = val_strlen(v); value v2 = alloc_empty_string(len); char *out = (char*)val_string(v2); while( len-- > 0 ) { char c = in[pin++]; if( c == '+' ) c = ' '; else if( c == '%' ) { int p1, p2; if( len < 2 ) break; p1 = in[pin++]; p2 = in[pin++]; len -= 2; if( p1 >= '0' && p1 <= '9' ) p1 -= '0'; else if( p1 >= 'a' && p1 <= 'f' ) p1 -= 'a' - 10; else if( p1 >= 'A' && p1 <= 'F' ) p1 -= 'A' - 10; else continue; if( p2 >= '0' && p2 <= '9' ) p2 -= '0'; else if( p2 >= 'a' && p2 <= 'f' ) p2 -= 'a' - 10; else if( p2 >= 'A' && p2 <= 'F' ) p2 -= 'A' - 10; else continue; c = (char)((unsigned char)((p1 << 4) + p2)); } out[pout++] = c; } out[pout] = 0; val_set_size(v2,pout); return v2; } } /** url_encode : string -> string Encode an url using escaped format **/ static value url_encode( value v ) { val_check(v,string); { int pin = 0; int pout = 0; const unsigned char *in = (const unsigned char*)val_string(v); static const char *hex = "0123456789ABCDEF"; int len = val_strlen(v); value v2 = alloc_empty_string(len * 3); unsigned char *out = (unsigned char*)val_string(v2); while( len-- > 0 ) { unsigned char c = in[pin++]; if( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '.' ) out[pout++] = c; else { out[pout++] = '%'; out[pout++] = hex[c >> 4]; out[pout++] = hex[c & 0xF]; } } out[pout] = 0; val_set_size(v2,pout); return v2; } } /** base_encode : s:string -> base:string -> string Encode a string using the specified base. The base length must be a power of two. **/ static value base_encode( value s, value base ) { int nbits; int len; int size; int mask; unsigned int buf; int curbits; value out; unsigned char *cin, *cout, *chars; val_check(s,string); val_check(base,string); len = val_strlen(base); cin = (unsigned char *)val_string(s); chars = (unsigned char *)val_string(base); nbits = 1; while( len > 1 << nbits ) nbits++; if( nbits > 8 || len != 1 << nbits ) neko_error(); size = (val_strlen(s) * 8 + nbits - 1) / nbits; out = alloc_empty_string(size); cout = (unsigned char *)val_string(out); buf = 0; curbits = 0; mask = ((1 << nbits) - 1); while( size-- > 0 ) { while( curbits < nbits ) { curbits += 8; buf <<= 8; buf |= *cin++; } curbits -= nbits; *cout++ = chars[(buf >> curbits) & mask]; } return out; } /** base_decode : s:string -> base:string -> string Decode a string encode in the specified base. The base length must be a power of two. **/ static value base_decode( value s, value base ) { int nbits; int len; int size; unsigned int buf; int curbits; value out; int i; int tbl[256]; unsigned char *cin, *cout, *chars; val_check(s,string); val_check(base,string); len = val_strlen(base); cin = (unsigned char *)val_string(s); chars = (unsigned char *)val_string(base); nbits = 1; while( len > 1 << nbits ) nbits++; if( nbits > 8 || len != 1 << nbits ) neko_error(); for(i=0;i<256;i++) tbl[i] = -1; for(i=0;i 0 ) { while( curbits < 8 ) { curbits += nbits; buf <<= nbits; i = tbl[*cin++]; if( i == -1 ) neko_error(); buf |= i; } curbits -= 8; *cout++ = (buf >> curbits) & 0xFF; } return out; } #define neko_sprintf__2 sprintf__2 DEFINE_PRIM(neko_sprintf,2); DEFINE_PRIM(string_split,2); DEFINE_PRIM(url_decode,1); DEFINE_PRIM(url_encode,1); DEFINE_PRIM(base_encode,2); DEFINE_PRIM(base_decode,2); /* ************************************************************************ */ neko-2-2-0/libs/std/sys.c000066400000000000000000000403421321613172000151510ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #ifdef NEKO_WINDOWS # include # include # include #else # include # include # include # include # include # include # include # include #ifdef NEKO_XLOCALE_H # include #else # include #endif #endif #ifdef NEKO_MAC # include # include # include #endif #ifndef CLK_TCK # define CLK_TCK 100 #endif /**

System

Interactions with the operating system.

**/ /** get_env : string -> string? Get some environment variable if exists **/ static value get_env( value v ) { char *s; val_check(v,string); s = getenv(val_string(v)); if( s == NULL ) return val_null; return alloc_string(s); } /** put_env : var:string -> val:string -> void Set some environment variable value **/ static value put_env( value e, value v ) { #ifdef NEKO_WINDOWS buffer b; val_check(e,string); val_check(v,string); b = alloc_buffer(NULL); val_buffer(b,e); buffer_append_sub(b,"=",1); val_buffer(b,v); if( putenv(val_string(buffer_to_string(b))) != 0 ) neko_error(); #else val_check(e,string); val_check(v,string); if( setenv(val_string(e),val_string(v),1) != 0 ) neko_error(); #endif return val_true; } /** sys_sleep : number -> void Sleep a given number of seconds **/ static value sys_sleep( value f ) { val_check(f,number); #ifdef NEKO_WINDOWS Sleep((DWORD)(val_number(f) * 1000)); #else { struct timespec t; struct timespec tmp; t.tv_sec = (int)val_number(f); t.tv_nsec = (int)((val_number(f) - t.tv_sec) * 1e9); while( nanosleep(&t,&tmp) == -1 ) { if( errno != EINTR ) neko_error(); t = tmp; } } #endif return val_true; } /** set_time_locale : string -> bool Set the locale for LC_TIME, returns true on success **/ static value set_time_locale( value l ) { #ifdef NEKO_POSIX locale_t lc, old; val_check(l,string); lc = newlocale(LC_TIME_MASK,val_string(l),NULL); if( lc == NULL ) return val_false; old = uselocale(lc); if( old == NULL ) { freelocale(lc); return val_false; } if( old != LC_GLOBAL_LOCALE ) freelocale(old); return val_true; #else val_check(l,string); return alloc_bool(setlocale(LC_TIME,val_string(l)) != NULL); #endif } /** get_cwd : void -> string Return current working directory **/ static value get_cwd() { char buf[256]; int l; if( getcwd(buf,256) == NULL ) neko_error(); l = (int)strlen(buf); if( buf[l-1] != '/' && buf[l-1] != '\\' ) { buf[l] = '/'; buf[l+1] = 0; } return alloc_string(buf); } /** set_cwd : string -> void Set current working directory **/ static value set_cwd( value d ) { val_check(d,string); if( chdir(val_string(d)) ) neko_error(); return val_true; } /** sys_string : void -> string Return the local system string. The current value are possible :
  • [Windows]
  • [Linux]
  • [BSD]
  • [Mac]
**/ static value sys_string() { #if defined(NEKO_WINDOWS) || defined(NEKO_CYGWIN) return alloc_string("Windows"); #elif defined(NEKO_GNUKBSD) return alloc_string("GNU/kFreeBSD"); #elif defined(NEKO_LINUX) return alloc_string("Linux"); #elif defined(NEKO_BSD) return alloc_string("BSD"); #elif defined(NEKO_HURD) return alloc_string("GNU/Hurd"); #elif defined(NEKO_MAC) return alloc_string("Mac"); #else #error Unknow system string #endif } /** sys_is64 : void -> bool Returns true if we are on a 64-bit system **/ static value sys_is64() { #ifdef NEKO_64BITS return val_true; #else return val_false; #endif } /** sys_command : string -> int Run the shell command and return exit code **/ static value sys_command( value cmd ) { val_check(cmd,string); if( val_strlen(cmd) == 0 ) return alloc_int(-1); #ifdef NEKO_WINDOWS return alloc_int( system(val_string(cmd)) ); #else int status = system(val_string(cmd)); return alloc_int( WEXITSTATUS(status) | (WTERMSIG(status) << 8) ); #endif } /** sys_exit : int -> void Exit with the given errorcode. Never returns. **/ static value sys_exit( value ecode ) { val_check(ecode,int); exit(val_int(ecode)); return val_true; } /** sys_exists : string -> bool Returns true if the file or directory exists. **/ static value sys_exists( value path ) { struct stat st; val_check(path,string); return alloc_bool(stat(val_string(path),&st) == 0); } /** file_exists : string -> bool Deprecated : use sys_exists instead. **/ static value file_exists( value path ) { return sys_exists(path); } /** file_delete : string -> void Delete the file. Exception on error. **/ static value file_delete( value path ) { val_check(path,string); if( unlink(val_string(path)) != 0 ) neko_error(); return val_true; } /** sys_rename : from:string -> to:string -> void Rename the file or directory. Exception on error. **/ static value sys_rename( value path, value newname ) { val_check(path,string); val_check(newname,string); if( rename(val_string(path),val_string(newname)) != 0 ) neko_error(); return val_true; } #define STATF(f) alloc_field(o,val_id(#f),alloc_int(s.st_##f)) #define STATF32(f) alloc_field(o,val_id(#f),alloc_int32((int)s.st_##f)) /** sys_stat : string -> { gid => int, uid => int, atime => 'int32, mtime => 'int32, ctime => 'int32, dev => int, ino => int, nlink => int, rdev => int, mode => int, size => int } Run the [stat] command on the given file or directory. **/ static value sys_stat( value path ) { struct stat s; value o; val_check(path,string); if( stat(val_string(path),&s) != 0 ) neko_error(); o = alloc_object(NULL); STATF(gid); STATF(uid); STATF32(atime); STATF32(mtime); STATF32(ctime); STATF(dev); STATF(ino); STATF(mode); STATF(nlink); STATF(rdev); STATF(size); STATF(mode); return o; } /** sys_file_type : string -> string Return the type of the file. The current values are possible :
  • [file]
  • [dir]
  • [symlink]
  • [sock]
  • [char]
  • [block]
  • [fifo]
**/ static value sys_file_type( value path ) { struct stat s; val_check(path,string); if( stat(val_string(path),&s) != 0 ) neko_error(); if( s.st_mode & S_IFREG ) return alloc_string("file"); if( s.st_mode & S_IFDIR ) return alloc_string("dir"); if( s.st_mode & S_IFCHR ) return alloc_string("char"); #ifndef NEKO_WINDOWS if( s.st_mode & S_IFLNK ) return alloc_string("symlink"); if( s.st_mode & S_IFBLK ) return alloc_string("block"); if( s.st_mode & S_IFIFO ) return alloc_string("fifo"); if( s.st_mode & S_IFSOCK ) return alloc_string("sock"); #endif neko_error(); } /** sys_create_dir : string -> mode:int -> void Create a directory with the specified rights **/ static value sys_create_dir( value path, value mode ) { val_check(path,string); val_check(mode,int); #ifdef NEKO_WINDOWS if( mkdir(val_string(path)) != 0 ) #else if( mkdir(val_string(path),val_int(mode)) != 0 ) #endif neko_error(); return val_true; } /** sys_remove_dir : string -> void Remove a directory. Exception on error **/ static value sys_remove_dir( value path ) { val_check(path,string); if( rmdir(val_string(path)) != 0 ) neko_error(); return val_true; } /** sys_time : void -> float Return an accurate local time stamp in seconds since Jan 1 1970 **/ static value sys_time() { #ifdef NEKO_WINDOWS #define EPOCH_DIFF (134774*24*60*60.0) SYSTEMTIME t; FILETIME ft; ULARGE_INTEGER ui; GetSystemTime(&t); if( !SystemTimeToFileTime(&t,&ft) ) neko_error(); ui.LowPart = ft.dwLowDateTime; ui.HighPart = ft.dwHighDateTime; return alloc_float( ((tfloat)ui.QuadPart) / 10000000.0 - EPOCH_DIFF ); #else struct timeval tv; if( gettimeofday(&tv,NULL) != 0 ) neko_error(); return alloc_float( tv.tv_sec + ((tfloat)tv.tv_usec) / 1000000.0 ); #endif } /** sys_cpu_time : void -> float Return the most accurate CPU time spent since the process started (in seconds) **/ static value sys_cpu_time() { #ifdef NEKO_WINDOWS FILETIME unused; FILETIME stime; FILETIME utime; if( !GetProcessTimes(GetCurrentProcess(),&unused,&unused,&stime,&utime) ) neko_error(); return alloc_float( ((tfloat)(utime.dwHighDateTime+stime.dwHighDateTime)) * 65.536 * 6.5536 + (((tfloat)utime.dwLowDateTime + (tfloat)stime.dwLowDateTime) / 10000000) ); #else struct tms t; times(&t); return alloc_float( ((tfloat)(t.tms_utime + t.tms_stime)) / CLK_TCK ); #endif } /** sys_thread_cpu_time : void -> float Return the most accurate CPU time spent in user mode in the current thread (in seconds) **/ static value sys_thread_cpu_time() { #if defined(NEKO_WINDOWS) FILETIME unused; FILETIME utime; if( !GetThreadTimes(GetCurrentThread(),&unused,&unused,&unused,&utime) ) neko_error(); return alloc_float( ((tfloat)utime.dwHighDateTime) * 65.536 * 6.5536 + (((tfloat)utime.dwLowDateTime) / 10000000) ); #elif defined(NEKO_MAC) val_throw(alloc_string("sys_thread_cpu_time not implmented on OSX")); return val_null; #else struct timespec t; if( clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t) ) neko_error(); return alloc_float( t.tv_sec + t.tv_nsec * 1e-9 ); #endif } /** sys_read_dir : string -> string list Return the content of a directory **/ static value sys_read_dir( value path ) { value h = val_null; value cur = NULL, tmp; #ifdef NEKO_WINDOWS WIN32_FIND_DATA d; HANDLE handle; buffer b; int len; val_check(path,string); len = val_strlen(path); b = alloc_buffer(NULL); val_buffer(b,path); if( len && val_string(path)[len-1] != '/' && val_string(path)[len-1] != '\\' ) buffer_append(b,"/*.*"); else buffer_append(b,"*.*"); path = buffer_to_string(b); handle = FindFirstFile(val_string(path),&d); if( handle == INVALID_HANDLE_VALUE ) neko_error(); while( true ) { // skip magic dirs if( d.cFileName[0] != '.' || (d.cFileName[1] != 0 && (d.cFileName[1] != '.' || d.cFileName[2] != 0)) ) { tmp = alloc_array(2); val_array_ptr(tmp)[0] = alloc_string(d.cFileName); val_array_ptr(tmp)[1] = val_null; if( cur ) val_array_ptr(cur)[1] = tmp; else h = tmp; cur = tmp; } if( !FindNextFile(handle,&d) ) break; } FindClose(handle); #else DIR *d; struct dirent *e; val_check(path,string); d = opendir(val_string(path)); if( d == NULL ) neko_error(); while( true ) { e = readdir(d); if( e == NULL ) break; // skip magic dirs if( e->d_name[0] == '.' && (e->d_name[1] == 0 || (e->d_name[1] == '.' && e->d_name[2] == 0)) ) continue; tmp = alloc_array(2); val_array_ptr(tmp)[0] = alloc_string(e->d_name); val_array_ptr(tmp)[1] = val_null; if( cur ) val_array_ptr(cur)[1] = tmp; else h = tmp; cur = tmp; } closedir(d); #endif return h; } /** file_full_path : string -> string Return an absolute path from a relative one. The file or directory must exists **/ static value file_full_path( value path ) { #ifdef NEKO_WINDOWS char buf[MAX_PATH+1]; val_check(path,string); if( GetFullPathName(val_string(path),MAX_PATH+1,buf,NULL) == 0 ) neko_error(); return alloc_string(buf); #elif defined(__GLIBC__) val_check(path,string); char *buf = realpath(val_string(path), NULL); if( buf == NULL ) neko_error(); value ret = alloc_string(buf); free(buf); return ret; #else char buf[PATH_MAX]; val_check(path,string); if( realpath(val_string(path),buf) == NULL ) neko_error(); return alloc_string(buf); #endif } /** sys_exe_path : void -> string Return the path of the executable **/ static value sys_exe_path() { #if defined(NEKO_WINDOWS) char path[MAX_PATH]; if( GetModuleFileName(NULL,path,MAX_PATH) == 0 ) neko_error(); return alloc_string(path); #elif defined(NEKO_MAC) char path[PATH_MAX+1]; uint32_t path_len = PATH_MAX; if( _NSGetExecutablePath(path, &path_len) ) neko_error(); return alloc_string(path); #elif defined(NEKO_LINUX) static char path[PATH_MAX]; int length = readlink("/proc/self/exe", path, sizeof(path)); if( length < 0 || length >= PATH_MAX ) { char *p = getenv(" "); // for upx if( p == NULL ) p = getenv("_"); if( p == NULL ) neko_error(); return alloc_string(p); } path[length] = '\0'; return alloc_string(path); #else const char *p = getenv("_"); if( p != NULL ) return alloc_string(p); neko_error(); #endif } #ifdef NEKO_MAC # define environ (*_NSGetEnviron()) #endif #ifndef NEKO_WINDOWS extern char **environ; #endif /** sys_env : void -> #list Return all the (key,value) pairs in the environment as a chained list **/ static value sys_env() { value h = val_null; value cur = NULL, tmp, key; char **e = environ; while( *e ) { char *x = strchr(*e,'='); if( x == NULL ) { e++; continue; } tmp = alloc_array(3); key = alloc_empty_string((int)(x - *e)); memcpy(val_string(key),*e,(int)(x - *e)); val_array_ptr(tmp)[0] = key; val_array_ptr(tmp)[1] = alloc_string(x+1); val_array_ptr(tmp)[2] = val_null; if( cur ) val_array_ptr(cur)[2] = tmp; else h = tmp; cur = tmp; e++; } return h; } /** sys_getch : bool -> int Read a character from stdin with or without echo **/ static value sys_getch( value b ) { # ifdef NEKO_WINDOWS val_check(b,bool); return alloc_int( val_bool(b)?getche():getch() ); # else // took some time to figure out how to do that // without relying on ncurses, which clear the // terminal on initscr() int c; struct termios term, old; val_check(b,bool); tcgetattr(fileno(stdin), &old); term = old; cfmakeraw(&term); tcsetattr(fileno(stdin), 0, &term); c = getchar(); tcsetattr(fileno(stdin), 0, &old); if( val_bool(b) ) fputc(c,stdout); return alloc_int(c); # endif } /** sys_get_pid : void -> int Returns the current process identifier **/ static value sys_get_pid() { # ifdef NEKO_WINDOWS return alloc_int(GetCurrentProcessId()); # else return alloc_int(getpid()); # endif } /** win_env_changed : void -> void Tell that the windows envionment variables were changed in the registry **/ static value win_env_changed() { # ifdef NEKO_WINDOWS DWORD unused; SendMessageTimeout(HWND_BROADCAST,WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, &unused ); # endif return val_null; } DEFINE_PRIM(get_env,1); DEFINE_PRIM(put_env,2); DEFINE_PRIM(set_time_locale,1); DEFINE_PRIM(get_cwd,0); DEFINE_PRIM(set_cwd,1); DEFINE_PRIM(sys_sleep,1); DEFINE_PRIM(sys_command,1); DEFINE_PRIM(sys_exit,1); DEFINE_PRIM(sys_string,0); DEFINE_PRIM(sys_is64,0); DEFINE_PRIM(sys_stat,1); DEFINE_PRIM(sys_time,0); DEFINE_PRIM(sys_cpu_time,0); DEFINE_PRIM(sys_env,0); DEFINE_PRIM(sys_create_dir,2); DEFINE_PRIM(sys_remove_dir,1); DEFINE_PRIM(sys_read_dir,1); DEFINE_PRIM(file_full_path,1); DEFINE_PRIM(file_exists,1); DEFINE_PRIM(sys_exists,1); DEFINE_PRIM(file_delete,1); DEFINE_PRIM(sys_rename,2); DEFINE_PRIM(sys_exe_path,0); DEFINE_PRIM(sys_file_type,1); DEFINE_PRIM(sys_getch,1); DEFINE_PRIM(sys_get_pid,0); DEFINE_PRIM(sys_thread_cpu_time,0); DEFINE_PRIM(win_env_changed,0); /* ************************************************************************ */ neko-2-2-0/libs/std/thread.c000066400000000000000000000350401321613172000156010ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #undef free_lock #undef lock_release #include #include #include #ifdef NEKO_WINDOWS # include typedef HANDLE vlock; #else # include # include typedef struct _vlock { pthread_mutex_t lock; pthread_cond_t cond; int counter; } *vlock; #endif typedef struct _tqueue { value msg; struct _tqueue *next; } tqueue; typedef struct { tqueue *first; tqueue *last; # ifdef NEKO_WINDOWS CRITICAL_SECTION lock; HANDLE wait; # else pthread_mutex_t lock; pthread_cond_t wait; # endif } vdeque; typedef struct { # ifdef NEKO_WINDOWS DWORD tid; # else pthread_t phandle; # endif value v; vdeque q; neko_vm *vm; } vthread; DECLARE_KIND(k_thread); #define val_thread(t) ((vthread*)val_data(t)) #ifdef NEKO_WINDOWS # define LOCK(l) EnterCriticalSection(&(l)) # define UNLOCK(l) LeaveCriticalSection(&(l)) # define SIGNAL(l) ReleaseSemaphore(l,1,NULL) #else # define LOCK(l) pthread_mutex_lock(&(l)) # define UNLOCK(l) pthread_mutex_unlock(&(l)) # define SIGNAL(l) pthread_cond_signal(&(l)) #endif /* deque raw API */ static void _deque_init( vdeque *q ) { # ifdef NEKO_WINDOWS q->wait = CreateSemaphore(NULL,0,(1 << 30),NULL); InitializeCriticalSection(&q->lock); # else pthread_mutex_init(&q->lock,NULL); pthread_cond_init(&q->wait,NULL); # endif } static void _deque_destroy( vdeque *q ) { #ifdef NEKO_WINDOWS DeleteCriticalSection(&q->lock); CloseHandle(q->wait); #else pthread_mutex_destroy(&q->lock); pthread_cond_destroy(&q->wait); #endif } static void _deque_add( vdeque *q, value msg ) { tqueue *t; t = (tqueue*)alloc(sizeof(tqueue)); t->msg = msg; t->next = NULL; LOCK(q->lock); if( q->last == NULL ) q->first = t; else q->last->next = t; q->last = t; SIGNAL(q->wait); UNLOCK(q->lock); } static void _deque_push( vdeque *q, value msg ) { tqueue *t; t = (tqueue*)alloc(sizeof(tqueue)); t->msg = msg; LOCK(q->lock); t->next = q->first; q->first = t; if( q->last == NULL ) q->last = t; SIGNAL(q->wait); UNLOCK(q->lock); } static value _deque_pop( vdeque *q, int block ) { value msg; LOCK(q->lock); while( q->first == NULL ) if( block ) { # ifdef NEKO_WINDOWS UNLOCK(q->lock); WaitForSingleObject(q->wait,INFINITE); LOCK(q->lock); # else pthread_cond_wait(&q->wait,&q->lock); # endif } else { UNLOCK(q->lock); return val_null; } msg = q->first->msg; q->first = q->first->next; if( q->first == NULL ) q->last = NULL; else SIGNAL(q->wait); UNLOCK(q->lock); return msg; } /**

Thread

An API to create and manager system threads and locks.

**/ #define val_lock(l) ((vlock)val_data(l)) #define val_tls(l) ((vtls*)val_data(l)) #define val_mutex(l) ((mt_lock*)val_data(l)) #define val_deque(l) ((vdeque*)val_data(l)) typedef struct { # ifdef NEKO_WINDOWS DWORD tls; # else pthread_key_t key; # endif } vtls; DEFINE_KIND(k_thread); DEFINE_KIND(k_lock); DEFINE_KIND(k_tls); DEFINE_KIND(k_mutex); DEFINE_KIND(k_deque); typedef struct { value callb; value callparam; vthread *t; void *handle; int jit; } tparams; static vthread *neko_thread_current() { return (vthread*)neko_vm_custom(neko_vm_current(),k_thread); } static void free_thread( value v ) { vthread *t = val_thread(v); _deque_destroy(&t->q); } static vthread *alloc_thread( neko_vm *vm ) { vthread *t = (vthread*)alloc(sizeof(vthread)); memset(t,0,sizeof(vthread)); #ifdef NEKO_WINDOWS t->tid = GetCurrentThreadId(); #else t->phandle = pthread_self(); #endif t->v = alloc_abstract(k_thread,t); t->vm = vm; _deque_init(&t->q); val_gc(t->v,free_thread); return t; } static void thread_init( void *_p ) { tparams *p = (tparams*)_p; neko_vm *vm; // init the VM and set current thread vm = neko_vm_alloc(NULL); p->t = alloc_thread(vm); neko_vm_jit(vm,p->jit); neko_vm_select(vm); neko_vm_set_custom(vm,k_thread,p->t); } static void thread_loop( void *_p ) { tparams *p = (tparams*)_p; value exc = NULL; val_callEx(val_null,p->callb,&p->callparam,1,&exc); // display exception if( exc != NULL ) { buffer b = alloc_buffer(NULL); fprintf(stderr,"An exception occurred in a neko Thread :\n"); val_buffer(b,exc); fprintf(stderr,"%s\n",val_string(buffer_to_string(b))); } // cleanup neko_vm_select(NULL); p->t->v = val_null; p->t->vm = NULL; } /** thread_create : f:function:1 -> p:any -> 'thread Creates a thread that will be running the function [f(p)] **/ static value thread_create( value f, value param ) { tparams *p; val_check_function(f,1); p = (tparams*)alloc(sizeof(tparams)); p->callb = f; p->callparam = param; p->jit = neko_vm_jit(neko_vm_current(),-1); if( !neko_thread_create(thread_init,thread_loop,p,&p->handle) ) neko_error(); return p->t->v; } /** thread_current : void -> 'thread Returns the current thread **/ static value thread_current() { vthread *t = neko_thread_current(); // should only occur for main thread ! if( t == NULL ) { neko_vm *vm = neko_vm_current(); t = alloc_thread(vm); neko_vm_set_custom(vm,k_thread,t); } return t->v; } /** thread_send : 'thread -> msg:any -> void Send a message into the target thread message queue **/ static value thread_send( value vt, value msg ) { vthread *t; val_check_kind(vt,k_thread); t = val_thread(vt); _deque_add(&t->q,msg); return val_null; } /** thread_read_message : block:bool -> any Reads a message from the message queue. If [block] is true, the function only returns when a message is available. If [block] is false and no message is available in the queue, the function will return immediatly [null]. **/ static value thread_read_message( value block ) { value v = thread_current(); vthread *t; if( v == NULL ) neko_error(); t = val_thread(v); val_check(block,bool); return _deque_pop( &t->q, val_bool(block) ); } /** thread_stack : 'thread -> array Get the thread current call stack. Might crash if the thread currently manipulate the stack, so mostly used to debug infinite loops. **/ static value thread_stack( value vt ) { vthread *t; val_check_kind(vt,k_thread); t = val_thread(vt); if( t->vm == NULL ) neko_error(); return neko_call_stack(t->vm); } static void free_lock( value l ) { # ifdef NEKO_WINDOWS CloseHandle( val_lock(l) ); # else pthread_cond_destroy( &val_lock(l)->cond ); pthread_mutex_destroy( &val_lock(l)->lock ); # endif } /** lock_create : void -> 'lock Creates a lock which is initially locked **/ static value lock_create() { value vl; vlock l; # ifdef NEKO_WINDOWS l = CreateSemaphore(NULL,0,(1 << 30),NULL); if( l == NULL ) neko_error(); # else l = (vlock)alloc_private(sizeof(struct _vlock)); l->counter = 0; if( pthread_mutex_init(&l->lock,NULL) != 0 || pthread_cond_init(&l->cond,NULL) != 0 ) neko_error(); # endif vl = alloc_abstract(k_lock,l); val_gc(vl,free_lock); return vl; } /** lock_release : 'lock -> void Release a lock. The thread does not need to own the lock to be able to release it. If a lock is released several times, it can be acquired as many times **/ static value lock_release( value lock ) { vlock l; val_check_kind(lock,k_lock); l = val_lock(lock); # ifdef NEKO_WINDOWS if( !ReleaseSemaphore(l,1,NULL) ) neko_error(); # else pthread_mutex_lock(&l->lock); l->counter++; pthread_cond_signal(&l->cond); pthread_mutex_unlock(&l->lock); # endif return val_true; } /** lock_wait : 'lock -> timeout:number? -> bool Waits for a lock to be released and acquire it. If [timeout] (in seconds) is not null and expires then the returned value is false **/ static value lock_wait( value lock, value timeout ) { int has_timeout = !val_is_null(timeout); val_check_kind(lock,k_lock); if( has_timeout ) val_check(timeout,number); # ifdef NEKO_WINDOWS switch( WaitForSingleObject(val_lock(lock),has_timeout?(DWORD)(val_number(timeout) * 1000.0):INFINITE) ) { case WAIT_ABANDONED: case WAIT_OBJECT_0: return val_true; case WAIT_TIMEOUT: return val_false; default: neko_error(); } # else { vlock l = val_lock(lock); pthread_mutex_lock(&l->lock); while( l->counter == 0 ) { if( has_timeout ) { struct timeval tv; struct timespec t; double delta = val_number(timeout); int idelta = (int)delta, idelta2; delta -= idelta; delta *= 1.0e9; gettimeofday(&tv,NULL); delta += tv.tv_usec * 1000.0; idelta2 = (int)(delta / 1e9); delta -= idelta2 * 1e9; t.tv_sec = tv.tv_sec + idelta + idelta2; t.tv_nsec = (long)delta; if( pthread_cond_timedwait(&l->cond,&l->lock,&t) != 0 ) { pthread_mutex_unlock(&l->lock); return val_false; } } else pthread_cond_wait(&l->cond,&l->lock); } l->counter--; if( l->counter > 0 ) pthread_cond_signal(&l->cond); pthread_mutex_unlock(&l->lock); return val_true; } # endif } static void free_tls( value v ) { vtls *t = val_tls(v); # ifdef NEKO_WINDOWS TlsFree(t->tls); # else pthread_key_delete(t->key); # endif free(t); } /** tls_create : void -> 'tls Creates thread local storage. This is placeholder that can store a value that will be different depending on the local thread. You must set the tls value to [null] before exiting the thread or the memory will never be collected. **/ static value tls_create() { value v; vtls *t = (vtls*)malloc(sizeof(vtls)); # ifdef NEKO_WINDOWS t->tls = TlsAlloc(); TlsSetValue(t->tls,NULL); # else pthread_key_create(&t->key,NULL); # endif v = alloc_abstract(k_tls,t); val_gc(v,free_tls); return v; } /** tls_get : 'tls -> any Returns the value set by [tls_set] for the local thread. **/ static value tls_get( value v ) { vtls *t; value *r; val_check_kind(v,k_tls); t = val_tls(v); # ifdef NEKO_WINDOWS r = (value*)TlsGetValue(t->tls); # else r = (value*)pthread_getspecific(t->key); # endif if( r == NULL ) return val_null; return *r; } /** tls_set : 'tls -> any -> void Set the value of the TLS for the local thread. **/ static value tls_set( value v, value content ) { vtls *t; value *r; val_check_kind(v,k_tls); t = val_tls(v); # ifdef NEKO_WINDOWS r = (value*)TlsGetValue(t->tls); # else r = (value*)pthread_getspecific(t->key); # endif if( r == NULL ) { if( val_is_null(content) ) return val_null; r = alloc_root(1); # ifdef NEKO_WINDOWS TlsSetValue(t->tls,r); # else pthread_setspecific(t->key,r); # endif } else if( val_is_null(content) ) { free_root(r); # ifdef NEKO_WINDOWS TlsSetValue(t->tls,NULL); # else pthread_setspecific(t->key,NULL); # endif return val_null; } *r = content; return val_null; } static void free_mutex( value v ) { neko_free_lock( val_mutex(v) ); } /** mutex_create : void -> 'mutex Creates a mutex, which can be used to acquire a temporary lock to access some ressource. The main difference with a lock is that a mutex must always be released by the owner thread. **/ static value mutex_create() { mt_lock *m = neko_alloc_lock(); value v = alloc_abstract(k_mutex,m); val_gc(v,free_mutex); return v; } /** mutex_acquire : 'mutex -> void The current thread acquire the mutex or wait if not available. The same thread can acquire several times the same mutex but must release it as many times it has been acquired. **/ static value mutex_acquire( value m ) { val_check_kind(m,k_mutex); neko_lock_acquire( val_mutex(m) ); return val_null; } /** mutex_try : 'mutex -> bool Try to acquire the mutex, returns true if acquire or false if it's already locked by another thread. **/ static value mutex_try( value m ) { val_check_kind(m,k_mutex); return alloc_bool( neko_lock_try(val_mutex(m)) ); } /** mutex_release : 'mutex -> void Release a mutex that has been acquired by the current thread. The behavior is undefined if the current thread does not own the mutex. **/ static value mutex_release( value m ) { val_check_kind(m,k_mutex); neko_lock_release(val_mutex(m)); return val_null; } static void free_deque( value v ) { _deque_destroy(val_deque(v)); } /** deque_create : void -> 'deque create a message queue for multithread access **/ static value deque_create() { vdeque *q = (vdeque*)alloc(sizeof(vdeque)); value v = alloc_abstract(k_deque,q); val_gc(v,free_deque); _deque_init(q); return v; } /** deque_add : 'deque -> any -> void add a message at the end of the queue **/ static value deque_add( value v, value i ) { val_check_kind(v,k_deque); _deque_add(val_deque(v),i); return val_null; } /** deque_push : 'deque -> any -> void add a message at the head of the queue **/ static value deque_push( value v, value i ) { val_check_kind(v,k_deque); _deque_push(val_deque(v),i); return val_null; } /** deque_pop : 'deque -> bool -> any? pop a message from the queue head. Either block until a message is available or return immedialtly with null. **/ static value deque_pop( value v, value block ) { val_check_kind(v,k_deque); val_check(block,bool); return _deque_pop(val_deque(v),val_bool(block)); } DEFINE_PRIM(thread_create,2); DEFINE_PRIM(thread_current,0); DEFINE_PRIM(thread_send,2); DEFINE_PRIM(thread_read_message,1); DEFINE_PRIM(thread_stack,1); DEFINE_PRIM(lock_create,0); DEFINE_PRIM(lock_wait,2); DEFINE_PRIM(lock_release,1); DEFINE_PRIM(tls_create,0); DEFINE_PRIM(tls_set,2); DEFINE_PRIM(tls_get,1); DEFINE_PRIM(mutex_create,0); DEFINE_PRIM(mutex_acquire,1); DEFINE_PRIM(mutex_try,1); DEFINE_PRIM(mutex_release,1); DEFINE_PRIM(deque_create,0); DEFINE_PRIM(deque_add,2); DEFINE_PRIM(deque_push,2); DEFINE_PRIM(deque_pop,2); neko-2-2-0/libs/std/unicase.c000066400000000000000000000671271321613172000157740ustar00rootroot00000000000000#define UL_BITS 6 #define UL_SIZE 64 static uchar _E[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L1[UL_SIZE] = {0,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L3[UL_SIZE] = {224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,0,248,249,250,251,252,253,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L4[UL_SIZE] = {257,0,259,0,261,0,263,0,265,0,267,0,269,0,271,0,273,0,275,0,277,0,279,0,281,0,283,0,285,0,287,0,289,0,291,0,293,0,295,0,297,0,299,0,301,0,303,0,105,0,307,0,309,0,311,0,0,314,0,316,0,318,0,320}; static uchar L5[UL_SIZE] = {0,322,0,324,0,326,0,328,0,0,331,0,333,0,335,0,337,0,339,0,341,0,343,0,345,0,347,0,349,0,351,0,353,0,355,0,357,0,359,0,361,0,363,0,365,0,367,0,369,0,371,0,373,0,375,0,255,378,0,380,0,382,0,0}; static uchar L6[UL_SIZE] = {0,595,387,0,389,0,596,392,0,598,599,396,0,0,477,601,603,402,0,608,611,0,617,616,409,0,0,0,623,626,0,629,417,0,419,0,421,0,640,424,0,643,0,0,429,0,648,432,0,650,651,436,0,438,0,658,441,0,0,0,445,0,0,0}; static uchar L7[UL_SIZE] = {0,0,0,0,454,454,0,457,457,0,460,460,0,462,0,464,0,466,0,468,0,470,0,472,0,474,0,476,0,0,479,0,481,0,483,0,485,0,487,0,489,0,491,0,493,0,495,0,0,499,499,0,501,0,405,447,505,0,507,0,509,0,511,0}; static uchar L8[UL_SIZE] = {513,0,515,0,517,0,519,0,521,0,523,0,525,0,527,0,529,0,531,0,533,0,535,0,537,0,539,0,541,0,543,0,414,0,547,0,549,0,551,0,553,0,555,0,557,0,559,0,561,0,563,0,0,0,0,0,0,0,11365,572,0,410,11366,0}; static uchar L9[UL_SIZE] = {0,578,0,384,649,652,583,0,585,0,587,0,589,0,591,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L13[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,881,0,883,0,0,0,887,0,0,0,0,0,0,0,0,1011}; static uchar L14[UL_SIZE] = {0,0,0,0,0,0,940,0,941,942,943,0,972,0,973,974,0,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,0,963,964,965,966,967,968,969,970,971,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L15[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,983,0,0,0,0,0,0,0,0,985,0,987,0,989,0,991,0,993,0,995,0,997,0,999,0,1001,0,1003,0,1005,0,1007,0,0,0,0,0,952,0,0,1016,0,1010,1019,0,0,891,892,893}; static uchar L16[UL_SIZE] = {1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L17[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1121,0,1123,0,1125,0,1127,0,1129,0,1131,0,1133,0,1135,0,1137,0,1139,0,1141,0,1143,0,1145,0,1147,0,1149,0,1151,0}; static uchar L18[UL_SIZE] = {1153,0,0,0,0,0,0,0,0,0,1163,0,1165,0,1167,0,1169,0,1171,0,1173,0,1175,0,1177,0,1179,0,1181,0,1183,0,1185,0,1187,0,1189,0,1191,0,1193,0,1195,0,1197,0,1199,0,1201,0,1203,0,1205,0,1207,0,1209,0,1211,0,1213,0,1215,0}; static uchar L19[UL_SIZE] = {1231,1218,0,1220,0,1222,0,1224,0,1226,0,1228,0,1230,0,0,1233,0,1235,0,1237,0,1239,0,1241,0,1243,0,1245,0,1247,0,1249,0,1251,0,1253,0,1255,0,1257,0,1259,0,1261,0,1263,0,1265,0,1267,0,1269,0,1271,0,1273,0,1275,0,1277,0,1279,0}; static uchar L20[UL_SIZE] = {1281,0,1283,0,1285,0,1287,0,1289,0,1291,0,1293,0,1295,0,1297,0,1299,0,1301,0,1303,0,1305,0,1307,0,1309,0,1311,0,1313,0,1315,0,1317,0,1319,0,1321,0,1323,0,1325,0,1327,0,0,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391}; static uchar L21[UL_SIZE] = {1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L66[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,11530,11531,11532,11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548,11549,11550,11551}; static uchar L67[UL_SIZE] = {11552,11553,11554,11555,11556,11557,0,11559,0,0,0,0,0,11565,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L120[UL_SIZE] = {7681,0,7683,0,7685,0,7687,0,7689,0,7691,0,7693,0,7695,0,7697,0,7699,0,7701,0,7703,0,7705,0,7707,0,7709,0,7711,0,7713,0,7715,0,7717,0,7719,0,7721,0,7723,0,7725,0,7727,0,7729,0,7731,0,7733,0,7735,0,7737,0,7739,0,7741,0,7743,0}; static uchar L121[UL_SIZE] = {7745,0,7747,0,7749,0,7751,0,7753,0,7755,0,7757,0,7759,0,7761,0,7763,0,7765,0,7767,0,7769,0,7771,0,7773,0,7775,0,7777,0,7779,0,7781,0,7783,0,7785,0,7787,0,7789,0,7791,0,7793,0,7795,0,7797,0,7799,0,7801,0,7803,0,7805,0,7807,0}; static uchar L122[UL_SIZE] = {7809,0,7811,0,7813,0,7815,0,7817,0,7819,0,7821,0,7823,0,7825,0,7827,0,7829,0,0,0,0,0,0,0,0,0,223,0,7841,0,7843,0,7845,0,7847,0,7849,0,7851,0,7853,0,7855,0,7857,0,7859,0,7861,0,7863,0,7865,0,7867,0,7869,0,7871,0}; static uchar L123[UL_SIZE] = {7873,0,7875,0,7877,0,7879,0,7881,0,7883,0,7885,0,7887,0,7889,0,7891,0,7893,0,7895,0,7897,0,7899,0,7901,0,7903,0,7905,0,7907,0,7909,0,7911,0,7913,0,7915,0,7917,0,7919,0,7921,0,7923,0,7925,0,7927,0,7929,0,7931,0,7933,0,7935,0}; static uchar L124[UL_SIZE] = {0,0,0,0,0,0,0,0,7936,7937,7938,7939,7940,7941,7942,7943,0,0,0,0,0,0,0,0,7952,7953,7954,7955,7956,7957,0,0,0,0,0,0,0,0,0,0,7968,7969,7970,7971,7972,7973,7974,7975,0,0,0,0,0,0,0,0,7984,7985,7986,7987,7988,7989,7990,7991}; static uchar L125[UL_SIZE] = {0,0,0,0,0,0,0,0,8000,8001,8002,8003,8004,8005,0,0,0,0,0,0,0,0,0,0,0,8017,0,8019,0,8021,0,8023,0,0,0,0,0,0,0,0,8032,8033,8034,8035,8036,8037,8038,8039,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L126[UL_SIZE] = {0,0,0,0,0,0,0,0,8064,8065,8066,8067,8068,8069,8070,8071,0,0,0,0,0,0,0,0,8080,8081,8082,8083,8084,8085,8086,8087,0,0,0,0,0,0,0,0,8096,8097,8098,8099,8100,8101,8102,8103,0,0,0,0,0,0,0,0,8112,8113,8048,8049,8115,0,0,0}; static uchar L127[UL_SIZE] = {0,0,0,0,0,0,0,0,8050,8051,8052,8053,8131,0,0,0,0,0,0,0,0,0,0,0,8144,8145,8054,8055,0,0,0,0,0,0,0,0,0,0,0,0,8160,8161,8058,8059,8165,0,0,0,0,0,0,0,0,0,0,0,8056,8057,8060,8061,8179,0,0,0}; static uchar L132[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,969,0,0,0,107,229,0,0,0,0,0,0,8526,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L133[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L134[UL_SIZE] = {0,0,0,8580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L146[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433}; static uchar L147[UL_SIZE] = {9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L176[UL_SIZE] = {11312,11313,11314,11315,11316,11317,11318,11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334,11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,11348,11349,11350,11351,11352,11353,11354,11355,11356,11357,11358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L177[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11361,0,619,7549,637,0,0,11368,0,11370,0,11372,0,593,625,592,594,0,11379,0,0,11382,0,0,0,0,0,0,0,0,575,576}; static uchar L178[UL_SIZE] = {11393,0,11395,0,11397,0,11399,0,11401,0,11403,0,11405,0,11407,0,11409,0,11411,0,11413,0,11415,0,11417,0,11419,0,11421,0,11423,0,11425,0,11427,0,11429,0,11431,0,11433,0,11435,0,11437,0,11439,0,11441,0,11443,0,11445,0,11447,0,11449,0,11451,0,11453,0,11455,0}; static uchar L179[UL_SIZE] = {11457,0,11459,0,11461,0,11463,0,11465,0,11467,0,11469,0,11471,0,11473,0,11475,0,11477,0,11479,0,11481,0,11483,0,11485,0,11487,0,11489,0,11491,0,0,0,0,0,0,0,0,11500,0,11502,0,0,0,0,11507,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L665[UL_SIZE] = {42561,0,42563,0,42565,0,42567,0,42569,0,42571,0,42573,0,42575,0,42577,0,42579,0,42581,0,42583,0,42585,0,42587,0,42589,0,42591,0,42593,0,42595,0,42597,0,42599,0,42601,0,42603,0,42605,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L666[UL_SIZE] = {42625,0,42627,0,42629,0,42631,0,42633,0,42635,0,42637,0,42639,0,42641,0,42643,0,42645,0,42647,0,42649,0,42651,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L668[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42787,0,42789,0,42791,0,42793,0,42795,0,42797,0,42799,0,0,0,42803,0,42805,0,42807,0,42809,0,42811,0,42813,0,42815,0}; static uchar L669[UL_SIZE] = {42817,0,42819,0,42821,0,42823,0,42825,0,42827,0,42829,0,42831,0,42833,0,42835,0,42837,0,42839,0,42841,0,42843,0,42845,0,42847,0,42849,0,42851,0,42853,0,42855,0,42857,0,42859,0,42861,0,42863,0,0,0,0,0,0,0,0,0,0,42874,0,42876,0,7545,42879,0}; static uchar L670[UL_SIZE] = {42881,0,42883,0,42885,0,42887,0,0,0,0,42892,0,613,0,0,42897,0,42899,0,0,0,42903,0,42905,0,42907,0,42909,0,42911,0,42913,0,42915,0,42917,0,42919,0,42921,0,614,604,609,620,0,0,670,647,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L1020[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0}; static uchar L1040[UL_SIZE] = {66600,66601,66602,66603,66604,66605,66606,66607,66608,66609,66610,66611,66612,66613,66614,66615,66616,66617,66618,66619,66620,66621,66622,66623,66624,66625,66626,66627,66628,66629,66630,66631,66632,66633,66634,66635,66636,66637,66638,66639,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar L1122[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71872,71873,71874,71875,71876,71877,71878,71879,71880,71881,71882,71883,71884,71885,71886,71887,71888,71889,71890,71891,71892,71893,71894,71895,71896,71897,71898,71899,71900,71901,71902,71903}; static uchar U1[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,0,0,0,0,0}; static uchar U2[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,924,0,0,0,0,0,0,0,0,0,0}; static uchar U3[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,0,216,217,218,219,220,221,222,376}; static uchar U4[UL_SIZE] = {0,256,0,258,0,260,0,262,0,264,0,266,0,268,0,270,0,272,0,274,0,276,0,278,0,280,0,282,0,284,0,286,0,288,0,290,0,292,0,294,0,296,0,298,0,300,0,302,0,73,0,306,0,308,0,310,0,0,313,0,315,0,317,0}; static uchar U5[UL_SIZE] = {319,0,321,0,323,0,325,0,327,0,0,330,0,332,0,334,0,336,0,338,0,340,0,342,0,344,0,346,0,348,0,350,0,352,0,354,0,356,0,358,0,360,0,362,0,364,0,366,0,368,0,370,0,372,0,374,0,0,377,0,379,0,381,83}; static uchar U6[UL_SIZE] = {579,0,0,386,0,388,0,0,391,0,0,0,395,0,0,0,0,0,401,0,0,502,0,0,0,408,573,0,0,0,544,0,0,416,0,418,0,420,0,0,423,0,0,0,0,428,0,0,431,0,0,0,435,0,437,0,0,440,0,0,0,444,0,503}; static uchar U7[UL_SIZE] = {0,0,0,0,453,453,453,456,456,456,459,459,459,0,461,0,463,0,465,0,467,0,469,0,471,0,473,0,475,398,0,478,0,480,0,482,0,484,0,486,0,488,0,490,0,492,0,494,0,498,498,498,0,500,0,0,0,504,0,506,0,508,0,510}; static uchar U8[UL_SIZE] = {0,512,0,514,0,516,0,518,0,520,0,522,0,524,0,526,0,528,0,530,0,532,0,534,0,536,0,538,0,540,0,542,0,0,0,546,0,548,0,550,0,552,0,554,0,556,0,558,0,560,0,562,0,0,0,0,0,0,0,0,571,0,0,11390}; static uchar U9[UL_SIZE] = {11391,0,577,0,0,0,0,582,0,584,0,586,0,588,0,590,11375,11373,11376,385,390,0,393,394,0,399,0,400,42923,0,0,0,403,42924,0,404,0,42893,42922,0,407,406,0,11362,42925,0,0,412,0,11374,413,0,0,415,0,0,0,0,0,0,0,11364,0,0}; static uchar U10[UL_SIZE] = {422,0,0,425,0,0,0,42929,430,580,433,434,581,0,0,0,0,0,439,0,0,0,0,0,0,0,0,0,0,0,42928,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U13[UL_SIZE] = {0,0,0,0,0,921,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,882,0,0,0,886,0,0,0,1021,1022,1023,0,0}; static uchar U14[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,902,904,905,906,0,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927}; static uchar U15[UL_SIZE] = {928,929,931,931,932,933,934,935,936,937,938,939,908,910,911,0,914,920,0,0,0,934,928,975,0,984,0,986,0,988,0,990,0,992,0,994,0,996,0,998,0,1000,0,1002,0,1004,0,1006,922,929,1017,895,0,917,0,0,1015,0,0,1018,0,0,0,0}; static uchar U16[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055}; static uchar U17[UL_SIZE] = {1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,0,1120,0,1122,0,1124,0,1126,0,1128,0,1130,0,1132,0,1134,0,1136,0,1138,0,1140,0,1142,0,1144,0,1146,0,1148,0,1150}; static uchar U18[UL_SIZE] = {0,1152,0,0,0,0,0,0,0,0,0,1162,0,1164,0,1166,0,1168,0,1170,0,1172,0,1174,0,1176,0,1178,0,1180,0,1182,0,1184,0,1186,0,1188,0,1190,0,1192,0,1194,0,1196,0,1198,0,1200,0,1202,0,1204,0,1206,0,1208,0,1210,0,1212,0,1214}; static uchar U19[UL_SIZE] = {0,0,1217,0,1219,0,1221,0,1223,0,1225,0,1227,0,1229,1216,0,1232,0,1234,0,1236,0,1238,0,1240,0,1242,0,1244,0,1246,0,1248,0,1250,0,1252,0,1254,0,1256,0,1258,0,1260,0,1262,0,1264,0,1266,0,1268,0,1270,0,1272,0,1274,0,1276,0,1278}; static uchar U20[UL_SIZE] = {0,1280,0,1282,0,1284,0,1286,0,1288,0,1290,0,1292,0,1294,0,1296,0,1298,0,1300,0,1302,0,1304,0,1306,0,1308,0,1310,0,1312,0,1314,0,1316,0,1318,0,1320,0,1322,0,1324,0,1326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U21[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359}; static uchar U22[UL_SIZE] = {1360,1361,1362,1363,1364,1365,1366,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U117[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42877,0,0,0,11363,0,0}; static uchar U120[UL_SIZE] = {0,7680,0,7682,0,7684,0,7686,0,7688,0,7690,0,7692,0,7694,0,7696,0,7698,0,7700,0,7702,0,7704,0,7706,0,7708,0,7710,0,7712,0,7714,0,7716,0,7718,0,7720,0,7722,0,7724,0,7726,0,7728,0,7730,0,7732,0,7734,0,7736,0,7738,0,7740,0,7742}; static uchar U121[UL_SIZE] = {0,7744,0,7746,0,7748,0,7750,0,7752,0,7754,0,7756,0,7758,0,7760,0,7762,0,7764,0,7766,0,7768,0,7770,0,7772,0,7774,0,7776,0,7778,0,7780,0,7782,0,7784,0,7786,0,7788,0,7790,0,7792,0,7794,0,7796,0,7798,0,7800,0,7802,0,7804,0,7806}; static uchar U122[UL_SIZE] = {0,7808,0,7810,0,7812,0,7814,0,7816,0,7818,0,7820,0,7822,0,7824,0,7826,0,7828,0,0,0,0,0,7776,0,0,0,0,0,7840,0,7842,0,7844,0,7846,0,7848,0,7850,0,7852,0,7854,0,7856,0,7858,0,7860,0,7862,0,7864,0,7866,0,7868,0,7870}; static uchar U123[UL_SIZE] = {0,7872,0,7874,0,7876,0,7878,0,7880,0,7882,0,7884,0,7886,0,7888,0,7890,0,7892,0,7894,0,7896,0,7898,0,7900,0,7902,0,7904,0,7906,0,7908,0,7910,0,7912,0,7914,0,7916,0,7918,0,7920,0,7922,0,7924,0,7926,0,7928,0,7930,0,7932,0,7934}; static uchar U124[UL_SIZE] = {7944,7945,7946,7947,7948,7949,7950,7951,0,0,0,0,0,0,0,0,7960,7961,7962,7963,7964,7965,0,0,0,0,0,0,0,0,0,0,7976,7977,7978,7979,7980,7981,7982,7983,0,0,0,0,0,0,0,0,7992,7993,7994,7995,7996,7997,7998,7999,0,0,0,0,0,0,0,0}; static uchar U125[UL_SIZE] = {8008,8009,8010,8011,8012,8013,0,0,0,0,0,0,0,0,0,0,0,8025,0,8027,0,8029,0,8031,0,0,0,0,0,0,0,0,8040,8041,8042,8043,8044,8045,8046,8047,0,0,0,0,0,0,0,0,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,0,0}; static uchar U126[UL_SIZE] = {8072,8073,8074,8075,8076,8077,8078,8079,0,0,0,0,0,0,0,0,8088,8089,8090,8091,8092,8093,8094,8095,0,0,0,0,0,0,0,0,8104,8105,8106,8107,8108,8109,8110,8111,0,0,0,0,0,0,0,0,8120,8121,0,8124,0,0,0,0,0,0,0,0,0,0,921,0}; static uchar U127[UL_SIZE] = {0,0,0,8140,0,0,0,0,0,0,0,0,0,0,0,0,8152,8153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8168,8169,0,0,0,8172,0,0,0,0,0,0,0,0,0,0,0,0,0,8188,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U133[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,8498,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559}; static uchar U134[UL_SIZE] = {0,0,0,0,8579,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U147[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U176[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279}; static uchar U177[UL_SIZE] = {11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,11310,0,0,11360,0,0,0,570,574,0,11367,0,11369,0,11371,0,0,0,0,0,0,11378,0,0,11381,0,0,0,0,0,0,0,0,0}; static uchar U178[UL_SIZE] = {0,11392,0,11394,0,11396,0,11398,0,11400,0,11402,0,11404,0,11406,0,11408,0,11410,0,11412,0,11414,0,11416,0,11418,0,11420,0,11422,0,11424,0,11426,0,11428,0,11430,0,11432,0,11434,0,11436,0,11438,0,11440,0,11442,0,11444,0,11446,0,11448,0,11450,0,11452,0,11454}; static uchar U179[UL_SIZE] = {0,11456,0,11458,0,11460,0,11462,0,11464,0,11466,0,11468,0,11470,0,11472,0,11474,0,11476,0,11478,0,11480,0,11482,0,11484,0,11486,0,11488,0,11490,0,0,0,0,0,0,0,0,11499,0,11501,0,0,0,0,11506,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U180[UL_SIZE] = {4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,0,4295,0,0,0,0,0,4301,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U665[UL_SIZE] = {0,42560,0,42562,0,42564,0,42566,0,42568,0,42570,0,42572,0,42574,0,42576,0,42578,0,42580,0,42582,0,42584,0,42586,0,42588,0,42590,0,42592,0,42594,0,42596,0,42598,0,42600,0,42602,0,42604,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U666[UL_SIZE] = {0,42624,0,42626,0,42628,0,42630,0,42632,0,42634,0,42636,0,42638,0,42640,0,42642,0,42644,0,42646,0,42648,0,42650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U668[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42786,0,42788,0,42790,0,42792,0,42794,0,42796,0,42798,0,0,0,42802,0,42804,0,42806,0,42808,0,42810,0,42812,0,42814}; static uchar U669[UL_SIZE] = {0,42816,0,42818,0,42820,0,42822,0,42824,0,42826,0,42828,0,42830,0,42832,0,42834,0,42836,0,42838,0,42840,0,42842,0,42844,0,42846,0,42848,0,42850,0,42852,0,42854,0,42856,0,42858,0,42860,0,42862,0,0,0,0,0,0,0,0,0,0,42873,0,42875,0,0,42878}; static uchar U670[UL_SIZE] = {0,42880,0,42882,0,42884,0,42886,0,0,0,0,42891,0,0,0,0,42896,0,42898,0,0,0,42902,0,42904,0,42906,0,42908,0,42910,0,42912,0,42914,0,42916,0,42918,0,42920,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U1021[UL_SIZE] = {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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U1040[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66560,66561,66562,66563,66564,66565,66566,66567,66568,66569,66570,66571,66572,66573,66574,66575,66576,66577,66578,66579,66580,66581,66582,66583}; static uchar U1041[UL_SIZE] = {66584,66585,66586,66587,66588,66589,66590,66591,66592,66593,66594,66595,66596,66597,66598,66599,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uchar U1123[UL_SIZE] = {71840,71841,71842,71843,71844,71845,71846,71847,71848,71849,71850,71851,71852,71853,71854,71855,71856,71857,71858,71859,71860,71861,71862,71863,71864,71865,71866,71867,71868,71869,71870,71871,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; #define LMAX 1123 #define UMAX 1124 static uchar *LOWER[LMAX] = {_E,L1,_E,L3,L4,L5,L6,L7,L8,L9,_E,_E,_E,L13,L14,L15,L16,L17,L18,L19,L20,L21,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L66,L67,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L120,L121,L122,L123,L124,L125,L126,L127,_E,_E,_E,_E,L132,L133,L134,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L146,L147,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L176,L177,L178,L179,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L665,L666,_E,L668,L669,L670,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L1020,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L1040,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L1122}; static uchar *UPPER[UMAX] = {_E,U1,U2,U3,U4,U5,U6,U7,U8,U9,U10,_E,_E,U13,U14,U15,U16,U17,U18,U19,U20,U21,U22,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U117,_E,_E,U120,U121,U122,U123,U124,U125,U126,U127,_E,_E,_E,_E,_E,U133,U134,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U147,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U176,U177,U178,U179,U180,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U665,U666,_E,U668,U669,U670,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U1021,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U1040,U1041,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U1123}; neko-2-2-0/libs/std/unicode.c000066400000000000000000000527331321613172000157700ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include /**

Unicode

Operations on Unicode strings. Most of the operations are optimized for speed so they might still succeed on some malformed Unicode string. The only function that completely check the Unicode format is [unicode_validate]. Other functions might raise some exception or not depending on the malformed data.

Supported encodings are "ascii", "iso-latin1", "utf8", "ucs2-le", "ucs2-be", "utf16-le", "utf16-be", "utf32-le", "utf32-be"

**/ #define INVALID_CHAR 0xFFFFFFFF typedef unsigned int uchar; typedef unsigned char *ustring; #include "unicase.c" #define val_ustring(s) ((ustring)val_string(s)) typedef enum { ASCII = 0, ISO_LATIN1 = 1, UTF8 = 2, UCS2_BE = 3, UCS2_LE = 4, UTF16_BE = 5, UTF16_LE = 6, UTF32_BE = 7, UTF32_LE = 8, LAST_ENCODING = 9 } encoding; static const char *encodings[] = { "ascii", "iso-latin1", "utf8", "ucs2-le", "ucs2-be", "utf16-le", "utf16-be", "utf32-le", "utf32-be", }; static int utf8_codelen[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 4 }; DEFINE_KIND(k_uni_buf); #define IS_BE(e) (neko_is_big_endian() ^ ((e) & 1)) #define u16be(v) (((v) >> 8) | (((v) << 8) & 0xFF00)) #define u32be(v) (((v) >> 24) | (((v) >> 8) & 0xFF00) | (((v) << 8) & 0xFF0000) | ((v) << 24)) static void TODO() { val_throw(alloc_string("Not implemented")); } /* ------------ UCHAR LIB FUNCTIONS -------------------- */ static int uchar_size( uchar c, encoding e ) { switch( e ) { case ASCII: if( c >= 0x80 ) return 0; return 1; case ISO_LATIN1: if( c >= 0x100 ) return 0; return 1; case UCS2_LE: case UCS2_BE: if( c >= 0x10000 ) return 0; return 2; case UTF16_LE: case UTF16_BE: if( c >= 0x110000 ) return 0; return c >= 0x10000 ? 4 : 2; case UTF32_LE: case UTF32_BE: return 4; case UTF8: if( c >= 0x200000 ) return 0; return utf8_codelen[c>>4]; default: TODO(); break; } return 0; } static void uchar_set( ustring str, encoding e, uchar c ) { switch( e ) { case ASCII: case ISO_LATIN1: *str = c; break; case UTF8: if( c < 0x80 ) *str++ = c; else if( c < 0x800 ) { *str++ = (c >> 6); *str++ = (c & 63); } else if( c < 0x10000 ) { *str++ = 0xE0 | (c >> 12); *str++ = 0x80 | ((c >> 6) & 63); *str++ = 0x80 | (c & 63); } else { *str++ = 0xF0 | (c >> 18); *str++ = 0x80 | ((c >> 12) & 63); *str++ = 0x80 | ((c >> 6) & 63); *str++ = 0x80 | (c & 63); } break; case UCS2_LE: case UCS2_BE: if( IS_BE(e) ) c = u16be(c); *((unsigned short*)str) = c; break; case UTF32_LE: case UTF32_BE: if( IS_BE(e) ) c = u32be(c); *((unsigned int*)str) = c; break; } } static ustring uchar_pos( ustring str, int size, encoding e, int pos ) { if( pos < 0 ) return NULL; switch( e ) { case ASCII: case ISO_LATIN1: if( pos > size ) return NULL; return str + pos; case UCS2_LE: case UCS2_BE: if( pos > (size >> 1) ) return NULL; return str + (pos << 1); case UTF32_LE: case UTF32_BE: if( pos > (size >> 2) ) return NULL; return str + (pos << 2); case UTF16_LE: case UTF16_BE: { ustring end = str + size; int dec = IS_BE(e) ? 0 : 8; while( str + 1 < end && pos-- > 0 ) { unsigned short c = *(unsigned short *)str; if( ((c >> dec) & 0xFC) == 0xD8 ) str += 4; else str += 2; } if( str > end ) return NULL; return str; } case UTF8: { ustring end = str + size; while( str < end && pos-- > 0 ) { int l = utf8_codelen[(*str)>>4]; if( l == 0 ) return NULL; str += l; } if( str > end ) return NULL; return str; } default: TODO(); break; } return NULL; } static uchar uchar_get( ustring *rstr, int size, encoding e, int pos ) { uchar c; ustring str = *rstr; if( pos < 0 ) return INVALID_CHAR; switch( e ) { case ASCII: case ISO_LATIN1: if( pos >= size ) return INVALID_CHAR; str = str + pos; c = *str++; break; case UCS2_LE: case UCS2_BE: if( pos >= size << 1 ) return INVALID_CHAR; str = str + (pos<<1); c = *((unsigned short *)str); str += 2; if( IS_BE(e) ) c = u16be(c); break; case UTF32_LE: case UTF32_BE: if( pos >= size << 2 ) return INVALID_CHAR; str = str + (pos<<2); c = *((unsigned int *)str); str += 4; if( IS_BE(e) ) c = u32be(c); break; case UTF16_LE: case UTF16_BE: if( pos > 0 ) { ustring str2 = uchar_pos(str, size, e, pos); size = (str + size) - str2; str = str2; } if( size < 2 ) return INVALID_CHAR; c = *(unsigned short *)str; str += 2; if( IS_BE(e) ) c = u16be(c); if( (c & 0xFC00) == 0xD800 ) { unsigned short c2; if( size < 4 ) return INVALID_CHAR; c2 = *(unsigned short *)str; str += 2; if( IS_BE(e) ) c2 = u16be(c2); if( (c2 & 0xFC00) != 0xDC00 ) return INVALID_CHAR; c = (((c&0x3FFF)<<10) | (c2&0x3FFF)) + 0x10000; } break; case UTF8: if( pos > 0 ) { ustring str2 = uchar_pos(str, size, e, pos); size = (str + size) - str2; str = str2; } if( size < 1 ) return INVALID_CHAR; c = *str; if( c >= 0x80 ) { int len = utf8_codelen[c>>4]; if( len == 0 || size < len ) return INVALID_CHAR; if( c < 0xE0 ) { c = ((c & 0x3F) << 6) | ((*str) & 0x7F); str++; } else if( c < 0xF0 ) { c = ((c & 0x1F) << 12) | (((*str) & 0x7F) << 6) | (str[1] & 0x7F); str += 2; } else { c = ((c & 0x0F) << 18) | (((*str) & 0x7F) << 12) | ((str[1] & 0x7F) << 6) | (str[2] & 0x7F); str += 3; } } break; default: c = INVALID_CHAR; TODO(); break; } *rstr = str; return c; } /* -------------------------------------------------------------------- */ /** unicode_encoding : string -> int Gets the encoding code corresponding the given value ascii=0 iso-latin1=1 utf8=2 ucs2-be=3 ucs2-le=4 utf16-be=5 utf16-le=6 utf32-be=7 utf32-le=8 **/ static value unicode_encoding_code( value str ) { int i; val_check(str, string); for( i = 0; i < LAST_ENCODING; i++ ) if( strcmp(val_string(str), encodings[i]) == 0 ) return alloc_int(i); neko_error(); return val_null; } static value unicode_encoding_string( value enc ) { val_check(enc, int); if( val_int(enc) < 0 || val_int(enc) >= LAST_ENCODING ) neko_error(); return alloc_string(encodings[val_int(enc)]); } typedef struct { value buf; encoding enc; int pos; int nchars; } uni_buf; static encoding get_encoding( value v ) { int e; if( !val_is_int(v) || (e = val_int(v)) < 0 || e >= LAST_ENCODING ) val_throw(alloc_string("Invalid encoding value")); return e; } /** unicode_buf_alloc : size:int -> encoding:int -> 'ubuf Create a new buffer with an initial size in bytes and specific encoding. **/ static value unicode_buf_alloc( value size, value encoding ) { uni_buf *b; val_check(size,int); if( val_int(size) < 0 ) neko_error(); b = (uni_buf*)alloc(sizeof(uni_buf)); b->buf = alloc_empty_string(val_int(size)); b->pos = 0; b->nchars = 0; b->enc = get_encoding(encoding); return alloc_abstract(k_uni_buf,b); } static void unicode_buf_resize( uni_buf *b ) { value s; int len = val_strlen(b->buf); int size2 = (len * 3) >> 1; if( size2 - len < 10 ) size2 = 10 + len; s = alloc_empty_string(size2); memcpy(val_string(s),val_string(b->buf),len); b->buf = s; } /** unicode_buf_add : 'buf -> int -> void Add an Unicode char to the buffer **/ static value unicode_buf_add( value buf, value uc ) { uni_buf *b; uchar c; int req; val_check_kind(buf,k_uni_buf); val_check(uc,int); b = (uni_buf*)val_data(buf); c = (uchar)val_int(uc); req = uchar_size(c, b->enc); if( req == 0 ) val_throw(alloc_string("Unicode char outside of encoding range")); if( b->pos + req > val_strlen(b->buf) ) unicode_buf_resize(b); uchar_set(val_ustring(b->buf) + b->pos, b->enc, c); return val_null; } /** unicode_buf_content : 'buf -> string Return the current content of the buffer. This is not a copy of the buffer but the shared content. Retreiving content and then continuing to add chars is possible but not very efficient. **/ static value unicode_buf_content( value buf ) { uni_buf *b; val_check_kind(buf,k_uni_buf); b = (uni_buf*)val_data(buf); val_set_length(b->buf,b->pos); val_string(b->buf)[b->pos] = 0; return b->buf; } /** unicode_buf_length : 'buf -> int Return the number of Unicode chars stored in the buffer **/ static value unicode_buf_length( value buf ) { uni_buf *b; val_check_kind(buf,k_uni_buf); b = (uni_buf*)val_data(buf); return alloc_int(b->nchars); } /** unicode_buf_size : 'buf -> int Return the current size in bytes of the buffer **/ static value unicode_buf_size( value buf ) { uni_buf *b; val_check_kind(buf,k_uni_buf); b = (uni_buf*)val_data(buf); return alloc_int(b->pos); } /** unicode_validate : s:string -> encoding:int -> bool Tells if a string [s] is encoded using the given Unicode format. **/ static value unicode_validate( value str, value encoding ) { int l; ustring s; val_check(str,string); l = val_strlen(str); s = val_ustring(str); switch( get_encoding(encoding) ) { case ASCII: while( l-- ) { unsigned char c = *s++; if( c >= 0x80 ) return val_false; } break; case ISO_LATIN1: return val_true; case UCS2_LE: if( s[0] == 0xFE && s[1] == 0xFF ) return val_false; // BOM fail return alloc_bool((l & 1) == 0); case UCS2_BE: if( s[0] == 0xFF && s[1] == 0xFE ) return val_false; // BOM fail return alloc_bool((l & 1) == 0); case UTF32_LE: if( l >= 4 && s[0] == 0 && s[1] == 0 && s[2] == 0xFE && s[3] == 0xFF ) return val_false; // BOM fail return alloc_bool((l & 3) == 0); case UTF32_BE: if( l >= 4 && s[0] == 0xFF && s[1] == 0xFE && s[2] == 0 && s[3] == 0 ) return val_false; // BOM fail return alloc_bool((l & 3) == 0); case UTF16_LE: if( s[0] == 0xFE && s[1] == 0xFF ) return val_false; // BOM fail { ustring end = s + l; int dec = IS_BE(UTF16_LE) ? 0 : 8; while( s + 1 < end ) { unsigned short c = *(unsigned short*)s; if( ((c >> dec) & 0xFC) == 0xD8 ) { if( s + 3 >= end ) return val_false; if( ((((unsigned short*)s)[1] >> dec) & 0xFC) != 0xDC ) return val_false; s += 4; } else s += 2; } return alloc_bool(s == end); } case UTF16_BE: if( s[0] == 0xFF && s[1] == 0xFE ) return val_false; // BOM fail { ustring end = s + l; int dec = IS_BE(UTF16_BE) ? 8 : 0; while( s + 1 < end ) { unsigned short c = *(unsigned short*)s; if( ((c >> dec) & 0xFC) == 0xD8 ) { if( s + 3 >= end ) return val_false; if( ((((unsigned short*)s)[1] >> dec) & 0xFC) != 0xDC ) return val_false; s += 4; } else s += 2; } return alloc_bool(s == end); } case UTF8: { ustring end = s + l; while( s < end ) { int l = utf8_codelen[(*s) >> 4]; if( l == 0 ) return val_false; s += l; } return alloc_bool(s == end); } default: TODO(); break; } return val_false; } /** unicode_length : string -> encoding:int -> int Returns the number of Unicode chars in the string. **/ static value unicode_length( value str, value enc ) { int l; int count = 0; encoding e; ustring s; val_check(str,string); l = val_strlen(str); s = val_ustring(str); e = get_encoding(enc); switch( e ) { case ASCII: case ISO_LATIN1: count = l; break; case UCS2_LE: case UCS2_BE: count = l >> 1; break; case UTF16_LE: case UTF16_BE: { ustring end = s + l; int dec = IS_BE(e) ? 0 : 8; while( s + 1 < end ) { unsigned short c = *(unsigned short *)s; if( ((c >> dec) & 0xFC) == 0xD8 ) s += 4; else s += 2; count++; } if( s > end ) count--; } break; case UTF32_LE: case UTF32_BE: count = l >> 2; break; case UTF8: { ustring end = s + l; while( s < end ) { int l = utf8_codelen[(*s) >> 4]; if( l == 0 ) l = 1; count++; s += l; } if( s > end ) count--; } break; default: TODO(); break; } return alloc_int(count); } /** unicode_sub : string -> encoding:int -> pos:int -> len:int -> string Returns a part of an Unicode string. **/ static value unicode_sub( value str, value enc, value vpos, value vlen ) { int l; int pos, len; encoding e; ustring s, start, end; val_check(str,string); val_check(vpos,int); val_check(vlen,int); e = get_encoding(enc); l = val_strlen(str); pos = val_int(vpos); len = val_int(vlen); s = val_ustring(str); start = uchar_pos(s,l,e,pos); if( start == NULL ) neko_error(); end = uchar_pos(start,l-(start-s),e,len); if( end == NULL ) neko_error(); l = (int)(end - start); str = alloc_empty_string(l); memcpy(val_string(str),start,l); return str; } /** unicode_get : string -> encoding:int -> n:int -> int Returns the [n]th char in an Unicode string. This might be inefficient if [n] is big and the string has variable length per char. **/ static value unicode_get( value str, value enc, value pos ) { uchar c; ustring s; val_check(str,string); val_check(pos,int); s = val_ustring(str); c = uchar_get(&s, val_strlen(str), get_encoding(enc), val_int(pos)); if( c == INVALID_CHAR ) neko_error(); return alloc_best_int(c); } /** unicode_iter : string -> encoding:int -> f:(int -> void) -> void Call [f] with each of Unicode char of the string. **/ static value unicode_iter( value str, value enc, value f ) { encoding e; ustring s, end; val_check(str,string); val_check_function(f,1); e = get_encoding(enc); s = val_ustring(str); end = s + val_strlen(str); while( s < end ) { uchar c = uchar_get(&s, end - s, e, 0); if( c == INVALID_CHAR ) neko_error(); val_call1(f,alloc_best_int(c)); } return val_null; } /** unicode_compare : s1:string -> s2:string -> encoding:int -> int Compare two Unicode strings according to their char codes. **/ static value unicode_compare( value str1, value str2, value enc ) { int l1, l2, l; encoding e; ustring s1, s2; val_check(str1,string); val_check(str2,string); l1 = val_strlen(str1); l2 = val_strlen(str2); s1 = val_ustring(str1); s2 = val_ustring(str2); l = (l1 < l2)?l1:l2; e = get_encoding(enc); switch( e ) { case ISO_LATIN1: case ASCII: case UCS2_BE: case UTF32_BE: { int r = memcmp(s1,s2,l); if( r != 0 ) return alloc_int(r); break; } case UCS2_LE: { unsigned short *i1 = (unsigned short*)s1; unsigned short *i2 = (unsigned short*)s2; int i, d; for( i = 0; i < (l>>1); i++ ) { unsigned short c1 = i1[i]; unsigned short c2 = i2[i]; if( IS_BE(UCS2_LE) ) { c1 = u16be(c1); c2 = u16be(c2); } d = c1 - c2; if( d != 0 ) return alloc_int(d < 0 ? -1 : 1); } break; } case UTF32_LE: { unsigned int *i1 = (unsigned int*)s1; unsigned int *i2 = (unsigned int*)s2; int i, d; for( i = 0; i < (l>>2); i++ ) { unsigned int c1 = i1[i]; unsigned int c2 = i2[i]; if( IS_BE(UTF32_LE) ) { c1 = u32be(c1); c2 = u32be(c2); } d = c1 - c2; if( d != 0 ) return alloc_int(d < 0 ? -1 : 1); } break; } case UTF16_BE: case UTF16_LE: { unsigned short *i1 = (unsigned short*)s1; unsigned short *i2 = (unsigned short*)s2; unsigned short *end1 = i1 + (l1>>1); unsigned short *end2 = i2 + (l2>>1); int d; while( i1 < end1 && i2 < end2 ) { unsigned short c1 = *i1++; unsigned short c2 = *i2++; if( IS_BE(e) ) { c1 = u16be(c1); c2 = u16be(c2); } if( (c1 & 0xFC00) == 0xD800 ) { if( i1 == end1 ) neko_error(); c1 = (((c1&0x3FFF)<<10) | ((*i1++)&0x3FFF)) + 0x10000; } if( (c2 & 0xFC00) == 0xD800 ) { if( i2 == end2 ) neko_error(); c2 = (((c2&0x3FFF)<<10) | ((*i2++)&0x3FFF)) + 0x10000; } d = c1 - c2; if( d != 0 ) return alloc_int(d < 0 ? -1 : 1); } d = (end1 - i1) - (end2 - i2); return alloc_int( d == 0 ? 0 : d < 0 ? -1 : 1 ); } case UTF8: // assume that we have correctly encoded the code points // so they both take the minimum required number of stored bytes while( l-- ) { unsigned char c1 = *s1++; unsigned char c2 = *s2++; if( c1 != c2 ) return alloc_int((c1 > c2)?-1:1); if( c1 < 0x7F ) continue; else if( c1 < 0xC0 ) neko_error(); else if( c1 < 0xE0 ) { l--; if( l < 0 ) neko_error(); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?-1:1); } else if( c1 < 0xF0 ) { l-=2; if( l < 0 ) neko_error(); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?-1:1); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?-1:1); } else { l -= 3; if( l < 0 ) neko_error(); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?-1:1); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?-1:1); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?-1:1); } } default: TODO(); break; } if( l1 != l2 ) return alloc_int((l1 > l2)?1:-1); return alloc_int(0); } static void expand( value *str, int *len ) { int len2 = ((*len) * 5) >> 2; value v2; if( len2 - (*len) < 10 ) len2 = (*len) + 10; v2 = alloc_empty_string(len2); memcpy(val_string(v2), val_string(*str), *len); *len = len2; *str = v2; } /** unicode_convert : string -> encoding:int -> to_encoding:int -> string Convert an Unicode string from a given encoding to another. **/ static value unicode_convert( value str, value encoding, value to_encoding ) { ustring s, end; int e, e_to; int len, size, pos = 0; value vto; val_check(str,string); s = val_ustring(str); size = val_strlen(str); end = s + size; e = get_encoding(encoding); e_to = get_encoding(to_encoding); if( e == e_to ) return str; // try to allocate enough space at first guess switch( e ) { case ISO_LATIN1: case UTF8: case ASCII: len = size; break; case UCS2_LE: case UCS2_BE: case UTF16_LE: case UTF16_BE: len = size >> 1; break; case UTF32_LE: case UTF32_BE: len = size >> 2; break; default: TODO(); len = 0; break; } switch( e_to ) { case ISO_LATIN1: case ASCII: break; case UTF8: // assume one byte per char break; case UCS2_LE: case UCS2_BE: case UTF16_LE: case UTF16_BE: len *= 2; break; case UTF32_LE: case UTF32_BE: len *= 4; break; default: TODO(); break; } // convert vto = alloc_empty_string(len); while( s < end ) { uchar c = uchar_get(&s,end - s,e,0); int k; if( c == INVALID_CHAR ) val_throw(alloc_string("Input string is not correctly encoded")); k = uchar_size(c, e_to); if( k == 0 ) { if( e_to == ISO_LATIN1 || e_to == ASCII ) c = '?'; else c = 0xFFFD; k = uchar_size(c, e_to); } if( pos + k > len ) expand(&vto,&len); uchar_set(val_string(vto) + pos, e_to, c); pos += k; } val_set_length(vto, pos); val_string(vto)[pos] = 0; return vto; } /** unicode_lower : string -> encoding:int -> string Returns the lowercase version of the unicode string. **/ static value unicode_lower( value str, value enc ) { ustring s,end; value out; int pos = 0; int len; encoding e; val_check(str,string); e = get_encoding(enc); s = val_ustring(str); len = val_strlen(str); end = s + len; out = alloc_empty_string(len); while( s < end ) { uchar c = uchar_get(&s,end - s, e, 0); int up = c >> UL_BITS; int k; if( up < LMAX ) { uchar c2 = LOWER[up][c&((1< len ) expand(&out, &len); uchar_set(val_ustring(out)+pos, e, c); pos += k; } val_set_length(out, pos); val_string(out)[pos] = 0; return out; } /** unicode_upper : string -> encoding:int -> string Returns the lowercase version of the unicode string. **/ static value unicode_upper( value str, value enc ) { ustring s,end; value out; int pos = 0; int len; encoding e; val_check(str,string); e = get_encoding(enc); s = val_ustring(str); len = val_strlen(str); end = s + len; out = alloc_empty_string(len); while( s < end ) { uchar c = uchar_get(&s,end - s, e, 0); int up = c >> UL_BITS; int k; if( up < UMAX ) { uchar c2 = UPPER[up][c&((1< len ) expand(&out, &len); uchar_set(val_ustring(out)+pos, e, c); pos += k; } val_set_length(out, pos); val_string(out)[pos] = 0; return out; } DEFINE_PRIM(unicode_buf_alloc,2); DEFINE_PRIM(unicode_buf_add,2); DEFINE_PRIM(unicode_buf_content,1); DEFINE_PRIM(unicode_buf_length,1); DEFINE_PRIM(unicode_buf_size,1); DEFINE_PRIM(unicode_get,3); DEFINE_PRIM(unicode_validate,2); DEFINE_PRIM(unicode_iter,3); DEFINE_PRIM(unicode_length,2); DEFINE_PRIM(unicode_compare,3); DEFINE_PRIM(unicode_sub,4); DEFINE_PRIM(unicode_convert,3); DEFINE_PRIM(unicode_lower,2); DEFINE_PRIM(unicode_upper,2); /* ************************************************************************ */ neko-2-2-0/libs/std/utf8.c000066400000000000000000000244631321613172000152270ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include /**

UTF8

Operations on UTF8 strings. Most of the operations are optimized for speed so they might still succeed on some malformed UTF8 string. The only function that completely check the UTF8 format is [utf8_validate]. Other functions might raise some exception or not depending on the malformed data.

**/ typedef struct { value buf; int pos; int nesc; } ubuf; DEFINE_KIND(k_ubuf); /** utf8_buf_alloc : size:int -> 'ubuf Create a new buffer with an initial size in bytes **/ static value utf8_buf_alloc( value size ) { ubuf *b; val_check(size,int); if( val_int(size) < 0 ) neko_error(); b = (ubuf*)alloc(sizeof(ubuf)); b->buf = alloc_empty_string(val_int(size)); b->nesc = 0; b->pos = 0; return alloc_abstract(k_ubuf,b); } static void utf8_buf_resize( ubuf *b ) { value s; int len = val_strlen(b->buf); // allocate a number of bytes depending on previously // escaped caracters, with a minimum of 10 int nbytes = (b->nesc + b->pos * 2 - 1) / (b->pos?b->pos:1); if( nbytes < 10 ) nbytes = 10; s = alloc_empty_string(len+nbytes); memcpy(val_string(s),val_string(b->buf),len); b->buf = s; } /** utf8_buf_add : 'buf -> int -> void Add a valid UTF8 char (0 - 0x10FFFF) to the buffer **/ static value utf8_buf_add( value buf, value uchar ) { ubuf *b; unsigned char *s; unsigned int c; val_check_kind(buf,k_ubuf); val_check(uchar,int); b = (ubuf*)val_data(buf); c = (unsigned)val_int(uchar); if( c <= 0x7F ) { if( b->pos >= val_strlen(b->buf) ) utf8_buf_resize(b); val_string(b->buf)[b->pos++] = (char)c; return val_true; } if( b->pos + 4 > val_strlen(b->buf) ) utf8_buf_resize(b); s = (unsigned char*)val_string(b->buf); if( c <= 0x7FF ) { b->nesc += 1; s[b->pos++] = 0xC0 | (c >> 6); s[b->pos++] = 0x80 | (c & 63); } else if( c <= 0xFFFF ) { b->nesc += 2; s[b->pos++] = 0xE0 | (c >> 12); s[b->pos++] = 0x80 | ((c >> 6) & 63); s[b->pos++] = 0x80 | (c & 63); } else if( c <= 0x10FFFF ) { b->nesc += 3; s[b->pos++] = 0xF0 | (c >> 18); s[b->pos++] = 0x80 | ((c >> 12) & 63); s[b->pos++] = 0x80 | ((c >> 6) & 63); s[b->pos++] = 0x80 | (c & 63); } else neko_error(); return val_true; } /** utf8_buf_content : 'buf -> string Return the current content of the buffer. This is not a copy of the buffer but the shared content. Retreiving content and then continuing to add chars is possible but not very efficient. **/ static value utf8_buf_content( value buf ) { ubuf *b; val_check_kind(buf,k_ubuf); b = (ubuf*)val_data(buf); val_set_length(b->buf,b->pos); val_string(b->buf)[b->pos] = 0; return b->buf; } /** utf8_buf_length : 'buf -> int Return the number of UTF8 chars stored in the buffer **/ static value utf8_buf_length( value buf ) { ubuf *b; val_check_kind(buf,k_ubuf); b = (ubuf*)val_data(buf); return alloc_int(b->pos - b->nesc); } /** utf8_buf_size : 'buf -> int Return the current size in bytes of the buffer **/ static value utf8_buf_size( value buf ) { ubuf *b; val_check_kind(buf,k_ubuf); b = (ubuf*)val_data(buf); return alloc_int(b->pos); } /** utf8_validate : string -> bool Validate if a string is encoded using the UTF8 format **/ static value utf8_validate( value str ) { int l; unsigned char *s; val_check(str,string); l = val_strlen(str); s = (unsigned char*)val_string(str); while( l-- ) { unsigned char c = *s++; if( c < 0x7F ) continue; else if( c < 0xC0 ) return val_false; else if( c < 0xE0 ) { if( (*s++ & 0x80) != 0x80 ) return val_false; l--; } else if( c < 0xF0 ) { if( (*s++ & 0x80) != 0x80 ) return val_false; if( (*s++ & 0x80) != 0x80 ) return val_false; l-=2; } else { if( (*s++ & 0x80) != 0x80 ) return val_false; if( (*s++ & 0x80) != 0x80 ) return val_false; if( (*s++ & 0x80) != 0x80 ) return val_false; l-=3; } } return val_true; } /** utf8_length : string -> int Returns the number of UTF8 chars in the string. **/ static value utf8_length( value str ) { int l; int count = 0; unsigned char *s; val_check(str,string); l = val_strlen(str); s = (unsigned char*)val_string(str); while( l > 0 ) { unsigned char c = *s; count++; if( c < 0x7F ) { l--; s++; } else if( c < 0xC0 ) neko_error(); else if( c < 0xE0 ) { l-=2; s+=2; } else if( c < 0xF0 ) { l-=3; s+=3; } else { l-=4; s+=4; } } if( l < 0 ) neko_error(); return alloc_int(count); } /** utf8_sub : string -> pos:int -> len:int -> string Returns a part of an UTF8 string. **/ static value utf8_sub( value str, value pos, value len ) { int l; int count; unsigned char *s, *save; val_check(str,string); val_check(pos,int); val_check(len,int); l = val_strlen(str); count = val_int(pos); if( count < 0 ) neko_error(); s = (unsigned char*)val_string(str); while( count-- && l > 0 ) { unsigned char c = *s; if( c < 0x7F ) { l--; s++; } else if( c < 0xC0 ) neko_error(); else if( c < 0xE0 ) { l-=2; s+=2; } else if( c < 0xF0 ) { l-=3; s+=3; } else { l-=4; s+=4; } } if( l < 0 ) neko_error(); save = s; count = val_int(len); if( count < 0 ) neko_error(); while( count-- && l > 0 ) { unsigned char c = *s; if( c < 0x7F ) { l--; s++; } else if( c < 0xC0 ) neko_error(); else if( c < 0xE0 ) { l-=2; s+=2; } else if( c < 0xF0 ) { l-=3; s+=3; } else { l-=4; s+=4; } } if( l < 0 ) neko_error(); l = (int)(s - save); str = alloc_empty_string(l); memcpy(val_string(str),save,l); return str; } /** utf8_get : string -> n:int -> int Returns the [n]th char in an UTF8 string. This might be inefficient if [n] is big. **/ static value utf8_get( value str, value pos ) { int l; int p; unsigned char *s; val_check(pos,int); val_check(str,string); l = val_strlen(str); p = val_int(pos); if( p < 0 ) neko_error(); s = (unsigned char*)val_string(str); while( l-- ) { unsigned char c = *s++; if( c < 0x7F ) { if( p-- == 0 ) return alloc_int(c); } else if( c < 0xC0 ) neko_error(); else if( c < 0xE0 ) { l--; if( l < 0 ) neko_error(); if( p-- == 0 ) return alloc_int(((c & 0x3F) << 6) | ((*s) & 0x7F)); s++; } else if( c < 0xF0 ) { l -= 2; if( l < 0 ) neko_error(); if( p-- == 0 ) return alloc_int(((c & 0x1F) << 12) | (((*s) & 0x7F) << 6) | (s[1] & 0x7F)); s += 2; } else { l -= 3; if( l < 0 ) neko_error(); if( p-- == 0 ) return alloc_int(((c & 0x0F) << 18) | (((*s) & 0x7F) << 12) | ((s[1] & 0x7F) << 6) | (s[2] & 0x7F)); s += 3; } } neko_error(); return val_true; } /** utf8_iter : string -> f:(int -> void) -> void Call [f] with each of UTF8 char of the string. **/ static value utf8_iter( value str, value f ) { int l; unsigned char *s; val_check(str,string); val_check_function(f,1); l = val_strlen(str); s = (unsigned char*)val_string(str); while( l-- ) { unsigned char c = *s++; if( c < 0x7F ) val_call1(f,alloc_int(c)); else if( c < 0xC0 ) neko_error(); else if( c < 0xE0 ) { l--; if( l < 0 ) neko_error(); val_call1(f,alloc_int(((c & 0x3F) << 6) | ((*s) & 0x7F))); s++; } else if( c < 0xF0 ) { l -= 2; if( l < 0 ) neko_error(); val_call1(f,alloc_int(((c & 0x1F) << 12) | (((*s) & 0x7F) << 6) | (s[1] & 0x7F))); s += 2; } else { l -= 3; if( l < 0 ) neko_error(); val_call1(f,alloc_int(((c & 0x0F) << 18) | (((*s) & 0x7F) << 12) | ((s[1] & 0x7F) << 6) | (s[2] & 0x7F))); s += 3; } } return val_true; } /** utf8_compare : s1:string -> s2:string -> int Compare two UTF8 strings according to UTF8 char codes. **/ static value utf8_compare( value str1, value str2 ) { int l1, l2, l; unsigned char *s1, *s2; val_check(str1,string); val_check(str2,string); l1 = val_strlen(str1); l2 = val_strlen(str2); s1 = (unsigned char*)val_string(str1); s2 = (unsigned char*)val_string(str2); l = (l1 < l2)?l1:l2; while( l-- ) { unsigned char c1 = *s1++; unsigned char c2 = *s2++; if( c1 != c2 ) return alloc_int((c1 > c2)?1:-1); if( c1 < 0x7F ) continue; else if( c1 < 0xC0 ) neko_error(); else if( c1 < 0xE0 ) { l--; if( l < 0 ) neko_error(); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?1:-1); } else if( c1 < 0xF0 ) { l-=2; if( l < 0 ) neko_error(); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?1:-1); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?1:-1); } else { l -= 3; if( l < 0 ) neko_error(); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?1:-1); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?1:-1); if( *s1++ != *s2++ ) return alloc_int((s1[-1] > s2[-1])?1:-1); } } if( l1 != l2 ) return alloc_int((l1 > l2)?1:-1); return alloc_int(0); } DEFINE_PRIM(utf8_buf_alloc,1); DEFINE_PRIM(utf8_buf_add,2); DEFINE_PRIM(utf8_buf_content,1); DEFINE_PRIM(utf8_buf_length,1); DEFINE_PRIM(utf8_buf_size,1); DEFINE_PRIM(utf8_get,2); DEFINE_PRIM(utf8_validate,1); DEFINE_PRIM(utf8_iter,2); DEFINE_PRIM(utf8_length,1); DEFINE_PRIM(utf8_compare,2); DEFINE_PRIM(utf8_sub,3); /* ************************************************************************ */ neko-2-2-0/libs/std/xml.c000066400000000000000000000216611321613172000151360ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #ifndef NEKO_WINDOWS # include # undef strcmpi # define strcmpi(a,b) strcasecmp(a,b) #else # include #endif #define ERROR(msg) xml_error(xml,p,line,msg); // -------------- parsing -------------------------- typedef enum { IGNORE_SPACES, BEGIN, BEGIN_NODE, TAG_NAME, BODY, ATTRIB_NAME, EQUALS, ATTVAL_BEGIN, ATTRIB_VAL, CHILDREN, CLOSE, WAIT_END, WAIT_END_RET, PCDATA, HEADER, COMMENT, DOCTYPE, CDATA, } STATE; extern field id_pcdata; extern field id_xml; extern field id_done; extern field id_comment; extern field id_cdata; extern field id_doctype; static void xml_error( const char *xml, const char *p, int *line, const char *msg ) { buffer b = alloc_buffer("Xml parse error : "); int l = (int)strlen(p); int nchars = 30; buffer_append(b,msg); buffer_append(b," at line "); val_buffer(b,alloc_int(*line)); buffer_append(b," : "); if( p != xml ) buffer_append(b,"..."); buffer_append_sub(b,p,(l < nchars)?l:nchars); if( l > nchars ) buffer_append(b,"..."); if( l == 0 ) buffer_append(b,""); bfailure(b); } static bool is_valid_char( int c ) { return ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c >= '0' && c <= '9' ) || c == ':' || c == '.' || c == '_' || c == '-'; } static void do_parse_xml( const char *xml, const char **lp, int *line, value callb, const char *parentname ) { STATE state = BEGIN; STATE next = BEGIN; field aname = (field)0; value attribs = NULL; value nodename = NULL; const char *start = NULL; const char *p = *lp; char c = *p; int nsubs = 0, nbrackets = 0; while( c ) { switch( state ) { case IGNORE_SPACES: switch( c ) { case '\n': case '\r': case '\t': case ' ': break; default: state = next; continue; } break; case BEGIN: switch( c ) { case '<': state = IGNORE_SPACES; next = BEGIN_NODE; break; default: start = p; state = PCDATA; continue; } break; case PCDATA: if( c == '<' ) { val_ocall1(callb,id_pcdata,copy_string(start,p-start)); nsubs++; state = IGNORE_SPACES; next = BEGIN_NODE; } break; case CDATA: if( c == ']' && p[1] == ']' && p[2] == '>' ) { val_ocall1(callb,id_cdata,copy_string(start,p-start)); nsubs++; p += 2; state = BEGIN; } break; case BEGIN_NODE: switch( c ) { case '!': if( p[1] == '[' ) { p += 2; if( (p[0] != 'C' && p[0] != 'c') || (p[1] != 'D' && p[1] != 'd') || (p[2] != 'A' && p[2] != 'a') || (p[3] != 'T' && p[3] != 't') || (p[4] != 'A' && p[4] != 'a') || (p[5] != '[') ) ERROR("Expected ': state = CHILDREN; nsubs++; val_ocall2(callb,id_xml,nodename,attribs); break; default: state = ATTRIB_NAME; start = p; continue; } break; case ATTRIB_NAME: if( !is_valid_char(c) ) { value tmp; if( start == p ) ERROR("Expected attribute name"); tmp = copy_string(start,p-start); aname = val_id(val_string(tmp)); if( !val_is_null(val_field(attribs,aname)) ) ERROR("Duplicate attribute"); state = IGNORE_SPACES; next = EQUALS; continue; } break; case EQUALS: switch( c ) { case '=': state = IGNORE_SPACES; next = ATTVAL_BEGIN; break; default: ERROR("Expected ="); } break; case ATTVAL_BEGIN: switch( c ) { case '"': case '\'': state = ATTRIB_VAL; start = p; break; default: ERROR("Expected \""); } break; case ATTRIB_VAL: if( c == *start ) { value aval = copy_string(start+1,p-start-1); alloc_field(attribs,aname,aval); state = IGNORE_SPACES; next = BODY; } break; case CHILDREN: *lp = p; do_parse_xml(xml,lp,line,callb,val_string(nodename)); p = *lp; start = p; state = BEGIN; break; case WAIT_END: switch( c ) { case '>': val_ocall0(callb,id_done); state = BEGIN; break; default : ERROR("Expected >"); } break; case WAIT_END_RET: switch( c ) { case '>': if( nsubs == 0 ) val_ocall1(callb,id_pcdata,alloc_string("")); val_ocall0(callb,id_done); *lp = p; return; default : ERROR("Expected >"); } break; case CLOSE: if( !is_valid_char(c) ) { if( start == p ) ERROR("Expected node name"); { value v = copy_string(start,p - start); if( strcmpi(parentname,val_string(v)) != 0 ) { buffer b = alloc_buffer("Expected "); ERROR(val_string(buffer_to_string(b))); } } state = IGNORE_SPACES; next = WAIT_END_RET; continue; } break; case COMMENT: if( c == '-' && p[1] == '-' && p[2] == '>' ) { val_ocall1(callb,id_comment,copy_string(start,p-start)); p += 2; state = BEGIN; } break; case DOCTYPE: if( c == '[' ) nbrackets++; else if( c == ']' ) nbrackets--; else if( c == '>' && nbrackets == 0 ) { val_ocall1(callb,id_doctype,copy_string(start,p-start)); state = BEGIN; } break; case HEADER: if( c == '?' && p[1] == '>' ) { p++; val_ocall1(callb,id_comment,copy_string(start,p-start)); state = BEGIN; } break; } c = *++p; if( c == '\n' ) (*line)++; } if( state == BEGIN ) { start = p; state = PCDATA; } if( parentname == NULL && state == PCDATA ) { if( p != start || nsubs == 0 ) val_ocall1(callb,id_pcdata,copy_string(start,p-start)); return; } ERROR("Unexpected end"); } // ---------------------------------------------- /**

Xml

The standard event-driven XML parser.

**/ /** parse_xml : xml:string -> events:object -> void The [parse_xml] parse a string and for each parsed element call the corresponding object method in [events] :
  • [void xml( name : string, attribs : object)] when an XML node is found
  • [void done()] when an XML node is closed
  • [void pcdata(string)] when PCData chars found
  • [void cdata(string)] when a CData session is found
  • [void comment(string)] when some comment or special header is found
You can then implement the events so they build the appropriate XML data structure needed by your language.
**/ static value parse_xml( value str, value callb ) { const char *p; int line = 0; val_check(str,string); val_check(callb,object); p = val_string(str); // skip BOM if( p[0] == (char)0xEF && p[1] == (char)0xBB && p[2] == (char)0xBF ) p += 3; do_parse_xml(p,&p,&line,callb,NULL); return val_true; } DEFINE_PRIM(parse_xml,2); /* ************************************************************************ */ neko-2-2-0/libs/ui/000077500000000000000000000000001321613172000140075ustar00rootroot00000000000000neko-2-2-0/libs/ui/CMakeLists.txt000066400000000000000000000011611321613172000165460ustar00rootroot00000000000000include(FindPkgConfig) ###################### # ui.ndll add_library(ui.ndll MODULE ui.c) target_link_libraries(ui.ndll libneko) if(APPLE) find_library(CARBON_LIBRARY Carbon REQUIRED) target_link_libraries(ui.ndll ${CARBON_LIBRARY}) elseif(UNIX) pkg_check_modules(GTK2 REQUIRED gtk+-2.0) target_include_directories(ui.ndll PRIVATE ${GTK2_INCLUDEDIR} ${GTK2_INCLUDE_DIRS} ) target_link_libraries(ui.ndll ${GTK2_LIBRARIES}) endif() set_target_properties(ui.ndll PROPERTIES PREFIX "" OUTPUT_NAME ui SUFFIX .ndll ) install ( TARGETS ui.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/ui/ui.c000066400000000000000000000150631321613172000145750ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #define HEADER_IMPORTS #include #include #if defined(NEKO_WINDOWS) # include # define CLASS_NAME "Neko_UI_wnd_class" # define WM_SYNC_CALL (WM_USER + 101) #elif defined(NEKO_MAC) # undef lock_acquire # undef lock_release # undef lock_try # include # include # define UIEvent 0xFFFFAA00 # define eCall 0x0 enum { pFunc = 'func' }; #else # include # include # include # include #endif /**

UI

Core native User Interface support. This API uses native WIN32 API on Windows, Carbon API on OSX, and GTK2 on Linux.

**/ typedef struct { int init_done; #if defined(NEKO_WINDOWS) DWORD tid; HWND wnd; #elif defined(NEKO_MAC) pthread_t tid; #else pthread_t tid; pthread_mutex_t lock; #endif } ui_data; static ui_data data = { 0 }; #if defined(NEKO_WINDOWS) static LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { switch( msg ) { case WM_SYNC_CALL: { value *r = (value*)lparam; value f = *r; free_root(r); // There are some GC issues here when having a lot of threads // It seems that somehow the function is not called, it might // also trigger some crashes. val_call0(f); return 0; }} return DefWindowProc(hwnd,msg,wparam,lparam); } #elif defined(NEKO_MAC) static OSStatus nothing() { return 0; } static OSStatus handleEvents( EventHandlerCallRef ref, EventRef e, void *data ) { switch( GetEventKind(e) ) { case eCall: { value *r; value f; GetEventParameter(e,pFunc,typeVoidPtr,0,sizeof(void*),0,&r); f = *r; free_root(r); val_call0(f); break; }} return 0; } #elif defined(NEKO_LINUX) static gint onSyncCall( gpointer data ) { value *r = (value*)data; value f = *r; free_root(r); val_call0(f); return FALSE; } #endif DEFINE_ENTRY_POINT(ui_main); void ui_main() { if( data.init_done ) return; data.init_done = 1; # if defined(NEKO_WINDOWS) { WNDCLASSEX wcl; HINSTANCE hinst = GetModuleHandle(NULL); memset(&wcl,0,sizeof(wcl)); wcl.cbSize = sizeof(WNDCLASSEX); wcl.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wcl.lpfnWndProc = WindowProc; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hInstance = hinst; wcl.hIcon = NULL; wcl.hCursor = LoadCursor(NULL, IDC_ARROW); wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); wcl.lpszMenuName = ""; wcl.lpszClassName = CLASS_NAME; wcl.hIconSm = 0; RegisterClassEx(&wcl); } data.tid = GetCurrentThreadId(); data.wnd = CreateWindow(CLASS_NAME,"",0,0,0,0,0,NULL,NULL,NULL,NULL); # elif defined(NEKO_MAC) MPCreateTask(nothing,NULL,0,0,0,0,0,NULL); // creates a MPTask that will enable Carbon MT data.tid = pthread_self(); EventTypeSpec ets = { UIEvent, eCall }; InstallEventHandler(GetApplicationEventTarget(),NewEventHandlerUPP(handleEvents),1,&ets,0,0); # elif defined(NEKO_LINUX) gdk_threads_init(); gtk_init(NULL,NULL); setlocale(LC_NUMERIC,"POSIX"); // prevent broking atof() data.tid = pthread_self(); pthread_mutex_init(&data.lock,NULL); # endif } /** ui_is_main : void -> bool Tells if the current thread is the main loop thread or not. The main loop thread is the one in which the first "ui" library primitive has been loaded. **/ static value ui_is_main() { # ifdef NEKO_WINDOWS return alloc_bool(data.tid == GetCurrentThreadId()); # else return alloc_bool(pthread_equal(data.tid,pthread_self())); # endif } /** ui_loop : void -> void Starts the native UI event loop. This method can only be called from the main thread. **/ static value ui_loop() { if( !val_bool(ui_is_main()) ) neko_error(); # if defined(NEKO_WINDOWS) { MSG msg; while( GetMessage(&msg,NULL,0,0) ) { TranslateMessage(&msg); DispatchMessage(&msg); if( msg.message == WM_QUIT ) break; } } # elif defined(NEKO_MAC) RunApplicationEventLoop(); # else gtk_main(); # endif return val_null; } /** ui_stop_loop : void -> void Stop the native UI event loop. This method can only be called from the main thread. **/ static value ui_stop_loop() { if( !val_bool(ui_is_main()) ) neko_error(); # if defined(NEKO_WINDOWS) while( !PostMessage(data.wnd,WM_QUIT,0,0) ) Sleep(100); # elif defined(NEKO_MAC) QuitApplicationEventLoop(); # else gtk_main_quit(); # endif return val_null; } /** ui_sync : callb:(void -> void) -> void Queue a method call [callb] to be executed by the main thread while running the UI event loop. This can be used to perform UI updates in the UI thread using results processed by another thread. **/ static value ui_sync( value f ) { value *r; val_check_function(f,0); r = alloc_root(1); *r = f; # if defined(NEKO_WINDOWS) while( !PostMessage(data.wnd,WM_SYNC_CALL,0,(LPARAM)r) ) Sleep(100); # elif defined(NEKO_MAC) EventRef e; CreateEvent(NULL,UIEvent,eCall,GetCurrentEventTime(),kEventAttributeUserEvent,&e); SetEventParameter(e,pFunc,typeVoidPtr,sizeof(void*),&r); PostEventToQueue(GetMainEventQueue(),e,kEventPriorityStandard); ReleaseEvent(e); # elif defined(NEKO_LINUX) // the lock should not be needed because GTK is MT-safe // however the GTK lock mechanism is a LOT slower than // using a pthread_mutex pthread_mutex_lock(&data.lock); gtk_timeout_add( 0, onSyncCall, (gpointer)r ); pthread_mutex_unlock(&data.lock); # endif return val_null; } DEFINE_PRIM(ui_loop,0); DEFINE_PRIM(ui_stop_loop,0); DEFINE_PRIM(ui_is_main,0); DEFINE_PRIM(ui_sync,1); /* ************************************************************************ */ neko-2-2-0/libs/zlib/000077500000000000000000000000001321613172000143325ustar00rootroot00000000000000neko-2-2-0/libs/zlib/CMakeLists.txt000066400000000000000000000040141321613172000170710ustar00rootroot00000000000000include(FindPkgConfig) ###################### # zlib.ndll add_library(zlib.ndll MODULE zlib.c) if (STATIC_ZLIB) set(ZLIB_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libs/src/install-prefix -Wno-dev ) if (UNIX) list(APPEND ZLIB_CMAKE_ARGS -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} ${ARG_PIC} ) endif() if (WIN32) set(ZLIB_LIBRARIES optimized ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/zlibstatic.lib debug ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/zlibstaticd.lib ) else() set(ZLIB_LIBRARIES ${CMAKE_BINARY_DIR}/libs/src/install-prefix/lib/libz.a) endif() # Get the current config. Borrowed from # https://github.com/Kitware/CMake/blob/bc7d64f896d6e180970cb404cc7699732db34adc/Modules/ExternalProject.cmake if (CMAKE_CFG_INTDIR AND NOT CMAKE_CFG_INTDIR STREQUAL "." AND NOT CMAKE_CFG_INTDIR MATCHES "\\$") set(config ${CMAKE_CFG_INTDIR}) else() set(config $) endif() ExternalProject_Add(Zlib ${EP_CONFIGS} URL http://zlib.net/zlib-1.2.11.tar.gz URL_MD5 1c9f62f0778697a09d36121ead88e08e CMAKE_ARGS ${ZLIB_CMAKE_ARGS} INSTALL_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/Zlib-build && ${CMAKE_COMMAND} --build . --target install --config ${config} BYPRODUCTS ${ZLIB_LIBRARIES} ) set_target_properties(Zlib PROPERTIES ${EP_PROPS}) set(ZLIB_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/libs/src/install-prefix/include) add_dependencies(zlib.ndll Zlib) target_include_directories(zlib.ndll PRIVATE ${ZLIB_INCLUDE_DIRS}) # Download project for fat source archive add_dependencies(download_static_deps Zlib-download) else() pkg_check_modules(ZLIB REQUIRED zlib) target_include_directories(zlib.ndll PRIVATE ${ZLIB_INCLUDEDIR} ${ZLIB_INCLUDE_DIRS}) endif() target_link_libraries(zlib.ndll libneko ${ZLIB_LIBRARIES}) set_target_properties(zlib.ndll PROPERTIES PREFIX "" OUTPUT_NAME zlib SUFFIX .ndll ) install ( TARGETS zlib.ndll DESTINATION ${DEST_NDLL} ) install(SCRIPT ${NEKO_FLATTEN_SCRIPT}) neko-2-2-0/libs/zlib/zlib.c000066400000000000000000000205671321613172000154500ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include /**

ZLib

Give access to the popular ZLib compression library, used in several file formats such as ZIP and PNG.

**/ DEFINE_KIND(k_stream_def); DEFINE_KIND(k_stream_inf); #define val_stream(v) ((z_stream *)val_data(v)) #define val_flush(s) *((int*)(((char*)s)+sizeof(z_stream))) static field id_read, id_write, id_done; DEFINE_ENTRY_POINT(zlib_main); void zlib_main() { id_read = val_id("read"); id_write = val_id("write"); id_done = val_id("done"); } static void free_stream_def( value v ) { z_stream *s = val_stream(v); deflateEnd(s); // no error free(s); val_kind(v) = NULL; val_gc(v,NULL); } static void free_stream_inf( value v ) { z_stream *s = val_stream(v); inflateEnd(s); // no error free(s); val_kind(v) = NULL; val_gc(v,NULL); } static void zlib_error( z_stream *z, int err ) { buffer b = alloc_buffer("ZLib Error : "); if( z && z->msg ) { buffer_append(b,z->msg); buffer_append(b," ("); } val_buffer(b,alloc_int(err)); if( z && z->msg ) buffer_append_char(b,')'); val_throw(buffer_to_string(b)); } /** deflate_init : level:int -> 'dstream Open a compression stream with the given level of compression **/ static value deflate_init( value level ) { z_stream *z; value s; int err; val_check(level,int); z = (z_stream*)malloc(sizeof(z_stream) + sizeof(int)); memset(z,0,sizeof(z_stream)); val_flush(z) = Z_NO_FLUSH; if( (err = deflateInit(z,val_int(level))) != Z_OK ) { free(z); zlib_error(NULL,err); } s = alloc_abstract(k_stream_def,z); val_gc(s,free_stream_def); return s; } /** deflate_buffer : 'dstream -> src:string -> srcpos:int -> dst:string -> dstpos:int -> { done => bool, read => int, write => int } **/ static value deflate_buffer( value s, value src, value srcpos, value dst, value dstpos ) { z_stream *z; int slen, dlen, err; value o; val_check_kind(s,k_stream_def); val_check(src,string); val_check(srcpos,int); val_check(dst,string); val_check(dstpos,int); z = val_stream(s); if( val_int(srcpos) < 0 || val_int(dstpos) < 0 ) neko_error(); slen = val_strlen(src) - val_int(srcpos); dlen = val_strlen(dst) - val_int(dstpos); if( slen < 0 || dlen < 0 ) neko_error(); z->next_in = (Bytef*)(val_string(src) + val_int(srcpos)); z->next_out = (Bytef*)(val_string(dst) + val_int(dstpos)); z->avail_in = slen; z->avail_out = dlen; if( (err = deflate(z,val_flush(z))) < 0 ) zlib_error(z,err); z->next_in = NULL; z->next_out = NULL; o = alloc_object(NULL); alloc_field(o,id_done,alloc_bool(err == Z_STREAM_END)); alloc_field(o,id_read,alloc_int(slen - z->avail_in)); alloc_field(o,id_write,alloc_int(dlen - z->avail_out)); return o; } /** deflate_end : 'dstream -> void Close a compression stream **/ static value deflate_end( value s ) { val_check_kind(s,k_stream_def); free_stream_def(s); return val_null; } /** inflate_init : window_size:int? -> 'istream Open a decompression stream **/ static value inflate_init( value wsize ) { z_stream *z; value s; int err; int wbits; if( val_is_null(wsize) ) wbits = MAX_WBITS; else { val_check(wsize,int); wbits = val_int(wsize); } z = (z_stream*)malloc(sizeof(z_stream) + sizeof(int)); memset(z,0,sizeof(z_stream)); val_flush(z) = Z_NO_FLUSH; if( (err = inflateInit2(z,wbits)) != Z_OK ) { free(z); zlib_error(NULL,err); } s = alloc_abstract(k_stream_inf,z); val_gc(s,free_stream_inf); return s; } /** inflate_buffer : 'istream -> src:string -> srcpos:int -> dst:string -> dstpos:int -> { done => bool, read => int, write => int } **/ static value inflate_buffer( value s, value src, value srcpos, value dst, value dstpos ) { z_stream *z; int slen, dlen, err; value o; val_check_kind(s,k_stream_inf); val_check(src,string); val_check(srcpos,int); val_check(dst,string); val_check(dstpos,int); z = val_stream(s); if( val_int(srcpos) < 0 || val_int(dstpos) < 0 ) neko_error(); slen = val_strlen(src) - val_int(srcpos); dlen = val_strlen(dst) - val_int(dstpos); if( slen < 0 || dlen < 0 ) neko_error(); z->next_in = (Bytef*)(val_string(src) + val_int(srcpos)); z->next_out = (Bytef*)(val_string(dst) + val_int(dstpos)); z->avail_in = slen; z->avail_out = dlen; if( (err = inflate(z,val_flush(z))) < 0 ) zlib_error(z,err); z->next_in = NULL; z->next_out = NULL; o = alloc_object(NULL); alloc_field(o,id_done,alloc_bool(err == Z_STREAM_END)); alloc_field(o,id_read,alloc_int(slen - z->avail_in)); alloc_field(o,id_write,alloc_int(dlen - z->avail_out)); return o; } /** inflate_end : 'istream -> void Close a decompression stream **/ static value inflate_end( value s ) { val_check_kind(s,k_stream_inf); free_stream_inf(s); return val_null; } /** set_flush_mode : 'stream -> string -> void Change the flush mode ("NO","SYNC","FULL","FINISH","BLOCK") **/ static value set_flush_mode( value s, value flush ) { int f; if( !val_is_kind(s,k_stream_inf) ) val_check_kind(s,k_stream_def); val_check(flush,string); if( strcmp(val_string(flush),"NO") == 0 ) f = Z_NO_FLUSH; else if( strcmp(val_string(flush),"SYNC") == 0 ) f = Z_SYNC_FLUSH; else if( strcmp(val_string(flush),"FULL") == 0 ) f = Z_FULL_FLUSH; else if( strcmp(val_string(flush),"FINISH") == 0 ) f = Z_FINISH; else if( strcmp(val_string(flush),"BLOCK") == 0 ) f = Z_BLOCK; else neko_error(); val_flush(val_stream(s)) = f; return val_null; } /** get_adler32 : 'stream -> 'int32 Returns the adler32 value of the stream **/ static value get_adler32( value s ) { if( !val_is_kind(s,k_stream_inf) ) val_check_kind(s,k_stream_def); return alloc_int32(val_stream(s)->adler); } /** update_adler32 : adler:'int32 -> string -> pos:int -> len:int -> 'int32 Update an adler32 value with a substring **/ static value update_adler32( value adler, value s, value pos, value len ) { val_check(adler,int32); val_check(s,string); val_check(pos,int); val_check(len,int); if( val_int(pos) < 0 || val_int(len) < 0 || val_int(pos) + val_int(len) > val_strlen(s) ) neko_error(); return alloc_int32(adler32(val_int32(adler),(Bytef*)(val_string(s)+val_int(pos)),val_int(len))); } /** update_crc32 : crc:'int32 -> string -> pos:int -> len:int -> 'int32 Update a CRC32 value with a substring **/ static value update_crc32( value crc, value s, value pos, value len ) { val_check(crc,int32); val_check(s,string); val_check(pos,int); val_check(len,int); if( val_int(pos) < 0 || val_int(len) < 0 || val_int(pos) + val_int(len) > val_strlen(s) ) neko_error(); return alloc_int32(crc32(val_int32(crc),(Bytef*)(val_string(s)+val_int(pos)),val_int(len))); } /** deflate_bound : 'dstream -> n:int -> int Return the maximum buffer size needed to write [n] bytes **/ static value deflate_bound( value s, value size ) { val_check_kind(s,k_stream_def); val_check(size,int); return alloc_int(deflateBound(val_stream(s),val_int(size))); } DEFINE_PRIM(deflate_init,1); DEFINE_PRIM(deflate_buffer,5); DEFINE_PRIM(deflate_end,1); DEFINE_PRIM(inflate_init,1); DEFINE_PRIM(inflate_buffer,5); DEFINE_PRIM(inflate_end,1); DEFINE_PRIM(set_flush_mode,2); DEFINE_PRIM(deflate_bound,2); DEFINE_PRIM(get_adler32,1); DEFINE_PRIM(update_adler32,4); DEFINE_PRIM(update_crc32,4); /* ************************************************************************ */ neko-2-2-0/src/000077500000000000000000000000001321613172000132305ustar00rootroot00000000000000neko-2-2-0/src/benchs/000077500000000000000000000000001321613172000144725ustar00rootroot00000000000000neko-2-2-0/src/benchs/ackerman.neko000066400000000000000000000004531321613172000171330ustar00rootroot00000000000000ack = function(x,y) { if( x == 0 ) return y + 1; if( y == 0 ) return ack(x-1,1); return ack(x-1,ack(x,y-1)); }; var arg1 = $int($loader.args[1]); var arg2 = $int($loader.args[0]); if( arg1 == null ) arg1 = 3; if( arg2 == null ) arg2 = 4; $print("Ack(",arg1,",",arg2,"): ",ack(arg1,arg2),"\n"); neko-2-2-0/src/benchs/binary-trees.neko000066400000000000000000000020731321613172000177560ustar00rootroot00000000000000/* The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Nicolas Cannasse */ make = function(i,d) { if( d == 0 ) return $array(i,null,null); var i2 = 2 * i; d -= 1; $array(i,make(i2-1,d),make(i2,d)); }; check = function(n) { if( n[1] == null ) return n[0]; return n[0] + check(n[1]) - check(n[2]); } var arg = $int($loader.args[0]); if( arg == null ) arg = 10; var min_depth = 4; var max_depth = if( min_depth + 2 < arg ) arg else min_depth + 2; var stretch_depth = max_depth + 1 var c = check(make(0,stretch_depth)); $print("stretch tree of depth ",stretch_depth,"\t check: ",c,"\n"); var long_lived_tree = make(0,max_depth); loop_depths = function(d) { if( d <= max_depth ) { var niter = 1 << (max_depth - d + min_depth); var c = 0; var i = 0; while( i < niter ) { i += 1; c += check(make(i,d))+check(make(0-i,d)); } $print(2*niter,"\t trees of depth ",d,"\t check: ",c,"\n"); loop_depths(d + 2); } } loop_depths(min_depth); $print("long lived tree of depth ",max_depth,"\t check: ",check(long_lived_tree),"\n"); neko-2-2-0/src/benchs/fannkuch.neko000066400000000000000000000022501321613172000171440ustar00rootroot00000000000000/* The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Nicolas Cannasse */ var n = $int($loader.args[0]); if( n == null ) n = 7; check = 0; perm = $amake(n); perm1 = $amake(n); count = $amake(n); maxPerm = $amake(n); maxflips = 0; m = n - 1; r = n; i = 0; while( i < n ) { perm1[i] = i; i += 1 }; while (true) { if( check < 30 ) { i = 0; while( i < n ) { $print(perm1[i]+1); i += 1; }; $print("\n"); check += 1; } while( r != 1 ) { count[r-1] = r; r -= 1; }; if( perm1[0] != 0 && perm1[m] != m ) { i = 0; while( i < n ) { perm[i] = perm1[i]; i += 1; }; flips = 0; k = perm[0]; do { i = 1; j = k - 1; while( i < j ) { tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp; i += 1; j -= 1; } flips += 1; j = perm[k]; perm[k] = k; k = j; } while( k != 0 ); if( flips > maxflips ) maxflips = flips; } while (true) { if( r == n ) { $print("Pfannkuchen(",n,") = ",maxflips,"\n"); $goto(exit); } perm0 = perm1[0]; i = 0; while( i < r ) { j = i + 1; perm1[i] = perm1[j]; i = j; } perm1[r] = perm0; count[r] -= 1; if( count[r] > 0 ) break; r += 1; } } exit: neko-2-2-0/src/benchs/fib.neko000066400000000000000000000002631321613172000161110ustar00rootroot00000000000000fib = function(n) { if( n <= 1 ) return 1; return fib(n-1) + fib(n-2); }; var arg = $int($loader.args[0]); if( arg == null ) arg = 30; $print("fib(",arg,") = ",fib(arg),"\n"); neko-2-2-0/src/benchs/fp.neko000066400000000000000000000002301321613172000157500ustar00rootroot00000000000000var x = 1.0; var y = 1.0; var i = $float($loader.args[0]); while( i > 0.0 ) { x *= 1.000000001; y /= 1.000000001; i -= 1.0; } $print(x,"\n",y,"\n"); neko-2-2-0/src/benchs/module.neko000066400000000000000000000003001321613172000166260ustar00rootroot00000000000000var arg = $int($loader.args[0]); if( arg == null ) arg = 100; $loader.args = $array(); while( arg > 0 ) { $loader.cache = $new(null); $loader.loadmodule("boot/nekoc.n",$loader); arg -= 1; }neko-2-2-0/src/benchs/nbodies.neko000066400000000000000000000070771321613172000170060ustar00rootroot00000000000000/* The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Nicolas Cannasse */ pi = 3.141592653589793; solar_mass = (4 * pi * pi); days_per_year = 365.24; sqrt = $loader.loadprim("std@math_sqrt",1); round = $loader.loadprim("std@math_round",1); advance = function(nbodies,bodies,dt) { var i = 0,j; while( i < nbodies ) { var b = bodies[i]; i += 1; j = i; while( j < nbodies ) { var b2 = bodies[j]; var dx = b.x - b2.x; var dy = b.y - b2.y; var dz = b.z - b2.z; var dist = sqrt(dx*dx+dy*dy+dz*dz); var mag = dt / (dist * dist * dist); var bm = b.mass * mag; var b2m = b2.mass * mag; b.vx -= dx * b2m; b.vy -= dy * b2m; b.vz -= dz * b2m; b2.vx += dx * bm; b2.vy += dy * bm; b2.vz += dz * bm; j += 1; } } i = 0; while( i < nbodies ) { var b = bodies[i]; b.x += dt * b.vx; b.y += dt * b.vy; b.z += dt * b.vz; i += 1; } } energy = function(nbodies,bodies) { var e = 0, i = 0, j; while( i < nbodies ) { var b = bodies[i]; e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz); i += 1; j = i; while( j < nbodies ) { var b2 = bodies[j]; var dx = b.x - b2.x; var dy = b.y - b2.y; var dz = b.z - b2.z; var dist = sqrt(dx*dx+dy*dy+dz*dz); e -= (b.mass * b2.mass) / dist; j += 1; } } return e; }; offset_momentum = function(nbodies,bodies) { var px = 0, py = 0, pz = 0; var i = 0; while( i < nbodies ) { var b = bodies[i]; px += b.vx * b.mass; py += b.vy * b.mass; pz += b.vz * b.mass; i += 1; } var b = bodies[0]; b.vx = 0 - px / solar_mass; b.vy = 0 - py / solar_mass; b.vz = 0 - pz / solar_mass; } ; var bodies = $array( // sun { x => 0, y => 0, z => 0, vx => 0, vy => 0, vz => 0, mass => solar_mass }, // jupiter { x => $float("4.84143144246472090e+00"), y => $float("-1.16032004402742839e+00"), z => $float("-1.03622044471123109e-01"), vx => $float("1.66007664274403694e-03") * days_per_year, vy => $float("7.69901118419740425e-03") * days_per_year, vz => $float("-6.90460016972063023e-05") * days_per_year, mass => $float("9.54791938424326609e-04") * solar_mass }, // saturn { x => $float("8.34336671824457987e+00"), y => $float("4.12479856412430479e+00"), z => $float("-4.03523417114321381e-01"), vx => $float("-2.76742510726862411e-03") * days_per_year, vy => $float("4.99852801234917238e-03") * days_per_year, vz => $float("2.30417297573763929e-05") * days_per_year, mass => $float("2.85885980666130812e-04") * solar_mass }, // uranus { x => $float("1.28943695621391310e+01"), y => $float("-1.51111514016986312e+01"), z => $float("-2.23307578892655734e-01"), vx => $float("2.96460137564761618e-03") * days_per_year, vy => $float("2.37847173959480950e-03") * days_per_year, vz => $float("-2.96589568540237556e-05") * days_per_year, mass => $float("4.36624404335156298e-05") * solar_mass }, // neptune { x => $float("1.53796971148509165e+01"), y => $float("-2.59193146099879641e+01"), z => $float("1.79258772950371181e-01"), vx => $float("2.68067772490389322e-03") * days_per_year, vy => $float("1.62824170038242295e-03") * days_per_year, vz => $float("-9.51592254519715870e-05") * days_per_year, mass => $float("5.15138902046611451e-05") * solar_mass } ); var nbodies = $asize(bodies); display = function() { var prec = $float("1e+09"); var e = energy(nbodies,bodies) * prec; $print(round(e)/prec,"\n"); } var n = $int($loader.args[0]); if( n == null ) n = 1000; offset_momentum(nbodies, bodies); display(); var i = 0; while( i < n ) { advance(nbodies,bodies,0.01); i += 1; }; display(); neko-2-2-0/src/benchs/nsieve.neko000066400000000000000000000011411321613172000166360ustar00rootroot00000000000000/* The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Nicolas Cannasse */ fmt = function(i) { var s = $string(i); while( $ssize(s) < 8 ) s = " "+s; return s; } nsieve = function(m) { var a = $amake(m); var count = 0; var i = 2; while( i < m ) { if $not(a[i]) { count += 1; var j = (i << 1); while( j < m ) { if( $not(a[j]) ) a[j] = true; j += i; } } i += 1; } $print("Primes up to ",fmt(m)," ",fmt(count),"\n"); } var n = $int($loader.args[0]); if( n == null ) n = 2; var i = 0; while( i < 3 ) { nsieve(10000 << (n - i)); i += 1; } neko-2-2-0/src/benchs/recursive.neko000066400000000000000000000016711321613172000173640ustar00rootroot00000000000000/* The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Nicolas Cannasse */ ack = function(x,y) { if( x == 0 ) return y + 1; if( y == 0 ) return ack(x - 1,1); return ack(x - 1,ack(x,y - 1)); } fib = function(n) { if( n < 2 ) return 1; return fib(n-2) + fib(n-1); } fib_fp = function(n) { if( n < 2.0 ) return 1.0; return fib_fp(n - 2.0) + fib_fp(n - 1.0); } tak = function(x,y,z) { if( y >= x ) return z; return tak(tak(x-1,y,z),tak(y-1,z,x),tak(z-1,x,y)); } tak_fp = function(x,y,z) { if( y >= x ) return z; return tak_fp(tak_fp(x-1.0,y,z),tak_fp(y-1.0,z,x),tak_fp(z-1.0,x,y)); } var n = $int($loader.args[0]); if( n == null ) n = 4; n -= 1; $print("Ack(3,",n + 1,"): ",ack(3,n + 1),"\n"); $print("Fib(",n + 28.0,".0): ",fib_fp(n + 28.0),".0\n"); $print("Tak(",3*n,",",2*n,",",n,"): ",tak(3*n,2*n,n),"\n"); $print("Fib(",3,"): ",fib(3),"\n"); $print("Tak(3.0,2.0,1.0): ",tak_fp(3.0,2.0,1.0),".0\n"); neko-2-2-0/src/benchs/startup.neko000066400000000000000000000002101321613172000170430ustar00rootroot00000000000000/* The Computer Language Shootout http://shootout.alioth.debian.org/ contributed by Nicolas Cannasse */ $print("hello world\n"); neko-2-2-0/src/benchs/test_ops.neko000066400000000000000000000022531321613172000172120ustar00rootroot00000000000000 eq = function(a,b) { if( a != b ) $print(a," should be ",b,"\n") else $print(".") } eq($string(1),"1"); eq($string(0xFFFFFFFF),"-1"); o = $new(null); o.__add = function(x) return x + 66; o.__radd = function(x) return x + 77; o.__sub = function(x) return x - 66; o.__rsub = function(x) return x - 77; var small = 0x7FFF; var med = 0x7FFF0000; var less = 0x80000000; var spe1 = 0xC0000000; eq($string(small),"32767"); eq($string(med),"2147418112"); eq($string(less),"-2147483648"); eq($string(spe1),"-1073741824"); $print("\n"); eq(small<<16,med); eq(small<<17,-131072); eq(med+0x10000,less); var low = 0xC000; eq(low<<16,spe1); var low = 0xA000; eq(low<<16,0xA0000000); eq(small*small,1073676289); eq(small*small*small,1073840127); eq(small*small*small*med,65536); eq(med+med,-131072); eq(o + 1, 67); eq(1 + o, 78); eq(o + "x", "x66"); eq("x" + o, "x77"); eq( med + 1.1, 2147418113.1 ); eq( 1.1 + med, 2147418113.1 ); eq( 1 - 1.25, -0.25 ); eq( 1.25 - 1, 0.25 ); eq( med - 1, 2147418111 ); eq( 1 - med, -2147418111 ); eq( med - 1.25, 2147418110.75 ); eq( 1.25 - med, -2147418110.75 ); eq( o - 1, -65 ); eq( 1 - o, -76 ); neko-2-2-0/src/core/000077500000000000000000000000001321613172000141605ustar00rootroot00000000000000neko-2-2-0/src/core/Args.nml000066400000000000000000000045121321613172000155660ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type argtype { Void : void -> void; String : string -> void; Int : int -> void; } exception Invalid; function help(head,decl) { print head; print "\n Options :\n"; List.iter (function((name,_,help)) { printf " %s %s\n" (name,help); }) decl; Sys.exit(1) } function parse_args(args,head,decl,def) { var i = &0; var l = Array.length args; var h = Hashtbl.create(); var hdecl = Void (function() { help head decl }); Hashtbl.add h "-help" hdecl; Hashtbl.add h "--help" hdecl; List.iter (function((name,decl,_)) { Hashtbl.add h name decl; }) decl; try { while *i < l { var arg = args.[*i]; i := *i + 1; var d = try { Hashtbl.find h arg; } catch { Not_found -> Void (function() { def arg }) }; match d { | Void f -> f() | String f -> if *i == l then throw Invalid; var param = args.[*i]; i := *i + 1; f param | Int f -> if *i == l then throw Invalid; var param = args.[*i]; i := *i + 1; var pval = try { int param } catch { _ -> throw Invalid }; f pval } } } catch { Invalid -> var arg = args.[*i - 1]; print "Invalid argument : "; print arg; print "\n"; help head decl } } function parse(head,decl,def) { parse_args(Sys.args(),head,decl,def); } neko-2-2-0/src/core/Array.nml000066400000000000000000000074461321613172000157610ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ function string( a : 'a array ) : string { neko(" var s = '['; var items = a[0]; var l = a[2]; var i = 0; while i < l { s = s + @Core.string(items[i]); i = i + 1; if i < l s = s + ', '; } s = s + ']'; s "); }; neko(" @make = function(a) { $array(a,string,$asize(a)); }; @merge_sort = $loader.loadprim('std@merge_sort',3); $exports.@make = @make; "); function length( a : 'a array ) : int { neko("a[2]"); } function create() : 'a array { neko("$array($array(),string,0)"); } function add( a : 'a array, x : 'a ) : void { neko(" var k = a[0]; var n = a[2]; if( $asize(k) == n ) { k = $amake(n*2+1); $ablit(k,0,a[0],0,n); a[0] = k; } k[n] = x; a[2] = n + 1; "); } function get( a : 'a array, p : int ) : 'a { a.[p] } function set( a : 'a array, p : int, x : 'a ) : void { a.[p] := x; } function make( size : int, x : 'a ) : 'a array { neko(" var a = $amake(size); var i = 0; while( i < size ) { a[i] = x; i = i + 1; } $array(a,string,size) "); } function init( size : int, f : int -> 'a ) : 'a array { neko(" var a = $amake(size); var i = 0; while( i < size ) { a[i] = $apply(f,i); i = i + 1; } $array(a,string,size) "); } function iter( f : 'a -> void, a : 'a array ) : void { neko(" var l = a[2]; var i = 0; a = a[0]; while (i < l) { f(a[i]); i = i + 1; } "); } function iteri( f : int -> 'a -> void, a : 'a array ) : void { neko(" var l = a[2]; var i = 0; a = a[0]; while (i < l) { f(i,a[i]); i = i + 1; } "); } function map( f : 'a -> 'b, a : 'a array ) : 'b array { neko(" var l = a[2]; var i = 0; var a2 = $amake(l); a = a[0]; while i < l { a2[i] = $apply(f,a[i]); i = i + 1; } $array(a2,string,l); "); } function sort( f : 'a -> 'a -> int, a : 'a array ) : void { neko(" @merge_sort(a[0],a[2],f) "); } function list( a : 'a array ) : 'a list { neko(" var i = a[2]; var l = @Core.@empty; a = a[0]; while i > 0 { i = i - 1; l = @Core.@cons(a[i],l); } l "); } function append( src : 'a array, dst : 'a array ) : void { neko(" var l = src[2]; var i = 0; src = src[0]; while i < l { add(dst,src[i]); i = i + 1; } "); } function sub( a : 'a array, p : int, l : int ) : 'a array { neko(" var al = a[2]; if( p + l > al ) $throw('$asub'); $array($asub(a[0],p,l),string,l) "); } function blit( dst : 'a array, pdst : int, src : 'a array, psrc : int, len : int ) { neko(" $ablit(dst[0],pdst,src[0],psrc,len) "); } function index( a : 'a array, it : 'a ) : int { neko(" var al = a[2]; a = a[0]; var i = 0; while( i < al ) { if( @Core.@compare(a[i],it) == 0 ) return i; i = i + 1; } "); throw Not_found } neko-2-2-0/src/core/Buffer.nml000066400000000000000000000035001321613172000160770ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type t; neko(" @buffer_new = $loader.loadprim('std@buffer_new',0); @buffer_add = $loader.loadprim('std@buffer_add',2); @buffer_add_sub = $loader.loadprim('std@buffer_add_sub',4); @buffer_add_char = $loader.loadprim('std@buffer_add_char',2); @buffer_string = $loader.loadprim('std@buffer_string',1); @buffer_reset = $loader.loadprim('std@buffer_reset',1); "); function create() : t { neko("@buffer_new()"); } function add(b:t,x : 'a) : void { neko("@buffer_add(b,x)"); } function reset(b:t) : void { neko("@buffer_reset(b)"); } var string : t -> string = neko("@buffer_string"); var add_sub : t -> string -> int -> int -> void = neko("@buffer_add_sub"); var add_char : t -> char -> void = neko("@buffer_add_char"); neko-2-2-0/src/core/Core.nml000066400000000000000000000141561321613172000155670ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type void; type int; type int32; type float; type char; type string; type error; type 'a array; type 'a ref; type 'a format; type 'a stream; type 'a option { None; Some : 'a; } type neko_value; exception Neko_error : neko_value; exception Invalid_argument : string; exception Assert_failure : (string,int); exception Error : string; exception Stream_error; exception Not_found; exception Exit; /* ----- theses are defined directly in the compiler because they need additional magic. type bool { true; false; } type 'a list { []; :: : ('a , 'a list); } val neko : string -> 'a ----- */ neko(" @sprintf = $loader.loadprim('std@sprintf',2); @string = function(x) { // tuples if( $typeof(x) == $tarray ) { // constructor var printer = x[1]; if( $typeof(printer) == $tfunction && $nargs(printer) == 1 ) return printer(x); var s = '('; var l = $asize(x); var i = 0; while i < l { s = s + @string(x[i]); i = i + 1; if i < l s = s + ', '; } s = s + ')'; return s; } // others return $string(x); } $exports.@print_record = function() { var o = $objfields(this); var s = '{ '; var i = 0; var l = $asize(o) - 1; while i < l { var f = o[i]; var fname = $field(f); if fname == '__string' l = l + 1; else s = s + fname + ' = ' + @string($objget(this,f))+'; '; i = i + 1; } s = s + '}'; s } $exports.@print_union = function(s,a) { var l = $asize(a); if l == 2 return s; var i = 2; s = s + '('; while i < l { s = s + @string(a[i]); i = i + 1; if i < l s = s + ', '; } s = s + ')'; return s; } @compare = function(a,b,history) { if( $pcompare(a,b) == 0 ) return 0; if( $typeof(a) == $tarray ) { var l1 = $asize(a); var l2 = $asize(b); if( l1 != l2 ) return $compare(l1,l2); var h = history; while h != null { if( h[0] == a && h[1] == b ) return $pcompare(a,b); h = h[2]; } var i = 0; while i < l1 { var k = @compare(a[i],b[i],$array(a,b,history)); if( k != 0 ) return k; i = i + 1; } return 0; } if( $typeof(a) == $tobject ) { var h = history; while h != null { if( h[0] == a && h[1] == b ) return $pcompare(a,b); h = h[2]; } var o = $objfields(a); var i = 0; var l = $asize(o); while i < l { var v = $objget(b,o[i]); var k = @compare($objget(a,o[i]),v,$array(a,b,history)); if( k != 0 ) return k; i = i + 1; } return 0; } return $compare(a,b); } $exports.@compare = function(a,b) { @compare(a,b,null) }; $exports.@aget = function(a,i) { if( i < 0 || i >= a[2] ) $exports.invalid_arg('Array.get'); a[0][i] } $exports.@aset = function(a,i,v) { if( i < 0 || i >= a[2] ) $exports.invalid_arg('Array.set'); a[0][i] = v; } @empty = $array(0,function(_){ '[]' }); @pcons = function(c) { @string(c[2]) + ' :: ' + @string(c[3]) }; @cons = function(x,l) { $array(1,@pcons,x,l) } $exports.@pcons = @pcons; $exports.@cons = @cons; $exports.@empty = @empty; "); function magic(x) { neko("x"); } function throw(x : error) : 'a { neko("$throw(x)"); } function assert(file,line) { throw Assert_failure(file,line) } function invalid_arg(fun) : 'a { throw Invalid_argument(fun); } function error(x : string) { throw Error(x) } function ignore(x) { } function fst((a,_)) { a } function snd((_,a)) { a } function int(x:string) : int { var i = neko("$int(x)"); if i == neko("null") then invalid_arg(); i } function float(x:string) : float { var i = neko("$float(x)"); if i == neko("null") then invalid_arg(); i } function ord(x:char) : int { neko("x"); } function chr(x:int) : char { if x < 0 || x > 255 then invalid_arg(); neko("x"); } function string(x : 'a) : string { neko("@string(x)"); } function nstring(x : 'a) : string { neko("$string(x)"); } function print(x) : void { neko("$print(string(x))"); } function nprint(x) : void { neko("$print(x)"); } function compare(x : 'a, y : 'a) : int { neko("$exports.@compare(x,y)"); } function min(x,y) { if x < y then x else y } function max(x,y) { if x < y then y else x } function sprintf(fmt : 'a format, p : 'a ) : string { neko("@sprintf(fmt,p)") } function printf(fmt : 'a format, p : 'a ) : void { print (sprintf fmt p) } function stream(f : void -> 'a ) : 'a stream { neko("{ get => f, pos => 0, cache => $array() }"); } function stream_token( s : 'a stream, x : int ) : 'a { if x < 0 then invalid_arg(); neko(" var tmp = s.cache[x]; if( tmp != null ) return tmp; var n = $asize(s.cache); var c = $amake(x + 1); $ablit(c,0,s.cache,0,n); while n <= x { c[n] = s.get(null); n = n + 1; } s.cache = c; return c[x]; "); } function stream_junk( s : 'a stream, x : int ) : void { if x < 0 then invalid_arg(); neko(" var c = $asize(s.cache); s.pos = s.pos + x; if( c >= x ) s.cache = $asub(s.cache,x,c - x); else { s.cache = $array(); x = x - c; while x > 0 { s.get(null); x = x - 1; } } "); } function stream_pos( s : 'a stream ) : int { neko("s.pos"); } neko-2-2-0/src/core/Hashtbl.nml000066400000000000000000000035241321613172000162610ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type ('a,'b) t; function hash(x:'a) : int { neko("$hkey(x)") } function create() : ('a,'b) t { neko("$hnew(0)") } function length(h : ('a,'b) t) : int { neko("$hcount(h)") } function find(h : ('a,'b) t,k : 'a) : 'b { var v = neko("$hget(h,k,@Core.@compare)"); if neko("v == null") then throw Not_found; v } function exists(h : ('a,'b) t,k : 'a) : bool { neko("$hmem(h,k,@Core.@compare)"); } function add(h : ('a,'b) t, k : 'a, v : 'b) : void { neko("$hadd(h,k,v)"); } function remove(h : ('a,'b) t,k : 'a) : void { neko("$hremove(h,k,@Core.@compare)"); } function replace(h : ('a,'b) t,k : 'a,v : 'b) : void { neko("$hset(h,k,v,@Core.@compare)"); } function iter(f : 'a -> 'b -> void,h : ('a,'b) t) : void { neko("$hiter(h,f)"); } neko-2-2-0/src/core/IO.nml000066400000000000000000000174501321613172000152060ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type file type input { mutable in_read : void -> char; mutable in_input : string -> int -> int -> int; mutable in_close : void -> void; } type output { mutable out_write : char -> void; mutable out_output : string -> int -> int -> int; mutable out_close : void -> void; mutable out_flush : void -> void; } exception Overflow : string; exception Eof; exception Closed; exception Blocked; /* ---------------------------- RAW FILE API ------------------------------- */ neko(" @load = function(name,nargs) { return $loader.loadprim('std@'+name,nargs); } "); var file_open : string -> string -> file = neko("@load('file_open',2)"); var file_contents : string -> string = neko("@load('file_contents',1)"); var file_close : file -> void = neko("@load('file_close',1)"); var file_read : file -> string -> int -> int -> int = neko("@load('file_read',4)"); var file_read_char : file -> char = neko("@load('file_read_char',1)"); var file_write : file -> string -> int -> int -> int = neko("@load('file_write',4)"); var file_write_char : file -> char -> void = neko("@load('file_write_char',2)"); var file_flush : file -> void = neko("@load('file_flush',1)"); function file_input(f) { { in_read = function() { try file_read_char(f) catch { _ -> throw Eof } }; in_input = function(s,p,l) { try file_read f s p l catch { _ -> throw Eof } }; in_close = function() { file_close(f) }; } } function read_file(path,bin) { var f = file_open(path,if bin then "rb" else "r"); file_input f } function read_string(str) { var p = &0; var len = String.length str; { in_read = function() { if *p == len then throw Eof; var c = String.get str (*p); p := *p + 1; c }; in_input = function(s,pp,l) { if *p == len then throw Eof; var l = min l (len - *p); String.blit s pp str (*p) l; p := *p + l; l }; in_close = function() { } } } function file_output(f) { { out_write = file_write_char f; out_output = file_write f; out_close = function() { file_close(f) }; out_flush = function() { file_flush(f) }; } } function write_file(path,bin) { var f = file_open(path,if bin then "wb" else "w"); file_output f } function write_string() { var b = Buffer.create(); var o = { out_write = Buffer.add_char b; out_output = function(s,pp,l) { Buffer.add_sub b s pp l; l }; out_close = function() { }; out_flush = function() { }; }; (o , function() { Buffer.string b }) } var file_stdin : file = neko("@load('file_stdin',0)()"); var file_stdout : file = neko("@load('file_stdout',0)()"); var file_stderr : file = neko("@load('file_stderr',0)()"); var stdin : input = file_input file_stdin; var stdout : output = file_output file_stdout; var stderr : output = file_output file_stderr; /* ---------------------------- INPUT API ------------------------------- */ function create_in(read,input,close) { { in_read = read; in_input = input; in_close = close; } } function read_char(i) { i.in_read() } function read_byte(i) { ord i.in_read() } function input(i,s,p,n) { var len = String.length s; if p < 0 || n < 0 || p > len || p + n > len then invalid_arg(); i.in_input s p n } function read(i,n) { if n < 0 then invalid_arg(); if n == 0 then "" else { var s = String.create n; var p = &0; var len = &n; while *len > 0 { var n = i.in_input s (*p) (*len); if n == 0 then throw Blocked; p := *p + n; len := *len - n; }; s } } function read_buf(i,n) { if n < 0 then invalid_arg(); if n == 0 then "" else { var s = String.create n; var p = &0; var len = &n; try { while *len > 0 { var n = i.in_input s (*p) (*len); if n == 0 then throw (if *p == 0 then Blocked else Eof); p := *p + n; len := *len - n; }; s } catch { Eof -> if *p == 0 then throw Eof; String.sub s 0 (*p) } } } function read_all(i : input) : string { var b = Buffer.create(); var maxlen = 4096; try { while true { Buffer.add b (read_buf i maxlen); } magic(); } catch { Eof -> Buffer.string b } } function read_line(i : input) : string { var buf = Buffer.create(); try { while true { var ch = i.in_read(); if ch == '\n' then throw Exit; Buffer.add_char buf ch; } assert() } catch { Exit -> Buffer.string buf } } function read_i32(i) : int { var ch1 = read_byte i; var ch2 = read_byte i; var ch3 = read_byte i; var ch4 = read_byte i; ch1 or (ch2 << 8) or (ch3 << 16) or (ch4 << 24) } function read_ui16(i) { var ch1 = read_byte i; var ch2 = read_byte i; ch1 or (ch2 << 8) } function read_ui24(i) { var ch1 = read_byte i; var ch2 = read_byte i; var ch3 = read_byte i; ch1 or (ch2 << 8) or (ch3 << 16) } function read_i16(i) { var ch1 = read_byte i; var ch2 = read_byte i; var n = ch1 or (ch2 << 8); if ch2 and 128 != 0 then n - 65536 else n } function close_in(i) { i.in_close(); i.in_read := function() { throw Closed }; i.in_input := function(s,p,l) { throw Closed }; i.in_close := function() { throw Closed }; } /* ---------------------------- OUTPUT API ------------------------------- */ function create_out(write,output,flush,close) { { out_write = write; out_output = output; out_flush = flush; out_close = close; } } function write_char(o : output, x : char) : void { o.out_write x } function write_byte(o : output, x : int) : void { o.out_write (chr (x and 255)) } function write_i8(o : output, x : int) : void { if x < 127 || x > 128 then invalid_arg(); write_byte o (x and 0xFF) } function output(o,s,p,n) { var len = String.length s; if p < 0 || n < 0 || p > len || p + n > len then invalid_arg(); o.out_output s p n } function write(o : output,x : string) : void { var p = &0; var len = &(String.length x); while *len > 0 { var n = o.out_output x (*p) (*len); if n == 0 then throw Blocked; p := *p + n; len := *len - n; } } function write_i32(o : output, x : int) : void { write_byte o x; write_byte o (x >> 8); write_byte o (x >> 16); write_byte o (x >>> 24) } function write_ui16(o : output, x : int) : void { if x < 0 || x > 0xFFFF then invalid_arg(); write_byte o x; write_byte o (x >> 8) } function write_i16(o : output, x : int) : void { if x < -0x7FFF || x > 0x7FFF then invalid_arg(); if x < 0 then write_ui16 o (65536 + x) else write_ui16 o x } function write_ui24(o : output, x : int) : void { if x < 0 || x > 0xFFFFFF then invalid_arg(); write_byte o x; write_byte o (x >> 8); write_byte o (x >> 16); } function flush(o) { o.out_flush(); } function close_out(o) { o.out_close(); o.out_flush := function() { throw Closed }; o.out_write := function(_) { throw Closed }; o.out_output := function(_,_,_) { throw Closed }; o.out_close := function() { throw Closed }; } function printf(o : output, fmt : 'a format, p : 'a ) : void { write o (sprintf fmt p) } neko-2-2-0/src/core/LexEngine.nml000066400000000000000000000201731321613172000165510ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* most of this code is taken from the ULex lexer by Alain Frish, originaly written as an OCaml library. */ type charset = (int , int) list type node { mutable id : int; mutable trans : (charset , node) list; mutable epsilon : node list; } type state = node list type tables = (int array array , int array) type t { Empty; Match : charset; Star : t; Plus : t; Next : (t , t); Choice : (t , t); } /* ------- charset ------ */ var max_code = 255; var cempty = []; var call = [(0,max_code)]; function is_empty(c) { c == [] } function rec cunion(c1,c2) { match (c1 , c2) { | ([] , _) -> c2 | (_ , []) -> c1 | (((i1,j1) as s1)::r1, (i2,j2)::r2) -> if i1 <= i2 then if j1 + 1 < i2 then s1::(cunion r1 c2) else if (j1 < j2) then cunion r1 ((i1,j2)::r2) else cunion c1 r2 else cunion c2 c1 | _ -> assert() } } function ccomplement(c) { function rec loop(start,l) { match l { | [] -> if start <= max_code then [(start,max_code)] else [] | (i,j) :: l -> (start,i-1) :: (loop (j + 1) l) } }; match c { | (-1,j) :: l -> loop (j + 1) l | l -> loop (-1) l } } function cinter(c1,c2) { ccomplement (cunion (ccomplement c1) (ccomplement c2)) } function cdiff(c1,c2) { ccomplement (cunion (ccomplement c1) c2) } /* ------- nodes -------- */ function node(g) { { id = g(); trans = []; epsilon = []; } } function rec add_node(state,node) { if List.exists (function(k) { k === node }) state then state else add_nodes (node::state) node.epsilon } function rec add_nodes(state,nodes) { List.fold add_node state nodes } function nodes(nfa) { var g = &0; var gen = function() { g := *g + 1; *g }; function rec loop(n,final) { match n { | Empty -> final | Match c -> var n = node gen; n.trans := [(c,final)]; n | Star a -> var n = node gen; var an = loop a n; n.epsilon := [an; final]; n | Plus a -> var n = node gen; var an = loop a n; n.epsilon := [an; final]; an | Next (a,b) -> loop a (loop b final) | Choice (a,b) -> var n = node gen; n.epsilon := [loop a final; loop b final]; n } }; Array.map (function(n) { var f = node gen; (loop n f,f) }) nfa } /* ------- NFA -> DFA -------- */ function transitions(state : state) { // Merge transition with the same target function rec norm(l) { match l { | (t1,n1) :: (((t2,n2) :: q) as l) -> if n1 === n2 then norm ((cunion t1 t2,n1) :: q) else (t1,n1) :: (norm l) | _ -> l } }; var t = List.concat (List.map (function(n) { n.trans }) state); var t = norm (List.sort (function((t1,n1),(t2,n2)) { n1.id - n2.id }) t); // Split char sets so as to make them disjoint function rec split((all,t),(c0,n0)) { var t = (cdiff c0 all, [n0]) :: List.append (List.map (function((c,ns)) { (cinter c c0, n0::ns) }) t) (List.map (function((c,ns)) { (cdiff c c0, ns) }) t); (cunion all c0, List.filter (function((c,ns)) { !is_empty c }) t) }; var _ , t = List.fold split (cempty,[]) t; // Epsilon closure of targets var t = List.map (function((t,ns)) { (t,add_nodes [] ns) }) t; // Canonical ordering var t = List.array t; Array.sort (function((c1,ns1),(c2,ns2)) { compare c1 c2 }) t; (Array.map fst t, Array.map snd t) } function determinize(nfa : t array) { var nfa = nodes nfa; var h = Hashtbl.create(); var parts = Hashtbl.create(); var state_counter = &0; var part_counter = &0; var lparts = &[]; var states = &[]; function get_part(p) { try Hashtbl.find parts p catch { Not_found -> var pid = *part_counter; part_counter := *part_counter + 1; Hashtbl.add parts p pid; lparts := p :: *lparts; pid } }; function rec loop(state) { var sid = List.map (function(s) { s.id }) state; try Hashtbl.find h sid catch { Not_found -> var id = *state_counter; state_counter := *state_counter + 1; Hashtbl.add h sid id; var part, targets = transitions state; var part = get_part part; var targets = Array.map loop targets; var finals = Array.map (function((_,f)) { List.mem f state }) nfa; states := (id, (part,targets,finals)) :: *states; id } }; var init : node list ref = &[]; Array.iter (function((i,_)) { init := add_node (*init) i }) nfa; ignore(loop (*init)); var dfa = Array.init (*state_counter) (function(id) { List.assoc id (*states) }); function loop(part) { var seg = &[]; Array.iteri (function(i,c) { List.iter (function((a,b)) { seg := (a,b,i) :: *seg }) c }) part; List.sort (function((a1,_,_),(a2,_,_)) { compare a1 a2 }) (*seg); }; var trans = List.array (List.map loop (List.rev (*lparts))); (dfa , trans) } /* ---- DFA -> Tables ---- */ // this expands memory but is better since all accesses are O(1) function make_trans(trans,tbl) { var a = Array.make 256 (-1); List.iter (function((min,max,n)) { var i = &min; while *i <= max { a.[*i] := tbl.[n]; i := *i + 1; } }) trans; a } function make_tables((dfa,trans)) { function rec first(p,a) { if p == Array.length a then -1 else if a.[p] then p else first (p + 1) a }; var exits = Array.map (function((_,_,states)) { first 0 states }) dfa; var tbls = Array.map (function((tid,tbl,_)) { make_trans trans.[tid] tbl }) dfa; (tbls , exits) } /* ---- Regexp Parsing ---- */ exception InvalidRegexp : string function single(c) { var n = ord c; [(n,n)] } function group(chars) { var chars = List.map (function((c1,c2)) { [(ord c1,ord c2)] }) chars; List.fold cunion cempty chars } function invalid(s) { throw InvalidRegexp(s) } function escaped(s,i) { var c = String.get s (*i); i := *i + 1; match c { | '\\' | '+' | '*' | '?' | '[' | ']' | '-' -> c | _ -> invalid s } } function rec plus(r) { match r { | Next (r1,r2) -> Next(r1,plus r2) | _ -> Plus r } } function rec star(r) { match r { | Next (r1,r2) -> Next(r1,star r2) | _ -> Star r } } function rec opt(r) { match r { | Next(r1,r2) -> Next(r1,opt r2) | _ -> Choice(r,Empty) } } function next(r,r2) { match r { | Empty -> r2 | _ -> Next r r2 } } function parse( s : string ) : t { var i = &0; var r = &Empty; var l = String.length s; while *i < l { var c = String.get s (*i); i := *i + 1; match c { | '+' -> r := plus (*r) | '*' -> r := star (*r) | '?' -> r := opt (*r) | '[' -> var range = &None; function rec loop(acc) { var c = String.get s (*i); i := *i + 1; if c == ']' then { if *range != None then invalid s; acc } else if c == '-' then { if *range != None then invalid s; match acc { | [] -> loop ((c,c) :: acc) | (x1,x2) :: l -> if x1 != x2 then invalid s; range := Some x1; loop l } } else { var c = (if c == '\\' then escaped s i else c); match *range { | None -> loop ((c,c) :: acc) | Some c2 -> range := None; loop ((c2,c) :: acc) } } }; var c = String.get s (*i); var g = if c == '^' then { i := *i + 1; cdiff call (group (loop [])) } else group (loop []); r := next (*r) Match(g) | '\\' -> r := next (*r) Match(single (escaped s i)) | _ -> r := next (*r) Match(single c) } }; *r } neko-2-2-0/src/core/Lexer.nml000066400000000000000000000120771321613172000157560ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type pos { psource : string; pline : int; pmin : int; pmax : int; } type 'a t { mutable data : 'a; mutable current : string; mutable buffer : string; mutable bsize : int; mutable bin : int; mutable bpos : int; mutable cin : int; mutable cpos : int; mutable input : IO.input; mutable source : string; mutable line : int; mutable pos : int; mutable carriage : bool; } type ('a,'b) tables { engine : LexEngine.tables; cases : ('b t -> 'a) array; def : 'b t -> 'a; } exception Invalid_rule : string var null_pos = { pmin = 0; pmax = 0; pline = 0; psource = "" }; function source(p) { p.psource } function line(p) { p.pline } function punion(p,p2) { { psource = p.psource; pline = p.pline; pmin = min p.pmin p2.pmin; pmax = max p.pmax p2.pmax; } } function create(data) { var bufsize = 4096; { data = data; carriage = false; current = ""; buffer = String.create bufsize; bsize = bufsize; bin = 0; cin = 0; bpos = bufsize; cpos = bufsize; input = IO.read_string ""; source = ""; line = 0; pos = 0; } } function data(l) { l.data; } function set(l,data) { l.data := data; } function input(l,source,input,line,pos) { l.bin := 0; l.cin := 0; l.bpos := l.bsize; l.cpos := l.bsize; l.input := input; l.source := source; l.line := line; l.pos := pos; } function curpos(l) { { psource = l.source; pline = l.line; pmin = l.pos - String.length l.current; pmax = l.pos; } } function current(l) : string { l.current } function read(l) : char { if l.bin == 0 then { if l.bpos == l.bsize then { var buf = String.create (l.bsize * 2); String.blit buf l.bsize l.buffer 0 l.bsize; l.cpos := l.cpos + l.bsize; l.bpos := l.bpos + l.bsize; l.buffer := buf; l.bsize := l.bsize * 2; } var delta = l.bpos - l.cpos; String.blit l.buffer 0 l.buffer l.cpos delta; l.bpos := delta; l.cpos := 0; var k = IO.input l.input l.buffer delta (l.bsize - delta); l.bin := l.bin + k; l.cin := l.cin + k; }; var c = String.get l.buffer l.bpos; l.bpos := l.bpos + 1; l.bin := l.bin - 1; c } function inc_line(l,c) { if c == '\r' then l.carriage := true else if c == '\n' || l.carriage then { l.carriage := false; l.line := l.line + 1; }; } function char(l) : char option { try { var c = read l; l.bpos := l.bpos - 1; l.bin := l.bin + 1; inc_line l c; Some c } catch { IO.Eof -> None } } type cur { mutable cur_n : int; mutable cur_res : int; } function token(l,t) : 'a { var tbl = fst t.engine; var exits = snd t.engine; var cur = { cur_n = 0; cur_res = -1 }; var last = { cur_n = 0; cur_res = -1 }; function rec loop(n,k) { var res = neko("tbl[0][k][0][read(l)]"); var e = exits.[k]; cur.cur_n := n; cur.cur_res := res; if e != -1 then { last.cur_n := n; last.cur_res := e; } if res == -1 then throw Exit; neko("loop[0](n+1,res)"); }; function process(eof) { var n = last.cur_n; var k = last.cur_res; if k == -1 then { l.current := ""; if !eof then { l.bpos := l.bpos - (cur.cur_n + 1); l.bin := l.bin + (cur.cur_n + 1); } -1; } else { l.cin := l.cin - n; l.bin := l.cin; l.current := String.sub l.buffer l.cpos n; l.cpos := l.cpos + n; l.bpos := l.cpos; l.pos := l.pos + n; var i = &0; while *i < n { inc_line l (String.get l.current (*i)); i := *i + 1; } k } }; var k = try { loop 0 0; assert(); } catch { | IO.Eof -> if cur.cur_res != -1 then { last.cur_n := cur.cur_n + 1; last.cur_res := exits.[cur.cur_res]; } process true; | Exit -> process false } if k == -1 then t.def(l) else t.cases.[k](l) } function build(rules,def) { var nfa = List.map (function((r,_)) { try LexEngine.parse r catch { _ -> throw Invalid_rule(r) } }) rules; var cases = List.array (List.map snd rules); { engine = LexEngine.make_tables (LexEngine.determinize (List.array nfa)); cases = cases; def = def; } } function empty() { function empty_table(_) { invalid_arg() }; build [] empty_table; } neko-2-2-0/src/core/List.nml000066400000000000000000000100171321613172000156020ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ neko(" @make = function(s) { if( s == null ) return @Core.@empty; return @Core.@cons(s[0],@make(s[1])); } @rmake = function(s,x) { if( s == null ) return x; return @rmake(s[1],@Core.@cons(s[0],x)); } $exports.@rmake = function(s) { @rmake(s,@Core.@empty) }; $exports.@make = @make; "); function rec length(l) { match l { | [] -> 0 | _ :: l -> 1 + length l } } function hd(l) { match l { | [] -> invalid_arg() | x :: _ -> x } } function tl(l) { match l { | [] -> invalid_arg() | _ :: l -> l } } function rec map(f,l) { match l { | [] -> [] | x :: l -> f(x) :: map f l } } function rec iter(f,l) { match l { | [] -> () | x :: l -> f x; iter f l } } function rec iter2(f,l1,l2) { match l1 { | [] -> match l2 { | [] -> () | _ -> invalid_arg() } | x1 :: l1 -> match l2 { | [] -> invalid_arg() | x2 :: l2 -> f x1 x2; iter2 f l1 l2 } } } function rec split(l) { match l { | [] -> ([] , []) | (a,b) :: l -> var la , lb = split l; (a :: la, b :: lb) } } function rec exists(f,l) { match l { | [] -> false | x :: l -> if f x then true else exists f l } } function rec mem(v,l) { match l { | [] -> false | x :: l -> if x == v then true else mem v l } } function rec assoc(k,l) { match l { | [] -> throw Not_found | (k2,v) :: l -> if k == k2 then v else assoc k l } } function rec phys(k,l) { match l { | [] -> throw Not_found | (k2,v) :: l -> if k === k2 then v else phys k l } } function rec find(f,l) { match l { | [] -> throw Not_found | k :: l -> if f k then k else find f l } } function rec rev_rec(l,acc) { match l { | [] -> acc | x :: l -> rev_rec l (x :: acc) } } function rev(l) { rev_rec l [] } function rec fold(f,acc,l) { match l { | [] -> acc | x :: l -> fold f (f acc x) l } } function rec append(l1,l2) { match l1 { | [] -> l2 | x :: l1 -> x :: append l1 l2 } } function rec concat(ll) { function rec loop(ll,acc) { match ll { | [] -> acc | l :: ll -> loop ll (append acc l) } }; loop ll [] } function rec chop(n,l) { if n == 0 then l else match l { | [] -> invalid_arg() | _ :: l -> chop (n -1) l } } function rec all(f,l) { match l { | [] -> true | x :: l -> if f x then all(f,l) else false } } function rec none(f,l) { match l { | [] -> true | x :: l -> if f x then false else none(f,l) } } function nth(l,n) { function rec loop(l,n) { match l { | [] -> invalid_arg() | x :: l -> if n == 0 then x else loop l (n-1) } } if n < 0 then invalid_arg(); loop l n } function rec filter(f,l) { match l { | [] -> [] | x :: l -> if f x then x :: filter f l else filter f l } } function array(l) { match l { | [] -> Array.create() | x :: l -> var a = Array.make (1+ List.length l) x; function rec loop(p,l) { match l { | [] -> () | x :: l -> a.[p] := x; loop (p + 1) l } }; loop 1 l; a } } function sort(cmp,l) { var a = array l; Array.sort cmp a; Array.list a } neko-2-2-0/src/core/Map.nml000066400000000000000000000107071321613172000154120ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* This code is translated from OCaml ExtLib PMap Copyright (C) 1996-2003 Xavier Leroy, Nicolas Cannasse, Markus Mottl */ type ('k, 'v) map { Empty; Node : (('k, 'v) map , 'k , 'v , ('k, 'v) map , int); } type ('k, 'v) t { cmp : 'k -> 'k -> int; map : ('k, 'v) map; } function height(m) { match m { | Node (_, _, _, _, h) -> h | Empty -> 0 } } function make(l,k,v,r) { Node(l, k, v, r, max (height l) (height r) + 1) } function bal(l,k,v,r) { var hl = height l; var hr = height r; if hl > hr + 2 then match l { | Node (ll,lk,lv,lr,_) -> if height ll >= height lr then make ll lk lv (make lr k v r) else match lr { | Node (lrl,lrk,lrv,lrr,_) -> make (make ll lk lv lrl) lrk lrv (make lrr k v r) | Empty -> assert() } | Empty -> assert() } else if hr > hl + 2 then match r { | Node (rl,rk,rv,rr,_) -> if height rr >= height rl then make (make l k v rl) rk rv rr else match rl { | Node (rll, rlk, rlv, rlr, _) -> make (make l k v rll) rlk rlv (make rlr rk rv rr) | Empty -> assert() } | Empty -> assert() } else Node(l, k, v, r, max hl hr + 1) } function rec min_binding(m) { match m { | Node (Empty, k, v, _, _) -> (k, v) | Node (l, _, _, _, _) -> min_binding l | Empty -> throw Not_found } } function rec remove_min_binding(m) { match m { | Node (Empty, _, _, r, _) -> r | Node (l, k, v, r, _) -> bal (remove_min_binding l) k v r | Empty -> invalid_arg() } } function merge(t1,t2) { match (t1, t2) { | (Empty, _) -> t2 | (_, Empty) -> t1 | _ -> var k, v = min_binding t2; bal t1 k v (remove_min_binding t2) } } function create(cmp) { { cmp = cmp; map = Empty; } } function empty() { { cmp = compare; map = Empty; } } function is_empty(m) { m.map == Empty } function add(m,x,d) { var cmp = m.cmp; function rec loop(m) { match m { | Node (l, k, v, r, h) -> var c = cmp x k; if c == 0 then Node(l, x, d, r, h) else if c < 0 then { var nl = loop l; bal nl k v r; } else { var nr = loop r; bal l k v nr } | Empty -> Node(Empty, x, d, Empty, 1) } }; { cmp = cmp; map = loop m.map; } } function find(m,x) { var cmp = m.cmp; function rec loop(m) { match m { | Node (l, k, v, r, _) -> var c = cmp x k; if c < 0 then loop l else if c > 0 then loop r else v | Empty -> throw Not_found } }; loop m.map } function remove(m,x) { var cmp = m.cmp; function rec loop(m) { match m { | Node(l, k, v, r, _) -> var c = cmp x k; if c == 0 then merge l r else if c < 0 then bal (loop l) k v r else bal l k v (loop r) | Empty -> Empty } }; { cmp = cmp; map = loop m.map; } } function exists(m,x) { var cmp = m.cmp; function rec loop(m) { match m { | Node (l, k, v, r, _) -> var c = cmp x k; c == 0 || loop (if c < 0 then l else r) | Empty -> false } }; loop m.map } function iter(f,m) { function rec loop(m) { match m { | Empty -> () | Node (l, k, v, r, _) -> loop l; f k v; loop r } }; loop m.map } function map(f,m) { function rec loop(m) { match m { | Empty -> Empty | Node (l, k, v, r, h) -> var l = loop l; var r = loop r; Node(l, k, f v, r, h) } }; { cmp = m.cmp; map = loop m.map; } } function fold(f,m,acc) { function rec loop(acc,m) { match m { | Empty -> acc | Node (l, k, v, r, _) -> loop (f (loop acc l) v) r } }; loop acc m.map } neko-2-2-0/src/core/Math.nml000066400000000000000000000044251321613172000155660ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ function _load(name,nargs) : 'a { neko("return $loader.loadprim('std@math_'+name,nargs)"); } function _lload(name,nargs) : 'a { neko("return try $loader.loadprim('std@math_'+name,nargs) catch e function(_) $throw(e)"); } var atan2 : float -> float -> float = _load("atan2",2); var pow : float -> float -> float = _load("pow",2); var abs : float -> float = _load("abs",1); var iabs : int -> int = _load("abs",1); var ceil : float -> int = _load("ceil",1); var floor : float -> int = _load("floor",1); var round : float -> int = _load("round",1); var fceil : float -> float = _lload("fceil",1); var ffloor : float -> float = _lload("ffloor",1); var fround : float -> float = _lload("fround",1); var fint : float -> int = _lload("int",1); var pi : float = neko "$loader.loadprim('std@math_pi',0)()"; var sqrt : float -> float = _load("sqrt",1); var atan : float -> float = _load("atan",1); var cos : float -> float = _load("cos",1); var sin : float -> float = _load("sin",1); var tan : float -> float = _load("tan",1); var log : float -> float = _load("log",1); var exp : float -> float = _load("exp",1); var acos : float -> float = _load("acos",1); var asin : float -> float = _load("asin",1); neko-2-2-0/src/core/Net.nml000066400000000000000000000107611321613172000154230ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type socket; type ip = int32; // init neko "$loader.loadprim('std@socket_init',0)()"; var socket_new : bool -> socket = neko "$loader.loadprim('std@socket_new',1)"; var socket_close : socket -> void = neko "$loader.loadprim('std@socket_close',1)"; var socket_send_char : socket -> char -> void = neko "$loader.loadprim('std@socket_send_char',2)"; var socket_send : socket -> string -> int -> int -> int = neko "$loader.loadprim('std@socket_send',4)"; var socket_recv : socket -> string -> int -> int -> int = neko "$loader.loadprim('std@socket_recv',4)"; var socket_recv_char : socket -> char = neko "$loader.loadprim('std@socket_recv_char',1)"; var socket_write : socket -> string -> void = neko "$loader.loadprim('std@socket_write',2)"; var socket_read : socket -> string = neko "$loader.loadprim('std@socket_read',1)"; var socket_connect : socket -> ip -> int -> void = neko "$loader.loadprim('std@socket_connect',3)"; var socket_listen : socket -> int -> void = neko "$loader.loadprim('std@socket_listen',2)"; var socket_bind : socket -> ip -> int -> void = neko "$loader.loadprim('std@socket_bind',3)"; var socket_accept : socket -> socket = neko "$loader.loadprim('std@socket_accept',1)"; var socket_peer : socket -> (ip,int) = neko "$loader.loadprim('std@socket_peer',1)"; var socket_host : socket -> (ip,int) = neko "$loader.loadprim('std@socket_host',1)"; var socket_set_timeout : socket -> int -> void = neko "$loader.loadprim('std@socket_set_timeout',2)"; var host_resolve : string -> ip = neko "$loader.loadprim('std@host_resolve',1)"; var host_to_string : ip -> string = neko "$loader.loadprim('std@host_to_string',1)"; neko "@host_local = $loader.loadprim('std@host_local',0)"; function host_local() : string { neko "@host_local()" }; var url_encode : string -> string = neko "$loader.loadprim('std@url_encode',1)"; var url_decode : string -> string = neko "$loader.loadprim('std@url_decode',1)"; neko "@socket_select = $loader.loadprim('std@socket_select',4)" var _array_dep = Array.make; function socket_select( read : socket array, write : socket array, others : socket array, timeout : float option ) : (socket array, socket array, socket array) { var t = match timeout { None -> neko "null" | Some t -> t }; neko " var r = @socket_select($asub(read[0],0,read[2]),$asub(write[0],0,write[2]),$asub(others[0],0,others[2]),t); r[0] = @Array.@make(r[0]); r[1] = @Array.@make(r[1]); r[2] = @Array.@make(r[2]); r " } function socket_io(s) { (IO.create_in (function() { try socket_recv_char s catch { e -> throw IO.Eof } }) (function(b,p,l) { try { var n = socket_recv s b p l; if n == 0 then throw IO.Eof; n } catch { e -> throw IO.Eof } }) (function() { socket_close s }) ,IO.create_out (socket_send_char s) (socket_send s) (function() { }) (function() { socket_close s }) ) } function start_server( ip, port, on_connect, on_data ) { var sock = socket_new false; socket_bind sock ip port; socket_listen sock 10; var clients = &[]; var empty = Array.create(); while true { var r, _ , _ = socket_select List.array(sock :: List.map fst (*clients)) empty empty None; Array.iter (function(s) { if s == sock then { var s2 = socket_accept sock; clients := (s2,on_connect s2) :: *clients; } else { var cldata = List.assoc s (*clients); if !(on_data cldata) then clients := List.filter (function((s2,_)) { s != s2 }) (*clients); } }) r; } () } neko-2-2-0/src/core/Reflect.nml000066400000000000000000000077541321613172000162710ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type neko_object; type neko_abstract; type neko_function; type neko_array; type neko_loader; type module; type value { VNull; VInt : int; VFloat : float; VBool : bool; VString : string; VObject : neko_object; VAbstract : neko_abstract; VFunction : neko_function; VArray : neko_array; } neko(" @module_read = $loader.loadprim('std@module_read',2); @module_name = $loader.loadprim('std@module_name',1); @module_exports = $loader.loadprim('std@module_exports',1); @module_loader = $loader.loadprim('std@module_loader',1); @module_exec = $loader.loadprim('std@module_exec',1); @module_nglobals = $loader.loadprim('std@module_nglobals',1); @module_global_get = $loader.loadprim('std@module_global_get',2); @module_global_set = $loader.loadprim('std@module_global_set',3); @module_code_size = $loader.loadprim('std@module_code_size',1); @module_read_path = $loader.loadprim('std@module_read_path',3); "); function value( n : neko_value ) : value { var i = function() { invalid_arg() }; neko(" switch $typeof(n) { $tnull => VNull $tint => VInt(n) $tfloat => VFloat(n) $tbool => VBool(n) $tstring => VString(n) $tobject => VObject(n) $tabstract => VAbstract(n) $tfunction => VFunction(n) $tarray => VArray(n) default => i() } "); } function neko_value(v) : neko_value { match v { | VNull -> neko("null") | VInt i -> magic i | VFloat f -> magic f | VBool b -> magic b | VString s -> magic s | VObject o -> magic o | VAbstract a -> magic a | VFunction f -> magic f | VArray a -> magic a } } function asize(a : neko_array) : int { neko("$asize(a)"); } function aget(a : neko_array, p : int) : value { value(neko("a[p]")); } function aset(a : neko_array, p : int, v : value) : void { var v = neko_value v; neko("a[p] = v"); } function module_read( fread : string -> int -> int -> int ) : module { neko("@module_read(fread,$loader)"); } var __list_dep = List.map function loader_path() : string list { neko("@List.@make($loader.path)"); } function module_read_path( path : string array, name : string, loader : neko_loader ) : module { neko(" var h; var n = path[2]; path = path[0]; while( n > 0 ) { n -= 1; h = $array(path[n],h); } @module_read_path(h,name,loader); "); } function module_name( m : module ) : string { neko("@module_name(m)"); } function module_execute( m : module ) { value neko("@module_exec(m)"); } function module_exports( m : module ) { value neko("@module_exports(m)") } function module_loader( m : module ) { value neko("@module_loader(m)") } function module_globals_count( m : module ) : int { neko("@module_nglobals(m)"); } function module_get_global( m : module, n : int ) { value neko("@module_global_get(m,n)"); } function module_set_global( m : module, n : int, v : value ) : void { var v = neko_value v; neko("@module_global_set(m,n,v)"); } function module_code_size( m : module ) : int { neko("@module_code_size(m)"); } neko-2-2-0/src/core/Regexp.nml000066400000000000000000000035601321613172000161260ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type t neko(" regexp_matched_pos = $loader.loadprim('regexp@regexp_matched_pos',2); "); var build : string -> t = neko("$loader.loadprim('regexp@regexp_new',1)"); var find : t -> string -> int -> int -> bool = neko("$loader.loadprim('regexp@regexp_match',4)"); var matched : t -> int -> string = neko("$loader.loadprim('regexp@regexp_matched',2)"); function matched_pos( r : t, n : int ) : (int , int) { neko(" var s = regexp_matched_pos(r,n); $array(s.pos,s.len); "); } function split( r, str ) { function rec loop(pos,len) { if !find r str pos len then [String.sub str pos len] else { var ppos, plen = matched_pos r 0; var tot = ppos - pos + plen; String.sub str pos (ppos - pos) :: loop (pos + tot) (len - tot) } } loop 0 String.length(str) }neko-2-2-0/src/core/Set.nml000066400000000000000000000136141321613172000154300ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* This is very similar to PMap except that it does only store one value */ type 'a set { Empty; Node : ('a set, 'a ,'a set, int); } type 'a t { cmp : 'a -> 'a -> int; set : 'a set; } /* -------- tools ----------- */ function height(s) { match s { | Empty -> 0 | Node(_, _, _, h) -> h } } function make(l,v,r) { Node(l, v, r, max (height l) (height r) + 1) } function bal(l,v,r) { var hl = height l; var hr = height r; if hl > hr + 2 then match l { | Node (ll,lv,lr,_) -> if height ll >= height lr then make ll lv (make lr v r) else match lr { | Node (lrl,lrv,lrr,_) -> make (make ll lv lrl) lrv (make lrr v r) | Empty -> assert() } | Empty -> assert() } else if hr > hl + 2 then match r { | Node (rl,rv,rr,_) -> if height rr >= height rl then make (make l v rl) rv rr else match rl { | Node (rll, rlv, rlr, _) -> make (make l v rll) rlv (make rlr rv rr) | Empty -> assert() } | Empty -> assert() } else Node l v r (max hl hr + 1) } function rec remove_min_elt(s) { match s { | Empty -> assert() | Node(Empty, v, r, _) -> r | Node(l, v, r, _) -> bal (remove_min_elt l) v r } } function rec min_elt(s) { match s { | Empty -> throw Not_found | Node(Empty, v, r, _) -> v | Node(l, v, r, _) -> min_elt l } } function merge(t1,t2) { match (t1, t2) { | (Empty, t) -> t | (t, Empty) -> t | _ -> bal t1 (min_elt t2) (remove_min_elt t2) } } function rec add_loop(cmp,x,s) { match s { | Empty -> Node(Empty,x,Empty,1) | Node(l, v, r, _) -> var c = cmp x v; if c == 0 then s else if c < 0 then bal (add_loop cmp x l) v r else bal l v (add_loop cmp x r) } } function rec join(cmp,l,v,r) { match (l, r) { | (Empty, _) -> add_loop cmp v r | (_, Empty) -> add_loop cmp v l | (Node(ll, lv, lr, lh), Node(rl, rv, rr, rh)) -> if lh > rh + 2 then bal ll lv (join cmp lr v r) else if rh > lh + 2 then bal (join cmp l v rl) rv rr else make l v r | _ -> assert() } } function concat(cmp,t1,t2) { match (t1, t2) { | (Empty, t) -> t | (t, Empty) -> t | _ -> join cmp t1 (min_elt t2) (remove_min_elt t2) } } function rec split(cmp,x,s) { match s { | Empty -> (Empty, false, Empty) | Node(l, v, r, _) -> var c = cmp x v; if c == 0 then (l, true, r) else if c < 0 then { var ll, pres, rl = split cmp x l; (ll, pres, join cmp rl v r) } else { var lr, pres, rr = split cmp x r; (join cmp l v lr, pres, rr) } } } /* ---------- api ----------- */ function rec add(set : 'a t, x : 'a) { { cmp = set.cmp; set = add_loop set.cmp x set.set; } } function create(cmp) { { cmp = cmp; set = Empty; } } function empty() { { cmp = compare; set = Empty; } } function is_empty(s) { match s.set { | Empty -> true | _ -> false } } function exists(set,x) { function rec loop(s) { match s { | Empty -> false | Node(l, v, r, _) -> var c = set.cmp x v; c == 0 || loop (if c < 0 then l else r) } } loop set.set } function remove(set,x) { function rec loop(s) { match s { | Empty -> Empty | Node(l, v, r, _) -> var c = set.cmp x v; if c == 0 then merge l r else if c < 0 then bal (loop l) v r else bal l v (loop r) } } { cmp = set.cmp; set = loop set.set; } } function union(set1,set2) { var cmp = set1.cmp; function rec loop(s1,s2) { match (s1, s2) { | (Empty, t2) -> t2 | (t1, Empty) -> t1 | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) -> if h1 >= h2 then if h2 == 1 then add_loop cmp v2 s1 else { var l2, _, r2 = split cmp v1 s2; join cmp (loop l1 l2) v1 (loop r1 r2) } else if h1 == 1 then add_loop cmp v1 s2 else { var l1, _, r1 = split cmp v2 s1; join cmp (loop l1 l2) v2 (loop r1 r2) } | _ -> assert() } } { cmp = cmp; set = loop set1.set set2.set; } } function inter(set1,set2) { var cmp = set1.cmp; function rec loop(s1,s2) { match (s1, s2) { | (Empty, t2) -> Empty | (t1, Empty) -> Empty | (Node(l1, v1, r1, _), t2) -> match split cmp v1 t2 { | (l2, false, r2) -> concat cmp (loop l1 l2) (loop r1 r2) | (l2, true, r2) -> join cmp (loop l1 l2) v1 (loop r1 r2) | _ -> assert() } | _ -> assert() } } { cmp = cmp; set = loop set1.set set2.set; } } function diff(set1,set2) { var cmp = set1.cmp; function rec loop(s1,s2) { match (s1, s2) { | (Empty, t2) -> Empty | (t1, Empty) -> t1 | (Node(l1, v1, r1, _), t2) -> match split cmp v1 t2 { | (l2, false, r2) -> join cmp (loop l1 l2) v1 (loop r1 r2) | (l2, true, r2) -> concat cmp (loop l1 l2) (loop r1 r2) | _ -> assert() } | _ -> assert() } } { cmp = cmp; set = loop set1.set set2.set; } } function iter(f,set) { function rec loop(s) { match s { | Empty -> () | Node(l, v, r, _) -> loop l; f v; loop r } } loop set.set } neko-2-2-0/src/core/Stack.nml000066400000000000000000000036761321613172000157510ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type stack_item { CFunction; Module : string; Pos : (string,int); } type stack = stack_item array; neko(" @make_stack = function(a) { var a = $acopy(a); var i = 0; var l = $asize(a); while( i < l ) { var k = a[i]; a[i] = if( k == null ) CFunction else if( $typeof(k) == $tstring ) Module(k) else Pos(k[0],k[1]); i = i + 1; } return @Array.@make(a); } ") function call() : stack { neko("@make_stack($callstack())"); } function exc() : stack { neko("@make_stack($excstack())"); } function dump(ch,stack) { Array.iter (function(s) { match s { | CFunction -> IO.write ch "Called from a C function\n" | Module m -> IO.printf ch "Called from %s (no debug available)\n" m | Pos (file,line) -> IO.printf ch "Called from %s line %d\n" (file,line) } }) stack } function print() { dump(IO.stdout,call()); } neko-2-2-0/src/core/String.nml000066400000000000000000000116701321613172000161430ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ neko(" @string_split = $loader.loadprim('std@string_split',2); "); function make(size : int, c : char) : string { neko(" var s = $smake(size); var i = 0; while( i < size ) { $sset(s,i,c); i = i + 1; } s "); } var create : int -> string = neko("$smake"); var length : string -> int = neko("$ssize"); function get(s : string,n : int) : char { var c = neko("$sget(s,n)"); if c == neko("null") then invalid_arg(); c } function set(s : string, n : int, c : char) : void { if neko("$sset(s,n,c) == null") then invalid_arg(); } function blit(dst : string, p : int, src : string, p2 : int, l : int ) : void { if neko("try { $sblit(dst,p,src,p2,l); false; } catch e true") then invalid_arg(); } function sub(s : string, p : int, l : int ) : string { var s = neko("$ssub(s,p,l)"); if s == neko("null") then invalid_arg(); s } function find( s : string, p : int, pat : string ) : int { var pos = neko "$sfind(s,p,pat)"; if pos == neko "null" then throw Not_found; pos } var list_depency = List.iter function split( s : string, sub : string ) : string list { neko(" var l = @string_split(s,sub); return @List.@make(l); "); } function concat( sep : string, s : string list ) : string { var b = Buffer.create(); function rec loop(l) { match l { | [] -> () | [x] -> Buffer.add b x | x :: l -> Buffer.add b x; Buffer.add b sep; loop l } }; loop(s); Buffer.string b } function is_printable(c) { c >= '\032' && c <= '\126' } function escape_char(c) { match c { | '\n' -> "\\n" | '\t' -> "\\t" | '\r' -> "\\r" | '\\' -> "\\\\" | '"' -> "\\\"" | c when !is_printable c -> sprintf "\\%.3d" (ord c) | c -> String.make 1 c } } function escape(s) { var b = Buffer.create(); function rec loop(i) { if i == String.length s then Buffer.string b else { match String.get s i { | '\n' -> Buffer.add b "\\n" | '\t' -> Buffer.add b "\\t" | '\r' -> Buffer.add b "\\r" | '\\' -> Buffer.add b "\\\\" | '"' -> Buffer.add b "\\\"" | c when !is_printable c -> Buffer.add b (sprintf "\\%.3d" (ord c)) | c -> Buffer.add_char b c }; loop (i+1) } }; loop(0); } function unescape(s) { var l = length s; var s2 = create l; var i = &0; var p = &0; while *i < l { match neko("$sget")(s,*i) { | '\\' -> i := *i + 1; if *i == l then invalid_arg(); var c = neko("$sget")(s,*i); match c { | 'n' -> neko("$sset")(s2,*p,'\n'); | 't' -> neko("$sset")(s2,*p,'\t'); | 'r' -> neko("$sset")(s2,*p,'\r'); | '"' -> neko("$sset")(s2,*p,'"'); | '\\' -> neko("$sset")(s2,*p,'\\'); | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' -> if *i + 2 >= l then invalid_arg(); var c2 = neko("$sget")(s,*i + 1); var c3 = neko("$sget")(s,*i + 2); i := *i + 2; if c2 < '0' || c2 > '9' || c3 < '0' || c3 > '9' then invalid_arg(); var o0 = ord '0'; var n = (ord c - o0) * 100 + (ord c2 - o0) * 10 + (ord c3 - o0); if n > 255 then invalid_arg(); neko("$sset")(s2,*p,chr n); | _ -> invalid_arg() } | c -> neko("$sset")(s2,*p,c); } p := *p + 1; i := *i + 1; } sub s2 0 (*p) } function lowercase(s) { var l = length s; var s2 = sub s 0 l; var i = &0; var delta = ord 'a' - ord 'A'; while *i < l { var c = neko("$sget")(s,*i); if c >= 'A' && c <= 'Z' then neko("$sset")(s2,*i,chr(ord c + delta)); i := *i + 1; } s2 } function uppercase(s) { var l = length s; var s2 = sub s 0 l; var i = &0; var delta = ord 'A' - ord 'a'; while *i < l { var c = neko("$sget")(s,*i); if c >= 'a' && c <= 'z' then neko("$sset")(s2,*i,chr(ord c + delta)); i := *i + 1; } s2 } neko(" @serialize = $loader.loadprim('std@serialize',1); @unserialize = $loader.loadprim('std@unserialize',2); "); function serialize( x : 'a ) : string { neko "@serialize(x)"; } function unserialize( x : string ) : 'a { neko "@unserialize(x,$loader)"; } neko-2-2-0/src/core/Sys.nml000066400000000000000000000054571321613172000154610ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ neko(" @sys_exit = $loader.loadprim('std@sys_exit',1); @get_env = $loader.loadprim('std@get_env',1); @get_cwd = $loader.loadprim('std@get_cwd',0); @exe_path = $loader.loadprim('std@sys_exe_path',0); @sys_file_type = $loader.loadprim('std@sys_file_type',1); @sys_read_dir = $loader.loadprim('std@sys_read_dir',1); "); type version { maj : int; min : int; build : int; } function without_extension(s) { match List.rev (String.split s ".") { | [] -> "" | [x] -> x | ext :: l -> String.concat "." (List.rev l) } } function extension(s) { match List.rev (String.split s ".") { | [] | [_] -> "" | ext :: _ -> ext } } function without_dir(s) { var s = String.concat "/" (String.split s "\\"); match List.rev (String.split s "/") { | [] -> assert() | file :: _ -> file } } var array_dependency = Array.make function args() : string array { neko(" @Array.@make($loader.args) "); } function exit(code : int) : 'a { neko(" @sys_exit(code); "); } var exists : string -> bool = neko "$loader.loadprim('std@sys_exists',1)" var version = { var v : int = neko "$version()"; { maj = v / 100; min = (v / 10) % 10; build = v % 10; } } function get_env( s : string ) : string option { var s = neko "@get_env(s)"; if s == neko "null" then None else Some s; } var put_env : string -> string -> void = neko "$loader.loadprim('std@put_env',2)" function get_cwd() : string { neko "@get_cwd()" } var set_cwd : string -> void = neko "$loader.loadprim('std@set_cwd',1)" function executable_path() : string { neko "@exe_path()" } function is_directory(str:string) : bool { neko "@sys_file_type(str) == 'dir'"; } function read_directory(str:string) : string list { neko "@List.@make(@sys_read_dir(str))" } neko-2-2-0/src/core/Xml.nml000066400000000000000000000074311321613172000154350ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type t { Node : (string, (string, string) list , t list); PCData : string; CData : string; Document : t list; } exception Error : string; var __list = List.hd; neko(" @parser = function() { return { stack => null, doc => null, cdata => function(s) { this.doc = $array(CData(s),this.doc); }, pcdata => function(s) { this.doc = $array(PCData(s),this.doc); }, xml => function(name,att) { var fields = $objfields(att); var nf = $asize(fields); var fl = null; var i = 0; while( i < nf ) { var f = fields[i]; fl = $array($array($field(f),$objget(att,f)),fl); i = i + 1; } this.stack = $array(name,fl,this.doc,this.stack); this.doc = null; }, done => function() { var s = this.stack; var d = this.doc; this.doc = $array(Node(s[0],@List.@rmake(s[1]),@List.@rmake(d)),s[2]); this.stack = s[3]; } } } @parse = $loader.loadprim('std@parse_xml',2); "); function parse( s : string ) : t { neko(" var p = @parser(); try { @parse(s,p); return Document(@List.@rmake(p.doc)); } catch e { if( $typeof(e) == $tstring ) $rethrow(Error(e)); $rethrow(e); } "); } function is_node(x) { match x { | Node _ -> true | _ -> false } } function is_pcdata(x) { match x { | PCData _ -> true | _ -> false } } function is_cdata(x) { match x { | CData _ -> true | _ -> false } } function firstNode(x) { match x { | Node (_,_,l) | Document l -> List.find is_node l | CData _ | PCData _ -> invalid_arg() } } function nodes(x) { match x { | Node (_,_,l) | Document l -> List.filter is_node l | CData _ | PCData _ -> invalid_arg() } } function node_name(x) { match x { | Node (name,_,_) -> name | _ -> invalid_arg() } } function node_text(x) { match x { | Node (_,_,children) -> var b = Buffer.create(); List.iter (function(x) { match x { | CData t | PCData t -> Buffer.add b t | _ -> invalid_arg() } }) children; Buffer.string b | _ -> invalid_arg() } } function attrib(x,n) { var n = String.lowercase n; match x { | Node (_,att,_) -> snd (List.find (function((n2,_)) { String.lowercase n2 == n }) att) | _ -> invalid_arg() } } function rec write(ch,x) { match x { | Document l -> List.iter write(ch) l | CData c -> IO.write ch ""; | PCData c -> IO.write ch c; | Node (name,att,children) -> IO.printf ch "<%s%s" (name,String.concat "" (List.map (function((a,v)) { " "+a+"=\""+String.escape v+"\"" }) att)); match children { | [] -> IO.write ch "/>" | l -> IO.write ch ">"; List.iter write(ch) l; IO.printf ch "" name } } } function to_string(x) { var ch , str = IO.write_string(); write ch x; str() } neko-2-2-0/src/core/Zip.nml000066400000000000000000000064231321613172000154370ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type in; type out; type flush { NO; SYNC; FULL; FINISH; BLOCK; } type result { done : bool; read : int; write : int; } function init() { neko(" @set_flush_mode = $loader.loadprim('zlib@set_flush_mode',2); @inflate_init = $loader.loadprim('zlib@inflate_init',1); @deflate_buffer = $loader.loadprim('zlib@deflate_buffer',5); @inflate_buffer = $loader.loadprim('zlib@inflate_buffer',5); @deflate_init = $loader.loadprim('zlib@deflate_init',1); @deflate_bound = $loader.loadprim('zlib@deflate_bound',2); @deflate_end = $loader.loadprim('zlib@deflate_end',1); @inflate_end = $loader.loadprim('zlib@inflate_end',1); "); } function __result(x) { { done = neko "x.done"; read = neko "x.read"; write = neko "x.write" } } function output(v:int) : out { neko("@deflate_init")(v); } function output_bound(o:out,size:int) : int { neko("@deflate_bound")(o,size); } function output_end(o:out) : void { neko("@deflate_end")(o); } function output_buffer(o:out,in:string,ipos:int,out:string,opos:int) { __result(neko "@deflate_buffer(o,in,ipos,out,opos)"); } function input( n : int option ) : in { neko("@inflate_init")(match n { None -> neko "null" | Some i -> i }) } function input_buffer(i:in,in:string,ipos:int,out:string,opos:int) { __result(neko "@inflate_buffer(i,in,ipos,out,opos)"); } function input_end(i:in) : void { neko("@inflate_end")(i); } function output_set_flush_mode(o:out,f:flush) : void { neko("@set_flush_mode")(o,string f); } function input_set_flush_mode(i:in,f:flush) : void { neko("@set_flush_mode")(i,string f); } function compress(str,level) { var c = output level; output_set_flush_mode c FINISH; var out = String.create (output_bound c (String.length str)); var r = output_buffer c str 0 out 0; output_end c; if !r.done || r.read != String.length str then throw Error("Compression failed"); String.sub out 0 r.write; } function uncompress(str) { var u = input None; var tmp = String.create (1 << 16); // 64K var b = Buffer.create(); input_set_flush_mode u SYNC; function rec loop(pos) { var r = input_buffer u str pos tmp 0; Buffer.add_sub b tmp 0 r.write; if !r.done then loop(pos + r.read); } loop(0); input_end u; Buffer.string b; } neko-2-2-0/src/mtypes/000077500000000000000000000000001321613172000145515ustar00rootroot00000000000000neko-2-2-0/src/mtypes/std.neko000066400000000000000000000342061321613172000162260ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ version = 0; // ---------------------------------------------------------------------- // List List = $new(null); List.new = function() { var o = $new(null); $objsetproto(o,@List); o.l = 0; o.h = null; o.q = null; return o; }; @List = $new(null); List.prototype = @List; @List.get_length = function() { return this.l; }; @List.add = function(x) { var a = $array(x,null); if( this.q != null ) this.q[1] = a; else this.h = a; this.q = a; this.l = this.l + 1; }; @List.push = function(x) { var a = $array(x,this.h); this.h = a; if( this.q == null ) this.q = a; this.l = this.l + 1; }; @List.remove = function(x) { var cur = this.h; var prev = null; while( cur != null ) { if( cur[0] == x ) { if( prev == null ) this.h = cur[1]; else prev[1] = cur[1]; if( this.q == cur ) this.q = prev; this.l = this.l - 1; return true; } prev = cur; cur = cur[1]; } return false; } @List.at = function(p) { var cur = this.h; while( cur != null ) { if( $not(p) ) return cur[0]; p = p - 1; cur = cur[1]; } return null; } @List.pop = function() { if( this.h == null ) return null; if( this.q == this.h ) this.q = null; var x = this.h[0]; this.h = this.h[1]; this.l = this.l - 1; return x; } @List.first = function() { if( this.h == null ) return null; return this.h[0]; } @List.last = function() { if( this.q == null ) return null; return this.q[0]; } @List.iter = function(f) { var p = this.h; while( p != null ) { f(p[0]); p = p[1]; } } @List.find = function(f) { var p = this.h; while( p != null ) { var x = f(p[0]); if( x != null ) return x; p = p[1]; } return null; } @List.exists = function(f) { var p = this.h; while( p != null ) { if( f(p[0]) ) return true; p = p[1]; } return false; } @List.join = function(sep) { if( $not(this.l) ) return String.new(""); var b = StringBuf.new(); var p = this.h; while( p != null ) { b.add(p[0]); p = p[1]; if( p != null ) b.add(sep); } return String.new(b.__string()); } @List.toArray = function() { var a = $amake(this.l); var p = this.h; var n = 0; while( p != null ) { a[n] = p[0]; n = n + 1; p = p[1]; } return Array.new1(a); } @List.toString = function() { return String.new(this.__string()); } @List.__string = function() { var b = StringBuf.new(); var p = this.h; b.add("["); while( p != null ) { b.add(p[0]); p = p[1]; if( p != null ) b.add(","); } b.add("]"); return b.__string(); } @List.map = function(f) { var l = List.new(); if( this.h != null ) { var cur = this.h; var last = null; l.h = null; while( cur != null ) { if( last == null ) { last = $array(f(cur[0]),null); l.h = last; } else { var tmp = $array(f(cur[0]),null); last[1] = tmp; last = tmp; } cur = cur[1]; } l.q = last; l.l = this.l; } return l; } @List.filter = function(f) { var l = List.new(); if( this.h != null ) { var cur = this.h; var last = null; var count = 0; l.h = null; while( cur != null ) { if( f(cur[0]) ) { if( last == null ) { last = $array(cur[0],null); l.h = last; } else { var tmp = $array(cur[0],null); last[1] = tmp; last = tmp; } count += 1; } cur = cur[1]; } l.q = last; l.l = count; } return l; } @List.__serialize = function() { return $array("List",version); } $exports.List = List; // ---------------------------------------------------------------------- // Array Array = $new(null); Array.new = function() { var o = $new(null); $objsetproto(o,@Array); o.@a = $array(); return o; } Array.new1 = function(a) { var o = $new(null); $objsetproto(o,@Array); o.@a = a; return o; } @Array = $new(null); Array.prototype = @Array; @Array.get_length = function() { return $asize(this.@a); } @Array.concat = function(a) { var l = $asize(this.@a); var l2 = $asize(a.@a); var a = $amake(l+l2); $ablit(a,0,this.@a,0,l); $ablit(a,l,a.@a,0,l2); this.@a = a; } @Array.sub = function(s,l) { var a = $asub(this.@a,s,l); if( a == null ) return null; return Array.new1(a); } @Array.sort = function(f) { var a = this.@a; var i = 0; var l = $asize(a); while( i < l ) { var swap = false; var j = 0; var max = l - i - 1; while( j < max ) { if( f(a[j],a[j+1]) > 0 ) { var tmp = a[j+1]; a[j+1] = a[j]; a[j] = tmp; swap = true; } j = j + 1; } if( $not(swap) ) break; i = i + 1; } } @Array.iter = function(f) { var i = 0; var a = this.@a; var l = $asize(a); while( i < l ) { f(a[i]); i = i + 1; } } @Array.map = function(f) { var i = 0; var a = this.@a; var l = $asize(a); var a2 = $amake(l); while( i < l ) { a2[i] = f(a[i]); i = i + 1; } return Array.new1(a2); } @Array.join = function(sep) { var i = 0; var a = this.@a; var l = $asize(a); var b = StringBuf.new(); while( i < l ) { b.add(a[i]); i = i + 1; if( i != l ) b.add(sep); } return b.toString(); } @Array.toList = function() { var i = 0; var a = this.@a; var l = $asize(a); var li = List.new(); while( i < l ) { li.add(a[i]); i = i + 1; } return li; } @Array.toString = function() { return String.new(this.__string()); } @Array.__string = function() { return $string(this.@a); } @Array.set = function(p,v) { var a = this.@a; if( $asize(a) > p ) return (a[p] = v); var a2 = $amake(p+1); $ablit(a2,0,a,0,$asize(a)); this.@a = a2; return (a2[p] = v); } @Array.__serialize = function() { return $array("Array",version); } $exports.Array = Array; // ---------------------------------------------------------------------- // Hash Hash = $new(null); Hash.new = function() { var o = $new(null); $objsetproto(o,@Hash); o.@h = $hnew(3); return o; } @Hash = $new(null); Hash.prototype = @Hash; @Hash.get = function(k) { return $hget(this.@h,k.@s,null); } @Hash.set = function(k,v) { $hset(this.@h,k.@s,v,null); } @Hash.remove = function(k) { return $hremove(this.@h,k.@s,null); } @Hash.exists = function(k) { return $hmem(this.@h,k.@s,null); } @Hash.iter = function(f) { $hiter(this.@h,function(k,v) { f(String.new(k),v) }); } @Hash.toString = function() { return String.new(this.__string()); } @Hash.__string = function() { var s = StringBuf.new(); var i = 0; var first = true; s.add("#hash["); $hiter(this.@h,function(k,v) { if( first ) first = false; else s.add(", "); s.add(k); s.add(" => "); s.add(v); }); s.add("]"); return s.__string(); } @Hash.__serialize = function() { return $array("Hash",version); } $exports.Hash = Hash; // ---------------------------------------------------------------------- // String string_split = $loader.loadprim("std@string_split",2); String = $new(null); String.new = function(s) { if( s == null ) return null; if( $typeof(s) != $tstring ) s = $string(s); var o = $new(null); $objsetproto(o,@String); o.@s = s; return o; } @String = $new(null); String.prototype = @String; @String.get_length = function() { return $ssize(this.@s); } @String.charAt = function(p) { return String.new( $ssub(this.@s,p,1) ); } @String.at = function(p) { return $sget(this.@s,p); } @String.sub = function(s,l) { if( l == null ) l = $ssize(this.@s) - s; return String.new( $ssub(this.@s,s,l) ); } @String.split = function(s) { var a = string_split(this.@s,s.@s); var l = List.new(); while( a != null ) { l.add( String.new(a[0]) ); a = a[1]; } return l; } @String.toString = function() { return this; } @String.__string = function() { return this.@s; } @String.__compare = function(o) { return $compare(this.@s,o.@s); } @String.__add = function(s) { return String.new(this.@s+$string(s)); } @String.__radd = function(s) { return String.new($string(s)+this.@s); } @String.__serialize = function() { return $array("String",version); } $exports.String = String; // ---------------------------------------------------------------------- // Int32 Int32 = $new(null); Int32.of_int = $loader.loadprim("std@int32_new",1); Int32.to_int = $loader.loadprim("std@int32_to_int",1); Int32.add = $loader.loadprim("std@int32_add",2); Int32.sub = $loader.loadprim("std@int32_sub",2); Int32.mul = $loader.loadprim("std@int32_mul",2); Int32.div = $loader.loadprim("std@int32_div",2); Int32.mod = $loader.loadprim("std@int32_mod",2); Int32.shl = $loader.loadprim("std@int32_shl",2); Int32.shr = $loader.loadprim("std@int32_shr",2); Int32.ushr = $loader.loadprim("std@int32_ushr",2); Int32.and = $loader.loadprim("std@int32_and",2); Int32.xor = $loader.loadprim("std@int32_xor",2); Int32.or = $loader.loadprim("std@int32_or",2); Int32.neg = $loader.loadprim("std@int32_neg",1); Int32.complement = $loader.loadprim("std@int32_complement",1); Int32.compare = $loader.loadprim("std@int32_compare",2); $exports.Int32 = Int32; // ---------------------------------------------------------------------- // StringBuf buffer_new = $loader.loadprim("std@buffer_new",0); buffer_add = $loader.loadprim("std@buffer_add",2); buffer_add_sub = $loader.loadprim("std@buffer_add_sub",4); buffer_add_char = $loader.loadprim("std@buffer_add_char",2); buffer_string = $loader.loadprim("std@buffer_string",1); StringBuf = $new(null); StringBuf.new = function() { var b = $new(null); $objsetproto(b,@StringBuf); b.@b = buffer_new(); return b; } @StringBuf = $new(null); StringBuf.prototype = @StringBuf; @StringBuf.add = function(s) { buffer_add(this.@b,s); } @StringBuf.addSub = function(s,p,l) { buffer_add_sub(this.@b,s,p,l); } @StringBuf.addChar = function(c) { buffer_add_char(this.@b,c); } @StringBuf.__string = function() { return buffer_string(this.@b); } @StringBuf.toString = function() { return String.new(this.__string()); } $exports.StringBuf = StringBuf; // ---------------------------------------------------------------------- // Xml parse_xml = $loader.loadprim("std@parse_xml",2); fxml = function(name,att) { var o = $new(null); $objsetproto(o,@Xml); var f = $objfields(att); var i = 0; var l = $asize(f); while( i < l ) { $objset(att,f[i], String.new($objget(att,f[i])) ); i = i + 1; } o.att = att; o.node = String.new(name); o.children = List.new(); o.parent = this.cur; this.cur.children.add(o); this.cur = o; } fpcdata = function(text) { var o = $new(null); $objsetproto(o,@Xml); o.text = String.new(text); o.parent = this.cur; o.cdata = false; this.cur.children.add(o); } fcdata = function(text) { var o = $new(); $objsetproto(o,@Xml); o.text = String.new(text); o.parent = this.cur; o.cdata = true; this.cur.children.add(o); } fcomment = function(comment) { } fdoctype = function(dtype) { } fdone = function() { this.cur = this.cur.parent; } Xml = $new(null); Xml.new = function(s) { var doc = $new(null); $objsetproto(doc,@Xml); doc.children = List.new(); parse_xml(s.@s,{ cur => doc, xml => fxml, cdata => fcdata, pcdata => fpcdata, comment => fcomment, doctype => fdoctype, done => fdone }); return doc; } @Xml = $new(null); Xml.prototype = @Xml; @Xml.get = function(name) { if( this.att == null ) $throw(String.new("Xml.get")); return $objget(this.att,$hash(name.@s)); } @Xml.set = function(name,val) { if( this.att == null ) $throw(String.new("Xml.set")); return $objset(this.att,$hash(name.@s),val); } @Xml.nodes = function() { if( this.children == null ) $throw(String.new("Xml.nodes")); var s = this.children.h; var l = List.new(); while( s != null ) { var x = s[0]; if( x.node != null ) l.add(x); s = s[1]; } return l; } @Xml.firstChild = function() { if( this.children == null ) $throw(String.new("Xml.firstChild")); return this.children.first() } @Xml.firstNode = function() { if( this.children == null ) $throw(String.new("Xml.firstNode")); var s = this.children.h; while( s != null ) { if( s[0].node != null ) return s[0]; s = s[1]; } return null; } @Xml.toString = function() { return String.new(this.__string()); } xml_string_rec = function(x,b) { if( x.text != null ) { if( x.cdata ) buffer_add(b,""); return; } var s = x.children; if( s == null ) return; s = s.h; if( x.node != null ) { buffer_add(b,"<"); buffer_add(b,x.node); var a = x.att; var f = $objfields(a); var n = $asize(f); var i = 0; while( i < n ) { buffer_add(b," "); buffer_add(b,$field(f[i])); buffer_add(b,"=\""); buffer_add(b,$objget(a,f[i])); buffer_add(b,"\""); i = i + 1; } if( s == null ) { buffer_add(b,"/>"); return; } buffer_add(b,">"); while( s != null ) { xml_string_rec(s[0],b); s = s[1]; } buffer_add(b,""); return; } while( s != null ) { xml_string_rec(s[0],b); s = s[1]; } } @Xml.__string = function() { var b = buffer_new(); xml_string_rec(this,b); return buffer_string(b); } @Xml.__serialize = function() { return $array("Xml",version); } $exports.Xml = Xml; $exports.__unserialize = function(v) { if( $typeof(v) != $tarray ) $throw("Invalid serialized data"); if( v[1] != version ) $throw("Invalid version for class "+v[0]); return switch( v[0] ) { "Xml" => @Xml "List" => @List "Array" => @Array "String" => @String "Hash" => @Hash default => $throw("Unknown class "+v[0]) } } neko-2-2-0/src/neko/000077500000000000000000000000001321613172000141645ustar00rootroot00000000000000neko-2-2-0/src/neko/Ast.nml000066400000000000000000000126331321613172000154300ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type pos = Lexer.pos type constant { True; False; Null; This; Int : int; Float : string; String : string; Builtin : string; Ident : string; } type keyword { Var; While; Do; If; Else; Function; Return; Break; Continue; Default; Try; Catch; Switch; } type token { Eof; Semicolon; Dot; Comma; Arrow; BraceOpen; BraceClose; ParentOpen; ParentClose; BracketOpen; BracketClose; Const : constant; Keyword : keyword; Binop : string; Comment : string; CommentLine : string; } type while_flag { NormalWhile; DoWhile; } type expr; type expr_decl { EConst : constant; EBlock : expr list; EParenthesis : expr; EField : (expr , string); ECall : (expr , expr list); EArray : (expr , expr); EVars : (string , expr option) list; EWhile : (expr , expr , while_flag); EIf : (expr , expr , expr option); ETry : (expr , string , expr); EFunction : (string list , expr); EBinop : (string , expr , expr); EReturn : expr option; EBreak : expr option; EContinue; ENext : (expr , expr); EObject : (string , expr) list; ELabel : string; ESwitch : (expr, (expr, expr) list, expr option); } type expr = (expr_decl , pos) function pos((_,x)) { x } var var_args = -1; function mk_call(v,args,p) { (ECall v args , p) } function mk_call0(v,p) { (ECall v [], p) } function mk_call1(v,a,p) { (ECall v [a], p) } function mk_ident(i,p) { (EConst (Ident i), p) } function mk_builtin(b,p) { (EConst (Builtin b), p) } function mk_int(i,p) { (EConst (Int i), p) } function mk_string(s,p) { (EConst (String s), p) } function mk_binop(op,e1,e2,p) { (EBinop op e1 e2, p) } function map(f,(e,p)) { (match e { | EBlock el -> EBlock (List.map f el) | EParenthesis e -> EParenthesis f(e) | EField (e,s) -> EField f(e) s | ECall (e,el) -> ECall f(e) (List.map f el) | EArray (e1,e2) -> EArray f(e1) f(e2) | EVars vl -> EVars(List.map(function((v,e)) { (v , match e { | None -> None | Some e -> Some (f e) }) },vl)) | EWhile (e1,e2,flag) -> EWhile f(e1) f(e2) flag | EIf (e,e1,e2) -> EIf f(e) f(e1) (match e2 { None -> None | Some e -> Some f(e)}) | ETry (e,ident,e2) -> ETry f(e) ident f(e2) | EFunction (params,e) -> EFunction params f(e) | EBinop (op,e1,e2) -> EBinop op f(e1) f(e2) | EReturn (Some e) -> EReturn Some(f e) | EBreak (Some e) -> EBreak Some(f e) | ENext (e1,e2) -> ENext f(e1) f(e2) | EObject fl -> EObject (List.map (function((s,e)) { (s , f e) }) fl) | ESwitch (e,cases,eo) -> ESwitch f(e) (List.map (function((e1,e2)) { (f e1, f e2) }) cases) (match eo { None -> None | Some e -> Some f(e) }) | EReturn None | EBreak None | EContinue | ELabel _ | EConst _ -> e }, p) } function iter(f,(e,p)) { match e { | EBlock el -> List.iter f el | EParenthesis e -> f e | EField (e,s) -> f e | ECall (e,el) -> f e; List.iter f el | EArray (e1,e2) -> f e1; f e2 | EVars vl -> List.iter (function((_,e)) { match e { None -> () | Some e -> f e } }) vl | EWhile (e1,e2,_) -> f e1; f e2 | EIf (e,e1,e2) -> f e; f e1; (match e2 { None -> () | Some e -> f e }) | ETry (e1,_,e2) -> f e1; f e2 | EFunction (_,e) -> f e | EBinop (_,e1,e2) -> f e1; f e2 | EReturn (Some e) -> f e | EBreak (Some e) -> f e | ENext (e1,e2) -> f e1; f e2 | EObject fl -> List.iter (function((_,e)) { f e }) fl | ESwitch (e,cases,eo) -> f e; List.iter (function((e1,e2)) { f e1; f e2 }) cases; match eo { None -> () | Some e -> f e }; | EReturn None | EBreak None | EContinue | ELabel _ | EConst _ -> () } } function s_constant(x) { match x { | True -> "true" | False -> "false" | Null -> "null" | This -> "this" | Int i -> string i | Float s -> s | String s -> "\"" + String.escape s + "\"" | Builtin s -> "$" + s | Ident s -> s } } function s_keyword(x) { match x { | Var -> "var" | While -> "while" | Do -> "do" | If -> "if" | Else -> "else" | Function -> "function" | Return -> "return" | Break -> "break" | Continue -> "continue" | Default -> "default" | Try -> "try" | Catch -> "catch" | Switch -> "switch" } } function s_token(x) { match x { | Eof -> "" | Semicolon -> ";" | Dot -> "." | Comma -> "," | Arrow -> "=>" | BraceOpen -> "{" | BraceClose -> "}" | ParentOpen -> "(" | ParentClose -> ")" | BracketOpen -> "[" | BracketClose -> "]" | Const c -> s_constant c | Keyword k -> s_keyword k | Binop s -> s | Comment s -> "/*" + s + "*/" | CommentLine s -> "//" + s } } neko-2-2-0/src/neko/Binast.nml000066400000000000000000000126611321613172000161220ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Lexer; open Neko.Ast; type context { ch : IO.input; strings : string array; mutable pos : Lexer.pos; } var parse_from_string : (string -> pos -> expr) ref = &(function(_,_) { assert() }); var header = "NBA\001"; function parse_string(ctx) { var index = IO.read_byte ctx.ch; if index == 0 then { var size = IO.read_ui16 ctx.ch; var str = IO.read ctx.ch size; Array.add ctx.strings str; str } else Array.get ctx.strings (Array.length ctx.strings - index) } function rec parse_list(ctx,f,n) { if n == 0 then [] else { var x = f ctx; x :: parse_list ctx f (n - 1); } } function parse_constant(ctx) { match IO.read_byte ctx.ch { | 0 -> True | 1 -> False | 2 -> Null | 3 -> This | 4 -> Int (IO.read_byte ctx.ch) | 5 -> Int (IO.read_i32 ctx.ch) | 6 -> Float (parse_string ctx) | 7 -> String (parse_string ctx) | 8 -> Builtin (parse_string ctx) | 9 -> Ident (parse_string ctx) | n -> error ("Invalid const tag : " + n) } } function parse_op(ctx) { match IO.read_byte ctx.ch { | 0 -> "+" | 1 -> "-" | 2 -> "/" | 3 -> "*" | 4 -> "%" | 5 -> "<<" | 6 -> ">>" | 7 -> ">>>" | 8 -> "|" | 9 -> "&" | 10 -> "^" | 11 -> "==" | 12 -> "!=" | 13 -> ">" | 14 -> ">=" | 15 -> "<" | 16 -> "<=" | 17 -> "=" | 18 -> "&&" | 19 -> "||" | 20 -> "++=" | 21 -> "--=" | 22 -> "+=" | 23 -> "-=" | 24 -> "/=" | 25 -> "*=" | 26 -> "%=" | 27 -> "<<=" | 28 -> ">>=" | 29 -> ">>>=" | 30 -> "|=" | 31 -> "&=" | 32 -> "^=" | n -> error ("Invalid op tag "+n) } } function rec parse_field(ctx) { var name = parse_string ctx; (name,parse_expr ctx) } function rec parse_switch(ctx,n) { var e = parse_expr ctx; var l = parse_list ctx (function(ctx) { var e1 = parse_expr ctx; var e2 = parse_expr ctx; (e1,e2) }) n; var eo = parse_expr_opt ctx; ESwitch e l eo } function rec parse_expr_opt(ctx) { if IO.read_byte ctx.ch == 0 then None else Some (parse_expr ctx) } function rec parse_expr(ctx) { var n = IO.read_byte ctx.ch; if n < 2 then { var file = if n == 1 then ctx.pos.psource else parse_string ctx; var line = IO.read_ui24 ctx.ch; ctx.pos := { psource = file; pline = line; pmin = 0; pmax = 0; }; parse_expr(ctx); } else { var pos = ctx.pos; (match n { | 2 -> EConst (parse_constant ctx) | 3 -> EBlock (parse_list ctx parse_expr (IO.read_byte ctx.ch)) | 4 -> EBlock (parse_list ctx parse_expr (IO.read_ui24 ctx.ch)) | 5 -> EParenthesis (parse_expr ctx) | 6 -> var e = parse_expr ctx; EField e (parse_string ctx) | 7 -> var e = parse_expr ctx; ECall e (parse_list ctx parse_expr (IO.read_byte ctx.ch)) | 8 -> var e = parse_expr ctx; EArray e (parse_expr ctx) | 9 -> function parse_var(_) { var v = parse_string ctx; var e = parse_expr_opt ctx; (v,e); } EVars (parse_list ctx parse_var (IO.read_byte ctx.ch)) | 10 -> var e1 = parse_expr ctx; var e2 = parse_expr ctx; EWhile e1 e2 NormalWhile | 11 -> var e1 = parse_expr ctx; var e2 = parse_expr ctx; EWhile e1 e2 DoWhile | 12 -> var e1 = parse_expr ctx; var e2 = parse_expr ctx; EIf e1 e2 (parse_expr_opt ctx) | 13 -> var e1 = parse_expr ctx; var str = parse_string ctx; ETry e1 str (parse_expr ctx) | 14 -> var vars = parse_list ctx parse_string (IO.read_byte ctx.ch); EFunction vars (parse_expr ctx) | 15 -> var op = parse_op ctx; var e1 = parse_expr ctx; var e2 = parse_expr ctx; EBinop op e1 e2 | 16 -> EReturn None | 17 -> EReturn Some(parse_expr ctx) | 18 -> EBreak None | 19 -> EBreak Some(parse_expr ctx) | 20 -> EContinue | 21 -> var e1 = parse_expr ctx; var e2 = parse_expr ctx; ENext e1 e2 | 22 -> EObject (parse_list ctx parse_field (IO.read_byte ctx.ch)) | 23 -> EObject (parse_list ctx parse_field (IO.read_ui24 ctx.ch)) | 24 -> ELabel (parse_string ctx) | 25 -> parse_switch ctx (IO.read_byte ctx.ch) | 26 -> parse_switch ctx (IO.read_ui24 ctx.ch) | 27 -> var str = IO.read ctx.ch (IO.read_ui24 ctx.ch); fst (*parse_from_string)(str,pos) | 28 -> var e = parse_expr ctx; ECall e (parse_list ctx parse_expr (IO.read_ui24 ctx.ch)) | n -> error ("Invalid expr tag : " + n) },pos) } } function parse(ch,pos) { var ctx = { ch = ch; strings = Array.create(); pos = pos; }; if IO.read ctx.ch 4 != header then error "Invalid binast header"; parse_expr(ctx); } neko-2-2-0/src/neko/Bytecode.nml000066400000000000000000000373751321613172000164510ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type opcode { // getters AccNull; AccTrue; AccFalse; AccThis; AccInt : int; AccStack : int; AccGlobal : int; AccEnv : int; AccField : string; AccArray; AccIndex : int; AccBuiltin : string; // setters SetStack : int; SetGlobal : int; SetEnv : int; SetField : string; SetArray; SetIndex : int; SetThis; // stack ops Push; Pop : int; Call : int; ObjCall : int; Jump : int; JumpIf : int; JumpIfNot : int; Trap : int; EndTrap; Ret : int; MakeEnv : int; MakeArray : int; // value ops Bool; IsNull; IsNotNull; Add; Sub; Mult; Div; Mod; Shl; Shr; UShr; Or; And; Xor; Eq; Neq; Gt; Gte; Lt; Lte; Not; // extra ops TypeOf; Compare; Hash; New; JumpTable : int; Apply : int; AccStack0; AccStack1; AccIndex0; AccIndex1; PhysCompare; TailCall : (int, int); Loop; }; type global { GlobalVar : string; GlobalFunction : (int , int); GlobalString : string; GlobalFloat : string; GlobalDebug : (string array, (int, int) array); GlobalVersion : int; } exception Invalid_file; var trap_stack_delta = 6 var inull : int = neko("null") function hash_field(s : string) : int { neko("$hash(s)") } function op_param(x) { match x { | AccInt _ | AccStack _ | AccGlobal _ | AccEnv _ | AccField _ | AccBuiltin _ | SetStack _ | SetGlobal _ | SetEnv _ | SetField _ | Pop _ | Call _ | ObjCall _ | Jump _ | JumpIf _ | JumpIfNot _ | JumpTable _ | Trap _ | MakeEnv _ | MakeArray _ | Ret _ | AccIndex _ | SetIndex _ | Apply _ | TailCall _ -> true | AccNull | AccTrue | AccFalse | AccThis | AccArray | SetArray | SetThis | Push | EndTrap | Bool | Add | Sub | Mult | Div | Mod | Shl | Shr | UShr | Or | And | Xor | Eq | Neq | Gt | Gte | Lt | Lte | IsNull | IsNotNull | Not | TypeOf | Compare | Hash | New | AccStack0 | AccStack1 | AccIndex0 | AccIndex1 | PhysCompare | Loop -> false } } function code_tables(ops) { var ids = Hashtbl.create(); var fids = Array.create(); Array.iter (function(x) { match x { | AccField s | SetField s | AccBuiltin s -> var id = hash_field s; try var f = Hashtbl.find ids id; if f != s then error("Field hashing conflict " + s + " and " + f); catch { Not_found -> Hashtbl.add ids id s; Array.add fids s } | _ -> () } }) ops; var p = &0; var pos = Array.make (Array.length(ops) + 1) 0; Array.iteri (function(i,op) { pos.[i] := *p; p := *p + (if op_param op then 2 else 1); }) ops; pos.[Array.length ops] := *p; (fids , pos , *p) } function write_debug_infos(ch,files,inf) { var nfiles = Array.length files; // the encoding of nfiles was set to keep // backward compatibility with 1.3 which // only allowed up to 127 filenames var lot_of_files = &false; if nfiles < 0x80 then IO.write_byte ch nfiles else if nfiles < 0x8000 then { lot_of_files := true; IO.write_byte ch ((nfiles >> 8) or 0x80); IO.write_byte ch (nfiles and 0xFF); } else invalid_arg(); Array.iter (function(s) { IO.write ch s; IO.write_char ch '\000' }) files; IO.write_i32 ch (Array.length inf); var curfile = &0; var curpos = &0; var rcount = &0; function rec flush_repeat(p) { if *rcount > 0 then { if *rcount > 15 then { IO.write_byte ch ((15 << 2) or 2); rcount := *rcount - 15; flush_repeat(p) } else { var delta = p - *curpos; var delta = (if delta > 0 && delta < 4 then delta else 0); IO.write_byte ch ((delta << 6) or (*rcount << 2) or 2); rcount := 0; curpos := *curpos + delta; } } } Array.iter (function((f,p)) { if f != *curfile then { flush_repeat(p); curfile := f; if *lot_of_files then { IO.write_byte ch ((f >> 7) or 1); IO.write_byte ch (f and 0xFF); } else IO.write_byte ch ((f << 1) or 1); } if p != *curpos then flush_repeat(p); if p == *curpos then rcount := *rcount + 1 else { var delta = p - *curpos; if delta > 0 && delta < 32 then { IO.write_byte ch ((delta << 3) or 4) } else { IO.write_byte ch (p << 3); IO.write_byte ch (p >> 5); IO.write_byte ch (p >> 13); } curpos := p; } }) inf; flush_repeat(*curpos) } function write(ch,(globals,ops)) { IO.write ch "NEKO"; var ids , pos , csize = code_tables ops; IO.write_i32 ch (Array.length globals); IO.write_i32 ch (Array.length ids); IO.write_i32 ch csize; Array.iter (function(x) { match x { | GlobalVar s -> IO.write_byte ch 1; IO.write ch s; IO.write_char ch '\000'; | GlobalFunction (p,nargs) -> IO.write_byte ch 2; IO.write_i32 ch (pos.[p] or (nargs << 24)) | GlobalString s -> IO.write_byte ch 3; IO.write_ui16 ch (String.length s); IO.write ch s | GlobalFloat s -> IO.write_byte ch 4; IO.write ch s; IO.write_char ch '\000' | GlobalDebug (files,inf) -> IO.write_byte ch 5; write_debug_infos ch files inf; | GlobalVersion v -> IO.write_byte ch 6; IO.write_byte ch v } }) globals; Array.iter (function(s) { IO.write ch s; IO.write_char ch '\000'; }) ids; Array.iteri (function(i,op) { var pop = &inull; var opid = (match op { | AccNull -> 0 | AccTrue -> 1 | AccFalse -> 2 | AccThis -> 3 | AccInt n -> pop := n; 4 | AccStack n -> pop := (n - 2); 5 | AccGlobal n -> pop := n; 6 | AccEnv n -> pop := n; 7 | AccField s -> pop := (hash_field s); 8 | AccArray -> 9 | AccIndex n -> pop := (n - 2); 10 | AccBuiltin s -> pop := (hash_field s); 11 | SetStack n -> pop := n; 12 | SetGlobal n -> pop := n; 13 | SetEnv n -> pop := n; 14 | SetField s -> pop := (hash_field s); 15 | SetArray -> 16 | SetIndex n -> pop := n; 17 | SetThis -> 18 | Push -> 19 | Pop n -> pop := n; 20 | Call n -> pop := n; 21 | ObjCall n -> pop := n; 22 | Jump n -> pop := (pos.[i+n] - pos.[i]); 23 | JumpIf n -> pop := (pos.[i+n] - pos.[i]); 24 | JumpIfNot n -> pop := (pos.[i+n] - pos.[i]); 25 | Trap n -> pop := (pos.[i+n] - pos.[i]); 26 | EndTrap -> 27 | Ret n -> pop := n; 28 | MakeEnv n -> pop := n; 29 | MakeArray n -> pop := n; 30 | Bool -> 31 | IsNull -> 32 | IsNotNull -> 33 | Add -> 34 | Sub -> 35 | Mult -> 36 | Div -> 37 | Mod -> 38 | Shl -> 39 | Shr -> 40 | UShr -> 41 | Or -> 42 | And -> 43 | Xor -> 44 | Eq -> 45 | Neq -> 46 | Gt -> 47 | Gte -> 48 | Lt -> 49 | Lte -> 50 | Not -> 51 | TypeOf -> 52 | Compare -> 53 | Hash -> 54 | New -> 55 | JumpTable n -> pop := n; 56 | Apply n -> pop := n; 57 | AccStack0 -> 58 | AccStack1 -> 59 | AccIndex0 -> 60 | AccIndex1 -> 61 | PhysCompare -> 62 | TailCall (args,st) -> pop := (args or (st << 3)); 63 | Loop -> pop := 64; 0 }); var n = *pop; if n == inull then IO.write_byte ch (opid << 2) else if opid < 32 && (n == 0 || n == 1) then IO.write_byte ch ((opid << 3) or (n << 2) or 1) else if n >= 0 && n <= 0xFF then { IO.write_byte ch ((opid << 2) or 2); IO.write_byte ch n; } else { IO.write_byte ch ((opid << 2) or 3); IO.write_i32 ch n; } }) ops } function read_string(ch) { var b = Buffer.create(); function rec loop() { var c = IO.read_char ch; if c == '\000' then Buffer.string b else { Buffer.add_char b c; loop() } }; loop() } function read_debug_infos(ch) { var nfiles = IO.read_byte ch; // see comments in read_debug_infos var lot_of_files = &false; var nfiles = if nfiles < 0x80 then nfiles else { lot_of_files := true; var b = IO.read_byte ch; ((nfiles and 0x7F) << 8) or b }; if nfiles == 0 then invalid_arg(); var files = Array.init nfiles (function(_) { read_string ch }); var npos = IO.read_i32 ch; var curfile = &0; var curpos = &0; var pos = Array.make npos (0,0); function rec loop(i) { if i == npos then () else { var b = IO.read_byte ch; if b and 1 != 0 then { var file = if *lot_of_files then { var b2 = IO.read_byte ch; ((b >> 1) << 8) or b2 } else b >> 1; if file >= Array.length files then invalid_arg(); curfile := file; loop(i) } else if b and 2 != 0 then { var delta = b >> 6; var count = (b >> 2) and 15; var p = &0; while *p < count { pos.[i + *p] := (*curfile,*curpos); p := *p + 1; } curpos := *curpos + delta; loop (i + count) } else if b and 4 != 0 then { curpos := *curpos + (b >> 3); pos.[i] := (*curfile,*curpos); loop (i + 1) } else { var b2 = IO.read_byte ch; var b3 = IO.read_byte ch; curpos := (b >> 3) or (b2 << 5) or (b3 << 13); pos.[i] := (*curfile,*curpos); loop (i + 1) } } } loop 0; (files, pos) } function read(ch) { try { var head = IO.read ch 4; if head != "NEKO" then throw Invalid_file; var nglobals = IO.read_i32 ch; var nids = IO.read_i32 ch; var csize = IO.read_i32 ch; if nglobals < 0 || nglobals > 0xFFFF || nids < 0 || nids > 0xFFFF || csize < 0 || csize > 0xFFFFFF then throw Invalid_file; var globals = Array.init nglobals (function(_) { match IO.read_byte ch { | 1 -> GlobalVar(read_string ch) | 2 -> var v = IO.read_i32 ch; GlobalFunction(v and 0xFFFFFF, v >> 24) | 3 -> var len = IO.read_ui16 ch; GlobalString(IO.read ch len) | 4 -> GlobalFloat(read_string ch) | 5 -> var files, inf = read_debug_infos ch; GlobalDebug files inf | 6 -> GlobalVersion(IO.read_byte ch) | _ -> throw Invalid_file } }); var ids = Hashtbl.create(); function rec loop(n) { if n == 0 then () else { var s = read_string ch; var id = hash_field s; try var s2 = Hashtbl.find ids id; if s != s2 then throw Invalid_file; catch { Not_found -> Hashtbl.add ids id s; loop (n-1) } } }; loop nids; var pos = Array.make (csize+1) (-1); var cpos = &0; var jumps = &[]; var ops = Array.create(); while *cpos < csize { var code = IO.read_byte ch; var op , p = match code and 3 { | 0 -> (code >> 2 , inull) | 1 -> (code >> 3 , ((code >> 2) and 1)) | 2 -> if code == 2 then (IO.read_byte ch, inull) else (code >> 2 , IO.read_byte ch) | 3 -> (code >> 2 , IO.read_i32 ch) | _ -> assert() }; var op = match op { | 0 -> AccNull | 1 -> AccTrue | 2 -> AccFalse | 3 -> AccThis | 4 -> AccInt p | 5 -> AccStack (p + 2) | 6 -> AccGlobal p | 7 -> AccEnv p | 8 -> AccField (try Hashtbl.find ids p catch { Not_found -> throw Invalid_file }) | 9 -> AccArray | 10 -> AccIndex (p + 2) | 11 -> AccBuiltin (try Hashtbl.find ids p catch { Not_found -> throw Invalid_file }) | 12 -> SetStack p | 13 -> SetGlobal p | 14 -> SetEnv p | 15 -> SetField (try Hashtbl.find ids p catch { Not_found -> throw Invalid_file }) | 16 -> SetArray | 17 -> SetIndex p | 18 -> SetThis | 19 -> Push | 20 -> Pop p | 21 -> Call p | 22 -> ObjCall p | 23 -> jumps := (*cpos , Array.length ops) :: *jumps; Jump p | 24 -> jumps := (*cpos , Array.length ops) :: *jumps; JumpIf p | 25 -> jumps := (*cpos , Array.length ops) :: *jumps; JumpIfNot p | 26 -> jumps := (*cpos , Array.length ops) :: *jumps; Trap p | 27 -> EndTrap | 28 -> Ret p | 29 -> MakeEnv p | 30 -> MakeArray p | 31 -> Bool | 32 -> IsNull | 33 -> IsNotNull | 34 -> Add | 35 -> Sub | 36 -> Mult | 37 -> Div | 38 -> Mod | 39 -> Shl | 40 -> Shr | 41 -> UShr | 42 -> Or | 43 -> And | 44 -> Xor | 45 -> Eq | 46 -> Neq | 47 -> Gt | 48 -> Gte | 49 -> Lt | 50 -> Lte | 51 -> Not | 52 -> TypeOf | 53 -> Compare | 54 -> Hash | 55 -> New | 56 -> JumpTable p | 57 -> Apply p | 58 -> AccStack0 | 59 -> AccStack1 | 60 -> AccIndex0 | 61 -> AccIndex1 | 62 -> PhysCompare | 63 -> TailCall (p and 7) (p >> 3) | 64 -> Loop | _ -> throw Invalid_file }; pos.[*cpos] := Array.length ops; cpos := *cpos + (if op_param op then 2 else 1); Array.add ops op; }; if *cpos != csize then throw Invalid_file; pos.[*cpos] := Array.length ops; function pos_index(i,sadr) { var idx = pos.[sadr]; if idx == -1 then throw Invalid_file; idx - i }; List.iter (function((a,i)) { Array.set ops i (match Array.get ops i { | Jump p -> Jump (pos_index i (a+p)) | JumpIf p -> JumpIf (pos_index i (a+p)) | JumpIfNot p -> JumpIfNot (pos_index i (a+p)) | Trap p -> Trap (pos_index i (a+p)) | _ -> assert() }); }) (*jumps); Array.iteri (function(i,g) { match g { | GlobalFunction(f,n) -> globals.[i] := GlobalFunction(pos_index 0 f,n) | _ -> () } }) globals; (globals , ops) } catch { | IO.Eof | IO.Overflow _ -> throw Invalid_file } } function dump(ch,(globals,ops)) { var ids, pos , csize = code_tables ops; IO.printf ch "nglobals : %d\n" (Array.length globals); IO.printf ch "nfields : %d\n" (Array.length ids); IO.printf ch "codesize : %d ops , %d total\n" (Array.length ops,csize); IO.printf ch "GLOBALS =\n" (); var marks = Array.make csize false; Array.iteri (function(i,g) { IO.printf ch " global %d : %s\n" (i, match g { | GlobalVar s -> "var " + String.escape s | GlobalFunction (p,n) -> if p >= 0 && p < csize then marks.[p] := true; "function " + string p + " nargs " + string n | GlobalString s -> "string \"" + String.escape s + "\"" | GlobalFloat s -> "float " + String.escape s | GlobalDebug (files,inf) -> var ch, buf = IO.write_string(); write_debug_infos ch files inf; sprintf "debug %d ops %d bytes" (Array.length inf,String.length buf()) | GlobalVersion v -> "version " + string v }) }) globals; IO.printf ch "FIELDS =\n" (); Array.iter (function(f) { IO.printf ch " %s%s%.8X\n" (f , if String.length(f) >= 24 then " " else String.make (24 - String.length f) ' ', hash_field f); }) ids; IO.printf ch "CODE =\n" (); function str(s,i) { s + " " + string i }; var bpos = &0; Array.iteri (function(pos,op) { if marks.[pos] then IO.write_char ch '\n'; IO.printf ch "%.6X %6d %s\n" (*bpos , pos , match op { | AccInt i -> str "AccInt" i | AccStack i -> str "AccStack" i | AccGlobal i -> str "AccGlobal" i | AccEnv i -> str "AccEnv" i | AccField s -> "AccField " + s | AccIndex i -> str "AccIndex" i | AccBuiltin s -> "AccBuiltin " + s | SetStack i -> str "SetStack" i | SetGlobal i -> str "SetGlobal" i | SetEnv i -> str "SetEnv" i | SetField f -> "SetField " + f | SetIndex i -> str "SetIndex" i | Pop i -> str "Pop" i | Call i -> str "Call" i | ObjCall i -> str "ObjCall" i | Jump i -> str "Jump" (pos + i) | JumpIf i -> str "JumpIf" (pos + i) | JumpIfNot i -> str "JumpIfNot" (pos + i) | Trap i -> str "Trap" (pos + i) | Ret i -> str "Ret" i | MakeEnv i -> str "MakeEnv" i | MakeArray i -> str "MakeArray" i | JumpTable i -> str "JumpTable" i | Apply i -> str "Apply" i | _ -> string op }); bpos := *bpos + if op_param op then 2 else 1; }) ops; IO.printf ch "END\n" (); } neko-2-2-0/src/neko/Compile.nml000066400000000000000000000655441321613172000163020ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Lexer; open Neko.Ast; open Neko.Bytecode; type access { XEnv : int; XStack : int; XGlobal : int; XField : string; XIndex : int; XArray; XThis; } type label { lname : string; ltraps : int list; lstack : int; mutable lpos : int option; mutable lwait : (void -> void) list; } type globals { globals : (global,int) Hashtbl.t; gobjects : (string list,int) Hashtbl.t; mutable functions : (opcode array, (int,int) array, int , int) list; mutable gtable : global array; labels : (string,label) Hashtbl.t; hfiles : (string,int) Hashtbl.t; files : string array; } type context { g : globals; version : int; mutable ops : opcode array; mutable locals : (string,int) Map.t; mutable env : (string,int) Map.t; mutable nenv : int; mutable stack : int; mutable loop_limit : int; mutable loop_traps : int; mutable limit : int; mutable traps : int list; mutable breaks : (void -> void, pos) list; mutable continues : (void -> void, pos) list; mutable pos : (int,int) array; mutable curpos : (int, int); mutable curfile : string; } type error_msg = string exception Error : (error_msg , pos) function error(e,p) { throw Error(e,p) } function error_msg(s) { s } function stack_delta(o) { match o { | AccNull | AccTrue | AccFalse | AccThis | AccInt _ | AccStack _ | AccGlobal _ | AccEnv _ | AccField _ | AccBuiltin _ | AccIndex _ | JumpIf _ | JumpIfNot _ | Jump _ | JumpTable _ | Ret _ | SetGlobal _ | SetStack _ | SetEnv _ | SetThis | Bool | IsNull | IsNotNull | Not | Hash | TypeOf | New | AccStack0 | AccStack1 | AccIndex0 | AccIndex1 | Loop -> 0 | Add | Sub | Mult | Div | Mod | Shl | Shr | UShr | Or | And | Xor | Eq | Neq | Gt | Gte | Lt | Lte | PhysCompare -> -1 | AccArray -> -1 | SetField _ | SetIndex _ | Compare -> -1 | SetArray -> -2 | Push -> 1 | Pop x -> -x | Apply nargs | Call nargs | TailCall (nargs,_) -> -nargs | ObjCall nargs -> -(nargs + 1) | MakeEnv size | MakeArray size -> -size | Trap _ -> trap_stack_delta | EndTrap -> -trap_stack_delta } } function check_stack(ctx,stack,p) { if ctx.stack != stack then error "Stack alignment failure" p; } function pos(ctx) { Array.length ctx.ops } function set_pos(ctx,p) { if p.psource == ctx.curfile then { if p.pline != snd ctx.curpos then ctx.curpos := (fst ctx.curpos, p.pline); } else if p == Lexer.null_pos then { // nothing } else { var fid = try Hashtbl.find ctx.g.hfiles p.psource catch { Not_found -> var fid = Array.length ctx.g.files; Array.add ctx.g.files p.psource; Hashtbl.add ctx.g.hfiles p.psource fid; fid; } ctx.curfile := p.psource; ctx.curpos := (fid,p.pline); } } function write(ctx,op) { ctx.stack := ctx.stack + stack_delta op; Array.add ctx.pos ctx.curpos; if op_param op then Array.add ctx.pos ctx.curpos; Array.add ctx.ops op; } function jmp(ctx) { var p = pos ctx; write ctx (Jump 0); function() { Array.set ctx.ops p Jump(pos ctx - p) } } function cjmp(cond,ctx) { var p = pos ctx; write ctx (Jump 0); function() { Array.set ctx.ops p (if cond then JumpIf else JumpIfNot)(pos ctx - p) } } function trap(ctx) { var p = pos ctx; write ctx (Trap 0); function() { Array.set ctx.ops p Trap(pos ctx - p) } } function goto(ctx,p) { write ctx Jump(p - pos ctx) } function global(ctx,g) { var ginf = ctx.g; try Hashtbl.find ginf.globals g catch { Not_found -> var gid = Array.length ginf.gtable; Hashtbl.add ginf.globals g gid; Array.add ginf.gtable g; gid } } function save_breaks(ctx) { var oldc = ctx.continues; var oldb = ctx.breaks; var oldl = ctx.loop_limit; var oldt = ctx.loop_traps; ctx.loop_limit := ctx.stack; ctx.breaks := []; ctx.continues := []; (ctx , oldc, oldb , oldl, oldt) } function process_continues((ctx,oldc,_,_,_)) { List.iter (function((f,_)) { f() }) ctx.continues; ctx.continues := oldc } function process_breaks((ctx,_,oldb,oldl,oldt)) { List.iter (function((f,_)) { f() }) ctx.breaks; ctx.loop_limit := oldl; ctx.loop_traps := oldt; ctx.breaks := oldb } function check_breaks(ctx) { List.iter (function((_,p)) { error "Break outside a loop" p }) ctx.breaks; List.iter (function((_,p)) { error "Continue outside a loop" p }) ctx.continues } function make_array(p,el) { (ECall (EConst (Builtin "array"),p) el , p) } function get_cases_ints(cases) { var max = &(-1); var l = List.map (function((e,e2)) { match e { | (EConst (Int n),_) when n >= 0 -> if n > *max then max := n; (n,e2) | _ -> throw Exit } }) cases; // only create jump table if small or >10% cases matched var nmatches = List.length l; if nmatches < 3 then throw Exit; if *max >= 16 && (nmatches * 100) / (*max + 1) < 10 then throw Exit; if *max > 512 then throw Exit; (l,*max + 1) } function rec scan_labels(ctx,supported,in_block,e) { match fst e { | EFunction (args,e) -> var nargs = List.length args; var traps = ctx.traps; ctx.traps := []; ctx.stack := ctx.stack + nargs; scan_labels ctx supported false e; ctx.stack := ctx.stack - nargs; ctx.traps := traps | EBlock _ -> var old = ctx.stack; Neko.Ast.iter (scan_labels ctx supported true) e; ctx.stack := old | EVars l -> if !in_block then error "Variable declaration must be done inside a block" (snd e); List.iter (function((_,e)) { match e { | None -> () | Some e -> scan_labels ctx supported false e }; ctx.stack := ctx.stack + 1 }) l | ELabel l when !supported -> error "Label is not supported in this part of the program" (snd e); | ELabel l when Hashtbl.exists ctx.g.labels l -> error ("Duplicate label " + l) (snd e) | ELabel l -> var label = { lname = l; ltraps = List.rev ctx.traps; lstack = ctx.stack; lpos = None; lwait = []; }; Hashtbl.add ctx.g.labels l label | ETry (e,_,e2) -> ctx.stack := ctx.stack + trap_stack_delta; ctx.traps := ctx.stack :: ctx.traps; scan_labels ctx supported false e; ctx.stack := ctx.stack - trap_stack_delta; ctx.traps := match ctx.traps { [] -> assert() | _ :: l -> l }; ctx.stack := ctx.stack + 1; scan_labels ctx supported false e2; ctx.stack := ctx.stack - 1; | EBinop ("=",e1,e2) -> function rec is_extended((e,_)) { match e { | EParenthesis e -> is_extended e | EArray _ | EField _ -> true | _ -> false } }; var ext = is_extended e1; if ext then ctx.stack := ctx.stack + 1; scan_labels ctx supported false e2; ctx.stack := ctx.stack + 1; scan_labels ctx supported false e1; ctx.stack := ctx.stack - (if ext then 2 else 1); | ECall ((EConst (Builtin "array"),_),e :: el) -> if ctx.version >= 2 then { scan_labels ctx supported false e; List.iter (function(e) { ctx.stack := ctx.stack + 1; scan_labels ctx supported false e; }) el; ctx.stack := ctx.stack - List.length el } else { List.iter (function(e) { scan_labels ctx supported false e; ctx.stack := ctx.stack + 1; }) el; scan_labels ctx supported false e; ctx.stack := ctx.stack - List.length el } | ECall ((EConst (Builtin x),_),el) when x != "apply" -> Neko.Ast.iter (scan_labels ctx false false) e | ECall ((EConst (Builtin "apply"),_),e :: el) | ECall(e,el) -> List.iter (function(e) { scan_labels ctx supported false e; ctx.stack := ctx.stack + 1; }) el; scan_labels ctx supported false e; ctx.stack := ctx.stack - List.length el | EObject fl -> ctx.stack := ctx.stack + 2; List.iter (function((s,e)) { scan_labels ctx supported false e }) fl; ctx.stack := ctx.stack - 2; | ESwitch (ee,[(econd,exec)],eo) -> var p = snd e; scan_labels ctx supported false (EIf (EBinop "==" ee econd,p) exec eo,p) | ESwitch (e,cases,eo) -> scan_labels ctx supported false e; var delta = try { ignore(get_cases_ints cases); 0 } catch { Exit -> 1 }; ctx.stack := ctx.stack + delta; List.iter (function((e1,e2)) { ctx.stack := ctx.stack + delta; scan_labels ctx supported false e1; ctx.stack := ctx.stack - delta; scan_labels ctx supported false e2; }) cases; match eo { | None -> () | Some e -> scan_labels ctx supported false e } ctx.stack := ctx.stack - delta; | ENext (e1,e2) -> scan_labels ctx supported in_block e1; scan_labels ctx supported in_block e2; | EConst _ | EContinue | EBreak _ | EReturn _ | EIf _ | EWhile _ | EParenthesis _ -> Neko.Ast.iter (scan_labels ctx supported false) e | EBinop (_,_,_) | EArray _ | EField _ -> Neko.Ast.iter (scan_labels ctx false false) e } } function compile_constant(ctx,c,p) { match c { | True -> write ctx AccTrue | False -> write ctx AccFalse | Null -> write ctx AccNull | This -> write ctx AccThis | Int n -> write ctx (AccInt n) | Float f -> write ctx (AccGlobal (global ctx (GlobalFloat f))) | String s -> write ctx (AccGlobal (global ctx (GlobalString s))) | Builtin s -> match s { | "tnull" -> write ctx (AccInt 0) | "tint" -> write ctx (AccInt 1) | "tfloat" -> write ctx (AccInt 2) | "tbool" -> write ctx (AccInt 3) | "tstring" -> write ctx (AccInt 4) | "tobject" -> write ctx (AccInt 5) | "tarray" -> write ctx (AccInt 6) | "tfunction" -> write ctx (AccInt 7) | "tabstract" -> write ctx (AccInt 8) | s -> write ctx (AccBuiltin s) } | Ident s -> try { var l = Map.find ctx.locals s; if l <= ctx.limit then { var e = try { Map.find ctx.env s } catch { Not_found -> var e = ctx.nenv; ctx.nenv := ctx.nenv + 1; ctx.env := Map.add ctx.env s e; e }; write ctx (AccEnv e); } else { var p = ctx.stack - l; write ctx (if p == 0 then AccStack0 else if p == 1 then AccStack1 else AccStack p); } } catch { Not_found -> var g = global ctx (GlobalVar s); write ctx (AccGlobal g) } } } function rec compile_access(ctx,e) { match fst e { | EConst (Ident s) -> try { var l = Map.find ctx.locals s; if l <= ctx.limit then { var e = try { Map.find ctx.env s } catch { Not_found -> var e = ctx.nenv; ctx.nenv := ctx.nenv + 1; ctx.env := Map.add ctx.env s e; e }; XEnv e } else XStack l } catch { Not_found -> var g = global ctx (GlobalVar s); XGlobal g } | EField (e,f) -> compile ctx false e; write ctx Push; XField f | EArray (e1,(EConst (Int n),_)) -> compile ctx false e1; write ctx Push; XIndex n | EArray (ea,ei) -> compile ctx false ei; write ctx Push; compile ctx false ea; write ctx Push; XArray | EConst This -> XThis | _ -> error "Invalid access" (snd e) } } function rec compile_access_set(ctx,a) { match a { | XEnv n -> write ctx (SetEnv n) | XStack l -> write ctx (SetStack (ctx.stack - l)) | XGlobal g -> write ctx (SetGlobal g) | XField f -> write ctx (SetField f) | XIndex i -> write ctx (SetIndex i) | XThis -> write ctx SetThis | XArray -> write ctx SetArray } } function rec compile_access_get(ctx,a) { match a { | XEnv n -> write ctx (AccEnv n) | XStack l -> write ctx (AccStack (ctx.stack - l)) | XGlobal g -> write ctx (AccGlobal g) | XField f -> write ctx (AccField f) | XIndex i -> write ctx (AccIndex i) | XThis -> write ctx AccThis | XArray -> write ctx Push; write ctx (AccStack 2); write ctx AccArray } } function rec write_op(ctx,op,p) { match op { | "+" -> write ctx Add | "-" -> write ctx Sub | "/" -> write ctx Div | "*" -> write ctx Mult | "%" -> write ctx Mod | "<<" -> write ctx Shl | ">>" -> write ctx Shr | ">>>" -> write ctx UShr | "|" -> write ctx Or | "&" -> write ctx And | "^" -> write ctx Xor | "==" -> write ctx Eq | "!=" -> write ctx Neq | ">" -> write ctx Gt | ">=" -> write ctx Gte | "<" -> write ctx Lt | "<=" -> write ctx Lte | _ -> error "Unknown operation" p } } function rec compile_binop(ctx,tail,op,e1,e2,p) { match op { | "=" -> var a = compile_access ctx e1; compile ctx false e2; compile_access_set ctx a | "&&" -> compile ctx false e1; var jnext = cjmp false ctx; compile ctx tail e2; jnext() | "||" -> compile ctx false e1; var jnext = cjmp true ctx; compile ctx tail e2; jnext() | "++=" | "--=" -> write ctx Push; var base = ctx.stack; var a = compile_access ctx e1; compile_access_get ctx a; write ctx SetStack(ctx.stack - base); write ctx Push; compile ctx false e2; write_op ctx (String.sub op 0 (String.length op - 2)) p; compile_access_set ctx a; write ctx (AccStack 0); write ctx (Pop 1); | "+=" | "-=" | "/=" | "*=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "&=" | "^=" -> var a = compile_access ctx e1; compile_access_get ctx a; write ctx Push; compile ctx false e2; write_op ctx (String.sub op 0 (String.length op - 1)) p; compile_access_set ctx a | _ -> match (op , e1 , e2) { | ("==" , _ , (EConst Null,_)) -> compile ctx false e1; write ctx IsNull | ("!=" , _ , (EConst Null,_)) -> compile ctx false e1; write ctx IsNotNull | ("==" , (EConst Null,_) , _) -> compile ctx false e2; write ctx IsNull | ("!=" , (EConst Null,_) , _) -> compile ctx false e2; write ctx IsNotNull | ("-", (EConst (Int 0),_) , (EConst (Int i),_)) -> compile ctx tail (EConst (Int (-i)),p) | _ -> compile ctx false e1; write ctx Push; compile ctx false e2; write_op ctx op p } } } function rec compile_function(main,params,e) { var ctx = { g = main.g; // reset ops = Array.create(); pos = Array.create(); breaks = []; continues = []; env = Map.empty(); nenv = 0; traps = []; loop_traps = 0; limit = main.stack; // dup version = main.version; stack = main.stack; locals = main.locals; loop_limit = main.loop_limit; curpos = main.curpos; curfile = main.curfile; }; List.iter (function(v) { ctx.stack := ctx.stack + 1; ctx.locals := Map.add ctx.locals v ctx.stack; }) params; var s = ctx.stack; compile ctx true e; write ctx (Ret (ctx.stack - ctx.limit)); check_stack ctx s (snd e); check_breaks ctx; // add function var gid = Array.length ctx.g.gtable; ctx.g.functions := (ctx.ops,ctx.pos,gid,List.length params) :: ctx.g.functions; Array.add ctx.g.gtable GlobalFunction(gid,-1); // environment if ctx.nenv > 0 then { var a = Array.make ctx.nenv ""; Map.iter (function(v,i){ a.[i] := v }) ctx.env; Array.iter (function(v){ compile_constant main (Ident v) snd(e); write main Push; }) a; write main (AccGlobal gid); write main (MakeEnv ctx.nenv); } else write main (AccGlobal gid); } function rec compile_builtin(ctx,tail,b,el,p) { match (b , el) { | ("istrue" , [e]) -> compile ctx false e; write ctx Bool | ("not" , [e]) -> compile ctx false e; write ctx Not | ("typeof" , [e]) -> compile ctx false e; write ctx TypeOf | ("hash" , [e]) -> compile ctx false e; write ctx Hash | ("new" , [e]) -> compile ctx false e; write ctx New | ("compare" , [e1;e2]) -> compile ctx false e1; write ctx Push; compile ctx false e2; write ctx Compare | ("pcompare" , [e1;e2]) -> compile ctx false e1; write ctx Push; compile ctx false e2; write ctx PhysCompare | ("goto" , [(EConst (Ident l) , _)] ) -> var l = try Hashtbl.find ctx.g.labels l catch { Not_found -> error ("Unknown label " + l) p }; var os = ctx.stack; function rec loop(l1,l2) { match (l1,l2) { | (x :: l1 , y :: l2) when x == y -> loop l1 l2 | _ -> (l1,l2) } } var straps , dtraps = loop List.rev(ctx.traps) l.ltraps; List.iter (function(l) { if ctx.stack != l then write ctx Pop(ctx.stack - l); write ctx EndTrap; }) List.rev(straps); var dtraps = List.map (function(l) { var l = l - trap_stack_delta; if l < ctx.stack then write ctx Pop(ctx.stack - l); while ctx.stack < l { write ctx Push; } trap ctx }) dtraps; if l.lstack < ctx.stack then write ctx Pop(ctx.stack - l.lstack); while l.lstack > ctx.stack { write ctx Push }; ctx.stack := os; match l.lpos { | None -> l.lwait := jmp ctx :: l.lwait | Some p -> write ctx (Jump p) }; List.iter (function(t) { t(); write ctx Push; compile_constant ctx (Builtin "throw") p; write ctx (Call 1); // insert an infinite loop in order to // comply with bytecode checker ignore(jmp ctx) }) dtraps; | ("goto" , _) -> error "Invalid $goto statement" p | ("array",e :: el) -> var count = List.length el; // a single function can't have >128 stack if count > 120 - ctx.stack && count > 8 then { // split in 8 and recurse var part = count >> 3; function rec loop(el,acc,count) { match el { | [] -> [List.rev acc] | e :: l -> if count == part then List.rev(acc) :: loop el [] 0 else loop l (e :: acc) (count + 1) } } var arr = make_array p (List.map make_array(p) (loop (e :: el) [] 0)); compile_builtin ctx tail "aconcat" [arr] p; } else if ctx.version >= 2 then { compile ctx false e; List.iter (function(e) { write ctx Push; compile ctx false e; }) el; write ctx (MakeArray count); } else { List.iter (function(e) { compile ctx false e; write ctx Push; }) el; compile ctx false e; write ctx (MakeArray count); } | ("apply",e :: el) -> List.iter (function(e) { compile ctx false e; write ctx Push; }) el; compile ctx false e; var nargs = List.length el; if nargs > 0 then write ctx (Apply nargs); | _ -> List.iter (function(e) { compile ctx false e; write ctx Push; }) el; compile_constant ctx (Builtin b) p; if tail then write ctx TailCall(List.length el,ctx.stack - ctx.limit) else write ctx Call(List.length el) } } function rec compile(ctx,tail,(e,p)) { set_pos ctx p; match e { | EConst c -> compile_constant ctx c p | EBlock [] -> write ctx AccNull | EBlock el -> var locals = ctx.locals; var stack = ctx.stack; function rec loop(el) { match el { | [] -> assert() | [e] -> compile ctx tail e | [e; (ELabel _,_) as f] -> compile ctx tail e; compile ctx tail f | e :: el -> compile ctx false e; loop el } } loop el; if stack < ctx.stack then write ctx (Pop (ctx.stack - stack)); check_stack ctx stack p; ctx.locals := locals | EParenthesis e -> compile ctx tail e | EField (e,f) -> compile ctx false e; write ctx (AccField f) | ECall (e,a :: b :: c :: d :: x1 :: x2 :: l) when match e { (EConst (Builtin "array"),_) -> false | _ -> true } -> var call = (EConst (Builtin "call"),p); var args = (ECall (EConst (Builtin "array"),p) (a :: b :: c :: d :: x1 :: x2 :: l),p); match e { | (EField (e,name) , p2) -> var locals = ctx.locals; var etmp = (EConst (Ident "$tmp"),p2); compile ctx false (EVars [("$tmp",Some e)],p2); compile ctx tail (ECall call [(EField etmp name,p2);etmp;args], p); write ctx (Pop 1); ctx.locals := locals | _ -> compile ctx tail (ECall call [e; (EConst This,p); args],p); } | ECall ((EConst (Builtin b),_),el) -> compile_builtin ctx tail b el p | ECall ((EField (e,f),_),el) -> List.iter (function(e) { compile ctx false e; write ctx Push; }) el; compile ctx false e; write ctx Push; write ctx (AccField f); write ctx ObjCall(List.length el) | ECall (e,el) -> List.iter (function(e) { compile ctx false e; write ctx Push; }) el; compile ctx false e; if tail then write ctx TailCall(List.length el,ctx.stack - ctx.limit) else write ctx Call(List.length el) | EArray (e1,(EConst (Int n),_)) -> compile ctx false e1; write ctx (if n == 0 then AccIndex0 else if n == 1 then AccIndex1 else AccIndex n) | EArray (e1,e2) -> compile ctx false e1; write ctx Push; compile ctx false e2; write ctx AccArray | EVars vl -> List.iter (function((v,o)) { match o { | None -> write ctx AccNull | Some e -> compile ctx false e }; write ctx Push; ctx.locals := Map.add ctx.locals v ctx.stack; }) vl | EWhile (econd,e,NormalWhile) -> var start = pos ctx; if ctx.version >= 2 then write ctx Loop; compile ctx false econd; var jend = cjmp false ctx; var save = save_breaks ctx; compile ctx false e; process_continues save; goto ctx start; process_breaks save; jend(); | EWhile (econd,e,DoWhile) -> var start = pos ctx; if ctx.version >= 2 then write ctx Loop; var save = save_breaks ctx; compile ctx false e; process_continues save; compile ctx false econd; write ctx (JumpIf (start - pos ctx)); process_breaks save | EIf (e,e1,e2) -> var stack = ctx.stack; compile ctx false e; var jelse = cjmp false ctx; compile ctx tail e1; check_stack ctx stack p; match e2 { | None -> jelse() | Some e2 -> var jend = jmp ctx; jelse(); compile ctx tail e2; check_stack ctx stack p; jend() }; | ETry (e,v,ecatch) -> var trap = trap ctx; ctx.traps := ctx.stack :: ctx.traps; compile ctx false e; write ctx EndTrap; ctx.traps := match ctx.traps { [] -> assert() | _ :: l -> l }; var jend = jmp ctx; trap(); write ctx Push; var locals = ctx.locals; ctx.locals := Map.add ctx.locals v ctx.stack; compile ctx tail ecatch; write ctx (Pop 1); ctx.locals := locals; jend() | EBinop (op,e1,e2) -> compile_binop ctx tail op e1 e2 p | EReturn e -> match e { None -> write ctx AccNull | Some e -> compile ctx (ctx.traps == []) e }; var stack = ctx.stack; List.iter (function(t) { if ctx.stack > t then write ctx Pop(ctx.stack - t); write ctx EndTrap; }) ctx.traps; write ctx (Ret (ctx.stack - ctx.limit)); ctx.stack := stack | EBreak e -> match e { | None -> () | Some e -> compile ctx false e }; var s = ctx.stack; var n = &(List.length ctx.traps - ctx.loop_traps); List.iter (function(t) { if *n > 0 then { n := *n - 1; if ctx.stack > t then write ctx Pop(ctx.stack - t); write ctx EndTrap; } }) ctx.traps; if ctx.loop_limit != ctx.stack then write ctx Pop(ctx.stack - ctx.loop_limit); ctx.stack := s; ctx.breaks := (jmp ctx , p) :: ctx.breaks | EContinue -> var s = ctx.stack; var n = &(List.length ctx.traps - ctx.loop_traps); List.iter (function(t) { if *n > 0 then { n := *n - 1; if ctx.stack > t then write ctx Pop(ctx.stack - t); write ctx EndTrap; } }) ctx.traps; if ctx.loop_limit != ctx.stack then write ctx Pop(ctx.stack - ctx.loop_limit); ctx.stack := s; ctx.continues := (jmp ctx , p) :: ctx.continues | EFunction (params,e) -> compile_function ctx params e | ENext (e1,e2) -> compile ctx false e1; compile ctx tail e2 | EObject [] -> write ctx AccNull; write ctx New | EObject fl -> var fields = List.sort compare (List.map fst fl); var id = try Hashtbl.find ctx.g.gobjects fields catch { Not_found -> var id = global ctx (GlobalVar ("o:" + Hashtbl.length ctx.g.gobjects)); Hashtbl.add ctx.g.gobjects fields id; id }; write ctx (AccGlobal id); write ctx New; write ctx Push; List.iter (function((f,e)) { write ctx Push; compile ctx false e; write ctx (SetField f); write ctx AccStack0; }) fl; write ctx (Pop 1) | ELabel l -> var l = try Hashtbl.find ctx.g.labels l catch { Not_found -> assert() }; if ctx.stack != l.lstack || List.rev(ctx.traps) != l.ltraps then error (sprintf "Label failure %d %d %s %s" (ctx.stack,l.lstack,string List.rev(ctx.traps),string l.ltraps)) p; List.iter (function(f) { f() }) l.lwait; l.lwait := []; l.lpos := Some (pos ctx) | ESwitch (e,[(econd,exec)],eo) -> compile ctx tail (EIf (EBinop "==" e econd,p) exec eo,p) | ESwitch (e,cases,eo) -> try { var ints , size = get_cases_ints cases; compile ctx false e; write ctx (JumpTable size); var tbl = Array.make size None; List.iter (function((i,e)) { tbl.[i] := Some e; }) ints; var tbl = Array.map (function(e) { (jmp ctx,e) }) tbl; Array.iter (function((j,e)) { if e == None then j() }) tbl; match eo { | None -> write ctx AccNull | Some e -> compile ctx tail e } var jump_end = jmp ctx; var tbl = Array.map (function((j,e)) { match e { | Some e -> j(); compile ctx tail e; jmp ctx | None -> function() { } } }) tbl; jump_end(); Array.iter (function(j) { j() }) tbl } catch { Exit -> compile ctx false e; write ctx Push; var jumps = List.map (function((e1,e2)) { write ctx AccStack0; write ctx Push; compile ctx false e1; write ctx Eq; (cjmp true ctx , e2) }) cases; match eo { | None -> write ctx AccNull | Some e -> compile ctx tail (EBlock [e],p) } var jump_end = jmp ctx; var jumps = List.map (function((j,e)) { j(); compile ctx tail (EBlock [e],p); jmp ctx; }) jumps; jump_end(); List.iter (function(j) { j() }) jumps; write ctx (Pop 1) } } } function compile(version,ast) { var g = { globals = Hashtbl.create(); gobjects = Hashtbl.create(); gtable = Array.create(); functions = []; labels = Hashtbl.create(); hfiles = Hashtbl.create(); files = Array.create(); }; var ctx = { g = g; version = version; stack = 0; loop_limit = 0; loop_traps = 0; limit = -1; locals = Map.empty(); ops = Array.create(); breaks = []; continues = []; env = Map.empty(); nenv = 0; traps = []; pos = Array.create(); curpos = (0,0); curfile = "_"; }; if version >= 2 then Array.add g.gtable (GlobalVersion version); scan_labels ctx true true ast; compile ctx false ast; check_breaks ctx; if g.functions != [] || Hashtbl.length g.gobjects != 0 then { var ctxops = ctx.ops; var ctxpos = ctx.pos; var ops = Array.create(); var pos = Array.create(); ctx.pos := pos; ctx.ops := ops; write ctx (Jump 0); List.iter (function((fops,fpos,gid,nargs)) { Array.set g.gtable gid GlobalFunction(Array.length ops,nargs); Array.append fops ops; Array.append fpos pos; }) (List.rev g.functions); Array.set ops 0 (Jump (Array.length ops)); var objects = Array.create(); Hashtbl.iter (function(fl,g) Array.add objects (fl,g)) g.gobjects; Array.sort (function((_,g1),(_,g2)) g1 - g2) objects; Array.iter (function((fl,g)) { write ctx AccNull; write ctx New; write ctx (SetGlobal g); List.iter (function(f) { write ctx (AccGlobal g); write ctx Push; write ctx (SetField f); }) fl }) objects; Array.append ctxpos pos; Array.append ctxops ops; }; Array.add g.gtable (GlobalDebug ctx.g.files ctx.pos); (g.gtable, ctx.ops) } neko-2-2-0/src/neko/Console.nml000066400000000000000000000067451321613172000163120ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ function read() { var buf = Buffer.create(); function rec loop() { var l = IO.read_line IO.stdin; var len = String.length l; if len > 0 && String.get l (len - 1) == '!' then Buffer.add buf (String.sub l 0 (len - 1)) else { Buffer.add buf l; Buffer.add_char buf '\n'; loop(); } } loop(); Buffer.string buf } function report(msg,p) { IO.printf IO.stderr "%s(%d): %s\n" (Lexer.source p,Lexer.line p,msg); } function run(version) { var ctx = Hashtbl.create(); function loop() { // read input print "> "; var code = read(); var bytecode , module = if String.length code > 6 && String.sub code 0 6 == "#load " then { // load bytecode var file = String.sub code 6 (String.length code - 6); var input = IO.read_file file true; var bytecode = Neko.Bytecode.read input; IO.close_in input; var input = IO.read_file file true; var str = IO.read_all input; IO.close_in input; (bytecode, str) } else { // parse and compile var input = IO.read_string code; var lex = Lexer.create Buffer.create(); Lexer.input lex "@console" input 1 0; var ast = Neko.Parser.parse lex; var bytecode = Neko.Compile.compile version ast; var output , str = IO.write_string(); Neko.Bytecode.write output bytecode; (bytecode , str()) } // read compiled module var m = Reflect.module_read (IO.input (IO.read_string module)); // set module environement var globals = fst bytecode; Array.iteri (function(i,g) { match g { | Neko.Bytecode.GlobalVar v -> try { var v = Hashtbl.find ctx v; Reflect.module_set_global m i v } catch { Not_found -> () } | _ -> () } }) globals; // execute try { nprint Reflect.neko_value(Reflect.module_execute m); nprint "\n"; } catch { e -> var st = Stack.exc(); Stack.dump IO.stdout st; print "Exception : "; match e { | Neko_error e -> nprint e | _ -> print e } print "\n"; } // save environment Array.iteri (function(i,g) { match g { | Neko.Bytecode.GlobalVar v -> Hashtbl.replace ctx v (Reflect.module_get_global m i) | _ -> () } }) globals; } while true { try { loop() } catch { | Neko.Lexer.Error(msg,pos) -> report Neko.Lexer.error_msg(msg) pos | Neko.Parser.Error(msg,pos) -> report Neko.Parser.error_msg(msg) pos | Neko.Compile.Error(msg,pos) -> report Neko.Compile.error_msg(msg) pos } } }neko-2-2-0/src/neko/Doc.nml000066400000000000000000000221071321613172000154030ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type doc_type { TBase : string; TAbstract : string; TCustom : string; TFun : (doc_type, doc_type); TOpt : doc_type; TStar : doc_type; TMult : doc_type list; TObj : (string , doc_type) list; TNamed : (string , doc_type); TPoly : (string, doc_type); TFunction : int; } type doc_item { Function : (string , doc_type, Xml.t option); Document : Xml.t; } type doc = doc_item list type token { Eof; Begin; End; Star; Question; Arrow; DoubleDot; POpen; PClose; BrOpen; BrClose; Comma; Field; Or; Quote; Sharp; Int : int; Doc : Xml.t; Ident : string; } type status { mutable doc : bool; buf : Buffer.t; } type error_msg { Unexpected : token; Invalid_char : char; Unknown_type : string; Unclosed_doc; Invalid_doc; } exception Error : (error_msg,Lexer.pos); function error(msg,p) { throw Error(msg,p) } function s_token(t) { match t { | Eof -> "" | Begin -> "/**" | End -> "**/" | DoubleDot -> ":" | Arrow -> "->" | Star -> "*" | POpen -> "(" | PClose -> ")" | BrOpen -> "{" | BrClose -> "}" | Comma -> "," | Field -> "=>" | Or -> "|" | Quote -> "'" | Sharp -> "#" | Question -> "?" | Int i -> string i | Ident i -> i | Doc d -> ""+Xml.to_string d+"" } } function error_msg(msg) { match msg { | Unexpected t -> "Unexpected " + s_token t | Invalid_char c -> "Invalid character " + String.escape_char c | Unknown_type s -> "Unknown type " + s | Unclosed_doc -> "Unclosed doc tag" | Invalid_doc -> "Documentation is not XHTML valid" } } function mk_tok(l,t) { (t,Lexer.curpos l) } function status() { { buf = Buffer.create(); doc = false; } } var doc_token = &Lexer.empty(); var doc_content = &Lexer.empty(); var doc_doc = &Lexer.empty(); doc_token := Lexer.build [ ("/\\*\\*" , function(l) { (Lexer.data l).doc := true; mk_tok l Begin }); ("/" , function(l) { Lexer.token l (*doc_token) }); ("[^/]+", function(l) { Lexer.token l (*doc_token) }); ] (function(l) { mk_tok l Eof }); doc_content := Lexer.build [ ("\\*\\*/", function(l) { (Lexer.data l).doc := false; mk_tok l End }); (":", function(l) { mk_tok l DoubleDot }); ("(", function(l) { mk_tok l POpen }); (")", function(l) { mk_tok l PClose }); ("{", function(l) { mk_tok l BrOpen }); ("}", function(l) { mk_tok l BrClose }); (",", function(l) { mk_tok l Comma }); ("=>", function(l) { mk_tok l Field }); ("|", function(l) { mk_tok l Or }); ("->", function(l) { mk_tok l Arrow }); ("\\*", function(l) { mk_tok l Star }); ("\\?", function(l) { mk_tok l Question }); ("'", function(l) { mk_tok l Quote }); ("#", function(l) { mk_tok l Sharp }); ("", function(l) { var p1 = Lexer.curpos l; var buf = (Lexer.data l).buf; Buffer.reset buf; try Lexer.token l (*doc_doc) catch { Exit -> error Unclosed_doc p1 }; var p2 = Lexer.curpos l; var x = try Xml.parse (Buffer.string buf) catch { _ -> error Invalid_doc p1 }; (Doc x, Lexer.punion p1 p2) }); ("[ \t\r\n]+", function(l) { Lexer.token l (*doc_content) }); ("[0-9]+", function(l) { mk_tok l Int(int (Lexer.current l)) }); ("$?[a-zA-Z_@][a-zA-Z0-9_@]*", function(l) { mk_tok l Ident(Lexer.current l) }); ] (function(l) { match Lexer.char l { | None -> mk_tok l Eof | Some c -> error Invalid_char(c) Lexer.curpos(l) } }); doc_doc := Lexer.build [ ("", function(l) { }); ("<", function(l) { Buffer.add_char (Lexer.data l).buf '<'; Lexer.token l (*doc_doc) }); ("[^<]+", function(l) { Buffer.add (Lexer.data l).buf Lexer.current(l); Lexer.token l (*doc_doc) }); ] (function(l) { throw Exit }); function rec documentation(s) { match s { | [< (Eof,_) >] -> [] | [< (Begin,_); d = document s; (End,_); l = documentation s >] -> d :: l } } function rec document(s) { match s { | [< (Ident i,_); (DoubleDot,_); t = doc_type s; d = doc_option s >] -> Function i t d | [< (Doc d,_) >] -> Document d } } function rec doc_option(s) { match s { | [< (Doc d,_) >] -> Some d | [< >] -> None } } function rec doc_type(s) { match s { | [< t = doc_type_base s >] -> doc_type_next t s } } function rec doc_type_base(s) { match s { | [< (Quote,_); (Ident i,_); >] -> TAbstract i | [< (Sharp,_); (Ident i,_); >] -> TCustom i | [< (Ident i,p) >] -> match i { | "null" | "int" | "float" | "string" | "array" | "bool" | "any" | "void" | "number" | "object" -> TBase i | "function" -> match s { | [< (DoubleDot,_); (Int n,_) >] -> TFunction n | [< >] -> TBase i } | _ -> match s { | [< (DoubleDot,_); t = doc_type_base s >] -> TNamed i t | [< >] -> error Unknown_type(i) p } } | [< (POpen,_); t = doc_type s; l = doc_type_list s; (PClose,_) >] -> TMult (t :: l) | [< (BrOpen,_); f = doc_type_fields s; (BrClose,_) >] -> TObj f } } function rec doc_type_next(t,s) { match s { | [< (Arrow,_); t2 = doc_type s >] -> doc_type_next (TFun t t2) s | [< (Star,_) >] -> doc_type_next (TStar t) s | [< (Question,_) >] -> doc_type_next (TOpt t) s | [< (Ident "array",_) >] -> doc_type_next TPoly("array",t) s | [< (Ident "list",_) >] -> doc_type_next TPoly("list",t) s | [< >] -> t } } function rec doc_type_list(s) { match s { | [< (Or,_); t = doc_type s; l = doc_type_list s >] -> t :: l | [< >] -> [] } } function rec doc_type_fields(s) { match s { | [< (Ident i,_); (Field,_); t = doc_type s >] -> (i,t) :: doc_type_fields s | [< (Comma,_) >] -> doc_type_fields s | [< >] -> [] } } function parse(lex) : doc { var last = &(Eof,Lexer.null_pos); function rec next_token() { var t = Lexer.token lex (if (Lexer.data lex).doc then (*doc_content) else (*doc_token)); last := t; t } try { documentation (stream next_token) } catch { Stream_error -> error Unexpected(fst(*last)) snd(*last) } } function rec type_write(ch,t) { match t { | TBase b -> IO.write ch b | TAbstract a -> IO.printf ch "'%s" a | TCustom s -> IO.printf ch "#%s" s | TFun (t1,t2) -> type_write_par ch t1; IO.write ch " -> "; type_write ch t2 | TOpt t -> type_write_par ch t; IO.write ch "?" | TStar t -> type_write_par ch t; IO.write ch "*" | TMult l -> IO.write ch "("; function rec loop(l) { match l { | [] -> () | [t] -> type_write_par ch t | t :: l -> type_write_par ch t; IO.write ch " | "; loop l } } loop l; IO.write ch ")" | TObj l -> IO.write ch "{ "; function rec loop(l) { match l { | [] -> () | [(n,t)] -> IO.write ch n; IO.write ch " => "; type_write ch t; | (n,t) :: l -> IO.write ch n; IO.write ch " => "; type_write ch t; IO.write ch ", "; loop l } } loop l; IO.write ch "}"; | TNamed (s,t) -> IO.printf ch "%s : " s; type_write_par ch t | TPoly (s,t) -> type_write_par ch t; IO.printf ch " %s" s | TFunction n -> IO.printf ch "function:%d" n } } function rec type_write_par(ch,t) { match t { | TFun _ -> IO.write ch "("; type_write ch t; IO.write ch ")"; | _ -> type_write ch t; } } function format_xml(s) { var s = String.concat "" (String.split s "["); var s = String.concat "" (String.split s "]"); s } function to_html(ch,doc) { List.iter (function(d) { match d { | Document x -> IO.write ch (format_xml Xml.to_string(x)); IO.write ch "\n" | Function (f,t,doc) -> IO.write ch "\n"; function rec loop(t) { match t { | TFun (p,r) -> var args , r = loop r; (p :: args, r) | _ -> ([],t) } } var args , r = loop t; match args { | [] -> IO.printf ch " %s : " f; type_write ch r; | _ -> IO.write ch " "; type_write_par ch r; IO.printf ch " %s(" f; function rec loop(l) { match l { | [] -> () | [t] -> type_write ch t | t :: l -> type_write ch t; IO.write ch ", "; loop l } } match args { | [TBase "void"] -> () | _ -> loop args } IO.write ch ")"; } IO.write ch " "; match doc { | None -> () | Some x -> IO.write ch (format_xml Xml.to_string(x)) } IO.write ch "\n\n"; } }) doc; }neko-2-2-0/src/neko/Lexer.nml000066400000000000000000000136261321613172000157630ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Neko.Ast; type error_msg { Invalid_character : char; Unterminated_string; Unclosed_comment; Unclosed_nxml; Invalid_escaped_character : int; Invalid_escape; } exception Error : (error_msg , Lexer.pos) function error_msg(msg) { match msg { | Invalid_character c when ord c > 32 && ord c < 128 -> sprintf "Invalid character '%c'" c | Invalid_character c -> sprintf "Invalid character 0x%.2X" (ord c) | Unterminated_string -> "Unterminated string" | Unclosed_comment -> "Unclosed comment" | Unclosed_nxml -> "Unclosed nxml" | Invalid_escaped_character n -> sprintf "Invalid escaped character %d" n | Invalid_escape -> "Invalid escape sequence" } } function error(l,msg) { throw Error(msg,Lexer.curpos l) } var keywords = { var h = Hashtbl.create(); List.iter (function(k) { Hashtbl.add h (s_keyword k) k }) [Var;While;Do;If;Else;Function;Return;Break;Continue;Try;Catch;Switch;Default]; h } function mk(l,t) { (t,Lexer.curpos l) } function mk_int(l) { mk l Const(Int(int (Lexer.current l))) } function mk_float(l) { mk l Const(Float(Lexer.current l)) } function mk_ident(l) { var s = Lexer.current l; mk l (try Keyword (Hashtbl.find keywords s) catch { Not_found -> Const (Ident s) }) } var ident = "[a-zA-Z_@][a-zA-Z0-9_@]*"; var binop = "[-!=\\*/<>&|^%\\+:]"; var expr = &Lexer.empty(); var estring = &Lexer.empty(); var ecomment = &Lexer.empty(); var enxml = &Lexer.empty(); function comment(l) { Lexer.token l (*ecomment) } function str(l) { Lexer.token l (*estring) }; function nxml(l) { Lexer.token l (*enxml) } exception Continue : bool; expr := Lexer.build [ (";", function(l) { mk l Semicolon }); (".", function(l) { mk l Dot }); (",", function(l) { mk l Comma }); ("{", function(l) { mk l BraceOpen }); ("}", function(l) { mk l BraceClose }); ("(", function(l) { mk l ParentOpen }); (")", function(l) { mk l ParentClose }); ("\\[", function(l) { mk l BracketOpen }); ("]", function(l) { mk l BracketClose }); ("=>", function(l) { mk l Arrow }); ("[ \r\t\n]+", function(l) { Lexer.token l (*expr) }); ("0x[0-9a-fA-F]+", mk_int); ("[0-9]+", mk_int); ("[0-9]+.[0-9]*", mk_float); (".[0-9]+", mk_float); ("$"+ident, function(l) { var s = Lexer.current l; var s = String.sub s 1 (String.length s - 1); mk l Const(Builtin s) }); ("true", function(l) { mk l (Const True) }); ("false", function(l) { mk l (Const False) }); ("null", function(l) { mk l (Const Null) }); ("this", function(l) { mk l (Const This) }); (ident , function(l) { mk_ident l }); ("\"", function(l) { var p1 = Lexer.curpos l; var buf = Lexer.data l; Buffer.reset buf; try str l catch { Exit -> throw Error(Unterminated_string,p1) }; var p2 = Lexer.curpos l; (Const String(Buffer.string buf) , Lexer.punion p1 p2) }); ("/\\*", function(l) { var p1 = Lexer.curpos l; var buf = Lexer.data l; Buffer.reset buf; try comment l catch { Exit -> throw Error(Unclosed_comment,p1) }; var p2 = Lexer.curpos l; (Comment(Buffer.string buf) , Lexer.punion p1 p2) }); ("//[^\r\n]*\n?", function(l) { var s = Lexer.current l; var len = String.length s; var n = (if String.get s (len - 1) == '\r' then 3 else 2); mk l CommentLine(String.sub s 0 (len - n)) }); (binop + binop + "?",function(l) { mk l (Binop (Lexer.current l)) }); (binop + binop + "=",function(l) { mk l (Binop (Lexer.current l)) }); (">>>",function(l) { mk l (Binop ">>>") }); (">>>=",function(l) { mk l (Binop ">>>=") }); ] (function(l) { match Lexer.char l { | None -> mk l Eof | Some c -> error l (Invalid_character c) } }); ; ecomment := Lexer.build [ ("\\*/", function(l) { }); ("\\*", function(l) { Buffer.add (Lexer.data l) (Lexer.current l); comment l }); ("[^*]+", function(l) { Buffer.add (Lexer.data l) (Lexer.current l); comment l }); ] (function(l) { throw Exit }); estring := Lexer.build [ ("\\\\\"", function(l) { Buffer.add_char (Lexer.data l) '"'; str l }); ("\\\\\\\\", function(l) { Buffer.add_char (Lexer.data l) '\\'; str l }); ("\\\\n", function(l) { Buffer.add_char (Lexer.data l) '\n'; str l }); ("\\\\t", function(l) { Buffer.add_char (Lexer.data l) '\t'; str l }); ("\\\\r", function(l) { Buffer.add_char (Lexer.data l) '\r'; str l }); ("\\\\[0-9][0-9][0-9]", function(l) { var k = int (String.sub (Lexer.current l) 1 3); if k > 255 then error l (Invalid_escaped_character k); Buffer.add_char (Lexer.data l) (chr k); str l }); ("\\\\" , function(l) { error l Invalid_escape }); ("\"" , function(l) { }); ("[^\\\\\"]+", function(l) { Buffer.add (Lexer.data l) (Lexer.current l); str l }); ] (function(l) { throw Exit }); enxml := Lexer.build [ ("", function(l) { throw Continue(false) }); ("<",function(l) { Buffer.add_char (Lexer.data l) '<'; throw Continue(true) }); ("[^<]+", function(l) { Buffer.add (Lexer.data l) (Lexer.current l); nxml l }); ] (function(l) { throw Exit }); neko-2-2-0/src/neko/Linker.nml000066400000000000000000000135401321613172000161230ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Neko.Bytecode; type context { globals : global array; opcodes : opcode array; debug : (int, int) array; debug_files : string array; loaded : (string, int option) Hashtbl.t; mutable version : int option; mutable have_debug : bool; } var neko_path : string list = neko "@List.@make($loader.path)"; function file_open(file) { function rec loop(l) { match l { | [] -> throw Error("File not found : " + file) | p :: l -> try IO.read_file (p + file) true; catch { _ -> loop l } } } loop ("" :: neko_path) } function rec do_link(ctx,module) { print (module + "\n"); var ch = file_open (module + ".n"); var globals, opcodes = Neko.Bytecode.read ch; IO.close_in ch; var debug = &None; var funcs = &[]; var version = &0; var gtbl = Array.map (function(g) { match g { | GlobalVar _ -> var k = Array.length ctx.globals; Array.add ctx.globals g; k | GlobalFunction (p,nargs) -> var k = Array.length ctx.globals; Array.add ctx.globals g; funcs := (p,nargs,k) :: *funcs; k | GlobalString _ | GlobalFloat _ -> try Array.index ctx.globals g catch { Not_found -> var k = Array.length ctx.globals; Array.add ctx.globals g; k } | GlobalDebug(files,inf) -> ctx.have_debug := true; debug := Some (files,inf); -1 | GlobalVersion v -> if ctx.version == None then { ctx.version := Some v; Array.add ctx.globals GlobalVersion(v); } version := v; -1 } }) globals; match ctx.version { | None -> ctx.version := Some (*version); | Some v2 -> if v2 != (*version) then throw Error("Linking modules with different version"); } var mid = Array.length ctx.globals; var module_fid = Array.length ctx.debug_files; Array.add ctx.debug_files module; Array.add ctx.globals (GlobalVar module); List.iter (Array.add ctx.opcodes) [AccNull; Push; AccBuiltin "new"; Call 1; SetGlobal mid]; Array.append (Array.make 8 (module_fid,0)) ctx.debug; Hashtbl.add ctx.loaded module None; var nops = Array.length opcodes; var opmap = Array.make nops (-1); var debug = match *debug { | None -> Array.make (nops*2) (module_fid,0) | Some(files,inf) -> var fmap = Array.map (function(f) { var p = Array.length ctx.debug_files; Array.add ctx.debug_files f; p }) files; Array.map (function((f,p)) { (fmap.[f],p) }) inf }; var debug_pos = &0; var jumps = &[]; function op(o) { Array.add ctx.opcodes o; Array.add ctx.debug (Array.get debug (*debug_pos)); debug_pos := *debug_pos + 1; if Neko.Bytecode.op_param o then { Array.add ctx.debug (Array.get debug (*debug_pos)); debug_pos := *debug_pos + 1; } } function jump(mkop,p,i) { var k = Array.length ctx.opcodes; op (Jump 0); jumps := (mkop,k,p,i) :: *jumps } function rec loop((p,l)) { match l { | [] -> assert() // $loader.loadmodule("name",$loader) | (AccGlobal str) :: Push :: (AccBuiltin "loader") :: Push :: (AccBuiltin "loader") :: Push :: (AccField "loadmodule") :: (ObjCall 2) :: l -> match Array.get globals str { | GlobalString s -> var mid = try Hashtbl.find ctx.loaded s catch { Not_found -> Some (do_link ctx s) }; match mid { | None -> throw Error("Recursive loading " + module + " => " + s) | Some i -> op (AccGlobal i); debug_pos := *debug_pos + 11; (p + 8, l) } | _ -> throw Error("Cannot link not constant file") } | o :: l -> Array.set opmap p (Array.length ctx.opcodes); match o { | AccBuiltin "exports" -> op (AccGlobal mid) | AccGlobal g -> op (AccGlobal (Array.get gtbl g)); | SetGlobal g -> op (SetGlobal (Array.get gtbl g)); | Jump i -> jump Jump p i | JumpIf i -> jump JumpIf p i | JumpIfNot i -> jump JumpIfNot p i | Trap i -> jump Trap p i | _ -> op o } (p+1 , l) } } var l = &(0,Array.list opcodes); while snd (*l) != [] { l := loop (*l) } List.iter (function((op,k,p,i)) { var ik = Array.get opmap (p + i) - Array.get opmap p; Array.set ctx.opcodes k op(ik) }) (*jumps); List.iter (function((p,nargs,k)) { Array.set ctx.globals k (GlobalFunction (Array.get opmap p) nargs) }) (*funcs); Hashtbl.replace ctx.loaded module (Some mid); Array.add ctx.opcodes (AccGlobal mid); Array.add ctx.debug (module_fid,0); Array.add ctx.debug (module_fid,0); mid } function link(output,modules) { var ctx = { globals = Array.create(); opcodes = Array.create(); debug = Array.create(); debug_files = Array.create(); loaded = Hashtbl.create(); have_debug = false; version = None; }; List.iter (function(m) { ignore(do_link ctx m) }) modules; if ctx.have_debug then Array.add ctx.globals (GlobalDebug ctx.debug_files ctx.debug); var ch = IO.write_file output true; Neko.Bytecode.write ch (ctx.globals,ctx.opcodes); IO.close_out ch } neko-2-2-0/src/neko/Main.nml000066400000000000000000000127471321613172000155730ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ var dir = &None; var verbose = &false; function out(file,ext) { var file = Sys.without_extension file + ext; match *dir { | None -> file | Some dir -> dir + Sys.without_dir file } } function is_nxml(str) { var len = String.length str; if len <= 10 || String.sub str 0 6 != "" then None else if String.sub str (len - 7) 7 == "" then Some (String.sub str 6 (len - 13)) else if String.sub str (len - 8) 8 == "\n" then Some (String.sub str 6 (len - 14)) else if String.sub str (len - 9) 9 == "\r\n" then Some (String.sub str 6 (len - 15)) else None } function parse_multiformat(file) { var str = IO.file_contents file; match is_nxml str { | Some nxml -> Neko.Xml.parse nxml Lexer.null_pos | None when String.length str > 4 && String.sub str 0 4 == Neko.Binast.header -> Neko.Binast.parse (IO.read_string str) Lexer.null_pos | None -> var i = IO.read_string str; var lex = Lexer.create Buffer.create(); Lexer.input lex file i 1 0; Neko.Parser.parse lex; } } function compile(version,file) { if *verbose then printf "Compiling %s\n" file; var ast = parse_multiformat file; var code = Neko.Compile.compile version ast; var o = IO.write_file out(file,".n") true; Neko.Bytecode.write o code; IO.close_out o } function dump(file) { if *verbose then printf "Dumping %s\n" file; var i = IO.read_file file true; var code = Neko.Bytecode.read i; IO.close_in i; var o = IO.write_file out(file,".dump") false; Neko.Bytecode.dump o code; IO.close_out o } function print_ast(file) { if *verbose then printf "Printing %s\n" file; var ast = parse_multiformat file; var o = IO.write_file out(file,"2.neko") false; Neko.Printer.print Neko.Printer.create(o) ast; IO.close_out o } function release(file) { if *verbose then printf "Releasing %s\n" file; var i = IO.read_file file true; var globals, code = Neko.Bytecode.read i; IO.close_in i; var globals = Array.map (function(g) { match g { | Neko.Bytecode.GlobalVar _ | Neko.Bytecode.GlobalDebug _ -> Neko.Bytecode.GlobalVar "" | _ -> g } }) globals; var o = IO.write_file out(file,".n") true; Neko.Bytecode.write o (globals,code); IO.close_out o } function documentation(file) { if *verbose then printf "Building documentation for %s\n" file; var i = IO.read_file file false; var lex = Lexer.create Neko.Doc.status(); Lexer.input lex file i 1 0; var doc = Neko.Doc.parse lex; IO.close_in i; var o = IO.write_file out(file,".html") false; Neko.Doc.to_html o doc; IO.close_out o } function report(msg,p) { if p == Lexer.null_pos then { Stack.dump IO.stderr Stack.exc(); IO.printf IO.stderr "Exception : %s\n" msg } else IO.printf IO.stderr "%s(%d): %s\n" (Lexer.source p,Lexer.line p,msg); Sys.exit(-1); } function complete(dir) { var l = String.length dir; if l > 0 && String.get dir (l - 1) != '/' && String.get dir (l - 1) != '\\' then dir + "/" else dir } try { var v = Sys.version; var head = "Neko Compiler v" + v.maj + "." + v.min + "." + v.build + " - (c)2005-2017 Haxe Foundation\n Usage : neko [options] files..."; var link = &None; var links = &[]; var version = &0; var decl = [ ("-d", Args.String (function(f) { dump f }) , " : dump bytecode"); ("-z", Args.String (function(f) { release f }), " : make bytecode release"); ("-p", Args.String (function(f) { print_ast f }), " : parse and print neko source"); ("-doc", Args.String (function(f) { documentation f }) , " : make documentation"); ("-o", Args.String (function(f) { dir := Some (complete f) })," : set output directory"); ("-console", Args.Void (function() { Neko.Console.run(*version) }),": run the console"); ("-link", Args.String (function(f) { link := Some f })," : link bytecodes files"); ("-v", Args.Void (function() { verbose := true }) , ": verbose mode"); ("-version", Args.Int (function(v) version := v), ": set the bytecode version"); ]; Args.parse head decl (function(f) { match *link { | None -> compile (*version) f | Some _ -> links := f :: *links } }); match *link { None -> () | Some f -> Neko.Linker.link f List.rev(*links) }; } catch { | Neko.Lexer.Error(msg,pos) -> report Neko.Lexer.error_msg(msg) pos | Neko.Parser.Error(msg,pos) -> report Neko.Parser.error_msg(msg) pos | Neko.Compile.Error(msg,pos) -> report Neko.Compile.error_msg(msg) pos | Neko.Doc.Error(msg,pos) -> report Neko.Doc.error_msg(msg) pos | e -> report string(e) Lexer.null_pos } neko-2-2-0/src/neko/Parser.nml000066400000000000000000000166171321613172000161430ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Lexer; open Neko.Ast; type error_msg { Unexpected : token; Unclosed : string; Invalid_nxml : error; } exception Error : (error_msg , pos) function error_msg(m) { match m { | Unexpected t -> "Unexpected " + s_token t | Unclosed s -> "Unclosed " + s | Invalid_nxml e -> "Invalid nxml (" + string e + ")" } } function error(m,p) { throw Error(m,p) } function priority(x) { match x { | "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "&=" | "^=" -> -4 | "++=" | "--=" -> -3 | "&&" | "||" -> -2 | "==" | "!=" | ">" | "<" | "<=" | ">=" -> -1 | "+" | "-" -> 0 | "*" | "/" -> 1 | "|" | "&" | "^" -> 2 | "<<" | ">>" | "%" | ">>>" -> 3 | _ -> 4 } } function mk(t,p) { (t,p) } function rec make_binop(op,e,e2) { var v , p2 = e2; match v { | EBinop (_op,_e,_e2) when priority _op <= priority op -> var _e = make_binop op e _e; mk EBinop(_op,_e,_e2) punion(pos _e,pos _e2) | _ -> mk EBinop(op,e,e2) punion(pos e,pos e2) } } function rec program(s) { match s { | [< e = expr s; p = program s >] -> e :: p | [< (Semicolon,_); p = program s >] -> p | [< (Eof,_) >] -> [] } } function rec expr(s) { match s { | [< (Const ((Ident k) as i),p) >] -> match s { | [< (Binop ":",p2) >] -> mk ELabel(k) punion(p,p2) | [< >] -> expr_next (EConst i,p) s } | [< (Const c,p) >] -> expr_next (EConst c,p) s | [< (BraceOpen,p1); e = block1 s >] -> match s { | [< (BraceClose,p2) >] -> expr_next (e,punion p1 p2) s | [< (Eof,_) >] -> error (Unclosed "{") p1 } | [< (ParentOpen,p1); e = expr s >] -> match s { | [< (ParentClose,p2) >] -> expr_next (EParenthesis e,punion p1 p2) s | [< (Eof,_) >] -> error (Unclosed "(") p1 } | [< (Keyword Var,p1); v , p2 = variables p1 s >] -> expr_next (EVars v,punion p1 p2) s | [< (Keyword While,p1); cond = expr s; e = expr s >] -> expr_next (EWhile cond e NormalWhile, punion p1 (pos e)) s | [< (Keyword Do,p1); e = expr s; (Keyword While,_); cond = expr s >] -> expr_next (EWhile cond e DoWhile, punion p1 (pos cond)) s | [< (Keyword Switch,p1); v = expr s; (BraceOpen,_); l , def = switch_cases s; (BraceClose,p2) >] -> expr_next (ESwitch v l def,punion p1 p2) s; | [< (Keyword If,p1); cond = expr s; e = expr s >] -> function rec loop() { match s { | [< (Keyword Else,_); e2 = expr s >] -> expr_next (EIf cond e Some(e2),punion p1 (pos e2)) s | [< (Semicolon,_) >] -> loop() | [< >] -> expr_next (EIf cond e None,punion p1 (pos e)) s } }; loop() | [< (Keyword Function,p1); (ParentOpen,po); p = parameter_names s >] -> match s { | [< (ParentClose,_); e = expr s >] -> expr_next (EFunction p e,punion p1 (pos e)) s | [< (Eof,_) >] -> error (Unclosed "(") po } | [< (Keyword Return,p1) >] -> match s { | [< e = expr s >] -> expr_next (EReturn (Some e), punion p1 (pos e)) s | [< (Semicolon,_) >] -> expr_next (EReturn None,p1) s } | [< (Keyword Break,p1) >] -> match s { | [< e = expr s >] -> expr_next (EBreak (Some e), punion p1 (pos e)) s | [< (Semicolon,_) >] -> expr_next (EBreak None,p1) s } | [< (Keyword Continue,p1) >] -> expr_next (EContinue,p1) s | [< (Keyword Try,p1); e = expr s; (Keyword Catch,_); (Const (Ident name),_); e2 = expr s >] -> expr_next (ETry e name e2,punion p1 (pos e2)) s | [< (Binop "-",p1); e2 = expr s >] -> (EParenthesis (make_binop "-" (EConst (Int 0),p1) e2), punion p1 (pos e2)) } } function rec expr_next(e,s) { match s { | [< (Dot,_); (Const (Ident name),p) >] -> expr_next (EField e name,punion (pos e) p) s | [< (ParentOpen,po); pl = parameters s >] -> match s { | [< (ParentClose,p) >] -> expr_next (ECall e pl,punion (pos e) p) s | [< (Eof,_) >] -> error (Unclosed "(") po } | [< (BracketOpen,po); e2 = expr s >] -> match s { | [< (BracketClose,p) >] -> expr_next (EArray e e2,punion (pos e) p) s | [< (Eof,_) >] -> error (Unclosed "[") po } | [< (Binop op,_); e2 = expr s >] -> make_binop op e e2 | [< >] -> e } } function rec block1(s) { match s { | [< (Const (Ident name),p) >] -> match s { | [< (Arrow,_); e = expr s; l = object_fields s >] -> EObject ((name,e) :: l) | [< (Binop ":",p2); b = block s >] -> EBlock ( (ELabel name, punion p p2) :: b ) | [< e = expr_next (EConst (Ident name),p) s; b = block s >] -> EBlock (e :: b) } | [< b = block s >] -> EBlock b } } function rec block(s) { match s { | [< e = expr s; b = block s >] -> e :: b | [< (Semicolon,_); b = block s >] -> b | [< >] -> [] } } function rec object_fields(s) { match s { | [< (Const (Ident name),_); (Arrow,_); e = expr s; l = object_fields s >] -> (name,e) :: l | [< (Comma,_); l = object_fields s >] -> l | [< >] -> [] } } function rec switch_cases(s) { match s { | [< e1 = expr s; (Arrow,p); e2 = expr s; l , def = switch_cases s >] -> ((e1,e2) :: l , def) | [< (Keyword Default,pp); (Arrow,p); e = expr s; l, def = switch_cases s >] -> match def { | None -> (l, Some e) | Some _ -> error (Unexpected (Keyword Default)) pp } | [< >] -> ([] , None) } } function rec parameter_names(s) { match s { | [< (Const (Ident name),_); p = parameter_names s >] -> name :: p | [< (Comma,_); p = parameter_names s >] -> p | [< >] -> [] } } function rec parameters(s) { match s { | [< e = expr s; p = parameters_next s >] -> e :: p | [< >] -> [] } } function rec parameters_next(s) { match s { | [< (Comma,_); p = parameters s >] -> p | [< >] -> [] } } function rec variables(sp,s) { match s { | [< (Const (Ident name),p) >] -> match s { | [< (Binop "=",_); e = expr s; v , p = variables_next (pos e) s >] -> ((name, Some e) :: v , p) | [< v , p = variables_next p s >] -> ((name, None) :: v , p) } } } function rec variables_next(sp,s) { match s { | [< (Comma,p); v = variables p s >] -> v | [< >] -> ([] , sp) } } function parse(lexer) { var last = &(Eof,null_pos); function rec next_token() { var t = Lexer.token lexer (*Neko.Lexer.expr); match fst t { | Comment s | CommentLine s -> next_token() | _ -> last := t; t } } try { var p = program (stream next_token); (EBlock p,null_pos) } catch { Stream_error -> error Unexpected(fst(*last)) snd(*last) } } function parse_string(str,p) { var ch = IO.read_string str; var lex = Lexer.create Buffer.create(); Lexer.input lex p.psource ch p.pline p.pmin; parse lex } Neko.Xml.parse_string := parse_string; Neko.Binast.parse_from_string := parse_string; neko-2-2-0/src/neko/Printer.nml000066400000000000000000000127561321613172000163320ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Neko.Ast type ctx { ch : IO.output; mutable level : int; mutable tabs : bool; } function create(ch) { { ch = ch; level = 0; tabs = true; } } function newline(ctx) { IO.write_char ctx.ch '\n'; ctx.tabs := false; } function level(ctx,b) { ctx.level := ctx.level + (if b then 1 else -1); newline ctx } function printf(ctx) { if !ctx.tabs then { IO.write ctx.ch (String.make (ctx.level * 4) ' '); ctx.tabs := true; }; IO.printf ctx.ch } function rec print_list(ctx,sep,f,x) { match x { | [] -> () | x :: [] -> f x | x :: l -> f x; printf ctx "%s" sep; print_list ctx sep f l } } function print(ctx,n) { printf ctx "%s" n } function rec print_ast(ctx,binop,(e,p)) { var print_rec = print_ast ctx false; match e { | EConst c -> printf ctx "%s" (s_constant c) | EBlock el -> print ctx "{"; level ctx true; List.iter (function(e) { print_rec e; if ctx.tabs then { print ctx ";"; newline ctx; } }) el; ctx.level := ctx.level - 1; print ctx "}"; newline ctx; | EParenthesis e when !ctx.tabs -> print ctx "{ "; print_rec e; print ctx " }"; | EParenthesis e -> print ctx "( "; print_rec e; print ctx " )"; | EField (e,s) -> print_rec e; printf ctx ".%s" s; | ECall (e,el) -> print_rec e; print ctx "("; print_list ctx "," print_rec el; print ctx ")"; | EArray (e1,e2) -> print_rec e1; print ctx "["; print_rec e2; print ctx "]" | EVars vl -> print ctx "var "; print_list ctx ", " (function((n,v)) { printf ctx "%s" n; match v { | None -> () | Some e -> print ctx " = "; print_rec e } }) vl; print ctx ";"; newline ctx | EWhile(cond,e,NormalWhile) -> print ctx "while "; print_rec cond; level_expr ctx e false; | EWhile (cond,e,DoWhile) -> print ctx "do "; level_expr ctx e false; print ctx "while "; print_rec cond; newline ctx | EIf (cond,e,e2) -> print ctx "if "; print_rec cond; level_expr ctx e (e2 == None); match e2 { | None -> () | Some e -> print ctx "else"; level_expr ctx e false } | ETry (e,id,e2) -> print ctx "try"; level_expr ctx e false; printf ctx "catch %s" id; level_expr ctx e2 false; | EFunction (params,e) -> print ctx "function("; print_list ctx "," (printf ctx "%s") params; print ctx ")"; level_expr ctx e false; | EBinop (op,e1,e2) -> var tabs = ctx.tabs; if binop then (if tabs then print ctx "(" else print ctx "{"); print_ast ctx true e1; printf ctx " %s " op; print_ast ctx true e2; if binop then (if tabs then print ctx ")" else print ctx "}"); | EReturn None -> print ctx "return;"; | EReturn (Some e) -> print ctx "return "; print_rec e; | EBreak None -> print ctx "break;"; | EBreak (Some e) -> print ctx "break "; print_rec e; | EContinue -> print ctx "continue" | ENext (e1,e2) -> print_rec e1; print ctx ";"; newline ctx; print_rec e2 | EObject [] -> print ctx "$new(null)" | EObject fl -> print ctx "{"; level ctx true; function rec loop(x) { match x { | [] -> assert() | [(f,e)] -> printf ctx "%s => " f; print_rec e; newline ctx; | (f,e) :: l -> printf ctx "%s => " f; print_rec e; print ctx ", "; newline ctx; loop l } }; loop fl; level ctx false; print ctx "}" | ELabel s -> printf ctx "%s:" s | ESwitch (e,cases,eo) -> print ctx "switch "; print_rec e; print ctx "{"; newline ctx; List.iter (function((e1,e2)) { print_rec e1; print ctx " => "; level ctx true; print_rec e2; level ctx false; }) cases; match eo { | None -> () | Some e -> print ctx "default => "; level ctx true; print_rec e; level ctx false } print ctx "}"; newline ctx } } function rec level_expr(ctx,(e,p),closed) { match e { | EBlock _ -> if ctx.tabs then print ctx " "; print_ast ctx false (e,p) | EParenthesis e -> if ctx.tabs then print ctx " "; print ctx "{"; level ctx true; print_ast ctx false e; level ctx false; print ctx "}"; | _ -> level ctx true; print_ast ctx false (e,p); if closed then print ctx ";"; level ctx false } } function print(ctx,ast) { match fst ast { | EBlock el -> List.iter (function(e) { print_ast ctx false e; if ctx.tabs then { print ctx ";"; newline ctx; } }) el; | _ -> print_ast ctx false ast } } function to_string(ast) { var ch , str = IO.write_string(); var ctx = create ch; print ctx ast; IO.close_out ch; str() } neko-2-2-0/src/neko/Xml.nml000066400000000000000000000165411321613172000154430ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Lexer; open Neko.Ast; open Xml; exception Error : string; var parse_string : (string -> pos -> expr) ref = &(function(_,_) { assert() }); function parse_pos(p,x) { try { var a = attrib x "p"; var f, l = match String.split a ":" { | [] -> assert() | [line] -> (p.psource, int line) | l -> match List.rev l { | [] -> assert() | line :: l -> (String.concat ":" (List.rev l),int line) } }; { psource = f; pmin = p.pmin; pmax = p.pmax; pline = l; } } catch { Not_found -> p } } function rec parse_xml(p,x) { function error() { invalid_arg(); } var p = parse_pos p x; function binop(f) { match nodes x { | [a;b] -> (f (parse_xml p a) (parse_xml p b),p) | _ -> error() } } match node_name x { | "i" -> var v = int (attrib x "v"); (EConst Int(v),p) | "f" -> var v = attrib x "v"; (EConst Float(v),p) | "s" -> var v = attrib x "v"; (EConst String(String.unescape v),p) | "v" -> var v = attrib x "v"; if String.get v 0 == '$' then (EConst Builtin(String.sub v 1 (String.length v - 1)),p) else match v { | "true" -> (EConst True,p) | "false" -> (EConst False,p) | "null" -> (EConst Null,p) | "this" -> (EConst This,p) | _ -> (EConst Ident(v),p) } | "b" -> (EBlock (List.map (parse_xml p) (nodes x)),p) | "p" -> (EParenthesis (parse_xml p (firstNode x)),p) | "g" -> var v = attrib x "v"; (EField (parse_xml p (firstNode x)) v,p) | "c" -> match nodes x { | [] -> error() | x :: l -> (ECall (parse_xml p x) (List.map (parse_xml p) l),p) } | "a" -> binop EArray | "var" -> (EVars (List.map (function(x) { var e = try Some (firstNode x) catch { _ -> None }; (attrib x "v", match e { None -> None | Some x -> Some (parse_xml p x) }) }) nodes(x)),p) | "while" -> binop (function(a,b) { EWhile a b NormalWhile }) | "do" -> binop (function(a,b) { EWhile b a DoWhile }) | "if" -> match nodes x { | [cond;e] -> (EIf (parse_xml p cond) (parse_xml p e) None,p) | [cond;e1;e2] -> (EIf (parse_xml p cond) (parse_xml p e1) Some(parse_xml p e2),p) | _ -> error() } | "o" -> var v = attrib x "v"; binop (EBinop v) | "try" -> var v = attrib x "v"; binop (function(a,b) { ETry a v b }) | "function" -> var args = String.split (attrib x "v") ":"; (EFunction args (parse_xml p (firstNode x)),p) | "return" -> var x = try Some (firstNode x) catch { _ -> None }; (EReturn (match x { None -> None | Some x -> Some (parse_xml p x) }),p) | "break" -> var x = try Some (firstNode x) catch { _ -> None }; (EBreak (match x { None -> None | Some x -> Some (parse_xml p x) }),p) | "continue" -> (EContinue,p) | "next" -> binop ENext | "object" -> (EObject (List.map (function(x) { (attrib x "v", parse_xml p (firstNode x)) }) nodes(x)),p) | "label" -> var v = attrib x "v"; (ELabel v,p) | "switch" -> var cases = &[]; var def = &None; var e = &None; List.iter (function(x) { match node_name x { | "case" -> var c = match nodes x { | [a;b] -> (parse_xml p a, parse_xml p b) | _ -> error() }; cases := c :: *cases; | "default" -> if *def != None then error(); def := Some (parse_xml p firstNode(x)); | _ -> if *e != None then error(); e := Some (parse_xml p x); } }) nodes(x); match *e { | None -> error() | Some e -> (ESwitch e (List.rev (*cases)) (*def),p) } | "neko" -> var e , _ = (*parse_string) (node_text x) p; (e,p) | n -> throw Error("Unknown node name : "+n); } } function parse(s,p) { var x = parse s; match nodes x { | [(Node _) as x] -> parse_xml p x | _ -> invalid_arg() } } function rec to_xml_rec(p2,ast) { var e , p = ast; var name = &""; var val = &None; var children = &[]; match e { | EConst c -> match c { | True | False | Null | This | Builtin _ | Ident _ -> name := "v"; val := Some (s_constant c) | Int i -> name := "i"; val := Some (string i); | Float s -> name := "f"; val := Some s; | String s -> name := "s"; val := Some s; } | EBlock el -> name := "b"; children := List.map (to_xml_rec p) el; | EParenthesis e -> name := "p"; children := [to_xml_rec p e]; | EField (e,f) -> name := "g"; val := Some f; children := [to_xml_rec p e]; | ECall (e,el) -> name := "c"; children := to_xml_rec p e :: List.map (to_xml_rec p) el; | EArray (a,b) -> name := "a"; children := [to_xml_rec p a; to_xml_rec p b]; | EVars vl -> name := "var"; children := List.map (function((v,e)) { Node "v" [("v",v)] (match e { None -> [] | Some e -> [to_xml_rec p e] }) }) vl; | EWhile (econd,e,NormalWhile) -> name := "while"; children := [to_xml_rec p econd; to_xml_rec p e]; | EWhile (econd,e,DoWhile) -> name := "do"; children := [to_xml_rec p e; to_xml_rec p econd]; | EIf (cond,e,eelse) -> name := "if"; children := to_xml_rec p cond :: to_xml_rec p e :: (match eelse { None -> [] | Some e -> [to_xml_rec p e] }) | ETry (e1,v,e2) -> name := "try"; val := Some v; children := [to_xml_rec p e1; to_xml_rec p e2]; | EFunction (args,e) -> name := "function"; val := Some (String.concat ":" args); children := [to_xml_rec p e]; | EBinop (op,e1,e2) -> name := "o"; val := Some op; children := [to_xml_rec p e1; to_xml_rec p e2]; | EReturn e -> name := "return"; children := match e { None -> [] | Some e -> [to_xml_rec p e]}; | EBreak e -> name := "break"; children := match e { None -> [] | Some e -> [to_xml_rec p e]}; | EContinue -> name := "continue"; | ENext (e1,e2) -> name := "next"; children := [to_xml_rec p e1; to_xml_rec p e2]; | EObject fl -> name := "object"; children := List.map (function((v,e)) { Node "v" [("v",v)] [to_xml_rec p e] }) fl; | ELabel v -> name := "label"; val := Some v; | ESwitch (e,cases,def) -> name := "switch"; var cases = List.map (function((e1,e2)) { Node "case" [] [to_xml_rec p e1; to_xml_rec p e2] }) cases; children := to_xml_rec p e :: (match def { None -> cases | Some e -> Node "default" [] [to_xml_rec p e] :: cases }); } var pos = (if p.psource != p2.psource then [("p",p.psource + ":" + p.pline)] else if p.pline != p2.pline then [("p",string p.pline)] else []); var val = match *val { None -> [] | Some v -> [("v",v)] }; Node (*name) (List.append pos val) (*children) } function to_xml(ast) { to_xml_rec null_pos ast } neko-2-2-0/src/nekoml/000077500000000000000000000000001321613172000145155ustar00rootroot00000000000000neko-2-2-0/src/nekoml/Ast.nml000066400000000000000000000106221321613172000157550ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type pos = Lexer.pos type constant { Int : int; Char : char; Bool : bool; Float : string; String : string; Ident : string; Constr : string; Module : (string list , constant); } type keyword { Var; If; Else; Function; Try; Catch; Type; Match; Then; When; While; Exception; } type token { Eof; Semicolon; Dot; Comma; Quote; BraceOpen; BraceClose; ParentOpen : bool; ParentClose; BracketOpen; BracketClose; Arrow; Vertical; StreamOpen; StreamClose; Const : constant; Keyword : keyword; Binop : string; Comment : string; CommentLine : string; } type type_path { EType : (type_path option , string list , string); EPoly : string; ETuple : type_path list; EArrow : (type_path , type_path); } type type_decl { EAbstract; EAlias : type_path; ERecord : (string , bool , type_path) list; EUnion : (string , type_path option) list; } type arg { ATyped : (arg , type_path); ANamed : string; ATuple : arg list; } type pattern; type expr; type stream_item; type pattern_decl { PIdent : string; PConst : constant; PTuple : pattern list; PRecord : ((string , pattern) list, int); PConstr : (string list , string , pattern option); PAlias : (string , pattern); PTyped : (pattern , type_path); PStream : (stream_item list , int); } type stream_item { SPattern : pattern; SExpr : (string list , expr); SMagicExpr : (pattern , int); } type expr_decl { EConst : constant; EBlock : expr list; EField : (expr , string); ECall : (expr , expr list); EArray : (expr , expr); EVar : ((string , type_path option) list , expr); EIf : (expr , expr , expr option); EFunction : (bool , string option , arg list , expr , type_path option); EBinop : (string , expr , expr); EUnop : (string , expr); ETypeAnnot : (expr , type_path); ETupleDecl : expr list; ETypeDecl : (string list , string , type_decl); EErrorDecl : (string , type_path option); ERecordDecl : (string , expr) list; EMatch : (expr , (pattern list , expr option , expr) list); ETry : (expr , (pattern list , expr option , expr) list); ETupleGet : (expr , int); EApply : (expr , expr list); EWhile : (expr , expr); } type pattern = (pattern_decl , pos) type expr = (expr_decl , pos) var pos = snd; function rec s_constant(c) { match c { | Int i -> string i | Float s -> s | Bool b -> if b then "true" else "false" | Char c -> "\"" + String.escape_char c + "\"" | String s -> "\"" + String.escape s + "\"" | Ident s -> s | Constr s -> s | Module (l,c) -> String.concat "." l + "." + s_constant c } } function s_path(path,n) { match path { | [] -> n | _ -> String.concat "." path + "." + n } } function s_keyword(k) { match k { | Var -> "var" | If -> "if" | Else -> "else" | Function -> "function" | Try -> "try" | Catch -> "catch" | Type -> "type" | Match -> "match" | Then -> "then" | When -> "when" | While -> "while" | Exception -> "exception" } } function s_token(t) { match t { | Eof -> "" | Semicolon -> ";" | Dot -> "." | Comma -> "," | Quote -> "'" | BraceOpen -> "{" | BraceClose -> "}" | ParentOpen _ -> "(" | ParentClose -> ")" | BracketOpen -> "[" | BracketClose -> "]" | StreamOpen -> "[<" | StreamClose -> ">]" | Arrow -> "->" | Vertical -> "|" | Const c -> s_constant c | Keyword k -> s_keyword k | Binop s -> s | Comment s -> "/*" + s + "*--" | CommentLine s -> "//" + s } } neko-2-2-0/src/nekoml/Lexer.nml000066400000000000000000000121051321613172000163030ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Nekoml.Ast type error_msg { Invalid_character : char; Unterminated_string; Unclosed_comment; Invalid_escaped_character : int; Invalid_escape; } exception Error : (error_msg , pos) function error_msg(msg) { match msg { | Invalid_character c -> sprintf "Invalid character '%s'" (String.escape_char c) | Unterminated_string -> "Unterminated string" | Unclosed_comment -> "Unclosed comment" | Invalid_escaped_character n -> sprintf "Invalid escaped character %d" n | Invalid_escape -> "Invalid escape sequence" } } function error(l,msg) { throw Error(msg,Lexer.curpos l) } var keywords = { var h = Hashtbl.create(); List.iter (function(k) { Hashtbl.add h (s_keyword k) k }) [Var;If;Else;Function;Try;Catch;Type;Match;Then;When;While;Exception]; h } function mk(l,t) { (t,Lexer.curpos l) } function mk_ident(l) { var s = Lexer.current l; mk l (try Keyword (Hashtbl.find keywords s) catch { Not_found -> Const (Ident s) }) } function mk_int(l) { mk l (Const (Int (int (Lexer.current l)))) } function mk_float(l) { mk l (Const (Float (Lexer.current l))) } function mk_binop(l) { mk l (Binop (Lexer.current l)); } var ident = "[a-z_][a-zA-Z0-9_]*"; var modident = "[A-Z][a-zA-Z0-9_]*"; var binop = "[-!=*/<>&|%+:]"; var number = "[0-9]"; var numbers = number + "+"; var spaces = "[ \r\n\t]+"; var token = &Lexer.empty(); function comment(l) { Lexer.token l (*Neko.Lexer.ecomment) } function str(l) { Lexer.token l (*Neko.Lexer.estring) } token := Lexer.build [ (";", function(l) { mk l Semicolon }); (".", function(l) { mk l Dot }); (",", function(l) { mk l Comma }); ("{", function(l) { mk l BraceOpen }); ("}", function(l) { mk l BraceClose }); (spaces + "(", function(l) { mk l (ParentOpen true) }); ("(", function(l) { mk l (ParentOpen false) }); (")", function(l) { mk l ParentClose }); ("\\[", function(l) { mk l BracketOpen }); ("]", function(l) { mk l BracketClose }); ("'", function(l) { mk l Quote }); ("|", function(l) { mk l Vertical }); (spaces, function(l) { Lexer.token l (*token) }); ( "0x[0-9a-fA-F]+", mk_int ); ( numbers, mk_int ); ( numbers + "." + number + "*", mk_float); ( "." + numbers, mk_float ); ("true", function(l) { mk l (Const (Bool true)) }); ("false", function(l) { mk l (Const (Bool false))}); ("\"", function(l) { var p1 = Lexer.curpos l; var buf = Lexer.data l; Buffer.reset buf; try str l catch { Exit -> throw Error(Unterminated_string,p1) }; var p2 = Lexer.curpos l; (Const String(Buffer.string buf) , Lexer.punion p1 p2) }); ("/\\*", function(l) { var p1 = Lexer.curpos l; var buf = Lexer.data l; Buffer.reset buf; try comment l catch { Exit -> throw Error(Unclosed_comment,p1) }; var p2 = Lexer.curpos l; (Comment(Buffer.string buf) , Lexer.punion p1 p2) }); ("'\\\\n'", function(l) { mk l Const(Char '\n') }); ("'\\\\t'", function(l) { mk l Const(Char '\t') }); ("'\\\\r'", function(l) { mk l Const(Char '\r') }); ("'\\\\''", function(l) { mk l Const(Char '\'') }); ("'\\\\\\\\'", function(l) { mk l Const(Char '\\') }); ("'\\\\\"'", function(l) { mk l Const(Char '"') }); ("'[^\\\\]'", function(l) { mk l Const(Char (String.get Lexer.current(l) 1)) }); ("'\\\\[0-9][0-9][0-9]'", function(l) { var s = String.sub (Lexer.current l) 2 3; var n = int s; if n > 255 then error l Invalid_escaped_character(n); mk l (Const (Char (chr n))) }); ("//[^\r\n]*\n?", function(l) { var s = Lexer.current l; var len = String.length s; var n = (if String.get s (len - 1) == '\r' then 3 else 2); mk l CommentLine(String.sub s 0 (len - n)) }); ("\\[<", function(l) { mk l StreamOpen }); (">]", function(l) { mk l StreamClose }); ("->", function(l) { mk l Arrow }); (binop + binop + "?", mk_binop); (">>>" , mk_binop); ("===" , mk_binop); ("!==" , mk_binop); ("or" , mk_binop); ("and" , mk_binop); ("xor" , mk_binop); (ident , mk_ident); (modident , function(l) { mk l Const(Constr (Lexer.current l)) }); ] (function(l) { match Lexer.char l { | None -> mk l Eof | Some c -> error l (Invalid_character c) } }); neko-2-2-0/src/nekoml/Main.nml000066400000000000000000000124131321613172000161120ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Nekoml.Typer; function complete(s) { var l = String.length s; if l > 0 && String.get s (l - 1) != '\\' && String.get s (l-1) != '/' then s + "/" else s } function report(msg,p) { if p == Lexer.null_pos then { Stack.dump IO.stderr Stack.exc(); IO.printf IO.stderr "Exception : %s\n" msg } else IO.printf IO.stderr "%s(%d): %s\n" (Lexer.source p,Lexer.line p,msg); Sys.exit(-1); } function gen_neko(ctx,m,e) { var path , deps, idents = module_infos m; var file = Nekoml.Type.file_name path ".neko"; if *verbose then printf "Generating %s\n" file; var e = Nekoml.Neko.generate ctx e deps idents path; var ch = IO.write_file file false; var ctx = Neko.Printer.create ch; Neko.Printer.print ctx e; IO.close_out ch } function compile(ctx,m,e) { var path, deps, idents = module_infos m; var file = Nekoml.Type.file_name path ".n"; if *verbose then printf "Compiling %s\n" file; /* don't use version 1+ since this will use left-to-right evaluation for $array, leading to too much stack used with big chained lists */ var code = Neko.Compile.compile 0 (Nekoml.Neko.generate ctx e deps idents path); var ch = IO.write_file file true; Neko.Bytecode.write ch code; IO.close_out ch } function capitalize(p) { var c = String.get p 0; if c < 'a' || c > 'z' then p else { var p = String.sub p 0 (String.length p); String.set p 0 chr(ord c - ord 'a' + ord 'A'); p } } exception FileNotFound : string; try { var v = Sys.version; var head = "NekoML Compiler v" + v.maj + "." + v.min + "." + v.build + " - (c)2005-2017 Haxe Foundation\n Usage : nekoml [options] files..."; var path = &[""]; var files = &[]; var neko = &false; var std = &Some("nekoml.std"); var pack = &None; var packs = Hashtbl.create(); function use_pack(file) { var data = try IO.file_contents file catch { _ -> throw FileNotFound(file) }; Zip.init(); var h = String.unserialize (Zip.uncompress data); Hashtbl.iter (function(key,m) { if *verbose then printf "Cached %s [%d bytes]\n" (key,String.length m); Hashtbl.add packs key m }) h; } var decl = [ ("-p", Args.String (function(p) { path := complete p :: *path }) , " : additional file search path"); ("-v", Args.Void (function() { verbose := true }) , ": verbose mode"); ("-n", Args.Void (function() { neko := true }) , ": generate intermediate .neko files"); ("-pack", Args.String (function(p) { pack := Some p })," : build module packages"); ("-use", Args.String use_pack," : use this module package"); ("-nostd", Args.Void (function() { path := List.append (*path) ["core/"]; std := None; }),": disable std lib"); ]; var std_path = List.append (*path) Reflect.loader_path(); function rec loop(std,l) { match l { | [] -> if *verbose then printf "%s not found in %s\n" (std,String.concat ":" std_path) | path :: l -> try use_pack (path+std) catch { FileNotFound _ -> loop std l } } } Args.parse head decl (function(f) { files := f :: *files }); match *std { | None -> () | Some std -> loop std std_path } var ctx = context (*path) packs (function(ctx,m,e) { if *neko then gen_neko ctx m e else compile ctx m e }); List.iter (function(file) { if *verbose then printf "Compiling %s\n" file; var modname = String.split (Sys.without_extension file) "/"; var modname = match List.map capitalize modname { | "Core" :: m -> m | m -> m }; ignore(load_module ctx modname Lexer.null_pos); }) (List.rev (*files)); match *pack { | None -> () | Some file -> var h = Hashtbl.create(); Hashtbl.iter (function(key,m) { Hashtbl.add h (String.concat "." key) (IO.file_contents m.file) }) ctx.modules; Zip.init(); var ch = IO.write_file file true; IO.write ch (Zip.compress (String.serialize h) 9); IO.close_out ch; } } catch { | Neko.Lexer.Error (msg,p) -> report Neko.Lexer.error_msg(msg) p | Neko.Parser.Error (msg,p) -> report Neko.Parser.error_msg(msg) p | Neko.Compile.Error (msg,p) -> report Neko.Compile.error_msg(msg) p | Nekoml.Lexer.Error (msg,p) -> report Nekoml.Lexer.error_msg(msg) p | Nekoml.Parser.Error (msg,p) -> report Nekoml.Parser.error_msg(msg) p | Nekoml.Typer.Error (msg,p) -> report Nekoml.Typer.error_msg(msg) p | e -> report string(e) Lexer.null_pos } neko-2-2-0/src/nekoml/Match.nml000066400000000000000000000244301321613172000162640ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* ----- We're using the same algorithm and source code as described in chapter 5.2.4 of "The Zinc experiment" by X. Leroy ( http://citeseer.ist.psu.edu/leroy90zinc.html ) also described in "The Implementation of Functional Programming Languages" by Simon Peyton Jones, in the Chapter 5 by Philip Wadler ( http://research.microsoft.com/Users/simonpj/Papers/slpj-book-1987/ ) */ open Nekoml.Ast; open Nekoml.Type; type complete { Total; Partial; Dubious; } type lambda = match_op type matching = ((pattern list , lambda) list , lambda list) var fully_matched_ref = &(function(cl) { false }) var error_ref = &(function(msg : string,p : pos) { assert() }) function error(msg,p) { (*error_ref) msg p; } var failure = MFailure function handle(l1,l2) { if l2 == MFailure then l1 else if l1 == MFailure then l2 else MHandle l1 l2 } function exec(e) { MExecute e true } function cond(path,lambdas) { MConstants path lambdas } function rec mswitch(path,lambdas) { match lambdas { | (TVoid,m1) :: [] -> m1 | (TVoid,m1) :: l -> MNext m1 (mswitch path l) | _ -> MSwitch path lambdas } } function ewhen(e,e2) { MWhen e e2 } function rec bind(v,p,m) { match m { | MBind (v2,p2,m) -> MBind v2 p2 (bind v p m) | act -> if v == "_" then act else MBind v p act } } function rec junk(p,k,m) { match m { | MBind (v,m,m2) -> MBind v m (junk p k m2) | act -> if k == 0 then act else MJunk p k act } } function rec stream_pattern((p,pos)) { (match p { | PIdent i -> PConst (Ident i) | PConst c -> PConst c | PTuple pl -> PTuple (List.map stream_pattern pl) | PRecord (pr,t) -> PRecord (List.map (function((s,p)) { (s , stream_pattern p) }) pr) t | PConstr (path,name,param) -> PConstr path name (match param { None -> None | Some p -> Some (stream_pattern p) }) | PAlias (s,p) -> PAlias s (stream_pattern p) | PTyped (p,t) -> PTyped (stream_pattern p) t | PStream (s,k) -> PStream s k } , pos) } function rec have_when(m) { match m { | MWhen _ -> true | MBind (_,_,e) -> have_when e | _ -> false } } function t_const(c) { match c { | Int i -> TInt i | String s -> TString s | Float f -> TFloat f | Char c -> TChar c | Ident i -> TIdent i | Bool b -> TBool b | _ -> assert() } } function total(p1,p2) { match (p1 , p2) { | (Total , Total) -> Total | (Partial , _) -> Partial | (_ , Partial) -> Partial | _ -> Dubious } } function partial(p1,p2) { match (p1 , p2) { | (Total , _) -> p2 | (_ , Total) -> Total | _ -> Dubious } } function rec start_by_a_variable((p,_)) { match p { | PAlias (_,p) -> start_by_a_variable p | PIdent _ -> true | _ -> false } } function add_to_match((casel,pathl),cas) { (cas :: casel , pathl) } function make_constant_match(path,cas) { match path { | [] -> assert() | _ :: pathl -> ([cas] , pathl) } } function make_token_match(path,cas) { ([cas] , path) } function make_construct_match(tuple,nargs,pathl,cas) { match pathl { | [] -> assert() | path :: pathl -> function rec make_path(i) { if i >= nargs then pathl else { var k = if tuple then MTuple path i else MField path i; k :: make_path (i + 1) } } ([cas] , make_path 0) } } function make_record_match(args,pathl,t,cas) { match pathl { | [] -> assert() | path :: pathl -> var l = List.fold (function(acc,(f,_)) { MRecordField(path,f,t) :: acc }) pathl (List.rev args); ([cas] , l) } } function add_to_division(make_match,divlist,key,cas) { try { var matchref = List.assoc key divlist; matchref := add_to_match (*matchref) cas; divlist } catch { Not_found -> (key , &(make_match cas)) :: divlist } } function always_add(make_match,divlist,cas) { (TVoid , &(make_match cas)) :: divlist } var lines_of_matching = fst function fully_matched(cl) { (*fully_matched_ref) cl } function flatten(a) { match a { | None -> [] | Some p -> match p { | (PTuple l,_) -> l | _ -> [p] } } } function split_matching(m) { match m { | (_ , []) -> assert() | (casel, (curpath :: endpathl) as pathl) -> function rec split_rec(l) { match l { | ((PTyped (p,_),_) :: l , act) :: rest -> split_rec ((p :: l, act) :: rest) | ((PAlias (v,p),_) :: l , act) :: rest -> split_rec ((p :: l, bind v curpath act) :: rest) | ((PIdent v,_) :: l , act) :: rest -> var vars , others = split_rec rest; (add_to_match vars (l, bind v curpath act) , others) | casel -> (([] , endpathl) , (casel , pathl)) } } split_rec casel } } function divide_matching(m) { match m { | (_ , []) -> assert() | (casel , (curpath :: tailpathl) as pathl) -> function rec divide_rec(l) { match l { | [] -> ([] , [] , ([] , pathl)) | ([],_) :: _ -> assert() | ((PTyped (p,_),_) :: l , act) :: rest -> divide_rec ((p :: l , act) :: rest) | ((PAlias (v,p),_) :: l, act) :: rest -> divide_rec ((p :: l , bind v curpath act) :: rest) | ((PConst c,_) :: l, act) :: rest -> var constant , constrs, others = divide_rec rest; (add_to_division (make_constant_match pathl) constant (t_const c) (l, act), constrs , others) | ((PConstr (path,c,arg),_) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; var args = flatten arg; (constants , add_to_division (make_construct_match false (List.length args) pathl) constrs (TModule path TConstr(c)) (List.append args l,act) , others) | ((PTuple [],_) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; (constants , add_to_division (make_constant_match pathl) constrs TVoid (l, act), others) | ((PTuple args,_) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; (constants , add_to_division (make_construct_match true (List.length args) pathl) constrs TVoid (List.append args l,act) , others) | ((PRecord (args,t),_) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; (constants , add_to_division (make_record_match args pathl magic(t)) constrs TVoid (List.append (List.map snd args) l,act) , others) | ((PStream ((SPattern p) :: sl,k),pp) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; (constants , always_add (make_token_match ((MToken curpath k) :: pathl)) constrs (stream_pattern p :: (PStream sl (k+1),pp) :: l, act) , others) | ((PStream ((SMagicExpr ((PTuple _,_) as p,e)) :: sl,k),pp) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; var ebind = MExecute (mk TConst(TIdent "@tmp") t_void pp) false; (constants , always_add (make_token_match (junk curpath k (MExecute magic(e) false) :: ebind :: pathl)) constrs ((PConst (Ident "@tmp"),pp) :: stream_pattern p :: (PStream sl 0,pp) :: l, act) , others) | ((PStream ((SMagicExpr (p,e)) :: sl,k),pp) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; (constants , always_add (make_token_match (junk curpath k (MExecute magic(e) false) :: pathl)) constrs (stream_pattern p :: (PStream sl 0,pp) :: l, act) , others) | ((PStream ([],k),pp) :: l,act) :: rest -> var constants , constrs, others = divide_rec rest; (constants , always_add (make_constant_match pathl) constrs (l, junk curpath k act) , others) | casel -> ([] , [] , (casel,pathl)) } } divide_rec casel } } function rec conquer_divided_matching(m) { match m { | [] -> ([], Total, []) | (key, matchref) :: rest -> var l1, p1, u1 = conquer_matching (*matchref); var l2, p2, u2 = conquer_divided_matching rest; ((key , l1) :: l2 , total p1 p2 , List.append u1 u2) } } function rec conquer_matching(m) { match m { | ([] , _) -> (failure , Partial , []) | (([],action) :: rest , k) -> if have_when action then { var a , p , r = conquer_matching (rest,k); (handle action a , p , r) } else (action , Total, rest) | (_ , []) -> assert() | ((p :: _,_) :: _ , _ :: _) when start_by_a_variable p -> var vars , rest = split_matching m; var l1, p1, u1 = conquer_matching vars; var l2, p2, u2 = conquer_matching rest; if p1 == Total then (l1 , Total, List.append u1 lines_of_matching(rest)) else (handle l1 l2 , (if p2 == Total then Total else Dubious) , List.append u1 u2) | (_ , path :: _) -> match divide_matching m { | ([] , [] , vars) -> conquer_matching vars | (consts , [] , vars) -> var l1, _ , u1 = conquer_divided_matching consts; var l2, p2, u2 = conquer_matching vars; (handle (cond path l1) l2 , p2 , List.append u1 u2) | ([] , constrs , vars) -> var l1, p1, u1 = conquer_divided_matching constrs; var l2, p2, u2 = conquer_matching vars; if fully_matched (List.map fst constrs) && p1 == Total then (mswitch path l1 , Total , List.append u1 lines_of_matching(vars)) else (handle (mswitch path l1) l2 , partial p1 p2 , List.append u1 u2) | _ -> assert() } | _ -> assert() } } function make(cases : (pattern list, texpr option, texpr) list,p) { var cases = List.concat (List.map (function((pl,wcond,e)) { var e = exec e; var e = match wcond { None -> e | Some e2 -> ewhen e2 e }; List.map (function(p) { ([p] , e) }) pl }) cases); var m = (cases , [MRoot]); var lambda, partial, unused = conquer_matching m; match unused { | [] -> () | ([] , _ ) :: _ -> error "Some pattern are never matched" p | ((_,p) :: _ , _) :: _ -> error "This pattern is never matched" p}; (partial != Total , lambda) } neko-2-2-0/src/nekoml/Neko.nml000066400000000000000000000420101321613172000161160ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Lexer; open Neko.Ast; open Nekoml.Type; type comparison { Native; Structural; } type context { typectx : Nekoml.Typer.context; current : string list; module_name : string; imports : (string list,string) Hashtbl.t; mutable counter : int; mutable refvars : string Set.t; } function gen_label(ctx) { var c = ctx.counter; ctx.counter := ctx.counter + 1; "l" + string c } function gen_variable(ctx) { var c = ctx.counter; ctx.counter := ctx.counter + 1; "v" + string c } function module_name(m) { "@" + String.concat "_" m } function builtin(name) { (EConst (Builtin name) , null_pos) } function ident(name) { (EConst (Ident name) , null_pos) } function int(n) { (EConst (Int n) , null_pos) } var enull = (EConst Null , null_pos) var core = ["Core"]; function record_index(f,t) { match tlinks false t { | TRecord fl -> function rec loop(i,l) { match l { | [] -> assert() | (ff,_,_) :: l -> if f == ff then i else loop (i+1) l } } loop 0 fl | _ -> assert() } } function construct_id(ctx,m,c) { var m = if m == [] then ctx.current else m; var mod = try Nekoml.Typer.module ctx.typectx m catch { Not_found -> assert() }; var r = try Nekoml.Typer.union mod c catch { Not_found -> assert() }; if r == t_error then Hashtbl.hash (c :: m) else match tlinks false r { | TUnion (_,fl) -> function rec loop(i,l) { match l { | [] -> assert() | (cc,_) :: l -> if c == cc then i else loop (i+1) l } } loop 0 fl | _ -> assert() } } function rec is_fun(t) { match t.texpr { | TNamed (_,_,t) | TLink t -> is_fun t | TPoly | TMono _ | TFun _ -> true | _ -> false } } function call(ret,f,args,p) { if is_fun ret then (ECall (EConst (Builtin "apply"),p) (f :: args) , p) else (ECall f args , p) } function array(args,p) { (ECall (EConst (Builtin "array"),p) args , p) } function block(e) { match fst e { | EBlock _ -> e | _ -> (EBlock [e] , snd e) } } function rec arity(t) { match t.texpr { | TAbstract -> 0 | TTuple tl -> List.length tl | TLink t -> arity t | _ -> 1 } } function comparison(t) { match tlinks true t { | TNamed (["int"],[],_) | TNamed (["char"],[],_) | TNamed (["float"],[],_) | TNamed (["string"],[],_) -> Native | _ -> Structural } } function import(ctx,m,i,p) { if m == ctx.current then (EField ident(ctx.module_name) i,p) else { var key = i :: m; (EConst Ident(try { Hashtbl.find ctx.imports key } catch { Not_found -> var i = "@" + String.concat "_" m + "_" + i; Hashtbl.add ctx.imports key i; i }),p) } } function rec gen_constant(ctx,c,p) { (match c { | TVoid -> EConst Null | TInt n when n < 0 -> EBinop "-" int(0) int(-n) | TInt n -> EConst (Int n) | TFloat s -> EConst (Float s) | TChar c -> EConst Int(ord c) | TString s -> EConst (String s) | TIdent s -> if Set.exists ctx.refvars s then EArray ident(s) int(0) else EConst (Ident s) | TBool b -> EConst (if b then True else False) | TConstr "[]" | TModule (["Core"],TConstr "[]") -> fst (import ctx core "@empty" p) | TConstr "::" | TModule (["Core"],TConstr "::") -> fst (import ctx core "@cons" p) | TConstr s -> EConst (Ident s) | TModule ([],c) -> fst (gen_constant ctx c p) | TModule (m,c) -> fst (import ctx m (match c { TConstr x -> x | TIdent s -> s | _ -> assert() }) p) } , p) } type match_context { ctx : context; out : string; pos : pos; mutable cache : (match_op , string) list; mutable next : string; mutable first : bool; } var no_label = "" function rec gen_match_rec(mctx,fail,next,m) { try ident (List.phys m mctx.cache) catch { Not_found -> var p = mctx.pos; var ctx = mctx.ctx; var gen_rec = gen_match_rec mctx; match m { | MFailure -> var label = if mctx.first && mctx.next != no_label then mctx.next else fail; if label == no_label then (EBlock [] , p) else call t_void (builtin "goto") [ident label] p | MHandle (m1,m2) -> var label = gen_label ctx; var m1 = gen_rec label true m1; var m2 = gen_rec fail next m2; (EBlock [m1; (ELabel label, p); m2] , p) | MRoot -> assert() | MExecute (e,b) -> if !b then { var ematch = (EBinop "==" ident("@exc") (import ctx core "Stream_error" p) , p); var stream_pos = (ECall (import ctx core "stream_pos" p) [gen_rec fail true MRoot] , p); var test = (EBinop "==" ident("@pos") stream_pos , p); var reraise = (EIf (EBinop "&&" ematch test,p) gen_rec(fail,true,MFailure) Some((ECall (builtin "rethrow") [ident "@exc"],p)) , p); mctx.first := false; match e.edecl { | TConst _ -> gen_expr ctx e | _ -> (ETry gen_expr(ctx,e) "@exc" reraise , p) } } else { mctx.first := true; if !next then gen_expr ctx e else { var out = call t_void (builtin "goto") [ident mctx.out] p; (EBlock [gen_expr ctx e;out] , p) } } | MConstants (m,[(TIdent v,m1)]) -> var m = gen_rec fail true m; (EBlock [ (EVars [(v, Some m)] , p); gen_rec fail next m1 ] , p) | MConstants (m,cl) -> var e = gen_rec fail true m; var cases = List.map (function((c,m)) { (gen_constant ctx c p, gen_rec fail next m) }) cl; (ESwitch e cases Some(gen_rec fail next MFailure), p) | MRecordField (m,f,t) -> (EArray gen_rec(fail,true,m) int(record_index f t) , p) | MTuple (m,n) -> (EArray gen_rec(fail,true,m) int(n) , p) | MField (m,n) -> (EArray gen_rec(fail,true,m) int(n + 2) , p) | MNext (m1,m2) -> var old = mctx.next; var label = gen_label ctx; mctx.next := label; var m1 = gen_rec fail true m1; mctx.next := old; var m2 = gen_rec fail next m2; (EBlock [m1; (ELabel label, p); m2] , p) | MSwitch (m,cl) -> var e = (EArray (gen_rec fail true m) int(0) , p); var cases = List.map (function((c,m)) { var path , c = match c { | TModule (path,TConstr c) -> (path , c) | TConstr c -> (ctx.current,c) | _ -> assert() } (int(construct_id ctx path c), gen_rec fail next m) }) cl; (ESwitch e cases Some(gen_rec fail next MFailure), p) | MBind (v,m1,m2) -> var e1 = gen_rec fail true m1; var old = mctx.cache; mctx.cache := (m1,v) :: mctx.cache; var e2 = gen_rec fail next m2; mctx.cache := old; (EBlock [(EVars [(v, Some e1)] , p); e2] , p) | MWhen (e,m) -> var e = gen_expr ctx e; var m = gen_rec fail next m; var fail = gen_rec fail next MFailure; (EIf e m Some(fail), p) | MToken (m,n) -> call t_void (import ctx core "stream_token" p) [gen_rec fail true m; int n] p | MJunk (m,n,m2) -> var m = gen_rec fail true m; mctx.first := false; (EBlock [ call t_void (import ctx core "stream_junk" p) [m; int n] p; gen_rec fail next m2 ] , p) } } } function rec gen_matching(ctx,v,m,p,stream,next,out) { var mctx = { ctx = ctx; cache = [(MRoot,v)]; pos = p; out = out; first = stream; next = no_label; }; var label = (if stream then gen_label ctx else no_label); var e = gen_match_rec mctx label next m; if stream then { var vpos = "@pos"; var stream_pos = (ECall (import ctx core "stream_pos" p) [ident v] , p); var exc = (ECall builtin("throw") [import ctx core "Stream_error" p] , p); (EBlock [(EVars [(vpos , Some stream_pos)] , p); e; (ELabel label , p); exc] , p) } else e } function rec gen_match(ctx,e,m,stream,p) { var out = gen_label ctx; var v = gen_variable ctx; var m = gen_matching ctx v m p stream stream out; var m = (ENext (EVars [(v,Some e)],p) m, p); (EBlock [m; (ELabel out , p)] , p) } function rec gen_constructor(ctx,tname,c,id,t,p) { var field = ident c; var printer = (EConst Ident(tname + "__string"), p); function val_type(t) { match arity t { | 0 -> var make = array [int id;printer] p; (EBinop "=" field make , p) | n -> var args = Array.list (Array.init n (function(n) { "p" + string n })); var build = array (int id :: printer :: List.map (function(a) { (EConst (Ident a) , p) }) args) p; var func = (EFunction args (EBlock [(EReturn (Some build),p)] , p) , p); (EBinop "=" field func , p) } } var export = (EBinop "=" (EField ident(ctx.module_name) c,p) field , p); (ENext val_type(t) export , p) } function rec gen_type_printer(ctx,c,t,p) { var printer = mk TConst(TModule ["Core"] TIdent("@print_union")) t_void p; var e = mk (TCall printer [ mk TConst(TString c) t_string p; mk TConst(TIdent "v") t_void p ]) t_string p; e } function rec gen_type(ctx,name,t,p) { match t.texpr { | TAbstract | TMono _ | TPoly | TRecord _ | TTuple _ | TFun _ | TNamed (_,_,{ texpr = TNamed _ }) -> (EBlock [] , p) | TLink t -> gen_type ctx name t p | TNamed (name,_,t) -> function rec loop(l) { match l { | [] -> assert() | [x] -> x | _ :: l -> loop l } } gen_type ctx (loop name) t p | TUnion (_,constrs) -> var cmatch = gen_match ctx (ident "v") (MSwitch MRoot (List.map (function((c,t)) { var e = gen_type_printer ctx c t p; (TConstr c , MExecute e true) }) constrs)) false p; var printer = (EFunction ["v"] cmatch , p); var i = &(-1); var regs = List.map (function((c,t)) { i := *i + 1; gen_constructor ctx name c (*i) t p }) constrs; (EBlock ((EVars [(name + "__string",Some printer)],p) :: regs) , p) } } function rec gen_binop(ctx,op,e1,e2,p) { function compare(op) { var cmp = (ECall (import ctx core "@compare" p) [gen_expr ctx e1; gen_expr ctx e2] , p); (EBinop op cmp int(0) , p) } function make(op) { (EBinop op gen_expr(ctx,e1) gen_expr(ctx,e2) , p) } function builtin2(op) { (ECall (builtin op) [gen_expr ctx e1; gen_expr ctx e2] , p) } match op { | "and" -> make "&" | "or" -> make "|" | "xor" -> make "+" | "==" | "!=" | ">" | "<" | ">=" | "<=" -> match comparison e1.etype { | Structural -> compare op | Native -> make op } | "===" -> (EBinop "==" builtin2("pcompare") int(0) , p) | "!==" -> (EBinop "!=" builtin2("pcompare") int(0) , p) | ":=" -> match e1.edecl { | TField _ -> make "=" | TArray (a,i) -> (ECall (import ctx core "@aset" p) [gen_expr ctx a; gen_expr ctx i; gen_expr ctx e2] , p) | _ -> (EBinop "=" (EArray gen_expr(ctx,e1) int(0),e1.epos) gen_expr(ctx,e2) , p) } | "/" when is_int e1.etype && is_int e2.etype -> builtin2 "idiv" | _ -> make op } } function rec gen_call(ctx,rt,e,el,p) { match e.edecl { | TConst (TIdent "neko") | TConst (TModule ([],TIdent "neko")) | TConst (TModule (["Core"],TIdent "neko")) -> match el { | [{ edecl = TConst (TString s) }] -> var ch = IO.read_string (String.concat "\"" (String.split s "'")); var lex = Lexer.create Buffer.create(); Lexer.input lex p.psource ch p.pline p.pmin; fst (Neko.Parser.parse lex) | _ -> assert() } | TConst (TConstr "::") | TConst (TModule ([],TConstr "::")) | TConst (TModule (["Core"],TConstr "::")) -> match el { | [e1;e2] -> ECall (EConst (Builtin "array"),p) [int 1;import ctx core "@pcons" p;gen_expr ctx e1;gen_expr ctx e2] | _ -> assert() } | _ -> fst (call rt (gen_expr ctx e) (List.map (gen_expr ctx) el) p) } } function rec gen_expr(ctx,e) { var p = e.epos; var e = match e.edecl { | TConst c -> fst (gen_constant ctx c p) | TBlock el -> EBlock (gen_block ctx el p) | TParenthesis e -> EParenthesis (gen_expr ctx e) | TCall (f,el) -> gen_call ctx e.etype f el p | TField (e,s) -> EArray gen_expr(ctx,e) int(record_index s e.etype) | TArray (e1,e2) -> ECall (import ctx core "@aget" p) [gen_expr ctx e1;gen_expr ctx e2] | TVar ([v],e) -> ctx.refvars := Set.remove ctx.refvars v; EVars [(v , Some (gen_expr ctx e))] | TVar (vl,e) -> var n = &(-1); EVars (("@tmp" , Some (gen_expr ctx e)) :: List.map (function(v) { ctx.refvars := Set.remove ctx.refvars v; n := *n + 1; (v , Some (EArray ident("@tmp") int(*n),p)) }) vl) | TIf (e,e1,e2) -> EIf (gen_expr ctx e) (gen_expr ctx e1) (match e2 { None -> None | Some e2 -> Some (gen_expr ctx e2) }) | TWhile (e1,e2) -> EWhile (gen_expr ctx e1) (gen_expr ctx e2) NormalWhile | TFunction (rflag,name,params,code) -> if name == "_" then EFunction (List.map fst params) block(gen_expr ctx code) else if !rflag then EVars [(name , Some (EFunction (List.map fst params) block(gen_expr ctx code), p))] else EBlock [gen_functions ctx [e] p] | TBinop (op,e1,e2) -> fst (gen_binop ctx op e1 e2 p) | TTupleDecl tl -> fst (array (List.map (gen_expr ctx) tl) p) | TTypeDecl t -> fst (gen_type ctx "" t p) | TMut e -> fst (gen_expr ctx (*e)) | TRecordDecl fl -> var fl = List.sort (function((f1,_),(f2,_)) { compare (record_index f1 e.etype) (record_index f2 e.etype)}) fl; fst(array (List.map (function((_,e)) { gen_expr ctx e }) fl) p) | TListDecl el -> fst (match el { | [] -> array [] p | x :: l -> array [gen_expr ctx x; gen_expr ctx (mk TListDecl(l) e.etype p)] p }) | TUnop (op,e) -> match op { | "-" -> EBinop "-" int(0) gen_expr(ctx,e) | "*" -> EArray gen_expr(ctx,e) int(0) | "!" -> fst (call t_void (builtin "not") [gen_expr ctx e] p) | "&" -> fst (array [gen_expr ctx e] p) | _ -> assert() } | TMatch (e,m,stream) -> fst (gen_match ctx (gen_expr ctx e) m stream p) | TTupleGet (e,n) -> EArray (gen_expr ctx e) int(n) | TErrorDecl (e,t) -> var printer = gen_expr ctx (gen_type_printer ctx e t p); var printer = (EFunction ["v"] (EBlock [printer],p) , p); var printer = (EVars [(e + "__string",Some printer)] , p); ENext printer (gen_constructor ctx e e (Hashtbl.hash (e :: ctx.current)) t p) | TTry (e,m) -> var out = gen_label ctx; var not_exc = (EBinop "!=" (call t_void (builtin "typeof") [ident "@exc"] p) builtin("tarray"),p); var type_check = (EIf not_exc (EBinop "=" ident("@exc") (call t_void (import ctx core "Neko_error" p) [ident "@exc"] p),p) None,p); var matching = gen_matching ctx "@exc" m p false true out; var reraise = call t_void (builtin "rethrow") [ident "@exc"] p; var handle = (EBlock [type_check; matching; reraise;(ELabel out , p)] , p); ETry (gen_expr ctx e) "@exc" handle }; (e,p) } function rec gen_functions(ctx,fl,p) { var ell = &(EVars (List.map (function(e) { match e.edecl { | TFunction (_,"_",params,e) -> ("_" , Some (EFunction (List.map fst params) block(gen_expr ctx e),p)) | TFunction (_,name,_,_) -> ctx.refvars := Set.add ctx.refvars name; (name , Some (array [enull] p)) | _ -> assert() } }) fl) , p); List.iter (function(e) { var p = e.epos; match e.edecl { | TFunction (_,name,params,e) -> if name != "_" then { var e = gen_expr ctx e; var e = (EFunction (List.map fst params) block(e) , p); var e = (EBinop "=" (EArray ident(name) int(0),p) e, p); var e = (EBlock [e; (EBinop "=" ident(name) (EArray ident(name) int(0),p) , p)] , p); ell := (ENext (*ell) e , p); ctx.refvars := Set.remove ctx.refvars name; } | _ -> assert() } }) fl; *ell } function rec gen_block(ctx,el,p) { var old = ctx.refvars; var ell = &[]; function rec loop(fl,l) { match l { | [] -> if fl != [] then ell := gen_functions ctx (List.rev fl) p :: *ell | ({ edecl = TFunction (true,name,p,f) } as e) :: l -> loop (e :: fl) l | { edecl = TMut r } :: l -> loop fl ((*r) :: l) | x :: l -> if fl != [] then ell := gen_functions ctx (List.rev fl) p :: *ell; ell := gen_expr ctx x :: *ell; loop [] l } } loop [] el; ctx.refvars := old; List.rev (*ell) } function generate(tctx,e,deps,idents,mod) { var m = module_name mod; var ctx = { typectx = tctx; current = mod; module_name = m; counter = 0; imports = Hashtbl.create(); refvars = Set.empty(); }; var p = e.epos; var init = (EBinop "=" ident(m) builtin("exports") , p); var deps = List.map (function(m) { var file = file_name m ""; var load = (ECall (EField builtin("loader") "loadmodule",p) [gen_constant ctx (TString file) p;builtin "loader"] , p); (EBinop "=" ident(module_name m) load , p) }) deps; var exports = List.map (function(i) { (EBinop "=" (EField builtin("exports") i,p) ident(i) , p) }) idents; var el = match gen_expr ctx e { | (EBlock el, _) -> el | e -> [e] } var imports = &[]; Hashtbl.iter (function(key,id) { var e = match key { | [] -> assert() | i :: m -> (EBinop "=" ident(id) (EField ident(module_name m) i , p) , p) } imports := e :: *imports; }) ctx.imports; (EBlock (List.append (init :: List.append deps (*imports)) (List.append el exports)) , e.epos) } neko-2-2-0/src/nekoml/Parser.nml000066400000000000000000000351501321613172000164650ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Nekoml.Ast type error_msg { Unexpected : token; Unclosed : string; } exception Error : (error_msg , pos) function error_msg(msg) { match msg { | Unexpected t -> "Unexpected " + s_token t | Unclosed s -> "Unclosed " + s } } var punion = Lexer.punion; function error(m,p) { throw Error(m,p) } function priority(op) { match op { | "+=" | "-=" | "*=" | "/=" | "|=" | "&=" | "^=" | ":=" -> -3 | "&&" | "||" -> -2 | "==" | "!=" | ">" | "<" | "<=" | ">=" | "===" | "!==" | "<>" | "=" -> -1 | "+" | "-" -> 0 | "*" | "/" -> 1 | "or" | "and" | "xor" -> 2 | "<<" | ">>" | "%" | ">>>" -> 3 | _ -> 4 } } function can_swap(_op,op) { var p1 = priority _op; var p2 = priority op; if p1 < p2 then true else if p1 == p2 then op != "::" else false } function rec make_binop(op,e,e2) { var v , p2 = e2; match v { | EBinop (_op,_e,_e2) when can_swap _op op -> var _e = make_binop op e _e; (EBinop _op _e _e2 , punion (pos _e) (pos _e2)) | _ -> (EBinop op e e2 , punion (pos e) (pos e2)) } } function rec make_unop(op,e,p1) { var v , p2 = e; match v { | EBinop (bop,e,e2) -> ( EBinop bop (make_unop op e p1) e2 , punion p1 p2) | _ -> (EUnop op e, punion p1 p2) } } function rec make_list_pat(p,l) { match l { | [] -> (PConstr [] "[]" None , p) | x :: l -> var p = snd x; var params = (PTuple [x;make_list_pat p l] , p); (PConstr [] "::" Some(params) , p) } } function rec make_list(p,l) { match l { | [] -> (EConst Constr("[]") , p) | x :: l -> var p = snd x; (ECall (EConst Constr("::"), p) [x;make_list p l] , p) } } function is_unop(op) { match op { | "-" | "*" | "!" | "&" -> true | _ -> false } } function unclosed(s,p) { error (Unclosed s) p } function mk(e,p) { (e,p) } function rec program(s) { match s { | [< e = expr s; p = program s >] -> e :: p | [< (Semicolon,_); p = program s >] -> p | [< (Eof,_) >] -> [] } } function rec expr(s) { match s { | [< (BraceOpen,p1); e = block1 s >] -> match s { | [< (BraceClose,p2) >] -> mk e punion(p1,p2) | [< (Eof,_) >] -> unclosed "{" p1 } | [< (Keyword Var,p1); (Const (Ident name),_); t = type_opt s; l = vars s; e = expr s >] -> mk EVar((name,t) :: l,e) punion(p1,pos e) | [< (Keyword If,p1); cond = expr s; (Keyword Then,_); e = expr s >] -> match s { | [< (Keyword Else,_); e2 = expr s >] -> mk EIf(cond,e,Some e2) punion(p1,pos e2) | [< >] -> mk EIf(cond,e,None) punion(p1,pos e) } | [< (Keyword Function,p1); r = function_rec s; n = ident_opt s; (ParentOpen _,po); p = parameters_decl s; t = type_opt s; e = expr s >] -> mk EFunction(r,n,p,e,t) punion(p1,pos e) | [< (Keyword Type,p1); pl = type_decl_parameters s; (Const (Ident tname),p2); d , p3 = type_declaration p2 s >] -> mk ETypeDecl(pl,tname,d) punion(p1,p3) | [< (Keyword Exception,p1); (Const (Constr ename),p2); t = type_opt s >] -> mk EErrorDecl(ename,t) punion(p1,p2) | [< (Keyword Match,p1); e = expr s; (BraceOpen,po); pl = patterns_begin s >] -> match s { | [< (BraceClose,pe) >] -> mk EMatch(e,pl) punion(p1,pe) | [< (Eof,_) >] -> unclosed "{" po } | [< (Keyword Try,p1); b = block s; (Keyword Catch,p2); (BraceOpen,po); pl = patterns_begin s >] -> match s { | [< (BraceClose,pe); >] -> mk ETry((EBlock b,punion p1 p2),pl) punion(p1,pe) | [< (Eof,_) >] -> unclosed "{" po } | [< (Keyword While,p1); e = expr s; (BraceOpen,po); b = block s >] -> match s { | [< (BraceClose,pe) >] -> mk EWhile(e,(EBlock b,punion po pe)) punion(po,pe) | [< (Eof,_) >] -> unclosed "{" po } | [< e = expr_short s >] -> e } } function rec expr_short(s) { match s { | [< (ParentOpen _,p1); pl = parameters s >] -> match s { | [< (ParentClose,p2) >] -> expr_next (ETupleDecl pl,punion p1 p2) s | [< (Eof,_) >] -> unclosed "(" p1 } | [< (Binop op,p) >] -> if ! is_unop op then throw Stream_error; match s { | [< e = expr s >] -> expr_next (make_unop op e p) s } | [< (Const (Constr n),p); e = expr_constr n p s >] -> expr_next e s | [< (Const c,p) >] -> expr_next (EConst c,p) s | [< (BracketOpen,p1); b = block s; (BracketClose,p2) >] -> expr_next (make_list (punion p1 p2) b) s } } function rec expr_next(e,s) { match s { | [< (Binop ":",_); t , p = type_path s >] -> expr_next (ETypeAnnot e t,punion (pos e) p) s | [< (ParentOpen false,po); pl = parameters s >] -> match s { | [< (ParentClose,p) >] -> expr_next (ECall e pl,punion (pos e) p) s | [< (Eof,_) >] -> unclosed "(" po } | [< (Dot,_) >] -> match s { | [< (Const (Ident name),p) >] -> expr_next (EField e name,punion (pos e) p) s | [< (BracketOpen,po); e2 = expr s >] -> match s { | [< (BracketClose,p) >] -> expr_next (EArray e e2,punion (pos e) p) s | [< (Eof,_) >] -> unclosed "[" po } } | [< (Binop op,_); e2 = expr s >] -> make_binop op e e2 | [< ep = expr_short s >] -> function rec loop(ep) { var p = pos ep; match fst ep { | EApply (e2,l) -> mk EApply(e,e2 :: l) punion(pos e,p) | EBinop (op,e1,e2) -> mk EBinop(op,loop e1,e2) punion(pos e,p) | _ -> mk EApply(e,[ep]) punion(pos e,pos ep) } } loop ep | [< >] -> e } } function rec expr_constr(n,p,s) { match s { | [< (Dot,_); e , p2 = expr_constr2 s >] -> match e { | EConst ((Ident _) as c) | EConst ((Constr _) as c) -> mk EConst(Module [n] c) punion(p,p2) | EConst (Module (l,c)) -> mk EConst(Module (n :: l) c) punion(p,p2) | _ -> assert() } | [< >] -> mk EConst(Constr n) p } } function rec expr_constr2(s) { match s { | [< (Const (Ident n),p) >] -> mk EConst(Ident n) p | [< (Const (Constr n),p); e = expr_constr n p s >] -> e } } function rec block1(s) { match s { | [< (Const (Ident name),p) >] -> match s { | [< (Binop "=",_); e = expr s; l = record_fields s >] -> ERecordDecl ((name,e) :: l) | [< e = expr_next (EConst (Ident name),p) s; b = block s >] -> EBlock (e :: b) } | [< b = block s >] -> EBlock b } } function rec record_fields(s) { match s { | [< (Const (Ident name),_); (Binop "=",_); e = expr s; l = record_fields s >] -> (name,e) :: l | [< (Semicolon,_); l = record_fields s >] -> l | [< >] -> [] } } function rec vars(s) { match s { | [< (Binop "=",_) >] -> [] | [< (Comma,_); (Const (Ident name),_); t = type_opt s; l = vars s >] -> (name,t) :: l } } function rec block(s) { match s { | [< e = expr s; b = block s >] -> e :: b | [< (Semicolon,_); b = block s >] -> b | [< >] -> [] } } function rec parameters_decl(s) { match s { | [< (Const (Ident name),_) >] -> parameters_decl_next (ANamed name) s | [< (ParentOpen _,_); l = parameters_decl s >] -> parameters_decl_next (ATuple l) s | [< (ParentClose,_) >] -> [] } } function rec parameters_decl_next(acc,s) { match s { | [< (Comma,_); p = parameters_decl s >] -> acc :: p | [< (Binop ":",_); t , _ = type_path s >] -> parameters_decl_next ATyped(acc,t) s | [< (ParentClose,_) >] -> [acc] } } function rec type_opt(s) { match s { | [< (Binop ":",_); t , _ = type_path s >] -> Some t | [< >] -> None } } function rec function_rec(s) { match s { | [< (Const (Ident "rec"),_) >] -> true | [< >] -> false } } function rec ident_opt(s) { match s { | [< (Const (Ident name),_) >] -> Some name | [< >] -> None } } function rec parameters(s) { match s { | [< e = expr s; p = parameters_next s >] -> e :: p | [< >] -> [] } } function rec parameters_next(s) { match s { | [< (Comma,_); p = parameters s >] -> p | [< >] -> [] } } function rec type_path(s) { match s { | [< (Const (Ident tname),p) >] -> type_path_next EType(None,[],tname) p s | [< (Const (Constr m),p); (Dot,_); l = type_path_mod s; (Const (Ident tname),_) >] -> type_path_next EType(None,m :: l,tname) p s | [< (Quote,_); (Const (Ident a),p) >] -> type_path_next (EPoly a) p s | [< (ParentOpen _,_); t , p = type_path s; l , p2 = type_path_list_next p s; (ParentClose,_) >] -> type_path_next (ETuple (t :: l)) p2 s } } function rec type_path_list(p,s) { match s { | [< t , p = type_path s; l , p2 = type_path_list_next p s >] -> mk (t :: l) p2 } } function rec type_path_list_next(p,s) { match s { | [< (Comma,_); t = type_path_list p s >] -> t | [< >] -> ([] , p) } } function rec type_path_next(t,p,s) { match s { | [< (Arrow,_); t2 , p = type_path s >] -> mk EArrow(t,t2) p | [< (Const (Ident tname),p) >] -> type_path_next EType(Some t,[],tname) p s | [< (Const (Constr m),p); (Dot,_); l = type_path_mod s; (Const (Ident tname),_) >] -> type_path_next EType(Some t,m :: l,tname) p s | [< >] -> (t , p) } } function rec type_path_mod(s) { match s { | [< (Const (Constr m),_); (Dot,_); l = type_path_mod s >] -> m :: l | [< >] -> [] } } function rec type_decl_parameters(s) { match s { | [< (Quote,_); (Const (Ident a),_); >] -> [a] | [< (ParentOpen _,_); l = type_decl_plist s; (ParentClose,_); >] -> l | [< >] -> [] } } function rec type_decl_plist(s) { match s { | [< (Quote,_); (Const (Ident a),_); l = type_decl_plist_next s >] -> a :: l } } function rec type_decl_plist_next(s) { match s { | [< (Comma,_); l = type_decl_plist s >] -> l | [< >] -> [] } } function rec type_declaration(p,s) { match s { | [< (BraceOpen,_) >] -> match s { | [< el , p = record_declaration false s >] -> mk ERecord(el) p | [< el , p = union_declaration s >] -> mk EUnion(el) p } | [< (Binop "=",_); t , p = type_path s >] -> mk EAlias(t) p | [< >] -> mk EAbstract p } } function rec record_declaration(mut,s) { match s { | [< (BraceClose,p) >] -> mk [] p | [< (Const (Ident "mutable"),_); l = record_declaration true s >] -> l | [< (Semicolon,_); l = record_declaration false s >] -> l | [< (Const (Ident name),_); (Binop ":",_); t , _ = type_path s; l , p = record_declaration false s >] -> mk ((name,mut,t) :: l) p } } function rec union_declaration(s) { match s { | [< (BraceClose,p) >] -> mk [] p | [< (Semicolon,_); l = union_declaration s >] -> l | [< (Const (Constr name),_); t = type_opt s; l , p = union_declaration s >] -> mk ((name,t) :: l) p } } function rec patterns_begin(s) { match s { | [< (Vertical,_); l = patterns s >] -> l | [< l = patterns s >] -> l } } function rec patterns(s) { match s { | [< p = pattern s; pl = pattern_next s; w = when_clause s; (Arrow,pa); b = block s; l = patterns_begin s >] -> var pat = (p :: pl,w,match b { [e] -> e | _ -> mk EBlock(b) pa }); pat :: l | [< >] -> [] } } function rec pattern_next(s) { match s { | [< (Vertical,_); p = pattern s; l = pattern_next s >] -> p :: l | [< >] -> [] } } function rec pattern(s) { match s { | [< d , p = pattern_decl s >] -> match s { | [< (Const (Ident "as"),_); (Const (Ident v),p2) >] -> mk PAlias(v,(d,p)) punion(p,p2) | [< (Binop "::",_); d2 , p2 = pattern s >] -> mk PConstr([],"::",Some (PTuple [(d,p);(d2,p2)] , punion p p2)) punion(p,p2) | [< t = type_opt s >] -> match t { | None -> mk d p | Some t -> mk PTyped((d,p),t) p } } } } function rec pattern_decl(s) { match s { | [< (ParentOpen _,p1); pl = pattern_tuple s; (ParentClose,p2) >] -> mk PTuple(pl) punion(p1,p2) | [< (BraceOpen,p1); (Const (Ident name),_); (Binop "=",_); p = pattern s; pl = pattern_record s; (BraceClose,p2) >] -> mk PRecord((name,p) :: pl,0) punion(p1,p2) | [< (Const (Constr name),p1); l, name2, p2 = pattern_mod_path name p1 s; p , p3 = pattern_opt p2 s >] -> mk PConstr(l,name2,p) punion(p1,p3) | [< (Const (Ident i),p); >] -> mk PIdent(i) p | [< (Const c,p); >] -> mk PConst(c) p | [< (Binop "-",p1); (Const (Int i),p2) >] -> mk PConst(Int (-i)) punion(p1,p2) | [< (BracketOpen,p1); l = pattern_list s; (BracketClose,p2) >] -> make_list_pat (punion p1 p2) l | [< (StreamOpen,p1); l = stream_list s; (StreamClose,p2) >] -> mk PStream(l,0) punion(p1,p2) } } function rec pattern_mod_path(name,p,s) { match s { | [< (Dot,_); (Const (Constr n),p); l, n2, p2 = pattern_mod_path n p s >] -> (name :: l , n2 , p2) | [< >] -> ([], name, p) } } function rec stream_list(s) { match s { | [< (Const (Ident v),p1) >] -> match s { | [< l = stream_ident_list s; e = expr s >] -> SExpr(v :: l,e) :: stream_next s | [< >] -> SPattern (PIdent v,p1) :: stream_next s } | [< p = pattern s; l = stream_next s >] -> SPattern p :: l | [< >] -> [] } } function rec stream_ident_list(s) { match s { | [< (Comma,_); (Const (Ident v),_); l = stream_ident_list s >] -> v :: l | [< (Binop "=",_) >] -> [] } } function rec stream_next(s) { match s { | [< (Semicolon,_); l = stream_list s >] -> l | [< >] -> [] } } function rec pattern_list(s) { match s { | [< p = pattern s; l = pattern_list_next s >] -> p :: l | [< >] -> [] } } function rec pattern_list_next(s) { match s { | [< (Semicolon,_); l = pattern_list s >] -> l | [< >] -> [] } } function rec pattern_tuple(s) { match s { | [< p = pattern s; l = pattern_tuple_next s >] -> p :: l | [< >] -> [] } } function rec pattern_tuple_next(s) { match s { | [< (Comma,_); l = pattern_tuple s >] -> l | [< >] -> [] } } function rec pattern_record(s) { match s { | [< (Const (Ident name),_); (Binop "=",_); p = pattern s; l = pattern_record s >] -> (name,p) :: l | [< (Semicolon,_); l = pattern_record s >] -> l | [< >] -> [] } } function rec pattern_opt(p,s) { match s { | [< p = pattern s >] -> (Some p , snd p) | [< >] -> (None , p) } } function rec when_clause(s) { match s { | [< (Keyword When,_); e = expr s >] -> Some e | [< >] -> None } } function parse(lex) { var last = &(Eof,Lexer.null_pos); function rec next_token() { var t = Lexer.token lex (*Nekoml.Lexer.token); match fst t { | Comment s | CommentLine s -> next_token() | _ -> last := t; t } }; try { var p = program (stream next_token); mk EBlock(p) Lexer.null_pos } catch { Stream_error -> error Unexpected(fst (*last)) snd(*last) } } neko-2-2-0/src/nekoml/Type.nml000066400000000000000000000201421321613172000161450ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type pos = Lexer.pos type mutflag { Mutable; Immutable; } type t; type type_expr { TAbstract; TMono : int; TPoly; TRecord : (string , mutflag , t) list; TUnion : (int , (string , t) list); TTuple : t list; TLink : t; TFun : (t list , t); TNamed : (string list , t list , t); } type t { mutable tid : int; mutable texpr : type_expr; } type tconstant { TVoid; TInt : int; TBool : bool; TFloat : string; TString : string; TChar : char; TIdent : string; TConstr : string; TModule : (string list, tconstant); } type texpr; type match_op { MRoot; MFailure; MHandle : (match_op, match_op); MExecute : (texpr, bool); MConstants : (match_op, (tconstant, match_op) list); MField : (match_op, int); MTuple : (match_op, int); MToken : (match_op, int); MRecordField : (match_op, string, t); MJunk : (match_op, int, match_op); MSwitch : (match_op, (tconstant, match_op) list); MBind : (string, match_op, match_op); MWhen : (texpr, match_op); MNext : (match_op, match_op); } type texpr_decl { TConst : tconstant; TBlock : texpr list; TParenthesis : texpr; TCall : (texpr, texpr list); TField : (texpr, string); TArray : (texpr, texpr); TVar : (string list, texpr); TIf : (texpr, texpr, texpr option); TFunction : (bool, string, (string, t) list, texpr); TBinop : (string, texpr, texpr); TTupleDecl : texpr list; TTypeDecl : t; TMut : texpr ref; TRecordDecl : (string, texpr) list; TListDecl : texpr list; TUnop : (string, texpr); TMatch : (texpr, match_op, bool); TTry : (texpr, match_op); TTupleGet : (texpr, int); TErrorDecl : (string, t); TWhile : (texpr, texpr); } type texpr { edecl : texpr_decl; etype : t; epos : pos; } type id_gen = int ref function pos(e) { e.epos } function rec tlinks(name,t) { match t.texpr { | TLink t -> tlinks name t | TNamed (_,_,t) when !name -> tlinks name t | _ -> t.texpr } } function etype(name,e) { tlinks name e.etype } function genid(i) { i := *i + 1; *i } function generator() { &0 } function mk(e,t,p) { { edecl = e; etype = t; epos = p; } } var t_abstract = { tid = -1; texpr = TAbstract } function abstract(s) { tid = -1; texpr = TNamed [s] [] t_abstract; } // theses are not really unique since they're declared // also in Core, so it's not possible to use physeq var t_void = abstract "void"; var t_int = abstract "int"; var t_float = abstract "float"; var t_char = abstract "char"; var t_error = abstract "error"; var t_string = abstract "string" var t_bool = { tid = -1; texpr = TNamed ["bool"] [] ({ tid = -1; texpr = TUnion 2 [ ("true",t_abstract); ("false",t_abstract) ]; }); } function rec is_int(t) { match t.texpr { | TNamed(["int"],_,_) -> true | TLink t -> is_int t | _ -> false } } function t_mono(g) { { tid = -2; texpr = TMono (genid g); } } function t_polymorph(g) { { tid = genid g; texpr = TPoly; } } function t_poly(g,name) { var param = t_mono g; ({ tid = genid g; texpr = TNamed [name] [param] ({ tid = -1; texpr = TAbstract }); } , param) } function mk_fun(g,params,ret) { { tid = if List.exists (function(t) { t.tid != -1 }) (ret :: params) then genid g else -1; texpr = TFun params ret; } } function mk_tup(g,l) { { tid = if List.exists (function(t) { t.tid != -1 }) l then genid g else -1; texpr = TTuple l; } } function mk_record(g,fl) { { tid = if List.exists (function((_,_,t)) { t.tid != -1 }) fl then genid g else -1; texpr = TRecord fl; } } function mk_union(g,fl) { { tid = if List.exists (function((_,t)) { t.tid != -1 }) fl then genid g else -1; texpr = TUnion List.length(fl) fl; } } function rec file_name(m : string list,ext) { match m { | [] -> invalid_arg() | [x] -> x + ext | p :: l -> var c = String.get p 0; var p = if c < 'A' || c > 'Z' then p else { var p = String.sub p 0 (String.length p); String.set p 0 chr(ord c - ord 'A' + ord 'a'); p } p + "/" + file_name l ext } } type print_infos { mutable pi_mcount : int; mutable pi_pcount : int; mutable pi_ml : (t, int) list; mutable pi_ph : (int, int) Hashtbl.t; } function s_context() { { pi_mcount = 0; pi_pcount = 0; pi_ml = []; pi_ph = Hashtbl.create(); } } function poly_id(n) { if n < 26 then String.make 1 chr(ord 'a' + n) else string (n - 25) } function s_mutable(m) { match m { | Mutable -> "mutable " | Immutable -> "" } } function rec s_type(ext,h,t) { match t.texpr { | TAbstract -> "" | TMono _ -> sprintf "'_%s" poly_id(try if t.tid != -2 then assert(); List.phys t h.pi_ml; catch { Not_found -> var k = h.pi_mcount; h.pi_mcount := h.pi_mcount + 1; h.pi_ml := (t,k) :: h.pi_ml; k }) | TPoly -> sprintf "'%s" poly_id(try if t.tid == -1 then assert(); Hashtbl.find h.pi_ph t.tid catch { Not_found -> var k = h.pi_pcount; h.pi_pcount := h.pi_pcount + 1; Hashtbl.add h.pi_ph t.tid k; k }) | TRecord fl -> sprintf "{ %s }" (String.concat "; " (List.map (function((f,m,t)) { s_mutable m + f + " : " + s_type false h t }) fl)) | TUnion (_,fl) -> sprintf "{ %s }" (String.concat "; " (List.map (function((f,t)) { f + " : " + s_type false h t }) fl)) | TTuple l -> sprintf "(%s)" (String.concat ", " (List.map (s_type false h) l)) | TLink t -> s_type ext h t | TFun (tl,r) -> var l = String.concat " -> " (List.map (s_fun false h) tl) + " -> "; l + s_type false h r | TNamed (name,params,t) -> var s = match params { | [] -> "" | [p] -> s_type false h p + " " | l -> "(" + String.concat ", " (List.map (s_type false h) l) + ") " }; var name = String.concat "." name; if ext then s + name + " = " + s_type false h t else s + name } } function rec s_fun(ext,h,t) { match t.texpr { | TLink t -> s_fun ext h t | TFun _ -> "(" + s_type ext h t + ")" | _ -> s_type ext h t } } function rec duplicate(g,h,t) { if t.tid < 0 then t else try Hashtbl.find h t.tid catch { Not_found -> var t2 = { tid = genid g; texpr = TAbstract; }; Hashtbl.add h t.tid t2; t2.texpr := match t.texpr { | TAbstract -> TAbstract | TMono _ -> assert() | TPoly -> t2.tid := -2; TMono (genid g) | TRecord tl -> TRecord (List.map (function((n,m,t)) { (n , m, duplicate g h t) }) tl) | TUnion (n,tl) -> TUnion n (List.map (function((n,t)) { (n , duplicate g h t) }) tl) | TTuple tl -> TTuple (List.map (duplicate g h) tl) | TLink t -> TLink (duplicate g h t) | TFun (tl,t) -> TFun (List.map (duplicate g h) tl) (duplicate g h t) | TNamed (n,p,t) -> TNamed n (List.map (duplicate g h) p) (duplicate g h t) }; t2 } } function rec polymorphize(g,mink,t) { if t.tid == -1 then () else match t.texpr { | TAbstract -> () | TMono k -> if k > mink then { t.texpr := TPoly; t.tid := genid g } | TPoly -> () | TRecord fl -> List.iter (function((_,_,t)) { polymorphize g mink t }) fl | TUnion (_,fl) -> List.iter (function((_,t)) { polymorphize g mink t }) fl | TTuple tl -> List.iter (polymorphize g mink) tl | TLink t -> polymorphize g mink t | TFun (tl,t) -> List.iter (polymorphize g mink) tl; polymorphize g mink t | TNamed (_,tl,t) -> List.iter (polymorphize g mink) tl } } neko-2-2-0/src/nekoml/Typer.nml000066400000000000000000000775531321613172000163510ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ open Nekoml.Ast; open Nekoml.Type; type module_context { mutable file : string; path : string list; types : (string,t) Hashtbl.t; constrs : (string, (t, t)) Hashtbl.t; records : (string, (t, t, mutflag)) Hashtbl.t; deps : (string list, module_context) Hashtbl.t; mutable done : bool; mutable idents : (string,t) Map.t; } type context { gen : id_gen; mutable mink : int; mutable functions : (bool, string, texpr ref, t, (string, t) list, expr, t, pos) list; mutable opens : module_context list; mutable curfunction : string; filecache : (string, string) Hashtbl.t; tmptypes : (string, (t, t list, (string,t) Hashtbl.t)) Hashtbl.t; current : module_context; modules : (string list, module_context) Hashtbl.t; classpath : string list; callback : context -> module_context -> texpr -> void; } type error_msg { Cannot_unify : (t, t); Have_no_field : (t, string); Stack : (error_msg, error_msg); Unknown_field : string; Module_not_loaded : module_context; Custom : string; } exception Error : (error_msg , pos); function rec error_msg_loop(h,m) { match m { | Cannot_unify (t1,t2) -> "Cannot unify " + s_type false h t1 + " and " + s_type false h t2 | Have_no_field (t,f) -> s_type false h t + " have no field " + f | Stack (m1,m2) -> error_msg_loop h m1 + "\n " + error_msg_loop h m2 | Unknown_field s -> "Unknown field " + s | Module_not_loaded m -> "Module " + String.concat "." m.path + " require an interface" | Custom s -> s } } function error_msg(m) { error_msg_loop s_context() m } function s_ttype(t) { s_type false s_context() t } function error(m,p) { throw Error(m,p) } Nekoml.Match.error_ref := (function(msg,p) error Custom(msg) p); var verbose = &false; var load_module_ref = &(function(_,_,_) { assert() }); function add_local(ctx,v,t) { if v != "_" then ctx.current.idents := Map.add ctx.current.idents v t } function save_locals(ctx) { ctx.current.idents } function restore_locals(ctx,l) { ctx.current.idents := l } function module(ctx,path) { Hashtbl.find ctx.modules path } function union(m,c) { fst (Hashtbl.find m.constrs c) } function get_module(ctx,path,p) { match path { | [] -> ctx.current | _ -> var m = try Hashtbl.find ctx.modules path catch { Not_found -> (*load_module_ref) ctx path p }; if m != ctx.current then { if !m.done then error (Module_not_loaded m) p; Hashtbl.replace ctx.current.deps m.path m; }; m } } function get_type(ctx,path,name,p) { function rec loop(l) { match l { | [] -> error Custom("Unknown type " + s_path path name) p | m :: l -> try { Hashtbl.find m.types name } catch { Not_found -> loop l } } } match path { | [] -> loop (ctx.current :: ctx.opens); | _ -> loop [get_module ctx path p] } } function get_constr(ctx,path,name,p) { function rec loop(l) { match l { | [] -> error Custom("Unknown constructor " + s_path path name) p | m :: l -> try { var t1, t2 = Hashtbl.find m.constrs name; (if m == ctx.current then [] else m.path , t1, t2) } catch { Not_found -> loop l } } }; match path { | [] -> loop (ctx.current :: ctx.opens) | _ -> loop [get_module ctx path p] } } function get_ident(ctx,path,name,p) { function rec loop(l) { match l { | [] -> error Custom("Unknown identifier " + s_path path name) p | m :: l -> try (if m == ctx.current then [] else m.path , Map.find m.idents name) catch { Not_found -> loop l } } } match path { | [] -> loop (ctx.current :: ctx.opens) | _ -> loop [get_module ctx path p] } } function get_record(ctx,f,p) { function rec loop(l) { match l { | [] -> error (Unknown_field f) p | m :: l -> try Hashtbl.find m.records f catch { Not_found -> loop l } } } var rt , ft , mut = loop (ctx.current :: ctx.opens); var h = Hashtbl.create(); (duplicate ctx.gen h rt, duplicate ctx.gen h ft, mut) } function rec is_tuple(t) { match t.texpr { | TLink t -> is_tuple t | TTuple _ -> true | TNamed(_,_,t) -> is_tuple t | _ -> false } } function rec is_recursive(t1,t2) { if t1 === t2 then true else match t2.texpr { | TAbstract | TMono _ | TPoly -> false | TRecord _ | TUnion _ -> assert() | TTuple tl -> List.exists (is_recursive t1) tl | TLink t -> is_recursive t1 t | TFun (tl,t) -> List.exists (is_recursive t1) tl || is_recursive t1 t | TNamed (_,p,t) -> List.exists (is_recursive t1) p } } function link(ctx,t1,t2,p) { if is_recursive t1 t2 then error Cannot_unify(t1,t2) p; t1.texpr := TLink t2; if t1.tid < 0 then { if t2.tid == -1 then t1.tid := -1 else t1.tid := genid ctx.gen; } else if t2.tid == -1 then t1.tid := -1 } function unify_stack(t1,t2,e) { match e { | Error ((Cannot_unify _) as e, p) -> error (Stack e Cannot_unify(t1,t2)) p | e -> throw e } } function is_alias(t) { match t { | TAbstract | TRecord _ | TUnion _ -> false | TMono _ | TPoly | TTuple _ | TLink _ | TFun _ | TNamed _ -> true } } function rec propagate(k,t) { match t.texpr { | TAbstract | TPoly -> () | TUnion _ | TRecord _ -> assert() | TMono k2 -> if k < k2 then t.texpr := TMono k | TTuple tl -> List.iter (propagate k) tl | TLink t -> propagate k t | TFun (tl,t) -> propagate k t; List.iter (propagate k) tl | TNamed (_,tl,_) -> List.iter (propagate k) tl } } function rec unify(ctx,t1,t2,p) { if t1 == t2 then () else match (t1.texpr , t2.texpr) { | (TLink t , _) -> unify ctx t t2 p | (_ , TLink t) -> unify ctx t1 t p | (TPoly , _) -> link ctx t1 t2 p | (_ , TPoly) -> link ctx t2 t1 p | (TMono k , _) -> link ctx t1 t2 p; propagate k t2 | (_ , TMono k) -> link ctx t2 t1 p; propagate k t1 | (TNamed (n1,p1,_) , TNamed (n2,p2,_)) when n1 == n2 -> try List.iter2 (function(p1,p2) { unify ctx p1 p2 p }) p1 p2 catch { e -> unify_stack t1 t2 e } | (TNamed (_,_,t1) , _) when is_alias t1.texpr -> try unify ctx t1 t2 p catch { e -> unify_stack t1 t2 e } | (_ , TNamed (_,_,t2)) when is_alias t2.texpr -> try unify ctx t1 t2 p catch { e -> unify_stack t1 t2 e } | (TFun (tl1,r1) , TFun (tl2,r2)) when List.length tl1 == List.length tl2 -> try List.iter2 (function(t1,t2) { unify ctx t1 t2 p }) tl1 tl2; unify ctx r1 r2 p; catch { e -> unify_stack t1 t2 e } | (TTuple tl1 , TTuple tl2) when List.length tl1 == List.length tl2 -> try List.iter2 (function(t1,t2) { unify ctx t1 t2 p }) tl1 tl2 catch { e -> unify_stack t1 t2 e } | _ -> error Cannot_unify(t1,t2) p } } function rec type_type(allow,h,ctx,t,p) { match t { | ETuple [] -> assert() | ETuple [t] -> type_type allow h ctx t p | ETuple el -> mk_tup ctx.gen (List.map (function(t) { type_type allow h ctx t p }) el) | EPoly s -> try Hashtbl.find h s catch { Not_found -> if !allow then error Custom("Unbound type variable '" + s) p; var t = t_mono ctx.gen; Hashtbl.add h s t; t } | EType (param,path,name) -> var param = match param { None -> None | Some t -> Some (type_type allow h ctx t p) }; var t = get_type ctx path name p; match t.texpr { | TNamed (_,params,t2) -> var tl = match (params, param) { | ([] , None) -> [] | ([x] , Some t) -> [t] | (l , Some { texpr = TTuple tl }) when List.length tl == List.length l -> tl | _ -> error Custom("Invalid number of type parameters for " + s_path path name) p }; var h = Hashtbl.create(); var t = duplicate ctx.gen h t; var params = List.map (duplicate ctx.gen h) params; List.iter2 (function(pa,t) { unify ctx pa t p }) params tl; t | _ -> assert() } | EArrow _ -> function rec loop(params,t) { match t { | EArrow (ta,tb) -> var ta = type_type allow h ctx ta p; loop (ta :: params) tb | _ -> var t = type_type allow h ctx t p; mk_fun ctx.gen (List.rev params) t } }; loop [] t } } function rec type_constant(ctx,path,c,p) { match c { | Int i -> mk TConst(TInt i) t_int p | Float s -> mk TConst(TFloat s) t_float p | Bool b -> mk TConst(TBool b) t_bool p | String s -> mk TConst(TString s) t_string p | Char c -> mk TConst(TChar c) t_char p | Ident s -> var path , t = get_ident ctx path s p; var t = duplicate ctx.gen Hashtbl.create() t; mk TConst(TModule path TIdent(s)) t p | Constr s -> var path , ut , t = get_constr ctx path s p; var t = duplicate ctx.gen Hashtbl.create() (match t.texpr { | TAbstract -> ut | TTuple tl -> mk_fun ctx.gen tl ut | _ -> mk_fun ctx.gen [t] ut }); mk TConst(TModule path TConstr(s)) t p | Module (path,c) -> type_constant ctx path c p } } type addable { NInt; NFloat; NString; NNan; } function addable(str,e) { match etype true e { | TNamed (["int"],_,_) -> NInt | TNamed (["float"],_,_) -> NFloat | TNamed (["string"],_,_) when str -> NString | _ -> NNan } } function type_binop(ctx,op,e1,e2,p) { function emk(t) { mk TBinop(op,e1,e2) t p }; match op { | "%" | "+" | "-" | "/" | "*" -> var str = (op == "+"); match (addable str e1, addable str e2) { | (NInt , NInt) -> emk t_int | (NFloat , NFloat) | (NInt , NFloat) | (NFloat , NInt) -> emk t_float | (NInt , NString) | (NFloat , NString) | (NString , NInt) | (NString , NFloat) | (NString , NString) -> emk t_string | (NInt , NNan) | (NFloat , NNan) | (NString , NNan) -> unify ctx e2.etype e1.etype (pos e2); emk e1.etype | (NNan , NInt) | (NNan , NFloat) | (NNan , NString) -> unify ctx e1.etype e2.etype (pos e1); emk e2.etype | (NNan , NNan) -> unify ctx e1.etype t_int (pos e1); unify ctx e2.etype t_int (pos e2); emk t_int } | ">>" | ">>>" | "<<" | "and" | "or" | "xor" -> unify ctx e1.etype t_int (pos e1); unify ctx e2.etype t_int (pos e2); emk t_int | "&&" | "||" -> unify ctx e1.etype t_bool (pos e1); unify ctx e2.etype t_bool (pos e2); emk t_bool | "<" | "<=" | ">" | ">=" | "==" | "!=" | "===" | "!==" -> unify ctx e2.etype e1.etype (pos e2); emk t_bool | ":=" -> match e1.edecl { | TArray _ -> unify ctx e2.etype e1.etype (pos e2); emk t_void | TField (e,f) -> match tlinks false e.etype { | TRecord fl -> var _ , mut , _ = try List.find (function((f2,_,_)) { f2 == f }) fl catch { Not_found -> assert() }; if mut == Immutable then error Custom("Field " + f + " is not mutable") pos(e1); unify ctx e2.etype e1.etype (pos e2); emk t_void | _ -> assert(); } | _ -> var t , pt = t_poly ctx.gen "ref"; unify ctx e2.etype pt (pos e2); unify ctx e1.etype t (pos e1); emk t_void } | "::" -> var t , pt = t_poly ctx.gen "list"; unify ctx e1.etype pt (pos e1); unify ctx e2.etype t (pos e2); var c = mk TConst(TConstr "::") t_mono(ctx.gen) p; mk (TCall c [e1;e2]) t p | _ -> error Custom("Invalid operation " + op) p } } function type_unop(ctx,op,e,p) { function emk(t) { mk TUnop(op,e) t p }; match op { | "&" -> var p , pt = t_poly ctx.gen "ref"; unify ctx e.etype pt (pos e); emk p | "*" -> var p , pt = t_poly ctx.gen "ref"; unify ctx e.etype p (pos e); emk pt | "!" -> unify ctx e.etype t_bool (pos e); emk t_bool | "-" -> match addable false e { | NInt -> emk t_int | NFloat -> emk t_float | _ -> unify ctx e.etype t_int (pos e); emk t_int } | _ -> assert() } } function rec type_arg(ctx,h,binds,p,a) { match a { | ATyped (a,t) -> var n , ta = type_arg ctx h binds p a; unify ctx ta (type_type true h ctx t p) p; (n , ta) | ANamed s -> (s , t_mono ctx.gen) | ATuple al -> var aname = "@t" + string (genid ctx.gen); var nl , tl = List.split (List.map (type_arg ctx h binds p) al); var k = &0; List.iter (function(n) { if n != "_" then binds := (aname,*k,n) :: *binds; k := *k + 1; }) nl; (aname , mk_tup ctx.gen tl) } } function register_function(ctx,isrec,name,pl,e,rt,p) { if ctx.functions == [] then ctx.mink := *ctx.gen; var pl = match pl { | [] -> [ATyped (ANamed "_") EType(None,[],"void")] | _ -> pl }; var expr = &(mk (TConst TVoid) t_void p); var h = Hashtbl.create(); var binds = &[]; var el = List.map (type_arg ctx h binds p) pl; var name = match name { None -> "_" | Some n -> n }; var e = match List.rev (*binds) { | [] -> e | l -> var b = List.fold (function(acc,(v,n,v2)) { var tget = ETupleGet (EConst Ident(v),p) n; (EVar [(v2,None)] (tget,p) , p) :: acc }) [e] l; (EBlock b , p) }; var rt = match rt { | None -> t_mono ctx.gen | Some rt -> type_type true h ctx rt p }; var ft = mk_fun ctx.gen (List.map snd el) rt; ctx.functions := (isrec,name,expr,ft,el,e,rt,p) :: ctx.functions; if isrec then add_local ctx name ft; mk (TMut expr) (if name == "_" then ft else t_void) p } function type_format(ctx,s,p) { var types = &[]; var percent = &false; var i = &0; var l = String.length s; while *i < l { var c = String.get s (*i); if *percent then { percent := false; match c { | '%' -> () | 'x' | 'X' | 'd' -> types := t_int :: *types | 'f' -> types := t_float :: *types | 's' -> types := t_string :: *types | 'b' -> types := t_bool :: *types | 'c' -> types := t_char :: *types | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '.' -> percent := true | _ -> error (Custom "Invalid % sequence") p } } else match c { | '%' -> percent := true | _ -> () } i := *i + 1; }; if *percent then error (Custom "Invalid % sequence") p; match *types { | [] -> t_void | [x] -> x | l -> mk_tup ctx.gen (List.rev l) } } function rec type_functions(ctx) { var l = ctx.functions; if l != [] then { var mink = ctx.mink; ctx.functions := []; var l = List.map (function((isrec,name,expr,ft,el,e,rt,p)) { var locals = save_locals ctx; var func = ctx.curfunction; if name != "_" then { var fname = s_path ctx.current.path name; if *verbose then print ("Typing "+fname+"\n"); ctx.curfunction := fname; } List.iter (function((p,pt)) { add_local ctx p pt }) el; var e = type_expr ctx e; restore_locals ctx locals; ctx.curfunction := func; var ft2 = mk_fun ctx.gen (List.map snd el) e.etype; unify ctx ft ft2 p; expr := mk TFunction(isrec,name,el,e) ft2 p; if !isrec then add_local ctx name ft; (name == "_" , ft2) }) (List.rev l); List.iter (function((anon,t)) { if !anon then polymorphize ctx.gen mink t }) l } } function rec type_expr(ctx,(e,p)) { match e { | EConst c -> type_constant ctx [] c p | EBlock [] -> mk TConst(TVoid) t_void p | EBlock (e :: l) -> var locals = save_locals ctx; var e = type_block ctx e; var el , t = List.fold (function((l,t),e) { unify ctx t t_void (List.hd l).epos; var e = type_block ctx e; (e :: l , e.etype) }) ([e] , e.etype) l; type_functions ctx; restore_locals ctx locals; mk TBlock(List.rev el) t p | EApply (e,el) -> type_expr ctx (ECall e el,p) | ECall ((EConst (Ident "open"),_),[(EConst (Module (m,Constr modname)),p)]) -> ctx.opens := get_module ctx (List.append m [modname]) p :: ctx.opens; mk (TConst TVoid) t_void p | ECall ((EConst (Ident "open"),_),[(EConst (Constr modname),p)]) -> ctx.opens := get_module ctx [modname] p :: ctx.opens; mk (TConst TVoid) t_void p | ECall ((EConst (Ident "assert"),_) as a,[]) -> type_expr ctx (ECall a [(EConst (String p.psource),p);(EConst (Int p.pline),p)], p) | ECall ((EConst (Ident "invalid_arg"),_) as a,[]) -> type_expr ctx (ECall a [(EConst (String ctx.curfunction),p)], p) | ECall ((EConst (Constr "TYPE"),_),[e]) -> var e = type_expr ctx e; printf "%s:(%d): type : %s\n" (p.psource,p.pline,s_type true s_context() e.etype); mk (TParenthesis e) t_void p | ECall (e,el) -> var e = type_expr ctx e; var el = match el { [] -> [(ETupleDecl [],p)] | _ -> el }; var el = List.map (type_expr ctx) el; match etype false e { | TFun (args,r) -> function rec loop(acc,expr,l,tl,r) { match (l , tl) { | (e :: l , t :: tl) -> match tlinks true t { | TNamed (["format"],[param],_) -> match e.edecl { | TConst (TString s) -> var tfmt = type_format ctx s e.epos; unify ctx param tfmt e.epos; | _ -> match tlinks true e.etype { | TNamed (["format"],[param2],_) -> unify ctx param2 param e.epos | _ -> error Custom("Constant string required for format") e.epos } } | _ -> unify ctx e.etype t (pos e) } loop (e :: acc) expr l tl r | ([] , []) -> mk TCall(expr,List.rev acc) r p | ([] , tl) -> mk TCall(expr,List.rev acc) (mk_fun ctx.gen tl r) p | (el , []) -> match tlinks false r { | TFun (args,r2) -> loop [] (mk TCall(expr,List.rev acc) r p) el args r2 | _ -> error Custom("Too many arguments") p } | _ -> assert() } } loop [] e el args r | _ -> var r = t_mono ctx.gen; var f = mk_fun ctx.gen (List.map (function(e) { e.etype }) el) r; unify ctx e.etype f p; mk TCall(e,el) r p } | EField (e,s) -> var e = type_expr ctx e; var t = match etype false e { | TRecord fl -> try { var _ , _ , t = List.find (function((s2,_,_)) { s == s2 }) fl; t } catch { Not_found -> error Have_no_field(e.etype,s) p } | _ -> var r , t , _ = get_record ctx s p; unify ctx e.etype r (pos e); t }; mk TField(e,s) t p | EArray (e,ei) -> var e = type_expr ctx e; var ei = type_expr ctx ei; unify ctx ei.etype t_int (pos ei); var t , pt = t_poly ctx.gen "array"; unify ctx e.etype t (pos e); mk TArray(e,ei) pt p | EVar _ -> error Custom("Variable declaration not allowed outside a block") p | EIf (e,e1,None) -> var e = type_expr ctx e; unify ctx e.etype t_bool (pos e); var e1 = type_expr ctx e1; unify ctx e1.etype t_void (pos e1); mk TIf(e,e1,None) t_void p | EIf (e,e1,Some e2) -> var e = type_expr ctx e; unify ctx e.etype t_bool (pos e); var e1 = type_expr ctx e1; var e2 = type_expr ctx e2; unify ctx e2.etype e1.etype (pos e2); mk TIf(e,e1,Some e2) e1.etype p | EWhile (e1,e2) -> var e1 = type_expr ctx e1; unify ctx e1.etype t_bool (pos e1); var e2 = type_expr ctx e2; unify ctx e2.etype t_void (pos e2); mk TWhile(e1,e2) t_void p | EFunction (isrec,name,pl,e,rt) -> var r = register_function ctx isrec name pl e rt p; type_functions ctx; r | EBinop (op,e1,e2) -> type_binop ctx op (type_expr ctx e1) (type_expr ctx e2) p | ETypeAnnot (e,t) -> var e = type_expr ctx e; var t = type_type true Hashtbl.create() ctx t p; unify ctx e.etype t (pos e); mk e.edecl t p | ETupleDecl [] -> mk TConst(TVoid) t_void p | ETupleDecl [e] -> var e = type_expr ctx e; mk TParenthesis(e) e.etype (pos e) | ETupleDecl el -> var el = List.map (type_expr ctx) el; mk TTupleDecl(el) (mk_tup ctx.gen (List.map (function(e) { e.etype }) el)) p | ETypeDecl (params,tname,decl) -> var fullname = match ctx.current.path { ["Core"] -> [tname] | p -> List.append p [tname]}; var t , tl , h = try { var t , tl , h = Hashtbl.find ctx.tmptypes tname; if decl != EAbstract then Hashtbl.remove ctx.tmptypes tname; if List.length tl != List.length params then error Custom("Invalid number of parameters for type " + tname) p; (t , tl , h) } catch { Not_found -> if Hashtbl.exists ctx.current.types tname then error Custom("Invalid type redefinition of type " + tname) p; var h = Hashtbl.create(); var tl = List.map (function(p) { var t = t_mono ctx.gen; Hashtbl.add h p t; t }) params; var t = { tid = -1; texpr = TNamed fullname tl t_abstract; }; Hashtbl.add ctx.current.types tname t; if decl == EAbstract then Hashtbl.add ctx.tmptypes tname (t,tl,h); (t , tl , h) }; var t2 = match decl { | EAbstract -> t_abstract | EAlias t -> type_type false h ctx t p | ERecord fields -> var fields = List.map (function((f,m,ft)) { var ft = type_type false h ctx ft p; var m = (if m then Mutable else Immutable); Hashtbl.add ctx.current.records f (t,ft,m); (f , m , ft) }) fields; mk_record ctx.gen fields | EUnion constr -> var constr = List.map (function((c,ft)) { var ft = match ft { | None -> t_abstract | Some ft -> type_type false h ctx ft p }; Hashtbl.add ctx.current.constrs c (t,ft); (c , ft) }) constr; mk_union ctx.gen constr }; t.tid := if t2.tid == -1 && params == [] then -1 else genid ctx.gen; t.texpr := TNamed fullname tl t2; polymorphize ctx.gen 0 t; mk TTypeDecl(t) t_void p | ERecordDecl fl -> var s , _ = try List.hd fl catch { _ -> assert() }; var r , _ , _ = get_record ctx s p; var fll = match tlinks false r { | TRecord fl -> fl | _ -> assert() }; var fl2 = &fll; function rec loop(f,l) { match l { | [] -> if List.exists (function((f2,_,_)) { f == f2 }) fll then error Custom("Duplicate declaration for field " + f) p else error Have_no_field(r,f) p | (f2,_,ft) :: l when f == f2 -> (ft , l) | x :: l -> var t , l = loop f l; (t , x :: l) } } var el = List.map (function((f,e)) { var ft , fl2b = loop f (*fl2); fl2 := fl2b; var e = type_expr ctx e; unify ctx e.etype ft (pos e); (f , e) }) fl; List.iter (function((f,_,_)) { error Custom("Missing field " + f + " in record declaration") p; }) (*fl2); mk (TRecordDecl el) r p | EErrorDecl (name,t) -> var t = match t { None -> t_abstract | Some t -> type_type false Hashtbl.create() ctx t p }; Hashtbl.add ctx.current.constrs name (t_error,t); mk TErrorDecl(name,t) t_void p | EUnop (op,e) -> type_unop ctx op (type_expr ctx e) p | EMatch (e,cl) -> var e = type_expr ctx e; var is_stream = match cl { [] -> false | _ -> List.all (function((l,_,_)) { List.all (function((p,_)) { match p { PStream _ -> true | _ -> false }}) l}) cl }; var partial , m , t = type_match ctx e.etype cl p; if !is_stream && partial then error Custom("This matching is not complete") p; mk TMatch(e,m,is_stream) t p | ETry (e,cl) -> var e = type_expr ctx e; var _ , m , t = type_match ctx t_error cl p; unify ctx t e.etype p; mk TTry(e,m) t p | ETupleGet (e,n) -> var e = type_expr ctx e; function try_unify(et) { var t = Array.init (n + 1) (function(_) { t_mono ctx.gen }); unify ctx et (mk_tup ctx.gen (Array.list t)) p; t.[n] } function rec loop(et) { match et.texpr { | TLink et -> loop et | TTuple l -> try List.nth l n catch { _ -> try_unify et } | _ -> try_unify et } } mk TTupleGet(e,n) (loop e.etype) p } } function rec type_block(ctx,x) { var e , p = x; match e { | EVar (vl,e) -> type_functions ctx; var e = type_expr ctx e; function make(v,t) { var t = match t { | None -> t_mono ctx.gen | Some t -> type_type true Hashtbl.create() ctx t p } add_local ctx v t; t } var t = match vl { | [] -> assert() | [(v,t)] -> make v t | _ -> mk_tup ctx.gen (List.map (function((v,t)) { make v t }) vl) } unify ctx t e.etype (pos e); mk TVar(List.map fst vl,e) t_void p | EFunction (true,name,pl,e,rt) -> register_function ctx true name pl e rt p | _ -> type_functions ctx; type_expr ctx x } } function rec type_pattern(ctx,h,h2,set,add,(pat,p)) { function pvar(add,s) { if Set.exists (*set) s then error Custom("This variable is several time in the pattern") p; set := Set.add (*set) s; try Hashtbl.find h s catch { Not_found -> var t = t_mono ctx.gen; Hashtbl.add h s t; if add then add_local ctx s t; t } } var pt , pat = match pat { | PConst c -> (match c { | Int n -> t_int | Float s -> t_float | String s -> t_string | Char c -> t_char | Bool b -> t_bool | Ident _ | Constr _ | Module _ -> assert() } , pat) | PTuple [p] -> var pt , pat = type_pattern ctx h h2 set add p; (pt , fst pat) | PTuple pl -> var pl , patl = List.split (List.map (type_pattern ctx h h2 set add) pl); (mk_tup ctx.gen pl , PTuple patl) | PRecord (fl,_) -> var s = try fst (List.hd fl) catch { _ -> assert() }; var r , _ , _ = get_record ctx s p; var fl = match tlinks false r { | TRecord rl -> List.map (function((f,pat)) { var pt , pat = type_pattern ctx h h2 set add pat; var t = try { var _ , _ , t = List.find (function((f2,_,_)) { f == f2 }) rl; t } catch { Not_found -> error Have_no_field(r,f) p }; unify ctx pt t (snd pat); (f , pat) }) fl | _ -> assert() }; (r , PRecord fl magic(r)) | PIdent s -> (if s == "_" then t_mono ctx.gen else pvar add s , pat) | PConstr (path,s,param) -> var tparam , param = match param { | None -> (None , None ) | Some ((_,p) as param) -> var t , pat = type_pattern ctx h h2 set add param; (Some (p,t) , Some pat) } var path , ut , t = get_constr ctx path s p; match (t.texpr , tparam) { | (TAbstract , None) -> (duplicate ctx.gen Hashtbl.create() ut , PConstr path s param) | (TAbstract , Some _) -> error Custom("Constructor does not take parameters") p | (_ , None) -> error Custom("Constructor require parameters") p | (_ , Some (p,pt)) -> var h = Hashtbl.create(); var ut = duplicate ctx.gen h ut; var t = duplicate ctx.gen h t; var param , pt = match param { | Some (PTuple l,p) when !is_tuple t -> (Some (PTuple [(PTuple l,p)],p) , mk_fun ctx.gen [pt] ut) | Some (PIdent "_",p) -> (param , pt) | _ -> (param , match pt.texpr { TTuple l -> mk_fun ctx.gen l ut | _ -> mk_fun ctx.gen [pt] ut }) } var t = match t.texpr { TTuple l -> mk_fun ctx.gen l ut | _ -> mk_fun ctx.gen [t] ut }; unify ctx t pt p; (ut , PConstr path s param) } | PAlias (s,pat) -> var pt , pat = type_pattern ctx h h2 set false pat; var t = pvar false s; unify ctx pt t (snd pat); (t , PAlias s pat) | PTyped (pat,t) -> var pt , pat = type_pattern ctx h h2 set add pat; unify ctx pt (type_type true h2 ctx t p) p; (pt , PTyped pat t) | PStream (l,k) -> var t , polyt = t_poly ctx.gen "stream"; var locals = save_locals ctx; var l = List.map (function(s) { match s { | SPattern pat -> var t , p = type_pattern ctx h h2 set true pat; unify ctx t polyt (snd p); SPattern p | SExpr ([v],e) -> var e = type_expr ctx e; var t = pvar true v; unify ctx t e.etype e.epos; SMagicExpr (PIdent v,e.epos) magic(e) | SExpr (vl,e) -> var e = type_expr ctx e; var tl = List.map (pvar true) vl; unify ctx (mk_tup ctx.gen tl) e.etype e.epos; var tup = PTuple (List.map (function(v) { (PIdent v, e.epos) }) vl); SMagicExpr (tup,e.epos) magic(e) | SMagicExpr _ -> assert() } }) l; restore_locals ctx locals; (t , PStream l k) } (pt , (pat,p)) } function rec type_match(ctx,t,cl,p) { var ret = t_mono ctx.gen; var cl = List.map (function((pl,wh,pe)) { var first = &true; var h = Hashtbl.create(); var mainset = &Set.empty(); var pl = List.map (function(pat) { var set = &Set.empty(); var pt , pat = type_pattern ctx h Hashtbl.create() set false pat; if *first then { first := false; mainset := *set; } else { var s1 = Set.diff (*set) (*mainset); var s2 = Set.diff (*mainset) (*set); Set.iter (function(s) { error Custom("Variable " + s + " must occur in all patterns") p }) (Set.union s1 s2); } unify ctx pt t p; pat }) pl; var locals = save_locals ctx; Hashtbl.iter (function(v,t) { add_local ctx v t }) h; var wh = match wh { | None -> None | Some e -> var e = type_expr ctx e; unify ctx e.etype t_bool e.epos; Some e } var pe = type_expr ctx pe; unify ctx pe.etype ret (pos pe); restore_locals ctx locals; (pl , wh , pe) }) cl; Nekoml.Match.fully_matched_ref := (function(cl) { match cl { | (TModule(path,TConstr c)) :: l -> var path , ut , t = get_constr ctx path c Lexer.null_pos; if ut == t_error then false else match tlinks false ut { | TUnion (n,_) -> n == List.length cl | _ -> assert() } | TVoid :: _ -> true | _ -> false } }); var partial , m = Nekoml.Match.make cl p; (partial , m , ret) } function module_infos(m) { var h = Hashtbl.create(); var deps = &(if m.path == ["Core"] || Hashtbl.exists m.deps ["Core"] then [] else [["Core"]]); var idents = &[]; Hashtbl.iter (function(_,m) { deps := m.path :: *deps }) m.deps; Map.iter (function(i,t) { idents := i :: *idents }) m.idents; (m.path,*deps,*idents) } function open_file(ctx,m,p) { var file = file_name m ".nml"; function rec loop(l) { match l { | [] -> try { (file, IO.read_string (Hashtbl.find ctx.filecache (String.concat "." m))) } catch { Not_found -> error Custom("File not found " + file) p } | pp :: l -> try { var f = pp + file; (f , IO.read_file f true) } catch { _ -> loop l } } } loop ctx.classpath } function load_module(ctx,m,p) { try Hashtbl.find ctx.modules m catch { Not_found -> var file , ch = open_file ctx m p; var is_core , core = try (false , Hashtbl.find ctx.modules ["Core"]) catch { Not_found -> ctx.current.file := file; (true , ctx.current) } var ctx = { mink = ctx.mink; gen = ctx.gen; modules = ctx.modules; classpath = ctx.classpath; callback = ctx.callback; filecache = ctx.filecache; curfunction = "anonymous"; tmptypes = Hashtbl.create(); functions = []; opens = [core]; current = if is_core then ctx.current else { file = file; path = m; constrs = Hashtbl.create(); records = Hashtbl.create(); types = Hashtbl.create(); done = false; idents = Map.empty(); deps = Hashtbl.create(); } }; Hashtbl.add ctx.modules m ctx.current; var lex = Lexer.create Buffer.create(); Lexer.input lex file ch 1 0; var ast = Nekoml.Parser.parse lex; if *verbose then printf "Parsed %s\n" file; var e = match ast { | (EBlock (e :: l) , p) -> var e = type_block ctx e; var el , t = List.fold (function((l,t),e) { var e = type_block ctx e; (e :: l , e.etype) }) ([e] , e.etype) l; type_functions ctx; mk TBlock(List.rev el) t p | _ -> type_expr ctx ast } if *verbose then printf "Typing done with %s\n" file; ctx.current.done := true; ctx.callback ctx ctx.current e; ctx.current } } function context(cpath,filecache,callb) { var ctx = { gen = generator(); tmptypes = Hashtbl.create(); modules = Hashtbl.create(); filecache = filecache; functions = []; opens = []; mink = 0; classpath = cpath; curfunction = "anonymous"; callback = callb; current = { file = ""; path = ["Core"]; done = false; idents = Map.empty(); constrs = Hashtbl.create(); types = Hashtbl.create(); deps = Hashtbl.create(); records = Hashtbl.create(); }; }; function add_type(args,name,t) { ignore(type_expr ctx (ETypeDecl args name t, Lexer.null_pos)); } function add_variable(name,t) { ctx.current.idents := Map.add ctx.current.idents name t } add_type [] "bool" EUnion([("true",None);("false",None)]); add_type ["a"] "list" (EUnion [("[]",None);("::",Some (ETuple [ EPoly "a"; EType Some(EPoly "a") [] "list"; ]))]); add_variable "neko" (mk_fun ctx.gen [t_polymorph ctx.gen] (t_polymorph ctx.gen)); var core = load_module ctx ["Core"] Lexer.null_pos; ctx } load_module_ref := load_module neko-2-2-0/src/tools/000077500000000000000000000000001321613172000143705ustar00rootroot00000000000000neko-2-2-0/src/tools/Tools.nml000066400000000000000000000035661321613172000162120ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ exception Done; function erase_argument() { neko "$loader.args = $asub($loader.args,1,$asize($loader.args)-1)" } function invalid_arg(f) { throw Args.Invalid } try { var head = "Neko Tools v1.0 - (c)2005-2017 Haxe Foundation\nUsage : nekotools [options]"; var decl = [ ("server", Args.Void (function() { erase_argument(); WebServer.init(); throw Done }) , " : start a neko web server"); ("boot", Args.String (function(_) { erase_argument(); neko "$loader.loadmodule('tools/nekoboot',$loader)"; throw Done; }) , " : build an standalone executable"); ]; Args.parse head decl invalid_arg; } catch { | e -> if e == Done then Sys.exit(0); Stack.dump IO.stderr Stack.exc(); IO.printf IO.stderr "Exception : %s\n" string(e); Sys.exit (-1); }neko-2-2-0/src/tools/WebServer.nml000066400000000000000000000400531321613172000170060ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ type main_function; type client { sock : Net.socket; in : IO.input; out : IO.output; mutable headers : (string, string) list; mutable headers_sent : bool; mutable return_code : (int, string); mutable main : main_function option; } var mime = [ ("gif" , "image/gif"); ("jpeg", "image/jpeg"); ("jpg", "image/jpeg"); ("png", "image/png"); ("css", "text/css"); ("html", "text/html"); ("htm", "text/html"); ("txt", "text/plain"); ("js", "application/javascript"); ("pdf", "application/pdf"); // do we really want that ?? ("xml", "text/xml"); ("wav", "audio/x-wav") ]; var cur_path = &Sys.get_cwd(); var file_log = &None; var module_cache = Hashtbl.create(); var mod_rewrite = &false; function sys_is_file(file) { neko "$loader.loadprim('std@sys_file_type',1)(file)" == "file" } function page_404(url) { " 404 Not Found

Not Found

The requested URL "+url+" was not found on this server.


Neko Web DevServer
" } function page_config() { var path = String.concat " - " neko("@List.@make($loader.path)"); " Neko WebServer Config

Neko WebServer Configuration

Visit website" } type http_method { MethodGet; MethodPost; MethodCustom : string; } type http_request { method : http_method; res : string; url : (string, string); version : string; ctype : string option; headers : (string,string) list; mutable params : (string, string) list; mutable post_data : string option; } exception Invalid_char; function invalid_char(l) { throw Invalid_char }; function part(lex,p,l) { var s = Lexer.current lex; String.sub s p (String.length s - (p+l)) } function parse_get_params(str) { var params = String.split str ";"; var params = List.concat (List.map (function(s) { String.split s "&" }) params); List.map (function(p) { match String.split p "=" { | [] -> ("","") | [p] -> (Net.url_decode p,"") | p :: val -> (Net.url_decode p , Net.url_decode (String.concat "=" val)) } }) params; } var http_request_method = Lexer.build [ ("GET", function(l) { MethodGet }); ("POST", function(l) { MethodPost }); ("PUT", function(l) { MethodCustom "PUT" }); ("HEAD", function(l) { MethodCustom "HEAD" }); ("DELETE", function(l) { MethodCustom "DELETE" }); ("TRACE",function(l) { MethodCustom "TRACE" }); ("CONNECT",function(l) { MethodCustom "CONNECT" }); ("OPTIONS",function(l) { MethodCustom "OPTIONS" }); ] invalid_char; var http_request_url = Lexer.build [ (" [^ ]+ ", function(l) { var url = part l 1 1; try { var p = String.find url 0 "?"; var base = String.sub url 0 p; var params = String.sub url (p + 1) (String.length url - (p+1)); (base, params) } catch { Not_found -> (url,"") } }) ] invalid_char; var http_request_version = Lexer.build [ ("HTTP/[0-9.]+\r\n", function(l) { part l 5 2 }); ] invalid_char; var http_header_value = Lexer.build [ ("[^\r]+\r\n", function(l) { part l 0 2 }) ] invalid_char; var http_headers = &Lexer.empty(); http_headers := Lexer.build [ ("\r", function(l) { if Lexer.read l != '\n' then throw Invalid_char; [] }); ("[-A-Za-z0-9_]+: ", function(l) { var s = part l 0 2; var v = Lexer.token l http_header_value; (s,v) :: Lexer.token l (*http_headers) }); ] invalid_char; function header(name,headers) { try { Some snd(List.find (function((n,_)) { String.lowercase n == String.lowercase name }) headers) } catch { Not_found -> None } } function parse_http_request(c) { var l = Lexer.create(); Lexer.input l "http-stream" c.in 1 0; var meth = Lexer.token l http_request_method; var url = Lexer.token l http_request_url; var version = Lexer.token l http_request_version; var headers = Lexer.token l (*http_headers); var params = parse_get_params snd(url); var ctype = header "Content-Type" headers; var post_data, params = if meth == MethodPost && ctype != Some "multipart/form-data" then { var len = match header "Content-Length" headers { None -> 0 | Some len -> int len }; if len >= (1 << 18) then { IO.write c.out "HTTP/1.1 200 OK\r\n"; IO.write c.out "\n\n"; IO.write c.out "Max post data exceeded"; printf "Max post data exceeded (%d bytes)\n" len; throw IO.Eof; } var b = Buffer.create(); var i = &0; while *i < len { Buffer.add_char b (Lexer.read l); i := *i + 1; } var data = Buffer.string b; (Some data , List.append (parse_get_params data) params); } else (None , params); { method = meth; res = Net.url_decode fst(url); url = url; params = params; version = version; headers = headers; post_data = post_data; ctype = ctype; } } function flog(s) { match *file_log { | None -> () | Some f -> IO.write f s; IO.flush f; } } function log( fmt : 'a format, args : 'a ) { var s = sprintf fmt args + "\n"; print s; flog s; } function init_client(s) { var read, write = Net.socket_io s; var ip , port = Net.socket_peer s; { sock = s; in = read; out = write; headers = [("Content-Type","text/html")]; headers_sent = false; return_code = (200,"OK"); main = None; } } function rec find_url_file(url,recursive) { var len = String.length url; if len > 0 && String.get url (len - 1) == '/' then { function rec loop(l) { match l { | [] -> if *mod_rewrite then find_url_file (String.sub url 0 (len - 1)) true else None | f :: l -> match find_url_file(url + f) false { | None -> loop l | x -> x } } } loop ["index.html"; "index.htm"; "index.n"]; } else { var path = if len > 0 && String.get url 0 == '/' then String.sub url 1 (len - 1) else url; var path = *cur_path + path; if Sys.exists path && sys_is_file path then Some path else if recursive && *mod_rewrite then // if path like /path/to/file then lookup /path/to/file.n match find_url_file (url + ".n") false { | Some url -> Some url | None -> // lookup in subdirectory match List.rev String.split(url,"/") { | [] | [_] -> None | _ :: dir -> find_url_file (String.concat "/" List.rev(dir) + "/") true } } else None } } function log_exception(e) { Stack.dump IO.stderr Stack.exc(); IO.printf IO.stderr "Exception : %s\n" string(e); } function print_exception(e) { var stack = Stack.exc(); function format(s) { var s = String.concat "<" (String.split s "<"); var s = String.concat ">" (String.split s ">"); s }; Array.iter (function(s) { match s { | Stack.CFunction -> print "Called from a C function
" | Stack.Module m -> printf "Called from %s (no debug available)
" format(m) | Stack.Pos (file,line) -> printf "Called from %s line %d
" (format file,line) } }) stack var s = string(e); printf "Exception : %s" format(s); } function send_headers(c) { if !c.headers_sent then { c.headers_sent := true; IO.write c.out (sprintf "HTTP/1.1 %d %s\r\n" c.return_code); List.iter (function((name,v)) { IO.write c.out (sprintf "%s: %s\r\n" (name,v)); }) (List.rev c.headers); IO.write c.out "\r\n"; } } function headers_not_sent(c,s) { // should we send an object like mod_neko failure does ? if c.headers_sent then (neko "$throw")("Cannot set "+s+" : Headers already sent"); } function set_header(c,n,v) { headers_not_sent c n; c.headers := (n,v) :: List.filter (function((n2,_)) { n != n2 }) c.headers; } var cur_client : client option ref = &None; var cur_request : http_request option ref = &None; function client() { match *cur_client { | None -> assert() | Some c -> c } } function request() { match *cur_request { | None -> assert() | Some r -> r } } function do_print(v) { var c = client(); try { send_headers(c); var s = string(v); IO.write c.out s; } catch { Neko_error e when magic e == "std@socket_send" -> () } } function init_mod_neko() { // simulate a mod_neko environment var hmethods = Hashtbl.create(); function rec flatten(l) { match l { | [] -> neko "null" | (x,y) :: l -> var l = flatten l; neko "$array(x,y,l)" } } Sys.put_env "MOD_NEKO" "1"; var jit = Sys.get_env "MOD_NEKO_JIT" != None; neko "$loader.loadprim('std@enable_jit',1)(jit)"; function def(name : string,f) { Hashtbl.replace hmethods name magic(f); } function no_param(name,f) { def name neko("function() { f(null) }"); } no_param "get_cookies" (function() { flatten ( match header "Cookie" request().headers { | None -> [] | Some k -> var l = String.split k "; "; List.map (function(k) { match String.split k "=" { | [] | [_] -> (k,"") | k :: l -> (k,String.concat "=" l) } }) l } ) }); def "set_cookie" (function(name,val) { var c = client(); headers_not_sent c "Cookie"; c.headers := ("Set-Cookie",name+"="+val+";") :: c.headers; }); no_param "get_host_name" (function() { Net.host_to_string fst(Net.socket_host client().sock); }); no_param "get_client_ip" (function() { Net.host_to_string fst(Net.socket_peer client().sock); }); no_param "get_uri" (function() { var r = request(); fst r.url }); def "redirect" (function(url) { var c = client(); headers_not_sent c "Redirection"; set_header c "Location" url; c.return_code := (302, "Found"); }); def "set_return_code" (function(i) { var c = client(); headers_not_sent c "Return code"; c.return_code := (i, "OK"); }); def "set_header" (function(name,val) { var c = client(); headers_not_sent c name; set_header c name val; }); def "get_client_header" (function(name) { match header name request().headers { | None -> neko "null" | Some h -> h } }); no_param "get_client_headers" (function() { flatten request().headers }); no_param "get_params_string" (function() { snd request().url }); no_param "get_post_data" (function() { match request().post_data { | None -> neko "null" | Some d -> d } }); no_param "get_params" (function() { flatten request().params }); no_param "cgi_get_cwd" (function() { *cur_path }); def "cgi_set_main" (function(f) { client().main := (if f == neko "null" then None else Some f); }); no_param "cgi_flush" (function() { IO.flush client().out; }); def "parse_multipart_data" (function(part,data) { if request().ctype == Some "multipart/form-data" then (neko "$throw")("parse_multipart_data not implemented"); }); no_param "get_http_method" (function() { match request().method { | MethodGet -> "GET" | MethodPost -> "POST" | MethodCustom r -> r } }); def "log_message" (function (s) { IO.printf IO.stderr "[log] %s\n" s; }); function resolve_method(f:string) { try { Hashtbl.find hmethods f } catch { Not_found -> neko "null" } } var loader = neko "{ args => $array(), path => $loader.path, cache => $loader.cache, loadmodule => function(name,l) { $loader.cache = this.cache; $loader.loadmodule(name,l); }, loadprim => function(prim,nargs) { var l = $ssize(prim); if l > 9 && $ssub(prim,0,9) == 'mod_neko@' { prim = $ssub(prim,9,l-9); var f = resolve_method(prim); if( f == null ) $throw('Unknown mod_neko primitive : '+prim); if( $nargs(f) != nargs ) $throw('Invalid number of arguments for '+prim); return f; } return $loader.loadprim(prim,nargs); } }"; var redirect = neko "$loader.loadprim('std@print_redirect',1)"; var old_cache = neko "$new($loader.cache)"; function(c,r,file) { cur_client := Some c; cur_request := Some r; var main_fun = try { var f = Hashtbl.find module_cache file; c.main := Some f; f } catch { Not_found -> neko "null" }; try { redirect(do_print); if main_fun == neko "null" then neko "loader.loadmodule(file,loader)" else neko "main_fun()"; redirect(neko "null"); } catch { e -> log_exception(e); // stderr try { print_exception(e) } catch { e -> () }; // on screen redirect(neko "null"); } if !c.headers_sent then do_print " "; match c.main { | None -> neko " $loader.cache = $new(old_cache); loader.cache = $loader.cache; "; | Some f -> Hashtbl.add module_cache file f; } } } var mod_neko = init_mod_neko(); function config(c,r) { try { var dir = List.assoc "path" r.params; var old = Sys.get_cwd(); try { Sys.set_cwd dir; cur_path := Sys.get_cwd(); Sys.set_cwd old; } catch { e -> log_exception e } } catch { Not_found -> () } do_print page_config() } function client_msg(c) { var r = parse_http_request c; cur_client := Some c; if r.res == "/server:config" then config(c,r) else match find_url_file r.res true { | None -> c.return_code := (404,"Not Found"); do_print page_404(r.res); | Some file -> var ext = String.lowercase (Sys.extension file); if ext == "n" then { log "Request %s [%s]" (r.res, match r.params { | [] -> "" | l -> "\n " + (String.concat "\n " (List.map (function((p,v)) { p + " => "+ v }) l)) + "\n" }); mod_neko c r file } else { // directly send the file content IO.write c.out "HTTP/1.1 200 OK\r\n"; var ctype = try { List.assoc ext mime } catch { Not_found -> "unknown/unknown" }; var file_size : int = neko "$loader.loadprim('std@sys_stat',1)(file).size"; IO.write c.out ("Content-Type: " + ctype + "\r\n"); IO.write c.out ("Content-Length: " + file_size + "\r\n"); IO.write c.out "\r\n"; var fin = IO.read_file file true; var bufsize = 100000; var n = &(file_size / bufsize); try { while *n > 0 { IO.write c.out IO.read(fin,bufsize); n := *n - 1; } IO.write c.out IO.read(fin,file_size % bufsize); } catch { e -> IO.close_in fin; throw e } IO.close_in fin } } } function client_msg_safe(c) { try { client_msg(c); } catch { | Invalid_char -> printf "Invalid char received\n" (); | IO.Eof -> printf "Connection aborted\n" (); | Neko_error e when Reflect.value e == Reflect.VString "std@socket_send" -> printf "Sending file aborted\n" (); } Net.socket_close c.sock; neko "$loader.loadprim('std@run_gc',1)(true)"; false } function init() { var head = "Neko Web Server v1.0 - (c)2005-2017 Haxe Foundation"; var port = &2000; var host = &"localhost"; var decl = [ ("-p", Args.Int (function(n) { port := n }) , " : change server port"); ("-h", Args.String (function(h) { host := h }) , " : change server host"); ("-d", Args.String (function(d) { var old = Sys.get_cwd(); Sys.set_cwd d; cur_path := Sys.get_cwd(); Sys.set_cwd old; }), " : change the server base directory"); ("-log", Args.String (function(s) { file_log := Some (IO.write_file s true) }), " : set log file"); ("-rewrite", Args.Void (function() { mod_rewrite := true }), ": activate pseudo mod-rewrite for smart urls"); ]; Args.parse head decl (function(f) { throw Args.Invalid }); log "Starting Neko Server on %s:%d" (*host,*port); Net.start_server Net.host_resolve(*host) (*port) init_client client_msg_safe; } neko-2-2-0/src/tools/makedoc.neko000066400000000000000000000035131321613172000166530ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ readdir = $loader.loadprim("std@sys_read_dir",1); command = $loader.loadprim("std@sys_command",1); exec = function(cmd) { $print(cmd,"\n"); var ecode = command(cmd); if( ecode != 0 ) $throw("Error "+ecode+" : aborted"); } makedoc = function(file) { exec("nekoc -o ../www/libs -doc ../"+file); } files = $array( "vm/builtins.c", ); var i = 0; var l = $asize(files); while i < l { makedoc(files[i]); i = i + 1; } var libs = readdir("../libs"); while( libs != null ) { var l = libs[0]; var k = try readdir("../libs/"+l) catch _ { null }; if( l == "mod_tora" ) k = null; while( k != null ) { var f = k[0]; var len = $ssize(f); if( $ssub(f,len-2,2) == ".c" ) makedoc("libs/"+l+"/"+f); k = k[1]; } libs = libs[1]; } neko-2-2-0/src/tools/mod_neko_config.neko000066400000000000000000000064451321613172000203770ustar00rootroot00000000000000begin = " Mod_Neko Configuration

Mod_neko Configuration

"; end = "

Home

"; var params = $loader.loadprim("mod_neko@get_params",0)(); var get_config = $loader.loadprim("mod_neko@cgi_get_config",0); var memory = $loader.loadprim("std@mem_size",1); var execCommand = $loader.loadprim("mod_neko@cgi_command",1); var setHeader = $loader.loadprim("mod_neko@set_header",2); getParam = function(name) { var p = params; while( p != null ) { if( p[0] == name ) return p[1]; p = p[2]; } return null; } error = function(e) { $throw(e); } message = function(msg) { $print(begin); $print("

",msg,"

"); $print(end); } displayObject = function(obj,edit) { var fl = $objfields(obj); var i = 0; $print("
    "); while( i < $asize(fl) ) { var name = $field(fl[i]); var data = $objget(obj,fl[i]); $print("
  • ",name," "); if( edit && $typeof(data) == $tbool ) $print(""); else $print(": ",data); $print("
  • "); i += 1; } $print("
"); } displayVars = function() { var gc = $loader.loadprim("std@gc_stats",0)(); var now = $loader.loadprim("std@date_now",0)(); displayObject({ date => $loader.loadprim("std@date_format",2)(now,null), pid => $loader.loadprim("std@sys_get_pid",0)(), gc_heap => gc.heap, gc_free => gc.free, gc_free_size => $int(gc.free * 100.0 / gc.heap) + "%", },false); } displayConfig = function(cfg) { $print("
"); displayObject(cfg,true); $print(""); $print(""); } displayCache = function(cache) { $print("
Loader path : "+path+"
Server directory :
 
"); $print(""); while( cache != null ) { $print(""); cache = cache[3]; } $print("
FileMemHits
",cache[0],"",memory(cache[1]),"",cache[2],"
"); } displayMenu = function() { $print(begin); $print("

Vars

"); displayVars(); $print("

Config

"); displayConfig(get_config()); $print("

Cache

"); displayCache(execCommand("cache")); $print("

Command

"); $print(""); $print(end); } displayStatistics = function(stats) { $print(begin); $print("

Statistics

"); $print(""); $print(""); while( stats != null ) { $print(""); stats = stats[5]; } $print("
NameTotal TimeInner TimeHitsErrors
",stats[0],"",stats[1],"",stats[2],"",stats[3],"",stats[4],"
"); $print(end); } setConfig = function() { var cfg = get_config(); var fl = $objfields(cfg); var i = 0; while( i < $asize(fl) ) { var name = $field(fl[i]); var data = $objget(cfg,fl[i]); var value = getParam(name); if( $typeof(data) == $tbool ) $objset(cfg,fl[i],value != null); i += 1; } $loader.loadprim("mod_neko@cgi_set_config",1)(cfg); message("Configuration Updated"); } var cmd = getParam("command"); switch( cmd ) { "stats" => displayStatistics(execCommand("stats")) "setconfig" => setConfig() default => { if( cmd != null && cmd != "" ) error("Unknown command "+cmd); displayMenu() } } neko-2-2-0/src/tools/nekoboot.neko000066400000000000000000000217511321613172000170740ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ // primitives var c_src = "#include #include #include #include \"neko_vm.h\" #include \"neko_elf.h\" #ifdef NEKO_WINDOWS # include #else # include #endif #ifdef NEKO_MAC # include # include #endif #ifdef NEKO_BSD # include # include #endif #ifdef NEKO_POSIX # include #endif #define default_loader neko_default_loader unsigned char program[] = %s; unsigned int program_len = %d; unsigned int program_pos = 0; static void report( neko_vm *vm, value exc, int isexc ) { int i; buffer b = alloc_buffer(NULL); value st = neko_exc_stack(vm); for(i=0;i available) mlen = available; memcpy(val_string(str)+val_int(pos), prog, mlen); program_pos += mlen; return alloc_int(mlen); } /* C functions corresponding to the following Neko code : module_read = $loader.loadprim(\"std@module_read\",2); module_exec = $loader.loadprim(\"std@module_exec\",1); module_val = module_read(read_bytecode,$loader); module_exec(module_val); */ int neko_execute_self( neko_vm *vm, value mload ) { value args[] = { alloc_string(\"std@module_read\"), alloc_int(2) }; value args2[] = { alloc_string(\"std@module_exec\"), alloc_int(1) }; value args3[] = { alloc_function(read_bytecode,3,\"boot_read_bytecode\"), mload }; value exc = NULL; value module_read, module_exec, module_val; module_read = val_callEx(mload,val_field(mload,val_id(\"loadprim\")),args,2,&exc); if( exc != NULL ) { report(vm,exc,1); return 1; } module_exec = val_callEx(mload,val_field(mload,val_id(\"loadprim\")),args2,2,&exc); if( exc != NULL ) { report(vm,exc,1); return 1; } module_val = val_callEx(val_null,module_read,args3,2,&exc); if( exc != NULL ) { report(vm,exc,1); return 1; } alloc_field(val_field(mload,val_id(\"cache\")),val_id(\"_self\"),module_val); val_callEx(val_null,module_exec,&module_val,1,&exc); if( exc != NULL ) { report(vm,exc,1); return 1; } return 0; } #ifdef NEKO_POSIX static void handle_signal( int signal ) { if( signal == SIGPIPE ) val_throw(alloc_string(\"Broken pipe\")); else val_throw(alloc_string(\"Segmentation fault\")); } #endif int main( int argc, char *argv[] ) { neko_vm *vm; value mload; int r; neko_global_init(); vm = neko_vm_alloc(NULL); neko_vm_select(vm); mload = default_loader(argv+1,argc-1); r = neko_execute_self(vm,mload); if( mload != NULL && val_field(mload,val_id(\"dump_prof\")) != val_null ) val_ocall0(mload,val_id(\"dump_prof\")); vm = NULL; mload = NULL; neko_vm_select(NULL); neko_global_free(); return r; }"; var elf_update_section_header = $loader.loadprim("std@elf_update_section_header_for_bytecode",3); var file_contents = $loader.loadprim("std@file_contents",1); var file_open = $loader.loadprim("std@file_open",2); var file_write = $loader.loadprim("std@file_write",4); var file_write_char = $loader.loadprim("std@file_write_char",2); var file_close = $loader.loadprim("std@file_close",1); var command = $loader.loadprim("std@sys_command",1); var system = $loader.loadprim("std@sys_string",0)(); var cwd = $loader.loadprim("std@get_cwd",0)(); var get_env = $loader.loadprim("std@get_env",1); var string_split = $loader.loadprim("std@string_split",2); var buffer_new = $loader.loadprim("std@buffer_new",0); var buffer_add = $loader.loadprim("std@buffer_add",2); var buffer_string = $loader.loadprim("std@buffer_string",1); var sprintf = $loader.loadprim("std@sprintf",2); // find a substring from then end var find = function(str,sub,pos) { var l1 = $ssize(str); var l2 = $ssize(sub); var i = l1 - pos; while( i >= 0 ) { if( $ssub(str,i,l2) == sub ) return i; i -= 1; } return null; } // find a file in a path var find_exe_in_path = function(path,file) { while( path != null ) { try { var p = path[0]; var l = $ssize(p); if ( l > 0 ) { // add trailing slash var last = $sget(p,l-1); if ( last != "/" || last != "\\" ) p = p + "/"; } var s = file_contents(p + file); if( $sget(s,0) == 35 ) // '#' $throw("Is a script"); return s; } catch e { path = path[1]; } } $throw("The bootable executable file was not found : "+file); } var find_exe_in_paths = function(paths,file) { var i = 0; var len = $asize(paths); while( i < len ) { try { return find_exe_in_path(paths[i],file); } catch e { i ++= 1; } } $throw("The bootable executable file was not found : "+file); } // bytecode = first argument var args = $loader.args; if( args[0] == "-c" ) { var file = args[1]; var bytecode = file_contents(file); var bytecode_len = $ssize(bytecode); var program_buf = buffer_new(); buffer_add(program_buf, "{"); var i = 0; while(true) { buffer_add(program_buf, $sget(bytecode, i)); i += 1; if (i < bytecode_len) { buffer_add(program_buf, ","); } else { break; } } buffer_add(program_buf, "}"); // write a C source that run the module using neko var c_name = if ($ssub(file, $ssize(file)-2, 2) == ".n") $ssub(file, 0, $ssize(file)-2) + ".c"; else file+".c"; var c_file = file_open(c_name,"wb"); c_src = sprintf(c_src, $array(buffer_string(program_buf), bytecode_len, "%s")); file_write(c_file, c_src, 0, $ssize(c_src)); file_close(c_file); } else { var exe_ext = switch system { "Windows" => ".exe" default => "" }; var boot_exe = "neko" + exe_ext; if( args[0] == "-b" ) { boot_exe = args[1]; args = $asub(args,2,$asize(args)-2); } if( $asize(args) != 1 ) $throw("Need bytecode argument"); var file = args[0]; var bytecode = file_contents(file); // load boot binary var path_sep = switch system { "Windows" => ";" default => ":" } var path = string_split(get_env("PATH"), path_sep); var boot = find_exe_in_paths($array($array(cwd,null),$loader.path,path),boot_exe); var boot_size = $ssize(boot); var dot_pos = find(file,".",1); if( dot_pos != null ) file = $ssub(file,0,dot_pos); // create executable file : // this is the content of boot.bin where is appended // the neko bytecode followed by 'NEKO' and the original exe size var out_name = file+exe_ext; var out = file_open(out_name,"wb"); var bytecode_size = $ssize(bytecode); var pad_size = (4-(boot_size&0x3)) & 0x3; file_write(out,boot,0,boot_size); boot_size += pad_size; if( pad_size >= 3 ) file_write_char(out,0x00); if( pad_size >= 2 ) file_write_char(out,0x00); if( pad_size >= 1 ) file_write_char(out,0x00); file_write(out,bytecode,0,bytecode_size) file_write(out,"NEKO",0,4); file_write_char(out,boot_size & 0xFF); file_write_char(out,(boot_size >> 8) & 0xFF); file_write_char(out,(boot_size >> 16) & 0xFF); file_write_char(out,boot_size >>> 24); file_close(out); // set execution rights switch system { "Windows" => null default => command("chmod 755 "+out_name) } // Update ELF section header (on platforms where that is appropriate) to protect // binary's bytecode from being removed by the strip program var res = elf_update_section_header(out_name,boot_size,bytecode_size+8); if( res == 0 ) $print("Trouble updating elf section header; stripping binary may lead to problems!") } neko-2-2-0/src/tools/test.neko000066400000000000000000000001711321613172000162240ustar00rootroot00000000000000$print("The virtual machine is working !\n"); test = $loader.loadprim("std@test",0); test(); $print("Test successful\n");neko-2-2-0/vm/000077500000000000000000000000001321613172000130635ustar00rootroot00000000000000neko-2-2-0/vm/alloc.c000066400000000000000000000266201321613172000143270ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "neko.h" #include "objtable.h" #include "opcodes.h" #include "vm.h" #include "neko_mod.h" #include "neko_vm.h" #ifdef NEKO_POSIX # include #endif #ifdef NEKO_WINDOWS #ifdef NEKO_STANDALONE # define GC_NOT_DLL #else # define GC_DLL #endif # define GC_WIN32_THREADS #endif #define GC_THREADS #include "gc/gc.h" #ifndef GC_MALLOC # error Looks like libgc was not installed, please install it before compiling #else // activate to get debug informations about the GC // #define GC_LOG #define gc_alloc GC_MALLOC #define gc_alloc_private GC_MALLOC_ATOMIC #define gc_alloc_big(n) (((n) > 256) ? GC_MALLOC_IGNORE_OFF_PAGE(n) : GC_MALLOC(n)) #define gc_alloc_private_big(n) (((n) > 256) ? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n) : GC_MALLOC_ATOMIC(n)) #define gc_alloc_root GC_MALLOC_UNCOLLECTABLE #define gc_free_root GC_FREE typedef struct _klist { const char *name; vkind k; struct _klist *next; } kind_list; static int_val op_last = Last; static value *apply_string = NULL; int_val *callback_return = &op_last; value *neko_builtins = NULL; objtable *neko_fields = NULL; mt_lock *neko_fields_lock = NULL; mt_local *neko_vm_context = NULL; static val_type t_null = VAL_NULL; static val_type t_true = VAL_BOOL; static val_type t_false = VAL_BOOL; EXTERN value val_null = (value)&t_null; EXTERN value val_true = (value)&t_true; EXTERN value val_false = (value)&t_false; static varray empty_array = { VAL_ARRAY, NULL }; static vstring empty_string = { VAL_STRING, 0 }; static kind_list **kind_names = NULL; field id_compare; field id_string; field id_loader; field id_exports; field id_cache; field id_path; field id_loader_libs; field id_get, id_set; field id_add, id_radd, id_sub, id_rsub, id_mult, id_rmult, id_div, id_rdiv, id_mod, id_rmod; EXTERN field neko_id_module; #if defined (GC_LOG) && defined(NEKO_POSIX) static void handle_signal( int signal ) { // reset to default handler struct sigaction act; act.sa_sigaction = NULL; act.sa_handler = SIG_DFL; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGSEGV,&act,NULL); // print signal VM stack printf("**** SIGNAL %d CAUGHT ****\n",signal); neko_vm_dump_stack(neko_vm_current()); // signal again raise(signal); } #endif static void null_warn_proc( char *msg, int arg ) { # ifdef GC_LOG printf(msg,arg); if( strstr(msg,"very large block") ) neko_vm_dump_stack(neko_vm_current()); # endif } void neko_gc_init() { # ifndef NEKO_WINDOWS // we can't set this on windows with old GC since // it's already initialized through its own DllMain GC_all_interior_pointers = 0; # endif #if (GC_VERSION_MAJOR >= 7) && defined(NEKO_WINDOWS) GC_all_interior_pointers = 0; # ifndef NEKO_STANDALONE GC_use_DllMain(); // needed to auto-detect threads created by Apache # endif #endif GC_java_finalization = 1; GC_init(); GC_set_warn_proc((GC_warn_proc)(void*)null_warn_proc); GC_no_dls = 1; #ifdef LOW_MEM GC_dont_expand = 1; #endif GC_clear_roots(); #if defined(GC_LOG) && defined(NEKO_POSIX) { struct sigaction act; act.sa_sigaction = NULL; act.sa_handler = handle_signal; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGSEGV,&act,NULL); } #endif } EXTERN void neko_gc_loop() { GC_collect_a_little(); } EXTERN void neko_gc_major() { GC_gcollect(); } EXTERN void neko_gc_stats( int *heap, int *free ) { *heap = (int)GC_get_heap_size(); *free = (int)GC_get_free_bytes(); } EXTERN char *alloc( unsigned int nbytes ) { return (char*)gc_alloc_big(nbytes); } EXTERN char *alloc_private( unsigned int nbytes ) { return (char*)gc_alloc_private_big(nbytes); } EXTERN value alloc_empty_string( unsigned int size ) { vstring *s; if( size == 0 ) return (value)&empty_string; if( size > max_string_size ) failure("max_string_size reached"); s = (vstring*)gc_alloc_private_big(size+sizeof(vstring)); if( s == NULL ) failure("out of memory"); s->t = VAL_STRING | (size << NEKO_TAG_BITS); (&s->c)[size] = 0; return (value)s; } EXTERN value alloc_string( const char *str ) { if( str == NULL ) return val_null; return copy_string(str,strlen(str)); } EXTERN value alloc_float( tfloat f ) { vfloat *v = (vfloat*)gc_alloc_private(sizeof(vfloat)); v->t = VAL_FLOAT; v->f = f; return (value)v; } EXTERN value alloc_int32( int i ) { vint32 *v = (vint32*)gc_alloc_private(sizeof(vint32)); v->t = VAL_INT32; v->i = i; return (value)v; } EXTERN value alloc_array( unsigned int n ) { value v; if( n == 0 ) return (value)(void*)&empty_array; if( n > max_array_size ) failure("max_array_size reached"); v = (value)gc_alloc_big(sizeof(varray)+(n - 1)*sizeof(value)); if( v == NULL ) failure("out of memory"); v->t = VAL_ARRAY | (n << NEKO_TAG_BITS); return v; } EXTERN value alloc_abstract( vkind k, void *data ) { vabstract *v = (vabstract*)gc_alloc(sizeof(vabstract)); v->t = VAL_ABSTRACT; v->kind = k; v->data = data; return (value)v; } EXTERN value alloc_function( void *c_prim, unsigned int nargs, const char *name ) { vfunction *v; if( c_prim == NULL || ((int)nargs < 0 && nargs != VAR_ARGS) ) failure("alloc_function"); v = (vfunction*)gc_alloc(sizeof(vfunction)); v->t = VAL_PRIMITIVE; v->addr = c_prim; v->nargs = nargs; v->env = alloc_array(0); v->module = alloc_string(name); return (value)v; } value neko_alloc_module_function( void *m, int_val pos, int nargs ) { vfunction *v; if( nargs < 0 && nargs != VAR_ARGS ) failure("alloc_module_function"); v = (vfunction*)gc_alloc(sizeof(vfunction)); v->t = VAL_FUNCTION; v->addr = (void*)pos; v->nargs = nargs; v->env = alloc_array(0); v->module = m; return (value)v; } static value apply1( value p1 ) { value env = NEKO_VM()->env; value *a = val_array_ptr(env) + 1; int n = val_array_size(env) - 1; a[n-1] = p1; return val_callN(a[-1],a,n); } static value apply2( value p1, value p2 ) { value env = NEKO_VM()->env; value *a = val_array_ptr(env) + 1; int n = val_array_size(env) - 1; a[n-2] = p1; a[n-1] = p2; return val_callN(a[-1],a,n); } static value apply3( value p1, value p2, value p3 ) { value env = NEKO_VM()->env; value *a = val_array_ptr(env) + 1; int n = val_array_size(env) - 1; a[n-3] = p1; a[n-2] = p2; a[n-1] = p3; return val_callN(a[-1],a,n); } static value apply4( value p1, value p2, value p3, value p4 ) { value env = NEKO_VM()->env; value *a = val_array_ptr(env) + 1; int n = val_array_size(env) - 1; a[n-4] = p1; a[n-3] = p2; a[n-2] = p3; a[n-1] = p4; return val_callN(a[-1],a,n); } static value apply5( value p1, value p2, value p3, value p4, value p5 ) { value env = NEKO_VM()->env; value *a = val_array_ptr(env) + 1; int n = val_array_size(env) - 1; a[n-4] = p1; a[n-3] = p2; a[n-2] = p3; a[n-1] = p4; a[n-1] = p5; return val_callN(a[-1],a,n); } value neko_alloc_apply( int nargs, value env ) { vfunction *v = (vfunction*)gc_alloc(sizeof(vfunction)); v->t = VAL_PRIMITIVE; switch( nargs ) { case 1: v->addr = apply1; break; case 2: v->addr = apply2; break; case 3: v->addr = apply3; break; case 4: v->addr = apply4; break; case 5: v->addr = apply5; break; default: failure("Too many apply arguments"); break; } v->nargs = nargs; v->env = env; v->module = *apply_string; return (value)v; } EXTERN value alloc_object( value cpy ) { vobject *v; if( cpy != NULL && !val_is_null(cpy) && !val_is_object(cpy) ) val_throw(alloc_string("$new")); // 'new' opcode simulate $new v = (vobject*)gc_alloc(sizeof(vobject)); v->t = VAL_OBJECT; if( cpy == NULL || val_is_null(cpy) ) { v->proto = NULL; otable_init(&v->table); } else { v->proto = ((vobject*)cpy)->proto; otable_copy(&((vobject*)cpy)->table,&v->table); } return (value)v; } EXTERN value copy_string( const char *str, int_val strlen ) { value v = alloc_empty_string((unsigned int)strlen); char *c = (char*)val_string(v); memcpy(c,str,strlen); return v; } EXTERN void alloc_field( value obj, field f, value v ) { otable_replace(&((vobject*)obj)->table,f,v); } static void __on_finalize( value v, void *f ) { ((finalizer)f)(v); } EXTERN void val_gc(value v, finalizer f ) { if( !val_is_abstract(v) ) failure("val_gc"); if( f ) GC_REGISTER_FINALIZER_NO_ORDER(v,(GC_finalization_proc)__on_finalize,f,0,0); else GC_REGISTER_FINALIZER_NO_ORDER(v,NULL,NULL,0,0); } EXTERN value *alloc_root( unsigned int nvals ) { return (value*)gc_alloc_root(nvals*sizeof(value)); } EXTERN void free_root(value *v) { gc_free_root(v); } extern void neko_init_builtins(); extern void neko_init_fields(); extern void neko_init_jit(); extern void neko_free_jit(); #define INIT_ID(x) id_##x = val_id("__" #x) EXTERN void neko_global_init() { # ifdef NEKO_DIRECT_THREADED op_last = neko_get_ttable()[Last]; # endif empty_array.ptr = val_null; neko_gc_init(); neko_vm_context = alloc_local(); neko_fields_lock = alloc_lock(); neko_fields = (objtable*)alloc_root((NEKO_FIELDS_MASK+1) * sizeof(struct _objtable) / sizeof(value)); { int i; for(i=0;i<=NEKO_FIELDS_MASK;i++) otable_init(&neko_fields[i]); } neko_init_builtins(); kind_names = (kind_list**)alloc_root(1); *kind_names = NULL; id_loader = val_id("loader"); id_exports = val_id("exports"); id_cache = val_id("cache"); id_path = val_id("path"); id_loader_libs = val_id("__libs"); neko_id_module = val_id("__module"); INIT_ID(compare); INIT_ID(string); INIT_ID(add); INIT_ID(radd); INIT_ID(sub); INIT_ID(rsub); INIT_ID(mult); INIT_ID(rmult); INIT_ID(div); INIT_ID(rdiv); INIT_ID(mod); INIT_ID(rmod); INIT_ID(get); INIT_ID(set); apply_string = alloc_root(1); *apply_string = alloc_string("apply"); neko_init_jit(); } EXTERN void neko_global_free() { neko_free_jit(); free_root((value*)kind_names); free_root(apply_string); free_root(neko_builtins); free_root((value*)neko_fields); apply_string = NULL; free_local(neko_vm_context); free_lock(neko_fields_lock); neko_gc_major(); } EXTERN void neko_set_stack_base( void *s ) { // deprecated } EXTERN vkind kind_lookup( const char *name ) { kind_list *l = *kind_names; while( l != NULL ) { if( strcmp(l->name,name) == 0 ) return l->k; l = l->next; } return NULL; } EXTERN void kind_share( vkind *k, const char *name ) { kind_list *l = *kind_names; while( l != NULL ) { if( strcmp(l->name,name) == 0 ) { *k = l->k; return; } l = l->next; } l = (kind_list*)alloc(sizeof(kind_list)); l->k = *k; l->name = name; l->next = *kind_names; *kind_names = l; } #endif /* ************************************************************************ */ neko-2-2-0/vm/builtins.c000066400000000000000000001121421321613172000150610ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include "neko.h" #include "objtable.h" #include "vm.h" #ifdef NEKO_MINGW # undef setjmp # define setjmp _setjmp #endif extern value *neko_builtins; DEFINE_KIND(neko_k_kind); DEFINE_KIND(k_old_int32); /**

Builtins

Builtins are basic operations that can be optimized by the Neko compiler.

**/ /**

Array Builtins

**/ /** $array : any* -> array Create an array from a list of values **/ static value builtin_array( value *args, int nargs ) { value a = alloc_array(nargs); int i; for(i=0;i array Create an array of size [n] **/ static value builtin_amake( value size ) { value a; int i,s; val_check(size,int); s = val_int(size); a = alloc_array(s); for(i=0;i array Make a copy of an array **/ static value builtin_acopy( value a ) { int i; value a2; val_check(a,array); a2 = alloc_array(val_array_size(a)); for(i=0;i int Return the size of an array **/ static value builtin_asize( value a ) { val_check(a,array); return alloc_int( val_array_size(a) ); } /** $asub : array -> p:int -> l:int -> array Return [l] elements starting at position [p] of an array. An error occurs if out of array bounds. **/ static value builtin_asub( value a, value p, value l ) { value a2; int i; int pp, ll; val_check(a,array); val_check(p,int); val_check(l,int); pp = val_int(p); ll = val_int(l); if( pp < 0 || ll < 0 || pp+ll < 0 || pp+ll > val_array_size(a) ) neko_error(); a2 = alloc_array(ll); for(i=0;i dst_pos:int -> src:array -> src_pos:int -> len:int -> void Copy [len] elements from [src_pos] of [src] to [dst_pos] of [dst]. An error occurs if out of arrays bounds. **/ static value builtin_ablit( value dst, value dp, value src, value sp, value l ) { int dpp, spp, ll; val_check(dst,array); val_check(dp,int); val_check(src,array); val_check(sp,int); val_check(l,int); dpp = val_int(dp); spp = val_int(sp); ll = val_int(l); if( dpp < 0 || spp < 0 || ll < 0 || dpp + ll < 0 || spp + ll < 0 || dpp + ll > val_array_size(dst) || spp + ll > val_array_size(src) ) neko_error(); memmove(val_array_ptr(dst)+dpp,val_array_ptr(src)+spp,ll * sizeof(value)); return val_null; } /** $aconcat : array array -> array Build a single array from several ones. **/ static value builtin_aconcat( value arrs ) { int tot = 0; int len; int i; value all; val_check(arrs,array); len = val_array_size(arrs); for(i=0;i

String Builtins

**/ /** $string : any -> string Convert any value to a string. This will make a copy of string. **/ static value builtin_string( value v ) { buffer b = alloc_buffer(NULL); val_buffer(b,v); return buffer_to_string(b); } /** $smake : n:int -> string Return an uninitialized string of size [n] **/ static value builtin_smake( value l ) { value v; val_check(l,int); v = alloc_empty_string( val_int(l) ); memset(val_string(v),0,val_int(l)); return v; } /** $ssize : string -> int Return the size of a string **/ static value builtin_ssize( value s ) { val_check(s,string); return alloc_int(val_strlen(s)); } /** $scopy : string -> string Make a copy of a string **/ static value builtin_scopy( value s ) { val_check(s,string); return copy_string( val_string(s), val_strlen(s) ); } /** $ssub : string -> p:int -> l:int -> string Return [l] chars starting at position [p] of a string. An error occurs if out of string bounds. **/ static value builtin_ssub( value s, value p, value l ) { int pp , ll; val_check(s,string); val_check(p,int); val_check(l,int); pp = val_int(p); ll = val_int(l); if( pp < 0 || ll < 0 || pp + ll < 0 || pp + ll > val_strlen(s) ) neko_error(); return copy_string( val_string(s) + pp , ll ); } /** $sget : string -> n:int -> int? Return the [n]th char of a string or [null] if out of bounds **/ static value builtin_sget( value s, value p ) { int pp; val_check(s,string); val_check(p,int); pp = val_int(p); if( pp < 0 || pp >= val_strlen(s) ) return val_null; return alloc_int( (unsigned char)(val_string(s)[pp]) ); } /** $sset : string -> n:int -> c:anyint -> int? Set the [n]th char of a string to ([c] & 255). Returns the char set or [null] if out of bounds. **/ static value builtin_sset( value s, value p, value c ) { int pp; unsigned char cc; val_check(s,string); val_check(p,int); val_check(c,any_int); pp = val_int(p); if( pp < 0 || pp >= val_strlen(s) ) return val_null; cc = (unsigned char)val_any_int(c); val_string(s)[pp] = (char)cc; return alloc_int(cc); } // if our endian value is null, we will use hardware endianness #ifdef NEKO_BIG_ENDIAN # define TO_BE(v) v == val_false #else # define TO_BE(v) v == val_true #endif # define LTB32(bits) bits = (bits >> 24) | ((bits >> 8) & 0xFF00) | ((bits << 8) & 0xFF0000) | (bits << 24) /** $sget16 : string -> n:int -> bigEndian:bool -> int? Return the 16 bit unsigned value at position [n] or [null] if out of bounds **/ static value builtin_sget16( value s, value p, value endian ) { int pp; unsigned short v; val_check(s,string); val_check(p,int); pp = val_int(p); if( pp < 0 || pp+2 > val_strlen(s) ) return val_null; v = *(unsigned short*)(val_string(s)+pp); if( TO_BE(endian) ) v = ((v&0xFF) << 8) | (v>>8); return alloc_int(v); } /** $sset16 : s:string -> n:int -> val:anyint -> bigEndian:bool -> void Set the 16 bit unsigned value at position [n] of string [s] **/ static value builtin_sset16( value s, value p, value val, value endian ) { int pp, v; val_check(s,string); val_check(p,int); val_check(val,any_int); pp = val_int(p); if( pp < 0 || pp+2 > val_strlen(s) ) neko_error(); v = val_any_int(val); if( TO_BE(endian) ) v = ((v&0xFF) << 8) | (v>>8); *(unsigned short*)(val_string(s)+pp) = v; return val_null; } /** $sget32 : string -> n:int -> bigEndian:bool -> anyint? Return the 32 bit int value at position [n] or [null] if out of bounds **/ static value builtin_sget32( value s, value p, value endian ) { int pp; unsigned int v; val_check(s,string); val_check(p,int); pp = val_int(p); if( pp < 0 || pp+4 > val_strlen(s) ) return val_null; v = *(unsigned int*)(val_string(s)+pp); if( TO_BE(endian) ) LTB32(v); return alloc_best_int(v); } /** $sset32 : s:string -> n:int -> val:anyint -> bigEndian:bool -> void Set the 32 bit unsigned value at position [n] of string [s] **/ static value builtin_sset32( value s, value p, value val, value endian ) { int pp, v; val_check(s,string); val_check(p,int); val_check(val,int); pp = val_int(p); if( pp < 0 || pp+4 > val_strlen(s) ) neko_error(); v = val_int(val); if( TO_BE(endian) ) LTB32(v); *(unsigned int*)(val_string(s)+pp) = v; return val_null; } /** $sgetf : string -> n:int -> bigEndian:bool -> float? Return the single precision float value at position [n] or [null] if out of bounds **/ static value builtin_sgetf( value s, value p, value endian ) { int pp; float f; val_check(s,string); val_check(p,int); pp = val_int(p); if( pp < 0 || pp+4 > val_strlen(s) ) return val_null; if( TO_BE(endian) ) { unsigned int bits; bits = *(unsigned int*)(val_string(s)+pp); LTB32(bits); f = *(float*)(&bits); } else f = *(float*)(val_string(s)+pp); return alloc_float(f); } /** $ssetf : s:string -> n:int -> val:float -> bigEndian:bool -> void Set the single precision float value at position [n] of string [s] **/ static value builtin_ssetf( value s, value p, value val, value endian ) { int pp; float f; val_check(s,string); val_check(p,int); val_check(val,float); pp = val_int(p); if( pp < 0 || pp+4 > val_strlen(s) ) neko_error(); f = (float)val_float(val); if( TO_BE(endian) ) { unsigned int bits = *(unsigned int *)&f; LTB32(bits); *(unsigned int*)(val_string(s)+pp) = bits; } else *(float*)(val_string(s)+pp) = f; return val_null; } /** $sgetd : string -> n:int -> float? Return the double precision float value at position [n] or [null] if out of bounds **/ static value builtin_sgetd( value s, value p, value endian ) { int pp; double f; val_check(s,string); val_check(p,int); pp = val_int(p); if( pp < 0 || pp+8 > val_strlen(s) ) return val_null; if( TO_BE(endian) ) { const unsigned char *p = (unsigned char*)(val_string(s) + pp); union { unsigned char bytes[8]; double f; } s; s.bytes[0] = p[7]; s.bytes[1] = p[6]; s.bytes[2] = p[5]; s.bytes[3] = p[4]; s.bytes[4] = p[3]; s.bytes[5] = p[2]; s.bytes[6] = p[1]; s.bytes[7] = p[0]; f = s.f; } else f = *(double*)(val_string(s)+pp); return alloc_float(f); } /** $ssetd : s:string -> n:int -> val:float -> bigEndian:bool -> void Set the double precision float value at position [n] of string [s] **/ static value builtin_ssetd( value s, value p, value val, value endian ) { int pp; double f; val_check(s,string); val_check(p,int); val_check(val,float); pp = val_int(p); if( pp < 0 || pp+8 > val_strlen(s) ) neko_error(); f = (double)val_float(val); if( TO_BE(endian) ) { unsigned char *p = (unsigned char*)(val_string(s) + pp); union { unsigned char bytes[8]; double f; } s; s.f = f; *p = s.bytes[7]; p++; *p = s.bytes[6]; p++; *p = s.bytes[5]; p++; *p = s.bytes[4]; p++; *p = s.bytes[3]; p++; *p = s.bytes[2]; p++; *p = s.bytes[1]; p++; *p = s.bytes[0]; } else *(double*)(val_string(s)+pp) = f; return val_null; } /** // $itof : anyint -> float Convert the low endian bytes integer to the corresponding float value **/ static value builtin_itof( value v, value endian ) { int bits; float f; val_check(v,any_int); bits = val_any_int(v); if( TO_BE(endian) ) LTB32(bits); f = *(float*)&bits; return alloc_float(f); } /** $ftod : float -> anyint Returns the binary integer representation of the float value **/ static value builtin_ftoi( value v, value endian ) { int bits; float f; val_check(v,float); f = (float)val_float(v); bits = *(int *)&f; if( TO_BE(endian) ) LTB32(bits); return alloc_best_int(bits); } /** $itod : low:anyint -> high:anyint -> float Convert the low endian bytes integers to the corresponding double value **/ static value builtin_itod( value low, value high, value endian ) { union { unsigned int i[2]; double d; } s; val_check(low,any_int); val_check(high,any_int) if( TO_BE(endian) ) { unsigned int bits; bits = val_any_int(low); LTB32(bits); s.i[1] = bits; bits = val_any_int(high); LTB32(bits); s.i[0] = bits; } else { s.i[0] = val_any_int(low); s.i[1] = val_any_int(high); } return alloc_float(s.d); } /** $dtoi : float -> anyint array -> void Save the low endian bytes representation of the double value into the array as two any int **/ static value builtin_dtoi( value v, value out, value endian ) { union { unsigned int i[2]; double d; } s; val_check(v,float); val_check(out,array); if( val_array_size(out) < 2 ) neko_error(); s.d = val_float(v); if( TO_BE(endian) ) { unsigned int bits; bits = s.i[0]; LTB32(bits); val_array_ptr(out)[1] = alloc_best_int(bits); bits = s.i[1]; LTB32(bits); val_array_ptr(out)[0] = alloc_best_int(bits); } else { val_array_ptr(out)[0] = alloc_best_int(s.i[0]); val_array_ptr(out)[1] = alloc_best_int(s.i[1]); } return val_null; } /** $isbigendian : void -> bool Tells if we are on a big endian CPU or not. **/ static value builtin_isbigendian() { #ifdef NEKO_BIG_ENDIAN return val_true; #else return val_false; #endif } /** $sblit : dst:string -> dst_pos:int -> src:string -> src_pos:int -> len:int -> void Copy [len] chars from [src_pos] of [src] to [dst_pos] of [dst]. An error occurs if out of strings bounds. **/ static value builtin_sblit( value dst, value dp, value src, value sp, value l ) { int dpp, spp, ll; val_check(dst,string); val_check(dp,int); val_check(src,string); val_check(sp,int); val_check(l,int); dpp = val_int(dp); spp = val_int(sp); ll = val_int(l); if( dpp < 0 || spp < 0 || ll < 0 || dpp + ll < 0 || spp + ll < 0 || dpp + ll > val_strlen(dst) || spp + ll > val_strlen(src) ) neko_error(); memmove(val_string(dst)+dpp,val_string(src)+spp,ll); return val_null; } /** $sfind : src:string -> pos:int -> pat:string -> int? Return the first position starting at [pos] in [src] where [pat] was found. Return null if not found. Error if [pos] is outside [src] bounds. **/ static value builtin_sfind( value src, value pos, value pat ) { int p, l, l2; const char *ptr; val_check(src,string); val_check(pos,int); val_check(pat,string); p = val_int(pos); l = val_strlen(src); l2 = val_strlen(pat); if( p < 0 || p >= l ) neko_error(); ptr = val_string(src) + p; while( l - p >= l2 ) { if( memcmp(ptr,val_string(pat),l2) == 0 ) return alloc_int(p); p++; ptr++; } return val_null; } /**

Object Builtins

**/ /** $new : object? -> object Return a copy of the object or a new object if [null] **/ static value builtin_new( value o ) { if( !val_is_null(o) && !val_is_object(o) ) neko_error(); return alloc_object(o); } /** $objget : o:any -> f:int -> any Return the field [f] of [o] or [null] if doesn't exists or [o] is not an object **/ static value builtin_objget( value o, value f ) { if( !val_is_object(o) ) return val_null; // keep dot-access semantics val_check(f,int); return val_field(o,val_int(f)); } /** $objset : o:any -> f:int -> v:any -> any Set the field [f] of [o] to [v] and return [v] if [o] is an object or [null] if not **/ static value builtin_objset( value o, value f, value v ) { if( !val_is_object(o) ) return val_null; // keep dot-access semantics val_check(f,int); alloc_field(o,val_int(f),v); return v; } /** $objcall : o:any -> f:int -> args:array -> any Call the field [f] of [o] with [args] and return the value or [null] is [o] is not an object **/ static value builtin_objcall( value o, value f, value args ) { if( !val_is_object(o) ) return val_null; // keep dot-access semantics val_check(f,int); val_check(args,array); return val_ocallN(o,val_int(f),val_array_ptr(args),val_array_size(args)); } /** $objfield : o:any -> f:int -> bool Return true if [o] is an object which have field [f] **/ static value builtin_objfield( value o, value f ) { val_check(f,int); return alloc_bool( val_is_object(o) && otable_find(&((vobject*)o)->table, val_int(f)) != NULL ); } /** $objremove : o:object -> f:int -> bool Remove the field [f] from object [o]. Return [true] on success **/ static value builtin_objremove( value o, value f ) { val_check(o,object); val_check(f,int); return alloc_bool( otable_remove(&((vobject*)o)->table,val_int(f)) ); } static void builtin_objfields_rec( value d, field id, void *a ) { *((*(value**)a)++) = alloc_int((int)id); } /** $objfields : o:object -> int array Return all fields of the object **/ static value builtin_objfields( value o ) { value a; value *aptr; objtable *t; val_check(o,object); t = &((vobject*)o)->table; a = alloc_array(otable_count(t)); aptr = val_array_ptr(a); otable_iter(t,builtin_objfields_rec,&aptr); return a; } /** $hash : string -> int Return the hashed value of a field name **/ static value builtin_hash( value f ) { val_check(f,string); return alloc_int( (int)val_id(val_string(f)) ); } /** $fasthash : string -> int Return the hashed value of a field name, without accessing the cache **/ static value builtin_fasthash( value f ) { value acc = alloc_int(0); unsigned char *name; val_check(f,string); name = (unsigned char *)val_string(f); while( *name ) { acc = alloc_int(223 * val_int(acc) + *name); name++; } return acc; } /** $field : int -> string Reverse the hashed value of a field name. Return [null] on failure **/ static value builtin_field( value f ) { val_check(f,int); return val_field_name(val_int(f)); } /** $objsetproto : o:object -> proto:object? -> void Set the prototype of the object **/ static value builtin_objsetproto( value o, value p ) { val_check(o,object); if( val_is_null(p) ) ((vobject*)o)->proto = NULL; else { val_check(p,object); ((vobject*)o)->proto = (vobject*)p; } return val_null; } /** $objgetproto : o:object -> object? Get the prototype of the object **/ static value builtin_objgetproto( value o ) { val_check(o,object); o = (value)((vobject*)o)->proto; if( o == NULL ) return val_null; return o; } /**

Function Builtins

**/ /** $nargs : function -> int Return the number of arguments of a function. If the function have a variable number of arguments, it returns -1 **/ static value builtin_nargs( value f ) { val_check(f,function); return alloc_int( val_fun_nargs(f) ); } /** $call : f:function -> this:any -> args:array -> any Call [f] with [this] context and [args] arguments **/ static value builtin_call( value f, value ctx, value args ) { value old; value ret; neko_vm *vm; val_check(args,array); vm = NEKO_VM(); old = vm->vthis; vm->vthis = ctx; ret = val_callN(f,val_array_ptr(args),val_array_size(args)); vm->vthis = old; return ret; } static value closure_callback( value *args, int nargs ) { value env = NEKO_VM()->env; int cargs = val_array_size(env) - 2; value *a = val_array_ptr(env); value f = a[0]; value o = a[1]; int fargs = val_fun_nargs(f); int i; if( fargs != cargs + nargs && fargs != VAR_ARGS ) return val_null; if( nargs == 0 ) a = val_array_ptr(env) + 2; else if( cargs == 0 ) a = args; else { a = (value*)alloc(sizeof(value)*(nargs+cargs)); for(i=0;i object -> any* -> function Build a closure by applying a given number of arguments to a function **/ static value builtin_closure( value *args, int nargs ) { value f; value env; int fargs; if( nargs <= 1 ) failure("Invalid closure arguments number"); f = args[0]; if( !val_is_function(f) ) neko_error(); fargs = val_fun_nargs(f); if( fargs != VAR_ARGS && fargs < nargs-2 ) failure("Invalid closure arguments number"); env = alloc_array(nargs); memcpy(val_array_ptr(env),args,nargs * sizeof(f)); f = alloc_function( closure_callback, VAR_ARGS, "closure_callback" ); ((vfunction*)f)->env = env; return f; } /** $apply : function -> any* -> any Apply the function to several arguments. Return a function asking for more arguments or the function result if more args needed. **/ static value builtin_apply( value *args, int nargs ) { value f, env; int fargs; int i; nargs--; args++; if( nargs < 0 ) neko_error(); f = args[-1]; if( !val_is_function(f) ) neko_error(); if( nargs == 0 ) return f; fargs = val_fun_nargs(f); if( fargs == nargs || fargs == VAR_ARGS ) return val_callN(f,args,nargs); if( nargs > fargs ) neko_error(); env = alloc_array(fargs + 1); val_array_ptr(env)[0] = f; for(i=0;ienv; value a = alloc_array(nargs); int i; for(i=0;i function Return a variable argument function that, when called, will callback [f] with the array of arguments. **/ static value builtin_varargs( value f ) { value fvar; val_check_function(f,1); fvar = alloc_function(varargs_callback,VAR_ARGS,"varargs"); ((vfunction*)fvar)->env = f; return fvar; } /**

Number Builtins

**/ /** $iadd : anyint -> anyint -> anyint Add two integers **/ static value builtin_iadd( value a, value b ) { return alloc_best_int( val_any_int(a) + val_any_int(b) ); } /** $isub : anyint -> anyint -> anyint Subtract two integers **/ static value builtin_isub( value a, value b ) { return alloc_best_int( val_any_int(a) - val_any_int(b) ); } /** $imult : anyint -> anyint -> anyint Multiply two integers **/ static value builtin_imult( value a, value b ) { return alloc_best_int( val_any_int(a) * val_any_int(b) ); } /** $idiv : anyint -> anyint -> anyint Divide two integers. An error occurs if division by 0 **/ static value builtin_idiv( value a, value b ) { if( val_any_int(b) == 0 ) neko_error(); return alloc_best_int( val_any_int(a) / val_any_int(b) ); } typedef union { double d; struct { unsigned int l; unsigned int h; } i; } qw; /** $isnan : any -> bool Return if a value is the float NaN **/ static value builtin_isnan( value f ) { qw q; unsigned int h, l; if( !val_is_float(f) ) return val_false; q.d = val_float(f); h = q.i.h; l = q.i.l; l = l | (h & 0xFFFFF); h = h & 0x7FF00000; return alloc_bool( h == 0x7FF00000 && l != 0 ); } /** $isinfinite : any -> bool Return if a value is the float +Infinite **/ static value builtin_isinfinite( value f ) { qw q; unsigned int h, l; if( !val_is_float(f) ) return val_false; q.d = val_float(f); h = q.i.h; l = q.i.l; l = l | (h & 0xFFFFF); h = h & 0x7FF00000; return alloc_bool( h == 0x7FF00000 && l == 0 ); } /** $int : any -> int? Convert the value to the corresponding integer or return [null] **/ static value builtin_int( value f ) { switch( val_type(f) ) { case VAL_FLOAT: #ifdef NEKO_WINDOWS return alloc_best_int((int)val_float(f)); #else // in case of overflow, the result is unspecified by ISO // so we have to make a module 2^32 before casting to int return alloc_int((unsigned int)fmod(val_float(f),4294967296.0)); #endif case VAL_STRING: { char *c = val_string(f), *end; int h; if( val_strlen(f) >= 2 && c[0] == '0' && (c[1] == 'x' || c[1] == 'X') ) { h = 0; c += 2; while( *c ) { char k = *c++; if( k >= '0' && k <= '9' ) h = (h << 4) | (k - '0'); else if( k >= 'A' && k <= 'F' ) h = (h << 4) | ((k - 'A') + 10); else if( k >= 'a' && k <= 'f' ) h = (h << 4) | ((k - 'a') + 10); else return val_null; } return alloc_best_int(h); } h = strtol(c,&end,10); return ( c == end ) ? val_null : alloc_best_int(h); } case VAL_INT: case VAL_INT32: return f; } return val_null; } /** $float : any -> float? Convert the value to the corresponding float or return [null] **/ static value builtin_float( value f ) { if( val_is_string(f) ) { char *c = val_string(f), *end; tfloat f = (tfloat)strtod(c,&end); return (c == end) ? val_null : alloc_float(f); } if( val_is_number(f) ) return alloc_float( val_number(f) ); return val_null; } /**

Abstract Builtins

**/ /** $getkind : 'abstract -> 'kind Returns the kind value of the abstract **/ static value builtin_getkind( value v ) { if( val_is_int32(v) ) return alloc_abstract(neko_k_kind,k_old_int32); val_check(v,abstract); return alloc_abstract(neko_k_kind,val_kind(v)); } /** $iskind : any -> 'kind -> bool Tells if a value is of the given kind **/ static value builtin_iskind( value v, value k ) { val_check_kind(k,neko_k_kind); return val_is_abstract(v) ? alloc_bool(val_kind(v) == (vkind)val_data(k)) : (val_data(k) == k_old_int32 ? alloc_bool(val_is_int32(v)) : val_false); } /**

Hashtable Builtins

**/ /** $hkey : any -> int Return the hash of any value **/ static value builtin_hkey( value v ) { return alloc_int(val_hash(v)); } #define HASH_DEF_SIZE 7 /** $hnew : s:int -> 'hash Create an hashtable with [s] slots **/ static value builtin_hnew( value size ) { vhash *h; int i; val_check(size,int); h = (vhash*)alloc(sizeof(vhash)); h->nitems = 0; h->ncells = val_int(size); if( h->ncells <= 0 ) h->ncells = HASH_DEF_SIZE; h->cells = (hcell**)alloc(sizeof(hcell*)*h->ncells); for(i=0;incells;i++) h->cells[i] = NULL; return alloc_abstract(k_hash,h); } static void add_rec( hcell **cc, int size, hcell *c ) { int k; if( c == NULL ) return; add_rec(cc,size,c->next); k = c->hkey % size; c->next = cc[k]; cc[k] = c; } /** $hresize : 'hash -> int -> void Resize an hashtable **/ static value builtin_hresize( value vh, value size ) { vhash *h; hcell **cc; int nsize; int i; val_check_kind(vh,k_hash); val_check(size,int); h = val_hdata(vh); nsize = val_int(size); if( nsize <= 0 ) nsize = HASH_DEF_SIZE; cc = (hcell**)alloc(sizeof(hcell*)*nsize); memset(cc,0,sizeof(hcell*)*nsize); for(i=0;incells;i++) add_rec(cc,nsize,h->cells[i]); h->cells = cc; h->ncells = nsize; return val_null; } /** $hget : 'hash -> k:any -> cmp:function:2? -> any Look for the value bound to the key [k] in the hashtable. Use the comparison function [cmp] or [$compare] if [null]. Return [null] if no value is found. **/ static value builtin_hget( value vh, value key, value cmp ) { vhash *h; hcell *c; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); c = h->cells[val_hash(key) % h->ncells]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) return c->val; c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) return c->val; c = c->next; } } return val_null; } /** $hmem : 'hash -> k:any -> cmp:function:2? -> bool Look for the value bound to the key [k] in the hashtable. Use the comparison function [cmp] or [$compare] if [null]. Return true if such value exists, false either. **/ static value builtin_hmem( value vh, value key, value cmp ) { vhash *h; hcell *c; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); c = h->cells[val_hash(key) % h->ncells]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) return val_true; c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) return val_true; c = c->next; } } return val_false; } /** $hremove : 'hash -> k:any -> cmp:function:2? -> bool Look for the value bound to the key [k] in the hashtable. Use the comparison function [cmp] or [$compare] if [null]. Return true if such value exists and remove it from the hash, false either. **/ static value builtin_hremove( value vh, value key, value cmp ) { vhash *h; hcell *c, *prev = NULL; int hkey; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); hkey = val_hash(key) % h->ncells; c = h->cells[hkey]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) { if( prev == NULL ) h->cells[hkey] = c->next; else prev->next = c->next; h->nitems--; return val_true; } prev = c; c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) { if( prev == NULL ) h->cells[hkey] = c->next; else prev->next = c->next; h->nitems--; return val_true; } prev = c; c = c->next; } } return val_false; } /** $hset : 'hash -> k:any -> v:any -> cmp:function:2? -> bool Set the value bound to key [k] to [v] or add it to the hashtable if not found. Return true if the value was added to the hashtable. **/ static value builtin_hset( value vh, value key, value val, value cmp ) { vhash *h; hcell *c; int hkey; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); hkey = val_hash(key); c = h->cells[hkey % h->ncells]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) { c->val = val; return val_false; } c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) { c->val = val; return val_false; } c = c->next; } } if( h->nitems >= (h->ncells << 1) ) builtin_hresize(vh,alloc_int(h->ncells << 1)); c = (hcell*)alloc(sizeof(hcell)); c->hkey = hkey; c->key = key; c->val = val; hkey %= h->ncells; c->next = h->cells[hkey]; h->cells[hkey] = c; h->nitems++; return val_true; } /** $hadd : 'hash -> k:any -> v:any -> void Add the value [v] with key [k] to the hashtable. Previous binding is masked but not removed. **/ static value builtin_hadd( value vh, value key, value val ) { vhash *h; hcell *c; int hkey; val_check_kind(vh,k_hash); h = val_hdata(vh); hkey = val_hash(key); if( hkey < 0 ) neko_error(); if( h->nitems >= (h->ncells << 1) ) builtin_hresize(vh,alloc_int(h->ncells << 1)); c = (hcell*)alloc(sizeof(hcell)); c->hkey = hkey; c->key = key; c->val = val; hkey %= h->ncells; c->next = h->cells[hkey]; h->cells[hkey] = c; h->nitems++; return val_null; } /** $hiter : 'hash -> f:function:2 -> void Call the function [f] with every key and value in the hashtable **/ static value builtin_hiter( value vh, value f ) { int i; hcell *c; vhash *h; val_check_function(f,2); val_check_kind(vh,k_hash); h = val_hdata(vh); for(i=0;incells;i++) { c = h->cells[i]; while( c != NULL ) { val_call2(f,c->key,c->val); c = c->next; } } return val_null; } /** $hcount : 'hash -> int Return the number of elements in the hashtable **/ static value builtin_hcount( value vh ) { val_check_kind(vh,k_hash); return alloc_int( val_hdata(vh)->nitems ); } /** $hsize : 'hash -> int Return the size of the hashtable **/ static value builtin_hsize( value vh ) { val_check_kind(vh,k_hash); return alloc_int( val_hdata(vh)->ncells ); } /**

Other Builtins

**/ /** $print : any* -> void Can print any value **/ static value builtin_print( value *args, int nargs ) { buffer b; int i; if( nargs == 1 && val_is_string(*args) ) { val_print(*args); return neko_builtins[1]; } b = alloc_buffer(NULL); for(i=0;i any Throw any value as an exception. Never returns **/ static value builtin_throw( value v ) { val_throw(v); return val_null; } /** $rethrow : any -> any Throw any value as an exception while keeping previous exception stack. Never returns **/ static value builtin_rethrow( value v ) { val_rethrow(v); return val_null; } /** $istrue : v:any -> bool Return true if [v] is not [false], not [null] and not 0 **/ static value builtin_istrue( value f ) { return alloc_bool(f != val_false && f != val_null && f != alloc_int(0) && (val_is_int(f) || val_tag(f) != VAL_INT32 || val_int32(f) != 0)); } /** $not : any -> bool Return true if [v] is [false] or [null] or [0] **/ static value builtin_not( value f ) { return alloc_bool(f == val_false || f == val_null || f == alloc_int(0) || (!val_is_int(f) && val_tag(f) == VAL_INT32 && val_int32(f) == 0)); } /** $typeof : any -> int Return the type of a value. The following builtins are defined :
  • [$tnull] = 0
  • [$tint] = 1
  • [$tfloat] = 2
  • [$tbool] = 3
  • [$tstring] = 4
  • [$tobject] = 5
  • [$tarray] = 6
  • [$tfunction] = 7
  • [$tabstract] = 8
**/ static value builtin_typeof( value v ) { switch( val_type(v) ) { case VAL_INT: case VAL_INT32: return alloc_int(1); case VAL_NULL: return alloc_int(0); case VAL_FLOAT: return alloc_int(2); case VAL_BOOL: return alloc_int(3); case VAL_STRING: return alloc_int(4); case VAL_OBJECT: return alloc_int(5); case VAL_ARRAY: return alloc_int(6); case VAL_FUNCTION: return alloc_int(7); case VAL_ABSTRACT: return alloc_int(8); default: neko_error(); } } /** $compare : any -> any -> int? Compare two values and return 1, -1 or 0. Return [null] if comparison is not possible **/ static value builtin_compare( value a, value b ) { int r = val_compare(a,b); return (r == invalid_comparison)?val_null:alloc_int(r); } /** $pcompare : any -> any -> int Physically compare two values. Same as [$compare] for integers. **/ static value builtin_pcompare( value a, value b ) { int_val ia = (int_val)a; int_val ib = (int_val)b; if( ia > ib ) return alloc_int(1); else if( ia < ib ) return alloc_int(-1); else return alloc_int(0); } /** $excstack : void -> array Return the stack between the place the last exception was raised and the place it was catched. The stack is composed of the following items :
  • [null] when it's a C function
  • a string when it's a module without debug informations
  • an array of two elements (usually file and line) if debug informations where available
**/ static value builtin_excstack() { return NEKO_VM()->exc_stack; } /** $callstack : void -> array Return the current callstack. Same format as [$excstack] **/ static value builtin_callstack() { return neko_call_stack(NEKO_VM()); } /** $version : void -> int Return the version of Neko : 135 means 1.3.5 **/ static value builtin_version() { return alloc_int(NEKO_VERSION); } /** $setresolver : function:2? -> void Set a function to callback with object and field id when an object field is not found. **/ static value builtin_setresolver( value f ) { neko_vm *vm = NEKO_VM(); if( val_is_null(f) ) vm->resolver = NULL; else { val_check_function(f,2); vm->resolver = f; } return val_null; } #define BUILTIN(name,nargs) \ alloc_field(neko_builtins[0],val_id(#name),alloc_function(builtin_##name,nargs,"$" #name)); void neko_init_builtins() { neko_builtins = alloc_root(2); neko_builtins[0] = alloc_object(NULL); neko_builtins[1] = alloc_function(builtin_print,VAR_ARGS,"$print"); BUILTIN(print,VAR_ARGS); BUILTIN(array,VAR_ARGS); BUILTIN(amake,1); BUILTIN(acopy,1); BUILTIN(asize,1); BUILTIN(asub,3); BUILTIN(ablit,5); BUILTIN(aconcat,1); BUILTIN(smake,1); BUILTIN(ssize,1); BUILTIN(scopy,1); BUILTIN(ssub,3); BUILTIN(sget,2); BUILTIN(sset,3); BUILTIN(sblit,5); BUILTIN(sfind,3); BUILTIN(sget16,3); BUILTIN(sget32,3); BUILTIN(sgetf,3); BUILTIN(sgetd,3); BUILTIN(sset16,4); BUILTIN(sset32,4); BUILTIN(ssetf,4); BUILTIN(ssetd,4); BUILTIN(itof,2); BUILTIN(itod,3); BUILTIN(ftoi,2); BUILTIN(dtoi,3); BUILTIN(isbigendian,0); BUILTIN(new,1); BUILTIN(objget,2); BUILTIN(objset,3); BUILTIN(objcall,3); BUILTIN(objfield,2); BUILTIN(objremove,2); BUILTIN(objfields,1); BUILTIN(hash,1); BUILTIN(fasthash,1); BUILTIN(field,1); BUILTIN(objsetproto,2); BUILTIN(objgetproto,1); BUILTIN(int,1); BUILTIN(float,1); BUILTIN(string,1); BUILTIN(typeof,1); BUILTIN(closure,VAR_ARGS); BUILTIN(apply,VAR_ARGS); BUILTIN(varargs,1); BUILTIN(compare,2); BUILTIN(pcompare,2); BUILTIN(not,1); BUILTIN(throw,1); BUILTIN(rethrow,1); BUILTIN(nargs,1); BUILTIN(call,3); BUILTIN(isnan,1); BUILTIN(isinfinite,1); BUILTIN(istrue,1); BUILTIN(getkind,1); BUILTIN(iskind,2); BUILTIN(hnew,1); BUILTIN(hget,3); BUILTIN(hmem,3); BUILTIN(hset,4); BUILTIN(hadd,3); BUILTIN(hremove,3); BUILTIN(hresize,2); BUILTIN(hkey,1); BUILTIN(hcount,1); BUILTIN(hsize,1); BUILTIN(hiter,2); BUILTIN(iadd,2); BUILTIN(isub,2); BUILTIN(imult,2); BUILTIN(idiv,2); BUILTIN(excstack,0); BUILTIN(callstack,0); BUILTIN(version,0); BUILTIN(setresolver,1); } /* ************************************************************************ */ neko-2-2-0/vm/callback.c000066400000000000000000000127761321613172000150000ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include "neko.h" #include "objtable.h" #include "vm.h" #include "neko_mod.h" #define MAXCALLS 350 typedef value (*c_prim0)(); typedef value (*c_prim1)(value); typedef value (*c_prim2)(value,value); typedef value (*c_prim3)(value,value,value); typedef value (*c_prim4)(value,value,value,value); typedef value (*c_prim5)(value,value,value,value,value); typedef value (*c_primN)(value*,int); typedef value (*jit_prim)( neko_vm *, void *, value, neko_module * ); extern void neko_setup_trap( neko_vm *vm ); extern void neko_process_trap( neko_vm *vm ); extern int neko_stack_expand( int_val *sp, int_val *csp, neko_vm *vm ); extern char *jit_boot_seq; EXTERN value val_callEx( value vthis, value f, value *args, int nargs, value *exc ) { neko_vm *vm = NEKO_VM(); value old_this = vm->vthis; value old_env = vm->env; value ret = val_null; jmp_buf oldjmp; if( vthis != NULL ) vm->vthis = vthis; if( exc ) { memcpy(&oldjmp,&vm->start,sizeof(jmp_buf)); if( setjmp(vm->start) ) { *exc = vm->vthis; neko_process_trap(vm); vm->vthis = old_this; vm->env = old_env; memcpy(&vm->start,&oldjmp,sizeof(jmp_buf)); return val_null; } neko_setup_trap(vm); } if( (uintptr_t)&vm < (uintptr_t)vm->c_stack_max ) val_throw(alloc_string("C Stack Overflow")); if( val_is_int(f) ) val_throw(alloc_string("Invalid call")); if( val_tag(f) == VAL_PRIMITIVE ) { vm->env = ((vfunction *)f)->env; if( nargs == ((vfunction*)f)->nargs ) { if( nargs > CALL_MAX_ARGS ) failure("Too many arguments for a call"); switch( nargs ) { case 0: ret = ((c_prim0)((vfunction*)f)->addr)(); break; case 1: ret = ((c_prim1)((vfunction*)f)->addr)(args[0]); break; case 2: ret = ((c_prim2)((vfunction*)f)->addr)(args[0],args[1]); break; case 3: ret = ((c_prim3)((vfunction*)f)->addr)(args[0],args[1],args[2]); break; case 4: ret = ((c_prim4)((vfunction*)f)->addr)(args[0],args[1],args[2],args[3]); break; case 5: ret = ((c_prim5)((vfunction*)f)->addr)(args[0],args[1],args[2],args[3],args[4]); break; } } else if( ((vfunction*)f)->nargs == -1 ) ret = (value)((c_primN)((vfunction*)f)->addr)(args,nargs); else val_throw(alloc_string("Invalid call")); if( ret == NULL ) val_throw( (value)((vfunction*)f)->module ); } else if( val_short_tag(f) == VAL_FUNCTION ) { if( nargs == ((vfunction*)f)->nargs ) { int n; if( vm->csp + 4 >= vm->sp - nargs && !neko_stack_expand(vm->sp,vm->csp,vm) ) { if( exc ) { neko_process_trap(vm); memcpy(&vm->start,&oldjmp,sizeof(jmp_buf)); } failure("Stack Overflow"); } else { for(n=0;nsp = (int_val)args[n]; vm->env = ((vfunction*)f)->env; if( val_tag(f) == VAL_FUNCTION ) { *++vm->csp = (int_val)callback_return; *++vm->csp = 0; *++vm->csp = 0; *++vm->csp = 0; ret = neko_interp(vm,((vfunction*)f)->module,(int_val)val_null,(int_val*)((vfunction*)f)->addr); } else { neko_module *m = (neko_module*)((vfunction*)f)->module; ret = ((jit_prim)jit_boot_seq)(vm,((vfunction*)f)->addr,val_null,m); } } } else val_throw(alloc_string("Invalid call")); } else val_throw(alloc_string("Invalid call")); if( exc ) { neko_process_trap(vm); memcpy(&vm->start,&oldjmp,sizeof(jmp_buf)); } vm->vthis = old_this; vm->env = old_env; return ret; } EXTERN value val_callN( value f, value *args, int nargs ) { return val_callEx(NULL,f,args,nargs,NULL); } EXTERN value val_ocallN( value o, field f, value *args, int nargs ) { return val_callEx(o,val_field(o,f),args,nargs,NULL); } EXTERN value val_call0( value f ) { return val_callN(f,NULL,0); } EXTERN value val_call1( value f, value v ) { return val_callN(f,&v,1); } EXTERN value val_call2( value f, value v1, value v2 ) { value args[2] = { v1, v2 }; return val_callN(f,args,2); } EXTERN value val_call3( value f, value arg1, value arg2, value arg3 ) { value args[3] = { arg1, arg2, arg3 }; return val_callN(f,args,3); } EXTERN value val_ocall0( value o, field f ) { return val_ocallN(o,f,NULL,0); } EXTERN value val_ocall1( value o, field f, value arg ) { return val_ocallN(o,f,&arg,1); } EXTERN value val_ocall2( value o, field f, value arg1, value arg2 ) { value args[2] = { arg1, arg2 }; return val_ocallN(o,f,args,2); } EXTERN value val_this() { return (value)NEKO_VM()->vthis; } /* ************************************************************************ */ neko-2-2-0/vm/elf.c000066400000000000000000000121111321613172000137710ustar00rootroot00000000000000/* * Copyright (C)2016-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "neko_elf.h" /* None of this is needed on non-ELF platforms... */ #ifdef SEPARATE_SECTION_FOR_BYTECODE #include #include /* Name of neko bytecode section... */ static const char const* BYTECODE_SEC_NAME = ".nekobytecode"; /* Must be big enough to hold Elf32_Ehdr or Elf64_Ehdr... */ int size_Ehdr = sizeof(Elf64_Ehdr); /* Must be big enough to hold Elf32_Shdr or Elf64_Shdr... */ int size_Shdr = sizeof(Elf64_Shdr); static int is_32, shoff, shent, shnum, shstr; static char *strbuf; static int strsize, stroff; static value elf_read_exe(FILE *exe, int loc, char *buf, int size) { if ( 0 != fseek(exe,loc,SEEK_SET) || size != fread(buf,1,size,exe) ) { fclose(exe); return val_false; } return val_true; } static value elf_write_exe(FILE *exe, int loc, char *buf, int size) { if ( 0 != fseek(exe,loc,SEEK_SET) || size != fwrite(buf,1,size,exe) ) { fclose(exe); return val_false; } return val_true; } value elf_read_header(FILE *exe) { char hdr[size_Ehdr]; int hdrsize; /* First read the elf header to determine 32/64-bit-ness... */ if ( val_true != elf_read_exe(exe,0,hdr,EI_NIDENT) ) return val_false; if ( hdr[EI_CLASS] == ELFCLASS32 || hdr[EI_CLASS] == ELFCLASS64 ) { is_32 = hdr[EI_CLASS] == ELFCLASS32; } else return val_false; /* Read the full elf header now... */ hdrsize = is_32 ? sizeof(Elf32_Ehdr) : sizeof(Elf64_Ehdr); if ( val_true != elf_read_exe(exe,0,hdr,hdrsize) ) return val_false; if ( elf_get_Ehdr(hdr,e_type) != ET_EXEC ) return val_false; /* Remember the section headers info... */ shoff = elf_get_Ehdr(hdr,e_shoff); shent = elf_get_Ehdr(hdr,e_shentsize); shnum = elf_get_Ehdr(hdr,e_shnum); shstr = elf_get_Ehdr(hdr,e_shstrndx); return val_true; } int elf_is_32() { return is_32; } value elf_read_section(FILE *exe, int sec, char *buf) { return elf_read_exe(exe,shoff+sec*shent,buf,shent); } value elf_write_section(FILE *exe, int sec, char *buf) { return elf_write_exe(exe,shoff+sec*shent,buf,shent); } static value elf_read_section_string_table(FILE *exe) { char buf[size_Ehdr]; if ( NULL != strbuf ) return val_true; if ( val_true != elf_read_section(exe,shstr,buf) ) return val_false; stroff = elf_get_Shdr(buf,sh_offset); strsize = elf_get_Shdr(buf,sh_size); strbuf = (char*) malloc(strsize); if ( val_true != elf_read_exe(exe,stroff,strbuf,strsize) ) return val_false; return val_true; } void elf_free_section_string_table() { if ( NULL != strbuf ) { free(strbuf); strbuf = NULL; } } static int elf_find_section_by_name(FILE *exe, const char *name) { char buf[size_Shdr]; int shcur = 0, shname; if ( val_true != elf_read_section_string_table(exe) ) return -1; while ( shcur < shnum ) { if ( val_true != elf_read_section(exe,shcur,buf) ) return -1; shname = elf_get_Shdr(buf,sh_name); if ( shname < strsize && !strncmp(&strbuf[shname], name, strlen(name)) ) { /* found the .nekobytecode section! */ return shcur; } shcur++; } return -1; } int elf_find_bytecode_section(FILE *exe) { return elf_find_section_by_name(exe, BYTECODE_SEC_NAME); } value elf_find_embedded_bytecode(const char *file, int *beg, int *end) { FILE *exe; char buf[size_Shdr]; int bytecode_sec_idx; /* Open the file to update the elf nekobytecode section header... */ exe = fopen(file,"rb"); if( exe == NULL ) return val_false; /* First read the elf header... */ if ( val_true != elf_read_header(exe) ) goto failed; /* Find the right section header... */ bytecode_sec_idx = elf_find_bytecode_section(exe); if ( -1 == bytecode_sec_idx ) goto failed; if ( val_true != elf_read_section(exe,bytecode_sec_idx,buf) ) goto failed; elf_free_section_string_table(); fclose(exe); if ( NULL != beg ) *beg = elf_get_Shdr(buf,sh_offset); if ( NULL != end ) *end = elf_get_Shdr(buf,sh_offset) + elf_get_Shdr(buf,sh_size); return val_true; failed: elf_free_section_string_table(); fclose(exe); return val_false; } #endif neko-2-2-0/vm/hash.c000066400000000000000000000054471321613172000141640ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "neko.h" typedef struct vlist { value v; struct vlist *next; } vlist; typedef struct vparam { int *h; vlist l; } vparam; #define HBIG(x) *h = *h * 65599 + (x) #define HSMALL(x) *h = *h * 19 + (x) static void hash_obj_rec( value v, field f, void *_p ); static void hash_rec( value v, int *h, vlist *l ) { val_type t = val_type(v); switch( t ) { case VAL_INT: HBIG(val_int(v)); break; case VAL_INT32: HBIG(val_int32(v)); break; case VAL_NULL: HSMALL(0); break; case VAL_FLOAT: { int k = sizeof(tfloat); while( k ) HSMALL(val_string(v)[--k]); } break; case VAL_BOOL: HSMALL(val_bool(v)); break; case VAL_STRING: { int k = val_strlen(v); while( k ) HSMALL(val_string(v)[--k]); } break; case VAL_OBJECT: case VAL_ARRAY: { vlist *tmp = l; int k = 0; while( tmp != NULL ) { if( tmp->v == v ) { HSMALL(k); return; } k = k + 1; tmp = tmp->next; } } if( t == VAL_OBJECT ) { vparam p; p.h = h; p.l.v = v; p.l.next = l; val_iter_fields(v,hash_obj_rec,&p); v = (value)((vobject*)v)->proto; if( v != NULL ) hash_rec(v,h,&p.l); } else { vlist cur; int k = val_array_size(v); cur.v = v; cur.next = l; while( k ) hash_rec(val_array_ptr(v)[--k],h,&cur); } break; default: // ignore since we want hashes to be stable wrt memory break; } } static void hash_obj_rec( value v, field f, void *_p ) { vparam *p = (vparam*)_p; int *h = p->h; HBIG((int)f); hash_rec(v,h,&p->l); } EXTERN int val_hash( value v ) { int h = 0; hash_rec(v,&h,NULL); return (((unsigned int)h) & 0x3FFFFFFF); } /* ************************************************************************ */ neko-2-2-0/vm/interp.c000066400000000000000000000753421321613172000145430ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include "opcodes.h" #include "vm.h" #include "neko_mod.h" #include "objtable.h" #ifndef NEKO_WINDOWS # include #endif #if defined(NEKO_GCC) && defined(NEKO_X86) && (__GNUC__ == 3) # define ACC_BACKUP int_val __acc = acc; # define ACC_RESTORE acc = __acc; # define ACC_REG asm("%eax") # define PC_REG asm("%esi") # define SP_REG asm("%edi") # define CSP_REG # define VM_ARG vm #elif defined(NEKO_GCC) && defined(NEKO_PPC) # define ACC_BACKUP # define ACC_RESTORE # define ACC_REG asm("26") # define PC_REG asm("27") # define SP_REG asm("28") # define CSP_REG asm("29") # define VM_REG asm("30") # define VM_ARG _vm #else # define ACC_BACKUP # define ACC_RESTORE # define ACC_REG # define PC_REG # define SP_REG # define CSP_REG # define VM_ARG vm #endif #define ERASE 0 #define address_int(a) (((int_val)(a)) | 1) #define int_address(a) (int_val*)(a & ~1) extern field id_add, id_radd, id_sub, id_rsub, id_mult, id_rmult, id_div, id_rdiv, id_mod, id_rmod; extern field id_get, id_set; extern value neko_alloc_module_function( void *m, int_val pos, int nargs ); extern char *jit_boot_seq; extern char *jit_handle_trap; typedef void (*jit_handle)( neko_vm * ); extern int neko_can_jit(); value NEKO_TYPEOF[] = { alloc_int(0), alloc_int(2), alloc_int(3), alloc_int(4), alloc_int(5), alloc_int(6), alloc_int(7), alloc_int(8), alloc_int(1), }; static void default_printer( const char *s, int len, void *out ) { while( len > 0 ) { int p = (int)fwrite(s,1,len,(FILE*)out); if( p <= 0 ) { fputs("[ABORTED]",(FILE*)out); break; } len -= p; s += p; } fflush((FILE*)out); } EXTERN neko_vm *neko_vm_alloc( void *custom ) { neko_vm *vm = (neko_vm*)alloc(sizeof(neko_vm)); # ifdef NEKO_WINDOWS int stack_size = 0x100000; // 1MB default # else struct rlimit st; int stack_size; if( getrlimit(RLIMIT_STACK,&st) != 0 || st.rlim_cur == RLIM_INFINITY ) stack_size = 8192 << 10; else stack_size = st.rlim_cur; # endif vm->spmin = (int_val*)alloc(INIT_STACK_SIZE*sizeof(int_val)); vm->print = default_printer; vm->print_param = stdout; vm->clist = NULL; // the maximum stack position for a C call is estimated // - stack grows bottom // - neko_vm_alloc should be near the beginning of the stack // - we keep 64KB for the C call work space and error margin vm->c_stack_max = (void*)(((int_val)&vm) - (stack_size - 0x10000)); vm->exc_stack = alloc_array(0); vm->spmax = vm->spmin + INIT_STACK_SIZE; vm->sp = vm->spmax; vm->csp = vm->spmin - 1; vm->vthis = val_null; vm->env = alloc_array(0); vm->jit_val = NULL; vm->run_jit = 0; vm->resolver = NULL; vm->trusted_code = 0; vm->fstats = NULL; vm->pstats = NULL; return vm; } EXTERN int neko_vm_jit( neko_vm *vm, int enable_jit ) { if( enable_jit < 0 ) return vm->run_jit; if( enable_jit ) vm->run_jit = neko_can_jit(); else vm->run_jit = 0; return vm->run_jit; } EXTERN int neko_vm_trusted( neko_vm *vm, int t ) { int old = vm->trusted_code; vm->trusted_code = t; return old; } EXTERN void neko_vm_set_stats( neko_vm *vm, neko_stat_func fstats, neko_stat_func pstats ) { vm->fstats = fstats; vm->pstats = pstats; } EXTERN void neko_vm_select( neko_vm *vm ) { local_set(neko_vm_context,vm); } EXTERN neko_vm *neko_vm_current() { return NEKO_VM(); } EXTERN void *neko_vm_custom( neko_vm *vm, vkind k ) { custom_list *c = vm->clist; while( c != NULL ) { if( c->tag == k ) return c->custom; c = c->next; } return NULL; } EXTERN void neko_vm_set_custom( neko_vm *vm, vkind k, void *v ) { custom_list *c = vm->clist, *prev = NULL; while( c != NULL ) { if( c->tag == k ) { if( v ) { c->custom = v; return; } if( prev == NULL ) vm->clist = c->next; else prev->next = c->next; return; } prev = c; c = c->next; } c = (custom_list*)alloc(sizeof(custom_list)); c->tag = k; c->custom = v; c->next = vm->clist; vm->clist = c; } typedef struct { neko_printer prev; void *prev_param; neko_printer cur; void *cur_param; } redirect_param; static void redirected_print( const char *s, int size, void *_p ) { redirect_param *p = (redirect_param*)_p; p->cur(s,size,p->cur_param); } EXTERN void neko_vm_redirect( neko_vm *vm, neko_printer print, void *param ) { redirect_param *p; if( print == NULL ) { if( vm->print != redirected_print ) return; p = (redirect_param*)vm->print_param; vm->print = p->prev; vm->print_param = p->prev_param; return; } p = (redirect_param*)alloc(sizeof(redirect_param)); p->prev = vm->print; p->prev_param = vm->print_param; p->cur = print; p->cur_param = param; vm->print = redirected_print; vm->print_param = p; } EXTERN value neko_vm_execute( neko_vm *vm, void *_m ) { unsigned int i; neko_module *m = (neko_module*)_m; value old_env = vm->env, ret; value old_this = vm->vthis; neko_vm_select(vm); for(i=0;infields;i++) val_id(val_string(m->fields[i])); vm->env = alloc_array(0); vm->vthis = val_null; ret = neko_interp(vm,m,(int_val)val_null,m->code); vm->env = old_env; vm->vthis = old_this; return ret; } EXTERN value neko_exc_stack( neko_vm *vm ) { return vm->exc_stack; } static value neko_flush_stack( int_val *cspup, int_val *csp, value old ); EXTERN value neko_call_stack( neko_vm *vm ) { return neko_flush_stack(vm->csp,vm->spmin - 1,NULL); } typedef int_val (*c_prim0)(); typedef int_val (*c_prim1)(int_val); typedef int_val (*c_prim2)(int_val,int_val); typedef int_val (*c_prim3)(int_val,int_val,int_val); typedef int_val (*c_prim4)(int_val,int_val,int_val,int_val); typedef int_val (*c_prim5)(int_val,int_val,int_val,int_val,int_val); typedef int_val (*c_primN)(value*,int); typedef int_val (*jit_prim)( neko_vm *, void *, value , neko_module *m ); static int_val jit_run( neko_vm *vm, vfunction *acc ) { neko_module *m = (neko_module*)acc->module; return ((jit_prim)jit_boot_seq)(vm,acc->addr,(value)acc,m); } #define RuntimeError(err,param) { if( param ) pc++; PushInfos(); BeginCall(); val_throw(alloc_string(err)); } #define CallFailure() RuntimeError("Invalid call",false) #define InvalidFieldAccess() { \ value v = val_field_name((field)*pc); \ buffer b; \ if( val_is_null(v) ) RuntimeError("Invalid field access",true); \ b = alloc_buffer("Invalid field access : "); \ val_buffer(b,v); \ pc++; PushInfos(); BeginCall(); \ val_throw(buffer_to_string(b)); \ } #ifdef NEKO_THREADED # define Instr(x) Label##x: # ifdef NEKO_DIRECT_THREADED # define Next goto *((const void *)*pc++); # else # define Next goto **(instructions + *pc++); # endif #else # define Instr(x) case x: # define Next break; #endif #define PopMacro(n) { \ int tmp = (int)n; \ while( tmp-- > 0 ) \ *sp++ = ERASE; \ } #define BeginCall() \ vm->sp = sp; \ vm->csp = csp; #define EndCall() \ sp = vm->sp; \ csp = vm->csp #define PushInfos() \ if( csp + 4 >= sp ) STACK_EXPAND; \ *++csp = (int_val)pc; \ *++csp = (int_val)vm->env; \ *++csp = (int_val)vm->vthis; \ *++csp = (int_val)m; #define PopInfos(restpc) \ m = (neko_module*)*csp; \ *csp-- = ERASE; \ vm->vthis = (value)*csp; \ *csp-- = ERASE; \ vm->env = (value)*csp; \ *csp-- = ERASE; \ if( restpc ) pc = (int_val*)*csp; \ *csp-- = ERASE; #define SetupBeforeCall(this_arg) \ vfunction *f = (vfunction*)acc; \ PushInfos(); \ vm->vthis = this_arg; \ vm->env = ((vfunction*)acc)->env; \ BeginCall(); #define RestoreAfterCall() \ if( acc == (int_val)NULL ) val_throw( (value)f->module ); \ EndCall(); \ PopInfos(false); #define DoCall(this_arg,pc_args) \ if( acc & 1 ) \ CallFailure() \ else if( val_tag(acc) == VAL_FUNCTION && pc_args == ((vfunction*)acc)->nargs ) { \ PushInfos(); \ m = (neko_module*)((vfunction*)acc)->module; \ pc = (int_val*)((vfunction*)acc)->addr; \ vm->vthis = this_arg; \ vm->env = ((vfunction*)acc)->env; \ } else if( val_tag(acc) == VAL_PRIMITIVE ) { \ if( pc_args == ((vfunction*)acc)->nargs ) { \ SetupBeforeCall(this_arg); \ switch( pc_args ) { \ case 0: \ acc = ((c_prim0)((vfunction*)acc)->addr)(); \ break; \ case 1: \ acc = ((c_prim1)((vfunction*)acc)->addr)(sp[0]); \ break; \ case 2: \ acc = ((c_prim2)((vfunction*)acc)->addr)(sp[1],sp[0]); \ break; \ case 3: \ acc = ((c_prim3)((vfunction*)acc)->addr)(sp[2],sp[1],sp[0]); \ break; \ case 4: \ acc = ((c_prim4)((vfunction*)acc)->addr)(sp[3],sp[2],sp[1],sp[0]); \ break; \ case 5: \ acc = ((c_prim5)((vfunction*)acc)->addr)(sp[4],sp[3],sp[2],sp[1],sp[0]); \ break; \ } \ RestoreAfterCall(); \ } \ else if( ((vfunction*)acc)->nargs == VAR_ARGS ) { \ int_val args[CALL_MAX_ARGS]; \ int_val tmp; \ SetupBeforeCall(this_arg); \ sp += pc_args; \ for(tmp=0;tmpaddr)((value*)(void*)args,(int)pc_args); \ RestoreAfterCall(); \ } else \ CallFailure(); \ PopMacro(pc_args); \ } else if( val_tag(acc) == VAL_JITFUN ) { \ if( pc_args == ((vfunction*)acc)->nargs ) { \ SetupBeforeCall(this_arg); \ acc = jit_run(vm,(vfunction*)acc); \ RestoreAfterCall(); \ } else \ CallFailure(); \ } else \ CallFailure(); #define OpError(op) RuntimeError("Invalid operation (" op ")", false) #define IntOp(op) \ if( (acc & 1) && (*sp & 1) ) \ acc = (int_val)alloc_best_int(val_int(*sp) op val_int(acc)); \ else if( val_is_any_int(acc) && val_is_any_int(*sp) ) \ acc = (int_val)alloc_best_int(val_any_int(*sp) op val_any_int(acc)); \ else \ OpError(#op); \ *sp++ = ERASE; \ Next #define Test(test) \ BeginCall(); \ acc = (int_val)val_compare((value)*sp,(value)acc); \ EndCall(); \ *sp++ = ERASE; \ acc = (int_val)((acc test 0 && acc != invalid_comparison)?val_true:val_false); \ Next #define SUB(x,y) ((x) - (y)) #define MULT(x,y) ((x) * (y)) #define DIV(x,y) ((x) / (y)) #define ObjectOpGen(obj,param,id,err) { \ ACC_BACKUP \ value _o = (value)obj; \ value _arg = (value)param; \ value _f = val_field(_o,id); \ if( _f == val_null ) { \ ACC_RESTORE \ err; \ } else { \ PushInfos(); \ BeginCall(); \ acc = (int_val)val_callEx(_o,_f,&_arg,1,NULL); \ EndCall(); \ PopInfos(false); \ } \ } #define ObjectOp(obj,param,id) ObjectOpGen(obj,param,id,RuntimeError("Unsupported operation",false)) #define NumberOp(op,fop,id_op,id_rop) \ if( (acc & 1) && (*sp & 1) ) \ acc = (int_val)alloc_best_int(val_int(*sp) op val_int(acc)); \ else if( acc & 1 ) { \ if( val_tag(*sp) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_float(*sp),val_int(acc))); \ else if( val_tag(*sp) == VAL_INT32 ) \ acc = (int_val)alloc_best_int(val_int32(*sp) op val_int(acc)); \ else if( val_tag(*sp) == VAL_OBJECT ) \ ObjectOp(*sp,acc,id_op) \ else \ OpError(#op); \ } else if( *sp & 1 ) { \ if( val_tag(acc) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_int(*sp),val_float(acc))); \ else if( val_tag(acc) == VAL_INT32 ) \ acc = (int_val)alloc_best_int(val_int(*sp) op val_int32(acc)); \ else if( val_tag(acc) == VAL_OBJECT ) \ ObjectOp(acc,*sp,id_rop) \ else \ OpError(#op); \ } else if( val_tag(acc) == VAL_FLOAT ) { \ if( val_tag(*sp) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_float(*sp),val_float(acc))); \ else if( val_tag(*sp) == VAL_INT32 ) \ acc = (int_val)alloc_float(fop(val_int32(*sp),val_float(acc))); \ else \ goto id_op##_next; \ } else if( val_tag(acc) == VAL_INT32 ) {\ if( val_tag(*sp) == VAL_INT32 ) \ acc = (int_val)alloc_best_int(val_int32(*sp) op val_int32(acc)); \ else if( val_tag(*sp) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_float(*sp),val_int32(acc))); \ else \ goto id_op##_next; \ } else { \ id_op##_next: \ if( val_tag(*sp) == VAL_OBJECT ) \ ObjectOpGen(*sp,acc,id_op,goto id_op##_next2) \ else { \ id_op##_next2: \ if( val_tag(acc) == VAL_OBJECT ) \ ObjectOp(acc,*sp,id_rop) \ else \ OpError(#op); \ } \ } \ *sp++ = ERASE; \ Next; extern int neko_stack_expand( int_val *sp, int_val *csp, neko_vm *vm ); extern value neko_append_int( neko_vm *vm, value str, int x, bool way ); extern value neko_append_strings( value s1, value s2 ); #define STACK_EXPAND { \ ACC_BACKUP; \ if( neko_stack_expand(sp,csp,vm) ) { \ sp = vm->sp; \ csp = vm->csp; \ } else \ val_throw(alloc_string("Stack Overflow")); \ ACC_RESTORE; \ } // optimized for sparse bits static int bitcount( unsigned int k ) { int b = 0; while( k ) { b++; k &= (k - 1); } return b; } static value neko_flush_stack( int_val *cspup, int_val *csp, value old ) { int ncalls = (int)((cspup - csp) / 4); value stack_trace = alloc_array(ncalls + ((old == NULL)?0:val_array_size(old))); value *st = val_array_ptr(stack_trace); neko_module *m; while( csp != cspup ) { m = (neko_module*)csp[4]; if( m ) { if( m->dbgidxs ) { unsigned int ppc = (unsigned int)((((int_val**)csp)[1]-2) - m->code); if( ppc < m->codesize ) { int idx =m->dbgidxs[ppc>>5].base + bitcount(m->dbgidxs[ppc>>5].bits >> (31 - (ppc & 31))); *st = val_array_ptr(m->dbgtbl)[idx]; } else *st = m->name; } else *st = m->name; } else *st = val_null; st++; if( old ) { *++csp = ERASE; *++csp = ERASE; *++csp = ERASE; *++csp = ERASE; } else csp += 4; } if( old ) { value *oldst = val_array_ptr(old); ncalls = val_array_size(old); while( ncalls-- ) *st++ = *oldst++; } return stack_trace; } EXTERN void neko_vm_dump_stack( neko_vm *vm ) { // we can't do any GC allocation here since we might hold the lock int_val *cspup = vm->csp; int_val *csp = vm->spmin - 1; while( csp != cspup ) { neko_module *m = (neko_module*)csp[4]; printf("Called from "); if( m ) { printf("%s ",val_string(m->name)); if( m->dbgidxs ) { int ppc = (int)((((int_val**)csp)[1]-2) - m->code); int idx = m->dbgidxs[ppc>>5].base + bitcount(m->dbgidxs[ppc>>5].bits >> (31 - (ppc & 31))); value s = val_array_ptr(m->dbgtbl)[idx]; if( val_is_string(s) ) printf("%s",val_string(s)); else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) printf("file %s line %d",val_string(val_array_ptr(s)[0]),val_int(val_array_ptr(s)[1])); else printf("???"); } } else printf("a C function"); csp += 4; printf("\n"); } fflush(stdout); } void neko_setup_trap( neko_vm *vm ) { vm->sp -= 6; if( vm->sp <= vm->csp && !neko_stack_expand(vm->sp,vm->csp,vm) ) val_throw(alloc_string("Stack Overflow")); vm->sp[0] = (int_val)alloc_int((int_val)(vm->csp - vm->spmin)); vm->sp[1] = (int_val)vm->vthis; vm->sp[2] = (int_val)vm->env; vm->sp[3] = address_int(vm->jit_val); vm->sp[4] = (int_val)val_null; vm->sp[5] = (int_val)alloc_int((int_val)vm->trap); vm->trap = vm->spmax - vm->sp; } void neko_process_trap( neko_vm *vm ) { // pop csp int_val *sp; int_val *trap; if( vm->trap == 0 ) return; trap = vm->spmax - vm->trap; sp = vm->spmin + val_int(trap[0]); vm->exc_stack = neko_flush_stack(vm->csp,sp,vm->exc_stack); vm->csp = sp; // restore state vm->vthis = (value)trap[1]; vm->env = (value)trap[2]; vm->jit_val = int_address(trap[3]); // pop sp sp = trap + 6; vm->trap = val_int(trap[5]); while( vm->sp < sp ) *vm->sp++ = ERASE; } int_val neko_interp_loop( neko_vm *VM_ARG, neko_module *m, int_val _acc, int_val *_pc ) { register int_val acc ACC_REG = _acc; register int_val *pc PC_REG = _pc; # ifdef VM_REG register neko_vm *vm VM_REG = VM_ARG; # endif # ifdef NEKO_THREADED static void *instructions[] = { # undef _NEKO_OPCODES_H # undef OPBEGIN # undef OPEND # undef OP # define OPBEGIN # define OPEND # define OP(x) &&Label##x # include "opcodes.h" }; if( m == NULL ) return (int_val)instructions; # endif register int_val *sp SP_REG = vm->sp; register int_val *csp CSP_REG = vm->csp; #ifdef NEKO_THREADED Next; {{ #else while( true ) { # ifdef NEKO_PROF if( *pc != Last ) pc[PROF_SIZE]++; # endif switch( *pc++ ) { #endif Instr(AccNull) acc = (int_val)val_null; Next; Instr(AccTrue) acc = (int_val)val_true; Next; Instr(AccFalse) acc = (int_val)val_false; Next; Instr(AccThis) acc = (int_val)vm->vthis; Next; Instr(AccInt) acc = *pc++; Next; Instr(AccInt32) acc = (int_val)alloc_int32((int)*pc++); Next; Instr(AccStack0) acc = *sp; Next; Instr(AccStack1) acc = sp[1]; Next; Instr(AccStack) acc = sp[*pc++]; Next; Instr(AccGlobal) acc = *(int_val*)(*pc++); Next; Instr(AccEnv) if( *pc >= val_array_size(vm->env) ) RuntimeError("Reading Outside Env",true); acc = (int_val)val_array_ptr(vm->env)[*pc++]; Next; Instr(AccField) if( val_is_object(acc) ) { value *f; value old = (value)acc, tacc = (value)acc; do { f = otable_find(&((vobject*)acc)->table,(field)*pc); if( f ) break; acc = (int_val)((vobject*)tacc)->proto; tacc = (value)acc; } while( acc ); if( f ) acc = (int_val)*f; else if( vm->resolver ) { BeginCall(); acc = (int_val)val_call2(vm->resolver,old,alloc_int(*pc)); EndCall(); } else acc = (int_val)val_null; } else InvalidFieldAccess(); pc++; Next; Instr(AccArray) if( val_is_int(acc) && val_is_array(*sp) ) { int k = val_int(acc); if( k < 0 || k >= val_array_size(*sp) ) acc = (int_val)val_null; else acc = (int_val)val_array_ptr(*sp)[k]; } else if( val_is_object(*sp) ) ObjectOp(*sp,acc,id_get) else if( val_is_int32(acc) && val_is_array(*sp) ) acc = (int_val)val_null; else RuntimeError("Invalid array access",false); *sp++ = ERASE; Next; Instr(AccIndex0) if( val_is_array(acc) ) { if( val_array_size(acc) ) acc = (int_val)*val_array_ptr(acc); else acc = (int_val)val_null; } else if( val_is_object(acc) ) ObjectOp(acc,alloc_int(0),id_get) else RuntimeError("Invalid array access",false); Next; Instr(AccIndex1) if( val_is_array(acc) ) { if( val_array_size(acc) > 1 ) acc = (int_val)val_array_ptr(acc)[1]; else acc = (int_val)val_null; } else if( val_is_object(acc) ) ObjectOp(acc,alloc_int(1),id_get) else RuntimeError("Invalid array access",false); Next; Instr(AccIndex) if( val_is_array(acc) ) { if( *pc < 0 || *pc >= val_array_size(acc) ) acc = (int_val)val_null; else acc = (int_val)val_array_ptr(acc)[*pc]; pc++; } else if( val_is_object(acc) ) ObjectOp(acc,alloc_int(*pc++),id_get) else RuntimeError("Invalid array access",true); Next; Instr(AccBuiltin) acc = *pc++; Next; Instr(SetStack) sp[*pc++] = acc; Next; Instr(SetGlobal) *(int_val*)(*pc++) = acc; Next; Instr(SetEnv) if( *pc >= val_array_size(vm->env) ) RuntimeError("Writing Outside Env",true); val_array_ptr(vm->env)[*pc++] = (value)acc; Next; Instr(SetField) if( val_is_object(*sp) ) { ACC_BACKUP; otable_replace(&((vobject*)*sp)->table,(field)*pc,(value)acc); ACC_RESTORE; } else InvalidFieldAccess(); *sp++ = ERASE; pc++; Next; Instr(SetArray) if( val_is_array(*sp) && val_is_int(sp[1]) ) { int k = val_int(sp[1]); if( k >= 0 && k < val_array_size(*sp) ) val_array_ptr(*sp)[k] = (value)acc; } else if( val_is_object(*sp) ) { value args[] = { (value)sp[1], (value)acc }; value f = val_field((value)*sp,id_set); if( f == val_null ) RuntimeError("Unsupported operation",false); PushInfos(); BeginCall(); val_callEx((value)*sp,f,args,2,NULL); EndCall(); PopInfos(false); acc = (int_val)args[1]; } else if( val_is_int32(sp[1]) && val_is_array(*sp) ) { // out range } else RuntimeError("Invalid array access",false); *sp++ = ERASE; *sp++ = ERASE; Next; Instr(SetIndex) if( val_is_array(*sp) ) { if( *pc >= 0 && *pc < val_array_size(*sp) ) val_array_ptr(*sp)[*pc] = (value)acc; } else if( val_is_object(*sp) ) { value args[] = { (value)alloc_int(*pc), (value)acc }; value f = val_field((value)*sp,id_set); if( f == val_null ) RuntimeError("Unsupported operation",true); PushInfos(); BeginCall(); val_callEx((value)*sp,f,args,2,NULL); EndCall(); PopInfos(false); acc = (int_val)args[1]; } else RuntimeError("Invalid array access",true); pc++; *sp++ = ERASE; Next; Instr(SetThis) vm->vthis = (value)acc; Next; Instr(Push) --sp; if( sp <= csp ) STACK_EXPAND; *sp = acc; Next; Instr(Pop) PopMacro(*pc++) Next; Instr(Apply) if( !val_is_function(acc) ) RuntimeError("$apply",true); { int fargs = val_fun_nargs(acc); if( fargs == *pc || fargs == VAR_ARGS ) goto do_call; if( *pc > fargs ) RuntimeError("$apply",true); { int i = fargs; ACC_BACKUP value env = alloc_array(fargs + 1); ACC_RESTORE; val_array_ptr(env)[0] = (value)acc; while( i > *pc ) val_array_ptr(env)[i--] = val_null; while( i ) { val_array_ptr(env)[i--] = (value)*sp; *sp++ = ERASE; } acc = (int_val)neko_alloc_apply((int)(fargs - *pc++),env); } } Next; Instr(TailCall) { int stack = (int)((*pc) >> 3); int nargs = (int)((*pc) & 7); int i = nargs; value cur_this = vm->vthis; stack -= nargs; sp += nargs; while( i > 0 ) { sp--; sp[stack] = *sp; i--; } while( stack-- > 0 ) *sp++ = ERASE; // preserve 'this' through the call PopInfos(true); DoCall(cur_this,nargs); } Next; Instr(Call) do_call: pc++; DoCall(vm->vthis,pc[-1]); Next; Instr(ObjCall) { value vtmp = (value)*sp; *sp++ = ERASE; pc++; DoCall(vtmp,pc[-1]); } Next; Instr(Jump) pc = (int_val*)*pc; Next; Instr(JumpIf) if( acc == (int_val)val_true ) pc = (int_val*)*pc; else pc++; Next; Instr(JumpIfNot) if( acc != (int_val)val_true ) pc = (int_val*)*pc; else pc++; Next; Instr(Trap) sp -= 6; if( sp <= csp ) STACK_EXPAND; sp[0] = (int_val)alloc_int((int_val)(csp - vm->spmin)); sp[1] = (int_val)vm->vthis; sp[2] = (int_val)vm->env; sp[3] = address_int(*pc); sp[4] = address_int(m); sp[5] = (int_val)alloc_int(vm->trap); vm->trap = vm->spmax - sp; pc++; Next; Instr(EndTrap) if( vm->spmax - vm->trap != sp ) RuntimeError("Invalid End Trap",false); vm->trap = val_int(sp[5]); PopMacro(6); Next; Instr(Ret) PopMacro( *pc++ ); PopInfos(true); Next; Instr(MakeEnv) { int n = (int)(*pc++); ACC_BACKUP int_val tmp = (int_val)alloc_array(n); ACC_RESTORE; while( n-- ) { val_array_ptr(tmp)[n] = (value)*sp; *sp++ = ERASE; } if( val_is_int(acc) || val_tag(acc) != VAL_FUNCTION ) RuntimeError("Invalid environment",false); acc = (int_val)neko_alloc_module_function(((vfunction*)acc)->module,(int_val)((vfunction*)acc)->addr,((vfunction*)acc)->nargs); ((vfunction*)acc)->env = (value)tmp; } Next; Instr(MakeArray) { int n = (int)*pc++; ACC_BACKUP value arr = alloc_array(n+1); ACC_RESTORE; while( n ) { val_array_ptr(arr)[n] = (value)*sp; *sp++ = ERASE; n--; } val_array_ptr(arr)[0] = (value)acc; acc = (int_val)arr; } Next; Instr(MakeArray2) { // similar to MakeArray but will keep a correct evaluation order int n = (int)*pc++; ACC_BACKUP value arr = alloc_array(n+1); ACC_RESTORE; if( n == 2 ) { n += 0; } val_array_ptr(arr)[n] = (value)acc; while( n ) { val_array_ptr(arr)[--n] = (value)*sp; *sp++ = ERASE; } acc = (int_val)arr; } Next; Instr(Bool) acc = (acc == (int_val)val_false || acc == (int_val)val_null || acc == 1)?(int_val)val_false:(int_val)val_true; Next; Instr(Not) acc = (acc == (int_val)val_false || acc == (int_val)val_null || acc == 1)?(int_val)val_true:(int_val)val_false; Next; Instr(IsNull) acc = (int_val)((acc == (int_val)val_null)?val_true:val_false); Next; Instr(IsNotNull) acc = (int_val)((acc == (int_val)val_null)?val_false:val_true); Next; Instr(Add) if( (acc & 1) && (*sp & 1) ) acc = (int_val)alloc_best_int(val_int(*sp) + val_int(acc)); else if( acc & 1 ) { if( val_tag(*sp) == VAL_FLOAT ) acc = (int_val)alloc_float(val_float(*sp) + val_int(acc)); else if( val_tag(*sp) == VAL_INT32 ) acc = (int_val)alloc_best_int(val_int32(*sp) + val_int(acc)); else if( val_short_tag(*sp) == VAL_STRING ) acc = (int_val)neko_append_int(vm,(value)*sp,val_int(acc),true); else if( val_tag(*sp) == VAL_OBJECT ) ObjectOp(*sp,acc,id_add) else OpError("+"); } else if( *sp & 1 ) { if( val_tag(acc) == VAL_FLOAT ) acc = (int_val)alloc_float(val_int(*sp) + val_float(acc)); else if( val_tag(acc) == VAL_INT32 ) acc = (int_val)alloc_best_int(val_int(*sp) + val_int32(acc)); else if( val_short_tag(acc) == VAL_STRING ) acc = (int_val)neko_append_int(vm,(value)acc,val_int(*sp),false); else if( val_tag(acc) == VAL_OBJECT ) ObjectOp(acc,*sp,id_radd) else OpError("+"); } else if( val_tag(acc) == VAL_FLOAT ) { if( val_tag(*sp) == VAL_FLOAT ) acc = (int_val)alloc_float(val_float(*sp) + val_float(acc)); else if( val_tag(*sp) == VAL_INT32 ) acc = (int_val)alloc_float(val_int32(*sp) + val_float(acc)); else goto add_next; } else if( val_tag(acc) == VAL_INT32 ) { if( val_tag(*sp) == VAL_INT32 ) acc = (int_val)alloc_best_int(val_int32(*sp) + val_int32(acc)); else if( val_tag(*sp) == VAL_FLOAT ) acc = (int_val)alloc_float(val_float(*sp) + val_int32(acc)); else goto add_next; } else { add_next: if( val_tag(*sp) == VAL_OBJECT ) ObjectOpGen(*sp,acc,id_add,goto add_2) else { add_2: if( val_tag(acc) == VAL_OBJECT ) ObjectOpGen(acc,*sp,id_radd,goto add_3) else { add_3: if( val_short_tag(acc) == VAL_STRING || val_short_tag(*sp) == VAL_STRING ) { ACC_BACKUP buffer b = alloc_buffer(NULL); BeginCall(); val_buffer(b,(value)*sp); ACC_RESTORE; val_buffer(b,(value)acc); EndCall(); acc = (int_val)buffer_to_string(b); } else OpError("+"); } } } *sp++ = ERASE; Next; Instr(Sub) NumberOp(-,SUB,id_sub,id_rsub) Instr(Mult) NumberOp(*,MULT,id_mult,id_rmult) Instr(Div) if( val_is_number(acc) && val_is_number(*sp) ) acc = (int_val)alloc_float( ((tfloat)val_number(*sp)) / val_number(acc) ); else if( val_is_object(*sp) ) ObjectOpGen(*sp,acc,id_div,goto div_next) else { div_next: if( val_is_object(acc) ) ObjectOp(acc,*sp,id_rdiv) else OpError("/"); } *sp++ = ERASE; Next; Instr(Mod) if( (acc == 1 || (val_is_int32(acc) && val_int32(acc)==0)) && val_is_any_int(*sp) ) OpError("%"); NumberOp(%,fmod,id_mod,id_rmod); Instr(Shl) IntOp(<<); Instr(Shr) IntOp(>>); Instr(UShr) if( (acc & 1) && (*sp & 1) ) acc = (int_val)alloc_best_int(((unsigned int)val_int(*sp)) >> val_int(acc)); else if( val_is_any_int(acc) && val_is_any_int(*sp) ) acc = (int_val)alloc_best_int(((unsigned int)val_any_int(*sp)) >> val_any_int(acc)); else OpError(">>>"); *sp++ = ERASE; Next; Instr(Or) IntOp(|); Instr(And) IntOp(&); Instr(Xor) IntOp(^); Instr(Eq) Test(==) Instr(Neq) BeginCall(); acc = (int_val)((val_compare((value)*sp,(value)acc) == 0)?val_false:val_true); EndCall(); *sp++ = ERASE; Next; Instr(Lt) Test(<) Instr(Lte) Test(<=) Instr(Gt) Test(>) Instr(Gte) Test(>=) Instr(TypeOf) acc = (int_val)(val_is_int(acc) ? alloc_int(1) : NEKO_TYPEOF[val_short_tag(acc)]); Next; Instr(Compare) BeginCall(); acc = (int_val)val_compare((value)*sp,(value)acc); EndCall(); acc = (int_val)((acc == invalid_comparison)?val_null:alloc_int(acc)); *sp++ = ERASE; Next; Instr(PhysCompare) acc = (int_val)(( *sp > acc )?alloc_int(1):(( *sp < acc )?alloc_int(-1):alloc_int(0))); *sp++ = ERASE; Next; Instr(Hash) if( val_is_string(acc) ) { BeginCall(); acc = (int_val)alloc_int( val_id(val_string(acc)) ); } else RuntimeError("$hash",false); Next; Instr(New) BeginCall(); acc = (int_val)alloc_object((value)acc); Next; Instr(JumpTable) if( val_is_int(acc) && ((unsigned)acc) < ((unsigned)*pc) ) pc += acc; else pc += *pc + 1; Next; Instr(Loop) // space for GC/Debug Next; Instr(Last) goto end; #ifdef NEKO_VCC default: __assume(0); #endif }} end: vm->sp = sp; vm->csp = csp; return acc; } int_val *neko_get_ttable() { # ifdef NEKO_THREADED return (int_val*)neko_interp_loop(NULL,NULL,0,NULL); # else return NULL; # endif } value neko_interp( neko_vm *vm, void *_m, int_val acc, int_val *pc ) { int_val *sp, *csp, *trap; int_val init_sp = vm->spmax - vm->sp; neko_module *m = (neko_module*)_m; jmp_buf old; memcpy(&old,&vm->start,sizeof(jmp_buf)); if( setjmp(vm->start) ) { acc = (int_val)vm->vthis; // if uncaught or outside init stack, reraise if( vm->trap == 0 || vm->trap <= init_sp ) { char **tmp; memcpy(&vm->start,&old,sizeof(jmp_buf)); tmp = (char**)vm->start; if( *tmp == jit_handle_trap ) ((jit_handle)jit_handle_trap)(vm); else longjmp(vm->start,1); } trap = vm->spmax - vm->trap; if( trap < vm->sp ) { // trap outside stack vm->trap = 0; val_throw(alloc_string("Invalid Trap")); } // pop csp csp = vm->spmin + val_int(trap[0]); vm->exc_stack = neko_flush_stack(vm->csp,csp,vm->exc_stack); vm->csp = csp; // restore state vm->vthis = (value)trap[1]; vm->env = (value)trap[2]; pc = int_address(trap[3]); m = (neko_module*)int_address(trap[4]); // pop sp sp = trap + 6; vm->trap = val_int(trap[5]); while( vm->sp < sp ) *vm->sp++ = ERASE; // jit return ? if( val_is_kind(m,neko_kind_module) ) { m = (neko_module*)val_data(m); pc = (int_val*)((((int_val)pc)>>1) + (int_val)m->jit); acc = ((jit_prim)jit_boot_seq)(vm,pc,(value)acc,m); return (value)acc; } } if( m->jit != NULL && m->code == pc ) acc = ((jit_prim)jit_boot_seq)(vm,m->jit,(value)acc,m); else acc = neko_interp_loop(vm,m,acc,pc); memcpy(&vm->start,&old,sizeof(jmp_buf)); return (value)acc; } /* ************************************************************************ */ neko-2-2-0/vm/jit_x86.c000066400000000000000000001676711321613172000145440ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "vm.h" #include "neko_mod.h" #include "objtable.h" #include #include #include #include #ifdef NEKO_POSIX # include # include # define USE_MMAP #endif #define tmp_alloc(size) malloc(size) #define tmp_free(ptr) free(ptr) #ifdef NEKO_MAC #define STACK_ALIGN #endif #if defined(NEKO_WINDOWS) && defined(_DEBUG_XX) #define STACK_ALIGN #define STACK_ALIGN_DEBUG #endif #define TAG_MASK ((1<pos); tmp_free(ctx->baseptr); failure("JIT error"); } #define CONST(v) ((int)(int_val)(v)) #define PATCH_JUMP(local) if( local != NULL ) { \ int delta = (int)((int_val)buf.p - ((int_val)local + 1)); \ if( sizeof(*local) == sizeof(int) ) \ *local = delta - 3; \ else { \ if( delta > 127 || delta < -127 ) \ ERROR; \ *local = (char)delta; \ } \ } \ #define FIELD(n) ((n) * 4) #define VMFIELD(f) ((int)(int_val)&((neko_vm*)0)->f) #define FUNFIELD(f) ((int)(int_val)&((vfunction*)0)->f) #define POS() ((int)((int_val)ctx->buf.p - (int_val)ctx->baseptr)) #define GET_PC() CONST(ctx->module->code + ctx->curpc) #define INIT_BUFFER register jit_buffer buf = ctx->buf #define END_BUFFER ctx->buf = buf #define MOD_RM(mod,reg,rm) B((mod << 6) | (reg << 3) | rm) #define SIB MOD_RM #define IS_SBYTE(c) ( (c) >= -128 && (c) < 128 ) #define OP_RM(op,mod,reg,rm) { B(op); MOD_RM(mod,reg,rm); } #define OP_ADDR(op,addr,reg,rm) { B(op); \ MOD_RM(((addr) == 0 && reg != Ebp)?0:(IS_SBYTE(addr)?1:2),rm,reg); \ if( reg == Esp ) B(0x24); \ if( (addr) == 0 && reg != Ebp ) {} \ else if IS_SBYTE(addr) B(addr); \ else W(addr); } // OPCODES : // _r : register // _c : constant // _b : 8-bit constant // _a : [constant] // _i : [reg] // _p : [reg + constant:idx] // _x : [reg + reg:idx * mult] #define XRet() B(0xC3) #define XMov_rr(dst,src) OP_RM(0x8B,3,dst,src) #define XMov_rc(dst,cst) B(0xB8+(dst)); W(cst) #define XMov_rp(dst,reg,idx) OP_ADDR(0x8B,idx,reg,dst) #define XMov_ra(dst,addr) OP_RM(0x8B,0,dst,5); W(addr) #define XMov_rx(dst,r,idx,mult) OP_RM(0x8B,0,dst,4); SIB(Mult##mult,idx,r) #define XMov_pr(dst,idx,src) OP_ADDR(0x89,idx,dst,src) #define XMov_pc(dst,idx,c) OP_ADDR(0xC7,idx,dst,0); W(c) #define XMov_ar(addr,reg) B(0x3E); if( reg == Eax ) { B(0xA3); } else { OP_RM(0x89,0,reg,5); }; W(addr) #define XMov_xr(r,idx,mult,src) OP_RM(0x89,0,src,4); SIB(Mult##mult,idx,r) #define XCall_r(r) OP_RM(0xFF,3,2,r) #define XCall_m_debug(v) { \ int *l; \ XMov_rr(TMP,Ebp); \ XSub_rr(TMP,Esp); \ XAnd_rc(TMP,15); \ XCmp_rc(TMP,0); \ XJump(JEq,l); \ XShr_rc(TMP,2); \ XPush_r(TMP); \ XPush_c(CONST(__LINE__)); \ XMov_rc(TMP,CONST(debug_method_call)); \ XCall_r(TMP); \ PATCH_JUMP(l); \ XMov_rc(TMP,CONST(v)); \ XCall_r(TMP); \ } #define XCall_m_real(v) XMov_rc(TMP,CONST(v)); XCall_r(TMP); #ifdef STACK_ALIGN_DEBUG # define XCall_m XCall_m_debug #else # define XCall_m XCall_m_real #endif #define XCall_d(delta) B(0xE8); W(delta) #define XPush_r(r) B(0x50+(r)) #define XPush_c(cst) B(0x68); W(cst) #define XPush_p(reg,idx) OP_ADDR(0xFF,idx,reg,6) #define XAdd_rc(reg,cst) if IS_SBYTE(cst) { OP_RM(0x83,3,0,reg); B(cst); } else { OP_RM(0x81,3,0,reg); W(cst); } #define XAdd_rr(dst,src) OP_RM(0x03,3,dst,src) #define XSub_rc(reg,cst) if IS_SBYTE(cst) { OP_RM(0x83,3,5,reg); B(cst); } else { OP_RM(0x81,3,5,reg); W(cst); } #define XSub_rr(dst,src) OP_RM(0x2B,3,dst,src) #define XCmp_rr(r1,r2) OP_RM(0x3B,3,r1,r2) #define XCmp_rc(reg,cst) if( reg == Eax ) { B(0x3D); } else { OP_RM(0x81,3,7,reg); }; W(cst) #define XCmp_rb(reg,byte) OP_RM(0x83,3,7,reg); B(byte) #define XJump(how,local) if( (how) == JAlways ) { B(0xE9); } else { B(0x0F); B(how); }; local = buf.i; W(0) #define XJump_near(local) B(0xEB); local = buf.c; B(0) #define XJump_r(reg) OP_RM(0xFF,3,4,reg) #define XPop_r(reg) B(0x58 + (reg)) #define XTest_rc(r,cst) if( r == Eax ) { B(0xA9); W(cst); } else { B(0xF7); MOD_RM(3,0,r); W(cst); } #define XTest_rr(r,src) B(0x85); MOD_RM(3,r,src) #define XAnd_rc(r,cst) if( r == Eax ) { B(0x25); W(cst); } else { B(0x81); MOD_RM(3,4,r); W(cst); } #define XAnd_rr(r,src) B(0x23); MOD_RM(3,r,src) #define XOr_rc(r,cst) if( r == Eax ) { B(0x0D); W(cst); } else { B(0x81); MOD_RM(3,1,r); W(cst); } #define XOr_rr(r,src) B(0x0B); MOD_RM(3,r,src) #define XXor_rc(r,cst) if( r == Eax ) { B(0x35); W(cst); } else { B(0x81); MOD_RM(3,6,r); W(cst); } #define XXor_rr(r,src) B(0x33); MOD_RM(3,r,src) #define shift_r(r,spec) B(0xD3); MOD_RM(3,spec,r); #define shift_c(r,n,spec) if( (n) == 1 ) { B(0xD1); MOD_RM(3,spec,r); } else { B(0xC1); MOD_RM(3,spec,r); B(n); } #define XShl_rr(r,src) if( src != Ecx ) ERROR; shift_r(r,4) #define XShl_rc(r,n) shift_c(r,n,4) #define XShr_rr(r,src) if( src != Ecx ) ERROR; shift_r(r,7) #define XShr_rc(r,n) shift_c(r,n,7) #define XUShr_rr(r,src) if( src != Ecx ) ERROR; shift_r(r,5) #define XUShr_rc(r,n) shift_c(r,n,5) #define XIMul_rr(dst,src) B(0x0F); B(0xAF); MOD_RM(3,dst,src) #define XIDiv_r(r) B(0xF7); MOD_RM(3,7,r) #define XCdq() B(0x99); // FPU #define XFAddp() B(0xDE); B(0xC1) #define XFSubp() B(0xDE); B(0xE9) #define XFMulp() B(0xDE); B(0xC9) #define XFDivp() B(0xDE); B(0xF9) #define XFStp_i(r) B(0xDD); MOD_RM(0,3,r); if( r == Esp ) B(0x24) #define XFLd_i(r) B(0xDD); MOD_RM(0,0,r); if( r == Esp ) B(0x24) #define XFILd_i(r) B(0xDB); MOD_RM(0,0,r); if( r == Esp ) B(0x24) #define is_int(r,flag,local) { XTest_rc(r,1); XJump((flag)?JNeq:JEq,local); } #ifdef STACK_ALIGN # define stack_pad(n) stack_push(Esp,n) # define stack_pop_pad(n,n2) stack_pop(Esp,((n) + (n2))) #else # define stack_pad(n) # define stack_pop_pad(n,n2) stack_pop(Esp,(n)) #endif #define stack_push(r,n) \ if( (n) != 0 ) { \ if( (r) == CSP ) { \ XAdd_rc(r,(n) * 4); \ } else { \ XSub_rc(r,(n) * 4); \ } \ } #define stack_pop(r,n) \ if( (n) != 0 ) { \ if( (r) == CSP ) { \ XSub_rc(r,(n) * 4); \ } else { \ XAdd_rc(r,(n) * 4); \ } \ } #define begin_call() { XMov_pr(VM,VMFIELD(sp),SP); XMov_pr(VM,VMFIELD(csp),CSP); } #define end_call() { XMov_rp(SP,VM,VMFIELD(sp)); XMov_rp(CSP,VM,VMFIELD(csp)); } #define label(code) { XMov_rc(TMP2,CONST(code)); XCall_r(TMP2); } #define todo(str) { int *loop; XMov_rc(TMP2,CONST(str)); XJump(JAlways,loop); *loop = -5; } #define pop(n) if( (n) != 0 ) { \ int i = (n); \ while( i-- > 0 ) { \ XMov_pc(SP,FIELD(i),0); \ } \ stack_pop(SP,n); \ } #define pop_loop(n) { \ char *start; \ int *loop; \ XMov_rc(TMP,n); \ start = buf.c; \ XMov_pc(SP,FIELD(0),0); \ stack_pop(SP,1); \ XSub_rc(TMP,1); \ XCmp_rc(TMP,0); \ XJump(JNeq,loop); \ *loop = (int)(start - buf.c); \ } #ifdef STACK_ALIGN # define PAD_OPT(x) (x) #else # define PAD_OPT(x) 0 #endif #define runtime_error(msg_id,in_label) { \ if( in_label ) { stack_pad(2); } else { stack_pad(1); } \ XPush_c(CONST(strings[msg_id])); \ if( in_label ) { \ XMov_rp(TMP2,Esp,FIELD(2+PAD_OPT(2))); \ XPush_r(TMP2); \ } else { \ XPush_c(GET_PC()); \ } \ label(code->runtime_error); \ } #define get_var_r(reg,v) { \ switch( v ) { \ case VThis: \ XMov_rp(reg,VM,VMFIELD(vthis)); \ break; \ case VEnv: \ XMov_rp(reg,VM,VMFIELD(env)); \ break; \ case VModule: \ XMov_rp(reg,VM,VMFIELD(jit_val)); \ break; \ case VVm: \ XMov_rr(reg,VM); \ break; \ case VSpMax: \ XMov_rp(reg,VM,VMFIELD(spmax)); \ break; \ case VTrap: \ XMov_rp(reg,VM,VMFIELD(trap)); \ break; \ default: \ ERROR; \ break; \ } \ } #define get_var_p(reg,idx,v) { \ switch( v ) { \ case VThis: \ XMov_rp(TMP,VM,VMFIELD(vthis)); \ XMov_pr(reg,idx,TMP); \ break; \ case VEnv: \ XMov_rp(TMP,VM,VMFIELD(env)); \ XMov_pr(reg,idx,TMP); \ break; \ case VModule: \ XMov_rp(TMP,VM,VMFIELD(jit_val)); \ XMov_pr(reg,idx,TMP); \ break; \ case VVm: \ XMov_pr(reg,idx,VM); \ break; \ case VSpMax: \ XMov_rp(TMP,VM,VMFIELD(spmax)); \ XMov_pr(reg,idx,TMP); \ break; \ case VTrap: \ XMov_rp(TMP,VM,VMFIELD(trap)); \ XMov_pr(reg,idx,TMP); \ break; \ default: \ ERROR; \ break; \ } \ } #define set_var_r(v,reg) { \ switch( v ) { \ case VThis: \ XMov_pr(VM,VMFIELD(vthis),reg); \ break; \ case VEnv: \ XMov_pr(VM,VMFIELD(env),reg); \ break; \ case VTrap: \ XMov_pr(VM,VMFIELD(trap),reg); \ break; \ case VModule: \ XMov_pr(VM,VMFIELD(jit_val),reg); \ break; \ default: \ ERROR; \ break; \ } \ } #define set_var_p(v,reg,idx) { \ switch( v ) { \ case VThis: \ XMov_rp(TMP,reg,idx); \ XMov_pr(VM,VMFIELD(vthis),TMP); \ break; \ case VEnv: \ XMov_rp(TMP,reg,idx); \ XMov_pr(VM,VMFIELD(env),TMP); \ break; \ case VTrap: \ XMov_rp(TMP,reg,idx); \ XMov_pr(VM,VMFIELD(trap),TMP); \ break; \ case VModule: \ XMov_rp(TMP,reg,idx); \ XMov_pr(VM,VMFIELD(jit_val),TMP); \ break; \ default: \ ERROR; \ break; \ } \ } #define jump(how,targ) { \ jlist *j = (jlist*)alloc(sizeof(jlist)); \ void *jcode; \ j->target = (int)((int_val*)(int_val)(targ) - ctx->module->code); \ j->next = ctx->jumps; \ ctx->jumps = j; \ XJump(how,jcode); \ j->pos = (int)((int_val)jcode - (int_val)ctx->baseptr); \ } #define setup_before_call(mode,is_callb) { \ push_infos(is_callb?CALLBACK:PC_ARG); \ if( !is_callb ) { XPush_r(ACC); } \ if( mode == THIS_CALL ) { \ set_var_p(VThis,SP,FIELD(0)); \ pop(1); \ } \ set_var_p(VEnv,ACC,FUNFIELD(env)); \ } #define restore_after_call(nargs,pad) { \ int *jok; \ XCmp_rc(ACC,0); \ XJump(JNeq,jok); \ XMov_rp(ACC,Esp,FIELD(nargs+PAD_OPT(pad))); \ XMov_rp(ACC,ACC,FUNFIELD(module)); \ stack_pad(-1); \ XPush_r(ACC); \ XCall_m(val_throw); \ PATCH_JUMP(jok); \ stack_pop_pad(1+nargs,pad); \ pop_infos(); \ } #define NARGS (CALL_MAX_ARGS + 1) #define MAX_ENV 8 typedef struct { char *boot; char *stack_expand; char *runtime_error; char *call_normal_jit[NARGS]; char *call_this_jit[NARGS]; char *call_tail_jit[NARGS]; char *call_normal_prim[NARGS]; char *call_this_prim[NARGS]; char *call_tail_prim[NARGS]; char *call_normal_fun[NARGS]; char *call_this_fun[NARGS]; char *call_tail_fun[NARGS]; char *make_env[MAX_ENV]; char *make_env_n; char *oo_get; char *oo_set; char *handle_trap; char *invalid_access; } jit_code; char *jit_boot_seq = NULL; char *jit_handle_trap = NULL; static jit_code *code; static value *strings; static const char *cstrings[] = { "Stack overflow", // 0 "Reading Outside Env", // 1 "Writing Outside Env", // 2 "Invalid call", // 3 "Invalid array access", // 4 "Invalid field access", // 5 "Invalid environment", // 6 "Invalid operation (%)", // 7 "$apply", // 8 "Invalid End Trap", // 9 "$hash", // 10 }; #define DEFINE_PROC(p,arg) ctx->buf = buf; jit_##p(ctx,arg); buf = ctx->buf #define push_infos(arg) DEFINE_PROC(push_infos,arg) #define test(arg) DEFINE_PROC(test,arg) #define call(mode,nargs) ctx->buf = buf; jit_call(ctx,mode,nargs); buf = ctx->buf #define number_op(arg) DEFINE_PROC(number_op,arg) #define array_access(p) DEFINE_PROC(array_access,p) #define int_op(arg) DEFINE_PROC(int_op,arg) #define best_int() DEFINE_PROC(best_int,0) #ifdef STACK_ALIGN_DEBUG #include static void debug_method_call( int line, int stack ) { printf("Stack align error line %d (%d)\n" , line ,stack); exit(-1); } #endif #ifdef NEKO_JIT_DEBUG static void val_print_2( value v ) { val_print(alloc_string(" ")); val_print(v); } static void val_print_3( value v ) { val_print_2(v); val_print(alloc_string("\n")); } #endif static jit_ctx *jit_init_context( void *ptr, int size ) { jit_ctx *c = (jit_ctx*)alloc(sizeof(jit_ctx)); c->size = size; c->baseptr = ptr; c->buf.p = ptr; c->pos = NULL; c->curpc = 0; c->debug_wait = 0; c->jumps = NULL; c->traps = NULL; return c; } static void jit_finalize_context( jit_ctx *ctx ) { jlist *l; int nbytes = POS(); if( nbytes == 0 || nbytes > ctx->size ) *(int*)0xAABBCC = 0; l = ctx->jumps; while( l != NULL ) { *(int*)((char*)ctx->baseptr + l->pos) = ctx->pos[l->target] - (l->pos + 4); l = l->next; } l = ctx->traps; while( l != NULL ) { *(int*)((char*)ctx->baseptr + l->pos) = ctx->pos[l->target] + (int)(int_val)ctx->baseptr; l = l->next; } } static void jit_push_infos( jit_ctx *ctx, enum PushInfosMode callb ) { INIT_BUFFER; stack_push(CSP,4); if( callb == CALLBACK ) { XMov_pc(CSP,FIELD(-3),CONST(callback_return)); get_var_p(CSP,FIELD(-2),VEnv); get_var_p(CSP,FIELD(-1),VThis); XMov_pc(CSP,FIELD(0),0); } else { if( callb == PC_CUR ) { XMov_pc(CSP,FIELD(-3),GET_PC()); } else { // PC_ARG : on the stack XMov_rp(TMP2,Esp,FIELD(1)); XMov_pr(CSP,FIELD(-3),TMP2); } get_var_p(CSP,FIELD(-2),VEnv); get_var_p(CSP,FIELD(-1),VThis); get_var_p(CSP,FIELD(0),VModule) } END_BUFFER; } static void jit_best_int( jit_ctx *ctx, int _ ) { int *wrap; char *jend; INIT_BUFFER; XMov_rr(TMP,ACC); XShl_rc(ACC,1); XJump(JOverflow,wrap); XOr_rc(ACC,1); XJump_near(jend); PATCH_JUMP(wrap); XPush_r(TMP); XCall_m(alloc_int32); stack_pop(Esp,1); PATCH_JUMP(jend); END_BUFFER; } #define pop_infos() { \ set_var_p(VModule,CSP,FIELD(0)); \ set_var_p(VThis,CSP,FIELD(-1)); \ set_var_p(VEnv,CSP,FIELD(-2)); \ XMov_pc(CSP,FIELD(0),0); \ XMov_pc(CSP,FIELD(-1),0); \ XMov_pc(CSP,FIELD(-2),0); \ XMov_pc(CSP,FIELD(-3),0); \ stack_pop(CSP,4); \ } static void jit_boot( jit_ctx *ctx, void *_ ) { INIT_BUFFER; XPush_r(Ebp); XPush_r(Ebx); XPush_r(Esi); # ifdef STACK_ALIGN_DEBUG XMov_rr(Ebp,Esp); // ALIGNED STACK # endif XPush_r(Edi); XMov_rp(VM,Esp,FIELD(5)); get_var_r(TMP,VModule); XPush_r(TMP); set_var_p(VModule,Esp,FIELD(9)); XMov_rp(TMP,Esp,FIELD(7)); XMov_rp(ACC,Esp,FIELD(8)); end_call(); XCall_r(TMP); begin_call(); XPop_r(TMP); set_var_r(VModule,TMP); XPop_r(Edi); XPop_r(Esi); XPop_r(Ebx); XPop_r(Ebp); XRet(); END_BUFFER; } static void jit_trap( jit_ctx *ctx, int n ) { INIT_BUFFER; XMov_rp(VM,Esp,FIELD(1)); get_var_r(Ebp,VThis); // restore vm stack_pad(3); XPush_r(VM); XCall_m(neko_process_trap); stack_pop_pad(1,3); // restore registers end_call(); XMov_rr(ACC,Ebp); XMov_rp(Ebp,VM,VMFIELD(start)+FIELD(1)); XMov_rp(Esp,VM,VMFIELD(start)+FIELD(2)); XMov_rp(TMP2,VM,VMFIELD(start)+FIELD(3)); // restore vm jmp_buf XPop_r(TMP); XMov_pr(VM,VMFIELD(start)+FIELD(3),TMP); XPop_r(TMP); XMov_pr(VM,VMFIELD(start)+FIELD(2),TMP); XPop_r(TMP); XMov_pr(VM,VMFIELD(start)+FIELD(1),TMP); XPop_r(TMP); XMov_pr(VM,VMFIELD(start),TMP); XPush_r(TMP2); XRet(); END_BUFFER; } static void jit_stack_expand( jit_ctx *ctx, int _ ) { int *jresize, *jdone; int max = MAX_STACK_PER_FUNCTION; INIT_BUFFER; stack_push(CSP,max); XCmp_rr(SP,CSP); XJump(JLt,jresize); stack_pop(CSP,max); XRet(); PATCH_JUMP(jresize); stack_pop(CSP,max); XPush_r(ACC); XPush_r(VM); XPush_r(CSP); XPush_r(SP); XCall_m(neko_stack_expand); XCmp_rb(ACC,0); XJump(JNeq,jdone); stack_pad(-1); XPush_c(CONST(strings[0])); // Stack overflow XCall_m(val_throw); PATCH_JUMP(jdone); XMov_rp(ACC,Esp,FIELD(3)); end_call(); stack_pop(Esp,4); XRet(); END_BUFFER; } static void jit_runtime_error( jit_ctx *ctx, void *unused ) { INIT_BUFFER; push_infos(PC_ARG); // pc begin_call(); XMov_rp(TMP,Esp,FIELD(2)); // msg on stack XPush_r(TMP); XCall_m(val_throw); END_BUFFER; } static void jit_invalid_access( jit_ctx *ctx, int _ ) { INIT_BUFFER; int *jnext; // if( val_field_name(f) == val_null ) RuntimeError("Invalid field access") stack_pad(1); XMov_rp(TMP,Esp,FIELD(2)); // field XPush_r(TMP); XCall_m(val_field_name); stack_pop_pad(1,1); XCmp_rc(ACC,CONST(val_null)); XJump(JNeq,jnext); runtime_error(5,true); // else { // b = alloc_buffer("Invalid field access : "); PATCH_JUMP(jnext); XPush_r(ACC); XPush_c(CONST("Invalid field access : ")); XCall_m(alloc_buffer); stack_pop(Esp,1); // val_buffer(b,v); XPush_r(ACC); XCall_m(val_buffer); // buffer_to_string(b); XCall_m(buffer_to_string); stack_pop(Esp,2); push_infos(PC_ARG); // pc begin_call(); XPush_r(ACC); XCall_m(val_throw); END_BUFFER; } static void jit_test( jit_ctx *ctx, int how ) { INIT_BUFFER; int *jnot1, *jnot2; char *jend; // call val_compare(sp[0],acc) XPush_r(ACC); XMov_rp(TMP,SP,FIELD(0)); XPush_r(TMP); begin_call(); XCall_m(val_compare); end_call(); stack_pop(Esp,2); pop(1); // test ok and != invalid_comparison XCmp_rc(ACC,0); XJump(how,jnot1); XCmp_rc(ACC,invalid_comparison); XJump(JEq,jnot2); XMov_rc(ACC,CONST(val_true)); XJump_near(jend); PATCH_JUMP(jnot1); PATCH_JUMP(jnot2); XMov_rc(ACC,CONST(val_false)); PATCH_JUMP(jend); END_BUFFER; } static void jit_call( jit_ctx *ctx, int mode, int nargs ) { INIT_BUFFER; int *jerr, *jother, *jerr2; char *jend1, *jend2, *jend3; // if( is_int ) : error is_int(ACC,1,jerr); // if( type == jit ) XMov_rp(TMP,ACC,FUNFIELD(t)); XCmp_rb(TMP,VAL_JITFUN); XJump(JNeq,jother); XPush_c(GET_PC()); switch( mode ) { case NORMAL: label(code->call_normal_jit[nargs]); break; case THIS_CALL: label(code->call_this_jit[nargs]); break; case TAIL_CALL: label(code->call_tail_jit[nargs]); break; } if( mode == TAIL_CALL ) jend1 = NULL; else { XJump_near(jend1); } // else if( type == prim ) PATCH_JUMP(jother); XCmp_rb(TMP,VAL_PRIMITIVE); XJump(JNeq,jother); XPush_c(GET_PC()); switch( mode ) { case NORMAL: label(code->call_normal_prim[nargs]); break; case THIS_CALL: label(code->call_this_prim[nargs]); break; case TAIL_CALL: label(code->call_tail_prim[nargs]); break; } XJump_near(jend2); // else if( type == function ) PATCH_JUMP(jother); XCmp_rb(TMP,VAL_FUNCTION); XJump(JNeq,jerr2); XPush_c(GET_PC()); switch( mode ) { case NORMAL: label(code->call_normal_fun[nargs]); break; case THIS_CALL: label(code->call_this_fun[nargs]); break; case TAIL_CALL: label(code->call_tail_fun[nargs]); break; } XJump_near(jend3); // else error PATCH_JUMP(jerr); PATCH_JUMP(jerr2); runtime_error(3,false); // Invalid call // end PATCH_JUMP(jend1); PATCH_JUMP(jend2); PATCH_JUMP(jend3); stack_pop(Esp,1); // pushed pc END_BUFFER; } static void jit_call_jit( jit_ctx *ctx, int nargs, int mode ) { INIT_BUFFER; int *jerr; // check arg count XMov_rp(TMP,ACC,FUNFIELD(nargs)); XCmp_rb(TMP,nargs); XJump(JNeq,jerr); if( mode == TAIL_CALL ) { // pop PC and EIP from the stack stack_pop(Esp,2); set_var_p(VModule,ACC,FUNFIELD(module)); set_var_p(VEnv,ACC,FUNFIELD(env)); XMov_rp(TMP,ACC,FUNFIELD(addr)); XJump_r(TMP); } else { push_infos(PC_ARG); set_var_p(VModule,ACC,FUNFIELD(module)); set_var_p(VEnv,ACC,FUNFIELD(env)); if( mode == THIS_CALL ) { set_var_p(VThis,SP,FIELD(0)); pop(1); } XMov_rp(TMP,ACC,FUNFIELD(addr)); stack_pad(1); XCall_r(TMP); stack_pad(-1); pop_infos(); XRet(); } PATCH_JUMP(jerr); runtime_error(3,true); // Invalid call END_BUFFER; } static void jit_call_prim( jit_ctx *ctx, int nargs, int mode ) { INIT_BUFFER; int *jvararg, *jerr; int i; # ifdef STACK_ALIGN int pad_size = 4 - ((2+nargs)%4); # endif // check arg count XMov_rp(TMP,ACC,FUNFIELD(nargs)); XCmp_rb(TMP,nargs); XJump(JNeq,jvararg); // push args from VMSP to PROCSP setup_before_call(mode,false); stack_pad(pad_size); for(i=0;isp,vm->csp,vm) ) val_throw(alloc_string("Stack Overflow")) #define ERASE 0 #define ACC_BACKUP #define ACC_RESTORE #define PushInfos() \ if( vm->csp + 4 >= vm->sp ) STACK_EXPAND; \ *++vm->csp = (int_val)pc; \ *++vm->csp = (int_val)vm->env; \ *++vm->csp = (int_val)vm->vthis; \ *++vm->csp = (int_val)vm->jit_val; #define PopInfos(restpc) \ vm->jit_val = (void*)*vm->csp; \ *vm->csp-- = ERASE; \ vm->vthis = (value)*vm->csp; \ *vm->csp-- = ERASE; \ vm->env = (value)*vm->csp; \ *vm->csp-- = ERASE; \ if( restpc ) pc = (int)*vm->csp; \ *vm->csp-- = ERASE; #define BeginCall() #define EndCall() #define RuntimeError(err) { PushInfos(); BeginCall(); val_throw(alloc_string(err)); } #define ObjectOpGen(obj,param,id,err) { \ value _o = (value)obj; \ value _arg = (value)param; \ value _f = val_field(_o,id); \ if( _f == val_null ) { \ err; \ } else { \ PushInfos(); \ BeginCall(); \ acc = (int_val)val_callEx(_o,_f,&_arg,1,NULL); \ EndCall(); \ PopInfos(false); \ } \ } #define ObjectOp(obj,param,id) ObjectOpGen(obj,param,id,RuntimeError("Unsupported operation")) #define OpError(op) RuntimeError("Invalid operation (" op ")") static int_val generic_add( neko_vm *vm, int_val acc, int_val sp, int pc ) { if( acc & 1 ) { if( val_tag(sp) == VAL_FLOAT ) acc = (int_val)alloc_float(val_float(sp) + val_int(acc)); else if( val_tag(sp) == VAL_INT32 ) acc = (int_val)alloc_best_int(val_int32(sp) + val_int(acc)); else if( val_short_tag(sp) == VAL_STRING ) acc = (int_val)neko_append_int(vm,(value)sp,val_int(acc),true); else if( val_tag(sp) == VAL_OBJECT ) ObjectOp(sp,acc,id_add) else OpError("+"); } else if( sp & 1 ) { if( val_tag(acc) == VAL_FLOAT ) acc = (int_val)alloc_float(val_int(sp) + val_float(acc)); else if( val_tag(acc) == VAL_INT32 ) acc = (int_val)alloc_best_int(val_int(sp) + val_int32(acc)); else if( val_short_tag(acc) == VAL_STRING ) acc = (int_val)neko_append_int(vm,(value)acc,val_int(sp),false); else if( val_tag(acc) == VAL_OBJECT ) ObjectOp(acc,sp,id_radd) else OpError("+"); } else if( val_tag(acc) == VAL_FLOAT ) { if( val_tag(sp) == VAL_FLOAT ) acc = (int_val)alloc_float(val_float(sp) + val_float(acc)); else if( val_tag(sp) == VAL_INT32 ) acc = (int_val)alloc_float(val_int32(sp) + val_float(acc)); else goto add_next; } else if( val_tag(acc) == VAL_INT32 ) { if( val_tag(sp) == VAL_INT32 ) acc = (int_val)alloc_best_int(val_int32(sp) + val_int32(acc)); else if( val_tag(sp) == VAL_FLOAT ) acc = (int_val)alloc_float(val_float(sp) + val_int32(acc)); else goto add_next; } else { add_next: if( val_tag(sp) == VAL_OBJECT ) ObjectOpGen(sp,acc,id_add,goto add_2) else { add_2: if( val_tag(acc) == VAL_OBJECT ) ObjectOpGen(acc,sp,id_radd,goto add_3) else { add_3: if( val_short_tag(acc) == VAL_STRING || val_short_tag(sp) == VAL_STRING ) { ACC_BACKUP buffer b = alloc_buffer(NULL); BeginCall(); val_buffer(b,(value)sp); ACC_RESTORE; val_buffer(b,(value)acc); EndCall(); acc = (int_val)buffer_to_string(b); } else OpError("+"); } } } return acc; } #define NumberOp(op,fop,id_op,id_rop) \ if( acc & 1 ) { \ if( val_tag(sp) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_float(sp),val_int(acc))); \ else if( val_tag(sp) == VAL_INT32 ) \ acc = (int_val)alloc_best_int(val_int32(sp) op val_int(acc)); \ else if( val_tag(sp) == VAL_OBJECT ) \ ObjectOp(sp,acc,id_op) \ else \ OpError(#op); \ } else if( sp & 1 ) { \ if( val_tag(acc) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_int(sp),val_float(acc))); \ else if( val_tag(acc) == VAL_INT32 ) \ acc = (int_val)alloc_best_int(val_int(sp) op val_int32(acc)); \ else if( val_tag(acc) == VAL_OBJECT ) \ ObjectOp(acc,sp,id_rop) \ else \ OpError(#op); \ } else if( val_tag(acc) == VAL_FLOAT ) { \ if( val_tag(sp) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_float(sp),val_float(acc))); \ else if( val_tag(sp) == VAL_INT32 ) \ acc = (int_val)alloc_float(fop(val_int32(sp),val_float(acc))); \ else \ goto id_op##_next; \ } else if( val_tag(acc) == VAL_INT32 ) {\ if( val_tag(sp) == VAL_INT32 ) \ acc = (int_val)alloc_best_int(val_int32(sp) op val_int32(acc)); \ else if( val_tag(sp) == VAL_FLOAT ) \ acc = (int_val)alloc_float(fop(val_float(sp),val_int32(acc))); \ else \ goto id_op##_next; \ } else { \ id_op##_next: \ if( val_tag(sp) == VAL_OBJECT ) \ ObjectOpGen(sp,acc,id_op,goto id_op##_next2) \ else { \ id_op##_next2: \ if( val_tag(acc) == VAL_OBJECT ) \ ObjectOp(acc,sp,id_rop) \ else \ OpError(#op); \ } \ } #define SUB(x,y) ((x) - (y)) #define MULT(x,y) ((x) * (y)) #define DIV(x,y) ((x) / (y)) #define GENERIC_OP(id,op,fop) \ static int_val generic_##id( neko_vm *vm, int_val acc, int_val sp, int pc ) { \ NumberOp(op,fop,id_##id,id_r##id); \ return acc; \ } GENERIC_OP(sub,-,SUB); GENERIC_OP(mult,*,MULT); static int_val generic_div( neko_vm *vm, int_val acc, int_val sp, int pc ) { if( val_is_number(acc) && val_is_number(sp) ) acc = (int_val)alloc_float( ((tfloat)val_number(sp)) / val_number(acc) ); else if( val_is_object(sp) ) ObjectOpGen(sp,acc,id_div,goto div_next) else { div_next: if( val_is_object(acc) ) ObjectOp(acc,sp,id_rdiv) else OpError("/"); } return acc; } static int_val generic_mod( neko_vm *vm, int_val acc, int_val sp, int pc ) { if( (acc == 1 || (val_is_int32(acc) && val_int32(acc)==0)) && val_is_any_int(sp) ) OpError("%"); NumberOp(%,fmod,id_mod,id_rmod); return acc; } #define GENERIC_IOP(id,op) \ static int_val generic_##id( neko_vm *vm, int_val acc, int_val sp, int pc ) { \ if( val_is_any_int(acc) && val_is_any_int(sp) ) \ acc = (int_val)alloc_best_int(val_any_int(sp) op val_any_int(acc)); \ else \ OpError(#op); \ return acc; \ } GENERIC_IOP(shl,<<); GENERIC_IOP(shr,>>); GENERIC_IOP(or,|); GENERIC_IOP(and,&); GENERIC_IOP(xor,^); static int_val generic_ushr( neko_vm *vm, int_val acc, int_val sp, int pc ) { if( val_is_any_int(acc) && val_is_any_int(sp) ) acc = (int_val)alloc_best_int( ((unsigned int)val_any_int(sp)) >> val_any_int(acc)); else OpError(">>>"); return acc; } // -------------------------------------------- // we only inline operations for (int,int) and (float,float) // other cases are handled by a single generic_op primitive // through a small jit_generic_* wrapper static void jit_number_op( jit_ctx *ctx, enum Operation op ) { INIT_BUFFER; int *jnot_int, *jnot_int2, *jint, *jnot_float1, *jnot_float2, *jmod0; char *jend, *jend2, *jdiv = NULL; // tmp = acc XMov_rr(TMP,ACC); // acc = *sp XMov_rp(ACC,SP,FIELD(0)); // is_int(acc) && is_int(sp) is_int(ACC,false,jnot_int); is_int(TMP,false,jnot_int2); XShr_rc(ACC,1); XShr_rc(TMP,1); switch( op ) { case OP_ADD: XAdd_rr(ACC,TMP); break; case OP_SUB: XSub_rr(ACC,TMP); break; case OP_MUL: XIMul_rr(ACC,TMP); break; case OP_MOD: XCmp_rc(TMP,0); XJump(JNeq,jmod0); runtime_error(7,false); PATCH_JUMP(jmod0); XCdq(); XIDiv_r(TMP); XMov_rr(ACC,Edx); break; case OP_DIV: XPush_r(ACC); XFILd_i(Esp); XPush_r(TMP); XFILd_i(Esp); stack_pop(Esp,2); XJump_near(jdiv); break; default: ERROR; break; } best_int(); XJump_near(jend); // is_float(acc) && is_float(sp) PATCH_JUMP(jnot_int); XMov_rp(TMP2,ACC,FIELD(0)); XCmp_rb(TMP2,VAL_FLOAT); XJump(JNeq,jnot_float1); is_int(TMP,true,jint); XMov_rp(TMP2,TMP,FIELD(0)); XCmp_rb(TMP2,VAL_FLOAT); XJump(JNeq,jnot_float2); // load floats XAdd_rc(ACC,4); XFLd_i(ACC); XAdd_rc(TMP,4); XFLd_i(TMP); switch( op ) { case OP_ADD: XFAddp(); break; case OP_SUB: XFSubp(); break; case OP_DIV: PATCH_JUMP(jdiv); XFDivp(); break; case OP_MUL: XFMulp(); break; case OP_MOD: stack_push(Esp,2); XFStp_i(Esp); stack_push(Esp,2); XFStp_i(Esp); XCall_m(fmod); stack_pop(Esp,2); break; default: ERROR; break; } if( op != OP_MOD ) { stack_push(Esp,2); } XFStp_i(Esp); XCall_m(alloc_float); stack_pop(Esp,2); XJump_near(jend2); // else... PATCH_JUMP(jint); PATCH_JUMP(jnot_float1); PATCH_JUMP(jnot_float2); PATCH_JUMP(jnot_int2); begin_call(); XPush_c(GET_PC()); XPush_r(ACC); XPush_r(TMP); XPush_r(VM); switch( op ) { case OP_ADD: XCall_m(generic_add); break; case OP_SUB: XCall_m(generic_sub); break; case OP_DIV: XCall_m(generic_div); break; case OP_MUL: XCall_m(generic_mult); break; case OP_MOD: XCall_m(generic_mod); break; case OP_GET: case OP_SET: case OP_LAST: // not used here break; } stack_pop(Esp,4); end_call(); PATCH_JUMP(jend); PATCH_JUMP(jend2); pop(1); END_BUFFER; } static void jit_int_op( jit_ctx *ctx, enum IOperation op ) { INIT_BUFFER; int *jerr1, *jerr2; char *jend; XMov_rr(TMP,ACC); XMov_rp(ACC,SP,FIELD(0)); is_int(ACC,false,jerr1); is_int(TMP,false,jerr2); XShr_rc(TMP,1); XShr_rc(ACC,1); switch( op ) { case IOP_SHL: XShl_rr(ACC,TMP); break; case IOP_SHR: XShr_rr(ACC,TMP); break; case IOP_USHR: XUShr_rr(ACC,TMP); break; case IOP_AND: XAnd_rr(ACC,TMP); break; case IOP_OR: XOr_rr(ACC,TMP); break; case IOP_XOR: XXor_rr(ACC,TMP); break; default: ERROR; } best_int(); XJump_near(jend); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); begin_call(); XPush_c(GET_PC()); XPush_r(ACC); // acc and tmp are reversed in jit_number_op XPush_r(TMP); // XPush_r(VM); switch( op ) { case IOP_SHL: XCall_m(generic_shl); break; case IOP_SHR: XCall_m(generic_shr); break; case IOP_USHR: XCall_m(generic_ushr); break; case IOP_AND: XCall_m(generic_and); break; case IOP_OR: XCall_m(generic_or); break; case IOP_XOR: XCall_m(generic_xor); break; case IOP_LAST: // nothing break; } stack_pop(Esp,4); end_call(); PATCH_JUMP(jend); pop(1); END_BUFFER; } static void jit_array_access( jit_ctx *ctx, int n ) { INIT_BUFFER; int *jerr1, *jerr2; char *jend1, *jend2 = NULL, *jend3; int *jnot_array, *jbounds = NULL; is_int(ACC,true,jerr1); XMov_rp(TMP,ACC,0); XMov_rr(TMP2,TMP); XAnd_rc(TMP2,TAG_MASK); XCmp_rb(TMP2,VAL_ARRAY); XJump(JNeq,jnot_array); if( n > 0 ) { XUShr_rc(TMP,NEKO_TAG_BITS); XCmp_rc(TMP,n); XJump(JLte,jbounds); } XMov_rp(ACC,ACC,FIELD(n + 1)); XJump_near(jend1); if( n > 0 ) { PATCH_JUMP(jbounds); XMov_rc(ACC,CONST(val_null)); XJump_near(jend2); } PATCH_JUMP(jnot_array); XCmp_rb(TMP2,VAL_OBJECT); XJump(JNeq,jerr2); XPush_c(GET_PC()); XMov_rr(TMP,ACC); XMov_rc(ACC,CONST(alloc_int(n))); label(code->oo_get); stack_pop(Esp,1); XJump_near(jend3); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); runtime_error(4,false); PATCH_JUMP(jend1); PATCH_JUMP(jend2); PATCH_JUMP(jend3); END_BUFFER; } static void jit_make_env( jit_ctx *ctx, int esize ) { INIT_BUFFER; int *jerr1, *jerr2, *jok; int i; if( esize == -1 ) { XMov_rr(TMP2,TMP); // store esize } // check type t_function or t_jit is_int(ACC,true,jerr1); XMov_rp(TMP,ACC,FUNFIELD(t)); XCmp_rb(TMP,VAL_JITFUN); XJump(JEq,jok); XCmp_rb(TMP,VAL_FUNCTION); XJump(JNeq,jerr2); PATCH_JUMP(jok); // prepare args for alloc_module_function XPush_r(TMP); // acc->type stack_push(Esp,1); // empty cell stack_pad(2); XMov_rp(TMP,ACC,FUNFIELD(nargs)); XPush_r(TMP); XMov_rp(TMP,ACC,FUNFIELD(addr)); XPush_r(TMP); XMov_rp(TMP,ACC,FUNFIELD(module)); XPush_r(TMP); // call alloc_array(n) stack_pad(3); if( esize == -1 ) { XPush_r(TMP2); } else { XPush_c(esize); } XCall_m(alloc_array); if( esize == -1 ) { char *start; int *loop; XPop_r(TMP2); stack_pad(-3); // fill array start = buf.c; XMov_rp(TMP,SP,FIELD(0)); XMov_xr(ACC,TMP2,4,TMP); XMov_pc(SP,FIELD(0),0); stack_pop(SP,1); XSub_rc(TMP2,1); XCmp_rc(TMP2,0); XJump(JNeq,loop); *loop = (int)(start - buf.c); } else { stack_pop_pad(1,3); // fill array for(i=0;ioo_get); stack_pop(Esp,1); XJump_near(jend3); // check int32 index (with array) PATCH_JUMP(jerr2); XMov_rp(TMP2,ACC,FIELD(0)); XCmp_rb(TMP2,VAL_INT32); XJump(JNeq,jerr4); XMov_rc(ACC,CONST(val_null)); XJump_near(jend4); PATCH_JUMP(jerr1); PATCH_JUMP(jerr3); PATCH_JUMP(jerr4); runtime_error(4,false); // Invalid array access PATCH_JUMP(jend1); PATCH_JUMP(jend2); PATCH_JUMP(jend3); PATCH_JUMP(jend4); break; } case AccIndex: array_access(p); break; case AccIndex0: array_access(0); break; case AccIndex1: array_access(1); break; case AccField: { int *jerr1, *jerr2, *jend1, *loop, *no_resolver; char *jend2, *jend3, *start; is_int(ACC,true,jerr1); XMov_rp(TMP,ACC,FIELD(0)); XCmp_rb(TMP,VAL_OBJECT); XJump(JNeq,jerr2); XPush_r(ACC); XPush_r(VM); stack_pad(1); XMov_rr(VM,ACC); XPush_c(p); start = buf.c; XMov_rr(TMP,VM); XAdd_rc(TMP,FIELD(1)); XPush_r(TMP); XCall_m(otable_find); XCmp_rc(ACC,0); XJump(JNeq,jend1); stack_pop(Esp,1); XMov_rp(VM,VM,FIELD(3)); // acc = acc->proto XCmp_rc(VM,0); XJump(JNeq,loop); *loop = (int)(start - buf.c); stack_pop_pad(1,1); XPop_r(VM); XPop_r(ACC); XMov_rp(TMP,VM,VMFIELD(resolver)); XCmp_rc(TMP,0); XJump(JEq,no_resolver); XPush_c(CONST(alloc_int(p))); XPush_r(ACC); XPush_r(TMP); begin_call(); XCall_m(val_call2); end_call(); stack_pop(Esp,3); XJump_near(jend3); PATCH_JUMP(no_resolver); XMov_rc(ACC,CONST(val_null)); XJump_near(jend2); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); XPush_c(p); XPush_c(GET_PC()); label(code->invalid_access); PATCH_JUMP(jend1); stack_pop_pad(2,2); XPop_r(VM); stack_pop(Esp,1); XMov_rp(ACC,ACC,FIELD(0)); PATCH_JUMP(jend2); PATCH_JUMP(jend3); break; } case SetStack: XMov_pr(SP,FIELD(p),ACC); break; case SetGlobal: XMov_ar(CONST(p),ACC); break; case SetEnv: get_var_r(TMP,VEnv); XMov_rp(TMP2,TMP,FIELD(0)); XCmp_rc(TMP2,(p << NEKO_TAG_BITS) | VAL_ARRAY); XJump(JGt,jok); runtime_error(2,false); // Writing Outside Env PATCH_JUMP(jok); XMov_pr(TMP,FIELD(p+1),ACC); // val_array_ptr(env)[p] = acc break; case SetThis: set_var_r(VThis,ACC); break; case SetField: { int *jerr1, *jerr2; char *jend; XMov_rp(TMP,SP,FIELD(0)); is_int(TMP,true,jerr1); XMov_rp(TMP2,TMP,FIELD(0)); XCmp_rb(TMP2,VAL_OBJECT); XJump(JNeq,jerr2); // call otable_replace(table,field,acc) stack_pad(2); XPush_r(ACC); XPush_c(p); XAdd_rc(TMP,FIELD(1)); XPush_r(TMP); XCall_m(otable_replace); stack_pop(Esp,3); XMov_rp(ACC,Esp,FIELD(-1)); stack_pad(-2); XJump_near(jend); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); runtime_error(5,false); PATCH_JUMP(jend); pop(1); break; } case SetArray: { int *jerr1, *jerr2, *jerr3, *jnot_array, *jend1, *jend4; char *jend2, *jend3; XMov_rp(TMP,SP,FIELD(0)); // sp[0] : array/object is_int(TMP,true,jerr1); XMov_rp(TMP2,TMP,FIELD(0)); XAnd_rc(TMP2,TAG_MASK); XCmp_rb(TMP2,VAL_ARRAY); XJump(JNeq,jnot_array); XMov_rp(TMP2,SP,FIELD(1)); // sp[1] : index is_int(TMP2,false,jerr2); XMov_rp(TMP,TMP,FIELD(0)); // tmp = tmp->type XShr_rc(TMP2,1); XUShr_rc(TMP,NEKO_TAG_BITS); XCmp_rr(TMP2,TMP); XJump(JGte,jend1); XMov_rp(TMP,SP,FIELD(0)); XAdd_rc(TMP2,1); XMov_xr(TMP,TMP2,4,ACC); XJump_near(jend2); PATCH_JUMP(jnot_array); XCmp_rb(TMP2,VAL_OBJECT); XJump(JNeq,jerr3); XMov_rp(TMP2,SP,FIELD(1)); // index XPush_r(TMP2); XPush_c(GET_PC()); label(code->oo_set); stack_pop(Esp,2); XJump_near(jend3); // check int32 index (with array) PATCH_JUMP(jerr2); XMov_rp(TMP2,TMP2,FIELD(0)); XCmp_rb(TMP2,VAL_INT32); XJump(JEq,jend4); PATCH_JUMP(jerr1); PATCH_JUMP(jerr3); runtime_error(4,false); PATCH_JUMP(jend1); PATCH_JUMP(jend2); PATCH_JUMP(jend3); PATCH_JUMP(jend4); pop(2); break; } case SetIndex: { int *jerr1, *jerr2, *jnot_array, *jend1; char *jend2, *jend3; XMov_rp(TMP,SP,FIELD(0)); // sp[0] : array / object pop(1); is_int(TMP,true,jerr1); XMov_rp(TMP2,TMP,FIELD(0)); XAnd_rc(TMP2,TAG_MASK); XCmp_rb(TMP2,VAL_ARRAY); XJump(JNeq,jnot_array); XMov_rp(TMP2,TMP,FIELD(0)); XCmp_rc(TMP2,(p << NEKO_TAG_BITS) | VAL_ARRAY); // fake header XJump(JLte,jend1); XMov_pr(TMP,FIELD(p + 1),ACC); XJump_near(jend2); PATCH_JUMP(jnot_array); XCmp_rb(TMP2,VAL_OBJECT); XJump(JNeq,jerr2); XPush_c(CONST(alloc_int(p))); XPush_c(GET_PC()); label(code->oo_set); stack_pop(Esp,2); XJump_near(jend3); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); runtime_error(4,false); PATCH_JUMP(jend1); PATCH_JUMP(jend2); PATCH_JUMP(jend3); break; } case Push: stack_push(SP,1); XMov_pr(SP,FIELD(0),ACC); break; case Pop: if( p > 10 ) { pop_loop(p); } else { pop(p); } break; case Jump: jump(JAlways,p); break; case JumpIf: XCmp_rc(ACC,CONST(val_true)); jump(JEq,p); break; case JumpIfNot: XCmp_rc(ACC,CONST(val_true)); jump(JNeq,p); break; case Neq: { int *jnot1, *jnot2; char *jend; // call val_compare(sp[0],acc) XPush_r(ACC); XMov_rp(TMP,SP,FIELD(0)); XPush_r(TMP); begin_call(); XCall_m(val_compare); end_call(); stack_pop(Esp,2); pop(1); // test if ok and != invalid_comparison XCmp_rc(ACC,0); XJump(JNeq,jnot1); XCmp_rc(ACC,invalid_comparison); XJump(JEq,jnot2); XMov_rc(ACC,CONST(val_false)); XJump_near(jend); PATCH_JUMP(jnot1); PATCH_JUMP(jnot2); XMov_rc(ACC,CONST(val_true)); PATCH_JUMP(jend); break; } case Eq: test(JNeq); break; case Gt: test(JSignLte); break; case Gte: test(JSignLt); break; case Lt: test(JSignGte); break; case Lte: test(JSignGt); break; case Bool: case Not: { int *jfalse1, *jfalse2, *jfalse3; char *jend; XCmp_rc(ACC,CONST(val_false)); XJump(JEq,jfalse1); XCmp_rc(ACC,CONST(val_null)); XJump(JEq,jfalse2); XCmp_rc(ACC,CONST(alloc_int(0))); XJump(JEq,jfalse3); XMov_rc(ACC,CONST((op == Bool)?val_true:val_false)); XJump_near(jend); PATCH_JUMP(jfalse1); PATCH_JUMP(jfalse2); PATCH_JUMP(jfalse3); XMov_rc(ACC,CONST((op == Bool)?val_false:val_true)); PATCH_JUMP(jend); break; } case IsNull: { int *jnext; char *jend; XCmp_rc(ACC,CONST(val_null)); XJump(JNeq,jnext); XMov_rc(ACC,CONST(val_true)); XJump_near(jend); PATCH_JUMP(jnext); XMov_rc(ACC,CONST(val_false)); PATCH_JUMP(jend); break; } case IsNotNull: { int *jnext; char *jend; XCmp_rc(ACC,CONST(val_null)); XJump(JNeq,jnext); XMov_rc(ACC,CONST(val_false)); XJump_near(jend); PATCH_JUMP(jnext); XMov_rc(ACC,CONST(val_true)); PATCH_JUMP(jend); break; } case Call: call(NORMAL,p); break; case ObjCall: call(THIS_CALL,p); break; case TailCall: { int stack = (p >> 3); int nargs = (p & 7); int i = nargs; while( i > 0 ) { i--; XMov_rp(TMP,SP,FIELD(i)); XMov_pr(SP,FIELD(stack - nargs + i),TMP); } if( stack - nargs > 10 ) { pop_loop(stack - nargs); } else { pop(stack - nargs); } call(TAIL_CALL,nargs); // in case we return from a Primitive XRet(); } break; case Ret: if( p > 10 ) { pop_loop(p); } else { pop(p); } XRet(); break; case Add: number_op(OP_ADD); break; case Sub: number_op(OP_SUB); break; case Div: number_op(OP_DIV); break; case Mult: number_op(OP_MUL); break; case Mod: number_op(OP_MOD); break; case Shl: int_op(IOP_SHL); break; case Shr: int_op(IOP_SHR); break; case UShr: int_op(IOP_USHR); break; case And: int_op(IOP_AND); break; case Or: int_op(IOP_OR); break; case Xor: int_op(IOP_XOR); break; case New: XPush_r(ACC); XCall_m(alloc_object); stack_pop(Esp,1); break; case MakeArray: stack_pad(3); XPush_r(ACC); XPush_c(p + 1); XCall_m(alloc_array); XMov_rp(TMP,Esp,FIELD(1)); // tmp = saved acc XMov_pr(ACC,FIELD(1),TMP); // val_array_ptr(acc)[0] = tmp stack_pop_pad(2,3); if( p < 6 ) { i = 0; while( p > 0 ) { p--; i++; XMov_rp(TMP,SP,FIELD(p)); XMov_pr(ACC,FIELD(i + 1),TMP); XMov_pc(SP,FIELD(p),0); } stack_pop(SP,i); } else { char *start; int *loop; XMov_rc(TMP2,(p+1)); start = buf.c; XMov_rp(TMP,SP,FIELD(0)); XMov_pc(SP,FIELD(0),0); XMov_xr(ACC,TMP2,4,TMP); stack_pop(SP,1); XSub_rc(TMP2,1); XCmp_rc(TMP2,1); XJump(JNeq,loop); *loop = (int)(start - buf.c); } break; case MakeArray2: stack_pad(3); XPush_r(ACC); XPush_c(p + 1); XCall_m(alloc_array); XMov_rp(TMP,Esp,FIELD(1)); // tmp = saved acc XMov_pr(ACC,FIELD(p+1),TMP); // val_array_ptr(acc)[p] = tmp stack_pop_pad(2,3); if( p < 6 ) { i = 0; while( p > 0 ) { p--; i++; XMov_rp(TMP,SP,FIELD(p)); XMov_pr(ACC,FIELD(i),TMP); XMov_pc(SP,FIELD(p),0); } stack_pop(SP,i); } else { char *start; int *loop; XMov_rc(TMP2,p); start = buf.c; XMov_rp(TMP,SP,FIELD(0)); XMov_pc(SP,FIELD(0),0); XMov_xr(ACC,TMP2,4,TMP); stack_pop(SP,1); XSub_rc(TMP2,1); XCmp_rc(TMP2,0); XJump(JNeq,loop); *loop = (int)(start - buf.c); } break; case MakeEnv: XPush_c(GET_PC()); if( p >= MAX_ENV ) { XMov_rc(TMP,p); label(code->make_env_n); } else { label(code->make_env[p]); } stack_pop(Esp,1); break; case Last: XRet(); break; case Apply: { int *jerr1, *jerr2, *jnext, *jcall1, *jcall2, *jdone; char *jend, *start; is_int(ACC,true,jerr1); XMov_rp(TMP,ACC,FIELD(0)); XAnd_rc(TMP,TAG_MASK); XCmp_rb(TMP,VAL_FUNCTION); XJump(JNeq,jerr2); XMov_rp(TMP,ACC,FUNFIELD(nargs)); // what do we do depending of the number of args ? XCmp_rb(TMP,p); XJump(JSignGt,jnext); XJump(JEq,jcall1); XCmp_rb(TMP,VAR_ARGS); XJump(JEq,jcall2); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); runtime_error(8,false); // $apply // build the apply PATCH_JUMP(jnext); XPush_r(ACC); XPush_r(TMP); XAdd_rc(TMP,1); XPush_r(TMP); XCall_m(alloc_array); stack_pop(Esp,1); XPop_r(TMP); XPop_r(TMP2); // fill the env array XMov_pr(ACC,FIELD(1),TMP2); // env[0] = f i = p; while( i-- > 0 ) { // env[*pc-i] = sp[i] XMov_rp(TMP2,SP,FIELD(i)); XMov_pr(ACC,FIELD(1+p-i),TMP2); } pop(p); // fargs = fargs - *pc XSub_rc(TMP,p); // prepare stack for alloc_apply XPush_r(ACC); XPush_r(TMP); // fill the env array with null's XAdd_rc(ACC,(2+p) * 4 ); start = buf.c; XCmp_rb(TMP,0); XJump(JEq,jdone); XMov_pc(ACC,FIELD(0),CONST(val_null)); XAdd_rc(ACC,4); XSub_rc(TMP,1); // jump back to "start" { char *back; XJump_near(back); *back = (char)(start - (back + 1)); } // call alloc_apply PATCH_JUMP(jdone); XCall_m(neko_alloc_apply); stack_pop(Esp,2); XJump_near(jend); // direct call PATCH_JUMP(jcall1); PATCH_JUMP(jcall2); call(NORMAL,p); PATCH_JUMP(jend); break; } case Trap: { // save some vm->start on the stack XMov_rp(TMP,VM,VMFIELD(start)); XPush_r(TMP); XMov_rp(TMP,VM,VMFIELD(start)+FIELD(1)); XPush_r(TMP); XMov_rp(TMP,VM,VMFIELD(start)+FIELD(2)); XPush_r(TMP); XMov_rp(TMP,VM,VMFIELD(start)+FIELD(3)); XPush_r(TMP); // save magic, ebp , esp and ret_pc XMov_pc(VM,VMFIELD(start),CONST(jit_handle_trap)); XMov_pr(VM,VMFIELD(start)+FIELD(1),Ebp); XMov_pr(VM,VMFIELD(start)+FIELD(2),Esp); XMov_pc(VM,VMFIELD(start)+FIELD(3),-1); { jlist *t = (jlist*)alloc(sizeof(jlist)); ctx->buf = buf; t->pos = POS() - 4; t->target = (int)((int_val*)(int_val)p - ctx->module->code); t->next = ctx->traps; ctx->traps = t; } // neko_setup_trap(vm) XPush_r(ACC); stack_pad(3); XPush_r(VM); begin_call(); XCall_m(neko_setup_trap); end_call(); stack_pop(Esp,1); stack_pad(-3); XPop_r(ACC); break; } case EndTrap: { // check spmax - trap = sp get_var_r(TMP,VSpMax); get_var_r(TMP2,VTrap); XShl_rc(TMP2,2); XSub_rr(TMP,TMP2); XCmp_rr(TMP,SP); XJump(JEq,jok); runtime_error(9,false); // Invalid End Trap PATCH_JUMP(jok); // restore VM jmp_buf XPop_r(TMP); XMov_pr(VM,VMFIELD(start)+FIELD(3),TMP); XPop_r(TMP); XMov_pr(VM,VMFIELD(start)+FIELD(2),TMP); XPop_r(TMP); XMov_pr(VM,VMFIELD(start)+FIELD(1),TMP); XPop_r(TMP); XMov_pr(VM,VMFIELD(start),TMP); // trap = val_int(sp[5]) XMov_rp(TMP,SP,FIELD(5)); XShr_rc(TMP,1); set_var_r(VTrap,TMP); pop(6); break; } case TypeOf: { int *jnot_int; char *jend; is_int(ACC,false,jnot_int); XMov_rc(ACC,CONST(alloc_int(1))); // t_int != VAL_INT XJump_near(jend); PATCH_JUMP(jnot_int); XMov_rp(TMP,ACC,FIELD(0)); XAnd_rc(TMP,TAG_MASK); XMov_rc(TMP2,CONST(NEKO_TYPEOF)); XMov_rx(ACC,TMP2,TMP,4); PATCH_JUMP(jend); break; } case Compare: { int *jint; char *jend; // val_compare(sp[0],acc) XPush_r(ACC); XMov_rp(TMP,SP,FIELD(0)); XPush_r(TMP); begin_call(); XCall_m(val_compare); end_call(); stack_pop(Esp,2); XCmp_rc(ACC,invalid_comparison); XJump(JNeq,jint); XMov_rc(ACC,CONST(val_null)); XJump_near(jend); PATCH_JUMP(jint); XShl_rc(ACC,1); XOr_rc(ACC,1); PATCH_JUMP(jend); pop(1); break; } case PhysCompare: { int *jeq, *jlow; char *jend1, *jend2; XMov_rp(TMP,SP,FIELD(0)); pop(1); XCmp_rr(ACC,TMP); XJump(JEq,jeq); XJump(JSignLt,jlow); XMov_rc(ACC,CONST(alloc_int(-1))); XJump_near(jend1); PATCH_JUMP(jlow); XMov_rc(ACC,CONST(alloc_int(1))); XJump_near(jend2); PATCH_JUMP(jeq); XMov_rc(ACC,CONST(alloc_int(0))); PATCH_JUMP(jend1); PATCH_JUMP(jend2); break; } case Hash: { int *jerr1, *jerr2; char *jend; is_int(ACC,true,jerr1); XMov_rp(TMP,ACC,FIELD(0)); XAnd_rc(TMP,TAG_MASK); XCmp_rb(TMP,VAL_STRING); XJump(JNeq,jerr2); begin_call(); XAdd_rc(ACC,4); // val_string(acc) XPush_r(ACC); XCall_m(val_id); stack_pop(Esp,1); XShl_rc(ACC,1); XOr_rc(ACC,1); XJump_near(jend); PATCH_JUMP(jerr1); PATCH_JUMP(jerr2); runtime_error(10,false); // $hash PATCH_JUMP(jend); break; } case JumpTable: { int njumps = p / 2; int *jok1, *jok2; char *jnext1, *jnext2; is_int(ACC,true,jok1); XMov_rc(TMP2,njumps); XJump_near(jnext1); PATCH_JUMP(jok1); XCmp_rc(ACC,p); XJump(JLt,jok2); XMov_rc(TMP2,njumps); XJump_near(jnext2); PATCH_JUMP(jok2); XMov_rr(TMP2,ACC); XShr_rc(TMP2,1); PATCH_JUMP(jnext1); PATCH_JUMP(jnext2); get_var_r(TMP,VModule); // tmp = jit + tmp2 * 5 XMov_rp(TMP,TMP,FIELD(0)); // m->jit XAdd_rr(TMP,TMP2); XShl_rc(TMP2,2); XAdd_rr(TMP,TMP2); ctx->debug_wait = njumps; ctx->buf = buf; { int add_size = 6; int small_add_size = 3; int jump_rsize = 2; int delta = POS() + add_size + jump_rsize; if( IS_SBYTE(delta) ) delta += small_add_size - add_size; XAdd_rc(TMP,delta); XJump_r(TMP); } break; } case Loop: // nothing break; default: ERROR; } END_BUFFER; } #if defined(STACK_ALIGN_DEBUG) || defined(NEKO_JIT_DEBUG) # define MAX_OP_SIZE 1000 # define MAX_BUF_SIZE 1000 #else # define MAX_OP_SIZE 298 // Apply(4) + label(stack_expand) # define MAX_BUF_SIZE 500 #endif #define FILL_BUFFER(f,param,ptr) \ { \ jit_ctx *ctx; \ char *buf = alloc_private(MAX_BUF_SIZE); \ int size; \ ctx = jit_init_context(buf,MAX_BUF_SIZE); \ f(ctx,param); \ size = POS(); \ buf = alloc_jit_mem(size); \ code->ptr = buf; \ memcpy(buf,ctx->baseptr,size); \ ctx->buf.p = buf + size; \ ctx->baseptr = buf; \ jit_finalize_context(ctx); \ } #ifdef USE_MMAP static void free_jit_mem( void *_p ) { int *p = (int*)_p - 1; munmap(p,*p); } static void free_jit_abstract( value v ) { free_jit_mem(val_data(v)); } static char *alloc_jit_mem( int size ) { int *p; // add space for size size += sizeof(int); // round to next page size += (4096 - size%4096); p = (int*)mmap(NULL,size,PROT_READ|PROT_WRITE|PROT_EXEC,(MAP_PRIVATE|MAP_ANON),-1,0); if( p == (int*)-1 ) { buffer b = alloc_buffer("Failed to allocate JIT memory "); val_buffer(b,alloc_int(size>>10)); val_buffer(b,alloc_string("KB")); val_throw(buffer_to_string(b)); } *p = size; return (char*)(p + 1); } #else # define alloc_jit_mem alloc_private #endif void neko_init_jit() { int nstrings = sizeof(cstrings) / sizeof(const char *); int i; strings = alloc_root(nstrings); for(i=0;iboot; jit_handle_trap = code->handle_trap; } void neko_free_jit() { # ifdef USE_MMAP int i; for(i=0;inglobals && !val_is_function(m->globals[k]) ) k++; if( k == m->nglobals ) { *faddr = -1; return 0; } *faddr = (int_val*)((vfunction*)m->globals[k])->addr - m->code; return k; } void neko_module_jit( neko_module *m ) { unsigned int i = 0; int_val faddr; unsigned int fcursor = next_function(m,0,&faddr); jit_ctx *ctx = jit_init_context(NULL,0); ctx->pos = (int*)tmp_alloc(sizeof(int)*(m->codesize + 1)); ctx->module = m; while( i <= m->codesize ) { enum OPCODE op = m->code[i]; int curpos = POS(); ctx->pos[i] = curpos; ctx->curpc = i + 2; // resize buffer if( curpos + MAX_OP_SIZE > ctx->size ) { int nsize = ctx->size ? (ctx->size * 4) / 3 : ((m->codesize + 1) * 20); char *buf2; if( nsize - curpos < MAX_OP_SIZE ) nsize = curpos + MAX_OP_SIZE; buf2 = tmp_alloc(nsize); memcpy(buf2,ctx->baseptr,curpos); tmp_free(ctx->baseptr); ctx->baseptr = buf2; ctx->buf.p = buf2 + curpos; ctx->size = nsize; } // begin of function : check stack overflow if( faddr == i ) { INIT_BUFFER; label(code->stack_expand); END_BUFFER; fcursor = next_function(m,fcursor+1,&faddr); } // --------- debug --------- # ifdef NEKO_JIT_DEBUG if( ctx->debug_wait ) ctx->debug_wait--; else { INIT_BUFFER; XPush_r(ACC); // val_print(acc) XPush_r(ACC); XCall_m_real(val_print); stack_pop(Esp,1); // val_print(pc_pos) XPush_c(CONST(alloc_int(i))); XCall_m_real(val_print_2); stack_pop(Esp,1); // val_print(alloc_int(spmax - sp)) get_var_r(TMP,VSpMax); XSub_rr(TMP,SP); XShr_rc(TMP,1); XOr_rc(TMP,1); XPush_r(TMP); XCall_m_real(val_print_2); stack_pop(Esp,1); // val_print(alloc_int(csp - spmin)) XMov_rp(TMP2,VM,VMFIELD(spmin)); XMov_rr(TMP,CSP); XSub_rr(TMP,TMP2); XShr_rc(TMP,1); XOr_rc(TMP,1); XPush_r(TMP); XCall_m_real(val_print_3); stack_pop(Esp,1); XPop_r(ACC); END_BUFFER; } # endif i++; jit_opcode(ctx,op,(int)m->code[i]); # ifdef _DEBUG { int bytes = POS() - curpos; if( bytes > MAX_OP_SIZE ) ERROR; } # endif i += parameter_table[op]; } // FINALIZE { int csize = POS(); char *rbuf = alloc_jit_mem(csize); memcpy(rbuf,ctx->baseptr,csize); tmp_free(ctx->baseptr); ctx->baseptr = rbuf; ctx->buf.p = rbuf + csize; ctx->size = csize; # ifdef USE_MMAP m->jit_gc = alloc_abstract(NULL,rbuf); val_gc(m->jit_gc,free_jit_abstract); # endif # ifdef NEKO_JIT_DEBUG printf("Jit size = %d ( x%.1f )\n",csize,csize * 1.0 / ((m->codesize + 1) * 4)); # endif jit_finalize_context(ctx); } // UPDATE GLOBALS { for(i=0;inglobals;i++) { vfunction *f = (vfunction*)m->globals[i]; if( !val_is_int(f) && val_tag(f) == VAL_FUNCTION && f->module == m ) { int pc = (int)((int_val*)f->addr - m->code); f->t = VAL_JITFUN; f->addr = (char*)ctx->baseptr + ctx->pos[pc]; } } } m->jit = ctx->baseptr; tmp_free(ctx->pos); } #else // NEKO_JIT_ENABLE char *jit_boot_seq = NULL; char *jit_handle_trap = (char*)&jit_boot_seq; void neko_init_jit() { } void neko_free_jit() { } int neko_can_jit() { return 0; } void neko_module_jit( neko_module *m ) { } #endif /* ************************************************************************ */ neko-2-2-0/vm/load.c000066400000000000000000000265261321613172000141610ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "vm.h" #include "neko_mod.h" #ifndef NEKO_WINDOWS # include #endif extern field id_cache; extern field id_path; extern field id_loader_libs; DEFINE_KIND(k_loader_libs); #ifdef NEKO_PROF typedef void (*callb)( const char *name, neko_module *m, int *tot ); typedef struct { callb callb; int tot; } dump_param; static void profile_total( const char *name, neko_module *m, int *tot ) { unsigned int i; unsigned int n = 0; for(i=0;icodesize;i++) n += (int)m->code[PROF_SIZE+i]; *tot += n; } static void profile_summary( const char *name, neko_module *m, int *ptr ) { unsigned int i; unsigned int tot = 0; for(i=0;icodesize;i++) tot += (int)m->code[PROF_SIZE+i]; printf("%10d %-4.1f%% %s\n",tot,(tot * 100.0f) / (*ptr),name); } static void profile_details( const char *name, neko_module *m, int *tot ) { unsigned int i; value *dbg = val_is_null(m->debuginf)?NULL:val_array_ptr(m->debuginf); printf("Details for : %s[%d]\n",name,m->codesize); for(i=0;icodesize;i++) { int c = (int)m->code[PROF_SIZE+i]; if( c > 0 ) { if( dbg ) val_print(dbg[i]); printf(" %-4X %d\n",i,c); } } printf("\n"); } static void profile_functions( const char *name, neko_module *m, int *tot ) { unsigned int i; value *dbg = val_is_null(m->debuginf)?NULL:val_array_ptr(m->debuginf); for(i=0;inglobals;i++) { value v = m->globals[i]; if( val_is_function(v) && val_type(v) == VAL_FUNCTION && ((vfunction*)v)->module == m ) { int pos = (int)(((int_val)((vfunction*)v)->addr - (int_val)m->code) / sizeof(int_val)); if( m->code[PROF_SIZE+pos] > 0 ) { printf("%-8d %-4d %-20s %X ",m->code[PROF_SIZE+pos],i,name,pos); if( dbg ) val_print(dbg[pos]); printf("\n"); } } } } static void dump_module( value v, field f, void *p ) { value vname; const char *name; if( !val_is_kind(v,neko_kind_module) ) return; vname = val_field_name(f); name = val_is_null(vname)?"???":val_string(vname); ((dump_param*)p)->callb( name, (neko_module*)val_data(v), &((dump_param*)p)->tot ); } static value dump_prof() { dump_param p; value o = val_this(); value cache; val_check(o,object); cache = val_field(o,id_cache); val_check(cache,object); p.tot = 0; p.callb = profile_total; val_iter_fields(cache,dump_module,&p); printf("Summary :\n"); p.callb = profile_summary; val_iter_fields(cache,dump_module,&p); printf("%10d\n\n",p.tot); printf("Functions :\n"); p.callb = profile_functions; val_iter_fields(cache,dump_module,&p); printf("\n"); p.callb = profile_details; val_iter_fields(cache,dump_module,&p); return val_true; } #endif #ifdef NEKO_WINDOWS # undef ERROR # include # define dlopen(l,p) (void*)LoadLibrary(l) # define dlsym(h,n) GetProcAddress((HANDLE)h,n) #endif EXTERN value neko_select_file( value path, const char *file, const char *ext ) { struct stat s; value ff; buffer b = alloc_buffer(file); buffer_append(b,ext); ff = buffer_to_string(b); if( stat(val_string(ff),&s) == 0 ) { char *p = strchr(file,'/'); if( p == NULL ) p = strchr(file,'\\'); if( p != NULL ) return ff; b = alloc_buffer("./"); buffer_append(b,file); buffer_append(b,ext); return buffer_to_string(b); } while( val_is_array(path) && val_array_size(path) == 2 ) { value p = val_array_ptr(path)[0]; buffer b = alloc_buffer(NULL); path = val_array_ptr(path)[1]; val_buffer(b,p); val_buffer(b,ff); p = buffer_to_string(b); if( stat(val_string(p),&s) == 0 ) return p; } return ff; } static void open_module( value path, const char *mname, reader *r, readp *p ) { FILE *f; value fname; char *ext = strrchr(mname,'.'); if( ext && ext[1] == 'n' && ext[2] == 0 ) fname = neko_select_file(path,mname,""); else fname = neko_select_file(path,mname,".n"); f = fopen(val_string(fname),"rb"); if( f == NULL ) { buffer b = alloc_buffer("Module not found : "); buffer_append(b,mname); bfailure(b); } *r = neko_file_reader; *p = f; } static void close_module( readp p ) { fclose(p); } typedef struct _liblist { char *name; void *handle; struct _liblist *next; } liblist; typedef value (*PRIM0)(); static void *load_primitive( const char *prim, int nargs, value path, liblist **libs ) { char *pos = strchr(prim,'@'); int len; liblist *l; PRIM0 ptr; if( pos == NULL ) return NULL; l = *libs; *pos = 0; len = (int)strlen(prim) + 1; # ifndef NEKO_STANDALONE while( l != NULL ) { if( memcmp(l->name,prim,len) == 0 ) break; l = l->next; } # endif if( l == NULL ) { void *h; value pname = pname = neko_select_file(path,prim,".ndll"); #ifdef NEKO_STANDALONE # ifdef NEKO_WINDOWS h = (void*)GetModuleHandle(NULL); # else h = dlopen(NULL,RTLD_LAZY); # endif #else h = dlopen(val_string(pname),RTLD_LAZY); #endif if( h == NULL ) { buffer b = alloc_buffer("Failed to load library : "); val_buffer(b,pname); #ifndef NEKO_WINDOWS buffer_append(b," ("); buffer_append(b,dlerror()); buffer_append(b,")"); #endif *pos = '@'; bfailure(b); } l = (liblist*)alloc(sizeof(liblist)); l->handle = h; l->name = alloc_private(len); memcpy(l->name,prim,len); l->next = *libs; *libs = l; ptr = (PRIM0)dlsym(l->handle,"__neko_entry_point"); if( ptr != NULL ) ((PRIM0)ptr())(); } *pos++ = '@'; { char buf[100]; if( strlen(pos) > 90 ) return NULL; if( nargs == VAR_ARGS ) sprintf(buf,"%s__MULT",pos); else sprintf(buf,"%s__%d",pos,nargs); ptr = (PRIM0)dlsym(l->handle,buf); if( ptr == NULL ) return NULL; return ptr(); } } static value init_path( const char *path ) { value l = val_null, tmp; char *p, *p2; char *allocated = NULL; #ifdef NEKO_WINDOWS char exe_path[MAX_PATH]; if( path == NULL ) { # ifdef NEKO_STANDALONE # define SELF_DLL NULL # else # define SELF_DLL "neko.dll" # endif if( GetModuleFileName(GetModuleHandle(SELF_DLL),exe_path,MAX_PATH) == 0 ) return val_null; p = strrchr(exe_path,'\\'); if( p == NULL ) return val_null; *p = 0; path = exe_path; } #else if( path == NULL ) { allocated = strdup(NEKO_MODULE_PATH ":/usr/local/lib/neko:/usr/lib/neko:/usr/local/bin:/usr/bin"); path = allocated; } #endif while( true ) { // windows drive letter (same behavior expected on all os) if( *path && path[1] == ':' ) { p = strchr(path+2,':'); p2 = strchr(path+2,';'); } else { p = strchr(path,':'); p2 = strchr(path,';'); } if( p == NULL || (p2 != NULL && p2 < p) ) p = p2; if( p != NULL ) *p = 0; tmp = alloc_array(2); if( (p && p[-1] != '/' && p[-1] != '\\') || (!p && path[strlen(path)-1] != '/' && path[strlen(path)-1] != '\\') ) { buffer b = alloc_buffer(path); char c = '/'; buffer_append_sub(b,&c,1); val_array_ptr(tmp)[0] = buffer_to_string(b); } else val_array_ptr(tmp)[0] = alloc_string(path); val_array_ptr(tmp)[1] = l; l = tmp; if( p != NULL ) *p = (p == p2)?';':':'; else break; path = p+1; } if( allocated != NULL ) free(allocated); return l; } typedef value (*stats_callback)( value, value, value, value, value, value ); static value stats_proxy( value p1, value p2, value p3, value p4, value p5, value p6 ) { neko_vm *vm = NEKO_VM(); value env = vm->env; value ret; if( vm->pstats ) vm->pstats(vm,val_string(val_array_ptr(env)[0]),1); ret = ((stats_callback)((int_val)val_array_ptr(vm->env)[1]&~1))(p1,p2,p3,p4,p5,p6); if( vm->pstats ) vm->pstats(vm,val_string(val_array_ptr(env)[0]),0); return ret; } static value loader_loadprim( value prim, value nargs ) { value o = val_this(); value libs; val_check(o,object); val_check(prim,string); val_check(nargs,int); libs = val_field(o,id_loader_libs); val_check_kind(libs,k_loader_libs); if( val_int(nargs) >= 10 || val_int(nargs) < -1 ) neko_error(); { neko_vm *vm = NEKO_VM(); void *ptr = load_primitive(val_string(prim),val_int(nargs),val_field(o,id_path),(liblist**)(void*)&val_data(libs)); vfunction *f; if( ptr == NULL ) { buffer b = alloc_buffer("Primitive not found : "); val_buffer(b,prim); buffer_append(b,"("); val_buffer(b,nargs); buffer_append(b,")"); bfailure(b); } f = (vfunction*)alloc_function(ptr,val_int(nargs),val_string(copy_string(val_string(prim),val_strlen(prim)))); if( vm->pstats && val_int(nargs) <= 6 ) { value env = alloc_array(2); val_array_ptr(env)[0] = f->module; val_array_ptr(env)[1] = (value)(((int_val)f->addr) | 1); f->addr = stats_proxy; f->env = env; } return (value)f; } } static value loader_loadmodule( value mname, value vthis ) { value o = val_this(); value cache; val_check(o,object); val_check(mname,string); val_check(vthis,object); cache = val_field(o,id_cache); val_check(cache,object); { reader r; readp p; neko_module *m; neko_vm *vm = NEKO_VM(); field mid = val_id(val_string(mname)); value mv = val_field(cache,mid); if( val_is_kind(mv,neko_kind_module) ) { m = (neko_module*)val_data(mv); return m->exports; } open_module(val_field(o,id_path),val_string(mname),&r,&p); if( vm->fstats ) vm->fstats(vm,"neko_read_module",1); m = neko_read_module(r,p,vthis); if( vm->fstats ) vm->fstats(vm,"neko_read_module",0); close_module(p); if( m == NULL ) { buffer b = alloc_buffer("Invalid module : "); val_buffer(b,mname); bfailure(b); } m->name = alloc_string(val_string(mname)); mv = alloc_abstract(neko_kind_module,m); alloc_field(cache,mid,mv); if( vm->fstats ) vm->fstats(vm,val_string(mname),1); neko_vm_execute(neko_vm_current(),m); if( vm->fstats ) vm->fstats(vm,val_string(mname),0); return m->exports; } } EXTERN value neko_default_loader( char **argv, int argc ) { value o = alloc_object(NULL); value args = alloc_array(argc); int i; for(i=0;i #include #include #include "neko_vm.h" #include "neko_elf.h" #ifdef NEKO_WINDOWS # include #else # include # include #endif #ifdef NEKO_MAC # include # include #endif #ifdef NEKO_BSD # include # include #endif #ifdef NEKO_POSIX # include #endif #ifdef __GNUC__ #ifdef ABI_ELF # define SEPARATE_SECTION_FOR_BYTECODE #endif #endif #ifdef SEPARATE_SECTION_FOR_BYTECODE // Make a special section header that can be repurposed to encapsulate // any attached bytecode so that it will not be stripped away by // accident... const unsigned int BYTECODE_SEC __attribute__((__section__(".nekobytecode"))) = 0x00; #endif #ifdef NEKO_STANDALONE extern void neko_standalone_init(); extern void neko_standalone_error( const char *str ); extern value neko_standalone_loader( char **arv, int argc ); # define default_loader neko_standalone_loader #else # define default_loader neko_default_loader #endif static FILE *self; extern void neko_stats_measure( neko_vm *vm, const char *kind, int start ); extern value neko_stats_build( neko_vm *vm ); static char *executable_path() { #if defined(NEKO_WINDOWS) static char path[MAX_PATH]; if( GetModuleFileName(NULL,path,MAX_PATH) == 0 ) return NULL; return path; #elif defined(NEKO_MAC) static char path[MAXPATHLEN+1]; uint32_t path_len = MAXPATHLEN; if ( _NSGetExecutablePath(path, &path_len) ) return NULL; return path; #elif defined(NEKO_BSD) int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; static char path[MAXPATHLEN]; size_t cb = sizeof(path); sysctl(mib, 4, path, &cb, NULL, 0); if (!cb) return NULL; return path; #elif defined(NEKO_LINUX) static char path[PATH_MAX]; int length = readlink("/proc/self/exe", path, sizeof(path)); if( length < 0 || length >= PATH_MAX ) { char *p = getenv(" "); // for upx if( p == NULL ) p = getenv("_"); return p; } path[length] = '\0'; return path; #else return getenv("_"); #endif } int neko_has_embedded_module( neko_vm *vm ) { char *exe = executable_path(); unsigned char id[8]; int beg=-1, end=0; if( exe == NULL ) return 0; #ifdef SEPARATE_SECTION_FOR_BYTECODE /* Look for a .nekobytecode section in the executable..., there is always a small section */ if ( val_true != elf_find_embedded_bytecode(exe,&beg,&end) || end-beg <= 8) { /* Couldn't find a big enough .nekobytecode section, fallback to looking at the end of the executable... */ beg = -1; end = 0; } #endif /* Back up eight bytes to the possible bytecode signature... */ end -= 8; self = fopen(exe,"rb"); if( self == NULL ) return 0; fseek(self,end,(end<0)?SEEK_END:SEEK_SET); if( fread(id,1,8,self) != 8 || id[0] != 'N' || id[1] != 'E' || id[2] != 'K' || id[3] != 'O' ) { fclose(self); return 0; } if ( -1 == beg ) { beg = id[4] | id[5] << 8 | id[6] << 16; } fseek(self,beg,(beg<0)?SEEK_END:SEEK_SET); // flags if( (id[7] & 1) == 0 ) neko_vm_jit(vm,1); return 1; } static void report( neko_vm *vm, value exc, int isexc ) { int i; buffer b = alloc_buffer(NULL); value st = neko_exc_stack(vm); for(i=0;i #else # define _CrtSetDbgFlag(x) #endif #ifdef NEKO_POSIX static void handle_signal( int signal ) { if( signal == SIGPIPE ) val_throw(alloc_string("Broken pipe")); else val_throw(alloc_string("Segmentation fault")); } #endif int main( int argc, char *argv[] ) { neko_vm *vm; value mload; int r; _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); neko_global_init(); vm = neko_vm_alloc(NULL); neko_vm_select(vm); # ifdef NEKO_STANDALONE neko_standalone_init(); # endif # ifdef NEKO_POSIX struct sigaction act; act.sa_sigaction = NULL; act.sa_handler = handle_signal; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGPIPE,&act,NULL); # endif if( !neko_has_embedded_module(vm) ) { int jit = 1; int stats = 0; while( argc > 1 ) { if( strcmp(argv[1],"-interp") == 0 ) { argc--; argv++; jit = 0; continue; } if( strcmp(argv[1],"-stats") == 0 ) { argc--; argv++; stats = 1; neko_vm_set_stats(vm,neko_stats_measure,neko_stats_measure); neko_stats_measure(vm,"total",1); continue; } if( strcmp(argv[1],"-version") == 0 ) { argc--; argv++; printf("%d.%d.%d\n",NEKO_VERSION_MAJOR,NEKO_VERSION_MINOR,NEKO_VERSION_PATCH); return 0; } break; } # ifdef NEKO_POSIX if( jit ) sigaction(SIGSEGV,&act,NULL); # endif neko_vm_jit(vm,jit); if( argc == 1 ) { # ifdef NEKO_STANDALONE report(vm,alloc_string("No embedded module in this executable"),0); # else printf("NekoVM %d.%d.%d (c)2005-2017 Haxe Foundation\n Usage : neko \n",NEKO_VERSION_MAJOR,NEKO_VERSION_MINOR,NEKO_VERSION_PATCH); # endif mload = NULL; r = 1; } else { mload = default_loader(argv+2,argc-2); r = execute_file(vm,argv[1],mload); } if( stats ) { value v; neko_stats_measure(vm,"total",0); v = neko_stats_build(vm); val_print(alloc_string("TOT\tTIME\tCOUNT\tNAME\n")); while( v != val_null ) { char buf[256]; value *s = val_array_ptr(v); int errors = val_int(s[4]); sprintf(buf,"%d\t%d\t%d\t%s%c", val_int(s[1]), val_int(s[2]), val_int(s[3]), val_string(s[0]), errors?' ':'\n'); if( errors ) sprintf(buf+strlen(buf),"ERRORS=%d\n",errors); val_print(alloc_string(buf)); v = s[5]; } } } else { mload = default_loader(argv+1,argc-1); r = neko_execute_self(vm,mload); } if( mload != NULL && val_field(mload,val_id("dump_prof")) != val_null ) val_ocall0(mload,val_id("dump_prof")); vm = NULL; mload = NULL; neko_vm_select(NULL); neko_global_free(); return r; } /* ************************************************************************ */ neko-2-2-0/vm/module.c000066400000000000000000000346311321613172000145230ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include "neko_mod.h" #include "vm.h" #define PARAMETER_TABLE #define STACK_TABLE #include "opcodes.h" DEFINE_KIND(neko_kind_module); /* Endianness macros. */ #ifdef NEKO_BSD # include #endif /* *_TO_LE(X) converts (X) to little endian. */ #ifdef NEKO_LITTLE_ENDIAN # define LONG_TO_LE(X) (X) # define SHORT_TO_LE(X) (X) #else # define LONG_TO_LE(X) ((((X) >> 24) & 0xff) | \ (((X) >> 8) & 0xff00) | (((X) & 0xff00) << 8) | \ (((X) & 0xff) << 24)) # define SHORT_TO_LE(X) ((((X) >> 8) & 0xff) | (((X) & 0xff) << 8)) #endif #define MAXSIZE 0x100 #define ERROR() { free(tmp); return NULL; } #define READ(buf,len) if( r(p,buf,len) == -1 ) ERROR() #ifdef NEKO_64BITS static void read_long( reader r, readp p, unsigned int *i ) { unsigned char c[4]; int n; r(p,c,4); n = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); *i = LONG_TO_LE(n); } static void read_short( reader r, readp p, unsigned short *i ) { unsigned char c[2]; int n; r(p,c,2); n = c[0] | (c[1] << 8); *i = SHORT_TO_LE(n); } # define READ_LONG(var) read_long(r,p,&(var)) # define READ_SHORT(var) read_short(r,p,&(var)) #else # define READ_LONG(var) READ(&(var), 4); var = LONG_TO_LE(var) # define READ_SHORT(var) READ(&(var), 2); var = SHORT_TO_LE(var) #endif extern field id_loader; extern field id_exports; extern value *neko_builtins; extern value neko_alloc_module_function( void *m, int_val pos, int nargs ); extern void neko_module_jit( neko_module *m ); EXTERN int neko_is_big_endian() { #ifdef NEKO_LITTLE_ENDIAN return 0; #else return 1; #endif } static int read_string( reader r, readp p, char *buf ) { int i = 0; char c; while( i < MAXSIZE ) { if( r(p,&c,1) == -1 ) return -1; buf[i++] = c; if( c == 0 ) return i; } return -1; } static value get_builtin( neko_module *m, field id ) { value f = val_field(*neko_builtins,id); if( val_is_null(f) ) { unsigned int i; for(i=0;infields;i++) if( val_id(val_string(m->fields[i])) == id ) { buffer b = alloc_buffer("Builtin not found : "); val_buffer(b,m->fields[i]); bfailure(b); } failure("Builtin not found"); } return f; } #define UNKNOWN ((unsigned char)-1) static int neko_check_stack( neko_module *m, unsigned char *tmp, unsigned int i, int stack, int istack ) { unsigned int itmp; while( true ) { int c = (int)m->code[i]; int s = stack_table[c]; if( tmp[i] == UNKNOWN ) tmp[i] = stack; else if( tmp[i] != stack ) return 0; else return 1; if( s == P ) stack += (int)m->code[i+1]; else if( s == -P ) stack -= (int)m->code[i+1]; else stack += s; // 4 because it's the size of a push-infos needed in case of subcall if( stack < istack || stack >= MAX_STACK_PER_FUNCTION - 4 ) return 0; switch( c ) { case Jump: case JumpIf: case JumpIfNot: case Trap: itmp = (int)(((int_val*)m->code[i+1]) - m->code); if( tmp[itmp] == UNKNOWN ) { if( c == Trap ) stack -= s; if( !neko_check_stack(m,tmp,itmp,stack,istack) ) return 0; if( c == Trap ) stack += s; } else if( tmp[itmp] != stack ) return 0; if( c == Jump ) return 1; break; case JumpTable: itmp = (int)m->code[i+1]; i += itmp; while( itmp > 0 ) { itmp -= 2; if( m->code[i - itmp] != Jump ) return 0; if( !neko_check_stack(m,tmp,i - itmp,stack,istack) ) return 0; } break; case AccStack: case SetStack: if( m->code[i+1] >= stack ) return 0; break; case AccStack0: if( 0 >= stack ) return 0; break; case AccStack1: if( 1 >= stack ) return 0; break; case Last: if( stack != 0 ) return 0; return 1; case Ret: if( m->code[i+1] != stack ) return 0; return 1; case ObjCall: stack--; if( stack < istack ) return 0; break; case TailCall: if( stack - (m->code[i+1] & 7) < istack || (m->code[i+1]>>3) != stack ) return 0; return 1; } i += parameter_table[c]?2:1; } return 1; } static void append_array( value *arr, int pos, value v ) { int len = val_array_size(*arr); if( pos >= len ) { value a2 = alloc_array((len * 3) / 2); memcpy(val_array_ptr(a2),val_array_ptr(*arr),len * sizeof(value)); *arr = a2; } val_array_ptr(*arr)[pos] = v; } #define SETBIT(b) { \ if( (i & 31) == 0 ) { \ bits++; \ bits->base = pos_index; \ bits->bits = 0; \ } else \ bits->bits |= b << (31 - (i & 31)); \ i++; \ } static void *read_debug_infos( reader r, readp p, char *tmp, neko_module *m ) { unsigned int i; int curline = 0; value curfile; unsigned int npos; unsigned int nfiles; unsigned char c,c2; value files; value positions, pp; neko_debug *bits; int pos_index = -1; int lot_of_files = 0; READ(&c,1); if( c >= 0x80 ) { READ(&c2,1); nfiles = ((c & 0x7F) << 8) | c2; lot_of_files = 1; } else nfiles = c; if( nfiles == 0 ) ERROR(); files = alloc_array(nfiles); for(i=0;icodesize ) ERROR(); curfile = val_array_ptr(files)[0]; positions = alloc_array(2 + (npos / 20)); bits = (neko_debug *)alloc_private(sizeof(neko_debug) * ((npos + 31) >> 5)); m->dbgidxs = bits; bits--; i = 0; pp = NULL; while( i < npos ) { READ(&c,1); if( c & 1 ) { c >>= 1; if( lot_of_files ) { READ(&c2,1); nfiles = (c << 8) | c2; } else nfiles = c; if( nfiles >= (unsigned int)val_array_size(files) ) ERROR(); curfile = val_array_ptr(files)[nfiles]; pp = NULL; } else if( c & 2 ) { int delta = c >> 6; int count = (c >> 2) & 15; if( i + count > npos ) ERROR(); if( pp == NULL ) { pp = alloc_array(2); val_array_ptr(pp)[0] = curfile; val_array_ptr(pp)[1] = alloc_int(curline); append_array(&positions,++pos_index,pp); SETBIT(1); count--; } while( count-- ) SETBIT(0); if( delta ) { curline += delta; pp = NULL; } } else if( c & 4 ) { curline += c >> 3; pp = alloc_array(2); val_array_ptr(pp)[0] = curfile; val_array_ptr(pp)[1] = alloc_int(curline); append_array(&positions,++pos_index,pp); SETBIT(1); } else { unsigned char b2; unsigned char b3; READ(&b2,1); READ(&b3,1); curline = (c >> 3) | (b2 << 5) | (b3 << 13); pp = alloc_array(2); val_array_ptr(pp)[0] = curfile; val_array_ptr(pp)[1] = alloc_int(curline); append_array(&positions,++pos_index,pp); SETBIT(1); } } // table copy pos_index++; m->dbgtbl = alloc_array(pos_index); memcpy(val_array_ptr(m->dbgtbl),val_array_ptr(positions),pos_index * sizeof(value)); return m; } neko_module *neko_read_module( reader r, readp p, value loader ) { register unsigned int i; unsigned int itmp; unsigned char t; unsigned short stmp; register char *tmp = NULL; unsigned char version = 1; register neko_module *m = (neko_module*)alloc(sizeof(neko_module)); neko_vm *vm = NEKO_VM(); READ_LONG(itmp); if( itmp != 0x4F4B454E ) ERROR(); READ_LONG(m->nglobals); READ_LONG(m->nfields); READ_LONG(m->codesize); if( (int)m->nglobals < 0 || m->nglobals > 0xFFFF || (int)m->nfields < 0 || m->nfields > 0xFFFF || (int)m->codesize < 0 || m->codesize > 0xFFFFFF ) ERROR(); tmp = (char*)malloc(sizeof(char)*(((m->codesize+1)>MAXSIZE)?(m->codesize+1):MAXSIZE)); m->jit = NULL; m->jit_gc = NULL; m->dbgtbl = val_null; m->dbgidxs = NULL; m->globals = (value*)alloc(m->nglobals * sizeof(value)); m->fields = (value*)alloc(sizeof(value*)*m->nfields); m->loader = loader; m->exports = alloc_object(NULL); if( vm->fstats ) vm->fstats(vm,"neko_read_module_data",1); alloc_field(m->exports,neko_id_module,alloc_abstract(neko_kind_module,m)); // Init global table for(i=0;inglobals;i++) { READ(&t,1); switch( t ) { case 1: if( read_string(r,p,tmp) == -1 ) ERROR(); m->globals[i] = val_null; break; case 2: READ_LONG(itmp); if( (itmp & 0xFFFFFF) >= m->codesize ) ERROR(); m->globals[i] = neko_alloc_module_function(m,(itmp&0xFFFFFF),(itmp >> 24)); break; case 3: READ_SHORT(stmp); m->globals[i] = alloc_empty_string(stmp); READ(val_string(m->globals[i]),stmp); break; case 4: if( read_string(r,p,tmp) == -1 ) ERROR(); m->globals[i] = alloc_float( atof(tmp) ); break; case 5: if( !read_debug_infos(r,p,tmp,m) ) { tmp = NULL; // already free in read_debug_infos ERROR(); } m->globals[i] = val_null; break; case 6: READ(&version,1); m->globals[i] = val_null; break; default: ERROR(); break; } } for(i=0;infields;i++) { if( read_string(r,p,tmp) == -1 ) ERROR(); m->fields[i] = alloc_string(tmp); } if( vm->fstats ) { vm->fstats(vm,"neko_read_module_data",0); vm->fstats(vm,"neko_read_module_code",1); } #ifdef NEKO_PROF if( m->codesize >= PROF_SIZE ) ERROR(); m->code = (int_val*)alloc_private(sizeof(int_val)*(m->codesize+PROF_SIZE)); memset(m->code+PROF_SIZE,0,m->codesize*sizeof(int_val)); #else m->code = (int_val*)alloc_private(sizeof(int_val)*(m->codesize+1)); #endif i = 0; // Unpack opcodes while( i < m->codesize ) { READ(&t,1); tmp[i] = 1; switch( t & 3 ) { case 0: m->code[i++] = (t >> 2); break; case 1: m->code[i++] = (t >> 3); tmp[i] = 0; m->code[i++] = (t >> 2) & 1; break; case 2: m->code[i++] = (t >> 2); if( t == 2 ) { // extra opcodes READ(&t,1); m->code[i-1] = t; } else { READ(&t,1); tmp[i] = 0; m->code[i++] = t; } break; case 3: m->code[i++] = (t >> 2); READ_LONG(itmp); tmp[i] = 0; m->code[i++] = (int)itmp; break; } } tmp[i] = 1; m->code[i] = Last; if( vm->fstats ) { vm->fstats(vm,"neko_read_module_code",0); vm->fstats(vm,"neko_read_module_check",1); } // Check bytecode for(i=0;icodesize;i++) { register int c = (int)m->code[i]; itmp = (unsigned int)m->code[i+1]; if( c >= Last || tmp[i+1] == parameter_table[c] ) ERROR(); // Additional checks and optimizations switch( m->code[i] ) { case AccGlobal: case SetGlobal: if( itmp >= m->nglobals ) ERROR(); m->code[i+1] = (int_val)(m->globals + itmp); break; case Jump: case JumpIf: case JumpIfNot: case Trap: itmp += i; if( itmp > m->codesize || !tmp[itmp] ) ERROR(); m->code[i+1] = (int_val)(m->code + itmp); break; case AccInt: if( need_32_bits((int)itmp) ) m->code[i] = AccInt32; else m->code[i+1] = (int_val)alloc_int((int)itmp); break; case AccIndex: m->code[i+1] += 2; break; case AccStack: m->code[i+1] += 2; itmp = (unsigned int)m->code[i+1]; case SetStack: if( ((int)itmp) < 0 ) ERROR(); break; case Ret: case Pop: case AccEnv: case SetEnv: if( ((int)itmp) < 0 ) ERROR(); break; case AccBuiltin: { field f = (field)(int_val)itmp; if( f == id_loader ) m->code[i+1] = (int_val)loader; else if( f == id_exports ) m->code[i+1] = (int_val)m->exports; else m->code[i+1] = (int_val)get_builtin(m,f); } break; case Call: case ObjCall: if( itmp > CALL_MAX_ARGS ) ERROR(); break; case TailCall: if( (itmp&7) > CALL_MAX_ARGS ) ERROR(); break; case Apply: if( itmp == 0 || itmp >= CALL_MAX_ARGS ) ERROR(); break; case MakeEnv: if( itmp > 0xFF ) failure("Too much big environment"); break; case MakeArray: if( itmp > 0x10000 ) failure("Too much big array"); if( version >= 2 ) m->code[i] = MakeArray2; break; case JumpTable: if( itmp > 512 || i + 1 + itmp * 2 >= m->codesize ) ERROR(); m->code[i+1] <<= 1; break; } if( !tmp[i+1] ) i++; } // Check stack preservation { unsigned char *stmp = (unsigned char*)malloc(m->codesize+1); unsigned int prev = 0; memset(stmp,UNKNOWN,m->codesize+1); if( !vm->trusted_code && !neko_check_stack(m,stmp,0,0,0) ) { free(stmp); ERROR(); } for(i=0;inglobals;i++) { vfunction *f = (vfunction*)m->globals[i]; if( val_type(f) == VAL_FUNCTION ) { itmp = (unsigned int)(int_val)f->addr; if( itmp >= m->codesize || !tmp[itmp] || itmp < prev ) { free(stmp); ERROR(); } if( !vm->trusted_code && !neko_check_stack(m,stmp,itmp,f->nargs,f->nargs) ) { free(stmp); ERROR(); } f->addr = m->code + itmp; prev = itmp; } } free(stmp); } free(tmp); if( vm->fstats ) vm->fstats(vm,"neko_read_module_check",0); // jit ? if( vm->run_jit ) { if( vm->fstats ) vm->fstats(vm,"neko_read_module_jit",1); neko_module_jit(m); if( vm->fstats ) vm->fstats(vm,"neko_read_module_jit",0); } # ifdef NEKO_DIRECT_THREADED { int_val *jtbl = neko_get_ttable(); if( vm->fstats ) vm->fstats(vm,"neko_read_module_thread",1); for(i=0;i<=m->codesize;i++) { int_val c = m->code[i]; m->code[i] = jtbl[c]; i += parameter_table[c]; } if( vm->fstats ) vm->fstats(vm,"neko_read_module_thread",0); } # endif return m; } int neko_file_reader( readp p, void *buf, int size ) { int len = 0; while( size > 0 ) { int l; POSIX_LABEL(fread_again); l = (int)fread(buf,1,size,(FILE*)p); if( l <= 0 ) { HANDLE_FINTR((FILE*)p,fread_again); return len; } size -= l; len += l; buf = (char*)buf+l; } return len; } int neko_string_reader( readp p, void *buf, int size ) { string_pos *sp = (string_pos*)p; int delta = (sp->len >= size)?size:sp->len; memcpy(buf,sp->p,delta); sp->p += delta; sp->len -= delta; return delta; } /* ************************************************************************ */ neko-2-2-0/vm/neko.h.in000066400000000000000000000336501321613172000146040ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _NEKO_H #define _NEKO_H // OS FLAGS #if defined(_WIN32) # define NEKO_WINDOWS #endif #if defined(__APPLE__) || defined(macintosh) # define NEKO_MAC #endif #if defined(linux) || defined(__linux__) # define NEKO_LINUX #endif #if defined(__FreeBSD_kernel__) # define NEKO_GNUKBSD #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # define NEKO_BSD #endif #if defined(__GNU__) # define NEKO_HURD #endif // COMPILER/PROCESSOR FLAGS #if defined(__GNUC__) # define NEKO_GCC #endif #if defined(_MSC_VER) # define NEKO_VCC // remove deprecated C API usage warnings # pragma warning( disable : 4996 ) #endif #if defined(__MINGW32__) # define NEKO_MINGW #endif #if defined(__CYGWIN__) # define NEKO_CYGWIN #endif #if defined(__i386__) || defined(_WIN32) # define NEKO_X86 #endif #if defined(__ppc__) # define NEKO_PPC #endif #if defined(_64BITS) || defined(__x86_64__) # define NEKO_64BITS #endif #if defined(NEKO_LINUX) || defined(NEKO_MAC) || defined(NEKO_BSD) || defined(NEKO_GNUKBSD) || defined(NEKO_HURD) || defined(NEKO_CYGWIN) # define NEKO_POSIX #endif #if defined(NEKO_GCC) # define NEKO_THREADED # define NEKO_DIRECT_THREADED #endif #ifndef NEKO_NO_THREADS # define NEKO_THREADS #endif #include #ifndef NEKO_VCC # include #endif #cmakedefine NEKO_XLOCALE_H #cmakedefine NEKO_BIG_ENDIAN #ifndef NEKO_BIG_ENDIAN # define NEKO_LITTLE_ENDIAN #endif #cmakedefine NEKO_JIT_DISABLE #cmakedefine NEKO_JIT_DEBUG #if !defined(NEKO_JIT_DISABLE) && defined(NEKO_X86) && !defined(NEKO_MAC) && !defined(_WIN64) #define NEKO_JIT_ENABLE #endif #define NEKO_VERSION_MAJOR @NEKO_VERSION_MAJOR@ #define NEKO_VERSION_MINOR @NEKO_VERSION_MINOR@ #define NEKO_VERSION_PATCH @NEKO_VERSION_PATCH@ #define NEKO_VERSION @NEKO_VERSION_MAJOR@@NEKO_VERSION_MINOR@@NEKO_VERSION_PATCH@ #define NEKO_MODULE_PATH "@NEKO_MODULE_PATH@" typedef intptr_t int_val; typedef enum { VAL_INT = 0xFF, VAL_NULL = 0, VAL_FLOAT = 1, VAL_BOOL = 2, VAL_STRING = 3, VAL_OBJECT = 4, VAL_ARRAY = 5, VAL_FUNCTION = 6, VAL_ABSTRACT = 7, VAL_INT32 = 8, VAL_PRIMITIVE = 6 | 16, VAL_JITFUN = 6 | 32, VAL_32_BITS = 0xFFFFFFFF } val_type; struct _value { val_type t; }; struct _buffer; typedef int field; typedef struct { int __zero; } *vkind; typedef struct _value *value; typedef struct { field id; value v; } objcell; typedef struct _objtable { int count; objcell *cells; } objtable; typedef struct _buffer *buffer; typedef double tfloat; typedef void (*finalizer)(value v); #pragma pack(4) typedef struct { val_type t; tfloat f; } vfloat; typedef struct { val_type t; int i; } vint32; #pragma pack() typedef struct _vobject { val_type t; objtable table; struct _vobject *proto; } vobject; typedef struct { val_type t; int nargs; void *addr; value env; void *module; } vfunction; typedef struct { val_type t; char c; } vstring; typedef struct { val_type t; value ptr; } varray; typedef struct { val_type t; vkind kind; void *data; } vabstract; typedef struct hcell { int hkey; value key; value val; struct hcell *next; } hcell; typedef struct { hcell **cells; int ncells; int nitems; } vhash; struct _mt_local; struct _mt_lock; typedef struct _mt_local mt_local; typedef struct _mt_lock mt_lock; #define NEKO_TAG_BITS 4 #define val_tag(v) (*(val_type*)(v)) #define val_short_tag(v) (val_tag(v)&((1<data #define val_kind(v) ((vabstract*)(v))->kind #define val_type(v) (val_is_int(v) ? VAL_INT : val_short_tag(v)) #define val_int(v) (((int)(int_val)(v)) >> 1) #define val_float(v) (CONV_FLOAT ((vfloat*)(v))->f) #define val_int32(v) (((vint32*)(v))->i) #define val_any_int(v) (val_is_int(v)?val_int(v):val_int32(v)) #define val_bool(v) ((v) == val_true) #define val_number(v) (val_is_int(v)?val_int(v):((val_tag(v)==VAL_FLOAT)?val_float(v):val_int32(v))) #define val_hdata(v) ((vhash*)val_data(v)) #define val_string(v) (&((vstring*)(v))->c) #define val_strlen(v) ((signed)(((unsigned)val_tag(v)) >> NEKO_TAG_BITS)) #define val_set_length(v,l) val_tag(v) = val_short_tag(v) | ((l) << NEKO_TAG_BITS) #define val_set_size val_set_length #define val_array_size(v) ((signed)(((unsigned)val_tag(v)) >> NEKO_TAG_BITS)) #define val_array_ptr(v) (&((varray*)(v))->ptr) #define val_fun_nargs(v) ((vfunction*)(v))->nargs #define alloc_int(v) ((value)(int_val)((((int)(v)) << 1) | 1)) #define alloc_bool(b) ((b)?val_true:val_false) #define max_array_size ((1 << (32 - NEKO_TAG_BITS)) - 1) #define max_string_size ((1 << (32 - NEKO_TAG_BITS)) - 1) #define invalid_comparison 0xFE #undef EXTERN #undef EXPORT #undef IMPORT #if defined(NEKO_VCC) || defined(NEKO_MINGW) # define INLINE __inline # define EXPORT __declspec( dllexport ) # define IMPORT __declspec( dllimport ) #else # define INLINE inline # define EXPORT # define IMPORT #endif #if defined(NEKO_SOURCES) || defined(NEKO_STANDALONE) # define EXTERN EXPORT #else # define EXTERN IMPORT #endif #define VEXTERN extern EXTERN #ifdef __cplusplus # define C_FUNCTION_BEGIN extern "C" { # define C_FUNCTION_END }; #else # define C_FUNCTION_BEGIN # define C_FUNCTION_END # ifndef true # define true 1 # define false 0 typedef int bool; # endif #endif // the two upper bits must be either 00 or 11 #define need_32_bits(i) ( (((unsigned int)(i)) + 0x40000000) & 0x80000000 ) #define alloc_best_int(i) (need_32_bits(i) ? alloc_int32(i) : alloc_int(i)) #define neko_error() return NULL #define failure(msg) _neko_failure(alloc_string(msg),__FILE__,__LINE__) #define bfailure(buf) _neko_failure(buffer_to_string(buf),__FILE__,__LINE__) #ifndef CONV_FLOAT # define CONV_FLOAT #endif #ifdef NEKO_POSIX # include # define POSIX_LABEL(name) name: # define HANDLE_EINTR(label) if( errno == EINTR ) goto label # define HANDLE_FINTR(f,label) if( ferror(f) && errno == EINTR ) goto label #else # define POSIX_LABEL(name) # define HANDLE_EINTR(label) # define HANDLE_FINTR(f,label) #endif #define VAR_ARGS (-1) #define DEFINE_PRIM_MULT(func) C_FUNCTION_BEGIN EXPORT void *func##__MULT() { return (void*)(&func); } C_FUNCTION_END #define DEFINE_PRIM(func,nargs) C_FUNCTION_BEGIN EXPORT void *func##__##nargs() { return (void*)(&func); } C_FUNCTION_END #define DEFINE_PRIM_WITH_NAME(func,name,nargs) C_FUNCTION_BEGIN EXPORT void *name##__##nargs() { return (void*)(&func); } C_FUNCTION_END #define DEFINE_KIND(name) int_val __kind_##name = 0; vkind name = (vkind)&__kind_##name; #ifdef NEKO_STANDALONE # define DEFINE_ENTRY_POINT(name) #else # define DEFINE_ENTRY_POINT(name) C_FUNCTION_BEGIN void name(); EXPORT void *__neko_entry_point() { return &name; } C_FUNCTION_END #endif #ifdef HEADER_IMPORTS # define H_EXTERN IMPORT #else # define H_EXTERN EXPORT #endif #define DECLARE_PRIM(func,nargs) C_FUNCTION_BEGIN H_EXTERN void *func##__##nargs(); C_FUNCTION_END #define DECLARE_KIND(name) C_FUNCTION_BEGIN H_EXTERN extern vkind name; C_FUNCTION_END #define alloc_int32 neko_alloc_int32 #define alloc_float neko_alloc_float #define alloc_string neko_alloc_string #define alloc_empty_string neko_alloc_empty_string #define copy_string neko_copy_string #define val_this neko_val_this #define val_id neko_val_id #define val_field neko_val_field #define alloc_object neko_alloc_object #define alloc_field neko_alloc_field #define alloc_array neko_alloc_array #define val_call0 neko_val_call0 #define val_call1 neko_val_call1 #define val_call2 neko_val_call2 #define val_call3 neko_val_call3 #define val_callN neko_val_callN #define val_ocall0 neko_val_ocall0 #define val_ocall1 neko_val_ocall1 #define val_ocall2 neko_val_ocall2 #define val_ocallN neko_val_ocallN #define val_callEx neko_val_callEx #define alloc_root neko_alloc_root #define free_root neko_free_root #define alloc neko_alloc #define alloc_private neko_alloc_private #define alloc_abstract neko_alloc_abstract #define alloc_function neko_alloc_function #define alloc_buffer neko_alloc_buffer #define buffer_append neko_buffer_append #define buffer_append_sub neko_buffer_append_sub #define buffer_append_char neko_buffer_append_char #define buffer_length neko_buffer_length #define buffer_to_string neko_buffer_to_string #define val_buffer neko_val_buffer #define val_compare neko_val_compare #define val_print neko_val_print #define val_gc neko_val_gc #define val_throw neko_val_throw #define val_rethrow neko_val_rethrow #define val_iter_fields neko_val_iter_fields #define val_field_name neko_val_field_name #define val_hash neko_val_hash #define k_hash neko_k_hash #define kind_share neko_kind_share #define kind_lookup neko_kind_lookup #define alloc_local neko_alloc_local #define local_get neko_local_get #define local_set neko_local_set #define free_local neko_free_local #define alloc_lock neko_alloc_lock #define lock_acquire neko_lock_acquire #define lock_try neko_lock_try #define lock_release neko_lock_release #define free_lock neko_free_lock C_FUNCTION_BEGIN VEXTERN vkind k_hash; VEXTERN value val_null; VEXTERN value val_true; VEXTERN value val_false; EXTERN value alloc_float( tfloat t ); EXTERN value alloc_int32( int i ); EXTERN value alloc_string( const char *str ); EXTERN value alloc_empty_string( unsigned int size ); EXTERN value copy_string( const char *str, int_val size ); EXTERN value val_this(); EXTERN field val_id( const char *str ); EXTERN value val_field( value o, field f ); EXTERN value alloc_object( value o ); EXTERN void alloc_field( value obj, field f, value v ); EXTERN void val_iter_fields( value obj, void f( value v, field f, void * ), void *p ); EXTERN value val_field_name( field f ); EXTERN value alloc_array( unsigned int n ); EXTERN value alloc_abstract( vkind k, void *data ); EXTERN value val_call0( value f ); EXTERN value val_call1( value f, value arg ); EXTERN value val_call2( value f, value arg1, value arg2 ); EXTERN value val_call3( value f, value arg1, value arg2, value arg3 ); EXTERN value val_callN( value f, value *args, int nargs ); EXTERN value val_ocall0( value o, field f ); EXTERN value val_ocall1( value o, field f, value arg ); EXTERN value val_ocall2( value o, field f, value arg1, value arg2 ); EXTERN value val_ocallN( value o, field f, value *args, int nargs ); EXTERN value val_callEx( value vthis, value f, value *args, int nargs, value *exc ); EXTERN value *alloc_root( unsigned int nvals ); EXTERN void free_root( value *r ); EXTERN char *alloc( unsigned int nbytes ); EXTERN char *alloc_private( unsigned int nbytes ); EXTERN value alloc_function( void *c_prim, unsigned int nargs, const char *name ); EXTERN buffer alloc_buffer( const char *init ); EXTERN void buffer_append( buffer b, const char *s ); EXTERN void buffer_append_sub( buffer b, const char *s, int_val len ); EXTERN void buffer_append_char( buffer b, char c ); EXTERN value buffer_to_string( buffer b ); EXTERN int buffer_length( buffer b ); EXTERN void val_buffer( buffer b, value v ); EXTERN int val_compare( value a, value b ); EXTERN void val_print( value s ); EXTERN void val_gc( value v, finalizer f ); EXTERN void val_throw( value v ); EXTERN void val_rethrow( value v ); EXTERN int val_hash( value v ); EXTERN void kind_share( vkind *k, const char *name ); EXTERN vkind kind_lookup( const char *name ); EXTERN void _neko_failure( value msg, const char *file, int line ); // MULTITHREADING API EXTERN mt_local *alloc_local(); EXTERN void *local_get( mt_local *l ); EXTERN void local_set( mt_local *l, void *v ); EXTERN void free_local( mt_local *l ); EXTERN mt_lock *alloc_lock(); EXTERN void lock_acquire( mt_lock *l ); EXTERN int lock_try( mt_lock *l ); EXTERN void lock_release( mt_lock *l ); EXTERN void free_lock( mt_lock *l ); C_FUNCTION_END #endif /* ************************************************************************ */ neko-2-2-0/vm/neko_elf.h000066400000000000000000000046501321613172000150230ustar00rootroot00000000000000/* * Copyright (C)2016-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _NEKO_ELF_H #define _NEKO_ELF_H #include "neko.h" #ifdef __GNUC__ #ifdef ABI_ELF # define SEPARATE_SECTION_FOR_BYTECODE #endif #endif /* None of this is needed on non-ELF platforms... */ #ifdef SEPARATE_SECTION_FOR_BYTECODE #include #include #define elf_get_Ehdr(p,f) (elf_is_32() ? ((Elf32_Ehdr*)p)->f : ((Elf64_Ehdr*)p)->f) #define elf_get_Shdr(p,f) (elf_is_32() ? ((Elf32_Shdr*)p)->f : ((Elf64_Shdr*)p)->f) #define elf_set_Ehdr(p,f,v) { if (elf_is_32()) ((Elf32_Ehdr*)p)->f = v; else ((Elf64_Ehdr*)p)->f = v; } #define elf_set_Shdr(p,f,v) { if (elf_is_32()) ((Elf32_Shdr*)p)->f = v; else ((Elf64_Shdr*)p)->f = v; } C_FUNCTION_BEGIN VEXTERN int size_Ehdr; /* Big enough to hold Elf32_Ehdr or Elf64_Ehdr... */ VEXTERN int size_Shdr; /* Big enough to hold Elf32_Shdr or Elf64_Shdr... */ EXTERN value elf_read_header(FILE *exe); EXTERN int elf_is_32(); EXTERN value elf_read_section(FILE *exe, int sec, char *buf); EXTERN value elf_write_section(FILE *exe, int sec, char *buf); EXTERN int elf_find_bytecode_section(FILE *exe); EXTERN void elf_free_section_string_table(); EXTERN value elf_find_embedded_bytecode(const char *file, int *beg, int *end); EXTERN int elf_find_bytecode_section(FILE *exe); C_FUNCTION_END #endif #endif /* ************************************************************************ */ neko-2-2-0/vm/neko_mod.h000066400000000000000000000041431321613172000150310ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _NEKO_MOD_H #define _NEKO_MOD_H #include "neko.h" typedef struct _neko_debug { int base; unsigned int bits; } neko_debug; typedef struct _neko_module { void *jit; unsigned int nglobals; unsigned int nfields; unsigned int codesize; value name; value *globals; value *fields; value loader; value exports; value dbgtbl; neko_debug *dbgidxs; int_val *code; value jit_gc; } neko_module; typedef void *readp; typedef int (*reader)( readp p, void *buf, int size ); typedef struct { char *p; int len; } string_pos; C_FUNCTION_BEGIN VEXTERN field neko_id_module; VEXTERN vkind neko_kind_module; EXTERN neko_module *neko_read_module( reader r, readp p, value loader ); EXTERN int neko_file_reader( readp p, void *buf, int size ); // FILE * EXTERN int neko_string_reader( readp p, void *buf, int size ); // string_pos * EXTERN value neko_select_file( value path, const char *file, const char *ext ); C_FUNCTION_END #endif /* ************************************************************************ */ neko-2-2-0/vm/neko_vm.h000066400000000000000000000052611321613172000146760ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _NEKO_VM_H #define _NEKO_VM_H #include "neko.h" typedef void (*neko_printer)( const char *data, int size, void *param ); typedef void (*thread_main_func)( void *param ); typedef struct _neko_vm neko_vm; typedef void (*neko_stat_func)( neko_vm *vm, const char *kind, int start ); C_FUNCTION_BEGIN EXTERN void neko_global_init(); EXTERN void neko_global_free(); EXTERN void neko_gc_major(); EXTERN void neko_gc_loop(); EXTERN void neko_gc_stats( int *heap, int *free ); EXTERN int neko_thread_create( thread_main_func init, thread_main_func main, void *param, void **handle ); EXTERN void neko_thread_blocking( thread_main_func f, void *p ); EXTERN bool neko_thread_register( bool t ); EXTERN neko_vm *neko_vm_alloc( void *unused ); EXTERN neko_vm *neko_vm_current(); EXTERN value neko_exc_stack( neko_vm *vm ); EXTERN value neko_call_stack( neko_vm *vm ); EXTERN void *neko_vm_custom( neko_vm *vm, vkind k ); EXTERN void neko_vm_set_custom( neko_vm *vm, vkind k, void *v ); EXTERN value neko_vm_execute( neko_vm *vm, void *module ); EXTERN void neko_vm_select( neko_vm *vm ); EXTERN int neko_vm_jit( neko_vm *vm, int enable_jit ); EXTERN int neko_vm_trusted( neko_vm *vm, int trusted ); EXTERN value neko_default_loader( char **argv, int argc ); EXTERN void neko_vm_redirect( neko_vm *vm, neko_printer print, void *param ); EXTERN void neko_vm_set_stats( neko_vm *vm, neko_stat_func fstats, neko_stat_func pstats ); EXTERN void neko_vm_dump_stack( neko_vm *vm ); EXTERN int neko_is_big_endian(); C_FUNCTION_END #endif /* ************************************************************************ */ neko-2-2-0/vm/objtable.c000066400000000000000000000056341321613172000150210ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include "objtable.h" int otable_remove( objtable *t, field id ) { int min = 0; int max = t->count; int mid; field cid; objcell *c = t->cells; if( !max ) return 0; while( min < max ) { mid = (min + max) >> 1; cid = c[mid].id; if( cid < id ) min = mid + 1; else if( cid > id ) max = mid; else { t->count--; memmove(&c[mid], &c[mid + 1], (t->count - mid) * sizeof(objcell)); c[t->count].v = val_null; return 1; } } return 0; } void otable_optimize( objtable *t ) { int max = t->count; int i; int cur = 0; objcell *c = t->cells; for(i=0;icount = cur; } void otable_replace( objtable *t, field id, value data ) { int min = 0; int max = t->count; int mid; field cid; objcell *c = t->cells; const size_t objcell_size = sizeof(objcell); while( min < max ) { mid = (min + max) >> 1; cid = c[mid].id; if( cid < id ) min = mid + 1; else if( cid > id ) max = mid; else { c[mid].v = data; return; } } mid = (min + max) >> 1; c = (objcell*)alloc(objcell_size * (t->count + 1)); memcpy(c, t->cells, mid * objcell_size); c[mid].id = id; c[mid].v = data; memcpy(&c[mid + 1], &t->cells[mid], (t->count - mid) * objcell_size); t->cells = c; t->count++; } void otable_copy( objtable *t, objtable *target ) { const size_t size = sizeof(objcell) * t->count; target->count = t->count; target->cells = (objcell*)alloc(size); memcpy(target->cells,t->cells,size); } void otable_iter(objtable *t, void f( value data, field id, void *), void *p ) { int i; const int n = (const int)t->count; objcell *c = t->cells; for(i=0;icount = 0; t->cells = NULL; } static INLINE value *otable_find(objtable *t,field id) { int min; int max; int mid; objcell *c; field cid; min = 0; max = t->count; c = t->cells; while( min < max ) { mid = (min + max) >> 1; cid = c[mid].id; if( cid < id ) min = mid + 1; else if( cid > id ) max = mid; else return &c[mid].v; } return NULL; } static INLINE value otable_get(objtable *t,field id) { int min; int max; int mid; const objcell *c; field cid; min = 0; max = t->count; c = (const objcell*)t->cells; while( min < max ) { mid = (min + max) >> 1; cid = c[mid].id; if( cid < id ) min = mid + 1; else if( cid > id ) max = mid; else return c[mid].v; } return val_null; } void otable_replace(objtable *t, field id, value data); int otable_remove(objtable *t, field id); void otable_optimize(objtable *t); #define otable_count(t) (t)->count void otable_copy(objtable *t, objtable *target); void otable_iter(objtable *t, void f( value data, field id, void *), void *p ); #endif /* ************************************************************************ */ neko-2-2-0/vm/opcodes.h000066400000000000000000000102711321613172000146710ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _NEKO_OPCODES_H #define _NEKO_OPCODES_H #ifndef OP # define OP(x) x # define OPBEGIN enum OPCODE { # define OPEND }; #endif OPBEGIN OP(AccNull), OP(AccTrue), OP(AccFalse), OP(AccThis), OP(AccInt), OP(AccStack), OP(AccGlobal), OP(AccEnv), OP(AccField), OP(AccArray), OP(AccIndex), OP(AccBuiltin), OP(SetStack), OP(SetGlobal), OP(SetEnv), OP(SetField), OP(SetArray), OP(SetIndex), OP(SetThis), OP(Push), OP(Pop), OP(Call), OP(ObjCall), OP(Jump), OP(JumpIf), OP(JumpIfNot), OP(Trap), OP(EndTrap), OP(Ret), OP(MakeEnv), OP(MakeArray), OP(Bool), OP(IsNull), OP(IsNotNull), OP(Add), OP(Sub), OP(Mult), OP(Div), OP(Mod), OP(Shl), OP(Shr), OP(UShr), OP(Or), OP(And), OP(Xor), OP(Eq), OP(Neq), OP(Gt), OP(Gte), OP(Lt), OP(Lte), OP(Not), OP(TypeOf), OP(Compare), OP(Hash), OP(New), OP(JumpTable), OP(Apply), OP(AccStack0), OP(AccStack1), OP(AccIndex0), OP(AccIndex1), OP(PhysCompare), OP(TailCall), OP(Loop), OP(MakeArray2), OP(AccInt32), OP(Last), OPEND #ifdef PARAMETER_TABLE static int parameter_table[] = { 0, // AccNull 0, // AccTrue 0, // AccFalse 0, // AccThis 1, // AccInt 1, // AccStack 1, // AccGlobal 1, // AccEnv 1, // AccField 0, // AccArray 1, // AccIndex 1, // AccBuiltin 1, // SetStack 1, // SetGlobal 1, // SetEnv 1, // SetField 0, // SetArray 1, // SetIndex 0, // SetThis 0, // Push 1, // Pop 1, // Call 1, // ObjCall 1, // Jump 1, // JumpIf 1, // JumpIfNot 1, // Trap 0, // EndTrap 1, // Ret 1, // MakeEnv 1, // MakeArray 0, // Bool 0, // IsNull 0, // IsNotNull 0, // Add 0, // Sub 0, // Mult 0, // Div 0, // Mod 0, // Shl 0, // Shr 0, // UShr 0, // Or 0, // And 0, // Xor 0, // Eq 0, // Neq 0, // Gt 0, // Gte 0, // Lt 0, // Lte 0, // Not 0, // TypeOf 0, // Compare 0, // Hash 0, // New 1, // JumpTable 1, // Apply 0, // AccStack0 0, // AccStack1 0, // AccIndex0 0, // AccIndex1 0, // PhysCompare 1, // TailCall 0, // Loop 1, // MakeArray2 1, // AccInt32 }; #endif #ifdef STACK_TABLE #define P 0xFF static int stack_table[] = { 0, // AccNull 0, // AccTrue 0, // AccFalse 0, // AccThis 0, // AccInt 0, // AccStack 0, // AccGlobal 0, // AccEnv 0, // AccField -1, // AccArray 0, // AccIndex 0, // AccBuiltin 0, // SetStack 0, // SetGlobal 0, // SetEnv -1, // SetField -2, // SetArray -1, // SetIndex 0, // SetThis 1, // Push -P, // Pop -P, // Call -P, // ObjCall 0, // Jump 0, // JumpIf 0, // JumpIfNot 6, // Trap -6, // EndTrap 0, // Ret -P, // MakeEnv -P, // MakeArray 0, // Bool 0, // IsNull 0, // IsNotNull -1, // Add -1, // Sub -1, // Mult -1, // Div -1, // Mod -1, // Shl -1, // Shr -1, // UShr -1, // Or -1, // And -1, // Xor -1, // Eq -1, // Neq -1, // Gt -1, // Gte -1, // Lt -1, // Lte 0, // Not 0, // TypeOf -1, // Compare 0, // Hash 0, // New 0, // JumpTable -P, // Apply 0, // AccStack0 0, // AccStack1 0, // AccIndex0 0, // AccIndex1 -1, // PhysCompare 0, // TailCall 0, // Loop -P, // MakeArray2 0, // AccInt32 0, // Last }; #endif #endif /* ************************************************************************ */ neko-2-2-0/vm/others.c000066400000000000000000000321451321613172000145400ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "neko.h" #include "objtable.h" #include "vm.h" #define C(x,y) ((x << 8) | y) #define FLOAT_FMT "%.15g" DEFINE_KIND(k_hash); extern mt_lock *neko_fields_lock; extern objtable *neko_fields; extern field id_compare; extern field id_string; extern char *jit_handle_trap; typedef void (*jit_handle)( neko_vm * ); static INLINE int icmp( int a, int b ) { return (a == b)?0:((a < b)?-1:1); } static INLINE int fcmp( tfloat a, tfloat b ) { if(a != a || b != b) return invalid_comparison; return (a == b)?0:((a < b)?-1:1); } static INLINE int scmp( const char *s1, int l1, const char *s2, int l2 ) { int r = memcmp(s1,s2,(l1 < l2)?l1:l2); return r?r:icmp(l1,l2); } EXTERN int val_compare( value a, value b ) { char tmp_buf[32]; switch( C(val_type(a),val_type(b)) ) { case C(VAL_INT,VAL_INT): return icmp(val_int(a),val_int(b)); case C(VAL_INT32,VAL_INT): return icmp(val_int32(a),val_int(b)); case C(VAL_INT,VAL_INT32): return icmp(val_int(a),val_int32(b)); case C(VAL_INT32,VAL_INT32): return icmp(val_int32(a),val_int32(b)); case C(VAL_INT,VAL_FLOAT): return fcmp(val_int(a),val_float(b)); case C(VAL_INT32,VAL_FLOAT): return fcmp(val_int32(a),val_float(b)); case C(VAL_INT,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,"%d",val_int(a)),val_string(b),val_strlen(b)); case C(VAL_INT32,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,"%d",val_int32(a)),val_string(b),val_strlen(b)); case C(VAL_FLOAT,VAL_INT): return fcmp(val_float(a),val_int(b)); case C(VAL_FLOAT,VAL_INT32): return fcmp(val_float(a),val_int32(b)); case C(VAL_FLOAT,VAL_FLOAT): return fcmp(val_float(a),val_float(b)); case C(VAL_FLOAT,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,FLOAT_FMT,val_float(a)),val_string(b),val_strlen(b)); case C(VAL_STRING,VAL_INT): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,"%d",val_int(b))); case C(VAL_STRING,VAL_INT32): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,"%d",val_int32(b))); case C(VAL_STRING,VAL_FLOAT): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,FLOAT_FMT,val_float(b))); case C(VAL_STRING,VAL_BOOL): return scmp(val_string(a),val_strlen(a),val_bool(b)?"true":"false",val_bool(b)?4:5); case C(VAL_BOOL,VAL_STRING): return scmp(val_bool(a)?"true":"false",val_bool(a)?4:5,val_string(b),val_strlen(b)); case C(VAL_STRING,VAL_STRING): return scmp(val_string(a),val_strlen(a),val_string(b),val_strlen(b)); case C(VAL_BOOL,VAL_BOOL): return (a == b) ? 0 : (val_bool(a) ? 1 : -1); case C(VAL_OBJECT,VAL_OBJECT): if( a == b ) return 0; { value tmp = val_field(a,id_compare); if( tmp == val_null ) return invalid_comparison; a = val_callEx(a,tmp,&b,1,NULL); } if( val_is_int(a) ) return val_int(a); return invalid_comparison; default: if( a == b ) return 0; return invalid_comparison; } } typedef struct _stringitem { char *str; int size; int len; struct _stringitem *next; } * stringitem; struct _buffer { int totlen; int blen; stringitem data; }; EXTERN buffer alloc_buffer( const char *init ) { buffer b = (buffer)alloc(sizeof(struct _buffer)); b->totlen = 0; b->blen = 16; b->data = NULL; if( init ) buffer_append(b,init); return b; } static void buffer_append_new( buffer b, const char *s, int len ) { int size; stringitem it; while( b->totlen >= (b->blen << 2) ) b->blen <<= 1; size = (len < b->blen)?b->blen:len; it = (stringitem)alloc(sizeof(struct _stringitem)); it->str = alloc_private(size); memcpy(it->str,s,len); it->size = size; it->len = len; it->next = b->data; b->data = it; } EXTERN void buffer_append_sub( buffer b, const char *s, int_val _len ) { stringitem it; int len = (int)_len; if( s == NULL || len <= 0 ) return; b->totlen += len; it = b->data; if( it ) { int free = it->size - it->len; if( free >= len ) { memcpy(it->str + it->len,s,len); it->len += len; return; } else { memcpy(it->str + it->len,s,free); it->len += free; s += free; len -= free; } } buffer_append_new(b,s,len); } EXTERN void buffer_append( buffer b, const char *s ) { if( s == NULL ) return; buffer_append_sub(b,s,strlen(s)); } EXTERN void buffer_append_char( buffer b, char c ) { stringitem it; b->totlen++; it = b->data; if( it && it->len != it->size ) { it->str[it->len++] = c; return; } buffer_append_new(b,&c,1); } EXTERN value buffer_to_string( buffer b ) { value v = alloc_empty_string(b->totlen); stringitem it = b->data; char *s = (char*)val_string(v) + b->totlen; while( it != NULL ) { stringitem tmp; s -= it->len; memcpy(s,it->str,it->len); tmp = it->next; it = tmp; } return v; } EXTERN int buffer_length( buffer b ) { return b->totlen; } typedef struct vlist { value v; struct vlist *next; } vlist; typedef struct vlist2 { value v; struct vlist *next; buffer b; int prev; } vlist2; static void val_buffer_rec( buffer b, value v, vlist *stack ); static void val_buffer_fields( value v, field f, void *_l ) { vlist2 *l = (vlist2*)_l; if( l->prev ) buffer_append_sub(l->b,", ",2); else { buffer_append_sub(l->b," ",1); l->prev = 1; } val_buffer(l->b,val_field_name(f)); buffer_append_sub(l->b," => ",4); val_buffer_rec(l->b,v,(vlist*)l); } static void val_buffer_rec( buffer b, value v, vlist *stack ) { char buf[32]; int i, l; vlist *vtmp = stack; while( vtmp != NULL ) { if( vtmp->v == v ) { buffer_append_sub(b,"...",3); return; } vtmp = vtmp->next; } switch( val_type(v) ) { case VAL_INT: buffer_append_sub(b,buf,sprintf(buf,"%d",val_int(v))); break; case VAL_STRING: buffer_append_sub(b,val_string(v),val_strlen(v)); break; case VAL_FLOAT: buffer_append_sub(b,buf,sprintf(buf,FLOAT_FMT,val_float(v))); break; case VAL_NULL: buffer_append_sub(b,"null",4); break; case VAL_BOOL: if( val_bool(v) ) buffer_append_sub(b,"true",4); else buffer_append_sub(b,"false",5); break; case VAL_FUNCTION: buffer_append_sub(b,buf,sprintf(buf,"#function:%d",val_fun_nargs(v))); break; case VAL_OBJECT: { value s = val_field(v,id_string); if( s != val_null ) s = val_callEx(v,s,NULL,0,NULL); if( val_is_string(s) ) buffer_append_sub(b,val_string(s),val_strlen(s)); else { vlist2 vtmp; vtmp.v = v; vtmp.next = stack; vtmp.b = b; vtmp.prev = 0; buffer_append_sub(b,"{",1); val_iter_fields(v,val_buffer_fields,&vtmp); if( vtmp.prev ) buffer_append_sub(b," }",2); else buffer_append_sub(b,"}",1); } break; } case VAL_ARRAY: buffer_append_sub(b,"[",1); l = val_array_size(v); { vlist vtmp; vtmp.v = v; vtmp.next = stack; for(i=0;itmp,"%d",x); v = alloc_empty_string(len+len2); if( way ) { memcpy((char*)val_string(v),val_string(str),len); memcpy((char*)val_string(v)+len,vm->tmp,len2+1); } else { memcpy((char*)val_string(v),vm->tmp,len2); memcpy((char*)val_string(v)+len2,val_string(str),len+1); } return v; } value neko_append_strings( value s1, value s2 ) { int len1 = val_strlen(s1); int len2 = val_strlen(s2); value v = alloc_empty_string(len1+len2); memcpy((char*)val_string(v),val_string(s1),len1); memcpy((char*)val_string(v)+len1,val_string(s2),len2+1); return v; } int neko_stack_expand( int_val *sp, int_val *csp, neko_vm *vm ) { int i; int size = (int)((((int_val)vm->spmax - (int_val)vm->spmin) / sizeof(int_val)) << 1); int_val *nsp; if( size > MAX_STACK_SIZE ) { vm->sp = sp; vm->csp = csp; return 0; } nsp = (int_val*)alloc(size * sizeof(int_val)); // csp size i = (int)(((int_val)(csp + 1) - (int_val)vm->spmin) / sizeof(int_val)); memcpy(nsp,vm->spmin,sizeof(int_val) * i); vm->csp = nsp + i - 1; // sp size i = (int)(((int_val)vm->spmax - (int_val)sp) / sizeof(int_val)); memcpy(nsp+size-i,sp,sizeof(int_val) * i); vm->sp = nsp + size - i; vm->spmin = nsp; vm->spmax = nsp + size; return 1; } EXTERN field val_id( const char *name ) { objtable *t; value fdata; field f; value acc = alloc_int(0); const char *oname = name; while( *name ) { acc = alloc_int(223 * val_int(acc) + *((unsigned char*)name)); name++; } f = val_int(acc); t = &neko_fields[f&NEKO_FIELDS_MASK]; fdata = otable_get(t,f); if( fdata == val_null ) { // insert in the table, but by using a larger table that grows faster // since we don't want to resize the table for each insert int min; int max; int mid; field cid; objcell *c; lock_acquire(neko_fields_lock); min = 0; max = t->count; c = t->cells; while( min < max ) { mid = (min + max) >> 1; cid = c[mid].id; if( cid < f ) min = mid + 1; else if( cid > f ) max = mid; else { fdata = c[mid].v; break; } } // in case we found it, it means that it's been inserted by another thread if( fdata == val_null ) { const size_t objcell_size = sizeof(objcell); objcell *c2 = (objcell*)alloc(objcell_size * (t->count + 1)); // copy the whole table mid = (min + max) >> 1; memcpy(c2, c, mid * objcell_size); c2[mid].id = f; c2[mid].v = copy_string(oname,name - oname); memcpy(&c2[mid + 1], &c[mid], (t->count - mid) * objcell_size); // update t->cells = c2; t->count++; } lock_release(neko_fields_lock); } if( fdata != val_null && scmp(val_string(fdata),val_strlen(fdata),oname,(int)(name - oname)) != 0 ) { buffer b = alloc_buffer("Field conflict between "); val_buffer(b,fdata); buffer_append(b," and "); buffer_append(b,oname); bfailure(b); } return f; } EXTERN value val_field_name( field id ) { return otable_get(&neko_fields[id&NEKO_FIELDS_MASK],id); } EXTERN value val_field( value _o, field id ) { value *f; vobject *o = (vobject*)_o; do { f = otable_find(&o->table,id); if( f != NULL ) return *f; o = o->proto; } while( o ); return val_null; } EXTERN void val_iter_fields( value o, void f( value , field, void * ) , void *p ) { otable_iter( &((vobject*)o)->table, f, p ); } EXTERN void val_print( value v ) { neko_vm *vm; if( !val_is_string(v) ) { buffer b = alloc_buffer(NULL); val_buffer(b,v); v = buffer_to_string(b); } vm = NEKO_VM(); vm->print( val_string(v), val_strlen(v), vm->print_param ); } EXTERN void val_throw( value v ) { neko_vm *vm = NEKO_VM(); vm->exc_stack = alloc_array(0); vm->vthis = v; if( *(char**)vm->start == jit_handle_trap ) ((jit_handle)jit_handle_trap)(vm); else longjmp(vm->start,1); } EXTERN void val_rethrow( value v ) { neko_vm *vm = NEKO_VM(); vm->vthis = v; if( *(char**)vm->start == jit_handle_trap ) ((jit_handle)jit_handle_trap)(vm); else longjmp(vm->start,1); } static value failure_to_string() { value o = val_this(); buffer b = alloc_buffer(NULL); val_check(o,object); val_buffer(b,val_field(o,val_id("file"))); buffer_append(b,"("); val_buffer(b,val_field(o,val_id("line"))); buffer_append(b,") : "); val_buffer(b,val_field(o,val_id("msg"))); return buffer_to_string(b); } EXTERN void _neko_failure( value msg, const char *file, int line ) { char *fname = strrchr(file,'/'); char *fname2 = strrchr(file,'\\'); value o = alloc_object(NULL); if( fname2 > fname ) fname = fname2; alloc_field(o,val_id("msg"),msg); alloc_field(o,val_id("file"),alloc_string(fname?(fname+1):file)); alloc_field(o,val_id("line"),alloc_int(line)); alloc_field(o,id_string,alloc_function(failure_to_string,0,"failure_to_string")); val_throw(o); } /* ************************************************************************ */ neko-2-2-0/vm/stats.c000066400000000000000000000125511321613172000143710ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include "neko_vm.h" #ifdef NEKO_WINDOWS # include #else # include #endif typedef struct _statinfos { const char *kind; int ksize; int ncalls; int nerrors; int subtime; int totaltime; int starttime; struct _statinfos *stack; struct _statinfos *next; } statinfos; static statinfos *list = NULL; static statinfos *stack = NULL; static int init_done = 0; static int precise_timer() { # ifdef NEKO_WINDOWS LARGE_INTEGER t; static LARGE_INTEGER freq; if( !init_done ) { DWORD procs, sm, procid = 1; // ensure that we always use the same processor // or else, performance counter might vary depending // on the current CPU GetProcessAffinityMask(GetCurrentProcess(),&procs,&sm); while( !(procs & procid) ) procid <<= 1; SetProcessAffinityMask(GetCurrentProcess(),procid); init_done = 1; QueryPerformanceFrequency(&freq); } QueryPerformanceCounter(&t); return (int)( t.QuadPart * 1000000 / freq.QuadPart ); # else static int base_sec; struct timeval tv; gettimeofday(&tv,NULL); if( !init_done ) { init_done = 1; base_sec = tv.tv_sec; } return (tv.tv_sec - base_sec) * 1000000 + tv.tv_usec; # endif } void neko_stats_measure( neko_vm *vm, const char *kind, int start ) { int ksize = (int)strlen(kind); statinfos *s; if( start ) { int time = precise_timer(); // lookup in list s = list; while( s ) { if( ksize == s->ksize && s->starttime == 0 && memcmp(kind,s->kind,ksize) == 0 ) break; s = s->next; } // init if( s == NULL ) { s = (statinfos*)malloc(sizeof(statinfos)); s->kind = strdup(kind); s->ksize = ksize; s->ncalls = 0; s->nerrors = 0; s->totaltime = 0; s->subtime = 0; s->next = list; list = s; } // add to stack s->ncalls++; s->stack = stack; stack = s; s->starttime = time; } else { // lookup on stack s = stack; while( s ) { statinfos *next; if( ksize == s->ksize && memcmp(kind,s->kind,ksize) == 0 ) break; next = s->stack; s->nerrors++; // stop was not done (exception) s->starttime = 0; s = next; } // pop from stack if( s ) { int delta = precise_timer() - s->starttime; s->totaltime += delta; stack = s->stack; if( stack ) stack->subtime += delta; s->starttime = 0; } else stack = NULL; } } // merged-sort for linked list static int cmp( statinfos *a, statinfos *b ) { int delta = a->totaltime - b->totaltime; if( delta == 0 ) return b->ncalls - a->ncalls; return delta; } static statinfos *sort( statinfos *list ) { statinfos *p, *q, *e, *tail; int insize, nmerges, psize, qsize, i; insize = 1; while( list ) { p = list; list = NULL; tail = NULL; nmerges = 0; while( p ) { nmerges++; q = p; psize = 0; for(i=0;inext; if (!q) break; } qsize = insize; while (psize > 0 || (qsize > 0 && q)) { if( psize == 0 ) { e = q; q = q->next; qsize--; } else if( qsize == 0 || !q ) { e = p; p = p->next; psize--; } else if( cmp(p,q) <= 0 ) { e = p; p = p->next; psize--; } else { e = q; q = q->next; qsize--; } if( tail ) tail->next = e; else list = e; tail = e; } p = q; } tail->next = NULL; if( nmerges <= 1 ) return list; insize *= 2; } return NULL; } value neko_stats_build( neko_vm *vm ) { value v = val_null; statinfos *s = list; // merge duplicates while( s ) { statinfos *s2 = s->next, *prev = s; while( s2 ) { if( s2->ksize == s->ksize && memcmp(s->kind,s2->kind,s->ksize) == 0 ) { s->nerrors += s2->nerrors; s->ncalls += s2->ncalls; s->totaltime += s2->totaltime; s->subtime += s2->subtime; prev->next = s2->next; free(s2); s2 = prev->next; } else { prev = s2; s2 = s2->next; } } s = s->next; } list = sort(list); s = list; while( s ) { value tmp = alloc_array(6); val_array_ptr(tmp)[0] = alloc_string(s->kind); val_array_ptr(tmp)[1] = alloc_int(s->totaltime); val_array_ptr(tmp)[2] = alloc_int(s->totaltime - s->subtime); val_array_ptr(tmp)[3] = alloc_int(s->ncalls); val_array_ptr(tmp)[4] = alloc_int(s->nerrors); val_array_ptr(tmp)[5] = v; v = tmp; s = s->next; } return v; } neko-2-2-0/vm/threads.c000066400000000000000000000206131321613172000146630ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifdef __APPLE__ // prevent later redefinition of bool # include #endif #include "vm.h" #include #if !defined(NEKO_THREADS) #include struct _mt_local { void *value; }; #else #ifdef NEKO_WINDOWS // necessary for TryEnterCriticalSection // which is only available on 2000 PRO and XP # define _WIN32_WINNT 0x0400 # define GC_NOT_DLL # define GC_WIN32_THREADS #endif #define GC_THREADS #include #if GC_VERSION_MAJOR < 7 # define GC_SUCCESS 0 # define GC_DUPLICATE 1 #endif #ifdef NEKO_WINDOWS struct _mt_lock { CRITICAL_SECTION cs; }; #else #include #include struct _mt_local { pthread_key_t key; }; struct _mt_lock { pthread_mutex_t lock; }; // should be enough to store any GC_stack_base // implementation typedef char __stack_base[64]; #endif #endif // !NEKO_THREADS typedef struct { thread_main_func init; thread_main_func main; void *param; #ifdef NEKO_THREADS # ifdef NEKO_WINDOWS HANDLE lock; # else pthread_mutex_t lock; # endif #endif } tparams; #ifdef NEKO_THREADS #ifdef NEKO_WINDOWS # define THREAD_FUN DWORD WINAPI #else # define THREAD_FUN void * #endif typedef int (*rec)( int, void * ); static int clean_c_stack( int n, void *f ) { char buf[256]; memset(buf,n,sizeof(buf)); if( n == 0 ) return *buf; return ((rec)f)(n-1,f) ? 1 : 0; // prevent tail-rec } static THREAD_FUN ThreadMain( void *_p ) { tparams *lp = (tparams*)_p; tparams p = *lp; p.init(p.param); // we have the 'param' value on this thread C stack // so it's safe to give back control to main thread # ifdef NEKO_WINDOWS ReleaseSemaphore(p.lock,1,NULL); # else pthread_mutex_unlock(&lp->lock); # endif clean_c_stack(40,clean_c_stack); p.main(p.param); return 0; } #endif EXTERN int neko_thread_create( thread_main_func init, thread_main_func main, void *param, void **handle ) { tparams p; p.init = init; p.main = main; p.param = param; # if !defined(NEKO_THREADS) return 0; # elif defined(NEKO_WINDOWS) { HANDLE h; p.lock = CreateSemaphore(NULL,0,1,NULL); h = GC_CreateThread(NULL,0,ThreadMain,&p,0,(void*)handle); if( h == NULL ) { CloseHandle(p.lock); return 0; } WaitForSingleObject(p.lock,INFINITE); CloseHandle(p.lock); CloseHandle(h); return 1; } # else pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); pthread_mutex_init(&p.lock,NULL); pthread_mutex_lock(&p.lock); // force the use of a the GC method to capture created threads // this function should be defined in gc/gc.h if( GC_pthread_create((pthread_t*)handle,&attr,&ThreadMain,&p) != 0 ) { pthread_attr_destroy(&attr); pthread_mutex_destroy(&p.lock); return 0; } pthread_mutex_lock(&p.lock); pthread_attr_destroy(&attr); pthread_mutex_destroy(&p.lock); return 1; # endif } #if defined(NEKO_POSIX) && defined(NEKO_THREADS) # include typedef void (*callb_func)( thread_main_func, void * ); typedef int (*std_func)(); typedef int (*gc_stack_ptr)( __stack_base * ); static int do_nothing( __stack_base *sb ) { return -1; } #endif EXTERN void neko_thread_blocking( thread_main_func f, void *p ) { # if !defined(NEKO_THREADS) f(p); // nothing # elif defined(NEKO_WINDOWS) f(p); // we don't have pthreads issues # else // we have different APIs depending on the GC version, make sure we load // the good one at runtime static callb_func do_blocking = NULL; static std_func start = NULL, end = NULL; if( do_blocking ) do_blocking(f,p); else if( start ) { start(); f(p); end(); } else { void *self = dlopen(NULL,0); do_blocking = (callb_func)dlsym(self,"GC_do_blocking"); if( !do_blocking ) { start = (std_func)dlsym(self,"GC_start_blocking"); end = (std_func)dlsym(self,"GC_end_blocking"); if( !start || !end ) val_throw(alloc_string("Could not init GC blocking API")); } neko_thread_blocking(f,p); } # endif } EXTERN bool neko_thread_register( bool t ) { # if !defined(NEKO_THREADS) return 0; # elif defined(NEKO_WINDOWS) struct GC_stack_base sb; int r; if( !t ) return GC_unregister_my_thread() == GC_SUCCESS; if( GC_get_stack_base(&sb) != GC_SUCCESS ) return 0; r = GC_register_my_thread(&sb); return( r == GC_SUCCESS || r == GC_DUPLICATE ); # else // since the API is only available on GC 7.0, // we will do our best to locate it dynamically static gc_stack_ptr get_sb = NULL, my_thread = NULL; static std_func unreg_my_thread = NULL; if( !t && unreg_my_thread != NULL ) { return unreg_my_thread() == GC_SUCCESS; } else if( my_thread != NULL ) { __stack_base sb; int r; if( get_sb(&sb) != GC_SUCCESS ) return 0; r = my_thread(&sb); return( r == GC_SUCCESS || r == GC_DUPLICATE ); } else { void *self = dlopen(NULL,0); my_thread = (gc_stack_ptr)dlsym(self,"GC_register_my_thread"); get_sb = (gc_stack_ptr)dlsym(self,"GC_get_stack_base"); unreg_my_thread = (std_func)dlsym(self,"GC_unregister_my_thread"); if( my_thread == NULL ) my_thread = do_nothing; if( get_sb == NULL ) get_sb = do_nothing; if( unreg_my_thread == NULL ) unreg_my_thread = (std_func)do_nothing; return neko_thread_register(t); } # endif } EXTERN mt_local *alloc_local() { # if !defined(NEKO_THREADS) mt_local *l = malloc(sizeof(mt_local)); l->value = NULL; return l; # elif defined(NEKO_WINDOWS) DWORD t = TlsAlloc(); TlsSetValue(t,NULL); return (mt_local*)(int_val)t; # else mt_local *l = malloc(sizeof(mt_local)); pthread_key_create(&l->key,NULL); return l; # endif } EXTERN void free_local( mt_local *l ) { # if !defined(NEKO_THREADS) free(l); # elif defined(NEKO_WINDOWS) TlsFree((DWORD)(int_val)l); # else pthread_key_delete(l->key); free(l); # endif } EXTERN void local_set( mt_local *l, void *v ) { # if !defined(NEKO_THREADS) l->value = v; # elif defined(NEKO_WINDOWS) TlsSetValue((DWORD)(int_val)l,v); # else pthread_setspecific(l->key,v); # endif } EXTERN void *local_get( mt_local *l ) { if( l == NULL ) return NULL; # if !defined(NEKO_THREADS) return l->value; # elif defined(NEKO_WINDOWS) return (void*)TlsGetValue((DWORD)(int_val)l); # else return pthread_getspecific(l->key); # endif } EXTERN mt_lock *alloc_lock() { # if !defined(NEKO_THREADS) return (mt_lock*)1; # elif defined(NEKO_WINDOWS) mt_lock *l = (mt_lock*)malloc(sizeof(mt_lock)); InitializeCriticalSection(&l->cs); return l; # else mt_lock *l = (mt_lock*)malloc(sizeof(mt_lock)); pthread_mutexattr_t a; pthread_mutexattr_init(&a); pthread_mutexattr_settype(&a,PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&l->lock,&a); pthread_mutexattr_destroy(&a); return l; # endif } EXTERN void lock_acquire( mt_lock *l ) { # if !defined(NEKO_THREADS) # elif defined(NEKO_WINDOWS) EnterCriticalSection(&l->cs); # else pthread_mutex_lock(&l->lock); # endif } EXTERN int lock_try( mt_lock *l ) { #if !defined(NEKO_THREADS) return 1; # elif defined(NEKO_WINDOWS) return TryEnterCriticalSection(&l->cs); # else return pthread_mutex_trylock(&l->lock) == 0; # endif } EXTERN void lock_release( mt_lock *l ) { # if !defined(NEKO_THREADS) # elif defined(NEKO_WINDOWS) LeaveCriticalSection(&l->cs); # else pthread_mutex_unlock(&l->lock); # endif } EXTERN void free_lock( mt_lock *l ) { # if !defined(NEKO_THREADS) # elif defined(NEKO_WINDOWS) DeleteCriticalSection(&l->cs); free(l); # else pthread_mutex_destroy(&l->lock); free(l); # endif } /* ************************************************************************ */ neko-2-2-0/vm/vm.h000066400000000000000000000043151321613172000136610ustar00rootroot00000000000000/* * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _NEKO_VMCONTEXT_H #define _NEKO_VMCONTEXT_H #include #include "neko_vm.h" #define INIT_STACK_SIZE (1 << 8) #define MAX_STACK_SIZE (1 << 18) #define MAX_STACK_PER_FUNCTION 128 #define PROF_SIZE (1 << 20) #define CALL_MAX_ARGS 5 #define NEKO_FIELDS_MASK 63 typedef struct _custom_list { vkind tag; void *custom; struct _custom_list *next; } custom_list; struct _neko_vm { int_val *sp; int_val *csp; value env; value vthis; int_val *spmin; int_val *spmax; int_val trap; void *jit_val; jmp_buf start; void *c_stack_max; int run_jit; value exc_stack; neko_printer print; void *print_param; custom_list *clist; value resolver; char tmp[100]; int trusted_code; neko_stat_func fstats; neko_stat_func pstats; }; extern int_val *callback_return; extern mt_local *neko_vm_context; #define NEKO_VM() ((neko_vm*)local_get(neko_vm_context)) extern value neko_alloc_apply( int nargs, value env ); extern value neko_interp( neko_vm *vm, void *m, int_val acc, int_val *pc ); extern int_val *neko_get_ttable(); #endif /* ************************************************************************ */