summaryrefslogtreecommitdiff
path: root/erts/lib_src
diff options
context:
space:
mode:
Diffstat (limited to 'erts/lib_src')
-rw-r--r--erts/lib_src/Makefile.in3
-rw-r--r--erts/lib_src/common/erl_misc_utils.c260
-rw-r--r--erts/lib_src/common/erl_printf.c5
-rw-r--r--erts/lib_src/common/erl_printf_format.c5
-rw-r--r--erts/lib_src/common/ethr_aux.c3
-rw-r--r--erts/lib_src/yielding_c_fun/.gitignore16
-rw-r--r--erts/lib_src/yielding_c_fun/GNUmakefile212
-rw-r--r--erts/lib_src/yielding_c_fun/Makefile54
-rw-r--r--erts/lib_src/yielding_c_fun/README.md610
-rw-r--r--erts/lib_src/yielding_c_fun/TODO4
-rwxr-xr-xerts/lib_src/yielding_c_fun/bin/yielding_c_fun42
-rw-r--r--erts/lib_src/yielding_c_fun/doc/thread_tutorial.md222
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/.gitignore11
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/.misc/clang_blacklist.txt10
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/GIT_VERSION73
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/LICENSE201
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/Makefile121
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/README.md69
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/chained_hash_set.h307
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.c310
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.h57
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/sorted_list_set.h370
-rw-r--r--erts/lib_src/yielding_c_fun/lib/simple_c_gc/test.c53
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/GIT_VERSION468
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/LICENSE24
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/Makefile106
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md138
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.c470
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.h54
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/exrex.py307
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test.py77
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test_neg.py82
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test1.c141
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test2.c2097
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_print.c21
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand.c28
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand_neg.c29
-rw-r--r--erts/lib_src/yielding_c_fun/main_target.mk26
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/auto_yield.c124
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/auto_yield.c.out173
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/const_defenition.c54
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/const_defenition.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/consume_reds.c85
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/consume_reds.c.out11
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/control_statements.c289
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/control_statements.c.out45
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c129
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c.out11
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c131
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c.out11
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c54
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/declarations.c91
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/declarations.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c83
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c.out211
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c92
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c.out33
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c54
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c93
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c.out9
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c91
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c.out11
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c104
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c.out74
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/.gitignore25
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/LICENSE191
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/Makefile34
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/README.md23
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/Makefile83
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.gitignore3
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.travis.yml2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/GIT_VERSION265
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/LICENSE24
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/Makefile11
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md97
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c224
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.h4
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c210
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/test.c238
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c173
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/rebar.config12
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.app.src14
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.erl27
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/test/basic_SUITE.erl32
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c92
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_yield.c58
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_yield.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c61
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c111
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c.out18
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/stack_array.c135
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/stack_array.c.out4
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c71
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_code.c66
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c71
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c.out302
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c60
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/test_trap.c42
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/thread_example.c88
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/thread_example.c.out47
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/void_param.c79
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/void_param.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c85
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c126
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c.out15
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c67
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c.out2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c68
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c.out10
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c104
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c.out302
-rwxr-xr-xerts/lib_src/yielding_c_fun/test/test.sh176
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_helpers.h40
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_lexer.c483
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_lists.h316
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_main.c330
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_node.c915
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_node.h455
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_parser.c1498
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_parser.h27
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_printers.c493
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_printers.h30
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_string.c111
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_string.h89
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_symbol.c166
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_symbol.h110
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_utils.c106
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_utils.h40
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_yield_fun.c1625
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_yield_fun.h116
137 files changed, 20056 insertions, 17 deletions
diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in
index 1da11c2d0a..85250c4358 100644
--- a/erts/lib_src/Makefile.in
+++ b/erts/lib_src/Makefile.in
@@ -152,7 +152,6 @@ ERTS_INCL_INT=../include/internal
INCLUDES=-I$(ERTS_INCL) -I$(ERTS_INCL)/$(TARGET) -I$(ERTS_INCL_INT) -I$(ERTS_INCL_INT)/$(TARGET)
INCLUDES += -I../emulator/beam -I../emulator/sys/$(ERLANG_OSTYPE)
-USING_MINGW=@MIXED_CYGWIN_MINGW@
USING_VC=@MIXED_VC@
ifeq ($(USING_VC),yes)
@@ -657,8 +656,10 @@ endif
endif
@echo "# EOF" >> $(DEPEND_MK);
+ifneq ($(ERTS_SKIP_DEPEND),true)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPEND_MK)
endif
+endif
# eof
diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c
index c75c492c9d..e047c0eec7 100644
--- a/erts/lib_src/common/erl_misc_utils.c
+++ b/erts/lib_src/common/erl_misc_utils.c
@@ -29,10 +29,7 @@
#include "ethread_inline.h"
#include "erl_misc_utils.h"
-#if defined(__WIN32__)
-#elif defined(VXWORKS)
-# include <selectLib.h>
-#else /* UNIX */
+#if !defined(__WIN32__) /* UNIX */
# include <stdio.h>
# include <sys/types.h>
# include <sys/param.h>
@@ -54,6 +51,7 @@
# endif
# endif
# include <string.h>
+# include <stdio.h>
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
@@ -133,6 +131,7 @@
#endif
static int read_topology(erts_cpu_info_t *cpuinfo);
+static int read_cpu_quota(int limit);
#if defined(ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__)
static int
@@ -176,6 +175,7 @@ struct erts_cpu_info_t_ {
int online;
int available;
int topology_size;
+ int quota;
erts_cpu_topology_t *topology;
#if defined(ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__)
char *affinity_str;
@@ -238,6 +238,7 @@ erts_cpu_info_create(void)
cpuinfo->configured = -1;
cpuinfo->online = -1;
cpuinfo->available = -1;
+ cpuinfo->quota = -1;
erts_cpu_info_update(cpuinfo);
return cpuinfo;
}
@@ -269,6 +270,7 @@ erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
int configured = 0;
int online = 0;
int available = 0;
+ int quota = 0;
erts_cpu_topology_t *old_topology;
int old_topology_size;
#if defined(ERTS_HAVE_MISC_UTIL_AFFINITY_MASK__)
@@ -412,9 +414,14 @@ erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
if (cpuinfo->available != available)
changed = 1;
+ quota = read_cpu_quota(online);
+ if (cpuinfo->quota != quota)
+ changed = 1;
+
cpuinfo->configured = configured;
cpuinfo->online = online;
cpuinfo->available = available;
+ cpuinfo->quota = quota;
old_topology = cpuinfo->topology;
old_topology_size = cpuinfo->topology_size;
@@ -471,6 +478,16 @@ erts_get_cpu_available(erts_cpu_info_t *cpuinfo)
return cpuinfo->available;
}
+int
+erts_get_cpu_quota(erts_cpu_info_t *cpuinfo)
+{
+ if (!cpuinfo)
+ return -EINVAL;
+ if (cpuinfo->quota <= 0)
+ return -ENOTSUP;
+ return cpuinfo->quota;
+}
+
char *
erts_get_unbind_from_cpu_str(erts_cpu_info_t *cpuinfo)
{
@@ -775,7 +792,7 @@ adjust_processor_nodes(erts_cpu_info_t *cpuinfo, int no_nodes)
#ifdef __linux__
static int
-read_file(char *path, char *buf, int size)
+read_file(const char *path, char *buf, int size)
{
int ix = 0;
ssize_t sz = size-1;
@@ -1004,6 +1021,211 @@ read_topology(erts_cpu_info_t *cpuinfo)
return res;
}
+static int
+csv_contains(const char *haystack,
+ const char *element,
+ char separator) {
+ size_t element_len;
+ const char *ptr;
+
+ element_len = strlen(element);
+ ptr = strstr(haystack, element);
+
+ while (ptr) {
+ if (!ptr[element_len] || ptr[element_len] == separator) {
+ if (ptr == haystack || ptr[-1] == separator) {
+ return 1;
+ }
+ }
+
+ ptr = strstr(&ptr[1], element);
+ }
+
+ return 0;
+}
+
+static const char*
+str_combine(const char *a, const char *b) {
+ size_t a_len, b_len;
+ char *result;
+
+ a_len = strlen(a);
+ b_len = strlen(b);
+
+ result = malloc(a_len + b_len + 1);
+
+ memcpy(&result[0], a, a_len);
+ memcpy(&result[a_len], b, b_len + 1);
+
+ return result;
+}
+
+static const char*
+get_cgroup_v1_base_dir(const char *controller) {
+ char line_buf[5 << 10];
+ FILE *var_file;
+
+ var_file = fopen("/proc/self/cgroup", "r");
+
+ if (var_file == NULL) {
+ return NULL;
+ }
+
+ while (fgets(line_buf, sizeof(line_buf), var_file)) {
+ /* sscanf_s requires C11, so we use hardcoded sizes (rather than rely
+ * on macros like MAXPATHLEN) so we can specify them directly in the
+ * format string. */
+ char base_dir[4 << 10];
+ char controllers[256];
+
+ if (sscanf(line_buf, "%*d:%255[^:]:%4095s\n",
+ controllers, base_dir) != 2) {
+ continue;
+ }
+
+ if (csv_contains(controllers, controller, ',')) {
+ fclose(var_file);
+ return strdup(base_dir);
+ }
+ }
+
+ fclose(var_file);
+ return NULL;
+}
+
+static const char*
+get_cgroup_path(const char *controller) {
+ char line_buf[10 << 10];
+ FILE *var_file;
+
+ var_file = fopen("/proc/self/mountinfo", "r");
+
+ if (var_file == NULL) {
+ return NULL;
+ }
+
+ while (fgets(line_buf, sizeof(line_buf), var_file)) {
+ char mount_path[4 << 10];
+ char root_path[4 << 10];
+ char fs_flags[512];
+ char fs_type[64];
+
+ /* Format:
+ * [Mount id] [Parent id] [Major] [Minor] [Root] [Mounted at] \
+ * [Mount flags] ... (options terminated by a single hyphen) ... \
+ * [FS type] [Mount source] [Flags]
+ *
+ * (See proc(5) for a more complete description.)
+ *
+ * This fails if any of the fs options contain a hyphen, but this is
+ * not likely to happen on a cgroup, so we just skip such lines. */
+ if (sscanf(line_buf,
+ "%*d %*d %*d:%*d %4095s %4095s %*s %*[^-]- "
+ "%63s %*s %511[^\n]\n",
+ root_path, mount_path,
+ fs_type, fs_flags) != 4) {
+ continue;
+ }
+
+ if (!strcmp(fs_type, "cgroup2")) {
+ char controllers[256];
+ const char *cgc_path;
+
+ cgc_path = str_combine(mount_path, "/cgroup.controllers");
+ if (read_file(cgc_path, controllers, sizeof(controllers)) > 0) {
+ if (csv_contains(controllers, controller, ' ')) {
+ free((void*)cgc_path);
+ fclose(var_file);
+ return strdup(mount_path);
+ }
+ }
+ free((void*)cgc_path);
+ } else if (!strcmp(fs_type, "cgroup")) {
+ if (csv_contains(fs_flags, controller, ',')) {
+ const char *base_dir = get_cgroup_v1_base_dir(controller);
+
+ if (base_dir) {
+ const char *result;
+
+ if (strcmp(root_path, base_dir)) {
+ result = str_combine(mount_path, base_dir);
+ } else {
+ result = strdup(mount_path);
+ }
+
+ free((void*)base_dir);
+ fclose(var_file);
+ return result;
+ }
+ }
+ }
+ }
+
+ fclose(var_file);
+ return NULL;
+}
+
+static int read_cgroup_var(const char *group_path, const char *var_name,
+ ssize_t *out) {
+ const char *var_path;
+ int res;
+
+ var_path = str_combine(group_path, var_name);
+ res = 0;
+
+ if (var_path) {
+ FILE *var_file = fopen(var_path, "r");
+ free((void*)var_path);
+
+ if (var_file) {
+ if (fscanf(var_file, "%zi", out) == 1) {
+ res = 1;
+ }
+ fclose(var_file);
+ }
+ }
+
+ return res;
+}
+
+/* CPU quotas are read from the cgroup configuration, which can be pretty hairy
+ * as we need to support both v1 and v2, and it's possible for both versions to
+ * be active at the same time. */
+
+static int
+read_cpu_quota(int limit)
+{
+ const char *cgroup_path = get_cgroup_path("cpu");
+
+ if (cgroup_path) {
+ ssize_t cfs_period_us, cfs_quota_us;
+ int succeeded;
+
+ cfs_period_us = -1;
+ cfs_quota_us = -1;
+
+ succeeded =
+ read_cgroup_var(cgroup_path, "/cpu.cfs_quota_us", &cfs_quota_us) &&
+ read_cgroup_var(cgroup_path, "/cpu.cfs_period_us", &cfs_period_us);
+
+ free((void*)cgroup_path);
+
+ if (succeeded) {
+ if (cfs_period_us > 0 && cfs_quota_us > 0) {
+ size_t quota = cfs_quota_us / cfs_period_us;
+
+ if (quota > 0 && quota <= (size_t)limit) {
+ return quota;
+ }
+ }
+
+ return limit;
+ }
+ }
+
+ return 0;
+}
+
#elif defined(HAVE_KSTAT) /* SunOS kstat */
#include <kstat.h>
@@ -1157,6 +1379,13 @@ read_topology(erts_cpu_info_t *cpuinfo)
}
+static int
+read_cpu_quota(int limit)
+{
+ (void)limit;
+ return 0;
+}
+
#elif defined(__WIN32__)
/*
@@ -1431,6 +1660,13 @@ read_topology(erts_cpu_info_t *cpuinfo)
return res;
}
+static int
+read_cpu_quota(int limit)
+{
+ (void)limit;
+ return 0;
+}
+
#elif defined(__FreeBSD__)
/**
@@ -1670,9 +1906,23 @@ error:
return res;
}
+static int
+read_cpu_quota(int limit)
+{
+ (void)limit;
+ return 0;
+}
+
#else
static int
+read_cpu_quota(int limit)
+{
+ (void)limit;
+ return 0;
+}
+
+static int
read_topology(erts_cpu_info_t *cpuinfo)
{
return -ENOTSUP;
diff --git a/erts/lib_src/common/erl_printf.c b/erts/lib_src/common/erl_printf.c
index dd808eb158..9c33a107d1 100644
--- a/erts/lib_src/common/erl_printf.c
+++ b/erts/lib_src/common/erl_printf.c
@@ -18,11 +18,6 @@
* %CopyrightEnd%
*/
-/* Without this, variable argument lists break on VxWorks */
-#ifdef VXWORKS
-#include <vxWorks.h>
-#endif
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c
index 8f9e0b4a90..c8256532b5 100644
--- a/erts/lib_src/common/erl_printf_format.c
+++ b/erts/lib_src/common/erl_printf_format.c
@@ -31,11 +31,6 @@
* sz: 8 | 16 | 32 | 64 | p | e
*/
-/* Without this, variable argument lists break on VxWorks */
-#ifdef VXWORKS
-#include <vxWorks.h>
-#endif
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c
index 7b156fe01a..931469b386 100644
--- a/erts/lib_src/common/ethr_aux.c
+++ b/erts/lib_src/common/ethr_aux.c
@@ -109,7 +109,8 @@ x86_init(void)
if (eax > 0
&& (ETHR_IS_X86_VENDOR("GenuineIntel", ebx, ecx, edx)
- || ETHR_IS_X86_VENDOR("AuthenticAMD", ebx, ecx, edx))) {
+ || ETHR_IS_X86_VENDOR("AuthenticAMD", ebx, ecx, edx)
+ || ETHR_IS_X86_VENDOR("HygonGenuine", ebx, ecx, edx))) {
eax = 1;
ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
}
diff --git a/erts/lib_src/yielding_c_fun/.gitignore b/erts/lib_src/yielding_c_fun/.gitignore
new file mode 100644
index 0000000000..eb74315e49
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/.gitignore
@@ -0,0 +1,16 @@
+*.o
+*~
+bin/yielding_c_fun.bin
+core
+test/test_trap_out.c
+GPATH
+GRTAGS
+GTAGS
+test/tmp_dir
+compile_commands.json
+compile_commands_old.json
+CMakeLists.txt
+cmake_mkdir/
+.idea/
+cmake-build-debug/
+ycf_malloc_log.txt \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/GNUmakefile b/erts/lib_src/yielding_c_fun/GNUmakefile
new file mode 100644
index 0000000000..1a18214c21
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/GNUmakefile
@@ -0,0 +1,212 @@
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+#
+# 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.
+#
+# %CopyrightEnd%
+
+#
+# Author: Kjell Winblad
+#
+
+#
+# Note: The main target of this makefile generates another makefile
+# which is named "Makefile". The generated file "Makefile" should be
+# compatible with other make implementations than GNU make while this
+# file is only compatible with GNU make. GNU make will automatically
+# use this file as makefile when executed in the directory where this
+# file is located.
+#
+# Erlang/OTP note: The build system for Erlang/OTP does not use this
+# file to build Yielding C Fun (YCF). The file "main_target.mk"
+# contains the necessary rules to build YCF and is included both by
+# this file and the Erlang/OTP file
+# $(ERL_TOP)/erts/emulator/Makefile.in. This file is intended for
+# building YCF independently of Erlang/OTP. This file also contains
+# several special make targets (e.g., to invoke tests).
+#
+
+
+ifdef MODERN_CC
+ EXTRA_C_FLAGS = -g -O02 -std=c99 -pedantic -Wall
+endif
+
+ifdef CC_32_BIT
+ EXTRA_C_FLAGS = -m32 -g -O03 -std=c99 -pedantic -Wall
+endif
+
+ifdef USE_GC
+ USE_GC_STRING = -use_gc
+endif
+
+ifdef ADD_SAN
+ V_CC = clang
+ EXTRA_C_FLAGS = -std=c99 -Wall -pedantic -g -O00 -fsanitize-blacklist=lib/simple_c_gc/.misc/clang_blacklist.txt -fsanitize=address -fno-omit-frame-pointer
+ USE_GC_STRING = -use_gc
+endif
+
+ifdef MEM_SAN
+ V_CC = clang
+ EXTRA_C_FLAGS = -std=c99 -Wall -pedantic -g -O00 -fsanitize-blacklist=lib/simple_c_gc/.misc/clang_blacklist.txt -fsanitize=memory -fno-omit-frame-pointer
+endif
+
+ifdef UB_SAN
+ V_CC = clang
+ EXTRA_C_FLAGS = -std=c99 -Wall -pedantic -g -O00 -fsanitize-blacklist=lib/simple_c_gc/.misc/clang_blacklist.txt -fsanitize=undefined -fno-omit-frame-pointer
+endif
+
+
+YCF_SOURCE_DIR = .
+
+ifndef V_CC
+ V_CC = cc
+endif
+
+ifndef V_LD
+ V_LD = $(CC)
+endif
+
+CFLAGS = $(EXTRA_C_FLAGS)
+
+all: ./bin/yielding_c_fun.bin Makefile
+
+include main_target.mk
+
+##############################################################
+# Generate a simple Makefile intended to work with other make
+# implementations than GNU make
+##############################################################
+
+Makefile: $(YCF_SOURCES)
+ echo '#' > Makefile
+ echo '# !!!!!!!!!!! OBS Generated by GNUmakefile !!!!!!!!!!!!' >> Makefile
+ echo '# This file is supposed to be compatible with as many make implementations as possible' >> Makefile
+ echo '# Do not modify this file manually unless you cannot use GNU make.' >> Makefile
+ echo '# Instead, just run GNU make in the directory where this file is located' >> Makefile
+ echo '# and a new version of this file will be generated when needed.' >> Makefile
+ echo '# GNU make will use the file GNUmakefile which is located in the same' >> Makefile
+ echo '# directory.' >> Makefile
+ echo '#' >> Makefile
+ echo '#' >> Makefile
+ echo '# Erlang/OTP note: The build system for Erlang/OTP does not use this' >> Makefile
+ echo '# file to build Yielding C Fun (YCF). The file "main_target.mk"' >> Makefile
+ echo '# contains the necessary rules to build YCF and is included both by' >> Makefile
+ echo '# this file and the Erlang/OTP file' >> Makefile
+ echo '# $$(ERL_TOP)/erts/emulator/Makefile.in. This file is intended for' >> Makefile
+ echo '# building YCF independently of Erlang/OTP.' >> Makefile
+ echo '#' >> Makefile
+ echo >> Makefile
+ O_FILES="";\
+ for FILE in $(YCF_SOURCES);\
+ do\
+ OFILE_FULL=`echo $$FILE | sed 's/\.c/.o/'` ; \
+ OFILE=`basename $$OFILE_FULL` ; \
+ O_FILES="$$O_FILES $$OFILE" ; \
+ done ; \
+ echo $(YCF_EXECUTABLE)':' $$O_FILES >> Makefile ; \
+ echo ' $$(CC) $(YCF_INCLUDE_DIRS) $$(CFLAGS) -o '$(YCF_EXECUTABLE)' ' $$O_FILES >> Makefile
+ for FILE in $(YCF_SOURCES);\
+ do\
+ echo >> Makefile ; \
+ OFILE_FULL=`echo $$FILE | sed 's/\.c/.o/'` ; \
+ OFILE=`basename $$OFILE_FULL` ; \
+ echo "$$OFILE: $$FILE" >> Makefile ;\
+ echo ' $$(CC) $(YCF_INCLUDE_DIRS) $$(CFLAGS) ' -c -o $$OFILE $$FILE >> Makefile ;\
+ done
+ echo >> Makefile
+
+##############################################
+# Special targets for testing etc:
+##############################################
+
+.PHONY: all clean test run_test_continusly CMakeLists.txt cmake_compile clang_format test_add_san test_mem_san test_modern_cc test_sanitizers test_gcc_clang_tcc clang_tidy test_bmake test_all
+
+test: $(YCF_EXECUTABLE)
+ ./test/test.sh $(USE_GC_STRING) ;\
+ RESULT=$$? &&\
+ (exit $$RESULT) &&\
+ printf "\n\n\033[0;32mALL TESTS PASSED!\033[0m\n\n\n" ||\
+ printf "\n\n\033[0;31mTEST FAILED!\033[0m\n\n\n" &&\
+ exit $$RESULT
+
+test_add_san:
+ make clean && \
+ make V_CC=clang V_LD=clang ADD_SAN=1 test
+
+test_mem_san:
+ make clean && \
+ make V_CC=clang V_LD=clang MEM_SAN=1 test
+
+test_ub_san:
+ make clean && \
+ make V_CC=clang V_LD=clang UB_SAN=1 test
+
+test_modern_cc:
+ make clean && \
+ make V_CC=clang V_LD=clang MODERN_CC=1 test
+
+test_sanitizers:
+ make test_add_san && \
+ make test_mem_san && \
+ make test_ub_san
+
+test_gcc_clang_tcc:
+ make V_CC=gcc V_LD=gcc EXTRA_C_FLAGS="-g -O01 -std=c99 -pedantic -Wall -Werror" clean $(YCF_EXECUTABLE) && \
+ make V_CC=clang V_LD=clang EXTRA_C_FLAGS="-g -O01 -std=c99 -pedantic -Wall -Werror" clean $(YCF_EXECUTABLE) && \
+ make V_CC=tcc V_LD=tcc EXTRA_C_FLAGS="-g -O01 -std=c99 -pedantic -Wall -Werror" clean $(YCF_EXECUTABLE)
+
+test_32_bit:
+ make clean && \
+ make CC_32_BIT=1 test && \
+ make clean
+
+# sudo apt-get install bmake
+# test that something else than GNU make can compile the tool
+test_bmake:
+ make clean && \
+ make Makefile && \
+ bmake
+
+test_all:
+ make test_gcc_clang_tcc && \
+ make clang_tidy && \
+ make test_sanitizers && \
+ make test_modern_cc && \
+ make test_32_bit && \
+ make test_bmake
+
+run_test_continusly:
+ inotifywait -e close_write,moved_to,create -m ./*.c ./*.h -m test -m test/examples | while read -r directory events filename; do gtags ; make test_all ; done
+
+cmake_compile: CMakeLists.txt
+ mkdir cmake_mkdir || true
+ cd cmake_mkdir && cmake ..
+
+clang_tidy:
+ (ls *.c ; echo lib/tiny_regex_c/re.c ; echo lib/simple_c_gc/simple_c_gc.c) | xargs -I{} -n1 clang-tidy -warnings-as-errors=* {} -- $(YCF_INCLUDE_DIRS) $(YCF_CFLAGS)
+
+clang_format:
+ clang-format -style="{BasedOnStyle: LLVM}" -i *.c *.h
+
+clean:
+ rm -f lib/simple_c_gc/*.o lib/tiny_regex_c/*.o ./*.o ./*~ core trap parse $(YCF_EXECUTABLE) CMakeLists.txt
+
+# Produce a CMakeLists.txt to build with cmake
+CMakeLists.txt: $(YCF_SOURCES)
+ echo "cmake_minimum_required (VERSION 2.6)" > CMakeLists.txt
+ echo "project (YIELDING_C_FUN C)" >> CMakeLists.txt
+ echo "add_executable(cmake.out " >> CMakeLists.txt
+ echo $(YCF_SOURCES) >> CMakeLists.txt
+ echo ")" >> CMakeLists.txt
+
diff --git a/erts/lib_src/yielding_c_fun/Makefile b/erts/lib_src/yielding_c_fun/Makefile
new file mode 100644
index 0000000000..35de0a86ac
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/Makefile
@@ -0,0 +1,54 @@
+#
+# !!!!!!!!!!! OBS Generated by GNUmakefile !!!!!!!!!!!!
+# This file is supposed to be compatible with as many make implementations as possible
+# Do not modify this file manually unless you cannot use GNU make.
+# Instead, just run GNU make in the directory where this file is located
+# and a new version of this file will be generated when needed.
+# GNU make will use the file GNUmakefile which is located in the same
+# directory.
+#
+#
+# Erlang/OTP note: The build system for Erlang/OTP does not use this
+# file to build Yielding C Fun (YCF). The file "main_target.mk"
+# contains the necessary rules to build YCF and is included both by
+# this file and the Erlang/OTP file
+# $(ERL_TOP)/erts/emulator/Makefile.in. This file is intended for
+# building YCF independently of Erlang/OTP.
+#
+
+./bin/yielding_c_fun.bin: simple_c_gc.o re.o ycf_lexer.o ycf_main.o ycf_node.o ycf_parser.o ycf_printers.o ycf_string.o ycf_symbol.o ycf_utils.o ycf_yield_fun.o
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -o ./bin/yielding_c_fun.bin simple_c_gc.o re.o ycf_lexer.o ycf_main.o ycf_node.o ycf_parser.o ycf_printers.o ycf_string.o ycf_symbol.o ycf_utils.o ycf_yield_fun.o
+
+simple_c_gc.o: ./lib/simple_c_gc/simple_c_gc.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o simple_c_gc.o ./lib/simple_c_gc/simple_c_gc.c
+
+re.o: ./lib/tiny_regex_c/re.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o re.o ./lib/tiny_regex_c/re.c
+
+ycf_lexer.o: ./ycf_lexer.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_lexer.o ./ycf_lexer.c
+
+ycf_main.o: ./ycf_main.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_main.o ./ycf_main.c
+
+ycf_node.o: ./ycf_node.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_node.o ./ycf_node.c
+
+ycf_parser.o: ./ycf_parser.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_parser.o ./ycf_parser.c
+
+ycf_printers.o: ./ycf_printers.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_printers.o ./ycf_printers.c
+
+ycf_string.o: ./ycf_string.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_string.o ./ycf_string.c
+
+ycf_symbol.o: ./ycf_symbol.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_symbol.o ./ycf_symbol.c
+
+ycf_utils.o: ./ycf_utils.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_utils.o ./ycf_utils.c
+
+ycf_yield_fun.o: ./ycf_yield_fun.c
+ $(CC) -I. -I./lib/tiny_regex_c -I./lib/simple_c_gc $(CFLAGS) -c -o ycf_yield_fun.o ./ycf_yield_fun.c
+
diff --git a/erts/lib_src/yielding_c_fun/README.md b/erts/lib_src/yielding_c_fun/README.md
new file mode 100644
index 0000000000..f63475e6a8
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/README.md
@@ -0,0 +1,610 @@
+Yielding C Fun
+==============
+
+Introduction
+------------
+
+Yielding C Fun (YCF) is a tool that transforms functions written in a
+subset of the C programming language so that they become yieldable. A
+yieldable function can be suspended/yielded/paused/trapped (either
+automatically or where the user has inserted a particular statement)
+and then be resumed at a later point. Yileldable functions are also
+called [coroutines](https://en.wikipedia.org/wiki/Coroutine).
+
+Difference Between Yielding C Fun and Coroutine Libraries
+---------------------------------------------------------
+
+Several libraries implement [coroutine support for the C programming
+language](https://en.wikipedia.org/wiki/Coroutine#Implementations_for_C)
+(e.g., \[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11],
+[12], [13]\]). These libraries either rely on platform-specific code
+or do not save call stack variables. Yielding C Fun (YCF) does not
+have any of these two limitations. YCF can accomplish this as it is a
+source-to-source transformation tool and not only a library.
+
+YCF has been created to make it easier to implement yielding Erlang
+[NIFs](http://erlang.org/doc/tutorial/nif.html) and
+[BIFs](http://erlang.org/pipermail/erlang-questions/2009-October/046899.html)
+(i.e., Erlang functions that are written in C). Below are examples of
+YCF features that are useful when implementing yielding Erlang NIFs
+and BIFs:
+
+ * YCF automatically generates a destroy function for each yieldable
+ function. The destroy function frees resources that are used by a
+ suspended function. The destroy function is useful when a suspended
+ function needs to abort (e.g., when the Erlang process that invoked
+ the function has died).
+
+ * YCF can automatically insert code that yields functions after a
+ user specifiable number of loop iterations and goto statements.
+
+ * YCF has a hook system that lets the user insert code that is
+ triggered when certain events happen (e.g., when a function
+ yields).
+
+The main limitations of YCF are that it cannot handle all valid C code
+and that it cannot make library functions without source code
+yieldable. Pointers to stack-allocated data are also not allowed (YCF
+has a memory allocation function called `YCF_STACK_ALLOC` to work
+around this issue).
+
+Requirements
+------------
+
+* A C99 compatible C compiler
+* make (optional but useful for building)
+
+Compile and Test
+----------------
+
+Build the executable `$YCF_ROOT/bin/yielding_c_fun.bin`:
+
+ make
+
+Build the executable and run all tests:
+
+ make test
+
+Getting Started
+---------------
+
+A brief introduction tutorial can be found
+[here](doc/thread_tutorial.md). This tutorial is a perfect place to
+start!
+
+The "[test/examples/](test/examples/)" folder in this repository
+contains many small examples that are useful when learning about
+YCF. YCF's automatic tests use these examples as well. The driver for
+these tests is located in `test/test.sh`.
+
+[This Erlang NIF example](test/examples/sha256_erlang_nif/) shows how
+one can use YCF to write a yielding Erlang NIF library.
+
+
+Command Line Parameters
+-----------------------
+
+```
+Usage: yielding_c_fun [-h]
+ yielding_c_fun [-use_gc [-print_gc_info]]
+ [-log_max_mem_usage log_file]
+ [(( -f | -frec | -fnoauto ) function_name)...
+ [-output_file_name output_file]
+ [-header_file_name header_file]
+ [-debug]
+ [-only_yielding_funs]
+ [-static_aux_funs]
+ input_c_file]]
+```
+
+* `-h`
+
+ Print help text
+
+* `-use_gc`
+
+ Use garbage collection. The garbage collection system assumes that
+ the C call stack consists of a continuous memory block and is
+ therefore not enabled by default even though this assumption is
+ valid on all major platforms. YCF does not reclaim any allocated
+ memory if the `-use_gc` flag is not set.
+
+* `-print_gc_info`
+
+ (For debugging) Print garbage collection information to `stderr`
+
+* `-log_max_mem_usage log_file`
+
+ (For debugging) Print the peak memory usage of the tool to the file
+ `log_file`
+
+* `-fnoauto function_name`
+
+ Generate a yieldable version of the function named
+ function_name. The user can use `YCF_YIELD()`,
+ `YCF_YIELD_NO_REDS()`, and `YCF_CONSUME_REDS(N)` to control
+ when and where the function should yield. See the section titled
+ "Special Statements and Macros" for more information.
+
+* `-f function_name`
+
+ Generate a yieldable version of the function named
+ `function_name`. The generated function automatically decrements the
+ reduction counter by one at the beginning of loop bodies and before
+ goto statements. The function yields automatically if the reduction
+ counter reaches a value that is zero or smaller after it has been
+ decremented.
+
+* `-frec function_name`
+
+ Same as the -f option with the exception that the generated function
+ also decrements one reduction before calls to other yieldable
+ functions and before returning. The function yields automatically if
+ the reduction counter reaches a value that is zero or smaller after
+ it has been decremented.
+
+* `-output_file_name output_file`
+
+ Output the generated code to a file named output_file. The output
+ is printed to standard output if this parameter is unspecified.
+
+* `-header_file_name header_file`
+
+ Generate a header file containing only declarations for the generated
+ functions and write the header file to the file named header_file.
+
+* `-debug`
+
+ Generate debug code that executes when a function yields. The debug
+ code searches the call stack of the yielding functions for pointers
+ to data that is allocated on the call stack. The program crashes
+ with an error message if any such pointer is found.
+
+* `-only_yielding_funs`
+
+ Print only the generated functions and struct declarations. The
+ default behavior is to insert the generated functions into a copy of
+ the input source file.
+
+* `-static_aux_funs`
+
+ Make the generated auxiliary functions static (i.e., local to the C
+ compilation unit)
+
+* `input_c_file`
+
+ The source file containing the functions that YCF shall create
+ yieldable versions of. YCF does not do any macro expansions. There
+ are several restrictions on the code that YCF can handle that are
+ described in the "Code Restrictions" section below.
+
+Generated Functions
+-------------------
+
+YCF generates three functions for each function name that it is
+given. These functions have the original function name as prefix and
+different suffixes. Descriptions of the functions that YCF generates
+follows below:
+
+
+```c
+
+/* Shall return a pointer to a memory block of size size bytes. */
+typedef void* (*ycf_yield_alloc_type) (size_t size ,void* ctx);
+/* Shall free the memory block which block points to. */
+typedef void (*ycf_yield_free_type) (void* block,void* ctx);
+
+return_type_of_orginal_fun
+original_fun_name_ycf_gen_yielding(
+ long * ycf_nr_of_reductions,
+ void ** ycf_yield_state,
+ void * ycf_extra_context,
+ ycf_yield_alloc_type ycf_yield_alloc,
+ ycf_yield_free_type ycf_yield_free,
+ void * ycf_yield_alloc_free_context,
+ size_t ycf_stack_alloc_size_or_max_size,
+ void* ycf_stack_alloc_data
+ paremeters_of_orginal_function);
+```
+
+The generated function with suffix `_ycf_gen_yielding` initiates the
+call of a yieldable function. Its parameters and return types are
+described below:
+
+* `return_type_of_orginal_fun`
+
+ The return type is the same as the return type of the original
+ function. The return value is the return value of the function if
+ the `_ycf_gen_yielding` function returns without yielding and is
+ uninitialized otherwise.
+
+* `long * ycf_nr_of_reductions`
+
+ (input/output parameter) Gives the yieldable function the number of
+ reductions it can consume before yielding and is also used to write
+ back the number of reductions that are left when the function
+ returns or yields.
+
+* `void ** ycf_yield_state`
+
+ (input/output parameter) Should be a pointer to a pointer to NULL
+ when the `_ycf_gen_yielding` function is called. The value pointed
+ to by ycf_yield_state is NULL when the `_ycf_gen_yielding` function
+ has returned if it did not yield and points to the yield state
+ otherwise.
+
+* `void * ycf_extra_context`
+
+ This parameter is useful if the yieldable function needs to access
+ data that may change when it resumes after having been yielded. The
+ extra context can be accessed from within the yieldable function
+ with the `YCF_GET_EXTRA_CONTEXT()` function.
+
+* `ycf_yield_alloc_type ycf_yield_alloc`
+
+ A memory allocator function that is used by the yieldable function
+ to allocate memory (e.g., to save the state when the function
+ yields).
+
+* `ycf_yield_free ycf_yield_free`
+
+ A memory free function that should free a memory block that has been
+ allocated with ycf_yield_alloc.
+
+* `void * ycf_yield_alloc_free_context`
+
+ A context that is passed as the second argument to `ycf_yield_alloc`
+ and `ycf_yield_free`.
+
+* `size_t ycf_stack_alloc_size_or_max_size`
+
+ The max number of total bytes that can be allocated with the special
+ allocator `YCF_STACK_ALLOC(n)`. This can be set to 0 if
+ `YCF_STACK_ALLOC(n)` is unused. See the documentation of
+ `YCF_STACK_ALLOC(n)` below for more information.
+
+* `void* ycf_stack_alloc_data`
+
+ A pointer to a data block that will be used by
+ `YCF_STACK_ALLOC(n)`. The value of `ycf_stack_alloc_data` should be
+ `NULL` or a pointer to a data block that is least
+ `ycf_stack_alloc_size_or_max_size` bytes large if
+ `YCF_STACK_ALLOC(n)` is used within the yieldable function or any
+ yieldable function that is called by the yieldable function. The
+ `ycf_yield_alloc` and `ycf_yield_free` functions will be used to
+ automatically alloc and free a data block when needed, if
+ `ycf_stack_alloc_data` is set to `NULL`. The value of
+ `ycf_stack_alloc_data` does not matter if `YCF_STACK_ALLOC(n)` is
+ unused.
+
+* `paremeters_of_orginal_function`
+
+ Parameters that the original function takes will be placed in the
+ end of the parameter list of the `ycf_gen_yielding` function.
+
+
+```c
+return_type_of_orginal_fun
+original_fun_name_ycf_gen_continue(
+ long * ycf_nr_of_reduction,
+ void ** ycf_yield_state,
+ void * ycf_extra_context);
+```
+
+The generated function with the suffix `_ycf_gen_continue` is used to
+resume a yielded function. The descriptions of the parameters and
+return type for the `_ycf_gen_yielding` function above are valid for
+the `_ycf_gen_continue` function as well, with the exception that the
+parameter `ycf_yield_state` should point to a pointer to a yield state
+(created in the previous call to `_ycf_gen_yielding` or
+`_ycf_gen_continue`).
+
+```c
+void original_fun_name_ycf_gen_destroy(void * ycf_yield_state);
+```
+
+The `_gen_destroy` function frees the state of a yieldable function
+that has been suspended. Note that the parameter `ycf_yield_state`
+points directly to the yield state, unlike the parameter of the
+`_ycf_gen_yielding` and `_ycf_gen_continue` functions with the same
+name.
+
+
+
+The `YCF_YIELD_CODE_GENERATED` Macro
+------------------------------------
+
+YCF also generates code that defines the macro
+`YCF_YIELD_CODE_GENERATED`. This macro may be useful if one wants to
+compile one version of a program with yieldable functions and another
+without yieldable functions.
+
+Special Statements and Macros
+-----------------------------
+
+Some special statements and macros can be used from within a yieldable
+function. Descriptions of those follow below:
+
+* `YCF_YIELD();`
+
+ The `YCF_YIELD();` statement sets the reduction counter to zero
+ and yields the function when it is executed.
+
+* `YCF_YIELD_NO_REDS();`
+
+ The `YCF_YIELD_NO_REDS();` statement yields the function
+ without changing the reduction counter when it is executed.
+
+* `YCF_CONSUME_REDS(N);`
+
+ The `YCF_CONSUME_REDS(N);` statement decrements the
+ reductions counter by N and yields if the reduction counter is less
+ than or equal to zero after the decrement.
+
+* `YCF_STACK_ALLOC(N)`
+
+ The `YCF_STACK_ALLOC(N)` macro uses an allocator that is included in
+ the code generated by YCF to allocate a block with `N` bytes and
+ return a pointer to these bytes. A block that has been allocated
+ with `YCF_STACK_ALLOC(N)` is automatically freed when the function
+ that allocated the block returns. Memory blocks that are allocated
+ with `YCF_STACK_ALLOC(N)` do not move when a yieldable function
+ yields and then resumes again. In contrast, data that is allocated
+ directly on the call stack may move when a function yields and
+ resumes. `YCF_STACK_ALLOC(N)` can thus be useful if one wants to
+ port C code that has variables that point to data that is allocated
+ on the call stack. The parameters `ycf_stack_alloc_size_or_max_size`
+ and `ycf_stack_alloc_data` of the `_ycf_gen_yielding` function need
+ to be set correctly if `YCF_STACK_ALLOC(N)` is used. Please see the
+ description of the `_ycf_gen_yielding` function in the "Generated
+ Functions" section above for details about those parameters. Notice
+ also that the `-debug` flag that is described in the "Command Line
+ Parameters" section above can be useful when one wants to find out
+ if a function points to data that is allocated on the call stack of
+ a yieldable function.
+
+* `YCF_GET_EXTRA_CONTEXT()`
+
+ The `YCF_GET_EXTRA_CONTEXT()` macro returns the value of the
+ `ycf_extra_context` parameter that was passed to the latest call of
+ one of the corresponding `_ycf_gen_yielding` or `_ycf_gen_continue`
+ functions. See the "Generated Functions" section above for
+ information about the parameters of `_ycf_gen_yielding` and
+ `_ycf_gen_continue` functions.
+
+* `YCF_NR_OF_REDS_LEFT()`
+
+ The `YCF_NR_OF_REDS_LEFT()` macro returns the current value of
+ the reduction counter (a value of type `long`).
+
+* `YCF_SET_NR_OF_REDS_LEFT(NEW_NR_OF_REDS_LEFT)`
+
+ The `YCF_SET_NR_OF_REDS_LEFT(NEW_NR_OF_REDS_LEFT)` macro sets
+ the value that the reduction counter (which stores a value of type
+ `long`) to `NEW_NR_OF_REDS_LEFT`.
+
+* `YCF_MAX_NR_OF_REDS`
+
+ The `YCF_MAX_NR_OF_REDS` macro returns the maximum value that the
+ reduction counter may have.
+
+Code Restrictions
+-----------------
+
+YCF cannot parse all valid C code. The code restrictions that
+yieldable functions need to follow are described below. It is
+recommended to check that the generated code is correct.
+
+* **Declarations**
+
+ Variable declarations and parameters of yieldable functions need to
+ be in the following form:
+
+ ```
+ "(optional) type descriptor (i.e., struct, union or enum)"
+
+ "type name"
+
+ "(optional) one or more star characters (i.e., *)"
+
+ "variable name"
+
+ "(optional) one or more square brackets with a number inside (e.g, [3])"
+
+ "(optional) one or more empty square brackets (e.g, [])"
+
+ "(optional) equal sign followed by an expression (automatic array
+ initialization and struct initialization of the form
+ {.filed_name=value...} are not allowed)"
+
+ "semicolon"
+ ```
+
+ Here are some examples of declarations that are **correct**:
+
+ ```c
+ int var1;
+ int var2 = 1;
+ int var3 = var2 + 1;
+ int var4 = function(var3);
+ int * var5 = malloc(sizeof(int*));
+ int ** var6 = malloc(sizeof(int*)*10);
+ int ***** var7;
+ struct struct_name var8;
+ struct struct_name var9 = function2();
+ double var10[128];
+ double var11[128][];
+ double * var12[128];
+ ```
+
+ Here are examples of declarations that are **incorrect**:
+
+ ```c
+ int var1, var2;
+ int var1 = 1, var2 = 10;
+ void (*printer_t)(int);
+ ```
+
+ Note that one has to use a `typedef` to be able to declare a
+ function pointer variable.
+
+* **Pointers**
+
+ Pointers to call-stack-allocated data are not allowed. The
+ `YCF_YIELD_ALLOC(N)` function, which is described in the "Special
+ Statements and Macros" section above, can be used to work around
+ this limitation. The `-debug` flag that is described in the "Command
+ Line Parameters" section above, can be useful when one wants to find
+ out if a yieldable function points to call-stack-allocated data.
+
+
+* **Macros**
+
+ YCF does not expand macros so macros in functions that YCF
+ transforms should not "hide" variables or any other code that is
+ relevant for yielding.
+
+* **Calls to a Yieldable Function from Another Yieldable Function**
+
+ Calls to a yieldable function from another yieldable function need
+ to be in a form that YCF recognizes. Such calls need to be in one of
+ the following forms:
+
+ * As a separate statement:
+
+ Examples:
+ ```c
+ my_fun(my_param_expression + 1, 10);
+ my_fun2();
+ ```
+
+ * A separate assignment statement to a variable. The function call
+ expression may be negated but is not allowed to be nested in other
+ types of expressions.
+
+ Examples of **correct** ways of calling yieldable functions:
+ ```c
+ int var_name_1 = my_fun();
+ int var_name_2 = !my_fun();
+ var_name_3 = my_fun();
+ var_name_4 = !my_fun();
+ ```
+
+ Examples of **incorrect** ways of calling yieldable functions:
+ ```c
+ int var_name_1 = (my_fun());
+ var_name_2 = 1 + my_fun();
+ t->name = my_fun();
+ *ptr = my_fun();
+ ```
+
+ * As the expression of `while`-statements, `do-while`-statements or
+ 'if`-statements:
+
+ Examples of **correct** ways of calling yieldable functions:
+ ```c
+ if(my_fun()) printf("hej\n");
+ if(0) else if(my_fun()) printf("hej\n");
+ while(!my_fun()) printf("hej\n");
+ do { printf("hej\n"); } while(my_fun());
+ var_name_3 = my_fun();
+ var_name_4 = !my_fun();
+ ```
+
+ Examples of **incorrect** ways of calling yieldable functions:
+ ```
+ if(3+my_fun()) printf("hej\n");
+ if(hej=my_fun()) printf("hej\n");
+ ```
+
+ YCF ignores calls to yieldable functions that are not in any of
+ the forms described above, so it is important to check the
+ generated source code.
+
+Hooks
+-----
+
+It is possible to insert special hooks in yieldable functions. Hooks
+execute when certain events are happening. Hooks may read and write to
+variables (changes to variables are visible after the code block has
+executed). Hooks can be placed anywhere one can place a normal
+statement within the function body. There are two ways to write hooks:
+
+**Hook Style 1:**
+
+```c
+ YCF_SPECIAL_CODE_START(ON_EVENT_NAME);
+ printf("This will be printed when EVENT_NAME is happening\n");
+ YCF_SPECIAL_CODE_END();
+```
+
+**Hook Style 2:**
+
+```c
+ /*special_code_start:ON_EVENT_NAME*/
+ if(0){
+ printf("This will be printed when EVENT_NAME is happening\n");
+ }
+ /*special_code_end*/
+```
+
+The following hook events are currently available:
+
+* `ON_SAVE_YIELD_STATE`
+
+ Triggered when the function yields.
+
+* `ON_RESTORE_YIELD_STATE`
+
+ Triggered before a function resumes after a yield.
+
+* `ON_DESTROY_STATE`
+
+ Triggered if and when the corresponding `_ycf_gen_destroy` function
+ is executing.
+
+* `ON_DESTROY_STATE_OR_RETURN`
+
+ Triggered if and when the corresponding `_ycf_gen_destroy` function
+ for the function is executing or when the function is returning.
+
+* `ON_RETURN`
+
+ Triggered when the function is returning.
+
+License
+-------
+
+Yielding C Fun is released under the [Apache License
+2.0](http://www.apache.org/licenses/LICENSE-2.0).
+
+
+> Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+>
+> 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.
+
+
+
+[1]: http://swtch.com/libtask/ "libtask"
+[2]: http://xmailserver.org/libpcl.html
+[3]: https://web.archive.org/web/20060110123338/http://www.goron.de/~froese/coro/
+[4]: https://github.com/halayli/lthread
+[5]: http://dekorte.com/projects/opensource/libcoroutine/
+[6]: http://code.google.com/p/libconcurrency/libconcurrency
+[7]: http://software.schmorp.de/pkg/libcoro.html
+[8]: https://github.com/Adaptv/ribs2
+[9]: http://libdill.org/
+[10]: https://github.com/hnes/libaco
+[11]: https://byuu.org/library/libco/
+[12]: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+[13]: https://github.com/jsseldenthuis/coroutine
diff --git a/erts/lib_src/yielding_c_fun/TODO b/erts/lib_src/yielding_c_fun/TODO
new file mode 100644
index 0000000000..f3ded2dd22
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/TODO
@@ -0,0 +1,4 @@
+* Refactor and beautify the code so it does not look like spaghetti
+* Handle "automatic" array size initialization
+* Handle struct initialization (e.g., struct t my_struct = {.field = hej});
+* Print warning or error message when calling yieldable function from a position that YCF can't handle
diff --git a/erts/lib_src/yielding_c_fun/bin/yielding_c_fun b/erts/lib_src/yielding_c_fun/bin/yielding_c_fun
new file mode 100755
index 0000000000..87745e7aad
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/bin/yielding_c_fun
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+
+#Code to find directory of this file from https://stackoverflow.com/questions/59895/get-the-source-directory-of-a-bash-script-from-within-the-script-itself
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+ DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+ SOURCE="$(readlink "$SOURCE")"
+ [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+done
+DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+
+
+FOUND="no"
+
+for FILE in "$@"
+do
+ if [ "${FILE: -2}" == ".c" ]
+ then
+ if ! cc -c $FILE -o $DIR/a.out ; then
+ echo "$0: error: Could not compile file with cc"
+ exit 1
+ fi
+ rm $DIR/a.out
+ if [ $1 == "-rr" ]
+ then
+ rr record $DIR/yielding_c_fun.bin "${@:2}" > $DIR/TMP_OUT_WITH_RR
+ # rr does not print when stdout is redirected
+ cat $DIR/TMP_OUT_WITH_RR
+ rm $DIR/TMP_OUT_WITH_RR
+ else
+ $DIR/yielding_c_fun.bin $@
+ fi
+ fi
+ FOUND="yes"
+done
+
+if [ $FOUND == "no" ]
+then
+ echo "$0: error: Expected a file name with .c ending"
+ exit 1
+fi
diff --git a/erts/lib_src/yielding_c_fun/doc/thread_tutorial.md b/erts/lib_src/yielding_c_fun/doc/thread_tutorial.md
new file mode 100644
index 0000000000..c818032bc5
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/doc/thread_tutorial.md
@@ -0,0 +1,222 @@
+Yielding C Fun Thread Example Tutorial
+======================================
+
+This tutorial goes through how Yielding C Fun can be used to simulate
+multi-threading in a single thread. You can find the source code that
+we use in the tutorial below or in
+[../test/examples/thread_example.c](../test/examples/thread_example.c).
+
+```c
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD_NO_REDS()
+
+static int f_2(char* name, int n) {
+ for(int y = 0; y < 2; y++) {
+ printf("%s f_2: y=%d\n", name, y);
+ }
+ return n*2;
+}
+
+static void f_1(char* name, int x) {
+ YCF_YIELD_NO_REDS();
+ while (x > 0) {
+ int f_2_ret = f_2(name, x);
+ printf("%s f_1: x=%d f_2_ret=%d\n", name, x, f_2_ret);
+ x--;
+ }
+ printf("%s f_1: DONE\n", name);
+}
+
+static void* ycf_alloc(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+static void ycf_free(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] ) {
+#ifdef YCF_YIELD_CODE_GENERATED
+ long t1_nr_of_reds = 1;
+ void* t1_state = NULL;
+ long t2_nr_of_reds = 2;
+ void* t2_state = NULL;
+ long t3_nr_of_reds = 1000;
+ void* t3_state = NULL;
+ /* Start t1, t2 and t3*/
+ f_1_ycf_gen_yielding(&t1_nr_of_reds, &t1_state, NULL,
+ ycf_alloc, ycf_free, NULL, 0, NULL,
+ "t1", 2);
+ f_1_ycf_gen_yielding(&t2_nr_of_reds, &t2_state, NULL,
+ ycf_alloc, ycf_free, NULL, 0, NULL,
+ "t2", 4);
+ f_1_ycf_gen_yielding(&t3_nr_of_reds, &t3_state, NULL,
+ ycf_alloc, ycf_free, NULL, 0, NULL,
+ "t3", 2);
+ printf("THREADS STARTED\n");
+ /* Execute t1, t2 and t3*/
+ while (t1_state != NULL ||
+ t2_state != NULL ||
+ t3_state != NULL) {
+ t1_nr_of_reds = 1;
+ t2_nr_of_reds = 2;
+ if (t1_state != NULL) {
+ printf("SCHEDULING THREAD: t1\n");
+ f_1_ycf_gen_continue(&t1_nr_of_reds, &t1_state, NULL);
+ if (t1_state == NULL) {
+ printf("THREAD t1 DONE (number of reductions left = %ld)\n",
+ t1_nr_of_reds);
+ }
+ }
+ if (t2_state != NULL) {
+ printf("SCHEDULING THREAD: t2\n");
+ f_1_ycf_gen_continue(&t2_nr_of_reds, &t2_state, NULL);
+ if (t2_state == NULL) {
+ printf("THREAD t2 DONE (number of reductions left = %ld)\n",
+ t2_nr_of_reds);
+ }
+ }
+ if (t3_state != NULL) {
+ printf("SCHEDULING THREAD: t3\n");
+ f_1_ycf_gen_continue(&t3_nr_of_reds, &t3_state, NULL);
+ if (t3_state == NULL) {
+ printf("THREAD t3 DONE (number of reductions left = %ld)\n",
+ t3_nr_of_reds);
+ }
+ }
+ }
+#endif
+ (void)f_1;
+ printf("DONE\n");
+ return 0;
+}
+```
+
+To run this example, you need to compile YCF itself, if you have not
+done so already:
+
+ cd directory_where_the_ycf_source_code_is_located
+ YCF_ROOT=`pwd`
+ make
+
+Now, you can transform `test/examples/thread_example.c` by executing
+the following command:
+
+ "$YCF_ROOT"/bin/yielding_c_fun.bin \
+ -f f_1 -f f_2 \
+ -output_file_name modified_thread_example.c \
+ "$YCF_ROOT"/test/examples/thread_example.c
+
+A new file should now exist in your current directory called
+`modified_thread_example.c`. This file contains a transformed
+version of `test/examples/thread_example.c`. The parameters `-f
+f_1` and `-f f_2` tells YCF to generate yieldable versions of the
+functions named `f_1` and `f_2`.
+
+Before you inspect the generated file to see what the tool has done,
+it is smart to format the generated source code with `clang-format` or
+some other tool to make the code more readable:
+
+ clang-format -i modified_thread_example.c
+
+You can now open the generated source code in your favorite editor:
+
+ emacs modified_thread_example.c &
+
+The yieldable functions get the suffix `_ycf_gen_yielding`. For
+example, the yielding version of `f_1` is called
+`f_1_ycf_gen_yielding`. As you can see, several parameters have been
+added to the yieldable versions of `f_1`. We explain the first two of
+these parameters here. [The main documentation of YCF](../README.md)
+explains the rest of the parameters. The first parameter is an
+input/output parameter that tells the yieldable function how many
+reductions that can be "consumed" before it yields. The first
+parameter can also be used by the caller to get the number of
+reductions that have been consumed. The second parameter is also an
+input/output parameter that should be a pointer to a `NULL` pointer
+when the yieldable function is first started. The pointer that is
+pointed to by the second parameter is set to a value which is
+different from `NULL` when the function yields.
+
+Let us now compile and run the generated source code so we can see
+what is happening:
+
+
+ cc -g modified_thread_example.c
+
+```
+$ ./a.out
+THREADS STARTED
+SCHEDULING THREAD: t1
+SCHEDULING THREAD: t2
+SCHEDULING THREAD: t3
+t3 f_2: y=0
+t3 f_2: y=1
+t3 f_1: x=2 f_2_ret=4
+t3 f_2: y=0
+t3 f_2: y=1
+t3 f_1: x=1 f_2_ret=2
+t3 f_1: DONE
+THREAD t3 DONE (number of reductions left = 994)
+SCHEDULING THREAD: t1
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+t2 f_2: y=1
+t2 f_1: x=4 f_2_ret=8
+SCHEDULING THREAD: t1
+t1 f_2: y=0
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+SCHEDULING THREAD: t1
+t1 f_2: y=1
+t1 f_1: x=2 f_2_ret=4
+SCHEDULING THREAD: t2
+t2 f_2: y=1
+t2 f_1: x=3 f_2_ret=6
+SCHEDULING THREAD: t1
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+t2 f_2: y=1
+t2 f_1: x=2 f_2_ret=4
+SCHEDULING THREAD: t1
+t1 f_2: y=0
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+SCHEDULING THREAD: t1
+t1 f_2: y=1
+t1 f_1: x=1 f_2_ret=2
+t1 f_1: DONE
+THREAD t1 DONE (number of reductions left = 1)
+SCHEDULING THREAD: t2
+t2 f_2: y=1
+t2 f_1: x=1 f_2_ret=2
+t2 f_1: DONE
+THREAD t2 DONE (number of reductions left = 2)
+DONE
+$
+```
+
+We can see that all three calls to the yieldable version of `f_1`
+yield before printing anything. This is due to the
+`YCF_YIELD_NO_REDS()` statement at the beginning of `f_1`'s
+body. We can also see that the "thread" named `t3` runs to completion
+without yielding when we call `f_1_ycf_gen_continue` with `t3_state`
+in the while loop and that `t3` consumed (1000-994=6) reductions. This
+is expected as we gave `t3` 1000 reductions when we started it with
+the `f_1_ycf_gen_yielding` function. The "threads" `t1` and `t2` get
+much fewer reductions (i.e., 1 and 2) each time they get to execute
+and they are therefore interleaved.
+
+You can now experiment with other transformation options (e.g.,
+`-frec` and `-fnoauto`) and the special statements that you can use
+inside functions that can yield. All these options and statements are
+documented [here](../README.md).
+
+The best way to figure out how YCF works under the hood is probably to
+step through the transformed program in a debugger.
+
+Good Luck! \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/.gitignore b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/.gitignore
new file mode 100644
index 0000000000..e72b2fe033
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/.gitignore
@@ -0,0 +1,11 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+*~
+GPATH
+GRTAGS
+GTAGS
+test.bin
+.tmp_out \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/.misc/clang_blacklist.txt b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/.misc/clang_blacklist.txt
new file mode 100644
index 0000000000..d212057d10
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/.misc/clang_blacklist.txt
@@ -0,0 +1,10 @@
+
+[memory]
+
+fun:scgc_mark_reachable_objects_in_region
+fun:reverse_bits
+
+[address]
+
+fun:scgc_mark_reachable_objects_in_region
+fun:reverse_bits
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/GIT_VERSION b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/GIT_VERSION
new file mode 100644
index 0000000000..8cd6ceac63
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/GIT_VERSION
@@ -0,0 +1,73 @@
+origin https://github.com/kjellwinblad/simple_c_gc.git (fetch)
+origin https://github.com/kjellwinblad/simple_c_gc.git (push)
+commit 76577516b6e9bd8e8f647d869fb19361f42f9f9f
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Wed Sep 25 16:04:40 2019 +0200
+
+ Fix more Microsoft VS C/C++ compiler errors
+
+commit 4b2734f051ca1386bb970af6b0308e5f2d338403
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Tue Sep 24 16:36:48 2019 +0200
+
+ Make compatible with Microsoft VS C/C++ compiler and fix make test
+
+commit 41e6f3558756d9b6da44ca5247049c23bceadad9
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Mon Sep 23 16:25:55 2019 +0200
+
+ Small fix
+
+commit 8fbd03f880a1eb741462c395e689d844f8d58e06
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Mon Sep 23 16:13:56 2019 +0200
+
+ Fix compile warnings when compiling on a 32-bit system
+
+commit fc051d92bbef9ad1a22f855bc24b46d4efadda93
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Tue Sep 10 15:14:20 2019 +0200
+
+ Add clang-tidy Makefile target
+
+commit c6c3c1adc24f500472c22aad7f467d0a925108f0
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Tue Sep 10 15:07:39 2019 +0200
+
+ Add undefined behavior sanitizer and fix undefined behavior
+
+commit c734e684030a24ae694ed1fe7477c0eb5719bc12
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Mon Sep 9 09:06:19 2019 +0200
+
+ Improve Makefile and add info support
+
+commit 286c6ace1a71f2b021b76b602d5bfe4813f0b519
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Thu Sep 5 12:08:19 2019 +0200
+
+ Make clang_format target .PHONY
+
+commit eacdda4f9c71b5d917111bb9285671739d1cb671
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Thu Sep 5 11:33:03 2019 +0200
+
+ Add clang-format make target and reformat files
+
+commit c617afa556535620633117bdd6cc232ecc8c62f2
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Thu Sep 5 11:07:17 2019 +0200
+
+ Small fixes
+
+commit fb043e17d6e63100ca89ec41c34f667d35da7fb8
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Thu Sep 5 10:55:18 2019 +0200
+
+ Fix compiler warning and make c99 compatible
+
+commit d4b8333a49e62d8ffdbf60ab8382de39209891e2
+Author: Kjell Winblad <kjellwinblad@gmail.com>
+Date: Sat Aug 17 05:59:27 2019 +0200
+
+ First version of Simple C GC
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/LICENSE b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/LICENSE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/LICENSE
@@ -0,0 +1,201 @@
+ 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.
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/Makefile b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/Makefile
new file mode 100644
index 0000000000..1b326a9988
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/Makefile
@@ -0,0 +1,121 @@
+IDIR = .
+CC = cc
+
+ifdef MODERN_CC
+ EXTRA_C_FLAGS = -g -O03 -std=c99 -pedantic -Wall
+endif
+
+ifdef CC_32_BIT
+ EXTRA_C_FLAGS = -m32 -g -O03 -std=c99 -pedantic -Wall
+endif
+
+ifdef ADD_SAN
+ CC = clang
+ EXTRA_C_FLAGS = -std=c99 -Wall -pedantic -g -O00 -fsanitize-blacklist=.misc/clang_blacklist.txt -fsanitize=address -fno-omit-frame-pointer
+ USE_GC_STRING = -use_gc
+endif
+
+ifdef MEM_SAN
+ CC = clang
+ EXTRA_C_FLAGS = -std=c99 -Wall -pedantic -g -O00 -fsanitize-blacklist=.misc/clang_blacklist.txt -fsanitize=memory -fno-omit-frame-pointer
+endif
+
+ifdef UB_SAN
+ CC = clang
+ EXTRA_C_FLAGS = -std=c99 -Wall -pedantic -g -O00 -fsanitize-blacklist=.misc/clang_blacklist.txt -fsanitize=undefined -fno-omit-frame-pointer
+endif
+
+CFLAGS = -I$(IDIR) $(EXTRA_C_FLAGS)
+
+ODIR = .
+LDIR =
+
+_DEPS = bitreversal.h simple_c_gc.h chained_hash_set.h sorted_list_set.h
+DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
+
+_OBJ = simple_c_gc.o test.o
+OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
+C_FILES = $(patsubst %.o,%.c,$(_OBJ))
+
+$(ODIR)/%.o: %.c $(DEPS)
+ $(CC) -c -o $@ $< $(CFLAGS)
+
+test.bin: $(OBJ)
+ $(CC) -o $@ $^ $(CFLAGS)
+
+
+.PHONY: clean test run_test_continusly CMakeLists.txt cmake_compile clang_format test_add_san test_ub_san test_mem_san test_sanitizers test_modern_cc test_valgrind
+
+test: test.bin
+ ./test.bin ;\
+ RESULT=$$? &&\
+ (exit $$RESULT) &&\
+ printf "\n\n\033[0;32mALL TESTS PASSED!\033[0m\n\n\n" ||\
+ printf "\n\n\033[0;31mTEST FAILED!\033[0m\n\n\n" &&\
+ exit $$RESULT
+
+test_valgrind:
+ make clean && \
+ make EXTRA_C_FLAGS="-g -O01" && \
+ valgrind --undef-value-errors=no ./test.bin ;\
+ RESULT=$$? &&\
+ (exit $$RESULT) &&\
+ printf "\n\n\033[0;32mALL TESTS PASSED!\033[0m\n\n\n" ||\
+ printf "\n\n\033[0;31mTEST FAILED!\033[0m\n\n\n" &&\
+ exit $$RESULT
+
+test_add_san:
+ make clean && \
+ make ADD_SAN=1 test
+
+test_mem_san:
+ make clean && \
+ make MEM_SAN=1 test
+
+test_ub_san:
+ make clean && \
+ make UB_SAN=1 test
+
+test_sanitizers:
+ make test_add_san && \
+ make test_mem_san && \
+ make test_ub_san
+
+test_modern_cc:
+ make clean && \
+ make MODERN_CC=1 test
+
+test_32_bit:
+ make clean && \
+ make CC_32_BIT=1 test && \
+ make clean
+
+test_all:
+ make test_valgrind && \
+ make test_sanitizers && \
+ make test_modern_cc && \
+ make test_32_bit
+
+run_test_continusly:
+ inotifywait -e close_write,moved_to,create -m ./*.c ./*.h | while read -r directory events filename; do gtags ; make test ; done
+
+CMakeLists.txt: $(C_FILES)
+ echo "cmake_minimum_required (VERSION 2.6)" > CMakeLists.txt
+ echo "project (SIMPLE_C_GC)" >> CMakeLists.txt
+ echo "add_executable(cmake.out" >> CMakeLists.txt
+ echo $(C_FILES) >> CMakeLists.txt
+ echo ")" >> CMakeLists.txt
+
+
+cmake_compile: CMakeLists.txt
+ mkdir cmake_mkdir || true
+ cd cmake_mkdir && cmake ..
+
+clang_tidy:
+ ls *.c | xargs -I{} -n1 clang-tidy -warnings-as-errors=* {} -- $(CFLAGS)
+
+clang_format:
+ clang-format -style="{BasedOnStyle: LLVM}" -i *.c *.h
+
+clean:
+ rm -f $(ODIR)/*.o *~ core $(IDIR)/*~ test.bin CMakeLists.txt
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/README.md b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/README.md
new file mode 100644
index 0000000000..c1f6834505
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/README.md
@@ -0,0 +1,69 @@
+Simple C GC
+===========
+
+This is the readme file for Simple C GC. Simple C GC is a simple
+garbage collection system for the C programming language inspired by
+[Daniel Holden's article about Cello's garbage collection
+system](http://libcello.org/learn/garbage-collection).
+
+Usage
+-----
+
+The interface of Simple C GC consists of only two functions:
+
+```C
+/**
+ * This function starts code that will be garbage collected
+ *
+ * @param main The function that will be started and garbage collected
+ * @param argc Passed to main
+ * @param argv Passed to main
+ * @param my_malloc Simple C GC will use this to allocated memory
+ * @param my_free Simple C GC will use this to free memory
+ */
+int scgc_start_gced_code(int (*main)(int, char *[]),
+ int argc,
+ char *argv[],
+ void* (*my_malloc)( size_t ),
+ void (*my_free)( void* ));
+
+/**
+ * Allocate a new memory block that will be garbage collected
+ *
+ * @param size The size of the new memory block
+ */
+void* scgc_new(size_t size);
+```
+
+An example that illustrates how these functions can be used in
+practice is located in the `test.c` file.
+
+
+Notes
+-----
+
+The garbage collector assumes that all data that should be garbage
+collected is pointed to directly or indirectly from the "C stack" and
+that the "C stack" is implemented as a continuous block of memory.
+
+Compile and Test
+----------------
+
+ make test
+
+License
+-------
+
+ Copyright 2019 Kjell Winblad (kjellwinblad@gmail.com, http://winsh.me)
+
+ 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. \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/chained_hash_set.h b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/chained_hash_set.h
new file mode 100644
index 0000000000..ee508e5ccc
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/chained_hash_set.h
@@ -0,0 +1,307 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright 2019 Kjell Winblad (kjellwinblad@gmail.com, http://winsh.me).
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#ifndef CHAINED_HASH_SET_H
+#define CHAINED_HASH_SET_H
+
+
+#if defined(_MSC_VER)
+#define inline __inline
+#endif
+
+#include "sorted_list_set.h"
+#include <stdint.h>
+
+#define CHAIN_LENGHT_EXPAND_THRESHOLD 2
+#define CHAIN_LENGHT_SHRINK_THRESHOLD 0.5
+/*Must be power of two*/
+#define INITIAL_NUMBER_OF_BUCKETS 4
+
+typedef struct {
+ unsigned int keyPosition;
+ void *(*extract_key)(void *v, int keyPos);
+ unsigned int (*hash_key)(void *key);
+ bool (*are_equal)(void *v1, void *v2);
+ char *(*to_string)(void *v1);
+ void *(*malloc)(size_t size);
+ void (*free)(void *ptr);
+ unsigned int numberOfBuckets;
+ unsigned int expandTreshold;
+ unsigned int shrinkTreshold;
+ unsigned int size;
+ SortedListSetNode **buckets;
+} ChainedHashSet;
+
+/*
+ * The reverse_bits function is inspired by:
+ * https://stackoverflow.com/questions/746171/efficient-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c
+ */
+static const unsigned char BitReverseTable256[] = {
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0,
+ 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4,
+ 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC,
+ 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA,
+ 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6,
+ 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1,
+ 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9,
+ 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD,
+ 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3,
+ 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7,
+ 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF,
+ 0x3F, 0xBF, 0x7F, 0xFF};
+
+static inline uint32_t reverse_bits(uint32_t v) {
+ return (((uint32_t)BitReverseTable256[v & 0xff]) << 24) |
+ (((uint32_t)BitReverseTable256[(v >> 8) & 0xff]) << 16) |
+ (((uint32_t)BitReverseTable256[(v >> 16) & 0xff]) << 8) |
+ (((uint32_t)BitReverseTable256[(v >> 24) & 0xff]));
+}
+
+static inline void ch_set_increase_size(ChainedHashSet *set) {
+ set->size = set->size + 1;
+ if (set->size > set->expandTreshold) {
+ unsigned int oldNumberOfBuckets = set->numberOfBuckets;
+ unsigned int newNumberOfBuckets = oldNumberOfBuckets * 2;
+ unsigned int splitUpMask = reverse_bits(newNumberOfBuckets - 1) ^
+ reverse_bits(oldNumberOfBuckets - 1);
+ SortedListSetNode **newBuckets =
+ set->malloc(sizeof(SortedListSetNode *) * newNumberOfBuckets);
+ SortedListSetNode **oldBuckets = set->buckets;
+ SortedListSetNode *moveTemp;
+ for (unsigned int i = 0; i < oldNumberOfBuckets; i++) {
+ moveTemp = sl_set_split_opt(&oldBuckets[i], splitUpMask);
+ newBuckets[i] = oldBuckets[i];
+ newBuckets[i + oldNumberOfBuckets] = moveTemp;
+ }
+ set->free(oldBuckets);
+ set->buckets = newBuckets;
+ set->numberOfBuckets = newNumberOfBuckets;
+ set->expandTreshold = newNumberOfBuckets * CHAIN_LENGHT_EXPAND_THRESHOLD;
+ set->shrinkTreshold = newNumberOfBuckets * CHAIN_LENGHT_SHRINK_THRESHOLD;
+ }
+}
+
+static inline void ch_set_decrease_size(ChainedHashSet *set) {
+ set->size = set->size - 1;
+ if (set->size < set->shrinkTreshold) {
+ unsigned int oldNumberOfBuckets = set->numberOfBuckets;
+ unsigned int newNumberOfBuckets = oldNumberOfBuckets / 2;
+ SortedListSetNode **newBuckets =
+ set->malloc(sizeof(SortedListSetNode *) * newNumberOfBuckets);
+ SortedListSetNode **oldBuckets = set->buckets;
+ for (unsigned int i = 0; i < newNumberOfBuckets; i++) {
+ newBuckets[i] = oldBuckets[i];
+ sl_set_concat_opt(&newBuckets[i], oldBuckets[i + newNumberOfBuckets]);
+ }
+ set->free(oldBuckets);
+ set->buckets = newBuckets;
+ set->numberOfBuckets = newNumberOfBuckets;
+ set->expandTreshold = newNumberOfBuckets * CHAIN_LENGHT_EXPAND_THRESHOLD;
+ if (set->numberOfBuckets == INITIAL_NUMBER_OF_BUCKETS) {
+ set->shrinkTreshold = 0;
+ } else {
+ set->shrinkTreshold = newNumberOfBuckets * CHAIN_LENGHT_SHRINK_THRESHOLD;
+ }
+ }
+}
+
+static inline void ch_set_initialize(ChainedHashSet *set,
+ unsigned int keyPosition,
+ void *(*extract_key)(void *v, int keyPos),
+ unsigned int (*hash_key)(void *k),
+ bool (*are_equal)(void *v1, void *v2),
+ char *(*to_string)(void *v1),
+ void *(*my_malloc)(size_t size),
+ void (*my_free)(void *ptr)) {
+ set->keyPosition = keyPosition;
+ set->extract_key = extract_key;
+ set->hash_key = hash_key;
+ set->are_equal = are_equal;
+ set->to_string = to_string;
+ set->malloc = my_malloc;
+ set->free = my_free;
+ set->numberOfBuckets = INITIAL_NUMBER_OF_BUCKETS;
+ set->expandTreshold = set->numberOfBuckets * CHAIN_LENGHT_EXPAND_THRESHOLD;
+ set->shrinkTreshold = set->numberOfBuckets * CHAIN_LENGHT_EXPAND_THRESHOLD;
+ set->size = 0;
+ set->buckets =
+ set->malloc(sizeof(SortedListSetNode *) * INITIAL_NUMBER_OF_BUCKETS);
+ for (int i = 0; i < INITIAL_NUMBER_OF_BUCKETS; i++) {
+ set->buckets[i] = NULL;
+ }
+}
+
+static inline ChainedHashSet *ch_set_create(
+ unsigned int keyPosition, void *(*extract_key)(void *v, int keyPos),
+ unsigned int (*hash_key)(void *k), bool (*are_equal)(void *v1, void *v2),
+ char *(*to_string)(void *v1), void *(*my_malloc)(size_t size),
+ void (*my_free)(void *ptr)) {
+ ChainedHashSet *set = my_malloc(sizeof(ChainedHashSet));
+ ch_set_initialize(set, keyPosition, extract_key, hash_key, are_equal,
+ to_string, my_malloc, my_free);
+ return set;
+}
+
+static inline bool ch_set_insert_opt(ChainedHashSet *set, void *value,
+ unsigned int valueSize,
+ unsigned int hashValue, bool overwrite) {
+ unsigned int bucketIndex = hashValue & (set->numberOfBuckets - 1);
+ SortedListSetNode **bucket = &set->buckets[bucketIndex];
+ bool oneAdded = sl_set_insert_opt(
+ bucket, value, valueSize, reverse_bits(hashValue), set->keyPosition,
+ overwrite, set->extract_key, set->are_equal, set->malloc, set->free);
+ if (oneAdded) {
+ ch_set_increase_size(set);
+ }
+ return oneAdded;
+}
+
+static inline void ch_set_insert(void *setParam, void *value,
+ unsigned int valueSize) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ void *key = set->extract_key(value, set->keyPosition);
+ unsigned int hashValue = set->hash_key(key);
+ ch_set_insert_opt(set, value, valueSize, hashValue, true);
+}
+
+static inline bool ch_set_insert_new(void *setParam, void *value,
+ unsigned int valueSize) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ void *key = set->extract_key(value, set->keyPosition);
+ unsigned int hashValue = set->hash_key(key);
+ return ch_set_insert_opt(set, value, valueSize, hashValue, false);
+}
+
+static inline void *ch_set_lookup(void *setParam, void *key) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ unsigned int hashValue = set->hash_key(key);
+ unsigned int bucketIndex = hashValue & (set->numberOfBuckets - 1);
+ SortedListSetNode **bucket = &set->buckets[bucketIndex];
+ return sl_set_lookup_opt(bucket, key, reverse_bits(hashValue),
+ set->keyPosition, set->extract_key, set->are_equal,
+ false, set->malloc);
+}
+
+static inline void ch_set_delete(void *setParam, void *key,
+ unsigned int keySize) {
+ (void)keySize;
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ unsigned int hashValue = set->hash_key(key);
+ unsigned int bucketIndex = hashValue & (set->numberOfBuckets - 1);
+ SortedListSetNode **bucket = &set->buckets[bucketIndex];
+ bool oneRemoved =
+ sl_set_delete_opt(bucket, key, reverse_bits(hashValue), set->keyPosition,
+ set->extract_key, set->are_equal, set->free);
+ if (oneRemoved) {
+ ch_set_decrease_size(set);
+ }
+}
+
+static inline void ch_set_traverse(void *setParam,
+ void (*traverser)(size_t index, void *v,
+ void *context),
+ void *context) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ unsigned int numberOfBuckets = set->numberOfBuckets;
+ SortedListSetNode *itemNode;
+ size_t index = 0;
+ for (unsigned int i = 0; i < numberOfBuckets; i++) {
+ itemNode = set->buckets[i];
+ while (itemNode != NULL) {
+ traverser(index, (void *)itemNode->value, context);
+ index++;
+ itemNode = itemNode->next;
+ }
+ }
+}
+
+static inline void ch_set_free(void *setParam) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ unsigned int numberOfBuckets = set->numberOfBuckets;
+ for (unsigned int i = 0; i < numberOfBuckets; i++) {
+ sl_set_free_opt(&set->buckets[i], set->free);
+ }
+ set->free(set->buckets);
+ set->free(set);
+}
+
+static inline char *ch_set_to_string(void *setParam) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ unsigned int numberOfBuckets = set->numberOfBuckets;
+ char **bucketStrings = malloc(sizeof(char*)*numberOfBuckets);
+ unsigned int *bucketStringSizes = malloc(sizeof(unsigned int)*numberOfBuckets);
+ unsigned int totalBucketsStringSize = 0;
+ SortedListSet *tempListSet = plain_sl_set_create(
+ set->keyPosition, set->extract_key, set->hash_key, set->are_equal,
+ set->to_string, set->malloc, set->free);
+ for (unsigned int i = 0; i < numberOfBuckets; i++) {
+ tempListSet->head = set->buckets[i];
+ bucketStrings[i] = sl_set_to_string(tempListSet);
+ bucketStringSizes[i] = strlen(bucketStrings[i]);
+ totalBucketsStringSize = totalBucketsStringSize + bucketStringSizes[i];
+ }
+ tempListSet->head = NULL;
+ sl_set_free(tempListSet);
+ char *resultString =
+ set->malloc(totalBucketsStringSize + numberOfBuckets * 3 - 3 + 3);
+ resultString[0] = '[';
+ unsigned int currentPosition = 1;
+ for (unsigned int i = 0; i < numberOfBuckets; i++) {
+ sprintf(&resultString[currentPosition], "%s", bucketStrings[i]);
+ set->free(bucketStrings[i]);
+ currentPosition = currentPosition + bucketStringSizes[i];
+ if (i != (numberOfBuckets - 1)) {
+ sprintf(&resultString[currentPosition], ",\n ");
+ currentPosition = currentPosition + 3;
+ }
+ }
+ sprintf(&resultString[currentPosition], "]");
+ free(bucketStrings);
+ free(bucketStringSizes);
+ return resultString;
+}
+
+static inline void ch_set_print(void *setParam) {
+ ChainedHashSet *set = (ChainedHashSet *)setParam;
+ char *str = ch_set_to_string(set);
+ printf("%s\n", str);
+ set->free(str);
+}
+
+static inline bool ch_set_is_concurrent() { return false; }
+
+#endif
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.c b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.c
new file mode 100644
index 0000000000..a6932ab99b
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.c
@@ -0,0 +1,310 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright 2019 Kjell Winblad (kjellwinblad@gmail.com, http://winsh.me).
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include "simple_c_gc.h"
+#include "chained_hash_set.h"
+
+#include <setjmp.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+static bool scgc_print_gc_info = false;
+static ChainedHashSet *scgc_objects;
+static void *scgc_stack_top;
+
+#define SCGC_MIN_ALLOCS_UNTIL_FREE 100
+static int scgc_allocs_until_gc = SCGC_MIN_ALLOCS_UNTIL_FREE;
+static void *(*scgc_user_malloc)(size_t size);
+static void (*scgc_user_free)(void *ptr);
+
+typedef enum { scgc_blank_state, scgc_marked } scgc_object_state;
+
+typedef struct {
+ unsigned long magic_number;
+ size_t size;
+ scgc_object_state state;
+ void *data[1];
+} scgc_object;
+
+typedef struct {
+ void *address;
+ scgc_object *base;
+ unsigned long magic_number;
+} scgc_object_ref;
+
+static void *scgc_malloc(size_t size) {
+ void *(*my_malloc)(size_t size);
+ if (scgc_user_malloc == NULL) {
+ my_malloc = malloc;
+ } else {
+ my_malloc = scgc_user_malloc;
+ }
+ void *res = my_malloc(size);
+ if (res == NULL) {
+ printf("GCGC: Allocator returned NULL.\n");
+ exit(1);
+ }
+ return res;
+}
+
+static void scgc_free(void *ptr) {
+ void (*my_free)(void *ptr);
+ if (scgc_user_free == NULL) {
+ my_free = free;
+ } else {
+ my_free = scgc_user_free;
+ }
+ my_free(ptr);
+}
+
+static void *scgc_extract_key(void *v, int keyPos) {
+ (void)keyPos;
+ return v;
+}
+
+static unsigned int scgc_hash_key(void *keyPtr) {
+ /* From
+ * https://lemire.me/blog/2018/08/15/fast-strongly-universal-64-bit-hashing-everywhere*/
+ int64_t x = (long)*((void **)keyPtr);
+ int64_t a = 2348923;
+ int64_t b = 3292;
+ int64_t c = 9893487421;
+ int32_t low = (int)x;
+ int32_t high = (int)(x >> 32);
+ return (unsigned int)((a * low + b * high + c) >> 32);
+}
+
+static bool scgc_are_equal(void *v1p, void *v2p) {
+ scgc_object_ref *v1 = ((scgc_object_ref *)v1p);
+ scgc_object_ref *v2 = ((scgc_object_ref *)v2p);
+ return v1->address == v2->address;
+}
+
+static char *scgc_to_string(void *vp) {
+ scgc_object_ref *v = ((scgc_object_ref *)vp);
+ char *str = scgc_malloc(200);
+ sprintf(str, "{.address=%p, .base_address=%p, magic_number=%lu}", v->address,
+ (void *)v->base, v->magic_number);
+ return str;
+}
+
+static void scgc_initialize_global_state() {
+ scgc_objects =
+ ch_set_create(0, scgc_extract_key, scgc_hash_key, scgc_are_equal,
+ scgc_to_string, scgc_malloc, scgc_free);
+ srand((int)(long)scgc_objects * 2654435761);
+}
+
+static void scgc_do_gc(bool no_stack);
+
+static void scgc_destroy_global_state() {
+ scgc_do_gc(true);
+ ch_set_free(scgc_objects);
+}
+
+static int scgc_start_gced_code_2(int (*main)(int, char *[]), int argc,
+ char **argv[]) {
+ volatile int noinline = 1;
+ volatile char **my_argv = (volatile char **)*argv;
+ scgc_stack_top = (void *)my_argv;
+ int (*next)(int, char *[]) = noinline ? main : (int (*)(int, char *[]))(NULL);
+ {
+ int to_return;
+ scgc_initialize_global_state();
+ to_return = next(argc, (char **)my_argv);
+ scgc_destroy_global_state();
+ return to_return;
+ }
+}
+
+static void scgc_global_set_put(scgc_object_ref ref) {
+ ch_set_insert(scgc_objects, &ref, sizeof(scgc_object_ref));
+}
+
+static void scgc_global_set_del(void *key) {
+ ch_set_delete(scgc_objects, &key, sizeof(void *));
+}
+
+static scgc_object_ref *scgc_global_set_get(void *key) {
+ scgc_object_ref *ret = ch_set_lookup(scgc_objects, &key);
+ return ret;
+}
+
+static void scgc_mark_reachable_objects_in_region(void *start, void *end);
+
+static void *scgc_min(void *a, void *b) { return a <= b ? a : b; }
+
+static void *scgc_max(void *a, void *b) { return a > b ? a : b; }
+
+static void ycf_find_stack_bottom_and_mark_conservative_helper(void) {
+ volatile void *p = NULL;
+ volatile intptr_t stack_bottom = (intptr_t)&p;
+ scgc_mark_reachable_objects_in_region(
+ scgc_min(scgc_stack_top, (void *)&stack_bottom),
+ scgc_max((void *)&stack_bottom, scgc_stack_top));
+}
+
+static void scgc_get_stack_bottom_and_mark() {
+ jmp_buf env;
+ setjmp(env);
+
+ volatile int noinline = 1;
+
+ void (*bottom)(void) =
+ noinline ? ycf_find_stack_bottom_and_mark_conservative_helper
+ : (void (*)(void))(NULL);
+
+ bottom();
+}
+
+static void scgc_mark_reachable_objects_in_region(void *start, void *end) {
+ void **iter = start;
+ void **iter_end = end;
+ scgc_object *object;
+ while (iter <= iter_end) {
+ scgc_object_ref *ref = scgc_global_set_get(*iter);
+ if (ref != NULL && ref->base->data == *iter &&
+ ref->magic_number == ref->base->magic_number &&
+ ref->base->state == scgc_blank_state) {
+ object = ref->base;
+ object->state = scgc_marked;
+ scgc_mark_reachable_objects_in_region(
+ &object->data[0], &((char *)object->data)[object->size - 1]);
+ }
+ iter = iter + 1;
+ }
+}
+
+static void scgc_mark_reachable_objects(bool no_stack) {
+ void *tmp = NULL;
+ if (no_stack) {
+ scgc_mark_reachable_objects_in_region(&tmp, &tmp);
+ } else {
+ scgc_get_stack_bottom_and_mark();
+ }
+}
+
+static void scgc_collect_unmarked_traverser(size_t index, void *v,
+ void *context) {
+ void **objects_to_remove = context;
+ scgc_object_ref *ref = v;
+ if (ref->base->state == scgc_blank_state) {
+ scgc_free(ref->base);
+ objects_to_remove[index] = ref->address;
+ } else {
+ objects_to_remove[index] = NULL;
+ }
+}
+
+static void scgc_remove_unmarked_objects() {
+ size_t nr_of_candidates = scgc_objects->size;
+ void **objects_to_remove = scgc_malloc(sizeof(void *) * nr_of_candidates);
+ for (size_t i = 0; i < nr_of_candidates; i++) {
+ objects_to_remove[i] = NULL;
+ }
+ ch_set_traverse(scgc_objects, scgc_collect_unmarked_traverser,
+ objects_to_remove);
+ for (size_t i = 0; i < nr_of_candidates; i++) {
+ if (objects_to_remove[i] != NULL) {
+ scgc_global_set_del(objects_to_remove[i]);
+ }
+ }
+ scgc_free(objects_to_remove);
+}
+
+static void scgc_unmark_traverser(size_t index, void *v, void *context) {
+ scgc_object_ref *ref = v;
+ ref->base->state = scgc_blank_state;
+}
+
+static void scgc_unmark_objects() {
+ ch_set_traverse(scgc_objects, scgc_unmark_traverser, NULL);
+}
+
+static void scgc_do_gc(bool no_stack) {
+ unsigned int objects_before = scgc_objects->size;
+ scgc_mark_reachable_objects(no_stack);
+ scgc_remove_unmarked_objects();
+ scgc_unmark_objects();
+ if (scgc_print_gc_info) {
+ unsigned int objects_after = scgc_objects->size;
+ unsigned int objects_removed = objects_before - objects_after;
+ fprintf(stderr, "GC: before=%u, after=%u, removed=%u\n", objects_before,
+ objects_after, objects_removed);
+ }
+}
+
+static void scgc_gc() {
+ scgc_allocs_until_gc--;
+ if (scgc_allocs_until_gc <= 0) {
+ scgc_do_gc(false);
+ unsigned int objects_after = scgc_objects->size;
+ scgc_allocs_until_gc = objects_after * 2;
+ if (scgc_allocs_until_gc < SCGC_MIN_ALLOCS_UNTIL_FREE) {
+ scgc_allocs_until_gc = SCGC_MIN_ALLOCS_UNTIL_FREE;
+ }
+ }
+}
+
+/* Public interface */
+
+int scgc_start_gced_code(int (*main)(int, char *[]), int argc, char *argv[],
+ void *(*my_malloc)(size_t), void (*my_free)(void *)) {
+ volatile int noinline = 1;
+ int (*next)(int (*)(int, char *[]), int, char **[]) =
+ (noinline ? scgc_start_gced_code_2
+ : (int (*)(int (*)(int, char *[]), int, char **[]))(NULL));
+ volatile char **my_argv = (volatile char **)argv;
+ int res;
+ scgc_user_malloc = my_malloc;
+ scgc_user_free = my_free;
+ if (my_argv == NULL) {
+ fprintf(stderr,
+ "scgc_start_gced_code: the argv parameter should not be NULL!");
+ exit(1);
+ }
+ res = next(main, argc, (char ***)&my_argv);
+ return res;
+}
+
+void *scgc_new(size_t size) {
+ scgc_gc();
+ scgc_object *new = scgc_malloc(size + sizeof(scgc_object));
+ scgc_object_ref new_ref;
+ unsigned long magic_number = (unsigned long)rand();
+ new->state = scgc_blank_state;
+ new->magic_number = magic_number;
+ new->size = size;
+ new_ref.address = new->data;
+ new_ref.base = new;
+ new_ref.magic_number = magic_number;
+ scgc_global_set_put(new_ref);
+ return new->data;
+}
+
+void scgc_enable_print_gc_info() { scgc_print_gc_info = true; }
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.h b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.h
new file mode 100644
index 0000000000..0e9aff84b8
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/simple_c_gc.h
@@ -0,0 +1,57 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright 2019 Kjell Winblad (kjellwinblad@gmail.com, http://winsh.me).
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/**
+ * Pulic interface for Simple C GC.
+ *
+ * @author Kjell Winblad
+ *
+ */
+
+#ifndef SIMPLE_C_GC_H
+#define SIMPLE_C_GC_H
+
+#include <stddef.h>
+
+/**
+ * This function starts code that will be garbage collected
+ *
+ * @param main The function that will be started and garbage collected
+ * @param argc Passed to main
+ * @param argv Passed to main
+ * @param my_malloc Simple C GC will use this to allocated memory
+ * @param my_free Simple C GC will use this to free memory
+ */
+int scgc_start_gced_code(int (*main)(int, char *[]), int argc, char *argv[],
+ void *(*my_malloc)(size_t), void (*my_free)(void *));
+
+/**
+ * Allocate a new memory block that will be garbage collected
+ *
+ * @param size The size of the new memory block
+ */
+void *scgc_new(size_t size);
+
+/**
+ * Enables printing of garbage collection information
+ */
+void scgc_enable_print_gc_info(void);
+#endif
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/sorted_list_set.h b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/sorted_list_set.h
new file mode 100644
index 0000000000..1c216d2ed9
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/sorted_list_set.h
@@ -0,0 +1,370 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright 2019 Kjell Winblad (kjellwinblad@gmail.com, http://winsh.me).
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#ifndef SORTED_LIST_SET_H
+#define SORTED_LIST_SET_H
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct SortedListSetNodeImpl {
+ struct SortedListSetNodeImpl *next;
+ unsigned int key_hash_value;
+ unsigned int valueSize;
+ char value[]; /* Flexible size array member */
+} SortedListSetNode;
+
+typedef struct {
+ SortedListSetNode *head;
+ unsigned int keyPosition;
+ void *(*extract_key)(void *v, int keyPos);
+ unsigned int (*hash_key)(void *k);
+ bool (*are_equal)(void *v1, void *v2);
+ char *(*to_string)(void *v1);
+ void *(*malloc)(size_t size);
+ void (*free)(void *ptr);
+} SortedListSet;
+
+static inline SortedListSet *plain_sl_set_create(
+ unsigned int keyPosition, void *(*extract_key)(void *v, int keyPos),
+ unsigned int (*hash_key)(void *k), bool (*are_equal)(void *v1, void *v2),
+ char *(*to_string)(void *v1), void *(*my_malloc)(size_t size),
+ void (*my_free)(void *ptr)) {
+ SortedListSet *set = my_malloc(sizeof(SortedListSet));
+ set->head = NULL;
+ set->keyPosition = keyPosition;
+ set->extract_key = extract_key;
+ set->hash_key = hash_key;
+ set->are_equal = are_equal;
+ set->to_string = to_string;
+ set->malloc = my_malloc;
+ set->free = my_free;
+ return set;
+}
+
+static inline int compare_hash_codes(unsigned int code1, unsigned int code2) {
+ return code1 - code2;
+}
+
+static inline bool sl_set_insert_opt(SortedListSetNode **root, void *valuePtr,
+ unsigned int valueSize,
+ unsigned int keyHashValue, int keyPosition,
+ bool overwrite,
+ void *(*extract_key)(void *v, int keyPos),
+ bool (*are_equal)(void *v1, void *v2),
+ void *(*my_malloc)(size_t size),
+ void (*my_free)(void *ptr)) {
+ void *key = extract_key(valuePtr, keyPosition);
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ bool oneMore = true;
+ int compareResult;
+ while (current != NULL) {
+ compareResult = compare_hash_codes(current->key_hash_value, keyHashValue);
+ if (compareResult < 0) {
+ previous = current;
+ current = previous->next;
+ } else if (compareResult > 0) {
+ break;
+ } else {
+ if (are_equal(extract_key(current->value, keyPosition), key)) {
+ if (overwrite) {
+ SortedListSetNode *oldCurrent = current;
+ current = current->next;
+ previous->next = current;
+ my_free(oldCurrent);
+ oneMore = false;
+ break;
+ } else {
+ return false;
+ }
+ } else {
+ previous = current;
+ current = previous->next;
+ }
+ }
+ }
+ SortedListSetNode *newNode = my_malloc(sizeof(SortedListSetNode) + valueSize);
+ previous->next = newNode;
+ newNode->next = current;
+ newNode->key_hash_value = keyHashValue;
+ memcpy(newNode->value, valuePtr, valueSize);
+ newNode->valueSize = valueSize;
+ return oneMore;
+}
+
+static inline void sl_set_insert(void *setParam, void *valuePtr,
+ unsigned int valueSize) {
+ SortedListSet *set = (SortedListSet *)setParam;
+ sl_set_insert_opt(&set->head, valuePtr, valueSize,
+ set->hash_key(set->extract_key(valuePtr, set->keyPosition)),
+ set->keyPosition, true, set->extract_key, set->are_equal,
+ set->malloc, set->free);
+}
+
+static inline bool sl_set_insert_new(void *setParam, void *valuePtr,
+ unsigned int valueSize) {
+ SortedListSet *set = (SortedListSet *)setParam;
+ return sl_set_insert_opt(
+ &set->head, valuePtr, valueSize,
+ set->hash_key(set->extract_key(valuePtr, set->keyPosition)),
+ set->keyPosition, false, set->extract_key, set->are_equal, set->malloc,
+ set->free);
+}
+
+static inline void *sl_set_lookup_opt(SortedListSetNode **root, void *key,
+ unsigned int keyHashValue,
+ int keyPosition,
+ void *(*extract_key)(void *v, int keyPos),
+ bool (*are_equal)(void *v1, void *v2),
+ bool copyOut,
+ void *(*my_malloc)(size_t size)) {
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ int compareResult;
+ while (current != NULL) {
+ compareResult = compare_hash_codes(current->key_hash_value, keyHashValue);
+ if (compareResult < 0) {
+ previous = current;
+ current = previous->next;
+ } else if (compareResult > 0) {
+ return NULL;
+ } else if (are_equal(extract_key(current->value, keyPosition), key)) {
+ if (copyOut) {
+ void *toReturn = my_malloc(current->valueSize);
+ memcpy(toReturn, current->value, current->valueSize);
+ return toReturn;
+ } else {
+ return current->value;
+ }
+ } else {
+ previous = current;
+ current = previous->next;
+ }
+ }
+ return NULL;
+}
+
+static inline void *sl_set_lookup(void *setParam, void *key) {
+ SortedListSet *set = (SortedListSet *)setParam;
+ return sl_set_lookup_opt(&set->head, key, set->hash_key(key),
+ set->keyPosition, set->extract_key, set->are_equal,
+ false, set->malloc);
+}
+
+static inline bool sl_set_delete_opt(SortedListSetNode **root, void *key,
+ unsigned int keyHashValue, int keyPosition,
+ void *(*extract_key)(void *v, int keyPos),
+ bool (*are_equal)(void *v1, void *v2),
+ void (*my_free)(void *ptr)) {
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ int compareResult;
+ while (current != NULL) {
+ compareResult = compare_hash_codes(current->key_hash_value, keyHashValue);
+ if (compareResult < 0) {
+ previous = current;
+ current = previous->next;
+ } else if (compareResult > 0) {
+ return false;
+ } else if (are_equal(extract_key(current->value, keyPosition), key)) {
+ previous->next = current->next;
+ my_free(current);
+ return true;
+ } else {
+ previous = current;
+ current = previous->next;
+ }
+ }
+ return false;
+}
+
+static inline void sl_set_delete(void *setParam, void *key,
+ unsigned int keySize) {
+ (void)keySize;
+ SortedListSet *set = (SortedListSet *)setParam;
+ sl_set_delete_opt(&set->head, key, set->hash_key(key), set->keyPosition,
+ set->extract_key, set->are_equal, set->free);
+}
+
+static inline void sl_set_free_opt(SortedListSetNode **root,
+ void (*my_free)(void *ptr)) {
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ while (current != NULL) {
+ previous = current;
+ current = current->next;
+ my_free(previous);
+ }
+}
+
+static inline void sl_set_free(void *setParam) {
+ SortedListSet *set = (SortedListSet *)setParam;
+ sl_set_free_opt(&set->head, set->free);
+ set->free(set);
+}
+
+static inline SortedListSetNode *sl_set_split_opt(SortedListSetNode **root,
+ unsigned int splitPattern) {
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ while (current != NULL) {
+ if (current->key_hash_value & splitPattern) {
+ previous->next = NULL;
+ return current;
+ }
+ previous = current;
+ current = previous->next;
+ }
+ return NULL;
+}
+
+static inline void sl_set_concat_opt(SortedListSetNode **root,
+ SortedListSetNode *list) {
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ while (current != NULL) {
+ previous = current;
+ current = previous->next;
+ }
+ previous->next = list;
+}
+
+static inline void sl_set_append_opt(SortedListSetNode **root,
+ SortedListSetNode *list) {
+ if (list == NULL) {
+ return;
+ }
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ while (current != NULL) {
+ previous = current;
+ current = previous->next;
+ }
+ previous->next = list;
+}
+
+static inline void *
+sl_set_fold_opt(SortedListSetNode **root, void *initialValue,
+ void *(*f)(void *soFar, void *currentValue)) {
+ SortedListSetNode *previous = (SortedListSetNode *)root;
+ SortedListSetNode *current = previous->next;
+ void *soFar = initialValue;
+ while (current != NULL) {
+ soFar = f(soFar, current->value);
+ current = current->next;
+ }
+ return soFar;
+}
+
+static inline void *sl_set_fold(SortedListSet *set, void *initialValue,
+ void *(*f)(void *soFar, void *currentValue)) {
+ return sl_set_fold_opt(&set->head, initialValue, f);
+}
+
+static inline void *_______size_helper(void *soFarParam, void *currentValue) {
+ unsigned int *soFar = (unsigned int *)soFarParam;
+ (void)currentValue;
+ unsigned int prev = *soFar;
+ *soFar = prev + 1;
+ return soFar;
+}
+
+static inline unsigned int sl_set_size_opt(SortedListSetNode **root) {
+ unsigned int size = 0;
+ sl_set_fold_opt(root, &size, _______size_helper);
+ return size;
+}
+
+static inline unsigned int sl_set_size(SortedListSet *set) {
+ return sl_set_size_opt(&set->head);
+}
+
+static inline void sl_set_print(void *setParam) {
+ SortedListSet *set = (SortedListSet *)setParam;
+ SortedListSetNode *previous = (SortedListSetNode *)set;
+ SortedListSetNode *current = previous->next;
+ printf("[");
+ while (current != NULL) {
+ char *string = set->to_string(current->value);
+ printf("%s", string);
+ set->free(string);
+ previous = current;
+ current = previous->next;
+ if (current != NULL) {
+ printf(",");
+ }
+ }
+ printf("]\n");
+}
+
+static inline char *sl_set_to_string(void *setParam) {
+ SortedListSet *set = (SortedListSet *)setParam;
+ unsigned int numberOfElements = sl_set_size(set);
+ char **stringArray = malloc(sizeof(char*)*numberOfElements);
+ unsigned int *stringLengths = malloc(sizeof(unsigned int)*numberOfElements);
+ SortedListSetNode *previous = (SortedListSetNode *)set;
+ SortedListSetNode *current = previous->next;
+ unsigned int elementNumber = 0;
+ unsigned int totalCharCount = 2;
+ if (numberOfElements == 0) {
+ char *buffer = (char *)set->malloc(3);
+ sprintf(buffer, "[]");
+ free(stringArray);
+ free(stringLengths);
+ return buffer;
+ }
+ while (current != NULL) {
+ stringArray[elementNumber] = set->to_string(current->value);
+ stringLengths[elementNumber] = strlen(stringArray[elementNumber]);
+ totalCharCount = totalCharCount + stringLengths[elementNumber];
+ current = current->next;
+ elementNumber++;
+ }
+ totalCharCount = totalCharCount + numberOfElements;
+ char *stringBuffer = set->malloc(totalCharCount);
+ stringBuffer[0] = '[';
+ unsigned int currentPosition = 1;
+ for (unsigned int i = 0; i < numberOfElements; i++) {
+ sprintf(&stringBuffer[currentPosition], "%s", stringArray[i]);
+ set->free(stringArray[i]);
+ currentPosition = currentPosition + stringLengths[i];
+ if (i != (numberOfElements - 1)) {
+ sprintf(&stringBuffer[currentPosition], ",");
+ currentPosition = currentPosition + 1;
+ }
+ }
+ sprintf(&stringBuffer[currentPosition], "]");
+ free(stringArray);
+ free(stringLengths);
+ return stringBuffer;
+}
+
+#endif
diff --git a/erts/lib_src/yielding_c_fun/lib/simple_c_gc/test.c b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/test.c
new file mode 100644
index 0000000000..f118db4361
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/simple_c_gc/test.c
@@ -0,0 +1,53 @@
+#include "simple_c_gc.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static size_t nr_of_objects_created = 0;
+static size_t nr_of_objects = 0;
+static size_t peek_nr_of_objects = 0;
+
+static void *my_malloc(size_t size) {
+ nr_of_objects++;
+ nr_of_objects_created++;
+ if (nr_of_objects > peek_nr_of_objects) {
+ peek_nr_of_objects = nr_of_objects;
+ }
+ return calloc(1, size);
+}
+
+static void my_free(void *ptr) {
+ nr_of_objects--;
+ free(ptr);
+}
+
+int my_main(int argc, char *argv[]) {
+ if (argc == 2 && strcmp(argv[1], "-enable_gc_info") == 0) {
+ scgc_enable_print_gc_info();
+ }
+ void **my = scgc_new(100);
+ FILE *fp = fopen(".tmp_out", "w");
+ fprintf(fp, "my %p %p\n", (void *)my, (void *)&my);
+ for (int i = 0; i < 100000; i++) {
+ my[0] = scgc_new(32);
+ my[1] = scgc_new(32);
+ my[2] = scgc_new(32);
+ ((void **)my[2])[0] = scgc_new(32);
+ ((void **)my[2])[1] = scgc_new(32);
+ fprintf(fp, "test1 %p\n", ((void **)my[0])[0]);
+ fprintf(fp, "test2 %p\n", ((void **)my[1])[0]);
+ fprintf(fp, "test3 %p\n", ((void ***)my[2])[0][0]);
+ fprintf(fp, "test4 %p\n", ((void ***)my[2])[1][0]);
+ }
+ fclose(fp);
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ /*Test the gc*/
+ scgc_start_gced_code(my_main, argc, argv, my_malloc, my_free);
+ fprintf(stderr, "Peek nr of live objects: %zu\n", peek_nr_of_objects);
+ fprintf(stderr, "Nr of objects after: %zu\n", nr_of_objects);
+ fprintf(stderr, "Nr of objects created: %zu\n", nr_of_objects_created);
+ return 0;
+}
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/GIT_VERSION b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/GIT_VERSION
new file mode 100644
index 0000000000..0bbde9c80d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/GIT_VERSION
@@ -0,0 +1,468 @@
+origin https://github.com/kokke/tiny-regex-c.git (fetch)
+origin https://github.com/kokke/tiny-regex-c.git (push)
+commit d3058f271f7a06ff298dff0a6a9a1e0753a5fa17
+Merge: 28882c4 c2ed772
+Author: kokke <spam@rowdy.dk>
+Date: Fri Oct 26 23:20:07 2018 +0200
+
+ Merge pull request #22 from monolifed/master
+
+ Update re.c for #20
+
+commit c2ed77267c86e30aa342f48528e5ffce6ab4d103
+Author: monolifed <6624464+monolifed@users.noreply.github.com>
+Date: Thu Oct 25 19:19:24 2018 +0300
+
+ Update re.c
+
+commit 28882c4a39fbc9ddd44e69caa22aac4c4a208934
+Author: kokke <spam@rowdy.dk>
+Date: Tue Oct 23 11:27:23 2018 +0200
+
+ Update README.md
+
+commit 4583018febd2d28277b512f09427e2ba01b4cbd5
+Author: kokke <spam@rowdy.dk>
+Date: Tue Oct 23 11:26:47 2018 +0200
+
+ Update README.md
+
+commit 2211111107da75f5574d5f0140e4396ae701d947
+Author: kokke <spam@rowdy.dk>
+Date: Mon Oct 22 16:04:02 2018 +0200
+
+ Update test1.c
+
+ Adding failing test-case for question-mark '?', brought to my attention by @tobermory in https://github.com/kokke/tiny-regex-c/issues/20
+
+commit 679aebd38a245afb9f9d107d066b68765b94865b
+Author: kokke <spam@rowdy.dk>
+Date: Mon Oct 22 15:41:33 2018 +0200
+
+ Update re.c
+
+ fixing typo, noticed by @tobermory -> https://github.com/kokke/tiny-regex-c/issues/19
+
+commit 2f225fa5e355ad3a99cdd5e953768399fe0b6607
+Author: kokke <spam@rowdy.dk>
+Date: Wed Jun 6 18:15:48 2018 +0200
+
+ Update test1.c
+
+commit b587a65abf0f1347a3b7c7050b73c5dbb94d9cb7
+Merge: 89a479f 96a8f77
+Author: kokke <spam@rowdy.dk>
+Date: Wed Jun 6 18:10:57 2018 +0200
+
+ Merge pull request #17 from monolifed/patch-1
+
+ Update re.c
+
+commit 96a8f770c2922505699c9a4d6ba9b9584be5ee29
+Author: monolifed <6624464+monolifed@users.noreply.github.com>
+Date: Thu May 31 02:06:49 2018 +0300
+
+ Update re.c
+
+ hopefully fixes #12
+
+commit 89a479f985cb25284c4e11870c1531c299255790
+Merge: bf9b2f0 e5f3564
+Author: kokke <spam@rowdy.dk>
+Date: Tue May 15 11:25:53 2018 +0200
+
+ Merge pull request #16 from TermoSINteZ/master
+
+ Fix pattern ".?" issues
+
+commit e5f3564a1de7230cec207cb6aec3866b0b7931e0
+Author: TermoSINteZ <termo.sintez@gmail.com>
+Date: Tue May 15 10:41:17 2018 +0300
+
+ Remove tabs
+
+commit acb0a441470808c99a08ecc8d8716d258866835c
+Author: TermoSINteZ <termo.sintez@gmail.com>
+Date: Tue May 15 00:10:55 2018 +0300
+
+ Fix pattern ".?" issues
+
+commit bf9b2f0c5e91dd12e1fea8cbc7ae7a6193e7b4ed
+Merge: cb80dee 84af23d
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 17 14:09:03 2018 +0200
+
+ Merge pull request #14 from roflcopter4/master
+
+ Check for correct python2 binary in Makefile
+
+commit 84af23dde1c6785ca680d5aced93e20e484efa8d
+Author: roflcopter4 <brendan.leason.4@gmail.com>
+Date: Mon Apr 16 14:45:34 2018 -0600
+
+ Fix dumb typos
+
+commit 0cb0b1348392b795971be9472d8dd2854403a2cb
+Author: roflcopter4 <brendan.leason.4@gmail.com>
+Date: Mon Apr 16 14:42:13 2018 -0600
+
+ Add back '@' signs I accidentally removed
+
+commit 81d12dfd3de805d0969e66650731e4df9158169c
+Author: roflcopter4 <brendan.leason.4@gmail.com>
+Date: Mon Apr 16 14:26:28 2018 -0600
+
+ Check for correct python2 binry in Makefile
+
+commit cb80dee0644f41df67b1740fefd8573d18d84a53
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 15:39:17 2018 +0100
+
+ Update README.md
+
+commit 005de160fa2d8796eb2bce75b52eeaac3ac13d8d
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 15:32:37 2018 +0100
+
+ Update Makefile
+
+commit 9ec0029e83e7cba718f6b6f8b107a0133d22b4a7
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 15:31:40 2018 +0100
+
+ Create regex_test_neg.py
+
+commit 960dd3ebec78d2ac61969840d4e23c97d443bdc9
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 15:31:11 2018 +0100
+
+ Create test_rand_neg.c
+
+commit 3d472f3d78d9702ffcdf4439ac842e3250da7c49
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 14:02:23 2018 +0100
+
+ Update README.md
+
+commit cdf61829adc1c94a9f2d019b2683c34c7732ca60
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 13:06:49 2018 +0100
+
+ Update Makefile
+
+commit 98812bdcafa58c7f35fc40fae9ba64d6d2a9eac1
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 12:52:34 2018 +0100
+
+ Update README.md
+
+commit 9c192d4199e4e1e6a764f1b1699deb5b159b161e
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 12:47:27 2018 +0100
+
+ Update re.c
+
+commit fb677f315fd159e13c2c2fc5b40f199148c0fb0f
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 12:45:20 2018 +0100
+
+ Update test1.c
+
+commit dc1b3ee8fc4354e5dfa1846ee6b778452609d50e
+Author: kokke <spam@rowdy.dk>
+Date: Fri Mar 23 12:08:34 2018 +0100
+
+ Update README.md
+
+commit eac0cef080a32c4b606bd10994ddcf8a72249d78
+Author: kokke <spam@rowdy.dk>
+Date: Mon Dec 11 23:26:53 2017 +0100
+
+ Update README.md
+
+commit dc9f34d74b6ac80cd0bed17fca76ef35fca3b101
+Author: kokke <spam@rowdy.dk>
+Date: Mon Dec 11 23:23:40 2017 +0100
+
+ Update re.c
+
+commit d76301fa18f3575cca94816cff291a01fda58ad7
+Author: kokke <spam@rowdy.dk>
+Date: Mon Dec 11 23:23:22 2017 +0100
+
+ Update test1.c
+
+commit b72898ef7a67a0650c7d00b7a09f36abc1fa57a1
+Author: kokke <spam@rowdy.dk>
+Date: Mon Dec 11 21:35:55 2017 +0100
+
+ Update re.c
+
+commit 3cd275c9c55ec51a01ad01c317232247aeec9bab
+Merge: baf3a15 881f634
+Author: kokke <spam@rowdy.dk>
+Date: Mon Dec 11 21:32:26 2017 +0100
+
+ Merge pull request #9 from mrigger/out-of-bounds-fixes
+
+ Out of bounds fixes.
+
+commit 881f634e9a905933d1889a4e0b9b09920337478a
+Author: Manuel Rigger <manuel.rigger@jku.at>
+Date: Sun Dec 10 11:42:17 2017 +0100
+
+ Fix out-of-bunds access found by AFL (input: [00000000000000000000000000000000000000][).
+
+commit e6c91ab986f1ed7d7e39d58e6fdfae44d3110c99
+Author: Manuel Rigger <manuel.rigger@jku.at>
+Date: Sun Dec 10 10:30:06 2017 +0100
+
+ Fix out-of-bounds accesses found by AFL (input: [00000000000000000000000000000000000000).
+
+commit 619a9c654df6a471d7e043081b3fb4bf0e1cd642
+Author: Manuel Rigger <manuel.rigger@jku.at>
+Date: Sat Dec 9 22:56:12 2017 +0100
+
+ Fix out-of-bounds access found by AFL.
+
+commit 43051e257141740e99c32f1cffea78d2a72fe10e
+Author: Manuel Rigger <manuel.rigger@jku.at>
+Date: Fri Dec 8 21:25:01 2017 +0100
+
+ Fix out-of-bounds access found by AFL.
+
+commit baf3a15d7b99b856e82d3dd69555d3bac6750049
+Author: kokke <spam@rowdy.dk>
+Date: Thu Oct 12 00:54:16 2017 +0200
+
+ Update re.h
+
+ To make the C++ crowd and their compilers happy ;)
+
+commit 107352174172b05f25d153c651b327890ab3b574
+Author: kokke <spam@rowdy.dk>
+Date: Sat Jul 8 03:32:29 2017 +0200
+
+ Update re.c
+
+commit ef6b2416b17388da413d3b9cce95ef6897255970
+Author: kokke <spam@rowdy.dk>
+Date: Sat Jul 8 03:26:59 2017 +0200
+
+ Update test1.c
+
+commit b8446ecba1c59b7a9f29e7d8174661deb38a74a5
+Author: kokke <spam@rowdy.dk>
+Date: Wed May 3 22:55:11 2017 +0200
+
+ Update README.md
+
+commit 1600de0a66b11610183c02c4f778866dce6927af
+Author: kokke <spam@rowdy.dk>
+Date: Mon May 1 21:43:47 2017 +0200
+
+ Update regex_test.py
+
+commit e5dafc83fe1672de45ab1bc40e7f34876e2d1d15
+Author: kokke <spam@rowdy.dk>
+Date: Mon May 1 21:34:22 2017 +0200
+
+ Update test_rand.c
+
+commit a39262a534a628d7c07bbb753a66d031a4b4a43a
+Author: kokke <spam@rowdy.dk>
+Date: Mon May 1 21:27:17 2017 +0200
+
+ Update test_print.c
+
+commit 96b9af356129a263ef60355426de0c339308cd26
+Author: kokke <spam@rowdy.dk>
+Date: Mon May 1 21:25:11 2017 +0200
+
+ Update re.c
+
+commit 529889acae614c91697af87feba5abe5334a4274
+Author: kokke <spam@rowdy.dk>
+Date: Mon May 1 21:18:40 2017 +0200
+
+ Update README.md
+
+commit 1afc07dc2936f17dc0df5178ef61caeb19d2c5b1
+Author: kokke <spam@rowdy.dk>
+Date: Mon May 1 21:17:57 2017 +0200
+
+ Update README.md
+
+commit 407f4fe08fb219d68026817d47d1a453a0b6c1ba
+Author: kokke <spam@rowdy.dk>
+Date: Fri Apr 28 17:27:12 2017 +0200
+
+ Update README.md
+
+commit 2d2ebe66d55349ba6add2a4335b24b0a13fb26d2
+Author: kokke <spam@rowdy.dk>
+Date: Mon Apr 24 23:48:18 2017 +0200
+
+ Update README.md
+
+commit 5c76b8cc4e77af9c4a3cb1bbd1cfda3e73e1be56
+Author: kokke <spam@rowdy.dk>
+Date: Mon Apr 24 23:33:34 2017 +0200
+
+ Update README.md
+
+commit e4c7cb9d63d1b284f92053f535402738ee2c3a6a
+Author: kokke <spam@rowdy.dk>
+Date: Mon Apr 24 09:28:24 2017 +0200
+
+ Update README.md
+
+commit 1e694fe184be1261e9f684ea3556103e45649c3b
+Author: kokke <spam@rowdy.dk>
+Date: Thu Apr 20 17:58:33 2017 +0200
+
+ Update README.md
+
+commit 52810460dd877f337e23d58e627b5ae3fbbee430
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 02:38:00 2017 +0200
+
+ Update Makefile
+
+commit d44fb891007d56e0344f7372521f3ff583630d61
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 01:19:38 2017 +0200
+
+ Update README.md
+
+commit af6e7b642b75255bc2a608383a1b0969816bbd83
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 01:16:23 2017 +0200
+
+ Update README.md
+
+commit 858d217db95390b6e7bd1fd1ba7be950142852c9
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 00:32:20 2017 +0200
+
+ Update README.md
+
+commit 28fffd4d32b56cd9b318091cacc8a5c71fbfffed
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 00:31:44 2017 +0200
+
+ Update README.md
+
+commit bd874728041ad0444744a9e739dd5d078f249150
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 00:28:26 2017 +0200
+
+ Update README.md
+
+commit 02110e89252e76c1a2b2a44430f0f402e523f50a
+Author: kokke <spam@rowdy.dk>
+Date: Wed Apr 19 00:26:41 2017 +0200
+
+ Update test1.c
+
+commit 939bc7572148c77d398b22892857b769ec63ac54
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 23:31:14 2017 +0200
+
+ Update README.md
+
+commit 5fef3901aabb6100b28460dccf3154d3e1cc18e7
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 23:09:12 2017 +0200
+
+ Update README.md
+
+commit cae4b96ced1679ea703890eff00deefb0b80cc16
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 23:08:34 2017 +0200
+
+ Update README.md
+
+commit 72398075ee66c49e3e804be94146956dc8bafff6
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:58:10 2017 +0200
+
+ Update Makefile
+
+commit 2994559b99506b35e71c8e18aa99dd706f3b7e38
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:53:05 2017 +0200
+
+ Update re.c
+
+commit 124052b32f302c5a570e79089f951a7d1d56cb38
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:52:01 2017 +0200
+
+ Update Makefile
+
+commit ba8caa931b36b6c274c82214b636770857f7872d
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:50:11 2017 +0200
+
+ Create regex_test.py
+
+commit 9630b56d1faffea799575bb9a81f9c0278906a16
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:49:39 2017 +0200
+
+ Create exrex.py
+
+commit 7da49b443622deaaa472d233a80c58a378fb8646
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:47:37 2017 +0200
+
+ Create test_rand.c
+
+commit 29384927296062ecf0fec81a1c7e35d315b5d84a
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:47:09 2017 +0200
+
+ Create test_print.c
+
+commit 475c199a1b1af4fdd8422b8639117ec97f53b350
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:46:34 2017 +0200
+
+ Create test2.c
+
+commit 2e6e69622061daa740fa03c726f4cc66c5fbc38c
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:45:08 2017 +0200
+
+ Create test1.c
+
+commit e9e4ce1b91609d839a2996bb918397b502f908b7
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:44:33 2017 +0200
+
+ Create Makefile
+
+commit 5a8f0e60718fbfdca7c1fc079a77051af68bdc87
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:41:01 2017 +0200
+
+ Create re.c
+
+commit 52b0aeb459cf1682b636fabe01a97de17579b036
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:38:55 2017 +0200
+
+ Create re.h
+
+commit d061985f504096a59e320a4760784a4090eaf1e4
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:38:01 2017 +0200
+
+ Update README.md
+
+commit 32cbf08728415efb96a3f562f31b780c024502ff
+Author: kokke <spam@rowdy.dk>
+Date: Tue Apr 18 22:37:02 2017 +0200
+
+ Initial commit
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/LICENSE b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/LICENSE
new file mode 100644
index 0000000000..cf1ab25da0
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <http://unlicense.org>
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/Makefile b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/Makefile
new file mode 100644
index 0000000000..deb9fea33a
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/Makefile
@@ -0,0 +1,106 @@
+# Compiler to use - can be replaced by clang for instance
+CC := gcc
+
+# Number of random text expressions to generate, for random testing
+NRAND_TESTS := 1000
+
+PYTHON != if (python --version 2>&1 | grep -q 'Python 2\..*'); then \
+ echo 'python'; \
+ elif command -v python2 >/dev/null 2>&1; then \
+ echo 'python2'; \
+ else \
+ echo 'Error: no compatible python version found.' >&2; \
+ exit 1; \
+ fi
+
+# Flags to pass to compiler
+CFLAGS := -O3 -Wall -Wextra -std=c99 -I.
+
+all:
+ @$(CC) $(CFLAGS) re.c tests/test1.c -o tests/test1
+ @$(CC) $(CFLAGS) re.c tests/test2.c -o tests/test2
+ @$(CC) $(CFLAGS) re.c tests/test_rand.c -o tests/test_rand
+ @$(CC) $(CFLAGS) re.c tests/test_rand_neg.c -o tests/test_rand_neg
+
+clean:
+ @rm -f tests/test1 tests/test2 tests/test_rand
+ @#@$(foreach test_bin,$(TEST_BINS), rm -f $(test_bin) ; )
+ @rm -f a.out
+ @rm -f *.o
+
+
+test: all
+ @$(test $(PYTHON))
+ @echo
+ @echo Testing hand-picked regex\'s:
+ @./tests/test1
+ @echo Testing patterns against $(NRAND_TESTS) random strings matching the Python implementation and comparing:
+ @echo
+ @$(PYTHON) ./scripts/regex_test.py \\d+\\w?\\D\\d $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\s+[a-zA-Z0-9?]* $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\w*\\d?\\w\\? $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^\\d]+\\\\?\\s $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^\\w][^-1-4] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^\\w] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^1-4] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^-1-4] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^\\d]+\\s?[\\w]* $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py a+b*[ac]*.+.*.[\\.]. $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py a?b[ac*]*.?[\\]+[?]? $(NRAND_TESTS)
+ @#python ./scripts/regex_test.py [1-5-]+[-1-2]-[-] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [-1-3]-[-]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [1-5]+[-1-2]-[\\-] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [-1-2]* $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\s?[a-fKL098]+-? $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [\\-]* $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [\\\\]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [0-9a-fA-F]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [1379][2468][abcdef] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [012345-9]?[0123-789] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [012345-9] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [0-56789] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [abc-zABC-Z] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [a\d]?1234 $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py .*123faerdig $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py .?\\w+jsj$ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [?to][+to][?ta][*ta] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\d+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [a-z]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\s+[a-zA-Z0-9?]* $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\w $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py \\d $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [\\d] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test.py [^\\d] $(NRAND_TESTS)
+ @#python ./scripts/regex_test.py [^-1-4] $(NRAND_TESTS)
+ @echo
+ @echo
+ @echo
+ @echo Testing rejection of patterns against $(NRAND_TESTS) random strings also rejected by the Python implementation:
+ @echo
+ @$(PYTHON) ./scripts/regex_test_neg.py \\d+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [a-z]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py \\s+[a-zA-Z0-9?]* $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py ^\\w $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py ^\\d $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [\\d] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py ^[^\\d] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [^\\w]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py ^[\\w]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py ^[^0-9] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [a-z].[A-Z] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [-1-3]-[-]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [1-5]+[-1-2]-[\\-] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [-0-9]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [\\-]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [\\\\]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [0-9a-fA-F]+ $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [1379][2468][abcdef] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [012345-9] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py [0-56789] $(NRAND_TESTS)
+ @$(PYTHON) ./scripts/regex_test_neg.py .*123faerdig $(NRAND_TESTS)
+ @echo
+ @echo
+ @./tests/test2
+ @echo
+ @echo
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md
new file mode 100644
index 0000000000..ab89576f08
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md
@@ -0,0 +1,138 @@
+# tiny-regex-c
+# A small regex implementation in C
+### Description
+Small and portable [Regular Expression](https://en.wikipedia.org/wiki/Regular_expression) (regex) library written in C.
+
+Design is inspired by Rob Pike's regex-code for the book *"Beautiful Code"* [available online here](http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html).
+
+Supports a subset of the syntax and semantics of the Python standard library implementation (the `re`-module).
+
+### Current status
+All supported regex-operators seem to work properly according to the test-set, with the following exception:
+
+There is a problem with ranges (e.g. `[0-9]` for a digit 0-9) combined with inverted character-cases, e.g. `[^ab]` for anything but 'a' or 'b' - like `[^-0-9]` for anything not '-' or a digit 0-9. I think the code mathces too broadly in that case.
+
+I think you should test the patterns you are going to use. You can easily modify the test-harness to generate tests for your intended patterns to check for compliance.
+
+**I will gladly accept patches correcting bugs.**
+
+### Design goals
+The main design goal of this library is to be small, correct, self contained and use few resources while retaining acceptable performance and feature completeness. Clarity of the code is also highly valued.
+
+### Notable features and omissions
+- Small code and binary size: <500 SLOC, ~3kb binary for x86. Statically #define'd memory usage / allocation.
+- No use of dynamic memory allocation (i.e. no calls to `malloc` / `free`).
+- To avoid call-stack exhaustion, iterative searching is preferred over recursive by default (can be changed with a pre-processor flag).
+- No support for capturing groups or named capture: `(^P<name>group)` etc.
+- Thorough testing : [exrex](https://github.com/asciimoo/exrex) is used to randomly generate test-cases from regex patterns, which are fed into the regex code for verification. Try `make test` to generate a few thousand tests cases yourself.
+- Compiled for x86 using GCC 4.7.4 and optimizing for size, the binary takes up ~2-3kb code space and allocates ~0.5kb RAM :
+ ```
+ > gcc -Os -c re.c
+ > size re.o
+ text data bss dec hex filename
+ 2319 0 544 2863 b2f re.o
+
+ ```
+ For ARM/Thumb using GCC 4.8.1 it's around 1.5kb code and less RAM :
+ ```
+ > arm-none-eabi-gcc -Os -mthumb -c re.c
+ > size re.o
+ text data bss dec hex filename
+ 1418 0 280 1698 6a2 re.o
+
+ ```
+ For 8-bit AVR using AVR-GCC 4.8.1 it's around 2kb code and less RAM :
+ ```
+ > avr-gcc -Os -c re.c
+ > size re.o
+ text data bss dec hex filename
+ 2128 0 130 2258 8d2 re.o
+ ```
+
+
+
+### API
+This is the public / exported API:
+```C
+/* Typedef'd pointer to hide implementation details. */
+typedef struct regex_t* re_t;
+
+/* Compiles regex string pattern to a regex_t-array. */
+re_t re_compile(const char* pattern);
+
+/* Finds matches of the compiled pattern inside text. */
+int re_matchp(re_t pattern, const char* text);
+
+/* Finds matches of pattern inside text (compiles first automatically). */
+int re_match(const char* pattern, const char* text);
+```
+
+### Supported regex-operators
+The following features / regex-operators are supported by this library.
+
+NOTE: inverted character classes are buggy - see the test harness for concrete examples.
+
+
+ - `.` Dot, matches any character
+ - `^` Start anchor, matches beginning of string
+ - `$` End anchor, matches end of string
+ - `*` Asterisk, match zero or more (greedy)
+ - `+` Plus, match one or more (greedy)
+ - `?` Question, match zero or one (non-greedy)
+ - `[abc]` Character class, match if one of {'a', 'b', 'c'}
+ - `[^abc]` Inverted class, match if NOT one of {'a', 'b', 'c'}
+ **`NOTE: This feature is currently broken for some usage of character ranges!`**
+ - `[a-zA-Z]` Character ranges, the character set of the ranges { a-z | A-Z }
+ - `\s` Whitespace, \t \f \r \n \v and spaces
+ - `\S` Non-whitespace
+ - `\w` Alphanumeric, [a-zA-Z0-9_]
+ - `\W` Non-alphanumeric
+ - `\d` Digits, [0-9]
+ - `\D` Non-digits
+
+### Usage
+Compile a regex from ASCII-string (char-array) to a custom pattern structure using `re_compile()`.
+
+Search a text-string for a regex and get an index into the string, using `re_match()` or `re_matchp()`.
+
+The returned index points to the first place in the string, where the regex pattern matches.
+
+If the regular expression doesn't match, the matching function returns an index of -1 to indicate failure.
+
+### Examples
+Example of usage:
+```C
+/* Standard null-terminated C-string to search: */
+const char* string_to_search = "ahem.. 'hello world !' ..";
+
+/* Compile a simple regular expression using character classes, meta-char and greedy + non-greedy quantifiers: */
+re_t pattern = re_compile("[Hh]ello [Ww]orld\\s*[!]?");
+
+/* Check if the regex matches the text: */
+int match_idx = re_matchp(pattern, string_to_search);
+if (match_idx != -1)
+{
+ printf("match at idx %d.\n", match_idx);
+}
+```
+
+For more usage examples I encourage you to look at the code in the `tests`-folder.
+
+### TODO
+- Fix the implementation of inverted character classes.
+- Fix implementation of branches (`|`), and see if that can lead us closer to groups as well, e.g. `(a|b)+`.
+- Add `example.c` that demonstrates usage.
+- Add `tests/test_perf.c` for performance and time measurements.
+- Testing: Improve pattern rejection testing.
+
+### FAQ
+- *Q: What differentiates this library from other C regex implementations?*
+
+ A: Well, the small size for one. <500 lines of C-code compiling to 2-3kb ROM, using very little RAM.
+
+### License
+All material in this repository is in the public domain.
+
+
+
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.c b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.c
new file mode 100644
index 0000000000..76d4066247
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.c
@@ -0,0 +1,470 @@
+/*
+ *
+ * Mini regex-module inspired by Rob Pike's regex code described in:
+ *
+ * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html
+ *
+ *
+ *
+ * Supports:
+ * ---------
+ * '.' Dot, matches any character
+ * '^' Start anchor, matches beginning of string
+ * '$' End anchor, matches end of string
+ * '*' Asterisk, match zero or more (greedy)
+ * '+' Plus, match one or more (greedy)
+ * '?' Question, match zero or one (non-greedy)
+ * '[abc]' Character class, match if one of {'a', 'b', 'c'}
+ * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken!
+ * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z }
+ * '\s' Whitespace, \t \f \r \n \v and spaces
+ * '\S' Non-whitespace
+ * '\w' Alphanumeric, [a-zA-Z0-9_]
+ * '\W' Non-alphanumeric
+ * '\d' Digits, [0-9]
+ * '\D' Non-digits
+ *
+ *
+ */
+
+
+
+#include "re.h"
+#include <stdio.h>
+
+/* Definitions: */
+
+#define MAX_REGEXP_OBJECTS 30 /* Max number of regex symbols in expression. */
+#define MAX_CHAR_CLASS_LEN 40 /* Max length of character-class buffer in. */
+
+
+enum { UNUSED, DOT, BEGIN, END, QUESTIONMARK, STAR, PLUS, CHAR, CHAR_CLASS, INV_CHAR_CLASS, DIGIT, NOT_DIGIT, ALPHA, NOT_ALPHA, WHITESPACE, NOT_WHITESPACE, /* BRANCH */ };
+
+typedef struct regex_t
+{
+ unsigned char type; /* CHAR, STAR, etc. */
+ union
+ {
+ unsigned char ch; /* the character itself */
+ unsigned char* ccl; /* OR a pointer to characters in class */
+ } u;
+} regex_t;
+
+
+
+/* Private function declarations: */
+static int matchpattern(regex_t* pattern, const char* text);
+static int matchcharclass(char c, const char* str);
+static int matchstar(regex_t p, regex_t* pattern, const char* text);
+static int matchplus(regex_t p, regex_t* pattern, const char* text);
+static int matchone(regex_t p, char c);
+static int matchdigit(char c);
+static int matchalpha(char c);
+static int matchwhitespace(char c);
+static int matchmetachar(char c, const char* str);
+static int matchrange(char c, const char* str);
+static int ismetachar(char c);
+
+
+
+/* Public functions: */
+int re_match(const char* pattern, const char* text)
+{
+ return re_matchp(re_compile(pattern), text);
+}
+
+int re_matchp(re_t pattern, const char* text)
+{
+ if (pattern != 0)
+ {
+ if (pattern[0].type == BEGIN)
+ {
+ return ((matchpattern(&pattern[1], text)) ? 0 : -1);
+ }
+ else
+ {
+ int idx = -1;
+
+ do
+ {
+ idx += 1;
+
+ if (matchpattern(pattern, text))
+ {
+ if (text[0] == '\0')
+ return -1;
+
+ return idx;
+ }
+ }
+ while (*text++ != '\0');
+ }
+ }
+ return -1;
+}
+
+re_t re_compile(const char* pattern)
+{
+ /* The sizes of the two static arrays below substantiates the static RAM usage of this module.
+ MAX_REGEXP_OBJECTS is the max number of symbols in the expression.
+ MAX_CHAR_CLASS_LEN determines the size of buffer for chars in all char-classes in the expression. */
+ static regex_t re_compiled[MAX_REGEXP_OBJECTS];
+ static unsigned char ccl_buf[MAX_CHAR_CLASS_LEN];
+ int ccl_bufidx = 1;
+
+ char c; /* current char in pattern */
+ int i = 0; /* index into pattern */
+ int j = 0; /* index into re_compiled */
+
+ while (pattern[i] != '\0' && (j+1 < MAX_REGEXP_OBJECTS))
+ {
+ c = pattern[i];
+
+ switch (c)
+ {
+ /* Meta-characters: */
+ case '^': { re_compiled[j].type = BEGIN; } break;
+ case '$': { re_compiled[j].type = END; } break;
+ case '.': { re_compiled[j].type = DOT; } break;
+ case '*': { re_compiled[j].type = STAR; } break;
+ case '+': { re_compiled[j].type = PLUS; } break;
+ case '?': { re_compiled[j].type = QUESTIONMARK; } break;
+/* case '|': { re_compiled[j].type = BRANCH; } break; <-- not working properly */
+
+ /* Escaped character-classes (\s \w ...): */
+ case '\\':
+ {
+ if (pattern[i+1] != '\0')
+ {
+ /* Skip the escape-char '\\' */
+ i += 1;
+ /* ... and check the next */
+ switch (pattern[i])
+ {
+ /* Meta-character: */
+ case 'd': { re_compiled[j].type = DIGIT; } break;
+ case 'D': { re_compiled[j].type = NOT_DIGIT; } break;
+ case 'w': { re_compiled[j].type = ALPHA; } break;
+ case 'W': { re_compiled[j].type = NOT_ALPHA; } break;
+ case 's': { re_compiled[j].type = WHITESPACE; } break;
+ case 'S': { re_compiled[j].type = NOT_WHITESPACE; } break;
+
+ /* Escaped character, e.g. '.' or '$' */
+ default:
+ {
+ re_compiled[j].type = CHAR;
+ re_compiled[j].u.ch = pattern[i];
+ } break;
+ }
+ }
+ /* '\\' as last char in pattern -> invalid regular expression. */
+/*
+ else
+ {
+ re_compiled[j].type = CHAR;
+ re_compiled[j].ch = pattern[i];
+ }
+*/
+ } break;
+
+ /* Character class: */
+ case '[':
+ {
+ /* Remember where the char-buffer starts. */
+ int buf_begin = ccl_bufidx;
+
+ /* Look-ahead to determine if negated */
+ if (pattern[i+1] == '^')
+ {
+ re_compiled[j].type = INV_CHAR_CLASS;
+ i += 1; /* Increment i to avoid including '^' in the char-buffer */
+ }
+ else
+ {
+ re_compiled[j].type = CHAR_CLASS;
+ }
+
+ /* Copy characters inside [..] to buffer */
+ while ( (pattern[++i] != ']')
+ && (pattern[i] != '\0')) /* Missing ] */
+ {
+ if (pattern[i] == '\\')
+ {
+ if (ccl_bufidx >= MAX_CHAR_CLASS_LEN - 1)
+ {
+ //fputs("exceeded internal buffer!\n", stderr);
+ return 0;
+ }
+ ccl_buf[ccl_bufidx++] = pattern[i++];
+ }
+ else if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
+ {
+ //fputs("exceeded internal buffer!\n", stderr);
+ return 0;
+ }
+ ccl_buf[ccl_bufidx++] = pattern[i];
+ }
+ if (ccl_bufidx >= MAX_CHAR_CLASS_LEN)
+ {
+ /* Catches cases such as [00000000000000000000000000000000000000][ */
+ //fputs("exceeded internal buffer!\n", stderr);
+ return 0;
+ }
+ /* Null-terminate string end */
+ ccl_buf[ccl_bufidx++] = 0;
+ re_compiled[j].u.ccl = &ccl_buf[buf_begin];
+ } break;
+
+ /* Other characters: */
+ default:
+ {
+ re_compiled[j].type = CHAR;
+ re_compiled[j].u.ch = c;
+ } break;
+ }
+ i += 1;
+ j += 1;
+ }
+ /* 'UNUSED' is a sentinel used to indicate end-of-pattern */
+ re_compiled[j].type = UNUSED;
+
+ return (re_t) re_compiled;
+}
+
+void re_print(regex_t* pattern)
+{
+ const char* types[] = { "UNUSED", "DOT", "BEGIN", "END", "QUESTIONMARK", "STAR", "PLUS", "CHAR", "CHAR_CLASS", "INV_CHAR_CLASS", "DIGIT", "NOT_DIGIT", "ALPHA", "NOT_ALPHA", "WHITESPACE", "NOT_WHITESPACE", "BRANCH" };
+
+ int i;
+ for (i = 0; i < MAX_REGEXP_OBJECTS; ++i)
+ {
+ if (pattern[i].type == UNUSED)
+ {
+ break;
+ }
+
+ printf("type: %s", types[pattern[i].type]);
+ if (pattern[i].type == CHAR_CLASS || pattern[i].type == INV_CHAR_CLASS)
+ {
+ printf(" [");
+ int j;
+ char c;
+ for (j = 0; j < MAX_CHAR_CLASS_LEN; ++j)
+ {
+ c = pattern[i].u.ccl[j];
+ if ((c == '\0') || (c == ']'))
+ {
+ break;
+ }
+ printf("%c", c);
+ }
+ printf("]");
+ }
+ else if (pattern[i].type == CHAR)
+ {
+ printf(" '%c'", pattern[i].u.ch);
+ }
+ printf("\n");
+ }
+}
+
+
+
+/* Private functions: */
+static int matchdigit(char c)
+{
+ return ((c >= '0') && (c <= '9'));
+}
+static int matchalpha(char c)
+{
+ return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
+}
+static int matchwhitespace(char c)
+{
+ return ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\f') || (c == '\v'));
+}
+static int matchalphanum(char c)
+{
+ return ((c == '_') || matchalpha(c) || matchdigit(c));
+}
+static int matchrange(char c, const char* str)
+{
+ return ((c != '-') && (str[0] != '\0') && (str[0] != '-') &&
+ (str[1] == '-') && (str[1] != '\0') &&
+ (str[2] != '\0') && ((c >= str[0]) && (c <= str[2])));
+}
+static int ismetachar(char c)
+{
+ return ((c == 's') || (c == 'S') || (c == 'w') || (c == 'W') || (c == 'd') || (c == 'D'));
+}
+
+static int matchmetachar(char c, const char* str)
+{
+ switch (str[0])
+ {
+ case 'd': return matchdigit(c);
+ case 'D': return !matchdigit(c);
+ case 'w': return matchalphanum(c);
+ case 'W': return !matchalphanum(c);
+ case 's': return matchwhitespace(c);
+ case 'S': return !matchwhitespace(c);
+ default: return (c == str[0]);
+ }
+}
+
+static int matchcharclass(char c, const char* str)
+{
+ do
+ {
+ if (matchrange(c, str))
+ {
+ return 1;
+ }
+ else if (str[0] == '\\')
+ {
+ /* Escape-char: increment str-ptr and match on next char */
+ str += 1;
+ if (matchmetachar(c, str))
+ {
+ return 1;
+ }
+ else if ((c == str[0]) && !ismetachar(c))
+ {
+ return 1;
+ }
+ }
+ else if (c == str[0])
+ {
+ if (c == '-')
+ {
+ return ((str[-1] == '\0') || (str[1] == '\0'));
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+ while (*str++ != '\0');
+
+ return 0;
+}
+
+static int matchone(regex_t p, char c)
+{
+ switch (p.type)
+ {
+ case DOT: return 1;
+ case CHAR_CLASS: return matchcharclass(c, (const char*)p.u.ccl);
+ case INV_CHAR_CLASS: return !matchcharclass(c, (const char*)p.u.ccl);
+ case DIGIT: return matchdigit(c);
+ case NOT_DIGIT: return !matchdigit(c);
+ case ALPHA: return matchalphanum(c);
+ case NOT_ALPHA: return !matchalphanum(c);
+ case WHITESPACE: return matchwhitespace(c);
+ case NOT_WHITESPACE: return !matchwhitespace(c);
+ default: return (p.u.ch == c);
+ }
+}
+
+static int matchstar(regex_t p, regex_t* pattern, const char* text)
+{
+ do
+ {
+ if (matchpattern(pattern, text))
+ return 1;
+ }
+ while ((text[0] != '\0') && matchone(p, *text++));
+
+ return 0;
+}
+
+static int matchplus(regex_t p, regex_t* pattern, const char* text)
+{
+ while ((text[0] != '\0') && matchone(p, *text++))
+ {
+ if (matchpattern(pattern, text))
+ return 1;
+ }
+ return 0;
+}
+
+static int matchquestion(regex_t p, regex_t* pattern, const char* text)
+{
+ if (p.type == UNUSED)
+ return 1;
+ if (matchpattern(pattern, text))
+ return 1;
+ if (*text && matchone(p, *text++))
+ return matchpattern(pattern, text);
+ return 0;
+}
+
+
+#if 0
+
+/* Recursive matching */
+static int matchpattern(regex_t* pattern, const char* text)
+{
+ if ((pattern[0].type == UNUSED) || (pattern[1].type == QUESTIONMARK))
+ {
+ return matchquestion(pattern[1], &pattern[2], text);
+ }
+ else if (pattern[1].type == STAR)
+ {
+ return matchstar(pattern[0], &pattern[2], text);
+ }
+ else if (pattern[1].type == PLUS)
+ {
+ return matchplus(pattern[0], &pattern[2], text);
+ }
+ else if ((pattern[0].type == END) && pattern[1].type == UNUSED)
+ {
+ return text[0] == '\0';
+ }
+ else if ((text[0] != '\0') && matchone(pattern[0], text[0]))
+ {
+ return matchpattern(&pattern[1], text+1);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+#else
+
+/* Iterative matching */
+static int matchpattern(regex_t* pattern, const char* text)
+{
+ do
+ {
+ if ((pattern[0].type == UNUSED) || (pattern[1].type == QUESTIONMARK))
+ {
+ return matchquestion(pattern[0], &pattern[2], text);
+ }
+ else if (pattern[1].type == STAR)
+ {
+ return matchstar(pattern[0], &pattern[2], text);
+ }
+ else if (pattern[1].type == PLUS)
+ {
+ return matchplus(pattern[0], &pattern[2], text);
+ }
+ else if ((pattern[0].type == END) && pattern[1].type == UNUSED)
+ {
+ return (text[0] == '\0');
+ }
+/* Branching is not working properly
+ else if (pattern[1].type == BRANCH)
+ {
+ return (matchpattern(pattern, text) || matchpattern(&pattern[2], text));
+ }
+*/
+ }
+ while ((text[0] != '\0') && matchone(*pattern++, *text++));
+
+ return 0;
+}
+
+#endif
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.h b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.h
new file mode 100644
index 0000000000..fd36412100
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/re.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Mini regex-module inspired by Rob Pike's regex code described in:
+ *
+ * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html
+ *
+ *
+ *
+ * Supports:
+ * ---------
+ * '.' Dot, matches any character
+ * '^' Start anchor, matches beginning of string
+ * '$' End anchor, matches end of string
+ * '*' Asterisk, match zero or more (greedy)
+ * '+' Plus, match one or more (greedy)
+ * '?' Question, match zero or one (non-greedy)
+ * '[abc]' Character class, match if one of {'a', 'b', 'c'}
+ * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken!
+ * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z }
+ * '\s' Whitespace, \t \f \r \n \v and spaces
+ * '\S' Non-whitespace
+ * '\w' Alphanumeric, [a-zA-Z0-9_]
+ * '\W' Non-alphanumeric
+ * '\d' Digits, [0-9]
+ * '\D' Non-digits
+ *
+ *
+ */
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+
+/* Typedef'd pointer to get abstract datatype. */
+typedef struct regex_t* re_t;
+
+
+/* Compile regex string pattern to a regex_t-array. */
+re_t re_compile(const char* pattern);
+
+
+/* Find matches of the compiled pattern inside text. */
+int re_matchp(re_t pattern, const char* text);
+
+
+/* Find matches of the txt pattern inside text (will compile automatically first). */
+int re_match(const char* pattern, const char* text);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/exrex.py b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/exrex.py
new file mode 100644
index 0000000000..fc6fa7d5cc
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/exrex.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+
+# This file is part of exrex.
+#
+# exrex is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# exrex 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with exrex. If not, see < http://www.gnu.org/licenses/ >.
+#
+# (C) 2012- by Adam Tauber, <asciimoo@gmail.com>
+
+try:
+ from future_builtins import map, range
+except:
+ pass
+from re import sre_parse
+from itertools import product, chain, tee
+from random import choice,randint
+import string
+
+__all__ = ('generate', 'CATEGORIES', 'count', 'parse', 'getone')
+
+CATEGORIES = {'category_space' : sorted(sre_parse.WHITESPACE)
+ ,'category_digit' : sorted(sre_parse.DIGITS)
+ ,'category_any' : [chr(x) for x in range(32, 123)]
+ ,'category_word' : sorted( frozenset(string.ascii_letters + string.digits + "_") )
+ }
+
+def comb(g, i):
+ for c in g:
+ g2,i = tee(i)
+ for c2 in g2:
+ yield c+c2
+
+def mappend(g, c):
+ for cc in g:
+ yield cc+c
+
+def _in(d):
+ ret = []
+ neg = False
+ for i in d:
+ if i[0] == 'range':
+ subs = map(chr, range(i[1][0], i[1][1]+1))
+ if neg:
+ for char in subs:
+ try:
+ ret.remove(char)
+ except:
+ pass
+ else:
+ ret.extend(subs)
+ elif i[0] == 'literal':
+ if neg:
+ try:
+ ret.remove(chr(i[1]))
+ except:
+ pass
+ else:
+ ret.append(chr(i[1]))
+ elif i[0] == 'category':
+ subs = CATEGORIES.get(i[1], [''])
+ if neg:
+ for char in subs:
+ try:
+ ret.remove(char)
+ except:
+ pass
+ else:
+ ret.extend(subs)
+ elif i[0] == 'negate':
+ ret = list(CATEGORIES['category_any'])
+ neg = True
+ return ret
+
+
+def prods(orig, ran, items):
+ for o in orig:
+ for r in ran:
+ for s in product(items, repeat=r):
+ yield o+''.join(s)
+
+def ggen(g1, f, *args, **kwargs):
+ for a in g1:
+ g2 = f(*args, **kwargs)
+ if isinstance(g2, int):
+ yield g2
+ else:
+ for b in g2:
+ yield a+b
+
+def _gen(d, limit=20, count=False):
+ """docstring for _gen"""
+ ret = ['']
+ strings = 0
+ for i in d:
+ if i[0] == 'in':
+ subs = _in(i[1])
+ if count:
+ strings = (strings or 1) * len(subs)
+ ret = comb(ret, subs)
+ elif i[0] == 'literal':
+ ret = mappend(ret, chr(i[1]))
+ elif i[0] == 'category':
+ subs = CATEGORIES.get(i[1], [''])
+ if count:
+ strings = (strings or 1) * len(subs)
+ ret = comb(ret, subs)
+ elif i[0] == 'any':
+ subs = CATEGORIES['category_any']
+ if count:
+ strings = (strings or 1) * len(subs)
+ ret = comb(ret, subs)
+ elif i[0] == 'max_repeat':
+ chars = filter(None, _gen(list(i[1][2]), limit))
+ if i[1][1]+1 - i[1][0] >= limit:
+ ran = range(i[1][0], i[1][0]+limit)
+ else:
+ ran = range(i[1][0], i[1][1]+1)
+ if count:
+ for i in ran:
+ strings += pow(len(chars), i)
+ ret = prods(ret, ran, chars)
+ elif i[0] == 'branch':
+ subs = list(chain.from_iterable(_gen(list(x), limit) for x in i[1][1]))
+ if count:
+ strings = (strings or 1) * (len(subs) or 1)
+ ret = comb(ret, subs)
+ elif i[0] == 'subpattern':
+ if count:
+ strings = (strings or 1) * (sum(ggen([0], _gen, i[1][1], limit=limit, count=True)) or 1)
+ ret = ggen(ret, _gen, i[1][1], limit=limit, count=False)
+ # ignore ^ and $
+ elif i[0] == 'at':
+ continue
+ elif i[0] == 'not_literal':
+ subs = list(CATEGORIES['category_any'])
+ subs.remove(chr(i[1]))
+ if count:
+ strings = (strings or 1) * len(subs)
+ ret = comb(ret, subs)
+ elif i[0] == 'assert':
+ print i[1][1]
+ continue
+ else:
+ #print('[!] cannot handle expression ' + repr(i))
+ raise Exception('[!] cannot handle expression ' + repr(i))
+
+ if count:
+ return strings
+
+ return ret
+
+def _randone(d, limit=20):
+ """docstring for _randone"""
+ ret = ''
+ for i in d:
+ if i[0] == 'in':
+ ret += choice(_in(i[1]))
+ elif i[0] == 'literal':
+ ret += chr(i[1])
+ elif i[0] == 'category':
+ ret += choice(CATEGORIES.get(i[1], ['']))
+ elif i[0] == 'any':
+ ret += choice(CATEGORIES['category_any'])
+ elif i[0] == 'max_repeat':
+ chars = filter(None, _gen(list(i[1][2]), limit))
+ if i[1][1]+1 - i[1][0] >= limit:
+ min,max = i[1][0], i[1][0]+limit
+ else:
+ min,max = i[1][0], i[1][1]
+ for _ in range(randint(min, max)):
+ ret += choice(chars)
+ elif i[0] == 'branch':
+ ret += choice(list(chain.from_iterable(_gen(list(x), limit) for x in i[1][1])))
+ elif i[0] == 'subpattern':
+ ret += _randone(i[1][1], limit)
+ elif i[0] == 'at':
+ continue
+ elif i[0] == 'not_literal':
+ c=list(CATEGORIES['category_any'])
+ c.remove(chr(i[1]))
+ ret += choice(c)
+ else:
+ #print('[!] cannot handle expression "%s"' % str(i))
+ raise Exception('[!] cannot handle expression "%s"' % str(i))
+
+ return ret
+
+
+def parse(s):
+ """Regular expression parser
+ :param s: Regular expression
+ :type s: str
+ :rtype: list
+ """
+ r = sre_parse.parse(s)
+ return list(r)
+
+def generate(s, limit=20):
+ """Creates a generator that generates all matching strings to a given regular expression
+ :param s: Regular expression
+ :type s: str
+ :param limit: Range limit
+ :type limit: int
+ :returns: string generator object
+ """
+ return _gen(parse(s), limit)
+
+def count(s, limit=20):
+ """Counts all matching strings to a given regular expression
+ :param s: Regular expression
+ :type s: str
+ :param limit: Range limit
+ :type limit: int
+ :rtype: int
+ :returns: number of matching strings
+ """
+ return _gen(parse(s), limit, count=True)
+
+def getone(regex_string, limit=20):
+ """Returns a random matching string to a given regular expression
+ """
+ return _randone(parse(regex_string), limit)
+
+def argparser():
+ import argparse
+ from sys import stdout
+ argp = argparse.ArgumentParser(description='exrex - regular expression string generator')
+ argp.add_argument('-o', '--output'
+ ,help = 'Output file - default is STDOUT'
+ ,metavar = 'FILE'
+ ,default = stdout
+ ,type = argparse.FileType('w')
+ )
+ argp.add_argument('-l', '--limit'
+ ,help = 'Max limit for range size - default is 20'
+ ,default = 20
+ ,action = 'store'
+ ,type = int
+ ,metavar = 'N'
+ )
+ argp.add_argument('-c', '--count'
+ ,help = 'Count matching strings'
+ ,default = False
+ ,action = 'store_true'
+ )
+ argp.add_argument('-r', '--random'
+ ,help = 'Returns a random string that matches to the regex'
+ ,default = False
+ ,action = 'store_true'
+ )
+ argp.add_argument('-d', '--delimiter'
+ ,help = 'Delimiter - default is \\n'
+ ,default = '\n'
+ )
+ argp.add_argument('-v', '--verbose'
+ ,action = 'store_true'
+ ,help = 'Verbose mode'
+ ,default = False
+ )
+ argp.add_argument('regex'
+ ,metavar = 'REGEX'
+ ,help = 'REGEX string'
+ )
+ return vars(argp.parse_args())
+
+def __main__():
+ from sys import exit, stderr
+ # 'as(d|f)qw(e|r|s)[a-zA-Z]{2,3}'
+ # 'as(QWE|Z([XC]|Y|U)V){2,3}asdf'
+ # '.?'
+ # '.+'
+ # 'asdf.{1,4}qwer{2,5}'
+ # 'a(b)?(c)?(d)?'
+ # 'a[b][c][d]?[e]?
+ args = argparser()
+ if args['verbose']:
+ args['output'].write('%r%s' % (parse(args['regex'], limit=args['limit']), args['delimiter']))
+ if args['count']:
+ args['output'].write('%d%s' % (count(args['regex'], limit=args['limit']), args['delimiter']))
+ exit(0)
+ if args['random']:
+ args['output'].write('%s%s' % (getone(args['regex'], limit=args['limit']), args['delimiter']))
+ exit(0)
+ try:
+ g = generate(args['regex'], args['limit'])
+ except Exception, e:
+ print >> stderr, '[!] Error: ', e
+ exit(1)
+ for s in g:
+ try:
+ args['output'].write(s+args['delimiter'])
+ except:
+ break
+
+if __name__ == '__main__':
+ __main__()
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test.py b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test.py
new file mode 100644
index 0000000000..0d3d00702c
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+"""
+ This program generates random text that matches a given regex-pattern.
+ The pattern is given via sys.argv and the generated text is passed to
+ the binary 'tests/test_rand' to check if the generated text also matches
+ the regex-pattern in the C implementation.
+ The exit-code of the testing program, is used to determine test success.
+
+ This script is called by the Makefile when doing 'make test'
+"""
+
+
+import re
+import sys
+import exrex
+from subprocess import call
+
+
+prog = "./tests/test_rand"
+
+if len(sys.argv) < 2:
+ print("")
+ print("usage: %s pattern [nrepeat]" % sys.argv[0])
+ print(" where [nrepeat] is optional")
+ print("")
+ sys.exit(-1)
+
+own_prog = sys.argv[0]
+pattern = sys.argv[1]
+if len(sys.argv) > 2:
+ ntests = int(sys.argv[2])
+else:
+ ntests = 10
+nfails = 0
+repeats = ntests
+
+
+try:
+ repeats = int(sys.argv[2])
+except:
+ pass
+
+r = 50
+while r < 0:
+ try:
+ g = exrex.generate(pattern)
+ break
+ except:
+ pass
+
+
+sys.stdout.write("%-35s" % (" pattern '%s': " % pattern))
+
+
+while repeats >= 0:
+ try:
+ repeats -= 1
+ example = exrex.getone(pattern)
+ #print("%s %s %s" % (prog, pattern, example))
+ ret = call([prog, "\"%s\"" % pattern, "\"%s\"" % example])
+ if ret != 0:
+ escaped = repr(example) # escapes special chars for better printing
+ print(" FAIL : doesn't match %s as expected [%s]." % (escaped, ", ".join([("0x%02x" % ord(e)) for e in example]) ))
+ nfails += 1
+
+ except:
+ #import traceback
+ #print("EXCEPTION!")
+ #raw_input(traceback.format_exc())
+ ntests -= 1
+ repeats += 1
+ #nfails += 1
+
+sys.stdout.write("%4d/%d tests succeeded \n" % (ntests - nfails, ntests))
+#print("")
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test_neg.py b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test_neg.py
new file mode 100644
index 0000000000..c3daad62c0
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/scripts/regex_test_neg.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+"""
+ This program generates random text that matches a given regex-pattern.
+ The pattern is given via sys.argv and the generated text is passed to
+ the binary 'tests/test_rand' to check if the generated text also matches
+ the regex-pattern in the C implementation.
+ The exit-code of the testing program, is used to determine test success.
+
+ This script is called by the Makefile when doing 'make test'
+"""
+
+
+import re
+import sys
+import string
+import random
+from subprocess import call
+
+
+prog = "./tests/test_rand_neg"
+
+if len(sys.argv) < 2:
+ print("")
+ print("usage: %s pattern [nrepeat]" % sys.argv[0])
+ print(" where [nrepeat] is optional")
+ print("")
+ sys.exit(-1)
+
+own_prog = sys.argv[0]
+pattern = sys.argv[1]
+if len(sys.argv) > 2:
+ ntests = int(sys.argv[2])
+else:
+ ntests = 10
+nfails = 0
+repeats = ntests
+
+
+try:
+ repeats = int(sys.argv[2])
+except:
+ pass
+
+sys.stdout.write("%-35s" % (" pattern '%s': " % pattern))
+
+
+
+
+def gen_no_match(pattern, minlen=1, maxlen=50, maxattempts=500):
+ nattempts = 0
+ while True:
+ nattempts += 1
+ ret = "".join([random.choice(string.printable) for i in range(random.Random().randint(minlen, maxlen))])
+ if re.findall(pattern, ret) == []:
+ return ret
+ if nattempts >= maxattempts:
+ raise Exception("Could not generate string that did not match the regex pattern '%s' after %d attempts" % (pattern, nattempts))
+
+
+
+while repeats >= 0:
+ try:
+ repeats -= 1
+ example = gen_no_match(pattern)
+ #print("%s %s %s" % (prog, pattern, example))
+ ret = call([prog, "\"%s\"" % pattern, "\"%s\"" % example])
+ if ret != 0:
+ escaped = repr(example) # escapes special chars for better printing
+ print(" FAIL : matches %s unexpectedly [%s]." % (escaped, ", ".join([("0x%02x" % ord(e)) for e in example]) ))
+ nfails += 1
+
+ except:
+ #import traceback
+ #print("EXCEPTION!")
+ #raw_input(traceback.format_exc())
+ ntests -= 1
+ repeats += 1
+ #nfails += 1
+
+sys.stdout.write("%4d/%d tests succeeded \n" % (ntests - nfails, ntests))
+#print("")
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test1.c b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test1.c
new file mode 100644
index 0000000000..ab54cc2ebe
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test1.c
@@ -0,0 +1,141 @@
+/*
+ * Testing various regex-patterns
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "re.h"
+
+
+#define OK ((char*) 1)
+#define NOK ((char*) 0)
+
+
+char* test_vector[][3] =
+{
+ { OK, "\\d", "5" },
+ { OK, "\\w+", "hej" },
+ { OK, "\\s", "\t \n" },
+ { NOK, "\\S", "\t \n" },
+ { OK, "[\\s]", "\t \n" },
+ { NOK, "[\\S]", "\t \n" },
+ { NOK, "\\D", "5" },
+ { NOK, "\\W+", "hej" },
+ { OK, "[0-9]+", "12345" },
+ { OK, "\\D", "hej" },
+ { NOK, "\\d", "hej" },
+ { OK, "[^\\w]", "\\" },
+ { OK, "[\\W]", "\\" },
+ { NOK, "[\\w]", "\\" },
+ { OK, "[^\\d]", "d" },
+ { NOK, "[\\d]", "d" },
+ { NOK, "[^\\D]", "d" },
+ { OK, "[\\D]", "d" },
+ { OK, "^.*\\\\.*$", "c:\\Tools" },
+ { OK, "^[\\+-]*[\\d]+$", "+27" },
+ { OK, "[abc]", "1c2" },
+ { NOK, "[abc]", "1C2" },
+ { OK, "[1-5]+", "0123456789" },
+ { OK, "[.2]", "1C2" },
+ { OK, "a*$", "Xaa" },
+ { OK, "a*$", "Xaa" },
+ { OK, "[a-h]+", "abcdefghxxx" },
+ { NOK, "[a-h]+", "ABCDEFGH" },
+ { OK, "[A-H]+", "ABCDEFGH" },
+ { NOK, "[A-H]+", "abcdefgh" },
+ { OK, "[^\\s]+", "abc def" },
+ { OK, "[^fc]+", "abc def" },
+ { OK, "[^d\\sf]+", "abc def" },
+ { OK, "\n", "abc\ndef" },
+ { OK, "b.\\s*\n", "aa\r\nbb\r\ncc\r\n\r\n" },
+ { OK, ".*c", "abcabc" },
+ { OK, ".+c", "abcabc" },
+ { OK, "[b-z].*", "ab" },
+ { OK, "b[k-z]*", "ab" },
+ { NOK, "[0-9]", " - " },
+ { OK, "[^0-9]", " - " },
+ { OK, "0|", "0|" },
+ { NOK, "\\d\\d:\\d\\d:\\d\\d", "0s:00:00" },
+ { NOK, "\\d\\d:\\d\\d:\\d\\d", "000:00" },
+ { NOK, "\\d\\d:\\d\\d:\\d\\d", "00:0000" },
+ { NOK, "\\d\\d:\\d\\d:\\d\\d", "100:0:00" },
+ { NOK, "\\d\\d:\\d\\d:\\d\\d", "00:100:00" },
+ { NOK, "\\d\\d:\\d\\d:\\d\\d", "0:00:100" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "0:0:0" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "0:00:0" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "0:0:00" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "00:0:0" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "00:00:0" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "00:0:00" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "0:00:00" },
+ { OK, "\\d\\d?:\\d\\d?:\\d\\d?", "00:00:00" },
+ { OK, "[Hh]ello [Ww]orld\\s*[!]?", "Hello world !" },
+ { OK, "[Hh]ello [Ww]orld\\s*[!]?", "hello world !" },
+ { OK, "[Hh]ello [Ww]orld\\s*[!]?", "Hello World !" },
+ { OK, "[Hh]ello [Ww]orld\\s*[!]?", "Hello world! " },
+ { OK, "[Hh]ello [Ww]orld\\s*[!]?", "Hello world !" },
+ { OK, "[Hh]ello [Ww]orld\\s*[!]?", "hello World !" },
+ { NOK, "\\d\\d?:\\d\\d?:\\d\\d?", "a:0" }, /* Failing test case reported in https://github.com/kokke/tiny-regex-c/issues/12 */
+/*
+ { OK, "[^\\w][^-1-4]", ")T" },
+ { OK, "[^\\w][^-1-4]", ")^" },
+ { OK, "[^\\w][^-1-4]", "*)" },
+ { OK, "[^\\w][^-1-4]", "!." },
+ { OK, "[^\\w][^-1-4]", " x" },
+ { OK, "[^\\w][^-1-4]", "$b" },
+*/
+ { OK, ".?bar", "real_bar" },
+ { NOK, ".?bar", "real_foo" },
+ { NOK, "X?Y", "Z" },
+};
+
+
+void re_print(re_t);
+
+int main()
+{
+ char* text;
+ char* pattern;
+ int should_fail;
+ size_t ntests = sizeof(test_vector) / sizeof(*test_vector);
+ size_t nfailed = 0;
+ size_t i;
+
+ for (i = 0; i < ntests; ++i)
+ {
+ pattern = test_vector[i][1];
+ text = test_vector[i][2];
+ should_fail = (test_vector[i][0] == NOK);
+
+ int m = re_match(pattern, text);
+
+ if (should_fail)
+ {
+ if (m != (-1))
+ {
+ printf("\n");
+ re_print(re_compile(pattern));
+ fprintf(stderr, "[%lu/%lu]: pattern '%s' matched '%s' unexpectedly. \n", (i+1), ntests, pattern, text);
+ nfailed += 1;
+ }
+ }
+ else
+ {
+ if (m == (-1))
+ {
+ printf("\n");
+ re_print(re_compile(pattern));
+ fprintf(stderr, "[%lu/%lu]: pattern '%s' didn't match '%s' as expected. \n", (i+1), ntests, pattern, text);
+ nfailed += 1;
+ }
+ }
+ }
+
+ // printf("\n");
+ printf("%lu/%lu tests succeeded.\n", ntests - nfailed, ntests);
+ printf("\n");
+ printf("\n");
+ printf("\n");
+
+ return 0;
+}
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test2.c b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test2.c
new file mode 100644
index 0000000000..f234f2d49a
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test2.c
@@ -0,0 +1,2097 @@
+/*
+ * A small performance test, to see how the library performs on a few MBs of text.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "re.h"
+
+
+char buf[] = {
+ 0x79, 0x66, 0x75, 0x66, 0x63, 0x6f, 0x75, 0x62, 0x74, 0x77, 0x66, 0x6f, 0x69, 0x72, 0x71, 0x78,
+ 0x66, 0x69, 0x63, 0x72, 0x6c, 0x61, 0x6a, 0x79, 0x68, 0x6d, 0x67, 0x66, 0x67, 0x75, 0x69, 0x65,
+ 0x62, 0x6d, 0x72, 0x63, 0x67, 0x74, 0x64, 0x62, 0x67, 0x64, 0x6c, 0x66, 0x78, 0x68, 0x75, 0x6f,
+ 0x73, 0x6b, 0x68, 0x68, 0x64, 0x68, 0x71, 0x66, 0x79, 0x6a, 0x6a, 0x67, 0x70, 0x6e, 0x6f, 0x77,
+ 0x6e, 0x68, 0x79, 0x65, 0x76, 0x61, 0x73, 0x6e, 0x77, 0x71, 0x74, 0x64, 0x77, 0x76, 0x74, 0x6d,
+ 0x6e, 0x76, 0x79, 0x71, 0x79, 0x79, 0x6a, 0x63, 0x74, 0x75, 0x6f, 0x74, 0x6d, 0x66, 0x67, 0x64,
+ 0x77, 0x61, 0x75, 0x79, 0x72, 0x79, 0x69, 0x73, 0x6f, 0x69, 0x67, 0x65, 0x6a, 0x6b, 0x66, 0x69,
+ 0x63, 0x79, 0x64, 0x71, 0x68, 0x6c, 0x67, 0x66, 0x6c, 0x6e, 0x79, 0x64, 0x67, 0x76, 0x64, 0x6a,
+ 0x73, 0x64, 0x6a, 0x61, 0x79, 0x6d, 0x71, 0x72, 0x68, 0x67, 0x68, 0x67, 0x66, 0x64, 0x63, 0x77,
+ 0x6f, 0x73, 0x67, 0x6d, 0x63, 0x74, 0x77, 0x72, 0x6b, 0x6f, 0x6f, 0x63, 0x68, 0x6f, 0x66, 0x67,
+ 0x73, 0x66, 0x6f, 0x75, 0x77, 0x62, 0x71, 0x6b, 0x77, 0x72, 0x68, 0x6d, 0x66, 0x71, 0x78, 0x75,
+ 0x6a, 0x74, 0x75, 0x6c, 0x69, 0x62, 0x64, 0x61, 0x78, 0x78, 0x66, 0x71, 0x61, 0x6d, 0x76, 0x76,
+ 0x6f, 0x65, 0x68, 0x78, 0x70, 0x79, 0x65, 0x68, 0x76, 0x62, 0x73, 0x6f, 0x64, 0x76, 0x63, 0x64,
+ 0x74, 0x73, 0x6e, 0x6a, 0x6a, 0x61, 0x72, 0x62, 0x66, 0x76, 0x63, 0x71, 0x6d, 0x74, 0x67, 0x75,
+ 0x6a, 0x6b, 0x6a, 0x6e, 0x75, 0x72, 0x73, 0x6d, 0x65, 0x69, 0x79, 0x62, 0x6d, 0x67, 0x63, 0x63,
+ 0x6c, 0x6c, 0x67, 0x6e, 0x6b, 0x76, 0x6e, 0x61, 0x79, 0x6a, 0x62, 0x6d, 0x70, 0x69, 0x67, 0x68,
+ 0x70, 0x74, 0x6b, 0x70, 0x74, 0x6e, 0x62, 0x6f, 0x6e, 0x6e, 0x61, 0x76, 0x68, 0x78, 0x77, 0x6f,
+ 0x77, 0x76, 0x6d, 0x6d, 0x75, 0x6b, 0x73, 0x6e, 0x79, 0x69, 0x6f, 0x72, 0x6a, 0x78, 0x67, 0x65,
+ 0x6b, 0x71, 0x61, 0x6b, 0x72, 0x75, 0x69, 0x65, 0x6b, 0x70, 0x69, 0x72, 0x70, 0x76, 0x79, 0x76,
+ 0x72, 0x76, 0x69, 0x76, 0x67, 0x66, 0x61, 0x72, 0x6c, 0x71, 0x66, 0x79, 0x74, 0x78, 0x6c, 0x6e,
+ 0x64, 0x68, 0x61, 0x66, 0x6f, 0x76, 0x6e, 0x67, 0x63, 0x78, 0x61, 0x75, 0x73, 0x65, 0x69, 0x77,
+ 0x67, 0x75, 0x77, 0x62, 0x75, 0x6b, 0x70, 0x77, 0x75, 0x69, 0x70, 0x62, 0x76, 0x73, 0x71, 0x70,
+ 0x78, 0x71, 0x77, 0x78, 0x66, 0x6e, 0x75, 0x65, 0x76, 0x6b, 0x79, 0x6d, 0x74, 0x61, 0x68, 0x61,
+ 0x78, 0x6e, 0x74, 0x77, 0x63, 0x79, 0x6e, 0x6d, 0x77, 0x71, 0x6f, 0x66, 0x6f, 0x65, 0x65, 0x72,
+ 0x61, 0x76, 0x64, 0x64, 0x67, 0x77, 0x69, 0x78, 0x6a, 0x75, 0x67, 0x66, 0x63, 0x79, 0x65, 0x6d,
+ 0x62, 0x68, 0x72, 0x6e, 0x78, 0x6d, 0x71, 0x6c, 0x6e, 0x6a, 0x62, 0x62, 0x64, 0x75, 0x6c, 0x6d,
+ 0x61, 0x71, 0x67, 0x6d, 0x68, 0x6f, 0x67, 0x71, 0x69, 0x74, 0x75, 0x78, 0x69, 0x6c, 0x65, 0x79,
+ 0x6e, 0x65, 0x76, 0x61, 0x75, 0x6a, 0x65, 0x73, 0x68, 0x63, 0x62, 0x6d, 0x6b, 0x6d, 0x6f, 0x6d,
+ 0x6c, 0x69, 0x79, 0x69, 0x6e, 0x76, 0x74, 0x66, 0x6f, 0x63, 0x6c, 0x6e, 0x6a, 0x75, 0x70, 0x70,
+ 0x62, 0x78, 0x71, 0x63, 0x6d, 0x6e, 0x67, 0x6e, 0x66, 0x65, 0x72, 0x62, 0x62, 0x74, 0x78, 0x77,
+ 0x6f, 0x69, 0x66, 0x75, 0x76, 0x79, 0x6c, 0x73, 0x62, 0x6e, 0x6c, 0x70, 0x6a, 0x76, 0x6c, 0x78,
+ 0x6e, 0x66, 0x6f, 0x68, 0x65, 0x6c, 0x75, 0x70, 0x62, 0x62, 0x78, 0x61, 0x62, 0x6b, 0x61, 0x6e,
+ 0x61, 0x78, 0x71, 0x71, 0x73, 0x6e, 0x6c, 0x6f, 0x6a, 0x67, 0x61, 0x65, 0x61, 0x6b, 0x74, 0x78,
+ 0x70, 0x67, 0x73, 0x65, 0x78, 0x79, 0x74, 0x76, 0x6f, 0x74, 0x73, 0x6f, 0x63, 0x76, 0x63, 0x70,
+ 0x66, 0x6d, 0x6a, 0x71, 0x62, 0x78, 0x68, 0x74, 0x71, 0x70, 0x69, 0x65, 0x77, 0x65, 0x77, 0x65,
+ 0x78, 0x6a, 0x72, 0x71, 0x6e, 0x65, 0x79, 0x64, 0x6b, 0x73, 0x79, 0x63, 0x64, 0x6b, 0x78, 0x64,
+ 0x66, 0x69, 0x77, 0x62, 0x6f, 0x71, 0x6c, 0x73, 0x6c, 0x68, 0x78, 0x70, 0x71, 0x79, 0x72, 0x79,
+ 0x6f, 0x6b, 0x6c, 0x77, 0x63, 0x6a, 0x68, 0x67, 0x69, 0x70, 0x68, 0x6e, 0x61, 0x71, 0x77, 0x61,
+ 0x70, 0x65, 0x76, 0x6c, 0x72, 0x71, 0x66, 0x66, 0x6e, 0x67, 0x71, 0x6c, 0x77, 0x63, 0x6c, 0x65,
+ 0x6b, 0x72, 0x66, 0x63, 0x73, 0x61, 0x70, 0x71, 0x64, 0x69, 0x6e, 0x71, 0x78, 0x6c, 0x74, 0x61,
+ 0x77, 0x65, 0x71, 0x61, 0x64, 0x66, 0x68, 0x67, 0x6f, 0x75, 0x66, 0x69, 0x73, 0x6e, 0x76, 0x6e,
+ 0x66, 0x63, 0x66, 0x74, 0x6c, 0x6b, 0x68, 0x62, 0x6e, 0x6c, 0x78, 0x65, 0x73, 0x70, 0x76, 0x78,
+ 0x61, 0x70, 0x66, 0x70, 0x79, 0x67, 0x69, 0x67, 0x68, 0x78, 0x70, 0x76, 0x73, 0x63, 0x6b, 0x68,
+ 0x71, 0x67, 0x66, 0x6c, 0x78, 0x77, 0x6c, 0x72, 0x76, 0x6c, 0x73, 0x68, 0x68, 0x61, 0x68, 0x6c,
+ 0x6c, 0x79, 0x6a, 0x66, 0x74, 0x77, 0x65, 0x62, 0x6e, 0x71, 0x6b, 0x61, 0x71, 0x75, 0x67, 0x62,
+ 0x76, 0x62, 0x6b, 0x71, 0x71, 0x6b, 0x65, 0x69, 0x74, 0x75, 0x79, 0x77, 0x6c, 0x65, 0x64, 0x67,
+ 0x70, 0x6a, 0x71, 0x73, 0x6c, 0x73, 0x61, 0x69, 0x70, 0x68, 0x73, 0x76, 0x74, 0x69, 0x77, 0x69,
+ 0x6b, 0x6b, 0x70, 0x68, 0x78, 0x79, 0x67, 0x79, 0x62, 0x63, 0x74, 0x68, 0x69, 0x63, 0x77, 0x70,
+ 0x6b, 0x6a, 0x74, 0x6a, 0x66, 0x75, 0x75, 0x73, 0x65, 0x68, 0x63, 0x6a, 0x64, 0x76, 0x64, 0x72,
+ 0x79, 0x77, 0x6d, 0x74, 0x69, 0x6a, 0x66, 0x65, 0x67, 0x77, 0x67, 0x73, 0x73, 0x74, 0x6a, 0x75,
+ 0x65, 0x6e, 0x72, 0x61, 0x63, 0x6e, 0x67, 0x74, 0x6d, 0x6d, 0x65, 0x76, 0x76, 0x65, 0x61, 0x64,
+ 0x70, 0x77, 0x78, 0x72, 0x77, 0x70, 0x6f, 0x69, 0x66, 0x71, 0x6e, 0x6c, 0x75, 0x68, 0x68, 0x6f,
+ 0x63, 0x6f, 0x6d, 0x62, 0x61, 0x70, 0x72, 0x77, 0x6c, 0x76, 0x6b, 0x70, 0x68, 0x6e, 0x6d, 0x78,
+ 0x68, 0x65, 0x6c, 0x6f, 0x65, 0x73, 0x63, 0x69, 0x65, 0x74, 0x77, 0x66, 0x64, 0x74, 0x68, 0x66,
+ 0x71, 0x62, 0x67, 0x72, 0x6a, 0x64, 0x68, 0x77, 0x6d, 0x72, 0x6b, 0x78, 0x72, 0x6b, 0x72, 0x78,
+ 0x70, 0x65, 0x69, 0x65, 0x72, 0x63, 0x6a, 0x69, 0x62, 0x75, 0x72, 0x6b, 0x69, 0x6a, 0x78, 0x65,
+ 0x68, 0x69, 0x6d, 0x6a, 0x75, 0x72, 0x66, 0x76, 0x79, 0x66, 0x67, 0x74, 0x79, 0x69, 0x76, 0x6d,
+ 0x77, 0x77, 0x65, 0x6b, 0x73, 0x61, 0x73, 0x6c, 0x70, 0x74, 0x6f, 0x76, 0x79, 0x6a, 0x66, 0x64,
+ 0x67, 0x6d, 0x72, 0x66, 0x66, 0x6e, 0x68, 0x63, 0x64, 0x73, 0x6c, 0x63, 0x6c, 0x71, 0x6d, 0x6c,
+ 0x63, 0x69, 0x65, 0x6b, 0x73, 0x64, 0x6b, 0x76, 0x68, 0x73, 0x71, 0x61, 0x72, 0x67, 0x6a, 0x79,
+ 0x78, 0x6a, 0x6f, 0x65, 0x71, 0x65, 0x72, 0x66, 0x62, 0x6d, 0x63, 0x73, 0x64, 0x77, 0x78, 0x77,
+ 0x6f, 0x67, 0x70, 0x6d, 0x6f, 0x66, 0x79, 0x79, 0x74, 0x75, 0x65, 0x75, 0x6e, 0x72, 0x76, 0x72,
+ 0x6a, 0x77, 0x78, 0x6e, 0x6e, 0x67, 0x74, 0x6d, 0x6f, 0x66, 0x6f, 0x6a, 0x67, 0x65, 0x6c, 0x75,
+ 0x63, 0x78, 0x6c, 0x67, 0x78, 0x79, 0x72, 0x61, 0x6b, 0x71, 0x76, 0x77, 0x6d, 0x6d, 0x69, 0x76,
+ 0x6f, 0x6e, 0x66, 0x61, 0x61, 0x62, 0x62, 0x79, 0x61, 0x66, 0x6d, 0x78, 0x74, 0x78, 0x69, 0x6f,
+ 0x63, 0x79, 0x70, 0x74, 0x75, 0x79, 0x63, 0x63, 0x70, 0x6d, 0x70, 0x66, 0x67, 0x65, 0x61, 0x70,
+ 0x79, 0x79, 0x6d, 0x6a, 0x6d, 0x77, 0x6a, 0x75, 0x62, 0x6b, 0x69, 0x64, 0x71, 0x67, 0x64, 0x63,
+ 0x62, 0x68, 0x6c, 0x68, 0x72, 0x6a, 0x67, 0x6d, 0x72, 0x73, 0x78, 0x72, 0x64, 0x65, 0x77, 0x72,
+ 0x72, 0x71, 0x6a, 0x64, 0x70, 0x71, 0x76, 0x73, 0x65, 0x75, 0x6d, 0x76, 0x6f, 0x6b, 0x66, 0x73,
+ 0x6b, 0x69, 0x6b, 0x66, 0x68, 0x79, 0x64, 0x78, 0x6b, 0x67, 0x76, 0x6e, 0x74, 0x70, 0x67, 0x69,
+ 0x62, 0x64, 0x72, 0x6a, 0x6e, 0x72, 0x72, 0x6b, 0x73, 0x6f, 0x6d, 0x6c, 0x6c, 0x66, 0x78, 0x75,
+ 0x66, 0x66, 0x6e, 0x6b, 0x69, 0x74, 0x6c, 0x79, 0x69, 0x70, 0x6c, 0x72, 0x6e, 0x74, 0x6e, 0x6e,
+ 0x67, 0x6f, 0x62, 0x70, 0x65, 0x62, 0x62, 0x6a, 0x68, 0x66, 0x76, 0x6a, 0x74, 0x6a, 0x69, 0x71,
+ 0x6c, 0x76, 0x77, 0x6b, 0x6b, 0x73, 0x6f, 0x64, 0x62, 0x67, 0x6a, 0x6b, 0x68, 0x65, 0x61, 0x69,
+ 0x77, 0x78, 0x74, 0x62, 0x70, 0x73, 0x70, 0x68, 0x6b, 0x75, 0x72, 0x70, 0x68, 0x6b, 0x75, 0x6d,
+ 0x62, 0x74, 0x77, 0x65, 0x71, 0x77, 0x6d, 0x65, 0x70, 0x66, 0x70, 0x6c, 0x69, 0x68, 0x75, 0x75,
+ 0x62, 0x62, 0x75, 0x69, 0x6d, 0x68, 0x63, 0x6e, 0x6d, 0x6b, 0x78, 0x70, 0x77, 0x61, 0x77, 0x69,
+ 0x78, 0x69, 0x6a, 0x68, 0x64, 0x74, 0x6e, 0x72, 0x6c, 0x6d, 0x72, 0x75, 0x6e, 0x66, 0x66, 0x67,
+ 0x6f, 0x73, 0x6e, 0x6f, 0x78, 0x72, 0x72, 0x6c, 0x66, 0x70, 0x66, 0x69, 0x6a, 0x71, 0x6e, 0x67,
+ 0x6c, 0x74, 0x76, 0x78, 0x74, 0x77, 0x73, 0x66, 0x73, 0x75, 0x70, 0x67, 0x67, 0x62, 0x75, 0x77,
+ 0x67, 0x78, 0x76, 0x6d, 0x6a, 0x78, 0x69, 0x75, 0x63, 0x6a, 0x62, 0x6e, 0x6d, 0x66, 0x61, 0x6b,
+ 0x73, 0x68, 0x72, 0x78, 0x79, 0x6d, 0x69, 0x68, 0x6f, 0x73, 0x6d, 0x62, 0x68, 0x70, 0x78, 0x6f,
+ 0x6e, 0x63, 0x63, 0x6f, 0x78, 0x65, 0x74, 0x6a, 0x77, 0x78, 0x79, 0x6a, 0x62, 0x78, 0x70, 0x69,
+ 0x65, 0x79, 0x77, 0x6d, 0x6b, 0x6c, 0x6b, 0x62, 0x6e, 0x75, 0x73, 0x6e, 0x63, 0x67, 0x6c, 0x63,
+ 0x63, 0x6a, 0x71, 0x62, 0x61, 0x78, 0x6c, 0x6d, 0x69, 0x64, 0x6f, 0x71, 0x62, 0x6f, 0x62, 0x72,
+ 0x6b, 0x61, 0x65, 0x77, 0x62, 0x75, 0x79, 0x6e, 0x73, 0x79, 0x67, 0x76, 0x63, 0x70, 0x69, 0x6a,
+ 0x6c, 0x62, 0x70, 0x62, 0x61, 0x77, 0x69, 0x6e, 0x62, 0x71, 0x6e, 0x6b, 0x72, 0x76, 0x76, 0x64,
+ 0x77, 0x68, 0x66, 0x78, 0x77, 0x64, 0x6b, 0x6a, 0x74, 0x66, 0x67, 0x69, 0x70, 0x65, 0x6a, 0x68,
+ 0x71, 0x76, 0x71, 0x69, 0x75, 0x64, 0x6b, 0x71, 0x71, 0x61, 0x67, 0x6d, 0x67, 0x62, 0x69, 0x6b,
+ 0x61, 0x66, 0x62, 0x63, 0x76, 0x64, 0x66, 0x73, 0x63, 0x78, 0x74, 0x77, 0x6e, 0x63, 0x68, 0x61,
+ 0x6c, 0x71, 0x70, 0x69, 0x65, 0x77, 0x6d, 0x69, 0x72, 0x6b, 0x6e, 0x6f, 0x75, 0x78, 0x6d, 0x74,
+ 0x6a, 0x68, 0x72, 0x6b, 0x69, 0x72, 0x6b, 0x78, 0x72, 0x68, 0x65, 0x68, 0x76, 0x6d, 0x67, 0x71,
+ 0x65, 0x6f, 0x61, 0x72, 0x6f, 0x63, 0x70, 0x67, 0x78, 0x73, 0x6f, 0x62, 0x6b, 0x65, 0x64, 0x6b,
+ 0x62, 0x76, 0x76, 0x77, 0x63, 0x6a, 0x77, 0x78, 0x6e, 0x79, 0x63, 0x75, 0x62, 0x75, 0x67, 0x67,
+ 0x62, 0x6a, 0x6a, 0x74, 0x6f, 0x6a, 0x6c, 0x75, 0x70, 0x65, 0x61, 0x6f, 0x68, 0x6b, 0x67, 0x6e,
+ 0x6a, 0x6c, 0x69, 0x71, 0x63, 0x75, 0x6a, 0x72, 0x71, 0x6d, 0x75, 0x73, 0x78, 0x62, 0x78, 0x66,
+ 0x79, 0x79, 0x70, 0x6e, 0x75, 0x6c, 0x66, 0x6e, 0x6b, 0x6b, 0x73, 0x71, 0x6d, 0x77, 0x68, 0x6d,
+ 0x76, 0x75, 0x6c, 0x77, 0x6f, 0x71, 0x6c, 0x67, 0x70, 0x6f, 0x76, 0x70, 0x72, 0x64, 0x74, 0x77,
+ 0x63, 0x78, 0x69, 0x73, 0x6f, 0x77, 0x6f, 0x6a, 0x64, 0x64, 0x77, 0x6b, 0x79, 0x72, 0x65, 0x6f,
+ 0x74, 0x61, 0x71, 0x71, 0x6d, 0x6d, 0x68, 0x66, 0x63, 0x6d, 0x73, 0x76, 0x6f, 0x76, 0x68, 0x6c,
+ 0x61, 0x6b, 0x76, 0x6a, 0x69, 0x73, 0x76, 0x72, 0x6c, 0x63, 0x78, 0x74, 0x73, 0x78, 0x62, 0x74,
+ 0x70, 0x68, 0x62, 0x6a, 0x70, 0x66, 0x74, 0x66, 0x61, 0x66, 0x72, 0x74, 0x6f, 0x67, 0x76, 0x67,
+ 0x6c, 0x64, 0x73, 0x69, 0x6d, 0x69, 0x6a, 0x74, 0x67, 0x73, 0x78, 0x69, 0x75, 0x72, 0x6e, 0x61,
+ 0x76, 0x6a, 0x69, 0x73, 0x6a, 0x77, 0x71, 0x67, 0x66, 0x6e, 0x66, 0x74, 0x71, 0x6a, 0x6f, 0x64,
+ 0x63, 0x6c, 0x67, 0x70, 0x77, 0x78, 0x64, 0x6f, 0x6b, 0x69, 0x76, 0x75, 0x66, 0x6c, 0x6d, 0x6d,
+ 0x65, 0x75, 0x65, 0x75, 0x77, 0x6a, 0x72, 0x6b, 0x77, 0x67, 0x65, 0x63, 0x6f, 0x6e, 0x6d, 0x6a,
+ 0x6d, 0x66, 0x78, 0x66, 0x66, 0x76, 0x61, 0x6f, 0x74, 0x6f, 0x63, 0x75, 0x79, 0x74, 0x61, 0x6a,
+ 0x64, 0x62, 0x75, 0x79, 0x77, 0x6a, 0x68, 0x76, 0x67, 0x61, 0x74, 0x64, 0x6d, 0x64, 0x75, 0x65,
+ 0x64, 0x6c, 0x70, 0x75, 0x68, 0x6c, 0x70, 0x74, 0x70, 0x71, 0x6a, 0x6d, 0x61, 0x79, 0x67, 0x76,
+ 0x69, 0x6c, 0x6a, 0x63, 0x6b, 0x69, 0x77, 0x63, 0x77, 0x63, 0x61, 0x72, 0x66, 0x76, 0x69, 0x78,
+ 0x72, 0x68, 0x72, 0x75, 0x74, 0x63, 0x64, 0x6a, 0x73, 0x79, 0x70, 0x6f, 0x69, 0x65, 0x6b, 0x73,
+ 0x71, 0x70, 0x6b, 0x68, 0x61, 0x68, 0x79, 0x62, 0x75, 0x65, 0x79, 0x68, 0x65, 0x6f, 0x67, 0x70,
+ 0x77, 0x78, 0x6f, 0x77, 0x72, 0x65, 0x75, 0x73, 0x6a, 0x64, 0x6c, 0x75, 0x6e, 0x65, 0x76, 0x78,
+ 0x73, 0x6a, 0x69, 0x6d, 0x61, 0x6d, 0x6a, 0x6d, 0x71, 0x6d, 0x71, 0x6b, 0x64, 0x6c, 0x65, 0x61,
+ 0x67, 0x6a, 0x6c, 0x64, 0x78, 0x64, 0x64, 0x78, 0x75, 0x73, 0x70, 0x76, 0x69, 0x66, 0x6e, 0x74,
+ 0x72, 0x73, 0x79, 0x78, 0x72, 0x74, 0x6b, 0x78, 0x71, 0x63, 0x62, 0x72, 0x75, 0x6d, 0x68, 0x63,
+ 0x69, 0x78, 0x6d, 0x71, 0x68, 0x6d, 0x64, 0x65, 0x75, 0x70, 0x6b, 0x73, 0x63, 0x72, 0x69, 0x75,
+ 0x77, 0x76, 0x67, 0x72, 0x75, 0x6c, 0x76, 0x65, 0x6e, 0x70, 0x63, 0x6f, 0x66, 0x71, 0x65, 0x62,
+ 0x73, 0x64, 0x70, 0x63, 0x78, 0x74, 0x6f, 0x73, 0x75, 0x6f, 0x78, 0x73, 0x71, 0x6e, 0x77, 0x75,
+ 0x70, 0x76, 0x74, 0x75, 0x61, 0x70, 0x68, 0x72, 0x71, 0x79, 0x6d, 0x72, 0x69, 0x79, 0x69, 0x74,
+ 0x61, 0x72, 0x75, 0x68, 0x72, 0x79, 0x62, 0x65, 0x6d, 0x61, 0x71, 0x6c, 0x77, 0x67, 0x73, 0x66,
+ 0x67, 0x69, 0x6e, 0x62, 0x6c, 0x74, 0x76, 0x70, 0x71, 0x64, 0x71, 0x79, 0x70, 0x73, 0x63, 0x6c,
+ 0x67, 0x63, 0x73, 0x6f, 0x68, 0x78, 0x73, 0x66, 0x6c, 0x6b, 0x62, 0x78, 0x70, 0x68, 0x62, 0x6c,
+ 0x66, 0x67, 0x74, 0x77, 0x61, 0x6c, 0x71, 0x70, 0x6a, 0x6f, 0x6c, 0x75, 0x6e, 0x61, 0x79, 0x68,
+ 0x73, 0x61, 0x79, 0x69, 0x71, 0x6e, 0x6d, 0x66, 0x6c, 0x68, 0x74, 0x72, 0x64, 0x64, 0x6a, 0x75,
+ 0x70, 0x6c, 0x69, 0x69, 0x68, 0x72, 0x66, 0x75, 0x61, 0x61, 0x69, 0x64, 0x66, 0x69, 0x68, 0x63,
+ 0x67, 0x6d, 0x76, 0x71, 0x6a, 0x6e, 0x6a, 0x78, 0x61, 0x77, 0x67, 0x77, 0x69, 0x77, 0x71, 0x6d,
+ 0x6b, 0x6a, 0x72, 0x71, 0x72, 0x6e, 0x61, 0x65, 0x6f, 0x71, 0x6f, 0x64, 0x6d, 0x79, 0x61, 0x66,
+ 0x6b, 0x77, 0x76, 0x64, 0x67, 0x6f, 0x66, 0x6e, 0x79, 0x64, 0x77, 0x75, 0x6d, 0x76, 0x64, 0x69,
+ 0x78, 0x6b, 0x72, 0x6f, 0x75, 0x74, 0x71, 0x6c, 0x77, 0x61, 0x6d, 0x69, 0x61, 0x75, 0x72, 0x61,
+ 0x6d, 0x78, 0x6c, 0x71, 0x6e, 0x74, 0x6c, 0x6e, 0x71, 0x78, 0x77, 0x6f, 0x64, 0x76, 0x66, 0x62,
+ 0x62, 0x75, 0x6b, 0x75, 0x66, 0x75, 0x73, 0x6a, 0x76, 0x75, 0x70, 0x73, 0x68, 0x6c, 0x77, 0x6d,
+ 0x75, 0x71, 0x78, 0x73, 0x64, 0x73, 0x78, 0x69, 0x76, 0x64, 0x61, 0x6e, 0x62, 0x6a, 0x79, 0x6f,
+ 0x70, 0x6a, 0x6d, 0x75, 0x6e, 0x75, 0x63, 0x66, 0x65, 0x75, 0x6a, 0x64, 0x6b, 0x65, 0x66, 0x64,
+ 0x62, 0x66, 0x78, 0x67, 0x77, 0x75, 0x74, 0x62, 0x67, 0x61, 0x6e, 0x67, 0x68, 0x6b, 0x6c, 0x73,
+ 0x6d, 0x69, 0x69, 0x75, 0x6e, 0x6c, 0x69, 0x73, 0x77, 0x69, 0x63, 0x64, 0x75, 0x6c, 0x6b, 0x78,
+ 0x69, 0x78, 0x67, 0x73, 0x72, 0x6a, 0x64, 0x78, 0x6a, 0x72, 0x78, 0x6f, 0x61, 0x76, 0x71, 0x66,
+ 0x76, 0x63, 0x77, 0x67, 0x75, 0x65, 0x73, 0x64, 0x64, 0x6a, 0x77, 0x68, 0x6f, 0x61, 0x6f, 0x78,
+ 0x6e, 0x6d, 0x78, 0x70, 0x76, 0x6b, 0x67, 0x67, 0x75, 0x6d, 0x6e, 0x62, 0x70, 0x74, 0x66, 0x6a,
+ 0x70, 0x68, 0x70, 0x6c, 0x74, 0x6d, 0x62, 0x66, 0x69, 0x73, 0x6a, 0x70, 0x66, 0x69, 0x6b, 0x73,
+ 0x62, 0x70, 0x6f, 0x61, 0x63, 0x63, 0x71, 0x6f, 0x70, 0x6a, 0x75, 0x64, 0x6d, 0x74, 0x68, 0x76,
+ 0x61, 0x6e, 0x72, 0x71, 0x62, 0x70, 0x64, 0x66, 0x70, 0x71, 0x61, 0x69, 0x68, 0x64, 0x61, 0x65,
+ 0x79, 0x78, 0x6b, 0x72, 0x64, 0x63, 0x6d, 0x6c, 0x67, 0x61, 0x6a, 0x67, 0x64, 0x73, 0x70, 0x76,
+ 0x74, 0x70, 0x6c, 0x66, 0x77, 0x71, 0x66, 0x72, 0x6c, 0x67, 0x69, 0x66, 0x70, 0x68, 0x67, 0x6e,
+ 0x70, 0x69, 0x67, 0x71, 0x73, 0x72, 0x6d, 0x71, 0x74, 0x64, 0x6b, 0x71, 0x73, 0x70, 0x78, 0x70,
+ 0x75, 0x76, 0x74, 0x6e, 0x73, 0x63, 0x6d, 0x64, 0x6e, 0x73, 0x79, 0x68, 0x6b, 0x6e, 0x6a, 0x77,
+ 0x6e, 0x62, 0x67, 0x6d, 0x72, 0x68, 0x6c, 0x76, 0x64, 0x6f, 0x73, 0x6d, 0x62, 0x67, 0x69, 0x68,
+ 0x64, 0x65, 0x72, 0x67, 0x75, 0x66, 0x68, 0x64, 0x61, 0x67, 0x6a, 0x75, 0x75, 0x6c, 0x72, 0x71,
+ 0x75, 0x74, 0x73, 0x78, 0x74, 0x6d, 0x62, 0x79, 0x6f, 0x63, 0x6f, 0x62, 0x67, 0x73, 0x70, 0x70,
+ 0x72, 0x6e, 0x68, 0x79, 0x76, 0x77, 0x76, 0x6e, 0x6e, 0x6e, 0x78, 0x65, 0x65, 0x63, 0x64, 0x61,
+ 0x62, 0x78, 0x71, 0x72, 0x63, 0x68, 0x71, 0x63, 0x73, 0x70, 0x70, 0x61, 0x71, 0x76, 0x64, 0x67,
+ 0x74, 0x71, 0x74, 0x67, 0x74, 0x77, 0x6e, 0x79, 0x73, 0x67, 0x79, 0x70, 0x77, 0x6f, 0x6b, 0x79,
+ 0x74, 0x79, 0x67, 0x6a, 0x6e, 0x6a, 0x70, 0x76, 0x62, 0x77, 0x74, 0x70, 0x72, 0x63, 0x6c, 0x74,
+ 0x65, 0x64, 0x63, 0x78, 0x64, 0x6d, 0x73, 0x69, 0x65, 0x70, 0x6d, 0x71, 0x6e, 0x6c, 0x62, 0x64,
+ 0x67, 0x6c, 0x72, 0x65, 0x6b, 0x63, 0x77, 0x6d, 0x63, 0x70, 0x72, 0x65, 0x6d, 0x74, 0x6d, 0x63,
+ 0x78, 0x75, 0x68, 0x70, 0x73, 0x63, 0x6e, 0x77, 0x71, 0x61, 0x73, 0x6b, 0x75, 0x6e, 0x76, 0x74,
+ 0x63, 0x70, 0x72, 0x65, 0x62, 0x75, 0x61, 0x6a, 0x76, 0x66, 0x75, 0x73, 0x64, 0x67, 0x6d, 0x77,
+ 0x64, 0x6a, 0x66, 0x6b, 0x6b, 0x6c, 0x66, 0x64, 0x69, 0x72, 0x70, 0x76, 0x67, 0x74, 0x6c, 0x6a,
+ 0x72, 0x67, 0x74, 0x66, 0x6a, 0x62, 0x66, 0x73, 0x79, 0x77, 0x6b, 0x62, 0x77, 0x6a, 0x75, 0x73,
+ 0x61, 0x69, 0x78, 0x6b, 0x66, 0x67, 0x62, 0x70, 0x65, 0x64, 0x76, 0x79, 0x77, 0x6c, 0x75, 0x74,
+ 0x77, 0x63, 0x73, 0x62, 0x63, 0x73, 0x6f, 0x6c, 0x64, 0x65, 0x6e, 0x6c, 0x6a, 0x72, 0x77, 0x6b,
+ 0x61, 0x78, 0x75, 0x77, 0x6c, 0x61, 0x64, 0x63, 0x64, 0x6a, 0x61, 0x68, 0x6e, 0x65, 0x68, 0x66,
+ 0x71, 0x6b, 0x73, 0x6f, 0x62, 0x6e, 0x69, 0x72, 0x79, 0x63, 0x6f, 0x79, 0x79, 0x75, 0x70, 0x77,
+ 0x75, 0x76, 0x63, 0x77, 0x76, 0x75, 0x70, 0x68, 0x65, 0x68, 0x63, 0x6c, 0x6d, 0x62, 0x73, 0x68,
+ 0x70, 0x68, 0x6b, 0x70, 0x63, 0x70, 0x79, 0x66, 0x68, 0x70, 0x72, 0x77, 0x65, 0x6e, 0x65, 0x74,
+ 0x62, 0x64, 0x74, 0x78, 0x6d, 0x70, 0x79, 0x74, 0x74, 0x6f, 0x6e, 0x6d, 0x78, 0x73, 0x6d, 0x6a,
+ 0x74, 0x6d, 0x75, 0x6f, 0x79, 0x66, 0x6c, 0x6b, 0x62, 0x68, 0x77, 0x67, 0x75, 0x71, 0x6e, 0x6d,
+ 0x6b, 0x63, 0x6a, 0x6a, 0x78, 0x78, 0x70, 0x68, 0x74, 0x72, 0x74, 0x65, 0x6f, 0x77, 0x6c, 0x72,
+ 0x74, 0x6c, 0x66, 0x78, 0x77, 0x78, 0x72, 0x73, 0x6f, 0x78, 0x6d, 0x66, 0x63, 0x61, 0x63, 0x6e,
+ 0x69, 0x73, 0x79, 0x72, 0x6f, 0x72, 0x62, 0x76, 0x75, 0x71, 0x70, 0x61, 0x78, 0x77, 0x76, 0x70,
+ 0x78, 0x69, 0x77, 0x65, 0x75, 0x63, 0x71, 0x6f, 0x6b, 0x6a, 0x74, 0x61, 0x63, 0x61, 0x64, 0x72,
+ 0x64, 0x62, 0x67, 0x72, 0x79, 0x6b, 0x74, 0x70, 0x6e, 0x6b, 0x63, 0x79, 0x66, 0x74, 0x6c, 0x6e,
+ 0x78, 0x6c, 0x70, 0x73, 0x6c, 0x69, 0x66, 0x6d, 0x71, 0x77, 0x79, 0x76, 0x71, 0x6e, 0x67, 0x78,
+ 0x74, 0x6b, 0x6b, 0x64, 0x6f, 0x63, 0x77, 0x61, 0x75, 0x6c, 0x6a, 0x6d, 0x6e, 0x72, 0x66, 0x6a,
+ 0x76, 0x75, 0x71, 0x6f, 0x6d, 0x71, 0x77, 0x75, 0x70, 0x77, 0x76, 0x74, 0x70, 0x71, 0x6b, 0x63,
+ 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x71, 0x6a, 0x71, 0x75, 0x65, 0x69, 0x6b, 0x63, 0x76,
+ 0x79, 0x6b, 0x76, 0x62, 0x77, 0x76, 0x73, 0x78, 0x6d, 0x76, 0x66, 0x6f, 0x69, 0x64, 0x72, 0x6d,
+ 0x6c, 0x62, 0x71, 0x61, 0x72, 0x6c, 0x6c, 0x70, 0x64, 0x69, 0x76, 0x6e, 0x62, 0x62, 0x69, 0x75,
+ 0x64, 0x73, 0x6b, 0x76, 0x76, 0x67, 0x6b, 0x78, 0x76, 0x70, 0x78, 0x70, 0x68, 0x67, 0x72, 0x6e,
+ 0x6b, 0x68, 0x6f, 0x73, 0x69, 0x6d, 0x71, 0x6b, 0x74, 0x6f, 0x79, 0x73, 0x65, 0x78, 0x6c, 0x67,
+ 0x74, 0x73, 0x6f, 0x62, 0x61, 0x73, 0x61, 0x63, 0x62, 0x74, 0x74, 0x6c, 0x68, 0x70, 0x76, 0x77,
+ 0x6a, 0x6a, 0x6a, 0x6f, 0x77, 0x6f, 0x66, 0x68, 0x78, 0x67, 0x64, 0x73, 0x75, 0x69, 0x6d, 0x69,
+ 0x62, 0x6b, 0x77, 0x63, 0x69, 0x6f, 0x61, 0x72, 0x61, 0x6f, 0x61, 0x77, 0x6a, 0x63, 0x69, 0x70,
+ 0x62, 0x79, 0x61, 0x61, 0x66, 0x71, 0x75, 0x72, 0x75, 0x61, 0x69, 0x6c, 0x78, 0x63, 0x78, 0x6c,
+ 0x74, 0x78, 0x6f, 0x78, 0x6a, 0x76, 0x72, 0x61, 0x69, 0x68, 0x6c, 0x67, 0x65, 0x79, 0x75, 0x6d,
+ 0x76, 0x65, 0x62, 0x67, 0x6b, 0x74, 0x6a, 0x62, 0x74, 0x6a, 0x63, 0x66, 0x62, 0x6c, 0x75, 0x6a,
+ 0x78, 0x61, 0x6f, 0x79, 0x62, 0x64, 0x61, 0x64, 0x77, 0x69, 0x77, 0x77, 0x75, 0x78, 0x77, 0x69,
+ 0x72, 0x69, 0x67, 0x65, 0x73, 0x65, 0x71, 0x6d, 0x6c, 0x65, 0x73, 0x68, 0x6e, 0x68, 0x69, 0x6b,
+ 0x72, 0x74, 0x76, 0x78, 0x62, 0x6a, 0x78, 0x72, 0x77, 0x76, 0x78, 0x68, 0x74, 0x74, 0x62, 0x6a,
+ 0x6c, 0x73, 0x76, 0x73, 0x79, 0x71, 0x72, 0x77, 0x65, 0x6f, 0x6a, 0x6e, 0x63, 0x64, 0x73, 0x65,
+ 0x69, 0x74, 0x72, 0x76, 0x68, 0x79, 0x67, 0x67, 0x78, 0x77, 0x75, 0x78, 0x72, 0x72, 0x68, 0x64,
+ 0x76, 0x73, 0x64, 0x61, 0x64, 0x78, 0x6f, 0x67, 0x6c, 0x6e, 0x61, 0x6a, 0x6b, 0x79, 0x71, 0x6b,
+ 0x62, 0x74, 0x71, 0x6b, 0x76, 0x6e, 0x6e, 0x6e, 0x6e, 0x74, 0x6b, 0x76, 0x61, 0x6e, 0x67, 0x65,
+ 0x73, 0x72, 0x79, 0x66, 0x61, 0x65, 0x65, 0x74, 0x6e, 0x61, 0x66, 0x74, 0x70, 0x69, 0x65, 0x67,
+ 0x67, 0x76, 0x62, 0x61, 0x6c, 0x66, 0x67, 0x76, 0x65, 0x76, 0x6a, 0x62, 0x64, 0x64, 0x6b, 0x6d,
+ 0x70, 0x70, 0x63, 0x74, 0x63, 0x67, 0x78, 0x73, 0x72, 0x6d, 0x63, 0x78, 0x6d, 0x70, 0x6e, 0x75,
+ 0x76, 0x74, 0x79, 0x6b, 0x61, 0x69, 0x6d, 0x73, 0x73, 0x69, 0x64, 0x66, 0x6e, 0x76, 0x67, 0x67,
+ 0x62, 0x77, 0x74, 0x68, 0x74, 0x68, 0x65, 0x64, 0x75, 0x68, 0x70, 0x69, 0x73, 0x6f, 0x67, 0x6b,
+ 0x74, 0x79, 0x68, 0x6c, 0x77, 0x73, 0x68, 0x61, 0x64, 0x68, 0x76, 0x61, 0x62, 0x74, 0x71, 0x6f,
+ 0x79, 0x6b, 0x6d, 0x61, 0x63, 0x65, 0x64, 0x74, 0x67, 0x75, 0x73, 0x6d, 0x65, 0x6a, 0x76, 0x69,
+ 0x75, 0x63, 0x72, 0x6c, 0x69, 0x70, 0x73, 0x70, 0x62, 0x77, 0x61, 0x76, 0x65, 0x69, 0x62, 0x70,
+ 0x6f, 0x6d, 0x70, 0x77, 0x78, 0x64, 0x78, 0x62, 0x77, 0x6e, 0x65, 0x71, 0x63, 0x6d, 0x79, 0x74,
+ 0x72, 0x78, 0x6e, 0x6b, 0x74, 0x62, 0x6f, 0x68, 0x74, 0x71, 0x66, 0x6e, 0x6d, 0x73, 0x76, 0x76,
+ 0x6f, 0x76, 0x73, 0x66, 0x66, 0x62, 0x62, 0x68, 0x66, 0x6e, 0x72, 0x72, 0x73, 0x6a, 0x73, 0x72,
+ 0x69, 0x63, 0x73, 0x79, 0x69, 0x6b, 0x66, 0x6e, 0x6c, 0x71, 0x66, 0x66, 0x74, 0x78, 0x62, 0x6e,
+ 0x75, 0x61, 0x74, 0x62, 0x68, 0x6f, 0x76, 0x6c, 0x75, 0x6c, 0x6a, 0x69, 0x67, 0x77, 0x61, 0x6b,
+ 0x76, 0x76, 0x6f, 0x66, 0x62, 0x6f, 0x66, 0x62, 0x67, 0x62, 0x75, 0x6e, 0x72, 0x6d, 0x71, 0x6d,
+ 0x6f, 0x73, 0x69, 0x6c, 0x70, 0x69, 0x69, 0x6a, 0x6d, 0x6e, 0x68, 0x70, 0x63, 0x63, 0x69, 0x68,
+ 0x68, 0x65, 0x73, 0x6a, 0x67, 0x65, 0x74, 0x79, 0x77, 0x67, 0x6d, 0x76, 0x75, 0x69, 0x71, 0x68,
+ 0x62, 0x6c, 0x72, 0x66, 0x76, 0x65, 0x76, 0x71, 0x78, 0x74, 0x68, 0x62, 0x6c, 0x68, 0x68, 0x66,
+ 0x64, 0x62, 0x6d, 0x6f, 0x77, 0x68, 0x69, 0x78, 0x65, 0x71, 0x68, 0x79, 0x6d, 0x67, 0x77, 0x6b,
+ 0x64, 0x6a, 0x79, 0x6b, 0x68, 0x71, 0x65, 0x68, 0x65, 0x6d, 0x74, 0x63, 0x72, 0x67, 0x66, 0x76,
+ 0x6c, 0x61, 0x78, 0x74, 0x6c, 0x67, 0x62, 0x73, 0x75, 0x73, 0x70, 0x66, 0x69, 0x64, 0x61, 0x72,
+ 0x6b, 0x6e, 0x66, 0x73, 0x6d, 0x71, 0x76, 0x75, 0x6a, 0x61, 0x6a, 0x70, 0x78, 0x61, 0x6c, 0x63,
+ 0x75, 0x6d, 0x79, 0x65, 0x66, 0x61, 0x79, 0x68, 0x74, 0x72, 0x6b, 0x77, 0x74, 0x63, 0x77, 0x67,
+ 0x61, 0x73, 0x6b, 0x79, 0x67, 0x63, 0x73, 0x6d, 0x67, 0x79, 0x65, 0x73, 0x64, 0x72, 0x71, 0x65,
+ 0x68, 0x66, 0x6b, 0x64, 0x73, 0x76, 0x63, 0x70, 0x78, 0x70, 0x76, 0x78, 0x6d, 0x66, 0x79, 0x63,
+ 0x6a, 0x6a, 0x6c, 0x75, 0x77, 0x64, 0x62, 0x67, 0x77, 0x64, 0x74, 0x76, 0x69, 0x6d, 0x72, 0x64,
+ 0x73, 0x75, 0x71, 0x6e, 0x74, 0x66, 0x65, 0x6e, 0x76, 0x6b, 0x6c, 0x70, 0x70, 0x6e, 0x68, 0x78,
+ 0x75, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x76, 0x63, 0x72, 0x70, 0x71, 0x67, 0x67, 0x70, 0x64, 0x66,
+ 0x67, 0x68, 0x79, 0x70, 0x63, 0x67, 0x6f, 0x68, 0x70, 0x6f, 0x68, 0x6f, 0x6b, 0x71, 0x79, 0x62,
+ 0x76, 0x6a, 0x75, 0x6e, 0x77, 0x65, 0x70, 0x6f, 0x72, 0x6f, 0x61, 0x66, 0x65, 0x6b, 0x73, 0x63,
+ 0x61, 0x62, 0x66, 0x65, 0x67, 0x77, 0x77, 0x79, 0x72, 0x72, 0x6b, 0x6e, 0x6d, 0x75, 0x6b, 0x65,
+ 0x68, 0x6e, 0x6a, 0x6e, 0x65, 0x65, 0x61, 0x78, 0x66, 0x68, 0x64, 0x62, 0x79, 0x66, 0x63, 0x72,
+ 0x64, 0x74, 0x71, 0x6a, 0x72, 0x78, 0x76, 0x64, 0x6c, 0x66, 0x6d, 0x75, 0x6b, 0x64, 0x6d, 0x78,
+ 0x68, 0x74, 0x63, 0x69, 0x6c, 0x6d, 0x65, 0x63, 0x63, 0x69, 0x70, 0x76, 0x6d, 0x6e, 0x70, 0x67,
+ 0x6d, 0x64, 0x6d, 0x6f, 0x69, 0x6d, 0x76, 0x75, 0x65, 0x6b, 0x6f, 0x73, 0x78, 0x70, 0x63, 0x6c,
+ 0x73, 0x6e, 0x77, 0x6f, 0x6d, 0x79, 0x70, 0x77, 0x63, 0x77, 0x69, 0x65, 0x71, 0x6d, 0x74, 0x6d,
+ 0x78, 0x78, 0x61, 0x70, 0x65, 0x65, 0x64, 0x65, 0x75, 0x71, 0x67, 0x63, 0x64, 0x74, 0x6c, 0x68,
+ 0x78, 0x65, 0x6d, 0x6f, 0x68, 0x72, 0x65, 0x72, 0x68, 0x6b, 0x65, 0x74, 0x68, 0x78, 0x66, 0x64,
+ 0x69, 0x77, 0x79, 0x72, 0x77, 0x73, 0x71, 0x78, 0x71, 0x76, 0x67, 0x74, 0x79, 0x74, 0x6b, 0x77,
+ 0x63, 0x6d, 0x75, 0x76, 0x6f, 0x67, 0x62, 0x76, 0x67, 0x72, 0x72, 0x72, 0x61, 0x6d, 0x73, 0x74,
+ 0x78, 0x65, 0x64, 0x64, 0x67, 0x77, 0x67, 0x6f, 0x78, 0x74, 0x76, 0x6b, 0x75, 0x69, 0x75, 0x68,
+ 0x62, 0x72, 0x67, 0x73, 0x6f, 0x75, 0x73, 0x79, 0x6a, 0x6b, 0x70, 0x79, 0x76, 0x64, 0x6b, 0x71,
+ 0x64, 0x79, 0x68, 0x76, 0x6a, 0x71, 0x63, 0x65, 0x70, 0x78, 0x61, 0x74, 0x72, 0x65, 0x6f, 0x68,
+ 0x76, 0x75, 0x6a, 0x75, 0x6a, 0x62, 0x65, 0x61, 0x62, 0x6b, 0x74, 0x64, 0x70, 0x6d, 0x6e, 0x74,
+ 0x74, 0x72, 0x6b, 0x72, 0x71, 0x66, 0x72, 0x72, 0x75, 0x6b, 0x6b, 0x6a, 0x63, 0x73, 0x6c, 0x76,
+ 0x77, 0x71, 0x6e, 0x70, 0x65, 0x71, 0x61, 0x72, 0x68, 0x79, 0x79, 0x74, 0x78, 0x62, 0x6a, 0x63,
+ 0x72, 0x78, 0x6d, 0x61, 0x72, 0x73, 0x69, 0x61, 0x61, 0x78, 0x69, 0x63, 0x6b, 0x64, 0x79, 0x75,
+ 0x66, 0x72, 0x63, 0x67, 0x77, 0x6f, 0x77, 0x65, 0x75, 0x6f, 0x6a, 0x72, 0x61, 0x6a, 0x6c, 0x66,
+ 0x72, 0x6e, 0x70, 0x69, 0x68, 0x6a, 0x62, 0x6c, 0x6c, 0x70, 0x71, 0x6e, 0x75, 0x69, 0x76, 0x76,
+ 0x66, 0x6e, 0x77, 0x76, 0x66, 0x69, 0x78, 0x74, 0x68, 0x78, 0x64, 0x79, 0x66, 0x75, 0x74, 0x68,
+ 0x6f, 0x67, 0x79, 0x78, 0x73, 0x6d, 0x78, 0x79, 0x66, 0x63, 0x74, 0x75, 0x6f, 0x62, 0x62, 0x62,
+ 0x68, 0x78, 0x6c, 0x64, 0x76, 0x64, 0x72, 0x6e, 0x65, 0x71, 0x66, 0x69, 0x77, 0x76, 0x62, 0x66,
+ 0x71, 0x63, 0x74, 0x61, 0x78, 0x62, 0x74, 0x72, 0x6b, 0x67, 0x69, 0x78, 0x63, 0x6a, 0x6e, 0x76,
+ 0x62, 0x61, 0x6f, 0x68, 0x6a, 0x67, 0x72, 0x72, 0x79, 0x74, 0x78, 0x67, 0x65, 0x72, 0x6a, 0x68,
+ 0x6d, 0x6f, 0x61, 0x71, 0x65, 0x72, 0x64, 0x61, 0x79, 0x73, 0x6a, 0x64, 0x76, 0x77, 0x6a, 0x6b,
+ 0x71, 0x6c, 0x75, 0x75, 0x6c, 0x78, 0x67, 0x77, 0x76, 0x78, 0x69, 0x74, 0x62, 0x74, 0x75, 0x71,
+ 0x77, 0x77, 0x70, 0x69, 0x6c, 0x61, 0x71, 0x66, 0x6c, 0x78, 0x6a, 0x67, 0x77, 0x68, 0x65, 0x63,
+ 0x77, 0x72, 0x79, 0x6c, 0x6f, 0x64, 0x78, 0x77, 0x68, 0x78, 0x63, 0x68, 0x66, 0x70, 0x78, 0x6f,
+ 0x70, 0x78, 0x66, 0x79, 0x76, 0x63, 0x6a, 0x65, 0x79, 0x66, 0x78, 0x63, 0x6e, 0x6b, 0x75, 0x61,
+ 0x70, 0x6c, 0x62, 0x68, 0x79, 0x63, 0x6b, 0x6d, 0x62, 0x77, 0x68, 0x76, 0x62, 0x6f, 0x68, 0x62,
+ 0x78, 0x78, 0x72, 0x72, 0x6c, 0x74, 0x79, 0x74, 0x6b, 0x68, 0x6e, 0x74, 0x74, 0x70, 0x73, 0x67,
+ 0x73, 0x71, 0x6b, 0x6f, 0x69, 0x6a, 0x71, 0x78, 0x6a, 0x77, 0x70, 0x76, 0x72, 0x64, 0x6a, 0x68,
+ 0x6e, 0x6a, 0x69, 0x79, 0x73, 0x78, 0x71, 0x77, 0x71, 0x68, 0x6d, 0x6b, 0x68, 0x79, 0x63, 0x62,
+ 0x63, 0x6b, 0x67, 0x6f, 0x69, 0x68, 0x6e, 0x6d, 0x67, 0x65, 0x6a, 0x74, 0x67, 0x66, 0x73, 0x62,
+ 0x67, 0x78, 0x6d, 0x69, 0x62, 0x73, 0x67, 0x76, 0x71, 0x73, 0x79, 0x6d, 0x6a, 0x77, 0x65, 0x67,
+ 0x70, 0x6e, 0x64, 0x76, 0x66, 0x6b, 0x70, 0x73, 0x6e, 0x61, 0x69, 0x71, 0x71, 0x62, 0x75, 0x70,
+ 0x72, 0x63, 0x69, 0x68, 0x6e, 0x6d, 0x65, 0x6e, 0x6a, 0x73, 0x62, 0x70, 0x6a, 0x69, 0x67, 0x69,
+ 0x6f, 0x76, 0x6f, 0x70, 0x74, 0x6f, 0x66, 0x6f, 0x64, 0x64, 0x76, 0x66, 0x6b, 0x62, 0x73, 0x6c,
+ 0x6a, 0x6e, 0x73, 0x6b, 0x75, 0x6f, 0x66, 0x6e, 0x78, 0x6b, 0x64, 0x6c, 0x6d, 0x73, 0x6e, 0x69,
+ 0x6a, 0x6f, 0x78, 0x62, 0x6b, 0x78, 0x74, 0x65, 0x67, 0x72, 0x66, 0x66, 0x69, 0x69, 0x63, 0x73,
+ 0x75, 0x79, 0x75, 0x73, 0x77, 0x72, 0x77, 0x77, 0x74, 0x74, 0x68, 0x78, 0x76, 0x71, 0x79, 0x78,
+ 0x61, 0x6c, 0x6b, 0x6e, 0x61, 0x76, 0x6b, 0x6d, 0x76, 0x63, 0x70, 0x79, 0x6e, 0x78, 0x72, 0x61,
+ 0x75, 0x6c, 0x64, 0x69, 0x6f, 0x78, 0x61, 0x71, 0x68, 0x6c, 0x61, 0x77, 0x69, 0x69, 0x74, 0x75,
+ 0x6f, 0x66, 0x75, 0x6e, 0x62, 0x6c, 0x6d, 0x67, 0x79, 0x6f, 0x69, 0x71, 0x76, 0x71, 0x78, 0x67,
+ 0x75, 0x66, 0x6d, 0x69, 0x67, 0x75, 0x6f, 0x6b, 0x63, 0x61, 0x6f, 0x63, 0x70, 0x63, 0x76, 0x75,
+ 0x63, 0x74, 0x70, 0x78, 0x64, 0x77, 0x6e, 0x69, 0x78, 0x6c, 0x63, 0x70, 0x66, 0x6d, 0x68, 0x64,
+ 0x6a, 0x75, 0x64, 0x71, 0x6b, 0x64, 0x67, 0x78, 0x73, 0x63, 0x6e, 0x75, 0x74, 0x77, 0x76, 0x6a,
+ 0x62, 0x74, 0x73, 0x76, 0x67, 0x70, 0x6f, 0x78, 0x6f, 0x63, 0x75, 0x64, 0x61, 0x79, 0x6b, 0x70,
+ 0x73, 0x75, 0x65, 0x64, 0x74, 0x70, 0x61, 0x6f, 0x77, 0x6d, 0x74, 0x6e, 0x78, 0x65, 0x72, 0x75,
+ 0x63, 0x71, 0x69, 0x66, 0x79, 0x65, 0x74, 0x77, 0x6f, 0x6d, 0x66, 0x6a, 0x77, 0x6f, 0x78, 0x76,
+ 0x66, 0x67, 0x65, 0x64, 0x66, 0x61, 0x62, 0x61, 0x71, 0x79, 0x64, 0x6c, 0x79, 0x6b, 0x64, 0x75,
+ 0x79, 0x6c, 0x67, 0x6d, 0x76, 0x67, 0x77, 0x71, 0x69, 0x65, 0x66, 0x71, 0x6b, 0x70, 0x62, 0x64,
+ 0x73, 0x6e, 0x6d, 0x67, 0x67, 0x6f, 0x75, 0x70, 0x65, 0x79, 0x63, 0x62, 0x61, 0x6b, 0x62, 0x6a,
+ 0x66, 0x68, 0x67, 0x75, 0x78, 0x68, 0x6b, 0x77, 0x66, 0x79, 0x67, 0x6c, 0x6f, 0x6a, 0x6a, 0x73,
+ 0x6f, 0x73, 0x63, 0x78, 0x6a, 0x67, 0x74, 0x6d, 0x6f, 0x68, 0x6b, 0x62, 0x70, 0x66, 0x6a, 0x6e,
+ 0x6e, 0x67, 0x6c, 0x65, 0x74, 0x6f, 0x6c, 0x67, 0x68, 0x6d, 0x67, 0x79, 0x61, 0x6a, 0x6e, 0x70,
+ 0x64, 0x6f, 0x68, 0x6b, 0x6a, 0x64, 0x64, 0x6f, 0x6a, 0x64, 0x66, 0x67, 0x73, 0x6a, 0x76, 0x78,
+ 0x6c, 0x67, 0x66, 0x75, 0x6c, 0x79, 0x69, 0x65, 0x71, 0x6c, 0x6b, 0x63, 0x61, 0x6d, 0x61, 0x78,
+ 0x6a, 0x74, 0x6a, 0x78, 0x65, 0x75, 0x62, 0x6b, 0x6b, 0x75, 0x77, 0x78, 0x73, 0x77, 0x64, 0x61,
+ 0x61, 0x6b, 0x71, 0x6f, 0x6f, 0x6c, 0x67, 0x6e, 0x6d, 0x77, 0x64, 0x6d, 0x64, 0x6d, 0x64, 0x76,
+ 0x77, 0x6b, 0x69, 0x76, 0x72, 0x70, 0x77, 0x62, 0x75, 0x69, 0x73, 0x68, 0x65, 0x76, 0x70, 0x76,
+ 0x76, 0x6c, 0x6a, 0x69, 0x77, 0x73, 0x69, 0x66, 0x67, 0x6a, 0x74, 0x6a, 0x70, 0x6f, 0x6c, 0x77,
+ 0x70, 0x6a, 0x76, 0x6a, 0x61, 0x68, 0x78, 0x73, 0x70, 0x72, 0x78, 0x62, 0x76, 0x6b, 0x66, 0x6b,
+ 0x64, 0x71, 0x6d, 0x62, 0x6d, 0x70, 0x79, 0x6a, 0x66, 0x6c, 0x79, 0x76, 0x66, 0x75, 0x69, 0x71,
+ 0x66, 0x79, 0x78, 0x77, 0x75, 0x75, 0x6b, 0x77, 0x6d, 0x67, 0x67, 0x6b, 0x75, 0x75, 0x64, 0x75,
+ 0x62, 0x73, 0x6c, 0x6a, 0x6c, 0x64, 0x69, 0x74, 0x6e, 0x65, 0x63, 0x79, 0x6e, 0x6d, 0x6c, 0x77,
+ 0x6a, 0x69, 0x6d, 0x78, 0x62, 0x74, 0x69, 0x6a, 0x66, 0x75, 0x6e, 0x6f, 0x6e, 0x78, 0x73, 0x6d,
+ 0x74, 0x74, 0x62, 0x6c, 0x68, 0x6b, 0x70, 0x61, 0x6c, 0x6c, 0x63, 0x64, 0x67, 0x65, 0x68, 0x73,
+ 0x74, 0x6d, 0x64, 0x78, 0x68, 0x71, 0x61, 0x66, 0x77, 0x66, 0x6a, 0x66, 0x6f, 0x61, 0x65, 0x6f,
+ 0x6f, 0x74, 0x6a, 0x69, 0x6a, 0x75, 0x68, 0x6c, 0x73, 0x6b, 0x72, 0x75, 0x69, 0x63, 0x63, 0x62,
+ 0x6e, 0x64, 0x76, 0x75, 0x79, 0x71, 0x64, 0x61, 0x6a, 0x65, 0x65, 0x61, 0x61, 0x6e, 0x66, 0x65,
+ 0x74, 0x77, 0x61, 0x62, 0x68, 0x68, 0x67, 0x71, 0x69, 0x68, 0x6b, 0x73, 0x6b, 0x76, 0x68, 0x73,
+ 0x62, 0x63, 0x65, 0x65, 0x73, 0x72, 0x6a, 0x71, 0x6e, 0x61, 0x6a, 0x63, 0x61, 0x62, 0x73, 0x6e,
+ 0x6e, 0x70, 0x67, 0x6f, 0x63, 0x70, 0x64, 0x66, 0x62, 0x61, 0x64, 0x6a, 0x78, 0x70, 0x61, 0x6f,
+ 0x69, 0x79, 0x66, 0x77, 0x74, 0x69, 0x62, 0x6a, 0x73, 0x75, 0x6d, 0x76, 0x74, 0x6d, 0x61, 0x77,
+ 0x67, 0x67, 0x72, 0x6f, 0x79, 0x75, 0x61, 0x72, 0x65, 0x6c, 0x67, 0x69, 0x63, 0x77, 0x71, 0x61,
+ 0x62, 0x63, 0x61, 0x71, 0x6d, 0x6d, 0x64, 0x6a, 0x6a, 0x70, 0x63, 0x71, 0x72, 0x6b, 0x6a, 0x66,
+ 0x62, 0x76, 0x6c, 0x61, 0x72, 0x6f, 0x75, 0x72, 0x75, 0x65, 0x6b, 0x75, 0x73, 0x64, 0x76, 0x6b,
+ 0x6c, 0x6d, 0x73, 0x74, 0x6a, 0x70, 0x61, 0x64, 0x74, 0x71, 0x6c, 0x63, 0x6f, 0x6c, 0x68, 0x75,
+ 0x69, 0x70, 0x73, 0x73, 0x76, 0x78, 0x6b, 0x67, 0x73, 0x74, 0x6f, 0x70, 0x72, 0x61, 0x75, 0x6c,
+ 0x66, 0x66, 0x69, 0x6f, 0x75, 0x6b, 0x6d, 0x64, 0x74, 0x79, 0x6b, 0x66, 0x6b, 0x65, 0x65, 0x6c,
+ 0x6b, 0x61, 0x6c, 0x73, 0x63, 0x66, 0x67, 0x76, 0x6d, 0x74, 0x61, 0x65, 0x6e, 0x62, 0x61, 0x72,
+ 0x63, 0x6d, 0x6c, 0x6a, 0x75, 0x67, 0x6d, 0x62, 0x6e, 0x70, 0x76, 0x6b, 0x64, 0x77, 0x6b, 0x68,
+ 0x75, 0x74, 0x77, 0x61, 0x73, 0x62, 0x6c, 0x79, 0x79, 0x77, 0x6f, 0x66, 0x63, 0x73, 0x67, 0x64,
+ 0x63, 0x62, 0x66, 0x71, 0x73, 0x79, 0x66, 0x73, 0x69, 0x72, 0x71, 0x70, 0x72, 0x67, 0x68, 0x72,
+ 0x6d, 0x6d, 0x79, 0x68, 0x77, 0x6f, 0x68, 0x62, 0x64, 0x70, 0x64, 0x70, 0x6e, 0x72, 0x69, 0x66,
+ 0x6b, 0x72, 0x64, 0x65, 0x63, 0x77, 0x61, 0x61, 0x6b, 0x73, 0x73, 0x77, 0x78, 0x77, 0x6c, 0x64,
+ 0x61, 0x69, 0x62, 0x72, 0x72, 0x6d, 0x6e, 0x76, 0x70, 0x75, 0x72, 0x63, 0x77, 0x69, 0x65, 0x62,
+ 0x73, 0x73, 0x6b, 0x70, 0x70, 0x64, 0x67, 0x71, 0x72, 0x6a, 0x6f, 0x79, 0x75, 0x75, 0x64, 0x75,
+ 0x6f, 0x73, 0x78, 0x67, 0x79, 0x79, 0x78, 0x6e, 0x76, 0x63, 0x6c, 0x73, 0x6a, 0x6c, 0x65, 0x6e,
+ 0x6c, 0x70, 0x69, 0x76, 0x63, 0x6a, 0x6f, 0x6a, 0x6a, 0x6f, 0x6b, 0x66, 0x75, 0x73, 0x66, 0x71,
+ 0x61, 0x75, 0x78, 0x68, 0x6b, 0x67, 0x71, 0x72, 0x6b, 0x65, 0x67, 0x6d, 0x68, 0x74, 0x62, 0x78,
+ 0x65, 0x6f, 0x69, 0x74, 0x71, 0x79, 0x63, 0x67, 0x79, 0x77, 0x6b, 0x69, 0x61, 0x6e, 0x6b, 0x69,
+ 0x70, 0x78, 0x74, 0x75, 0x72, 0x66, 0x6f, 0x64, 0x77, 0x62, 0x79, 0x73, 0x79, 0x73, 0x78, 0x65,
+ 0x62, 0x6b, 0x6f, 0x6b, 0x76, 0x62, 0x6e, 0x68, 0x6a, 0x72, 0x61, 0x61, 0x73, 0x6f, 0x78, 0x61,
+ 0x68, 0x76, 0x63, 0x6c, 0x77, 0x6c, 0x63, 0x6e, 0x6d, 0x6c, 0x71, 0x6f, 0x70, 0x72, 0x63, 0x75,
+ 0x68, 0x61, 0x67, 0x69, 0x6f, 0x6a, 0x6e, 0x61, 0x71, 0x72, 0x6b, 0x66, 0x73, 0x6c, 0x64, 0x79,
+ 0x79, 0x75, 0x79, 0x6d, 0x6e, 0x6c, 0x67, 0x65, 0x6a, 0x76, 0x66, 0x76, 0x77, 0x6c, 0x6b, 0x77,
+ 0x75, 0x64, 0x72, 0x73, 0x77, 0x69, 0x64, 0x74, 0x72, 0x69, 0x66, 0x6b, 0x6f, 0x6d, 0x76, 0x74,
+ 0x64, 0x64, 0x73, 0x74, 0x69, 0x6f, 0x71, 0x79, 0x65, 0x64, 0x71, 0x69, 0x6d, 0x62, 0x6d, 0x70,
+ 0x6c, 0x76, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x77, 0x6a, 0x67, 0x72, 0x78, 0x74, 0x72, 0x69, 0x62,
+ 0x6f, 0x71, 0x71, 0x6a, 0x69, 0x70, 0x73, 0x79, 0x6a, 0x70, 0x70, 0x6d, 0x6f, 0x6f, 0x6d, 0x79,
+ 0x6f, 0x6e, 0x6a, 0x6e, 0x75, 0x67, 0x76, 0x78, 0x65, 0x72, 0x77, 0x64, 0x69, 0x6f, 0x63, 0x69,
+ 0x73, 0x68, 0x72, 0x79, 0x6c, 0x6a, 0x61, 0x77, 0x6b, 0x72, 0x78, 0x63, 0x72, 0x63, 0x79, 0x69,
+ 0x6a, 0x72, 0x6e, 0x79, 0x62, 0x67, 0x6f, 0x72, 0x63, 0x6b, 0x6d, 0x61, 0x76, 0x6e, 0x73, 0x64,
+ 0x62, 0x6a, 0x78, 0x74, 0x72, 0x74, 0x64, 0x79, 0x6b, 0x71, 0x72, 0x68, 0x67, 0x63, 0x63, 0x76,
+ 0x6f, 0x77, 0x76, 0x61, 0x64, 0x65, 0x70, 0x71, 0x72, 0x61, 0x63, 0x63, 0x66, 0x75, 0x73, 0x62,
+ 0x70, 0x70, 0x67, 0x68, 0x70, 0x63, 0x6c, 0x64, 0x6d, 0x76, 0x6d, 0x67, 0x73, 0x72, 0x6a, 0x6a,
+ 0x78, 0x6b, 0x64, 0x78, 0x71, 0x71, 0x66, 0x68, 0x79, 0x6b, 0x6b, 0x69, 0x67, 0x70, 0x6e, 0x66,
+ 0x73, 0x73, 0x78, 0x72, 0x63, 0x76, 0x79, 0x65, 0x63, 0x67, 0x79, 0x64, 0x69, 0x71, 0x75, 0x68,
+ 0x79, 0x6c, 0x6b, 0x61, 0x78, 0x6a, 0x6c, 0x76, 0x63, 0x61, 0x70, 0x79, 0x71, 0x6c, 0x77, 0x6c,
+ 0x6f, 0x66, 0x63, 0x6a, 0x69, 0x64, 0x6f, 0x6f, 0x75, 0x64, 0x76, 0x70, 0x65, 0x63, 0x72, 0x70,
+ 0x62, 0x71, 0x6c, 0x73, 0x74, 0x74, 0x6b, 0x6f, 0x6e, 0x79, 0x72, 0x64, 0x66, 0x6d, 0x79, 0x73,
+ 0x6d, 0x64, 0x67, 0x6b, 0x69, 0x6d, 0x76, 0x65, 0x63, 0x73, 0x6c, 0x6a, 0x66, 0x64, 0x64, 0x70,
+ 0x72, 0x67, 0x69, 0x6c, 0x63, 0x63, 0x71, 0x63, 0x69, 0x73, 0x78, 0x67, 0x77, 0x6a, 0x6d, 0x74,
+ 0x63, 0x63, 0x68, 0x78, 0x61, 0x73, 0x6b, 0x6b, 0x73, 0x69, 0x73, 0x72, 0x73, 0x71, 0x67, 0x68,
+ 0x65, 0x76, 0x77, 0x65, 0x6e, 0x68, 0x72, 0x6a, 0x63, 0x6d, 0x67, 0x6e, 0x65, 0x73, 0x78, 0x73,
+ 0x6a, 0x6d, 0x74, 0x61, 0x61, 0x73, 0x74, 0x62, 0x6a, 0x6a, 0x62, 0x63, 0x65, 0x63, 0x70, 0x69,
+ 0x66, 0x71, 0x70, 0x68, 0x6a, 0x66, 0x67, 0x78, 0x61, 0x63, 0x6c, 0x75, 0x79, 0x6a, 0x63, 0x6b,
+ 0x72, 0x78, 0x65, 0x65, 0x77, 0x77, 0x73, 0x71, 0x68, 0x6f, 0x6b, 0x64, 0x6e, 0x66, 0x64, 0x6e,
+ 0x6b, 0x78, 0x67, 0x73, 0x6c, 0x75, 0x64, 0x6d, 0x66, 0x6b, 0x77, 0x73, 0x74, 0x70, 0x68, 0x66,
+ 0x6c, 0x70, 0x6a, 0x62, 0x6b, 0x78, 0x6e, 0x65, 0x61, 0x6a, 0x68, 0x63, 0x6a, 0x64, 0x75, 0x69,
+ 0x71, 0x77, 0x6e, 0x67, 0x72, 0x70, 0x70, 0x76, 0x70, 0x6e, 0x6b, 0x74, 0x75, 0x76, 0x6b, 0x62,
+ 0x79, 0x63, 0x78, 0x6c, 0x63, 0x6f, 0x69, 0x68, 0x76, 0x6f, 0x62, 0x6a, 0x61, 0x66, 0x6b, 0x72,
+ 0x75, 0x76, 0x67, 0x74, 0x78, 0x73, 0x69, 0x63, 0x63, 0x72, 0x75, 0x61, 0x64, 0x75, 0x69, 0x70,
+ 0x63, 0x68, 0x72, 0x67, 0x69, 0x6f, 0x6d, 0x62, 0x61, 0x68, 0x62, 0x76, 0x6e, 0x6f, 0x62, 0x76,
+ 0x70, 0x6a, 0x67, 0x6b, 0x74, 0x75, 0x75, 0x70, 0x70, 0x6c, 0x76, 0x6d, 0x71, 0x6b, 0x6f, 0x72,
+ 0x70, 0x67, 0x63, 0x79, 0x72, 0x64, 0x67, 0x6f, 0x6d, 0x77, 0x64, 0x61, 0x6f, 0x68, 0x63, 0x61,
+ 0x64, 0x61, 0x67, 0x62, 0x6e, 0x65, 0x6a, 0x6e, 0x77, 0x66, 0x6e, 0x75, 0x79, 0x64, 0x75, 0x79,
+ 0x79, 0x61, 0x63, 0x6f, 0x63, 0x79, 0x77, 0x64, 0x73, 0x74, 0x6a, 0x71, 0x63, 0x61, 0x6b, 0x76,
+ 0x63, 0x6e, 0x73, 0x72, 0x75, 0x62, 0x75, 0x75, 0x67, 0x68, 0x71, 0x6f, 0x6e, 0x61, 0x65, 0x75,
+ 0x6e, 0x6a, 0x76, 0x71, 0x68, 0x74, 0x79, 0x68, 0x65, 0x70, 0x65, 0x6e, 0x6c, 0x62, 0x78, 0x6e,
+ 0x66, 0x64, 0x63, 0x77, 0x68, 0x75, 0x78, 0x6e, 0x71, 0x6d, 0x79, 0x71, 0x68, 0x68, 0x75, 0x73,
+ 0x6c, 0x67, 0x73, 0x75, 0x6d, 0x74, 0x72, 0x6d, 0x77, 0x65, 0x67, 0x67, 0x6f, 0x67, 0x66, 0x75,
+ 0x6d, 0x63, 0x75, 0x6d, 0x6d, 0x74, 0x72, 0x6f, 0x64, 0x74, 0x6f, 0x76, 0x73, 0x75, 0x67, 0x65,
+ 0x73, 0x78, 0x77, 0x67, 0x66, 0x77, 0x66, 0x69, 0x73, 0x75, 0x61, 0x65, 0x6a, 0x61, 0x6b, 0x72,
+ 0x6c, 0x6a, 0x71, 0x71, 0x73, 0x6e, 0x6f, 0x70, 0x65, 0x6e, 0x72, 0x6a, 0x74, 0x6f, 0x72, 0x76,
+ 0x61, 0x69, 0x74, 0x67, 0x72, 0x6f, 0x6d, 0x74, 0x75, 0x74, 0x72, 0x63, 0x65, 0x78, 0x71, 0x6b,
+ 0x79, 0x73, 0x63, 0x6c, 0x6f, 0x75, 0x73, 0x62, 0x70, 0x70, 0x73, 0x65, 0x79, 0x6d, 0x6f, 0x76,
+ 0x64, 0x76, 0x67, 0x69, 0x64, 0x6a, 0x72, 0x69, 0x75, 0x69, 0x79, 0x6e, 0x6d, 0x78, 0x69, 0x62,
+ 0x71, 0x6e, 0x6b, 0x66, 0x75, 0x73, 0x6b, 0x74, 0x6e, 0x61, 0x6c, 0x69, 0x76, 0x63, 0x66, 0x6d,
+ 0x69, 0x61, 0x62, 0x73, 0x74, 0x6a, 0x79, 0x64, 0x6f, 0x67, 0x77, 0x68, 0x6b, 0x63, 0x75, 0x63,
+ 0x74, 0x6d, 0x76, 0x68, 0x72, 0x6e, 0x69, 0x6d, 0x74, 0x6f, 0x79, 0x78, 0x62, 0x76, 0x62, 0x6f,
+ 0x70, 0x6c, 0x6f, 0x62, 0x65, 0x78, 0x63, 0x65, 0x72, 0x77, 0x64, 0x76, 0x65, 0x66, 0x74, 0x63,
+ 0x63, 0x6a, 0x6d, 0x6b, 0x6e, 0x64, 0x73, 0x62, 0x66, 0x6d, 0x62, 0x66, 0x6b, 0x76, 0x63, 0x68,
+ 0x6c, 0x65, 0x69, 0x72, 0x75, 0x62, 0x6e, 0x64, 0x6a, 0x6a, 0x6d, 0x75, 0x74, 0x79, 0x6d, 0x67,
+ 0x65, 0x6e, 0x6b, 0x67, 0x6a, 0x6e, 0x63, 0x63, 0x63, 0x6d, 0x6b, 0x64, 0x6f, 0x6e, 0x6a, 0x75,
+ 0x77, 0x71, 0x74, 0x65, 0x73, 0x71, 0x62, 0x61, 0x76, 0x67, 0x6d, 0x6b, 0x74, 0x78, 0x6c, 0x66,
+ 0x65, 0x74, 0x6f, 0x68, 0x61, 0x73, 0x66, 0x63, 0x79, 0x64, 0x6a, 0x79, 0x74, 0x67, 0x67, 0x6b,
+ 0x78, 0x70, 0x6f, 0x6c, 0x64, 0x68, 0x69, 0x76, 0x6b, 0x77, 0x67, 0x6d, 0x62, 0x72, 0x71, 0x76,
+ 0x69, 0x76, 0x6e, 0x76, 0x71, 0x6c, 0x74, 0x74, 0x71, 0x75, 0x6b, 0x6c, 0x70, 0x6e, 0x69, 0x78,
+ 0x71, 0x6d, 0x62, 0x6d, 0x69, 0x65, 0x6c, 0x77, 0x68, 0x68, 0x6d, 0x6d, 0x62, 0x70, 0x75, 0x74,
+ 0x77, 0x6f, 0x65, 0x69, 0x78, 0x62, 0x78, 0x74, 0x6b, 0x76, 0x72, 0x76, 0x65, 0x78, 0x77, 0x74,
+ 0x63, 0x75, 0x71, 0x66, 0x6e, 0x6c, 0x6d, 0x62, 0x76, 0x6b, 0x77, 0x70, 0x76, 0x79, 0x6b, 0x78,
+ 0x76, 0x6e, 0x6d, 0x66, 0x6d, 0x6b, 0x69, 0x6b, 0x64, 0x79, 0x77, 0x62, 0x65, 0x61, 0x67, 0x6c,
+ 0x66, 0x6f, 0x70, 0x73, 0x73, 0x66, 0x68, 0x71, 0x68, 0x70, 0x65, 0x65, 0x74, 0x69, 0x65, 0x6e,
+ 0x65, 0x68, 0x76, 0x79, 0x66, 0x76, 0x67, 0x66, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x6d, 0x69, 0x79,
+ 0x63, 0x6f, 0x64, 0x64, 0x79, 0x68, 0x71, 0x75, 0x73, 0x6d, 0x63, 0x67, 0x75, 0x64, 0x6b, 0x65,
+ 0x69, 0x76, 0x70, 0x65, 0x6a, 0x63, 0x70, 0x68, 0x61, 0x66, 0x73, 0x73, 0x68, 0x74, 0x71, 0x6c,
+ 0x63, 0x61, 0x62, 0x73, 0x75, 0x73, 0x78, 0x6d, 0x66, 0x74, 0x74, 0x73, 0x63, 0x74, 0x64, 0x75,
+ 0x6b, 0x6c, 0x6a, 0x72, 0x72, 0x61, 0x64, 0x74, 0x71, 0x70, 0x6b, 0x69, 0x70, 0x75, 0x61, 0x6e,
+ 0x71, 0x77, 0x73, 0x6f, 0x72, 0x77, 0x67, 0x67, 0x67, 0x61, 0x73, 0x73, 0x61, 0x6e, 0x63, 0x70,
+ 0x6c, 0x69, 0x68, 0x67, 0x62, 0x76, 0x71, 0x72, 0x72, 0x72, 0x72, 0x65, 0x65, 0x6d, 0x70, 0x6d,
+ 0x73, 0x73, 0x69, 0x68, 0x74, 0x76, 0x71, 0x66, 0x67, 0x67, 0x70, 0x66, 0x69, 0x78, 0x62, 0x78,
+ 0x72, 0x6d, 0x78, 0x76, 0x79, 0x6a, 0x6f, 0x79, 0x76, 0x65, 0x61, 0x61, 0x6f, 0x6c, 0x6c, 0x79,
+ 0x6e, 0x62, 0x63, 0x76, 0x69, 0x69, 0x77, 0x76, 0x6d, 0x66, 0x69, 0x79, 0x79, 0x6f, 0x75, 0x71,
+ 0x64, 0x75, 0x6b, 0x6c, 0x6d, 0x73, 0x6c, 0x71, 0x78, 0x6e, 0x6d, 0x74, 0x6e, 0x71, 0x6b, 0x66,
+ 0x6d, 0x67, 0x69, 0x6b, 0x77, 0x66, 0x69, 0x6d, 0x6d, 0x6d, 0x6a, 0x74, 0x77, 0x6f, 0x63, 0x76,
+ 0x6d, 0x67, 0x65, 0x65, 0x64, 0x76, 0x68, 0x67, 0x68, 0x66, 0x68, 0x6f, 0x61, 0x63, 0x78, 0x6d,
+ 0x76, 0x64, 0x74, 0x6e, 0x6d, 0x69, 0x66, 0x71, 0x62, 0x70, 0x71, 0x66, 0x77, 0x77, 0x63, 0x6b,
+ 0x76, 0x78, 0x72, 0x66, 0x70, 0x76, 0x78, 0x65, 0x72, 0x6f, 0x62, 0x62, 0x67, 0x65, 0x62, 0x76,
+ 0x66, 0x6e, 0x79, 0x69, 0x64, 0x69, 0x68, 0x67, 0x66, 0x70, 0x77, 0x6e, 0x76, 0x64, 0x75, 0x6c,
+ 0x71, 0x68, 0x6a, 0x71, 0x71, 0x70, 0x65, 0x68, 0x61, 0x71, 0x78, 0x75, 0x6c, 0x76, 0x68, 0x6d,
+ 0x64, 0x65, 0x65, 0x79, 0x6f, 0x78, 0x66, 0x77, 0x70, 0x66, 0x66, 0x6f, 0x74, 0x73, 0x71, 0x6e,
+ 0x65, 0x65, 0x75, 0x68, 0x6e, 0x64, 0x6e, 0x67, 0x72, 0x76, 0x71, 0x6b, 0x65, 0x71, 0x6d, 0x6f,
+ 0x63, 0x73, 0x63, 0x6e, 0x66, 0x73, 0x68, 0x6d, 0x6b, 0x72, 0x67, 0x6d, 0x6f, 0x6a, 0x77, 0x70,
+ 0x64, 0x77, 0x62, 0x79, 0x6e, 0x65, 0x6c, 0x62, 0x66, 0x77, 0x6e, 0x73, 0x77, 0x64, 0x74, 0x74,
+ 0x77, 0x64, 0x65, 0x66, 0x6e, 0x73, 0x78, 0x6d, 0x79, 0x76, 0x73, 0x71, 0x76, 0x61, 0x66, 0x6e,
+ 0x76, 0x77, 0x6f, 0x73, 0x6c, 0x6e, 0x6d, 0x78, 0x73, 0x71, 0x64, 0x66, 0x78, 0x65, 0x73, 0x63,
+ 0x69, 0x73, 0x69, 0x62, 0x64, 0x63, 0x74, 0x6f, 0x6e, 0x69, 0x79, 0x66, 0x75, 0x71, 0x70, 0x79,
+ 0x6c, 0x6d, 0x67, 0x72, 0x67, 0x65, 0x72, 0x75, 0x78, 0x68, 0x73, 0x6f, 0x76, 0x62, 0x62, 0x78,
+ 0x68, 0x78, 0x79, 0x72, 0x65, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x67, 0x79, 0x6d, 0x78, 0x73, 0x78,
+ 0x68, 0x67, 0x77, 0x71, 0x76, 0x78, 0x74, 0x61, 0x6c, 0x76, 0x78, 0x65, 0x78, 0x6a, 0x76, 0x64,
+ 0x6f, 0x6d, 0x71, 0x6f, 0x6a, 0x6f, 0x77, 0x79, 0x69, 0x6e, 0x66, 0x71, 0x6e, 0x62, 0x66, 0x6f,
+ 0x61, 0x68, 0x73, 0x72, 0x69, 0x68, 0x68, 0x73, 0x63, 0x67, 0x69, 0x74, 0x6c, 0x76, 0x79, 0x66,
+ 0x6f, 0x75, 0x6c, 0x69, 0x73, 0x72, 0x74, 0x6c, 0x6f, 0x62, 0x78, 0x68, 0x6b, 0x6d, 0x77, 0x63,
+ 0x6d, 0x67, 0x64, 0x77, 0x6f, 0x64, 0x72, 0x77, 0x6b, 0x6f, 0x6c, 0x6c, 0x6e, 0x6c, 0x63, 0x77,
+ 0x73, 0x77, 0x6c, 0x71, 0x73, 0x73, 0x6f, 0x61, 0x64, 0x65, 0x69, 0x78, 0x63, 0x66, 0x6f, 0x66,
+ 0x72, 0x77, 0x69, 0x64, 0x6c, 0x72, 0x6b, 0x6d, 0x72, 0x6c, 0x6d, 0x64, 0x71, 0x6b, 0x69, 0x61,
+ 0x75, 0x66, 0x65, 0x62, 0x6e, 0x6f, 0x68, 0x75, 0x6a, 0x6d, 0x71, 0x74, 0x78, 0x71, 0x75, 0x6a,
+ 0x75, 0x6f, 0x68, 0x6d, 0x68, 0x68, 0x78, 0x61, 0x75, 0x71, 0x75, 0x62, 0x79, 0x6c, 0x75, 0x73,
+ 0x72, 0x6b, 0x66, 0x62, 0x71, 0x71, 0x79, 0x69, 0x6f, 0x6d, 0x69, 0x6d, 0x79, 0x6a, 0x66, 0x69,
+ 0x6a, 0x66, 0x79, 0x61, 0x63, 0x65, 0x69, 0x67, 0x61, 0x73, 0x71, 0x65, 0x72, 0x73, 0x6b, 0x6b,
+ 0x70, 0x6f, 0x78, 0x69, 0x78, 0x6c, 0x78, 0x61, 0x66, 0x6b, 0x69, 0x69, 0x64, 0x6c, 0x74, 0x70,
+ 0x78, 0x75, 0x6f, 0x73, 0x79, 0x6f, 0x6a, 0x6e, 0x74, 0x70, 0x70, 0x66, 0x6c, 0x64, 0x79, 0x67,
+ 0x78, 0x6e, 0x6c, 0x78, 0x71, 0x6c, 0x74, 0x62, 0x6e, 0x77, 0x6c, 0x66, 0x71, 0x6f, 0x76, 0x79,
+ 0x70, 0x71, 0x76, 0x67, 0x73, 0x76, 0x76, 0x77, 0x64, 0x61, 0x6c, 0x68, 0x61, 0x61, 0x78, 0x74,
+ 0x72, 0x78, 0x6d, 0x6d, 0x64, 0x6d, 0x72, 0x65, 0x6a, 0x6a, 0x79, 0x63, 0x6c, 0x62, 0x66, 0x75,
+ 0x79, 0x72, 0x68, 0x71, 0x71, 0x64, 0x6f, 0x79, 0x63, 0x72, 0x6c, 0x6b, 0x64, 0x63, 0x75, 0x68,
+ 0x71, 0x72, 0x77, 0x72, 0x6c, 0x6b, 0x75, 0x6d, 0x6e, 0x6c, 0x67, 0x75, 0x66, 0x65, 0x68, 0x6d,
+ 0x79, 0x70, 0x6c, 0x73, 0x79, 0x6b, 0x6c, 0x6d, 0x72, 0x6f, 0x70, 0x76, 0x78, 0x6d, 0x6f, 0x61,
+ 0x68, 0x76, 0x6f, 0x6a, 0x66, 0x77, 0x72, 0x6e, 0x62, 0x71, 0x6b, 0x71, 0x63, 0x65, 0x71, 0x65,
+ 0x6d, 0x70, 0x65, 0x6e, 0x6d, 0x77, 0x61, 0x66, 0x76, 0x6e, 0x79, 0x71, 0x76, 0x63, 0x70, 0x76,
+ 0x75, 0x6b, 0x74, 0x65, 0x6f, 0x67, 0x6e, 0x79, 0x6f, 0x61, 0x72, 0x6e, 0x6a, 0x61, 0x6d, 0x63,
+ 0x66, 0x6c, 0x63, 0x6a, 0x6e, 0x62, 0x62, 0x77, 0x63, 0x75, 0x71, 0x78, 0x65, 0x79, 0x6e, 0x79,
+ 0x6a, 0x65, 0x78, 0x73, 0x73, 0x63, 0x69, 0x74, 0x79, 0x66, 0x73, 0x71, 0x74, 0x63, 0x62, 0x76,
+ 0x73, 0x6a, 0x67, 0x78, 0x64, 0x77, 0x69, 0x78, 0x6b, 0x62, 0x79, 0x78, 0x67, 0x67, 0x76, 0x72,
+ 0x75, 0x70, 0x66, 0x68, 0x76, 0x6e, 0x6e, 0x6e, 0x75, 0x64, 0x77, 0x6a, 0x65, 0x6a, 0x70, 0x77,
+ 0x65, 0x79, 0x67, 0x6e, 0x61, 0x79, 0x6b, 0x77, 0x77, 0x78, 0x6e, 0x63, 0x72, 0x68, 0x79, 0x67,
+ 0x76, 0x77, 0x68, 0x6c, 0x78, 0x72, 0x65, 0x73, 0x71, 0x6f, 0x78, 0x78, 0x77, 0x71, 0x70, 0x64,
+ 0x6a, 0x63, 0x76, 0x6f, 0x68, 0x70, 0x72, 0x6f, 0x63, 0x72, 0x67, 0x67, 0x76, 0x77, 0x65, 0x72,
+ 0x6d, 0x75, 0x74, 0x63, 0x6b, 0x73, 0x6b, 0x73, 0x6c, 0x6b, 0x6e, 0x70, 0x75, 0x76, 0x67, 0x6e,
+ 0x68, 0x66, 0x75, 0x70, 0x78, 0x69, 0x69, 0x6c, 0x6b, 0x66, 0x77, 0x67, 0x78, 0x66, 0x69, 0x6b,
+ 0x72, 0x61, 0x64, 0x64, 0x78, 0x62, 0x68, 0x72, 0x76, 0x73, 0x78, 0x71, 0x65, 0x6f, 0x63, 0x79,
+ 0x70, 0x74, 0x77, 0x78, 0x75, 0x79, 0x75, 0x66, 0x65, 0x72, 0x70, 0x78, 0x6c, 0x79, 0x70, 0x76,
+ 0x61, 0x73, 0x64, 0x79, 0x76, 0x74, 0x79, 0x77, 0x66, 0x65, 0x61, 0x63, 0x76, 0x75, 0x64, 0x75,
+ 0x6e, 0x70, 0x63, 0x6b, 0x6c, 0x79, 0x62, 0x67, 0x67, 0x74, 0x73, 0x72, 0x68, 0x6f, 0x67, 0x62,
+ 0x6e, 0x6b, 0x68, 0x62, 0x64, 0x62, 0x70, 0x71, 0x61, 0x74, 0x6d, 0x6c, 0x78, 0x6b, 0x6b, 0x75,
+ 0x68, 0x69, 0x6e, 0x6d, 0x66, 0x76, 0x6a, 0x63, 0x68, 0x72, 0x6d, 0x63, 0x6d, 0x6b, 0x6c, 0x78,
+ 0x73, 0x72, 0x6b, 0x6c, 0x64, 0x73, 0x71, 0x6e, 0x76, 0x73, 0x69, 0x6c, 0x77, 0x72, 0x73, 0x72,
+ 0x74, 0x78, 0x61, 0x65, 0x6b, 0x6e, 0x6f, 0x62, 0x75, 0x6c, 0x69, 0x63, 0x77, 0x6d, 0x78, 0x76,
+ 0x72, 0x65, 0x75, 0x6d, 0x6f, 0x70, 0x63, 0x6b, 0x62, 0x64, 0x75, 0x6d, 0x62, 0x64, 0x77, 0x6d,
+ 0x6b, 0x70, 0x70, 0x72, 0x77, 0x64, 0x65, 0x74, 0x62, 0x69, 0x63, 0x65, 0x69, 0x71, 0x71, 0x6f,
+ 0x62, 0x67, 0x67, 0x6a, 0x77, 0x79, 0x75, 0x69, 0x77, 0x6e, 0x62, 0x77, 0x61, 0x67, 0x62, 0x74,
+ 0x79, 0x76, 0x78, 0x71, 0x78, 0x70, 0x65, 0x61, 0x65, 0x76, 0x76, 0x70, 0x69, 0x73, 0x6d, 0x75,
+ 0x6a, 0x76, 0x6a, 0x72, 0x6a, 0x73, 0x74, 0x6a, 0x76, 0x74, 0x6d, 0x70, 0x79, 0x74, 0x6b, 0x76,
+ 0x64, 0x68, 0x62, 0x76, 0x6c, 0x79, 0x77, 0x71, 0x64, 0x75, 0x6a, 0x77, 0x76, 0x6e, 0x6d, 0x74,
+ 0x65, 0x71, 0x76, 0x6a, 0x67, 0x62, 0x70, 0x71, 0x64, 0x6b, 0x71, 0x63, 0x6b, 0x72, 0x71, 0x70,
+ 0x68, 0x64, 0x72, 0x70, 0x70, 0x6d, 0x6e, 0x61, 0x77, 0x64, 0x78, 0x67, 0x70, 0x6b, 0x71, 0x63,
+ 0x66, 0x74, 0x64, 0x75, 0x72, 0x72, 0x67, 0x66, 0x75, 0x74, 0x63, 0x62, 0x71, 0x76, 0x6f, 0x69,
+ 0x65, 0x6e, 0x6f, 0x62, 0x70, 0x72, 0x74, 0x6a, 0x6c, 0x72, 0x78, 0x72, 0x66, 0x78, 0x6d, 0x75,
+ 0x79, 0x63, 0x67, 0x6c, 0x74, 0x66, 0x79, 0x71, 0x67, 0x68, 0x75, 0x67, 0x78, 0x78, 0x71, 0x6a,
+ 0x74, 0x6f, 0x62, 0x76, 0x63, 0x63, 0x65, 0x76, 0x64, 0x68, 0x71, 0x6f, 0x65, 0x61, 0x6b, 0x72,
+ 0x67, 0x64, 0x66, 0x63, 0x6e, 0x68, 0x74, 0x66, 0x6d, 0x67, 0x70, 0x6d, 0x6c, 0x65, 0x68, 0x6f,
+ 0x62, 0x65, 0x63, 0x68, 0x62, 0x66, 0x76, 0x61, 0x67, 0x61, 0x62, 0x6f, 0x74, 0x71, 0x78, 0x65,
+ 0x68, 0x6a, 0x6c, 0x66, 0x79, 0x61, 0x6b, 0x6c, 0x6c, 0x6d, 0x64, 0x62, 0x72, 0x67, 0x77, 0x75,
+ 0x6d, 0x69, 0x70, 0x6b, 0x62, 0x6b, 0x70, 0x62, 0x75, 0x79, 0x6e, 0x78, 0x6f, 0x75, 0x6a, 0x66,
+ 0x73, 0x68, 0x71, 0x6b, 0x77, 0x76, 0x66, 0x72, 0x6e, 0x6c, 0x72, 0x6d, 0x68, 0x6e, 0x6b, 0x6c,
+ 0x72, 0x78, 0x70, 0x62, 0x6b, 0x67, 0x65, 0x6b, 0x6a, 0x61, 0x68, 0x6a, 0x61, 0x67, 0x63, 0x73,
+ 0x62, 0x73, 0x6d, 0x62, 0x70, 0x72, 0x77, 0x67, 0x6c, 0x68, 0x67, 0x6b, 0x74, 0x79, 0x65, 0x79,
+ 0x78, 0x72, 0x6a, 0x75, 0x76, 0x6b, 0x66, 0x6e, 0x6e, 0x70, 0x71, 0x61, 0x6b, 0x64, 0x61, 0x77,
+ 0x72, 0x63, 0x63, 0x61, 0x64, 0x68, 0x65, 0x75, 0x6c, 0x61, 0x70, 0x75, 0x76, 0x68, 0x69, 0x64,
+ 0x71, 0x68, 0x73, 0x78, 0x71, 0x71, 0x6a, 0x6d, 0x79, 0x74, 0x71, 0x63, 0x78, 0x74, 0x6e, 0x6f,
+ 0x70, 0x6f, 0x74, 0x73, 0x70, 0x6e, 0x74, 0x73, 0x76, 0x75, 0x69, 0x76, 0x63, 0x6b, 0x69, 0x67,
+ 0x70, 0x78, 0x63, 0x67, 0x67, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x68, 0x69, 0x71, 0x6f, 0x6d, 0x6c,
+ 0x72, 0x68, 0x76, 0x78, 0x76, 0x73, 0x6d, 0x65, 0x6a, 0x69, 0x76, 0x66, 0x62, 0x63, 0x71, 0x73,
+ 0x73, 0x62, 0x6d, 0x66, 0x67, 0x68, 0x61, 0x75, 0x67, 0x6b, 0x70, 0x6e, 0x6d, 0x66, 0x61, 0x74,
+ 0x76, 0x67, 0x6a, 0x6d, 0x69, 0x6b, 0x75, 0x68, 0x6a, 0x65, 0x6f, 0x6f, 0x64, 0x70, 0x76, 0x67,
+ 0x69, 0x63, 0x70, 0x63, 0x64, 0x75, 0x6c, 0x67, 0x6d, 0x76, 0x67, 0x6a, 0x64, 0x62, 0x6b, 0x65,
+ 0x72, 0x71, 0x6c, 0x68, 0x6d, 0x78, 0x66, 0x73, 0x75, 0x6f, 0x72, 0x63, 0x77, 0x6b, 0x77, 0x71,
+ 0x68, 0x62, 0x6f, 0x6c, 0x77, 0x6c, 0x69, 0x6b, 0x6b, 0x6b, 0x76, 0x66, 0x76, 0x72, 0x6f, 0x67,
+ 0x63, 0x70, 0x66, 0x78, 0x6b, 0x76, 0x6a, 0x74, 0x62, 0x67, 0x61, 0x6c, 0x75, 0x63, 0x68, 0x76,
+ 0x6c, 0x6e, 0x75, 0x76, 0x63, 0x6a, 0x6f, 0x64, 0x75, 0x65, 0x61, 0x6d, 0x72, 0x63, 0x62, 0x69,
+ 0x76, 0x66, 0x6e, 0x6a, 0x6c, 0x63, 0x68, 0x68, 0x71, 0x69, 0x6b, 0x62, 0x66, 0x69, 0x63, 0x6f,
+ 0x6d, 0x6f, 0x70, 0x76, 0x77, 0x63, 0x69, 0x62, 0x76, 0x70, 0x6e, 0x76, 0x78, 0x69, 0x71, 0x73,
+ 0x75, 0x6b, 0x6d, 0x78, 0x61, 0x64, 0x78, 0x64, 0x6e, 0x76, 0x72, 0x66, 0x64, 0x72, 0x66, 0x67,
+ 0x6e, 0x66, 0x67, 0x78, 0x69, 0x6d, 0x62, 0x6e, 0x72, 0x63, 0x71, 0x6c, 0x67, 0x62, 0x6a, 0x63,
+ 0x70, 0x71, 0x6c, 0x71, 0x66, 0x66, 0x67, 0x76, 0x69, 0x6a, 0x65, 0x72, 0x64, 0x6e, 0x67, 0x6c,
+ 0x68, 0x6b, 0x6c, 0x65, 0x6b, 0x70, 0x6b, 0x6a, 0x66, 0x73, 0x70, 0x77, 0x71, 0x61, 0x78, 0x74,
+ 0x63, 0x6c, 0x75, 0x6a, 0x62, 0x77, 0x69, 0x6d, 0x6d, 0x6e, 0x65, 0x75, 0x71, 0x76, 0x66, 0x77,
+ 0x78, 0x78, 0x72, 0x72, 0x68, 0x79, 0x66, 0x68, 0x65, 0x6e, 0x6d, 0x68, 0x6b, 0x65, 0x70, 0x66,
+ 0x72, 0x65, 0x79, 0x65, 0x79, 0x73, 0x78, 0x62, 0x62, 0x69, 0x75, 0x63, 0x74, 0x6c, 0x72, 0x74,
+ 0x73, 0x71, 0x64, 0x6c, 0x75, 0x77, 0x6a, 0x6a, 0x68, 0x64, 0x68, 0x76, 0x71, 0x6d, 0x74, 0x6f,
+ 0x66, 0x75, 0x70, 0x71, 0x62, 0x64, 0x64, 0x74, 0x6b, 0x72, 0x70, 0x71, 0x6d, 0x79, 0x68, 0x61,
+ 0x64, 0x6c, 0x61, 0x75, 0x72, 0x79, 0x77, 0x69, 0x6d, 0x67, 0x64, 0x78, 0x6c, 0x6b, 0x63, 0x78,
+ 0x6a, 0x71, 0x63, 0x67, 0x6d, 0x68, 0x64, 0x61, 0x73, 0x6a, 0x73, 0x68, 0x74, 0x69, 0x6a, 0x72,
+ 0x64, 0x6c, 0x77, 0x70, 0x72, 0x6b, 0x68, 0x6c, 0x6d, 0x6d, 0x63, 0x63, 0x6c, 0x6f, 0x78, 0x63,
+ 0x61, 0x79, 0x6a, 0x64, 0x6a, 0x70, 0x72, 0x71, 0x70, 0x74, 0x66, 0x73, 0x6d, 0x79, 0x6d, 0x6a,
+ 0x62, 0x71, 0x6f, 0x79, 0x66, 0x69, 0x65, 0x78, 0x61, 0x73, 0x61, 0x6b, 0x78, 0x70, 0x78, 0x64,
+ 0x6e, 0x6d, 0x79, 0x6b, 0x77, 0x75, 0x78, 0x78, 0x68, 0x61, 0x6f, 0x6d, 0x78, 0x79, 0x6a, 0x77,
+ 0x6b, 0x77, 0x69, 0x64, 0x74, 0x6e, 0x63, 0x76, 0x67, 0x65, 0x73, 0x61, 0x72, 0x73, 0x78, 0x66,
+ 0x6b, 0x6c, 0x64, 0x6e, 0x78, 0x73, 0x73, 0x68, 0x6e, 0x73, 0x76, 0x62, 0x6e, 0x6d, 0x66, 0x6d,
+ 0x64, 0x79, 0x62, 0x6a, 0x6e, 0x72, 0x71, 0x64, 0x70, 0x79, 0x6a, 0x62, 0x64, 0x65, 0x61, 0x73,
+ 0x74, 0x6e, 0x63, 0x6b, 0x6a, 0x6f, 0x66, 0x68, 0x6e, 0x67, 0x68, 0x77, 0x73, 0x68, 0x61, 0x63,
+ 0x74, 0x73, 0x62, 0x6a, 0x69, 0x75, 0x72, 0x6d, 0x77, 0x6c, 0x6e, 0x72, 0x6f, 0x70, 0x6d, 0x76,
+ 0x71, 0x6e, 0x76, 0x66, 0x6e, 0x6e, 0x75, 0x70, 0x69, 0x72, 0x66, 0x61, 0x6f, 0x6d, 0x66, 0x75,
+ 0x65, 0x68, 0x69, 0x64, 0x78, 0x6c, 0x6f, 0x6b, 0x66, 0x72, 0x6a, 0x77, 0x64, 0x72, 0x72, 0x61,
+ 0x6f, 0x67, 0x61, 0x64, 0x6c, 0x76, 0x70, 0x6c, 0x66, 0x76, 0x79, 0x77, 0x6b, 0x6e, 0x6e, 0x67,
+ 0x76, 0x76, 0x75, 0x6a, 0x64, 0x70, 0x71, 0x63, 0x67, 0x6a, 0x6e, 0x63, 0x73, 0x76, 0x6e, 0x78,
+ 0x62, 0x6e, 0x63, 0x6f, 0x74, 0x65, 0x64, 0x6f, 0x6f, 0x62, 0x79, 0x75, 0x72, 0x69, 0x61, 0x78,
+ 0x72, 0x75, 0x6e, 0x6b, 0x64, 0x67, 0x6e, 0x72, 0x6f, 0x73, 0x68, 0x79, 0x68, 0x61, 0x6b, 0x6d,
+ 0x72, 0x64, 0x6f, 0x71, 0x72, 0x64, 0x6b, 0x71, 0x6c, 0x62, 0x68, 0x6b, 0x6a, 0x6d, 0x64, 0x6b,
+ 0x71, 0x76, 0x6c, 0x63, 0x72, 0x61, 0x73, 0x62, 0x6f, 0x6f, 0x6c, 0x69, 0x75, 0x64, 0x63, 0x70,
+ 0x6b, 0x6e, 0x6f, 0x6f, 0x6c, 0x65, 0x6f, 0x78, 0x6a, 0x74, 0x64, 0x79, 0x62, 0x64, 0x69, 0x79,
+ 0x63, 0x6c, 0x77, 0x6f, 0x74, 0x6a, 0x68, 0x61, 0x6a, 0x68, 0x74, 0x6a, 0x70, 0x68, 0x72, 0x68,
+ 0x63, 0x6f, 0x71, 0x77, 0x78, 0x76, 0x6a, 0x6e, 0x76, 0x73, 0x67, 0x69, 0x6f, 0x73, 0x68, 0x71,
+ 0x69, 0x6c, 0x73, 0x73, 0x79, 0x67, 0x79, 0x61, 0x64, 0x70, 0x61, 0x71, 0x68, 0x73, 0x6b, 0x65,
+ 0x64, 0x75, 0x76, 0x69, 0x73, 0x6e, 0x67, 0x77, 0x6a, 0x72, 0x62, 0x74, 0x76, 0x63, 0x6f, 0x73,
+ 0x64, 0x64, 0x62, 0x69, 0x72, 0x6b, 0x71, 0x63, 0x73, 0x73, 0x64, 0x69, 0x6e, 0x73, 0x64, 0x6d,
+ 0x63, 0x70, 0x67, 0x76, 0x61, 0x79, 0x6d, 0x73, 0x74, 0x6c, 0x79, 0x6d, 0x74, 0x68, 0x65, 0x77,
+ 0x63, 0x66, 0x77, 0x6e, 0x64, 0x69, 0x6a, 0x62, 0x65, 0x6e, 0x79, 0x6b, 0x6c, 0x6e, 0x79, 0x6e,
+ 0x65, 0x76, 0x6b, 0x6e, 0x62, 0x6a, 0x72, 0x73, 0x72, 0x76, 0x69, 0x71, 0x62, 0x76, 0x63, 0x69,
+ 0x6c, 0x63, 0x64, 0x70, 0x6d, 0x6b, 0x63, 0x6c, 0x61, 0x77, 0x71, 0x74, 0x61, 0x71, 0x6c, 0x65,
+ 0x65, 0x70, 0x70, 0x67, 0x6c, 0x77, 0x6e, 0x74, 0x64, 0x79, 0x62, 0x64, 0x63, 0x77, 0x79, 0x73,
+ 0x73, 0x66, 0x68, 0x70, 0x65, 0x61, 0x67, 0x72, 0x61, 0x6a, 0x68, 0x66, 0x62, 0x72, 0x6d, 0x6e,
+ 0x65, 0x78, 0x6b, 0x6b, 0x78, 0x74, 0x72, 0x6b, 0x71, 0x67, 0x6a, 0x69, 0x71, 0x65, 0x6d, 0x76,
+ 0x79, 0x69, 0x61, 0x65, 0x70, 0x68, 0x6e, 0x64, 0x6a, 0x77, 0x69, 0x6c, 0x6b, 0x6b, 0x63, 0x62,
+ 0x6d, 0x63, 0x76, 0x77, 0x67, 0x6e, 0x6b, 0x6d, 0x67, 0x71, 0x69, 0x78, 0x6e, 0x6d, 0x6b, 0x78,
+ 0x65, 0x6c, 0x61, 0x77, 0x6f, 0x64, 0x79, 0x62, 0x63, 0x61, 0x6b, 0x66, 0x72, 0x79, 0x69, 0x65,
+ 0x76, 0x77, 0x65, 0x6d, 0x6c, 0x69, 0x62, 0x6f, 0x79, 0x77, 0x6d, 0x78, 0x6d, 0x62, 0x6f, 0x78,
+ 0x68, 0x77, 0x6d, 0x70, 0x72, 0x6d, 0x63, 0x71, 0x79, 0x65, 0x61, 0x66, 0x78, 0x66, 0x63, 0x6e,
+ 0x69, 0x68, 0x73, 0x74, 0x6d, 0x6f, 0x76, 0x71, 0x64, 0x75, 0x77, 0x63, 0x6c, 0x63, 0x70, 0x61,
+ 0x6d, 0x77, 0x76, 0x78, 0x72, 0x71, 0x6f, 0x61, 0x74, 0x62, 0x64, 0x68, 0x64, 0x6a, 0x67, 0x75,
+ 0x71, 0x79, 0x66, 0x70, 0x64, 0x72, 0x62, 0x6b, 0x65, 0x65, 0x66, 0x79, 0x6d, 0x75, 0x70, 0x6a,
+ 0x61, 0x75, 0x67, 0x65, 0x70, 0x6c, 0x65, 0x61, 0x77, 0x72, 0x67, 0x73, 0x74, 0x68, 0x77, 0x70,
+ 0x65, 0x6c, 0x74, 0x75, 0x73, 0x74, 0x6d, 0x61, 0x64, 0x6f, 0x79, 0x78, 0x79, 0x62, 0x75, 0x6b,
+ 0x66, 0x79, 0x78, 0x75, 0x73, 0x71, 0x75, 0x76, 0x6a, 0x63, 0x73, 0x68, 0x65, 0x71, 0x6e, 0x62,
+ 0x75, 0x77, 0x74, 0x68, 0x70, 0x77, 0x6c, 0x66, 0x6d, 0x79, 0x65, 0x64, 0x66, 0x69, 0x70, 0x66,
+ 0x74, 0x66, 0x6c, 0x77, 0x71, 0x6f, 0x6d, 0x78, 0x6d, 0x6d, 0x70, 0x73, 0x77, 0x75, 0x79, 0x65,
+ 0x63, 0x6e, 0x76, 0x66, 0x63, 0x6d, 0x71, 0x65, 0x67, 0x74, 0x73, 0x6b, 0x6f, 0x70, 0x62, 0x74,
+ 0x78, 0x68, 0x6d, 0x67, 0x72, 0x66, 0x75, 0x77, 0x69, 0x68, 0x62, 0x70, 0x74, 0x75, 0x6f, 0x63,
+ 0x68, 0x70, 0x79, 0x6e, 0x77, 0x61, 0x68, 0x6d, 0x6d, 0x68, 0x74, 0x78, 0x76, 0x78, 0x76, 0x74,
+ 0x65, 0x75, 0x6f, 0x70, 0x65, 0x79, 0x6f, 0x73, 0x63, 0x61, 0x6b, 0x76, 0x6c, 0x74, 0x75, 0x75,
+ 0x68, 0x6f, 0x65, 0x6d, 0x74, 0x68, 0x63, 0x71, 0x67, 0x64, 0x72, 0x63, 0x67, 0x6b, 0x68, 0x74,
+ 0x69, 0x65, 0x6c, 0x73, 0x74, 0x63, 0x75, 0x69, 0x71, 0x65, 0x75, 0x67, 0x6b, 0x79, 0x79, 0x6f,
+ 0x75, 0x63, 0x6d, 0x66, 0x75, 0x6f, 0x6d, 0x6d, 0x73, 0x63, 0x6d, 0x73, 0x70, 0x71, 0x76, 0x74,
+ 0x71, 0x72, 0x77, 0x71, 0x70, 0x76, 0x65, 0x79, 0x72, 0x6d, 0x6d, 0x76, 0x78, 0x65, 0x77, 0x72,
+ 0x78, 0x72, 0x6c, 0x75, 0x76, 0x76, 0x72, 0x72, 0x77, 0x6b, 0x68, 0x6a, 0x73, 0x6c, 0x6f, 0x6d,
+ 0x79, 0x68, 0x75, 0x62, 0x6c, 0x6d, 0x69, 0x68, 0x78, 0x62, 0x65, 0x79, 0x72, 0x78, 0x6d, 0x6e,
+ 0x68, 0x69, 0x6d, 0x74, 0x63, 0x65, 0x66, 0x70, 0x77, 0x62, 0x6b, 0x64, 0x75, 0x6e, 0x72, 0x6a,
+ 0x76, 0x6e, 0x75, 0x6f, 0x6e, 0x61, 0x71, 0x72, 0x74, 0x76, 0x61, 0x61, 0x74, 0x66, 0x66, 0x61,
+ 0x78, 0x72, 0x70, 0x62, 0x65, 0x73, 0x79, 0x64, 0x75, 0x67, 0x75, 0x66, 0x71, 0x73, 0x73, 0x70,
+ 0x69, 0x73, 0x6d, 0x6c, 0x70, 0x64, 0x69, 0x6f, 0x74, 0x78, 0x70, 0x72, 0x78, 0x71, 0x73, 0x63,
+ 0x62, 0x70, 0x76, 0x6c, 0x6b, 0x62, 0x61, 0x76, 0x73, 0x67, 0x77, 0x75, 0x6a, 0x72, 0x65, 0x64,
+ 0x62, 0x79, 0x6e, 0x76, 0x6d, 0x65, 0x6c, 0x62, 0x67, 0x63, 0x62, 0x77, 0x72, 0x78, 0x65, 0x77,
+ 0x71, 0x72, 0x64, 0x75, 0x69, 0x77, 0x6c, 0x6f, 0x77, 0x61, 0x69, 0x6d, 0x69, 0x76, 0x63, 0x72,
+ 0x79, 0x79, 0x6a, 0x6f, 0x63, 0x72, 0x74, 0x62, 0x78, 0x77, 0x6d, 0x75, 0x62, 0x6c, 0x6b, 0x6f,
+ 0x74, 0x63, 0x73, 0x70, 0x74, 0x6d, 0x6a, 0x70, 0x6f, 0x6a, 0x6f, 0x66, 0x61, 0x66, 0x71, 0x75,
+ 0x74, 0x73, 0x6a, 0x6c, 0x6d, 0x79, 0x68, 0x71, 0x78, 0x75, 0x6d, 0x6f, 0x70, 0x74, 0x70, 0x76,
+ 0x71, 0x6a, 0x61, 0x62, 0x67, 0x69, 0x6d, 0x62, 0x74, 0x6b, 0x67, 0x73, 0x66, 0x6f, 0x6d, 0x6c,
+ 0x79, 0x69, 0x69, 0x6d, 0x67, 0x6d, 0x71, 0x66, 0x73, 0x66, 0x6e, 0x65, 0x6c, 0x75, 0x79, 0x68,
+ 0x6a, 0x74, 0x79, 0x70, 0x72, 0x73, 0x6b, 0x65, 0x6d, 0x6a, 0x6e, 0x6a, 0x76, 0x6d, 0x6d, 0x6a,
+ 0x6b, 0x68, 0x65, 0x6a, 0x68, 0x71, 0x6b, 0x63, 0x73, 0x6a, 0x78, 0x68, 0x6f, 0x76, 0x70, 0x75,
+ 0x73, 0x72, 0x78, 0x6f, 0x74, 0x6c, 0x6f, 0x6d, 0x6c, 0x74, 0x6b, 0x73, 0x71, 0x66, 0x6a, 0x64,
+ 0x6a, 0x68, 0x6b, 0x67, 0x72, 0x78, 0x76, 0x68, 0x70, 0x69, 0x6e, 0x75, 0x6d, 0x76, 0x6b, 0x62,
+ 0x6b, 0x61, 0x78, 0x6f, 0x77, 0x72, 0x75, 0x76, 0x6e, 0x69, 0x6f, 0x6c, 0x6d, 0x68, 0x6e, 0x6b,
+ 0x6d, 0x75, 0x6c, 0x75, 0x72, 0x75, 0x78, 0x6b, 0x73, 0x71, 0x6b, 0x76, 0x63, 0x63, 0x6f, 0x6b,
+ 0x75, 0x6a, 0x6a, 0x74, 0x6c, 0x78, 0x73, 0x74, 0x75, 0x71, 0x6e, 0x76, 0x77, 0x66, 0x6e, 0x61,
+ 0x66, 0x62, 0x63, 0x65, 0x72, 0x63, 0x67, 0x77, 0x62, 0x6a, 0x71, 0x75, 0x6a, 0x6f, 0x63, 0x71,
+ 0x77, 0x72, 0x74, 0x6e, 0x71, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x66, 0x77, 0x61, 0x68, 0x74, 0x70,
+ 0x64, 0x76, 0x62, 0x65, 0x64, 0x68, 0x63, 0x68, 0x77, 0x75, 0x6b, 0x79, 0x77, 0x70, 0x61, 0x63,
+ 0x6b, 0x64, 0x6a, 0x79, 0x72, 0x6f, 0x73, 0x62, 0x65, 0x69, 0x71, 0x6d, 0x66, 0x61, 0x73, 0x6e,
+ 0x6b, 0x63, 0x65, 0x77, 0x73, 0x72, 0x77, 0x62, 0x63, 0x75, 0x67, 0x62, 0x65, 0x62, 0x6b, 0x76,
+ 0x61, 0x71, 0x78, 0x76, 0x61, 0x6d, 0x70, 0x65, 0x6f, 0x68, 0x77, 0x64, 0x61, 0x6a, 0x6f, 0x67,
+ 0x6b, 0x67, 0x68, 0x75, 0x71, 0x66, 0x73, 0x69, 0x75, 0x62, 0x6a, 0x6c, 0x72, 0x71, 0x68, 0x69,
+ 0x61, 0x6a, 0x6a, 0x79, 0x71, 0x6c, 0x6d, 0x76, 0x6f, 0x68, 0x74, 0x77, 0x6a, 0x63, 0x62, 0x6d,
+ 0x6a, 0x6f, 0x74, 0x61, 0x6f, 0x6b, 0x69, 0x64, 0x72, 0x6b, 0x67, 0x75, 0x76, 0x77, 0x78, 0x61,
+ 0x6c, 0x70, 0x69, 0x6f, 0x69, 0x62, 0x61, 0x67, 0x72, 0x62, 0x67, 0x65, 0x67, 0x6e, 0x62, 0x6c,
+ 0x66, 0x69, 0x69, 0x6b, 0x6a, 0x6d, 0x6a, 0x70, 0x6d, 0x73, 0x6f, 0x77, 0x63, 0x75, 0x6c, 0x69,
+ 0x65, 0x6c, 0x79, 0x6d, 0x79, 0x71, 0x6d, 0x61, 0x74, 0x6b, 0x78, 0x75, 0x6b, 0x6c, 0x73, 0x63,
+ 0x6d, 0x6c, 0x6c, 0x78, 0x74, 0x6f, 0x6f, 0x67, 0x71, 0x67, 0x78, 0x71, 0x64, 0x65, 0x63, 0x6b,
+ 0x69, 0x74, 0x6d, 0x74, 0x6b, 0x6b, 0x78, 0x61, 0x74, 0x66, 0x75, 0x77, 0x66, 0x68, 0x69, 0x6a,
+ 0x66, 0x65, 0x79, 0x78, 0x65, 0x6a, 0x6e, 0x71, 0x76, 0x79, 0x69, 0x71, 0x64, 0x76, 0x77, 0x67,
+ 0x61, 0x6d, 0x6c, 0x71, 0x66, 0x6c, 0x67, 0x64, 0x65, 0x62, 0x66, 0x77, 0x6c, 0x65, 0x74, 0x72,
+ 0x62, 0x64, 0x61, 0x6c, 0x6e, 0x6c, 0x75, 0x6e, 0x64, 0x74, 0x78, 0x63, 0x62, 0x62, 0x68, 0x73,
+ 0x61, 0x67, 0x79, 0x6f, 0x67, 0x6c, 0x66, 0x62, 0x75, 0x72, 0x76, 0x6f, 0x62, 0x61, 0x66, 0x73,
+ 0x74, 0x75, 0x6c, 0x62, 0x69, 0x6a, 0x68, 0x6b, 0x75, 0x77, 0x6d, 0x72, 0x6e, 0x62, 0x77, 0x6a,
+ 0x64, 0x72, 0x74, 0x67, 0x76, 0x79, 0x6c, 0x65, 0x79, 0x78, 0x79, 0x68, 0x76, 0x75, 0x78, 0x69,
+ 0x61, 0x78, 0x6e, 0x77, 0x64, 0x69, 0x61, 0x69, 0x74, 0x70, 0x66, 0x78, 0x75, 0x64, 0x6a, 0x68,
+ 0x6f, 0x67, 0x6c, 0x6e, 0x74, 0x70, 0x75, 0x74, 0x75, 0x6a, 0x61, 0x6d, 0x78, 0x76, 0x63, 0x67,
+ 0x6f, 0x66, 0x6b, 0x71, 0x6d, 0x74, 0x6c, 0x66, 0x63, 0x62, 0x73, 0x6c, 0x74, 0x63, 0x6c, 0x6d,
+ 0x72, 0x73, 0x6c, 0x77, 0x75, 0x6a, 0x77, 0x66, 0x75, 0x75, 0x73, 0x71, 0x68, 0x6d, 0x6d, 0x61,
+ 0x6d, 0x6b, 0x63, 0x63, 0x6c, 0x6d, 0x77, 0x74, 0x6c, 0x69, 0x65, 0x68, 0x6d, 0x67, 0x63, 0x70,
+ 0x63, 0x61, 0x6a, 0x71, 0x72, 0x67, 0x6f, 0x78, 0x73, 0x62, 0x70, 0x6f, 0x6f, 0x65, 0x6f, 0x6f,
+ 0x73, 0x75, 0x6d, 0x6a, 0x75, 0x70, 0x71, 0x61, 0x61, 0x72, 0x6a, 0x66, 0x72, 0x72, 0x62, 0x61,
+ 0x67, 0x63, 0x73, 0x79, 0x6e, 0x71, 0x62, 0x6a, 0x63, 0x66, 0x76, 0x6c, 0x64, 0x64, 0x68, 0x77,
+ 0x66, 0x6b, 0x6c, 0x6e, 0x6b, 0x61, 0x73, 0x6e, 0x73, 0x63, 0x78, 0x72, 0x62, 0x75, 0x6b, 0x63,
+ 0x6e, 0x6b, 0x6e, 0x65, 0x6a, 0x62, 0x62, 0x77, 0x6a, 0x77, 0x6c, 0x62, 0x70, 0x67, 0x68, 0x72,
+ 0x73, 0x6d, 0x71, 0x63, 0x69, 0x74, 0x68, 0x6c, 0x78, 0x69, 0x78, 0x65, 0x75, 0x6d, 0x63, 0x6b,
+ 0x64, 0x75, 0x65, 0x76, 0x6c, 0x72, 0x6e, 0x63, 0x79, 0x6d, 0x63, 0x6d, 0x67, 0x70, 0x66, 0x6b,
+ 0x76, 0x6a, 0x6b, 0x62, 0x75, 0x69, 0x76, 0x6c, 0x62, 0x76, 0x66, 0x72, 0x61, 0x6a, 0x67, 0x71,
+ 0x64, 0x74, 0x74, 0x70, 0x6c, 0x63, 0x73, 0x6e, 0x71, 0x74, 0x6b, 0x6a, 0x64, 0x62, 0x69, 0x68,
+ 0x65, 0x71, 0x6a, 0x6b, 0x62, 0x73, 0x6c, 0x67, 0x6d, 0x68, 0x78, 0x6d, 0x73, 0x69, 0x65, 0x74,
+ 0x6c, 0x61, 0x66, 0x74, 0x65, 0x65, 0x62, 0x6a, 0x6a, 0x6d, 0x71, 0x61, 0x69, 0x74, 0x70, 0x6c,
+ 0x68, 0x65, 0x65, 0x6b, 0x69, 0x79, 0x72, 0x71, 0x71, 0x74, 0x6f, 0x6e, 0x6c, 0x62, 0x74, 0x63,
+ 0x64, 0x69, 0x66, 0x70, 0x76, 0x6d, 0x6b, 0x72, 0x6c, 0x6a, 0x77, 0x61, 0x74, 0x72, 0x62, 0x65,
+ 0x68, 0x6e, 0x75, 0x62, 0x71, 0x6e, 0x63, 0x63, 0x64, 0x64, 0x62, 0x69, 0x74, 0x6c, 0x6e, 0x70,
+ 0x78, 0x69, 0x63, 0x65, 0x6a, 0x6f, 0x78, 0x6c, 0x6a, 0x65, 0x6e, 0x6c, 0x6c, 0x65, 0x67, 0x6e,
+ 0x68, 0x62, 0x63, 0x65, 0x6c, 0x62, 0x6f, 0x6e, 0x6d, 0x61, 0x6c, 0x61, 0x76, 0x69, 0x71, 0x77,
+ 0x74, 0x6a, 0x74, 0x74, 0x6d, 0x6a, 0x6a, 0x77, 0x70, 0x76, 0x70, 0x75, 0x6c, 0x6f, 0x6c, 0x75,
+ 0x69, 0x61, 0x6c, 0x75, 0x62, 0x6f, 0x68, 0x67, 0x69, 0x67, 0x61, 0x6d, 0x72, 0x72, 0x63, 0x6b,
+ 0x63, 0x70, 0x6c, 0x70, 0x69, 0x71, 0x6e, 0x76, 0x6f, 0x77, 0x74, 0x64, 0x76, 0x67, 0x6f, 0x77,
+ 0x76, 0x77, 0x6e, 0x61, 0x72, 0x76, 0x74, 0x65, 0x63, 0x63, 0x73, 0x65, 0x6d, 0x67, 0x69, 0x65,
+ 0x74, 0x6e, 0x77, 0x63, 0x78, 0x77, 0x63, 0x76, 0x68, 0x65, 0x76, 0x73, 0x64, 0x6a, 0x68, 0x6a,
+ 0x65, 0x72, 0x75, 0x70, 0x61, 0x6b, 0x71, 0x68, 0x74, 0x6f, 0x78, 0x6d, 0x74, 0x62, 0x61, 0x71,
+ 0x64, 0x6b, 0x6a, 0x76, 0x79, 0x61, 0x6c, 0x77, 0x6a, 0x68, 0x78, 0x62, 0x70, 0x78, 0x78, 0x65,
+ 0x64, 0x74, 0x6f, 0x71, 0x69, 0x75, 0x70, 0x78, 0x71, 0x78, 0x66, 0x65, 0x74, 0x6d, 0x6a, 0x75,
+ 0x66, 0x76, 0x70, 0x75, 0x69, 0x6c, 0x73, 0x76, 0x79, 0x63, 0x62, 0x68, 0x74, 0x6e, 0x69, 0x72,
+ 0x76, 0x6b, 0x62, 0x6d, 0x67, 0x65, 0x79, 0x70, 0x79, 0x6d, 0x65, 0x70, 0x79, 0x6a, 0x62, 0x61,
+ 0x76, 0x64, 0x65, 0x75, 0x69, 0x6a, 0x76, 0x70, 0x6c, 0x69, 0x74, 0x6b, 0x65, 0x6d, 0x69, 0x75,
+ 0x77, 0x68, 0x6b, 0x6f, 0x72, 0x66, 0x68, 0x75, 0x73, 0x63, 0x77, 0x69, 0x69, 0x6b, 0x68, 0x67,
+ 0x66, 0x6f, 0x71, 0x69, 0x63, 0x77, 0x74, 0x61, 0x6b, 0x70, 0x62, 0x6b, 0x6e, 0x6f, 0x77, 0x6e,
+ 0x78, 0x6e, 0x66, 0x69, 0x78, 0x6f, 0x64, 0x77, 0x61, 0x6c, 0x70, 0x75, 0x62, 0x70, 0x6d, 0x76,
+ 0x79, 0x72, 0x66, 0x64, 0x76, 0x75, 0x6f, 0x6f, 0x71, 0x73, 0x75, 0x73, 0x77, 0x79, 0x71, 0x63,
+ 0x76, 0x78, 0x73, 0x6e, 0x6d, 0x70, 0x69, 0x78, 0x75, 0x6c, 0x6e, 0x76, 0x76, 0x79, 0x6d, 0x68,
+ 0x71, 0x76, 0x63, 0x77, 0x67, 0x6d, 0x6a, 0x64, 0x6f, 0x73, 0x64, 0x70, 0x68, 0x67, 0x6f, 0x61,
+ 0x67, 0x6d, 0x76, 0x6f, 0x6c, 0x74, 0x72, 0x74, 0x76, 0x62, 0x70, 0x61, 0x64, 0x6f, 0x73, 0x63,
+ 0x64, 0x74, 0x68, 0x68, 0x76, 0x79, 0x6a, 0x66, 0x78, 0x6a, 0x63, 0x68, 0x6a, 0x61, 0x73, 0x65,
+ 0x65, 0x6c, 0x6f, 0x61, 0x61, 0x71, 0x6b, 0x72, 0x6e, 0x71, 0x62, 0x6f, 0x66, 0x77, 0x72, 0x66,
+ 0x63, 0x75, 0x73, 0x65, 0x62, 0x66, 0x74, 0x69, 0x71, 0x66, 0x72, 0x67, 0x61, 0x6c, 0x68, 0x64,
+ 0x63, 0x66, 0x73, 0x78, 0x74, 0x63, 0x64, 0x71, 0x71, 0x75, 0x77, 0x6a, 0x71, 0x6a, 0x6e, 0x6b,
+ 0x77, 0x64, 0x66, 0x68, 0x69, 0x77, 0x77, 0x71, 0x62, 0x73, 0x64, 0x70, 0x71, 0x65, 0x63, 0x71,
+ 0x71, 0x70, 0x6e, 0x6a, 0x75, 0x6f, 0x70, 0x63, 0x67, 0x65, 0x72, 0x76, 0x77, 0x79, 0x72, 0x6b,
+ 0x68, 0x77, 0x75, 0x68, 0x6a, 0x66, 0x6f, 0x6c, 0x79, 0x76, 0x66, 0x65, 0x62, 0x72, 0x75, 0x62,
+ 0x69, 0x65, 0x77, 0x72, 0x77, 0x74, 0x69, 0x6f, 0x76, 0x6e, 0x76, 0x6a, 0x68, 0x76, 0x6f, 0x75,
+ 0x77, 0x6f, 0x75, 0x6c, 0x67, 0x74, 0x6d, 0x75, 0x79, 0x62, 0x6c, 0x6c, 0x66, 0x6e, 0x76, 0x62,
+ 0x6a, 0x71, 0x65, 0x66, 0x77, 0x62, 0x6b, 0x71, 0x61, 0x66, 0x71, 0x76, 0x6b, 0x6c, 0x72, 0x6c,
+ 0x63, 0x63, 0x68, 0x68, 0x6a, 0x69, 0x6a, 0x63, 0x75, 0x71, 0x68, 0x6b, 0x6d, 0x61, 0x76, 0x76,
+ 0x6e, 0x6a, 0x6a, 0x67, 0x68, 0x6f, 0x65, 0x67, 0x72, 0x6f, 0x70, 0x70, 0x6b, 0x63, 0x64, 0x75,
+ 0x63, 0x67, 0x65, 0x71, 0x69, 0x64, 0x66, 0x65, 0x6c, 0x72, 0x72, 0x66, 0x72, 0x74, 0x66, 0x75,
+ 0x65, 0x77, 0x6d, 0x69, 0x68, 0x6e, 0x72, 0x77, 0x6a, 0x61, 0x72, 0x67, 0x73, 0x76, 0x6b, 0x67,
+ 0x67, 0x6c, 0x75, 0x67, 0x61, 0x73, 0x78, 0x68, 0x72, 0x6b, 0x64, 0x69, 0x6d, 0x6c, 0x6e, 0x68,
+ 0x78, 0x76, 0x70, 0x67, 0x6c, 0x6f, 0x68, 0x63, 0x72, 0x76, 0x61, 0x69, 0x68, 0x71, 0x69, 0x6f,
+ 0x67, 0x6b, 0x61, 0x69, 0x6d, 0x73, 0x66, 0x6c, 0x64, 0x76, 0x71, 0x78, 0x79, 0x74, 0x62, 0x71,
+ 0x6b, 0x62, 0x71, 0x63, 0x69, 0x74, 0x61, 0x6a, 0x63, 0x75, 0x6f, 0x6a, 0x6b, 0x64, 0x61, 0x77,
+ 0x66, 0x61, 0x6c, 0x74, 0x71, 0x75, 0x61, 0x69, 0x6e, 0x69, 0x6a, 0x6b, 0x61, 0x65, 0x78, 0x68,
+ 0x62, 0x78, 0x75, 0x6c, 0x6b, 0x68, 0x79, 0x77, 0x6a, 0x76, 0x6f, 0x61, 0x63, 0x71, 0x65, 0x66,
+ 0x6e, 0x67, 0x73, 0x74, 0x62, 0x73, 0x73, 0x76, 0x78, 0x6b, 0x63, 0x78, 0x72, 0x6c, 0x6a, 0x67,
+ 0x69, 0x63, 0x78, 0x64, 0x63, 0x6d, 0x6a, 0x6f, 0x6d, 0x6d, 0x63, 0x74, 0x70, 0x64, 0x6d, 0x74,
+ 0x72, 0x77, 0x6a, 0x75, 0x73, 0x6c, 0x63, 0x68, 0x71, 0x71, 0x62, 0x75, 0x6d, 0x79, 0x70, 0x6f,
+ 0x77, 0x72, 0x62, 0x6a, 0x69, 0x6e, 0x76, 0x77, 0x61, 0x73, 0x71, 0x79, 0x78, 0x70, 0x78, 0x6e,
+ 0x64, 0x79, 0x78, 0x6e, 0x6e, 0x65, 0x78, 0x73, 0x68, 0x76, 0x79, 0x75, 0x65, 0x73, 0x65, 0x6c,
+ 0x72, 0x6d, 0x64, 0x76, 0x73, 0x76, 0x6e, 0x67, 0x73, 0x74, 0x6a, 0x62, 0x79, 0x79, 0x70, 0x64,
+ 0x71, 0x73, 0x6d, 0x64, 0x6a, 0x62, 0x66, 0x67, 0x70, 0x67, 0x74, 0x66, 0x6e, 0x78, 0x78, 0x6e,
+ 0x64, 0x6e, 0x64, 0x6f, 0x64, 0x6f, 0x73, 0x6d, 0x68, 0x79, 0x68, 0x67, 0x6f, 0x61, 0x66, 0x68,
+ 0x78, 0x73, 0x62, 0x6b, 0x61, 0x63, 0x6b, 0x6a, 0x76, 0x62, 0x66, 0x78, 0x79, 0x61, 0x76, 0x6c,
+ 0x64, 0x71, 0x72, 0x75, 0x66, 0x69, 0x6c, 0x64, 0x62, 0x6b, 0x63, 0x6d, 0x73, 0x72, 0x61, 0x77,
+ 0x69, 0x71, 0x73, 0x78, 0x63, 0x74, 0x74, 0x66, 0x71, 0x73, 0x63, 0x6c, 0x70, 0x66, 0x65, 0x68,
+ 0x6a, 0x72, 0x62, 0x70, 0x75, 0x65, 0x66, 0x70, 0x73, 0x72, 0x62, 0x69, 0x70, 0x6f, 0x78, 0x78,
+ 0x66, 0x78, 0x71, 0x63, 0x73, 0x6a, 0x70, 0x70, 0x6a, 0x74, 0x67, 0x6e, 0x79, 0x67, 0x75, 0x72,
+ 0x69, 0x74, 0x61, 0x73, 0x74, 0x68, 0x75, 0x70, 0x6f, 0x72, 0x63, 0x75, 0x70, 0x73, 0x64, 0x69,
+ 0x72, 0x75, 0x74, 0x63, 0x71, 0x75, 0x6f, 0x64, 0x74, 0x66, 0x63, 0x65, 0x68, 0x76, 0x74, 0x77,
+ 0x75, 0x69, 0x75, 0x63, 0x65, 0x61, 0x79, 0x77, 0x67, 0x77, 0x69, 0x6f, 0x6e, 0x74, 0x75, 0x75,
+ 0x74, 0x6c, 0x62, 0x6f, 0x6b, 0x78, 0x71, 0x66, 0x78, 0x62, 0x64, 0x64, 0x6b, 0x69, 0x77, 0x64,
+ 0x66, 0x70, 0x74, 0x73, 0x6a, 0x68, 0x74, 0x75, 0x65, 0x6e, 0x73, 0x70, 0x78, 0x6f, 0x74, 0x69,
+ 0x72, 0x76, 0x70, 0x72, 0x69, 0x68, 0x70, 0x6d, 0x66, 0x67, 0x74, 0x73, 0x6d, 0x66, 0x68, 0x73,
+ 0x6b, 0x6c, 0x66, 0x62, 0x66, 0x76, 0x66, 0x6a, 0x70, 0x76, 0x67, 0x72, 0x65, 0x78, 0x61, 0x6f,
+ 0x78, 0x68, 0x62, 0x61, 0x73, 0x64, 0x65, 0x6b, 0x73, 0x6a, 0x64, 0x61, 0x68, 0x67, 0x64, 0x78,
+ 0x6f, 0x6f, 0x61, 0x65, 0x78, 0x68, 0x64, 0x6f, 0x71, 0x72, 0x69, 0x66, 0x64, 0x71, 0x73, 0x61,
+ 0x78, 0x74, 0x69, 0x77, 0x6a, 0x74, 0x74, 0x79, 0x6f, 0x70, 0x78, 0x6b, 0x76, 0x6d, 0x79, 0x72,
+ 0x6e, 0x65, 0x74, 0x62, 0x6f, 0x67, 0x67, 0x6e, 0x6b, 0x74, 0x77, 0x73, 0x69, 0x75, 0x61, 0x64,
+ 0x6a, 0x79, 0x70, 0x70, 0x62, 0x78, 0x6c, 0x71, 0x61, 0x72, 0x6c, 0x65, 0x79, 0x61, 0x77, 0x6a,
+ 0x79, 0x6b, 0x6f, 0x66, 0x66, 0x79, 0x6a, 0x79, 0x6c, 0x62, 0x67, 0x6f, 0x64, 0x6a, 0x67, 0x61,
+ 0x72, 0x6a, 0x64, 0x72, 0x72, 0x77, 0x79, 0x61, 0x78, 0x77, 0x71, 0x70, 0x76, 0x67, 0x78, 0x78,
+ 0x63, 0x6b, 0x78, 0x64, 0x77, 0x6c, 0x73, 0x66, 0x6c, 0x63, 0x74, 0x6e, 0x6c, 0x65, 0x63, 0x74,
+ 0x65, 0x68, 0x64, 0x6c, 0x65, 0x6d, 0x64, 0x76, 0x71, 0x72, 0x6b, 0x66, 0x74, 0x71, 0x6d, 0x6b,
+ 0x74, 0x69, 0x75, 0x73, 0x67, 0x65, 0x6c, 0x73, 0x63, 0x6c, 0x72, 0x66, 0x78, 0x69, 0x67, 0x73,
+ 0x75, 0x6f, 0x6a, 0x75, 0x6b, 0x6e, 0x6f, 0x64, 0x6a, 0x66, 0x73, 0x69, 0x63, 0x66, 0x6e, 0x6b,
+ 0x68, 0x71, 0x69, 0x61, 0x6a, 0x63, 0x78, 0x6e, 0x6c, 0x6a, 0x78, 0x66, 0x71, 0x69, 0x6e, 0x62,
+ 0x78, 0x75, 0x72, 0x64, 0x73, 0x6f, 0x65, 0x78, 0x70, 0x73, 0x72, 0x72, 0x70, 0x78, 0x76, 0x6a,
+ 0x6b, 0x63, 0x75, 0x78, 0x76, 0x67, 0x6c, 0x66, 0x61, 0x6a, 0x71, 0x71, 0x6d, 0x6a, 0x6a, 0x62,
+ 0x65, 0x76, 0x73, 0x71, 0x77, 0x69, 0x63, 0x65, 0x74, 0x64, 0x79, 0x66, 0x6d, 0x66, 0x74, 0x68,
+ 0x62, 0x6d, 0x6d, 0x64, 0x78, 0x74, 0x76, 0x75, 0x78, 0x79, 0x66, 0x71, 0x6d, 0x6d, 0x6f, 0x78,
+ 0x61, 0x63, 0x64, 0x74, 0x71, 0x63, 0x65, 0x63, 0x68, 0x64, 0x78, 0x6b, 0x79, 0x6d, 0x71, 0x6f,
+ 0x61, 0x79, 0x72, 0x6e, 0x64, 0x71, 0x63, 0x63, 0x6f, 0x71, 0x73, 0x6d, 0x74, 0x71, 0x63, 0x64,
+ 0x74, 0x6f, 0x71, 0x78, 0x78, 0x6b, 0x68, 0x74, 0x6f, 0x63, 0x62, 0x6f, 0x78, 0x6e, 0x6f, 0x76,
+ 0x6a, 0x6b, 0x6c, 0x68, 0x68, 0x62, 0x62, 0x6a, 0x71, 0x67, 0x6f, 0x63, 0x66, 0x72, 0x63, 0x63,
+ 0x6f, 0x74, 0x6d, 0x72, 0x77, 0x71, 0x72, 0x6d, 0x65, 0x6c, 0x6b, 0x76, 0x70, 0x74, 0x72, 0x61,
+ 0x74, 0x72, 0x71, 0x76, 0x79, 0x6a, 0x77, 0x72, 0x65, 0x61, 0x6b, 0x74, 0x6d, 0x61, 0x67, 0x75,
+ 0x73, 0x73, 0x69, 0x67, 0x77, 0x66, 0x73, 0x72, 0x63, 0x6b, 0x66, 0x76, 0x6a, 0x69, 0x67, 0x61,
+ 0x74, 0x64, 0x66, 0x78, 0x64, 0x72, 0x62, 0x6a, 0x64, 0x65, 0x61, 0x62, 0x63, 0x72, 0x61, 0x66,
+ 0x68, 0x72, 0x78, 0x77, 0x73, 0x6a, 0x72, 0x66, 0x79, 0x6d, 0x70, 0x77, 0x78, 0x64, 0x66, 0x63,
+ 0x73, 0x68, 0x61, 0x75, 0x73, 0x77, 0x63, 0x79, 0x79, 0x78, 0x66, 0x6f, 0x6d, 0x79, 0x67, 0x6f,
+ 0x74, 0x61, 0x66, 0x78, 0x6f, 0x77, 0x6b, 0x77, 0x66, 0x6a, 0x63, 0x61, 0x75, 0x69, 0x77, 0x62,
+ 0x72, 0x77, 0x74, 0x66, 0x67, 0x6b, 0x63, 0x61, 0x71, 0x77, 0x63, 0x75, 0x67, 0x72, 0x67, 0x67,
+ 0x76, 0x73, 0x61, 0x72, 0x72, 0x61, 0x75, 0x6a, 0x68, 0x67, 0x75, 0x64, 0x79, 0x78, 0x6a, 0x61,
+ 0x73, 0x6c, 0x6f, 0x62, 0x64, 0x73, 0x69, 0x79, 0x71, 0x79, 0x65, 0x72, 0x79, 0x6c, 0x6c, 0x6f,
+ 0x71, 0x70, 0x66, 0x72, 0x77, 0x73, 0x62, 0x66, 0x66, 0x78, 0x79, 0x72, 0x71, 0x73, 0x64, 0x68,
+ 0x6b, 0x6e, 0x6f, 0x6e, 0x67, 0x73, 0x6c, 0x6a, 0x74, 0x74, 0x6a, 0x6a, 0x74, 0x64, 0x70, 0x62,
+ 0x79, 0x75, 0x61, 0x6d, 0x6b, 0x70, 0x70, 0x6c, 0x6a, 0x73, 0x62, 0x72, 0x72, 0x76, 0x72, 0x66,
+ 0x78, 0x66, 0x78, 0x78, 0x75, 0x70, 0x6d, 0x6a, 0x70, 0x66, 0x65, 0x6f, 0x72, 0x76, 0x6c, 0x67,
+ 0x76, 0x69, 0x73, 0x74, 0x76, 0x63, 0x76, 0x75, 0x70, 0x76, 0x69, 0x6f, 0x65, 0x70, 0x72, 0x6a,
+ 0x6b, 0x68, 0x6d, 0x6a, 0x71, 0x79, 0x72, 0x6a, 0x74, 0x68, 0x64, 0x72, 0x76, 0x65, 0x6e, 0x63,
+ 0x66, 0x6a, 0x61, 0x66, 0x71, 0x69, 0x62, 0x69, 0x76, 0x66, 0x71, 0x67, 0x73, 0x6f, 0x6c, 0x61,
+ 0x62, 0x63, 0x69, 0x6f, 0x64, 0x70, 0x6e, 0x66, 0x70, 0x68, 0x70, 0x6d, 0x77, 0x66, 0x74, 0x73,
+ 0x64, 0x64, 0x6f, 0x64, 0x68, 0x63, 0x79, 0x72, 0x70, 0x6c, 0x76, 0x64, 0x66, 0x74, 0x70, 0x6b,
+ 0x78, 0x6a, 0x63, 0x6a, 0x61, 0x69, 0x74, 0x61, 0x6b, 0x6a, 0x62, 0x63, 0x71, 0x6b, 0x6e, 0x6f,
+ 0x67, 0x77, 0x61, 0x64, 0x79, 0x73, 0x6c, 0x64, 0x64, 0x64, 0x74, 0x71, 0x6a, 0x73, 0x64, 0x6b,
+ 0x65, 0x6a, 0x79, 0x78, 0x70, 0x6e, 0x72, 0x71, 0x66, 0x79, 0x78, 0x77, 0x76, 0x61, 0x78, 0x69,
+ 0x6f, 0x76, 0x71, 0x70, 0x6b, 0x75, 0x69, 0x75, 0x72, 0x6f, 0x66, 0x65, 0x66, 0x69, 0x79, 0x67,
+ 0x71, 0x76, 0x76, 0x79, 0x71, 0x6b, 0x74, 0x6f, 0x77, 0x61, 0x77, 0x63, 0x71, 0x75, 0x72, 0x73,
+ 0x63, 0x6d, 0x72, 0x6e, 0x73, 0x66, 0x62, 0x70, 0x66, 0x79, 0x77, 0x73, 0x61, 0x69, 0x6a, 0x6a,
+ 0x6c, 0x69, 0x69, 0x69, 0x62, 0x63, 0x63, 0x76, 0x74, 0x6d, 0x6e, 0x72, 0x69, 0x6d, 0x67, 0x76,
+ 0x6a, 0x72, 0x73, 0x61, 0x61, 0x6f, 0x6f, 0x67, 0x78, 0x74, 0x76, 0x77, 0x62, 0x73, 0x64, 0x74,
+ 0x69, 0x76, 0x61, 0x69, 0x65, 0x70, 0x76, 0x73, 0x6f, 0x70, 0x77, 0x73, 0x75, 0x72, 0x68, 0x76,
+ 0x73, 0x62, 0x78, 0x74, 0x78, 0x74, 0x69, 0x71, 0x69, 0x77, 0x6c, 0x68, 0x6d, 0x6a, 0x65, 0x75,
+ 0x70, 0x79, 0x6c, 0x76, 0x62, 0x64, 0x68, 0x62, 0x70, 0x72, 0x6d, 0x65, 0x70, 0x67, 0x65, 0x73,
+ 0x6f, 0x77, 0x66, 0x63, 0x74, 0x77, 0x68, 0x6e, 0x74, 0x6a, 0x76, 0x70, 0x79, 0x77, 0x72, 0x67,
+ 0x65, 0x68, 0x71, 0x66, 0x70, 0x76, 0x67, 0x6e, 0x65, 0x68, 0x77, 0x61, 0x6c, 0x76, 0x76, 0x75,
+ 0x6f, 0x78, 0x77, 0x77, 0x6c, 0x65, 0x73, 0x76, 0x6b, 0x64, 0x70, 0x6f, 0x6a, 0x79, 0x6d, 0x73,
+ 0x6e, 0x64, 0x62, 0x6d, 0x79, 0x63, 0x72, 0x71, 0x68, 0x61, 0x74, 0x62, 0x64, 0x63, 0x72, 0x73,
+ 0x62, 0x79, 0x73, 0x66, 0x66, 0x6e, 0x79, 0x61, 0x70, 0x6b, 0x6a, 0x6e, 0x62, 0x79, 0x6b, 0x64,
+ 0x68, 0x65, 0x66, 0x62, 0x74, 0x63, 0x76, 0x71, 0x73, 0x77, 0x6d, 0x73, 0x71, 0x66, 0x64, 0x6d,
+ 0x71, 0x68, 0x68, 0x77, 0x74, 0x61, 0x79, 0x70, 0x74, 0x66, 0x65, 0x71, 0x74, 0x66, 0x63, 0x73,
+ 0x6c, 0x68, 0x64, 0x75, 0x72, 0x62, 0x72, 0x72, 0x6e, 0x71, 0x6e, 0x69, 0x75, 0x72, 0x71, 0x63,
+ 0x75, 0x65, 0x79, 0x73, 0x65, 0x62, 0x67, 0x62, 0x70, 0x61, 0x62, 0x74, 0x69, 0x6b, 0x6d, 0x6c,
+ 0x65, 0x6a, 0x78, 0x63, 0x72, 0x6f, 0x66, 0x62, 0x77, 0x62, 0x75, 0x69, 0x6f, 0x70, 0x6c, 0x68,
+ 0x6a, 0x78, 0x73, 0x61, 0x66, 0x79, 0x6f, 0x6e, 0x73, 0x67, 0x76, 0x79, 0x64, 0x62, 0x6f, 0x66,
+ 0x63, 0x6b, 0x6c, 0x75, 0x74, 0x77, 0x6a, 0x66, 0x75, 0x63, 0x77, 0x76, 0x6b, 0x6d, 0x69, 0x77,
+ 0x71, 0x61, 0x65, 0x72, 0x66, 0x6d, 0x70, 0x73, 0x68, 0x73, 0x74, 0x77, 0x6e, 0x73, 0x74, 0x76,
+ 0x63, 0x75, 0x72, 0x63, 0x66, 0x6d, 0x67, 0x72, 0x61, 0x69, 0x61, 0x6b, 0x69, 0x74, 0x77, 0x68,
+ 0x74, 0x6e, 0x73, 0x77, 0x66, 0x65, 0x62, 0x6a, 0x6d, 0x66, 0x71, 0x6c, 0x78, 0x79, 0x65, 0x66,
+ 0x62, 0x68, 0x72, 0x61, 0x6e, 0x6a, 0x79, 0x6e, 0x70, 0x79, 0x70, 0x68, 0x71, 0x77, 0x69, 0x6f,
+ 0x63, 0x66, 0x67, 0x77, 0x71, 0x6b, 0x6b, 0x62, 0x71, 0x67, 0x66, 0x6b, 0x65, 0x65, 0x78, 0x75,
+ 0x75, 0x74, 0x75, 0x71, 0x68, 0x72, 0x64, 0x6b, 0x6e, 0x6d, 0x69, 0x62, 0x64, 0x68, 0x73, 0x63,
+ 0x61, 0x74, 0x6e, 0x77, 0x6a, 0x6f, 0x77, 0x74, 0x63, 0x75, 0x6f, 0x70, 0x75, 0x61, 0x67, 0x68,
+ 0x68, 0x72, 0x6b, 0x73, 0x73, 0x66, 0x6f, 0x79, 0x64, 0x77, 0x68, 0x74, 0x71, 0x6d, 0x69, 0x73,
+ 0x71, 0x62, 0x76, 0x77, 0x68, 0x68, 0x79, 0x75, 0x6c, 0x75, 0x79, 0x6e, 0x78, 0x6f, 0x66, 0x71,
+ 0x65, 0x6a, 0x62, 0x67, 0x75, 0x74, 0x6f, 0x64, 0x78, 0x6a, 0x63, 0x73, 0x72, 0x63, 0x68, 0x6b,
+ 0x69, 0x70, 0x6c, 0x73, 0x65, 0x6d, 0x69, 0x63, 0x74, 0x77, 0x6c, 0x6b, 0x78, 0x65, 0x75, 0x6b,
+ 0x6a, 0x77, 0x73, 0x77, 0x77, 0x64, 0x61, 0x69, 0x75, 0x76, 0x77, 0x78, 0x61, 0x6e, 0x71, 0x78,
+ 0x65, 0x77, 0x76, 0x71, 0x70, 0x6d, 0x6d, 0x65, 0x69, 0x71, 0x65, 0x66, 0x74, 0x6c, 0x61, 0x66,
+ 0x6c, 0x62, 0x76, 0x73, 0x77, 0x66, 0x6a, 0x65, 0x79, 0x71, 0x6b, 0x67, 0x68, 0x6e, 0x72, 0x71,
+ 0x73, 0x71, 0x62, 0x71, 0x74, 0x6d, 0x75, 0x6e, 0x6e, 0x6f, 0x75, 0x73, 0x76, 0x6c, 0x68, 0x6e,
+ 0x79, 0x6e, 0x79, 0x74, 0x79, 0x79, 0x79, 0x74, 0x66, 0x77, 0x6d, 0x75, 0x6e, 0x67, 0x68, 0x68,
+ 0x6c, 0x76, 0x68, 0x65, 0x68, 0x6f, 0x76, 0x71, 0x69, 0x68, 0x6f, 0x6c, 0x66, 0x74, 0x6d, 0x73,
+ 0x70, 0x76, 0x61, 0x65, 0x73, 0x62, 0x79, 0x76, 0x6c, 0x69, 0x76, 0x76, 0x79, 0x6a, 0x77, 0x65,
+ 0x68, 0x6d, 0x61, 0x75, 0x6f, 0x6c, 0x66, 0x69, 0x70, 0x73, 0x62, 0x73, 0x6e, 0x72, 0x77, 0x6d,
+ 0x68, 0x67, 0x6d, 0x75, 0x74, 0x67, 0x69, 0x6e, 0x69, 0x65, 0x72, 0x63, 0x64, 0x75, 0x63, 0x63,
+ 0x6a, 0x62, 0x67, 0x74, 0x6b, 0x74, 0x77, 0x73, 0x77, 0x73, 0x65, 0x69, 0x71, 0x63, 0x63, 0x6f,
+ 0x64, 0x63, 0x79, 0x6c, 0x75, 0x74, 0x6b, 0x70, 0x78, 0x62, 0x69, 0x69, 0x6a, 0x72, 0x63, 0x64,
+ 0x62, 0x78, 0x6e, 0x74, 0x6d, 0x66, 0x73, 0x75, 0x77, 0x6c, 0x6a, 0x77, 0x78, 0x62, 0x67, 0x78,
+ 0x70, 0x64, 0x77, 0x6b, 0x6b, 0x77, 0x68, 0x75, 0x62, 0x67, 0x73, 0x76, 0x61, 0x61, 0x71, 0x63,
+ 0x75, 0x70, 0x6a, 0x78, 0x6d, 0x6a, 0x76, 0x72, 0x76, 0x63, 0x66, 0x6c, 0x6e, 0x77, 0x79, 0x6f,
+ 0x69, 0x65, 0x65, 0x65, 0x69, 0x6e, 0x71, 0x79, 0x64, 0x71, 0x72, 0x75, 0x6f, 0x70, 0x61, 0x65,
+ 0x75, 0x6f, 0x70, 0x6b, 0x78, 0x79, 0x6a, 0x6c, 0x78, 0x62, 0x6d, 0x6d, 0x64, 0x62, 0x6e, 0x68,
+ 0x79, 0x64, 0x79, 0x74, 0x61, 0x65, 0x6a, 0x68, 0x6f, 0x62, 0x62, 0x65, 0x73, 0x71, 0x6e, 0x77,
+ 0x76, 0x63, 0x62, 0x74, 0x74, 0x74, 0x6b, 0x6d, 0x79, 0x78, 0x69, 0x75, 0x69, 0x6f, 0x62, 0x6b,
+ 0x6a, 0x75, 0x77, 0x67, 0x71, 0x6d, 0x67, 0x70, 0x6d, 0x65, 0x6b, 0x70, 0x6d, 0x70, 0x74, 0x78,
+ 0x61, 0x68, 0x72, 0x6d, 0x78, 0x79, 0x6d, 0x77, 0x66, 0x68, 0x73, 0x73, 0x64, 0x71, 0x64, 0x64,
+ 0x6e, 0x72, 0x66, 0x74, 0x72, 0x65, 0x75, 0x79, 0x6c, 0x6c, 0x68, 0x72, 0x6c, 0x71, 0x6b, 0x6c,
+ 0x70, 0x61, 0x79, 0x76, 0x72, 0x6a, 0x65, 0x71, 0x72, 0x76, 0x71, 0x6e, 0x74, 0x75, 0x62, 0x64,
+ 0x67, 0x6c, 0x65, 0x78, 0x75, 0x67, 0x6f, 0x79, 0x64, 0x69, 0x66, 0x67, 0x6f, 0x64, 0x62, 0x72,
+ 0x73, 0x79, 0x70, 0x68, 0x63, 0x61, 0x64, 0x6a, 0x6f, 0x6d, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x6e,
+ 0x6f, 0x74, 0x61, 0x6e, 0x6c, 0x62, 0x6f, 0x64, 0x62, 0x76, 0x6c, 0x74, 0x68, 0x79, 0x70, 0x6a,
+ 0x68, 0x71, 0x71, 0x6b, 0x6c, 0x66, 0x67, 0x6e, 0x61, 0x68, 0x6a, 0x6f, 0x65, 0x77, 0x64, 0x70,
+ 0x6c, 0x65, 0x63, 0x66, 0x6b, 0x65, 0x63, 0x62, 0x79, 0x6f, 0x79, 0x63, 0x77, 0x70, 0x61, 0x67,
+ 0x65, 0x73, 0x67, 0x6e, 0x74, 0x6c, 0x67, 0x6e, 0x64, 0x71, 0x75, 0x61, 0x70, 0x70, 0x6c, 0x68,
+ 0x64, 0x65, 0x63, 0x6c, 0x6e, 0x68, 0x6c, 0x67, 0x70, 0x64, 0x63, 0x65, 0x76, 0x78, 0x78, 0x78,
+ 0x68, 0x65, 0x61, 0x79, 0x77, 0x6d, 0x72, 0x72, 0x6f, 0x79, 0x67, 0x78, 0x6d, 0x6d, 0x67, 0x71,
+ 0x75, 0x70, 0x72, 0x69, 0x68, 0x75, 0x6f, 0x70, 0x63, 0x66, 0x65, 0x69, 0x75, 0x64, 0x75, 0x72,
+ 0x6b, 0x67, 0x75, 0x6b, 0x67, 0x6f, 0x6d, 0x65, 0x6d, 0x63, 0x73, 0x79, 0x61, 0x6e, 0x65, 0x69,
+ 0x64, 0x6c, 0x73, 0x75, 0x69, 0x66, 0x79, 0x65, 0x61, 0x68, 0x76, 0x70, 0x62, 0x76, 0x78, 0x72,
+ 0x6b, 0x74, 0x73, 0x6b, 0x66, 0x63, 0x6c, 0x79, 0x68, 0x72, 0x78, 0x6a, 0x62, 0x70, 0x73, 0x6a,
+ 0x68, 0x73, 0x67, 0x67, 0x64, 0x70, 0x77, 0x69, 0x71, 0x65, 0x6f, 0x6c, 0x68, 0x61, 0x6f, 0x64,
+ 0x6c, 0x68, 0x6d, 0x64, 0x79, 0x74, 0x78, 0x63, 0x68, 0x62, 0x64, 0x61, 0x70, 0x78, 0x6e, 0x74,
+ 0x6b, 0x71, 0x67, 0x73, 0x71, 0x73, 0x62, 0x61, 0x64, 0x6a, 0x6c, 0x6e, 0x77, 0x70, 0x66, 0x65,
+ 0x6b, 0x64, 0x66, 0x6d, 0x6d, 0x6a, 0x69, 0x65, 0x65, 0x71, 0x66, 0x62, 0x6f, 0x74, 0x6c, 0x6e,
+ 0x65, 0x73, 0x75, 0x6f, 0x78, 0x62, 0x68, 0x72, 0x65, 0x6c, 0x6f, 0x6a, 0x70, 0x77, 0x64, 0x6b,
+ 0x6d, 0x73, 0x71, 0x68, 0x6b, 0x61, 0x6b, 0x69, 0x73, 0x65, 0x6d, 0x61, 0x70, 0x79, 0x6f, 0x76,
+ 0x62, 0x67, 0x78, 0x61, 0x6d, 0x63, 0x6f, 0x70, 0x66, 0x6e, 0x65, 0x65, 0x62, 0x62, 0x6b, 0x73,
+ 0x64, 0x6c, 0x78, 0x71, 0x62, 0x76, 0x65, 0x6e, 0x71, 0x73, 0x6e, 0x75, 0x6d, 0x71, 0x6e, 0x75,
+ 0x73, 0x6a, 0x74, 0x75, 0x6d, 0x68, 0x6f, 0x69, 0x6a, 0x73, 0x6b, 0x75, 0x70, 0x75, 0x69, 0x6a,
+ 0x71, 0x6a, 0x73, 0x71, 0x6c, 0x66, 0x70, 0x63, 0x75, 0x6d, 0x6f, 0x65, 0x71, 0x75, 0x77, 0x61,
+ 0x63, 0x78, 0x6f, 0x78, 0x6c, 0x69, 0x76, 0x6b, 0x65, 0x79, 0x67, 0x74, 0x77, 0x65, 0x64, 0x6f,
+ 0x74, 0x79, 0x6f, 0x74, 0x6e, 0x74, 0x66, 0x6e, 0x69, 0x70, 0x77, 0x68, 0x78, 0x73, 0x66, 0x6a,
+ 0x65, 0x6f, 0x6b, 0x64, 0x6c, 0x73, 0x75, 0x64, 0x64, 0x6b, 0x68, 0x62, 0x77, 0x72, 0x75, 0x76,
+ 0x75, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x64, 0x77, 0x62, 0x65, 0x66, 0x65, 0x6a, 0x71, 0x69, 0x71,
+ 0x78, 0x65, 0x77, 0x77, 0x79, 0x66, 0x67, 0x72, 0x6d, 0x6c, 0x68, 0x6a, 0x63, 0x79, 0x79, 0x72,
+ 0x73, 0x62, 0x62, 0x77, 0x6e, 0x6c, 0x79, 0x75, 0x6f, 0x78, 0x68, 0x6a, 0x64, 0x6c, 0x62, 0x67,
+ 0x65, 0x6c, 0x65, 0x64, 0x65, 0x70, 0x75, 0x68, 0x64, 0x72, 0x71, 0x62, 0x66, 0x74, 0x70, 0x77,
+ 0x63, 0x6d, 0x76, 0x63, 0x78, 0x64, 0x76, 0x75, 0x72, 0x6e, 0x65, 0x68, 0x71, 0x78, 0x73, 0x62,
+ 0x77, 0x6c, 0x6f, 0x63, 0x74, 0x64, 0x71, 0x62, 0x79, 0x78, 0x70, 0x6a, 0x69, 0x6c, 0x73, 0x68,
+ 0x6c, 0x6a, 0x6b, 0x6f, 0x73, 0x6a, 0x6e, 0x62, 0x73, 0x66, 0x6f, 0x67, 0x76, 0x74, 0x6c, 0x78,
+ 0x63, 0x6c, 0x76, 0x77, 0x6c, 0x6c, 0x74, 0x71, 0x6b, 0x66, 0x66, 0x63, 0x61, 0x68, 0x6c, 0x76,
+ 0x68, 0x72, 0x72, 0x6c, 0x6b, 0x61, 0x6f, 0x6c, 0x72, 0x6b, 0x6b, 0x78, 0x77, 0x78, 0x61, 0x68,
+ 0x63, 0x66, 0x6a, 0x68, 0x78, 0x74, 0x71, 0x68, 0x64, 0x69, 0x6d, 0x75, 0x72, 0x6d, 0x78, 0x6c,
+ 0x6a, 0x68, 0x61, 0x74, 0x69, 0x64, 0x67, 0x71, 0x62, 0x67, 0x6b, 0x6f, 0x6e, 0x63, 0x64, 0x73,
+ 0x72, 0x6c, 0x6c, 0x78, 0x64, 0x70, 0x76, 0x79, 0x69, 0x61, 0x76, 0x6d, 0x72, 0x65, 0x64, 0x75,
+ 0x64, 0x77, 0x70, 0x64, 0x71, 0x73, 0x77, 0x75, 0x61, 0x6b, 0x76, 0x6e, 0x62, 0x70, 0x75, 0x69,
+ 0x6e, 0x73, 0x74, 0x66, 0x6d, 0x6c, 0x6b, 0x70, 0x67, 0x66, 0x6f, 0x75, 0x65, 0x69, 0x78, 0x67,
+ 0x68, 0x78, 0x67, 0x6b, 0x6a, 0x68, 0x72, 0x71, 0x72, 0x71, 0x77, 0x6c, 0x74, 0x64, 0x79, 0x74,
+ 0x73, 0x6d, 0x73, 0x6f, 0x79, 0x62, 0x79, 0x71, 0x6c, 0x73, 0x73, 0x6a, 0x67, 0x6e, 0x72, 0x69,
+ 0x75, 0x71, 0x62, 0x72, 0x65, 0x63, 0x6b, 0x63, 0x79, 0x76, 0x74, 0x79, 0x79, 0x67, 0x77, 0x79,
+ 0x66, 0x64, 0x72, 0x73, 0x61, 0x6f, 0x62, 0x72, 0x76, 0x66, 0x62, 0x76, 0x73, 0x68, 0x67, 0x63,
+ 0x72, 0x64, 0x6b, 0x74, 0x6c, 0x6b, 0x78, 0x6f, 0x64, 0x6a, 0x69, 0x76, 0x67, 0x75, 0x73, 0x70,
+ 0x78, 0x73, 0x75, 0x67, 0x71, 0x71, 0x74, 0x65, 0x65, 0x6d, 0x70, 0x6e, 0x74, 0x64, 0x77, 0x68,
+ 0x78, 0x72, 0x6e, 0x71, 0x73, 0x70, 0x6f, 0x6a, 0x6a, 0x6f, 0x69, 0x70, 0x63, 0x6b, 0x71, 0x6e,
+ 0x77, 0x79, 0x6c, 0x6e, 0x73, 0x6f, 0x63, 0x71, 0x67, 0x65, 0x77, 0x6d, 0x75, 0x6d, 0x64, 0x67,
+ 0x64, 0x65, 0x73, 0x73, 0x64, 0x74, 0x61, 0x66, 0x73, 0x69, 0x69, 0x65, 0x68, 0x66, 0x6e, 0x67,
+ 0x69, 0x6d, 0x66, 0x65, 0x78, 0x79, 0x72, 0x61, 0x6b, 0x68, 0x64, 0x75, 0x67, 0x67, 0x71, 0x76,
+ 0x76, 0x75, 0x79, 0x71, 0x62, 0x76, 0x61, 0x77, 0x71, 0x76, 0x76, 0x67, 0x70, 0x69, 0x62, 0x6e,
+ 0x6e, 0x65, 0x65, 0x67, 0x75, 0x6a, 0x70, 0x70, 0x71, 0x68, 0x71, 0x6b, 0x61, 0x6c, 0x74, 0x6a,
+ 0x6b, 0x63, 0x70, 0x72, 0x6c, 0x73, 0x79, 0x77, 0x74, 0x67, 0x71, 0x72, 0x65, 0x61, 0x72, 0x67,
+ 0x66, 0x6d, 0x69, 0x65, 0x75, 0x61, 0x6d, 0x69, 0x77, 0x6c, 0x76, 0x71, 0x64, 0x6f, 0x79, 0x69,
+ 0x77, 0x6a, 0x68, 0x73, 0x65, 0x6a, 0x75, 0x6f, 0x75, 0x6a, 0x63, 0x67, 0x6c, 0x6d, 0x78, 0x74,
+ 0x74, 0x75, 0x72, 0x6a, 0x64, 0x74, 0x72, 0x75, 0x63, 0x6f, 0x72, 0x6f, 0x6b, 0x65, 0x64, 0x76,
+ 0x79, 0x6d, 0x78, 0x71, 0x61, 0x61, 0x79, 0x6d, 0x77, 0x79, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x72,
+ 0x74, 0x70, 0x64, 0x72, 0x6a, 0x78, 0x6c, 0x61, 0x6d, 0x71, 0x6b, 0x6a, 0x64, 0x70, 0x62, 0x6a,
+ 0x67, 0x69, 0x64, 0x6e, 0x6b, 0x62, 0x61, 0x6a, 0x74, 0x61, 0x69, 0x78, 0x75, 0x78, 0x72, 0x69,
+ 0x6d, 0x6e, 0x79, 0x63, 0x70, 0x68, 0x78, 0x6d, 0x79, 0x64, 0x63, 0x6e, 0x62, 0x6e, 0x65, 0x6f,
+ 0x6c, 0x79, 0x71, 0x70, 0x6a, 0x68, 0x70, 0x75, 0x6e, 0x64, 0x72, 0x79, 0x67, 0x77, 0x63, 0x68,
+ 0x72, 0x79, 0x65, 0x78, 0x64, 0x77, 0x6e, 0x6d, 0x62, 0x71, 0x79, 0x75, 0x6b, 0x63, 0x72, 0x71,
+ 0x65, 0x69, 0x6c, 0x68, 0x66, 0x62, 0x61, 0x79, 0x6c, 0x67, 0x61, 0x78, 0x76, 0x6c, 0x6d, 0x75,
+ 0x73, 0x6d, 0x6a, 0x6c, 0x6e, 0x66, 0x70, 0x61, 0x6f, 0x6e, 0x6b, 0x70, 0x69, 0x6b, 0x61, 0x75,
+ 0x6d, 0x73, 0x6b, 0x61, 0x63, 0x72, 0x73, 0x65, 0x6a, 0x77, 0x6b, 0x78, 0x68, 0x6e, 0x6f, 0x78,
+ 0x69, 0x6b, 0x67, 0x63, 0x73, 0x76, 0x6f, 0x67, 0x63, 0x71, 0x6d, 0x67, 0x62, 0x6e, 0x76, 0x71,
+ 0x71, 0x78, 0x78, 0x68, 0x78, 0x63, 0x65, 0x72, 0x6f, 0x6b, 0x75, 0x6a, 0x76, 0x6d, 0x79, 0x68,
+ 0x75, 0x78, 0x77, 0x75, 0x6d, 0x70, 0x6e, 0x71, 0x76, 0x77, 0x76, 0x76, 0x70, 0x77, 0x72, 0x61,
+ 0x6a, 0x62, 0x71, 0x67, 0x67, 0x73, 0x71, 0x75, 0x6a, 0x73, 0x66, 0x6e, 0x64, 0x76, 0x6a, 0x65,
+ 0x76, 0x66, 0x6e, 0x68, 0x67, 0x78, 0x79, 0x66, 0x65, 0x6d, 0x6d, 0x71, 0x73, 0x66, 0x63, 0x79,
+ 0x6c, 0x72, 0x6a, 0x6f, 0x78, 0x76, 0x6d, 0x78, 0x63, 0x6b, 0x67, 0x70, 0x78, 0x76, 0x61, 0x62,
+ 0x6e, 0x76, 0x75, 0x76, 0x74, 0x70, 0x75, 0x61, 0x77, 0x65, 0x75, 0x6b, 0x65, 0x74, 0x76, 0x78,
+ 0x66, 0x6f, 0x6a, 0x72, 0x72, 0x70, 0x66, 0x70, 0x63, 0x73, 0x78, 0x6e, 0x74, 0x77, 0x78, 0x68,
+ 0x61, 0x6a, 0x61, 0x75, 0x74, 0x75, 0x6b, 0x62, 0x6c, 0x6a, 0x72, 0x79, 0x73, 0x79, 0x6b, 0x6f,
+ 0x77, 0x6b, 0x75, 0x74, 0x76, 0x74, 0x64, 0x79, 0x64, 0x74, 0x64, 0x77, 0x71, 0x6b, 0x75, 0x72,
+ 0x66, 0x75, 0x61, 0x79, 0x78, 0x6a, 0x69, 0x6a, 0x68, 0x6a, 0x6c, 0x77, 0x68, 0x67, 0x77, 0x73,
+ 0x76, 0x6e, 0x65, 0x6d, 0x6f, 0x6a, 0x6e, 0x61, 0x6e, 0x6c, 0x74, 0x6b, 0x70, 0x70, 0x75, 0x66,
+ 0x70, 0x72, 0x76, 0x69, 0x77, 0x6b, 0x76, 0x68, 0x6e, 0x6b, 0x77, 0x64, 0x76, 0x61, 0x6b, 0x6d,
+ 0x77, 0x6f, 0x6a, 0x6a, 0x62, 0x6b, 0x79, 0x73, 0x6a, 0x6a, 0x76, 0x62, 0x64, 0x69, 0x6e, 0x6a,
+ 0x6e, 0x6a, 0x6b, 0x75, 0x6f, 0x61, 0x72, 0x6d, 0x79, 0x66, 0x71, 0x77, 0x6e, 0x72, 0x68, 0x74,
+ 0x69, 0x6d, 0x6b, 0x70, 0x65, 0x77, 0x65, 0x64, 0x66, 0x77, 0x6b, 0x71, 0x6c, 0x66, 0x70, 0x75,
+ 0x63, 0x63, 0x62, 0x65, 0x64, 0x65, 0x75, 0x6a, 0x6b, 0x67, 0x69, 0x64, 0x77, 0x71, 0x65, 0x70,
+ 0x78, 0x67, 0x63, 0x62, 0x79, 0x74, 0x75, 0x73, 0x72, 0x70, 0x63, 0x72, 0x77, 0x66, 0x6f, 0x73,
+ 0x66, 0x6e, 0x61, 0x69, 0x62, 0x75, 0x79, 0x71, 0x68, 0x77, 0x6f, 0x79, 0x67, 0x76, 0x62, 0x67,
+ 0x78, 0x63, 0x70, 0x67, 0x62, 0x69, 0x6b, 0x75, 0x78, 0x77, 0x6d, 0x71, 0x78, 0x63, 0x77, 0x78,
+ 0x61, 0x61, 0x75, 0x74, 0x6b, 0x77, 0x62, 0x71, 0x70, 0x74, 0x6d, 0x6e, 0x62, 0x71, 0x73, 0x71,
+ 0x78, 0x76, 0x79, 0x68, 0x61, 0x73, 0x78, 0x61, 0x77, 0x77, 0x62, 0x67, 0x77, 0x6b, 0x6d, 0x69,
+ 0x77, 0x6a, 0x6a, 0x74, 0x69, 0x64, 0x62, 0x70, 0x6c, 0x6e, 0x75, 0x71, 0x6e, 0x66, 0x72, 0x76,
+ 0x63, 0x63, 0x61, 0x6b, 0x74, 0x62, 0x68, 0x61, 0x70, 0x69, 0x75, 0x64, 0x6a, 0x6b, 0x68, 0x73,
+ 0x6f, 0x6b, 0x67, 0x63, 0x6a, 0x79, 0x79, 0x65, 0x78, 0x78, 0x78, 0x67, 0x73, 0x6d, 0x63, 0x79,
+ 0x6c, 0x75, 0x6e, 0x65, 0x79, 0x66, 0x6d, 0x63, 0x76, 0x6a, 0x6b, 0x67, 0x71, 0x67, 0x69, 0x61,
+ 0x77, 0x71, 0x75, 0x76, 0x76, 0x70, 0x74, 0x6d, 0x69, 0x67, 0x61, 0x66, 0x64, 0x6b, 0x73, 0x66,
+ 0x66, 0x70, 0x65, 0x77, 0x6d, 0x70, 0x6f, 0x61, 0x71, 0x6e, 0x76, 0x69, 0x6a, 0x68, 0x70, 0x71,
+ 0x70, 0x66, 0x6e, 0x6f, 0x70, 0x72, 0x64, 0x78, 0x6f, 0x75, 0x66, 0x69, 0x73, 0x68, 0x71, 0x77,
+ 0x6b, 0x69, 0x73, 0x66, 0x79, 0x6d, 0x64, 0x69, 0x74, 0x66, 0x73, 0x64, 0x6e, 0x63, 0x6b, 0x75,
+ 0x70, 0x70, 0x64, 0x72, 0x71, 0x79, 0x74, 0x71, 0x73, 0x6f, 0x6a, 0x72, 0x6d, 0x72, 0x78, 0x63,
+ 0x73, 0x61, 0x70, 0x6d, 0x69, 0x76, 0x73, 0x64, 0x6c, 0x73, 0x69, 0x61, 0x78, 0x61, 0x78, 0x78,
+ 0x67, 0x75, 0x6a, 0x78, 0x75, 0x6e, 0x6f, 0x61, 0x6e, 0x62, 0x75, 0x74, 0x77, 0x6a, 0x68, 0x70,
+ 0x67, 0x65, 0x72, 0x6c, 0x6e, 0x75, 0x79, 0x6a, 0x72, 0x6b, 0x6b, 0x63, 0x79, 0x77, 0x74, 0x73,
+ 0x6a, 0x6c, 0x6a, 0x69, 0x6b, 0x66, 0x6b, 0x61, 0x6a, 0x72, 0x66, 0x67, 0x73, 0x6c, 0x67, 0x6d,
+ 0x6c, 0x69, 0x6a, 0x6d, 0x6f, 0x64, 0x78, 0x6f, 0x6c, 0x75, 0x74, 0x6c, 0x74, 0x74, 0x64, 0x72,
+ 0x76, 0x6f, 0x62, 0x63, 0x77, 0x66, 0x69, 0x74, 0x70, 0x6e, 0x72, 0x75, 0x6c, 0x77, 0x61, 0x79,
+ 0x78, 0x72, 0x62, 0x75, 0x75, 0x6c, 0x6a, 0x6c, 0x69, 0x70, 0x76, 0x63, 0x6a, 0x74, 0x75, 0x6c,
+ 0x77, 0x6c, 0x75, 0x72, 0x68, 0x79, 0x6b, 0x62, 0x6a, 0x64, 0x63, 0x6b, 0x70, 0x6e, 0x6d, 0x6b,
+ 0x78, 0x6e, 0x77, 0x6c, 0x61, 0x6d, 0x66, 0x6e, 0x62, 0x77, 0x75, 0x76, 0x6c, 0x72, 0x73, 0x6c,
+ 0x61, 0x63, 0x77, 0x75, 0x64, 0x70, 0x76, 0x72, 0x6a, 0x63, 0x62, 0x6d, 0x72, 0x71, 0x62, 0x6e,
+ 0x76, 0x70, 0x66, 0x68, 0x63, 0x68, 0x69, 0x66, 0x6c, 0x72, 0x74, 0x6c, 0x78, 0x74, 0x64, 0x64,
+ 0x74, 0x63, 0x6a, 0x6d, 0x69, 0x6a, 0x74, 0x78, 0x66, 0x68, 0x63, 0x66, 0x76, 0x63, 0x74, 0x67,
+ 0x6e, 0x74, 0x69, 0x66, 0x69, 0x75, 0x63, 0x65, 0x64, 0x62, 0x6f, 0x71, 0x6c, 0x62, 0x79, 0x61,
+ 0x71, 0x6d, 0x76, 0x6e, 0x63, 0x62, 0x66, 0x61, 0x6d, 0x65, 0x74, 0x6e, 0x6a, 0x78, 0x61, 0x73,
+ 0x6e, 0x62, 0x78, 0x72, 0x65, 0x6b, 0x6a, 0x76, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x72, 0x6c, 0x61,
+ 0x64, 0x61, 0x64, 0x69, 0x61, 0x6f, 0x6f, 0x66, 0x6a, 0x70, 0x63, 0x6e, 0x77, 0x6b, 0x77, 0x63,
+ 0x74, 0x62, 0x79, 0x6e, 0x77, 0x6b, 0x70, 0x6d, 0x67, 0x72, 0x66, 0x71, 0x72, 0x6a, 0x6f, 0x73,
+ 0x77, 0x71, 0x77, 0x62, 0x75, 0x78, 0x6b, 0x6a, 0x63, 0x6b, 0x78, 0x67, 0x66, 0x66, 0x61, 0x77,
+ 0x79, 0x65, 0x66, 0x64, 0x73, 0x71, 0x72, 0x77, 0x73, 0x77, 0x77, 0x75, 0x79, 0x73, 0x75, 0x65,
+ 0x75, 0x65, 0x6d, 0x74, 0x75, 0x65, 0x74, 0x67, 0x69, 0x70, 0x6c, 0x6d, 0x74, 0x73, 0x68, 0x6f,
+ 0x61, 0x6c, 0x76, 0x65, 0x6d, 0x6c, 0x6d, 0x64, 0x64, 0x61, 0x73, 0x6f, 0x68, 0x77, 0x6e, 0x6c,
+ 0x6a, 0x77, 0x73, 0x77, 0x64, 0x69, 0x79, 0x6d, 0x75, 0x65, 0x6f, 0x6a, 0x72, 0x68, 0x75, 0x6f,
+ 0x6a, 0x77, 0x69, 0x6c, 0x61, 0x70, 0x69, 0x64, 0x78, 0x73, 0x6e, 0x70, 0x74, 0x75, 0x63, 0x71,
+ 0x77, 0x78, 0x73, 0x69, 0x66, 0x73, 0x73, 0x6a, 0x6e, 0x66, 0x65, 0x67, 0x70, 0x63, 0x6b, 0x6f,
+ 0x76, 0x77, 0x75, 0x74, 0x6d, 0x77, 0x74, 0x6c, 0x74, 0x69, 0x78, 0x6d, 0x6c, 0x75, 0x75, 0x66,
+ 0x76, 0x69, 0x71, 0x69, 0x73, 0x66, 0x78, 0x6e, 0x69, 0x78, 0x69, 0x69, 0x62, 0x71, 0x70, 0x69,
+ 0x70, 0x78, 0x64, 0x6d, 0x67, 0x70, 0x62, 0x67, 0x64, 0x65, 0x71, 0x77, 0x6b, 0x72, 0x6a, 0x71,
+ 0x70, 0x68, 0x70, 0x62, 0x71, 0x71, 0x74, 0x70, 0x73, 0x6d, 0x70, 0x64, 0x67, 0x76, 0x69, 0x74,
+ 0x70, 0x64, 0x72, 0x6a, 0x70, 0x6d, 0x66, 0x69, 0x74, 0x62, 0x66, 0x6a, 0x72, 0x69, 0x62, 0x74,
+ 0x71, 0x77, 0x6e, 0x72, 0x6b, 0x73, 0x66, 0x71, 0x74, 0x6a, 0x6c, 0x68, 0x6b, 0x6a, 0x68, 0x6c,
+ 0x6c, 0x69, 0x6d, 0x67, 0x76, 0x78, 0x61, 0x78, 0x6b, 0x6a, 0x65, 0x74, 0x75, 0x6d, 0x74, 0x71,
+ 0x79, 0x61, 0x6a, 0x75, 0x75, 0x6c, 0x74, 0x6f, 0x72, 0x6f, 0x74, 0x65, 0x75, 0x76, 0x62, 0x74,
+ 0x6f, 0x64, 0x62, 0x6a, 0x67, 0x62, 0x68, 0x6f, 0x6b, 0x75, 0x6a, 0x6c, 0x77, 0x69, 0x78, 0x66,
+ 0x6e, 0x68, 0x70, 0x66, 0x68, 0x77, 0x74, 0x67, 0x6b, 0x68, 0x63, 0x69, 0x76, 0x62, 0x6e, 0x69,
+ 0x64, 0x6d, 0x70, 0x63, 0x6a, 0x78, 0x67, 0x64, 0x69, 0x70, 0x65, 0x6c, 0x61, 0x67, 0x6a, 0x64,
+ 0x67, 0x61, 0x62, 0x76, 0x69, 0x77, 0x70, 0x70, 0x6a, 0x78, 0x70, 0x68, 0x78, 0x65, 0x64, 0x61,
+ 0x69, 0x6e, 0x76, 0x62, 0x64, 0x66, 0x6a, 0x79, 0x63, 0x78, 0x6b, 0x71, 0x78, 0x77, 0x6d, 0x6b,
+ 0x75, 0x72, 0x6f, 0x67, 0x75, 0x69, 0x72, 0x76, 0x66, 0x79, 0x63, 0x77, 0x74, 0x6d, 0x67, 0x6c,
+ 0x70, 0x75, 0x71, 0x78, 0x6f, 0x6d, 0x73, 0x75, 0x64, 0x78, 0x6b, 0x77, 0x6b, 0x77, 0x6f, 0x79,
+ 0x78, 0x6f, 0x73, 0x65, 0x62, 0x61, 0x79, 0x75, 0x74, 0x66, 0x71, 0x74, 0x6e, 0x6b, 0x68, 0x61,
+ 0x74, 0x62, 0x75, 0x65, 0x76, 0x78, 0x6b, 0x75, 0x6b, 0x69, 0x70, 0x74, 0x75, 0x74, 0x6e, 0x6b,
+ 0x68, 0x62, 0x61, 0x65, 0x6b, 0x77, 0x63, 0x66, 0x61, 0x62, 0x6a, 0x73, 0x68, 0x63, 0x61, 0x79,
+ 0x68, 0x70, 0x74, 0x70, 0x73, 0x6d, 0x67, 0x71, 0x6b, 0x73, 0x63, 0x6d, 0x61, 0x6b, 0x69, 0x69,
+ 0x72, 0x65, 0x61, 0x6e, 0x61, 0x78, 0x67, 0x6a, 0x73, 0x67, 0x6a, 0x6c, 0x66, 0x74, 0x6b, 0x75,
+ 0x6a, 0x6b, 0x66, 0x69, 0x68, 0x63, 0x73, 0x65, 0x6b, 0x62, 0x77, 0x68, 0x73, 0x72, 0x6a, 0x67,
+ 0x6a, 0x63, 0x6a, 0x70, 0x77, 0x72, 0x69, 0x69, 0x6d, 0x6b, 0x70, 0x62, 0x79, 0x74, 0x63, 0x74,
+ 0x6d, 0x6c, 0x79, 0x79, 0x76, 0x6e, 0x74, 0x79, 0x6b, 0x6a, 0x70, 0x6b, 0x6f, 0x78, 0x6f, 0x72,
+ 0x77, 0x69, 0x71, 0x62, 0x61, 0x6a, 0x72, 0x6b, 0x6e, 0x78, 0x6e, 0x65, 0x75, 0x61, 0x70, 0x70,
+ 0x71, 0x61, 0x66, 0x6d, 0x65, 0x6c, 0x75, 0x71, 0x70, 0x6e, 0x63, 0x6a, 0x69, 0x61, 0x62, 0x72,
+ 0x77, 0x79, 0x6c, 0x65, 0x70, 0x6d, 0x75, 0x78, 0x6f, 0x78, 0x6f, 0x73, 0x6c, 0x78, 0x61, 0x75,
+ 0x73, 0x63, 0x65, 0x6b, 0x78, 0x61, 0x6d, 0x67, 0x69, 0x71, 0x6e, 0x76, 0x6a, 0x70, 0x70, 0x6b,
+ 0x68, 0x78, 0x73, 0x75, 0x74, 0x70, 0x72, 0x70, 0x61, 0x67, 0x63, 0x78, 0x78, 0x61, 0x68, 0x76,
+ 0x77, 0x64, 0x6d, 0x66, 0x71, 0x69, 0x71, 0x61, 0x6a, 0x6f, 0x6c, 0x6c, 0x62, 0x6a, 0x77, 0x77,
+ 0x77, 0x70, 0x6b, 0x78, 0x68, 0x61, 0x67, 0x6d, 0x72, 0x6b, 0x73, 0x75, 0x70, 0x67, 0x70, 0x73,
+ 0x76, 0x6a, 0x74, 0x76, 0x79, 0x67, 0x6d, 0x61, 0x67, 0x73, 0x6c, 0x6a, 0x79, 0x64, 0x61, 0x76,
+ 0x68, 0x75, 0x76, 0x69, 0x75, 0x72, 0x6e, 0x63, 0x62, 0x63, 0x6c, 0x76, 0x78, 0x6b, 0x79, 0x78,
+ 0x79, 0x79, 0x68, 0x74, 0x6a, 0x71, 0x6c, 0x73, 0x69, 0x69, 0x6c, 0x61, 0x70, 0x74, 0x66, 0x65,
+ 0x71, 0x67, 0x75, 0x6b, 0x66, 0x69, 0x61, 0x72, 0x72, 0x6e, 0x6e, 0x6c, 0x64, 0x65, 0x79, 0x68,
+ 0x6d, 0x66, 0x63, 0x71, 0x6b, 0x73, 0x62, 0x6d, 0x68, 0x72, 0x70, 0x6c, 0x68, 0x64, 0x76, 0x61,
+ 0x77, 0x6a, 0x61, 0x6c, 0x6b, 0x69, 0x63, 0x77, 0x6f, 0x78, 0x63, 0x64, 0x62, 0x63, 0x74, 0x62,
+ 0x69, 0x79, 0x6f, 0x75, 0x6a, 0x6f, 0x73, 0x6a, 0x66, 0x62, 0x6a, 0x6a, 0x76, 0x65, 0x69, 0x6d,
+ 0x78, 0x68, 0x6d, 0x67, 0x78, 0x76, 0x78, 0x73, 0x6e, 0x6f, 0x72, 0x73, 0x72, 0x77, 0x6c, 0x64,
+ 0x6e, 0x74, 0x62, 0x65, 0x61, 0x64, 0x72, 0x75, 0x6a, 0x64, 0x63, 0x67, 0x61, 0x6f, 0x76, 0x76,
+ 0x68, 0x69, 0x73, 0x75, 0x6b, 0x6d, 0x65, 0x69, 0x6d, 0x6a, 0x77, 0x6e, 0x77, 0x67, 0x6a, 0x6b,
+ 0x6d, 0x77, 0x73, 0x62, 0x63, 0x73, 0x6c, 0x62, 0x71, 0x6c, 0x6f, 0x73, 0x6d, 0x61, 0x77, 0x76,
+ 0x64, 0x66, 0x79, 0x6a, 0x6f, 0x76, 0x67, 0x6c, 0x6c, 0x6f, 0x76, 0x72, 0x77, 0x72, 0x6d, 0x64,
+ 0x6b, 0x76, 0x74, 0x69, 0x62, 0x79, 0x63, 0x6b, 0x64, 0x6a, 0x63, 0x75, 0x6d, 0x76, 0x76, 0x62,
+ 0x69, 0x6b, 0x71, 0x65, 0x6c, 0x79, 0x6c, 0x76, 0x64, 0x70, 0x68, 0x6a, 0x6d, 0x75, 0x6e, 0x73,
+ 0x68, 0x77, 0x66, 0x6a, 0x73, 0x61, 0x72, 0x67, 0x6d, 0x63, 0x6a, 0x77, 0x64, 0x61, 0x6b, 0x68,
+ 0x6c, 0x6a, 0x64, 0x73, 0x68, 0x77, 0x67, 0x71, 0x74, 0x72, 0x72, 0x6a, 0x67, 0x66, 0x6d, 0x69,
+ 0x77, 0x72, 0x67, 0x75, 0x76, 0x65, 0x6e, 0x79, 0x6b, 0x71, 0x6c, 0x79, 0x6a, 0x64, 0x66, 0x6a,
+ 0x6f, 0x6c, 0x75, 0x71, 0x71, 0x6e, 0x75, 0x79, 0x68, 0x79, 0x63, 0x71, 0x69, 0x67, 0x69, 0x70,
+ 0x70, 0x67, 0x68, 0x71, 0x68, 0x76, 0x68, 0x78, 0x62, 0x6e, 0x79, 0x73, 0x77, 0x73, 0x66, 0x6c,
+ 0x63, 0x74, 0x71, 0x66, 0x70, 0x6b, 0x75, 0x6d, 0x79, 0x64, 0x77, 0x64, 0x6c, 0x68, 0x62, 0x79,
+ 0x78, 0x62, 0x6f, 0x76, 0x64, 0x62, 0x69, 0x62, 0x77, 0x61, 0x70, 0x67, 0x79, 0x73, 0x66, 0x6d,
+ 0x6d, 0x62, 0x77, 0x70, 0x66, 0x61, 0x79, 0x66, 0x67, 0x65, 0x78, 0x73, 0x65, 0x70, 0x79, 0x71,
+ 0x75, 0x71, 0x77, 0x77, 0x68, 0x6e, 0x6a, 0x6b, 0x72, 0x64, 0x68, 0x67, 0x64, 0x66, 0x6c, 0x62,
+ 0x75, 0x68, 0x64, 0x6f, 0x68, 0x73, 0x76, 0x61, 0x6e, 0x61, 0x77, 0x6f, 0x71, 0x62, 0x62, 0x65,
+ 0x6f, 0x68, 0x6b, 0x76, 0x6c, 0x67, 0x65, 0x6c, 0x74, 0x65, 0x79, 0x66, 0x72, 0x76, 0x74, 0x6f,
+ 0x63, 0x69, 0x6d, 0x6d, 0x78, 0x6c, 0x6d, 0x65, 0x6a, 0x63, 0x72, 0x65, 0x62, 0x6b, 0x66, 0x64,
+ 0x6d, 0x79, 0x72, 0x76, 0x74, 0x6d, 0x6a, 0x66, 0x67, 0x67, 0x61, 0x67, 0x6f, 0x64, 0x76, 0x79,
+ 0x76, 0x69, 0x6e, 0x66, 0x79, 0x73, 0x69, 0x65, 0x76, 0x6a, 0x6f, 0x66, 0x68, 0x64, 0x72, 0x6c,
+ 0x67, 0x6c, 0x79, 0x70, 0x6e, 0x72, 0x61, 0x69, 0x73, 0x6e, 0x65, 0x79, 0x67, 0x63, 0x6d, 0x74,
+ 0x67, 0x75, 0x6c, 0x6c, 0x71, 0x70, 0x62, 0x74, 0x61, 0x61, 0x64, 0x76, 0x69, 0x74, 0x6b, 0x76,
+ 0x76, 0x68, 0x62, 0x62, 0x66, 0x71, 0x6a, 0x72, 0x6a, 0x6b, 0x6c, 0x72, 0x6e, 0x74, 0x74, 0x77,
+ 0x61, 0x77, 0x69, 0x63, 0x6e, 0x6e, 0x68, 0x6c, 0x68, 0x61, 0x76, 0x61, 0x61, 0x75, 0x75, 0x6e,
+ 0x69, 0x70, 0x6d, 0x6c, 0x68, 0x73, 0x71, 0x63, 0x73, 0x61, 0x72, 0x75, 0x6f, 0x75, 0x67, 0x70,
+ 0x65, 0x69, 0x65, 0x77, 0x72, 0x79, 0x77, 0x73, 0x76, 0x6f, 0x77, 0x6a, 0x69, 0x72, 0x69, 0x71,
+ 0x79, 0x63, 0x63, 0x75, 0x6b, 0x69, 0x75, 0x62, 0x63, 0x75, 0x6d, 0x61, 0x6b, 0x6a, 0x63, 0x6f,
+ 0x77, 0x71, 0x69, 0x6b, 0x6e, 0x77, 0x75, 0x68, 0x78, 0x74, 0x70, 0x77, 0x68, 0x67, 0x73, 0x72,
+ 0x76, 0x61, 0x66, 0x68, 0x62, 0x61, 0x6a, 0x6e, 0x73, 0x77, 0x79, 0x61, 0x66, 0x74, 0x6a, 0x61,
+ 0x70, 0x6f, 0x66, 0x75, 0x65, 0x6a, 0x76, 0x66, 0x67, 0x75, 0x6c, 0x79, 0x6d, 0x79, 0x73, 0x79,
+ 0x66, 0x64, 0x61, 0x75, 0x79, 0x6d, 0x66, 0x6a, 0x78, 0x6a, 0x73, 0x76, 0x6a, 0x6a, 0x6d, 0x6f,
+ 0x67, 0x63, 0x66, 0x71, 0x67, 0x69, 0x73, 0x68, 0x6b, 0x6e, 0x6e, 0x6a, 0x70, 0x61, 0x68, 0x6a,
+ 0x77, 0x6d, 0x65, 0x69, 0x6b, 0x67, 0x6e, 0x6f, 0x63, 0x72, 0x79, 0x70, 0x73, 0x6d, 0x75, 0x76,
+ 0x77, 0x6b, 0x6b, 0x72, 0x70, 0x61, 0x74, 0x6c, 0x76, 0x76, 0x76, 0x75, 0x70, 0x72, 0x77, 0x6c,
+ 0x6b, 0x64, 0x66, 0x6f, 0x64, 0x6e, 0x6f, 0x75, 0x64, 0x67, 0x63, 0x71, 0x64, 0x70, 0x79, 0x67,
+ 0x61, 0x70, 0x62, 0x72, 0x71, 0x6d, 0x66, 0x65, 0x6f, 0x66, 0x63, 0x77, 0x6b, 0x78, 0x70, 0x77,
+ 0x65, 0x71, 0x78, 0x66, 0x70, 0x64, 0x76, 0x63, 0x74, 0x6d, 0x62, 0x77, 0x6b, 0x70, 0x6d, 0x6a,
+ 0x64, 0x72, 0x65, 0x61, 0x6e, 0x75, 0x62, 0x6a, 0x66, 0x6d, 0x6f, 0x6e, 0x74, 0x6a, 0x79, 0x67,
+ 0x73, 0x6e, 0x64, 0x74, 0x72, 0x79, 0x64, 0x6a, 0x79, 0x61, 0x61, 0x64, 0x62, 0x66, 0x6f, 0x72,
+ 0x70, 0x72, 0x75, 0x66, 0x77, 0x6e, 0x62, 0x6c, 0x73, 0x64, 0x66, 0x71, 0x69, 0x79, 0x66, 0x74,
+ 0x64, 0x61, 0x70, 0x67, 0x62, 0x69, 0x72, 0x71, 0x61, 0x78, 0x74, 0x77, 0x6b, 0x6f, 0x62, 0x77,
+ 0x6c, 0x75, 0x67, 0x78, 0x67, 0x61, 0x64, 0x76, 0x68, 0x72, 0x68, 0x71, 0x64, 0x63, 0x70, 0x69,
+ 0x6f, 0x75, 0x6e, 0x76, 0x78, 0x6d, 0x69, 0x68, 0x78, 0x62, 0x63, 0x72, 0x65, 0x69, 0x63, 0x72,
+ 0x71, 0x75, 0x71, 0x69, 0x74, 0x65, 0x6b, 0x71, 0x79, 0x6e, 0x6e, 0x74, 0x63, 0x70, 0x71, 0x6a,
+ 0x6a, 0x6e, 0x73, 0x6a, 0x6e, 0x66, 0x63, 0x66, 0x66, 0x63, 0x6f, 0x76, 0x69, 0x78, 0x75, 0x68,
+ 0x65, 0x74, 0x65, 0x6b, 0x68, 0x68, 0x6c, 0x66, 0x79, 0x6d, 0x64, 0x78, 0x6a, 0x69, 0x71, 0x6b,
+ 0x6b, 0x61, 0x69, 0x73, 0x67, 0x78, 0x6d, 0x73, 0x78, 0x6b, 0x62, 0x75, 0x71, 0x76, 0x79, 0x6b,
+ 0x61, 0x73, 0x6d, 0x75, 0x66, 0x63, 0x6f, 0x6c, 0x65, 0x6a, 0x6f, 0x78, 0x63, 0x78, 0x75, 0x6b,
+ 0x78, 0x6e, 0x6c, 0x71, 0x70, 0x75, 0x68, 0x68, 0x6b, 0x78, 0x77, 0x69, 0x73, 0x6c, 0x67, 0x6b,
+ 0x6d, 0x6f, 0x6b, 0x72, 0x77, 0x78, 0x73, 0x68, 0x63, 0x68, 0x69, 0x62, 0x77, 0x72, 0x77, 0x77,
+ 0x73, 0x66, 0x77, 0x6e, 0x68, 0x6a, 0x68, 0x73, 0x6c, 0x6c, 0x6d, 0x73, 0x67, 0x63, 0x64, 0x6d,
+ 0x68, 0x73, 0x69, 0x66, 0x78, 0x64, 0x6e, 0x74, 0x69, 0x71, 0x6f, 0x62, 0x68, 0x6f, 0x76, 0x71,
+ 0x65, 0x63, 0x70, 0x61, 0x68, 0x67, 0x72, 0x79, 0x71, 0x6e, 0x69, 0x68, 0x74, 0x61, 0x6c, 0x6b,
+ 0x6c, 0x6f, 0x63, 0x70, 0x69, 0x71, 0x6d, 0x63, 0x64, 0x6b, 0x79, 0x67, 0x72, 0x75, 0x65, 0x6b,
+ 0x75, 0x61, 0x76, 0x63, 0x61, 0x6d, 0x6e, 0x6d, 0x70, 0x6a, 0x77, 0x66, 0x75, 0x66, 0x68, 0x6d,
+ 0x71, 0x66, 0x6d, 0x6e, 0x64, 0x63, 0x65, 0x6c, 0x72, 0x6f, 0x6f, 0x62, 0x78, 0x6d, 0x67, 0x62,
+ 0x6a, 0x6d, 0x75, 0x67, 0x63, 0x63, 0x61, 0x78, 0x66, 0x78, 0x66, 0x78, 0x6d, 0x66, 0x79, 0x78,
+ 0x72, 0x65, 0x65, 0x79, 0x61, 0x79, 0x70, 0x73, 0x72, 0x73, 0x77, 0x69, 0x62, 0x62, 0x71, 0x61,
+ 0x76, 0x66, 0x73, 0x66, 0x66, 0x62, 0x63, 0x62, 0x6f, 0x63, 0x64, 0x63, 0x6d, 0x6d, 0x75, 0x6d,
+ 0x6f, 0x68, 0x62, 0x62, 0x6e, 0x76, 0x65, 0x6b, 0x6a, 0x69, 0x70, 0x63, 0x75, 0x68, 0x6f, 0x6e,
+ 0x6d, 0x71, 0x66, 0x75, 0x64, 0x79, 0x74, 0x69, 0x6d, 0x6e, 0x78, 0x6c, 0x73, 0x69, 0x73, 0x79,
+ 0x67, 0x6b, 0x6a, 0x6e, 0x63, 0x6f, 0x79, 0x66, 0x62, 0x69, 0x63, 0x71, 0x6c, 0x73, 0x73, 0x63,
+ 0x6c, 0x77, 0x64, 0x6d, 0x67, 0x72, 0x64, 0x6b, 0x75, 0x72, 0x69, 0x70, 0x68, 0x70, 0x62, 0x62,
+ 0x64, 0x78, 0x69, 0x78, 0x6f, 0x67, 0x6e, 0x6c, 0x77, 0x6f, 0x78, 0x65, 0x70, 0x70, 0x6a, 0x68,
+ 0x6e, 0x71, 0x64, 0x61, 0x6d, 0x63, 0x75, 0x75, 0x6e, 0x79, 0x66, 0x63, 0x6e, 0x70, 0x6f, 0x74,
+ 0x77, 0x75, 0x63, 0x6e, 0x71, 0x78, 0x67, 0x74, 0x79, 0x66, 0x71, 0x6b, 0x64, 0x74, 0x6c, 0x79,
+ 0x62, 0x78, 0x6d, 0x67, 0x6b, 0x6a, 0x67, 0x61, 0x63, 0x61, 0x6e, 0x73, 0x61, 0x6b, 0x66, 0x69,
+ 0x74, 0x6e, 0x70, 0x66, 0x6a, 0x66, 0x64, 0x73, 0x66, 0x74, 0x6a, 0x74, 0x63, 0x72, 0x63, 0x73,
+ 0x71, 0x76, 0x6c, 0x64, 0x69, 0x74, 0x6b, 0x73, 0x6c, 0x6d, 0x75, 0x66, 0x62, 0x79, 0x6d, 0x62,
+ 0x70, 0x77, 0x6f, 0x63, 0x6b, 0x69, 0x6c, 0x78, 0x69, 0x78, 0x66, 0x65, 0x68, 0x62, 0x6f, 0x67,
+ 0x65, 0x61, 0x71, 0x6f, 0x69, 0x71, 0x75, 0x74, 0x75, 0x62, 0x69, 0x79, 0x76, 0x78, 0x6a, 0x66,
+ 0x79, 0x6e, 0x6e, 0x73, 0x62, 0x63, 0x77, 0x74, 0x75, 0x71, 0x6d, 0x6d, 0x6d, 0x74, 0x73, 0x6a,
+ 0x78, 0x74, 0x64, 0x6d, 0x79, 0x6c, 0x6f, 0x66, 0x6d, 0x61, 0x6f, 0x70, 0x71, 0x76, 0x79, 0x70,
+ 0x67, 0x71, 0x6d, 0x69, 0x62, 0x66, 0x75, 0x79, 0x71, 0x61, 0x69, 0x6b, 0x68, 0x66, 0x62, 0x66,
+ 0x6c, 0x73, 0x6e, 0x71, 0x62, 0x6c, 0x6e, 0x6d, 0x63, 0x66, 0x73, 0x6d, 0x61, 0x69, 0x75, 0x6a,
+ 0x64, 0x61, 0x72, 0x71, 0x75, 0x73, 0x6d, 0x71, 0x79, 0x68, 0x61, 0x77, 0x74, 0x64, 0x69, 0x6d,
+ 0x6d, 0x61, 0x72, 0x72, 0x76, 0x64, 0x66, 0x70, 0x64, 0x6c, 0x73, 0x6c, 0x75, 0x74, 0x73, 0x66,
+ 0x75, 0x67, 0x77, 0x6d, 0x6f, 0x77, 0x6e, 0x68, 0x67, 0x66, 0x68, 0x6f, 0x6b, 0x68, 0x62, 0x73,
+ 0x64, 0x79, 0x73, 0x75, 0x69, 0x6f, 0x77, 0x71, 0x68, 0x6e, 0x66, 0x78, 0x6f, 0x66, 0x73, 0x68,
+ 0x74, 0x76, 0x6d, 0x6d, 0x67, 0x6d, 0x6d, 0x73, 0x65, 0x66, 0x6b, 0x6d, 0x69, 0x70, 0x72, 0x70,
+ 0x70, 0x70, 0x64, 0x71, 0x75, 0x74, 0x61, 0x78, 0x77, 0x64, 0x6f, 0x79, 0x63, 0x69, 0x6b, 0x64,
+ 0x67, 0x78, 0x6d, 0x65, 0x63, 0x66, 0x73, 0x6d, 0x70, 0x64, 0x77, 0x75, 0x66, 0x61, 0x77, 0x70,
+ 0x63, 0x66, 0x75, 0x65, 0x78, 0x6c, 0x77, 0x73, 0x62, 0x77, 0x75, 0x67, 0x64, 0x72, 0x61, 0x6b,
+ 0x6c, 0x6a, 0x68, 0x79, 0x6a, 0x6b, 0x6b, 0x70, 0x67, 0x74, 0x6b, 0x71, 0x72, 0x65, 0x78, 0x71,
+ 0x74, 0x64, 0x79, 0x79, 0x61, 0x69, 0x68, 0x6c, 0x68, 0x64, 0x67, 0x74, 0x64, 0x67, 0x64, 0x73,
+ 0x6d, 0x6a, 0x6c, 0x61, 0x70, 0x6e, 0x72, 0x62, 0x6d, 0x66, 0x62, 0x77, 0x6e, 0x6e, 0x74, 0x79,
+ 0x62, 0x6d, 0x77, 0x76, 0x65, 0x6c, 0x72, 0x76, 0x79, 0x75, 0x76, 0x78, 0x6f, 0x77, 0x61, 0x75,
+ 0x6c, 0x75, 0x63, 0x65, 0x79, 0x77, 0x69, 0x73, 0x62, 0x71, 0x6a, 0x6e, 0x6b, 0x72, 0x6c, 0x76,
+ 0x6e, 0x62, 0x64, 0x75, 0x62, 0x6e, 0x75, 0x6c, 0x65, 0x78, 0x72, 0x6c, 0x6a, 0x66, 0x6f, 0x6e,
+ 0x74, 0x68, 0x77, 0x64, 0x68, 0x6d, 0x6b, 0x6b, 0x6b, 0x6e, 0x71, 0x76, 0x6f, 0x71, 0x66, 0x75,
+ 0x68, 0x70, 0x73, 0x75, 0x6d, 0x6c, 0x6e, 0x6b, 0x74, 0x75, 0x79, 0x66, 0x69, 0x61, 0x79, 0x61,
+ 0x6d, 0x66, 0x71, 0x67, 0x63, 0x73, 0x63, 0x75, 0x76, 0x68, 0x70, 0x67, 0x78, 0x6f, 0x6c, 0x68,
+ 0x6e, 0x75, 0x69, 0x69, 0x75, 0x78, 0x6f, 0x6b, 0x67, 0x76, 0x79, 0x73, 0x61, 0x72, 0x74, 0x62,
+ 0x64, 0x61, 0x63, 0x64, 0x63, 0x77, 0x6e, 0x6b, 0x78, 0x65, 0x70, 0x73, 0x6b, 0x64, 0x6a, 0x64,
+ 0x76, 0x6b, 0x74, 0x6e, 0x6b, 0x67, 0x64, 0x78, 0x65, 0x71, 0x68, 0x68, 0x74, 0x62, 0x79, 0x75,
+ 0x73, 0x6a, 0x69, 0x72, 0x64, 0x75, 0x61, 0x66, 0x70, 0x66, 0x71, 0x6d, 0x6b, 0x63, 0x62, 0x71,
+ 0x66, 0x65, 0x68, 0x78, 0x77, 0x65, 0x62, 0x78, 0x66, 0x72, 0x67, 0x78, 0x6d, 0x75, 0x6d, 0x75,
+ 0x6a, 0x72, 0x68, 0x6d, 0x71, 0x68, 0x63, 0x6e, 0x76, 0x63, 0x79, 0x66, 0x73, 0x69, 0x6e, 0x6f,
+ 0x70, 0x66, 0x70, 0x62, 0x66, 0x63, 0x6a, 0x61, 0x72, 0x69, 0x79, 0x69, 0x69, 0x74, 0x76, 0x61,
+ 0x61, 0x67, 0x68, 0x72, 0x62, 0x61, 0x64, 0x6b, 0x66, 0x6d, 0x6e, 0x79, 0x79, 0x67, 0x68, 0x79,
+ 0x76, 0x64, 0x65, 0x65, 0x61, 0x6b, 0x6a, 0x6f, 0x6d, 0x6e, 0x63, 0x68, 0x6e, 0x76, 0x71, 0x67,
+ 0x6b, 0x74, 0x70, 0x68, 0x73, 0x77, 0x6c, 0x76, 0x67, 0x6a, 0x77, 0x79, 0x77, 0x74, 0x68, 0x6a,
+ 0x70, 0x6e, 0x6f, 0x62, 0x6f, 0x62, 0x6c, 0x6d, 0x63, 0x6f, 0x77, 0x6e, 0x75, 0x6c, 0x6a, 0x61,
+ 0x68, 0x71, 0x76, 0x64, 0x78, 0x66, 0x66, 0x67, 0x65, 0x6e, 0x74, 0x6e, 0x77, 0x65, 0x6c, 0x67,
+ 0x62, 0x6e, 0x62, 0x6d, 0x6b, 0x69, 0x6c, 0x67, 0x74, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x6d, 0x71,
+ 0x6c, 0x65, 0x6d, 0x74, 0x62, 0x62, 0x6f, 0x64, 0x61, 0x61, 0x70, 0x6a, 0x79, 0x62, 0x62, 0x77,
+ 0x6d, 0x70, 0x79, 0x70, 0x67, 0x69, 0x76, 0x75, 0x66, 0x70, 0x6a, 0x6c, 0x62, 0x71, 0x61, 0x6b,
+ 0x77, 0x68, 0x6d, 0x6b, 0x73, 0x73, 0x68, 0x62, 0x70, 0x71, 0x71, 0x6b, 0x70, 0x68, 0x75, 0x63,
+ 0x77, 0x63, 0x76, 0x62, 0x6a, 0x66, 0x61, 0x77, 0x6f, 0x76, 0x64, 0x75, 0x72, 0x64, 0x6a, 0x70,
+ 0x75, 0x76, 0x65, 0x68, 0x68, 0x63, 0x6c, 0x6f, 0x78, 0x6b, 0x66, 0x68, 0x68, 0x71, 0x79, 0x74,
+ 0x76, 0x68, 0x77, 0x76, 0x79, 0x75, 0x6b, 0x79, 0x61, 0x64, 0x69, 0x6f, 0x6e, 0x68, 0x6d, 0x75,
+ 0x63, 0x71, 0x6b, 0x77, 0x65, 0x68, 0x72, 0x63, 0x64, 0x64, 0x6a, 0x62, 0x6e, 0x6d, 0x72, 0x77,
+ 0x74, 0x71, 0x67, 0x6d, 0x68, 0x61, 0x63, 0x65, 0x6c, 0x64, 0x64, 0x71, 0x75, 0x62, 0x67, 0x69,
+ 0x6d, 0x76, 0x68, 0x62, 0x71, 0x74, 0x65, 0x62, 0x61, 0x6f, 0x70, 0x78, 0x6f, 0x65, 0x78, 0x71,
+ 0x67, 0x77, 0x70, 0x66, 0x65, 0x72, 0x69, 0x79, 0x72, 0x66, 0x62, 0x79, 0x66, 0x62, 0x6d, 0x6b,
+ 0x6b, 0x6b, 0x78, 0x6a, 0x68, 0x66, 0x6f, 0x77, 0x70, 0x75, 0x70, 0x75, 0x78, 0x6d, 0x63, 0x74,
+ 0x61, 0x78, 0x77, 0x65, 0x63, 0x68, 0x6f, 0x6f, 0x74, 0x79, 0x73, 0x6a, 0x6b, 0x6b, 0x67, 0x70,
+ 0x74, 0x77, 0x76, 0x73, 0x75, 0x6a, 0x74, 0x66, 0x6a, 0x73, 0x64, 0x6f, 0x6c, 0x73, 0x6e, 0x75,
+ 0x77, 0x6d, 0x71, 0x71, 0x63, 0x6f, 0x62, 0x75, 0x62, 0x72, 0x72, 0x66, 0x71, 0x63, 0x71, 0x6f,
+ 0x67, 0x71, 0x65, 0x76, 0x71, 0x70, 0x6f, 0x79, 0x73, 0x69, 0x67, 0x64, 0x71, 0x68, 0x73, 0x79,
+ 0x74, 0x68, 0x70, 0x6d, 0x6e, 0x74, 0x6e, 0x79, 0x79, 0x62, 0x65, 0x6f, 0x74, 0x75, 0x61, 0x6b,
+ 0x69, 0x6e, 0x70, 0x6e, 0x70, 0x6b, 0x70, 0x72, 0x78, 0x63, 0x6c, 0x66, 0x67, 0x71, 0x6e, 0x72,
+ 0x65, 0x69, 0x72, 0x6e, 0x75, 0x71, 0x61, 0x6e, 0x64, 0x6b, 0x6a, 0x69, 0x63, 0x62, 0x76, 0x62,
+ 0x6f, 0x61, 0x74, 0x72, 0x66, 0x6b, 0x67, 0x63, 0x6d, 0x66, 0x73, 0x64, 0x65, 0x72, 0x65, 0x73,
+ 0x76, 0x70, 0x62, 0x62, 0x70, 0x71, 0x70, 0x66, 0x78, 0x62, 0x6b, 0x6f, 0x63, 0x6e, 0x74, 0x63,
+ 0x61, 0x63, 0x78, 0x74, 0x79, 0x6e, 0x77, 0x64, 0x6a, 0x73, 0x64, 0x72, 0x6a, 0x68, 0x6a, 0x68,
+ 0x64, 0x62, 0x67, 0x68, 0x6a, 0x75, 0x78, 0x74, 0x73, 0x70, 0x6d, 0x65, 0x75, 0x71, 0x61, 0x6f,
+ 0x6c, 0x78, 0x67, 0x79, 0x66, 0x71, 0x64, 0x75, 0x79, 0x75, 0x77, 0x67, 0x78, 0x69, 0x70, 0x70,
+ 0x74, 0x6d, 0x62, 0x70, 0x68, 0x71, 0x75, 0x6d, 0x67, 0x73, 0x79, 0x64, 0x74, 0x72, 0x67, 0x74,
+ 0x70, 0x6b, 0x67, 0x78, 0x66, 0x6c, 0x77, 0x71, 0x78, 0x6c, 0x75, 0x66, 0x69, 0x67, 0x69, 0x67,
+ 0x79, 0x6c, 0x70, 0x71, 0x6b, 0x6c, 0x67, 0x74, 0x79, 0x79, 0x78, 0x79, 0x63, 0x73, 0x79, 0x6c,
+ 0x62, 0x62, 0x78, 0x62, 0x74, 0x75, 0x61, 0x6d, 0x73, 0x6d, 0x61, 0x64, 0x78, 0x6d, 0x61, 0x6b,
+ 0x70, 0x77, 0x67, 0x63, 0x65, 0x67, 0x62, 0x78, 0x70, 0x6c, 0x6b, 0x63, 0x78, 0x63, 0x66, 0x79,
+ 0x62, 0x6c, 0x73, 0x65, 0x6c, 0x6d, 0x70, 0x67, 0x69, 0x67, 0x6d, 0x61, 0x79, 0x6b, 0x76, 0x66,
+ 0x66, 0x76, 0x6e, 0x62, 0x66, 0x61, 0x77, 0x67, 0x6c, 0x61, 0x6f, 0x61, 0x62, 0x75, 0x64, 0x72,
+ 0x77, 0x76, 0x6d, 0x65, 0x77, 0x65, 0x67, 0x73, 0x64, 0x73, 0x77, 0x68, 0x73, 0x69, 0x74, 0x6a,
+ 0x65, 0x62, 0x77, 0x73, 0x6a, 0x61, 0x64, 0x73, 0x6f, 0x65, 0x75, 0x76, 0x61, 0x63, 0x78, 0x64,
+ 0x69, 0x79, 0x6d, 0x68, 0x69, 0x65, 0x6b, 0x69, 0x6b, 0x62, 0x6d, 0x6d, 0x73, 0x6f, 0x61, 0x70,
+ 0x79, 0x67, 0x6d, 0x6c, 0x61, 0x72, 0x70, 0x79, 0x66, 0x78, 0x61, 0x66, 0x71, 0x74, 0x6c, 0x73,
+ 0x62, 0x70, 0x61, 0x72, 0x6e, 0x78, 0x77, 0x69, 0x77, 0x6a, 0x62, 0x75, 0x6f, 0x6d, 0x67, 0x79,
+ 0x71, 0x63, 0x61, 0x76, 0x77, 0x75, 0x6b, 0x65, 0x72, 0x72, 0x63, 0x65, 0x65, 0x64, 0x71, 0x74,
+ 0x78, 0x77, 0x6f, 0x70, 0x71, 0x63, 0x77, 0x63, 0x75, 0x66, 0x66, 0x6d, 0x67, 0x61, 0x76, 0x77,
+ 0x69, 0x64, 0x72, 0x6f, 0x73, 0x69, 0x6d, 0x69, 0x71, 0x74, 0x64, 0x71, 0x63, 0x72, 0x6d, 0x75,
+ 0x77, 0x63, 0x77, 0x67, 0x77, 0x64, 0x6d, 0x6f, 0x72, 0x6f, 0x6d, 0x6b, 0x62, 0x63, 0x70, 0x6f,
+ 0x72, 0x62, 0x61, 0x71, 0x65, 0x67, 0x64, 0x76, 0x78, 0x63, 0x66, 0x66, 0x71, 0x6f, 0x69, 0x73,
+ 0x6b, 0x72, 0x67, 0x6e, 0x77, 0x77, 0x79, 0x73, 0x69, 0x79, 0x6a, 0x6d, 0x72, 0x74, 0x79, 0x68,
+ 0x72, 0x6e, 0x70, 0x61, 0x6d, 0x67, 0x66, 0x74, 0x67, 0x6d, 0x73, 0x72, 0x79, 0x62, 0x6d, 0x6f,
+ 0x64, 0x63, 0x6f, 0x67, 0x70, 0x69, 0x79, 0x71, 0x68, 0x72, 0x79, 0x63, 0x6e, 0x77, 0x6b, 0x66,
+ 0x67, 0x73, 0x65, 0x71, 0x72, 0x68, 0x64, 0x73, 0x78, 0x6f, 0x64, 0x66, 0x78, 0x68, 0x66, 0x65,
+ 0x64, 0x78, 0x72, 0x61, 0x68, 0x74, 0x79, 0x6f, 0x6f, 0x6a, 0x63, 0x6a, 0x66, 0x6b, 0x64, 0x71,
+ 0x6f, 0x66, 0x6b, 0x67, 0x6c, 0x6c, 0x6c, 0x73, 0x61, 0x6f, 0x78, 0x73, 0x71, 0x62, 0x6e, 0x65,
+ 0x74, 0x67, 0x66, 0x6f, 0x6c, 0x77, 0x6a, 0x67, 0x6d, 0x61, 0x77, 0x77, 0x73, 0x73, 0x61, 0x6c,
+ 0x79, 0x6a, 0x78, 0x62, 0x74, 0x62, 0x62, 0x62, 0x70, 0x64, 0x6e, 0x6e, 0x62, 0x63, 0x79, 0x62,
+ 0x61, 0x6c, 0x74, 0x6e, 0x67, 0x77, 0x63, 0x75, 0x71, 0x61, 0x63, 0x67, 0x6f, 0x71, 0x63, 0x67,
+ 0x76, 0x73, 0x63, 0x66, 0x74, 0x68, 0x63, 0x6c, 0x66, 0x6a, 0x71, 0x69, 0x76, 0x6c, 0x72, 0x62,
+ 0x72, 0x67, 0x61, 0x6f, 0x72, 0x71, 0x64, 0x74, 0x64, 0x71, 0x6b, 0x68, 0x63, 0x6b, 0x67, 0x62,
+ 0x68, 0x6b, 0x79, 0x76, 0x70, 0x71, 0x76, 0x62, 0x72, 0x72, 0x74, 0x61, 0x6f, 0x67, 0x6f, 0x79,
+ 0x74, 0x69, 0x62, 0x72, 0x65, 0x61, 0x73, 0x61, 0x6b, 0x72, 0x6d, 0x73, 0x79, 0x78, 0x63, 0x62,
+ 0x70, 0x68, 0x63, 0x73, 0x77, 0x65, 0x61, 0x71, 0x79, 0x70, 0x71, 0x6a, 0x67, 0x70, 0x6c, 0x62,
+ 0x6f, 0x79, 0x62, 0x72, 0x73, 0x61, 0x75, 0x77, 0x74, 0x79, 0x70, 0x76, 0x64, 0x6c, 0x71, 0x61,
+ 0x67, 0x68, 0x76, 0x66, 0x71, 0x75, 0x72, 0x69, 0x71, 0x66, 0x6a, 0x78, 0x66, 0x6d, 0x6f, 0x75,
+ 0x6d, 0x6a, 0x61, 0x75, 0x6c, 0x6f, 0x71, 0x75, 0x6d, 0x70, 0x67, 0x79, 0x69, 0x61, 0x65, 0x72,
+ 0x6c, 0x6c, 0x71, 0x68, 0x72, 0x75, 0x65, 0x61, 0x77, 0x69, 0x73, 0x63, 0x6d, 0x75, 0x67, 0x69,
+ 0x76, 0x6b, 0x6e, 0x78, 0x70, 0x64, 0x6a, 0x6c, 0x67, 0x6e, 0x6e, 0x69, 0x77, 0x67, 0x67, 0x6e,
+ 0x66, 0x76, 0x61, 0x72, 0x6b, 0x61, 0x78, 0x74, 0x66, 0x76, 0x6e, 0x68, 0x6b, 0x66, 0x64, 0x66,
+ 0x72, 0x6b, 0x68, 0x74, 0x6f, 0x6b, 0x77, 0x73, 0x77, 0x6f, 0x6d, 0x70, 0x61, 0x76, 0x78, 0x76,
+ 0x6c, 0x71, 0x6f, 0x75, 0x79, 0x67, 0x68, 0x68, 0x68, 0x77, 0x68, 0x68, 0x62, 0x6d, 0x6d, 0x74,
+ 0x6f, 0x78, 0x6e, 0x62, 0x6e, 0x65, 0x77, 0x74, 0x79, 0x62, 0x67, 0x79, 0x65, 0x61, 0x72, 0x78,
+ 0x61, 0x73, 0x6e, 0x6e, 0x77, 0x6c, 0x6a, 0x77, 0x62, 0x70, 0x68, 0x64, 0x62, 0x79, 0x65, 0x73,
+ 0x6d, 0x77, 0x77, 0x78, 0x78, 0x69, 0x65, 0x6e, 0x75, 0x71, 0x79, 0x6b, 0x73, 0x6e, 0x75, 0x69,
+ 0x77, 0x69, 0x65, 0x75, 0x6f, 0x79, 0x79, 0x6c, 0x6b, 0x74, 0x74, 0x63, 0x67, 0x67, 0x75, 0x71,
+ 0x74, 0x73, 0x76, 0x69, 0x68, 0x6d, 0x67, 0x67, 0x74, 0x62, 0x69, 0x6d, 0x6b, 0x78, 0x77, 0x68,
+ 0x66, 0x61, 0x6a, 0x67, 0x6f, 0x65, 0x62, 0x69, 0x67, 0x64, 0x78, 0x6b, 0x75, 0x6a, 0x67, 0x72,
+ 0x76, 0x64, 0x6f, 0x72, 0x63, 0x63, 0x76, 0x66, 0x6b, 0x6c, 0x62, 0x64, 0x70, 0x63, 0x68, 0x70,
+ 0x74, 0x71, 0x61, 0x77, 0x6b, 0x78, 0x68, 0x6c, 0x77, 0x63, 0x76, 0x71, 0x6c, 0x69, 0x6a, 0x6c,
+ 0x70, 0x75, 0x78, 0x68, 0x62, 0x77, 0x61, 0x63, 0x77, 0x6c, 0x66, 0x77, 0x79, 0x64, 0x79, 0x79,
+ 0x76, 0x75, 0x77, 0x6e, 0x6d, 0x72, 0x66, 0x6b, 0x74, 0x6b, 0x62, 0x67, 0x76, 0x66, 0x74, 0x74,
+ 0x6d, 0x68, 0x6e, 0x6a, 0x77, 0x6c, 0x6c, 0x75, 0x6b, 0x65, 0x74, 0x6d, 0x62, 0x6c, 0x61, 0x70,
+ 0x75, 0x67, 0x6f, 0x67, 0x6d, 0x64, 0x76, 0x72, 0x6b, 0x6a, 0x65, 0x6e, 0x6c, 0x63, 0x71, 0x6b,
+ 0x6a, 0x64, 0x6f, 0x74, 0x67, 0x70, 0x69, 0x6e, 0x62, 0x72, 0x66, 0x65, 0x66, 0x65, 0x6e, 0x74,
+ 0x64, 0x6a, 0x78, 0x71, 0x61, 0x62, 0x61, 0x66, 0x6a, 0x63, 0x73, 0x66, 0x66, 0x79, 0x69, 0x6c,
+ 0x74, 0x6e, 0x78, 0x69, 0x6b, 0x6c, 0x62, 0x6f, 0x6c, 0x65, 0x61, 0x74, 0x65, 0x65, 0x66, 0x70,
+ 0x74, 0x71, 0x64, 0x67, 0x76, 0x69, 0x79, 0x6f, 0x6a, 0x74, 0x63, 0x62, 0x76, 0x71, 0x6a, 0x6e,
+ 0x78, 0x6b, 0x75, 0x67, 0x6c, 0x68, 0x63, 0x76, 0x63, 0x73, 0x6b, 0x6d, 0x69, 0x62, 0x72, 0x72,
+ 0x70, 0x64, 0x79, 0x79, 0x63, 0x6c, 0x70, 0x72, 0x6a, 0x79, 0x76, 0x74, 0x67, 0x6f, 0x6a, 0x67,
+ 0x68, 0x63, 0x69, 0x69, 0x78, 0x65, 0x77, 0x64, 0x6e, 0x6f, 0x78, 0x72, 0x68, 0x79, 0x68, 0x6f,
+ 0x6a, 0x62, 0x72, 0x75, 0x70, 0x6b, 0x75, 0x76, 0x6c, 0x69, 0x6b, 0x6d, 0x6d, 0x65, 0x73, 0x62,
+ 0x69, 0x68, 0x76, 0x78, 0x61, 0x6c, 0x6e, 0x61, 0x72, 0x72, 0x75, 0x75, 0x70, 0x78, 0x71, 0x79,
+ 0x74, 0x6e, 0x73, 0x6a, 0x75, 0x73, 0x76, 0x67, 0x6d, 0x6b, 0x68, 0x75, 0x77, 0x72, 0x79, 0x62,
+ 0x68, 0x6d, 0x77, 0x6b, 0x6b, 0x61, 0x73, 0x75, 0x6a, 0x74, 0x72, 0x66, 0x68, 0x63, 0x70, 0x79,
+ 0x69, 0x66, 0x6c, 0x67, 0x71, 0x72, 0x67, 0x76, 0x73, 0x63, 0x67, 0x76, 0x68, 0x6e, 0x63, 0x6e,
+ 0x75, 0x63, 0x69, 0x70, 0x6e, 0x78, 0x66, 0x66, 0x75, 0x6b, 0x67, 0x79, 0x6d, 0x6d, 0x70, 0x6e,
+ 0x6e, 0x6e, 0x6a, 0x69, 0x76, 0x63, 0x6c, 0x76, 0x75, 0x79, 0x61, 0x79, 0x74, 0x65, 0x71, 0x67,
+ 0x62, 0x64, 0x62, 0x67, 0x6f, 0x6b, 0x6c, 0x68, 0x61, 0x6d, 0x73, 0x74, 0x70, 0x6b, 0x62, 0x63,
+ 0x75, 0x66, 0x6a, 0x6a, 0x6a, 0x6a, 0x64, 0x76, 0x6b, 0x67, 0x73, 0x75, 0x69, 0x73, 0x6a, 0x6e,
+ 0x6a, 0x68, 0x6d, 0x72, 0x73, 0x71, 0x73, 0x75, 0x6a, 0x6d, 0x69, 0x75, 0x66, 0x71, 0x67, 0x75,
+ 0x73, 0x70, 0x71, 0x61, 0x69, 0x71, 0x74, 0x71, 0x65, 0x6b, 0x71, 0x6f, 0x77, 0x68, 0x6a, 0x77,
+ 0x74, 0x79, 0x6f, 0x74, 0x69, 0x62, 0x70, 0x70, 0x65, 0x6d, 0x6d, 0x77, 0x6d, 0x72, 0x62, 0x67,
+ 0x62, 0x74, 0x61, 0x76, 0x79, 0x6b, 0x79, 0x6d, 0x75, 0x71, 0x6e, 0x6e, 0x76, 0x78, 0x72, 0x70,
+ 0x62, 0x64, 0x70, 0x6c, 0x6e, 0x79, 0x6c, 0x68, 0x70, 0x65, 0x67, 0x6d, 0x65, 0x75, 0x76, 0x62,
+ 0x63, 0x70, 0x6b, 0x75, 0x66, 0x68, 0x68, 0x6f, 0x70, 0x66, 0x68, 0x73, 0x6e, 0x78, 0x75, 0x68,
+ 0x6a, 0x6e, 0x61, 0x78, 0x6e, 0x6b, 0x78, 0x6e, 0x71, 0x66, 0x75, 0x68, 0x62, 0x79, 0x6f, 0x6c,
+ 0x66, 0x67, 0x67, 0x6c, 0x6c, 0x75, 0x62, 0x79, 0x6b, 0x69, 0x71, 0x69, 0x75, 0x72, 0x71, 0x6a,
+ 0x70, 0x76, 0x70, 0x6d, 0x73, 0x70, 0x72, 0x61, 0x6b, 0x77, 0x78, 0x78, 0x6e, 0x73, 0x75, 0x75,
+ 0x6f, 0x68, 0x63, 0x6c, 0x75, 0x75, 0x6d, 0x72, 0x70, 0x75, 0x63, 0x63, 0x63, 0x6b, 0x6a, 0x79,
+ 0x6d, 0x61, 0x73, 0x62, 0x79, 0x75, 0x6b, 0x6d, 0x6a, 0x6f, 0x67, 0x61, 0x62, 0x6a, 0x6e, 0x71,
+ 0x69, 0x71, 0x6a, 0x6a, 0x61, 0x68, 0x68, 0x76, 0x61, 0x6a, 0x72, 0x6b, 0x76, 0x74, 0x6f, 0x61,
+ 0x70, 0x77, 0x6b, 0x67, 0x73, 0x75, 0x70, 0x62, 0x6d, 0x65, 0x67, 0x6e, 0x62, 0x79, 0x74, 0x74,
+ 0x72, 0x61, 0x6b, 0x76, 0x64, 0x69, 0x69, 0x69, 0x6c, 0x68, 0x78, 0x65, 0x70, 0x68, 0x79, 0x70,
+ 0x65, 0x72, 0x64, 0x68, 0x68, 0x6c, 0x61, 0x6f, 0x74, 0x62, 0x78, 0x6c, 0x72, 0x6c, 0x62, 0x75,
+ 0x6c, 0x64, 0x72, 0x64, 0x79, 0x6b, 0x72, 0x72, 0x62, 0x6d, 0x74, 0x72, 0x6b, 0x78, 0x6c, 0x75,
+ 0x78, 0x6a, 0x71, 0x67, 0x72, 0x79, 0x76, 0x71, 0x75, 0x6d, 0x75, 0x67, 0x6a, 0x63, 0x66, 0x6f,
+ 0x63, 0x66, 0x79, 0x74, 0x74, 0x70, 0x75, 0x6a, 0x6e, 0x64, 0x64, 0x6e, 0x68, 0x6e, 0x6e, 0x78,
+ 0x6b, 0x68, 0x72, 0x74, 0x6c, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x6c, 0x68, 0x78, 0x72, 0x66, 0x70,
+ 0x79, 0x6d, 0x61, 0x61, 0x76, 0x77, 0x64, 0x6e, 0x77, 0x74, 0x67, 0x6f, 0x74, 0x6f, 0x6b, 0x77,
+ 0x69, 0x79, 0x79, 0x73, 0x72, 0x71, 0x63, 0x62, 0x69, 0x78, 0x75, 0x72, 0x62, 0x71, 0x6f, 0x6e,
+ 0x66, 0x67, 0x6c, 0x72, 0x66, 0x6b, 0x61, 0x6e, 0x70, 0x70, 0x71, 0x65, 0x68, 0x71, 0x6e, 0x79,
+ 0x75, 0x75, 0x75, 0x67, 0x64, 0x67, 0x75, 0x74, 0x6a, 0x6b, 0x6a, 0x65, 0x71, 0x75, 0x73, 0x6d,
+ 0x77, 0x78, 0x72, 0x6e, 0x71, 0x61, 0x73, 0x63, 0x75, 0x78, 0x6c, 0x6c, 0x78, 0x6a, 0x75, 0x68,
+ 0x65, 0x71, 0x77, 0x6a, 0x76, 0x6d, 0x6d, 0x6e, 0x6a, 0x6e, 0x61, 0x65, 0x64, 0x72, 0x6c, 0x74,
+ 0x76, 0x63, 0x69, 0x65, 0x77, 0x70, 0x61, 0x69, 0x65, 0x74, 0x6d, 0x74, 0x68, 0x67, 0x6f, 0x65,
+ 0x62, 0x69, 0x63, 0x77, 0x77, 0x61, 0x75, 0x76, 0x69, 0x69, 0x77, 0x6f, 0x66, 0x6b, 0x77, 0x65,
+ 0x77, 0x6c, 0x6b, 0x69, 0x6a, 0x6a, 0x6c, 0x67, 0x76, 0x66, 0x74, 0x75, 0x72, 0x6c, 0x66, 0x6a,
+ 0x64, 0x67, 0x62, 0x73, 0x65, 0x75, 0x6e, 0x75, 0x6a, 0x6a, 0x69, 0x6a, 0x70, 0x63, 0x6f, 0x6c,
+ 0x69, 0x6b, 0x69, 0x6e, 0x79, 0x69, 0x70, 0x71, 0x66, 0x6b, 0x71, 0x71, 0x6e, 0x73, 0x66, 0x77,
+ 0x66, 0x73, 0x72, 0x77, 0x70, 0x74, 0x66, 0x71, 0x69, 0x6b, 0x74, 0x64, 0x61, 0x79, 0x65, 0x6e,
+ 0x6d, 0x6f, 0x6b, 0x78, 0x61, 0x70, 0x76, 0x74, 0x63, 0x78, 0x76, 0x63, 0x75, 0x67, 0x77, 0x62,
+ 0x63, 0x6a, 0x62, 0x79, 0x70, 0x61, 0x6e, 0x6c, 0x72, 0x6f, 0x6c, 0x6a, 0x63, 0x79, 0x75, 0x65,
+ 0x72, 0x72, 0x6e, 0x76, 0x64, 0x73, 0x77, 0x6b, 0x6d, 0x75, 0x67, 0x74, 0x75, 0x6f, 0x73, 0x67,
+ 0x6b, 0x61, 0x6a, 0x68, 0x69, 0x66, 0x6f, 0x64, 0x6f, 0x6e, 0x6a, 0x68, 0x61, 0x75, 0x79, 0x76,
+ 0x69, 0x70, 0x69, 0x6b, 0x6f, 0x71, 0x76, 0x6a, 0x77, 0x63, 0x68, 0x6f, 0x6e, 0x64, 0x71, 0x62,
+ 0x6d, 0x67, 0x76, 0x78, 0x70, 0x67, 0x6f, 0x67, 0x79, 0x78, 0x68, 0x73, 0x6a, 0x6f, 0x6b, 0x67,
+ 0x74, 0x6a, 0x77, 0x71, 0x77, 0x72, 0x70, 0x6c, 0x69, 0x78, 0x73, 0x72, 0x72, 0x71, 0x67, 0x6d,
+ 0x63, 0x6c, 0x6a, 0x72, 0x77, 0x61, 0x6b, 0x66, 0x63, 0x6c, 0x71, 0x78, 0x70, 0x6f, 0x70, 0x76,
+ 0x79, 0x61, 0x79, 0x6f, 0x6d, 0x61, 0x6b, 0x73, 0x6f, 0x6a, 0x64, 0x78, 0x6d, 0x6e, 0x67, 0x6e,
+ 0x74, 0x67, 0x74, 0x6a, 0x74, 0x6e, 0x79, 0x79, 0x6c, 0x63, 0x79, 0x6b, 0x6f, 0x6c, 0x69, 0x71,
+ 0x67, 0x75, 0x61, 0x62, 0x6b, 0x6d, 0x66, 0x71, 0x65, 0x79, 0x63, 0x6b, 0x79, 0x6e, 0x76, 0x6c,
+ 0x77, 0x75, 0x61, 0x66, 0x63, 0x65, 0x77, 0x75, 0x6a, 0x78, 0x75, 0x6f, 0x6a, 0x61, 0x61, 0x6d,
+ 0x69, 0x68, 0x77, 0x73, 0x79, 0x64, 0x77, 0x6f, 0x77, 0x76, 0x76, 0x6d, 0x69, 0x67, 0x78, 0x6f,
+ 0x76, 0x6a, 0x73, 0x65, 0x77, 0x6e, 0x70, 0x6a, 0x78, 0x75, 0x77, 0x79, 0x62, 0x6e, 0x76, 0x63,
+ 0x61, 0x76, 0x69, 0x6a, 0x68, 0x74, 0x78, 0x69, 0x78, 0x71, 0x6f, 0x6d, 0x76, 0x6f, 0x6d, 0x64,
+ 0x6d, 0x73, 0x6c, 0x65, 0x68, 0x6c, 0x71, 0x6d, 0x61, 0x66, 0x69, 0x78, 0x6e, 0x6b, 0x64, 0x79,
+ 0x62, 0x70, 0x6d, 0x66, 0x6d, 0x74, 0x6e, 0x70, 0x67, 0x6c, 0x6e, 0x68, 0x6c, 0x6a, 0x71, 0x79,
+ 0x66, 0x67, 0x68, 0x73, 0x6f, 0x72, 0x73, 0x6a, 0x77, 0x73, 0x65, 0x67, 0x62, 0x75, 0x69, 0x6d,
+ 0x71, 0x67, 0x73, 0x73, 0x72, 0x6b, 0x6e, 0x70, 0x6f, 0x68, 0x62, 0x72, 0x6c, 0x74, 0x66, 0x72,
+ 0x77, 0x72, 0x6d, 0x67, 0x75, 0x74, 0x77, 0x62, 0x72, 0x73, 0x68, 0x6e, 0x70, 0x65, 0x64, 0x6b,
+ 0x6f, 0x65, 0x76, 0x6c, 0x6f, 0x69, 0x72, 0x72, 0x77, 0x62, 0x63, 0x61, 0x6e, 0x6e, 0x72, 0x73,
+ 0x62, 0x6d, 0x6b, 0x69, 0x76, 0x6d, 0x71, 0x62, 0x61, 0x6b, 0x6a, 0x62, 0x6d, 0x79, 0x6d, 0x78,
+ 0x6a, 0x70, 0x68, 0x61, 0x65, 0x76, 0x66, 0x71, 0x64, 0x6c, 0x65, 0x77, 0x72, 0x66, 0x71, 0x6f,
+ 0x69, 0x71, 0x79, 0x70, 0x72, 0x6d, 0x6c, 0x69, 0x70, 0x69, 0x72, 0x64, 0x61, 0x79, 0x74, 0x6a,
+ 0x61, 0x79, 0x72, 0x6c, 0x74, 0x68, 0x66, 0x72, 0x72, 0x67, 0x63, 0x68, 0x6d, 0x77, 0x64, 0x71,
+ 0x71, 0x75, 0x69, 0x6d, 0x6e, 0x69, 0x72, 0x76, 0x6e, 0x6d, 0x72, 0x78, 0x75, 0x73, 0x66, 0x72,
+ 0x6b, 0x77, 0x6b, 0x77, 0x77, 0x72, 0x64, 0x77, 0x74, 0x76, 0x6e, 0x66, 0x62, 0x6e, 0x69, 0x77,
+ 0x62, 0x6f, 0x62, 0x73, 0x67, 0x79, 0x69, 0x63, 0x79, 0x63, 0x73, 0x64, 0x78, 0x76, 0x70, 0x6b,
+ 0x6f, 0x77, 0x72, 0x61, 0x6f, 0x78, 0x79, 0x67, 0x68, 0x76, 0x61, 0x6f, 0x63, 0x78, 0x6e, 0x6c,
+ 0x69, 0x73, 0x6c, 0x79, 0x74, 0x79, 0x67, 0x79, 0x79, 0x77, 0x77, 0x78, 0x65, 0x75, 0x6b, 0x65,
+ 0x65, 0x69, 0x77, 0x6c, 0x66, 0x65, 0x75, 0x68, 0x78, 0x66, 0x62, 0x6c, 0x75, 0x67, 0x67, 0x70,
+ 0x69, 0x6c, 0x79, 0x71, 0x77, 0x69, 0x6f, 0x79, 0x6d, 0x69, 0x6d, 0x79, 0x71, 0x66, 0x63, 0x75,
+ 0x69, 0x69, 0x76, 0x72, 0x75, 0x69, 0x6b, 0x64, 0x62, 0x70, 0x64, 0x78, 0x79, 0x69, 0x64, 0x72,
+ 0x68, 0x73, 0x6d, 0x68, 0x6c, 0x72, 0x66, 0x6a, 0x6a, 0x6f, 0x66, 0x67, 0x6d, 0x6f, 0x66, 0x74,
+ 0x62, 0x74, 0x70, 0x61, 0x71, 0x70, 0x70, 0x68, 0x77, 0x73, 0x78, 0x65, 0x61, 0x6f, 0x6e, 0x6c,
+ 0x61, 0x71, 0x6f, 0x66, 0x68, 0x76, 0x76, 0x66, 0x79, 0x70, 0x6c, 0x6d, 0x64, 0x6d, 0x76, 0x75,
+ 0x6d, 0x6e, 0x73, 0x6d, 0x67, 0x62, 0x78, 0x75, 0x6c, 0x6a, 0x6b, 0x74, 0x78, 0x63, 0x67, 0x65,
+ 0x62, 0x63, 0x66, 0x67, 0x6d, 0x77, 0x79, 0x66, 0x77, 0x72, 0x79, 0x6a, 0x64, 0x76, 0x78, 0x78,
+ 0x6b, 0x66, 0x6f, 0x6c, 0x6e, 0x6d, 0x6b, 0x73, 0x71, 0x6d, 0x68, 0x68, 0x74, 0x6a, 0x75, 0x6b,
+ 0x63, 0x77, 0x66, 0x6b, 0x6e, 0x69, 0x66, 0x75, 0x6e, 0x75, 0x6c, 0x67, 0x66, 0x6e, 0x6f, 0x73,
+ 0x6e, 0x73, 0x73, 0x77, 0x75, 0x71, 0x72, 0x76, 0x68, 0x64, 0x6a, 0x6c, 0x61, 0x66, 0x6b, 0x6d,
+ 0x6e, 0x63, 0x79, 0x69, 0x73, 0x6f, 0x64, 0x72, 0x61, 0x65, 0x6a, 0x67, 0x79, 0x6c, 0x6d, 0x61,
+ 0x62, 0x6e, 0x67, 0x6d, 0x77, 0x6a, 0x77, 0x72, 0x68, 0x68, 0x6f, 0x76, 0x77, 0x73, 0x76, 0x6f,
+ 0x6c, 0x66, 0x69, 0x75, 0x63, 0x74, 0x70, 0x74, 0x75, 0x6e, 0x66, 0x6d, 0x66, 0x69, 0x6b, 0x70,
+ 0x70, 0x74, 0x66, 0x6a, 0x6c, 0x6e, 0x65, 0x6b, 0x67, 0x71, 0x79, 0x76, 0x65, 0x64, 0x6a, 0x70,
+ 0x63, 0x71, 0x6f, 0x68, 0x76, 0x77, 0x65, 0x77, 0x78, 0x78, 0x65, 0x68, 0x69, 0x63, 0x66, 0x74,
+ 0x70, 0x65, 0x6e, 0x6a, 0x68, 0x6c, 0x70, 0x67, 0x6f, 0x62, 0x66, 0x79, 0x75, 0x71, 0x63, 0x6b,
+ 0x64, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x63, 0x6b, 0x78, 0x66, 0x63, 0x6f, 0x6f, 0x73, 0x67, 0x73,
+ 0x72, 0x67, 0x61, 0x66, 0x77, 0x6f, 0x78, 0x63, 0x6f, 0x64, 0x6d, 0x68, 0x70, 0x74, 0x70, 0x70,
+ 0x6c, 0x61, 0x63, 0x63, 0x78, 0x72, 0x68, 0x69, 0x76, 0x79, 0x74, 0x6c, 0x6c, 0x64, 0x72, 0x62,
+ 0x65, 0x73, 0x6e, 0x63, 0x70, 0x74, 0x6a, 0x74, 0x68, 0x6d, 0x62, 0x63, 0x74, 0x6b, 0x62, 0x6f,
+ 0x61, 0x72, 0x68, 0x62, 0x6c, 0x6e, 0x72, 0x71, 0x79, 0x76, 0x74, 0x67, 0x74, 0x70, 0x74, 0x67,
+ 0x77, 0x6e, 0x79, 0x70, 0x6f, 0x66, 0x72, 0x6b, 0x75, 0x6f, 0x64, 0x63, 0x65, 0x6f, 0x67, 0x66,
+ 0x68, 0x65, 0x75, 0x77, 0x64, 0x76, 0x61, 0x66, 0x69, 0x6a, 0x67, 0x62, 0x72, 0x71, 0x64, 0x79,
+ 0x72, 0x61, 0x73, 0x72, 0x75, 0x61, 0x65, 0x63, 0x77, 0x77, 0x77, 0x70, 0x65, 0x65, 0x62, 0x76,
+ 0x65, 0x68, 0x70, 0x77, 0x6c, 0x63, 0x63, 0x62, 0x6a, 0x68, 0x79, 0x64, 0x63, 0x73, 0x6f, 0x66,
+ 0x78, 0x66, 0x78, 0x63, 0x6f, 0x67, 0x74, 0x75, 0x69, 0x73, 0x77, 0x69, 0x6b, 0x78, 0x65, 0x70,
+ 0x6c, 0x66, 0x70, 0x77, 0x62, 0x69, 0x66, 0x74, 0x76, 0x75, 0x6e, 0x64, 0x71, 0x6f, 0x79, 0x62,
+ 0x67, 0x78, 0x77, 0x79, 0x74, 0x62, 0x73, 0x61, 0x6a, 0x67, 0x76, 0x6a, 0x6f, 0x62, 0x65, 0x75,
+ 0x75, 0x74, 0x68, 0x6a, 0x68, 0x6b, 0x65, 0x79, 0x73, 0x75, 0x6c, 0x69, 0x66, 0x68, 0x6c, 0x79,
+ 0x6f, 0x78, 0x75, 0x72, 0x72, 0x61, 0x6c, 0x68, 0x76, 0x64, 0x79, 0x6a, 0x6f, 0x69, 0x62, 0x75,
+ 0x6b, 0x73, 0x71, 0x74, 0x74, 0x79, 0x6d, 0x6d, 0x61, 0x6d, 0x72, 0x78, 0x72, 0x6e, 0x65, 0x61,
+ 0x75, 0x65, 0x65, 0x77, 0x62, 0x62, 0x69, 0x6c, 0x6d, 0x6a, 0x76, 0x78, 0x64, 0x76, 0x61, 0x63,
+ 0x69, 0x71, 0x6b, 0x6d, 0x62, 0x78, 0x6a, 0x6d, 0x6a, 0x78, 0x67, 0x68, 0x79, 0x79, 0x66, 0x71,
+ 0x6b, 0x73, 0x72, 0x76, 0x78, 0x74, 0x63, 0x72, 0x74, 0x76, 0x70, 0x79, 0x68, 0x79, 0x69, 0x62,
+ 0x61, 0x74, 0x6b, 0x79, 0x79, 0x6c, 0x78, 0x62, 0x65, 0x78, 0x71, 0x64, 0x75, 0x73, 0x68, 0x62,
+ 0x68, 0x74, 0x71, 0x70, 0x77, 0x61, 0x6a, 0x65, 0x79, 0x6d, 0x61, 0x68, 0x61, 0x75, 0x6e, 0x6e,
+ 0x6d, 0x73, 0x73, 0x65, 0x77, 0x66, 0x70, 0x78, 0x69, 0x65, 0x64, 0x71, 0x6f, 0x65, 0x62, 0x6e,
+ 0x72, 0x69, 0x61, 0x6e, 0x75, 0x76, 0x79, 0x68, 0x69, 0x64, 0x6e, 0x69, 0x63, 0x6d, 0x68, 0x65,
+ 0x62, 0x63, 0x68, 0x67, 0x79, 0x67, 0x67, 0x66, 0x63, 0x71, 0x69, 0x79, 0x69, 0x6a, 0x77, 0x76,
+ 0x64, 0x6c, 0x73, 0x71, 0x6b, 0x6b, 0x77, 0x63, 0x79, 0x78, 0x62, 0x76, 0x75, 0x73, 0x68, 0x65,
+ 0x64, 0x6b, 0x70, 0x78, 0x75, 0x71, 0x6e, 0x64, 0x70, 0x64, 0x6b, 0x6f, 0x77, 0x63, 0x77, 0x67,
+ 0x74, 0x66, 0x78, 0x73, 0x6c, 0x77, 0x62, 0x68, 0x76, 0x66, 0x70, 0x6e, 0x71, 0x66, 0x73, 0x6f,
+ 0x70, 0x65, 0x77, 0x63, 0x61, 0x71, 0x64, 0x6c, 0x72, 0x6a, 0x71, 0x68, 0x73, 0x66, 0x67, 0x62,
+ 0x70, 0x77, 0x69, 0x67, 0x6e, 0x78, 0x63, 0x75, 0x6a, 0x6b, 0x70, 0x69, 0x6c, 0x76, 0x64, 0x6f,
+ 0x76, 0x63, 0x75, 0x62, 0x77, 0x67, 0x6e, 0x67, 0x67, 0x6d, 0x63, 0x66, 0x6d, 0x67, 0x65, 0x6b,
+ 0x66, 0x73, 0x66, 0x75, 0x66, 0x73, 0x73, 0x6b, 0x6b, 0x78, 0x75, 0x65, 0x75, 0x76, 0x70, 0x76,
+ 0x61, 0x6e, 0x78, 0x66, 0x6c, 0x71, 0x66, 0x62, 0x71, 0x75, 0x79, 0x70, 0x74, 0x79, 0x65, 0x70,
+ 0x66, 0x79, 0x6f, 0x75, 0x70, 0x63, 0x76, 0x75, 0x62, 0x6c, 0x78, 0x68, 0x6f, 0x77, 0x75, 0x6e,
+ 0x79, 0x6d, 0x70, 0x64, 0x71, 0x63, 0x69, 0x75, 0x76, 0x68, 0x71, 0x75, 0x67, 0x79, 0x69, 0x69,
+ 0x77, 0x6d, 0x69, 0x6a, 0x68, 0x6a, 0x6d, 0x6a, 0x70, 0x6c, 0x73, 0x6d, 0x6c, 0x6c, 0x6f, 0x6c,
+ 0x69, 0x71, 0x73, 0x78, 0x6d, 0x61, 0x61, 0x73, 0x6f, 0x66, 0x66, 0x63, 0x71, 0x6b, 0x6d, 0x6f,
+ 0x75, 0x67, 0x71, 0x77, 0x67, 0x73, 0x76, 0x76, 0x6a, 0x76, 0x6c, 0x61, 0x67, 0x66, 0x6a, 0x69,
+ 0x73, 0x71, 0x69, 0x72, 0x72, 0x78, 0x63, 0x6b, 0x76, 0x6f, 0x6b, 0x78, 0x6b, 0x72, 0x6f, 0x6a,
+ 0x64, 0x64, 0x73, 0x74, 0x75, 0x64, 0x6f, 0x75, 0x77, 0x62, 0x64, 0x6a, 0x67, 0x6a, 0x73, 0x69,
+ 0x6a, 0x79, 0x63, 0x77, 0x75, 0x72, 0x75, 0x62, 0x68, 0x73, 0x6c, 0x69, 0x74, 0x64, 0x6d, 0x71,
+ 0x76, 0x76, 0x6e, 0x67, 0x67, 0x65, 0x71, 0x70, 0x6a, 0x79, 0x74, 0x75, 0x76, 0x74, 0x67, 0x79,
+ 0x62, 0x63, 0x68, 0x6c, 0x6c, 0x70, 0x67, 0x65, 0x64, 0x76, 0x72, 0x65, 0x76, 0x6b, 0x69, 0x71,
+ 0x73, 0x79, 0x78, 0x64, 0x70, 0x79, 0x61, 0x76, 0x61, 0x66, 0x74, 0x79, 0x6a, 0x6a, 0x6a, 0x78,
+ 0x6b, 0x6e, 0x74, 0x6f, 0x66, 0x67, 0x62, 0x76, 0x71, 0x65, 0x62, 0x64, 0x73, 0x6f, 0x63, 0x66,
+ 0x66, 0x6c, 0x63, 0x77, 0x6e, 0x72, 0x66, 0x72, 0x74, 0x70, 0x70, 0x6c, 0x6f, 0x72, 0x6b, 0x79,
+ 0x68, 0x67, 0x63, 0x62, 0x79, 0x6f, 0x73, 0x65, 0x62, 0x76, 0x67, 0x65, 0x77, 0x64, 0x6c, 0x61,
+ 0x62, 0x61, 0x64, 0x68, 0x79, 0x72, 0x70, 0x61, 0x77, 0x6d, 0x6a, 0x69, 0x70, 0x6f, 0x77, 0x77,
+ 0x77, 0x6f, 0x6d, 0x78, 0x76, 0x69, 0x69, 0x78, 0x74, 0x68, 0x68, 0x74, 0x6c, 0x6e, 0x66, 0x67,
+ 0x67, 0x64, 0x62, 0x6d, 0x63, 0x71, 0x75, 0x65, 0x75, 0x71, 0x6c, 0x75, 0x62, 0x66, 0x66, 0x61,
+ 0x69, 0x67, 0x79, 0x70, 0x6e, 0x6b, 0x6f, 0x71, 0x62, 0x77, 0x6c, 0x75, 0x67, 0x77, 0x78, 0x79,
+ 0x6e, 0x77, 0x6a, 0x71, 0x71, 0x77, 0x68, 0x72, 0x73, 0x77, 0x69, 0x75, 0x61, 0x62, 0x65, 0x71,
+ 0x6a, 0x78, 0x6e, 0x6c, 0x6c, 0x70, 0x76, 0x74, 0x69, 0x76, 0x61, 0x78, 0x66, 0x76, 0x6e, 0x62,
+ 0x64, 0x71, 0x71, 0x6c, 0x79, 0x65, 0x65, 0x6b, 0x71, 0x6a, 0x73, 0x6e, 0x6b, 0x76, 0x70, 0x79,
+ 0x77, 0x63, 0x63, 0x67, 0x75, 0x6e, 0x66, 0x74, 0x63, 0x76, 0x75, 0x6d, 0x66, 0x6c, 0x63, 0x6b,
+ 0x79, 0x6d, 0x72, 0x69, 0x67, 0x75, 0x65, 0x78, 0x70, 0x6c, 0x71, 0x69, 0x69, 0x76, 0x70, 0x75,
+ 0x6b, 0x6a, 0x64, 0x66, 0x71, 0x71, 0x6b, 0x6a, 0x66, 0x64, 0x79, 0x69, 0x6f, 0x74, 0x62, 0x6c,
+ 0x78, 0x61, 0x77, 0x65, 0x6e, 0x6f, 0x62, 0x70, 0x76, 0x6e, 0x73, 0x73, 0x74, 0x6d, 0x6d, 0x6a,
+ 0x68, 0x66, 0x6f, 0x78, 0x70, 0x76, 0x66, 0x6f, 0x6a, 0x76, 0x6a, 0x6b, 0x6c, 0x6f, 0x64, 0x77,
+ 0x78, 0x61, 0x68, 0x63, 0x72, 0x61, 0x69, 0x78, 0x69, 0x74, 0x78, 0x6c, 0x79, 0x61, 0x61, 0x67,
+ 0x72, 0x6a, 0x6f, 0x76, 0x6d, 0x6d, 0x6c, 0x78, 0x63, 0x63, 0x65, 0x69, 0x67, 0x78, 0x73, 0x76,
+ 0x78, 0x69, 0x6d, 0x70, 0x73, 0x76, 0x78, 0x71, 0x75, 0x65, 0x77, 0x69, 0x73, 0x77, 0x6f, 0x66,
+ 0x65, 0x6b, 0x61, 0x6a, 0x78, 0x70, 0x70, 0x71, 0x71, 0x79, 0x67, 0x79, 0x79, 0x6e, 0x64, 0x6c,
+ 0x6c, 0x6a, 0x6d, 0x6a, 0x79, 0x73, 0x63, 0x72, 0x6a, 0x72, 0x77, 0x6d, 0x74, 0x70, 0x77, 0x6e,
+ 0x77, 0x63, 0x6c, 0x71, 0x74, 0x75, 0x61, 0x79, 0x69, 0x71, 0x6a, 0x64, 0x62, 0x64, 0x68, 0x74,
+ 0x75, 0x75, 0x64, 0x6d, 0x6f, 0x66, 0x64, 0x69, 0x74, 0x73, 0x6c, 0x66, 0x77, 0x64, 0x73, 0x6e,
+ 0x63, 0x6e, 0x73, 0x6d, 0x67, 0x73, 0x76, 0x6b, 0x73, 0x6b, 0x77, 0x6c, 0x6f, 0x70, 0x69, 0x6f,
+ 0x6f, 0x62, 0x63, 0x6c, 0x70, 0x70, 0x6e, 0x61, 0x78, 0x6d, 0x63, 0x74, 0x67, 0x66, 0x79, 0x69,
+ 0x6c, 0x68, 0x71, 0x68, 0x68, 0x75, 0x79, 0x61, 0x62, 0x6b, 0x6b, 0x70, 0x6a, 0x69, 0x75, 0x6a,
+ 0x78, 0x65, 0x74, 0x62, 0x6d, 0x72, 0x6c, 0x74, 0x79, 0x74, 0x66, 0x63, 0x6d, 0x71, 0x68, 0x70,
+ 0x6c, 0x74, 0x79, 0x6e, 0x69, 0x75, 0x66, 0x6d, 0x69, 0x6f, 0x74, 0x68, 0x6c, 0x6b, 0x65, 0x72,
+ 0x69, 0x70, 0x68, 0x72, 0x65, 0x66, 0x6e, 0x72, 0x71, 0x66, 0x6f, 0x6e, 0x68, 0x62, 0x70, 0x6d,
+ 0x6e, 0x75, 0x77, 0x68, 0x74, 0x77, 0x74, 0x61, 0x76, 0x74, 0x79, 0x63, 0x6f, 0x63, 0x6c, 0x64,
+ 0x78, 0x69, 0x6f, 0x6d, 0x66, 0x78, 0x6c, 0x6c, 0x6f, 0x6a, 0x77, 0x6d, 0x74, 0x67, 0x63, 0x64,
+ 0x79, 0x64, 0x6d, 0x61, 0x66, 0x64, 0x79, 0x6a, 0x61, 0x68, 0x63, 0x6d, 0x61, 0x69, 0x70, 0x6e,
+ 0x61, 0x77, 0x6a, 0x64, 0x63, 0x64, 0x70, 0x6d, 0x75, 0x62, 0x6d, 0x74, 0x64, 0x6d, 0x74, 0x67,
+ 0x6d, 0x72, 0x77, 0x79, 0x6f, 0x76, 0x6f, 0x75, 0x62, 0x6b, 0x72, 0x77, 0x66, 0x6b, 0x6c, 0x73,
+ 0x6a, 0x76, 0x69, 0x68, 0x6f, 0x77, 0x62, 0x74, 0x71, 0x66, 0x74, 0x64, 0x63, 0x79, 0x6d, 0x72,
+ 0x76, 0x65, 0x69, 0x6f, 0x74, 0x73, 0x73, 0x6b, 0x68, 0x66, 0x64, 0x72, 0x70, 0x62, 0x73, 0x76,
+ 0x64, 0x6d, 0x70, 0x6c, 0x6d, 0x63, 0x73, 0x73, 0x72, 0x76, 0x69, 0x76, 0x62, 0x64, 0x72, 0x75,
+ 0x76, 0x6a, 0x62, 0x78, 0x69, 0x61, 0x73, 0x68, 0x6a, 0x67, 0x62, 0x6a, 0x64, 0x67, 0x77, 0x76,
+ 0x6c, 0x69, 0x77, 0x74, 0x72, 0x6f, 0x77, 0x66, 0x67, 0x62, 0x6e, 0x6e, 0x66, 0x70, 0x72, 0x64,
+ 0x71, 0x79, 0x66, 0x6f, 0x72, 0x65, 0x75, 0x64, 0x6b, 0x6f, 0x77, 0x73, 0x79, 0x75, 0x78, 0x6a,
+ 0x64, 0x6d, 0x79, 0x77, 0x6b, 0x62, 0x77, 0x62, 0x66, 0x67, 0x73, 0x68, 0x72, 0x62, 0x62, 0x67,
+ 0x6d, 0x6d, 0x6c, 0x78, 0x69, 0x6c, 0x75, 0x77, 0x6d, 0x69, 0x6c, 0x6b, 0x71, 0x64, 0x67, 0x65,
+ 0x73, 0x63, 0x6d, 0x6d, 0x63, 0x65, 0x6a, 0x71, 0x79, 0x6d, 0x63, 0x6e, 0x77, 0x64, 0x63, 0x71,
+ 0x67, 0x77, 0x68, 0x6d, 0x63, 0x61, 0x67, 0x6e, 0x63, 0x71, 0x6a, 0x72, 0x75, 0x61, 0x74, 0x69,
+ 0x6c, 0x76, 0x62, 0x65, 0x78, 0x74, 0x63, 0x67, 0x75, 0x6e, 0x71, 0x69, 0x68, 0x77, 0x69, 0x6b,
+ 0x69, 0x67, 0x70, 0x6c, 0x77, 0x6d, 0x6d, 0x6c, 0x77, 0x77, 0x6d, 0x66, 0x61, 0x6d, 0x66, 0x76,
+ 0x69, 0x62, 0x66, 0x6b, 0x64, 0x68, 0x75, 0x78, 0x67, 0x64, 0x61, 0x6b, 0x78, 0x6c, 0x78, 0x70,
+ 0x77, 0x61, 0x68, 0x65, 0x6d, 0x66, 0x6f, 0x77, 0x78, 0x6f, 0x61, 0x6e, 0x6e, 0x77, 0x67, 0x6b,
+ 0x62, 0x70, 0x6b, 0x69, 0x61, 0x67, 0x6a, 0x76, 0x68, 0x74, 0x61, 0x6d, 0x70, 0x69, 0x70, 0x6a,
+ 0x68, 0x71, 0x69, 0x63, 0x74, 0x6a, 0x6a, 0x73, 0x69, 0x64, 0x64, 0x75, 0x79, 0x6a, 0x65, 0x6d,
+ 0x71, 0x62, 0x68, 0x77, 0x74, 0x65, 0x68, 0x6b, 0x78, 0x69, 0x6e, 0x73, 0x65, 0x66, 0x6e, 0x64,
+ 0x6b, 0x79, 0x66, 0x61, 0x78, 0x63, 0x6a, 0x6b, 0x68, 0x76, 0x74, 0x6f, 0x72, 0x6d, 0x73, 0x6c,
+ 0x67, 0x6a, 0x72, 0x78, 0x75, 0x6f, 0x6d, 0x6e, 0x61, 0x6d, 0x66, 0x6b, 0x65, 0x72, 0x70, 0x62,
+ 0x67, 0x78, 0x64, 0x74, 0x77, 0x6c, 0x67, 0x78, 0x71, 0x75, 0x71, 0x62, 0x61, 0x6d, 0x79, 0x70,
+ 0x74, 0x71, 0x6e, 0x6a, 0x70, 0x61, 0x74, 0x6a, 0x6f, 0x6a, 0x78, 0x6d, 0x72, 0x61, 0x67, 0x76,
+ 0x71, 0x71, 0x75, 0x61, 0x62, 0x6d, 0x62, 0x67, 0x6a, 0x61, 0x73, 0x73, 0x70, 0x64, 0x69, 0x74,
+ 0x6e, 0x62, 0x72, 0x72, 0x6d, 0x78, 0x72, 0x76, 0x6a, 0x6b, 0x70, 0x6d, 0x72, 0x77, 0x61, 0x63,
+ 0x79, 0x64, 0x6b, 0x6e, 0x72, 0x6b, 0x61, 0x6e, 0x77, 0x70, 0x6f, 0x6e, 0x68, 0x6c, 0x71, 0x62,
+ 0x74, 0x64, 0x63, 0x67, 0x65, 0x67, 0x67, 0x6e, 0x6d, 0x66, 0x62, 0x72, 0x71, 0x74, 0x76, 0x79,
+ 0x70, 0x72, 0x6f, 0x6f, 0x63, 0x79, 0x72, 0x63, 0x73, 0x64, 0x68, 0x63, 0x73, 0x6c, 0x6f, 0x6c,
+ 0x66, 0x71, 0x6a, 0x75, 0x69, 0x6e, 0x67, 0x72, 0x74, 0x6a, 0x61, 0x73, 0x68, 0x69, 0x6d, 0x71,
+ 0x76, 0x73, 0x65, 0x6f, 0x63, 0x62, 0x71, 0x6d, 0x66, 0x71, 0x69, 0x61, 0x76, 0x6d, 0x76, 0x6f,
+ 0x64, 0x6c, 0x6c, 0x74, 0x6c, 0x74, 0x76, 0x6b, 0x63, 0x62, 0x79, 0x70, 0x6e, 0x64, 0x64, 0x6e,
+ 0x71, 0x73, 0x71, 0x6d, 0x71, 0x67, 0x6a, 0x69, 0x66, 0x76, 0x6e, 0x73, 0x6f, 0x77, 0x67, 0x6f,
+ 0x65, 0x71, 0x73, 0x70, 0x61, 0x6b, 0x67, 0x69, 0x6b, 0x75, 0x68, 0x6d, 0x6a, 0x6c, 0x61, 0x70,
+ 0x71, 0x74, 0x66, 0x63, 0x61, 0x67, 0x77, 0x77, 0x68, 0x61, 0x61, 0x6a, 0x74, 0x72, 0x6d, 0x75,
+ 0x75, 0x64, 0x69, 0x70, 0x64, 0x62, 0x6b, 0x75, 0x6c, 0x73, 0x68, 0x65, 0x6b, 0x74, 0x74, 0x6e,
+ 0x6c, 0x61, 0x6c, 0x74, 0x71, 0x6c, 0x79, 0x69, 0x65, 0x76, 0x74, 0x77, 0x76, 0x69, 0x66, 0x78,
+ 0x68, 0x79, 0x64, 0x79, 0x61, 0x76, 0x68, 0x70, 0x78, 0x73, 0x68, 0x6d, 0x6a, 0x67, 0x65, 0x76,
+ 0x73, 0x66, 0x6b, 0x6b, 0x70, 0x68, 0x64, 0x79, 0x76, 0x71, 0x77, 0x63, 0x65, 0x6a, 0x6e, 0x6f,
+ 0x6f, 0x75, 0x6e, 0x65, 0x6a, 0x64, 0x6c, 0x69, 0x6e, 0x70, 0x6f, 0x6d, 0x66, 0x76, 0x76, 0x66,
+ 0x62, 0x6c, 0x78, 0x71, 0x71, 0x73, 0x63, 0x6e, 0x72, 0x6d, 0x6a, 0x74, 0x67, 0x77, 0x78, 0x74,
+ 0x65, 0x66, 0x6d, 0x72, 0x73, 0x6f, 0x64, 0x6e, 0x66, 0x71, 0x61, 0x6c, 0x72, 0x77, 0x67, 0x71,
+ 0x6d, 0x74, 0x69, 0x72, 0x61, 0x6b, 0x78, 0x67, 0x78, 0x73, 0x70, 0x6b, 0x63, 0x76, 0x6f, 0x65,
+ 0x6b, 0x70, 0x74, 0x71, 0x75, 0x67, 0x78, 0x6c, 0x6b, 0x79, 0x76, 0x71, 0x63, 0x6b, 0x6a, 0x6e,
+ 0x61, 0x66, 0x6f, 0x69, 0x6f, 0x64, 0x6d, 0x6e, 0x61, 0x76, 0x69, 0x6f, 0x78, 0x68, 0x61, 0x74,
+ 0x6d, 0x68, 0x72, 0x64, 0x63, 0x79, 0x78, 0x76, 0x6c, 0x6e, 0x6f, 0x6a, 0x72, 0x6b, 0x6b, 0x70,
+ 0x65, 0x65, 0x6c, 0x63, 0x66, 0x73, 0x66, 0x68, 0x6e, 0x74, 0x6d, 0x64, 0x62, 0x6f, 0x6f, 0x67,
+ 0x79, 0x6d, 0x69, 0x61, 0x78, 0x6b, 0x6b, 0x61, 0x6e, 0x76, 0x6b, 0x70, 0x6e, 0x6d, 0x68, 0x67,
+ 0x72, 0x72, 0x69, 0x74, 0x78, 0x6a, 0x78, 0x75, 0x68, 0x71, 0x70, 0x6b, 0x6b, 0x64, 0x71, 0x63,
+ 0x65, 0x6c, 0x6c, 0x69, 0x72, 0x76, 0x70, 0x6f, 0x70, 0x6e, 0x73, 0x74, 0x6a, 0x61, 0x75, 0x63,
+ 0x61, 0x78, 0x6f, 0x79, 0x67, 0x65, 0x61, 0x69, 0x6d, 0x68, 0x6c, 0x62, 0x75, 0x79, 0x68, 0x79,
+ 0x65, 0x6a, 0x67, 0x6f, 0x68, 0x78, 0x70, 0x69, 0x62, 0x6b, 0x6b, 0x64, 0x77, 0x78, 0x6b, 0x76,
+ 0x69, 0x64, 0x75, 0x70, 0x72, 0x6e, 0x67, 0x73, 0x65, 0x73, 0x71, 0x73, 0x70, 0x78, 0x66, 0x6b,
+ 0x6e, 0x6b, 0x6a, 0x6f, 0x73, 0x6b, 0x70, 0x71, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x70, 0x6f, 0x6b,
+ 0x69, 0x75, 0x61, 0x70, 0x72, 0x65, 0x6a, 0x75, 0x61, 0x67, 0x75, 0x76, 0x65, 0x6d, 0x6c, 0x73,
+ 0x71, 0x6b, 0x73, 0x65, 0x79, 0x68, 0x70, 0x69, 0x6f, 0x69, 0x6c, 0x6b, 0x72, 0x64, 0x6c, 0x79,
+ 0x6b, 0x6a, 0x61, 0x6e, 0x6b, 0x6b, 0x74, 0x6f, 0x79, 0x64, 0x68, 0x68, 0x6c, 0x6f, 0x62, 0x70,
+ 0x6e, 0x79, 0x62, 0x62, 0x6b, 0x66, 0x6e, 0x6f, 0x70, 0x64, 0x66, 0x75, 0x73, 0x79, 0x62, 0x75,
+ 0x6d, 0x67, 0x73, 0x73, 0x6b, 0x71, 0x6e, 0x6d, 0x75, 0x62, 0x72, 0x6a, 0x6b, 0x63, 0x6d, 0x6c,
+ 0x6f, 0x6c, 0x74, 0x65, 0x71, 0x65, 0x6b, 0x77, 0x61, 0x66, 0x78, 0x6c, 0x78, 0x6d, 0x6e, 0x6d,
+ 0x6a, 0x71, 0x62, 0x64, 0x68, 0x67, 0x61, 0x6a, 0x68, 0x72, 0x72, 0x62, 0x6e, 0x6b, 0x71, 0x6d,
+ 0x66, 0x75, 0x6a, 0x78, 0x64, 0x66, 0x75, 0x74, 0x6f, 0x6a, 0x74, 0x73, 0x75, 0x62, 0x71, 0x6b,
+ 0x6d, 0x66, 0x65, 0x62, 0x64, 0x68, 0x79, 0x74, 0x6f, 0x75, 0x76, 0x66, 0x79, 0x70, 0x77, 0x65,
+ 0x78, 0x72, 0x65, 0x6e, 0x6a, 0x62, 0x61, 0x74, 0x65, 0x73, 0x68, 0x6e, 0x72, 0x75, 0x62, 0x64,
+ 0x69, 0x73, 0x65, 0x6b, 0x61, 0x6f, 0x6e, 0x71, 0x61, 0x6e, 0x64, 0x6e, 0x76, 0x73, 0x65, 0x63,
+ 0x6c, 0x6b, 0x6d, 0x77, 0x66, 0x6b, 0x72, 0x72, 0x78, 0x72, 0x6b, 0x6c, 0x69, 0x69, 0x79, 0x76,
+ 0x6c, 0x78, 0x75, 0x73, 0x65, 0x6d, 0x6e, 0x74, 0x68, 0x65, 0x76, 0x70, 0x64, 0x6b, 0x77, 0x6c,
+ 0x77, 0x6d, 0x66, 0x79, 0x64, 0x64, 0x6f, 0x74, 0x62, 0x6d, 0x6b, 0x61, 0x78, 0x6a, 0x73, 0x63,
+ 0x6e, 0x6a, 0x62, 0x73, 0x72, 0x6e, 0x6c, 0x62, 0x75, 0x79, 0x62, 0x66, 0x69, 0x72, 0x6c, 0x67,
+ 0x78, 0x61, 0x76, 0x62, 0x6e, 0x66, 0x63, 0x69, 0x68, 0x73, 0x78, 0x78, 0x74, 0x61, 0x78, 0x71,
+ 0x6e, 0x70, 0x75, 0x77, 0x63, 0x64, 0x61, 0x6f, 0x75, 0x68, 0x76, 0x71, 0x64, 0x72, 0x74, 0x75,
+ 0x6c, 0x73, 0x72, 0x75, 0x63, 0x61, 0x74, 0x61, 0x77, 0x74, 0x64, 0x65, 0x74, 0x68, 0x74, 0x78,
+ 0x63, 0x65, 0x79, 0x75, 0x6e, 0x6d, 0x78, 0x77, 0x67, 0x65, 0x6e, 0x74, 0x66, 0x76, 0x6c, 0x78,
+ 0x66, 0x76, 0x62, 0x76, 0x68, 0x65, 0x6f, 0x73, 0x78, 0x76, 0x69, 0x6c, 0x63, 0x76, 0x70, 0x79,
+ 0x6d, 0x75, 0x6e, 0x69, 0x61, 0x66, 0x65, 0x78, 0x6d, 0x68, 0x62, 0x73, 0x66, 0x73, 0x6b, 0x6c,
+ 0x77, 0x64, 0x6c, 0x72, 0x78, 0x75, 0x6c, 0x63, 0x6a, 0x64, 0x68, 0x79, 0x6f, 0x74, 0x65, 0x6d,
+ 0x65, 0x70, 0x6d, 0x70, 0x68, 0x65, 0x65, 0x65, 0x6c, 0x74, 0x6b, 0x69, 0x74, 0x6a, 0x71, 0x64,
+ 0x72, 0x74, 0x6e, 0x74, 0x75, 0x6a, 0x72, 0x73, 0x6b, 0x69, 0x6c, 0x71, 0x78, 0x77, 0x75, 0x6c,
+ 0x69, 0x62, 0x6e, 0x6a, 0x68, 0x73, 0x77, 0x77, 0x63, 0x66, 0x6a, 0x78, 0x6d, 0x77, 0x6e, 0x62,
+ 0x6c, 0x76, 0x66, 0x66, 0x75, 0x65, 0x6e, 0x69, 0x79, 0x75, 0x72, 0x6d, 0x70, 0x71, 0x65, 0x67,
+ 0x74, 0x75, 0x6a, 0x6d, 0x66, 0x64, 0x72, 0x66, 0x77, 0x70, 0x76, 0x75, 0x73, 0x75, 0x6c, 0x73,
+ 0x75, 0x6b, 0x71, 0x6f, 0x79, 0x6a, 0x62, 0x78, 0x69, 0x62, 0x72, 0x61, 0x6a, 0x69, 0x67, 0x71,
+ 0x66, 0x71, 0x6a, 0x63, 0x62, 0x79, 0x78, 0x69, 0x61, 0x63, 0x6a, 0x62, 0x6a, 0x63, 0x68, 0x79,
+ 0x68, 0x69, 0x63, 0x73, 0x65, 0x67, 0x70, 0x74, 0x72, 0x6f, 0x79, 0x75, 0x65, 0x73, 0x6a, 0x76,
+ 0x6f, 0x64, 0x66, 0x72, 0x6d, 0x71, 0x66, 0x6d, 0x62, 0x6a, 0x68, 0x74, 0x67, 0x68, 0x6e, 0x6b,
+ 0x67, 0x6c, 0x6e, 0x72, 0x79, 0x6e, 0x6b, 0x6a, 0x66, 0x6a, 0x65, 0x69, 0x75, 0x6a, 0x6e, 0x6a,
+ 0x61, 0x62, 0x79, 0x6c, 0x65, 0x74, 0x63, 0x76, 0x63, 0x6a, 0x68, 0x76, 0x6d, 0x69, 0x66, 0x68,
+ 0x67, 0x71, 0x66, 0x68, 0x66, 0x75, 0x76, 0x6e, 0x74, 0x70, 0x63, 0x67, 0x73, 0x68, 0x67, 0x61,
+ 0x74, 0x66, 0x65, 0x6e, 0x6b, 0x6c, 0x64, 0x6b, 0x70, 0x70, 0x75, 0x78, 0x76, 0x68, 0x74, 0x69,
+ 0x76, 0x77, 0x6e, 0x6c, 0x77, 0x76, 0x66, 0x6a, 0x61, 0x6a, 0x63, 0x6a, 0x6e, 0x73, 0x67, 0x73,
+ 0x6b, 0x6e, 0x75, 0x6a, 0x6a, 0x70, 0x73, 0x66, 0x78, 0x79, 0x61, 0x79, 0x6a, 0x6e, 0x76, 0x74,
+ 0x65, 0x74, 0x79, 0x6d, 0x6e, 0x79, 0x75, 0x76, 0x72, 0x6f, 0x6a, 0x67, 0x61, 0x66, 0x6a, 0x72,
+ 0x65, 0x79, 0x61, 0x6b, 0x65, 0x6b, 0x67, 0x77, 0x6a, 0x69, 0x73, 0x64, 0x6e, 0x6a, 0x68, 0x68,
+ 0x73, 0x76, 0x70, 0x78, 0x79, 0x6c, 0x71, 0x78, 0x6b, 0x77, 0x6b, 0x72, 0x70, 0x64, 0x75, 0x64,
+ 0x6a, 0x63, 0x69, 0x79, 0x70, 0x64, 0x72, 0x78, 0x72, 0x70, 0x79, 0x6a, 0x61, 0x6f, 0x73, 0x64,
+ 0x76, 0x79, 0x77, 0x71, 0x69, 0x75, 0x69, 0x6a, 0x77, 0x65, 0x77, 0x72, 0x6b, 0x61, 0x65, 0x78,
+ 0x65, 0x64, 0x66, 0x62, 0x6f, 0x72, 0x74, 0x72, 0x73, 0x71, 0x64, 0x77, 0x76, 0x70, 0x6c, 0x73,
+ 0x6e, 0x68, 0x6a, 0x62, 0x6d, 0x6f, 0x70, 0x78, 0x64, 0x6e, 0x65, 0x6f, 0x6d, 0x65, 0x64, 0x71,
+ 0x70, 0x6c, 0x6c, 0x6d, 0x6e, 0x71, 0x65, 0x66, 0x63, 0x74, 0x62, 0x71, 0x6a, 0x6c, 0x6b, 0x70,
+ 0x6a, 0x65, 0x6e, 0x6c, 0x6c, 0x69, 0x6e, 0x61, 0x79, 0x73, 0x78, 0x72, 0x65, 0x69, 0x78, 0x62,
+ 0x6f, 0x79, 0x6e, 0x63, 0x74, 0x6c, 0x65, 0x66, 0x72, 0x6d, 0x6a, 0x6c, 0x6b, 0x62, 0x6b, 0x6c,
+ 0x70, 0x65, 0x64, 0x70, 0x67, 0x71, 0x6c, 0x77, 0x6b, 0x66, 0x62, 0x77, 0x72, 0x6d, 0x6a, 0x62,
+ 0x61, 0x62, 0x65, 0x71, 0x78, 0x67, 0x62, 0x66, 0x69, 0x70, 0x79, 0x6b, 0x66, 0x6f, 0x62, 0x6c,
+ 0x61, 0x73, 0x61, 0x6c, 0x64, 0x62, 0x61, 0x70, 0x61, 0x63, 0x73, 0x6d, 0x76, 0x79, 0x68, 0x66,
+ 0x66, 0x6f, 0x66, 0x6f, 0x6a, 0x63, 0x61, 0x66, 0x75, 0x75, 0x61, 0x72, 0x61, 0x6a, 0x71, 0x6b,
+ 0x62, 0x65, 0x6c, 0x62, 0x62, 0x74, 0x69, 0x75, 0x69, 0x6f, 0x77, 0x65, 0x73, 0x72, 0x63, 0x72,
+ 0x62, 0x78, 0x75, 0x75, 0x6d, 0x70, 0x6c, 0x75, 0x6e, 0x72, 0x6f, 0x6c, 0x61, 0x61, 0x6d, 0x79,
+ 0x65, 0x71, 0x68, 0x6a, 0x6e, 0x6e, 0x6d, 0x69, 0x68, 0x75, 0x65, 0x6a, 0x72, 0x61, 0x77, 0x75,
+ 0x69, 0x73, 0x76, 0x6b, 0x64, 0x77, 0x75, 0x61, 0x68, 0x74, 0x65, 0x63, 0x69, 0x6e, 0x62, 0x6f,
+ 0x63, 0x79, 0x65, 0x65, 0x6e, 0x66, 0x6f, 0x6c, 0x61, 0x78, 0x69, 0x68, 0x73, 0x62, 0x61, 0x6f,
+ 0x65, 0x75, 0x70, 0x6a, 0x68, 0x72, 0x6e, 0x66, 0x62, 0x6a, 0x74, 0x61, 0x63, 0x72, 0x6e, 0x65,
+ 0x65, 0x67, 0x71, 0x79, 0x61, 0x63, 0x72, 0x6f, 0x77, 0x77, 0x77, 0x74, 0x67, 0x77, 0x68, 0x6c,
+ 0x72, 0x64, 0x61, 0x77, 0x64, 0x62, 0x6f, 0x63, 0x67, 0x77, 0x6a, 0x6b, 0x71, 0x78, 0x75, 0x6b,
+ 0x6a, 0x77, 0x76, 0x75, 0x6e, 0x6d, 0x61, 0x67, 0x74, 0x6c, 0x62, 0x75, 0x78, 0x63, 0x6a, 0x71,
+ 0x6f, 0x6f, 0x77, 0x6f, 0x74, 0x6c, 0x66, 0x73, 0x78, 0x75, 0x78, 0x62, 0x66, 0x62, 0x70, 0x78,
+ 0x65, 0x6a, 0x77, 0x71, 0x6c, 0x71, 0x65, 0x79, 0x79, 0x70, 0x6b, 0x70, 0x79, 0x6b, 0x78, 0x69,
+ 0x6d, 0x65, 0x6c, 0x66, 0x78, 0x73, 0x6e, 0x6a, 0x72, 0x77, 0x69, 0x76, 0x68, 0x78, 0x6b, 0x71,
+ 0x70, 0x76, 0x63, 0x61, 0x62, 0x79, 0x6f, 0x64, 0x6e, 0x72, 0x65, 0x72, 0x69, 0x69, 0x64, 0x65,
+ 0x6b, 0x71, 0x68, 0x6b, 0x6d, 0x6c, 0x6c, 0x62, 0x72, 0x71, 0x72, 0x65, 0x61, 0x69, 0x65, 0x71,
+ 0x6c, 0x6d, 0x66, 0x69, 0x67, 0x71, 0x6d, 0x6d, 0x71, 0x69, 0x6f, 0x69, 0x68, 0x6d, 0x61, 0x74,
+ 0x6f, 0x65, 0x6c, 0x68, 0x67, 0x79, 0x6b, 0x63, 0x69, 0x78, 0x61, 0x6f, 0x65, 0x6c, 0x79, 0x64,
+ 0x68, 0x66, 0x72, 0x6a, 0x6d, 0x64, 0x6d, 0x71, 0x6c, 0x64, 0x6b, 0x6d, 0x64, 0x74, 0x64, 0x62,
+ 0x72, 0x64, 0x67, 0x71, 0x68, 0x61, 0x76, 0x70, 0x69, 0x61, 0x73, 0x6a, 0x72, 0x62, 0x66, 0x75,
+ 0x64, 0x77, 0x70, 0x6e, 0x72, 0x6f, 0x76, 0x6f, 0x68, 0x73, 0x6c, 0x6a, 0x61, 0x78, 0x72, 0x73,
+ 0x70, 0x76, 0x76, 0x6b, 0x75, 0x71, 0x65, 0x6d, 0x6a, 0x67, 0x73, 0x64, 0x62, 0x68, 0x79, 0x74,
+ 0x71, 0x70, 0x66, 0x77, 0x6e, 0x72, 0x65, 0x75, 0x72, 0x74, 0x76, 0x72, 0x78, 0x64, 0x73, 0x68,
+ 0x71, 0x65, 0x74, 0x67, 0x6b, 0x67, 0x64, 0x61, 0x64, 0x63, 0x6e, 0x71, 0x6e, 0x74, 0x76, 0x67,
+ 0x6b, 0x6c, 0x6c, 0x63, 0x6e, 0x70, 0x72, 0x76, 0x65, 0x72, 0x6c, 0x6f, 0x64, 0x71, 0x66, 0x78,
+ 0x66, 0x6c, 0x62, 0x76, 0x75, 0x69, 0x65, 0x70, 0x75, 0x76, 0x77, 0x6e, 0x78, 0x6a, 0x6f, 0x6e,
+ 0x67, 0x73, 0x6b, 0x61, 0x6b, 0x6a, 0x6a, 0x72, 0x6f, 0x69, 0x77, 0x61, 0x61, 0x75, 0x6f, 0x71,
+ 0x76, 0x76, 0x70, 0x71, 0x75, 0x63, 0x75, 0x6d, 0x6e, 0x74, 0x68, 0x63, 0x64, 0x6c, 0x65, 0x74,
+ 0x77, 0x64, 0x72, 0x67, 0x73, 0x72, 0x65, 0x61, 0x64, 0x70, 0x71, 0x76, 0x6a, 0x79, 0x6f, 0x6e,
+ 0x61, 0x71, 0x63, 0x76, 0x78, 0x71, 0x63, 0x77, 0x66, 0x75, 0x78, 0x67, 0x6e, 0x66, 0x6c, 0x61,
+ 0x6d, 0x78, 0x79, 0x61, 0x67, 0x6c, 0x79, 0x6e, 0x68, 0x6d, 0x66, 0x67, 0x61, 0x75, 0x76, 0x73,
+ 0x6c, 0x6c, 0x76, 0x6c, 0x6f, 0x61, 0x71, 0x61, 0x73, 0x72, 0x69, 0x6e, 0x64, 0x78, 0x73, 0x79,
+ 0x64, 0x63, 0x69, 0x61, 0x71, 0x65, 0x74, 0x65, 0x6b, 0x6d, 0x75, 0x74, 0x61, 0x64, 0x77, 0x65,
+ 0x78, 0x71, 0x64, 0x65, 0x6b, 0x71, 0x6d, 0x6b, 0x70, 0x6c, 0x62, 0x68, 0x64, 0x62, 0x63, 0x62,
+ 0x6c, 0x70, 0x6b, 0x72, 0x78, 0x62, 0x79, 0x68, 0x6e, 0x79, 0x6a, 0x65, 0x6d, 0x69, 0x64, 0x79,
+ 0x6d, 0x6a, 0x69, 0x6d, 0x79, 0x69, 0x6e, 0x76, 0x6d, 0x74, 0x71, 0x79, 0x74, 0x6a, 0x70, 0x6f,
+ 0x79, 0x6c, 0x6e, 0x71, 0x63, 0x77, 0x76, 0x64, 0x66, 0x6c, 0x74, 0x64, 0x68, 0x65, 0x75, 0x72,
+ 0x73, 0x6a, 0x65, 0x67, 0x73, 0x69, 0x6b, 0x6f, 0x64, 0x62, 0x61, 0x74, 0x70, 0x73, 0x6f, 0x6a,
+ 0x6a, 0x6b, 0x6a, 0x67, 0x6a, 0x66, 0x72, 0x6e, 0x73, 0x62, 0x65, 0x77, 0x6a, 0x70, 0x65, 0x69,
+ 0x6a, 0x70, 0x61, 0x62, 0x6f, 0x63, 0x62, 0x77, 0x77, 0x6b, 0x65, 0x75, 0x63, 0x65, 0x61, 0x65,
+ 0x68, 0x66, 0x67, 0x75, 0x61, 0x67, 0x79, 0x71, 0x6a, 0x66, 0x65, 0x73, 0x6c, 0x64, 0x70, 0x65,
+ 0x68, 0x6e, 0x71, 0x6b, 0x74, 0x67, 0x77, 0x75, 0x6a, 0x79, 0x74, 0x70, 0x79, 0x6d, 0x62, 0x6e,
+ 0x71, 0x75, 0x72, 0x62, 0x6b, 0x6d, 0x68, 0x71, 0x78, 0x66, 0x67, 0x75, 0x6a, 0x6f, 0x6f, 0x67,
+ 0x6b, 0x62, 0x67, 0x63, 0x63, 0x71, 0x62, 0x79, 0x68, 0x6e, 0x77, 0x70, 0x68, 0x73, 0x64, 0x76,
+ 0x65, 0x75, 0x6e, 0x66, 0x6a, 0x75, 0x61, 0x63, 0x6b, 0x73, 0x62, 0x61, 0x71, 0x69, 0x6b, 0x70,
+ 0x6c, 0x76, 0x79, 0x77, 0x6c, 0x6c, 0x64, 0x6e, 0x6d, 0x79, 0x71, 0x62, 0x70, 0x6f, 0x6e, 0x6d,
+ 0x73, 0x74, 0x69, 0x76, 0x6f, 0x74, 0x71, 0x73, 0x78, 0x6c, 0x61, 0x70, 0x78, 0x78, 0x6f, 0x67,
+ 0x68, 0x70, 0x72, 0x64, 0x71, 0x6d, 0x6a, 0x67, 0x75, 0x61, 0x78, 0x71, 0x74, 0x73, 0x63, 0x6c,
+ 0x65, 0x66, 0x6c, 0x72, 0x6d, 0x77, 0x6f, 0x62, 0x77, 0x70, 0x68, 0x68, 0x72, 0x72, 0x66, 0x73,
+ 0x74, 0x79, 0x69, 0x79, 0x65, 0x79, 0x68, 0x67, 0x69, 0x71, 0x74, 0x75, 0x65, 0x6c, 0x62, 0x61,
+ 0x63, 0x64, 0x74, 0x63, 0x76, 0x77, 0x79, 0x65, 0x73, 0x63, 0x73, 0x6c, 0x6d, 0x6b, 0x6a, 0x78,
+ 0x6c, 0x67, 0x76, 0x64, 0x68, 0x73, 0x63, 0x78, 0x66, 0x73, 0x78, 0x67, 0x75, 0x70, 0x63, 0x63,
+ 0x61, 0x77, 0x6f, 0x68, 0x6d, 0x6d, 0x74, 0x6a, 0x66, 0x62, 0x61, 0x76, 0x62, 0x63, 0x6c, 0x6f,
+ 0x68, 0x6f, 0x74, 0x69, 0x6a, 0x6b, 0x6c, 0x70, 0x78, 0x6a, 0x75, 0x63, 0x67, 0x6d, 0x6e, 0x6e,
+ 0x6f, 0x63, 0x69, 0x64, 0x66, 0x72, 0x69, 0x6d, 0x6d, 0x6a, 0x74, 0x74, 0x62, 0x6a, 0x61, 0x67,
+ 0x79, 0x6f, 0x78, 0x62, 0x6e, 0x63, 0x64, 0x74, 0x71, 0x75, 0x6d, 0x73, 0x72, 0x67, 0x6f, 0x72,
+ 0x6d, 0x70, 0x6f, 0x6c, 0x6b, 0x66, 0x69, 0x79, 0x63, 0x79, 0x79, 0x63, 0x66, 0x70, 0x6c, 0x61,
+ 0x6a, 0x61, 0x62, 0x76, 0x70, 0x71, 0x73, 0x71, 0x72, 0x63, 0x77, 0x78, 0x62, 0x6b, 0x75, 0x68,
+ 0x69, 0x75, 0x6b, 0x77, 0x71, 0x6e, 0x61, 0x6e, 0x62, 0x79, 0x6d, 0x61, 0x6e, 0x63, 0x6a, 0x74,
+ 0x77, 0x6d, 0x78, 0x64, 0x75, 0x6b, 0x79, 0x79, 0x73, 0x62, 0x67, 0x62, 0x75, 0x6f, 0x72, 0x67,
+ 0x6f, 0x76, 0x73, 0x68, 0x66, 0x6f, 0x78, 0x72, 0x69, 0x64, 0x61, 0x66, 0x69, 0x6c, 0x6a, 0x71,
+ 0x73, 0x75, 0x6a, 0x69, 0x71, 0x64, 0x6c, 0x61, 0x72, 0x67, 0x71, 0x76, 0x6d, 0x64, 0x74, 0x72,
+ 0x78, 0x67, 0x6d, 0x70, 0x65, 0x79, 0x61, 0x6d, 0x79, 0x6a, 0x68, 0x67, 0x6c, 0x64, 0x70, 0x74,
+ 0x62, 0x70, 0x6c, 0x6d, 0x72, 0x6e, 0x72, 0x68, 0x70, 0x78, 0x6f, 0x6e, 0x6b, 0x72, 0x66, 0x77,
+ 0x72, 0x61, 0x64, 0x68, 0x6b, 0x61, 0x6a, 0x6d, 0x77, 0x6c, 0x63, 0x78, 0x6c, 0x65, 0x63, 0x74,
+ 0x78, 0x76, 0x68, 0x61, 0x6f, 0x6b, 0x64, 0x66, 0x73, 0x72, 0x73, 0x66, 0x65, 0x67, 0x6d, 0x70,
+ 0x69, 0x63, 0x75, 0x6a, 0x79, 0x6e, 0x6d, 0x79, 0x63, 0x71, 0x61, 0x75, 0x76, 0x79, 0x73, 0x66,
+ 0x76, 0x61, 0x6c, 0x71, 0x69, 0x71, 0x6b, 0x66, 0x65, 0x78, 0x78, 0x63, 0x6d, 0x78, 0x6c, 0x6e,
+ 0x6e, 0x79, 0x69, 0x6a, 0x6f, 0x75, 0x64, 0x6c, 0x65, 0x71, 0x68, 0x78, 0x67, 0x73, 0x76, 0x75,
+ 0x70, 0x6c, 0x6d, 0x6f, 0x6c, 0x64, 0x67, 0x73, 0x74, 0x73, 0x6b, 0x6b, 0x78, 0x68, 0x77, 0x62,
+ 0x74, 0x79, 0x72, 0x6f, 0x6f, 0x76, 0x73, 0x74, 0x76, 0x67, 0x6d, 0x6c, 0x71, 0x75, 0x61, 0x6a,
+ 0x69, 0x77, 0x6d, 0x68, 0x72, 0x72, 0x6b, 0x6b, 0x69, 0x6c, 0x6c, 0x63, 0x68, 0x62, 0x76, 0x6c,
+ 0x78, 0x69, 0x79, 0x62, 0x79, 0x68, 0x71, 0x62, 0x70, 0x72, 0x6e, 0x66, 0x71, 0x71, 0x67, 0x63,
+ 0x69, 0x67, 0x70, 0x6b, 0x76, 0x69, 0x79, 0x78, 0x73, 0x74, 0x69, 0x67, 0x6a, 0x78, 0x63, 0x66,
+ 0x65, 0x65, 0x64, 0x65, 0x72, 0x6d, 0x67, 0x72, 0x64, 0x70, 0x73, 0x66, 0x6e, 0x73, 0x70, 0x65,
+ 0x6e, 0x61, 0x68, 0x66, 0x66, 0x6a, 0x75, 0x6a, 0x65, 0x66, 0x70, 0x65, 0x66, 0x6b, 0x77, 0x63,
+ 0x62, 0x6c, 0x61, 0x73, 0x77, 0x70, 0x65, 0x72, 0x61, 0x69, 0x76, 0x62, 0x6b, 0x72, 0x64, 0x69,
+ 0x61, 0x62, 0x6d, 0x79, 0x64, 0x76, 0x61, 0x76, 0x69, 0x72, 0x64, 0x73, 0x76, 0x66, 0x67, 0x6b,
+ 0x71, 0x75, 0x6b, 0x75, 0x76, 0x68, 0x77, 0x63, 0x79, 0x76, 0x6c, 0x69, 0x67, 0x69, 0x76, 0x6d,
+ 0x79, 0x6c, 0x62, 0x65, 0x66, 0x76, 0x73, 0x78, 0x73, 0x75, 0x6e, 0x68, 0x6e, 0x61, 0x79, 0x75,
+ 0x6f, 0x77, 0x71, 0x6d, 0x62, 0x74, 0x63, 0x67, 0x66, 0x68, 0x63, 0x79, 0x72, 0x75, 0x6a, 0x78,
+ 0x79, 0x75, 0x66, 0x75, 0x6e, 0x61, 0x6a, 0x6b, 0x72, 0x75, 0x6f, 0x6f, 0x6f, 0x75, 0x78, 0x70,
+ 0x71, 0x68, 0x76, 0x67, 0x65, 0x63, 0x78, 0x78, 0x6d, 0x73, 0x63, 0x63, 0x74, 0x67, 0x71, 0x6c,
+ 0x75, 0x78, 0x74, 0x6e, 0x66, 0x62, 0x6e, 0x63, 0x78, 0x75, 0x64, 0x78, 0x69, 0x67, 0x6b, 0x64,
+ 0x6d, 0x6f, 0x79, 0x74, 0x61, 0x6f, 0x64, 0x67, 0x71, 0x77, 0x62, 0x63, 0x6d, 0x64, 0x76, 0x67,
+ 0x63, 0x79, 0x75, 0x74, 0x6f, 0x68, 0x73, 0x77, 0x69, 0x76, 0x6e, 0x68, 0x6a, 0x6a, 0x79, 0x75,
+ 0x65, 0x68, 0x69, 0x6e, 0x6d, 0x6a, 0x69, 0x68, 0x65, 0x6c, 0x77, 0x62, 0x61, 0x6b, 0x6d, 0x77,
+ 0x78, 0x70, 0x6a, 0x73, 0x79, 0x6b, 0x63, 0x6e, 0x79, 0x6d, 0x65, 0x72, 0x75, 0x66, 0x6c, 0x79,
+ 0x6f, 0x6e, 0x77, 0x69, 0x6d, 0x72, 0x70, 0x74, 0x75, 0x62, 0x75, 0x72, 0x6c, 0x65, 0x77, 0x66,
+ 0x78, 0x62, 0x70, 0x70, 0x6c, 0x6e, 0x69, 0x78, 0x73, 0x79, 0x71, 0x6b, 0x6d, 0x75, 0x62, 0x76,
+ 0x63, 0x65, 0x6d, 0x67, 0x6c, 0x66, 0x74, 0x6d, 0x6b, 0x72, 0x66, 0x6e, 0x61, 0x6f, 0x6d, 0x61,
+ 0x67, 0x6b, 0x66, 0x71, 0x71, 0x6a, 0x6e, 0x72, 0x78, 0x64, 0x71, 0x73, 0x63, 0x79, 0x74, 0x72,
+ 0x74, 0x70, 0x77, 0x66, 0x73, 0x79, 0x71, 0x65, 0x6a, 0x73, 0x66, 0x66, 0x67, 0x63, 0x65, 0x6f,
+ 0x71, 0x6c, 0x73, 0x79, 0x73, 0x67, 0x78, 0x74, 0x61, 0x6f, 0x6a, 0x75, 0x74, 0x70, 0x76, 0x78,
+ 0x69, 0x6b, 0x75, 0x78, 0x6f, 0x68, 0x6c, 0x65, 0x65, 0x61, 0x71, 0x65, 0x66, 0x67, 0x66, 0x74,
+ 0x79, 0x6c, 0x62, 0x74, 0x69, 0x66, 0x79, 0x61, 0x79, 0x77, 0x64, 0x69, 0x70, 0x67, 0x73, 0x6b,
+ 0x75, 0x74, 0x6c, 0x68, 0x74, 0x62, 0x64, 0x66, 0x76, 0x6a, 0x69, 0x72, 0x68, 0x73, 0x65, 0x63,
+ 0x74, 0x61, 0x6e, 0x6c, 0x63, 0x64, 0x67, 0x6d, 0x68, 0x75, 0x63, 0x6a, 0x68, 0x64, 0x79, 0x61,
+ 0x6b, 0x77, 0x6a, 0x66, 0x75, 0x79, 0x6b, 0x65, 0x6f, 0x77, 0x75, 0x62, 0x72, 0x77, 0x75, 0x73,
+ 0x64, 0x69, 0x79, 0x61, 0x73, 0x67, 0x6b, 0x68, 0x62, 0x75, 0x69, 0x6f, 0x6a, 0x64, 0x77, 0x68,
+ 0x65, 0x65, 0x66, 0x61, 0x61, 0x68, 0x72, 0x6a, 0x69, 0x6b, 0x77, 0x71, 0x78, 0x6c, 0x6b, 0x74,
+ 0x76, 0x6c, 0x6a, 0x70, 0x63, 0x6f, 0x71, 0x65, 0x65, 0x6f, 0x69, 0x71, 0x62, 0x73, 0x6c, 0x75,
+ 0x6a, 0x74, 0x61, 0x78, 0x6d, 0x62, 0x6e, 0x6e, 0x79, 0x69, 0x68, 0x69, 0x77, 0x6c, 0x6a, 0x6c,
+ 0x75, 0x62, 0x6e, 0x66, 0x67, 0x66, 0x62, 0x71, 0x75, 0x69, 0x66, 0x6c, 0x68, 0x75, 0x71, 0x61,
+ 0x78, 0x62, 0x69, 0x64, 0x6c, 0x66, 0x70, 0x61, 0x64, 0x61, 0x70, 0x63, 0x6b, 0x6d, 0x78, 0x62,
+ 0x6f, 0x65, 0x71, 0x73, 0x75, 0x66, 0x6a, 0x69, 0x6b, 0x64, 0x63, 0x6f, 0x63, 0x6d, 0x69, 0x73,
+ 0x79, 0x77, 0x69, 0x68, 0x66, 0x70, 0x76, 0x6e, 0x6f, 0x64, 0x72, 0x79, 0x70, 0x66, 0x6f, 0x63,
+ 0x79, 0x64, 0x76, 0x69, 0x70, 0x6e, 0x65, 0x67, 0x73, 0x6c, 0x63, 0x6f, 0x77, 0x67, 0x63, 0x6a,
+ 0x69, 0x6a, 0x6f, 0x74, 0x61, 0x68, 0x6b, 0x63, 0x6c, 0x63, 0x71, 0x68, 0x61, 0x70, 0x70, 0x64,
+ 0x62, 0x6b, 0x68, 0x75, 0x63, 0x6e, 0x78, 0x68, 0x61, 0x71, 0x6e, 0x77, 0x6f, 0x6b, 0x78, 0x78,
+ 0x74, 0x73, 0x70, 0x77, 0x66, 0x61, 0x6b, 0x77, 0x6c, 0x63, 0x76, 0x65, 0x79, 0x73, 0x76, 0x79,
+ 0x68, 0x78, 0x6b, 0x73, 0x61, 0x71, 0x77, 0x70, 0x61, 0x6b, 0x79, 0x73, 0x6b, 0x6c, 0x77, 0x63,
+ 0x69, 0x62, 0x77, 0x64, 0x68, 0x6c, 0x68, 0x79, 0x62, 0x72, 0x6a, 0x62, 0x72, 0x62, 0x61, 0x6b,
+ 0x71, 0x63, 0x63, 0x66, 0x62, 0x6a, 0x75, 0x65, 0x79, 0x6e, 0x65, 0x63, 0x6a, 0x75, 0x63, 0x79,
+ 0x74, 0x69, 0x69, 0x76, 0x78, 0x66, 0x68, 0x6c, 0x67, 0x77, 0x65, 0x6f, 0x76, 0x75, 0x61, 0x63,
+ 0x71, 0x73, 0x76, 0x64, 0x69, 0x64, 0x75, 0x64, 0x71, 0x62, 0x74, 0x6f, 0x74, 0x63, 0x66, 0x63,
+ 0x74, 0x70, 0x6d, 0x66, 0x6f, 0x6f, 0x6b, 0x79, 0x74, 0x61, 0x70, 0x76, 0x6d, 0x6f, 0x70, 0x64,
+ 0x74, 0x68, 0x6a, 0x6e, 0x6b, 0x70, 0x68, 0x64, 0x72, 0x72, 0x75, 0x63, 0x6e, 0x69, 0x69, 0x61,
+ 0x6f, 0x64, 0x76, 0x6a, 0x69, 0x6e, 0x79, 0x70, 0x61, 0x64, 0x76, 0x69, 0x6d, 0x6b, 0x67, 0x6a,
+ 0x6e, 0x67, 0x63, 0x6f, 0x78, 0x79, 0x73, 0x64, 0x77, 0x77, 0x72, 0x73, 0x61, 0x65, 0x6a, 0x65,
+ 0x6d, 0x62, 0x6b, 0x69, 0x78, 0x6d, 0x78, 0x74, 0x62, 0x75, 0x79, 0x6b, 0x66, 0x65, 0x73, 0x64,
+ 0x67, 0x72, 0x61, 0x64, 0x6c, 0x64, 0x61, 0x6f, 0x74, 0x64, 0x68, 0x73, 0x69, 0x6d, 0x69, 0x6f,
+ 0x6f, 0x71, 0x70, 0x77, 0x75, 0x77, 0x71, 0x73, 0x75, 0x63, 0x79, 0x74, 0x6f, 0x79, 0x6f, 0x63,
+ 0x64, 0x72, 0x78, 0x70, 0x63, 0x65, 0x62, 0x6e, 0x65, 0x64, 0x70, 0x6a, 0x6f, 0x63, 0x70, 0x6b,
+ 0x67, 0x73, 0x78, 0x61, 0x77, 0x70, 0x6e, 0x70, 0x78, 0x71, 0x61, 0x63, 0x6d, 0x68, 0x6a, 0x63,
+ 0x74, 0x73, 0x62, 0x75, 0x74, 0x75, 0x6c, 0x6b, 0x6c, 0x76, 0x6b, 0x65, 0x6a, 0x77, 0x77, 0x64,
+ 0x77, 0x6f, 0x6f, 0x70, 0x61, 0x74, 0x65, 0x74, 0x6d, 0x6f, 0x68, 0x77, 0x6b, 0x63, 0x65, 0x62,
+ 0x6a, 0x74, 0x6b, 0x78, 0x6d, 0x76, 0x63, 0x73, 0x6c, 0x68, 0x6f, 0x6d, 0x6c, 0x78, 0x79, 0x6b,
+ 0x74, 0x74, 0x66, 0x69, 0x76, 0x70, 0x6f, 0x6f, 0x78, 0x61, 0x6d, 0x68, 0x77, 0x75, 0x74, 0x79,
+ 0x68, 0x6f, 0x63, 0x64, 0x6b, 0x72, 0x65, 0x68, 0x70, 0x6c, 0x61, 0x79, 0x73, 0x6d, 0x72, 0x75,
+ 0x74, 0x75, 0x6d, 0x6f, 0x6f, 0x65, 0x68, 0x64, 0x6a, 0x74, 0x64, 0x68, 0x62, 0x70, 0x6d, 0x68,
+ 0x73, 0x6d, 0x65, 0x76, 0x75, 0x64, 0x65, 0x66, 0x77, 0x69, 0x71, 0x6a, 0x64, 0x6b, 0x73, 0x6f,
+ 0x70, 0x6c, 0x6e, 0x6c, 0x6a, 0x66, 0x67, 0x78, 0x61, 0x79, 0x68, 0x63, 0x70, 0x79, 0x68, 0x6c,
+ 0x70, 0x6c, 0x76, 0x64, 0x68, 0x76, 0x67, 0x73, 0x65, 0x62, 0x65, 0x71, 0x71, 0x79, 0x72, 0x77,
+ 0x65, 0x77, 0x79, 0x78, 0x72, 0x75, 0x6e, 0x71, 0x68, 0x72, 0x64, 0x66, 0x64, 0x63, 0x68, 0x79,
+ 0x66, 0x70, 0x67, 0x64, 0x75, 0x62, 0x79, 0x66, 0x62, 0x74, 0x6b, 0x72, 0x6a, 0x70, 0x78, 0x61,
+ 0x70, 0x6e, 0x76, 0x63, 0x6a, 0x62, 0x76, 0x69, 0x68, 0x77, 0x6c, 0x73, 0x62, 0x68, 0x65, 0x6f,
+ 0x6f, 0x6c, 0x65, 0x6e, 0x66, 0x6a, 0x71, 0x69, 0x71, 0x66, 0x63, 0x6e, 0x63, 0x6d, 0x67, 0x78,
+ 0x72, 0x72, 0x66, 0x79, 0x66, 0x75, 0x72, 0x73, 0x69, 0x76, 0x75, 0x75, 0x69, 0x64, 0x6f, 0x6e,
+ 0x67, 0x67, 0x78, 0x72, 0x72, 0x71, 0x71, 0x69, 0x61, 0x66, 0x6f, 0x6d, 0x67, 0x68, 0x63, 0x62,
+ 0x6b, 0x6b, 0x6c, 0x61, 0x63, 0x65, 0x62, 0x76, 0x72, 0x74, 0x6c, 0x78, 0x68, 0x64, 0x71, 0x78,
+ 0x76, 0x6c, 0x72, 0x71, 0x73, 0x79, 0x66, 0x67, 0x72, 0x76, 0x6c, 0x75, 0x68, 0x6b, 0x70, 0x6e,
+ 0x63, 0x62, 0x6d, 0x67, 0x64, 0x70, 0x68, 0x68, 0x6c, 0x65, 0x77, 0x61, 0x75, 0x71, 0x61, 0x6d,
+ 0x6d, 0x67, 0x6c, 0x69, 0x63, 0x6a, 0x6d, 0x62, 0x6a, 0x77, 0x73, 0x6d, 0x65, 0x6f, 0x73, 0x76,
+ 0x69, 0x6f, 0x70, 0x66, 0x64, 0x73, 0x69, 0x72, 0x71, 0x6a, 0x79, 0x74, 0x6e, 0x65, 0x6a, 0x6b,
+ 0x63, 0x76, 0x66, 0x66, 0x72, 0x6e, 0x79, 0x6d, 0x6b, 0x6d, 0x75, 0x76, 0x68, 0x70, 0x6a, 0x78,
+ 0x6a, 0x6c, 0x78, 0x68, 0x77, 0x66, 0x75, 0x62, 0x6c, 0x75, 0x79, 0x69, 0x6a, 0x6e, 0x78, 0x74,
+ 0x6c, 0x6e, 0x65, 0x78, 0x64, 0x6f, 0x78, 0x68, 0x76, 0x6c, 0x75, 0x73, 0x62, 0x62, 0x79, 0x68,
+ 0x6d, 0x77, 0x75, 0x6d, 0x67, 0x6c, 0x68, 0x72, 0x72, 0x65, 0x62, 0x68, 0x67, 0x61, 0x74, 0x63,
+ 0x72, 0x6c, 0x63, 0x65, 0x74, 0x78, 0x6a, 0x68, 0x71, 0x71, 0x6b, 0x64, 0x79, 0x77, 0x73, 0x68,
+ 0x69, 0x76, 0x64, 0x62, 0x77, 0x75, 0x78, 0x76, 0x67, 0x65, 0x75, 0x67, 0x75, 0x68, 0x6e, 0x64,
+ 0x79, 0x67, 0x77, 0x6f, 0x68, 0x70, 0x69, 0x64, 0x61, 0x62, 0x69, 0x76, 0x64, 0x78, 0x71, 0x6e,
+ 0x6e, 0x69, 0x61, 0x68, 0x75, 0x76, 0x6c, 0x74, 0x68, 0x63, 0x6d, 0x79, 0x73, 0x69, 0x61, 0x64,
+ 0x6c, 0x69, 0x74, 0x75, 0x69, 0x70, 0x69, 0x73, 0x74, 0x6c, 0x62, 0x6c, 0x6e, 0x6c, 0x6f, 0x73,
+ 0x61, 0x63, 0x6e, 0x66, 0x72, 0x63, 0x65, 0x71, 0x62, 0x68, 0x77, 0x74, 0x6d, 0x62, 0x62, 0x75,
+ 0x69, 0x75, 0x63, 0x63, 0x6b, 0x68, 0x70, 0x71, 0x63, 0x6f, 0x65, 0x70, 0x6a, 0x78, 0x73, 0x61,
+ 0x68, 0x75, 0x71, 0x66, 0x6a, 0x77, 0x6b, 0x6a, 0x76, 0x79, 0x61, 0x64, 0x6a, 0x6f, 0x68, 0x72,
+ 0x78, 0x64, 0x75, 0x6f, 0x64, 0x64, 0x6d, 0x65, 0x75, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x65, 0x6d,
+ 0x6d, 0x72, 0x65, 0x62, 0x70, 0x64, 0x64, 0x69, 0x6b, 0x6a, 0x63, 0x78, 0x6c, 0x74, 0x61, 0x68,
+ 0x61, 0x6e, 0x6c, 0x75, 0x73, 0x62, 0x62, 0x6e, 0x71, 0x62, 0x6a, 0x78, 0x65, 0x63, 0x61, 0x65,
+ 0x75, 0x73, 0x66, 0x61, 0x6b, 0x74, 0x6b, 0x65, 0x6f, 0x69, 0x63, 0x6e, 0x6f, 0x69, 0x6b, 0x62,
+ 0x65, 0x73, 0x64, 0x64, 0x6d, 0x72, 0x76, 0x66, 0x76, 0x76, 0x72, 0x6d, 0x67, 0x6a, 0x65, 0x6d,
+ 0x73, 0x65, 0x67, 0x79, 0x79, 0x63, 0x62, 0x6a, 0x6e, 0x68, 0x71, 0x65, 0x69, 0x6a, 0x6e, 0x63,
+ 0x76, 0x72, 0x6c, 0x67, 0x6f, 0x6d, 0x64, 0x74, 0x61, 0x76, 0x6d, 0x76, 0x6d, 0x75, 0x64, 0x6a,
+ 0x64, 0x63, 0x75, 0x70, 0x64, 0x6a, 0x68, 0x72, 0x65, 0x64, 0x79, 0x79, 0x72, 0x6a, 0x6d, 0x77,
+ 0x75, 0x64, 0x6f, 0x72, 0x63, 0x65, 0x74, 0x72, 0x6e, 0x67, 0x66, 0x70, 0x63, 0x6d, 0x64, 0x65,
+ 0x63, 0x72, 0x69, 0x6a, 0x74, 0x68, 0x77, 0x74, 0x72, 0x79, 0x77, 0x71, 0x6c, 0x6d, 0x79, 0x6f,
+ 0x62, 0x79, 0x72, 0x61, 0x62, 0x6a, 0x77, 0x76, 0x61, 0x6d, 0x74, 0x65, 0x73, 0x69, 0x6f, 0x74,
+ 0x76, 0x68, 0x71, 0x76, 0x67, 0x76, 0x62, 0x6f, 0x63, 0x6f, 0x6c, 0x77, 0x69, 0x6a, 0x62, 0x64,
+ 0x62, 0x74, 0x6a, 0x69, 0x71, 0x6a, 0x6c, 0x78, 0x67, 0x78, 0x67, 0x65, 0x65, 0x70, 0x79, 0x65,
+ 0x71, 0x75, 0x6c, 0x6e, 0x6b, 0x68, 0x6e, 0x62, 0x78, 0x65, 0x76, 0x69, 0x6d, 0x66, 0x6a, 0x70,
+ 0x6c, 0x63, 0x68, 0x75, 0x6a, 0x6c, 0x73, 0x75, 0x68, 0x6d, 0x63, 0x73, 0x68, 0x6e, 0x64, 0x6f,
+ 0x61, 0x65, 0x75, 0x6a, 0x75, 0x62, 0x76, 0x79, 0x6d, 0x64, 0x71, 0x76, 0x78, 0x62, 0x6a, 0x75,
+ 0x6c, 0x6b, 0x77, 0x79, 0x6a, 0x6a, 0x77, 0x74, 0x6a, 0x72, 0x73, 0x66, 0x72, 0x63, 0x69, 0x75,
+ 0x62, 0x70, 0x77, 0x6e, 0x62, 0x65, 0x71, 0x71, 0x6c, 0x76, 0x6b, 0x73, 0x6e, 0x64, 0x74, 0x75,
+ 0x62, 0x79, 0x71, 0x77, 0x75, 0x73, 0x6f, 0x76, 0x6d, 0x6a, 0x73, 0x72, 0x62, 0x6d, 0x69, 0x73,
+ 0x6a, 0x6a, 0x6d, 0x6f, 0x73, 0x63, 0x72, 0x75, 0x6c, 0x6c, 0x68, 0x67, 0x70, 0x74, 0x61, 0x73,
+ 0x78, 0x6d, 0x63, 0x6c, 0x6d, 0x74, 0x71, 0x65, 0x67, 0x74, 0x75, 0x6a, 0x6f, 0x6a, 0x6e, 0x64,
+ 0x6d, 0x68, 0x63, 0x77, 0x79, 0x6a, 0x65, 0x6b, 0x62, 0x6a, 0x66, 0x6b, 0x76, 0x73, 0x74, 0x75,
+ 0x6b, 0x6a, 0x79, 0x69, 0x6d, 0x6c, 0x79, 0x6a, 0x79, 0x79, 0x79, 0x78, 0x71, 0x75, 0x76, 0x67,
+ 0x70, 0x64, 0x69, 0x74, 0x70, 0x61, 0x62, 0x79, 0x65, 0x6e, 0x65, 0x6e, 0x77, 0x63, 0x67, 0x73,
+ 0x79, 0x77, 0x6a, 0x73, 0x78, 0x61, 0x62, 0x76, 0x74, 0x6f, 0x6b, 0x6f, 0x75, 0x6b, 0x6f, 0x67,
+ 0x6b, 0x67, 0x76, 0x65, 0x6b, 0x70, 0x6d, 0x6a, 0x61, 0x70, 0x6c, 0x67, 0x61, 0x64, 0x74, 0x63,
+ 0x63, 0x6b, 0x73, 0x74, 0x68, 0x6d, 0x6d, 0x69, 0x79, 0x65, 0x67, 0x71, 0x6e, 0x66, 0x6b, 0x72,
+ 0x69, 0x75, 0x6f, 0x65, 0x61, 0x75, 0x71, 0x67, 0x63, 0x70, 0x6b, 0x63, 0x76, 0x73, 0x64, 0x6a,
+ 0x6e, 0x61, 0x75, 0x72, 0x68, 0x6d, 0x62, 0x68, 0x65, 0x67, 0x79, 0x63, 0x6f, 0x66, 0x68, 0x68,
+ 0x66, 0x61, 0x79, 0x68, 0x62, 0x74, 0x70, 0x69, 0x6e, 0x6a, 0x78, 0x65, 0x6c, 0x77, 0x79, 0x73,
+ 0x69, 0x62, 0x71, 0x63, 0x62, 0x73, 0x65, 0x65, 0x6b, 0x6f, 0x6f, 0x71, 0x6b, 0x62, 0x6f, 0x68,
+ 0x75, 0x66, 0x78, 0x62, 0x73, 0x6d, 0x62, 0x71, 0x64, 0x6a, 0x6c, 0x63, 0x76, 0x66, 0x66, 0x69,
+ 0x62, 0x6c, 0x6a, 0x69, 0x78, 0x78, 0x65, 0x68, 0x73, 0x70, 0x65, 0x6f, 0x67, 0x73, 0x79, 0x69,
+ 0x67, 0x71, 0x70, 0x62, 0x6e, 0x65, 0x63, 0x62, 0x69, 0x70, 0x6e, 0x6f, 0x70, 0x77, 0x64, 0x62,
+ 0x6e, 0x6e, 0x69, 0x66, 0x61, 0x61, 0x79, 0x62, 0x68, 0x72, 0x6a, 0x75, 0x6c, 0x6f, 0x73, 0x75,
+ 0x6a, 0x73, 0x62, 0x6e, 0x6f, 0x65, 0x65, 0x62, 0x6d, 0x6a, 0x71, 0x6c, 0x6c, 0x77, 0x71, 0x6c,
+ 0x69, 0x6a, 0x6c, 0x74, 0x6a, 0x6b, 0x73, 0x78, 0x72, 0x6e, 0x68, 0x64, 0x69, 0x63, 0x73, 0x78,
+ 0x77, 0x6b, 0x6a, 0x6b, 0x78, 0x72, 0x61, 0x6d, 0x6b, 0x64, 0x71, 0x75, 0x6d, 0x65, 0x71, 0x71,
+ 0x6b, 0x61, 0x72, 0x71, 0x6e, 0x76, 0x77, 0x6e, 0x61, 0x66, 0x6d, 0x66, 0x68, 0x6a, 0x64, 0x6a,
+ 0x66, 0x75, 0x66, 0x6c, 0x76, 0x64, 0x73, 0x6a, 0x6c, 0x63, 0x6d, 0x71, 0x67, 0x73, 0x74, 0x76,
+ 0x74, 0x66, 0x70, 0x75, 0x6c, 0x6c, 0x63, 0x74, 0x70, 0x68, 0x6e, 0x78, 0x61, 0x73, 0x6a, 0x6f,
+ 0x67, 0x78, 0x6d, 0x79, 0x62, 0x68, 0x6f, 0x66, 0x64, 0x78, 0x61, 0x64, 0x6d, 0x61, 0x74, 0x72,
+ 0x61, 0x77, 0x6a, 0x79, 0x75, 0x66, 0x6f, 0x6c, 0x79, 0x78, 0x76, 0x76, 0x72, 0x69, 0x6f, 0x79,
+ 0x65, 0x62, 0x65, 0x73, 0x6e, 0x61, 0x6e, 0x71, 0x63, 0x68, 0x6e, 0x76, 0x64, 0x6f, 0x69, 0x62,
+ 0x6e, 0x6c, 0x6e, 0x79, 0x71, 0x79, 0x73, 0x72, 0x71, 0x65, 0x6b, 0x65, 0x65, 0x76, 0x65, 0x6d,
+ 0x72, 0x69, 0x77, 0x71, 0x70, 0x78, 0x78, 0x6b, 0x64, 0x70, 0x77, 0x79, 0x73, 0x75, 0x74, 0x62,
+ 0x79, 0x6b, 0x79, 0x70, 0x71, 0x70, 0x76, 0x6f, 0x71, 0x71, 0x66, 0x62, 0x6d, 0x6b, 0x74, 0x73,
+ 0x6c, 0x78, 0x77, 0x68, 0x6d, 0x6d, 0x65, 0x75, 0x74, 0x64, 0x71, 0x72, 0x6c, 0x64, 0x6f, 0x68,
+ 0x63, 0x75, 0x78, 0x68, 0x6f, 0x71, 0x61, 0x68, 0x78, 0x78, 0x73, 0x62, 0x74, 0x70, 0x61, 0x6e,
+ 0x68, 0x72, 0x71, 0x6c, 0x72, 0x71, 0x70, 0x77, 0x68, 0x6b, 0x64, 0x63, 0x6c, 0x76, 0x79, 0x70,
+ 0x76, 0x6f, 0x6a, 0x65, 0x67, 0x74, 0x73, 0x6a, 0x72, 0x64, 0x6a, 0x77, 0x6b, 0x61, 0x62, 0x69,
+ 0x70, 0x75, 0x6c, 0x6f, 0x6e, 0x6e, 0x6b, 0x76, 0x66, 0x71, 0x74, 0x62, 0x71, 0x75, 0x6c, 0x70,
+ 0x71, 0x70, 0x73, 0x61, 0x6a, 0x61, 0x79, 0x78, 0x74, 0x77, 0x77, 0x61, 0x76, 0x6f, 0x6c, 0x75,
+ 0x68, 0x63, 0x72, 0x77, 0x64, 0x64, 0x77, 0x6e, 0x67, 0x6a, 0x6c, 0x74, 0x73, 0x78, 0x72, 0x6a,
+ 0x6e, 0x69, 0x70, 0x79, 0x64, 0x62, 0x63, 0x76, 0x65, 0x76, 0x6d, 0x6f, 0x6b, 0x79, 0x63, 0x78,
+ 0x68, 0x70, 0x6e, 0x75, 0x64, 0x77, 0x64, 0x6e, 0x6c, 0x6e, 0x64, 0x78, 0x72, 0x73, 0x70, 0x74,
+ 0x72, 0x69, 0x76, 0x74, 0x61, 0x77, 0x64, 0x72, 0x65, 0x67, 0x6e, 0x68, 0x68, 0x67, 0x64, 0x6c,
+ 0x6f, 0x6e, 0x6f, 0x76, 0x71, 0x6c, 0x6f, 0x67, 0x75, 0x77, 0x6a, 0x72, 0x6d, 0x72, 0x70, 0x79,
+ 0x75, 0x72, 0x70, 0x78, 0x6f, 0x6e, 0x65, 0x6d, 0x74, 0x72, 0x6a, 0x62, 0x63, 0x76, 0x69, 0x68,
+ 0x77, 0x78, 0x6c, 0x72, 0x77, 0x63, 0x75, 0x6a, 0x6b, 0x74, 0x73, 0x64, 0x64, 0x70, 0x74, 0x61,
+ 0x6e, 0x6e, 0x62, 0x77, 0x76, 0x71, 0x78, 0x6a, 0x71, 0x76, 0x74, 0x61, 0x64, 0x75, 0x75, 0x63,
+ 0x61, 0x71, 0x78, 0x67, 0x77, 0x71, 0x66, 0x6e, 0x6c, 0x73, 0x61, 0x6e, 0x77, 0x62, 0x71, 0x63,
+ 0x6b, 0x6f, 0x6c, 0x6c, 0x6d, 0x77, 0x6a, 0x78, 0x77, 0x64, 0x6d, 0x70, 0x6a, 0x6c, 0x73, 0x78,
+ 0x68, 0x76, 0x6e, 0x6d, 0x6c, 0x70, 0x6f, 0x65, 0x64, 0x74, 0x61, 0x61, 0x73, 0x66, 0x76, 0x6a,
+ 0x62, 0x71, 0x6f, 0x6f, 0x73, 0x68, 0x79, 0x6b, 0x6b, 0x70, 0x73, 0x62, 0x75, 0x6a, 0x74, 0x73,
+ 0x75, 0x65, 0x6b, 0x6b, 0x6e, 0x74, 0x75, 0x75, 0x70, 0x6b, 0x70, 0x78, 0x77, 0x64, 0x65, 0x75,
+ 0x6f, 0x75, 0x73, 0x64, 0x66, 0x72, 0x67, 0x65, 0x77, 0x68, 0x66, 0x6b, 0x62, 0x6d, 0x62, 0x67,
+ 0x6d, 0x70, 0x66, 0x67, 0x62, 0x71, 0x68, 0x6f, 0x78, 0x68, 0x76, 0x67, 0x6d, 0x61, 0x63, 0x67,
+ 0x6b, 0x75, 0x65, 0x65, 0x67, 0x63, 0x78, 0x61, 0x6e, 0x78, 0x66, 0x71, 0x75, 0x6d, 0x66, 0x73,
+ 0x69, 0x75, 0x62, 0x78, 0x70, 0x70, 0x73, 0x75, 0x67, 0x67, 0x79, 0x63, 0x63, 0x62, 0x67, 0x72,
+ 0x69, 0x62, 0x6e, 0x78, 0x73, 0x77, 0x78, 0x79, 0x64, 0x70, 0x64, 0x66, 0x72, 0x66, 0x63, 0x6e,
+ 0x74, 0x70, 0x62, 0x77, 0x6e, 0x61, 0x77, 0x64, 0x79, 0x69, 0x74, 0x70, 0x63, 0x62, 0x6e, 0x6d,
+ 0x72, 0x71, 0x6c, 0x6b, 0x6f, 0x6d, 0x67, 0x69, 0x68, 0x6f, 0x79, 0x6a, 0x73, 0x67, 0x70, 0x65,
+ 0x62, 0x6a, 0x75, 0x6f, 0x67, 0x67, 0x68, 0x6d, 0x6f, 0x64, 0x64, 0x70, 0x69, 0x70, 0x64, 0x62,
+ 0x67, 0x76, 0x64, 0x62, 0x6e, 0x71, 0x63, 0x66, 0x65, 0x70, 0x68, 0x78, 0x6a, 0x66, 0x6f, 0x68,
+ 0x70, 0x78, 0x67, 0x70, 0x6e, 0x63, 0x6c, 0x67, 0x61, 0x62, 0x67, 0x69, 0x77, 0x73, 0x61, 0x77,
+ 0x6f, 0x6d, 0x6b, 0x6f, 0x67, 0x68, 0x66, 0x77, 0x6c, 0x71, 0x63, 0x72, 0x74, 0x79, 0x77, 0x65,
+ 0x66, 0x6d, 0x77, 0x77, 0x74, 0x71, 0x63, 0x78, 0x64, 0x69, 0x79, 0x74, 0x71, 0x74, 0x74, 0x71,
+ 0x75, 0x78, 0x62, 0x6b, 0x78, 0x6d, 0x6c, 0x70, 0x71, 0x71, 0x78, 0x70, 0x69, 0x75, 0x6b, 0x6b,
+ 0x63, 0x6e, 0x72, 0x68, 0x67, 0x6c, 0x71, 0x69, 0x6c, 0x75, 0x70, 0x6a, 0x61, 0x6d, 0x66, 0x76,
+ 0x73, 0x6a, 0x74, 0x65, 0x67, 0x66, 0x71, 0x6f, 0x68, 0x6f, 0x6e, 0x71, 0x78, 0x72, 0x6b, 0x75,
+ 0x79, 0x77, 0x6c, 0x66, 0x61, 0x6b, 0x75, 0x65, 0x6d, 0x62, 0x68, 0x6c, 0x70, 0x72, 0x73, 0x72,
+ 0x63, 0x64, 0x67, 0x69, 0x67, 0x72, 0x64, 0x6b, 0x61, 0x77, 0x62, 0x6f, 0x79, 0x6a, 0x68, 0x64,
+ 0x65, 0x6e, 0x76, 0x72, 0x68, 0x6e, 0x6e, 0x77, 0x62, 0x68, 0x71, 0x62, 0x66, 0x69, 0x73, 0x64,
+ 0x6f, 0x78, 0x6c, 0x6a, 0x77, 0x6b, 0x62, 0x76, 0x71, 0x70, 0x71, 0x70, 0x6e, 0x6e, 0x76, 0x68,
+ 0x6a, 0x6c, 0x6b, 0x63, 0x71, 0x79, 0x68, 0x6a, 0x78, 0x6e, 0x74, 0x66, 0x73, 0x65, 0x6d, 0x77,
+ 0x6a, 0x67, 0x79, 0x67, 0x64, 0x71, 0x79, 0x62, 0x75, 0x68, 0x65, 0x74, 0x6c, 0x6a, 0x72, 0x6b,
+ 0x79, 0x73, 0x71, 0x74, 0x6b, 0x63, 0x70, 0x70, 0x69, 0x65, 0x69, 0x76, 0x79, 0x69, 0x6b, 0x70,
+ 0x6a, 0x76, 0x6a, 0x65, 0x63, 0x73, 0x70, 0x69, 0x6a, 0x6c, 0x71, 0x63, 0x72, 0x6a, 0x73, 0x79,
+ 0x62, 0x65, 0x69, 0x79, 0x63, 0x6c, 0x75, 0x65, 0x6d, 0x6e, 0x73, 0x63, 0x66, 0x71, 0x75, 0x61,
+ 0x72, 0x79, 0x75, 0x6f, 0x61, 0x61, 0x6c, 0x68, 0x6e, 0x77, 0x66, 0x74, 0x6f, 0x70, 0x75, 0x65,
+ 0x66, 0x66, 0x65, 0x78, 0x72, 0x62, 0x67, 0x6d, 0x70, 0x69, 0x64, 0x65, 0x68, 0x63, 0x67, 0x72,
+ 0x79, 0x6c, 0x67, 0x64, 0x6d, 0x68, 0x70, 0x6a, 0x73, 0x6b, 0x62, 0x6e, 0x62, 0x66, 0x76, 0x77,
+ 0x69, 0x6a, 0x6e, 0x61, 0x74, 0x6d, 0x73, 0x72, 0x6f, 0x79, 0x6b, 0x68, 0x71, 0x62, 0x79, 0x6e,
+ 0x62, 0x6b, 0x67, 0x79, 0x77, 0x6e, 0x64, 0x6d, 0x66, 0x64, 0x73, 0x6f, 0x77, 0x70, 0x65, 0x6b,
+ 0x65, 0x71, 0x65, 0x6d, 0x69, 0x67, 0x6c, 0x75, 0x72, 0x66, 0x77, 0x61, 0x76, 0x6e, 0x69, 0x74,
+ 0x61, 0x72, 0x74, 0x62, 0x68, 0x67, 0x72, 0x6a, 0x65, 0x77, 0x6e, 0x75, 0x75, 0x79, 0x6a, 0x6d,
+ 0x6f, 0x75, 0x65, 0x6c, 0x6f, 0x6a, 0x71, 0x74, 0x74, 0x6f, 0x6e, 0x71, 0x71, 0x79, 0x62, 0x74,
+ 0x77, 0x6a, 0x61, 0x75, 0x74, 0x74, 0x6d, 0x61, 0x6f, 0x77, 0x77, 0x76, 0x71, 0x64, 0x79, 0x73,
+ 0x61, 0x69, 0x66, 0x6a, 0x61, 0x61, 0x64, 0x62, 0x74, 0x77, 0x6a, 0x6d, 0x6e, 0x6f, 0x68, 0x78,
+ 0x75, 0x6d, 0x6c, 0x70, 0x77, 0x74, 0x71, 0x78, 0x77, 0x75, 0x6c, 0x62, 0x72, 0x73, 0x63, 0x6c,
+ 0x74, 0x63, 0x64, 0x64, 0x73, 0x68, 0x74, 0x64, 0x6b, 0x63, 0x72, 0x76, 0x6d, 0x68, 0x74, 0x6c,
+ 0x6a, 0x79, 0x70, 0x68, 0x6b, 0x6c, 0x68, 0x61, 0x77, 0x69, 0x71, 0x64, 0x66, 0x64, 0x61, 0x76,
+ 0x61, 0x6a, 0x68, 0x75, 0x73, 0x6e, 0x70, 0x68, 0x77, 0x69, 0x67, 0x6d, 0x67, 0x6e, 0x73, 0x79,
+ 0x6a, 0x70, 0x77, 0x65, 0x6f, 0x68, 0x67, 0x6a, 0x66, 0x64, 0x6c, 0x6e, 0x6e, 0x72, 0x67, 0x70,
+ 0x76, 0x78, 0x68, 0x6d, 0x69, 0x66, 0x76, 0x77, 0x77, 0x66, 0x63, 0x74, 0x74, 0x68, 0x62, 0x65,
+ 0x74, 0x65, 0x74, 0x65, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x64, 0x6a, 0x72, 0x75, 0x72, 0x6c, 0x79,
+ 0x61, 0x77, 0x66, 0x62, 0x71, 0x63, 0x71, 0x66, 0x6f, 0x65, 0x6d, 0x62, 0x61, 0x66, 0x73, 0x71,
+ 0x77, 0x75, 0x62, 0x75, 0x63, 0x75, 0x68, 0x6a, 0x79, 0x68, 0x68, 0x77, 0x64, 0x79, 0x67, 0x67,
+ 0x64, 0x76, 0x69, 0x78, 0x6b, 0x6b, 0x64, 0x61, 0x64, 0x61, 0x76, 0x64, 0x6f, 0x75, 0x71, 0x6b,
+ 0x72, 0x70, 0x72, 0x6b, 0x66, 0x6c, 0x68, 0x73, 0x66, 0x62, 0x73, 0x75, 0x66, 0x79, 0x79, 0x71,
+ 0x69, 0x73, 0x6b, 0x70, 0x65, 0x67, 0x79, 0x66, 0x65, 0x69, 0x65, 0x6a, 0x64, 0x73, 0x79, 0x74,
+ 0x65, 0x64, 0x76, 0x77, 0x68, 0x74, 0x72, 0x79, 0x68, 0x62, 0x66, 0x74, 0x67, 0x78, 0x70, 0x6d,
+ 0x68, 0x70, 0x6d, 0x6b, 0x73, 0x74, 0x75, 0x76, 0x64, 0x6f, 0x6f, 0x79, 0x76, 0x68, 0x67, 0x6c,
+ 0x78, 0x72, 0x64, 0x67, 0x63, 0x65, 0x70, 0x6f, 0x61, 0x77, 0x62, 0x6b, 0x61, 0x64, 0x77, 0x6c,
+ 0x70, 0x74, 0x64, 0x70, 0x6d, 0x6e, 0x71, 0x68, 0x79, 0x73, 0x72, 0x6c, 0x72, 0x70, 0x77, 0x62,
+ 0x68, 0x61, 0x6d, 0x68, 0x6a, 0x73, 0x75, 0x6e, 0x74, 0x61, 0x61, 0x6f, 0x75, 0x67, 0x79, 0x77,
+ 0x67, 0x6d, 0x61, 0x70, 0x64, 0x76, 0x69, 0x67, 0x70, 0x79, 0x6f, 0x78, 0x70, 0x66, 0x76, 0x6a,
+ 0x6e, 0x69, 0x63, 0x66, 0x73, 0x69, 0x78, 0x6e, 0x66, 0x64, 0x62, 0x62, 0x66, 0x75, 0x61, 0x61,
+ 0x6c, 0x63, 0x79, 0x6b, 0x63, 0x6c, 0x6e, 0x64, 0x6e, 0x6a, 0x68, 0x66, 0x64, 0x63, 0x61, 0x75,
+ 0x79, 0x65, 0x67, 0x6b, 0x6a, 0x76, 0x75, 0x74, 0x6c, 0x63, 0x78, 0x63, 0x78, 0x61, 0x70, 0x66,
+ 0x64, 0x76, 0x71, 0x73, 0x73, 0x6f, 0x65, 0x64, 0x6f, 0x73, 0x75, 0x79, 0x72, 0x70, 0x65, 0x6f,
+ 0x65, 0x64, 0x70, 0x62, 0x6f, 0x73, 0x69, 0x72, 0x62, 0x76, 0x67, 0x67, 0x62, 0x77, 0x70, 0x67,
+ 0x6a, 0x78, 0x65, 0x70, 0x64, 0x73, 0x6d, 0x79, 0x77, 0x71, 0x68, 0x6b, 0x79, 0x76, 0x69, 0x65,
+ 0x75, 0x66, 0x75, 0x76, 0x6b, 0x6b, 0x71, 0x6d, 0x6b, 0x6e, 0x67, 0x6b, 0x6f, 0x71, 0x77, 0x6f,
+ 0x61, 0x70, 0x61, 0x62, 0x64, 0x75, 0x63, 0x6c, 0x77, 0x65, 0x6a, 0x77, 0x62, 0x69, 0x64, 0x6a,
+ 0x71, 0x77, 0x65, 0x66, 0x6c, 0x6f, 0x67, 0x6c, 0x62, 0x74, 0x79, 0x69, 0x62, 0x79, 0x6c, 0x6f,
+ 0x71, 0x6e, 0x6c, 0x68, 0x66, 0x6e, 0x66, 0x76, 0x62, 0x6a, 0x75, 0x73, 0x6c, 0x67, 0x68, 0x73,
+ 0x77, 0x73, 0x76, 0x77, 0x6f, 0x79, 0x74, 0x6c, 0x75, 0x71, 0x78, 0x6e, 0x63, 0x62, 0x72, 0x64,
+ 0x74, 0x74, 0x73, 0x70, 0x68, 0x66, 0x76, 0x75, 0x77, 0x6e, 0x6b, 0x76, 0x73, 0x73, 0x70, 0x63,
+ 0x6a, 0x78, 0x77, 0x77, 0x70, 0x6e, 0x63, 0x6c, 0x77, 0x78, 0x6e, 0x72, 0x6a, 0x6d, 0x62, 0x6e,
+ 0x6d, 0x75, 0x72, 0x63, 0x64, 0x78, 0x62, 0x66, 0x71, 0x67, 0x72, 0x6b, 0x62, 0x73, 0x75, 0x70,
+ 0x74, 0x6d, 0x67, 0x70, 0x63, 0x69, 0x69, 0x76, 0x68, 0x74, 0x70, 0x62, 0x75, 0x6a, 0x72, 0x75,
+ 0x79, 0x6e, 0x77, 0x68, 0x63, 0x65, 0x71, 0x68, 0x66, 0x66, 0x79, 0x6b, 0x6b, 0x6b, 0x62, 0x74,
+ 0x68, 0x63, 0x69, 0x6d, 0x6f, 0x71, 0x78, 0x66, 0x6e, 0x64, 0x70, 0x78, 0x6e, 0x67, 0x66, 0x62,
+ 0x66, 0x6f, 0x79, 0x6d, 0x6a, 0x77, 0x6e, 0x6b, 0x78, 0x64, 0x65, 0x64, 0x6e, 0x64, 0x68, 0x73,
+ 0x75, 0x72, 0x70, 0x71, 0x67, 0x63, 0x76, 0x61, 0x6a, 0x61, 0x66, 0x6f, 0x79, 0x74, 0x68, 0x6a,
+ 0x70, 0x77, 0x75, 0x70, 0x69, 0x76, 0x70, 0x72, 0x76, 0x61, 0x78, 0x6b, 0x62, 0x69, 0x68, 0x77,
+ 0x6c, 0x6a, 0x78, 0x65, 0x71, 0x66, 0x61, 0x6a, 0x74, 0x72, 0x66, 0x72, 0x6e, 0x6c, 0x74, 0x73,
+ 0x69, 0x68, 0x6f, 0x75, 0x71, 0x6b, 0x6b, 0x69, 0x70, 0x71, 0x73, 0x74, 0x61, 0x71, 0x69, 0x77,
+ 0x64, 0x6d, 0x6c, 0x77, 0x6f, 0x76, 0x76, 0x6f, 0x62, 0x63, 0x74, 0x73, 0x73, 0x74, 0x62, 0x67,
+ 0x6f, 0x71, 0x6f, 0x70, 0x73, 0x65, 0x6a, 0x71, 0x75, 0x62, 0x63, 0x79, 0x65, 0x61, 0x64, 0x75,
+ 0x79, 0x69, 0x74, 0x64, 0x6a, 0x61, 0x6a, 0x77, 0x63, 0x6c, 0x67, 0x69, 0x6e, 0x62, 0x73, 0x68,
+ 0x65, 0x64, 0x72, 0x62, 0x6f, 0x68, 0x73, 0x66, 0x6b, 0x76, 0x79, 0x6a, 0x73, 0x6b, 0x70, 0x69,
+ 0x62, 0x62, 0x71, 0x76, 0x6f, 0x6d, 0x6e, 0x6f, 0x71, 0x66, 0x6f, 0x70, 0x75, 0x73, 0x67, 0x72,
+ 0x64, 0x78, 0x6a, 0x79, 0x76, 0x68, 0x73, 0x65, 0x65, 0x71, 0x6f, 0x66, 0x6e, 0x61, 0x62, 0x72,
+ 0x70, 0x62, 0x65, 0x6b, 0x66, 0x73, 0x73, 0x76, 0x6e, 0x69, 0x79, 0x66, 0x69, 0x6f, 0x73, 0x6e,
+ 0x77, 0x72, 0x79, 0x65, 0x69, 0x73, 0x78, 0x61, 0x68, 0x6e, 0x6c, 0x79, 0x70, 0x64, 0x75, 0x6b,
+ 0x70, 0x73, 0x77, 0x75, 0x65, 0x79, 0x77, 0x73, 0x61, 0x72, 0x6b, 0x69, 0x79, 0x74, 0x63, 0x6a,
+ 0x64, 0x68, 0x63, 0x69, 0x61, 0x6a, 0x76, 0x74, 0x63, 0x6a, 0x79, 0x75, 0x6d, 0x70, 0x67, 0x6d,
+ 0x64, 0x64, 0x78, 0x61, 0x6d, 0x6d, 0x72, 0x78, 0x74, 0x6e, 0x6e, 0x65, 0x77, 0x65, 0x63, 0x72,
+ 0x74, 0x70, 0x70, 0x71, 0x6a, 0x72, 0x67, 0x69, 0x75, 0x6e, 0x6c, 0x61, 0x74, 0x66, 0x79, 0x63,
+ 0x66, 0x67, 0x75, 0x75, 0x79, 0x75, 0x79, 0x63, 0x72, 0x6c, 0x6f, 0x73, 0x77, 0x71, 0x78, 0x74,
+ 0x72, 0x75, 0x6f, 0x6b, 0x71, 0x67, 0x65, 0x63, 0x77, 0x78, 0x6b, 0x6c, 0x69, 0x6d, 0x6a, 0x78,
+ 0x63, 0x6c, 0x69, 0x6d, 0x6a, 0x6f, 0x61, 0x62, 0x64, 0x67, 0x61, 0x6b, 0x6b, 0x6d, 0x71, 0x61,
+ 0x64, 0x6b, 0x6f, 0x6d, 0x72, 0x65, 0x6d, 0x66, 0x65, 0x77, 0x78, 0x78, 0x6c, 0x63, 0x65, 0x76,
+ 0x71, 0x67, 0x73, 0x61, 0x69, 0x68, 0x71, 0x76, 0x6c, 0x72, 0x72, 0x63, 0x69, 0x6b, 0x78, 0x6a,
+ 0x6e, 0x79, 0x62, 0x64, 0x6c, 0x63, 0x6c, 0x72, 0x62, 0x6f, 0x72, 0x68, 0x79, 0x62, 0x70, 0x67,
+ 0x64, 0x73, 0x6e, 0x67, 0x6c, 0x69, 0x77, 0x76, 0x68, 0x70, 0x6f, 0x66, 0x63, 0x67, 0x72, 0x72,
+ 0x6c, 0x69, 0x61, 0x75, 0x61, 0x62, 0x6e, 0x75, 0x69, 0x61, 0x77, 0x77, 0x65, 0x6a, 0x6b, 0x74,
+ 0x61, 0x61, 0x6d, 0x6f, 0x77, 0x79, 0x72, 0x78, 0x73, 0x77, 0x6b, 0x63, 0x6d, 0x6b, 0x66, 0x71,
+ 0x78, 0x64, 0x64, 0x76, 0x79, 0x6f, 0x63, 0x62, 0x74, 0x69, 0x65, 0x6f, 0x65, 0x62, 0x74, 0x6f,
+ 0x74, 0x77, 0x78, 0x64, 0x64, 0x63, 0x61, 0x65, 0x76, 0x70, 0x63, 0x71, 0x62, 0x66, 0x66, 0x75,
+ 0x76, 0x78, 0x63, 0x65, 0x68, 0x6d, 0x6e, 0x61, 0x72, 0x74, 0x67, 0x77, 0x71, 0x71, 0x67, 0x66,
+ 0x6c, 0x67, 0x73, 0x65, 0x76, 0x72, 0x74, 0x67, 0x68, 0x75, 0x76, 0x70, 0x66, 0x68, 0x78, 0x6e,
+ 0x6d, 0x62, 0x6b, 0x77, 0x6c, 0x61, 0x65, 0x6a, 0x6d, 0x6c, 0x6f, 0x6c, 0x66, 0x6f, 0x76, 0x73,
+ 0x76, 0x6e, 0x72, 0x63, 0x62, 0x63, 0x72, 0x74, 0x6f, 0x63, 0x6a, 0x72, 0x6b, 0x63, 0x6d, 0x6d,
+ 0x62, 0x78, 0x72, 0x71, 0x71, 0x70, 0x6a, 0x6d, 0x65, 0x6e, 0x6e, 0x79, 0x74, 0x66, 0x74, 0x64,
+ 0x73, 0x64, 0x73, 0x74, 0x79, 0x66, 0x77, 0x61, 0x6a, 0x71, 0x68, 0x72, 0x73, 0x73, 0x77, 0x71,
+ 0x67, 0x61, 0x6e, 0x68, 0x75, 0x69, 0x61, 0x66, 0x67, 0x73, 0x73, 0x6e, 0x6b, 0x70, 0x61, 0x69,
+ 0x61, 0x63, 0x6e, 0x67, 0x62, 0x78, 0x6e, 0x6f, 0x74, 0x67, 0x61, 0x74, 0x68, 0x74, 0x63, 0x68,
+ 0x64, 0x68, 0x6a, 0x63, 0x79, 0x65, 0x78, 0x6c, 0x78, 0x6a, 0x62, 0x73, 0x71, 0x65, 0x65, 0x66,
+ 0x6a, 0x62, 0x75, 0x6b, 0x70, 0x66, 0x68, 0x73, 0x72, 0x6d, 0x71, 0x79, 0x6e, 0x71, 0x6f, 0x65,
+ 0x66, 0x6b, 0x72, 0x78, 0x75, 0x6c, 0x74, 0x6a, 0x62, 0x62, 0x74, 0x78, 0x61, 0x62, 0x75, 0x65,
+ 0x6d, 0x67, 0x64, 0x67, 0x78, 0x65, 0x68, 0x6e, 0x75, 0x6d, 0x78, 0x77, 0x61, 0x6a, 0x79, 0x72,
+ 0x63, 0x6a, 0x6b, 0x66, 0x6b, 0x75, 0x69, 0x73, 0x64, 0x73, 0x65, 0x64, 0x6a, 0x6c, 0x62, 0x6e,
+ 0x66, 0x6f, 0x63, 0x78, 0x67, 0x63, 0x76, 0x76, 0x6f, 0x78, 0x61, 0x67, 0x77, 0x73, 0x72, 0x77,
+ 0x63, 0x6e, 0x62, 0x79, 0x79, 0x73, 0x6c, 0x65, 0x66, 0x75, 0x6d, 0x68, 0x72, 0x61, 0x70, 0x6f,
+ 0x76, 0x6f, 0x68, 0x62, 0x65, 0x6f, 0x70, 0x6b, 0x6c, 0x65, 0x69, 0x66, 0x73, 0x71, 0x66, 0x71,
+ 0x74, 0x78, 0x76, 0x65, 0x75, 0x66, 0x78, 0x6b, 0x63, 0x78, 0x70, 0x6b, 0x74, 0x67, 0x78, 0x75,
+ 0x65, 0x6c, 0x6c, 0x75, 0x75, 0x75, 0x6b, 0x68, 0x6f, 0x63, 0x64, 0x64, 0x67, 0x61, 0x63, 0x61,
+ 0x6d, 0x65, 0x79, 0x76, 0x69, 0x70, 0x74, 0x71, 0x62, 0x68, 0x67, 0x65, 0x6f, 0x77, 0x74, 0x63,
+ 0x64, 0x65, 0x67, 0x78, 0x62, 0x66, 0x65, 0x6d, 0x6a, 0x6c, 0x62, 0x6c, 0x6a, 0x75, 0x61, 0x67,
+ 0x71, 0x6e, 0x6e, 0x70, 0x72, 0x6c, 0x78, 0x77, 0x69, 0x6d, 0x66, 0x69, 0x6e, 0x6b, 0x63, 0x76,
+ 0x72, 0x70, 0x67, 0x79, 0x64, 0x6e, 0x68, 0x73, 0x75, 0x73, 0x6d, 0x62, 0x6b, 0x6d, 0x69, 0x70,
+ 0x6b, 0x6f, 0x65, 0x6f, 0x78, 0x6d, 0x69, 0x79, 0x63, 0x71, 0x68, 0x72, 0x75, 0x6d, 0x67, 0x71,
+ 0x6d, 0x76, 0x6f, 0x6f, 0x69, 0x62, 0x78, 0x64, 0x69, 0x6f, 0x65, 0x66, 0x66, 0x63, 0x62, 0x6c,
+ 0x6b, 0x74, 0x79, 0x6f, 0x6f, 0x79, 0x70, 0x73, 0x79, 0x75, 0x67, 0x72, 0x79, 0x72, 0x63, 0x73,
+ 0x6c, 0x64, 0x72, 0x6f, 0x62, 0x6b, 0x62, 0x6f, 0x77, 0x76, 0x6c, 0x62, 0x6c, 0x70, 0x66, 0x67,
+ 0x6f, 0x63, 0x79, 0x66, 0x69, 0x67, 0x65, 0x79, 0x6e, 0x64, 0x6e, 0x69, 0x6d, 0x71, 0x67, 0x6f,
+ 0x69, 0x74, 0x67, 0x65, 0x72, 0x63, 0x6f, 0x64, 0x68, 0x73, 0x79, 0x79, 0x6d, 0x6d, 0x69, 0x67,
+ 0x77, 0x6d, 0x64, 0x70, 0x74, 0x6c, 0x75, 0x79, 0x74, 0x62, 0x62, 0x6a, 0x63, 0x65, 0x61, 0x79,
+ 0x62, 0x65, 0x68, 0x65, 0x6b, 0x73, 0x78, 0x73, 0x68, 0x6a, 0x79, 0x71, 0x71, 0x6e, 0x62, 0x61,
+ 0x6b, 0x73, 0x6a, 0x65, 0x6b, 0x74, 0x68, 0x74, 0x66, 0x6b, 0x6f, 0x76, 0x73, 0x6e, 0x65, 0x6d,
+ 0x6e, 0x78, 0x72, 0x69, 0x69, 0x76, 0x6e, 0x72, 0x71, 0x61, 0x61, 0x6c, 0x73, 0x63, 0x74, 0x6e,
+ 0x64, 0x71, 0x6d, 0x6b, 0x62, 0x62, 0x63, 0x6c, 0x61, 0x61, 0x65, 0x78, 0x64, 0x71, 0x78, 0x68,
+ 0x6b, 0x76, 0x72, 0x79, 0x70, 0x65, 0x6e, 0x6a, 0x65, 0x77, 0x63, 0x61, 0x64, 0x66, 0x71, 0x61,
+ 0x76, 0x72, 0x75, 0x68, 0x69, 0x63, 0x75, 0x71, 0x71, 0x6f, 0x75, 0x77, 0x76, 0x61, 0x6b, 0x73,
+ 0x6e, 0x77, 0x70, 0x71, 0x64, 0x62, 0x61, 0x76, 0x65, 0x65, 0x6f, 0x71, 0x76, 0x77, 0x72, 0x73,
+ 0x64, 0x73, 0x61, 0x74, 0x75, 0x75, 0x6c, 0x6f, 0x74, 0x64, 0x6d, 0x6c, 0x6a, 0x72, 0x66, 0x68,
+ 0x6f, 0x75, 0x63, 0x71, 0x73, 0x73, 0x6e, 0x6b, 0x75, 0x67, 0x74, 0x6e, 0x6b, 0x6f, 0x73, 0x73,
+ 0x6a, 0x61, 0x70, 0x66, 0x66, 0x61, 0x68, 0x70, 0x76, 0x6c, 0x70, 0x64, 0x72, 0x63, 0x61, 0x6e,
+ 0x77, 0x74, 0x73, 0x6d, 0x73, 0x67, 0x6e, 0x63, 0x61, 0x73, 0x63, 0x73, 0x6d, 0x76, 0x6a, 0x6d,
+ 0x6e, 0x6d, 0x6a, 0x66, 0x71, 0x6e, 0x66, 0x6c, 0x66, 0x72, 0x77, 0x6a, 0x79, 0x67, 0x67, 0x62,
+ 0x69, 0x72, 0x71, 0x66, 0x66, 0x69, 0x61, 0x6d, 0x75, 0x77, 0x66, 0x74, 0x6e, 0x6d, 0x67, 0x75,
+ 0x74, 0x63, 0x65, 0x75, 0x6d, 0x6f, 0x73, 0x61, 0x74, 0x6a, 0x66, 0x64, 0x70, 0x69, 0x61, 0x6e,
+ 0x61, 0x64, 0x77, 0x75, 0x63, 0x76, 0x6c, 0x66, 0x79, 0x77, 0x74, 0x79, 0x64, 0x6f, 0x65, 0x66,
+ 0x62, 0x71, 0x6a, 0x6c, 0x6a, 0x67, 0x69, 0x68, 0x61, 0x66, 0x75, 0x78, 0x73, 0x65, 0x6c, 0x61,
+ 0x6b, 0x74, 0x68, 0x75, 0x70, 0x70, 0x6a, 0x67, 0x73, 0x71, 0x63, 0x68, 0x65, 0x64, 0x77, 0x66,
+ 0x66, 0x6a, 0x71, 0x77, 0x72, 0x62, 0x73, 0x6d, 0x62, 0x73, 0x65, 0x6c, 0x75, 0x6f, 0x67, 0x6a,
+ 0x61, 0x79, 0x6b, 0x70, 0x61, 0x71, 0x61, 0x64, 0x6f, 0x63, 0x6a, 0x75, 0x63, 0x6e, 0x79, 0x78,
+ 0x71, 0x69, 0x73, 0x68, 0x6a, 0x6b, 0x66, 0x6f, 0x68, 0x66, 0x62, 0x65, 0x75, 0x70, 0x70, 0x68,
+ 0x61, 0x68, 0x76, 0x78, 0x6d, 0x64, 0x6c, 0x64, 0x63, 0x73, 0x72, 0x76, 0x65, 0x62, 0x66, 0x6b,
+ 0x66, 0x78, 0x62, 0x75, 0x6b, 0x69, 0x77, 0x76, 0x64, 0x77, 0x71, 0x72, 0x71, 0x6d, 0x78, 0x6a,
+ 0x6b, 0x73, 0x79, 0x64, 0x6b, 0x6a, 0x76, 0x73, 0x76, 0x6c, 0x78, 0x6d, 0x6c, 0x6a, 0x78, 0x79,
+ 0x75, 0x76, 0x75, 0x79, 0x67, 0x77, 0x6d, 0x76, 0x72, 0x79, 0x6a, 0x62, 0x6f, 0x78, 0x69, 0x73,
+ 0x73, 0x61, 0x70, 0x66, 0x67, 0x79, 0x61, 0x67, 0x62, 0x6d, 0x65, 0x6a, 0x72, 0x77, 0x66, 0x65,
+ 0x62, 0x63, 0x71, 0x6d, 0x6d, 0x62, 0x62, 0x6d, 0x75, 0x6a, 0x6e, 0x64, 0x79, 0x70, 0x67, 0x68,
+ 0x70, 0x65, 0x71, 0x77, 0x75, 0x77, 0x6e, 0x67, 0x6e, 0x61, 0x6c, 0x6e, 0x64, 0x64, 0x70, 0x70,
+ 0x6f, 0x6a, 0x62, 0x70, 0x62, 0x69, 0x6d, 0x62, 0x70, 0x6b, 0x63, 0x6c, 0x68, 0x79, 0x6b, 0x68,
+ 0x71, 0x6e, 0x71, 0x63, 0x6e, 0x62, 0x6c, 0x71, 0x76, 0x6a, 0x6b, 0x67, 0x66, 0x6a, 0x73, 0x79,
+ 0x6a, 0x73, 0x67, 0x77, 0x6c, 0x61, 0x6c, 0x6c, 0x6a, 0x63, 0x76, 0x6b, 0x64, 0x78, 0x61, 0x70,
+ 0x63, 0x6d, 0x6a, 0x75, 0x6f, 0x74, 0x65, 0x63, 0x6b, 0x68, 0x67, 0x73, 0x73, 0x63, 0x71, 0x63,
+ 0x73, 0x68, 0x68, 0x74, 0x76, 0x6e, 0x6e, 0x6c, 0x66, 0x61, 0x68, 0x71, 0x6c, 0x6e, 0x76, 0x79,
+ 0x77, 0x76, 0x61, 0x66, 0x69, 0x6d, 0x65, 0x6a, 0x70, 0x6a, 0x79, 0x79, 0x6a, 0x74, 0x65, 0x65,
+ 0x66, 0x6b, 0x77, 0x77, 0x68, 0x72, 0x62, 0x79, 0x6d, 0x78, 0x71, 0x67, 0x78, 0x74, 0x63, 0x79,
+ 0x74, 0x65, 0x69, 0x64, 0x64, 0x71, 0x68, 0x74, 0x65, 0x6d, 0x6a, 0x64, 0x78, 0x6c, 0x61, 0x76,
+ 0x73, 0x6c, 0x75, 0x73, 0x63, 0x64, 0x68, 0x76, 0x67, 0x6e, 0x78, 0x78, 0x68, 0x75, 0x69, 0x65,
+ 0x6a, 0x65, 0x75, 0x78, 0x77, 0x69, 0x71, 0x6a, 0x70, 0x6a, 0x70, 0x6b, 0x70, 0x72, 0x72, 0x63,
+ 0x64, 0x74, 0x79, 0x65, 0x63, 0x68, 0x79, 0x62, 0x63, 0x61, 0x79, 0x6e, 0x77, 0x79, 0x61, 0x65,
+ 0x66, 0x71, 0x6e, 0x79, 0x78, 0x69, 0x73, 0x6c, 0x67, 0x6f, 0x66, 0x75, 0x63, 0x63, 0x65, 0x78,
+ 0x66, 0x6a, 0x70, 0x67, 0x62, 0x63, 0x69, 0x77, 0x63, 0x76, 0x6d, 0x79, 0x68, 0x71, 0x77, 0x74,
+ 0x6f, 0x6c, 0x6b, 0x71, 0x6c, 0x67, 0x6e, 0x70, 0x71, 0x78, 0x66, 0x69, 0x73, 0x6e, 0x72, 0x69,
+ 0x77, 0x71, 0x65, 0x6f, 0x6f, 0x6b, 0x69, 0x66, 0x6e, 0x61, 0x6d, 0x73, 0x61, 0x70, 0x70, 0x6b,
+ 0x67, 0x76, 0x72, 0x66, 0x64, 0x71, 0x65, 0x71, 0x64, 0x61, 0x79, 0x64, 0x6b, 0x6a, 0x6c, 0x6c,
+ 0x69, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x6e, 0x74, 0x79, 0x63, 0x63, 0x6d, 0x65, 0x6b, 0x68, 0x6c,
+ 0x71, 0x76, 0x62, 0x78, 0x63, 0x77, 0x75, 0x69, 0x79, 0x6f, 0x76, 0x66, 0x77, 0x6e, 0x6c, 0x78,
+ 0x6e, 0x78, 0x73, 0x6a, 0x74, 0x62, 0x68, 0x66, 0x65, 0x68, 0x61, 0x6d, 0x77, 0x72, 0x69, 0x6f,
+ 0x6b, 0x6f, 0x65, 0x71, 0x6b, 0x79, 0x74, 0x77, 0x61, 0x74, 0x69, 0x74, 0x6a, 0x75, 0x70, 0x76,
+ 0x6a, 0x77, 0x70, 0x73, 0x77, 0x72, 0x75, 0x71, 0x76, 0x68, 0x73, 0x73, 0x6b, 0x6c, 0x63, 0x69,
+ 0x6b, 0x75, 0x67, 0x74, 0x6e, 0x79, 0x76, 0x67, 0x71, 0x78, 0x64, 0x6a, 0x79, 0x68, 0x6e, 0x65,
+ 0x65, 0x62, 0x76, 0x6f, 0x6d, 0x75, 0x74, 0x73, 0x6a, 0x68, 0x71, 0x67, 0x6b, 0x64, 0x62, 0x74,
+ 0x64, 0x62, 0x77, 0x65, 0x69, 0x61, 0x78, 0x68, 0x72, 0x70, 0x6d, 0x69, 0x6b, 0x70, 0x6e, 0x62,
+ 0x69, 0x74, 0x62, 0x6b, 0x6d, 0x64, 0x78, 0x70, 0x76, 0x74, 0x6a, 0x6a, 0x63, 0x65, 0x77, 0x78,
+ 0x72, 0x71, 0x63, 0x6d, 0x6c, 0x69, 0x63, 0x68, 0x71, 0x62, 0x62, 0x6f, 0x79, 0x75, 0x75, 0x73,
+ 0x71, 0x6c, 0x77, 0x6d, 0x62, 0x75, 0x67, 0x66, 0x61, 0x6e, 0x73, 0x73, 0x62, 0x67, 0x63, 0x72,
+ 0x66, 0x6e, 0x63, 0x71, 0x78, 0x6d, 0x68, 0x67, 0x79, 0x79, 0x76, 0x74, 0x6d, 0x74, 0x74, 0x73,
+ 0x79, 0x76, 0x6d, 0x79, 0x71, 0x72, 0x70, 0x65, 0x69, 0x66, 0x73, 0x74, 0x77, 0x6d, 0x74, 0x6e,
+ 0x6f, 0x72, 0x71, 0x62, 0x67, 0x74, 0x62, 0x77, 0x6f, 0x6b, 0x6c, 0x66, 0x65, 0x63, 0x75, 0x6e,
+ 0x66, 0x6b, 0x75, 0x69, 0x61, 0x79, 0x6c, 0x74, 0x77, 0x6b, 0x73, 0x78, 0x70, 0x6f, 0x69, 0x72,
+ 0x72, 0x74, 0x69, 0x6f, 0x62, 0x66, 0x61, 0x6c, 0x72, 0x6b, 0x63, 0x6c, 0x73, 0x67, 0x6e, 0x6b,
+ 0x74, 0x70, 0x70, 0x73, 0x6d, 0x6a, 0x73, 0x67, 0x71, 0x70, 0x77, 0x71, 0x69, 0x6a, 0x79, 0x71,
+ 0x75, 0x70, 0x67, 0x62, 0x72, 0x61, 0x79, 0x64, 0x73, 0x73, 0x66, 0x78, 0x64, 0x76, 0x69, 0x79,
+ 0x6f, 0x62, 0x6a, 0x6d, 0x76, 0x69, 0x66, 0x6b, 0x69, 0x6c, 0x6a, 0x69, 0x75, 0x71, 0x66, 0x77,
+ 0x69, 0x75, 0x76, 0x6b, 0x73, 0x69, 0x6d, 0x66, 0x61, 0x6b, 0x79, 0x74, 0x61, 0x66, 0x64, 0x64,
+ 0x65, 0x66, 0x73, 0x64, 0x76, 0x74, 0x6f, 0x63, 0x6c, 0x6c, 0x66, 0x75, 0x69, 0x6a, 0x79, 0x72,
+ 0x70, 0x64, 0x61, 0x74, 0x75, 0x74, 0x62, 0x61, 0x72, 0x6a, 0x73, 0x6f, 0x77, 0x65, 0x67, 0x71,
+ 0x64, 0x66, 0x69, 0x69, 0x63, 0x6a, 0x66, 0x73, 0x76, 0x70, 0x63, 0x69, 0x75, 0x64, 0x78, 0x62,
+ 0x79, 0x67, 0x79, 0x6b, 0x78, 0x6f, 0x63, 0x6d, 0x69, 0x61, 0x67, 0x6f, 0x77, 0x64, 0x70, 0x66,
+ 0x6b, 0x73, 0x76, 0x6c, 0x6a, 0x64, 0x69, 0x6f, 0x68, 0x75, 0x72, 0x67, 0x6c, 0x64, 0x73, 0x71,
+ 0x67, 0x6f, 0x69, 0x6c, 0x63, 0x6a, 0x62, 0x71, 0x70, 0x78, 0x73, 0x66, 0x66, 0x6e, 0x79, 0x62,
+ 0x6c, 0x77, 0x65, 0x6f, 0x6e, 0x70, 0x61, 0x76, 0x67, 0x77, 0x6d, 0x71, 0x73, 0x70, 0x75, 0x62,
+ 0x62, 0x68, 0x78, 0x6f, 0x62, 0x76, 0x61, 0x65, 0x61, 0x6a, 0x70, 0x65, 0x70, 0x70, 0x73, 0x75,
+ 0x62, 0x73, 0x61, 0x72, 0x64, 0x6c, 0x76, 0x6e, 0x6b, 0x74, 0x67, 0x6a, 0x6b, 0x66, 0x65, 0x6c,
+ 0x62, 0x65, 0x79, 0x6b, 0x69, 0x78, 0x61, 0x72, 0x73, 0x62, 0x6c, 0x70, 0x64, 0x78, 0x71, 0x78,
+ 0x68, 0x6c, 0x63, 0x72, 0x66, 0x78, 0x73, 0x79, 0x68, 0x73, 0x62, 0x68, 0x68, 0x6f, 0x67, 0x63,
+ 0x73, 0x6d, 0x6d, 0x75, 0x64, 0x63, 0x79, 0x74, 0x68, 0x74, 0x79, 0x69, 0x6b, 0x63, 0x63, 0x67,
+ 0x6a, 0x76, 0x75, 0x6b, 0x63, 0x77, 0x79, 0x64, 0x76, 0x74, 0x68, 0x6c, 0x76, 0x77, 0x68, 0x70,
+ 0x69, 0x6f, 0x73, 0x66, 0x76, 0x62, 0x76, 0x64, 0x73, 0x65, 0x64, 0x61, 0x70, 0x67, 0x6e, 0x6b,
+ 0x72, 0x70, 0x6e, 0x70, 0x79, 0x75, 0x6e, 0x6f, 0x6c, 0x67, 0x6d, 0x78, 0x61, 0x62, 0x6c, 0x6e,
+ 0x79, 0x75, 0x75, 0x66, 0x74, 0x65, 0x61, 0x74, 0x69, 0x6d, 0x78, 0x64, 0x63, 0x68, 0x70, 0x61,
+ 0x73, 0x67, 0x65, 0x6e, 0x70, 0x74, 0x67, 0x66, 0x69, 0x62, 0x68, 0x6d, 0x73, 0x64, 0x6f, 0x67,
+ 0x6c, 0x6a, 0x67, 0x71, 0x6c, 0x72, 0x6e, 0x6a, 0x6b, 0x6f, 0x73, 0x73, 0x70, 0x77, 0x66, 0x61,
+ 0x6b, 0x70, 0x65, 0x6e, 0x6e, 0x76, 0x6a, 0x6e, 0x63, 0x75, 0x77, 0x6f, 0x72, 0x62, 0x78, 0x6a,
+ 0x6a, 0x6e, 0x6e, 0x66, 0x69, 0x66, 0x68, 0x76, 0x61, 0x74, 0x6f, 0x76, 0x6c, 0x63, 0x68, 0x66,
+ 0x65, 0x72, 0x71, 0x65, 0x63, 0x69, 0x75, 0x73, 0x6b, 0x64, 0x6b, 0x79, 0x68, 0x62, 0x79, 0x65,
+ 0x74, 0x61, 0x70, 0x76, 0x79, 0x70, 0x74, 0x75, 0x79, 0x62, 0x6e, 0x6c, 0x70, 0x6d, 0x69, 0x72,
+ 0x77, 0x71, 0x6b, 0x63, 0x71, 0x61, 0x6c, 0x72, 0x67, 0x6d, 0x6b, 0x74, 0x6e, 0x71, 0x75, 0x66,
+ 0x6b, 0x6b, 0x65, 0x77, 0x65, 0x73, 0x72, 0x63, 0x67, 0x6b, 0x6a, 0x61, 0x69, 0x73, 0x61, 0x64,
+ 0x6d, 0x77, 0x74, 0x76, 0x65, 0x63, 0x61, 0x6e, 0x62, 0x68, 0x6e, 0x70, 0x62, 0x64, 0x6e, 0x79,
+ 0x69, 0x79, 0x68, 0x75, 0x6c, 0x79, 0x71, 0x78, 0x62, 0x64, 0x62, 0x78, 0x79, 0x66, 0x70, 0x65,
+ 0x70, 0x68, 0x67, 0x6d, 0x67, 0x6b, 0x62, 0x65, 0x63, 0x68, 0x67, 0x63, 0x6b, 0x78, 0x6a, 0x63,
+ 0x73, 0x63, 0x62, 0x6c, 0x61, 0x6b, 0x68, 0x68, 0x6e, 0x61, 0x70, 0x73, 0x69, 0x74, 0x63, 0x68,
+ 0x64, 0x66, 0x69, 0x62, 0x6e, 0x6c, 0x63, 0x72, 0x63, 0x62, 0x62, 0x74, 0x67, 0x67, 0x61, 0x62,
+ 0x67, 0x72, 0x75, 0x6a, 0x74, 0x78, 0x62, 0x66, 0x67, 0x63, 0x69, 0x73, 0x75, 0x68, 0x76, 0x6c,
+ 0x66, 0x65, 0x69, 0x66, 0x6e, 0x6e, 0x68, 0x72, 0x72, 0x65, 0x62, 0x71, 0x63, 0x72, 0x71, 0x69,
+ 0x63, 0x66, 0x74, 0x77, 0x65, 0x67, 0x6b, 0x70, 0x6c, 0x63, 0x6d, 0x68, 0x68, 0x71, 0x70, 0x72,
+ 0x76, 0x72, 0x77, 0x61, 0x72, 0x73, 0x75, 0x68, 0x6c, 0x73, 0x6f, 0x61, 0x6e, 0x76, 0x6e, 0x66,
+ 0x70, 0x61, 0x67, 0x6c, 0x6b, 0x61, 0x75, 0x67, 0x64, 0x76, 0x6d, 0x6f, 0x77, 0x78, 0x72, 0x70,
+ 0x6e, 0x6e, 0x6d, 0x77, 0x67, 0x71, 0x75, 0x78, 0x74, 0x71, 0x73, 0x76, 0x67, 0x61, 0x79, 0x70,
+ 0x6d, 0x71, 0x73, 0x76, 0x6c, 0x6f, 0x6d, 0x77, 0x65, 0x65, 0x76, 0x68, 0x66, 0x6a, 0x76, 0x72,
+ 0x76, 0x71, 0x64, 0x67, 0x74, 0x6d, 0x62, 0x6b, 0x64, 0x6d, 0x74, 0x78, 0x6f, 0x73, 0x62, 0x76,
+ 0x78, 0x79, 0x74, 0x6b, 0x75, 0x77, 0x6a, 0x77, 0x66, 0x65, 0x74, 0x74, 0x79, 0x6e, 0x64, 0x6d,
+ 0x6e, 0x67, 0x64, 0x62, 0x6b, 0x77, 0x72, 0x69, 0x61, 0x70, 0x67, 0x64, 0x64, 0x77, 0x6b, 0x63,
+ 0x70, 0x74, 0x67, 0x73, 0x69, 0x72, 0x79, 0x65, 0x64, 0x6e, 0x71, 0x68, 0x71, 0x79, 0x6e, 0x6e,
+ 0x63, 0x64, 0x6a, 0x70, 0x62, 0x73, 0x76, 0x72, 0x71, 0x71, 0x74, 0x67, 0x6a, 0x62, 0x70, 0x63,
+ 0x69, 0x61, 0x6f, 0x6d, 0x63, 0x67, 0x74, 0x74, 0x70, 0x72, 0x6c, 0x6d, 0x6a, 0x69, 0x64, 0x79,
+ 0x77, 0x6d, 0x77, 0x75, 0x6b, 0x68, 0x6e, 0x70, 0x71, 0x64, 0x66, 0x6f, 0x72, 0x78, 0x78, 0x69,
+ 0x6e, 0x75, 0x6b, 0x74, 0x65, 0x6c, 0x65, 0x79, 0x73, 0x73, 0x65, 0x66, 0x6f, 0x72, 0x75, 0x69,
+ 0x77, 0x61, 0x75, 0x74, 0x63, 0x68, 0x73, 0x6c, 0x73, 0x78, 0x6d, 0x6b, 0x66, 0x64, 0x75, 0x76,
+ 0x6f, 0x6f, 0x79, 0x78, 0x68, 0x6d, 0x6b, 0x6f, 0x6a, 0x72, 0x6e, 0x62, 0x63, 0x67, 0x79, 0x78,
+ 0x6b, 0x77, 0x75, 0x71, 0x69, 0x6e, 0x70, 0x73, 0x61, 0x68, 0x66, 0x63, 0x6a, 0x66, 0x75, 0x74,
+ 0x63, 0x6d, 0x72, 0x71, 0x64, 0x77, 0x77, 0x69, 0x68, 0x70, 0x79, 0x6c, 0x72, 0x62, 0x78, 0x69,
+ 0x6a, 0x61, 0x6d, 0x75, 0x6d, 0x67, 0x61, 0x78, 0x61, 0x6e, 0x73, 0x6b, 0x6c, 0x74, 0x67, 0x61,
+ 0x71, 0x68, 0x62, 0x6c, 0x62, 0x77, 0x75, 0x65, 0x6c, 0x76, 0x73, 0x64, 0x68, 0x73, 0x68, 0x79,
+ 0x78, 0x6a, 0x73, 0x6a, 0x72, 0x65, 0x77, 0x68, 0x64, 0x76, 0x75, 0x6d, 0x6d, 0x64, 0x75, 0x78,
+ 0x78, 0x76, 0x61, 0x63, 0x6f, 0x78, 0x69, 0x76, 0x61, 0x66, 0x62, 0x64, 0x72, 0x6c, 0x70, 0x79,
+ 0x6e, 0x63, 0x6a, 0x70, 0x6f, 0x73, 0x63, 0x76, 0x6d, 0x76, 0x77, 0x6f, 0x78, 0x63, 0x67, 0x6c,
+ 0x6b, 0x77, 0x71, 0x79, 0x70, 0x6a, 0x78, 0x71, 0x69, 0x69, 0x76, 0x6c, 0x6d, 0x66, 0x6f, 0x66,
+ 0x68, 0x64, 0x61, 0x71, 0x61, 0x74, 0x68, 0x72, 0x75, 0x6e, 0x6d, 0x73, 0x69, 0x71, 0x71, 0x6b,
+ 0x79, 0x76, 0x74, 0x67, 0x63, 0x64, 0x70, 0x69, 0x65, 0x75, 0x72, 0x6e, 0x6c, 0x76, 0x63, 0x72,
+ 0x6d, 0x6e, 0x73, 0x6d, 0x75, 0x6c, 0x73, 0x75, 0x61, 0x64, 0x69, 0x72, 0x75, 0x66, 0x71, 0x6b,
+ 0x77, 0x6b, 0x64, 0x62, 0x68, 0x61, 0x6e, 0x67, 0x6d, 0x68, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x78,
+ 0x70, 0x6d, 0x74, 0x6d, 0x6c, 0x75, 0x63, 0x72, 0x71, 0x71, 0x70, 0x78, 0x62, 0x6a, 0x69, 0x70,
+ 0x70, 0x68, 0x6a, 0x6e, 0x6e, 0x74, 0x69, 0x62, 0x64, 0x69, 0x66, 0x62, 0x78, 0x6b, 0x6c, 0x64,
+ 0x66, 0x79, 0x6a, 0x77, 0x77, 0x79, 0x70, 0x6e, 0x76, 0x78, 0x6a, 0x70, 0x69, 0x63, 0x62, 0x72,
+ 0x6f, 0x64, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x67, 0x74, 0x65, 0x77, 0x6c, 0x6e, 0x72, 0x64, 0x6d,
+ 0x62, 0x68, 0x72, 0x66, 0x67, 0x63, 0x69, 0x74, 0x69, 0x6c, 0x75, 0x72, 0x6c, 0x63, 0x73, 0x71,
+ 0x66, 0x6f, 0x79, 0x67, 0x73, 0x6b, 0x6f, 0x6c, 0x65, 0x72, 0x78, 0x72, 0x76, 0x6a, 0x6f, 0x6e,
+ 0x66, 0x6e, 0x75, 0x6c, 0x6b, 0x75, 0x72, 0x74, 0x6a, 0x6d, 0x67, 0x67, 0x67, 0x74, 0x61, 0x6c,
+ 0x64, 0x64, 0x71, 0x79, 0x62, 0x72, 0x65, 0x6d, 0x62, 0x6c, 0x6f, 0x76, 0x63, 0x71, 0x68, 0x79,
+ 0x6e, 0x78, 0x6c, 0x63, 0x79, 0x61, 0x69, 0x65, 0x68, 0x68, 0x64, 0x66, 0x66, 0x6d, 0x6a, 0x79,
+ 0x62, 0x71, 0x78, 0x70, 0x77, 0x78, 0x73, 0x69, 0x61, 0x6e, 0x66, 0x6e, 0x77, 0x72, 0x63, 0x68,
+ 0x75, 0x6e, 0x75, 0x64, 0x67, 0x6e, 0x69, 0x6a, 0x73, 0x71, 0x6f, 0x71, 0x62, 0x73, 0x6b, 0x65,
+ 0x74, 0x73, 0x73, 0x70, 0x66, 0x66, 0x75, 0x6e, 0x70, 0x76, 0x77, 0x71, 0x78, 0x6d, 0x71, 0x78,
+ 0x6b, 0x6e, 0x62, 0x6d, 0x6f, 0x69, 0x66, 0x61, 0x6f, 0x63, 0x6e, 0x6d, 0x79, 0x77, 0x65, 0x73,
+ 0x62, 0x73, 0x77, 0x61, 0x65, 0x61, 0x79, 0x76, 0x61, 0x78, 0x62, 0x77, 0x77, 0x70, 0x77, 0x77,
+ 0x77, 0x6b, 0x63, 0x6e, 0x70, 0x76, 0x6e, 0x79, 0x72, 0x68, 0x70, 0x6f, 0x62, 0x74, 0x65, 0x78,
+ 0x6d, 0x76, 0x6a, 0x63, 0x6a, 0x66, 0x6d, 0x77, 0x6c, 0x73, 0x66, 0x6c, 0x78, 0x6e, 0x6d, 0x6b,
+ 0x6f, 0x67, 0x6a, 0x67, 0x71, 0x79, 0x75, 0x77, 0x76, 0x74, 0x6d, 0x6e, 0x68, 0x66, 0x79, 0x69,
+ 0x68, 0x75, 0x64, 0x70, 0x6c, 0x74, 0x77, 0x70, 0x6f, 0x74, 0x71, 0x6f, 0x67, 0x6e, 0x6d, 0x6f,
+ 0x76, 0x62, 0x64, 0x74, 0x65, 0x74, 0x63, 0x66, 0x67, 0x6d, 0x75, 0x63, 0x79, 0x69, 0x65, 0x73,
+ 0x6c, 0x73, 0x65, 0x62, 0x6d, 0x78, 0x68, 0x66, 0x77, 0x66, 0x74, 0x71, 0x6b, 0x65, 0x6d, 0x72,
+ 0x63, 0x73, 0x61, 0x66, 0x6e, 0x71, 0x67, 0x64, 0x73, 0x64, 0x77, 0x6a, 0x78, 0x6f, 0x66, 0x63,
+ 0x61, 0x65, 0x63, 0x76, 0x63, 0x6d, 0x71, 0x6d, 0x79, 0x79, 0x65, 0x61, 0x79, 0x66, 0x6f, 0x64,
+ 0x6b, 0x74, 0x6c, 0x75, 0x70, 0x63, 0x66, 0x77, 0x74, 0x65, 0x70, 0x75, 0x78, 0x63, 0x66, 0x6f,
+ 0x6e, 0x62, 0x6f, 0x62, 0x79, 0x73, 0x65, 0x72, 0x66, 0x6a, 0x63, 0x79, 0x66, 0x73, 0x73, 0x63,
+ 0x62, 0x69, 0x76, 0x63, 0x6e, 0x6b, 0x74, 0x76, 0x75, 0x73, 0x71, 0x74, 0x6e, 0x6e, 0x73, 0x68,
+ 0x65, 0x61, 0x6c, 0x68, 0x67, 0x65, 0x79, 0x6c, 0x79, 0x63, 0x6b, 0x77, 0x62, 0x75, 0x6d, 0x73,
+ 0x6f, 0x70, 0x69, 0x68, 0x68, 0x77, 0x6c, 0x63, 0x63, 0x6e, 0x78, 0x76, 0x69, 0x76, 0x75, 0x74,
+ 0x70, 0x64, 0x6a, 0x70, 0x6c, 0x67, 0x6f, 0x62, 0x6c, 0x73, 0x6e, 0x6e, 0x78, 0x66, 0x74, 0x65,
+ 0x6b, 0x70, 0x79, 0x72, 0x73, 0x69, 0x6c, 0x72, 0x61, 0x6c, 0x78, 0x6e, 0x63, 0x72, 0x72, 0x76,
+ 0x64, 0x68, 0x78, 0x78, 0x70, 0x79, 0x61, 0x76, 0x70, 0x6f, 0x73, 0x6c, 0x69, 0x72, 0x63, 0x72,
+ 0x72, 0x78, 0x62, 0x69, 0x61, 0x73, 0x67, 0x66, 0x64, 0x6b, 0x67, 0x66, 0x79, 0x6c, 0x61, 0x6b,
+ 0x72, 0x6d, 0x6a, 0x74, 0x70, 0x72, 0x69, 0x6b, 0x71, 0x74, 0x6e, 0x6a, 0x79, 0x69, 0x78, 0x73,
+ 0x73, 0x77, 0x68, 0x68, 0x73, 0x6b, 0x78, 0x72, 0x66, 0x6a, 0x68, 0x61, 0x67, 0x67, 0x68, 0x76,
+ 0x6a, 0x71, 0x62, 0x62, 0x68, 0x6b, 0x68, 0x66, 0x76, 0x6b, 0x6e, 0x78, 0x65, 0x77, 0x62, 0x70,
+ 0x72, 0x76, 0x76, 0x6b, 0x76, 0x64, 0x6c, 0x68, 0x79, 0x6f, 0x68, 0x69, 0x6a, 0x66, 0x67, 0x73,
+ 0x63, 0x61, 0x6b, 0x69, 0x74, 0x64, 0x62, 0x6a, 0x76, 0x74, 0x6b, 0x79, 0x77, 0x65, 0x69, 0x65,
+ 0x6b, 0x77, 0x72, 0x74, 0x6f, 0x74, 0x62, 0x64, 0x78, 0x6f, 0x62, 0x73, 0x6b, 0x69, 0x79, 0x64,
+ 0x76, 0x78, 0x71, 0x6a, 0x79, 0x61, 0x77, 0x64, 0x66, 0x77, 0x63, 0x77, 0x77, 0x6b, 0x69, 0x68,
+ 0x6e, 0x6d, 0x67, 0x6a, 0x74, 0x6c, 0x76, 0x68, 0x68, 0x72, 0x61, 0x77, 0x71, 0x64, 0x61, 0x65,
+ 0x6b, 0x72, 0x65, 0x61, 0x6f, 0x64, 0x6d, 0x71, 0x76, 0x68, 0x66, 0x78, 0x71, 0x6c, 0x6e, 0x68,
+ 0x75, 0x74, 0x75, 0x6f, 0x73, 0x70, 0x70, 0x66, 0x76, 0x6d, 0x73, 0x66, 0x6a, 0x75, 0x63, 0x77,
+ 0x69, 0x66, 0x67, 0x76, 0x6b, 0x68, 0x65, 0x63, 0x68, 0x73, 0x6f, 0x75, 0x64, 0x79, 0x6d, 0x6f,
+ 0x6e, 0x79, 0x6a, 0x78, 0x64, 0x69, 0x71, 0x70, 0x6d, 0x78, 0x70, 0x61, 0x63, 0x77, 0x66, 0x79,
+ 0x6c, 0x79, 0x66, 0x70, 0x73, 0x77, 0x65, 0x6b, 0x72, 0x6d, 0x70, 0x65, 0x74, 0x61, 0x68, 0x66,
+ 0x63, 0x79, 0x79, 0x6b, 0x76, 0x76, 0x79, 0x78, 0x6f, 0x76, 0x67, 0x79, 0x77, 0x77, 0x62, 0x77,
+ 0x69, 0x78, 0x74, 0x65, 0x65, 0x6f, 0x6a, 0x6d, 0x76, 0x6d, 0x75, 0x66, 0x6d, 0x6e, 0x70, 0x79,
+ 0x6e, 0x6c, 0x79, 0x67, 0x72, 0x6b, 0x6c, 0x64, 0x76, 0x6c, 0x6e, 0x65, 0x69, 0x64, 0x76, 0x6d,
+ 0x68, 0x79, 0x6b, 0x74, 0x63, 0x6a, 0x63, 0x66, 0x65, 0x74, 0x69, 0x74, 0x71, 0x6e, 0x62, 0x66,
+ 0x78, 0x75, 0x62, 0x74, 0x73, 0x66, 0x61, 0x77, 0x6d, 0x6c, 0x62, 0x77, 0x61, 0x68, 0x6e, 0x76,
+ 0x66, 0x6a, 0x68, 0x73, 0x63, 0x6e, 0x74, 0x64, 0x6a, 0x75, 0x68, 0x63, 0x6f, 0x73, 0x77, 0x6a,
+ 0x68, 0x75, 0x72, 0x69, 0x79, 0x69, 0x65, 0x64, 0x6d, 0x6a, 0x67, 0x70, 0x79, 0x68, 0x6f, 0x6c,
+ 0x6d, 0x75, 0x6f, 0x73, 0x68, 0x68, 0x6f, 0x73, 0x70, 0x6c, 0x65, 0x67, 0x6b, 0x6e, 0x74, 0x69,
+ 0x63, 0x72, 0x6f, 0x63, 0x68, 0x6b, 0x79, 0x74, 0x77, 0x79, 0x76, 0x63, 0x71, 0x6b, 0x6d, 0x6d,
+ 0x6f, 0x69, 0x6c, 0x77, 0x6c, 0x6c, 0x62, 0x6b, 0x71, 0x6c, 0x74, 0x67, 0x6c, 0x64, 0x6b, 0x69,
+ 0x62, 0x73, 0x78, 0x66, 0x68, 0x77, 0x64, 0x74, 0x73, 0x73, 0x71, 0x74, 0x64, 0x6b, 0x6a, 0x69,
+ 0x74, 0x6c, 0x61, 0x72, 0x74, 0x6e, 0x6a, 0x6c, 0x68, 0x78, 0x77, 0x6b, 0x67, 0x6f, 0x6f, 0x6a,
+ 0x61, 0x65, 0x6a, 0x78, 0x67, 0x61, 0x77, 0x72, 0x6e, 0x62, 0x6d, 0x6c, 0x6e, 0x67, 0x69, 0x66,
+ 0x6e, 0x6a, 0x76, 0x69, 0x77, 0x72, 0x79, 0x6f, 0x63, 0x69, 0x6e, 0x67, 0x72, 0x6a, 0x76, 0x69,
+ 0x75, 0x78, 0x6d, 0x6e, 0x65, 0x64, 0x67, 0x70, 0x6a, 0x6d, 0x74, 0x78, 0x79, 0x73, 0x72, 0x70,
+ 0x72, 0x61, 0x6f, 0x77, 0x61, 0x79, 0x6f, 0x72, 0x6b, 0x61, 0x61, 0x75, 0x77, 0x69, 0x63, 0x6d,
+ 0x68, 0x78, 0x74, 0x65, 0x74, 0x67, 0x63, 0x77, 0x63, 0x71, 0x72, 0x72, 0x71, 0x6c, 0x64, 0x79,
+ 0x78, 0x6b, 0x63, 0x75, 0x70, 0x64, 0x6f, 0x6f, 0x6c, 0x76, 0x6f, 0x71, 0x75, 0x6d, 0x63, 0x74,
+ 0x71, 0x63, 0x76, 0x6e, 0x75, 0x63, 0x65, 0x69, 0x67, 0x76, 0x64, 0x61, 0x6d, 0x72, 0x6a, 0x6b,
+ 0x64, 0x70, 0x68, 0x75, 0x67, 0x6c, 0x77, 0x71, 0x61, 0x70, 0x6e, 0x67, 0x73, 0x70, 0x6e, 0x68,
+ 0x73, 0x73, 0x69, 0x65, 0x6a, 0x66, 0x68, 0x67, 0x72, 0x73, 0x72, 0x69, 0x6a, 0x77, 0x6b, 0x78,
+ 0x6a, 0x61, 0x73, 0x66, 0x66, 0x65, 0x6b, 0x65, 0x6b, 0x61, 0x68, 0x6b, 0x6a, 0x73, 0x79, 0x6f,
+ 0x64, 0x78, 0x72, 0x76, 0x6c, 0x67, 0x61, 0x70, 0x79, 0x77, 0x77, 0x6c, 0x69, 0x67, 0x71, 0x76,
+ 0x79, 0x61, 0x72, 0x62, 0x74, 0x64, 0x69, 0x64, 0x6f, 0x78, 0x6d, 0x6f, 0x67, 0x67, 0x6c, 0x78,
+ 0x74, 0x62, 0x64, 0x72, 0x63, 0x70, 0x64, 0x71, 0x79, 0x6f, 0x63, 0x74, 0x6c, 0x69, 0x6c, 0x6d,
+ 0x77, 0x6b, 0x69, 0x63, 0x72, 0x70, 0x70, 0x71, 0x75, 0x73, 0x68, 0x68, 0x6c, 0x79, 0x6c, 0x67,
+ 0x69, 0x65, 0x79, 0x76, 0x6b, 0x74, 0x6f, 0x6d, 0x61, 0x79, 0x79, 0x6a, 0x78, 0x6e, 0x78, 0x62,
+ 0x78, 0x65, 0x61, 0x70, 0x68, 0x75, 0x78, 0x6d, 0x77, 0x77, 0x70, 0x6e, 0x75, 0x67, 0x65, 0x66,
+ 0x6f, 0x6c, 0x65, 0x77, 0x61, 0x6b, 0x69, 0x68, 0x73, 0x61, 0x74, 0x62, 0x6c, 0x6a, 0x65, 0x6d,
+ 0x74, 0x77, 0x77, 0x64, 0x67, 0x6f, 0x76, 0x78, 0x62, 0x6b, 0x71, 0x6d, 0x67, 0x62, 0x75, 0x61,
+ 0x79, 0x78, 0x64, 0x65, 0x65, 0x72, 0x62, 0x64, 0x75, 0x61, 0x66, 0x6e, 0x66, 0x6c, 0x70, 0x73,
+ 0x70, 0x68, 0x6d, 0x79, 0x63, 0x71, 0x64, 0x70, 0x6d, 0x75, 0x78, 0x61, 0x6b, 0x61, 0x62, 0x67,
+ 0x65, 0x62, 0x64, 0x66, 0x64, 0x6a, 0x76, 0x67, 0x68, 0x78, 0x6e, 0x6d, 0x65, 0x79, 0x73, 0x64,
+ 0x63, 0x68, 0x72, 0x71, 0x6a, 0x6f, 0x71, 0x61, 0x77, 0x6a, 0x6b, 0x69, 0x62, 0x73, 0x63, 0x69,
+ 0x73, 0x63, 0x64, 0x6c, 0x67, 0x71, 0x69, 0x75, 0x71, 0x63, 0x64, 0x6b, 0x61, 0x6e, 0x73, 0x6c,
+ 0x65, 0x66, 0x64, 0x6e, 0x6a, 0x74, 0x6b, 0x78, 0x69, 0x6a, 0x64, 0x6a, 0x77, 0x70, 0x70, 0x67,
+ 0x6d, 0x72, 0x6b, 0x65, 0x79, 0x64, 0x61, 0x6f, 0x64, 0x70, 0x73, 0x63, 0x72, 0x6d, 0x68, 0x73,
+ 0x74, 0x6e, 0x6f, 0x72, 0x61, 0x73, 0x61, 0x72, 0x71, 0x72, 0x61, 0x75, 0x77, 0x67, 0x70, 0x68,
+ 0x70, 0x66, 0x61, 0x72, 0x67, 0x73, 0x69, 0x67, 0x6b, 0x71, 0x73, 0x64, 0x77, 0x61, 0x67, 0x70,
+ 0x69, 0x71, 0x72, 0x77, 0x77, 0x68, 0x71, 0x63, 0x6a, 0x61, 0x70, 0x63, 0x70, 0x62, 0x71, 0x68,
+ 0x63, 0x78, 0x71, 0x62, 0x70, 0x79, 0x74, 0x76, 0x76, 0x62, 0x74, 0x63, 0x76, 0x68, 0x62, 0x73,
+ 0x72, 0x64, 0x64, 0x66, 0x71, 0x65, 0x6d, 0x72, 0x63, 0x77, 0x6a, 0x77, 0x6a, 0x76, 0x62, 0x6c,
+ 0x77, 0x65, 0x61, 0x63, 0x6b, 0x62, 0x79, 0x71, 0x75, 0x6b, 0x68, 0x74, 0x6f, 0x66, 0x74, 0x65,
+ 0x72, 0x76, 0x74, 0x6f, 0x71, 0x71, 0x6e, 0x65, 0x63, 0x78, 0x6d, 0x74, 0x74, 0x66, 0x71, 0x78,
+ 0x77, 0x68, 0x75, 0x74, 0x72, 0x62, 0x73, 0x6c, 0x65, 0x71, 0x66, 0x6c, 0x6d, 0x75, 0x66, 0x62,
+ 0x71, 0x78, 0x68, 0x63, 0x65, 0x6f, 0x72, 0x63, 0x69, 0x74, 0x68, 0x74, 0x72, 0x64, 0x62, 0x68,
+ 0x63, 0x65, 0x74, 0x78, 0x67, 0x74, 0x61, 0x74, 0x75, 0x69, 0x6f, 0x6b, 0x78, 0x6c, 0x72, 0x79,
+ 0x77, 0x69, 0x63, 0x6a, 0x6c, 0x75, 0x62, 0x62, 0x77, 0x77, 0x64, 0x77, 0x72, 0x62, 0x79, 0x74,
+ 0x73, 0x6e, 0x75, 0x69, 0x68, 0x64, 0x71, 0x68, 0x6f, 0x65, 0x64, 0x77, 0x63, 0x6f, 0x75, 0x74,
+ 0x6a, 0x74, 0x75, 0x64, 0x62, 0x68, 0x62, 0x76, 0x75, 0x75, 0x66, 0x63, 0x69, 0x62, 0x79, 0x62,
+ 0x6d, 0x70, 0x75, 0x71, 0x74, 0x76, 0x71, 0x63, 0x68, 0x6f, 0x69, 0x77, 0x6b, 0x6b, 0x61, 0x6b,
+ 0x79, 0x74, 0x77, 0x6c, 0x65, 0x67, 0x6b, 0x71, 0x61, 0x76, 0x66, 0x77, 0x69, 0x72, 0x79, 0x66,
+ 0x6e, 0x63, 0x75, 0x70, 0x73, 0x6f, 0x6c, 0x72, 0x70, 0x69, 0x6e, 0x71, 0x61, 0x77, 0x6b, 0x61,
+ 0x6c, 0x70, 0x69, 0x74, 0x72, 0x6a, 0x75, 0x74, 0x78, 0x6e, 0x6a, 0x71, 0x6b, 0x6a, 0x67, 0x71,
+ 0x78, 0x61, 0x6d, 0x77, 0x6b, 0x6d, 0x68, 0x77, 0x79, 0x66, 0x77, 0x6a, 0x75, 0x76, 0x70, 0x62,
+ 0x67, 0x64, 0x64, 0x73, 0x6e, 0x72, 0x71, 0x69, 0x65, 0x6e, 0x66, 0x64, 0x70, 0x65, 0x73, 0x67,
+ 0x6e, 0x74, 0x6e, 0x6e, 0x62, 0x78, 0x68, 0x71, 0x64, 0x62, 0x68, 0x6e, 0x77, 0x6c, 0x6c, 0x74,
+ 0x66, 0x76, 0x72, 0x65, 0x62, 0x79, 0x6d, 0x72, 0x79, 0x78, 0x63, 0x62, 0x64, 0x77, 0x6a, 0x67,
+ 0x6b, 0x6b, 0x79, 0x65, 0x6d, 0x67, 0x6a, 0x72, 0x79, 0x78, 0x63, 0x64, 0x68, 0x66, 0x75, 0x6e,
+ 0x63, 0x6d, 0x70, 0x66, 0x69, 0x64, 0x64, 0x76, 0x74, 0x62, 0x69, 0x66, 0x6f, 0x75, 0x6d, 0x67,
+ 0x63, 0x79, 0x74, 0x61, 0x72, 0x70, 0x6a, 0x73, 0x65, 0x71, 0x71, 0x62, 0x75, 0x75, 0x65, 0x69,
+ 0x6d, 0x6d, 0x72, 0x64, 0x62, 0x64, 0x72, 0x63, 0x74, 0x6e, 0x74, 0x72, 0x6f, 0x79, 0x67, 0x79,
+ 0x78, 0x6c, 0x64, 0x63, 0x6b, 0x74, 0x76, 0x78, 0x70, 0x64, 0x6c, 0x64, 0x72, 0x66, 0x62, 0x71,
+ 0x69, 0x62, 0x61, 0x6a, 0x6f, 0x73, 0x6d, 0x77, 0x6d, 0x65, 0x6b, 0x71, 0x64, 0x6c, 0x63, 0x61,
+ 0x6c, 0x71, 0x65, 0x6c, 0x78, 0x74, 0x76, 0x67, 0x74, 0x69, 0x64, 0x76, 0x72, 0x74, 0x75, 0x68,
+ 0x68, 0x63, 0x77, 0x65, 0x64, 0x67, 0x70, 0x70, 0x70, 0x61, 0x6b, 0x65, 0x68, 0x67, 0x6d, 0x72,
+ 0x6e, 0x6a, 0x64, 0x68, 0x62, 0x69, 0x61, 0x76, 0x6b, 0x71, 0x64, 0x74, 0x66, 0x67, 0x6c, 0x71,
+ 0x6b, 0x76, 0x61, 0x77, 0x79, 0x75, 0x76, 0x6c, 0x71, 0x62, 0x6e, 0x61, 0x6b, 0x6d, 0x6e, 0x6d,
+ 0x77, 0x72, 0x75, 0x66, 0x72, 0x6b, 0x62, 0x6b, 0x62, 0x73, 0x75, 0x75, 0x71, 0x61, 0x67, 0x66,
+ 0x79, 0x70, 0x6c, 0x6c, 0x6b, 0x62, 0x63, 0x66, 0x6a, 0x74, 0x76, 0x6d, 0x70, 0x71, 0x6a, 0x62,
+ 0x68, 0x75, 0x72, 0x75, 0x62, 0x74, 0x70, 0x6b, 0x66, 0x61, 0x67, 0x6e, 0x61, 0x6f, 0x6f, 0x68,
+ 0x77, 0x6a, 0x72, 0x78, 0x79, 0x73, 0x71, 0x78, 0x75, 0x61, 0x78, 0x63, 0x6a, 0x75, 0x73, 0x73,
+ 0x62, 0x70, 0x71, 0x75, 0x63, 0x6e, 0x66, 0x72, 0x74, 0x79, 0x6f, 0x6f, 0x73, 0x6a, 0x75, 0x62,
+ 0x65, 0x79, 0x79, 0x79, 0x75, 0x6f, 0x79, 0x78, 0x6e, 0x77, 0x75, 0x62, 0x66, 0x6e, 0x67, 0x73,
+ 0x63, 0x68, 0x65, 0x74, 0x68, 0x75, 0x6a, 0x78, 0x69, 0x6f, 0x70, 0x62, 0x78, 0x65, 0x68, 0x63,
+ 0x75, 0x78, 0x62, 0x6d, 0x73, 0x6a, 0x68, 0x6a, 0x76, 0x6f, 0x76, 0x6a, 0x6c, 0x73, 0x62, 0x6e,
+ 0x64, 0x68, 0x6f, 0x63, 0x63, 0x67, 0x72, 0x78, 0x64, 0x71, 0x74, 0x76, 0x71, 0x62, 0x66, 0x79,
+ 0x70, 0x61, 0x78, 0x61, 0x77, 0x64, 0x69, 0x79, 0x6e, 0x64, 0x78, 0x66, 0x68, 0x75, 0x65, 0x76,
+ 0x70, 0x6a, 0x67, 0x6a, 0x63, 0x67, 0x61, 0x74, 0x67, 0x77, 0x6c, 0x78, 0x78, 0x75, 0x73, 0x64,
+ 0x69, 0x64, 0x69, 0x6f, 0x72, 0x62, 0x70, 0x65, 0x77, 0x74, 0x74, 0x66, 0x76, 0x6e, 0x74, 0x6b,
+ 0x74, 0x77, 0x76, 0x67, 0x62, 0x75, 0x68, 0x62, 0x66, 0x78, 0x77, 0x72, 0x6a, 0x66, 0x6a, 0x64,
+ 0x6b, 0x6c, 0x70, 0x78, 0x63, 0x77, 0x6b, 0x63, 0x62, 0x77, 0x77, 0x77, 0x65, 0x66, 0x73, 0x64,
+ 0x62, 0x76, 0x6b, 0x73, 0x75, 0x6a, 0x70, 0x63, 0x72, 0x6b, 0x71, 0x73, 0x66, 0x61, 0x70, 0x6c,
+ 0x76, 0x64, 0x61, 0x74, 0x69, 0x76, 0x79, 0x6a, 0x76, 0x75, 0x65, 0x6e, 0x67, 0x63, 0x6e, 0x75,
+ 0x65, 0x74, 0x6c, 0x75, 0x78, 0x6a, 0x6b, 0x78, 0x66, 0x68, 0x71, 0x6e, 0x76, 0x68, 0x68, 0x6c,
+ 0x70, 0x6c, 0x66, 0x64, 0x65, 0x72, 0x6f, 0x73, 0x74, 0x75, 0x6f, 0x6b, 0x6c, 0x6b, 0x6b, 0x6a,
+ 0x74, 0x71, 0x66, 0x63, 0x70, 0x69, 0x6e, 0x61, 0x6d, 0x64, 0x6b, 0x73, 0x74, 0x75, 0x6f, 0x6f,
+ 0x61, 0x61, 0x65, 0x6d, 0x73, 0x67, 0x71, 0x77, 0x65, 0x70, 0x73, 0x67, 0x6d, 0x6d, 0x6d, 0x62,
+ 0x74, 0x6c, 0x68, 0x65, 0x68, 0x74, 0x65, 0x76, 0x62, 0x6f, 0x70, 0x6c, 0x74, 0x68, 0x76, 0x6e,
+ 0x6c, 0x68, 0x6b, 0x76, 0x68, 0x68, 0x78, 0x72, 0x79, 0x6a, 0x67, 0x64, 0x71, 0x71, 0x6a, 0x77,
+ 0x6a, 0x74, 0x74, 0x64, 0x72, 0x69, 0x74, 0x74, 0x66, 0x61, 0x71, 0x70, 0x64, 0x68, 0x69, 0x6b,
+ 0x6b, 0x6e, 0x6b, 0x6a, 0x61, 0x70, 0x73, 0x68, 0x70, 0x62, 0x65, 0x77, 0x77, 0x62, 0x64, 0x73,
+ 0x6a, 0x6e, 0x79, 0x76, 0x78, 0x68, 0x6d, 0x6a, 0x6c, 0x76, 0x61, 0x71, 0x73, 0x73, 0x69, 0x78,
+ 0x69, 0x6c, 0x65, 0x73, 0x6f, 0x6d, 0x67, 0x6a, 0x64, 0x6b, 0x6e, 0x73, 0x69, 0x72, 0x64, 0x65,
+ 0x77, 0x71, 0x79, 0x72, 0x67, 0x71, 0x68, 0x6a, 0x63, 0x74, 0x75, 0x70, 0x79, 0x75, 0x73, 0x78,
+ 0x6d, 0x64, 0x76, 0x63, 0x67, 0x64, 0x69, 0x6b, 0x77, 0x73, 0x6a, 0x6d, 0x6b, 0x6d, 0x77, 0x68,
+ 0x62, 0x6c, 0x67, 0x76, 0x6a, 0x6f, 0x64, 0x6a, 0x76, 0x64, 0x61, 0x6a, 0x74, 0x77, 0x68, 0x69,
+ 0x6a, 0x6d, 0x6d, 0x6b, 0x67, 0x6f, 0x76, 0x73, 0x6e, 0x6f, 0x70, 0x67, 0x65, 0x77, 0x68, 0x63,
+ 0x64, 0x75, 0x64, 0x63, 0x79, 0x62, 0x77, 0x78, 0x64, 0x70, 0x6b, 0x70, 0x70, 0x69, 0x75, 0x62,
+ 0x73, 0x76, 0x76, 0x72, 0x67, 0x6f, 0x73, 0x6e, 0x70, 0x74, 0x70, 0x6d, 0x78, 0x79, 0x77, 0x6e,
+ 0x75, 0x77, 0x70, 0x76, 0x6f, 0x62, 0x73, 0x64, 0x78, 0x6f, 0x66, 0x64, 0x67, 0x69, 0x68, 0x79,
+ 0x70, 0x71, 0x72, 0x72, 0x6a, 0x73, 0x6d, 0x78, 0x61, 0x64, 0x67, 0x70, 0x72, 0x77, 0x79, 0x65,
+ 0x6e, 0x72, 0x62, 0x64, 0x74, 0x62, 0x72, 0x72, 0x78, 0x76, 0x79, 0x76, 0x68, 0x63, 0x64, 0x62,
+ 0x67, 0x70, 0x6e, 0x76, 0x6d, 0x6f, 0x74, 0x72, 0x76, 0x61, 0x64, 0x72, 0x74, 0x79, 0x67, 0x64,
+ 0x6f, 0x74, 0x69, 0x68, 0x78, 0x79, 0x65, 0x69, 0x69, 0x64, 0x6c, 0x63, 0x69, 0x62, 0x63, 0x61,
+ 0x64, 0x68, 0x78, 0x65, 0x64, 0x67, 0x6d, 0x6e, 0x6e, 0x67, 0x71, 0x6e, 0x65, 0x76, 0x76, 0x64,
+ 0x6a, 0x66, 0x65, 0x70, 0x77, 0x79, 0x67, 0x74, 0x74, 0x67, 0x6c, 0x69, 0x65, 0x72, 0x6e, 0x70,
+ 0x62, 0x6b, 0x78, 0x65, 0x68, 0x74, 0x70, 0x6a, 0x64, 0x6d, 0x6e, 0x79, 0x76, 0x73, 0x70, 0x72,
+ 0x6f, 0x67, 0x62, 0x75, 0x63, 0x64, 0x74, 0x74, 0x71, 0x78, 0x73, 0x79, 0x69, 0x79, 0x62, 0x66,
+ 0x64, 0x75, 0x6f, 0x76, 0x68, 0x75, 0x72, 0x75, 0x66, 0x71, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x67,
+ 0x61, 0x69, 0x6b, 0x69, 0x77, 0x68, 0x72, 0x69, 0x6b, 0x70, 0x72, 0x6b, 0x75, 0x66, 0x64, 0x79,
+ 0x6b, 0x65, 0x71, 0x69, 0x61, 0x67, 0x6c, 0x75, 0x64, 0x70, 0x75, 0x72, 0x68, 0x65, 0x73, 0x69,
+ 0x67, 0x65, 0x6d, 0x71, 0x66, 0x79, 0x61, 0x64, 0x70, 0x65, 0x73, 0x6a, 0x76, 0x76, 0x79, 0x71,
+ 0x71, 0x6e, 0x76, 0x64, 0x63, 0x6b, 0x73, 0x70, 0x6a, 0x6d, 0x65, 0x73, 0x74, 0x63, 0x6a, 0x6f,
+ 0x73, 0x75, 0x76, 0x72, 0x67, 0x67, 0x61, 0x72, 0x66, 0x70, 0x77, 0x79, 0x78, 0x6a, 0x76, 0x64,
+ 0x61, 0x6c, 0x6f, 0x79, 0x73, 0x62, 0x69, 0x62, 0x64, 0x6e, 0x62, 0x69, 0x67, 0x6d, 0x6e, 0x6b,
+ 0x78, 0x66, 0x64, 0x61, 0x6d, 0x79, 0x63, 0x77, 0x66, 0x61, 0x64, 0x72, 0x6a, 0x6e, 0x74, 0x78,
+ 0x62, 0x63, 0x6f, 0x6f, 0x66, 0x6d, 0x6b, 0x63, 0x64, 0x76, 0x6d, 0x67, 0x75, 0x65, 0x68, 0x6b,
+ 0x68, 0x63, 0x77, 0x6a, 0x70, 0x77, 0x6b, 0x67, 0x61, 0x79, 0x6b, 0x62, 0x79, 0x74, 0x68, 0x73,
+ 0x71, 0x78, 0x75, 0x75, 0x63, 0x64, 0x6f, 0x6a, 0x6b, 0x61, 0x73, 0x75, 0x6e, 0x71, 0x63, 0x68,
+ 0x71, 0x6a, 0x78, 0x6b, 0x68, 0x70, 0x68, 0x73, 0x72, 0x65, 0x73, 0x64, 0x70, 0x75, 0x64, 0x78,
+ 0x78, 0x78, 0x66, 0x76, 0x6f, 0x71, 0x65, 0x63, 0x61, 0x76, 0x74, 0x64, 0x78, 0x6b, 0x72, 0x61,
+ 0x6e, 0x64, 0x6e, 0x65, 0x78, 0x77, 0x63, 0x65, 0x6c, 0x6d, 0x77, 0x6c, 0x79, 0x6b, 0x65, 0x74,
+ 0x78, 0x62, 0x73, 0x66, 0x76, 0x62, 0x79, 0x76, 0x61, 0x79, 0x70, 0x69, 0x64, 0x66, 0x6b, 0x68,
+ 0x72, 0x62, 0x74, 0x6d, 0x6b, 0x75, 0x73, 0x67, 0x68, 0x78, 0x61, 0x6e, 0x62, 0x6f, 0x75, 0x65,
+ 0x72, 0x65, 0x78, 0x75, 0x69, 0x67, 0x70, 0x6e, 0x73, 0x61, 0x71, 0x61, 0x65, 0x77, 0x69, 0x6c,
+ 0x6a, 0x73, 0x62, 0x73, 0x66, 0x6b, 0x6f, 0x71, 0x73, 0x71, 0x62, 0x73, 0x78, 0x6d, 0x77, 0x67,
+ 0x78, 0x75, 0x66, 0x6c, 0x77, 0x6e, 0x65, 0x6c, 0x63, 0x79, 0x77, 0x6f, 0x70, 0x6f, 0x65, 0x75,
+ 0x72, 0x6f, 0x67, 0x63, 0x6c, 0x69, 0x75, 0x70, 0x69, 0x70, 0x6e, 0x67, 0x74, 0x72, 0x72, 0x72,
+ 0x6e, 0x69, 0x70, 0x74, 0x71, 0x68, 0x70, 0x76, 0x6b, 0x62, 0x68, 0x6f, 0x77, 0x66, 0x6b, 0x64,
+ 0x75, 0x66, 0x67, 0x79, 0x65, 0x65, 0x78, 0x61, 0x70, 0x67, 0x77, 0x76, 0x67, 0x6d, 0x64, 0x65,
+ 0x69, 0x62, 0x73, 0x65, 0x67, 0x70, 0x74, 0x6e, 0x67, 0x78, 0x75, 0x69, 0x6a, 0x68, 0x6d, 0x65,
+ 0x78, 0x62, 0x6d, 0x6d, 0x62, 0x68, 0x65, 0x6c, 0x6e, 0x67, 0x6b, 0x61, 0x78, 0x6f, 0x62, 0x79,
+ 0x64, 0x78, 0x6f, 0x65, 0x74, 0x72, 0x73, 0x6d, 0x6c, 0x61, 0x76, 0x77, 0x68, 0x64, 0x71, 0x77,
+ 0x71, 0x79, 0x77, 0x69, 0x6c, 0x66, 0x75, 0x65, 0x79, 0x72, 0x70, 0x75, 0x6b, 0x61, 0x64, 0x6c,
+ 0x67, 0x6e, 0x6e, 0x72, 0x75, 0x68, 0x68, 0x71, 0x62, 0x65, 0x72, 0x72, 0x73, 0x68, 0x71, 0x6a,
+ 0x78, 0x74, 0x74, 0x6a, 0x6a, 0x6f, 0x6d, 0x67, 0x62, 0x61, 0x6b, 0x6a, 0x66, 0x6a, 0x66, 0x6e,
+ 0x75, 0x64, 0x64, 0x74, 0x6e, 0x64, 0x62, 0x6f, 0x71, 0x6d, 0x74, 0x6c, 0x6b, 0x72, 0x6e, 0x68,
+ 0x6a, 0x70, 0x6d, 0x72, 0x66, 0x64, 0x6d, 0x71, 0x6b, 0x66, 0x65, 0x6e, 0x69, 0x74, 0x69, 0x68,
+ 0x78, 0x6c, 0x61, 0x66, 0x79, 0x6e, 0x71, 0x62, 0x75, 0x63, 0x6f, 0x79, 0x6b, 0x78, 0x65, 0x6f,
+ 0x73, 0x70, 0x64, 0x69, 0x74, 0x6d, 0x6d, 0x67, 0x6a, 0x75, 0x79, 0x71, 0x72, 0x67, 0x6f, 0x72,
+ 0x61, 0x6c, 0x79, 0x77, 0x72, 0x67, 0x66, 0x76, 0x77, 0x66, 0x71, 0x79, 0x79, 0x77, 0x74, 0x73,
+ 0x61, 0x63, 0x77, 0x79, 0x6f, 0x6b, 0x70, 0x78, 0x79, 0x62, 0x72, 0x63, 0x78, 0x66, 0x74, 0x65,
+ 0x79, 0x66, 0x63, 0x6a, 0x69, 0x6c, 0x64, 0x62, 0x62, 0x78, 0x64, 0x68, 0x72, 0x73, 0x64, 0x62,
+ 0x67, 0x76, 0x6a, 0x75, 0x74, 0x70, 0x79, 0x6e, 0x6e, 0x64, 0x63, 0x79, 0x63, 0x75, 0x73, 0x67,
+ 0x77, 0x77, 0x6a, 0x69, 0x76, 0x74, 0x75, 0x69, 0x76, 0x71, 0x62, 0x6f, 0x68, 0x70, 0x78, 0x69,
+ 0x75, 0x74, 0x76, 0x66, 0x6c, 0x77, 0x69, 0x66, 0x6b, 0x6b, 0x70, 0x6b, 0x6d, 0x6b, 0x79, 0x76,
+ 0x69, 0x73, 0x64, 0x69, 0x74, 0x64, 0x6b, 0x72, 0x6c, 0x78, 0x64, 0x68, 0x66, 0x63, 0x75, 0x72,
+ 0x6d, 0x6f, 0x68, 0x6e, 0x61, 0x76, 0x72, 0x79, 0x69, 0x67, 0x76, 0x69, 0x70, 0x6e, 0x6a, 0x6c,
+ 0x64, 0x79, 0x68, 0x65, 0x79, 0x63, 0x74, 0x6b, 0x64, 0x72, 0x62, 0x6e, 0x77, 0x6e, 0x6d, 0x62,
+ 0x78, 0x72, 0x77, 0x6c, 0x67, 0x74, 0x6a, 0x75, 0x78, 0x69, 0x65, 0x63, 0x6e, 0x72, 0x70, 0x70,
+ 0x69, 0x69, 0x62, 0x77, 0x61, 0x63, 0x77, 0x62, 0x6e, 0x61, 0x79, 0x66, 0x77, 0x73, 0x75, 0x71,
+ 0x6b, 0x6d, 0x68, 0x74, 0x69, 0x65, 0x6a, 0x67, 0x6c, 0x71, 0x77, 0x6d, 0x68, 0x78, 0x66, 0x68,
+ 0x68, 0x75, 0x6c, 0x65, 0x6e, 0x6e, 0x77, 0x6d, 0x79, 0x62, 0x6c, 0x76, 0x62, 0x6c, 0x69, 0x61,
+ 0x76, 0x68, 0x68, 0x78, 0x6d, 0x68, 0x6d, 0x75, 0x67, 0x6d, 0x68, 0x64, 0x63, 0x68, 0x6e, 0x6d,
+ 0x68, 0x63, 0x76, 0x74, 0x78, 0x78, 0x66, 0x61, 0x64, 0x6a, 0x69, 0x6e, 0x74, 0x66, 0x63, 0x62,
+ 0x68, 0x78, 0x74, 0x73, 0x72, 0x78, 0x6b, 0x76, 0x79, 0x61, 0x65, 0x61, 0x68, 0x6d, 0x73, 0x76,
+ 0x74, 0x69, 0x6c, 0x70, 0x6a, 0x6b, 0x77, 0x72, 0x67, 0x79, 0x65, 0x6c, 0x6a, 0x77, 0x66, 0x73,
+ 0x66, 0x67, 0x71, 0x6f, 0x67, 0x61, 0x68, 0x6c, 0x73, 0x6e, 0x72, 0x67, 0x75, 0x6e, 0x78, 0x79,
+ 0x72, 0x62, 0x78, 0x63, 0x6d, 0x69, 0x79, 0x62, 0x63, 0x70, 0x64, 0x70, 0x67, 0x78, 0x79, 0x6d,
+ 0x76, 0x65, 0x6e, 0x68, 0x70, 0x65, 0x6c, 0x73, 0x71, 0x63, 0x6a, 0x75, 0x75, 0x6f, 0x66, 0x77,
+ 0x72, 0x6d, 0x6b, 0x71, 0x72, 0x6a, 0x6b, 0x71, 0x74, 0x75, 0x64, 0x64, 0x6e, 0x6e, 0x6f, 0x63,
+ 0x74, 0x72, 0x76, 0x76, 0x77, 0x67, 0x65, 0x6a, 0x69, 0x78, 0x63, 0x6a, 0x68, 0x68, 0x63, 0x74,
+ 0x6f, 0x70, 0x61, 0x73, 0x6e, 0x61, 0x64, 0x62, 0x6b, 0x65, 0x61, 0x74, 0x77, 0x62, 0x74, 0x6d,
+ 0x66, 0x62, 0x6e, 0x76, 0x6e, 0x6c, 0x67, 0x78, 0x67, 0x6b, 0x77, 0x64, 0x67, 0x69, 0x73, 0x79,
+ 0x67, 0x77, 0x6e, 0x6f, 0x68, 0x73, 0x6c, 0x69, 0x68, 0x75, 0x65, 0x6c, 0x77, 0x74, 0x77, 0x78,
+ 0x62, 0x62, 0x68, 0x6d, 0x6f, 0x77, 0x74, 0x68, 0x78, 0x67, 0x71, 0x79, 0x62, 0x74, 0x6d, 0x66,
+ 0x78, 0x64, 0x69, 0x6f, 0x65, 0x70, 0x6b, 0x62, 0x68, 0x6c, 0x62, 0x69, 0x63, 0x75, 0x6e, 0x68,
+ 0x79, 0x73, 0x78, 0x6f, 0x6b, 0x78, 0x65, 0x79, 0x71, 0x6e, 0x6a, 0x67, 0x73, 0x62, 0x73, 0x6b,
+ 0x6f, 0x68, 0x6e, 0x65, 0x6e, 0x78, 0x62, 0x61, 0x62, 0x78, 0x6e, 0x71, 0x72, 0x6a, 0x71, 0x67,
+ 0x70, 0x79, 0x67, 0x6e, 0x69, 0x75, 0x74, 0x71, 0x70, 0x78, 0x66, 0x70, 0x61, 0x6f, 0x6a, 0x70,
+ 0x61, 0x76, 0x74, 0x76, 0x67, 0x74, 0x79, 0x65, 0x67, 0x6b, 0x64, 0x78, 0x70, 0x63, 0x66, 0x79,
+ 0x74, 0x65, 0x74, 0x6f, 0x62, 0x79, 0x77, 0x74, 0x77, 0x71, 0x63, 0x61, 0x73, 0x78, 0x6c, 0x77,
+ 0x6c, 0x71, 0x67, 0x62, 0x79, 0x69, 0x67, 0x6a, 0x6f, 0x6c, 0x68, 0x67, 0x64, 0x76, 0x66, 0x73,
+ 0x77, 0x6d, 0x76, 0x65, 0x62, 0x68, 0x68, 0x76, 0x61, 0x68, 0x6d, 0x75, 0x6e, 0x61, 0x76, 0x00, 0x00
+};
+
+
+int main()
+{
+ const int ntests = 10;
+ size_t bufsize = sizeof(buf) - 1;
+ int i;
+ size_t bufsizes[ntests];
+ char old;
+
+ for (i = ntests-1; i >= 0; --i)
+ {
+ bufsizes[i] = bufsize;
+ bufsize /= 2;
+ }
+
+ printf("\n\n");
+ printf("Testing pathological pattern '.+nonexisting.+' to force worst-case asymptotic performance: \n");
+
+ for (i = 0; i < ntests; ++i)
+ {
+ old = buf[bufsizes[i]];
+ buf[bufsizes[i]] = 0;
+
+ printf(" matching on %lu bytes of test input: ", bufsizes[i]);
+ fflush(stdout);
+ printf("%d \n", re_match(".+nonexisting.+", buf));
+
+ buf[bufsizes[i]] = old;
+ }
+
+ printf("\n\n");
+
+ return 0;
+}
+
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_print.c b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_print.c
new file mode 100644
index 0000000000..42eddbe704
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_print.c
@@ -0,0 +1,21 @@
+/*
+ This program prints out a verbose explanation of a given regular expression.
+*/
+
+#include <stdio.h>
+#include "re.h"
+
+
+int main(int argc, char** argv)
+{
+ if (argc == 2)
+ {
+ re_print(re_compile(argv[1]));
+ }
+ else
+ {
+ printf("\nUsage: %s <PATTERN> \n", argv[0]);
+ }
+ return -2;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand.c b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand.c
new file mode 100644
index 0000000000..5a8baede6c
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand.c
@@ -0,0 +1,28 @@
+/*
+ This program tries to match a given regular expression with text given as input to stdin.
+ If the text is a match for the pattern, the program returns 0.
+ If the text doesn't match the pattern, the program returns -2.
+
+ This program is used in random testing to test a lot of random text and regex together.
+ See ./scripts/regex_test.py and the Makefile for this project for the gritty details.
+*/
+
+#include <stdio.h>
+#include "re.h"
+
+
+int main(int argc, char** argv)
+{
+ if (argc == 3)
+ {
+ int m = re_match(argv[1], argv[2]);
+ if (m != -1)
+ return 0;
+ }
+ else
+ {
+ printf("\nUsage: %s <PATTERN> <TEXT> \n", argv[0]);
+ }
+ return -2;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand_neg.c b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand_neg.c
new file mode 100644
index 0000000000..192ce5c608
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/tests/test_rand_neg.c
@@ -0,0 +1,29 @@
+/*
+ Negative version of test_rand.c -- returns true if no match
+
+ This program tries to match a given regular expression with text given as input to stdin.
+ If the text is NOT a match for the pattern, the program returns 0.
+ If the text does match the pattern, the program returns -2.
+
+ This program is used in random testing to test a lot of random text and regex together.
+ See ./scripts/regex_test_neg.py and the Makefile for this project for the gritty details.
+*/
+
+#include <stdio.h>
+#include "re.h"
+
+
+int main(int argc, char** argv)
+{
+ if (argc == 3)
+ {
+ int m = re_match(argv[1], argv[2]);
+ if (m == -1)
+ return 0;
+ }
+ else
+ {
+ printf("\nUsage: %s <PATTERN> <TEXT> \n", argv[0]);
+ }
+ return -2;
+}
diff --git a/erts/lib_src/yielding_c_fun/main_target.mk b/erts/lib_src/yielding_c_fun/main_target.mk
new file mode 100644
index 0000000000..de37c19897
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/main_target.mk
@@ -0,0 +1,26 @@
+# This file is included by GNUmakefile
+
+YCF_INCLUDE_DIRS = \
+ -I$(YCF_SOURCE_DIR) \
+ -I$(YCF_SOURCE_DIR)/lib/tiny_regex_c \
+ -I$(YCF_SOURCE_DIR)/lib/simple_c_gc
+
+YCF_HEADERS = $(sort $(shell find $(YCF_SOURCE_DIR) -name '*.h'))
+
+YCF_EXTRA_SOURCES = \
+ $(YCF_SOURCE_DIR)/lib/tiny_regex_c/re.c \
+ $(YCF_SOURCE_DIR)/lib/simple_c_gc/simple_c_gc.c
+
+YCF_SOURCES = $(sort $(wildcard $(YCF_SOURCE_DIR)/*.c) $(YCF_EXTRA_SOURCES))
+
+YCF_OBJECTS = $(patsubst $(YCF_SOURCE_DIR)/%.c, $(YCF_SOURCE_DIR)/%.o, $(YCF_SOURCES))
+
+YCF_CFLAGS = $(filter-out -Wstrict-prototypes -Wdeclaration-after-statement -Wmissing-prototypes,$(CFLAGS))
+
+YCF_EXECUTABLE = $(YCF_SOURCE_DIR)/bin/yielding_c_fun.bin$(EXE_SUFFIX)
+
+$(YCF_EXECUTABLE): $(YCF_OBJECTS)
+ $(V_LD) $(YCF_CFLAGS) $(LDFLAGS) $(YCF_OBJECTS) -o $@
+
+$(YCF_SOURCE_DIR)/%.o: $(YCF_SOURCE_DIR)/%.c $(YCF_HEADERS)
+ $(V_CC) $(YCF_CFLAGS) $(LDFLAGS) $(YCF_INCLUDE_DIRS) -c $< -o $@
diff --git a/erts/lib_src/yielding_c_fun/test/examples/auto_yield.c b/erts/lib_src/yielding_c_fun/test/examples/auto_yield.c
new file mode 100644
index 0000000000..3fa85ba061
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/auto_yield.c
@@ -0,0 +1,124 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int rec_inc(int to_inc, int nr_of_incs){
+ int res;
+ printf("nr_of_incs %d\n", nr_of_incs);
+ if(nr_of_incs == 0) {
+ return to_inc;
+ } else {
+ res = rec_inc(to_inc + 1, nr_of_incs -1);
+ return res;
+ }
+}
+
+
+int fun(){
+ int i;
+ int v1;
+ int v2 = 13;
+ int v3 = 7;
+ int v4 = 5;
+ int v5 = 2;
+ printf("REC CALL START\n");
+ v1 = rec_inc(42, 100); /* v1 == 142 */
+ printf("REC CALL END\n");
+ printf("FOR LOOP START\n");
+ for(i = 0; i < 100; i++){
+ v2 = v2 + 1;
+ } /* v2 == 113 */
+ printf("FOR LOOP END\n");
+ printf("WHILE LOOP START\n");
+ i = 0;
+ while(i < 100){
+ v3 = v3 + 1;
+ i++;
+ } /* v3 == 107 */
+ printf("WHILE LOOP END\n");
+ printf("DO WHILE LOOP START\n");
+ i = 0;
+ do {
+ v4 = v4 + 1;
+ i++;
+ } while (i < 100); /* v4 == 105 */
+ printf("DO WHILE LOOP END\n");
+ printf("GOTO START\n");
+ i = 0;
+ my_label:
+ v5 = v5 + 1;
+ i++;
+ if (i < 100) goto my_label; /* v5 == 102 */
+ printf("GOTO END\n");
+ return v1 + v2 + v3 + v4 + v5; /* 142 + 113 + 107 + 105 + 102 == 569 */
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ nr_of_reductions = 10;
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL);
+ if(wb != NULL){
+ printf("TRAPPED %ld\n", nr_of_reductions);
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+ printf("REDS LEFT WHEN READY %ld\n", nr_of_reductions);
+#else
+ ret = fun();
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 569){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/auto_yield.c.out b/erts/lib_src/yielding_c_fun/test/examples/auto_yield.c.out
new file mode 100644
index 0000000000..d6962791d0
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/auto_yield.c.out
@@ -0,0 +1,173 @@
+REC CALL START
+nr_of_incs 100
+nr_of_incs 99
+nr_of_incs 98
+nr_of_incs 97
+nr_of_incs 96
+nr_of_incs 95
+nr_of_incs 94
+nr_of_incs 93
+nr_of_incs 92
+TRAPPED 0
+nr_of_incs 91
+nr_of_incs 90
+nr_of_incs 89
+nr_of_incs 88
+nr_of_incs 87
+nr_of_incs 86
+nr_of_incs 85
+nr_of_incs 84
+nr_of_incs 83
+nr_of_incs 82
+TRAPPED 0
+nr_of_incs 81
+nr_of_incs 80
+nr_of_incs 79
+nr_of_incs 78
+nr_of_incs 77
+nr_of_incs 76
+nr_of_incs 75
+nr_of_incs 74
+nr_of_incs 73
+nr_of_incs 72
+TRAPPED 0
+nr_of_incs 71
+nr_of_incs 70
+nr_of_incs 69
+nr_of_incs 68
+nr_of_incs 67
+nr_of_incs 66
+nr_of_incs 65
+nr_of_incs 64
+nr_of_incs 63
+nr_of_incs 62
+TRAPPED 0
+nr_of_incs 61
+nr_of_incs 60
+nr_of_incs 59
+nr_of_incs 58
+nr_of_incs 57
+nr_of_incs 56
+nr_of_incs 55
+nr_of_incs 54
+nr_of_incs 53
+nr_of_incs 52
+TRAPPED 0
+nr_of_incs 51
+nr_of_incs 50
+nr_of_incs 49
+nr_of_incs 48
+nr_of_incs 47
+nr_of_incs 46
+nr_of_incs 45
+nr_of_incs 44
+nr_of_incs 43
+nr_of_incs 42
+TRAPPED 0
+nr_of_incs 41
+nr_of_incs 40
+nr_of_incs 39
+nr_of_incs 38
+nr_of_incs 37
+nr_of_incs 36
+nr_of_incs 35
+nr_of_incs 34
+nr_of_incs 33
+nr_of_incs 32
+TRAPPED 0
+nr_of_incs 31
+nr_of_incs 30
+nr_of_incs 29
+nr_of_incs 28
+nr_of_incs 27
+nr_of_incs 26
+nr_of_incs 25
+nr_of_incs 24
+nr_of_incs 23
+nr_of_incs 22
+TRAPPED 0
+nr_of_incs 21
+nr_of_incs 20
+nr_of_incs 19
+nr_of_incs 18
+nr_of_incs 17
+nr_of_incs 16
+nr_of_incs 15
+nr_of_incs 14
+nr_of_incs 13
+nr_of_incs 12
+TRAPPED 0
+nr_of_incs 11
+nr_of_incs 10
+nr_of_incs 9
+nr_of_incs 8
+nr_of_incs 7
+nr_of_incs 6
+nr_of_incs 5
+nr_of_incs 4
+nr_of_incs 3
+nr_of_incs 2
+TRAPPED 0
+nr_of_incs 1
+nr_of_incs 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+REC CALL END
+FOR LOOP START
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+FOR LOOP END
+WHILE LOOP START
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+WHILE LOOP END
+DO WHILE LOOP START
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+DO WHILE LOOP END
+GOTO START
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+TRAPPED 0
+GOTO END
+REDS LEFT WHEN READY 8
+RETURNED 569
diff --git a/erts/lib_src/yielding_c_fun/test/examples/const_defenition.c b/erts/lib_src/yielding_c_fun/test/examples/const_defenition.c
new file mode 100644
index 0000000000..683acda063
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/const_defenition.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(const char x){
+ const int y = x + 1; /* y == 2*/
+ int const *ptr = NULL;
+ YCF_YIELD();
+ if(ptr != NULL){
+ printf("ERROR\n");
+ }
+ return y;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 2){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/const_defenition.c.out b/erts/lib_src/yielding_c_fun/test/examples/const_defenition.c.out
new file mode 100644
index 0000000000..37d51cb983
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/const_defenition.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 2
diff --git a/erts/lib_src/yielding_c_fun/test/examples/consume_reds.c b/erts/lib_src/yielding_c_fun/test/examples/consume_reds.c
new file mode 100644
index 0000000000..fcab3dbe5e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/consume_reds.c
@@ -0,0 +1,85 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+#define YCF_CONSUME_REDS(X)
+
+int fun(int x){
+ int i;
+ int count = 0;
+ for(i = 0; i < 100; i++){
+ count = count + 2;
+ YCF_CONSUME_REDS(10);
+ }
+ return count + x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ int nr_of_yields = 0;
+ long nr_of_reductions;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ nr_of_reductions = 101;
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED %ld\n", nr_of_reductions);
+ nr_of_yields++;
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("Number of yields %d\n", nr_of_yields);
+ printf("RETURNED %d\n", ret);
+ if(ret != 201){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/consume_reds.c.out b/erts/lib_src/yielding_c_fun/test/examples/consume_reds.c.out
new file mode 100644
index 0000000000..32b93f33f6
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/consume_reds.c.out
@@ -0,0 +1,11 @@
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+Number of yields 9
+RETURNED 201
diff --git a/erts/lib_src/yielding_c_fun/test/examples/control_statements.c b/erts/lib_src/yielding_c_fun/test/examples/control_statements.c
new file mode 100644
index 0000000000..3abac5e57d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/control_statements.c
@@ -0,0 +1,289 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(char x){
+ YCF_YIELD();
+ if(x == 1){
+ /*empty control statement*/
+ } else {
+ /* another empty*/
+ }
+ if(x == 1){
+
+ } else {
+
+ }
+ if(x == 1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_1 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ if(x == 1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_2 %d %d\n", x, y);
+ }else printf("Hej\n");
+ YCF_YIELD();
+ if(x == 1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_3 %d %d\n", x, y);
+ }else if(x == 1){
+ int y = 4;
+ printf("Hej %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ if(x == 2){
+ int y = 4;
+ printf("Hej %d %d\n", x, y);
+ }else if(x == 1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_4 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ if(x == 2){
+ int y = 4;
+ printf("Hej %d %d\n", x, y);
+ }else{
+ int y = 4;
+ YCF_YIELD();
+ printf("s_5 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ while(x == 1) {
+ int y = 4;
+ x = 2;
+ YCF_YIELD();
+ printf("s_6 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ x = 1;
+ YCF_YIELD();
+ do x++; while(x == 1);
+ YCF_YIELD();
+ printf("s_7 %d\n", x);
+ YCF_YIELD();
+ x = 1;
+ do {
+ int y = 4;
+ YCF_YIELD();
+ printf("s_8 %d %d\n", x, y);
+ YCF_YIELD();
+ x++;
+ } while(x == 2);
+ YCF_YIELD();
+ x = 1;
+ YCF_YIELD();
+ while(x==1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_9 %d %d\n", x, y);
+ YCF_YIELD();
+ x++;
+ }
+ YCF_YIELD();
+ x = 2;
+ for(;;){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_10 %d %d\n", x, y);
+ YCF_YIELD();
+ break;
+ }
+ YCF_YIELD();
+ for(x = 0;x < 10;x++){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_11 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ x = 42;
+ YCF_YIELD();
+ switch(x){
+ int y;
+ case 42:
+ y = 4;
+ YCF_YIELD();
+ printf("s_12 %d %d\n", x, y);
+ YCF_YIELD();
+ }
+ YCF_YIELD();
+ {
+ x = 1;
+ YCF_YIELD();
+ if(x == 1) if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_1 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ if(x == 1) switch(1){
+ int y;
+ case 1:;
+ y = 4;
+ YCF_YIELD();
+ printf("s_2 %d %d\n", x, y);
+ }else printf("Hej\n");
+ YCF_YIELD();
+ if(x == 1) switch(1){
+ int y;
+ case 1:;
+ y = 4;
+ YCF_YIELD();
+ printf("s_3 %d %d\n", x, y);
+ }else if(x == 1){
+ int y = 4;
+ printf("Hej %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ if(x == 2){
+ int y = 4;
+ printf("Hej %d %d\n", x, y);
+ }else if(x == 1) if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_4 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ if(x == 2){
+ int y = 4;
+ printf("Hej %d %d\n", x, y);
+ }else if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_5 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ while(x == 1) if(1) {
+ int y = 4;
+ x = 2;
+ YCF_YIELD();
+ printf("s_6 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ x = 1;
+ YCF_YIELD();
+ do if(1) x++; while(x == 1);
+ YCF_YIELD();
+ printf("s_7 %d\n", x);
+ YCF_YIELD();
+ x = 1;
+ do if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_8 %d %d\n", x, y);
+ YCF_YIELD();
+ x++;
+ } while(x == 2);
+ YCF_YIELD();
+ x = 1;
+ YCF_YIELD();
+ while(x==1) if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_9 %d %d\n", x, y);
+ YCF_YIELD();
+ x++;
+ }
+ YCF_YIELD();
+ x = 2;
+ for(;;) if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_10 %d %d\n", x, y);
+ YCF_YIELD();
+ break;
+ }
+ YCF_YIELD();
+ for(x = 0;x < 10;x++) if(1){
+ int y = 4;
+ YCF_YIELD();
+ printf("s_11 %d %d\n", x, y);
+ }
+ YCF_YIELD();
+ x = 42;
+ YCF_YIELD();
+ switch(x){
+ int y;
+ case 42:
+ y = 4;
+ YCF_YIELD();
+ printf("s_12 %d %d\n", x, y);
+ YCF_YIELD();
+ }
+ YCF_YIELD();
+ }
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ int nr_of_trapps = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ nr_of_trapps++;
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+ nr_of_trapps = 86;
+#endif
+ printf("RETURNED %d %d\n", ret, nr_of_trapps);
+ if(ret != 42){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/control_statements.c.out b/erts/lib_src/yielding_c_fun/test/examples/control_statements.c.out
new file mode 100644
index 0000000000..1beeae592e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/control_statements.c.out
@@ -0,0 +1,45 @@
+s_1 1 4
+s_2 1 4
+s_3 1 4
+s_4 1 4
+s_5 1 4
+s_6 2 4
+s_7 2
+s_8 1 4
+s_8 2 4
+s_9 1 4
+s_10 2 4
+s_11 0 4
+s_11 1 4
+s_11 2 4
+s_11 3 4
+s_11 4 4
+s_11 5 4
+s_11 6 4
+s_11 7 4
+s_11 8 4
+s_11 9 4
+s_12 42 4
+s_1 1 4
+s_2 1 4
+s_3 1 4
+s_4 1 4
+s_5 1 4
+s_6 2 4
+s_7 2
+s_8 1 4
+s_8 2 4
+s_9 1 4
+s_10 2 4
+s_11 0 4
+s_11 1 4
+s_11 2 4
+s_11 3 4
+s_11 4 4
+s_11 5 4
+s_11 6 4
+s_11 7 4
+s_11 8 4
+s_11 9 4
+s_12 42 4
+RETURNED 42 86
diff --git a/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c
new file mode 100644
index 0000000000..739cd9702a
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c
@@ -0,0 +1,129 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int fun(char x){
+ int y = 10;
+ /*special_code_start:ON_SAVE_YIELD_STATE*/
+ if(0){
+ printf("y=%d\n", y);
+ y = 42;
+ }
+ /*special_code_end*/
+ /*special_code_start:ON_RETURN*/
+ if(0){
+ printf("I returned y=%d\n", y);
+ }
+ /*special_code_end*/
+ /*special_code_start:ON_DESTROY_STATE_OR_RETURN*/
+ if(0){
+ printf("I got destroyed or returned y=%d\n", y);
+ }
+ /*special_code_end*/
+ /*special_code_start:ON_RESTORE_YIELD_STATE*/
+ if(0){
+ x = 9;
+ }
+ /*special_code_end*/
+ if(0){
+ /*special_code_start:ON_SAVE_YIELD_STATE*/
+ if(0){
+ int z = 10;
+ printf("y=%d z=%d\n", y, z);
+ }
+ /*special_code_end*/
+ }
+ if(y != 10 || x != 1){
+ /*special_code_start:ON_RESTORE_YIELD_STATE*/
+ if(0){
+ printf("y=%d x=%d\n", y, x);
+ x = x*2;
+ printf("y=%d x=%d\n", y, x);
+ }
+ /*special_code_end*/
+ /*special_code_start:ON_RESTORE_YIELD_STATE*/
+ if(0){
+ printf("y=%d x=%d\n", y, x);
+ x = x/2;
+ printf("y=%d x=%d\n", y, x);
+ }
+ /*special_code_end*/
+ printf("ERROR BEFORE YIELD\n");
+ exit(1);
+ }
+ YCF_YIELD();
+ if(y != 42 || x != 9){
+ printf("ERROR AFTER YIELD\n");
+ exit(1);
+ }
+ printf("SUCCESS\n");
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 9){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c.out b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c.out
new file mode 100644
index 0000000000..639fd64b46
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state.c.out
@@ -0,0 +1,11 @@
+y=10
+y=42 z=10
+TRAPPED
+y=42 x=9
+y=42 x=18
+y=42 x=18
+y=42 x=9
+SUCCESS
+I returned y=42
+I got destroyed or returned y=42
+RETURNED 9
diff --git a/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c
new file mode 100644
index 0000000000..28e1512ece
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c
@@ -0,0 +1,131 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+#ifndef YCF_YIELDING_C_FUN_HELPERS
+
+#define ON_SAVE_YIELD_STATE
+#define ON_RESTORE_YIELD_STATE
+#define ON_DESTROY_STATE
+#define ON_RETURN
+#define ON_DESTROY_STATE_OR_RETURN
+#define YCF_SPECIAL_CODE_START(PARAM) \
+ /*special_code_start:PARAM*/ \
+ if(0){
+#define YCF_SPECIAL_CODE_END() \
+ } \
+ /*special_code_end*/
+
+#endif
+
+int fun(char x){
+ int y = 10;
+ YCF_SPECIAL_CODE_START(ON_SAVE_YIELD_STATE);
+ printf("y=%d\n", y);
+ y = 42;
+ YCF_SPECIAL_CODE_END();
+ YCF_SPECIAL_CODE_START(ON_RETURN);
+ printf("I returned y=%d\n", y);
+ YCF_SPECIAL_CODE_END();
+ YCF_SPECIAL_CODE_START(ON_DESTROY_STATE_OR_RETURN);
+ printf("I got destroyed or returned y=%d\n", y);
+ YCF_SPECIAL_CODE_END();
+ YCF_SPECIAL_CODE_START(ON_RESTORE_YIELD_STATE);
+ x = 9;
+ YCF_SPECIAL_CODE_END();
+ if(0){
+ YCF_SPECIAL_CODE_START(ON_SAVE_YIELD_STATE); {
+ int z = 10;
+ printf("y=%d z=%d\n", y, z);
+ } YCF_SPECIAL_CODE_END();
+ }
+ if(y != 10 || x != 1){
+ YCF_SPECIAL_CODE_START(ON_RESTORE_YIELD_STATE);
+ printf("y=%d x=%d\n", y, x);
+ x = x*2;
+ printf("y=%d x=%d\n", y, x);
+ YCF_SPECIAL_CODE_END();
+ YCF_SPECIAL_CODE_START(ON_RESTORE_YIELD_STATE);
+ printf("y=%d x=%d\n", y, x);
+ x = x/2;
+ printf("y=%d x=%d\n", y, x);
+ YCF_SPECIAL_CODE_END();
+ printf("ERROR BEFORE YIELD\n");
+ exit(1);
+ }
+ YCF_YIELD();
+ if(y != 42 || x != 9){
+ printf("ERROR AFTER YIELD\n");
+ exit(1);
+ }
+ printf("SUCCESS\n");
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 9){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c.out b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c.out
new file mode 100644
index 0000000000..639fd64b46
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/custom_code_save_restore_yield_state_alt_syntax.c.out
@@ -0,0 +1,11 @@
+y=10
+y=42 z=10
+TRAPPED
+y=42 x=9
+y=42 x=18
+y=42 x=18
+y=42 x=9
+SUCCESS
+I returned y=42
+I got destroyed or returned y=42
+RETURNED 9
diff --git a/erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c b/erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c
new file mode 100644
index 0000000000..76d500de24
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int fun(){
+ int array[1];
+ int* ptr;
+ array[0] = 1;
+ ptr = &array[0];
+ (void)ptr;
+ YCF_YIELD();
+ array[0] = 1;
+ return array[0];
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun();
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 1){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c.out b/erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c.out
new file mode 100644
index 0000000000..7c3cfb5078
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/debug_ptr_to_stack.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 1
diff --git a/erts/lib_src/yielding_c_fun/test/examples/declarations.c b/erts/lib_src/yielding_c_fun/test/examples/declarations.c
new file mode 100644
index 0000000000..718471c73f
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/declarations.c
@@ -0,0 +1,91 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+unsigned long fun(char x, char* y, char **z, unsigned long a, unsigned long* b, unsigned long** c){
+ unsigned int f = 3 + 3;
+ x = x + 1;
+ y = y + 1;
+ z = z + 1;
+ a = a + 1;
+ b = b + 1;
+ c = c + 1;
+ YCF_YIELD();
+ f = f - 6;
+ x = x + 1;
+ y = y + 1;
+ z = z + 1;
+ a = a + 1;
+ b = b + 1;
+ c = c + 1;
+ return (unsigned long)((long)(x + y) + ((z + a) + ((long)b + (long)c))) + f;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1,(void*)1,(void*)1,1,(void*)1,(void*)1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1,(void*)1,(void*)1,1,(void*)1,(void*)1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != fun(1,(void*)1,(void*)1,1,(void*)1,(void*)1)){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/declarations.c.out b/erts/lib_src/yielding_c_fun/test/examples/declarations.c.out
new file mode 100644
index 0000000000..d96b566da5
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/declarations.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 361
diff --git a/erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c b/erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c
new file mode 100644
index 0000000000..a8d2b02f02
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c
@@ -0,0 +1,83 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(){
+ int y = 0;
+ for(int x = 0; x < 10; x++){
+ y++;
+ for(int x = 0; x < 10; x++){
+ y++;
+ }
+ }
+ return y;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ nr_of_reductions = 1;
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 110){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c.out b/erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c.out
new file mode 100644
index 0000000000..88a9c3bbd1
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/declarations_in_for_loops.c.out
@@ -0,0 +1,211 @@
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+RETURNED 110
diff --git a/erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c b/erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c
new file mode 100644
index 0000000000..aedaf74fb0
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c
@@ -0,0 +1,92 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+void fun(int level){
+ void* my_mem = malloc(1000);
+ /*special_code_start:ON_DESTROY_STATE*/
+ if(0){
+ printf("FREE AT LEVEL %d\n", level);
+ free(my_mem);
+ }
+ /*special_code_end*/
+ /*special_code_start:ON_DESTROY_STATE_OR_RETURN*/
+ if(0){
+ printf("I got destroyed or returned %d\n", level);
+ }
+ /*special_code_end*/
+ printf("LEVEL %d\n", level);
+ if (level == 10) {
+ YCF_YIELD();
+ printf("SHOULD NOT BE PRINTED 1\n");
+ return;
+ }else {
+ fun(level + 1);
+ printf("SHOULD NOT BE PRINTED 2\n");
+ }
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+ do {
+ fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ fun_ycf_gen_destroy(wb);
+ printf("DESTROYED\n");
+ wb = NULL;
+ break;
+ }
+ } while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED\n");
+ return 0;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c.out b/erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c.out
new file mode 100644
index 0000000000..bdf7893e32
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/destroy_while_yielded.c.out
@@ -0,0 +1,33 @@
+LEVEL 1
+LEVEL 2
+LEVEL 3
+LEVEL 4
+LEVEL 5
+LEVEL 6
+LEVEL 7
+LEVEL 8
+LEVEL 9
+LEVEL 10
+TRAPPED
+I got destroyed or returned 1
+FREE AT LEVEL 1
+I got destroyed or returned 2
+FREE AT LEVEL 2
+I got destroyed or returned 3
+FREE AT LEVEL 3
+I got destroyed or returned 4
+FREE AT LEVEL 4
+I got destroyed or returned 5
+FREE AT LEVEL 5
+I got destroyed or returned 6
+FREE AT LEVEL 6
+I got destroyed or returned 7
+FREE AT LEVEL 7
+I got destroyed or returned 8
+FREE AT LEVEL 8
+I got destroyed or returned 9
+FREE AT LEVEL 9
+I got destroyed or returned 10
+FREE AT LEVEL 10
+DESTROYED
+RETURNED
diff --git a/erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c b/erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c
new file mode 100644
index 0000000000..a99fed5753
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(char x){
+ x = x + 1; /* x == 2*/
+ int y;
+ y = 1;
+ int z = 1;
+ YCF_YIELD();
+ x = x + y + z; /* x == 4*/
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 4){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c.out b/erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c.out
new file mode 100644
index 0000000000..cf0b7ff2c6
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/in_code_var_declaration.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 4
diff --git a/erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c b/erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c
new file mode 100644
index 0000000000..87024abe39
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c
@@ -0,0 +1,93 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(char x){
+ long y = x + 1; /* y == 2*/
+ YCF_YIELD();
+ {
+ int x = 10;
+ YCF_YIELD();
+ y = y + x; /* y == 12*/
+ YCF_YIELD();
+ {
+ long x = 30;
+ YCF_YIELD();
+ y = y + x; /* y == 42*/
+ YCF_YIELD();
+ }
+ YCF_YIELD();
+ y = y + x; /* y == 52*/
+ }
+ YCF_YIELD();
+ y = y + x; /* y == 53*/
+ YCF_YIELD();
+ return y;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 53){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c.out b/erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c.out
new file mode 100644
index 0000000000..bf653730af
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/multi_scope_yield.c.out
@@ -0,0 +1,9 @@
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+RETURNED 53
diff --git a/erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c b/erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c
new file mode 100644
index 0000000000..239de1a334
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c
@@ -0,0 +1,91 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+#define YCF_CONSUME_REDS(X)
+
+int sub_fun(int x){
+ int i;
+ int count = 0;
+ for(i = 0; i < 100; i++){
+ count = count + 2;
+ YCF_CONSUME_REDS(10);
+ }
+ return count + x;
+}
+
+int fun(int x){
+ int ret;
+ ret = sub_fun(x);
+ return ret;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ int nr_of_yields = 0;
+ long nr_of_reductions;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ nr_of_reductions = 101;
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED %ld\n", nr_of_reductions);
+ nr_of_yields++;
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("Number of yields %d\n", nr_of_yields);
+ printf("RETURNED %d\n", ret);
+ if(ret != 201){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c.out b/erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c.out
new file mode 100644
index 0000000000..32b93f33f6
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/nested_call_consume_reds.c.out
@@ -0,0 +1,11 @@
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+TRAPPED -9
+Number of yields 9
+RETURNED 201
diff --git a/erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c b/erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c
new file mode 100644
index 0000000000..b87685e23d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c
@@ -0,0 +1,104 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(){
+ int x;
+ int y;
+ int z;
+ int outer = 0;
+ int inner = 0;
+ for(x = 0; x < 2; x++){
+ for(y = 0; y < 2; y++){ /* 2 times */
+ for(z = 0; z < 2; z++){ /* 4 times */
+ YCF_YIELD(); /* 8 times */
+ outer++;
+ printf("outer %d: x=%d y=%d z=%d\n", outer, x, y, z);
+ {
+ int x;
+ int y;
+ int z;
+ for(x = 0; x < 2; x++){ /* 8 times */
+ for(y = 0; y < 2; y++){ /* 16 times */
+ for(z = 0; z < 2; z++){ /* 32 times */
+ YCF_YIELD(); /* 64 times */
+ inner++;
+ printf("inner %d: x=%d y=%d z=%d\n", inner, x, y, z);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return inner + outer;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ int nr_of_traps = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL);
+ if(wb != NULL){
+ nr_of_traps++;
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun();
+#endif
+ printf("NR OF TRAPS %d\n", nr_of_traps);
+ printf("RETURNED %d\n", ret);
+ if(ret != 72 || nr_of_traps != ret){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c.out b/erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c.out
new file mode 100644
index 0000000000..b48664e112
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/nested_loop_yield.c.out
@@ -0,0 +1,74 @@
+outer 1: x=0 y=0 z=0
+inner 1: x=0 y=0 z=0
+inner 2: x=0 y=0 z=1
+inner 3: x=0 y=1 z=0
+inner 4: x=0 y=1 z=1
+inner 5: x=1 y=0 z=0
+inner 6: x=1 y=0 z=1
+inner 7: x=1 y=1 z=0
+inner 8: x=1 y=1 z=1
+outer 2: x=0 y=0 z=1
+inner 9: x=0 y=0 z=0
+inner 10: x=0 y=0 z=1
+inner 11: x=0 y=1 z=0
+inner 12: x=0 y=1 z=1
+inner 13: x=1 y=0 z=0
+inner 14: x=1 y=0 z=1
+inner 15: x=1 y=1 z=0
+inner 16: x=1 y=1 z=1
+outer 3: x=0 y=1 z=0
+inner 17: x=0 y=0 z=0
+inner 18: x=0 y=0 z=1
+inner 19: x=0 y=1 z=0
+inner 20: x=0 y=1 z=1
+inner 21: x=1 y=0 z=0
+inner 22: x=1 y=0 z=1
+inner 23: x=1 y=1 z=0
+inner 24: x=1 y=1 z=1
+outer 4: x=0 y=1 z=1
+inner 25: x=0 y=0 z=0
+inner 26: x=0 y=0 z=1
+inner 27: x=0 y=1 z=0
+inner 28: x=0 y=1 z=1
+inner 29: x=1 y=0 z=0
+inner 30: x=1 y=0 z=1
+inner 31: x=1 y=1 z=0
+inner 32: x=1 y=1 z=1
+outer 5: x=1 y=0 z=0
+inner 33: x=0 y=0 z=0
+inner 34: x=0 y=0 z=1
+inner 35: x=0 y=1 z=0
+inner 36: x=0 y=1 z=1
+inner 37: x=1 y=0 z=0
+inner 38: x=1 y=0 z=1
+inner 39: x=1 y=1 z=0
+inner 40: x=1 y=1 z=1
+outer 6: x=1 y=0 z=1
+inner 41: x=0 y=0 z=0
+inner 42: x=0 y=0 z=1
+inner 43: x=0 y=1 z=0
+inner 44: x=0 y=1 z=1
+inner 45: x=1 y=0 z=0
+inner 46: x=1 y=0 z=1
+inner 47: x=1 y=1 z=0
+inner 48: x=1 y=1 z=1
+outer 7: x=1 y=1 z=0
+inner 49: x=0 y=0 z=0
+inner 50: x=0 y=0 z=1
+inner 51: x=0 y=1 z=0
+inner 52: x=0 y=1 z=1
+inner 53: x=1 y=0 z=0
+inner 54: x=1 y=0 z=1
+inner 55: x=1 y=1 z=0
+inner 56: x=1 y=1 z=1
+outer 8: x=1 y=1 z=1
+inner 57: x=0 y=0 z=0
+inner 58: x=0 y=0 z=1
+inner 59: x=0 y=1 z=0
+inner 60: x=0 y=1 z=1
+inner 61: x=1 y=0 z=0
+inner 62: x=1 y=0 z=1
+inner 63: x=1 y=1 z=0
+inner 64: x=1 y=1 z=1
+NR OF TRAPS 72
+RETURNED 72
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/.gitignore b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/.gitignore
new file mode 100644
index 0000000000..b5e8b97bac
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/.gitignore
@@ -0,0 +1,25 @@
+.rebar3
+_*
+.eunit
+*.o
+*.beam
+*.plt
+*.swp
+*.swo
+.erlang.cookie
+ebin
+log
+erl_crash.dump
+.rebar
+logs
+_build
+.idea
+*.iml
+rebar3.crashdump
+*~
+c_src/compile_commands.json
+c_src/compile_commands_old.json
+c_src/gen_yielding_sha_256.c
+c_src/gen_yielding_sha_256.h
+priv/
+rebar.lock
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/LICENSE b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/LICENSE
new file mode 100644
index 0000000000..66232832b9
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/LICENSE
@@ -0,0 +1,191 @@
+ 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
+
+ Copyright 2019, Kjell Winblad <kjellwinblad@gmail.com>.
+
+ 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.
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/Makefile b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/Makefile
new file mode 100644
index 0000000000..8bae3dc26a
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/Makefile
@@ -0,0 +1,34 @@
+
+ifeq ($(wildcard rebar3),rebar3)
+REBAR3 = $(CURDIR)/rebar3
+endif
+
+REBAR3 ?= $(shell test -e `which rebar3` 2>/dev/null && which rebar3 || echo "./rebar3")
+
+
+.PHONY: deps test build
+
+all: build test docs
+
+build: $(REBAR3)
+ @$(REBAR3) compile
+
+deps:
+ @$(REBAR3) get-deps
+
+clean:
+ @$(REBAR3) clean
+
+distclean: clean
+ @$(REBAR3) delete-deps
+
+docs:
+ @$(REBAR3) edoc
+
+
+test:
+ @$(REBAR3) ct
+
+
+release: test
+ @$(REBAR3) release
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/README.md b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/README.md
new file mode 100644
index 0000000000..ba579880b3
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/README.md
@@ -0,0 +1,23 @@
+sha256_nif
+=====
+
+An OTP library that illustrates how one can implement a yielding
+Erlang NIF API with the help of Yielding C Fun.
+
+Build
+-----
+
+ $ rebar3 compile
+
+or
+
+ $ make
+
+Test
+----
+
+ $ rebar3 ct
+
+or
+
+ $ make test \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/Makefile b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/Makefile
new file mode 100644
index 0000000000..dde621c591
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/Makefile
@@ -0,0 +1,83 @@
+# Based on c_src.mk from erlang.mk by Loic Hoguin <essen@ninenines.eu>
+
+CURDIR := $(shell pwd)
+BASEDIR := $(abspath $(CURDIR)/..)
+
+PROJECT ?= $(notdir $(BASEDIR))
+PROJECT := $(strip $(PROJECT))
+
+ERTS_INCLUDE_DIR ?= $(shell erl -noshell -s init stop -eval "io:format(\"~ts/erts-~ts/include/\", [code:root_dir(), erlang:system_info(version)]).")
+ERL_INTERFACE_INCLUDE_DIR ?= $(shell erl -noshell -s init stop -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, include)]).")
+ERL_INTERFACE_LIB_DIR ?= $(shell erl -noshell -s init stop -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, lib)]).")
+
+C_SRC_DIR = $(CURDIR)
+C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so
+
+# System type and C compiler/flags.
+
+UNAME_SYS := $(shell uname -s)
+ifeq ($(UNAME_SYS), Darwin)
+ CC ?= cc
+ CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall
+ CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
+ LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
+else ifeq ($(UNAME_SYS), FreeBSD)
+ CC ?= cc
+ CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
+ CXXFLAGS ?= -O3 -finline-functions -Wall
+else ifeq ($(UNAME_SYS), Linux)
+ CC ?= gcc
+ CFLAGS ?= -O3 -std=c99 -g -Wall -Wno-missing-prototypes -Wno-unused-function
+#-O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
+ CXXFLAGS ?= -O3 -finline-functions -Wall
+endif
+
+EXTRACFLAGSYCFCODE=-Wno-unused-function
+
+CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
+CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
+
+LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei
+LDFLAGS += -shared
+
+# Verbosity.
+
+c_verbose_0 = @echo " C " $(?F);
+c_verbose = $(c_verbose_$(V))
+
+cpp_verbose_0 = @echo " CPP " $(?F);
+cpp_verbose = $(cpp_verbose_$(V))
+
+link_verbose_0 = @echo " LD " $(@F);
+link_verbose = $(link_verbose_$(V))
+
+SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \) | grep -v "./sha-2/sha-256_orginal.c" | grep -v "./sha-2/sha-256.c" | grep -v "./gen_yielding_sha_256.c" | grep -v "./sha-2/test.c")
+OBJECTS = gen_yielding_sha_256.o $(addsuffix .o, $(basename $(SOURCES)))
+
+COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
+COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
+
+$(C_SRC_OUTPUT): $(OBJECTS)
+ @mkdir -p $(BASEDIR)/priv/
+ $(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT)
+
+gen_yielding_sha_256.c: sha-2/sha-256.c
+ ../../../../bin/yielding_c_fun -use_gc -yield -debug -f calc_sha_256 -f calc_chunk -header_file_name gen_yielding_sha_256.h "sha-2/sha-256.c" > gen_yielding_sha_256.c
+
+gen_yielding_sha_256.o: gen_yielding_sha_256.c
+ $(CC) $(CFLAGS) $(EXTRACFLAGSYCFCODE) $(CPPFLAGS) -c gen_yielding_sha_256.c
+
+%.o: %.c
+ $(COMPILE_C) $(OUTPUT_OPTION) $<
+
+%.o: %.cc
+ $(COMPILE_CPP) $(OUTPUT_OPTION) $<
+
+%.o: %.C
+ $(COMPILE_CPP) $(OUTPUT_OPTION) $<
+
+%.o: %.cpp
+ $(COMPILE_CPP) $(OUTPUT_OPTION) $<
+
+clean:
+ @rm -f gen_yielding_sha_256.c gen_yielding_sha_256.h $(C_SRC_OUTPUT) $(OBJECTS)
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.gitignore b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.gitignore
new file mode 100644
index 0000000000..6587b2f0fc
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.gitignore
@@ -0,0 +1,3 @@
+*~
+*.o
+test
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.travis.yml b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.travis.yml
new file mode 100644
index 0000000000..ffec9e605d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/.travis.yml
@@ -0,0 +1,2 @@
+language: c
+script: make
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/GIT_VERSION b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/GIT_VERSION
new file mode 100644
index 0000000000..28e48c7b6f
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/GIT_VERSION
@@ -0,0 +1,265 @@
+origin https://github.com/amosnier/sha-2.git (fetch)
+origin https://github.com/amosnier/sha-2.git (push)
+commit ff76937294694ec347819d81a1f580187fb34246
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 23:24:58 2018 +0200
+
+ Update README.md
+
+commit ad933ac6959f8507c349b2c60f02b9336f5ade10
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 23:24:18 2018 +0200
+
+ Update README.md
+
+commit 92e7db3c188a2c7a971564b2fdac2d38c7b329e3
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 23:22:45 2018 +0200
+
+ Update README.md
+
+commit 6d500e221aa29f9a3701833f1f31ccabba9c58f7
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 23:22:00 2018 +0200
+
+ Update README.md
+
+ Added section about reference implementation.
+
+commit 924fba5c17abac8e6b90eef99b509f2cf759d223
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 22:02:09 2018 +0200
+
+ Replaced some for loops by memset
+
+commit 9583456b329abe8bfbaaedd0aca76fc3eb31e0b8
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 19:16:41 2018 +0200
+
+ Implemented workaround for ld issue with large BSS
+
+ The large arrays are now allocated on heap instead of in BSS. This
+ actually feels like a pretty stupid linker limitation, and the
+ workaround leads to code that is less readable. But it only impacts
+ the test program.
+
+ The issue was reported with GCC 7.3.0 and compiling for 64-bit arch on
+ MSYS2's MinGW compiler. GCC 7.3.0 for 64-bit on Linux (my own machine
+ and Travis) seems perfectly OK with a large BSS segment (around 3 GB
+ is what the test program uses for test data).
+
+ Reported issue:
+
+ $ make
+ cc -Wall -Wextra -Wpedantic -c -o test.o test.c
+ cc -Wall -Wextra -Wpedantic -c -o sha-256.o sha-256.c
+ cc test.o sha-256.o -o test
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o: in function `__tmainCRTStartup':
+ C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:251:(.text+0x1cd): relocation truncated to fit: R_X86_64_PC32 against symbol `__imp_Sleep' defined in .idata$5 section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libkernel32.a(dkhchs01360.o)
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:278:(.text+0x255): relocation truncated to fit: R_X86_64_PC32 against symbol `__imp_SetUnhandledExceptionFilter' defined in .idata$5 section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libkernel32.a(dkhchs01346.o)
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:286:(.text+0x283): relocation truncated to fit: R_X86_64_PC32 against symbol `__mingw_winmain_hInstance' defined in COMMON section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:312:(.text+0x2f3): relocation truncated to fit: R_X86_64_PC32 against symbol `__mingw_winmain_lpCmdLine' defined in COMMON section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:238:(.text+0x475): relocation truncated to fit: R_X86_64_PC32 against symbol `__imp_GetStartupInfoA' defined in .idata$5 section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libkernel32.a(dkhchs00721.o)
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-gccmain.o): in function `__main':
+ C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:74:(.text+0xb2): relocation truncated to fit: R_X86_64_PC32 against `.bss'
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:76:(.text+0xc2): relocation truncated to fit: R_X86_64_PC32 against `.bss'
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-charmax.o): in function `my_lconv_init':
+ C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/charmax.c:19:(.text+0x3): relocation truncated to fit: R_X86_64_PC32 against symbol `__imp___lconv_init' defined in .idata$5 section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmsvcrt.a(dkxcbs00090.o)
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-gs_support.o): in function `__security_init_cookie':
+ C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gs_support.c:62:(.text+0x47): relocation truncated to fit: R_X86_64_PC32 against symbol `__imp_GetSystemTimeAsFileTime' defined in .idata$5 section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libkernel32.a(dkhchs00746.o)
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gs_support.c:70:(.text+0x52): relocation truncated to fit: R_X86_64_PC32 against symbol `__imp_GetCurrentProcessId' defined in .idata$5 section in C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libkernel32.a(dkhchs00536.o)
+ C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gs_support.c:71:(.text+0x5b): additional relocation overflows omitted from the output
+ collect2.exe: error: ld returned 1 exit status
+ make: *** [<builtin>: test] Error 1```
+
+commit 23b53726f3c5c283112110468ff1c9b4981260e9
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Sat Jul 28 16:53:38 2018 +0200
+
+ Added explicit cast to correct printf() related bug
+
+commit f03474231fc0e86c66cbe2a74a9d9f6589dd96f9
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 23:41:17 2017 +0100
+
+ Activated testing of long messages
+
+commit a222d72880c8b9b2b22155d34adfc72e49e511c5
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 23:11:41 2017 +0100
+
+ Minor README change
+
+commit 98a0bf165c558dde77211ff09cc6b0e1c30badc7
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 23:08:48 2017 +0100
+
+ Minor README change
+
+commit 688b14926c42b61dbfb61f3046594afb058dad31
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 23:07:54 2017 +0100
+
+ Added Travis comment
+
+commit d6b49c65bdaa54120d20401e15368cb462f8a122
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 23:00:29 2017 +0100
+
+ Fixed minor warnings
+
+commit a6c25e2cdf96eeb522199c67e895f0791e297fc9
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 22:53:19 2017 +0100
+
+ Included test in make
+
+commit 538cfe97fa7ad217875196b4e5ce8ddfc1d88f7a
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 22:34:57 2017 +0100
+
+ Travis icon again
+
+commit 903e46163b6d6258b3d5e5b5de60f134749e2f10
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 22:33:50 2017 +0100
+
+ Work on Travis icon
+
+commit d87b78db4bfa08ddceecb3837943b7886d2f4f88
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 22:31:02 2017 +0100
+
+ Added Travis link
+
+commit 19d1e8a568af53c9788ed6fc2ecc9fcb34b17037
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 22:24:03 2017 +0100
+
+ Started adding Travis
+
+commit 8f83e8dedf169858efd366fe2237ec31e8f3c3ec
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:54:31 2017 +0100
+
+ Minor README change
+
+commit 369c47af630d6f3dc6cf817e402ef070a588d5a9
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:52:36 2017 +0100
+
+ Minor README change
+
+commit b177afbe06965bec656f0cf437f449f747f6575e
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:45:25 2017 +0100
+
+ Improved formatting
+
+commit 8fd2b04fed6b5bcaad04e66cb2a3158b61b5ce1e
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:44:04 2017 +0100
+
+ Improved formatting
+
+commit 96988951cc63d2305ce7612ebad5456bfca444c9
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:40:56 2017 +0100
+
+ Improved formatting
+
+commit 37500f461fbc5e0553ec4ea2f5ec449126ac63c0
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:37:39 2017 +0100
+
+ Formatting improvement
+
+commit 6f35ae7007f0f9b54e5798d6a63ffbd1f9f9d59c
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 21:34:20 2017 +0100
+
+ Added extensive testing
+
+commit cba84edcb52079236c0c32c591a74ec89155fc62
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Fri Dec 15 19:37:47 2017 +0100
+
+ Made changes according to review comments from StackExchange CODE REVIEW
+
+commit d7214be72713f020f2dffbac01a13442921cabce
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Thu Dec 14 22:45:59 2017 +0100
+
+ Added comment about code review
+
+commit da12ae4e94725e87052da5c0191103de0d817ed5
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Thu Dec 14 20:11:09 2017 +0100
+
+ Tests at compile time instead of runtime
+
+commit b21a7b552969cbf8a2c702f617e15750fe1b2b2b
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 12:03:01 2017 +0100
+
+ Added comment
+
+commit 85e93b4a79b7ed9f20077021b489c3a1cbd6a251
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 12:01:19 2017 +0100
+
+ Typo
+
+commit ccc3d23b29eeb4c1ace83ae93f415d7a3d57ed45
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 12:00:03 2017 +0100
+
+ Added comment.
+
+commit 047f309134372f826027ac383667c18ce7a2062f
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 11:29:58 2017 +0100
+
+ Added comment about testing
+
+commit 5833df68d9de2f1cb1cc3db57608eba25559a9bf
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 11:27:39 2017 +0100
+
+ Removed temporary code
+
+commit f3f5e1b4532a40e37fc9b880f348a525c4a4165a
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 11:23:44 2017 +0100
+
+ Added some notes
+
+commit 097f4b536db64d29fbc5f54d052ba795db68f00f
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 11:18:17 2017 +0100
+
+ Typo
+
+commit 73684be1627a05d4dbd585d2cc926e6b91275dc4
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 11:14:32 2017 +0100
+
+ Corrected typo
+
+commit 489f5e66b63ed90ed3de197237e608e101253efb
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 11:12:47 2017 +0100
+
+ Completed the implementation, including testing, and fixed bugs
+
+commit d676207600a94c5d94ef6f6188cc1c907f06b42a
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Wed Dec 13 00:52:28 2017 +0100
+
+ Started a SHA-256 implementation. Buggy so far.
+
+commit 3433d4ef5ccb136f0b889610cac3f752776ea525
+Author: Alain Mosnier <alain@wanamoon.net>
+Date: Tue Dec 12 20:48:09 2017 +0100
+
+ Initial commit
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/LICENSE b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/LICENSE
new file mode 100644
index 0000000000..cf1ab25da0
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <http://unlicense.org>
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/Makefile b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/Makefile
new file mode 100644
index 0000000000..53bcbab93e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/Makefile
@@ -0,0 +1,11 @@
+CFLAGS = -Wall -Wextra -Wpedantic
+
+.PHONY: all
+all: test
+ ./test
+
+test: test.o sha-256.o
+
+.PHONY: clean
+clean:
+ rm test *.o
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md
new file mode 100644
index 0000000000..167a69d08c
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md
@@ -0,0 +1,97 @@
+# sha-2 [![Build Status](https://travis-ci.org/amosnier/sha-2.svg?branch=master)](https://travis-ci.org/amosnier/sha-2)
+
+## Contents
+
+SHA-2 algorithm implementations.
+
+At the moment, only SHA-256 is implemented.
+
+## Design criteria
+
+- Easy to test, include in any project, compile and link.
+
+- ANSI C with as little specific C99 as possible (e.g. extended
+ integer types are used, but not bool).
+
+- Portable. Makes no assumptions on the target system's endianess or
+ word size.
+
+- The SHA-256 implementation is a straightforward implementation of
+ the algorithm specified on
+ [Wikipedia](https://en.wikipedia.org/wiki/SHA-2).
+
+## Notes
+
+The Makefile is as minimal as possible. No effort was put into making
+it general. Its purpose is mainly to ease testing for the developer's
+host machine. The actual implementation is however extremely easy to
+include in any project, may it use GNU make or any other build tool.
+
+## Code review
+
+This code has been reviewed at [Stack Exchange CODE
+REVIEW](https://codereview.stackexchange.com/questions/182812/self-contained-sha-256-implementation-in-c),
+and the implementation has been improved accordingly.
+
+## Testing
+
+Testing is continuously performed on Travis CI (see above).
+
+Apart from that, the implementation has been successfully tested on an x86-64 machine
+under Linux as well as on a 16-bit DSP. On the x86-64 machine, all the
+available NIST test vectors where successfully tested ([SHA-256
+examples](https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA256.pdf)
+and [SHA-2 Additional
+examples](https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA2_Additional.pdf),
+plus a few others).
+
+In particular:
+
+```
+Input Message: "abc"
+Message Digest is BA7816BF 8F01CFEA 414140DE 5DAE2223 B00361A3 96177A9C B410FF61 F20015AD
+```
+
+```
+Input Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+Message Digest is 248D6A61 D20638B8 E5C02693 0C3E6039 A33CE459 64FF2167 F6ECEDD4 19DB06C1
+```
+
+```
+SHA-256 Test Data
+#1) 1 byte 0xbd
+68325720 aabd7c82 f30f554b 313d0570 c95accbb 7dc4b5aa e11204c0 8ffe732b
+#2) 4 bytes 0xc98c8e55
+7abc22c0 ae5af26c e93dbb94 433a0e0b 2e119d01 4f8e7f65 bd56c61c cccd9504
+#3) 55 bytes of zeros
+02779466 cdec1638 11d07881 5c633f21 90141308 1449002f 24aa3e80 f0b88ef7
+#4) 56 bytes of zeros
+d4817aa5 497628e7 c77e6b60 6107042b bba31308 88c5f47a 375e6179 be789fbb
+#5) 57 bytes of zeros
+65a16cb7 861335d5 ace3c607 18b5052e 44660726 da4cd13b b745381b 235a1785
+#6) 64 bytes of zeros
+f5a5fd42 d16a2030 2798ef6e d309979b 43003d23 20d9f0e8 ea9831a9 2759fb4b
+#7) 1000 bytes of zeros
+541b3e9d aa09b20b f85fa273 e5cbd3e8 0185aa4e c298e765 db87742b 70138a53
+#8) 1000 bytes of 0x41 ‘A’
+c2e68682 3489ced2 017f6059 b8b23931 8b6364f6 dcd835d0 a519105a 1eadd6e4
+#9) 1005 bytes of 0x55 ‘U’
+f4d62dde c0f3dd90 ea1380fa 16a5ff8d c4c54b21 740650f2 4afc4120 903552b0
+#10) 1000000 bytes of zeros
+d29751f2 649b32ff 572b5e0a 9f541ea6 60a50f94 ff0beedf b0b692b9 24cc8025
+#11) 0x20000000 (536870912) bytes of 0x5a ‘Z’
+15a1868c 12cc5395 1e182344 277447cd 0979536b adcc512a d24c67e9 b2d4f3dd
+#12) 0x41000000 (1090519040) bytes of zeros
+461c19a9 3bd4344f 9215f5ec 64357090 342bc66b 15a14831 7d276e31 cbc20b53
+#13) 0x6000003e (1610612798) bytes of 0x42 ‘B’
+c23ce8a7 895f4b21 ec0daf37 920ac0a2 62a22004 5a03eb2d fed48ef9 b05aabea
+```
+
+## License
+
+This repository is made available in the public domain. See [LICENSE
+FILE](LICENSE).
+
+## Reference implementation
+
+I had missed that when I made this implementation but [RFC 6234, chapter 8](https://tools.ietf.org/html/rfc6234#section-8) actually includes a reference implementation in C that is (at least in ambition) broader in scope than this one. I have however neither compiled nor tested it.
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c
new file mode 100644
index 0000000000..4338531d7e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c
@@ -0,0 +1,224 @@
+#include <stdint.h>
+#include <string.h>
+
+#ifdef YCF_YIELD_CODE_GENERATED
+#include "sha-2/sha-256.h"
+#else
+#include "sha-256.h"
+#endif
+
+#define CHUNK_SIZE 64
+#define TOTAL_LEN_LEN 8
+
+/*
+ * ABOUT bool: this file does not use bool in order to be as pre-C99 compatible as possible.
+ */
+
+/*
+ * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here.
+ * When useful for clarification, portions of the pseudo-code are reproduced here too.
+ */
+
+/*
+ * Initialize array of round constants:
+ * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
+ */
+static const uint32_t k[] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+struct buffer_state {
+ const uint8_t * p;
+ size_t len;
+ size_t total_len;
+ int single_one_delivered; /* bool */
+ int total_len_delivered; /* bool */
+};
+
+static inline uint32_t right_rot(uint32_t value, unsigned int count)
+{
+ /*
+ * Defined behaviour in standard C for all count where 0 < count < 32,
+ * which is what we need here.
+ */
+ return value >> count | value << (32 - count);
+}
+
+static void init_buf_state(struct buffer_state * state, const void * input, size_t len)
+{
+ state->p = input;
+ state->len = len;
+ state->total_len = len;
+ state->single_one_delivered = 0;
+ state->total_len_delivered = 0;
+}
+
+/* Return value: bool */
+static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state)
+{
+ size_t space_in_chunk;
+
+ if (state->total_len_delivered) {
+ return 0;
+ }
+
+ if (state->len >= CHUNK_SIZE) {
+ memcpy(chunk, state->p, CHUNK_SIZE);
+ state->p += CHUNK_SIZE;
+ state->len -= CHUNK_SIZE;
+ return 1;
+ }
+
+ memcpy(chunk, state->p, state->len);
+ chunk += state->len;
+ space_in_chunk = CHUNK_SIZE - state->len;
+ state->p += state->len;
+ state->len = 0;
+
+ /* If we are here, space_in_chunk is one at minimum. */
+ if (!state->single_one_delivered) {
+ *chunk++ = 0x80;
+ space_in_chunk -= 1;
+ state->single_one_delivered = 1;
+ }
+
+ /*
+ * Now:
+ * - either there is enough space left for the total length, and we can conclude,
+ * - or there is too little space left, and we have to pad the rest of this chunk with zeroes.
+ * In the latter case, we will conclude at the next invokation of this function.
+ */
+ if (space_in_chunk >= TOTAL_LEN_LEN) {
+ const size_t left = space_in_chunk - TOTAL_LEN_LEN;
+ size_t len = state->total_len;
+ int i;
+ memset(chunk, 0x00, left);
+ chunk += left;
+
+ /* Storing of len * 8 as a big endian 64-bit without overflow. */
+ chunk[7] = (uint8_t) (len << 3);
+ len >>= 5;
+ for (i = 6; i >= 0; i--) {
+ chunk[i] = (uint8_t) len;
+ len >>= 8;
+ }
+ state->total_len_delivered = 1;
+ } else {
+ memset(chunk, 0x00, space_in_chunk);
+ }
+
+ return 1;
+}
+
+#define YCF_STACK_ALLOC(X) malloc(X)
+
+
+/*
+ * Limitations:
+ * - Since input is a pointer in RAM, the data to hash should be in RAM, which could be a problem
+ * for large data sizes.
+ * - SHA algorithms theoretically operate on bit strings. However, this implementation has no support
+ * for bit string lengths that are not multiples of eight, and it really operates on arrays of bytes.
+ * In particular, the len parameter is a number of bytes.
+ */
+void calc_sha_256(uint8_t hash[32], const void * input, size_t len)
+{
+ /*
+ * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32.
+ * Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 = i = 63
+ * Note 3: The compression function uses 8 working variables, a through h
+ * Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
+ * and when parsing message block data from bytes to words, for example,
+ * the first word of the input message "abc" after padding is 0x61626380
+ */
+
+ /*
+ * Initialize hash values:
+ * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
+ */
+ uint32_t h[8];
+ int i;
+ int j;
+
+ /* 512-bit chunks is what we will operate on. */
+ uint8_t* chunk = YCF_STACK_ALLOC(64);
+ struct buffer_state state;
+ h[0] = 0x6a09e667;
+ h[1] = 0xbb67ae85;
+ h[2] = 0x3c6ef372;
+ h[3] = 0xa54ff53a;
+ h[4] = 0x510e527f;
+ h[5] = 0x9b05688c;
+ h[6] = 0x1f83d9ab;
+ h[7] = 0x5be0cd19;
+ init_buf_state(&state, input, len);
+
+ while (calc_chunk(chunk, &state)) {
+ uint32_t ah[8];
+
+ /*
+ * create a 64-entry message schedule array w[0..63] of 32-bit words
+ * (The initial values in w[0..63] don't matter, so many implementations zero them here)
+ * copy chunk into first 16 words w[0..15] of the message schedule array
+ */
+ uint32_t w[64];
+ const uint8_t *p = chunk;
+
+ memset(w, 0x00, sizeof w);
+ for (i = 0; i < 16; i++) {
+ w[i] = (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 |
+ (uint32_t) p[2] << 8 | (uint32_t) p[3];
+ p += 4;
+ }
+
+ /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */
+ for (i = 16; i < 64; i++) {
+ const uint32_t s0 = right_rot(w[i - 15], 7) ^ right_rot(w[i - 15], 18) ^ (w[i - 15] >> 3);
+ const uint32_t s1 = right_rot(w[i - 2], 17) ^ right_rot(w[i - 2], 19) ^ (w[i - 2] >> 10);
+ w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+ }
+
+ /* Initialize working variables to current hash value: */
+ for (i = 0; i < 8; i++)
+ ah[i] = h[i];
+
+ /* Compression function main loop: */
+ for (i = 0; i < 64; i++) {
+ const uint32_t s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25);
+ const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
+ const uint32_t temp1 = ah[7] + s1 + ch + k[i] + w[i];
+ const uint32_t s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22);
+ const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
+ const uint32_t temp2 = s0 + maj;
+
+ ah[7] = ah[6];
+ ah[6] = ah[5];
+ ah[5] = ah[4];
+ ah[4] = ah[3] + temp1;
+ ah[3] = ah[2];
+ ah[2] = ah[1];
+ ah[1] = ah[0];
+ ah[0] = temp1 + temp2;
+ }
+
+ /* Add the compressed chunk to the current hash value: */
+ for (i = 0; i < 8; i++)
+ h[i] += ah[i];
+ }
+
+ /* Produce the final hash value (big-endian): */
+ for (i = 0, j = 0; i < 8; i++)
+ {
+ hash[j++] = (uint8_t) (h[i] >> 24);
+ hash[j++] = (uint8_t) (h[i] >> 16);
+ hash[j++] = (uint8_t) (h[i] >> 8);
+ hash[j++] = (uint8_t) h[i];
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.h b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.h
new file mode 100644
index 0000000000..2cce60bb7b
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.h
@@ -0,0 +1,4 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+void calc_sha_256(uint8_t hash[], const void *input, size_t len);
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c
new file mode 100644
index 0000000000..53d6ff2e2a
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c
@@ -0,0 +1,210 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "sha-256.h"
+
+#define CHUNK_SIZE 64
+#define TOTAL_LEN_LEN 8
+
+/*
+ * ABOUT bool: this file does not use bool in order to be as pre-C99 compatible as possible.
+ */
+
+/*
+ * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here.
+ * When useful for clarification, portions of the pseudo-code are reproduced here too.
+ */
+
+/*
+ * Initialize array of round constants:
+ * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
+ */
+static const uint32_t k[] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+struct buffer_state {
+ const uint8_t * p;
+ size_t len;
+ size_t total_len;
+ int single_one_delivered; /* bool */
+ int total_len_delivered; /* bool */
+};
+
+static inline uint32_t right_rot(uint32_t value, unsigned int count)
+{
+ /*
+ * Defined behaviour in standard C for all count where 0 < count < 32,
+ * which is what we need here.
+ */
+ return value >> count | value << (32 - count);
+}
+
+static void init_buf_state(struct buffer_state * state, const void * input, size_t len)
+{
+ state->p = input;
+ state->len = len;
+ state->total_len = len;
+ state->single_one_delivered = 0;
+ state->total_len_delivered = 0;
+}
+
+/* Return value: bool */
+static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state)
+{
+ size_t space_in_chunk;
+
+ if (state->total_len_delivered) {
+ return 0;
+ }
+
+ if (state->len >= CHUNK_SIZE) {
+ memcpy(chunk, state->p, CHUNK_SIZE);
+ state->p += CHUNK_SIZE;
+ state->len -= CHUNK_SIZE;
+ return 1;
+ }
+
+ memcpy(chunk, state->p, state->len);
+ chunk += state->len;
+ space_in_chunk = CHUNK_SIZE - state->len;
+ state->p += state->len;
+ state->len = 0;
+
+ /* If we are here, space_in_chunk is one at minimum. */
+ if (!state->single_one_delivered) {
+ *chunk++ = 0x80;
+ space_in_chunk -= 1;
+ state->single_one_delivered = 1;
+ }
+
+ /*
+ * Now:
+ * - either there is enough space left for the total length, and we can conclude,
+ * - or there is too little space left, and we have to pad the rest of this chunk with zeroes.
+ * In the latter case, we will conclude at the next invokation of this function.
+ */
+ if (space_in_chunk >= TOTAL_LEN_LEN) {
+ const size_t left = space_in_chunk - TOTAL_LEN_LEN;
+ size_t len = state->total_len;
+ int i;
+ memset(chunk, 0x00, left);
+ chunk += left;
+
+ /* Storing of len * 8 as a big endian 64-bit without overflow. */
+ chunk[7] = (uint8_t) (len << 3);
+ len >>= 5;
+ for (i = 6; i >= 0; i--) {
+ chunk[i] = (uint8_t) len;
+ len >>= 8;
+ }
+ state->total_len_delivered = 1;
+ } else {
+ memset(chunk, 0x00, space_in_chunk);
+ }
+
+ return 1;
+}
+
+/*
+ * Limitations:
+ * - Since input is a pointer in RAM, the data to hash should be in RAM, which could be a problem
+ * for large data sizes.
+ * - SHA algorithms theoretically operate on bit strings. However, this implementation has no support
+ * for bit string lengths that are not multiples of eight, and it really operates on arrays of bytes.
+ * In particular, the len parameter is a number of bytes.
+ */
+void calc_sha_256(uint8_t hash[32], const void * input, size_t len)
+{
+ /*
+ * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32.
+ * Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 = i = 63
+ * Note 3: The compression function uses 8 working variables, a through h
+ * Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
+ * and when parsing message block data from bytes to words, for example,
+ * the first word of the input message "abc" after padding is 0x61626380
+ */
+
+ /*
+ * Initialize hash values:
+ * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
+ */
+ uint32_t h[] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
+ int i, j;
+
+ /* 512-bit chunks is what we will operate on. */
+ uint8_t chunk[64];
+
+ struct buffer_state state;
+
+ init_buf_state(&state, input, len);
+
+ while (calc_chunk(chunk, &state)) {
+ uint32_t ah[8];
+
+ /*
+ * create a 64-entry message schedule array w[0..63] of 32-bit words
+ * (The initial values in w[0..63] don't matter, so many implementations zero them here)
+ * copy chunk into first 16 words w[0..15] of the message schedule array
+ */
+ uint32_t w[64];
+ const uint8_t *p = chunk;
+
+ memset(w, 0x00, sizeof w);
+ for (i = 0; i < 16; i++) {
+ w[i] = (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 |
+ (uint32_t) p[2] << 8 | (uint32_t) p[3];
+ p += 4;
+ }
+
+ /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */
+ for (i = 16; i < 64; i++) {
+ const uint32_t s0 = right_rot(w[i - 15], 7) ^ right_rot(w[i - 15], 18) ^ (w[i - 15] >> 3);
+ const uint32_t s1 = right_rot(w[i - 2], 17) ^ right_rot(w[i - 2], 19) ^ (w[i - 2] >> 10);
+ w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+ }
+
+ /* Initialize working variables to current hash value: */
+ for (i = 0; i < 8; i++)
+ ah[i] = h[i];
+
+ /* Compression function main loop: */
+ for (i = 0; i < 64; i++) {
+ const uint32_t s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25);
+ const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
+ const uint32_t temp1 = ah[7] + s1 + ch + k[i] + w[i];
+ const uint32_t s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22);
+ const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
+ const uint32_t temp2 = s0 + maj;
+
+ ah[7] = ah[6];
+ ah[6] = ah[5];
+ ah[5] = ah[4];
+ ah[4] = ah[3] + temp1;
+ ah[3] = ah[2];
+ ah[2] = ah[1];
+ ah[1] = ah[0];
+ ah[0] = temp1 + temp2;
+ }
+
+ /* Add the compressed chunk to the current hash value: */
+ for (i = 0; i < 8; i++)
+ h[i] += ah[i];
+ }
+
+ /* Produce the final hash value (big-endian): */
+ for (i = 0, j = 0; i < 8; i++)
+ {
+ hash[j++] = (uint8_t) (h[i] >> 24);
+ hash[j++] = (uint8_t) (h[i] >> 16);
+ hash[j++] = (uint8_t) (h[i] >> 8);
+ hash[j++] = (uint8_t) h[i];
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/test.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/test.c
new file mode 100644
index 0000000000..5b5031c374
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/test.c
@@ -0,0 +1,238 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "sha-256.h"
+
+struct string_vector {
+ const char *input;
+ const char *output;
+};
+
+static const struct string_vector STRING_VECTORS[] = {
+ {
+ "",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ {
+ "abc",
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+ },
+ {
+ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+ "a8ae6e6ee929abea3afcfc5258c8ccd6f85273e0d4626d26c7279f3250f77c8e"
+ },
+ {
+ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde",
+ "057ee79ece0b9a849552ab8d3c335fe9a5f1c46ef5f1d9b190c295728628299c"
+ },
+ {
+ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0",
+ "2a6ad82f3620d3ebe9d678c812ae12312699d673240d5be8fac0910a70000d93"
+ },
+ {
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
+ },
+ {
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"
+ "ijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
+ }
+};
+
+#define LARGE_MESSAGES 1
+
+static uint8_t data1[] = { 0xbd };
+static uint8_t data2[] = { 0xc9, 0x8c, 0x8e, 0x55 };
+static uint8_t data7[1000];
+static uint8_t data8[1000];
+static uint8_t data9[1005];
+#if LARGE_MESSAGES
+#define SIZEOF_DATA11 536870912
+#define SIZEOF_DATA12 1090519040
+#define SIZEOF_DATA13 1610612798
+static uint8_t * data11;
+static uint8_t * data12;
+static uint8_t * data13;
+#endif
+
+struct vector {
+ const uint8_t *input;
+ size_t input_len;
+ const char *output;
+};
+
+static struct vector vectors[] = {
+ {
+ data1,
+ sizeof data1,
+ "68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b"
+ },
+ {
+ data2,
+ sizeof data2,
+ "7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504"
+ },
+ {
+ data7,
+ 55,
+ "02779466cdec163811d078815c633f21901413081449002f24aa3e80f0b88ef7"
+ },
+ {
+ data7,
+ 56,
+ "d4817aa5497628e7c77e6b606107042bbba3130888c5f47a375e6179be789fbb"
+ },
+ {
+ data7,
+ 57,
+ "65a16cb7861335d5ace3c60718b5052e44660726da4cd13bb745381b235a1785"
+ },
+ {
+ data7,
+ 64,
+ "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b"
+ },
+ {
+ data7,
+ sizeof data7,
+ "541b3e9daa09b20bf85fa273e5cbd3e80185aa4ec298e765db87742b70138a53"
+ },
+ {
+ data8,
+ sizeof data8,
+ "c2e686823489ced2017f6059b8b239318b6364f6dcd835d0a519105a1eadd6e4"
+ },
+ {
+ data9,
+ sizeof data9,
+ "f4d62ddec0f3dd90ea1380fa16a5ff8dc4c54b21740650f24afc4120903552b0"
+ }
+#if LARGE_MESSAGES
+ ,
+ {
+ NULL,
+ 1000000,
+ "d29751f2649b32ff572b5e0a9f541ea660a50f94ff0beedfb0b692b924cc8025"
+ },
+ {
+ NULL,
+ SIZEOF_DATA11,
+ "15a1868c12cc53951e182344277447cd0979536badcc512ad24c67e9b2d4f3dd"
+ },
+ {
+ NULL,
+ SIZEOF_DATA12,
+ "461c19a93bd4344f9215f5ec64357090342bc66b15a148317d276e31cbc20b53"
+ },
+ {
+ NULL,
+ SIZEOF_DATA13,
+ "c23ce8a7895f4b21ec0daf37920ac0a262a220045a03eb2dfed48ef9b05aabea"
+ }
+#endif
+};
+
+static void construct_binary_messages(void)
+{
+ memset(data7, 0x00, sizeof data7);
+ memset(data8, 0x41, sizeof data8);
+ memset(data9, 0x55, sizeof data9);
+#if LARGE_MESSAGES
+ /*
+ * Heap allocation as a workaround for some linkers not liking
+ * large BSS segments.
+ */
+ data11 = malloc(SIZEOF_DATA11);
+ data12 = malloc(SIZEOF_DATA12);
+ data13 = malloc(SIZEOF_DATA13);
+ memset(data11, 0x5a, SIZEOF_DATA11);
+ memset(data12, 0x00, SIZEOF_DATA12);
+ memset(data13, 0x42, SIZEOF_DATA13);
+ vectors[9].input = data12;
+ vectors[10].input = data11;
+ vectors[11].input = data12;
+ vectors[12].input = data13;
+#endif
+}
+
+static void destruct_binary_messages(void)
+{
+#if LARGE_MESSAGES
+ free(data11);
+ free(data12);
+ free(data13);
+#endif
+}
+
+static void hash_to_string(char string[65], const uint8_t hash[32])
+{
+ size_t i;
+ for (i = 0; i < 32; i++) {
+ string += sprintf(string, "%02x", hash[i]);
+ }
+}
+
+static int string_test(const char input[], const char output[])
+{
+ uint8_t hash[32];
+ char hash_string[65];
+ calc_sha_256(hash, input, strlen(input));
+ hash_to_string(hash_string, hash);
+ printf("input: %s\n", input);
+ printf("hash : %s\n", hash_string);
+ if (strcmp(output, hash_string)) {
+ printf("FAILURE!\n\n");
+ return 1;
+ } else {
+ printf("SUCCESS!\n\n");
+ return 0;
+ }
+}
+
+/*
+ * Limitation:
+ * - The variable input_len will be truncated to its LONG_BIT least
+ * significant bits in the print output. This will never be a problem
+ * for values that in practice are less than 2^32 - 1. Rationale: ANSI
+ * C-compatibility and keeping it simple.
+ */
+static int test(const uint8_t * input, size_t input_len, const char output[])
+{
+ uint8_t hash[32];
+ char hash_string[65];
+ calc_sha_256(hash, input, input_len);
+ hash_to_string(hash_string, hash);
+ printf("input starts with 0x%02x, length %lu\n", *input, (unsigned long) input_len);
+ printf("hash : %s\n", hash_string);
+ if (strcmp(output, hash_string)) {
+ printf("FAILURE!\n\n");
+ return 1;
+ } else {
+ printf("SUCCESS!\n\n");
+ return 0;
+ }
+}
+
+int main(void)
+{
+ size_t i;
+ for (i = 0; i < (sizeof STRING_VECTORS / sizeof (struct string_vector)); i++) {
+ const struct string_vector *vector = &STRING_VECTORS[i];
+ if (string_test(vector->input, vector->output))
+ return 1;
+ }
+ construct_binary_messages();
+ for (i = 0; i < (sizeof vectors / sizeof (struct vector)); i++) {
+ const struct vector *vector = &vectors[i];
+ if (test(vector->input, vector->input_len, vector->output))
+ {
+ destruct_binary_messages();
+ return 1;
+ }
+ }
+ destruct_binary_messages();
+ return 0;
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c
new file mode 100644
index 0000000000..6ad22c1dcd
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c
@@ -0,0 +1,173 @@
+
+#include "erl_nif.h"
+
+#include "sha-2/sha-256.h"
+struct buffer_state;
+#include "gen_yielding_sha_256.h"
+
+
+
+
+ERL_NIF_TERM
+mk_atom(ErlNifEnv* env, const char* atom)
+{
+ ERL_NIF_TERM ret;
+
+ if(!enif_make_existing_atom(env, atom, &ret, ERL_NIF_LATIN1))
+ {
+ return enif_make_atom(env, atom);
+ }
+
+ return ret;
+}
+
+ERL_NIF_TERM
+mk_error(ErlNifEnv* env, const char* mesg)
+{
+ return enif_make_tuple2(env, mk_atom(env, "error"), mk_atom(env, mesg));
+}
+
+
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return enif_alloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ enif_free(data);
+}
+
+typedef struct {
+ void* continuation;
+ ErlNifEnv* work_env;
+ ErlNifBinary out_bin;
+} sha256continuation;
+
+/* #define DEBUG */
+#ifdef DEBUG
+# define DEBUG_PRINT(x) printf x
+long nr_of_yields = 0;
+#else
+# define DEBUG_PRINT(x) do {} while (0)
+#endif
+
+void sha256continuation_ErlNifResourceDtor(ErlNifEnv* caller_env, void* obj){
+ sha256continuation* continuation = obj;
+ if(continuation->continuation != NULL){
+ calc_sha_256_ycf_gen_destroy(continuation->continuation);
+ enif_release_binary(&continuation->out_bin);
+ enif_free_env(continuation->work_env);
+ continuation->continuation = NULL;
+ DEBUG_PRINT(("DESTOY\n"));
+ }
+ DEBUG_PRINT(("DEALLOC\n"));
+}
+
+#define REDUCTIONS_UNTIL_YCF_YIELD() (200*300*8)
+
+static ERL_NIF_TERM
+sha256_nif_cont_after_yield(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ ErlNifResourceType* res_type = (ErlNifResourceType*)enif_priv_data(env);
+ long nr_of_reductions = REDUCTIONS_UNTIL_YCF_YIELD();
+ sha256continuation* continuation;
+ enif_get_resource(env,
+ argv[0],
+ res_type,
+ (void**)&continuation);
+ calc_sha_256_ycf_gen_continue(&nr_of_reductions,
+ &continuation->continuation,
+ NULL);
+ if(YCF_IS_YIELDED(continuation->continuation)){
+#ifdef DEBUG
+ nr_of_yields++;
+#endif
+ return enif_schedule_nif(env, "sha256_nif_cont_after_yield", 0, sha256_nif_cont_after_yield, 1, argv);
+ }
+ DEBUG_PRINT(("NUMBER OF YCF_YIELD()S %ld \n", nr_of_yields));
+ enif_free_env(continuation->work_env);
+ ErlNifBinary out_bin = continuation->out_bin;
+ return enif_make_binary(env, &out_bin);
+}
+
+static ERL_NIF_TERM
+sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ /* ErlNifEnv* msg_env; */
+ ErlNifResourceType* res_type = (ErlNifResourceType*)enif_priv_data(env);
+ ErlNifEnv *work_env = enif_alloc_env();
+ void* wb = NULL;
+ long nr_of_reductions;
+ ERL_NIF_TERM newargv[1];
+ if(argc != 1 || !enif_is_binary(env, argv[0]))
+ {
+ return enif_make_badarg(env);
+ }
+ /* Copy the input binary to the work environemnt so it will be kept when we are yielding */
+ ERL_NIF_TERM input_bin_term = enif_make_copy(work_env, argv[0]);
+ ErlNifBinary input_bin;
+ enif_inspect_binary(work_env, input_bin_term, &input_bin);
+ ErlNifBinary out_bin;
+ enif_alloc_binary(256/8, &out_bin);
+ nr_of_reductions = REDUCTIONS_UNTIL_YCF_YIELD();
+#ifdef DEBUG
+ nr_of_yields = 0;
+#endif
+ calc_sha_256_ycf_gen_yielding(&nr_of_reductions,
+ &wb,
+ NULL,
+ allocator,
+ freer,
+ NULL,
+ 64,
+ NULL,
+ out_bin.data,
+ input_bin.data,
+ input_bin.size);
+ if(YCF_IS_YIELDED(wb)){
+ DEBUG_PRINT(("TRAPPED FIRST CALL %ld \n", nr_of_reductions));
+ sha256continuation* continuation =
+ enif_alloc_resource(res_type,
+ sizeof(sha256continuation));
+ continuation->work_env = work_env;
+ continuation->continuation = wb;
+ continuation->out_bin = out_bin;
+ newargv[0] = enif_make_resource(env, continuation);
+ enif_release_resource(continuation);
+ return enif_schedule_nif(env, "sha256_nif_cont_after_yield", 0, sha256_nif_cont_after_yield, 1, newargv);
+ }
+ enif_free_env(work_env);
+ return enif_make_binary(env, &out_bin);
+}
+
+static ErlNifFunc nif_funcs[] = {
+ {"sha256", 1, sha256_nif}
+};
+
+static int
+nifload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ *priv_data = enif_open_resource_type(env,
+ NULL,
+ "sha256_nif",
+ sha256continuation_ErlNifResourceDtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ return 0;
+}
+
+static int
+nifupgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
+{
+ *priv_data = enif_open_resource_type(env,
+ NULL,
+ "sha256_nif",
+ sha256continuation_ErlNifResourceDtor,
+ ERL_NIF_RT_TAKEOVER,
+ NULL);
+ return 0;
+}
+
+ERL_NIF_INIT(sha256_nif, nif_funcs, nifload, NULL, nifupgrade, NULL);
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/rebar.config b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/rebar.config
new file mode 100644
index 0000000000..d20b1db59d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/rebar.config
@@ -0,0 +1,12 @@
+{erl_opts, [debug_info]}.
+{deps, []}.
+
+{erl_opts, [debug_info]}.
+{deps, []}.
+
+{pre_hooks,
+ [{"(linux|darwin|solaris)", compile, "make -C c_src"},
+ {"(freebsd)", compile, "gmake -C c_src"}]}.
+{post_hooks,
+ [{"(linux|darwin|solaris)", clean, "make -C c_src clean"},
+ {"(freebsd)", clean, "gmake -C c_src clean"}]}. \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.app.src b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.app.src
new file mode 100644
index 0000000000..603a5092bb
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.app.src
@@ -0,0 +1,14 @@
+{application, sha256_nif,
+ [{description, "An OTP library"},
+ {vsn, "0.1.0"},
+ {registered, []},
+ {applications,
+ [kernel,
+ stdlib
+ ]},
+ {env,[]},
+ {modules, []},
+
+ {licenses, ["Apache 2.0"]},
+ {links, []}
+ ]}.
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.erl b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.erl
new file mode 100644
index 0000000000..d613f2c5aa
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/src/sha256_nif.erl
@@ -0,0 +1,27 @@
+-module(sha256_nif).
+
+-export([sha256/1]).
+-on_load(init/0).
+
+-define(APPNAME, sha256_nif).
+-define(LIBNAME, sha256_erlang_nif).
+
+sha256(_) ->
+ not_loaded(?LINE).
+
+init() ->
+ SoName = case code:priv_dir(?APPNAME) of
+ {error, bad_name} ->
+ case filelib:is_dir(filename:join(["..", priv])) of
+ true ->
+ filename:join(["..", priv, ?LIBNAME]);
+ _ ->
+ filename:join([priv, ?LIBNAME])
+ end;
+ Dir ->
+ filename:join(Dir, ?LIBNAME)
+ end,
+ erlang:load_nif(SoName, 0).
+
+not_loaded(Line) ->
+ exit({not_loaded, [{module, ?MODULE}, {line, Line}]}).
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/test/basic_SUITE.erl b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/test/basic_SUITE.erl
new file mode 100644
index 0000000000..7d0a42ce84
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/test/basic_SUITE.erl
@@ -0,0 +1,32 @@
+-module(basic_SUITE).
+-include_lib("common_test/include/ct.hrl").
+-export([all/0]).
+-export([test1/1, test2/1]).
+
+all() ->
+ [test1, test2].
+
+bin_to_hex_string(Bin)->
+ lists:flatten(io_lib:format("~s", [lists:flatten([io_lib:format("~2.16.0B",[X]) || <<X:8>> <= Bin ])])).
+
+foreach_up_to_helper(UpTo, UpTo, Fun) ->
+ ok;
+foreach_up_to_helper(UpTo, Current, Fun) ->
+ Fun(Current),
+ foreach_up_to_helper(UpTo, Current + 1, Fun).
+
+foreach_up_to(UpTo, Fun) ->
+ foreach_up_to_helper(UpTo, 1, Fun).
+
+test1(_Config) ->
+ foreach_up_to(15, fun(V) ->
+ In = erlang:list_to_binary(lists:flatten(lists:duplicate(1024 bsl V, "h"))),
+ {CryptoHashTime, Expect} = timer:tc(crypto, hash, [sha256,In]),
+ {MyTime, Expect} = timer:tc(sha256_nif, sha256, [In]),
+ io:format("Size: ~p My Time: ~p Crypto Hash Time: ~p", [1024 bsl V, MyTime/1000000, CryptoHashTime/1000000])
+ end),
+ ok.
+
+test2(_Config) ->
+ Expect = crypto:hash(sha256, "hej"),
+ Expect = sha256_nif:sha256(<<"hej">>).
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c b/erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c
new file mode 100644
index 0000000000..0ac86d0b7d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c
@@ -0,0 +1,92 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+void sub_fun(char* x){
+ *x = *x + 1; /* x == 3*/
+ *x = *x + 1; /* x == 4*/
+}
+
+int sub_fun2(int x, int y){
+ return x+y;
+}
+
+int fun(char x){
+ int y;
+ (void)y;
+ x = x + 1; /* x == 2*/
+ sub_fun(((&x)));
+ sub_fun2(10, 20);
+ y = sub_fun2(10, 20);
+ YCF_YIELD();
+ x = x + 1; /* x == 5*/
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 5){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c.out b/erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c.out
new file mode 100644
index 0000000000..20db8bc359
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_fun_call.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 5
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_yield.c b/erts/lib_src/yielding_c_fun/test/examples/simple_yield.c
new file mode 100644
index 0000000000..49316af598
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_yield.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int empty_fun(){
+ return 1;
+}
+
+int fun(char x){
+ x = x + 1; /* x == 2*/
+ YCF_YIELD();
+ x = x + 1; /* x == 3*/
+ {
+ int hej = !!empty_fun();
+ (void)hej;
+ }
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 3){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_yield.c.out b/erts/lib_src/yielding_c_fun/test/examples/simple_yield.c.out
new file mode 100644
index 0000000000..96f574d048
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_yield.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 3
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c b/erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c
new file mode 100644
index 0000000000..5c3778e203
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD_NO_REDS()
+
+int empty_fun(){
+ return 1;
+}
+
+int fun(char x){
+ x = x + 1; /* x == 2*/
+ YCF_YIELD_NO_REDS();
+ x = x + 1; /* x == 3*/
+ {
+ int hej = !!empty_fun();
+ (void)hej;
+ return x;
+ }
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 777;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ if(nr_of_reductions != 777){
+ printf("SHOULD NOT HAPPEN\n");
+ }
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 3){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c.out b/erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c.out
new file mode 100644
index 0000000000..96f574d048
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_yield_no_reds.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 3
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c b/erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c
new file mode 100644
index 0000000000..99fcabaf99
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c
@@ -0,0 +1,111 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+void sub_fun_1(char* res, char x, char y){
+ printf("sub_fun_1_1\n");
+ YCF_YIELD();
+ printf("sub_fun_1_2\n");
+ *res = x + y;
+ YCF_YIELD();
+ printf("sub_fun_1_3\n");
+ YCF_YIELD();
+ printf("sub_fun_1_4\n");
+}
+
+void sub_fun_2(){
+ printf("sub_fun_2_1\n");
+ YCF_YIELD();
+ printf("sub_fun_2_2\n");
+}
+
+char sub_fun_3(char x, char y){
+ char res;
+ printf("sub_fun_2_1\n");
+ YCF_YIELD();
+ res = x + y;
+ YCF_YIELD();
+ printf("sub_fun_2_2\n");
+ return res;
+}
+
+int fun(char x){
+ char y;
+ char z = 10
+ YCF_YIELD();
+ sub_fun_1(&y,x,1); /* y == 2 */
+ YCF_YIELD();
+ sub_fun_2();
+ YCF_YIELD();
+ y = sub_fun_3(y, 1); /* y == 3 */
+ YCF_YIELD();
+ return y + z;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 13){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c.out b/erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c.out
new file mode 100644
index 0000000000..cc807db6c3
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/simple_yielding_fun_call.c.out
@@ -0,0 +1,18 @@
+sub_fun_1_1
+TRAPPED
+sub_fun_1_2
+TRAPPED
+sub_fun_1_3
+TRAPPED
+sub_fun_1_4
+TRAPPED
+sub_fun_2_1
+TRAPPED
+sub_fun_2_2
+TRAPPED
+sub_fun_2_1
+TRAPPED
+TRAPPED
+sub_fun_2_2
+TRAPPED
+RETURNED 13
diff --git a/erts/lib_src/yielding_c_fun/test/examples/stack_array.c b/erts/lib_src/yielding_c_fun/test/examples/stack_array.c
new file mode 100644
index 0000000000..9f251749d6
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/stack_array.c
@@ -0,0 +1,135 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define YCF_YIELD()
+
+
+void fun(int x3content[]){
+ int x1[2];
+ int x2[2][2];
+ int *x3[2];
+ int z = 42;
+ (void)z;
+ x1[0] = 1;
+ x1[1] = 2;
+ x2[0][0] = 3;
+ x2[0][1] = 4;
+ x2[1][0] = 5;
+ x2[1][1] = 6;
+ x3[0] = x3content;
+ x3[1] = x3content;
+ x3[0][0] = 7;
+ x3[0][1] = 8;
+ x3[1][0] = 9;
+ x3[1][1] = 10;
+ printf("%d %d %d %d %d %d %d %d %d %d\n",
+ x1[0],
+ x1[1],
+ x2[0][0],
+ x2[0][1],
+ x2[1][0],
+ x2[1][1],
+ x3[0][0],
+ x3[0][1],
+ x3[1][0],
+ x3[1][1]);
+ YCF_YIELD();
+ printf("%d %d %d %d %d %d %d %d %d %d\n",
+ x1[0],
+ x1[1],
+ x2[0][0],
+ x2[0][1],
+ x2[1][0],
+ x2[1][1],
+ x3[0][0],
+ x3[0][1],
+ x3[1][0],
+ x3[1][1]);
+ return;
+}
+
+void fun_reset(int x3content[]){
+ int x1[2];
+ int x2[2][2];
+ int *x3[2];
+ (void)x2;
+ (void)x1;
+ x1[0] = 42;
+ x1[1] = 42;
+ x2[0][0] = 42;
+ x2[0][1] = 42;
+ x2[1][0] = 42;
+ x2[1][1] = 42;
+ x3[0] = x3content;
+ x3[1] = x3content;
+ x3[0][0] = 42;
+ x3[0][1] = 42;
+ x3[1][0] = 42;
+ x3[1][1] = 42;
+ return;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int x3content[2];
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL, x3content);
+ fun_reset(x3content);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(x3content);
+#endif
+ printf("RETURNED\n");
+ return 0;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/stack_array.c.out b/erts/lib_src/yielding_c_fun/test/examples/stack_array.c.out
new file mode 100644
index 0000000000..c5cd129186
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/stack_array.c.out
@@ -0,0 +1,4 @@
+1 2 3 4 5 6 9 10 9 10
+TRAPPED
+1 2 3 4 5 6 42 42 42 42
+RETURNED
diff --git a/erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c b/erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c
new file mode 100644
index 0000000000..146364d936
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#if __STDC_VERSION__ >= 199901L
+
+#else
+#define inline
+#endif
+
+#define YCF_YIELD()
+
+static
+inline
+int fun(char x);
+
+
+static
+inline
+int fun(char x){
+ x = x + 1; /* x == 2*/
+ {
+ int y;
+ y = 1;
+ {
+ int z = 1;
+ YCF_YIELD();
+ x = x + y + z; /* x == 4*/
+ return x;
+ }
+ }
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+ (void)fun;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 4){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c.out b/erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c.out
new file mode 100644
index 0000000000..cf0b7ff2c6
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/static_inline_function.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 4
diff --git a/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_code.c b/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_code.c
new file mode 100644
index 0000000000..fd1240c180
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_code.c
@@ -0,0 +1,66 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int A(int depth);
+int B(int depth);
+
+int A(int depth){
+ int b;
+ YCF_YIELD();
+ depth++;
+ printf("A ");
+ YCF_YIELD();
+ if(depth == 100){
+ return 1;
+ } else {
+ b = B(depth);
+ }
+ YCF_YIELD();
+ return b + 1;
+}
+
+int B(int depth){
+ int a;
+ YCF_YIELD();
+ depth++;
+ printf("B ");
+ YCF_YIELD();
+ if(depth == 100){
+ YCF_YIELD();
+ return 1;
+ } else {
+ a = A(depth);
+ }
+ YCF_YIELD();
+ return a + 1;
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c b/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c
new file mode 100644
index 0000000000..b8d377f724
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c
@@ -0,0 +1,71 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#ifdef YCF_YIELD_CODE_GENERATED
+#include "tmp_dir/tmp.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int A(int depth);
+int B(int depth);
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = A_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,0);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+#else
+ ret = A(0);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != A(0)){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c.out b/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c.out
new file mode 100644
index 0000000000..c41fe372ae
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/test_generated_header_file_main.c.out
@@ -0,0 +1,302 @@
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+RETURNED 100
+A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c b/erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c
new file mode 100644
index 0000000000..04e071e94b
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int empty_fun(){
+ return 1;
+}
+
+#include "tmp.inc"
+
+static int fun(char x){
+ x = x + 1; /* x == 2*/
+ YCF_YIELD();
+ x = x + 1; /* x == 3*/
+ {
+ int hej = !!empty_fun();
+ return x + hej;
+ }
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+ (void)fun;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 4){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c.out b/erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c.out
new file mode 100644
index 0000000000..cf0b7ff2c6
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/test_only_output_yielding_funs.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 4
diff --git a/erts/lib_src/yielding_c_fun/test/examples/test_trap.c b/erts/lib_src/yielding_c_fun/test/examples/test_trap.c
new file mode 100644
index 0000000000..7799de618e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/test_trap.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(char x){
+ int y = 10;
+ int i = 0;
+ printf("BEFORE YCF_YIELD()\n");
+ y = y + x;/*y == 11*/
+ for (i = 0; i < 100; i++){
+ printf("ITER %d\n", i);
+ y = y + x;
+ YCF_YIELD();
+ }
+ printf("AFTER YCF_YIELD()\n");/*y == 111*/
+ y = y*3;
+ return y;/*y == 333*/
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun(1,&wb,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ return 0;
+}
+
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/thread_example.c b/erts/lib_src/yielding_c_fun/test/examples/thread_example.c
new file mode 100644
index 0000000000..875e9fe990
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/thread_example.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD_NO_REDS()
+
+static int f_2(char* name, int n) {
+ for(int y = 0; y < 2; y++) {
+ printf("%s f_2: y=%d\n", name, y);
+ }
+ return n*2;
+}
+
+static void f_1(char* name, int x) {
+ YCF_YIELD_NO_REDS();
+ while (x > 0) {
+ int f_2_ret = f_2(name, x);
+ printf("%s f_1: x=%d f_2_ret=%d\n", name, x, f_2_ret);
+ x--;
+ }
+ printf("%s f_1: DONE\n", name);
+}
+
+static void* ycf_alloc(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+static void ycf_free(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] ) {
+#ifdef YCF_YIELD_CODE_GENERATED
+ long t1_nr_of_reds = 1;
+ void* t1_state = NULL;
+ long t2_nr_of_reds = 2;
+ void* t2_state = NULL;
+ long t3_nr_of_reds = 1000;
+ void* t3_state = NULL;
+ /* Start t1, t2 and t3*/
+ f_1_ycf_gen_yielding(&t1_nr_of_reds, &t1_state, NULL,
+ ycf_alloc, ycf_free, NULL, 0, NULL,
+ "t1", 2);
+ f_1_ycf_gen_yielding(&t2_nr_of_reds, &t2_state, NULL,
+ ycf_alloc, ycf_free, NULL, 0, NULL,
+ "t2", 4);
+ f_1_ycf_gen_yielding(&t3_nr_of_reds, &t3_state, NULL,
+ ycf_alloc, ycf_free, NULL, 0, NULL,
+ "t3", 2);
+ printf("THREADS STARTED\n");
+ /* Execute t1, t2 and t3*/
+ while (t1_state != NULL ||
+ t2_state != NULL ||
+ t3_state != NULL) {
+ t1_nr_of_reds = 1;
+ t2_nr_of_reds = 2;
+ if (t1_state != NULL) {
+ printf("SCHEDULING THREAD: t1\n");
+ f_1_ycf_gen_continue(&t1_nr_of_reds, &t1_state, NULL);
+ if (t1_state == NULL) {
+ printf("THREAD t1 DONE (number of reductions left = %ld)\n",
+ t1_nr_of_reds);
+ }
+ }
+ if (t2_state != NULL) {
+ printf("SCHEDULING THREAD: t2\n");
+ f_1_ycf_gen_continue(&t2_nr_of_reds, &t2_state, NULL);
+ if (t2_state == NULL) {
+ printf("THREAD t2 DONE (number of reductions left = %ld)\n",
+ t2_nr_of_reds);
+ }
+ }
+ if (t3_state != NULL) {
+ printf("SCHEDULING THREAD: t3\n");
+ f_1_ycf_gen_continue(&t3_nr_of_reds, &t3_state, NULL);
+ if (t3_state == NULL) {
+ printf("THREAD t3 DONE (number of reductions left = %ld)\n",
+ t3_nr_of_reds);
+ }
+ }
+ }
+#endif
+ (void)f_1;
+ printf("DONE\n");
+ return 0;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/thread_example.c.out b/erts/lib_src/yielding_c_fun/test/examples/thread_example.c.out
new file mode 100644
index 0000000000..015f2204ea
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/thread_example.c.out
@@ -0,0 +1,47 @@
+THREADS STARTED
+SCHEDULING THREAD: t1
+SCHEDULING THREAD: t2
+SCHEDULING THREAD: t3
+t3 f_2: y=0
+t3 f_2: y=1
+t3 f_1: x=2 f_2_ret=4
+t3 f_2: y=0
+t3 f_2: y=1
+t3 f_1: x=1 f_2_ret=2
+t3 f_1: DONE
+THREAD t3 DONE (number of reductions left = 994)
+SCHEDULING THREAD: t1
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+t2 f_2: y=1
+t2 f_1: x=4 f_2_ret=8
+SCHEDULING THREAD: t1
+t1 f_2: y=0
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+SCHEDULING THREAD: t1
+t1 f_2: y=1
+t1 f_1: x=2 f_2_ret=4
+SCHEDULING THREAD: t2
+t2 f_2: y=1
+t2 f_1: x=3 f_2_ret=6
+SCHEDULING THREAD: t1
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+t2 f_2: y=1
+t2 f_1: x=2 f_2_ret=4
+SCHEDULING THREAD: t1
+t1 f_2: y=0
+SCHEDULING THREAD: t2
+t2 f_2: y=0
+SCHEDULING THREAD: t1
+t1 f_2: y=1
+t1 f_1: x=1 f_2_ret=2
+t1 f_1: DONE
+THREAD t1 DONE (number of reductions left = 1)
+SCHEDULING THREAD: t2
+t2 f_2: y=1
+t2 f_1: x=1 f_2_ret=2
+t2 f_1: DONE
+THREAD t2 DONE (number of reductions left = 2)
+DONE
diff --git a/erts/lib_src/yielding_c_fun/test/examples/void_param.c b/erts/lib_src/yielding_c_fun/test/examples/void_param.c
new file mode 100644
index 0000000000..f5e089b27a
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/void_param.c
@@ -0,0 +1,79 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+int fun(void){
+ int z = 1;
+ char x = z + 1; /* x == 2*/
+ YCF_YIELD();
+ x = x + 1; /* x == 3*/
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun();
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 3){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/void_param.c.out b/erts/lib_src/yielding_c_fun/test/examples/void_param.c.out
new file mode 100644
index 0000000000..96f574d048
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/void_param.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 3
diff --git a/erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c b/erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c
new file mode 100644
index 0000000000..10dd51bfae
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c
@@ -0,0 +1,85 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+
+void fun(int* y){
+ int x = 1;
+ x = x + 1; /* x == 2*/
+ YCF_YIELD();
+ x = x + 1; /* x == 3*/
+ *y = x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int nr_of_trapps = 0;
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,&ret);
+ if(wb != NULL){
+ printf("TRAP\n");
+ nr_of_trapps++;
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+ if(nr_of_trapps != 1){
+ printf("ERROR\n");
+ exit(1);
+ }
+#else
+ fun(&ret);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 3){
+ printf("ERROR\n");
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c.out b/erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c.out
new file mode 100644
index 0000000000..4b85bbb30e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/void_ret_fun.c.out
@@ -0,0 +1,2 @@
+TRAP
+RETURNED 3
diff --git a/erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c b/erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c
new file mode 100644
index 0000000000..20fe2a444d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c
@@ -0,0 +1,126 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+#define YCF_CONSUME_REDS(X)
+#ifndef YCF_YIELD_CODE_GENERATED
+#define YCF_STACK_ALLOC(X) malloc(1)
+#endif
+
+int sub_fun(int x){
+ int i;
+ int count = 0;
+ char* my_data = YCF_STACK_ALLOC(5);
+ my_data[0] = 's';
+ my_data[1] = 'u';
+ my_data[2] = 'b';
+ my_data[3] = '\n';
+ my_data[4] = '\0';
+ for(i = 0; i < 2; i++){
+ count = count + 2;
+ YCF_YIELD();
+ printf("%s", my_data);
+ }
+ return count + x;
+}
+
+int fun(int x){
+ int ret;
+ char* my_data = YCF_STACK_ALLOC(5);
+ char* my_data2 = YCF_STACK_ALLOC(5);
+ char* my_data3;
+ my_data[0] = 'h';
+ my_data[1] = 'e';
+ my_data[2] = 'j';
+ my_data[3] = '\n';
+ my_data[4] = '\0';
+ my_data2[0] = 's';
+ my_data2[1] = 'o';
+ my_data2[2] = 's';
+ my_data2[3] = '\n';
+ my_data2[4] = '\0';
+ YCF_YIELD();
+ printf("%s", my_data);
+ printf("%s", my_data2);
+ ret = sub_fun(x);
+ ret = sub_fun(x);
+ my_data3 = YCF_STACK_ALLOC(5);
+ printf("BEFORE OVERWRITE %s", my_data3);
+ my_data3[0] = 'e';
+ my_data3[1] = 'r';
+ my_data3[2] = 'l';
+ my_data3[3] = '\n';
+ my_data3[4] = '\0';
+ printf("AFTER OVERWRITE %s", my_data3);
+ return ret;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ int nr_of_yields = 0;
+ long nr_of_reductions;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ nr_of_reductions = 101;
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,15,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED %ld\n", nr_of_reductions);
+ nr_of_yields++;
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = fun(1);
+#endif
+ printf("Number of yields %d\n", nr_of_yields);
+ printf("RETURNED %d\n", ret);
+ if(ret != 5){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c.out b/erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c.out
new file mode 100644
index 0000000000..8b3c31c9e5
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/ycf_stack_alloc.c.out
@@ -0,0 +1,15 @@
+TRAPPED 0
+hej
+sos
+TRAPPED 0
+sub
+TRAPPED 0
+sub
+TRAPPED 0
+sub
+TRAPPED 0
+sub
+BEFORE OVERWRITE sub
+AFTER OVERWRITE erl
+Number of yields 5
+RETURNED 5
diff --git a/erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c b/erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c
new file mode 100644
index 0000000000..3506d83499
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct my_struct {
+ struct my_struct* my_struct;
+ int len;
+} my_struct;
+
+
+#define YCF_YIELD()
+
+int fun(char x){
+ my_struct s;
+ my_struct* sp;
+ int len = 55;
+ s.len = 10;
+ s.my_struct = NULL;
+ sp = malloc(sizeof(my_struct));
+ sp->len = 10;
+ sp->my_struct = NULL;
+ YCF_YIELD();
+ return
+ s.len == 10 &&
+ s.my_struct == NULL &&
+ sp->len == 10 &&
+ sp->my_struct == NULL &&
+ len == 55;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != 1){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c.out b/erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c.out
new file mode 100644
index 0000000000..7c3cfb5078
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/yield_with_struct.c.out
@@ -0,0 +1,2 @@
+TRAPPED
+RETURNED 1
diff --git a/erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c b/erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c
new file mode 100644
index 0000000000..c0d7ac6c13
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int sub_fun(char x){
+ YCF_YIELD();
+ x = x + 1; /* x == 1*/
+ return (x == 10 ? 0 : 1);
+}
+
+
+int fun(char x){
+ if(sub_fun(0)){
+ printf("hej\n");
+ }
+ if(0) printf("NO");
+ else if(sub_fun(0)){
+ printf("hej 2\n");
+ }
+ if(sub_fun(10)){
+ printf("hej 3\n");
+ } else {
+ printf("HEJ\n");
+ }
+ while(sub_fun(9)){
+ printf("hoo\n");
+ }
+ do{
+ printf("haa\n");
+ }while(sub_fun(9));
+ return x;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+ long nr_of_reductions = 1;
+#endif
+ int ret = 0;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ fun(1);
+#endif
+ printf("RETURNED %d\n", ret);
+ return 0;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c.out b/erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c.out
new file mode 100644
index 0000000000..11b01b7d63
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/yielding_fun_in_control.c.out
@@ -0,0 +1,10 @@
+TRAPPED
+hej
+TRAPPED
+hej 2
+TRAPPED
+hej 3
+TRAPPED
+haa
+TRAPPED
+RETURNED 1
diff --git a/erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c b/erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c
new file mode 100644
index 0000000000..655c94e956
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c
@@ -0,0 +1,104 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Description:
+ *
+ * Author: Kjell Winblad
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define YCF_YIELD()
+
+int A(int depth);
+int B(int depth);
+
+int A(int depth){
+ int b;
+ YCF_YIELD();
+ depth++;
+ printf("A ");
+ YCF_YIELD();
+ if(depth == 100){
+ return 1;
+ } else {
+ b = B(depth);
+ }
+ YCF_YIELD();
+ return b + 1;
+}
+
+int B(int depth){
+ int a;
+ YCF_YIELD();
+ depth++;
+ printf("B ");
+ YCF_YIELD();
+ if(depth == 100){
+ YCF_YIELD();
+ return 1;
+ } else {
+ a = A(depth);
+ }
+ YCF_YIELD();
+ return a + 1;
+}
+
+void* allocator(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void freer(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+int main( int argc, const char* argv[] )
+{
+#ifdef YCF_YIELD_CODE_GENERATED
+ void* wb = NULL;
+#endif
+ int ret = 0;
+ long nr_of_reductions = 1;
+#ifdef YCF_YIELD_CODE_GENERATED
+ do{
+ ret = A_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,0);
+ if(wb != NULL){
+ printf("TRAPPED\n");
+ }
+ }while(wb != NULL);
+ if(wb != NULL){
+ free(wb);
+ }
+#else
+ ret = A(0);
+#endif
+ printf("RETURNED %d\n", ret);
+ if(ret != A(0)){
+ return 1;
+ }else{
+ return 0;
+ }
+}
diff --git a/erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c.out b/erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c.out
new file mode 100644
index 0000000000..c41fe372ae
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/examples/yielding_mutual_recursion.c.out
@@ -0,0 +1,302 @@
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+A TRAPPED
+TRAPPED
+B TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+TRAPPED
+RETURNED 100
+A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/test/test.sh b/erts/lib_src/yielding_c_fun/test/test.sh
new file mode 100755
index 0000000000..a0270475fb
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/test/test.sh
@@ -0,0 +1,176 @@
+#!/bin/bash
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+#
+# 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.
+#
+# %CopyrightEnd%
+
+
+#
+# Description:
+#
+# Author: Kjell Winblad
+#
+
+#Code to find directory of this file from https://stackoverflow.com/questions/59895/get-the-source-directory-of-a-bash-script-from-within-the-script-itself
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+ DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+ SOURCE="$(readlink "$SOURCE")"
+ [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+done
+DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
+
+GC=$1
+
+RR=-rr
+RR=""
+
+PATH=$PATH:$DIR/../bin
+
+set -e
+set -x
+
+TMP_DIR=$DIR/tmp_dir
+
+mkdir -p $TMP_DIR
+
+TMP_FILE=$TMP_DIR/tmp
+
+TMP_C_FILE=$TMP_DIR/tmp.c
+TMP_INC_FILE=$TMP_DIR/tmp.inc
+TMP_C_FILE2=$TMP_DIR/tmp2.c
+TMP_O_FILE1=$TMP_DIR/tmp1.o
+TMP_O_FILE2=$TMP_DIR/tmp2.o
+TMP_H_FILE=$TMP_DIR/tmp.h
+TMP_CC_OUT=$TMP_DIR/a.out
+
+CC_ARGS="-std=c99 -pedantic -Wall"
+
+CC=clang
+
+SIMPLE_TEST_FILES=("$DIR/examples/simple_yield.c"
+ "$DIR/examples/multi_scope_yield.c"
+ "$DIR/examples/nested_loop_yield.c"
+ "$DIR/examples/void_ret_fun.c"
+ "$DIR/examples/declarations.c"
+ "$DIR/examples/void_param.c"
+ "$DIR/examples/simple_fun_call.c"
+ "$DIR/examples/control_statements.c"
+ "$DIR/examples/simple_yielding_fun_call.c"
+ "$DIR/examples/yielding_mutual_recursion.c"
+ "$DIR/examples/stack_array.c"
+ "$DIR/examples/custom_code_save_restore_yield_state.c"
+ "$DIR/examples/custom_code_save_restore_yield_state_alt_syntax.c"
+ "$DIR/examples/destroy_while_yielded.c"
+ "$DIR/examples/consume_reds.c"
+ "$DIR/examples/nested_call_consume_reds.c"
+ "$DIR/examples/auto_yield.c"
+ "$DIR/examples/yield_with_struct.c"
+ "$DIR/examples/const_defenition.c"
+ "$DIR/examples/ycf_stack_alloc.c"
+ "$DIR/examples/declarations_in_for_loops.c"
+ "$DIR/examples/in_code_var_declaration.c"
+ "$DIR/examples/static_inline_function.c"
+ "$DIR/examples/yielding_fun_in_control.c"
+ "$DIR/examples/debug_ptr_to_stack.c"
+ "$DIR/examples/simple_yield_no_reds.c"
+ "$DIR/examples/thread_example.c")
+
+SIMPLE_TEST_FILES_YIELD_FUNS=("-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun -fnoauto sub_fun_1 -fnoauto sub_fun_2 -fnoauto sub_fun_3"
+ "-fnoauto A -fnoauto B"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun -fnoauto sub_fun"
+ "-frec fun -frec rec_inc"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun -fnoauto sub_fun"
+ "-f fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-fnoauto fun -fnoauto sub_fun"
+ "-fnoauto fun"
+ "-fnoauto fun"
+ "-f f_1 -f f_2")
+
+# Check that yielding_c_fun can repeat files correctly
+for C_FILE in $SIMPLE_TEST_FILES
+do
+ yielding_c_fun $GC $RR -repeat $C_FILE > $TMP_C_FILE
+ cmp $C_FILE $TMP_C_FILE
+done
+
+# Check that the default action is to generate correct yield code
+yielding_c_fun $GC -yield $DIR/examples/simple_yield.c > $TMP_C_FILE
+yielding_c_fun $GC $DIR/examples/simple_yield.c > $TMP_C_FILE2
+cmp $TMP_C_FILE $TMP_C_FILE2
+
+# Check yielding
+for ((i = 0; i < ${#SIMPLE_TEST_FILES[@]}; i++))
+do
+ yielding_c_fun $GC $RR -yield ${SIMPLE_TEST_FILES_YIELD_FUNS[$i]} "${SIMPLE_TEST_FILES[$i]}" > $TMP_C_FILE
+ $CC $CC_ARGS -g $TMP_C_FILE -o $TMP_CC_OUT
+ $TMP_CC_OUT > $TMP_FILE
+ cmp $TMP_FILE "${SIMPLE_TEST_FILES[$i]}.out"
+done
+
+
+# Check generated header file and output file
+yielding_c_fun $GC $RR -yield -fnoauto A -fnoauto B -header_file_name $TMP_H_FILE -output_file_name $TMP_C_FILE "$DIR/examples/test_generated_header_file_code.c"
+$CC $CC_ARGS -c $TMP_C_FILE -o $TMP_O_FILE1
+$CC $CC_ARGS -I$DIR -DYCF_YIELD_CODE_GENERATED=1 -c "$DIR/examples/test_generated_header_file_main.c" -o $TMP_O_FILE2
+$CC $CC_ARGS $TMP_O_FILE1 $TMP_O_FILE2 -o $TMP_CC_OUT
+$TMP_CC_OUT > $TMP_FILE
+cmp $TMP_FILE "$DIR/examples/test_generated_header_file_main.c.out"
+
+
+# Check generation of only yielding fun
+echo $TMP_INC_FILE
+yielding_c_fun.bin $GC $RR -yield -static_aux_funs -only_yielding_funs -fnoauto fun -output_file_name $TMP_INC_FILE "$DIR/examples/test_only_output_yielding_funs.c"
+$CC $CC_ARGS -I "$TMP_DIR" "$DIR/examples/test_only_output_yielding_funs.c" -o $TMP_CC_OUT
+$TMP_CC_OUT > $TMP_FILE
+cmp $TMP_FILE "$DIR/examples/test_only_output_yielding_funs.c.out"
+
+# Check that debug mode can detect pointers to stack
+yielding_c_fun $GC $RR -yield -debug -fnoauto fun "$DIR/examples/debug_ptr_to_stack.c" > $TMP_C_FILE
+$CC $CC_ARGS $TMP_C_FILE -o $TMP_CC_OUT
+(set +e ; $TMP_CC_OUT ; [ $? -ne 0 ])
+
+# Check that memory usage of the tool can be logged
+MEM_LOG_FILE="$TMP_DIR/my_mem_log_file.txt"
+yielding_c_fun $GC $RR -log_max_mem_usage "$MEM_LOG_FILE" -yield -debug -fnoauto fun "$DIR/examples/multi_scope_yield.c" > $TMP_C_FILE
+test -f "$MEM_LOG_FILE"
+#rm "$MEM_LOG_FILE"
+
+# Uncomment to the test the Erlang NIF example
+# if [ `rebar3 > /dev/null 2>&1 ; echo $?` = 0 ]
+# then
+# (cd "$DIR/examples/sha256_erlang_nif/" && make clean && make test)
+# fi
+
+
diff --git a/erts/lib_src/yielding_c_fun/ycf_helpers.h b/erts/lib_src/yielding_c_fun/ycf_helpers.h
new file mode 100644
index 0000000000..ae32f60f10
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_helpers.h
@@ -0,0 +1,40 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#ifndef YIELDING_C_FUN_HELPERS_H
+#define YIELDING_C_FUN_HELPERS_H
+
+#include <stdlib.h>
+
+static void* ycf_alloc(size_t size, void* context){
+ (void)context;
+ return malloc(size);
+}
+
+void ycf_free(void* data, void* context){
+ (void)context;
+ free(data);
+}
+
+#endif
diff --git a/erts/lib_src/yielding_c_fun/ycf_lexer.c b/erts/lib_src/yielding_c_fun/ycf_lexer.c
new file mode 100644
index 0000000000..8fcebcc6b0
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_lexer.c
@@ -0,0 +1,483 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+
+#include "lib/tiny_regex_c/re.h"
+#include "ycf_yield_fun.h"
+#include "ycf_utils.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+
+
+int ycf_symbol_is_text_eq(ycf_symbol* symbol, char* str){
+ unsigned long symbol_length = symbol->stop - symbol->start;
+ return
+ symbol_length == strlen(str) &&
+ strncmp(str, &symbol->source[symbol->start], symbol_length) == 0;
+}
+
+char* ycf_symbol_text_between(ycf_symbol* s1, ycf_symbol* s2){
+ int size = s2->stop - s1->start;
+ char* str = ycf_malloc(size+1);
+ strncpy(str, &s1->source[s1->start], size);
+ str[size] = 0;
+ return str;
+}
+
+char* get_symbol_type_text(ycf_symbol_type type){
+ switch(type) {
+ case ycf_symbol_type_comment: return "ycf_symbol_type_comment";
+ case ycf_symbol_type_string_literal: return "ycf_symbol_type_string_literal";
+ case ycf_symbol_type_macro_define: return "ycf_symbol_type_macro_define";
+ case ycf_symbol_type_macro_command: return "ycf_symbol_type_macro_command";
+ case ycf_symbol_type_whitespace: return "ycf_symbol_type_whitespace";
+ case ycf_symbol_type_identifier: return "ycf_symbol_type_identifier";
+ case ycf_symbol_type_number: return "ycf_symbol_type_number";
+ case ycf_symbol_type_star: return "ycf_symbol_type_star";
+ case ycf_symbol_type_neg: return "ycf_symbol_type_neg";
+ case ycf_symbol_type_equal_equal_sign: return "ycf_symbol_type_equal_equal_sign";
+ case ycf_symbol_type_not_equal_sign: return "ycf_symbol_type_not_equal_sign";
+ case ycf_symbol_type_open_parenthesis: return "ycf_symbol_type_open_parenthesis";
+ case ycf_symbol_type_end_parenthesis: return "ycf_symbol_type_end_parenthesis";
+ case ycf_symbol_type_open_curly_brace: return "ycf_symbol_type_open_curly_brace";
+ case ycf_symbol_type_end_curly_brace: return "ycf_symbol_type_end_curly_brace";
+ case ycf_symbol_type_open_square_bracket: return "ycf_symbol_type_open_square_bracket";
+ case ycf_symbol_type_end_square_bracket: return "ycf_symbol_type_end_square_bracket";
+ case ycf_symbol_type_equal_sign: return "ycf_symbol_type_equal_sign";
+ case ycf_symbol_type_semicolon: return "ycf_symbol_type_semicolon";
+ case ycf_symbol_type_comma: return "ycf_symbol_type_comma";
+ case ycf_symbol_type_consume_reds: return "ycf_symbol_type_consume_reds";
+ case ycf_symbol_type_pointer_field_access: return "ycf_symbol_type_pointer_field_access";
+ case ycf_symbol_type_period: return "ycf_symbol_type_period";
+ case ycf_symbol_type_const: return "ycf_symbol_type_const";
+ case ycf_symbol_type_void: return "ycf_symbol_type_void";
+ case ycf_symbol_type_volatile: return "ycf_symbol_type_volatile";
+ case ycf_symbol_type_static: return "ycf_symbol_type_static";
+ case ycf_symbol_type_inline: return "ycf_symbol_type_inline";
+ case ycf_symbol_type_return: return "ycf_symbol_type_return";
+ case ycf_symbol_type_if: return "ycf_symbol_type_if";
+ case ycf_symbol_type_else: return "ycf_symbol_type_else";
+ case ycf_symbol_type_goto: return "ycf_symbol_type_goto";
+ case ycf_symbol_type_break: return "ycf_symbol_type_break";
+ case ycf_symbol_type_while: return "ycf_symbol_type_while";
+ case ycf_symbol_type_do: return "ycf_symbol_type_do";
+ case ycf_symbol_type_for: return "ycf_symbol_type_for";
+ case ycf_symbol_type_switch: return "ycf_symbol_type_switch";
+ case ycf_symbol_type_continue: return "ycf_symbol_type_continue";
+ case ycf_symbol_type_something_else: return "ycf_symbol_type_something_else";
+ case ycf_symbol_type_special_code_start: return "ycf_symbol_type_special_code_start";
+ case ycf_symbol_type_special_code_end: return "ycf_symbol_type_special_code_end";
+ }
+ return "non_existing_symbol?";
+}
+
+typedef struct symbol_finder {
+ int (*finder)(struct symbol_finder*,char*);
+ ycf_symbol_type type;
+ int length;
+ char *str_1;
+ char *str_2;
+} symbol_finder;
+
+int starts_with(char *str, char *prefix)
+{
+ return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+int until_no_match(symbol_finder* f, char* text){
+ int pos = 0;
+ while(re_match(f->str_1, &(text[pos])) == 0){
+ pos++;
+ }
+ return pos;
+}
+
+int string_litteral_finder(symbol_finder* f, char* text){
+ int pos = 0;
+ if (starts_with(text, "\"")){
+ pos++;
+ //\"(\\.|[^"\\])*\"
+ while(re_match("\\.", &(text[pos])) == 0 ||
+ re_match("[^\"]", &(text[pos])) == 0){
+ pos++;
+ }
+ if(starts_with(&(text[pos]), "\"")){
+ return pos + 1;
+ }else {
+ printf("Broken string litteral\n");
+ exit(1);
+ }
+ }
+ return pos;
+}
+
+int macro_define_finder(symbol_finder* f, char* text){
+ int pos = 0;
+ if (starts_with(text, "#define")){
+ pos = pos + strlen("#define");
+ while(1){
+ if(starts_with(&(text[pos]), "\\\n")){
+ pos = pos + 2;
+ } else if (starts_with(&(text[pos]), "\n")){
+ break;
+ } else {
+ pos++;
+ }
+ }
+ }
+ return pos;
+}
+
+
+int starts_with_until_no_match(symbol_finder* f, char* text){
+ int pos = 0;
+ if(re_match(f->str_1, text) == 0){
+ while(re_match(f->str_2, &(text[pos])) == 0){
+ pos++;
+ }
+ }
+ return pos;
+}
+
+int starts_with_ends_with(symbol_finder* f, char* text){
+ if(starts_with(text, f->str_1)){
+ int pos = 1;
+ while(!starts_with(&(text[pos]), f->str_2)){
+ pos++;
+ }
+ return pos+strlen(f->str_2);
+ }
+ return 0;
+}
+
+int fixed_string(symbol_finder* f, char* text){
+ if(starts_with(text, f->str_1)){
+ return strlen(f->str_1);
+ }
+ return 0;
+}
+
+int fixed_alpha_string(symbol_finder* f, char* text){
+ if(starts_with(text, f->str_1) &&
+ re_match("[^\\W]", &text[strlen(f->str_1)])){
+ return strlen(f->str_1);
+ }
+ return 0;
+}
+
+int regex_char(symbol_finder* f, char* text){
+ if(re_match(f->str_1, text) == 0){
+ return 1;
+ }
+ return 0;
+}
+
+void fold_whitespace_and_comments(ycf_symbol_list* symbols){
+ ycf_symbol* prev = NULL;
+ ycf_symbol* current = symbols->head;
+ ycf_symbol* dummy = ycf_malloc(sizeof(ycf_symbol));
+ while(current != NULL){
+ current->whitespace_or_comment_before = NULL;
+ if(prev != NULL && (prev->type == ycf_symbol_type_whitespace ||
+ prev->type == ycf_symbol_type_comment)){
+ current->whitespace_or_comment_before = prev;
+ }
+ prev = current;
+ current = current->next;
+ }
+ // remove ycf_symbol_type_whitespace and comments from list
+ dummy->type = ycf_symbol_type_void;
+ dummy->next = symbols->head;
+ prev = dummy;
+ current = prev->next;
+ while(current != NULL &&
+ current != symbols->last){
+ if(current->type == ycf_symbol_type_whitespace ||
+ current->type == ycf_symbol_type_comment){
+ prev->next = current->next;
+ current = current->next;
+ }else {
+ prev = current;
+ current = current->next;
+ }
+ }
+ symbols->head = dummy->next;
+}
+
+ycf_symbol_list ycf_symbol_list_from_text(char* text){
+ int pos = 0;
+ int nr_of_finders = 41;
+ int i;
+ ycf_symbol_list ret = ycf_symbol_list_empty();
+ symbol_finder symbol_finders[] =
+ {
+ {
+ .type = ycf_symbol_type_special_code_start,
+ .str_1 = "/*special_code_start:",
+ .str_2 = "*/",
+ .finder = starts_with_ends_with
+ },
+ {
+ .type = ycf_symbol_type_special_code_end,
+ .str_1 = "/*special_code_end*/",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_comment,
+ .str_1 = "/*",
+ .str_2 = "*/",
+ .finder = starts_with_ends_with
+ },
+ {
+ .type = ycf_symbol_type_string_literal,
+ .finder = string_litteral_finder
+ },
+ {
+ .type = ycf_symbol_type_macro_define,
+ .finder = macro_define_finder
+ },
+ {
+ .type = ycf_symbol_type_macro_command,
+ .str_1 = "#",
+ .str_2 = "\n",
+ .finder = starts_with_ends_with
+ },
+ {
+ .type = ycf_symbol_type_whitespace,
+ .str_1 = "\\s",
+ .finder = until_no_match
+ },
+ {
+ .type = ycf_symbol_type_void,
+ .str_1 = "void",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_static,
+ .str_1 = "static",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_inline,
+ .str_1 = "inline",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_const,
+ .str_1 = "const",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_volatile,
+ .str_1 = "volatile",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_consume_reds,
+ .str_1 = "YCF_CONSUME_REDS",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_return,
+ .str_1 = "return",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_if,
+ .str_1 = "if",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_else,
+ .str_1 = "else",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_goto,
+ .str_1 = "goto",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_break,
+ .str_1 = "break",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_continue,
+ .str_1 = "continue",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_while,
+ .str_1 = "while",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_do,
+ .str_1 = "do",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_for,
+ .str_1 = "for",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_switch,
+ .str_1 = "switch",
+ .finder = fixed_alpha_string
+ },
+ {
+ .type = ycf_symbol_type_identifier,
+ .str_1 = "[a-zA-Z]",
+ .str_2 = "\\w",
+ .finder = starts_with_until_no_match
+ },
+ {
+ .type = ycf_symbol_type_number,
+ .str_1 = "\\d",
+ .finder = until_no_match
+ },
+ {
+ .type = ycf_symbol_type_open_parenthesis,
+ .str_1 = "(",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_end_parenthesis,
+ .str_1 = ")",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_open_curly_brace,
+ .str_1 = "{",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_end_curly_brace,
+ .str_1 = "}",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_open_square_bracket,
+ .str_1 = "[",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_end_square_bracket,
+ .str_1 = "]",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_equal_sign,
+ .str_1 = "=",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_not_equal_sign,
+ .str_1 = "!=",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_equal_sign,
+ .str_1 = "==",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_star,
+ .str_1 = "*",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_neg,
+ .str_1 = "!",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_semicolon,
+ .str_1 = ";",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_comma,
+ .str_1 = ",",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_period,
+ .str_1 = ".",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_pointer_field_access,
+ .str_1 = "->",
+ .finder = fixed_string
+ },
+ {
+ .type = ycf_symbol_type_something_else,
+ .str_1 = ".",
+ .finder = regex_char
+ }
+ };
+ while(text[pos] != 0){
+ int last_pos = pos;
+ for(i = 0; i < nr_of_finders; i++) {
+ symbol_finder f = symbol_finders[i];
+ int stop = f.finder(&f, &text[pos]);
+ if(stop){
+ ycf_symbol* s = ycf_malloc(sizeof(ycf_symbol));
+ s->type = f.type;
+ s->source = text;
+ s->start = pos;
+ s->stop = pos + stop;
+ s->next = NULL;
+ ycf_symbol_list_append(&ret, s);
+ pos = s->stop;
+ break;
+ }
+ }
+ if (last_pos == pos){
+ printf("Lexer: NOTHING MATCH Stuck at: \n%s\n", &text[pos]);
+ exit(1);
+ }
+ }
+ fold_whitespace_and_comments(&ret);
+ return ret;
+}
+
+void ycf_symbol_list_print(char* text){
+ ycf_symbol_list symbols = ycf_symbol_list_from_text(text);
+ ycf_symbol* s = symbols.head;
+ while(s != NULL){
+ printf("TYPE %s, START=%d, STOP=%d\n",
+ get_symbol_type_text(s->type),
+ s->start,
+ s->stop);
+ s = s->next;
+ }
+ printf("||||| END OF SYMBOLS\n");
+}
diff --git a/erts/lib_src/yielding_c_fun/ycf_lists.h b/erts/lib_src/yielding_c_fun/ycf_lists.h
new file mode 100644
index 0000000000..7bb3487ecf
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_lists.h
@@ -0,0 +1,316 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#ifndef YIELDING_C_FUN_LISTS_H
+#define YIELDING_C_FUN_LISTS_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define INIT_LIST(L) \
+ do{ \
+ (L)->head = NULL; \
+ (L)->last = NULL; \
+ }while(0)
+
+#define APPEND_LIST(L,E) \
+ do{ \
+ void* e = E; \
+ if((L)->head == NULL){ \
+ (L)->head = e; \
+ } else { \
+ (L)->last->next = e; \
+ } \
+ (L)->last = e; \
+ }while(0)
+
+#define PREPEND_LIST(T,L,E) \
+ do{ \
+ T* e = E; \
+ if((L)->head == NULL){ \
+ (L)->last = e; \
+ } else { \
+ e->next = (L)->head; \
+ } \
+ (L)->head = e; \
+ }while(0)
+
+#define CONCAT_LIST(T,L1,L2) \
+ do{ \
+ T* current = (L2)->head; \
+ while(current != NULL){ \
+ APPEND_LIST(L1, current); \
+ current = current->next; \
+ } \
+ }while(0)
+
+#define PRINT_LIST(T,L, NAME) \
+ do{ \
+ printf("NAME %s\n", NAME); \
+ printf("HEAD %p\n", (L)->head); \
+ printf("LAST %p\n", (L)->last); \
+ printf("ELEMS:\n"); \
+ T* current = (L)->head; \
+ while(current != NULL){ \
+ printf("E: %p\n", current); \
+ current = current->next; \
+ } \
+ }while(0)
+
+#define REMOVE_LIST(T,L,E) \
+ do{ \
+ T* prev = NULL; \
+ T* rl_current = (L)->head; \
+ T* e = E; \
+ while(rl_current != e && rl_current != NULL){ \
+ prev = rl_current ; \
+ rl_current = rl_current ->next; \
+ } \
+ if(rl_current == NULL){ \
+ exit(1); \
+ } \
+ if(prev == NULL){ \
+ if((L)->head == (L)->last){ \
+ (L)->last = NULL; \
+ } \
+ (L)->head = (L)->head->next; \
+ }else{ \
+ if(rl_current == (L)->last){ \
+ (L)->last = prev; \
+ } \
+ prev->next = rl_current ->next; \
+ } \
+ }while(0)
+
+#define INSERT_AFTER_LIST(T,L,E,TO_INSERT) \
+ do{ \
+ T* current_y = (L)->head; \
+ T* elem_x = E; \
+ T* to_insert2 = TO_INSERT; \
+ if(elem_x == NULL){ \
+ PREPEND_LIST(T,L,to_insert2); \
+ break; \
+ }else if(elem_x == (L)->last){ \
+ APPEND_LIST(L,to_insert2); \
+ break; \
+ } \
+ while(current_y != elem_x && current_y != NULL){ \
+ current_y = current_y->next; \
+ } \
+ if(current_y == NULL){ \
+ printf("CANNOT INSERT AFTER NONEXISTING\n"); \
+ exit(1); \
+ } \
+ to_insert2->next = current_y->next; \
+ current_y->next = to_insert2; \
+ }while(0)
+
+#define INSERT_BEFORE_LIST(T,L,E_BEFORE,TO_INSERT) \
+ do{ \
+ T* prev_x = NULL; \
+ T* current_x = (L)->head; \
+ T* to_insert_x = TO_INSERT; \
+ T* e_before_x = E_BEFORE; \
+ while(current_x != e_before_x && current_x != NULL){ \
+ prev_x = current_x; \
+ current_x = current_x->next; \
+ } \
+ if(current_x == NULL){ \
+ printf("CANNOT INSERT AFTER NONEXISTING\n"); \
+ exit(1); \
+ } \
+ INSERT_AFTER_LIST(T,L,prev_x,to_insert_x); \
+ }while(0)
+
+
+#define REPLACE_LIST(T,L,OLD,NEW) \
+ do{ \
+ T* old = OLD; \
+ T* new = NEW; \
+ T* prev_old_next = old->next; \
+ INSERT_AFTER_LIST(T,L,old,new); \
+ REMOVE_LIST(T,L,old); \
+ old->next = prev_old_next; \
+ }while(0)
+
+
+/* list functions */
+
+#define GENERATE_LIST_FUNCTIONS(NODE_TYPE) \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_empty(){ \
+ NODE_TYPE##_list list; \
+ INIT_LIST(&list); \
+ return list; \
+ } \
+ \
+ NODE_TYPE* NODE_TYPE##_shallow_copy(NODE_TYPE* n){ \
+ NODE_TYPE* new = ycf_malloc(sizeof(NODE_TYPE)); \
+ *new = *n; \
+ new->next = NULL; \
+ return new; \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_shallow_copy(NODE_TYPE##_list n){ \
+ NODE_TYPE##_list new; \
+ NODE_TYPE* current = n.head; \
+ INIT_LIST(&new); \
+ while(current != NULL){ \
+ APPEND_LIST(&new, NODE_TYPE##_shallow_copy(current)); \
+ current = current->next; \
+ } \
+ return new; \
+ } \
+ \
+ int NODE_TYPE##_list_get_item_position(NODE_TYPE##_list* list, NODE_TYPE* node){ \
+ NODE_TYPE* current = list->head; \
+ int pos = 0; \
+ while(current != NULL){ \
+ if(current == node){ \
+ return pos; \
+ } \
+ pos = pos + 1; \
+ current = current->next; \
+ } \
+ return -1; \
+ } \
+ \
+ NODE_TYPE* NODE_TYPE##_list_get_item_at_position(NODE_TYPE##_list* list, int pos){ \
+ NODE_TYPE* current = list->head; \
+ int current_pos = 0; \
+ while(current != NULL){ \
+ if(current_pos == pos){ \
+ return current; \
+ } \
+ current_pos = current_pos + 1; \
+ current = current->next; \
+ } \
+ return NULL; \
+ } \
+ \
+ void NODE_TYPE##_list_append(NODE_TYPE##_list* list, NODE_TYPE* node){ \
+ APPEND_LIST(list, node); \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_append(NODE_TYPE##_list list, NODE_TYPE* node){ \
+ NODE_TYPE##_list list_copy = NODE_TYPE##_list_shallow_copy(list); \
+ NODE_TYPE* node_copy = NODE_TYPE##_shallow_copy(node); \
+ NODE_TYPE##_list_append(&list_copy, node_copy); \
+ return list_copy; \
+ } \
+ \
+ void NODE_TYPE##_list_prepend(NODE_TYPE##_list* list, NODE_TYPE* node){ \
+ PREPEND_LIST(NODE_TYPE, list, node); \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_prepend(NODE_TYPE##_list list, NODE_TYPE* node){ \
+ NODE_TYPE##_list list_copy = NODE_TYPE##_list_shallow_copy(list); \
+ NODE_TYPE* node_copy = NODE_TYPE##_shallow_copy(node); \
+ NODE_TYPE##_list_prepend(&list_copy, node_copy); \
+ return list_copy; \
+ } \
+ \
+ void NODE_TYPE##_list_insert_before(NODE_TYPE##_list* list, NODE_TYPE* before_this, NODE_TYPE* to_insert_z){ \
+ INSERT_BEFORE_LIST(NODE_TYPE, list, before_this, to_insert_z); \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_insert_before(NODE_TYPE##_list list, NODE_TYPE* before_this, NODE_TYPE* to_insert){ \
+ int pos = NODE_TYPE##_list_get_item_position(&list, before_this); \
+ NODE_TYPE##_list list_copy = NODE_TYPE##_list_shallow_copy(list);; \
+ NODE_TYPE* actual_this = NODE_TYPE##_list_get_item_at_position(&list_copy, pos); \
+ NODE_TYPE* to_insert_copy = NODE_TYPE##_shallow_copy(to_insert); \
+ NODE_TYPE##_list_insert_before(&list_copy, actual_this, to_insert_copy); \
+ return list_copy; \
+ } \
+ \
+ void NODE_TYPE##_list_insert_after(NODE_TYPE##_list* list, NODE_TYPE* after_this, NODE_TYPE* to_insert_z){ \
+ INSERT_AFTER_LIST(NODE_TYPE, list, after_this, to_insert_z); \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_insert_after(NODE_TYPE##_list list, NODE_TYPE* after_this, NODE_TYPE* to_insert){ \
+ int pos = NODE_TYPE##_list_get_item_position(&list, after_this); \
+ NODE_TYPE##_list list_copy = NODE_TYPE##_list_shallow_copy(list); \
+ NODE_TYPE* actual_this = NODE_TYPE##_list_get_item_at_position(&list_copy, pos); \
+ NODE_TYPE* to_insert_copy = NODE_TYPE##_shallow_copy(to_insert); \
+ NODE_TYPE##_list_insert_after(&list_copy, actual_this, to_insert_copy); \
+ return list_copy; \
+ } \
+ \
+ void NODE_TYPE##_list_remove(NODE_TYPE##_list* list, NODE_TYPE* to_remove){ \
+ REMOVE_LIST(NODE_TYPE, list, to_remove); \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_remove(NODE_TYPE##_list list, NODE_TYPE* to_remove){ \
+ int pos = NODE_TYPE##_list_get_item_position(&list, to_remove); \
+ NODE_TYPE##_list list_copy = NODE_TYPE##_list_shallow_copy(list); \
+ NODE_TYPE* actual_this = NODE_TYPE##_list_get_item_at_position(&list_copy, pos); \
+ NODE_TYPE##_list_remove(&list_copy, actual_this); \
+ return list_copy; \
+ } \
+ \
+ void NODE_TYPE##_list_replace(NODE_TYPE##_list* list, NODE_TYPE* to_replace, NODE_TYPE* replace_with){ \
+ REPLACE_LIST(NODE_TYPE, list, to_replace, replace_with); \
+ } \
+ \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_replace(NODE_TYPE##_list list, NODE_TYPE* to_replace, NODE_TYPE* replace_with){ \
+ int pos = NODE_TYPE##_list_get_item_position(&list, to_replace); \
+ NODE_TYPE##_list list_copy = NODE_TYPE##_list_shallow_copy(list); \
+ NODE_TYPE* actual_this = NODE_TYPE##_list_get_item_at_position(&list_copy, pos); \
+ NODE_TYPE* replace_with_copy = NODE_TYPE##_shallow_copy(replace_with); \
+ NODE_TYPE##_list_replace(&list_copy, actual_this, replace_with_copy); \
+ return list_copy; \
+ } \
+ \
+ void NODE_TYPE##_list_concat(NODE_TYPE##_list* list1, NODE_TYPE##_list* list2){ \
+ CONCAT_LIST(NODE_TYPE, list1, list2); \
+ } \
+ NODE_TYPE##_list NODE_TYPE##_list_copy_concat(NODE_TYPE##_list list1, NODE_TYPE##_list list2){ \
+ NODE_TYPE##_list list1_copy = NODE_TYPE##_list_shallow_copy(list1); \
+ NODE_TYPE##_list list2_copy = NODE_TYPE##_list_shallow_copy(list2); \
+ CONCAT_LIST(NODE_TYPE, &list1_copy, &list2_copy); \
+ return list1_copy; \
+ } \
+ \
+ size_t NODE_TYPE##_list_length(NODE_TYPE##_list list){ \
+ NODE_TYPE* current = list.head; \
+ size_t count = 0; \
+ while(current != NULL){ \
+ count = count + 1; \
+ current = current->next; \
+ } \
+ return count; \
+ }
+
+/* void print_string_list(string_list n){ */
+/* string_list_item* current = n.head; */
+/* printf("START\n"); */
+/* while(current != NULL){ */
+/* printf("%s\n", current->str); */
+/* current = current->next; */
+/* } */
+/* printf("END\n"); */
+/* } */
+
+#endif //YIELDING_C_FUN_LISTS_H
diff --git a/erts/lib_src/yielding_c_fun/ycf_main.c b/erts/lib_src/yielding_c_fun/ycf_main.c
new file mode 100644
index 0000000000..2287db8161
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_main.c
@@ -0,0 +1,330 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+
+#include "ycf_utils.h"
+#include "ycf_yield_fun.h"
+#include "ycf_node.h"
+#include "lib/simple_c_gc/simple_c_gc.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+char* file_to_str(const char* filename) {
+ char * buffer;
+ long length;
+ FILE * f = fopen (filename, "rb");
+
+ if (f) {
+ fseek (f, 0, SEEK_END);
+ length = ftell (f);
+ fseek (f, 0, SEEK_SET);
+ buffer = ycf_malloc (length+1);
+ size_t nr_of_read_bytes =
+ fread (buffer, 1, length, f);
+ if (nr_of_read_bytes != length) {
+ printf("error: while reading file %s\n", filename);
+ exit (1);
+ }
+ fclose (f);
+ buffer[length] = 0;
+ } else {
+ printf("error: could not open file %s\n", filename);
+ exit(1);
+ }
+
+ return buffer;
+}
+
+void str_to_file(const char *filepath, const char *data)
+{
+ FILE *fp = fopen(filepath, "w");
+ if (fp != NULL)
+ {
+ fputs(data, fp);
+ fclose(fp);
+ }
+}
+
+void parse_and_repeat_src_from_ast(const char* file_name){
+ char* content = file_to_str(file_name);
+ ycf_node* tree = ycf_node_from_string(content);
+ ycf_node_print(tree, NULL);
+}
+
+void parse_and_print_symbols(const char* file_name){
+ char* content = file_to_str(file_name);
+ ycf_symbol_list_print(content);
+}
+
+void parse_and_print_ast(const char* file_name){
+ char* content = file_to_str(file_name);
+ ycf_node* tree = ycf_node_from_string(content);
+ print_abstract_syntax_tree(tree);
+}
+
+void print_help_text_and_exit(char* program_name, int error_code) {
+ printf("Usage: %s [-h]\n"
+ " %s [-use_gc [-print_gc_info]]\n"
+ " [-log_max_mem_usage log_file]\n"
+ " [(( -f | -frec | -fnoauto ) function_name)...\n"
+ " [-output_file_name output_file]\n"
+ " [-header_file_name header_file]\n"
+ " [-debug]\n"
+ " [-only_yielding_funs]\n"
+ " [-static_aux_funs]\n"
+ " input_c_file]]\n"
+ "\n"
+ "Please see the README.md file for more details.\n",
+ program_name,
+ program_name);
+ exit(0);
+}
+
+int ycf_main( int argc, char* argv[] )
+{
+ int i = 1;
+ for(i = 1; i < argc; i++ ){
+ bool repeat = ycf_string_is_equal("-repeat", argv[i]);
+ bool print_symbols = ycf_string_is_equal("-print_symbols", argv[i]);
+ bool print_ast = ycf_string_is_equal("-print_ast", argv[i]);;
+ bool yield = ycf_string_is_equal("-yield", argv[i]);
+ if(repeat || print_symbols || print_ast || yield){
+ i++;
+ if(i >= argc){
+ printf("ERROR: Expected at least one more argument\n\n");
+ print_help_text_and_exit(argv[0], 1);
+ }
+ }
+ if (print_ast) {
+ parse_and_print_ast(argv[i]);
+ } else if (repeat) {
+ parse_and_repeat_src_from_ast(argv[i]);
+ } else if (print_symbols) {
+ parse_and_print_symbols(argv[i]);
+ } else /* Default is yield */ {
+ ycf_string_item_list funs_to_yield = ycf_string_item_list_empty();
+ ycf_string_item_list funs_to_yield_no_auto = ycf_string_item_list_empty();
+ ycf_string_item_list funs_to_yield_frec = ycf_string_item_list_empty();
+ ycf_string_item_list all_yield_funs = ycf_string_item_list_empty();
+ char* header_file_name = NULL;
+ char* output_file_name = NULL;
+ bool debug = false;
+ bool only_yielding_funs = false;
+ bool static_aux_funs = false;
+ while(i < argc && (ycf_string_is_equal(argv[i], "-f") ||
+ ycf_string_is_equal(argv[i], "-frec") ||
+ ycf_string_is_equal(argv[i], "-fnoauto") ||
+ ycf_string_is_equal(argv[i], "-header_file_name") ||
+ ycf_string_is_equal(argv[i], "-output_file_name") ||
+ ycf_string_is_equal(argv[i], "-debug") ||
+ ycf_string_is_equal(argv[i], "-only_yielding_funs") ||
+ ycf_string_is_equal(argv[i], "-static_aux_funs"))){
+ bool frec = ycf_string_is_equal(argv[i], "-frec");
+ bool noauto = ycf_string_is_equal(argv[i], "-fnoauto");
+ bool header = ycf_string_is_equal(argv[i], "-header_file_name");
+ bool output = ycf_string_is_equal(argv[i], "-output_file_name");
+ i++;
+ if(ycf_string_is_equal(argv[i-1], "-debug")){
+ debug = true;
+ continue;
+ }
+ if(ycf_string_is_equal(argv[i-1], "-only_yielding_funs")){
+ only_yielding_funs = true;
+ continue;
+ }
+ if(ycf_string_is_equal(argv[i-1], "-static_aux_funs")){
+ static_aux_funs = true;
+ continue;
+ }
+ if(i >= argc){
+ fprintf(stderr, "ERROR: Expected a name after %s\n\n", argv[i-1]);
+ print_help_text_and_exit(argv[0], 1);
+ }
+ if(header){
+ if(header_file_name != NULL){
+ fprintf(stderr, "ERROR: Can only print a single header file\n\n");
+ print_help_text_and_exit(argv[0], 1);
+ }
+ header_file_name = (char*)argv[i];
+ } else if(output){
+ if(output_file_name != NULL){
+ fprintf(stderr, "ERROR: Can only print a single output file\n\n");
+ print_help_text_and_exit(argv[0], 1);
+ }
+ output_file_name = (char*)argv[i];
+ } else if(frec){
+ ycf_string_item_list_append(&funs_to_yield_frec, ycf_string_item_new((char *) argv[i]));
+ } else if(noauto){
+ ycf_string_item_list_append(&funs_to_yield_no_auto, ycf_string_item_new((char *) argv[i]));
+ } else{
+ ycf_string_item_list_append(&funs_to_yield, ycf_string_item_new((char *) argv[i]));
+ }
+ i++;
+ }
+ ycf_string_item_list funs_to_yield_copy = ycf_string_item_list_shallow_copy(funs_to_yield);
+ ycf_string_item_list funs_to_yield_no_auto_copy = ycf_string_item_list_shallow_copy(funs_to_yield_no_auto);
+ ycf_string_item_list funs_to_yield_frec_copy = ycf_string_item_list_shallow_copy(funs_to_yield_frec);
+ ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_copy);
+ ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_no_auto_copy);
+ ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_frec_copy);
+ if(funs_to_yield.head == NULL && funs_to_yield_no_auto.head == NULL && funs_to_yield_frec.head == NULL){
+ fprintf(stderr, "ERROR: Expected at least one \"(-f|-frec|-fnoauto) function_name\" argument\n\n");
+ print_help_text_and_exit(argv[0], 1);
+ }
+ if(i >= argc){
+ fprintf(stderr, "ERROR: Expected an input file name as the last parameter\n\n");
+ print_help_text_and_exit(argv[0], 1);
+ }
+ {
+ char* file_name = (char*)argv[i];
+ char* src = file_to_str(file_name);
+ ycf_string_item* current_fun = funs_to_yield.head;
+ ycf_node* header_file = ycf_node_from_string("");
+ ycf_node* tree = ycf_node_from_string(src);
+ ycf_node* only_yielding_funs_tree = NULL;
+ while(current_fun != NULL){
+ tree = ast_get_ast_with_yieldified_function(tree,
+ header_file,
+ current_fun->str,
+ &all_yield_funs,
+ true,
+ false,
+ debug,
+ only_yielding_funs,
+ &only_yielding_funs_tree,
+ static_aux_funs);
+ current_fun = current_fun->next;
+ }
+ current_fun = funs_to_yield_no_auto.head;
+ while(current_fun != NULL){
+ tree = ast_get_ast_with_yieldified_function(tree,
+ header_file,
+ current_fun->str,
+ &all_yield_funs,
+ false,
+ false,
+ debug,
+ only_yielding_funs,
+ &only_yielding_funs_tree,
+ static_aux_funs);
+ current_fun = current_fun->next;
+ }
+ current_fun = funs_to_yield_frec.head;
+ while(current_fun != NULL){
+ tree = ast_get_ast_with_yieldified_function(tree,
+ header_file,
+ current_fun->str,
+ &all_yield_funs,
+ true,
+ true,
+ debug,
+ only_yielding_funs,
+ &only_yielding_funs_tree,
+ static_aux_funs);
+ current_fun = current_fun->next;
+ }
+ ast_add_yield_code_generated_define(tree, debug);
+ ast_add_yield_code_generated_define(header_file, debug);
+ if(only_yielding_funs){
+ ast_add_yield_code_generated_define(only_yielding_funs_tree, debug);
+ }
+ if(header_file_name != NULL){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ ycf_node_print(header_file, b);
+ str_to_file(header_file_name, b->buffer);
+ }
+ if(only_yielding_funs){
+ tree = only_yielding_funs_tree;
+ }
+ if(output_file_name != NULL){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ ycf_node_print(tree, b);
+ str_to_file(output_file_name, b->buffer);
+ } else {
+ ycf_node_print(tree, NULL);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+bool is_help_option(char* string) {
+return
+ ycf_string_is_equal("-h", string) ||
+ ycf_string_is_equal("--h", string) ||
+ ycf_string_is_equal("-help", string) ||
+ ycf_string_is_equal("--help", string);
+}
+
+int main( int argc, char* argv[] )
+{
+ bool log_max_mem_usage = false;
+ bool use_gc = false;
+ char * log_max_mem_usage_file = NULL;
+ int i = 1;
+ if (argc == 1) {
+ print_help_text_and_exit(argv[0], 0);
+ }
+ while(i < argc &&
+ (ycf_string_is_equal("-use_gc", argv[i]) ||
+ ycf_string_is_equal("-log_max_mem_usage", argv[i]) ||
+ ycf_string_is_equal("-print_gc_info", argv[i]) ||
+ is_help_option(argv[i]))) {
+ if (is_help_option(argv[i])) {
+ print_help_text_and_exit(argv[0], 0);
+ } else if (ycf_string_is_equal("-use_gc", argv[i])) {
+ use_gc = true;
+ i++;
+ } else if(ycf_string_is_equal("-print_gc_info", argv[i])) {
+ scgc_enable_print_gc_info();
+ i++;
+ } else if(ycf_string_is_equal(argv[i], "-log_max_mem_usage")) {
+ ycf_enable_memory_tracking();
+ log_max_mem_usage = true;
+ i++;
+ log_max_mem_usage_file = (char*)argv[i];
+ i++;
+ }
+ }
+ int nr_of_params_to_remove = i - 1;
+ int ret;
+ if (!use_gc) {
+ ret = ycf_main(argc - nr_of_params_to_remove ,
+ argv + nr_of_params_to_remove);
+ } else {
+ ycf_enable_gc();
+ ret = scgc_start_gced_code(ycf_main,
+ argc - nr_of_params_to_remove,
+ argv + nr_of_params_to_remove,
+ ycf_raw_malloc,
+ ycf_free);
+ }
+ if(log_max_mem_usage){
+ ycf_malloc_log(log_max_mem_usage_file, "all");
+ }
+ return ret;
+}
diff --git a/erts/lib_src/yielding_c_fun/ycf_node.c b/erts/lib_src/yielding_c_fun/ycf_node.c
new file mode 100644
index 0000000000..517c7e991d
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_node.c
@@ -0,0 +1,915 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "ycf_symbol.h"
+#include "ycf_node.h"
+#include "ycf_string.h"
+#include "ycf_lists.h"
+#include "ycf_yield_fun.h"
+#include "ycf_parser.h"
+
+GENERATE_LIST_FUNCTIONS(ycf_node)
+
+#define YCF_UNIQ_VARIABLE_NAME_NUMBER_PREFIX "_N"
+
+static int ycf_uniq_variable_name_number_counter = 0;
+
+static void uniqify_local_vars_in_node_rename_var_helper(ycf_node* n,
+ char* old_name,
+ char* new_name);
+static void uniqify_local_vars_in_scope_rename_var_helper(ycf_node_code_scope* s,
+ char* old_name,
+ char* new_name);
+
+
+static void uniqify_local_vars_in_expression_rename_var_helper(ycf_node_expression* n,
+ char* old_name,
+ char* new_name){
+ ycf_node* current = n->content.head;
+ while(current != NULL){
+ uniqify_local_vars_in_node_rename_var_helper(current,
+ old_name,
+ new_name);
+ current = current->next;
+ }
+}
+
+static void uniqify_local_vars_in_paran_expression_rename_var_helper(ycf_node_parentheses_expression* n,
+ char* old_name,
+ char* new_name){
+ uniqify_local_vars_in_expression_rename_var_helper(&n->content,
+ old_name,
+ new_name);
+}
+
+static void uniqify_local_vars_in_fun_call_rename_var_helper(ycf_node_function_call* n,
+ char* old_name,
+ char* new_name)
+{
+ ycf_node* e = n->parameter_expressions.head;
+ while(e != NULL){
+ uniqify_local_vars_in_node_rename_var_helper(e, old_name, new_name);
+ e = e->next;
+ }
+ if(ycf_symbol_is_text_eq(n->identifier, old_name)){
+ n->identifier = ycf_symbol_copy_change_text(n->identifier, new_name);
+ }
+}
+
+static void uniqify_local_vars_in_assignment_fun_call_rename_var_helper(ycf_node_function_call_assignment* n,
+ char* old_name,
+ char* new_name)
+{
+ uniqify_local_vars_in_expression_rename_var_helper(&n->left_side, old_name, new_name);
+ uniqify_local_vars_in_fun_call_rename_var_helper(&n->fun_call, old_name, new_name);
+}
+
+static void uniqify_local_vars_in_node_rename_var_helper(ycf_node* n,
+ char* old_name,
+ char* new_name){
+ if(n == NULL){
+ return;
+ } else if(n->type == ycf_node_type_code_scope){
+ uniqify_local_vars_in_scope_rename_var_helper(&n->u.code_scope, old_name, new_name);
+ } else if(n->type == ycf_node_type_on_restore_yield_state_code ||
+ n->type == ycf_node_type_on_save_yield_state_code ||
+ n->type == ycf_node_type_on_destroy_state_code ||
+ n->type == ycf_node_type_on_return_code ||
+ n->type == ycf_node_type_on_destroy_state_or_return_code){
+ uniqify_local_vars_in_scope_rename_var_helper(&n->u.special_code_block.code.if_statement->u.code_scope, old_name, new_name);
+ } else if(n->type == ycf_node_type_other &&
+ n->u.other.what->type == ycf_symbol_type_identifier &&
+ ycf_symbol_is_text_eq(n->u.other.what, old_name)){
+ n->u.other.what =
+ ycf_symbol_copy_change_text(n->u.other.what, new_name);
+ } else if(n->type == ycf_node_type_assignment){
+ uniqify_local_vars_in_expression_rename_var_helper(&n->u.a.left_side, old_name, new_name);
+ uniqify_local_vars_in_expression_rename_var_helper(&n->u.a.right_side, old_name, new_name);
+ } else if (n->type == ycf_node_type_function_call){
+ uniqify_local_vars_in_fun_call_rename_var_helper(&n->u.function_call, old_name, new_name);
+ } else if (n->type == ycf_node_type_statement){
+ ycf_node* e = n->u.statement.expression;
+ uniqify_local_vars_in_node_rename_var_helper(e, old_name, new_name);
+ } else if (n->type == ycf_node_type_return_statement && n->u.return_n.return_expression != NULL){
+ ycf_node* e = n->u.return_n.return_expression;
+ uniqify_local_vars_in_node_rename_var_helper(e, old_name, new_name);
+ } else if (n->type == ycf_node_type_expression){
+ uniqify_local_vars_in_expression_rename_var_helper(&n->u.expression, old_name, new_name);
+ } else if (n->type == ycf_node_type_assignment_function_call){
+ uniqify_local_vars_in_assignment_fun_call_rename_var_helper(&n->u.function_call_assignment, old_name, new_name);
+ }else if (n->type == ycf_node_type_parentheses_expression){
+ uniqify_local_vars_in_paran_expression_rename_var_helper(&n->u.parentheses_expression, old_name, new_name);
+ } else if (n->type == ycf_node_type_if){
+ uniqify_local_vars_in_paran_expression_rename_var_helper(&n->u.if_n.expression, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.if_n.if_statement, old_name, new_name);
+ } else if (n->type == ycf_node_type_if_else){
+ uniqify_local_vars_in_paran_expression_rename_var_helper(&n->u.if_else.if_part.expression, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.if_else.if_part.if_statement, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.if_else.else_statement, old_name, new_name);
+ } else if (n->type == ycf_node_type_while){
+ uniqify_local_vars_in_paran_expression_rename_var_helper(&n->u.while_n.expression, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.while_n.statement, old_name, new_name);
+ } else if (n->type == ycf_node_type_do_while){
+ uniqify_local_vars_in_paran_expression_rename_var_helper(&n->u.do_while.expression, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.do_while.statement, old_name, new_name);
+ } else if (n->type == ycf_node_type_switch){
+ uniqify_local_vars_in_paran_expression_rename_var_helper(&n->u.switch_n.expression, old_name, new_name);
+ uniqify_local_vars_in_scope_rename_var_helper(&n->u.switch_n.scope, old_name, new_name);
+ } else if (n->type == ycf_node_type_for){
+ uniqify_local_vars_in_node_rename_var_helper(n->u.for_n.init, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.for_n.stop_cond, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.for_n.end_exp, old_name, new_name);
+ uniqify_local_vars_in_node_rename_var_helper(n->u.for_n.statement, old_name, new_name);
+ }
+}
+
+static void uniqify_local_vars_in_scope_rename_var_helper(ycf_node_code_scope* s,
+ char* old_name,
+ char* new_name){
+ ycf_node* current = s->other_nodes.head;
+ while(current != NULL){
+ uniqify_local_vars_in_node_rename_var_helper(current, old_name, new_name);
+ current = current->next;
+ }
+}
+
+
+
+static void uniqify_definitions_in_scope(ycf_node_list* definition_nodes, ycf_node_code_scope* s){
+ ycf_node* current = definition_nodes->head;
+ while(current != NULL){
+ ycf_symbol * old_symbol = NULL;
+ if(current->type == ycf_node_type_variable_definition){
+ old_symbol = current->u.definition.identifier;
+ }else if(current->type == ycf_node_type_variable_definition_init){
+ old_symbol = current->u.definition_init.definition.identifier;
+ }
+ ycf_uniq_variable_name_number_counter++;
+ {
+ char* old_name = ycf_symbol_get_text(old_symbol);
+ char* new_name = ycf_string_new("%s%s%lu", old_name, YCF_UNIQ_VARIABLE_NAME_NUMBER_PREFIX,
+ ycf_uniq_variable_name_number_counter);
+ if(current->type == ycf_node_type_variable_definition){
+ current->u.definition.identifier = ycf_symbol_copy_change_text(old_symbol, new_name);
+ }else if(current->type == ycf_node_type_variable_definition_init){
+ current->u.definition_init.definition.identifier = ycf_symbol_copy_change_text(old_symbol, new_name);
+ }
+ uniqify_local_vars_in_scope_rename_var_helper(s, old_name, new_name);
+ current = current->next;
+ }
+ }
+}
+
+static void uniqify_local_vars_in_scope(ycf_node_code_scope* s);
+
+static void uniqify_local_vars_in_node(ycf_node* n){
+ if(n->type == ycf_node_type_code_scope){
+ uniqify_local_vars_in_scope(&n->u.code_scope);
+ } else if(n->type == ycf_node_type_on_restore_yield_state_code){
+ uniqify_local_vars_in_scope(&n->u.special_code_block.code.if_statement->u.code_scope);
+ } else if(n->type == ycf_node_type_on_save_yield_state_code ||
+ n->type == ycf_node_type_on_save_yield_state_code ||
+ n->type == ycf_node_type_on_destroy_state_code ||
+ n->type == ycf_node_type_on_return_code ||
+ n->type == ycf_node_type_on_destroy_state_or_return_code){
+ uniqify_local_vars_in_scope(&n->u.special_code_block.code.if_statement->u.code_scope);
+ } else if (n->type == ycf_node_type_if){
+ uniqify_local_vars_in_node(n->u.if_n.if_statement);
+ } else if (n->type == ycf_node_type_if_else){
+ uniqify_local_vars_in_node(n->u.if_else.if_part.if_statement);
+ uniqify_local_vars_in_node(n->u.if_else.else_statement);
+ } else if (n->type == ycf_node_type_while){
+ uniqify_local_vars_in_node(n->u.while_n.statement);
+ } else if (n->type == ycf_node_type_do_while){
+ uniqify_local_vars_in_node(n->u.do_while.statement);
+ } else if (n->type == ycf_node_type_switch){
+ uniqify_local_vars_in_scope(&n->u.switch_n.scope);
+ } else if (n->type == ycf_node_type_for){
+ uniqify_local_vars_in_node(n->u.for_n.statement);
+ }
+}
+
+static void uniqify_local_vars_in_scope(ycf_node_code_scope* s){
+ ycf_node* current = s->other_nodes.head;
+ while(current != NULL){
+ uniqify_local_vars_in_node(current);
+ current = current->next;
+ }
+ uniqify_definitions_in_scope(&s->definition_nodes, s);
+}
+
+void ycf_uniqify_local_vars_in_function(ycf_node* function){
+ uniqify_local_vars_in_scope(&function->u.function.body);
+ uniqify_definitions_in_scope(&function->u.function.definition.parameters,
+ &function->u.function.body);
+}
+
+
+ycf_node* ycf_node_new_assignment_from_definition_init(ycf_node_definition_init* n){
+ ycf_node* res = ycf_malloc(sizeof(ycf_node));
+ res->type = ycf_node_type_assignment;
+ res->next = NULL;
+ res->u.a.assignment_symbol = n->definition.end;
+ {
+ ycf_symbol* ident = ycf_symbol_copy(n->definition.identifier);
+ ident->whitespace_or_comment_before =
+ n->definition.type_specifiers.head->whitespace_or_comment_before;
+ res->u.a.left_side = parse_expression(ident).result->u.expression;
+ }
+ res->u.a.right_side = parse_expression(n->initializer_expression.head).result->u.expression;
+ res->u.a.end = ycf_symbol_new_semicolon();
+ return res;
+}
+
+ycf_node* ycf_node_new_definition_from_definition_init(ycf_node_definition_init* n){
+ ycf_node* res = ycf_malloc(sizeof(ycf_node));
+ res->type = ycf_node_type_variable_definition;
+ res->next = NULL;
+ res->u.definition = n->definition;
+ res->u.definition.end = ycf_symbol_new_semicolon();
+ return res;
+}
+
+ycf_node* ycf_node_code_scope_shallow_copy(ycf_node* n){
+ ycf_node* new_scope = ycf_node_shallow_copy(n);
+ new_scope->u.code_scope.definition_nodes = ycf_node_list_shallow_copy(new_scope->u.code_scope.definition_nodes);
+ new_scope->u.code_scope.other_nodes = ycf_node_list_shallow_copy(new_scope->u.code_scope.other_nodes);
+ return new_scope;
+}
+
+
+void ycf_node_search_and_replace_statements_in_node(ycf_node* n, ycf_node* (*replacer) (ycf_node*,
+ ycf_node_code_scope*,
+ void*), void* context,
+ ycf_node_code_scope* s){
+ if(n->type == ycf_node_type_code_scope){
+ ycf_node_search_and_replace_statements_in_scope(&n->u.code_scope, replacer, context);
+ } else if(n->type == ycf_node_type_on_destroy_state_code ||
+ n->type == ycf_node_type_on_restore_yield_state_code ||
+ n->type == ycf_node_type_on_save_yield_state_code ||
+ n->type == ycf_node_type_on_destroy_state_or_return_code ||
+ n->type == ycf_node_type_on_return_code) {
+ ycf_node* replace_candidate = n->u.special_code_block.code.if_statement;
+ ycf_node* possible_replacement = replacer(replace_candidate, s, context);
+ if(replace_candidate != possible_replacement){
+ n->u.special_code_block.code.if_statement = possible_replacement;
+ } else {
+ ycf_node_search_and_replace_statements_in_node(n->u.special_code_block.code.if_statement,
+ replacer,
+ context,
+ s);
+ }
+ } else if (n->type == ycf_node_type_if){
+ ycf_node_search_and_replace_statements_in_node(n->u.if_n.if_statement, replacer, context, s);
+ } else if (n->type == ycf_node_type_if_else){
+ ycf_node_search_and_replace_statements_in_node(n->u.if_else.if_part.if_statement, replacer, context, s);
+ ycf_node_search_and_replace_statements_in_node(n->u.if_else.else_statement, replacer, context, s);
+ } else if (n->type == ycf_node_type_while){
+ ycf_node_search_and_replace_statements_in_node(n->u.while_n.statement, replacer, context, s);
+ } else if (n->type == ycf_node_type_do_while){
+ ycf_node_search_and_replace_statements_in_node(n->u.do_while.statement, replacer, context, s);
+ } else if (n->type == ycf_node_type_switch){
+ ycf_node_search_and_replace_statements_in_scope(&n->u.switch_n.scope, replacer, context);
+ } else if (n->type == ycf_node_type_for){
+ ycf_node_search_and_replace_statements_in_node(n->u.for_n.statement, replacer, context, s);
+ }
+}
+
+void ycf_node_search_and_replace_statements_in_scope(ycf_node_code_scope* s,
+ ycf_node* (*replacer) (ycf_node* canditate,
+ ycf_node_code_scope* candidates_scope,
+ void* context),
+ void* context){
+ ycf_node* n = s->other_nodes.head;
+ while(n != NULL){
+ ycf_node* replace_candidate = n;
+ ycf_node* possible_replacement = replacer(replace_candidate, s, context);
+ if(replace_candidate != possible_replacement){
+ ycf_node_list_replace(&s->other_nodes, replace_candidate, possible_replacement);
+ } else {
+ ycf_node_search_and_replace_statements_in_node(n, replacer, context, s);
+ }
+ n = n->next;
+ }
+ return;
+}
+
+ycf_node_code_scope ycf_node_copy_search_and_replace_statements_in_scope(ycf_node_code_scope s,
+ ycf_node* (*replacer) (ycf_node*,
+ ycf_node_code_scope*,
+ void*),
+ void* context){
+ ycf_node_search_and_replace_statements_in_scope(&s, replacer, context);
+ return s;
+}
+
+char* ycf_node_to_string(ycf_node* n){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ ycf_node_print(n, b);
+ return b->buffer;
+}
+
+char* ycf_node_list_to_string(ycf_node_list* l){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ ycf_node* current = l->head;
+ while(current != NULL){
+ ycf_node_print(current, b);
+ current = current->next;
+ }
+ return b->buffer;
+}
+
+ycf_node* ycf_node_new_text_node(char* text){
+ ycf_node* n = ycf_node_new();
+ n->type = ycf_node_type_other;
+ n->u.other.what = ycf_symbol_new_something_else(text);
+ return n;
+}
+
+ycf_node* ycf_node_new(){
+ ycf_node* new = ycf_malloc(sizeof(ycf_node));
+ new->next = NULL;
+ return new;
+}
+
+ycf_node* ycf_node_find_function(ycf_node* c_file_node, char* fun_name){
+ ycf_node* current = c_file_node->u.c_file.content.head;
+ while(current != NULL){
+ if(current->type == ycf_node_type_function_definition &&
+ ycf_symbol_is_text_eq(current->u.function.definition.definition.identifier,
+ fun_name)){
+ return current;
+ }
+ current = current->next;
+ }
+ return NULL;
+}
+
+ycf_node* ycf_node_find_function_declaration(ycf_node* c_file_node, char* fun_name){
+ ycf_node* current = c_file_node->u.c_file.content.head;
+ while(current != NULL){
+ if(current->type == ycf_node_type_function_declaration &&
+ ycf_symbol_is_text_eq(current->u.function_definition.definition.identifier,
+ fun_name)){
+ return current;
+ }
+ current = current->next;
+ }
+ return NULL;
+}
+
+ycf_node* ycf_node_find_define_node(ycf_node* c_file_node, char* define_name){
+ ycf_node* current = c_file_node->u.c_file.content.head;
+ while(current != NULL){
+ if(current->type == ycf_node_type_other &&
+ ycf_symbol_is_text_eq(current->u.other.what,
+ ycf_string_new("#define %s", define_name))){
+ return current;
+ }
+ current = current->next;
+ }
+ return NULL;
+}
+
+bool ycf_node_is_void_ret_fun(ycf_node* f_node){
+ ycf_symbol_list type = f_node->u.function.definition.definition.type_specifiers;
+ return type.last->type == ycf_symbol_type_void;
+}
+
+ycf_node* ycf_node_get_from_code_scope_text(char* code){
+ char* f_code = ycf_string_new("void f(){\n"
+ "{\n"
+ "%s\n"
+ "}\n"
+ "}\n",
+ code);
+ ycf_symbol_list symbols = ycf_symbol_list_from_text(f_code);
+ ycf_node* tree = get_abstract_syntax_tree_root(&symbols);
+ if(tree->u.c_file.content.head->type != ycf_node_type_function_definition){
+ printf("NOT A FUNCTION\n");
+ exit(1);
+ }
+ return tree->u.c_file.content.head->u.function.body.other_nodes.head;
+}
+
+ycf_node* ycf_node_get_function_from_text(char* code){
+ char* f_code = ycf_string_new("%s",
+ code);
+ ycf_symbol_list symbols = ycf_symbol_list_from_text(f_code);
+ ycf_node* tree = get_abstract_syntax_tree_root(&symbols);
+ if(tree->u.c_file.content.head->type != ycf_node_type_function_definition){
+ printf("ycf_get_function_from_text: NOT A FUNCTION\n");
+ exit(1);
+ }
+ return tree->u.c_file.content.head;
+}
+
+ycf_node* ycf_node_from_string(char* src){
+ ycf_symbol_list symbols = ycf_symbol_list_from_text(src);
+ ycf_node* tree = get_abstract_syntax_tree_root(&symbols);
+ return tree;
+}
+
+ycf_node* mk_scope_wrapper(ycf_node* statement){
+ return ycf_node_get_from_code_scope_text(ycf_string_new("{\n"
+ " %s\n"
+ "}\n",
+ ycf_node_to_string(statement)));
+}
+
+static ycf_node* scope_inserter(ycf_node* candidate, ycf_node_code_scope* s, void* context){
+ (void)context;
+ (void)s;
+ if (candidate->type == ycf_node_type_while){
+ if(candidate->u.while_n.statement->type == ycf_node_type_code_scope){
+ ycf_node_insert_scopes_in_complex_statements(&candidate->u.while_n.statement->u.code_scope);
+ }
+ candidate->u.while_n.statement = mk_scope_wrapper(candidate->u.while_n.statement);
+ return candidate;
+ } else if (candidate->type == ycf_node_type_do_while){
+ if(candidate->u.do_while.statement->type == ycf_node_type_code_scope){
+ ycf_node_insert_scopes_in_complex_statements(&candidate->u.do_while.statement->u.code_scope);
+ }
+ candidate->u.do_while.statement = mk_scope_wrapper(candidate->u.do_while.statement);
+ return candidate;
+ } else if (candidate->type == ycf_node_type_for){
+ if(candidate->u.for_n.statement->type == ycf_node_type_code_scope){
+ ycf_node_insert_scopes_in_complex_statements(&candidate->u.for_n.statement->u.code_scope);
+ }
+ candidate->u.for_n.statement = mk_scope_wrapper(candidate->u.for_n.statement);
+ return candidate;
+ } else if (candidate->type == ycf_node_type_if){
+ if(candidate->u.if_n.if_statement->type == ycf_node_type_code_scope){
+ ycf_node_insert_scopes_in_complex_statements(&candidate->u.if_n.if_statement->u.code_scope);
+ }
+ candidate->u.if_n.if_statement = mk_scope_wrapper(candidate->u.if_n.if_statement);
+ return candidate;
+ } else if (candidate->type == ycf_node_type_if_else){
+ if(candidate->u.if_else.if_part.if_statement->type == ycf_node_type_code_scope){
+ ycf_node_insert_scopes_in_complex_statements(&candidate->u.if_else.if_part.if_statement->u.code_scope);
+ }
+ candidate->u.if_else.if_part.if_statement = mk_scope_wrapper(candidate->u.if_else.if_part.if_statement);
+ if(candidate->u.if_else.else_statement->type == ycf_node_type_code_scope){
+ ycf_node_insert_scopes_in_complex_statements(&candidate->u.if_else.else_statement->u.code_scope);
+ }
+ candidate->u.if_else.else_statement = mk_scope_wrapper(candidate->u.if_else.else_statement);
+ return candidate;
+ } else {
+ return candidate;
+ }
+}
+
+void ycf_node_insert_scopes_in_complex_statements(ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ scope_inserter,
+ NULL);
+}
+
+
+static ycf_node* scope_remover(ycf_node* candidate, ycf_node_code_scope* s, void* context){
+ uintptr_t* removed_scopes = context;
+ if(candidate->type == ycf_node_type_code_scope &&
+ ycf_node_list_length(candidate->u.code_scope.definition_nodes) == 0 &&
+ ycf_node_list_length(candidate->u.code_scope.other_nodes) == 1 &&
+ candidate->u.code_scope.other_nodes.head->type == ycf_node_type_code_scope) {
+ *removed_scopes = *removed_scopes + 1;
+ return candidate->u.code_scope.other_nodes.head;
+ }
+ return candidate;
+}
+
+void ycf_node_remove_unecessary_scopes(ycf_node_code_scope* s){
+ uintptr_t removed_scopes;
+ do{
+ removed_scopes = 0;
+ ycf_node_search_and_replace_statements_in_scope(s,
+ scope_remover,
+ &removed_scopes);
+ }while(removed_scopes > 0);
+}
+
+static ycf_node* for_declaration_normalizer(ycf_node* candidate,
+ ycf_node_code_scope* s,
+ void* context){
+ (void)context;
+ (void)s;
+ if (candidate->type == ycf_node_type_for){
+ if(candidate->u.for_n.init != NULL &&
+ (candidate->u.for_n.init->type == ycf_node_type_variable_definition ||
+ candidate->u.for_n.init->type == ycf_node_type_variable_definition_init)){
+ if(candidate->u.for_n.statement->type == ycf_node_type_code_scope){
+ ycf_node_normalize_for_var_declarations(&candidate->u.for_n.statement->u.code_scope);
+ }
+ ycf_string_printable_buffer * b = ycf_string_printable_buffer_new();
+ ycf_node_print(candidate->u.for_n.init, b);
+ candidate->u.for_n.init = ycf_node_statement_new(ycf_node_expression_new(ycf_node_list_empty()),
+ ycf_symbol_new_semicolon());
+ ycf_node_print(candidate, b);
+ return ycf_node_get_from_code_scope_text(b->buffer);
+ }else {
+ return candidate;
+ }
+
+ } else {
+ return candidate;
+ }
+}
+
+void ycf_node_normalize_for_var_declarations(ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ for_declaration_normalizer,
+ NULL);
+}
+
+
+
+static ycf_node* ycf_node_move_in_code_var_declarations_to_top_mover(ycf_node* candidate,
+ ycf_node_code_scope* candidates_scope,
+ void* context){
+ (void)context;
+ if (candidate->type == ycf_node_type_variable_definition) {
+ ycf_node_list_append(&candidates_scope->definition_nodes,
+ ycf_node_shallow_copy(candidate));
+ return ycf_node_get_from_code_scope_text(ycf_string_new("\n/* moved declaration (%s)*/\n",
+ ycf_symbol_get_text(candidate->u.definition.identifier)));
+ } else if (candidate->type == ycf_node_type_variable_definition_init) {
+ ycf_node_list_append(&candidates_scope->definition_nodes,
+ ycf_node_new_definition_from_definition_init(&candidate->u.definition_init));
+ return ycf_node_new_assignment_from_definition_init(&candidate->u.definition_init);
+ } else {
+ return candidate;
+ }
+}
+
+void ycf_node_move_in_code_var_declarations_to_top(ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ ycf_node_move_in_code_var_declarations_to_top_mover,
+ NULL);
+}
+
+static ycf_node* ycf_node_remove_declarations_in_scope_helper(ycf_node* candidate,
+ ycf_node_code_scope* candidates_scope,
+ void* context){
+ (void)context;
+ candidates_scope->definition_nodes = ycf_node_list_empty();
+ return candidate;
+}
+
+void ycf_node_remove_declarations_in_scope(ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ ycf_node_remove_declarations_in_scope_helper,
+ NULL);
+}
+
+static void normalize_init_definitions_in_scope_helper_insert_assignments(ycf_node* current_def,
+ ycf_node_list* other_nodes){
+ if(current_def == NULL){
+ return;
+ }
+ normalize_init_definitions_in_scope_helper_insert_assignments(current_def->next,
+ other_nodes);
+ if(current_def->type == ycf_node_type_variable_definition_init){
+ ycf_node* assignment = ycf_node_new_assignment_from_definition_init(&current_def->u.definition_init);
+ ycf_node_list_prepend(other_nodes, assignment);
+ return;
+ }else{
+ return;
+ }
+}
+
+static ycf_node* ycf_node_normalize_init_definitions_in_scope_helper(ycf_node* candidate,
+ ycf_node_code_scope* candidates_scope,
+ void* context){
+ (void)context;
+ (void)candidates_scope;
+ ycf_node_code_scope* s = NULL;
+ if(candidate == NULL){
+ s = context;
+ } else if(candidate->type == ycf_node_type_code_scope){
+ s = &candidate->u.code_scope;
+
+ } else if(candidate->type == ycf_node_type_switch){
+ s = &candidate->u.switch_n.scope;
+ }
+ if(s != NULL) {
+ ycf_node * current = s->definition_nodes.head;
+ normalize_init_definitions_in_scope_helper_insert_assignments(s->definition_nodes.head,
+ &s->other_nodes);
+ while (current != NULL) {
+ if (current->type == ycf_node_type_variable_definition_init) {
+ ycf_node *def_node = ycf_node_new_definition_from_definition_init(&current->u.definition_init);
+ ycf_node_list_replace(&s->definition_nodes, current, def_node);
+ }
+ current = current->next;
+ }
+ }
+ return candidate;
+}
+
+void ycf_node_normalize_init_definitions_in_scope(ycf_node_code_scope* s){
+ ycf_node_normalize_init_definitions_in_scope_helper(NULL,
+ NULL,
+ s);
+ ycf_node_search_and_replace_statements_in_scope(s,
+ ycf_node_normalize_init_definitions_in_scope_helper,
+ NULL);
+}
+
+
+static ycf_node* ycf_node_get_declarations_in_scope_helper(ycf_node* candidate,
+ ycf_node_code_scope* candidates_scope,
+ void* context){
+ ycf_node_list* list = (ycf_node_list*)context;
+ if(candidate->type == ycf_node_type_code_scope){
+ ycf_node_list to_append = ycf_node_list_shallow_copy(candidate->u.code_scope.definition_nodes);
+ ycf_node_list_concat(list, &to_append);
+ } else if(candidate->type == ycf_node_type_switch){
+ ycf_node_list to_append = ycf_node_list_shallow_copy(candidate->u.switch_n.scope.definition_nodes);
+ ycf_node_list_concat(list, &to_append);
+ }
+ return candidate;
+}
+
+ycf_node_list ycf_node_get_declarations_in_scope(ycf_node_code_scope* s){
+ ycf_node_list res = s->definition_nodes;
+ ycf_node_search_and_replace_statements_in_scope(s,
+ ycf_node_get_declarations_in_scope_helper,
+ &res);
+ return res;
+}
+
+ycf_node_list ycf_node_definition_list_from_string(char* str){
+ return ycf_node_get_from_code_scope_text(str)->u.code_scope.definition_nodes;
+}
+
+void ycf_node_rename_function(ycf_node_function* f, char* new_name){
+ f->definition.definition.identifier =
+ ycf_symbol_copy_change_text(f->definition.definition.identifier,
+ new_name);
+}
+
+static bool is_scope_ends_with_void_ret(ycf_node_code_scope* scope_node){
+ if(scope_node->other_nodes.last->type == ycf_node_type_code_scope){
+ return is_scope_ends_with_void_ret(&scope_node->other_nodes.last->u.code_scope);
+ }else{
+ ycf_node* prev = NULL;
+ ycf_node* current = scope_node->other_nodes.head;
+ while(current != NULL){
+ prev = current;
+ current = current->next;
+ }
+ return
+ prev != NULL &&
+ current != NULL &&
+ prev->type == ycf_node_type_other &&
+ prev->u.other.what->type == ycf_symbol_type_return &&
+ current->type == ycf_node_type_other &&
+ current->u.other.what->type == ycf_symbol_type_semicolon;
+ }
+}
+
+bool ycf_node_is_void_ret_ending_fun(ycf_node* f_node){
+ return is_scope_ends_with_void_ret(&f_node->u.function.body);
+}
+
+ycf_node_list ycf_node_get_all_definitions_in_function(ycf_node_function* f){
+ ycf_node_list all = ycf_node_get_declarations_in_scope(&f->body);
+ ycf_node_list all_copy = ycf_node_list_shallow_copy(all);
+ ycf_node_list params = f->definition.parameters;
+ ycf_node_list_concat(&all_copy, &params);
+ return all_copy;
+}
+
+void ycf_node_remove_const_specifiers_from_declaration(ycf_node* declaration){
+ ycf_symbol* current = declaration->u.definition.type_specifiers.head;
+ while(current != NULL) {
+ if(current->type == ycf_symbol_type_const){
+ ycf_symbol_list_remove(&declaration->u.definition.type_specifiers,
+ current);
+ }
+ current = current->next;
+ }
+}
+
+void ycf_node_remove_static_specifiers_from_declaration(ycf_node* declaration){
+ ycf_symbol* current = declaration->u.definition.type_specifiers.head;
+ while(current != NULL) {
+ if(current->type == ycf_symbol_type_static){
+ ycf_symbol_list_remove(&declaration->u.definition.type_specifiers,
+ current);
+ }
+ current = current->next;
+ }
+}
+
+void ycf_node_remove_inline_specifiers_from_declaration(ycf_node* declaration){
+ ycf_symbol* current = declaration->u.definition.type_specifiers.head;
+ while(current != NULL) {
+ if(current->type == ycf_symbol_type_inline){
+ ycf_symbol_list_remove(&declaration->u.definition.type_specifiers,
+ current);
+ }
+ current = current->next;
+ }
+}
+
+void ycf_node_remove_array_size_info_from_declaration(ycf_node* declaration){
+ ycf_node* current = declaration->u.definition.array_brackets.head;
+ while(current != NULL) {
+ current->u.array_bracket.empty = true;
+ current = current->next;
+ }
+}
+
+void ycf_node_modify_declarations(ycf_node_list declarations, void (*modifer)(ycf_node*)){
+ ycf_node* current = declarations.head;
+ while(current != NULL) {
+ modifer(current);
+ current = current->next;
+ }
+}
+
+ycf_symbol_list ycf_node_get_return_type(ycf_node* f_node_or_f_dec_node){
+ ycf_node_function_definition def;
+ ycf_node * tmp;
+ if (f_node_or_f_dec_node->type == ycf_node_type_function_declaration) {
+ def = f_node_or_f_dec_node->u.function_definition;
+ } else {
+ def = f_node_or_f_dec_node->u.function.definition;
+ }
+ tmp =
+ ycf_node_defenition_new(ycf_symbol_list_shallow_copy(def.definition.type_specifiers),
+ ycf_symbol_new_identifier(ycf_string_new("tmp")),
+ ycf_node_list_empty(),
+ ycf_symbol_new_semicolon());
+ ycf_node_remove_inline_specifiers_from_declaration(tmp);
+ ycf_node_remove_static_specifiers_from_declaration(tmp);
+ return tmp->u.definition.type_specifiers;
+}
+
+ycf_symbol_list ycf_node_find_function_return_type(ycf_node* c_file_node, char* fun_name)
+{
+ ycf_node* f_node_or_f_dec_node = ycf_node_find_function(c_file_node, fun_name);
+ if (f_node_or_f_dec_node == NULL) {
+ f_node_or_f_dec_node = ycf_node_find_function_declaration(c_file_node, fun_name);
+ }
+ if (f_node_or_f_dec_node == NULL) {
+ fprintf(stderr, "ycf_node_find_function_return_type: Could not find function declaration or definition: %s\n", fun_name);
+ exit(1);
+ }
+ return ycf_node_get_return_type(f_node_or_f_dec_node);
+}
+
+char* ycf_node_get_node_type_string(ycf_node_type t){
+ switch (t){
+ case ycf_node_type_c_file:
+ return "ycf_node_type_c_file";
+ case ycf_node_type_variable_definition:
+ return "ycf_node_type_variable_definition";
+ case ycf_node_type_variable_definition_init:
+ return "ycf_node_type_variable_definition_init";
+ case ycf_node_type_function_definition:
+ return "ycf_node_type_function_definition";
+ case ycf_node_type_function_declaration:
+ return "ycf_node_type_function_declaration";
+ case ycf_node_type_code_scope:
+ return "ycf_node_type_code_scope";
+ case ycf_node_type_other:
+ return "ycf_node_type_other";
+ case ycf_node_type_gen_typedef_struct:
+ return "ycf_node_type_gen_typedef_struct";
+ case ycf_node_type_expression:
+ return "ycf_node_type_expression";
+ case ycf_node_type_statement:
+ return "ycf_node_type_statement";
+ case ycf_node_type_return_statement:
+ return "ycf_node_type_return_statement";
+ case ycf_node_type_assignment:
+ return "ycf_node_type_assignment";
+ case ycf_node_type_yield:
+ return "ycf_node_type_yield";
+ case ycf_node_type_consume_reds:
+ return "ycf_node_type_consume_reds";
+ case ycf_node_type_goto:
+ return "ycf_node_type_goto";
+ case ycf_node_type_parentheses_expression:
+ return "ycf_node_type_parentheses_expression";
+ case ycf_node_type_function_call:
+ return "ycf_node_type_function_call";
+ case ycf_node_type_assignment_function_call:
+ return "ycf_node_type_assignment_function_call";
+ case ycf_node_type_while:
+ return "ycf_node_type_while";
+ case ycf_node_type_do_while:
+ return "ycf_node_type_do_while";
+ case ycf_node_type_for:
+ return "ycf_node_type_for";
+ case ycf_node_type_switch:
+ return "ycf_node_type_switch";
+ case ycf_node_type_if:
+ return "ycf_node_type_if";
+ case ycf_node_type_if_else:
+ return "ycf_node_type_if_else";
+ case ycf_node_type_comma:
+ return "ycf_node_type_comma";
+ case ycf_node_type_array_bracket:
+ return "ycf_node_type_array_bracket";
+ case ycf_node_type_macro_cmd:
+ return "ycf_node_type_macro_cmd";
+ case ycf_node_type_period_field_access:
+ return "ycf_node_type_period_field_access";
+ case ycf_node_type_pointer_field_access:
+ return "ycf_node_type_pointer_field_access";
+ case ycf_node_type_on_save_yield_state_code:
+ return "ycf_node_type_on_save_yield_state_code";
+ case ycf_node_type_on_restore_yield_state_code:
+ return "ycf_node_type_on_restore_yield_state_code";
+ case ycf_node_type_on_destroy_state_code:
+ return "ycf_node_type_on_destroy_state_code";
+ case ycf_node_type_on_return_code:
+ return "ycf_node_type_on_return_code";
+ case ycf_node_type_on_destroy_state_or_return_code:
+ return "ycf_node_type_on_destroy_state_or_return_code";
+ }
+ return "unrecognized type";
+}
+
+void ycf_node_print_node_type(ycf_node_type t){
+ printf("%s\n",ycf_node_get_node_type_string(t));
+}
+
+ycf_node_assignment* ycf_node_get_assignment(ycf_node* n) {
+ if(n->type == ycf_node_type_assignment){
+ return &n->u.a;
+ } else if (n->type == ycf_node_type_statement &&
+ n->u.statement.expression->u.expression.content.head->type == ycf_node_type_assignment){
+ return &n->u.statement.expression->u.expression.content.head->u.a;
+ } else {
+ fprintf(stderr,
+ "Trying to get %s from a node of type %s\n",
+ "ycf_node_type_assignment",
+ ycf_node_get_node_type_string(n->type));
+ exit(1);
+ }
+}
+
+void ycf_node_normalize_function(ycf_node* fun){
+ /* Remove array size info from parameters */
+ ycf_node_modify_declarations(fun->u.function.definition.parameters,
+ ycf_node_remove_array_size_info_from_declaration);
+ /* Insert scope in nest statements (e.g., if(1) print(); -> if(1) {print();}) */
+ ycf_node_insert_scopes_in_complex_statements(&fun->u.function.body);
+ /* Move out declarations from for loops */
+ ycf_node_normalize_for_var_declarations(&fun->u.function.body);
+ /* Move in code declations to top of scope */
+ ycf_node_move_in_code_var_declarations_to_top(&fun->u.function.body);
+ /* Normalize declarations */
+ ycf_node_normalize_init_definitions_in_scope(&fun->u.function.body);
+ /* Uniqify local variables */
+ ycf_uniqify_local_vars_in_function(fun);
+ /* Save scope declarations and function declarations (includes
+ parameters) */
+ ycf_node_list scope_defs = ycf_node_get_declarations_in_scope(&fun->u.function.body);
+ scope_defs = ycf_node_list_shallow_copy(scope_defs);
+ ycf_node_list defs = ycf_node_get_all_definitions_in_function(&fun->u.function);
+ defs = ycf_node_list_shallow_copy(defs);
+ /* Remove const from const declarations */
+ ycf_node_modify_declarations(defs, ycf_node_remove_const_specifiers_from_declaration);
+ ycf_node_modify_declarations(scope_defs, ycf_node_remove_const_specifiers_from_declaration);
+ ycf_node_modify_declarations(fun->u.function.definition.parameters,
+ ycf_node_remove_const_specifiers_from_declaration);
+ /* Move all declarations to top scope */
+ ycf_node_remove_declarations_in_scope(&fun->u.function.body);
+ fun->u.function.body.definition_nodes = scope_defs;
+ /* Add return statement if function is missing return statement */
+ if(ycf_node_is_void_ret_fun(fun) &&
+ !ycf_node_is_void_ret_ending_fun(fun)){
+ ycf_node_list_append(&fun->u.function.body.other_nodes,
+ ycf_node_get_from_code_scope_text("return;"));
+ }
+ ycf_node_remove_unecessary_scopes(&fun->u.function.body);
+}
diff --git a/erts/lib_src/yielding_c_fun/ycf_node.h b/erts/lib_src/yielding_c_fun/ycf_node.h
new file mode 100644
index 0000000000..d230a1a2c2
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_node.h
@@ -0,0 +1,455 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#ifndef YIELDING_C_FUN_YCF_NODE_FUNS_H
+#define YIELDING_C_FUN_YCF_NODE_FUNS_H
+
+#include "ycf_utils.h"
+#include "ycf_string.h"
+#include "ycf_symbol.h"
+
+/* Types for nodes */
+typedef enum {
+ ycf_node_type_c_file,
+ ycf_node_type_variable_definition,
+ ycf_node_type_variable_definition_init,
+ ycf_node_type_function_definition,
+ ycf_node_type_function_declaration,
+ ycf_node_type_code_scope,
+ ycf_node_type_other,
+ ycf_node_type_gen_typedef_struct,
+ ycf_node_type_expression,
+ ycf_node_type_statement,
+ ycf_node_type_return_statement,
+ ycf_node_type_assignment,
+ ycf_node_type_yield,
+ ycf_node_type_consume_reds,
+ ycf_node_type_goto,
+ ycf_node_type_parentheses_expression,
+ ycf_node_type_function_call,
+ ycf_node_type_assignment_function_call,
+ ycf_node_type_while,
+ ycf_node_type_do_while,
+ ycf_node_type_for,
+ ycf_node_type_switch,
+ ycf_node_type_if,
+ ycf_node_type_if_else,
+ ycf_node_type_comma,
+ ycf_node_type_array_bracket,
+ ycf_node_type_macro_cmd,
+ ycf_node_type_period_field_access,
+ ycf_node_type_pointer_field_access,
+ ycf_node_type_on_save_yield_state_code,
+ ycf_node_type_on_restore_yield_state_code,
+ ycf_node_type_on_destroy_state_code,
+ ycf_node_type_on_return_code,
+ ycf_node_type_on_destroy_state_or_return_code
+} ycf_node_type;
+
+struct ycf_node;
+
+typedef struct {
+ struct ycf_node* head;
+ struct ycf_node* last;
+} ycf_node_list;
+
+typedef struct {
+ ycf_node_list content;
+} ycf_node_c_file;
+
+typedef struct {
+ ycf_node_list content;
+ ycf_symbol* end_symbol;
+} ycf_node_expression;
+
+typedef struct {
+ ycf_symbol* start_symbol;
+ ycf_node_expression content;
+ ycf_symbol* end_symbol;
+} ycf_node_parentheses_expression;
+
+typedef struct {
+ ycf_symbol_list neg_symbols;
+ ycf_symbol* identifier;
+ ycf_symbol* start_symbol;
+ ycf_node_list parameter_expressions;
+ ycf_symbol* end_symbol;
+} ycf_node_function_call;
+
+typedef struct array_bracket {
+ ycf_symbol* start;
+ bool empty;
+ ycf_node_expression content;
+ ycf_symbol* end;
+} ycf_node_array_bracket;
+
+
+typedef struct {
+ ycf_symbol_list type_specifiers;
+ ycf_symbol* identifier;
+ ycf_node_list array_brackets;
+ ycf_symbol* end;
+} ycf_node_definition;
+
+typedef struct {
+ ycf_node_definition definition;
+ ycf_symbol_list initializer_expression;
+ ycf_symbol* end;
+} ycf_node_definition_init;
+
+typedef struct {
+ struct ycf_node* expression;
+ ycf_symbol* end_symbol;
+} ycf_node_statement;
+
+typedef struct {
+ ycf_node_list definition_nodes;
+ ycf_node_list other_nodes;
+ ycf_symbol* start;
+ ycf_symbol* end;
+} ycf_node_code_scope;
+
+typedef struct {
+ ycf_symbol* while_word;
+ ycf_node_parentheses_expression expression;
+ struct ycf_node* statement;
+} ycf_node_while;
+
+typedef struct {
+ ycf_symbol* do_word;
+ struct ycf_node* statement;
+ ycf_symbol* while_word;
+ ycf_node_parentheses_expression expression;
+ ycf_symbol* end;
+} ycf_node_do_while;
+
+typedef struct {
+ ycf_symbol* for_word;
+ ycf_symbol* start_parentheses;
+ struct ycf_node* init;
+ struct ycf_node* stop_cond;
+ ycf_symbol* stop_cond_end;
+ struct ycf_node* end_exp;
+ ycf_symbol* end_parentheses;
+ struct ycf_node* statement;
+} ycf_node_for;
+
+typedef struct {
+ ycf_symbol* switch_word;
+ ycf_node_parentheses_expression expression;
+ ycf_node_code_scope scope;
+} ycf_node_switch;
+
+typedef struct {
+ ycf_symbol* if_word;
+ ycf_node_parentheses_expression expression;
+ struct ycf_node* if_statement;
+} ycf_node_if;
+
+typedef struct {
+ ycf_node_if if_part;
+ ycf_symbol* else_word;
+ struct ycf_node* else_statement;
+} ycf_node_if_else;
+
+typedef struct {
+ ycf_node_expression left_side;
+ ycf_symbol* assignment_symbol;
+ ycf_node_expression right_side;
+ ycf_symbol* end;
+} ycf_node_assignment;
+
+/*typedef struct {
+ ycf_symbol* id;
+} ycf_node_identifier;*/
+
+typedef struct {
+ ycf_symbol* yield_symbol;
+ ycf_symbol* end_symbol;
+} ycf_node_yield;
+
+typedef struct {
+ ycf_symbol* consume_reds_symbol;
+ ycf_node_parentheses_expression nr_of_reds_expression;
+ ycf_symbol* end_symbol;
+} ycf_node_consume_reds;
+
+typedef struct {
+ ycf_symbol* what;
+} ycf_node_other;
+
+typedef struct {
+ ycf_node_definition definition;
+ int ignore_param_ending;
+ ycf_node_list parameters;
+ ycf_symbol_list end;
+} ycf_node_function_definition;
+
+typedef struct {
+ ycf_node_function_definition definition;
+ ycf_node_code_scope body;
+} ycf_node_function;
+
+typedef struct {
+ ycf_node_expression left_side;
+ ycf_symbol* assignment_symbol;
+ ycf_node_function_call fun_call;
+} ycf_node_function_call_assignment;
+
+typedef struct {
+ ycf_node_list definition_nodes;
+ char* name;
+} ycf_node_gen_typedef_struct;
+
+typedef struct {
+ ycf_symbol* comma_symbol;
+} ycf_node_comma;
+
+typedef struct {
+ ycf_symbol* symbol;
+} ycf_node_macro_cmd;
+
+typedef struct {
+ struct ycf_symbol* start;
+ ycf_node_if code;
+ struct ycf_symbol* end;
+} ycf_node_special_code_block;
+
+
+typedef struct {
+ struct ycf_symbol* goto_symbol;
+ struct ycf_symbol* label_symbol;
+ struct ycf_symbol* end_symbol;
+} ycf_node_goto;
+
+typedef struct {
+ struct ycf_symbol* return_symbol;
+ struct ycf_node* return_expression;
+ struct ycf_symbol* end_symbol;
+} ycf_node_return;
+
+typedef struct {
+ struct ycf_symbol* period;
+ struct ycf_symbol* field_name;
+} ycf_node_period_field_access;
+
+typedef struct {
+ struct ycf_symbol* pointer;
+ struct ycf_symbol* field_name;
+} ycf_pointer_field_access;
+
+typedef struct ycf_node {
+ ycf_node_type type;
+ struct ycf_node* next;
+ union {
+ ycf_node_c_file c_file;
+ ycf_node_definition definition;
+ ycf_node_definition_init definition_init;
+ ycf_node_code_scope code_scope;
+ ycf_node_other other;
+ ycf_node_function function;
+ ycf_node_function_definition function_definition;
+ ycf_node_assignment a;
+ ycf_node_gen_typedef_struct gen_typedef_struct;
+ ycf_node_yield yield;
+ ycf_node_consume_reds consume_reds;
+ ycf_node_expression expression;
+ ycf_node_parentheses_expression parentheses_expression;
+ ycf_node_function_call function_call;
+ ycf_node_statement statement;
+ ycf_node_while while_n;
+ ycf_node_do_while do_while;
+ ycf_node_for for_n;
+ ycf_node_switch switch_n;
+ ycf_node_if if_n;
+ ycf_node_if_else if_else;
+ ycf_node_function_call_assignment function_call_assignment;
+ ycf_node_comma comma;
+ ycf_node_array_bracket array_bracket;
+ ycf_node_macro_cmd macro_cmd;
+ ycf_node_special_code_block special_code_block;
+ ycf_node_goto goto_n;
+ ycf_node_return return_n;
+ ycf_node_period_field_access period_field_access;
+ ycf_pointer_field_access pointer_field_access;
+ } u;
+} ycf_node;
+
+void ycf_node_search_and_replace_statements_in_scope(ycf_node_code_scope* s,
+ ycf_node* (*replacer) (ycf_node* canditate,
+ ycf_node_code_scope* candidates_scope,
+ void* context),
+ void* context);
+
+char* ycf_node_to_string(ycf_node* n);
+ycf_node* ycf_node_new_text_node(char* text);
+ycf_node* ycf_node_new();
+ycf_node* ycf_node_find_function(ycf_node* c_file_node, char* fun_name);
+ycf_node* ycf_node_find_function_declaration(ycf_node* c_file_node, char* fun_name);
+ycf_node* ycf_node_find_define_node(ycf_node* c_file_node, char* define_name);
+bool ycf_node_is_void_ret_fun(ycf_node* f_node);
+ycf_node* ycf_node_get_from_code_scope_text(char* code);
+ycf_node* ycf_node_get_function_from_text(char* code);
+void ycf_node_print(ycf_node* node, ycf_string_printable_buffer* b);
+ycf_node* ycf_node_deep_copy(ycf_node *n);
+ycf_node* ycf_node_from_string(char* src);
+void ycf_node_insert_scopes_in_complex_statements(ycf_node_code_scope* s);
+void ycf_node_normalize_for_var_declarations(ycf_node_code_scope* s);
+void ycf_node_move_in_code_var_declarations_to_top(ycf_node_code_scope* s);
+void ycf_node_remove_declarations_in_scope(ycf_node_code_scope* s);
+ycf_node_list ycf_node_get_declarations_in_scope(ycf_node_code_scope* s);
+void ycf_node_normalize_init_definitions_in_scope(ycf_node_code_scope* s);
+ycf_node_list ycf_node_get_all_definitions_in_function(ycf_node_function* f);
+void ycf_uniqify_local_vars_in_function(ycf_node* function);
+
+ycf_node* ycf_node_new_assignment_from_definition_init(ycf_node_definition_init* n);
+ycf_node* ycf_node_new_definition_from_definition_init(ycf_node_definition_init* n);
+ycf_node* ycf_node_defenition_new(ycf_symbol_list type_spec,
+ ycf_symbol* id,
+ ycf_node_list array_brackets,
+ ycf_symbol* end);
+ycf_node* ycf_node_defenition_with_init_new(ycf_node_definition def,
+ ycf_symbol_list expression,
+ ycf_symbol* end);
+ycf_node* ycf_node_c_file_new(ycf_node_list content);
+ycf_node* ycf_node_function_def_new(ycf_node_definition def_node,
+ ycf_node_list parameters,
+ bool ignore_param_ending,
+ ycf_symbol_list end);
+ycf_node* ycf_node_yield_new(ycf_symbol* yield_symbol,
+ ycf_symbol* end);
+ycf_node* ycf_node_consume_reds_new(ycf_symbol* consume_reds_symbol,
+ ycf_node_parentheses_expression nr_of_reds_expression,
+ ycf_symbol* end_symbol);
+ycf_node* ycf_node_other_new(ycf_symbol* other_symbol);
+ycf_node* ycf_node_scope_new(ycf_symbol* start,
+ ycf_node_list declaration_nodes,
+ ycf_node_list other_nodes,
+ ycf_symbol* end);
+ycf_node* ycf_node_function_new(ycf_node_function_definition fun_def,
+ ycf_node_code_scope body);
+ycf_node* ycf_node_function_call_new(ycf_symbol_list neg_symbols,
+ ycf_symbol* ident,
+ ycf_symbol* paran_start,
+ ycf_node_list parameters,
+ ycf_symbol* paran_end);
+ycf_node* ycf_node_paran_expression_new(ycf_symbol* start, ycf_node_expression expr, ycf_symbol* end);
+ycf_node* ycf_node_expression_new(ycf_node_list expr);
+ycf_node* ycf_node_statement_new(ycf_node* expression,
+ ycf_symbol* end_symbol);
+ycf_node* ycf_node_while_new(ycf_symbol* while_word,
+ ycf_node_parentheses_expression expression,
+ ycf_node* statement);
+ycf_node* ycf_node_do_while_new(ycf_symbol* do_word,
+ ycf_node* statm,
+ ycf_symbol* while_word,
+ ycf_node_parentheses_expression expression,
+ ycf_symbol* end);
+ycf_node* ycf_node_for_new(ycf_symbol* for_word,
+ ycf_symbol* start_paran,
+ struct ycf_node* init,
+ ycf_node* stop_cond,
+ ycf_symbol* stop_cond_end,
+ ycf_node* end_exp,
+ ycf_symbol* end_paran,
+ ycf_node* statem);
+ycf_node* ycf_node_switch_new(ycf_symbol* switch_word,
+ ycf_node_parentheses_expression expression,
+ ycf_node_code_scope scope);
+ycf_node* ycf_node_if_new(ycf_symbol* if_word,
+ ycf_node_parentheses_expression expression,
+ struct ycf_node* if_statem);
+ycf_node* ycf_node_if_else_new(ycf_node_if if_n,
+ ycf_symbol* else_word,
+ struct ycf_node* else_statement);
+ycf_node* ycf_node_fun_call_assignment_new(ycf_node_expression left_side,
+ ycf_symbol* assignment_symbol,
+ ycf_node_function_call fun_call);
+ycf_node* ycf_node_comma_new(ycf_symbol* comma_symbol);
+ycf_node* ycf_node_array_bracket_new(ycf_symbol* start,
+ bool empty,
+ ycf_node_expression content,
+ ycf_symbol* end);
+ycf_node* ycf_node_macro_cmd_new(ycf_symbol* macro_symbol);
+ycf_node* ycf_node_special_code_block_new(ycf_node_type type,
+ ycf_symbol* start,
+ ycf_node_if code,
+ ycf_symbol* end);
+ycf_node* ycf_node_goto_new(ycf_symbol* goto_symbol,
+ ycf_symbol* label_symbol,
+ ycf_symbol* end_symbol);
+ycf_node* ycf_node_return_new(ycf_symbol* return_symbol,
+ ycf_node* return_expression,
+ ycf_symbol* end_symbol);
+ycf_node* ycf_node_period_field_access_new(ycf_symbol* period,
+ ycf_symbol* field_name);
+ycf_node* ycf_pointer_field_access_new(ycf_symbol* pointer,
+ ycf_symbol* field_name);
+
+ycf_node_list ycf_node_definition_list_from_string(char* str);
+void ycf_node_rename_function(ycf_node_function* f, char* new_name);
+bool ycf_node_is_void_ret_ending_fun(ycf_node* f_node);
+void ycf_node_remove_const_specifiers_from_declaration(ycf_node* declaration);
+void ycf_node_remove_static_specifiers_from_declaration(ycf_node* declaration);
+void ycf_node_remove_inline_specifiers_from_declaration(ycf_node* declaration);
+void ycf_node_remove_array_size_info_from_declaration(ycf_node* declaration);
+void ycf_node_modify_declarations(ycf_node_list declarations, void (*modifer)(ycf_node*));
+ycf_symbol_list ycf_node_get_return_type(ycf_node* f_node);
+ycf_symbol_list ycf_node_find_function_return_type(ycf_node* c_file_node, char* fun_name);
+
+
+/* Functions for node lists */
+
+int ycf_node_list_get_item_position(ycf_node_list* list, ycf_node* node);
+
+ycf_node* ycf_node_shallow_copy(ycf_node* n);
+ycf_node* ycf_node_list_get_item_at_position(ycf_node_list* list, int pos);
+
+void ycf_node_list_append(ycf_node_list* list, ycf_node* node);
+void ycf_node_list_prepend(ycf_node_list* list, ycf_node* node);
+void ycf_node_list_insert_before(ycf_node_list* list, ycf_node* before_this, ycf_node* to_insert);
+void ycf_node_list_insert_after(ycf_node_list* list, ycf_node* after_this, ycf_node* to_insert);
+void ycf_node_list_remove(ycf_node_list* list, ycf_node* to_remove);
+void ycf_node_list_replace(ycf_node_list* list, ycf_node* to_replace, ycf_node* replace_with);
+void ycf_node_list_concat(ycf_node_list* list1, ycf_node_list* list2);
+
+ycf_node_list ycf_node_list_empty();
+ycf_node_list ycf_node_list_shallow_copy(ycf_node_list n);
+ycf_node_list ycf_node_list_copy_append(ycf_node_list list, ycf_node* node);
+ycf_node_list ycf_node_list_copy_prepend(ycf_node_list list, ycf_node* node);
+ycf_node_list ycf_node_list_copy_insert_before(ycf_node_list list, ycf_node* before_this, ycf_node* to_insert);
+ycf_node_list ycf_node_list_copy_insert_after(ycf_node_list list, ycf_node* after_this, ycf_node* to_insert);
+ycf_node_list ycf_node_list_copy_remove(ycf_node_list list, ycf_node* to_remove);
+ycf_node_list ycf_node_list_copy_replace(ycf_node_list list, ycf_node* to_replace, ycf_node* replace_with);
+ycf_node_list ycf_node_list_copy_concat(ycf_node_list list1, ycf_node_list list2);
+size_t ycf_node_list_length(ycf_node_list list);
+char* ycf_node_list_to_string(ycf_node_list* l);
+char* ycf_node_get_node_type_string(ycf_node_type t);
+
+ycf_node_assignment* ycf_node_get_assignment(ycf_node* n);
+void ycf_node_print_node_type(ycf_node_type t);
+void ycf_node_normalize_function(ycf_node* fun);
+void ycf_node_remove_unecessary_scopes(ycf_node_code_scope* s);
+
+#endif //YIELDING_C_FUN_YCF_NODE_FUNS_H
diff --git a/erts/lib_src/yielding_c_fun/ycf_parser.c b/erts/lib_src/yielding_c_fun/ycf_parser.c
new file mode 100644
index 0000000000..ed2747c955
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_parser.c
@@ -0,0 +1,1498 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#include "ycf_yield_fun.h"
+#include "ycf_utils.h"
+#include "ycf_node.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void print_symbol_code(ycf_symbol* s);
+ycf_parse_result parse_exp_statement(ycf_symbol* symbols);
+
+ycf_parse_result fail_parse_result(){
+ ycf_parse_result r;
+ r.success = false;
+ r.next_symbol = NULL;
+ r.result = NULL;
+ return r;
+}
+
+ycf_parse_result success_parse_result(ycf_symbol* next,
+ ycf_node* result){
+ ycf_parse_result r;
+ r.success = true;
+ r.next_symbol = next;
+ r.result = result;
+ return r;
+}
+
+typedef struct {
+ ycf_node_list list;
+ ycf_symbol* next_symbol;
+} parse_list_res;
+
+typedef struct {
+ ycf_symbol_list list;
+ ycf_symbol* next_symbol;
+} parse_symbol_list_res;
+
+
+parse_list_res parse_list_generic(int number_of_parsers,
+ ycf_parse_result (*parsers[])(ycf_symbol*),
+ ycf_symbol* symbols,
+ bool use_break_symbol,
+ int nr_of_break_symbols,
+ ycf_symbol_type break_symbols[]){
+ parse_list_res r;
+ ycf_symbol* current = symbols;
+ int i;
+ r.list = ycf_node_list_empty();
+ while(current != NULL){
+ if(use_break_symbol){
+ bool is_break = false;
+ for(int i = 0; i < nr_of_break_symbols; i++){
+ if(break_symbols[i] == current->type){
+ is_break = true;
+ }
+ }
+ if(is_break){
+ break;
+ }
+ }
+ ycf_symbol* prev_current_symbol = current;
+ for(i = 0; i < number_of_parsers; i++){
+ ycf_parse_result res = parsers[i](current);
+ if(res.success){
+ ycf_node_list_append(&r.list, res.result);
+ current = res.next_symbol;
+ break;
+ }
+ }
+ if(prev_current_symbol == current){
+ break;
+ }
+ }
+ r.next_symbol = current;
+ return r;
+}
+
+parse_list_res parse_list(int number_of_parsers,
+ ycf_parse_result (*parsers[])(ycf_symbol*),
+ ycf_symbol* symbols){
+ return parse_list_generic(number_of_parsers,
+ parsers,
+ symbols,
+ false,
+ 0,
+ NULL);
+
+}
+
+parse_list_res parse_list_break_symbol(int number_of_parsers,
+ ycf_parse_result (*parsers[])(ycf_symbol*),
+ ycf_symbol* symbols,
+ ycf_symbol_type break_symbol){
+ ycf_symbol_type break_s[1] = {break_symbol};
+ return parse_list_generic(number_of_parsers,
+ parsers,
+ symbols,
+ true,
+ 1,
+ break_s);
+
+}
+
+parse_list_res parse_list_break_symbols(int number_of_parsers,
+ ycf_parse_result (*parsers[])(ycf_symbol*),
+ ycf_symbol* symbols,
+ int nr_of_break_symbols,
+ ycf_symbol_type break_symbols[]){
+ return parse_list_generic(number_of_parsers,
+ parsers,
+ symbols,
+ true,
+ nr_of_break_symbols,
+ break_symbols);
+
+}
+
+
+ycf_node* ycf_node_defenition_new(ycf_symbol_list type_spec,
+ ycf_symbol* id,
+ ycf_node_list array_brackets,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_variable_definition;
+ n->next = NULL;
+ n->u.definition.identifier = ycf_symbol_copy(id);
+ n->u.definition.type_specifiers = type_spec;
+ n->u.definition.array_brackets = array_brackets;
+ n->u.definition.end = ycf_symbol_copy(end);
+ return n;
+}
+
+ycf_node* ycf_node_defenition_with_init_new(ycf_node_definition def,
+ ycf_symbol_list expression,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_variable_definition_init;
+ n->next = NULL;
+ n->u.definition_init.definition = def;
+ n->u.definition_init.initializer_expression = expression;
+ n->u.definition_init.end = ycf_symbol_copy(end);
+ return n;
+}
+
+ycf_node* ycf_node_c_file_new(ycf_node_list content){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_c_file;
+ n->next = NULL;
+ n->u.c_file.content = content;
+ return n;
+}
+
+
+ycf_node* ycf_node_function_def_new(ycf_node_definition def_node,
+ ycf_node_list parameters,
+ bool ignore_param_ending,
+ ycf_symbol_list end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_function_declaration;
+ n->next = NULL;
+ n->u.function_definition.definition = def_node;
+ n->u.function_definition.parameters = parameters;
+ n->u.function_definition.ignore_param_ending = ignore_param_ending;
+ n->u.function_definition.end = end;
+ return n;
+}
+
+ycf_node* ycf_node_yield_new(ycf_symbol* yield_symbol,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_yield;
+ n->next = NULL;
+ n->u.yield.yield_symbol = ycf_symbol_copy(yield_symbol);
+ n->u.yield.end_symbol = ycf_symbol_copy(end);
+ return n;
+}
+
+
+
+ycf_node* ycf_node_consume_reds_new(ycf_symbol* consume_reds_symbol,
+ ycf_node_parentheses_expression nr_of_reds_expression,
+ ycf_symbol* end_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_consume_reds;
+ n->next = NULL;
+ n->u.consume_reds.consume_reds_symbol = ycf_symbol_copy(consume_reds_symbol);
+ n->u.consume_reds.nr_of_reds_expression = nr_of_reds_expression;
+ n->u.consume_reds.end_symbol = ycf_symbol_copy(end_symbol);
+ return n;
+}
+
+
+ycf_node* ycf_node_other_new(ycf_symbol* other_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_other;
+ n->next = NULL;
+ n->u.other.what = ycf_symbol_copy(other_symbol);
+ return n;
+}
+
+ycf_node* ycf_node_scope_new(ycf_symbol* start,
+ ycf_node_list declaration_nodes,
+ ycf_node_list other_nodes,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_code_scope;
+ n->next = NULL;
+ n->u.code_scope.start = ycf_symbol_copy(start);
+ n->u.code_scope.definition_nodes = declaration_nodes;
+ n->u.code_scope.other_nodes = other_nodes;
+ n->u.code_scope.end = ycf_symbol_copy(end);
+ return n;
+}
+
+ycf_node* ycf_node_function_new(ycf_node_function_definition fun_def,
+ ycf_node_code_scope body){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_function_definition;
+ n->next = NULL;
+ n->u.function.definition = fun_def;
+ n->u.function.body = body;
+ return n;
+}
+
+ycf_node* ycf_node_function_call_new(ycf_symbol_list neg_symbols,
+ ycf_symbol* ident,
+ ycf_symbol* paran_start,
+ ycf_node_list parameters,
+ ycf_symbol* paran_end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_function_call;
+ n->next = NULL;
+ n->u.function_call.neg_symbols = neg_symbols;
+ n->u.function_call.identifier = ident;
+ n->u.function_call.start_symbol = paran_start;
+ n->u.function_call.parameter_expressions = parameters;
+ n->u.function_call.end_symbol = paran_end;
+ return n;
+}
+
+ycf_node* ycf_node_paran_expression_new(ycf_symbol* start, ycf_node_expression expr, ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_parentheses_expression;
+ n->next = NULL;
+ n->u.parentheses_expression.start_symbol = start;
+ n->u.parentheses_expression.content = expr;
+ n->u.parentheses_expression.end_symbol = end;
+ return n;
+}
+
+ycf_node* ycf_node_expression_new(ycf_node_list expr){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_expression;
+ n->next = NULL;
+ n->u.expression.content = expr;
+ n->u.expression.end_symbol = NULL;
+ return n;
+}
+
+ycf_node* ycf_node_statement_new(ycf_node* expression,
+ ycf_symbol* end_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->type = ycf_node_type_statement;
+ n->next = NULL;
+ n->u.statement.expression = expression;
+ n->u.statement.end_symbol = end_symbol;
+ return n;
+}
+
+ycf_node* ycf_node_while_new(ycf_symbol* while_word,
+ ycf_node_parentheses_expression expression,
+ ycf_node* statement){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_while;
+ n->u.while_n.while_word = while_word;
+ n->u.while_n.expression = expression;
+ n->u.while_n.statement = statement;
+ return n;
+}
+
+
+
+ycf_node* ycf_node_do_while_new(ycf_symbol* do_word,
+ ycf_node* statm,
+ ycf_symbol* while_word,
+ ycf_node_parentheses_expression expression,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_do_while;
+ n->u.do_while.do_word = do_word;
+ n->u.do_while.statement = statm;
+ n->u.do_while.while_word = while_word;
+ n->u.do_while.expression = expression;
+ n->u.do_while.end = end;
+ return n;
+}
+
+ycf_node* ycf_node_for_new(ycf_symbol* for_word,
+ ycf_symbol* start_paran,
+ struct ycf_node* init,
+ ycf_node* stop_cond,
+ ycf_symbol* stop_cond_end,
+ ycf_node* end_exp,
+ ycf_symbol* end_paran,
+ ycf_node* statem){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_for;
+ n->u.for_n.for_word = for_word;
+ n->u.for_n.start_parentheses = start_paran;
+ n->u.for_n.init = init;
+ n->u.for_n.stop_cond = stop_cond;
+ n->u.for_n.stop_cond_end = stop_cond_end;
+ n->u.for_n.end_exp = end_exp;
+ n->u.for_n.end_parentheses = end_paran;
+ n->u.for_n.statement = statem;
+ return n;
+}
+
+ycf_node* ycf_node_switch_new(ycf_symbol* switch_word,
+ ycf_node_parentheses_expression expression,
+ ycf_node_code_scope scope){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_switch;
+ n->u.switch_n.switch_word = switch_word;
+ n->u.switch_n.expression = expression;
+ n->u.switch_n.scope = scope;
+ return n;
+}
+
+ycf_node* ycf_node_if_new(ycf_symbol* if_word,
+ ycf_node_parentheses_expression expression,
+ struct ycf_node* if_statem){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_if;
+ n->u.if_n.if_word = if_word;
+ n->u.if_n.expression = expression;
+ n->u.if_n.if_statement = if_statem;
+ return n;
+}
+
+ycf_node* ycf_node_if_else_new(ycf_node_if if_n,
+ ycf_symbol* else_word,
+ struct ycf_node* else_statement){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_if_else;
+ n->u.if_else.if_part = if_n;
+ n->u.if_else.else_word = else_word;
+ n->u.if_else.else_statement = else_statement;
+ return n;
+}
+
+
+ycf_node* ycf_node_fun_call_assignment_new(ycf_node_expression left_side,
+ ycf_symbol* assignment_symbol,
+ ycf_node_function_call fun_call){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_assignment_function_call;
+ n->u.function_call_assignment.left_side = left_side;
+ n->u.function_call_assignment.assignment_symbol = assignment_symbol;
+ n->u.function_call_assignment.fun_call = fun_call;
+ return n;
+}
+
+ycf_node* ycf_node_assignment_new(ycf_node_expression left_side,
+ ycf_symbol* assignment_symbol,
+ ycf_node_expression right_side,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_assignment;
+ n->u.a.left_side = left_side;
+ n->u.a.right_side = right_side;
+ n->u.a.assignment_symbol = assignment_symbol;
+ n->u.a.end = end;
+ return n;
+}
+
+ycf_node* ycf_node_comma_new(ycf_symbol* comma_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_comma;
+ n->u.comma.comma_symbol = comma_symbol;
+ return n;
+}
+
+ycf_node* ycf_node_array_bracket_new(ycf_symbol* start,
+ bool empty,
+ ycf_node_expression content,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_array_bracket;
+ n->u.array_bracket.start = start;
+ n->u.array_bracket.empty = empty;
+ n->u.array_bracket.content = content;
+ n->u.array_bracket.end = end;
+ return n;
+}
+
+ycf_node* ycf_node_macro_cmd_new(ycf_symbol* macro_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_macro_cmd;
+ n->u.macro_cmd.symbol = macro_symbol;
+ return n;
+}
+
+ycf_node* ycf_node_special_code_block_new(ycf_node_type type,
+ ycf_symbol* start,
+ ycf_node_if code,
+ ycf_symbol* end){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = type;
+ n->u.special_code_block.start = start;
+ n->u.special_code_block.code = code;
+ n->u.special_code_block.end = end;
+ return n;
+}
+
+ycf_node* ycf_node_goto_new(ycf_symbol* goto_symbol,
+ ycf_symbol* label_symbol,
+ ycf_symbol* end_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_goto;
+ n->u.goto_n.goto_symbol = goto_symbol;
+ n->u.goto_n.label_symbol = label_symbol;
+ n->u.goto_n.end_symbol = end_symbol;
+ return n;
+}
+
+ycf_node* ycf_node_return_new(ycf_symbol* return_symbol,
+ ycf_node* return_expression,
+ ycf_symbol* end_symbol){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_return_statement;
+ n->u.return_n.return_symbol = return_symbol;
+ n->u.return_n.return_expression = return_expression;
+ n->u.return_n.end_symbol = end_symbol;
+ return n;
+}
+
+
+ycf_node* ycf_node_period_field_access_new(ycf_symbol* period,
+ ycf_symbol* field_name){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_period_field_access;
+ n->u.period_field_access.period = period;
+ n->u.period_field_access.field_name = field_name;
+ return n;
+}
+
+ycf_node* ycf_pointer_field_access_new(ycf_symbol* pointer,
+ ycf_symbol* field_name){
+ ycf_node* n = ycf_malloc(sizeof(ycf_node));
+ n->next = NULL;
+ n->type = ycf_node_type_period_field_access;
+ n->u.pointer_field_access.pointer = pointer;
+ n->u.pointer_field_access.field_name = field_name;
+ return n;
+}
+
+parse_symbol_list_res parse_symbol_list(int nr_of_aloved_symbols,
+ ycf_symbol_type accept_symbols[],
+ ycf_symbol* symbols){
+ int i;
+ parse_symbol_list_res r;
+ ycf_symbol* current = symbols;
+ r.list = ycf_symbol_list_empty();
+ while (current != NULL){
+ ycf_symbol* prev_current = current;
+ for(i = 0; i < nr_of_aloved_symbols; i++){
+ if(current->type == accept_symbols[i]){
+ ycf_symbol_list_append(&r.list, ycf_symbol_copy(current));
+ current = current->next;
+ }
+ }
+ if(prev_current == current){
+ break;
+ }
+ }
+ r.next_symbol = current;
+ return r;
+}
+
+parse_symbol_list_res
+parse_symbol_list_until(ycf_symbol* symbols, ycf_symbol_type end_symbol){
+ parse_symbol_list_res r;
+ ycf_symbol* current = symbols;
+ r.list = ycf_symbol_list_empty();
+ while (current->type != end_symbol){
+ ycf_symbol_list_append(&r.list, ycf_symbol_copy(current));
+ current = current->next;
+ }
+ r.next_symbol = current;
+ return r;
+}
+
+ycf_parse_result parse_expression_end_end_squarebracket(ycf_symbol* symbols);
+
+ycf_parse_result parse_array_bracket(ycf_symbol* symbols){
+ if(symbols->type != ycf_symbol_type_open_square_bracket){
+ return fail_parse_result();
+ }
+ if(symbols->next->type == ycf_symbol_type_end_square_bracket){
+ ycf_node_expression empty = {.content = ycf_node_list_empty(), .end_symbol = NULL};
+ return success_parse_result(symbols->next->next,
+ ycf_node_array_bracket_new(symbols, true, empty, symbols->next));
+ }
+ ycf_parse_result square_bracket_content =
+ parse_expression_end_end_squarebracket(symbols->next);
+ if(!square_bracket_content.success){
+ return fail_parse_result();
+ }
+ return success_parse_result(square_bracket_content.next_symbol->next,
+ ycf_node_array_bracket_new(symbols,
+ false,
+ square_bracket_content.result->u.expression,
+ square_bracket_content.next_symbol));
+}
+
+ycf_parse_result parse_defenition_until_identifier(ycf_symbol* symbols,
+ ycf_symbol_type end_symbol_type){
+ ycf_symbol* current = symbols;
+ ycf_symbol_list type_specifier = ycf_symbol_list_empty();
+ ycf_symbol* ident = NULL;
+ ycf_node_list array_brackets;
+ /* Parse modifiers */
+ {
+ int nr_of_aloved_symbols = 4;
+ ycf_symbol_type accept_symbols[4];
+ accept_symbols[0] = ycf_symbol_type_static;
+ accept_symbols[1] = ycf_symbol_type_const;
+ accept_symbols[2] = ycf_symbol_type_inline;
+ accept_symbols[3] = ycf_symbol_type_volatile;
+ parse_symbol_list_res more =
+ parse_symbol_list(nr_of_aloved_symbols,
+ accept_symbols,
+ current);
+ ycf_symbol_list_concat(&type_specifier, &more.list);
+ current = more.next_symbol;
+ }
+ /* Parse first symbol */
+ if(current->type == ycf_symbol_type_identifier ||
+ current->type == ycf_symbol_type_void){
+ ycf_symbol_list_append(&type_specifier, ycf_symbol_copy(current));
+ current = current->next;
+ } else {
+ return fail_parse_result();
+ }
+ if(type_specifier.last->type == ycf_symbol_type_identifier){
+ /* Parse remaining identifiers if first symbol is ycf_symbol_type_identifier */
+ int nr_of_aloved_symbols = 2;
+ ycf_symbol_type accept_symbols[2];
+ accept_symbols[0] = ycf_symbol_type_identifier;
+ accept_symbols[1] = ycf_symbol_type_const;
+ parse_symbol_list_res more =
+ parse_symbol_list(nr_of_aloved_symbols,
+ accept_symbols,
+ current);
+ ycf_symbol_list_concat(&type_specifier, &more.list);
+ current = more.next_symbol;
+ }
+ {
+ /* Parse stars */
+ int nr_of_aloved_symbols = 1;
+ ycf_symbol_type accept_symbols[1];
+ accept_symbols[0] = ycf_symbol_type_star;
+ parse_symbol_list_res more =
+ parse_symbol_list(nr_of_aloved_symbols,
+ accept_symbols,
+ current);
+ ycf_symbol_list_concat(&type_specifier, &more.list);
+ current = more.next_symbol;
+ }
+ /* Handle ycf_symbol_type_identifier */
+ if(type_specifier.last->type == ycf_symbol_type_identifier){
+ ident = type_specifier.last;
+ ycf_symbol_list_remove(&type_specifier, type_specifier.last);
+ if (type_specifier.head == NULL) {
+ return fail_parse_result();
+ }
+ } else if (current->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ } else {
+ ident = current;
+ current = current->next;
+ }
+ /* Handle array brackets */
+ {
+ ycf_parse_result (*parsers[])(ycf_symbol *) = {
+ parse_array_bracket
+ };
+ parse_list_res res = parse_list(1, parsers, current);
+ array_brackets = res.list;
+ current = res.next_symbol;
+ }
+ /* Parse end symbol */
+ if (current == NULL ||
+ current->type != end_symbol_type){
+ return fail_parse_result();
+ } else {
+ return success_parse_result(current->next,
+ ycf_node_defenition_new(type_specifier,
+ ident,
+ array_brackets,
+ current));
+ }
+}
+
+ycf_parse_result parse_defenition_no_init(ycf_symbol* symbols){
+ ycf_parse_result res = parse_defenition_until_identifier(symbols, ycf_symbol_type_semicolon);
+ return res;
+}
+
+ycf_parse_result parse_defenition_with_init(ycf_symbol* symbols){
+ ycf_parse_result dec = parse_defenition_until_identifier(symbols, ycf_symbol_type_equal_sign);
+ parse_symbol_list_res expression_list_res;
+ if(!dec.success){
+ return fail_parse_result();
+ }
+ expression_list_res =
+ parse_symbol_list_until(dec.next_symbol, ycf_symbol_type_semicolon);
+ return success_parse_result(expression_list_res.next_symbol->next,
+ ycf_node_defenition_with_init_new(dec.result->u.definition,
+ expression_list_res.list,
+ expression_list_res.next_symbol));
+}
+
+ycf_parse_result parse_defenition_comma(ycf_symbol* symbols){
+ ycf_parse_result res = parse_defenition_until_identifier(symbols, ycf_symbol_type_comma);
+ return res;
+}
+
+ycf_parse_result parse_defenition_end_paran(ycf_symbol* symbols){
+ ycf_parse_result res = parse_defenition_until_identifier(symbols, ycf_symbol_type_end_parenthesis);
+ return res;
+}
+
+ycf_parse_result parse_function_head(ycf_symbol* symbols,
+ ycf_symbol_type end_symbol,
+ bool exclude_end_symbol){
+ ycf_symbol* current = symbols;
+ ycf_parse_result def_res =
+ parse_defenition_until_identifier(current,
+ ycf_symbol_type_open_parenthesis);
+ if(!def_res.success){
+ return fail_parse_result();
+ }
+ current = def_res.next_symbol;
+
+ /* Parse function without parameters */
+
+ if(current->type == ycf_symbol_type_end_parenthesis &&
+ current->next->type == end_symbol){
+ ycf_symbol_list end = ycf_symbol_list_empty();
+ ycf_symbol* next_symbol;
+ ycf_node_list parameter_list = ycf_node_list_empty();
+ ycf_symbol_list_append(&end, ycf_symbol_copy(current));
+ if(!exclude_end_symbol){
+ next_symbol = current->next->next;
+ ycf_symbol_list_append(&end, ycf_symbol_copy(current->next));
+ } else {
+ next_symbol = current->next;
+ }
+ return success_parse_result(next_symbol,
+ ycf_node_function_def_new(def_res.result->u.definition,
+ parameter_list,
+ false,
+ end));
+ } else if(current->type == ycf_symbol_type_void &&
+ current->next->type == ycf_symbol_type_end_parenthesis &&
+ current->next->next->type == end_symbol){
+ ycf_symbol_list end = ycf_symbol_list_empty();
+ ycf_symbol* next_symbol;
+ ycf_node_list parameter_list = ycf_node_list_empty();
+ ycf_symbol_list_append(&end, ycf_symbol_copy(current));
+ ycf_symbol_list_append(&end, ycf_symbol_copy(current->next));
+ if(!exclude_end_symbol){
+ next_symbol = current->next->next->next;
+ ycf_symbol_list_append(&end, ycf_symbol_copy(current->next->next));
+ }else{
+ next_symbol = current->next->next;
+ }
+ return success_parse_result(next_symbol,
+ ycf_node_function_def_new(def_res.result->u.definition,
+ parameter_list,
+ false,
+ end));
+ }
+
+ /* Parse parameters */
+
+ int number_of_parsers = 2;
+ ycf_parse_result (*parsers[])(ycf_symbol *) = {
+ parse_defenition_comma,
+ parse_defenition_end_paran
+ };
+ parse_list_res param_list =
+ parse_list(number_of_parsers, parsers, current);
+ if(param_list.next_symbol == NULL ||
+ param_list.next_symbol->type != end_symbol){
+ return fail_parse_result();
+ }
+
+ /* Parse ending */
+
+ {
+ ycf_symbol_list end = ycf_symbol_list_empty();
+ ycf_symbol* next_symbol;
+ if(!exclude_end_symbol){
+ next_symbol = param_list.next_symbol->next;
+ ycf_symbol_list_append(&end, ycf_symbol_copy(param_list.next_symbol));
+ }else{
+ next_symbol = param_list.next_symbol;
+ }
+ return success_parse_result(next_symbol,
+ ycf_node_function_def_new(def_res.result->u.definition,
+ param_list.list,
+ false,
+ end));
+ }
+}
+
+ycf_parse_result parse_function_def(ycf_symbol* symbols){
+ return parse_function_head(symbols, ycf_symbol_type_semicolon, false);
+}
+
+ycf_parse_result parse_other(ycf_symbol* symbols){
+ ycf_symbol* what = symbols;
+ return success_parse_result(symbols->next,
+ ycf_node_other_new(what));
+}
+
+
+ycf_parse_result parse_goto(ycf_symbol* symbols){
+ ycf_symbol* goto_symbol = symbols;
+ if(goto_symbol->type != ycf_symbol_type_goto){
+ return fail_parse_result();
+ }
+ ycf_symbol* label_symbol = goto_symbol->next;
+ if(label_symbol->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ }
+ ycf_symbol* end_symbol = label_symbol->next;
+ if(end_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(end_symbol->next,
+ ycf_node_goto_new(goto_symbol, label_symbol, end_symbol));
+}
+
+
+ycf_parse_result parse_comma(ycf_symbol* symbols){
+ if(symbols->type == ycf_symbol_type_comma){
+ return success_parse_result(symbols->next, ycf_node_comma_new(symbols));
+ } else {
+ return fail_parse_result();
+ }
+}
+
+
+ycf_parse_result parse_pointer_field_access_node(ycf_symbol* symbols){
+ ycf_symbol* pointer = symbols;
+ if(pointer->type != ycf_symbol_type_pointer_field_access){
+ return fail_parse_result();
+ }
+ ycf_symbol* field_name = pointer->next;
+ if(field_name->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ }
+ return success_parse_result(field_name->next,
+ ycf_pointer_field_access_new(pointer, field_name));
+}
+
+ycf_parse_result parse_period_field_access_node(ycf_symbol* symbols){
+ ycf_symbol* p = symbols;
+ if(p->type != ycf_symbol_type_period){
+ return fail_parse_result();
+ }
+ ycf_symbol* field_name = p->next;
+ if(field_name->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ }
+ return success_parse_result(field_name->next,
+ ycf_node_period_field_access_new(p, field_name));
+}
+
+ycf_parse_result parse_function_call(ycf_symbol* symbols);
+ycf_parse_result parse_expression_generic(ycf_symbol* symbols,
+ bool use_end_symbol,
+ bool no_function_call_assignment,
+ int nr_of_end_symbols,
+ ycf_symbol_type end_symbols[]);
+
+ycf_parse_result parse_paran_expression(ycf_symbol* symbols){
+ if(symbols->type != ycf_symbol_type_open_parenthesis){
+ return fail_parse_result();
+ }
+ ycf_symbol* start = symbols;
+ ycf_parse_result exp = parse_expression_generic(start->next,
+ true,
+ false,
+ 1,
+ (ycf_symbol_type[]){ycf_symbol_type_end_parenthesis});
+ if(!exp.success || exp.next_symbol->type != ycf_symbol_type_end_parenthesis ){
+ return fail_parse_result();
+ }
+ return success_parse_result(exp.next_symbol->next,
+ ycf_node_paran_expression_new(start,
+ exp.result->u.expression,
+ exp.next_symbol));
+}
+
+ycf_parse_result parse_function_call_assignment(ycf_symbol* symbols);
+ycf_parse_result parse_assignment(ycf_symbol* symbols);
+
+ycf_parse_result parse_expression_generic(ycf_symbol* symbols,
+ bool use_end_symbol,
+ bool no_function_call_assignment,
+ int nr_of_end_symbols,
+ ycf_symbol_type end_symbols[]){
+ int number_of_parsers = (!no_function_call_assignment ? 1 : 0) + 5;
+ ycf_parse_result (*parsers[7])(ycf_symbol *);
+ if(!no_function_call_assignment){
+ parsers[0] = parse_function_call;
+ parsers[1] = parse_function_call_assignment;
+ parsers[2] = parse_paran_expression;
+ parsers[3] = parse_period_field_access_node;
+ parsers[4] = parse_pointer_field_access_node;
+ parsers[5] = parse_other;
+ }else{
+ parsers[0] = parse_function_call;
+ parsers[1] = parse_paran_expression;
+ parsers[2] = parse_period_field_access_node;
+ parsers[3] = parse_pointer_field_access_node;
+ parsers[4] = parse_other;
+ }
+ parse_list_res res = parse_list_break_symbols(number_of_parsers, parsers, symbols, nr_of_end_symbols,end_symbols);
+ if(res.list.head == NULL || (use_end_symbol &&
+ (res.next_symbol == NULL ||res.next_symbol->type != end_symbols[0]))){
+ return fail_parse_result();
+ }
+ return success_parse_result(res.next_symbol,
+ ycf_node_expression_new(res.list));
+}
+
+ycf_parse_result parse_expression(ycf_symbol* symbols){
+ return parse_expression_generic(symbols,
+ false,
+ false,
+ 0 /* ignored */,
+ NULL);
+}
+
+ycf_parse_result parse_expression_end_comma(ycf_symbol* symbols){
+ return parse_expression_generic(symbols,
+ true,
+ false,
+ 2,
+ (ycf_symbol_type[]){ycf_symbol_type_comma, ycf_symbol_type_end_parenthesis});
+}
+
+ycf_parse_result parse_expression_end_end_paren(ycf_symbol* symbols){
+ return parse_expression_generic(symbols,
+ true,
+ false,
+ 1,
+ (ycf_symbol_type[]){ycf_symbol_type_end_parenthesis});
+}
+
+ycf_parse_result parse_expression_end_end_semicolon(ycf_symbol* symbols){
+ return parse_expression_generic(symbols,
+ true,
+ false,
+ 1,
+ (ycf_symbol_type[]){ycf_symbol_type_semicolon});
+}
+
+ycf_parse_result parse_expression_end_end_squarebracket(ycf_symbol* symbols){
+ return parse_expression_generic(symbols,
+ true,
+ false,
+ 1,
+ (ycf_symbol_type[]){ycf_symbol_type_end_square_bracket});
+}
+
+
+ycf_parse_result parse_function_call(ycf_symbol* symbols){
+ parse_symbol_list_res negs;
+ {
+ /* Parse neg symbols */
+ int nr_of_aloved_symbols = 1;
+ ycf_symbol_type accept_symbols[1];
+ accept_symbols[0] = ycf_symbol_type_neg;
+ negs =
+ parse_symbol_list(nr_of_aloved_symbols,
+ accept_symbols,
+ symbols);
+ }
+ ycf_symbol* ident = negs.next_symbol;
+ if(ident == NULL ||
+ ident->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ }
+ ycf_symbol* paran_start = ident->next;
+ if(paran_start == NULL || paran_start->type != ycf_symbol_type_open_parenthesis){
+ return fail_parse_result();
+ }
+ int number_of_parsers = 3;
+ ycf_parse_result (*parsers[])(ycf_symbol *) = {
+ parse_comma,
+ parse_expression_end_comma,
+ parse_expression_end_end_paren
+ };
+ parse_list_res param_list_res =
+ parse_list_break_symbol(number_of_parsers,
+ parsers,
+ paran_start->next,
+ ycf_symbol_type_end_parenthesis);
+ if(param_list_res.next_symbol == NULL ||
+ param_list_res.next_symbol->type != ycf_symbol_type_end_parenthesis){
+ return fail_parse_result();
+ }
+ return success_parse_result(param_list_res.next_symbol->next,
+ ycf_node_function_call_new(negs.list,
+ ident,
+ paran_start,
+ param_list_res.list,
+ param_list_res.next_symbol));
+}
+
+ycf_parse_result parse_assignment(ycf_symbol* symbols) {
+ if(symbols->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ }
+ if(symbols->next == NULL || symbols->next->type != ycf_symbol_type_equal_sign){
+ return fail_parse_result();
+ }
+ ycf_parse_result left_expression = parse_expression_generic(symbols,
+ false,
+ true,
+ 3,
+ (ycf_symbol_type[]){
+ ycf_symbol_type_equal_sign,
+ ycf_symbol_type_semicolon,
+ ycf_symbol_type_end_parenthesis});
+ if(!left_expression.success){
+ return fail_parse_result();
+ }
+ ycf_symbol* equal_sign = left_expression.next_symbol;
+ if(equal_sign == NULL || equal_sign->type != ycf_symbol_type_equal_sign) {
+ return fail_parse_result();
+ }
+ if(equal_sign->next == NULL || equal_sign->next->type != ycf_symbol_type_identifier){
+ return fail_parse_result();
+ }
+ if(equal_sign->next->next == NULL || equal_sign->next->next->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ ycf_parse_result right_expression = parse_expression_generic(equal_sign->next,
+ false,
+ true,
+ 3,
+ (ycf_symbol_type[]){
+ ycf_symbol_type_semicolon,
+ ycf_symbol_type_equal_sign,
+ ycf_symbol_type_end_parenthesis});
+ if(!right_expression.success ||
+ right_expression.next_symbol == NULL ||
+ right_expression.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ ycf_node* node = ycf_node_assignment_new(left_expression.result->u.expression,
+ ycf_symbol_copy(equal_sign),
+ right_expression.result->u.expression,
+ ycf_symbol_copy(right_expression.next_symbol));
+ return success_parse_result(right_expression.next_symbol->next,
+ node);
+}
+
+ycf_parse_result parse_function_call_assignment(ycf_symbol* symbols){
+ ycf_parse_result expression = parse_expression_generic(symbols,
+ true,
+ true,
+ 3,
+ (ycf_symbol_type[]){ycf_symbol_type_equal_sign,
+ ycf_symbol_type_semicolon,
+ ycf_symbol_type_end_parenthesis});
+ if(!expression.success){
+ return fail_parse_result();
+ }
+ ycf_symbol* equal_sign = expression.next_symbol;
+ ycf_parse_result fun_call = parse_function_call(equal_sign->next);
+ if(!fun_call.success){
+ return fail_parse_result();
+ }
+ return success_parse_result(fun_call.next_symbol,
+ ycf_node_fun_call_assignment_new(expression.result->u.expression,
+ equal_sign,
+ fun_call.result->u.function_call));
+}
+
+
+ycf_parse_result parse_function_call_assignment_statement(ycf_symbol* symbols){
+ ycf_parse_result fun_call_ass = parse_function_call_assignment(symbols);
+ if(!fun_call_ass.success || fun_call_ass.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(fun_call_ass.next_symbol->next,
+ ycf_node_statement_new(fun_call_ass.result,
+ fun_call_ass.next_symbol));
+}
+
+
+ycf_parse_result parse_function_call_statement(ycf_symbol* symbols){
+ ycf_parse_result fun_call = parse_function_call(symbols);
+ if(!fun_call.success || fun_call.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(fun_call.next_symbol->next,
+ ycf_node_statement_new(fun_call.result,
+ fun_call.next_symbol));
+}
+
+ycf_parse_result parse_statement(ycf_symbol* symbols);
+
+
+ycf_parse_result parse_cond_statement(ycf_symbol* symbols, ycf_symbol_type cond_keyword){
+ if(symbols->type != cond_keyword){
+ return fail_parse_result();
+ }
+ ycf_symbol* cond_word = symbols;
+ ycf_parse_result cond_exp = parse_paran_expression(cond_word->next);
+ if(!cond_exp.success){
+ return fail_parse_result();
+ }
+ ycf_parse_result cond_statement = parse_statement(cond_exp.next_symbol);
+ if(!cond_statement.success){
+ return fail_parse_result();
+ }
+ /* Return if node even though it might be something else */
+ return success_parse_result(cond_statement.next_symbol,
+ ycf_node_if_new(cond_word,
+ cond_exp.result->u.parentheses_expression,
+ cond_statement.result));
+}
+
+ycf_parse_result parse_if_statement(ycf_symbol* symbols){
+ return parse_cond_statement(symbols, ycf_symbol_type_if);
+}
+
+ycf_parse_result parse_if_else_statement(ycf_symbol* symbols){
+ ycf_parse_result if_statem = parse_if_statement(symbols);
+ if(!if_statem.success){
+ return fail_parse_result();
+ }
+ if(if_statem.next_symbol->type != ycf_symbol_type_else){
+ return fail_parse_result();
+ }
+ ycf_symbol* else_w = if_statem.next_symbol;
+ ycf_parse_result else_statement = parse_statement(else_w->next);
+ if(!else_statement.success){
+ return fail_parse_result();
+ }
+ return success_parse_result(else_statement.next_symbol,
+ ycf_node_if_else_new(if_statem.result->u.if_n,
+ else_w,
+ else_statement.result));
+}
+
+ycf_parse_result parse_while_statement(ycf_symbol* symbols){
+ ycf_parse_result cond_statem = parse_cond_statement(symbols, ycf_symbol_type_while);
+ if(!cond_statem.success){
+ return fail_parse_result();
+ }
+ return success_parse_result(cond_statem.next_symbol,
+ ycf_node_while_new(cond_statem.result->u.if_n.if_word,
+ cond_statem.result->u.if_n.expression,
+ cond_statem.result->u.if_n.if_statement));
+}
+
+ycf_parse_result parse_do_while_statement(ycf_symbol* symbols){
+ if(symbols->type != ycf_symbol_type_do){
+ return fail_parse_result();
+ }
+ ycf_symbol* do_word = symbols;
+ ycf_parse_result statement = parse_statement(do_word->next);
+ if(!statement.success || statement.next_symbol->type != ycf_symbol_type_while){
+ return fail_parse_result();
+ }
+ ycf_symbol* while_word = statement.next_symbol;
+ ycf_parse_result cond = parse_paran_expression(while_word->next);
+ if(!cond.success){
+ return fail_parse_result();
+ }
+ if(cond.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(cond.next_symbol->next,
+ ycf_node_do_while_new(do_word, statement.result, while_word,
+ cond.result->u.parentheses_expression, cond.next_symbol));
+}
+
+ycf_parse_result parse_for_statement(ycf_symbol* symbols){
+ if(symbols->type != ycf_symbol_type_for){
+ return fail_parse_result();
+ }
+ ycf_symbol* for_word = symbols;
+ if(for_word->next->type != ycf_symbol_type_open_parenthesis){
+ return fail_parse_result();
+ }
+ ycf_symbol* start_paran = for_word->next;
+ ycf_node* init = NULL;
+ ycf_parse_result init_res = parse_defenition_with_init(start_paran->next);
+ if(!init_res.success){
+ init_res = parse_defenition_no_init(start_paran->next);
+ }
+ if(!init_res.success){
+ init_res = parse_exp_statement(start_paran->next);
+ }
+ if(!init_res.success){
+ return fail_parse_result();
+ }
+ init = init_res.result;
+ ycf_node* stop_cond = NULL;
+ ycf_symbol* stop_cond_end = NULL;
+ if(init_res.next_symbol->type == ycf_symbol_type_semicolon){
+ stop_cond_end = init_res.next_symbol;
+ }else{
+ ycf_parse_result stop_cond_res = parse_expression_end_end_semicolon(init_res.next_symbol);
+ if(!stop_cond_res.success || stop_cond_res.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ stop_cond = stop_cond_res.result;
+ stop_cond_end = stop_cond_res.next_symbol;
+ }
+ ycf_node* end_exp = NULL;
+ ycf_symbol* end_exp_end = NULL;
+ if(stop_cond_end->next->type == ycf_symbol_type_end_parenthesis){
+ end_exp_end = stop_cond_end->next;
+ }else{
+ ycf_parse_result end_exp_res = parse_expression_end_end_paren(stop_cond_end->next);
+ if(!end_exp_res.success || end_exp_res.next_symbol->type != ycf_symbol_type_end_parenthesis){
+ return fail_parse_result();
+ }
+ end_exp = end_exp_res.result;
+ end_exp_end = end_exp_res.next_symbol;
+ }
+ ycf_parse_result for_statement = parse_statement(end_exp_end->next);
+ if(!for_statement.success){
+ return fail_parse_result();
+ }
+ return success_parse_result(for_statement.next_symbol,
+ ycf_node_for_new(for_word,
+ start_paran,
+ init,
+ stop_cond,
+ stop_cond_end,
+ end_exp,
+ end_exp_end,
+ for_statement.result));
+}
+
+
+ycf_parse_result parse_switch_statement(ycf_symbol* symbols){
+ ycf_parse_result cond_statem = parse_cond_statement(symbols, ycf_symbol_type_switch);
+ if(!cond_statem.success){
+ return fail_parse_result();
+ }
+ if(cond_statem.result->u.if_n.if_statement->type != ycf_node_type_code_scope){
+ return fail_parse_result();
+ }
+ return success_parse_result(cond_statem.next_symbol,
+ ycf_node_switch_new(cond_statem.result->u.if_n.if_word,
+ cond_statem.result->u.if_n.expression,
+ cond_statem.result->u.if_n.if_statement->u.code_scope));
+}
+
+ycf_parse_result parse_exp_statement(ycf_symbol* symbols){
+ if(symbols->type == ycf_symbol_type_semicolon){
+ /*Empty statement*/
+ return success_parse_result(symbols->next,
+ ycf_node_statement_new(ycf_node_expression_new(ycf_node_list_empty()),
+ symbols));
+ }
+ ycf_parse_result expression = parse_expression_end_end_semicolon(symbols);
+ if(!expression.success || expression.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(expression.next_symbol->next,
+ ycf_node_statement_new(expression.result,
+ expression.next_symbol));
+}
+
+ycf_parse_result parse_return_statement(ycf_symbol* symbols){
+ ycf_symbol* return_symbol = symbols;
+ if(return_symbol->type != ycf_symbol_type_return){
+ return fail_parse_result();
+ }
+ if(return_symbol->next->type == ycf_symbol_type_semicolon){
+ return success_parse_result(return_symbol->next->next,
+ ycf_node_return_new(return_symbol,
+ NULL,
+ return_symbol->next));
+ }
+ ycf_parse_result expression = parse_expression_end_end_semicolon(return_symbol->next);
+ if(!expression.success || expression.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(expression.next_symbol->next,
+ ycf_node_return_new(return_symbol,
+ expression.result,
+ expression.next_symbol));
+}
+
+ycf_parse_result parse_macro_command(ycf_symbol* symbols){
+ if(symbols->type == ycf_symbol_type_macro_command || symbols->type == ycf_symbol_type_macro_define){
+ return success_parse_result(symbols->next, ycf_node_macro_cmd_new(symbols));
+ } else {
+ return fail_parse_result();
+ }
+}
+
+ycf_parse_result parse_scope(ycf_symbol* symbols);
+
+ycf_parse_result parse_special_code_block(ycf_symbol* symbols, char* code_block_name, ycf_node_type type){
+ ycf_symbol* start = symbols;
+ if(symbols->type != ycf_symbol_type_special_code_start ||
+ !ycf_symbol_is_text_eq(start,
+ ycf_string_new("/*special_code_start:%s*/", code_block_name))){
+ return fail_parse_result();
+ }
+ ycf_parse_result code = parse_if_statement(start->next);
+ if(!code.success){
+ return fail_parse_result();
+ }
+ ycf_symbol* end = code.next_symbol;
+ if(end->type != ycf_symbol_type_special_code_end){
+ return fail_parse_result();
+ }
+ return success_parse_result(end->next,
+ ycf_node_special_code_block_new(type,
+ start,
+ code.result->u.if_n,
+ end));
+}
+
+ycf_parse_result parse_on_save_yield_state(ycf_symbol* symbols){
+ return parse_special_code_block(symbols, "ON_SAVE_YIELD_STATE", ycf_node_type_on_save_yield_state_code);
+}
+
+ycf_parse_result parse_on_restore_yield_state(ycf_symbol* symbols){
+ return parse_special_code_block(symbols, "ON_RESTORE_YIELD_STATE", ycf_node_type_on_restore_yield_state_code);
+}
+
+ycf_parse_result parse_destroy_state_code(ycf_symbol* symbols){
+ ycf_parse_result res = parse_special_code_block(symbols, "ON_DESTROY_STATE", ycf_node_type_on_destroy_state_code);
+ return res;
+}
+
+ycf_parse_result parse_on_return_code(ycf_symbol* symbols){
+ ycf_parse_result res = parse_special_code_block(symbols, "ON_RETURN", ycf_node_type_on_return_code);
+ return res;
+}
+
+ycf_parse_result parse_on_destroy_state_or_return_code(ycf_symbol* symbols){
+ ycf_parse_result res = parse_special_code_block(symbols, "ON_DESTROY_STATE_OR_RETURN", ycf_node_type_on_destroy_state_or_return_code);
+ return res;
+}
+
+ycf_parse_result parse_consume_reds(ycf_symbol* symbols){
+ ycf_symbol* consume_reds_symbol = symbols;
+ if(consume_reds_symbol->type != ycf_symbol_type_consume_reds){
+ return fail_parse_result();
+ }
+ ycf_parse_result paran_expression =
+ parse_paran_expression(consume_reds_symbol->next);
+ if(!paran_expression.success){
+ return fail_parse_result();
+ }
+ if(paran_expression.next_symbol->type != ycf_symbol_type_semicolon){
+ return fail_parse_result();
+ }
+ return success_parse_result(paran_expression.next_symbol->next,
+ ycf_node_consume_reds_new(consume_reds_symbol,
+ paran_expression.result->u.parentheses_expression,
+ paran_expression.next_symbol));
+}
+
+ycf_parse_result parse_statement(ycf_symbol* symbols){
+ int number_of_parsers = 22;
+ ycf_parse_result (*parsers[])(ycf_symbol *) = {
+ parse_defenition_no_init,
+ parse_defenition_with_init,
+ parse_if_else_statement,
+ parse_if_statement,
+ parse_while_statement,
+ parse_do_while_statement,
+ parse_for_statement,
+ parse_switch_statement,
+ parse_scope,
+ parse_goto,
+ parse_return_statement,
+ parse_consume_reds,
+ parse_function_call_statement,
+ parse_function_call_assignment_statement,
+ parse_assignment,
+ parse_on_save_yield_state,
+ parse_on_restore_yield_state,
+ parse_on_return_code,
+ parse_on_destroy_state_or_return_code,
+ parse_destroy_state_code,
+ parse_macro_command,
+ parse_exp_statement
+ };
+ for(int i = 0; i < number_of_parsers; i++){
+ ycf_parse_result res = parsers[i](symbols);
+ if(res.success){
+ return res;
+ }
+ }
+ return fail_parse_result();
+}
+
+ycf_parse_result parse_scope(ycf_symbol* symbols){
+ ycf_symbol* current = symbols;
+ ycf_symbol* start;
+ if(current->type != ycf_symbol_type_open_curly_brace){
+ return fail_parse_result();
+ }
+ start = current;
+ current = current->next;
+ int number_of_parsers = 2;
+ ycf_parse_result (*parsers[])(ycf_symbol *) = {
+ parse_defenition_no_init,
+ parse_defenition_with_init
+ };
+ parse_list_res decs = parse_list(number_of_parsers, parsers, current);
+ current = decs.next_symbol;
+ /* parse rest */
+ number_of_parsers = 1;
+ ycf_parse_result (*rest_parsers[])(ycf_symbol *) = {
+ parse_statement
+ };
+ parse_list_res others =
+ parse_list_break_symbol(number_of_parsers,
+ rest_parsers,
+ current,
+ ycf_symbol_type_end_curly_brace);
+ current = others.next_symbol;
+ if (current == NULL) {
+ return fail_parse_result();
+ }
+ return success_parse_result(current->next, ycf_node_scope_new(start,
+ decs.list,
+ others.list,
+ current));
+}
+
+ycf_parse_result parse_function(ycf_symbol* symbols){
+ ycf_parse_result fun_head = parse_function_head(symbols, ycf_symbol_type_open_curly_brace, true);
+ if(!fun_head.success){
+ return fail_parse_result();
+ }
+ ycf_parse_result scope = parse_scope(fun_head.next_symbol);
+ if(!scope.success){
+ return fail_parse_result();
+ }
+ return success_parse_result(scope.next_symbol,
+ ycf_node_function_new(fun_head.result->u.function_definition,
+ scope.result->u.code_scope));
+}
+
+ycf_parse_result parse_c_file(ycf_symbol* symbols){
+ int number_of_parsers = 5;
+ ycf_parse_result (*parsers[])(ycf_symbol *) = {
+ parse_defenition_no_init,
+ parse_defenition_with_init,
+ parse_function_def,
+ parse_function,
+ parse_other
+ };
+ parse_list_res program_list =
+ parse_list(number_of_parsers, parsers, symbols);
+ if(program_list.next_symbol != NULL){
+ return fail_parse_result();
+ } else {
+ return success_parse_result(NULL,
+ ycf_node_c_file_new(program_list.list));
+ }
+}
+
+
+ycf_node* get_abstract_syntax_tree_root(ycf_symbol_list* symbols){
+ ycf_parse_result res = parse_c_file(symbols->head);
+ if(!res.success){
+ printf("ERROR: Could not parse file\n");
+ exit(1);
+ }
+ return res.result;
+}
+
+ycf_node* ycf_node_deep_copy(ycf_node *n) {
+ ycf_string_printable_buffer *b = ycf_string_printable_buffer_new();
+ ycf_node_print(n, b);
+ ycf_symbol_list symbols = ycf_symbol_list_from_text(b->buffer);
+ ycf_parse_result res;
+ if (n->type == ycf_node_type_c_file) {
+ res = parse_c_file(symbols.head);
+ } else if (n->type == ycf_node_type_variable_definition ||
+ n->type == ycf_node_type_variable_definition_init ||
+ n->type == ycf_node_type_other ||
+ n->type == ycf_node_type_code_scope ||
+ n->type == ycf_node_type_assignment ||
+ n->type == ycf_node_type_yield ||
+ n->type == ycf_node_type_statement ||
+ n->type == ycf_node_type_if ||
+ n->type == ycf_node_type_if_else ||
+ n->type == ycf_node_type_while ||
+ n->type == ycf_node_type_do_while ||
+ n->type == ycf_node_type_switch ||
+ n->type == ycf_node_type_for ||
+ n->type == ycf_node_type_assignment_function_call ||
+ n->type == ycf_node_type_on_save_yield_state_code ||
+ n->type == ycf_node_type_on_restore_yield_state_code ||
+ n->type == ycf_node_type_on_destroy_state_code ||
+ n->type == ycf_node_type_on_return_code ||
+ n->type == ycf_node_type_on_destroy_state_or_return_code ||
+ n->type == ycf_node_type_goto ||
+ n->type == ycf_node_type_return_statement ||
+ n->type == ycf_node_type_consume_reds) {
+ res = parse_statement(symbols.head);
+ } else if (n->type == ycf_node_type_function_declaration) {
+ res = parse_function_def(symbols.head);
+ } else if (n->type == ycf_node_type_function_definition) {
+ res = parse_function(symbols.head);
+ } else if (n->type == ycf_node_type_function_call) {
+ res = parse_function_call(symbols.head);
+ } else if (n->type == ycf_node_type_expression) {
+ res = parse_expression(symbols.head);
+ } else if (n->type == ycf_node_type_parentheses_expression) {
+ res = parse_paran_expression(symbols.head);
+ } else if (n->type == ycf_node_type_comma) {
+ res = parse_comma(symbols.head);
+ } else if (n->type == ycf_node_type_array_bracket) {
+ res = parse_array_bracket(symbols.head);
+ } else if (n->type == ycf_node_type_macro_cmd) {
+ res = parse_macro_command(symbols.head);
+ } else if (n->type == ycf_node_type_period_field_access) {
+ res = parse_period_field_access_node(symbols.head);
+ } else if (n->type == ycf_node_type_pointer_field_access) {
+ res = parse_pointer_field_access_node(symbols.head);
+ } else {
+ fprintf(stderr, "Unknown node type %d\n", n->type);
+ exit(1);
+ }
+ if(!res.success) {
+ fprintf(stderr, "An error has been detected in the function ycf_node_deep_copy\n");
+ exit(1);
+ }
+ return res.result;
+}
+
diff --git a/erts/lib_src/yielding_c_fun/ycf_parser.h b/erts/lib_src/yielding_c_fun/ycf_parser.h
new file mode 100644
index 0000000000..566c7ec503
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_parser.h
@@ -0,0 +1,27 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#include "ycf_node.h"
+
+ycf_node* get_abstract_syntax_tree_root(ycf_symbol_list* symbols);
diff --git a/erts/lib_src/yielding_c_fun/ycf_printers.c b/erts/lib_src/yielding_c_fun/ycf_printers.c
new file mode 100644
index 0000000000..0cebfc5ebc
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_printers.c
@@ -0,0 +1,493 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ycf_yield_fun.h"
+#include "ycf_node.h"
+
+void print_node_code_expression(ycf_node_expression e, ycf_string_printable_buffer* b);
+
+void print_symbol_code(ycf_symbol* s, ycf_string_printable_buffer* b){
+ if(s == NULL){
+ return;
+ }
+ print_symbol_code(s->whitespace_or_comment_before, b);
+ ycf_string_printable_buffer_printf(b, "%s", ycf_symbol_get_text(s));
+}
+
+void print_symbol_list(ycf_symbol_list* l, ycf_string_printable_buffer* b){
+ ycf_symbol* s = l->head;
+ while(s != NULL){
+ print_symbol_code(s, b);
+ s = s->next;
+ }
+}
+
+void print_node_code_array_bracket(ycf_node_array_bracket n, ycf_string_printable_buffer* b){
+ print_symbol_code(n.start, b);
+ if(!n.empty){
+ print_node_code_expression(n.content, b);
+ }
+ print_symbol_code(n.end, b);
+}
+
+void print_node_code_definition_custom_end(ycf_node_definition d, bool dyn_array_to_ptr, ycf_symbol* end, ycf_string_printable_buffer* b){
+ int nr_of_empty_brackets = 0;
+ {
+ ycf_node* current = d.array_brackets.head;
+ while(current != NULL){
+ if(current->u.array_bracket.empty){
+ nr_of_empty_brackets++;
+ }
+ current = current->next;
+ }
+ }
+ print_symbol_list(&d.type_specifiers, b);
+ if(dyn_array_to_ptr){
+ for(int i = 0; i < nr_of_empty_brackets; i++){
+ ycf_string_printable_buffer_printf(b, "*");
+ }
+ }
+ print_symbol_code(d.identifier, b);
+ if (!dyn_array_to_ptr || nr_of_empty_brackets == 0){
+ print_node_list_code(d.array_brackets.head, b);
+ }
+ print_symbol_code(end, b);
+}
+
+void print_node_code_definition(ycf_node_definition d, ycf_string_printable_buffer* b){
+ print_node_code_definition_custom_end(d, false, d.end, b);
+}
+
+void print_node_code_definition_init(ycf_node_definition_init d, ycf_string_printable_buffer* b){
+ print_node_code_definition(d.definition, b);
+ print_symbol_list(&d.initializer_expression, b);
+ print_symbol_code(d.end, b);
+}
+
+void print_node_list_code(ycf_node* n, ycf_string_printable_buffer* b){
+ while(n != NULL){
+ ycf_node_print(n, b);
+ n = n->next;
+ }
+}
+
+void print_node_code_function_def_parameters(ycf_node_function_definition f_def, ycf_string_printable_buffer* b){
+ if(f_def.ignore_param_ending){
+ ycf_node* n = f_def.parameters.head;
+ while(n != NULL){
+ if(n->next == NULL){
+ print_node_code_definition_custom_end(n->u.definition, false, ycf_symbol_new_parenthesis(), b);
+ }else{
+ print_node_code_definition_custom_end(n->u.definition, false, ycf_symbol_new_comma(), b);
+ }
+ n = n->next;
+ }
+ if(f_def.end.head != NULL && f_def.end.head->type == ycf_symbol_type_end_parenthesis){
+ ycf_symbol_list end = f_def.end;
+ end.head = end.head->next;
+ print_symbol_list(&end, b);
+ }else if(f_def.end.head != NULL && f_def.end.head->type != ycf_symbol_type_void){
+ print_symbol_list(&f_def.end, b);
+ }
+ }else {
+ print_node_list_code(f_def.parameters.head, b);
+ print_symbol_list(&f_def.end, b);
+ }
+}
+void print_node_code_function_def(ycf_node_function_definition f_def, ycf_string_printable_buffer* b){
+ print_node_code_definition(f_def.definition, b);
+ print_node_code_function_def_parameters(f_def, b);
+}
+
+void print_node_code_scope(ycf_node_code_scope s, ycf_string_printable_buffer* b){
+ print_symbol_code(s.start, b);
+ print_node_list_code(s.definition_nodes.head, b);
+ print_node_list_code(s.other_nodes.head, b);
+ print_symbol_code(s.end, b);
+}
+
+void print_node_code_function(ycf_node_function f, ycf_string_printable_buffer* b){
+ print_node_code_function_def(f.definition, b);
+ print_node_code_scope(f.body, b);
+}
+
+void print_node_code_assignment(ycf_node_assignment a, ycf_string_printable_buffer* b){
+ print_node_code_expression(a.left_side, b);
+ print_symbol_code(a.assignment_symbol, b);
+ print_node_code_expression(a.right_side, b);
+ print_symbol_code(a.end, b);
+}
+
+void print_node_code_gen_struct(ycf_node_gen_typedef_struct n, ycf_string_printable_buffer* b){
+ ycf_string_printable_buffer_printf(b, "\n\n\nstruct %s {", n.name);
+ ycf_node* current = n.definition_nodes.head;
+ while(current != NULL){
+ print_node_code_definition_custom_end(current->u.definition, true, ycf_symbol_new_semicolon(), b);
+ current = current->next;
+ }
+ ycf_string_printable_buffer_printf(b, "\n};\n");
+}
+
+void print_node_code_yield(ycf_node_yield n, ycf_string_printable_buffer* b){
+ print_symbol_code(n.yield_symbol,b);
+ print_symbol_code(n.end_symbol,b);
+
+}
+
+void print_node_code_function_call(ycf_node_function_call n, ycf_string_printable_buffer* b){
+ print_symbol_list(&n.neg_symbols, b);
+ print_symbol_code(n.identifier, b);
+ print_symbol_code(n.start_symbol, b);
+ print_node_list_code(n.parameter_expressions.head, b);
+ print_symbol_code(n.end_symbol, b);
+}
+
+void print_node_code_expression(ycf_node_expression e, ycf_string_printable_buffer* b){
+ print_node_list_code(e.content.head, b);
+}
+
+
+void print_node_code_paran_expression(ycf_node_parentheses_expression e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.start_symbol, b);
+ print_node_code_expression(e.content, b);
+ print_symbol_code(e.end_symbol, b);
+}
+
+void print_node_code_consume_reds(ycf_node_consume_reds e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.consume_reds_symbol, b);
+ print_node_code_paran_expression(e.nr_of_reds_expression, b);
+ print_symbol_code(e.end_symbol, b);
+}
+
+void print_node_code_if_statement(ycf_node_if e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.if_word, b);
+ print_node_code_paran_expression(e.expression, b);
+ ycf_node_print(e.if_statement, b);
+}
+
+void print_node_code_while_statement(ycf_node_while e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.while_word, b);
+ print_node_code_paran_expression(e.expression, b);
+ ycf_node_print(e.statement, b);
+}
+
+void print_node_code_do_while_statement(ycf_node_do_while e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.do_word, b);
+ ycf_node_print(e.statement, b);
+ print_symbol_code(e.while_word, b);
+ print_node_code_paran_expression(e.expression, b);
+ print_symbol_code(e.end, b);
+}
+
+void print_node_code_switch_statement(ycf_node_switch e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.switch_word, b);
+ print_node_code_paran_expression(e.expression, b);
+ print_node_code_scope(e.scope, b);
+}
+
+void print_node_code_for_statement(ycf_node_for e, ycf_string_printable_buffer* b){
+ print_symbol_code(e.for_word, b);
+ print_symbol_code(e.start_parentheses, b);
+ ycf_node_print(e.init, b);
+ ycf_node_print(e.stop_cond, b);
+ print_symbol_code(e.stop_cond_end, b);
+ ycf_node_print(e.end_exp, b);
+ print_symbol_code(e.end_parentheses, b);
+ ycf_node_print(e.statement, b);
+}
+
+void print_node_code_if_else_statement(ycf_node_if_else e, ycf_string_printable_buffer* b){
+ print_node_code_if_statement(e.if_part, b);
+ print_symbol_code(e.else_word, b);
+ ycf_node_print(e.else_statement, b);
+}
+
+void print_node_code_for_assignment_fun_call(ycf_node_function_call_assignment e, ycf_string_printable_buffer* b){
+ print_node_code_expression(e.left_side, b);
+ print_symbol_code(e.assignment_symbol, b);
+ print_node_code_function_call(e.fun_call, b);
+}
+
+void print_node_code_special_code_block(ycf_node_special_code_block block, ycf_string_printable_buffer* b){
+ print_symbol_code(block.start, b);
+ print_node_code_if_statement(block.code, b);
+ print_symbol_code(block.end, b);
+
+}
+
+void print_node_code_goto(ycf_node_goto n, ycf_string_printable_buffer* b){
+ print_symbol_code(n.goto_symbol, b);
+ print_symbol_code(n.label_symbol, b);
+ print_symbol_code(n.end_symbol, b);
+}
+
+void print_node_code_period_field_access(ycf_node_period_field_access n, ycf_string_printable_buffer* b){
+ print_symbol_code(n.period, b);
+ print_symbol_code(n.field_name, b);
+}
+
+void print_node_code_pointer_field_access(ycf_pointer_field_access n, ycf_string_printable_buffer* b){
+ print_symbol_code(n.pointer, b);
+ print_symbol_code(n.field_name, b);
+}
+
+void print_node_code_return(ycf_node_return n, ycf_string_printable_buffer* b){
+ print_symbol_code(n.return_symbol, b);
+ if (n.return_expression != NULL) {
+ ycf_node_print(n.return_expression, b);
+ }
+ print_symbol_code(n.end_symbol, b);
+}
+
+void ycf_node_print(ycf_node* node, ycf_string_printable_buffer* b){
+ if(node == NULL){
+ return;
+ } else if(node->type == ycf_node_type_c_file){
+ print_node_list_code(node->u.c_file.content.head, b);
+ } else if(node->type == ycf_node_type_variable_definition){
+ print_node_code_definition(node->u.definition, b);
+ } else if(node->type == ycf_node_type_variable_definition_init){
+ print_node_code_definition_init(node->u.definition_init, b);
+ } else if(node->type == ycf_node_type_function_declaration){
+ print_node_code_function_def(node->u.function_definition, b);
+ } else if(node->type == ycf_node_type_other){
+ print_symbol_code(node->u.other.what, b);
+ } else if(node->type == ycf_node_type_code_scope){
+ print_node_code_scope(node->u.code_scope, b);
+ }else if(node->type == ycf_node_type_function_definition){
+ print_node_code_function(node->u.function, b);
+ }else if(node->type == ycf_node_type_assignment){
+ print_node_code_assignment(node->u.a, b);
+ }else if(node->type == ycf_node_type_gen_typedef_struct){
+ print_node_code_gen_struct(node->u.gen_typedef_struct, b);
+ }else if(node->type == ycf_node_type_yield){
+ print_node_code_yield(node->u.yield, b);
+ } else if(node->type == ycf_node_type_statement){
+ ycf_node_print(node->u.statement.expression, b);
+ print_symbol_code(node->u.statement.end_symbol, b);
+ } else if(node->type == ycf_node_type_function_call){
+ print_node_code_function_call(node->u.function_call, b);
+ } else if(node->type == ycf_node_type_expression){
+ print_node_code_expression(node->u.expression, b);
+ } else if(node->type == ycf_node_type_parentheses_expression){
+ print_node_code_paran_expression(node->u.parentheses_expression, b);
+ } else if(node->type == ycf_node_type_if){
+ print_node_code_if_statement(node->u.if_n, b);
+ }else if(node->type == ycf_node_type_if_else){
+ print_node_code_if_else_statement(node->u.if_else, b);
+ }else if(node->type == ycf_node_type_while){
+ print_node_code_while_statement(node->u.while_n, b);
+ }else if(node->type == ycf_node_type_do_while){
+ print_node_code_do_while_statement(node->u.do_while, b);
+ }else if(node->type == ycf_node_type_switch){
+ print_node_code_switch_statement(node->u.switch_n, b);
+ }else if(node->type == ycf_node_type_for){
+ print_node_code_for_statement(node->u.for_n, b);
+ }else if(node->type == ycf_node_type_assignment_function_call){
+ print_node_code_for_assignment_fun_call(node->u.function_call_assignment, b);
+ } else if(node->type == ycf_node_type_comma){
+ print_symbol_code(node->u.comma.comma_symbol, b);
+ } else if(node->type == ycf_node_type_array_bracket){
+ print_node_code_array_bracket(node->u.array_bracket, b);
+ } else if(node->type == ycf_node_type_macro_cmd){
+ print_symbol_code(node->u.macro_cmd.symbol, b);
+ } else if(node->type == ycf_node_type_on_save_yield_state_code ||
+ node->type == ycf_node_type_on_restore_yield_state_code ||
+ node->type == ycf_node_type_on_destroy_state_code ||
+ node->type == ycf_node_type_on_return_code ||
+ node->type == ycf_node_type_on_destroy_state_or_return_code){
+ print_node_code_special_code_block(node->u.special_code_block, b);
+ } else if(node->type == ycf_node_type_consume_reds){
+ print_node_code_consume_reds(node->u.consume_reds, b);
+ } else if(node->type == ycf_node_type_goto){
+ print_node_code_goto(node->u.goto_n, b);
+ } else if(node->type == ycf_node_type_return_statement){
+ print_node_code_return(node->u.return_n, b);
+ } else if(node->type == ycf_node_type_period_field_access){
+ print_node_code_period_field_access(node->u.period_field_access, b);
+ } else if(node->type == ycf_node_type_pointer_field_access){
+ print_node_code_pointer_field_access(node->u.pointer_field_access, b);
+ } else {
+ fprintf(stderr, "Unknown node type %d\n", node->type);
+ exit(1);
+ }
+}
+
+
+void print_definition(ycf_node_definition d){
+ printf("NODE: definition (type=%s,%s=%s)\n",
+ ycf_symbol_text_between(d.type_specifiers.head,
+ d.type_specifiers.last),
+ get_symbol_type_text(d.identifier->type),
+ ycf_symbol_get_text(d.identifier) );
+}
+
+void print_scope(ycf_node_code_scope node){
+ printf("NODE: scope\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ printf("Defenition Nodes:\n");
+ struct ycf_node* n = node.definition_nodes.head;
+ while(n != NULL){
+ print_abstract_syntax_tree(n);
+ n = n->next;
+ }
+ printf("Other Nodes:\n");
+ n = node.other_nodes.head;
+ while(n != NULL){
+ print_abstract_syntax_tree(n);
+ n = n->next;
+ }
+ printf("END SCOPE\n");
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+}
+
+void print_function_def(ycf_node_function_definition node){
+ printf("NODE: function def:\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ printf("definition:\n");
+ print_definition(node.definition);
+ printf("parameters:\n");
+ struct ycf_node* n = node.parameters.head;
+ while(n != NULL){
+ print_abstract_syntax_tree(n);
+ n = n->next;
+ }
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+}
+
+void print_fun_call(ycf_node_function_call f_call){
+ printf("NODE: fun_call %s parameters:\n", ycf_symbol_get_text(f_call.identifier));
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ struct ycf_node* current = f_call.parameter_expressions.head;
+ int i = 1;
+ while(current != NULL){
+ printf("param %d: \n", i);
+ ycf_node_print(current, NULL);
+ current = current->next;
+ i++;
+ }
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+}
+
+void print_abstract_syntax_tree(ycf_node* node){
+ printf("%p\n",(void*)node);
+ if(node == NULL){
+ return;
+ } else if(node->type == ycf_node_type_c_file){
+ printf("NODE: c_file\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ struct ycf_node* n = node->u.c_file.content.head;
+ while(n != NULL){
+ print_abstract_syntax_tree(n);
+ n = n->next;
+ }
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ } else if(node->type == ycf_node_type_variable_definition){
+ print_definition(node->u.definition);
+ } else if(node->type == ycf_node_type_variable_definition_init){
+ printf("NODE: definition_init (type=%s,%s=%s,init=%s)\n",
+ ycf_symbol_text_between(node->u.definition_init.definition.type_specifiers.head,
+ node->u.definition_init.definition.type_specifiers.last),
+ get_symbol_type_text(node->u.definition_init.definition.identifier->type),
+ ycf_symbol_get_text(node->u.definition_init.definition.identifier),
+ ycf_symbol_text_between(node->u.definition_init.initializer_expression.head,
+ node->u.definition_init.initializer_expression.last));
+ } else if(node->type == ycf_node_type_function_declaration){
+ print_function_def(node->u.function_definition);
+ } else if(node->type == ycf_node_type_other){
+ printf("NODE: other (%s)\n", get_symbol_type_text(node->u.other.what->type));
+ } else if(node->type == ycf_node_type_code_scope){
+ print_scope(node->u.code_scope);
+ }else if(node->type == ycf_node_type_function_definition){
+ printf("NODE: function\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ print_function_def(node->u.function.definition);
+ print_scope(node->u.function.body);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_assignment){
+ printf("NODE: assignment\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ print_node_code_assignment(node->u.a, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_yield){
+ printf("NODE: yield\n");
+ }else if(node->type == ycf_node_type_statement){
+ printf("NODE: statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ print_abstract_syntax_tree(node->u.statement.expression);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_if){
+ printf("NODE: if_statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_if_else){
+ printf("NODE: if_else_statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_while){
+ printf("NODE: while_statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_do_while){
+ printf("NODE: do_while_statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_for){
+ printf("NODE: for_statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }else if(node->type == ycf_node_type_switch){
+ printf("NODE: switch_statement\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ } else if(node->type == ycf_node_type_function_call) {
+ print_fun_call(node->u.function_call);
+ } else if(node->type == ycf_node_type_assignment_function_call) {
+ printf("NODE: assignment fun call\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ printf("Assignment expression:\n");
+ print_node_code_expression(node->u.function_call_assignment.left_side, NULL);
+ print_fun_call(node->u.function_call_assignment.fun_call);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+
+
+ } else {
+ printf("NODE: OTHER???\n");
+ printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
+ ycf_node_print(node, NULL);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }
+
+}
+
diff --git a/erts/lib_src/yielding_c_fun/ycf_printers.h b/erts/lib_src/yielding_c_fun/ycf_printers.h
new file mode 100644
index 0000000000..1cc23165c8
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_printers.h
@@ -0,0 +1,30 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#include "ycf_node.h"
+
+void print_node_code_function_def_parameters(ycf_node_function_definition f_def, ycf_string_printable_buffer* b);
+void print_node_code_function_def(ycf_node_function_definition f_def, ycf_string_printable_buffer* b);
+void print_node_list_code(ycf_node* n, ycf_string_printable_buffer* b);
+
diff --git a/erts/lib_src/yielding_c_fun/ycf_string.c b/erts/lib_src/yielding_c_fun/ycf_string.c
new file mode 100644
index 0000000000..aabb0c3c61
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_string.c
@@ -0,0 +1,111 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ycf_string.h"
+#include "ycf_lists.h"
+#include "ycf_utils.h"
+
+bool ycf_string_is_equal(const char* str1, const char* str2)
+{
+ size_t str1_length = strlen(str1);
+ size_t str2_length = strlen(str2);
+ return
+ str1_length == str2_length &&
+ strncmp(str1, str2, str1_length) == 0;
+}
+
+
+ycf_string_item* ycf_string_item_new(char* str){
+ ycf_string_item* item = ycf_malloc(sizeof(ycf_string_item));
+ item->str = str;
+ item->next = NULL;
+ return item;
+}
+
+char* ycf_string_new(char* format, ...){
+ va_list args;
+ va_start (args, format);
+ int n = vsnprintf(NULL, 0, format, args);
+ va_end (args);
+ char* new = ycf_malloc(n +1);
+ va_start (args, format);
+ vsnprintf(new, n +1, format, args);
+ va_end (args);
+ return new;
+}
+
+
+ycf_string_printable_buffer* ycf_string_printable_buffer_new(){
+ const size_t init_size = 128;
+ ycf_string_printable_buffer* b = ycf_malloc(sizeof(ycf_string_printable_buffer));
+ b->current_pos = 0;
+ b->buffer = ycf_malloc(init_size);
+ b->size = init_size;
+ return b;
+}
+
+void ycf_string_printable_buffer_printf(ycf_string_printable_buffer* buf, char* format, ...){
+ va_list args;
+ if(buf == NULL){
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ return;
+ }
+ va_start (args, format);
+ int n = vsnprintf(NULL, 0, format, args) + 1;
+ va_end (args);
+ while(buf->current_pos + n + 64 > buf->size){
+ char* new_buf = ycf_malloc(buf->size * 2);
+ for(int i = 0; i < buf->size; i++){
+ new_buf[i] = buf->buffer[i];
+ }
+ buf->buffer = new_buf;
+ buf->size = buf->size * 2;
+ }
+ va_start (args, format);
+ vsnprintf(&buf->buffer[buf->current_pos], n, format, args);
+ va_end (args);
+ buf->current_pos = buf->current_pos + n - 1;
+}
+
+bool ycf_string_item_list_contains(ycf_string_item_list* l, char* str){
+ ycf_string_item* current = l->head;
+ while(current != NULL){
+ if(strcmp(current->str, str) == 0){
+ return true;
+ }
+ current = current->next;
+ }
+ return false;
+}
+
+
+GENERATE_LIST_FUNCTIONS(ycf_string_item)
diff --git a/erts/lib_src/yielding_c_fun/ycf_string.h b/erts/lib_src/yielding_c_fun/ycf_string.h
new file mode 100644
index 0000000000..0c19e08572
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_string.h
@@ -0,0 +1,89 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#ifndef YIELDING_C_FUN_YCF_STRING_H
+#define YIELDING_C_FUN_YCF_STRING_H
+
+#include <stdlib.h>
+#include "ycf_utils.h"
+
+/* Types for printable buffers */
+
+typedef struct {
+ char* buffer;
+ size_t current_pos;
+ size_t size;
+} ycf_string_printable_buffer;
+
+/* Types for string lists */
+
+typedef struct ycf_string_item {
+ char* str;
+ struct ycf_string_item* next;
+} ycf_string_item;
+
+typedef struct string_item_list {
+ ycf_string_item* head;
+ ycf_string_item* last;
+} ycf_string_item_list;
+
+
+bool ycf_string_is_equal(const char* str1, const char* str2);
+ycf_string_item* ycf_string_item_new(char* str);
+char* ycf_string_new(char* format, ...);
+
+/* Functions for printable buffers */
+
+ycf_string_printable_buffer* ycf_string_printable_buffer_new(void);
+void ycf_string_printable_buffer_printf(ycf_string_printable_buffer* buf, char* format, ...);
+
+/* Functions for string lists */
+
+int ycf_string_item_list_get_item_position(ycf_string_item_list* list, ycf_string_item* node);
+
+bool ycf_string_item_list_contains(ycf_string_item_list* l, char* str);
+
+ycf_string_item* ycf_string_item_shallow_copy(ycf_string_item* n);
+ycf_string_item* ycf_string_item_list_get_item_at_position(ycf_string_item_list* list, int pos);
+
+void ycf_string_item_list_append(ycf_string_item_list* list, ycf_string_item* node);
+void ycf_string_item_list_prepend(ycf_string_item_list* list, ycf_string_item* node);
+void ycf_string_item_list_insert_before(ycf_string_item_list* list, ycf_string_item* before_this, ycf_string_item* to_insert);
+void ycf_string_item_list_insert_after(ycf_string_item_list* list, ycf_string_item* after_this, ycf_string_item* to_insert);
+void ycf_string_item_list_remove(ycf_string_item_list* list, ycf_string_item* to_remove);
+void ycf_string_item_list_replace(ycf_string_item_list* list, ycf_string_item* to_replace, ycf_string_item* replace_with);
+void ycf_string_item_list_concat(ycf_string_item_list* list1, ycf_string_item_list* list2);
+
+ycf_string_item_list ycf_string_item_list_empty();
+ycf_string_item_list ycf_string_item_list_shallow_copy(ycf_string_item_list n);
+ycf_string_item_list ycf_string_item_list_copy_append(ycf_string_item_list list, ycf_string_item* node);
+ycf_string_item_list ycf_string_item_list_copy_prepend(ycf_string_item_list list, ycf_string_item* node);
+ycf_string_item_list ycf_string_item_list_copy_insert_before(ycf_string_item_list list, ycf_string_item* before_this, ycf_string_item* to_insert);
+ycf_string_item_list ycf_string_item_list_copy_insert_after(ycf_string_item_list list, ycf_string_item* after_this, ycf_string_item* to_insert);
+ycf_string_item_list ycf_string_item_list_copy_remove(ycf_string_item_list list, ycf_string_item* to_remove);
+ycf_string_item_list ycf_string_item_list_copy_replace(ycf_string_item_list list, ycf_string_item* to_replace, ycf_string_item* replace_with);
+ycf_string_item_list ycf_string_item_list_copy_concat(ycf_string_item_list list1, ycf_string_item_list list2);
+
+
+#endif //YIELDING_C_FUN_YCF_STRING_H
diff --git a/erts/lib_src/yielding_c_fun/ycf_symbol.c b/erts/lib_src/yielding_c_fun/ycf_symbol.c
new file mode 100644
index 0000000000..826aac3afd
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_symbol.c
@@ -0,0 +1,166 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ycf_symbol.h"
+#include "ycf_string.h"
+#include "ycf_utils.h"
+#include "ycf_lists.h"
+
+
+
+ycf_symbol* ycf_symbol_copy(ycf_symbol* symbol){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = symbol->source;
+ new_symbol->start = symbol->start;
+ new_symbol->stop = symbol->stop;
+ new_symbol->type = symbol->type;
+ new_symbol->whitespace_or_comment_before = symbol->whitespace_or_comment_before;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_copy_change_text(ycf_symbol* to_copy, char* new_text){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = new_text;
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(new_text);
+ new_symbol->type = to_copy->type;
+ new_symbol->whitespace_or_comment_before = to_copy->whitespace_or_comment_before;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_new_something_else(char* text){
+ ycf_symbol* new = ycf_malloc(sizeof(ycf_symbol));
+ new->type = ycf_symbol_type_something_else;
+ new->next = NULL;
+ new->source = text;
+ new->whitespace_or_comment_before = NULL;
+ new->start = 0;
+ new->stop = strlen(text);
+ return new;
+}
+
+ycf_symbol* ycf_symbol_new_semicolon(){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = ";";
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(";");
+ new_symbol->type = ycf_symbol_type_semicolon;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_new_identifier(char* name){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = name;
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(new_symbol->source);
+ new_symbol->type = ycf_symbol_type_identifier;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_new_star(){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = "*";
+ new_symbol->start = 0;
+ new_symbol->stop = strlen("*");
+ new_symbol->type = ycf_symbol_type_star;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_new_parenthesis(){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = ")";
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(")");
+ new_symbol->type = ycf_symbol_type_semicolon;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_new_open_curly_brace(){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = "\n{\n";
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(new_symbol->source);
+ new_symbol->type = ycf_symbol_type_open_curly_brace;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+ycf_symbol* ycf_symbol_new_end_curly_brace(){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = "\n}\n";
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(new_symbol->source);
+ new_symbol->type = ycf_symbol_type_end_curly_brace;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+
+ycf_symbol* ycf_symbol_new_comma(){
+ ycf_symbol* new_symbol = ycf_malloc(sizeof(ycf_symbol));
+ new_symbol->next = NULL;
+ new_symbol->source = ",";
+ new_symbol->start = 0;
+ new_symbol->stop = strlen(",");
+ new_symbol->type = ycf_symbol_type_semicolon;
+ new_symbol->whitespace_or_comment_before = NULL;
+ return new_symbol;
+}
+
+
+char* ycf_symbol_get_text(ycf_symbol* symbol){
+ int size = symbol->stop - symbol->start;
+ char* str = ycf_malloc(size+1);
+ strncpy(str, &symbol->source[symbol->start], size);
+ str[size] = 0;
+ return str;
+}
+
+char* ycf_symbol_list_to_str(ycf_symbol_list* l){
+ ycf_symbol* s = l->head;
+ char* str = "";
+ while(s != NULL){
+ str = ycf_string_new(" %s %s ", str, ycf_symbol_get_text(s));
+ s = s->next;
+ }
+ return str;
+}
+
+GENERATE_LIST_FUNCTIONS(ycf_symbol)
diff --git a/erts/lib_src/yielding_c_fun/ycf_symbol.h b/erts/lib_src/yielding_c_fun/ycf_symbol.h
new file mode 100644
index 0000000000..b6d69cc5cb
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_symbol.h
@@ -0,0 +1,110 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#ifndef YIELDING_C_FUN_YCF_SYMBOL_H
+#define YIELDING_C_FUN_YCF_SYMBOL_H
+
+/* Types for symbols */
+
+typedef enum {
+ ycf_symbol_type_comment,
+ ycf_symbol_type_string_literal,
+ ycf_symbol_type_macro_define,
+ ycf_symbol_type_macro_command,
+ ycf_symbol_type_whitespace,
+ ycf_symbol_type_identifier,
+ ycf_symbol_type_number,
+ ycf_symbol_type_open_parenthesis,
+ ycf_symbol_type_end_parenthesis,
+ ycf_symbol_type_open_curly_brace,
+ ycf_symbol_type_end_curly_brace,
+ ycf_symbol_type_open_square_bracket,
+ ycf_symbol_type_end_square_bracket,
+ ycf_symbol_type_not_equal_sign,
+ ycf_symbol_type_equal_sign,
+ ycf_symbol_type_equal_equal_sign,
+ ycf_symbol_type_star,
+ ycf_symbol_type_neg,
+ ycf_symbol_type_semicolon,
+ ycf_symbol_type_comma,
+ ycf_symbol_type_pointer_field_access,
+ ycf_symbol_type_period,
+ ycf_symbol_type_special_code_start,
+ ycf_symbol_type_special_code_end,
+ ycf_symbol_type_const,
+ ycf_symbol_type_void,
+ ycf_symbol_type_static,
+ ycf_symbol_type_inline,
+ ycf_symbol_type_volatile,
+ ycf_symbol_type_consume_reds,
+ ycf_symbol_type_return,
+ ycf_symbol_type_if,
+ ycf_symbol_type_else,
+ ycf_symbol_type_goto,
+ ycf_symbol_type_while,
+ ycf_symbol_type_do,
+ ycf_symbol_type_for,
+ ycf_symbol_type_switch,
+ ycf_symbol_type_break,
+ ycf_symbol_type_continue,
+ ycf_symbol_type_something_else
+} ycf_symbol_type;
+
+
+typedef struct ycf_symbol {
+ ycf_symbol_type type;
+ int start;
+ int stop;
+ char* source;
+ struct ycf_symbol* whitespace_or_comment_before;
+ struct ycf_symbol* next;
+} ycf_symbol;
+
+typedef struct symbol_list {
+ struct ycf_symbol* head;
+ struct ycf_symbol* last;
+} ycf_symbol_list;
+
+/* Functions for symbols */
+
+ycf_symbol_list ycf_symbol_list_shallow_copy(ycf_symbol_list n);
+
+ycf_symbol* ycf_symbol_new_something_else(char* text);
+ycf_symbol* ycf_symbol_copy_change_text(ycf_symbol* to_copy, char* new_text);
+ycf_symbol* ycf_symbol_new_semicolon(void);
+ycf_symbol* ycf_symbol_new_star();
+ycf_symbol* ycf_symbol_new_parenthesis(void);
+ycf_symbol* ycf_symbol_new_comma(void);
+ycf_symbol* ycf_symbol_new_open_curly_brace(void);
+ycf_symbol* ycf_symbol_new_end_curly_brace(void);
+ycf_symbol* ycf_symbol_new_identifier(char* name);
+char* ycf_symbol_get_text(ycf_symbol* symbol);
+ycf_symbol_list ycf_symbol_list_from_text(char* text);
+void ycf_symbol_list_print(char* text);
+char* get_symbol_type_text(ycf_symbol_type type);
+ycf_symbol* ycf_symbol_copy(ycf_symbol* symbol);
+char* ycf_symbol_text_between(ycf_symbol* s1, ycf_symbol* s2);
+int ycf_symbol_is_text_eq(ycf_symbol* symbol, char* str);
+char* ycf_symbol_list_to_str(ycf_symbol_list* l);
+#endif //YIELDING_C_FUN_YCF_SYMBOL_H
diff --git a/erts/lib_src/yielding_c_fun/ycf_utils.c b/erts/lib_src/yielding_c_fun/ycf_utils.c
new file mode 100644
index 0000000000..1c51043b41
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_utils.c
@@ -0,0 +1,106 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ycf_utils.h"
+#include "lib/simple_c_gc/simple_c_gc.h"
+#include <stdint.h>
+
+bool ycf_use_gc = false;
+bool ycf_track_memory = false;
+
+size_t ycf_memory_usage = 0;
+size_t ycf_max_memory_usage = 0;
+
+void ycf_enable_gc(){
+ ycf_use_gc = true;
+}
+
+void ycf_enable_memory_tracking(){
+ ycf_track_memory = true;
+}
+
+void ycf_malloc_log(char* log_file, char* log_entry_id) {
+ FILE* out = fopen(log_file, "a");
+ fprintf(out,
+ "(%s)\nMax memory consumption %zu bytes ~ %zu kilo bytes ~ %zu mega bytes (after=%zu)\n",
+ log_entry_id,
+ ycf_max_memory_usage,
+ ycf_max_memory_usage / 1000,
+ ycf_max_memory_usage / 1000000,
+ ycf_memory_usage);
+ fclose(out);
+}
+
+void* ycf_raw_malloc(size_t size) {
+ if (ycf_track_memory) {
+ void* block = malloc(size + sizeof(intptr_t));
+ intptr_t* size_ptr = block;
+ *size_ptr = size + sizeof(intptr_t);
+ ycf_memory_usage = ycf_memory_usage + size + sizeof(intptr_t);
+ if (ycf_memory_usage > ycf_max_memory_usage) {
+ ycf_max_memory_usage = ycf_memory_usage;
+ }
+ if(block == NULL) {
+ fprintf(stderr, "ycf_malloc failed: is there enough memory in the machine?\n");
+ exit(1);
+ }
+ return (void*)(((char*)block) + sizeof(intptr_t));
+ } else {
+ void* block = malloc(size);
+ if(block == NULL) {
+ fprintf(stderr, "ycf_malloc failed: is there enough memory in the machine?\n");
+ exit(1);
+ }
+ return block;
+ }
+}
+
+void* ycf_malloc(size_t size) {
+ if (ycf_use_gc) {
+ return scgc_new(size);
+ } else {
+ return ycf_raw_malloc(size);
+ }
+}
+
+
+void ycf_free(void* to_free) {
+ if (ycf_track_memory) {
+ char* to_free_cp = to_free;
+ char* start = to_free_cp - sizeof(intptr_t);
+ intptr_t* size_ptr = (intptr_t*)start;
+ ycf_memory_usage = ycf_memory_usage - *size_ptr;
+ free(start);
+ } else {
+ free(to_free);
+ }
+}
+
+
+
diff --git a/erts/lib_src/yielding_c_fun/ycf_utils.h b/erts/lib_src/yielding_c_fun/ycf_utils.h
new file mode 100644
index 0000000000..d713fafc09
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_utils.h
@@ -0,0 +1,40 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <stddef.h>
+#include <stdbool.h>
+
+
+void ycf_enable_gc(void);
+void ycf_enable_memory_tracking(void);
+void* ycf_malloc(size_t size);
+void ycf_malloc_log(char* log_file, char* log_entry_id);
+void* ycf_raw_malloc(size_t size);
+void ycf_free(void* to_free);
+
+
+#endif
diff --git a/erts/lib_src/yielding_c_fun/ycf_yield_fun.c b/erts/lib_src/yielding_c_fun/ycf_yield_fun.c
new file mode 100644
index 0000000000..6260e5402e
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_yield_fun.c
@@ -0,0 +1,1625 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include "ycf_utils.h"
+#include "ycf_yield_fun.h"
+#include "ycf_node.h"
+#include "ycf_symbol.h"
+#include "ycf_string.h"
+#include "ycf_printers.h"
+#include "ycf_parser.h"
+
+static int ycf_yield_location_id_counter = 0;
+
+static
+ycf_node* mk_typedef_struct_node(ycf_node_list definitions, char* name){
+ ycf_node* res = ycf_malloc(sizeof(ycf_node));
+ res->next = NULL;
+ res->type = ycf_node_type_gen_typedef_struct;
+ res->u.gen_typedef_struct.definition_nodes = definitions;
+ res->u.gen_typedef_struct.name = name;
+ return res;
+}
+
+static
+ycf_node_list mk_ycf_trap_state_params(){
+ return ycf_node_definition_list_from_string(ycf_string_new(
+ "long* ycf_nr_of_reductions_param;\n"
+ "void** ycf_trap_state;\n"
+ "void* ycf_extra_context;\n"));
+}
+
+static
+ycf_node_list mk_saved_ycf_trap_state_params(){
+ return ycf_node_definition_list_from_string(
+ "ycf_yield_alloc_type ycf_yield_alloc;\n"
+ "ycf_yield_free_type ycf_yield_free;\n"
+ "void* ycf_yield_alloc_free_context;\n"
+ "size_t ycf_stack_alloc_size_or_max_size;\n"
+ "void* ycf_stack_alloc_data;\n");
+}
+
+static
+ycf_node_list mk_trap_extra_state(){
+ return ycf_node_definition_list_from_string(
+ "int ycf_trap_location;\n"
+ "long ycf_nr_of_reductions;\n"
+ "struct ycf_alloc_data ycf_frame_alloc_data;\n");;
+}
+
+static
+char* get_ycf_trap_state_assignments(ycf_node_list ycf_trap_state_defines){
+ ycf_node* current = ycf_trap_state_defines.head;
+ char* str = "";
+ while(current != NULL){
+ char* ident = ycf_symbol_get_text(current->u.definition.identifier);
+ if(current->u.definition.array_brackets.head != NULL && !current->u.definition.array_brackets.head->u.array_bracket.empty){
+ ycf_string_printable_buffer* array_size_exp = ycf_string_printable_buffer_new();
+ ycf_node* bracket = current->u.definition.array_brackets.head;
+ while(bracket != NULL){
+ print_node_code_expression(bracket->u.array_bracket.content,array_size_exp);
+ ycf_string_printable_buffer_printf(array_size_exp, " * ");
+ bracket = bracket->next;
+ }
+ ycf_string_printable_buffer_printf(array_size_exp, " sizeof(");
+ print_symbol_list(&current->u.definition.type_specifiers, array_size_exp);
+ ycf_string_printable_buffer_printf(array_size_exp, ")");
+ str = ycf_string_new("%s"
+ " memcpy(ycf_my_trap_state->%s, %s, %s);\n",
+ str,
+ ident,
+ ident,
+ array_size_exp->buffer);
+ }else{
+ str = ycf_string_new("%s"
+ " ycf_my_trap_state->%s = %s;\n",
+ str,
+ ident,
+ ident);
+ }
+ current = current->next;
+ }
+ return str;
+}
+
+static
+char* mk_code_from_special_code_list(ycf_node_list special_code_list){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ ycf_node* current = special_code_list.head;
+ ycf_string_printable_buffer_printf(b, "\n/* YCF SPECIAL CUSTOM CODE START */\n");
+ while(current != NULL) {
+ ycf_node_print(current->u.special_code_block.code.if_statement, b);
+ ycf_string_printable_buffer_printf(b, "\n");
+ current = current->next;
+ }
+ ycf_string_printable_buffer_printf(b, "\n/* YCF SPECIAL CUSTOM CODE END */\n");
+ return b->buffer;
+}
+
+static
+ycf_node* mk_yield_code(ycf_node* f_node,
+ char* ycf_trap_state_name,
+ ycf_node_list ycf_trap_state_defines,
+ ycf_node_list on_save_yield_state_code_list,
+ bool debug){
+ char* ret_code;
+ if(ycf_node_is_void_ret_fun(f_node)){
+ ret_code = "return;\n";
+ } else{
+ ycf_symbol_list ret_type = ycf_node_get_return_type(f_node);
+ ret_code =
+ ycf_string_new(" {\n"
+ " %s ycf_ret_value;\n"
+ " return ycf_ret_value;\n"
+ " }\n",
+ ycf_symbol_list_to_str(&ret_type));
+ }
+ char *debug_check_for_stack_ptrs = "";
+ if(debug){
+ debug_check_for_stack_ptrs =
+ ycf_string_new("ycf_debug_check_block(\"%s\",\n"
+ " ycf_find_stack_bottom_conservative(),\n"
+ " ycf_trap_state,\n"
+ " ycf_my_trap_state,\n"
+ " sizeof(struct %s));\n",
+ ycf_trap_state_name,
+ ycf_trap_state_name);
+ }
+ char* code = ycf_string_new("\n"
+ "{\n"
+ " struct %s* ycf_my_trap_state;\n"
+ " ycf_do_yield_label_%s:;\n"
+ " %s"
+ " if (*ycf_trap_state == NULL) {\n"
+ " ycf_my_trap_state = ycf_yield_alloc(sizeof(struct %s), ycf_yield_alloc_free_context);\n"
+ " } else {\n"
+ " ycf_my_trap_state = *ycf_trap_state;\n"
+ " }\n"
+ " %s\n"
+ " *ycf_nr_of_reductions_param = ycf_nr_of_reductions;\n"
+ " *ycf_trap_state = ycf_my_trap_state;\n"
+ " %s"
+ " %s\n"
+ "}\n"
+ "\n",
+ ycf_trap_state_name,
+ ycf_symbol_get_text(f_node->u.function.definition.definition.identifier),
+ mk_code_from_special_code_list(on_save_yield_state_code_list),
+ ycf_trap_state_name,
+ get_ycf_trap_state_assignments(ycf_trap_state_defines),
+ debug_check_for_stack_ptrs,
+ ret_code
+ );
+ return ycf_node_get_from_code_scope_text(code);
+}
+
+ycf_node* mk_goto_yield_code(ycf_node* f_node,
+ char* ycf_trap_state_name,
+ ycf_node_list ycf_trap_state_defines){
+ ycf_yield_location_id_counter++;
+ char* code = ycf_string_new("\n"
+ "{\n"
+ " ycf_nr_of_reductions = 0;\n"
+ " ycf_trap_location = %d;\n"
+ " goto ycf_do_yield_label_%s;\n"
+ " ycf_yield_location_label_%d:;\n"
+ "}\n",
+ ycf_yield_location_id_counter,
+ ycf_symbol_get_text(f_node->u.function.definition.definition.identifier),
+ ycf_yield_location_id_counter
+ );
+ return ycf_node_get_from_code_scope_text(code);
+}
+
+static
+ycf_node* mk_goto_yield_no_reds_code(ycf_node* f_node,
+ char* ycf_trap_state_name,
+ ycf_node_list ycf_trap_state_defines){
+ ycf_yield_location_id_counter++;
+ char* code = ycf_string_new("\n"
+ "{\n"
+ " ycf_trap_location = %d;\n"
+ " goto ycf_do_yield_label_%s;\n"
+ " ycf_yield_location_label_%d:;\n"
+ "}\n",
+ ycf_yield_location_id_counter,
+ ycf_symbol_get_text(f_node->u.function.definition.definition.identifier),
+ ycf_yield_location_id_counter
+ );
+ return ycf_node_get_from_code_scope_text(code);
+}
+
+
+static
+ycf_node* mk_yield_fun_call_state_var(ycf_node* f){
+ ycf_node_list code = ycf_node_list_empty();
+ char* fun_name = NULL;
+ if(f->u.statement.expression->type == ycf_node_type_function_call){
+ fun_name = ycf_symbol_get_text(f->u.statement.expression->u.function_call.identifier);
+ }else{
+ fun_name = ycf_symbol_get_text(f->u.statement.expression->u.function_call_assignment.fun_call.identifier);
+ }
+ ycf_node * scope_with_dec =
+ ycf_node_get_from_code_scope_text(ycf_string_new("void* ycf_sub_fun_trap_state_wb = NULL;\n"
+ "/*special_code_start:ON_DESTROY_STATE*/\n"
+ "if(0){\n"
+ " if(ycf_sub_fun_trap_state_wb != NULL)\n{"
+ " %s_ycf_gen_destroy(ycf_sub_fun_trap_state_wb);\n"
+ " }\n"
+ "}\n"
+ "/*special_code_end*/\n", fun_name));
+ ycf_node_list_append(&code, ycf_node_shallow_copy(f));
+ ycf_node_list_append(&code, scope_with_dec->u.code_scope.other_nodes.head);
+ ycf_node* ret = ycf_node_scope_new(ycf_symbol_new_open_curly_brace(),
+ scope_with_dec->u.code_scope.definition_nodes,
+ code,
+ ycf_symbol_new_end_curly_brace());
+ return ret;
+}
+
+static
+ycf_node* mk_yield_fun_call(ycf_node* c_file_node,
+ ycf_node* f,
+ char* ycf_trap_state_var_name,
+ char* calling_fun_name,
+ bool auto_yield){
+ ycf_yield_location_id_counter++;
+ ycf_node_function_call f_node;
+ char* assignment_code = "";
+ char* tmp_assignment_var_name = "ycf_tmp_fun_call_tmp_var";
+ char* tmp_assignment_var_declaration = "";
+ char* parameters = "";
+ char* finalize_call_code = "";
+ if(f->u.statement.expression->type == ycf_node_type_function_call){
+ f_node = f->u.statement.expression->u.function_call;
+ }else{
+ ycf_symbol_list called_fun_ret_type;
+ ycf_string_printable_buffer* assign_to_b = ycf_string_printable_buffer_new();
+ f_node = f->u.statement.expression->u.function_call_assignment.fun_call;
+ called_fun_ret_type =
+ ycf_node_find_function_return_type(c_file_node,
+ ycf_symbol_get_text(f_node.identifier));
+ tmp_assignment_var_declaration =
+ ycf_string_new("%s %s;\n",
+ ycf_symbol_list_to_str(&called_fun_ret_type),
+ tmp_assignment_var_name);
+ print_node_code_expression(f->u.statement.expression->u.function_call_assignment.left_side, assign_to_b);
+ assignment_code = ycf_string_new("%s = ", tmp_assignment_var_name);
+ finalize_call_code = ycf_string_new("%s = %s;\n",
+ assign_to_b->buffer,
+ tmp_assignment_var_name);
+ }
+ if (f_node.parameter_expressions.head != NULL){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ print_node_list_code(f_node.parameter_expressions.head, b);
+ parameters = ycf_string_new(",%s", b->buffer);
+ }
+
+ char* code = ycf_string_new("%s"
+ "%s"
+ "%s %s%s_ycf_gen_yielding(&ycf_nr_of_reductions,\n"
+ " &%s,ycf_extra_context,\n"
+ " ycf_yield_alloc,ycf_yield_free,\n"
+ " ycf_yield_alloc_free_context,\n"
+ " YCF_ALLOC_NEXT_MAX_SIZE(),\n"
+ " YCF_ALLOC_NEXT_BLOCK()\n"
+ " %s);\n"
+ "while(YCF_IS_YIELDED(%s)){\n"
+ " ycf_trap_location = %d;\n"
+ " goto ycf_do_yield_label_%s;\n"
+ " ycf_yield_location_label_%d:;\n"
+ " %s %s%s_ycf_gen_continue(&ycf_nr_of_reductions,\n"
+ " &%s,\n"
+ " ycf_extra_context);\n"
+ "}\n"
+ "%s\n",
+ tmp_assignment_var_declaration,
+ auto_yield ? "YCF_CONSUME_REDS(1);" : "",
+ assignment_code,
+ ycf_symbol_list_to_str(&f_node.neg_symbols),
+ ycf_symbol_get_text(f_node.identifier),
+ ycf_trap_state_var_name,
+ parameters,
+ ycf_trap_state_var_name,
+ ycf_yield_location_id_counter,
+ calling_fun_name,
+ ycf_yield_location_id_counter,
+ assignment_code,
+ ycf_symbol_list_to_str(&f_node.neg_symbols),
+ ycf_symbol_get_text(f_node.identifier),
+ ycf_trap_state_var_name,
+ finalize_call_code
+ );
+
+ return ycf_node_get_from_code_scope_text(code);
+}
+
+
+static
+char* get_trap_restore_assignments(ycf_node_list ycf_trap_state_defines){
+ ycf_node* current = ycf_trap_state_defines.head;
+ char* str = "\n";
+ while(current != NULL){
+ char* ident = ycf_symbol_get_text(current->u.definition.identifier);
+ if(current->u.definition.array_brackets.head != NULL && !current->u.definition.array_brackets.head->u.array_bracket.empty){
+ ycf_string_printable_buffer* array_size_exp = ycf_string_printable_buffer_new();
+ ycf_node* bracket = current->u.definition.array_brackets.head;
+ while(bracket != NULL){
+ print_node_code_expression(bracket->u.array_bracket.content,array_size_exp);
+ ycf_string_printable_buffer_printf(array_size_exp, " * ");
+ bracket = bracket->next;
+ }
+ ycf_string_printable_buffer_printf(array_size_exp, " sizeof(");
+ print_symbol_list(&current->u.definition.type_specifiers, array_size_exp);
+ ycf_string_printable_buffer_printf(array_size_exp, ")");
+ str = ycf_string_new("%s"
+ " memcpy(%s, ycf_my_trap_state->%s, %s);\n",
+ str,
+ ident,
+ ident,
+ array_size_exp->buffer);
+ }else{
+ str = ycf_string_new("%s"
+ " %s = ycf_my_trap_state->%s;\n",
+ str,
+ ident,
+ ident);
+ }
+ current = current->next;
+ }
+ return str;
+}
+
+static
+char* get_goto_ycf_trap_location_switch(int nr_of_ycf_trap_locations){
+ int i;
+ char* str = "switch(ycf_trap_location){\n";
+ for(i = 1; i <= nr_of_ycf_trap_locations; i++){
+ str = ycf_string_new("%s"
+ "case %d: goto ycf_yield_location_label_%d;\n", str, i, i);
+ }
+ str = ycf_string_new("%s\n}", str, i, i);
+ return str;
+}
+
+typedef struct {
+ ycf_node* f_node;
+ char* ycf_trap_state_name;
+ ycf_node_list ycf_trap_state_defines;
+} yield_code_replacer_context;
+
+ycf_node* yield_code_replacer(ycf_node* candidate, ycf_node_code_scope* s,void* context){
+ yield_code_replacer_context* c = context;
+ (void)s;
+ if(candidate->type == ycf_node_type_statement &&
+ candidate->u.statement.expression != NULL &&
+ candidate->u.statement.expression->type == ycf_node_type_function_call &&
+ ycf_symbol_is_text_eq(candidate->u.statement.expression->u.function_call.identifier,
+ "YCF_YIELD") &&
+ candidate->u.statement.expression->u.function_call.parameter_expressions.head == NULL){
+ ycf_node* yield_code = mk_goto_yield_code(c->f_node, c->ycf_trap_state_name, c->ycf_trap_state_defines);
+ return yield_code;
+ } else {
+ return candidate;
+ }
+}
+
+static
+void insert_yield_code(ycf_node* f_node, char* ycf_trap_state_name, ycf_node_list ycf_trap_state_defines, ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ yield_code_replacer,
+ &(yield_code_replacer_context) {f_node, ycf_trap_state_name,
+ ycf_trap_state_defines});
+}
+
+static
+ycf_node* special_code_section_replacer(ycf_node* candidate, ycf_node_code_scope* s,void* context){
+ (void)context;
+ (void)s;
+ if(candidate->type == ycf_node_type_statement &&
+ candidate->u.statement.expression != NULL &&
+ candidate->u.statement.expression->type == ycf_node_type_function_call) {
+ ycf_node_function_call fun_call = candidate->u.statement.expression->u.function_call;
+ ycf_symbol* fun_name = fun_call.identifier;
+ if(ycf_symbol_is_text_eq(fun_name, "YCF_SPECIAL_CODE_START") &&
+ ycf_node_list_length(fun_call.parameter_expressions) == 1) {
+ char* parameter = ycf_node_to_string(fun_call.parameter_expressions.head);
+ ycf_node* special_code_start =
+ ycf_node_new_text_node(ycf_string_new("/*special_code_start:%s*/\n"
+ "if(0){\n",
+ parameter));
+ return special_code_start;
+ } else if (ycf_symbol_is_text_eq(candidate->u.statement.expression->u.function_call.identifier,
+ "YCF_SPECIAL_CODE_END") &&
+ ycf_node_list_length(fun_call.parameter_expressions) == 0) {
+ return ycf_node_new_text_node("}/*special_code_end*/\n");
+ }
+ }
+ return candidate;
+}
+
+static
+ycf_node* replace_alt_syntax_special_code_section_code(ycf_node* f_node){
+ ycf_node_search_and_replace_statements_in_scope(&f_node->u.function.body,
+ special_code_section_replacer,
+ NULL);
+ return ycf_node_get_function_from_text(ycf_node_to_string(f_node));
+}
+
+
+static
+ycf_node* yield_no_reds_code_replacer(ycf_node* candidate, ycf_node_code_scope* s,void* context){
+ yield_code_replacer_context* c = context;
+ (void)s;
+ if(candidate->type == ycf_node_type_statement &&
+ candidate->u.statement.expression != NULL &&
+ candidate->u.statement.expression->type == ycf_node_type_function_call &&
+ ycf_symbol_is_text_eq(candidate->u.statement.expression->u.function_call.identifier,
+ "YCF_YIELD_NO_REDS") &&
+ candidate->u.statement.expression->u.function_call.parameter_expressions.head == NULL){
+ ycf_node* yield_code = mk_goto_yield_no_reds_code(c->f_node, c->ycf_trap_state_name, c->ycf_trap_state_defines);
+ return yield_code;
+ } else {
+ return candidate;
+ }
+}
+
+static
+void insert_yield_no_reds_code(ycf_node* f_node, char* ycf_trap_state_name, ycf_node_list ycf_trap_state_defines, ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ yield_no_reds_code_replacer,
+ &(yield_code_replacer_context){f_node, ycf_trap_state_name,
+ ycf_trap_state_defines});
+}
+
+typedef struct {
+ ycf_node_list on_return_code_list;
+ ycf_node_list on_return_or_destroy_code_list;
+ bool auto_yield;
+} replace_return_ctx;
+
+static
+ycf_node* save_nr_of_reductions_before_return_replacer(ycf_node* candidate,
+ ycf_node_code_scope* s,
+ void* context){
+ replace_return_ctx* ctx = context;
+ (void)s;
+ char* consume_reds_code = ctx->auto_yield ? "YCF_CONSUME_REDS(1);\n" : "";
+ if(candidate->type == ycf_node_type_return_statement){
+ char* code =
+ ycf_string_new("\n"
+ "%s"
+ "if (*ycf_trap_state != NULL) {\n"
+ " ycf_yield_free(*ycf_trap_state, ycf_yield_alloc_free_context);\n"
+ " *ycf_trap_state = NULL;\n"
+ "}\n"
+ "ycf_destroy_stack_allocator(&ycf_frame_alloc_data,\n"
+ " ycf_yield_free,\n"
+ " ycf_yield_alloc_free_context);\n"
+ "*ycf_nr_of_reductions_param = ycf_nr_of_reductions;"
+ "%s"
+ "%s"
+ "%s",
+ consume_reds_code,
+ mk_code_from_special_code_list(
+ ctx->on_return_or_destroy_code_list),
+ mk_code_from_special_code_list(ctx->on_return_code_list),
+ ycf_node_to_string(candidate));
+ return ycf_node_get_from_code_scope_text(code);
+ } else {
+ return candidate;
+ }
+}
+
+static
+void save_nr_of_reductions_before_return(ycf_node_code_scope* s,
+ ycf_node_list on_return_code_list,
+ ycf_node_list on_return_or_destroy_code_list,
+ bool auto_yield){
+ replace_return_ctx ctx;
+ ctx.on_return_code_list = on_return_code_list;
+ ctx.on_return_or_destroy_code_list = on_return_or_destroy_code_list;
+ ctx.auto_yield = auto_yield;
+ ycf_node_search_and_replace_statements_in_scope(s,
+ save_nr_of_reductions_before_return_replacer,
+ &ctx);
+}
+
+ycf_node* mk_consume_reds_code(char* function_name, ycf_node* consume_reds_node){
+ ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
+ ycf_yield_location_id_counter++;
+ print_node_code_paran_expression(consume_reds_node->u.consume_reds.nr_of_reds_expression, b);
+ return ycf_node_get_from_code_scope_text(ycf_string_new("ycf_nr_of_reductions = ycf_nr_of_reductions - %s;\n"
+ "if (ycf_nr_of_reductions <= 0) {\n"
+ " ycf_trap_location = %d;\n"
+ " goto ycf_do_yield_label_%s;\n"
+ " ycf_yield_location_label_%d:;\n"
+ "}\n",
+ b->buffer,
+ ycf_yield_location_id_counter,
+ function_name,
+ ycf_yield_location_id_counter));
+}
+
+static
+ycf_node* consume_reds_replacer(ycf_node* candidate, ycf_node_code_scope* s, void* context){
+ char* function_name = context;
+ (void)s;
+ if(candidate->type == ycf_node_type_consume_reds){
+ return mk_consume_reds_code(function_name, candidate);
+ } else {
+ return candidate;
+ }
+}
+
+static
+void insert_consume_reds_code(char* function_name, ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ consume_reds_replacer,
+ function_name);
+}
+
+static
+ycf_node* mk_consume_reds_wrapped_statement(ycf_node* statement){
+ return ycf_node_get_from_code_scope_text(ycf_string_new("YCF_CONSUME_REDS(1);\n"
+ "%s\n", ycf_node_to_string(statement)));
+}
+
+static
+void insert_consume_reds_calls(ycf_node_code_scope* s);
+
+static
+ycf_node* consume_reds_calls_inserter(ycf_node* candidate, ycf_node_code_scope* s, void* context){
+ if(candidate->type == ycf_node_type_goto){
+ return mk_consume_reds_wrapped_statement(candidate);
+ } else if (candidate->type == ycf_node_type_while){
+ if(candidate->u.while_n.statement->type == ycf_node_type_code_scope){
+ insert_consume_reds_calls(&candidate->u.while_n.statement->u.code_scope);
+ }
+ candidate->u.while_n.statement = mk_consume_reds_wrapped_statement(candidate->u.while_n.statement);
+ return candidate;
+ } else if (candidate->type == ycf_node_type_do_while){
+ if(candidate->u.do_while.statement->type == ycf_node_type_code_scope){
+ insert_consume_reds_calls(&candidate->u.do_while.statement->u.code_scope);
+ }
+ candidate->u.do_while.statement = mk_consume_reds_wrapped_statement(candidate->u.do_while.statement);
+ return candidate;
+ } else if (candidate->type == ycf_node_type_for){
+ if(candidate->u.for_n.statement->type == ycf_node_type_code_scope){
+ insert_consume_reds_calls(&candidate->u.for_n.statement->u.code_scope);
+ }
+ candidate->u.for_n.statement = mk_consume_reds_wrapped_statement(candidate->u.for_n.statement);
+ return candidate;
+ } else {
+ return candidate;
+ }
+}
+
+static void insert_consume_reds_calls(ycf_node_code_scope* s){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ consume_reds_calls_inserter,
+ NULL);
+}
+
+typedef struct {
+ ycf_node_list code;
+ ycf_node_type code_type;
+} special_code_context;
+
+ycf_node* do_special_code_replace(ycf_node* candidate, ycf_node_code_scope* s, void* context){
+ special_code_context* c = context;
+ (void)s;
+ if(candidate->type == c->code_type){
+ ycf_node_list_append(&c->code, ycf_node_shallow_copy(candidate));
+ return ycf_node_new_text_node("\n/* YCF Replaced special code */\n");
+ } else {
+ return candidate;
+ }
+}
+
+static
+ycf_node_list save_and_replace_special_code(ycf_node_code_scope* s, ycf_node_type code_type){
+ special_code_context context;
+ context.code = ycf_node_list_empty();
+ context.code_type = code_type;
+ ycf_node_search_and_replace_statements_in_scope(s,
+ do_special_code_replace,
+ &context);
+ return context.code;
+}
+
+static
+ycf_node* insert_fun_call_state_var_replacer(ycf_node* candidate, ycf_node_code_scope* s, void* context){
+ ycf_string_item_list* yielding_funs = context;
+ (void)s;
+ if(candidate->type == ycf_node_type_statement &&
+ (candidate->u.statement.expression->type == ycf_node_type_function_call ||
+ candidate->u.statement.expression->type == ycf_node_type_assignment_function_call)){
+ ycf_string_item* current = yielding_funs->head;
+ while(current != NULL){
+ char* fun_name = NULL;
+ if(candidate->u.statement.expression->type == ycf_node_type_function_call){
+ fun_name = ycf_symbol_get_text(candidate->u.statement.expression->u.function_call.identifier);
+ } else if(candidate->u.statement.expression->type == ycf_node_type_assignment_function_call){
+ fun_name = ycf_symbol_get_text(
+ candidate->u.statement.expression->u.function_call_assignment.fun_call.identifier);
+ } else {
+ current = current->next;
+ continue;
+ }
+ if(ycf_string_is_equal(current->str, fun_name)){
+ return mk_yield_fun_call_state_var(candidate);
+ }
+ current = current->next;
+ }
+ }
+ return candidate;
+}
+
+static
+void insert_fun_call_state_var(ycf_node_code_scope* s, ycf_string_item_list* yielding_funs){
+ ycf_node_search_and_replace_statements_in_scope(s,
+ insert_fun_call_state_var_replacer,
+ yielding_funs);
+}
+
+typedef struct {
+ ycf_node* c_file_node;
+ char* calling_fun_name;
+ ycf_string_item_list* yielding_funs;
+ ycf_string_item_list* starte_vars_wb;
+ bool auto_yield;
+} yielding_fun_call_code_context;
+
+static
+ycf_node* insert_yielding_fun_call_code_replacer(ycf_node* candidate,
+ ycf_node_code_scope* s,
+ void* context){
+ yielding_fun_call_code_context* c = context;
+ ycf_node* c_file_node = c->c_file_node;
+ ycf_string_item_list* yielding_funs = c->yielding_funs;
+ (void)s;
+ if (candidate->type == ycf_node_type_code_scope &&
+ candidate->u.code_scope.other_nodes.head != candidate->u.code_scope.other_nodes.last){
+ ycf_node* call_candidate = candidate->u.code_scope.other_nodes.head->next;
+ if (call_candidate->type == ycf_node_type_statement &&
+ (call_candidate->u.statement.expression->type == ycf_node_type_function_call ||
+ call_candidate->u.statement.expression->type == ycf_node_type_assignment_function_call)) {
+ ycf_string_item* current = yielding_funs->head;
+ while(current != NULL){
+ char* fun_name = NULL;
+ if (call_candidate->u.statement.expression->type == ycf_node_type_function_call) {
+ fun_name = ycf_symbol_get_text(call_candidate->u.statement.expression->u.function_call.identifier);
+ } else if (call_candidate->u.statement.expression->type == ycf_node_type_assignment_function_call) {
+ fun_name = ycf_symbol_get_text(
+ call_candidate->u.statement.expression->u.function_call_assignment.fun_call.identifier);
+ } else {
+ current = current->next;
+ continue;
+ }
+ if(ycf_string_is_equal(current->str, fun_name)){
+ char* ycf_trap_state_var_name =
+ ycf_symbol_get_text(ycf_node_get_assignment(candidate->u.code_scope.other_nodes.head)->left_side.content.head->u.other.what);
+ ycf_string_item_list_append(c->starte_vars_wb, ycf_string_item_new(ycf_trap_state_var_name));
+ ycf_node* new_call_code = mk_yield_fun_call(c_file_node,
+ call_candidate,
+ ycf_trap_state_var_name,
+ c->calling_fun_name,
+ c->auto_yield);
+ ycf_node_list_replace(&candidate->u.code_scope.other_nodes, call_candidate, new_call_code);
+ return ycf_node_scope_new(ycf_symbol_new_open_curly_brace(),
+ candidate->u.code_scope.definition_nodes,
+ candidate->u.code_scope.other_nodes,
+ ycf_symbol_new_end_curly_brace());;
+ }
+ current = current->next;
+ }
+ }
+ }
+ return candidate;
+}
+
+ycf_string_item_list insert_yielding_fun_call_code(ycf_node* c_file_node,
+ ycf_node_code_scope* s,
+ ycf_string_item_list* yielding_funs,
+ char* calling_fun_name,
+ bool auto_yield){
+ yielding_fun_call_code_context context;
+ ycf_string_item_list state_vars = ycf_string_item_list_empty();
+ context.c_file_node = c_file_node;
+ context.calling_fun_name = calling_fun_name;
+ context.yielding_funs = yielding_funs;
+ context.starte_vars_wb = &state_vars;
+ context.auto_yield = auto_yield;
+ ycf_node_search_and_replace_statements_in_scope(s,
+ insert_yielding_fun_call_code_replacer,
+ &context);
+ return state_vars;
+}
+
+static
+ycf_node* mk_yield_init_code(char* ycf_trap_state_name, ycf_node_list ycf_trap_state_defines, ycf_node_list on_restore_yield_state_code_list, bool auto_yield, char *function_name){
+ char* code = ycf_string_new("\n"
+ "{\n"
+ " ycf_nr_of_reductions = *ycf_nr_of_reductions_param;\n"
+ " ycf_frame_alloc_data.size = 0;\n"
+ " ycf_frame_alloc_data.max_size = ycf_stack_alloc_size_or_max_size;\n"
+ " ycf_frame_alloc_data.data = ycf_stack_alloc_data;\n"
+ " ycf_frame_alloc_data.needs_freeing = 0;\n"
+ " if(*ycf_trap_state != NULL){\n"
+ " struct %s* ycf_my_trap_state = *ycf_trap_state;\n"
+ " %s\n"
+ " %s\n"
+ " ycf_nr_of_reductions = *ycf_nr_of_reductions_param;\n"
+ " %s\n"
+ " }\n"
+ "}\n",
+ ycf_trap_state_name,
+ get_trap_restore_assignments(ycf_trap_state_defines),
+ mk_code_from_special_code_list(on_restore_yield_state_code_list),
+ get_goto_ycf_trap_location_switch(ycf_yield_location_id_counter));
+ return ycf_node_get_from_code_scope_text(code);
+}
+
+static
+ycf_node* mk_destroy_state_function_node(char* yielding_function_name,
+ ycf_node_list defs,
+ char* ycf_trap_state_struct_name,
+ ycf_node_list destroy_code,
+ ycf_node_list on_destroy_state_or_return_code_list,
+ bool static_aux_funs){
+ ycf_node_list my_defs = ycf_node_list_shallow_copy(defs);
+ ycf_node* current = my_defs.head;
+ while(current != NULL){
+ current->u.definition.end = ycf_symbol_new_semicolon();
+ int empty_array_brackets = 0;
+ {
+ current->u.definition.array_brackets = ycf_node_list_shallow_copy(current->u.definition.array_brackets);
+ ycf_node* b = current->u.definition.array_brackets.head;
+ while(b != NULL && b->u.array_bracket.empty){
+ empty_array_brackets++;
+ ycf_node_list_remove(&current->u.definition.array_brackets, b);
+ b = b->next;
+ }
+ }
+ current->u.definition.type_specifiers = ycf_symbol_list_shallow_copy(current->u.definition.type_specifiers);
+ if(empty_array_brackets > 0){
+ for(int i = 0; i < empty_array_brackets; i++){
+ ycf_symbol_list_append(&current->u.definition.type_specifiers, ycf_symbol_new_star());
+ }
+ }
+ current = current->next;
+ }
+ char* code =
+ ycf_string_new("\n"
+ "%s void %s_ycf_gen_destroy(struct %s* ycf_my_trap_state){\n"
+ " {\n"
+ " %s\n"
+ " %s\n"
+ " %s\n"
+ " %s\n"
+ " ycf_destroy_stack_allocator(&ycf_frame_alloc_data, ycf_yield_free, ycf_yield_alloc_free_context);\n"
+ " ycf_yield_free(ycf_my_trap_state, ycf_yield_alloc_free_context);\n"
+ " }\n"
+ "}\n",
+ static_aux_funs ? "static" : "",
+ yielding_function_name,
+ ycf_trap_state_struct_name,
+ ycf_node_list_to_string(&my_defs),
+ get_trap_restore_assignments(my_defs),
+ mk_code_from_special_code_list(on_destroy_state_or_return_code_list),
+ mk_code_from_special_code_list(destroy_code));
+ return ycf_node_get_function_from_text(code);
+}
+
+void ast_add_yield_code_generated_define(ycf_node* source_out_tree/*Will be changed*/, bool debug_mode)
+{
+ char *debug_mode_code =
+ (debug_mode ?
+ "\n"
+ "#include <setjmp.h>\n"
+ "#include <stdint.h>\n"
+ "#include <string.h>\n"
+ "static void* ycf_find_stack_bottom_conservative_helper() {\n"
+ " void* p = NULL;\n"
+ " volatile intptr_t tmp = (intptr_t)&p;\n"
+ " return (void*)tmp;\n"
+ "}\n"
+ "static void* ycf_find_stack_bottom_conservative() {\n"
+ " jmp_buf env;\n"
+ " setjmp(env);\n"
+ "\n"
+ " {\n"
+ " volatile int noinline = 1;\n"
+ " void* (*bottom)(void) = noinline\n"
+ " ? ycf_find_stack_bottom_conservative_helper\n"
+ " : (void*(*)(void))(NULL);\n"
+ "\n"
+ " return bottom();\n"
+ " }\n"
+ "}\n"
+ "static void ycf_debug_check_block(char* struct_name, void* stack_start, void* stack_end, void* block, size_t block_size) {\n"
+ " char* p;\n"
+ " for (p = block; p < (((char*)block) + block_size); p += sizeof(void*)) {\n"
+ " if(*((char**)p) > (char*)stack_start && *((char**)p) <= (char*)stack_end){\n"
+ " fprintf(stderr, \"Pointer to stack in yielded functions state!!!!! (pointer_address=%p, struct %s,offset=%lu)\\n\", (void*)p, struct_name, (unsigned long)(p-(size_t)block));\n"
+ " exit(1);\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "\n"
+ :
+ "");
+ char* ycf_yielding_c_fun_helpers_code =
+ ycf_string_new("#ifndef YCF_YIELDING_C_FUN_HELPERS\n"
+ "#define YCF_YIELDING_C_FUN_HELPERS 1\n"
+ "#include <string.h>\n"
+ "#include <stdio.h>\n"
+ "#include <stdlib.h>\n"
+ "\n"
+ "/*\n"
+ " * YCF_GCC_DIAG_ON and YCF_GCC_DIAG_OFF can be used to temporarly\n"
+ " * disable a gcc or clang warning in a file.\n"
+ " *\n"
+ " * Example:\n"
+ " * YCF_GCC_DIAG_OFF(unused-function)\n"
+ " * static int test(){ return 0;}\n"
+ " * YCF_GCC_DIAG_ON(unused-function)\n"
+ " *\n"
+ " * These macros were orginally authored by Jonathan Wakely and has\n"
+ " * been modified by Patrick Horgan.\n"
+ " *\n"
+ " * Source: http://dbp-consulting.com/tutorials/SuppressingGCCWarnings.html\n"
+ " *\n"
+ " */\n"
+ "#if defined(_MSC_VER)\n"
+ "# define YCF_GCC_DIAG_OFF(x) __pragma(warning(push, 0))\n"
+ "# define YCF_GCC_DIAG_ON(x) __pragma(warning(pop))\n"
+ "#elif ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402\n"
+ "#define YCF_GCC_DIAG_STR(s) #s\n"
+ "#define YCF_GCC_DIAG_JOINSTR(x,y) YCF_GCC_DIAG_STR(x ## y)\n"
+ "# define YCF_GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)\n"
+ "# define YCF_GCC_DIAG_PRAGMA(x) YCF_GCC_DIAG_DO_PRAGMA(GCC diagnostic x)\n"
+ "# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406\n"
+ "# define YCF_GCC_DIAG_OFF(x) YCF_GCC_DIAG_PRAGMA(push) \\\n"
+ " YCF_GCC_DIAG_PRAGMA(ignored YCF_GCC_DIAG_JOINSTR(-W,x))\n"
+ "# define YCF_GCC_DIAG_ON(x) YCF_GCC_DIAG_PRAGMA(pop)\n"
+ "# else\n"
+ "# define YCF_GCC_DIAG_OFF(x) YCF_GCC_DIAG_PRAGMA(ignored YCF_GCC_DIAG_JOINSTR(-W,x))\n"
+ "# define YCF_GCC_DIAG_ON(x) YCF_GCC_DIAG_PRAGMA(warning YCF_GCC_DIAG_JOINSTR(-W,x))\n"
+ "# endif\n"
+ "#else\n"
+ "# define YCF_GCC_DIAG_OFF(x)\n"
+ "# define YCF_GCC_DIAG_ON(x)\n"
+ "#endif\n"
+ "#ifdef __GNUC__\n"
+ "# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined(__clang__)\n"
+ "# define YCF_GCC_ATTRIBUTE_UNUSED __attribute__ ((unused))\n"
+ "# else\n"
+ "# define YCF_GCC_ATTRIBUTE_UNUSED\n"
+ "# endif\n"
+ "#else\n"
+ "# define YCF_GCC_ATTRIBUTE_UNUSED\n"
+ "#endif\n"
+ "\n"
+ "typedef void* (*ycf_yield_alloc_type) (size_t,void*);\n"
+ "typedef void (*ycf_yield_free_type) (void*,void*);\n"
+ "\n"
+ "struct ycf_alloc_data {\n"
+ " size_t size;\n"
+ " size_t max_size;\n"
+ " int needs_freeing;\n"
+ " char* data;\n"
+ "};\n"
+ "\n"
+ "#define YCF_ALLOC_NEXT_BLOCK() (\\\n"
+ " ycf_frame_alloc_data.data == NULL \\\n"
+ " ? NULL \\\n"
+ " : ((void*)(&ycf_frame_alloc_data.data[ycf_frame_alloc_data.size]))\\\n"
+ ")\n"
+ "#define YCF_ALLOC_NEXT_MAX_SIZE() (\\\n"
+ " ycf_frame_alloc_data.data == NULL \\\n"
+ " ? 0 \\\n"
+ " : (ycf_frame_alloc_data.max_size - ycf_frame_alloc_data.size)\\\n"
+ ")\n"
+ "\n"
+ "/* Macros for special code sections */\n"
+ "#define ON_SAVE_YIELD_STATE ON_SAVE_YIELD_STATE\n"
+ "#define ON_RESTORE_YIELD_STATE ON_RESTORE_YIELD_STATE\n"
+ "#define ON_DESTROY_STATE ON_DESTROY_STATE\n"
+ "#define ON_RETURN ON_RETURN\n"
+ "#define ON_DESTROY_STATE_OR_RETURN ON_DESTROY_STATE_OR_RETURN\n"
+ "#define YCF_SPECIAL_CODE_START(PARAM) \\\n"
+ " /*special_code_start:PARAM*/ \\\n"
+ " if(0){\n"
+ "#define YCF_SPECIAL_CODE_END() \\\n"
+ " }\\\n"
+ " /*special_code_end*/\n"
+ "\n"
+ "YCF_GCC_ATTRIBUTE_UNUSED\n"
+ "static void* ycf_stack_alloc(size_t size,\n"
+ " struct ycf_alloc_data* data,\n"
+ " ycf_yield_alloc_type allocator,\n"
+ " void* ycf_yield_alloc_free_context,\n"
+ " size_t default_stack_size){\n"
+ " void * ret = NULL;"
+ " if (data->data == NULL) {\n"
+ " if (default_stack_size == 0) {\n"
+ " fprintf(stderr, \"ycf_alloc: not enough stack!!\\n\");\n"
+ " exit(1);\n"
+ " }\n"
+ " data->data = allocator(default_stack_size, ycf_yield_alloc_free_context);\n"
+ " data->needs_freeing = 1;"
+ " data->max_size = default_stack_size;"
+ " data->size = 0;"
+ " }\n"
+ " if (data->size + size > data->max_size) {\n"
+ " fprintf(stderr, \"ycf_alloc: not enough stack!\\n\");\n"
+ " exit(1);\n"
+ " }\n"
+ " ret = &data->data[data->size];\n"
+ " data->size = data->size + size;\n"
+ " return ret;\n"
+ "}\n"
+ "static void ycf_destroy_stack_allocator(struct ycf_alloc_data* data,\n"
+ " ycf_yield_free_type freer,\n"
+ " void* ycf_yield_alloc_free_context){\n"
+ " if(data->needs_freeing){\n"
+ " freer(data->data, ycf_yield_alloc_free_context);\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "#include <limits.h>\n"
+ "#define YCF_MAX_NR_OF_REDS LONG_MAX\n"
+ "#define YCF_NR_OF_REDS_LEFT() ycf_nr_of_reductions\n"
+ "#define YCF_SET_NR_OF_REDS_LEFT(NEW_NR_OF_REDS_LEFT) \\\n"
+ " do{ycf_nr_of_reductions = (NEW_NR_OF_REDS_LEFT);}while(0)\n"
+ "\n"
+ "#define YCF_GET_EXTRA_CONTEXT() ycf_extra_context\n"
+ "\n"
+ "#define YCF_IS_YIELDED(CTX) (CTX != NULL)\n"
+ "\n"
+ "#define YCF_YIELD_CODE_GENERATED 1\n"
+ "\n"
+ "%s"
+ "\n"
+ "/* end of YCF_YIELDING_C_FUN_HELPERS guard */\n"
+ "#endif\n", debug_mode_code);
+ ycf_node_list_prepend(&source_out_tree->u.c_file.content,
+ ycf_node_new_text_node(ycf_yielding_c_fun_helpers_code));
+}
+
+static
+ycf_node* mk_fun_def(ycf_node* fun_node){
+ ycf_node* fun_def = ycf_malloc(sizeof(ycf_node));
+ fun_def->next = NULL;
+ fun_def->type = ycf_node_type_function_declaration;
+ fun_def->u.function_definition = fun_node->u.function.definition;
+ ycf_symbol_list fun_node_def_end = ycf_symbol_list_empty();
+ ycf_symbol_list_append(&fun_node_def_end, ycf_symbol_new_semicolon());
+ fun_def->u.function_definition.end = fun_node_def_end;
+ return fun_def;
+}
+
+
+static
+ycf_node* mk_null_vars_code(ycf_string_item_list fun_call_state_vars){
+ ycf_string_item* current = fun_call_state_vars.head;
+ char* assignments = "";
+ while(current != NULL){
+ assignments = ycf_string_new("%s\n"
+ "%s = NULL;\n",
+ assignments,
+ current->str);
+ current = current->next;
+ }
+ ycf_node* code = ycf_node_get_from_code_scope_text(assignments);
+ return code;
+}
+
+static
+ycf_node* mk_continue_function_node(char* yielding_function_name,
+ char* ycf_trap_state_struct_name,
+ ycf_node* yielding_fun,
+ ycf_node_list uniqified_parameters){
+ char* parameters = "";
+ ycf_node* current = uniqified_parameters.head;
+ while(current != NULL){
+ parameters = ycf_string_new("%s,ycf_my_trap_state->%s", parameters, ycf_symbol_get_text(current->u.definition.identifier));
+ current = current->next;
+ }
+ char* fun_call_str =
+ ycf_string_new("%s_ycf_gen_yielding(ycf_number_of_reduction_param,\n"
+ " ycf_trap_state,\n"
+ " ycf_extra_context,\n"
+ " ycf_my_trap_state->ycf_yield_alloc,\n"
+ " ycf_my_trap_state->ycf_yield_free,\n"
+ " ycf_my_trap_state->ycf_yield_alloc_free_context,\n"
+ " ycf_my_trap_state->ycf_stack_alloc_size_or_max_size,\n"
+ " ycf_my_trap_state->ycf_stack_alloc_data\n"
+ " %s)\n",
+ yielding_function_name,
+ parameters);
+ char* code = ycf_string_new("\n"
+ "%s %s_ycf_gen_continue(long* ycf_number_of_reduction_param,\n"
+ " void** ycf_trap_state,\n"
+ " void* ycf_extra_context){\n"
+ " struct %s* ycf_my_trap_state = *ycf_trap_state;\n"
+ "%s"
+ "}\n",
+ ycf_symbol_list_to_str(&yielding_fun->u.function.definition.definition.type_specifiers),
+ yielding_function_name,
+ ycf_trap_state_struct_name,
+ (ycf_node_is_void_ret_fun(yielding_fun) ?
+ ycf_string_new("%s;\n"
+ "return;\n",
+ fun_call_str):
+ ycf_string_new("return %s;\n",
+ fun_call_str)));
+ ycf_symbol_list symbols = ycf_symbol_list_from_text(code);
+ ycf_node* tree = get_abstract_syntax_tree_root(&symbols);
+ if(tree->u.c_file.content.head->type != ycf_node_type_function_definition){
+ printf("NOT A FUNCTION\n");
+ exit(1);
+ }
+ return tree->u.c_file.content.head;
+}
+
+static
+ycf_node* mk_debug_yielding_fun_call_wrapper(char* yielding_function_name,
+ char* ycf_trap_state_struct_name,
+ ycf_node* yielding_fun){
+ char* parameters_2 = "";
+ {
+ ycf_node* current = yielding_fun->u.function.definition.parameters.head;
+ bool first = true;
+ char* identifier;
+ while(current != NULL){
+ identifier = ycf_symbol_get_text(current->u.definition.identifier);
+ if(strcmp(identifier, "ycf_trap_state") == 0){
+ identifier = ycf_string_new("(void**)(&ycf_my_trap_state)");
+ }
+ parameters_2 = ycf_string_new(first ? "%s%s" :"%s,%s",
+ parameters_2,
+ identifier);
+ current = current->next;
+ first = false;
+ }
+ }
+ char* parameters = "";
+ {
+ ycf_node* current = yielding_fun->u.function.definition.parameters.head;
+ bool first = true;
+ while(current != NULL){
+ parameters = ycf_string_new(first ? "%s%s" :"%s,%s",
+ parameters,
+ ycf_symbol_get_text(current->u.definition.identifier));
+ current = current->next;
+ first = false;
+ }
+ }
+ ycf_string_printable_buffer* header_2 = ycf_string_printable_buffer_new();
+ ycf_node_function_definition def_2 = yielding_fun->u.function.definition;
+ def_2.definition.identifier =
+ ycf_symbol_copy_change_text(def_2.definition.identifier,
+ ycf_string_new("%s_2",
+ ycf_symbol_get_text(def_2.definition.identifier)));
+ print_node_code_function_def(def_2, header_2);
+ ycf_string_printable_buffer* header = ycf_string_printable_buffer_new();
+ print_node_code_function_def(yielding_fun->u.function.definition, header);
+ ycf_string_printable_buffer* parameter_types = ycf_string_printable_buffer_new();
+ print_node_code_function_def_parameters(yielding_fun->u.function.definition, parameter_types);
+ ycf_symbol_list ret_type = ycf_node_get_return_type(yielding_fun);
+ char* wrapper_assignment = NULL;
+ char* wrapper_return = NULL;
+ if(ycf_node_is_void_ret_fun(yielding_fun)){
+ wrapper_assignment = ycf_string_new("");
+ wrapper_return = ycf_string_new("return;");
+ }else{
+ wrapper_assignment = ycf_string_new("%s ycf_to_return = ", ycf_symbol_list_to_str(&ret_type));
+ wrapper_return = ycf_string_new("return ycf_to_return;");
+ }
+ char* code = ycf_string_new("\n"
+ "%s{\n"
+ " volatile int noinline = 1;\n"
+ " volatile void* ycf_my_trap_state = *ycf_trap_state;\n"
+ " %s (*next)(%s = noinline\n"
+ " ? %s_ycf_gen_yielding_3\n"
+ " : (%s(*)(%s)(NULL);\n"
+ " {\n"
+ " %s next(%s);\n"
+ " *ycf_trap_state = (struct %s*)ycf_my_trap_state;\n"
+ " %s\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "\n"
+ "%s{\n"
+ " volatile int noinline = 1;\n"
+ " %s (*next)(%s = noinline\n"
+ " ? %s_ycf_gen_yielding_2\n"
+ " : (%s(*)(%s)(NULL);\n"
+ "\n"
+ " {\n"
+ " %s next(%s);\n"
+ " %s;\n"
+ " }\n"
+ "}\n",
+ header_2->buffer,
+ ycf_symbol_list_to_str(&ret_type),
+ parameter_types->buffer,
+ yielding_function_name,
+ ycf_symbol_list_to_str(&ret_type),
+ parameter_types->buffer,
+ wrapper_assignment,
+ parameters_2,
+ ycf_trap_state_struct_name,
+ wrapper_return,
+ /* Second function*/
+ header->buffer,
+ ycf_symbol_list_to_str(&ret_type),
+ parameter_types->buffer,
+ yielding_function_name,
+ ycf_symbol_list_to_str(&ret_type),
+ parameter_types->buffer,
+ wrapper_assignment,
+ parameters,
+ wrapper_return);
+
+ return ycf_node_new_text_node(code);
+}
+
+
+static
+void break_up_control_expressions(ycf_node_code_scope* s,
+ ycf_string_item_list* yielding_function_names);
+
+
+static ycf_node* break_up_control_expressions_helper(ycf_node* candidate,
+ ycf_node_code_scope* candidates_scope,
+ void* context){
+ ycf_string_item_list* list = (ycf_string_item_list*)context;
+ if(candidate->type == ycf_node_type_if &&
+ ycf_node_list_length(candidate->u.if_n.expression.content.content) == 1 &&
+ candidate->u.if_n.expression.content.content.head->type == ycf_node_type_function_call &&
+ ycf_string_item_list_contains(list,
+ ycf_symbol_get_text(candidate->u.if_n.expression.content.content.head->u.function_call.identifier))){
+ break_up_control_expressions(&candidate->u.if_n.if_statement->u.code_scope, list);
+ ycf_node * wrapper =
+ ycf_node_get_from_code_scope_text(ycf_string_new("int ycf_gen_control_tmp;\n"
+ "ycf_gen_control_tmp = !!%s;\n"
+ "if(ycf_gen_control_tmp)\n"
+ "%s",
+ ycf_node_to_string(candidate->u.if_n.expression.content.content.head),
+ ycf_node_to_string(candidate->u.if_n.if_statement)));
+ return wrapper;
+ } else if(candidate->type == ycf_node_type_if_else &&
+ ycf_node_list_length(candidate->u.if_else.if_part.expression.content.content) == 1 &&
+ candidate->u.if_else.if_part.expression.content.content.head->type == ycf_node_type_function_call &&
+ ycf_string_item_list_contains(list,
+ ycf_symbol_get_text(candidate->u.if_else.if_part.expression.content.content.head->u.function_call.identifier))){
+ break_up_control_expressions(&candidate->u.if_else.if_part.if_statement->u.code_scope, list);
+ ycf_node * wrapper =
+ ycf_node_get_from_code_scope_text(ycf_string_new("int ycf_gen_control_tmp;\n"
+ "ycf_gen_control_tmp = !!%s;\n"
+ "if(ycf_gen_control_tmp)\n"
+ "%s\n"
+ "%s\n"
+ "%s\n",
+ ycf_node_to_string(candidate->u.if_else.if_part.expression.content.content.head),
+ ycf_node_to_string(candidate->u.if_else.if_part.if_statement),
+ ycf_symbol_get_text(candidate->u.if_else.else_word),
+ ycf_node_to_string(candidate->u.if_else.else_statement)));
+ return wrapper;
+ } else if(candidate->type == ycf_node_type_do_while &&
+ ycf_node_list_length(candidate->u.do_while.expression.content.content) == 1 &&
+ candidate->u.do_while.expression.content.content.head->type == ycf_node_type_function_call &&
+ ycf_string_item_list_contains(list,
+ ycf_symbol_get_text(candidate->u.do_while.expression.content.content.head->u.function_call.identifier))){
+ break_up_control_expressions(&candidate->u.do_while.statement->u.code_scope, list);
+ ycf_node * wrapper =
+ ycf_node_get_from_code_scope_text(ycf_string_new("int ycf_gen_control_tmp;\n"
+ "do {\n"
+ " %s\n"
+ " ycf_gen_control_tmp = !!%s;\n"
+ "}while(ycf_gen_control_tmp);\n",
+ ycf_node_to_string(candidate->u.do_while.statement),
+ ycf_node_to_string(candidate->u.do_while.expression.content.content.head)));
+ return wrapper;
+ } else if(candidate->type == ycf_node_type_while &&
+ ycf_node_list_length(candidate->u.while_n.expression.content.content) == 1 &&
+ candidate->u.while_n.expression.content.content.head->type == ycf_node_type_function_call &&
+ ycf_string_item_list_contains(list,
+ ycf_symbol_get_text(candidate->u.while_n.expression.content.content.head->u.function_call.identifier))){
+ break_up_control_expressions(&candidate->u.while_n.statement->u.code_scope, list);
+ ycf_node * wrapper =
+ ycf_node_get_from_code_scope_text(ycf_string_new("int ycf_gen_control_tmp;\n"
+ "ycf_gen_control_tmp = !!%s;\n"
+ "while(ycf_gen_control_tmp){\n"
+ " %s\n"
+ " ycf_gen_control_tmp = !!%s;\n"
+ "}\n",
+ ycf_node_to_string(candidate->u.while_n.expression.content.content.head),
+ ycf_node_to_string(candidate->u.while_n.statement),
+ ycf_node_to_string(candidate->u.while_n.expression.content.content.head)));
+ return wrapper;
+ }
+ return candidate;
+}
+
+static
+void break_up_control_expressions(ycf_node_code_scope* s,
+ ycf_string_item_list* yielding_function_names){
+ ycf_node_insert_scopes_in_complex_statements(s);
+ ycf_node_search_and_replace_statements_in_scope(s,
+ break_up_control_expressions_helper,
+ yielding_function_names);
+}
+
+static
+ycf_node* mk_wrap_in_surpress_warn(char* warning, ycf_node* to_wrap) {
+ ycf_string_printable_buffer* buf = ycf_string_printable_buffer_new();
+ ycf_string_printable_buffer_printf(buf,
+ "\n"
+ "/* clang-format off */\n"
+ "YCF_GCC_DIAG_OFF(%s)\n"
+ "/* clang-format on */\n", warning);
+ ycf_node_print(to_wrap, buf);
+ ycf_string_printable_buffer_printf(buf,
+ "\n"
+ "/* clang-format off */\n"
+ "YCF_GCC_DIAG_ON(%s)\n"
+ "/* clang-format on */\n", warning);
+ return ycf_node_new_text_node(buf->buffer);
+
+}
+
+static
+ycf_node* supress_warnings_wrap_yielding_fun(ycf_node* yielding_fun){
+ ycf_node* ret = yielding_fun;
+ ret = mk_wrap_in_surpress_warn("uninitialized", ret);
+ ret = mk_wrap_in_surpress_warn("maybe-uninitialized", ret);
+ ret = mk_wrap_in_surpress_warn("sometimes-uninitialized", ret);
+ ret = mk_wrap_in_surpress_warn("unknown-warning-option", ret);
+ ret = mk_wrap_in_surpress_warn("pragmas", ret);
+ return ret;
+}
+
+static
+ycf_node* supress_warnings_wrap_destroy_fun(ycf_node* fun){
+ ycf_node* ret = fun;
+ ret = mk_wrap_in_surpress_warn("unused-function", ret);
+ ret = mk_wrap_in_surpress_warn("unused-but-set-variable", ret);
+ ret = mk_wrap_in_surpress_warn("unknown-warning-option", ret);
+ ret = mk_wrap_in_surpress_warn("pragmas", ret);
+ return ret;
+}
+
+ycf_node* insert_yielding_function_with_prefix_suffix(ycf_node* tree_to_insert_to,
+ ycf_node* insert_before,
+ ycf_node* yielding_fun,
+ bool debug_mode,
+ char* yielding_function_name,
+ char* ycf_trap_state_struct_name){
+ ycf_node* prefix = ycf_node_new_text_node("\n"
+ "#define YCF_IN_YIELDING_FUN 1\n"
+ "#undef YCF_STACK_ALLOC\n"
+ "#define YCF_STACK_ALLOC(SIZE) \\\n"
+ " ycf_stack_alloc(SIZE,\\\n"
+ " &ycf_frame_alloc_data,\\\n"
+ " ycf_yield_alloc, ycf_yield_alloc_free_context,\\\n"
+ " ycf_stack_alloc_size_or_max_size)\n");
+ if(insert_before == NULL){
+ ycf_node_list_append(&tree_to_insert_to->u.c_file.content, prefix);
+ }else{
+ ycf_node_list_insert_before(&tree_to_insert_to->u.c_file.content,
+ insert_before,
+ prefix);
+ }
+ if(debug_mode){
+ ycf_node* wrapper_funs =
+ mk_debug_yielding_fun_call_wrapper(yielding_function_name,
+ ycf_trap_state_struct_name,
+ yielding_fun);
+ ycf_node_rename_function(&yielding_fun->u.function,
+ ycf_string_new("%s_ycf_gen_yielding_3",
+ yielding_function_name));
+
+ if(insert_before == NULL){
+ yielding_fun = supress_warnings_wrap_yielding_fun(yielding_fun);
+ ycf_node_list_append(&tree_to_insert_to->u.c_file.content,
+ yielding_fun);
+ ycf_node_list_append(&tree_to_insert_to->u.c_file.content, wrapper_funs);
+ } else {
+ yielding_fun = supress_warnings_wrap_yielding_fun(yielding_fun);
+ ycf_node_list_insert_before(&tree_to_insert_to->u.c_file.content,
+ insert_before,
+ yielding_fun);
+ ycf_node_list_insert_before(&tree_to_insert_to->u.c_file.content,
+ insert_before,
+ wrapper_funs);
+ }
+ }else {
+ if(insert_before == NULL){
+ yielding_fun = supress_warnings_wrap_yielding_fun(yielding_fun);
+ ycf_node_list_append(&tree_to_insert_to->u.c_file.content,
+ yielding_fun);
+ }else{
+ yielding_fun = supress_warnings_wrap_yielding_fun(yielding_fun);
+ ycf_node_list_insert_before(&tree_to_insert_to->u.c_file.content,
+ insert_before,
+ yielding_fun);
+ }
+ }
+ if(insert_before == NULL){
+ ycf_node_list_append(&tree_to_insert_to->u.c_file.content,
+ ycf_node_new_text_node("\n"
+ "#undef YCF_STACK_ALLOC\n"
+ "#undef YCF_IN_YIELDING_FUN\n"));
+ }else{
+ ycf_node_list_insert_after(&tree_to_insert_to->u.c_file.content,
+ yielding_fun,
+ ycf_node_new_text_node("\n"
+ "#undef YCF_STACK_ALLOC\n"
+ "#undef YCF_IN_YIELDING_FUN\n"
+ "#define YCF_STACK_ALLOC(SIZE) malloc(SIZE)\n"));
+ ycf_node_list_insert_after(&tree_to_insert_to->u.c_file.content,
+ insert_before,
+ ycf_node_new_text_node("\n#undef YCF_STACK_ALLOC\n"));
+ }
+ return yielding_fun;
+}
+
+ycf_node* ast_get_ast_with_yieldified_function(ycf_node* source_tree,
+ ycf_node* header_tree,
+ char* yielding_function_name,
+ ycf_string_item_list* all_yielding_function_names,
+ bool auto_yield,
+ bool recusive_auto_yield,
+ bool debug_mode,
+ bool only_yielding_funs,
+ ycf_node** only_yielding_funs_tree,
+ bool static_aux_funs)
+{
+ ycf_yield_location_id_counter = 0;
+ ycf_node* tree_ret = ycf_node_deep_copy(source_tree);
+ if (*only_yielding_funs_tree == NULL){
+ *only_yielding_funs_tree = ycf_node_c_file_new(ycf_node_list_empty());
+ }
+ /* Find function */
+ ycf_node* fun = ycf_node_find_function(tree_ret, yielding_function_name);
+ if(fun == NULL){
+ fprintf(stderr, "Could not find function %s\n", yielding_function_name);
+ exit(1);
+ }
+ ycf_node* fun_change = ycf_node_deep_copy(fun);
+ /* Replace alternative syntax for special code sections */
+ fun_change = replace_alt_syntax_special_code_section_code(fun_change);
+ ycf_node_normalize_function(fun_change);
+ /* Brake up control expressions with simple calls to yielding functions */
+ break_up_control_expressions(&fun_change->u.function.body, all_yielding_function_names);
+ /* Insert trap state var for calls to yielding functions */
+ insert_fun_call_state_var(&fun_change->u.function.body, all_yielding_function_names);
+ /* Normalize the function to make transformation easier (move all declarations to the top etc) */
+ ycf_node_normalize_function(fun_change);
+ /* Insert YCF_CONSUME_REDS(1) code if auto yielding is on */
+ if(auto_yield){
+ insert_consume_reds_calls(&fun_change->u.function.body);
+ }
+ /* Save variable declaraions */
+ ycf_node_list uniqified_parameters =
+ ycf_node_list_shallow_copy(fun_change->u.function.definition.parameters);
+ ycf_node_list scope_defs =
+ ycf_node_list_shallow_copy(ycf_node_get_declarations_in_scope(&fun_change->u.function.body));
+ ycf_node_list defs =
+ ycf_node_list_shallow_copy(ycf_node_get_all_definitions_in_function(&fun_change->u.function));
+ /* Add extra vaiables that are needed for yielding */
+ ycf_node_list extra_ycf_trap_state = mk_trap_extra_state();
+ ycf_node_list_concat(&scope_defs, &extra_ycf_trap_state);
+ fun_change->u.function.body.definition_nodes = scope_defs;
+ /* Generate trap state struct */
+ ycf_node_list trap_state_struct_var_declarations =
+ ycf_node_list_shallow_copy(extra_ycf_trap_state);
+ ycf_node_list_concat(&trap_state_struct_var_declarations, &defs);
+ char* ycf_trap_state_struct_name =
+ ycf_string_new("gen_ycf_trap_state_for_%s",
+ yielding_function_name);
+ trap_state_struct_var_declarations =
+ ycf_node_list_copy_concat(mk_saved_ycf_trap_state_params(),
+ trap_state_struct_var_declarations);
+ ycf_node* ycf_trap_state_struct =
+ mk_typedef_struct_node(trap_state_struct_var_declarations,
+ ycf_trap_state_struct_name);
+ /* Add extra parameters for trapping */
+ {
+ ycf_node_list trap_params = mk_ycf_trap_state_params();
+ ycf_node_list saved_params = mk_saved_ycf_trap_state_params();
+ ycf_node_list_concat(&trap_params, &saved_params);
+ ycf_node_list_concat(&trap_params, &fun_change->u.function.definition.parameters);
+ fun_change->u.function.definition.parameters = trap_params;
+ fun_change->u.function.definition.ignore_param_ending = 1;
+ }
+ /* Collect and replace special code */
+ ycf_node_list on_save_yield_state_code_list =
+ save_and_replace_special_code(&fun_change->u.function.body,
+ ycf_node_type_on_save_yield_state_code);
+ ycf_node_list on_restore_yield_state_code_list =
+ save_and_replace_special_code(&fun_change->u.function.body,
+ ycf_node_type_on_restore_yield_state_code);
+ ycf_node_list on_destroy_state_code_list =
+ save_and_replace_special_code(&fun_change->u.function.body,
+ ycf_node_type_on_destroy_state_code);
+ ycf_node_list on_destroy_state_or_return_code_list =
+ save_and_replace_special_code(&fun_change->u.function.body,
+ ycf_node_type_on_destroy_state_or_return_code);
+ ycf_node_list on_return_code_list =
+ save_and_replace_special_code(&fun_change->u.function.body, ycf_node_type_on_return_code);
+ save_nr_of_reductions_before_return(&fun_change->u.function.body,
+ on_destroy_state_or_return_code_list,
+ on_return_code_list,
+ recusive_auto_yield);
+ /* Insert goto yield code in function */
+ insert_yield_code(fun_change,
+ ycf_trap_state_struct_name,
+ trap_state_struct_var_declarations,
+ &fun_change->u.function.body);
+ insert_yield_no_reds_code(fun_change,
+ ycf_trap_state_struct_name,
+ trap_state_struct_var_declarations,
+ &fun_change->u.function.body);
+ {
+ ycf_string_item_list fun_call_state_vars =
+ insert_yielding_fun_call_code(source_tree,
+ &fun_change->u.function.body,
+ all_yielding_function_names,
+ yielding_function_name,
+ recusive_auto_yield);
+ /* Null all fun_call_state_vars */
+ ycf_node_list_prepend(&fun_change->u.function.body.other_nodes, mk_null_vars_code(fun_call_state_vars));
+ }
+ /* Replace YCF_CONSUME_REDS calls */
+ insert_consume_reds_code(yielding_function_name, &fun_change->u.function.body);
+ /* Insert yield initialization in the beginning of the function */
+ {
+ ycf_node* trap_init = mk_yield_init_code(ycf_trap_state_struct_name,
+ trap_state_struct_var_declarations,
+ on_restore_yield_state_code_list,
+ auto_yield,
+ yielding_function_name);
+ ycf_node_list_prepend(&fun_change->u.function.body.other_nodes, trap_init);
+ }
+ /* Add code that saves the state and yields to the end of the function */
+ ycf_node_list_append(&fun_change->u.function.body.other_nodes,
+ mk_yield_code(fun_change,
+ ycf_trap_state_struct_name,
+ trap_state_struct_var_declarations,
+ on_save_yield_state_code_list,
+ debug_mode));
+ /* Change name of function */
+ ycf_node_rename_function(&fun_change->u.function,
+ ycf_string_new("%s_ycf_gen_yielding",
+ yielding_function_name));
+ /* Remove unecessary scopes */
+ ycf_node_remove_unecessary_scopes(&fun_change->u.function.body);
+ /* Make continue function */
+ ycf_node* continue_function =
+ mk_continue_function_node(yielding_function_name,
+ ycf_trap_state_struct_name,
+ fun,
+ uniqified_parameters);
+ /* Make destroy state function */
+ ycf_node* destroy_state_function =
+ mk_destroy_state_function_node(yielding_function_name,
+ trap_state_struct_var_declarations,
+ ycf_trap_state_struct_name,
+ on_destroy_state_code_list,
+ on_destroy_state_or_return_code_list,
+ static_aux_funs);
+ ycf_node* fun_change_dec = mk_fun_def(fun_change);
+ /****************************************************************
+ *
+ * The following code inserts the changed function and its helper
+ * function into the output AST(s)
+ *
+ ****************************************************************/
+ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* Insert changed function into tree that will be printed */
+ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ ycf_node* fun_ret = ycf_node_find_function(tree_ret, yielding_function_name);
+ ycf_node* fun_change_wrapper =
+ insert_yielding_function_with_prefix_suffix(tree_ret,
+ fun_ret,
+ fun_change,
+ debug_mode,
+ yielding_function_name,
+ ycf_trap_state_struct_name);
+ /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* END: Insert changed function into tree that will be printed */
+ /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* Insert declarations in the top */
+ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ ycf_node* fun_dec_node = ycf_node_find_function_declaration(tree_ret, yielding_function_name);
+ ycf_node_list_prepend(&tree_ret->u.c_file.content, ycf_node_new_text_node("\n"));
+ if(fun_dec_node == NULL){
+ ycf_node_list_prepend(&tree_ret->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(destroy_state_function)));
+ ycf_node_list_prepend(&tree_ret->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(continue_function)));
+ } else {
+ ycf_node_list_insert_before(&tree_ret->u.c_file.content,
+ fun_dec_node,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(destroy_state_function)));
+ ycf_node_list_insert_before(&tree_ret->u.c_file.content,
+ fun_dec_node,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(continue_function)));
+
+ }
+ ycf_node_list_prepend(&header_tree->u.c_file.content, ycf_node_shallow_copy(fun_change_dec));
+ ycf_node_list_prepend(&header_tree->u.c_file.content, ycf_node_new_text_node("\n"));
+ ycf_node_list_prepend(&header_tree->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(destroy_state_function)));
+ ycf_node_list_prepend(&header_tree->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(continue_function)));
+ ycf_node* ycf_trap_state_struct_dec =
+ ycf_node_new_text_node(ycf_string_new("\n\nstruct %s;",
+ ycf_trap_state_struct->u.gen_typedef_struct.name));
+ ycf_node_list_prepend(&tree_ret->u.c_file.content,
+ ycf_trap_state_struct_dec);
+ ycf_node_list_prepend(&header_tree->u.c_file.content,
+ ycf_node_shallow_copy(ycf_trap_state_struct_dec));
+ ycf_node_list_append(&header_tree->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ /* Insert definition of changed function */
+ if(fun_dec_node != NULL){
+ ycf_node_list_insert_before(&tree_ret->u.c_file.content,
+ fun_dec_node,
+ ycf_node_shallow_copy(ycf_node_shallow_copy(fun_change_dec)));
+ }else{
+ ycf_node_list_insert_before(&tree_ret->u.c_file.content,
+ fun_change_wrapper,
+ ycf_node_shallow_copy(ycf_node_shallow_copy(fun_change_dec)));
+ }
+ ycf_node_list_insert_before(&tree_ret->u.c_file.content, fun_change_wrapper, ycf_trap_state_struct);
+ ycf_node_list_insert_after(&tree_ret->u.c_file.content,
+ ycf_trap_state_struct,
+ supress_warnings_wrap_destroy_fun(destroy_state_function));
+ ycf_node_list_insert_after(&tree_ret->u.c_file.content,
+ ycf_trap_state_struct,
+ mk_wrap_in_surpress_warn("unused-function",
+ continue_function));
+ /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* END: Insert declarations in the top */
+ /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ if(only_yielding_funs){
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_shallow_copy(fun_change_dec));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",mk_fun_def(destroy_state_function)));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",
+ mk_fun_def(continue_function)));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_shallow_copy(ycf_trap_state_struct_dec));
+ ycf_node_list_prepend(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+
+ ycf_node_list_append(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_shallow_copy(ycf_trap_state_struct));
+ ycf_node_list_append(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ ycf_node_list_append(&(*only_yielding_funs_tree)->u.c_file.content,
+ supress_warnings_wrap_destroy_fun(destroy_state_function));
+ ycf_node_list_append(&(*only_yielding_funs_tree)->u.c_file.content,
+ ycf_node_new_text_node("\n"));
+ ycf_node_list_append(&(*only_yielding_funs_tree)->u.c_file.content,
+ mk_wrap_in_surpress_warn("unused-function",continue_function));
+ insert_yielding_function_with_prefix_suffix((*only_yielding_funs_tree),
+ NULL,
+ fun_change,
+ debug_mode,
+ yielding_function_name,
+ ycf_trap_state_struct_name);
+ }
+ return tree_ret;
+}
diff --git a/erts/lib_src/yielding_c_fun/ycf_yield_fun.h b/erts/lib_src/yielding_c_fun/ycf_yield_fun.h
new file mode 100644
index 0000000000..410256e71c
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/ycf_yield_fun.h
@@ -0,0 +1,116 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Kjell Winblad
+ */
+
+
+#ifndef YCF_AST_H
+#define YCF_AST_H
+
+#include "ycf_utils.h"
+#include "ycf_symbol.h"
+#include "ycf_string.h"
+#include "ycf_node.h"
+
+
+typedef struct {
+ bool success;
+ ycf_symbol* next_symbol;
+ ycf_node* result;
+} ycf_parse_result;
+
+
+/* Functions for strings */
+
+void string_item_list_print(ycf_string_item_list n);
+
+
+/* Functions for symbol lists */
+
+int ycf_symbol_list_get_item_position(ycf_symbol_list* list, ycf_symbol* node);
+
+ycf_symbol* ycf_symbol_shallow_copy(ycf_symbol* n);
+ycf_symbol* ycf_symbol_list_get_item_at_position(ycf_symbol_list* list, int pos);
+
+void ycf_symbol_list_append(ycf_symbol_list* list, ycf_symbol* node);
+void ycf_symbol_list_prepend(ycf_symbol_list* list, ycf_symbol* node);
+void ycf_symbol_list_insert_before(ycf_symbol_list* list, ycf_symbol* before_this, ycf_symbol* to_insert);
+void ycf_symbol_list_insert_after(ycf_symbol_list* list, ycf_symbol* after_this, ycf_symbol* to_insert);
+void ycf_symbol_list_remove(ycf_symbol_list* list, ycf_symbol* to_remove);
+void ycf_symbol_list_replace(ycf_symbol_list* list, ycf_symbol* to_replace, ycf_symbol* replace_with);
+void ycf_symbol_list_concat(ycf_symbol_list* list1, ycf_symbol_list* list2);
+
+ycf_symbol_list ycf_symbol_list_empty();
+ycf_symbol_list ycf_symbol_list_shallow_copy(ycf_symbol_list n);
+ycf_symbol_list ycf_symbol_list_copy_append(ycf_symbol_list list, ycf_symbol* node);
+ycf_symbol_list ycf_symbol_list_copy_prepend(ycf_symbol_list list, ycf_symbol* node);
+ycf_symbol_list ycf_symbol_list_copy_insert_before(ycf_symbol_list list, ycf_symbol* before_this, ycf_symbol* to_insert);
+ycf_symbol_list ycf_symbol_list_copy_insert_after(ycf_symbol_list list, ycf_symbol* after_this, ycf_symbol* to_insert);
+ycf_symbol_list ycf_symbol_list_copy_remove(ycf_symbol_list list, ycf_symbol* to_remove);
+ycf_symbol_list ycf_symbol_list_copy_replace(ycf_symbol_list list, ycf_symbol* to_replace, ycf_symbol* replace_with);
+ycf_symbol_list ycf_symbol_list_copy_concat(ycf_symbol_list list1, ycf_symbol_list list2);
+
+
+
+
+/* Functions for parsing text to AST */
+
+ycf_node* ycf_node_scope_new(ycf_symbol* start,
+ ycf_node_list declaration_nodes,
+ ycf_node_list other_nodes,
+ ycf_symbol* end);
+ycf_parse_result parse_expression(ycf_symbol* symbols);
+
+
+void print_abstract_syntax_tree(ycf_node* node);
+void print_node_code_paran_expression(ycf_node_parentheses_expression e, ycf_string_printable_buffer* b);
+void print_node_code_expression(ycf_node_expression e, ycf_string_printable_buffer* b);
+
+void ast_add_yield_code_generated_define(ycf_node* source_out_tree/*Will be changed*/, bool debug_mode);
+void print_symbol_list(ycf_symbol_list* l, ycf_string_printable_buffer* b);
+
+
+/* Abstract syntax tree functions */
+
+
+
+ycf_node* ycf_node_find_function(ycf_node* c_file_node, char* fun_name);
+ycf_node_list ycf_node_get_all_definitions_in_function(ycf_node_function* f);
+
+
+ycf_node* ast_get_ast_with_yieldified_function(ycf_node* source_tree,
+ ycf_node* header_tree, /*Will be changed*/
+ char* yielding_function_name,
+ ycf_string_item_list* all_yielding_function_names,
+ bool auto_yield,
+ bool recusive_auto_yield,
+ bool debug_mode,
+ bool only_yielding_funs,
+ ycf_node** only_yielding_funs_tree,
+ bool static_aux_funs);
+
+void print_abstract_syntax_tree(ycf_node* node);
+void print_node_code_expression(ycf_node_expression e, ycf_string_printable_buffer* b);
+void print_node_list_code(ycf_node* n, ycf_string_printable_buffer* b);
+void ast_add_yield_code_generated_define(ycf_node* source_out_tree, bool debug_mode);
+
+#endif